From bca969dcae7a24f5ffee3548b25891c0186f7afe Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Wed, 17 Jan 2024 14:56:16 +0000 Subject: [PATCH] bug 1034: add crternlogi. involved adding a new CR field BFA_BFB_BF sigh --- openpower/isa/bitmanip.mdwn | 24 +++++++++ openpower/isatables/fields.text | 8 ++- openpower/isatables/minor_5.csv | 1 + src/openpower/decoder/isa/caller.py | 4 +- src/openpower/decoder/power_decoder2.py | 9 +++- src/openpower/decoder/power_enums.py | 5 ++ src/openpower/decoder/power_svp64.py | 7 ++- src/openpower/insndb/core.py | 14 ++++++ src/openpower/test/bitmanip/bitmanip_cases.py | 50 ++++++++++++++++++- 9 files changed, 115 insertions(+), 7 deletions(-) diff --git a/openpower/isa/bitmanip.mdwn b/openpower/isa/bitmanip.mdwn index 1f8081d7..88fa79ea 100644 --- a/openpower/isa/bitmanip.mdwn +++ b/openpower/isa/bitmanip.mdwn @@ -40,6 +40,30 @@ Special Registers Altered: CR0 (if Rc=1) +# Condition Register Ternary Bitwise Logic Immediate + +CRB-Form + +* crternlogi BF,BFA,BFB,TLI,msk + +Pseudo-code: + + bf <- CR[4*BF+32:4*BF+35] + bfa <- CR[4*BFA+32:4*BFA+35] + bfb <- CR[4*BFB+32:4*BFB+35] + + result <- [0] * 4 + do i = 0 to 3 + idx <- bf[i] || bfa[i] || bfb[i] + result[i] <- TLI[7-idx] + do i = 0 to 3 + if msk[i] = 1 then + CR[4*BF+32+i] <- result[i] + +Special Registers Altered: + + CR field BF + # Add With Shift By Immediate Z23-Form diff --git a/openpower/isatables/fields.text b/openpower/isatables/fields.text index 1edbb6a5..5554ed5e 100644 --- a/openpower/isatables/fields.text +++ b/openpower/isatables/fields.text @@ -402,7 +402,7 @@ BF (6:8) Field used to specify one of the CR fields or one of the FPSCR fields to be used as a target. - Formats: D, X, XL, XX2, XX3, Z22 + Formats: D, X, XL, XX2, XX3, Z22, CRB BFA (22:24) Field used to specify one of the CR fields to be used as a source. @@ -414,7 +414,11 @@ BFA (11:13) Field used to specify one of the CR fields or one of the FPSCR fields to be used as a source. - Formats: X, XL + Formats: X, XL, CRB + BFB (16:18) + Field used to specify one of the CR fields + to be used as a source. + Formats: CRB BH (19:20) Field used to specify a hint in the Branch Condi- tional to Link Register and Branch Conditional to diff --git a/openpower/isatables/minor_5.csv b/openpower/isatables/minor_5.csv index 742d7b69..bcc96fd2 100644 --- a/openpower/isatables/minor_5.csv +++ b/openpower/isatables/minor_5.csv @@ -1,2 +1,3 @@ opcode,unit,internal op,in1,in2,in3,out,CR in,CR out,inv A,inv out,cry in,cry out,ldst len,BR,sgn ext,upd,rsrv,32b,sgn,rc,lk,sgl pipe,comment,form,CONDITIONS,unofficial,comment2 --------00-,SHIFT_ROT,OP_TERNLOG,RA,RB,RT,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,0,0,RC_ONLY,0,0,ternlogi,TLI,,1,unofficial until submitted and approved/renumbered by the opf isa wg +--------01-,CR,OP_CRTERNLOG,NONE,NONE,NONE,NONE,BFA_BFB_BF,BF,0,0,ZERO,0,NONE,0,0,0,0,0,0,NONE,0,0,crternlogi,CRB,,1,unofficial until submitted and approved/renumbered by the opf isa wg diff --git a/src/openpower/decoder/isa/caller.py b/src/openpower/decoder/isa/caller.py index 8e476a28..dd0b3f26 100644 --- a/src/openpower/decoder/isa/caller.py +++ b/src/openpower/decoder/isa/caller.py @@ -1652,7 +1652,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): # these are all opcode fields involved in index-selection of CR, # and need to do "standard" arithmetic. CR[BA+32] for example # would, if using SelectableInt, only be 5-bit. - if name in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']: + if name in ['BF', 'BFA', 'BFB', 'BC', 'BA', 'BB', 'BT', 'BI']: self.namespace[name] = val else: self.namespace[name] = SelectableInt(val, sig.width) @@ -2275,7 +2275,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): "brh", "brw", "brd", 'setvl', 'svindex', 'svremap', 'svstep', 'svshape', 'svshape2', - 'ternlogi', 'bmask', 'cprop', 'gbbd', + 'crternlogi', 'ternlogi', 'bmask', 'cprop', 'gbbd', 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd', 'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du", "dsld", "dsrd", "maddedus", diff --git a/src/openpower/decoder/power_decoder2.py b/src/openpower/decoder/power_decoder2.py index b73fbe76..9e3bca4a 100644 --- a/src/openpower/decoder/power_decoder2.py +++ b/src/openpower/decoder/power_decoder2.py @@ -654,6 +654,13 @@ class DecodeCRIn(Elaboratable): comb += self.cr_bitfield_b.ok.eq(1) comb += self.cr_bitfield_o.data.eq(self.dec.BT[2:5]) comb += self.cr_bitfield_o.ok.eq(1) + with m.Case(CRInSel.BFA_BFB_BF): + comb += self.cr_bitfield.data.eq(self.dec.FormCRB.BFA) + comb += self.cr_bitfield.ok.eq(1) + comb += self.cr_bitfield_b.data.eq(self.dec.FormCRB.BFB) + comb += self.cr_bitfield_b.ok.eq(1) + comb += self.cr_bitfield_o.data.eq(self.dec.FormCRB.BF) + comb += self.cr_bitfield_o.ok.eq(1) with m.Case(CRInSel.BC): comb += self.cr_bitfield.data.eq(self.dec.BC[2:5]) comb += self.cr_bitfield.ok.eq(1) @@ -1543,7 +1550,7 @@ class PowerDecode2(PowerDecodeSubset): (e.read_cr1, self.dec_cr_in, "cr_bitfield", ), (e.read_cr2, self.dec_cr_in, "cr_bitfield_b", ), (e.read_cr3, self.dec_cr_in, "cr_bitfield_o", ), - (e.write_cr, self.dec_cr_out, "cr_bitfield", )): + (e.write_cr, self.dec_cr_out, "cr_bitfield", )): fromreg = getattr(cr, name) comb += to_reg.data.eq(fromreg.data) comb += to_reg.ok.eq(fromreg.ok) diff --git a/src/openpower/decoder/power_enums.py b/src/openpower/decoder/power_enums.py index c0c1ddca..e6876f62 100644 --- a/src/openpower/decoder/power_enums.py +++ b/src/openpower/decoder/power_enums.py @@ -278,6 +278,7 @@ class Reg(Enum): CR1 = auto() BF = auto() BFA = auto() + BFB = auto() BA = auto() BB = auto() BC = auto() @@ -652,6 +653,7 @@ class RegType(Enum): CR_3BIT = 2 # CR field; the CR register is 32-bit BF = CR_3BIT BFA = CR_3BIT + BFB = CR_3BIT CR_5BIT = 3 # bit of the 32-bit CR register BA = CR_5BIT @@ -747,6 +749,7 @@ _insns = [ "cprop", # AV bitmanip "crand", "crandc", "creqv", "crnand", "crnor", "cror", "crorc", "crxor", + "crternlogi", # ternary bitmanip "darn", "dcbf", "dcbst", "dcbt", "dcbtst", "dcbz", "divd", "divde", "divdeo", "divdeu", @@ -965,6 +968,7 @@ class MicrOp(Enum): OP_PEXT = 110 OP_SETBC = 111 OP_BMAT = 112 # bmatflip/xor/and - known by many names (vgbbd in Power) + OP_CRTERNLOG = 113 class SelType(Enum): @@ -1138,6 +1142,7 @@ class CRInSel(Enum): WHOLE_REG = 6 CR1 = 7 BA = 8 + BFA_BFB_BF = 9 def __str__(self): return self.name diff --git a/src/openpower/decoder/power_svp64.py b/src/openpower/decoder/power_svp64.py index 5c36f03e..97463b6a 100644 --- a/src/openpower/decoder/power_svp64.py +++ b/src/openpower/decoder/power_svp64.py @@ -8,7 +8,7 @@ import os # identifies register by type def is_CR_3bit(regname): - return regname in ['BF', 'BFA'] + return regname in ['BF', 'BFA', 'BFB'] def is_CR_5bit(regname): return regname in ['BA', 'BB', 'BC', 'BI', 'BT'] @@ -155,6 +155,11 @@ class SVP64RM: index1 = svp64_src.get('BA', None) index2 = svp64_src.get('BB', None) entry['sv_cr_in'] = "Idx_%d_%d" % (index1, index2) + elif cr_in == 'BFA_BFB_BF': + index1 = svp64_src.get('BFA', None) + index2 = svp64_src.get('BFB', None) + index3 = svp64_src.get('BF', None) + entry['sv_cr_in'] = "Idx_%d_%d_%d" % (index1, index2, index3) # CRout a lot easier. ignore WHOLE_REG for now cr_out = entry['CR out'] diff --git a/src/openpower/insndb/core.py b/src/openpower/insndb/core.py index f441cf8b..4a7f4feb 100644 --- a/src/openpower/insndb/core.py +++ b/src/openpower/insndb/core.py @@ -391,6 +391,11 @@ class SVP64Record(Dataclass): record["cr_in"] = "BA" record["cr_in2"] = "BB" del record["CR in"] + elif record["CR in"] == "BFA_BFB_BF": + record["cr_in"] = "BFA" + record["cr_in2"] = "BFB" + #record["cr_out"] = "BF" # only use BFA_BFB_BF when BF is a dest + del record["CR in"] extra = [] for idx in range(0, 4): @@ -458,6 +463,15 @@ class SVP64Record(Dataclass): regs[key] = _Reg(sels[key]) seltype[key] = _SelType.SRC + # should only be used when BF is also a destination + if sels["cr_in"] is _CRInSel.BFA_BFB_BF: + sels["cr_in"] = _CRIn2Sel.BFA + sels["cr_in2"] = _CRIn2Sel.BFB + idxs["cr_in2"] = idxs["cr_in"] + for key in ("cr_in", "cr_in2"): + regs[key] = _Reg(sels[key]) + seltype[key] = _SelType.SRC + records = {} for key in keys: records[key] = { diff --git a/src/openpower/test/bitmanip/bitmanip_cases.py b/src/openpower/test/bitmanip/bitmanip_cases.py index e9f6bb46..ba685b2e 100644 --- a/src/openpower/test/bitmanip/bitmanip_cases.py +++ b/src/openpower/test/bitmanip/bitmanip_cases.py @@ -4,7 +4,7 @@ from openpower.endian import bigendian from openpower.simulator.program import Program from openpower.test.state import ExpectedState from nmutil.sim_util import hash_256 -from openpower.decoder.isa.caller import SVP64State +from openpower.decoder.isa.caller import SVP64State, CRFields from openpower.util import log import struct import itertools @@ -32,6 +32,54 @@ class BitManipTestCase(TestAccumulatorBase): self.add_case(Program(lst, bigendian), initial_regs, expected=e) + def do_case_crternlogi(self, bf, bfa, bfb, imm, mask): + lst = [f"crternlogi 3,4,5,%d,%d" % (imm, mask)] + # set up CR + bf %= 2 ** 4 + bfa %= 2 ** 4 + bfb %= 2 ** 4 + cr = CRFields() + cr.crl[3][0:4] = bf + cr.crl[4][0:4] = bfa + cr.crl[5][0:4] = bfb + initial_cr = cr.cr.asint() + print("initial cr", bin(initial_cr), bf, bfa, bfb) + print("mask tli", bin(mask), bin(imm)) + + lst = list(SVP64Asm(lst, bigendian)) + e = ExpectedState(pc=4) + expected = bf&~mask # start at BF, mask overwrites masked bits only + checks = (bfb, bfa, bf) # LUT positions 1<<0=bfb 1<<1=bfa 1<<2=bf + for i in range(4): + lut_index = 0 + for j, check in enumerate(checks): + if check & (1<> i) & 0b1 + if (imm & (1<