215 lines
7.0 KiB
NASM
215 lines
7.0 KiB
NASM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;
|
|
;;; Microsoft Research Singularity
|
|
;;;
|
|
;;; Copyright (c) Microsoft Corporation. All rights reserved.
|
|
;;;
|
|
;;; This file contains ARM-specific assembly code.
|
|
;;;
|
|
|
|
; nans.s
|
|
;
|
|
; Copyright (C) Advanced RISC Machines Limited, 1994. All rights reserved.
|
|
;
|
|
; RCS Revision: 1
|
|
; Checkin Date: 2007/06/29 02:59:16
|
|
; Revising Author
|
|
|
|
GET fpe.asm
|
|
|
|
[ :DEF: thumb
|
|
CODE32
|
|
]
|
|
|
|
AREA |.text|, CODE, READONLY
|
|
|
|
EXPORT __fp_convert_NaNs
|
|
EXPORT __fp_convert_NaN1
|
|
EXPORT __fp_convert_NaN_1Of2
|
|
EXPORT __fp_convert_NaN_2Of2
|
|
|
|
__fp_convert_NaNs
|
|
|
|
; First check for cases where the first operand determines which routine to
|
|
; use - i.e. if it is a signalling NaN or not a NaN at all.
|
|
|
|
ORRS Rtmp,OP1mlo,OP1mhi,LSL #1 ;First operand a NaN?
|
|
BEQ __fp_convert_NaN_2Of2 ;If not, use ConvertNaN2Of2
|
|
TST OP1mhi,#EIFracTop_bit ;First operand a sign.NaN?
|
|
BEQ __fp_convert_NaN_1Of2 ;If so, use ConvertNaN1Of2
|
|
|
|
; First operand is a quiet NaN. If second is a signalling NaN, we use
|
|
; ConvertNaN2Of2; otherwise, we use ConvertNaN1Of2.
|
|
|
|
ORRS Rtmp,OP2mlo,OP2mhi,LSL #1 ;Second operand a NaN?
|
|
BEQ __fp_convert_NaN_1Of2 ;If not, use ConvertNaN1Of2
|
|
TST OP2mhi,#EIFracTop_bit ;Second operand a sign.NaN?
|
|
BNE __fp_convert_NaN_1Of2 ;If not, use ConvertNaN1Of2
|
|
|
|
__fp_convert_NaN_2Of2
|
|
|
|
CDebug3 4,"ConvertNaN2Of2: NaN =",OP2sue,OP2mhi,OP2mlo
|
|
|
|
; We must check for an invalid operation trap *before* we start using shared
|
|
; code, because the operands must be left unchanged for the trap handler.
|
|
|
|
;; There is always a trap handler, and it doesn't care about the operands
|
|
|
|
TST OP2mhi,#EIFracTop_bit ;Signalling NaN?
|
|
BEQ ReturnIVO
|
|
|
|
; Now we can transfer the NaN to OP1sue/mhi/mlo and use shared code.
|
|
|
|
MOV OP1sue,OP2sue
|
|
MOV OP1mhi,OP2mhi
|
|
MOV OP1mlo,OP2mlo
|
|
B ConvertNaN1_NoTrap
|
|
|
|
__fp_convert_NaN1
|
|
|
|
; We must check for an invalid operation trap *before* we start using shared
|
|
; code, because the operands must be left unchanged for the trap handler.
|
|
|
|
CDebug3 4,"ConvertNaN1: NaN =",OP1sue,OP1mhi,OP1mlo
|
|
|
|
TST OP1mhi,#EIFracTop_bit ;Signalling NaN?
|
|
BEQ ReturnIVO
|
|
B ConvertNaN1_NoTrap ; becomes 0 = InvReas_SigNaN
|
|
|
|
__fp_convert_NaN_1Of2
|
|
|
|
CDebug3 4,"ConvertNaN1Of2: NaN =",OP1sue,OP1mhi,OP1mlo
|
|
|
|
; We must check for an invalid operation trap *before* we start using shared
|
|
; code, because the operands must be left unchanged for the trap handler.
|
|
|
|
TST OP1mhi,#EIFracTop_bit ;Signalling NaN?
|
|
BEQ ReturnIVO
|
|
|
|
ConvertNaN1_NoTrap
|
|
|
|
; Now we need to perform the actual NaN conversion. The rules here are:
|
|
;
|
|
; * The exponent field must be converted to the appropriate value for the
|
|
; destination precision;
|
|
;
|
|
; * Fraction bits that are not used by the destination precision must be
|
|
; cleared;
|
|
;
|
|
; * If result precision is single or double, units bit is forced to 1;
|
|
;
|
|
; * If the NE bit is 0 and we're converting to extended precision, the
|
|
; bottom bit of the fraction must be set or cleared to indicate whether
|
|
; the NaN is "really" single or double precision respectively.
|
|
|
|
; Split according to result precision.
|
|
|
|
TST Rins,#Single_mask
|
|
BNE ConvertNaN1_ToSingle
|
|
TST Rins,#Double_mask
|
|
BNE ConvertNaN1_ToDouble
|
|
|
|
;------------------------------------------------------------------------------
|
|
|
|
ConvertNaN1_ToExtended
|
|
|
|
; If NE=0, we just need to modify the exponent. Otherwise, we need to
|
|
; establish the effective precision and set or clear the bottom bit of the
|
|
; fraction appropriately.
|
|
|
|
TST Rins,#NE_bit
|
|
BNE ConvertNaN1_ToExtended_MantissaDone
|
|
AND Rtmp,OP1sue,#ToExp_mask ;Isolate exponent field
|
|
MOV Rtmp2,#NaNInfExp_Double:AND:&FF
|
|
ORR Rtmp2,Rtmp2,#NaNInfExp_Double:AND:&FF00
|
|
ASSERT NaNInfExp_Double <= &FFFF
|
|
CMP Rtmp,Rtmp2 ;LO/EQ/HI if single/double/extended
|
|
ASSERT NaNInfExp_Single < NaNInfExp_Double
|
|
ASSERT NaNInfExp_Double < NaNInfExp_Extended
|
|
BICLO OP1mlo,OP1mlo,#1 ;Bottom bit cleared for single NaN
|
|
ORREQ OP1mlo,OP1mlo,#1 ;Bottom bit set for double NaN
|
|
;Bottom bit unchanged for extended NaN
|
|
|
|
ConvertNaN1_ToExtended_MantissaDone
|
|
|
|
; Change exponent and return.
|
|
|
|
AND OP1sue,OP1sue,#Sign_bit+Uncommon_bit
|
|
ORR OP1sue,OP1sue,#NaNInfExp_Extended:AND:&FF
|
|
ORR OP1sue,OP1sue,#NaNInfExp_Extended:AND:&FF00
|
|
ASSERT NaNInfExp_Extended <= &FFFF
|
|
|
|
TEQ OP1sue,OP1sue ;Force EQ condition
|
|
IF Interworking :LOR: Thumbing
|
|
BX LR
|
|
ELSE
|
|
MOV PC,LR
|
|
ENDIF
|
|
|
|
;------------------------------------------------------------------------------
|
|
|
|
ConvertNaN1_ToDouble
|
|
|
|
; Change exponent.
|
|
|
|
AND OP1sue,OP1sue,#Sign_bit+Uncommon_bit
|
|
ORR OP1sue,OP1sue,#NaNInfExp_Double:AND:&FF
|
|
ORR OP1sue,OP1sue,#NaNInfExp_Double:AND:&FF00
|
|
ASSERT NaNInfExp_Double <= &FFFF
|
|
|
|
; Clear appropriate fraction bits and set the units bit. Note that we know
|
|
; this won't change a NaN into an infinity unless someone is misusing
|
|
; extended precision with NE=0.
|
|
|
|
MOV OP1mlo,OP1mlo,LSR #11
|
|
MOV OP1mlo,OP1mlo,LSL #11
|
|
ORR OP1mhi,OP1mhi,#EIUnits_bit
|
|
|
|
TEQ OP1sue,OP1sue ;Force EQ condition
|
|
IF Interworking :LOR: Thumbing
|
|
BX LR
|
|
ELSE
|
|
MOV PC,LR
|
|
ENDIF
|
|
|
|
;------------------------------------------------------------------------------
|
|
|
|
ConvertNaN1_ToSingle
|
|
|
|
; Change exponent.
|
|
|
|
AND OP1sue,OP1sue,#Sign_bit+Uncommon_bit
|
|
ORR OP1sue,OP1sue,#NaNInfExp_Single:AND:&FF
|
|
ORR OP1sue,OP1sue,#NaNInfExp_Single:AND:&FF00
|
|
ASSERT NaNInfExp_Single <= &FFFF
|
|
|
|
; Clear appropriate fraction bits and set the units bit. Note that we know
|
|
; this won't change a NaN into an infinity unless someone is misusing
|
|
; extended precision with the NE bit equal to 0.
|
|
|
|
MOV OP1mlo,#0
|
|
BIC OP1mhi,OP1mhi,#&FF
|
|
ORR OP1mhi,OP1mhi,#EIUnits_bit
|
|
IF Interworking :LOR: Thumbing
|
|
BX LR
|
|
ELSE
|
|
MOV PC,LR ;Note we still have EQ from above
|
|
ENDIF
|
|
|
|
;==============================================================================
|
|
|
|
ReturnIVO
|
|
|
|
; Return to the veneer with an IVO exception signalled.
|
|
|
|
ORR OP1sue,OP1sue,#IVO_bits
|
|
IF Interworking :LOR: Thumbing
|
|
BX lr
|
|
ELSE
|
|
MOV pc, lr
|
|
ENDIF
|
|
|
|
;==============================================================================
|
|
|
|
END
|