Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -334,6 +334,16 @@ AssemblerOptions.back()->setFeatures(getAvailableFeatures()); } + void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) { + setFeatureBits(Feature, FeatureString); + AssemblerOptions.front()->setFeatures(getAvailableFeatures()); + } + + void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) { + clearFeatureBits(Feature, FeatureString); + AssemblerOptions.front()->setFeatures(getAvailableFeatures()); + } + public: enum MipsMatchResultTy { Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY @@ -4070,6 +4080,8 @@ /// ::= .module oddspreg /// ::= .module nooddspreg /// ::= .module fp=value +/// ::= .module softfloat +/// ::= .module hardfloat bool MipsAsmParser::parseDirectiveModule() { MCAsmParser &Parser = getParser(); MCAsmLexer &Lexer = getLexer(); @@ -4116,6 +4128,30 @@ return false; // parseDirectiveModule has finished successfully. } else if (Option == "fp") { return parseDirectiveModuleFP(); + } else if (Option == "softfloat") { + getTargetStreamer().emitDirectiveModuleSoftFloat(); + setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float"); + getTargetStreamer().updateABIInfo(*this); + + // 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; + } + + return false; // parseDirectiveModule has finished successfully. + } else if (Option == "hardfloat") { + getTargetStreamer().emitDirectiveModuleHardFloat(); + clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float"); + getTargetStreamer().updateABIInfo(*this); + + // 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; + } + + return false; // parseDirectiveModule has finished successfully. } else { return Error(L, "'" + Twine(Option) + "' is not a valid .module option."); } Index: lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -372,6 +372,16 @@ OS << ABIFlagsSection.getFpABIString(Value) << "\n"; } +void MipsTargetAsmStreamer::emitDirectiveModuleSoftFloat() { + MipsTargetStreamer::emitDirectiveModuleSoftFloat(); + OS << "\t.module\tsoftfloat\n"; +} + +void MipsTargetAsmStreamer::emitDirectiveModuleHardFloat() { + MipsTargetStreamer::emitDirectiveModuleHardFloat(); + OS << "\t.module\thardfloat\n"; +} + void MipsTargetAsmStreamer::emitDirectiveModuleOddSPReg(bool Enabled, bool IsO32ABI) { MipsTargetStreamer::emitDirectiveModuleOddSPReg(Enabled, IsO32ABI); Index: lib/Target/Mips/MipsTargetStreamer.h =================================================================== --- lib/Target/Mips/MipsTargetStreamer.h +++ lib/Target/Mips/MipsTargetStreamer.h @@ -94,6 +94,17 @@ virtual void emitDirectiveModuleOddSPReg(bool Enabled, bool IsO32ABI); virtual void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value); + + virtual void emitDirectiveModuleSoftFloat() { + ABIFlagsSection.setFpABI(MipsABIFlagsSection::FpABIKind::SOFT, + ABIFlagsSection.Is32BitABI); + } + + virtual void emitDirectiveModuleHardFloat() { + ABIFlagsSection.setFpABI(MipsABIFlagsSection::FpABIKind::ANY, + ABIFlagsSection.Is32BitABI); + } + void forbidModuleDirective() { ModuleDirectiveAllowed = false; } void reallowModuleDirective() { ModuleDirectiveAllowed = true; } bool isModuleDirectiveAllowed() { return ModuleDirectiveAllowed; } @@ -199,6 +210,8 @@ bool Is32BitABI) override; void emitDirectiveModuleOddSPReg(bool Enabled, bool IsO32ABI) override; void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value) override; + void emitDirectiveModuleSoftFloat() override; + void emitDirectiveModuleHardFloat() override; }; // This part is for ELF object output Index: test/MC/Mips/module-hardfloat.s =================================================================== --- /dev/null +++ test/MC/Mips/module-hardfloat.s @@ -0,0 +1,28 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 | \ +# RUN: FileCheck %s -check-prefix=CHECK-ASM +# +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -filetype=obj -o - | \ +# RUN: llvm-readobj -sections -section-data -section-relocations - | \ +# RUN: FileCheck %s -check-prefix=CHECK-OBJ + +# CHECK-ASM: .module hardfloat + +# Check if the MIPS.abiflags section was correctly emitted: +# CHECK-OBJ: Section { +# CHECK-OBJ-LABEL: Name: .MIPS.abiflags +# CHECK-OBJ: SectionData ( +# CHECK-OBJ: 0000: 00002001 01010001 00000000 00000000 |.. .............| +# CHECK-OBJ: 0010: 00000001 00000000 |........| +# CHECK-OBJ: ) +# CHECK-OBJ: } +# The cpr1_size and fp_abi are in the second group of values: +# 01 -> gpr_size == AFL_REG_32 +# 01 -> cpr1_size == AFL_REG_32 +# 00 -> cpr2_size == AFL_REG_NONE +# 01 -> fp_abi == Val_GNU_MIPS_ABI_FP_DOUBLE + + .module hardfloat + +# FIXME: Test should include gnu_attributes directive when implemented. +# An explicit .gnu_attribute must be checked against the effective +# command line options and any inconsistencies reported via a warning. Index: test/MC/Mips/module-softfloat.s =================================================================== --- /dev/null +++ test/MC/Mips/module-softfloat.s @@ -0,0 +1,28 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 | \ +# RUN: FileCheck %s -check-prefix=CHECK-ASM +# +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -filetype=obj -o - | \ +# RUN: llvm-readobj -sections -section-data -section-relocations - | \ +# RUN: FileCheck %s -check-prefix=CHECK-OBJ + +# CHECK-ASM: .module softfloat + +# Check if the MIPS.abiflags section was correctly emitted: +# CHECK-OBJ: Section { +# CHECK-OBJ-LABEL: Name: .MIPS.abiflags +# CHECK-OBJ: SectionData ( +# CHECK-OBJ: 0000: 00002001 01000003 00000000 00000000 |.. .............| +# CHECK-OBJ: 0010: 00000001 00000000 |........| +# CHECK-OBJ: ) +# CHECK-OBJ: } +# The cpr1_size and fp_abi are in the second group of values: +# 01 -> gpr_size == AFL_REG_32 +# 00 -> cpr1_size == AFL_REG_NONE +# 00 -> cpr2_size == AFL_REG_NONE +# 03 -> fp_abi == Val_GNU_MIPS_ABI_FP_SOFT + + .module softfloat + +# FIXME: Test should include gnu_attributes directive when implemented. +# An explicit .gnu_attribute must be checked against the effective +# command line options and any inconsistencies reported via a warning.