code wiki / (root) / nx_emu_cortexm.nx

nx_emu_cortexm.nx source

↩ module page · 167 lines · 8858 B

1// nx_emu_cortexm.nx -- sovereign ARMv7-M / Cortex-M (Thumb-2) interpreter (NX-EMU). 2// Little-endian, MIXED 16/32-bit instructions (32-bit iff hw1[15:11] in {11101,11110, 3// 11111} i.e. hw1>=0xE800), 16 GPRs + C flag. Decodes the subset nxc2's cortex_m 4// backend emits: push/pop, mov(hi), movs, adds/subs/adcs/sbcs, sub-sp, ldr/str (16-bit 5// imm5 + 32-bit T4 neg-offset), blx, movw, umull, mla, subw. Bare-metal: BKPT halts 6// with result=r0 (no OS). NO qemu. license_tier: ORIGINAL 7import "nx_syscalls_x86_64.nx" 8 9const CM_GUEST: i64 = 16777216 10const CM_MASK: i64 = 0xFFFFFFFF 11 12func cm_ld(mem: *u8, va: i64, width: i64) -> i64 { var v: i64 = 0; var i: i64 = 0; while i < width { v = v | ((mem[va + i] & 0xff) << (i * 8)); i = i + 1 } return v } 13func cm_st(mem: *u8, va: i64, width: i64, val: i64) -> i64 { var i: i64 = 0; while i < width { mem[va + i] = (val >> (i * 8)) & 0xff; i = i + 1 } return 0 } 14 15func emu_cortexm_run_mem(mem: *u8, mem_size: i64, entry: i64, sp0: i64) -> i64 { 16 let r: *i64 = sys_mmap(16 * 8) as *i64 17 var i: i64 = 0 18 while i < 16 { r[i] = 0; i = i + 1 } 19 r[13] = sp0 20 var pc: i64 = entry 21 var cf: i64 = 0 22 var result: i64 = 0 23 var halted: i64 = 0 24 var steps: i64 = 0 25 while halted == 0 { 26 if steps > 5000000 { halted = 1 } else { 27 let hw1: i64 = cm_ld(mem, pc, 2) 28 var next: i64 = pc + 2 29 var handled: i64 = 0 30 if (hw1 & 0xF800) >= 0xE800 { 31 // ---- 32-bit Thumb-2 ---- 32 let hw2: i64 = cm_ld(mem, pc + 2, 2) 33 next = pc + 4 34 if (hw1 & 0xFBF0) == 0xF240 { // MOVW 35 handled = 1 36 let rd: i64 = (hw2 >> 8) & 0xF 37 let imm: i64 = (((hw1 & 0xF) << 12) | (((hw1 >> 10) & 1) << 11) | (((hw2 >> 12) & 7) << 8) | (hw2 & 0xFF)) 38 r[rd] = imm 39 } 40 if (hw1 & 0xFBF0) == 0xF2A0 { // SUBW (T4, plain imm12) 41 handled = 1 42 let rn: i64 = hw1 & 0xF 43 let rd: i64 = (hw2 >> 8) & 0xF 44 let imm: i64 = (((hw1 >> 10) & 1) << 11) | (((hw2 >> 12) & 7) << 8) | (hw2 & 0xFF) 45 r[rd] = (r[rn] - imm) & CM_MASK 46 } 47 if (hw1 & 0xFFF0) == 0xFBA0 { // UMULL 48 handled = 1 49 let rn: i64 = hw1 & 0xF 50 let rdlo: i64 = (hw2 >> 12) & 0xF 51 let rdhi: i64 = (hw2 >> 8) & 0xF 52 let rm: i64 = hw2 & 0xF 53 let p: i64 = (r[rn] & CM_MASK) * (r[rm] & CM_MASK) 54 r[rdlo] = p & CM_MASK 55 r[rdhi] = (p >> 32) & CM_MASK 56 } 57 if (hw1 & 0xFFF0) == 0xFB00 { if (hw2 & 0xF0) == 0x00 { // MLA 58 handled = 1 59 let rn: i64 = hw1 & 0xF 60 let ra: i64 = (hw2 >> 12) & 0xF 61 let rd: i64 = (hw2 >> 8) & 0xF 62 let rm: i64 = hw2 & 0xF 63 r[rd] = (r[rn] * r[rm] + r[ra]) & CM_MASK 64 } } 65 if (hw1 & 0xFFF0) == 0xF850 { // LDR (T4) 66 handled = 1 67 let rn: i64 = hw1 & 0xF 68 let rt: i64 = (hw2 >> 12) & 0xF 69 let U: i64 = (hw2 >> 9) & 1 70 var off: i64 = hw2 & 0xFF 71 if U == 0 { off = 0 - off } 72 r[rt] = cm_ld(mem, (r[rn] + off) & CM_MASK, 4) & CM_MASK 73 } 74 if (hw1 & 0xFFF0) == 0xF840 { // STR (T4) 75 handled = 1 76 let rn: i64 = hw1 & 0xF 77 let rt: i64 = (hw2 >> 12) & 0xF 78 let U: i64 = (hw2 >> 9) & 1 79 var off: i64 = hw2 & 0xFF 80 if U == 0 { off = 0 - off } 81 cm_st(mem, (r[rn] + off) & CM_MASK, 4, r[rt] & CM_MASK) 82 } 83 } else { 84 // ---- 16-bit Thumb ---- 85 if (hw1 & 0xFF00) == 0xBE00 { handled = 1; result = r[0] & 0xff; halted = 1 } // BKPT -> halt 86 if (hw1 & 0xFF87) == 0x4780 { handled = 1; let rm: i64 = (hw1 >> 3) & 0xF; r[14] = (pc + 2) | 1; next = r[rm] & (CM_MASK - 1) } // BLX reg 87 if (hw1 & 0xFE00) == 0xB400 { // PUSH 88 handled = 1 89 var list: i64 = hw1 & 0xFF 90 if ((hw1 >> 8) & 1) == 1 { list = list | (1 << 14) } // M -> lr 91 var cnt: i64 = 0; var k: i64 = 0; while k < 16 { if (list & (1<<k)) != 0 { cnt = cnt + 1 } k = k + 1 } 92 var addr: i64 = (r[13] - 4 * cnt) & CM_MASK 93 r[13] = addr 94 k = 0; while k < 16 { if (list & (1<<k)) != 0 { cm_st(mem, addr, 4, r[k] & CM_MASK); addr = addr + 4 } k = k + 1 } 95 } 96 if (hw1 & 0xFE00) == 0xBC00 { // POP 97 handled = 1 98 var list: i64 = hw1 & 0xFF 99 var ppc: i64 = (hw1 >> 8) & 1 // P -> pc 100 var addr: i64 = r[13] 101 var k: i64 = 0; while k < 16 { if (list & (1<<k)) != 0 { r[k] = cm_ld(mem, addr, 4) & CM_MASK; addr = addr + 4 } k = k + 1 } 102 if ppc == 1 { next = cm_ld(mem, addr, 4) & (CM_MASK - 1); addr = addr + 4 } 103 r[13] = addr 104 } 105 if (hw1 & 0xFF00) == 0x4600 { // MOV (hi) 106 handled = 1 107 let rd: i64 = (((hw1 >> 7) & 1) << 3) | (hw1 & 7) 108 let rm: i64 = (hw1 >> 3) & 0xF 109 r[rd] = r[rm] & CM_MASK 110 } 111 if (hw1 & 0xF800) == 0x2000 { // MOVS imm8 112 handled = 1 113 r[(hw1 >> 8) & 7] = hw1 & 0xFF 114 } 115 if (hw1 & 0xFE00) == 0x1800 { // ADDS 3-reg 116 handled = 1 117 let rm: i64 = (hw1 >> 6) & 7; let rn: i64 = (hw1 >> 3) & 7; let rd: i64 = hw1 & 7 118 let s2: i64 = (r[rn] & CM_MASK) + (r[rm] & CM_MASK); cf = (s2 >> 32) & 1; r[rd] = s2 & CM_MASK 119 } 120 if (hw1 & 0xFE00) == 0x1A00 { // SUBS 3-reg 121 handled = 1 122 let rm: i64 = (hw1 >> 6) & 7; let rn: i64 = (hw1 >> 3) & 7; let rd: i64 = hw1 & 7 123 let a: i64 = r[rn] & CM_MASK; let b: i64 = r[rm] & CM_MASK 124 if a < b { cf = 0 } else { cf = 1 } 125 r[rd] = (a - b) & CM_MASK 126 } 127 if (hw1 & 0xFFC0) == 0x4140 { // ADCS rdn,rm 128 handled = 1 129 let rm: i64 = (hw1 >> 3) & 7; let rd: i64 = hw1 & 7 130 let s2: i64 = (r[rd] & CM_MASK) + (r[rm] & CM_MASK) + cf; cf = (s2 >> 32) & 1; r[rd] = s2 & CM_MASK 131 } 132 if (hw1 & 0xFFC0) == 0x4180 { // SBCS rdn,rm 133 handled = 1 134 let rm: i64 = (hw1 >> 3) & 7; let rd: i64 = hw1 & 7 135 let a: i64 = r[rd] & CM_MASK; let b: i64 = r[rm] & CM_MASK 136 r[rd] = (a - b - (1 - cf)) & CM_MASK 137 if a >= (b + (1 - cf)) { cf = 1 } else { cf = 0 } 138 } 139 if (hw1 & 0xF800) == 0x6800 { // LDR imm5 140 handled = 1 141 let imm: i64 = ((hw1 >> 6) & 0x1F) * 4; let rn: i64 = (hw1 >> 3) & 7; let rt: i64 = hw1 & 7 142 r[rt] = cm_ld(mem, (r[rn] + imm) & CM_MASK, 4) & CM_MASK 143 } 144 if (hw1 & 0xF800) == 0x6000 { // STR imm5 145 handled = 1 146 let imm: i64 = ((hw1 >> 6) & 0x1F) * 4; let rn: i64 = (hw1 >> 3) & 7; let rt: i64 = hw1 & 7 147 cm_st(mem, (r[rn] + imm) & CM_MASK, 4, r[rt] & CM_MASK) 148 } 149 if (hw1 & 0xFF80) == 0xB080 { // SUB SP imm7 150 handled = 1 151 r[13] = (r[13] - (hw1 & 0x7F) * 4) & CM_MASK 152 } 153 } 154 if handled == 0 { result = 0 - 1; halted = 1 } 155 pc = next 156 steps = steps + 1 157 } 158 } 159 return result 160} 161 162func emu_cortexm_run(code: *u8, code_len: i64) -> i64 { 163 let mem: *u8 = sys_mmap(CM_GUEST) 164 var i: i64 = 0 165 while i < code_len { mem[i] = code[i]; i = i + 1 } 166 return emu_cortexm_run_mem(mem, CM_GUEST, 0, 0x00800000) // entry at offset 0 (aligned) 167}