dasm_ppc.lua 36 KB

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