diff options
Diffstat (limited to 'modutils/insmod.c')
-rw-r--r-- | modutils/insmod.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/modutils/insmod.c b/modutils/insmod.c index f694329..7ed4cdb 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c @@ -988,6 +988,65 @@ arch_apply_relocation(struct obj_file *f, *loc += v - got; break; +#elif defined (__microblaze__) + case R_MICROBLAZE_NONE: + case R_MICROBLAZE_64_NONE: + case R_MICROBLAZE_32_SYM_OP_SYM: + case R_MICROBLAZE_32_PCREL: + break; + + case R_MICROBLAZE_64_PCREL: { + /* dot is the address of the current instruction. + * v is the target symbol address. + * So we need to extract the offset in the code, + * adding v, then subtrating the current address + * of this instruction. + * Ex: "IMM 0xFFFE bralid 0x0000" = "bralid 0xFFFE0000" + */ + + /* Get split offset stored in code */ + unsigned int temp = (loc[0] & 0xFFFF) << 16 | + (loc[1] & 0xFFFF); + + /* Adjust relative offset. -4 adjustment required + * because dot points to the IMM insn, but branch + * is computed relative to the branch instruction itself. + */ + temp += v - dot - 4; + + /* Store back into code */ + loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16; + loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF); + + break; + } + + case R_MICROBLAZE_32: + *loc += v; + break; + + case R_MICROBLAZE_64: { + /* Get split pointer stored in code */ + unsigned int temp1 = (loc[0] & 0xFFFF) << 16 | + (loc[1] & 0xFFFF); + + /* Add reloc offset */ + temp1+=v; + + /* Store back into code */ + loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16; + loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF); + + break; + } + + case R_MICROBLAZE_32_PCREL_LO: + case R_MICROBLAZE_32_LO: + case R_MICROBLAZE_SRO32: + case R_MICROBLAZE_SRW32: + ret = obj_reloc_unhandled; + break; + #elif defined(__mc68000__) case R_68K_NONE: |