# Funded by NLnet http://nlnet.nl
# sigh this entire module is a laborious mess. it really should be
-# auto-generated from the power_insn.py database but a technique
+# auto-generated from the insndb/types.py database but a technique
# for doing so (similar to python HTML/XML-node-walking) is needed
"""SVP64 RM (Remap) Record.
]
"""RM Mode
-there are four Mode variants, two for LD/ST, one for Branch-Conditional,
+there are five Mode variants, two for LD/ST, one for Branch-Conditional,
and one for everything else
https://libre-soc.org/openpower/sv/svp64/
https://libre-soc.org/openpower/sv/ldst/
https://libre-soc.org/openpower/sv/branches/
+https://libre-soc.org/openpower/sv/crops/
LD/ST immed:
+
| 0 | 1 | 2 | 3 4 | description |
|---|---| --- |---------|--------------------------- |
-| 0 | 0 | 0 | zz els | simple mode |
-| 0 | 0 | 1 | PI LF | post-increment and Fault-First |
-| 1 | 0 | N | zz els | sat mode: N=0/1 u/s |
-|VLi| 1 | inv | CR-bit | Rc=1: ffirst CR sel |
-|VLi| 1 | inv | els RC1 | Rc=0: ffirst z/nonz |
-
-00 0 zz els normal mode (with element-stride option)
-01 inv CR-bit Rc=1: ffirst CR sel
-01 inv els RC1 Rc=0: ffirst z/nonz
-10 N zz els sat mode: N=0/1 u/s
-11 inv CR-bit Rc=1: pred-result CR sel
-11 inv els RC1 Rc=0: pred-result z/nonz
+|els| 0 | PI | zz LF | simple mode |
+|VLi| 1 | inv | CR-bit | ffirst CR sel |
LD/ST indexed:
| 0 | 1 | 2 | 3 4 | description |
|---|---| --- |---------|--------------------------- |
-|els| 0 | SEA | dz sz | simple mode |
-|VLi| 1 | inv | CR-bit | Rc=1: ffirst CR sel |
-|VLi| 1 | inv | els RC1 | Rc=0: ffirst z/nonz |
-
-00 0 sz dz normal mode
-00 1 rsvd reserved
-01 inv CR-bit Rc=1: ffirst CR sel
-01 inv dz RC1 Rc=0: ffirst z/nonz
-10 N sz dz sat mode: N=0/1 u/s
-11 inv CR-bit Rc=1: pred-result CR sel
-11 inv zz RC1 Rc=0: pred-result z/nonz
+|els| 0 | PI | zz SEA | simple mode |
+|VLi| 1 | inv | CR-bit | ffirst CR sel |
Arithmetic:
-| 0-1 | 2 | 3 4 | description |
-| --- | --- |---------|-------------------------- |
-| 00 | 0 | dz sz | simple mode |
-| 00 | 1 | 0 RG | scalar reduce mode (mapreduce), SUBVL=1 |
-| 00 | 1 | SVM 0 | subvector reduce mode, SUBVL>1 |
-| 00 | 1 | / 1 | reserved |
-| 01 | inv | CR-bit | Rc=1: ffirst CR sel |
-| 01 | inv | VLi RC1 | Rc=0: ffirst z/nonz |
-| 10 | N | dz sz | sat mode: N=0/1 u/s, SUBVL=1 |
-| 10 | N | zz 0 | sat mode: N=0/1 u/s, SUBVL>1 |
-| 10 | N | / 1 | reserved |
-| 11 | inv | CR-bit | Rc=1: pred-result CR sel |
-| 11 | inv | zz RC1 | Rc=0: pred-result z/nonz |
+
+| 0-1 | 2 | 3 4 | description |
+| ------ | --- |---------|----------------------------------|
+| 0 0 | 0 | dz sz | simple mode |
+| 0 0 | 1 | RG 0 | scalar reduce mode (mapreduce) |
+| 0 0 | 1 | / 1 | reserved |
+| 1 0 | N | dz sz | sat mode: N=0/1 u/s |
+| VLi 1 | inv | CR-bit | Rc=1: ffirst CR sel |
+| VLi 1 | inv | zz RC1 | Rc=0: ffirst z/nonz |
+
+CROps:
+
+|6 | 7 |19:20|21 | 22:23 | description |
+|--|---|-----|---|---------|------------------|
+|/ | / |0 0 |RG | dz sz | simple mode |
+|/ | / |1 0 |RG | dz sz | scalar reduce mode (mapreduce) |
+|zz|SNZ|VLI 1|inv| CR-bit | Ffirst 3-bit mode |
+|/ |SNZ|VLI 1|inv| dz sz | Ffirst 5-bit mode (implies CR-bit from result) |
Branch Conditional:
+
note that additional BC modes are in *other bits*, specifically
the element-width fields: SVP64Rec.ewsrc and SVP64Rec.elwidth
#####################
with m.Elif(is_ldst):
with m.Switch(mode2):
- with m.Case(0): # needs further decoding (LDST no mapreduce)
- with m.If(is_ldstimm & mode[SVP64MODE.LDI_POST]):
- comb += self.mode.eq(SVP64RMMode.NORMAL)
- comb += self.ldst_postinc.eq(mode[SVP64MODE.LDI_PI])
- comb += self.ldst_ffirst.eq(mode[SVP64MODE.LDI_FF])
- with m.Elif(is_ldst):
- comb += self.mode.eq(SVP64RMMode.NORMAL)
+ with m.Case(0, 2): # needs further decoding (LDST no mapreduce)
+ comb += self.mode.eq(SVP64RMMode.NORMAL)
+ comb += self.ldst_postinc.eq(mode[SVP64MODE.LDI_PI])
+ comb += self.ldst_ffirst.eq(mode[SVP64MODE.LDI_FF])
with m.Case(1, 3):
comb += self.mode.eq(SVP64RMMode.FFIRST) # ffirst
- with m.Case(2):
- with m.If(is_ldstimm):
- comb += self.mode.eq(SVP64RMMode.SATURATE) # saturate
- with m.Else():
- comb += self.mode.eq(SVP64RMMode.NORMAL) # els-bit
# extract zeroing
with m.If(is_ldst & ~is_ldstimm): # LDST-Indexed
with m.Elif(is_ldstimm): # LDST-Immediate
with m.Switch(mode2):
- with m.Case(0): # simple mode
- with m.If(~mode[2]): # (but not PI/LF)
- # [MSB0-numbered] bits 0,1,2 of mode zero, use zz
- comb += self.pred_sz.eq(mode[SVP64MODE.ZZ])
- comb += self.pred_dz.eq(mode[SVP64MODE.ZZ])
- with m.Case(2): # saturated mode
- # saturated-mode also uses zz
- comb += self.pred_sz.eq(mode[SVP64MODE.ZZ])
- comb += self.pred_dz.eq(mode[SVP64MODE.ZZ])
+ with m.Case(0,2): # simple mode
+ # use zz
+ comb += self.pred_sz.eq(mode[SVP64MODE.ZZ])
+ comb += self.pred_dz.eq(mode[SVP64MODE.ZZ])
# extract failfirst
with m.If(self.mode == SVP64RMMode.FFIRST): # fail-first
# extract els (element strided mode bit)
# see https://libre-soc.org/openpower/sv/ldst/
els = Signal()
- with m.If(is_ldstimm): # LD/ST-immediate
- with m.Switch(mode2):
- with m.Case(0):
- with m.If(~mode[2]): # (but not PI/LF)
- comb += els.eq(mode[SVP64MODE.ELS_NORMAL])
- with m.Case(2):
- comb += els.eq(mode[SVP64MODE.ELS_SAT])
- with m.Case(1, 3):
- with m.If(self.rc_in):
- comb += els.eq(mode[SVP64MODE.ELS_FFIRST_PRED])
- with m.Else(): # LD/ST-Indexed
- with m.Switch(mode2):
- with m.Case(0, 2):
- comb += els.eq(mode[SVP64MODE.LDIDX_ELS])
- with m.Case(1, 3):
- with m.If(self.rc_in):
- comb += els.eq(mode[SVP64MODE.ELS_FFIRST_PRED])
+ with m.Switch(mode2):
+ with m.Case(0, 2):
+ comb += els.eq(mode[SVP64MODE.LDST_ELS])
+ with m.Case(1, 3):
+ with m.If(self.rc_in):
+ comb += els.eq(mode[SVP64MODE.ELS_FFIRST_PRED])
# RA is vectorised
with m.If(self.ldst_ra_vec):
comb += self.ew_dst.eq(self.rm_in.elwidth)
comb += self.subvl.eq(self.rm_in.subvl)
- # extract els (element strided mode bit)
- # see https://libre-soc.org/openpower/sv/ldst/
- els = Signal()
- with m.If(is_ldst):
- with m.If(is_ldstimm):
- with m.Switch(mode2):
- with m.Case(0):
- comb += els.eq(mode[SVP64MODE.ELS_NORMAL])
- with m.Case(2):
- comb += els.eq(mode[SVP64MODE.ELS_SAT])
- with m.Case(1, 3):
- with m.If(self.rc_in):
- comb += els.eq(mode[SVP64MODE.ELS_FFIRST_PRED])
- with m.Else():
- with m.Switch(mode2):
- with m.Case(0, 2):
- comb += els.eq(mode[SVP64MODE.LDIDX_ELS])
- with m.Case(1, 3):
- with m.If(self.rc_in):
- comb += els.eq(mode[SVP64MODE.ELS_FFIRST_PRED])
-
- # RA is vectorised
- with m.If(self.ldst_ra_vec):
- comb += self.ldstmode.eq(SVP64LDSTmode.INDEXED)
- # not element-strided, therefore unit...
- with m.Elif(~els):
- comb += self.ldstmode.eq(SVP64LDSTmode.UNITSTRIDE)
- # but if the LD/ST immediate is zero, allow cache-inhibited
- # loads from same location, therefore don't do element-striding
- with m.Elif(~self.ldst_imz_in):
- comb += self.ldstmode.eq(SVP64LDSTmode.ELSTRIDE)
-
######################
# Common fields (not many, sigh)
######################