[llvm] 11ec730 - [LoongArch] Add privilege instructions definition

Weining Lu via llvm-commits llvm-commits at lists.llvm.org
Sat May 14 02:50:06 PDT 2022


Author: Weining Lu
Date: 2022-05-14T17:46:02+08:00
New Revision: 11ec7307a38adcd0ec7a0a9d5bcab11cfce48e2f

URL: https://github.com/llvm/llvm-project/commit/11ec7307a38adcd0ec7a0a9d5bcab11cfce48e2f
DIFF: https://github.com/llvm/llvm-project/commit/11ec7307a38adcd0ec7a0a9d5bcab11cfce48e2f.diff

LOG: [LoongArch] Add privilege instructions definition

These instructions are added by following the `LoongArch Reference
Manual Volume 1: Basic Architecture Version 1.00`.

Differential Revision: https://reviews.llvm.org/D124826

Added: 
    llvm/test/MC/LoongArch/Basic/Privilege/invalid.s
    llvm/test/MC/LoongArch/Basic/Privilege/valid.s

Modified: 
    llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
    llvm/lib/Target/LoongArch/LoongArchInstrFormats.td
    llvm/lib/Target/LoongArch/LoongArchInstrInfo.td

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
index 0c9518233751..d11f5a9080a0 100644
--- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
+++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
@@ -69,6 +69,7 @@ class LoongArchAsmParser : public MCTargetAsmParser {
   enum LoongArchMatchResultTy {
     Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
     Match_RequiresMsbNotLessThanLsb,
+    Match_RequiresOpnd2NotR0R1,
 #define GET_OPERAND_DIAGNOSTIC_TYPES
 #include "LoongArchGenAsmMatcher.inc"
 #undef GET_OPERAND_DIAGNOSTIC_TYPES
@@ -151,7 +152,9 @@ class LoongArchOperand : public MCParsedAsmOperand {
   bool isUImm3() const { return isUImm<3>(); }
   bool isUImm5() const { return isUImm<5>(); }
   bool isUImm6() const { return isUImm<6>(); }
+  bool isUImm8() const { return isUImm<8>(); }
   bool isUImm12() const { return isUImm<12>(); }
+  bool isUImm14() const { return isUImm<14>(); }
   bool isUImm15() const { return isUImm<15>(); }
   bool isSImm12() const { return isSImm<12>(); }
   bool isSImm14lsl2() const { return isSImm<14, 2>(); }
@@ -376,6 +379,12 @@ unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
   switch (Inst.getOpcode()) {
   default:
     break;
+  case LoongArch::CSRXCHG: {
+    unsigned Rj = Inst.getOperand(2).getReg();
+    if (Rj == LoongArch::R0 || Rj == LoongArch::R1)
+      return Match_RequiresOpnd2NotR0R1;
+    return Match_Success;
+  }
   case LoongArch::BSTRINS_W:
   case LoongArch::BSTRINS_D:
   case LoongArch::BSTRPICK_W:
@@ -489,6 +498,8 @@ bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     return Error(ErrorStart, "msb is less than lsb",
                  SMRange(ErrorStart, Operands[4]->getEndLoc()));
   }
+  case Match_RequiresOpnd2NotR0R1:
+    return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1");
   case Match_InvalidUImm2:
     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
                                       /*Upper=*/(1 << 2) - 1);

diff  --git a/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td b/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td
index a41caceec0e3..bebc83a861ae 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td
@@ -322,3 +322,83 @@ class FmtPRELDX<dag outs, dag ins, string opcstr, string opnstr,
   let Inst{9-5} = rj;
   let Inst{4-0} = imm5;
 }
+
+// FmtCSR
+// <opcode[12:5] | csr_num | opcode[4:0] | rd>
+class FmtCSR<bits<13> op, dag outs, dag ins, string opcstr, string opnstr,
+             list<dag> pattern = []>
+    : LAInst<outs, ins, opcstr, opnstr, pattern> {
+  bits<14> csr_num;
+  bits<5> rd;
+
+  let Inst{31-24} = op{12-5};
+  let Inst{23-10} = csr_num;
+  let Inst{9-5} = op{4-0};
+  let Inst{4-0} = rd;
+}
+
+// FmtCSRXCHG
+// <opcode | csr_num | rj | rd>
+class FmtCSRXCHG<bits<8> op, dag outs, dag ins, string opcstr, string opnstr,
+                 list<dag> pattern = []>
+    : LAInst<outs, ins, opcstr, opnstr, pattern> {
+  bits<14> csr_num;
+  bits<5> rj;
+  bits<5> rd;
+
+  let Inst{31-24} = op;
+  let Inst{23-10} = csr_num;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = rd;
+}
+
+// FmtCACOP
+// <0b0000011000 | I12 | rj | I5>
+class FmtCACOP<dag outs, dag ins, string opcstr, string opnstr,
+               list<dag> pattern = []>
+    : LAInst<outs, ins, opcstr, opnstr, pattern> {
+  bits<12> imm12;
+  bits<5> rj;
+  bits<5> op;
+
+  let Inst{31-22} = 0b0000011000;
+  let Inst{21-10} = imm12;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = op;
+}
+
+// FmtIMM32
+// <I32>
+class FmtI32<bits<32> op, string opstr, list<dag> pattern = []>
+    : LAInst<(outs), (ins), opstr, "", pattern> {
+  let Inst{31-0} = op;
+}
+
+// FmtINVTLB
+// <0b00000110010010011 | rk | rj | I5>
+class FmtINVTLB<dag outs, dag ins, string opcstr, string opnstr,
+                list<dag> pattern = []>
+    : LAInst<outs, ins, opcstr, opnstr, pattern> {
+  bits<5> rk;
+  bits<5> rj;
+  bits<5> op;
+
+  let Inst{31-15} = 0b00000110010010011;
+  let Inst{14-10} = rk;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = op;
+}
+
+// FmtLDPTE
+// <0b00000110010001 | seq | rj | 00000>
+class FmtLDPTE<dag outs, dag ins, string opcstr, string opnstr,
+               list<dag> pattern = []>
+    : LAInst<outs, ins, opcstr, opnstr, pattern> {
+  bits<8> seq;
+  bits<5> rj;
+
+  let Inst{31-18} = 0b00000110010001;
+  let Inst{17-10} = seq;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = 0b00000;
+}

diff  --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 477e12db952f..78885dc1cfa9 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -60,10 +60,18 @@ def uimm6 : Operand<GRLenVT> {
   let ParserMatchClass = UImmAsmOperand<6>;
 }
 
+def uimm8 : Operand<GRLenVT> {
+  let ParserMatchClass = UImmAsmOperand<8>;
+}
+
 def uimm12 : Operand<GRLenVT> {
   let ParserMatchClass = UImmAsmOperand<12>;
 }
 
+def uimm14 : Operand<GRLenVT> {
+  let ParserMatchClass = UImmAsmOperand<14>;
+}
+
 def uimm15 : Operand<GRLenVT> {
   let ParserMatchClass = UImmAsmOperand<15>;
 }
@@ -205,6 +213,12 @@ class SCBase<bits<8> op, string opstr>
     : Fmt2RI14<op, (outs GPR:$dst), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14),
                opstr, "$rd, $rj, $imm14">;
 
+class IOCSRRD<bits<22> op, string opstr>
+    : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), opstr, "$rd, $rj">;
+
+class IOCSRWR<bits<22> op, string opstr>
+    : Fmt2R<op, (outs), (ins GPR:$rd, GPR:$rj), opstr, "$rd, $rj">;
+
 //===----------------------------------------------------------------------===//
 // Basic Integer Instructions
 //===----------------------------------------------------------------------===//
@@ -536,3 +550,55 @@ def : InstAlias<"move $dst, $src", (OR GPR:$dst, GPR:$src, R0)>;
 
 include "LoongArchFloat32InstrInfo.td"
 include "LoongArchFloat64InstrInfo.td"
+
+//===----------------------------------------------------------------------===//
+// Privilege Instructions
+//===----------------------------------------------------------------------===//
+
+// CSR Access Instructions
+def CSRRD : FmtCSR<0b0000010000000, (outs GPR:$rd), (ins uimm14:$csr_num),
+                   "csrrd", "$rd, $csr_num">;
+let Constraints = "$rd = $dst" in {
+def CSRWR : FmtCSR<0b0000010000001, (outs GPR:$dst),
+                   (ins GPR:$rd, uimm14:$csr_num), "csrwr", "$rd, $csr_num">;
+def CSRXCHG : FmtCSRXCHG<0b00000100, (outs GPR:$dst),
+                         (ins GPR:$rd, GPR:$rj, uimm14:$csr_num),
+                         "csrxchg", "$rd, $rj, $csr_num">;
+} // Constraints = "$rd = $dst"
+
+// IOCSR Access Instructions
+def IOCSRRD_B : IOCSRRD<0b0000011001001000000000, "iocsrrd.b">;
+def IOCSRRD_H : IOCSRRD<0b0000011001001000000001, "iocsrrd.h">;
+def IOCSRRD_W : IOCSRRD<0b0000011001001000000010, "iocsrrd.w">;
+def IOCSRWR_B : IOCSRWR<0b0000011001001000000100, "iocsrwr.b">;
+def IOCSRWR_H : IOCSRWR<0b0000011001001000000101, "iocsrwr.h">;
+def IOCSRWR_W : IOCSRWR<0b0000011001001000000110, "iocsrwr.w">;
+let Predicates = [IsLA64] in {
+def IOCSRRD_D : IOCSRRD<0b0000011001001000000011, "iocsrrd.d">;
+def IOCSRWR_D : IOCSRWR<0b0000011001001000000111, "iocsrwr.d">;
+} // Predicates = [IsLA64]
+
+// Cache Maintenance Instructions
+def CACOP : FmtCACOP<(outs), (ins uimm5:$op, GPR:$rj, simm12:$imm12), "cacop",
+                     "$op, $rj, $imm12">;
+
+// TLB Maintenance Instructions
+def TLBSRCH  : FmtI32<0b00000110010010000010100000000000, "tlbsrch">;
+def TLBRD    : FmtI32<0b00000110010010000010110000000000, "tlbrd">;
+def TLBWR    : FmtI32<0b00000110010010000011000000000000, "tlbwr">;
+def TLBFILL  : FmtI32<0b00000110010010000011010000000000, "tlbfill">;
+def TLBCLR   : FmtI32<0b00000110010010000010000000000000, "tlbclr">;
+def TLBFLUSH : FmtI32<0b00000110010010000010010000000000, "tlbflush">;
+def INVTLB : FmtINVTLB<(outs), (ins GPR:$rk, GPR:$rj, uimm5:$op), "invtlb",
+                       "$op, $rj, $rk">;
+
+// Software Page Walking Instructions
+def LDDIR : Fmt2RI8<0b00000110010000, (outs GPR:$rd),
+                    (ins GPR:$rj, uimm8:$imm8), "lddir", "$rd, $rj, $imm8">;
+def LDPTE : FmtLDPTE<(outs), (ins GPR:$rj, uimm8:$seq), "ldpte", "$rj, $seq">;
+
+
+// Other Miscellaneous Instructions
+def ERTN : FmtI32<0b00000110010010000011100000000000, "ertn">;
+def DBCL : MISC_I15<0b00000000001010101, "dbcl">;
+def IDLE : MISC_I15<0b00000110010010001, "idle">;

diff  --git a/llvm/test/MC/LoongArch/Basic/Privilege/invalid.s b/llvm/test/MC/LoongArch/Basic/Privilege/invalid.s
new file mode 100644
index 000000000000..380b848a6af9
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Privilege/invalid.s
@@ -0,0 +1,14 @@
+# RUN: not llvm-mc --triple=loongarch32 %s 2>&1 | FileCheck %s --check-prefixes=ERR,ERR32
+# RUN: not llvm-mc --triple=loongarch64 %s 2>&1 | FileCheck %s --check-prefix=ERR
+
+## csrxchg: rj != 0,1
+csrxchg $a0, $zero, 0
+# ERR: :[[#@LINE-1]]:15: error: must not be $r0 or $r1
+csrxchg $a0, $ra, 0
+# ERR: :[[#@LINE-1]]:15: error: must not be $r0 or $r1
+
+## LoongArch64 mnemonics
+iocsrrd.d $a0, $a1
+# ERR32: :[[#@LINE-1]]:1: error: instruction requires the following: LA64 Basic Integer and Privilege Instruction Set
+iocsrwr.d $a0, $a1
+# ERR32: :[[#@LINE-1]]:1: error: instruction requires the following: LA64 Basic Integer and Privilege Instruction Set

diff  --git a/llvm/test/MC/LoongArch/Basic/Privilege/valid.s b/llvm/test/MC/LoongArch/Basic/Privilege/valid.s
new file mode 100644
index 000000000000..1d5ca68664d4
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Privilege/valid.s
@@ -0,0 +1,118 @@
+## Test valid privilege instructions
+
+# RUN: llvm-mc %s --triple=loongarch32 --show-encoding \
+# RUN:     | FileCheck --check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --show-encoding --defsym=LA64=1 \
+# RUN:     | FileCheck --check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ,CHECK64-ASM,CHECK64-ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch32 --filetype=obj | llvm-objdump -d - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --filetype=obj --defsym=LA64=1 | llvm-objdump -d - \
+# RUN:     | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ,CHECK64-ASM-AND-OBJ %s
+
+#############################################################
+## Instructions for both loongarch32 and loongarch64
+#############################################################
+
+# CHECK-ASM-AND-OBJ: csrrd $s3, 30
+# CHECK-ASM: encoding: [0x1a,0x78,0x00,0x04]
+csrrd $s3, 30
+
+# CHECK-ASM-AND-OBJ: csrwr $s1, 194
+# CHECK-ASM: encoding: [0x38,0x08,0x03,0x04]
+csrwr $s1, 194
+
+# CHECK-ASM-AND-OBJ: csrxchg $a2, $s4, 214
+# CHECK-ASM: encoding: [0x66,0x5b,0x03,0x04]
+csrxchg $a2, $s4, 214
+
+# CHECK-ASM-AND-OBJ: iocsrrd.b $s3, $s1
+# CHECK-ASM: encoding: [0x1a,0x03,0x48,0x06]
+iocsrrd.b $s3, $s1
+
+# CHECK-ASM-AND-OBJ: iocsrrd.h $a1, $s4
+# CHECK-ASM: encoding: [0x65,0x07,0x48,0x06]
+iocsrrd.h $a1, $s4
+
+# CHECK-ASM-AND-OBJ: iocsrrd.w $a6, $t8
+# CHECK-ASM: encoding: [0x8a,0x0a,0x48,0x06]
+iocsrrd.w $a6, $t8
+
+# CHECK-ASM-AND-OBJ: iocsrwr.b $a0, $s0
+# CHECK-ASM: encoding: [0xe4,0x12,0x48,0x06]
+iocsrwr.b $a0, $s0
+
+# CHECK-ASM-AND-OBJ: iocsrwr.h $a7, $zero
+# CHECK-ASM: encoding: [0x0b,0x14,0x48,0x06]
+iocsrwr.h $a7, $zero
+
+# CHECK-ASM-AND-OBJ: iocsrwr.w $t8, $s3
+# CHECK-ASM: encoding: [0x54,0x1b,0x48,0x06]
+iocsrwr.w $t8, $s3
+
+# CHECK-ASM-AND-OBJ: cacop 0, $a6, 27
+# CHECK-ASM: encoding: [0x40,0x6d,0x00,0x06]
+cacop 0, $a6, 27
+
+# CHECK-ASM-AND-OBJ: tlbclr
+# CHECK-ASM: encoding: [0x00,0x20,0x48,0x06]
+tlbclr
+
+# CHECK-ASM-AND-OBJ: tlbflush
+# CHECK-ASM: encoding: [0x00,0x24,0x48,0x06]
+tlbflush
+
+# CHECK-ASM-AND-OBJ: tlbsrch
+# CHECK-ASM: encoding: [0x00,0x28,0x48,0x06]
+tlbsrch
+
+# CHECK-ASM-AND-OBJ: tlbrd
+# CHECK-ASM: encoding: [0x00,0x2c,0x48,0x06]
+tlbrd
+
+# CHECK-ASM-AND-OBJ: tlbwr
+# CHECK-ASM: encoding: [0x00,0x30,0x48,0x06]
+tlbwr
+
+# CHECK-ASM-AND-OBJ: tlbfill
+# CHECK-ASM: encoding: [0x00,0x34,0x48,0x06]
+tlbfill
+
+# CHECK-ASM-AND-OBJ: invtlb 16, $s6, $s2
+# CHECK-ASM: encoding: [0xb0,0xe7,0x49,0x06]
+invtlb 16, $s6, $s2
+
+# CHECK-ASM-AND-OBJ: lddir $t0, $s7, 92
+# CHECK-ASM: encoding: [0xcc,0x73,0x41,0x06]
+lddir $t0, $s7, 92
+
+# CHECK-ASM-AND-OBJ: ldpte $t6, 200
+# CHECK-ASM: encoding: [0x40,0x22,0x47,0x06]
+ldpte $t6, 200
+
+# CHECK-ASM-AND-OBJ: ertn
+# CHECK-ASM: encoding: [0x00,0x38,0x48,0x06]
+ertn
+
+# CHECK-ASM-AND-OBJ: dbcl 201
+# CHECK-ASM: encoding: [0xc9,0x80,0x2a,0x00]
+dbcl 201
+
+# CHECK-ASM-AND-OBJ: idle 204
+# CHECK-ASM: encoding: [0xcc,0x80,0x48,0x06]
+idle 204
+
+#############################################################
+## Instructions only for loongarch64
+#############################################################
+
+.ifdef LA64
+
+# CHECK64-ASM-AND-OBJ: iocsrrd.d $t5, $s2
+# CHECK64-ASM: encoding: [0x31,0x0f,0x48,0x06]
+iocsrrd.d $t5, $s2
+
+# CHECK64-ASM-AND-OBJ: iocsrwr.d $t8, $a3
+# CHECK64-ASM: encoding: [0xf4,0x1c,0x48,0x06]
+iocsrwr.d $t8, $a3
+
+.endif


        


More information about the llvm-commits mailing list