fp_arm.cc revision 5030d3ee8c6fe10394912ede107cbc8df63b7b16
167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/* 267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Copyright (C) 2011 The Android Open Source Project 367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * 467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Licensed under the Apache License, Version 2.0 (the "License"); 567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * you may not use this file except in compliance with the License. 667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * You may obtain a copy of the License at 767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * 867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * http://www.apache.org/licenses/LICENSE-2.0 967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * 1067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Unless required by applicable law or agreed to in writing, software 1167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * distributed under the License is distributed on an "AS IS" BASIS, 1267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * See the License for the specific language governing permissions and 1467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * limitations under the License. 1567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */ 1667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee 171bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "arm_lir.h" 1802031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_arm.h" 197940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h" 201bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 2111d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughesnamespace art { 2211d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes 231fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, 242ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom RegLocation rl_src1, RegLocation rl_src2) { 25a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int op = kThumbBkpt; 26fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 2767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee 28a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 29a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Don't attempt to optimize register usage since these opcodes call out to 30a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * the handlers. 31a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 32408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee switch (opcode) { 33a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::ADD_FLOAT_2ADDR: 34a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::ADD_FLOAT: 35a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op = kThumb2Vadds; 36a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 37a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::SUB_FLOAT_2ADDR: 38a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::SUB_FLOAT: 39a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op = kThumb2Vsubs; 40a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 41a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::DIV_FLOAT_2ADDR: 42a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::DIV_FLOAT: 43a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op = kThumb2Vdivs; 44a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 45a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::MUL_FLOAT_2ADDR: 46a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::MUL_FLOAT: 47a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op = kThumb2Vmuls; 48a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 49a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::REM_FLOAT_2ADDR: 50a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::REM_FLOAT: 511fd3346740dfb7f47be9922312b68a4227fada96buzbee FlushAllRegs(); // Send everything to home location 52dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(4, pFmodf), rl_src1, rl_src2, 537655f29fabc0a12765de828914a18314382e5a35Ian Rogers false); 54a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee rl_result = GetReturn(kFPReg); 551fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 56a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 57a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee case Instruction::NEG_FLOAT: 581fd3346740dfb7f47be9922312b68a4227fada96buzbee GenNegFloat(rl_dest, rl_src1); 59a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 60a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee default: 61a5954be0aac5edd892fb31a209960543d00e4500buzbee LOG(FATAL) << "Unexpected opcode: " << opcode; 62a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 631fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValue(rl_src1, kFPReg); 641fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValue(rl_src2, kFPReg); 651fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 6600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 671fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 6867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee} 6967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee 701fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArithOpDouble(Instruction::Code opcode, 712ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { 72a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int op = kThumbBkpt; 73fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 7467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee 75408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee switch (opcode) { 76a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::ADD_DOUBLE_2ADDR: 77a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::ADD_DOUBLE: 78a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op = kThumb2Vaddd; 79a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 80a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::SUB_DOUBLE_2ADDR: 81a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::SUB_DOUBLE: 82a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op = kThumb2Vsubd; 83a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 84a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::DIV_DOUBLE_2ADDR: 85a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::DIV_DOUBLE: 86a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op = kThumb2Vdivd; 87a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 88a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::MUL_DOUBLE_2ADDR: 89a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::MUL_DOUBLE: 90a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op = kThumb2Vmuld; 91a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 92a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::REM_DOUBLE_2ADDR: 93a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::REM_DOUBLE: 941fd3346740dfb7f47be9922312b68a4227fada96buzbee FlushAllRegs(); // Send everything to home location 95dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(4, pFmod), rl_src1, rl_src2, 967655f29fabc0a12765de828914a18314382e5a35Ian Rogers false); 97a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee rl_result = GetReturnWide(kFPReg); 981fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_result); 99a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 100a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee case Instruction::NEG_DOUBLE: 1011fd3346740dfb7f47be9922312b68a4227fada96buzbee GenNegDouble(rl_dest, rl_src1); 102a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 103a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee default: 104a5954be0aac5edd892fb31a209960543d00e4500buzbee LOG(FATAL) << "Unexpected opcode: " << opcode; 105a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 10667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee 1071fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValueWide(rl_src1, kFPReg); 108fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DCHECK(rl_src1.wide); 1091fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValueWide(rl_src2, kFPReg); 110fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DCHECK(rl_src2.wide); 1111fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 112fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DCHECK(rl_dest.wide); 113fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DCHECK(rl_result.wide); 114091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 1151fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_result); 11667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee} 11767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee 118091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeevoid ArmMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src) { 119a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int op = kThumbBkpt; 120fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int src_reg; 121fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 12267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee 123a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee switch (opcode) { 124a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::INT_TO_FLOAT: 125a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op = kThumb2VcvtIF; 126a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 127a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::FLOAT_TO_INT: 128a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op = kThumb2VcvtFI; 129a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 130a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::DOUBLE_TO_FLOAT: 131a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op = kThumb2VcvtDF; 132a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 133a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::FLOAT_TO_DOUBLE: 134a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op = kThumb2VcvtFd; 135a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 136a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::INT_TO_DOUBLE: 137e19649a91702234f9aa9941d76da447a1e0dcc2aZheng Xu op = kThumb2VcvtF64S32; 138a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 139a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::DOUBLE_TO_INT: 140a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op = kThumb2VcvtDI; 141a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 142ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers case Instruction::LONG_TO_DOUBLE: { 143ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers rl_src = LoadValueWide(rl_src, kFPReg); 14485089dd28a39dd20f42ac258398b2a08668f9ef1buzbee RegisterInfo* info = GetRegInfo(rl_src.reg); 14585089dd28a39dd20f42ac258398b2a08668f9ef1buzbee RegStorage src_low = info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg(); 14685089dd28a39dd20f42ac258398b2a08668f9ef1buzbee DCHECK(src_low.Valid()); 14785089dd28a39dd20f42ac258398b2a08668f9ef1buzbee RegStorage src_high = info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg(); 14885089dd28a39dd20f42ac258398b2a08668f9ef1buzbee DCHECK(src_high.Valid()); 149ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers rl_result = EvalLoc(rl_dest, kFPReg, true); 1502700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage tmp1 = AllocTempDouble(); 1512700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage tmp2 = AllocTempDouble(); 152ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers 153091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kThumb2VcvtF64S32, tmp1.GetReg(), src_high.GetReg()); 154091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kThumb2VcvtF64U32, rl_result.reg.GetReg(), src_low.GetReg()); 1552700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantWide(tmp2, 0x41f0000000000000LL); 156091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR3(kThumb2VmlaF64, rl_result.reg.GetReg(), tmp1.GetReg(), tmp2.GetReg()); 157ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers FreeTemp(tmp1); 158ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers FreeTemp(tmp2); 159ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers StoreValueWide(rl_dest, rl_result); 160a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 161ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers } 162a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::FLOAT_TO_LONG: 163dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pF2l), rl_dest, rl_src); 164a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 165f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu case Instruction::LONG_TO_FLOAT: { 166f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu rl_src = LoadValueWide(rl_src, kFPReg); 16785089dd28a39dd20f42ac258398b2a08668f9ef1buzbee RegisterInfo* info = GetRegInfo(rl_src.reg); 16885089dd28a39dd20f42ac258398b2a08668f9ef1buzbee RegStorage src_low = info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg(); 16985089dd28a39dd20f42ac258398b2a08668f9ef1buzbee DCHECK(src_low.Valid()); 17085089dd28a39dd20f42ac258398b2a08668f9ef1buzbee RegStorage src_high = info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg(); 17185089dd28a39dd20f42ac258398b2a08668f9ef1buzbee DCHECK(src_high.Valid()); 172f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu rl_result = EvalLoc(rl_dest, kFPReg, true); 173f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu // Allocate temp registers. 1742700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage high_val = AllocTempDouble(); 1752700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage low_val = AllocTempDouble(); 1762700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage const_val = AllocTempDouble(); 177f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu // Long to double. 178091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kThumb2VcvtF64S32, high_val.GetReg(), src_high.GetReg()); 179091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kThumb2VcvtF64U32, low_val.GetReg(), src_low.GetReg()); 1802700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantWide(const_val, INT64_C(0x41f0000000000000)); 181091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR3(kThumb2VmlaF64, low_val.GetReg(), high_val.GetReg(), const_val.GetReg()); 182f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu // Double to float. 183091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kThumb2VcvtDF, rl_result.reg.GetReg(), low_val.GetReg()); 184f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu // Free temp registers. 185f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu FreeTemp(high_val); 186f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu FreeTemp(low_val); 187f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu FreeTemp(const_val); 188f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu // Store result. 189f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu StoreValue(rl_dest, rl_result); 190a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 191f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu } 192a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::DOUBLE_TO_LONG: 193dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pD2l), rl_dest, rl_src); 194a5954be0aac5edd892fb31a209960543d00e4500buzbee return; 195a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee default: 196a5954be0aac5edd892fb31a209960543d00e4500buzbee LOG(FATAL) << "Unexpected opcode: " << opcode; 197a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 198fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (rl_src.wide) { 1991fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValueWide(rl_src, kFPReg); 200091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee src_reg = rl_src.reg.GetReg(); 201a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 2021fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValue(rl_src, kFPReg); 20300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee src_reg = rl_src.reg.GetReg(); 204a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 205fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (rl_dest.wide) { 2061fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 207091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(op, rl_result.reg.GetReg(), src_reg); 2081fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_result); 209a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 2101fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 21100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(op, rl_result.reg.GetReg(), src_reg); 2121fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 213a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 21467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee} 21567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee 2161fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, 2172ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom bool is_double) { 2180d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee LIR* target = &block_label_list_[bb->taken]; 219fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_src1; 220fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_src2; 221fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (is_double) { 2221fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = mir_graph_->GetSrcWide(mir, 0); 2231fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = mir_graph_->GetSrcWide(mir, 2); 2241fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValueWide(rl_src1, kFPReg); 2251fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValueWide(rl_src2, kFPReg); 226091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kThumb2Vcmpd, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 227a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 2281fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = mir_graph_->GetSrc(mir, 0); 2291fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = mir_graph_->GetSrc(mir, 1); 2301fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValue(rl_src1, kFPReg); 2311fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValue(rl_src2, kFPReg); 23200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kThumb2Vcmps, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 233a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 2341fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR0(kThumb2Fmstat); 235a894607bca7eb623bc957363e4b36f44cfeea1b6Vladimir Marko ConditionCode ccode = mir->meta.ccode; 236df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom switch (ccode) { 237a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kCondEq: 238a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kCondNe: 239a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 240a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kCondLt: 241fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 242a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee ccode = kCondMi; 243a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 244a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 245a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kCondLe: 246fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 247a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee ccode = kCondLs; 248a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 249a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 250a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kCondGt: 251fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 252a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee ccode = kCondHi; 253a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 254a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 255a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kCondGe: 256fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (gt_bias) { 25758af1f9385742f70aca4fcb5e13aba53b8be2ef4Vladimir Marko ccode = kCondUge; 258a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 259a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 260a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee default: 261cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(FATAL) << "Unexpected ccode: " << ccode; 262a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 2631fd3346740dfb7f47be9922312b68a4227fada96buzbee OpCondBranch(ccode, target); 26484fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee} 26584fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee 26684fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee 2671fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, 2682ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom RegLocation rl_src1, RegLocation rl_src2) { 269a5954be0aac5edd892fb31a209960543d00e4500buzbee bool is_double = false; 270a5954be0aac5edd892fb31a209960543d00e4500buzbee int default_result = -1; 271fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 27267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee 273408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee switch (opcode) { 274a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::CMPL_FLOAT: 275fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee is_double = false; 276fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee default_result = -1; 277a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 278a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::CMPG_FLOAT: 279fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee is_double = false; 280fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee default_result = 1; 281a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 282a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::CMPL_DOUBLE: 283fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee is_double = true; 284fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee default_result = -1; 285a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 286a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case Instruction::CMPG_DOUBLE: 287fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee is_double = true; 288fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee default_result = 1; 289a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 290a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee default: 291a5954be0aac5edd892fb31a209960543d00e4500buzbee LOG(FATAL) << "Unexpected opcode: " << opcode; 292a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 293fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (is_double) { 2941fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValueWide(rl_src1, kFPReg); 2951fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValueWide(rl_src2, kFPReg); 296078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee // In case result vreg is also a src vreg, break association to avoid useless copy by EvalLoc() 2971fd3346740dfb7f47be9922312b68a4227fada96buzbee ClobberSReg(rl_dest.s_reg_low); 2981fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kCoreReg, true); 2992700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstant(rl_result.reg, default_result); 300091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kThumb2Vcmpd, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 301a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 3021fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src1 = LoadValue(rl_src1, kFPReg); 3031fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src2 = LoadValue(rl_src2, kFPReg); 304078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee // In case result vreg is also a srcvreg, break association to avoid useless copy by EvalLoc() 3051fd3346740dfb7f47be9922312b68a4227fada96buzbee ClobberSReg(rl_dest.s_reg_low); 3061fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kCoreReg, true); 3072700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstant(rl_result.reg, default_result); 30800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kThumb2Vcmps, rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 309a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 310091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(!rl_result.reg.IsFloat()); 3111fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR0(kThumb2Fmstat); 31267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee 3133da67a558f1fd3d8a157d8044d521753f3f99ac8Dave Allison LIR* it = OpIT((default_result == -1) ? kCondGt : kCondMi, ""); 31400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kThumb2MovI8M, rl_result.reg.GetReg(), 3157934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom ModifiedImmediate(-default_result)); // Must not alter ccodes 3163da67a558f1fd3d8a157d8044d521753f3f99ac8Dave Allison OpEndIT(it); 31767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee 3183da67a558f1fd3d8a157d8044d521753f3f99ac8Dave Allison it = OpIT(kCondEq, ""); 3192700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstant(rl_result.reg, 0); 3203da67a558f1fd3d8a157d8044d521753f3f99ac8Dave Allison OpEndIT(it); 32167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee 3221fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 32367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee} 32411d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes 3252ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) { 326fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 3271fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValue(rl_src, kFPReg); 3281fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 32900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee NewLIR2(kThumb2Vnegs, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 3301fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 331efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 332efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 3332ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) { 334fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_result; 3351fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValueWide(rl_src, kFPReg); 3361fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_result = EvalLoc(rl_dest, kFPReg, true); 337091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kThumb2Vnegd, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 3381fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_result); 339efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 340efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 3415030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Markostatic RegisterClass RegClassForAbsFP(RegLocation rl_src, RegLocation rl_dest) { 3425030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko // If src is in a core reg or, unlikely, dest has been promoted to a core reg, use core reg. 3435030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko if ((rl_src.location == kLocPhysReg && !rl_src.reg.IsFloat()) || 3445030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko (rl_dest.location == kLocPhysReg && !rl_dest.reg.IsFloat())) { 3455030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko return kCoreReg; 3465030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko } 3475030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko // If src is in an fp reg or dest has been promoted to an fp reg, use fp reg. 3485030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko if (rl_src.location == kLocPhysReg || rl_dest.location == kLocPhysReg) { 3495030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko return kFPReg; 3505030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko } 3515030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko // With both src and dest in the stack frame we have to perform load+abs+store. Whether this 3525030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko // is faster using a core reg or fp reg depends on the particular CPU. Without further 3535030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko // investigation and testing we prefer core register. (If the result is subsequently used in 3545030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko // another fp operation, the dalvik reg will probably get promoted and that should be handled 3555030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko // by the cases above.) 3565030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko return kCoreReg; 3575030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko} 3585030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko 3595030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Markobool ArmMir2Lir::GenInlinedAbsFloat(CallInfo* info) { 3605030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko if (info->result.location == kLocInvalid) { 3615030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko return true; // Result is unused: inlining successful, no code generated. 3625030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko } 3635030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko RegLocation rl_dest = info->result; 3645030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko RegLocation rl_src = UpdateLoc(info->args[0]); 3655030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko RegisterClass reg_class = RegClassForAbsFP(rl_src, rl_dest); 3665030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko rl_src = LoadValue(rl_src, reg_class); 3675030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko RegLocation rl_result = EvalLoc(rl_dest, reg_class, true); 3685030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko if (reg_class == kFPReg) { 3695030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko NewLIR2(kThumb2Vabss, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 3705030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko } else { 3715030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko OpRegRegImm(kOpAnd, rl_result.reg, rl_src.reg, 0x7fffffff); 3725030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko } 3735030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko StoreValue(rl_dest, rl_result); 3745030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko return true; 3755030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko} 3765030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko 3775030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Markobool ArmMir2Lir::GenInlinedAbsDouble(CallInfo* info) { 3785030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko if (info->result.location == kLocInvalid) { 3795030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko return true; // Result is unused: inlining successful, no code generated. 3805030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko } 3815030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko RegLocation rl_dest = info->result; 3825030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko RegLocation rl_src = UpdateLocWide(info->args[0]); 3835030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko RegisterClass reg_class = RegClassForAbsFP(rl_src, rl_dest); 3845030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko rl_src = LoadValueWide(rl_src, reg_class); 3855030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko RegLocation rl_result = EvalLoc(rl_dest, reg_class, true); 3865030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko if (reg_class == kFPReg) { 3875030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko NewLIR2(kThumb2Vabsd, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 3885030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko } else { 3895030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko OpRegImm(kOpAnd, rl_result.reg.GetHigh(), 0x7fffffff); 3905030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko } 3915030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko StoreValueWide(rl_dest, rl_result); 3925030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko return true; 3935030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko} 3945030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko 3951fd3346740dfb7f47be9922312b68a4227fada96buzbeebool ArmMir2Lir::GenInlinedSqrt(CallInfo* info) { 3961fd3346740dfb7f47be9922312b68a4227fada96buzbee DCHECK_EQ(cu_->instruction_set, kThumb2); 397fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_src = info->args[0]; 3981fd3346740dfb7f47be9922312b68a4227fada96buzbee RegLocation rl_dest = InlineTargetWide(info); // double place for result 3991fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValueWide(rl_src, kFPReg); 4001fd3346740dfb7f47be9922312b68a4227fada96buzbee RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true); 401091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR2(kThumb2Vsqrtd, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 4021fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_result); 403efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return true; 404efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 405efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 406efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 40711d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes} // namespace art 408