ocaml/asmrun/s390x.S

359 lines
12 KiB
ArmAsm

/**************************************************************************/
/* */
/* OCaml */
/* */
/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */
/* Bill O'Farrell, IBM */
/* */
/* Copyright 2015 Institut National de Recherche en Informatique et */
/* en Automatique. */
/* Copyright 2015 IBM (Bill O'Farrell with help from Tristan Amini). */
/* */
/* All rights reserved. This file is distributed under the terms of */
/* the GNU Lesser General Public License version 2.1, with the */
/* special exception on linking described in the file LICENSE. */
/* */
/**************************************************************************/
#define Addrglobal(reg,glob) \
larl reg, glob
#define Loadglobal(reg,glob) \
lgrl reg, glob
#define Storeglobal(reg,glob) \
stgrl reg, glob
#define Loadglobal32(reg,glob) \
lgfrl reg, glob
#define Storeglobal32(reg,glob) \
strl reg, glob
.section ".text"
/* Invoke the garbage collector. */
.globl caml_system__code_begin
caml_system__code_begin:
.globl caml_call_gc
.type caml_call_gc, @function
caml_call_gc:
/* Set up stack frame */
#define FRAMESIZE (16*8 + 16*8)
lay %r15, -FRAMESIZE(%r15)
/* Record return address into OCaml code */
Storeglobal(%r14, caml_last_return_address)
/* Record lowest stack address */
lay %r0, FRAMESIZE(%r15)
Storeglobal(%r0, caml_bottom_of_stack)
/* Record pointer to register array */
lay %r0, (8*16)(%r15)
Storeglobal(%r0, caml_gc_regs)
/* Save current allocation pointer for debugging purposes */
Storeglobal(%r11, caml_young_ptr)
/* Save exception pointer (if e.g. a sighandler raises) */
Storeglobal(%r13, caml_exception_pointer)
/* Save all registers used by the code generator */
stmg %r2,%r9, (8*16)(%r15)
stg %r12, (8*16 + 8*8)(%r15)
std %f0, 0(%r15)
std %f1, 8(%r15)
std %f2, 16(%r15)
std %f3, 24(%r15)
std %f4, 32(%r15)
std %f5, 40(%r15)
std %f6, 48(%r15)
std %f7, 56(%r15)
std %f8, 64(%r15)
std %f9, 72(%r15)
std %f10, 80(%r15)
std %f11, 88(%r15)
std %f12, 96(%r15)
std %f13, 108(%r15)
std %f14, 112(%r15)
std %f15, 120(%r15)
/* Call the GC */
lay %r15, -160(%r15)
stg %r15, 0(%r15)
brasl %r14, caml_garbage_collection@PLT
lay %r15, 160(%r15)
/* Reload new allocation pointer and allocation limit */
Loadglobal(%r11, caml_young_ptr)
Loadglobal(%r10, caml_young_limit)
/* Restore all regs used by the code generator */
lmg %r2,%r9, (8*16)(%r15)
lg %r12, (8*16 + 8*8)(%r15)
ld %f0, 0(%r15)
ld %f1, 8(%r15)
ld %f2, 16(%r15)
ld %f3, 24(%r15)
ld %f4, 32(%r15)
ld %f5, 40(%r15)
ld %f6, 48(%r15)
ld %f7, 56(%r15)
ld %f8, 64(%r15)
ld %f9, 72(%r15)
ld %f10, 80(%r15)
ld %f11, 88(%r15)
ld %f12, 96(%r15)
ld %f13, 108(%r15)
ld %f14, 112(%r15)
ld %f15, 120(%r15)
/* Return to caller */
Loadglobal(%r1, caml_last_return_address)
/* Deallocate stack frame */
lay %r15, FRAMESIZE(%r15)
/* Return */
br %r1
/* Call a C function from OCaml */
.globl caml_c_call
.type caml_c_call, @function
caml_c_call:
Storeglobal(%r15, caml_bottom_of_stack)
/* Save return address */
ldgr %f15, %r14
/* Get ready to call C function (address in r7) */
/* Record lowest stack address and return address */
Storeglobal(%r14, caml_last_return_address)
/* Make the exception handler and alloc ptr available to the C code */
Storeglobal(%r11, caml_young_ptr)
Storeglobal(%r13, caml_exception_pointer)
/* Call the function */
basr %r14, %r7
/* restore return address */
lgdr %r14,%f15
/* Reload allocation pointer and allocation limit*/
Loadglobal(%r11, caml_young_ptr)
Loadglobal(%r10, caml_young_limit)
/* Say we are back into OCaml code */
lgfi %r0, 0
Storeglobal(%r0, caml_last_return_address)
/* Return to caller */
br %r14
/* Raise an exception from OCaml */
.globl caml_raise_exn
.type caml_raise_exn, @function
caml_raise_exn:
Loadglobal32(%r0, caml_backtrace_active)
cgfi %r0, 0
jne .L110
.L111:
/* Pop trap frame */
lg %r1, 0(%r13)
lgr %r15, %r13
lg %r13, 8(13)
agfi %r15, 16
/* Branch to handler */
br %r1
.L110:
lgfi %r0, 0
Storeglobal32(%r0, caml_backtrace_pos)
.L114:
ldgr %f15, %r2 /* preserve exn bucket in callee-save reg */
/* arg1: exception bucket, already in r3 */
lgr %r3,%r14 /* arg2: PC of raise */
lgr %r4, %r15 /* arg3: SP of raise */
lgr %r5, %r13 /* arg4: SP of handler */
agfi %r15, -160 /* reserve stack space for C call */
brasl %r14, caml_stash_backtrace@PLT
agfi %r15, 160
lgdr %r2,%f15 /* restore exn bucket */
j .L111 /* raise the exn */
.globl caml_reraise_exn
.type caml_reraise_exn, @function
caml_reraise_exn:
Loadglobal32(%r0, caml_backtrace_active)
cgfi %r0, 0
jne .L114
/* Pop trap frame */
lg %r1, 0(%r13)
lgr %r15, %r13
lg %r13, 8(%r13)
agfi %r15, 16
/* Branch to handler */
br %r1;
/* Raise an exception from C */
.globl caml_raise_exception
.type caml_raise_exception, @function
caml_raise_exception:
Loadglobal32(0, caml_backtrace_active)
cgfi %r0, 0
jne .L112
.L113:
/* Reload OCaml global registers */
Loadglobal(%r15, caml_exception_pointer)
Loadglobal(%r11, caml_young_ptr)
Loadglobal(%r10, caml_young_limit)
/* Say we are back into OCaml code */
lgfi %r0, 0
Storeglobal(%r0, caml_last_return_address)
/* Pop trap frame */
lg %r1, 0(%r15)
lg %r13, 8(%r15)
agfi %r15, 16
/* Branch to handler */
br %r1;
.L112:
ldgr %f15,%r2 /* preserve exn bucket in callee-save reg */
/* arg1: exception bucket, already in r2 */
Loadglobal(%r3, caml_last_return_address) /* arg2: PC of raise */
Loadglobal(%r4, caml_bottom_of_stack) /* arg3: SP of raise */
Loadglobal(%r5, caml_exception_pointer) /* arg4: SP of handler */
/* reserve stack space for C call */
lay %r15, -160(%r15)
brasl %r14, caml_stash_backtrace@PLT
lay %r15, 160(%r15)
lgdr %r2,%f15 /* restore exn bucket */
j .L113 /* raise the exn */
/* Start the OCaml program */
.globl caml_start_program
.type caml_start_program, @function
caml_start_program:
Addrglobal(%r0, caml_program)
/* Code shared between caml_start_program and caml_callback */
.L102:
/* Allocate stack frame */
lay %r15, -144(%r15)
/* Save all callee-save registers + return address */
/* GPR 6..14 at sp + 0 ... sp + 64
FPR 10..15 at sp + 72 ... sp + 128 */
stmg %r6,%r14, 0(%r15)
std %f8, 72(%r15)
std %f9, 80(%r15)
std %f10, 88(%r15)
std %f11, 96(%r15)
std %f12, 104(%r15)
std %f13, 112(%r15)
std %f14, 120(%r15)
std %f15, 128(%r15)
/* Set up a callback link */
lay %r15, -32(%r15)
Loadglobal(%r1, caml_bottom_of_stack)
stg %r1, 0(%r15)
Loadglobal(%r1, caml_last_return_address)
stg %r1, 8(%r15)
Loadglobal(%r1, caml_gc_regs)
stg %r1, 16(%r15)
/* Build an exception handler to catch exceptions escaping out of OCaml */
brasl %r14, .L103
j .L104
.L103:
lay %r15, -16(%r15)
stg %r14, 0(%r15)
Loadglobal(%r1, caml_exception_pointer)
stg %r1, 8(%r15)
lgr %r13, %r15
/* Reload allocation pointers */
Loadglobal(%r11, caml_young_ptr)
Loadglobal(%r10, caml_young_limit)
/* Call the OCaml code */
lgr %r1,%r0
basr %r14, %r1
.L105:
/* Pop the trap frame, restoring caml_exception_pointer */
lg %r0, 8(%r15)
Storeglobal(%r0, caml_exception_pointer)
la %r15, 16(%r15)
/* Pop the callback link, restoring the global variables */
.L106:
lg %r5, 0(%r15)
lg %r6, 8(%r15)
lg %r1, 16(%r15)
Storeglobal(%r5, caml_bottom_of_stack)
Storeglobal(%r6, caml_last_return_address)
Storeglobal(%r1, caml_gc_regs)
la %r15, 32(%r15)
/* Update allocation pointer */
Storeglobal(%r11, caml_young_ptr)
/* Restore registers */
lmg %r6,%r14, 0(%r15)
ld %f8, 72(%r15)
ld %f9, 80(%r15)
ld %f10, 88(%r15)
ld %f11, 96(%r15)
ld %f12, 104(%r15)
ld %f13, 112(%r15)
ld %f14, 120(%r15)
ld %f15, 128(%r15)
/* Return */
lay %r15, 144(%r15)
br %r14
/* The trap handler: */
.L104:
/* Update caml_exception_pointer */
Storeglobal(%r13, caml_exception_pointer)
/* Encode exception bucket as an exception result and return it */
oill %r2, 2
j .L106
/* Callback from C to OCaml */
.globl caml_callback_exn
.type caml_callback_exn, @function
caml_callback_exn:
/* Initial shuffling of arguments */
lgr %r0, %r2 /* Closure */
lgr %r2, %r3 /* Argument */
lgr %r3, %r0
lg %r0, 0(%r3) /* Code pointer */
j .L102
.globl caml_callback2_exn
.type caml_callback2_exn, @function
caml_callback2_exn:
lgr %r0, %r2 /* Closure */
lgr %r2, %r3 /* First argument */
lgr %r3, %r4 /* Second argument */
lgr %r4, %r0
Addrglobal(%r0, caml_apply2)
j .L102
.globl caml_callback3_exn
.type caml_callback3_exn, @function
caml_callback3_exn:
lgr %r0, %r2 /* Closure */
lgr %r2, %r3 /* First argument */
lgr %r3, %r4 /* Second argument */
lgr %r4, %r5 /* Third argument */
lgr %r5, %r0
Addrglobal(%r0, caml_apply3)
j .L102
.globl caml_ml_array_bound_error
.type caml_ml_array_bound_error, @function
caml_ml_array_bound_error:
lay %r15, -160(%r15) /* Reserve stack space for C call */
larl %r7, caml_array_bound_error
j caml_c_call
.globl caml_system__code_end
caml_system__code_end:
/* Frame table */
.section ".data"
.align 8
.globl caml_system__frametable
.type caml_system__frametable, @object
caml_system__frametable:
.quad 1 /* one descriptor */
.quad .L105 /* return address into callback */
.short -1 /* negative size count => use callback link */
.short 0 /* no roots here */
.align 8
/* Mark stack as non-executable */
.section .note.GNU-stack,"",%progbits