aboutsummaryrefslogtreecommitdiff
path: root/tccelf.c
diff options
context:
space:
mode:
authorThomas Preud'homme <robotux@celest.fr>2012-10-07 17:48:46 +0200
committerThomas Preud'homme <robotux@celest.fr>2012-10-10 00:19:43 +0200
commit2fe7fd9e875979d0947c17609b64799219485d2d (patch)
treeb0e5449c3dc18206cc8cc58992386a7f84e7ef65 /tccelf.c
parent3d409b08893873b917ccb8c34398bc41a4e84d7c (diff)
downloadtinycc-2fe7fd9e875979d0947c17609b64799219485d2d.tar.gz
tinycc-2fe7fd9e875979d0947c17609b64799219485d2d.tar.bz2
Support for R_ARM_[THM_]MOV{W,T}_ABS[_NC} relocs
Add support for relocations R_ARM_MOVW_ABS_NC and R_ARM_MOVT_ABS as well as their Thumb2 counterpart R_ARM_THM_MOVW_ABS_NC and R_ARM_THM_MOVT_ABS. These are encountered with gcc when compiling for armv7-a and a data is loaded in a register, either in arm or Thumb2 mode. The first half of the data is loaded with movw ; the second half is loaded with movt.
Diffstat (limited to 'tccelf.c')
-rw-r--r--tccelf.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/tccelf.c b/tccelf.c
index a16499b..5e1a64e 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -620,6 +620,38 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
(*(int *)ptr) |= x;
}
break;
+ case R_ARM_MOVT_ABS:
+ case R_ARM_MOVW_ABS_NC:
+ {
+ int x, imm4, imm12;
+ if (type == R_ARM_MOVT_ABS)
+ val >>= 16;
+ imm12 = val & 0xfff;
+ imm4 = (val >> 12) & 0xf;
+ x = (imm4 << 16) | imm12;
+ if (type == R_ARM_THM_MOVT_ABS)
+ *(int *)ptr |= x;
+ else
+ *(int *)ptr += x;
+ }
+ break;
+ case R_ARM_THM_MOVT_ABS:
+ case R_ARM_THM_MOVW_ABS_NC:
+ {
+ int x, i, imm4, imm3, imm8;
+ if (type == R_ARM_THM_MOVT_ABS)
+ val >>= 16;
+ imm8 = val & 0xff;
+ imm3 = (val >> 8) & 0x7;
+ i = (val >> 11) & 1;
+ imm4 = (val >> 12) & 0xf;
+ x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
+ if (type == R_ARM_THM_MOVT_ABS)
+ *(int *)ptr |= x;
+ else
+ *(int *)ptr += x;
+ }
+ break;
case R_ARM_PREL31:
{
int x;