run64.S (3076B)
1 // 2 // Assembly-language support code for vx32-to-x86-64 translation 3 // 4 5 #include "libvx32/asm.h" 6 #include "libvx32/os.h" 7 8 .text 9 10 .globl vx_run_S_start 11 vx_run_S_start: 12 13 // Set up the segment registers as necessary for the emulation environment. 14 // Args: 15 // rdi: vxemu pointer 16 // 17 .code64 18 19 .globl vxrun_setup 20 vxrun_setup: 21 22 // Save the host's normal segment registers. 23 movw %ss,%dx 24 movw %dx,VXEMU_HOST_SS(%rdi) 25 movw %ds,VXEMU_HOST_DS(%rdi) 26 movw %es,VXEMU_HOST_ES(%rdi) 27 movw VSEG,VXEMU_HOST_VS(%rdi) 28 29 // Load the special vxemu segment into VSEG (%fs or %gs). 30 movw VXEMU_EMUSEL(%rdi),VSEG 31 32 ret 33 34 35 // Start running translated vx32 code until something goes wrong - 36 // usually, until we hit a piece of code that hasn't been translated yet. 37 // 38 // Args: 39 // rdi: vxemu pointer 40 // rsi: translated code entrypoint at which to start running 41 // 42 .p2align 4 43 .code64 44 .globl vxrun 45 vxrun: 46 47 // Save important host registers in x86-64 registers 48 // that the 32-bit vx32 environment code can't touch. 49 movq %rdi,%r8 // vxemu pointer argument in r8 50 movq %rbx,%r9 // callee-saved regs into r9,r10,r11 51 movq %rbp,%r10 52 movq %rsp,%r11 53 54 // Save the translated code entrypoint into the vxemu struct 55 // so that we can use it in the far indirect jmp below. 56 movl %esi,VXEMU_RUNPTR(%rdi) 57 58 // Load the vx32 environment's data segment into %ds,%es,%ss. 59 // The processor won't actually use the base and offset 60 // of this segment until we jump into 32-bit compatibility mode. 61 movw VXEMU_DATASEL(%rdi),%ax 62 movw %ax,%ds 63 movw %ax,%es 64 movw %ax,%ss 65 66 // Restore vx32 env's eflags register 67 movl VXEMU_EFLAGS(%rdi),%eax 68 pushq %rax 69 popfq 70 71 // Load vx32 env's registers 72 movl VXEMU_EAX(%r8),%eax 73 movl VXEMU_ECX(%r8),%ecx 74 movl VXEMU_EDX(%r8),%edx 75 // translated code will restore %EBX 76 movl VXEMU_ESP(%r8),%esp 77 movl VXEMU_EBP(%r8),%ebp 78 movl VXEMU_ESI(%r8),%esi 79 movl VXEMU_EDI(%r8),%edi 80 81 // Run translated code 82 #ifndef __FreeBSD__ 83 ljmpl *VXEMU_RUNPTR(%r8) // 'ljmpq' doesn't work - gas bug?? 84 #else 85 ljmpq *VXEMU_RUNPTR(%r8) 86 #endif 87 88 89 // Return from running translated code to the normal host environment. 90 // Assumes EAX, EBX, ECX, and EDX have already been saved. 91 // Assumes return code for vxrun is already in eax. 92 // 93 .p2align 4 94 .code64 95 .globl vxrun_return 96 vxrun_return: 97 98 // Save remaining vx32 registers 99 movl %esp,VXEMU_ESP(%r8) 100 movl %ebp,VXEMU_EBP(%r8) 101 movl %esi,VXEMU_ESI(%r8) 102 movl %edi,VXEMU_EDI(%r8) 103 104 // Restore host's callee-saved registers 105 movq %r11,%rsp 106 movq %r10,%rbp 107 movq %r9,%rbx 108 109 // Save vx32 env's eflags register 110 pushfq 111 popq %rdx 112 movl %edx,VXEMU_EFLAGS(%r8) 113 114 // Return to caller 115 cld // x86-64 ABI says DF must be cleared 116 ret 117 118 119 // Clean up segment registers after running emulated code. 120 // Args: 121 // rdi: vxemu pointer 122 // 123 .code64 124 .globl vxrun_cleanup 125 vxrun_cleanup: 126 127 // Restore host's original segment registers. 128 movw VXEMU_HOST_SS(%rdi),%ss 129 movw VXEMU_HOST_DS(%rdi),%ds 130 movw VXEMU_HOST_ES(%rdi),%es 131 movw VXEMU_HOST_VS(%rdi),VSEG 132 133 ret 134 135 // Don't put anything here! 136 // The signal handler knows that vxrun_cleanup 137 // is at the bottom of this file. 138