dasm_ppc.lua 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249
  1. ------------------------------------------------------------------------------
  2. -- DynASM PPC module.
  3. --
  4. -- Copyright (C) 2005-2013 Mike Pall. All rights reserved.
  5. -- See dynasm.lua for full copyright notice.
  6. ------------------------------------------------------------------------------
  7. -- Module information:
  8. local _info = {
  9. arch = "ppc",
  10. description = "DynASM PPC module",
  11. version = "1.3.0",
  12. vernum = 10300,
  13. release = "2011-05-05",
  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. local bit = bit or require("bit")
  27. local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
  28. local tohex = bit.tohex
  29. -- Inherited tables and callbacks.
  30. local g_opt, g_arch
  31. local wline, werror, wfatal, wwarn
  32. -- Action name list.
  33. -- CHECK: Keep this in sync with the C code!
  34. local action_names = {
  35. "STOP", "SECTION", "ESC", "REL_EXT",
  36. "ALIGN", "REL_LG", "LABEL_LG",
  37. "REL_PC", "LABEL_PC", "IMM",
  38. }
  39. -- Maximum number of section buffer positions for dasm_put().
  40. -- CHECK: Keep this in sync with the C code!
  41. local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
  42. -- Action name -> action number.
  43. local map_action = {}
  44. for n,name in ipairs(action_names) do
  45. map_action[name] = n-1
  46. end
  47. -- Action list buffer.
  48. local actlist = {}
  49. -- Argument list for next dasm_put(). Start with offset 0 into action list.
  50. local actargs = { 0 }
  51. -- Current number of section buffer positions for dasm_put().
  52. local secpos = 1
  53. ------------------------------------------------------------------------------
  54. -- Dump action names and numbers.
  55. local function dumpactions(out)
  56. out:write("DynASM encoding engine action codes:\n")
  57. for n,name in ipairs(action_names) do
  58. local num = map_action[name]
  59. out:write(format(" %-10s %02X %d\n", name, num, num))
  60. end
  61. out:write("\n")
  62. end
  63. -- Write action list buffer as a huge static C array.
  64. local function writeactions(out, name)
  65. local nn = #actlist
  66. if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
  67. out:write("static const unsigned int ", name, "[", nn, "] = {\n")
  68. for i = 1,nn-1 do
  69. assert(out:write("0x", tohex(actlist[i]), ",\n"))
  70. end
  71. assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
  72. end
  73. ------------------------------------------------------------------------------
  74. -- Add word to action list.
  75. local function wputxw(n)
  76. assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
  77. actlist[#actlist+1] = n
  78. end
  79. -- Add action to list with optional arg. Advance buffer pos, too.
  80. local function waction(action, val, a, num)
  81. local w = assert(map_action[action], "bad action name `"..action.."'")
  82. wputxw(w * 0x10000 + (val or 0))
  83. if a then actargs[#actargs+1] = a end
  84. if a or num then secpos = secpos + (num or 1) end
  85. end
  86. -- Flush action list (intervening C code or buffer pos overflow).
  87. local function wflush(term)
  88. if #actlist == actargs[1] then return end -- Nothing to flush.
  89. if not term then waction("STOP") end -- Terminate action list.
  90. wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true)
  91. actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
  92. secpos = 1 -- The actionlist offset occupies a buffer position, too.
  93. end
  94. -- Put escaped word.
  95. local function wputw(n)
  96. if n <= 0xffffff then waction("ESC") end
  97. wputxw(n)
  98. end
  99. -- Reserve position for word.
  100. local function wpos()
  101. local pos = #actlist+1
  102. actlist[pos] = ""
  103. return pos
  104. end
  105. -- Store word to reserved position.
  106. local function wputpos(pos, n)
  107. assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
  108. actlist[pos] = n
  109. end
  110. ------------------------------------------------------------------------------
  111. -- Global label name -> global label number. With auto assignment on 1st use.
  112. local next_global = 20
  113. local map_global = setmetatable({}, { __index = function(t, name)
  114. if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
  115. local n = next_global
  116. if n > 2047 then werror("too many global labels") end
  117. next_global = n + 1
  118. t[name] = n
  119. return n
  120. end})
  121. -- Dump global labels.
  122. local function dumpglobals(out, lvl)
  123. local t = {}
  124. for name, n in pairs(map_global) do t[n] = name end
  125. out:write("Global labels:\n")
  126. for i=20,next_global-1 do
  127. out:write(format(" %s\n", t[i]))
  128. end
  129. out:write("\n")
  130. end
  131. -- Write global label enum.
  132. local function writeglobals(out, prefix)
  133. local t = {}
  134. for name, n in pairs(map_global) do t[n] = name end
  135. out:write("enum {\n")
  136. for i=20,next_global-1 do
  137. out:write(" ", prefix, t[i], ",\n")
  138. end
  139. out:write(" ", prefix, "_MAX\n};\n")
  140. end
  141. -- Write global label names.
  142. local function writeglobalnames(out, name)
  143. local t = {}
  144. for name, n in pairs(map_global) do t[n] = name end
  145. out:write("static const char *const ", name, "[] = {\n")
  146. for i=20,next_global-1 do
  147. out:write(" \"", t[i], "\",\n")
  148. end
  149. out:write(" (const char *)0\n};\n")
  150. end
  151. ------------------------------------------------------------------------------
  152. -- Extern label name -> extern label number. With auto assignment on 1st use.
  153. local next_extern = 0
  154. local map_extern_ = {}
  155. local map_extern = setmetatable({}, { __index = function(t, name)
  156. -- No restrictions on the name for now.
  157. local n = next_extern
  158. if n > 2047 then werror("too many extern labels") end
  159. next_extern = n + 1
  160. t[name] = n
  161. map_extern_[n] = name
  162. return n
  163. end})
  164. -- Dump extern labels.
  165. local function dumpexterns(out, lvl)
  166. out:write("Extern labels:\n")
  167. for i=0,next_extern-1 do
  168. out:write(format(" %s\n", map_extern_[i]))
  169. end
  170. out:write("\n")
  171. end
  172. -- Write extern label names.
  173. local function writeexternnames(out, name)
  174. out:write("static const char *const ", name, "[] = {\n")
  175. for i=0,next_extern-1 do
  176. out:write(" \"", map_extern_[i], "\",\n")
  177. end
  178. out:write(" (const char *)0\n};\n")
  179. end
  180. ------------------------------------------------------------------------------
  181. -- Arch-specific maps.
  182. local map_archdef = { sp = "r1" } -- Ext. register name -> int. name.
  183. local map_type = {} -- Type name -> { ctype, reg }
  184. local ctypenum = 0 -- Type number (for Dt... macros).
  185. -- Reverse defines for registers.
  186. function _M.revdef(s)
  187. if s == "r1" then return "sp" end
  188. return s
  189. end
  190. local map_cond = {
  191. lt = 0, gt = 1, eq = 2, so = 3,
  192. ge = 4, le = 5, ne = 6, ns = 7,
  193. }
  194. ------------------------------------------------------------------------------
  195. -- Template strings for PPC instructions.
  196. local map_op = {
  197. tdi_3 = "08000000ARI",
  198. twi_3 = "0c000000ARI",
  199. mulli_3 = "1c000000RRI",
  200. subfic_3 = "20000000RRI",
  201. cmplwi_3 = "28000000XRU",
  202. cmplwi_2 = "28000000-RU",
  203. cmpldi_3 = "28200000XRU",
  204. cmpldi_2 = "28200000-RU",
  205. cmpwi_3 = "2c000000XRI",
  206. cmpwi_2 = "2c000000-RI",
  207. cmpdi_3 = "2c200000XRI",
  208. cmpdi_2 = "2c200000-RI",
  209. addic_3 = "30000000RRI",
  210. ["addic._3"] = "34000000RRI",
  211. addi_3 = "38000000RR0I",
  212. li_2 = "38000000RI",
  213. la_2 = "38000000RD",
  214. addis_3 = "3c000000RR0I",
  215. lis_2 = "3c000000RI",
  216. lus_2 = "3c000000RU",
  217. bc_3 = "40000000AAK",
  218. bcl_3 = "40000001AAK",
  219. bdnz_1 = "42000000K",
  220. bdz_1 = "42400000K",
  221. sc_0 = "44000000",
  222. b_1 = "48000000J",
  223. bl_1 = "48000001J",
  224. rlwimi_5 = "50000000RR~AAA.",
  225. rlwinm_5 = "54000000RR~AAA.",
  226. rlwnm_5 = "5c000000RR~RAA.",
  227. ori_3 = "60000000RR~U",
  228. nop_0 = "60000000",
  229. oris_3 = "64000000RR~U",
  230. xori_3 = "68000000RR~U",
  231. xoris_3 = "6c000000RR~U",
  232. ["andi._3"] = "70000000RR~U",
  233. ["andis._3"] = "74000000RR~U",
  234. lwz_2 = "80000000RD",
  235. lwzu_2 = "84000000RD",
  236. lbz_2 = "88000000RD",
  237. lbzu_2 = "8c000000RD",
  238. stw_2 = "90000000RD",
  239. stwu_2 = "94000000RD",
  240. stb_2 = "98000000RD",
  241. stbu_2 = "9c000000RD",
  242. lhz_2 = "a0000000RD",
  243. lhzu_2 = "a4000000RD",
  244. lha_2 = "a8000000RD",
  245. lhau_2 = "ac000000RD",
  246. sth_2 = "b0000000RD",
  247. sthu_2 = "b4000000RD",
  248. lmw_2 = "b8000000RD",
  249. stmw_2 = "bc000000RD",
  250. lfs_2 = "c0000000FD",
  251. lfsu_2 = "c4000000FD",
  252. lfd_2 = "c8000000FD",
  253. lfdu_2 = "cc000000FD",
  254. stfs_2 = "d0000000FD",
  255. stfsu_2 = "d4000000FD",
  256. stfd_2 = "d8000000FD",
  257. stfdu_2 = "dc000000FD",
  258. ld_2 = "e8000000RD", -- NYI: displacement must be divisible by 4.
  259. ldu_2 = "e8000001RD",
  260. lwa_2 = "e8000002RD",
  261. std_2 = "f8000000RD",
  262. stdu_2 = "f8000001RD",
  263. -- Primary opcode 19:
  264. mcrf_2 = "4c000000XX",
  265. isync_0 = "4c00012c",
  266. crnor_3 = "4c000042CCC",
  267. crnot_2 = "4c000042CC=",
  268. crandc_3 = "4c000102CCC",
  269. crxor_3 = "4c000182CCC",
  270. crclr_1 = "4c000182C==",
  271. crnand_3 = "4c0001c2CCC",
  272. crand_3 = "4c000202CCC",
  273. creqv_3 = "4c000242CCC",
  274. crset_1 = "4c000242C==",
  275. crorc_3 = "4c000342CCC",
  276. cror_3 = "4c000382CCC",
  277. crmove_2 = "4c000382CC=",
  278. bclr_2 = "4c000020AA",
  279. bclrl_2 = "4c000021AA",
  280. bcctr_2 = "4c000420AA",
  281. bcctrl_2 = "4c000421AA",
  282. blr_0 = "4e800020",
  283. blrl_0 = "4e800021",
  284. bctr_0 = "4e800420",
  285. bctrl_0 = "4e800421",
  286. -- Primary opcode 31:
  287. cmpw_3 = "7c000000XRR",
  288. cmpw_2 = "7c000000-RR",
  289. cmpd_3 = "7c200000XRR",
  290. cmpd_2 = "7c200000-RR",
  291. tw_3 = "7c000008ARR",
  292. subfc_3 = "7c000010RRR.",
  293. subc_3 = "7c000010RRR~.",
  294. mulhdu_3 = "7c000012RRR.",
  295. addc_3 = "7c000014RRR.",
  296. mulhwu_3 = "7c000016RRR.",
  297. isel_4 = "7c00001eRRRC",
  298. isellt_3 = "7c00001eRRR",
  299. iselgt_3 = "7c00005eRRR",
  300. iseleq_3 = "7c00009eRRR",
  301. mfcr_1 = "7c000026R",
  302. mfocrf_2 = "7c100026RG",
  303. mtcrf_2 = "7c000120GR",
  304. mtocrf_2 = "7c100120GR",
  305. lwarx_3 = "7c000028RR0R",
  306. ldx_3 = "7c00002aRR0R",
  307. lwzx_3 = "7c00002eRR0R",
  308. slw_3 = "7c000030RR~R.",
  309. cntlzw_2 = "7c000034RR~",
  310. sld_3 = "7c000036RR~R.",
  311. and_3 = "7c000038RR~R.",
  312. cmplw_3 = "7c000040XRR",
  313. cmplw_2 = "7c000040-RR",
  314. cmpld_3 = "7c200040XRR",
  315. cmpld_2 = "7c200040-RR",
  316. subf_3 = "7c000050RRR.",
  317. sub_3 = "7c000050RRR~.",
  318. ldux_3 = "7c00006aRR0R",
  319. dcbst_2 = "7c00006c-RR",
  320. lwzux_3 = "7c00006eRR0R",
  321. cntlzd_2 = "7c000074RR~",
  322. andc_3 = "7c000078RR~R.",
  323. td_3 = "7c000088ARR",
  324. mulhd_3 = "7c000092RRR.",
  325. mulhw_3 = "7c000096RRR.",
  326. ldarx_3 = "7c0000a8RR0R",
  327. dcbf_2 = "7c0000ac-RR",
  328. lbzx_3 = "7c0000aeRR0R",
  329. neg_2 = "7c0000d0RR.",
  330. lbzux_3 = "7c0000eeRR0R",
  331. popcntb_2 = "7c0000f4RR~",
  332. not_2 = "7c0000f8RR~%.",
  333. nor_3 = "7c0000f8RR~R.",
  334. subfe_3 = "7c000110RRR.",
  335. sube_3 = "7c000110RRR~.",
  336. adde_3 = "7c000114RRR.",
  337. stdx_3 = "7c00012aRR0R",
  338. stwcx_3 = "7c00012cRR0R.",
  339. stwx_3 = "7c00012eRR0R",
  340. prtyw_2 = "7c000134RR~",
  341. stdux_3 = "7c00016aRR0R",
  342. stwux_3 = "7c00016eRR0R",
  343. prtyd_2 = "7c000174RR~",
  344. subfze_2 = "7c000190RR.",
  345. addze_2 = "7c000194RR.",
  346. stdcx_3 = "7c0001acRR0R.",
  347. stbx_3 = "7c0001aeRR0R",
  348. subfme_2 = "7c0001d0RR.",
  349. mulld_3 = "7c0001d2RRR.",
  350. addme_2 = "7c0001d4RR.",
  351. mullw_3 = "7c0001d6RRR.",
  352. dcbtst_2 = "7c0001ec-RR",
  353. stbux_3 = "7c0001eeRR0R",
  354. add_3 = "7c000214RRR.",
  355. dcbt_2 = "7c00022c-RR",
  356. lhzx_3 = "7c00022eRR0R",
  357. eqv_3 = "7c000238RR~R.",
  358. eciwx_3 = "7c00026cRR0R",
  359. lhzux_3 = "7c00026eRR0R",
  360. xor_3 = "7c000278RR~R.",
  361. mfspefscr_1 = "7c0082a6R",
  362. mfxer_1 = "7c0102a6R",
  363. mflr_1 = "7c0802a6R",
  364. mfctr_1 = "7c0902a6R",
  365. lwax_3 = "7c0002aaRR0R",
  366. lhax_3 = "7c0002aeRR0R",
  367. mftb_1 = "7c0c42e6R",
  368. mftbu_1 = "7c0d42e6R",
  369. lwaux_3 = "7c0002eaRR0R",
  370. lhaux_3 = "7c0002eeRR0R",
  371. sthx_3 = "7c00032eRR0R",
  372. orc_3 = "7c000338RR~R.",
  373. ecowx_3 = "7c00036cRR0R",
  374. sthux_3 = "7c00036eRR0R",
  375. or_3 = "7c000378RR~R.",
  376. mr_2 = "7c000378RR~%.",
  377. divdu_3 = "7c000392RRR.",
  378. divwu_3 = "7c000396RRR.",
  379. mtspefscr_1 = "7c0083a6R",
  380. mtxer_1 = "7c0103a6R",
  381. mtlr_1 = "7c0803a6R",
  382. mtctr_1 = "7c0903a6R",
  383. dcbi_2 = "7c0003ac-RR",
  384. nand_3 = "7c0003b8RR~R.",
  385. divd_3 = "7c0003d2RRR.",
  386. divw_3 = "7c0003d6RRR.",
  387. cmpb_3 = "7c0003f8RR~R.",
  388. mcrxr_1 = "7c000400X",
  389. subfco_3 = "7c000410RRR.",
  390. subco_3 = "7c000410RRR~.",
  391. addco_3 = "7c000414RRR.",
  392. ldbrx_3 = "7c000428RR0R",
  393. lswx_3 = "7c00042aRR0R",
  394. lwbrx_3 = "7c00042cRR0R",
  395. lfsx_3 = "7c00042eFR0R",
  396. srw_3 = "7c000430RR~R.",
  397. srd_3 = "7c000436RR~R.",
  398. subfo_3 = "7c000450RRR.",
  399. subo_3 = "7c000450RRR~.",
  400. lfsux_3 = "7c00046eFR0R",
  401. lswi_3 = "7c0004aaRR0A",
  402. sync_0 = "7c0004ac",
  403. lwsync_0 = "7c2004ac",
  404. ptesync_0 = "7c4004ac",
  405. lfdx_3 = "7c0004aeFR0R",
  406. nego_2 = "7c0004d0RR.",
  407. lfdux_3 = "7c0004eeFR0R",
  408. subfeo_3 = "7c000510RRR.",
  409. subeo_3 = "7c000510RRR~.",
  410. addeo_3 = "7c000514RRR.",
  411. stdbrx_3 = "7c000528RR0R",
  412. stswx_3 = "7c00052aRR0R",
  413. stwbrx_3 = "7c00052cRR0R",
  414. stfsx_3 = "7c00052eFR0R",
  415. stfsux_3 = "7c00056eFR0R",
  416. subfzeo_2 = "7c000590RR.",
  417. addzeo_2 = "7c000594RR.",
  418. stswi_3 = "7c0005aaRR0A",
  419. stfdx_3 = "7c0005aeFR0R",
  420. subfmeo_2 = "7c0005d0RR.",
  421. mulldo_3 = "7c0005d2RRR.",
  422. addmeo_2 = "7c0005d4RR.",
  423. mullwo_3 = "7c0005d6RRR.",
  424. dcba_2 = "7c0005ec-RR",
  425. stfdux_3 = "7c0005eeFR0R",
  426. addo_3 = "7c000614RRR.",
  427. lhbrx_3 = "7c00062cRR0R",
  428. sraw_3 = "7c000630RR~R.",
  429. srad_3 = "7c000634RR~R.",
  430. srawi_3 = "7c000670RR~A.",
  431. sradi_3 = "7c000674RR~H.",
  432. eieio_0 = "7c0006ac",
  433. lfiwax_3 = "7c0006aeFR0R",
  434. sthbrx_3 = "7c00072cRR0R",
  435. extsh_2 = "7c000734RR~.",
  436. extsb_2 = "7c000774RR~.",
  437. divduo_3 = "7c000792RRR.",
  438. divwou_3 = "7c000796RRR.",
  439. icbi_2 = "7c0007ac-RR",
  440. stfiwx_3 = "7c0007aeFR0R",
  441. extsw_2 = "7c0007b4RR~.",
  442. divdo_3 = "7c0007d2RRR.",
  443. divwo_3 = "7c0007d6RRR.",
  444. dcbz_2 = "7c0007ec-RR",
  445. -- Primary opcode 30:
  446. rldicl_4 = "78000000RR~HM.",
  447. rldicr_4 = "78000004RR~HM.",
  448. rldic_4 = "78000008RR~HM.",
  449. rldimi_4 = "7800000cRR~HM.",
  450. rldcl_4 = "78000010RR~RM.",
  451. rldcr_4 = "78000012RR~RM.",
  452. -- Primary opcode 59:
  453. fdivs_3 = "ec000024FFF.",
  454. fsubs_3 = "ec000028FFF.",
  455. fadds_3 = "ec00002aFFF.",
  456. fsqrts_2 = "ec00002cF-F.",
  457. fres_2 = "ec000030F-F.",
  458. fmuls_3 = "ec000032FF-F.",
  459. frsqrtes_2 = "ec000034F-F.",
  460. fmsubs_4 = "ec000038FFFF~.",
  461. fmadds_4 = "ec00003aFFFF~.",
  462. fnmsubs_4 = "ec00003cFFFF~.",
  463. fnmadds_4 = "ec00003eFFFF~.",
  464. -- Primary opcode 63:
  465. fdiv_3 = "fc000024FFF.",
  466. fsub_3 = "fc000028FFF.",
  467. fadd_3 = "fc00002aFFF.",
  468. fsqrt_2 = "fc00002cF-F.",
  469. fsel_4 = "fc00002eFFFF~.",
  470. fre_2 = "fc000030F-F.",
  471. fmul_3 = "fc000032FF-F.",
  472. frsqrte_2 = "fc000034F-F.",
  473. fmsub_4 = "fc000038FFFF~.",
  474. fmadd_4 = "fc00003aFFFF~.",
  475. fnmsub_4 = "fc00003cFFFF~.",
  476. fnmadd_4 = "fc00003eFFFF~.",
  477. fcmpu_3 = "fc000000XFF",
  478. fcpsgn_3 = "fc000010FFF.",
  479. fcmpo_3 = "fc000040XFF",
  480. mtfsb1_1 = "fc00004cA",
  481. fneg_2 = "fc000050F-F.",
  482. mcrfs_2 = "fc000080XX",
  483. mtfsb0_1 = "fc00008cA",
  484. fmr_2 = "fc000090F-F.",
  485. frsp_2 = "fc000018F-F.",
  486. fctiw_2 = "fc00001cF-F.",
  487. fctiwz_2 = "fc00001eF-F.",
  488. mtfsfi_2 = "fc00010cAA", -- NYI: upshift.
  489. fnabs_2 = "fc000110F-F.",
  490. fabs_2 = "fc000210F-F.",
  491. frin_2 = "fc000310F-F.",
  492. friz_2 = "fc000350F-F.",
  493. frip_2 = "fc000390F-F.",
  494. frim_2 = "fc0003d0F-F.",
  495. mffs_1 = "fc00048eF.",
  496. -- NYI: mtfsf, mtfsb0, mtfsb1.
  497. fctid_2 = "fc00065cF-F.",
  498. fctidz_2 = "fc00065eF-F.",
  499. fcfid_2 = "fc00069cF-F.",
  500. -- Primary opcode 4, SPE APU extension:
  501. evaddw_3 = "10000200RRR",
  502. evaddiw_3 = "10000202RAR~",
  503. evsubw_3 = "10000204RRR~",
  504. evsubiw_3 = "10000206RAR~",
  505. evabs_2 = "10000208RR",
  506. evneg_2 = "10000209RR",
  507. evextsb_2 = "1000020aRR",
  508. evextsh_2 = "1000020bRR",
  509. evrndw_2 = "1000020cRR",
  510. evcntlzw_2 = "1000020dRR",
  511. evcntlsw_2 = "1000020eRR",
  512. brinc_3 = "1000020fRRR",
  513. evand_3 = "10000211RRR",
  514. evandc_3 = "10000212RRR",
  515. evxor_3 = "10000216RRR",
  516. evor_3 = "10000217RRR",
  517. evmr_2 = "10000217RR=",
  518. evnor_3 = "10000218RRR",
  519. evnot_2 = "10000218RR=",
  520. eveqv_3 = "10000219RRR",
  521. evorc_3 = "1000021bRRR",
  522. evnand_3 = "1000021eRRR",
  523. evsrwu_3 = "10000220RRR",
  524. evsrws_3 = "10000221RRR",
  525. evsrwiu_3 = "10000222RRA",
  526. evsrwis_3 = "10000223RRA",
  527. evslw_3 = "10000224RRR",
  528. evslwi_3 = "10000226RRA",
  529. evrlw_3 = "10000228RRR",
  530. evsplati_2 = "10000229RS",
  531. evrlwi_3 = "1000022aRRA",
  532. evsplatfi_2 = "1000022bRS",
  533. evmergehi_3 = "1000022cRRR",
  534. evmergelo_3 = "1000022dRRR",
  535. evcmpgtu_3 = "10000230XRR",
  536. evcmpgtu_2 = "10000230-RR",
  537. evcmpgts_3 = "10000231XRR",
  538. evcmpgts_2 = "10000231-RR",
  539. evcmpltu_3 = "10000232XRR",
  540. evcmpltu_2 = "10000232-RR",
  541. evcmplts_3 = "10000233XRR",
  542. evcmplts_2 = "10000233-RR",
  543. evcmpeq_3 = "10000234XRR",
  544. evcmpeq_2 = "10000234-RR",
  545. evsel_4 = "10000278RRRW",
  546. evsel_3 = "10000278RRR",
  547. evfsadd_3 = "10000280RRR",
  548. evfssub_3 = "10000281RRR",
  549. evfsabs_2 = "10000284RR",
  550. evfsnabs_2 = "10000285RR",
  551. evfsneg_2 = "10000286RR",
  552. evfsmul_3 = "10000288RRR",
  553. evfsdiv_3 = "10000289RRR",
  554. evfscmpgt_3 = "1000028cXRR",
  555. evfscmpgt_2 = "1000028c-RR",
  556. evfscmplt_3 = "1000028dXRR",
  557. evfscmplt_2 = "1000028d-RR",
  558. evfscmpeq_3 = "1000028eXRR",
  559. evfscmpeq_2 = "1000028e-RR",
  560. evfscfui_2 = "10000290R-R",
  561. evfscfsi_2 = "10000291R-R",
  562. evfscfuf_2 = "10000292R-R",
  563. evfscfsf_2 = "10000293R-R",
  564. evfsctui_2 = "10000294R-R",
  565. evfsctsi_2 = "10000295R-R",
  566. evfsctuf_2 = "10000296R-R",
  567. evfsctsf_2 = "10000297R-R",
  568. evfsctuiz_2 = "10000298R-R",
  569. evfsctsiz_2 = "1000029aR-R",
  570. evfststgt_3 = "1000029cXRR",
  571. evfststgt_2 = "1000029c-RR",
  572. evfststlt_3 = "1000029dXRR",
  573. evfststlt_2 = "1000029d-RR",
  574. evfststeq_3 = "1000029eXRR",
  575. evfststeq_2 = "1000029e-RR",
  576. efsadd_3 = "100002c0RRR",
  577. efssub_3 = "100002c1RRR",
  578. efsabs_2 = "100002c4RR",
  579. efsnabs_2 = "100002c5RR",
  580. efsneg_2 = "100002c6RR",
  581. efsmul_3 = "100002c8RRR",
  582. efsdiv_3 = "100002c9RRR",
  583. efscmpgt_3 = "100002ccXRR",
  584. efscmpgt_2 = "100002cc-RR",
  585. efscmplt_3 = "100002cdXRR",
  586. efscmplt_2 = "100002cd-RR",
  587. efscmpeq_3 = "100002ceXRR",
  588. efscmpeq_2 = "100002ce-RR",
  589. efscfd_2 = "100002cfR-R",
  590. efscfui_2 = "100002d0R-R",
  591. efscfsi_2 = "100002d1R-R",
  592. efscfuf_2 = "100002d2R-R",
  593. efscfsf_2 = "100002d3R-R",
  594. efsctui_2 = "100002d4R-R",
  595. efsctsi_2 = "100002d5R-R",
  596. efsctuf_2 = "100002d6R-R",
  597. efsctsf_2 = "100002d7R-R",
  598. efsctuiz_2 = "100002d8R-R",
  599. efsctsiz_2 = "100002daR-R",
  600. efststgt_3 = "100002dcXRR",
  601. efststgt_2 = "100002dc-RR",
  602. efststlt_3 = "100002ddXRR",
  603. efststlt_2 = "100002dd-RR",
  604. efststeq_3 = "100002deXRR",
  605. efststeq_2 = "100002de-RR",
  606. efdadd_3 = "100002e0RRR",
  607. efdsub_3 = "100002e1RRR",
  608. efdcfuid_2 = "100002e2R-R",
  609. efdcfsid_2 = "100002e3R-R",
  610. efdabs_2 = "100002e4RR",
  611. efdnabs_2 = "100002e5RR",
  612. efdneg_2 = "100002e6RR",
  613. efdmul_3 = "100002e8RRR",
  614. efddiv_3 = "100002e9RRR",
  615. efdctuidz_2 = "100002eaR-R",
  616. efdctsidz_2 = "100002ebR-R",
  617. efdcmpgt_3 = "100002ecXRR",
  618. efdcmpgt_2 = "100002ec-RR",
  619. efdcmplt_3 = "100002edXRR",
  620. efdcmplt_2 = "100002ed-RR",
  621. efdcmpeq_3 = "100002eeXRR",
  622. efdcmpeq_2 = "100002ee-RR",
  623. efdcfs_2 = "100002efR-R",
  624. efdcfui_2 = "100002f0R-R",
  625. efdcfsi_2 = "100002f1R-R",
  626. efdcfuf_2 = "100002f2R-R",
  627. efdcfsf_2 = "100002f3R-R",
  628. efdctui_2 = "100002f4R-R",
  629. efdctsi_2 = "100002f5R-R",
  630. efdctuf_2 = "100002f6R-R",
  631. efdctsf_2 = "100002f7R-R",
  632. efdctuiz_2 = "100002f8R-R",
  633. efdctsiz_2 = "100002faR-R",
  634. efdtstgt_3 = "100002fcXRR",
  635. efdtstgt_2 = "100002fc-RR",
  636. efdtstlt_3 = "100002fdXRR",
  637. efdtstlt_2 = "100002fd-RR",
  638. efdtsteq_3 = "100002feXRR",
  639. efdtsteq_2 = "100002fe-RR",
  640. evlddx_3 = "10000300RR0R",
  641. evldd_2 = "10000301R8",
  642. evldwx_3 = "10000302RR0R",
  643. evldw_2 = "10000303R8",
  644. evldhx_3 = "10000304RR0R",
  645. evldh_2 = "10000305R8",
  646. evlwhex_3 = "10000310RR0R",
  647. evlwhe_2 = "10000311R4",
  648. evlwhoux_3 = "10000314RR0R",
  649. evlwhou_2 = "10000315R4",
  650. evlwhosx_3 = "10000316RR0R",
  651. evlwhos_2 = "10000317R4",
  652. evstddx_3 = "10000320RR0R",
  653. evstdd_2 = "10000321R8",
  654. evstdwx_3 = "10000322RR0R",
  655. evstdw_2 = "10000323R8",
  656. evstdhx_3 = "10000324RR0R",
  657. evstdh_2 = "10000325R8",
  658. evstwhex_3 = "10000330RR0R",
  659. evstwhe_2 = "10000331R4",
  660. evstwhox_3 = "10000334RR0R",
  661. evstwho_2 = "10000335R4",
  662. evstwwex_3 = "10000338RR0R",
  663. evstwwe_2 = "10000339R4",
  664. evstwwox_3 = "1000033cRR0R",
  665. evstwwo_2 = "1000033dR4",
  666. evmhessf_3 = "10000403RRR",
  667. evmhossf_3 = "10000407RRR",
  668. evmheumi_3 = "10000408RRR",
  669. evmhesmi_3 = "10000409RRR",
  670. evmhesmf_3 = "1000040bRRR",
  671. evmhoumi_3 = "1000040cRRR",
  672. evmhosmi_3 = "1000040dRRR",
  673. evmhosmf_3 = "1000040fRRR",
  674. evmhessfa_3 = "10000423RRR",
  675. evmhossfa_3 = "10000427RRR",
  676. evmheumia_3 = "10000428RRR",
  677. evmhesmia_3 = "10000429RRR",
  678. evmhesmfa_3 = "1000042bRRR",
  679. evmhoumia_3 = "1000042cRRR",
  680. evmhosmia_3 = "1000042dRRR",
  681. evmhosmfa_3 = "1000042fRRR",
  682. evmwhssf_3 = "10000447RRR",
  683. evmwlumi_3 = "10000448RRR",
  684. evmwhumi_3 = "1000044cRRR",
  685. evmwhsmi_3 = "1000044dRRR",
  686. evmwhsmf_3 = "1000044fRRR",
  687. evmwssf_3 = "10000453RRR",
  688. evmwumi_3 = "10000458RRR",
  689. evmwsmi_3 = "10000459RRR",
  690. evmwsmf_3 = "1000045bRRR",
  691. evmwhssfa_3 = "10000467RRR",
  692. evmwlumia_3 = "10000468RRR",
  693. evmwhumia_3 = "1000046cRRR",
  694. evmwhsmia_3 = "1000046dRRR",
  695. evmwhsmfa_3 = "1000046fRRR",
  696. evmwssfa_3 = "10000473RRR",
  697. evmwumia_3 = "10000478RRR",
  698. evmwsmia_3 = "10000479RRR",
  699. evmwsmfa_3 = "1000047bRRR",
  700. evmra_2 = "100004c4RR",
  701. evdivws_3 = "100004c6RRR",
  702. evdivwu_3 = "100004c7RRR",
  703. evmwssfaa_3 = "10000553RRR",
  704. evmwumiaa_3 = "10000558RRR",
  705. evmwsmiaa_3 = "10000559RRR",
  706. evmwsmfaa_3 = "1000055bRRR",
  707. evmwssfan_3 = "100005d3RRR",
  708. evmwumian_3 = "100005d8RRR",
  709. evmwsmian_3 = "100005d9RRR",
  710. evmwsmfan_3 = "100005dbRRR",
  711. evmergehilo_3 = "1000022eRRR",
  712. evmergelohi_3 = "1000022fRRR",
  713. evlhhesplatx_3 = "10000308RR0R",
  714. evlhhesplat_2 = "10000309R2",
  715. evlhhousplatx_3 = "1000030cRR0R",
  716. evlhhousplat_2 = "1000030dR2",
  717. evlhhossplatx_3 = "1000030eRR0R",
  718. evlhhossplat_2 = "1000030fR2",
  719. evlwwsplatx_3 = "10000318RR0R",
  720. evlwwsplat_2 = "10000319R4",
  721. evlwhsplatx_3 = "1000031cRR0R",
  722. evlwhsplat_2 = "1000031dR4",
  723. evaddusiaaw_2 = "100004c0RR",
  724. evaddssiaaw_2 = "100004c1RR",
  725. evsubfusiaaw_2 = "100004c2RR",
  726. evsubfssiaaw_2 = "100004c3RR",
  727. evaddumiaaw_2 = "100004c8RR",
  728. evaddsmiaaw_2 = "100004c9RR",
  729. evsubfumiaaw_2 = "100004caRR",
  730. evsubfsmiaaw_2 = "100004cbRR",
  731. evmheusiaaw_3 = "10000500RRR",
  732. evmhessiaaw_3 = "10000501RRR",
  733. evmhessfaaw_3 = "10000503RRR",
  734. evmhousiaaw_3 = "10000504RRR",
  735. evmhossiaaw_3 = "10000505RRR",
  736. evmhossfaaw_3 = "10000507RRR",
  737. evmheumiaaw_3 = "10000508RRR",
  738. evmhesmiaaw_3 = "10000509RRR",
  739. evmhesmfaaw_3 = "1000050bRRR",
  740. evmhoumiaaw_3 = "1000050cRRR",
  741. evmhosmiaaw_3 = "1000050dRRR",
  742. evmhosmfaaw_3 = "1000050fRRR",
  743. evmhegumiaa_3 = "10000528RRR",
  744. evmhegsmiaa_3 = "10000529RRR",
  745. evmhegsmfaa_3 = "1000052bRRR",
  746. evmhogumiaa_3 = "1000052cRRR",
  747. evmhogsmiaa_3 = "1000052dRRR",
  748. evmhogsmfaa_3 = "1000052fRRR",
  749. evmwlusiaaw_3 = "10000540RRR",
  750. evmwlssiaaw_3 = "10000541RRR",
  751. evmwlumiaaw_3 = "10000548RRR",
  752. evmwlsmiaaw_3 = "10000549RRR",
  753. evmheusianw_3 = "10000580RRR",
  754. evmhessianw_3 = "10000581RRR",
  755. evmhessfanw_3 = "10000583RRR",
  756. evmhousianw_3 = "10000584RRR",
  757. evmhossianw_3 = "10000585RRR",
  758. evmhossfanw_3 = "10000587RRR",
  759. evmheumianw_3 = "10000588RRR",
  760. evmhesmianw_3 = "10000589RRR",
  761. evmhesmfanw_3 = "1000058bRRR",
  762. evmhoumianw_3 = "1000058cRRR",
  763. evmhosmianw_3 = "1000058dRRR",
  764. evmhosmfanw_3 = "1000058fRRR",
  765. evmhegumian_3 = "100005a8RRR",
  766. evmhegsmian_3 = "100005a9RRR",
  767. evmhegsmfan_3 = "100005abRRR",
  768. evmhogumian_3 = "100005acRRR",
  769. evmhogsmian_3 = "100005adRRR",
  770. evmhogsmfan_3 = "100005afRRR",
  771. evmwlusianw_3 = "100005c0RRR",
  772. evmwlssianw_3 = "100005c1RRR",
  773. evmwlumianw_3 = "100005c8RRR",
  774. evmwlsmianw_3 = "100005c9RRR",
  775. -- NYI: Book E instructions.
  776. }
  777. -- Add mnemonics for "." variants.
  778. do
  779. local t = {}
  780. for k,v in pairs(map_op) do
  781. if sub(v, -1) == "." then
  782. local v2 = sub(v, 1, 7)..char(byte(v, 8)+1)..sub(v, 9, -2)
  783. t[sub(k, 1, -3).."."..sub(k, -2)] = v2
  784. end
  785. end
  786. for k,v in pairs(t) do
  787. map_op[k] = v
  788. end
  789. end
  790. -- Add more branch mnemonics.
  791. for cond,c in pairs(map_cond) do
  792. local b1 = "b"..cond
  793. local c1 = shl(band(c, 3), 16) + (c < 4 and 0x01000000 or 0)
  794. -- bX[l]
  795. map_op[b1.."_1"] = tohex(0x40800000 + c1).."K"
  796. map_op[b1.."y_1"] = tohex(0x40a00000 + c1).."K"
  797. map_op[b1.."l_1"] = tohex(0x40800001 + c1).."K"
  798. map_op[b1.."_2"] = tohex(0x40800000 + c1).."-XK"
  799. map_op[b1.."y_2"] = tohex(0x40a00000 + c1).."-XK"
  800. map_op[b1.."l_2"] = tohex(0x40800001 + c1).."-XK"
  801. -- bXlr[l]
  802. map_op[b1.."lr_0"] = tohex(0x4c800020 + c1)
  803. map_op[b1.."lrl_0"] = tohex(0x4c800021 + c1)
  804. map_op[b1.."ctr_0"] = tohex(0x4c800420 + c1)
  805. map_op[b1.."ctrl_0"] = tohex(0x4c800421 + c1)
  806. -- bXctr[l]
  807. map_op[b1.."lr_1"] = tohex(0x4c800020 + c1).."-X"
  808. map_op[b1.."lrl_1"] = tohex(0x4c800021 + c1).."-X"
  809. map_op[b1.."ctr_1"] = tohex(0x4c800420 + c1).."-X"
  810. map_op[b1.."ctrl_1"] = tohex(0x4c800421 + c1).."-X"
  811. end
  812. ------------------------------------------------------------------------------
  813. local function parse_gpr(expr)
  814. local tname, ovreg = match(expr, "^([%w_]+):(r[1-3]?[0-9])$")
  815. local tp = map_type[tname or expr]
  816. if tp then
  817. local reg = ovreg or tp.reg
  818. if not reg then
  819. werror("type `"..(tname or expr).."' needs a register override")
  820. end
  821. expr = reg
  822. end
  823. local r = match(expr, "^r([1-3]?[0-9])$")
  824. if r then
  825. r = tonumber(r)
  826. if r <= 31 then return r, tp end
  827. end
  828. werror("bad register name `"..expr.."'")
  829. end
  830. local function parse_fpr(expr)
  831. local r = match(expr, "^f([1-3]?[0-9])$")
  832. if r then
  833. r = tonumber(r)
  834. if r <= 31 then return r end
  835. end
  836. werror("bad register name `"..expr.."'")
  837. end
  838. local function parse_cr(expr)
  839. local r = match(expr, "^cr([0-7])$")
  840. if r then return tonumber(r) end
  841. werror("bad condition register name `"..expr.."'")
  842. end
  843. local function parse_cond(expr)
  844. local r, cond = match(expr, "^4%*cr([0-7])%+(%w%w)$")
  845. if r then
  846. r = tonumber(r)
  847. local c = map_cond[cond]
  848. if c and c < 4 then return r*4+c end
  849. end
  850. werror("bad condition bit name `"..expr.."'")
  851. end
  852. local function parse_imm(imm, bits, shift, scale, signed)
  853. local n = tonumber(imm)
  854. if n then
  855. local m = sar(n, scale)
  856. if shl(m, scale) == n then
  857. if signed then
  858. local s = sar(m, bits-1)
  859. if s == 0 then return shl(m, shift)
  860. elseif s == -1 then return shl(m + shl(1, bits), shift) end
  861. else
  862. if sar(m, bits) == 0 then return shl(m, shift) end
  863. end
  864. end
  865. werror("out of range immediate `"..imm.."'")
  866. elseif match(imm, "^r([1-3]?[0-9])$") or
  867. match(imm, "^([%w_]+):(r[1-3]?[0-9])$") then
  868. werror("expected immediate operand, got register")
  869. else
  870. waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm)
  871. return 0
  872. end
  873. end
  874. local function parse_shiftmask(imm, isshift)
  875. local n = tonumber(imm)
  876. if n then
  877. if shr(n, 6) == 0 then
  878. local lsb = band(imm, 31)
  879. local msb = imm - lsb
  880. return isshift and (shl(lsb, 11)+shr(msb, 4)) or (shl(lsb, 6)+msb)
  881. end
  882. werror("out of range immediate `"..imm.."'")
  883. elseif match(imm, "^r([1-3]?[0-9])$") or
  884. match(imm, "^([%w_]+):(r[1-3]?[0-9])$") then
  885. werror("expected immediate operand, got register")
  886. else
  887. werror("NYI: parameterized 64 bit shift/mask")
  888. end
  889. end
  890. local function parse_disp(disp)
  891. local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$")
  892. if imm then
  893. local r = parse_gpr(reg)
  894. if r == 0 then werror("cannot use r0 in displacement") end
  895. return shl(r, 16) + parse_imm(imm, 16, 0, 0, true)
  896. end
  897. local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
  898. if reg and tailr ~= "" then
  899. local r, tp = parse_gpr(reg)
  900. if r == 0 then werror("cannot use r0 in displacement") end
  901. if tp then
  902. waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr))
  903. return shl(r, 16)
  904. end
  905. end
  906. werror("bad displacement `"..disp.."'")
  907. end
  908. local function parse_u5disp(disp, scale)
  909. local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$")
  910. if imm then
  911. local r = parse_gpr(reg)
  912. if r == 0 then werror("cannot use r0 in displacement") end
  913. return shl(r, 16) + parse_imm(imm, 5, 11, scale, false)
  914. end
  915. local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
  916. if reg and tailr ~= "" then
  917. local r, tp = parse_gpr(reg)
  918. if r == 0 then werror("cannot use r0 in displacement") end
  919. if tp then
  920. waction("IMM", scale*1024+5*32+11, format(tp.ctypefmt, tailr))
  921. return shl(r, 16)
  922. end
  923. end
  924. werror("bad displacement `"..disp.."'")
  925. end
  926. local function parse_label(label, def)
  927. local prefix = sub(label, 1, 2)
  928. -- =>label (pc label reference)
  929. if prefix == "=>" then
  930. return "PC", 0, sub(label, 3)
  931. end
  932. -- ->name (global label reference)
  933. if prefix == "->" then
  934. return "LG", map_global[sub(label, 3)]
  935. end
  936. if def then
  937. -- [1-9] (local label definition)
  938. if match(label, "^[1-9]$") then
  939. return "LG", 10+tonumber(label)
  940. end
  941. else
  942. -- [<>][1-9] (local label reference)
  943. local dir, lnum = match(label, "^([<>])([1-9])$")
  944. if dir then -- Fwd: 1-9, Bkwd: 11-19.
  945. return "LG", lnum + (dir == ">" and 0 or 10)
  946. end
  947. -- extern label (extern label reference)
  948. local extname = match(label, "^extern%s+(%S+)$")
  949. if extname then
  950. return "EXT", map_extern[extname]
  951. end
  952. end
  953. werror("bad label `"..label.."'")
  954. end
  955. ------------------------------------------------------------------------------
  956. -- Handle opcodes defined with template strings.
  957. map_op[".template__"] = function(params, template, nparams)
  958. if not params then return sub(template, 9) end
  959. local op = tonumber(sub(template, 1, 8), 16)
  960. local n, rs = 1, 26
  961. -- Limit number of section buffer positions used by a single dasm_put().
  962. -- A single opcode needs a maximum of 3 positions (rlwinm).
  963. if secpos+3 > maxsecpos then wflush() end
  964. local pos = wpos()
  965. -- Process each character.
  966. for p in gmatch(sub(template, 9), ".") do
  967. if p == "R" then
  968. rs = rs - 5; op = op + shl(parse_gpr(params[n]), rs); n = n + 1
  969. elseif p == "F" then
  970. rs = rs - 5; op = op + shl(parse_fpr(params[n]), rs); n = n + 1
  971. elseif p == "A" then
  972. rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, false); n = n + 1
  973. elseif p == "S" then
  974. rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, true); n = n + 1
  975. elseif p == "I" then
  976. op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1
  977. elseif p == "U" then
  978. op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1
  979. elseif p == "D" then
  980. op = op + parse_disp(params[n]); n = n + 1
  981. elseif p == "2" then
  982. op = op + parse_u5disp(params[n], 1); n = n + 1
  983. elseif p == "4" then
  984. op = op + parse_u5disp(params[n], 2); n = n + 1
  985. elseif p == "8" then
  986. op = op + parse_u5disp(params[n], 3); n = n + 1
  987. elseif p == "C" then
  988. rs = rs - 5; op = op + shl(parse_cond(params[n]), rs); n = n + 1
  989. elseif p == "X" then
  990. rs = rs - 5; op = op + shl(parse_cr(params[n]), rs+2); n = n + 1
  991. elseif p == "W" then
  992. op = op + parse_cr(params[n]); n = n + 1
  993. elseif p == "G" then
  994. op = op + parse_imm(params[n], 8, 12, 0, false); n = n + 1
  995. elseif p == "H" then
  996. op = op + parse_shiftmask(params[n], true); n = n + 1
  997. elseif p == "M" then
  998. op = op + parse_shiftmask(params[n], false); n = n + 1
  999. elseif p == "J" or p == "K" then
  1000. local mode, n, s = parse_label(params[n], false)
  1001. if p == "K" then n = n + 2048 end
  1002. waction("REL_"..mode, n, s, 1)
  1003. n = n + 1
  1004. elseif p == "0" then
  1005. if band(shr(op, rs), 31) == 0 then werror("cannot use r0") end
  1006. elseif p == "=" or p == "%" then
  1007. local t = band(shr(op, p == "%" and rs+5 or rs), 31)
  1008. rs = rs - 5
  1009. op = op + shl(t, rs)
  1010. elseif p == "~" then
  1011. local mm = shl(31, rs)
  1012. local lo = band(op, mm)
  1013. local hi = band(op, shl(mm, 5))
  1014. op = op - lo - hi + shl(lo, 5) + shr(hi, 5)
  1015. elseif p == "-" then
  1016. rs = rs - 5
  1017. elseif p == "." then
  1018. -- Ignored.
  1019. else
  1020. assert(false)
  1021. end
  1022. end
  1023. wputpos(pos, op)
  1024. end
  1025. ------------------------------------------------------------------------------
  1026. -- Pseudo-opcode to mark the position where the action list is to be emitted.
  1027. map_op[".actionlist_1"] = function(params)
  1028. if not params then return "cvar" end
  1029. local name = params[1] -- No syntax check. You get to keep the pieces.
  1030. wline(function(out) writeactions(out, name) end)
  1031. end
  1032. -- Pseudo-opcode to mark the position where the global enum is to be emitted.
  1033. map_op[".globals_1"] = function(params)
  1034. if not params then return "prefix" end
  1035. local prefix = params[1] -- No syntax check. You get to keep the pieces.
  1036. wline(function(out) writeglobals(out, prefix) end)
  1037. end
  1038. -- Pseudo-opcode to mark the position where the global names are to be emitted.
  1039. map_op[".globalnames_1"] = function(params)
  1040. if not params then return "cvar" end
  1041. local name = params[1] -- No syntax check. You get to keep the pieces.
  1042. wline(function(out) writeglobalnames(out, name) end)
  1043. end
  1044. -- Pseudo-opcode to mark the position where the extern names are to be emitted.
  1045. map_op[".externnames_1"] = function(params)
  1046. if not params then return "cvar" end
  1047. local name = params[1] -- No syntax check. You get to keep the pieces.
  1048. wline(function(out) writeexternnames(out, name) end)
  1049. end
  1050. ------------------------------------------------------------------------------
  1051. -- Label pseudo-opcode (converted from trailing colon form).
  1052. map_op[".label_1"] = function(params)
  1053. if not params then return "[1-9] | ->global | =>pcexpr" end
  1054. if secpos+1 > maxsecpos then wflush() end
  1055. local mode, n, s = parse_label(params[1], true)
  1056. if mode == "EXT" then werror("bad label definition") end
  1057. waction("LABEL_"..mode, n, s, 1)
  1058. end
  1059. ------------------------------------------------------------------------------
  1060. -- Pseudo-opcodes for data storage.
  1061. map_op[".long_*"] = function(params)
  1062. if not params then return "imm..." end
  1063. for _,p in ipairs(params) do
  1064. local n = tonumber(p)
  1065. if not n then werror("bad immediate `"..p.."'") end
  1066. if n < 0 then n = n + 2^32 end
  1067. wputw(n)
  1068. if secpos+2 > maxsecpos then wflush() end
  1069. end
  1070. end
  1071. -- Alignment pseudo-opcode.
  1072. map_op[".align_1"] = function(params)
  1073. if not params then return "numpow2" end
  1074. if secpos+1 > maxsecpos then wflush() end
  1075. local align = tonumber(params[1])
  1076. if align then
  1077. local x = align
  1078. -- Must be a power of 2 in the range (2 ... 256).
  1079. for i=1,8 do
  1080. x = x / 2
  1081. if x == 1 then
  1082. waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1.
  1083. return
  1084. end
  1085. end
  1086. end
  1087. werror("bad alignment")
  1088. end
  1089. ------------------------------------------------------------------------------
  1090. -- Pseudo-opcode for (primitive) type definitions (map to C types).
  1091. map_op[".type_3"] = function(params, nparams)
  1092. if not params then
  1093. return nparams == 2 and "name, ctype" or "name, ctype, reg"
  1094. end
  1095. local name, ctype, reg = params[1], params[2], params[3]
  1096. if not match(name, "^[%a_][%w_]*$") then
  1097. werror("bad type name `"..name.."'")
  1098. end
  1099. local tp = map_type[name]
  1100. if tp then
  1101. werror("duplicate type `"..name.."'")
  1102. end
  1103. -- Add #type to defines. A bit unclean to put it in map_archdef.
  1104. map_archdef["#"..name] = "sizeof("..ctype..")"
  1105. -- Add new type and emit shortcut define.
  1106. local num = ctypenum + 1
  1107. map_type[name] = {
  1108. ctype = ctype,
  1109. ctypefmt = format("Dt%X(%%s)", num),
  1110. reg = reg,
  1111. }
  1112. wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
  1113. ctypenum = num
  1114. end
  1115. map_op[".type_2"] = map_op[".type_3"]
  1116. -- Dump type definitions.
  1117. local function dumptypes(out, lvl)
  1118. local t = {}
  1119. for name in pairs(map_type) do t[#t+1] = name end
  1120. sort(t)
  1121. out:write("Type definitions:\n")
  1122. for _,name in ipairs(t) do
  1123. local tp = map_type[name]
  1124. local reg = tp.reg or ""
  1125. out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
  1126. end
  1127. out:write("\n")
  1128. end
  1129. ------------------------------------------------------------------------------
  1130. -- Set the current section.
  1131. function _M.section(num)
  1132. waction("SECTION", num)
  1133. wflush(true) -- SECTION is a terminal action.
  1134. end
  1135. ------------------------------------------------------------------------------
  1136. -- Dump architecture description.
  1137. function _M.dumparch(out)
  1138. out:write(format("DynASM %s version %s, released %s\n\n",
  1139. _info.arch, _info.version, _info.release))
  1140. dumpactions(out)
  1141. end
  1142. -- Dump all user defined elements.
  1143. function _M.dumpdef(out, lvl)
  1144. dumptypes(out, lvl)
  1145. dumpglobals(out, lvl)
  1146. dumpexterns(out, lvl)
  1147. end
  1148. ------------------------------------------------------------------------------
  1149. -- Pass callbacks from/to the DynASM core.
  1150. function _M.passcb(wl, we, wf, ww)
  1151. wline, werror, wfatal, wwarn = wl, we, wf, ww
  1152. return wflush
  1153. end
  1154. -- Setup the arch-specific module.
  1155. function _M.setup(arch, opt)
  1156. g_arch, g_opt = arch, opt
  1157. end
  1158. -- Merge the core maps and the arch-specific maps.
  1159. function _M.mergemaps(map_coreop, map_def)
  1160. setmetatable(map_op, { __index = map_coreop })
  1161. setmetatable(map_def, { __index = map_archdef })
  1162. return map_op, map_def
  1163. end
  1164. return _M
  1165. ------------------------------------------------------------------------------