dasm_mips.lua 27 KB

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