X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FARMAsmBackend.cpp;h=cb0c54386ed67e95d7663b157d773d7d5ef039cd;hb=c266600bec4b5ba0ee93ffdfeaafcab8f1295145;hp=28d902a553c9e3db178db32d4415eb5e65619762;hpb=cc78f5c09c451dd84ef5c4abdfcdadd4270a4942;p=oota-llvm.git diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp index 28d902a553c..cb0c54386ed 100644 --- a/lib/Target/ARM/ARMAsmBackend.cpp +++ b/lib/Target/ARM/ARMAsmBackend.cpp @@ -98,16 +98,29 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { Value = (Hi4 << 16) | (Lo12); return Value; } - case ARM::fixup_arm_ldst_pcrel_12: { - bool isAdd = true; + case ARM::fixup_arm_ldst_pcrel_12: // ARM PC-relative values are offset by 8. - Value -= 8; + Value -= 4; + // FALLTHROUGH + case ARM::fixup_t2_ldst_pcrel_12: { + // Offset by 4, adjusted by two due to the half-word ordering of thumb. + Value -= 4; + bool isAdd = true; if ((int64_t)Value < 0) { Value = -Value; isAdd = false; } assert ((Value < 4096) && "Out of range pc-relative fixup value!"); Value |= isAdd << 23; + + // Same addressing mode as fixup_arm_pcrel_10, + // but with 16-bit halfwords swapped. + if (Kind == ARM::fixup_t2_ldst_pcrel_12) { + uint64_t swapped = (Value & 0xFFFF0000) >> 16; + swapped |= (Value & 0x0000FFFF) << 16; + return swapped; + } + return Value; } case ARM::fixup_arm_adr_pcrel_12: { @@ -127,24 +140,100 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { // These values don't encode the low two bits since they're always zero. // Offset by 8 just as above. return 0xffffff & ((Value - 8) >> 2); + case ARM::fixup_t2_uncondbranch: { + Value = Value - 4; + Value >>= 1; // Low bit is not encoded. + + uint32_t out = 0; + bool I = Value & 0x800000; + bool J1 = Value & 0x400000; + bool J2 = Value & 0x200000; + J1 ^= I; + J2 ^= I; + + out |= I << 26; // S bit + out |= !J1 << 13; // J1 bit + out |= !J2 << 11; // J2 bit + out |= (Value & 0x1FF800) << 5; // imm6 field + out |= (Value & 0x0007FF); // imm11 field + + uint64_t swapped = (out & 0xFFFF0000) >> 16; + swapped |= (out & 0x0000FFFF) << 16; + return swapped; + } + case ARM::fixup_t2_condbranch: { + Value = Value - 4; + Value >>= 1; // Low bit is not encoded. + + uint64_t out = 0; + out |= (Value & 0x80000) << 7; // S bit + out |= (Value & 0x40000) >> 7; // J2 bit + out |= (Value & 0x20000) >> 4; // J1 bit + out |= (Value & 0x1F800) << 5; // imm6 field + out |= (Value & 0x007FF); // imm11 field + + uint32_t swapped = (out & 0xFFFF0000) >> 16; + swapped |= (out & 0x0000FFFF) << 16; + return swapped; + } case ARM::fixup_arm_thumb_bl: { // The value doesn't encode the low bit (always zero) and is offset by // four. The value is encoded into disjoint bit positions in the destination // opcode. x = unchanged, I = immediate value bit, S = sign extension bit - // xxxxxSIIIIIIIIII xxxxxIIIIIIIIIII + // + // BL: xxxxxSIIIIIIIIII xxxxxIIIIIIIIIII + // + // Note that the halfwords are stored high first, low second; so we need + // to transpose the fixup value here to map properly. + unsigned isNeg = (int64_t(Value) < 0) ? 1 : 0; + uint32_t Binary = 0; + Value = 0x3fffff & ((Value - 4) >> 1); + Binary = (Value & 0x7ff) << 16; // Low imm11 value. + Binary |= (Value & 0x1ffc00) >> 11; // High imm10 value. + Binary |= isNeg << 10; // Sign bit. + return Binary; + } + case ARM::fixup_arm_thumb_blx: { + // The value doesn't encode the low two bits (always zero) and is offset by + // four (see fixup_arm_thumb_cp). The value is encoded into disjoint bit + // positions in the destination opcode. x = unchanged, I = immediate value + // bit, S = sign extension bit, 0 = zero. + // + // BLX: xxxxxSIIIIIIIIII xxxxxIIIIIIIIII0 + // // Note that the halfwords are stored high first, low second; so we need // to transpose the fixup value here to map properly. - uint32_t Binary = 0x3fffff & ((Value - 4) >> 1); - Binary = ((Binary & 0x7ff) << 16) | (Binary >> 11); + unsigned isNeg = (int64_t(Value) < 0) ? 1 : 0; + uint32_t Binary = 0; + Value = 0xfffff & ((Value - 2) >> 2); + Binary = (Value & 0x3ff) << 17; // Low imm10L value. + Binary |= (Value & 0xffc00) >> 10; // High imm10H value. + Binary |= isNeg << 10; // Sign bit. return Binary; } case ARM::fixup_arm_thumb_cp: - // Offset by 4, and don't encode the low two bits. - return ((Value - 4) >> 2) & 0xff; - case ARM::fixup_t2_pcrel_10: - case ARM::fixup_arm_pcrel_10: { - // Offset by 8 just as above. - Value = Value - 8; + // Offset by 4, and don't encode the low two bits. Two bytes of that + // 'off by 4' is implicitly handled by the half-word ordering of the + // Thumb encoding, so we only need to adjust by 2 here. + return ((Value - 2) >> 2) & 0xff; + case ARM::fixup_arm_thumb_cb: { + // Offset by 4 and don't encode the lower bit, which is always 0. + uint32_t Binary = (Value - 4) >> 1; + return ((Binary & 0x20) << 9) | ((Binary & 0x1f) << 3); + } + case ARM::fixup_arm_thumb_br: + // Offset by 4 and don't encode the lower bit, which is always 0. + return ((Value - 4) >> 1) & 0x7ff; + case ARM::fixup_arm_thumb_bcc: + // Offset by 4 and don't encode the lower bit, which is always 0. + return ((Value - 4) >> 1) & 0xff; + case ARM::fixup_arm_pcrel_10: + Value = Value - 4; // ARM fixups offset by an additional word and don't + // need to adjust for the half-word ordering. + // Fall through. + case ARM::fixup_t2_pcrel_10: { + // Offset by 4, adjusted by two due to the half-word ordering of thumb. + Value = Value - 4; bool isAdd = true; if ((int64_t)Value < 0) { Value = -Value; @@ -154,15 +243,15 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { Value >>= 2; assert ((Value < 256) && "Out of range pc-relative fixup value!"); Value |= isAdd << 23; - + // Same addressing mode as fixup_arm_pcrel_10, // but with 16-bit halfwords swapped. if (Kind == ARM::fixup_t2_pcrel_10) { - uint64_t swapped = (Value & 0xFFFF0000) >> 16; + uint32_t swapped = (Value & 0xFFFF0000) >> 16; swapped |= (Value & 0x0000FFFF) << 16; return swapped; } - + return Value; } } @@ -248,9 +337,14 @@ static unsigned getFixupKindNumBytes(unsigned Kind) { default: llvm_unreachable("Unknown fixup kind!"); + case ARM::fixup_arm_thumb_bcc: case ARM::fixup_arm_thumb_cp: return 1; + case ARM::fixup_arm_thumb_br: + case ARM::fixup_arm_thumb_cb: + return 2; + case ARM::fixup_arm_ldst_pcrel_12: case ARM::fixup_arm_pcrel_10: case ARM::fixup_arm_adr_pcrel_12: @@ -258,8 +352,12 @@ static unsigned getFixupKindNumBytes(unsigned Kind) { return 3; case FK_Data_4: + case ARM::fixup_t2_ldst_pcrel_12: + case ARM::fixup_t2_condbranch: + case ARM::fixup_t2_uncondbranch: case ARM::fixup_t2_pcrel_10: case ARM::fixup_arm_thumb_bl: + case ARM::fixup_arm_thumb_blx: return 4; } }