ljx

FORK: LuaJIT with native 5.2 and 5.3 support
git clone https://git.neptards.moe/neptards/ljx.git
Log | Files | Refs | README

dasm_mips.lua (30354B)


      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 
      8 local mips64 = mips64
      9 
     10 -- Module information:
     11 local _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.
     22 local _M = { _info = _info }
     23 
     24 -- Cache library functions.
     25 local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
     26 local assert, setmetatable = assert, setmetatable
     27 local _s = string
     28 local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
     29 local match, gmatch = _s.match, _s.gmatch
     30 local concat, sort = table.concat, table.sort
     31 local bit = bit or require("bit")
     32 local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
     33 local tohex = bit.tohex
     34 
     35 -- Inherited tables and callbacks.
     36 local g_opt, g_arch
     37 local wline, werror, wfatal, wwarn
     38 
     39 -- Action name list.
     40 -- CHECK: Keep this in sync with the C code!
     41 local 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!
     49 local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
     50 
     51 -- Action name -> action number.
     52 local map_action = {}
     53 for n,name in ipairs(action_names) do
     54   map_action[name] = n-1
     55 end
     56 
     57 -- Action list buffer.
     58 local actlist = {}
     59 
     60 -- Argument list for next dasm_put(). Start with offset 0 into action list.
     61 local actargs = { 0 }
     62 
     63 -- Current number of section buffer positions for dasm_put().
     64 local secpos = 1
     65 
     66 ------------------------------------------------------------------------------
     67 
     68 -- Dump action names and numbers.
     69 local 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")
     76 end
     77 
     78 -- Write action list buffer as a huge static C array.
     79 local 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"))
     87 end
     88 
     89 ------------------------------------------------------------------------------
     90 
     91 -- Add word to action list.
     92 local function wputxw(n)
     93   assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
     94   actlist[#actlist+1] = n
     95 end
     96 
     97 -- Add action to list with optional arg. Advance buffer pos, too.
     98 local 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
    103 end
    104 
    105 -- Flush action list (intervening C code or buffer pos overflow).
    106 local 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.
    112 end
    113 
    114 -- Put escaped word.
    115 local function wputw(n)
    116   if n >= 0xff000000 then waction("ESC") end
    117   wputxw(n)
    118 end
    119 
    120 -- Reserve position for word.
    121 local function wpos()
    122   local pos = #actlist+1
    123   actlist[pos] = ""
    124   return pos
    125 end
    126 
    127 -- Store word to reserved position.
    128 local function wputpos(pos, n)
    129   assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
    130   actlist[pos] = n
    131 end
    132 
    133 ------------------------------------------------------------------------------
    134 
    135 -- Global label name -> global label number. With auto assignment on 1st use.
    136 local next_global = 20
    137 local 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
    144 end})
    145 
    146 -- Dump global labels.
    147 local 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")
    155 end
    156 
    157 -- Write global label enum.
    158 local 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")
    166 end
    167 
    168 -- Write global label names.
    169 local 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")
    177 end
    178 
    179 ------------------------------------------------------------------------------
    180 
    181 -- Extern label name -> extern label number. With auto assignment on 1st use.
    182 local next_extern = 0
    183 local map_extern_ = {}
    184 local 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
    192 end})
    193 
    194 -- Dump extern labels.
    195 local 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")
    201 end
    202 
    203 -- Write extern label names.
    204 local 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")
    210 end
    211 
    212 ------------------------------------------------------------------------------
    213 
    214 -- Arch-specific maps.
    215 local map_archdef = { sp="r29", ra="r31" } -- Ext. register name -> int. name.
    216 
    217 local map_type = {}		-- Type name -> { ctype, reg }
    218 local ctypenum = 0		-- Type number (for Dt... macros).
    219 
    220 -- Reverse defines for registers.
    221 function _M.revdef(s)
    222   if s == "r29" then return "sp"
    223   elseif s == "r31" then return "ra" end
    224   return s
    225 end
    226 
    227 ------------------------------------------------------------------------------
    228 
    229 -- Template strings for MIPS instructions.
    230 local 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 
    660 local 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.."'")
    676 end
    677 
    678 local 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.."'")
    685 end
    686 
    687 local 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
    709 end
    710 
    711 local 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.."'")
    732 end
    733 
    734 local 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.."'")
    742 end
    743 
    744 local 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.."'")
    772 end
    773 
    774 ------------------------------------------------------------------------------
    775 
    776 -- Handle opcodes defined with template strings.
    777 map_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)
    842 end
    843 
    844 ------------------------------------------------------------------------------
    845 
    846 -- Pseudo-opcode to mark the position where the action list is to be emitted.
    847 map_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)
    851 end
    852 
    853 -- Pseudo-opcode to mark the position where the global enum is to be emitted.
    854 map_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)
    858 end
    859 
    860 -- Pseudo-opcode to mark the position where the global names are to be emitted.
    861 map_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)
    865 end
    866 
    867 -- Pseudo-opcode to mark the position where the extern names are to be emitted.
    868 map_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)
    872 end
    873 
    874 ------------------------------------------------------------------------------
    875 
    876 -- Label pseudo-opcode (converted from trailing colon form).
    877 map_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)
    883 end
    884 
    885 ------------------------------------------------------------------------------
    886 
    887 -- Pseudo-opcodes for data storage.
    888 map_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
    897 end
    898 
    899 -- Alignment pseudo-opcode.
    900 map_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")
    916 end
    917 
    918 ------------------------------------------------------------------------------
    919 
    920 -- Pseudo-opcode for (primitive) type definitions (map to C types).
    921 map_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
    944 end
    945 map_op[".type_2"] = map_op[".type_3"]
    946 
    947 -- Dump type definitions.
    948 local 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")
    959 end
    960 
    961 ------------------------------------------------------------------------------
    962 
    963 -- Set the current section.
    964 function _M.section(num)
    965   waction("SECTION", num)
    966   wflush(true) -- SECTION is a terminal action.
    967 end
    968 
    969 ------------------------------------------------------------------------------
    970 
    971 -- Dump architecture description.
    972 function _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)
    976 end
    977 
    978 -- Dump all user defined elements.
    979 function _M.dumpdef(out, lvl)
    980   dumptypes(out, lvl)
    981   dumpglobals(out, lvl)
    982   dumpexterns(out, lvl)
    983 end
    984 
    985 ------------------------------------------------------------------------------
    986 
    987 -- Pass callbacks from/to the DynASM core.
    988 function _M.passcb(wl, we, wf, ww)
    989   wline, werror, wfatal, wwarn = wl, we, wf, ww
    990   return wflush
    991 end
    992 
    993 -- Setup the arch-specific module.
    994 function _M.setup(arch, opt)
    995   g_arch, g_opt = arch, opt
    996 end
    997 
    998 -- Merge the core maps and the arch-specific maps.
    999 function _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
   1003 end
   1004 
   1005 return _M
   1006 
   1007 ------------------------------------------------------------------------------
   1008