## Introduction

BBC BASIC makes use of a floating-point arithmetic package, or FPP, to perform calculations and conversions between string and number forms. It uses all the Z80's general purpose registers, including *IX*, *IY* and the "alternate" (shadow) 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.

The FPP requires no private or shared workspace, it uses registers and the stack for all working and temporary storage. Stack requirements 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 the Format of Program and Variables in Memory appendix 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 the Format of Program and Variables in Memory appendix 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, &4087:

LD A,opcode CALL fpp

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) and *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:

- Bad operation code
- Division by zero
- Too big
- -ve root
- Log range
- Accuracy lost
- Exp range

## 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.

## Details of FPP operations

Opcode | Operation | Description | Parameters | Results |
---|---|---|---|---|

0 | AND | Integer bitwise logical AND | HLH'L'C & DED'E'B | HLH'L'C (C = 0) |

1 | DIV | Integer quotient after division | HLH'L'C (left) DED'E'B (right) | HLH'L'C (C = 0) |

2 | EOR | Integer bitwise logical exclusive-OR | HLH'L'C & DED'E'B | HLH'L'C (C = 0) |

3 | MOD | Integer remainder after division | HLH'L'C (left) DED'E'B (right) | HLH'L'C (C = 0) |

4 | OR | Integer bitwise logical OR | HLH'L'C & DED'E'B | HLH'L'C (C = 0) |

5 | <= | Test for less-than or equal-to | HLH'L'C (left) DED'E'B (right) | HLH'L'C (C = 0, HLH'L' = 0 FALSE or -1 TRUE) |

6 | <> | Test for not equal to | HLH'L'C & DED'E'B | HLH'L'C (C = 0, HLH'L' = 0 FALSE or -1 TRUE) |

7 | >= | Test for greater-than or equal-to | HLH'L'C (left) DED'E'B (right) | HLH'L'C (C = 0, HLH'L' = 0 FALSE or -1 TRUE) |

8 | < | Test for less than | HLH'L'C (left) DED'E'B (right) | HLH'L'C (C = 0, HLH'L' = 0 FALSE or -1 TRUE) |

9 | = | Test for equality | HLH'L'C & DED'E'B | HLH'L'C (C = 0, HLH'L' = 0 FALSE or -1 TRUE) |

10 | * | Integer or floating-point multiplication | HLH'L'C & DED'E'B | HLH'L'C |

11 | + | Integer or floating-point addition | HLH'L'C & DED'E'B | HLH'L'C |

12 | > | Test for greater than | HLH'L'C (left) DED'E'B (right) | HLH'L'C (C = 0, HLH'L' = 0 FALSE or -1 TRUE) |

13 | - | Integer or floating-point subtraction | HLH'L'C (left) DED'E'B (right) | HLH'L'C |

14 | ^ | Integer or floating-point involution (raise to power) | HLH'L'C (left) DED'E'B (right) | HLH'L'C |

15 | / | Floating-point division | HLH'L'C (left) DED'E'B (right) | HLH'L'C |

16 | ABS | Absolute value | HLH'L'C | HLH'L'C |

17 | ACS | Arc cosine (inverse cosine) | HLH'L'C | HLH'L'C (radians) |

18 | ASN | Arc sine (inverse sine) | HLH'L'C | HLH'L'C (radians) |

19 | ATN | Arc tangent (inverse tangent) | HLH'L'C | HLH'L'C (radians) |

20 | COS | Cosine | HLH'L'C (radians) | HLH'L'C |

21 | DEG | Convert radians to degrees | HLH'L'C (radians) | HLH'L'C (degrees) |

22 | EXP | Exponential (raise e to the power of the argument) | HLH'L'C | HLH'L'C |

23 | INT | Integer part (floor function) | HLH'L'C | HLH'L'C (C = 0) |

24 | LN | Natural (Napierian) logarithm | HLH'L'C | HLH'L'C |

25 | LOG | Base-10 (Common) logarithm | HLH'L'C | HLH'L'C |

26 | NOT | Bitwise logical NOT (one's complement) | HLH'L'C | HLH'L'C (C = 0) |

27 | RAD | Convert degrees to radians | HLH'L'C (degrees) | HLH'L'C (radians) |

28 | SGN | Sign (signum) | HLH'L'C | HLH'L'C (=-1 if negative, =0 if zero, =+1 if positive; C = 0) |

29 | SIN | Sine | HLH'L'C (radians) | HLH'L'C |

30 | SQR | Square root | HLH'L'C | HLH'L'C |

31 | TAN | Tangent | HLH'L'C (radians) | HLH'L'C |

32 | ZERO | Return the floating-point & integer constant zero | HL=&0000, H'L'=&0000, C=0 | |

33 | FONE | Return the floating-point constant one | HL=&0000, H'L'=&0000, C=&80 | |

34 | TRUE | Return the integer constant minus one | HL=&FFFF, H'L'=&FFFF, C=0 | |

35 | PI | Return the floating-point constant PI | HLH'L'C (= 3.141592654) | |

36 | VAL | Return the numeric value of a string | IX addresses string in memory, terminated by a NUL | HLH'L'C. If the string does not represent a number, 0 is returned. IX addresses the terminating character (not necessarily the NUL). |

37 | STR$ | Return the string representation of a number | - HLH'L'C = number to be converted
- DE = destination address in memory for string
- IX addresses format variable (@%), only (IX+1) & (IX+2) used
| String stored in memory, DE addresses byte following last character |

38 | FIX | Truncate a number to an integer | HLH'L'C (if C=0 the number is returned unchanged) | HLH'L'C (C = 0). The "too big" error may result. |

39 | FLOAT | Convert an integer to floating-point format | HLH'L'C (if C<>0 the number is returned unchanged) | HLH'L'C |

40 | TEST | Test a number for zero and sign | HLH'L'C | If zero, A=0; if positive A=&40; if negative A=&C0 |

41 | COMPARE | Compare two numeric values | HLH'L'C (left) DED'E'B (right) | If equal, A=0; If left>right A=&40; If left<right A=&C0 |