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}