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