(Comp.sys.hp48) Item: 3867 by jamesu@anacad.fr [James Unterburger] Subj: HP48 floating point ML suggestions Date: 23 Feb 1994 [Note: The JAZZ library's assembler recognizes Inf (infinity) and NaN (Not a Number) as valid objects. These were described in the HP-71 literature ten years ago, and were never mentioned again... until this article. Thanks, Jim! -jkh-] Here is what I think I know about HP48 (and HP71B) floating point. If I'm wrong in any detail, please let me know. The entry point addresses are for the HP48SX-E, but are supported entry points, so should be the same on any HP48 version. A "split" floating point number is held in two registers. I call this a "15-form" number (throwback to HP71B terminology). It is obtained by calling SPLITA (#2BC4Ah) with a "12-form" number in A.W. Or if you have two 12-forms, one in A.W and the other in C.W, you can call SPLTAC (#2BCA0h), which returns two 15-forms, in A/B and C/D (the "/" does _not_ mean "division", it is simply notation showing the location of the 15-form split extended real). Each of these routines returns in DEC mode. If you need to know how a 15-form number is stored in the two registers it occupies, it's like this (X is don't care, M is mantissa digit, E is exponent digit, S is sign nibble): 12-form: SMMMMMMMMMMMMEEE 15-form: SXXXXXXXXXXEEEEE XMMMMMMMMMMMMMMM Notice that you get 15 mantissa digits (hence the term 15-form) for an extended real. When you first split a 12-form into a 15-form, the extra three digits will be zeros. The SPLITA and SPLTAC routines also check for "funny" inputs in that Inf and NaN (not obtainable on the HP48 from user-level operations) are handled. For Inf and NaN inputs, Carry will be set upon return. Otherwise, Carry is clear. Also, the numbers are "normalized" meaning that if the first mantissa digit is zero, the mantissa is shifted left (and exponent adjusted accordingly) until the first mantissa digit is non-zero. To add two real numbers in ML, the routine RADDF is the one that I use. It expects two 15-form extended precision reals in A/B and C/D and returns the sum in A/B. It uses the D0 register (and ABCD obviously). It should be called with the mode set to DEC (SETDEC instruction). To subtract C/D from A/B, simply issue the C=-C-1 S instruction (in DEC mode) before calling RADDF. RADDF is at #2B7CAh. To multiply A/B by C/D, call MULTF (#2B91Eh). It does not use the D0 register, thankfully. To divide A/B by C/D, call DIVF (#2B977h). It doesn't use D0 either. Special cases (like Inf and NaN) are trapped partially I believe, but can't be sure. A better (unsupported unfortunately) entry point is ((=DIVF)-6) which is the same as DIVF except that Inf and NaN are checked for as inputs as well. (NaN can be considered the "Undefined Result") As a matter of fact, RADDF, MULTF, and DIVF all have, 6 nibbles before them, the old HP71B code which checks for Inf and NaN as inputs and handles accordingly. Generally, this type of exceptions causes the [XM] bit of the hardware status to be set. P==3 for Inf and P==4 for NaN as well. If you want to know more about these hidden HP71B remnants, read my ML code for the TRID (tridiagonal matrix system solver) program which makes full use of them. If you want a copy, just let me know. jamesu@anacad.fr James Unterburger