//// Assembly-language support code for vx32-to-x86-64 translation//#include "libvx32/asm.h"#include "libvx32/os.h" .text .globl vx_run_S_startvx_run_S_start:// Set up the segment registers as necessary for the emulation environment.// Args:// rdi: vxemu pointer// .code64 .globl vxrun_setupvxrun_setup: // Save the host's normal segment registers. movw %ss,%dx movw %dx,VXEMU_HOST_SS(%rdi) movw %ds,VXEMU_HOST_DS(%rdi) movw %es,VXEMU_HOST_ES(%rdi) movw VSEG,VXEMU_HOST_VS(%rdi) // Load the special vxemu segment into VSEG (%fs or %gs). movw VXEMU_EMUSEL(%rdi),VSEG ret// Start running translated vx32 code until something goes wrong -// usually, until we hit a piece of code that hasn't been translated yet.//// Args:// rdi: vxemu pointer// rsi: translated code entrypoint at which to start running// .p2align 4 .code64 .globl vxrunvxrun: // Save important host registers in x86-64 registers // that the 32-bit vx32 environment code can't touch. movq %rdi,%r8 // vxemu pointer argument in r8 movq %rbx,%r9 // callee-saved regs into r9,r10,r11 movq %rbp,%r10 movq %rsp,%r11 // Save the translated code entrypoint into the vxemu struct // so that we can use it in the far indirect jmp below. movl %esi,VXEMU_RUNPTR(%rdi) // Load the vx32 environment's data segment into %ds,%es,%ss. // The processor won't actually use the base and offset // of this segment until we jump into 32-bit compatibility mode. movw VXEMU_DATASEL(%rdi),%ax movw %ax,%ds movw %ax,%es movw %ax,%ss // Restore vx32 env's eflags register movl VXEMU_EFLAGS(%rdi),%eax pushq %rax popfq // Load vx32 env's registers movl VXEMU_EAX(%r8),%eax movl VXEMU_ECX(%r8),%ecx movl VXEMU_EDX(%r8),%edx // translated code will restore %EBX movl VXEMU_ESP(%r8),%esp movl VXEMU_EBP(%r8),%ebp movl VXEMU_ESI(%r8),%esi movl VXEMU_EDI(%r8),%edi // Run translated code#ifndef __FreeBSD__ ljmpl *VXEMU_RUNPTR(%r8) // 'ljmpq' doesn't work - gas bug??#else ljmpq *VXEMU_RUNPTR(%r8)#endif// Return from running translated code to the normal host environment.// Assumes EAX, EBX, ECX, and EDX have already been saved.// Assumes return code for vxrun is already in eax.// .p2align 4 .code64 .globl vxrun_returnvxrun_return: // Save remaining vx32 registers movl %esp,VXEMU_ESP(%r8) movl %ebp,VXEMU_EBP(%r8) movl %esi,VXEMU_ESI(%r8) movl %edi,VXEMU_EDI(%r8) // Restore host's callee-saved registers movq %r11,%rsp movq %r10,%rbp movq %r9,%rbx // Save vx32 env's eflags register pushfq popq %rdx movl %edx,VXEMU_EFLAGS(%r8) // Return to caller cld // x86-64 ABI says DF must be cleared ret// Clean up segment registers after running emulated code.// Args:// rdi: vxemu pointer// .code64 .globl vxrun_cleanupvxrun_cleanup: // Restore host's original segment registers. movw VXEMU_HOST_SS(%rdi),%ss movw VXEMU_HOST_DS(%rdi),%ds movw VXEMU_HOST_ES(%rdi),%es movw VXEMU_HOST_VS(%rdi),VSEG ret// Don't put anything here!// The signal handler knows that vxrun_cleanup// is at the bottom of this file.
//
// Assembly-language support code for vx32-to-x86-64 translation
//
#include "libvx32/asm.h"
#include "libvx32/os.h"
.text
.globl vx_run_S_start
vx_run_S_start:
// Set up the segment registers as necessary for the emulation environment.
// Args:
// rdi: vxemu pointer
//
.code64
.globl vxrun_setup
vxrun_setup:
// Save the host's normal segment registers.
movw %ss,%dx
movw %dx,VXEMU_HOST_SS(%rdi)
movw %ds,VXEMU_HOST_DS(%rdi)
movw %es,VXEMU_HOST_ES(%rdi)
movw VSEG,VXEMU_HOST_VS(%rdi)
// Load the special vxemu segment into VSEG (%fs or %gs).
movw VXEMU_EMUSEL(%rdi),VSEG
ret
// Start running translated vx32 code until something goes wrong -
// usually, until we hit a piece of code that hasn't been translated yet.
//
// Args:
// rdi: vxemu pointer
// rsi: translated code entrypoint at which to start running
//
.p2align 4
.code64
.globl vxrun
vxrun:
// Save important host registers in x86-64 registers
// that the 32-bit vx32 environment code can't touch.
movq %rdi,%r8 // vxemu pointer argument in r8
movq %rbx,%r9 // callee-saved regs into r9,r10,r11
movq %rbp,%r10
movq %rsp,%r11
// Save the translated code entrypoint into the vxemu struct
// so that we can use it in the far indirect jmp below.
movl %esi,VXEMU_RUNPTR(%rdi)
// Load the vx32 environment's data segment into %ds,%es,%ss.
// The processor won't actually use the base and offset
// of this segment until we jump into 32-bit compatibility mode.
movw VXEMU_DATASEL(%rdi),%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%ss
// Restore vx32 env's eflags register
movl VXEMU_EFLAGS(%rdi),%eax
pushq %rax
popfq
// Load vx32 env's registers
movl VXEMU_EAX(%r8),%eax
movl VXEMU_ECX(%r8),%ecx
movl VXEMU_EDX(%r8),%edx
// translated code will restore %EBX
movl VXEMU_ESP(%r8),%esp
movl VXEMU_EBP(%r8),%ebp
movl VXEMU_ESI(%r8),%esi
movl VXEMU_EDI(%r8),%edi
// Run translated code
#ifndef __FreeBSD__
ljmpl *VXEMU_RUNPTR(%r8) // 'ljmpq' doesn't work - gas bug??
#else
ljmpq *VXEMU_RUNPTR(%r8)
#endif
// Return from running translated code to the normal host environment.
// Assumes EAX, EBX, ECX, and EDX have already been saved.
// Assumes return code for vxrun is already in eax.
//
.p2align 4
.code64
.globl vxrun_return
vxrun_return:
// Save remaining vx32 registers
movl %esp,VXEMU_ESP(%r8)
movl %ebp,VXEMU_EBP(%r8)
movl %esi,VXEMU_ESI(%r8)
movl %edi,VXEMU_EDI(%r8)
// Restore host's callee-saved registers
movq %r11,%rsp
movq %r10,%rbp
movq %r9,%rbx
// Save vx32 env's eflags register
pushfq
popq %rdx
movl %edx,VXEMU_EFLAGS(%r8)
// Return to caller
cld // x86-64 ABI says DF must be cleared
ret
// Clean up segment registers after running emulated code.
// Args:
// rdi: vxemu pointer
//
.code64
.globl vxrun_cleanup
vxrun_cleanup:
// Restore host's original segment registers.
movw VXEMU_HOST_SS(%rdi),%ss
movw VXEMU_HOST_DS(%rdi),%ds
movw VXEMU_HOST_ES(%rdi),%es
movw VXEMU_HOST_VS(%rdi),VSEG
ret
// Don't put anything here!
// The signal handler knows that vxrun_cleanup
// is at the bottom of this file.