fp_x86.cc revision a014776f4474579d4dfc72e3374ba45c6f6e5f35
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:
511fd3346740dfb7f47be9922312b68a4227fada96buzbee      FlushAllRegs();   // Send everything to home location
529ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      if (Is64BitInstructionSet(cu_->instruction_set)) {
539ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(8, pFmodf), rl_src1, rl_src2,
549ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko                                                false);
559ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      } else {
569ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(4, pFmodf), rl_src1, rl_src2,
579ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko                                                false);
589ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      }
59a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee      rl_result = GetReturn(kFPReg);
601fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValue(rl_dest, rl_result);
61a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
62a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    case Instruction::NEG_FLOAT:
631fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenNegFloat(rl_dest, rl_src1);
64a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
65b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
66a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
67b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
681fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValue(rl_src1, kFPReg);
691fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValue(rl_src2, kFPReg);
701fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
712700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  RegStorage r_dest = rl_result.reg;
722700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  RegStorage r_src1 = rl_src1.reg;
732700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  RegStorage r_src2 = rl_src2.reg;
74fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (r_dest == r_src2) {
75091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    r_src2 = AllocTempSingle();
761fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegCopy(r_src2, r_dest);
774abb1a9000b525a0636763a97528e24468f16d10jeffhao  }
781fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegCopy(r_dest, r_src1);
792700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  NewLIR2(op, r_dest.GetReg(), r_src2.GetReg());
801fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
81e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
82e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
831fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenArithOpDouble(Instruction::Code opcode,
8402031b185b4653e6c72e21f7a51238b903f6d638buzbee                                  RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
85091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(rl_dest.wide);
86091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(rl_dest.fp);
87091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(rl_src1.wide);
88091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(rl_src1.fp);
89091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(rl_src2.wide);
90091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(rl_src2.fp);
91b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode op = kX86Nop;
92fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
93e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
94408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee  switch (opcode) {
95b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::ADD_DOUBLE_2ADDR:
96b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::ADD_DOUBLE:
97b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86AddsdRR;
98b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
99b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::SUB_DOUBLE_2ADDR:
100b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::SUB_DOUBLE:
101b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86SubsdRR;
102b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
103b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::DIV_DOUBLE_2ADDR:
104b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::DIV_DOUBLE:
105b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86DivsdRR;
106b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
107b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::MUL_DOUBLE_2ADDR:
108b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::MUL_DOUBLE:
109b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86MulsdRR;
110b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
111b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::REM_DOUBLE_2ADDR:
112babda950caf2d577aa57102c3281f0f3c36f3d6djeffhao    case Instruction::REM_DOUBLE:
1131fd3346740dfb7f47be9922312b68a4227fada96buzbee      FlushAllRegs();   // Send everything to home location
1149ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      if (Is64BitInstructionSet(cu_->instruction_set)) {
1159ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(8, pFmod), rl_src1, rl_src2,
1169ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko                                                false);
1179ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      } else {
1189ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(4, pFmod), rl_src1, rl_src2,
1199ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko                                                false);
1209ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      }
121a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee      rl_result = GetReturnWide(kFPReg);
1221fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValueWide(rl_dest, rl_result);
123a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
124a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    case Instruction::NEG_DOUBLE:
1251fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenNegDouble(rl_dest, rl_src1);
126a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
127b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
128a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
129b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
1301fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kFPReg);
1311fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValueWide(rl_src2, kFPReg);
1321fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
133091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  if (rl_result.reg == rl_src2.reg) {
134091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    rl_src2.reg = AllocTempDouble();
135091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    OpRegCopy(rl_src2.reg, rl_result.reg);
1364abb1a9000b525a0636763a97528e24468f16d10jeffhao  }
137091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  OpRegCopy(rl_result.reg, rl_src1.reg);
138091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR2(op, rl_result.reg.GetReg(), rl_src2.reg.GetReg());
1391fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
140e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
141e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
142614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoruvoid X86Mir2Lir::GenLongToFP(RegLocation rl_dest, RegLocation rl_src, bool is_double) {
143614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  // Compute offsets to the source and destination VRs on stack
144614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  int src_v_reg_offset = SRegOffset(rl_src.s_reg_low);
145614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  int dest_v_reg_offset = SRegOffset(rl_dest.s_reg_low);
146614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru
147614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  // Update the in-register state of source.
148614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  rl_src = UpdateLocWide(rl_src);
149614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru
150614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  // If the source is in physical register, then put it in its location on stack.
151614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  if (rl_src.location == kLocPhysReg) {
152091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    RegisterInfo* reg_info = GetRegInfo(rl_src.reg);
153614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru
154091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    if (reg_info != nullptr && reg_info->IsTemp()) {
155614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru      // Calling FlushSpecificReg because it will only write back VR if it is dirty.
156091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      FlushSpecificReg(reg_info);
157091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      // ResetDef to prevent NullifyRange from removing stores.
158091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      ResetDef(rl_src.reg);
159614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru    } else {
160614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru      // It must have been register promoted if it is not a temp but is still in physical
161614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru      // register. Since we need it to be in memory to convert, we place it there now.
162455759b5702b9435b91d1b4dada22c4cce7cae3cVladimir Marko      StoreBaseDisp(TargetReg(kSp), src_v_reg_offset, rl_src.reg, k64);
163614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru    }
164614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  }
165614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru
166614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  // Push the source virtual register onto the x87 stack.
167091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LIR *fild64 = NewLIR2NoDest(kX86Fild64M, TargetReg(kSp).GetReg(),
168091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee                              src_v_reg_offset + LOWORD_OFFSET);
169614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  AnnotateDalvikRegAccess(fild64, (src_v_reg_offset + LOWORD_OFFSET) >> 2,
170091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee                          true /* is_load */, true /* is64bit */);
171614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru
172614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  // Now pop off x87 stack and store it in the destination VR's stack location.
173614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  int opcode = is_double ? kX86Fstp64M : kX86Fstp32M;
174614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  int displacement = is_double ? dest_v_reg_offset + LOWORD_OFFSET : dest_v_reg_offset;
1752700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  LIR *fstp = NewLIR2NoDest(opcode, TargetReg(kSp).GetReg(), displacement);
176614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  AnnotateDalvikRegAccess(fstp, displacement >> 2, false /* is_load */, is_double);
177614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru
178614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  /*
179614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru   * The result is in a physical register if it was in a temp or was register
180614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru   * promoted. For that reason it is enough to check if it is in physical
181614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru   * register. If it is, then we must do all of the bookkeeping necessary to
182614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru   * invalidate temp (if needed) and load in promoted register (if needed).
183614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru   * If the result's location is in memory, then we do not need to do anything
184614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru   * more since the fstp has already placed the correct value in memory.
185614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru   */
18630adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee  RegLocation rl_result = is_double ? UpdateLocWideTyped(rl_dest, kFPReg) :
18730adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee      UpdateLocTyped(rl_dest, kFPReg);
188614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  if (rl_result.location == kLocPhysReg) {
189614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru    /*
190614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru     * We already know that the result is in a physical register but do not know if it is the
191614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru     * right class. So we call EvalLoc(Wide) first which will ensure that it will get moved to the
192614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru     * correct register class.
193614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru     */
194614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru    if (is_double) {
195614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru      rl_result = EvalLocWide(rl_dest, kFPReg, true);
196614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru
1973bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko      LoadBaseDisp(TargetReg(kSp), dest_v_reg_offset, rl_result.reg, k64);
198614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru
19951a80d72dc436a4a89c636987b9cedabe774fdd6Maxim Kazantsev      StoreFinalValueWide(rl_dest, rl_result);
200614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru    } else {
201614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru      rl_result = EvalLoc(rl_dest, kFPReg, true);
202614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru
203695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee      Load32Disp(TargetReg(kSp), dest_v_reg_offset, rl_result.reg);
204614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru
20551a80d72dc436a4a89c636987b9cedabe774fdd6Maxim Kazantsev      StoreFinalValue(rl_dest, rl_result);
206614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru    }
207614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru  }
208614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru}
209614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru
2101fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest,
21102031b185b4653e6c72e21f7a51238b903f6d638buzbee                               RegLocation rl_src) {
2125121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao  RegisterClass rcSrc = kFPReg;
213b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode op = kX86Nop;
214fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
215b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (opcode) {
216b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::INT_TO_FLOAT:
2175121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao      rcSrc = kCoreReg;
218b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86Cvtsi2ssRR;
219b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
220b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::DOUBLE_TO_FLOAT:
2215121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao      rcSrc = kFPReg;
222b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86Cvtsd2ssRR;
223b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
224b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::FLOAT_TO_DOUBLE:
2255121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao      rcSrc = kFPReg;
226b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86Cvtss2sdRR;
227b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
228b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::INT_TO_DOUBLE:
2295121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao      rcSrc = kCoreReg;
230b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86Cvtsi2sdRR;
231b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
232292188d514c9826971308a18fcc5a66261729f3bjeffhao    case Instruction::FLOAT_TO_INT: {
2331fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_src = LoadValue(rl_src, kFPReg);
234078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee      // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc()
2351fd3346740dfb7f47be9922312b68a4227fada96buzbee      ClobberSReg(rl_dest.s_reg_low);
2361fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_result = EvalLoc(rl_dest, kCoreReg, true);
237091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      RegStorage temp_reg = AllocTempSingle();
23841005ddb5576b8630a1084fbb3979ffa602c0599jeffhao
2392700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      LoadConstant(rl_result.reg, 0x7fffffff);
240091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kX86Cvtsi2ssRR, temp_reg.GetReg(), rl_result.reg.GetReg());
241091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kX86ComissRR, rl_src.reg.GetReg(), temp_reg.GetReg());
2421fd3346740dfb7f47be9922312b68a4227fada96buzbee      LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondA);
2431fd3346740dfb7f47be9922312b68a4227fada96buzbee      LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP);
244091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kX86Cvttss2siRR, rl_result.reg.GetReg(), rl_src.reg.GetReg());
2451fd3346740dfb7f47be9922312b68a4227fada96buzbee      LIR* branch_normal = NewLIR1(kX86Jmp8, 0);
2461fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch_na_n->target = NewLIR0(kPseudoTargetLabel);
24700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee      NewLIR2(kX86Xor32RR, rl_result.reg.GetReg(), rl_result.reg.GetReg());
2481fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel);
2491fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch_normal->target = NewLIR0(kPseudoTargetLabel);
2501fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValue(rl_dest, rl_result);
251a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
252292188d514c9826971308a18fcc5a66261729f3bjeffhao    }
253292188d514c9826971308a18fcc5a66261729f3bjeffhao    case Instruction::DOUBLE_TO_INT: {
2541fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_src = LoadValueWide(rl_src, kFPReg);
255078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee      // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc()
2561fd3346740dfb7f47be9922312b68a4227fada96buzbee      ClobberSReg(rl_dest.s_reg_low);
2571fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_result = EvalLoc(rl_dest, kCoreReg, true);
258091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      RegStorage temp_reg = AllocTempDouble();
25941005ddb5576b8630a1084fbb3979ffa602c0599jeffhao
2602700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      LoadConstant(rl_result.reg, 0x7fffffff);
261091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kX86Cvtsi2sdRR, temp_reg.GetReg(), rl_result.reg.GetReg());
262091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kX86ComisdRR, rl_src.reg.GetReg(), temp_reg.GetReg());
2631fd3346740dfb7f47be9922312b68a4227fada96buzbee      LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondA);
2641fd3346740dfb7f47be9922312b68a4227fada96buzbee      LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP);
265091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kX86Cvttsd2siRR, rl_result.reg.GetReg(), rl_src.reg.GetReg());
2661fd3346740dfb7f47be9922312b68a4227fada96buzbee      LIR* branch_normal = NewLIR1(kX86Jmp8, 0);
2671fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch_na_n->target = NewLIR0(kPseudoTargetLabel);
26800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee      NewLIR2(kX86Xor32RR, rl_result.reg.GetReg(), rl_result.reg.GetReg());
2691fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel);
2701fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch_normal->target = NewLIR0(kPseudoTargetLabel);
2711fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValue(rl_dest, rl_result);
272a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
273292188d514c9826971308a18fcc5a66261729f3bjeffhao    }
274b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::LONG_TO_DOUBLE:
275a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu      if (Gen64Bit()) {
276a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        rcSrc = kCoreReg;
277a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        op = kX86Cvtsqi2sdRR;
278a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        break;
279a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu      }
280614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru      GenLongToFP(rl_dest, rl_src, true /* is_double */);
281a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
282b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::LONG_TO_FLOAT:
283a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu      if (Gen64Bit()) {
284a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        rcSrc = kCoreReg;
285a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        op = kX86Cvtsqi2ssRR;
286a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu       break;
287a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu      }
288614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru      GenLongToFP(rl_dest, rl_src, false /* is_double */);
289a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
29041005ddb5576b8630a1084fbb3979ffa602c0599jeffhao    case Instruction::FLOAT_TO_LONG:
291a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu      if (Gen64Bit()) {
292a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        rl_src = LoadValue(rl_src, kFPReg);
293a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        // If result vreg is also src vreg, break association to avoid useless copy by EvalLoc()
294a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        ClobberSReg(rl_dest.s_reg_low);
295a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        rl_result = EvalLoc(rl_dest, kCoreReg, true);
296a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        RegStorage temp_reg = AllocTempSingle();
297a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu
298a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        // Set 0x7fffffffffffffff to rl_result
299a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        LoadConstantWide(rl_result.reg, 0x7fffffffffffffff);
300a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        NewLIR2(kX86Cvtsqi2ssRR, temp_reg.GetReg(), rl_result.reg.GetReg());
301a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        NewLIR2(kX86ComissRR, rl_src.reg.GetReg(), temp_reg.GetReg());
302a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondA);
303a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP);
304a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        NewLIR2(kX86Cvttss2sqiRR, rl_result.reg.GetReg(), rl_src.reg.GetReg());
305a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        LIR* branch_normal = NewLIR1(kX86Jmp8, 0);
306a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        branch_na_n->target = NewLIR0(kPseudoTargetLabel);
307a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        NewLIR2(kX86Xor64RR, rl_result.reg.GetReg(), rl_result.reg.GetReg());
308a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel);
309a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        branch_normal->target = NewLIR0(kPseudoTargetLabel);
310a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        StoreValueWide(rl_dest, rl_result);
3119ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      } else {
3129ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pF2l), rl_dest, rl_src);
3139ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      }
314a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
315b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::DOUBLE_TO_LONG:
316a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu      if (Gen64Bit()) {
317a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        rl_src = LoadValueWide(rl_src, kFPReg);
318a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        // If result vreg is also src vreg, break association to avoid useless copy by EvalLoc()
319a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        ClobberSReg(rl_dest.s_reg_low);
320a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        rl_result = EvalLoc(rl_dest, kCoreReg, true);
321a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        RegStorage temp_reg = AllocTempDouble();
322a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu
323a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        // Set 0x7fffffffffffffff to rl_result
324a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        LoadConstantWide(rl_result.reg, 0x7fffffffffffffff);
325a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        NewLIR2(kX86Cvtsqi2sdRR, temp_reg.GetReg(), rl_result.reg.GetReg());
326a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        NewLIR2(kX86ComisdRR, rl_src.reg.GetReg(), temp_reg.GetReg());
327a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondA);
328a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP);
329a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        NewLIR2(kX86Cvttsd2sqiRR, rl_result.reg.GetReg(), rl_src.reg.GetReg());
330a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        LIR* branch_normal = NewLIR1(kX86Jmp8, 0);
331a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        branch_na_n->target = NewLIR0(kPseudoTargetLabel);
332a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        NewLIR2(kX86Xor64RR, rl_result.reg.GetReg(), rl_result.reg.GetReg());
333a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel);
334a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        branch_normal->target = NewLIR0(kPseudoTargetLabel);
335a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu        StoreValueWide(rl_dest, rl_result);
3369ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      } else {
3379ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pD2l), rl_dest, rl_src);
3389ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      }
339a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
340b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
341a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(INFO) << "Unexpected opcode: " << opcode;
342b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
343091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // At this point, target will be either float or double.
344091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(rl_dest.fp);
345fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_src.wide) {
3461fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src = LoadValueWide(rl_src, rcSrc);
347b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  } else {
3481fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src = LoadValue(rl_src, rcSrc);
349b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
350091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
351091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR2(op, rl_result.reg.GetReg(), rl_src.reg.GetReg());
352fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_dest.wide) {
3531fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValueWide(rl_dest, rl_result);
354b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  } else {
3551fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValue(rl_dest, rl_result);
356b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
357e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
358e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
3591fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenCmpFP(Instruction::Code code, RegLocation rl_dest,
36002031b185b4653e6c72e21f7a51238b903f6d638buzbee                          RegLocation rl_src1, RegLocation rl_src2) {
361b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  bool single = (code == Instruction::CMPL_FLOAT) || (code == Instruction::CMPG_FLOAT);
362fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool unordered_gt = (code == Instruction::CMPG_DOUBLE) || (code == Instruction::CMPG_FLOAT);
363b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  if (single) {
3641fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValue(rl_src1, kFPReg);
3651fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValue(rl_src2, kFPReg);
366b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  } else {
3671fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValueWide(rl_src1, kFPReg);
3681fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValueWide(rl_src2, kFPReg);
369b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
370078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee  // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc()
3711fd3346740dfb7f47be9922312b68a4227fada96buzbee  ClobberSReg(rl_dest.s_reg_low);
3721fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
3732700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  LoadConstantNoClobber(rl_result.reg, unordered_gt ? 1 : 0);
374b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  if (single) {
375091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    NewLIR2(kX86UcomissRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
376b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  } else {
377091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    NewLIR2(kX86UcomisdRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
378b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
379b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  LIR* branch = NULL;
380fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (unordered_gt) {
3811fd3346740dfb7f47be9922312b68a4227fada96buzbee    branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
382b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
383703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao  // If the result reg can't be byte accessed, use a jump and move instead of a set.
384091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  if (rl_result.reg.GetReg() >= rs_rX86_SP.GetReg()) {
385703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao    LIR* branch2 = NULL;
386fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (unordered_gt) {
3871fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch2 = NewLIR2(kX86Jcc8, 0, kX86CondA);
38800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee      NewLIR2(kX86Mov32RI, rl_result.reg.GetReg(), 0x0);
389703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao    } else {
3901fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch2 = NewLIR2(kX86Jcc8, 0, kX86CondBe);
39100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee      NewLIR2(kX86Mov32RI, rl_result.reg.GetReg(), 0x1);
392703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao    }
3931fd3346740dfb7f47be9922312b68a4227fada96buzbee    branch2->target = NewLIR0(kPseudoTargetLabel);
394703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao  } else {
39500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    NewLIR2(kX86Set8R, rl_result.reg.GetReg(), kX86CondA /* above - unsigned > */);
396703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao  }
39700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  NewLIR2(kX86Sbb32RI, rl_result.reg.GetReg(), 0);
398fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (unordered_gt) {
3991fd3346740dfb7f47be9922312b68a4227fada96buzbee    branch->target = NewLIR0(kPseudoTargetLabel);
400b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
4011fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
402e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
403e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
4041fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias,
40502031b185b4653e6c72e21f7a51238b903f6d638buzbee                                     bool is_double) {
4060d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  LIR* taken = &block_label_list_[bb->taken];
4070d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  LIR* not_taken = &block_label_list_[bb->fall_through];
4084b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao  LIR* branch = NULL;
409fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src1;
410fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src2;
411fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_double) {
4121fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = mir_graph_->GetSrcWide(mir, 0);
4131fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = mir_graph_->GetSrcWide(mir, 2);
4141fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValueWide(rl_src1, kFPReg);
4151fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValueWide(rl_src2, kFPReg);
416091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    NewLIR2(kX86UcomisdRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
4174b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao  } else {
4181fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = mir_graph_->GetSrc(mir, 0);
4191fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = mir_graph_->GetSrc(mir, 1);
4201fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValue(rl_src1, kFPReg);
4211fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValue(rl_src2, kFPReg);
42200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    NewLIR2(kX86UcomissRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
4234b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao  }
424a894607bca7eb623bc957363e4b36f44cfeea1b6Vladimir Marko  ConditionCode ccode = mir->meta.ccode;
4254b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao  switch (ccode) {
4264b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao    case kCondEq:
427fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (!gt_bias) {
4281fd3346740dfb7f47be9922312b68a4227fada96buzbee        branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
429fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        branch->target = not_taken;
4304b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      }
4314b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      break;
4324b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao    case kCondNe:
433fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (!gt_bias) {
4341fd3346740dfb7f47be9922312b68a4227fada96buzbee        branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
4354b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao        branch->target = taken;
4364b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      }
4374b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      break;
4384b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao    case kCondLt:
439fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
4401fd3346740dfb7f47be9922312b68a4227fada96buzbee        branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
441fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        branch->target = not_taken;
4424b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      }
44358af1f9385742f70aca4fcb5e13aba53b8be2ef4Vladimir Marko      ccode = kCondUlt;
4444b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      break;
4454b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao    case kCondLe:
446fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
4471fd3346740dfb7f47be9922312b68a4227fada96buzbee        branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
448fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        branch->target = not_taken;
4494b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      }
4504b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      ccode = kCondLs;
4514b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      break;
4524b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao    case kCondGt:
453fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
4541fd3346740dfb7f47be9922312b68a4227fada96buzbee        branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
4554b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao        branch->target = taken;
4564b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      }
4574b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      ccode = kCondHi;
4584b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      break;
4594b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao    case kCondGe:
460fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
4611fd3346740dfb7f47be9922312b68a4227fada96buzbee        branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
4624b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao        branch->target = taken;
4634b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      }
46458af1f9385742f70aca4fcb5e13aba53b8be2ef4Vladimir Marko      ccode = kCondUge;
4654b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      break;
4664b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao    default:
467cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected ccode: " << ccode;
4684b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao  }
4691fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpCondBranch(ccode, taken);
4704b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao}
4714b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao
4722ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
473fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
4741fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValue(rl_src, kCoreReg);
4751fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kCoreReg, true);
4762700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000);
4771fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
478efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
479efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4802ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
481fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
4821fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kCoreReg);
483a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu  rl_result = EvalLocWide(rl_dest, kCoreReg, true);
484a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu  if (Gen64Bit()) {
485a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu    LoadConstantWide(rl_result.reg, 0x8000000000000000);
486a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu    OpRegReg(kOpAdd, rl_result.reg, rl_src.reg);
487a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu  } else {
488a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu    OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000);
489a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu    OpRegCopy(rl_result.reg, rl_src.reg);
490a014776f4474579d4dfc72e3374ba45c6f6e5f35Chao-ying Fu  }
4911fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
492efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
493efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4941fd3346740dfb7f47be9922312b68a4227fada96buzbeebool X86Mir2Lir::GenInlinedSqrt(CallInfo* info) {
495bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell  RegLocation rl_src = info->args[0];
496bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell  RegLocation rl_dest = InlineTargetWide(info);  // double place for result
497bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell  rl_src = LoadValueWide(rl_src, kFPReg);
498bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell  RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true);
499091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR2(kX86SqrtsdRR, rl_result.reg.GetReg(), rl_src.reg.GetReg());
500bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell  StoreValueWide(rl_dest, rl_result);
501bff1ef0746048978b877c0664f758d2d6006f27dMark Mendell  return true;
502efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
503efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
504efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
505efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5067934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom}  // namespace art
507