forked from OSchip/llvm-project
Add R_HEX_6_X relocation support
This is a larger patch. This relocation has irregular immediate masks that require a lookup to find the correct mask. Differential Revision: https://reviews.llvm.org/D50450 llvm-svn: 339332
This commit is contained in:
parent
79cf42e869
commit
17858207a0
|
@ -58,18 +58,62 @@ RelExpr Hexagon::getRelExpr(RelType Type, const Symbol &S,
|
|||
case R_HEX_B22_PCREL:
|
||||
case R_HEX_B22_PCREL_X:
|
||||
case R_HEX_B32_PCREL_X:
|
||||
case R_HEX_6_PCREL_X:
|
||||
return R_PC;
|
||||
default:
|
||||
return R_ABS;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t findMaskR6(uint32_t Insn) {
|
||||
// There are (arguably too) many relocation masks for the DSP's
|
||||
// R_HEX_6_X type. The table below is used to select the correct mask
|
||||
// for the given instruction.
|
||||
struct InstructionMask {
|
||||
uint32_t CmpMask;
|
||||
uint32_t RelocMask;
|
||||
};
|
||||
|
||||
static const InstructionMask R6[] = {
|
||||
{0x38000000, 0x0000201f}, {0x39000000, 0x0000201f},
|
||||
{0x3e000000, 0x00001f80}, {0x3f000000, 0x00001f80},
|
||||
{0x40000000, 0x000020f8}, {0x41000000, 0x000007e0},
|
||||
{0x42000000, 0x000020f8}, {0x43000000, 0x000007e0},
|
||||
{0x44000000, 0x000020f8}, {0x45000000, 0x000007e0},
|
||||
{0x46000000, 0x000020f8}, {0x47000000, 0x000007e0},
|
||||
{0x6a000000, 0x00001f80}, {0x7c000000, 0x001f2000},
|
||||
{0x9a000000, 0x00000f60}, {0x9b000000, 0x00000f60},
|
||||
{0x9c000000, 0x00000f60}, {0x9d000000, 0x00000f60},
|
||||
{0x9f000000, 0x001f0100}, {0xab000000, 0x0000003f},
|
||||
{0xad000000, 0x0000003f}, {0xaf000000, 0x00030078},
|
||||
{0xd7000000, 0x006020e0}, {0xd8000000, 0x006020e0},
|
||||
{0xdb000000, 0x006020e0}, {0xdf000000, 0x006020e0}};
|
||||
|
||||
// Duplex forms have a fixed mask and parse bits 15:14 are always
|
||||
// zero. Non-duplex insns will always have at least one bit set in the
|
||||
// parse field.
|
||||
if ((0xC000 & Insn) == 0x0)
|
||||
return 0x03f00000;
|
||||
|
||||
for (InstructionMask I : R6)
|
||||
if ((0xff000000 & Insn) == I.CmpMask)
|
||||
return I.RelocMask;
|
||||
|
||||
error("unrecognized instruction for R_HEX_6 relocation: 0x" +
|
||||
utohexstr(Insn));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); }
|
||||
|
||||
void Hexagon::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
|
||||
switch (Type) {
|
||||
case R_HEX_NONE:
|
||||
break;
|
||||
case R_HEX_6_PCREL_X:
|
||||
case R_HEX_6_X:
|
||||
or32le(Loc, applyMask(findMaskR6(read32le(Loc)), Val));
|
||||
break;
|
||||
case R_HEX_12_X:
|
||||
or32le(Loc, applyMask(0x000007e0, Val));
|
||||
break;
|
||||
|
|
|
@ -29,3 +29,125 @@ call #_start
|
|||
call ##_start
|
||||
# CHECK: immext(#4294967232)
|
||||
# CHECK: call 0x11000
|
||||
|
||||
# R_HEX_6_X tests:
|
||||
# One test for each mask in the lookup table.
|
||||
|
||||
#0x38000000
|
||||
if (!P0) memw(r0+#8)=##_start
|
||||
# CHECK: 38c0c100 if (!p0) memw(r0+#8) = ##69632 }
|
||||
|
||||
#0x39000000
|
||||
{ p0 = p1
|
||||
if (!P0.new) memw(r0+#0)=##_start }
|
||||
# CHECK: 39c0c000 if (!p0.new) memw(r0+#0) = ##69632 }
|
||||
|
||||
#0x3e000000
|
||||
memw(r0+##_start)+=r1
|
||||
# CHECK: 3e40c001 memw(r0+##69632) += r1 }
|
||||
|
||||
#0x3f000000
|
||||
memw(r0+##_start)+=#4
|
||||
# CHECK: 3f40c004 memw(r0+##69632) += #4 }
|
||||
|
||||
#0x40000000
|
||||
{ r0 = r1
|
||||
if (p0) memb(r0+##_start)=r0.new }
|
||||
# CHECK: 40a0c200 if (p0) memb(r0+##69632) = r0.new }
|
||||
|
||||
#0x41000000
|
||||
if (p0) r0=memb(r1+##_start)
|
||||
# CHECK: 4101c000 if (p0) r0 = memb(r1+##69632) }
|
||||
|
||||
#0x42000000
|
||||
{ r0 = r1
|
||||
p0 = p1
|
||||
if (p0.new) memb(r0+##_start)=r0.new }
|
||||
# CHECK: 42a0c200 if (p0.new) memb(r0+##69632) = r0.new }
|
||||
|
||||
#0x43000000
|
||||
{ p0 = p1
|
||||
if (P0.new) r0=memb(r0+##_start) }
|
||||
# CHECK: 4300c000 if (p0.new) r0 = memb(r0+##69632) }
|
||||
|
||||
#0x44000000
|
||||
if (!p0) memb(r0+##_start)=r1
|
||||
# CHECK: 4400c100 if (!p0) memb(r0+##69632) = r1 }
|
||||
|
||||
#0x45000000
|
||||
if (!p0) r0=memb(r1+##_start)
|
||||
# CHECK: 4501c000 if (!p0) r0 = memb(r1+##69632) }
|
||||
|
||||
#0x46000000
|
||||
{ p0 = p1
|
||||
if (!p0.new) memb(r0+##_start)=r1 }
|
||||
# CHECK: 4600c100 if (!p0.new) memb(r0+##69632) = r1 }
|
||||
|
||||
#0x47000000
|
||||
{ p0 = p1
|
||||
if (!p0.new) r0=memb(r1+##_start) }
|
||||
# CHECK: 4701c000 if (!p0.new) r0 = memb(r1+##69632) }
|
||||
|
||||
#0x6a000000 -- Note 4294967132 == -0xa4 the distance between
|
||||
# here and _start, so this will change if
|
||||
# tests are added between here and _start
|
||||
r0=add(pc,##_start@pcrel)
|
||||
# CHECK: 6a49ce00 r0 = add(pc,##4294967132) }
|
||||
|
||||
#0x7c000000
|
||||
r1:0=combine(#8,##_start)
|
||||
# CHECK: 7c80c100 r1:0 = combine(#8,##69632) }
|
||||
|
||||
#0x9a000000
|
||||
r1:0=memb_fifo(r2=##_start)
|
||||
# CHECK: 9a82d000 r1:0 = memb_fifo(r2=##69632) }
|
||||
|
||||
#0x9b000000
|
||||
r0=memb(r1=##_start)
|
||||
# CHECK: 9b01d000 r0 = memb(r1=##69632) }
|
||||
|
||||
#0x9c000000
|
||||
r1:0=memb_fifo(r2<<#2+##_start)
|
||||
# CHECK: 9c82f000 r1:0 = memb_fifo(r2<<#2+##69632) }
|
||||
|
||||
#0x9d000000
|
||||
r0=memb(r1<<#2+##_start)
|
||||
# CHECK: 9d01f000 r0 = memb(r1<<#2+##69632) }
|
||||
|
||||
#0x9f000000
|
||||
if (!p0) r0=memb(##_start)
|
||||
# CHECK: 9f00e880 if (!p0) r0 = memb(##69632) }
|
||||
|
||||
#0xab000000
|
||||
memb(r0=##_start)=r1
|
||||
# CHECK: ab00c180 memb(r0=##69632) = r1 }
|
||||
|
||||
#0xad000000
|
||||
memb(r0<<#2+##_start)=r1
|
||||
# CHECK: ad00e180 memb(r0<<#2+##69632) = r1 }
|
||||
|
||||
#0xaf000000
|
||||
if (!p0) memb(##_start)=r1
|
||||
# CHECK: af00c184 if (!p0) memb(##69632) = r1 }
|
||||
|
||||
#0xd7000000
|
||||
r0=add(##_start,mpyi(r1,r2))
|
||||
# CHECK: d701c200 r0 = add(##69632,mpyi(r1,r2)) }
|
||||
|
||||
#0xd8000000
|
||||
R0=add(##_start,mpyi(r0,#2))
|
||||
# CHECK: d800c002 r0 = add(##69632,mpyi(r0,#2)) }
|
||||
|
||||
#0xdb000000
|
||||
r0=add(r1,add(r2,##_start))
|
||||
# CHECK: db01c002 r0 = add(r1,add(r2,##69632)) }
|
||||
|
||||
#0xdf000000
|
||||
r0=add(r1,mpyi(r2,##_start))
|
||||
# CHECK: df82c001 r0 = add(r1,mpyi(r2,##69632)) }
|
||||
|
||||
# Duplex form of R_HEX_6_X
|
||||
# R_HEX_32_6_X
|
||||
# R_HEX_6_X
|
||||
{ r0 = ##_start; r2 = r16 }
|
||||
# CHECK: 28003082 r0 = ##69632; r2 = r16 }
|
||||
|
|
Loading…
Reference in New Issue