dasm_arm64.lua 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248
  1. ------------------------------------------------------------------------------
  2. -- DynASM ARM64 module.
  3. --
  4. -- Copyright (C) 2005-2025 Mike Pall. All rights reserved.
  5. -- See dynasm.lua for full copyright notice.
  6. ------------------------------------------------------------------------------
  7. -- Module information:
  8. local _info = {
  9. arch = "arm",
  10. description = "DynASM ARM64 module",
  11. version = "1.5.0",
  12. vernum = 10500,
  13. release = "2021-05-02",
  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, rawget = assert, setmetatable, rawget
  22. local _s = string
  23. local format, byte, char = _s.format, _s.byte, _s.char
  24. local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
  25. local concat, sort, insert = table.concat, table.sort, table.insert
  26. local bit = bit or require("bit")
  27. local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
  28. local ror, tohex, tobit = bit.ror, bit.tohex, bit.tobit
  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", "REL_A",
  38. "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML", "IMMV",
  39. "VREG",
  40. }
  41. -- Maximum number of section buffer positions for dasm_put().
  42. -- CHECK: Keep this in sync with the C code!
  43. local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
  44. -- Action name -> action number.
  45. local map_action = {}
  46. for n,name in ipairs(action_names) do
  47. map_action[name] = n-1
  48. end
  49. -- Action list buffer.
  50. local actlist = {}
  51. -- Argument list for next dasm_put(). Start with offset 0 into action list.
  52. local actargs = { 0 }
  53. -- Current number of section buffer positions for dasm_put().
  54. local secpos = 1
  55. ------------------------------------------------------------------------------
  56. -- Dump action names and numbers.
  57. local function dumpactions(out)
  58. out:write("DynASM encoding engine action codes:\n")
  59. for n,name in ipairs(action_names) do
  60. local num = map_action[name]
  61. out:write(format(" %-10s %02X %d\n", name, num, num))
  62. end
  63. out:write("\n")
  64. end
  65. -- Write action list buffer as a huge static C array.
  66. local function writeactions(out, name)
  67. local nn = #actlist
  68. if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
  69. out:write("static const unsigned int ", name, "[", nn, "] = {\n")
  70. for i = 1,nn-1 do
  71. assert(out:write("0x", tohex(actlist[i]), ",\n"))
  72. end
  73. assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
  74. end
  75. ------------------------------------------------------------------------------
  76. -- Add word to action list.
  77. local function wputxw(n)
  78. assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
  79. actlist[#actlist+1] = n
  80. end
  81. -- Add action to list with optional arg. Advance buffer pos, too.
  82. local function waction(action, val, a, num)
  83. local w = assert(map_action[action], "bad action name `"..action.."'")
  84. wputxw(w * 0x10000 + (val or 0))
  85. if a then actargs[#actargs+1] = a end
  86. if a or num then secpos = secpos + (num or 1) end
  87. end
  88. -- Flush action list (intervening C code or buffer pos overflow).
  89. local function wflush(term)
  90. if #actlist == actargs[1] then return end -- Nothing to flush.
  91. if not term then waction("STOP") end -- Terminate action list.
  92. wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true)
  93. actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
  94. secpos = 1 -- The actionlist offset occupies a buffer position, too.
  95. end
  96. -- Put escaped word.
  97. local function wputw(n)
  98. if n <= 0x000fffff then waction("ESC") end
  99. wputxw(n)
  100. end
  101. -- Reserve position for word.
  102. local function wpos()
  103. local pos = #actlist+1
  104. actlist[pos] = ""
  105. return pos
  106. end
  107. -- Store word to reserved position.
  108. local function wputpos(pos, n)
  109. assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
  110. if n <= 0x000fffff then
  111. insert(actlist, pos+1, n)
  112. n = map_action.ESC * 0x10000
  113. end
  114. actlist[pos] = n
  115. end
  116. ------------------------------------------------------------------------------
  117. -- Global label name -> global label number. With auto assignment on 1st use.
  118. local next_global = 20
  119. local map_global = setmetatable({}, { __index = function(t, name)
  120. if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
  121. local n = next_global
  122. if n > 2047 then werror("too many global labels") end
  123. next_global = n + 1
  124. t[name] = n
  125. return n
  126. end})
  127. -- Dump global labels.
  128. local function dumpglobals(out, lvl)
  129. local t = {}
  130. for name, n in pairs(map_global) do t[n] = name end
  131. out:write("Global labels:\n")
  132. for i=20,next_global-1 do
  133. out:write(format(" %s\n", t[i]))
  134. end
  135. out:write("\n")
  136. end
  137. -- Write global label enum.
  138. local function writeglobals(out, prefix)
  139. local t = {}
  140. for name, n in pairs(map_global) do t[n] = name end
  141. out:write("enum {\n")
  142. for i=20,next_global-1 do
  143. out:write(" ", prefix, t[i], ",\n")
  144. end
  145. out:write(" ", prefix, "_MAX\n};\n")
  146. end
  147. -- Write global label names.
  148. local function writeglobalnames(out, name)
  149. local t = {}
  150. for name, n in pairs(map_global) do t[n] = name end
  151. out:write("static const char *const ", name, "[] = {\n")
  152. for i=20,next_global-1 do
  153. out:write(" \"", t[i], "\",\n")
  154. end
  155. out:write(" (const char *)0\n};\n")
  156. end
  157. ------------------------------------------------------------------------------
  158. -- Extern label name -> extern label number. With auto assignment on 1st use.
  159. local next_extern = 0
  160. local map_extern_ = {}
  161. local map_extern = setmetatable({}, { __index = function(t, name)
  162. -- No restrictions on the name for now.
  163. local n = next_extern
  164. if n > 2047 then werror("too many extern labels") end
  165. next_extern = n + 1
  166. t[name] = n
  167. map_extern_[n] = name
  168. return n
  169. end})
  170. -- Dump extern labels.
  171. local function dumpexterns(out, lvl)
  172. out:write("Extern labels:\n")
  173. for i=0,next_extern-1 do
  174. out:write(format(" %s\n", map_extern_[i]))
  175. end
  176. out:write("\n")
  177. end
  178. -- Write extern label names.
  179. local function writeexternnames(out, name)
  180. out:write("static const char *const ", name, "[] = {\n")
  181. for i=0,next_extern-1 do
  182. out:write(" \"", map_extern_[i], "\",\n")
  183. end
  184. out:write(" (const char *)0\n};\n")
  185. end
  186. ------------------------------------------------------------------------------
  187. -- Arch-specific maps.
  188. -- Ext. register name -> int. name.
  189. local map_archdef = { xzr = "@x31", wzr = "@w31", lr = "x30", }
  190. -- Int. register name -> ext. name.
  191. local map_reg_rev = { ["@x31"] = "xzr", ["@w31"] = "wzr", x30 = "lr", }
  192. local map_type = {} -- Type name -> { ctype, reg }
  193. local ctypenum = 0 -- Type number (for Dt... macros).
  194. -- Reverse defines for registers.
  195. function _M.revdef(s)
  196. return map_reg_rev[s] or s
  197. end
  198. local map_shift = { lsl = 0, lsr = 1, asr = 2, }
  199. local map_extend = {
  200. uxtb = 0, uxth = 1, uxtw = 2, uxtx = 3,
  201. sxtb = 4, sxth = 5, sxtw = 6, sxtx = 7,
  202. }
  203. local map_cond = {
  204. eq = 0, ne = 1, cs = 2, cc = 3, mi = 4, pl = 5, vs = 6, vc = 7,
  205. hi = 8, ls = 9, ge = 10, lt = 11, gt = 12, le = 13, al = 14,
  206. hs = 2, lo = 3,
  207. }
  208. local map_bti = {
  209. c = 0x40, j = 0x80, jc = 0xc0,
  210. }
  211. ------------------------------------------------------------------------------
  212. local parse_reg_type
  213. local function parse_reg(expr, shift, no_vreg)
  214. if not expr then werror("expected register name") end
  215. local tname, ovreg = match(expr, "^([%w_]+):(@?%l%d+)$")
  216. if not tname then
  217. tname, ovreg = match(expr, "^([%w_]+):(R[xwqdshb]%b())$")
  218. end
  219. local tp = map_type[tname or expr]
  220. if tp then
  221. local reg = ovreg or tp.reg
  222. if not reg then
  223. werror("type `"..(tname or expr).."' needs a register override")
  224. end
  225. expr = reg
  226. end
  227. local ok31, rt, r = match(expr, "^(@?)([xwqdshb])([123]?[0-9])$")
  228. if r then
  229. r = tonumber(r)
  230. if r <= 30 or (r == 31 and ok31 ~= "" or (rt ~= "w" and rt ~= "x")) then
  231. if not parse_reg_type then
  232. parse_reg_type = rt
  233. elseif parse_reg_type ~= rt then
  234. werror("register size mismatch")
  235. end
  236. return shl(r, shift), tp
  237. end
  238. end
  239. local vrt, vreg = match(expr, "^R([xwqdshb])(%b())$")
  240. if vreg then
  241. if not parse_reg_type then
  242. parse_reg_type = vrt
  243. elseif parse_reg_type ~= vrt then
  244. werror("register size mismatch")
  245. end
  246. if not no_vreg then waction("VREG", shift, vreg) end
  247. return 0
  248. end
  249. werror("bad register name `"..expr.."'")
  250. end
  251. local function parse_reg_base(expr)
  252. if expr == "sp" then return 0x3e0 end
  253. local base, tp = parse_reg(expr, 5)
  254. if parse_reg_type ~= "x" then werror("bad register type") end
  255. parse_reg_type = false
  256. return base, tp
  257. end
  258. local parse_ctx = {}
  259. local loadenv = setfenv and function(s)
  260. local code = loadstring(s, "")
  261. if code then setfenv(code, parse_ctx) end
  262. return code
  263. end or function(s)
  264. return load(s, "", nil, parse_ctx)
  265. end
  266. -- Try to parse simple arithmetic, too, since some basic ops are aliases.
  267. local function parse_number(n)
  268. local x = tonumber(n)
  269. if x then return x end
  270. local code = loadenv("return "..n)
  271. if code then
  272. local ok, y = pcall(code)
  273. if ok and type(y) == "number" then return y end
  274. end
  275. return nil
  276. end
  277. local function parse_imm(imm, bits, shift, scale, signed)
  278. imm = match(imm, "^#(.*)$")
  279. if not imm then werror("expected immediate operand") end
  280. local n = parse_number(imm)
  281. if n then
  282. local m = sar(n, scale)
  283. if shl(m, scale) == n then
  284. if signed then
  285. local s = sar(m, bits-1)
  286. if s == 0 then return shl(m, shift)
  287. elseif s == -1 then return shl(m + shl(1, bits), shift) end
  288. else
  289. if sar(m, bits) == 0 then return shl(m, shift) end
  290. end
  291. end
  292. werror("out of range immediate `"..imm.."'")
  293. else
  294. waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm)
  295. return 0
  296. end
  297. end
  298. local function parse_imm12(imm)
  299. imm = match(imm, "^#(.*)$")
  300. if not imm then werror("expected immediate operand") end
  301. local n = parse_number(imm)
  302. if n then
  303. if shr(n, 12) == 0 then
  304. return shl(n, 10)
  305. elseif band(n, 0xff000fff) == 0 then
  306. return shr(n, 2) + 0x00400000
  307. end
  308. werror("out of range immediate `"..imm.."'")
  309. else
  310. waction("IMM12", 0, imm)
  311. return 0
  312. end
  313. end
  314. local function parse_imm13(imm)
  315. imm = match(imm, "^#(.*)$")
  316. if not imm then werror("expected immediate operand") end
  317. local n = parse_number(imm)
  318. local r64 = parse_reg_type == "x"
  319. if n and n % 1 == 0 and n >= 0 and n <= 0xffffffff then
  320. local inv = false
  321. if band(n, 1) == 1 then n = bit.bnot(n); inv = true end
  322. local t = {}
  323. for i=1,32 do t[i] = band(n, 1); n = shr(n, 1) end
  324. local b = table.concat(t)
  325. b = b..(r64 and (inv and "1" or "0"):rep(32) or b)
  326. local p0, p1, p0a, p1a = b:match("^(0+)(1+)(0*)(1*)")
  327. if p0 then
  328. local w = p1a == "" and (r64 and 64 or 32) or #p1+#p0a
  329. if band(w, w-1) == 0 and b == b:sub(1, w):rep(64/w) then
  330. local s = band(-2*w, 0x3f) - 1
  331. if w == 64 then s = s + 0x1000 end
  332. if inv then
  333. return shl(w-#p1-#p0, 16) + shl(s+w-#p1, 10)
  334. else
  335. return shl(w-#p0, 16) + shl(s+#p1, 10)
  336. end
  337. end
  338. end
  339. werror("out of range immediate `"..imm.."'")
  340. elseif r64 then
  341. waction("IMM13X", 0, format("(unsigned int)(%s)", imm))
  342. actargs[#actargs+1] = format("(unsigned int)((unsigned long long)(%s)>>32)", imm)
  343. return 0
  344. else
  345. waction("IMM13W", 0, imm)
  346. return 0
  347. end
  348. end
  349. local function parse_imm6(imm)
  350. imm = match(imm, "^#(.*)$")
  351. if not imm then werror("expected immediate operand") end
  352. local n = parse_number(imm)
  353. if n then
  354. if n >= 0 and n <= 63 then
  355. return shl(band(n, 0x1f), 19) + (n >= 32 and 0x80000000 or 0)
  356. end
  357. werror("out of range immediate `"..imm.."'")
  358. else
  359. waction("IMM6", 0, imm)
  360. return 0
  361. end
  362. end
  363. local function parse_imm_load(imm, scale)
  364. local n = parse_number(imm)
  365. if n then
  366. local m = sar(n, scale)
  367. if shl(m, scale) == n and m >= 0 and m < 0x1000 then
  368. return shl(m, 10) + 0x01000000 -- Scaled, unsigned 12 bit offset.
  369. elseif n >= -256 and n < 256 then
  370. return shl(band(n, 511), 12) -- Unscaled, signed 9 bit offset.
  371. end
  372. werror("out of range immediate `"..imm.."'")
  373. else
  374. waction("IMML", scale, imm)
  375. return 0
  376. end
  377. end
  378. local function parse_fpimm(imm)
  379. imm = match(imm, "^#(.*)$")
  380. if not imm then werror("expected immediate operand") end
  381. local n = parse_number(imm)
  382. if n then
  383. local m, e = math.frexp(n)
  384. local s, e2 = 0, band(e-2, 7)
  385. if m < 0 then m = -m; s = 0x00100000 end
  386. m = m*32-16
  387. if m % 1 == 0 and m >= 0 and m <= 15 and sar(shl(e2, 29), 29)+2 == e then
  388. return s + shl(e2, 17) + shl(m, 13)
  389. end
  390. werror("out of range immediate `"..imm.."'")
  391. else
  392. werror("NYI fpimm action")
  393. end
  394. end
  395. local function parse_shift(expr)
  396. local s, s2 = match(expr, "^(%S+)%s*(.*)$")
  397. s = map_shift[s]
  398. if not s then werror("expected shift operand") end
  399. return parse_imm(s2, 6, 10, 0, false) + shl(s, 22)
  400. end
  401. local function parse_lslx16(expr)
  402. local n = match(expr, "^lsl%s*#(%d+)$")
  403. n = tonumber(n)
  404. if not n then werror("expected shift operand") end
  405. if band(n, parse_reg_type == "x" and 0xffffffcf or 0xffffffef) ~= 0 then
  406. werror("bad shift amount")
  407. end
  408. return shl(n, 17)
  409. end
  410. local function parse_extend(expr)
  411. local s, s2 = match(expr, "^(%S+)%s*(.*)$")
  412. if s == "lsl" then
  413. s = parse_reg_type == "x" and 3 or 2
  414. else
  415. s = map_extend[s]
  416. end
  417. if not s then werror("expected extend operand") end
  418. return (s2 == "" and 0 or parse_imm(s2, 3, 10, 0, false)) + shl(s, 13)
  419. end
  420. local function parse_cond(expr, inv)
  421. local c = map_cond[expr]
  422. if not c then werror("expected condition operand") end
  423. return shl(bit.bxor(c, inv), 12)
  424. end
  425. local function parse_map(expr, map)
  426. local x = map[expr]
  427. if not x then werror("bad operand") end
  428. return x
  429. end
  430. local function parse_load(params, nparams, n, op)
  431. if params[n+2] then werror("too many operands") end
  432. local scale = shr(op, 30)
  433. local pn, p2 = params[n], params[n+1]
  434. local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
  435. if not p1 then
  436. if not p2 then
  437. local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$")
  438. if reg and tailr ~= "" then
  439. local base, tp = parse_reg_base(reg)
  440. if tp then
  441. waction("IMML", scale, format(tp.ctypefmt, tailr))
  442. return op + base
  443. end
  444. end
  445. end
  446. werror("expected address operand")
  447. end
  448. if p2 then
  449. if wb == "!" then werror("bad use of '!'") end
  450. op = op + parse_reg_base(p1) + parse_imm(p2, 9, 12, 0, true) + 0x400
  451. elseif wb == "!" then
  452. local p1a, p2a = match(p1, "^([^,%s]*)%s*,%s*(.*)$")
  453. if not p1a then werror("bad use of '!'") end
  454. op = op + parse_reg_base(p1a) + parse_imm(p2a, 9, 12, 0, true) + 0xc00
  455. else
  456. local p1a, p2a = match(p1, "^([^,%s]*)%s*(.*)$")
  457. op = op + parse_reg_base(p1a)
  458. if p2a ~= "" then
  459. local imm = match(p2a, "^,%s*#(.*)$")
  460. if imm then
  461. op = op + parse_imm_load(imm, scale)
  462. else
  463. local p2b, p3b, p3s = match(p2a, "^,%s*([^,%s]*)%s*,?%s*(%S*)%s*(.*)$")
  464. op = op + parse_reg(p2b, 16) + 0x00200800
  465. if parse_reg_type ~= "x" and parse_reg_type ~= "w" then
  466. werror("bad index register type")
  467. end
  468. if p3b == "" then
  469. if parse_reg_type ~= "x" then werror("bad index register type") end
  470. op = op + 0x6000
  471. else
  472. if p3s == "" or p3s == "#0" then
  473. elseif p3s == "#"..scale then
  474. op = op + 0x1000
  475. else
  476. werror("bad scale")
  477. end
  478. if parse_reg_type == "x" then
  479. if p3b == "lsl" and p3s ~= "" then op = op + 0x6000
  480. elseif p3b == "sxtx" then op = op + 0xe000
  481. else
  482. werror("bad extend/shift specifier")
  483. end
  484. else
  485. if p3b == "uxtw" then op = op + 0x4000
  486. elseif p3b == "sxtw" then op = op + 0xc000
  487. else
  488. werror("bad extend/shift specifier")
  489. end
  490. end
  491. end
  492. end
  493. else
  494. if wb == "!" then werror("bad use of '!'") end
  495. op = op + 0x01000000
  496. end
  497. end
  498. return op
  499. end
  500. local function parse_load_pair(params, nparams, n, op)
  501. if params[n+2] then werror("too many operands") end
  502. local pn, p2 = params[n], params[n+1]
  503. local scale = 2 + shr(op, 31 - band(shr(op, 26), 1))
  504. local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
  505. if not p1 then
  506. if not p2 then
  507. local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$")
  508. if reg and tailr ~= "" then
  509. local base, tp = parse_reg_base(reg)
  510. if tp then
  511. waction("IMM", 32768+7*32+15+scale*1024, format(tp.ctypefmt, tailr))
  512. return op + base + 0x01000000
  513. end
  514. end
  515. end
  516. werror("expected address operand")
  517. end
  518. if p2 then
  519. if wb == "!" then werror("bad use of '!'") end
  520. op = op + 0x00800000
  521. else
  522. local p1a, p2a = match(p1, "^([^,%s]*)%s*,%s*(.*)$")
  523. if p1a then p1, p2 = p1a, p2a else p2 = "#0" end
  524. op = op + (wb == "!" and 0x01800000 or 0x01000000)
  525. end
  526. return op + parse_reg_base(p1) + parse_imm(p2, 7, 15, scale, true)
  527. end
  528. local function parse_label(label, def)
  529. local prefix = label:sub(1, 2)
  530. -- =>label (pc label reference)
  531. if prefix == "=>" then
  532. return "PC", 0, label:sub(3)
  533. end
  534. -- ->name (global label reference)
  535. if prefix == "->" then
  536. return "LG", map_global[label:sub(3)]
  537. end
  538. if def then
  539. -- [1-9] (local label definition)
  540. if match(label, "^[1-9]$") then
  541. return "LG", 10+tonumber(label)
  542. end
  543. else
  544. -- [<>][1-9] (local label reference)
  545. local dir, lnum = match(label, "^([<>])([1-9])$")
  546. if dir then -- Fwd: 1-9, Bkwd: 11-19.
  547. return "LG", lnum + (dir == ">" and 0 or 10)
  548. end
  549. -- extern label (extern label reference)
  550. local extname = match(label, "^extern%s+(%S+)$")
  551. if extname then
  552. return "EXT", map_extern[extname]
  553. end
  554. -- &expr (pointer)
  555. if label:sub(1, 1) == "&" then
  556. return "A", 0, format("(ptrdiff_t)(%s)", label:sub(2))
  557. end
  558. end
  559. end
  560. local function branch_type(op)
  561. if band(op, 0x7c000000) == 0x14000000 then return 0 -- B, BL
  562. elseif shr(op, 24) == 0x54 or band(op, 0x7e000000) == 0x34000000 or
  563. band(op, 0x3b000000) == 0x18000000 then
  564. return 0x800 -- B.cond, CBZ, CBNZ, LDR* literal
  565. elseif band(op, 0x7e000000) == 0x36000000 then return 0x1000 -- TBZ, TBNZ
  566. elseif band(op, 0x9f000000) == 0x10000000 then return 0x2000 -- ADR
  567. elseif band(op, 0x9f000000) == band(0x90000000) then return 0x3000 -- ADRP
  568. else
  569. assert(false, "unknown branch type")
  570. end
  571. end
  572. ------------------------------------------------------------------------------
  573. local map_op, op_template
  574. local function op_alias(opname, f)
  575. return function(params, nparams)
  576. if not params then return "-> "..opname:sub(1, -3) end
  577. f(params, nparams)
  578. op_template(params, map_op[opname], nparams)
  579. end
  580. end
  581. local function alias_bfx(p)
  582. p[4] = "#("..p[3]:sub(2)..")+("..p[4]:sub(2)..")-1"
  583. end
  584. local function alias_bfiz(p)
  585. parse_reg(p[1], 0, true)
  586. if parse_reg_type == "w" then
  587. p[3] = "#(32-("..p[3]:sub(2).."))%32"
  588. p[4] = "#("..p[4]:sub(2)..")-1"
  589. else
  590. p[3] = "#(64-("..p[3]:sub(2).."))%64"
  591. p[4] = "#("..p[4]:sub(2)..")-1"
  592. end
  593. end
  594. local alias_lslimm = op_alias("ubfm_4", function(p)
  595. parse_reg(p[1], 0, true)
  596. local sh = p[3]:sub(2)
  597. if parse_reg_type == "w" then
  598. p[3] = "#(32-("..sh.."))%32"
  599. p[4] = "#31-("..sh..")"
  600. else
  601. p[3] = "#(64-("..sh.."))%64"
  602. p[4] = "#63-("..sh..")"
  603. end
  604. end)
  605. -- Template strings for ARM instructions.
  606. map_op = {
  607. -- Basic data processing instructions.
  608. add_3 = "0b000000DNMg|11000000pDpNIg|8b206000pDpNMx",
  609. add_4 = "0b000000DNMSg|0b200000DNMXg|8b200000pDpNMXx|8b200000pDpNxMwX",
  610. adds_3 = "2b000000DNMg|31000000DpNIg|ab206000DpNMx",
  611. adds_4 = "2b000000DNMSg|2b200000DNMXg|ab200000DpNMXx|ab200000DpNxMwX",
  612. cmn_2 = "2b00001fNMg|3100001fpNIg|ab20601fpNMx",
  613. cmn_3 = "2b00001fNMSg|2b20001fNMXg|ab20001fpNMXx|ab20001fpNxMwX",
  614. sub_3 = "4b000000DNMg|51000000pDpNIg|cb206000pDpNMx",
  615. sub_4 = "4b000000DNMSg|4b200000DNMXg|cb200000pDpNMXx|cb200000pDpNxMwX",
  616. subs_3 = "6b000000DNMg|71000000DpNIg|eb206000DpNMx",
  617. subs_4 = "6b000000DNMSg|6b200000DNMXg|eb200000DpNMXx|eb200000DpNxMwX",
  618. cmp_2 = "6b00001fNMg|7100001fpNIg|eb20601fpNMx",
  619. cmp_3 = "6b00001fNMSg|6b20001fNMXg|eb20001fpNMXx|eb20001fpNxMwX",
  620. neg_2 = "4b0003e0DMg",
  621. neg_3 = "4b0003e0DMSg",
  622. negs_2 = "6b0003e0DMg",
  623. negs_3 = "6b0003e0DMSg",
  624. adc_3 = "1a000000DNMg",
  625. adcs_3 = "3a000000DNMg",
  626. sbc_3 = "5a000000DNMg",
  627. sbcs_3 = "7a000000DNMg",
  628. ngc_2 = "5a0003e0DMg",
  629. ngcs_2 = "7a0003e0DMg",
  630. and_3 = "0a000000DNMg|12000000pDNig",
  631. and_4 = "0a000000DNMSg",
  632. orr_3 = "2a000000DNMg|32000000pDNig",
  633. orr_4 = "2a000000DNMSg",
  634. eor_3 = "4a000000DNMg|52000000pDNig",
  635. eor_4 = "4a000000DNMSg",
  636. ands_3 = "6a000000DNMg|72000000DNig",
  637. ands_4 = "6a000000DNMSg",
  638. tst_2 = "6a00001fNMg|7200001fNig",
  639. tst_3 = "6a00001fNMSg",
  640. bic_3 = "0a200000DNMg",
  641. bic_4 = "0a200000DNMSg",
  642. orn_3 = "2a200000DNMg",
  643. orn_4 = "2a200000DNMSg",
  644. eon_3 = "4a200000DNMg",
  645. eon_4 = "4a200000DNMSg",
  646. bics_3 = "6a200000DNMg",
  647. bics_4 = "6a200000DNMSg",
  648. movn_2 = "12800000DWg",
  649. movn_3 = "12800000DWRg",
  650. movz_2 = "52800000DWg",
  651. movz_3 = "52800000DWRg",
  652. movk_2 = "72800000DWg",
  653. movk_3 = "72800000DWRg",
  654. -- TODO: this doesn't cover all valid immediates for mov reg, #imm.
  655. mov_2 = "2a0003e0DMg|52800000DW|320003e0pDig|11000000pDpNg",
  656. mov_3 = "2a0003e0DMSg",
  657. mvn_2 = "2a2003e0DMg",
  658. mvn_3 = "2a2003e0DMSg",
  659. adr_2 = "10000000DBx",
  660. adrp_2 = "90000000DBx",
  661. csel_4 = "1a800000DNMCg",
  662. csinc_4 = "1a800400DNMCg",
  663. csinv_4 = "5a800000DNMCg",
  664. csneg_4 = "5a800400DNMCg",
  665. cset_2 = "1a9f07e0Dcg",
  666. csetm_2 = "5a9f03e0Dcg",
  667. cinc_3 = "1a800400DNmcg",
  668. cinv_3 = "5a800000DNmcg",
  669. cneg_3 = "5a800400DNmcg",
  670. ccmn_4 = "3a400000NMVCg|3a400800N5VCg",
  671. ccmp_4 = "7a400000NMVCg|7a400800N5VCg",
  672. madd_4 = "1b000000DNMAg",
  673. msub_4 = "1b008000DNMAg",
  674. mul_3 = "1b007c00DNMg",
  675. mneg_3 = "1b00fc00DNMg",
  676. smaddl_4 = "9b200000DxNMwAx",
  677. smsubl_4 = "9b208000DxNMwAx",
  678. smull_3 = "9b207c00DxNMw",
  679. smnegl_3 = "9b20fc00DxNMw",
  680. smulh_3 = "9b407c00DNMx",
  681. umaddl_4 = "9ba00000DxNMwAx",
  682. umsubl_4 = "9ba08000DxNMwAx",
  683. umull_3 = "9ba07c00DxNMw",
  684. umnegl_3 = "9ba0fc00DxNMw",
  685. umulh_3 = "9bc07c00DNMx",
  686. udiv_3 = "1ac00800DNMg",
  687. sdiv_3 = "1ac00c00DNMg",
  688. -- Bit operations.
  689. sbfm_4 = "13000000DN12w|93400000DN12x",
  690. bfm_4 = "33000000DN12w|b3400000DN12x",
  691. ubfm_4 = "53000000DN12w|d3400000DN12x",
  692. extr_4 = "13800000DNM2w|93c00000DNM2x",
  693. sxtb_2 = "13001c00DNw|93401c00DNx",
  694. sxth_2 = "13003c00DNw|93403c00DNx",
  695. sxtw_2 = "93407c00DxNw",
  696. uxtb_2 = "53001c00DNw",
  697. uxth_2 = "53003c00DNw",
  698. sbfx_4 = op_alias("sbfm_4", alias_bfx),
  699. bfxil_4 = op_alias("bfm_4", alias_bfx),
  700. ubfx_4 = op_alias("ubfm_4", alias_bfx),
  701. sbfiz_4 = op_alias("sbfm_4", alias_bfiz),
  702. bfi_4 = op_alias("bfm_4", alias_bfiz),
  703. ubfiz_4 = op_alias("ubfm_4", alias_bfiz),
  704. lsl_3 = function(params, nparams)
  705. if params and params[3]:byte() == 35 then
  706. return alias_lslimm(params, nparams)
  707. else
  708. return op_template(params, "1ac02000DNMg", nparams)
  709. end
  710. end,
  711. lsr_3 = "1ac02400DNMg|53007c00DN1w|d340fc00DN1x",
  712. asr_3 = "1ac02800DNMg|13007c00DN1w|9340fc00DN1x",
  713. ror_3 = "1ac02c00DNMg|13800000DNm2w|93c00000DNm2x",
  714. clz_2 = "5ac01000DNg",
  715. cls_2 = "5ac01400DNg",
  716. rbit_2 = "5ac00000DNg",
  717. rev_2 = "5ac00800DNw|dac00c00DNx",
  718. rev16_2 = "5ac00400DNg",
  719. rev32_2 = "dac00800DNx",
  720. -- Loads and stores.
  721. ["strb_*"] = "38000000DwL",
  722. ["ldrb_*"] = "38400000DwL",
  723. ["ldrsb_*"] = "38c00000DwL|38800000DxL",
  724. ["strh_*"] = "78000000DwL",
  725. ["ldrh_*"] = "78400000DwL",
  726. ["ldrsh_*"] = "78c00000DwL|78800000DxL",
  727. ["str_*"] = "b8000000DwL|f8000000DxL|bc000000DsL|fc000000DdL",
  728. ["ldr_*"] = "18000000DwB|58000000DxB|1c000000DsB|5c000000DdB|b8400000DwL|f8400000DxL|bc400000DsL|fc400000DdL",
  729. ["ldrsw_*"] = "98000000DxB|b8800000DxL",
  730. -- NOTE: ldur etc. are handled by ldr et al.
  731. ["stp_*"] = "28000000DAwP|a8000000DAxP|2c000000DAsP|6c000000DAdP|ac000000DAqP",
  732. ["ldp_*"] = "28400000DAwP|a8400000DAxP|2c400000DAsP|6c400000DAdP|ac400000DAqP",
  733. ["ldpsw_*"] = "68400000DAxP",
  734. -- Branches.
  735. b_1 = "14000000B",
  736. bl_1 = "94000000B",
  737. blr_1 = "d63f0000Nx",
  738. br_1 = "d61f0000Nx",
  739. ret_0 = "d65f03c0",
  740. ret_1 = "d65f0000Nx",
  741. -- b.cond is added below.
  742. cbz_2 = "34000000DBg",
  743. cbnz_2 = "35000000DBg",
  744. tbz_3 = "36000000DTBw|36000000DTBx",
  745. tbnz_3 = "37000000DTBw|37000000DTBx",
  746. -- Branch Target Identification.
  747. bti_1 = "d503241ft",
  748. -- ARM64e: Pointer authentication codes (PAC).
  749. blraaz_1 = "d63f081fNx",
  750. blrabz_1 = "d63f0c1fNx",
  751. braa_2 = "d71f0800NDx",
  752. brab_2 = "d71f0c00NDx",
  753. braaz_1 = "d61f081fNx",
  754. brabz_1 = "d61f0c1fNx",
  755. paciasp_0 = "d503233f",
  756. pacibsp_0 = "d503237f",
  757. autiasp_0 = "d50323bf",
  758. autibsp_0 = "d50323ff",
  759. retaa_0 = "d65f0bff",
  760. retab_0 = "d65f0fff",
  761. -- Miscellaneous instructions.
  762. -- TODO: hlt, hvc, smc, svc, eret, dcps[123], drps, mrs, msr
  763. -- TODO: sys, sysl, ic, dc, at, tlbi
  764. -- TODO: hint, yield, wfe, wfi, sev, sevl
  765. -- TODO: clrex, dsb, dmb, isb
  766. nop_0 = "d503201f",
  767. brk_0 = "d4200000",
  768. brk_1 = "d4200000W",
  769. -- Floating point instructions.
  770. fmov_2 = "1e204000DNf|1e260000DwNs|1e270000DsNw|9e660000DxNd|9e670000DdNx|1e201000DFf",
  771. fabs_2 = "1e20c000DNf",
  772. fneg_2 = "1e214000DNf",
  773. fsqrt_2 = "1e21c000DNf",
  774. fcvt_2 = "1e22c000DdNs|1e624000DsNd",
  775. -- TODO: half-precision and fixed-point conversions.
  776. fcvtas_2 = "1e240000DwNs|9e240000DxNs|1e640000DwNd|9e640000DxNd",
  777. fcvtau_2 = "1e250000DwNs|9e250000DxNs|1e650000DwNd|9e650000DxNd",
  778. fcvtms_2 = "1e300000DwNs|9e300000DxNs|1e700000DwNd|9e700000DxNd",
  779. fcvtmu_2 = "1e310000DwNs|9e310000DxNs|1e710000DwNd|9e710000DxNd",
  780. fcvtns_2 = "1e200000DwNs|9e200000DxNs|1e600000DwNd|9e600000DxNd",
  781. fcvtnu_2 = "1e210000DwNs|9e210000DxNs|1e610000DwNd|9e610000DxNd",
  782. fcvtps_2 = "1e280000DwNs|9e280000DxNs|1e680000DwNd|9e680000DxNd",
  783. fcvtpu_2 = "1e290000DwNs|9e290000DxNs|1e690000DwNd|9e690000DxNd",
  784. fcvtzs_2 = "1e380000DwNs|9e380000DxNs|1e780000DwNd|9e780000DxNd",
  785. fcvtzu_2 = "1e390000DwNs|9e390000DxNs|1e790000DwNd|9e790000DxNd",
  786. scvtf_2 = "1e220000DsNw|9e220000DsNx|1e620000DdNw|9e620000DdNx",
  787. ucvtf_2 = "1e230000DsNw|9e230000DsNx|1e630000DdNw|9e630000DdNx",
  788. frintn_2 = "1e244000DNf",
  789. frintp_2 = "1e24c000DNf",
  790. frintm_2 = "1e254000DNf",
  791. frintz_2 = "1e25c000DNf",
  792. frinta_2 = "1e264000DNf",
  793. frintx_2 = "1e274000DNf",
  794. frinti_2 = "1e27c000DNf",
  795. fadd_3 = "1e202800DNMf",
  796. fsub_3 = "1e203800DNMf",
  797. fmul_3 = "1e200800DNMf",
  798. fnmul_3 = "1e208800DNMf",
  799. fdiv_3 = "1e201800DNMf",
  800. fmadd_4 = "1f000000DNMAf",
  801. fmsub_4 = "1f008000DNMAf",
  802. fnmadd_4 = "1f200000DNMAf",
  803. fnmsub_4 = "1f208000DNMAf",
  804. fmax_3 = "1e204800DNMf",
  805. fmaxnm_3 = "1e206800DNMf",
  806. fmin_3 = "1e205800DNMf",
  807. fminnm_3 = "1e207800DNMf",
  808. fcmp_2 = "1e202000NMf|1e202008NZf",
  809. fcmpe_2 = "1e202010NMf|1e202018NZf",
  810. fccmp_4 = "1e200400NMVCf",
  811. fccmpe_4 = "1e200410NMVCf",
  812. fcsel_4 = "1e200c00DNMCf",
  813. -- TODO: crc32*, aes*, sha*, pmull
  814. -- TODO: SIMD instructions.
  815. }
  816. for cond,c in pairs(map_cond) do
  817. map_op["b"..cond.."_1"] = tohex(0x54000000+c).."B"
  818. end
  819. ------------------------------------------------------------------------------
  820. -- Handle opcodes defined with template strings.
  821. local function parse_template(params, template, nparams, pos)
  822. local op = tonumber(template:sub(1, 8), 16)
  823. local n = 1
  824. local rtt = {}
  825. parse_reg_type = false
  826. -- Process each character.
  827. for p in gmatch(template:sub(9), ".") do
  828. local q = params[n]
  829. if p == "D" then
  830. op = op + parse_reg(q, 0); n = n + 1
  831. elseif p == "N" then
  832. op = op + parse_reg(q, 5); n = n + 1
  833. elseif p == "M" then
  834. op = op + parse_reg(q, 16); n = n + 1
  835. elseif p == "A" then
  836. op = op + parse_reg(q, 10); n = n + 1
  837. elseif p == "m" then
  838. op = op + parse_reg(params[n-1], 16)
  839. elseif p == "p" then
  840. if q == "sp" then params[n] = "@x31" end
  841. elseif p == "g" then
  842. if parse_reg_type == "x" then
  843. op = op + 0x80000000
  844. elseif parse_reg_type ~= "w" then
  845. werror("bad register type")
  846. end
  847. parse_reg_type = false
  848. elseif p == "f" then
  849. if parse_reg_type == "d" then
  850. op = op + 0x00400000
  851. elseif parse_reg_type ~= "s" then
  852. werror("bad register type")
  853. end
  854. parse_reg_type = false
  855. elseif p == "x" or p == "w" or p == "d" or p == "s" or p == "q" then
  856. if parse_reg_type ~= p then
  857. werror("register size mismatch")
  858. end
  859. parse_reg_type = false
  860. elseif p == "L" then
  861. op = parse_load(params, nparams, n, op)
  862. elseif p == "P" then
  863. op = parse_load_pair(params, nparams, n, op)
  864. elseif p == "B" then
  865. local mode, v, s = parse_label(q, false); n = n + 1
  866. if not mode then werror("bad label `"..q.."'") end
  867. local m = branch_type(op)
  868. if mode == "A" then
  869. waction("REL_"..mode, v+m, format("(unsigned int)(%s)", s))
  870. actargs[#actargs+1] = format("(unsigned int)((%s)>>32)", s)
  871. else
  872. waction("REL_"..mode, v+m, s, 1)
  873. end
  874. elseif p == "I" then
  875. op = op + parse_imm12(q); n = n + 1
  876. elseif p == "i" then
  877. op = op + parse_imm13(q); n = n + 1
  878. elseif p == "W" then
  879. op = op + parse_imm(q, 16, 5, 0, false); n = n + 1
  880. elseif p == "T" then
  881. op = op + parse_imm6(q); n = n + 1
  882. elseif p == "1" then
  883. op = op + parse_imm(q, 6, 16, 0, false); n = n + 1
  884. elseif p == "2" then
  885. op = op + parse_imm(q, 6, 10, 0, false); n = n + 1
  886. elseif p == "5" then
  887. op = op + parse_imm(q, 5, 16, 0, false); n = n + 1
  888. elseif p == "V" then
  889. op = op + parse_imm(q, 4, 0, 0, false); n = n + 1
  890. elseif p == "F" then
  891. op = op + parse_fpimm(q); n = n + 1
  892. elseif p == "Z" then
  893. if q ~= "#0" and q ~= "#0.0" then werror("expected zero immediate") end
  894. n = n + 1
  895. elseif p == "S" then
  896. op = op + parse_shift(q); n = n + 1
  897. elseif p == "X" then
  898. op = op + parse_extend(q); n = n + 1
  899. elseif p == "R" then
  900. op = op + parse_lslx16(q); n = n + 1
  901. elseif p == "C" then
  902. op = op + parse_cond(q, 0); n = n + 1
  903. elseif p == "c" then
  904. op = op + parse_cond(q, 1); n = n + 1
  905. elseif p == "t" then
  906. op = op + parse_map(q, map_bti); n = n + 1
  907. else
  908. assert(false)
  909. end
  910. end
  911. wputpos(pos, op)
  912. end
  913. function op_template(params, template, nparams)
  914. if not params then return template:gsub("%x%x%x%x%x%x%x%x", "") end
  915. -- Limit number of section buffer positions used by a single dasm_put().
  916. -- A single opcode needs a maximum of 4 positions.
  917. if secpos+4 > maxsecpos then wflush() end
  918. local pos = wpos()
  919. local lpos, apos, spos = #actlist, #actargs, secpos
  920. local ok, err
  921. for t in gmatch(template, "[^|]+") do
  922. ok, err = pcall(parse_template, params, t, nparams, pos)
  923. if ok then return end
  924. secpos = spos
  925. actlist[lpos+1] = nil
  926. actlist[lpos+2] = nil
  927. actlist[lpos+3] = nil
  928. actlist[lpos+4] = nil
  929. actargs[apos+1] = nil
  930. actargs[apos+2] = nil
  931. actargs[apos+3] = nil
  932. actargs[apos+4] = nil
  933. end
  934. error(err, 0)
  935. end
  936. map_op[".template__"] = op_template
  937. ------------------------------------------------------------------------------
  938. -- Pseudo-opcode to mark the position where the action list is to be emitted.
  939. map_op[".actionlist_1"] = function(params)
  940. if not params then return "cvar" end
  941. local name = params[1] -- No syntax check. You get to keep the pieces.
  942. wline(function(out) writeactions(out, name) end)
  943. end
  944. -- Pseudo-opcode to mark the position where the global enum is to be emitted.
  945. map_op[".globals_1"] = function(params)
  946. if not params then return "prefix" end
  947. local prefix = params[1] -- No syntax check. You get to keep the pieces.
  948. wline(function(out) writeglobals(out, prefix) end)
  949. end
  950. -- Pseudo-opcode to mark the position where the global names are to be emitted.
  951. map_op[".globalnames_1"] = function(params)
  952. if not params then return "cvar" end
  953. local name = params[1] -- No syntax check. You get to keep the pieces.
  954. wline(function(out) writeglobalnames(out, name) end)
  955. end
  956. -- Pseudo-opcode to mark the position where the extern names are to be emitted.
  957. map_op[".externnames_1"] = function(params)
  958. if not params then return "cvar" end
  959. local name = params[1] -- No syntax check. You get to keep the pieces.
  960. wline(function(out) writeexternnames(out, name) end)
  961. end
  962. ------------------------------------------------------------------------------
  963. -- Label pseudo-opcode (converted from trailing colon form).
  964. map_op[".label_1"] = function(params)
  965. if not params then return "[1-9] | ->global | =>pcexpr" end
  966. if secpos+1 > maxsecpos then wflush() end
  967. local mode, n, s = parse_label(params[1], true)
  968. if not mode or mode == "EXT" then werror("bad label definition") end
  969. waction("LABEL_"..mode, n, s, 1)
  970. end
  971. ------------------------------------------------------------------------------
  972. -- Pseudo-opcodes for data storage.
  973. local function op_data(params)
  974. if not params then return "imm..." end
  975. local sz = params.op == ".long" and 4 or 8
  976. for _,p in ipairs(params) do
  977. local imm = parse_number(p)
  978. if imm then
  979. local n = tobit(imm)
  980. if n == imm or (n < 0 and n + 2^32 == imm) then
  981. wputw(n < 0 and n + 2^32 or n)
  982. if sz == 8 then
  983. wputw(imm < 0 and 0xffffffff or 0)
  984. end
  985. elseif sz == 4 then
  986. werror("bad immediate `"..p.."'")
  987. else
  988. imm = nil
  989. end
  990. end
  991. if not imm then
  992. local mode, v, s = parse_label(p, false)
  993. if sz == 4 then
  994. if mode then werror("label does not fit into .long") end
  995. waction("IMMV", 0, p)
  996. elseif mode and mode ~= "A" then
  997. waction("REL_"..mode, v+0x8000, s, 1)
  998. else
  999. if mode == "A" then p = s end
  1000. waction("IMMV", 0, format("(unsigned int)(%s)", p))
  1001. waction("IMMV", 0, format("(unsigned int)((unsigned long long)(%s)>>32)", p))
  1002. end
  1003. end
  1004. if secpos+2 > maxsecpos then wflush() end
  1005. end
  1006. end
  1007. map_op[".long_*"] = op_data
  1008. map_op[".quad_*"] = op_data
  1009. map_op[".addr_*"] = op_data
  1010. -- Alignment pseudo-opcode.
  1011. map_op[".align_1"] = function(params)
  1012. if not params then return "numpow2" end
  1013. if secpos+1 > maxsecpos then wflush() end
  1014. local align = tonumber(params[1])
  1015. if align then
  1016. local x = align
  1017. -- Must be a power of 2 in the range (2 ... 256).
  1018. for i=1,8 do
  1019. x = x / 2
  1020. if x == 1 then
  1021. waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1.
  1022. return
  1023. end
  1024. end
  1025. end
  1026. werror("bad alignment")
  1027. end
  1028. ------------------------------------------------------------------------------
  1029. -- Pseudo-opcode for (primitive) type definitions (map to C types).
  1030. map_op[".type_3"] = function(params, nparams)
  1031. if not params then
  1032. return nparams == 2 and "name, ctype" or "name, ctype, reg"
  1033. end
  1034. local name, ctype, reg = params[1], params[2], params[3]
  1035. if not match(name, "^[%a_][%w_]*$") then
  1036. werror("bad type name `"..name.."'")
  1037. end
  1038. local tp = map_type[name]
  1039. if tp then
  1040. werror("duplicate type `"..name.."'")
  1041. end
  1042. -- Add #type to defines. A bit unclean to put it in map_archdef.
  1043. map_archdef["#"..name] = "sizeof("..ctype..")"
  1044. -- Add new type and emit shortcut define.
  1045. local num = ctypenum + 1
  1046. map_type[name] = {
  1047. ctype = ctype,
  1048. ctypefmt = format("Dt%X(%%s)", num),
  1049. reg = reg,
  1050. }
  1051. wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
  1052. ctypenum = num
  1053. end
  1054. map_op[".type_2"] = map_op[".type_3"]
  1055. -- Dump type definitions.
  1056. local function dumptypes(out, lvl)
  1057. local t = {}
  1058. for name in pairs(map_type) do t[#t+1] = name end
  1059. sort(t)
  1060. out:write("Type definitions:\n")
  1061. for _,name in ipairs(t) do
  1062. local tp = map_type[name]
  1063. local reg = tp.reg or ""
  1064. out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
  1065. end
  1066. out:write("\n")
  1067. end
  1068. ------------------------------------------------------------------------------
  1069. -- Set the current section.
  1070. function _M.section(num)
  1071. waction("SECTION", num)
  1072. wflush(true) -- SECTION is a terminal action.
  1073. end
  1074. ------------------------------------------------------------------------------
  1075. -- Dump architecture description.
  1076. function _M.dumparch(out)
  1077. out:write(format("DynASM %s version %s, released %s\n\n",
  1078. _info.arch, _info.version, _info.release))
  1079. dumpactions(out)
  1080. end
  1081. -- Dump all user defined elements.
  1082. function _M.dumpdef(out, lvl)
  1083. dumptypes(out, lvl)
  1084. dumpglobals(out, lvl)
  1085. dumpexterns(out, lvl)
  1086. end
  1087. ------------------------------------------------------------------------------
  1088. -- Pass callbacks from/to the DynASM core.
  1089. function _M.passcb(wl, we, wf, ww)
  1090. wline, werror, wfatal, wwarn = wl, we, wf, ww
  1091. return wflush
  1092. end
  1093. -- Setup the arch-specific module.
  1094. function _M.setup(arch, opt)
  1095. g_arch, g_opt = arch, opt
  1096. end
  1097. -- Merge the core maps and the arch-specific maps.
  1098. function _M.mergemaps(map_coreop, map_def)
  1099. setmetatable(map_op, { __index = map_coreop })
  1100. setmetatable(map_def, { __index = map_archdef })
  1101. return map_op, map_def
  1102. end
  1103. return _M
  1104. ------------------------------------------------------------------------------