"Falconer Floating Point Arithmetic"
by Charles Falconer,
formerly Chief Instrumentation Engineer, Yale University
http://www.qwikpages.com/backstreets/cbfalconer
in DDJ, March 1979, p.4 and April 1979, p.16
This software package provides full floating point arithmetic
capability for 8080, 8085, and Z80-based machines, with very
little speed penalty over use of integer arithmetic. The system
can handle all 16-bit integer values (treated either as positive
integers in the range 0 to 65535, or as signed integers in the
range -32768 to 32767) without any loss of information, yet the
extended range (approximately 10^-38 to 10^+38) convenience of
floating point is directly available, together with various
mathematical functions (i.e., logarithms, exponentials, etc). I
hope that this publication will discourage use of integer
arithmetic in various interpreters, compilers, etc.
The operand size is such as to allow virtually all inner loops to
be performed entirely in registers, with attendant speed benefits.
At a 518 nanoseconds clock, most arithmetic operations are
performed in one millisecond or less, division in about 1.5
milliseconds. A 4-MHz Z80 system can halve this. This is not far
removed from integer execution times.
I strongly recommend that any user of this package do so without
any alteration (except deletion of routines not needed in the
application). This system has been in routine operation since
April 1976, and is incorporated in other systems. The least
exercised routines are in FLTINPUT and FUNCTION.
While the calling convention to IVAL, for example, may appear
unusual, it has been specifically designed to allow re-entrant use
with various data sources. A calling routine of the form:
GETNUM: PUSH B
LXI B,(address of char input routine)
CALL IVAL ; (or IVALC)
POP B
RET
will customize this as required and will avoid conflict with any
other software.
The system does not have the awkward range limitation of the EA
chip (approximately 10^-18 to 10^+18) and some other systems,
which I have found to bite the user all too often. Due to the
careful treatment of rounding and over/underflow, the system will
usually give the expected results (inversion of large matrices is
the only exception noted so far, yet systems of 5 to 10
simultaneous equations, on our typical input data, can be handled
adequately), and the error and overflow reporting will provide
adequate warnings of runtime misuse. Error analysis is
mathematically tractable.
The AERC (arithmetic error connector) allows trappings of illegal
operands (division by zero, logarithm of negative number, etc). If
desired, this can be specified a:
AERC: STC
RET
which will cause all such occurrences to be treated as overflows.
In general, any error is signaled by Carry set on routine exit.
The individual routine functions are stated in the commentary, and
registers disturbed are listed.
Notice that the unspecified I/O routines output register C, and
return with A set to C on entry. Input routines return characters
in A.
Also, notice that all routines (except those specifically using
I/O devices) are re-entrant, and use only stack-assigned temporary
storage. The code is thus inherently suitable for the time sharing
or interrupt driven applications. Users who have been using
integer arithmetic may find that extra stack space must be
allocated. An extra 32 bytes should normally suffice.
For the benefit of readers without a macro-assembler, macros used
generally depend on the definition of registers as B=0, C=1, D=2,
E=3, H=4, L=5, M=SP=PSW=6, A=7. Between the macro definitions and
the actual code generated, users should be able to substitute
suitable source code. Our assembler permits "@" and "." in names,
automatically increments and decrements the global variable ".LVL"
on each PUSH and POP instruction, respectively, and can generate
relocatable code. Source code between IF and ENDIF statements is
assembled only if the IF operand is non-zero, and between IFZ and
ENDIF only if the IFZ operand is zero. This listing uses this
construct only within macros. The "EXTRN" lists show external
addresses required within a module, and the "ENTRY" lists show
address required by other modules. Note that some character
constants may be in lower case (and are so marked). The printer
used translated these to upper case. This should be sufficient to
allow the user to customize the source to his assembler.
I originally intended to submit listings with all macros fully
expanded, but the results were excessively cluttered, no longer
held any clarity, and the listing length was virtually doubled. As
submitted, all information remains present, but the reader may
have to refer to the macro definitions fairly often.
The load map below shows the location of all routines when loaded
at location 1000H up, in the order shown. The "U" identifies
labels undefined in the overall system.
Historically, this system replaced an earlier design (published in
the Intel User Library) which used 2's complement mantissas and
exponents. That system had 1 less bit of resolution, control of
negative extremes and rounding had a problem, and was 5 to 10
times slower than the present system.
Load Map
--------
Code Data Name
--------- ---- ----
1000-115A None INTARITH.ASM
115B-1463 None FLTARITH.ASM
1464-15BB None FLTINPUT.ASM
15BC-17D2 None FLTOUT.ASM
17D3-19FA None FUNCTION.ASM
.AND 1986 .EQU 19A6 .GE. 19D7 .GG. 19E0
.GT. 19C5 .LE. 19BC .LT. 19CE .NE. 19AF
.OR. 1971 .XOR 1996 U-AERC 0000 BCLC 102B
BCLZ 102A BCRA 1032 BCRC 1034 C1BC 1045
C1DE 104D C2BC 1044 C2DE 104C C2DHL 1054
U-COUT 0000 DEBLK 1479 DERA 103B DERC 103D
DHLZ 1022 DIV 1114 DQUIK 1082 DTEN 106A
EXDG 15FF EXP2 18E1 EXPX 1931 FADD 1303
FCMP 1387 FDIV 1248 FDIVR 12A5 FDIVT 1202
FINT 13DC FIXR 1439 FIXT 1404 FLOAD 11DC
FLOT 13E1 FLOTA 13B9 FLOTD 13D7 FLOTP 13CE
FMAT 172B FMOD 17EE FMUL 1210 FMULT 11F4
FRACT 17D3 FRCIP 12B1 FSTOR 11E8 FSUB 137A
FSUBR 12FF FXCHG 11B5 IDIV 10A7 IMUL 108A
IVAL 1482 IVALC 14B5 JBC 1477 LAS 101A
LBCS 1011 LDES 1008 LFBIS 11A9 LFBS 119C
LFDIS 11B9 LFDS 11BF LFLT 170C LOG2 1B23
LOGB 188C U-LOUT 0000 MUL 10D9 MUL10 1061
MLRD 115B DDZS 15E1 DFLT 171C ONEG 15DC
OPT 15D7 DTCBK 15BC DTCCL 15BE POLY 1BAB
QMAX 146B QNUM 1464 SFDIS 11C9 STADR 1000
TFLT 1714
EOF