;************************************************************************** ;* * ;* 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. * ;* * ;************************************************************************** ; Asm part of the runtime system, Intel 386 processor, Intel syntax .386 .MODEL FLAT EXTERN _caml_garbage_collection: PROC EXTERN _caml_apply2: PROC EXTERN _caml_apply3: PROC EXTERN _caml_program: PROC EXTERN _caml_array_bound_error: PROC EXTERN _caml_stash_backtrace: PROC EXTERN _Caml_state: DWORD .CODE PUBLIC _caml_system__code_begin _caml_system__code_begin: ret ; just one instruction, so that debuggers don't display ; caml_system__code_begin instead of caml_call_gc ; Allocation PUBLIC _caml_call_gc PUBLIC _caml_alloc1 PUBLIC _caml_alloc2 PUBLIC _caml_alloc3 PUBLIC _caml_allocN INCLUDE domain_state32.inc _caml_call_gc: ; Record lowest stack address and return address mov ebx, _Caml_state mov eax, [esp] Store_last_return_address ebx, eax lea eax, [esp+4] Store_bottom_of_stack ebx, eax ; Save all regs used by the code generator push ebp push edi push esi push edx push ecx push ebx push eax Store_gc_regs ebx, esp ; Call the garbage collector call _caml_garbage_collection ; Restore all regs used by the code generator pop eax pop ebx pop ecx pop edx pop esi pop edi pop ebp ; Return to caller. Returns young_ptr in eax Load_young_ptr ebx, eax ret ALIGN 4 _caml_alloc1: mov ebx, _Caml_state Load_young_ptr ebx, eax sub eax, 8 Store_young_ptr ebx, eax Cmp_young_limit ebx, eax jb _caml_call_gc ret ALIGN 4 _caml_alloc2: mov ebx, _Caml_state Load_young_ptr ebx, eax sub eax, 12 Store_young_ptr ebx, eax Cmp_young_limit ebx, eax jb _caml_call_gc ret ALIGN 4 _caml_alloc3: mov ebx, _Caml_state Load_young_ptr ebx, eax sub eax, 16 Store_young_ptr ebx, eax Cmp_young_limit ebx, eax jb _caml_call_gc ret ALIGN 4 _caml_allocN: mov ebx, _Caml_state Sub_young_ptr ebx, eax ; eax = size - young_ptr neg eax ; eax = young_ptr - size Store_young_ptr ebx, eax Cmp_young_limit ebx, eax jb _caml_call_gc ret ; Call a C function from OCaml PUBLIC _caml_c_call ALIGN 4 _caml_c_call: ; Record lowest stack address and return address ; ecx and edx are destroyed at C call. Use them as temp. mov ecx, _Caml_state mov edx, [esp] Store_last_return_address ecx, edx lea edx, [esp+4] Store_bottom_of_stack ecx, edx ; Call the function (address in %eax) jmp eax ; Start the OCaml program PUBLIC _caml_start_program ALIGN 4 _caml_start_program: ; Save callee-save registers push ebx push esi push edi push ebp ; Initial code pointer is caml_program mov esi, offset _caml_program ; Code shared between caml_start_program and callback* L106: mov edi, _Caml_state ; Build a callback link Push_gc_regs edi Push_last_return_address edi Push_bottom_of_stack edi ; Build an exception handler push L108 Push_exception_pointer edi Store_exception_pointer edi, esp ; Call the OCaml code call esi L107: mov edi, _Caml_state ; Pop the exception handler Pop_exception_pointer edi add esp, 4 L109: mov edi, _Caml_state ; Pop the callback link, restoring the global variables ; used by caml_c_call Pop_bottom_of_stack edi Pop_last_return_address edi Pop_gc_regs edi ; Restore callee-save registers. pop ebp pop edi pop esi pop ebx ; Return to caller. ret L108: ; Exception handler ; Mark the bucket as an exception result and return it or eax, 2 jmp L109 ; Raise an exception for OCaml PUBLIC _caml_raise_exn ALIGN 4 _caml_raise_exn: mov ebx, _Caml_state Load_backtrace_active ebx, ecx test ecx, 1 jne L110 Load_exception_pointer ebx, esp Pop_exception_pointer ebx ret L110: mov esi, eax ; Save exception bucket in esi Load_exception_pointer ebx, edi ; SP of handler mov eax, [esp] ; PC of raise lea edx, [esp+4] ; SP of raise push edi ; arg 4: SP of handler push edx ; arg 3: SP of raise push eax ; arg 2: PC of raise push esi ; arg 1: exception bucket call _caml_stash_backtrace mov eax, esi ; recover exception bucket mov esp, edi ; cut the stack Pop_exception_pointer ebx ret ; Raise an exception from C PUBLIC _caml_raise_exception ALIGN 4 _caml_raise_exception: mov ebx, _Caml_state Load_backtrace_active ebx, ecx test ecx, 1 jne L112 mov eax, [esp+8] Load_exception_pointer ebx, esp Pop_exception_pointer ebx ret L112: mov esi, [esp+8] ; Save exception bucket in esi Push_exception_pointer ebx ; arg 4: SP of handler Push_bottom_of_stack ebx ; arg 3: SP of raise Push_last_return_address ebx ; arg 2: PC of raise push esi ; arg 1: exception bucket call _caml_stash_backtrace mov eax, esi ; recover exception bucket Load_exception_pointer ebx, esp ; cut the stack Pop_exception_pointer ebx ret ; Callback from C to OCaml PUBLIC _caml_callback_asm ALIGN 4 _caml_callback_asm: ; Save callee-save registers push ebx push esi push edi push ebp ; Initial loading of arguments mov ebx, [esp+24] ; arg2: closure mov edi, [esp+28] ; arguments array mov eax, [edi] ; arg1: argument mov esi, [ebx] ; code pointer jmp L106 PUBLIC _caml_callback2_asm ALIGN 4 _caml_callback2_asm: ; Save callee-save registers push ebx push esi push edi push ebp ; Initial loading of arguments mov ecx, [esp+24] ; arg3: closure mov edi, [esp+28] ; arguments array mov eax, [edi] ; arg1: first argument mov ebx, [edi+4] ; arg2: second argument mov esi, offset _caml_apply2 ; code pointer jmp L106 PUBLIC _caml_callback3_asm ALIGN 4 _caml_callback3_asm: ; Save callee-save registers push ebx push esi push edi push ebp ; Initial loading of arguments mov edx, [esp+24] ; arg4: closure mov edi, [esp+28] ; arguments array mov eax, [edi] ; arg1: first argument mov ebx, [edi+4] ; arg2: second argument mov ecx, [edi+8] ; arg3: third argument mov esi, offset _caml_apply3 ; code pointer jmp L106 PUBLIC _caml_ml_array_bound_error ALIGN 4 _caml_ml_array_bound_error: ; Empty the floating-point stack ffree st(0) ffree st(1) ffree st(2) ffree st(3) ffree st(4) ffree st(5) ffree st(6) ffree st(7) ; Branch to caml_array_bound_error mov eax, offset _caml_array_bound_error jmp _caml_c_call PUBLIC _caml_system__code_end _caml_system__code_end: .DATA PUBLIC _caml_system__frametable _caml_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 PUBLIC _caml_extra_params _caml_extra_params LABEL DWORD BYTE 64 DUP (?) END