dasm_mips.lua 30 KB

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