Home | History | Annotate | Download | only in FP
      1 /*
      2  * Copyright (C) 2009 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 static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir,
     18                             RegLocation rlDest, RegLocation rlSrc1,
     19                             RegLocation rlSrc2)
     20 {
     21     int op = kThumbBkpt;
     22     RegLocation rlResult;
     23 
     24     /*
     25      * Don't attempt to optimize register usage since these opcodes call out to
     26      * the handlers.
     27      */
     28     switch (mir->dalvikInsn.opcode) {
     29         case OP_ADD_FLOAT_2ADDR:
     30         case OP_ADD_FLOAT:
     31             op = kThumb2Vadds;
     32             break;
     33         case OP_SUB_FLOAT_2ADDR:
     34         case OP_SUB_FLOAT:
     35             op = kThumb2Vsubs;
     36             break;
     37         case OP_DIV_FLOAT_2ADDR:
     38         case OP_DIV_FLOAT:
     39             op = kThumb2Vdivs;
     40             break;
     41         case OP_MUL_FLOAT_2ADDR:
     42         case OP_MUL_FLOAT:
     43             op = kThumb2Vmuls;
     44             break;
     45         case OP_REM_FLOAT_2ADDR:
     46         case OP_REM_FLOAT:
     47         case OP_NEG_FLOAT: {
     48             return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1,
     49                                               rlSrc2);
     50         }
     51         default:
     52             return true;
     53     }
     54     rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
     55     rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
     56     rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
     57     newLIR3(cUnit, (ArmOpcode)op, rlResult.lowReg, rlSrc1.lowReg,
     58             rlSrc2.lowReg);
     59     storeValue(cUnit, rlDest, rlResult);
     60     return false;
     61 }
     62 
     63 static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir,
     64                              RegLocation rlDest, RegLocation rlSrc1,
     65                              RegLocation rlSrc2)
     66 {
     67     int op = kThumbBkpt;
     68     RegLocation rlResult;
     69 
     70     switch (mir->dalvikInsn.opcode) {
     71         case OP_ADD_DOUBLE_2ADDR:
     72         case OP_ADD_DOUBLE:
     73             op = kThumb2Vaddd;
     74             break;
     75         case OP_SUB_DOUBLE_2ADDR:
     76         case OP_SUB_DOUBLE:
     77             op = kThumb2Vsubd;
     78             break;
     79         case OP_DIV_DOUBLE_2ADDR:
     80         case OP_DIV_DOUBLE:
     81             op = kThumb2Vdivd;
     82             break;
     83         case OP_MUL_DOUBLE_2ADDR:
     84         case OP_MUL_DOUBLE:
     85             op = kThumb2Vmuld;
     86             break;
     87         case OP_REM_DOUBLE_2ADDR:
     88         case OP_REM_DOUBLE:
     89         case OP_NEG_DOUBLE: {
     90             return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1,
     91                                                rlSrc2);
     92         }
     93         default:
     94             return true;
     95     }
     96 
     97     rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
     98     assert(rlSrc1.wide);
     99     rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
    100     assert(rlSrc2.wide);
    101     rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
    102     assert(rlDest.wide);
    103     assert(rlResult.wide);
    104     newLIR3(cUnit, (ArmOpcode)op, S2D(rlResult.lowReg, rlResult.highReg),
    105             S2D(rlSrc1.lowReg, rlSrc1.highReg),
    106             S2D(rlSrc2.lowReg, rlSrc2.highReg));
    107     storeValueWide(cUnit, rlDest, rlResult);
    108     return false;
    109 }
    110 
    111 static bool genConversion(CompilationUnit *cUnit, MIR *mir)
    112 {
    113     Opcode opcode = mir->dalvikInsn.opcode;
    114     int op = kThumbBkpt;
    115     bool longSrc = false;
    116     bool longDest = false;
    117     int srcReg;
    118     RegLocation rlSrc;
    119     RegLocation rlDest;
    120     RegLocation rlResult;
    121 
    122     switch (opcode) {
    123         case OP_INT_TO_FLOAT:
    124             longSrc = false;
    125             longDest = false;
    126             op = kThumb2VcvtIF;
    127             break;
    128         case OP_FLOAT_TO_INT:
    129             longSrc = false;
    130             longDest = false;
    131             op = kThumb2VcvtFI;
    132             break;
    133         case OP_DOUBLE_TO_FLOAT:
    134             longSrc = true;
    135             longDest = false;
    136             op = kThumb2VcvtDF;
    137             break;
    138         case OP_FLOAT_TO_DOUBLE:
    139             longSrc = false;
    140             longDest = true;
    141             op = kThumb2VcvtFd;
    142             break;
    143         case OP_INT_TO_DOUBLE:
    144             longSrc = false;
    145             longDest = true;
    146             op = kThumb2VcvtID;
    147             break;
    148         case OP_DOUBLE_TO_INT:
    149             longSrc = true;
    150             longDest = false;
    151             op = kThumb2VcvtDI;
    152             break;
    153         case OP_LONG_TO_DOUBLE:
    154         case OP_FLOAT_TO_LONG:
    155         case OP_LONG_TO_FLOAT:
    156         case OP_DOUBLE_TO_LONG:
    157             return genConversionPortable(cUnit, mir);
    158         default:
    159             return true;
    160     }
    161     if (longSrc) {
    162         rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
    163         rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
    164         srcReg = S2D(rlSrc.lowReg, rlSrc.highReg);
    165     } else {
    166         rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
    167         rlSrc = loadValue(cUnit, rlSrc, kFPReg);
    168         srcReg = rlSrc.lowReg;
    169     }
    170     if (longDest) {
    171         rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
    172         rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
    173         newLIR2(cUnit, (ArmOpcode)op, S2D(rlResult.lowReg, rlResult.highReg),
    174                 srcReg);
    175         storeValueWide(cUnit, rlDest, rlResult);
    176     } else {
    177         rlDest = dvmCompilerGetDest(cUnit, mir, 0);
    178         rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
    179         newLIR2(cUnit, (ArmOpcode)op, rlResult.lowReg, srcReg);
    180         storeValue(cUnit, rlDest, rlResult);
    181     }
    182     return false;
    183 }
    184 
    185 static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir)
    186 {
    187     ArmLIR *branch;
    188     RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
    189     RegLocation rlDest = inlinedTargetWide(cUnit, mir, true);
    190     rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
    191     RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
    192     newLIR2(cUnit, kThumb2Vsqrtd, S2D(rlResult.lowReg, rlResult.highReg),
    193             S2D(rlSrc.lowReg, rlSrc.highReg));
    194     newLIR2(cUnit, kThumb2Vcmpd, S2D(rlResult.lowReg, rlResult.highReg),
    195             S2D(rlResult.lowReg, rlResult.highReg));
    196     newLIR0(cUnit, kThumb2Fmstat);
    197     branch = newLIR2(cUnit, kThumbBCond, 0, kArmCondEq);
    198     dvmCompilerClobberCallRegs(cUnit);
    199     LOAD_FUNC_ADDR(cUnit, r2, (int) (double (*)(double)) sqrt);
    200     newLIR3(cUnit, kThumb2Fmrrd, r0, r1, S2D(rlSrc.lowReg, rlSrc.highReg));
    201     newLIR1(cUnit, kThumbBlxR, r2);
    202     newLIR3(cUnit, kThumb2Fmdrr, S2D(rlResult.lowReg, rlResult.highReg),
    203             r0, r1);
    204     ArmLIR *label = newLIR0(cUnit, kArmPseudoTargetLabel);
    205     label->defMask = ENCODE_ALL;
    206     branch->generic.target = (LIR *)label;
    207     storeValueWide(cUnit, rlDest, rlResult);
    208     return false;
    209 }
    210 
    211 static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
    212                      RegLocation rlSrc1, RegLocation rlSrc2)
    213 {
    214     bool isDouble;
    215     int defaultResult;
    216     RegLocation rlResult;
    217 
    218     switch(mir->dalvikInsn.opcode) {
    219         case OP_CMPL_FLOAT:
    220             isDouble = false;
    221             defaultResult = -1;
    222             break;
    223         case OP_CMPG_FLOAT:
    224             isDouble = false;
    225             defaultResult = 1;
    226             break;
    227         case OP_CMPL_DOUBLE:
    228             isDouble = true;
    229             defaultResult = -1;
    230             break;
    231         case OP_CMPG_DOUBLE:
    232             isDouble = true;
    233             defaultResult = 1;
    234             break;
    235         default:
    236             return true;
    237     }
    238     if (isDouble) {
    239         rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
    240         rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
    241         dvmCompilerClobberSReg(cUnit, rlDest.sRegLow);
    242         rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
    243         loadConstant(cUnit, rlResult.lowReg, defaultResult);
    244         newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
    245                 S2D(rlSrc2.lowReg, rlSrc2.highReg));
    246     } else {
    247         rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
    248         rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
    249         dvmCompilerClobberSReg(cUnit, rlDest.sRegLow);
    250         rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
    251         loadConstant(cUnit, rlResult.lowReg, defaultResult);
    252         newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
    253     }
    254     assert(!FPREG(rlResult.lowReg));
    255     newLIR0(cUnit, kThumb2Fmstat);
    256 
    257     genIT(cUnit, (defaultResult == -1) ? kArmCondGt : kArmCondMi, "");
    258     newLIR2(cUnit, kThumb2MovImmShift, rlResult.lowReg,
    259             modifiedImmediate(-defaultResult)); // Must not alter ccodes
    260     genBarrier(cUnit);
    261 
    262     genIT(cUnit, kArmCondEq, "");
    263     loadConstant(cUnit, rlResult.lowReg, 0);
    264     genBarrier(cUnit);
    265 
    266     storeValue(cUnit, rlDest, rlResult);
    267     return false;
    268 }
    269