Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae51e609 authored by Paul Gortmaker's avatar Paul Gortmaker Committed by Russell King
Browse files

[ARM] 5507/1: support R_ARM_MOVW_ABS_NC and MOVT_ABS relocation types



From: Bruce Ashfield <bruce.ashfield@windriver.com>

To fully support the armv7-a instruction set/optimizations, support
for the R_ARM_MOVW_ABS_NC and R_ARM_MOVT_ABS relocation types is
required.

The MOVW and MOVT are both load-immediate instructions, MOVW loads 16
bits into the bottom half of a register, and MOVT loads 16 bits into the
top half of a register.

The relocation information for these instructions has a full 32 bit
value, plus an addend which is stored in the 16 immediate bits in the
instruction itself.  The immediate bits in the instruction are not
contiguous (the register # splits it into a 4 bit and 12 bit value),
so the addend has to be extracted accordingly and added to the value.
The value is then split and put into the instruction; a MOVW uses the
bottom 16 bits of the value, and a MOVT uses the top 16 bits.

Signed-off-by: default avatarDavid Borman <david.borman@windriver.com>
Signed-off-by: default avatarBruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: default avatarPaul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent a029b706
Loading
Loading
Loading
Loading
+9 −7
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ typedef struct user_fp elf_fpregset_t;
#define R_ARM_JUMP24		29
#define R_ARM_V4BX		40
#define R_ARM_PREL31		42
#define R_ARM_MOVW_ABS_NC	43
#define R_ARM_MOVT_ABS		44

/*
 * These are used to set parameters in the core dumps.
+15 −0
Original line number Diff line number Diff line
@@ -169,6 +169,21 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
			*(u32 *)loc = offset & 0x7fffffff;
			break;

		case R_ARM_MOVW_ABS_NC:
		case R_ARM_MOVT_ABS:
			offset = *(u32 *)loc;
			offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff);
			offset = (offset ^ 0x8000) - 0x8000;

			offset += sym->st_value;
			if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_ABS)
				offset >>= 16;

			*(u32 *)loc &= 0xfff0f000;
			*(u32 *)loc |= ((offset & 0xf000) << 4) |
					(offset & 0x0fff);
			break;

		default:
			printk(KERN_ERR "%s: unknown relocation: %u\n",
			       module->name, ELF32_R_TYPE(rel->r_info));