136 lines
5.0 KiB
NASM
136 lines
5.0 KiB
NASM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;
|
|
;;; Microsoft Research Singularity
|
|
;;;
|
|
;;; Copyright (c) Microsoft Corporation. All rights reserved.
|
|
;;;
|
|
;;; This file contains ARM-specific assembly code.
|
|
;;;
|
|
|
|
; __stoi single precision floating point to signed integer convert
|
|
;
|
|
; Input: r0 - float to be converted
|
|
; Output: r0 - converted float in integer format
|
|
;
|
|
|
|
; Local stack size and offsets
|
|
LOC_SIZE EQU 0x18
|
|
OrgOp1l EQU 0x14
|
|
ExDResl EQU 0x08
|
|
NewResl EQU 0x10
|
|
|
|
|
|
GET fpe.asm
|
|
GET kxarm.inc
|
|
|
|
AREA |.text|, CODE, READONLY
|
|
|
|
Export __stoi
|
|
IMPORT FPE_Raise
|
|
|
|
NESTED_ENTRY __stoi
|
|
EnterWithLR_16
|
|
STMFD sp!, {lr} ; Save return address
|
|
SUB sp, sp, #LOC_SIZE ; Allocate local storage
|
|
PROLOG_END
|
|
MOVS r12, r0 ; Save original arg in case of exception
|
|
MOV r3, #_FpSToI ; Initialize opcode, no exceptions
|
|
|
|
MOVS r2, r0, ASR #SFrc_len ; Right justify exponent, save sign bit
|
|
MOV r0, r0, LSL #SExp_len ; Left justify mantissa and
|
|
ORR r0, r0, #1 << 31 ; insert hidden one (even for denorms)
|
|
BMI _ffix_negative ; If negative input, separate case
|
|
|
|
RSBS r2, r2, #31 + SExp_bias ; Determine shift amount
|
|
BLE shift_left ; Negative shift is a shift left, NaN,
|
|
; or INF; zero shift is an overflow
|
|
CMP r2, #32 ; See if shifting all bits out
|
|
BGE shift_right_32 ; If shifting all bits out, return zero
|
|
|
|
shift_right
|
|
RSB r1, r2, #32 ; Check for inexact
|
|
MOVS r1, r0, LSL r1 ; ..
|
|
ORRNE r3, r3, #INX_bit ; ..
|
|
MOV r0, r0, LSR r2 ; Shift the result
|
|
B __stoi_return ; Return
|
|
|
|
shift_left
|
|
ORR r3, r3, #IVO_bit ; Overflow so set invalid operation
|
|
RSB r2, r2, #0 ; Get left shift amount
|
|
MOV r0, r0, LSL r2 ; Perform shift
|
|
B __stoi_return ; Return
|
|
|
|
shift_right_32 ; abs(Arg) < 1.0, so losing all bits
|
|
MOV r0, #0 ; Return zero
|
|
MOVS r1, r12, LSL #1 ; Check for inexact
|
|
ORRNE r3, r3, #INX_bit ; If bits being lost, set inexact
|
|
B __stoi_return ; Return
|
|
|
|
|
|
_ffix_negative
|
|
AND r2, r2, #0xFF ; Mask off exponent field
|
|
RSBS r2, r2, #31 + SExp_bias ; Determine shift amount
|
|
BLT shift_left_neg ; Negative shift is a shift left, NaN
|
|
; or INF
|
|
BEQ special_min_int ; INT_MIN special case
|
|
CMP r2, #32 ; See if shifting all bits out
|
|
BGE shift_right_32 ; If shifting all bits out, return zero
|
|
|
|
shift_right_neg
|
|
RSB r1, r2, #32 ; Check for inexact
|
|
MOVS r1, r0, LSL r1 ; ..
|
|
ORRNE r3, r3, #INX_bit ; ..
|
|
MOV r0, r0, LSR r2 ; Shift the result
|
|
RSB r0, r0, #0 ; Negate result
|
|
B __stoi_return ; Return
|
|
|
|
shift_left_neg
|
|
ORR r3, r3, #IVO_bit ; Overflow so set invalid operation
|
|
RSB r2, r2, #0 ; Get left shift amount
|
|
MOV r0, r0, LSL r2 ; Perform shift
|
|
RSB r0, r0, #0 ; Negate result
|
|
B __stoi_return ; Return
|
|
|
|
|
|
special_min_int
|
|
TEQ r0, #0x80000000 ; Special case of INT_MIN
|
|
RSB r0, r0, #0 ; Negate result
|
|
ORRNE r3, r3, #IVO_bit ; Set invalid if not special case
|
|
|
|
|
|
__stoi_return
|
|
TST r3, #FPECause_mask ; Any exceptions?
|
|
ADDEQ sp, sp, #LOC_SIZE ; If not, restore stack and
|
|
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 new result
|
|
MOV r1, r3 ; Exception information
|
|
MOV r2, r12 ; Original arg
|
|
|
|
CALL FPE_Raise ; Handle exception information
|
|
|
|
IF Thumbing :LAND: :LNOT: Interworking
|
|
CODE16
|
|
bx pc ; switch back to ARM mode
|
|
nop
|
|
CODE32
|
|
ENDIF
|
|
|
|
LDR r0, [sp, #NewResl] ; Load new result
|
|
ADD sp, sp, #LOC_SIZE ; Pop off exception record
|
|
IF Interworking :LOR: Thumbing
|
|
LDMFD sp!, {lr} ; Return
|
|
BX lr
|
|
ELSE
|
|
LDMFD sp!, {pc} ; Return
|
|
ENDIF
|
|
|
|
ENTRY_END __stoi
|
|
|
|
END
|