code wiki / _hdl_build / nx_emu_x86.nx

nx_emu_x86.nx source

↩ module page · 62 lines · 2894 B

1// nx_emu_x86.nx -- a minimal sovereign x86-64 interpreter (the THIRD target family, 2// after RV64 + AArch64). x86-64 is variable-length with REX/ModRM, so this decodes 3// exactly the register-direct forms our machine-code generator emits -- enough to 4// EXECUTE and thus PROVE x86 machine code, no qemu. Register-direct (mod=11) only, 5// REX.W (0x48), regs 0..7 (rax rcx rdx rbx rsp rbp rsi rdi). 6// 7// Decoded forms (Intel SDM Vol.2): 8// 48 C7 /0 id mov r/m64, imm32 (sign-extended) 9// 48 89 /r mov r/m64, r64 10// 48 C1 /4 ib shl r/m64, imm8 11// 48 01 /r add r/m64, r64 12// 48 29 /r sub r/m64, r64 13// 0F 05 syscall (rax==60 -> exit(rdi & 0xff)) 14// Returns the 8-bit exit status, or a negative sentinel on an unknown byte. 15 16import "nx_syscalls_x86_64.nx" 17 18// read a little-endian imm32, sign-extended to 64 bits. 19func emu_x86_i32(code: *u8, off: i64) -> i64 { 20 var v: i64 = (code[off] as i64) | ((code[off+1] as i64) << 8) | ((code[off+2] as i64) << 16) | ((code[off+3] as i64) << 24) 21 if (v & 0x80000000) != 0 { v = v - (1 << 32) } 22 return v 23} 24 25func emu_x86_run(code: *u8, len: i64) -> i64 { 26 let reg: *i64 = sys_mmap(8 * 16) as *i64 27 var pc: i64 = 0 28 while pc < len { 29 let b: i64 = code[pc] as i64 30 if b == 0x0F { 31 if (code[pc+1] as i64) == 0x05 { // syscall 32 if reg[0] == 60 { return reg[7] & 0xff } // exit(rdi) 33 if reg[0] == 1 { sys_write(reg[7], ((code as i64) + reg[6]) as *u8, reg[2]) } // write(fd, buf=image+rsi, len) -- additive 34 pc = pc + 2 35 } else { return 0 - 1 } 36 } else { 37 if b != 0x48 { return 0 - 3 } // expect REX.W 38 let op: i64 = code[pc+1] as i64 39 if op == 0xC7 { // mov r/m64, imm32 40 reg[(code[pc+2] as i64) & 7] = emu_x86_i32(code, pc + 3) 41 pc = pc + 7 42 } else { if op == 0x89 { // mov r/m64, r64 43 let m: i64 = code[pc+2] as i64 44 reg[m & 7] = reg[(m >> 3) & 7] 45 pc = pc + 3 46 } else { if op == 0xC1 { // shl r/m64, imm8 47 let m: i64 = code[pc+2] as i64 48 reg[m & 7] = reg[m & 7] << (code[pc+3] as i64) 49 pc = pc + 4 50 } else { if op == 0x01 { // add r/m64, r64 51 let m: i64 = code[pc+2] as i64 52 reg[m & 7] = reg[m & 7] + reg[(m >> 3) & 7] 53 pc = pc + 3 54 } else { if op == 0x29 { // sub r/m64, r64 55 let m: i64 = code[pc+2] as i64 56 reg[m & 7] = reg[m & 7] - reg[(m >> 3) & 7] 57 pc = pc + 3 58 } else { return 0 - 2 } } } } } 59 } 60 } 61 return 0 - 4 62}