Mark Wielaard 1a6c01
From f730da53e59ab25c5b250d7730ead57b6f72fdcf Mon Sep 17 00:00:00 2001
Mark Wielaard 1a6c01
From: Julian Seward <jseward@acm.org>
Mark Wielaard 1a6c01
Date: Sun, 23 Dec 2018 21:03:08 +0100
Mark Wielaard 1a6c01
Subject: [PATCH] Implement Iop_Sar64 in the x86 back end.
Mark Wielaard 1a6c01
Mark Wielaard 1a6c01
---
Mark Wielaard 1a6c01
 VEX/priv/host_x86_isel.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
Mark Wielaard 1a6c01
 1 file changed, 50 insertions(+)
Mark Wielaard 1a6c01
Mark Wielaard 1a6c01
diff --git a/VEX/priv/host_x86_isel.c b/VEX/priv/host_x86_isel.c
Mark Wielaard 1a6c01
index 45aafeb..9ca8a45 100644
Mark Wielaard 1a6c01
--- a/VEX/priv/host_x86_isel.c
Mark Wielaard 1a6c01
+++ b/VEX/priv/host_x86_isel.c
Mark Wielaard 1a6c01
@@ -2380,6 +2380,56 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env,
Mark Wielaard 1a6c01
             return;
Mark Wielaard 1a6c01
          }
Mark Wielaard 1a6c01
 
Mark Wielaard 1a6c01
+         case Iop_Sar64: {
Mark Wielaard 1a6c01
+            /* gcc -O2 does the following.  I don't know how it works, but it
Mark Wielaard 1a6c01
+               does work.  Don't mess with it.  This is hard to test because the
Mark Wielaard 1a6c01
+               x86 front end doesn't create Iop_Sar64 for any x86 instruction,
Mark Wielaard 1a6c01
+               so it's impossible to write a test program that feeds values
Mark Wielaard 1a6c01
+               through Iop_Sar64 and prints their results.  The implementation
Mark Wielaard 1a6c01
+               here was tested by using psrlq on mmx registers -- that generates
Mark Wielaard 1a6c01
+               Iop_Shr64 -- and temporarily hacking the front end to generate
Mark Wielaard 1a6c01
+               Iop_Sar64 for that instruction instead.
Mark Wielaard 1a6c01
+
Mark Wielaard 1a6c01
+               movl  %amount, %ecx
Mark Wielaard 1a6c01
+               movl  %srcHi,  %r1
Mark Wielaard 1a6c01
+               movl  %srcLo,  %r2
Mark Wielaard 1a6c01
+
Mark Wielaard 1a6c01
+               movl   %r1, %r3
Mark Wielaard 1a6c01
+               sarl   %cl, %r3
Mark Wielaard 1a6c01
+               movl   %r2, %r4
Mark Wielaard 1a6c01
+               shrdl  %cl, %r1, %r4
Mark Wielaard 1a6c01
+               movl   %r3, %r2
Mark Wielaard 1a6c01
+               sarl   $31, %r2
Mark Wielaard 1a6c01
+               andl   $32, %ecx
Mark Wielaard 1a6c01
+               cmovne %r3, %r4   // = resLo
Mark Wielaard 1a6c01
+               cmovne %r2, %r3   // = resHi
Mark Wielaard 1a6c01
+            */
Mark Wielaard 1a6c01
+            HReg amount = iselIntExpr_R(env, e->Iex.Binop.arg2);
Mark Wielaard 1a6c01
+            HReg srcHi = INVALID_HREG, srcLo = INVALID_HREG;
Mark Wielaard 1a6c01
+            iselInt64Expr(&srcHi, &srcLo, env, e->Iex.Binop.arg1);
Mark Wielaard 1a6c01
+            HReg r1 = newVRegI(env);
Mark Wielaard 1a6c01
+            HReg r2 = newVRegI(env);
Mark Wielaard 1a6c01
+            HReg r3 = newVRegI(env);
Mark Wielaard 1a6c01
+            HReg r4 = newVRegI(env);
Mark Wielaard 1a6c01
+            addInstr(env, mk_iMOVsd_RR(amount, hregX86_ECX()));
Mark Wielaard 1a6c01
+            addInstr(env, mk_iMOVsd_RR(srcHi, r1));
Mark Wielaard 1a6c01
+            addInstr(env, mk_iMOVsd_RR(srcLo, r2));
Mark Wielaard 1a6c01
+
Mark Wielaard 1a6c01
+            addInstr(env, mk_iMOVsd_RR(r1, r3));
Mark Wielaard 1a6c01
+            addInstr(env, X86Instr_Sh32(Xsh_SAR, 0/*%cl*/, r3));
Mark Wielaard 1a6c01
+            addInstr(env, mk_iMOVsd_RR(r2, r4));
Mark Wielaard 1a6c01
+            addInstr(env, X86Instr_Sh3232(Xsh_SHR, 0/*%cl*/, r1, r4));
Mark Wielaard 1a6c01
+            addInstr(env, mk_iMOVsd_RR(r3, r2));
Mark Wielaard 1a6c01
+            addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, r2));
Mark Wielaard 1a6c01
+            addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(32),
Mark Wielaard 1a6c01
+                                                    hregX86_ECX()));
Mark Wielaard 1a6c01
+            addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(r3), r4));
Mark Wielaard 1a6c01
+            addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(r2), r3));
Mark Wielaard 1a6c01
+            *rHi = r3;
Mark Wielaard 1a6c01
+            *rLo = r4;
Mark Wielaard 1a6c01
+            return;
Mark Wielaard 1a6c01
+         }
Mark Wielaard 1a6c01
+
Mark Wielaard 1a6c01
          /* F64 -> I64 */
Mark Wielaard 1a6c01
          /* Sigh, this is an almost exact copy of the F64 -> I32/I16
Mark Wielaard 1a6c01
             case.  Unfortunately I see no easy way to avoid the
Mark Wielaard 1a6c01
-- 
Mark Wielaard 1a6c01
1.8.3.1
Mark Wielaard 1a6c01