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