arch-riscv: Make use of ImmOp's polymorphism

This patch makes use of ImmOp's polymorphism to remove unnecessary
casting from the implementations of arithmetic instructions with
immediate operands and to remove the CUIOp format by combining it with
the CIOp format (compressed arithmetic instructions with immediate
operands). Interestingly, RISC-V specifies that instructions with
unsigned immediate operands still need to sign-extend the immediates
from 12 (or 20) bits to 64 bits, so that is left alone.

Change-Id: If20d70c1e90f379b9ed8a4155b2b9222b6defe16
Reviewed-on: https://gem5-review.googlesource.com/6401
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Tuan Ta <qtt2@cornell.edu>
Maintainer: Alec Roelke <ar4jc@virginia.edu>
diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa
index 2761fac..435266c 100644
--- a/src/arch/riscv/isa/decoder.isa
+++ b/src/arch/riscv/isa/decoder.isa
@@ -36,7 +36,7 @@
 
 decode QUADRANT default Unknown::unknown() {
     0x0: decode COPCODE {
-        0x0: CUIOp::c_addi4spn({{
+        0x0: CIOp::c_addi4spn({{
             imm = CIMM8<1:1> << 2 |
                   CIMM8<0:0> << 3 |
                   CIMM8<7:6> << 4 |
@@ -45,7 +45,7 @@
             if (machInst == 0)
                 fault = make_shared<IllegalInstFault>("zero instruction");
             Rp2 = sp + imm;
-        }});
+        }}, uint64_t);
         format CompressedLoad {
             0x1: c_fld({{
                 offset = CIMM3 << 3 | CIMM2 << 6;
@@ -152,26 +152,26 @@
             }
         }
         0x4: decode CFUNCT2HIGH {
-            format CUIOp {
+            format CIOp {
                 0x0: c_srli({{
                     imm = CIMM5 | (CIMM1 << 5);
                     assert(imm != 0);
                 }}, {{
                     Rp1 = Rp1 >> imm;
-                }});
+                }}, uint64_t);
                 0x1: c_srai({{
                     imm = CIMM5 | (CIMM1 << 5);
                     assert(imm != 0);
                 }}, {{
                     Rp1_sd = Rp1_sd >> imm;
-                }});
+                }}, uint64_t);
                 0x2: c_andi({{
                     imm = CIMM5;
                     if (CIMM1 > 0)
                         imm |= ~((uint64_t)0x1F);
                 }}, {{
                     Rp1 = Rp1 & imm;
-                }});
+                }}, uint64_t);
             }
             format ROp {
                 0x3: decode CFUNCT1 {
@@ -242,13 +242,13 @@
         }
     }
     0x2: decode COPCODE {
-        0x0: CUIOp::c_slli({{
+        0x0: CIOp::c_slli({{
             imm = CIMM5 | (CIMM1 << 5);
             assert(imm != 0);
         }}, {{
             assert(RC1 != 0);
             Rc1 = Rc1 << imm;
-        }});
+        }}, uint64_t);
         format CompressedLoad {
             0x1: c_fldsp({{
                 offset = CIMM5<4:3> << 3 |
@@ -376,9 +376,9 @@
         0x03: decode FUNCT3 {
             format IOp {
                 0x0: fence({{
-                }}, IsNonSpeculative, IsMemBarrier, No_OpClass);
+                }}, uint64_t, IsNonSpeculative, IsMemBarrier, No_OpClass);
                 0x1: fence_i({{
-                }}, IsNonSpeculative, IsSerializeAfter, No_OpClass);
+                }}, uint64_t, IsNonSpeculative, IsSerializeAfter, No_OpClass);
             }
         }
 
@@ -394,11 +394,11 @@
                     Rd = (Rs1_sd < imm) ? 1 : 0;
                 }});
                 0x3: sltiu({{
-                    Rd = (Rs1 < (uint64_t)imm) ? 1 : 0;
-                }});
+                    Rd = (Rs1 < imm) ? 1 : 0;
+                }}, uint64_t);
                 0x4: xori({{
-                    Rd = Rs1 ^ (uint64_t)imm;
-                }});
+                    Rd = Rs1 ^ imm;
+                }}, uint64_t);
                 0x5: decode SRTYPE {
                     0x0: srli({{
                         Rd = Rs1 >> SHAMT6;
@@ -408,11 +408,11 @@
                     }});
                 }
                 0x6: ori({{
-                    Rd = Rs1 | (uint64_t)imm;
-                }});
+                    Rd = Rs1 | imm;
+                }}, uint64_t);
                 0x7: andi({{
-                    Rd = Rs1 & (uint64_t)imm;
-                }});
+                    Rd = Rs1 & imm;
+                }}, uint64_t);
             }
         }
 
@@ -423,8 +423,8 @@
         0x06: decode FUNCT3 {
             format IOp {
                 0x0: addiw({{
-                    Rd_sd = (int32_t)Rs1 + (int32_t)imm;
-                }});
+                    Rd_sd = Rs1_sw + imm;
+                }}, int32_t);
                 0x1: slliw({{
                     Rd_sd = Rs1_sw << SHAMT5;
                 }});
diff --git a/src/arch/riscv/isa/formats/compressed.isa b/src/arch/riscv/isa/formats/compressed.isa
index 3c47a90..03b7fb1 100644
--- a/src/arch/riscv/isa/formats/compressed.isa
+++ b/src/arch/riscv/isa/formats/compressed.isa
@@ -36,20 +36,9 @@
     exec_output = BasicExecute.subst(iop)
 }};
 
-def format CIOp(imm_code, code, *opt_flags) {{
+def format CIOp(imm_code, code, imm_type='int64_t', *opt_flags) {{
     regs = ['_destRegIdx[0]','_srcRegIdx[0]']
-    iop = InstObjParams(name, Name, 'ImmOp<int64_t>',
-        {'code': code, 'imm_code': imm_code,
-         'regs': ','.join(regs)}, opt_flags)
-    header_output = ImmDeclare.subst(iop)
-    decoder_output = ImmConstructor.subst(iop)
-    decode_block = BasicDecode.subst(iop)
-    exec_output = ImmExecute.subst(iop)
-}};
-
-def format CUIOp(imm_code, code, *opt_flags) {{
-    regs = ['_destRegIdx[0]','_srcRegIdx[0]']
-    iop = InstObjParams(name, Name, 'ImmOp<uint64_t>',
+    iop = InstObjParams(name, Name, 'ImmOp<%s>' % imm_type,
         {'code': code, 'imm_code': imm_code,
          'regs': ','.join(regs)}, opt_flags)
     header_output = ImmDeclare.subst(iop)
diff --git a/src/arch/riscv/isa/formats/standard.isa b/src/arch/riscv/isa/formats/standard.isa
index 517313d..ebe1571 100644
--- a/src/arch/riscv/isa/formats/standard.isa
+++ b/src/arch/riscv/isa/formats/standard.isa
@@ -218,9 +218,9 @@
     exec_output = BasicExecute.subst(iop)
 }};
 
-def format IOp(code, *opt_flags) {{
+def format IOp(code, imm_type='int64_t', *opt_flags) {{
     regs = ['_destRegIdx[0]','_srcRegIdx[0]']
-    iop = InstObjParams(name, Name, 'ImmOp<int64_t>',
+    iop = InstObjParams(name, Name, 'ImmOp<%s>' % imm_type,
         {'code': code, 'imm_code': 'imm = sext<12>(IMM12);',
          'regs': ','.join(regs)}, opt_flags)
     header_output = ImmDeclare.subst(iop)
diff --git a/tests/test-progs/insttest/bin/riscv/linux-rv64i/insttest b/tests/test-progs/insttest/bin/riscv/linux-rv64i/insttest
index a6e5d02..c5a2173 100755
--- a/tests/test-progs/insttest/bin/riscv/linux-rv64i/insttest
+++ b/tests/test-progs/insttest/bin/riscv/linux-rv64i/insttest
Binary files differ
diff --git a/tests/test-progs/insttest/src/riscv/rv64i.cpp b/tests/test-progs/insttest/src/riscv/rv64i.cpp
index 95e8ee0..cfe5e29 100644
--- a/tests/test-progs/insttest/src/riscv/rv64i.cpp
+++ b/tests/test-progs/insttest/src/riscv/rv64i.cpp
@@ -137,6 +137,7 @@
     // SLTIU
     expect<bool>(false, []{return I::sltiu(-1, 0);}, "sltiu, false");
     expect<bool>(true, []{return I::sltiu(0, -1);}, "sltiu, true");
+    expect<bool>(true, []{return I::sltiu(0xFFFF, -1);}, "sltiu, sext");
 
     // XORI
     expect<uint64_t>(0xFF, []{return I::xori(0xAA, 0x55);}, "xori (1)");