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