From a5e874ed4f20a8febed2f7cf51715e2a930f1f01 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Fri, 28 Oct 2022 15:06:25 -0700 Subject: [PATCH] add tests for carry/overflow calculation of addmeo/subfmeo the logic for computing carry/overflow in the simulator is likely broken... the pseudocode may also need to be changed to add [1] * XLEN like in the description of addme/subfme --- src/openpower/test/alu/alu_cases.py | 43 +++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/openpower/test/alu/alu_cases.py b/src/openpower/test/alu/alu_cases.py index bb8a21ee..de2c65e2 100644 --- a/src/openpower/test/alu/alu_cases.py +++ b/src/openpower/test/alu/alu_cases.py @@ -199,6 +199,49 @@ class ALUTestCase(TestAccumulatorBase): self.add_case(Program(lst, bigendian), initial_regs, initial_sprs, expected=e) + def case_addme_subfme_ca_propagation(self): + for flags in range(1 << 2): + ca = flags & 1 + is_sub = (flags >> 1) & 1 + if is_sub: + prog = Program(["subfmeo 3, 4"], bigendian) + else: + prog = Program(["addmeo 3, 4"], bigendian) + for i in range(-2, 3): + ra = i % 2 ** 64 + with self.subTest(ra=hex(ra), ca=ca, is_sub=is_sub): + initial_regs = [0] * 32 + initial_regs[4] = ra + initial_sprs = {} + xer = SelectableInt(0, 64) + xer[XER_bits['CA']] = ca + initial_sprs[special_sprs['XER']] = xer + e = ExpectedState(pc=4) + e.intregs[4] = ra + rb = 2 ** 64 - 1 # add 0xfff...fff *not* -1 + expected = ca + rb + expected32 = ca + (rb % 2 ** 32) + inv_ra = ra + if is_sub: + # 64-bit bitwise not + inv_ra = ~ra % 2 ** 64 + expected += inv_ra + expected32 += inv_ra % 2 ** 32 + e.intregs[3] = expected % 2 ** 64 + ca = bool(expected >> 64) + ca32 = bool(expected32 >> 32) + e.ca = (ca32 << 1) | ca + # use algorithm from microwatt's calc_ov + # https://github.com/antonblanchard/microwatt/blob/5c6d57de3056bd08fdc1f656bc8656635a77512b/execute1.vhdl#L284 + axb = inv_ra ^ rb + emsb = (expected >> 63) & 1 + ov = ca ^ emsb and not (axb >> 63) & 1 + e32msb = (expected32 >> 31) & 1 + ov32 = ca32 ^ e32msb and not (axb >> 31) & 1 + e.ov = (ov32 << 1) | ov + self.add_case(prog, initial_regs, initial_sprs, + expected=e) + def case_addze(self): insns = ["addze", "addze.", "addzeo", "addzeo."] for choice in insns: -- 2.30.2