Mercurial
comparison third_party/luajit/src/jit/dis_ppc.lua @ 178:94705b5986b3
[ThirdParty] Added WRK and luajit for load testing.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Thu, 22 Jan 2026 20:10:30 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 177:24fe8ff94056 | 178:94705b5986b3 |
|---|---|
| 1 ---------------------------------------------------------------------------- | |
| 2 -- LuaJIT PPC disassembler module. | |
| 3 -- | |
| 4 -- Copyright (C) 2005-2023 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 byte, format = 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~RM.", "rldcrRR~RM.", | |
| 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 return { | |
| 587 create = create, | |
| 588 disass = disass, | |
| 589 regname = regname | |
| 590 } | |
| 591 |