diff options
author | Mike Pall <mike> | 2011-04-08 02:44:21 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2011-04-08 02:44:21 +0200 |
commit | 3f8fed53587e406415945389243dd18284a20939 (patch) | |
tree | 573d03f63c855c4c47e3059141abf56db9a7bb6e | |
parent | 1a56dacbcf49e959971689fceef889f82a2dd3c5 (diff) | |
download | luajit-3f8fed53587e406415945389243dd18284a20939.tar.gz luajit-3f8fed53587e406415945389243dd18284a20939.tar.bz2 luajit-3f8fed53587e406415945389243dd18284a20939.zip |
ARM: Add pc-relative loads to DynASM.
-rw-r--r-- | dynasm/dasm_arm.h | 20 | ||||
-rw-r--r-- | dynasm/dasm_arm.lua | 70 |
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) | |||
360 | case DASM_STOP: case DASM_SECTION: goto stop; | 360 | case DASM_STOP: case DASM_SECTION: goto stop; |
361 | case DASM_ESC: *cp++ = *p++; break; | 361 | case DASM_ESC: *cp++ = *p++; break; |
362 | case DASM_REL_EXT: | 362 | case DASM_REL_EXT: |
363 | n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1); | 363 | n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048)); |
364 | goto patchrel; | 364 | goto patchrel; |
365 | case DASM_ALIGN: | 365 | case DASM_ALIGN: |
366 | ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000; | 366 | ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000; |
@@ -369,10 +369,18 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
369 | CK(n >= 0, UNDEF_LG); | 369 | CK(n >= 0, UNDEF_LG); |
370 | case DASM_REL_PC: | 370 | case DASM_REL_PC: |
371 | CK(n >= 0, UNDEF_PC); | 371 | CK(n >= 0, UNDEF_PC); |
372 | n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base); | 372 | n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) - 4; |
373 | patchrel: | 373 | patchrel: |
374 | CK((n & 3) == 0 && ((n-4+0x02000000) >> 26) == 0, RANGE_REL); | 374 | if ((ins & 0x800) == 0) { |
375 | cp[-1] |= (((n-4) >> 2) & 0x00ffffff); | 375 | CK((n & 3) == 0 && ((n+0x02000000) >> 26) == 0, RANGE_REL); |
376 | cp[-1] |= ((n >> 2) & 0x00ffffff); | ||
377 | } else if ((ins & 0x1000)) { | ||
378 | CK((n & 3) == 0 && -256 <= n && n <= 256, RANGE_REL); | ||
379 | goto patchimml8; | ||
380 | } else { | ||
381 | CK((n & 3) == 0 && -4096 <= n && n <= 4096, RANGE_REL); | ||
382 | goto patchimml12; | ||
383 | } | ||
376 | break; | 384 | break; |
377 | case DASM_LABEL_LG: | 385 | case DASM_LABEL_LG: |
378 | ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); | 386 | ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); |
@@ -387,11 +395,11 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
387 | case DASM_IMM16: | 395 | case DASM_IMM16: |
388 | cp[-1] |= ((n & 0xf000) << 4) | (n & 0x0fff); | 396 | cp[-1] |= ((n & 0xf000) << 4) | (n & 0x0fff); |
389 | break; | 397 | break; |
390 | case DASM_IMML8: | 398 | case DASM_IMML8: patchimml8: |
391 | cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) : | 399 | cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) : |
392 | ((-n & 0x0f) | ((-n & 0xf0) << 4)); | 400 | ((-n & 0x0f) | ((-n & 0xf0) << 4)); |
393 | break; | 401 | break; |
394 | case DASM_IMML12: | 402 | case DASM_IMML12: patchimml12: |
395 | cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n); | 403 | cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n); |
396 | break; | 404 | break; |
397 | default: *cp++ = ins; break; | 405 | 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) | |||
586 | end | 586 | end |
587 | end | 587 | end |
588 | 588 | ||
589 | local function parse_label(label, def) | ||
590 | local prefix = sub(label, 1, 2) | ||
591 | -- =>label (pc label reference) | ||
592 | if prefix == "=>" then | ||
593 | return "PC", 0, sub(label, 3) | ||
594 | end | ||
595 | -- ->name (global label reference) | ||
596 | if prefix == "->" then | ||
597 | return "LG", map_global[sub(label, 3)] | ||
598 | end | ||
599 | if def then | ||
600 | -- [1-9] (local label definition) | ||
601 | if match(label, "^[1-9]$") then | ||
602 | return "LG", 10+tonumber(label) | ||
603 | end | ||
604 | else | ||
605 | -- [<>][1-9] (local label reference) | ||
606 | local dir, lnum = match(label, "^([<>])([1-9])$") | ||
607 | if dir then -- Fwd: 1-9, Bkwd: 11-19. | ||
608 | return "LG", lnum + (dir == ">" and 0 or 10) | ||
609 | end | ||
610 | -- extern label (extern label reference) | ||
611 | local extname = match(label, "^extern%s+(%S+)$") | ||
612 | if extname then | ||
613 | return "EXT", map_extern[extname] | ||
614 | end | ||
615 | end | ||
616 | werror("bad label `"..label.."'") | ||
617 | end | ||
618 | |||
589 | local function parse_load(params, nparams, n, op) | 619 | local function parse_load(params, nparams, n, op) |
590 | local oplo = op % 256 | 620 | local oplo = op % 256 |
591 | local ext, ldrd = (oplo ~= 0), (oplo == 208) | 621 | local ext, ldrd = (oplo ~= 0), (oplo == 208) |
@@ -594,11 +624,17 @@ local function parse_load(params, nparams, n, op) | |||
594 | d = ((op - (op % 4096)) / 4096) % 16 | 624 | d = ((op - (op % 4096)) / 4096) % 16 |
595 | if d % 2 ~= 0 then werror("odd destination register") end | 625 | if d % 2 ~= 0 then werror("odd destination register") end |
596 | end | 626 | end |
597 | local p1, wb = match(params[n], "^%[%s*(.-)%s*%](!?)$") | 627 | local pn = params[n] |
628 | local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$") | ||
598 | local p2 = params[n+1] | 629 | local p2 = params[n+1] |
599 | if not p1 then | 630 | if not p1 then |
600 | if not p2 then | 631 | if not p2 then |
601 | local reg, tailr = match(params[n], "^([%w_:]+)%s*(.*)$") | 632 | if match(pn, "^[<>=%-]") or match(pn, "^extern%s+") then |
633 | local mode, n, s = parse_label(pn, false) | ||
634 | waction("REL_"..mode, n + (ext and 0x1800 or 0x0800), s, 1) | ||
635 | return op + 15 * 65536 + 0x01000000 + (ext and 0x00400000 or 0) | ||
636 | end | ||
637 | local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$") | ||
602 | if reg and tailr ~= "" then | 638 | if reg and tailr ~= "" then |
603 | local d, tp = parse_gpr(reg) | 639 | local d, tp = parse_gpr(reg) |
604 | if tp then | 640 | if tp then |
@@ -653,36 +689,6 @@ local function parse_load(params, nparams, n, op) | |||
653 | return op | 689 | return op |
654 | end | 690 | end |
655 | 691 | ||
656 | local function parse_label(label, def) | ||
657 | local prefix = sub(label, 1, 2) | ||
658 | -- =>label (pc label reference) | ||
659 | if prefix == "=>" then | ||
660 | return "PC", 0, sub(label, 3) | ||
661 | end | ||
662 | -- ->name (global label reference) | ||
663 | if prefix == "->" then | ||
664 | return "LG", map_global[sub(label, 3)] | ||
665 | end | ||
666 | if def then | ||
667 | -- [1-9] (local label definition) | ||
668 | if match(label, "^[1-9]$") then | ||
669 | return "LG", 10+tonumber(label) | ||
670 | end | ||
671 | else | ||
672 | -- [<>][1-9] (local label reference) | ||
673 | local dir, lnum = match(label, "^([<>])([1-9])$") | ||
674 | if dir then -- Fwd: 1-9, Bkwd: 11-19. | ||
675 | return "LG", lnum + (dir == ">" and 0 or 10) | ||
676 | end | ||
677 | -- extern label (extern label reference) | ||
678 | local extname = match(label, "^extern%s+(%S+)$") | ||
679 | if extname then | ||
680 | return "EXT", map_extern[extname] | ||
681 | end | ||
682 | end | ||
683 | werror("bad label `"..label.."'") | ||
684 | end | ||
685 | |||
686 | ------------------------------------------------------------------------------ | 692 | ------------------------------------------------------------------------------ |
687 | 693 | ||
688 | -- Handle opcodes defined with template strings. | 694 | -- Handle opcodes defined with template strings. |