ocaml/asmrun/i386nt.asm

290 lines
7.4 KiB
NASM

;*********************************************************************
;
; 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, Intel syntax
.386
.MODEL FLAT
EXTERN _garbage_collection: PROC
EXTERN _mlraise: PROC
EXTERN _caml_apply2: PROC
EXTERN _caml_apply3: PROC
EXTERN _caml_program: PROC
EXTERN _young_limit: DWORD
EXTERN _young_ptr: DWORD
PUBLIC _gc_entry_regs
PUBLIC _caml_bottom_of_stack
PUBLIC _caml_top_of_stack
PUBLIC _caml_last_return_address
PUBLIC _caml_exception_pointer
.DATA
ALIGN 4
_gc_entry_regs DWORD 7 DUP(?)
_caml_bottom_of_stack DWORD 0
_caml_top_of_stack DWORD 0
_caml_last_return_address DWORD 0
_caml_exception_pointer DWORD 0
; Allocation
.CODE
PUBLIC _caml_alloc1
PUBLIC _caml_alloc2
PUBLIC _caml_alloc3
PUBLIC _caml_alloc
PUBLIC _caml_call_gc
ALIGN 4
_caml_alloc1:
mov eax, _young_ptr
sub eax, 8
mov _young_ptr, eax
cmp eax, _young_limit
jb L100
ret
L100: mov eax, 8
jmp L105
ALIGN 4
_caml_alloc2:
mov eax, _young_ptr
sub eax, 12
mov _young_ptr, eax
cmp eax, _young_limit
jb L101
ret
L101: mov eax, 12
jmp L105
ALIGN 4
_caml_alloc3:
mov eax, _young_ptr
sub eax, 16
mov _young_ptr, eax
cmp eax, _young_limit
jb L102
ret
L102: mov eax, 16
jmp L105
ALIGN 4
_caml_alloc:
push eax
mov eax, _young_ptr
sub eax, [esp]
mov _young_ptr, eax
cmp eax, _young_limit
jb L103
add esp, 4
ret
L103: pop eax
jmp L105
_caml_call_gc:
; Adjust return address and recover desired size in eax
pop eax
add eax, 2
push eax
movzx eax, WORD PTR [eax-2]
L105:
; Record lowest stack address and return address
pop _caml_last_return_address
mov _caml_bottom_of_stack, esp
; Save all regs used by the code generator
mov _gc_entry_regs + 4, ebx
mov _gc_entry_regs + 8, ecx
mov _gc_entry_regs + 12, edx
mov _gc_entry_regs + 16, esi
mov _gc_entry_regs + 20, edi
mov _gc_entry_regs + 24, ebp
; Save desired size
push eax
; Call the garbage collector
call _garbage_collection
; Restore all regs used by the code generator
mov ebx, _gc_entry_regs + 4
mov ecx, _gc_entry_regs + 8
mov edx, _gc_entry_regs + 12
mov esi, _gc_entry_regs + 16
mov edi, _gc_entry_regs + 20
mov ebp, _gc_entry_regs + 24
; Recover desired size
pop eax
; Decrement young_ptr by desired size
sub _young_ptr, eax
; Reload result of allocation in %eax
mov eax, _young_ptr
; Return to caller
push _caml_last_return_address
ret
; Call a C function from Caml
PUBLIC _caml_c_call
ALIGN 4
_caml_c_call:
; Record lowest stack address and return address
; In parallel, free the floating point registers
; (Pairing is expected on the Pentium.)
mov edx, [esp]
ffree st(0)
mov _caml_last_return_address, edx
ffree st(1)
lea edx, [esp+4]
ffree st(2)
mov _caml_bottom_of_stack, edx
ffree st(3)
; Call the function (address in %eax)
jmp eax
; Start the Caml program
PUBLIC _caml_start_program
ALIGN 4
_caml_start_program:
; Save callee-save registers
push ebx
push esi
push edi
push ebp
; Build an exception handler
push L104
push 0
mov _caml_exception_pointer, esp
; Record highest stack address
mov _caml_top_of_stack, esp
; Go for it
call _caml_program
; Pop handler
add esp, 8
; Zero return code
xor eax, eax
L104:
; Restore registers and return
pop ebp
pop edi
pop esi
pop ebx
ret
; Raise an exception from C
PUBLIC _raise_caml_exception
ALIGN 4
_raise_caml_exception:
mov eax, [esp+4]
mov esp, _caml_exception_pointer
pop _caml_exception_pointer
ret
; Callback from C to Caml
PUBLIC _callback
ALIGN 4
_callback:
; Save callee-save registers
push ebx
push esi
push edi
push ebp
; Initial loading of arguments
mov ebx, [esp+20] ; closure
mov eax, [esp+24] ; argument
mov esi, [ebx] ; code pointer
L106:
; Build a callback link
push _caml_last_return_address
push _caml_bottom_of_stack
; Build an exception handler
push L108
push _caml_exception_pointer
mov _caml_exception_pointer, esp
; Call the Caml code
call esi
L107:
; Pop the exception handler
pop _caml_exception_pointer
pop esi ; dummy register
; Pop the callback link, restoring the global variables
; used by caml_c_call
pop _caml_bottom_of_stack
pop _caml_last_return_address
; Restore callee-save registers.
; In parallel, free the floating-point registers
; that may have been used by Caml.
pop ebp
ffree st(0)
pop edi
ffree st(1)
pop esi
ffree st(2)
pop ebx
ffree st(3)
; Return to caller.
ret
L108:
; Exception handler
; Pop the callback link, restoring the global variables
; used by caml_c_call
pop _caml_bottom_of_stack
pop _caml_last_return_address
; Re-raise the exception through mlraise,
; so that local C roots are cleaned up correctly.
push eax ; exn bucket is the argument
call _mlraise ; never returns
PUBLIC _callback2
ALIGN 4
_callback2:
; Save callee-save registers
push ebx
push esi
push edi
push ebp
; Initial loading of arguments
mov ecx, [esp+20] ; closure
mov eax, [esp+24] ; first argument
mov ebx, [esp+28] ; second argument
mov esi, offset _caml_apply2 ; code pointer
jmp L106
PUBLIC _callback3
ALIGN 4
_callback3:
; Save callee-save registers
push ebx
push esi
push edi
push ebp
; Initial loading of arguments
mov edx, [esp+20] ; closure
mov eax, [esp+24] ; first argument
mov ebx, [esp+28] ; second argument
mov ecx, [esp+32] ; third argument
mov esi, offset _caml_apply3 ; code pointer
jmp L106
.DATA
PUBLIC _system_frametable
_system_frametable LABEL DWORD
DWORD 1 ; one descriptor
DWORD L107 ; return address into callback
WORD -1 ; negative frame size => use callback link
WORD 0 ; no roots here
END