diff options
Diffstat (limited to 'compiler/dex/quick')
-rw-r--r-- | compiler/dex/quick/arm/codegen_arm.h | 2 | ||||
-rw-r--r-- | compiler/dex/quick/arm/utility_arm.cc | 10 | ||||
-rw-r--r-- | compiler/dex/quick/gen_invoke.cc | 163 | ||||
-rw-r--r-- | compiler/dex/quick/mips/codegen_mips.h | 2 | ||||
-rw-r--r-- | compiler/dex/quick/mips/utility_mips.cc | 10 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.h | 21 | ||||
-rw-r--r-- | compiler/dex/quick/x86/assemble_x86.cc | 18 | ||||
-rw-r--r-- | compiler/dex/quick/x86/codegen_x86.h | 2 | ||||
-rw-r--r-- | compiler/dex/quick/x86/utility_x86.cc | 104 | ||||
-rw-r--r-- | compiler/dex/quick/x86/x86_lir.h | 8 |
10 files changed, 310 insertions, 30 deletions
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h index 32673db41e..0ed4576e80 100644 --- a/compiler/dex/quick/arm/codegen_arm.h +++ b/compiler/dex/quick/arm/codegen_arm.h @@ -154,6 +154,8 @@ class ArmMir2Lir : public Mir2Lir { LIR* OpRegImm(OpKind op, int r_dest_src1, int value); LIR* OpRegMem(OpKind op, int r_dest, int rBase, int offset); LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2); + LIR* OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type); + LIR* OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type); LIR* OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src); LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value); LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2); diff --git a/compiler/dex/quick/arm/utility_arm.cc b/compiler/dex/quick/arm/utility_arm.cc index 07fc6c790d..9d3968bff2 100644 --- a/compiler/dex/quick/arm/utility_arm.cc +++ b/compiler/dex/quick/arm/utility_arm.cc @@ -367,6 +367,16 @@ LIR* ArmMir2Lir::OpRegReg(OpKind op, int r_dest_src1, int r_src2) { return OpRegRegShift(op, r_dest_src1, r_src2, 0); } +LIR* ArmMir2Lir::OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type) { + UNIMPLEMENTED(FATAL); + return nullptr; +} + +LIR* ArmMir2Lir::OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type) { + UNIMPLEMENTED(FATAL); + return nullptr; +} + LIR* ArmMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src) { LOG(FATAL) << "Unexpected use of OpCondRegReg for Arm"; return NULL; diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc index 3823fb31d4..6382dd6608 100644 --- a/compiler/dex/quick/gen_invoke.cc +++ b/compiler/dex/quick/gen_invoke.cc @@ -811,42 +811,145 @@ int Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state, } } + // Logic below assumes that Method pointer is at offset zero from SP. + DCHECK_EQ(VRegOffset(static_cast<int>(kVRegMethodPtrBaseReg)), 0); + + // The first 3 arguments are passed via registers. + // TODO: For 64-bit, instead of hardcoding 4 for Method* size, we should either + // get size of uintptr_t or size of object reference according to model being used. + int outs_offset = 4 /* Method* */ + (3 * sizeof(uint32_t)); int start_offset = SRegOffset(info->args[3].s_reg_low); - int outs_offset = 4 /* Method* */ + (3 * 4); - if (cu_->instruction_set != kThumb2) { + int regs_left_to_pass_via_stack = info->num_arg_words - 3; + DCHECK_GT(regs_left_to_pass_via_stack, 0); + + if (cu_->instruction_set == kThumb2 && regs_left_to_pass_via_stack <= 16) { + // Use vldm/vstm pair using kArg3 as a temp + call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx, + direct_code, direct_method, type); + OpRegRegImm(kOpAdd, TargetReg(kArg3), TargetReg(kSp), start_offset); + LIR* ld = OpVldm(TargetReg(kArg3), regs_left_to_pass_via_stack); + // TUNING: loosen barrier + ld->u.m.def_mask = ENCODE_ALL; + SetMemRefType(ld, true /* is_load */, kDalvikReg); + call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx, + direct_code, direct_method, type); + OpRegRegImm(kOpAdd, TargetReg(kArg3), TargetReg(kSp), 4 /* Method* */ + (3 * 4)); + call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx, + direct_code, direct_method, type); + LIR* st = OpVstm(TargetReg(kArg3), regs_left_to_pass_via_stack); + SetMemRefType(st, false /* is_load */, kDalvikReg); + st->u.m.def_mask = ENCODE_ALL; + call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx, + direct_code, direct_method, type); + } else if (cu_->instruction_set == kX86) { + int current_src_offset = start_offset; + int current_dest_offset = outs_offset; + + while (regs_left_to_pass_via_stack > 0) { + // This is based on the knowledge that the stack itself is 16-byte aligned. + bool src_is_16b_aligned = (current_src_offset & 0xF) == 0; + bool dest_is_16b_aligned = (current_dest_offset & 0xF) == 0; + size_t bytes_to_move; + + /* + * The amount to move defaults to 32-bit. If there are 4 registers left to move, then do a + * a 128-bit move because we won't get the chance to try to aligned. If there are more than + * 4 registers left to move, consider doing a 128-bit only if either src or dest are aligned. + * We do this because we could potentially do a smaller move to align. + */ + if (regs_left_to_pass_via_stack == 4 || + (regs_left_to_pass_via_stack > 4 && (src_is_16b_aligned || dest_is_16b_aligned))) { + // Moving 128-bits via xmm register. + bytes_to_move = sizeof(uint32_t) * 4; + + // Allocate a free xmm temp. Since we are working through the calling sequence, + // we expect to have an xmm temporary available. + int temp = AllocTempDouble(); + CHECK_GT(temp, 0); + + LIR* ld1 = nullptr; + LIR* ld2 = nullptr; + LIR* st1 = nullptr; + LIR* st2 = nullptr; + + /* + * The logic is similar for both loads and stores. If we have 16-byte alignment, + * do an aligned move. If we have 8-byte alignment, then do the move in two + * parts. This approach prevents possible cache line splits. Finally, fall back + * to doing an unaligned move. In most cases we likely won't split the cache + * line but we cannot prove it and thus take a conservative approach. + */ + bool src_is_8b_aligned = (current_src_offset & 0x7) == 0; + bool dest_is_8b_aligned = (current_dest_offset & 0x7) == 0; + + if (src_is_16b_aligned) { + ld1 = OpMovRegMem(temp, TargetReg(kSp), current_src_offset, kMovA128FP); + } else if (src_is_8b_aligned) { + ld1 = OpMovRegMem(temp, TargetReg(kSp), current_src_offset, kMovLo128FP); + ld2 = OpMovRegMem(temp, TargetReg(kSp), current_src_offset + (bytes_to_move >> 1), kMovHi128FP); + } else { + ld1 = OpMovRegMem(temp, TargetReg(kSp), current_src_offset, kMovU128FP); + } + + if (dest_is_16b_aligned) { + st1 = OpMovMemReg(TargetReg(kSp), current_dest_offset, temp, kMovA128FP); + } else if (dest_is_8b_aligned) { + st1 = OpMovMemReg(TargetReg(kSp), current_dest_offset, temp, kMovLo128FP); + st2 = OpMovMemReg(TargetReg(kSp), current_dest_offset + (bytes_to_move >> 1), temp, kMovHi128FP); + } else { + st1 = OpMovMemReg(TargetReg(kSp), current_dest_offset, temp, kMovU128FP); + } + + // TODO If we could keep track of aliasing information for memory accesses that are wider + // than 64-bit, we wouldn't need to set up a barrier. + if (ld1 != nullptr) { + if (ld2 != nullptr) { + // For 64-bit load we can actually set up the aliasing information. + AnnotateDalvikRegAccess(ld1, current_src_offset >> 2, true, true); + AnnotateDalvikRegAccess(ld2, (current_src_offset + (bytes_to_move >> 1)) >> 2, true, true); + } else { + // Set barrier for 128-bit load. + SetMemRefType(ld1, true /* is_load */, kDalvikReg); + ld1->u.m.def_mask = ENCODE_ALL; + } + } + if (st1 != nullptr) { + if (st2 != nullptr) { + // For 64-bit store we can actually set up the aliasing information. + AnnotateDalvikRegAccess(st1, current_dest_offset >> 2, false, true); + AnnotateDalvikRegAccess(st2, (current_dest_offset + (bytes_to_move >> 1)) >> 2, false, true); + } else { + // Set barrier for 128-bit store. + SetMemRefType(st1, false /* is_load */, kDalvikReg); + st1->u.m.def_mask = ENCODE_ALL; + } + } + + // Free the temporary used for the data movement. + FreeTemp(temp); + } else { + // Moving 32-bits via general purpose register. + bytes_to_move = sizeof(uint32_t); + + // Instead of allocating a new temp, simply reuse one of the registers being used + // for argument passing. + int temp = TargetReg(kArg3); + + // Now load the argument VR and store to the outs. + LoadWordDisp(TargetReg(kSp), current_src_offset, temp); + StoreWordDisp(TargetReg(kSp), current_dest_offset, temp); + } + + current_src_offset += bytes_to_move; + current_dest_offset += bytes_to_move; + regs_left_to_pass_via_stack -= (bytes_to_move >> 2); + } + } else { // Generate memcpy OpRegRegImm(kOpAdd, TargetReg(kArg0), TargetReg(kSp), outs_offset); OpRegRegImm(kOpAdd, TargetReg(kArg1), TargetReg(kSp), start_offset); CallRuntimeHelperRegRegImm(QUICK_ENTRYPOINT_OFFSET(pMemcpy), TargetReg(kArg0), TargetReg(kArg1), (info->num_arg_words - 3) * 4, false); - } else { - if (info->num_arg_words >= 20) { - // Generate memcpy - OpRegRegImm(kOpAdd, TargetReg(kArg0), TargetReg(kSp), outs_offset); - OpRegRegImm(kOpAdd, TargetReg(kArg1), TargetReg(kSp), start_offset); - CallRuntimeHelperRegRegImm(QUICK_ENTRYPOINT_OFFSET(pMemcpy), TargetReg(kArg0), - TargetReg(kArg1), (info->num_arg_words - 3) * 4, false); - } else { - // Use vldm/vstm pair using kArg3 as a temp - int regs_left = std::min(info->num_arg_words - 3, 16); - call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx, - direct_code, direct_method, type); - OpRegRegImm(kOpAdd, TargetReg(kArg3), TargetReg(kSp), start_offset); - LIR* ld = OpVldm(TargetReg(kArg3), regs_left); - // TUNING: loosen barrier - ld->u.m.def_mask = ENCODE_ALL; - SetMemRefType(ld, true /* is_load */, kDalvikReg); - call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx, - direct_code, direct_method, type); - OpRegRegImm(kOpAdd, TargetReg(kArg3), TargetReg(kSp), 4 /* Method* */ + (3 * 4)); - call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx, - direct_code, direct_method, type); - LIR* st = OpVstm(TargetReg(kArg3), regs_left); - SetMemRefType(st, false /* is_load */, kDalvikReg); - st->u.m.def_mask = ENCODE_ALL; - call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx, - direct_code, direct_method, type); - } } call_state = LoadArgRegs(info, call_state, next_call_insn, diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h index aca93f51d3..11b8f83058 100644 --- a/compiler/dex/quick/mips/codegen_mips.h +++ b/compiler/dex/quick/mips/codegen_mips.h @@ -151,6 +151,8 @@ class MipsMir2Lir : public Mir2Lir { LIR* OpRegImm(OpKind op, int r_dest_src1, int value); LIR* OpRegMem(OpKind op, int r_dest, int rBase, int offset); LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2); + LIR* OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type); + LIR* OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type); LIR* OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src); LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value); LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2); diff --git a/compiler/dex/quick/mips/utility_mips.cc b/compiler/dex/quick/mips/utility_mips.cc index c5e2b36ef2..21c971c327 100644 --- a/compiler/dex/quick/mips/utility_mips.cc +++ b/compiler/dex/quick/mips/utility_mips.cc @@ -325,6 +325,16 @@ LIR* MipsMir2Lir::OpRegReg(OpKind op, int r_dest_src1, int r_src2) { return NewLIR2(opcode, r_dest_src1, r_src2); } +LIR* MipsMir2Lir::OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type) { + UNIMPLEMENTED(FATAL); + return nullptr; +} + +LIR* MipsMir2Lir::OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type) { + UNIMPLEMENTED(FATAL); + return nullptr; +} + LIR* MipsMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src) { LOG(FATAL) << "Unexpected use of OpCondRegReg for MIPS"; return NULL; diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index 09b501aba7..3a68044d51 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -946,6 +946,27 @@ class Mir2Lir : public Backend { virtual LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2) = 0; /** + * @brief Used to generate an LIR that does a load from mem to reg. + * @param r_dest The destination physical register. + * @param r_base The base physical register for memory operand. + * @param offset The displacement for memory operand. + * @param move_type Specification on the move desired (size, alignment, register kind). + * @return Returns the generate move LIR. + */ + virtual LIR* OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type) = 0; + + /** + * @brief Used to generate an LIR that does a store from reg to mem. + * @param r_base The base physical register for memory operand. + * @param offset The displacement for memory operand. + * @param r_src The destination physical register. + * @param bytes_to_move The number of bytes to move. + * @param is_aligned Whether the memory location is known to be aligned. + * @return Returns the generate move LIR. + */ + virtual LIR* OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type) = 0; + + /** * @brief Used for generating a conditional register to register operation. * @param op The opcode kind. * @param cc The condition code that when true will perform the opcode. diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc index 3058b0c884..ae53ddbc9e 100644 --- a/compiler/dex/quick/x86/assemble_x86.cc +++ b/compiler/dex/quick/x86/assemble_x86.cc @@ -297,6 +297,24 @@ ENCODING_MAP(Cmp, IS_LOAD, 0, 0, { kX86SqrtsdRR, kRegReg, IS_BINARY_OP | REG_DEF0_USE1, { 0xF2, 0, 0x0F, 0x51, 0, 0, 0, 0 }, "SqrtsdRR", "!0r,!1r" }, { kX86FstpdM, kMem, IS_STORE | IS_BINARY_OP | REG_USE0, { 0x0, 0, 0xDD, 0x00, 0, 3, 0, 0 }, "FstpdM", "[!0r,!1d]" }, + EXT_0F_ENCODING_MAP(Movups, 0x0, 0x10, REG_DEF0), + { kX86MovupsMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0x0, 0, 0x0F, 0x11, 0, 0, 0, 0 }, "MovupsMR", "[!0r+!1d],!2r" }, + { kX86MovupsAR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014, { 0x0, 0, 0x0F, 0x11, 0, 0, 0, 0 }, "MovupsAR", "[!0r+!1r<<!2d+!3d],!4r" }, + + EXT_0F_ENCODING_MAP(Movaps, 0x0, 0x28, REG_DEF0), + { kX86MovapsMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0x0, 0, 0x0F, 0x29, 0, 0, 0, 0 }, "MovapsMR", "[!0r+!1d],!2r" }, + { kX86MovapsAR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014, { 0x0, 0, 0x0F, 0x29, 0, 0, 0, 0 }, "MovapsAR", "[!0r+!1r<<!2d+!3d],!4r" }, + + { kX86MovlpsRM, kRegMem, IS_LOAD | IS_TERTIARY_OP | REG_DEF0 | REG_USE01, { 0x0, 0, 0x0F, 0x12, 0, 0, 0, 0 }, "MovlpsRM", "!0r,[!1r+!2d]" }, + { kX86MovlpsRA, kRegArray, IS_LOAD | IS_QUIN_OP | REG_DEF0 | REG_USE012, { 0x0, 0, 0x0F, 0x12, 0, 0, 0, 0 }, "MovlpsRA", "!0r,[!1r+!2r<<!3d+!4d]" }, + { kX86MovlpsMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0x0, 0, 0x0F, 0x13, 0, 0, 0, 0 }, "MovlpsMR", "[!0r+!1d],!2r" }, + { kX86MovlpsAR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014, { 0x0, 0, 0x0F, 0x13, 0, 0, 0, 0 }, "MovlpsAR", "[!0r+!1r<<!2d+!3d],!4r" }, + + { kX86MovhpsRM, kRegMem, IS_LOAD | IS_TERTIARY_OP | REG_DEF0 | REG_USE01, { 0x0, 0, 0x0F, 0x16, 0, 0, 0, 0 }, "MovhpsRM", "!0r,[!1r+!2d]" }, + { kX86MovhpsRA, kRegArray, IS_LOAD | IS_QUIN_OP | REG_DEF0 | REG_USE012, { 0x0, 0, 0x0F, 0x16, 0, 0, 0, 0 }, "MovhpsRA", "!0r,[!1r+!2r<<!3d+!4d]" }, + { kX86MovhpsMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0x0, 0, 0x0F, 0x17, 0, 0, 0, 0 }, "MovhpsMR", "[!0r+!1d],!2r" }, + { kX86MovhpsAR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014, { 0x0, 0, 0x0F, 0x17, 0, 0, 0, 0 }, "MovhpsAR", "[!0r+!1r<<!2d+!3d],!4r" }, + EXT_0F_ENCODING_MAP(Movdxr, 0x66, 0x6E, REG_DEF0), { kX86MovdrxRR, kRegRegStore, IS_BINARY_OP | REG_DEF0 | REG_USE01, { 0x66, 0, 0x0F, 0x7E, 0, 0, 0, 0 }, "MovdrxRR", "!0r,!1r" }, { kX86MovdrxMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0x66, 0, 0x0F, 0x7E, 0, 0, 0, 0 }, "MovdrxMR", "[!0r+!1d],!2r" }, diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h index 6896504f52..4c1c1711c0 100644 --- a/compiler/dex/quick/x86/codegen_x86.h +++ b/compiler/dex/quick/x86/codegen_x86.h @@ -207,6 +207,8 @@ class X86Mir2Lir : public Mir2Lir { LIR* OpMemReg(OpKind op, RegLocation rl_dest, int value); LIR* OpRegMem(OpKind op, int r_dest, RegLocation value); LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2); + LIR* OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type); + LIR* OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type); LIR* OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src); LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value); LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2); diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc index 18c5ca801b..e2744d076d 100644 --- a/compiler/dex/quick/x86/utility_x86.cc +++ b/compiler/dex/quick/x86/utility_x86.cc @@ -211,6 +211,110 @@ LIR* X86Mir2Lir::OpRegReg(OpKind op, int r_dest_src1, int r_src2) { return NewLIR2(opcode, r_dest_src1, r_src2); } +LIR* X86Mir2Lir::OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type) { + DCHECK(!(X86_FPREG(r_base))); + + X86OpCode opcode = kX86Nop; + switch (move_type) { + case kMov8GP: + CHECK(!X86_FPREG(r_dest)); + opcode = kX86Mov8RM; + break; + case kMov16GP: + CHECK(!X86_FPREG(r_dest)); + opcode = kX86Mov16RM; + break; + case kMov32GP: + CHECK(!X86_FPREG(r_dest)); + opcode = kX86Mov32RM; + break; + case kMov32FP: + CHECK(X86_FPREG(r_dest)); + opcode = kX86MovssRM; + break; + case kMov64FP: + CHECK(X86_FPREG(r_dest)); + opcode = kX86MovsdRM; + break; + case kMovU128FP: + CHECK(X86_FPREG(r_dest)); + opcode = kX86MovupsRM; + break; + case kMovA128FP: + CHECK(X86_FPREG(r_dest)); + opcode = kX86MovapsRM; + break; + case kMovLo128FP: + CHECK(X86_FPREG(r_dest)); + opcode = kX86MovlpsRM; + break; + case kMovHi128FP: + CHECK(X86_FPREG(r_dest)); + opcode = kX86MovhpsRM; + break; + case kMov64GP: + case kMovLo64FP: + case kMovHi64FP: + default: + LOG(FATAL) << "Bad case in OpMovRegMem"; + break; + } + + return NewLIR3(opcode, r_dest, r_base, offset); +} + +LIR* X86Mir2Lir::OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type) { + DCHECK(!(X86_FPREG(r_base))); + + X86OpCode opcode = kX86Nop; + switch (move_type) { + case kMov8GP: + CHECK(!X86_FPREG(r_src)); + opcode = kX86Mov8MR; + break; + case kMov16GP: + CHECK(!X86_FPREG(r_src)); + opcode = kX86Mov16MR; + break; + case kMov32GP: + CHECK(!X86_FPREG(r_src)); + opcode = kX86Mov32MR; + break; + case kMov32FP: + CHECK(X86_FPREG(r_src)); + opcode = kX86MovssMR; + break; + case kMov64FP: + CHECK(X86_FPREG(r_src)); + opcode = kX86MovsdMR; + break; + case kMovU128FP: + CHECK(X86_FPREG(r_src)); + opcode = kX86MovupsMR; + break; + case kMovA128FP: + CHECK(X86_FPREG(r_src)); + opcode = kX86MovapsMR; + break; + case kMovLo128FP: + CHECK(X86_FPREG(r_src)); + opcode = kX86MovlpsMR; + break; + case kMovHi128FP: + CHECK(X86_FPREG(r_src)); + opcode = kX86MovhpsMR; + break; + case kMov64GP: + case kMovLo64FP: + case kMovHi64FP: + default: + LOG(FATAL) << "Bad case in OpMovMemReg"; + break; + } + + return NewLIR3(opcode, r_base, offset, r_src); +} + LIR* X86Mir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src) { // The only conditional reg to reg operation supported is Cmov DCHECK_EQ(op, kOpCmov); diff --git a/compiler/dex/quick/x86/x86_lir.h b/compiler/dex/quick/x86/x86_lir.h index 7f35d061b5..6962ff7a49 100644 --- a/compiler/dex/quick/x86/x86_lir.h +++ b/compiler/dex/quick/x86/x86_lir.h @@ -357,6 +357,14 @@ enum X86OpCode { kX86PsllqRI, // left shift of floating point registers kX86SqrtsdRR, // sqrt of floating point register kX86FstpdM, // Store and pop top x87 fp stack + Binary0fOpCode(kX86Movups), // load unaligned packed single FP values from xmm2/m128 to xmm1 + kX86MovupsMR, kX86MovupsAR, // store unaligned packed single FP values from xmm1 to m128 + Binary0fOpCode(kX86Movaps), // load aligned packed single FP values from xmm2/m128 to xmm1 + kX86MovapsMR, kX86MovapsAR, // store aligned packed single FP values from xmm1 to m128 + kX86MovlpsRM, kX86MovlpsRA, // load packed single FP values from m64 to low quadword of xmm + kX86MovlpsMR, kX86MovlpsAR, // store packed single FP values from low quadword of xmm to m64 + kX86MovhpsRM, kX86MovhpsRA, // load packed single FP values from m64 to high quadword of xmm + kX86MovhpsMR, kX86MovhpsAR, // store packed single FP values from high quadword of xmm to m64 Binary0fOpCode(kX86Movdxr), // move into xmm from gpr kX86MovdrxRR, kX86MovdrxMR, kX86MovdrxAR, // move into reg from xmm kX86Set8R, kX86Set8M, kX86Set8A, // set byte depending on condition operand |