diff options
| -rw-r--r-- | dynasm/dasm_arm64.h | 11 | ||||
| -rw-r--r-- | dynasm/dasm_arm64.lua | 56 |
2 files changed, 50 insertions, 17 deletions
diff --git a/dynasm/dasm_arm64.h b/dynasm/dasm_arm64.h index 30bc3f95..4a9a49bc 100644 --- a/dynasm/dasm_arm64.h +++ b/dynasm/dasm_arm64.h | |||
| @@ -22,7 +22,7 @@ enum { | |||
| 22 | DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, | 22 | DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, |
| 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_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML, | 25 | DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML, |
| 26 | DASM__MAX | 26 | DASM__MAX |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| @@ -290,6 +290,10 @@ void dasm_put(Dst_DECL, int start, ...) | |||
| 290 | #endif | 290 | #endif |
| 291 | b[pos++] = n; | 291 | b[pos++] = n; |
| 292 | break; | 292 | break; |
| 293 | case DASM_IMM6: | ||
| 294 | CK((n >> 6) == 0, RANGE_I); | ||
| 295 | b[pos++] = n; | ||
| 296 | break; | ||
| 293 | case DASM_IMM12: | 297 | case DASM_IMM12: |
| 294 | CK(dasm_imm12((unsigned int)n) != -1, RANGE_I); | 298 | CK(dasm_imm12((unsigned int)n) != -1, RANGE_I); |
| 295 | b[pos++] = n; | 299 | b[pos++] = n; |
| @@ -369,7 +373,7 @@ int dasm_link(Dst_DECL, size_t *szp) | |||
| 369 | case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; | 373 | case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; |
| 370 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; | 374 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; |
| 371 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; | 375 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; |
| 372 | case DASM_IMM: case DASM_IMM12: case DASM_IMM13W: | 376 | case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W: |
| 373 | case DASM_IMML: pos++; break; | 377 | case DASM_IMML: pos++; break; |
| 374 | case DASM_IMM13X: pos += 2; break; | 378 | case DASM_IMM13X: pos += 2; break; |
| 375 | } | 379 | } |
| @@ -449,6 +453,9 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
| 449 | case DASM_IMM: | 453 | case DASM_IMM: |
| 450 | cp[-1] |= ((n>>((ins>>10)&31)) & ((1<<((ins>>5)&31))-1)) << (ins&31); | 454 | cp[-1] |= ((n>>((ins>>10)&31)) & ((1<<((ins>>5)&31))-1)) << (ins&31); |
| 451 | break; | 455 | break; |
| 456 | case DASM_IMM6: | ||
| 457 | cp[-1] |= ((n&31) << 19) | ((n&32) << 26); | ||
| 458 | break; | ||
| 452 | case DASM_IMM12: | 459 | case DASM_IMM12: |
| 453 | cp[-1] |= (dasm_imm12((unsigned int)n) << 10); | 460 | cp[-1] |= (dasm_imm12((unsigned int)n) << 10); |
| 454 | break; | 461 | break; |
diff --git a/dynasm/dasm_arm64.lua b/dynasm/dasm_arm64.lua index 33328606..125d722b 100644 --- a/dynasm/dasm_arm64.lua +++ b/dynasm/dasm_arm64.lua | |||
| @@ -39,7 +39,7 @@ local wline, werror, wfatal, wwarn | |||
| 39 | local action_names = { | 39 | 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", "IMM12", "IMM13W", "IMM13X", "IMML", | 42 | "REL_PC", "LABEL_PC", "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML", |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | -- Maximum number of section buffer positions for dasm_put(). | 45 | -- Maximum number of section buffer positions for dasm_put(). |
| @@ -274,10 +274,10 @@ end | |||
| 274 | 274 | ||
| 275 | local function parse_reg_base(expr) | 275 | local function parse_reg_base(expr) |
| 276 | if expr == "sp" then return 0x3e0 end | 276 | if expr == "sp" then return 0x3e0 end |
| 277 | local base = parse_reg(expr) | 277 | local base, tp = parse_reg(expr) |
| 278 | if parse_reg_type ~= "x" then werror("bad register type") end | 278 | if parse_reg_type ~= "x" then werror("bad register type") end |
| 279 | parse_reg_type = false | 279 | parse_reg_type = false |
| 280 | return shl(base, 5) | 280 | return shl(base, 5), tp |
| 281 | end | 281 | end |
| 282 | 282 | ||
| 283 | local parse_ctx = {} | 283 | local parse_ctx = {} |
| @@ -387,7 +387,8 @@ local function parse_imm6(imm) | |||
| 387 | end | 387 | end |
| 388 | werror("out of range immediate `"..imm.."'") | 388 | werror("out of range immediate `"..imm.."'") |
| 389 | else | 389 | else |
| 390 | werror("NYI imm6 action") | 390 | waction("IMM6", 0, imm) |
| 391 | return 0 | ||
| 391 | end | 392 | end |
| 392 | end | 393 | end |
| 393 | 394 | ||
| @@ -460,12 +461,23 @@ local function parse_cond(expr, inv) | |||
| 460 | end | 461 | end |
| 461 | 462 | ||
| 462 | local function parse_load(params, nparams, n, op) | 463 | local function parse_load(params, nparams, n, op) |
| 463 | local pn = params[n] | ||
| 464 | local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$") | ||
| 465 | if not p1 then werror("expected address operand") end | ||
| 466 | if params[n+2] then werror("too many operands") end | 464 | if params[n+2] then werror("too many operands") end |
| 465 | local pn, p2 = params[n], params[n+1] | ||
| 466 | local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$") | ||
| 467 | if not p1 then | ||
| 468 | if not p2 then | ||
| 469 | local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$") | ||
| 470 | if reg and tailr ~= "" then | ||
| 471 | local base, tp = parse_reg_base(reg) | ||
| 472 | if tp then | ||
| 473 | waction("IMML", 0, format(tp.ctypefmt, tailr)) | ||
| 474 | return op + base | ||
| 475 | end | ||
| 476 | end | ||
| 477 | end | ||
| 478 | werror("expected address operand") | ||
| 479 | end | ||
| 467 | local scale = shr(op, 30) | 480 | local scale = shr(op, 30) |
| 468 | local p2 = params[n+1] | ||
| 469 | if p2 then | 481 | if p2 then |
| 470 | if wb == "!" then werror("bad use of '!'") end | 482 | if wb == "!" then werror("bad use of '!'") end |
| 471 | op = op + parse_reg_base(p1) + parse_imm(p2, 9, 12, 0, true) + 0x400 | 483 | op = op + parse_reg_base(p1) + parse_imm(p2, 9, 12, 0, true) + 0x400 |
| @@ -520,12 +532,23 @@ local function parse_load(params, nparams, n, op) | |||
| 520 | end | 532 | end |
| 521 | 533 | ||
| 522 | local function parse_load_pair(params, nparams, n, op) | 534 | local function parse_load_pair(params, nparams, n, op) |
| 523 | local pn = params[n] | ||
| 524 | local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$") | ||
| 525 | if not p1 then werror("expected address operand") end | ||
| 526 | if params[n+2] then werror("too many operands") end | 535 | if params[n+2] then werror("too many operands") end |
| 536 | local pn, p2 = params[n], params[n+1] | ||
| 527 | local scale = shr(op, 30) == 0 and 2 or 3 | 537 | local scale = shr(op, 30) == 0 and 2 or 3 |
| 528 | local p2 = params[n+1] | 538 | local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$") |
| 539 | if not p1 then | ||
| 540 | if not p2 then | ||
| 541 | local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$") | ||
| 542 | if reg and tailr ~= "" then | ||
| 543 | local base, tp = parse_reg_base(reg) | ||
| 544 | if tp then | ||
| 545 | waction("IMM", 32768+7*32+15+scale*1024, format(tp.ctypefmt, tailr)) | ||
| 546 | return op + base + 0x01000000 | ||
| 547 | end | ||
| 548 | end | ||
| 549 | end | ||
| 550 | werror("expected address operand") | ||
| 551 | end | ||
| 529 | if p2 then | 552 | if p2 then |
| 530 | if wb == "!" then werror("bad use of '!'") end | 553 | if wb == "!" then werror("bad use of '!'") end |
| 531 | op = op + 0x00800000 | 554 | op = op + 0x00800000 |
| @@ -724,7 +747,7 @@ map_op = { | |||
| 724 | 747 | ||
| 725 | sxtb_2 = "13001c00DNw|93401c00DNx", | 748 | sxtb_2 = "13001c00DNw|93401c00DNx", |
| 726 | sxth_2 = "13003c00DNw|93403c00DNx", | 749 | sxth_2 = "13003c00DNw|93403c00DNx", |
| 727 | sxtw_2 = "93407c00DNx", | 750 | sxtw_2 = "93407c00DxNw", |
| 728 | uxtb_2 = "53001c00DNw", | 751 | uxtb_2 = "53001c00DNw", |
| 729 | uxth_2 = "53003c00DNw", | 752 | uxth_2 = "53003c00DNw", |
| 730 | 753 | ||
| @@ -851,7 +874,7 @@ map_op = { | |||
| 851 | } | 874 | } |
| 852 | 875 | ||
| 853 | for cond,c in pairs(map_cond) do | 876 | for cond,c in pairs(map_cond) do |
| 854 | map_op["b"..cond.."_1"] = tohex(0x54000000+c) | 877 | map_op["b"..cond.."_1"] = tohex(0x54000000+c).."B" |
| 855 | end | 878 | end |
| 856 | 879 | ||
| 857 | ------------------------------------------------------------------------------ | 880 | ------------------------------------------------------------------------------ |
| @@ -957,13 +980,16 @@ function op_template(params, template, nparams) | |||
| 957 | -- A single opcode needs a maximum of 3 positions. | 980 | -- A single opcode needs a maximum of 3 positions. |
| 958 | if secpos+3 > maxsecpos then wflush() end | 981 | if secpos+3 > maxsecpos then wflush() end |
| 959 | local pos = wpos() | 982 | local pos = wpos() |
| 960 | local apos, spos = #actargs, secpos | 983 | local lpos, apos, spos = #actlist, #actargs, secpos |
| 961 | 984 | ||
| 962 | local ok, err | 985 | local ok, err |
| 963 | for t in gmatch(template, "[^|]+") do | 986 | for t in gmatch(template, "[^|]+") do |
| 964 | ok, err = pcall(parse_template, params, t, nparams, pos) | 987 | ok, err = pcall(parse_template, params, t, nparams, pos) |
| 965 | if ok then return end | 988 | if ok then return end |
| 966 | secpos = spos | 989 | secpos = spos |
| 990 | actlist[lpos+1] = nil | ||
| 991 | actlist[lpos+2] = nil | ||
| 992 | actlist[lpos+3] = nil | ||
| 967 | actargs[apos+1] = nil | 993 | actargs[apos+1] = nil |
| 968 | actargs[apos+2] = nil | 994 | actargs[apos+2] = nil |
| 969 | actargs[apos+3] = nil | 995 | actargs[apos+3] = nil |
