code wiki / (root) / nx_emu_s390x.nx

nx_emu_s390x.nx source

↩ module page · 138 lines · 6310 B

1// nx_emu_s390x.nx -- sovereign IBM Z (s390x) interpreter (NX-EMU). 2// 64-bit big-endian, 16 GPRs, VARIABLE-LENGTH instructions (length from the top 2 3// bits of byte0: 00->2, 01/10->4, 11->6). Decodes the subset nxc2's s390x backend 4// emits: BCR(br) RI(aghi/lghi) RRE(agr/lgr/msgr/sgr) RX(la) RXY(lg/stg) RSY(lmg/stmg) 5// RIL(brasl) + SVC. Linux s390x: svc <imm>=number, args r2.., exit=1 (code in r2). 6// NO qemu. license_tier: ORIGINAL 7import "nx_syscalls_x86_64.nx" 8 9const SZ_GUEST: i64 = 16777216 10const SZ_SYS_EXIT: i64 = 1 11 12func sz_ld(mem: *u8, va: i64, width: i64) -> i64 { var v: i64 = 0; var i: i64 = 0; while i < width { v = (v << 8) | (mem[va + i] & 0xff); i = i + 1 } return v } // big-endian 13func sz_st(mem: *u8, va: i64, width: i64, val: i64) -> i64 { var i: i64 = 0; while i < width { mem[va + (width - 1 - i)] = (val >> (i * 8)) & 0xff; i = i + 1 } return 0 } 14func sz_sx(v: i64, bits: i64) -> i64 { let m: i64 = 1 << (bits - 1); if (v & m) != 0 { return v - (1 << bits) } return v } 15 16func emu_s390x_run_mem(mem: *u8, mem_size: i64, entry: i64, sp0: i64) -> i64 { 17 let r: *i64 = sys_mmap(16 * 8) as *i64 18 var i: i64 = 0 19 while i < 16 { r[i] = 0; i = i + 1 } 20 r[15] = sp0 21 var pc: i64 = entry 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 b0: i64 = mem[pc] & 0xff 28 let hi2: i64 = b0 >> 6 29 var len: i64 = 4 30 if hi2 == 0 { len = 2 } 31 if hi2 == 3 { len = 6 } 32 var next: i64 = pc + len 33 var handled: i64 = 0 34 if b0 == 0x07 { // BCR (br = bcr 15,r2) 35 handled = 1 36 let b1: i64 = mem[pc+1] & 0xff 37 let mask: i64 = b1 >> 4 38 let r2: i64 = b1 & 0xF 39 if mask == 15 { next = r[r2] } 40 } 41 if b0 == 0x0A { // SVC 42 handled = 1 43 let imm: i64 = mem[pc+1] & 0xff 44 if imm == SZ_SYS_EXIT { result = r[2] & 0xff; halted = 1 } 45 } 46 if b0 == 0xA7 { // RI: aghi/lghi 47 handled = 1 48 let b1: i64 = mem[pc+1] & 0xff 49 let r1: i64 = b1 >> 4 50 let op2: i64 = b1 & 0xF 51 let imm: i64 = sz_sx(sz_ld(mem, pc+2, 2), 16) 52 if op2 == 0xA { r[r1] = r[r1] + imm } // aghi 53 if op2 == 0x9 { r[r1] = imm } // lghi 54 } 55 if b0 == 0xB9 { // RRE: agr/lgr/msgr/sgr 56 handled = 1 57 let op2: i64 = mem[pc+1] & 0xff 58 let b3: i64 = mem[pc+3] & 0xff 59 let r1: i64 = b3 >> 4 60 let r2: i64 = b3 & 0xF 61 if op2 == 0x08 { r[r1] = r[r1] + r[r2] } // agr 62 if op2 == 0x04 { r[r1] = r[r2] } // lgr 63 if op2 == 0x0C { r[r1] = r[r1] * r[r2] } // msgr 64 if op2 == 0x09 { r[r1] = r[r1] - r[r2] } // sgr 65 } 66 if b0 == 0x41 { // RX: la 67 handled = 1 68 let b1: i64 = mem[pc+1] & 0xff 69 let r1: i64 = b1 >> 4 70 let x2: i64 = b1 & 0xF 71 let bb: i64 = mem[pc+2] & 0xff 72 let b2: i64 = bb >> 4 73 let d: i64 = ((bb & 0xF) << 8) | (mem[pc+3] & 0xff) 74 var ea: i64 = r[b2] + d 75 if x2 != 0 { ea = ea + r[x2] } 76 r[r1] = ea 77 } 78 if b0 == 0xE3 { // RXY: lg/stg 79 handled = 1 80 let b1: i64 = mem[pc+1] & 0xff 81 let r1: i64 = b1 >> 4 82 let x2: i64 = b1 & 0xF 83 let bb: i64 = mem[pc+2] & 0xff 84 let b2: i64 = bb >> 4 85 let DL: i64 = ((bb & 0xF) << 8) | (mem[pc+3] & 0xff) 86 let DH: i64 = mem[pc+4] & 0xff 87 let op2: i64 = mem[pc+5] & 0xff 88 var disp: i64 = DL | (DH << 12) 89 if (disp & 0x80000) != 0 { disp = disp - 0x100000 } 90 var ea: i64 = r[b2] + disp 91 if x2 != 0 { ea = ea + r[x2] } 92 if op2 == 0x04 { r[r1] = sz_ld(mem, ea, 8) } // lg 93 if op2 == 0x24 { sz_st(mem, ea, 8, r[r1]) } // stg 94 } 95 if b0 == 0xEB { // RSY: lmg/stmg 96 handled = 1 97 let b1: i64 = mem[pc+1] & 0xff 98 let r1: i64 = b1 >> 4 99 let r3: i64 = b1 & 0xF 100 let bb: i64 = mem[pc+2] & 0xff 101 let b2: i64 = bb >> 4 102 let DL: i64 = ((bb & 0xF) << 8) | (mem[pc+3] & 0xff) 103 let DH: i64 = mem[pc+4] & 0xff 104 let op2: i64 = mem[pc+5] & 0xff 105 var disp: i64 = DL | (DH << 12) 106 if (disp & 0x80000) != 0 { disp = disp - 0x100000 } 107 var ea: i64 = r[b2] + disp 108 var reg: i64 = r1 109 var go: i64 = 1 110 while go == 1 { 111 if op2 == 0x04 { r[reg] = sz_ld(mem, ea, 8) } // lmg 112 if op2 == 0x24 { sz_st(mem, ea, 8, r[reg]) } // stmg 113 ea = ea + 8 114 if reg == r3 { go = 0 } else { reg = (reg + 1) & 0xF } 115 } 116 } 117 if b0 == 0xC0 { // RIL: brasl 118 handled = 1 119 let b1: i64 = mem[pc+1] & 0xff 120 let r1: i64 = b1 >> 4 121 let op2: i64 = b1 & 0xF 122 let imm: i64 = sz_sx(sz_ld(mem, pc+2, 4), 32) 123 if op2 == 0x5 { r[r1] = pc + 6; next = pc + imm * 2 } // brasl 124 } 125 if handled == 0 { result = 0 - 1; halted = 1 } 126 pc = next 127 steps = steps + 1 128 } 129 } 130 return result 131} 132 133func emu_s390x_run(code: *u8, code_len: i64) -> i64 { 134 let mem: *u8 = sys_mmap(SZ_GUEST) 135 var i: i64 = 0 136 while i < code_len { mem[i] = code[i]; i = i + 1 } 137 return emu_s390x_run_mem(mem, SZ_GUEST, 0, 0x00800000) 138}