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

386 lines
10 KiB
NASM
Raw Permalink 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.
;;;
; format_e.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
AREA |.text|, CODE, READONLY
SNaNInf EQU NaNInfExp_Single - EIExp_bias + SExp_bias
DNaNInf EQU NaNInfExp_Double - EIExp_bias + DExp_bias
;==============================================================================
[ :DEF: e2e_s
EXPORT _e2e
; Convert a five-word internal value to a three word value
;
; Enters with the partly-constructed internal precision value in OP1sue,
; OP1mhi and OP1mlo, the exponent in RNDexp and the guard/sticky bits in
; Rarith. No truncation is needed, only rounding.
[ :DEF: thumb
CODE32
]
_e2e
TST OP1sue,#Error_bit+Uncommon_bit
BNE _e2e_error_or_uncommon
MOVS Rtmp,Rarith,LSL #1 ;C<-round, Z<-"tied (or exact) case"
BEQ _e2e_exact_or_tied
_e2e_round_by_C
ADDCSS OP1mlo,OP1mlo,#1 ;Increment low word
ADDCSS OP1mhi,OP1mhi,#1 ;If carry out, increment high word
MOVCS OP1mhi,#EIUnits_bit ;If mantissa overflow, adjust
ADCS RNDexp,RNDexp,#0 ; mantissa and exponent
BMI _e2e_underflow
;Check for overflow in the usual way
ADD tmp,RNDexp,#1
BIC tmp,tmp,#Uncommon_bit
CMP tmp,#1<<EIExp_len
MOVGT a4,#OVF_bits
_e2e_return_value
AND OP1sue,OP1sue,#Sign_bit
ORR OP1sue,RNDexp,OP1sue
MOV pc, lr ;Only *ever* called from ARM
;So no INTERWORK hacks needed!
;In the event of an error just return
_e2e_error_or_uncommon
MOV a4,OP1sue
MOV pc,lr
_e2e_exact_or_tied
MOVCSS Rtmp,OP1mlo,LSR #1 ;If "tied" C<-low mantissa bit
B _e2e_round_by_C ;(If exact, C remains 0)
_e2e_underflow
;We have come out with a negative exponent. If the units bit is unset this
;may be recoverable.
TST OP1mhi,#EIUnits_bit
BNE _e2e_underflow_recover
_e2e_massive_underflow
;It is not - i.e. this is a normalised number. We return a signed zero.
MOV OP1mhi,#0
MOV OP1mlo,#0
AND OP1sue,OP1sue,#Sign_bit
MOV a4, #0
MOV pc,lr
_e2e_underflow_recover
;We may be able to shift the mantissa enough to bring the exponent back
;into range.
MACRO
I2ECheckBits $n
MOVS tmp,OP1mhi,LSR #32-$n
MOVEQ tmp,OP1mlo,LSR #32-$n
ORREQ OP1mhi,tmp,OP1mhi,LSL #$n
ADDEQ RNDexp,RNDexp,#$n
MEND
I2ECheckBits 16
I2ECheckBits 8
I2ECheckBits 4
I2ECheckBits 2
I2ECheckBits 1
MOVS RNDexp,RNDexp
BMI _e2e_massive_underflow
BPL _e2e_return_value
]
;===========================================================================
[ :DEF: eflt_s :LOR: :DEF: efltu_s
;Macro for normalisation
MACRO
ExtendNormalise
;The sign bit is stored in OP1sue.
ORR OP1sue,OP1sue,#((EIExp_bias+31):AND:&ff00)<<EIExp_pos
ORR OP1sue,OP1sue,#((EIExp_bias+31):AND:&00ff)<<EIExp_pos
;Now that we have the basis for the exponent, we do the rounding
MOVS tmp,OP1mhi,LSR #16
MOVEQ OP1mhi,OP1mhi,LSL #16
SUBEQ OP1sue,OP1sue,#16<<EIExp_pos
MOVS tmp,OP1mhi,LSR #24
MOVEQ OP1mhi,OP1mhi,LSL #8
SUBEQ OP1sue,OP1sue,#8<<EIExp_pos
MOVS tmp,OP1mhi,LSR #28
MOVEQ OP1mhi,OP1mhi,LSL #4
SUBEQ OP1sue,OP1sue,#4<<EIExp_pos
MOVS tmp,OP1mhi,LSR #30
MOVEQ OP1mhi,OP1mhi,LSL #2
SUBEQ OP1sue,OP1sue,#2<<EIExp_pos
MOVS tmp,OP1mhi,LSR #31
MOVEQ OP1mhi,OP1mhi,LSL #1
SUBEQ OP1sue,OP1sue,#1<<EIExp_pos
;We want to keep the units bit, which now must be in the top bit of a1.
MEND
]
;..............................................................................
[ :DEF: eflt_s
EXPORT _eflt
_eflt EnterWithLR
MOVS OP1mhi,a1 ;Check for zero and -ve; put in place
AND OP1sue,a1,#Sign_bit ;Extract sign
RSBMI OP1mhi,OP1mhi,#0 ;Undo two's complement
ASSERT OP1sue = a1
MOV OP1mlo,#0 ;This will be done regardless
;MOVEQ OP1sue,#0 ;Return a zero as appropiate
;MOVEQ OP1mhi,#0 ;Already done this move
ReturnToLR EQ
ExtendNormalise
ReturnToLR
]
;------------------------------------------------------------------------------
[ :DEF: efltu_s
EXPORT _efltu
_efltu EnterWithLR
MOVS OP1mhi,a1 ;Check for zero and -ve; put in place
MOV OP1mlo,#0 ;This will be done regardless
MOV OP1sue,#0 ;Return a zero as appropiate
;MOVEQ OP1mhi,#0 ;Already done this move
ReturnToLR EQ
ExtendNormalise
ReturnToLR
]
;---------------------------------------------------------------------------
[ :DEF: norm_op1_s
EXPORT __fp_norm_op1
; This routine is called to normalised the first operand on entry to one
; of the veneered functions.
; Takes OP1 is r0,r1,r2 and corrupts tmp (r11).
;Called from ARM code
[ :DEF: thumb
CODE32
]
__fp_norm_op1
TST OP1mhi, #EIUnits_bit
MOVEQ pc, lr ;Only ever called from ARM - so
;no INTERWORK hacks needed
STMFD r13!,{RNDexp,lr}
BICS OP1mhi,OP1mhi,#Sign_bit
BEQ __fp_denorm_low
; The top set bit in the high word, so find out how much to denormalise
; by
MOVS RNDexp,OP1mhi,LSR #16
MOVEQ OP1mhi,OP1mhi,LSL #16
MOVEQ tmp,#16
MOVNE tmp,#0
MOVS RNDexp,OP1mhi,LSR #24
MOVEQ OP1mhi,OP1mhi,LSL #8
ADDEQ tmp,tmp,#8
MOVS RNDexp,OP1mhi,LSR #28
MOVEQ OP1mhi,OP1mhi,LSL #4
ADDEQ tmp,tmp,#4
MOVS RNDexp,OP1mhi,LSR #30
MOVEQ OP1mhi,OP1mhi,LSL #2
ADDEQ tmp,tmp,#2
MOVS RNDexp,OP1mhi,LSR #31
MOVEQ OP1mhi,OP1mhi,LSL #1
ADDEQ tmp,tmp,#1
; tmp now contains the amount to shift by.
RSB RNDexp,tmp,#32
ORR OP1mhi,OP1mhi,OP1mlo,LSR RNDexp
MOV OP1mlo,OP1mlo,LSL tmp
SUB OP1sue,OP1sue,tmp
ADD OP1sue,OP1sue,#1
LDMFD r13!,{RNDexp,pc}
__fp_denorm_low
; The top bit to be set is in OP1mlo
MOVS RNDexp,OP1mlo,LSR #16
MOVEQ OP1mlo,OP1mlo,LSL #16
MOVEQ tmp,#16
MOVNE tmp,#0
MOVS RNDexp,OP1mlo,LSR #24
MOVEQ OP1mlo,OP1mlo,LSL #8
ADDEQ tmp,tmp,#8
MOVS RNDexp,OP1mlo,LSR #28
MOVEQ OP1mlo,OP1mlo,LSL #4
ADDEQ tmp,tmp,#4
MOVS RNDexp,OP1mlo,LSR #30
MOVEQ OP1mlo,OP1mlo,LSL #2
ADDEQ tmp,tmp,#2
MOVS RNDexp,OP1mlo,LSR #31
MOVEQ OP1mlo,OP1mlo,LSL #1
ADDEQ tmp,tmp,#1
; tmp now contains the amount to shift by.
MOV OP1mhi,OP1mlo
MOV OP1mlo,#0
SUB OP1sue,OP1sue,#31
SUB OP1sue,OP1sue,tmp
LDMFD r13!,{RNDexp,pc}
]
;---------------------------------------------------------------------------
[ :DEF: norm_op2_s
EXPORT __fp_norm_op2
; This routine is called to normalised the second operand on entry to one
; of the veneered functions.
; takes OP2 in r4,r5,r6 and corrupts tmp (r11)
; Called from ARM code
[ :DEF: thumb
CODE32
]
__fp_norm_op2
TST OP2mhi, #EIUnits_bit
MOVEQ pc, lr
STMFD r13!,{OP1sue,lr}
BICS OP2mhi,OP2mhi,#Sign_bit
BEQ __fp_denorm_low
; The top set bit in the high word, so find out how much to denormalise
; by
MOVS OP1sue,OP2mhi,LSR #16
MOVEQ OP2mhi,OP2mhi,LSL #16
MOVEQ tmp,#16
MOVNE tmp,#0
MOVS OP1sue,OP2mhi,LSR #24
MOVEQ OP2mhi,OP2mhi,LSL #8
ADDEQ tmp,tmp,#8
MOVS OP1sue,OP2mhi,LSR #28
MOVEQ OP2mhi,OP2mhi,LSL #4
ADDEQ tmp,tmp,#4
MOVS OP1sue,OP2mhi,LSR #30
MOVEQ OP2mhi,OP2mhi,LSL #2
ADDEQ tmp,tmp,#2
MOVS OP1sue,OP2mhi,LSR #31
MOVEQ OP2mhi,OP2mhi,LSL #1
ADDEQ tmp,tmp,#1
; tmp now contains the amount to shift by.
RSB OP1sue,tmp,#32
ORR OP2mhi,OP2mhi,OP2mlo,LSR OP1sue
MOV OP2mlo,OP2mlo,LSL tmp
SUB OP2sue,OP2sue,tmp
ADD OP2sue,OP2sue,#1
LDMFD r13!,{OP1sue,pc}
__fp_denorm_low
; The top bit to be set is in OP2mlo
MOVS OP1sue,OP2mlo,LSR #16
MOVEQ OP2mlo,OP2mlo,LSL #16
MOVEQ tmp,#16
MOVNE tmp,#0
MOVS OP1sue,OP2mlo,LSR #24
MOVEQ OP2mlo,OP2mlo,LSL #8
ADDEQ tmp,tmp,#8
MOVS OP1sue,OP2mlo,LSR #28
MOVEQ OP2mlo,OP2mlo,LSL #4
ADDEQ tmp,tmp,#4
MOVS OP1sue,OP2mlo,LSR #30
MOVEQ OP2mlo,OP2mlo,LSL #2
ADDEQ tmp,tmp,#2
MOVS OP1sue,OP2mlo,LSR #31
MOVEQ OP2mlo,OP2mlo,LSL #1
ADDEQ tmp,tmp,#1
; tmp now contains the amount to shift by.
MOV OP2mhi,OP2mlo
MOV OP2mlo,#0
SUB OP2sue,OP2sue,#31
SUB OP2sue,OP2sue,tmp
LDMFD r13!,{OP1sue,pc}
]
;---------------------------------------------------------------------------
END