fp_x86.cc revision dd64450b37776f68b9bfc47f8d9a88bc72c95727
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" 19641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "x86_lir.h" 201bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 21e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbeenamespace art { 22e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 231fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenArithOpFloat(Instruction::Code opcode, 2402031b185b4653e6c72e21f7a51238b903f6d638buzbee RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { 25b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode op = kX86Nop; 26fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 27e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 28b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers /* 29b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers * Don't attempt to optimize register usage since these opcodes call out to 30b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers * the handlers. 31b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers */ 32408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee switch (opcode) { 33b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::ADD_FLOAT_2ADDR: 34b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::ADD_FLOAT: 35b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86AddssRR; 36b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 37b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::SUB_FLOAT_2ADDR: 38b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::SUB_FLOAT: 39b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86SubssRR; 40b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 41b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DIV_FLOAT_2ADDR: 42b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DIV_FLOAT: 43b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86DivssRR; 44b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 45b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::MUL_FLOAT_2ADDR: 46b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::MUL_FLOAT: 47b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86MulssRR; 48b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 49b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::REM_FLOAT_2ADDR: 50babda950caf2d577aa57102c3281f0f3c36f3d6djeffhao case Instruction::REM_FLOAT: 51bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov GenRemFP(rl_dest, rl_src1, rl_src2, false /* is_double */); 52a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 53a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee case Instruction::NEG_FLOAT: 541fd3346740dfb7f47be9922312b68a4227fada96buzbee GenNegFloat(rl_dest, rl_src1); 55a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 56b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 57a5954be0aac5edd892fb31a209960543d00e4500buzbee LOG(FATAL) << "Unexpected opcode: " << opcode; 58b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 591fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValue(rl_src1, kFPReg); 601fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValue(rl_src2, kFPReg); 611fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 622700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_dest = rl_result.reg; 632700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_src1 = rl_src1.reg; 642700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_src2 = rl_src2.reg; 65fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (r_dest == r_src2) { 66091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee r_src2 = AllocTempSingle(); 671fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_src2, r_dest); 684abb1a9000b525a0636763a97528e24468f16d10jeffhao } 691fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_dest, r_src1); 702700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee NewLIR2(op, r_dest.GetReg(), r_src2.GetReg()); 711fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 72e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 73e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 741fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenArithOpDouble(Instruction::Code opcode, 7502031b185b4653e6c72e21f7a51238b903f6d638buzbee RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { 76091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_dest.wide); 77091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_dest.fp); 78091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_src1.wide); 79091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_src1.fp); 80091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_src2.wide); 81091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_src2.fp); 82b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode op = kX86Nop; 83fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 84e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 85408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee switch (opcode) { 86b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::ADD_DOUBLE_2ADDR: 87b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::ADD_DOUBLE: 88b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86AddsdRR; 89b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 90b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::SUB_DOUBLE_2ADDR: 91b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::SUB_DOUBLE: 92b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86SubsdRR; 93b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 94b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DIV_DOUBLE_2ADDR: 95b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DIV_DOUBLE: 96b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86DivsdRR; 97b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 98b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::MUL_DOUBLE_2ADDR: 99b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::MUL_DOUBLE: 100b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86MulsdRR; 101b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 102b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::REM_DOUBLE_2ADDR: 103babda950caf2d577aa57102c3281f0f3c36f3d6djeffhao case Instruction::REM_DOUBLE: 104bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov GenRemFP(rl_dest, rl_src1, rl_src2, true /* is_double */); 105a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 106a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee case Instruction::NEG_DOUBLE: 1071fd3346740dfb7f47be9922312b68a4227fada96buzbee GenNegDouble(rl_dest, rl_src1); 108a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 109b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 110a5954be0aac5edd892fb31a209960543d00e4500buzbee LOG(FATAL) << "Unexpected opcode: " << opcode; 111b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 1121fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValueWide(rl_src1, kFPReg); 1131fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValueWide(rl_src2, kFPReg); 1141fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 115091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (rl_result.reg == rl_src2.reg) { 116091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rl_src2.reg = AllocTempDouble(); 117091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee OpRegCopy(rl_src2.reg, rl_result.reg); 1184abb1a9000b525a0636763a97528e24468f16d10jeffhao } 119091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee OpRegCopy(rl_result.reg, rl_src1.reg); 120091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(op, rl_result.reg.GetReg(), rl_src2.reg.GetReg()); 1211fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_result); 122e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 123e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 124614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoruvoid X86Mir2Lir::GenLongToFP(RegLocation rl_dest, RegLocation rl_src, bool is_double) { 125614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Compute offsets to the source and destination VRs on stack 126614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru int src_v_reg_offset = SRegOffset(rl_src.s_reg_low); 127614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru int dest_v_reg_offset = SRegOffset(rl_dest.s_reg_low); 128614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 129614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Update the in-register state of source. 130614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru rl_src = UpdateLocWide(rl_src); 131614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 1328dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko // All memory accesses below reference dalvik regs. 1338dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 1348dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko 135614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // If the source is in physical register, then put it in its location on stack. 136614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru if (rl_src.location == kLocPhysReg) { 137091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegisterInfo* reg_info = GetRegInfo(rl_src.reg); 138614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 139091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (reg_info != nullptr && reg_info->IsTemp()) { 140614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Calling FlushSpecificReg because it will only write back VR if it is dirty. 141091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FlushSpecificReg(reg_info); 142091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // ResetDef to prevent NullifyRange from removing stores. 143091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee ResetDef(rl_src.reg); 144614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } else { 145614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // It must have been register promoted if it is not a temp but is still in physical 146614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // register. Since we need it to be in memory to convert, we place it there now. 1473c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe StoreBaseDisp(TargetReg(kSp), src_v_reg_offset, rl_src.reg, k64, kNotVolatile); 148614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } 149614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } 150614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 151614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Push the source virtual register onto the x87 stack. 152091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LIR *fild64 = NewLIR2NoDest(kX86Fild64M, TargetReg(kSp).GetReg(), 153091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee src_v_reg_offset + LOWORD_OFFSET); 154614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru AnnotateDalvikRegAccess(fild64, (src_v_reg_offset + LOWORD_OFFSET) >> 2, 155091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee true /* is_load */, true /* is64bit */); 156614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 157614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Now pop off x87 stack and store it in the destination VR's stack location. 158614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru int opcode = is_double ? kX86Fstp64M : kX86Fstp32M; 159614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru int displacement = is_double ? dest_v_reg_offset + LOWORD_OFFSET : dest_v_reg_offset; 1602700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LIR *fstp = NewLIR2NoDest(opcode, TargetReg(kSp).GetReg(), displacement); 161614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru AnnotateDalvikRegAccess(fstp, displacement >> 2, false /* is_load */, is_double); 162614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 163614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru /* 164614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * The result is in a physical register if it was in a temp or was register 165614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * promoted. For that reason it is enough to check if it is in physical 166614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * register. If it is, then we must do all of the bookkeeping necessary to 167614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * invalidate temp (if needed) and load in promoted register (if needed). 168614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * If the result's location is in memory, then we do not need to do anything 169614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * more since the fstp has already placed the correct value in memory. 170614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru */ 17130adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee RegLocation rl_result = is_double ? UpdateLocWideTyped(rl_dest, kFPReg) : 17230adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee UpdateLocTyped(rl_dest, kFPReg); 173614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru if (rl_result.location == kLocPhysReg) { 174614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru /* 175614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * We already know that the result is in a physical register but do not know if it is the 176614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * right class. So we call EvalLoc(Wide) first which will ensure that it will get moved to the 177614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * correct register class. 178614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru */ 1798dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko rl_result = EvalLoc(rl_dest, kFPReg, true); 180614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru if (is_double) { 1813c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe LoadBaseDisp(TargetReg(kSp), dest_v_reg_offset, rl_result.reg, k64, kNotVolatile); 182614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 18351a80d72dc436a4a89c636987b9cedabe774fdd6Maxim Kazantsev StoreFinalValueWide(rl_dest, rl_result); 184614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } else { 185695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee Load32Disp(TargetReg(kSp), dest_v_reg_offset, rl_result.reg); 186614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 18751a80d72dc436a4a89c636987b9cedabe774fdd6Maxim Kazantsev StoreFinalValue(rl_dest, rl_result); 188614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } 189614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } 190614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru} 191614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 1921fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest, 19302031b185b4653e6c72e21f7a51238b903f6d638buzbee RegLocation rl_src) { 1945121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao RegisterClass rcSrc = kFPReg; 195b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode op = kX86Nop; 196fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 197b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers switch (opcode) { 198b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::INT_TO_FLOAT: 1995121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao rcSrc = kCoreReg; 200b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86Cvtsi2ssRR; 201b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 202b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DOUBLE_TO_FLOAT: 2035121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao rcSrc = kFPReg; 204b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86Cvtsd2ssRR; 205b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 206b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::FLOAT_TO_DOUBLE: 2075121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao rcSrc = kFPReg; 208b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86Cvtss2sdRR; 209b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 210b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::INT_TO_DOUBLE: 2115121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao rcSrc = kCoreReg; 212b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86Cvtsi2sdRR; 213b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 214292188d514c9826971308a18fcc5a66261729f3bjeffhao case Instruction::FLOAT_TO_INT: { 2151fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValue(rl_src, kFPReg); 216078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 2171fd3346740dfb7f47be9922312b68a4227fada96buzbee ClobberSReg(rl_dest.s_reg_low); 2181fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kCoreReg, true); 219091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegStorage temp_reg = AllocTempSingle(); 22041005ddb5576b8630a1084fbb3979ffa602c0599jeffhao 2212700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstant(rl_result.reg, 0x7fffffff); 222091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86Cvtsi2ssRR, temp_reg.GetReg(), rl_result.reg.GetReg()); 223091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86ComissRR, rl_src.reg.GetReg(), temp_reg.GetReg()); 2245078d978f21620824d9c2fdcd73063260592398cSerguei Katkov LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondAe); 2251fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP); 226091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86Cvttss2siRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 2271fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_normal = NewLIR1(kX86Jmp8, 0); 2281fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_na_n->target = NewLIR0(kPseudoTargetLabel); 22900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Xor32RR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 2301fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel); 2311fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_normal->target = NewLIR0(kPseudoTargetLabel); 2321fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 233a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 234292188d514c9826971308a18fcc5a66261729f3bjeffhao } 235292188d514c9826971308a18fcc5a66261729f3bjeffhao case Instruction::DOUBLE_TO_INT: { 2361fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValueWide(rl_src, kFPReg); 237078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 2381fd3346740dfb7f47be9922312b68a4227fada96buzbee ClobberSReg(rl_dest.s_reg_low); 2391fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kCoreReg, true); 240091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegStorage temp_reg = AllocTempDouble(); 24141005ddb5576b8630a1084fbb3979ffa602c0599jeffhao 2422700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstant(rl_result.reg, 0x7fffffff); 243091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86Cvtsi2sdRR, temp_reg.GetReg(), rl_result.reg.GetReg()); 244091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86ComisdRR, rl_src.reg.GetReg(), temp_reg.GetReg()); 2455078d978f21620824d9c2fdcd73063260592398cSerguei Katkov LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondAe); 2461fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP); 247091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86Cvttsd2siRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 2481fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_normal = NewLIR1(kX86Jmp8, 0); 2491fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_na_n->target = NewLIR0(kPseudoTargetLabel); 25000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Xor32RR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 2511fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel); 2521fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_normal->target = NewLIR0(kPseudoTargetLabel); 2531fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 254a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 255292188d514c9826971308a18fcc5a66261729f3bjeffhao } 256b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::LONG_TO_DOUBLE: 257dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 258a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rcSrc = kCoreReg; 259a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu op = kX86Cvtsqi2sdRR; 260a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu break; 261a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu } 262614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru GenLongToFP(rl_dest, rl_src, true /* is_double */); 263a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 264b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::LONG_TO_FLOAT: 265dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 266a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rcSrc = kCoreReg; 267a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu op = kX86Cvtsqi2ssRR; 268a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu break; 269a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu } 270614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru GenLongToFP(rl_dest, rl_src, false /* is_double */); 271a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 27241005ddb5576b8630a1084fbb3979ffa602c0599jeffhao case Instruction::FLOAT_TO_LONG: 273dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 274a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rl_src = LoadValue(rl_src, kFPReg); 275a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu // If result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 276a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu ClobberSReg(rl_dest.s_reg_low); 277a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rl_result = EvalLoc(rl_dest, kCoreReg, true); 278a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu RegStorage temp_reg = AllocTempSingle(); 279a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu 280a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu // Set 0x7fffffffffffffff to rl_result 281a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LoadConstantWide(rl_result.reg, 0x7fffffffffffffff); 282a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Cvtsqi2ssRR, temp_reg.GetReg(), rl_result.reg.GetReg()); 283a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86ComissRR, rl_src.reg.GetReg(), temp_reg.GetReg()); 2845078d978f21620824d9c2fdcd73063260592398cSerguei Katkov LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondAe); 285a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP); 286a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Cvttss2sqiRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 287a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LIR* branch_normal = NewLIR1(kX86Jmp8, 0); 288a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_na_n->target = NewLIR0(kPseudoTargetLabel); 289a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Xor64RR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 290a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel); 291a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_normal->target = NewLIR0(kPseudoTargetLabel); 292a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu StoreValueWide(rl_dest, rl_result); 2939ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 2949ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pF2l), rl_dest, rl_src); 2959ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 296a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 297b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DOUBLE_TO_LONG: 298dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 299a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rl_src = LoadValueWide(rl_src, kFPReg); 300a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu // If result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 301a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu ClobberSReg(rl_dest.s_reg_low); 302a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rl_result = EvalLoc(rl_dest, kCoreReg, true); 303a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu RegStorage temp_reg = AllocTempDouble(); 304a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu 305a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu // Set 0x7fffffffffffffff to rl_result 306a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LoadConstantWide(rl_result.reg, 0x7fffffffffffffff); 307a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Cvtsqi2sdRR, temp_reg.GetReg(), rl_result.reg.GetReg()); 308a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86ComisdRR, rl_src.reg.GetReg(), temp_reg.GetReg()); 3095078d978f21620824d9c2fdcd73063260592398cSerguei Katkov LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondAe); 310a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP); 311a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Cvttsd2sqiRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 312a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LIR* branch_normal = NewLIR1(kX86Jmp8, 0); 313a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_na_n->target = NewLIR0(kPseudoTargetLabel); 314a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Xor64RR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 315a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel); 316a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_normal->target = NewLIR0(kPseudoTargetLabel); 317a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu StoreValueWide(rl_dest, rl_result); 3189ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 3199ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pD2l), rl_dest, rl_src); 3209ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 321a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 322b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 323a5954be0aac5edd892fb31a209960543d00e4500buzbee LOG(INFO) << "Unexpected opcode: " << opcode; 324b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 325091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // At this point, target will be either float or double. 326091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_dest.fp); 327fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (rl_src.wide) { 3281fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValueWide(rl_src, rcSrc); 329b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 3301fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValue(rl_src, rcSrc); 331b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 332091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 333091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(op, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 334fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (rl_dest.wide) { 3351fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_result); 336b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 3371fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 338b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 339e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 340e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 341bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalovvoid X86Mir2Lir::GenRemFP(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2, bool is_double) { 342bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Compute offsets to the source and destination VRs on stack. 343bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int src1_v_reg_offset = SRegOffset(rl_src1.s_reg_low); 344bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int src2_v_reg_offset = SRegOffset(rl_src2.s_reg_low); 345bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int dest_v_reg_offset = SRegOffset(rl_dest.s_reg_low); 346bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 347bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Update the in-register state of sources. 348bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov rl_src1 = is_double ? UpdateLocWide(rl_src1) : UpdateLoc(rl_src1); 349bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov rl_src2 = is_double ? UpdateLocWide(rl_src2) : UpdateLoc(rl_src2); 350bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 351bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // All memory accesses below reference dalvik regs. 352bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 353bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 354bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // If the source is in physical register, then put it in its location on stack. 355bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (rl_src1.location == kLocPhysReg) { 356bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov RegisterInfo* reg_info = GetRegInfo(rl_src1.reg); 357bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 358bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (reg_info != nullptr && reg_info->IsTemp()) { 359bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Calling FlushSpecificReg because it will only write back VR if it is dirty. 360bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov FlushSpecificReg(reg_info); 361bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // ResetDef to prevent NullifyRange from removing stores. 362bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov ResetDef(rl_src1.reg); 363bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } else { 364bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // It must have been register promoted if it is not a temp but is still in physical 365bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // register. Since we need it to be in memory to convert, we place it there now. 3663c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe StoreBaseDisp(TargetReg(kSp), src1_v_reg_offset, rl_src1.reg, is_double ? k64 : k32, 3673c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe kNotVolatile); 368bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 369bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 370bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 371bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (rl_src2.location == kLocPhysReg) { 372bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov RegisterInfo* reg_info = GetRegInfo(rl_src2.reg); 373bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (reg_info != nullptr && reg_info->IsTemp()) { 374bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov FlushSpecificReg(reg_info); 375bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov ResetDef(rl_src2.reg); 376bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } else { 3773c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe StoreBaseDisp(TargetReg(kSp), src2_v_reg_offset, rl_src2.reg, is_double ? k64 : k32, 3783c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe kNotVolatile); 379bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 380bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 381bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 382bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int fld_opcode = is_double ? kX86Fld64M : kX86Fld32M; 383bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 384bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Push the source virtual registers onto the x87 stack. 385bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov LIR *fld_2 = NewLIR2NoDest(fld_opcode, TargetReg(kSp).GetReg(), 386bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov src2_v_reg_offset + LOWORD_OFFSET); 387bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov AnnotateDalvikRegAccess(fld_2, (src2_v_reg_offset + LOWORD_OFFSET) >> 2, 388bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov true /* is_load */, is_double /* is64bit */); 389bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 390bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov LIR *fld_1 = NewLIR2NoDest(fld_opcode, TargetReg(kSp).GetReg(), 391bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov src1_v_reg_offset + LOWORD_OFFSET); 392bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov AnnotateDalvikRegAccess(fld_1, (src1_v_reg_offset + LOWORD_OFFSET) >> 2, 393bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov true /* is_load */, is_double /* is64bit */); 394bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 395bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov FlushReg(rs_rAX); 396bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov Clobber(rs_rAX); 397bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov LockTemp(rs_rAX); 398bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 399bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov LIR* retry = NewLIR0(kPseudoTargetLabel); 400bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 401bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Divide ST(0) by ST(1) and place result to ST(0). 402bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov NewLIR0(kX86Fprem); 403bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 404bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Move FPU status word to AX. 405bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov NewLIR0(kX86Fstsw16R); 406bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 407bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Check if reduction is complete. 408bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov OpRegImm(kOpAnd, rs_rAX, 0x400); 409bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 410bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // If no then continue to compute remainder. 411bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov LIR* branch = NewLIR2(kX86Jcc8, 0, kX86CondNe); 412bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov branch->target = retry; 413bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 414bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov FreeTemp(rs_rAX); 415bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 416bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Now store result in the destination VR's stack location. 417bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int displacement = dest_v_reg_offset + LOWORD_OFFSET; 418bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int opcode = is_double ? kX86Fst64M : kX86Fst32M; 419bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov LIR *fst = NewLIR2NoDest(opcode, TargetReg(kSp).GetReg(), displacement); 420bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov AnnotateDalvikRegAccess(fst, displacement >> 2, false /* is_load */, is_double /* is64bit */); 421bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 422bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Pop ST(1) and ST(0). 423bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov NewLIR0(kX86Fucompp); 424bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 425bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov /* 426bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * The result is in a physical register if it was in a temp or was register 427bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * promoted. For that reason it is enough to check if it is in physical 428bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * register. If it is, then we must do all of the bookkeeping necessary to 429bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * invalidate temp (if needed) and load in promoted register (if needed). 430bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * If the result's location is in memory, then we do not need to do anything 431bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * more since the fstp has already placed the correct value in memory. 432bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov */ 433bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov RegLocation rl_result = is_double ? UpdateLocWideTyped(rl_dest, kFPReg) : 434bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov UpdateLocTyped(rl_dest, kFPReg); 435bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (rl_result.location == kLocPhysReg) { 436bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov rl_result = EvalLoc(rl_dest, kFPReg, true); 437bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (is_double) { 4383c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe LoadBaseDisp(TargetReg(kSp), dest_v_reg_offset, rl_result.reg, k64, kNotVolatile); 439bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov StoreFinalValueWide(rl_dest, rl_result); 440bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } else { 441bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov Load32Disp(TargetReg(kSp), dest_v_reg_offset, rl_result.reg); 442bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov StoreFinalValue(rl_dest, rl_result); 443bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 444bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 445bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov} 446bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 4471fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenCmpFP(Instruction::Code code, RegLocation rl_dest, 44802031b185b4653e6c72e21f7a51238b903f6d638buzbee RegLocation rl_src1, RegLocation rl_src2) { 449b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers bool single = (code == Instruction::CMPL_FLOAT) || (code == Instruction::CMPG_FLOAT); 450fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bool unordered_gt = (code == Instruction::CMPG_DOUBLE) || (code == Instruction::CMPG_FLOAT); 451b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (single) { 4521fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValue(rl_src1, kFPReg); 4531fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValue(rl_src2, kFPReg); 454b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 4551fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValueWide(rl_src1, kFPReg); 4561fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValueWide(rl_src2, kFPReg); 457b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 458078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 4591fd3346740dfb7f47be9922312b68a4227fada96buzbee ClobberSReg(rl_dest.s_reg_low); 4601fd3346740dfb7f47be9922312b68a4227fada96buzbee RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 4612700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantNoClobber(rl_result.reg, unordered_gt ? 1 : 0); 462b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (single) { 463091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86UcomissRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 464b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 465091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86UcomisdRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 466b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 467b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers LIR* branch = NULL; 468fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (unordered_gt) { 4691fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 470b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 471703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao // If the result reg can't be byte accessed, use a jump and move instead of a set. 4727e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu if (!IsByteRegister(rl_result.reg)) { 473703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao LIR* branch2 = NULL; 474fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (unordered_gt) { 4751fd3346740dfb7f47be9922312b68a4227fada96buzbee branch2 = NewLIR2(kX86Jcc8, 0, kX86CondA); 47600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Mov32RI, rl_result.reg.GetReg(), 0x0); 477703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } else { 4781fd3346740dfb7f47be9922312b68a4227fada96buzbee branch2 = NewLIR2(kX86Jcc8, 0, kX86CondBe); 47900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Mov32RI, rl_result.reg.GetReg(), 0x1); 480703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } 4811fd3346740dfb7f47be9922312b68a4227fada96buzbee branch2->target = NewLIR0(kPseudoTargetLabel); 482703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } else { 48300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Set8R, rl_result.reg.GetReg(), kX86CondA /* above - unsigned > */); 484703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } 48500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Sbb32RI, rl_result.reg.GetReg(), 0); 486fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (unordered_gt) { 4871fd3346740dfb7f47be9922312b68a4227fada96buzbee branch->target = NewLIR0(kPseudoTargetLabel); 488b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 4891fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 490e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 491e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 4921fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, 49302031b185b4653e6c72e21f7a51238b903f6d638buzbee bool is_double) { 4940d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee LIR* taken = &block_label_list_[bb->taken]; 4950d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee LIR* not_taken = &block_label_list_[bb->fall_through]; 4964b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao LIR* branch = NULL; 497fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_src1; 498fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_src2; 499fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (is_double) { 5001fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = mir_graph_->GetSrcWide(mir, 0); 5011fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = mir_graph_->GetSrcWide(mir, 2); 5021fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValueWide(rl_src1, kFPReg); 5031fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValueWide(rl_src2, kFPReg); 504091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86UcomisdRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 5054b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } else { 5061fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = mir_graph_->GetSrc(mir, 0); 5071fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = mir_graph_->GetSrc(mir, 1); 5081fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValue(rl_src1, kFPReg); 5091fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValue(rl_src2, kFPReg); 51000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86UcomissRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 5114b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 512a894607bca7eb623bc957363e4b36f44cfeea1b6Vladimir Marko ConditionCode ccode = mir->meta.ccode; 5134b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao switch (ccode) { 5144b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondEq: 515fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!gt_bias) { 5161fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 517fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee branch->target = not_taken; 5184b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5194b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5204b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondNe: 521fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!gt_bias) { 5221fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 5234b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao branch->target = taken; 5244b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5254b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5264b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondLt: 527fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 5281fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 529fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee branch->target = not_taken; 5304b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 53158af1f9385742f70aca4fcb5e13aba53b8be2ef4Vladimir Marko ccode = kCondUlt; 5324b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5334b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondLe: 534fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 5351fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 536fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee branch->target = not_taken; 5374b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5384b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao ccode = kCondLs; 5394b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5404b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondGt: 541fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 5421fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 5434b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao branch->target = taken; 5444b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5454b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao ccode = kCondHi; 5464b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5474b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondGe: 548fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 5491fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 5504b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao branch->target = taken; 5514b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 55258af1f9385742f70aca4fcb5e13aba53b8be2ef4Vladimir Marko ccode = kCondUge; 5534b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5544b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao default: 555cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(FATAL) << "Unexpected ccode: " << ccode; 5564b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5571fd3346740dfb7f47be9922312b68a4227fada96buzbee OpCondBranch(ccode, taken); 5584b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao} 5594b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao 5602ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) { 561fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 5621fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValue(rl_src, kCoreReg); 5631fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kCoreReg, true); 5642700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000); 5651fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 566efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 567efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5682ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) { 569fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 5701fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValueWide(rl_src, kCoreReg); 571a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rl_result = EvalLocWide(rl_dest, kCoreReg, true); 572dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 57302959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov OpRegCopy(rl_result.reg, rl_src.reg); 57402959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov // Flip sign bit. 57502959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov NewLIR2(kX86Rol64RI, rl_result.reg.GetReg(), 1); 57602959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov NewLIR2(kX86Xor64RI, rl_result.reg.GetReg(), 1); 57702959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov NewLIR2(kX86Ror64RI, rl_result.reg.GetReg(), 1); 578a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu } else { 579a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000); 580a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu OpRegCopy(rl_result.reg, rl_src.reg); 581a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu } 5821fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_result); 583efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 584efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5851fd3346740dfb7f47be9922312b68a4227fada96buzbeebool X86Mir2Lir::GenInlinedSqrt(CallInfo* info) { 586bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell RegLocation rl_src = info->args[0]; 587bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell RegLocation rl_dest = InlineTargetWide(info); // double place for result 588bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell rl_src = LoadValueWide(rl_src, kFPReg); 589bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true); 590091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86SqrtsdRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 591bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell StoreValueWide(rl_dest, rl_result); 592bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell return true; 593efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 594efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5957071c8d5885175a746723a3b38a347855965be08Yixin Shoubool X86Mir2Lir::GenInlinedAbsFloat(CallInfo* info) { 5967071c8d5885175a746723a3b38a347855965be08Yixin Shou // Get the argument 5977071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_src = info->args[0]; 5987071c8d5885175a746723a3b38a347855965be08Yixin Shou 5997071c8d5885175a746723a3b38a347855965be08Yixin Shou // Get the inlined intrinsic target virtual register 6007071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_dest = InlineTarget(info); 6017071c8d5885175a746723a3b38a347855965be08Yixin Shou 6027071c8d5885175a746723a3b38a347855965be08Yixin Shou // Get the virtual register number 6037071c8d5885175a746723a3b38a347855965be08Yixin Shou DCHECK_NE(rl_src.s_reg_low, INVALID_SREG); 6047071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_dest.s_reg_low == INVALID_SREG) { 6057071c8d5885175a746723a3b38a347855965be08Yixin Shou // Result is unused, the code is dead. Inlining successful, no code generated. 6067071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6077071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6087071c8d5885175a746723a3b38a347855965be08Yixin Shou int v_src_reg = mir_graph_->SRegToVReg(rl_src.s_reg_low); 6097071c8d5885175a746723a3b38a347855965be08Yixin Shou int v_dst_reg = mir_graph_->SRegToVReg(rl_dest.s_reg_low); 6107071c8d5885175a746723a3b38a347855965be08Yixin Shou 6117071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is the same as inlined intrinsic target 6127071c8d5885175a746723a3b38a347855965be08Yixin Shou if (v_src_reg == v_dst_reg) { 6137071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = UpdateLoc(rl_src); 6147071c8d5885175a746723a3b38a347855965be08Yixin Shou 6157071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is in the physical register 6167071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_src.location == kLocPhysReg) { 6177071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = LoadValue(rl_src, kCoreReg); 6187071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegImm(kOpAnd, rl_src.reg, 0x7fffffff); 6197071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValue(rl_dest, rl_src); 6207071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6217071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6227071c8d5885175a746723a3b38a347855965be08Yixin Shou // the argument is in memory 6237071c8d5885175a746723a3b38a347855965be08Yixin Shou DCHECK((rl_src.location == kLocDalvikFrame) || 6247071c8d5885175a746723a3b38a347855965be08Yixin Shou (rl_src.location == kLocCompilerTemp)); 6257071c8d5885175a746723a3b38a347855965be08Yixin Shou 6267071c8d5885175a746723a3b38a347855965be08Yixin Shou // Operate directly into memory. 6277071c8d5885175a746723a3b38a347855965be08Yixin Shou int displacement = SRegOffset(rl_dest.s_reg_low); 6287071c8d5885175a746723a3b38a347855965be08Yixin Shou ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 6297071c8d5885175a746723a3b38a347855965be08Yixin Shou LIR *lir = NewLIR3(kX86And32MI, TargetReg(kSp).GetReg(), displacement, 0x7fffffff); 6307071c8d5885175a746723a3b38a347855965be08Yixin Shou AnnotateDalvikRegAccess(lir, displacement >> 2, false /*is_load */, false /* is_64bit */); 6317071c8d5885175a746723a3b38a347855965be08Yixin Shou AnnotateDalvikRegAccess(lir, displacement >> 2, true /* is_load */, false /* is_64bit*/); 6327071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6337071c8d5885175a746723a3b38a347855965be08Yixin Shou } else { 6347071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = LoadValue(rl_src, kCoreReg); 6357071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 6367071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegRegImm(kOpAnd, rl_result.reg, rl_src.reg, 0x7fffffff); 6377071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValue(rl_dest, rl_result); 6387071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6397071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6407071c8d5885175a746723a3b38a347855965be08Yixin Shou} 6417071c8d5885175a746723a3b38a347855965be08Yixin Shou 6427071c8d5885175a746723a3b38a347855965be08Yixin Shoubool X86Mir2Lir::GenInlinedAbsDouble(CallInfo* info) { 6437071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_src = info->args[0]; 6447071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_dest = InlineTargetWide(info); 6457071c8d5885175a746723a3b38a347855965be08Yixin Shou DCHECK_NE(rl_src.s_reg_low, INVALID_SREG); 6467071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_dest.s_reg_low == INVALID_SREG) { 6477071c8d5885175a746723a3b38a347855965be08Yixin Shou // Result is unused, the code is dead. Inlining successful, no code generated. 6487071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6497071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6507071c8d5885175a746723a3b38a347855965be08Yixin Shou int v_src_reg = mir_graph_->SRegToVReg(rl_src.s_reg_low); 6517071c8d5885175a746723a3b38a347855965be08Yixin Shou int v_dst_reg = mir_graph_->SRegToVReg(rl_dest.s_reg_low); 6527071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = UpdateLocWide(rl_src); 6537071c8d5885175a746723a3b38a347855965be08Yixin Shou 6547071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is in the physical XMM register 6557071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_src.location == kLocPhysReg && rl_src.reg.IsFloat()) { 6567071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true); 6577071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_result.reg != rl_src.reg) { 6587071c8d5885175a746723a3b38a347855965be08Yixin Shou LoadConstantWide(rl_result.reg, 0x7fffffffffffffff); 6597071c8d5885175a746723a3b38a347855965be08Yixin Shou NewLIR2(kX86PandRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 6607071c8d5885175a746723a3b38a347855965be08Yixin Shou } else { 6617071c8d5885175a746723a3b38a347855965be08Yixin Shou RegStorage sign_mask = AllocTempDouble(); 6627071c8d5885175a746723a3b38a347855965be08Yixin Shou LoadConstantWide(sign_mask, 0x7fffffffffffffff); 6637071c8d5885175a746723a3b38a347855965be08Yixin Shou NewLIR2(kX86PandRR, rl_result.reg.GetReg(), sign_mask.GetReg()); 6647071c8d5885175a746723a3b38a347855965be08Yixin Shou FreeTemp(sign_mask); 6657071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6667071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValueWide(rl_dest, rl_result); 6677071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6687071c8d5885175a746723a3b38a347855965be08Yixin Shou } else if (v_src_reg == v_dst_reg) { 6697071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is the same as inlined intrinsic target 6707071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is in the physical register 6717071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_src.location == kLocPhysReg) { 6727071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = LoadValueWide(rl_src, kCoreReg); 6737071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegImm(kOpAnd, rl_src.reg.GetHigh(), 0x7fffffff); 6747071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValueWide(rl_dest, rl_src); 6757071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6767071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6777071c8d5885175a746723a3b38a347855965be08Yixin Shou // the argument is in memory 6787071c8d5885175a746723a3b38a347855965be08Yixin Shou DCHECK((rl_src.location == kLocDalvikFrame) || 6797071c8d5885175a746723a3b38a347855965be08Yixin Shou (rl_src.location == kLocCompilerTemp)); 6807071c8d5885175a746723a3b38a347855965be08Yixin Shou 6817071c8d5885175a746723a3b38a347855965be08Yixin Shou // Operate directly into memory. 6827071c8d5885175a746723a3b38a347855965be08Yixin Shou int displacement = SRegOffset(rl_dest.s_reg_low); 6837071c8d5885175a746723a3b38a347855965be08Yixin Shou ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 6847071c8d5885175a746723a3b38a347855965be08Yixin Shou LIR *lir = NewLIR3(kX86And32MI, TargetReg(kSp).GetReg(), displacement + HIWORD_OFFSET, 0x7fffffff); 6857071c8d5885175a746723a3b38a347855965be08Yixin Shou AnnotateDalvikRegAccess(lir, (displacement + HIWORD_OFFSET) >> 2, true /* is_load */, true /* is_64bit*/); 6867071c8d5885175a746723a3b38a347855965be08Yixin Shou AnnotateDalvikRegAccess(lir, (displacement + HIWORD_OFFSET) >> 2, false /*is_load */, true /* is_64bit */); 6877071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6887071c8d5885175a746723a3b38a347855965be08Yixin Shou } else { 6897071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = LoadValueWide(rl_src, kCoreReg); 6907071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 6917071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegCopyWide(rl_result.reg, rl_src.reg); 6927071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegImm(kOpAnd, rl_result.reg.GetHigh(), 0x7fffffff); 6937071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValueWide(rl_dest, rl_result); 6947071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6957071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6967071c8d5885175a746723a3b38a347855965be08Yixin Shou} 697efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 6987934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom} // namespace art 699