1e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee/* 2e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * Copyright (C) 2012 The Android Open Source Project 3e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * 4e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * Licensed under the Apache License, Version 2.0 (the "License"); 5e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * you may not use this file except in compliance with the License. 6e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * You may obtain a copy of the License at 7e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * 8e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * http://www.apache.org/licenses/LICENSE-2.0 9e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * 10e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * Unless required by applicable law or agreed to in writing, software 11e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * distributed under the License is distributed on an "AS IS" BASIS, 12e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * See the License for the specific language governing permissions and 14e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * limitations under the License. 15e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee */ 16e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 1702031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_x86.h" 180b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe 190b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "base/logging.h" 201961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko#include "dex/mir_graph.h" 217940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h" 2267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell#include "dex/dataflow_iterator-inl.h" 237071c8d5885175a746723a3b38a347855965be08Yixin Shou#include "dex/quick/dex_file_method_inliner.h" 247071c8d5885175a746723a3b38a347855965be08Yixin Shou#include "dex/quick/dex_file_to_method_inliner_map.h" 25b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee#include "dex/reg_storage_eq.h" 260b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "driver/compiler_driver.h" 270b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "x86_lir.h" 281bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 29e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbeenamespace art { 30e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 31b046e16d8b8da318d6055f9308950131f1255e08buzbee/* This file contains codegen for the X86 ISA */ 32e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 332700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) { 34a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int opcode; 35a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* must be both DOUBLE or both not DOUBLE */ 36091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(r_dest.IsFloat() || r_src.IsFloat()); 37091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK_EQ(r_dest.IsDouble(), r_src.IsDouble()); 38091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest.IsDouble()) { 39a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee opcode = kX86MovsdRR; 40a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 41091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest.IsSingle()) { 42091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_src.IsSingle()) { 43a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee opcode = kX86MovssRR; 44a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { // Fpr <- Gpr 45a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee opcode = kX86MovdxrRR; 46a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 47a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { // Gpr <- Fpr 48091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(r_src.IsSingle()) << "Raw: 0x" << std::hex << r_src.GetRawBits(); 49a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee opcode = kX86MovdrxRR; 50e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 51a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 52ec13743da80a80c1817cf6660c28917fc28846bcbuzbee DCHECK_NE((EncodingMap[opcode].flags & IS_BINARY_OP), 0ULL); 532700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest.GetReg(), r_src.GetReg()); 54fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (r_dest == r_src) { 55fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee res->flags.is_nop = true; 56a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 57a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return res; 58e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 59e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 602ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::InexpensiveConstantInt(int32_t value) { 616a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(value); 62e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee return true; 63e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee} 64e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee 652ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::InexpensiveConstantFloat(int32_t value) { 666a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers return value == 0; 674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee} 684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee 692ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::InexpensiveConstantLong(int64_t value) { 706a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(value); 714ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee return true; 724ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee} 734ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee 742ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::InexpensiveConstantDouble(int64_t value) { 7567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell return value == 0; 764ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee} 774ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee 78e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee/* 79e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * Load a immediate using a shortcut if possible; otherwise 80e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * grab from the per-translation literal pool. If target is 81e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * a high register, build constant into a low register and copy. 82e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * 83e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * No additional register clobbering operation performed. Use this version when 84fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * 1) r_dest is freshly returned from AllocTemp or 85e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * 2) The codegen is under fixed register usage 86e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee */ 872700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) { 882700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_dest_save = r_dest; 89091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest.IsFloat()) { 90b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers if (value == 0) { 912700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR2(kX86XorpsRR, r_dest.GetReg(), r_dest.GetReg()); 92b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } 931fd3346740dfb7f47be9922312b68a4227fada96buzbee r_dest = AllocTemp(); 946cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers } 95e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 96b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers LIR *res; 976cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers if (value == 0) { 982700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee res = NewLIR2(kX86Xor32RR, r_dest.GetReg(), r_dest.GetReg()); 996cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers } else { 1002e9f7ed8d00271cb1cf082d68b4f4bc60702d6ecIan Rogers // Note, there is no byte immediate form of a 32 bit immediate move. 101e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu // 64-bit immediate is not supported by LIR structure 102e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu res = NewLIR2(kX86Mov32RI, r_dest.GetReg(), value); 1036cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers } 104e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 105091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest_save.IsFloat()) { 1062700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee NewLIR2(kX86MovdxrRR, r_dest_save.GetReg(), r_dest.GetReg()); 1071fd3346740dfb7f47be9922312b68a4227fada96buzbee FreeTemp(r_dest); 1086cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers } 109e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 1106cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers return res; 111e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 112e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 1132ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* X86Mir2Lir::OpUnconditionalBranch(LIR* target) { 114df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom LIR* res = NewLIR1(kX86Jmp8, 0 /* offset to be patched during assembly*/); 11502031b185b4653e6c72e21f7a51238b903f6d638buzbee res->target = target; 11602031b185b4653e6c72e21f7a51238b903f6d638buzbee return res; 117e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 118e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 1192ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* X86Mir2Lir::OpCondBranch(ConditionCode cc, LIR* target) { 1201fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch = NewLIR2(kX86Jcc8, 0 /* offset to be patched */, 12152a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee X86ConditionEncoding(cc)); 122b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers branch->target = target; 123b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers return branch; 124a7678db092ac6bb79f7cad490099a1015fbbc714buzbee} 125a7678db092ac6bb79f7cad490099a1015fbbc714buzbee 1262700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpReg(OpKind op, RegStorage r_dest_src) { 127b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode opcode = kX86Bkpt; 128b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers switch (op) { 129e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpNeg: opcode = r_dest_src.Is64Bit() ? kX86Neg64R : kX86Neg32R; break; 130e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpNot: opcode = r_dest_src.Is64Bit() ? kX86Not64R : kX86Not32R; break; 131c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk case kOpRev: opcode = r_dest_src.Is64Bit() ? kX86Bswap64R : kX86Bswap32R; break; 132b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpBlx: opcode = kX86CallR; break; 133b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 13452a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee LOG(FATAL) << "Bad case in OpReg " << op; 135b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 1362700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR1(opcode, r_dest_src.GetReg()); 137e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 138e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 1392700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) { 140b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode opcode = kX86Bkpt; 141fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bool byte_imm = IS_SIMM8(value); 142091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!r_dest_src1.IsFloat()); 1439ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko if (r_dest_src1.Is64Bit()) { 1449ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko switch (op) { 1459ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpAdd: opcode = byte_imm ? kX86Add64RI8 : kX86Add64RI; break; 1469ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpSub: opcode = byte_imm ? kX86Sub64RI8 : kX86Sub64RI; break; 147e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpLsl: opcode = kX86Sal64RI; break; 148e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpLsr: opcode = kX86Shr64RI; break; 149e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpAsr: opcode = kX86Sar64RI; break; 1507e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu case kOpCmp: opcode = byte_imm ? kX86Cmp64RI8 : kX86Cmp64RI; break; 1519ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko default: 1529ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko LOG(FATAL) << "Bad case in OpRegImm (64-bit) " << op; 1539ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 1549ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 1559ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko switch (op) { 1569ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpLsl: opcode = kX86Sal32RI; break; 1579ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpLsr: opcode = kX86Shr32RI; break; 1589ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpAsr: opcode = kX86Sar32RI; break; 1599ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpAdd: opcode = byte_imm ? kX86Add32RI8 : kX86Add32RI; break; 1609ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpOr: opcode = byte_imm ? kX86Or32RI8 : kX86Or32RI; break; 1619ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpAdc: opcode = byte_imm ? kX86Adc32RI8 : kX86Adc32RI; break; 1629ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko // case kOpSbb: opcode = kX86Sbb32RI; break; 1639ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpAnd: opcode = byte_imm ? kX86And32RI8 : kX86And32RI; break; 1649ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpSub: opcode = byte_imm ? kX86Sub32RI8 : kX86Sub32RI; break; 1659ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpXor: opcode = byte_imm ? kX86Xor32RI8 : kX86Xor32RI; break; 1669ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpCmp: opcode = byte_imm ? kX86Cmp32RI8 : kX86Cmp32RI; break; 1679ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpMov: 1689ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko /* 1699ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko * Moving the constant zero into register can be specialized as an xor of the register. 1709ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko * However, that sets eflags while the move does not. For that reason here, always do 1719ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko * the move and if caller is flexible, they should be calling LoadConstantNoClobber instead. 1729ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko */ 1739ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko opcode = kX86Mov32RI; 1749ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko break; 1759ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpMul: 1769ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI; 1779ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko return NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), value); 178e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell case kOp2Byte: 179e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell opcode = kX86Mov32RI; 180e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell value = static_cast<int8_t>(value); 181e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell break; 182e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell case kOp2Short: 183e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell opcode = kX86Mov32RI; 184e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell value = static_cast<int16_t>(value); 185e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell break; 186e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell case kOp2Char: 187e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell opcode = kX86Mov32RI; 188e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell value = static_cast<uint16_t>(value); 189e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell break; 190e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell case kOpNeg: 191e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell opcode = kX86Mov32RI; 192e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell value = -value; 193e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell break; 1949ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko default: 1959ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko LOG(FATAL) << "Bad case in OpRegImm " << op; 1969ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 197b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 1982700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR2(opcode, r_dest_src1.GetReg(), value); 199e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 200e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 2012700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) { 202e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu bool is64Bit = r_dest_src1.Is64Bit(); 203a7678db092ac6bb79f7cad490099a1015fbbc714buzbee X86OpCode opcode = kX86Nop; 204d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers bool src2_must_be_cx = false; 205e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee switch (op) { 206b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // X86 unary opcodes 207b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpMvn: 2081fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_dest_src1, r_src2); 2091fd3346740dfb7f47be9922312b68a4227fada96buzbee return OpReg(kOpNot, r_dest_src1); 210b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpNeg: 2111fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_dest_src1, r_src2); 2121fd3346740dfb7f47be9922312b68a4227fada96buzbee return OpReg(kOpNeg, r_dest_src1); 213a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko case kOpRev: 214a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko OpRegCopy(r_dest_src1, r_src2); 215a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko return OpReg(kOpRev, r_dest_src1); 216a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko case kOpRevsh: 217a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko OpRegCopy(r_dest_src1, r_src2); 218a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko OpReg(kOpRev, r_dest_src1); 219a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko return OpRegImm(kOpAsr, r_dest_src1, 16); 220b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // X86 binary opcodes 221e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpSub: opcode = is64Bit ? kX86Sub64RR : kX86Sub32RR; break; 222e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpSbc: opcode = is64Bit ? kX86Sbb64RR : kX86Sbb32RR; break; 223e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpLsl: opcode = is64Bit ? kX86Sal64RC : kX86Sal32RC; src2_must_be_cx = true; break; 224e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpLsr: opcode = is64Bit ? kX86Shr64RC : kX86Shr32RC; src2_must_be_cx = true; break; 225e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpAsr: opcode = is64Bit ? kX86Sar64RC : kX86Sar32RC; src2_must_be_cx = true; break; 226e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpMov: opcode = is64Bit ? kX86Mov64RR : kX86Mov32RR; break; 227e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpCmp: opcode = is64Bit ? kX86Cmp64RR : kX86Cmp32RR; break; 228e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpAdd: opcode = is64Bit ? kX86Add64RR : kX86Add32RR; break; 229e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpAdc: opcode = is64Bit ? kX86Adc64RR : kX86Adc32RR; break; 230e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpAnd: opcode = is64Bit ? kX86And64RR : kX86And32RR; break; 231e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpOr: opcode = is64Bit ? kX86Or64RR : kX86Or32RR; break; 232e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpXor: opcode = is64Bit ? kX86Xor64RR : kX86Xor32RR; break; 233703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case kOp2Byte: 234091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // TODO: there are several instances of this check. A utility function perhaps? 235091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // TODO: Similar to Arm's reg < 8 check. Perhaps add attribute checks to RegStorage? 236703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao // Use shifts instead of a byte operand if the source can't be byte accessed. 237b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers if (r_src2.GetRegNum() >= rs_rX86_SP_32.GetRegNum()) { 238e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu NewLIR2(is64Bit ? kX86Mov64RR : kX86Mov32RR, r_dest_src1.GetReg(), r_src2.GetReg()); 239e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu NewLIR2(is64Bit ? kX86Sal64RI : kX86Sal32RI, r_dest_src1.GetReg(), is64Bit ? 56 : 24); 240e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu return NewLIR2(is64Bit ? kX86Sar64RI : kX86Sar32RI, r_dest_src1.GetReg(), 241e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu is64Bit ? 56 : 24); 242703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } else { 243e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu opcode = is64Bit ? kX86Bkpt : kX86Movsx8RR; 244703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } 245703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 246e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOp2Short: opcode = is64Bit ? kX86Bkpt : kX86Movsx16RR; break; 247e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOp2Char: opcode = is64Bit ? kX86Bkpt : kX86Movzx16RR; break; 248e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpMul: opcode = is64Bit ? kX86Bkpt : kX86Imul32RR; break; 249b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 25052a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee LOG(FATAL) << "Bad case in OpRegReg " << op; 251b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 252e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 253091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(!src2_must_be_cx || r_src2.GetReg() == rs_rCX.GetReg()); 2542700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg()); 255e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 256e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 2572700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type) { 258091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!r_base.IsFloat()); 2592c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru X86OpCode opcode = kX86Nop; 2602700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int dest = r_dest.IsPair() ? r_dest.GetLowReg() : r_dest.GetReg(); 2612c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru switch (move_type) { 2622c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov8GP: 263091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(!r_dest.IsFloat()); 2642c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86Mov8RM; 2652c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2662c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov16GP: 267091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(!r_dest.IsFloat()); 2682c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86Mov16RM; 2692c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2702c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov32GP: 271091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(!r_dest.IsFloat()); 2722c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86Mov32RM; 2732c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2742c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov32FP: 275091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_dest.IsFloat()); 2762c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovssRM; 2772c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2782c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov64FP: 279091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_dest.IsFloat()); 2802c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovsdRM; 2812c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2822c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovU128FP: 283091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_dest.IsFloat()); 2842c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovupsRM; 2852c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2862c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovA128FP: 287091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_dest.IsFloat()); 2882c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovapsRM; 2892c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2902c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovLo128FP: 291091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_dest.IsFloat()); 2922c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovlpsRM; 2932c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2942c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovHi128FP: 295091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_dest.IsFloat()); 2962c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovhpsRM; 2972c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2982c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov64GP: 2992c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovLo64FP: 3002c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovHi64FP: 3012c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru default: 3022c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru LOG(FATAL) << "Bad case in OpMovRegMem"; 3032c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3042c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } 3052c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru 3062700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR3(opcode, dest, r_base.GetReg(), offset); 3072c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru} 3082c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru 3092700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type) { 310091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!r_base.IsFloat()); 3112700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int src = r_src.IsPair() ? r_src.GetLowReg() : r_src.GetReg(); 3122c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru 3132c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru X86OpCode opcode = kX86Nop; 3142c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru switch (move_type) { 3152c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov8GP: 316091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(!r_src.IsFloat()); 3172c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86Mov8MR; 3182c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3192c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov16GP: 320091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(!r_src.IsFloat()); 3212c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86Mov16MR; 3222c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3232c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov32GP: 324091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(!r_src.IsFloat()); 3252c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86Mov32MR; 3262c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3272c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov32FP: 328091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_src.IsFloat()); 3292c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovssMR; 3302c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3312c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov64FP: 332091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_src.IsFloat()); 3332c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovsdMR; 3342c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3352c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovU128FP: 336091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_src.IsFloat()); 3372c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovupsMR; 3382c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3392c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovA128FP: 340091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_src.IsFloat()); 3412c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovapsMR; 3422c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3432c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovLo128FP: 344091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_src.IsFloat()); 3452c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovlpsMR; 3462c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3472c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovHi128FP: 348091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_src.IsFloat()); 3492c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovhpsMR; 3502c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3512c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov64GP: 3522c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovLo64FP: 3532c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovHi64FP: 3542c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru default: 3552c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru LOG(FATAL) << "Bad case in OpMovMemReg"; 3562c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3572c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } 3582c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru 3592700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR3(opcode, r_base.GetReg(), offset, src); 3602c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru} 3612c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru 3622700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) { 363bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru // The only conditional reg to reg operation supported is Cmov 364bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru DCHECK_EQ(op, kOpCmov); 365c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk DCHECK_EQ(r_dest.Is64Bit(), r_src.Is64Bit()); 366c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk return NewLIR3(r_dest.Is64Bit() ? kX86Cmov64RRC : kX86Cmov32RRC, r_dest.GetReg(), 367c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk r_src.GetReg(), X86ConditionEncoding(cc)); 368bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru} 369bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru 3702700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset) { 371e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu bool is64Bit = r_dest.Is64Bit(); 372b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode opcode = kX86Nop; 373b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers switch (op) { 374b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // X86 binary opcodes 375e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpSub: opcode = is64Bit ? kX86Sub64RM : kX86Sub32RM; break; 376e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpMov: opcode = is64Bit ? kX86Mov64RM : kX86Mov32RM; break; 377e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpCmp: opcode = is64Bit ? kX86Cmp64RM : kX86Cmp32RM; break; 378e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpAdd: opcode = is64Bit ? kX86Add64RM : kX86Add32RM; break; 379e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpAnd: opcode = is64Bit ? kX86And64RM : kX86And32RM; break; 380e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpOr: opcode = is64Bit ? kX86Or64RM : kX86Or32RM; break; 381e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpXor: opcode = is64Bit ? kX86Xor64RM : kX86Xor32RM; break; 382b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOp2Byte: opcode = kX86Movsx8RM; break; 383b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOp2Short: opcode = kX86Movsx16RM; break; 384b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOp2Char: opcode = kX86Movzx16RM; break; 385b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpMul: 386b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 38752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee LOG(FATAL) << "Bad case in OpRegMem " << op; 388b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 389b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 3902700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LIR *l = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), offset); 3918dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mem_ref_type_ == ResourceMask::kDalvikReg) { 392b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers DCHECK_EQ(r_base, cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32); 393feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell AnnotateDalvikRegAccess(l, offset >> 2, true /* is_load */, false /* is_64bit */); 394feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell } 395feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell return l; 396feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell} 397feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell 398feb2b4e2d1c6538777bb80b60f3a247537b6221dMark MendellLIR* X86Mir2Lir::OpMemReg(OpKind op, RegLocation rl_dest, int r_value) { 399feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell DCHECK_NE(rl_dest.location, kLocPhysReg); 400feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell int displacement = SRegOffset(rl_dest.s_reg_low); 401e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu bool is64Bit = rl_dest.wide != 0; 402feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell X86OpCode opcode = kX86Nop; 403feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell switch (op) { 404e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpSub: opcode = is64Bit ? kX86Sub64MR : kX86Sub32MR; break; 405e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpMov: opcode = is64Bit ? kX86Mov64MR : kX86Mov32MR; break; 406e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpCmp: opcode = is64Bit ? kX86Cmp64MR : kX86Cmp32MR; break; 407e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpAdd: opcode = is64Bit ? kX86Add64MR : kX86Add32MR; break; 408e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpAnd: opcode = is64Bit ? kX86And64MR : kX86And32MR; break; 409e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpOr: opcode = is64Bit ? kX86Or64MR : kX86Or32MR; break; 410e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpXor: opcode = is64Bit ? kX86Xor64MR : kX86Xor32MR; break; 411e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpLsl: opcode = is64Bit ? kX86Sal64MC : kX86Sal32MC; break; 412e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpLsr: opcode = is64Bit ? kX86Shr64MC : kX86Shr32MC; break; 413e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpAsr: opcode = is64Bit ? kX86Sar64MC : kX86Sar32MC; break; 414feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell default: 415feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell LOG(FATAL) << "Bad case in OpMemReg " << op; 416feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell break; 417feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell } 418b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LIR *l = NewLIR3(opcode, rs_rX86_SP_32.GetReg(), displacement, r_value); 4198dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mem_ref_type_ == ResourceMask::kDalvikReg) { 4208dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko AnnotateDalvikRegAccess(l, displacement >> 2, true /* is_load */, is64Bit /* is_64bit */); 4218dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko AnnotateDalvikRegAccess(l, displacement >> 2, false /* is_load */, is64Bit /* is_64bit */); 4228dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko } 423feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell return l; 424feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell} 425feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell 4262700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegMem(OpKind op, RegStorage r_dest, RegLocation rl_value) { 427feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell DCHECK_NE(rl_value.location, kLocPhysReg); 428e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu bool is64Bit = r_dest.Is64Bit(); 429feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell int displacement = SRegOffset(rl_value.s_reg_low); 430feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell X86OpCode opcode = kX86Nop; 431feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell switch (op) { 432e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpSub: opcode = is64Bit ? kX86Sub64RM : kX86Sub32RM; break; 433e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpMov: opcode = is64Bit ? kX86Mov64RM : kX86Mov32RM; break; 434e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpCmp: opcode = is64Bit ? kX86Cmp64RM : kX86Cmp32RM; break; 435e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpAdd: opcode = is64Bit ? kX86Add64RM : kX86Add32RM; break; 436e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpAnd: opcode = is64Bit ? kX86And64RM : kX86And32RM; break; 437e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpOr: opcode = is64Bit ? kX86Or64RM : kX86Or32RM; break; 438e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpXor: opcode = is64Bit ? kX86Xor64RM : kX86Xor32RM; break; 439e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu case kOpMul: opcode = is64Bit ? kX86Bkpt : kX86Imul32RM; break; 440feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell default: 441feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell LOG(FATAL) << "Bad case in OpRegMem " << op; 442feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell break; 443feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell } 444b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LIR *l = NewLIR3(opcode, r_dest.GetReg(), rs_rX86_SP_32.GetReg(), displacement); 4458dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mem_ref_type_ == ResourceMask::kDalvikReg) { 4468dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko AnnotateDalvikRegAccess(l, displacement >> 2, true /* is_load */, is64Bit /* is_64bit */); 4478dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko } 448feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell return l; 449b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers} 450e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 4512700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, 4522700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_src2) { 453e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu bool is64Bit = r_dest.Is64Bit(); 454fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (r_dest != r_src1 && r_dest != r_src2) { 4557934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom if (op == kOpAdd) { // lea special case, except can't encode rbp as base 456fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (r_src1 == r_src2) { 4571fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_dest, r_src1); 4581fd3346740dfb7f47be9922312b68a4227fada96buzbee return OpRegImm(kOpLsl, r_dest, 1); 4592700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee } else if (r_src1 != rs_rBP) { 460e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu return NewLIR5(is64Bit ? kX86Lea64RA : kX86Lea32RA, r_dest.GetReg(), 461e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu r_src1.GetReg() /* base */, r_src2.GetReg() /* index */, 462e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu 0 /* scale */, 0 /* disp */); 463b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 464e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu return NewLIR5(is64Bit ? kX86Lea64RA : kX86Lea32RA, r_dest.GetReg(), 465e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu r_src2.GetReg() /* base */, r_src1.GetReg() /* index */, 466e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu 0 /* scale */, 0 /* disp */); 467b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 468b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 4691fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_dest, r_src1); 4701fd3346740dfb7f47be9922312b68a4227fada96buzbee return OpRegReg(op, r_dest, r_src2); 471e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 472fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee } else if (r_dest == r_src1) { 4731fd3346740dfb7f47be9922312b68a4227fada96buzbee return OpRegReg(op, r_dest, r_src2); 474fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee } else { // r_dest == r_src2 475b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers switch (op) { 476b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpSub: // non-commutative 4771fd3346740dfb7f47be9922312b68a4227fada96buzbee OpReg(kOpNeg, r_dest); 478b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kOpAdd; 479b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 480b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpSbc: 481b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: { 4822700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage t_reg = AllocTemp(); 4831fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(t_reg, r_src1); 4841fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegReg(op, t_reg, r_src2); 4857a11ab09f93f54b1c07c0bf38dd65ed322e86bc6buzbee LIR* res = OpRegCopyNoInsert(r_dest, t_reg); 4867a11ab09f93f54b1c07c0bf38dd65ed322e86bc6buzbee AppendLIR(res); 4871fd3346740dfb7f47be9922312b68a4227fada96buzbee FreeTemp(t_reg); 488b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers return res; 489b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 490b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpAdd: // commutative 491b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpOr: 492b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpAdc: 493b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpAnd: 494b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpXor: 4954ee71b2df9eb74531d44528d028378bf0e90ecd7Pavel Vyssotski case kOpMul: 496b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 497b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 49852a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee LOG(FATAL) << "Bad case in OpRegRegReg " << op; 499e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 5001fd3346740dfb7f47be9922312b68a4227fada96buzbee return OpRegReg(op, r_dest, r_src1); 501b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 502e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 503e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 5042700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src, int value) { 505dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (op == kOpMul && !cu_->target64) { 506b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI; 5072700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR3(opcode, r_dest.GetReg(), r_src.GetReg(), value); 508dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina } else if (op == kOpAnd && !cu_->target64) { 509091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (value == 0xFF && r_src.Low4()) { 5102700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR2(kX86Movzx8RR, r_dest.GetReg(), r_src.GetReg()); 511b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } else if (value == 0xFFFF) { 5122700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR2(kX86Movzx16RR, r_dest.GetReg(), r_src.GetReg()); 513b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } 514b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 515fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (r_dest != r_src) { 5160b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe if ((false) && op == kOpLsl && value >= 0 && value <= 3) { // lea shift special case 5177caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers // TODO: fix bug in LEA encoding when disp == 0 5182700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR5(kX86Lea32RA, r_dest.GetReg(), r5sib_no_base /* base */, 5192700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee r_src.GetReg() /* index */, value /* scale */, 0 /* disp */); 5207934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (op == kOpAdd) { // lea add special case 5217e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu return NewLIR5(r_dest.Is64Bit() ? kX86Lea64RA : kX86Lea32RA, r_dest.GetReg(), 522b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers r_src.GetReg() /* base */, rs_rX86_SP_32.GetReg()/*r4sib_no_index*/ /* index */, 523e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu 0 /* scale */, value /* disp */); 524e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 5251fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_dest, r_src); 526b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 5271fd3346740dfb7f47be9922312b68a4227fada96buzbee return OpRegImm(op, r_dest, value); 528e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 529e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 530dd7624d2b9e599d57762d12031b10b89defc9807Ian RogersLIR* X86Mir2Lir::OpThreadMem(OpKind op, ThreadOffset<4> thread_offset) { 5312f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe DCHECK_EQ(kX86, cu_->instruction_set); 5322f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe X86OpCode opcode = kX86Bkpt; 5332f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe switch (op) { 5342f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe case kOpBlx: opcode = kX86CallT; break; 5352f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe case kOpBx: opcode = kX86JmpT; break; 5362f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe default: 5372f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe LOG(FATAL) << "Bad opcode: " << op; 5382f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe break; 5392f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe } 5402f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe return NewLIR1(opcode, thread_offset.Int32Value()); 5412f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe} 5422f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe 5432f244e9faccfcca68af3c5484c397a01a1c3a342Andreas GampeLIR* X86Mir2Lir::OpThreadMem(OpKind op, ThreadOffset<8> thread_offset) { 5442f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe DCHECK_EQ(kX86_64, cu_->instruction_set); 5456cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers X86OpCode opcode = kX86Bkpt; 5466cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers switch (op) { 5476cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers case kOpBlx: opcode = kX86CallT; break; 54860d7a65f7fb60f502160a2e479e86014c7787553Brian Carlstrom case kOpBx: opcode = kX86JmpT; break; 5496cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers default: 5506cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers LOG(FATAL) << "Bad opcode: " << op; 5516cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers break; 5526cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers } 553468532ea115657709bc32ee498e701a4c71762d4Ian Rogers return NewLIR1(opcode, thread_offset.Int32Value()); 5546cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers} 5556cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers 5562700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) { 5576cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers X86OpCode opcode = kX86Bkpt; 5586cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers switch (op) { 5596cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers case kOpBlx: opcode = kX86CallM; break; 5606cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers default: 5616cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers LOG(FATAL) << "Bad opcode: " << op; 5626cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers break; 5636cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers } 5642700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR2(opcode, r_base.GetReg(), disp); 5656cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers} 5666cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers 5672700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) { 5684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee int32_t val_lo = Low32Bits(value); 5694ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee int32_t val_hi = High32Bits(value); 5702700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int32_t low_reg_val = r_dest.IsPair() ? r_dest.GetLowReg() : r_dest.GetReg(); 571e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee LIR *res; 572e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell bool is_fp = r_dest.IsFloat(); 5732700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee // TODO: clean this up once we fully recognize 64-bit storage containers. 5742700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee if (is_fp) { 5750e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov DCHECK(r_dest.IsDouble()); 5764ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee if (value == 0) { 57727dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell return NewLIR2(kX86XorpdRR, low_reg_val, low_reg_val); 5781961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko } else if (pc_rel_base_reg_.Valid() || cu_->target64) { 57967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // We will load the value from the literal area. 58067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell LIR* data_target = ScanLiteralPoolWide(literal_list_, val_lo, val_hi); 5812cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier if (data_target == nullptr) { 58267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell data_target = AddWideData(&literal_list_, val_lo, val_hi); 58367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 58467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 58567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Load the proper value from the literal area. 58627dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell // We don't know the proper offset for the value, so pick one that 58727dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell // will force 4 byte offset. We will fix this up in the assembler 58827dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell // later to have the right value. 5898dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral); 59027dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell if (cu_->target64) { 59127dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell res = NewLIR3(kX86MovsdRM, low_reg_val, kRIPReg, 256 /* bogus */); 59227dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell } else { 5931961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko // Get the PC to a register and get the anchor. 5941961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko LIR* anchor; 5951961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko RegStorage r_pc = GetPcAndAnchor(&anchor); 59627dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell 5971961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko res = LoadBaseDisp(r_pc, kDummy32BitOffset, RegStorage::FloatSolo64(low_reg_val), 59827dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell kDouble, kNotVolatile); 5991961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko res->operands[4] = WrapPointer(anchor); 6001961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko if (IsTemp(r_pc)) { 6011961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko FreeTemp(r_pc); 6021961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko } 60327dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell } 60467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell res->target = data_target; 60567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell res->flags.fixup = kFixupLoad; 606b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } else { 6070e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov if (r_dest.IsPair()) { 6080e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov if (val_lo == 0) { 6090e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov res = NewLIR2(kX86XorpsRR, low_reg_val, low_reg_val); 6100e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov } else { 6110e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov res = LoadConstantNoClobber(RegStorage::FloatSolo32(low_reg_val), val_lo); 6120e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov } 6130e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov if (val_hi != 0) { 6140e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov RegStorage r_dest_hi = AllocTempDouble(); 6150e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov LoadConstantNoClobber(r_dest_hi, val_hi); 6160e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov NewLIR2(kX86PunpckldqRR, low_reg_val, r_dest_hi.GetReg()); 6170e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov FreeTemp(r_dest_hi); 6180e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov } 619b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } else { 6200e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov RegStorage r_temp = AllocTypedTempWide(false, kCoreReg); 6210e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov res = LoadConstantWide(r_temp, value); 6220e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov OpRegCopyWide(r_dest, r_temp); 6230e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov FreeTemp(r_temp); 624b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } 625b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } 626b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } else { 627e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu if (r_dest.IsPair()) { 628e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu res = LoadConstantNoClobber(r_dest.GetLow(), val_lo); 629e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu LoadConstantNoClobber(r_dest.GetHigh(), val_hi); 630e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu } else { 6315192cbb12856b12620dc346758605baaa1469cedYixin Shou if (value == 0) { 6321c55703526827b5fc63f5d4b8477f36574649342Serguei Katkov res = NewLIR2(kX86Xor64RR, r_dest.GetReg(), r_dest.GetReg()); 6335192cbb12856b12620dc346758605baaa1469cedYixin Shou } else if (value >= INT_MIN && value <= INT_MAX) { 6345192cbb12856b12620dc346758605baaa1469cedYixin Shou res = NewLIR2(kX86Mov64RI32, r_dest.GetReg(), val_lo); 6355192cbb12856b12620dc346758605baaa1469cedYixin Shou } else { 6365192cbb12856b12620dc346758605baaa1469cedYixin Shou res = NewLIR3(kX86Mov64RI64, r_dest.GetReg(), val_hi, val_lo); 637e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu } 638e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu } 639b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } 640e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee return res; 641e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 642e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 6432700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::LoadBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale, 6443bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko int displacement, RegStorage r_dest, OpSize size) { 6452cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier LIR *load = nullptr; 6462cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier LIR *load2 = nullptr; 6472700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee bool is_array = r_index.Valid(); 648091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee bool pair = r_dest.IsPair(); 649091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee bool is64bit = ((size == k64) || (size == kDouble)); 650b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode opcode = kX86Nop; 651b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers switch (size) { 652695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee case k64: 653b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kDouble: 654091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest.IsFloat()) { 655fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86MovsdRA : kX86MovsdRM; 656e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu } else if (!pair) { 657e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu opcode = is_array ? kX86Mov64RA : kX86Mov64RM; 658b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 659fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Mov32RA : kX86Mov32RM; 660b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 661b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // TODO: double store is to unaligned address 662b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers DCHECK_EQ((displacement & 0x3), 0); 663b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 6649ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kWord: 665dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 6669ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko opcode = is_array ? kX86Mov64RA : kX86Mov64RM; 6679ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko CHECK_EQ(is_array, false); 6689ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko CHECK_EQ(r_dest.IsFloat(), false); 6699ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko break; 670fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers } 671fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers FALLTHROUGH_INTENDED; // else fall-through to k32 case 672695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee case k32: 673b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kSingle: 674695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee case kReference: // TODO: update for reference decompression on 64-bit targets. 675fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Mov32RA : kX86Mov32RM; 676091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest.IsFloat()) { 677fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86MovssRA : kX86MovssRM; 678091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(r_dest.IsFloat()); 679b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 680b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers DCHECK_EQ((displacement & 0x3), 0); 681b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 682b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kUnsignedHalf: 683fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Movzx16RA : kX86Movzx16RM; 684b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers DCHECK_EQ((displacement & 0x1), 0); 685b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 686b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kSignedHalf: 687fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Movsx16RA : kX86Movsx16RM; 688b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers DCHECK_EQ((displacement & 0x1), 0); 689b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 690b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kUnsignedByte: 691fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Movzx8RA : kX86Movzx8RM; 692b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 693b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kSignedByte: 694fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Movsx8RA : kX86Movsx8RM; 695b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 696b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 69752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody"; 698b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 699b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers 700fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!is_array) { 701b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (!pair) { 7022700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee load = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), displacement + LOWORD_OFFSET); 703e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } else { 704091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!r_dest.IsFloat()); // Make sure we're not still using a pair here. 705091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_base == r_dest.GetLow()) { 70669dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison load = NewLIR3(opcode, r_dest.GetHighReg(), r_base.GetReg(), 707fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao displacement + HIWORD_OFFSET); 70869dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison load2 = NewLIR3(opcode, r_dest.GetLowReg(), r_base.GetReg(), displacement + LOWORD_OFFSET); 709fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 710091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load = NewLIR3(opcode, r_dest.GetLowReg(), r_base.GetReg(), displacement + LOWORD_OFFSET); 711091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load2 = NewLIR3(opcode, r_dest.GetHighReg(), r_base.GetReg(), 712fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao displacement + HIWORD_OFFSET); 713fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 714e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 7158dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mem_ref_type_ == ResourceMask::kDalvikReg) { 716b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers DCHECK_EQ(r_base, cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32); 7171fd3346740dfb7f47be9922312b68a4227fada96buzbee AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, 71802031b185b4653e6c72e21f7a51238b903f6d638buzbee true /* is_load */, is64bit); 719f7d9ad39541dd09030e26d54d3b73a076f90cc74Ian Rogers if (pair) { 7201fd3346740dfb7f47be9922312b68a4227fada96buzbee AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2, 721fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee true /* is_load */, is64bit); 722b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 723e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 724b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 725b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (!pair) { 7262700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee load = NewLIR5(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg(), scale, 727a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee displacement + LOWORD_OFFSET); 728b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 729091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!r_dest.IsFloat()); // Make sure we're not still using a pair here. 730091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_base == r_dest.GetLow()) { 731091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest.GetHigh() == r_index) { 732ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell // We can't use either register for the first load. 7332700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage temp = AllocTemp(); 73469dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison load = NewLIR5(opcode, temp.GetReg(), r_base.GetReg(), r_index.GetReg(), scale, 735ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + HIWORD_OFFSET); 73669dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison load2 = NewLIR5(opcode, r_dest.GetLowReg(), r_base.GetReg(), r_index.GetReg(), scale, 737ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + LOWORD_OFFSET); 738091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee OpRegCopy(r_dest.GetHigh(), temp); 739ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell FreeTemp(temp); 740ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell } else { 74169dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison load = NewLIR5(opcode, r_dest.GetHighReg(), r_base.GetReg(), r_index.GetReg(), scale, 742ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + HIWORD_OFFSET); 74369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison load2 = NewLIR5(opcode, r_dest.GetLowReg(), r_base.GetReg(), r_index.GetReg(), scale, 744ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + LOWORD_OFFSET); 745ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell } 746fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 747091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest.GetLow() == r_index) { 748ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell // We can't use either register for the first load. 7492700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage temp = AllocTemp(); 7502700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee load = NewLIR5(opcode, temp.GetReg(), r_base.GetReg(), r_index.GetReg(), scale, 751ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + LOWORD_OFFSET); 752091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load2 = NewLIR5(opcode, r_dest.GetHighReg(), r_base.GetReg(), r_index.GetReg(), scale, 753ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + HIWORD_OFFSET); 754091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee OpRegCopy(r_dest.GetLow(), temp); 755ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell FreeTemp(temp); 756ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell } else { 757091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load = NewLIR5(opcode, r_dest.GetLowReg(), r_base.GetReg(), r_index.GetReg(), scale, 758ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + LOWORD_OFFSET); 759091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load2 = NewLIR5(opcode, r_dest.GetHighReg(), r_base.GetReg(), r_index.GetReg(), scale, 760ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + HIWORD_OFFSET); 761ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell } 762fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 763b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 764b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 765b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers 7662cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // Always return first load generated as this might cause a fault if base is null. 767b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers return load; 768e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 769e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 7705772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao/* Load value from base + scaled index. */ 7712700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, 7722700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int scale, OpSize size) { 7733bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko return LoadBaseIndexedDisp(r_base, r_index, scale, 0, r_dest, size); 7745772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao} 7755772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao 7763c12c512faf6837844d5465b23b9410889e5eb11Andreas GampeLIR* X86Mir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, 7773c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe OpSize size, VolatileKind is_volatile) { 778674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // LoadBaseDisp() will emit correct insn for atomic load on x86 779674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // assuming r_dest is correctly prepared using RegClassForFieldLoadStore(). 780674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko 7813c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe LIR* load = LoadBaseIndexedDisp(r_base, RegStorage::InvalidReg(), 0, displacement, r_dest, 7823c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe size); 7833c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe 7843c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe if (UNLIKELY(is_volatile == kVolatile)) { 78548f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm GenMemBarrier(kLoadAny); // Only a scheduling barrier. 7863c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe } 7873c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe 7883c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe return load; 789e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 790e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 7912700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale, 792b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler int displacement, RegStorage r_src, OpSize size, 793b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler int opt_flags) { 7942cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier LIR *store = nullptr; 7952cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier LIR *store2 = nullptr; 7962700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee bool is_array = r_index.Valid(); 797091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee bool pair = r_src.IsPair(); 798091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee bool is64bit = (size == k64) || (size == kDouble); 799b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler bool consider_non_temporal = false; 800b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler 801b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers X86OpCode opcode = kX86Nop; 802b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers switch (size) { 803695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee case k64: 804b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler consider_non_temporal = true; 805fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers FALLTHROUGH_INTENDED; 806b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kDouble: 807091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_src.IsFloat()) { 808fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86MovsdAR : kX86MovsdMR; 809e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu } else if (!pair) { 810e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu opcode = is_array ? kX86Mov64AR : kX86Mov64MR; 811b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 812e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu opcode = is_array ? kX86Mov32AR : kX86Mov32MR; 813b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 814b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // TODO: double store is to unaligned address 815b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers DCHECK_EQ((displacement & 0x3), 0); 816b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 8179ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kWord: 818dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 8199ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko opcode = is_array ? kX86Mov64AR : kX86Mov64MR; 8209ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko CHECK_EQ(is_array, false); 8219ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko CHECK_EQ(r_src.IsFloat(), false); 822b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler consider_non_temporal = true; 8239ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko break; 824fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers } 825fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers FALLTHROUGH_INTENDED; // else fall-through to k32 case 826695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee case k32: 827b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kSingle: 828695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee case kReference: 829fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Mov32AR : kX86Mov32MR; 830091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_src.IsFloat()) { 831fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86MovssAR : kX86MovssMR; 832091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(r_src.IsSingle()); 833b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 834b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers DCHECK_EQ((displacement & 0x3), 0); 835b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler consider_non_temporal = true; 836b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 837b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kUnsignedHalf: 838b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kSignedHalf: 839fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Mov16AR : kX86Mov16MR; 840b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers DCHECK_EQ((displacement & 0x1), 0); 841b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 842b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kUnsignedByte: 843b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kSignedByte: 844fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Mov8AR : kX86Mov8MR; 845b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 846b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 84700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee LOG(FATAL) << "Bad case in StoreBaseIndexedDispBody"; 848b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 849b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers 850b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler // Handle non temporal hint here. 851b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler if (consider_non_temporal && ((opt_flags & MIR_STORE_NON_TEMPORAL) != 0)) { 852b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler switch (opcode) { 853b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler // We currently only handle 32/64 bit moves here. 854b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler case kX86Mov64AR: 855b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler opcode = kX86Movnti64AR; 856b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler break; 857b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler case kX86Mov64MR: 858b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler opcode = kX86Movnti64MR; 859b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler break; 860b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler case kX86Mov32AR: 861b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler opcode = kX86Movnti32AR; 862b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler break; 863b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler case kX86Mov32MR: 864b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler opcode = kX86Movnti32MR; 865b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler break; 866b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler default: 867b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler // Do nothing here. 868b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler break; 869b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler } 870b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler } 871b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler 872fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!is_array) { 873b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers if (!pair) { 8742700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee store = NewLIR3(opcode, r_base.GetReg(), displacement + LOWORD_OFFSET, r_src.GetReg()); 875b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } else { 876091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!r_src.IsFloat()); // Make sure we're not still using a pair here. 877091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee store = NewLIR3(opcode, r_base.GetReg(), displacement + LOWORD_OFFSET, r_src.GetLowReg()); 878091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee store2 = NewLIR3(opcode, r_base.GetReg(), displacement + HIWORD_OFFSET, r_src.GetHighReg()); 879e296248a124ed8287b38a9225463696c18d84cd6jeffhao } 8808dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mem_ref_type_ == ResourceMask::kDalvikReg) { 881b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers DCHECK_EQ(r_base, cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32); 8821fd3346740dfb7f47be9922312b68a4227fada96buzbee AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, 88302031b185b4653e6c72e21f7a51238b903f6d638buzbee false /* is_load */, is64bit); 884e296248a124ed8287b38a9225463696c18d84cd6jeffhao if (pair) { 8851fd3346740dfb7f47be9922312b68a4227fada96buzbee AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2, 886fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee false /* is_load */, is64bit); 887e296248a124ed8287b38a9225463696c18d84cd6jeffhao } 888b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } 889b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 890b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers if (!pair) { 8912700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee store = NewLIR5(opcode, r_base.GetReg(), r_index.GetReg(), scale, 8922700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee displacement + LOWORD_OFFSET, r_src.GetReg()); 893b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } else { 894091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!r_src.IsFloat()); // Make sure we're not still using a pair here. 8952700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee store = NewLIR5(opcode, r_base.GetReg(), r_index.GetReg(), scale, 896091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee displacement + LOWORD_OFFSET, r_src.GetLowReg()); 8972700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee store2 = NewLIR5(opcode, r_base.GetReg(), r_index.GetReg(), scale, 898091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee displacement + HIWORD_OFFSET, r_src.GetHighReg()); 899e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 900b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 901b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers return store; 902e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 903e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 904c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers/* store value base base + scaled index. */ 9052700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, 9063c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe int scale, OpSize size) { 9073bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko return StoreBaseIndexedDisp(r_base, r_index, scale, 0, r_src, size); 908c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers} 909c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers 9103c12c512faf6837844d5465b23b9410889e5eb11Andreas GampeLIR* X86Mir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src, OpSize size, 9113c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe VolatileKind is_volatile) { 9123c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe if (UNLIKELY(is_volatile == kVolatile)) { 91348f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm GenMemBarrier(kAnyStore); // Only a scheduling barrier. 9143c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe } 9153c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe 916674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // StoreBaseDisp() will emit correct insn for atomic store on x86 917674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // assuming r_dest is correctly prepared using RegClassForFieldLoadStore(). 91837f05ef45e0393de812d51261dc293240c17294dFred Shih // x86 only allows registers EAX-EDX to be used as byte registers, if the input src is not 91937f05ef45e0393de812d51261dc293240c17294dFred Shih // valid, allocate a temp. 92037f05ef45e0393de812d51261dc293240c17294dFred Shih bool allocated_temp = false; 92137f05ef45e0393de812d51261dc293240c17294dFred Shih if (size == kUnsignedByte || size == kSignedByte) { 92237f05ef45e0393de812d51261dc293240c17294dFred Shih if (!cu_->target64 && !r_src.Low4()) { 92337f05ef45e0393de812d51261dc293240c17294dFred Shih RegStorage r_input = r_src; 92437f05ef45e0393de812d51261dc293240c17294dFred Shih r_src = AllocateByteRegister(); 92537f05ef45e0393de812d51261dc293240c17294dFred Shih OpRegCopy(r_src, r_input); 92637f05ef45e0393de812d51261dc293240c17294dFred Shih allocated_temp = true; 92737f05ef45e0393de812d51261dc293240c17294dFred Shih } 92837f05ef45e0393de812d51261dc293240c17294dFred Shih } 929674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko 9303c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe LIR* store = StoreBaseIndexedDisp(r_base, RegStorage::InvalidReg(), 0, displacement, r_src, size); 9313c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe 9323c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe if (UNLIKELY(is_volatile == kVolatile)) { 93348f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm // A volatile load might follow the volatile store so insert a StoreLoad barrier. 93448f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm // This does require a fence, even on x86. 93548f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm GenMemBarrier(kAnyAny); 9363c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe } 9373c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe 93837f05ef45e0393de812d51261dc293240c17294dFred Shih if (allocated_temp) { 93937f05ef45e0393de812d51261dc293240c17294dFred Shih FreeTemp(r_src); 94037f05ef45e0393de812d51261dc293240c17294dFred Shih } 94137f05ef45e0393de812d51261dc293240c17294dFred Shih 9423c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe return store; 943e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 944e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 9452700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpCmpMemImmBranch(ConditionCode cond, RegStorage temp_reg, RegStorage base_reg, 94669dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison int offset, int check_value, LIR* target, LIR** compare) { 9476a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(temp_reg); // Comparison performed directly with memory. 9486a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers LIR* inst = NewLIR3(IS_SIMM8(check_value) ? kX86Cmp32MI8 : kX86Cmp32MI, base_reg.GetReg(), 9496a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers offset, check_value); 9506a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers if (compare != nullptr) { 9516a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers *compare = inst; 9526a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers } 9536a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers LIR* branch = OpCondBranch(cond, target); 9546a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers return branch; 955766e9295d2c34cd1846d81610c9045b5d5093dddMark Mendell} 956766e9295d2c34cd1846d81610c9045b5d5093dddMark Mendell 9571961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Markovoid X86Mir2Lir::AnalyzeMIR(RefCounts* core_counts, MIR* mir, uint32_t weight) { 9581961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko if (cu_->target64) { 9591961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko Mir2Lir::AnalyzeMIR(core_counts, mir, weight); 96067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell return; 96167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 96267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 9631961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko int opcode = mir->dalvikInsn.opcode; 9641961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko bool uses_pc_rel_load = false; 96567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell switch (opcode) { 96667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Instructions referencing doubles. 96767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::CMPL_DOUBLE: 96867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::CMPG_DOUBLE: 96967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::NEG_DOUBLE: 97067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::ADD_DOUBLE: 97167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::SUB_DOUBLE: 97267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::MUL_DOUBLE: 97367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::DIV_DOUBLE: 97467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::REM_DOUBLE: 97567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::ADD_DOUBLE_2ADDR: 97667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::SUB_DOUBLE_2ADDR: 97767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::MUL_DOUBLE_2ADDR: 97867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::DIV_DOUBLE_2ADDR: 97967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::REM_DOUBLE_2ADDR: 9801961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko case kMirOpFusedCmplDouble: 9811961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko case kMirOpFusedCmpgDouble: 9821961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko uses_pc_rel_load = AnalyzeFPInstruction(opcode, mir); 98367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell break; 98455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 9851961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko // Packed switch needs the PC-relative pointer if it's large. 98667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::PACKED_SWITCH: 9871961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko if (mir_graph_->GetTable(mir, mir->dalvikInsn.vB)[1] > kSmallSwitchThreshold) { 9881961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko uses_pc_rel_load = true; 98927dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell } 99067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell break; 9911961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko 9921961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko case kMirOpConstVector: 9931961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko uses_pc_rel_load = true; 9941961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko break; 9951961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko case kMirOpPackedMultiply: 9961961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko case kMirOpPackedShiftLeft: 9971961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko case kMirOpPackedSignedShiftRight: 9981961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko case kMirOpPackedUnsignedShiftRight: 9991961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko { 10001961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko // Byte emulation requires constants from the literal pool. 10011961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 10021961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko if (opsize == kSignedByte || opsize == kUnsignedByte) { 10031961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko uses_pc_rel_load = true; 10041961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko } 10051961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko } 10061961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko break; 10071961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko 10087071c8d5885175a746723a3b38a347855965be08Yixin Shou case Instruction::INVOKE_STATIC: 1009e5beb18ca08962ed271f4c1f703e0c52bc8805f3Razvan A Lupusoru case Instruction::INVOKE_STATIC_RANGE: 10101961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko if (mir_graph_->GetMethodLoweringInfo(mir).IsIntrinsic()) { 10111961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko uses_pc_rel_load = AnalyzeInvokeStaticIntrinsic(mir); 10121961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko break; 10131961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko } 10141961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko FALLTHROUGH_INTENDED; 101567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell default: 10161961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko Mir2Lir::AnalyzeMIR(core_counts, mir, weight); 101767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell break; 101867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 10191961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko 10201961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko if (uses_pc_rel_load) { 10211961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko DCHECK(pc_rel_temp_ != nullptr); 10221961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko core_counts[SRegToPMap(pc_rel_temp_->s_reg_low)].count += weight; 10231961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko } 102467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell} 102567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 10261961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Markobool X86Mir2Lir::AnalyzeFPInstruction(int opcode, MIR* mir) { 10271961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko DCHECK(!cu_->target64); 102867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Look at all the uses, and see if they are double constants. 1029cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler uint64_t attrs = MIRGraph::GetDataFlowAttributes(static_cast<Instruction::Code>(opcode)); 103067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell int next_sreg = 0; 103167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (attrs & DF_UA) { 103267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (attrs & DF_A_WIDE) { 10331961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko if (AnalyzeDoubleUse(mir_graph_->GetSrcWide(mir, next_sreg))) { 10341961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko return true; 10351961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko } 103667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell next_sreg += 2; 103767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } else { 103867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell next_sreg++; 103967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 104067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 104167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (attrs & DF_UB) { 104267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (attrs & DF_B_WIDE) { 10431961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko if (AnalyzeDoubleUse(mir_graph_->GetSrcWide(mir, next_sreg))) { 10441961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko return true; 10451961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko } 104667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell next_sreg += 2; 104767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } else { 104867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell next_sreg++; 104967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 105067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 105167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (attrs & DF_UC) { 105267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (attrs & DF_C_WIDE) { 10531961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko if (AnalyzeDoubleUse(mir_graph_->GetSrcWide(mir, next_sreg))) { 10541961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko return true; 10551961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko } 105667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 105767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 10581961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko return false; 105967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell} 106067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 10611961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Markoinline bool X86Mir2Lir::AnalyzeDoubleUse(RegLocation use) { 10620e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov // If this is a double literal, we will want it in the literal pool on 32b platforms. 10631961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko DCHECK(!cu_->target64); 10641961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko return use.is_const; 10651961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko} 10661961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko 10671961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Markobool X86Mir2Lir::AnalyzeInvokeStaticIntrinsic(MIR* mir) { 10681961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko // 64 bit RIP addressing doesn't need this analysis. 10691961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko DCHECK(!cu_->target64); 10701961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko 10711961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko // Retrieve the type of the intrinsic. 10721961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko MethodReference method_ref = mir_graph_->GetMethodLoweringInfo(mir).GetTargetMethod(); 10731961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko DCHECK(cu_->compiler_driver->GetMethodInlinerMap() != nullptr); 10741961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko DexFileMethodInliner* method_inliner = 10751961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko cu_->compiler_driver->GetMethodInlinerMap()->GetMethodInliner(method_ref.dex_file); 10761961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko InlineMethod method; 10771961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko bool is_intrinsic = method_inliner->IsIntrinsic(method_ref.dex_method_index, &method); 10781961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko DCHECK(is_intrinsic); 10791961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko 10801961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko switch (method.opcode) { 10811961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko case kIntrinsicAbsDouble: 10821961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko case kIntrinsicMinMaxDouble: 10831961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko return true; 10841961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko default: 10851961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko return false; 108667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 108767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell} 108867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 10896a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan RogersRegLocation X86Mir2Lir::UpdateLocTyped(RegLocation loc) { 109030adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee loc = UpdateLoc(loc); 109130adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee if ((loc.location == kLocPhysReg) && (loc.fp != loc.reg.IsFloat())) { 109230adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee if (GetRegInfo(loc.reg)->IsTemp()) { 109330adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee Clobber(loc.reg); 109430adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee FreeTemp(loc.reg); 109530adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee loc.reg = RegStorage::InvalidReg(); 109630adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee loc.location = kLocDalvikFrame; 109730adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee } 109830adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee } 1099e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu DCHECK(CheckCorePoolSanity()); 110030adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee return loc; 110130adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee} 110230adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee 11036a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan RogersRegLocation X86Mir2Lir::UpdateLocWideTyped(RegLocation loc) { 110430adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee loc = UpdateLocWide(loc); 110530adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee if ((loc.location == kLocPhysReg) && (loc.fp != loc.reg.IsFloat())) { 110630adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee if (GetRegInfo(loc.reg)->IsTemp()) { 110730adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee Clobber(loc.reg); 110830adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee FreeTemp(loc.reg); 110930adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee loc.reg = RegStorage::InvalidReg(); 111030adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee loc.location = kLocDalvikFrame; 111130adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee } 111230adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee } 1113e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu DCHECK(CheckCorePoolSanity()); 111430adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee return loc; 111530adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee} 11167071c8d5885175a746723a3b38a347855965be08Yixin Shou 11171961b609bfefaedb71cee3651c4f931cc3e7393dVladimir MarkoLIR* X86Mir2Lir::InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) { 11181961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko UNUSED(r_tgt); // Call to absolute memory location doesn't need a temporary target register. 11190e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov if (cu_->target64) { 11201961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko return OpThreadMem(op, GetThreadOffset<8>(trampoline)); 11211961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko } else { 11221961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko return OpThreadMem(op, GetThreadOffset<4>(trampoline)); 11230e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov } 11241961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko} 11250e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov 11261961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Markovoid X86Mir2Lir::CountRefs(RefCounts* core_counts, RefCounts* fp_counts, size_t num_regs) { 11271961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko // Start with the default counts. 11281961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko Mir2Lir::CountRefs(core_counts, fp_counts, num_regs); 11291961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko 11301961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko if (pc_rel_temp_ != nullptr) { 11311961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko // Now, if the dex cache array base temp is used only once outside any loops (weight = 1), 11321961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko // avoid the promotion, otherwise boost the weight by factor 2 because the full PC-relative 11331961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko // load sequence is 3 instructions long and by promoting the PC base we save 2 instructions 11341961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko // per use. 11351961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko int p_map_idx = SRegToPMap(pc_rel_temp_->s_reg_low); 11361961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko if (core_counts[p_map_idx].count == 1) { 11371961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko core_counts[p_map_idx].count = 0; 11381961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko } else { 11391961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko core_counts[p_map_idx].count *= 2; 11407071c8d5885175a746723a3b38a347855965be08Yixin Shou } 11417071c8d5885175a746723a3b38a347855965be08Yixin Shou } 11427071c8d5885175a746723a3b38a347855965be08Yixin Shou} 1143984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe 11441961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Markovoid X86Mir2Lir::DoPromotion() { 11451961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko if (!cu_->target64) { 11461961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko pc_rel_temp_ = mir_graph_->GetNewCompilerTemp(kCompilerTempBackend, false); 11471961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko } 11481961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko 11491961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko Mir2Lir::DoPromotion(); 11501961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko 11511961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko if (pc_rel_temp_ != nullptr) { 11521961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko // Now, if the dex cache array base temp is promoted, remember the register but 11531961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko // always remove the temp's stack location to avoid unnecessarily bloating the stack. 11541961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko pc_rel_base_reg_ = mir_graph_->reg_location_[pc_rel_temp_->s_reg_low].reg; 11551961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko DCHECK(!pc_rel_base_reg_.Valid() || !pc_rel_base_reg_.IsFloat()); 11561961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko mir_graph_->RemoveLastCompilerTemp(kCompilerTempBackend, false, pc_rel_temp_); 11571961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko pc_rel_temp_ = nullptr; 1158984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 1159984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe} 1160984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe 1161e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} // namespace art 1162