1 ------------------------------------------------------------------------------
4 -- Copyright (C) 2005-2012 Mike Pall. All rights reserved.
5 -- See dynasm.lua for full copyright notice.
6 ------------------------------------------------------------------------------
11 description
= "DynASM ARM module",
14 release
= "2011-05-05",
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
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.
32 local wline
, werror
, wfatal
, wwarn
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.
48 for n
,name
in ipairs(action_names
) do
49 map_action
[name
] = n
-1
52 -- Action list buffer.
55 -- Argument list for next dasm_put(). Start with offset 0 into action list.
58 -- Current number of section buffer positions for dasm_put().
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.
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
))
78 -- Write action list buffer as a huge static C array.
79 local function writeactions(out
, name
)
81 if nn
== 0 then nn
= 1; actlist
[0] = map_action
.STOP
end
82 out
:write("static const unsigned int ", name
, "[", nn
, "] = {\n")
84 assert(out
:write("0x", tohex(actlist
[i
]), ",\n"))
86 assert(out
:write("0x", tohex(actlist
[nn
]), "\n};\n\n"))
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
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.
115 local function wputw(n
)
116 if n
<= 0x000fffff then waction("ESC") end
120 -- Reserve position for word.
121 local function wpos()
122 local pos
= #actlist
+1
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
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
150 -- Dump global labels.
151 local function dumpglobals(out
, lvl
)
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
]))
161 -- Write global label enum.
162 local function writeglobals(out
, prefix
)
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
)
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
194 map_extern_
[n
] = name
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
]))
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, }
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,
242 ------------------------------------------------------------------------------
244 -- Template strings for ARM instructions.
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.
426 -- Miscellaneous instructions.
429 bkpt_1
= "e1200070K", -- v5T
430 svc_1
= "ef000000T", swi_1
= "ef000000T",
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.
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
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
]
462 local reg
= ovreg
or tp
.reg
464 werror("type `"..(tname
or expr
).."' needs a register override")
468 local r
= match(expr
, "^r(1?[0-9])$")
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
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
.."'")
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
)
500 if n
% 2^scale
== 0 then
504 if n
< 2^
(bits
-1) then return n
*2^shift
end
506 if n
>= -(2^
(bits
-1))-1 then return (n
+2^bits
)*2^shift
end
509 if n
>= 0 and n
<= 2^bits
-1 then return n
*2^shift
end
512 werror("out of range immediate `"..imm
.."'")
514 waction("IMM", (signed
and 32768 or 0)+scale
*1024+bits
*32+shift
, imm
)
519 local function parse_imm12(imm
)
520 local n
= tonumber(imm
)
524 if m
>= 0 and m
<= 255 and n
% 1 == 0 then return m
+ (i
%16) * 256 end
526 m
= (m
- t
) / 4 + t
* 2^
30
528 werror("out of range immediate `"..imm
.."'")
530 waction("IMM12", 0, imm
)
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
)
540 if n
>= 0 and n
<= 65535 and n
% 1 == 0 then
542 return (n
- t
) * 16 + t
544 werror("out of range immediate `"..imm
.."'")
546 waction("IMM16", 32*16, imm
)
551 local function parse_imm_load(imm
, ext
)
552 local n
= tonumber(imm
)
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
561 if n
>= -4095 and n
<= 4095 then
562 if n
>= 0 then return n
+0x00800000 end
566 werror("out of range immediate `"..imm
.."'")
568 waction(ext
and "IMML8" or "IMML12", 32768 + 32*(ext
and 8 or 12), imm
)
573 local function parse_shift(shift
, gprok
)
574 if shift
== "rrx" then
577 local s
, s2
= match(shift
, "^(%S+)%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
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)]
600 -- [1-9] (local label definition)
601 if match(label
, "^[1-9]$") then
602 return "LG", 10+tonumber(label
)
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+)$")
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)
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
628 local p1
, wb
= match(pn
, "^%[%s*(.-)%s*%](!?)$")
629 local p2
= params
[n
+1]
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
)
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
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
, "^#(.*)$")
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)
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
666 local p1a
, p2
= match(p1
, "^([^,%s]*)%s*(.*)$")
667 op
= op
+ parse_gpr(p1a
) * 65536 + 0x01000000
669 local imm
= match(p2
, "^,%s*#(.*)$")
671 local m
= parse_imm_load(imm
, ext
)
672 op
= op
+ m
+ (ext
and 0x00400000 or 0)
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)
679 if ext
then werror("too many parameters") end
680 op
= op
+ parse_shift(p3
)
684 if wb
== "!" then werror("bad use of '!'") end
685 op
= op
+ (ext
and 0x00c00000 or 0x00800000)
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)
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
704 -- Process each character.
705 for p
in gmatch(sub(template
, 9), ".") do
707 op
= op
+ parse_gpr(params
[n
]) * 4096; n
= n
+ 1
709 op
= op
+ parse_gpr(params
[n
]) * 65536; n
= n
+ 1
711 op
= op
+ parse_gpr(params
[n
]) * 256; n
= n
+ 1
713 op
= op
+ parse_gpr(params
[n
]); n
= n
+ 1
715 local imm
= match(params
[n
], "^#(.*)$")
717 op
= op
+ parse_imm12(imm
) + 0x02000000
719 op
= op
+ parse_gpr(params
[n
])
723 op
= op
+ parse_shift(params
[n
], true); n
= n
+ 1
725 op
= parse_load(params
, nparams
, n
, op
)
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.
731 if match(p
, "^([%w_]+):(r1?[0-9])$") or match(p
, "^r(1?[0-9])$") then
732 op
= op
+ parse_gpr(p
)
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)
740 local r
, wb
= match(params
[n
], "^([^!]*)(!?)$")
741 op
= op
+ parse_gpr(r
) * 65536 + (wb
== "!" and 0x00200000 or 0)
744 op
= op
+ parse_reglist(params
[n
]); n
= n
+ 1
746 op
= op
+ parse_imm16(params
[n
]); n
= n
+ 1
748 op
= op
+ parse_imm(params
[n
], 5, 7, 0, false); n
= n
+ 1
750 local imm
= match(params
[n
], "^#(.*)$")
752 op
= op
+ parse_imm(params
[n
], 5, 7, 0, false); n
= n
+ 1
754 op
= op
+ parse_gpr(params
[n
]) * 256 + 16
757 op
= op
+ parse_imm(params
[n
], 5, 16, 0, false); n
= n
+ 1
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")
764 op
= op
+ (imm
- t
) * 16 + t
766 op
= op
+ parse_imm(params
[n
], 24, 0, 0, false); n
= n
+ 1
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
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])
838 -- Must be a power of 2 in the range (2 ... 256).
842 waction("ALIGN", align
-1, nil, 1) -- Action byte is 2**n-1.
847 werror("bad alignment")
850 ------------------------------------------------------------------------------
852 -- Pseudo-opcode for (primitive) type definitions (map to C types).
853 map_op
[".type_3"] = function(params
, nparams
)
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
]
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
871 ctypefmt
= format("Dt%X(%%s)", num
),
874 wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num
, ctype
))
877 map_op
[".type_2"] = map_op
[".type_3"]
879 -- Dump type definitions.
880 local function dumptypes(out
, lvl
)
882 for name
in pairs(map_type
) do t
[#t
+1] = name
end
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
))
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
))
910 -- Dump all user defined elements.
911 function _M
.dumpdef(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
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
]
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
942 setmetatable(map_def
, { __index
= map_archdef
})
943 return map_op
, map_def
948 ------------------------------------------------------------------------------