From 51d543b9d0c4ebb2eca840fd81231bbf96213bd5 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Tue, 18 Jul 2023 20:01:30 -0700 Subject: [PATCH] add fminmax tests with corresponding pseudocode fixes --- openpower/isa/fptrans.mdwn | 6 +- .../decoder/isa/test_caller_fminmax.py | 23 +++ src/openpower/test/fptrans/fminmax_cases.py | 179 ++++++++++++++++++ 3 files changed, 205 insertions(+), 3 deletions(-) create mode 100644 src/openpower/decoder/isa/test_caller_fminmax.py create mode 100644 src/openpower/test/fptrans/fminmax_cases.py diff --git a/openpower/isa/fptrans.mdwn b/openpower/isa/fptrans.mdwn index 0a13b3d7..9060c79f 100644 --- a/openpower/isa/fptrans.mdwn +++ b/openpower/isa/fptrans.mdwn @@ -1462,9 +1462,9 @@ Pseudo-code: b_is_snan <- b_is_nan & (b[12] = 0) any_snan <- a_is_snan | b_is_snan a_quieted <- a - a_quieted[12] = 1 + a_quieted[12] <- 1 b_quieted <- b - b_quieted[12] = 1 + b_quieted[12] <- 1 if a_is_nan | b_is_nan then if FMM[2:3] = 0b00 then # min/maxnum08 if a_is_snan then result <- a_quieted @@ -1505,7 +1505,7 @@ Pseudo-code: else if cmp_l tuple[int, bool] + op = FMinMaxMode(FMM.value & 0b11) + is_max = bool(FMM.value & 0b1000) + is_mag = bool(FMM.value & 0b100) + MANT_MASK = 0xF_FFFF_FFFF_FFFF + EXP_MASK = 0x7FF0_0000_0000_0000 + SIGN_MASK = 0x8000_0000_0000_0000 + a_is_nan = RA & MANT_MASK and RA & EXP_MASK == EXP_MASK + a_quieted = RA | 0x8_0000_0000_0000 + b_is_nan = RB & MANT_MASK and RB & EXP_MASK == EXP_MASK + b_quieted = RB | 0x8_0000_0000_0000 + a_is_snan = a_is_nan and a_quieted != RA + b_is_snan = b_is_nan and b_quieted != RB + any_snan = a_is_snan or b_is_snan + if op is FMinMaxMode.fminnum08: + if a_is_snan: + return a_quieted, any_snan + if b_is_snan: + return b_quieted, any_snan + if a_is_nan and b_is_nan: + return a_quieted, any_snan + if a_is_nan: + return RB, any_snan + if b_is_nan: + return RA, any_snan + elif op is FMinMaxMode.fmin19: + if a_is_nan: + return a_quieted, any_snan + if b_is_nan: + return b_quieted, any_snan + elif op is FMinMaxMode.fminnum19: + if a_is_nan and b_is_nan: + return a_quieted, any_snan + if a_is_nan: + return RB, any_snan + if b_is_nan: + return RA, any_snan + else: + assert op is FMinMaxMode.fminc + if a_is_nan or b_is_nan: + return RB, any_snan + if RA & ~SIGN_MASK == 0 and RB & ~SIGN_MASK == 0: + return RB, any_snan + if RA & ~SIGN_MASK == 0 and RB & ~SIGN_MASK == 0: + if is_max: + return RA & RB, any_snan + return RA | RB, any_snan + cmp = operator.lt + if is_max: + cmp = operator.gt + cmp_RA = RA + cmp_RB = RB + if is_mag and RA & ~SIGN_MASK != RB & ~SIGN_MASK: + cmp_RA &= ~SIGN_MASK + cmp_RB &= ~SIGN_MASK + cmp_RA = struct.unpack(" None + if self._FILTER is not None and ( + str(FMM) != self._FILTER['FMM'] or + VE != self._FILTER['VE'] or + initial_VXSNAN != self._FILTER['initial_VXSNAN']): + return + prog = Program(list(SVP64Asm([f"fminmax. 3,4,5,{FMM.value}"])), False) + for RA in _TEST_VALUES: + for RB in _TEST_VALUES: + gprs = [0] * 32 + fprs = [0] * 32 + fprs[3] = 0x0123_4567_89AB_CDEF + fprs[4] = RA + fprs[5] = RB + e = ExpectedState(pc=4, int_regs=gprs, fp_regs=fprs) + initial_fpscr = FPSCRState() + initial_fpscr.VE = VE + initial_fpscr.VXSNAN = initial_VXSNAN + fpscr = FPSCRState(initial_fpscr) + RT, any_snan = self.reference_fminmax(FMM, RA, RB) + if any_snan: + if not fpscr.VXSNAN: + fpscr.FX = 1 + fpscr.VXSNAN = 1 + if not fpscr.VE or not any_snan: + e.fpregs[3] = RT + else: + e.pc = 0x700 + e.sprs['SRR0'] = 0 # insn is at address 0 + e.sprs['SRR1'] = e.msr | (1 << (63 - 43)) + e.msr = 0x9000000000000001 + e.fpscr = int(fpscr) + cr1 = int(fpscr.FX) << 3 + cr1 |= int(fpscr.FEX) << 2 + cr1 |= int(fpscr.VX) << 1 + cr1 |= int(fpscr.OX) + e.crregs[1] = cr1 + kwargs = dict( + RA=hex(RA), RB=hex(RB), FMM=str(FMM), VE=VE, + initial_VXSNAN=initial_VXSNAN, expected=hex(RT), + any_snan=any_snan, CR1=cr1) + if self._FILTER is not None and kwargs != self._FILTER: + continue + with self.subTest(**kwargs): + self.add_case(prog, gprs, fpregs=fprs, expected=e, + initial_fpscr=int(initial_fpscr)) + + def case_fminmax(self): + for FMM, VE, VXSNAN in itertools.product( + FMinMaxMode, (False, True), (False, True)): + if VE and VXSNAN: + # isn't really a legal state that the simulator can end up in + # since MSR.FE0/FE1 are also set, this would have been caught + # by whatever previous instruction changed to this state + continue + self.fminmax(FMM, VE, VXSNAN) -- 2.30.2