summaryrefslogtreecommitdiff
path: root/ocaml-binary-annot/asmrun/arm.S
diff options
context:
space:
mode:
Diffstat (limited to 'ocaml-binary-annot/asmrun/arm.S')
-rw-r--r--ocaml-binary-annot/asmrun/arm.S318
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