838 lines
23 KiB
NASM
838 lines
23 KiB
NASM
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;;;
|
||
|
;;; Microsoft Research Singularity
|
||
|
;;;
|
||
|
;;; Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
;;;
|
||
|
;;; This file contains ARM-specific assembly code.
|
||
|
;;;
|
||
|
|
||
|
; format_f.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
|
||
|
GET kxarm.inc
|
||
|
|
||
|
CodeArea |FPL$$Format|
|
||
|
|
||
|
IMPORT __fp_norm_op1
|
||
|
IMPORT __fp_nonveneer_error
|
||
|
|
||
|
SNaNInf EQU NaNInfExp_Single - EIExp_bias + SExp_bias
|
||
|
SExp_max * 255
|
||
|
|
||
|
exp RN 3
|
||
|
|
||
|
;==============================================================================
|
||
|
|
||
|
[ :DEF: f2e_s
|
||
|
|
||
|
[ :DEF: thumb
|
||
|
CODE32
|
||
|
]
|
||
|
|
||
|
EXPORT _f2e ; Not needed, but is an example
|
||
|
|
||
|
_f2e EnterWithLR
|
||
|
MOVS tmp,fOP,LSL #1 ;C:=sign; Z:=exp & frac.top zero
|
||
|
MOV OP1mhi,tmp,LSL #7 ;Frac.top in bits 30:11 of mhi
|
||
|
MOV fOP,tmp,LSR #20 ;Exponent in bits 11:1
|
||
|
ADDNE fOP,fOP,#(EIExp_bias - SExp_bias):SHL:1
|
||
|
MOV OP1sue,fOP,RRX ;Recombine sign and exponent
|
||
|
ORRNE OP1mhi,OP1mhi,#EIUnits_bit
|
||
|
MOV OP1mlo,#0
|
||
|
|
||
|
; Single precision exponent<<1+SExp_pos is in tmp.
|
||
|
; If 0 then this is a denormalised number.
|
||
|
; If 1fe then this is an uncommon number.
|
||
|
MOVS tmp,tmp,LSR #1+SExp_pos
|
||
|
ADDEQ lr,pc,#8 ;Skip two instructions past normalise call
|
||
|
BEQ __fp_norm_op1
|
||
|
TEQ tmp,#&ff
|
||
|
ORREQ OP1sue,OP1sue,#Uncommon_bit
|
||
|
ReturnToLR
|
||
|
|
||
|
]
|
||
|
|
||
|
;---------------------------------------------------------------------------
|
||
|
|
||
|
[ :DEF: e2f_s
|
||
|
|
||
|
; Called from ARM code (no INTERWORK hacks needed).
|
||
|
|
||
|
[ :DEF: thumb
|
||
|
CODE32
|
||
|
]
|
||
|
|
||
|
EXPORT __fp_e2f
|
||
|
|
||
|
__fp_e2f
|
||
|
|
||
|
;Passed in the result of an operation. That is the uncommon/sign are in
|
||
|
;OP1sue, the exponent in RNDexp, the fraction in OP1mlo/OP1mhi. Return with
|
||
|
;a result in dOPh/dOPl and possibly some error flags in a4
|
||
|
|
||
|
ASSERT Uncommon_bit = 1:SHL:(31-1)
|
||
|
ASSERT EIUnits_bit = 1:SHL:31
|
||
|
BICS tmp, OP1mhi, OP1sue, LSL #1
|
||
|
BPL _e2f_SpecialCase
|
||
|
|
||
|
SUBS RNDexp, RNDexp, #(EIExp_bias-SExp_bias)
|
||
|
BMI _e2f_ExpUnderflow
|
||
|
|
||
|
ASSERT tmp <> RNDexp
|
||
|
ADDNE tmp, RNDexp, #1
|
||
|
CMPNE tmp, #SNaNInf+1
|
||
|
BGE _e2f_ExpOverflow
|
||
|
|
||
|
MOVS tmp, OP1mhi, LSR #32-SFrc_len-1
|
||
|
;If rounding is needed then a one will have dropped out.
|
||
|
BCS _e2f_NeedsRounding
|
||
|
|
||
|
; Simple case - just merge in the exponent and sign
|
||
|
|
||
|
BIC tmp, tmp, #1<<SFrc_len ; clear out the J-bit
|
||
|
ORR fOP, OP1sue, RNDexp, LSL #SExp_pos
|
||
|
ORR fOP, fOP, tmp
|
||
|
MOV a4, #0
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BX lr
|
||
|
ELSE
|
||
|
MOV pc, lr
|
||
|
ENDIF
|
||
|
|
||
|
;...........................................................................
|
||
|
|
||
|
_e2f_SpecialCase
|
||
|
|
||
|
TST OP1sue, #Uncommon_bit
|
||
|
BNE _e2f_Uncommon
|
||
|
|
||
|
_e2f_UnitsBit
|
||
|
|
||
|
;Sign is in OP1sue's top bit. The units bit of OP1mhi is clear indicating a
|
||
|
;zero value (since the denorm case is handled by the uncommon bit).
|
||
|
|
||
|
AND dOPh, OP1sue, #Sign_bit
|
||
|
MOV a4, #0
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BX lr
|
||
|
ELSE
|
||
|
MOV pc, lr
|
||
|
ENDIF
|
||
|
|
||
|
;...........................................................................
|
||
|
|
||
|
_e2f_ExpOverflow
|
||
|
|
||
|
;Sign is in OP1sue's sign bit. May still need rounding. The exponent (RNDexp)
|
||
|
;is out of range for a double precision number, and wasn't signalled as a NaN.
|
||
|
|
||
|
;The exponent has been re-biased.
|
||
|
|
||
|
;Might just be the "just underflowing case" (because of a quirk above). In
|
||
|
;that case RNDexp = 0
|
||
|
|
||
|
TEQ RNDexp, #0
|
||
|
MOVNE a4, #OVF_bits
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BXNE lr
|
||
|
ELSE
|
||
|
MOVNE pc, lr
|
||
|
ENDIF
|
||
|
|
||
|
;...........................................................................
|
||
|
|
||
|
_e2f_ExpUnderflow
|
||
|
|
||
|
|
||
|
;Underflow. If the value can be represented as a denorm in the target
|
||
|
;precision, then it should be. For this to be the case the exponent needs
|
||
|
;to lie in range. Otherwise the result is a suitably
|
||
|
;signed zero. (A zero is, however, a denorm with zero mantissa.)
|
||
|
|
||
|
;The exponent (RNDexp) has been rebiased (by (EIExp_bias-SExp_bias))
|
||
|
|
||
|
ADDS RNDexp, RNDexp, #SFrc_len
|
||
|
|
||
|
;If the result is zero then we round according to the top bit of the
|
||
|
;fraction. Branch out of line to do this.
|
||
|
|
||
|
BEQ _e2f_ExpJustUnderflow
|
||
|
|
||
|
;If this result is negative, nothing can be done, so return a signed zero.
|
||
|
|
||
|
ANDMI dOPh, OP1sue, #Sign_bit
|
||
|
MOVMI dOPl, #0
|
||
|
MOVMI a4, #0
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BXMI lr
|
||
|
ELSE
|
||
|
MOVMI pc, lr
|
||
|
ENDIF
|
||
|
|
||
|
;We now have in OP1mhi 1MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||
|
;and in OP1mlo MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||
|
;These need to be converted into a denormalised number. We want the N
|
||
|
;left most bits (N<=23) from this 64-bit value. So we are throwing
|
||
|
;away all the bits from the low word, and some from the high word.
|
||
|
;RNDexp contains the value ([1..23])
|
||
|
|
||
|
MOVS tmp, OP1mhi, LSL RNDexp
|
||
|
BMI _e2f_UnderflowNeedsRounding
|
||
|
|
||
|
RSB tmp, RNDexp, #32
|
||
|
ORR fOP, OP1sue, OP1mhi, LSR tmp
|
||
|
MOV a4, #0
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BX lr
|
||
|
ELSE
|
||
|
MOV pc, lr
|
||
|
ENDIF
|
||
|
|
||
|
_e2f_UnderflowNeedsRounding
|
||
|
|
||
|
;tmp contains those bits out of the high word that determine rounding.
|
||
|
;We add in the bits from the low word, and the sticky bits.
|
||
|
|
||
|
ORR tmp, Rarith, tmp, LSL #1
|
||
|
ORRS tmp, tmp, OP1mlo ;C=1; Z=round to even
|
||
|
|
||
|
RSB tmp, RNDexp, #32
|
||
|
|
||
|
;Merge in the sign bit and add one (C flag). Undo the rounding if we
|
||
|
;need to round to even and the result
|
||
|
|
||
|
ORR fOP, OP1sue, OP1mhi, LSR tmp
|
||
|
MOV a4, #0
|
||
|
TSTEQ fOP, #1 ;test for even
|
||
|
ADDNE fOP, fOP, #1
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BX lr
|
||
|
ELSE
|
||
|
MOV pc, lr
|
||
|
ENDIF
|
||
|
|
||
|
;...........................................................................
|
||
|
|
||
|
_e2f_ExpJustUnderflow
|
||
|
|
||
|
;The number may just be representable as the single precision epsilon.
|
||
|
|
||
|
ORR tmp, OP1mlo, OP1mhi, LSL #1
|
||
|
ORRS tmp, tmp, Rarith
|
||
|
ASSERT OP1sue = fOP
|
||
|
ORRNE fOP, OP1sue, #1
|
||
|
MOV a4, #0
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BX lr
|
||
|
ELSE
|
||
|
MOV pc, lr
|
||
|
ENDIF
|
||
|
|
||
|
;...........................................................................
|
||
|
|
||
|
_e2f_Uncommon
|
||
|
|
||
|
TST OP1sue, #Error_bit
|
||
|
BNE _e2f_Error
|
||
|
MOV a4, #0
|
||
|
|
||
|
;And infinity or a NaN. Infinity is signalled by mhi=mlo=0
|
||
|
|
||
|
TEQ OP1mhi, #0
|
||
|
MOVNES OP1mhi, OP1mhi, LSL #1
|
||
|
MOVMI fOP, #-1
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BXMI lr
|
||
|
ELSE
|
||
|
MOVMI pc, lr
|
||
|
ENDIF
|
||
|
TEQEQ OP1mlo, #0
|
||
|
MOVNE a4, #IVO_bits
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BXNE lr
|
||
|
ELSE
|
||
|
MOVNE pc, lr
|
||
|
ENDIF
|
||
|
|
||
|
;An infinity, whose sign is in the sue register.
|
||
|
|
||
|
MOVS OP1sue, OP1sue, LSL #1 ; C<-sign
|
||
|
MOV fOP, #&ff000000
|
||
|
MOV fOP, fOP, RRX ; add sign
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BX lr
|
||
|
ELSE
|
||
|
MOV pc, lr
|
||
|
ENDIF
|
||
|
|
||
|
_e2f_Error
|
||
|
|
||
|
MOV a4, OP1sue
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BX lr
|
||
|
ELSE
|
||
|
MOV pc, lr
|
||
|
ENDIF
|
||
|
|
||
|
;...........................................................................
|
||
|
|
||
|
_e2f_NeedsRounding
|
||
|
|
||
|
;The sign is in OP1sue, the exponent (in range) is in RNDexp.
|
||
|
|
||
|
BIC OP1mhi, OP1mhi, #EIUnits_bit
|
||
|
|
||
|
;Get the bits that are to be thrown away, except for the topmost one.
|
||
|
|
||
|
ORR tmp, OP1mlo, OP1mhi, LSL #SFrc_len+2
|
||
|
ORRS tmp, tmp, Rarith ; Z<-round to even
|
||
|
|
||
|
AND tmp, OP1sue, #Sign_bit ; save the real sign
|
||
|
MOV fOP, RNDexp, LSL #SExp_pos
|
||
|
ORR fOP, fOP, OP1mhi, LSR #32-SFrc_len-1
|
||
|
|
||
|
MOV a4, #0
|
||
|
|
||
|
BEQ _e2f_RoundToEven ; go out of line for speed
|
||
|
|
||
|
ADD fOP, fOP, #1
|
||
|
ADDS a2, fOP, #1<<SExp_pos ; can't be done in one add :-(
|
||
|
ORR fOP, fOP, tmp
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BXPL lr
|
||
|
ELSE
|
||
|
MOVPL pc, lr
|
||
|
ENDIF
|
||
|
MOV a4, #OVF_bits
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BX lr
|
||
|
ELSE
|
||
|
MOV pc, lr
|
||
|
ENDIF
|
||
|
|
||
|
_e2f_RoundToEven
|
||
|
TSTEQ fOP, #1
|
||
|
ORREQ fOP, fOP, tmp
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BXEQ lr
|
||
|
ELSE
|
||
|
MOVEQ pc, lr
|
||
|
ENDIF
|
||
|
|
||
|
ADD fOP, fOP, #1
|
||
|
ADDS a2, fOP, #1<<SExp_pos ; can't be done in one add :-(
|
||
|
ORR fOP, fOP, tmp
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BXPL lr
|
||
|
ELSE
|
||
|
MOVPL pc, lr
|
||
|
ENDIF
|
||
|
MOV a4, #OVF_bits
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
BX lr
|
||
|
ELSE
|
||
|
MOV pc, lr
|
||
|
ENDIF
|
||
|
|
||
|
]
|
||
|
|
||
|
;---------------------------------------------------------------------------
|
||
|
|
||
|
[ :DEF: fflt_s :LOR: :DEF: ffltu_s
|
||
|
|
||
|
MACRO
|
||
|
SingleNormalise
|
||
|
|
||
|
MOVS utmp1, a1, LSR #16
|
||
|
MOVEQ a1, a1, LSL #16
|
||
|
SUBEQ tmp, tmp, #16<<SExp_pos
|
||
|
MOVS utmp1, a1, LSR #24
|
||
|
MOVEQ a1, a1, LSL #8
|
||
|
SUBEQ tmp, tmp, #8<<SExp_pos
|
||
|
MOVS utmp1, a1, LSR #28
|
||
|
MOVEQ a1, a1, LSL #4
|
||
|
SUBEQ tmp, tmp, #4<<SExp_pos
|
||
|
MOVS utmp1, a1, LSR #30
|
||
|
MOVEQ a1, a1, LSL #2
|
||
|
SUBEQ tmp, tmp, #2<<SExp_pos
|
||
|
MOVS utmp1, a1, LSR #31
|
||
|
MOVEQ a1, a1, LSL #1
|
||
|
SUBEQ tmp, tmp, #1<<SExp_pos
|
||
|
MOV a1, a1, LSL #1 ; throw away top bit.
|
||
|
|
||
|
; Have the normalised number in a1. We need to (possibly) round it.
|
||
|
; Use a2 as a scratch temporary.
|
||
|
|
||
|
MOVS a2, a1, LSL #24 ;C<-round Z<-sticky
|
||
|
ORRCC fOP, tmp, a1, LSR #SExp_len+1 ;no rounding needed
|
||
|
ReturnToLR CC ; so return
|
||
|
|
||
|
TSTEQ a1, #1:SHL:(SExp_len+1) ;Z<-even
|
||
|
ORR fOP, tmp, a1, LSR #SExp_len+1 ;combine exponext/sign/mantissa
|
||
|
ADDNE a1, a1, #1 ;round
|
||
|
ReturnToLR
|
||
|
|
||
|
MEND
|
||
|
|
||
|
]
|
||
|
|
||
|
;...........................................................................
|
||
|
|
||
|
[ :DEF: fflt_s
|
||
|
|
||
|
LOC_SIZE EQU 0x18
|
||
|
OrgOp1l EQU 0x10
|
||
|
ExDResl EQU 0x08
|
||
|
NewResl EQU 0x10
|
||
|
|
||
|
Export __itos
|
||
|
Export __utos
|
||
|
IMPORT FPE_Raise
|
||
|
|
||
|
; Prolog must be the same as __itos
|
||
|
NESTED_ENTRY __utos
|
||
|
EnterWithLR_16
|
||
|
STMFD sp!, {lr} ; Save return address
|
||
|
SUB sp, sp, #LOC_SIZE ; Allocate local storage
|
||
|
PROLOG_END
|
||
|
|
||
|
MOV r12, r0 ; Keep original operand
|
||
|
MOV r2, #_FpUToS ; Initialize opcode
|
||
|
MOV exp, #(SExp_bias+1) << SExp_pos
|
||
|
B __fflt_normalise
|
||
|
|
||
|
ENTRY_END __utos
|
||
|
|
||
|
|
||
|
; Prolog must be the same as __utos
|
||
|
NESTED_ENTRY __itos
|
||
|
EnterWithLR_16
|
||
|
STMFD sp!, {lr} ; Save return address
|
||
|
SUB sp, sp, #LOC_SIZE ; Allocate local storage
|
||
|
PROLOG_END
|
||
|
|
||
|
MOV r12, r0 ; Keep original operand
|
||
|
MOV r2, #_FpIToS ; Initialize opcode
|
||
|
ANDS exp, a1, #Sign_bit
|
||
|
RSBNE a1, a1, #0
|
||
|
ORR exp, exp, #(SExp_bias+1) << SExp_pos
|
||
|
; fallthrough
|
||
|
|
||
|
__fflt_normalise
|
||
|
MOVS a2, a1, LSR #16
|
||
|
ADDNE exp, exp, #16 << SExp_pos
|
||
|
MOVEQS a1, a1, LSL #16
|
||
|
ADDEQ sp, sp, #LOC_SIZE
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
LDMEQFD sp!, {lr} ; a1 was zero - return +0
|
||
|
BXEQ lr
|
||
|
ELSE
|
||
|
LDMEQFD sp!, {pc} ; a1 was zero - return +0
|
||
|
ENDIF
|
||
|
TST a1, #0xFF000000
|
||
|
ADDNE exp, exp, #8 << SExp_pos
|
||
|
MOVEQ a1, a1, LSL #8
|
||
|
TST a1, #0xF0000000
|
||
|
ADDNE exp, exp, #4 << SExp_pos
|
||
|
MOVEQ a1, a1, LSL #4
|
||
|
TST a1, #0xC0000000
|
||
|
ADDNE exp, exp, #2 << SExp_pos
|
||
|
MOVEQS a1, a1, LSL #2
|
||
|
; MI if high bit set, PL if not
|
||
|
ADDMI exp, exp, #1 << SExp_pos
|
||
|
MOVPL a1, a1, LSL #1
|
||
|
MOVS a2, a1, LSL #24 ; Check for inexact
|
||
|
ORRNE r2, r2, #INX_bit ; If bits set, have inexact
|
||
|
MOVS a2, a1, LSL #25 ; CS -> round, EQ round to even
|
||
|
ADC a1, exp, a1, ASR #8 ; combine, subtract one from exponent
|
||
|
BCC __itos_return
|
||
|
BNE __itos_return
|
||
|
BIC a1, a1, #1
|
||
|
|
||
|
__itos_return
|
||
|
TST r2, #FPECause_mask ; Check if any exceptions
|
||
|
ADDEQ sp, sp, #LOC_SIZE ; If no exceptions, restore stack
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
LDMEQFD sp!, {lr} ; return
|
||
|
BXEQ lr
|
||
|
ELSE
|
||
|
LDMEQFD sp!, {pc} ; return
|
||
|
ENDIF
|
||
|
STR r0, [sp, #ExDResl] ; Store default result
|
||
|
ADD r0, sp, #NewResl ; Pointer to return value
|
||
|
MOV r1, r2 ; Exception information
|
||
|
MOV r2, r12 ; Original arg
|
||
|
|
||
|
CALL FPE_Raise ; Deal with exception information
|
||
|
|
||
|
IF Thumbing :LAND: :LNOT: Interworking
|
||
|
CODE16
|
||
|
bx pc ; switch back to ARM mode
|
||
|
nop
|
||
|
CODE32
|
||
|
ENDIF
|
||
|
|
||
|
LDR r0, [sp, #NewResl] ; Load returned value
|
||
|
ADD sp, sp, #LOC_SIZE ; Restore stack
|
||
|
IF Interworking :LOR: Thumbing
|
||
|
LDMFD sp!, {lr} ; Return
|
||
|
BX lr
|
||
|
ELSE
|
||
|
LDMFD sp!, {pc} ; Return
|
||
|
ENDIF
|
||
|
|
||
|
ENTRY_END __itos
|
||
|
|
||
|
]
|
||
|
|
||
|
;---------------------------------------------------------------------------
|
||
|
|
||
|
[ :DEF: ll_sto_f_s :LOR: :DEF: ll_uto_f_s
|
||
|
|
||
|
MACRO
|
||
|
LongSingleNormalise
|
||
|
|
||
|
MOV utmp1, #0
|
||
|
MOVS utmp2, a2, LSR #16
|
||
|
MOVEQ a2, a2, LSL #16
|
||
|
ADDEQ utmp1, utmp1, #16
|
||
|
MOVS utmp2, a2, LSR #24
|
||
|
MOVEQ a2, a2, LSL #8
|
||
|
ADDEQ utmp1, utmp1, #8
|
||
|
MOVS utmp2, a2, LSR #28
|
||
|
MOVEQ a2, a2, LSL #4
|
||
|
ADDEQ utmp1, utmp1, #4
|
||
|
MOVS utmp2, a2, LSR #30
|
||
|
MOVEQ a2, a2, LSL #2
|
||
|
ADDEQ utmp1, utmp1, #2
|
||
|
MOVS utmp2, a2, LSR #31
|
||
|
MOVEQ a2, a2, LSL #1
|
||
|
ADDEQ utmp1, utmp1, #1
|
||
|
MOV a2, a2, LSL #1
|
||
|
|
||
|
SUB tmp, tmp, utmp1, LSL #SExp_pos
|
||
|
|
||
|
MOV utmp2, a1
|
||
|
|
||
|
; take bits from high word into mantissa
|
||
|
ORR fOP, tmp, a2, LSR #SExp_len+1
|
||
|
|
||
|
; get 32 - (number of bits from other word needed in mantissa)
|
||
|
RSB utmp1, utmp1, #64-SFrc_len-1
|
||
|
CMP utmp1, #32
|
||
|
|
||
|
BHI %ft01
|
||
|
ORR fOP, fOP, utmp2, LSR utmp1
|
||
|
RSB utmp1, utmp1, #33
|
||
|
MOVS utmp2, utmp2, LSL utmp1 ; C <- round, Z <- sticky
|
||
|
ReturnToLR CC
|
||
|
B %ft02
|
||
|
|
||
|
01 ; no words from high word - get round/carry from top word
|
||
|
ORRS a2, utmp2, a2, LSL #33-(SExp_len+1) ; C <- round, Z <- sticky
|
||
|
ReturnToLR CC
|
||
|
02 ; test to-even case
|
||
|
TSTEQ fOP, #1
|
||
|
ADDNE fOP, fOP, #1
|
||
|
ReturnToLR
|
||
|
|
||
|
MEND
|
||
|
|
||
|
]
|
||
|
|
||
|
;...........................................................................
|
||
|
|
||
|
[ :DEF: ll_sto_f_s
|
||
|
|
||
|
Export _ll_sto_f
|
||
|
ImportCodeSize _ll_to_f_shared
|
||
|
ROUT
|
||
|
|
||
|
_ll_sto_f EnterWithLR_16
|
||
|
|
||
|
IMPORT _ffltu
|
||
|
|
||
|
TEQ a2, #0
|
||
|
BEQ _ffltu ; a 'normal' long
|
||
|
|
||
|
ANDS tmp, a2, #Sign_bit ; Extract sign
|
||
|
; sign in in tmp, denormalised mantissa in a1/a2
|
||
|
[ CodeSize = 2
|
||
|
BEQ _ll_to_f_shared
|
||
|
|
|
||
|
ORR tmp, tmp, #((SExp_bias + 63) :AND: 0xff00) << SExp_pos
|
||
|
[ CodeSize = 1
|
||
|
BEQ _ll_to_f_shared
|
||
|
|
|
||
|
|
||
|
ORR tmp, tmp, #((SExp_bias + 63) :AND: 0x00ff) << SExp_pos
|
||
|
BEQ %ft01
|
||
|
]
|
||
|
]
|
||
|
RSBS a1, a1, #0
|
||
|
RSCS a2, a2, #0
|
||
|
[ CodeSize <> 0
|
||
|
BNE _ll_to_f_shared
|
||
|
|
|
||
|
BEQ %ft02
|
||
|
|
||
|
|
||
|
01
|
||
|
LongSingleNormalise
|
||
|
|
||
|
02
|
||
|
]
|
||
|
EnterWithStack
|
||
|
BL _ffltu
|
||
|
ORR fOP, fOP, #Sign_bit
|
||
|
ReturnToStack
|
||
|
|
||
|
]
|
||
|
|
||
|
;...........................................................................
|
||
|
|
||
|
[ :DEF: ll_uto_f_s
|
||
|
|
||
|
Export _ll_uto_f
|
||
|
ExportCodeSize _ll_to_f_shared
|
||
|
|
||
|
_ll_uto_f EnterWithLR_16
|
||
|
|
||
|
IMPORT _ffltu
|
||
|
|
||
|
TEQ a2, #0
|
||
|
BEQ _ffltu
|
||
|
|
||
|
[ CodeSize = 2
|
||
|
MOV tmp, #0
|
||
|
|
||
|
_ll_to_f_shared
|
||
|
ORR tmp, tmp, #((SExp_bias + 63) :AND: 0xff00) << SExp_pos
|
||
|
|
|
||
|
MOV tmp, #((SExp_bias + 63) :AND: 0xff00) << SExp_pos
|
||
|
]
|
||
|
[ CodeSize = 1
|
||
|
_ll_to_f_shared
|
||
|
]
|
||
|
ORR tmp, tmp, #((SExp_bias + 63) :AND: 0x00ff) << SExp_pos
|
||
|
|
||
|
LongSingleNormalise
|
||
|
|
||
|
]
|
||
|
|
||
|
|
||
|
;===========================================================================
|
||
|
|
||
|
[ :DEF: ffix_s
|
||
|
|
||
|
Export _ffix
|
||
|
IMPORT __fp_exception
|
||
|
|
||
|
_ffix EnterWithLR_16
|
||
|
MOVS a3, fOP, ASR #SFrc_len
|
||
|
MOV a1, fOP, LSL #SExp_len
|
||
|
ORR a1, a1, #1 << 31
|
||
|
BMI _ffix_negative
|
||
|
RSBS a3, a3, #31 + SExp_bias
|
||
|
MOVHI a1, a1, LSR a3
|
||
|
ReturnToLR HI ; 9 clk
|
||
|
BIC a1, a1, #1 << 31 ; clear high bit (positive)
|
||
|
B _ffix_ivo
|
||
|
|
||
|
_ffix_negative
|
||
|
AND a3, a3, #255
|
||
|
RSBS a3, a3, #31 + SExp_bias
|
||
|
MOVHI a1, a1, LSR a3
|
||
|
RSBHI a1, a1, #0 ; negative result
|
||
|
ReturnToLR HI ; 11 clk
|
||
|
TEQEQ a1, #0x80000000 ; MinInt special case
|
||
|
ReturnToLR EQ
|
||
|
; a1 negative
|
||
|
_ffix_ivo
|
||
|
CMP a3, #(31 + SExp_bias) - SExp_max ; EQ -> inf or NaN
|
||
|
MOV ip, #IVO_bit :OR: FixFn
|
||
|
BNE __fp_exception
|
||
|
MOVS a2, a1, LSL #1 ; NE -> NaN
|
||
|
MOVNE ip, #IVO_bit :OR: FixZeroFn
|
||
|
B __fp_exception
|
||
|
|
||
|
]
|
||
|
|
||
|
;---------------------------------------------------------------------------
|
||
|
|
||
|
[ :DEF: ffixu_s
|
||
|
|
||
|
Export _ffixu
|
||
|
IMPORT __fp_exception
|
||
|
|
||
|
_ffixu EnterWithLR_16
|
||
|
MOVS a3, fOP, ASR #SFrc_len
|
||
|
BMI _ffixu_negative
|
||
|
MOV a1, fOP, LSL #SExp_len
|
||
|
ORR a1, a1, #1 << 31
|
||
|
RSBS a3, a3, #31 + SExp_bias
|
||
|
MOVHS a1, a1, LSR a3
|
||
|
ReturnToLR HS
|
||
|
BIC a1, a1, #1 << 31 ; clear high bit (positive)
|
||
|
B _ffixu_ivo
|
||
|
|
||
|
_ffixu_negative
|
||
|
MOVS a1, fOP, LSL #1 ; don't generate IVO for -0
|
||
|
ReturnToLR EQ
|
||
|
MOV a1, #0x80000000 ; negative
|
||
|
_ffixu_ivo
|
||
|
CMP a3, #(31 + SExp_bias) - SExp_max ; EQ -> inf or NaN
|
||
|
MOV ip, #IVO_bit :OR: FixuFn
|
||
|
BNE __fp_exception
|
||
|
MOVS a2, a1, LSL #1 ; NE -> NaN
|
||
|
MOVNE ip, #IVO_bit :OR: FixZeroFn
|
||
|
B __fp_exception
|
||
|
|
||
|
]
|
||
|
|
||
|
;---------------------------------------------------------------------------
|
||
|
|
||
|
[ :DEF: ll_sfrom_f_s
|
||
|
|
||
|
Export _ll_sfrom_f
|
||
|
|
||
|
ROUT
|
||
|
_ll_sfrom_f EnterWithLR_16
|
||
|
|
||
|
MOVS a3, fOP, LSL #1 ; C <- sign
|
||
|
MOV a3, a3, LSR #SFrc_len+1 ; Get exponent
|
||
|
MOV a2, fOP, LSL #SExp_len ; mantissa + 1 spare bit
|
||
|
ORR a2, a2, #1<<31 ; add units bit
|
||
|
; mantissa is in a2
|
||
|
|
||
|
BCS ll_from_f_neg
|
||
|
|
||
|
SUBS a3, a3, #SExp_bias
|
||
|
BMI _ll_from_f_zero
|
||
|
RSBS a4, a3, #31
|
||
|
|
||
|
MOVGT a1, a2, LSR a4
|
||
|
MOVGT a2, #0
|
||
|
ReturnToLR GT
|
||
|
|
||
|
ADDS a4, a4, #32
|
||
|
SUB a3, a3, #31
|
||
|
MOVGT a1, a2, LSL a3
|
||
|
MOVGT a2, a2, LSR a4
|
||
|
ReturnToLR GT
|
||
|
; fall through
|
||
|
|
||
|
BIC a1, a1, #Sign_bit ; return +ve value
|
||
|
B _ll_from_f_ivo
|
||
|
|
||
|
_ll_from_f_zero
|
||
|
MOV a1, #0
|
||
|
MOV a2, #0
|
||
|
ReturnToLR
|
||
|
|
||
|
ll_from_f_neg
|
||
|
SUBS a3, a3, #SExp_bias
|
||
|
BMI _ll_from_f_zero
|
||
|
RSBS a4, a3, #31
|
||
|
|
||
|
MOVPL a1, a2, LSR a4
|
||
|
MOVPL a2, #0
|
||
|
BPL %ft01
|
||
|
|
||
|
ADDS a4, a4, #32
|
||
|
SUB a3, a3, #31
|
||
|
BLE %ft02
|
||
|
MOV a1, a2, LSL a3
|
||
|
MOV a2, a2, LSR a4
|
||
|
|
||
|
01 RSBS a1, a1, #0
|
||
|
RSC a2, a2, #0
|
||
|
|
||
|
ReturnToLR
|
||
|
|
||
|
02
|
||
|
; Special case - INT_MIN will leave a shift of zero (Z set), and
|
||
|
; r0=0x80000000 r1=0x00000000
|
||
|
TEQEQ a2, #Sign_bit
|
||
|
MOVEQ a1, #0
|
||
|
ReturnToLR EQ
|
||
|
|
||
|
ORR a1, a1, #Sign_bit ; return -ve value
|
||
|
_ll_from_f_ivo
|
||
|
; On some systems, casting NaN returns zero
|
||
|
; check for maximum exponent
|
||
|
ADD a3, a4, #:NOT:(63-((SExp_mask:SHR:SExp_pos)-SExp_bias))
|
||
|
CMN a3, #1
|
||
|
MOV a4, #IVO_bit :OR: FixFn :OR: LongLong_bit
|
||
|
BNE __fp_nonveneer_error
|
||
|
MOVS tmp, a2, LSL #1 ; ignore units bit
|
||
|
MOVNE a4, #IVO_bit :OR: FixZeroFn :OR: LongLong_bit
|
||
|
B __fp_nonveneer_error
|
||
|
]
|
||
|
|
||
|
;---------------------------------------------------------------------------
|
||
|
|
||
|
[ :DEF: ll_ufrom_f_s
|
||
|
|
||
|
|
||
|
Export _ll_ufrom_f
|
||
|
ExportCodeSize _ll_from_f_shared
|
||
|
ExportCodeSize _ll_from_f_zero
|
||
|
|
||
|
_ll_ufrom_f EnterWithLR_16
|
||
|
|
||
|
MOVS a3, fOP, LSL #1 ; C <- sign
|
||
|
BHI _ll_ufrom_f_neg
|
||
|
MOV a3, a3, LSR #SFrc_len+1
|
||
|
MOV a2, fOP, LSL #SExp_len
|
||
|
ORR a2, a2, #1<<31
|
||
|
|
||
|
SUBS a3, a3, #SExp_bias
|
||
|
BMI _ll_ufrom_f_zero
|
||
|
RSBS a4, a3, #31
|
||
|
|
||
|
MOVPL a1, a2, LSR a4
|
||
|
MOVPL a2, #0
|
||
|
ReturnToLR PL
|
||
|
|
||
|
ADDS a4, a4, #32
|
||
|
SUB a3, a3, #31
|
||
|
MOVPL a1, a2, LSL a3
|
||
|
MOVPL a2, a2, LSR a4
|
||
|
ReturnToLR PL
|
||
|
; fall through
|
||
|
|
||
|
_ll_ufrom_f_ivo
|
||
|
BIC a1, a1, #Sign_bit ; return unsigned result
|
||
|
; On some systems, casting NaN returns zero
|
||
|
; check for maximum exponent
|
||
|
ADD a3, a4, #:NOT:(63-((SExp_mask:SHR:SExp_pos)-SExp_bias))
|
||
|
CMN a3, #1
|
||
|
MOV a4, #IVO_bit :OR: FixuFn :OR: LongLong_bit
|
||
|
BNE __fp_nonveneer_error
|
||
|
MOVS tmp, a2, LSL #1 ; ignore units bit
|
||
|
MOVNE a4, #IVO_bit :OR: FixZeroFn :OR: LongLong_bit
|
||
|
B __fp_nonveneer_error
|
||
|
|
||
|
_ll_ufrom_f_neg
|
||
|
MOV a4, #IVO_bit :OR: FixZeroFn :OR: LongLong_bit
|
||
|
B __fp_nonveneer_error
|
||
|
|
||
|
_ll_ufrom_f_zero
|
||
|
MOV a1, #0
|
||
|
MOV a2, #0
|
||
|
ReturnToLR
|
||
|
|
||
|
]
|
||
|
|
||
|
;===========================================================================
|
||
|
|
||
|
END
|