aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dynasm/dasm_ppc.lua2
-rw-r--r--lib/dis_ppc.lua578
2 files changed, 579 insertions, 1 deletions
diff --git a/dynasm/dasm_ppc.lua b/dynasm/dasm_ppc.lua
index 8ff92585..4e078827 100644
--- a/dynasm/dasm_ppc.lua
+++ b/dynasm/dasm_ppc.lua
@@ -526,7 +526,7 @@ local map_op = {
526 frip_2 = "fc000390F-F.", 526 frip_2 = "fc000390F-F.",
527 frim_2 = "fc0003d0F-F.", 527 frim_2 = "fc0003d0F-F.",
528 mffs_1 = "fc00048eF.", 528 mffs_1 = "fc00048eF.",
529 mtfsf_1 = "fc00058eF.", 529 -- NYI: mtfsf, mtfsb0, mtfsb1.
530 fctid_2 = "fc00065cF-F.", 530 fctid_2 = "fc00065cF-F.",
531 fctidz_2 = "fc00065eF-F.", 531 fctidz_2 = "fc00065eF-F.",
532 fcfid_2 = "fc00069cF-F.", 532 fcfid_2 = "fc00069cF-F.",
diff --git a/lib/dis_ppc.lua b/lib/dis_ppc.lua
new file mode 100644
index 00000000..13d87c70
--- /dev/null
+++ b/lib/dis_ppc.lua
@@ -0,0 +1,578 @@
1----------------------------------------------------------------------------
2-- LuaJIT PPC disassembler module.
3--
4-- Copyright (C) 2005-2010 Mike Pall. All rights reserved.
5-- Released under the MIT/X license. See Copyright Notice in luajit.h
6----------------------------------------------------------------------------
7-- This is a helper module used by the LuaJIT machine code dumper module.
8--
9-- It disassembles all common, non-privileged 32/64 bit PowerPC instructions
10-- plus the e500 SPE instructions and some Cell/Xenon extensions.
11--
12-- NYI: VMX, VMX128
13------------------------------------------------------------------------------
14
15local type = type
16local sub, byte, format = string.sub, string.byte, string.format
17local match, gmatch, gsub = string.match, string.gmatch, string.gsub
18local concat = table.concat
19local bit = require("bit")
20local band, bor, tohex = bit.band, bit.bor, bit.tohex
21local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift
22
23------------------------------------------------------------------------------
24-- Primary and extended opcode maps
25------------------------------------------------------------------------------
26
27local map_crops = {
28 shift = 1, mask = 1023,
29 [0] = "mcrfXX",
30 [33] = "crnor|crnotCCC=", [129] = "crandcCCC",
31 [193] = "crxor|crclrCCC%", [225] = "crnandCCC",
32 [257] = "crandCCC", [289] = "creqv|crsetCCC%",
33 [417] = "crorcCCC", [449] = "cror|crmoveCCC=",
34 [16] = "b_lrKB", [528] = "b_ctrKB",
35 [150] = "isync",
36}
37
38local map_rld = {
39 shift = 2, mask = 7,
40 [0] = "rldiclRR~HM.", "rldicrRR~HM.", "rldicRR~HM.", "rldimiRR~HM.",
41 {
42 shift = 1, mask = 1,
43 [0] = "rldclRR~HM.", "rldcrRR~HM.",
44 },
45}
46
47local map_ext = setmetatable({
48 shift = 1, mask = 1023,
49
50 [0] = "cmp_YLRR", [32] = "cmpl_YLRR",
51 [4] = "twARR", [68] = "tdARR",
52
53 [8] = "subfcRRR.", [40] = "subfRRR.",
54 [104] = "negRR.", [136] = "subfeRRR.",
55 [200] = "subfzeRR.", [232] = "subfmeRR.",
56 [520] = "subfcoRRR.", [552] = "subfoRRR.",
57 [616] = "negoRR.", [648] = "subfeoRRR.",
58 [712] = "subfzeoRR.", [744] = "subfmeoRR.",
59
60 [9] = "mulhduRRR.", [73] = "mulhdRRR.", [233] = "mulldRRR.",
61 [457] = "divduRRR.", [489] = "divdRRR.",
62 [745] = "mulldoRRR.",
63 [969] = "divduoRRR.", [1001] = "divdoRRR.",
64
65 [10] = "addcRRR.", [138] = "addeRRR.",
66 [202] = "addzeRR.", [234] = "addmeRR.", [266] = "addRRR.",
67 [522] = "addcoRRR.", [650] = "addeoRRR.",
68 [714] = "addzeoRR.", [746] = "addmeoRR.", [778] = "addoRRR.",
69
70 [11] = "mulhwuRRR.", [75] = "mulhwRRR.", [235] = "mullwRRR.",
71 [459] = "divwuRRR.", [491] = "divwRRR.",
72 [747] = "mullwoRRR.",
73 [971] = "divwouRRR.", [1003] = "divwoRRR.",
74
75 [15] = "iselltRRR", [47] = "iselgtRRR", [79] = "iseleqRRR",
76
77 [144] = { shift = 20, mask = 1, [0] = "mtcrfRZ~", "mtocrfRZ~", },
78 [19] = { shift = 20, mask = 1, [0] = "mfcrR", "mfocrfRZ", },
79 [371] = { shift = 11, mask = 1023, [392] = "mftbR", [424] = "mftbuR", },
80 [339] = {
81 shift = 11, mask = 1023,
82 [32] = "mferR", [256] = "mflrR", [288] = "mfctrR", [16] = "mfspefscrR",
83 },
84 [467] = {
85 shift = 11, mask = 1023,
86 [32] = "mtxerR", [256] = "mtlrR", [288] = "mtctrR", [16] = "mtspefscrR",
87 },
88
89 [20] = "lwarxRR0R", [84] = "ldarxRR0R",
90
91 [21] = "ldxRR0R", [53] = "lduxRRR",
92 [149] = "stdxRR0R", [181] = "stduxRRR",
93 [341] = "lwaxRR0R", [373] = "lwauxRRR",
94
95 [23] = "lwzxRR0R", [55] = "lwzuxRRR",
96 [87] = "lbzxRR0R", [119] = "lbzuxRRR",
97 [151] = "stwxRR0R", [183] = "stwuxRRR",
98 [215] = "stbxRR0R", [247] = "stbuxRRR",
99 [279] = "lhzxRR0R", [311] = "lhzuxRRR",
100 [343] = "lhaxRR0R", [375] = "lhauxRRR",
101 [407] = "sthxRR0R", [439] = "sthuxRRR",
102
103 [54] = "dcbst-R0R", [86] = "dcbf-R0R",
104 [150] = "stwcxRR0R.", [214] = "stdcxRR0R.",
105 [246] = "dcbtst-R0R", [278] = "dcbt-R0R",
106 [310] = "eciwxRR0R", [438] = "ecowxRR0R",
107 [470] = "dcbi-RR",
108
109 [598] = {
110 shift = 21, mask = 3,
111 [0] = "sync", "lwsync", "ptesync",
112 },
113 [758] = "dcba-RR",
114 [854] = "eieio", [982] = "icbi-R0R", [1014] = "dcbz-R0R",
115
116 [26] = "cntlzwRR~", [58] = "cntlzdRR~",
117 [122] = "popcntbRR~",
118 [154] = "prtywRR~", [186] = "prtydRR~",
119
120 [28] = "andRR~R.", [60] = "andcRR~R.", [124] = "nor|notRR~R=.",
121 [284] = "eqvRR~R.", [316] = "xorRR~R.",
122 [412] = "orcRR~R.", [444] = "or|mrRR~R=.", [476] = "nandRR~R.",
123 [508] = "cmpbRR~R",
124
125 [512] = "mcrxrX",
126
127 [532] = "ldbrxRR0R", [660] = "stdbrxRR0R",
128
129 [533] = "lswxRR0R", [597] = "lswiRR0A",
130 [661] = "stswxRR0R", [725] = "stswiRR0A",
131
132 [534] = "lwbrxRR0R", [662] = "stwbrxRR0R",
133 [790] = "lhbrxRR0R", [918] = "sthbrxRR0R",
134
135 [535] = "lfsxFR0R", [567] = "lfsuxFRR",
136 [599] = "lfdxFR0R", [631] = "lfduxFRR",
137 [663] = "stfsxFR0R", [695] = "stfsuxFRR",
138 [727] = "stfdxFR0R", [759] = "stfduxFR0R",
139 [855] = "lfiwaxFR0R",
140 [983] = "stfiwxFR0R",
141
142 [24] = "slwRR~R.",
143
144 [27] = "sldRR~R.", [536] = "srwRR~R.",
145 [792] = "srawRR~R.", [824] = "srawiRR~A.",
146
147 [794] = "sradRR~R.", [826] = "sradiRR~H.", [827] = "sradiRR~H.",
148 [922] = "extshRR~.", [954] = "extsbRR~.", [986] = "extswRR~.",
149
150 [539] = "srdRR~R.",
151},
152{ __index = function(t, x)
153 if band(x, 31) == 15 then return "iselRRRC" end
154 end
155})
156
157local map_ld = {
158 shift = 0, mask = 3,
159 [0] = "ldRRE", "lduRRE", "lwaRRE",
160}
161
162local map_std = {
163 shift = 0, mask = 3,
164 [0] = "stdRRE", "stduRRE",
165}
166
167local map_fps = {
168 shift = 5, mask = 1,
169 {
170 shift = 1, mask = 15,
171 [0] = false, false, "fdivsFFF.", false,
172 "fsubsFFF.", "faddsFFF.", "fsqrtsF-F.", false,
173 "fresF-F.", "fmulsFF-F.", "frsqrtesF-F.", false,
174 "fmsubsFFFF~.", "fmaddsFFFF~.", "fnmsubsFFFF~.", "fnmaddsFFFF~.",
175 }
176}
177
178local map_fpd = {
179 shift = 5, mask = 1,
180 [0] = {
181 shift = 1, mask = 1023,
182 [0] = "fcmpuXFF", [32] = "fcmpoXFF", [64] = "mcrfsXX",
183 [38] = "mtfsb1A.", [70] = "mtfsb0A.", [134] = "mtfsfiA>>-A>",
184 [8] = "fcpsgnFFF.", [40] = "fnegF-F.", [72] = "fmrF-F.",
185 [136] = "fnabsF-F.", [264] = "fabsF-F.",
186 [12] = "frspF-F.",
187 [14] = "fctiwF-F.", [15] = "fctiwzF-F.",
188 [583] = "mffsF.", [711] = "mtfsfZF.",
189 [392] = "frinF-F.", [424] = "frizF-F.",
190 [456] = "fripF-F.", [488] = "frimF-F.",
191 [814] = "fctidF-F.", [815] = "fctidzF-F.", [846] = "fcfidF-F.",
192 },
193 {
194 shift = 1, mask = 15,
195 [0] = false, false, "fdivFFF.", false,
196 "fsubFFF.", "faddFFF.", "fsqrtF-F.", "fselFFFF~.",
197 "freF-F.", "fmulFF-F.", "frsqrteF-F.", false,
198 "fmsubFFFF~.", "fmaddFFFF~.", "fnmsubFFFF~.", "fnmaddFFFF~.",
199 }
200}
201
202local map_spe = {
203 shift = 0, mask = 2047,
204
205 [512] = "evaddwRRR", [514] = "evaddiwRAR~",
206 [516] = "evsubwRRR~", [518] = "evsubiwRAR~",
207 [520] = "evabsRR", [521] = "evnegRR",
208 [522] = "evextsbRR", [523] = "evextshRR", [524] = "evrndwRR",
209 [525] = "evcntlzwRR", [526] = "evcntlswRR",
210
211 [527] = "brincRRR",
212
213 [529] = "evandRRR", [530] = "evandcRRR", [534] = "evxorRRR",
214 [535] = "evor|evmrRRR=", [536] = "evnor|evnotRRR=",
215 [537] = "eveqvRRR", [539] = "evorcRRR", [542] = "evnandRRR",
216
217 [544] = "evsrwuRRR", [545] = "evsrwsRRR",
218 [546] = "evsrwiuRRA", [547] = "evsrwisRRA",
219 [548] = "evslwRRR", [550] = "evslwiRRA",
220 [552] = "evrlwRRR", [553] = "evsplatiRS",
221 [554] = "evrlwiRRA", [555] = "evsplatfiRS",
222 [556] = "evmergehiRRR", [557] = "evmergeloRRR",
223 [558] = "evmergehiloRRR", [559] = "evmergelohiRRR",
224
225 [560] = "evcmpgtuYRR", [561] = "evcmpgtsYRR",
226 [562] = "evcmpltuYRR", [563] = "evcmpltsYRR",
227 [564] = "evcmpeqYRR",
228
229 [632] = "evselRRR", [633] = "evselRRRW",
230 [634] = "evselRRRW", [635] = "evselRRRW",
231 [636] = "evselRRRW", [637] = "evselRRRW",
232 [638] = "evselRRRW", [639] = "evselRRRW",
233
234 [640] = "evfsaddRRR", [641] = "evfssubRRR",
235 [644] = "evfsabsRR", [645] = "evfsnabsRR", [646] = "evfsnegRR",
236 [648] = "evfsmulRRR", [649] = "evfsdivRRR",
237 [652] = "evfscmpgtYRR", [653] = "evfscmpltYRR", [654] = "evfscmpeqYRR",
238 [656] = "evfscfuiR-R", [657] = "evfscfsiR-R",
239 [658] = "evfscfufR-R", [659] = "evfscfsfR-R",
240 [660] = "evfsctuiR-R", [661] = "evfsctsiR-R",
241 [662] = "evfsctufR-R", [663] = "evfsctsfR-R",
242 [664] = "evfsctuizR-R", [666] = "evfsctsizR-R",
243 [668] = "evfststgtYRR", [669] = "evfststltYRR", [670] = "evfststeqYRR",
244
245 [704] = "efsaddRRR", [705] = "efssubRRR",
246 [708] = "efsabsRR", [709] = "efsnabsRR", [710] = "efsnegRR",
247 [712] = "efsmulRRR", [713] = "efsdivRRR",
248 [716] = "efscmpgtYRR", [717] = "efscmpltYRR", [718] = "efscmpeqYRR",
249 [719] = "efscfdR-R",
250 [720] = "efscfuiR-R", [721] = "efscfsiR-R",
251 [722] = "efscfufR-R", [723] = "efscfsfR-R",
252 [724] = "efsctuiR-R", [725] = "efsctsiR-R",
253 [726] = "efsctufR-R", [727] = "efsctsfR-R",
254 [728] = "efsctuizR-R", [730] = "efsctsizR-R",
255 [732] = "efststgtYRR", [733] = "efststltYRR", [734] = "efststeqYRR",
256
257 [736] = "efdaddRRR", [737] = "efdsubRRR",
258 [738] = "efdcfuidR-R", [739] = "efdcfsidR-R",
259 [740] = "efdabsRR", [741] = "efdnabsRR", [742] = "efdnegRR",
260 [744] = "efdmulRRR", [745] = "efddivRRR",
261 [746] = "efdctuidzR-R", [747] = "efdctsidzR-R",
262 [748] = "efdcmpgtYRR", [749] = "efdcmpltYRR", [750] = "efdcmpeqYRR",
263 [751] = "efdcfsR-R",
264 [752] = "efdcfuiR-R", [753] = "efdcfsiR-R",
265 [754] = "efdcfufR-R", [755] = "efdcfsfR-R",
266 [756] = "efdctuiR-R", [757] = "efdctsiR-R",
267 [758] = "efdctufR-R", [759] = "efdctsfR-R",
268 [760] = "efdctuizR-R", [762] = "efdctsizR-R",
269 [764] = "efdtstgtYRR", [765] = "efdtstltYRR", [766] = "efdtsteqYRR",
270
271 [768] = "evlddxRR0R", [769] = "evlddRR8",
272 [770] = "evldwxRR0R", [771] = "evldwRR8",
273 [772] = "evldhxRR0R", [773] = "evldhRR8",
274 [776] = "evlhhesplatxRR0R", [777] = "evlhhesplatRR2",
275 [780] = "evlhhousplatxRR0R", [781] = "evlhhousplatRR2",
276 [782] = "evlhhossplatxRR0R", [783] = "evlhhossplatRR2",
277 [784] = "evlwhexRR0R", [785] = "evlwheRR4",
278 [788] = "evlwhouxRR0R", [789] = "evlwhouRR4",
279 [790] = "evlwhosxRR0R", [791] = "evlwhosRR4",
280 [792] = "evlwwsplatxRR0R", [793] = "evlwwsplatRR4",
281 [796] = "evlwhsplatxRR0R", [797] = "evlwhsplatRR4",
282
283 [800] = "evstddxRR0R", [801] = "evstddRR8",
284 [802] = "evstdwxRR0R", [803] = "evstdwRR8",
285 [804] = "evstdhxRR0R", [805] = "evstdhRR8",
286 [816] = "evstwhexRR0R", [817] = "evstwheRR4",
287 [820] = "evstwhoxRR0R", [821] = "evstwhoRR4",
288 [824] = "evstwwexRR0R", [825] = "evstwweRR4",
289 [828] = "evstwwoxRR0R", [829] = "evstwwoRR4",
290
291 [1027] = "evmhessfRRR", [1031] = "evmhossfRRR", [1032] = "evmheumiRRR",
292 [1033] = "evmhesmiRRR", [1035] = "evmhesmfRRR", [1036] = "evmhoumiRRR",
293 [1037] = "evmhosmiRRR", [1039] = "evmhosmfRRR", [1059] = "evmhessfaRRR",
294 [1063] = "evmhossfaRRR", [1064] = "evmheumiaRRR", [1065] = "evmhesmiaRRR",
295 [1067] = "evmhesmfaRRR", [1068] = "evmhoumiaRRR", [1069] = "evmhosmiaRRR",
296 [1071] = "evmhosmfaRRR", [1095] = "evmwhssfRRR", [1096] = "evmwlumiRRR",
297 [1100] = "evmwhumiRRR", [1101] = "evmwhsmiRRR", [1103] = "evmwhsmfRRR",
298 [1107] = "evmwssfRRR", [1112] = "evmwumiRRR", [1113] = "evmwsmiRRR",
299 [1115] = "evmwsmfRRR", [1127] = "evmwhssfaRRR", [1128] = "evmwlumiaRRR",
300 [1132] = "evmwhumiaRRR", [1133] = "evmwhsmiaRRR", [1135] = "evmwhsmfaRRR",
301 [1139] = "evmwssfaRRR", [1144] = "evmwumiaRRR", [1145] = "evmwsmiaRRR",
302 [1147] = "evmwsmfaRRR",
303
304 [1216] = "evaddusiaawRR", [1217] = "evaddssiaawRR",
305 [1218] = "evsubfusiaawRR", [1219] = "evsubfssiaawRR",
306 [1220] = "evmraRR",
307 [1222] = "evdivwsRRR", [1223] = "evdivwuRRR",
308 [1224] = "evaddumiaawRR", [1225] = "evaddsmiaawRR",
309 [1226] = "evsubfumiaawRR", [1227] = "evsubfsmiaawRR",
310
311 [1280] = "evmheusiaawRRR", [1281] = "evmhessiaawRRR",
312 [1283] = "evmhessfaawRRR", [1284] = "evmhousiaawRRR",
313 [1285] = "evmhossiaawRRR", [1287] = "evmhossfaawRRR",
314 [1288] = "evmheumiaawRRR", [1289] = "evmhesmiaawRRR",
315 [1291] = "evmhesmfaawRRR", [1292] = "evmhoumiaawRRR",
316 [1293] = "evmhosmiaawRRR", [1295] = "evmhosmfaawRRR",
317 [1320] = "evmhegumiaaRRR", [1321] = "evmhegsmiaaRRR",
318 [1323] = "evmhegsmfaaRRR", [1324] = "evmhogumiaaRRR",
319 [1325] = "evmhogsmiaaRRR", [1327] = "evmhogsmfaaRRR",
320 [1344] = "evmwlusiaawRRR", [1345] = "evmwlssiaawRRR",
321 [1352] = "evmwlumiaawRRR", [1353] = "evmwlsmiaawRRR",
322 [1363] = "evmwssfaaRRR", [1368] = "evmwumiaaRRR",
323 [1369] = "evmwsmiaaRRR", [1371] = "evmwsmfaaRRR",
324 [1408] = "evmheusianwRRR", [1409] = "evmhessianwRRR",
325 [1411] = "evmhessfanwRRR", [1412] = "evmhousianwRRR",
326 [1413] = "evmhossianwRRR", [1415] = "evmhossfanwRRR",
327 [1416] = "evmheumianwRRR", [1417] = "evmhesmianwRRR",
328 [1419] = "evmhesmfanwRRR", [1420] = "evmhoumianwRRR",
329 [1421] = "evmhosmianwRRR", [1423] = "evmhosmfanwRRR",
330 [1448] = "evmhegumianRRR", [1449] = "evmhegsmianRRR",
331 [1451] = "evmhegsmfanRRR", [1452] = "evmhogumianRRR",
332 [1453] = "evmhogsmianRRR", [1455] = "evmhogsmfanRRR",
333 [1472] = "evmwlusianwRRR", [1473] = "evmwlssianwRRR",
334 [1480] = "evmwlumianwRRR", [1481] = "evmwlsmianwRRR",
335 [1491] = "evmwssfanRRR", [1496] = "evmwumianRRR",
336 [1497] = "evmwsmianRRR", [1499] = "evmwsmfanRRR",
337}
338
339local map_pri = {
340 [0] = false, false, "tdiARI", "twiARI",
341 map_spe, false, false, "mulliRRI",
342 "subficRRI", false, "cmpl_iYLRU", "cmp_iYLRI",
343 "addicRRI", "addic.RRI", "addi|liRR0I", "addis|lisRR0I",
344 "b_KBJ", "sc", "bKJ", map_crops,
345 "rlwimiRR~AAA.", "rlwinmRR~AAA.", false, "rlwnmRR~RAA.",
346 "oriNRR~U", "orisRR~U", "xoriRR~U", "xorisRR~U",
347 "andi.RR~U", "andis.RR~U", map_rld, map_ext,
348 "lwzRRD", "lwzuRRD", "lbzRRD", "lbzuRRD",
349 "stwRRD", "stwuRRD", "stbRRD", "stbuRRD",
350 "lhzRRD", "lhzuRRD", "lhaRRD", "lhauRRD",
351 "sthRRD", "sthuRRD", "lmwRRD", "stmwRRD",
352 "lfsFRD", "lfsuFRD", "lfdFRD", "lfduFRD",
353 "stfsFRD", "stfsuFRD", "stfdFRD", "stfduFRD",
354 false, false, map_ld, map_fps,
355 false, false, map_std, map_fpd,
356}
357
358------------------------------------------------------------------------------
359
360local map_gpr = {
361 [0] = "r0", "sp", "r2", "r3", "r4", "r5", "r6", "r7",
362 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
363 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
364 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
365}
366
367local map_cond = { [0] = "lt", "gt", "eq", "so", "ge", "le", "ne", "ns", }
368
369-- Format a condition bit.
370local function condfmt(cond)
371 if cond <= 3 then
372 return map_cond[band(cond, 3)]
373 else
374 return format("4*cr%d+%s", rshift(cond, 2), map_cond[band(cond, 3)])
375 end
376end
377
378------------------------------------------------------------------------------
379
380-- Output a nicely formatted line with an opcode and operands.
381local function putop(ctx, text, operands)
382 local pos = ctx.pos
383 local extra = ""
384 if ctx.rel then
385 local sym = ctx.symtab[ctx.rel]
386 if sym then extra = "\t->"..sym end
387 end
388 if ctx.hexdump > 0 then
389 ctx.out(format("%08x %s %-7s %s%s\n",
390 ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra))
391 else
392 ctx.out(format("%08x %-7s %s%s\n",
393 ctx.addr+pos, text, concat(operands, ", "), extra))
394 end
395 ctx.pos = pos + 4
396end
397
398-- Fallback for unknown opcodes.
399local function unknown(ctx)
400 return putop(ctx, ".long", { "0x"..tohex(ctx.op) })
401end
402
403-- Disassemble a single instruction.
404local function disass_ins(ctx)
405 local pos = ctx.pos
406 local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4)
407 local op = bor(lshift(b0, 24), lshift(b1, 16), lshift(b2, 8), b3)
408 local operands = {}
409 local last = nil
410 local rs = 21
411 ctx.op = op
412 ctx.rel = nil
413
414 local opat = map_pri[rshift(b0, 2)]
415 while type(opat) ~= "string" do
416 if not opat then return unknown(ctx) end
417 opat = opat[band(rshift(op, opat.shift), opat.mask)]
418 end
419 local name, pat = match(opat, "^([a-z0-9_.]*)(.*)")
420 local altname, pat2 = match(pat, "|([a-z0-9_.]*)(.*)")
421 if altname then pat = pat2 end
422
423 for p in gmatch(pat, ".") do
424 local x = nil
425 if p == "R" then
426 x = map_gpr[band(rshift(op, rs), 31)]
427 rs = rs - 5
428 elseif p == "F" then
429 x = "f"..band(rshift(op, rs), 31)
430 rs = rs - 5
431 elseif p == "A" then
432 x = band(rshift(op, rs), 31)
433 rs = rs - 5
434 elseif p == "S" then
435 x = arshift(lshift(op, 27-rs), 27)
436 rs = rs - 5
437 elseif p == "I" then
438 x = arshift(lshift(op, 16), 16)
439 elseif p == "U" then
440 x = band(op, 0xffff)
441 elseif p == "D" or p == "E" then
442 local disp = arshift(lshift(op, 16), 16)
443 if p == "E" then disp = band(disp, -4) end
444 if last == "r0" then last = "0" end
445 operands[#operands] = format("%d(%s)", disp, last)
446 elseif p >= "2" and p <= "8" then
447 local disp = band(rshift(op, rs), 31) * p
448 if last == "r0" then last = "0" end
449 operands[#operands] = format("%d(%s)", disp, last)
450 elseif p == "H" then
451 x = band(rshift(op, rs), 31) + lshift(band(op, 2), 4)
452 rs = rs - 5
453 elseif p == "M" then
454 x = band(rshift(op, rs), 31) + band(op, 0x20)
455 elseif p == "C" then
456 x = condfmt(band(rshift(op, rs), 31))
457 rs = rs - 5
458 elseif p == "B" then
459 local bo = rshift(op, 21)
460 local cond = band(rshift(op, 16), 31)
461 local cn = ""
462 rs = rs - 10
463 if band(bo, 4) == 0 then
464 cn = band(bo, 2) == 0 and "dnz" or "dz"
465 if band(bo, 0x10) == 0 then
466 cn = cn..(band(bo, 8) == 0 and "f" or "t")
467 if band(bo, 1) ~= 0 then
468 name = name..(band(op, 0x8000) ~= 0 and "-" or "+")
469 end
470 elseif band(bo, 8) ~= 0 then
471 name = name..(band(bo, 1) == 0 and "-" or "+")
472 elseif band(bo, 1) ~= 0 then
473 name = name..(band(op, 0x8000) ~= 0 and "-" or "+")
474 end
475 if band(bo, 0x10) == 0 then x = condfmt(cond) end
476 elseif band(bo, 0x10) == 0 then
477 cn = map_cond[band(cond, 3) + (band(bo, 8) == 0 and 4 or 0)]
478 if band(bo, 2) ~= 0 then
479 name = name..(band(bo, 1) == 0 and "-" or "+")
480 elseif band(bo, 1) ~= 0 then
481 name = name..(band(op, 0x8000) ~= 0 and "-" or "+")
482 end
483 if cond > 3 then x = "cr"..rshift(cond, 2) end
484 end
485 name = gsub(name, "_", cn)
486 elseif p == "J" then
487 x = arshift(lshift(op, 27-rs), 29-rs)*4
488 if band(op, 2) == 0 then x = ctx.addr + pos + x end
489 ctx.rel = x
490 x = "0x"..tohex(x)
491 elseif p == "K" then
492 if band(op, 1) ~= 0 then name = name.."l" end
493 if band(op, 2) ~= 0 then name = name.."a" end
494 elseif p == "X" or p == "Y" then
495 x = band(rshift(op, rs+2), 7)
496 if x == 0 and p == "Y" then x = nil else x = "cr"..x end
497 rs = rs - 5
498 elseif p == "W" then
499 x = "cr"..band(op, 7)
500 elseif p == "Z" then
501 x = band(rshift(op, rs-4), 255)
502 rs = rs - 10
503 elseif p == ">" then
504 operands[#operands] = rshift(operands[#operands], 1)
505 elseif p == "0" then
506 if last == "r0" then
507 operands[#operands] = nil
508 if altname then name = altname end
509 end
510 elseif p == "L" then
511 name = gsub(name, "_", band(op, 0x00200000) ~= 0 and "d" or "w")
512 elseif p == "." then
513 if band(op, 1) == 1 then name = name.."." end
514 elseif p == "N" then
515 if op == 0x60000000 then name = "nop"; break end
516 elseif p == "~" then
517 local n = #operands
518 operands[n-1], operands[n] = operands[n], operands[n-1]
519 elseif p == "=" then
520 local n = #operands
521 if last == operands[n-1] then
522 operands[n] = nil
523 name = altname
524 end
525 elseif p == "%" then
526 local n = #operands
527 if last == operands[n-1] and last == operands[n-2] then
528 operands[n] = nil
529 operands[n-1] = nil
530 name = altname
531 end
532 elseif p == "-" then
533 rs = rs - 5
534 else
535 assert(false)
536 end
537 if x then operands[#operands+1] = x; last = x end
538 end
539
540 return putop(ctx, name, operands)
541end
542
543------------------------------------------------------------------------------
544
545-- Disassemble a block of code.
546local function disass_block(ctx, ofs, len)
547 if not ofs then ofs = 0 end
548 local stop = len and ofs+len or #ctx.code
549 stop = stop - stop % 4
550 ctx.pos = ofs - ofs % 4
551 ctx.rel = nil
552 while ctx.pos < stop do disass_ins(ctx) end
553end
554
555-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
556local function create_(code, addr, out)
557 local ctx = {}
558 ctx.code = code
559 ctx.addr = addr or 0
560 ctx.out = out or io.write
561 ctx.symtab = {}
562 ctx.disass = disass_block
563 ctx.hexdump = 8
564 return ctx
565end
566
567-- Simple API: disassemble code (a string) at address and output via out.
568local function disass_(code, addr, out)
569 create_(code, addr, out):disass()
570end
571
572
573-- Public module functions.
574module(...)
575
576create = create_
577disass = disass_
578