There are some Mips instructions that are lowered by the

assembler such as shifts greater than 32. In the case 
of direct object, the code gen needs to do this lowering 
since the assembler is not involved.

With the advent of the llvm-mc assembler, it also needs 
to do the same lowering.

This patch makes that specific lowering code accessible 
to both the direct object output and the assembler.

This patch does not affect generated output.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163287 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jack Carter 2012-09-06 02:31:34 +00:00
parent 557a20a234
commit a7570a3d86
6 changed files with 124 additions and 95 deletions

View File

@ -21,6 +21,7 @@ add_llvm_target(MipsCodeGen
MipsAsmPrinter.cpp
MipsCodeEmitter.cpp
MipsDelaySlotFiller.cpp
MipsDirectObjLower.cpp
MipsELFWriterInfo.cpp
MipsJITInfo.cpp
MipsInstrInfo.cpp

View File

@ -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
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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,