815 lines
34 KiB
NASM
815 lines
34 KiB
NASM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;
|
|
;;; Microsoft Research Singularity
|
|
;;;
|
|
;;; Copyright (c) Microsoft Corporation. All rights reserved.
|
|
;;;
|
|
;;; This file contains ARM-specific assembly code.
|
|
;;;
|
|
|
|
; Assembler source for FPA support code and emulator
|
|
; ==================================================
|
|
; Definitions for FPA instructions and registers. Also used by "fplib".
|
|
;
|
|
; Copyright (C) Advanced RISC Machines Limited, 1992-7. All rights reserved.
|
|
;
|
|
; RCS Revision: 1
|
|
; Checkin Date: 2007/06/29 02:59:16
|
|
; Revising Author
|
|
|
|
;===========================================================================
|
|
|
|
; FPSR fields
|
|
; -----------
|
|
|
|
IOC_pos EQU 0
|
|
IOC_bit EQU 1:SHL:IOC_pos
|
|
DZC_pos EQU 1
|
|
DZC_bit EQU 1:SHL:DZC_pos
|
|
OFC_pos EQU 2
|
|
OFC_bit EQU 1:SHL:OFC_pos
|
|
UFC_pos EQU 3
|
|
UFC_bit EQU 1:SHL:UFC_pos
|
|
IXC_pos EQU 4
|
|
IXC_bit EQU 1:SHL:IXC_pos
|
|
ND_pos EQU 8
|
|
ND_bit EQU 1:SHL:ND_pos
|
|
NE_pos EQU 9
|
|
NE_bit EQU 1:SHL:NE_pos
|
|
SO_pos EQU 10
|
|
SO_bit EQU 1:SHL:SO_pos
|
|
EP_pos EQU 11
|
|
EP_bit EQU 1:SHL:EP_pos
|
|
AC_pos EQU 12
|
|
AC_bit EQU 1:SHL:AC_pos
|
|
IOE_pos EQU 16
|
|
IOE_bit EQU 1:SHL:IOE_pos
|
|
DZE_pos EQU 17
|
|
DZE_bit EQU 1:SHL:DZE_pos
|
|
OFE_pos EQU 18
|
|
OFE_bit EQU 1:SHL:OFE_pos
|
|
UFE_pos EQU 19
|
|
UFE_bit EQU 1:SHL:UFE_pos
|
|
IXE_pos EQU 20
|
|
IXE_bit EQU 1:SHL:IXE_pos
|
|
SysID_pos EQU 24
|
|
SysID_mask EQU &FF:SHL:SysID_pos
|
|
|
|
SysID_oldFPE EQU 0x00
|
|
SysID_FPE EQU 0x01
|
|
SysID_FPPC EQU 0x80
|
|
; SysID_FPA EQU 0x81 ;Already defined in "optcheck" file
|
|
|
|
;===========================================================================
|
|
|
|
; FPCR fields - many also valid for CPDO and CPRT instructions
|
|
; ------------------------------------------------------------
|
|
|
|
S2_pos EQU 0
|
|
S2_mask EQU &F:SHL:S2_pos
|
|
S2_Ibit EQU &8:SHL:S2_pos
|
|
Op3_pos EQU 4
|
|
Op3_mask EQU &1:SHL:Op3_pos
|
|
RM_pos EQU 5
|
|
RM_mask EQU &3:SHL:RM_pos
|
|
Pr2_pos EQU 7
|
|
Pr2_mask EQU &1:SHL:Pr2_pos
|
|
DA_pos EQU 8
|
|
DA_bit EQU 1:SHL:DA_pos
|
|
RE_pos EQU 9
|
|
RE_bit EQU 1:SHL:RE_pos
|
|
AB_pos EQU 10
|
|
AB_bit EQU 1:SHL:AB_pos
|
|
SB_pos EQU 11
|
|
SB_bit EQU 1:SHL:SB_pos
|
|
Ds_pos EQU 12
|
|
Ds_mask EQU &7:SHL:Ds_pos
|
|
Op2_pos EQU 15
|
|
Op2_mask EQU &1:SHL:Op2_pos
|
|
S1_pos EQU 16
|
|
S1_mask EQU &7:SHL:S1_pos
|
|
Pr1_pos EQU 19
|
|
Pr1_mask EQU &1:SHL:Pr1_pos
|
|
Op1_pos EQU 20
|
|
Op1_mask EQU &F:SHL:Op1_pos
|
|
EO_pos EQU 26
|
|
EO_bit EQU 1:SHL:EO_pos
|
|
MO_pos EQU 27
|
|
MO_bit EQU 1:SHL:MO_pos
|
|
IE_pos EQU 28
|
|
IE_bit EQU 1:SHL:IE_pos
|
|
RU_pos EQU 31
|
|
RU_bit EQU 1:SHL:RU_pos
|
|
|
|
Pr_mask EQU Pr1_mask+Pr2_mask
|
|
Op_mask EQU Op1_mask+Op2_mask+Op3_mask
|
|
|
|
; Rounding mode values
|
|
|
|
RM_Nearest EQU 0:SHL:RM_pos
|
|
RM_PlusInf EQU 1:SHL:RM_pos
|
|
RM_MinusInf EQU 2:SHL:RM_pos
|
|
RM_Zero EQU 3:SHL:RM_pos
|
|
|
|
;===========================================================================
|
|
|
|
; Instruction fields - all coprocessor instructions
|
|
; -------------------------------------------------
|
|
;
|
|
; The following bit distinguishes CPRTs from CPDOs.
|
|
|
|
RTnotDO_pos EQU 4
|
|
RTnotDO_bit EQU 1:SHL:RTnotDO_pos
|
|
|
|
; The two recognised coprocessor numbers and the position and mask of the
|
|
; field in the instruction.
|
|
|
|
Coproc_pos EQU 8
|
|
Coproc_mask EQU &F:SHL:Coproc_pos
|
|
Coproc_1 EQU 1:SHL:Coproc_pos
|
|
Coproc_2 EQU 2:SHL:Coproc_pos
|
|
|
|
; The following bit distinguishes CPDTs from CPRT/CPDOs.
|
|
|
|
RTDOnotDT_pos EQU 25
|
|
RTDOnotDT_bit EQU 1:SHL:RTDOnotDT_pos
|
|
|
|
; For instructions that take the undefined instruction exception vector, the
|
|
; following bit distinguishes coprocessor instructions from genuinely
|
|
; undefined instructions.
|
|
|
|
NotUndef_pos EQU 27
|
|
NotUndef_bit EQU 1:SHL:NotUndef_pos
|
|
|
|
Cond_pos EQU 28
|
|
Cond_mask EQU &F:SHL:Cond_pos
|
|
Cond_EQ EQU &0:SHL:Cond_pos
|
|
Cond_NE EQU &1:SHL:Cond_pos
|
|
Cond_CS EQU &2:SHL:Cond_pos
|
|
Cond_CC EQU &3:SHL:Cond_pos
|
|
Cond_MI EQU &4:SHL:Cond_pos
|
|
Cond_PL EQU &5:SHL:Cond_pos
|
|
Cond_VS EQU &6:SHL:Cond_pos
|
|
Cond_VC EQU &7:SHL:Cond_pos
|
|
Cond_HI EQU &8:SHL:Cond_pos
|
|
Cond_LS EQU &9:SHL:Cond_pos
|
|
Cond_GE EQU &A:SHL:Cond_pos
|
|
Cond_LT EQU &B:SHL:Cond_pos
|
|
Cond_GT EQU &C:SHL:Cond_pos
|
|
Cond_LE EQU &D:SHL:Cond_pos
|
|
Cond_AL EQU &E:SHL:Cond_pos
|
|
Cond_NV EQU &F:SHL:Cond_pos
|
|
|
|
; CPDT-specific instruction fields
|
|
; --------------------------------
|
|
|
|
DT_offset_pos EQU 0
|
|
DT_offset_mask EQU &FF:SHL:DT_offset_pos
|
|
DT_src_pos EQU 12
|
|
DT_src_mask EQU &7:SHL:DT_src_pos
|
|
DT_dst_pos EQU 12
|
|
DT_dst_mask EQU &7:SHL:DT_dst_pos
|
|
DT_pr2_pos EQU 15
|
|
DT_pr2_mask EQU &1:SHL:DT_pr2_pos
|
|
DT_ARMreg_pos EQU 16
|
|
DT_ARMreg_mask EQU &F:SHL:DT_ARMreg_pos
|
|
DT_LnotS_pos EQU 20
|
|
DT_LnotS_bit EQU 1:SHL:DT_LnotS_pos
|
|
DT_wb_pos EQU 21
|
|
DT_wb_bit EQU 1:SHL:DT_wb_pos
|
|
DT_pr1_pos EQU 22
|
|
DT_pr1_mask EQU &1:SHL:DT_pr1_pos
|
|
DT_UnotD_pos EQU 23
|
|
DT_UnotD_bit EQU 1:SHL:DT_UnotD_pos
|
|
DT_PreIndex_pos EQU 24
|
|
DT_PreIndex_bit EQU 1:SHL:DT_PreIndex_pos
|
|
|
|
; CPRT-specific instruction fields
|
|
; --------------------------------
|
|
;
|
|
; The following FPCR fields also apply to CPRTs: S2_pos, S2_mask, S2_Ibit,
|
|
; Op3_pos, Op3_mask, RM_pos, RM_mask, Pr2_pos, Pr2_mask, S1_pos, S1_mask,
|
|
; Pr1_pos, Pr1_mask, Op1_pos, Op1_mask. (Note Op2_pos and Op2_mask are not
|
|
; included in this list.)
|
|
|
|
RT_ARMreg_pos EQU 12
|
|
RT_ARMreg_mask EQU &F:SHL:RT_ARMreg_pos
|
|
RT_SnotL_pos EQU 20
|
|
RT_SnotL_bit EQU 1:SHL:RT_SnotL_pos
|
|
|
|
; The following is the full opcode mask for a CPRT, in which the Pr2_mask
|
|
; field is part of an ARM register number rather than of the opcode. It
|
|
; includes the Pr3_mask field, whose only purpose is to tell us that this
|
|
; *is* a CPRT rather than a CPDO
|
|
|
|
OpRT_mask EQU Op1_mask+Op3_mask
|
|
|
|
; The following bit distinguishes CMF(E)s from CNF(E)s.
|
|
|
|
CompNeg_pos EQU 21
|
|
CompNeg_bit EQU 1:SHL:CompNeg_pos
|
|
|
|
; The following bit distinguishes exception-causing comparisons from
|
|
; non-exception causing comparisons.
|
|
|
|
CompExc_pos EQU 22
|
|
CompExc_bit EQU 1:SHL:CompExc_pos
|
|
|
|
; CPDO-specific instruction fields
|
|
; --------------------------------
|
|
;
|
|
; The following FPCR fields also apply to CPDOs: S2_pos, S2_mask, S2_Ibit,
|
|
; Op3_pos, Op3_mask, RM_pos, RM_mask, Pr2_pos, Pr2_mask, Ds_pos, Ds_mask,
|
|
; Op2_pos, Op2_mask, S1_pos, S1_mask, Pr1_pos, Pr1_mask, Op1_pos, Op1_mask.
|
|
|
|
; The bit to indicate that the operation is monadic and not dyadic.
|
|
|
|
DO_monad_pos EQU 15
|
|
DO_monad_bit EQU 1:SHL:DO_monad_pos
|
|
|
|
; The bit to indicate that this is a subtraction (SUF or RSF) rather than an
|
|
; addition (ADF).
|
|
|
|
SubNotAdd_pos EQU 21
|
|
SubNotAdd_bit EQU 1:SHL:SubNotAdd_pos
|
|
|
|
; The bit to indicate that this is a reverse subtraction (RSF) rather than
|
|
; an addition or ordinary subtraction (ADF or SUF).
|
|
|
|
RSF_pos EQU 20
|
|
RSF_bit EQU 1:SHL:RSF_pos
|
|
|
|
; The bit to indicate that this is a reverse division (RDF or FRD) rather
|
|
; than a normal division (DVF or FDV).
|
|
|
|
RevDiv_pos EQU 20
|
|
RevDiv_bit EQU 1:SHL:RevDiv_pos
|
|
|
|
; The bit to indicate that this is a "fast" multiplication or division (FML,
|
|
; FDV or FRD), rather than the normal version (MUF, DVF or RDF).
|
|
|
|
Fast_pos EQU 23
|
|
Fast_bit EQU 1:SHL:Fast_pos
|
|
|
|
; The bit to indicate that a move-type instruction (MVF, MNF or ABS) is an
|
|
; MNF.
|
|
|
|
MNF_pos EQU 20
|
|
MNF_bit EQU 1:SHL:MNF_pos
|
|
|
|
; The bit to indicate that a move-type instruction (MVF, MNF or ABS) is an
|
|
; ABS.
|
|
|
|
ABS_pos EQU 21
|
|
ABS_bit EQU 1:SHL:ABS_pos
|
|
|
|
; The bit to indicate that this is a COS instruction rather than a SIN.
|
|
|
|
COSnotSIN_pos EQU 20
|
|
COSnotSIN_bit EQU 1:SHL:COSnotSIN_pos
|
|
|
|
; The bit to indicate that this is a ACS instruction rather than an ASN.
|
|
|
|
ACSnotASN_pos EQU 22
|
|
ACSnotASN_bit EQU 1:SHL:ACSnotASN_pos
|
|
|
|
; The bit to indicate that this is a LOG instruction rather than an LGN.
|
|
|
|
LOGnotLGN_pos EQU 20
|
|
LOGnotLGN_bit EQU 1:SHL:LOGnotLGN_pos
|
|
|
|
; The bit to indicate that this is a RPW instruction rather than a POW.
|
|
|
|
RPWnotPOW_pos EQU 20
|
|
RPWnotPOW_bit EQU 1:SHL:RPWnotPOW_pos
|
|
|
|
;===========================================================================
|
|
|
|
;
|
|
; Floating point formats.
|
|
;
|
|
; There are four floating point formats: Single, Double, Extended and
|
|
; Internal. Single, Double and Extended are memory formats and
|
|
; Internal is the floating point register format. (The FPE keeps the
|
|
; floating pointer registers in Internal format even through they are
|
|
; actually in memory somewhere.) The FPE uses precisely the same
|
|
; Internal format as the FPA chip in order to allow the FPASC and FPE
|
|
; to share code. STF converts from Internal format to Single, Double
|
|
; or Extended format. LDF converts from Single, Double or Extended
|
|
; format to Internal format.
|
|
;
|
|
; All floating point values in memory must be aligned on 4 byte
|
|
; boundaries.
|
|
;
|
|
; The Single and Double formats are specified by the ANSI/IEEE
|
|
; standard 754-1985. They look like this:
|
|
;
|
|
; The Single format is 32 bits wide:
|
|
;
|
|
; | Sign | Exponent | Fraction |
|
|
;
|
|
; The sign field is 1 bit wide the exponent field is 8 bits wide and
|
|
; the fraction field is 23 bits wide. The exponent field is biased by
|
|
; 127 (i.e. an exponent of 1 is encoded as 0x80). The fraction has an
|
|
; implicit leading 1 unless the number is denormalised (see table
|
|
; below).
|
|
;
|
|
; The following table summarises the Single format:
|
|
; Where: 's' is -1 if the sign bit is set and 1 if the sign bit is clear.
|
|
; 'e' is the value of the exponent field interpreted as unsigned.
|
|
; 'f' is the fraction field interpreted as binary digits
|
|
;
|
|
; Exponent Fraction What it is Value
|
|
; 0 0 signed zero +0 or -0
|
|
; 0 non-zero denorm. number s * (0.f) * (2**(-126))
|
|
; 255 0 infinity s * infinity
|
|
; 255 non-zero NaN
|
|
; otherwise normal number s * (1.f) * (2**(e-127))
|
|
;
|
|
; The Double format is 64 bits wide:
|
|
;
|
|
; address: | Sign | Exponent | Fraction high |
|
|
; address + 4: | Fraction low |
|
|
;
|
|
; The sign field is 1 bit wide the exponent field is 11 bits wide and
|
|
; the fraction field is 52 bits wide (20 bits in Fraction high and 32
|
|
; in Fraction low). The exponent is biased by 1023. The fraction has
|
|
; an implicit leading 1 unless the number is denormalised (see table
|
|
; below).
|
|
;
|
|
; The following table summarises the Double format:
|
|
;
|
|
; Exponent Fraction What it is Value
|
|
; 0 0 signed zero +0 or -0
|
|
; 0 non-zero denorm. number s * (0.f) * (2**(-1022))
|
|
; 2047 0 infinity s * infinity
|
|
; 2047 non-zero NaN
|
|
; otherwise normal number s * (1.f) * (2**(e-1023))
|
|
;
|
|
; Extended format implements the IEEE Double Extended format. People
|
|
; wanting an IEEE Single Extended format should either use Double or
|
|
; Extended. Since the reasons the standard suggests for wanting to
|
|
; have Single Extended as well as Double Extended are upwards
|
|
; compatibility and speed, and the former doesn't really apply in our
|
|
; world, and some Double precision operations are faster than Extended
|
|
; ones (e.g. multiplication), I would actually recommend someone who
|
|
; wanted an IEEE Single Extended format to use Double, not Extended.
|
|
;
|
|
; The Extended format is 96 bits wide:
|
|
;
|
|
; address: | Sign | Reserved | Exponent |
|
|
; address + 4: | Units | Fraction high |
|
|
; address + 8: | Fraction low |
|
|
;
|
|
; The sign field is 1 bit wide, the reserved field is 16 bits wide,
|
|
; the exponent field is 15 bits wide, the units field is 1 bit wide
|
|
; and the fraction is 63 bits wide (31 bits in Fraction high and 32 in
|
|
; Fraction low). The exponent is biased by 16383 = 0x3FFF. The Units
|
|
; bit is used instead of having the fraction have an implicit leading
|
|
; 1. The Reserved bits are ignored when read and always written as 0.
|
|
;
|
|
; The floating point registers are kept in Internal format. This is
|
|
; the same as Extended format except that the first word contains a
|
|
; new field:
|
|
;
|
|
; The Internal format is 96 bits wide:
|
|
;
|
|
; address: | Sign | Uncommon | Reserved | Exponent |
|
|
; address + 4: | Units | Fraction high |
|
|
; address + 8: | Fraction low |
|
|
;
|
|
; The sign field is 1 bit wide, the uncommon field is 1 bit wide, the
|
|
; reserved field is 15 bits wide, the exponent field is 15 bits wide,
|
|
; the units field is 1 bit wide and the fraction is 63 bits wide (31
|
|
; bits in Fraction high and 32 in Fraction low). The exponent is
|
|
; biased by 16383 = 0x3FFF. The Units bit is used instead of having
|
|
; the fraction have an implicit leading 1. The Reserved bits are
|
|
; ignored when read and always written as 0.
|
|
;
|
|
; SFM stores in Internal format. When LFM is loading if the uncommon
|
|
; bit is set the memory is loaded unchanged. If the uncommon bit is
|
|
; clear LFM will load it as an Extended number possibly setting the
|
|
; uncommon bit in the process.Another way of putting this is that LFM
|
|
; ORs the uncommon bit from memory with an uncommon bit calculated
|
|
; from the other fields of the number in memory.
|
|
;
|
|
; Extended numbers are interpreted as Internal numbers with the
|
|
; uncommon bit clear (which it is).
|
|
;
|
|
; The following table summarises the Exteded and Internal formats:
|
|
;
|
|
; Exponent Unit Fraction What it is Value
|
|
; 0 0 0 signed zero +0 or -0
|
|
; 0 0 non-zero denorm. number s * (0.f) * (2**(-16383))
|
|
; 32767 0 0 infinity s * infinity
|
|
; 32767 1 0 *** Not a valid bit pattern (see note 1) ***
|
|
; 32767 x non-zero NaN NaN
|
|
; other 0 anything *** Not a valid bit pattern (see note 2) ***
|
|
; other 1 anything normal number s * (1.f) * (2**(e-16383))
|
|
;
|
|
;
|
|
; Notes: 1. This bit pattern is known as an "anomalous infinity" in these
|
|
; sources and is actually treated as s * infinity.
|
|
; 2. These bit patterns are known as "unnormalised numbers" in these
|
|
; sources, and are actually treated as representing the value
|
|
; s * (0.f) * (2**(e-16383)). While this behaviour is not part of
|
|
; the architectural specification and should not be relied upon by
|
|
; programmers, it is important to the correct treatment of the
|
|
; intermediate result in the URD/NRM instruction pair in this
|
|
; implementation, and so should not be changed.
|
|
;
|
|
; Uncommon Units Exponent Fraction Notes What it is
|
|
; bit bit
|
|
; 0 0 0x0000 0 (a) A zero
|
|
; 0 0 0x0000 non-zero Should not happen
|
|
; 0 0 0x4016 x (b) Result of URD
|
|
; 0 0 0x4033 x (b) Result of URD
|
|
; 0 0 0x403E x (b) Result of URD
|
|
; 0 0 other x Should not happen
|
|
; 0 1 0x7FFF x Should not happen
|
|
; 0 1 other x (a) Normalised number
|
|
; 1 0 0x0000 0 Should not happen
|
|
; 1 0 0x0000 non-zero (a) Extended denorm. number
|
|
; 1 0 0x7FFF 0 (a) Extended infinity
|
|
; 1 0 0x7FFF non-zero (a,d-f) Extended NaN
|
|
; 1 0 other 0 (c) Extended unnormalised zero
|
|
; 1 0 other non-zero (c) Extended unnorm. number
|
|
; 1 1 0x3C00 0 Should not happen
|
|
; 1 1 0x3C00 non-zero (a) Double denormalised number
|
|
; 1 1 0x3F80 0 Should not happen
|
|
; 1 1 0x3F80 non-zero (a) Single denormalised number
|
|
; 1 1 0x407F 0 (a) Single infinity
|
|
; 1 1 0x407F non-zero (a,e) Single NaN
|
|
; 1 1 0x43FF 0 (a) Double infinity
|
|
; 1 1 0x43FF non-zero (a,e) Double NaN
|
|
; 1 1 0x7FFF 0 (c) Anomalous ext. infinity
|
|
; 1 1 0x7FFF non-zero (a,d-f) Extended NaN
|
|
; 1 1 other x Should not happen
|
|
;
|
|
; Notes:
|
|
;
|
|
; (a) These bit patterns occur normally.
|
|
; The original format is kept for NaNs because exceptions are
|
|
; generated for signalling NaNs only when converting to a
|
|
; different format. The original format is kept for denormalised
|
|
; numbers and infinites just because it is convenient.
|
|
;
|
|
; (b) These bit patterns are the intermediate result of URD before NRM.
|
|
; They are treated as unnormalized numbers. URD followed by NRM
|
|
; implements RND, or the IEEE "Round a floating point number to
|
|
; another floating point number whose value is an integer"
|
|
; operation (see section 5.5 "Round Floating-Point Number to
|
|
; Integer Value" on page 11 of the standard). If one of these
|
|
; numbers is saved (SFM) and restored (LFM) the uncommon bit may
|
|
; become set. ("may" rather than "will" because the URD
|
|
; instruction generally doesn't change numbers which are
|
|
; sufficiently large to already have an integer value). The same
|
|
; applies to STFE followed by LDFE (for the benefit of programs
|
|
; which use that pair for register preservation &
|
|
; restoration). This setting of the uncommon bit is OK because the
|
|
; URD results are chosen so that setting the uncommon bit
|
|
; transforms them into extended unnormalised numbers which have
|
|
; the correct values for the results.
|
|
;
|
|
; (c) Bit patterns that technically have no meaning.
|
|
; These can only be generated by abusing LDFE and LFM. See Notes 1
|
|
; & 2 above.
|
|
;
|
|
; (d) These are indeed both "Extended NaN": the units bit is effectively a
|
|
; "don't care" bit for extended NaNs. This is basically just a
|
|
; consequence of extended precision having a units bit, while single and
|
|
; double precision don't: the "anomalous extended infinity" is a similar
|
|
; consequence.
|
|
;
|
|
; (e) The general rules about NaN processing are:
|
|
;
|
|
; * If the top fraction bit is a 1, the NaN is a quiet NaN; if a 0, the
|
|
; NaN is a signalling NaN. (N.B. This is the top fraction bit - i.e.
|
|
; the second bit of the mantissa - rather than the units bit because
|
|
; the units bit does not exist in all formats.)
|
|
;
|
|
; * A format conversion on a NaN will truncate the fraction at the
|
|
; appropriate point for a format narrowing, or extend it with zeros
|
|
; for a format widening. If the original NaN was a signalling NaN, an
|
|
; invalid operation exception is generated. If this exception is
|
|
; untrapped, the result is also "quietened" by having its top fraction
|
|
; bit set. (The net result of this is that the result always ends up
|
|
; having its top fraction bit set and thus being a NaN rather than an
|
|
; infinity, unless the result is generated by a trap handler - in this
|
|
; latter case, the trap handler has the responsibility for producing
|
|
; the "correct" result.)
|
|
;
|
|
; * An operation on NaN operand(s) will generate an invalid operation
|
|
; exception if any operand is a signalling NaN, as mandated by the
|
|
; IEEE standard. If this doesn't happen, or if the exception is
|
|
; untrapped, the result is produced by the following rules:
|
|
;
|
|
; - If the operation is monadic, the result is obtained by
|
|
; format-converting the operand NaN to the destination format of the
|
|
; operation. (For some versions of the code, the invalid operation
|
|
; exception is suppressed if the operation is MVF, MNF, ABS or STF
|
|
; and no change of format occurs; for others, this doesn't happen.
|
|
; See the discussion under "FPESigNaNCopy_Invalid" in the "main.s"
|
|
; source file for more details of this.)
|
|
;
|
|
; - If the operation is dyadic, the result is obtained by
|
|
; format-converting the first operand to the destination format of
|
|
; the operation if the first operand is a NaN, and otherwise by
|
|
; format-converting the second operand similarly. (Note that this
|
|
; rule pays no attention to which NaNs are signalling. In
|
|
; particular, if the first operand is a quiet NaN and the second one
|
|
; a signalling NaN, the second operand will generate the invalid
|
|
; operation exception - but if the exception is untrapped, the first
|
|
; operand will generate the result. This is done to match likely
|
|
; future hardware behaviour.)
|
|
;
|
|
; * If an invalid operation exception occurs for other reasons than a
|
|
; NaN operand, and the exception is untrapped, the resulting quiet NaN
|
|
; has units bit 0, top fraction bit 1, all other fraction bits 0, and
|
|
; sign bit equal to what the operation would normally have produced -
|
|
; e.g. EOR of the operand signs for infinity * 0; ((rounding mode =
|
|
; "to -infinity") ? 1 : 0) for infinity - infinity; etc. (This is
|
|
; again to match likely future hardware behaviour.)
|
|
;
|
|
; (f) The NE bit in the FPSR modifies the rules about extended NaNs when it
|
|
; is 0. Basically, these rules cause extended precision to no longer be
|
|
; a fully supported IEEE format, but are necessary to allow code that
|
|
; uses STFE/LDFE for register preservation and restoration to use
|
|
; signalling NaNs effectively. (I.e. basically code that uses the
|
|
; "/fpe2" APCS option and some other legacy code.)
|
|
;
|
|
; The problem for such code is that if extended precision is treated as
|
|
; a fully supported IEEE precision, a register-preserving STFE normally
|
|
; contains an implicit format conversion and so *must* generate an
|
|
; exception. Having a procedure call generate an exception merely
|
|
; because the calling procedure happens to have a signalling NaN in a
|
|
; register isn't very desirable...
|
|
;
|
|
; To deal with this, NE=0 provides a "legacy code compatibility" option
|
|
; in which an extended precision NaN is regarded as being "really
|
|
; single" or "really double", depending on whether the bottom bit of the
|
|
; extended precision mantissa is 0 or 1 (respectively). Format
|
|
; conversions from single or double precision to extended precision then
|
|
; clear or set this bit appropriately in addition to the operations
|
|
; described above, and never generate an invalid operation exception.
|
|
; Format conversions from a "really single" extended signalling NaN to
|
|
; single precision or from a "really double" extended signalling NaN to
|
|
; double precision are regarded as not involving a change of precision
|
|
; and thus not generating an invalid operation exception; ones from a
|
|
; "really single" extended NaN to double precision or a "really double"
|
|
; extended NaN to single precision still operate as normal.
|
|
;
|
|
; NE=1 provides full IEEE compatibility, in which any conversion of a
|
|
; signalling NaN from one of single, double or extended precision to
|
|
; another will generate an invalid operation exception.
|
|
;
|
|
; Note also that all this only applies to current systems like the
|
|
; FPA+FPASC which don't generate invalid operation exceptions for copies
|
|
; of signalling NaNs without change of format. Possible future hardware
|
|
; systems which generate invalid operation exceptions on any copy of a
|
|
; signalling NaN by an MVF, MNF, ABS or STF instruction will pay no
|
|
; attention to the NE bit and only supply the full IEEE compatibility
|
|
; option.
|
|
|
|
;===========================================================================
|
|
|
|
; Fields in top words of numbers
|
|
; ------------------------------
|
|
|
|
; Single precision fields:
|
|
|
|
SFrc_pos EQU 0
|
|
SFrc_len EQU 23
|
|
SFrc_mask EQU ((1:SHL:SFrc_len) - 1):SHL:SFrc_len
|
|
SExp_pos EQU 23
|
|
SExp_len EQU 8
|
|
SExp_mask EQU ((1:SHL:SExp_len) - 1):SHL:SExp_pos
|
|
|
|
; Double precision fields:
|
|
|
|
DFhi_pos EQU 0
|
|
DFhi_len EQU 20
|
|
DFhi_mask EQU ((1:SHL:DFhi_len) - 1):SHL:DFhi_len
|
|
DExp_pos EQU 20
|
|
DExp_len EQU 11
|
|
DExp_mask EQU ((1:SHL:DExp_len) - 1):SHL:DExp_pos
|
|
|
|
; Extended and internal precision fields:
|
|
|
|
EIExp_pos EQU 0
|
|
EIExp_len EQU 15
|
|
EIExp_mask EQU ((1:SHL:EIExp_len) - 1):SHL:EIExp_pos
|
|
IRsv_pos EQU 15
|
|
IRsv_mask EQU &7FFF:SHL:IRsv_pos
|
|
ERsv_pos EQU 15
|
|
ERsv_mask EQU &FFFF:SHL:ERsv_pos
|
|
Uncommon_pos EQU 30
|
|
Uncommon_bit EQU 1:SHL:Uncommon_pos
|
|
|
|
EIExp_mask_pt1 EQU EIExp_mask:AND:&FF
|
|
EIExp_mask_pt2 EQU EIExp_mask:AND:&FF00
|
|
ASSERT EIExp_mask_pt1:OR:EIExp_mask_pt2 = EIExp_mask
|
|
ASSERT EIExp_mask_pt1:AND:EIExp_mask_pt2 = 0
|
|
|
|
IRsv_mask_pt1 EQU IRsv_mask:AND:&3FC000
|
|
IRsv_mask_pt2 EQU IRsv_mask:AND:&3FC00000
|
|
ASSERT IRsv_mask_pt1:OR:IRsv_mask_pt2 = IRsv_mask
|
|
ASSERT IRsv_mask_pt1:AND:IRsv_mask_pt2 = 0
|
|
|
|
; Shared fields:
|
|
|
|
Sign_pos EQU 31
|
|
Sign_bit EQU 1:SHL:Sign_pos
|
|
|
|
; The following immediate mask will reduce a sign/uncommon/exponent word to
|
|
; just the exponent.
|
|
|
|
ToExp_mask EQU &FFFFFFFF - Sign_bit - Uncommon_bit
|
|
ASSERT EIExp_pos = 0 ;This mask won't do its job otherwise
|
|
|
|
; The minimum and maximum allowed exponents for single, double and extended
|
|
; precision numbers held in internal format.
|
|
|
|
SMin_Exp EQU &3F81
|
|
SMax_Exp EQU &407E
|
|
DMin_Exp EQU &3C01
|
|
DMax_Exp EQU &43FE
|
|
EMin_Exp EQU &0000
|
|
EMax_Exp EQU &7FFE
|
|
|
|
; The normal exponent bias in a single, a double and an extended or internal
|
|
; precision number. In the first two cases, the bias for a denormalised
|
|
; number is one smaller.
|
|
|
|
SExp_bias EQU &7F
|
|
DExp_bias EQU &3FF
|
|
EIExp_bias EQU &3FFF
|
|
|
|
; The special exponents for NaNs and infinities of various precisions.
|
|
|
|
NaNInfExp_Single EQU &407F
|
|
NaNInfExp_Double EQU &43FF
|
|
NaNInfExp_Extended EQU &7FFF
|
|
|
|
; The special exponents for denormalised numbers of various precisions.
|
|
|
|
DenormExp_Single EQU &3F80
|
|
DenormExp_Double EQU &3C00
|
|
DenormExp_Extended EQU &0000
|
|
|
|
; The bias adjustments for entry to overflow and underflow trap handlers.
|
|
|
|
TrapBiasAdjust_Single EQU &C0
|
|
TrapBiasAdjust_Double EQU &600
|
|
TrapBiasAdjust_Extended EQU &6000
|
|
|
|
;===========================================================================
|
|
|
|
; Fields in other words of numbers
|
|
; --------------------------------
|
|
|
|
EIUnits_pos EQU 31
|
|
EIUnits_bit EQU 1:SHL:EIUnits_pos
|
|
EIFracTop_pos EQU 30
|
|
EIFracTop_bit EQU 1:SHL:EIFracTop_pos
|
|
|
|
;===========================================================================
|
|
|
|
; Comparison results
|
|
; ------------------
|
|
|
|
Comp_GT EQU &20000000
|
|
Comp_EQ EQU &60000000
|
|
Comp_LT EQU &80000000
|
|
Comp_Un_Orig EQU &10000000
|
|
Comp_Un_Alt EQU &30000000
|
|
|
|
;===========================================================================
|
|
|
|
; Floating point condition codes
|
|
;
|
|
; Here are the FPE/ARM condition code maps. The FPE has an FPSR bit
|
|
; called AC that determines if the old mapping or new is used:
|
|
;
|
|
; With AC=0:
|
|
;
|
|
; Relation Z C N V
|
|
; ---------------------------
|
|
; EQUAL 1 1 0 0
|
|
; LESS THAN 0 0 1 0
|
|
; GREATER TNAN 0 1 0 0
|
|
; UNORDERED 0 0 0 1
|
|
;
|
|
; Code Nm Flags Meaning Floating point meaning
|
|
; ------------------------------------------------------------------
|
|
; 0000 EQ Z==1 equal equal
|
|
; 0001 NE Z==0 not equal not equal (includes unordered)
|
|
; 0010 HS C==1 higher or same greater or equal
|
|
; 0011 LO C==0 lower than less than or unordered
|
|
; 0100 MI N==1 negative less than
|
|
; 0101 PL N==0 nonnegative greater, equal, or unordered
|
|
; 0110 VS V==1 overflow unordered
|
|
; 0111 VC V==0 not overflow less, greater, or equal
|
|
; 1000 HI C==1 && Z==0 higher than greater than
|
|
; 1001 LS C==0 || Z==1 lower or same less, equal, or unordered
|
|
; 1010 GE N==V greater or equal greater or equal (same as 0010)
|
|
; 1011 LT N!=V less than less than or unordered (same as 0011)
|
|
; 1100 GT Z==0 && N==V greater than greater than (same as 1000)
|
|
; 1101 LE Z==1 || N!=V less or equal less, equal, or unordered (same as 1001)
|
|
; 1110 AL don't care always always
|
|
; 1111 don't care never never
|
|
;
|
|
; With AC=1:
|
|
;
|
|
; Relation Z C N V
|
|
; --- ------------------------
|
|
; EQUAL 1 1 0 0
|
|
; LESS THAN 0 0 1 0
|
|
; GREATER TNAN 0 1 0 0
|
|
; UNORDERED 0 1 0 1
|
|
;
|
|
; The only difference is the UNORDERED now sets both C and V.
|
|
; Now: C <==> greater than or equal or unordered
|
|
;
|
|
; This changes the condition code table to:
|
|
;
|
|
; Code Nm Flags Meaning Floating point meaning
|
|
; --- ---------------------------------------------------------------
|
|
; 0000 EQ Z==1 equal equal
|
|
; 0001 NE Z==0 not equal not equal (includes unordered)
|
|
; 0010 HS C==1 higher or same greater, equal, or unordered
|
|
; 0011 LO C==0 lower than less than
|
|
; 0100 MI N==1 negative less than
|
|
; 0101 PL N==0 nonnegative greater, equal, or unordered
|
|
; 0110 VS V==1 overflow unordered
|
|
; 0111 VC V==0 not overflow less, greater, or equal
|
|
; 1000 HI C==1 && Z==0 higher than greater or unordered
|
|
; 1001 LS C==0 || Z==1 lower or same less or equal
|
|
; 1010 GE N==V greater or equal greater or equal
|
|
; 1011 LT N!=V less than less than or unordered
|
|
; 1100 GT Z==0 && N==V greater than greater than
|
|
; 1101 LE Z==1 || N!=V less or equal less, equal, or unordered
|
|
; 1110 AL don't care always always
|
|
; 1111 don't care never never
|
|
;
|
|
; Only the entries for 0010, 0011, 1000 and 1001 have changed.
|
|
;
|
|
; Now all floating point conditionals that can be expressed in C are
|
|
; available in one test.
|
|
;
|
|
; The ARM C compiler does not yet do the right thing for floating
|
|
; point comparisons.
|
|
|
|
;===========================================================================
|
|
|
|
; Invalid operation reason codes
|
|
; ------------------------------
|
|
; These were once used to construct quiet NaNs which would give some
|
|
; indication what sort of operation created the NaN. They are now only used
|
|
; for some internal purposes, having been removed because it is very
|
|
; unlikely that any future hardware which handles NaNs will mimic this
|
|
; behaviour.
|
|
; InvReas_InitNaN is not an invalid operation reason code; however, like
|
|
; all the others, it is related to a NaN that the system can generate. It is
|
|
; therefore placed in the same set of numbers.
|
|
; InvReas_MsvOverflow and InvReas_MsvUnderflow are similar: NaNs
|
|
; (originally constructed from them) are used on entry to overflow and
|
|
; underflow trap handlers respectively to indicate that the result is so
|
|
; massively out of range that the IEEE-specified exponent bias adjustment
|
|
; (&C0 for single, &600 for double and &6000 for extended) is not enough to
|
|
; bring it in range.
|
|
|
|
InvReas_SigNaN EQU 0 ;An operand is a signalling NaN
|
|
InvReas_InitNaN EQU 1 ;(Used to generate initial NaNs)
|
|
InvReas_MsvOverflow EQU 2 ;(Used for massive overflow)
|
|
InvReas_MsvUnderflow EQU 3 ;(Used for massive underflow)
|
|
InvReas_MagSubInf EQU 4 ;Magnitude subtraction of infinities
|
|
InvReas_InfTimes0 EQU 5 ;Infinity times zero
|
|
InvReas_0TimesInf EQU 6 ;Zero times infinity
|
|
InvReas_0Div0 EQU 7 ;Zero divided by zero
|
|
InvReas_InfDivInf EQU 8 ;Infinity divided by infinity
|
|
InvReas_InfRemX EQU 9 ;RMF with 1st operand infinite
|
|
InvReas_XRem0 EQU 10 ;RMF of non-infinite number by zero
|
|
InvReas_SqrtNeg EQU 11 ;Square root of a negative number
|
|
InvReas_FixQNaN EQU 12 ;FIX applied to a quiet NaN
|
|
InvReas_FixInf EQU 13 ;FIX applied to an infinity
|
|
InvReas_FixRange EQU 14 ;FIX on an out-of-range number
|
|
InvReas_CompQNaN EQU 15 ;CMFE/CNFE on a quiet NaN
|
|
InvReas_SinCosRange EQU 16 ;SIN/COS on too big an argument
|
|
InvReas_SinCosInf EQU 17 ;SIN/COS on an infinity
|
|
InvReas_TanRange EQU 18 ;TAN on too big an argument
|
|
InvReas_TanInf EQU 19 ;TAN on an infinity
|
|
InvReas_AsnAcsRange EQU 20 ;ASN/ACS on too big an argument
|
|
InvReas_AsnAcsInf EQU 21 ;ASN/ACS on an infinity
|
|
InvReas_PolZeroZero EQU 22 ;POL on two zeros
|
|
InvReas_PolInfInf EQU 23 ;POL on two infinities
|
|
InvReas_LgnLogNeg EQU 24 ;LGN/LOG of a negative argument
|
|
InvReas_NegPowX EQU 25 ;POW/RPW to do (negative)^X
|
|
InvReas_0PowNonpos EQU 26 ;POW/RPW to do (zero)^(non-positive)
|
|
InvReas_BadInfPow EQU 27 ;POW/RPW to do 1^(+/-infinity) or
|
|
; (+infinity)^0
|
|
|
|
;===========================================================================
|
|
|
|
END
|