; penter_arm.s
;
; Time-stamp: <04/11/01 13:37:23 keuchel@netwave.de>

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; __penter is called at every function entry when a program is
; compiled with /Gh (enable hook function)
;
; The call from C is like this:
; Func()
; str       lr, [sp, #-4]!              ; dec stackp and store link reg
; bl        |__penter|
; ldr       lr, [sp], #4                ; load link reg and inc stackp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        export  |__penter|
        import  |__handle_penter|
        import  |__handle_return|

        area    |.text|, code

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Called on return of function by manipulating stack in __penter.

|__return| proc
        ; maybe too many regs?
        stmdb sp!,{r0-r12}
        ; this pops the original return address from a stack, returns in r0
        bl __handle_return
        mov lr, r0                      ; new return
        ldmia sp!, {r0-r12}
        mov pc, lr

        endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Function pointer

pf_return DCD __return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

|__penter| proc
        ; maybe too many regs?
        stmdb sp!,{r0-r12, lr}
        mov r0, lr                      ; return of penter
        sub r0, r0, #8                  ; return of penter - 2 ins = caller

        ldr r1, [sp, #56]               ; return of function
        ldr r2, pf_return               ; replace return with our code
        str r2, [sp, #56]

        ; r0 = caller
        ; r1 = return of caller
        ; this pushes the original return address in r1 on a stack
        bl __handle_penter
        ldmia sp!, {r0-r12, lr}
        mov pc, lr

        endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        end
