namespace {
class MipsAssemblerOptions {
public:
- MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true), fpAbiMode(0) {}
+ MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {}
unsigned getATRegNum() { return aTReg; }
bool setATReg(unsigned Reg);
bool isReorder() { return reorder; }
void setReorder() { reorder = true; }
void setNoreorder() { reorder = false; }
- void setFpAbiMode(int Mode) { fpAbiMode = Mode; }
bool isMacro() { return macro; }
void setMacro() { macro = true; }
void setNomacro() { macro = false; }
- int getFpAbiMode() { return fpAbiMode; }
private:
unsigned aTReg;
bool reorder;
bool macro;
- int fpAbiMode;
};
}
void expandMemInst(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions, bool isLoad,
bool isImmOpnd);
- bool reportParseError(StringRef ErrorMsg);
- bool reportParseError(SMLoc Loc, StringRef ErrorMsg);
+ bool reportParseError(Twine ErrorMsg);
+ bool reportParseError(SMLoc Loc, Twine ErrorMsg);
bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
bool parseRelocOperand(const MCExpr *&Res);
bool parseDirectiveGpWord();
bool parseDirectiveGpDWord();
bool parseDirectiveModule();
+ bool parseDirectiveModuleFP();
+ bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
+ StringRef Directive);
MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
+
+ if (!isABI_O32() && !useOddSPReg() != 0)
+ report_fatal_error("-mno-odd-spreg requires the O32 ABI");
}
MCAsmParser &getParser() const { return Parser; }
bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
bool isABI_FPXX() const { return false; } // TODO: add check for FeatureXX
+ bool useOddSPReg() const {
+ return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
+ }
+
bool inMicroMipsMode() const {
return STI.getFeatureBits() & Mips::FeatureMicroMips;
}
void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
+ // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
+ if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
+ AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
+ "registers");
}
void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
return false;
}
-bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
+bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
SMLoc Loc = getLexer().getLoc();
Parser.eatToEndOfStatement();
return Error(Loc, ErrorMsg);
}
-bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) {
+bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
return Error(Loc, ErrorMsg);
}
}
bool MipsAsmParser::parseSetFpDirective() {
- int FpAbiMode;
+ MipsABIFlagsSection::FpABIKind FpAbiVal;
// Line can be: .set fp=32
// .set fp=xx
// .set fp=64
}
Parser.Lex(); // Eat '=' token.
Tok = Parser.getTok();
- if (Tok.is(AsmToken::Identifier)) {
- StringRef XX = Tok.getString();
- if (XX != "xx") {
- reportParseError("unsupported option");
- return false;
- }
- if (!isABI_O32()) {
- reportParseError("'set fp=xx'option requires O32 ABI");
- return false;
- }
- FpAbiMode = Val_GNU_MIPS_ABI_FP_XX;
- } else if (Tok.is(AsmToken::Integer)) {
- unsigned Value = Tok.getIntVal();
- if (Value != 32 && Value != 64) {
- reportParseError("unsupported option");
- return false;
- }
- if (Value == 32) {
- if (!isABI_O32()) {
- reportParseError("'set fp=32'option requires O32 ABI");
- return false;
- }
- FpAbiMode = Val_GNU_MIPS_ABI_FP_DOUBLE;
- } else {
- if (isABI_N32() || isABI_N64())
- FpAbiMode = Val_GNU_MIPS_ABI_FP_DOUBLE;
- else if (isABI_O32())
- FpAbiMode = Val_GNU_MIPS_ABI_FP_64;
- }
- }
- Parser.Lex(); // Eat option token.
+
+ if (!parseFpABIValue(FpAbiVal, ".set"))
+ return false;
+
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token in statement");
return false;
}
- Options.setFpAbiMode(FpAbiMode);
- getTargetStreamer().emitDirectiveSetFp(FpAbiMode, isABI_O32());
+ getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Parser.Lex(); // Consume the EndOfStatement.
return false;
}
return false;
}
+/// parseDirectiveModule
+/// ::= .module oddspreg
+/// ::= .module nooddspreg
+/// ::= .module fp=value
bool MipsAsmParser::parseDirectiveModule() {
- // Line can be: .module fp=32
- // .module fp=xx
- // .module fp=64
- unsigned FpAbiVal = 0;
+ MCAsmLexer &Lexer = getLexer();
+ SMLoc L = Lexer.getLoc();
+
if (!getTargetStreamer().getCanHaveModuleDir()) {
// TODO : get a better message.
reportParseError(".module directive must appear before any code");
return false;
}
- AsmToken Tok = Parser.getTok();
- if (Tok.isNot(AsmToken::Identifier) && Tok.getString() != "fp") {
- reportParseError("unexpected token in .module directive, 'fp' expected");
- return false;
+
+ if (Lexer.is(AsmToken::Identifier)) {
+ StringRef Option = Parser.getTok().getString();
+ Parser.Lex();
+
+ if (Option == "oddspreg") {
+ getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
+ clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
+
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ reportParseError("Expected end of statement");
+ return false;
+ }
+
+ return false;
+ } else if (Option == "nooddspreg") {
+ if (!isABI_O32()) {
+ Error(L, "'.module nooddspreg' requires the O32 ABI");
+ return false;
+ }
+
+ getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
+ setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
+
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ reportParseError("Expected end of statement");
+ return false;
+ }
+
+ return false;
+ } else if (Option == "fp") {
+ return parseDirectiveModuleFP();
+ }
+
+ return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
}
- Parser.Lex(); // Eat fp token
- Tok = Parser.getTok();
- if (Tok.isNot(AsmToken::Equal)) {
+
+ return false;
+}
+
+/// parseDirectiveModuleFP
+/// ::= =32
+/// ::= =xx
+/// ::= =64
+bool MipsAsmParser::parseDirectiveModuleFP() {
+ MCAsmLexer &Lexer = getLexer();
+
+ if (Lexer.isNot(AsmToken::Equal)) {
reportParseError("unexpected token in statement");
return false;
}
Parser.Lex(); // Eat '=' token.
- Tok = Parser.getTok();
- if (Tok.is(AsmToken::Identifier)) {
- StringRef XX = Tok.getString();
- if (XX != "xx") {
- reportParseError("unsupported option");
- return false;
- }
- FpAbiVal = Val_GNU_MIPS_ABI_FP_XX;
- } else if (Tok.is(AsmToken::Integer)) {
- unsigned Value = Tok.getIntVal();
- if (Value != 32 && Value != 64) {
- reportParseError("unsupported value, expected 32 or 64");
- return false;
- }
- if (Value == 64) {
- if (isABI_N32() || isABI_N64())
- FpAbiVal = Val_GNU_MIPS_ABI_FP_DOUBLE;
- else if (isABI_O32())
- FpAbiVal = Val_GNU_MIPS_ABI_FP_64;
- } else if (isABI_O32())
- FpAbiVal = Val_GNU_MIPS_ABI_FP_DOUBLE;
- }
- Parser.Lex(); // Eat option token.
+
+ MipsABIFlagsSection::FpABIKind FpABI;
+ if (!parseFpABIValue(FpABI, ".module"))
+ return false;
+
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token in statement");
return false;
}
+
// Emit appropriate flags.
- getTargetStreamer().emitDirectiveModule(FpAbiVal, isABI_O32());
- getTargetStreamer().setFpABI(FpAbiVal);
+ getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Parser.Lex(); // Consume the EndOfStatement.
return false;
}
+
+bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
+ StringRef Directive) {
+ MCAsmLexer &Lexer = getLexer();
+
+ if (Lexer.is(AsmToken::Identifier)) {
+ StringRef Value = Parser.getTok().getString();
+ Parser.Lex();
+
+ if (Value != "xx") {
+ reportParseError("unsupported value, expected 'xx', '32' or '64'");
+ return false;
+ }
+
+ if (!isABI_O32()) {
+ reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
+ return false;
+ }
+
+ FpABI = MipsABIFlagsSection::FpABIKind::XX;
+ return true;
+ }
+
+ if (Lexer.is(AsmToken::Integer)) {
+ unsigned Value = Parser.getTok().getIntVal();
+ Parser.Lex();
+
+ if (Value != 32 && Value != 64) {
+ reportParseError("unsupported value, expected 'xx', '32' or '64'");
+ return false;
+ }
+
+ if (Value == 32) {
+ if (!isABI_O32()) {
+ reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
+ return false;
+ }
+
+ FpABI = MipsABIFlagsSection::FpABIKind::S32;
+ } else
+ FpABI = MipsABIFlagsSection::FpABIKind::S64;
+
+ return true;
+ }
+
+ return false;
+}
+
bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
StringRef IDVal = DirectiveID.getString();