aboutsummaryrefslogtreecommitdiff
path: root/dynasm
diff options
context:
space:
mode:
authorMike Pall <mike>2021-05-02 22:25:56 +0200
committerMike Pall <mike>2021-05-02 22:25:56 +0200
commit0f8a340c8c71fb8f5b8ae7c3ae94bfe81af8f8e8 (patch)
tree6bead0550bc5e986e33cb5313cd11f3645706e97 /dynasm
parent1449663ecff3a51b15fe0113b62979b72690178f (diff)
downloadluajit-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.
Diffstat (limited to 'dynasm')
-rw-r--r--dynasm/dasm_arm64.h36
-rw-r--r--dynasm/dasm_arm64.lua71
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 }
23local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs 23local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
24local assert, setmetatable, rawget = assert, setmetatable, rawget 24local assert, setmetatable, rawget = assert, setmetatable, rawget
25local _s = string 25local _s = string
26local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char 26local format, byte, char = _s.format, _s.byte, _s.char
27local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub 27local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
28local concat, sort, insert = table.concat, table.sort, table.insert 28local concat, sort, insert = table.concat, table.sort, table.insert
29local bit = bit or require("bit") 29local bit = bit or require("bit")
30local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift 30local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
31local ror, tohex = bit.ror, bit.tohex 31local ror, tohex, tobit = bit.ror, bit.tohex, bit.tobit
32 32
33-- Inherited tables and callbacks. 33-- Inherited tables and callbacks.
34local g_opt, g_arch 34local g_opt, g_arch
@@ -39,7 +39,8 @@ local wline, werror, wfatal, wwarn
39local action_names = { 39local 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
317end 318end
@@ -575,14 +576,14 @@ local function parse_load_pair(params, nparams, n, op)
575end 576end
576 577
577local function parse_label(label, def) 578local 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.."'")
605end 609end
606 610
607local function branch_type(op) 611local 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.
897local function parse_template(params, template, nparams, pos) 901local 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)
1055end 1065end
1056 1066
1057------------------------------------------------------------------------------ 1067------------------------------------------------------------------------------
1058 1068
1059-- Pseudo-opcodes for data storage. 1069-- Pseudo-opcodes for data storage.
1060map_op[".long_*"] = function(params) 1070local 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
1069end 1103end
1104map_op[".long_*"] = op_data
1105map_op[".quad_*"] = op_data
1106map_op[".addr_*"] = op_data
1070 1107
1071-- Alignment pseudo-opcode. 1108-- Alignment pseudo-opcode.
1072map_op[".align_1"] = function(params) 1109map_op[".align_1"] = function(params)