From: Jacob Lifshay Date: Tue, 18 Jan 2022 04:58:03 +0000 (-0800) Subject: grev[w][i][.] pseudo-code works X-Git-Tag: sv_maxu_works-initial~552 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b55f37ee14b3253087f0a743eb795b53e59f25d2;p=openpower-isa.git grev[w][i][.] pseudo-code works --- diff --git a/openpower/isa/bitmanip.mdwn b/openpower/isa/bitmanip.mdwn index 3f73b0b8..b2b0ad8b 100644 --- a/openpower/isa/bitmanip.mdwn +++ b/openpower/isa/bitmanip.mdwn @@ -29,8 +29,9 @@ X-Form Pseudo-code: result <- [0] * XLEN + b <- EXTZ64(RB) do i = 0 to XLEN - 1 - idx <- ((RB) ^ i) % XLEN + idx <- b[64-log2(XLEN):63] ^ i result[i] <- (RA)[idx] RT <- result @@ -49,7 +50,7 @@ Pseudo-code: result <- [0] * XLEN do i = 0 to XLEN - 1 - idx <- (XBI ^ i) % XLEN + idx <- XBI[6-log2(XLEN):5] ^ i result[i] <- (RA)[idx] RT <- result @@ -66,11 +67,13 @@ X-Form Pseudo-code: - result <- [0] * XLEN # MSB half just stays zeroed + result <- [0] * (XLEN / 2) + a <- (RA)[XLEN/2:XLEN-1] + b <- EXTZ64(RB) do i = 0 to XLEN / 2 - 1 - idx <- ((RB) ^ i) % (XLEN / 2) - result[i] <- (RA)[idx] - RT <- result + idx <- b[64-log2(XLEN/2):63] ^ i + result[i] <- a[idx] + RT <- ([0] * (XLEN / 2)) || result Special Registers Altered: @@ -85,11 +88,12 @@ X-Form Pseudo-code: - result <- [0] * XLEN # MSB half just stays zeroed + result <- [0] * (XLEN / 2) + a <- (RA)[XLEN/2:XLEN-1] do i = 0 to XLEN / 2 - 1 - idx <- (SH ^ i) % (XLEN / 2) - result[i] <- (RA)[idx] - RT <- result + idx <- SH[5-log2(XLEN/2):4] ^ i + result[i] <- a[idx] + RT <- ([0] * (XLEN / 2)) || result Special Registers Altered: diff --git a/openpower/isatables/minor_5.csv b/openpower/isatables/minor_5.csv index ec0cbc17..c0260dbf 100644 --- a/openpower/isatables/minor_5.csv +++ b/openpower/isatables/minor_5.csv @@ -1,6 +1,6 @@ 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,NONE,0,0,ternlogi,TLI,,1,unofficial until submitted and approved/renumbered by the opf isa wg -0010010110-,SHIFT_ROT,OP_GREV,RA,RB,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,0,0,NONE,0,0,grev,X,,1,unofficial until submitted and approved/renumbered by the opf isa wg --011010110-,SHIFT_ROT,OP_GREV,RA,CONST_XBI,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,0,0,NONE,0,0,grevi,XB,,1,unofficial until submitted and approved/renumbered by the opf isa wg -0010110110-,SHIFT_ROT,OP_GREV,RA,RB,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,1,0,NONE,0,0,grevw,X,,1,unofficial until submitted and approved/renumbered by the opf isa wg -0011110110-,SHIFT_ROT,OP_GREV,RA,CONST_SH32,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,1,0,NONE,0,0,grevwi,X,,1,unofficial until submitted and approved/renumbered by the opf isa wg +0010010110-,SHIFT_ROT,OP_GREV,RA,RB,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,0,0,RC,0,0,grev,X,,1,unofficial until submitted and approved/renumbered by the opf isa wg +-011010110-,SHIFT_ROT,OP_GREV,RA,CONST_XBI,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,0,0,RC,0,0,grevi,XB,,1,unofficial until submitted and approved/renumbered by the opf isa wg +0010110110-,SHIFT_ROT,OP_GREV,RA,RB,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,1,0,RC,0,0,grevw,X,,1,unofficial until submitted and approved/renumbered by the opf isa wg +0011110110-,SHIFT_ROT,OP_GREV,RA,CONST_SH32,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,1,0,RC,0,0,grevwi,X,,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 a4b39ef1..804da2a4 100644 --- a/src/openpower/decoder/isa/caller.py +++ b/src/openpower/decoder/isa/caller.py @@ -13,6 +13,7 @@ related bugs: * https://bugs.libre-soc.org/show_bug.cgi?id=424 """ +import re from nmigen.back.pysim import Settle from functools import wraps from copy import copy, deepcopy @@ -1252,7 +1253,8 @@ class ISACaller(ISACallerHelper, ISAFPHelpers): illegal = False ins_name = 'ffadds' - if asmop == 'ternlogi': + if asmop == 'ternlogi' \ + or re.fullmatch(r'grevw?i?\.?', asmop or ''): illegal = False ins_name = asmop diff --git a/src/openpower/decoder/power_decoder2.py b/src/openpower/decoder/power_decoder2.py index a636fdf5..a8ff8532 100644 --- a/src/openpower/decoder/power_decoder2.py +++ b/src/openpower/decoder/power_decoder2.py @@ -575,7 +575,7 @@ class DecodeOE(Elaboratable): MicrOp.OP_SHL, MicrOp.OP_SHR, MicrOp.OP_RLC, MicrOp.OP_LOAD, MicrOp.OP_STORE, MicrOp.OP_RLCL, MicrOp.OP_RLCR, - MicrOp.OP_EXTSWSLI): + MicrOp.OP_EXTSWSLI, MicrOp.OP_GREV): pass # all other ops decode OE field diff --git a/src/openpower/decoder/power_enums.py b/src/openpower/decoder/power_enums.py index 757df322..a0f85b58 100644 --- a/src/openpower/decoder/power_enums.py +++ b/src/openpower/decoder/power_enums.py @@ -284,6 +284,8 @@ _insns = [ "fmul", "fmuls", "fdiv", "fdivs", # FP mul / div "fmr", "fabs", "fnabs", "fneg", "fcpsgn", # FP move/abs/neg "fsins", "fcoss", # FP SIN/COS + 'grev', 'grev.', 'grevi', 'grevi.', + 'grevw', 'grevw.', 'grevwi', 'grevwi.', "hrfid", "icbi", "icbt", "isel", "isync", "lbarx", "lbz", "lbzcix", "lbzu", "lbzux", "lbzx", # load byte "ld", "ldarx", "ldbrx", "ldu", "ldux", "ldx", # load double diff --git a/src/openpower/sv/trans/svp64.py b/src/openpower/sv/trans/svp64.py index 29bfadad..65aa1768 100644 --- a/src/openpower/sv/trans/svp64.py +++ b/src/openpower/sv/trans/svp64.py @@ -297,6 +297,38 @@ class SVP64Asm: yield f".4byte {hex(instr)} # {asm}" return + # XXX WARNING THESE ARE NOT APPROVED BY OPF ISA WG + # however we are out of space with opcode 22 + if opcode in ('grev', 'grevi', 'grevw', 'grevwi', + 'grev.', 'grevi.', 'grevw.', 'grevwi.'): + po = 5 + # _ matches fields in table at: + # https://libre-soc.org/openpower/sv/bitmanip/ + xo = 0b1_0010_110 + if 'w' in opcode: + xo |= 0b100_000 + if 'i' in opcode: + xo |= 0b1000_000 + Rc = 1 if '.' in opcode else 0 + rt = int(fields[0]) + ra = int(fields[1]) + rb_imm = int(fields[2]) + instr = po + instr = (instr << 5) | rt + instr = (instr << 5) | ra + if opcode == 'grevi' or opcode == 'grevi.': + assert 0 <= rb_imm < 64 + instr = (instr << 6) | rb_imm + instr = (instr << 9) | xo + else: + assert 0 <= rb_imm < 32 + instr = (instr << 5) | rb_imm + instr = (instr << 10) | xo + instr = (instr << 1) | Rc + asm = f"{opcode} {rt}, {ra}, {rb_imm}" + yield f".4byte {hex(instr)} # {asm}" + return + # identify if is a svp64 mnemonic if not opcode.startswith('sv.'): yield insn # unaltered diff --git a/src/openpower/test/bitmanip/bitmanip_cases.py b/src/openpower/test/bitmanip/bitmanip_cases.py index f38e0666..0fcb0d71 100644 --- a/src/openpower/test/bitmanip/bitmanip_cases.py +++ b/src/openpower/test/bitmanip/bitmanip_cases.py @@ -34,6 +34,36 @@ class BitManipTestCase(TestAccumulatorBase): e.intregs[5] = rb self.add_case(Program(lst, bigendian), initial_regs, expected=e) + def do_case_grev(self, w, is_imm, ra, rb): + bits = 32 if w else 64 + masked_rb = rb % bits + if is_imm: + lst = [f"grev{'w' if w else ''}i. 3, 4, {masked_rb}"] + else: + lst = [f"grev{'w' if w else ''}. 3, 4, 5"] + initial_regs = [0] * 32 + ra %= 2 ** 64 + rb %= 2 ** 64 + initial_regs[4] = ra + initial_regs[5] = rb + lst = list(SVP64Asm(lst, bigendian)) + e = ExpectedState(pc=4) + expected = 0 + for i in range(bits): + dest_bit = i ^ masked_rb + if ra & 2 ** i: + expected |= 2 ** dest_bit + e.intregs[3] = expected + e.intregs[4] = ra + e.intregs[5] = rb + if expected & 2 ** 63: # sign extend + expected -= 2 ** 64 + eq = expected == 0 + gt = expected > 0 + lt = expected < 0 + e.crregs[0] = (eq << 1) | (gt << 2) | (lt << 3) + self.add_case(Program(lst, bigendian), initial_regs, expected=e) + def case_ternlogi_0(self): self.do_case_ternlogi(0x8000_0000_FFFF_0000, 0x8000_0000_FF00_FF00, @@ -49,3 +79,21 @@ class BitManipTestCase(TestAccumulatorBase): ra = hash_256(f"ternlogi ra {i}") % 2 ** 64 rb = hash_256(f"ternlogi rb {i}") % 2 ** 64 self.do_case_ternlogi(rt, ra, rb, imm) + + def case_grev_random(self): + for i in range(100): + w = hash_256(f"grev w {i}") & 1 + is_imm = hash_256(f"grev is_imm {i}") & 1 + ra = hash_256(f"grev ra {i}") % 2 ** 64 + rb = hash_256(f"grev rb {i}") % 2 ** 64 + self.do_case_grev(w, is_imm, ra, rb) + + def case_grevi_1(self): + self.do_case_grev(False, True, 14361919363078703450, + 8396479064514513069) + + def case_grevi_2(self): + self.do_case_grev(True, True, 397097147229333315, 8326716970539357702) + + def case_grevi_3(self): + self.do_case_grev(True, True, 0xFFFF_FFFF_0000_0000, 6)