1e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee/* 2e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * Copyright (C) 2012 The Android Open Source Project 3e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * 4e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * Licensed under the Apache License, Version 2.0 (the "License"); 5e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * you may not use this file except in compliance with the License. 6e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * You may obtain a copy of the License at 7e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * 8e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * http://www.apache.org/licenses/LICENSE-2.0 9e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * 10e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * Unless required by applicable law or agreed to in writing, software 11e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * distributed under the License is distributed on an "AS IS" BASIS, 12e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * See the License for the specific language governing permissions and 14e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * limitations under the License. 15e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee */ 16e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 1702031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_x86.h" 180b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe 190b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "base/logging.h" 207940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h" 21b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee#include "dex/reg_storage_eq.h" 22641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "x86_lir.h" 231bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 24e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbeenamespace art { 25e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 261fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenArithOpFloat(Instruction::Code opcode, 2702031b185b4653e6c72e21f7a51238b903f6d638buzbee RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { 28b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode op = kX86Nop; 29fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 30e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 31b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers /* 32b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers * Don't attempt to optimize register usage since these opcodes call out to 33b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers * the handlers. 34b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers */ 35408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee switch (opcode) { 36b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::ADD_FLOAT_2ADDR: 37b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::ADD_FLOAT: 38b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86AddssRR; 39b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 40b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::SUB_FLOAT_2ADDR: 41b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::SUB_FLOAT: 42b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86SubssRR; 43b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 44b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DIV_FLOAT_2ADDR: 45b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DIV_FLOAT: 46b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86DivssRR; 47b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 48b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::MUL_FLOAT_2ADDR: 49b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::MUL_FLOAT: 50b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86MulssRR; 51b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 52b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::REM_FLOAT_2ADDR: 53babda950caf2d577aa57102c3281f0f3c36f3d6djeffhao case Instruction::REM_FLOAT: 54bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov GenRemFP(rl_dest, rl_src1, rl_src2, false /* is_double */); 55a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 56a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee case Instruction::NEG_FLOAT: 571fd3346740dfb7f47be9922312b68a4227fada96buzbee GenNegFloat(rl_dest, rl_src1); 58a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 59b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 60a5954be0aac5edd892fb31a209960543d00e4500buzbee LOG(FATAL) << "Unexpected opcode: " << opcode; 61b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 621fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValue(rl_src1, kFPReg); 631fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValue(rl_src2, kFPReg); 641fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 652700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_dest = rl_result.reg; 662700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_src1 = rl_src1.reg; 672700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage r_src2 = rl_src2.reg; 68fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (r_dest == r_src2) { 69091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee r_src2 = AllocTempSingle(); 701fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_src2, r_dest); 714abb1a9000b525a0636763a97528e24468f16d10jeffhao } 721fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(r_dest, r_src1); 732700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee NewLIR2(op, r_dest.GetReg(), r_src2.GetReg()); 741fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 75e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 76e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 771fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenArithOpDouble(Instruction::Code opcode, 7802031b185b4653e6c72e21f7a51238b903f6d638buzbee RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { 79091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_dest.wide); 80091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_dest.fp); 81091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_src1.wide); 82091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_src1.fp); 83091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_src2.wide); 84091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_src2.fp); 85b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode op = kX86Nop; 86fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 87e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 88408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee switch (opcode) { 89b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::ADD_DOUBLE_2ADDR: 90b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::ADD_DOUBLE: 91b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86AddsdRR; 92b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 93b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::SUB_DOUBLE_2ADDR: 94b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::SUB_DOUBLE: 95b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86SubsdRR; 96b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 97b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DIV_DOUBLE_2ADDR: 98b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DIV_DOUBLE: 99b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86DivsdRR; 100b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 101b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::MUL_DOUBLE_2ADDR: 102b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::MUL_DOUBLE: 103b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86MulsdRR; 104b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 105b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::REM_DOUBLE_2ADDR: 106babda950caf2d577aa57102c3281f0f3c36f3d6djeffhao case Instruction::REM_DOUBLE: 107bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov GenRemFP(rl_dest, rl_src1, rl_src2, true /* is_double */); 108a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 109a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee case Instruction::NEG_DOUBLE: 1101fd3346740dfb7f47be9922312b68a4227fada96buzbee GenNegDouble(rl_dest, rl_src1); 111a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 112b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 113a5954be0aac5edd892fb31a209960543d00e4500buzbee LOG(FATAL) << "Unexpected opcode: " << opcode; 114b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 1151fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValueWide(rl_src1, kFPReg); 1161fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValueWide(rl_src2, kFPReg); 1171fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 118091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (rl_result.reg == rl_src2.reg) { 119091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rl_src2.reg = AllocTempDouble(); 120091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee OpRegCopy(rl_src2.reg, rl_result.reg); 1214abb1a9000b525a0636763a97528e24468f16d10jeffhao } 122091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee OpRegCopy(rl_result.reg, rl_src1.reg); 123091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(op, rl_result.reg.GetReg(), rl_src2.reg.GetReg()); 1241fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_result); 125e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 126e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 127675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jianvoid X86Mir2Lir::GenMultiplyByConstantFloat(RegLocation rl_dest, RegLocation rl_src1, 128675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian int32_t constant) { 129675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian // TODO: need x86 implementation. 130675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian UNUSED(rl_dest, rl_src1, constant); 131675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian LOG(FATAL) << "Unimplemented GenMultiplyByConstantFloat in x86"; 132675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian} 133675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian 134675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jianvoid X86Mir2Lir::GenMultiplyByConstantDouble(RegLocation rl_dest, RegLocation rl_src1, 135675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian int64_t constant) { 136675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian // TODO: need x86 implementation. 137675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian UNUSED(rl_dest, rl_src1, constant); 138675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian LOG(FATAL) << "Unimplemented GenMultiplyByConstantDouble in x86"; 139675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian} 140675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian 141614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoruvoid X86Mir2Lir::GenLongToFP(RegLocation rl_dest, RegLocation rl_src, bool is_double) { 142614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Compute offsets to the source and destination VRs on stack 143614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru int src_v_reg_offset = SRegOffset(rl_src.s_reg_low); 144614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru int dest_v_reg_offset = SRegOffset(rl_dest.s_reg_low); 145614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 146614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Update the in-register state of source. 147614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru rl_src = UpdateLocWide(rl_src); 148614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 1498dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko // All memory accesses below reference dalvik regs. 1508dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 1518dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko 152614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // If the source is in physical register, then put it in its location on stack. 153614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru if (rl_src.location == kLocPhysReg) { 154091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegisterInfo* reg_info = GetRegInfo(rl_src.reg); 155614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 156091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (reg_info != nullptr && reg_info->IsTemp()) { 157614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Calling FlushSpecificReg because it will only write back VR if it is dirty. 158091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FlushSpecificReg(reg_info); 159091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // ResetDef to prevent NullifyRange from removing stores. 160091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee ResetDef(rl_src.reg); 161614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } else { 162614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // It must have been register promoted if it is not a temp but is still in physical 163614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // register. Since we need it to be in memory to convert, we place it there now. 164b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const RegStorage rs_rSP = cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32; 165b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers StoreBaseDisp(rs_rSP, src_v_reg_offset, rl_src.reg, k64, kNotVolatile); 166614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } 167614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } 168614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 169614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Push the source virtual register onto the x87 stack. 170b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LIR *fild64 = NewLIR2NoDest(kX86Fild64M, rs_rX86_SP_32.GetReg(), 171091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee src_v_reg_offset + LOWORD_OFFSET); 172614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru AnnotateDalvikRegAccess(fild64, (src_v_reg_offset + LOWORD_OFFSET) >> 2, 173091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee true /* is_load */, true /* is64bit */); 174614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 175614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru // Now pop off x87 stack and store it in the destination VR's stack location. 176614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru int opcode = is_double ? kX86Fstp64M : kX86Fstp32M; 177614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru int displacement = is_double ? dest_v_reg_offset + LOWORD_OFFSET : dest_v_reg_offset; 178b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LIR *fstp = NewLIR2NoDest(opcode, rs_rX86_SP_32.GetReg(), displacement); 179614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru AnnotateDalvikRegAccess(fstp, displacement >> 2, false /* is_load */, is_double); 180614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 181614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru /* 182614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * The result is in a physical register if it was in a temp or was register 183614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * promoted. For that reason it is enough to check if it is in physical 184614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * register. If it is, then we must do all of the bookkeeping necessary to 185614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * invalidate temp (if needed) and load in promoted register (if needed). 186614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * If the result's location is in memory, then we do not need to do anything 187614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * more since the fstp has already placed the correct value in memory. 188614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru */ 1896a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers RegLocation rl_result = is_double ? UpdateLocWideTyped(rl_dest) : UpdateLocTyped(rl_dest); 190614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru if (rl_result.location == kLocPhysReg) { 191614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru /* 192614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * We already know that the result is in a physical register but do not know if it is the 193614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * right class. So we call EvalLoc(Wide) first which will ensure that it will get moved to the 194614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru * correct register class. 195614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru */ 1968dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko rl_result = EvalLoc(rl_dest, kFPReg, true); 197b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const RegStorage rs_rSP = cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32; 198614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru if (is_double) { 199b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LoadBaseDisp(rs_rSP, dest_v_reg_offset, rl_result.reg, k64, kNotVolatile); 200614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 20151a80d72dc436a4a89c636987b9cedabe774fdd6Maxim Kazantsev StoreFinalValueWide(rl_dest, rl_result); 202614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } else { 203b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers Load32Disp(rs_rSP, dest_v_reg_offset, rl_result.reg); 204614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 20551a80d72dc436a4a89c636987b9cedabe774fdd6Maxim Kazantsev StoreFinalValue(rl_dest, rl_result); 206614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } 207614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru } 208614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru} 209614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru 2101fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest, 21102031b185b4653e6c72e21f7a51238b903f6d638buzbee RegLocation rl_src) { 2125121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao RegisterClass rcSrc = kFPReg; 213b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers X86OpCode op = kX86Nop; 214fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 215b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers switch (opcode) { 216b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::INT_TO_FLOAT: 2175121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao rcSrc = kCoreReg; 218b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86Cvtsi2ssRR; 219b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 220b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DOUBLE_TO_FLOAT: 2215121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao rcSrc = kFPReg; 222b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86Cvtsd2ssRR; 223b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 224b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::FLOAT_TO_DOUBLE: 2255121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao rcSrc = kFPReg; 226b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86Cvtss2sdRR; 227b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 228b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::INT_TO_DOUBLE: 2295121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao rcSrc = kCoreReg; 230b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers op = kX86Cvtsi2sdRR; 231b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers break; 232292188d514c9826971308a18fcc5a66261729f3bjeffhao case Instruction::FLOAT_TO_INT: { 2331fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValue(rl_src, kFPReg); 234078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 2351fd3346740dfb7f47be9922312b68a4227fada96buzbee ClobberSReg(rl_dest.s_reg_low); 2361fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kCoreReg, true); 237091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegStorage temp_reg = AllocTempSingle(); 23841005ddb5576b8630a1084fbb3979ffa602c0599jeffhao 2392700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstant(rl_result.reg, 0x7fffffff); 240091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86Cvtsi2ssRR, temp_reg.GetReg(), rl_result.reg.GetReg()); 241091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86ComissRR, rl_src.reg.GetReg(), temp_reg.GetReg()); 2425078d978f21620824d9c2fdcd73063260592398cSerguei Katkov LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondAe); 2431fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP); 244091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86Cvttss2siRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 2451fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_normal = NewLIR1(kX86Jmp8, 0); 2461fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_na_n->target = NewLIR0(kPseudoTargetLabel); 24700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Xor32RR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 2481fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel); 2491fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_normal->target = NewLIR0(kPseudoTargetLabel); 2501fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 251a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 252292188d514c9826971308a18fcc5a66261729f3bjeffhao } 253292188d514c9826971308a18fcc5a66261729f3bjeffhao case Instruction::DOUBLE_TO_INT: { 2541fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValueWide(rl_src, kFPReg); 255078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 2561fd3346740dfb7f47be9922312b68a4227fada96buzbee ClobberSReg(rl_dest.s_reg_low); 2571fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kCoreReg, true); 258091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegStorage temp_reg = AllocTempDouble(); 25941005ddb5576b8630a1084fbb3979ffa602c0599jeffhao 2602700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstant(rl_result.reg, 0x7fffffff); 261091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86Cvtsi2sdRR, temp_reg.GetReg(), rl_result.reg.GetReg()); 262091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86ComisdRR, rl_src.reg.GetReg(), temp_reg.GetReg()); 2635078d978f21620824d9c2fdcd73063260592398cSerguei Katkov LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondAe); 2641fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP); 265091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86Cvttsd2siRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 2661fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_normal = NewLIR1(kX86Jmp8, 0); 2671fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_na_n->target = NewLIR0(kPseudoTargetLabel); 26800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Xor32RR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 2691fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel); 2701fd3346740dfb7f47be9922312b68a4227fada96buzbee branch_normal->target = NewLIR0(kPseudoTargetLabel); 2711fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 272a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 273292188d514c9826971308a18fcc5a66261729f3bjeffhao } 274b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::LONG_TO_DOUBLE: 275dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 276a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rcSrc = kCoreReg; 277a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu op = kX86Cvtsqi2sdRR; 278a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu break; 279a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu } 280614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru GenLongToFP(rl_dest, rl_src, true /* is_double */); 281a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 282b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::LONG_TO_FLOAT: 283dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 284a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rcSrc = kCoreReg; 285a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu op = kX86Cvtsqi2ssRR; 286a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu break; 287a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu } 288614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru GenLongToFP(rl_dest, rl_src, false /* is_double */); 289a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 29041005ddb5576b8630a1084fbb3979ffa602c0599jeffhao case Instruction::FLOAT_TO_LONG: 291dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 292a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rl_src = LoadValue(rl_src, kFPReg); 293a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu // If result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 294a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu ClobberSReg(rl_dest.s_reg_low); 295a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rl_result = EvalLoc(rl_dest, kCoreReg, true); 296a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu RegStorage temp_reg = AllocTempSingle(); 297a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu 298a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu // Set 0x7fffffffffffffff to rl_result 299a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LoadConstantWide(rl_result.reg, 0x7fffffffffffffff); 300a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Cvtsqi2ssRR, temp_reg.GetReg(), rl_result.reg.GetReg()); 301a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86ComissRR, rl_src.reg.GetReg(), temp_reg.GetReg()); 3025078d978f21620824d9c2fdcd73063260592398cSerguei Katkov LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondAe); 303a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP); 304a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Cvttss2sqiRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 305a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LIR* branch_normal = NewLIR1(kX86Jmp8, 0); 306a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_na_n->target = NewLIR0(kPseudoTargetLabel); 307a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Xor64RR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 308a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel); 309a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_normal->target = NewLIR0(kPseudoTargetLabel); 310a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu StoreValueWide(rl_dest, rl_result); 3119ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 312fac10700fd99516e8a14f751fe35553021ce6982Vladimir Marko CheckEntrypointTypes<kQuickF2l, int64_t, float>(); // int64_t -> kCoreReg 313fac10700fd99516e8a14f751fe35553021ce6982Vladimir Marko GenConversionCall(kQuickF2l, rl_dest, rl_src, kCoreReg); 3149ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 315a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 316b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers case Instruction::DOUBLE_TO_LONG: 317dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 318a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rl_src = LoadValueWide(rl_src, kFPReg); 319a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu // If result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 320a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu ClobberSReg(rl_dest.s_reg_low); 321a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu rl_result = EvalLoc(rl_dest, kCoreReg, true); 322a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu RegStorage temp_reg = AllocTempDouble(); 323a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu 324a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu // Set 0x7fffffffffffffff to rl_result 325a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LoadConstantWide(rl_result.reg, 0x7fffffffffffffff); 326a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Cvtsqi2sdRR, temp_reg.GetReg(), rl_result.reg.GetReg()); 327a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86ComisdRR, rl_src.reg.GetReg(), temp_reg.GetReg()); 3285078d978f21620824d9c2fdcd73063260592398cSerguei Katkov LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondAe); 329a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP); 330a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Cvttsd2sqiRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 331a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu LIR* branch_normal = NewLIR1(kX86Jmp8, 0); 332a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_na_n->target = NewLIR0(kPseudoTargetLabel); 333a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu NewLIR2(kX86Xor64RR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 334a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel); 335a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu branch_normal->target = NewLIR0(kPseudoTargetLabel); 336a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu StoreValueWide(rl_dest, rl_result); 3379ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 338fac10700fd99516e8a14f751fe35553021ce6982Vladimir Marko CheckEntrypointTypes<kQuickD2l, int64_t, double>(); // int64_t -> kCoreReg 339fac10700fd99516e8a14f751fe35553021ce6982Vladimir Marko GenConversionCall(kQuickD2l, rl_dest, rl_src, kCoreReg); 3409ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 341a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 342b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers default: 343a5954be0aac5edd892fb31a209960543d00e4500buzbee LOG(INFO) << "Unexpected opcode: " << opcode; 344b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 345091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // At this point, target will be either float or double. 346091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(rl_dest.fp); 347fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (rl_src.wide) { 3481fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValueWide(rl_src, rcSrc); 349b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 3501fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValue(rl_src, rcSrc); 351b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 352091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 353091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(op, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 354fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (rl_dest.wide) { 3551fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_result); 356b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 3571fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 358b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 359e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 360e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 361bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalovvoid X86Mir2Lir::GenRemFP(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2, bool is_double) { 362bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Compute offsets to the source and destination VRs on stack. 363bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int src1_v_reg_offset = SRegOffset(rl_src1.s_reg_low); 364bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int src2_v_reg_offset = SRegOffset(rl_src2.s_reg_low); 365bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int dest_v_reg_offset = SRegOffset(rl_dest.s_reg_low); 366bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 367bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Update the in-register state of sources. 368bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov rl_src1 = is_double ? UpdateLocWide(rl_src1) : UpdateLoc(rl_src1); 369bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov rl_src2 = is_double ? UpdateLocWide(rl_src2) : UpdateLoc(rl_src2); 370bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 371bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // All memory accesses below reference dalvik regs. 372bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 373bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 374bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // If the source is in physical register, then put it in its location on stack. 375b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const RegStorage rs_rSP = cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32; 376bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (rl_src1.location == kLocPhysReg) { 377bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov RegisterInfo* reg_info = GetRegInfo(rl_src1.reg); 378bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 379bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (reg_info != nullptr && reg_info->IsTemp()) { 380bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Calling FlushSpecificReg because it will only write back VR if it is dirty. 381bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov FlushSpecificReg(reg_info); 382bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // ResetDef to prevent NullifyRange from removing stores. 383bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov ResetDef(rl_src1.reg); 384bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } else { 385bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // It must have been register promoted if it is not a temp but is still in physical 386bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // register. Since we need it to be in memory to convert, we place it there now. 387b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers StoreBaseDisp(rs_rSP, src1_v_reg_offset, rl_src1.reg, is_double ? k64 : k32, 3883c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe kNotVolatile); 389bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 390bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 391bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 392bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (rl_src2.location == kLocPhysReg) { 393bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov RegisterInfo* reg_info = GetRegInfo(rl_src2.reg); 394bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (reg_info != nullptr && reg_info->IsTemp()) { 395bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov FlushSpecificReg(reg_info); 396bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov ResetDef(rl_src2.reg); 397bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } else { 398b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers StoreBaseDisp(rs_rSP, src2_v_reg_offset, rl_src2.reg, is_double ? k64 : k32, 3993c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe kNotVolatile); 400bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 401bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 402bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 403bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int fld_opcode = is_double ? kX86Fld64M : kX86Fld32M; 404bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 405bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Push the source virtual registers onto the x87 stack. 406b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LIR *fld_2 = NewLIR2NoDest(fld_opcode, rs_rSP.GetReg(), 407bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov src2_v_reg_offset + LOWORD_OFFSET); 408bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov AnnotateDalvikRegAccess(fld_2, (src2_v_reg_offset + LOWORD_OFFSET) >> 2, 409bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov true /* is_load */, is_double /* is64bit */); 410bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 411b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LIR *fld_1 = NewLIR2NoDest(fld_opcode, rs_rSP.GetReg(), 412bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov src1_v_reg_offset + LOWORD_OFFSET); 413bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov AnnotateDalvikRegAccess(fld_1, (src1_v_reg_offset + LOWORD_OFFSET) >> 2, 414bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov true /* is_load */, is_double /* is64bit */); 415bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 416bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov FlushReg(rs_rAX); 417bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov Clobber(rs_rAX); 418bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov LockTemp(rs_rAX); 419bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 420bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov LIR* retry = NewLIR0(kPseudoTargetLabel); 421bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 422bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Divide ST(0) by ST(1) and place result to ST(0). 423bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov NewLIR0(kX86Fprem); 424bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 425bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Move FPU status word to AX. 426bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov NewLIR0(kX86Fstsw16R); 427bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 428bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Check if reduction is complete. 429bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov OpRegImm(kOpAnd, rs_rAX, 0x400); 430bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 431bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // If no then continue to compute remainder. 432bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov LIR* branch = NewLIR2(kX86Jcc8, 0, kX86CondNe); 433bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov branch->target = retry; 434bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 435bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov FreeTemp(rs_rAX); 436bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 437bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Now store result in the destination VR's stack location. 438bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int displacement = dest_v_reg_offset + LOWORD_OFFSET; 439bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov int opcode = is_double ? kX86Fst64M : kX86Fst32M; 440b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LIR *fst = NewLIR2NoDest(opcode, rs_rSP.GetReg(), displacement); 441bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov AnnotateDalvikRegAccess(fst, displacement >> 2, false /* is_load */, is_double /* is64bit */); 442bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 443bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov // Pop ST(1) and ST(0). 444bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov NewLIR0(kX86Fucompp); 445bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 446bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov /* 447bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * The result is in a physical register if it was in a temp or was register 448bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * promoted. For that reason it is enough to check if it is in physical 449bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * register. If it is, then we must do all of the bookkeeping necessary to 450bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * invalidate temp (if needed) and load in promoted register (if needed). 451bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * If the result's location is in memory, then we do not need to do anything 452bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov * more since the fstp has already placed the correct value in memory. 453bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov */ 4546a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers RegLocation rl_result = is_double ? UpdateLocWideTyped(rl_dest) : UpdateLocTyped(rl_dest); 455bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (rl_result.location == kLocPhysReg) { 456bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov rl_result = EvalLoc(rl_dest, kFPReg, true); 457bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov if (is_double) { 458b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LoadBaseDisp(rs_rSP, dest_v_reg_offset, rl_result.reg, k64, kNotVolatile); 459bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov StoreFinalValueWide(rl_dest, rl_result); 460bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } else { 461b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers Load32Disp(rs_rSP, dest_v_reg_offset, rl_result.reg); 462bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov StoreFinalValue(rl_dest, rl_result); 463bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 464bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov } 465bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov} 466bd3682eada753de52975ae2b4a712bd87dc139a6Alexei Zavjalov 4671fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenCmpFP(Instruction::Code code, RegLocation rl_dest, 46802031b185b4653e6c72e21f7a51238b903f6d638buzbee RegLocation rl_src1, RegLocation rl_src2) { 469b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers bool single = (code == Instruction::CMPL_FLOAT) || (code == Instruction::CMPG_FLOAT); 470fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bool unordered_gt = (code == Instruction::CMPG_DOUBLE) || (code == Instruction::CMPG_FLOAT); 471b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (single) { 4721fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValue(rl_src1, kFPReg); 4731fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValue(rl_src2, kFPReg); 474b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 4751fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValueWide(rl_src1, kFPReg); 4761fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValueWide(rl_src2, kFPReg); 477b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 478078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc() 4791fd3346740dfb7f47be9922312b68a4227fada96buzbee ClobberSReg(rl_dest.s_reg_low); 4801fd3346740dfb7f47be9922312b68a4227fada96buzbee RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 4812700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantNoClobber(rl_result.reg, unordered_gt ? 1 : 0); 482b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (single) { 483091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86UcomissRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 484b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 485091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86UcomisdRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 486b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 4872cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier LIR* branch = nullptr; 488fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (unordered_gt) { 4891fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 490b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 491703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao // If the result reg can't be byte accessed, use a jump and move instead of a set. 4927e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu if (!IsByteRegister(rl_result.reg)) { 4932cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier LIR* branch2 = nullptr; 494fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (unordered_gt) { 4951fd3346740dfb7f47be9922312b68a4227fada96buzbee branch2 = NewLIR2(kX86Jcc8, 0, kX86CondA); 49600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Mov32RI, rl_result.reg.GetReg(), 0x0); 497703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } else { 4981fd3346740dfb7f47be9922312b68a4227fada96buzbee branch2 = NewLIR2(kX86Jcc8, 0, kX86CondBe); 49900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Mov32RI, rl_result.reg.GetReg(), 0x1); 500703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } 5011fd3346740dfb7f47be9922312b68a4227fada96buzbee branch2->target = NewLIR0(kPseudoTargetLabel); 502703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } else { 50300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Set8R, rl_result.reg.GetReg(), kX86CondA /* above - unsigned > */); 504703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } 50500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86Sbb32RI, rl_result.reg.GetReg(), 0); 506fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (unordered_gt) { 5071fd3346740dfb7f47be9922312b68a4227fada96buzbee branch->target = NewLIR0(kPseudoTargetLabel); 508b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 5091fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 510e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee} 511e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 5121fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, 51302031b185b4653e6c72e21f7a51238b903f6d638buzbee bool is_double) { 5140d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee LIR* taken = &block_label_list_[bb->taken]; 5150d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee LIR* not_taken = &block_label_list_[bb->fall_through]; 5162cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier LIR* branch = nullptr; 517fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_src1; 518fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_src2; 519fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (is_double) { 5201fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = mir_graph_->GetSrcWide(mir, 0); 5211fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = mir_graph_->GetSrcWide(mir, 2); 5221fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValueWide(rl_src1, kFPReg); 5231fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValueWide(rl_src2, kFPReg); 524091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86UcomisdRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 5254b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } else { 5261fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = mir_graph_->GetSrc(mir, 0); 5271fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = mir_graph_->GetSrc(mir, 1); 5281fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValue(rl_src1, kFPReg); 5291fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValue(rl_src2, kFPReg); 53000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kX86UcomissRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 5314b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 532a894607bca7eb623bc957363e4b36f44cfeea1b6Vladimir Marko ConditionCode ccode = mir->meta.ccode; 5334b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao switch (ccode) { 5344b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondEq: 535fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!gt_bias) { 5361fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 537fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee branch->target = not_taken; 5384b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5394b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5404b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondNe: 541fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!gt_bias) { 5421fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 5434b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao branch->target = taken; 5444b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5454b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5464b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondLt: 547fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 5481fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 549fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee branch->target = not_taken; 5504b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 55158af1f9385742f70aca4fcb5e13aba53b8be2ef4Vladimir Marko ccode = kCondUlt; 5524b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5534b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondLe: 554fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 5551fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 556fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee branch->target = not_taken; 5574b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5584b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao ccode = kCondLs; 5594b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5604b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondGt: 561fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 5621fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 5634b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao branch->target = taken; 5644b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5654b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao ccode = kCondHi; 5664b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5674b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao case kCondGe: 568fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 5691fd3346740dfb7f47be9922312b68a4227fada96buzbee branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); 5704b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao branch->target = taken; 5714b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 57258af1f9385742f70aca4fcb5e13aba53b8be2ef4Vladimir Marko ccode = kCondUge; 5734b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao break; 5744b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao default: 575cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(FATAL) << "Unexpected ccode: " << ccode; 5764b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao } 5771fd3346740dfb7f47be9922312b68a4227fada96buzbee OpCondBranch(ccode, taken); 5784b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao} 5794b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao 5802ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) { 581fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 5821fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValue(rl_src, kCoreReg); 5831fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kCoreReg, true); 5842700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000); 5851fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 586efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 587efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5882ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) { 589fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 5901fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValueWide(rl_src, kCoreReg); 591dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 592d4812a97de5d54d29c2964b2db7c2d52217be60ePavel Vyssotski rl_result = EvalLocWide(rl_dest, kCoreReg, true); 59302959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov OpRegCopy(rl_result.reg, rl_src.reg); 59402959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov // Flip sign bit. 59502959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov NewLIR2(kX86Rol64RI, rl_result.reg.GetReg(), 1); 59602959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov NewLIR2(kX86Xor64RI, rl_result.reg.GetReg(), 1); 59702959eae949f37445c184ae6f3df4d068ff309e0Alexei Zavjalov NewLIR2(kX86Ror64RI, rl_result.reg.GetReg(), 1); 598a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu } else { 599d4812a97de5d54d29c2964b2db7c2d52217be60ePavel Vyssotski rl_result = ForceTempWide(rl_src); 600d4812a97de5d54d29c2964b2db7c2d52217be60ePavel Vyssotski OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_result.reg.GetHigh(), 0x80000000); 601a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu } 6021fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_result); 603efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 604efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 6051fd3346740dfb7f47be9922312b68a4227fada96buzbeebool X86Mir2Lir::GenInlinedSqrt(CallInfo* info) { 606bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell RegLocation rl_dest = InlineTargetWide(info); // double place for result 607ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu if (rl_dest.s_reg_low == INVALID_SREG) { 608ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu // Result is unused, the code is dead. Inlining successful, no code generated. 609ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu return true; 610ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu } 611ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu RegLocation rl_src = info->args[0]; 612bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell rl_src = LoadValueWide(rl_src, kFPReg); 613bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true); 614091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kX86SqrtsdRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 615bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell StoreValueWide(rl_dest, rl_result); 616bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell return true; 617efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 618efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 6197071c8d5885175a746723a3b38a347855965be08Yixin Shoubool X86Mir2Lir::GenInlinedAbsFloat(CallInfo* info) { 6207071c8d5885175a746723a3b38a347855965be08Yixin Shou // Get the argument 6217071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_src = info->args[0]; 6227071c8d5885175a746723a3b38a347855965be08Yixin Shou 6237071c8d5885175a746723a3b38a347855965be08Yixin Shou // Get the inlined intrinsic target virtual register 6247071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_dest = InlineTarget(info); 6257071c8d5885175a746723a3b38a347855965be08Yixin Shou 6267071c8d5885175a746723a3b38a347855965be08Yixin Shou // Get the virtual register number 6277071c8d5885175a746723a3b38a347855965be08Yixin Shou DCHECK_NE(rl_src.s_reg_low, INVALID_SREG); 6287071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_dest.s_reg_low == INVALID_SREG) { 6297071c8d5885175a746723a3b38a347855965be08Yixin Shou // Result is unused, the code is dead. Inlining successful, no code generated. 6307071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6317071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6327071c8d5885175a746723a3b38a347855965be08Yixin Shou int v_src_reg = mir_graph_->SRegToVReg(rl_src.s_reg_low); 6337071c8d5885175a746723a3b38a347855965be08Yixin Shou int v_dst_reg = mir_graph_->SRegToVReg(rl_dest.s_reg_low); 6347071c8d5885175a746723a3b38a347855965be08Yixin Shou 6357071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is the same as inlined intrinsic target 6367071c8d5885175a746723a3b38a347855965be08Yixin Shou if (v_src_reg == v_dst_reg) { 6377071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = UpdateLoc(rl_src); 6387071c8d5885175a746723a3b38a347855965be08Yixin Shou 6397071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is in the physical register 6407071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_src.location == kLocPhysReg) { 6417071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = LoadValue(rl_src, kCoreReg); 6427071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegImm(kOpAnd, rl_src.reg, 0x7fffffff); 6437071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValue(rl_dest, rl_src); 6447071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6457071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6467071c8d5885175a746723a3b38a347855965be08Yixin Shou // the argument is in memory 6477071c8d5885175a746723a3b38a347855965be08Yixin Shou DCHECK((rl_src.location == kLocDalvikFrame) || 6487071c8d5885175a746723a3b38a347855965be08Yixin Shou (rl_src.location == kLocCompilerTemp)); 6497071c8d5885175a746723a3b38a347855965be08Yixin Shou 6507071c8d5885175a746723a3b38a347855965be08Yixin Shou // Operate directly into memory. 6517071c8d5885175a746723a3b38a347855965be08Yixin Shou int displacement = SRegOffset(rl_dest.s_reg_low); 6527071c8d5885175a746723a3b38a347855965be08Yixin Shou ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 653b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LIR *lir = NewLIR3(kX86And32MI, rs_rX86_SP_32.GetReg(), displacement, 0x7fffffff); 6547071c8d5885175a746723a3b38a347855965be08Yixin Shou AnnotateDalvikRegAccess(lir, displacement >> 2, false /*is_load */, false /* is_64bit */); 6557071c8d5885175a746723a3b38a347855965be08Yixin Shou AnnotateDalvikRegAccess(lir, displacement >> 2, true /* is_load */, false /* is_64bit*/); 6567071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6577071c8d5885175a746723a3b38a347855965be08Yixin Shou } else { 6587071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = LoadValue(rl_src, kCoreReg); 6597071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 6607071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegRegImm(kOpAnd, rl_result.reg, rl_src.reg, 0x7fffffff); 6617071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValue(rl_dest, rl_result); 6627071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6637071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6647071c8d5885175a746723a3b38a347855965be08Yixin Shou} 6657071c8d5885175a746723a3b38a347855965be08Yixin Shou 6667071c8d5885175a746723a3b38a347855965be08Yixin Shoubool X86Mir2Lir::GenInlinedAbsDouble(CallInfo* info) { 6677071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_src = info->args[0]; 6687071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_dest = InlineTargetWide(info); 6697071c8d5885175a746723a3b38a347855965be08Yixin Shou DCHECK_NE(rl_src.s_reg_low, INVALID_SREG); 6707071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_dest.s_reg_low == INVALID_SREG) { 6717071c8d5885175a746723a3b38a347855965be08Yixin Shou // Result is unused, the code is dead. Inlining successful, no code generated. 6727071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 6737071c8d5885175a746723a3b38a347855965be08Yixin Shou } 674c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk if (cu_->target64) { 675c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk rl_src = LoadValueWide(rl_src, kCoreReg); 676c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 677c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk OpRegCopyWide(rl_result.reg, rl_src.reg); 678c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk OpRegImm(kOpLsl, rl_result.reg, 1); 679c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk OpRegImm(kOpLsr, rl_result.reg, 1); 680c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk StoreValueWide(rl_dest, rl_result); 681c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk return true; 682c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk } 6837071c8d5885175a746723a3b38a347855965be08Yixin Shou int v_src_reg = mir_graph_->SRegToVReg(rl_src.s_reg_low); 6847071c8d5885175a746723a3b38a347855965be08Yixin Shou int v_dst_reg = mir_graph_->SRegToVReg(rl_dest.s_reg_low); 6857071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = UpdateLocWide(rl_src); 6867071c8d5885175a746723a3b38a347855965be08Yixin Shou 6877071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is in the physical XMM register 6887071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_src.location == kLocPhysReg && rl_src.reg.IsFloat()) { 6897071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true); 6907071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_result.reg != rl_src.reg) { 6917071c8d5885175a746723a3b38a347855965be08Yixin Shou LoadConstantWide(rl_result.reg, 0x7fffffffffffffff); 6927071c8d5885175a746723a3b38a347855965be08Yixin Shou NewLIR2(kX86PandRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 6937071c8d5885175a746723a3b38a347855965be08Yixin Shou } else { 6947071c8d5885175a746723a3b38a347855965be08Yixin Shou RegStorage sign_mask = AllocTempDouble(); 6957071c8d5885175a746723a3b38a347855965be08Yixin Shou LoadConstantWide(sign_mask, 0x7fffffffffffffff); 6967071c8d5885175a746723a3b38a347855965be08Yixin Shou NewLIR2(kX86PandRR, rl_result.reg.GetReg(), sign_mask.GetReg()); 6977071c8d5885175a746723a3b38a347855965be08Yixin Shou FreeTemp(sign_mask); 6987071c8d5885175a746723a3b38a347855965be08Yixin Shou } 6997071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValueWide(rl_dest, rl_result); 7007071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 7017071c8d5885175a746723a3b38a347855965be08Yixin Shou } else if (v_src_reg == v_dst_reg) { 7027071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is the same as inlined intrinsic target 7037071c8d5885175a746723a3b38a347855965be08Yixin Shou // if argument is in the physical register 7047071c8d5885175a746723a3b38a347855965be08Yixin Shou if (rl_src.location == kLocPhysReg) { 7057071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = LoadValueWide(rl_src, kCoreReg); 7067071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegImm(kOpAnd, rl_src.reg.GetHigh(), 0x7fffffff); 7077071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValueWide(rl_dest, rl_src); 7087071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 7097071c8d5885175a746723a3b38a347855965be08Yixin Shou } 7107071c8d5885175a746723a3b38a347855965be08Yixin Shou // the argument is in memory 7117071c8d5885175a746723a3b38a347855965be08Yixin Shou DCHECK((rl_src.location == kLocDalvikFrame) || 7127071c8d5885175a746723a3b38a347855965be08Yixin Shou (rl_src.location == kLocCompilerTemp)); 7137071c8d5885175a746723a3b38a347855965be08Yixin Shou 7147071c8d5885175a746723a3b38a347855965be08Yixin Shou // Operate directly into memory. 7157071c8d5885175a746723a3b38a347855965be08Yixin Shou int displacement = SRegOffset(rl_dest.s_reg_low); 7167071c8d5885175a746723a3b38a347855965be08Yixin Shou ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 717b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LIR *lir = NewLIR3(kX86And32MI, rs_rX86_SP_32.GetReg(), displacement + HIWORD_OFFSET, 0x7fffffff); 7187071c8d5885175a746723a3b38a347855965be08Yixin Shou AnnotateDalvikRegAccess(lir, (displacement + HIWORD_OFFSET) >> 2, true /* is_load */, true /* is_64bit*/); 7197071c8d5885175a746723a3b38a347855965be08Yixin Shou AnnotateDalvikRegAccess(lir, (displacement + HIWORD_OFFSET) >> 2, false /*is_load */, true /* is_64bit */); 7207071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 7217071c8d5885175a746723a3b38a347855965be08Yixin Shou } else { 7227071c8d5885175a746723a3b38a347855965be08Yixin Shou rl_src = LoadValueWide(rl_src, kCoreReg); 7237071c8d5885175a746723a3b38a347855965be08Yixin Shou RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 7247071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegCopyWide(rl_result.reg, rl_src.reg); 7257071c8d5885175a746723a3b38a347855965be08Yixin Shou OpRegImm(kOpAnd, rl_result.reg.GetHigh(), 0x7fffffff); 7267071c8d5885175a746723a3b38a347855965be08Yixin Shou StoreValueWide(rl_dest, rl_result); 7277071c8d5885175a746723a3b38a347855965be08Yixin Shou return true; 7287071c8d5885175a746723a3b38a347855965be08Yixin Shou } 7297071c8d5885175a746723a3b38a347855965be08Yixin Shou} 730efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 7311222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalovbool X86Mir2Lir::GenInlinedMinMaxFP(CallInfo* info, bool is_min, bool is_double) { 7321222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov if (is_double) { 733ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu RegLocation rl_dest = InlineTargetWide(info); 734ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu if (rl_dest.s_reg_low == INVALID_SREG) { 735ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu // Result is unused, the code is dead. Inlining successful, no code generated. 736ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu return true; 737ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu } 7381222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov RegLocation rl_src1 = LoadValueWide(info->args[0], kFPReg); 7391222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov RegLocation rl_src2 = LoadValueWide(info->args[2], kFPReg); 7401222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov RegLocation rl_result = EvalLocWide(rl_dest, kFPReg, true); 7411222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov 7421222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Avoid src2 corruption by OpRegCopyWide. 7431222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov if (rl_result.reg == rl_src2.reg) { 7441222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov std::swap(rl_src2.reg, rl_src1.reg); 7451222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov } 7461222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov 7471222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov OpRegCopyWide(rl_result.reg, rl_src1.reg); 7481222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov NewLIR2(kX86UcomisdRR, rl_result.reg.GetReg(), rl_src2.reg.GetReg()); 7491222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // If either arg is NaN, return NaN. 7501222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_nan = NewLIR2(kX86Jcc8, 0, kX86CondP); 7511222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Min/Max branches. 7521222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_cond1 = NewLIR2(kX86Jcc8, 0, (is_min) ? kX86CondA : kX86CondB); 7531222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_cond2 = NewLIR2(kX86Jcc8, 0, (is_min) ? kX86CondB : kX86CondA); 7541222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // If equal, we need to resolve situations like min/max(0.0, -0.0) == -0.0/0.0. 7551222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov NewLIR2((is_min) ? kX86OrpdRR : kX86AndpdRR, rl_result.reg.GetReg(), rl_src2.reg.GetReg()); 7561222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_exit_equal = NewLIR1(kX86Jmp8, 0); 7571222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Handle NaN. 7581222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_nan->target = NewLIR0(kPseudoTargetLabel); 7591222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LoadConstantWide(rl_result.reg, INT64_C(0x7ff8000000000000)); 760e5beb18ca08962ed271f4c1f703e0c52bc8805f3Razvan A Lupusoru 7611222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_exit_nan = NewLIR1(kX86Jmp8, 0); 7621222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Handle Min/Max. Copy greater/lesser value from src2. 7631222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_cond1->target = NewLIR0(kPseudoTargetLabel); 7641222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov OpRegCopyWide(rl_result.reg, rl_src2.reg); 7651222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Right operand is already in result reg. 7661222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_cond2->target = NewLIR0(kPseudoTargetLabel); 7671222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Exit. 7681222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_exit_nan->target = NewLIR0(kPseudoTargetLabel); 7691222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_exit_equal->target = NewLIR0(kPseudoTargetLabel); 7701222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov StoreValueWide(rl_dest, rl_result); 7711222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov } else { 772ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu RegLocation rl_dest = InlineTarget(info); 773ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu if (rl_dest.s_reg_low == INVALID_SREG) { 774ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu // Result is unused, the code is dead. Inlining successful, no code generated. 775ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu return true; 776ff87d7bdc2c06bece8ea783dd4979360f1d51103Chao-ying Fu } 7771222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov RegLocation rl_src1 = LoadValue(info->args[0], kFPReg); 7781222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov RegLocation rl_src2 = LoadValue(info->args[1], kFPReg); 7791222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true); 7801222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov 7811222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Avoid src2 corruption by OpRegCopyWide. 7821222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov if (rl_result.reg == rl_src2.reg) { 7831222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov std::swap(rl_src2.reg, rl_src1.reg); 7841222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov } 7851222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov 7861222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov OpRegCopy(rl_result.reg, rl_src1.reg); 7871222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov NewLIR2(kX86UcomissRR, rl_result.reg.GetReg(), rl_src2.reg.GetReg()); 7881222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // If either arg is NaN, return NaN. 7891222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_nan = NewLIR2(kX86Jcc8, 0, kX86CondP); 7901222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Min/Max branches. 7911222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_cond1 = NewLIR2(kX86Jcc8, 0, (is_min) ? kX86CondA : kX86CondB); 7921222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_cond2 = NewLIR2(kX86Jcc8, 0, (is_min) ? kX86CondB : kX86CondA); 7931222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // If equal, we need to resolve situations like min/max(0.0, -0.0) == -0.0/0.0. 7941222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov NewLIR2((is_min) ? kX86OrpsRR : kX86AndpsRR, rl_result.reg.GetReg(), rl_src2.reg.GetReg()); 7951222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_exit_equal = NewLIR1(kX86Jmp8, 0); 7961222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Handle NaN. 7971222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_nan->target = NewLIR0(kPseudoTargetLabel); 7981222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LoadConstantNoClobber(rl_result.reg, 0x7fc00000); 7991222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov LIR* branch_exit_nan = NewLIR1(kX86Jmp8, 0); 8001222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Handle Min/Max. Copy greater/lesser value from src2. 8011222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_cond1->target = NewLIR0(kPseudoTargetLabel); 8021222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov OpRegCopy(rl_result.reg, rl_src2.reg); 8031222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Right operand is already in result reg. 8041222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_cond2->target = NewLIR0(kPseudoTargetLabel); 8051222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov // Exit. 8061222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_exit_nan->target = NewLIR0(kPseudoTargetLabel); 8071222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov branch_exit_equal->target = NewLIR0(kPseudoTargetLabel); 8081222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov StoreValue(rl_dest, rl_result); 8091222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov } 8101222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov return true; 8111222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov} 8121222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov 8137934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom} // namespace art 814