diff options
-rw-r--r-- | lib/Target/Mips/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Target/Mips/MipsAsmPrinter.cpp | 34 | ||||
-rw-r--r-- | lib/Target/Mips/MipsDirectObjLower.cpp | 86 | ||||
-rw-r--r-- | lib/Target/Mips/MipsDirectObjLower.h | 28 | ||||
-rw-r--r-- | lib/Target/Mips/MipsMCInstLower.cpp | 68 | ||||
-rw-r--r-- | lib/Target/Mips/MipsMCInstLower.h | 2 |
6 files changed, 124 insertions, 95 deletions
diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index f535c504db..0f84358e26 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -21,6 +21,7 @@ add_llvm_target(MipsCodeGen MipsAsmPrinter.cpp MipsCodeEmitter.cpp MipsDelaySlotFiller.cpp + MipsDirectObjLower.cpp MipsELFWriterInfo.cpp MipsJITInfo.cpp MipsInstrInfo.cpp diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index e4db9915f0..8057f9811e 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -15,6 +15,7 @@ #define DEBUG_TYPE "mips-asm-printer" #include "Mips.h" #include "MipsAsmPrinter.h" +#include "MipsDirectObjLower.h" #include "MipsInstrInfo.h" #include "MipsMCInstLower.h" #include "InstPrinter/MipsInstPrinter.h" @@ -63,42 +64,25 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { do { MCInst TmpInst0; + MCInstLowering.Lower(I++, TmpInst0); // Direct object specific instruction lowering - if (!OutStreamer.hasRawTextSupport()) - switch (I->getOpcode()) { + if (!OutStreamer.hasRawTextSupport()){ + switch (TmpInst0.getOpcode()) { // If shift amount is >= 32 it the inst needs to be lowered further case Mips::DSLL: case Mips::DSRL: case Mips::DSRA: - { - assert(I->getNumOperands() == 3 && - "Invalid no. of machine operands for shift!"); - assert(I->getOperand(2).isImm()); - int64_t Shift = I->getOperand(2).getImm(); - if (Shift > 31) { - MCInst TmpInst0; - MCInstLowering.LowerLargeShift(I, TmpInst0, Shift - 32); - OutStreamer.EmitInstruction(TmpInst0); - return; - } - } - break; - // Double extract instruction is chosen by pos and size operands + Mips::LowerLargeShift(TmpInst0); + break; + // Double extract instruction is chosen by pos and size operands case Mips::DEXT: case Mips::DINS: - assert(Subtarget->hasMips64() && "DEXT/DINS are MIPS64 instructions"); - { - MCInst TmpInst0; - MCInstLowering.LowerDextDins(I, TmpInst0); - OutStreamer.EmitInstruction(TmpInst0); - return; - } + Mips::LowerDextDins(TmpInst0); } + } - MCInstLowering.Lower(I++, TmpInst0); OutStreamer.EmitInstruction(TmpInst0); - } while ((I != E) && I->isInsideBundle()); // Delay slot check } diff --git a/lib/Target/Mips/MipsDirectObjLower.cpp b/lib/Target/Mips/MipsDirectObjLower.cpp new file mode 100644 index 0000000000..0d74db808c --- /dev/null +++ b/lib/Target/Mips/MipsDirectObjLower.cpp @@ -0,0 +1,86 @@ +//===-- MipsDirectObjLower.cpp - Mips LLVM direct object lowering -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains code to lower Mips MCInst records that are normally +// left to the assembler to lower such as large shifts. +// +//===----------------------------------------------------------------------===// +#include "MipsDirectObjLower.h" +#include "MipsInstrInfo.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCStreamer.h" + +using namespace llvm; + +// If the D<shift> instruction has a shift amount that is greater +// than 31 (checked in calling routine), lower it to a D<shift>32 instruction +void Mips::LowerLargeShift(MCInst& Inst) { + + assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!"); + assert(Inst.getOperand(2).isImm()); + + bool isLarge = false; + int64_t Shift; + Shift = Inst.getOperand(2).getImm(); + if (Shift > 31) { + Shift -= 32; + isLarge = true; + } + + // saminus32 + (Inst.getOperand(2)).setImm(Shift); + + if (isLarge) + switch (Inst.getOpcode()) { + default: + // Calling function is not synchronized + llvm_unreachable("Unexpected shift instruction"); + case Mips::DSLL: + Inst.setOpcode(Mips::DSLL32); + return; + case Mips::DSRL: + Inst.setOpcode(Mips::DSRL32); + return; + case Mips::DSRA: + Inst.setOpcode(Mips::DSRA32); + return; + } +} + +// Pick a DEXT or DINS instruction variant based on the pos and size operands +void Mips::LowerDextDins(MCInst& InstIn) { + int Opcode = InstIn.getOpcode(); + + if (Opcode == Mips::DEXT) + assert(InstIn.getNumOperands() == 4 && + "Invalid no. of machine operands for DEXT!"); + else // Only DEXT and DINS are possible + assert(InstIn.getNumOperands() == 5 && + "Invalid no. of machine operands for DINS!"); + + assert(InstIn.getOperand(2).isImm()); + int64_t pos = InstIn.getOperand(2).getImm(); + assert(InstIn.getOperand(3).isImm()); + int64_t size = InstIn.getOperand(3).getImm(); + + if (size <= 32) { + if ((pos < 32)) { // DEXT/DINS, do nothing + return; + } else { // DEXTU/DINSU + InstIn.getOperand(2).setImm(pos - 32); + InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU); + return; + } + } else { // DEXTM/DINSM + assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32"); + InstIn.getOperand(3).setImm(size - 32); + InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM); + return; + } +} diff --git a/lib/Target/Mips/MipsDirectObjLower.h b/lib/Target/Mips/MipsDirectObjLower.h new file mode 100644 index 0000000000..8813cc9ac7 --- /dev/null +++ b/lib/Target/Mips/MipsDirectObjLower.h @@ -0,0 +1,28 @@ +//===-- MipsDirectObjLower.h - Mips LLVM direct object lowering *- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef MIPSDIRECTOBJLOWER_H +#define MIPSDIRECTOBJLOWER_H +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + class MCInst; + class MCStreamer; + + namespace Mips { + /// MipsDirectObjLower - This name space is used to lower MCInstr in cases + // where the assembler usually finishes the lowering + // such as large shifts. + void LowerLargeShift(MCInst &Inst); + void LowerDextDins(MCInst &Inst); + } +} + +#endif diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp index 674bce30a5..5fa6339338 100644 --- a/lib/Target/Mips/MipsMCInstLower.cpp +++ b/lib/Target/Mips/MipsMCInstLower.cpp @@ -160,71 +160,3 @@ void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { } } -// If the D<shift> instruction has a shift amount that is greater -// than 31 (checked in calling routine), lower it to a D<shift>32 instruction -void MipsMCInstLower::LowerLargeShift(const MachineInstr *MI, - MCInst& Inst, - int64_t Shift) { - // rt - Inst.addOperand(LowerOperand(MI->getOperand(0))); - // rd - Inst.addOperand(LowerOperand(MI->getOperand(1))); - // saminus32 - Inst.addOperand(MCOperand::CreateImm(Shift)); - - switch (MI->getOpcode()) { - default: - // Calling function is not synchronized - llvm_unreachable("Unexpected shift instruction"); - break; - case Mips::DSLL: - Inst.setOpcode(Mips::DSLL32); - break; - case Mips::DSRL: - Inst.setOpcode(Mips::DSRL32); - break; - case Mips::DSRA: - Inst.setOpcode(Mips::DSRA32); - break; - } -} - -// Pick a DEXT or DINS instruction variant based on the pos and size operands -void MipsMCInstLower::LowerDextDins(const MachineInstr *MI, MCInst& Inst) { - int Opcode = MI->getOpcode(); - - if (Opcode == Mips::DEXT) - assert(MI->getNumOperands() == 4 && - "Invalid no. of machine operands for DEXT!"); - else // Only DEXT and DINS are possible - assert(MI->getNumOperands() == 5 && - "Invalid no. of machine operands for DINS!"); - - assert(MI->getOperand(2).isImm()); - int64_t pos = MI->getOperand(2).getImm(); - assert(MI->getOperand(3).isImm()); - int64_t size = MI->getOperand(3).getImm(); - - // rt - Inst.addOperand(LowerOperand(MI->getOperand(0))); - // rs - Inst.addOperand(LowerOperand(MI->getOperand(1))); - - if (size <= 32) { - if ((pos < 32)) { // DEXT/DINS - Inst.addOperand(MCOperand::CreateImm(pos)); - Inst.addOperand(MCOperand::CreateImm(size)); - Inst.setOpcode(Opcode); - } else { // DEXTU/DINSU - Inst.addOperand(MCOperand::CreateImm(pos - 32)); - Inst.addOperand(MCOperand::CreateImm(size)); - Inst.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU); - } - } else { // DEXTM/DINSM - assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32"); - Inst.addOperand(MCOperand::CreateImm(pos)); - Inst.addOperand(MCOperand::CreateImm(size - 32)); - Inst.setOpcode(Mips::DEXTM); - Inst.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM); - } -} diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h index c1fe697a20..3eab5a452e 100644 --- a/lib/Target/Mips/MipsMCInstLower.h +++ b/lib/Target/Mips/MipsMCInstLower.h @@ -33,8 +33,6 @@ public: MipsMCInstLower(MipsAsmPrinter &asmprinter); void Initialize(Mangler *mang, MCContext *C); void Lower(const MachineInstr *MI, MCInst &OutMI) const; - void LowerLargeShift(const MachineInstr *MI, MCInst &Inst, int64_t Shift); - void LowerDextDins(const MachineInstr *MI, MCInst &Inst); private: MCOperand LowerSymbolOperand(const MachineOperand &MO, |