698 lines
21 KiB
ArmAsm
698 lines
21 KiB
ArmAsm
/**************************************************************************/
|
|
/* */
|
|
/* OCaml */
|
|
/* */
|
|
/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
|
|
/* */
|
|
/* Copyright 1996 Institut National de Recherche en Informatique et */
|
|
/* en Automatique. */
|
|
/* */
|
|
/* 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. */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
#if defined(MODEL_ppc64le)
|
|
.abiversion 2
|
|
#endif
|
|
|
|
#if defined(MODEL_ppc64) || defined(MODEL_ppc64le)
|
|
#define EITHER(a,b) b
|
|
#else
|
|
#define EITHER(a,b) a
|
|
#endif
|
|
|
|
#define WORD EITHER(4,8)
|
|
#define lg EITHER(lwz,ld)
|
|
#define lgu EITHER(lwzu,ldu)
|
|
#define stg EITHER(stw,std)
|
|
#define stgu EITHER(stwu,stdu)
|
|
#define datag EITHER(.long,.quad)
|
|
#define wordalign EITHER(2,3)
|
|
|
|
/* Stack layout */
|
|
#if defined(MODEL_ppc)
|
|
#define RESERVED_STACK 16
|
|
#define PARAM_SAVE_AREA 0
|
|
#define LR_SAVE 4
|
|
#define TRAP_SIZE 16
|
|
#define TRAP_HANDLER_OFFSET 0
|
|
#define TRAP_PREVIOUS_OFFSET 4
|
|
#define CALLBACK_LINK_SIZE 16
|
|
#define CALLBACK_LINK_OFFSET 0
|
|
#endif
|
|
#if defined(MODEL_ppc64)
|
|
#define RESERVED_STACK 48
|
|
#define PARAM_SAVE_AREA (8*8)
|
|
#define LR_SAVE 16
|
|
#define TOC_SAVE 40
|
|
#define TOC_SAVE_PARENT 8
|
|
#define TRAP_SIZE 32
|
|
#define TRAP_HANDLER_OFFSET 56
|
|
#define TRAP_PREVIOUS_OFFSET 64
|
|
#define CALLBACK_LINK_SIZE 32
|
|
#define CALLBACK_LINK_OFFSET 48
|
|
#endif
|
|
#if defined(MODEL_ppc64le)
|
|
#define RESERVED_STACK 32
|
|
#define PARAM_SAVE_AREA 0
|
|
#define LR_SAVE 16
|
|
#define TOC_SAVE_PARENT 8
|
|
#define TOC_SAVE 24
|
|
#define TRAP_SIZE 32
|
|
#define TRAP_HANDLER_OFFSET 40
|
|
#define TRAP_PREVIOUS_OFFSET 48
|
|
#define CALLBACK_LINK_SIZE 32
|
|
#define CALLBACK_LINK_OFFSET 32
|
|
#endif
|
|
|
|
/* Function definitions */
|
|
|
|
#if defined(MODEL_ppc)
|
|
#define FUNCTION(name) \
|
|
.section ".text"; \
|
|
.globl name; \
|
|
.type name, @function; \
|
|
.align 2; \
|
|
name:
|
|
|
|
#define ENDFUNCTION(name) \
|
|
.size name, . - name
|
|
|
|
#endif
|
|
|
|
#if defined(MODEL_ppc64)
|
|
#define FUNCTION(name) \
|
|
.section ".opd","aw"; \
|
|
.align 3; \
|
|
.globl name; \
|
|
.type name, @function; \
|
|
name: .quad .L.name,.TOC.@tocbase; \
|
|
.text; \
|
|
.align 2; \
|
|
.L.name:
|
|
|
|
#define ENDFUNCTION(name) \
|
|
.size name, . - .L.name
|
|
|
|
#endif
|
|
|
|
#if defined(MODEL_ppc64le)
|
|
#define FUNCTION(name) \
|
|
.section ".text"; \
|
|
.globl name; \
|
|
.type name, @function; \
|
|
.align 2; \
|
|
name: ; \
|
|
0: addis 2, 12, (.TOC. - 0b)@ha; \
|
|
addi 2, 2, (.TOC. - 0b)@l; \
|
|
.localentry name, . - 0b
|
|
|
|
#define ENDFUNCTION(name) \
|
|
.size name, . - name
|
|
|
|
#endif
|
|
|
|
/* Accessing global variables. */
|
|
|
|
#if defined(MODEL_ppc)
|
|
|
|
#define Addrglobal(reg,glob) \
|
|
addis reg, 0, glob@ha; \
|
|
addi reg, reg, glob@l
|
|
#define Loadglobal(reg,glob,tmp) \
|
|
addis tmp, 0, glob@ha; \
|
|
lg reg, glob@l(tmp)
|
|
#define Storeglobal(reg,glob,tmp) \
|
|
addis tmp, 0, glob@ha; \
|
|
stg reg, glob@l(tmp)
|
|
#define Loadglobal32(reg,glob,tmp) \
|
|
addis tmp, 0, glob@ha; \
|
|
lwz reg, glob@l(tmp)
|
|
#define Storeglobal32(reg,glob,tmp) \
|
|
addis tmp, 0, glob@ha; \
|
|
stw reg, glob@l(tmp)
|
|
|
|
#endif
|
|
|
|
#if defined(MODEL_ppc64) || defined(MODEL_ppc64le)
|
|
|
|
#define LSYMB(glob) .L##glob
|
|
|
|
#define Addrglobal(reg,glob) \
|
|
ld reg, LSYMB(glob)@toc(2)
|
|
#define Loadglobal(reg,glob,tmp) \
|
|
Addrglobal(tmp,glob); \
|
|
lg reg, 0(tmp)
|
|
#define Storeglobal(reg,glob,tmp) \
|
|
Addrglobal(tmp,glob); \
|
|
stg reg, 0(tmp)
|
|
#define Loadglobal32(reg,glob,tmp) \
|
|
Addrglobal(tmp,glob); \
|
|
lwz reg, 0(tmp)
|
|
#define Storeglobal32(reg,glob,tmp) \
|
|
Addrglobal(tmp,glob); \
|
|
stw reg, 0(tmp)
|
|
|
|
#endif
|
|
|
|
#if defined(MODEL_ppc64)
|
|
.section ".opd","aw"
|
|
#else
|
|
.section ".text"
|
|
#endif
|
|
.globl caml_system__code_begin
|
|
caml_system__code_begin:
|
|
|
|
/* Invoke the garbage collector. */
|
|
|
|
FUNCTION(caml_call_gc)
|
|
#define STACKSIZE (WORD*32 + 8*32 + PARAM_SAVE_AREA + RESERVED_STACK)
|
|
/* 32 integer registers + 32 float registers + space for C call */
|
|
/* Set up stack frame */
|
|
stwu 1, -STACKSIZE(1)
|
|
/* Record return address into OCaml code */
|
|
mflr 0
|
|
Storeglobal(0, caml_last_return_address, 11)
|
|
/* Record lowest stack address */
|
|
addi 0, 1, STACKSIZE
|
|
Storeglobal(0, caml_bottom_of_stack, 11)
|
|
/* Record pointer to register array */
|
|
addi 0, 1, 8*32 + PARAM_SAVE_AREA + RESERVED_STACK
|
|
Storeglobal(0, caml_gc_regs, 11)
|
|
/* Save current allocation pointer for debugging purposes */
|
|
Storeglobal(31, caml_young_ptr, 11)
|
|
/* Save exception pointer (if e.g. a sighandler raises) */
|
|
Storeglobal(29, caml_exception_pointer, 11)
|
|
/* Save all registers used by the code generator */
|
|
addi 11, 1, 8*32 + PARAM_SAVE_AREA + RESERVED_STACK - WORD
|
|
stgu 3, WORD(11)
|
|
stgu 4, WORD(11)
|
|
stgu 5, WORD(11)
|
|
stgu 6, WORD(11)
|
|
stgu 7, WORD(11)
|
|
stgu 8, WORD(11)
|
|
stgu 9, WORD(11)
|
|
stgu 10, WORD(11)
|
|
stgu 14, WORD(11)
|
|
stgu 15, WORD(11)
|
|
stgu 16, WORD(11)
|
|
stgu 17, WORD(11)
|
|
stgu 18, WORD(11)
|
|
stgu 19, WORD(11)
|
|
stgu 20, WORD(11)
|
|
stgu 21, WORD(11)
|
|
stgu 22, WORD(11)
|
|
stgu 23, WORD(11)
|
|
stgu 24, WORD(11)
|
|
stgu 25, WORD(11)
|
|
stgu 26, WORD(11)
|
|
stgu 27, WORD(11)
|
|
stgu 28, WORD(11)
|
|
addi 11, 1, PARAM_SAVE_AREA + RESERVED_STACK - 8
|
|
stfdu 1, 8(11)
|
|
stfdu 2, 8(11)
|
|
stfdu 3, 8(11)
|
|
stfdu 4, 8(11)
|
|
stfdu 5, 8(11)
|
|
stfdu 6, 8(11)
|
|
stfdu 7, 8(11)
|
|
stfdu 8, 8(11)
|
|
stfdu 9, 8(11)
|
|
stfdu 10, 8(11)
|
|
stfdu 11, 8(11)
|
|
stfdu 12, 8(11)
|
|
stfdu 13, 8(11)
|
|
stfdu 14, 8(11)
|
|
stfdu 15, 8(11)
|
|
stfdu 16, 8(11)
|
|
stfdu 17, 8(11)
|
|
stfdu 18, 8(11)
|
|
stfdu 19, 8(11)
|
|
stfdu 20, 8(11)
|
|
stfdu 21, 8(11)
|
|
stfdu 22, 8(11)
|
|
stfdu 23, 8(11)
|
|
stfdu 24, 8(11)
|
|
stfdu 25, 8(11)
|
|
stfdu 26, 8(11)
|
|
stfdu 27, 8(11)
|
|
stfdu 28, 8(11)
|
|
stfdu 29, 8(11)
|
|
stfdu 30, 8(11)
|
|
stfdu 31, 8(11)
|
|
/* Call the GC */
|
|
bl caml_garbage_collection
|
|
#if defined(MODEL_ppc64) || defined(MODEL_ppc64le)
|
|
nop
|
|
#endif
|
|
/* Reload new allocation pointer and allocation limit */
|
|
Loadglobal(31, caml_young_ptr, 11)
|
|
Loadglobal(30, caml_young_limit, 11)
|
|
/* Restore all regs used by the code generator */
|
|
addi 11, 1, 8*32 + PARAM_SAVE_AREA + RESERVED_STACK - WORD
|
|
lgu 3, WORD(11)
|
|
lgu 4, WORD(11)
|
|
lgu 5, WORD(11)
|
|
lgu 6, WORD(11)
|
|
lgu 7, WORD(11)
|
|
lgu 8, WORD(11)
|
|
lgu 9, WORD(11)
|
|
lgu 10, WORD(11)
|
|
lgu 14, WORD(11)
|
|
lgu 15, WORD(11)
|
|
lgu 16, WORD(11)
|
|
lgu 17, WORD(11)
|
|
lgu 18, WORD(11)
|
|
lgu 19, WORD(11)
|
|
lgu 20, WORD(11)
|
|
lgu 21, WORD(11)
|
|
lgu 22, WORD(11)
|
|
lgu 23, WORD(11)
|
|
lgu 24, WORD(11)
|
|
lgu 25, WORD(11)
|
|
lgu 26, WORD(11)
|
|
lgu 27, WORD(11)
|
|
lgu 28, WORD(11)
|
|
addi 11, 1, PARAM_SAVE_AREA + RESERVED_STACK - 8
|
|
lfdu 1, 8(11)
|
|
lfdu 2, 8(11)
|
|
lfdu 3, 8(11)
|
|
lfdu 4, 8(11)
|
|
lfdu 5, 8(11)
|
|
lfdu 6, 8(11)
|
|
lfdu 7, 8(11)
|
|
lfdu 8, 8(11)
|
|
lfdu 9, 8(11)
|
|
lfdu 10, 8(11)
|
|
lfdu 11, 8(11)
|
|
lfdu 12, 8(11)
|
|
lfdu 13, 8(11)
|
|
lfdu 14, 8(11)
|
|
lfdu 15, 8(11)
|
|
lfdu 16, 8(11)
|
|
lfdu 17, 8(11)
|
|
lfdu 18, 8(11)
|
|
lfdu 19, 8(11)
|
|
lfdu 20, 8(11)
|
|
lfdu 21, 8(11)
|
|
lfdu 22, 8(11)
|
|
lfdu 23, 8(11)
|
|
lfdu 24, 8(11)
|
|
lfdu 25, 8(11)
|
|
lfdu 26, 8(11)
|
|
lfdu 27, 8(11)
|
|
lfdu 28, 8(11)
|
|
lfdu 29, 8(11)
|
|
lfdu 30, 8(11)
|
|
lfdu 31, 8(11)
|
|
/* Return to caller, restarting the allocation */
|
|
Loadglobal(11, caml_last_return_address, 11)
|
|
addi 11, 11, -16 /* Restart the allocation (4 instructions) */
|
|
mtlr 11
|
|
/* For PPC64: restore the TOC that the caller saved at the usual place */
|
|
#ifdef TOC_SAVE
|
|
ld 2, (STACKSIZE + TOC_SAVE)(1)
|
|
#endif
|
|
/* Deallocate stack frame */
|
|
addi 1, 1, STACKSIZE
|
|
blr
|
|
#undef STACKSIZE
|
|
ENDFUNCTION(caml_call_gc)
|
|
|
|
/* Call a C function from OCaml */
|
|
|
|
FUNCTION(caml_c_call)
|
|
.cfi_startproc
|
|
/* Save return address in a callee-save register */
|
|
mflr 27
|
|
.cfi_register 65, 27
|
|
/* Record lowest stack address and return address */
|
|
Storeglobal(1, caml_bottom_of_stack, 11)
|
|
Storeglobal(27, caml_last_return_address, 11)
|
|
/* Make the exception handler and alloc ptr available to the C code */
|
|
Storeglobal(31, caml_young_ptr, 11)
|
|
Storeglobal(29, caml_exception_pointer, 11)
|
|
/* Call C function (address in r28) */
|
|
#if defined(MODEL_ppc)
|
|
mtctr 28
|
|
bctrl
|
|
#elif defined(MODEL_ppc64)
|
|
ld 0, 0(28)
|
|
mr 26, 2 /* save current TOC in a callee-save register */
|
|
mtctr 0
|
|
ld 2, 8(28)
|
|
bctrl
|
|
mr 2, 26 /* restore current TOC */
|
|
#elif defined(MODEL_ppc64le)
|
|
mtctr 28
|
|
mr 12, 28
|
|
mr 26, 2 /* save current TOC in a callee-save register */
|
|
bctrl
|
|
mr 2, 26 /* restore current TOC */
|
|
#else
|
|
#error "wrong MODEL"
|
|
#endif
|
|
/* Restore return address (in 27, preserved by the C function) */
|
|
mtlr 27
|
|
/* Reload allocation pointer and allocation limit*/
|
|
Loadglobal(31, caml_young_ptr, 11)
|
|
Loadglobal(30, caml_young_limit, 11)
|
|
/* Return to caller */
|
|
blr
|
|
.cfi_endproc
|
|
ENDFUNCTION(caml_c_call)
|
|
|
|
/* Raise an exception from OCaml */
|
|
|
|
FUNCTION(caml_raise_exn)
|
|
Loadglobal32(0, caml_backtrace_active, 11)
|
|
cmpwi 0, 0
|
|
bne .L111
|
|
.L110:
|
|
/* Pop trap frame */
|
|
lg 0, TRAP_HANDLER_OFFSET(29)
|
|
mr 1, 29
|
|
mtctr 0
|
|
lg 29, TRAP_PREVIOUS_OFFSET(1)
|
|
addi 1, 1, TRAP_SIZE
|
|
/* Branch to handler */
|
|
bctr
|
|
.L111:
|
|
li 0, 0
|
|
Storeglobal32(0, caml_backtrace_pos, 11)
|
|
.L112:
|
|
mr 28, 3 /* preserve exn bucket in callee-save reg */
|
|
/* arg1: exception bucket, already in r3 */
|
|
mflr 4 /* arg2: PC of raise */
|
|
mr 5, 1 /* arg3: SP of raise */
|
|
mr 6, 29 /* arg4: SP of handler */
|
|
addi 1, 1, -(PARAM_SAVE_AREA + RESERVED_STACK)
|
|
/* reserve stack space for C call */
|
|
bl caml_stash_backtrace
|
|
#if defined(MODEL_ppc64) || defined(MODEL_ppc64le)
|
|
nop
|
|
#endif
|
|
mr 3, 28 /* restore exn bucket */
|
|
b .L110 /* raise the exn */
|
|
ENDFUNCTION(caml_raise_exn)
|
|
|
|
FUNCTION(caml_reraise_exn)
|
|
Loadglobal32(0, caml_backtrace_active, 11)
|
|
cmpwi 0, 0
|
|
bne- .L112
|
|
/* Pop trap frame */
|
|
lg 0, TRAP_HANDLER_OFFSET(29)
|
|
mr 1, 29
|
|
mtctr 0
|
|
lg 29, TRAP_PREVIOUS_OFFSET(1)
|
|
addi 1, 1, TRAP_SIZE
|
|
/* Branch to handler */
|
|
bctr
|
|
ENDFUNCTION(caml_reraise_exn)
|
|
|
|
/* Raise an exception from C */
|
|
|
|
FUNCTION(caml_raise_exception)
|
|
Loadglobal32(0, caml_backtrace_active, 11)
|
|
cmpwi 0, 0
|
|
bne .L121
|
|
.L120:
|
|
/* Reload OCaml global registers */
|
|
Loadglobal(1, caml_exception_pointer, 11)
|
|
Loadglobal(31, caml_young_ptr, 11)
|
|
Loadglobal(30, caml_young_limit, 11)
|
|
/* Pop trap frame */
|
|
lg 0, TRAP_HANDLER_OFFSET(1)
|
|
mtctr 0
|
|
lg 29, TRAP_PREVIOUS_OFFSET(1)
|
|
addi 1, 1, TRAP_SIZE
|
|
/* Branch to handler */
|
|
bctr
|
|
.L121:
|
|
li 0, 0
|
|
Storeglobal32(0, caml_backtrace_pos, 11)
|
|
mr 28, 3 /* preserve exn bucket in callee-save reg */
|
|
/* arg1: exception bucket, already in r3 */
|
|
Loadglobal(4, caml_last_return_address, 11) /* arg2: PC of raise */
|
|
Loadglobal(5, caml_bottom_of_stack, 11) /* arg3: SP of raise */
|
|
Loadglobal(6, caml_exception_pointer, 11) /* arg4: SP of handler */
|
|
addi 1, 1, -(PARAM_SAVE_AREA + RESERVED_STACK)
|
|
/* reserve stack space for C call */
|
|
bl caml_stash_backtrace
|
|
#if defined(MODEL_ppc64) || defined(MODEL_ppc64le)
|
|
nop
|
|
#endif
|
|
mr 3, 28 /* restore exn bucket */
|
|
b .L120 /* raise the exn */
|
|
ENDFUNCTION(caml_raise_exception)
|
|
|
|
/* Start the OCaml program */
|
|
|
|
FUNCTION(caml_start_program)
|
|
.cfi_startproc
|
|
#define STACKSIZE (WORD*18 + 8*18 + CALLBACK_LINK_SIZE + RESERVED_STACK)
|
|
/* 18 callee-save GPR14...GPR31 + 18 callee-save FPR14...FPR31 */
|
|
Addrglobal(12, caml_program)
|
|
/* Code shared between caml_start_program and caml_callback */
|
|
.L102:
|
|
/* Allocate and link stack frame */
|
|
stgu 1, -STACKSIZE(1)
|
|
.cfi_adjust_cfa_offset STACKSIZE
|
|
/* Save return address */
|
|
mflr 0
|
|
stg 0, (STACKSIZE + LR_SAVE)(1)
|
|
.cfi_offset 65, LR_SAVE
|
|
/* Save TOC pointer if applicable */
|
|
#ifdef TOC_SAVE_PARENT
|
|
std 2, (STACKSIZE + TOC_SAVE_PARENT)(1)
|
|
#endif
|
|
/* Save all callee-save registers */
|
|
addi 11, 1, CALLBACK_LINK_SIZE + RESERVED_STACK - WORD
|
|
stgu 14, WORD(11)
|
|
stgu 15, WORD(11)
|
|
stgu 16, WORD(11)
|
|
stgu 17, WORD(11)
|
|
stgu 18, WORD(11)
|
|
stgu 19, WORD(11)
|
|
stgu 20, WORD(11)
|
|
stgu 21, WORD(11)
|
|
stgu 22, WORD(11)
|
|
stgu 23, WORD(11)
|
|
stgu 24, WORD(11)
|
|
stgu 25, WORD(11)
|
|
stgu 26, WORD(11)
|
|
stgu 27, WORD(11)
|
|
stgu 28, WORD(11)
|
|
stgu 29, WORD(11)
|
|
stgu 30, WORD(11)
|
|
stgu 31, WORD(11)
|
|
stfdu 14, 8(11)
|
|
stfdu 15, 8(11)
|
|
stfdu 16, 8(11)
|
|
stfdu 17, 8(11)
|
|
stfdu 18, 8(11)
|
|
stfdu 19, 8(11)
|
|
stfdu 20, 8(11)
|
|
stfdu 21, 8(11)
|
|
stfdu 22, 8(11)
|
|
stfdu 23, 8(11)
|
|
stfdu 24, 8(11)
|
|
stfdu 25, 8(11)
|
|
stfdu 26, 8(11)
|
|
stfdu 27, 8(11)
|
|
stfdu 28, 8(11)
|
|
stfdu 29, 8(11)
|
|
stfdu 30, 8(11)
|
|
stfdu 31, 8(11)
|
|
/* Set up a callback link */
|
|
Loadglobal(11, caml_bottom_of_stack, 11)
|
|
stg 11, CALLBACK_LINK_OFFSET(1)
|
|
Loadglobal(11, caml_last_return_address, 11)
|
|
stg 11, (CALLBACK_LINK_OFFSET + WORD)(1)
|
|
Loadglobal(11, caml_gc_regs, 11)
|
|
stg 11, (CALLBACK_LINK_OFFSET + 2 * WORD)(1)
|
|
/* Build an exception handler to catch exceptions escaping out of OCaml */
|
|
bl .L103
|
|
b .L104
|
|
.L103:
|
|
addi 1, 1, -TRAP_SIZE
|
|
.cfi_adjust_cfa_offset TRAP_SIZE
|
|
mflr 0
|
|
stg 0, TRAP_HANDLER_OFFSET(1)
|
|
Loadglobal(11, caml_exception_pointer, 11)
|
|
stg 11, TRAP_PREVIOUS_OFFSET(1)
|
|
mr 29, 1
|
|
/* Reload allocation pointers */
|
|
Loadglobal(31, caml_young_ptr, 11)
|
|
Loadglobal(30, caml_young_limit, 11)
|
|
/* Call the OCaml code (address in r12) */
|
|
#if defined(MODEL_ppc)
|
|
mtctr 12
|
|
.L105: bctrl
|
|
#elif defined(MODEL_ppc64)
|
|
ld 0, 0(12)
|
|
mtctr 0
|
|
std 2, TOC_SAVE(1)
|
|
ld 2, 8(12)
|
|
.L105: bctrl
|
|
ld 2, TOC_SAVE(1)
|
|
#elif defined(MODEL_ppc64le)
|
|
mtctr 12
|
|
std 2, TOC_SAVE(1)
|
|
.L105: bctrl
|
|
ld 2, TOC_SAVE(1)
|
|
#else
|
|
#error "wrong MODEL"
|
|
#endif
|
|
/* Pop the trap frame, restoring caml_exception_pointer */
|
|
lg 0, TRAP_PREVIOUS_OFFSET(1)
|
|
Storeglobal(0, caml_exception_pointer, 11)
|
|
addi 1, 1, TRAP_SIZE
|
|
.cfi_adjust_cfa_offset -TRAP_SIZE
|
|
/* Pop the callback link, restoring the global variables */
|
|
.L106:
|
|
lg 0, CALLBACK_LINK_OFFSET(1)
|
|
Storeglobal(0, caml_bottom_of_stack, 11)
|
|
lg 0, (CALLBACK_LINK_OFFSET + WORD)(1)
|
|
Storeglobal(0, caml_last_return_address, 11)
|
|
lg 0, (CALLBACK_LINK_OFFSET + 2 * WORD)(1)
|
|
Storeglobal(0, caml_gc_regs, 11)
|
|
/* Update allocation pointer */
|
|
Storeglobal(31, caml_young_ptr, 11)
|
|
/* Restore callee-save registers */
|
|
addi 11, 1, CALLBACK_LINK_SIZE + RESERVED_STACK - WORD
|
|
lgu 14, WORD(11)
|
|
lgu 15, WORD(11)
|
|
lgu 16, WORD(11)
|
|
lgu 17, WORD(11)
|
|
lgu 18, WORD(11)
|
|
lgu 19, WORD(11)
|
|
lgu 20, WORD(11)
|
|
lgu 21, WORD(11)
|
|
lgu 22, WORD(11)
|
|
lgu 23, WORD(11)
|
|
lgu 24, WORD(11)
|
|
lgu 25, WORD(11)
|
|
lgu 26, WORD(11)
|
|
lgu 27, WORD(11)
|
|
lgu 28, WORD(11)
|
|
lgu 29, WORD(11)
|
|
lgu 30, WORD(11)
|
|
lgu 31, WORD(11)
|
|
lfdu 14, 8(11)
|
|
lfdu 15, 8(11)
|
|
lfdu 16, 8(11)
|
|
lfdu 17, 8(11)
|
|
lfdu 18, 8(11)
|
|
lfdu 19, 8(11)
|
|
lfdu 20, 8(11)
|
|
lfdu 21, 8(11)
|
|
lfdu 22, 8(11)
|
|
lfdu 23, 8(11)
|
|
lfdu 24, 8(11)
|
|
lfdu 25, 8(11)
|
|
lfdu 26, 8(11)
|
|
lfdu 27, 8(11)
|
|
lfdu 28, 8(11)
|
|
lfdu 29, 8(11)
|
|
lfdu 30, 8(11)
|
|
lfdu 31, 8(11)
|
|
/* Reload return address */
|
|
lg 0, (STACKSIZE + LR_SAVE)(1)
|
|
mtlr 0
|
|
/* Return */
|
|
addi 1, 1, STACKSIZE
|
|
blr
|
|
|
|
/* The trap handler: */
|
|
.L104:
|
|
/* Restore TOC pointer */
|
|
#ifdef TOC_SAVE_PARENT
|
|
ld 2, (STACKSIZE + TOC_SAVE_PARENT)(1)
|
|
#endif
|
|
/* Update caml_exception_pointer */
|
|
Storeglobal(29, caml_exception_pointer, 11)
|
|
/* Encode exception bucket as an exception result and return it */
|
|
ori 3, 3, 2
|
|
b .L106
|
|
#undef STACKSIZE
|
|
.cfi_endproc
|
|
ENDFUNCTION(caml_start_program)
|
|
|
|
/* Callback from C to OCaml */
|
|
|
|
FUNCTION(caml_callback_exn)
|
|
/* Initial shuffling of arguments */
|
|
mr 0, 3 /* Closure */
|
|
mr 3, 4 /* Argument */
|
|
mr 4, 0
|
|
lg 12, 0(4) /* Code pointer */
|
|
b .L102
|
|
ENDFUNCTION(caml_callback_exn)
|
|
|
|
FUNCTION(caml_callback2_exn)
|
|
mr 0, 3 /* Closure */
|
|
mr 3, 4 /* First argument */
|
|
mr 4, 5 /* Second argument */
|
|
mr 5, 0
|
|
Addrglobal(12, caml_apply2)
|
|
b .L102
|
|
ENDFUNCTION(caml_callback2_exn)
|
|
|
|
FUNCTION(caml_callback3_exn)
|
|
mr 0, 3 /* Closure */
|
|
mr 3, 4 /* First argument */
|
|
mr 4, 5 /* Second argument */
|
|
mr 5, 6 /* Third argument */
|
|
mr 6, 0
|
|
Addrglobal(12, caml_apply3)
|
|
b .L102
|
|
ENDFUNCTION(caml_callback3_exn)
|
|
|
|
#if defined(MODEL_ppc64)
|
|
.section ".opd","aw"
|
|
#else
|
|
.section ".text"
|
|
#endif
|
|
|
|
.globl caml_system__code_end
|
|
caml_system__code_end:
|
|
|
|
/* Frame table */
|
|
|
|
.section ".data"
|
|
.globl caml_system__frametable
|
|
.type caml_system__frametable, @object
|
|
caml_system__frametable:
|
|
datag 1 /* one descriptor */
|
|
datag .L105 + 4 /* return address into callback */
|
|
.short -1 /* negative size count => use callback link */
|
|
.short 0 /* no roots here */
|
|
|
|
/* TOC entries */
|
|
|
|
#if defined(MODEL_ppc64) || defined(MODEL_ppc64le)
|
|
|
|
.section ".toc", "aw"
|
|
|
|
#define TOCENTRY(glob) LSYMB(glob): .quad glob
|
|
|
|
TOCENTRY(caml_apply2)
|
|
TOCENTRY(caml_apply3)
|
|
TOCENTRY(caml_backtrace_active)
|
|
TOCENTRY(caml_backtrace_pos)
|
|
TOCENTRY(caml_bottom_of_stack)
|
|
TOCENTRY(caml_exception_pointer)
|
|
TOCENTRY(caml_gc_regs)
|
|
TOCENTRY(caml_last_return_address)
|
|
TOCENTRY(caml_program)
|
|
TOCENTRY(caml_young_limit)
|
|
TOCENTRY(caml_young_ptr)
|
|
|
|
#endif
|
|
|
|
/* Mark stack as non-executable */
|
|
.section .note.GNU-stack,"",%progbits
|