aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Carter <jack.carter@imgtec.com>2013-04-25 23:31:35 +0000
committerJack Carter <jack.carter@imgtec.com>2013-04-25 23:31:35 +0000
commit97265a48895a2cda7f04e47bfe935c4fdd71f8ae (patch)
tree10ee6dbec49767b76962179da183607488d8f85e
parent0fc7137f2f8a99cb749024c51e3247f4b24e1ee0 (diff)
downloadexternal_llvm-97265a48895a2cda7f04e47bfe935c4fdd71f8ae.zip
external_llvm-97265a48895a2cda7f04e47bfe935c4fdd71f8ae.tar.gz
external_llvm-97265a48895a2cda7f04e47bfe935c4fdd71f8ae.tar.bz2
Mips assembler: .set reorder support
Mips have delayslots for certain instructions like jumps and branches. These are instructions that follow the branch or jump and are executed before the jump or branch is completed. Early Mips compilers could not cope with delayslots and left them up to the assembler. The assembler would fill the delayslots with the appropriate instruction, usually just a nop to allow correct runtime behavior. The default behavior for this is set with .set reorder. To tell the assembler that you don't want it to mess with the delayslot one used .set noreorder. For backwards compatibility we need to support .set reorder and have it be the default behavior in the assembler. Our support for it is to insert a NOP directly after an instruction with a delayslot when in .set reorder mode. Contributer: Vladimir Medic git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180584 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/Mips/AsmParser/MipsAsmParser.cpp13
-rw-r--r--test/MC/Mips/mips_directives.s18
2 files changed, 31 insertions, 0 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index befc573..0795cb9 100644
--- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -418,6 +418,19 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions) {
const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Inst.setLoc(IDLoc);
+ if (MCID.hasDelaySlot() && Options.isReorder()) {
+ // If this instruction has a delay slot and .set reorder is active,
+ // emit a NOP after it.
+ Instructions.push_back(Inst);
+ MCInst NopInst;
+ NopInst.setOpcode(Mips::SLL);
+ NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
+ NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
+ NopInst.addOperand(MCOperand::CreateImm(0));
+ Instructions.push_back(NopInst);
+ return false;
+ }
+
if (MCID.mayLoad() || MCID.mayStore()) {
// Check the offset of memory operand, if it is a symbol
// reference or immediate we may have to expand instructions.
diff --git a/test/MC/Mips/mips_directives.s b/test/MC/Mips/mips_directives.s
index df7e645..45247cd 100644
--- a/test/MC/Mips/mips_directives.s
+++ b/test/MC/Mips/mips_directives.s
@@ -1,11 +1,20 @@
# RUN: llvm-mc -show-encoding -triple mips-unknown-unknown %s | FileCheck %s
#
+# CHECK: .text
+# CHECK: $BB0_2:
$BB0_2:
.ent directives_test
.frame $sp,0,$ra
.mask 0x00000000,0
.fmask 0x00000000,0
+# CHECK: b 1332 # encoding: [0x10,0x00,0x01,0x4d]
+# CHECK: j 1328 # encoding: [0x08,0x00,0x01,0x4c]
+# CHECK: jal 1328 # encoding: [0x0c,0x00,0x01,0x4c]
+
.set noreorder
+ b 1332
+ j 1328
+ jal 1328
.set nomacro
.set noat
$JTI0_0:
@@ -15,7 +24,16 @@ $JTI0_0:
# CHECK-NEXT: .4byte 2013265916
.set at=$12
.set macro
+# CHECK: b 1332 # encoding: [0x10,0x00,0x01,0x4d]
+# CHECK: nop # encoding: [0x00,0x00,0x00,0x00]
+# CHECK: j 1328 # encoding: [0x08,0x00,0x01,0x4c]
+# CHECK: nop # encoding: [0x00,0x00,0x00,0x00]
+# CHECK: jal 1328 # encoding: [0x0c,0x00,0x01,0x4c]
+# CHECK: nop # encoding: [0x00,0x00,0x00,0x00]
.set reorder
+ b 1332
+ j 1328
+ jal 1328
.set at=$a0
.set STORE_MASK,$t7
.set FPU_MASK,$f7