# LD immediate els (element-stride) locations, depending on mode
ELS_NORMAL = 4
ELS_FFIRST_PRED = 3
- ELS_SAT = 4
- LDI_POST = 2 # LD-Immediate Post/FF Mode
- LDI_PI = 3 # LD-Immediate Post-Increment
+ LDI_PI = 2 # LD-Immediate Post-Increment
LDI_FF = 4 # LD-Immediate Fault-First
- # LDST Indexed
- LDIDX_ELS = 0 # Indexed element-strided
+ # LDST element-strided
+ LDST_ELS = 0 # Indexed element-strided
# LDST VLI for ffirst is in bit 0
LDST_VLI = 0
# BO bits
class LDSTImmSimpleRM(ElsBaseRM, ZZBaseRM, LDSTImmBaseRM):
"""ld/st immediate: simple mode"""
+ pi: BaseRM.mode[2] # Post-Increment Mode
+ lf: BaseRM.mode[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
zz: BaseRM.mode[3]
- els: BaseRM.mode[4]
+ els: BaseRM.mode[0]
dz: BaseRM.mode[3]
sz: BaseRM.mode[3]
-
-class LDSTImmPostRM(LDSTImmBaseRM):
- """ld/st immediate: postinc mode (and load-fault)"""
- pi: BaseRM.mode[3] # Post-Increment Mode
- lf: BaseRM.mode[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
-
def specifiers(self, record):
if self.pi:
yield "pi"
if self.lf:
yield "lf"
+ yield from super().specifiers(record=record)
+
class LDSTFFRc1RM(FFRc1BaseRM, VLiBaseRM, LDSTImmBaseRM):
"""ld/st immediate&indexed: Rc=1: ffirst CR sel"""
yield from super().specifiers(record=record, mode="ff")
-class LDSTFFRc0RM(FFRc0BaseRM, VLiBaseRM, ElsBaseRM, LDSTImmBaseRM):
+class LDSTFFRc0RM(FFRc0BaseRM, VLiBaseRM, LDSTImmBaseRM):
"""ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
VLi: BaseRM.mode[0]
inv: BaseRM.mode[2]
- els: BaseRM.mode[3]
RC1: BaseRM.mode[4]
def specifiers(self, record):
yield from super().specifiers(record=record, mode="ff")
-class LDSTImmSatRM(ElsBaseRM, SatBaseRM, ZZBaseRM, LDSTImmBaseRM):
- """ld/st immediate: sat mode: N=0/1 u/s"""
- N: BaseRM.mode[2]
- zz: BaseRM.mode[3]
- els: BaseRM.mode[4]
- dz: BaseRM.mode[3]
- sz: BaseRM.mode[3]
-
-
class LDSTImmRM(LDSTImmBaseRM):
simple: LDSTImmSimpleRM
- post: LDSTImmPostRM
ffrc1: LDSTFFRc1RM
ffrc0: LDSTFFRc0RM
- sat: LDSTImmSatRM
class LDSTIdxBaseRM(PredicateWidthBaseRM):
yield from super().specifiers(record=record)
-class LDSTIdxSatRM(SatBaseRM, ZZCombinedBaseRM, LDSTIdxBaseRM):
- """ld/st index: sat mode: N=0/1 u/s"""
- N: BaseRM.mode[2]
- dz: BaseRM.mode[3]
- sz: BaseRM.mode[4]
-
-
class LDSTIdxRM(LDSTIdxBaseRM):
simple: LDSTIdxSimpleRM
- sat: LDSTIdxSatRM
ffrc1: LDSTFFRc1RM
ffrc0: LDSTFFRc0RM
def assemble(self, insn):
selector = insn.select(record=self.record)
- selector.mode[0] = 0b0
selector.mode[1] = 0b0
selector.mode[2] = 0b1
selector.pi = 0b1
def assemble(self, insn):
selector = insn.select(record=self.record)
- selector.mode[2] = 1
+ selector.mode[1] = 0
selector.lf = 0b1
# ironically/coincidentally this table is identical to NORMAL
# mode except reserved in place of mr
table = (
- (0b000000, 0b111000, "simple"), # simple (no Rc involved)
- (0b001000, 0b111000, "post"), # post (no Rc involved)
+ (0b000000, 0b010000, "simple"), # simple (no Rc involved)
(0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
(0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
- (0b100000, 0b110000, "sat"), # saturation (no Rc)
)
search = ((int(self.insn.prefix.rm.ldst_imm.mode) << 1) |
self.record.Rc)
#####################
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)
######################