diff options
-rw-r--r-- | dynasm/dasm_arm64.h | 15 | ||||
-rw-r--r-- | dynasm/dasm_arm64.lua | 44 |
2 files changed, 41 insertions, 18 deletions
diff --git a/dynasm/dasm_arm64.h b/dynasm/dasm_arm64.h index 577b54bc..b2251532 100644 --- a/dynasm/dasm_arm64.h +++ b/dynasm/dasm_arm64.h | |||
@@ -23,6 +23,7 @@ enum { | |||
23 | /* The following actions also have an argument. */ | 23 | /* The following actions also have an argument. */ |
24 | DASM_REL_PC, DASM_LABEL_PC, | 24 | DASM_REL_PC, DASM_LABEL_PC, |
25 | DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML, | 25 | DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML, |
26 | DASM_VREG, | ||
26 | DASM__MAX | 27 | DASM__MAX |
27 | }; | 28 | }; |
28 | 29 | ||
@@ -39,6 +40,7 @@ enum { | |||
39 | #define DASM_S_RANGE_LG 0x13000000 | 40 | #define DASM_S_RANGE_LG 0x13000000 |
40 | #define DASM_S_RANGE_PC 0x14000000 | 41 | #define DASM_S_RANGE_PC 0x14000000 |
41 | #define DASM_S_RANGE_REL 0x15000000 | 42 | #define DASM_S_RANGE_REL 0x15000000 |
43 | #define DASM_S_RANGE_VREG 0x16000000 | ||
42 | #define DASM_S_UNDEF_LG 0x21000000 | 44 | #define DASM_S_UNDEF_LG 0x21000000 |
43 | #define DASM_S_UNDEF_PC 0x22000000 | 45 | #define DASM_S_UNDEF_PC 0x22000000 |
44 | 46 | ||
@@ -312,13 +314,17 @@ void dasm_put(Dst_DECL, int start, ...) | |||
312 | } | 314 | } |
313 | case DASM_IMML: { | 315 | case DASM_IMML: { |
314 | #ifdef DASM_CHECKS | 316 | #ifdef DASM_CHECKS |
315 | int scale = (p[-2] >> 30); | 317 | int scale = (ins & 3); |
316 | CK((!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) || | 318 | CK((!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) || |
317 | (unsigned int)(n+256) < 512, RANGE_I); | 319 | (unsigned int)(n+256) < 512, RANGE_I); |
318 | #endif | 320 | #endif |
319 | b[pos++] = n; | 321 | b[pos++] = n; |
320 | break; | 322 | break; |
321 | } | 323 | } |
324 | case DASM_VREG: | ||
325 | CK(n < 32, RANGE_VREG); | ||
326 | b[pos++] = n; | ||
327 | break; | ||
322 | } | 328 | } |
323 | } | 329 | } |
324 | } | 330 | } |
@@ -375,7 +381,7 @@ int dasm_link(Dst_DECL, size_t *szp) | |||
375 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; | 381 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; |
376 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; | 382 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; |
377 | case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W: | 383 | case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W: |
378 | case DASM_IMML: pos++; break; | 384 | case DASM_IMML: case DASM_VREG: pos++; break; |
379 | case DASM_IMM13X: pos += 2; break; | 385 | case DASM_IMM13X: pos += 2; break; |
380 | } | 386 | } |
381 | } | 387 | } |
@@ -468,11 +474,14 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
468 | cp[-1] |= (dasm_imm13(n, *b++) << 10); | 474 | cp[-1] |= (dasm_imm13(n, *b++) << 10); |
469 | break; | 475 | break; |
470 | case DASM_IMML: { | 476 | case DASM_IMML: { |
471 | int scale = (p[-2] >> 30); | 477 | int scale = (ins & 3); |
472 | cp[-1] |= (!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ? | 478 | cp[-1] |= (!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ? |
473 | ((n << (10-scale)) | 0x01000000) : ((n & 511) << 12); | 479 | ((n << (10-scale)) | 0x01000000) : ((n & 511) << 12); |
474 | break; | 480 | break; |
475 | } | 481 | } |
482 | case DASM_VREG: | ||
483 | cp[-1] |= (n & 0x1f) << (ins & 0x1f); | ||
484 | break; | ||
476 | default: *cp++ = ins; break; | 485 | default: *cp++ = ins; break; |
477 | } | 486 | } |
478 | } | 487 | } |
diff --git a/dynasm/dasm_arm64.lua b/dynasm/dasm_arm64.lua index 861ff2b2..82412a05 100644 --- a/dynasm/dasm_arm64.lua +++ b/dynasm/dasm_arm64.lua | |||
@@ -40,6 +40,7 @@ local action_names = { | |||
40 | "STOP", "SECTION", "ESC", "REL_EXT", | 40 | "STOP", "SECTION", "ESC", "REL_EXT", |
41 | "ALIGN", "REL_LG", "LABEL_LG", | 41 | "ALIGN", "REL_LG", "LABEL_LG", |
42 | "REL_PC", "LABEL_PC", "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML", | 42 | "REL_PC", "LABEL_PC", "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML", |
43 | "VREG", | ||
43 | } | 44 | } |
44 | 45 | ||
45 | -- Maximum number of section buffer positions for dasm_put(). | 46 | -- Maximum number of section buffer positions for dasm_put(). |
@@ -246,9 +247,12 @@ local map_cond = { | |||
246 | 247 | ||
247 | local parse_reg_type | 248 | local parse_reg_type |
248 | 249 | ||
249 | local function parse_reg(expr) | 250 | local function parse_reg(expr, shift) |
250 | if not expr then werror("expected register name") end | 251 | if not expr then werror("expected register name") end |
251 | local tname, ovreg = match(expr, "^([%w_]+):(@?%l%d+)$") | 252 | local tname, ovreg = match(expr, "^([%w_]+):(@?%l%d+)$") |
253 | if not tname then | ||
254 | tname, ovreg = match(expr, "^([%w_]+):(R[xwqdshb]%b())$") | ||
255 | end | ||
252 | local tp = map_type[tname or expr] | 256 | local tp = map_type[tname or expr] |
253 | if tp then | 257 | if tp then |
254 | local reg = ovreg or tp.reg | 258 | local reg = ovreg or tp.reg |
@@ -266,18 +270,28 @@ local function parse_reg(expr) | |||
266 | elseif parse_reg_type ~= rt then | 270 | elseif parse_reg_type ~= rt then |
267 | werror("register size mismatch") | 271 | werror("register size mismatch") |
268 | end | 272 | end |
269 | return r, tp | 273 | return shl(r, shift), tp |
274 | end | ||
275 | end | ||
276 | local vrt, vreg = match(expr, "^R([xwqdshb])(%b())$") | ||
277 | if vreg then | ||
278 | if not parse_reg_type then | ||
279 | parse_reg_type = vrt | ||
280 | elseif parse_reg_type ~= vrt then | ||
281 | werror("register size mismatch") | ||
270 | end | 282 | end |
283 | if shift then waction("VREG", shift, vreg) end | ||
284 | return 0 | ||
271 | end | 285 | end |
272 | werror("bad register name `"..expr.."'") | 286 | werror("bad register name `"..expr.."'") |
273 | end | 287 | end |
274 | 288 | ||
275 | local function parse_reg_base(expr) | 289 | local function parse_reg_base(expr) |
276 | if expr == "sp" then return 0x3e0 end | 290 | if expr == "sp" then return 0x3e0 end |
277 | local base, tp = parse_reg(expr) | 291 | local base, tp = parse_reg(expr, 5) |
278 | if parse_reg_type ~= "x" then werror("bad register type") end | 292 | if parse_reg_type ~= "x" then werror("bad register type") end |
279 | parse_reg_type = false | 293 | parse_reg_type = false |
280 | return shl(base, 5), tp | 294 | return base, tp |
281 | end | 295 | end |
282 | 296 | ||
283 | local parse_ctx = {} | 297 | local parse_ctx = {} |
@@ -403,7 +417,7 @@ local function parse_imm_load(imm, scale) | |||
403 | end | 417 | end |
404 | werror("out of range immediate `"..imm.."'") | 418 | werror("out of range immediate `"..imm.."'") |
405 | else | 419 | else |
406 | waction("IMML", 0, imm) | 420 | waction("IMML", scale, imm) |
407 | return 0 | 421 | return 0 |
408 | end | 422 | end |
409 | end | 423 | end |
@@ -462,6 +476,7 @@ end | |||
462 | 476 | ||
463 | local function parse_load(params, nparams, n, op) | 477 | local function parse_load(params, nparams, n, op) |
464 | if params[n+2] then werror("too many operands") end | 478 | if params[n+2] then werror("too many operands") end |
479 | local scale = shr(op, 30) | ||
465 | local pn, p2 = params[n], params[n+1] | 480 | local pn, p2 = params[n], params[n+1] |
466 | local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$") | 481 | local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$") |
467 | if not p1 then | 482 | if not p1 then |
@@ -470,14 +485,13 @@ local function parse_load(params, nparams, n, op) | |||
470 | if reg and tailr ~= "" then | 485 | if reg and tailr ~= "" then |
471 | local base, tp = parse_reg_base(reg) | 486 | local base, tp = parse_reg_base(reg) |
472 | if tp then | 487 | if tp then |
473 | waction("IMML", 0, format(tp.ctypefmt, tailr)) | 488 | waction("IMML", scale, format(tp.ctypefmt, tailr)) |
474 | return op + base | 489 | return op + base |
475 | end | 490 | end |
476 | end | 491 | end |
477 | end | 492 | end |
478 | werror("expected address operand") | 493 | werror("expected address operand") |
479 | end | 494 | end |
480 | local scale = shr(op, 30) | ||
481 | if p2 then | 495 | if p2 then |
482 | if wb == "!" then werror("bad use of '!'") end | 496 | if wb == "!" then werror("bad use of '!'") end |
483 | op = op + parse_reg_base(p1) + parse_imm(p2, 9, 12, 0, true) + 0x400 | 497 | op = op + parse_reg_base(p1) + parse_imm(p2, 9, 12, 0, true) + 0x400 |
@@ -494,7 +508,7 @@ local function parse_load(params, nparams, n, op) | |||
494 | op = op + parse_imm_load(imm, scale) | 508 | op = op + parse_imm_load(imm, scale) |
495 | else | 509 | else |
496 | local p2b, p3b, p3s = match(p2a, "^,%s*([^,%s]*)%s*,?%s*(%S*)%s*(.*)$") | 510 | local p2b, p3b, p3s = match(p2a, "^,%s*([^,%s]*)%s*,?%s*(%S*)%s*(.*)$") |
497 | op = op + shl(parse_reg(p2b), 16) + 0x00200800 | 511 | op = op + parse_reg(p2b, 16) + 0x00200800 |
498 | if parse_reg_type ~= "x" and parse_reg_type ~= "w" then | 512 | if parse_reg_type ~= "x" and parse_reg_type ~= "w" then |
499 | werror("bad index register type") | 513 | werror("bad index register type") |
500 | end | 514 | end |
@@ -620,7 +634,7 @@ local function alias_bfx(p) | |||
620 | end | 634 | end |
621 | 635 | ||
622 | local function alias_bfiz(p) | 636 | local function alias_bfiz(p) |
623 | parse_reg(p[1]) | 637 | parse_reg(p[1], 0) |
624 | if parse_reg_type == "w" then | 638 | if parse_reg_type == "w" then |
625 | p[3] = "#-("..p[3]:sub(2)..")%32" | 639 | p[3] = "#-("..p[3]:sub(2)..")%32" |
626 | p[4] = "#("..p[4]:sub(2)..")-1" | 640 | p[4] = "#("..p[4]:sub(2)..")-1" |
@@ -631,7 +645,7 @@ local function alias_bfiz(p) | |||
631 | end | 645 | end |
632 | 646 | ||
633 | local alias_lslimm = op_alias("ubfm_4", function(p) | 647 | local alias_lslimm = op_alias("ubfm_4", function(p) |
634 | parse_reg(p[1]) | 648 | parse_reg(p[1], 0) |
635 | local sh = p[3]:sub(2) | 649 | local sh = p[3]:sub(2) |
636 | if parse_reg_type == "w" then | 650 | if parse_reg_type == "w" then |
637 | p[3] = "#-("..sh..")%32" | 651 | p[3] = "#-("..sh..")%32" |
@@ -891,15 +905,15 @@ local function parse_template(params, template, nparams, pos) | |||
891 | for p in gmatch(sub(template, 9), ".") do | 905 | for p in gmatch(sub(template, 9), ".") do |
892 | local q = params[n] | 906 | local q = params[n] |
893 | if p == "D" then | 907 | if p == "D" then |
894 | op = op + parse_reg(q); n = n + 1 | 908 | op = op + parse_reg(q, 0); n = n + 1 |
895 | elseif p == "N" then | 909 | elseif p == "N" then |
896 | op = op + shl(parse_reg(q), 5); n = n + 1 | 910 | op = op + parse_reg(q, 5); n = n + 1 |
897 | elseif p == "M" then | 911 | elseif p == "M" then |
898 | op = op + shl(parse_reg(q), 16); n = n + 1 | 912 | op = op + parse_reg(q, 16); n = n + 1 |
899 | elseif p == "A" then | 913 | elseif p == "A" then |
900 | op = op + shl(parse_reg(q), 10); n = n + 1 | 914 | op = op + parse_reg(q, 10); n = n + 1 |
901 | elseif p == "m" then | 915 | elseif p == "m" then |
902 | op = op + shl(parse_reg(params[n-1]), 16) | 916 | op = op + parse_reg(params[n-1], 16) |
903 | 917 | ||
904 | elseif p == "p" then | 918 | elseif p == "p" then |
905 | if q == "sp" then params[n] = "@x31" end | 919 | if q == "sp" then params[n] = "@x31" end |