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