Index: include/llvm/MC/MCSubtargetInfo.h =================================================================== --- include/llvm/MC/MCSubtargetInfo.h +++ include/llvm/MC/MCSubtargetInfo.h @@ -65,6 +65,10 @@ return FeatureBits; } + /// setFeatureBits - Set the feature bits. + /// + void setFeatureBits(uint64_t _FeatureBits) { FeatureBits = _FeatureBits; } + /// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with /// feature string). Recompute feature bits and scheduling model. void InitMCProcessorInfo(StringRef CPU, StringRef FS); Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -51,6 +51,20 @@ void setMacro() { macro = true; } void setNomacro() { macro = false; } + // Set of features that are either architecture features or referenced + // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6). + // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]). + // The reason we need this mask is explained in the selectArch function. + // FIXME: Ideally we would like TableGen to generate this information. + static const uint64_t AllArchRelatedMask = + Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 | + Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 | + Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 | + Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 | + Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 | + Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit | + Mips::FeatureGP64Bit | Mips::FeatureNaN2008; + private: unsigned aTReg; bool reorder; @@ -200,6 +214,36 @@ // Example: INSERT.B $w0[n], $1 => 16 > n >= 0 bool validateMSAIndex(int Val, int RegKind); + // Selects a new architecture by updating the FeatureBits with the necessary + // info including implied dependencies. + // Internally, it clears all the feature bits related to *any* architecture + // and selects the new one using the ToggleFeature functionality of the + // MCSubtargetInfo object that handles implied dependencies. The reason we + // clear all the arch related bits manually is because ToggleFeature only + // clears the features that imply the feature being cleared and not the + // features implied by the feature being cleared. This is easier to see + // with an example: + // -------------------------------------------------- + // | Feature | Implies | + // | -------------------------------------------------| + // | FeatureMips1 | None | + // | FeatureMips2 | FeatureMips1 | + // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 | + // | FeatureMips4 | FeatureMips3 | + // | ... | | + // -------------------------------------------------- + // + // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 | + // FeatureMipsGP64 | FeatureMips1) + // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4). + void selectArch(StringRef ArchFeature) { + uint64_t FeatureBits = STI.getFeatureBits(); + FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask; + STI.setFeatureBits(FeatureBits); + setAvailableFeatures( + ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature))); + } + void setFeatureBits(unsigned Feature, StringRef FeatureString) { if (!(STI.getFeatureBits() & Feature)) { setAvailableFeatures( @@ -2523,18 +2567,50 @@ case Mips::FeatureMips16: getTargetStreamer().emitDirectiveSetMips16(); break; + case Mips::FeatureMips1: + selectArch("mips1"); + getTargetStreamer().emitDirectiveSetMips1(); + break; + case Mips::FeatureMips2: + selectArch("mips2"); + getTargetStreamer().emitDirectiveSetMips2(); + break; + case Mips::FeatureMips3: + selectArch("mips3"); + getTargetStreamer().emitDirectiveSetMips3(); + break; + case Mips::FeatureMips4: + selectArch("mips4"); + getTargetStreamer().emitDirectiveSetMips4(); + break; + case Mips::FeatureMips5: + selectArch("mips5"); + getTargetStreamer().emitDirectiveSetMips5(); + break; + case Mips::FeatureMips32: + selectArch("mips32"); + getTargetStreamer().emitDirectiveSetMips32(); + break; case Mips::FeatureMips32r2: - setFeatureBits(Mips::FeatureMips32r2, "mips32r2"); + selectArch("mips32r2"); getTargetStreamer().emitDirectiveSetMips32R2(); break; + case Mips::FeatureMips32r6: + selectArch("mips32r6"); + getTargetStreamer().emitDirectiveSetMips32R6(); + break; case Mips::FeatureMips64: - setFeatureBits(Mips::FeatureMips64, "mips64"); + selectArch("mips64"); getTargetStreamer().emitDirectiveSetMips64(); break; case Mips::FeatureMips64r2: - setFeatureBits(Mips::FeatureMips64r2, "mips64r2"); + selectArch("mips64r2"); getTargetStreamer().emitDirectiveSetMips64R2(); break; + case Mips::FeatureMips64r6: + selectArch("mips64r6"); + getTargetStreamer().emitDirectiveSetMips64R6(); + break; } return false; } @@ -2682,12 +2758,28 @@ return false; } else if (Tok.getString() == "micromips") { return parseSetFeature(Mips::FeatureMicroMips); + } else if (Tok.getString() == "mips1") { + return parseSetFeature(Mips::FeatureMips1); + } else if (Tok.getString() == "mips2") { + return parseSetFeature(Mips::FeatureMips2); + } else if (Tok.getString() == "mips3") { + return parseSetFeature(Mips::FeatureMips3); + } else if (Tok.getString() == "mips4") { + return parseSetFeature(Mips::FeatureMips4); + } else if (Tok.getString() == "mips5") { + return parseSetFeature(Mips::FeatureMips5); + } else if (Tok.getString() == "mips32") { + return parseSetFeature(Mips::FeatureMips32); } else if (Tok.getString() == "mips32r2") { return parseSetFeature(Mips::FeatureMips32r2); + } else if (Tok.getString() == "mips32r6") { + return parseSetFeature(Mips::FeatureMips32r6); } else if (Tok.getString() == "mips64") { return parseSetFeature(Mips::FeatureMips64); } else if (Tok.getString() == "mips64r2") { return parseSetFeature(Mips::FeatureMips64r2); + } else if (Tok.getString() == "mips64r6") { + return parseSetFeature(Mips::FeatureMips64r6); } else if (Tok.getString() == "dsp") { return parseSetFeature(Mips::FeatureDSP); } else { Index: lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -52,9 +52,17 @@ void MipsTargetStreamer::emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) {} void MipsTargetStreamer::emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) { } +void MipsTargetStreamer::emitDirectiveSetMips1() {} +void MipsTargetStreamer::emitDirectiveSetMips2() {} +void MipsTargetStreamer::emitDirectiveSetMips3() {} +void MipsTargetStreamer::emitDirectiveSetMips4() {} +void MipsTargetStreamer::emitDirectiveSetMips5() {} +void MipsTargetStreamer::emitDirectiveSetMips32() {} void MipsTargetStreamer::emitDirectiveSetMips32R2() {} +void MipsTargetStreamer::emitDirectiveSetMips32R6() {} void MipsTargetStreamer::emitDirectiveSetMips64() {} void MipsTargetStreamer::emitDirectiveSetMips64R2() {} +void MipsTargetStreamer::emitDirectiveSetMips64R6() {} void MipsTargetStreamer::emitDirectiveSetDsp() {} void MipsTargetStreamer::emitDirectiveCpload(unsigned RegNo) {} void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, @@ -152,11 +160,46 @@ << StringRef(MipsInstPrinter::getRegisterName(ReturnReg)).lower() << '\n'; } +void MipsTargetAsmStreamer::emitDirectiveSetMips1() { + OS << "\t.set\tmips1\n"; + setCanHaveModuleDir(false); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips2() { + OS << "\t.set\tmips2\n"; + setCanHaveModuleDir(false); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips3() { + OS << "\t.set\tmips3\n"; + setCanHaveModuleDir(false); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips4() { + OS << "\t.set\tmips4\n"; + setCanHaveModuleDir(false); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips5() { + OS << "\t.set\tmips5\n"; + setCanHaveModuleDir(false); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips32() { + OS << "\t.set\tmips32\n"; + setCanHaveModuleDir(false); +} + void MipsTargetAsmStreamer::emitDirectiveSetMips32R2() { OS << "\t.set\tmips32r2\n"; setCanHaveModuleDir(false); } +void MipsTargetAsmStreamer::emitDirectiveSetMips32R6() { + OS << "\t.set\tmips32r6\n"; + setCanHaveModuleDir(false); +} + void MipsTargetAsmStreamer::emitDirectiveSetMips64() { OS << "\t.set\tmips64\n"; setCanHaveModuleDir(false); @@ -167,6 +210,11 @@ setCanHaveModuleDir(false); } +void MipsTargetAsmStreamer::emitDirectiveSetMips64R6() { + OS << "\t.set\tmips64r6\n"; + setCanHaveModuleDir(false); +} + void MipsTargetAsmStreamer::emitDirectiveSetDsp() { OS << "\t.set\tdsp\n"; setCanHaveModuleDir(false); @@ -496,10 +544,38 @@ // FIXME: implement. } +void MipsTargetELFStreamer::emitDirectiveSetMips1() { + setCanHaveModuleDir(false); +} + +void MipsTargetELFStreamer::emitDirectiveSetMips2() { + setCanHaveModuleDir(false); +} + +void MipsTargetELFStreamer::emitDirectiveSetMips3() { + setCanHaveModuleDir(false); +} + +void MipsTargetELFStreamer::emitDirectiveSetMips4() { + setCanHaveModuleDir(false); +} + +void MipsTargetELFStreamer::emitDirectiveSetMips5() { + setCanHaveModuleDir(false); +} + +void MipsTargetELFStreamer::emitDirectiveSetMips32() { + setCanHaveModuleDir(false); +} + void MipsTargetELFStreamer::emitDirectiveSetMips32R2() { setCanHaveModuleDir(false); } +void MipsTargetELFStreamer::emitDirectiveSetMips32R6() { + setCanHaveModuleDir(false); +} + void MipsTargetELFStreamer::emitDirectiveSetMips64() { setCanHaveModuleDir(false); } @@ -508,6 +584,10 @@ setCanHaveModuleDir(false); } +void MipsTargetELFStreamer::emitDirectiveSetMips64R6() { + setCanHaveModuleDir(false); +} + void MipsTargetELFStreamer::emitDirectiveSetDsp() { setCanHaveModuleDir(false); } Index: lib/Target/Mips/MipsTargetStreamer.h =================================================================== --- lib/Target/Mips/MipsTargetStreamer.h +++ lib/Target/Mips/MipsTargetStreamer.h @@ -45,9 +45,17 @@ virtual void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff); virtual void emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff); + virtual void emitDirectiveSetMips1(); + virtual void emitDirectiveSetMips2(); + virtual void emitDirectiveSetMips3(); + virtual void emitDirectiveSetMips4(); + virtual void emitDirectiveSetMips5(); + virtual void emitDirectiveSetMips32(); virtual void emitDirectiveSetMips32R2(); + virtual void emitDirectiveSetMips32R6(); virtual void emitDirectiveSetMips64(); virtual void emitDirectiveSetMips64R2(); + virtual void emitDirectiveSetMips64R6(); virtual void emitDirectiveSetDsp(); // PIC support @@ -121,9 +129,17 @@ void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) override; void emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) override; + void emitDirectiveSetMips1() override; + void emitDirectiveSetMips2() override; + void emitDirectiveSetMips3() override; + void emitDirectiveSetMips4() override; + void emitDirectiveSetMips5() override; + void emitDirectiveSetMips32() override; void emitDirectiveSetMips32R2() override; + void emitDirectiveSetMips32R6() override; void emitDirectiveSetMips64() override; void emitDirectiveSetMips64R2() override; + void emitDirectiveSetMips64R6() override; void emitDirectiveSetDsp() override; // PIC support @@ -178,9 +194,17 @@ void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) override; void emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) override; + void emitDirectiveSetMips1() override; + void emitDirectiveSetMips2() override; + void emitDirectiveSetMips3() override; + void emitDirectiveSetMips4() override; + void emitDirectiveSetMips5() override; + void emitDirectiveSetMips32() override; void emitDirectiveSetMips32R2() override; + void emitDirectiveSetMips32R6() override; void emitDirectiveSetMips64() override; void emitDirectiveSetMips64R2() override; + void emitDirectiveSetMips64R6() override; void emitDirectiveSetDsp() override; // PIC support Index: test/MC/Mips/set-mips-directives-bad.s =================================================================== --- /dev/null +++ test/MC/Mips/set-mips-directives-bad.s @@ -0,0 +1,30 @@ +# RUN: not llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips1 2>%t1 +# RUN: FileCheck %s < %t1 + +# FIXME: At the moment we emit the wrong error message if we try to assemble the +# ll instruction using an unsupported architecture so we just check for "error" +# and ignore the rest of the message. + + .text + .set noreorder + .set mips1 + ll $2,-2($2) # CHECK: error: + .set mips2 + dadd $2,$2,$2 # CHECK: error: instruction requires a CPU feature not currently enabled + .set mips3 + ldxc1 $f8,$2($4) # CHECK: error: instruction requires a CPU feature not currently enabled + .set mips4 + luxc1 $f19,$2($4) # CHECK: error: instruction requires a CPU feature not currently enabled + .set mips5 + clo $2,$2 # CHECK: error: instruction requires a CPU feature not currently enabled + .set mips32 + rotr $2,15 # CHECK: error: instruction requires a CPU feature not currently enabled + .set mips32r2 + mod $2, $4, $6 # CHECK: error:instruction requires a CPU feature not currently enabled + .set mips32r6 + daddi $2, $2, 10 # CHECK: error: instruction requires a CPU feature not currently enabled + .set mips64 + drotr32 $1,$14,15 # CHECK: error: instruction requires a CPU feature not currently enabled + .set mips64r2 + mod $2, $4, $6 # CHECK: error: instruction requires a CPU feature not currently enabled + Index: test/MC/Mips/set-mips-directives.s =================================================================== --- /dev/null +++ test/MC/Mips/set-mips-directives.s @@ -0,0 +1,51 @@ +# RUN: llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips1 | \ +# RUN: FileCheck %s + + .text + .set noreorder + .set mips1 + add $2, $2, $2 + .set mips2 + ll $2,-2($2) + .set mips3 + dadd $2,$2,$2 + .set mips4 + ldxc1 $f8,$2($4) + .set mips5 + luxc1 $f19,$2($4) + .set mips32 + clo $2,$2 + .set mips32r2 + rotr $2,15 + .set mips32r6 + mod $2, $4, $6 + .set mips64 + daddi $2, $2, 10 + .set mips64r2 + drotr32 $1,$14,15 + .set mips64r6 + mod $2, $4, $6 + +# CHECK: .set noreorder +# CHECK: .set mips1 +# CHECK: add $2, $2, $2 +# CHECK: .set mips2 +# CHECK: ll $2, -2($2) +# CHECK: .set mips3 +# CHECK: dadd $2, $2, $2 +# CHECK: .set mips4 +# CHECK: ldxc1 $f8, $2($4) +# CHECK: .set mips5 +# CHECK: luxc1 $f19, $2($4) +# CHECK: .set mips32 +# CHECK: clo $2, $2 +# CHECK: .set mips32r2 +# CHECK: rotr $2, $2, 15 +# CHECK: .set mips32r6 +# CHECK: mod $2, $4, $6 +# CHECK: .set mips64 +# CHECK: daddi $2, $2, 10 +# CHECK: .set mips64r2 +# CHECK: drotr32 $1, $14, 15 +# CHECK: .set mips64r6 +# CHECK: mod $2, $4, $6