summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoran Jovanovic <zoran.jovanovic@imgtec.com>2014-04-03 12:01:01 +0000
committerZoran Jovanovic <zoran.jovanovic@imgtec.com>2014-04-03 12:01:01 +0000
commit60f5dfea66f8ad2a3fffe559567ff8dd7c382898 (patch)
treefdd03da0c662f7b676dce358a9ddf902a45b8c1b
parentbadb1377291e99cea122b64ee62fa0382e9ee737 (diff)
downloadllvm-60f5dfea66f8ad2a3fffe559567ff8dd7c382898.tar.gz
llvm-60f5dfea66f8ad2a3fffe559567ff8dd7c382898.tar.bz2
llvm-60f5dfea66f8ad2a3fffe559567ff8dd7c382898.tar.xz
MicroMIPS specific little endian fixup data byte ordering.
Differential Revision: http://llvm-reviews.chandlerc.com/D3245 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205528 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp26
-rw-r--r--test/MC/Mips/micromips-el-fixup-data.s25
2 files changed, 49 insertions, 2 deletions
diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
index 541f8b6f91..0f99ecc548 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
@@ -112,6 +112,22 @@ MCObjectWriter *MipsAsmBackend::createObjectWriter(raw_ostream &OS) const {
MCELFObjectTargetWriter::getOSABI(OSType), IsLittle, Is64Bit);
}
+// Little-endian fixup data byte ordering:
+// mips32r2: a | b | x | x
+// microMIPS: x | x | a | b
+
+static bool needsMMLEByteOrder(unsigned Kind) {
+ return Kind >= Mips::fixup_MICROMIPS_26_S1 &&
+ Kind < Mips::LastTargetFixupKind;
+}
+
+// Calculate index for microMIPS specific little endian byte order
+static unsigned calculateMMLEIndex(unsigned i) {
+ assert(i <= 3 && "Index out of range!");
+
+ return (1 - i / 2) * 2 + i % 2;
+}
+
/// ApplyFixup - Apply the \p Value for given \p Fixup into the provided
/// data fragment, at the offset specified by the fixup and following the
/// fixup kind as appropriate.
@@ -149,8 +165,12 @@ void MipsAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
// Grab current value, if any, from bits.
uint64_t CurVal = 0;
+ bool microMipsLEByteOrder = needsMMLEByteOrder((unsigned) Kind);
+
for (unsigned i = 0; i != NumBytes; ++i) {
- unsigned Idx = IsLittle ? i : (FullSize - 1 - i);
+ unsigned Idx = IsLittle ? (microMipsLEByteOrder ? calculateMMLEIndex(i)
+ : i)
+ : (FullSize - 1 - i);
CurVal |= (uint64_t)((uint8_t)Data[Offset + Idx]) << (i*8);
}
@@ -160,7 +180,9 @@ void MipsAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
// Write out the fixed up bytes back to the code/data bits.
for (unsigned i = 0; i != NumBytes; ++i) {
- unsigned Idx = IsLittle ? i : (FullSize - 1 - i);
+ unsigned Idx = IsLittle ? (microMipsLEByteOrder ? calculateMMLEIndex(i)
+ : i)
+ : (FullSize - 1 - i);
Data[Offset + Idx] = (uint8_t)((CurVal >> (i*8)) & 0xff);
}
}
diff --git a/test/MC/Mips/micromips-el-fixup-data.s b/test/MC/Mips/micromips-el-fixup-data.s
new file mode 100644
index 0000000000..2293f63d46
--- /dev/null
+++ b/test/MC/Mips/micromips-el-fixup-data.s
@@ -0,0 +1,25 @@
+# RUN: llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 \
+# RUN: -mattr=+micromips 2>&1 -filetype=obj > %t.o
+# RUN: llvm-objdump %t.o -triple mipsel -mattr=+micromips -d | FileCheck %s
+
+# Check that fixup data is writen in the microMIPS specific little endian
+# byte order.
+
+ .text
+ .globl main
+ .align 2
+ .type main,@function
+ .set micromips
+ .set nomips16
+ .ent main
+main:
+ addiu $sp, $sp, -16
+ bnez $9, lab1
+
+# CHECK: 09 b4 04 00 bne $9, $zero, 8
+
+ addu $zero, $zero, $zero
+lab1:
+ jr $ra
+ addiu $sp, $sp, 16
+ .end main