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