<H2><font color="#0000DD">ARM Assembly language Programming<BR></font></H2>
<p><cite>RISCWorld</cite></p>
<P>
<B><FONT SIZE="+4">Appendix B The Floating Point Instruction Set </FONT></B>
<P>
Appendix A described the generic form which co-processor instructions take. In this appendix, we look at a specific use of these instructions: the floating point unit.
<P>
The definition given here does not describe any particular hardware. Rather, it gives a programmer's view of a system which could be implemented in a number of ways. In the first instance, the instruction set of the FPU has been implemented entirely in software. All of the instructions are trapped through the unimplemented instruction vector, and the floating point emulator package uses this facility to interpret the operation codes (using native ARM instructions) and perform the appropriate operations.
<P>
At the other end of the spectrum, a complete hardware implementation of the FPU would recognise the whole floating point instruction set, so the unimplemented instruction trap would never be used. The ARM's only involvement in dealing with the instructions would be in the generation of addresses for data transfers and providing or receiving values for register transfers.
<P>
The only difference, from the programmer's point of view, between the two implementations would be the speed at which the instructions are executed. The only reason for using a hardware solution is that this can provide a speed increase of hundreds of times over the interpreted implementation.
<P>
The FPU performs arithmetic to the IEEE 754 standard for floating point.
<P>
<B><FONT SIZE="+4">B.1 Some terminology</FONT></B>
<P>
In describing the FPU's instruction set, we have to use certain terms which are specific to floating point arithmetic. These are explained briefly in this section. For a more detailed discussion, you should see the appropriate IEEE standard document (ANSI/IEEE 754-1985), or manufacturer's data on one of the current available FPUs (e.g. the Motorola MC68881 or Western Digital WE32206).
<P>
<B><FONT SIZE="+2">Precision </FONT></B>
<P>
The instruction set includes three precisions to which calculations may be performed. The precision of a floating point number is the number of digits which can be stored with total accuracy. It is expressed in bits. In Chapter Five, we talked about the mantissa of a floating number being the part which stored the significant digits, and the exponent being the scaling factor applied to it.
<P>
When we say a given floating point representation has n bits of precision, this means that the mantissa part is stored in n bits. The three standard IEEE precisions are 24 bits, 53 bits and 65 bits. These are known as single, double, and extended precision respectively. The mantissa is stored in one fewer bits than the precision implies because numbers are held in normalised form (as in BBC BASIC) and the MSB is an implicit 1. The binary point comes <I>after</I> this.
<P>
There is a fixed correspondence between the precision of a number expressed in bits, and how many decimal digits that number can represent. Mathematically speaking, an n-bit number can hold n*LOG(2)/LOG(10) decimal digits, or more simply, n*0.3010. Thus the three IEEE floating points types can accurately represent the following number of decimal digits:
<DIV ALIGN=CENTER>
<TABLE CELLPADDING=5>
<TR><TD WIDTH=101><TT>Type </TT>
<TD ALIGN=CENTER WIDTH=104><TT>Precision </TT>
<TD WIDTH=240><TT>Decimal digits </TT>
</TABLE>
</DIV>
<DIV ALIGN=CENTER>
<TABLE CELLPADDING=5>
<TR><TD ALIGN=CENTER WIDTH=101><TT>Single </TT>
<TD WIDTH=104><TT>24 </TT>
<TD WIDTH=240><TT>7.2 </TT>
</TABLE>
</DIV>
<DIV ALIGN=CENTER>
<TABLE CELLPADDING=5>
<TR><TD ALIGN=CENTER WIDTH=101><TT>Double </TT>
<TD WIDTH=104><TT>53 </TT>
<TD WIDTH=240><TT>15.95 </TT>
</TABLE>
</DIV>
<DIV ALIGN=CENTER>
<TABLE CELLPADDING=5>
<TR><TD ALIGN=CENTER WIDTH=101><TT>Extended </TT>
<TD WIDTH=104><TT>65 </TT>
<TD WIDTH=240><TT>19.6 </TT>
</TABLE>
</DIV>
<P>
Obviously you cannot have fractional numbers of significant digits, so the values should be truncated to 7, 15 and 19 respectively. The fractional part means that one extra digit can be stored, but this cannot go all the way up to
<P>
9.
<P>
There is one further form of representation for floating point numbers: packed decimal. In this form, the decimal digits of the mantissa and exponent are represented in a coded form, with four bits representing each decimal digit (only the combinations 0000 to 1001 being used). In this form, called packed decimal, the mantissa is stored as 19 four-bit 'digits', and the exponent as 4 four-bit digits.
<P>
Just because a number can be represented exactly in decimal, do not assume that its binary representation is also exact. For example, the decimal fraction 0.1 is actually a recurring fraction in binary, and can never be stored exactly (though of course, when enough digits are used in the mantissa, the error is very small).
<P>
<B><FONT SIZE="+2">Dynamic range </FONT></B>
<P>
The mantissa has an imaginary binary point before after its first digit, and the first digit is always a binary 1, never 0. This is known as 'normalised form'. Thus the mantissa stands for a fraction between 1.0 and 1.99999... The exponent provides the power of two by which the mantissa has to be multiplied to obtain the desired value.
<P>
To obtain numbers greater than 1.999999... a positive exponent is used, and to represent numbers smaller than 1.0, a negative exponent is used (meaning that the mantissa is divided by a power of two instead of multiplied). The exact range of numbers depends on the maximum power of two by which the mantissa may be multiplied or divided. This is known as the dynamic range of the representation.
<P>
Each of the precisions uses a different size of exponent, as follows:
The table shows how many bits the exponent uses, and the smallest and largest factors by which the mantissa may be multiplied. The formula n*0.3010 can also be used to find out what power of ten these exponents correspond to. They are +/-39, +/-307 and +/-4931 respectively. Thus a single precision IEEE number could represent the number 1.234E12 but not 1.234E45. This would require a double precision number.
<P>
The exponent is held in an excess-n format, as with BBC BASIC. The excess number is 127, 1023 and 16383 for the three precisions respectively. Note that there is an exponent value at each end of the range (e.g. -127 and +128, stored as 0 and 255, in single precision) which is not used. These values are used to represent special numbers.
<P>
<B><FONT SIZE="+2">Rounding </FONT></B>
<P>
When the FPU performs its calculations, more digits are used than are necessary to store the numbers involved. Calculations are performed in what is called 'full working precision'. This is so that any errors which accumulate due to non-exact representations of fractions do not affect the final result. When a result is presented, the FPU converts the special full working form into a value of the desired precision. The way in which this conversion is performed is called the 'rounding mode' of the calculation, and there are four of them to choose from.
<P>
'Round to nearest' means that the final result is the closest number in the selected precision to the internal version. This is used as the default mode for ARM FPU instructions.
<P>
'Round to zero' means that the extra bits of precision are effectively ignored, so the final result is the one which is closest to zero.
<P>
'Round to plus infinity' means that the final result is the first number which is greater than the 'exact' result which can be stored in the required precision.
<P>
'Round to minus infinity' means that the final result is the first number which is less than the 'exact' result which can be stored in the required precision.
<P>
These four modes can be illustrated by using decimal numbers. Suppose that the calculations are performed to nine digits precision, and the final precision is seven digits:
<P>
<TT> Mode 'Exact' result Rounded result<BR>
</TT>
<P>
<TT> Nearest 0.123456789 0.1234568<BR>
-0.123456789 -0.1234568<BR>
</TT>
<P>
<TT> To zero 0.123456789 0.1234567<BR>
-0.123456789 -0.1234567<BR>
</TT>
<P>
<TT> To +infinity 0.123456789 0.1234568<BR>
-0.123456789 -0.1234567<BR>
</TT>
<P>
<TT> To -infinity 0.123456789 0.1234567<BR>
-0.123456789 -0.1234568<BR>
</TT>
<P>
<B><FONT SIZE="+2">Special values </FONT></B>
<P>
In addition to valid numeric values, the IEEE standard also defines representations for values which may arise from errors in calculations. These values are 'not a number' (NAN), plus infinity (+INF) and minus infinity (-INF). There are actually two types of NAN, trapping and non-trapping. Trapping is described in the next section. The ways in which these special values may arise are also described there.
<P>
Note that IEEE defines two representations for zero, positive and negative zero. Usually the distinction between them is not important, but sometimes a result will depend on the sign of the zero used (see the DVZ trap below for an example).
To the programmer, the FPU looks like a cut-down version of the ARM CPU. There are eight general purpose registers, called F0 to F7, a status register and a control register. There is no program counter; the ARM controls all interaction between a co-processor and memory. It is responsible for generating addresses for instruction fetches and data transfers.
<P>
Whereas the ARM's own 16 registers are 32 bits wide, there is no definition about how wide the FPU's registers are. The IEEE standard specifies several levels of precision to which operations may be performed, as described above. All the programmer needs to know about the FPU registers is that they are wide enough to maintain numbers to the highest precision required by the standard.
<P>
However, when floating point numbers are transferred between the FPU and memory, their representation becomes important. The formats of the various types of floating number are described in section B.6.
<P>
<B><FONT SIZE="+2">The FPU status register </FONT></B>
<P>
The FPU's status register is 32-bits wide, and contains three fields. These are the status flags, the interrupt masks, and a system id field. There are five flags, and each of these represents a specific error condition which can arise during floating point operations. Each flag has a corresponding interrupt mask. When an error condition arises, the FPU checks the state of the interrupt mask for that error. If the interrupt is enabled, a trap is generated, which causes the program to halt. The appropriate status flag is set, so that the trap handler can determine the cause of the error.
<P>
If the interrupt for the error condition is disabled, the status flag still gets set, but execution of the program is not affected. A special result, e.g. NAN or INF is returned.
<P>
Note that the way in which an error interrupt is implemented depends on the system in which the program is executing. Software and hardware FPUs will have different ways of stopping the program.
<P>
The flags are set if the appropriate condition has arisen, and cleared if not. The masks are set to enable the interrupt, and cleared to disable it. There is an FPU instruction which is used to initialise the status register to a known state.
<P>
Here is the layout of the status register:
<P>
bit 0 IVO flag<BR>
bit 1 DVZ flag<BR>
bit 2 OFL flag<BR>
bit 3 UFL flag<BR>
bit 4 INX flag<BR>
bits 5 to 15 Unused (These are read as zero)<BR>
bit 16 IVO mask<BR>
bit 17 DVZ mask<BR>
bit 18 OFL mask<BR>
bit 19 UFL mask<BR>
bit 20 INX mask<BR>
bits 21 to 23 Unused (These are read as zero)<BR>
bits 24 to 31 System id (These are 'read-only')<BR>
<P>
The meanings of the three-letter abbreviations are as follows:
<P>
<B>IVO -</B>Invalid operation. There are several operations which are deemed 'invalid', and each of these sets the IVO flag, and causes the instruction to be trapped if enabled. If the trap is not enabled, an operation which causes the IVO flag to be set returns NAN as the result. Invalid operations are:
<P>
Any operation on a NAN<BR>
Trying to 'cancel' infinities, e.g. -INF plus +INF<BR>
Zero times +INF or -INF<BR>
0/0 or INF/INF<BR>
INF <TT><B>REM</B></TT> anything or anything <TT><B>REM</B></TT> 0<BR>
<TT><B>SQT</B></TT>( <0 )<BR>
Converting INF, NAN or too large a number to integer<BR>
Writing to the unused or system id bits of the status register<BR>
<P>
where >1 means 'a number greater than one' etc, and INF means either +INF or -INF. Note that in the case of converting an INF or too large a number to an integer, the result (if the error is not trapped) is the largest integer of the appropriate sign which can be represented in 32 bits two's complement.
<P>
<B>DVZ</B> - Divide by zero. This is caused by trying to divide a non-zero number by zero. The result, if the error is not trapped, is an infinity of the appropriate sign (e.g. -1/0 gives -INF, -32.5/-0 gives +INF).
<P>
<B>OFL</B> - Overflow. This occurs when a result is being rounded to the specified precision for the operation. If it is impossible to legally represent the number, a trap occurs. If the trap is disabled, the result depends on the rounding mode specified in the operation:
<P>
Nearest Appropriately signed INF
<P>
To zero Largest representable number of appropriate sign
<P>
To +INF Negative overflows go to largest negative number
<P>
Positive overflows go to +INF<BR>
To -INF Negative overflows go to -INF<BR>
Positive overflows go to largest positive number<BR>
<P>
<B>UFL</B> - Underflow. This occurs when a number becomes too small (i.e. too close to zero) to represent properly in the specified precision. If the error is not trapped, the result is affected by the rounding mode as follows:
<P>
Nearest Appropriately signed zero
<P>
To zero Appropriately signed zero
<P>
To +INF Negative underflows go to -0
<P>
Positive underflows go to smallest positive number<BR>
To -INF Negative underflows go to smallest negative number<BR>
Positive underflows go to +0<BR>
<P>
<B>INX</B> - Inexact. This error occurs whenever a rounded result is obtained which is different from that which would have been calculated if 'infinite' working precision was used. Calculating the sine, cosine or tangent of an angle greater than 10E20 radians causes this error. Also, all OFL errors automatically cause this error, so if the OFL trap is disabled but the INX trap is enabled, an overflow will cause the inexact interrupt to be generated.
<P>
<B>System id</B> -These eight bits may be used to determine which type of FPU the system is running. The only one currently defined is bit 31:
<P>
bit 31 = 1 implies hardware FPU
<P>
bit 31 = 0 implies software FPU
<P>
The remaining eight bits are reserved by Acorn for further distinction between different FPU types. In the first systems they are all zero.
<P>
<B><FONT SIZE="+2">The FPU control register </FONT></B>
<P>
The control register is a system dependent entity. It is present to enable programs to, for example, disable a hardware FPU. Its format is dependent on the characteristics of the FPU hardware; as of this writing, it is undefined. Note that the instructions which read and write the control register are privileged. An attempt to access it from a user mode program will cause an error.
<P>
<B><FONT SIZE="+4">B.3 The FPU data processing instructions </FONT></B>
<P>
There are two classes of FPU data processing instructions, monadic and dyadic. These terms refer to whether the instruction operates on one or two operands respectively. The instruction formats are:
<P>
<TT><B>MNM{cond}<P>{R} <dest>,<rhs><BR>
MNM{cond}<P>{R} <dest>,<lhs>,<rhs><BR>
</B></TT>
<P>
where:<BR>
<TT><B>MNM</B></TT> is one of the mnemonics listed below<BR>
<TT><B>{cond}</B></TT> is the optional condition<BR>
<P>
<TT><B><P></B></TT> is the required precision, being one of:
<P>
<TT><B>S</B></TT> single precision
<P>
<TT><B>D</B></TT> double precision
<P>
<TT><B>E</B></TT> extended precision
<P>
Note that the precision is not optional - it must be given.
<P>
<TT><B>{R}</B></TT> is the required rounding mode for the stored result, being one of:
<P>
Round to nearest<BR>
<TT><B>P</B></TT> Round to +INF<BR>
<TT><B>M</B></TT> Round to -INF<BR>
<TT><B>Z</B></TT> Round to zero<BR>
<P>
This is optional, rounding to nearest being the default if it is omitted.
<P>
<TT><B><dest></B></TT> is the FPU register to hold the result. The standard names for the FPU registers are F0-F7, and assemblers which recognise the FPU instructions allow other names to be assigned, as for the normal ARM registers.
<P>
<TT><B><lhs></B></TT> (dyadic only) is the left hand side of the operation. It is an FPU register
<P>
<TT><B><rhs></B></TT> is the right hand side of a dyadic operation, or the argument of a monadic operation. It is an FPU register, or a small floating point constant. These are the allowed values:
<P>
<TT><B>0.0 1.0 2.0 3.0<BR>
</B></TT>
<P>
<TT><B>4.0 5.0 0.5 10.0<BR>
</B></TT>
<TT></TT>
<P>
As usual, the immediate operand is preceded by a <TT><B>#</B></TT> sign.
<P>
The available dyadic operations are:
<P>
<TT><B>ADF add<BR>
MUF multiply<BR>
SUF subtract<BR>
RSF reverse sub.<BR>
DVF divide<BR>
RDF reverse div.<BR>
POW power<BR>
RPW reverse power<BR>
RMF remainder<BR>
FML fast multiply<BR>
FDV fast divide<BR>
FRD fast rev. div.<BR>
POL polar angle<BR>
</B></TT>
<P>
<TT><B><dest> = <lhs> + <rhs><BR>
<dest> = <lhs> * <rhs><BR>
<dest> = <lhs> - <rhs><BR>
<dest> = <rhs> - <lhs><BR>
<dest> = <lhs> / <rhs><BR>
<dest> = <rhs> / <lhs><BR>
<dest> = <lhs> ^ <rhs><BR>
<dest> = <rhs> ^ <lhs><BR>
<dest> = <lhs> REM <rhs><BR>
<dest> = <lhs> * <rhs><BR>
<dest> = <lhs> / <rhs><BR>
<dest> = <rhs> / <lhs><BR>
<dest> = arctan(<lhs>/<rhs>)<BR>
</B></TT>
<P>
<B><FONT SIZE="+1">Notes: </FONT></B>
<P>
Reverse power gives a base ten antilog function:
<P>
<TT><B> RPWS F0,F0,#10.0 ;F0 = 10^F0<BR>
</B></TT>
<P>
<TT><B>REM <lhs>,<rhs></B></TT> gives the remainder of the division of <TT><B><lhs></B></TT> by <TT><B><rhs></B></TT>. In other words, <TT><B>a REM b = a-b*n</B></TT>, where <TT><B>n</B></TT> is the nearest integer to <TT><B>a/b</B></TT>.
<P>
The 'fast' operations <TT><B>FML</B></TT>, <TT><B>FDV</B></TT> and <TT><B>FRD</B></TT> are performed in single precision, rather than full working precision used for the other calculations. This means that rounding to any precision will always yield a result which is only as accurate as a single precision number.
<P>
The <TT><B>POL</B></TT> operation is an alternative to the <TT><B>ATN</B></TT> operation described below. The two operands may be regarded as the 'opposite' and 'adjacent' lengths (signed) of the angle whose value is required. This function will return a result in the range -PI to +PI radians, whereas the standard <TT><B>ATN</B></TT> function only gives a result in the -PI/2 to +PI/2 range.
<P>
The monadic operations are:
<P>
<TT><B>MVF move<BR>
MNF move negated<BR>
ABS absolute value<BR>
RND integer value<BR>
SQT square root<BR>
LOG log base 10<BR>
LGN log base e <BR>
</B></TT>
<P>
<TT><B><dest> = <rhs><BR>
<dest> = -<rhs><BR>
<dest> = ABS(<dest>)<BR>
<dest> = roundToInteger(<rhs>)<BR>
<dest> = SQR(<rhs>)<BR>
<dest> = LOG10(<rhs>)<BR>
</B></TT>
<P>
<TT><B><dest> = LN(<rhs>)<BR>
</B></TT>
<P>
<TT><B>EXP e to a power<BR>
SIN sine<BR>
COS cosine<BR>
TAN tangent<BR>
ASN arcsine<BR>
ACS arccosine<BR>
ATN arctangent<BR>
</B></TT>
<P>
<TT><B><dest> = e ^ <rhs><BR>
<dest> = SIN(<rhs>)<BR>
<dest> = COS(<rhs>)<BR>
<dest> = TAN(<rhs>)<BR>
<dest> = ATN(<rhs>)<BR>
<dest> = ACS(<rhs>)<BR>
<dest> = ATN(<rhs>)<BR>
</B></TT>
<P>
The argument of the <TT><B>SIN</B></TT>, <TT><B>COS</B></TT> and <TT><B>TAN</B></TT> is in radians, and <TT><B>ASN</B></TT>, <TT><B>ACS</B></TT> and <TT><B>ATN</B></TT> return a result in radians. The 'transcendental' functions, from <TT><B>SQT </B></TT>onwards, use 'to nearest' rounding for intermediate calculations performed in full working precision, only applying the specified rounding mode as the last operation.
<P>
<B><FONT SIZE="+1">Examples: </FONT></B>
<P>
<TT><B>MUFS F0,F1,#10.0 ;F0=F1*10, single precision,nearest<BR>
<B><FONT SIZE="+4">B.4 The FPU/ARM register transfer instructions </FONT></B>
<P>
The FPU uses the <TT><B>FRC</B></TT>/<TT><B>FCR</B></TT> class of instructions for three purposes: to convert between integer and floating point values, to examine and change the FPU status and control registers, and to perform floating point comparisons.
<P>
<TT><B>FIX</B></TT> and <TT><B>FLT</B></TT> are the type-conversion instructions. They have the following forms:
<P>
<TT><B>FIX{cond}<P>{R} <ARM dest>,<FPU srce><BR>
FLT{cond}<P>{R} <FPU dest>,<ARM srce><BR>
</B></TT>
<P>
<TT><B><ARM dest></B></TT> is R0-R14 (R15 not being useful; see Appendix A)<BR>
<TT><B><ARM srce></B></TT> is R0-R14 (R15 not being useful)<BR>
<TT><B><FPU dest></B></TT> is F0-F7<BR>
<TT><B><FPU srce></B></TT> is F0-F7<BR>
<P>
The <TT><B>FIX</B></TT> operation may result in an <TT><B>IVO</B></TT> trap occurring, as explained above.<BR>
<P>
<B><FONT SIZE="+1">Examples: </FONT></B>
<P>
<TT><B>FIXNES R0,F2 ;Convert F2 to integer in R0 if NE<BR>
FLTSZ F1,R0 ;Convert R0 to F1, round to zero<BR>
</B></TT>
<P>
The instructions to read and write the FPU status register are:
<P>
<TT><B>RFS{cond} <ARM dest><BR>
WFS{cond} <ARM srce><BR>
</B></TT>
<P>
<TT><B><ARM dest></B></TT> and <TT><B><ARM srce></B></TT> are the ARM register to or from which the 32-bit FPU status register is transferred. The format of this register is described above. After an <TT><B>RFS</B></TT> the ARM register will contain the state of the status flags and interrupt masks. The unused bits will be set to zero, and the system id part will be as described above. A program can clear the flags and set the desired mask bits using <TT><B>WFS</B></TT>. Zeros should be placed in the unused bits and the system id bits.
<P>
The instructions to read and write the FPU control register are:
<P>
<TT><B>RFC{cond} <ARM dest><BR>
WFC{cond} <ARM srce><BR>
</B></TT>
<P>
The format of this register is system dependent. These are privileged instructions and will abort if an attempt is made to execute them in user mode.
<P>
<B><FONT SIZE="+1">Examples: </FONT></B>
<P>
<TT><B>RFS R4<BR>
WFC R0<BR>
</B></TT>
<P>
The FPU compare instructions have the form:
<P>
<TT><B>MNM{cond}<P>{R} <lhs>,<rhs><BR>
</B></TT>
<P>
where all terms are as described in section B.3. The mnemonics are:
The versions with the <TT><B>E</B></TT> suffix generate an exception if the operands are 'unordered' (when at least one operand is a NAN) and thus can't be compared. After the instructions, the ARM flags are set as follows:
<P>
<TT><B>N</B></TT> set if 'less than' else clear
<P>
<TT><B>Z</B></TT> set if 'equal' else clear
<P>
<TT><B>C</B></TT> set if 'greater or equal' else clear
<P>
<TT><B>V</B></TT> set if 'unordered' else clear
<P>
Note that if <TT><B>V</B></TT>=1, then <TT><B>N</B></TT>=0 and <TT><B>C</B></TT>=0.
<P>
According to the IEEE standard, when testing for equality or for unorderedness, where the next instruction condition will be <TT><B>EQ</B></TT>, <TT><B>NE</B></TT>, <TT><B>VS</B></TT> or <TT><B>VC</B></TT> you should use <TT><B>CMF</B></TT> (or <TT><B>CNF</B></TT>). To test for other relationships (<TT><B>GT</B></TT>, <TT><B>LE</B></TT> etc.) you should use <TT><B>CMFE</B></TT> (or <TT><B>CNFE</B></TT>).
<P>
<B><FONT SIZE="+1">Examples: </FONT></B>
<P>
<TT><B>CMFE F0,#0.0 ;See if F0 is 0.0, extended precision<BR>
CMFEE F1,F2 ;Compare F1, F2 using extended <BR>
</B></TT>
<P>
<TT><B>;precision with disordered exception<BR>
CNFS F3,#1.0 ;Compare single precision F3 with -1<BR>
</B></TT>
<P>
<B><FONT SIZE="+4">B.5 The FPU data transfer instructions </FONT></B>
<P>
This final group is used to transfer floating point numbers, in the various formats, between main memory and the FPU. The instructions are <TT><B>LDF</B></TT> to load a floating point number, and <TT><B>STF</B></TT> to store one:
<P>
<TT><B>LDF{cond}<P> <FPU dest>,<address><BR>
STF{cond}<P> <FPU srce>,<address><BR>
</B></TT>
<P>
where:
<P>
<TT><B><P></B></TT> is as already described, with the additional option of
<P>
<TT><B>P</B></TT> packed decimal form
<P>
The FPU registers are F0-F7
<P>
the <TT><B><address></B></TT> can take any of the forms described in Appendix A, viz.
<TR><TD WIDTH=162><TT>Un-normalised number s </TT>
<TD ALIGN=RIGHT WIDTH=88><TT>Not 0/Max </TT>
<TD ALIGN=CENTER WIDTH=18><TT>0 </TT>
<TD WIDTH=147><TT>xxxxxxxxxxxxxx... </TT>
</TABLE>
</DIV>
<DIV ALIGN=CENTER>
<TABLE CELLPADDING=5>
<TR><TD WIDTH=119><TT>Normalised number </TT>
<TD WIDTH=32><TT>s </TT>
<TD ALIGN=RIGHT WIDTH=88><TT>Not 0/Max </TT>
<TD ALIGN=CENTER WIDTH=18><TT>1 </TT>
<TD WIDTH=147><TT>xxxxxxxxxxxxxx... </TT>
</TABLE>
</DIV>
<P>
<B><FONT SIZE="+2">Packed decimal </FONT></B>
<P>
Each field is four bits e0-e3 are the exponent digits d0-d18 are the mantissa digits Bit 31 of the first word is the sign of the number Bit 30 of the first word is the sign of the exponent
<P>
<B><FONT SIZE="+1">Format of values </FONT></B>
<P>
<TT><B>bit 31 30 e3-e0 d18-d0<BR>
</B></TT>
<DIV ALIGN=CENTER>
<TABLE CELLPADDING=5>
<TR><TD WIDTH=116><TT>Non-trapping NAN </TT>
<TD ALIGN=RIGHT WIDTH=49><TT>x </TT>
<TD ALIGN=CENTER WIDTH=17><TT>x </TT>
<TD WIDTH=60><TT>&FFFF </TT>
<TD ALIGN=RIGHT WIDTH=140><TT>d18>7, rest non 0 </TT>
</TABLE>
</DIV>
<DIV ALIGN=CENTER>
<TABLE CELLPADDING=5>
<TR><TD WIDTH=116><TT>Trapping NAN </TT>
<TD ALIGN=RIGHT WIDTH=49><TT>x </TT>
<TD ALIGN=CENTER WIDTH=17><TT>x </TT>
<TD WIDTH=60><TT>&FFFF </TT>
<TD ALIGN=RIGHT WIDTH=140><TT>d18<=7, rest non 0 </TT>