from openpower.insndb.asm import SVP64Asm
-import random
from openpower.test.common import TestAccumulatorBase, skip_case
from openpower.endian import bigendian
from openpower.simulator.program import Program
-from openpower.decoder.selectable_int import SelectableInt
-from openpower.decoder.power_enums import XER_bits
from openpower.decoder.isa.caller import SVP64State
-from openpower.decoder.helpers import exts
from openpower.test.state import ExpectedState
-import unittest
+from nmutil.sim_util import hash_256
import math
+from fractions import Fraction
class MADDSUBRSTestCase(TestAccumulatorBase):
-
def case_0_maddsubrs(self):
isa = SVP64Asm(["maddsubrs 1,10,14,11"])
lst = list(isa)
self.add_case(p, initial_regs, expected=e, initial_svstate=svstate)
+ def maddsubrs_many_helper(self, width, shift, prog, case_idx):
+ # if {'width': width, 'shift': shift, 'case_idx': case_idx} \
+ # != {'width': 8, 'shift': 1, 'case_idx': 0}:
+ # return # for debugging
+ gprs = [0] * 32
+ # make some reproducible random inputs
+ k = f"maddsubrs {width} {shift} {case_idx}"
+ gprs[10] = hash_256(k + " r10") % 2**64
+ gprs[20] = hash_256(k + " r20") % 2**64
+ gprs[30] = hash_256(k + " r30") % 2**64
+
+ svstate = SVP64State()
+ svstate.vl = 64 // width # one full 64-bit register
+ svstate.maxvl = 64 // width
+
+ e = ExpectedState(pc=8, int_regs=gprs)
+ e.intregs[10] = 0
+ e.intregs[11] = 0
+ for i in range(svstate.vl):
+ # extract elements
+ rt = (gprs[10] >> (i * width)) % 2 ** width
+ ra = (gprs[20] >> (i * width)) % 2 ** width
+ rb = (gprs[30] >> (i * width)) % 2 ** width
+ if rt >= 2 ** (width - 1):
+ rt -= 2 ** width # sign extend rt
+ if ra >= 2 ** (width - 1):
+ ra -= 2 ** width # sign extend ra
+ if rb >= 2 ** (width - 1):
+ rb -= 2 ** width # sign extend rb
+ s = rt + ra
+ d = rt - ra
+ factor = Fraction(1, 2 ** shift) # shr factor
+ round_up = Fraction(1, 2)
+ # mul & round & shr
+ rt = math.floor((s * rb) * factor + round_up)
+ rs = math.floor((d * rb) * factor + round_up)
+ # insert elements
+ e.intregs[10] |= (rt % 2 ** width) << (width * i)
+ e.intregs[11] |= (rs % 2 ** width) << (width * i)
+
+ with self.subTest(
+ width=width, shift=shift, case_idx=case_idx,
+ RT_in=hex(gprs[10]), RA_in=hex(gprs[20]), RB_in=hex(gprs[30]),
+ expected_RT=hex(e.intregs[10]), expected_RS=hex(e.intregs[11]),
+ ):
+ self.add_case(prog, gprs, expected=e, initial_svstate=svstate)
+
+ def case_maddsubrs_many(self):
+ for width in 8, 16, 32, 64:
+ shift_end = min(32, width)
+ for shift in range(0, shift_end, shift_end // 8):
+ w = "" if width == 64 else f"/w={width}"
+ prog = Program(list(SVP64Asm([
+ f"sv.maddsubrs{w} *10,*20,{shift},*30",
+ ])), bigendian)
+
+ for case_idx in range(25):
+ self.maddsubrs_many_helper(width, shift, prog, case_idx)
+
def case_0_maddrs(self):
isa = SVP64Asm(["maddsubrs 1,10,0,11",
"maddrs 1,10,0,12"])