diff options
Diffstat (limited to 'ocaml-binary-annot/asmrun/arm.S')
| -rw-r--r-- | ocaml-binary-annot/asmrun/arm.S | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/ocaml-binary-annot/asmrun/arm.S b/ocaml-binary-annot/asmrun/arm.S new file mode 100644 index 0000000000..8a47d182c9 --- /dev/null +++ b/ocaml-binary-annot/asmrun/arm.S @@ -0,0 +1,318 @@ +/***********************************************************************/ +/* */ +/* Objective Caml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1998 Institut National de Recherche en Informatique et */ +/* en Automatique. All rights reserved. This file is distributed */ +/* under the terms of the GNU Library General Public License, with */ +/* the special exception on linking described in file ../LICENSE. */ +/* */ +/***********************************************************************/ + +/* $Id$ */ + +/* Asm part of the runtime system, ARM processor */ + +trap_ptr .req r11 +alloc_ptr .req r8 +alloc_limit .req r10 + + .text + +/* Allocation functions and GC interface */ + + .globl caml_call_gc +caml_call_gc: + /* Record return address and desired size */ + /* Can use alloc_limit as a temporary since it will be reloaded by + invoke_gc */ + ldr alloc_limit, .Lcaml_last_return_address + str lr, [alloc_limit, #0] + ldr alloc_limit, .Lcaml_requested_size + str r12, [alloc_limit, #0] + /* Branch to shared GC code */ + bl .Linvoke_gc + /* Finish allocation */ + ldr r12, .Lcaml_requested_size + ldr r12, [r12, #0] + sub alloc_ptr, alloc_ptr, r12 + bx lr + + .globl caml_alloc1 +caml_alloc1: + sub alloc_ptr, alloc_ptr, #8 + cmp alloc_ptr, alloc_limit + movcs pc, lr /* Return if alloc_ptr >= alloc_limit */ + /* Record return address */ + ldr r12, .Lcaml_last_return_address + str lr, [r12, #0] + /* Invoke GC */ + bl .Linvoke_gc + /* Try again */ + b caml_alloc1 + + .globl caml_alloc2 +caml_alloc2: + sub alloc_ptr, alloc_ptr, #12 + cmp alloc_ptr, alloc_limit + movcs pc, lr /* Return if alloc_ptr >= alloc_limit */ + /* Record return address */ + ldr r12, .Lcaml_last_return_address + str lr, [r12, #0] + /* Invoke GC */ + bl .Linvoke_gc + /* Try again */ + b caml_alloc2 + + .globl caml_alloc3 +caml_alloc3: + sub alloc_ptr, alloc_ptr, #16 + cmp alloc_ptr, alloc_limit + movcs pc, lr /* Return if alloc_ptr >= alloc_limit */ + /* Record return address */ + ldr r12, .Lcaml_last_return_address + str lr, [r12, #0] + /* Invoke GC */ + bl .Linvoke_gc + /* Try again */ + b caml_alloc3 + + .globl caml_allocN +caml_allocN: + sub alloc_ptr, alloc_ptr, r12 + cmp alloc_ptr, alloc_limit + movcs pc, lr /* Return if alloc_ptr >= alloc_limit */ + /* Record return address and desired size */ + /* Can use alloc_limit as a temporary since it will be reloaded by + invoke_gc */ + ldr alloc_limit, .Lcaml_last_return_address + str lr, [alloc_limit, #0] + ldr alloc_limit, .Lcaml_requested_size + str r12, [alloc_limit, #0] + /* Invoke GC */ + bl .Linvoke_gc + /* Try again */ + ldr r12, .Lcaml_requested_size + ldr r12, [r12, #0] + b caml_allocN + +/* Shared code to invoke the GC */ +.Linvoke_gc: + /* Record lowest stack address */ + ldr r12, .Lcaml_bottom_of_stack + str sp, [r12, #0] + /* Save integer registers and return address on stack */ + stmfd sp!, {r0,r1,r2,r3,r4,r5,r6,r7,r12,lr} + /* Store pointer to saved integer registers in caml_gc_regs */ + ldr r12, .Lcaml_gc_regs + str sp, [r12, #0] + /* Save current allocation pointer for debugging purposes */ + ldr r12, .Lcaml_young_ptr + str alloc_ptr, [r12, #0] + /* Save trap pointer in case an exception is raised during GC */ + ldr r12, .Lcaml_exception_pointer + str trap_ptr, [r12, #0] + /* Call the garbage collector */ + bl caml_garbage_collection + /* Restore the registers from the stack */ + ldmfd sp!, {r0,r1,r2,r3,r4,r5,r6,r7,r12} + /* Reload return address */ + ldr r12, .Lcaml_last_return_address + ldr lr, [r12, #0] + /* Reload new allocation pointer and allocation limit */ + ldr r12, .Lcaml_young_ptr + ldr alloc_ptr, [r12, #0] + ldr r12, .Lcaml_young_limit + ldr alloc_limit, [r12, #0] + /* Return to caller */ + ldr r12, [sp], #4 + bx r12 + +/* Call a C function from Caml */ +/* Function to call is in r12 */ + + .globl caml_c_call +caml_c_call: + /* Preserve return address in callee-save register r4 */ + mov r4, lr + /* Record lowest stack address and return address */ + ldr r5, .Lcaml_last_return_address + ldr r6, .Lcaml_bottom_of_stack + str lr, [r5, #0] + str sp, [r6, #0] + /* Make the exception handler and alloc ptr available to the C code */ + ldr r6, .Lcaml_young_ptr + ldr r7, .Lcaml_exception_pointer + str alloc_ptr, [r6, #0] + str trap_ptr, [r7, #0] + /* Call the function */ + mov lr, pc + bx r12 + /* Reload alloc ptr and alloc limit */ + ldr r5, .Lcaml_young_limit + ldr alloc_ptr, [r6, #0] /* r6 still points to caml_young_ptr */ + ldr alloc_limit, [r5, #0] + /* Return */ + bx r4 + +/* Start the Caml program */ + + .globl caml_start_program +caml_start_program: + ldr r12, .Lcaml_program + +/* Code shared with caml_callback* */ +/* Address of Caml code to call is in r12 */ +/* Arguments to the Caml code are in r0...r3 */ + +.Ljump_to_caml: + /* Save return address and callee-save registers */ + stmfd sp!, {r4,r5,r6,r7,r8,r10,r11,lr} /* 8-alignment */ + /* Setup a callback link on the stack */ + sub sp, sp, #4*4 /* 8-alignment */ + ldr r4, .Lcaml_bottom_of_stack + ldr r4, [r4, #0] + str r4, [sp, #0] + ldr r4, .Lcaml_last_return_address + ldr r4, [r4, #0] + str r4, [sp, #4] + ldr r4, .Lcaml_gc_regs + ldr r4, [r4, #0] + str r4, [sp, #8] + /* Setup a trap frame to catch exceptions escaping the Caml code */ + sub sp, sp, #4*2 + ldr r4, .Lcaml_exception_pointer + ldr r4, [r4, #0] + str r4, [sp, #0] + ldr r4, .LLtrap_handler + str r4, [sp, #4] + mov trap_ptr, sp + /* Reload allocation pointers */ + ldr r4, .Lcaml_young_ptr + ldr alloc_ptr, [r4, #0] + ldr r4, .Lcaml_young_limit + ldr alloc_limit, [r4, #0] + /* Call the Caml code */ + mov lr, pc + bx r12 +.Lcaml_retaddr: + /* Pop the trap frame, restoring caml_exception_pointer */ + ldr r4, .Lcaml_exception_pointer + ldr r5, [sp, #0] + str r5, [r4, #0] + add sp, sp, #2 * 4 + /* Pop the callback link, restoring the global variables */ +.Lreturn_result: + ldr r4, .Lcaml_bottom_of_stack + ldr r5, [sp, #0] + str r5, [r4, #0] + ldr r4, .Lcaml_last_return_address + ldr r5, [sp, #4] + str r5, [r4, #0] + ldr r4, .Lcaml_gc_regs + ldr r5, [sp, #8] + str r5, [r4, #0] + add sp, sp, #4*4 + /* Update allocation pointer */ + ldr r4, .Lcaml_young_ptr + str alloc_ptr, [r4, #0] + /* Reload callee-save registers and return */ + ldmfd sp!, {r4,r5,r6,r7,r8,r10,r11,lr} + bx lr + + /* The trap handler */ +.Ltrap_handler: + /* Save exception pointer */ + ldr r4, .Lcaml_exception_pointer + str trap_ptr, [r4, #0] + /* Encode exception bucket as an exception result */ + orr r0, r0, #2 + /* Return it */ + b .Lreturn_result + +/* Raise an exception from C */ + + .globl caml_raise_exception +caml_raise_exception: + /* Reload Caml allocation pointers */ + ldr r12, .Lcaml_young_ptr + ldr alloc_ptr, [r12, #0] + ldr r12, .Lcaml_young_limit + ldr alloc_limit, [r12, #0] + /* Cut stack at current trap handler */ + ldr r12, .Lcaml_exception_pointer + ldr sp, [r12, #0] + /* Pop previous handler and addr of trap, and jump to it */ + ldmfd sp!, {trap_ptr, pc} + +/* Callback from C to Caml */ + + .globl caml_callback_exn +caml_callback_exn: + /* Initial shuffling of arguments (r0 = closure, r1 = first arg) */ + mov r12, r0 + mov r0, r1 /* r0 = first arg */ + mov r1, r12 /* r1 = closure environment */ + ldr r12, [r12, #0] /* code pointer */ + b .Ljump_to_caml + + .globl caml_callback2_exn +caml_callback2_exn: + /* Initial shuffling of arguments (r0 = closure, r1 = arg1, r2 = arg2) */ + mov r12, r0 + mov r0, r1 /* r0 = first arg */ + mov r1, r2 /* r1 = second arg */ + mov r2, r12 /* r2 = closure environment */ + ldr r12, .Lcaml_apply2 + b .Ljump_to_caml + + .globl caml_callback3_exn +caml_callback3_exn: + /* Initial shuffling of arguments */ + /* (r0 = closure, r1 = arg1, r2 = arg2, r3 = arg3) */ + mov r12, r0 + mov r0, r1 /* r0 = first arg */ + mov r1, r2 /* r1 = second arg */ + mov r2, r3 /* r2 = third arg */ + mov r3, r12 /* r3 = closure environment */ + ldr r12, .Lcaml_apply3 + b .Ljump_to_caml + + .globl caml_ml_array_bound_error +caml_ml_array_bound_error: + /* Load address of [caml_array_bound_error] in r12 */ + ldr r12, .Lcaml_array_bound_error + /* Call that function */ + b caml_c_call + +/* Global references */ + +.Lcaml_last_return_address: .word caml_last_return_address +.Lcaml_bottom_of_stack: .word caml_bottom_of_stack +.Lcaml_gc_regs: .word caml_gc_regs +.Lcaml_young_ptr: .word caml_young_ptr +.Lcaml_young_limit: .word caml_young_limit +.Lcaml_exception_pointer: .word caml_exception_pointer +.Lcaml_program: .word caml_program +.LLtrap_handler: .word .Ltrap_handler +.Lcaml_apply2: .word caml_apply2 +.Lcaml_apply3: .word caml_apply3 +.Lcaml_array_bound_error: .word caml_array_bound_error +.Lcaml_requested_size: .word caml_requested_size + + .data +caml_requested_size: + .word 0 + +/* GC roots for callback */ + + .data + .globl caml_system__frametable +caml_system__frametable: + .word 1 /* one descriptor */ + .word .Lcaml_retaddr /* return address into callback */ + .short -1 /* negative frame size => use callback link */ + .short 0 /* no roots */ + .align 2 |
