diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp --- a/lld/ELF/Arch/Hexagon.cpp +++ b/lld/ELF/Arch/Hexagon.cpp @@ -161,6 +161,13 @@ } } +static bool isDuplex(uint32_t insn) { + // 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. + return (0xC000 & insn) == 0; +} + 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 @@ -185,10 +192,7 @@ {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) + if (isDuplex(insn)) return 0x03f00000; for (InstructionMask i : r6) @@ -224,6 +228,9 @@ if ((0xff000000 & insn) == 0xb0000000) return 0x0fe03fe0; + if (isDuplex(insn)) + return 0x03f00000; + error("unrecognized instruction for R_HEX_16_X relocation: 0x" + utohexstr(insn)); return 0; diff --git a/lld/test/ELF/hexagon-shared.s b/lld/test/ELF/hexagon-shared.s --- a/lld/test/ELF/hexagon-shared.s +++ b/lld/test/ELF/hexagon-shared.s @@ -38,6 +38,11 @@ # R_HEX_GOT_16_X r0 = add(r1,##bar@GOT) +# R_HEX_GOT_16_X, duplex +{ r0 = add(r0,##bar@GOT) + memw(r0) = r2 } + + # foo is local so no plt will be generated foo: jumpr lr @@ -78,6 +83,7 @@ # TEXT: if (p0) jump:nt 0x102d0 # TEXT: r0 = #0 ; jump 0x102d0 # TEXT: r0 = add(r1,##-65548) +# TEXT: r0 = add(r0,##-65548); memw(r0+#0) = r2 } # GOT: .got: # GOT: 00 00 00 00 00000000