283 lines
8.6 KiB
ArmAsm
283 lines
8.6 KiB
ArmAsm
/***********************************************************************/
|
|
/* */
|
|
/* Caml Special Light */
|
|
/* */
|
|
/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
|
|
/* */
|
|
/* Copyright 1995 Institut National de Recherche en Informatique et */
|
|
/* Automatique. Distributed only by permission. */
|
|
/* */
|
|
/***********************************************************************/
|
|
|
|
/* $Id$ */
|
|
|
|
/* Asm part of the runtime system, Intel 386 processor */
|
|
/* Must be preprocessed by cpp */
|
|
|
|
/* Linux with ELF binaries does not prefix identifiers with _.
|
|
Linux with a.out binaries, FreeBSD, and NextStep do. */
|
|
|
|
#ifdef SYS_linux_elf
|
|
#define G(x) x
|
|
#define FUNCTION_ALIGN 16
|
|
#else
|
|
#define G(x) _##x
|
|
#define FUNCTION_ALIGN 4
|
|
#endif
|
|
|
|
.comm G(young_limit), 4
|
|
.comm G(young_ptr), 4
|
|
.comm G(gc_entry_regs), 4 * 7
|
|
.comm G(caml_bottom_of_stack), 4
|
|
.comm G(caml_top_of_stack), 4
|
|
.comm G(caml_last_return_address), 4
|
|
.comm G(caml_exception_pointer), 4
|
|
|
|
/* Allocation */
|
|
|
|
.text
|
|
.globl G(caml_alloc1)
|
|
.globl G(caml_alloc2)
|
|
.globl G(caml_alloc3)
|
|
.globl G(caml_alloc)
|
|
.globl G(caml_call_gc)
|
|
|
|
.align FUNCTION_ALIGN
|
|
G(caml_alloc1):
|
|
movl G(young_ptr), %eax
|
|
subl $8, %eax
|
|
movl %eax, G(young_ptr)
|
|
cmpl G(young_limit), %eax
|
|
jb L100
|
|
ret
|
|
L100: movl $8, %eax
|
|
jmp L105
|
|
|
|
.align FUNCTION_ALIGN
|
|
G(caml_alloc2):
|
|
movl G(young_ptr), %eax
|
|
subl $12, %eax
|
|
movl %eax, G(young_ptr)
|
|
cmpl G(young_limit), %eax
|
|
jb L101
|
|
ret
|
|
L101: movl $12, %eax
|
|
jmp L105
|
|
|
|
.align FUNCTION_ALIGN
|
|
G(caml_alloc3):
|
|
movl G(young_ptr), %eax
|
|
subl $16, %eax
|
|
movl %eax, G(young_ptr)
|
|
cmpl G(young_limit), %eax
|
|
jb L102
|
|
ret
|
|
L102: movl $16, %eax
|
|
jmp L105
|
|
|
|
.align FUNCTION_ALIGN
|
|
G(caml_alloc):
|
|
pushl %eax
|
|
movl G(young_ptr), %eax
|
|
subl (%esp), %eax
|
|
movl %eax, G(young_ptr)
|
|
cmpl G(young_limit), %eax
|
|
jb L103
|
|
addl $4, %esp
|
|
ret
|
|
L103: popl %eax
|
|
jmp L105
|
|
|
|
G(caml_call_gc):
|
|
/* Adjust return address and recover desired size in %eax */
|
|
popl %eax
|
|
addl $2, %eax
|
|
pushl %eax
|
|
movzwl -2(%eax), %eax
|
|
L105:
|
|
/* Record lowest stack address and return address */
|
|
popl G(caml_last_return_address)
|
|
movl %esp, G(caml_bottom_of_stack)
|
|
/* Save all regs used by the code generator */
|
|
movl %ebx, G(gc_entry_regs) + 4
|
|
movl %ecx, G(gc_entry_regs) + 8
|
|
movl %edx, G(gc_entry_regs) + 12
|
|
movl %esi, G(gc_entry_regs) + 16
|
|
movl %edi, G(gc_entry_regs) + 20
|
|
movl %ebp, G(gc_entry_regs) + 24
|
|
/* Save desired size */
|
|
pushl %eax
|
|
/* Call the garbage collector */
|
|
call G(garbage_collection)
|
|
/* Restore all regs used by the code generator */
|
|
movl G(gc_entry_regs) + 4, %ebx
|
|
movl G(gc_entry_regs) + 8, %ecx
|
|
movl G(gc_entry_regs) + 12, %edx
|
|
movl G(gc_entry_regs) + 16, %esi
|
|
movl G(gc_entry_regs) + 20, %edi
|
|
movl G(gc_entry_regs) + 24, %ebp
|
|
/* Recover desired size */
|
|
popl %eax
|
|
/* Decrement young_ptr by desired size */
|
|
subl %eax, G(young_ptr)
|
|
/* Reload result of allocation in %eax */
|
|
movl G(young_ptr), %eax
|
|
/* Return to caller */
|
|
pushl G(caml_last_return_address)
|
|
ret
|
|
|
|
/* Call a C function from Caml */
|
|
|
|
.globl G(caml_c_call)
|
|
|
|
.align FUNCTION_ALIGN
|
|
G(caml_c_call):
|
|
/* Record lowest stack address and return address */
|
|
/* In parallel, free the floating point registers */
|
|
/* (Pairing is expected on the Pentium.) */
|
|
movl (%esp), %edx
|
|
ffree %st(0)
|
|
movl %edx, G(caml_last_return_address)
|
|
ffree %st(1)
|
|
leal 4(%esp), %edx
|
|
ffree %st(2)
|
|
movl %edx, G(caml_bottom_of_stack)
|
|
ffree %st(3)
|
|
/* Call the function (address in %eax) */
|
|
jmp *%eax
|
|
|
|
/* Start the Caml program */
|
|
|
|
.globl G(caml_start_program)
|
|
.align FUNCTION_ALIGN
|
|
G(caml_start_program):
|
|
/* Save callee-save registers */
|
|
pushl %ebx
|
|
pushl %esi
|
|
pushl %edi
|
|
pushl %ebp
|
|
/* Build an exception handler */
|
|
pushl $L104
|
|
pushl $0
|
|
movl %esp, G(caml_exception_pointer)
|
|
/* Record highest stack address */
|
|
movl %esp, G(caml_top_of_stack)
|
|
/* Go for it */
|
|
call G(caml_program)
|
|
/* Pop handler */
|
|
addl $8, %esp
|
|
/* Zero return code */
|
|
xorl %eax, %eax
|
|
L104:
|
|
/* Restore registers and return */
|
|
popl %ebp
|
|
popl %edi
|
|
popl %esi
|
|
popl %ebx
|
|
ret
|
|
|
|
/* Raise an exception from C */
|
|
|
|
.globl G(raise_caml_exception)
|
|
.align FUNCTION_ALIGN
|
|
G(raise_caml_exception):
|
|
movl 4(%esp), %eax
|
|
movl G(caml_exception_pointer), %esp
|
|
popl G(caml_exception_pointer)
|
|
ret
|
|
|
|
/* Callback from C to Caml */
|
|
|
|
.globl G(callback)
|
|
.align FUNCTION_ALIGN
|
|
G(callback):
|
|
/* Save callee-save registers */
|
|
pushl %ebx
|
|
pushl %esi
|
|
pushl %edi
|
|
pushl %ebp
|
|
/* Initial loading of arguments */
|
|
movl 20(%esp), %ebx /* closure */
|
|
movl 24(%esp), %eax /* argument */
|
|
movl 0(%ebx), %esi /* code pointer */
|
|
L106:
|
|
/* Build a callback link */
|
|
pushl G(caml_last_return_address)
|
|
pushl G(caml_bottom_of_stack)
|
|
/* Build an exception handler */
|
|
pushl $L108
|
|
pushl G(caml_exception_pointer)
|
|
movl %esp, G(caml_exception_pointer)
|
|
/* Call the Caml code */
|
|
call *%esi
|
|
L107:
|
|
/* Pop the exception handler */
|
|
popl G(caml_exception_pointer)
|
|
popl %esi /* dummy register */
|
|
/* Pop the callback link, restoring the global variables
|
|
used by caml_c_call */
|
|
popl G(caml_bottom_of_stack)
|
|
popl G(caml_last_return_address)
|
|
/* Restore callee-save registers.
|
|
In parallel, free the floating-point registers
|
|
that may have been used by Caml. */
|
|
popl %ebp
|
|
ffree %st(0)
|
|
popl %edi
|
|
ffree %st(1)
|
|
popl %esi
|
|
ffree %st(2)
|
|
popl %ebx
|
|
ffree %st(3)
|
|
/* Return to caller. */
|
|
ret
|
|
L108:
|
|
/* Exception handler*/
|
|
/* Pop the callback link, restoring the global variables
|
|
used by caml_c_call */
|
|
popl G(caml_bottom_of_stack)
|
|
popl G(caml_last_return_address)
|
|
/* Re-raise the exception through mlraise,
|
|
so that local C roots are cleaned up correctly. */
|
|
pushl %eax /* exn bucket is the argument */
|
|
call G(mlraise) /* never returns */
|
|
|
|
.globl G(callback2)
|
|
.align FUNCTION_ALIGN
|
|
G(callback2):
|
|
/* Save callee-save registers */
|
|
pushl %ebx
|
|
pushl %esi
|
|
pushl %edi
|
|
pushl %ebp
|
|
/* Initial loading of arguments */
|
|
movl 20(%esp), %ecx /* closure */
|
|
movl 24(%esp), %eax /* first argument */
|
|
movl 28(%esp), %ebx /* second argument */
|
|
movl $ G(caml_apply2), %esi /* code pointer */
|
|
jmp L106
|
|
|
|
.globl G(callback3)
|
|
.align FUNCTION_ALIGN
|
|
G(callback3):
|
|
/* Save callee-save registers */
|
|
pushl %ebx
|
|
pushl %esi
|
|
pushl %edi
|
|
pushl %ebp
|
|
/* Initial loading of arguments */
|
|
movl 20(%esp), %edx /* closure */
|
|
movl 24(%esp), %eax /* first argument */
|
|
movl 28(%esp), %ebx /* second argument */
|
|
movl 32(%esp), %ecx /* third argument */
|
|
movl $ G(caml_apply3), %esi /* code pointer */
|
|
jmp L106
|
|
|
|
.data
|
|
.globl G(system_frametable)
|
|
G(system_frametable):
|
|
.long 1 /* one descriptor */
|
|
.long L107 /* return address into callback */
|
|
.word -1 /* negative frame size => use callback link */
|
|
.word 0 /* no roots here */
|