Mercurial
comparison third_party/luajit/dynasm/dasm_mips.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 -- DynASM MIPS32/MIPS64 module. | |
| 3 -- | |
| 4 -- Copyright (C) 2005-2023 Mike Pall. All rights reserved. | |
| 5 -- See dynasm.lua for full copyright notice. | |
| 6 ------------------------------------------------------------------------------ | |
| 7 | |
| 8 local mips64 = mips64 | |
| 9 local mipsr6 = _map_def.MIPSR6 | |
| 10 | |
| 11 -- Module information: | |
| 12 local _info = { | |
| 13 arch = mips64 and "mips64" or "mips", | |
| 14 description = "DynASM MIPS32/MIPS64 module", | |
| 15 version = "1.5.0", | |
| 16 vernum = 10500, | |
| 17 release = "2021-05-02", | |
| 18 author = "Mike Pall", | |
| 19 license = "MIT", | |
| 20 } | |
| 21 | |
| 22 -- Exported glue functions for the arch-specific module. | |
| 23 local _M = { _info = _info } | |
| 24 | |
| 25 -- Cache library functions. | |
| 26 local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs | |
| 27 local assert, setmetatable = assert, setmetatable | |
| 28 local _s = string | |
| 29 local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char | |
| 30 local match, gmatch = _s.match, _s.gmatch | |
| 31 local concat, sort = table.concat, table.sort | |
| 32 local bit = bit or require("bit") | |
| 33 local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift | |
| 34 local tohex = bit.tohex | |
| 35 | |
| 36 -- Inherited tables and callbacks. | |
| 37 local g_opt, g_arch | |
| 38 local wline, werror, wfatal, wwarn | |
| 39 | |
| 40 -- Action name list. | |
| 41 -- CHECK: Keep this in sync with the C code! | |
| 42 local action_names = { | |
| 43 "STOP", "SECTION", "ESC", "REL_EXT", | |
| 44 "ALIGN", "REL_LG", "LABEL_LG", | |
| 45 "REL_PC", "LABEL_PC", "IMM", "IMMS", | |
| 46 } | |
| 47 | |
| 48 -- Maximum number of section buffer positions for dasm_put(). | |
| 49 -- CHECK: Keep this in sync with the C code! | |
| 50 local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines. | |
| 51 | |
| 52 -- Action name -> action number. | |
| 53 local map_action = {} | |
| 54 for n,name in ipairs(action_names) do | |
| 55 map_action[name] = n-1 | |
| 56 end | |
| 57 | |
| 58 -- Action list buffer. | |
| 59 local actlist = {} | |
| 60 | |
| 61 -- Argument list for next dasm_put(). Start with offset 0 into action list. | |
| 62 local actargs = { 0 } | |
| 63 | |
| 64 -- Current number of section buffer positions for dasm_put(). | |
| 65 local secpos = 1 | |
| 66 | |
| 67 ------------------------------------------------------------------------------ | |
| 68 | |
| 69 -- Dump action names and numbers. | |
| 70 local function dumpactions(out) | |
| 71 out:write("DynASM encoding engine action codes:\n") | |
| 72 for n,name in ipairs(action_names) do | |
| 73 local num = map_action[name] | |
| 74 out:write(format(" %-10s %02X %d\n", name, num, num)) | |
| 75 end | |
| 76 out:write("\n") | |
| 77 end | |
| 78 | |
| 79 -- Write action list buffer as a huge static C array. | |
| 80 local function writeactions(out, name) | |
| 81 local nn = #actlist | |
| 82 if nn == 0 then nn = 1; actlist[0] = map_action.STOP end | |
| 83 out:write("static const unsigned int ", name, "[", nn, "] = {\n") | |
| 84 for i = 1,nn-1 do | |
| 85 assert(out:write("0x", tohex(actlist[i]), ",\n")) | |
| 86 end | |
| 87 assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n")) | |
| 88 end | |
| 89 | |
| 90 ------------------------------------------------------------------------------ | |
| 91 | |
| 92 -- Add word to action list. | |
| 93 local function wputxw(n) | |
| 94 assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") | |
| 95 actlist[#actlist+1] = n | |
| 96 end | |
| 97 | |
| 98 -- Add action to list with optional arg. Advance buffer pos, too. | |
| 99 local function waction(action, val, a, num) | |
| 100 local w = assert(map_action[action], "bad action name `"..action.."'") | |
| 101 wputxw(0xff000000 + w * 0x10000 + (val or 0)) | |
| 102 if a then actargs[#actargs+1] = a end | |
| 103 if a or num then secpos = secpos + (num or 1) end | |
| 104 end | |
| 105 | |
| 106 -- Flush action list (intervening C code or buffer pos overflow). | |
| 107 local function wflush(term) | |
| 108 if #actlist == actargs[1] then return end -- Nothing to flush. | |
| 109 if not term then waction("STOP") end -- Terminate action list. | |
| 110 wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true) | |
| 111 actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put(). | |
| 112 secpos = 1 -- The actionlist offset occupies a buffer position, too. | |
| 113 end | |
| 114 | |
| 115 -- Put escaped word. | |
| 116 local function wputw(n) | |
| 117 if n >= 0xff000000 then waction("ESC") end | |
| 118 wputxw(n) | |
| 119 end | |
| 120 | |
| 121 -- Reserve position for word. | |
| 122 local function wpos() | |
| 123 local pos = #actlist+1 | |
| 124 actlist[pos] = "" | |
| 125 return pos | |
| 126 end | |
| 127 | |
| 128 -- Store word to reserved position. | |
| 129 local function wputpos(pos, n) | |
| 130 assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") | |
| 131 actlist[pos] = n | |
| 132 end | |
| 133 | |
| 134 ------------------------------------------------------------------------------ | |
| 135 | |
| 136 -- Global label name -> global label number. With auto assignment on 1st use. | |
| 137 local next_global = 20 | |
| 138 local map_global = setmetatable({}, { __index = function(t, name) | |
| 139 if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end | |
| 140 local n = next_global | |
| 141 if n > 2047 then werror("too many global labels") end | |
| 142 next_global = n + 1 | |
| 143 t[name] = n | |
| 144 return n | |
| 145 end}) | |
| 146 | |
| 147 -- Dump global labels. | |
| 148 local function dumpglobals(out, lvl) | |
| 149 local t = {} | |
| 150 for name, n in pairs(map_global) do t[n] = name end | |
| 151 out:write("Global labels:\n") | |
| 152 for i=20,next_global-1 do | |
| 153 out:write(format(" %s\n", t[i])) | |
| 154 end | |
| 155 out:write("\n") | |
| 156 end | |
| 157 | |
| 158 -- Write global label enum. | |
| 159 local function writeglobals(out, prefix) | |
| 160 local t = {} | |
| 161 for name, n in pairs(map_global) do t[n] = name end | |
| 162 out:write("enum {\n") | |
| 163 for i=20,next_global-1 do | |
| 164 out:write(" ", prefix, t[i], ",\n") | |
| 165 end | |
| 166 out:write(" ", prefix, "_MAX\n};\n") | |
| 167 end | |
| 168 | |
| 169 -- Write global label names. | |
| 170 local function writeglobalnames(out, name) | |
| 171 local t = {} | |
| 172 for name, n in pairs(map_global) do t[n] = name end | |
| 173 out:write("static const char *const ", name, "[] = {\n") | |
| 174 for i=20,next_global-1 do | |
| 175 out:write(" \"", t[i], "\",\n") | |
| 176 end | |
| 177 out:write(" (const char *)0\n};\n") | |
| 178 end | |
| 179 | |
| 180 ------------------------------------------------------------------------------ | |
| 181 | |
| 182 -- Extern label name -> extern label number. With auto assignment on 1st use. | |
| 183 local next_extern = 0 | |
| 184 local map_extern_ = {} | |
| 185 local map_extern = setmetatable({}, { __index = function(t, name) | |
| 186 -- No restrictions on the name for now. | |
| 187 local n = next_extern | |
| 188 if n > 2047 then werror("too many extern labels") end | |
| 189 next_extern = n + 1 | |
| 190 t[name] = n | |
| 191 map_extern_[n] = name | |
| 192 return n | |
| 193 end}) | |
| 194 | |
| 195 -- Dump extern labels. | |
| 196 local function dumpexterns(out, lvl) | |
| 197 out:write("Extern labels:\n") | |
| 198 for i=0,next_extern-1 do | |
| 199 out:write(format(" %s\n", map_extern_[i])) | |
| 200 end | |
| 201 out:write("\n") | |
| 202 end | |
| 203 | |
| 204 -- Write extern label names. | |
| 205 local function writeexternnames(out, name) | |
| 206 out:write("static const char *const ", name, "[] = {\n") | |
| 207 for i=0,next_extern-1 do | |
| 208 out:write(" \"", map_extern_[i], "\",\n") | |
| 209 end | |
| 210 out:write(" (const char *)0\n};\n") | |
| 211 end | |
| 212 | |
| 213 ------------------------------------------------------------------------------ | |
| 214 | |
| 215 -- Arch-specific maps. | |
| 216 local map_archdef = { sp="r29", ra="r31" } -- Ext. register name -> int. name. | |
| 217 | |
| 218 local map_type = {} -- Type name -> { ctype, reg } | |
| 219 local ctypenum = 0 -- Type number (for Dt... macros). | |
| 220 | |
| 221 -- Reverse defines for registers. | |
| 222 function _M.revdef(s) | |
| 223 if s == "r29" then return "sp" | |
| 224 elseif s == "r31" then return "ra" end | |
| 225 return s | |
| 226 end | |
| 227 | |
| 228 ------------------------------------------------------------------------------ | |
| 229 | |
| 230 -- Template strings for MIPS instructions. | |
| 231 local map_op = { | |
| 232 -- First-level opcodes. | |
| 233 j_1 = "08000000J", | |
| 234 jal_1 = "0c000000J", | |
| 235 b_1 = "10000000B", | |
| 236 beqz_2 = "10000000SB", | |
| 237 beq_3 = "10000000STB", | |
| 238 bnez_2 = "14000000SB", | |
| 239 bne_3 = "14000000STB", | |
| 240 blez_2 = "18000000SB", | |
| 241 bgtz_2 = "1c000000SB", | |
| 242 li_2 = "24000000TI", | |
| 243 addiu_3 = "24000000TSI", | |
| 244 slti_3 = "28000000TSI", | |
| 245 sltiu_3 = "2c000000TSI", | |
| 246 andi_3 = "30000000TSU", | |
| 247 lu_2 = "34000000TU", | |
| 248 ori_3 = "34000000TSU", | |
| 249 xori_3 = "38000000TSU", | |
| 250 lui_2 = "3c000000TU", | |
| 251 daddiu_3 = mips64 and "64000000TSI", | |
| 252 ldl_2 = mips64 and "68000000TO", | |
| 253 ldr_2 = mips64 and "6c000000TO", | |
| 254 lb_2 = "80000000TO", | |
| 255 lh_2 = "84000000TO", | |
| 256 lw_2 = "8c000000TO", | |
| 257 lbu_2 = "90000000TO", | |
| 258 lhu_2 = "94000000TO", | |
| 259 lwu_2 = mips64 and "9c000000TO", | |
| 260 sb_2 = "a0000000TO", | |
| 261 sh_2 = "a4000000TO", | |
| 262 sw_2 = "ac000000TO", | |
| 263 lwc1_2 = "c4000000HO", | |
| 264 ldc1_2 = "d4000000HO", | |
| 265 ld_2 = mips64 and "dc000000TO", | |
| 266 swc1_2 = "e4000000HO", | |
| 267 sdc1_2 = "f4000000HO", | |
| 268 sd_2 = mips64 and "fc000000TO", | |
| 269 | |
| 270 -- Opcode SPECIAL. | |
| 271 nop_0 = "00000000", | |
| 272 sll_3 = "00000000DTA", | |
| 273 sextw_2 = "00000000DT", | |
| 274 srl_3 = "00000002DTA", | |
| 275 rotr_3 = "00200002DTA", | |
| 276 sra_3 = "00000003DTA", | |
| 277 sllv_3 = "00000004DTS", | |
| 278 srlv_3 = "00000006DTS", | |
| 279 rotrv_3 = "00000046DTS", | |
| 280 drotrv_3 = mips64 and "00000056DTS", | |
| 281 srav_3 = "00000007DTS", | |
| 282 jalr_1 = "0000f809S", | |
| 283 jalr_2 = "00000009DS", | |
| 284 syscall_0 = "0000000c", | |
| 285 syscall_1 = "0000000cY", | |
| 286 break_0 = "0000000d", | |
| 287 break_1 = "0000000dY", | |
| 288 sync_0 = "0000000f", | |
| 289 dsllv_3 = mips64 and "00000014DTS", | |
| 290 dsrlv_3 = mips64 and "00000016DTS", | |
| 291 dsrav_3 = mips64 and "00000017DTS", | |
| 292 add_3 = "00000020DST", | |
| 293 move_2 = mips64 and "00000025DS" or "00000021DS", | |
| 294 addu_3 = "00000021DST", | |
| 295 sub_3 = "00000022DST", | |
| 296 negu_2 = mips64 and "0000002fDT" or "00000023DT", | |
| 297 subu_3 = "00000023DST", | |
| 298 and_3 = "00000024DST", | |
| 299 or_3 = "00000025DST", | |
| 300 xor_3 = "00000026DST", | |
| 301 not_2 = "00000027DS", | |
| 302 nor_3 = "00000027DST", | |
| 303 slt_3 = "0000002aDST", | |
| 304 sltu_3 = "0000002bDST", | |
| 305 dadd_3 = mips64 and "0000002cDST", | |
| 306 daddu_3 = mips64 and "0000002dDST", | |
| 307 dsub_3 = mips64 and "0000002eDST", | |
| 308 dsubu_3 = mips64 and "0000002fDST", | |
| 309 tge_2 = "00000030ST", | |
| 310 tge_3 = "00000030STZ", | |
| 311 tgeu_2 = "00000031ST", | |
| 312 tgeu_3 = "00000031STZ", | |
| 313 tlt_2 = "00000032ST", | |
| 314 tlt_3 = "00000032STZ", | |
| 315 tltu_2 = "00000033ST", | |
| 316 tltu_3 = "00000033STZ", | |
| 317 teq_2 = "00000034ST", | |
| 318 teq_3 = "00000034STZ", | |
| 319 tne_2 = "00000036ST", | |
| 320 tne_3 = "00000036STZ", | |
| 321 dsll_3 = mips64 and "00000038DTa", | |
| 322 dsrl_3 = mips64 and "0000003aDTa", | |
| 323 drotr_3 = mips64 and "0020003aDTa", | |
| 324 dsra_3 = mips64 and "0000003bDTa", | |
| 325 dsll32_3 = mips64 and "0000003cDTA", | |
| 326 dsrl32_3 = mips64 and "0000003eDTA", | |
| 327 drotr32_3 = mips64 and "0020003eDTA", | |
| 328 dsra32_3 = mips64 and "0000003fDTA", | |
| 329 | |
| 330 -- Opcode REGIMM. | |
| 331 bltz_2 = "04000000SB", | |
| 332 bgez_2 = "04010000SB", | |
| 333 bltzl_2 = "04020000SB", | |
| 334 bgezl_2 = "04030000SB", | |
| 335 bal_1 = "04110000B", | |
| 336 synci_1 = "041f0000O", | |
| 337 | |
| 338 -- Opcode SPECIAL3. | |
| 339 ext_4 = "7c000000TSAM", -- Note: last arg is msbd = size-1 | |
| 340 dextm_4 = mips64 and "7c000001TSAM", -- Args: pos | size-1-32 | |
| 341 dextu_4 = mips64 and "7c000002TSAM", -- Args: pos-32 | size-1 | |
| 342 dext_4 = mips64 and "7c000003TSAM", -- Args: pos | size-1 | |
| 343 zextw_2 = mips64 and "7c00f803TS", | |
| 344 ins_4 = "7c000004TSAM", -- Note: last arg is msb = pos+size-1 | |
| 345 dinsm_4 = mips64 and "7c000005TSAM", -- Args: pos | pos+size-33 | |
| 346 dinsu_4 = mips64 and "7c000006TSAM", -- Args: pos-32 | pos+size-33 | |
| 347 dins_4 = mips64 and "7c000007TSAM", -- Args: pos | pos+size-1 | |
| 348 wsbh_2 = "7c0000a0DT", | |
| 349 dsbh_2 = mips64 and "7c0000a4DT", | |
| 350 dshd_2 = mips64 and "7c000164DT", | |
| 351 seb_2 = "7c000420DT", | |
| 352 seh_2 = "7c000620DT", | |
| 353 rdhwr_2 = "7c00003bTD", | |
| 354 | |
| 355 -- Opcode COP0. | |
| 356 mfc0_2 = "40000000TD", | |
| 357 mfc0_3 = "40000000TDW", | |
| 358 dmfc0_2 = mips64 and "40200000TD", | |
| 359 dmfc0_3 = mips64 and "40200000TDW", | |
| 360 mtc0_2 = "40800000TD", | |
| 361 mtc0_3 = "40800000TDW", | |
| 362 dmtc0_2 = mips64 and "40a00000TD", | |
| 363 dmtc0_3 = mips64 and "40a00000TDW", | |
| 364 rdpgpr_2 = "41400000DT", | |
| 365 di_0 = "41606000", | |
| 366 di_1 = "41606000T", | |
| 367 ei_0 = "41606020", | |
| 368 ei_1 = "41606020T", | |
| 369 wrpgpr_2 = "41c00000DT", | |
| 370 tlbr_0 = "42000001", | |
| 371 tlbwi_0 = "42000002", | |
| 372 tlbwr_0 = "42000006", | |
| 373 tlbp_0 = "42000008", | |
| 374 eret_0 = "42000018", | |
| 375 deret_0 = "4200001f", | |
| 376 wait_0 = "42000020", | |
| 377 | |
| 378 -- Opcode COP1. | |
| 379 mfc1_2 = "44000000TG", | |
| 380 dmfc1_2 = mips64 and "44200000TG", | |
| 381 cfc1_2 = "44400000TG", | |
| 382 mfhc1_2 = "44600000TG", | |
| 383 mtc1_2 = "44800000TG", | |
| 384 dmtc1_2 = mips64 and "44a00000TG", | |
| 385 ctc1_2 = "44c00000TG", | |
| 386 mthc1_2 = "44e00000TG", | |
| 387 | |
| 388 ["add.s_3"] = "46000000FGH", | |
| 389 ["sub.s_3"] = "46000001FGH", | |
| 390 ["mul.s_3"] = "46000002FGH", | |
| 391 ["div.s_3"] = "46000003FGH", | |
| 392 ["sqrt.s_2"] = "46000004FG", | |
| 393 ["abs.s_2"] = "46000005FG", | |
| 394 ["mov.s_2"] = "46000006FG", | |
| 395 ["neg.s_2"] = "46000007FG", | |
| 396 ["round.l.s_2"] = "46000008FG", | |
| 397 ["trunc.l.s_2"] = "46000009FG", | |
| 398 ["ceil.l.s_2"] = "4600000aFG", | |
| 399 ["floor.l.s_2"] = "4600000bFG", | |
| 400 ["round.w.s_2"] = "4600000cFG", | |
| 401 ["trunc.w.s_2"] = "4600000dFG", | |
| 402 ["ceil.w.s_2"] = "4600000eFG", | |
| 403 ["floor.w.s_2"] = "4600000fFG", | |
| 404 ["recip.s_2"] = "46000015FG", | |
| 405 ["rsqrt.s_2"] = "46000016FG", | |
| 406 ["cvt.d.s_2"] = "46000021FG", | |
| 407 ["cvt.w.s_2"] = "46000024FG", | |
| 408 ["cvt.l.s_2"] = "46000025FG", | |
| 409 ["add.d_3"] = "46200000FGH", | |
| 410 ["sub.d_3"] = "46200001FGH", | |
| 411 ["mul.d_3"] = "46200002FGH", | |
| 412 ["div.d_3"] = "46200003FGH", | |
| 413 ["sqrt.d_2"] = "46200004FG", | |
| 414 ["abs.d_2"] = "46200005FG", | |
| 415 ["mov.d_2"] = "46200006FG", | |
| 416 ["neg.d_2"] = "46200007FG", | |
| 417 ["round.l.d_2"] = "46200008FG", | |
| 418 ["trunc.l.d_2"] = "46200009FG", | |
| 419 ["ceil.l.d_2"] = "4620000aFG", | |
| 420 ["floor.l.d_2"] = "4620000bFG", | |
| 421 ["round.w.d_2"] = "4620000cFG", | |
| 422 ["trunc.w.d_2"] = "4620000dFG", | |
| 423 ["ceil.w.d_2"] = "4620000eFG", | |
| 424 ["floor.w.d_2"] = "4620000fFG", | |
| 425 ["recip.d_2"] = "46200015FG", | |
| 426 ["rsqrt.d_2"] = "46200016FG", | |
| 427 ["cvt.s.d_2"] = "46200020FG", | |
| 428 ["cvt.w.d_2"] = "46200024FG", | |
| 429 ["cvt.l.d_2"] = "46200025FG", | |
| 430 ["cvt.s.w_2"] = "46800020FG", | |
| 431 ["cvt.d.w_2"] = "46800021FG", | |
| 432 ["cvt.s.l_2"] = "46a00020FG", | |
| 433 ["cvt.d.l_2"] = "46a00021FG", | |
| 434 } | |
| 435 | |
| 436 if mipsr6 then -- Instructions added with MIPSR6. | |
| 437 | |
| 438 for k,v in pairs({ | |
| 439 | |
| 440 -- Add immediate to upper bits. | |
| 441 aui_3 = "3c000000TSI", | |
| 442 daui_3 = mips64 and "74000000TSI", | |
| 443 dahi_2 = mips64 and "04060000SI", | |
| 444 dati_2 = mips64 and "041e0000SI", | |
| 445 | |
| 446 -- TODO: addiupc, auipc, aluipc, lwpc, lwupc, ldpc. | |
| 447 | |
| 448 -- Compact branches. | |
| 449 blezalc_2 = "18000000TB", -- rt != 0. | |
| 450 bgezalc_2 = "18000000T=SB", -- rt != 0. | |
| 451 bgtzalc_2 = "1c000000TB", -- rt != 0. | |
| 452 bltzalc_2 = "1c000000T=SB", -- rt != 0. | |
| 453 | |
| 454 blezc_2 = "58000000TB", -- rt != 0. | |
| 455 bgezc_2 = "58000000T=SB", -- rt != 0. | |
| 456 bgec_3 = "58000000STB", -- rs != rt. | |
| 457 blec_3 = "58000000TSB", -- rt != rs. | |
| 458 | |
| 459 bgtzc_2 = "5c000000TB", -- rt != 0. | |
| 460 bltzc_2 = "5c000000T=SB", -- rt != 0. | |
| 461 bltc_3 = "5c000000STB", -- rs != rt. | |
| 462 bgtc_3 = "5c000000TSB", -- rt != rs. | |
| 463 | |
| 464 bgeuc_3 = "18000000STB", -- rs != rt. | |
| 465 bleuc_3 = "18000000TSB", -- rt != rs. | |
| 466 bltuc_3 = "1c000000STB", -- rs != rt. | |
| 467 bgtuc_3 = "1c000000TSB", -- rt != rs. | |
| 468 | |
| 469 beqzalc_2 = "20000000TB", -- rt != 0. | |
| 470 bnezalc_2 = "60000000TB", -- rt != 0. | |
| 471 beqc_3 = "20000000STB", -- rs < rt. | |
| 472 bnec_3 = "60000000STB", -- rs < rt. | |
| 473 bovc_3 = "20000000STB", -- rs >= rt. | |
| 474 bnvc_3 = "60000000STB", -- rs >= rt. | |
| 475 | |
| 476 beqzc_2 = "d8000000SK", -- rs != 0. | |
| 477 bnezc_2 = "f8000000SK", -- rs != 0. | |
| 478 jic_2 = "d8000000TI", | |
| 479 jialc_2 = "f8000000TI", | |
| 480 bc_1 = "c8000000L", | |
| 481 balc_1 = "e8000000L", | |
| 482 | |
| 483 -- Opcode SPECIAL. | |
| 484 jr_1 = "00000009S", | |
| 485 sdbbp_0 = "0000000e", | |
| 486 sdbbp_1 = "0000000eY", | |
| 487 lsa_4 = "00000005DSTA", | |
| 488 dlsa_4 = mips64 and "00000015DSTA", | |
| 489 seleqz_3 = "00000035DST", | |
| 490 selnez_3 = "00000037DST", | |
| 491 clz_2 = "00000050DS", | |
| 492 clo_2 = "00000051DS", | |
| 493 dclz_2 = mips64 and "00000052DS", | |
| 494 dclo_2 = mips64 and "00000053DS", | |
| 495 mul_3 = "00000098DST", | |
| 496 muh_3 = "000000d8DST", | |
| 497 mulu_3 = "00000099DST", | |
| 498 muhu_3 = "000000d9DST", | |
| 499 div_3 = "0000009aDST", | |
| 500 mod_3 = "000000daDST", | |
| 501 divu_3 = "0000009bDST", | |
| 502 modu_3 = "000000dbDST", | |
| 503 dmul_3 = mips64 and "0000009cDST", | |
| 504 dmuh_3 = mips64 and "000000dcDST", | |
| 505 dmulu_3 = mips64 and "0000009dDST", | |
| 506 dmuhu_3 = mips64 and "000000ddDST", | |
| 507 ddiv_3 = mips64 and "0000009eDST", | |
| 508 dmod_3 = mips64 and "000000deDST", | |
| 509 ddivu_3 = mips64 and "0000009fDST", | |
| 510 dmodu_3 = mips64 and "000000dfDST", | |
| 511 | |
| 512 -- Opcode SPECIAL3. | |
| 513 align_4 = "7c000220DSTA", | |
| 514 dalign_4 = mips64 and "7c000224DSTA", | |
| 515 bitswap_2 = "7c000020DT", | |
| 516 dbitswap_2 = mips64 and "7c000024DT", | |
| 517 | |
| 518 -- Opcode COP1. | |
| 519 bc1eqz_2 = "45200000HB", | |
| 520 bc1nez_2 = "45a00000HB", | |
| 521 | |
| 522 ["sel.s_3"] = "46000010FGH", | |
| 523 ["seleqz.s_3"] = "46000014FGH", | |
| 524 ["selnez.s_3"] = "46000017FGH", | |
| 525 ["maddf.s_3"] = "46000018FGH", | |
| 526 ["msubf.s_3"] = "46000019FGH", | |
| 527 ["rint.s_2"] = "4600001aFG", | |
| 528 ["class.s_2"] = "4600001bFG", | |
| 529 ["min.s_3"] = "4600001cFGH", | |
| 530 ["mina.s_3"] = "4600001dFGH", | |
| 531 ["max.s_3"] = "4600001eFGH", | |
| 532 ["maxa.s_3"] = "4600001fFGH", | |
| 533 ["cmp.af.s_3"] = "46800000FGH", | |
| 534 ["cmp.un.s_3"] = "46800001FGH", | |
| 535 ["cmp.or.s_3"] = "46800011FGH", | |
| 536 ["cmp.eq.s_3"] = "46800002FGH", | |
| 537 ["cmp.une.s_3"] = "46800012FGH", | |
| 538 ["cmp.ueq.s_3"] = "46800003FGH", | |
| 539 ["cmp.ne.s_3"] = "46800013FGH", | |
| 540 ["cmp.lt.s_3"] = "46800004FGH", | |
| 541 ["cmp.ult.s_3"] = "46800005FGH", | |
| 542 ["cmp.le.s_3"] = "46800006FGH", | |
| 543 ["cmp.ule.s_3"] = "46800007FGH", | |
| 544 ["cmp.saf.s_3"] = "46800008FGH", | |
| 545 ["cmp.sun.s_3"] = "46800009FGH", | |
| 546 ["cmp.sor.s_3"] = "46800019FGH", | |
| 547 ["cmp.seq.s_3"] = "4680000aFGH", | |
| 548 ["cmp.sune.s_3"] = "4680001aFGH", | |
| 549 ["cmp.sueq.s_3"] = "4680000bFGH", | |
| 550 ["cmp.sne.s_3"] = "4680001bFGH", | |
| 551 ["cmp.slt.s_3"] = "4680000cFGH", | |
| 552 ["cmp.sult.s_3"] = "4680000dFGH", | |
| 553 ["cmp.sle.s_3"] = "4680000eFGH", | |
| 554 ["cmp.sule.s_3"] = "4680000fFGH", | |
| 555 | |
| 556 ["sel.d_3"] = "46200010FGH", | |
| 557 ["seleqz.d_3"] = "46200014FGH", | |
| 558 ["selnez.d_3"] = "46200017FGH", | |
| 559 ["maddf.d_3"] = "46200018FGH", | |
| 560 ["msubf.d_3"] = "46200019FGH", | |
| 561 ["rint.d_2"] = "4620001aFG", | |
| 562 ["class.d_2"] = "4620001bFG", | |
| 563 ["min.d_3"] = "4620001cFGH", | |
| 564 ["mina.d_3"] = "4620001dFGH", | |
| 565 ["max.d_3"] = "4620001eFGH", | |
| 566 ["maxa.d_3"] = "4620001fFGH", | |
| 567 ["cmp.af.d_3"] = "46a00000FGH", | |
| 568 ["cmp.un.d_3"] = "46a00001FGH", | |
| 569 ["cmp.or.d_3"] = "46a00011FGH", | |
| 570 ["cmp.eq.d_3"] = "46a00002FGH", | |
| 571 ["cmp.une.d_3"] = "46a00012FGH", | |
| 572 ["cmp.ueq.d_3"] = "46a00003FGH", | |
| 573 ["cmp.ne.d_3"] = "46a00013FGH", | |
| 574 ["cmp.lt.d_3"] = "46a00004FGH", | |
| 575 ["cmp.ult.d_3"] = "46a00005FGH", | |
| 576 ["cmp.le.d_3"] = "46a00006FGH", | |
| 577 ["cmp.ule.d_3"] = "46a00007FGH", | |
| 578 ["cmp.saf.d_3"] = "46a00008FGH", | |
| 579 ["cmp.sun.d_3"] = "46a00009FGH", | |
| 580 ["cmp.sor.d_3"] = "46a00019FGH", | |
| 581 ["cmp.seq.d_3"] = "46a0000aFGH", | |
| 582 ["cmp.sune.d_3"] = "46a0001aFGH", | |
| 583 ["cmp.sueq.d_3"] = "46a0000bFGH", | |
| 584 ["cmp.sne.d_3"] = "46a0001bFGH", | |
| 585 ["cmp.slt.d_3"] = "46a0000cFGH", | |
| 586 ["cmp.sult.d_3"] = "46a0000dFGH", | |
| 587 ["cmp.sle.d_3"] = "46a0000eFGH", | |
| 588 ["cmp.sule.d_3"] = "46a0000fFGH", | |
| 589 | |
| 590 }) do map_op[k] = v end | |
| 591 | |
| 592 else -- Instructions removed by MIPSR6. | |
| 593 | |
| 594 for k,v in pairs({ | |
| 595 -- Traps, don't use. | |
| 596 addi_3 = "20000000TSI", | |
| 597 daddi_3 = mips64 and "60000000TSI", | |
| 598 | |
| 599 -- Branch on likely, don't use. | |
| 600 beqzl_2 = "50000000SB", | |
| 601 beql_3 = "50000000STB", | |
| 602 bnezl_2 = "54000000SB", | |
| 603 bnel_3 = "54000000STB", | |
| 604 blezl_2 = "58000000SB", | |
| 605 bgtzl_2 = "5c000000SB", | |
| 606 | |
| 607 lwl_2 = "88000000TO", | |
| 608 lwr_2 = "98000000TO", | |
| 609 swl_2 = "a8000000TO", | |
| 610 sdl_2 = mips64 and "b0000000TO", | |
| 611 sdr_2 = mips64 and "b1000000TO", | |
| 612 swr_2 = "b8000000TO", | |
| 613 cache_2 = "bc000000NO", | |
| 614 ll_2 = "c0000000TO", | |
| 615 pref_2 = "cc000000NO", | |
| 616 sc_2 = "e0000000TO", | |
| 617 scd_2 = mips64 and "f0000000TO", | |
| 618 | |
| 619 -- Opcode SPECIAL. | |
| 620 movf_2 = "00000001DS", | |
| 621 movf_3 = "00000001DSC", | |
| 622 movt_2 = "00010001DS", | |
| 623 movt_3 = "00010001DSC", | |
| 624 jr_1 = "00000008S", | |
| 625 movz_3 = "0000000aDST", | |
| 626 movn_3 = "0000000bDST", | |
| 627 mfhi_1 = "00000010D", | |
| 628 mthi_1 = "00000011S", | |
| 629 mflo_1 = "00000012D", | |
| 630 mtlo_1 = "00000013S", | |
| 631 mult_2 = "00000018ST", | |
| 632 multu_2 = "00000019ST", | |
| 633 div_3 = "0000001aST", | |
| 634 divu_3 = "0000001bST", | |
| 635 ddiv_3 = mips64 and "0000001eST", | |
| 636 ddivu_3 = mips64 and "0000001fST", | |
| 637 dmult_2 = mips64 and "0000001cST", | |
| 638 dmultu_2 = mips64 and "0000001dST", | |
| 639 | |
| 640 -- Opcode REGIMM. | |
| 641 tgei_2 = "04080000SI", | |
| 642 tgeiu_2 = "04090000SI", | |
| 643 tlti_2 = "040a0000SI", | |
| 644 tltiu_2 = "040b0000SI", | |
| 645 teqi_2 = "040c0000SI", | |
| 646 tnei_2 = "040e0000SI", | |
| 647 bltzal_2 = "04100000SB", | |
| 648 bgezal_2 = "04110000SB", | |
| 649 bltzall_2 = "04120000SB", | |
| 650 bgezall_2 = "04130000SB", | |
| 651 | |
| 652 -- Opcode SPECIAL2. | |
| 653 madd_2 = "70000000ST", | |
| 654 maddu_2 = "70000001ST", | |
| 655 mul_3 = "70000002DST", | |
| 656 msub_2 = "70000004ST", | |
| 657 msubu_2 = "70000005ST", | |
| 658 clz_2 = "70000020D=TS", | |
| 659 clo_2 = "70000021D=TS", | |
| 660 dclz_2 = mips64 and "70000024D=TS", | |
| 661 dclo_2 = mips64 and "70000025D=TS", | |
| 662 sdbbp_0 = "7000003f", | |
| 663 sdbbp_1 = "7000003fY", | |
| 664 | |
| 665 -- Opcode COP1. | |
| 666 bc1f_1 = "45000000B", | |
| 667 bc1f_2 = "45000000CB", | |
| 668 bc1t_1 = "45010000B", | |
| 669 bc1t_2 = "45010000CB", | |
| 670 bc1fl_1 = "45020000B", | |
| 671 bc1fl_2 = "45020000CB", | |
| 672 bc1tl_1 = "45030000B", | |
| 673 bc1tl_2 = "45030000CB", | |
| 674 | |
| 675 ["movf.s_2"] = "46000011FG", | |
| 676 ["movf.s_3"] = "46000011FGC", | |
| 677 ["movt.s_2"] = "46010011FG", | |
| 678 ["movt.s_3"] = "46010011FGC", | |
| 679 ["movz.s_3"] = "46000012FGT", | |
| 680 ["movn.s_3"] = "46000013FGT", | |
| 681 ["cvt.ps.s_3"] = "46000026FGH", | |
| 682 ["c.f.s_2"] = "46000030GH", | |
| 683 ["c.f.s_3"] = "46000030VGH", | |
| 684 ["c.un.s_2"] = "46000031GH", | |
| 685 ["c.un.s_3"] = "46000031VGH", | |
| 686 ["c.eq.s_2"] = "46000032GH", | |
| 687 ["c.eq.s_3"] = "46000032VGH", | |
| 688 ["c.ueq.s_2"] = "46000033GH", | |
| 689 ["c.ueq.s_3"] = "46000033VGH", | |
| 690 ["c.olt.s_2"] = "46000034GH", | |
| 691 ["c.olt.s_3"] = "46000034VGH", | |
| 692 ["c.ult.s_2"] = "46000035GH", | |
| 693 ["c.ult.s_3"] = "46000035VGH", | |
| 694 ["c.ole.s_2"] = "46000036GH", | |
| 695 ["c.ole.s_3"] = "46000036VGH", | |
| 696 ["c.ule.s_2"] = "46000037GH", | |
| 697 ["c.ule.s_3"] = "46000037VGH", | |
| 698 ["c.sf.s_2"] = "46000038GH", | |
| 699 ["c.sf.s_3"] = "46000038VGH", | |
| 700 ["c.ngle.s_2"] = "46000039GH", | |
| 701 ["c.ngle.s_3"] = "46000039VGH", | |
| 702 ["c.seq.s_2"] = "4600003aGH", | |
| 703 ["c.seq.s_3"] = "4600003aVGH", | |
| 704 ["c.ngl.s_2"] = "4600003bGH", | |
| 705 ["c.ngl.s_3"] = "4600003bVGH", | |
| 706 ["c.lt.s_2"] = "4600003cGH", | |
| 707 ["c.lt.s_3"] = "4600003cVGH", | |
| 708 ["c.nge.s_2"] = "4600003dGH", | |
| 709 ["c.nge.s_3"] = "4600003dVGH", | |
| 710 ["c.le.s_2"] = "4600003eGH", | |
| 711 ["c.le.s_3"] = "4600003eVGH", | |
| 712 ["c.ngt.s_2"] = "4600003fGH", | |
| 713 ["c.ngt.s_3"] = "4600003fVGH", | |
| 714 ["movf.d_2"] = "46200011FG", | |
| 715 ["movf.d_3"] = "46200011FGC", | |
| 716 ["movt.d_2"] = "46210011FG", | |
| 717 ["movt.d_3"] = "46210011FGC", | |
| 718 ["movz.d_3"] = "46200012FGT", | |
| 719 ["movn.d_3"] = "46200013FGT", | |
| 720 ["c.f.d_2"] = "46200030GH", | |
| 721 ["c.f.d_3"] = "46200030VGH", | |
| 722 ["c.un.d_2"] = "46200031GH", | |
| 723 ["c.un.d_3"] = "46200031VGH", | |
| 724 ["c.eq.d_2"] = "46200032GH", | |
| 725 ["c.eq.d_3"] = "46200032VGH", | |
| 726 ["c.ueq.d_2"] = "46200033GH", | |
| 727 ["c.ueq.d_3"] = "46200033VGH", | |
| 728 ["c.olt.d_2"] = "46200034GH", | |
| 729 ["c.olt.d_3"] = "46200034VGH", | |
| 730 ["c.ult.d_2"] = "46200035GH", | |
| 731 ["c.ult.d_3"] = "46200035VGH", | |
| 732 ["c.ole.d_2"] = "46200036GH", | |
| 733 ["c.ole.d_3"] = "46200036VGH", | |
| 734 ["c.ule.d_2"] = "46200037GH", | |
| 735 ["c.ule.d_3"] = "46200037VGH", | |
| 736 ["c.sf.d_2"] = "46200038GH", | |
| 737 ["c.sf.d_3"] = "46200038VGH", | |
| 738 ["c.ngle.d_2"] = "46200039GH", | |
| 739 ["c.ngle.d_3"] = "46200039VGH", | |
| 740 ["c.seq.d_2"] = "4620003aGH", | |
| 741 ["c.seq.d_3"] = "4620003aVGH", | |
| 742 ["c.ngl.d_2"] = "4620003bGH", | |
| 743 ["c.ngl.d_3"] = "4620003bVGH", | |
| 744 ["c.lt.d_2"] = "4620003cGH", | |
| 745 ["c.lt.d_3"] = "4620003cVGH", | |
| 746 ["c.nge.d_2"] = "4620003dGH", | |
| 747 ["c.nge.d_3"] = "4620003dVGH", | |
| 748 ["c.le.d_2"] = "4620003eGH", | |
| 749 ["c.le.d_3"] = "4620003eVGH", | |
| 750 ["c.ngt.d_2"] = "4620003fGH", | |
| 751 ["c.ngt.d_3"] = "4620003fVGH", | |
| 752 ["add.ps_3"] = "46c00000FGH", | |
| 753 ["sub.ps_3"] = "46c00001FGH", | |
| 754 ["mul.ps_3"] = "46c00002FGH", | |
| 755 ["abs.ps_2"] = "46c00005FG", | |
| 756 ["mov.ps_2"] = "46c00006FG", | |
| 757 ["neg.ps_2"] = "46c00007FG", | |
| 758 ["movf.ps_2"] = "46c00011FG", | |
| 759 ["movf.ps_3"] = "46c00011FGC", | |
| 760 ["movt.ps_2"] = "46c10011FG", | |
| 761 ["movt.ps_3"] = "46c10011FGC", | |
| 762 ["movz.ps_3"] = "46c00012FGT", | |
| 763 ["movn.ps_3"] = "46c00013FGT", | |
| 764 ["cvt.s.pu_2"] = "46c00020FG", | |
| 765 ["cvt.s.pl_2"] = "46c00028FG", | |
| 766 ["pll.ps_3"] = "46c0002cFGH", | |
| 767 ["plu.ps_3"] = "46c0002dFGH", | |
| 768 ["pul.ps_3"] = "46c0002eFGH", | |
| 769 ["puu.ps_3"] = "46c0002fFGH", | |
| 770 ["c.f.ps_2"] = "46c00030GH", | |
| 771 ["c.f.ps_3"] = "46c00030VGH", | |
| 772 ["c.un.ps_2"] = "46c00031GH", | |
| 773 ["c.un.ps_3"] = "46c00031VGH", | |
| 774 ["c.eq.ps_2"] = "46c00032GH", | |
| 775 ["c.eq.ps_3"] = "46c00032VGH", | |
| 776 ["c.ueq.ps_2"] = "46c00033GH", | |
| 777 ["c.ueq.ps_3"] = "46c00033VGH", | |
| 778 ["c.olt.ps_2"] = "46c00034GH", | |
| 779 ["c.olt.ps_3"] = "46c00034VGH", | |
| 780 ["c.ult.ps_2"] = "46c00035GH", | |
| 781 ["c.ult.ps_3"] = "46c00035VGH", | |
| 782 ["c.ole.ps_2"] = "46c00036GH", | |
| 783 ["c.ole.ps_3"] = "46c00036VGH", | |
| 784 ["c.ule.ps_2"] = "46c00037GH", | |
| 785 ["c.ule.ps_3"] = "46c00037VGH", | |
| 786 ["c.sf.ps_2"] = "46c00038GH", | |
| 787 ["c.sf.ps_3"] = "46c00038VGH", | |
| 788 ["c.ngle.ps_2"] = "46c00039GH", | |
| 789 ["c.ngle.ps_3"] = "46c00039VGH", | |
| 790 ["c.seq.ps_2"] = "46c0003aGH", | |
| 791 ["c.seq.ps_3"] = "46c0003aVGH", | |
| 792 ["c.ngl.ps_2"] = "46c0003bGH", | |
| 793 ["c.ngl.ps_3"] = "46c0003bVGH", | |
| 794 ["c.lt.ps_2"] = "46c0003cGH", | |
| 795 ["c.lt.ps_3"] = "46c0003cVGH", | |
| 796 ["c.nge.ps_2"] = "46c0003dGH", | |
| 797 ["c.nge.ps_3"] = "46c0003dVGH", | |
| 798 ["c.le.ps_2"] = "46c0003eGH", | |
| 799 ["c.le.ps_3"] = "46c0003eVGH", | |
| 800 ["c.ngt.ps_2"] = "46c0003fGH", | |
| 801 ["c.ngt.ps_3"] = "46c0003fVGH", | |
| 802 | |
| 803 -- Opcode COP1X. | |
| 804 lwxc1_2 = "4c000000FX", | |
| 805 ldxc1_2 = "4c000001FX", | |
| 806 luxc1_2 = "4c000005FX", | |
| 807 swxc1_2 = "4c000008FX", | |
| 808 sdxc1_2 = "4c000009FX", | |
| 809 suxc1_2 = "4c00000dFX", | |
| 810 prefx_2 = "4c00000fMX", | |
| 811 ["alnv.ps_4"] = "4c00001eFGHS", | |
| 812 ["madd.s_4"] = "4c000020FRGH", | |
| 813 ["madd.d_4"] = "4c000021FRGH", | |
| 814 ["madd.ps_4"] = "4c000026FRGH", | |
| 815 ["msub.s_4"] = "4c000028FRGH", | |
| 816 ["msub.d_4"] = "4c000029FRGH", | |
| 817 ["msub.ps_4"] = "4c00002eFRGH", | |
| 818 ["nmadd.s_4"] = "4c000030FRGH", | |
| 819 ["nmadd.d_4"] = "4c000031FRGH", | |
| 820 ["nmadd.ps_4"] = "4c000036FRGH", | |
| 821 ["nmsub.s_4"] = "4c000038FRGH", | |
| 822 ["nmsub.d_4"] = "4c000039FRGH", | |
| 823 ["nmsub.ps_4"] = "4c00003eFRGH", | |
| 824 | |
| 825 }) do map_op[k] = v end | |
| 826 | |
| 827 end | |
| 828 | |
| 829 ------------------------------------------------------------------------------ | |
| 830 | |
| 831 local function parse_gpr(expr) | |
| 832 local tname, ovreg = match(expr, "^([%w_]+):(r[1-3]?[0-9])$") | |
| 833 local tp = map_type[tname or expr] | |
| 834 if tp then | |
| 835 local reg = ovreg or tp.reg | |
| 836 if not reg then | |
| 837 werror("type `"..(tname or expr).."' needs a register override") | |
| 838 end | |
| 839 expr = reg | |
| 840 end | |
| 841 local r = match(expr, "^r([1-3]?[0-9])$") | |
| 842 if r then | |
| 843 r = tonumber(r) | |
| 844 if r <= 31 then return r, tp end | |
| 845 end | |
| 846 werror("bad register name `"..expr.."'") | |
| 847 end | |
| 848 | |
| 849 local function parse_fpr(expr) | |
| 850 local r = match(expr, "^f([1-3]?[0-9])$") | |
| 851 if r then | |
| 852 r = tonumber(r) | |
| 853 if r <= 31 then return r end | |
| 854 end | |
| 855 werror("bad register name `"..expr.."'") | |
| 856 end | |
| 857 | |
| 858 local function parse_imm(imm, bits, shift, scale, signed, action) | |
| 859 local n = tonumber(imm) | |
| 860 if n then | |
| 861 local m = sar(n, scale) | |
| 862 if shl(m, scale) == n then | |
| 863 if signed then | |
| 864 local s = sar(m, bits-1) | |
| 865 if s == 0 then return shl(m, shift) | |
| 866 elseif s == -1 then return shl(m + shl(1, bits), shift) end | |
| 867 else | |
| 868 if sar(m, bits) == 0 then return shl(m, shift) end | |
| 869 end | |
| 870 end | |
| 871 werror("out of range immediate `"..imm.."'") | |
| 872 elseif match(imm, "^[rf]([1-3]?[0-9])$") or | |
| 873 match(imm, "^([%w_]+):([rf][1-3]?[0-9])$") then | |
| 874 werror("expected immediate operand, got register") | |
| 875 else | |
| 876 waction(action or "IMM", | |
| 877 (signed and 32768 or 0)+shl(scale, 10)+shl(bits, 5)+shift, imm) | |
| 878 return 0 | |
| 879 end | |
| 880 end | |
| 881 | |
| 882 local function parse_disp(disp) | |
| 883 local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$") | |
| 884 if imm then | |
| 885 local r = shl(parse_gpr(reg), 21) | |
| 886 local extname = match(imm, "^extern%s+(%S+)$") | |
| 887 if extname then | |
| 888 waction("REL_EXT", map_extern[extname], nil, 1) | |
| 889 return r | |
| 890 else | |
| 891 return r + parse_imm(imm, 16, 0, 0, true) | |
| 892 end | |
| 893 end | |
| 894 local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") | |
| 895 if reg and tailr ~= "" then | |
| 896 local r, tp = parse_gpr(reg) | |
| 897 if tp then | |
| 898 waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr)) | |
| 899 return shl(r, 21) | |
| 900 end | |
| 901 end | |
| 902 werror("bad displacement `"..disp.."'") | |
| 903 end | |
| 904 | |
| 905 local function parse_index(idx) | |
| 906 local rt, rs = match(idx, "^(.*)%(([%w_:]+)%)$") | |
| 907 if rt then | |
| 908 rt = parse_gpr(rt) | |
| 909 rs = parse_gpr(rs) | |
| 910 return shl(rt, 16) + shl(rs, 21) | |
| 911 end | |
| 912 werror("bad index `"..idx.."'") | |
| 913 end | |
| 914 | |
| 915 local function parse_label(label, def) | |
| 916 local prefix = sub(label, 1, 2) | |
| 917 -- =>label (pc label reference) | |
| 918 if prefix == "=>" then | |
| 919 return "PC", 0, sub(label, 3) | |
| 920 end | |
| 921 -- ->name (global label reference) | |
| 922 if prefix == "->" then | |
| 923 return "LG", map_global[sub(label, 3)] | |
| 924 end | |
| 925 if def then | |
| 926 -- [1-9] (local label definition) | |
| 927 if match(label, "^[1-9]$") then | |
| 928 return "LG", 10+tonumber(label) | |
| 929 end | |
| 930 else | |
| 931 -- [<>][1-9] (local label reference) | |
| 932 local dir, lnum = match(label, "^([<>])([1-9])$") | |
| 933 if dir then -- Fwd: 1-9, Bkwd: 11-19. | |
| 934 return "LG", lnum + (dir == ">" and 0 or 10) | |
| 935 end | |
| 936 -- extern label (extern label reference) | |
| 937 local extname = match(label, "^extern%s+(%S+)$") | |
| 938 if extname then | |
| 939 return "EXT", map_extern[extname] | |
| 940 end | |
| 941 end | |
| 942 werror("bad label `"..label.."'") | |
| 943 end | |
| 944 | |
| 945 ------------------------------------------------------------------------------ | |
| 946 | |
| 947 -- Handle opcodes defined with template strings. | |
| 948 map_op[".template__"] = function(params, template, nparams) | |
| 949 if not params then return sub(template, 9) end | |
| 950 local op = tonumber(sub(template, 1, 8), 16) | |
| 951 local n = 1 | |
| 952 | |
| 953 -- Limit number of section buffer positions used by a single dasm_put(). | |
| 954 -- A single opcode needs a maximum of 2 positions (ins/ext). | |
| 955 if secpos+2 > maxsecpos then wflush() end | |
| 956 local pos = wpos() | |
| 957 | |
| 958 -- Process each character. | |
| 959 for p in gmatch(sub(template, 9), ".") do | |
| 960 if p == "D" then | |
| 961 op = op + shl(parse_gpr(params[n]), 11); n = n + 1 | |
| 962 elseif p == "T" then | |
| 963 op = op + shl(parse_gpr(params[n]), 16); n = n + 1 | |
| 964 elseif p == "S" then | |
| 965 op = op + shl(parse_gpr(params[n]), 21); n = n + 1 | |
| 966 elseif p == "F" then | |
| 967 op = op + shl(parse_fpr(params[n]), 6); n = n + 1 | |
| 968 elseif p == "G" then | |
| 969 op = op + shl(parse_fpr(params[n]), 11); n = n + 1 | |
| 970 elseif p == "H" then | |
| 971 op = op + shl(parse_fpr(params[n]), 16); n = n + 1 | |
| 972 elseif p == "R" then | |
| 973 op = op + shl(parse_fpr(params[n]), 21); n = n + 1 | |
| 974 elseif p == "I" then | |
| 975 op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1 | |
| 976 elseif p == "U" then | |
| 977 op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1 | |
| 978 elseif p == "O" then | |
| 979 op = op + parse_disp(params[n]); n = n + 1 | |
| 980 elseif p == "X" then | |
| 981 op = op + parse_index(params[n]); n = n + 1 | |
| 982 elseif p == "B" or p == "J" or p == "K" or p == "L" then | |
| 983 local mode, m, s = parse_label(params[n], false) | |
| 984 if p == "J" then m = m + 0xa800 | |
| 985 elseif p == "K" then m = m + 0x5000 | |
| 986 elseif p == "L" then m = m + 0xa000 end | |
| 987 waction("REL_"..mode, m, s, 1) | |
| 988 n = n + 1 | |
| 989 elseif p == "A" then | |
| 990 op = op + parse_imm(params[n], 5, 6, 0, false); n = n + 1 | |
| 991 elseif p == "a" then | |
| 992 local m = parse_imm(params[n], 6, 6, 0, false, "IMMS"); n = n + 1 | |
| 993 op = op + band(m, 0x7c0) + band(shr(m, 9), 4) | |
| 994 elseif p == "M" then | |
| 995 op = op + parse_imm(params[n], 5, 11, 0, false); n = n + 1 | |
| 996 elseif p == "N" then | |
| 997 op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1 | |
| 998 elseif p == "C" then | |
| 999 op = op + parse_imm(params[n], 3, 18, 0, false); n = n + 1 | |
| 1000 elseif p == "V" then | |
| 1001 op = op + parse_imm(params[n], 3, 8, 0, false); n = n + 1 | |
| 1002 elseif p == "W" then | |
| 1003 op = op + parse_imm(params[n], 3, 0, 0, false); n = n + 1 | |
| 1004 elseif p == "Y" then | |
| 1005 op = op + parse_imm(params[n], 20, 6, 0, false); n = n + 1 | |
| 1006 elseif p == "Z" then | |
| 1007 op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1 | |
| 1008 elseif p == "=" then | |
| 1009 n = n - 1 -- Re-use previous parameter for next template char. | |
| 1010 else | |
| 1011 assert(false) | |
| 1012 end | |
| 1013 end | |
| 1014 wputpos(pos, op) | |
| 1015 end | |
| 1016 | |
| 1017 ------------------------------------------------------------------------------ | |
| 1018 | |
| 1019 -- Pseudo-opcode to mark the position where the action list is to be emitted. | |
| 1020 map_op[".actionlist_1"] = function(params) | |
| 1021 if not params then return "cvar" end | |
| 1022 local name = params[1] -- No syntax check. You get to keep the pieces. | |
| 1023 wline(function(out) writeactions(out, name) end) | |
| 1024 end | |
| 1025 | |
| 1026 -- Pseudo-opcode to mark the position where the global enum is to be emitted. | |
| 1027 map_op[".globals_1"] = function(params) | |
| 1028 if not params then return "prefix" end | |
| 1029 local prefix = params[1] -- No syntax check. You get to keep the pieces. | |
| 1030 wline(function(out) writeglobals(out, prefix) end) | |
| 1031 end | |
| 1032 | |
| 1033 -- Pseudo-opcode to mark the position where the global names are to be emitted. | |
| 1034 map_op[".globalnames_1"] = function(params) | |
| 1035 if not params then return "cvar" end | |
| 1036 local name = params[1] -- No syntax check. You get to keep the pieces. | |
| 1037 wline(function(out) writeglobalnames(out, name) end) | |
| 1038 end | |
| 1039 | |
| 1040 -- Pseudo-opcode to mark the position where the extern names are to be emitted. | |
| 1041 map_op[".externnames_1"] = function(params) | |
| 1042 if not params then return "cvar" end | |
| 1043 local name = params[1] -- No syntax check. You get to keep the pieces. | |
| 1044 wline(function(out) writeexternnames(out, name) end) | |
| 1045 end | |
| 1046 | |
| 1047 ------------------------------------------------------------------------------ | |
| 1048 | |
| 1049 -- Label pseudo-opcode (converted from trailing colon form). | |
| 1050 map_op[".label_1"] = function(params) | |
| 1051 if not params then return "[1-9] | ->global | =>pcexpr" end | |
| 1052 if secpos+1 > maxsecpos then wflush() end | |
| 1053 local mode, n, s = parse_label(params[1], true) | |
| 1054 if mode == "EXT" then werror("bad label definition") end | |
| 1055 waction("LABEL_"..mode, n, s, 1) | |
| 1056 end | |
| 1057 | |
| 1058 ------------------------------------------------------------------------------ | |
| 1059 | |
| 1060 -- Pseudo-opcodes for data storage. | |
| 1061 map_op[".long_*"] = function(params) | |
| 1062 if not params then return "imm..." end | |
| 1063 for _,p in ipairs(params) do | |
| 1064 local n = tonumber(p) | |
| 1065 if not n then werror("bad immediate `"..p.."'") end | |
| 1066 if n < 0 then n = n + 2^32 end | |
| 1067 wputw(n) | |
| 1068 if secpos+2 > maxsecpos then wflush() end | |
| 1069 end | |
| 1070 end | |
| 1071 | |
| 1072 -- Alignment pseudo-opcode. | |
| 1073 map_op[".align_1"] = function(params) | |
| 1074 if not params then return "numpow2" end | |
| 1075 if secpos+1 > maxsecpos then wflush() end | |
| 1076 local align = tonumber(params[1]) | |
| 1077 if align then | |
| 1078 local x = align | |
| 1079 -- Must be a power of 2 in the range (2 ... 256). | |
| 1080 for i=1,8 do | |
| 1081 x = x / 2 | |
| 1082 if x == 1 then | |
| 1083 waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1. | |
| 1084 return | |
| 1085 end | |
| 1086 end | |
| 1087 end | |
| 1088 werror("bad alignment") | |
| 1089 end | |
| 1090 | |
| 1091 ------------------------------------------------------------------------------ | |
| 1092 | |
| 1093 -- Pseudo-opcode for (primitive) type definitions (map to C types). | |
| 1094 map_op[".type_3"] = function(params, nparams) | |
| 1095 if not params then | |
| 1096 return nparams == 2 and "name, ctype" or "name, ctype, reg" | |
| 1097 end | |
| 1098 local name, ctype, reg = params[1], params[2], params[3] | |
| 1099 if not match(name, "^[%a_][%w_]*$") then | |
| 1100 werror("bad type name `"..name.."'") | |
| 1101 end | |
| 1102 local tp = map_type[name] | |
| 1103 if tp then | |
| 1104 werror("duplicate type `"..name.."'") | |
| 1105 end | |
| 1106 -- Add #type to defines. A bit unclean to put it in map_archdef. | |
| 1107 map_archdef["#"..name] = "sizeof("..ctype..")" | |
| 1108 -- Add new type and emit shortcut define. | |
| 1109 local num = ctypenum + 1 | |
| 1110 map_type[name] = { | |
| 1111 ctype = ctype, | |
| 1112 ctypefmt = format("Dt%X(%%s)", num), | |
| 1113 reg = reg, | |
| 1114 } | |
| 1115 wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype)) | |
| 1116 ctypenum = num | |
| 1117 end | |
| 1118 map_op[".type_2"] = map_op[".type_3"] | |
| 1119 | |
| 1120 -- Dump type definitions. | |
| 1121 local function dumptypes(out, lvl) | |
| 1122 local t = {} | |
| 1123 for name in pairs(map_type) do t[#t+1] = name end | |
| 1124 sort(t) | |
| 1125 out:write("Type definitions:\n") | |
| 1126 for _,name in ipairs(t) do | |
| 1127 local tp = map_type[name] | |
| 1128 local reg = tp.reg or "" | |
| 1129 out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg)) | |
| 1130 end | |
| 1131 out:write("\n") | |
| 1132 end | |
| 1133 | |
| 1134 ------------------------------------------------------------------------------ | |
| 1135 | |
| 1136 -- Set the current section. | |
| 1137 function _M.section(num) | |
| 1138 waction("SECTION", num) | |
| 1139 wflush(true) -- SECTION is a terminal action. | |
| 1140 end | |
| 1141 | |
| 1142 ------------------------------------------------------------------------------ | |
| 1143 | |
| 1144 -- Dump architecture description. | |
| 1145 function _M.dumparch(out) | |
| 1146 out:write(format("DynASM %s version %s, released %s\n\n", | |
| 1147 _info.arch, _info.version, _info.release)) | |
| 1148 dumpactions(out) | |
| 1149 end | |
| 1150 | |
| 1151 -- Dump all user defined elements. | |
| 1152 function _M.dumpdef(out, lvl) | |
| 1153 dumptypes(out, lvl) | |
| 1154 dumpglobals(out, lvl) | |
| 1155 dumpexterns(out, lvl) | |
| 1156 end | |
| 1157 | |
| 1158 ------------------------------------------------------------------------------ | |
| 1159 | |
| 1160 -- Pass callbacks from/to the DynASM core. | |
| 1161 function _M.passcb(wl, we, wf, ww) | |
| 1162 wline, werror, wfatal, wwarn = wl, we, wf, ww | |
| 1163 return wflush | |
| 1164 end | |
| 1165 | |
| 1166 -- Setup the arch-specific module. | |
| 1167 function _M.setup(arch, opt) | |
| 1168 g_arch, g_opt = arch, opt | |
| 1169 end | |
| 1170 | |
| 1171 -- Merge the core maps and the arch-specific maps. | |
| 1172 function _M.mergemaps(map_coreop, map_def) | |
| 1173 setmetatable(map_op, { __index = map_coreop }) | |
| 1174 setmetatable(map_def, { __index = map_archdef }) | |
| 1175 return map_op, map_def | |
| 1176 end | |
| 1177 | |
| 1178 return _M | |
| 1179 | |
| 1180 ------------------------------------------------------------------------------ | |
| 1181 |