📄 vrtlib16.s
字号:
IF EnsureNoFPSupport = {FALSE}
LDR a2, fp_finalise ; finalise FP code if present
CMP a2, #0
MOVNE lr, pc
MOVNE pc, a2
ENDIF
LDR r3, =_user_exit
LDR r3,[r3]
CMP r3, #0
BLNE __call_via_r3 ;jump to user exit handler if present
MOV lr, pc ;else loop forever
NOP
NOP
MOV pc, lr ;loop forever
;----------------------------------------------------------------------------;
AREA |C$$code$$__rt_fpavailable|, CODE, READONLY, INTERWORK ;
; The code area containing __rt_fpavailable ;
;----------------------------------------------------------------------------;
|__rt_fpavailable|
;
; int __rt_fpavailable(); return non-0 if FP support code linked.
IF EnsureNoFPSupport = {FALSE}
LDR a1, fp_initialise
ELSE
MOV a1, #0
ENDIF
RET
;----------------------------------------------------------------------------;
AREA |C$$code$$__jmp|, CODE, READONLY, INTERWORK ;
; The code area containing setjmp, longjmp ;
;----------------------------------------------------------------------------;
; Setjmp and longjmp support. ;
; ;
; NOTES ;
; ;
; 1/ Specific to C and not implementable in C. ;
; ;
; 2/ Interacts with stack management and possibly with memory management. ;
; e.g. on a chunked stack, longjmp must de-allocate jumped-over chunks. ;
; ;
; 3/ Must know whether the floating-point instruction-set is supported! ;
; (DEPENDS ON __rt_fpavailable to discover this). ;
; ;
;----------------------------------------------------------------------------;
MAP 0 ; This structure maps the jmp_buf
sj_v1 # 4 ; data type assumed by the C compiler.
sj_v2 # 4 ; First, space to save the v-registers...
sj_v3 # 4
sj_v4 # 4
sj_v5 # 4
sj_v6 # 4
sj_sl # 4 ; then the frame registers sl, fp, sp (ap),
sj_fp # 4 ; and pc/lr...
sj_ap # 4
sj_pc # 4
sj_f4 # 3*4 ; and finally the floating-point reisters,
sj_f5 # 3*4 ; used only if floating point support is
sj_f6 # 3*4 ; available.
sj_f7 # 3*4
|setjmp| ; setjmp
;
; int setjmp(jmp_buf env);
; Saves everything that might count as a register variable in 'env'.
STMIA a1!, {v1-v6, r10, fp, sp, lr}
MOV v6, a1 ; v6 safe in env - use to point past
; saved lr (at 1st FP slot)
BL |__rt_fpavailable|
CMP a1, #0
BEQ setjmp_return ; no fp
STFE f4, [v6, #sj_f4-sj_f4]
STFE f5, [v6, #sj_f5-sj_f4]
STFE f6, [v6, #sj_f6-sj_f4]
STFE f7, [v6, #sj_f7-sj_f4]
MOV a1, #0 ; must return 0 from a direct call
setjmp_return
LDMDB v6, {v6, r10, fp, sp, lr}
RET
|longjmp| ; longjmp ;
; int longjmp(jmp_buf env, int val);
MOV v1, a1 ; save env ptr over call to fpavailable
MOVS v6, a2 ; ensure non-0 return value...
MOVEQ v6, #1 ; (must NOT return 0 on longjmp(env, 0))
BL |__rt_fpavailable|
CMP a1, #0
BEQ longjmp_return
LDFE f7, [v1, #sj_f7]
LDFE f6, [v1, #sj_f6]
LDFE f5, [v1, #sj_f5]
LDFE f4, [v1, #sj_f4]
longjmp_return
MOV a1, v6
LDMIA v1, {v1-v6, r10, fp, sp, lr}
RET
CODE16
;----------------------------------------------------------------------------;
AREA |C$$code$$__16__rt_stkovf|, CODE, READONLY, INTERWORK ;
; The code area containing __16__rt_stkovf_* ;
;----------------------------------------------------------------------------;
|__16__rt_stkovf_split_small|
;
; Enter here when a C function with frame size <= 256 bytes underflows
; the stack low-water mark + StackSlop (sl). Falls into the big-frame case.
|__16__rt_stkovf_split_big|
;
; Enter here when a C function with frame size > 256 bytes would underflow
; the stack low-water mark + StackSlop (sl). No stack space is been claimed
PUSH {r0,r1}
MOV r1,#DefaultStackIncrement ;0 default stack increment
MOV r0, r1 ; the default increment
MOV r1, r10 ; r10 is sl
SUB r1, r0
LDR r0, =StackSlop
SUB r1, r0 ; new stack low-water mark
MOV r10, r1 ;r10 is sl
POP {r0, r1}
SUB sp, sp, #8*4 ; Room for R8..R15
PUSH {r0-r7}
MOV r7, lr
ADR r0, StackOverflowError16
MOV r1, #StackOverflowErrorLen
MOV r8, r1 ;store message length in r8
BL save_regs_and_trap16
ALIGN
StackOverflowError16
DCD 3
DCB "stack overflow", 0
ALIGN
;----------------------------------------------------------------------------;
AREA |C$$code$$__rt_trap16|, CODE, READONLY, INTERWORK
; The code area containing __rt_trap ;
;----------------------------------------------------------------------------;
; Support for low-level failures - currently stack overflow and divide by 0. ;
; If there is a higher level handler, call it otherwise, print a message and ;
; exit gracefully. ;
; ;
; NOTES ;
; ;
; typedef struct { unsigned code; char message[252];} __rt_error; ;
; typedef struct { unsigned r[16];} __rt_registers; ;
; ;
;----------------------------------------------------------------------------;
__rt_trap16
;
; void __rt_trap16(__rt_error *e, __rt_registers *r);
PUSH {r0} ; save e in case handler returns...
LDR r3, = cpu_interrupt_disable
BL call_via_r3
LDR r3, =__err_handler
CMP r3, #0
BEQ %F0
BL call_via_r3 ; Call the routine pointed to by R3
; Note: BL sets bit 0 of LR so return will
; be to Thumb state. This is why we use this
; rather than the sequence
; MOV lr, pc
; BX r3
; which may return to ARM state!
0
ADR r0, RTErrorHead16 ; No handler, or handler returned
MOV r1, #RTErrorHeadLen ;length of run time error text
LDR r3,=vmc_write
CMP r3,#0 ;check if vmc_write BSP present
BEQ %F1
BL call_via_r3 ;call vmc_write could be arm or thumb
POP {r0}
ADD r0, #4
MOV r1, r8 ;r8 contains length of error message
LDR r3,=vmc_write ;vmc_write may destroy r3 so reload
BL call_via_r3
ADR r0, RTErrorTail16
MOV r1,#RTErrorTailLen ;length of program terminated text
LDR r3,=vmc_write
BL call_via_r3
1 MOV a1, #255
BL __rt_exit16 ; and terminate with non-zero exit code
call_via_r3
BX r3
; SP has already been decremented by 16 * 4 and R0..R7 saved.
; IP points to the error description
; R7 contains the LR register which has been destroyed as a BL was required
; to get here.
save_regs_and_trap16
PUSH {r0,r1} ;save regs r0,r1 used by cpu_interrupt_disable
LDR r3, = cpu_interrupt_disable
BL call_via_r3
POP {r0,r1}
MOV ip, r0
MOV r0, r8
MOV r1, r9
MOV r2, r10
MOV r3, r11
MOV r4, r12
ADD r5, sp, #16*4 ; Take account of previous SP adjustment
ADD r6, sp, #8*4 ; Pointer to hi reg save area
STMIA r6!, {r0-r5, r7}
STR r7, [sp, #15*4] ; Save my pc as callers lr
MOV a2, sp
MOV a1, ip
B __rt_trap16
ALIGN
RTErrorHead16
DCB 10, 13, "run time error: ", 0
ALIGN
RTErrorTail16
DCB 10, 13, "program terminated", 10, 13, 10, 13, 0
ALIGN
_user_exit DCD |user_exit|
;----------------------------------------------------------------------------;
AREA |C$$code$$__exit16|, CODE, READONLY, INTERWORK
; The code area containing __main, __rt_exit ;
;----------------------------------------------------------------------------;
__rt_exit16 ; exit
;
; void __rt_exit16(int code);
; Terminate execution, optionally setting return code (ignored here).
; MUST NOT RETURN.
LDR r3, =_user_exit
LDR r3,[r3]
CMP r3, #0
BEQ loop_forever
BL call_via_r3_exit ;jump to user exit handler if present
loop_forever
MOV lr, pc
NOP
NOP
MOV pc, lr ;loop forever
call_via_r3_exit
BX r3
IF EnsureNoFPSupport = {FALSE}
fp_initialise
DCD |__fp_initialise|
fp_finalise
DCD |__fp_finalise|
ENDIF
ALIGN
CODE32
;----------------------------------------------------------------------------;
AREA |C$$code$$__divide|, CODE, READONLY, INTERWORK ;
; The code area containing __rt_sdiv, __rt_udiv, __rt_sdiv_10, __rt_udiv10 ;
;----------------------------------------------------------------------------;
; GENERIC ARM FUNCTIONS - divide and remainder. ;
; ;
; NOTES ;
; ;
; 1/ You may wish to make these functions part of your O/S kernel, replacing ;
; the implementations here by branches to the relevant entry addresses. ;
; ;
; 2/ Each divide function is a div-rem function, returning the quotient in ;
; r0 and the remainder in r1. Thus (r0, r1) -> (r0/r1, r0%r1). This is ;
; understood by the C compiler. ;
; ;
; 3/ Because of its importance in many applications, divide by 10 is treated ;
; as a special case. The C compiler recognises divide by 10 and generates ;
; calls to __rt_{u,s}div10, as appropriate. ;
; ;
; 4/ Each of the implementations below has been coded with smallness as a ;
; higher priority than speed. Unrolling the loops will allow faster ;
; execution, but will produce much larger code. If the speed of divides ;
; is critical then unrolled versions can be extracted from the ARM ANSI C ;
; Library. ;
; ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -