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