"A floating point subroutine package for the 1802" Paul Wasserman, Union NJ published issue #37 Vol 4, 1979, pages 17-19 including hex dump. "Reprint Privileges: Article herein that are copyrighted by individual authors or otherwise explictly marked as having restricted reproduction rights may not be reprinted or copied without permission from People's Computer Company, or the authors. All other articles may be reprinted for any non-com- mercial purpose, provide a credit-line is included. The credit- line should indicate that the material was reprinted from "Dr. Dobb's Journal of Computer Calisthenics and Orthodontia, Box E, Menlo Park, CA 94025" - end quote. After purchasing my 1802 based microcomputer system, I was surprised to find how little software there is available for it. In particular, I was disappointed by the absence of a readily-available floating point arithmetic subroutine package. To help wipe out this void, I set out to write such a subroutine package. The results of my work appear in the rest of this article. When this project was started, I decided that the floating point arithmetic routines would implement a set of existing algorithms rather than writing a new set. Suitable algorithms were found in a book written by Neill Graham entitled "Micro- processor Programming for Computer Hobbyists", published by Tab Books. I strongly recommend the purchase of this book to anyone who wishes to understand or modify the intemal workings of this set of floating point arithmetic routines. This article will not attempt to describe the routines’ inner workings. It will, however, provide the information needed to use these routines. All floating point numbers contain two parts: a signed mantissa and a signed exponent. +1.16 X 10**+2 is an example of a decimal floating point number. +1.16 is the signed mantissa and +2 is the signed exponent. Similarly, +1.1101 X 2**+110 is the binary floating point equivalent of 116. Here, +l.1101 is the signed mantissa and +110 is the signed exponent. The binary mantissa used by the floating point subroutine is 32 bits long (4 bytes). The radix point lies between the left-most bit (LMB) and the bit to the immediate right of the LMB. The sign of the mantissa is represented by a single byte which can take on two values, 00(hex) or FF (hex). If this byte is 00 (hex), the mantissa is positive. Similarly, if this byte is FF (hex), the mantissa is negative. The signed binary exponent is represented by a single byte. In order to have both positive and negative integers in the single byte exponent, a convenient numbering scheme was adopted. This scheme defined 80 (hex) as zero. Anything larger than 80 (hex) is positive and anything smaller than 80 (hex) is negative. For example, 83 (hex) represents a binary exponent of +11 = +3 (decimal) and similarly 7F (hex) repre- sents a binary exponent of -1 . The exponent can vary between 00 (hex) and FF (hex). These numbers represent decimal exponents between the range of 10**-39 and 10**+38. Figure l - mantissa is always .MMMM. Byte addresses are in representation order. AC Sign .AC Mantissa AC exp 010D 103,102,101,100 010F,010E OP Sign .OP Mantissa OP exp 0110 107,106,105,104 0111 Figure 1 illustrates the representation of floating point numbers in the accumulator (AC) and operand (OP) registers. Notice that the accumulator exponent is 2 bytes wide. The hi byte is O0 (hex) unless an over or underfiow has occurred. The hexidecirnal numbers placed below the diagrams in Figure 1 are the memory locations used to store (in RAM) the bytes that make up the accumulator and operand. Most people can handle floating point decimal numbers with relative ease. The computer, unlike most people, is more efficient at handling binary numbers. To accommodate this difference, two routines are included in the floating point arithmetic package which allow for the conversion between binary and decimal numbers. Both of these routines use the accumulator register to hold binary numbers. An additional register is used by both routines for decimal numbers. This decimal register (D) is shown in Figure 2. Figure 2 decimal point is at right end of mantissa. DM sign DM mantissa. 0114 0115,116,117,118,119,11A,11B. DE sign DE exp 011C 011D,11E The decimal register is composed of four parts: the sign of the mantissa (DM Sign), the 7-digit decimal mantissa (DM), the sign of the exponent (DE Sign) and the 2-digit exponent (DE). Both signs are represented by their standard ASCII codes; that is, 2D (hex) for negative and 2B (hex) for positive. The decimal digits (0-9) of both the exponent for the mantissa are represented by their corresponding 4-bit binary codes. These codes are placed in the four least significant bits of each byte. The four most significant bits are ignored by the conversion routines. This allows the use of ASCII codes on all entries in decimal register. For example, the number +1.234567 X 10” = +1234567. X 10**+2 could be represented in the decimal register in the following ways: 2B 01 02 03 04 05 06 07 2D 00 04 or 2B 31 32 33 34 35 36 37 2D 30 34 (ASCII). These conversion routines appear in Figure 3 as D—>AC (decimal to binary conversion) and AC —> D (binary to deci- mal conversion). All the routines in the floating point arithmetic package use the Standard Call and Return Technique (SCRT). This technique is explained in RCA’s User Manual for the CDP 1802 [MPM-201] on pgs. 61-64. [Note by Herb: SCRT establishes: R2 is stack pointer to stack area stack is push and decrement addr, pop and increment addr R3 is program counter R4 is call as in SEP R4 [address] R5 is return as in SEP R5 R6 is pointer to (address) after the called address, which may have additional data/argument ] The microprocessor registers R(2)— R(6) must be set up to handle the SCRT before any sub- routines can be used. The user must also provide the SCRT code before using any subroutines. A subroutine is called by a D4 (hex) instruction, followed by the address of the sub- routine. In some cases, additional numbers (labeled arguments in Figure 3) follow the address. Figure 3 lists all the user subroutines in the floating point arithmetic package. [Figure 3: list of routine calls. Addresses preceeded by 1802 code D4 (SEP R4) which is SCRT CALL . V is a variable register numbered 00H to 29H. Calling code is detailed in the text.] 0400 AC+OP -> AC 02E9 AC-OP -> AC (address corrected from original article) 02B7 AC*OP -> AC 034C AC/OP -> AC 03C3 0 -> AC 03D9 0 -> OP 0773 SQRT(AC) -> AC 0500 D -> AC 0598 AC -> D 06DA V -> AC 0705 V -> OP 072C AC -> V 0754 MMMMSE -> AC The top four routines shown in Figure 3 perform floating point addition, subtraction, multiplication and division, res- pectively. The next two routines clear (set to zero) the con- tents of the accumulator or the operand. A square root routine follows next on the list. This routine uses the Newton-Raphson iterative method to find the square root of the contents of the accumulator. The next two routines perform conversions between binary and decimal numbers as previously described. The next three routines allow the user to store and recall [variable] numbers from memory. [The last stores a constant into the accumulator.] There are forty-two variable storage registers (referred to as variables) numbered 00(hex)-29 (hex). Any one of these variables can be loaded into either the accumulator or operand registers. Similarly, the contents of the accumulator can be stored in any one of the variables. For example, if we wanted to load the accumulator with the con- tents of variable 08, the following code would be used D4 06DA 08 (08 = V). The last routine shown in Figure 3 loads the accumulator with the binary floating point number that immediately follows the instruction. The first four bytes fol- lowing the calling address (0754) make up the binary mantissa. These bytes should be in reverse order. For example, if the mantissa equals 42 6C 3D 0E, this subroutine requires 0E, 3D, 6C, 42 be placed after the calling address. As shown in Figure 3, the mantissa sign (S) and exponent (E) should be placed im- mediately after the mantissa. [Figure 4 code example] D4 0500 D->AC ;convert radius R to binary D4 072C 01 AC->V1 ;store R in variable V1 D4 0754 08 EE 87 64 00 82 PI -> AC ; load AC with Pi D4 0705 01 V1->OP ; load OP with V1=R D4 02B7 AC*OP->AC ;ac = Pi*R D4 02B7 AC*OP->AC ;ac = Pi*R*R D4 0598 AC->D ;convert to decimal into D The example shown in Figure 4 illustrates how some of these routines may be used to find the area of a circle, given its radius. Figure 5 is a listing of the hex code for the floating point arithmetic subroutine package. These subroutines start at the beginning of memory page 01 and end at the last byte of page 08. Page 08 is used for the variable storage. If you want to change the location in memory of these subroutines you must always start them at the beginning of a page. Also, certain modifications to the routines must be made. For example, if you want to move the beginning of the subroutine package two pages, from page 01 to page 03 in memory, you must add 02 to all of the underlined bytes. You would also have to add 02 to the high order byte of all the routine calling addresses. This subroutine package uses the follow- ing 1802 registers: R(A), R(B), and R(C). In addition, the square root routine uses register R(D) and variables 26 (hex) and 27 (hex). Please note that the SCRT (which you must supply) uses R(2), R(3), R(4) and R(5). [Herb: also R(6) as a link to arguments after the calling address.] Using this floating point arithmetic package, I have been able to write routines that generate exponentials, sines and cosines. I hope that you will fmd these routines as useful as I have.