(no commit message)
authorlkcl <lkcl@web>
Thu, 7 Jan 2021 20:44:51 +0000 (20:44 +0000)
committerIkiWiki <ikiwiki.info>
Thu, 7 Jan 2021 20:44:51 +0000 (20:44 +0000)
openpower/sv/ldst.mdwn

index e39a852311c523f9401543886947723e71a6dff0..6aaf350c5bdcb370295b949fc921574ca9a12e92 100644 (file)
@@ -81,3 +81,64 @@ Indexed LD is:
         if (RB.isvec) i++;
         if (RT.isvec) j++;
 
+# LOAD/STORE Elwidths <a name="ldst"></a>
+
+Loads and Stores are almost unique in that the OpenPOWER Scalar ISA provides a width for the operation (lb, lh, lw, ld).  Only `extsb` and others like it provide an explicit operation width.  In order to fit the different types of LD/ST Modes into SV the src elwidth field is used to select that Mode, and the actual src elwidth is implicitly the same as the operation width.  We then still apply Twin Predication but using:
+
+* operation width (lb=8, lh=16, lw=32, ld=64) as src elwidth
+* destination element width override
+
+Saturation (and other transformations) occur on the value loaded from memory as if it was an "infinite bitwidth", sign-extended (if Saturation requests signed) from the source width (lb, lh, lw, ld) followed then by the actual Saturation to the destination width.
+
+In order to respect OpenPOWER v3.0B Scalar behaviour the memory side is treated effectively as completely separate and distinct from SV augmentation.  This is primarily down to quirks surrounding LE/BE and byte-reversal in OpenPOWER.
+
+Note the following regarding the pseudocode to follow:
+
+* `scalar identity behaviour` SV Context parameter conditions turn this
+  into a straight absolute fully-compliant Scalar v3.0B LD operation
+* `brev` selects whether the operation is the byte-reversed variant (`ldbrx`
+  rather than `ld`)
+* `op_width` specifies the operation width (`lb`, `lh`, `lw`, `ld`) as
+  a "normal" part of Scalar v3.0B LD
+* `imm_offs` specifies the immediate offset `ld r3, imm_offs(r5)`, again
+  as a "normal" part of Scalar v3.0B LD
+* `svctx` specifies the SV Context and includes VL as well as
+  destination elwidth overrides.
+
+Below is the pseudocode for Unit-Strided LD (which includes Vector capability).  Note that twin predication, predication-zeroing, saturation
+and other modes have all been removed, for clarity and simplicity:
+
+    # LD not VLD! (ldbrx if brev=True)
+    # this covers unit stride mode
+    function op_ld(RT, RA, brev, op_width, imm_offs, svctx)
+      for (int i = 0, int j = 0; i < svctx.VL && j < svctx.VL;):
+
+        # unit stride mode, compute the address
+        srcbase = ireg[RA] + i * op_width;
+
+        # takes care of (merges) processor LE/BE and ld/ldbrx
+        bytereverse = brev XNOR MSR.LE
+
+        # read the underlying memory
+        memread <= mem[srcbase + imm_offs];
+
+        # optionally performs 8-byte swap (because src_elwidth=64)
+        if (bytereverse):
+            memread = byteswap(memread, op_width)
+
+        # now truncate/extend to over-ridden width.
+        if not svpctx.saturation_mode:
+            memread = adjust_wid(memread, op_width, svctx.dest_elwidth)
+        else:
+            ... saturation adjustment...
+
+        # takes care of inserting memory-read (now correctly byteswapped)
+        # into regfile underlying LE-defined order, into the right place
+        # within the NEON-like register, respecting destination element
+        # bitwidth, and the element index (j)
+        set_polymorphed_reg(RT, svctx.dest_bitwidth, j, memread)
+
+        # increments both src and dest element indices (no predication here)
+        i++;
+        j++;
+