mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-28 14:10:41 +00:00
[mips] Add assembler support for '.set mipsX'.
Summary: This patch also fixes an issue with the way the Mips assembler enables/disables architecture features. Before this patch, the assembler never disabled feature bits. For example, .set mips64 .set mips32r2 would result in the 'OR' of mips64 with mips32r2 feature bits which isn't right. Unfortunately this isn't trivial to fix because there's not an easy way to clear feature bits as the algorithm in MCSubtargetInfo (ToggleFeature) only clears the bits that imply the feature being cleared and not the implied bits by the feature (there's a better explanation to the code I added). Patch by Matheus Almeida and updated by Toma Tabacu Reviewers: vmedic, matheusalmeida, dsanders Reviewed By: dsanders Subscribers: tomatabacu, llvm-commits Differential Revision: http://reviews.llvm.org/D4123 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@214709 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
12d4f9f4e4
commit
98b419bff7
@ -65,6 +65,10 @@ public:
|
||||
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);
|
||||
|
@ -51,6 +51,20 @@ public:
|
||||
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 @@ class MipsAsmParser : public MCTargetAsmParser {
|
||||
// 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 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
|
||||
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 @@ bool MipsAsmParser::parseDirectiveSet() {
|
||||
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 {
|
||||
|
@ -52,9 +52,17 @@ void MipsTargetStreamer::emitFrame(unsigned StackReg, unsigned StackSize,
|
||||
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 @@ void MipsTargetAsmStreamer::emitFrame(unsigned StackReg, unsigned StackSize,
|
||||
<< 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 @@ void MipsTargetAsmStreamer::emitDirectiveSetMips64R2() {
|
||||
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 @@ void MipsTargetELFStreamer::emitFMask(unsigned FPUBitmask,
|
||||
// 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 @@ void MipsTargetELFStreamer::emitDirectiveSetMips64R2() {
|
||||
setCanHaveModuleDir(false);
|
||||
}
|
||||
|
||||
void MipsTargetELFStreamer::emitDirectiveSetMips64R6() {
|
||||
setCanHaveModuleDir(false);
|
||||
}
|
||||
|
||||
void MipsTargetELFStreamer::emitDirectiveSetDsp() {
|
||||
setCanHaveModuleDir(false);
|
||||
}
|
||||
|
@ -45,9 +45,17 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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
|
||||
|
30
test/MC/Mips/set-mips-directives-bad.s
Normal file
30
test/MC/Mips/set-mips-directives-bad.s
Normal file
@ -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
|
||||
|
51
test/MC/Mips/set-mips-directives.s
Normal file
51
test/MC/Mips/set-mips-directives.s
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user