fp_mips.cc revision a0cd2d701f29e0bc6275f1b13c0edfd4ec391879
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "codegen_mips.h" 18#include "dex/quick/mir_to_lir-inl.h" 19#include "entrypoints/quick/quick_entrypoints.h" 20#include "mips_lir.h" 21 22namespace art { 23 24void MipsMir2Lir::GenArithOpFloat(Instruction::Code opcode, 25 RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { 26 int op = kMipsNop; 27 RegLocation rl_result; 28 29 /* 30 * Don't attempt to optimize register usage since these opcodes call out to 31 * the handlers. 32 */ 33 switch (opcode) { 34 case Instruction::ADD_FLOAT_2ADDR: 35 case Instruction::ADD_FLOAT: 36 op = kMipsFadds; 37 break; 38 case Instruction::SUB_FLOAT_2ADDR: 39 case Instruction::SUB_FLOAT: 40 op = kMipsFsubs; 41 break; 42 case Instruction::DIV_FLOAT_2ADDR: 43 case Instruction::DIV_FLOAT: 44 op = kMipsFdivs; 45 break; 46 case Instruction::MUL_FLOAT_2ADDR: 47 case Instruction::MUL_FLOAT: 48 op = kMipsFmuls; 49 break; 50 case Instruction::REM_FLOAT_2ADDR: 51 case Instruction::REM_FLOAT: 52 FlushAllRegs(); // Send everything to home location 53 CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(4, pFmodf), rl_src1, rl_src2, 54 false); 55 rl_result = GetReturn(kFPReg); 56 StoreValue(rl_dest, rl_result); 57 return; 58 case Instruction::NEG_FLOAT: 59 GenNegFloat(rl_dest, rl_src1); 60 return; 61 default: 62 LOG(FATAL) << "Unexpected opcode: " << opcode; 63 } 64 rl_src1 = LoadValue(rl_src1, kFPReg); 65 rl_src2 = LoadValue(rl_src2, kFPReg); 66 rl_result = EvalLoc(rl_dest, kFPReg, true); 67 NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 68 StoreValue(rl_dest, rl_result); 69} 70 71void MipsMir2Lir::GenArithOpDouble(Instruction::Code opcode, 72 RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { 73 int op = kMipsNop; 74 RegLocation rl_result; 75 76 switch (opcode) { 77 case Instruction::ADD_DOUBLE_2ADDR: 78 case Instruction::ADD_DOUBLE: 79 op = kMipsFaddd; 80 break; 81 case Instruction::SUB_DOUBLE_2ADDR: 82 case Instruction::SUB_DOUBLE: 83 op = kMipsFsubd; 84 break; 85 case Instruction::DIV_DOUBLE_2ADDR: 86 case Instruction::DIV_DOUBLE: 87 op = kMipsFdivd; 88 break; 89 case Instruction::MUL_DOUBLE_2ADDR: 90 case Instruction::MUL_DOUBLE: 91 op = kMipsFmuld; 92 break; 93 case Instruction::REM_DOUBLE_2ADDR: 94 case Instruction::REM_DOUBLE: 95 FlushAllRegs(); // Send everything to home location 96 CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(4, pFmod), rl_src1, rl_src2, 97 false); 98 rl_result = GetReturnWide(kFPReg); 99 StoreValueWide(rl_dest, rl_result); 100 return; 101 case Instruction::NEG_DOUBLE: 102 GenNegDouble(rl_dest, rl_src1); 103 return; 104 default: 105 LOG(FATAL) << "Unpexpected opcode: " << opcode; 106 } 107 rl_src1 = LoadValueWide(rl_src1, kFPReg); 108 DCHECK(rl_src1.wide); 109 rl_src2 = LoadValueWide(rl_src2, kFPReg); 110 DCHECK(rl_src2.wide); 111 rl_result = EvalLoc(rl_dest, kFPReg, true); 112 DCHECK(rl_dest.wide); 113 DCHECK(rl_result.wide); 114 NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg()); 115 StoreValueWide(rl_dest, rl_result); 116} 117 118void MipsMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest, 119 RegLocation rl_src) { 120 int op = kMipsNop; 121 RegLocation rl_result; 122 switch (opcode) { 123 case Instruction::INT_TO_FLOAT: 124 op = kMipsFcvtsw; 125 break; 126 case Instruction::DOUBLE_TO_FLOAT: 127 op = kMipsFcvtsd; 128 break; 129 case Instruction::FLOAT_TO_DOUBLE: 130 op = kMipsFcvtds; 131 break; 132 case Instruction::INT_TO_DOUBLE: 133 op = kMipsFcvtdw; 134 break; 135 case Instruction::FLOAT_TO_INT: 136 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pF2iz), rl_dest, rl_src); 137 return; 138 case Instruction::DOUBLE_TO_INT: 139 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pD2iz), rl_dest, rl_src); 140 return; 141 case Instruction::LONG_TO_DOUBLE: 142 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pL2d), rl_dest, rl_src); 143 return; 144 case Instruction::FLOAT_TO_LONG: 145 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pF2l), rl_dest, rl_src); 146 return; 147 case Instruction::LONG_TO_FLOAT: 148 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pL2f), rl_dest, rl_src); 149 return; 150 case Instruction::DOUBLE_TO_LONG: 151 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pD2l), rl_dest, rl_src); 152 return; 153 default: 154 LOG(FATAL) << "Unexpected opcode: " << opcode; 155 } 156 if (rl_src.wide) { 157 rl_src = LoadValueWide(rl_src, kFPReg); 158 } else { 159 rl_src = LoadValue(rl_src, kFPReg); 160 } 161 rl_result = EvalLoc(rl_dest, kFPReg, true); 162 NewLIR2(op, rl_result.reg.GetReg(), rl_src.reg.GetReg()); 163 if (rl_dest.wide) { 164 StoreValueWide(rl_dest, rl_result); 165 } else { 166 StoreValue(rl_dest, rl_result); 167 } 168} 169 170void MipsMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, 171 RegLocation rl_src1, RegLocation rl_src2) { 172 bool wide = true; 173 ThreadOffset<4> offset(-1); 174 175 switch (opcode) { 176 case Instruction::CMPL_FLOAT: 177 offset = QUICK_ENTRYPOINT_OFFSET(4, pCmplFloat); 178 wide = false; 179 break; 180 case Instruction::CMPG_FLOAT: 181 offset = QUICK_ENTRYPOINT_OFFSET(4, pCmpgFloat); 182 wide = false; 183 break; 184 case Instruction::CMPL_DOUBLE: 185 offset = QUICK_ENTRYPOINT_OFFSET(4, pCmplDouble); 186 break; 187 case Instruction::CMPG_DOUBLE: 188 offset = QUICK_ENTRYPOINT_OFFSET(4, pCmpgDouble); 189 break; 190 default: 191 LOG(FATAL) << "Unexpected opcode: " << opcode; 192 } 193 FlushAllRegs(); 194 LockCallTemps(); 195 if (wide) { 196 RegStorage r_tmp1(RegStorage::k64BitPair, rMIPS_FARG0, rMIPS_FARG1); 197 RegStorage r_tmp2(RegStorage::k64BitPair, rMIPS_FARG2, rMIPS_FARG3); 198 LoadValueDirectWideFixed(rl_src1, r_tmp1); 199 LoadValueDirectWideFixed(rl_src2, r_tmp2); 200 } else { 201 LoadValueDirectFixed(rl_src1, rs_rMIPS_FARG0); 202 LoadValueDirectFixed(rl_src2, rs_rMIPS_FARG2); 203 } 204 RegStorage r_tgt = LoadHelper(offset); 205 // NOTE: not a safepoint 206 OpReg(kOpBlx, r_tgt); 207 RegLocation rl_result = GetReturn(kCoreReg); 208 StoreValue(rl_dest, rl_result); 209} 210 211void MipsMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, 212 bool gt_bias, bool is_double) { 213 UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch"; 214} 215 216void MipsMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) { 217 RegLocation rl_result; 218 rl_src = LoadValue(rl_src, kCoreReg); 219 rl_result = EvalLoc(rl_dest, kCoreReg, true); 220 OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000); 221 StoreValue(rl_dest, rl_result); 222} 223 224void MipsMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) { 225 RegLocation rl_result; 226 rl_src = LoadValueWide(rl_src, kCoreReg); 227 rl_result = EvalLoc(rl_dest, kCoreReg, true); 228 OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000); 229 OpRegCopy(rl_result.reg, rl_src.reg); 230 StoreValueWide(rl_dest, rl_result); 231} 232 233bool MipsMir2Lir::GenInlinedMinMaxInt(CallInfo* info, bool is_min) { 234 // TODO: need Mips implementation 235 return false; 236} 237 238} // namespace art 239