STI);
// Load the $gp from the stack.
- createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
- IDLoc, Out, STI);
+ TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
} else
Warning(IDLoc, "no .cprestore used in PIC mode");
}
const MCSubtargetInfo *STI) {
MipsTargetStreamer &TOut = getTargetStreamer();
- // If the offset can not fit into 16 bits, we need to expand.
- if (!isInt<16>(StackOffset)) {
- MCInst MemInst;
- MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
- MemInst.addOperand(MCOperand::createReg(Mips::GP));
- MemInst.addOperand(MCOperand::createReg(Mips::SP));
- MemInst.addOperand(MCOperand::createImm(StackOffset));
- expandMemInst(MemInst, IDLoc, Out, STI, IsLoad, true /*HasImmOpnd*/);
+ if (IsLoad) {
+ TOut.emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, StackOffset,
+ Mips::GP, IDLoc, STI);
return;
}
- TOut.emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset,
- IDLoc, STI);
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return;
+
+ TOut.emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, StackOffset, ATReg,
+ IDLoc, STI);
}
unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
return false;
}
- // Store the $gp on the stack.
- if (getStreamer().isIntegratedAssemblerRequired()) {
- const MCSubtargetInfo &STI = getSTI();
- createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
- getStreamer(), &STI);
- }
+ unsigned ATReg = getATReg(Loc);
+ if (!ATReg)
+ return true;
- getTargetStreamer().emitDirectiveCpRestore(CpRestoreOffset);
+ getTargetStreamer().emitDirectiveCpRestore(CpRestoreOffset, ATReg, Loc, STI);
Parser.Lex(); // Consume the EndOfStatement.
return false;
}
void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {}
-void MipsTargetStreamer::emitDirectiveCpRestore(int Offset) {
+void MipsTargetStreamer::emitDirectiveCpRestore(int Offset, unsigned ATReg,
+ SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
forbidModuleDirective();
}
void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
}
-/// Emit a store instruction with an immediate offset. The immediate is
-/// expected to be out-of-range for a simm16 and will be expanded to
-/// appropriate instructions.
+/// Emit the $gp restore operation for .cprestore.
+void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, Offset, Mips::GP, IDLoc,
+ STI);
+}
+
+/// Emit a store instruction with an immediate offset.
void MipsTargetStreamer::emitStoreWithImmOffset(
unsigned Opcode, unsigned SrcReg, unsigned BaseReg, int64_t Offset,
unsigned ATReg, SMLoc IDLoc, const MCSubtargetInfo *STI) {
+ if (isInt<16>(Offset)) {
+ emitRRI(Opcode, SrcReg, BaseReg, Offset, IDLoc, STI);
+ return;
+ }
+
// sw $8, offset($8) => lui $at, %hi(offset)
// add $at, $at, $8
// sw $8, %lo(offset)($at)
emitRRX(Opcode, SrcReg, ATReg, LoOperand, IDLoc, STI);
}
-/// Emit a load instruction with an immediate offset. The immediate is expected
-/// to be out-of-range for a simm16 and will be expanded to appropriate
-/// instructions. DstReg and TmpReg are permitted to be the same register iff
-/// DstReg is distinct from BaseReg and DstReg is a GPR. It is the callers
-/// responsibility to identify such cases and pass the appropriate register in
-/// TmpReg.
+/// Emit a load instruction with an immediate offset. DstReg and TmpReg are
+/// permitted to be the same register iff DstReg is distinct from BaseReg and
+/// DstReg is a GPR. It is the callers responsibility to identify such cases
+/// and pass the appropriate register in TmpReg.
void MipsTargetStreamer::emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg,
unsigned BaseReg, int64_t Offset,
unsigned TmpReg, SMLoc IDLoc,
const MCSubtargetInfo *STI) {
+ if (isInt<16>(Offset)) {
+ emitRRI(Opcode, DstReg, BaseReg, Offset, IDLoc, STI);
+ return;
+ }
+
// 1) lw $8, offset($9) => lui $8, %hi(offset)
// add $8, $8, $9
// lw $8, %lo(offset)($9)
forbidModuleDirective();
}
-void MipsTargetAsmStreamer::emitDirectiveCpRestore(int Offset) {
- MipsTargetStreamer::emitDirectiveCpRestore(Offset);
+void MipsTargetAsmStreamer::emitDirectiveCpRestore(int Offset, unsigned ATReg,
+ SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer::emitDirectiveCpRestore(Offset, ATReg, IDLoc, STI);
OS << "\t.cprestore\t" << Offset << "\n";
}
forbidModuleDirective();
}
-void MipsTargetELFStreamer::emitDirectiveCpRestore(int Offset) {
- MipsTargetStreamer::emitDirectiveCpRestore(Offset);
+void MipsTargetELFStreamer::emitDirectiveCpRestore(int Offset, unsigned ATReg,
+ SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer::emitDirectiveCpRestore(Offset, ATReg, IDLoc, STI);
// .cprestore offset
// When PIC mode is enabled and the O32 ABI is used, this directive expands
// to:
if (!Pic || (getABI().IsN32() || getABI().IsN64()))
return;
- // FIXME: MipsAsmParser currently emits the instructions that should be
- // emitted here.
+ // Store the $gp on the stack.
+ emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, Offset, ATReg, IDLoc,
+ STI);
}
void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
// PIC support
virtual void emitDirectiveCpLoad(unsigned RegNo);
- virtual void emitDirectiveCpRestore(int Offset);
+ virtual void emitDirectiveCpRestore(int Offset, unsigned ATReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI);
virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
const MCSymbol &Sym, bool IsReg);
virtual void emitDirectiveCpreturn(unsigned SaveLocation,
MCOperand &HiOperand, MCOperand &LoOperand,
unsigned ATReg, SMLoc IDLoc,
const MCSubtargetInfo *STI);
+ void emitGPRestore(int Offset, SMLoc IDLoc, const MCSubtargetInfo *STI);
void forbidModuleDirective() { ModuleDirectiveAllowed = false; }
void reallowModuleDirective() { ModuleDirectiveAllowed = true; }
// PIC support
void emitDirectiveCpLoad(unsigned RegNo) override;
- void emitDirectiveCpRestore(int Offset) override;
+ void emitDirectiveCpRestore(int Offset, unsigned ATReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) override;
void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
const MCSymbol &Sym, bool IsReg) override;
void emitDirectiveCpreturn(unsigned SaveLocation,
// PIC support
void emitDirectiveCpLoad(unsigned RegNo) override;
- void emitDirectiveCpRestore(int Offset) override;
+ void emitDirectiveCpRestore(int Offset, unsigned ATReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) override;
void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
const MCSymbol &Sym, bool IsReg) override;
void emitDirectiveCpreturn(unsigned SaveLocation,