fp_mips.cc revision 7655f29fabc0a12765de828914a18314382e5a35
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(pFmodf), rl_src1, rl_src2, 54 false); 55 rl_result = GetReturn(true); 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.low_reg, rl_src1.low_reg, rl_src2.low_reg); 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(pFmod), rl_src1, rl_src2, 97 false); 98 rl_result = GetReturnWide(true); 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, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_src1.low_reg, rl_src1.high_reg), 115 S2d(rl_src2.low_reg, rl_src2.high_reg)); 116 StoreValueWide(rl_dest, rl_result); 117} 118 119void MipsMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest, 120 RegLocation rl_src) { 121 int op = kMipsNop; 122 int src_reg; 123 RegLocation rl_result; 124 switch (opcode) { 125 case Instruction::INT_TO_FLOAT: 126 op = kMipsFcvtsw; 127 break; 128 case Instruction::DOUBLE_TO_FLOAT: 129 op = kMipsFcvtsd; 130 break; 131 case Instruction::FLOAT_TO_DOUBLE: 132 op = kMipsFcvtds; 133 break; 134 case Instruction::INT_TO_DOUBLE: 135 op = kMipsFcvtdw; 136 break; 137 case Instruction::FLOAT_TO_INT: 138 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pF2iz), rl_dest, rl_src); 139 return; 140 case Instruction::DOUBLE_TO_INT: 141 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pD2iz), rl_dest, rl_src); 142 return; 143 case Instruction::LONG_TO_DOUBLE: 144 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src); 145 return; 146 case Instruction::FLOAT_TO_LONG: 147 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src); 148 return; 149 case Instruction::LONG_TO_FLOAT: 150 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src); 151 return; 152 case Instruction::DOUBLE_TO_LONG: 153 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src); 154 return; 155 default: 156 LOG(FATAL) << "Unexpected opcode: " << opcode; 157 } 158 if (rl_src.wide) { 159 rl_src = LoadValueWide(rl_src, kFPReg); 160 src_reg = S2d(rl_src.low_reg, rl_src.high_reg); 161 } else { 162 rl_src = LoadValue(rl_src, kFPReg); 163 src_reg = rl_src.low_reg; 164 } 165 if (rl_dest.wide) { 166 rl_result = EvalLoc(rl_dest, kFPReg, true); 167 NewLIR2(op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg); 168 StoreValueWide(rl_dest, rl_result); 169 } else { 170 rl_result = EvalLoc(rl_dest, kFPReg, true); 171 NewLIR2(op, rl_result.low_reg, src_reg); 172 StoreValue(rl_dest, rl_result); 173 } 174} 175 176void MipsMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, 177 RegLocation rl_src1, RegLocation rl_src2) { 178 bool wide = true; 179 int offset = -1; // Make gcc happy. 180 181 switch (opcode) { 182 case Instruction::CMPL_FLOAT: 183 offset = QUICK_ENTRYPOINT_OFFSET(pCmplFloat); 184 wide = false; 185 break; 186 case Instruction::CMPG_FLOAT: 187 offset = QUICK_ENTRYPOINT_OFFSET(pCmpgFloat); 188 wide = false; 189 break; 190 case Instruction::CMPL_DOUBLE: 191 offset = QUICK_ENTRYPOINT_OFFSET(pCmplDouble); 192 break; 193 case Instruction::CMPG_DOUBLE: 194 offset = QUICK_ENTRYPOINT_OFFSET(pCmpgDouble); 195 break; 196 default: 197 LOG(FATAL) << "Unexpected opcode: " << opcode; 198 } 199 FlushAllRegs(); 200 LockCallTemps(); 201 if (wide) { 202 LoadValueDirectWideFixed(rl_src1, rMIPS_FARG0, rMIPS_FARG1); 203 LoadValueDirectWideFixed(rl_src2, rMIPS_FARG2, rMIPS_FARG3); 204 } else { 205 LoadValueDirectFixed(rl_src1, rMIPS_FARG0); 206 LoadValueDirectFixed(rl_src2, rMIPS_FARG2); 207 } 208 int r_tgt = LoadHelper(offset); 209 // NOTE: not a safepoint 210 OpReg(kOpBlx, r_tgt); 211 RegLocation rl_result = GetReturn(false); 212 StoreValue(rl_dest, rl_result); 213} 214 215void MipsMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, 216 bool gt_bias, bool is_double) { 217 UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch"; 218} 219 220void MipsMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) { 221 RegLocation rl_result; 222 rl_src = LoadValue(rl_src, kCoreReg); 223 rl_result = EvalLoc(rl_dest, kCoreReg, true); 224 OpRegRegImm(kOpAdd, rl_result.low_reg, rl_src.low_reg, 0x80000000); 225 StoreValue(rl_dest, rl_result); 226} 227 228void MipsMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) { 229 RegLocation rl_result; 230 rl_src = LoadValueWide(rl_src, kCoreReg); 231 rl_result = EvalLoc(rl_dest, kCoreReg, true); 232 OpRegRegImm(kOpAdd, rl_result.high_reg, rl_src.high_reg, 0x80000000); 233 OpRegCopy(rl_result.low_reg, rl_src.low_reg); 234 StoreValueWide(rl_dest, rl_result); 235} 236 237bool MipsMir2Lir::GenInlinedMinMaxInt(CallInfo* info, bool is_min) { 238 // TODO: need Mips implementation 239 return false; 240} 241 242} // namespace art 243