From f02f5d77b58e486c9886fbec37fe7e6dc6f5933a Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 27 Apr 2021 15:23:26 +0300 Subject: [PATCH] DynASM/arm64: Support for "b &addr" --- dynasm/dasm_arm64.h | 10 ++++++++-- dynasm/dasm_arm64.lua | 17 ++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/dynasm/dasm_arm64.h b/dynasm/dasm_arm64.h index 9d223446..48a83e63 100644 --- a/dynasm/dasm_arm64.h +++ b/dynasm/dasm_arm64.h @@ -21,7 +21,7 @@ enum { /* The following actions need a buffer position. */ DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, DASM_ADDR_LG, /* 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_VREG, DASM__MAX @@ -312,6 +312,7 @@ void dasm_put(Dst_DECL, int start, ...) b[pos++] = m; break; } + case DASM_REL_A: case DASM_IMM_PC: { int m = va_arg(ap, int); 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_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W: 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; @@ -438,6 +439,11 @@ int dasm_encode(Dst_DECL, void *buffer) case DASM_ALIGN: ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000; 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: if (n < 0) { n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp + 4); diff --git a/dynasm/dasm_arm64.lua b/dynasm/dasm_arm64.lua index 932edb5e..15bef417 100644 --- a/dynasm/dasm_arm64.lua +++ b/dynasm/dasm_arm64.lua @@ -39,7 +39,7 @@ local wline, werror, wfatal, wwarn local action_names = { "STOP", "SECTION", "ESC", "REL_EXT", "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", } @@ -943,10 +943,17 @@ local function parse_template(params, template, nparams, pos) op = parse_load_pair(params, nparams, n, op) elseif p == "B" then - local mode, v, s = parse_label(q, false); n = n + 1 - local m = branch_type(op) - waction("REL_"..mode, v+m, s, 1) - + -- &expr (pointer) + if sub(q, 1, 1) == "&" then + 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 op = op + parse_imm12(q); n = n + 1 elseif p == "i" then