/* * void tramp64(void *args) * * Layout on stack: * args 20 * func 16 * retaddr 12 * %ebx 8 * %esi 4 * %edi 0 */ .globl tramp64 .type tramp64,@function .size tramp64,etramp64-tramp64 /* arrive here in 32 bit mode */ tramp64: pushl %ebx pushl %esi pushl %edi call base base: popl %esi /* relocatable address of "base" */ /* Set up for inter-segment jump to 64 bit code mode */ movl %esi,%edx addl $to64-base,%edx pushl $43 /* $GSEL(GUCODE_SEL, SEL_UPL) */ pushl %edx lretl .code64 .p2align 4 to64: movq %rsi,%r9 /* Set up our escape to 32 bit */ addq $to32-base,%r9 movl 16(%rsp),%eax /* func */ movl 20(%rsp),%edi /* args */ /* Call 64 bit code. %rdi = first arg */ call *%rax /* 32 bit return value is in %eax. */ /* We could split %rax into %eax/%edx if we wanted 64 bit returns: * movq %rax,%rdx * sarq $32,%rdx * However, the potential for garbled return values is high if * prototyping is less than perfect. It would be safer to have * a 64 bit return value in the arg structure */ /* Jump back to 32 bit code segment */ pushq $27 /* GSEL(GUCODE32_UPL, SEL_UPL) */ pushq %r9 lretq .code32 .p2align 4 to32: popl %edi popl %esi popl %ebx ret etramp64: