From 02b6a1de06e99ead310e91aa59ae1261aebaa761 Mon Sep 17 00:00:00 2001 From: Carl Love Date: Wed, 13 May 2020 15:19:07 -0500 Subject: [PATCH] Add ISA 3.1 Vector Integer Multiply/Divide/Modulo Instructions Add support for: vdivesd Vector Divide Extended Signed Doubleword vdivesw Vector Divide Extended Signed Word vdiveud Vector Divide Extended Unsigned Doubleword vdiveuw Vector Divide Extended Unsigned Word vdivsd Vector Divide Signed Doubleword vdivsw Vector Divide Signed Word vdivud Vector Divide Unsigned Doubleword vdivuw Vector Divide Unsigned Word vmodsd Vector Modulo Signed Doubleword vmodsw Vector Modulo Signed Word vmodud Vector Modulo Unsigned Doubleword vmoduw Vector Modulo Unsigned Word vmulhsd Vector Multiply High Signed Doubleword vmulhsw Vector Multiply High Signed Word vmulhud Vector Multiply High Unsigned Doubleword vmulhuw Vector Multiply High Unsigned Word vmulld Vector Multiply Low Doubleword --- VEX/priv/guest_ppc_toIR.c | 398 +++++++++++++++++++++++++++++++++++++- VEX/priv/host_ppc_isel.c | 6 +- 2 files changed, 396 insertions(+), 8 deletions(-) diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c index 7f5d5ba1c5..5d139d0741 100644 --- a/VEX/priv/guest_ppc_toIR.c +++ b/VEX/priv/guest_ppc_toIR.c @@ -3067,6 +3067,22 @@ static void set_XER_OV_OV32_ADDEX ( IRType ty, IRExpr* res, } } +static IRExpr * absI64( IRTemp src ) +{ + IRTemp sign_mask; + IRTemp twos_comp; + sign_mask = newTemp( Ity_I64 ); + twos_comp = newTemp( Ity_I64 ); + + assign( sign_mask, unop( Iop_1Sto64, unop( Iop_64to1, binop( Iop_Shr64, + mkexpr( src ), mkU8( 63 ) ) ) ) ); + assign( twos_comp, binop( Iop_Add64, unop( Iop_Not64, mkexpr( src ) ), mkU64( 1 ) ) ); + + return binop( Iop_Or64, + binop( Iop_And64, mkexpr ( src ), unop( Iop_Not64, mkexpr( sign_mask ) ) ), + binop( Iop_And64, mkexpr( twos_comp ), mkexpr( sign_mask ) ) ); +} + /*-----------------------------------------------------------*/ /*--- Prefix instruction helpers ---*/ /*-----------------------------------------------------------*/ @@ -4124,9 +4140,8 @@ static IRExpr * is_Denorm( IRType size, IRTemp src ) static IRExpr * is_Zero_Vector( IRType element_size, IRExpr *src ) { -/* Check elements of a 128-bit floating point vector, with element size - element_size, are zero. Return 1's in the elements of the vector - which are values. */ +/* Check elements of a 128-bit floating point vector, with element size are + zero. Return 1's in the elements of the vector which are values. */ IRTemp exp_maskV128 = newTemp( Ity_V128 ); IRTemp exp_zeroV128 = newTemp( Ity_V128 ); IRTemp frac_maskV128 = newTemp( Ity_V128 ); @@ -4159,6 +4174,23 @@ static IRExpr * is_Zero_Vector( IRType element_size, IRExpr *src ) mkexpr( frac_zeroV128 ) ); } +static IRExpr * Abs_Zero_Vector( IRType element_size, IRExpr *src ) +/* Vector of four 32-bit elements, convert any negative zeros to + positive zeros. */ +{ + IRTemp result = newTemp( Ity_V128 ); + + if ( element_size == Ity_I32 ) { + assign( result, binop( Iop_AndV128, + src, + unop( Iop_NotV128, + is_Zero_Vector( element_size, src) ) ) ); + } else + vex_printf("ERROR, Abs_Zero_Vector: Unknown input size\n"); + + return mkexpr( result ); +} + static IRExpr * is_Denorm_Vector( IRType element_size, IRExpr *src ) { /* Check elements of a 128-bit floating point vector, with element size @@ -7782,9 +7814,9 @@ static Bool dis_int_load_ds_form_prefix ( UInt prefix, break; case 0x1: // ldu (Load DWord, Update, PPC64 p474) - /* There is no prefixed version of these instructions. */ + /* There is no prefixed version of this instructions. */ if (rA_addr == 0 || rA_addr == rT_addr) { - vex_printf("dis_int_load(ppc)(ldu,rA_addr|rT_addr)\n"); + vex_printf("dis_int_load_ds_form_prefix(ppc)(ldu,rA_addr|rT_addr)\n"); return False; } DIP("ldu r%u,%u(r%u)\n", rT_addr, immediate_val, rA_addr); @@ -24772,6 +24804,347 @@ static Bool dis_av_arith ( UInt prefix, UInt theInstr ) // TODO: set VSCR[SAT] break; + case 0x08B: // vdivuw Vector Divide Unsigned Word + case 0x18B: // vdivsw Vector Divide Signed Word + case 0x289: // vmulhuw Vector Multiply High Unsigned Word + case 0x389: // vmulhsw Vector Multiply High Signed Word + case 0x28B: // vdiveuw Vector divide Extended Unsigned Word + case 0x38B: // vdivesw Vector divide Extended Signed Word + case 0x68B: // vmoduw Vector Modulo Unsigned Word + case 0x78B: // vmodsw Vector Modulo Signed Word + { + #define MAX_ELE 4 + IROp expand_op = Iop_32Uto64; + IROp extract_res = Iop_64to32; + IROp operation = Iop_DivU64; + IRTemp srcA_tmp[MAX_ELE]; + IRTemp srcB_tmp[MAX_ELE]; + IRTemp res_tmp[MAX_ELE]; + IRTemp res_tmp2[MAX_ELE]; + IRTemp res_tmp3[MAX_ELE]; + UInt shift_by = 32; + UInt i; + IRType size_op = Ity_I64, size_res = Ity_I32; + + if (opc2 == 0x08B) { + DIP("vdivuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); + expand_op= Iop_32Uto64; + operation = Iop_DivU64; + extract_res = Iop_64to32; + + } else if (opc2 == 0x68B) { + DIP("vmoduw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); + expand_op= Iop_32Uto64; + operation = Iop_DivU64; + extract_res = Iop_64to32; + + } else if (opc2 == 0x18B) { + DIP("vdivsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); + expand_op= Iop_32Sto64; + operation = Iop_DivS64; + extract_res = Iop_64to32; + + } else if (opc2 == 0x78B) { + DIP("vmodsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); + expand_op= Iop_32Sto64; + operation = Iop_DivS64; + extract_res = Iop_64to32; + + } else if (opc2 == 0x289) { + DIP("vmulhuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); + expand_op = Iop_32Uto64; + operation = Iop_Mul64; + extract_res = Iop_64HIto32; + + } else if (opc2 == 0x389) { + DIP("vmulhsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); + expand_op= Iop_32Sto64; + operation = Iop_Mul64; + extract_res = Iop_64HIto32; + + } else if (opc2 == 0x28B) { + DIP("vdiveuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); + expand_op= Iop_32Uto64; + operation = Iop_DivU64; + extract_res = Iop_64to32; + + } else if (opc2 == 0x38B) { + DIP("vdivesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); + expand_op= Iop_32Sto64; + operation = Iop_DivS64; + extract_res = Iop_64to32; + } + + for (i=0; iIex.Binop.op) { case Iop_CmpEQ64: return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ ); case Iop_CmpNE64: return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ ); - case Iop_CmpLT64U: return mk_PPCCondCode( Pct_TRUE, Pcf_7LT ); - case Iop_CmpLE64U: return mk_PPCCondCode( Pct_FALSE, Pcf_7GT ); + case Iop_CmpLT64U: case Iop_CmpLT64S: + return mk_PPCCondCode( Pct_TRUE, Pcf_7LT ); + case Iop_CmpLE64U: case Iop_CmpLE64S: + return mk_PPCCondCode( Pct_FALSE, Pcf_7GT ); default: vpanic("iselCondCode(ppc): CmpXX64"); } } -- 2.47.3