diff options
Diffstat (limited to 'src/jit/dis_mips.lua')
-rw-r--r-- | src/jit/dis_mips.lua | 372 |
1 files changed, 319 insertions, 53 deletions
diff --git a/src/jit/dis_mips.lua b/src/jit/dis_mips.lua index c720b537..791ac91d 100644 --- a/src/jit/dis_mips.lua +++ b/src/jit/dis_mips.lua | |||
@@ -19,13 +19,34 @@ local band, bor, tohex = bit.band, bit.bor, bit.tohex | |||
19 | local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift | 19 | local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift |
20 | 20 | ||
21 | ------------------------------------------------------------------------------ | 21 | ------------------------------------------------------------------------------ |
22 | -- Primary and extended opcode maps | 22 | -- Extended opcode maps common to all MIPS releases |
23 | ------------------------------------------------------------------------------ | 23 | ------------------------------------------------------------------------------ |
24 | 24 | ||
25 | local map_movci = { shift = 16, mask = 1, [0] = "movfDSC", "movtDSC", } | ||
26 | local map_srl = { shift = 21, mask = 1, [0] = "srlDTA", "rotrDTA", } | 25 | local map_srl = { shift = 21, mask = 1, [0] = "srlDTA", "rotrDTA", } |
27 | local map_srlv = { shift = 6, mask = 1, [0] = "srlvDTS", "rotrvDTS", } | 26 | local map_srlv = { shift = 6, mask = 1, [0] = "srlvDTS", "rotrvDTS", } |
28 | 27 | ||
28 | local map_cop0 = { | ||
29 | shift = 25, mask = 1, | ||
30 | [0] = { | ||
31 | shift = 21, mask = 15, | ||
32 | [0] = "mfc0TDW", [4] = "mtc0TDW", | ||
33 | [10] = "rdpgprDT", | ||
34 | [11] = { shift = 5, mask = 1, [0] = "diT0", "eiT0", }, | ||
35 | [14] = "wrpgprDT", | ||
36 | }, { | ||
37 | shift = 0, mask = 63, | ||
38 | [1] = "tlbr", [2] = "tlbwi", [6] = "tlbwr", [8] = "tlbp", | ||
39 | [24] = "eret", [31] = "deret", | ||
40 | [32] = "wait", | ||
41 | }, | ||
42 | } | ||
43 | |||
44 | ------------------------------------------------------------------------------ | ||
45 | -- Primary and extended opcode maps for MIPS R1-R5 | ||
46 | ------------------------------------------------------------------------------ | ||
47 | |||
48 | local map_movci = { shift = 16, mask = 1, [0] = "movfDSC", "movtDSC", } | ||
49 | |||
29 | local map_special = { | 50 | local map_special = { |
30 | shift = 0, mask = 63, | 51 | shift = 0, mask = 63, |
31 | [0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" }, | 52 | [0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" }, |
@@ -34,15 +55,17 @@ local map_special = { | |||
34 | "jrS", "jalrD1S", "movzDST", "movnDST", | 55 | "jrS", "jalrD1S", "movzDST", "movnDST", |
35 | "syscallY", "breakY", false, "sync", | 56 | "syscallY", "breakY", false, "sync", |
36 | "mfhiD", "mthiS", "mfloD", "mtloS", | 57 | "mfhiD", "mthiS", "mfloD", "mtloS", |
37 | false, false, false, false, | 58 | "dsllvDST", false, "dsrlvDST", "dsravDST", |
38 | "multST", "multuST", "divST", "divuST", | 59 | "multST", "multuST", "divST", "divuST", |
39 | false, false, false, false, | 60 | "dmultST", "dmultuST", "ddivST", "ddivuST", |
40 | "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T", | 61 | "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T", |
41 | "andDST", "orDST", "xorDST", "nor|notDST0", | 62 | "andDST", "or|moveDST0", "xorDST", "nor|notDST0", |
42 | false, false, "sltDST", "sltuDST", | 63 | false, false, "sltDST", "sltuDST", |
43 | false, false, false, false, | 64 | "daddDST", "dadduDST", "dsubDST", "dsubuDST", |
44 | "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ", | 65 | "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ", |
45 | "teqSTZ", false, "tneSTZ", | 66 | "teqSTZ", false, "tneSTZ", false, |
67 | "dsllDTA", false, "dsrlDTA", "dsraDTA", | ||
68 | "dsll32DTA", false, "dsrl32DTA", "dsra32DTA", | ||
46 | } | 69 | } |
47 | 70 | ||
48 | local map_special2 = { | 71 | local map_special2 = { |
@@ -60,11 +83,17 @@ local map_bshfl = { | |||
60 | [24] = "sehDT", | 83 | [24] = "sehDT", |
61 | } | 84 | } |
62 | 85 | ||
86 | local map_dbshfl = { | ||
87 | shift = 6, mask = 31, | ||
88 | [2] = "dsbhDT", | ||
89 | [5] = "dshdDT", | ||
90 | } | ||
91 | |||
63 | local map_special3 = { | 92 | local map_special3 = { |
64 | shift = 0, mask = 63, | 93 | shift = 0, mask = 63, |
65 | [0] = "extTSAK", [4] = "insTSAL", | 94 | [0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK", |
66 | [32] = map_bshfl, | 95 | [4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL", |
67 | [59] = "rdhwrTD", | 96 | [32] = map_bshfl, [36] = map_dbshfl, [59] = "rdhwrTD", |
68 | } | 97 | } |
69 | 98 | ||
70 | local map_regimm = { | 99 | local map_regimm = { |
@@ -79,22 +108,6 @@ local map_regimm = { | |||
79 | false, false, false, "synciSO", | 108 | false, false, false, "synciSO", |
80 | } | 109 | } |
81 | 110 | ||
82 | local map_cop0 = { | ||
83 | shift = 25, mask = 1, | ||
84 | [0] = { | ||
85 | shift = 21, mask = 15, | ||
86 | [0] = "mfc0TDW", [4] = "mtc0TDW", | ||
87 | [10] = "rdpgprDT", | ||
88 | [11] = { shift = 5, mask = 1, [0] = "diT0", "eiT0", }, | ||
89 | [14] = "wrpgprDT", | ||
90 | }, { | ||
91 | shift = 0, mask = 63, | ||
92 | [1] = "tlbr", [2] = "tlbwi", [6] = "tlbwr", [8] = "tlbp", | ||
93 | [24] = "eret", [31] = "deret", | ||
94 | [32] = "wait", | ||
95 | }, | ||
96 | } | ||
97 | |||
98 | local map_cop1s = { | 111 | local map_cop1s = { |
99 | shift = 0, mask = 63, | 112 | shift = 0, mask = 63, |
100 | [0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH", | 113 | [0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH", |
@@ -178,8 +191,8 @@ local map_cop1bc = { | |||
178 | 191 | ||
179 | local map_cop1 = { | 192 | local map_cop1 = { |
180 | shift = 21, mask = 31, | 193 | shift = 21, mask = 31, |
181 | [0] = "mfc1TG", false, "cfc1TG", "mfhc1TG", | 194 | [0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG", |
182 | "mtc1TG", false, "ctc1TG", "mthc1TG", | 195 | "mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG", |
183 | map_cop1bc, false, false, false, | 196 | map_cop1bc, false, false, false, |
184 | false, false, false, false, | 197 | false, false, false, false, |
185 | map_cop1s, map_cop1d, false, false, | 198 | map_cop1s, map_cop1d, false, false, |
@@ -213,16 +226,218 @@ local map_pri = { | |||
213 | "andiTSU", "ori|liTS0U", "xoriTSU", "luiTU", | 226 | "andiTSU", "ori|liTS0U", "xoriTSU", "luiTU", |
214 | map_cop0, map_cop1, false, map_cop1x, | 227 | map_cop0, map_cop1, false, map_cop1x, |
215 | "beql|beqzlST0B", "bnel|bnezlST0B", "blezlSB", "bgtzlSB", | 228 | "beql|beqzlST0B", "bnel|bnezlST0B", "blezlSB", "bgtzlSB", |
216 | false, false, false, false, | 229 | "daddiTSI", "daddiuTSI", false, false, |
217 | map_special2, false, false, map_special3, | 230 | map_special2, "jalxJ", false, map_special3, |
218 | "lbTSO", "lhTSO", "lwlTSO", "lwTSO", | 231 | "lbTSO", "lhTSO", "lwlTSO", "lwTSO", |
219 | "lbuTSO", "lhuTSO", "lwrTSO", false, | 232 | "lbuTSO", "lhuTSO", "lwrTSO", false, |
220 | "sbTSO", "shTSO", "swlTSO", "swTSO", | 233 | "sbTSO", "shTSO", "swlTSO", "swTSO", |
221 | false, false, "swrTSO", "cacheNSO", | 234 | false, false, "swrTSO", "cacheNSO", |
222 | "llTSO", "lwc1HSO", "lwc2TSO", "prefNSO", | 235 | "llTSO", "lwc1HSO", "lwc2TSO", "prefNSO", |
223 | false, "ldc1HSO", "ldc2TSO", false, | 236 | false, "ldc1HSO", "ldc2TSO", "ldTSO", |
224 | "scTSO", "swc1HSO", "swc2TSO", false, | 237 | "scTSO", "swc1HSO", "swc2TSO", false, |
225 | false, "sdc1HSO", "sdc2TSO", false, | 238 | false, "sdc1HSO", "sdc2TSO", "sdTSO", |
239 | } | ||
240 | |||
241 | ------------------------------------------------------------------------------ | ||
242 | -- Primary and extended opcode maps for MIPS R6 | ||
243 | ------------------------------------------------------------------------------ | ||
244 | |||
245 | local map_mul_r6 = { shift = 6, mask = 3, [2] = "mulDST", [3] = "muhDST" } | ||
246 | local map_mulu_r6 = { shift = 6, mask = 3, [2] = "muluDST", [3] = "muhuDST" } | ||
247 | local map_div_r6 = { shift = 6, mask = 3, [2] = "divDST", [3] = "modDST" } | ||
248 | local map_divu_r6 = { shift = 6, mask = 3, [2] = "divuDST", [3] = "moduDST" } | ||
249 | local map_dmul_r6 = { shift = 6, mask = 3, [2] = "dmulDST", [3] = "dmuhDST" } | ||
250 | local map_dmulu_r6 = { shift = 6, mask = 3, [2] = "dmuluDST", [3] = "dmuhuDST" } | ||
251 | local map_ddiv_r6 = { shift = 6, mask = 3, [2] = "ddivDST", [3] = "dmodDST" } | ||
252 | local map_ddivu_r6 = { shift = 6, mask = 3, [2] = "ddivuDST", [3] = "dmoduDST" } | ||
253 | |||
254 | local map_special_r6 = { | ||
255 | shift = 0, mask = 63, | ||
256 | [0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" }, | ||
257 | false, map_srl, "sraDTA", | ||
258 | "sllvDTS", false, map_srlv, "sravDTS", | ||
259 | "jrS", "jalrD1S", false, false, | ||
260 | "syscallY", "breakY", false, "sync", | ||
261 | "clzDS", "cloDS", "dclzDS", "dcloDS", | ||
262 | "dsllvDST", "dlsaDSTA", "dsrlvDST", "dsravDST", | ||
263 | map_mul_r6, map_mulu_r6, map_div_r6, map_divu_r6, | ||
264 | map_dmul_r6, map_dmulu_r6, map_ddiv_r6, map_ddivu_r6, | ||
265 | "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T", | ||
266 | "andDST", "or|moveDST0", "xorDST", "nor|notDST0", | ||
267 | false, false, "sltDST", "sltuDST", | ||
268 | "daddDST", "dadduDST", "dsubDST", "dsubuDST", | ||
269 | "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ", | ||
270 | "teqSTZ", "seleqzDST", "tneSTZ", "selnezDST", | ||
271 | "dsllDTA", false, "dsrlDTA", "dsraDTA", | ||
272 | "dsll32DTA", false, "dsrl32DTA", "dsra32DTA", | ||
273 | } | ||
274 | |||
275 | local map_bshfl_r6 = { | ||
276 | shift = 9, mask = 3, | ||
277 | [1] = "alignDSTa", | ||
278 | _ = { | ||
279 | shift = 6, mask = 31, | ||
280 | [0] = "bitswapDT", | ||
281 | [2] = "wsbhDT", | ||
282 | [16] = "sebDT", | ||
283 | [24] = "sehDT", | ||
284 | } | ||
285 | } | ||
286 | |||
287 | local map_dbshfl_r6 = { | ||
288 | shift = 9, mask = 3, | ||
289 | [1] = "dalignDSTa", | ||
290 | _ = { | ||
291 | shift = 6, mask = 31, | ||
292 | [0] = "dbitswapDT", | ||
293 | [2] = "dsbhDT", | ||
294 | [5] = "dshdDT", | ||
295 | } | ||
296 | } | ||
297 | |||
298 | local map_special3_r6 = { | ||
299 | shift = 0, mask = 63, | ||
300 | [0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK", | ||
301 | [4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL", | ||
302 | [32] = map_bshfl_r6, [36] = map_dbshfl_r6, [59] = "rdhwrTD", | ||
303 | } | ||
304 | |||
305 | local map_regimm_r6 = { | ||
306 | shift = 16, mask = 31, | ||
307 | [0] = "bltzSB", [1] = "bgezSB", | ||
308 | [6] = "dahiSI", [30] = "datiSI", | ||
309 | [23] = "sigrieI", [31] = "synciSO", | ||
310 | } | ||
311 | |||
312 | local map_pcrel_r6 = { | ||
313 | shift = 19, mask = 3, | ||
314 | [0] = "addiupcS2", "lwpcS2", "lwupcS2", { | ||
315 | shift = 18, mask = 1, | ||
316 | [0] = "ldpcS3", { shift = 16, mask = 3, [2] = "auipcSI", [3] = "aluipcSI" } | ||
317 | } | ||
318 | } | ||
319 | |||
320 | local map_cop1s_r6 = { | ||
321 | shift = 0, mask = 63, | ||
322 | [0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH", | ||
323 | "sqrt.sFG", "abs.sFG", "mov.sFG", "neg.sFG", | ||
324 | "round.l.sFG", "trunc.l.sFG", "ceil.l.sFG", "floor.l.sFG", | ||
325 | "round.w.sFG", "trunc.w.sFG", "ceil.w.sFG", "floor.w.sFG", | ||
326 | "sel.sFGH", false, false, false, | ||
327 | "seleqz.sFGH", "recip.sFG", "rsqrt.sFG", "selnez.sFGH", | ||
328 | "maddf.sFGH", "msubf.sFGH", "rint.sFG", "class.sFG", | ||
329 | "min.sFGH", "mina.sFGH", "max.sFGH", "maxa.sFGH", | ||
330 | false, "cvt.d.sFG", false, false, | ||
331 | "cvt.w.sFG", "cvt.l.sFG", | ||
332 | } | ||
333 | |||
334 | local map_cop1d_r6 = { | ||
335 | shift = 0, mask = 63, | ||
336 | [0] = "add.dFGH", "sub.dFGH", "mul.dFGH", "div.dFGH", | ||
337 | "sqrt.dFG", "abs.dFG", "mov.dFG", "neg.dFG", | ||
338 | "round.l.dFG", "trunc.l.dFG", "ceil.l.dFG", "floor.l.dFG", | ||
339 | "round.w.dFG", "trunc.w.dFG", "ceil.w.dFG", "floor.w.dFG", | ||
340 | "sel.dFGH", false, false, false, | ||
341 | "seleqz.dFGH", "recip.dFG", "rsqrt.dFG", "selnez.dFGH", | ||
342 | "maddf.dFGH", "msubf.dFGH", "rint.dFG", "class.dFG", | ||
343 | "min.dFGH", "mina.dFGH", "max.dFGH", "maxa.dFGH", | ||
344 | "cvt.s.dFG", false, false, false, | ||
345 | "cvt.w.dFG", "cvt.l.dFG", | ||
346 | } | ||
347 | |||
348 | local map_cop1w_r6 = { | ||
349 | shift = 0, mask = 63, | ||
350 | [0] = "cmp.af.sFGH", "cmp.un.sFGH", "cmp.eq.sFGH", "cmp.ueq.sFGH", | ||
351 | "cmp.lt.sFGH", "cmp.ult.sFGH", "cmp.le.sFGH", "cmp.ule.sFGH", | ||
352 | "cmp.saf.sFGH", "cmp.sun.sFGH", "cmp.seq.sFGH", "cmp.sueq.sFGH", | ||
353 | "cmp.slt.sFGH", "cmp.sult.sFGH", "cmp.sle.sFGH", "cmp.sule.sFGH", | ||
354 | false, "cmp.or.sFGH", "cmp.une.sFGH", "cmp.ne.sFGH", | ||
355 | false, false, false, false, | ||
356 | false, "cmp.sor.sFGH", "cmp.sune.sFGH", "cmp.sne.sFGH", | ||
357 | false, false, false, false, | ||
358 | "cvt.s.wFG", "cvt.d.wFG", | ||
359 | } | ||
360 | |||
361 | local map_cop1l_r6 = { | ||
362 | shift = 0, mask = 63, | ||
363 | [0] = "cmp.af.dFGH", "cmp.un.dFGH", "cmp.eq.dFGH", "cmp.ueq.dFGH", | ||
364 | "cmp.lt.dFGH", "cmp.ult.dFGH", "cmp.le.dFGH", "cmp.ule.dFGH", | ||
365 | "cmp.saf.dFGH", "cmp.sun.dFGH", "cmp.seq.dFGH", "cmp.sueq.dFGH", | ||
366 | "cmp.slt.dFGH", "cmp.sult.dFGH", "cmp.sle.dFGH", "cmp.sule.dFGH", | ||
367 | false, "cmp.or.dFGH", "cmp.une.dFGH", "cmp.ne.dFGH", | ||
368 | false, false, false, false, | ||
369 | false, "cmp.sor.dFGH", "cmp.sune.dFGH", "cmp.sne.dFGH", | ||
370 | false, false, false, false, | ||
371 | "cvt.s.lFG", "cvt.d.lFG", | ||
372 | } | ||
373 | |||
374 | local map_cop1_r6 = { | ||
375 | shift = 21, mask = 31, | ||
376 | [0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG", | ||
377 | "mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG", | ||
378 | false, "bc1eqzHB", false, false, | ||
379 | false, "bc1nezHB", false, false, | ||
380 | map_cop1s_r6, map_cop1d_r6, false, false, | ||
381 | map_cop1w_r6, map_cop1l_r6, | ||
382 | } | ||
383 | |||
384 | local function maprs_popTS(rs, rt) | ||
385 | if rt == 0 then return 0 elseif rs == 0 then return 1 | ||
386 | elseif rs == rt then return 2 else return 3 end | ||
387 | end | ||
388 | |||
389 | local map_pop06_r6 = { | ||
390 | maprs = maprs_popTS, [0] = "blezSB", "blezalcTB", "bgezalcTB", "bgeucSTB" | ||
391 | } | ||
392 | local map_pop07_r6 = { | ||
393 | maprs = maprs_popTS, [0] = "bgtzSB", "bgtzalcTB", "bltzalcTB", "bltucSTB" | ||
394 | } | ||
395 | local map_pop26_r6 = { | ||
396 | maprs = maprs_popTS, "blezcTB", "bgezcTB", "bgecSTB" | ||
397 | } | ||
398 | local map_pop27_r6 = { | ||
399 | maprs = maprs_popTS, "bgtzcTB", "bltzcTB", "bltcSTB" | ||
400 | } | ||
401 | |||
402 | local function maprs_popS(rs, rt) | ||
403 | if rs == 0 then return 0 else return 1 end | ||
404 | end | ||
405 | |||
406 | local map_pop66_r6 = { | ||
407 | maprs = maprs_popS, [0] = "jicTI", "beqzcSb" | ||
408 | } | ||
409 | local map_pop76_r6 = { | ||
410 | maprs = maprs_popS, [0] = "jialcTI", "bnezcSb" | ||
411 | } | ||
412 | |||
413 | local function maprs_popST(rs, rt) | ||
414 | if rs >= rt then return 0 elseif rs == 0 then return 1 else return 2 end | ||
415 | end | ||
416 | |||
417 | local map_pop10_r6 = { | ||
418 | maprs = maprs_popST, [0] = "bovcSTB", "beqzalcTB", "beqcSTB" | ||
419 | } | ||
420 | local map_pop30_r6 = { | ||
421 | maprs = maprs_popST, [0] = "bnvcSTB", "bnezalcTB", "bnecSTB" | ||
422 | } | ||
423 | |||
424 | local map_pri_r6 = { | ||
425 | [0] = map_special_r6, map_regimm_r6, "jJ", "jalJ", | ||
426 | "beq|beqz|bST00B", "bne|bnezST0B", map_pop06_r6, map_pop07_r6, | ||
427 | map_pop10_r6, "addiu|liTS0I", "sltiTSI", "sltiuTSI", | ||
428 | "andiTSU", "ori|liTS0U", "xoriTSU", "aui|luiTS0U", | ||
429 | map_cop0, map_cop1_r6, false, false, | ||
430 | false, false, map_pop26_r6, map_pop27_r6, | ||
431 | map_pop30_r6, "daddiuTSI", false, false, | ||
432 | false, "dauiTSI", false, map_special3_r6, | ||
433 | "lbTSO", "lhTSO", false, "lwTSO", | ||
434 | "lbuTSO", "lhuTSO", false, false, | ||
435 | "sbTSO", "shTSO", false, "swTSO", | ||
436 | false, false, false, false, | ||
437 | false, "lwc1HSO", "bc#", false, | ||
438 | false, "ldc1HSO", map_pop66_r6, "ldTSO", | ||
439 | false, "swc1HSO", "balc#", map_pcrel_r6, | ||
440 | false, "sdc1HSO", map_pop76_r6, "sdTSO", | ||
226 | } | 441 | } |
227 | 442 | ||
228 | ------------------------------------------------------------------------------ | 443 | ------------------------------------------------------------------------------ |
@@ -279,10 +494,14 @@ local function disass_ins(ctx) | |||
279 | ctx.op = op | 494 | ctx.op = op |
280 | ctx.rel = nil | 495 | ctx.rel = nil |
281 | 496 | ||
282 | local opat = map_pri[rshift(op, 26)] | 497 | local opat = ctx.map_pri[rshift(op, 26)] |
283 | while type(opat) ~= "string" do | 498 | while type(opat) ~= "string" do |
284 | if not opat then return unknown(ctx) end | 499 | if not opat then return unknown(ctx) end |
285 | opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ | 500 | if opat.maprs then |
501 | opat = opat[opat.maprs(band(rshift(op,21),31), band(rshift(op,16),31))] | ||
502 | else | ||
503 | opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ | ||
504 | end | ||
286 | end | 505 | end |
287 | local name, pat = match(opat, "^([a-z0-9_.]*)(.*)") | 506 | local name, pat = match(opat, "^([a-z0-9_.]*)(.*)") |
288 | local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)") | 507 | local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)") |
@@ -306,6 +525,10 @@ local function disass_ins(ctx) | |||
306 | x = "f"..band(rshift(op, 21), 31) | 525 | x = "f"..band(rshift(op, 21), 31) |
307 | elseif p == "A" then | 526 | elseif p == "A" then |
308 | x = band(rshift(op, 6), 31) | 527 | x = band(rshift(op, 6), 31) |
528 | elseif p == "a" then | ||
529 | x = band(rshift(op, 6), 7) | ||
530 | elseif p == "E" then | ||
531 | x = band(rshift(op, 6), 31) + 32 | ||
309 | elseif p == "M" then | 532 | elseif p == "M" then |
310 | x = band(rshift(op, 11), 31) | 533 | x = band(rshift(op, 11), 31) |
311 | elseif p == "N" then | 534 | elseif p == "N" then |
@@ -315,10 +538,18 @@ local function disass_ins(ctx) | |||
315 | if x == 0 then x = nil end | 538 | if x == 0 then x = nil end |
316 | elseif p == "K" then | 539 | elseif p == "K" then |
317 | x = band(rshift(op, 11), 31) + 1 | 540 | x = band(rshift(op, 11), 31) + 1 |
541 | elseif p == "P" then | ||
542 | x = band(rshift(op, 11), 31) + 33 | ||
318 | elseif p == "L" then | 543 | elseif p == "L" then |
319 | x = band(rshift(op, 11), 31) - last + 1 | 544 | x = band(rshift(op, 11), 31) - last + 1 |
545 | elseif p == "Q" then | ||
546 | x = band(rshift(op, 11), 31) - last + 33 | ||
320 | elseif p == "I" then | 547 | elseif p == "I" then |
321 | x = arshift(lshift(op, 16), 16) | 548 | x = arshift(lshift(op, 16), 16) |
549 | elseif p == "2" then | ||
550 | x = arshift(lshift(op, 13), 11) | ||
551 | elseif p == "3" then | ||
552 | x = arshift(lshift(op, 14), 11) | ||
322 | elseif p == "U" then | 553 | elseif p == "U" then |
323 | x = band(op, 0xffff) | 554 | x = band(op, 0xffff) |
324 | elseif p == "O" then | 555 | elseif p == "O" then |
@@ -328,13 +559,22 @@ local function disass_ins(ctx) | |||
328 | local index = map_gpr[band(rshift(op, 16), 31)] | 559 | local index = map_gpr[band(rshift(op, 16), 31)] |
329 | operands[#operands] = format("%s(%s)", index, last) | 560 | operands[#operands] = format("%s(%s)", index, last) |
330 | elseif p == "B" then | 561 | elseif p == "B" then |
331 | x = ctx.addr + ctx.pos + arshift(lshift(op, 16), 16)*4 + 4 | 562 | x = ctx.addr + ctx.pos + arshift(lshift(op, 16), 14) + 4 |
563 | ctx.rel = x | ||
564 | x = format("0x%08x", x) | ||
565 | elseif p == "b" then | ||
566 | x = ctx.addr + ctx.pos + arshift(lshift(op, 11), 9) + 4 | ||
332 | ctx.rel = x | 567 | ctx.rel = x |
333 | x = "0x"..tohex(x) | 568 | x = format("0x%08x", x) |
569 | elseif p == "#" then | ||
570 | x = ctx.addr + ctx.pos + arshift(lshift(op, 6), 4) + 4 | ||
571 | ctx.rel = x | ||
572 | x = format("0x%08x", x) | ||
334 | elseif p == "J" then | 573 | elseif p == "J" then |
335 | x = band(ctx.addr + ctx.pos, 0xf0000000) + band(op, 0x03ffffff)*4 | 574 | local a = ctx.addr + ctx.pos |
575 | x = a - band(a, 0x0fffffff) + band(op, 0x03ffffff)*4 | ||
336 | ctx.rel = x | 576 | ctx.rel = x |
337 | x = "0x"..tohex(x) | 577 | x = format("0x%08x", x) |
338 | elseif p == "V" then | 578 | elseif p == "V" then |
339 | x = band(rshift(op, 8), 7) | 579 | x = band(rshift(op, 8), 7) |
340 | if x == 0 then x = nil end | 580 | if x == 0 then x = nil end |
@@ -384,7 +624,7 @@ local function disass_block(ctx, ofs, len) | |||
384 | end | 624 | end |
385 | 625 | ||
386 | -- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). | 626 | -- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). |
387 | local function create_(code, addr, out) | 627 | local function create(code, addr, out) |
388 | local ctx = {} | 628 | local ctx = {} |
389 | ctx.code = code | 629 | ctx.code = code |
390 | ctx.addr = addr or 0 | 630 | ctx.addr = addr or 0 |
@@ -393,36 +633,62 @@ local function create_(code, addr, out) | |||
393 | ctx.disass = disass_block | 633 | ctx.disass = disass_block |
394 | ctx.hexdump = 8 | 634 | ctx.hexdump = 8 |
395 | ctx.get = get_be | 635 | ctx.get = get_be |
636 | ctx.map_pri = map_pri | ||
637 | return ctx | ||
638 | end | ||
639 | |||
640 | local function create_el(code, addr, out) | ||
641 | local ctx = create(code, addr, out) | ||
642 | ctx.get = get_le | ||
643 | return ctx | ||
644 | end | ||
645 | |||
646 | local function create_r6(code, addr, out) | ||
647 | local ctx = create(code, addr, out) | ||
648 | ctx.map_pri = map_pri_r6 | ||
396 | return ctx | 649 | return ctx |
397 | end | 650 | end |
398 | 651 | ||
399 | local function create_el_(code, addr, out) | 652 | local function create_r6_el(code, addr, out) |
400 | local ctx = create_(code, addr, out) | 653 | local ctx = create(code, addr, out) |
401 | ctx.get = get_le | 654 | ctx.get = get_le |
655 | ctx.map_pri = map_pri_r6 | ||
402 | return ctx | 656 | return ctx |
403 | end | 657 | end |
404 | 658 | ||
405 | -- Simple API: disassemble code (a string) at address and output via out. | 659 | -- Simple API: disassemble code (a string) at address and output via out. |
406 | local function disass_(code, addr, out) | 660 | local function disass(code, addr, out) |
407 | create_(code, addr, out):disass() | 661 | create(code, addr, out):disass() |
662 | end | ||
663 | |||
664 | local function disass_el(code, addr, out) | ||
665 | create_el(code, addr, out):disass() | ||
408 | end | 666 | end |
409 | 667 | ||
410 | local function disass_el_(code, addr, out) | 668 | local function disass_r6(code, addr, out) |
411 | create_el_(code, addr, out):disass() | 669 | create_r6(code, addr, out):disass() |
670 | end | ||
671 | |||
672 | local function disass_r6_el(code, addr, out) | ||
673 | create_r6_el(code, addr, out):disass() | ||
412 | end | 674 | end |
413 | 675 | ||
414 | -- Return register name for RID. | 676 | -- Return register name for RID. |
415 | local function regname_(r) | 677 | local function regname(r) |
416 | if r < 32 then return map_gpr[r] end | 678 | if r < 32 then return map_gpr[r] end |
417 | return "f"..(r-32) | 679 | return "f"..(r-32) |
418 | end | 680 | end |
419 | 681 | ||
420 | -- Public module functions. | 682 | -- Public module functions. |
421 | module(...) | 683 | return { |
422 | 684 | create = create, | |
423 | create = create_ | 685 | create_el = create_el, |
424 | create_el = create_el_ | 686 | create_r6 = create_r6, |
425 | disass = disass_ | 687 | create_r6_el = create_r6_el, |
426 | disass_el = disass_el_ | 688 | disass = disass, |
427 | regname = regname_ | 689 | disass_el = disass_el, |
690 | disass_r6 = disass_r6, | ||
691 | disass_r6_el = disass_r6_el, | ||
692 | regname = regname | ||
693 | } | ||
428 | 694 | ||