singrdk/base/Kernel/Native/arm/Crt/nans.asm

215 lines
7.0 KiB
NASM
Raw Normal View History

2008-11-17 18:29:00 -05:00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; 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