diff options
| author | Mike Pall <mike> | 2021-05-02 22:25:56 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2021-05-02 22:25:56 +0200 |
| commit | 0f8a340c8c71fb8f5b8ae7c3ae94bfe81af8f8e8 (patch) | |
| tree | 6bead0550bc5e986e33cb5313cd11f3645706e97 | |
| parent | 1449663ecff3a51b15fe0113b62979b72690178f (diff) | |
| download | luajit-0f8a340c8c71fb8f5b8ae7c3ae94bfe81af8f8e8.tar.gz luajit-0f8a340c8c71fb8f5b8ae7c3ae94bfe81af8f8e8.tar.bz2 luajit-0f8a340c8c71fb8f5b8ae7c3ae94bfe81af8f8e8.zip | |
DynASM/ARM64: Add .long expr. Add .quad/.addr expr + refs.
Suggested by Dmitry Stogov, Hao Sun and Nick Gasson.
| -rw-r--r-- | dynasm/dasm_arm64.h | 36 | ||||
| -rw-r--r-- | dynasm/dasm_arm64.lua | 71 |
2 files changed, 84 insertions, 23 deletions
diff --git a/dynasm/dasm_arm64.h b/dynasm/dasm_arm64.h index 5ff4414c..8d1d9a96 100644 --- a/dynasm/dasm_arm64.h +++ b/dynasm/dasm_arm64.h | |||
| @@ -21,9 +21,9 @@ enum { | |||
| 21 | /* The following actions need a buffer position. */ | 21 | /* The following actions need a buffer position. */ |
| 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, DASM_REL_A, |
| 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_IMMV, DASM_VREG, |
| 27 | DASM__MAX | 27 | DASM__MAX |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| @@ -249,7 +249,7 @@ void dasm_put(Dst_DECL, int start, ...) | |||
| 249 | n = (ins & 255); CK(n < D->maxsection, RANGE_SEC); | 249 | n = (ins & 255); CK(n < D->maxsection, RANGE_SEC); |
| 250 | D->section = &D->sections[n]; goto stop; | 250 | D->section = &D->sections[n]; goto stop; |
| 251 | case DASM_ESC: p++; ofs += 4; break; | 251 | case DASM_ESC: p++; ofs += 4; break; |
| 252 | case DASM_REL_EXT: break; | 252 | case DASM_REL_EXT: if ((ins & 0x8000)) ofs += 8; break; |
| 253 | case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break; | 253 | case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break; |
| 254 | case DASM_REL_LG: | 254 | case DASM_REL_LG: |
| 255 | n = (ins & 2047) - 10; pl = D->lglabels + n; | 255 | n = (ins & 2047) - 10; pl = D->lglabels + n; |
| @@ -270,6 +270,11 @@ void dasm_put(Dst_DECL, int start, ...) | |||
| 270 | *pl = pos; | 270 | *pl = pos; |
| 271 | } | 271 | } |
| 272 | pos++; | 272 | pos++; |
| 273 | if ((ins & 0x8000)) ofs += 8; | ||
| 274 | break; | ||
| 275 | case DASM_REL_A: | ||
| 276 | b[pos++] = n; | ||
| 277 | b[pos++] = va_arg(ap, int); | ||
| 273 | break; | 278 | break; |
| 274 | case DASM_LABEL_LG: | 279 | case DASM_LABEL_LG: |
| 275 | pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel; | 280 | pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel; |
| @@ -321,6 +326,10 @@ void dasm_put(Dst_DECL, int start, ...) | |||
| 321 | b[pos++] = n; | 326 | b[pos++] = n; |
| 322 | break; | 327 | break; |
| 323 | } | 328 | } |
| 329 | case DASM_IMMV: | ||
| 330 | ofs += 4; | ||
| 331 | b[pos++] = n; | ||
| 332 | break; | ||
| 324 | case DASM_VREG: | 333 | case DASM_VREG: |
| 325 | CK(n < 32, RANGE_VREG); | 334 | CK(n < 32, RANGE_VREG); |
| 326 | b[pos++] = n; | 335 | b[pos++] = n; |
| @@ -381,8 +390,8 @@ int dasm_link(Dst_DECL, size_t *szp) | |||
| 381 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; | 390 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; |
| 382 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; | 391 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; |
| 383 | case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W: | 392 | case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W: |
| 384 | case DASM_IMML: case DASM_VREG: pos++; break; | 393 | case DASM_IMML: case DASM_IMMV: case DASM_VREG: pos++; break; |
| 385 | case DASM_IMM13X: pos += 2; break; | 394 | case DASM_IMM13X: case DASM_REL_A: pos += 2; break; |
| 386 | } | 395 | } |
| 387 | } | 396 | } |
| 388 | stop: (void)0; | 397 | stop: (void)0; |
| @@ -433,7 +442,9 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
| 433 | break; | 442 | break; |
| 434 | case DASM_REL_LG: | 443 | case DASM_REL_LG: |
| 435 | if (n < 0) { | 444 | if (n < 0) { |
| 436 | n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp + 4); | 445 | ptrdiff_t na = (ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp + 4; |
| 446 | n = (int)na; | ||
| 447 | CK((ptrdiff_t)n == na, RANGE_REL); | ||
| 437 | goto patchrel; | 448 | goto patchrel; |
| 438 | } | 449 | } |
| 439 | /* fallthrough */ | 450 | /* fallthrough */ |
| @@ -455,8 +466,18 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
| 455 | } else if ((ins & 0x1000)) { /* TBZ, TBNZ */ | 466 | } else if ((ins & 0x1000)) { /* TBZ, TBNZ */ |
| 456 | CK((n & 3) == 0 && ((n+0x00008000) >> 16) == 0, RANGE_REL); | 467 | CK((n & 3) == 0 && ((n+0x00008000) >> 16) == 0, RANGE_REL); |
| 457 | cp[-1] |= ((n << 3) & 0x0007ffe0); | 468 | cp[-1] |= ((n << 3) & 0x0007ffe0); |
| 469 | } else if ((ins & 0x8000)) { /* absolute */ | ||
| 470 | cp[0] = (unsigned int)((ptrdiff_t)cp - 4 + n); | ||
| 471 | cp[1] = (unsigned int)(((ptrdiff_t)cp - 4 + n) >> 32); | ||
| 472 | cp += 2; | ||
| 458 | } | 473 | } |
| 459 | break; | 474 | break; |
| 475 | case DASM_REL_A: { | ||
| 476 | ptrdiff_t na = (((ptrdiff_t)(*b++) << 32) | (unsigned int)n) - (ptrdiff_t)cp + 4; | ||
| 477 | n = (int)na; | ||
| 478 | CK((ptrdiff_t)n == na, RANGE_REL); | ||
| 479 | goto patchrel; | ||
| 480 | } | ||
| 460 | case DASM_LABEL_LG: | 481 | case DASM_LABEL_LG: |
| 461 | ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); | 482 | ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); |
| 462 | break; | 483 | break; |
| @@ -482,6 +503,9 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
| 482 | ((n << (10-scale)) | 0x01000000) : ((n & 511) << 12); | 503 | ((n << (10-scale)) | 0x01000000) : ((n & 511) << 12); |
| 483 | break; | 504 | break; |
| 484 | } | 505 | } |
| 506 | case DASM_IMMV: | ||
| 507 | *cp++ = n; | ||
| 508 | break; | ||
| 485 | case DASM_VREG: | 509 | case DASM_VREG: |
| 486 | cp[-1] |= (n & 0x1f) << (ins & 0x1f); | 510 | cp[-1] |= (n & 0x1f) << (ins & 0x1f); |
| 487 | break; | 511 | break; |
diff --git a/dynasm/dasm_arm64.lua b/dynasm/dasm_arm64.lua index 82412a05..59a555d8 100644 --- a/dynasm/dasm_arm64.lua +++ b/dynasm/dasm_arm64.lua | |||
| @@ -23,12 +23,12 @@ local _M = { _info = _info } | |||
| 23 | local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs | 23 | local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs |
| 24 | local assert, setmetatable, rawget = assert, setmetatable, rawget | 24 | local assert, setmetatable, rawget = assert, setmetatable, rawget |
| 25 | local _s = string | 25 | local _s = string |
| 26 | local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char | 26 | local format, byte, char = _s.format, _s.byte, _s.char |
| 27 | local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub | 27 | local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub |
| 28 | local concat, sort, insert = table.concat, table.sort, table.insert | 28 | local concat, sort, insert = table.concat, table.sort, table.insert |
| 29 | local bit = bit or require("bit") | 29 | local bit = bit or require("bit") |
| 30 | local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift | 30 | local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift |
| 31 | local ror, tohex = bit.ror, bit.tohex | 31 | local ror, tohex, tobit = bit.ror, bit.tohex, bit.tobit |
| 32 | 32 | ||
| 33 | -- Inherited tables and callbacks. | 33 | -- Inherited tables and callbacks. |
| 34 | local g_opt, g_arch | 34 | local g_opt, g_arch |
| @@ -39,7 +39,8 @@ 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", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML", | 42 | "REL_PC", "LABEL_PC", "REL_A", |
| 43 | "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML", "IMMV", | ||
| 43 | "VREG", | 44 | "VREG", |
| 44 | } | 45 | } |
| 45 | 46 | ||
| @@ -311,7 +312,7 @@ local function parse_number(n) | |||
| 311 | local code = loadenv("return "..n) | 312 | local code = loadenv("return "..n) |
| 312 | if code then | 313 | if code then |
| 313 | local ok, y = pcall(code) | 314 | local ok, y = pcall(code) |
| 314 | if ok then return y end | 315 | if ok and type(y) == "number" then return y end |
| 315 | end | 316 | end |
| 316 | return nil | 317 | return nil |
| 317 | end | 318 | end |
| @@ -575,14 +576,14 @@ local function parse_load_pair(params, nparams, n, op) | |||
| 575 | end | 576 | end |
| 576 | 577 | ||
| 577 | local function parse_label(label, def) | 578 | local function parse_label(label, def) |
| 578 | local prefix = sub(label, 1, 2) | 579 | local prefix = label:sub(1, 2) |
| 579 | -- =>label (pc label reference) | 580 | -- =>label (pc label reference) |
| 580 | if prefix == "=>" then | 581 | if prefix == "=>" then |
| 581 | return "PC", 0, sub(label, 3) | 582 | return "PC", 0, label:sub(3) |
| 582 | end | 583 | end |
| 583 | -- ->name (global label reference) | 584 | -- ->name (global label reference) |
| 584 | if prefix == "->" then | 585 | if prefix == "->" then |
| 585 | return "LG", map_global[sub(label, 3)] | 586 | return "LG", map_global[label:sub(3)] |
| 586 | end | 587 | end |
| 587 | if def then | 588 | if def then |
| 588 | -- [1-9] (local label definition) | 589 | -- [1-9] (local label definition) |
| @@ -600,8 +601,11 @@ local function parse_label(label, def) | |||
| 600 | if extname then | 601 | if extname then |
| 601 | return "EXT", map_extern[extname] | 602 | return "EXT", map_extern[extname] |
| 602 | end | 603 | end |
| 604 | -- &expr (pointer) | ||
| 605 | if label:sub(1, 1) == "&" then | ||
| 606 | return "A", 0, format("(ptrdiff_t)(%s)", label:sub(2)) | ||
| 607 | end | ||
| 603 | end | 608 | end |
| 604 | werror("bad label `"..label.."'") | ||
| 605 | end | 609 | end |
| 606 | 610 | ||
| 607 | local function branch_type(op) | 611 | local function branch_type(op) |
| @@ -895,14 +899,14 @@ end | |||
| 895 | 899 | ||
| 896 | -- Handle opcodes defined with template strings. | 900 | -- Handle opcodes defined with template strings. |
| 897 | local function parse_template(params, template, nparams, pos) | 901 | local function parse_template(params, template, nparams, pos) |
| 898 | local op = tonumber(sub(template, 1, 8), 16) | 902 | local op = tonumber(template:sub(1, 8), 16) |
| 899 | local n = 1 | 903 | local n = 1 |
| 900 | local rtt = {} | 904 | local rtt = {} |
| 901 | 905 | ||
| 902 | parse_reg_type = false | 906 | parse_reg_type = false |
| 903 | 907 | ||
| 904 | -- Process each character. | 908 | -- Process each character. |
| 905 | for p in gmatch(sub(template, 9), ".") do | 909 | for p in gmatch(template:sub(9), ".") do |
| 906 | local q = params[n] | 910 | local q = params[n] |
| 907 | if p == "D" then | 911 | if p == "D" then |
| 908 | op = op + parse_reg(q, 0); n = n + 1 | 912 | op = op + parse_reg(q, 0); n = n + 1 |
| @@ -944,8 +948,14 @@ local function parse_template(params, template, nparams, pos) | |||
| 944 | 948 | ||
| 945 | elseif p == "B" then | 949 | elseif p == "B" then |
| 946 | local mode, v, s = parse_label(q, false); n = n + 1 | 950 | local mode, v, s = parse_label(q, false); n = n + 1 |
| 951 | if not mode then werror("bad label `"..q.."'") end | ||
| 947 | local m = branch_type(op) | 952 | local m = branch_type(op) |
| 948 | waction("REL_"..mode, v+m, s, 1) | 953 | if mode == "A" then |
| 954 | waction("REL_"..mode, v+m, format("(unsigned int)(%s)", s)) | ||
| 955 | actargs[#actargs+1] = format("(unsigned int)((%s)>>32)", s) | ||
| 956 | else | ||
| 957 | waction("REL_"..mode, v+m, s, 1) | ||
| 958 | end | ||
| 949 | 959 | ||
| 950 | elseif p == "I" then | 960 | elseif p == "I" then |
| 951 | op = op + parse_imm12(q); n = n + 1 | 961 | op = op + parse_imm12(q); n = n + 1 |
| @@ -1050,23 +1060,50 @@ map_op[".label_1"] = function(params) | |||
| 1050 | if not params then return "[1-9] | ->global | =>pcexpr" end | 1060 | if not params then return "[1-9] | ->global | =>pcexpr" end |
| 1051 | if secpos+1 > maxsecpos then wflush() end | 1061 | if secpos+1 > maxsecpos then wflush() end |
| 1052 | local mode, n, s = parse_label(params[1], true) | 1062 | local mode, n, s = parse_label(params[1], true) |
| 1053 | if mode == "EXT" then werror("bad label definition") end | 1063 | if not mode or mode == "EXT" then werror("bad label definition") end |
| 1054 | waction("LABEL_"..mode, n, s, 1) | 1064 | waction("LABEL_"..mode, n, s, 1) |
| 1055 | end | 1065 | end |
| 1056 | 1066 | ||
| 1057 | ------------------------------------------------------------------------------ | 1067 | ------------------------------------------------------------------------------ |
| 1058 | 1068 | ||
| 1059 | -- Pseudo-opcodes for data storage. | 1069 | -- Pseudo-opcodes for data storage. |
| 1060 | map_op[".long_*"] = function(params) | 1070 | local function op_data(params) |
| 1061 | if not params then return "imm..." end | 1071 | if not params then return "imm..." end |
| 1072 | local sz = params.op == ".long" and 4 or 8 | ||
| 1062 | for _,p in ipairs(params) do | 1073 | for _,p in ipairs(params) do |
| 1063 | local n = tonumber(p) | 1074 | local imm = parse_number(p) |
| 1064 | if not n then werror("bad immediate `"..p.."'") end | 1075 | if imm then |
| 1065 | if n < 0 then n = n + 2^32 end | 1076 | local n = tobit(imm) |
| 1066 | wputw(n) | 1077 | if n == imm or (n < 0 and n + 2^32 == imm) then |
| 1078 | wputw(n < 0 and n + 2^32 or n) | ||
| 1079 | if sz == 8 then | ||
| 1080 | wputw(imm < 0 and 0xffffffff or 0) | ||
| 1081 | end | ||
| 1082 | elseif sz == 4 then | ||
| 1083 | werror("bad immediate `"..p.."'") | ||
| 1084 | else | ||
| 1085 | imm = nil | ||
| 1086 | end | ||
| 1087 | end | ||
| 1088 | if not imm then | ||
| 1089 | local mode, v, s = parse_label(p, false) | ||
| 1090 | if sz == 4 then | ||
| 1091 | if mode then werror("label does not fit into .long") end | ||
| 1092 | waction("IMMV", 0, p) | ||
| 1093 | elseif mode and mode ~= "A" then | ||
| 1094 | waction("REL_"..mode, v+0x8000, s, 1) | ||
| 1095 | else | ||
| 1096 | if mode == "A" then p = s end | ||
| 1097 | waction("IMMV", 0, format("(unsigned int)(%s)", p)) | ||
| 1098 | waction("IMMV", 0, format("(unsigned int)((unsigned long long)(%s)>>32)", p)) | ||
| 1099 | end | ||
| 1100 | end | ||
| 1067 | if secpos+2 > maxsecpos then wflush() end | 1101 | if secpos+2 > maxsecpos then wflush() end |
| 1068 | end | 1102 | end |
| 1069 | end | 1103 | end |
| 1104 | map_op[".long_*"] = op_data | ||
| 1105 | map_op[".quad_*"] = op_data | ||
| 1106 | map_op[".addr_*"] = op_data | ||
| 1070 | 1107 | ||
| 1071 | -- Alignment pseudo-opcode. | 1108 | -- Alignment pseudo-opcode. |
| 1072 | map_op[".align_1"] = function(params) | 1109 | map_op[".align_1"] = function(params) |
