diff options
| author | Thomas Preud'homme <robotux@celest.fr> | 2012-10-07 17:48:46 +0200 |
|---|---|---|
| committer | Thomas Preud'homme <robotux@celest.fr> | 2012-10-10 00:19:43 +0200 |
| commit | 2fe7fd9e875979d0947c17609b64799219485d2d (patch) | |
| tree | b0e5449c3dc18206cc8cc58992386a7f84e7ef65 /tccelf.c | |
| parent | 3d409b08893873b917ccb8c34398bc41a4e84d7c (diff) | |
| download | tinycc-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.c | 32 |
1 files changed, 32 insertions, 0 deletions
@@ -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; |
