Was it BBC BASIC (Z80) v2 or v3? As noted earlier in the thread, v3 runs a little slower than v2. This is largely because of the modifications I had to make for the Cambridge Computer Z88, principally to separate out the arithmetic and floating-point package (FPP) into a separate self-contained module so that it could be called from other applications, notably Pipedream. It can also be called concurrently from multiple processes.

As a result the v3 interpreter calls the FPP via a common entry-point and a function number, whereas v2 called the appropriate subroutines directly; this unavoidably introduces a run-time overhead every time any numeric calculation is performed. So you can blame Clive Sinclair for BBC BASIC (Z80) slowing down slightly, but I felt it was quite a coup for my FPP to be shared like that.

Code: Select all

```
Specification of
Z80 Floating Point Arithmetic Package
for Protechnic Computers Limited
This document specifies the characteristics of the Z80 Floating Point
Package to be supplied to Protechnic Computers Ltd. It forms part of the
agreement between Protechnic Computers Limited and M-Tec Computer Services
(UK) for the supply of this product.
General characteristics:
1. The FPP is written in Z80 assembly language. It uses all the Z80's
general purpose registers, including IX, IY and the "alternate
registers", but does not use the R register or the I register nor does
it disable or enable interrupts or change the interrupt mode. It is
fully interruptible.
2. The FPP requires no private or shared workspace, it uses registers and
the stack for all working and temporary storage. It is fully re-entrant
and may be called freely from concurrent processes, even if pre-empted
by a non-maskable interrupt.
3. The code size of the FPP will not exceed three kilobytes (3072 bytes).
No self-modifying code is used and it is fully ROMmable. Stack
requirements have not yet been accurately determined but should not
exceed fifty bytes.
Operations provided:
The FPP provides sixteen operations which take two numeric parameters and
produce a numeric result (AND, DIV, EOR, MOD, OR, <=, <>, >=, <, =, >, +, -,
*, / and ^), sixteen numeric functions (ABS, ACS, ASN, ATN, COS, DEG, EXP,
INT, LN, LOG, NOT, RAD, SGN, SIN, SQR, TAN), four numeric constants (ZERO,
FONE, TRUE, PI), two numeric/string conversion routines (VAL, STR$), two
format conversion routines (FIX, FLOAT) and two miscellaneous routines
(TEST, COMPARE).
All numeric operations will accept either integer or floating-point
parameters, converting where necessary. Returned values may be in integer
or floating-point format, as appropriate.
Numeric range and precision:
Integers are stored in 4 bytes, and may represent values from -2147483648 to
+2147483647. Floating-point numbers are stored in 5 bytes (4 byte mantissa,
1 byte exponent) and may represent values from approximately +/- 5.9E-39 to
+/- 3.4E38, with a resolution of about nine significant figures.
Considerable care has been taken in coding the FPP to preserve the greatest
degree of accuracy consistent with the use of a 32-bit mantissa. However,
complex operations such as the transcendental functions make use of several
intermediate results, each of which is stored only with the normal
precision. It is therefore possible for errors to accumulate and for the
final result to be less accurate than would be desirable. This problem is
aggravated in certain special cases, such as the logarithm of numbers close
to 1. No guarantee can be given that the accuracy will be sufficient for any
specific application. As always, in financial applications you are strongly
advised to use only integer arithmetic.
Numeric Representation
Details of the formats of integers and floating-point numbers may be found
in Appendix E of the BBCBASIC (Z80) manual (section 28 onwards) except that,
in the case of the FPP, numbers are held in the processor's registers rather
than in memory. Two floating-point numbers may be held in the registers at
any one time, as follows:
Number 1 Number 2
Mantissa MS byte: H D
. L E
. H' D'
Mantissa LS byte: L' E'
Exponent byte: C B
As described in Appendix E, section 34, integer values are denoted by the
"exponent" (C or B register) being zero.
Interface details:
All FPP operations are accessed via a common entry point, the operation
required being specified by an 8-bit "operation code" passed in the A
register. The entry point is the base address of the FPP code:
LD A,opcode
CALL fpp
The intention is that two Restart entry points will be provided by the
machine's Operating System for accessing the FPP; these will take care of
overheads such as ensuring that the FPP code is suitably "paged in". One
Restart will take the "operation code" as an in-line parameter, thus
providing a convenient 2-byte mechanism for accessing the FPP from
applications programs:
RST fpprst1
DEFB opcode
The other Restart will take the operation code in A, for those circumstances
when the required operation has been computed rather than being known as a
constant:
LD A,opcode
RST fpprst2
This latter, 3-byte, method is particularly applicable to the BBC BASIC
interpreter which often derives the op-code from a keyword token. It should
also be slightly faster than the first method.
The argument of a numeric function is passed in registers HLH'L'C and the
result is returned in registers HLH'L'C. Operators (addition, multiplication
etc.) each take two operands and return a single result. The operands are
passed in HLH'L'C (left) & DED'E'B (right), and the result is returned in
HLH'L'C. The result of TEST and COMPARE is returned in the A register.
For information on the register usage of the numeric/string conversion
functions see the detailed descriptions.
Exception handling:
If an operation completes without error it returns with the zero flag set
and the carry flag reset. If an exception occurs during an operation it
returns with the zero flag reset, the carry flag set and an error code in
the A register. In this case the returned value in the other registers is
meaningless.
The possible error codes (decimal) are as follows:
1: "Bad operation code"
18: "Division by zero"
20: "Too big"
21: "-ve root"
22: "Log range"
23: "Accuracy lost"
24: "Exp range"
Note that these error codes are defined as manifest constants in the FPP
source code, but that it will be inconvenient to the BBC BASIC interpreter
if they are changed (they correspond to standard BBC BASIC error numbers).
Registers affected:
On return from the FPP, any or all of the following registers may have been
altered:
A,B,C,D,E,H,L,F,A',B',C',D',E',H',L',F',IX
The IY, SP and I registers are returned unchanged.
Operation codes:
The following (decimal) operation codes cause the specified operations to be
performed:
0: AND 16: ABS 32: ZERO
1: DIV 17: ACS 33: FONE
2: EOR 18: ASN 34: TRUE
3: MOD 19: ATN 35: PI
4: OR 20: COS 36: VAL
5: <= 21: DEG 37: STR$
6: <> 22: EXP 38: FIX
7: >= 23: INT 39: FLOAT
8: < 24: LN 40: TEST
9: = 25: LOG 41: COMPARE
10: * 26: NOT
11: + 27: RAD
12: > 28: SGN
13: - 29: SIN
14: ^ 30: SQR
15: / 31: TAN
Details of FPP operations:
Opcode 0: AND - Integer bitwise logical AND
Parameters: HLH'L'C & DED'E'B
Results: HLH'L'C (C = 0)
Opcode 1: DIV - Integer quotient after division
Parameters: HLH'L'C (left) DED'E'B (right)
Results: HLH'L'C (C = 0)
Opcode 2: EOR - Integer bitwise logical exclusive-OR
Parameters: HLH'L'C & DED'E'B
Results: HLH'L'C (C = 0)
Opcode 3: MOD - Integer remainder after division
Parameters: HLH'L'C (left) DED'E'B (right)
Results: HLH'L'C (C = 0)
Opcode 4: OR - Integer bitwise logical OR
Parameters: HLH'L'C & DED'E'B
Results: HLH'L'C (C = 0)
Opcode 5: <= - Test for less-than or equal-to
Parameters: HLH'L'C (left) DED'E'B (right)
Results: HLH'L'C (C = 0, HLH'L' = 0 [FALSE] or -1 [TRUE])
Opcode 6: <> - Test for not equal to
Parameters: HLH'L'C & DED'E'B
Results: HLH'L'C (C = 0, HLH'L' = 0 [FALSE] or -1 [TRUE])
Opcode 7: >= - Test for greater-than or equal-to
Parameters: HLH'L'C (left) DED'E'B (right)
Results: HLH'L'C (C = 0, HLH'L' = 0 [FALSE] or -1 [TRUE])
Opcode 8: < - Test for less than
Parameters: HLH'L'C (left) DED'E'B (right)
Results: HLH'L'C (C = 0, HLH'L' = 0 [FALSE] or -1 [TRUE])
Opcode 9: = - Test for equality
Parameters: HLH'L'C & DED'E'B
Results: HLH'L'C (C = 0, HLH'L' = 0 [FALSE] or -1 [TRUE])
Opcode 10: * - Integer or floating-point multiplication
Parameters: HLH'L'C & DED'E'B
Results: HLH'L'C
Opcode 11: + - Integer or floating-point addition
Parameters: HLH'L'C & DED'E'B
Results: HLH'L'C
Opcode 12: > - Test for greater than
Parameters: HLH'L'C (left) DED'E'B (right)
Results: HLH'L'C (C = 0, HLH'L' = 0 [FALSE] or -1 [TRUE])
Opcode 13: - - Integer or floating-point subtraction
Parameters: HLH'L'C (left) DED'E'B (right)
Results: HLH'L'C
Opcode 14: ^ - Integer or floating-point involution (raise to power)
Parameters: HLH'L'C (left) DED'E'B (right)
Results: HLH'L'C
Opcode 15: / - Floating-point division
Parameters: HLH'L'C (left) DED'E'B (right)
Results: HLH'L'C
Opcode 16: ABS - Absolute value
Parameters: HLH'L'C
Results: HLH'L'C
Opcode 17: ACS - Arc cosine (inverse cosine)
Parameters: HLH'L'C
Results: HLH'L'C (radians)
Opcode 18: ASN - Arc sine (inverse sine)
Parameters: HLH'L'C
Results: HLH'L'C (radians)
Opcode 19: ATN - Arc tangent (inverse tangent)
Parameters: HLH'L'C
Results: HLH'L'C (radians)
Opcode 20: COS - Cosine
Parameters: HLH'L'C (radians)
Results: HLH'L'C
Opcode 21: DEG - Convert radians to degrees
Parameters: HLH'L'C (radians)
Results: HLH'L'C (degrees)
Opcode 22: EXP - Exponential (raise e to the power of the argument)
Parameters: HLH'L'C
Results: HLH'L'C
Opcode 23: INT - Integer part (floor function)
Parameters: HLH'L'C
Results: HLH'L'C (C = 0)
Opcode 24: LN - Natural (Napierian) logarithm
Parameters: HLH'L'C
Results: HLH'L'C
Opcode 25: LOG - Base-10 (Common) logarithm
Parameters: HLH'L'C
Results: HLH'L'C
Opcode 26: NOT - Bitwise logical NOT (one's complement)
Parameters: HLH'L'C
Results: HLH'L'C (C = 0)
Opcode 27: RAD - Convert degrees to radians
Parameters: HLH'L'C (degrees)
Results: HLH'L'C (radians)
Opcode 28: SGN - Sign (signum)
Parameters: HLH'L'C
Results: HLH'L'C (=-1 if negative, =0 if zero, =+1 if positive; C = 0)
Opcode 29: SIN - Sine
Parameters: HLH'L'C (radians)
Results: HLH'L'C
Opcode 30: SQR - Square root
Parameters: HLH'L'C
Results: HLH'L'C
Opcode 31: TAN - Tangent
Parameters: HLH'L'C (radians)
Results: HLH'L'C
Opcode 32: ZERO - Return the floating-point & integer constant zero
Parameters: None
Results: HL=&0000, H'L'=&0000, C=0
Opcode 33: FONE - Return the floating-point constant one
Parameters: None
Results: HL=&0000, H'L'=&0000, C=&80
Opcode 34: TRUE - Return the integer constant minus one
Parameters: None
Results: HL=&FFFF, H'L'=&FFFF, C=0
Opcode 35: PI - Return the floating-point constant PI
Parameters: None
Results: HLH'L'C (= 3.141592654)
Opcode 36: VAL - Return the numeric value of a string
Parameters: IX addresses string in memory, terminated by a NUL
Results: HLH'L'C. If the string does not represent a number, 0 is returned.
IX addresses the terminating character (not necessarily the NUL).
Opcode 37: STR$ - Return the string representation of a number
Parameters: HLH'L'C = number to be converted
DE = destination address in memory for string
IX addresses format variable (@%), only (IX+1) & (IX+2) used
Results: String stored in memory, DE addresses byte following last character
Opcode 38: FIX - Truncate a number to an integer
Parameters: HLH'L'C (if C=0 the number is returned unchanged)
Results: HLH'L'C (C = 0). The "too big" error may result.
Opcode 39: FLOAT - Convert an integer to floating-point format
Parameters: HLH'L'C (if C<>0 the number is returned unchanged)
Results: HLH'L'C
Opcode 40: TEST - Test a number for zero and sign
Parameters: HLH'L'C
Results: If zero, A=0; if positive A=&40; if negative A=&C0
Opcode 41: COMPARE - Compare two numeric values
Parameters: HLH'L'C (left) DED'E'B (right)
Results: If equal, A=0; If left>right A=&40; If left<right A=&C0
```