summaryrefslogtreecommitdiff
path: root/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp')
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp96
1 files changed, 53 insertions, 43 deletions
diff --git a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
index e3bdb3b140a8..b6dae9f6dea8 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
@@ -34,6 +34,15 @@ static cl::opt<bool> RoundSectionSizes(
cl::desc("Round section sizes up to the section alignment"), cl::Hidden);
} // end anonymous namespace
+static bool isMipsR6(const MCSubtargetInfo *STI) {
+ return STI->getFeatureBits()[Mips::FeatureMips32r6] ||
+ STI->getFeatureBits()[Mips::FeatureMips64r6];
+}
+
+static bool isMicroMips(const MCSubtargetInfo *STI) {
+ return STI->getFeatureBits()[Mips::FeatureMicroMips];
+}
+
MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S)
: MCTargetStreamer(S), GPReg(Mips::GP), ModuleDirectiveAllowed(true) {
GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
@@ -216,6 +225,19 @@ void MipsTargetStreamer::emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1,
emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI);
}
+void MipsTargetStreamer::emitRRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1,
+ unsigned Reg2, MCOperand Op3, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ MCInst TmpInst;
+ TmpInst.setOpcode(Opcode);
+ TmpInst.addOperand(MCOperand::createReg(Reg0));
+ TmpInst.addOperand(MCOperand::createReg(Reg1));
+ TmpInst.addOperand(MCOperand::createReg(Reg2));
+ TmpInst.addOperand(Op3);
+ TmpInst.setLoc(IDLoc);
+ getStreamer().EmitInstruction(TmpInst, *STI);
+}
+
void MipsTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1,
int16_t Imm, SMLoc IDLoc,
const MCSubtargetInfo *STI) {
@@ -264,8 +286,7 @@ void MipsTargetStreamer::emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc,
}
void MipsTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) {
- const FeatureBitset &Features = STI->getFeatureBits();
- if (Features[Mips::FeatureMicroMips])
+ if (isMicroMips(STI))
emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, STI);
else
emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
@@ -311,21 +332,34 @@ void MipsTargetStreamer::emitStoreWithImmOffset(
emitRRI(Opcode, SrcReg, ATReg, LoOffset, IDLoc, STI);
}
-/// Emit a store instruction with an symbol offset. Symbols are assumed to be
-/// out of range for a simm16 will be expanded to appropriate instructions.
-void MipsTargetStreamer::emitStoreWithSymOffset(
- unsigned Opcode, unsigned SrcReg, unsigned BaseReg, MCOperand &HiOperand,
- MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- // sw $8, sym => lui $at, %hi(sym)
- // sw $8, %lo(sym)($at)
+/// Emit a store instruction with an symbol offset.
+void MipsTargetStreamer::emitSCWithSymOffset(unsigned Opcode, unsigned SrcReg,
+ unsigned BaseReg,
+ MCOperand &HiOperand,
+ MCOperand &LoOperand,
+ unsigned ATReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ // sc $8, sym => lui $at, %hi(sym)
+ // sc $8, %lo(sym)($at)
// Generate the base address in ATReg.
emitRX(Mips::LUi, ATReg, HiOperand, IDLoc, STI);
- if (BaseReg != Mips::ZERO)
- emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);
- // Emit the store with the adjusted base and offset.
- emitRRX(Opcode, SrcReg, ATReg, LoOperand, IDLoc, STI);
+ if (!isMicroMips(STI) && isMipsR6(STI)) {
+ // For non-micromips r6 offset for 'sc' is not in the lower 16 bits so we
+ // put it in 'at'.
+ // sc $8, sym => lui $at, %hi(sym)
+ // addiu $at, $at, %lo(sym)
+ // sc $8, 0($at)
+ emitRRX(Mips::ADDiu, ATReg, ATReg, LoOperand, IDLoc, STI);
+ MCOperand Offset = MCOperand::createImm(0);
+ // Emit the store with the adjusted base and offset.
+ emitRRRX(Opcode, SrcReg, SrcReg, ATReg, Offset, IDLoc, STI);
+ } else {
+ if (BaseReg != Mips::ZERO)
+ emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);
+ // Emit the store with the adjusted base and offset.
+ emitRRRX(Opcode, SrcReg, SrcReg, ATReg, LoOperand, IDLoc, STI);
+ }
}
/// Emit a load instruction with an immediate offset. DstReg and TmpReg are
@@ -364,30 +398,6 @@ void MipsTargetStreamer::emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg,
emitRRI(Opcode, DstReg, TmpReg, LoOffset, IDLoc, STI);
}
-/// Emit a load instruction with an symbol offset. Symbols are assumed to be
-/// out of range for a simm16 will be expanded to appropriate instructions.
-/// DstReg and TmpReg are permitted to be the same register iff DstReg is a
-/// GPR. It is the callers responsibility to identify such cases and pass the
-/// appropriate register in TmpReg.
-void MipsTargetStreamer::emitLoadWithSymOffset(unsigned Opcode, unsigned DstReg,
- unsigned BaseReg,
- MCOperand &HiOperand,
- MCOperand &LoOperand,
- unsigned TmpReg, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- // 1) lw $8, sym => lui $8, %hi(sym)
- // lw $8, %lo(sym)($8)
- // 2) ldc1 $f0, sym => lui $at, %hi(sym)
- // ldc1 $f0, %lo(sym)($at)
-
- // Generate the base address in TmpReg.
- emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI);
- if (BaseReg != Mips::ZERO)
- emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
- // Emit the load with the adjusted base and offset.
- emitRRX(Opcode, DstReg, TmpReg, LoOperand, IDLoc, STI);
-}
-
MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S,
formatted_raw_ostream &OS)
: MipsTargetStreamer(S), OS(OS) {}
@@ -891,9 +901,9 @@ void MipsTargetELFStreamer::finish() {
MCSection &BSSSection = *OFI.getBSSSection();
MCA.registerSection(BSSSection);
- TextSection.setAlignment(std::max(16u, TextSection.getAlignment()));
- DataSection.setAlignment(std::max(16u, DataSection.getAlignment()));
- BSSSection.setAlignment(std::max(16u, BSSSection.getAlignment()));
+ TextSection.setAlignment(Align(std::max(16u, TextSection.getAlignment())));
+ DataSection.setAlignment(Align(std::max(16u, DataSection.getAlignment())));
+ BSSSection.setAlignment(Align(std::max(16u, BSSSection.getAlignment())));
if (RoundSectionSizes) {
// Make sections sizes a multiple of the alignment. This is useful for
@@ -1016,7 +1026,7 @@ void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) {
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Context);
MCA.registerSection(*Sec);
- Sec->setAlignment(4);
+ Sec->setAlignment(Align(4));
OS.PushSection();
@@ -1306,7 +1316,7 @@ void MipsTargetELFStreamer::emitMipsAbiFlags() {
MCSectionELF *Sec = Context.getELFSection(
".MIPS.abiflags", ELF::SHT_MIPS_ABIFLAGS, ELF::SHF_ALLOC, 24, "");
MCA.registerSection(*Sec);
- Sec->setAlignment(8);
+ Sec->setAlignment(Align(8));
OS.SwitchSection(Sec);
OS << ABIFlagsSection;