Added hint instructions to decoder (simulated as nops)

PiperOrigin-RevId: 797052407
Change-Id: I557a4b4ae7efa1070f68d7e84521019c83d67e01
diff --git a/riscv/riscv32g.bin_fmt b/riscv/riscv32g.bin_fmt
index 5cb31e5..da8ec7e 100644
--- a/riscv/riscv32g.bin_fmt
+++ b/riscv/riscv32g.bin_fmt
@@ -26,9 +26,11 @@
 #include "riscv_format32.bin_fmt"
 #include "riscv_format16.bin_fmt"
 
-instruction group RiscVGInst32[32] : Inst32Format {
-  lui    : UType  : opcode == 0b011'0111;
-  auipc  : UType  : opcode == 0b001'0111;
+instruction group RiscVGInst32 = {RiscVGInstBase32, RiscVGHints32};
+
+instruction group RiscVGInstBase32[32] : Inst32Format {
+  lui    : UType  : opcode == 0b011'0111, rd != 0;
+  auipc  : UType  : opcode == 0b001'0111, rd != 0;
   jal    : JType  : rd != 0, opcode == 0b110'1111;
   j      : JType  : rd == 0, opcode == 0b110'1111;
   jalr   : IType  : rd != 0, func3 == 0b000, opcode == 0b110'0111;
@@ -47,25 +49,26 @@
   sb     : SType  : func3 == 0b000, opcode == 0b010'0011;
   sh     : SType  : func3 == 0b001, opcode == 0b010'0011;
   sw     : SType  : func3 == 0b010, opcode == 0b010'0011;
-  addi   : IType  : func3 == 0b000, opcode == 0b001'0011;
-  slti   : IType  : func3 == 0b010, opcode == 0b001'0011;
-  sltiu  : IType  : func3 == 0b011, opcode == 0b001'0011;
-  xori   : IType  : func3 == 0b100, opcode == 0b001'0011;
+  addi   : IType  : func3 == 0b000, opcode == 0b001'0011, rd != 0;
+  nop    : IType  : func3 == 0b000, opcode == 0b001'0011, rd == 0, imm12 == 0, rs1 == 0;
+  slti   : IType  : func3 == 0b010, opcode == 0b001'0011, rd != 0;
+  sltiu  : IType  : func3 == 0b011, opcode == 0b001'0011, rd != 0;
+  xori   : IType  : func3 == 0b100, rd != 0, opcode == 0b001'0011;
   ori    : IType  : func3 == 0b110, rd != 0b00000, opcode == 0b001'0011;
-  andi   : IType  : func3 == 0b111, opcode == 0b001'0011;
+  andi   : IType  : func3 == 0b111, opcode == 0b001'0011, rd != 0;
   slli   : RType  : func7 == 0b000'0000, func3==0b001, opcode == 0b001'0011;
-  srli   : RType  : func7 == 0b000'0000, func3==0b101, opcode == 0b001'0011;
+  srli   : RType  : func7 == 0b000'0000, func3==0b101, rd != 0, opcode == 0b001'0011;
   srai   : RType  : func7 == 0b010'0000, func3==0b101, opcode == 0b001'0011;
   add    : RType  : func7 == 0b000'0000, func3==0b000, rd != 0, opcode == 0b011'0011;
-  sub    : RType  : func7 == 0b010'0000, func3==0b000, opcode == 0b011'0011;
-  sll    : RType  : func7 == 0b000'0000, func3==0b001, opcode == 0b011'0011;
-  slt    : RType  : func7 == 0b000'0000, func3==0b010, opcode == 0b011'0011;
-  sltu   : RType  : func7 == 0b000'0000, func3==0b011, opcode == 0b011'0011;
-  xor    : RType  : func7 == 0b000'0000, func3==0b100, opcode == 0b011'0011;
-  srl    : RType  : func7 == 0b000'0000, func3==0b101, opcode == 0b011'0011;
-  sra    : RType  : func7 == 0b010'0000, func3==0b101, opcode == 0b011'0011;
-  or     : RType  : func7 == 0b000'0000, func3==0b110, opcode == 0b011'0011;
-  and    : RType  : func7 == 0b000'0000, func3==0b111, opcode == 0b011'0011;
+  sub     : RType : func7 == 0b010'0000, func3==0b000, rd != 0, opcode == 0b011'0011;
+  sll     : RType : func7 == 0b000'0000, func3==0b001, rd != 0, opcode == 0b011'0011;
+  slt     : RType : func7 == 0b000'0000, func3==0b010, rd != 0, opcode == 0b011'0011;
+  sltu    : RType : func7 == 0b000'0000, func3==0b011, rd != 0, opcode == 0b011'0011;
+  xor     : RType : func7 == 0b000'0000, func3==0b100, rd != 0, opcode == 0b011'0011;
+  srl     : RType : func7 == 0b000'0000, func3==0b101, rd != 0, opcode == 0b011'0011;
+  sra     : RType : func7 == 0b010'0000, func3==0b101, rd != 0, opcode == 0b011'0011;
+  or      : RType : func7 == 0b000'0000, func3==0b110, rd != 0, opcode == 0b011'0011;
+  and     : RType : func7 == 0b000'0000, func3==0b111, rd != 0, opcode == 0b011'0011;
   fence     : Fence : fm == 0b0000, succ != 0b0000, func3 == 0b000, opcode == 0b000'1111;
   fence_tso : Fence : fm == 0b1000, pred == 0b0011, succ == 0b0011, func3 == 0b000, opcode == 0b000'1111;
   ecall  : Inst32Format : bits == 0b0000'0000'0000'00000'000'00000, opcode == 0b111'0011;
@@ -176,8 +179,49 @@
   sfence_vma_nn : RType : func7 == 0b000'1001, rs2 != 0, rs1 != 0, func3 == 0, rd == 0, opcode == 0b111'0011;
 };
 
+// Encoding for RiscV hint instructions.
+instruction group RiscVGHints32[32] : Inst32Format {
+  lui_hint: UType      : opcode == 0b011'0111, rd == 0;
+  auipc_hint: UType    : opcode == 0b001'0111, rd == 0;
+  addi_hint1: IType    : func3 == 0b000, opcode == 0b001'0011, rd == 0, rs1 != 0;
+  addi_hint2: IType    : func3 == 0b000, opcode == 0b001'0011, rd == 0, imm12 != 0;
+  slti_hint : IType    : func3 == 0b010, opcode == 0b001'0011, rd == 0;
+  sltiu_hint: IType    : func3 == 0b011, opcode == 0b001'0011, rd == 0;
+  xori_hint: IType     : func3 == 0b100, rd == 0, opcode == 0b001'0011;
+  ori_hint: IType      : func3 == 0b110, rd == 0b00000, opcode == 0b001'0011;
+  andi_hint: IType     : func3 == 0b111, opcode == 0b001'0011, rd == 0;
+  srli_hint: RType     : func7 == 0b000'0000, func3==0b101, rd == 0, opcode == 0b001'0011;
+  slt_hint: RType      : func7 == 0b000'0000, func3==0b010, rd == 0, opcode == 0b011'0011;
+  slli_semihost: RType : func7 == 0b000'0000, func3==0b001, rd == 0, rs1 == 0, r_uimm5 == 31, opcode == 0b001'0011;
+  slli_hint1: RType    : func7 == 0b000'0000, func3==0b001, rd == 0, rs1 != 0, opcode == 0b001'0011;
+  slli_hint2: RType    : func7 == 0b000'0000, func3==0b001, rd == 0, r_uimm5 != 31, opcode == 0b001'0011;
+  srai_semihost: RType : func7 == 0b010'0000, func3==0b101, rd == 0, rs1 == 0, r_uimm5 == 7, opcode == 0b001'0011;
+  srai_hint1:    RType : func7 == 0b010'0000, func3==0b101, rd == 0, rs1 != 0, opcode == 0b001'0011;
+  srai_hint2:    RType : func7 == 0b010'0000, func3==0b101, rd == 0, r_uimm5 != 7, opcode == 0b001'0011;
+  add_hint1: RType     : func7 == 0b000'0000, func3==0b000, rd == 0, rs1 != 0, opcode == 0b011'0011;
+  add_hint2: RType     : func7 == 0b000'0000, func3==0b000, rd == 0, rs1 == 0, rs2 > 5, opcode == 0b011'0011;
+  add_hint3: RType     : func7 == 0b000'0000, func3==0b000, rd == 0, rs1 == 0, rs2 < 2, opcode == 0b011'0011;
+  sub_hint: RType      : func7 == 0b010'0000, func3==0b000, rd == 0, opcode == 0b011'0011;
+  sll_hint: RType      : func7 == 0b000'0000, func3==0b001, rd == 0, opcode == 0b011'0011;
+  sltu_hint: RType     : func7 == 0b000'0000, func3==0b011, rd == 0, opcode == 0b011'0011;
+  xor_hint: RType      : func7 == 0b000'0000, func3==0b100, rd == 0, opcode == 0b011'0011;
+  srl_hint: RType      : func7 == 0b000'0000, func3==0b101, rd == 0, opcode == 0b011'0011;
+  sra_hint: RType      : func7 == 0b010'0000, func3==0b101, rd == 0, opcode == 0b011'0011;
+  or_hint : RType      : func7 == 0b000'0000, func3==0b110, rd == 0, opcode == 0b011'0011;
+  and_hint: RType      : func7 == 0b000'0000, func3==0b111, rd == 0, opcode == 0b011'0011;
+  fence_hint1: Fence   : func3==0b000, rd == 0, rs1 != 0, fm == 0, pred == 0, opcode == 0b000'1111;
+  fence_hint2: Fence   : func3==0b000, rd == 0, rs1 != 0, fm == 0, succ == 0, opcode == 0b000'1111;
+  fence_hint3: Fence   : func3==0b000, rd != 0, rs1 == 0, fm == 0, pred == 0, opcode == 0b000'1111;
+  fence_hint4: Fence   : func3==0b000, rd != 0, rs1 == 0, fm == 0, succ == 0, opcode == 0b000'1111;
+  fence_hint5: Fence   : func3==0b000, rd == 0, rs1 == 0, fm == 0, pred == 0, succ != 0, opcode == 0b000'1111;
+  fence_hint6: Fence   : func3==0b000, rd == 0, rs1 == 0, fm == 0, succ == 0, opcode == 0b000'1111;
+  fence_hint7: Fence   : func3==0b000, rd != 0, rs1 == 0, fm == 0, pred != 1, succ == 0, opcode == 0b000'1111;
+};
+
+instruction group RiscVCInst16 = {RiscVCInstBase16, RiscVCHints16};
+
 // Compact instruction encodings.
-instruction group RiscVCInst16[16] : Inst16Format {
+instruction group RiscVCInstBase16[16] : Inst16Format {
   caddi4spn : CIW: func3 == 0b000, op == 0b00, imm8 != 0;
   cfld      : CL : func3 == 0b001, op == 0b00;
   clw       : CL : func3 == 0b010, op == 0b00;
@@ -187,7 +231,6 @@
   cfsw      : CS : func3 == 0b111, op == 0b00;
   cnop      : CI : func3 == 0b000, imm1 == 0, rs1 == 0, imm5 == 0, op == 0b01;
   caddi     : CI : func3 == 0b000, imm6 != 0, rd != 0, op == 0b01;
-  caddi_hint: CI : func3 == 0b000, imm6 == 0, rd != 0, op == 0b01;
   cjal      : CJ : func3 == 0b001, op == 0b01;
   cli       : CI : func3 == 0b010, rd != 0, op == 0b01;
   caddi16sp : CI : func3 == 0b011, rd == 2, op == 0b01;
@@ -211,9 +254,18 @@
   cebreak   : CR : func4 == 0b1001, rs1 == 0, rs2 == 0, op == 0b10;
   cjalr     : CR : func4 == 0b1001, rs1 != 0, rs2 == 0, op == 0b10;
   cadd      : CR : func4 == 0b1001, rs1 != 0, rs2 != 0, op == 0b10;
-  cadd_hint : CR : func4 == 0b1001, rs1 == 0,rs2 != 0, op == 0b10;
   cfsdsp    : CSS: func3 == 0b101, op == 0b10;
   cswsp     : CSS: func3 == 0b110, op == 0b10;
   cfswsp    : CSS: func3 == 0b111, op == 0b10;
   cunimp   : Inst16Format : func3 == 0b000, bits == 0b000'0000'0000, op == 0b00;
 };
+
+instruction group RiscVCHints16[16] : Inst16Format {
+  cnop_hint : CI : func3 == 0b000, imm6 != 0, rs1 == 0, op == 0b01;
+  caddi_hint: CI : func3 == 0b000, imm6 == 0, rd != 0, op == 0b01;
+  cli_hint  : CI : func3 == 0b010, rd == 0, op == 0b01;
+  clui_hint : CI : func3 == 0b011, rd == 0, imm6 != 0, op == 0b01;
+  cmv_hint  : CR : func4 == 0b1000, rs1 == 0, rs2 != 0, op == 0b10;
+  cslli_hint: CI : func3 == 0b000, imm6 != 0, rd == 0, op == 0b10;
+  cadd_hint : CR : func4 == 0b1001, rs1 == 0, rs2 != 0, rs2 != 2, rs2 != 3, rs2 != 4, rs2 != 5, op == 0b10;
+};
\ No newline at end of file
diff --git a/riscv/riscv32g.isa b/riscv/riscv32g.isa
index 828c820..04c3167 100644
--- a/riscv/riscv32g.isa
+++ b/riscv/riscv32g.isa
@@ -42,6 +42,10 @@
       resources: TwoOp,
       disasm: "addi", "%rd, %rs1, %I_imm12",
       semfunc: "&RV32::RiscVIAdd";
+    nop{},
+      resources: { next_pc },
+      disasm: "nop",
+      semfunc: "&RiscVINop";
     slti{: rs1, I_imm12 : rd},
       resources: TwoOp,
       disasm: "slti", "%rd, %rs1, %I_imm12",
@@ -122,9 +126,6 @@
       resources: ThreeOp,
       disasm: "sra", "%rd, %rs1, %rs2",
       semfunc: "&RV32::RiscVISra";
-    nop{},
-      disasm: "nop",
-      semfunc: "&RiscVINop";
     hint{},
       disasm: "hint",
       semfunc: "&RiscVINop";
@@ -218,6 +219,153 @@
   }
 }
 
+// This slot contains the hint instructions. These execute as nops, but can be
+// changed to provide performance hints to a simulated microarchitecture.
+slot riscv32_hints {
+  includes {
+    #include "riscv/riscv_i_instructions.h"
+  }
+  default size = 4;
+  default latency = global_latency;
+  resources TwoOp = { next_pc, rs1 : rd[..rd]};
+  resources ThreeOp = { next_pc, rs1, rs2 : rd[..rd]};
+  opcodes {
+    addi_hint1{: rs1, I_imm12 : rd},
+      resources: TwoOp,
+      disasm: "addi.hint", "%rd, %rs1, %I_imm12",
+      semfunc: "&RiscVINop";
+    addi_hint2{: rs1, I_imm12 : rd},
+      resources: TwoOp,
+      disasm: "addi.hint", "%rd, %rs1, %I_imm12",
+      semfunc: "&RiscVINop";
+    slti_hint{: rs1, I_imm12 : rd},
+      resources: TwoOp,
+      disasm: "slti.hint", "%rd, %rs1, %I_imm12",
+      semfunc: "&RiscVINop";
+    sltiu_hint{: rs1, I_imm12 : rd},
+      resources: TwoOp,
+      disasm: "sltiu.hint", "%rd, %rs1, %I_imm12",
+      semfunc: "&RiscVINop";
+    andi_hint{: rs1, I_imm12 : rd},
+      resources: TwoOp,
+      disasm: "andi.hint", "%rd, %rs1, %I_imm12",
+      semfunc: "&RiscVINop";
+    ori_hint{: rs1, I_imm12 : rd},
+      resources: TwoOp,
+      disasm: "ori.hint", "%rd, %rs1, %I_imm12",
+      semfunc: "&RiscVINop";
+    xori_hint{: rs1, I_imm12 : rd},
+      resources: TwoOp,
+      disasm: "xori.hint", "%rd, %rs1, %I_imm12",
+      semfunc: "&RiscVINop";
+    slli_semihost{: rs1, I_uimm5 : rd},
+      resources: TwoOp,
+      disasm: "slli.semihost", "%rd, %rs1, 0x%(I_uimm5:x)",
+      semfunc: "&RiscVINop";
+    slli_hint1{: rs1, I_uimm5 : rd},
+      resources: TwoOp,
+      disasm: "slli.hint", "%rd, %rs1, 0x%(I_uimm5:x)",
+      semfunc: "&RiscVINop";
+    slli_hint2{: rs1, I_uimm5 : rd},
+      resources: TwoOp,
+      disasm: "slli.hint", "%rd, %rs1, 0x%(I_uimm5:x)",
+      semfunc: "&RiscVINop";
+    srli_hint{: rs1, I_uimm5 : rd},
+      resources: TwoOp,
+      disasm: "srli.hint", "%rd  %rs1, 0x%(I_uimm5:x)",
+      semfunc: "&RiscVINop";
+    srai_semihost{: rs1, I_uimm5 : rd},
+      resources: TwoOp,
+      disasm: "srai.semihost", "%rd, %rs1, 0x%(I_uimm5:x)",
+      semfunc: "&RiscVINop";
+    srai_hint1{: rs1, I_uimm5 : rd},
+      resources: TwoOp,
+      disasm: "srai.hint", "%rd, %rs1, 0x%(I_uimm5:x)",
+      semfunc: "&RiscVINop";
+    srai_hint2{: rs1, I_uimm5 : rd},
+      resources: TwoOp,
+      disasm: "srai.hint", "%rd, %rs1, 0x%(I_uimm5:x)",
+      semfunc: "&RiscVINop";
+    lui_hint{: U_imm20 : rd},
+      resources: { next_pc : rd[0..]},
+      disasm: "lui.hint", "%rd, 0x%(U_imm20:08x)",
+      semfunc: "&RiscVINop";
+    auipc_hint{: U_imm20 : rd},
+      resources: { next_pc : rd[0..]},
+      disasm: "auipc.hint", "%rd, 0x%(U_imm20:08x)",
+      semfunc: "&RiscVINop";
+    add_hint1{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "add.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    add_hint2{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "add.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    add_hint3{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "add.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    and_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "and.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    or_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "or.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    xor_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "xor.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    sll_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "sll.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    srl_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "srl.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    sub_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "sub.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    sra_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "sra.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    slt_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "slt", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    sltu_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "sltu", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    fence_hint1{: pred, succ :},
+      disasm: "fence.hint",
+      semfunc: "&RiscVINop";
+    fence_hint2{: pred, succ :},
+      disasm: "fence.hint",
+      semfunc: "&RiscVINop";
+    fence_hint3{: pred, succ :},
+      disasm: "fence.hint",
+      semfunc: "&RiscVINop";
+    fence_hint4{: pred, succ :},
+      disasm: "fence.hint",
+      semfunc: "&RiscVINop";
+    fence_hint5{: pred, succ :},
+      disasm: "fence.hint",
+      semfunc: "&RiscVINop";
+    fence_hint6{: pred, succ :},
+      disasm: "fence.hint",
+      semfunc: "&RiscVINop";
+    fence_hint7{: pred, succ :},
+      disasm: "fence.hint",
+      semfunc: "&RiscVINop";
+  }
+}
+
 // Privileged instructions.
 slot privileged {
   includes {
@@ -794,9 +942,6 @@
       resources: {next_pc, rd : rd[0..]},
       disasm: "addi", "%rd, %rd, %I_ci_imm6",
       semfunc: "&RV32::RiscVIAdd";
-    caddi_hint{},
-      disasm: "caddi_hint",
-      semfunc: "&RiscVINop";
     caddi16sp{: x2, I_ci_imm6x16 : x2},
       resources: {next_pc, x2 : x2[0..]},
       disasm: "addi", "%x2, %x2, %(I_ci_imm6x16:d)",
@@ -829,9 +974,6 @@
       resources: {next_pc, crs2, rd : rd[0..]},
       disasm: "add", "%rd, %rd, %crs2",
       semfunc: "&RV32::RiscVIAdd";
-    cadd_hint{},
-      disasm: "cadd_hint",
-      semfunc: "&RiscVINop";
     cand{: c3rs1, c3rs2 : c3rs1},
       resources: {next_pc, c3rs1, c3rs2 : c3rs1[0..]},
       disasm: "and", "%c3rs1, %c3rs1, %c3rs2",
@@ -863,8 +1005,36 @@
   }
 }
 
+slot riscv32chints {
+  default size = 2;
+  default latency = global_latency;
+  opcodes {
+    cnop_hint{},
+      disasm: "cnop.hint",
+      semfunc: "&RiscVINop";
+    cli_hint{},
+      disasm: "cli.hint",
+      semfunc: "&RiscVINop";
+    clui_hint{},
+      disasm: "clui.hint",
+      semfunc: "&RiscVINop";
+    cmv_hint{},
+      disasm: "cmv.hint",
+      semfunc: "&RiscVINop";
+    caddi_hint{},
+      disasm: "caddi.hint",
+      semfunc: "&RiscVINop";
+    cslli_hint{},
+      disasm: "cslli.hint",
+      semfunc: "&RiscVINop";
+    cadd_hint{},
+      disasm: "cadd.hint",
+      semfunc: "&RiscVINop";
+  }
+}
+
 // This should be the RiscV32G set, where G stands for IMAFDZicsr_Zifencei.
-slot riscv32g : riscv32i, riscv32c, riscv32m, riscv32_amo_arithmetic, riscv32f, riscv32d, zicsr, zfencei, privileged {
+slot riscv32g : riscv32i, riscv32c, riscv32chints, riscv32m, riscv32_amo_arithmetic, riscv32f, riscv32d, riscv32_hints, zicsr, zfencei, privileged {
   default size = 4;
   default opcode =
     disasm: "Illegal instruction at 0x%(@:08x)",
diff --git a/riscv/riscv64g.bin_fmt b/riscv/riscv64g.bin_fmt
index f749576..7224ead 100644
--- a/riscv/riscv64g.bin_fmt
+++ b/riscv/riscv64g.bin_fmt
@@ -26,7 +26,9 @@
 #include "riscv_format32.bin_fmt"
 #include "riscv_format16.bin_fmt"
 
-instruction group RiscVGInst32[32] : Inst32Format {
+instruction group RiscVGInst32 = {RiscVGInstBase32, RiscVGHints32};
+
+instruction group RiscVGInstBase32[32] : Inst32Format {
   lui    : UType  : opcode == 0b011'0111;
   auipc  : UType  : opcode == 0b001'0111;
   jal    : JType  : rd != 0, opcode == 0b110'1111;
@@ -51,6 +53,7 @@
   sw     : SType  : func3 == 0b010, opcode == 0b010'0011;
   sd     : SType  : func3 == 0b011, opcode == 0b010'0011;
   addi   : IType  : func3 == 0b000, opcode == 0b001'0011;
+  nop    : IType  : func3 == 0b000, opcode == 0b001'0011, rd == 0, imm12 == 0, rs1 == 0;
   addiw  : IType  : func3 == 0b000, opcode == 0b001'1011;
   slti   : IType  : func3 == 0b010, opcode == 0b001'0011;
   sltiu  : IType  : func3 == 0b011, opcode == 0b001'0011;
@@ -218,8 +221,50 @@
   sfence_vma_nn : RType : func7 == 0b000'1001, rs2 != 0, rs1 != 0, func3 == 0, rd == 0, opcode == 0b111'0011;
 };
 
+
+// Encoding for RiscV hint instructions.
+instruction group RiscVGHints32[32] : Inst32Format {
+  lui_hint: UType      : opcode == 0b011'0111, rd == 0;
+  auipc_hint: UType    : opcode == 0b001'0111, rd == 0;
+  addi_hint1: IType    : func3 == 0b000, opcode == 0b001'0011, rd == 0, rs1 != 0;
+  addi_hint2: IType    : func3 == 0b000, opcode == 0b001'0011, rd == 0, imm12 != 0;
+  slti_hint : IType    : func3 == 0b010, opcode == 0b001'0011, rd == 0;
+  sltiu_hint: IType    : func3 == 0b011, opcode == 0b001'0011, rd == 0;
+  xori_hint: IType     : func3 == 0b100, rd == 0, opcode == 0b001'0011;
+  ori_hint: IType      : func3 == 0b110, rd == 0b00000, opcode == 0b001'0011;
+  andi_hint: IType     : func3 == 0b111, opcode == 0b001'0011, rd == 0;
+  srli_hint: RType     : func7 == 0b000'0000, func3==0b101, rd == 0, opcode == 0b001'0011;
+  slt_hint: RType      : func7 == 0b000'0000, func3==0b010, rd == 0, opcode == 0b011'0011;
+  slli_semihost: RType : func7 == 0b000'0000, func3==0b001, rd == 0, rs1 == 0, r_uimm5 == 31, opcode == 0b001'0011;
+  slli_hint1: RType    : func7 == 0b000'0000, func3==0b001, rd == 0, rs1 != 0, opcode == 0b001'0011;
+  slli_hint2: RType    : func7 == 0b000'0000, func3==0b001, rd == 0, r_uimm5 != 31, opcode == 0b001'0011;
+  srai_semihost: RType : func7 == 0b010'0000, func3==0b101, rd == 0, rs1 == 0, r_uimm5 == 7, opcode == 0b001'0011;
+  srai_hint1:    RType : func7 == 0b010'0000, func3==0b101, rd == 0, rs1 != 0, opcode == 0b001'0011;
+  srai_hint2:    RType : func7 == 0b010'0000, func3==0b101, rd == 0, r_uimm5 != 7, opcode == 0b001'0011;
+  add_hint1: RType     : func7 == 0b000'0000, func3==0b000, rd == 0, rs1 != 0, opcode == 0b011'0011;
+  add_hint2: RType     : func7 == 0b000'0000, func3==0b000, rd == 0, rs1 == 0, rs2 > 5, opcode == 0b011'0011;
+  add_hint3: RType     : func7 == 0b000'0000, func3==0b000, rd == 0, rs1 == 0, rs2 < 2, opcode == 0b011'0011;
+  sub_hint: RType      : func7 == 0b010'0000, func3==0b000, rd == 0, opcode == 0b011'0011;
+  sll_hint: RType      : func7 == 0b000'0000, func3==0b001, rd == 0, opcode == 0b011'0011;
+  sltu_hint: RType     : func7 == 0b000'0000, func3==0b011, rd == 0, opcode == 0b011'0011;
+  xor_hint: RType      : func7 == 0b000'0000, func3==0b100, rd == 0, opcode == 0b011'0011;
+  srl_hint: RType      : func7 == 0b000'0000, func3==0b101, rd == 0, opcode == 0b011'0011;
+  sra_hint: RType      : func7 == 0b010'0000, func3==0b101, rd == 0, opcode == 0b011'0011;
+  or_hint : RType      : func7 == 0b000'0000, func3==0b110, rd == 0, opcode == 0b011'0011;
+  and_hint: RType      : func7 == 0b000'0000, func3==0b111, rd == 0, opcode == 0b011'0011;
+  fence_hint1: Fence   : func3==0b000, rd == 0, rs1 != 0, fm == 0, pred == 0, opcode == 0b000'1111;
+  fence_hint2: Fence   : func3==0b000, rd == 0, rs1 != 0, fm == 0, succ == 0, opcode == 0b000'1111;
+  fence_hint3: Fence   : func3==0b000, rd != 0, rs1 == 0, fm == 0, pred == 0, opcode == 0b000'1111;
+  fence_hint4: Fence   : func3==0b000, rd != 0, rs1 == 0, fm == 0, succ == 0, opcode == 0b000'1111;
+  fence_hint5: Fence   : func3==0b000, rd == 0, rs1 == 0, fm == 0, pred == 0, succ != 0, opcode == 0b000'1111;
+  fence_hint6: Fence   : func3==0b000, rd == 0, rs1 == 0, fm == 0, succ == 0, opcode == 0b000'1111;
+  fence_hint7: Fence   : func3==0b000, rd != 0, rs1 == 0, fm == 0, pred != 1, succ == 0, opcode == 0b000'1111;
+};
+
+instruction group RiscVCInst16 = {RiscVCInstBase16, RiscVCHints16};
+
 // Compact instruction encodings.
-instruction group RiscVCInst16[16] : Inst16Format {
+instruction group RiscVCInstBase16[16] : Inst16Format {
   caddi4spn : CIW : func3 == 0b000, op == 0b00, imm8 != 0;
   cfld      : CL : func3 == 0b001, op == 0b00;
   clw       : CL : func3 == 0b010, op == 0b00;
@@ -229,7 +274,6 @@
   csd       : CS : func3 == 0b111, op == 0b00;
   cnop      : CI : func3 == 0b000, imm1 == 0, rs1 == 0, imm5 == 0, op == 0b01;
   caddi     : CI : func3 == 0b000, imm6 != 0, rd != 0, op == 0b01;
-  caddi_hint: CI : func3 == 0b000, imm6 == 0, rd != 0, op == 0b01;
   caddiw    : CI : func3 == 0b001, rs1 != 0, op == 0b01;
   cli       : CI : func3 == 0b010, rd != 0, op == 0b01;
   caddi16sp : CI : func3 == 0b011, rd == 2, ci_imm10 != 0, op == 0b01;
@@ -255,9 +299,18 @@
   cebreak   : CR : func4 == 0b1001, rs1 == 0, rs2 == 0, op == 0b10;
   cjalr     : CR : func4 == 0b1001, rs1 != 0, rs2 == 0, op == 0b10;
   cadd      : CR : func4 == 0b1001, rs1 != 0, rs2 != 0, op == 0b10;
-  cadd_hint : CR : func4 == 0b1001, rs1 == 0, rs2 != 0, op == 0b10;
   cfsdsp    : CSS: func3 == 0b101, op == 0b10;
   cswsp     : CSS: func3 == 0b110, op == 0b10;
   csdsp     : CSS: func3 == 0b111, op == 0b10;
   cunimp    : Inst16Format : func3 == 0b000, bits == 0b000'0000'0000, op == 0b00;
 };
+
+instruction group RiscVCHints16[16] : Inst16Format {
+  cnop_hint : CI : func3 == 0b000, imm6 != 0, rs1 == 0, op == 0b01;
+  caddi_hint: CI : func3 == 0b000, imm6 == 0, rd != 0, op == 0b01;
+  cli_hint  : CI : func3 == 0b010, rd == 0, op == 0b01;
+  clui_hint : CI : func3 == 0b011, rd == 0, imm6 != 0, op == 0b01;
+  cmv_hint  : CR : func4 == 0b1000, rs1 == 0, rs2 != 0, op == 0b10;
+  cslli_hint: CI : func3 == 0b000, imm6 != 0, rd == 0, op == 0b10;
+  cadd_hint : CR : func4 == 0b1001, rs1 == 0, rs2 != 0, rs2 != 2, rs2 != 3, rs2 != 4, rs2 != 5, op == 0b10;
+};
\ No newline at end of file
diff --git a/riscv/riscv64g.isa b/riscv/riscv64g.isa
index 9370734..64b74c8 100644
--- a/riscv/riscv64g.isa
+++ b/riscv/riscv64g.isa
@@ -40,7 +40,7 @@
 
 
 // This should be the RiscV64G set, where G stands for IMAFDZicsr_Zifencei.
-slot riscv64g : riscv64i, riscv64c, riscv64m, riscv64_amo_arithmetic, riscv64f, riscv64d, zicsr, zfencei, privileged {
+slot riscv64g : riscv64i, riscv64c, riscv64chints, riscv64m, riscv64_hints, riscv64_amo_arithmetic, riscv64f, riscv64d, zicsr, zfencei, privileged {
   default size = 4;
   default opcode =
     disasm: "Illegal instruction at %(@:08x)",
@@ -61,6 +61,10 @@
       resources: TwoOp,
       disasm: "addi", "%rd, %rs1, %I_imm12",
       semfunc: "&RV64::RiscVIAdd";
+    nop{},
+      resources: { next_pc },
+      disasm: "nop",
+      semfunc: "&RiscVINop";
     addiw{: rs1, %reloc(I_imm12) : rd},
       resources: TwoOp,
       disasm: "addiw", "%rd, %rs1, %I_imm12",
@@ -176,9 +180,6 @@
       resources: ThreeOp,
       disasm: "sra", "%rd, %rs1, %rs2",
       semfunc: "&RV64::RiscVISraw";
-    nop{},
-      disasm: "nop",
-      semfunc: "&RiscVINop";
     hint{},
       disasm: "hint",
       semfunc: "&RiscVINop";
@@ -284,6 +285,153 @@
   }
 }
 
+// This slot contains the hint instructions. These execute as nops, but can be
+// changed to provide performance hints to a simulated microarchitecture.
+slot riscv64_hints {
+  includes {
+    #include "riscv/riscv_i_instructions.h"
+  }
+  default size = 4;
+  default latency = global_latency;
+  resources TwoOp = { next_pc, rs1 : rd[..rd]};
+  resources ThreeOp = { next_pc, rs1, rs2 : rd[..rd]};
+  opcodes {
+    addi_hint1{: rs1, I_imm12 : rd},
+      resources: TwoOp,
+      disasm: "addi.hint", "%rd, %rs1, %I_imm12",
+      semfunc: "&RiscVINop";
+    addi_hint2{: rs1, I_imm12 : rd},
+      resources: TwoOp,
+      disasm: "addi.hint", "%rd, %rs1, %I_imm12",
+      semfunc: "&RiscVINop";
+    slti_hint{: rs1, I_imm12 : rd},
+      resources: TwoOp,
+      disasm: "slti.hint", "%rd, %rs1, %I_imm12",
+      semfunc: "&RiscVINop";
+    sltiu_hint{: rs1, I_imm12 : rd},
+      resources: TwoOp,
+      disasm: "sltiu.hint", "%rd, %rs1, %I_imm12",
+      semfunc: "&RiscVINop";
+    andi_hint{: rs1, I_imm12 : rd},
+      resources: TwoOp,
+      disasm: "andi.hint", "%rd, %rs1, %I_imm12",
+      semfunc: "&RiscVINop";
+    ori_hint{: rs1, I_imm12 : rd},
+      resources: TwoOp,
+      disasm: "ori.hint", "%rd, %rs1, %I_imm12",
+      semfunc: "&RiscVINop";
+    xori_hint{: rs1, I_imm12 : rd},
+      resources: TwoOp,
+      disasm: "xori.hint", "%rd, %rs1, %I_imm12",
+      semfunc: "&RiscVINop";
+    slli_semihost{: rs1, I_uimm5 : rd},
+      resources: TwoOp,
+      disasm: "slli.semihost", "%rd, %rs1, 0x%(I_uimm5:x)",
+      semfunc: "&RiscVINop";
+    slli_hint1{: rs1, I_uimm5 : rd},
+      resources: TwoOp,
+      disasm: "slli.hint", "%rd, %rs1, 0x%(I_uimm5:x)",
+      semfunc: "&RiscVINop";
+    slli_hint2{: rs1, I_uimm5 : rd},
+      resources: TwoOp,
+      disasm: "slli.hint", "%rd, %rs1, 0x%(I_uimm5:x)",
+      semfunc: "&RiscVINop";
+    srli_hint{: rs1, I_uimm5 : rd},
+      resources: TwoOp,
+      disasm: "srli.hint", "%rd  %rs1, 0x%(I_uimm5:x)",
+      semfunc: "&RiscVINop";
+    srai_semihost{: rs1, I_uimm5 : rd},
+      resources: TwoOp,
+      disasm: "srai.semihost", "%rd, %rs1, 0x%(I_uimm5:x)",
+      semfunc: "&RiscVINop";
+    srai_hint1{: rs1, I_uimm5 : rd},
+      resources: TwoOp,
+      disasm: "srai.hint", "%rd, %rs1, 0x%(I_uimm5:x)",
+      semfunc: "&RiscVINop";
+    srai_hint2{: rs1, I_uimm5 : rd},
+      resources: TwoOp,
+      disasm: "srai.hint", "%rd, %rs1, 0x%(I_uimm5:x)",
+      semfunc: "&RiscVINop";
+    lui_hint{: U_imm20 : rd},
+      resources: { next_pc : rd[0..]},
+      disasm: "lui.hint", "%rd, 0x%(U_imm20:08x)",
+      semfunc: "&RiscVINop";
+    auipc_hint{: U_imm20 : rd},
+      resources: { next_pc : rd[0..]},
+      disasm: "auipc.hint", "%rd, 0x%(U_imm20:08x)",
+      semfunc: "&RiscVINop";
+    add_hint1{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "add.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    add_hint2{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "add.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    add_hint3{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "add.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    and_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "and.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    or_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "or.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    xor_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "xor.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    sll_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "sll.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    srl_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "srl.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    sub_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "sub.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    sra_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "sra.hint", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    slt_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "slt", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    sltu_hint{: rs1, rs2 : rd},
+      resources: ThreeOp,
+      disasm: "sltu", "%rd, %rs1, %rs2",
+      semfunc: "&RiscVINop";
+    fence_hint1{: pred, succ :},
+      disasm: "fence.hint",
+      semfunc: "&RiscVINop";
+    fence_hint2{: pred, succ :},
+      disasm: "fence.hint",
+      semfunc: "&RiscVINop";
+    fence_hint3{: pred, succ :},
+      disasm: "fence.hint",
+      semfunc: "&RiscVINop";
+    fence_hint4{: pred, succ :},
+      disasm: "fence.hint",
+      semfunc: "&RiscVINop";
+    fence_hint5{: pred, succ :},
+      disasm: "fence.hint",
+      semfunc: "&RiscVINop";
+    fence_hint6{:pred, succ :},
+      disasm: "fence.hint",
+      semfunc: "&RiscVINop";
+    fence_hint7{: pred, succ :},
+      disasm: "fence.hint",
+      semfunc: "&RiscVINop";
+  }
+}
+
 // Privileged instructions.
 slot privileged {
   includes {
@@ -971,10 +1119,6 @@
       resources: {next_pc, rd : rd[0..]},
       disasm: "c.addi", "%rd, %rd, %I_ci_imm6",
       semfunc: "&RV64::RiscVIAdd";
-    caddi_hint{: rd, I_ci_imm6 : rd},
-      resources: {next_pc, rd : rd[0..]},
-      disasm: "caddi_hint",
-      semfunc: "&RiscVINop";
     caddiw{: rd, I_ci_imm6 : rd},
       resources: {next_pc, rd : rd[0..]},
       disasm: "c.addiw", "%rd, %rd, %I_ci_imm6",
@@ -1011,9 +1155,6 @@
       resources: {next_pc, crs2, rd : rd[0..]},
       disasm: "c.add", "%rd, %rd, %crs2",
       semfunc: "&RV64::RiscVIAdd";
-    cadd_hint{},
-      disasm: "cadd_hint",
-      semfunc: "&RiscVINop";
     cand{: c3rs1, c3rs2 : c3rs1},
       resources: {next_pc, c3rs1, c3rs2 : c3rs1[0..]},
       disasm: "c.and", "%c3rs1, %c3rs1, %c3rs2",
@@ -1052,3 +1193,33 @@
       semfunc: "&RiscVIUnimplemented";
   }
 }
+
+
+
+slot riscv64chints {
+  default size = 2;
+  default latency = global_latency;
+  opcodes {
+    cnop_hint{},
+      disasm: "cnop.hint",
+      semfunc: "&RiscVINop";
+    cli_hint{},
+      disasm: "cli.hint",
+      semfunc: "&RiscVINop";
+    clui_hint{},
+      disasm: "clui.hint",
+      semfunc: "&RiscVINop";
+    cmv_hint{},
+      disasm: "cmv.hint",
+      semfunc: "&RiscVINop";
+    caddi_hint{},
+      disasm: "caddi.hint",
+      semfunc: "&RiscVINop";
+    cslli_hint{},
+      disasm: "cslli.hint",
+      semfunc: "&RiscVINop";
+    cadd_hint{},
+      disasm: "cadd.hint",
+      semfunc: "&RiscVINop";
+  }
+}
diff --git a/riscv/rvm23.isa b/riscv/rvm23.isa
index b988fad..3ef7b24 100644
--- a/riscv/rvm23.isa
+++ b/riscv/rvm23.isa
@@ -35,6 +35,7 @@
   riscv32_amo_arithmetic,
   riscv32f,
   riscv32d,
+  riscv32_hints,
   zicsr,
   zfencei,
   privileged,