; Normal register names

r0              RN              0
r1              RN              1
r2              RN              2
r3              RN              3
r4              RN              4
r5              RN              5
r6              RN              6
r7              RN              7
r8              RN              8
r9              RN              9
r10             RN              10
r11             RN              11
r12             RN              12
r13             RN              13
r14             RN              14
r15             RN              15

; Alternate register names

a1              RN              0
a2              RN              1
a3              RN              2
a4              RN              3
v1              RN              4
v2              RN              5
v3              RN              6
v4              RN              7
v5              RN              8
v6              RN              9
sl              RN              10
fp              RN              11
ip              RN              12
sp              RN              13
lr              RN              14
pc              RN              15

V_bit           *               1 :SHL: 28

                IMPORT          |Image$$RO$$Base|
                IMPORT          |_Lib$Reloc$Off$DP|

                AREA            Veneer, REL, CODE, READONLY

                EXPORT          ABORT

AbortErrMsg     &               0
                =               "Aborted", 0
                ALIGN

ABORT           LDR             a1, SavedSPaddr
                DCD             |_Lib$Reloc$Off$DP| + &E24AC000  ; This is equivalent of 'SUB r12, r10, #0' + |_Lib$Reloc$Off$DP|
                LDR             ip, [ip, #4]
                ADD             a1, ip, a1
                LDR             sp, [a1]
                ADR             a1, AbortErrMsg
                B               wrapperX

                IMPORT          SavedSP
SavedSPaddr     &               SavedSP

; Call a C function
;
; R8  ==> Address of function to call
; R12 ==>

wrapper         STMFD           sp!, {r0-r9, sl, fp, ip, lr}  ; Store the input registers onto the stack

; Ensure SVC mode

                MOV             r5, pc
                ORR             r4, r5, #3
                TEQP            r4, #0
                MOV             r0, r0
                STMFD           sp!, {r4, r5, lr}

                MOV             sl, sp, LSR #20
                MOV             sl, sl, LSL #20  ; SP_LWM
                LDMIA           sl, {v1, v2}    ; save old reloc modifiers over fn call
                LDR             r12, [r12]      ; private word pointer
                LDMIB           r12, {fp, r12}  ; new relocation modifiers
                STMIA           sl, {fp, r12}   ; set by module init
                MOV             fp, #0          ; halt C backtrace here!

                DCD             |_Lib$Reloc$Off$DP| + &E28AA000  ; This is equivalent of 'ADD r10, r10, #0' + |_Lib$Reloc$Off$DP|

; Save the SP on entry

                DCD             |_Lib$Reloc$Off$DP| + &E24AC000  ; This is equivalent of 'SUB r12, r10, #0' + |_Lib$Reloc$Off$DP|

                LDR             ip, [ip, #4]
                LDR             a1, SavedSPaddr
                ADD             a1, ip, a1
                STR             sp, [a1]

                ADD             a1, sp, #4 * 3         ; Pass a pointer to the structure on the stack
                MOV             lr, pc
                MOV             pc, r8

wrapperX		DCD             |_Lib$Reloc$Off$DP| + &E24AA000  ; This is equivalent of 'SUB r10, r10, #0' + |_Lib$Reloc$Off$DP|

                STMIA           sl, {v1, v2}    ; restore old reloc modifiers

                LDMFD           sp!, {r4, r5, lr}
                TEQP            r5, #0
                MOV             r0, r0

                TEQ             a1, #0
                STRNE           a1, [sp]


                LDMFD           sp!, {r0-r9, sl, fp, ip, lr}  ; Get the stuff off the stack
                ORRNES          pc, lr, #V_bit
                BICS            pc, lr, #V_bit

; Veneer generates two labels, for example
;
; file          Veneer
;
; would create vec_file and xFiles_file 

                MACRO
$label          Veneer
                EXPORT         entry_$label
                IMPORT         xFiles_$label

entry_$label    STMFD          sp!, {r8-r12, lr}
                LDR            r8, =xFiles_$label
                BL             wrapper
                LDMFD          sp!, {r8-r12, lr}
                ORRVSS         pc, lr, #V_bit
                BICS           pc, lr, #V_bit

                LTORG
                MEND

Open            Veneer
GetBytes        Veneer
PutBytes        Veneer
Args            Veneer
Close           Veneer
File            Veneer
Func            Veneer

Ticker          Veneer
WriteBehind     Veneer


;;;                IMPORT         FileHook
;;;                EXPORT         RealFileHook
;;;
;;;RealFileHook    STMFD          sp!, {r8-r12, lr}
;;;                LDR            r8, =FileHook
;;;                BL             wrapper
;;;                LDMFD          sp!, {r8-r12, lr}
;;;                ORRVSS         pc, lr, #V_bit
;;;                BICS           pc, lr, #V_bit

                END
