utility_x86.cc revision 35ba7f3a78d38885ec54e61ed060d2771eeceea7
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" 187940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h" 1967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell#include "dex/dataflow_iterator-inl.h" 20641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "x86_lir.h" 211bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 22e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbeenamespace art { 23e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 24b046e16d8b8da318d6055f9308950131f1255e08buzbee/* This file contains codegen for the X86 ISA */ 25e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 262700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) { 27a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int opcode; 28a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* must be both DOUBLE or both not DOUBLE */ 29091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(r_dest.IsFloat() || r_src.IsFloat()); 30091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK_EQ(r_dest.IsDouble(), r_src.IsDouble()); 31091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest.IsDouble()) { 32a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee opcode = kX86MovsdRR; 33a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 34091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest.IsSingle()) { 35091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_src.IsSingle()) { 36a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee opcode = kX86MovssRR; 37a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { // Fpr <- Gpr 38a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee opcode = kX86MovdxrRR; 39a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 40a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { // Gpr <- Fpr 41091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(r_src.IsSingle()) << "Raw: 0x" << std::hex << r_src.GetRawBits(); 42a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee opcode = kX86MovdrxRR; 43e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 44a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 45ec13743da80a80c1817cf6660c28917fc28846bcbuzbee DCHECK_NE((EncodingMap[opcode].flags & IS_BINARY_OP), 0ULL); 462700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest.GetReg(), r_src.GetReg()); 47fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (r_dest == r_src) { 48fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee res->flags.is_nop = true; 49a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 50a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return res; 51e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 52e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 532ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::InexpensiveConstantInt(int32_t value) { 54e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee return true; 55e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee} 56e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee 572ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::InexpensiveConstantFloat(int32_t value) { 584ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee return false; 594ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee} 604ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee 612ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::InexpensiveConstantLong(int64_t value) { 624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee return true; 634ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee} 644ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee 652ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::InexpensiveConstantDouble(int64_t value) { 6667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell return value == 0; 674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee} 684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee 69e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee/* 70e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * Load a immediate using a shortcut if possible; otherwise 71e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * grab from the per-translation literal pool. If target is 72e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * a high register, build constant into a low register and copy. 73e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * 74e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * No additional register clobbering operation performed. Use this version when 75fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * 1) r_dest is freshly returned from AllocTemp or 76e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * 2) The codegen is under fixed register usage 77e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee */ 782700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) { 792700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_dest_save = r_dest; 80091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest.IsFloat()) { 81b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers if (value == 0) { 822700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR2(kX86XorpsRR, r_dest.GetReg(), r_dest.GetReg()); 83b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } 841fd3346740dfb7f47be9922312b68a4227fada96buzbee r_dest = AllocTemp(); 856cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers } 86e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 87b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers LIR *res; 886cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers if (value == 0) { 892700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee res = NewLIR2(kX86Xor32RR, r_dest.GetReg(), r_dest.GetReg()); 906cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers } else { 912e9f7ed8d00271cb1cf082d68b4f4bc60702d6ecIan Rogers // Note, there is no byte immediate form of a 32 bit immediate move. 9296992e8f2eddba05dc38a15cc7d4e705e8db4022Dmitry Petrochenko if (r_dest.Is64Bit()) { 9396992e8f2eddba05dc38a15cc7d4e705e8db4022Dmitry Petrochenko res = NewLIR2(kX86Mov64RI, r_dest.GetReg(), value); 9496992e8f2eddba05dc38a15cc7d4e705e8db4022Dmitry Petrochenko } else { 9596992e8f2eddba05dc38a15cc7d4e705e8db4022Dmitry Petrochenko res = NewLIR2(kX86Mov32RI, r_dest.GetReg(), value); 9696992e8f2eddba05dc38a15cc7d4e705e8db4022Dmitry Petrochenko } 976cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers } 98e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 99091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest_save.IsFloat()) { 1002700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee NewLIR2(kX86MovdxrRR, r_dest_save.GetReg(), r_dest.GetReg()); 1011fd3346740dfb7f47be9922312b68a4227fada96buzbee FreeTemp(r_dest); 1026cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers } 103e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 1046cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers return res; 105e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 106e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 1072ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* X86Mir2Lir::OpUnconditionalBranch(LIR* target) { 108df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom LIR* res = NewLIR1(kX86Jmp8, 0 /* offset to be patched during assembly*/); 10902031b185b4653e6c72e21f7a51238b903f6d638buzbee res->target = target; 11002031b185b4653e6c72e21f7a51238b903f6d638buzbee return res; 111e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 112e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 1132ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* X86Mir2Lir::OpCondBranch(ConditionCode cc, LIR* target) { 1141fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch = NewLIR2(kX86Jcc8, 0 /* offset to be patched */, 11552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee X86ConditionEncoding(cc)); 116b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers branch->target = target; 117b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers return branch; 118a7678db092ac6bb79f7cad490099a1015fbbc714buzbee} 119a7678db092ac6bb79f7cad490099a1015fbbc714buzbee 1202700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpReg(OpKind op, RegStorage r_dest_src) { 121b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode opcode = kX86Bkpt; 122b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers switch (op) { 123b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpNeg: opcode = kX86Neg32R; break; 1241395b1e06c1d0ff5155b0c5d113ad3bd6f163c07jeffhao case kOpNot: opcode = kX86Not32R; break; 125a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko case kOpRev: opcode = kX86Bswap32R; break; 126b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpBlx: opcode = kX86CallR; break; 127b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 12852a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee LOG(FATAL) << "Bad case in OpReg " << op; 129b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 1302700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR1(opcode, r_dest_src.GetReg()); 131e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 132e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 1332700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) { 134b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode opcode = kX86Bkpt; 135fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bool byte_imm = IS_SIMM8(value); 136091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!r_dest_src1.IsFloat()); 1379ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko if (r_dest_src1.Is64Bit()) { 1389ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko switch (op) { 1399ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpAdd: opcode = byte_imm ? kX86Add64RI8 : kX86Add64RI; break; 1409ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpSub: opcode = byte_imm ? kX86Sub64RI8 : kX86Sub64RI; break; 1419ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko default: 1429ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko LOG(FATAL) << "Bad case in OpRegImm (64-bit) " << op; 1439ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 1449ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 1459ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko switch (op) { 1469ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpLsl: opcode = kX86Sal32RI; break; 1479ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpLsr: opcode = kX86Shr32RI; break; 1489ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpAsr: opcode = kX86Sar32RI; break; 1499ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpAdd: opcode = byte_imm ? kX86Add32RI8 : kX86Add32RI; break; 1509ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpOr: opcode = byte_imm ? kX86Or32RI8 : kX86Or32RI; break; 1519ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpAdc: opcode = byte_imm ? kX86Adc32RI8 : kX86Adc32RI; break; 1529ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko // case kOpSbb: opcode = kX86Sbb32RI; break; 1539ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpAnd: opcode = byte_imm ? kX86And32RI8 : kX86And32RI; break; 1549ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpSub: opcode = byte_imm ? kX86Sub32RI8 : kX86Sub32RI; break; 1559ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpXor: opcode = byte_imm ? kX86Xor32RI8 : kX86Xor32RI; break; 1569ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpCmp: opcode = byte_imm ? kX86Cmp32RI8 : kX86Cmp32RI; break; 1579ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpMov: 1589ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko /* 1599ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko * Moving the constant zero into register can be specialized as an xor of the register. 1609ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko * However, that sets eflags while the move does not. For that reason here, always do 1619ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko * the move and if caller is flexible, they should be calling LoadConstantNoClobber instead. 1629ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko */ 1639ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko opcode = kX86Mov32RI; 1649ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko break; 1659ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kOpMul: 1669ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI; 1679ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko return NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), value); 168e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell case kOp2Byte: 169e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell opcode = kX86Mov32RI; 170e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell value = static_cast<int8_t>(value); 171e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell break; 172e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell case kOp2Short: 173e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell opcode = kX86Mov32RI; 174e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell value = static_cast<int16_t>(value); 175e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell break; 176e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell case kOp2Char: 177e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell opcode = kX86Mov32RI; 178e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell value = static_cast<uint16_t>(value); 179e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell break; 180e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell case kOpNeg: 181e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell opcode = kX86Mov32RI; 182e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell value = -value; 183e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell break; 1849ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko default: 1859ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko LOG(FATAL) << "Bad case in OpRegImm " << op; 1869ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 187b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 1882700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR2(opcode, r_dest_src1.GetReg(), value); 189e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 190e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 1912700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) { 192a7678db092ac6bb79f7cad490099a1015fbbc714buzbee X86OpCode opcode = kX86Nop; 193d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers bool src2_must_be_cx = false; 194e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee switch (op) { 195b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // X86 unary opcodes 196b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpMvn: 1971fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_dest_src1, r_src2); 1981fd3346740dfb7f47be9922312b68a4227fada96buzbee return OpReg(kOpNot, r_dest_src1); 199b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpNeg: 2001fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_dest_src1, r_src2); 2011fd3346740dfb7f47be9922312b68a4227fada96buzbee return OpReg(kOpNeg, r_dest_src1); 202a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko case kOpRev: 203a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko OpRegCopy(r_dest_src1, r_src2); 204a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko return OpReg(kOpRev, r_dest_src1); 205a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko case kOpRevsh: 206a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko OpRegCopy(r_dest_src1, r_src2); 207a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko OpReg(kOpRev, r_dest_src1); 208a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko return OpRegImm(kOpAsr, r_dest_src1, 16); 209b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // X86 binary opcodes 210b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpSub: opcode = kX86Sub32RR; break; 211b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpSbc: opcode = kX86Sbb32RR; break; 212d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers case kOpLsl: opcode = kX86Sal32RC; src2_must_be_cx = true; break; 213d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers case kOpLsr: opcode = kX86Shr32RC; src2_must_be_cx = true; break; 214d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers case kOpAsr: opcode = kX86Sar32RC; src2_must_be_cx = true; break; 215b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpMov: opcode = kX86Mov32RR; break; 216b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpCmp: opcode = kX86Cmp32RR; break; 217b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpAdd: opcode = kX86Add32RR; break; 218b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpAdc: opcode = kX86Adc32RR; break; 219b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpAnd: opcode = kX86And32RR; break; 220b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpOr: opcode = kX86Or32RR; break; 221b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpXor: opcode = kX86Xor32RR; break; 222703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case kOp2Byte: 223091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // TODO: there are several instances of this check. A utility function perhaps? 224091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // TODO: Similar to Arm's reg < 8 check. Perhaps add attribute checks to RegStorage? 225703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao // Use shifts instead of a byte operand if the source can't be byte accessed. 226091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_src2.GetRegNum() >= rs_rX86_SP.GetRegNum()) { 2272700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee NewLIR2(kX86Mov32RR, r_dest_src1.GetReg(), r_src2.GetReg()); 2282700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee NewLIR2(kX86Sal32RI, r_dest_src1.GetReg(), 24); 2292700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR2(kX86Sar32RI, r_dest_src1.GetReg(), 24); 230703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } else { 231703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao opcode = kX86Movsx8RR; 232703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } 233703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 234b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOp2Short: opcode = kX86Movsx16RR; break; 235b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOp2Char: opcode = kX86Movzx16RR; break; 236b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpMul: opcode = kX86Imul32RR; break; 237b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 23852a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee LOG(FATAL) << "Bad case in OpRegReg " << op; 239b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 240e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 241091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(!src2_must_be_cx || r_src2.GetReg() == rs_rCX.GetReg()); 2422700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg()); 243e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 244e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 2452700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type) { 246091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!r_base.IsFloat()); 2472c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru X86OpCode opcode = kX86Nop; 2482700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int dest = r_dest.IsPair() ? r_dest.GetLowReg() : r_dest.GetReg(); 2492c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru switch (move_type) { 2502c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov8GP: 251091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(!r_dest.IsFloat()); 2522c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86Mov8RM; 2532c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2542c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov16GP: 255091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(!r_dest.IsFloat()); 2562c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86Mov16RM; 2572c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2582c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov32GP: 259091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(!r_dest.IsFloat()); 2602c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86Mov32RM; 2612c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2622c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov32FP: 263091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_dest.IsFloat()); 2642c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovssRM; 2652c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2662c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov64FP: 267091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_dest.IsFloat()); 2682c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovsdRM; 2692c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2702c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovU128FP: 271091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_dest.IsFloat()); 2722c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovupsRM; 2732c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2742c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovA128FP: 275091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_dest.IsFloat()); 2762c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovapsRM; 2772c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2782c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovLo128FP: 279091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_dest.IsFloat()); 2802c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovlpsRM; 2812c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2822c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovHi128FP: 283091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_dest.IsFloat()); 2842c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovhpsRM; 2852c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2862c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov64GP: 2872c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovLo64FP: 2882c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovHi64FP: 2892c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru default: 2902c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru LOG(FATAL) << "Bad case in OpMovRegMem"; 2912c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2922c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } 2932c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru 2942700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR3(opcode, dest, r_base.GetReg(), offset); 2952c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru} 2962c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru 2972700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type) { 298091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!r_base.IsFloat()); 2992700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int src = r_src.IsPair() ? r_src.GetLowReg() : r_src.GetReg(); 3002c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru 3012c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru X86OpCode opcode = kX86Nop; 3022c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru switch (move_type) { 3032c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov8GP: 304091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(!r_src.IsFloat()); 3052c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86Mov8MR; 3062c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3072c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov16GP: 308091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(!r_src.IsFloat()); 3092c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86Mov16MR; 3102c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3112c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov32GP: 312091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(!r_src.IsFloat()); 3132c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86Mov32MR; 3142c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3152c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov32FP: 316091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_src.IsFloat()); 3172c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovssMR; 3182c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3192c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov64FP: 320091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_src.IsFloat()); 3212c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovsdMR; 3222c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3232c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovU128FP: 324091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_src.IsFloat()); 3252c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovupsMR; 3262c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3272c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovA128FP: 328091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_src.IsFloat()); 3292c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovapsMR; 3302c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3312c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovLo128FP: 332091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_src.IsFloat()); 3332c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovlpsMR; 3342c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3352c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovHi128FP: 336091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee CHECK(r_src.IsFloat()); 3372c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode = kX86MovhpsMR; 3382c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3392c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMov64GP: 3402c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovLo64FP: 3412c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case kMovHi64FP: 3422c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru default: 3432c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru LOG(FATAL) << "Bad case in OpMovMemReg"; 3442c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 3452c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } 3462c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru 3472700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR3(opcode, r_base.GetReg(), offset, src); 3482c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru} 3492c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru 3502700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) { 351bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru // The only conditional reg to reg operation supported is Cmov 352bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru DCHECK_EQ(op, kOpCmov); 3532700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR3(kX86Cmov32RRC, r_dest.GetReg(), r_src.GetReg(), X86ConditionEncoding(cc)); 354bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru} 355bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru 3562700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset) { 357b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode opcode = kX86Nop; 358b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers switch (op) { 359b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // X86 binary opcodes 360b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpSub: opcode = kX86Sub32RM; break; 361b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpMov: opcode = kX86Mov32RM; break; 362b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpCmp: opcode = kX86Cmp32RM; break; 363b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpAdd: opcode = kX86Add32RM; break; 364b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpAnd: opcode = kX86And32RM; break; 365b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpOr: opcode = kX86Or32RM; break; 366b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpXor: opcode = kX86Xor32RM; break; 367b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOp2Byte: opcode = kX86Movsx8RM; break; 368b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOp2Short: opcode = kX86Movsx16RM; break; 369b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOp2Char: opcode = kX86Movzx16RM; break; 370b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpMul: 371b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 37252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee LOG(FATAL) << "Bad case in OpRegMem " << op; 373b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 374b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 3752700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LIR *l = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), offset); 3762700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee if (r_base == rs_rX86_SP) { 377feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell AnnotateDalvikRegAccess(l, offset >> 2, true /* is_load */, false /* is_64bit */); 378feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell } 379feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell return l; 380feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell} 381feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell 382feb2b4e2d1c6538777bb80b60f3a247537b6221dMark MendellLIR* X86Mir2Lir::OpMemReg(OpKind op, RegLocation rl_dest, int r_value) { 383feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell DCHECK_NE(rl_dest.location, kLocPhysReg); 384feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell int displacement = SRegOffset(rl_dest.s_reg_low); 385feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell X86OpCode opcode = kX86Nop; 386feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell switch (op) { 387feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpSub: opcode = kX86Sub32MR; break; 388feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpMov: opcode = kX86Mov32MR; break; 389feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpCmp: opcode = kX86Cmp32MR; break; 390feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpAdd: opcode = kX86Add32MR; break; 391feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpAnd: opcode = kX86And32MR; break; 392feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpOr: opcode = kX86Or32MR; break; 393feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpXor: opcode = kX86Xor32MR; break; 394feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpLsl: opcode = kX86Sal32MC; break; 395feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpLsr: opcode = kX86Shr32MC; break; 396feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpAsr: opcode = kX86Sar32MC; break; 397feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell default: 398feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell LOG(FATAL) << "Bad case in OpMemReg " << op; 399feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell break; 400feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell } 401091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LIR *l = NewLIR3(opcode, rs_rX86_SP.GetReg(), displacement, r_value); 402217fe73a6c2f3ec44dc52c85c8a101313d048f04Serguei Katkov AnnotateDalvikRegAccess(l, displacement >> 2, true /* is_load */, false /* is_64bit */); 403feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell AnnotateDalvikRegAccess(l, displacement >> 2, false /* is_load */, false /* is_64bit */); 404feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell return l; 405feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell} 406feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell 4072700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegMem(OpKind op, RegStorage r_dest, RegLocation rl_value) { 408feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell DCHECK_NE(rl_value.location, kLocPhysReg); 409feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell int displacement = SRegOffset(rl_value.s_reg_low); 410feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell X86OpCode opcode = kX86Nop; 411feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell switch (op) { 412feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpSub: opcode = kX86Sub32RM; break; 413feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpMov: opcode = kX86Mov32RM; break; 414feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpCmp: opcode = kX86Cmp32RM; break; 415feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpAdd: opcode = kX86Add32RM; break; 416feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpAnd: opcode = kX86And32RM; break; 417feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpOr: opcode = kX86Or32RM; break; 418feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpXor: opcode = kX86Xor32RM; break; 419feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell case kOpMul: opcode = kX86Imul32RM; break; 420feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell default: 421feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell LOG(FATAL) << "Bad case in OpRegMem " << op; 422feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell break; 423feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell } 424091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LIR *l = NewLIR3(opcode, r_dest.GetReg(), rs_rX86_SP.GetReg(), displacement); 425feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell AnnotateDalvikRegAccess(l, displacement >> 2, true /* is_load */, false /* is_64bit */); 426feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell return l; 427b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers} 428e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 4292700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, 4302700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_src2) { 431fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (r_dest != r_src1 && r_dest != r_src2) { 4327934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom if (op == kOpAdd) { // lea special case, except can't encode rbp as base 433fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (r_src1 == r_src2) { 4341fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_dest, r_src1); 4351fd3346740dfb7f47be9922312b68a4227fada96buzbee return OpRegImm(kOpLsl, r_dest, 1); 4362700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee } else if (r_src1 != rs_rBP) { 4372700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR5(kX86Lea32RA, r_dest.GetReg(), r_src1.GetReg() /* base */, 4382700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee r_src2.GetReg() /* index */, 0 /* scale */, 0 /* disp */); 439b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 4402700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR5(kX86Lea32RA, r_dest.GetReg(), r_src2.GetReg() /* base */, 4412700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee r_src1.GetReg() /* index */, 0 /* scale */, 0 /* disp */); 442b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 443b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 4441fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_dest, r_src1); 4451fd3346740dfb7f47be9922312b68a4227fada96buzbee return OpRegReg(op, r_dest, r_src2); 446e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 447fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee } else if (r_dest == r_src1) { 4481fd3346740dfb7f47be9922312b68a4227fada96buzbee return OpRegReg(op, r_dest, r_src2); 449fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee } else { // r_dest == r_src2 450b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers switch (op) { 451b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpSub: // non-commutative 4521fd3346740dfb7f47be9922312b68a4227fada96buzbee OpReg(kOpNeg, r_dest); 453b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kOpAdd; 454b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 455b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpSbc: 456b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: { 4572700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage t_reg = AllocTemp(); 4581fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(t_reg, r_src1); 4591fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegReg(op, t_reg, r_src2); 4607a11ab09f93f54b1c07c0bf38dd65ed322e86bc6buzbee LIR* res = OpRegCopyNoInsert(r_dest, t_reg); 4617a11ab09f93f54b1c07c0bf38dd65ed322e86bc6buzbee AppendLIR(res); 4621fd3346740dfb7f47be9922312b68a4227fada96buzbee FreeTemp(t_reg); 463b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers return res; 464b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 465b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpAdd: // commutative 466b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpOr: 467b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpAdc: 468b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpAnd: 469b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kOpXor: 470b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 471b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 47252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee LOG(FATAL) << "Bad case in OpRegRegReg " << op; 473e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 4741fd3346740dfb7f47be9922312b68a4227fada96buzbee return OpRegReg(op, r_dest, r_src1); 475b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 476e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 477e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 4782700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src, int value) { 479b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (op == kOpMul) { 480b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI; 4812700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR3(opcode, r_dest.GetReg(), r_src.GetReg(), value); 482b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } else if (op == kOpAnd) { 483091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (value == 0xFF && r_src.Low4()) { 4842700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR2(kX86Movzx8RR, r_dest.GetReg(), r_src.GetReg()); 485b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } else if (value == 0xFFFF) { 4862700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR2(kX86Movzx16RR, r_dest.GetReg(), r_src.GetReg()); 487b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } 488b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 489fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (r_dest != r_src) { 4907934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom if (false && op == kOpLsl && value >= 0 && value <= 3) { // lea shift special case 4917caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers // TODO: fix bug in LEA encoding when disp == 0 4922700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR5(kX86Lea32RA, r_dest.GetReg(), r5sib_no_base /* base */, 4932700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee r_src.GetReg() /* index */, value /* scale */, 0 /* disp */); 4947934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (op == kOpAdd) { // lea add special case 4952700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR5(kX86Lea32RA, r_dest.GetReg(), r_src.GetReg() /* base */, 4969ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_SP.GetReg()/*r4sib_no_index*/ /* index */, 0 /* scale */, value /* disp */); 497e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 4981fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_dest, r_src); 499b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 5001fd3346740dfb7f47be9922312b68a4227fada96buzbee return OpRegImm(op, r_dest, value); 501e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 502e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 503dd7624d2b9e599d57762d12031b10b89defc9807Ian RogersLIR* X86Mir2Lir::OpThreadMem(OpKind op, ThreadOffset<4> thread_offset) { 5042f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe DCHECK_EQ(kX86, cu_->instruction_set); 5052f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe X86OpCode opcode = kX86Bkpt; 5062f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe switch (op) { 5072f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe case kOpBlx: opcode = kX86CallT; break; 5082f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe case kOpBx: opcode = kX86JmpT; break; 5092f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe default: 5102f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe LOG(FATAL) << "Bad opcode: " << op; 5112f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe break; 5122f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe } 5132f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe return NewLIR1(opcode, thread_offset.Int32Value()); 5142f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe} 5152f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe 5162f244e9faccfcca68af3c5484c397a01a1c3a342Andreas GampeLIR* X86Mir2Lir::OpThreadMem(OpKind op, ThreadOffset<8> thread_offset) { 5172f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe DCHECK_EQ(kX86_64, cu_->instruction_set); 5186cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers X86OpCode opcode = kX86Bkpt; 5196cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers switch (op) { 5206cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers case kOpBlx: opcode = kX86CallT; break; 52160d7a65f7fb60f502160a2e479e86014c7787553Brian Carlstrom case kOpBx: opcode = kX86JmpT; break; 5226cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers default: 5236cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers LOG(FATAL) << "Bad opcode: " << op; 5246cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers break; 5256cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers } 526468532ea115657709bc32ee498e701a4c71762d4Ian Rogers return NewLIR1(opcode, thread_offset.Int32Value()); 5276cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers} 5286cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers 5292700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) { 5306cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers X86OpCode opcode = kX86Bkpt; 5316cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers switch (op) { 5326cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers case kOpBlx: opcode = kX86CallM; break; 5336cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers default: 5346cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers LOG(FATAL) << "Bad opcode: " << op; 5356cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers break; 5366cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers } 5372700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR2(opcode, r_base.GetReg(), disp); 5386cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers} 5396cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers 5402700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) { 5414ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee int32_t val_lo = Low32Bits(value); 5424ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee int32_t val_hi = High32Bits(value); 5432700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int32_t low_reg_val = r_dest.IsPair() ? r_dest.GetLowReg() : r_dest.GetReg(); 544e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee LIR *res; 545e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell bool is_fp = r_dest.IsFloat(); 5462700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee // TODO: clean this up once we fully recognize 64-bit storage containers. 5472700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee if (is_fp) { 5484ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee if (value == 0) { 5492700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return NewLIR2(kX86XorpsRR, low_reg_val, low_reg_val); 55067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } else if (base_of_code_ != nullptr) { 55167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // We will load the value from the literal area. 55267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell LIR* data_target = ScanLiteralPoolWide(literal_list_, val_lo, val_hi); 55367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (data_target == NULL) { 55467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell data_target = AddWideData(&literal_list_, val_lo, val_hi); 55567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 55667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 55767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Address the start of the method 55867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low); 55967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell rl_method = LoadValue(rl_method, kCoreReg); 56067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 56167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Load the proper value from the literal area. 56267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // We don't know the proper offset for the value, so pick one that will force 56367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // 4 byte offset. We will fix this up in the assembler later to have the right 56467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // value. 5650c52451e9be14a6bff9ffefce89ff1d60691af60Mark Mendell res = LoadBaseDisp(rl_method.reg, 256 /* bogus */, RegStorage::FloatSolo64(low_reg_val), 5663bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko kDouble); 56767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell res->target = data_target; 56867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell res->flags.fixup = kFixupLoad; 56967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell SetMemRefType(res, true, kLiteral); 57055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell store_method_addr_used_ = true; 571b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } else { 572fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (val_lo == 0) { 5732700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee res = NewLIR2(kX86XorpsRR, low_reg_val, low_reg_val); 574b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } else { 5752700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee res = LoadConstantNoClobber(RegStorage::Solo32(low_reg_val), val_lo); 576b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } 577fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (val_hi != 0) { 5782700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_dest_hi = AllocTempDouble(); 579091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LoadConstantNoClobber(r_dest_hi, val_hi); 580091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86PunpckldqRR, low_reg_val, r_dest_hi.GetReg()); 581d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee FreeTemp(r_dest_hi); 582b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } 583b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } 584b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } else { 5852700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee res = LoadConstantNoClobber(r_dest.GetLow(), val_lo); 5862700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantNoClobber(r_dest.GetHigh(), val_hi); 587b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } 588e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee return res; 589e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 590e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 5912700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::LoadBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale, 5923bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko int displacement, RegStorage r_dest, OpSize size) { 593b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers LIR *load = NULL; 594b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers LIR *load2 = NULL; 5952700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee bool is_array = r_index.Valid(); 596091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee bool pair = r_dest.IsPair(); 597091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee bool is64bit = ((size == k64) || (size == kDouble)); 598b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode opcode = kX86Nop; 599b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers switch (size) { 600695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee case k64: 601b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kDouble: 602091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest.IsFloat()) { 603fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86MovsdRA : kX86MovsdRM; 604b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 605fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Mov32RA : kX86Mov32RM; 606b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 607b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // TODO: double store is to unaligned address 608b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers DCHECK_EQ((displacement & 0x3), 0); 609b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 6109ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kWord: 6119ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko if (Gen64Bit()) { 6129ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko opcode = is_array ? kX86Mov64RA : kX86Mov64RM; 6139ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko CHECK_EQ(is_array, false); 6149ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko CHECK_EQ(r_dest.IsFloat(), false); 6159ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko break; 6169ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } // else fall-through to k32 case 617695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee case k32: 618b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kSingle: 619695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee case kReference: // TODO: update for reference decompression on 64-bit targets. 620fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Mov32RA : kX86Mov32RM; 621091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest.IsFloat()) { 622fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86MovssRA : kX86MovssRM; 623091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(r_dest.IsFloat()); 624b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 625b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers DCHECK_EQ((displacement & 0x3), 0); 626b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 627b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kUnsignedHalf: 628fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Movzx16RA : kX86Movzx16RM; 629b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers DCHECK_EQ((displacement & 0x1), 0); 630b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 631b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kSignedHalf: 632fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Movsx16RA : kX86Movsx16RM; 633b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers DCHECK_EQ((displacement & 0x1), 0); 634b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 635b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kUnsignedByte: 636fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Movzx8RA : kX86Movzx8RM; 637b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 638b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kSignedByte: 639fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Movsx8RA : kX86Movsx8RM; 640b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 641b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 64252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody"; 643b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 644b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers 645fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!is_array) { 646b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (!pair) { 6472700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee load = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), displacement + LOWORD_OFFSET); 648e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } else { 649091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!r_dest.IsFloat()); // Make sure we're not still using a pair here. 650091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_base == r_dest.GetLow()) { 651091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load2 = NewLIR3(opcode, r_dest.GetHighReg(), r_base.GetReg(), 652fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao displacement + HIWORD_OFFSET); 653091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load = NewLIR3(opcode, r_dest.GetLowReg(), r_base.GetReg(), displacement + LOWORD_OFFSET); 654fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 655091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load = NewLIR3(opcode, r_dest.GetLowReg(), r_base.GetReg(), displacement + LOWORD_OFFSET); 656091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load2 = NewLIR3(opcode, r_dest.GetHighReg(), r_base.GetReg(), 657fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao displacement + HIWORD_OFFSET); 658fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 659e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 6602700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee if (r_base == rs_rX86_SP) { 6611fd3346740dfb7f47be9922312b68a4227fada96buzbee AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, 66202031b185b4653e6c72e21f7a51238b903f6d638buzbee true /* is_load */, is64bit); 663f7d9ad39541dd09030e26d54d3b73a076f90cc74Ian Rogers if (pair) { 6641fd3346740dfb7f47be9922312b68a4227fada96buzbee AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2, 665fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee true /* is_load */, is64bit); 666b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 667e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 668b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 669b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (!pair) { 6702700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee load = NewLIR5(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg(), scale, 671a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee displacement + LOWORD_OFFSET); 672b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 673091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!r_dest.IsFloat()); // Make sure we're not still using a pair here. 674091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_base == r_dest.GetLow()) { 675091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest.GetHigh() == r_index) { 676ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell // We can't use either register for the first load. 6772700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage temp = AllocTemp(); 6782700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee load2 = NewLIR5(opcode, temp.GetReg(), r_base.GetReg(), r_index.GetReg(), scale, 679ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + HIWORD_OFFSET); 680091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load = NewLIR5(opcode, r_dest.GetLowReg(), r_base.GetReg(), r_index.GetReg(), scale, 681ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + LOWORD_OFFSET); 682091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee OpRegCopy(r_dest.GetHigh(), temp); 683ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell FreeTemp(temp); 684ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell } else { 685091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load2 = NewLIR5(opcode, r_dest.GetHighReg(), r_base.GetReg(), r_index.GetReg(), scale, 686ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + HIWORD_OFFSET); 687091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load = NewLIR5(opcode, r_dest.GetLowReg(), r_base.GetReg(), r_index.GetReg(), scale, 688ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + LOWORD_OFFSET); 689ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell } 690fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 691091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_dest.GetLow() == r_index) { 692ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell // We can't use either register for the first load. 6932700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage temp = AllocTemp(); 6942700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee load = NewLIR5(opcode, temp.GetReg(), r_base.GetReg(), r_index.GetReg(), scale, 695ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + LOWORD_OFFSET); 696091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load2 = NewLIR5(opcode, r_dest.GetHighReg(), r_base.GetReg(), r_index.GetReg(), scale, 697ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + HIWORD_OFFSET); 698091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee OpRegCopy(r_dest.GetLow(), temp); 699ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell FreeTemp(temp); 700ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell } else { 701091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load = NewLIR5(opcode, r_dest.GetLowReg(), r_base.GetReg(), r_index.GetReg(), scale, 702ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + LOWORD_OFFSET); 703091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee load2 = NewLIR5(opcode, r_dest.GetHighReg(), r_base.GetReg(), r_index.GetReg(), scale, 704ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell displacement + HIWORD_OFFSET); 705ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell } 706fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 707b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 708b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 709b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers 710b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers return load; 711e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 712e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 7135772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao/* Load value from base + scaled index. */ 7142700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, 7152700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int scale, OpSize size) { 7163bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko return LoadBaseIndexedDisp(r_base, r_index, scale, 0, r_dest, size); 7175772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao} 7185772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao 719674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir MarkoLIR* X86Mir2Lir::LoadBaseDispVolatile(RegStorage r_base, int displacement, RegStorage r_dest, 720674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko OpSize size) { 721674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // LoadBaseDisp() will emit correct insn for atomic load on x86 722674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // assuming r_dest is correctly prepared using RegClassForFieldLoadStore(). 723674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko return LoadBaseDisp(r_base, displacement, r_dest, size); 724674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko} 725674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko 726091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeeLIR* X86Mir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, 7273bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko OpSize size) { 728091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee return LoadBaseIndexedDisp(r_base, RegStorage::InvalidReg(), 0, displacement, r_dest, 7293bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko size); 730e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 731e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 7322700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale, 7333bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko int displacement, RegStorage r_src, OpSize size) { 734b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers LIR *store = NULL; 735e296248a124ed8287b38a9225463696c18d84cd6jeffhao LIR *store2 = NULL; 7362700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee bool is_array = r_index.Valid(); 737091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee bool pair = r_src.IsPair(); 738091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee bool is64bit = (size == k64) || (size == kDouble); 739b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers X86OpCode opcode = kX86Nop; 740b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers switch (size) { 741695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee case k64: 742b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kDouble: 743091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_src.IsFloat()) { 744fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86MovsdAR : kX86MovsdMR; 745b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 7469ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko if (Gen64Bit()) { 7479ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko opcode = is_array ? kX86Mov64AR : kX86Mov64MR; 7489ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 7499ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko // TODO(64): pair = true; 7509ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko opcode = is_array ? kX86Mov32AR : kX86Mov32MR; 7519ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 752b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 753b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // TODO: double store is to unaligned address 754b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers DCHECK_EQ((displacement & 0x3), 0); 755b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 7569ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko case kWord: 7579ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko if (Gen64Bit()) { 7589ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko opcode = is_array ? kX86Mov64AR : kX86Mov64MR; 7599ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko CHECK_EQ(is_array, false); 7609ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko CHECK_EQ(r_src.IsFloat(), false); 7619ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko break; 7629ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } // else fall-through to k32 case 763695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee case k32: 764b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kSingle: 765695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee case kReference: 766fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Mov32AR : kX86Mov32MR; 767091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (r_src.IsFloat()) { 768fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86MovssAR : kX86MovssMR; 769091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(r_src.IsSingle()); 770b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 771b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers DCHECK_EQ((displacement & 0x3), 0); 772b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 773b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kUnsignedHalf: 774b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kSignedHalf: 775fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Mov16AR : kX86Mov16MR; 776b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers DCHECK_EQ((displacement & 0x1), 0); 777b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 778b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kUnsignedByte: 779b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case kSignedByte: 780fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee opcode = is_array ? kX86Mov8AR : kX86Mov8MR; 781b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 782b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 78300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee LOG(FATAL) << "Bad case in StoreBaseIndexedDispBody"; 784b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 785b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers 786fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!is_array) { 787b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers if (!pair) { 7882700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee store = NewLIR3(opcode, r_base.GetReg(), displacement + LOWORD_OFFSET, r_src.GetReg()); 789b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } else { 790091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!r_src.IsFloat()); // Make sure we're not still using a pair here. 791091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee store = NewLIR3(opcode, r_base.GetReg(), displacement + LOWORD_OFFSET, r_src.GetLowReg()); 792091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee store2 = NewLIR3(opcode, r_base.GetReg(), displacement + HIWORD_OFFSET, r_src.GetHighReg()); 793e296248a124ed8287b38a9225463696c18d84cd6jeffhao } 7942700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee if (r_base == rs_rX86_SP) { 7951fd3346740dfb7f47be9922312b68a4227fada96buzbee AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, 79602031b185b4653e6c72e21f7a51238b903f6d638buzbee false /* is_load */, is64bit); 797e296248a124ed8287b38a9225463696c18d84cd6jeffhao if (pair) { 7981fd3346740dfb7f47be9922312b68a4227fada96buzbee AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2, 799fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee false /* is_load */, is64bit); 800e296248a124ed8287b38a9225463696c18d84cd6jeffhao } 801b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } 802b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 803b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers if (!pair) { 8042700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee store = NewLIR5(opcode, r_base.GetReg(), r_index.GetReg(), scale, 8052700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee displacement + LOWORD_OFFSET, r_src.GetReg()); 806b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } else { 807091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!r_src.IsFloat()); // Make sure we're not still using a pair here. 8082700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee store = NewLIR5(opcode, r_base.GetReg(), r_index.GetReg(), scale, 809091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee displacement + LOWORD_OFFSET, r_src.GetLowReg()); 8102700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee store2 = NewLIR5(opcode, r_base.GetReg(), r_index.GetReg(), scale, 811091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee displacement + HIWORD_OFFSET, r_src.GetHighReg()); 812e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee } 813b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 814b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers return store; 815e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 816e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 817c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers/* store value base base + scaled index. */ 8182700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, 8192ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom int scale, OpSize size) { 8203bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko return StoreBaseIndexedDisp(r_base, r_index, scale, 0, r_src, size); 821c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers} 822c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers 823674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir MarkoLIR* X86Mir2Lir::StoreBaseDispVolatile(RegStorage r_base, int displacement, 824674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko RegStorage r_src, OpSize size) { 825674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // StoreBaseDisp() will emit correct insn for atomic store on x86 826674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // assuming r_dest is correctly prepared using RegClassForFieldLoadStore(). 827674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko return StoreBaseDisp(r_base, displacement, r_src, size); 828674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko} 829674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko 8302700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, 8312700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_src, OpSize size) { 8323bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko return StoreBaseIndexedDisp(r_base, RegStorage::InvalidReg(), 0, displacement, r_src, size); 833e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 834e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 8352700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpCmpMemImmBranch(ConditionCode cond, RegStorage temp_reg, RegStorage base_reg, 836766e9295d2c34cd1846d81610c9045b5d5093dddMark Mendell int offset, int check_value, LIR* target) { 8372700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee NewLIR3(IS_SIMM8(check_value) ? kX86Cmp32MI8 : kX86Cmp32MI, base_reg.GetReg(), offset, 838766e9295d2c34cd1846d81610c9045b5d5093dddMark Mendell check_value); 839766e9295d2c34cd1846d81610c9045b5d5093dddMark Mendell LIR* branch = OpCondBranch(cond, target); 840766e9295d2c34cd1846d81610c9045b5d5093dddMark Mendell return branch; 841766e9295d2c34cd1846d81610c9045b5d5093dddMark Mendell} 842766e9295d2c34cd1846d81610c9045b5d5093dddMark Mendell 84367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::AnalyzeMIR() { 84467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Assume we don't need a pointer to the base of the code. 84567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell cu_->NewTimingSplit("X86 MIR Analysis"); 84667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell store_method_addr_ = false; 84767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 84867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Walk the MIR looking for interesting items. 84967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell PreOrderDfsIterator iter(mir_graph_); 85067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell BasicBlock* curr_bb = iter.Next(); 85167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell while (curr_bb != NULL) { 85267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell AnalyzeBB(curr_bb); 85367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell curr_bb = iter.Next(); 85467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 85567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 85667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Did we need a pointer to the method code? 85767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (store_method_addr_) { 85867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell base_of_code_ = mir_graph_->GetNewCompilerTemp(kCompilerTempVR, false); 85967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } else { 86067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell base_of_code_ = nullptr; 86167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 86267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell} 86367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 86467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::AnalyzeBB(BasicBlock * bb) { 86567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (bb->block_type == kDead) { 86667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Ignore dead blocks 86767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell return; 86867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 86967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 87067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell for (MIR *mir = bb->first_mir_insn; mir != NULL; mir = mir->next) { 87167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell int opcode = mir->dalvikInsn.opcode; 87235ba7f3a78d38885ec54e61ed060d2771eeceea7buzbee if (MIRGraph::IsPseudoMirOp(opcode)) { 87367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell AnalyzeExtendedMIR(opcode, bb, mir); 87467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } else { 87567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell AnalyzeMIR(opcode, bb, mir); 87667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 87767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 87867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell} 87967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 88067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 88167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::AnalyzeExtendedMIR(int opcode, BasicBlock * bb, MIR *mir) { 88267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell switch (opcode) { 88367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Instructions referencing doubles. 88467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case kMirOpFusedCmplDouble: 88567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case kMirOpFusedCmpgDouble: 88667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell AnalyzeFPInstruction(opcode, bb, mir); 88767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell break; 888d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell case kMirOpConstVector: 889d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell store_method_addr_ = true; 890d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell break; 89167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell default: 89267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Ignore the rest. 89367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell break; 89467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 89567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell} 89667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 89767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::AnalyzeMIR(int opcode, BasicBlock * bb, MIR *mir) { 89867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Looking for 89967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // - Do we need a pointer to the code (used for packed switches and double lits)? 90067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 90167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell switch (opcode) { 90267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Instructions referencing doubles. 90367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::CMPL_DOUBLE: 90467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::CMPG_DOUBLE: 90567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::NEG_DOUBLE: 90667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::ADD_DOUBLE: 90767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::SUB_DOUBLE: 90867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::MUL_DOUBLE: 90967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::DIV_DOUBLE: 91067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::REM_DOUBLE: 91167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::ADD_DOUBLE_2ADDR: 91267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::SUB_DOUBLE_2ADDR: 91367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::MUL_DOUBLE_2ADDR: 91467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::DIV_DOUBLE_2ADDR: 91567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::REM_DOUBLE_2ADDR: 91667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell AnalyzeFPInstruction(opcode, bb, mir); 91767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell break; 91855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 91967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Packed switches and array fills need a pointer to the base of the method. 92067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::FILL_ARRAY_DATA: 92167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell case Instruction::PACKED_SWITCH: 92267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell store_method_addr_ = true; 92367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell break; 92467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell default: 92567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Other instructions are not interesting yet. 92667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell break; 92767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 92867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell} 92967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 93067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::AnalyzeFPInstruction(int opcode, BasicBlock * bb, MIR *mir) { 93167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Look at all the uses, and see if they are double constants. 932cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler uint64_t attrs = MIRGraph::GetDataFlowAttributes(static_cast<Instruction::Code>(opcode)); 93367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell int next_sreg = 0; 93467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (attrs & DF_UA) { 93567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (attrs & DF_A_WIDE) { 93667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell AnalyzeDoubleUse(mir_graph_->GetSrcWide(mir, next_sreg)); 93767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell next_sreg += 2; 93867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } else { 93967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell next_sreg++; 94067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 94167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 94267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (attrs & DF_UB) { 94367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (attrs & DF_B_WIDE) { 94467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell AnalyzeDoubleUse(mir_graph_->GetSrcWide(mir, next_sreg)); 94567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell next_sreg += 2; 94667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } else { 94767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell next_sreg++; 94867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 94967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 95067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (attrs & DF_UC) { 95167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (attrs & DF_C_WIDE) { 95267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell AnalyzeDoubleUse(mir_graph_->GetSrcWide(mir, next_sreg)); 95367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 95467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 95567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell} 95667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 95767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::AnalyzeDoubleUse(RegLocation use) { 95867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // If this is a double literal, we will want it in the literal pool. 95967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (use.is_const) { 96067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell store_method_addr_ = true; 96167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 96267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell} 96367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 96430adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbeeRegLocation X86Mir2Lir::UpdateLocTyped(RegLocation loc, int reg_class) { 96530adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee loc = UpdateLoc(loc); 96630adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee if ((loc.location == kLocPhysReg) && (loc.fp != loc.reg.IsFloat())) { 96730adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee if (GetRegInfo(loc.reg)->IsTemp()) { 96830adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee Clobber(loc.reg); 96930adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee FreeTemp(loc.reg); 97030adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee loc.reg = RegStorage::InvalidReg(); 97130adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee loc.location = kLocDalvikFrame; 97230adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee } 97330adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee } 97430adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee return loc; 97530adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee} 97630adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee 97730adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbeeRegLocation X86Mir2Lir::UpdateLocWideTyped(RegLocation loc, int reg_class) { 97830adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee loc = UpdateLocWide(loc); 97930adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee if ((loc.location == kLocPhysReg) && (loc.fp != loc.reg.IsFloat())) { 98030adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee if (GetRegInfo(loc.reg)->IsTemp()) { 98130adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee Clobber(loc.reg); 98230adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee FreeTemp(loc.reg); 98330adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee loc.reg = RegStorage::InvalidReg(); 98430adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee loc.location = kLocDalvikFrame; 98530adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee } 98630adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee } 98730adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee return loc; 98830adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee} 98930adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee 990e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} // namespace art 991