diff options
-rw-r--r-- | compiler/dex/quick/arm/codegen_arm.h | 3 | ||||
-rw-r--r-- | compiler/dex/quick/arm/int_arm.cc | 11 | ||||
-rw-r--r-- | compiler/dex/quick/gen_common.cc | 6 | ||||
-rw-r--r-- | compiler/dex/quick/mips/codegen_mips.h | 3 | ||||
-rw-r--r-- | compiler/dex/quick/mips/int_mips.cc | 11 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.h | 19 | ||||
-rw-r--r-- | compiler/dex/quick/x86/assemble_x86.cc | 9 | ||||
-rw-r--r-- | compiler/dex/quick/x86/codegen_x86.h | 28 | ||||
-rw-r--r-- | compiler/dex/quick/x86/int_x86.cc | 243 | ||||
-rw-r--r-- | compiler/dex/quick/x86/x86_lir.h | 1 | ||||
-rw-r--r-- | disassembler/disassembler_x86.cc | 3 |
11 files changed, 333 insertions, 4 deletions
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h index bf85d9163e..10cff38872 100644 --- a/compiler/dex/quick/arm/codegen_arm.h +++ b/compiler/dex/quick/arm/codegen_arm.h @@ -195,6 +195,9 @@ class ArmMir2Lir : public Mir2Lir { void ReplaceFixup(LIR* prev_lir, LIR* orig_lir, LIR* new_lir); void InsertFixupBefore(LIR* prev_lir, LIR* orig_lir, LIR* new_lir); void AssignDataOffsets(); + RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2, bool is_div, bool check_zero); + RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div); }; } // namespace art diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc index e02382bbc5..71c3492db4 100644 --- a/compiler/dex/quick/arm/int_arm.cc +++ b/compiler/dex/quick/arm/int_arm.cc @@ -444,6 +444,17 @@ LIR* ArmMir2Lir::GenRegMemCheck(ConditionCode c_code, return NULL; } +RegLocation ArmMir2Lir::GenDivRem(RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2, bool is_div, bool check_zero) { + LOG(FATAL) << "Unexpected use of GenDivRem for Arm"; + return rl_dest; +} + +RegLocation ArmMir2Lir::GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div) { + LOG(FATAL) << "Unexpected use of GenDivRemLit for Arm"; + return rl_dest; +} + RegLocation ArmMir2Lir::GenDivRemLit(RegLocation rl_dest, int reg1, int lit, bool is_div) { RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc index f2807c6209..1f00b2a6a5 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -1382,6 +1382,9 @@ void Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest, } rl_result = GenDivRem(rl_dest, rl_src1.low_reg, rl_src2.low_reg, op == kOpDiv); done = true; + } else if (cu_->instruction_set == kX86) { + rl_result = GenDivRem(rl_dest, rl_src1, rl_src2, op == kOpDiv, check_zero); + done = true; } else if (cu_->instruction_set == kThumb2) { if (cu_->GetInstructionSetFeatures().HasDivideInstruction()) { // Use ARM SDIV instruction for division. For remainder we also need to @@ -1650,6 +1653,9 @@ void Mir2Lir::GenArithOpIntLit(Instruction::Code opcode, RegLocation rl_dest, Re rl_src = LoadValue(rl_src, kCoreReg); rl_result = GenDivRemLit(rl_dest, rl_src.low_reg, lit, is_div); done = true; + } else if (cu_->instruction_set == kX86) { + rl_result = GenDivRemLit(rl_dest, rl_src, lit, is_div); + done = true; } else if (cu_->instruction_set == kThumb2) { if (cu_->GetInstructionSetFeatures().HasDivideInstruction()) { // Use ARM SDIV instruction for division. For remainder we also need to diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h index 1f99e10f31..aca93f51d3 100644 --- a/compiler/dex/quick/mips/codegen_mips.h +++ b/compiler/dex/quick/mips/codegen_mips.h @@ -175,6 +175,9 @@ class MipsMir2Lir : public Mir2Lir { private: void ConvertShortToLongBranch(LIR* lir); + RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2, bool is_div, bool check_zero); + RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div); }; } // namespace art diff --git a/compiler/dex/quick/mips/int_mips.cc b/compiler/dex/quick/mips/int_mips.cc index 3410ecb398..013041a9a5 100644 --- a/compiler/dex/quick/mips/int_mips.cc +++ b/compiler/dex/quick/mips/int_mips.cc @@ -250,6 +250,17 @@ RegLocation MipsMir2Lir::GenDivRemLit(RegLocation rl_dest, int reg1, int lit, return rl_result; } +RegLocation MipsMir2Lir::GenDivRem(RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2, bool is_div, bool check_zero) { + LOG(FATAL) << "Unexpected use of GenDivRem for Mips"; + return rl_dest; +} + +RegLocation MipsMir2Lir::GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div) { + LOG(FATAL) << "Unexpected use of GenDivRemLit for Mips"; + return rl_dest; +} + void MipsMir2Lir::OpLea(int rBase, int reg1, int reg2, int scale, int offset) { LOG(FATAL) << "Unexpected use of OpLea for Arm"; } diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index c6c500060d..b59ec5ef5e 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -758,6 +758,25 @@ class Mir2Lir : public Backend { bool is_div) = 0; virtual RegLocation GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit, bool is_div) = 0; + /* + * @brief Generate an integer div or rem operation by a literal. + * @param rl_dest Destination Location. + * @param rl_src1 Numerator Location. + * @param rl_src2 Divisor Location. + * @param is_div 'true' if this is a division, 'false' for a remainder. + * @param check_zero 'true' if an exception should be generated if the divisor is 0. + */ + virtual RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2, bool is_div, bool check_zero) = 0; + /* + * @brief Generate an integer div or rem operation by a literal. + * @param rl_dest Destination Location. + * @param rl_src Numerator Location. + * @param lit Divisor. + * @param is_div 'true' if this is a division, 'false' for a remainder. + */ + virtual RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, + int lit, bool is_div) = 0; virtual void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) = 0; diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc index 1dcff652ba..5e1c4d1e9f 100644 --- a/compiler/dex/quick/x86/assemble_x86.cc +++ b/compiler/dex/quick/x86/assemble_x86.cc @@ -242,12 +242,13 @@ ENCODING_MAP(Cmp, IS_LOAD, 0, 0, UNARY_ENCODING_MAP(Not, 0x2, IS_STORE, 0, R, kReg, IS_UNARY_OP | REG_DEF0_USE0, M, kMem, IS_BINARY_OP | REG_USE0, A, kArray, IS_QUAD_OP | REG_USE01, 0, 0, 0, 0, "", "", ""), UNARY_ENCODING_MAP(Neg, 0x3, IS_STORE, SETS_CCODES, R, kReg, IS_UNARY_OP | REG_DEF0_USE0, M, kMem, IS_BINARY_OP | REG_USE0, A, kArray, IS_QUAD_OP | REG_USE01, 0, 0, 0, 0, "", "", ""), - UNARY_ENCODING_MAP(Mul, 0x4, 0, SETS_CCODES, DaR, kRegRegReg, IS_UNARY_OP | REG_USE0, DaM, kRegRegMem, IS_BINARY_OP | REG_USE0, DaA, kRegRegArray, IS_QUAD_OP | REG_USE01, 0, REG_DEFA_USEA, REG_DEFAD_USEA, REG_DEFAD_USEA, "ax,al,", "dx:ax,ax,", "edx:eax,eax,"), - UNARY_ENCODING_MAP(Imul, 0x5, 0, SETS_CCODES, DaR, kRegRegReg, IS_UNARY_OP | REG_USE0, DaM, kRegRegMem, IS_BINARY_OP | REG_USE0, DaA, kRegRegArray, IS_QUAD_OP | REG_USE01, 0, REG_DEFA_USEA, REG_DEFAD_USEA, REG_DEFAD_USEA, "ax,al,", "dx:ax,ax,", "edx:eax,eax,"), - UNARY_ENCODING_MAP(Divmod, 0x6, 0, SETS_CCODES, DaR, kRegRegReg, IS_UNARY_OP | REG_USE0, DaM, kRegRegMem, IS_BINARY_OP | REG_USE0, DaA, kRegRegArray, IS_QUAD_OP | REG_USE01, 0, REG_DEFA_USEA, REG_DEFAD_USEAD, REG_DEFAD_USEAD, "ah:al,ax,", "dx:ax,dx:ax,", "edx:eax,edx:eax,"), - UNARY_ENCODING_MAP(Idivmod, 0x7, 0, SETS_CCODES, DaR, kRegRegReg, IS_UNARY_OP | REG_USE0, DaM, kRegRegMem, IS_BINARY_OP | REG_USE0, DaA, kRegRegArray, IS_QUAD_OP | REG_USE01, 0, REG_DEFA_USEA, REG_DEFAD_USEAD, REG_DEFAD_USEAD, "ah:al,ax,", "dx:ax,dx:ax,", "edx:eax,edx:eax,"), + UNARY_ENCODING_MAP(Mul, 0x4, 0, SETS_CCODES, DaR, kReg, IS_UNARY_OP | REG_USE0, DaM, kMem, IS_BINARY_OP | REG_USE0, DaA, kArray, IS_QUAD_OP | REG_USE01, 0, REG_DEFA_USEA, REG_DEFAD_USEA, REG_DEFAD_USEA, "ax,al,", "dx:ax,ax,", "edx:eax,eax,"), + UNARY_ENCODING_MAP(Imul, 0x5, 0, SETS_CCODES, DaR, kReg, IS_UNARY_OP | REG_USE0, DaM, kMem, IS_BINARY_OP | REG_USE0, DaA, kArray, IS_QUAD_OP | REG_USE01, 0, REG_DEFA_USEA, REG_DEFAD_USEA, REG_DEFAD_USEA, "ax,al,", "dx:ax,ax,", "edx:eax,eax,"), + UNARY_ENCODING_MAP(Divmod, 0x6, 0, SETS_CCODES, DaR, kReg, IS_UNARY_OP | REG_USE0, DaM, kMem, IS_BINARY_OP | REG_USE0, DaA, kArray, IS_QUAD_OP | REG_USE01, 0, REG_DEFA_USEA, REG_DEFAD_USEAD, REG_DEFAD_USEAD, "ah:al,ax,", "dx:ax,dx:ax,", "edx:eax,edx:eax,"), + UNARY_ENCODING_MAP(Idivmod, 0x7, 0, SETS_CCODES, DaR, kReg, IS_UNARY_OP | REG_USE0, DaM, kMem, IS_BINARY_OP | REG_USE0, DaA, kArray, IS_QUAD_OP | REG_USE01, 0, REG_DEFA_USEA, REG_DEFAD_USEAD, REG_DEFAD_USEAD, "ah:al,ax,", "dx:ax,dx:ax,", "edx:eax,edx:eax,"), #undef UNARY_ENCODING_MAP + { kx86Cdq32Da, kRegOpcode, NO_OPERAND | REG_DEFAD_USEA, { 0, 0, 0x99, 0, 0, 0, 0, 0 }, "Cdq", "" }, { kX86Bswap32R, kRegOpcode, IS_UNARY_OP | REG_DEF0_USE0, { 0, 0, 0x0F, 0xC8, 0, 0, 0, 0 }, "Bswap32R", "!0r" }, { kX86Push32R, kRegOpcode, IS_UNARY_OP | REG_USE0 | REG_USE_SP | REG_DEF_SP | IS_STORE, { 0, 0, 0x50, 0, 0, 0, 0, 0 }, "Push32R", "!0r" }, { kX86Pop32R, kRegOpcode, IS_UNARY_OP | REG_DEF0 | REG_USE_SP | REG_DEF_SP | IS_LOAD, { 0, 0, 0x58, 0, 0, 0, 0, 0 }, "Pop32R", "!0r" }, diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h index 53e82c3196..9cc4efd113 100644 --- a/compiler/dex/quick/x86/codegen_x86.h +++ b/compiler/dex/quick/x86/codegen_x86.h @@ -309,6 +309,34 @@ class X86Mir2Lir : public Mir2Lir { * @param loc Register location to dump */ static void DumpRegLocation(RegLocation loc); + + /** + * @brief Calculate magic number and shift for a given divisor + * @param divisor divisor number for calculation + * @param magic hold calculated magic number + * @param shift hold calculated shift + */ + void CalculateMagicAndShift(int divisor, int& magic, int& shift); + + /* + * @brief Generate an integer div or rem operation. + * @param rl_dest Destination Location. + * @param rl_src1 Numerator Location. + * @param rl_src2 Divisor Location. + * @param is_div 'true' if this is a division, 'false' for a remainder. + * @param check_zero 'true' if an exception should be generated if the divisor is 0. + */ + RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2, bool is_div, bool check_zero); + + /* + * @brief Generate an integer div or rem operation by a literal. + * @param rl_dest Destination Location. + * @param rl_src Numerator Location. + * @param lit Divisor. + * @param is_div 'true' if this is a division, 'false' for a remainder. + */ + RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src, int lit, bool is_div); }; } // namespace art diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc index 79820c925c..ccae130637 100644 --- a/compiler/dex/quick/x86/int_x86.cc +++ b/compiler/dex/quick/x86/int_x86.cc @@ -284,18 +284,261 @@ void X86Mir2Lir::GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1, OpCmpImmBranch(ccode, low_reg, val_lo, taken); } +void X86Mir2Lir::CalculateMagicAndShift(int divisor, int& magic, int& shift) { + // It does not make sense to calculate magic and shift for zero divisor. + DCHECK_NE(divisor, 0); + + /* According to H.S.Warren's Hacker's Delight Chapter 10 and + * T,Grablund, P.L.Montogomery's Division by invariant integers using multiplication. + * The magic number M and shift S can be calculated in the following way: + * Let nc be the most positive value of numerator(n) such that nc = kd - 1, + * where divisor(d) >=2. + * Let nc be the most negative value of numerator(n) such that nc = kd + 1, + * where divisor(d) <= -2. + * Thus nc can be calculated like: + * nc = 2^31 + 2^31 % d - 1, where d >= 2 + * nc = -2^31 + (2^31 + 1) % d, where d >= 2. + * + * So the shift p is the smallest p satisfying + * 2^p > nc * (d - 2^p % d), where d >= 2 + * 2^p > nc * (d + 2^p % d), where d <= -2. + * + * the magic number M is calcuated by + * M = (2^p + d - 2^p % d) / d, where d >= 2 + * M = (2^p - d - 2^p % d) / d, where d <= -2. + * + * Notice that p is always bigger than or equal to 32, so we just return 32-p as + * the shift number S. + */ + + int32_t p = 31; + const uint32_t two31 = 0x80000000U; + + // Initialize the computations. + uint32_t abs_d = (divisor >= 0) ? divisor : -divisor; + uint32_t tmp = two31 + (static_cast<uint32_t>(divisor) >> 31); + uint32_t abs_nc = tmp - 1 - tmp % abs_d; + uint32_t quotient1 = two31 / abs_nc; + uint32_t remainder1 = two31 % abs_nc; + uint32_t quotient2 = two31 / abs_d; + uint32_t remainder2 = two31 % abs_d; + + /* + * To avoid handling both positive and negative divisor, Hacker's Delight + * introduces a method to handle these 2 cases together to avoid duplication. + */ + uint32_t delta; + do { + p++; + quotient1 = 2 * quotient1; + remainder1 = 2 * remainder1; + if (remainder1 >= abs_nc) { + quotient1++; + remainder1 = remainder1 - abs_nc; + } + quotient2 = 2 * quotient2; + remainder2 = 2 * remainder2; + if (remainder2 >= abs_d) { + quotient2++; + remainder2 = remainder2 - abs_d; + } + delta = abs_d - remainder2; + } while (quotient1 < delta || (quotient1 == delta && remainder1 == 0)); + + magic = (divisor > 0) ? (quotient2 + 1) : (-quotient2 - 1); + shift = p - 32; +} + RegLocation X86Mir2Lir::GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit, bool is_div) { LOG(FATAL) << "Unexpected use of GenDivRemLit for x86"; return rl_dest; } +RegLocation X86Mir2Lir::GenDivRemLit(RegLocation rl_dest, RegLocation rl_src, + int imm, bool is_div) { + // Use a multiply (and fixup) to perform an int div/rem by a constant. + + // We have to use fixed registers, so flush all the temps. + FlushAllRegs(); + LockCallTemps(); // Prepare for explicit register usage. + + // Assume that the result will be in EDX. + RegLocation rl_result = {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, kVectorNotUsed, + r2, INVALID_REG, INVALID_SREG, INVALID_SREG}; + + // handle 0x80000000 / -1 special case. + LIR *minint_branch = 0; + if (imm == -1) { + if (is_div) { + LoadValueDirectFixed(rl_src, r0); + OpRegImm(kOpCmp, r0, 0x80000000); + minint_branch = NewLIR2(kX86Jcc8, 0, kX86CondEq); + + // for x != MIN_INT, x / -1 == -x. + NewLIR1(kX86Neg32R, r0); + + LIR* branch_around = NewLIR1(kX86Jmp8, 0); + // The target for cmp/jmp above. + minint_branch->target = NewLIR0(kPseudoTargetLabel); + // EAX already contains the right value (0x80000000), + branch_around->target = NewLIR0(kPseudoTargetLabel); + } else { + // x % -1 == 0. + LoadConstantNoClobber(r0, 0); + } + // For this case, return the result in EAX. + rl_result.low_reg = r0; + } else { + DCHECK(imm <= -2 || imm >= 2); + // Use H.S.Warren's Hacker's Delight Chapter 10 and + // T,Grablund, P.L.Montogomery's Division by invariant integers using multiplication. + int magic, shift; + CalculateMagicAndShift(imm, magic, shift); + + /* + * For imm >= 2, + * int(n/imm) = floor(n/imm) = floor(M*n/2^S), while n > 0 + * int(n/imm) = ceil(n/imm) = floor(M*n/2^S) +1, while n < 0. + * For imm <= -2, + * int(n/imm) = ceil(n/imm) = floor(M*n/2^S) +1 , while n > 0 + * int(n/imm) = floor(n/imm) = floor(M*n/2^S), while n < 0. + * We implement this algorithm in the following way: + * 1. multiply magic number m and numerator n, get the higher 32bit result in EDX + * 2. if imm > 0 and magic < 0, add numerator to EDX + * if imm < 0 and magic > 0, sub numerator from EDX + * 3. if S !=0, SAR S bits for EDX + * 4. add 1 to EDX if EDX < 0 + * 5. Thus, EDX is the quotient + */ + + // Numerator into EAX. + int numerator_reg = -1; + if (!is_div || (imm > 0 && magic < 0) || (imm < 0 && magic > 0)) { + // We will need the value later. + if (rl_src.location == kLocPhysReg) { + // We can use it directly. + DCHECK(rl_src.low_reg != r0 && rl_src.low_reg != r2); + numerator_reg = rl_src.low_reg; + } else { + LoadValueDirectFixed(rl_src, r1); + numerator_reg = r1; + } + OpRegCopy(r0, numerator_reg); + } else { + // Only need this once. Just put it into EAX. + LoadValueDirectFixed(rl_src, r0); + } + + // EDX = magic. + LoadConstantNoClobber(r2, magic); + + // EDX:EAX = magic & dividend. + NewLIR1(kX86Imul32DaR, r2); + + if (imm > 0 && magic < 0) { + // Add numerator to EDX. + DCHECK_NE(numerator_reg, -1); + NewLIR2(kX86Add32RR, r2, numerator_reg); + } else if (imm < 0 && magic > 0) { + DCHECK_NE(numerator_reg, -1); + NewLIR2(kX86Sub32RR, r2, numerator_reg); + } + + // Do we need the shift? + if (shift != 0) { + // Shift EDX by 'shift' bits. + NewLIR2(kX86Sar32RI, r2, shift); + } + + // Add 1 to EDX if EDX < 0. + + // Move EDX to EAX. + OpRegCopy(r0, r2); + + // Move sign bit to bit 0, zeroing the rest. + NewLIR2(kX86Shr32RI, r2, 31); + + // EDX = EDX + EAX. + NewLIR2(kX86Add32RR, r2, r0); + + // Quotient is in EDX. + if (!is_div) { + // We need to compute the remainder. + // Remainder is divisor - (quotient * imm). + DCHECK_NE(numerator_reg, -1); + OpRegCopy(r0, numerator_reg); + + // EAX = numerator * imm. + OpRegRegImm(kOpMul, r2, r2, imm); + + // EDX -= EAX. + NewLIR2(kX86Sub32RR, r0, r2); + + // For this case, return the result in EAX. + rl_result.low_reg = r0; + } + } + + return rl_result; +} + RegLocation X86Mir2Lir::GenDivRem(RegLocation rl_dest, int reg_lo, int reg_hi, bool is_div) { LOG(FATAL) << "Unexpected use of GenDivRem for x86"; return rl_dest; } +RegLocation X86Mir2Lir::GenDivRem(RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2, bool is_div, bool check_zero) { + // We have to use fixed registers, so flush all the temps. + FlushAllRegs(); + LockCallTemps(); // Prepare for explicit register usage. + + // Load LHS into EAX. + LoadValueDirectFixed(rl_src1, r0); + + // Load RHS into EBX. + LoadValueDirectFixed(rl_src2, r1); + + // Copy LHS sign bit into EDX. + NewLIR0(kx86Cdq32Da); + + if (check_zero) { + // Handle division by zero case. + GenImmedCheck(kCondEq, r1, 0, kThrowDivZero); + } + + // Have to catch 0x80000000/-1 case, or we will get an exception! + OpRegImm(kOpCmp, r1, -1); + LIR *minus_one_branch = NewLIR2(kX86Jcc8, 0, kX86CondNe); + + // RHS is -1. + OpRegImm(kOpCmp, r0, 0x80000000); + LIR * minint_branch = NewLIR2(kX86Jcc8, 0, kX86CondNe); + + // In 0x80000000/-1 case. + if (!is_div) { + // For DIV, EAX is already right. For REM, we need EDX 0. + LoadConstantNoClobber(r2, 0); + } + LIR* done = NewLIR1(kX86Jmp8, 0); + + // Expected case. + minus_one_branch->target = NewLIR0(kPseudoTargetLabel); + minint_branch->target = minus_one_branch->target; + NewLIR1(kX86Idivmod32DaR, r1); + done->target = NewLIR0(kPseudoTargetLabel); + + // Result is in EAX for div and EDX for rem. + RegLocation rl_result = {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, kVectorNotUsed, + r0, INVALID_REG, INVALID_SREG, INVALID_SREG}; + if (!is_div) { + rl_result.low_reg = r2; + } + return rl_result; +} + bool X86Mir2Lir::GenInlinedMinMaxInt(CallInfo* info, bool is_min) { DCHECK_EQ(cu_->instruction_set, kX86); diff --git a/compiler/dex/quick/x86/x86_lir.h b/compiler/dex/quick/x86/x86_lir.h index 1488f5d557..d7f61fc027 100644 --- a/compiler/dex/quick/x86/x86_lir.h +++ b/compiler/dex/quick/x86/x86_lir.h @@ -316,6 +316,7 @@ enum X86OpCode { UnaryOpcode(kX86Imul, DaR, DaM, DaA), UnaryOpcode(kX86Divmod, DaR, DaM, DaA), UnaryOpcode(kX86Idivmod, DaR, DaM, DaA), + kx86Cdq32Da, kX86Bswap32R, kX86Push32R, kX86Pop32R, #undef UnaryOpcode diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc index c51ea7b8a4..6d82f0a882 100644 --- a/disassembler/disassembler_x86.cc +++ b/disassembler/disassembler_x86.cc @@ -571,6 +571,9 @@ DISASSEMBLER_ENTRY(cmp, reg_is_opcode = true; store = true; break; + case 0x99: + opcode << "cdq"; + break; case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7: opcode << "mov"; immediate_bytes = 1; |