aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dynasm/dasm_arm64.h15
-rw-r--r--dynasm/dasm_arm64.lua44
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
247local parse_reg_type 248local parse_reg_type
248 249
249local function parse_reg(expr) 250local 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.."'")
273end 287end
274 288
275local function parse_reg_base(expr) 289local 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
281end 295end
282 296
283local parse_ctx = {} 297local 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
409end 423end
@@ -462,6 +476,7 @@ end
462 476
463local function parse_load(params, nparams, n, op) 477local 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)
620end 634end
621 635
622local function alias_bfiz(p) 636local 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)
631end 645end
632 646
633local alias_lslimm = op_alias("ubfm_4", function(p) 647local 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