summaryrefslogtreecommitdiff
path: root/dynasm
diff options
context:
space:
mode:
authorMike Pall <mike>2011-04-08 02:44:21 +0200
committerMike Pall <mike>2011-04-08 02:44:21 +0200
commit3f8fed53587e406415945389243dd18284a20939 (patch)
tree573d03f63c855c4c47e3059141abf56db9a7bb6e /dynasm
parent1a56dacbcf49e959971689fceef889f82a2dd3c5 (diff)
downloadluajit2-3f8fed53587e406415945389243dd18284a20939.tar.gz
ARM: Add pc-relative loads to DynASM.
Diffstat (limited to 'dynasm')
-rw-r--r--dynasm/dasm_arm.h20
-rw-r--r--dynasm/dasm_arm.lua70
2 files changed, 52 insertions, 38 deletions
diff --git a/dynasm/dasm_arm.h b/dynasm/dasm_arm.h
index 3fd795b7..87db7f00 100644
--- a/dynasm/dasm_arm.h
+++ b/dynasm/dasm_arm.h
@@ -360,7 +360,7 @@ int dasm_encode(Dst_DECL, void *buffer)
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: *cp++ = *p++; break;
case DASM_REL_EXT:
- n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1);
+ n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
goto patchrel;
case DASM_ALIGN:
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
@@ -369,10 +369,18 @@ int dasm_encode(Dst_DECL, void *buffer)
CK(n >= 0, UNDEF_LG);
case DASM_REL_PC:
CK(n >= 0, UNDEF_PC);
- n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base);
+ n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) - 4;
patchrel:
- CK((n & 3) == 0 && ((n-4+0x02000000) >> 26) == 0, RANGE_REL);
- cp[-1] |= (((n-4) >> 2) & 0x00ffffff);
+ if ((ins & 0x800) == 0) {
+ CK((n & 3) == 0 && ((n+0x02000000) >> 26) == 0, RANGE_REL);
+ cp[-1] |= ((n >> 2) & 0x00ffffff);
+ } else if ((ins & 0x1000)) {
+ CK((n & 3) == 0 && -256 <= n && n <= 256, RANGE_REL);
+ goto patchimml8;
+ } else {
+ CK((n & 3) == 0 && -4096 <= n && n <= 4096, RANGE_REL);
+ goto patchimml12;
+ }
break;
case DASM_LABEL_LG:
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
@@ -387,11 +395,11 @@ int dasm_encode(Dst_DECL, void *buffer)
case DASM_IMM16:
cp[-1] |= ((n & 0xf000) << 4) | (n & 0x0fff);
break;
- case DASM_IMML8:
+ case DASM_IMML8: patchimml8:
cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) :
((-n & 0x0f) | ((-n & 0xf0) << 4));
break;
- case DASM_IMML12:
+ case DASM_IMML12: patchimml12:
cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n);
break;
default: *cp++ = ins; break;
diff --git a/dynasm/dasm_arm.lua b/dynasm/dasm_arm.lua
index 243cfe90..1876078b 100644
--- a/dynasm/dasm_arm.lua
+++ b/dynasm/dasm_arm.lua
@@ -586,6 +586,36 @@ local function parse_shift(shift, gprok)
end
end
+local function parse_label(label, def)
+ local prefix = sub(label, 1, 2)
+ -- =>label (pc label reference)
+ if prefix == "=>" then
+ return "PC", 0, sub(label, 3)
+ end
+ -- ->name (global label reference)
+ if prefix == "->" then
+ return "LG", map_global[sub(label, 3)]
+ end
+ if def then
+ -- [1-9] (local label definition)
+ if match(label, "^[1-9]$") then
+ return "LG", 10+tonumber(label)
+ end
+ else
+ -- [<>][1-9] (local label reference)
+ local dir, lnum = match(label, "^([<>])([1-9])$")
+ if dir then -- Fwd: 1-9, Bkwd: 11-19.
+ return "LG", lnum + (dir == ">" and 0 or 10)
+ end
+ -- extern label (extern label reference)
+ local extname = match(label, "^extern%s+(%S+)$")
+ if extname then
+ return "EXT", map_extern[extname]
+ end
+ end
+ werror("bad label `"..label.."'")
+end
+
local function parse_load(params, nparams, n, op)
local oplo = op % 256
local ext, ldrd = (oplo ~= 0), (oplo == 208)
@@ -594,11 +624,17 @@ local function parse_load(params, nparams, n, op)
d = ((op - (op % 4096)) / 4096) % 16
if d % 2 ~= 0 then werror("odd destination register") end
end
- local p1, wb = match(params[n], "^%[%s*(.-)%s*%](!?)$")
+ local pn = params[n]
+ local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
local p2 = params[n+1]
if not p1 then
if not p2 then
- local reg, tailr = match(params[n], "^([%w_:]+)%s*(.*)$")
+ if match(pn, "^[<>=%-]") or match(pn, "^extern%s+") then
+ local mode, n, s = parse_label(pn, false)
+ waction("REL_"..mode, n + (ext and 0x1800 or 0x0800), s, 1)
+ return op + 15 * 65536 + 0x01000000 + (ext and 0x00400000 or 0)
+ end
+ local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$")
if reg and tailr ~= "" then
local d, tp = parse_gpr(reg)
if tp then
@@ -653,36 +689,6 @@ local function parse_load(params, nparams, n, op)
return op
end
-local function parse_label(label, def)
- local prefix = sub(label, 1, 2)
- -- =>label (pc label reference)
- if prefix == "=>" then
- return "PC", 0, sub(label, 3)
- end
- -- ->name (global label reference)
- if prefix == "->" then
- return "LG", map_global[sub(label, 3)]
- end
- if def then
- -- [1-9] (local label definition)
- if match(label, "^[1-9]$") then
- return "LG", 10+tonumber(label)
- end
- else
- -- [<>][1-9] (local label reference)
- local dir, lnum = match(label, "^([<>])([1-9])$")
- if dir then -- Fwd: 1-9, Bkwd: 11-19.
- return "LG", lnum + (dir == ">" and 0 or 10)
- end
- -- extern label (extern label reference)
- local extname = match(label, "^extern%s+(%S+)$")
- if extname then
- return "EXT", map_extern[extname]
- end
- end
- werror("bad label `"..label.."'")
-end
-
------------------------------------------------------------------------------
-- Handle opcodes defined with template strings.