Add missing mcode limit check in assembler backend.
[luajit-2.0.git] / dynasm / dasm_arm.lua
blobcc4fa17749c28520799889c3afa5ec0c533284f7
1 ------------------------------------------------------------------------------
2 -- DynASM ARM module.
3 --
4 -- Copyright (C) 2005-2012 Mike Pall. All rights reserved.
5 -- See dynasm.lua for full copyright notice.
6 ------------------------------------------------------------------------------
8 -- Module information:
9 local _info = {
10 arch = "arm",
11 description = "DynASM ARM module",
12 version = "1.3.0",
13 vernum = 10300,
14 release = "2011-05-05",
15 author = "Mike Pall",
16 license = "MIT",
19 -- Exported glue functions for the arch-specific module.
20 local _M = { _info = _info }
22 -- Cache library functions.
23 local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
24 local assert, setmetatable, rawget = assert, setmetatable, rawget
25 local _s = string
26 local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
27 local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
28 local concat, sort, insert = table.concat, table.sort, table.insert
30 -- Inherited tables and callbacks.
31 local g_opt, g_arch
32 local wline, werror, wfatal, wwarn
34 -- Action name list.
35 -- CHECK: Keep this in sync with the C code!
36 local action_names = {
37 "STOP", "SECTION", "ESC", "REL_EXT",
38 "ALIGN", "REL_LG", "LABEL_LG",
39 "REL_PC", "LABEL_PC", "IMM", "IMM12", "IMM16", "IMML8", "IMML12",
42 -- Maximum number of section buffer positions for dasm_put().
43 -- CHECK: Keep this in sync with the C code!
44 local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
46 -- Action name -> action number.
47 local map_action = {}
48 for n,name in ipairs(action_names) do
49 map_action[name] = n-1
50 end
52 -- Action list buffer.
53 local actlist = {}
55 -- Argument list for next dasm_put(). Start with offset 0 into action list.
56 local actargs = { 0 }
58 -- Current number of section buffer positions for dasm_put().
59 local secpos = 1
61 ------------------------------------------------------------------------------
63 -- Return 8 digit hex number.
64 local function tohex(x)
65 return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua.
66 end
68 -- Dump action names and numbers.
69 local function dumpactions(out)
70 out:write("DynASM encoding engine action codes:\n")
71 for n,name in ipairs(action_names) do
72 local num = map_action[name]
73 out:write(format(" %-10s %02X %d\n", name, num, num))
74 end
75 out:write("\n")
76 end
78 -- Write action list buffer as a huge static C array.
79 local function writeactions(out, name)
80 local nn = #actlist
81 if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
82 out:write("static const unsigned int ", name, "[", nn, "] = {\n")
83 for i = 1,nn-1 do
84 assert(out:write("0x", tohex(actlist[i]), ",\n"))
85 end
86 assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
87 end
89 ------------------------------------------------------------------------------
91 -- Add word to action list.
92 local function wputxw(n)
93 assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
94 actlist[#actlist+1] = n
95 end
97 -- Add action to list with optional arg. Advance buffer pos, too.
98 local function waction(action, val, a, num)
99 local w = assert(map_action[action], "bad action name `"..action.."'")
100 wputxw(w * 0x10000 + (val or 0))
101 if a then actargs[#actargs+1] = a end
102 if a or num then secpos = secpos + (num or 1) end
105 -- Flush action list (intervening C code or buffer pos overflow).
106 local function wflush(term)
107 if #actlist == actargs[1] then return end -- Nothing to flush.
108 if not term then waction("STOP") end -- Terminate action list.
109 wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true)
110 actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
111 secpos = 1 -- The actionlist offset occupies a buffer position, too.
114 -- Put escaped word.
115 local function wputw(n)
116 if n <= 0x000fffff then waction("ESC") end
117 wputxw(n)
120 -- Reserve position for word.
121 local function wpos()
122 local pos = #actlist+1
123 actlist[pos] = ""
124 return pos
127 -- Store word to reserved position.
128 local function wputpos(pos, n)
129 assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
130 if n <= 0x000fffff then
131 insert(actlist, pos+1, n)
132 n = map_action.ESC * 0x10000
134 actlist[pos] = n
137 ------------------------------------------------------------------------------
139 -- Global label name -> global label number. With auto assignment on 1st use.
140 local next_global = 20
141 local map_global = setmetatable({}, { __index = function(t, name)
142 if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
143 local n = next_global
144 if n > 2047 then werror("too many global labels") end
145 next_global = n + 1
146 t[name] = n
147 return n
148 end})
150 -- Dump global labels.
151 local function dumpglobals(out, lvl)
152 local t = {}
153 for name, n in pairs(map_global) do t[n] = name end
154 out:write("Global labels:\n")
155 for i=20,next_global-1 do
156 out:write(format(" %s\n", t[i]))
158 out:write("\n")
161 -- Write global label enum.
162 local function writeglobals(out, prefix)
163 local t = {}
164 for name, n in pairs(map_global) do t[n] = name end
165 out:write("enum {\n")
166 for i=20,next_global-1 do
167 out:write(" ", prefix, t[i], ",\n")
169 out:write(" ", prefix, "_MAX\n};\n")
172 -- Write global label names.
173 local function writeglobalnames(out, name)
174 local t = {}
175 for name, n in pairs(map_global) do t[n] = name end
176 out:write("static const char *const ", name, "[] = {\n")
177 for i=20,next_global-1 do
178 out:write(" \"", t[i], "\",\n")
180 out:write(" (const char *)0\n};\n")
183 ------------------------------------------------------------------------------
185 -- Extern label name -> extern label number. With auto assignment on 1st use.
186 local next_extern = 0
187 local map_extern_ = {}
188 local map_extern = setmetatable({}, { __index = function(t, name)
189 -- No restrictions on the name for now.
190 local n = next_extern
191 if n > 2047 then werror("too many extern labels") end
192 next_extern = n + 1
193 t[name] = n
194 map_extern_[n] = name
195 return n
196 end})
198 -- Dump extern labels.
199 local function dumpexterns(out, lvl)
200 out:write("Extern labels:\n")
201 for i=0,next_extern-1 do
202 out:write(format(" %s\n", map_extern_[i]))
204 out:write("\n")
207 -- Write extern label names.
208 local function writeexternnames(out, name)
209 out:write("static const char *const ", name, "[] = {\n")
210 for i=0,next_extern-1 do
211 out:write(" \"", map_extern_[i], "\",\n")
213 out:write(" (const char *)0\n};\n")
216 ------------------------------------------------------------------------------
218 -- Arch-specific maps.
220 -- Ext. register name -> int. name.
221 local map_archdef = { sp = "r13", lr = "r14", pc = "r15", }
223 -- Int. register name -> ext. name.
224 local map_reg_rev = { r13 = "sp", r14 = "lr", r15 = "pc", }
226 local map_type = {} -- Type name -> { ctype, reg }
227 local ctypenum = 0 -- Type number (for Dt... macros).
229 -- Reverse defines for registers.
230 function _M.revdef(s)
231 return map_reg_rev[s] or s
234 local map_shift = { lsl = 0, lsr = 1, asr = 2, ror = 3, }
236 local map_cond = {
237 eq = 0, ne = 1, cs = 2, cc = 3, mi = 4, pl = 5, vs = 6, vc = 7,
238 hi = 8, ls = 9, ge = 10, lt = 11, gt = 12, le = 13, al = 14,
239 hs = 2, lo = 3,
242 ------------------------------------------------------------------------------
244 -- Template strings for ARM instructions.
245 local map_op = {
246 -- Basic data processing instructions.
247 and_3 = "e0000000DNPs",
248 eor_3 = "e0200000DNPs",
249 sub_3 = "e0400000DNPs",
250 rsb_3 = "e0600000DNPs",
251 add_3 = "e0800000DNPs",
252 adc_3 = "e0a00000DNPs",
253 sbc_3 = "e0c00000DNPs",
254 rsc_3 = "e0e00000DNPs",
255 tst_2 = "e1100000NP",
256 teq_2 = "e1300000NP",
257 cmp_2 = "e1500000NP",
258 cmn_2 = "e1700000NP",
259 orr_3 = "e1800000DNPs",
260 mov_2 = "e1a00000DPs",
261 bic_3 = "e1c00000DNPs",
262 mvn_2 = "e1e00000DPs",
264 and_4 = "e0000000DNMps",
265 eor_4 = "e0200000DNMps",
266 sub_4 = "e0400000DNMps",
267 rsb_4 = "e0600000DNMps",
268 add_4 = "e0800000DNMps",
269 adc_4 = "e0a00000DNMps",
270 sbc_4 = "e0c00000DNMps",
271 rsc_4 = "e0e00000DNMps",
272 tst_3 = "e1100000NMp",
273 teq_3 = "e1300000NMp",
274 cmp_3 = "e1500000NMp",
275 cmn_3 = "e1700000NMp",
276 orr_4 = "e1800000DNMps",
277 mov_3 = "e1a00000DMps",
278 bic_4 = "e1c00000DNMps",
279 mvn_3 = "e1e00000DMps",
281 lsl_3 = "e1a00000DMws",
282 lsr_3 = "e1a00020DMws",
283 asr_3 = "e1a00040DMws",
284 ror_3 = "e1a00060DMws",
285 rrx_2 = "e1a00060DMs",
287 -- Multiply and multiply-accumulate.
288 mul_3 = "e0000090NMSs",
289 mla_4 = "e0200090NMSDs",
290 umaal_4 = "e0400090DNMSs", -- v6
291 mls_4 = "e0600090DNMSs", -- v6T2
292 umull_4 = "e0800090DNMSs",
293 umlal_4 = "e0a00090DNMSs",
294 smull_4 = "e0c00090DNMSs",
295 smlal_4 = "e0e00090DNMSs",
297 -- Halfword multiply and multiply-accumulate.
298 smlabb_4 = "e1000080NMSD", -- v5TE
299 smlatb_4 = "e10000a0NMSD", -- v5TE
300 smlabt_4 = "e10000c0NMSD", -- v5TE
301 smlatt_4 = "e10000e0NMSD", -- v5TE
302 smlawb_4 = "e1200080NMSD", -- v5TE
303 smulwb_3 = "e12000a0NMS", -- v5TE
304 smlawt_4 = "e12000c0NMSD", -- v5TE
305 smulwt_3 = "e12000e0NMS", -- v5TE
306 smlalbb_4 = "e1400080NMSD", -- v5TE
307 smlaltb_4 = "e14000a0NMSD", -- v5TE
308 smlalbt_4 = "e14000c0NMSD", -- v5TE
309 smlaltt_4 = "e14000e0NMSD", -- v5TE
310 smulbb_3 = "e1600080NMS", -- v5TE
311 smultb_3 = "e16000a0NMS", -- v5TE
312 smulbt_3 = "e16000c0NMS", -- v5TE
313 smultt_3 = "e16000e0NMS", -- v5TE
315 -- Miscellaneous data processing instructions.
316 clz_2 = "e16f0f10DM", -- v5T
317 rev_2 = "e6bf0f30DM", -- v6
318 rev16_2 = "e6bf0fb0DM", -- v6
319 revsh_2 = "e6ff0fb0DM", -- v6
320 sel_3 = "e6800fb0DNM", -- v6
321 usad8_3 = "e780f010NMS", -- v6
322 usada8_4 = "e7800010NMSD", -- v6
323 rbit_2 = "e6ff0f30DM", -- v6T2
324 movw_2 = "e3000000DW", -- v6T2
325 movt_2 = "e3400000DW", -- v6T2
326 -- Note: the X encodes width-1, not width.
327 sbfx_4 = "e7a00050DMvX", -- v6T2
328 ubfx_4 = "e7e00050DMvX", -- v6T2
329 -- Note: the X encodes the msb field, not the width.
330 bfc_3 = "e7c0001fDvX", -- v6T2
331 bfi_4 = "e7c00010DMvX", -- v6T2
333 -- Packing and unpacking instructions.
334 pkhbt_3 = "e6800010DNM", pkhbt_4 = "e6800010DNMv", -- v6
335 pkhtb_3 = "e6800050DNM", pkhtb_4 = "e6800050DNMv", -- v6
336 sxtab_3 = "e6a00070DNM", sxtab_4 = "e6a00070DNMv", -- v6
337 sxtab16_3 = "e6800070DNM", sxtab16_4 = "e6800070DNMv", -- v6
338 sxtah_3 = "e6b00070DNM", sxtah_4 = "e6b00070DNMv", -- v6
339 sxtb_2 = "e6af0070DM", sxtb_3 = "e6af0070DMv", -- v6
340 sxtb16_2 = "e68f0070DM", sxtb16_3 = "e68f0070DMv", -- v6
341 sxth_2 = "e6bf0070DM", sxth_3 = "e6bf0070DMv", -- v6
342 uxtab_3 = "e6e00070DNM", uxtab_4 = "e6e00070DNMv", -- v6
343 uxtab16_3 = "e6c00070DNM", uxtab16_4 = "e6c00070DNMv", -- v6
344 uxtah_3 = "e6f00070DNM", uxtah_4 = "e6f00070DNMv", -- v6
345 uxtb_2 = "e6ef0070DM", uxtb_3 = "e6ef0070DMv", -- v6
346 uxtb16_2 = "e6cf0070DM", uxtb16_3 = "e6cf0070DMv", -- v6
347 uxth_2 = "e6ff0070DM", uxth_3 = "e6ff0070DMv", -- v6
349 -- Saturating instructions.
350 qadd_3 = "e1000050DMN", -- v5TE
351 qsub_3 = "e1200050DMN", -- v5TE
352 qdadd_3 = "e1400050DMN", -- v5TE
353 qdsub_3 = "e1600050DMN", -- v5TE
354 -- Note: the X for ssat* encodes sat_imm-1, not sat_imm.
355 ssat_3 = "e6a00010DXM", ssat_4 = "e6a00010DXMp", -- v6
356 usat_3 = "e6e00010DXM", usat_4 = "e6e00010DXMp", -- v6
357 ssat16_3 = "e6a00f30DXM", -- v6
358 usat16_3 = "e6e00f30DXM", -- v6
360 -- Parallel addition and subtraction.
361 sadd16_3 = "e6100f10DNM", -- v6
362 sasx_3 = "e6100f30DNM", -- v6
363 ssax_3 = "e6100f50DNM", -- v6
364 ssub16_3 = "e6100f70DNM", -- v6
365 sadd8_3 = "e6100f90DNM", -- v6
366 ssub8_3 = "e6100ff0DNM", -- v6
367 qadd16_3 = "e6200f10DNM", -- v6
368 qasx_3 = "e6200f30DNM", -- v6
369 qsax_3 = "e6200f50DNM", -- v6
370 qsub16_3 = "e6200f70DNM", -- v6
371 qadd8_3 = "e6200f90DNM", -- v6
372 qsub8_3 = "e6200ff0DNM", -- v6
373 shadd16_3 = "e6300f10DNM", -- v6
374 shasx_3 = "e6300f30DNM", -- v6
375 shsax_3 = "e6300f50DNM", -- v6
376 shsub16_3 = "e6300f70DNM", -- v6
377 shadd8_3 = "e6300f90DNM", -- v6
378 shsub8_3 = "e6300ff0DNM", -- v6
379 uadd16_3 = "e6500f10DNM", -- v6
380 uasx_3 = "e6500f30DNM", -- v6
381 usax_3 = "e6500f50DNM", -- v6
382 usub16_3 = "e6500f70DNM", -- v6
383 uadd8_3 = "e6500f90DNM", -- v6
384 usub8_3 = "e6500ff0DNM", -- v6
385 uqadd16_3 = "e6600f10DNM", -- v6
386 uqasx_3 = "e6600f30DNM", -- v6
387 uqsax_3 = "e6600f50DNM", -- v6
388 uqsub16_3 = "e6600f70DNM", -- v6
389 uqadd8_3 = "e6600f90DNM", -- v6
390 uqsub8_3 = "e6600ff0DNM", -- v6
391 uhadd16_3 = "e6700f10DNM", -- v6
392 uhasx_3 = "e6700f30DNM", -- v6
393 uhsax_3 = "e6700f50DNM", -- v6
394 uhsub16_3 = "e6700f70DNM", -- v6
395 uhadd8_3 = "e6700f90DNM", -- v6
396 uhsub8_3 = "e6700ff0DNM", -- v6
398 -- Load/store instructions.
399 str_2 = "e4000000DL", str_3 = "e4000000DL", str_4 = "e4000000DL",
400 strb_2 = "e4400000DL", strb_3 = "e4400000DL", strb_4 = "e4400000DL",
401 ldr_2 = "e4100000DL", ldr_3 = "e4100000DL", ldr_4 = "e4100000DL",
402 ldrb_2 = "e4500000DL", ldrb_3 = "e4500000DL", ldrb_4 = "e4500000DL",
403 strh_2 = "e00000b0DL", strh_3 = "e00000b0DL",
404 ldrh_2 = "e01000b0DL", ldrh_3 = "e01000b0DL",
405 ldrd_2 = "e00000d0DL", ldrd_3 = "e00000d0DL", -- v5TE
406 ldrsb_2 = "e01000d0DL", ldrsb_3 = "e01000d0DL",
407 strd_2 = "e00000f0DL", strd_3 = "e00000f0DL", -- v5TE
408 ldrsh_2 = "e01000f0DL", ldrsh_3 = "e01000f0DL",
410 ldm_2 = "e8900000nR", ldmia_2 = "e8900000nR", ldmfd_2 = "e8900000nR",
411 ldmda_2 = "e8100000nR", ldmfa_2 = "e8100000nR",
412 ldmdb_2 = "e9100000nR", ldmea_2 = "e9100000nR",
413 ldmib_2 = "e9900000nR", ldmed_2 = "e9900000nR",
414 stm_2 = "e8800000nR", stmia_2 = "e8800000nR", stmfd_2 = "e8800000nR",
415 stmda_2 = "e8000000nR", stmfa_2 = "e8000000nR",
416 stmdb_2 = "e9000000nR", stmea_2 = "e9000000nR",
417 stmib_2 = "e9800000nR", stmed_2 = "e9800000nR",
418 pop_1 = "e8bd0000R", push_1 = "e92d0000R",
420 -- Branch instructions.
421 b_1 = "ea000000B",
422 bl_1 = "eb000000B",
423 blx_1 = "e12fff30C",
424 bx_1 = "e12fff10M",
426 -- Miscellaneous instructions.
427 nop_0 = "e1a00000",
428 mrs_1 = "e10f0000D",
429 bkpt_1 = "e1200070K", -- v5T
430 svc_1 = "ef000000T", swi_1 = "ef000000T",
431 ud_0 = "e7f001f0",
433 -- NYI: Advanced SIMD and VFP instructions.
435 -- NYI instructions, since I have no need for them right now:
436 -- swp, swpb, strex, ldrex, strexd, ldrexd, strexb, ldrexb, strexh, ldrexh
437 -- msr, nopv6, yield, wfe, wfi, sev, dbg, bxj, smc, srs, rfe
438 -- cps, setend, pli, pld, pldw, clrex, dsb, dmb, isb
439 -- stc, ldc, mcr, mcr2, mrc, mrc2, mcrr, mcrr2, mrrc, mrrc2, cdp, cdp2
442 -- Add mnemonics for "s" variants.
444 local t = {}
445 for k,v in pairs(map_op) do
446 if sub(v, -1) == "s" then
447 local v2 = sub(v, 1, 2)..char(byte(v, 3)+1)..sub(v, 4, -2)
448 t[sub(k, 1, -3).."s"..sub(k, -2)] = v2
451 for k,v in pairs(t) do
452 map_op[k] = v
456 ------------------------------------------------------------------------------
458 local function parse_gpr(expr)
459 local tname, ovreg = match(expr, "^([%w_]+):(r1?[0-9])$")
460 local tp = map_type[tname or expr]
461 if tp then
462 local reg = ovreg or tp.reg
463 if not reg then
464 werror("type `"..(tname or expr).."' needs a register override")
466 expr = reg
468 local r = match(expr, "^r(1?[0-9])$")
469 if r then
470 r = tonumber(r)
471 if r <= 15 then return r, tp end
473 werror("bad register name `"..expr.."'")
476 local function parse_gpr_pm(expr)
477 local pm, expr2 = match(expr, "^([+-]?)(.*)$")
478 return parse_gpr(expr2), (pm == "-")
481 local function parse_reglist(reglist)
482 reglist = match(reglist, "^{%s*([^}]*)}$")
483 if not reglist then werror("register list expected") end
484 local rr = 0
485 for p in gmatch(reglist..",", "%s*([^,]*),") do
486 local rbit = 2^parse_gpr(gsub(p, "%s+$", ""))
487 if ((rr - (rr % rbit)) / rbit) % 2 ~= 0 then
488 werror("duplicate register `"..p.."'")
490 rr = rr + rbit
492 return rr
495 local function parse_imm(imm, bits, shift, scale, signed)
496 imm = match(imm, "^#(.*)$")
497 if not imm then werror("expected immediate operand") end
498 local n = tonumber(imm)
499 if n then
500 if n % 2^scale == 0 then
501 n = n / 2^scale
502 if signed then
503 if n >= 0 then
504 if n < 2^(bits-1) then return n*2^shift end
505 else
506 if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end
508 else
509 if n >= 0 and n <= 2^bits-1 then return n*2^shift end
512 werror("out of range immediate `"..imm.."'")
513 else
514 waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm)
515 return 0
519 local function parse_imm12(imm)
520 local n = tonumber(imm)
521 if n then
522 local m = n
523 for i=0,-15,-1 do
524 if m >= 0 and m <= 255 and n % 1 == 0 then return m + (i%16) * 256 end
525 local t = m % 4
526 m = (m - t) / 4 + t * 2^30
528 werror("out of range immediate `"..imm.."'")
529 else
530 waction("IMM12", 0, imm)
531 return 0
535 local function parse_imm16(imm)
536 imm = match(imm, "^#(.*)$")
537 if not imm then werror("expected immediate operand") end
538 local n = tonumber(imm)
539 if n then
540 if n >= 0 and n <= 65535 and n % 1 == 0 then
541 local t = n % 4096
542 return (n - t) * 16 + t
544 werror("out of range immediate `"..imm.."'")
545 else
546 waction("IMM16", 32*16, imm)
547 return 0
551 local function parse_imm_load(imm, ext)
552 local n = tonumber(imm)
553 if n then
554 if ext then
555 if n >= -255 and n <= 255 then
556 local up = 0x00800000
557 if n < 0 then n = -n; up = 0 end
558 return (n-(n%16))*16+(n%16) + up
560 else
561 if n >= -4095 and n <= 4095 then
562 if n >= 0 then return n+0x00800000 end
563 return -n
566 werror("out of range immediate `"..imm.."'")
567 else
568 waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12), imm)
569 return 0
573 local function parse_shift(shift, gprok)
574 if shift == "rrx" then
575 return 3 * 32
576 else
577 local s, s2 = match(shift, "^(%S+)%s*(.*)$")
578 s = map_shift[s]
579 if not s then werror("expected shift operand") end
580 if sub(s2, 1, 1) == "#" then
581 return parse_imm(s2, 5, 7, 0, false) + s * 32
582 else
583 if not gprok then werror("expected immediate shift operand") end
584 return parse_gpr(s2) * 256 + s * 32 + 16
589 local function parse_label(label, def)
590 local prefix = sub(label, 1, 2)
591 -- =>label (pc label reference)
592 if prefix == "=>" then
593 return "PC", 0, sub(label, 3)
595 -- ->name (global label reference)
596 if prefix == "->" then
597 return "LG", map_global[sub(label, 3)]
599 if def then
600 -- [1-9] (local label definition)
601 if match(label, "^[1-9]$") then
602 return "LG", 10+tonumber(label)
604 else
605 -- [<>][1-9] (local label reference)
606 local dir, lnum = match(label, "^([<>])([1-9])$")
607 if dir then -- Fwd: 1-9, Bkwd: 11-19.
608 return "LG", lnum + (dir == ">" and 0 or 10)
610 -- extern label (extern label reference)
611 local extname = match(label, "^extern%s+(%S+)$")
612 if extname then
613 return "EXT", map_extern[extname]
616 werror("bad label `"..label.."'")
619 local function parse_load(params, nparams, n, op)
620 local oplo = op % 256
621 local ext, ldrd = (oplo ~= 0), (oplo == 208)
622 local d
623 if (ldrd or oplo == 240) then
624 d = ((op - (op % 4096)) / 4096) % 16
625 if d % 2 ~= 0 then werror("odd destination register") end
627 local pn = params[n]
628 local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
629 local p2 = params[n+1]
630 if not p1 then
631 if not p2 then
632 if match(pn, "^[<>=%-]") or match(pn, "^extern%s+") then
633 local mode, n, s = parse_label(pn, false)
634 waction("REL_"..mode, n + (ext and 0x1800 or 0x0800), s, 1)
635 return op + 15 * 65536 + 0x01000000 + (ext and 0x00400000 or 0)
637 local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$")
638 if reg and tailr ~= "" then
639 local d, tp = parse_gpr(reg)
640 if tp then
641 waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12),
642 format(tp.ctypefmt, tailr))
643 return op + d * 65536 + 0x01000000 + (ext and 0x00400000 or 0)
647 werror("expected address operand")
649 if wb == "!" then op = op + 0x00200000 end
650 if p2 then
651 if wb == "!" then werror("bad use of '!'") end
652 local p3 = params[n+2]
653 op = op + parse_gpr(p1) * 65536
654 local imm = match(p2, "^#(.*)$")
655 if imm then
656 local m = parse_imm_load(imm, ext)
657 if p3 then werror("too many parameters") end
658 op = op + m + (ext and 0x00400000 or 0)
659 else
660 local m, neg = parse_gpr_pm(p2)
661 if ldrd and (m == d or m-1 == d) then werror("register conflict") end
662 op = op + m + (neg and 0 or 0x00800000) + (ext and 0 or 0x02000000)
663 if p3 then op = op + parse_shift(p3) end
665 else
666 local p1a, p2 = match(p1, "^([^,%s]*)%s*(.*)$")
667 op = op + parse_gpr(p1a) * 65536 + 0x01000000
668 if p2 ~= "" then
669 local imm = match(p2, "^,%s*#(.*)$")
670 if imm then
671 local m = parse_imm_load(imm, ext)
672 op = op + m + (ext and 0x00400000 or 0)
673 else
674 local p2a, p3 = match(p2, "^,%s*([^,%s]*)%s*,?%s*(.*)$")
675 local m, neg = parse_gpr_pm(p2a)
676 if ldrd and (m == d or m-1 == d) then werror("register conflict") end
677 op = op + m + (neg and 0 or 0x00800000) + (ext and 0 or 0x02000000)
678 if p3 ~= "" then
679 if ext then werror("too many parameters") end
680 op = op + parse_shift(p3)
683 else
684 if wb == "!" then werror("bad use of '!'") end
685 op = op + (ext and 0x00c00000 or 0x00800000)
688 return op
691 ------------------------------------------------------------------------------
693 -- Handle opcodes defined with template strings.
694 map_op[".template__"] = function(params, template, nparams)
695 if not params then return sub(template, 9) end
696 local op = tonumber(sub(template, 1, 8), 16)
697 local n = 1
699 -- Limit number of section buffer positions used by a single dasm_put().
700 -- A single opcode needs a maximum of 3 positions.
701 if secpos+3 > maxsecpos then wflush() end
702 local pos = wpos()
704 -- Process each character.
705 for p in gmatch(sub(template, 9), ".") do
706 if p == "D" then
707 op = op + parse_gpr(params[n]) * 4096; n = n + 1
708 elseif p == "N" then
709 op = op + parse_gpr(params[n]) * 65536; n = n + 1
710 elseif p == "S" then
711 op = op + parse_gpr(params[n]) * 256; n = n + 1
712 elseif p == "M" then
713 op = op + parse_gpr(params[n]); n = n + 1
714 elseif p == "P" then
715 local imm = match(params[n], "^#(.*)$")
716 if imm then
717 op = op + parse_imm12(imm) + 0x02000000
718 else
719 op = op + parse_gpr(params[n])
721 n = n + 1
722 elseif p == "p" then
723 op = op + parse_shift(params[n], true); n = n + 1
724 elseif p == "L" then
725 op = parse_load(params, nparams, n, op)
726 elseif p == "B" then
727 local mode, n, s = parse_label(params[n], false)
728 waction("REL_"..mode, n, s, 1)
729 elseif p == "C" then -- blx gpr vs. blx label.
730 local p = params[n]
731 if match(p, "^([%w_]+):(r1?[0-9])$") or match(p, "^r(1?[0-9])$") then
732 op = op + parse_gpr(p)
733 else
734 if op < 0xe0000000 then werror("unconditional instruction") end
735 local mode, n, s = parse_label(p, false)
736 waction("REL_"..mode, n, s, 1)
737 op = 0xfa000000
739 elseif p == "n" then
740 local r, wb = match(params[n], "^([^!]*)(!?)$")
741 op = op + parse_gpr(r) * 65536 + (wb == "!" and 0x00200000 or 0)
742 n = n + 1
743 elseif p == "R" then
744 op = op + parse_reglist(params[n]); n = n + 1
745 elseif p == "W" then
746 op = op + parse_imm16(params[n]); n = n + 1
747 elseif p == "v" then
748 op = op + parse_imm(params[n], 5, 7, 0, false); n = n + 1
749 elseif p == "w" then
750 local imm = match(params[n], "^#(.*)$")
751 if imm then
752 op = op + parse_imm(params[n], 5, 7, 0, false); n = n + 1
753 else
754 op = op + parse_gpr(params[n]) * 256 + 16
756 elseif p == "X" then
757 op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1
758 elseif p == "K" then
759 local imm = tonumber(match(params[n], "^#(.*)$")); n = n + 1
760 if not imm or imm % 1 ~= 0 or imm < 0 or imm > 0xffff then
761 werror("bad immediate operand")
763 local t = imm % 16
764 op = op + (imm - t) * 16 + t
765 elseif p == "T" then
766 op = op + parse_imm(params[n], 24, 0, 0, false); n = n + 1
767 elseif p == "s" then
768 -- Ignored.
769 else
770 assert(false)
773 wputpos(pos, op)
776 ------------------------------------------------------------------------------
778 -- Pseudo-opcode to mark the position where the action list is to be emitted.
779 map_op[".actionlist_1"] = function(params)
780 if not params then return "cvar" end
781 local name = params[1] -- No syntax check. You get to keep the pieces.
782 wline(function(out) writeactions(out, name) end)
785 -- Pseudo-opcode to mark the position where the global enum is to be emitted.
786 map_op[".globals_1"] = function(params)
787 if not params then return "prefix" end
788 local prefix = params[1] -- No syntax check. You get to keep the pieces.
789 wline(function(out) writeglobals(out, prefix) end)
792 -- Pseudo-opcode to mark the position where the global names are to be emitted.
793 map_op[".globalnames_1"] = function(params)
794 if not params then return "cvar" end
795 local name = params[1] -- No syntax check. You get to keep the pieces.
796 wline(function(out) writeglobalnames(out, name) end)
799 -- Pseudo-opcode to mark the position where the extern names are to be emitted.
800 map_op[".externnames_1"] = function(params)
801 if not params then return "cvar" end
802 local name = params[1] -- No syntax check. You get to keep the pieces.
803 wline(function(out) writeexternnames(out, name) end)
806 ------------------------------------------------------------------------------
808 -- Label pseudo-opcode (converted from trailing colon form).
809 map_op[".label_1"] = function(params)
810 if not params then return "[1-9] | ->global | =>pcexpr" end
811 if secpos+1 > maxsecpos then wflush() end
812 local mode, n, s = parse_label(params[1], true)
813 if mode == "EXT" then werror("bad label definition") end
814 waction("LABEL_"..mode, n, s, 1)
817 ------------------------------------------------------------------------------
819 -- Pseudo-opcodes for data storage.
820 map_op[".long_*"] = function(params)
821 if not params then return "imm..." end
822 for _,p in ipairs(params) do
823 local n = tonumber(p)
824 if not n then werror("bad immediate `"..p.."'") end
825 if n < 0 then n = n + 2^32 end
826 wputw(n)
827 if secpos+2 > maxsecpos then wflush() end
831 -- Alignment pseudo-opcode.
832 map_op[".align_1"] = function(params)
833 if not params then return "numpow2" end
834 if secpos+1 > maxsecpos then wflush() end
835 local align = tonumber(params[1])
836 if align then
837 local x = align
838 -- Must be a power of 2 in the range (2 ... 256).
839 for i=1,8 do
840 x = x / 2
841 if x == 1 then
842 waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1.
843 return
847 werror("bad alignment")
850 ------------------------------------------------------------------------------
852 -- Pseudo-opcode for (primitive) type definitions (map to C types).
853 map_op[".type_3"] = function(params, nparams)
854 if not params then
855 return nparams == 2 and "name, ctype" or "name, ctype, reg"
857 local name, ctype, reg = params[1], params[2], params[3]
858 if not match(name, "^[%a_][%w_]*$") then
859 werror("bad type name `"..name.."'")
861 local tp = map_type[name]
862 if tp then
863 werror("duplicate type `"..name.."'")
865 -- Add #type to defines. A bit unclean to put it in map_archdef.
866 map_archdef["#"..name] = "sizeof("..ctype..")"
867 -- Add new type and emit shortcut define.
868 local num = ctypenum + 1
869 map_type[name] = {
870 ctype = ctype,
871 ctypefmt = format("Dt%X(%%s)", num),
872 reg = reg,
874 wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
875 ctypenum = num
877 map_op[".type_2"] = map_op[".type_3"]
879 -- Dump type definitions.
880 local function dumptypes(out, lvl)
881 local t = {}
882 for name in pairs(map_type) do t[#t+1] = name end
883 sort(t)
884 out:write("Type definitions:\n")
885 for _,name in ipairs(t) do
886 local tp = map_type[name]
887 local reg = tp.reg or ""
888 out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
890 out:write("\n")
893 ------------------------------------------------------------------------------
895 -- Set the current section.
896 function _M.section(num)
897 waction("SECTION", num)
898 wflush(true) -- SECTION is a terminal action.
901 ------------------------------------------------------------------------------
903 -- Dump architecture description.
904 function _M.dumparch(out)
905 out:write(format("DynASM %s version %s, released %s\n\n",
906 _info.arch, _info.version, _info.release))
907 dumpactions(out)
910 -- Dump all user defined elements.
911 function _M.dumpdef(out, lvl)
912 dumptypes(out, lvl)
913 dumpglobals(out, lvl)
914 dumpexterns(out, lvl)
917 ------------------------------------------------------------------------------
919 -- Pass callbacks from/to the DynASM core.
920 function _M.passcb(wl, we, wf, ww)
921 wline, werror, wfatal, wwarn = wl, we, wf, ww
922 return wflush
925 -- Setup the arch-specific module.
926 function _M.setup(arch, opt)
927 g_arch, g_opt = arch, opt
930 -- Merge the core maps and the arch-specific maps.
931 function _M.mergemaps(map_coreop, map_def)
932 setmetatable(map_op, { __index = function(t, k)
933 local v = map_coreop[k]
934 if v then return v end
935 local cc = sub(k, -4, -3)
936 local cv = map_cond[cc]
937 if cv then
938 local v = rawget(t, sub(k, 1, -5)..sub(k, -2))
939 if type(v) == "string" then return format("%x%s", cv, sub(v, 2)) end
941 end })
942 setmetatable(map_def, { __index = map_archdef })
943 return map_op, map_def
946 return _M
948 ------------------------------------------------------------------------------