534 lines
14 KiB
NASM
534 lines
14 KiB
NASM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;
|
|
;;; Microsoft Research Singularity
|
|
;;;
|
|
;;; Copyright (c) Microsoft Corporation. All rights reserved.
|
|
;;;
|
|
;;; This file contains ARM-specific assembly code.
|
|
;;;
|
|
|
|
; fpe.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 defaults.asm
|
|
GET callcode.asm
|
|
GBLL FPEWanted
|
|
GBLL FPASCWanted
|
|
GBLL EnableInterrupts
|
|
GBLA CoreDebugging
|
|
|
|
FPEWanted SETL {FALSE}
|
|
FPASCWanted SETL {FALSE}
|
|
EnableInterrupts SETL {FALSE}
|
|
CoreDebugging SETA 0
|
|
|
|
|
|
;==============================================================================
|
|
|
|
;
|
|
; Allow some control over the code/speed of code produced.
|
|
; 0 = fastest -> 2 = smallest (overall)
|
|
;
|
|
|
|
GBLA CodeSize
|
|
CodeSize SETA 0
|
|
|
|
MACRO
|
|
ImportCodeSize $name
|
|
[ CodeSize <> 0
|
|
IMPORT $name
|
|
]
|
|
MEND
|
|
|
|
MACRO
|
|
ExportCodeSize $name
|
|
[ CodeSize <> 0
|
|
EXPORT $name
|
|
]
|
|
MEND
|
|
|
|
;==============================================================================
|
|
|
|
MACRO
|
|
$label CDebug4 $level,$message,$reg1,$reg2,$reg3,$reg4
|
|
MEND
|
|
MACRO
|
|
$label CDebug3 $level,$message,$reg1,$reg2,$reg3
|
|
MEND
|
|
MACRO
|
|
$label CDebug2 $level,$message,$reg1,$reg2
|
|
MEND
|
|
MACRO
|
|
$label CDebug1 $level,$message,$reg1
|
|
MEND
|
|
MACRO
|
|
$label CDebug0 $level,$message
|
|
MEND
|
|
|
|
; File for setting up THUMB macros for entry and exit from the THUMB
|
|
; versions of the functions.
|
|
|
|
GBLA V_N
|
|
|
|
[ :DEF: thumb
|
|
|
|
MACRO
|
|
$label VEnter_16 ; Like VEnter, but declare __16$label as the
|
|
CODE16 ; THUMB entry point
|
|
__16$label
|
|
BX pc
|
|
CODE32
|
|
V_N SETA V_N+1
|
|
LCLS f_lab
|
|
f_lab SETS "|":CC:"$F":CC::STR:V_N:CC:"|"
|
|
KEEP $f_lab
|
|
$f_lab
|
|
$label STMFD r13!,veneer_s ; ARM is the declared entry point
|
|
MEND
|
|
|
|
MACRO
|
|
$label VEnter ; Declare the THUMB entry point as the main
|
|
CODE16 ; entry point
|
|
$label BX pc
|
|
CODE32
|
|
V_N SETA V_N+1
|
|
LCLS f_lab
|
|
f_lab SETS "|":CC:"$F":CC::STR:V_N:CC:"|"
|
|
KEEP $f_lab
|
|
$f_lab
|
|
__32$label ; Declare a __32$label entry point for ARM
|
|
STMFD r13!,veneer_s
|
|
MEND
|
|
|
|
MACRO
|
|
$label VReturn $cc
|
|
$label LDM$cc.FD r13!,veneer_s
|
|
BX$cc lr
|
|
MEND
|
|
|
|
MACRO
|
|
$label VPull $cc
|
|
$label LDM$cc.FD r13!,veneer_s
|
|
MEND
|
|
|
|
MACRO
|
|
$label ReturnToLR $cc
|
|
$label BX$cc lr
|
|
MEND
|
|
|
|
MACRO
|
|
$label ReturnToLR_flg $cc
|
|
$label BX$cc lr
|
|
MEND
|
|
|
|
MACRO
|
|
$label ReturnToStack $cc
|
|
$label LDM$cc.FD sp!,{lr}
|
|
BX$cc lr
|
|
MEND
|
|
|
|
MACRO
|
|
$label PullFromStack $cc
|
|
$label LDM$cc.FD sp!,{lr}
|
|
MEND
|
|
|
|
MACRO
|
|
$label EnterWithLR_16
|
|
CODE16
|
|
__16$label
|
|
BX pc
|
|
CODE32
|
|
V_N SETA V_N+1
|
|
LCLS f_lab
|
|
f_lab SETS "|":CC:"$F":CC::STR:V_N:CC:"|"
|
|
KEEP $f_lab
|
|
$f_lab
|
|
$label
|
|
MEND
|
|
|
|
MACRO
|
|
$label EnterWithStack_16
|
|
CODE16
|
|
__16$label
|
|
BX pc
|
|
CODE32
|
|
V_N SETA V_N+1
|
|
LCLS f_lab
|
|
f_lab SETS "|":CC:"$F":CC::STR:V_N:CC:"|"
|
|
KEEP $f_lab
|
|
$f_lab
|
|
$label STMFD sp!,{lr}
|
|
MEND
|
|
|
|
MACRO
|
|
$label EnterWithLR
|
|
CODE16
|
|
$label BX pc
|
|
CODE32
|
|
V_N SETA V_N+1
|
|
LCLS f_lab
|
|
f_lab SETS "|":CC:"$F":CC::STR:V_N:CC:"|"
|
|
KEEP $f_lab
|
|
$f_lab
|
|
__32$label
|
|
MEND
|
|
|
|
MACRO
|
|
$label EnterWithStack
|
|
CODE16
|
|
$label BX pc
|
|
CODE32
|
|
V_N SETA V_N+1
|
|
LCLS f_lab
|
|
f_lab SETS "|":CC:"$F":CC::STR:V_N:CC:"|"
|
|
KEEP $f_lab
|
|
$f_lab
|
|
__32$label
|
|
STMFD sp!,{lr}
|
|
MEND
|
|
|
|
MACRO
|
|
Export $name
|
|
EXPORT $name
|
|
EXPORT __16$name
|
|
MEND
|
|
|
|
MACRO
|
|
Export_32 $name
|
|
EXPORT __32$name
|
|
EXPORT $name
|
|
MEND
|
|
|
|
MACRO
|
|
Import_32 $name
|
|
IMPORT __32$name
|
|
MEND
|
|
|
|
MACRO
|
|
$label B_32 $name
|
|
$label B __32$name
|
|
MEND
|
|
|
|
|
|
|
|
|
;ARM 32 and 26-bit mode
|
|
|
|
MACRO
|
|
$label VEnter_16
|
|
$label STMFD r13!,veneer_s
|
|
MEND
|
|
|
|
MACRO
|
|
$label VEnter
|
|
$label STMFD r13!,veneer_s
|
|
MEND
|
|
|
|
MACRO
|
|
$label VReturn $cc
|
|
$label [ Interworking :LOR: Thumbing
|
|
LDM$cc.FD r13!,veneer_s
|
|
BX$cc lr
|
|
|
|
|
[ {CONFIG} = 32
|
|
LDM$cc.FD r13!,veneer_l
|
|
]
|
|
[ {CONFIG} = 26
|
|
LDM$cc.FD r13!,veneer_l^
|
|
]
|
|
]
|
|
MEND
|
|
|
|
MACRO
|
|
$label VPull $cc
|
|
$label LDM$cc.FD r13!,veneer_s
|
|
MEND
|
|
|
|
MACRO
|
|
$label ReturnToLR $cc
|
|
$label [ Interworking :LOR: Thumbing
|
|
BX$cc lr
|
|
|
|
|
[ {CONFIG} = 32
|
|
MOV$cc pc,lr
|
|
]
|
|
[ {CONFIG} = 26
|
|
MOV$cc.S pc,lr
|
|
]
|
|
]
|
|
MEND
|
|
|
|
MACRO
|
|
$label ReturnToLR_flg $cc
|
|
$label [ Interworking :LOR: Thumbing
|
|
BX$cc lr
|
|
|
|
|
MOV$cc pc,lr
|
|
]
|
|
MEND
|
|
|
|
MACRO
|
|
$label ReturnToStack $cc
|
|
$label [ Interworking :LOR: Thumbing
|
|
LDM$cc.FD sp!,{lr}
|
|
BX$cc lr
|
|
|
|
|
[ {CONFIG} = 32
|
|
LDM$cc.FD sp!,{pc}
|
|
]
|
|
[ {CONFIG} = 26
|
|
LDM$cc.FD sp!,{pc}^
|
|
]
|
|
]
|
|
MEND
|
|
|
|
MACRO
|
|
$label PullFromStack $cc
|
|
$label LDM$cc.FD sp!,{lr}
|
|
MEND
|
|
|
|
MACRO
|
|
$label EnterWithLR_16
|
|
$label
|
|
MEND
|
|
|
|
MACRO
|
|
$label EnterWithStack_16
|
|
$label STMFD sp!,{lr}
|
|
MEND
|
|
|
|
MACRO
|
|
$label EnterWithLR
|
|
$label
|
|
MEND
|
|
|
|
MACRO
|
|
$label EnterWithStack
|
|
$label STMFD sp!,{lr}
|
|
MEND
|
|
|
|
MACRO
|
|
Export $name
|
|
EXPORT $name
|
|
MEND
|
|
|
|
MACRO
|
|
Export_32 $name
|
|
EXPORT $name
|
|
MEND
|
|
|
|
MACRO
|
|
Import_32 $name
|
|
IMPORT $name
|
|
MEND
|
|
|
|
MACRO
|
|
$label B_32 $name
|
|
$label B $name
|
|
MEND
|
|
|
|
]
|
|
|
|
MACRO
|
|
CodeArea $name
|
|
;; $name will be a name for the area. However for a release we'll use
|
|
;; C$$code instead
|
|
[ Interworking
|
|
AREA |.text|, CODE, READONLY
|
|
|
|
|
AREA |.text|, CODE, READONLY
|
|
]
|
|
MEND
|
|
|
|
GET regnames.asm
|
|
GET armdefs.asm
|
|
GET fpadefs.asm
|
|
GET macros.asm
|
|
|
|
sp RN R13
|
|
lr RN R14
|
|
pc RN R15
|
|
|
|
dOP1h RN R1 ;Double OP1 hi-reg ("First word") - sign,expn,etc.
|
|
dOP1l RN R0 ;Double OP1 lo-reg ("Second word")
|
|
dOPh RN R1 ;Double OP hi-reg (unary ops)
|
|
dOPl RN R0 ;Double OP lo-reg
|
|
dOP2h RN R3 ;Double OP2 hi-reg ("First word")
|
|
dOP2l RN R2 ;Double OP2 lo-reg ("Second word")
|
|
|
|
fOP1 RN R0 ;Float OP1
|
|
fOP RN R0 ;Float OP for unary ops
|
|
fOP2 RN R1 ;Float OP2
|
|
|
|
utmp1 RN R2 ;Temporary register fo unary operations
|
|
utmp2 RN R3 ; "
|
|
|
|
ip RN R12
|
|
tmp RN R12 ;A temporary register
|
|
|
|
SignBit EQU &80000000
|
|
fSignalBit EQU &00400000
|
|
dSignalBit EQU &00080000
|
|
w_oSignBit EQU &7fffffff
|
|
w_ofSignalBit EQU &ffbfffff
|
|
w_odSignalBit EQU &fff7ffff
|
|
Internal_mask EQU &00000000
|
|
Single_pos EQU 0
|
|
Double_pos EQU 1
|
|
Single_mask EQU 1:SHL:Single_pos
|
|
Double_mask EQU 1:SHL:Double_pos
|
|
Reverse EQU 0x4 ; Used to signal a reverse divide
|
|
|
|
;;Error flags - an extension to the normal internal format
|
|
|
|
Error_pos EQU 29
|
|
Error_bit EQU 1:SHL:Error_pos
|
|
|
|
Except_len EQU 5
|
|
Except_pos EQU Error_pos-Except_len
|
|
|
|
ASSERT IOC_pos < DZC_pos
|
|
ASSERT DZC_pos < OFC_pos
|
|
ASSERT OFC_pos < UFC_pos
|
|
ASSERT UFC_pos < IXC_pos
|
|
FPExceptC_pos EQU IOC_pos
|
|
ASSERT IOE_pos < DZE_pos
|
|
ASSERT DZE_pos < OFE_pos
|
|
ASSERT OFE_pos < UFE_pos
|
|
ASSERT UFE_pos < IXE_pos
|
|
FPExceptE_pos EQU IOE_pos
|
|
|
|
|
|
; Following fields are used to identify the originator function and the return type so that the
|
|
; error handler can return the correct value.
|
|
|
|
;;
|
|
;; All fields and values must agree with C headers and programs.
|
|
;;
|
|
;; r12 (defined as ip above) is used to pass information about the operation being performed
|
|
;; to the exception handler. The bit fields are defined as follows.
|
|
;;
|
|
;; 31 0
|
|
;; +--------------------------------+
|
|
;; | |
|
|
;; +--------------------------------+
|
|
;;
|
|
;; Bits Meaning
|
|
;; ~~~~ ~~~~~~~
|
|
;; 31 unused
|
|
;; 30 Uncommon (possible exceptional case -- requires more checking)
|
|
;; 29 Error (exceptional case)
|
|
;; 28:25 unused
|
|
;; 24:20 Operation code (must agree with enumerated type in fpraise.c)
|
|
;; 19:5 unused
|
|
;; 4 Exception cause: Inexact (must agree with float.h)
|
|
;; 3 Exception cause: Underflow
|
|
;; 2 Exception cause: Overflow
|
|
;; 1 Exception cause: Zero Divide
|
|
;; 0 Exception cause: Invalid Operation
|
|
;;
|
|
|
|
|
|
;;
|
|
;; Operation code defines. These must match with the FP_CODE enumerated
|
|
;; type in fpraise.c.
|
|
;;
|
|
Fn_pos EQU 20 ;; Function (operation) code position
|
|
Fn_mask EQU 31 << Fn_pos ;; Mask for the field
|
|
|
|
_FpAddD EQU ( 0 << Fn_pos) ;; Add Double
|
|
_FpAddS EQU ( 1 << Fn_pos) ;; Add Single
|
|
_FpSubD EQU ( 2 << Fn_pos) ;; Subtract Double
|
|
_FpSubS EQU ( 3 << Fn_pos) ;; Subtract Single
|
|
_FpCmpD EQU ( 4 << Fn_pos) ;; Compare Double
|
|
_FpCmpS EQU ( 5 << Fn_pos) ;; Compare Single
|
|
_FpDivD EQU ( 6 << Fn_pos) ;; Divide Double
|
|
_FpDivS EQU ( 7 << Fn_pos) ;; Divide Single
|
|
_FpDToI EQU ( 8 << Fn_pos) ;; Convert Double To int
|
|
_FpDToI64 EQU ( 9 << Fn_pos) ;; Convert Double To __int64
|
|
_FpDToS EQU (10 << Fn_pos) ;; Convert Double To Single
|
|
_FpDToU EQU (11 << Fn_pos) ;; Convert Double To unsigned int
|
|
_FpDToU64 EQU (12 << Fn_pos) ;; Convert Double To unsigned __int64
|
|
_FpIToS EQU (13 << Fn_pos) ;; Convert int To Single
|
|
_FpMulD EQU (14 << Fn_pos) ;; Multiply Double
|
|
_FpMulS EQU (15 << Fn_pos) ;; Multiply Single
|
|
_FpSToD EQU (16 << Fn_pos) ;; Convert Single To Double
|
|
_FpSToI EQU (17 << Fn_pos) ;; Convert Single To int
|
|
_FpSToI64 EQU (18 << Fn_pos) ;; Convert Single To __int64
|
|
_FpSToU EQU (19 << Fn_pos) ;; Convert Single To unsigned int
|
|
_FpSToU64 EQU (20 << Fn_pos) ;; Convert Single To unsigned __int64
|
|
_FpUToS EQU (21 << Fn_pos) ;; Convert unsigned int To Single
|
|
_FpI64ToD EQU (22 << Fn_pos) ;; Convert __int64 To Double
|
|
_FpI64ToS EQU (23 << Fn_pos) ;; Convert __int64 To Single
|
|
_FpU64ToD EQU (24 << Fn_pos) ;; Convert unsigned __int64 To Double
|
|
_FpU64ToS EQU (25 << Fn_pos) ;; Convert unsigned __int64 To Single
|
|
_FpRndD EQU (26 << Fn_pos) ;; Round to double integer
|
|
|
|
|
|
;; FP Exception Causes (must agree with fpraise.c FPExInfo)
|
|
;; Note that this is modelled after the ARM 7500FE FPSR Cumulative exception
|
|
;; flags byte. The semantics here are slightly different. If a bit is set
|
|
;; here, it means that the corresponding exception occurred during the current
|
|
;; FP operation. If a bit is clear, it means that the corresponding exception
|
|
;; did not occur during the current FP operation. The bits are set regardless
|
|
;; of which exceptions are enabled, etc. Raising exceptions, checking enabled
|
|
;; exceptions, and updating status and cause bits is done in fpraise.c which
|
|
;; maintains the "true" FPSCR.
|
|
INX_bit EQU (1 << 4) ;; Inexact
|
|
UNF_bit EQU (1 << 3) ;; Underflow
|
|
OVF_bit EQU (1 << 2) ;; Overflow
|
|
DVZ_bit EQU (1 << 1) ;; Zero Divide
|
|
IVO_bit EQU (1 << 0) ;; Invalid Operation
|
|
FPECause_mask EQU (INX_bit :OR: \
|
|
UNF_bit :OR: \
|
|
OVF_bit :OR: \
|
|
DVZ_bit :OR: \
|
|
IVO_bit )
|
|
|
|
|
|
INX_bits EQU (INX_bit)
|
|
UNF_bits EQU (UNF_bit :OR: INX_bit)
|
|
OVF_bits EQU (OVF_bit :OR: INX_bit)
|
|
DVZ_bits EQU (DVZ_bit)
|
|
IVO_bits EQU (IVO_bit)
|
|
|
|
|
|
;; FP compare values from fpieee.h _FPIEEE_COMPARE_RESULT
|
|
;; These are used for the exception handler.
|
|
_FpCompareEqual EQU 0
|
|
_FpCompareGreater EQU 1
|
|
_FpCompareLess EQU 2
|
|
_FpCompareUnordered EQU 3
|
|
|
|
|
|
|
|
Double_bit EQU ((1 << 18) :AND:0) ;; RDCFix: Get rid of this and fix what it breaks.
|
|
LongLong_bit EQU ((1 << 18) :AND:0) ;; RDCFix: Get rid of this and fix what it breaks.
|
|
|
|
EDOM EQU 1 ;; RDCFix: Need this?
|
|
ERANGE EQU 2 ;; RDCFix: Need this?
|
|
ESIGNUM EQU 3 ;; RDCFix: Need this?
|
|
|
|
veneer_s RLIST {r4-r9,r11,lr}
|
|
veneer_l RLIST {r4-r9,r11,pc}
|
|
|
|
|
|
;; Macro to do a load immediate of an arbitrary whole word.
|
|
MACRO
|
|
LWI $cc, $reg, $imm
|
|
MOV$cc $reg, #(($imm) :AND: 0x000000FF)
|
|
ORR$cc $reg, $reg, #(($imm) :AND: 0x0000FF00)
|
|
ORR$cc $reg, $reg, #(($imm) :AND: 0x00FF0000)
|
|
ORR$cc $reg, $reg, #(($imm) :AND: 0xFF000000)
|
|
MEND
|
|
|
|
|
|
|
|
|
|
|
|
END
|