Blob Blame Raw
From 2c1f016e634bf79faf45e81c14c955c711bc202f Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mark@klomp.org>
Date: Mon, 31 Dec 2018 22:26:31 +0100
Subject: [PATCH] Bug 402519 - POWER 3.0 addex instruction incorrectly
 implemented

addex uses OV as carry in and carry out. For all other instructions
OV is the signed overflow flag. And instructions like adde use CA
as carry.

Replace set_XER_OV_OV32 with set_XER_OV_OV32_ADDEX, which will
call calculate_XER_CA_64 and calculate_XER_CA_32, but with OV
as input, and sets OV and OV32.

Enable test_addex in none/tests/ppc64/test_isa_3_0.c and update
the expected output. test_addex would fail to match the expected
output before this patch.
---
 NEWS                                              |  1 +
 VEX/priv/guest_ppc_toIR.c                         | 52 ++++++++++++++---------
 none/tests/ppc64/test_isa_3_0.c                   |  3 +-
 none/tests/ppc64/test_isa_3_0_other.stdout.exp-LE | 36 ++++++++++------
 4 files changed, 58 insertions(+), 34 deletions(-)

diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c
index 18df822..d685383 100644
--- a/VEX/priv/guest_ppc_toIR.c
+++ b/VEX/priv/guest_ppc_toIR.c
@@ -2645,21 +2645,6 @@ static void copy_OV_to_OV32( void ) {
    putXER_OV32( getXER_OV() );
 }
 
-static void set_XER_OV_OV32 ( IRType ty, UInt op, IRExpr* res,
-                              IRExpr* argL, IRExpr* argR )
-{
-   if (ty == Ity_I32) {
-      set_XER_OV_OV32_32( op, res, argL, argR );
-   } else {
-      IRExpr* xer_ov_32;
-      set_XER_OV_64( op, res, argL, argR );
-      xer_ov_32 = calculate_XER_OV_32( op, unop(Iop_64to32, res),
-                                       unop(Iop_64to32, argL),
-                                       unop(Iop_64to32, argR));
-      putXER_OV32( unop(Iop_32to8, xer_ov_32) );
-   }
-}
-
 static void set_XER_OV_OV32_SO ( IRType ty, UInt op, IRExpr* res,
                                  IRExpr* argL, IRExpr* argR )
 {
@@ -3005,6 +2990,33 @@ static void set_XER_CA_CA32 ( IRType ty, UInt op, IRExpr* res,
    }
 }
 
+/* Used only by addex instruction, which uses and sets OV as carry.  */
+static void set_XER_OV_OV32_ADDEX ( IRType ty, IRExpr* res,
+                                    IRExpr* argL, IRExpr* argR,
+                                    IRExpr* old_ov )
+{
+   if (ty == Ity_I32) {
+      IRTemp xer_ov = newTemp(Ity_I32);
+      assign ( xer_ov, unop(Iop_32to8,
+                            calculate_XER_CA_32( PPCG_FLAG_OP_ADDE,
+                                                 res, argL, argR, old_ov ) ) );
+      putXER_OV( mkexpr (xer_ov) );
+      putXER_OV32( mkexpr (xer_ov) );
+   } else {
+      IRExpr *xer_ov;
+      IRExpr* xer_ov_32;
+      xer_ov = calculate_XER_CA_64( PPCG_FLAG_OP_ADDE,
+                                    res, argL, argR, old_ov );
+      putXER_OV( unop(Iop_32to8, xer_ov) );
+      xer_ov_32 = calculate_XER_CA_32( PPCG_FLAG_OP_ADDE,
+                                       unop(Iop_64to32, res),
+                                       unop(Iop_64to32, argL),
+                                       unop(Iop_64to32, argR),
+                                       unop(Iop_64to32, old_ov) );
+      putXER_OV32( unop(Iop_32to8, xer_ov_32) );
+   }
+}
+
 
 
 /*------------------------------------------------------------*/
@@ -5094,16 +5106,18 @@ static Bool dis_int_arith ( UInt theInstr )
       }
 
       case 0xAA: {// addex (Add Extended alternate carry bit Z23-form)
+         IRTemp old_xer_ov = newTemp(ty);
          DIP("addex r%u,r%u,r%u,%d\n", rD_addr, rA_addr, rB_addr, (Int)flag_OE);
+         assign( old_xer_ov, mkWidenFrom32(ty, getXER_OV_32(), False) );
          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
                             binop( mkSzOp(ty, Iop_Add8), mkexpr(rB),
-                                   mkWidenFrom8( ty, getXER_OV(), False ) ) ) );
+                                   mkexpr(old_xer_ov) ) ) );
 
          /* CY bit is same as OE bit */
          if (flag_OE == 0) {
-            /* Exception, do not set SO bit */
-            set_XER_OV_OV32( ty, PPCG_FLAG_OP_ADDE,
-                             mkexpr(rD), mkexpr(rA), mkexpr(rB) );
+            /* Exception, do not set SO bit and set OV from carry. */
+            set_XER_OV_OV32_ADDEX( ty, mkexpr(rD), mkexpr(rA), mkexpr(rB),
+                                   mkexpr(old_xer_ov) );
          } else {
             /* CY=1, 2 and 3 (AKA flag_OE) are reserved */
             vex_printf("addex instruction, CY = %d is reserved.\n", flag_OE);
diff --git a/none/tests/ppc64/test_isa_3_0.c b/none/tests/ppc64/test_isa_3_0.c
index 2d13505..1c2cda3 100644
--- a/none/tests/ppc64/test_isa_3_0.c
+++ b/none/tests/ppc64/test_isa_3_0.c
@@ -286,7 +286,7 @@ static test_list_t testgroup_ia_ops_two[] = {
    { &test_moduw, "moduw" },
    { &test_modsd, "modsd" },
    { &test_modud, "modud" },
-   //{ &test_addex, "addex" },
+   { &test_addex, "addex" },
    { NULL       , NULL             },
 };
 
@@ -2741,7 +2741,6 @@ static void testfunction_gpr_vector_logical_one (const char* instruction_name,
     *   rt, xa
     */
    int i;
-   int t;
    volatile HWord_t res;
 
    VERBOSE_FUNCTION_CALLOUT
diff --git a/none/tests/ppc64/test_isa_3_0_other.stdout.exp-LE b/none/tests/ppc64/test_isa_3_0_other.stdout.exp-LE
index 152ff28..cc0e88e 100644
--- a/none/tests/ppc64/test_isa_3_0_other.stdout.exp-LE
+++ b/none/tests/ppc64/test_isa_3_0_other.stdout.exp-LE
@@ -40,7 +40,17 @@ modud ffffffffffffffff, 0000000000000000 => 0000000000000000 (00000000)
 modud ffffffffffffffff, 0000001cbe991def => 000000043eb0c0b2 (00000000)
 modud ffffffffffffffff, ffffffffffffffff => 0000000000000000 (00000000)
 
-All done. Tested 4 different instructions
+addex 0000000000000000, 0000000000000000 => 0000000000000000 (00000000)
+addex 0000000000000000, 0000001cbe991def => 0000001cbe991def (00000000)
+addex 0000000000000000, ffffffffffffffff => ffffffffffffffff (00000000)
+addex 0000001cbe991def, 0000000000000000 => 0000001cbe991def (00000000)
+addex 0000001cbe991def, 0000001cbe991def => 000000397d323bde (00000000) OV32
+addex 0000001cbe991def, ffffffffffffffff => 0000001cbe991dee (00000000) OV OV32
+addex ffffffffffffffff, 0000000000000000 => 0000000000000000 (00000000) OV OV32
+addex ffffffffffffffff, 0000001cbe991def => 0000001cbe991def (00000000) OV OV32
+addex ffffffffffffffff, ffffffffffffffff => ffffffffffffffff (00000000) OV OV32
+
+All done. Tested 5 different instructions
 ppc one argument plus shift:
 Test instruction group [ppc one argument plus shift]
 extswsli  aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa 0 ffffffffffffffff => aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa 0 ffffffffffffffff
@@ -85,7 +95,7 @@ extswsli. aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa 0 ffaa5599113377cc => aaaaaaaaaaaaaa
 extswsli. 5152535455565758 5152535455565758 0 ffaa5599113377cc => 5152535455565758 5152535455565758 0 ffaa5599113377cc
 extswsli. 0000000000000000 0000000000000000 0 ffaa5599113377cc => 0000000000000000 0000000000000000 0 ffaa5599113377cc
 
-All done. Tested 6 different instructions
+All done. Tested 7 different instructions
 ppc three parameter ops:
 Test instruction group [ppc three parameter ops]
 maddhd  0000000000000000, 0000000000000000, 0000000000000000  => 0000000000000000 (00000000)
@@ -172,7 +182,7 @@ maddld  ffffffffffffffff, ffffffffffffffff, 0000000000000000  => 000000000000000
 maddld  ffffffffffffffff, ffffffffffffffff, 0000001cbe991def  => 0000001cbe991df0 (00000000)
 maddld  ffffffffffffffff, ffffffffffffffff, ffffffffffffffff  => 0000000000000000 (00000000)
 
-All done. Tested 9 different instructions
+All done. Tested 10 different instructions
 ppc count zeros:
 Test instruction group [ppc count zeros]
 cnttzw 0000000000000000 => 0000000000000020
@@ -197,7 +207,7 @@ cnttzd. 0000001cbe991def => 0000000000000000 Expected cr0 to be zero, it is (200
 cnttzd. ffffffffffffffff => 0000000000000000 Expected cr0 to be zero, it is (20000000)
 
 
-All done. Tested 13 different instructions
+All done. Tested 14 different instructions
 ppc set boolean:
 Test instruction group [ppc set boolean]
 setb cr_field:0 cr_value::00000000 =>  0000000000000000
@@ -265,7 +275,7 @@ setb cr_field:7 cr_value::00000005 =>  0000000000000001
 setb cr_field:7 cr_value::00000006 =>  0000000000000001
 setb cr_field:7 cr_value::00000007 =>  0000000000000001
 
-All done. Tested 14 different instructions
+All done. Tested 15 different instructions
 ppc char compare:
 Test instruction group [ppc char compare]
 cmprb l=0 0x61 (a) (cmpeq:0x5b427b625a417a61) (cmprb:src22(a-z) src21(A-Z)) => in range/found
@@ -1711,7 +1721,7 @@ cmpeqb 0x5d (]) (cmpeq:0x4642666245416561) (cmprb:src22(a-e) src21(A-E)) =>
 cmpeqb 0x60 (`) (cmpeq:0x4642666245416561) (cmprb:src22(a-e) src21(A-E)) =>
 cmpeqb 0x5f (_) (cmpeq:0x4642666245416561) (cmprb:src22(a-e) src21(A-E)) =>
 
-All done. Tested 17 different instructions
+All done. Tested 18 different instructions
 ppc vector scalar move to/from:
 Test instruction group [ppc vector scalar move to/from]
 mfvsrld aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa 0 ffffffffffffffff => aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa ffffffffffffffff
@@ -1777,7 +1787,7 @@ mtvsrws aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa 0 ffaa5599113377cc => 113377cc113377cc
 mtvsrws 5152535455565758 5152535455565758 0 ffaa5599113377cc => 113377cc113377cc 113377cc113377cc 0 ffaa5599113377cc
 mtvsrws 0000000000000000 0000000000000000 0 ffaa5599113377cc => 113377cc113377cc 113377cc113377cc 0 ffaa5599113377cc
 
-All done. Tested 20 different instructions
+All done. Tested 21 different instructions
 ppc dfp significance:
 Test instruction group [ppc dfp significance]
 dtstsfi significance(0x00) +Finite                  0 * 10 ^ -12 (GT) (4)
@@ -1862,7 +1872,7 @@ dtstsfiq significance(0x20) -inf      (GT) (4)
 dtstsfiq significance(0x30) -inf      (GT) (4)
 dtstsfiq significance(0x3f) -inf      (GT) (4)
 
-All done. Tested 22 different instructions
+All done. Tested 23 different instructions
 ppc bcd misc:
 Test instruction group [ppc bcd misc]
 bcdadd. p0 xa:0000000000000000 000000000000000c (+|0) xb:0000000000000000 000000000000000c (+|0) => (EQ) (2) xt:0000000000000000 000000000000000c(+|0)
@@ -33338,12 +33348,12 @@ bcdcfsq. p1 xa:0000000000000000 000000000000000c (+|0) xb:9999999999999999 99999
 bcdcfsq. p1 xa:0000000000000000 000000000000000c (+|0) xb:0000000000000000 000000001234567d ( - ) => (GT) (4) xt:0000000000000000 000000305419901f(+|0)
 
 
-All done. Tested 51 different instructions
+All done. Tested 52 different instructions
 ppc noop misc:
 Test instruction group [ppc noop misc]
 wait   =>
 
-All done. Tested 52 different instructions
+All done. Tested 53 different instructions
 ppc addpc_misc:
 Test instruction group [ppc addpc_misc]
 addpcis   0000000000000000  =>  0000000000000000
@@ -33380,7 +33390,7 @@ subpcis   000000000000000d  =>  0000000000000000
 subpcis   000000000000000e  =>  0000000000000000
 subpcis   000000000000000f  =>  0000000000000000
 
-All done. Tested 54 different instructions
+All done. Tested 55 different instructions
 ppc mffpscr:
 Test instruction group [ppc mffpscr]
 mffsce  =>  000000000.000000
@@ -33395,7 +33405,7 @@ mffs  =>  000000000.000000
  fpscr: f14 
  local_fpscr: 
 
-All done. Tested 57 different instructions
+All done. Tested 58 different instructions
 ppc mffpscr:
 Test instruction group [ppc mffpscr]
 mffscdrni  0  =>  0X0
@@ -33426,4 +33436,4 @@ mffscrn  f15 0X1   =>  0X200000000
 mffscrn  f15 0X2   =>  0X200000000
  fpscr: f14  local_fpscr:  30-DRN1 RN-bit62
 
-All done. Tested 61 different instructions
+All done. Tested 62 different instructions
-- 
1.8.3.1