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}