Fixed x86 division and modulus and merged their entry points.

Also enabled compilation of fill-array-data instructions in x86
(untested), and improved x86 disassembly.

Change-Id: Ia3d8d0766080d01f1c228f9283085024cadd528b
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index d3ab039..e2b8282 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -582,20 +582,18 @@
         int rIdx = oatAllocTemp(cUnit);
 #if defined(TARGET_ARM)
         int rVal = rLR;  // Using a lot of temps, rLR is known free here
+#elif defined(TARGET_X86)
+        int rVal = rSrc;
 #else
         int rVal = oatAllocTemp(cUnit);
 #endif
         // Set up source pointer
         RegLocation rlFirst = oatGetSrc(cUnit, mir, 0);
-#if defined(TARGET_X86)
-        UNIMPLEMENTED(FATAL);
-#else
         opRegRegImm(cUnit, kOpAdd, rSrc, rSP,
                     oatSRegOffset(cUnit, rlFirst.sRegLow));
         // Set up the target pointer
         opRegRegImm(cUnit, kOpAdd, rDst, rRET0,
                     Array::DataOffset(component_size).Int32Value());
-#endif
         // Set up the loop counter (known to be > 0)
         loadConstant(cUnit, rIdx, dInsn->vA - 1);
         // Generate the copy loop.  Going backwards for convenience
@@ -1782,7 +1780,7 @@
             checkZero = true;
             op = kOpDiv;
             callOut = true;
-            funcOffset = ENTRYPOINT_OFFSET(pIdiv);
+            funcOffset = ENTRYPOINT_OFFSET(pIdivmod);
             retReg = rRET0;
             break;
         /* NOTE: returns in rARG1 */
@@ -2117,12 +2115,11 @@
             oatFlushAllRegs(cUnit);   /* Everything to home location */
             loadValueDirectFixed(cUnit, rlSrc, rARG0);
             oatClobber(cUnit, rARG0);
+            funcOffset = ENTRYPOINT_OFFSET(pIdivmod);
             if ((dalvikOpcode == Instruction::DIV_INT_LIT8) ||
                 (dalvikOpcode == Instruction::DIV_INT_LIT16)) {
-                funcOffset = ENTRYPOINT_OFFSET(pIdiv);
                 isDiv = true;
             } else {
-                funcOffset = ENTRYPOINT_OFFSET(pIdivmod);
                 isDiv = false;
             }
             callRuntimeHelperRegImm(cUnit, funcOffset, rARG0, lit);
diff --git a/src/disassembler_x86.cc b/src/disassembler_x86.cc
index d2c860b..dc12ef7 100644
--- a/src/disassembler_x86.cc
+++ b/src/disassembler_x86.cc
@@ -406,6 +406,14 @@
   case 0xE8: opcode << "call"; branch_bytes = 4; break;
   case 0xE9: opcode << "jmp"; branch_bytes = 4; break;
   case 0xEB: opcode << "jmp"; branch_bytes = 1; break;
+  case 0xF6: case 0xF7:
+    static const char* f7_opcodes[] = {"test", "unknown-f7", "not", "neg", "mul edx:eax, eax *", "imul edx:eax, eax *", "div edx:eax, edx:eax /", "idiv edx:eax, edx:eax /"};
+    modrm_opcodes = f7_opcodes;
+    has_modrm = true;
+    reg_is_opcode = true;
+    store = true;
+    immediate_bytes = ((instr[1] & 0x38) == 0) ? 1 : 0;
+    break;
   case 0xFF:
     static const char* ff_opcodes[] = {"inc", "dec", "call", "call", "jmp", "jmp", "push", "unknown-ff"};
     modrm_opcodes = ff_opcodes;
diff --git a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
index f8a071f..be390e9 100644
--- a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
+++ b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
@@ -99,8 +99,7 @@
 extern "C" double fmod(double a, double b);         // REM_DOUBLE[_2ADDR]
 
 // Integer arithmetics.
-extern "C" int __aeabi_idivmod(int32_t op1, int32_t op2);  // REM_INT[_2ADDR|_LIT8|_LIT16]
-extern "C" int __aeabi_idiv(int32_t op1, int32_t op2);     // DIV_INT[_2ADDR|_LIT8|_LIT16]
+extern "C" int __aeabi_idivmod(int32_t op1, int32_t op2);  // [DIV|REM]_INT[_2ADDR|_LIT8|_LIT16]
 
 // Long long arithmetics - REM_LONG[_2ADDR] and DIV_LONG[_2ADDR]
 extern "C" long long __aeabi_ldivmod(long long op1, long long op2);
@@ -214,7 +213,6 @@
   points->pL2f = __aeabi_l2f;
   points->pD2iz = __aeabi_d2iz;
   points->pF2iz = __aeabi_f2iz;
-  points->pIdiv = __aeabi_idivmod;
   points->pIdivmod = __aeabi_idivmod;
   points->pD2l = D2L;
   points->pF2l = F2L;
diff --git a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
index a5cdc33..d791632 100644
--- a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
+++ b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
@@ -212,7 +212,6 @@
   points->pL2f = __floatdisf;
   points->pD2iz = __fixdfsi;
   points->pF2iz = __fixsfi;
-  points->pIdiv = NULL;
   points->pIdivmod = NULL;
   points->pD2l = D2L;
   points->pF2l = F2L;
diff --git a/src/oat/runtime/oat_support_entrypoints.h b/src/oat/runtime/oat_support_entrypoints.h
index af7fee3..b585255 100644
--- a/src/oat/runtime/oat_support_entrypoints.h
+++ b/src/oat/runtime/oat_support_entrypoints.h
@@ -101,7 +101,6 @@
   float (*pL2f)(int64_t);
   int32_t (*pD2iz)(double);
   int32_t (*pF2iz)(float);
-  int32_t (*pIdiv)(int32_t, int32_t);
   int32_t (*pIdivmod)(int32_t, int32_t);
   int64_t (*pD2l)(double);
   int64_t (*pF2l)(float);
diff --git a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
index 7ded2d1..8a68858 100644
--- a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
+++ b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
@@ -72,7 +72,6 @@
 extern int32_t CmpgFloat(float a, float b);
 extern int32_t CmplFloat(float a, float b);
 extern int64_t Lmul(int64_t a, int64_t b);
-extern "C" int32_t art_idiv_from_code(int32_t, int32_t);
 extern "C" int32_t art_idivmod_from_code(int32_t, int32_t);
 extern "C" int64_t art_ldiv_from_code(int64_t, int64_t);
 extern "C" int64_t art_ldivmod_from_code(int64_t, int64_t);
@@ -182,7 +181,6 @@
   //points->pL2f = NULL;
   points->pD2iz = D2I;
   points->pF2iz = F2I;
-  points->pIdiv = art_idiv_from_code;
   points->pIdivmod = art_idivmod_from_code;
   points->pD2l = D2L;
   points->pF2l = F2L;
diff --git a/src/oat/runtime/x86/runtime_support_x86.S b/src/oat/runtime/x86/runtime_support_x86.S
index d529f31..109321e 100644
--- a/src/oat/runtime/x86/runtime_support_x86.S
+++ b/src/oat/runtime/x86/runtime_support_x86.S
@@ -395,16 +395,18 @@
 
 NO_ARG_DOWNCALL art_test_suspend, artTestSuspendFromCode, ret
 
-DEFINE_FUNCTION art_idiv_from_code
-    cdq         // edx:eax = sign extend eax
-    idiv %ecx   // (edx,eax) = (edx:eax % ecx, edx:eax / ecx)
-    ret
-
 DEFINE_FUNCTION art_idivmod_from_code
+    cmpl LITERAL(0x80000000), %eax
+    je check_arg2  // special case
+args_ok:
     cdq         // edx:eax = sign extend eax
     idiv %ecx   // (edx,eax) = (edx:eax % ecx, edx:eax / ecx)
-    movl %eax, %edx
     ret
+check_arg2:
+    cmpl LITERAL(-1), %ecx
+    jne args_ok
+    xorl %edx, %edx
+    ret         // eax already holds min int
 
 DEFINE_FUNCTION art_ldiv_from_code
     subl LITERAL(12), %esp        // alignment padding
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 5bcb927..94941c4 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -201,7 +201,6 @@
     DUMP_ENTRY_POINT(pL2f);
     DUMP_ENTRY_POINT(pD2iz);
     DUMP_ENTRY_POINT(pF2iz);
-    DUMP_ENTRY_POINT(pIdiv);
     DUMP_ENTRY_POINT(pIdivmod);
     DUMP_ENTRY_POINT(pD2l);
     DUMP_ENTRY_POINT(pF2l);
diff --git a/src/thread.cc b/src/thread.cc
index 04c5105..5eeb730 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -1620,7 +1620,6 @@
   DO_THREAD_ENTRY_POINT_OFFSET(pL2f)
   DO_THREAD_ENTRY_POINT_OFFSET(pD2iz)
   DO_THREAD_ENTRY_POINT_OFFSET(pF2iz)
-  DO_THREAD_ENTRY_POINT_OFFSET(pIdiv)
   DO_THREAD_ENTRY_POINT_OFFSET(pIdivmod)
   DO_THREAD_ENTRY_POINT_OFFSET(pD2l)
   DO_THREAD_ENTRY_POINT_OFFSET(pF2l)