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" 19b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee#include "dex/reg_storage_eq.h" 20641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "x86_lir.h" 211bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 22e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbeenamespace art { 23e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 241fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenArithOpFloat(Instruction::Code opcode, 2502031b185b4653e6c72e21f7a51238b903f6d638buzbee RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { 26b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode op = kX86Nop; 27fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 28e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 29b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers /* 30b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers * Don't attempt to optimize register usage since these opcodes call out to 31b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers * the handlers. 32b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers */ 33408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee switch (opcode) { 34b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::ADD_FLOAT_2ADDR: 35b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::ADD_FLOAT: 36b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86AddssRR; 37b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 38b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::SUB_FLOAT_2ADDR: 39b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::SUB_FLOAT: 40b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86SubssRR; 41b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 42b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DIV_FLOAT_2ADDR: 43b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DIV_FLOAT: 44b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86DivssRR; 45b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 46b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::MUL_FLOAT_2ADDR: 47b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::MUL_FLOAT: 48b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86MulssRR; 49b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 50b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::REM_FLOAT_2ADDR: 51babda950caf2d577aa57102c3281f0f3c36f3d6djeffhao case Instruction::REM_FLOAT: 52bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov GenRemFP(rl_dest, rl_src1, rl_src2, false /* is_double */); 53a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 54a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee case Instruction::NEG_FLOAT: 551fd3346740dfb7f47be9922312b68a4227fada96buzbee GenNegFloat(rl_dest, rl_src1); 56a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 57b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 58a5954be0aac5edd892fb31a209960543d00e4500buzbee LOG(FATAL) << "Unexpected opcode: " << opcode; 59b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 601fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValue(rl_src1, kFPReg); 611fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValue(rl_src2, kFPReg); 621fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 632700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_dest = rl_result.reg; 642700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_src1 = rl_src1.reg; 652700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_src2 = rl_src2.reg; 66fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (r_dest == r_src2) { 67091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee r_src2 = AllocTempSingle(); 681fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_src2, r_dest); 694abb1a9000b525a0636763a97528e24468f16d10jeffhao } 701fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_dest, r_src1); 712700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee NewLIR2(op, r_dest.GetReg(), r_src2.GetReg()); 721fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 73e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 74e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 751fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenArithOpDouble(Instruction::Code opcode, 7602031b185b4653e6c72e21f7a51238b903f6d638buzbee RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { 77091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_dest.wide); 78091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_dest.fp); 79091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_src1.wide); 80091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_src1.fp); 81091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_src2.wide); 82091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_src2.fp); 83b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode op = kX86Nop; 84fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 85e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 86408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee switch (opcode) { 87b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::ADD_DOUBLE_2ADDR: 88b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::ADD_DOUBLE: 89b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86AddsdRR; 90b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 91b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::SUB_DOUBLE_2ADDR: 92b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::SUB_DOUBLE: 93b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86SubsdRR; 94b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 95b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DIV_DOUBLE_2ADDR: 96b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DIV_DOUBLE: 97b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86DivsdRR; 98b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 99b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::MUL_DOUBLE_2ADDR: 100b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::MUL_DOUBLE: 101b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86MulsdRR; 102b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 103b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::REM_DOUBLE_2ADDR: 104babda950caf2d577aa57102c3281f0f3c36f3d6djeffhao case Instruction::REM_DOUBLE: 105bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov GenRemFP(rl_dest, rl_src1, rl_src2, true /* is_double */); 106a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 107a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee case Instruction::NEG_DOUBLE: 1081fd3346740dfb7f47be9922312b68a4227fada96buzbee GenNegDouble(rl_dest, rl_src1); 109a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 110b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 111a5954be0aac5edd892fb31a209960543d00e4500buzbee LOG(FATAL) << "Unexpected opcode: " << opcode; 112b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 1131fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValueWide(rl_src1, kFPReg); 1141fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValueWide(rl_src2, kFPReg); 1151fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 116091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (rl_result.reg == rl_src2.reg) { 117091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rl_src2.reg = AllocTempDouble(); 118091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee OpRegCopy(rl_src2.reg, rl_result.reg); 1194abb1a9000b525a0636763a97528e24468f16d10jeffhao } 120091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee OpRegCopy(rl_result.reg, rl_src1.reg); 121091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(op, rl_result.reg.GetReg(), rl_src2.reg.GetReg()); 1221fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_result); 123e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 124e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 125614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoruvoid X86Mir2Lir::GenLongToFP(RegLocation rl_dest, RegLocation rl_src, bool is_double) { 126614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Compute offsets to the source and destination VRs on stack 127614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru int src_v_reg_offset = SRegOffset(rl_src.s_reg_low); 128614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru int dest_v_reg_offset = SRegOffset(rl_dest.s_reg_low); 129614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 130614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Update the in-register state of source. 131614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru rl_src = UpdateLocWide(rl_src); 132614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 1338dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko // All memory accesses below reference dalvik regs. 1348dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 1358dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko 136614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // If the source is in physical register, then put it in its location on stack. 137614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru if (rl_src.location == kLocPhysReg) { 138091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegisterInfo* reg_info = GetRegInfo(rl_src.reg); 139614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 140091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (reg_info != nullptr && reg_info->IsTemp()) { 141614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Calling FlushSpecificReg because it will only write back VR if it is dirty. 142091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FlushSpecificReg(reg_info); 143091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // ResetDef to prevent NullifyRange from removing stores. 144091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee ResetDef(rl_src.reg); 145614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } else { 146614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // It must have been register promoted if it is not a temp but is still in physical 147614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // register. Since we need it to be in memory to convert, we place it there now. 148a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, src_v_reg_offset, rl_src.reg, k64, kNotVolatile); 149614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } 150614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } 151614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 152614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Push the source virtual register onto the x87 stack. 153a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LIR *fild64 = NewLIR2NoDest(kX86Fild64M, rs_rX86_SP.GetReg(), 154091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee src_v_reg_offset + LOWORD_OFFSET); 155614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru AnnotateDalvikRegAccess(fild64, (src_v_reg_offset + LOWORD_OFFSET) >> 2, 156091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee true /* is_load */, true /* is64bit */); 157614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 158614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Now pop off x87 stack and store it in the destination VR's stack location. 159614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru int opcode = is_double ? kX86Fstp64M : kX86Fstp32M; 160614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru int displacement = is_double ? dest_v_reg_offset + LOWORD_OFFSET : dest_v_reg_offset; 161a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LIR *fstp = NewLIR2NoDest(opcode, rs_rX86_SP.GetReg(), displacement); 162614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru AnnotateDalvikRegAccess(fstp, displacement >> 2, false /* is_load */, is_double); 163614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 164614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru /* 165614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * The result is in a physical register if it was in a temp or was register 166614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * promoted. For that reason it is enough to check if it is in physical 167614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * register. If it is, then we must do all of the bookkeeping necessary to 168614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * invalidate temp (if needed) and load in promoted register (if needed). 169614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * If the result's location is in memory, then we do not need to do anything 170614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * more since the fstp has already placed the correct value in memory. 171614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru */ 17230adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee RegLocation rl_result = is_double ? UpdateLocWideTyped(rl_dest, kFPReg) : 17330adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee UpdateLocTyped(rl_dest, kFPReg); 174614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru if (rl_result.location == kLocPhysReg) { 175614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru /* 176614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * We already know that the result is in a physical register but do not know if it is the 177614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * right class. So we call EvalLoc(Wide) first which will ensure that it will get moved to the 178614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * correct register class. 179614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru */ 1808dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko rl_result = EvalLoc(rl_dest, kFPReg, true); 181614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru if (is_double) { 182a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LoadBaseDisp(rs_rX86_SP, dest_v_reg_offset, rl_result.reg, k64, kNotVolatile); 183614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 18451a80d72dc436a4a89c636987b9cedabe774fdd6Maxim Kazantsev StoreFinalValueWide(rl_dest, rl_result); 185614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } else { 186a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu Load32Disp(rs_rX86_SP, dest_v_reg_offset, rl_result.reg); 187614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 18851a80d72dc436a4a89c636987b9cedabe774fdd6Maxim Kazantsev StoreFinalValue(rl_dest, rl_result); 189614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } 190614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } 191614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru} 192614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 1931fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest, 19402031b185b4653e6c72e21f7a51238b903f6d638buzbee RegLocation rl_src) { 1955121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao RegisterClass rcSrc = kFPReg; 196b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode op = kX86Nop; 197fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 198b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers switch (opcode) { 199b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::INT_TO_FLOAT: 2005121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao rcSrc = kCoreReg; 201b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86Cvtsi2ssRR; 202b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 203b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DOUBLE_TO_FLOAT: 2045121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao rcSrc = kFPReg; 205b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86Cvtsd2ssRR; 206b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 207b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::FLOAT_TO_DOUBLE: 2085121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao rcSrc = kFPReg; 209b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86Cvtss2sdRR; 210b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 211b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::INT_TO_DOUBLE: 2125121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao rcSrc = kCoreReg; 213b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86Cvtsi2sdRR; 214b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 215292188d514c9826971308a18fcc5a66261729f3bjeffhao case Instruction::FLOAT_TO_INT: { 2161fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValue(rl_src, kFPReg); 217078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 2181fd3346740dfb7f47be9922312b68a4227fada96buzbee ClobberSReg(rl_dest.s_reg_low); 2191fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kCoreReg, true); 220091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegStorage temp_reg = AllocTempSingle(); 22141005ddb5576b8630a1084fbb3979ffa602c0599jeffhao 2222700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstant(rl_result.reg, 0x7fffffff); 223091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86Cvtsi2ssRR, temp_reg.GetReg(), rl_result.reg.GetReg()); 224091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86ComissRR, rl_src.reg.GetReg(), temp_reg.GetReg()); 2255078d978f21620824d9c2fdcd73063260592398cSerguei Katkov LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondAe); 2261fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP); 227091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86Cvttss2siRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 2281fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_normal = NewLIR1(kX86Jmp8, 0); 2291fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_na_n->target = NewLIR0(kPseudoTargetLabel); 23000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Xor32RR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 2311fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel); 2321fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_normal->target = NewLIR0(kPseudoTargetLabel); 2331fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 234a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 235292188d514c9826971308a18fcc5a66261729f3bjeffhao } 236292188d514c9826971308a18fcc5a66261729f3bjeffhao case Instruction::DOUBLE_TO_INT: { 2371fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValueWide(rl_src, kFPReg); 238078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 2391fd3346740dfb7f47be9922312b68a4227fada96buzbee ClobberSReg(rl_dest.s_reg_low); 2401fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kCoreReg, true); 241091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegStorage temp_reg = AllocTempDouble(); 24241005ddb5576b8630a1084fbb3979ffa602c0599jeffhao 2432700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstant(rl_result.reg, 0x7fffffff); 244091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86Cvtsi2sdRR, temp_reg.GetReg(), rl_result.reg.GetReg()); 245091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86ComisdRR, rl_src.reg.GetReg(), temp_reg.GetReg()); 2465078d978f21620824d9c2fdcd73063260592398cSerguei Katkov LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondAe); 2471fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP); 248091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86Cvttsd2siRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 2491fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_normal = NewLIR1(kX86Jmp8, 0); 2501fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_na_n->target = NewLIR0(kPseudoTargetLabel); 25100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Xor32RR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 2521fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel); 2531fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_normal->target = NewLIR0(kPseudoTargetLabel); 2541fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 255a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 256292188d514c9826971308a18fcc5a66261729f3bjeffhao } 257b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::LONG_TO_DOUBLE: 258dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 259a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rcSrc = kCoreReg; 260a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu op = kX86Cvtsqi2sdRR; 261a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu break; 262a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu } 263614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru GenLongToFP(rl_dest, rl_src, true /* is_double */); 264a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 265b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::LONG_TO_FLOAT: 266dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 267a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rcSrc = kCoreReg; 268a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu op = kX86Cvtsqi2ssRR; 269a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu break; 270a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu } 271614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru GenLongToFP(rl_dest, rl_src, false /* is_double */); 272a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 27341005ddb5576b8630a1084fbb3979ffa602c0599jeffhao case Instruction::FLOAT_TO_LONG: 274dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 275a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rl_src = LoadValue(rl_src, kFPReg); 276a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu // If result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 277a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu ClobberSReg(rl_dest.s_reg_low); 278a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rl_result = EvalLoc(rl_dest, kCoreReg, true); 279a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu RegStorage temp_reg = AllocTempSingle(); 280a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu 281a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu // Set 0x7fffffffffffffff to rl_result 282a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LoadConstantWide(rl_result.reg, 0x7fffffffffffffff); 283a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Cvtsqi2ssRR, temp_reg.GetReg(), rl_result.reg.GetReg()); 284a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86ComissRR, rl_src.reg.GetReg(), temp_reg.GetReg()); 2855078d978f21620824d9c2fdcd73063260592398cSerguei Katkov LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondAe); 286a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP); 287a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Cvttss2sqiRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 288a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LIR* branch_normal = NewLIR1(kX86Jmp8, 0); 289a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_na_n->target = NewLIR0(kPseudoTargetLabel); 290a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Xor64RR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 291a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel); 292a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_normal->target = NewLIR0(kPseudoTargetLabel); 293a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu StoreValueWide(rl_dest, rl_result); 2949ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 295984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe GenConversionCall(kQuickF2l, rl_dest, rl_src); 2969ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 297a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 298b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DOUBLE_TO_LONG: 299dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 300a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rl_src = LoadValueWide(rl_src, kFPReg); 301a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu // If result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 302a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu ClobberSReg(rl_dest.s_reg_low); 303a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rl_result = EvalLoc(rl_dest, kCoreReg, true); 304a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu RegStorage temp_reg = AllocTempDouble(); 305a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu 306a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu // Set 0x7fffffffffffffff to rl_result 307a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LoadConstantWide(rl_result.reg, 0x7fffffffffffffff); 308a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Cvtsqi2sdRR, temp_reg.GetReg(), rl_result.reg.GetReg()); 309a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86ComisdRR, rl_src.reg.GetReg(), temp_reg.GetReg()); 3105078d978f21620824d9c2fdcd73063260592398cSerguei Katkov LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondAe); 311a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP); 312a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Cvttsd2sqiRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 313a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LIR* branch_normal = NewLIR1(kX86Jmp8, 0); 314a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_na_n->target = NewLIR0(kPseudoTargetLabel); 315a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Xor64RR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 316a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel); 317a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_normal->target = NewLIR0(kPseudoTargetLabel); 318a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu StoreValueWide(rl_dest, rl_result); 3199ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 320984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe GenConversionCall(kQuickD2l, rl_dest, rl_src); 3219ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 322a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 323b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 324a5954be0aac5edd892fb31a209960543d00e4500buzbee LOG(INFO) << "Unexpected opcode: " << opcode; 325b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 326091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // At this point, target will be either float or double. 327091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_dest.fp); 328fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (rl_src.wide) { 3291fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValueWide(rl_src, rcSrc); 330b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 3311fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValue(rl_src, rcSrc); 332b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 333091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 334091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(op, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 335fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (rl_dest.wide) { 3361fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_result); 337b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 3381fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 339b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 340e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 341e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 342bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalovvoid X86Mir2Lir::GenRemFP(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2, bool is_double) { 343bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Compute offsets to the source and destination VRs on stack. 344bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int src1_v_reg_offset = SRegOffset(rl_src1.s_reg_low); 345bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int src2_v_reg_offset = SRegOffset(rl_src2.s_reg_low); 346bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int dest_v_reg_offset = SRegOffset(rl_dest.s_reg_low); 347bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 348bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Update the in-register state of sources. 349bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov rl_src1 = is_double ? UpdateLocWide(rl_src1) : UpdateLoc(rl_src1); 350bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov rl_src2 = is_double ? UpdateLocWide(rl_src2) : UpdateLoc(rl_src2); 351bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 352bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // All memory accesses below reference dalvik regs. 353bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 354bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 355bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // If the source is in physical register, then put it in its location on stack. 356bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (rl_src1.location == kLocPhysReg) { 357bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov RegisterInfo* reg_info = GetRegInfo(rl_src1.reg); 358bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 359bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (reg_info != nullptr && reg_info->IsTemp()) { 360bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Calling FlushSpecificReg because it will only write back VR if it is dirty. 361bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov FlushSpecificReg(reg_info); 362bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // ResetDef to prevent NullifyRange from removing stores. 363bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov ResetDef(rl_src1.reg); 364bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } else { 365bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // It must have been register promoted if it is not a temp but is still in physical 366bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // register. Since we need it to be in memory to convert, we place it there now. 367a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, src1_v_reg_offset, rl_src1.reg, is_double ? k64 : k32, 3683c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe kNotVolatile); 369bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 370bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 371bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 372bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (rl_src2.location == kLocPhysReg) { 373bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov RegisterInfo* reg_info = GetRegInfo(rl_src2.reg); 374bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (reg_info != nullptr && reg_info->IsTemp()) { 375bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov FlushSpecificReg(reg_info); 376bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov ResetDef(rl_src2.reg); 377bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } else { 378a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, src2_v_reg_offset, rl_src2.reg, is_double ? k64 : k32, 3793c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe kNotVolatile); 380bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 381bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 382bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 383bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int fld_opcode = is_double ? kX86Fld64M : kX86Fld32M; 384bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 385bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Push the source virtual registers onto the x87 stack. 386a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LIR *fld_2 = NewLIR2NoDest(fld_opcode, rs_rX86_SP.GetReg(), 387bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov src2_v_reg_offset + LOWORD_OFFSET); 388bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov AnnotateDalvikRegAccess(fld_2, (src2_v_reg_offset + LOWORD_OFFSET) >> 2, 389bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov true /* is_load */, is_double /* is64bit */); 390bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 391a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LIR *fld_1 = NewLIR2NoDest(fld_opcode, rs_rX86_SP.GetReg(), 392bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov src1_v_reg_offset + LOWORD_OFFSET); 393bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov AnnotateDalvikRegAccess(fld_1, (src1_v_reg_offset + LOWORD_OFFSET) >> 2, 394bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov true /* is_load */, is_double /* is64bit */); 395bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 396bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov FlushReg(rs_rAX); 397bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov Clobber(rs_rAX); 398bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov LockTemp(rs_rAX); 399bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 400bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov LIR* retry = NewLIR0(kPseudoTargetLabel); 401bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 402bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Divide ST(0) by ST(1) and place result to ST(0). 403bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov NewLIR0(kX86Fprem); 404bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 405bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Move FPU status word to AX. 406bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov NewLIR0(kX86Fstsw16R); 407bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 408bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Check if reduction is complete. 409bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov OpRegImm(kOpAnd, rs_rAX, 0x400); 410bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 411bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // If no then continue to compute remainder. 412bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov LIR* branch = NewLIR2(kX86Jcc8, 0, kX86CondNe); 413bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov branch->target = retry; 414bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 415bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov FreeTemp(rs_rAX); 416bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 417bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Now store result in the destination VR's stack location. 418bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int displacement = dest_v_reg_offset + LOWORD_OFFSET; 419bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int opcode = is_double ? kX86Fst64M : kX86Fst32M; 420a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LIR *fst = NewLIR2NoDest(opcode, rs_rX86_SP.GetReg(), displacement); 421bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov AnnotateDalvikRegAccess(fst, displacement >> 2, false /* is_load */, is_double /* is64bit */); 422bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 423bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Pop ST(1) and ST(0). 424bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov NewLIR0(kX86Fucompp); 425bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 426bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov /* 427bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * The result is in a physical register if it was in a temp or was register 428bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * promoted. For that reason it is enough to check if it is in physical 429bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * register. If it is, then we must do all of the bookkeeping necessary to 430bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * invalidate temp (if needed) and load in promoted register (if needed). 431bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * If the result's location is in memory, then we do not need to do anything 432bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * more since the fstp has already placed the correct value in memory. 433bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov */ 434bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov RegLocation rl_result = is_double ? UpdateLocWideTyped(rl_dest, kFPReg) : 435bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov UpdateLocTyped(rl_dest, kFPReg); 436bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (rl_result.location == kLocPhysReg) { 437bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov rl_result = EvalLoc(rl_dest, kFPReg, true); 438bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (is_double) { 439a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LoadBaseDisp(rs_rX86_SP, dest_v_reg_offset, rl_result.reg, k64, kNotVolatile); 440bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov StoreFinalValueWide(rl_dest, rl_result); 441bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } else { 442a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu Load32Disp(rs_rX86_SP, dest_v_reg_offset, rl_result.reg); 443bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov StoreFinalValue(rl_dest, rl_result); 444bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 445bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 446bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov} 447bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 4481fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenCmpFP(Instruction::Code code, RegLocation rl_dest, 44902031b185b4653e6c72e21f7a51238b903f6d638buzbee RegLocation rl_src1, RegLocation rl_src2) { 450b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers bool single = (code == Instruction::CMPL_FLOAT) || (code == Instruction::CMPG_FLOAT); 451fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bool unordered_gt = (code == Instruction::CMPG_DOUBLE) || (code == Instruction::CMPG_FLOAT); 452b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (single) { 4531fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValue(rl_src1, kFPReg); 4541fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValue(rl_src2, kFPReg); 455b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 4561fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValueWide(rl_src1, kFPReg); 4571fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValueWide(rl_src2, kFPReg); 458b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 459078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 4601fd3346740dfb7f47be9922312b68a4227fada96buzbee ClobberSReg(rl_dest.s_reg_low); 4611fd3346740dfb7f47be9922312b68a4227fada96buzbee RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 4622700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantNoClobber(rl_result.reg, unordered_gt ? 1 : 0); 463b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (single) { 464091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86UcomissRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 465b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 466091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86UcomisdRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 467b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 468b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers LIR* branch = NULL; 469fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (unordered_gt) { 4701fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 471b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 472703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao // If the result reg can't be byte accessed, use a jump and move instead of a set. 4737e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu if (!IsByteRegister(rl_result.reg)) { 474703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao LIR* branch2 = NULL; 475fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (unordered_gt) { 4761fd3346740dfb7f47be9922312b68a4227fada96buzbee branch2 = NewLIR2(kX86Jcc8, 0, kX86CondA); 47700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Mov32RI, rl_result.reg.GetReg(), 0x0); 478703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } else { 4791fd3346740dfb7f47be9922312b68a4227fada96buzbee branch2 = NewLIR2(kX86Jcc8, 0, kX86CondBe); 48000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Mov32RI, rl_result.reg.GetReg(), 0x1); 481703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } 4821fd3346740dfb7f47be9922312b68a4227fada96buzbee branch2->target = NewLIR0(kPseudoTargetLabel); 483703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } else { 48400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Set8R, rl_result.reg.GetReg(), kX86CondA /* above - unsigned > */); 485703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } 48600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Sbb32RI, rl_result.reg.GetReg(), 0); 487fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (unordered_gt) { 4881fd3346740dfb7f47be9922312b68a4227fada96buzbee branch->target = NewLIR0(kPseudoTargetLabel); 489b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 4901fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 491e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 492e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 4931fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, 49402031b185b4653e6c72e21f7a51238b903f6d638buzbee bool is_double) { 4950d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee LIR* taken = &block_label_list_[bb->taken]; 4960d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee LIR* not_taken = &block_label_list_[bb->fall_through]; 4974b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao LIR* branch = NULL; 498fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_src1; 499fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_src2; 500fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (is_double) { 5011fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = mir_graph_->GetSrcWide(mir, 0); 5021fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = mir_graph_->GetSrcWide(mir, 2); 5031fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValueWide(rl_src1, kFPReg); 5041fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValueWide(rl_src2, kFPReg); 505091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86UcomisdRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 5064b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } else { 5071fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = mir_graph_->GetSrc(mir, 0); 5081fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = mir_graph_->GetSrc(mir, 1); 5091fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValue(rl_src1, kFPReg); 5101fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValue(rl_src2, kFPReg); 51100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86UcomissRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 5124b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 513a894607bca7eb623bc957363e4b36f44cfeea1b6Vladimir Marko ConditionCode ccode = mir->meta.ccode; 5144b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao switch (ccode) { 5154b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondEq: 516fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!gt_bias) { 5171fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 518fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee branch->target = not_taken; 5194b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5204b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5214b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondNe: 522fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!gt_bias) { 5231fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 5244b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao branch->target = taken; 5254b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5264b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5274b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondLt: 528fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 5291fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 530fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee branch->target = not_taken; 5314b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 53258af1f9385742f70aca4fcb5e13aba53b8be2ef4Vladimir Marko ccode = kCondUlt; 5334b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5344b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondLe: 535fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 5361fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 537fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee branch->target = not_taken; 5384b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5394b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao ccode = kCondLs; 5404b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5414b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondGt: 542fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 5431fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 5444b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao branch->target = taken; 5454b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5464b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao ccode = kCondHi; 5474b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5484b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondGe: 549fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 5501fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 5514b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao branch->target = taken; 5524b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 55358af1f9385742f70aca4fcb5e13aba53b8be2ef4Vladimir Marko ccode = kCondUge; 5544b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5554b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao default: 556cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(FATAL) << "Unexpected ccode: " << ccode; 5574b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5581fd3346740dfb7f47be9922312b68a4227fada96buzbee OpCondBranch(ccode, taken); 5594b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao} 5604b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao 5612ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) { 562fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 5631fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValue(rl_src, kCoreReg); 5641fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kCoreReg, true); 5652700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000); 5661fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 567efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 568efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5692ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) { 570fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 5711fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValueWide(rl_src, kCoreReg); 572a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rl_result = EvalLocWide(rl_dest, kCoreReg, true); 573dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 57402959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov OpRegCopy(rl_result.reg, rl_src.reg); 57502959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov // Flip sign bit. 57602959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov NewLIR2(kX86Rol64RI, rl_result.reg.GetReg(), 1); 57702959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov NewLIR2(kX86Xor64RI, rl_result.reg.GetReg(), 1); 57802959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov NewLIR2(kX86Ror64RI, rl_result.reg.GetReg(), 1); 579a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu } else { 580a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000); 581a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu OpRegCopy(rl_result.reg, rl_src.reg); 582a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu } 5831fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_result); 584efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 585efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5861fd3346740dfb7f47be9922312b68a4227fada96buzbeebool X86Mir2Lir::GenInlinedSqrt(CallInfo* info) { 587bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell RegLocation rl_src = info->args[0]; 588bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell RegLocation rl_dest = InlineTargetWide(info); // double place for result 589bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell rl_src = LoadValueWide(rl_src, kFPReg); 590bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true); 591091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86SqrtsdRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 592bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell StoreValueWide(rl_dest, rl_result); 593bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell return true; 594efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 595efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5967071c8d5885175a746723a3b38a347855965be08Yixin Shoubool X86Mir2Lir::GenInlinedAbsFloat(CallInfo* info) { 5977071c8d5885175a746723a3b38a347855965be08Yixin Shou // Get the argument 5987071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_src = info->args[0]; 5997071c8d5885175a746723a3b38a347855965be08Yixin Shou 6007071c8d5885175a746723a3b38a347855965be08Yixin Shou // Get the inlined intrinsic target virtual register 6017071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_dest = InlineTarget(info); 6027071c8d5885175a746723a3b38a347855965be08Yixin Shou 6037071c8d5885175a746723a3b38a347855965be08Yixin Shou // Get the virtual register number 6047071c8d5885175a746723a3b38a347855965be08Yixin Shou DCHECK_NE(rl_src.s_reg_low, INVALID_SREG); 6057071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_dest.s_reg_low == INVALID_SREG) { 6067071c8d5885175a746723a3b38a347855965be08Yixin Shou // Result is unused, the code is dead. Inlining successful, no code generated. 6077071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6087071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6097071c8d5885175a746723a3b38a347855965be08Yixin Shou int v_src_reg = mir_graph_->SRegToVReg(rl_src.s_reg_low); 6107071c8d5885175a746723a3b38a347855965be08Yixin Shou int v_dst_reg = mir_graph_->SRegToVReg(rl_dest.s_reg_low); 6117071c8d5885175a746723a3b38a347855965be08Yixin Shou 6127071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is the same as inlined intrinsic target 6137071c8d5885175a746723a3b38a347855965be08Yixin Shou if (v_src_reg == v_dst_reg) { 6147071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = UpdateLoc(rl_src); 6157071c8d5885175a746723a3b38a347855965be08Yixin Shou 6167071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is in the physical register 6177071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_src.location == kLocPhysReg) { 6187071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = LoadValue(rl_src, kCoreReg); 6197071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegImm(kOpAnd, rl_src.reg, 0x7fffffff); 6207071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValue(rl_dest, rl_src); 6217071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6227071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6237071c8d5885175a746723a3b38a347855965be08Yixin Shou // the argument is in memory 6247071c8d5885175a746723a3b38a347855965be08Yixin Shou DCHECK((rl_src.location == kLocDalvikFrame) || 6257071c8d5885175a746723a3b38a347855965be08Yixin Shou (rl_src.location == kLocCompilerTemp)); 6267071c8d5885175a746723a3b38a347855965be08Yixin Shou 6277071c8d5885175a746723a3b38a347855965be08Yixin Shou // Operate directly into memory. 6287071c8d5885175a746723a3b38a347855965be08Yixin Shou int displacement = SRegOffset(rl_dest.s_reg_low); 6297071c8d5885175a746723a3b38a347855965be08Yixin Shou ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 630a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LIR *lir = NewLIR3(kX86And32MI, rs_rX86_SP.GetReg(), displacement, 0x7fffffff); 6317071c8d5885175a746723a3b38a347855965be08Yixin Shou AnnotateDalvikRegAccess(lir, displacement >> 2, false /*is_load */, false /* is_64bit */); 6327071c8d5885175a746723a3b38a347855965be08Yixin Shou AnnotateDalvikRegAccess(lir, displacement >> 2, true /* is_load */, false /* is_64bit*/); 6337071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6347071c8d5885175a746723a3b38a347855965be08Yixin Shou } else { 6357071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = LoadValue(rl_src, kCoreReg); 6367071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 6377071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegRegImm(kOpAnd, rl_result.reg, rl_src.reg, 0x7fffffff); 6387071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValue(rl_dest, rl_result); 6397071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6407071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6417071c8d5885175a746723a3b38a347855965be08Yixin Shou} 6427071c8d5885175a746723a3b38a347855965be08Yixin Shou 6437071c8d5885175a746723a3b38a347855965be08Yixin Shoubool X86Mir2Lir::GenInlinedAbsDouble(CallInfo* info) { 6447071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_src = info->args[0]; 6457071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_dest = InlineTargetWide(info); 6467071c8d5885175a746723a3b38a347855965be08Yixin Shou DCHECK_NE(rl_src.s_reg_low, INVALID_SREG); 6477071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_dest.s_reg_low == INVALID_SREG) { 6487071c8d5885175a746723a3b38a347855965be08Yixin Shou // Result is unused, the code is dead. Inlining successful, no code generated. 6497071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6507071c8d5885175a746723a3b38a347855965be08Yixin Shou } 651c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk if (cu_->target64) { 652c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk rl_src = LoadValueWide(rl_src, kCoreReg); 653c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 654c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk OpRegCopyWide(rl_result.reg, rl_src.reg); 655c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk OpRegImm(kOpLsl, rl_result.reg, 1); 656c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk OpRegImm(kOpLsr, rl_result.reg, 1); 657c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk StoreValueWide(rl_dest, rl_result); 658c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk return true; 659c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk } 6607071c8d5885175a746723a3b38a347855965be08Yixin Shou int v_src_reg = mir_graph_->SRegToVReg(rl_src.s_reg_low); 6617071c8d5885175a746723a3b38a347855965be08Yixin Shou int v_dst_reg = mir_graph_->SRegToVReg(rl_dest.s_reg_low); 6627071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = UpdateLocWide(rl_src); 6637071c8d5885175a746723a3b38a347855965be08Yixin Shou 6647071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is in the physical XMM register 6657071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_src.location == kLocPhysReg && rl_src.reg.IsFloat()) { 6667071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true); 6677071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_result.reg != rl_src.reg) { 6687071c8d5885175a746723a3b38a347855965be08Yixin Shou LoadConstantWide(rl_result.reg, 0x7fffffffffffffff); 6697071c8d5885175a746723a3b38a347855965be08Yixin Shou NewLIR2(kX86PandRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 6707071c8d5885175a746723a3b38a347855965be08Yixin Shou } else { 6717071c8d5885175a746723a3b38a347855965be08Yixin Shou RegStorage sign_mask = AllocTempDouble(); 6727071c8d5885175a746723a3b38a347855965be08Yixin Shou LoadConstantWide(sign_mask, 0x7fffffffffffffff); 6737071c8d5885175a746723a3b38a347855965be08Yixin Shou NewLIR2(kX86PandRR, rl_result.reg.GetReg(), sign_mask.GetReg()); 6747071c8d5885175a746723a3b38a347855965be08Yixin Shou FreeTemp(sign_mask); 6757071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6767071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValueWide(rl_dest, rl_result); 6777071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6787071c8d5885175a746723a3b38a347855965be08Yixin Shou } else if (v_src_reg == v_dst_reg) { 6797071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is the same as inlined intrinsic target 6807071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is in the physical register 6817071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_src.location == kLocPhysReg) { 6827071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = LoadValueWide(rl_src, kCoreReg); 6837071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegImm(kOpAnd, rl_src.reg.GetHigh(), 0x7fffffff); 6847071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValueWide(rl_dest, rl_src); 6857071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6867071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6877071c8d5885175a746723a3b38a347855965be08Yixin Shou // the argument is in memory 6887071c8d5885175a746723a3b38a347855965be08Yixin Shou DCHECK((rl_src.location == kLocDalvikFrame) || 6897071c8d5885175a746723a3b38a347855965be08Yixin Shou (rl_src.location == kLocCompilerTemp)); 6907071c8d5885175a746723a3b38a347855965be08Yixin Shou 6917071c8d5885175a746723a3b38a347855965be08Yixin Shou // Operate directly into memory. 6927071c8d5885175a746723a3b38a347855965be08Yixin Shou int displacement = SRegOffset(rl_dest.s_reg_low); 6937071c8d5885175a746723a3b38a347855965be08Yixin Shou ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 694a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LIR *lir = NewLIR3(kX86And32MI, rs_rX86_SP.GetReg(), displacement + HIWORD_OFFSET, 0x7fffffff); 6957071c8d5885175a746723a3b38a347855965be08Yixin Shou AnnotateDalvikRegAccess(lir, (displacement + HIWORD_OFFSET) >> 2, true /* is_load */, true /* is_64bit*/); 6967071c8d5885175a746723a3b38a347855965be08Yixin Shou AnnotateDalvikRegAccess(lir, (displacement + HIWORD_OFFSET) >> 2, false /*is_load */, true /* is_64bit */); 6977071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6987071c8d5885175a746723a3b38a347855965be08Yixin Shou } else { 6997071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = LoadValueWide(rl_src, kCoreReg); 7007071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 7017071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegCopyWide(rl_result.reg, rl_src.reg); 7027071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegImm(kOpAnd, rl_result.reg.GetHigh(), 0x7fffffff); 7037071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValueWide(rl_dest, rl_result); 7047071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 7057071c8d5885175a746723a3b38a347855965be08Yixin Shou } 7067071c8d5885175a746723a3b38a347855965be08Yixin Shou} 707efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 7081222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalovbool X86Mir2Lir::GenInlinedMinMaxFP(CallInfo* info, bool is_min, bool is_double) { 7091222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov if (is_double) { 7101222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov RegLocation rl_src1 = LoadValueWide(info->args[0], kFPReg); 7111222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov RegLocation rl_src2 = LoadValueWide(info->args[2], kFPReg); 7121222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov RegLocation rl_dest = InlineTargetWide(info); 7131222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov RegLocation rl_result = EvalLocWide(rl_dest, kFPReg, true); 7141222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov 7151222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Avoid src2 corruption by OpRegCopyWide. 7161222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov if (rl_result.reg == rl_src2.reg) { 7171222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov std::swap(rl_src2.reg, rl_src1.reg); 7181222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov } 7191222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov 7201222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov OpRegCopyWide(rl_result.reg, rl_src1.reg); 7211222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov NewLIR2(kX86UcomisdRR, rl_result.reg.GetReg(), rl_src2.reg.GetReg()); 7221222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // If either arg is NaN, return NaN. 7231222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_nan = NewLIR2(kX86Jcc8, 0, kX86CondP); 7241222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Min/Max branches. 7251222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_cond1 = NewLIR2(kX86Jcc8, 0, (is_min) ? kX86CondA : kX86CondB); 7261222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_cond2 = NewLIR2(kX86Jcc8, 0, (is_min) ? kX86CondB : kX86CondA); 7271222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // If equal, we need to resolve situations like min/max(0.0, -0.0) == -0.0/0.0. 7281222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov NewLIR2((is_min) ? kX86OrpdRR : kX86AndpdRR, rl_result.reg.GetReg(), rl_src2.reg.GetReg()); 7291222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_exit_equal = NewLIR1(kX86Jmp8, 0); 7301222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Handle NaN. 7311222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_nan->target = NewLIR0(kPseudoTargetLabel); 7321222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LoadConstantWide(rl_result.reg, INT64_C(0x7ff8000000000000)); 7331222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_exit_nan = NewLIR1(kX86Jmp8, 0); 7341222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Handle Min/Max. Copy greater/lesser value from src2. 7351222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_cond1->target = NewLIR0(kPseudoTargetLabel); 7361222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov OpRegCopyWide(rl_result.reg, rl_src2.reg); 7371222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Right operand is already in result reg. 7381222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_cond2->target = NewLIR0(kPseudoTargetLabel); 7391222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Exit. 7401222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_exit_nan->target = NewLIR0(kPseudoTargetLabel); 7411222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_exit_equal->target = NewLIR0(kPseudoTargetLabel); 7421222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov StoreValueWide(rl_dest, rl_result); 7431222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov } else { 7441222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov RegLocation rl_src1 = LoadValue(info->args[0], kFPReg); 7451222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov RegLocation rl_src2 = LoadValue(info->args[1], kFPReg); 7461222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov RegLocation rl_dest = InlineTarget(info); 7471222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true); 7481222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov 7491222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Avoid src2 corruption by OpRegCopyWide. 7501222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov if (rl_result.reg == rl_src2.reg) { 7511222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov std::swap(rl_src2.reg, rl_src1.reg); 7521222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov } 7531222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov 7541222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov OpRegCopy(rl_result.reg, rl_src1.reg); 7551222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov NewLIR2(kX86UcomissRR, rl_result.reg.GetReg(), rl_src2.reg.GetReg()); 7561222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // If either arg is NaN, return NaN. 7571222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_nan = NewLIR2(kX86Jcc8, 0, kX86CondP); 7581222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Min/Max branches. 7591222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_cond1 = NewLIR2(kX86Jcc8, 0, (is_min) ? kX86CondA : kX86CondB); 7601222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_cond2 = NewLIR2(kX86Jcc8, 0, (is_min) ? kX86CondB : kX86CondA); 7611222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // If equal, we need to resolve situations like min/max(0.0, -0.0) == -0.0/0.0. 7621222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov NewLIR2((is_min) ? kX86OrpsRR : kX86AndpsRR, rl_result.reg.GetReg(), rl_src2.reg.GetReg()); 7631222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_exit_equal = NewLIR1(kX86Jmp8, 0); 7641222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Handle NaN. 7651222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_nan->target = NewLIR0(kPseudoTargetLabel); 7661222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LoadConstantNoClobber(rl_result.reg, 0x7fc00000); 7671222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_exit_nan = NewLIR1(kX86Jmp8, 0); 7681222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Handle Min/Max. Copy greater/lesser value from src2. 7691222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_cond1->target = NewLIR0(kPseudoTargetLabel); 7701222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov OpRegCopy(rl_result.reg, rl_src2.reg); 7711222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Right operand is already in result reg. 7721222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_cond2->target = NewLIR0(kPseudoTargetLabel); 7731222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Exit. 7741222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_exit_nan->target = NewLIR0(kPseudoTargetLabel); 7751222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_exit_equal->target = NewLIR0(kPseudoTargetLabel); 7761222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov StoreValue(rl_dest, rl_result); 7771222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov } 7781222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov return true; 7791222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov} 7801222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov 7817934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom} // namespace art 782