From ad0d7e3b552932c0552aecbda4c6440cbba91aa5 Mon Sep 17 00:00:00 2001
From: Per Hedbor <ph@opera.com>
Date: Thu, 28 Aug 2014 21:21:09 +0200
Subject: [PATCH] Added F_AND, F_OR and F_RSH opcodes

---
 src/code/amd64.c | 113 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 110 insertions(+), 3 deletions(-)

diff --git a/src/code/amd64.c b/src/code/amd64.c
index 71368ed8fc..ca2843d00b 100644
--- a/src/code/amd64.c
+++ b/src/code/amd64.c
@@ -251,6 +251,20 @@ static void xor_reg_reg( enum amd64_reg reg1,  enum amd64_reg reg2 )
   modrm(3,reg1,reg2);
 }
 
+static void and_reg_reg( enum amd64_reg reg1,  enum amd64_reg reg2 )
+{
+  rex(1,reg1,0,reg2);
+  opcode( 0x23 );
+  modrm(3,reg1,reg2);
+}
+
+static void or_reg_reg( enum amd64_reg reg1,  enum amd64_reg reg2 )
+{
+  rex(1,reg1,0,reg2);
+  opcode( 0x09 );
+  modrm(3,reg1,reg2);
+}
+
 static void and_reg_imm( enum amd64_reg reg, int imm32 )
 {
   rex( 1, 0, 0, reg );
@@ -386,6 +400,17 @@ static void shl_reg_mem( enum amd64_reg reg, enum amd64_reg mem, int offset)
 }
 #endif
 
+static void shr_mem_reg( enum amd64_reg reg, int off, enum amd64_reg sreg)
+{
+  if( sreg != P_REG_RCX )
+    Pike_fatal("Not supported\n");
+
+  rex( 1, 0, 0, reg );
+  opcode( 0xd3 ); /* SAR r/m64,CL */
+  offset_modrm_sib(off, 7, reg );
+/*   modrm( 3, 7, reg ); */
+}
+
 static void shr_reg_imm( enum amd64_reg from_reg, int shift )
 {
   rex( 1, from_reg, 0, 0 );
@@ -815,6 +840,14 @@ static void add_reg_reg( enum amd64_reg reg, enum amd64_reg reg2 )
   modrm( 3, reg2, reg );
 }
 
+/* reg += reg2 */
+static void add_reg32_reg32( enum amd64_reg reg, enum amd64_reg reg2 )
+{
+  rex(0,reg2,0,reg);
+  opcode( 0x1 );
+  modrm( 3, reg2, reg );
+}
+
 /* reg -= reg2 */
 static void sub_reg_reg( enum amd64_reg reg, enum amd64_reg reg2 )
 {
@@ -1779,7 +1812,81 @@ void ins_f_byte(unsigned int b)
      LABEL_B;
    }
    return;
-   return;
+  case F_AND:
+    {
+    LABELS();
+    ins_debug_instr_prologue(b, 0, 0);
+    amd64_load_sp_reg();
+    mov_mem8_reg(sp_reg, SVAL(-1).type, P_REG_RAX );
+    mov_mem8_reg(sp_reg, SVAL(-2).type, P_REG_RBX );
+    add_reg_reg(P_REG_RAX,P_REG_RBX);
+    /*    test_reg(P_REG_RAX); int == 0 */
+    jnz(&label_A);
+    
+    mov_mem_reg(sp_reg, SVAL(-1).value, P_REG_RAX );
+    mov_mem_reg(sp_reg, SVAL(-2).value, P_REG_RBX );
+    and_reg_reg(P_REG_RBX,P_REG_RAX);
+    mov_reg_mem(P_REG_RBX,sp_reg,SVAL(-2).value);
+    amd64_add_sp(-1);
+    jmp(&label_B);
+   LABEL_A;
+    amd64_call_c_opcode(addr, flags);
+    amd64_load_sp_reg();
+   LABEL_B;
+    }
+    return;
+
+  case F_OR:
+    {
+    LABELS();
+    ins_debug_instr_prologue(b, 0, 0);
+    amd64_load_sp_reg();
+    mov_mem8_reg(sp_reg, SVAL(-1).type, P_REG_RAX );
+    mov_mem8_reg(sp_reg, SVAL(-2).type, P_REG_RBX );
+    add_reg32_reg32(P_REG_RAX,P_REG_RBX);
+    /*    test_reg(P_REG_RAX); int == 0 */
+    jnz(&label_A);
+    
+    mov_mem_reg(sp_reg, SVAL(-1).value, P_REG_RAX );
+    mov_mem_reg(sp_reg, SVAL(-2).value, P_REG_RBX );
+    or_reg_reg(P_REG_RAX,P_REG_RBX);
+    mov_reg_mem(P_REG_RBX,sp_reg,SVAL(-2).value);
+    amd64_add_sp(-1);
+    jmp(&label_B);
+   LABEL_A;
+    amd64_call_c_opcode(addr, flags);
+    amd64_load_sp_reg();
+   LABEL_B;
+    }
+    return;
+
+  case F_RSH:
+    {
+    LABELS();
+    ins_debug_instr_prologue(b, 0, 0);
+    amd64_load_sp_reg();
+    mov_mem8_reg(sp_reg, -1*sizeof(struct svalue), P_REG_RAX );
+    mov_mem8_reg(sp_reg, -2*sizeof(struct svalue), P_REG_RBX );
+    add_reg32_reg32(P_REG_RAX,P_REG_RBX);
+    /* test_reg(P_REG_RAX);  int == 0 */
+    jnz(&label_A);
+
+    mov_mem_reg(sp_reg, SVAL(-1).value, P_REG_RCX );
+    cmp_reg_imm(P_REG_RCX,0);
+    jl( &label_A );
+    amd64_add_sp(-1);
+    cmp_reg_imm(P_REG_RCX,63);
+    jle( &label_B );
+    mov_imm_reg(P_REG_RCX,63);
+  LABEL_B;
+    shr_mem_reg(sp_reg,SVAL(-1).value, P_REG_RCX);
+    jmp(&label_C);
+  LABEL_A;
+    amd64_call_c_opcode(addr, flags);
+    amd64_load_sp_reg();
+  LABEL_C;
+    }
+    return;
   case F_ADD_INTS:
     {
       ins_debug_instr_prologue(b, 0, 0);
@@ -2049,8 +2156,8 @@ void ins_f_byte(unsigned int b)
     amd64_load_sp_reg();
     mov_mem8_reg(sp_reg, -1*sizeof(struct svalue), P_REG_RAX );
     mov_mem8_reg(sp_reg, -2*sizeof(struct svalue), P_REG_RBX );
-    add_reg_reg(P_REG_RAX,P_REG_RBX);
-    test_reg32(P_REG_RAX); /* int == 0 */
+    add_reg32_reg32(P_REG_RAX,P_REG_RBX);
+    /* test_reg32(P_REG_RAX);  int == 0 */
     jnz(&label_A);
 
 #ifdef PIKE_DEBUG
-- 
GitLab