sse: Fix mulhsl rule
authorDavid Schleef <ds@schleef.org>
Thu, 12 May 2011 17:23:11 +0000 (10:23 -0700)
committerDavid Schleef <ds@schleef.org>
Thu, 12 May 2011 18:27:47 +0000 (11:27 -0700)
orc/orcrules-sse.c
orc/orcx86.h
orc/orcx86insn.c

index 9538ee6..4dff729 100644 (file)
@@ -1582,8 +1582,8 @@ sse_rule_mulhsl_slow (OrcCompiler *p, void *user, OrcInstruction *insn)
 
   for(i=0;i<(1<<p->insn_shift);i++) {
     orc_x86_emit_mov_memoffset_reg (p, 4, offset + 4*i, p->exec_reg, X86_EAX);
-    orc_x86_emit_cpuinsn_load_memoffset (p, ORC_X86_imul_rm, 4, 0,
-        offset + 16 + 4*i, p->exec_reg, -1);
+    orc_x86_emit_cpuinsn_memoffset (p, ORC_X86_imul_rm, 4,
+        offset + 16 + 4*i, p->exec_reg);
     orc_x86_emit_mov_reg_memoffset (p, 4, X86_EDX, offset + 4*i, p->exec_reg);
   }
 
@@ -1628,6 +1628,38 @@ sse_rule_mulslq (OrcCompiler *p, void *user, OrcInstruction *insn)
 
 #ifndef MMX
 static void
+sse_rule_mulslq_slow (OrcCompiler *p, void *user, OrcInstruction *insn)
+{
+  int i;
+  int regsize = p->is_64bit ? 8 : 4;
+  int offset = ORC_STRUCT_OFFSET(OrcExecutor,arrays[ORC_VAR_T1]);
+
+  orc_x86_emit_mov_sse_memoffset (p, 8, p->vars[insn->src_args[0]].alloc,
+      offset, p->exec_reg, FALSE, FALSE);
+  orc_x86_emit_mov_sse_memoffset (p, 8, p->vars[insn->src_args[1]].alloc,
+      offset + 8, p->exec_reg, FALSE, FALSE);
+  orc_x86_emit_mov_reg_memoffset (p, regsize, X86_EAX, offset + 32,
+      p->exec_reg);
+  orc_x86_emit_mov_reg_memoffset (p, regsize, X86_EDX, offset + 40,
+      p->exec_reg);
+
+  for(i=0;i<(1<<p->insn_shift);i++) {
+    orc_x86_emit_mov_memoffset_reg (p, 4, offset + 4*i, p->exec_reg, X86_EAX);
+    orc_x86_emit_cpuinsn_memoffset (p, ORC_X86_imul_rm, 4,
+        offset + 8 + 4*i, p->exec_reg);
+    orc_x86_emit_mov_reg_memoffset (p, 4, X86_EAX, offset + 16 + 8*i, p->exec_reg);
+    orc_x86_emit_mov_reg_memoffset (p, 4, X86_EDX, offset + 16 + 8*i + 4, p->exec_reg);
+  }
+
+  orc_x86_emit_mov_memoffset_sse (p, 16, offset + 16, p->exec_reg,
+      p->vars[insn->dest_args[0]].alloc, FALSE);
+  orc_x86_emit_mov_memoffset_reg (p, 8, offset + 32, p->exec_reg, X86_EAX);
+  orc_x86_emit_mov_memoffset_reg (p, 8, offset + 40, p->exec_reg, X86_EDX);
+}
+#endif
+
+#ifndef MMX
+static void
 sse_rule_mululq (OrcCompiler *p, void *user, OrcInstruction *insn)
 {
   int src = p->vars[insn->src_args[1]].alloc;
@@ -2889,6 +2921,7 @@ orc_compiler_sse_register_rules (OrcTarget *target)
 #ifndef MMX
   orc_rule_register (rule_set, "mulhsl", sse_rule_mulhsl_slow, NULL);
   orc_rule_register (rule_set, "mulhul", sse_rule_mulhul, NULL);
+  orc_rule_register (rule_set, "mulslq", sse_rule_mulslq_slow, NULL);
 #endif
   orc_rule_register (rule_set, "mullb", sse_rule_mullb, NULL);
   orc_rule_register (rule_set, "mulhsb", sse_rule_mulhsb, NULL);
index 57b1ead..c29344f 100644 (file)
@@ -174,6 +174,8 @@ void orc_x86_emit_cpuinsn_reg_memoffset (OrcCompiler *p, int index, int src,
     int offset, int dest);
 void orc_x86_emit_cpuinsn_memoffset_reg (OrcCompiler *p, int index, int size,
     int offset, int src, int dest);
+void orc_x86_emit_cpuinsn_memoffset (OrcCompiler *p, int index, int size,
+    int offset, int srcdest);
 void orc_x86_emit_cpuinsn_branch (OrcCompiler *p, int index, int label);
 void orc_x86_emit_cpuinsn_label (OrcCompiler *p, int index, int label, int align_shift);
 void orc_x86_emit_cpuinsn_none (OrcCompiler *p, int index);
index 29d515c..2d129c6 100644 (file)
@@ -240,7 +240,7 @@ static const OrcSysOpcode orc_x86_opcodes[] = {
   { "leal", ORC_X86_INSN_TYPE_REGM_REG, 0, 0x00, 0x8d },
   { "leaq", ORC_X86_INSN_TYPE_REGM_REG, 0, 0x00, 0x8d },
   { "imul", ORC_X86_INSN_TYPE_REGM_REG, 0, 0x00, 0x0faf },
-  { "imul", ORC_X86_INSN_TYPE_REGM, 0, 0x00, 0xf7, 5 },
+  { "imull", ORC_X86_INSN_TYPE_REGM, 0, 0x00, 0xf7, 5 },
   { "incl", ORC_X86_INSN_TYPE_REGM, 0, 0x00, 0xff, 0 },
   { "decl", ORC_X86_INSN_TYPE_REGM, 0, 0x00, 0xff, 1 },
   { "sar", ORC_X86_INSN_TYPE_IMM8_REGM, 0, 0x00, 0xc1, 7 },
@@ -915,3 +915,19 @@ orc_x86_emit_cpuinsn_none (OrcCompiler *p, int index)
   xinsn->size = size;
 }
 
+void
+orc_x86_emit_cpuinsn_memoffset (OrcCompiler *p, int index, int size,
+    int offset, int srcdest)
+{
+  OrcX86Insn *xinsn = orc_x86_get_output_insn (p);
+  const OrcSysOpcode *opcode = orc_x86_opcodes + index;
+
+  xinsn->opcode_index = index;
+  xinsn->opcode = opcode;
+  xinsn->src = srcdest;
+  xinsn->dest = srcdest;
+  xinsn->type = ORC_X86_RM_MEMOFFSET;
+  xinsn->offset = offset;
+  xinsn->size = size;
+}
+