DynASM/arm64: Support for "b &addr"

This commit is contained in:
Dmitry Stogov 2021-04-27 15:23:26 +03:00
parent a9ffa6656c
commit f02f5d77b5
2 changed files with 20 additions and 7 deletions

View File

@ -21,7 +21,7 @@ enum {
/* The following actions need a buffer position. */ /* The following actions need a buffer position. */
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, DASM_ADDR_LG, DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, DASM_ADDR_LG,
/* The following actions also have an argument. */ /* The following actions also have an argument. */
DASM_REL_PC, DASM_LABEL_PC, DASM_ADDR_PC, DASM_REL_PC, DASM_LABEL_PC, DASM_ADDR_PC, DASM_REL_A,
DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML, DASM_IMM_PC, DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML, DASM_IMM_PC,
DASM_VREG, DASM_VREG,
DASM__MAX DASM__MAX
@ -312,6 +312,7 @@ void dasm_put(Dst_DECL, int start, ...)
b[pos++] = m; b[pos++] = m;
break; break;
} }
case DASM_REL_A:
case DASM_IMM_PC: { case DASM_IMM_PC: {
int m = va_arg(ap, int); int m = va_arg(ap, int);
b[pos++] = n; b[pos++] = n;
@ -388,7 +389,7 @@ int dasm_link(Dst_DECL, size_t *szp)
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W: case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W:
case DASM_IMML: case DASM_VREG: pos++; break; case DASM_IMML: case DASM_VREG: pos++; break;
case DASM_IMM13X: case DASM_IMM_PC: pos += 2; break; case DASM_IMM13X: case DASM_REL_A: case DASM_IMM_PC: pos += 2; break;
} }
} }
stop: (void)0; stop: (void)0;
@ -438,6 +439,11 @@ int dasm_encode(Dst_DECL, void *buffer)
case DASM_ALIGN: case DASM_ALIGN:
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000; ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
break; break;
case DASM_REL_A:
addr = (((unsigned long long)(*b++)) << 32) | (unsigned int)n;
CK((((addr - (ptrdiff_t)(cp+4)) + 0x08000000) >> 28) == 0, RANGE_REL);
n = (unsigned int)(addr - (ptrdiff_t)cp + 4);
goto patchrel;
case DASM_REL_LG: case DASM_REL_LG:
if (n < 0) { if (n < 0) {
n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp + 4); n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp + 4);

View File

@ -39,7 +39,7 @@ local wline, werror, wfatal, wwarn
local action_names = { local action_names = {
"STOP", "SECTION", "ESC", "REL_EXT", "STOP", "SECTION", "ESC", "REL_EXT",
"ALIGN", "REL_LG", "LABEL_LG", "ADDR_LG", "ALIGN", "REL_LG", "LABEL_LG", "ADDR_LG",
"REL_PC", "LABEL_PC", "ADDR_PC", "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML", "IMM_PC", "REL_PC", "LABEL_PC", "ADDR_PC", "REL_A", "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML", "IMM_PC",
"VREG", "VREG",
} }
@ -943,10 +943,17 @@ local function parse_template(params, template, nparams, pos)
op = parse_load_pair(params, nparams, n, op) op = parse_load_pair(params, nparams, n, op)
elseif p == "B" then elseif p == "B" then
local mode, v, s = parse_label(q, false); n = n + 1 -- &expr (pointer)
local m = branch_type(op) if sub(q, 1, 1) == "&" then
waction("REL_"..mode, v+m, s, 1) local a = sub(q,2); n = n + 1
local m = branch_type(op)
waction("REL_A", m, format("(unsigned int)(unsigned long long)(%s)", a))
actargs[#actargs+1] = format("(unsigned int)((unsigned long long)(%s)>>32)", a)
else
local mode, v, s = parse_label(q, false); n = n + 1
local m = branch_type(op)
waction("REL_"..mode, v+m, s, 1)
end
elseif p == "I" then elseif p == "I" then
op = op + parse_imm12(q); n = n + 1 op = op + parse_imm12(q); n = n + 1
elseif p == "i" then elseif p == "i" then