diff --git a/lib/Target/AArch64/AArch64InstrFormats.td b/lib/Target/AArch64/AArch64InstrFormats.td index 4b89035fa8e..2b0f5d2e32a 100644 --- a/lib/Target/AArch64/AArch64InstrFormats.td +++ b/lib/Target/AArch64/AArch64InstrFormats.td @@ -843,7 +843,7 @@ def MRSSystemRegisterOperand : AsmOperandClass { let ParserMethod = "tryParseSysReg"; let DiagnosticType = "MRS"; } -// concatenation of 1, op0, op1, CRn, CRm, op2. 16-bit immediate. +// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate. def mrs_sysreg_op : Operand { let ParserMatchClass = MRSSystemRegisterOperand; let DecoderMethod = "DecodeMRSSystemRegister"; @@ -863,9 +863,8 @@ def msr_sysreg_op : Operand { class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg), "mrs", "\t$Rt, $systemreg"> { - bits<15> systemreg; - let Inst{20} = 1; - let Inst{19-5} = systemreg; + bits<16> systemreg; + let Inst{20-5} = systemreg; } // FIXME: Some of these def NZCV, others don't. Best way to model that? @@ -873,9 +872,8 @@ class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg), // would do it, but feels like overkill at this point. class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt), "msr", "\t$systemreg, $Rt"> { - bits<15> systemreg; - let Inst{20} = 1; - let Inst{19-5} = systemreg; + bits<16> systemreg; + let Inst{20-5} = systemreg; } def SystemPStateFieldOperand : AsmOperandClass { diff --git a/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp index 87b2d5096dd..f522ca59a9a 100644 --- a/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ b/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -626,35 +626,19 @@ static DecodeStatus DecodeMemExtend(llvm::MCInst &Inst, unsigned Imm, static DecodeStatus DecodeMRSSystemRegister(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder) { - const AArch64Disassembler *Dis = - static_cast(Decoder); - const MCSubtargetInfo &STI = Dis->getSubtargetInfo(); - - Imm |= 0x8000; Inst.addOperand(MCOperand::CreateImm(Imm)); - bool ValidNamed; - (void)AArch64SysReg::MRSMapper(STI.getFeatureBits()) - .toString(Imm, ValidNamed); - - return ValidNamed ? Success : Fail; + // Every system register in the encoding space is valid with the syntax + // S____, so decoding system registers always succeeds. + return Success; } static DecodeStatus DecodeMSRSystemRegister(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder) { - const AArch64Disassembler *Dis = - static_cast(Decoder); - const MCSubtargetInfo &STI = Dis->getSubtargetInfo(); - - Imm |= 0x8000; Inst.addOperand(MCOperand::CreateImm(Imm)); - bool ValidNamed; - (void)AArch64SysReg::MSRMapper(STI.getFeatureBits()) - .toString(Imm, ValidNamed); - - return ValidNamed ? Success : Fail; + return Success; } static DecodeStatus DecodeFMOVLaneInstruction(llvm::MCInst &Inst, unsigned Insn, diff --git a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp index 0091ab354a0..46a1d797872 100644 --- a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp +++ b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp @@ -1276,24 +1276,20 @@ void AArch64InstPrinter::printMRSSystemRegister(const MCInst *MI, unsigned OpNo, raw_ostream &O) { unsigned Val = MI->getOperand(OpNo).getImm(); - bool Valid; auto Mapper = AArch64SysReg::MRSMapper(getAvailableFeatures()); - std::string Name = Mapper.toString(Val, Valid); + std::string Name = Mapper.toString(Val); - if (Valid) - O << StringRef(Name).upper(); + O << StringRef(Name).upper(); } void AArch64InstPrinter::printMSRSystemRegister(const MCInst *MI, unsigned OpNo, raw_ostream &O) { unsigned Val = MI->getOperand(OpNo).getImm(); - bool Valid; auto Mapper = AArch64SysReg::MSRMapper(getAvailableFeatures()); - std::string Name = Mapper.toString(Val, Valid); + std::string Name = Mapper.toString(Val); - if (Valid) - O << StringRef(Name).upper(); + O << StringRef(Name).upper(); } void AArch64InstPrinter::printSystemPStateField(const MCInst *MI, unsigned OpNo, diff --git a/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp b/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp index 3c24bb30a26..bc6c7a96f85 100644 --- a/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp +++ b/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp @@ -791,22 +791,22 @@ AArch64SysReg::SysRegMapper::fromString(StringRef Name, bool &Valid) const { } } - // Try to parse an S____ register name, where the bits - // are: 11 xxx 1x11 xxxx xxx - Regex GenericRegPattern("^s3_([0-7])_c(1[15])_c([0-9]|1[0-5])_([0-7])$"); + // Try to parse an S____ register name + Regex GenericRegPattern("^s([0-3])_([0-7])_c([0-9]|1[0-5])_c([0-9]|1[0-5])_([0-7])$"); - SmallVector Ops; + SmallVector Ops; if (!GenericRegPattern.match(NameLower, &Ops)) { Valid = false; return -1; } - uint32_t Op0 = 3, Op1 = 0, CRn = 0, CRm = 0, Op2 = 0; + uint32_t Op0 = 0, Op1 = 0, CRn = 0, CRm = 0, Op2 = 0; uint32_t Bits; - Ops[1].getAsInteger(10, Op1); - Ops[2].getAsInteger(10, CRn); - Ops[3].getAsInteger(10, CRm); - Ops[4].getAsInteger(10, Op2); + Ops[1].getAsInteger(10, Op0); + Ops[2].getAsInteger(10, Op1); + Ops[3].getAsInteger(10, CRn); + Ops[4].getAsInteger(10, CRm); + Ops[5].getAsInteger(10, Op2); Bits = (Op0 << 14) | (Op1 << 11) | (CRn << 7) | (CRm << 3) | Op2; Valid = true; @@ -814,11 +814,10 @@ AArch64SysReg::SysRegMapper::fromString(StringRef Name, bool &Valid) const { } std::string -AArch64SysReg::SysRegMapper::toString(uint32_t Bits, bool &Valid) const { +AArch64SysReg::SysRegMapper::toString(uint32_t Bits) const { // First search the registers shared by all for (unsigned i = 0; i < array_lengthof(SysRegPairs); ++i) { if (SysRegPairs[i].Value == Bits) { - Valid = true; return SysRegPairs[i].Name; } } @@ -827,7 +826,6 @@ AArch64SysReg::SysRegMapper::toString(uint32_t Bits, bool &Valid) const { if (FeatureBits & AArch64::ProcCyclone) { for (unsigned i = 0; i < array_lengthof(CycloneSysRegPairs); ++i) { if (CycloneSysRegPairs[i].Value == Bits) { - Valid = true; return CycloneSysRegPairs[i].Name; } } @@ -837,28 +835,18 @@ AArch64SysReg::SysRegMapper::toString(uint32_t Bits, bool &Valid) const { // write-only). for (unsigned i = 0; i < NumInstPairs; ++i) { if (InstPairs[i].Value == Bits) { - Valid = true; return InstPairs[i].Name; } } + assert(Bits < 0x10000); uint32_t Op0 = (Bits >> 14) & 0x3; uint32_t Op1 = (Bits >> 11) & 0x7; uint32_t CRn = (Bits >> 7) & 0xf; uint32_t CRm = (Bits >> 3) & 0xf; uint32_t Op2 = Bits & 0x7; - // Only combinations matching: 11 xxx 1x11 xxxx xxx are valid for a generic - // name. - if (Op0 != 3 || (CRn != 11 && CRn != 15)) { - Valid = false; - return ""; - } - - assert(Op0 == 3 && (CRn == 11 || CRn == 15) && "Invalid generic sysreg"); - - Valid = true; - return "s3_" + utostr(Op1) + "_c" + utostr(CRn) + return "s" + utostr(Op0)+ "_" + utostr(Op1) + "_c" + utostr(CRn) + "_c" + utostr(CRm) + "_" + utostr(Op2); } diff --git a/lib/Target/AArch64/Utils/AArch64BaseInfo.h b/lib/Target/AArch64/Utils/AArch64BaseInfo.h index 326eb9995d7..c60b09a5f11 100644 --- a/lib/Target/AArch64/Utils/AArch64BaseInfo.h +++ b/lib/Target/AArch64/Utils/AArch64BaseInfo.h @@ -1143,7 +1143,7 @@ namespace AArch64SysReg { SysRegMapper(uint64_t FeatureBits) : FeatureBits(FeatureBits) { } uint32_t fromString(StringRef Name, bool &Valid) const; - std::string toString(uint32_t Bits, bool &Valid) const; + std::string toString(uint32_t Bits) const; }; struct MSRMapper : SysRegMapper { diff --git a/test/MC/AArch64/arm64-system-encoding.s b/test/MC/AArch64/arm64-system-encoding.s index 87f8f8a4e98..eb29117428f 100644 --- a/test/MC/AArch64/arm64-system-encoding.s +++ b/test/MC/AArch64/arm64-system-encoding.s @@ -135,6 +135,8 @@ foo: msr VTTBR_EL2, x3 msr SPSel, x3 msr S3_2_C11_C6_4, x1 + msr S0_0_C0_C0_0, x0 + msr S1_2_C3_C4_5, x2 ; CHECK: msr ACTLR_EL1, x3 ; encoding: [0x23,0x10,0x18,0xd5] ; CHECK: msr ACTLR_EL2, x3 ; encoding: [0x23,0x10,0x1c,0xd5] ; CHECK: msr ACTLR_EL3, x3 ; encoding: [0x23,0x10,0x1e,0xd5] @@ -213,6 +215,8 @@ foo: ; CHECK: msr VTTBR_EL2, x3 ; encoding: [0x03,0x21,0x1c,0xd5] ; CHECK: msr SPSEL, x3 ; encoding: [0x03,0x42,0x18,0xd5] ; CHECK: msr S3_2_C11_C6_4, x1 ; encoding: [0x81,0xb6,0x1a,0xd5] +; CHECK: msr S0_0_C0_C0_0, x0 ; encoding: [0x00,0x00,0x00,0xd5] +; CHECK: msr S1_2_C3_C4_5, x2 ; encoding: [0xa2,0x34,0x0a,0xd5] mrs x3, ACTLR_EL1 mrs x3, ACTLR_EL2 diff --git a/test/MC/AArch64/basic-a64-diagnostics.s b/test/MC/AArch64/basic-a64-diagnostics.s index 5293131711b..07e6d012e93 100644 --- a/test/MC/AArch64/basic-a64-diagnostics.s +++ b/test/MC/AArch64/basic-a64-diagnostics.s @@ -3679,26 +3679,26 @@ // CHECK-ERROR-NEXT: ^ // Now check some invalid generic names - mrs xzr, s2_5_c11_c13_2 mrs x12, s3_8_c11_c13_2 - mrs x13, s3_3_c12_c13_2 mrs x19, s3_2_c15_c16_2 mrs x30, s3_2_c15_c1_8 -// CHECK-ERROR-NEXT: error: expected readable system register -// CHECK-ERROR-NEXT: mrs xzr, s2_5_c11_c13_2 -// CHECK-ERROR-NEXT: ^ + mrs x4, s4_7_c15_c15_7 + mrs x14, s3_7_c16_c15_7 // CHECK-ERROR-NEXT: error: expected readable system register // CHECK-ERROR-NEXT: mrs x12, s3_8_c11_c13_2 // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: expected readable system register -// CHECK-ERROR-NEXT: mrs x13, s3_3_c12_c13_2 -// CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-NEXT: error: expected readable system register // CHECK-ERROR-NEXT: mrs x19, s3_2_c15_c16_2 // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: expected readable system register // CHECK-ERROR-NEXT: mrs x30, s3_2_c15_c1_8 // CHECK-ERROR-NEXT: ^ +// CHECK-ERROR-NEXT: error: expected readable system register +// CHECK-ERROR-NEXT: mrs x4, s4_7_c15_c15_7 +// CHECK-ERROR-NEXT: ^ +// CHECK-ERROR-NEXT: error: expected readable system register +// CHECK-ERROR-NEXT: mrs x14, s3_7_c16_c15_7 +// CHECK-ERROR-NEXT: ^ //------------------------------------------------------------------------------ // Test and branch (immediate) diff --git a/test/MC/AArch64/basic-a64-instructions.s b/test/MC/AArch64/basic-a64-instructions.s index fd3b67423da..dd8dfd4e36d 100644 --- a/test/MC/AArch64/basic-a64-instructions.s +++ b/test/MC/AArch64/basic-a64-instructions.s @@ -4798,12 +4798,16 @@ _func: mrs x12, s3_7_c15_c1_5 mrs x13, s3_2_c11_c15_7 + mrs x14, s1_3_c9_c2_1 msr s3_0_c15_c0_0, x12 msr s3_7_c11_c13_7, x5 + msr s1_3_c9_c2_1, x4 // CHECK: mrs x12, {{s3_7_c15_c1_5|S3_7_C15_C1_5}} // encoding: [0xac,0xf1,0x3f,0xd5] -// CHECK: mrs x13, {{s3_2_c11_c15_7|S3_2_C11_C15_7}} // encoding: [0xed,0xbf,0x3a,0xd5] +// CHECK: mrs x13, {{s3_2_c11_c15_7|S3_2_C11_C15_7}} // encoding: [0xed,0xbf,0x3a,0xd5] +// CHECK: mrs x14, {{s1_3_c9_c2_1|S1_3_C9_C2_1}} // encoding: [0x2e,0x92,0x2b,0xd5] // CHECK: msr {{s3_0_c15_c0_0|S3_0_C15_C0_0}}, x12 // encoding: [0x0c,0xf0,0x18,0xd5] -// CHECK: msr {{s3_7_c11_c13_7|S3_7_C11_C13_7}}, x5 // encoding: [0xe5,0xbd,0x1f,0xd5] +// CHECK: msr {{s3_7_c11_c13_7|S3_7_C11_C13_7}}, x5 // encoding: [0xe5,0xbd,0x1f,0xd5] +// CHECK: msr {{s1_3_c9_c2_1|S1_3_C9_C2_1}}, x4 // encoding: [0x24,0x92,0x0b,0xd5] //------------------------------------------------------------------------------ // Unconditional branch (immediate)