1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 04:32:44 +01:00

[mips] Implement .cpadd directive

This directive inserts code to add $gp to the argument's register when
support for position independent code is enabled.

For example, this code:
  .cpadd $4
expands to:
  addu $4, $4, $gp
This commit is contained in:
Simon Atanasyan 2020-03-22 20:20:00 +03:00
parent d2c968e63d
commit 01b3e42958
5 changed files with 93 additions and 0 deletions

View File

@ -361,6 +361,7 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseSetArchDirective();
bool parseSetFeature(uint64_t Feature);
bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
bool parseDirectiveCpAdd(SMLoc Loc);
bool parseDirectiveCpLoad(SMLoc Loc);
bool parseDirectiveCpLocal(SMLoc Loc);
bool parseDirectiveCpRestore(SMLoc Loc);
@ -7632,6 +7633,31 @@ bool MipsAsmParser::isPicAndNotNxxAbi() {
return inPicMode() && !(isABI_N32() || isABI_N64());
}
bool MipsAsmParser::parseDirectiveCpAdd(SMLoc Loc) {
SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
OperandMatchResultTy ResTy = parseAnyRegister(Reg);
if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
reportParseError("expected register");
return false;
}
MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
if (!RegOpnd.isGPRAsmReg()) {
reportParseError(RegOpnd.getStartLoc(), "invalid register");
return false;
}
// If this is not the end of the statement, report an error.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token, expected end of statement");
return false;
}
getParser().Lex(); // Consume the EndOfStatement.
getTargetStreamer().emitDirectiveCpAdd(RegOpnd.getGPR32Reg());
return false;
}
bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
if (AssemblerOptions.back()->isReorder())
Warning(Loc, ".cpload should be inside a noreorder section");
@ -8544,6 +8570,10 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
MCAsmParser &Parser = getParser();
StringRef IDVal = DirectiveID.getString();
if (IDVal == ".cpadd") {
parseDirectiveCpAdd(DirectiveID.getLoc());
return false;
}
if (IDVal == ".cpload") {
parseDirectiveCpLoad(DirectiveID.getLoc());
return false;

View File

@ -111,6 +111,7 @@ void MipsTargetStreamer::emitDirectiveSetDspr2() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetMips3D() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetNoMips3D() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveCpAdd(unsigned RegNo) {}
void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {}
void MipsTargetStreamer::emitDirectiveCpLocal(unsigned RegNo) {
// .cplocal $reg
@ -662,6 +663,12 @@ void MipsTargetAsmStreamer::emitFMask(unsigned FPUBitmask,
OS << "," << FPUTopSavedRegOff << '\n';
}
void MipsTargetAsmStreamer::emitDirectiveCpAdd(unsigned RegNo) {
OS << "\t.cpadd\t$"
<< StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";
forbidModuleDirective();
}
void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) {
OS << "\t.cpload\t$"
<< StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";
@ -1120,6 +1127,17 @@ void MipsTargetELFStreamer::emitFMask(unsigned FPUBitmask,
FPROffset = FPUTopSavedRegOff;
}
void MipsTargetELFStreamer::emitDirectiveCpAdd(unsigned RegNo) {
// .cpadd $reg
// This directive inserts code to add $gp to the argument's register
// when support for position independent code is enabled.
if (!Pic)
return;
emitAddu(RegNo, RegNo, GPReg, getABI().IsN64(), &STI);
forbidModuleDirective();
}
void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {
// .cpload $reg
// This directive expands to:

View File

@ -92,6 +92,7 @@ public:
virtual void emitDirectiveSetHardFloat();
// PIC support
virtual void emitDirectiveCpAdd(unsigned RegNo);
virtual void emitDirectiveCpLoad(unsigned RegNo);
virtual void emitDirectiveCpLocal(unsigned RegNo);
virtual bool emitDirectiveCpRestore(int Offset,
@ -273,6 +274,7 @@ public:
void emitDirectiveSetHardFloat() override;
// PIC support
void emitDirectiveCpAdd(unsigned RegNo) override;
void emitDirectiveCpLoad(unsigned RegNo) override;
void emitDirectiveCpLocal(unsigned RegNo) override;
@ -345,6 +347,7 @@ public:
void emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) override;
// PIC support
void emitDirectiveCpAdd(unsigned RegNo) override;
void emitDirectiveCpLoad(unsigned RegNo) override;
void emitDirectiveCpLocal(unsigned RegNo) override;
bool emitDirectiveCpRestore(int Offset, function_ref<unsigned()> GetATReg,

13
test/MC/Mips/cpadd-bad.s Normal file
View File

@ -0,0 +1,13 @@
# RUN: not llvm-mc -triple=mips-unknown-linux-gnu %s 2>&1 | FileCheck %s
# RUN: not llvm-mc -triple=mips64-unknown-linux-gnuabin32 %s 2>&1 | FileCheck %s
# RUN: not llvm-mc -triple=mips64-unknown-linux-gnu %s 2>&1 | FileCheck %s
.text
.cpadd $32
# CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: invalid register
.cpadd $foo
# CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: expected register
.cpadd bar
# CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: expected register
.cpadd $25 foobar
# CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: unexpected token, expected end of statement

29
test/MC/Mips/cpadd.s Normal file
View File

@ -0,0 +1,29 @@
# RUN: llvm-mc -triple=mips-unknown-linux-gnu -position-independent %s \
# RUN: | FileCheck -check-prefix=ASM %s
# RUN: llvm-mc -triple=mips64-unknown-linux-gnu -position-independent %s \
# RUN: | FileCheck -check-prefix=ASM %s
# RUN: llvm-mc -triple=mips-unknown-linux-gnu %s \
# RUN: | FileCheck -check-prefix=ASM %s
# RUN: llvm-mc -triple=mips-unknown-linux-gnu \
# RUN: -position-independent -filetype=obj -o - %s \
# RUN: | llvm-objdump -d -r - | FileCheck -check-prefix=OBJ32-PIC %s
# RUN: llvm-mc -triple=mips64-unknown-linux-gnu \
# RUN: -position-independent -filetype=obj -o - %s \
# RUN: | llvm-objdump -d -r - | FileCheck -check-prefix=OBJ64-PIC %s
# RUN: llvm-mc -triple=mips-unknown-linux-gnu \
# RUN: -filetype=obj -o - %s \
# RUN: | llvm-objdump -d -r - | FileCheck -check-prefix=OBJ32-NPIC %s
# RUN: llvm-mc -triple=mips64-unknown-linux-gnu \
# RUN: -filetype=obj -o - %s \
# RUN: | llvm-objdump -d -r - | FileCheck -check-prefix=OBJ64-NPIC %s
# ASM: .cpadd $4
# OBJ32-PIC: addu $4, $4, $gp
# OBJ64-PIC: daddu $4, $4, $gp
# OBJ32-NPIC-NOT: addu
# OBJ64-NPIC-NOT: daddu
.text
.cpadd $4