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

446 lines
11 KiB
NASM

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Microsoft Research Singularity
;;;
;;; Copyright (c) Microsoft Corporation. All rights reserved.
;;;
;;; This file contains ARM-specific assembly code.
;;;
; except.s
;
; Copyright (C) Advanced RISC Machines Limited, 1994. All rights reserved.
;
; RCS Revision: 1
; Checkin Date: 2007/06/29 02:59:16
; Revising Author
;==============================================================================
;Error generation - from ANSI library
GET fpe.asm
GET h_errors.asm
[ :DEF: liberror_s
AREA |.text|, CODE, READONLY
Export_32 __fp_edom
Export_32 __fp_erange
; __fp_edom(ulong sign_bit, boolean huge_val);
; __fp_erange(ulong sign_bit, boolean huge_val);
;
; set errno to EDOM/ERANGE and return sign_bit | (huge_val ? HUGE_VAL : 0)
__fp_edom EnterWithLR
MOV a3, #EDOM
B skip
__fp_erange EnterWithLR
MOV a3, #ERANGE
skip
AND a4, a1, #Sign_bit
[ :DEF:EMBEDDED_CLIB
IMPORT __rt_errno_addr
LDR a1, =__rt_errno_addr
CMP a1, #0
BEQ %FT1
STMDB sp!, {a2-a4, lr}
BL __rt_errno_addr
LDMIA sp!, {a2-a4, lr}
STR a3, [a1]
1
|
LDR a1, errno
STR a3, [a1]
]
TEQ a2, #0
MOVEQ a1, #0 ; generate +/- 0.0 in a1/a2
LDRNE a1, huge_val
LDMNEIA a1, {a1, a2} ; load HUGE_VAL into a1/a2
ORR a1, a1, a4 ; add in sign bit
ReturnToLR
[ :LNOT::DEF:EMBEDDED_CLIB
errno
IMPORT __errno
DCD __errno
]
huge_val
IMPORT __huge_val
DCD __huge_val
]
;==============================================================================
;Setting/returning status flags.
[ :DEF: status_s
AREA |.text|, CODE, READONLY
EXPORT __fp_status
; extern unsigned int __fp_status(unsigned int mask,unsigned int flags)
__fp_status
[ :DEF: thumb
CODE16
; mask "mask" to an acceptable value
MOV a4,#&e0
LSL a3,a1,#32-FPExceptE_pos-Except_len
LSR a3,a3,#32-FPExceptE_pos-Except_len
BIC a3,a4
LSR a4,#8
BIC a3,a4
AND a4,a1
ORR a3,a1
AND a2,a3
; mask in a3, masked flags in a2
LDR a4,status_ptr
LDR a1,[a4]
; **** *WARNING* is ip spare under the TPCS ????? ****
MOV ip,a1 ; store value
BIC a1,a3
EOR a1,a2
STR a1,[a4]
MOV a1,ip ; restore value
BX lr
ALIGN
|
; mask "mask" to an acceptable value
MOV a3,a1,LSL #32-FPExceptE_pos-Except_len
BIC a3,a3,#&e0:SHL:(32-FPExceptE_pos-Except_len)
BIC a3,a3,#&e0:SHL:(32-FPExceptE_pos-Except_len+8)
AND a2,a2,a3,LSR #32-FPExceptE_pos-Except_len
; mask in a3, masked flags in a2.
LDR a4,status_ptr
LDR a1,[a4] ; load old flags
BIC a3,a1,a3,LSR #32-FPExceptE_pos-Except_len
EOR a3,a3,a2 ; clear/set/toggle flags and
STR a3,[a4] ; write back.
IF Interworking :LOR: Thumbing
BX lr
ELSE
MOV pc,lr ; return
ENDIF
]
status_ptr
IMPORT __fp_status_flags
DCD __fp_status_flags
]
;==============================================================================
;Error checking - from fplib code
[ :DEF: fcheck_s
AREA |.text|, CODE, READONLY
[ :DEF: thumb
CODE32
]
EXPORT __fp_fcheck_NaN2
EXPORT __fp_dcheck_NaN2
EXPORT __fp_return_NaN
EXPORT __fp_return_Inf
IMPORT __fp_exception
; Check fOP1 and fOP2 for signalling NaN, IP contains exception flags.
__fp_fcheck_NaN2
MOV a4, #0x01000000
CMN a4, fOP1, LSL #1
BLS fcheck_opnd2_NaN
fcheck_opnd1_NaN
TST fOP1, #fSignalBit
BEQ __fp_exception
CMN a4, fOP2, LSL #1
BLS __fp_return_NaN
fcheck_opnd2_NaN
MOV fOP1, fOP2
TST fOP1, #fSignalBit
BNE __fp_return_NaN ;; RDCFix: Do we really want to do this?
; BEQ __fp_return_NaN
B __fp_exception
; Check dOP1 and dOP2 for signalling NaN, IP contains exception flags.
__fp_dcheck_NaN2
STMFD sp!, {ip}
MOV tmp, #0x00200000
CMN tmp, dOP1h, LSL #1
CMPEQ dOP1l, #0
BLS dcheck_opnd2_NaN
dcheck_opnd1_NaN
TST dOP1h, #dSignalBit
LDMEQFD sp!, {ip}
BEQ __fp_exception
CMN tmp, dOP2h, LSL #1
CMPEQ dOP2l, #0
LDMLSFD sp!, {ip}
BLS __fp_return_NaN
dcheck_opnd2_NaN
LDMFD sp!, {ip}
MOV dOP1h, dOP2h
MOV dOP1l, dOP2l
TST dOP1h, #dSignalBit
BNE __fp_return_NaN ;; RDCFix: Do we really want to do this?
; BEQ __fp_return_NaN
B __fp_exception
; Return NaN in fOP / dOP, except for non-float returning functions.
; IP contains exception flags.
__fp_return_NaN
; test for special cases
;;
;; RDCFix: Will need to fix this once new defines are in. May want to
;; do some performance enhancements to keep from needing to check
;; each _Fp* operation code. Maybe a jump table. Maybe forget
;; this garbage and make the core emulation routines pack up
;; their proper results instead of hacking them up here.
;;
; AND a4, ip, #Fn_mask
; CMP a4, #CompareFalseFn
; CMPNE a4, #FixZeroFn
; BEQ return_zero
; CMP a4, #CompareTrueFn
; BEQ return_one
; CMP a4, #CmpLessFn
; BEQ return_HI
; CMP a4, #CmpGreaterFn
; BEQ return_LO
; CMP a4, #CmpEqualFn
; BEQ return_NE
; CMP a4, #FixFn
; BEQ return_smaxint
; CMP a4, #FixuFn
; BEQ return_umaxint
ReturnToLR
return_HI
MOV a1, #1
CMP a1, #0
ReturnToLR_flg
return_LO
MOV a1, #0
CMP a1, #1
ReturnToLR_flg
return_NE
MOVS a1, #1
ReturnToLR_flg
return_one
MOV a1, #1
ReturnToLR
return_zero
MOV a1, #0
MOV a2, #0
ReturnToLR
return_smaxint
MOV a3, a1
TST ip, #LongLong_bit
MOVEQ a1, #0x7fffffff
MOVNE a1, #0xffffffff
MOVNE a2, #0x7fffffff
TST a3, #Sign_bit
MVNNE a1, a1
MVNNE a2, a2
ReturnToLR
return_umaxint
MOV a1, #0xffffffff
MOV a2, #0xffffffff
ReturnToLR
__fp_return_Inf
; no special cases
ReturnToLR
]
;==============================================================================
;Error generation - from fplib code
[ :DEF: except_s
AREA |.text|, CODE, READONLY
; SWI Names
[ :DEF: thumb
CODE32
]
EXPORT __fp_veneer_error
EXPORT __fp_nonveneer_error
EXPORT __fp_exception
IMPORT __fp_return_NaN
IMPORT __fp_return_Inf
__fp_veneer_error ; a4 contains the exception flags
__fp_nonveneer_error ; a4 contains the exception flags OBSOLETE
MOV ip, a4
; fallthrough
; fp_exception is called when an IEEE exception has occurred
; a1 contains the sign of the NaN to be returned if the exception is disabled
; ip contains the exception flags (see fpe.s for a list)
__fp_exception
IMPORT FPE_Raise
STMDB sp!,{lr}
TST ip,#OVF_bit
BNE overflow
TST ip,#UNF_bit
BNE underflow
TST ip,#DVZ_bit
BNE divide_by_zero
TST ip,#INX_bit
BNE divide_by_zero
invalid_operation
BL return_NaN
B callraise
overflow
BL return_Inf
B callraise
underflow
MOV a1, #0
MOV a2, #0
B callraise
inexact
B callraise
divide_by_zero
BL return_Inf
callraise
IF Interworking :LOR: Thumbing
LDMIA sp!, {lr}
BX lr
ELSE
LDMIA sp!, {pc}
ENDIF
;GenerateError
; IMPORT RaiseException
; [ :DEF:EMBEDDED_CLIB
; STMDB sp!, {r0-r15}
; SUB lr, lr, #4
; STR lr, [sp, #15*4]
; MOV r1, sp
; |
; LDR r1,ErrBlock
; SUB lr,lr,#4
; STR lr,[r1,#15*4]
; MOV lr,#&de00
; ORR lr,lr,#&00ad
; ORR lr,lr,lr,LSL #16
; STMIA r1,{r0-r14}
; B RaiseException
status_ptr
IMPORT __fp_status_flags
DCD __fp_status_flags
ErrBlock
IMPORT __fp_errblock
DCD __fp_errblock
trap
; ]
IMPORT __rt_trap
LDR ip, =__rt_trap
CMP ip, #0
[ Interworking :LOR:(:DEF:thumb)
BXNE ip
|
MOVNE pc, ip
]
DCD 0xe6000010
ErrorBlock FP_IVO, "Floating Point Exception: Invalid Operation"
ErrorBlock FP_OFL, "Floating Point Exception: Overflow"
ErrorBlock FP_DVZ, "Floating Point Exception: Divide By Zero"
return_Inf
AND a3,a1,#Sign_bit
TST ip,#Double_bit
ADRNE a1,prototype_double_Inf
LDMNEIA a1,{a1,a2}
LDREQ a1,prototype_single_Inf
ORR a1,a1,a3
B __fp_return_Inf
return_NaN
AND a3, a1, #Sign_bit
TST ip, #Double_bit
ADRNE a1,prototype_double_NaN
LDMNEIA a1,{a1,a2}
LDREQ a1,prototype_single_NaN
ORR a1, a1, a3
B __fp_return_NaN
prototype_double_Inf
DCD &7ff00000,&00000000
prototype_single_Inf
DCD &7f800000
prototype_double_NaN
DCD &7ff00000,&00000001
prototype_single_NaN
DCD &7f800001
]
;------------------------------------------------------------------------------
[ :DEF: fpdata_s
AREA |.data|, DATA
EXPORT __fp_status_flags
__fp_status_flags
; default - all flags enabled.
DCD (&40:SHL:SysID_pos):OR:(((1:SHL:Except_len)-1):SHL:FPExceptE_pos)
EXPORT __fp_errblock
__fp_errblock
DCD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0
EXPORT __rt_trap
__rt_trap
DCD 0
]
;==============================================================================
END