diff options
| author | Mike Pall <mike> | 2021-03-31 18:11:32 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2021-03-31 18:11:32 +0200 |
| commit | d1132afb25e2ba66d5d4c287b886a3c0a61bd9db (patch) | |
| tree | ffdc630b5ed78067458ee65e542e352b224704d6 | |
| parent | 66563bdab0c7acf3cd61dc6cfcca36275951d084 (diff) | |
| download | luajit-d1132afb25e2ba66d5d4c287b886a3c0a61bd9db.tar.gz luajit-d1132afb25e2ba66d5d4c287b886a3c0a61bd9db.tar.bz2 luajit-d1132afb25e2ba66d5d4c287b886a3c0a61bd9db.zip | |
DynASM/ARM64: Add VREG support.
Contributed by Hao Sun and Nick Gasson.
| -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 |
