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
527655f29fabc0a12765de828914a18314382e5a35Ian Rogers      CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(pFmodf), rl_src1, rl_src2,
537655f29fabc0a12765de828914a18314382e5a35Ian Rogers                                              false);
541fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_result = GetReturn(true);
551fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValue(rl_dest, rl_result);
56a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
57a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    case Instruction::NEG_FLOAT:
581fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenNegFloat(rl_dest, rl_src1);
59a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
60b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
61a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
62b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
631fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValue(rl_src1, kFPReg);
641fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValue(rl_src2, kFPReg);
651fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
66fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int r_dest = rl_result.low_reg;
67fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int r_src1 = rl_src1.low_reg;
68fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int r_src2 = rl_src2.low_reg;
69fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (r_dest == r_src2) {
701fd3346740dfb7f47be9922312b68a4227fada96buzbee    r_src2 = AllocTempFloat();
711fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegCopy(r_src2, r_dest);
724abb1a9000b525a0636763a97528e24468f16d10jeffhao  }
731fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegCopy(r_dest, r_src1);
741fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(op, r_dest, r_src2);
751fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
76e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
77e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
781fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenArithOpDouble(Instruction::Code opcode,
7902031b185b4653e6c72e21f7a51238b903f6d638buzbee                                  RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
80b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode op = kX86Nop;
81fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
82e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
83408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee  switch (opcode) {
84b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::ADD_DOUBLE_2ADDR:
85b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::ADD_DOUBLE:
86b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86AddsdRR;
87b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
88b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::SUB_DOUBLE_2ADDR:
89b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::SUB_DOUBLE:
90b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86SubsdRR;
91b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
92b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::DIV_DOUBLE_2ADDR:
93b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::DIV_DOUBLE:
94b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86DivsdRR;
95b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
96b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::MUL_DOUBLE_2ADDR:
97b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::MUL_DOUBLE:
98b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86MulsdRR;
99b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
100b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::REM_DOUBLE_2ADDR:
101babda950caf2d577aa57102c3281f0f3c36f3d6djeffhao    case Instruction::REM_DOUBLE:
1021fd3346740dfb7f47be9922312b68a4227fada96buzbee      FlushAllRegs();   // Send everything to home location
1037655f29fabc0a12765de828914a18314382e5a35Ian Rogers      CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(pFmod), rl_src1, rl_src2,
1047655f29fabc0a12765de828914a18314382e5a35Ian Rogers                                              false);
1051fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_result = GetReturnWide(true);
1061fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValueWide(rl_dest, rl_result);
107a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
108a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    case Instruction::NEG_DOUBLE:
1091fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenNegDouble(rl_dest, rl_src1);
110a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
111b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
112a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
113b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
1141fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kFPReg);
115fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_src1.wide);
1161fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValueWide(rl_src2, kFPReg);
117fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_src2.wide);
1181fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
119fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_dest.wide);
120fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_result.wide);
121fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int r_dest = S2d(rl_result.low_reg, rl_result.high_reg);
122fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int r_src1 = S2d(rl_src1.low_reg, rl_src1.high_reg);
123fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int r_src2 = S2d(rl_src2.low_reg, rl_src2.high_reg);
124fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (r_dest == r_src2) {
1251fd3346740dfb7f47be9922312b68a4227fada96buzbee    r_src2 = AllocTempDouble() | X86_FP_DOUBLE;
1261fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegCopy(r_src2, r_dest);
1274abb1a9000b525a0636763a97528e24468f16d10jeffhao  }
1281fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegCopy(r_dest, r_src1);
1291fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(op, r_dest, r_src2);
1301fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
131e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
132e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
1331fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest,
13402031b185b4653e6c72e21f7a51238b903f6d638buzbee                               RegLocation rl_src) {
1355121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao  RegisterClass rcSrc = kFPReg;
136b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode op = kX86Nop;
137fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int src_reg;
138fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
139b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (opcode) {
140b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::INT_TO_FLOAT:
1415121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao      rcSrc = kCoreReg;
142b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86Cvtsi2ssRR;
143b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
144b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::DOUBLE_TO_FLOAT:
1455121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao      rcSrc = kFPReg;
146b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86Cvtsd2ssRR;
147b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
148b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::FLOAT_TO_DOUBLE:
1495121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao      rcSrc = kFPReg;
150b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86Cvtss2sdRR;
151b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
152b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::INT_TO_DOUBLE:
1535121e0b9699c8cd5e89ee323e30074b984b7b436jeffhao      rcSrc = kCoreReg;
154b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      op = kX86Cvtsi2sdRR;
155b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
156292188d514c9826971308a18fcc5a66261729f3bjeffhao    case Instruction::FLOAT_TO_INT: {
1571fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_src = LoadValue(rl_src, kFPReg);
158fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      src_reg = rl_src.low_reg;
159078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee      // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc()
1601fd3346740dfb7f47be9922312b68a4227fada96buzbee      ClobberSReg(rl_dest.s_reg_low);
1611fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_result = EvalLoc(rl_dest, kCoreReg, true);
1621fd3346740dfb7f47be9922312b68a4227fada96buzbee      int temp_reg = AllocTempFloat();
16341005ddb5576b8630a1084fbb3979ffa602c0599jeffhao
1641fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(rl_result.low_reg, 0x7fffffff);
1651fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kX86Cvtsi2ssRR, temp_reg, rl_result.low_reg);
1661fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kX86ComissRR, src_reg, temp_reg);
1671fd3346740dfb7f47be9922312b68a4227fada96buzbee      LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondA);
1681fd3346740dfb7f47be9922312b68a4227fada96buzbee      LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP);
1691fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kX86Cvttss2siRR, rl_result.low_reg, src_reg);
1701fd3346740dfb7f47be9922312b68a4227fada96buzbee      LIR* branch_normal = NewLIR1(kX86Jmp8, 0);
1711fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch_na_n->target = NewLIR0(kPseudoTargetLabel);
1721fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kX86Xor32RR, rl_result.low_reg, rl_result.low_reg);
1731fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel);
1741fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch_normal->target = NewLIR0(kPseudoTargetLabel);
1751fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValue(rl_dest, rl_result);
176a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
177292188d514c9826971308a18fcc5a66261729f3bjeffhao    }
178292188d514c9826971308a18fcc5a66261729f3bjeffhao    case Instruction::DOUBLE_TO_INT: {
1791fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_src = LoadValueWide(rl_src, kFPReg);
180fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      src_reg = rl_src.low_reg;
181078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee      // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc()
1821fd3346740dfb7f47be9922312b68a4227fada96buzbee      ClobberSReg(rl_dest.s_reg_low);
1831fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_result = EvalLoc(rl_dest, kCoreReg, true);
1841fd3346740dfb7f47be9922312b68a4227fada96buzbee      int temp_reg = AllocTempDouble() | X86_FP_DOUBLE;
18541005ddb5576b8630a1084fbb3979ffa602c0599jeffhao
1861fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(rl_result.low_reg, 0x7fffffff);
1871fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kX86Cvtsi2sdRR, temp_reg, rl_result.low_reg);
1881fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kX86ComisdRR, src_reg, temp_reg);
1891fd3346740dfb7f47be9922312b68a4227fada96buzbee      LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondA);
1901fd3346740dfb7f47be9922312b68a4227fada96buzbee      LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP);
1911fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kX86Cvttsd2siRR, rl_result.low_reg, src_reg);
1921fd3346740dfb7f47be9922312b68a4227fada96buzbee      LIR* branch_normal = NewLIR1(kX86Jmp8, 0);
1931fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch_na_n->target = NewLIR0(kPseudoTargetLabel);
1941fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kX86Xor32RR, rl_result.low_reg, rl_result.low_reg);
1951fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel);
1961fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch_normal->target = NewLIR0(kPseudoTargetLabel);
1971fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValue(rl_dest, rl_result);
198a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
199292188d514c9826971308a18fcc5a66261729f3bjeffhao    }
200b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::LONG_TO_DOUBLE:
2017655f29fabc0a12765de828914a18314382e5a35Ian Rogers      GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src);
202a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
203b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::LONG_TO_FLOAT:
204babda950caf2d577aa57102c3281f0f3c36f3d6djeffhao      // TODO: inline by using memory as a 64-bit source. Be careful about promoted registers.
2057655f29fabc0a12765de828914a18314382e5a35Ian Rogers      GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src);
206a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
20741005ddb5576b8630a1084fbb3979ffa602c0599jeffhao    case Instruction::FLOAT_TO_LONG:
2087655f29fabc0a12765de828914a18314382e5a35Ian Rogers      GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src);
209a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
210b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case Instruction::DOUBLE_TO_LONG:
2117655f29fabc0a12765de828914a18314382e5a35Ian Rogers      GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src);
212a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
213b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
214a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(INFO) << "Unexpected opcode: " << opcode;
215b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
216fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_src.wide) {
2171fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src = LoadValueWide(rl_src, rcSrc);
218fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    src_reg = S2d(rl_src.low_reg, rl_src.high_reg);
219b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  } else {
2201fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src = LoadValue(rl_src, rcSrc);
221fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    src_reg = rl_src.low_reg;
222b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
223fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_dest.wide) {
2241fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kFPReg, true);
2251fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg);
2261fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValueWide(rl_dest, rl_result);
227b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  } else {
2281fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kFPReg, true);
2291fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(op, rl_result.low_reg, src_reg);
2301fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValue(rl_dest, rl_result);
231b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
232e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
233e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
2341fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenCmpFP(Instruction::Code code, RegLocation rl_dest,
23502031b185b4653e6c72e21f7a51238b903f6d638buzbee                          RegLocation rl_src1, RegLocation rl_src2) {
236b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  bool single = (code == Instruction::CMPL_FLOAT) || (code == Instruction::CMPG_FLOAT);
237fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool unordered_gt = (code == Instruction::CMPG_DOUBLE) || (code == Instruction::CMPG_FLOAT);
238fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int src_reg1;
239fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int src_reg2;
240b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  if (single) {
2411fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValue(rl_src1, kFPReg);
242fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    src_reg1 = rl_src1.low_reg;
2431fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValue(rl_src2, kFPReg);
244fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    src_reg2 = rl_src2.low_reg;
245b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  } else {
2461fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValueWide(rl_src1, kFPReg);
247fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    src_reg1 = S2d(rl_src1.low_reg, rl_src1.high_reg);
2481fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValueWide(rl_src2, kFPReg);
249fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    src_reg2 = S2d(rl_src2.low_reg, rl_src2.high_reg);
250b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
251078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee  // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc()
2521fd3346740dfb7f47be9922312b68a4227fada96buzbee  ClobberSReg(rl_dest.s_reg_low);
2531fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
2541fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadConstantNoClobber(rl_result.low_reg, unordered_gt ? 1 : 0);
255b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  if (single) {
2561fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kX86UcomissRR, src_reg1, src_reg2);
257b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  } else {
2581fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kX86UcomisdRR, src_reg1, src_reg2);
259b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
260b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  LIR* branch = NULL;
261fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (unordered_gt) {
2621fd3346740dfb7f47be9922312b68a4227fada96buzbee    branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
263b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
264703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao  // If the result reg can't be byte accessed, use a jump and move instead of a set.
265fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_result.low_reg >= 4) {
266703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao    LIR* branch2 = NULL;
267fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (unordered_gt) {
2681fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch2 = NewLIR2(kX86Jcc8, 0, kX86CondA);
2691fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kX86Mov32RI, rl_result.low_reg, 0x0);
270703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao    } else {
2711fd3346740dfb7f47be9922312b68a4227fada96buzbee      branch2 = NewLIR2(kX86Jcc8, 0, kX86CondBe);
2721fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kX86Mov32RI, rl_result.low_reg, 0x1);
273703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao    }
2741fd3346740dfb7f47be9922312b68a4227fada96buzbee    branch2->target = NewLIR0(kPseudoTargetLabel);
275703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao  } else {
2761fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kX86Set8R, rl_result.low_reg, kX86CondA /* above - unsigned > */);
277703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao  }
2781fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kX86Sbb32RI, rl_result.low_reg, 0);
279fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (unordered_gt) {
2801fd3346740dfb7f47be9922312b68a4227fada96buzbee    branch->target = NewLIR0(kPseudoTargetLabel);
281b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
2821fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
283e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
284e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
2851fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias,
28602031b185b4653e6c72e21f7a51238b903f6d638buzbee                                     bool is_double) {
2871fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* taken = &block_label_list_[bb->taken->id];
2881fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* not_taken = &block_label_list_[bb->fall_through->id];
2894b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao  LIR* branch = NULL;
290fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src1;
291fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src2;
292fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_double) {
2931fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = mir_graph_->GetSrcWide(mir, 0);
2941fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = mir_graph_->GetSrcWide(mir, 2);
2951fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValueWide(rl_src1, kFPReg);
2961fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValueWide(rl_src2, kFPReg);
2971fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kX86UcomisdRR, S2d(rl_src1.low_reg, rl_src1.high_reg),
298fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            S2d(rl_src2.low_reg, rl_src2.high_reg));
2994b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao  } else {
3001fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = mir_graph_->GetSrc(mir, 0);
3011fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = mir_graph_->GetSrc(mir, 1);
3021fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValue(rl_src1, kFPReg);
3031fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValue(rl_src2, kFPReg);
3041fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kX86UcomissRR, rl_src1.low_reg, rl_src2.low_reg);
3054b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao  }
3064b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao  ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
3074b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao  switch (ccode) {
3084b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao    case kCondEq:
309fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (!gt_bias) {
3101fd3346740dfb7f47be9922312b68a4227fada96buzbee        branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
311fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        branch->target = not_taken;
3124b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      }
3134b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      break;
3144b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao    case kCondNe:
315fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (!gt_bias) {
3161fd3346740dfb7f47be9922312b68a4227fada96buzbee        branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
3174b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao        branch->target = taken;
3184b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      }
3194b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      break;
3204b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao    case kCondLt:
321fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
3221fd3346740dfb7f47be9922312b68a4227fada96buzbee        branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
323fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        branch->target = not_taken;
3244b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      }
3254b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      ccode = kCondCs;
3264b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      break;
3274b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao    case kCondLe:
328fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
3291fd3346740dfb7f47be9922312b68a4227fada96buzbee        branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
330fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        branch->target = not_taken;
3314b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      }
3324b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      ccode = kCondLs;
3334b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      break;
3344b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao    case kCondGt:
335fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
3361fd3346740dfb7f47be9922312b68a4227fada96buzbee        branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
3374b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao        branch->target = taken;
3384b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      }
3394b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      ccode = kCondHi;
3404b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      break;
3414b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao    case kCondGe:
342fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
3431fd3346740dfb7f47be9922312b68a4227fada96buzbee        branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
3444b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao        branch->target = taken;
3454b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      }
3464b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      ccode = kCondCc;
3474b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao      break;
3484b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao    default:
349cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected ccode: " << ccode;
3504b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao  }
3511fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpCondBranch(ccode, taken);
3524b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao}
3534b771a09fe1d947dee7265e3c018d7f1dd89a5d3jeffhao
3542ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
355fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
3561fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValue(rl_src, kCoreReg);
3571fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kCoreReg, true);
3581fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegRegImm(kOpAdd, rl_result.low_reg, rl_src.low_reg, 0x80000000);
3591fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
360efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
361efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3622ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
363fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
3641fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kCoreReg);
3651fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kCoreReg, true);
3661fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegRegImm(kOpAdd, rl_result.high_reg, rl_src.high_reg, 0x80000000);
3671fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegCopy(rl_result.low_reg, rl_src.low_reg);
3681fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
369efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
370efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3711fd3346740dfb7f47be9922312b68a4227fada96buzbeebool X86Mir2Lir::GenInlinedSqrt(CallInfo* info) {
3721fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK_NE(cu_->instruction_set, kThumb2);
373efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return false;
374efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
375efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
376efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
377efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3787934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom}  // namespace art
379