diff options
-rw-r--r-- | lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp | 37 | ||||
-rw-r--r-- | lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 6 | ||||
-rw-r--r-- | test/MC/Mips/elf-bigendian.ll | 45 |
3 files changed, 75 insertions, 13 deletions
diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index d69570bdf0..7f5c3775b0 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -92,25 +92,42 @@ public: if (!Value) return; // Doesn't change encoding. + // Where do we start in the object unsigned Offset = Fixup.getOffset(); - // FIXME: The below code will not work across endian models - // How many bytes/bits are we fixing up? - unsigned NumBytes = ((getFixupKindInfo(Kind).TargetSize-1)/8)+1; - uint64_t Mask = ((uint64_t)1 << getFixupKindInfo(Kind).TargetSize) - 1; + // Number of bytes we need to fixup + unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8; + // Used to point to big endian bytes + unsigned FullSize; + + switch (Kind) { + case Mips::fixup_Mips_16: + FullSize = 2; + break; + case Mips::fixup_Mips_64: + FullSize = 8; + break; + default: + FullSize = 4; + break; + } // Grab current value, if any, from bits. uint64_t CurVal = 0; - for (unsigned i = 0; i != NumBytes; ++i) - CurVal |= ((uint8_t)Data[Offset + i]) << (i * 8); + for (unsigned i = 0; i != NumBytes; ++i) { + unsigned Idx = IsLittle ? i : (FullSize - 1 - i); + CurVal |= (uint64_t)((uint8_t)Data[Offset + Idx]) << (i*8); + } + + uint64_t Mask = ((uint64_t)(-1) >> (64 - getFixupKindInfo(Kind).TargetSize)); CurVal = (CurVal & ~Mask) | ((CurVal + Value) & Mask); - // Write out the bytes back to the code/data bits. - // First the unaffected bits and then the fixup. + // Write out the fixed up bytes back to the code/data bits. for (unsigned i = 0; i != NumBytes; ++i) { - Data[Offset + i] = uint8_t((CurVal >> (i * 8)) & 0xff); + unsigned Idx = IsLittle ? i : (FullSize - 1 - i); + Data[Offset + Idx] = (uint8_t)((CurVal >> (i*8)) & 0xff); } -} + } unsigned getNumFixupKinds() const { return Mips::NumTargetFixupKinds; } diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index b039678175..9ebb6d2569 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -49,9 +49,9 @@ public: void EmitInstruction(uint64_t Val, unsigned Size, raw_ostream &OS) const { // Output the instruction encoding in little endian byte order. - for (unsigned i = 0; i != Size; ++i) { - EmitByte(Val & 255, OS); - Val >>= 8; + for (unsigned i = 0; i < Size; ++i) { + unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8; + EmitByte((Val >> Shift) & 0xff, OS); } } diff --git a/test/MC/Mips/elf-bigendian.ll b/test/MC/Mips/elf-bigendian.ll new file mode 100644 index 0000000000..875ba3ba96 --- /dev/null +++ b/test/MC/Mips/elf-bigendian.ll @@ -0,0 +1,45 @@ +; RUN: llc -filetype=obj -mtriple mips-unknown-linux %s -o - | elf-dump --dump-section-data | FileCheck %s + +; Check that this is big endian. +; CHECK: ('e_indent[EI_DATA]', 0x02) + +; Make sure that a section table (text) entry is correct. +; CHECK: (('sh_name', 0x{{[0]*}}5) # '.text' +; CHECKNEXT: ('sh_type', 0x{{[0]*}}1) +; CHECKNEXT: ('sh_flags', 0x{{[0]*}}6) +; CHECKNEXT: ('sh_addr', 0x{{{[0-9,a-f]+}}) +; CHECKNEXT: ('sh_offset', 0x{{{[0-9,a-f]+}}) +; CHECKNEXT: ('sh_size', 0x{{{[0-9,a-f]+}}) +; CHECKNEXT: ('sh_link', 0x{{[0]+}}) +; CHECKNEXT: ('sh_info', 0x{{[0]+}}) +; CHECKNEXT: ('sh_addralign', 0x{{[0]*}}4) +; CHECKNEXT: ('sh_entsize', 0x{{[0]+}}) + +; See that at least first 3 instructions are correct: GP prologue +; CHECKNEXT: ('_section_data', '3c1c0000 279c0000 0399e021 {{[0-9,a-f]*}}') + +; ModuleID = '../br1.c' +target datalayout = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32" +target triple = "mips-unknown-linux" + +@x = global i32 1, align 4 +@str = private unnamed_addr constant [4 x i8] c"goo\00" +@str2 = private unnamed_addr constant [4 x i8] c"foo\00" + +define i32 @main() nounwind { +entry: + %0 = load i32* @x, align 4 + %tobool = icmp eq i32 %0, 0 + br i1 %tobool, label %if.end, label %foo + +if.end: ; preds = %entry + %puts = tail call i32 @puts(i8* getelementptr inbounds ([4 x i8]* @str, i32 0, i32 0)) + br label %foo + +foo: ; preds = %entry, %if.end + %puts2 = tail call i32 @puts(i8* getelementptr inbounds ([4 x i8]* @str2, i32 0, i32 0)) + ret i32 0 +} + +declare i32 @puts(i8* nocapture) nounwind + |