Skip to content

Commit 5f44ed5

Browse files
Mike Palldstogov
authored andcommitted
DynASM/ARM64: Add .long expr. Add .quad/.addr expr + refs.
Suggested by Dmitry Stogov, Hao Sun and Nick Gasson.
1 parent 4a50741 commit 5f44ed5

File tree

2 files changed

+84
-23
lines changed

2 files changed

+84
-23
lines changed

ext/opcache/jit/dynasm/dasm_arm64.h

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ enum {
2121
/* The following actions need a buffer position. */
2222
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
2323
/* The following actions also have an argument. */
24-
DASM_REL_PC, DASM_LABEL_PC,
24+
DASM_REL_PC, DASM_LABEL_PC, DASM_REL_A,
2525
DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML,
26-
DASM_VREG,
26+
DASM_IMMV, DASM_VREG,
2727
DASM__MAX
2828
};
2929

@@ -249,7 +249,7 @@ void dasm_put(Dst_DECL, int start, ...)
249249
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
250250
D->section = &D->sections[n]; goto stop;
251251
case DASM_ESC: p++; ofs += 4; break;
252-
case DASM_REL_EXT: break;
252+
case DASM_REL_EXT: if ((ins & 0x8000)) ofs += 8; break;
253253
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
254254
case DASM_REL_LG:
255255
n = (ins & 2047) - 10; pl = D->lglabels + n;
@@ -270,6 +270,11 @@ void dasm_put(Dst_DECL, int start, ...)
270270
*pl = pos;
271271
}
272272
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);
273278
break;
274279
case DASM_LABEL_LG:
275280
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
@@ -321,6 +326,10 @@ void dasm_put(Dst_DECL, int start, ...)
321326
b[pos++] = n;
322327
break;
323328
}
329+
case DASM_IMMV:
330+
ofs += 4;
331+
b[pos++] = n;
332+
break;
324333
case DASM_VREG:
325334
CK(n < 32, RANGE_VREG);
326335
b[pos++] = n;
@@ -381,8 +390,8 @@ int dasm_link(Dst_DECL, size_t *szp)
381390
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
382391
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
383392
case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W:
384-
case DASM_IMML: case DASM_VREG: pos++; break;
385-
case DASM_IMM13X: pos += 2; break;
393+
case DASM_IMML: case DASM_IMMV: case DASM_VREG: pos++; break;
394+
case DASM_IMM13X: case DASM_REL_A: pos += 2; break;
386395
}
387396
}
388397
stop: (void)0;
@@ -433,7 +442,9 @@ int dasm_encode(Dst_DECL, void *buffer)
433442
break;
434443
case DASM_REL_LG:
435444
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);
437448
goto patchrel;
438449
}
439450
/* fallthrough */
@@ -455,8 +466,18 @@ int dasm_encode(Dst_DECL, void *buffer)
455466
} else if ((ins & 0x1000)) { /* TBZ, TBNZ */
456467
CK((n & 3) == 0 && ((n+0x00008000) >> 16) == 0, RANGE_REL);
457468
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;
458473
}
459474
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+
}
460481
case DASM_LABEL_LG:
461482
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
462483
break;
@@ -482,6 +503,9 @@ int dasm_encode(Dst_DECL, void *buffer)
482503
((n << (10-scale)) | 0x01000000) : ((n & 511) << 12);
483504
break;
484505
}
506+
case DASM_IMMV:
507+
*cp++ = n;
508+
break;
485509
case DASM_VREG:
486510
cp[-1] |= (n & 0x1f) << (ins & 0x1f);
487511
break;

ext/opcache/jit/dynasm/dasm_arm64.lua

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ local _M = { _info = _info }
2323
local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
2424
local assert, setmetatable, rawget = assert, setmetatable, rawget
2525
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
2727
local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
2828
local concat, sort, insert = table.concat, table.sort, table.insert
2929
local bit = bit or require("bit")
3030
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
3232

3333
-- Inherited tables and callbacks.
3434
local g_opt, g_arch
@@ -39,7 +39,8 @@ local wline, werror, wfatal, wwarn
3939
local action_names = {
4040
"STOP", "SECTION", "ESC", "REL_EXT",
4141
"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",
4344
"VREG",
4445
}
4546

@@ -311,7 +312,7 @@ local function parse_number(n)
311312
local code = loadenv("return "..n)
312313
if code then
313314
local ok, y = pcall(code)
314-
if ok then return y end
315+
if ok and type(y) == "number" then return y end
315316
end
316317
return nil
317318
end
@@ -575,14 +576,14 @@ local function parse_load_pair(params, nparams, n, op)
575576
end
576577

577578
local function parse_label(label, def)
578-
local prefix = sub(label, 1, 2)
579+
local prefix = label:sub(1, 2)
579580
-- =>label (pc label reference)
580581
if prefix == "=>" then
581-
return "PC", 0, sub(label, 3)
582+
return "PC", 0, label:sub(3)
582583
end
583584
-- ->name (global label reference)
584585
if prefix == "->" then
585-
return "LG", map_global[sub(label, 3)]
586+
return "LG", map_global[label:sub(3)]
586587
end
587588
if def then
588589
-- [1-9] (local label definition)
@@ -600,8 +601,11 @@ local function parse_label(label, def)
600601
if extname then
601602
return "EXT", map_extern[extname]
602603
end
604+
-- &expr (pointer)
605+
if label:sub(1, 1) == "&" then
606+
return "A", 0, format("(ptrdiff_t)(%s)", label:sub(2))
607+
end
603608
end
604-
werror("bad label `"..label.."'")
605609
end
606610

607611
local function branch_type(op)
@@ -895,14 +899,14 @@ end
895899

896900
-- Handle opcodes defined with template strings.
897901
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)
899903
local n = 1
900904
local rtt = {}
901905

902906
parse_reg_type = false
903907

904908
-- Process each character.
905-
for p in gmatch(sub(template, 9), ".") do
909+
for p in gmatch(template:sub(9), ".") do
906910
local q = params[n]
907911
if p == "D" then
908912
op = op + parse_reg(q, 0); n = n + 1
@@ -944,8 +948,14 @@ local function parse_template(params, template, nparams, pos)
944948

945949
elseif p == "B" then
946950
local mode, v, s = parse_label(q, false); n = n + 1
951+
if not mode then werror("bad label `"..q.."'") end
947952
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
949959

950960
elseif p == "I" then
951961
op = op + parse_imm12(q); n = n + 1
@@ -1050,23 +1060,50 @@ map_op[".label_1"] = function(params)
10501060
if not params then return "[1-9] | ->global | =>pcexpr" end
10511061
if secpos+1 > maxsecpos then wflush() end
10521062
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
10541064
waction("LABEL_"..mode, n, s, 1)
10551065
end
10561066

10571067
------------------------------------------------------------------------------
10581068

10591069
-- Pseudo-opcodes for data storage.
1060-
map_op[".long_*"] = function(params)
1070+
local function op_data(params)
10611071
if not params then return "imm..." end
1072+
local sz = params.op == ".long" and 4 or 8
10621073
for _,p in ipairs(params) do
1063-
local n = tonumber(p)
1064-
if not n then werror("bad immediate `"..p.."'") end
1065-
if n < 0 then n = n + 2^32 end
1066-
wputw(n)
1074+
local imm = parse_number(p)
1075+
if imm then
1076+
local n = tobit(imm)
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
10671101
if secpos+2 > maxsecpos then wflush() end
10681102
end
10691103
end
1104+
map_op[".long_*"] = op_data
1105+
map_op[".quad_*"] = op_data
1106+
map_op[".addr_*"] = op_data
10701107

10711108
-- Alignment pseudo-opcode.
10721109
map_op[".align_1"] = function(params)

0 commit comments

Comments
 (0)