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)