The routines which do floating point arithmetic are a part of the operating system ROM. The Atari computer uses the 6502's decimal math mode. This mode uses numbers represented in packed Binary Coded Decimal (BCD). This means that each byte of a floating point number holds two decimal digits. The actual method of representing a full number is complicated and probably not very important to a programmer. However, for those with the knowledge to use it, the format is given below.
Floating point number representation byte 0 xx excess 64 exponent + sign xx \ xx \ xx > 10 BCD digits xx / byte 7 xx /
The decimal point is shifted to left of the MSD and the exponent is adjusted accordingly. Therefore, the decimal point doesn't need to be represented.
For programming purposes, floating point numbers can be in ASCII code. It takes up to 14 bytes to store a floating point number in this manner. The floating point package has a routine to convert numbers between ASCII and floating point.
The floating point package has several routines to convert between ASCII and FP and to do the arithmetic functions. These are the important data base variables.
Floating point data base variables FR0 $00D4,6 (212): 6 byte buffer for floating point number FR1 $00E0,6 (224): 6 byte buffer for floating point number CIX $00F2 (242): index for INBUFF address INBUFF $00F3,2 (243): 2 byte pointer to ASCII floating point number FLPTR $00FC,2 (252): 2 byte pointer to user buffer for floating point number LBUFF $0580,? (1408): result buffer for FASC routine
To do a floating point function, first set the proper pointers and JSR to the operation entry point. Below is a list of the entry points and parameters.
ASCII to floating point
Converts ASCII representation pointed to by INBUFF to FP in FR0.
AFP = $D800
INBUFF = address of ASCII number
CIX = buffer offset if any
JSR AFP
FLOATING POINT TO ASCII
Converts floating Point number in FR0 to ASCII. The result will be in LBUFF. INBUFF will point to the ASCII number which will have the bit 7 of the last byte set to 1.
FASC = $D8E6
JSR FASC
INTEGER TO FLOATING POINT CONVERSION.
Converts a 2 byte unsigned integer (0 to 65535) in FR0 to floating point in FR0.
IFP = $D9AA
JSR IFP
FLOATING POINT TO INTEGER CONVERSION.
Converts floating point number in FR0 to 2 byte integer in FR0.
FPI = $D9D2
JSR FPI BCS overflow
ADDITION
Adds floating point numbers in FR0 and FR1 with result in FR0.
FADD = $DA66
JSR FADD BCS out of range
SUBTRACTION
subtracts FR1 from FR0 with the result in FR0.
FSUB = $DA60
JSR FSUB BCS out of range
MULTIPLICATION
Multiplies FR0 by FR1 with the result in FR0.
FMUL = $DADB
JSR FMUL BCS out of range
DIVISION
Divides FR0 by FR1 with result in FR0.
FDIV = $DB28
JSR FDIV BCS out of range or divisor is 0
LOGARITHMS
Puts logarithm of FR0 in FR0
LOG = $DECD LOG10 = $DED1
JSR LOG ;for natural log.
or
JSR LOG10 ;for base 10 log. BCS negative number or overflow
EXPONENTIATION
Put exponentiation of FR0 in FR0
EXP = $DDC0
EXP10 = $DDCC
JSR EXP ;for e ** Z
or
JSR EXP10 ;for 10 ** Z
POLYNOMIAL EVALUATION
Puts the result of an n degree polynomial evaluation of FR0 in FR0.
PLYEVL = $DD40
LDX LSB of pointer to list of floating point coefficients, ordered high to low. LDY MSB of above LDA number of coefficients in list
JSR PLYEVL BCS overflow
CLEAR FR0
Sets FR0 to all zeroes
ZFR0 = $DA44
JSR ZFR0
CLEAR ZERO PAGE FLOATING POINT NUMBER
Clears user floating point number in page zero.
ZF1 = $DA46
LDX address of zero page FP buffer
JSR ZF1
LOAD FR0 WITH FLOATING POINT NUMBER
Loads FR0 with user FP number in buffer pointed to by 6502 X and Y registers or by FLPTR. After either operation below, FLPTR will point to the user FP buffer.
FLD0R = $DD89
LDX lsb of pointer LDY msb
JSR FLD0R
or
FLD0P = $DD8D
FLPTR = address of FP number
JSR FLD0P
LOAD FR1 WITH FLOATING POINT NUMBER
Loads FR1 with user FP number in buffer pointed to by 6502 X and Y registers or by FLPTR. After either operation below, FLPTR will point to the user FP buffer.
FLD1R = $DD98
LDX lsb of pointer LDY msb
JSR FLD1R
or
FLD1P = $DD9C
FLPTR = address of FP number
JSR FLD1P
STORE FR0 IN USER BUFFER
stores the contents of FR0 in user FP buffer pointed to by 6502 X and Y registers or by FLPTR. After either operation below, FLPTR will point to the user FP buffer.
FST0R = $DDA7
LDX lsb of pointer LDY msb
JSR FST0R
or
FST0P = $DDAB
FLPTR = address of FP number
JSR FST0P
MOVE FR0 TO FR1
Moves the contents of FR0 to FR1
FMOVE = $DDB6
JSR FMOVE
The usual use sequence of the floating point package might be to:
load FR0 and FR1 with FP numbes from user specified buffers
do the math
then store FR0 in a user buffer.
An alternative might be to:
convert an ASCII representation to FP (the result is automatically in FR0).
move FR0 to FR1.
Convert the second ASCII number.
Do the math.
Convert FR0 back to ASCII.
Store the number back into a user buffer.
The floating point package uses the following blocks of RAM.
RAM used by floating point package $00D4 - $00FF $057E - $05FF
If the floating point package is not used the above ram is free.
Useful data base variables and OS equates FR0 $00D4,6 (212): system FP buffer FR1 $00E0,6 (224): system FP buffer CIX $00F2 (242): INBUFF index INBUFF $00F3,2 (243): pointer to ASCII FP buffer FLPTR $00FC,2 (252): pointer to user FP buffer LBUFF $0580 (1408): result buffer for FP to ASCII AFP $D800 (55296): ASCII to FP FASC $D8E6 (55526): FP to ASCII IFP $D9AA (55722): integer to FP FPI $D9D2 (55762): FP to integer ZFR0 $DA44 (55876): clear FR0 ZF1 $DA46 (55878): clear zero page FP buffer FSUB $DA60 (55904): FR0 - FR1 FADD $DA66 (55910): FR0 + FR1 FMUL $DADB (56027): FR0 * FR1 FDIV $DB28 (56104): FR0 / FR1 FLD0R $DD89 (56713): load FR0 by X,Y pointer FLD0P $DD8D (56717): load FR0 by FLPTR pointer FLD1R $DD98 (56728): load FR1 by X,Y pointer FLD1P $DD9C (56732): load FR1 by FLPTR pointer FST0R $DDA7 (56743): store FR0 at buffer by X,Y pointer FST1P $DDAB (56747): store FR0 at buffer by FLPTR pointer FMOVE $DDB6 (56758): move FR0 to FR1 EXP $DDC0 (56768): e exponentiation EXP10 $DDCC (56780): base 10 exponentiation PLYEVL $DD40 (56640): polynomial evaluation LOG $DECD (57037): natural log of FR0 LOG10 $DED1 (57041): base 10 log of FR0