add ld/st-immediate "post-inc" mode support. unit test for LD
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 11 Oct 2022 13:11:04 +0000 (14:11 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 11 Oct 2022 13:11:04 +0000 (14:11 +0100)
src/openpower/decoder/isa/caller.py
src/openpower/decoder/isa/test_caller_svp64_ldst.py
src/openpower/sv/trans/test_pysvp64dis.py

index 81da65aed0cb6a77931f56f37508fb232061355b..c260cb01af19bacd81a3a501af8db7a233928344 100644 (file)
@@ -1733,6 +1733,15 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
         if asmop.startswith('bc') and self.is_svp64_mode:
             ins_name = 'sv.%s' % ins_name
 
+        # ld-immediate-with-pi mode redirects to ld-with-postinc
+        sv_mode = yield self.dec2.rm_dec.sv_mode
+        is_ldst_imm = sv_mode == SVMode.LDST_IMM.value
+        ldst_imm_postinc = False
+        if is_ldst_imm and 'u' in ins_name and self.is_svp64_mode:
+            ins_name = ins_name.replace("u", "up")
+            ldst_imm_postinc = True
+            log("   enable ld/st postinc", ins_name)
+
         log("   post-processed name", dotstrp, ins_name, asmop)
 
         # illegal instructions call TRAP at 0x700
@@ -1859,7 +1868,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
         # in SVP64 mode for LD/ST work out immediate
         # XXX TODO: replace_ds for DS-Form rather than D-Form.
         # use info.form to detect
-        if self.is_svp64_mode:
+        if self.is_svp64_mode and not ldst_imm_postinc:
             yield from self.check_replace_d(info, remap_active)
 
         # "special" registers
index 4e1901df2170acb897e36b40d6e640e8837f9bf3..bed62b8ce9c4a2d2541ad730c3d2c0834d7e73f7 100644 (file)
@@ -29,6 +29,66 @@ class DecoderTestCase(FHDLTestCase):
         for i in range(32):
             self.assertEqual(sim.fpr(i), SelectableInt(expected[i], 64))
 
+    def test_sv_load_store_postinc(self):
+        """>>> lst = ["addi 2, 0, 0x0010",
+                        "addi 3, 0, 0x0008",
+                        "addi 4, 0, 0x1234",
+                        "addi 5, 0, 0x1235",
+                        "sv.stw/els *4, 24(2)",
+                        "addi 2, 2, 24",   # add on the 24
+                        "sv.lwu/pi *8, 8(2)"]
+
+        element stride is computed as:
+        for i in range(VL):
+            EA = (RA|0) + EXTS(D) * i
+
+        load-update with post-increment will do this however:
+        for i in range(VL):
+            *vector = MEM(RA)
+            EA = (RA|0) + EXTS(D)
+            RA = EA # update RA *after*
+
+        whereas without post-increment it would be:
+        for i in range(VL):
+            EA = (RA|0) + EXTS(D) # EA calculated (and used) *BEFORE* load
+            *vector = MEM(EA)
+            RA = EA # still updated after but it's used before
+        """
+        lst = SVP64Asm(["addi 2, 0, 0x0010",
+                        "addi 3, 0, 0x0008",
+                        "addi 4, 0, 0x1234",
+                        "addi 5, 0, 0x1235",
+                        "sv.stw/els *4, 24(2)",  # scalar r1 + 16 + 24*offs
+                        "addi 20, 2, 0",   # copy 2 to 20
+                        "sv.lwzu/pi *8, 24(20)"
+                        ]) # scalar r1 + 24*offs
+        lst = list(lst)
+
+        # SVSTATE (in this case, VL=2)
+        svstate = SVP64State()
+        svstate.vl = 2 # VL
+        svstate.maxvl = 2 # MAXVL
+        print ("SVSTATE", bin(svstate.asint()))
+
+        with Program(lst, bigendian=False) as program:
+            sim = self.run_tst_program(program, svstate=svstate)
+            mem = sim.mem.dump(printout=False)
+            print (mem)
+            # contents of memory expected at:
+            #    element 0:   r1=0x10, D=24, => EA = 0x10+24*0 = 16 (0x10)
+            #    element 1:   r1=0x10, D=24, => EA = 0x10+24*1 = 40 (0x28)
+            # therefore, at address 0x10 ==> 0x1234
+            # therefore, at address 0x28 ==> 0x1235
+            expected_mem = [(16, 0x1234),
+                            (40, 0x1235)]
+            self.assertEqual(mem, expected_mem)
+            print(sim.gpr(1))
+            self.assertEqual(sim.gpr(8), SelectableInt(0x1234, 64))
+            self.assertEqual(sim.gpr(9), SelectableInt(0x1235, 64))
+            # reg 20 (the EA) is expected to be the initial 16,
+            # plus 2x24 (2 lots of immediates).  16+2*24=64
+            self.assertEqual(sim.gpr(20), SelectableInt(64, 64))
+
     def test_sv_load_store_elementstride(self):
         """>>> lst = ["addi 2, 0, 0x0010",
                         "addi 3, 0, 0x0008",
index 54cbf6386ef14a2d1402c4ba2ff760c881302cb2..9621a447fe6d50410de73fa08e064c8a2eee5706 100644 (file)
@@ -387,6 +387,8 @@ class SVSTATETestCase(unittest.TestCase):
     def test_29_postinc(self):
         expected = [
                     "sv.ldu/pi 5,8(2)",
+                    "sv.lwzu/pi *6,8(2)",
+                    "sv.lwzu/pi *6,24(2)",
                         ]
         self._do_tst(expected)