summaryrefslogtreecommitdiff
path: root/ocaml-binary-annot/asmrun/amd64.S
diff options
context:
space:
mode:
Diffstat (limited to 'ocaml-binary-annot/asmrun/amd64.S')
-rw-r--r--ocaml-binary-annot/asmrun/amd64.S460
1 files changed, 460 insertions, 0 deletions
diff --git a/ocaml-binary-annot/asmrun/amd64.S b/ocaml-binary-annot/asmrun/amd64.S
new file mode 100644
index 0000000000..97de518399
--- /dev/null
+++ b/ocaml-binary-annot/asmrun/amd64.S
@@ -0,0 +1,460 @@
+/***********************************************************************/
+/* */
+/* Objective Caml */
+/* */
+/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
+/* */
+/* Copyright 2003 Institut National de Recherche en Informatique et */
+/* en Automatique. All rights reserved. This file is distributed */
+/* under the terms of the GNU Library General Public License, with */
+/* the special exception on linking described in file ../LICENSE. */
+/* */
+/***********************************************************************/
+
+/* $Id$ */
+
+/* Asm part of the runtime system, AMD64 processor */
+/* Must be preprocessed by cpp */
+
+/* PIC mode support based on contribution by Paul Stravers (see PR#4795) */
+
+#ifdef SYS_macosx
+
+#define G(r) _##r
+#define GREL(r) _##r@GOTPCREL
+#define GCALL(r) _##r
+#define FUNCTION_ALIGN 2
+#define EIGHT_ALIGN 3
+#define SIXTEEN_ALIGN 4
+#define FUNCTION(name) \
+ .globl name; \
+ .align FUNCTION_ALIGN; \
+ name:
+
+#else
+
+#define G(r) r
+#define GREL(r) r@GOTPCREL
+#define GCALL(r) r@PLT
+#define FUNCTION_ALIGN 4
+#define EIGHT_ALIGN 8
+#define SIXTEEN_ALIGN 16
+#define FUNCTION(name) \
+ .globl name; \
+ .type name,@function; \
+ .align FUNCTION_ALIGN; \
+ name:
+
+#endif
+
+#ifdef __PIC__
+
+/* Position-independent operations on global variables. */
+
+/* Store [srcreg] in global [dstlabel]. Clobbers %r11. */
+#define STORE_VAR(srcreg,dstlabel) \
+ movq GREL(dstlabel)(%rip), %r11 ; \
+ movq srcreg, (%r11)
+
+/* Load global [srclabel] in register [dstreg]. Clobbers %r11. */
+#define LOAD_VAR(srclabel,dstreg) \
+ movq GREL(srclabel)(%rip), %r11 ; \
+ movq (%r11), dstreg
+
+/* Compare global [label] with register [reg]. Clobbers %rax. */
+#define CMP_VAR(label,reg) \
+ movq GREL(label)(%rip), %rax ; \
+ cmpq (%rax), reg
+
+/* Test 32-bit global [label] against mask [imm]. Clobbers %r11. */
+#define TESTL_VAR(imm,label) \
+ movq GREL(label)(%rip), %r11 ; \
+ testl imm, (%r11)
+
+/* Push global [label] on stack. Clobbers %r11. */
+#define PUSH_VAR(srclabel) \
+ movq GREL(srclabel)(%rip), %r11 ; \
+ pushq (%r11)
+
+/* Pop global [label] off stack. Clobbers %r11. */
+#define POP_VAR(dstlabel) \
+ movq GREL(dstlabel)(%rip), %r11 ; \
+ popq (%r11)
+
+/* Record lowest stack address and return address. Clobbers %rax. */
+#define RECORD_STACK_FRAME(OFFSET) \
+ pushq %r11 ; \
+ movq 8+OFFSET(%rsp), %rax ; \
+ STORE_VAR(%rax,caml_last_return_address) ; \
+ leaq 16+OFFSET(%rsp), %rax ; \
+ STORE_VAR(%rax,caml_bottom_of_stack) ; \
+ popq %r11
+
+#else
+
+/* Non-PIC operations on global variables. Slightly faster. */
+
+#define STORE_VAR(srcreg,dstlabel) \
+ movq srcreg, G(dstlabel)(%rip)
+
+#define LOAD_VAR(srclabel,dstreg) \
+ movq G(srclabel)(%rip), dstreg
+
+#define CMP_VAR(label,reg) \
+ cmpq G(label)(%rip), %r15
+
+#define TESTL_VAR(imm,label) \
+ testl imm, G(label)(%rip)
+
+#define PUSH_VAR(srclabel) \
+ pushq G(srclabel)(%rip)
+
+#define POP_VAR(dstlabel) \
+ popq G(dstlabel)(%rip)
+
+#define RECORD_STACK_FRAME(OFFSET) \
+ movq OFFSET(%rsp), %rax ; \
+ STORE_VAR(%rax,caml_last_return_address) ; \
+ leaq 8+OFFSET(%rsp), %rax ; \
+ STORE_VAR(%rax,caml_bottom_of_stack)
+
+#endif
+
+ .text
+
+/* Allocation */
+
+FUNCTION(G(caml_call_gc))
+ RECORD_STACK_FRAME(0)
+.Lcaml_call_gc:
+ /* Build array of registers, save it into caml_gc_regs */
+ pushq %r13
+ pushq %r12
+ pushq %rbp
+ pushq %r11
+ pushq %r10
+ pushq %r9
+ pushq %r8
+ pushq %rcx
+ pushq %rdx
+ pushq %rsi
+ pushq %rdi
+ pushq %rbx
+ pushq %rax
+ STORE_VAR(%rsp, caml_gc_regs)
+ /* Save caml_young_ptr, caml_exception_pointer */
+ STORE_VAR(%r15, caml_young_ptr)
+ STORE_VAR(%r14, caml_exception_pointer)
+ /* Save floating-point registers */
+ subq $(16*8), %rsp
+ movlpd %xmm0, 0*8(%rsp)
+ movlpd %xmm1, 1*8(%rsp)
+ movlpd %xmm2, 2*8(%rsp)
+ movlpd %xmm3, 3*8(%rsp)
+ movlpd %xmm4, 4*8(%rsp)
+ movlpd %xmm5, 5*8(%rsp)
+ movlpd %xmm6, 6*8(%rsp)
+ movlpd %xmm7, 7*8(%rsp)
+ movlpd %xmm8, 8*8(%rsp)
+ movlpd %xmm9, 9*8(%rsp)
+ movlpd %xmm10, 10*8(%rsp)
+ movlpd %xmm11, 11*8(%rsp)
+ movlpd %xmm12, 12*8(%rsp)
+ movlpd %xmm13, 13*8(%rsp)
+ movlpd %xmm14, 14*8(%rsp)
+ movlpd %xmm15, 15*8(%rsp)
+ /* Call the garbage collector */
+ call GCALL(caml_garbage_collection)
+ /* Restore caml_young_ptr, caml_exception_pointer */
+ LOAD_VAR(caml_young_ptr, %r15)
+ LOAD_VAR(caml_exception_pointer, %r14)
+ /* Restore all regs used by the code generator */
+ movlpd 0*8(%rsp), %xmm0
+ movlpd 1*8(%rsp), %xmm1
+ movlpd 2*8(%rsp), %xmm2
+ movlpd 3*8(%rsp), %xmm3
+ movlpd 4*8(%rsp), %xmm4
+ movlpd 5*8(%rsp), %xmm5
+ movlpd 6*8(%rsp), %xmm6
+ movlpd 7*8(%rsp), %xmm7
+ movlpd 8*8(%rsp), %xmm8
+ movlpd 9*8(%rsp), %xmm9
+ movlpd 10*8(%rsp), %xmm10
+ movlpd 11*8(%rsp), %xmm11
+ movlpd 12*8(%rsp), %xmm12
+ movlpd 13*8(%rsp), %xmm13
+ movlpd 14*8(%rsp), %xmm14
+ movlpd 15*8(%rsp), %xmm15
+ addq $(16*8), %rsp
+ popq %rax
+ popq %rbx
+ popq %rdi
+ popq %rsi
+ popq %rdx
+ popq %rcx
+ popq %r8
+ popq %r9
+ popq %r10
+ popq %r11
+ popq %rbp
+ popq %r12
+ popq %r13
+ /* Return to caller */
+ ret
+
+FUNCTION(G(caml_alloc1))
+.Lcaml_alloc1:
+ subq $16, %r15
+ CMP_VAR(caml_young_limit, %r15)
+ jb .L100
+ ret
+.L100:
+ RECORD_STACK_FRAME(0)
+ subq $8, %rsp
+ call .Lcaml_call_gc
+ addq $8, %rsp
+ jmp .Lcaml_alloc1
+
+FUNCTION(G(caml_alloc2))
+.Lcaml_alloc2:
+ subq $24, %r15
+ CMP_VAR(caml_young_limit, %r15)
+ jb .L101
+ ret
+.L101:
+ RECORD_STACK_FRAME(0)
+ subq $8, %rsp
+ call .Lcaml_call_gc
+ addq $8, %rsp
+ jmp .Lcaml_alloc2
+
+FUNCTION(G(caml_alloc3))
+.Lcaml_alloc3:
+ subq $32, %r15
+ CMP_VAR(caml_young_limit, %r15)
+ jb .L102
+ ret
+.L102:
+ RECORD_STACK_FRAME(0)
+ subq $8, %rsp
+ call .Lcaml_call_gc
+ addq $8, %rsp
+ jmp .Lcaml_alloc3
+
+FUNCTION(G(caml_allocN))
+.Lcaml_allocN:
+ pushq %rax /* save desired size */
+ subq %rax, %r15
+ CMP_VAR(caml_young_limit, %r15)
+ jb .L103
+ addq $8, %rsp /* drop desired size */
+ ret
+.L103:
+ RECORD_STACK_FRAME(8)
+ call .Lcaml_call_gc
+ popq %rax /* recover desired size */
+ jmp .Lcaml_allocN
+
+/* Call a C function from Caml */
+
+FUNCTION(G(caml_c_call))
+.Lcaml_c_call:
+ /* Record lowest stack address and return address */
+ popq %r12
+ STORE_VAR(%r12, caml_last_return_address)
+ STORE_VAR(%rsp, caml_bottom_of_stack)
+ /* Make the exception handler and alloc ptr available to the C code */
+ STORE_VAR(%r15, caml_young_ptr)
+ STORE_VAR(%r14, caml_exception_pointer)
+ /* Call the function (address in %rax) */
+ call *%rax
+ /* Reload alloc ptr */
+ LOAD_VAR(caml_young_ptr, %r15)
+ /* Return to caller */
+ pushq %r12
+ ret
+
+/* Start the Caml program */
+
+FUNCTION(G(caml_start_program))
+ /* Save callee-save registers */
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ subq $8, %rsp /* stack 16-aligned */
+ /* Initial entry point is G(caml_program) */
+ leaq GCALL(caml_program)(%rip), %r12
+ /* Common code for caml_start_program and caml_callback* */
+.Lcaml_start_program:
+ /* Build a callback link */
+ subq $8, %rsp /* stack 16-aligned */
+ PUSH_VAR(caml_gc_regs)
+ PUSH_VAR(caml_last_return_address)
+ PUSH_VAR(caml_bottom_of_stack)
+ /* Setup alloc ptr and exception ptr */
+ LOAD_VAR(caml_young_ptr, %r15)
+ LOAD_VAR(caml_exception_pointer, %r14)
+ /* Build an exception handler */
+ lea .L108(%rip), %r13
+ pushq %r13
+ pushq %r14
+ movq %rsp, %r14
+ /* Call the Caml code */
+ call *%r12
+.L107:
+ /* Pop the exception handler */
+ popq %r14
+ popq %r12 /* dummy register */
+.L109:
+ /* Update alloc ptr and exception ptr */
+ STORE_VAR(%r15,caml_young_ptr)
+ STORE_VAR(%r14,caml_exception_pointer)
+ /* Pop the callback link, restoring the global variables */
+ POP_VAR(caml_bottom_of_stack)
+ POP_VAR(caml_last_return_address)
+ POP_VAR(caml_gc_regs)
+ addq $8, %rsp
+ /* Restore callee-save registers. */
+ addq $8, %rsp
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ popq %rbp
+ popq %rbx
+ /* Return to caller. */
+ ret
+.L108:
+ /* Exception handler*/
+ /* Mark the bucket as an exception result and return it */
+ orq $2, %rax
+ jmp .L109
+
+/* Raise an exception from Caml */
+
+FUNCTION(G(caml_raise_exn))
+ TESTL_VAR($1, caml_backtrace_active)
+ jne .L110
+ movq %r14, %rsp
+ popq %r14
+ ret
+.L110:
+ movq %rax, %r12 /* Save exception bucket */
+ movq %rax, %rdi /* arg 1: exception bucket */
+ movq 0(%rsp), %rsi /* arg 2: pc of raise */
+ leaq 8(%rsp), %rdx /* arg 3: sp of raise */
+ movq %r14, %rcx /* arg 4: sp of handler */
+ call GCALL(caml_stash_backtrace)
+ movq %r12, %rax /* Recover exception bucket */
+ movq %r14, %rsp
+ popq %r14
+ ret
+
+/* Raise an exception from C */
+
+FUNCTION(G(caml_raise_exception))
+ TESTL_VAR($1, caml_backtrace_active)
+ jne .L111
+ movq %rdi, %rax
+ LOAD_VAR(caml_exception_pointer, %rsp) /* Cut stack */
+ popq %r14 /* Recover previous exception handler */
+ LOAD_VAR(caml_young_ptr, %r15) /* Reload alloc ptr */
+ ret
+.L111:
+ movq %rdi, %r12 /* Save exception bucket */
+ /* arg 1: exception bucket */
+ LOAD_VAR(caml_last_return_address,%rsi) /* arg 2: pc of raise */
+ LOAD_VAR(caml_bottom_of_stack,%rdx) /* arg 3: sp of raise */
+ LOAD_VAR(caml_exception_pointer,%rcx) /* arg 4: sp of handler */
+ call GCALL(caml_stash_backtrace)
+ movq %r12, %rax /* Recover exception bucket */
+ LOAD_VAR(caml_exception_pointer,%rsp)
+ popq %r14 /* Recover previous exception handler */
+ LOAD_VAR(caml_young_ptr,%r15) /* Reload alloc ptr */
+ ret
+
+/* Callback from C to Caml */
+
+FUNCTION(G(caml_callback_exn))
+ /* Save callee-save registers */
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ subq $8, %rsp /* stack 16-aligned */
+ /* Initial loading of arguments */
+ movq %rdi, %rbx /* closure */
+ movq %rsi, %rax /* argument */
+ movq 0(%rbx), %r12 /* code pointer */
+ jmp .Lcaml_start_program
+
+FUNCTION(G(caml_callback2_exn))
+ /* Save callee-save registers */
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ subq $8, %rsp /* stack 16-aligned */
+ /* Initial loading of arguments */
+ /* closure stays in %rdi */
+ movq %rsi, %rax /* first argument */
+ movq %rdx, %rbx /* second argument */
+ leaq GCALL(caml_apply2)(%rip), %r12 /* code pointer */
+ jmp .Lcaml_start_program
+
+FUNCTION(G(caml_callback3_exn))
+ /* Save callee-save registers */
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ subq $8, %rsp /* stack 16-aligned */
+ /* Initial loading of arguments */
+ movq %rsi, %rax /* first argument */
+ movq %rdx, %rbx /* second argument */
+ movq %rdi, %rsi /* closure */
+ movq %rcx, %rdi /* third argument */
+ leaq GCALL(caml_apply3)(%rip), %r12 /* code pointer */
+ jmp .Lcaml_start_program
+
+FUNCTION(G(caml_ml_array_bound_error))
+ leaq GCALL(caml_array_bound_error)(%rip), %rax
+ jmp .Lcaml_c_call
+
+ .data
+ .globl G(caml_system__frametable)
+ .align EIGHT_ALIGN
+G(caml_system__frametable):
+ .quad 1 /* one descriptor */
+ .quad .L107 /* return address into callback */
+ .value -1 /* negative frame size => use callback link */
+ .value 0 /* no roots here */
+ .align EIGHT_ALIGN
+
+#ifdef SYS_macosx
+ .literal16
+#else
+ .section .rodata.cst8,"a",@progbits
+#endif
+ .globl G(caml_negf_mask)
+ .align SIXTEEN_ALIGN
+G(caml_negf_mask):
+ .quad 0x8000000000000000, 0
+ .globl G(caml_absf_mask)
+ .align SIXTEEN_ALIGN
+G(caml_absf_mask):
+ .quad 0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF
+
+#if defined(SYS_linux)
+ /* Mark stack as non-executable, PR#4564 */
+ .section .note.GNU-stack,"",%progbits
+#endif