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 /*
     18  * This file is included by Codegen-armv5te-vfp.c, and implements architecture
     19  * variant-specific code.
     20  */
     21 
     22 /*
     23  * Take the address of a Dalvik register and store it into rDest.
     24  * Clobber any live values associated either with the Dalvik value
     25  * or the target register and lock the target fixed register.
     26  */
     27 static void loadValueAddressDirect(CompilationUnit *cUnit, RegLocation rlSrc,
     28                                    int rDest)
     29 {
     30      rlSrc = rlSrc.wide ? dvmCompilerUpdateLocWide(cUnit, rlSrc) :
     31                           dvmCompilerUpdateLoc(cUnit, rlSrc);
     32      if (rlSrc.location == kLocPhysReg) {
     33          if (rlSrc.wide) {
     34              dvmCompilerFlushRegWide(cUnit, rlSrc.lowReg, rlSrc.highReg);
     35          } else {
     36              dvmCompilerFlushReg(cUnit, rlSrc.lowReg);
     37          }
     38      }
     39      dvmCompilerClobber(cUnit, rDest);
     40      dvmCompilerLockTemp(cUnit, rDest);
     41      opRegRegImm(cUnit, kOpAdd, rDest, r5FP,
     42                  dvmCompilerS2VReg(cUnit, rlSrc.sRegLow) << 2);
     43 }
     44 
     45 static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir)
     46 {
     47     RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
     48     RegLocation rlResult = LOC_C_RETURN_WIDE;
     49     RegLocation rlDest = LOC_DALVIK_RETURN_VAL_WIDE;
     50     loadValueAddressDirect(cUnit, rlSrc, r2);
     51     genDispatchToHandler(cUnit, TEMPLATE_SQRT_DOUBLE_VFP);
     52     storeValueWide(cUnit, rlDest, rlResult);
     53     return false;
     54 }
     55 
     56 /*
     57  * TUNING: On some implementations, it is quicker to pass addresses
     58  * to the handlers rather than load the operands into core registers
     59  * and then move the values to FP regs in the handlers.  Other implementations
     60  * may prefer passing data in registers (and the latter approach would
     61  * yield cleaner register handling - avoiding the requirement that operands
     62  * be flushed to memory prior to the call).
     63  */
     64 static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir,
     65                             RegLocation rlDest, RegLocation rlSrc1,
     66                             RegLocation rlSrc2)
     67 {
     68     TemplateOpcode opcode;
     69 
     70     /*
     71      * Don't attempt to optimize register usage since these opcodes call out to
     72      * the handlers.
     73      */
     74     switch (mir->dalvikInsn.opcode) {
     75         case OP_ADD_FLOAT_2ADDR:
     76         case OP_ADD_FLOAT:
     77             opcode = TEMPLATE_ADD_FLOAT_VFP;
     78             break;
     79         case OP_SUB_FLOAT_2ADDR:
     80         case OP_SUB_FLOAT:
     81             opcode = TEMPLATE_SUB_FLOAT_VFP;
     82             break;
     83         case OP_DIV_FLOAT_2ADDR:
     84         case OP_DIV_FLOAT:
     85             opcode = TEMPLATE_DIV_FLOAT_VFP;
     86             break;
     87         case OP_MUL_FLOAT_2ADDR:
     88         case OP_MUL_FLOAT:
     89             opcode = TEMPLATE_MUL_FLOAT_VFP;
     90             break;
     91         case OP_REM_FLOAT_2ADDR:
     92         case OP_REM_FLOAT:
     93         case OP_NEG_FLOAT: {
     94             return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
     95         }
     96         default:
     97             return true;
     98     }
     99     loadValueAddressDirect(cUnit, rlDest, r0);
    100     loadValueAddressDirect(cUnit, rlSrc1, r1);
    101     loadValueAddressDirect(cUnit, rlSrc2, r2);
    102     genDispatchToHandler(cUnit, opcode);
    103     rlDest = dvmCompilerUpdateLoc(cUnit, rlDest);
    104     if (rlDest.location == kLocPhysReg) {
    105         dvmCompilerClobber(cUnit, rlDest.lowReg);
    106     }
    107     return false;
    108 }
    109 
    110 static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir,
    111                              RegLocation rlDest, RegLocation rlSrc1,
    112                              RegLocation rlSrc2)
    113 {
    114     TemplateOpcode opcode;
    115 
    116     switch (mir->dalvikInsn.opcode) {
    117         case OP_ADD_DOUBLE_2ADDR:
    118         case OP_ADD_DOUBLE:
    119             opcode = TEMPLATE_ADD_DOUBLE_VFP;
    120             break;
    121         case OP_SUB_DOUBLE_2ADDR:
    122         case OP_SUB_DOUBLE:
    123             opcode = TEMPLATE_SUB_DOUBLE_VFP;
    124             break;
    125         case OP_DIV_DOUBLE_2ADDR:
    126         case OP_DIV_DOUBLE:
    127             opcode = TEMPLATE_DIV_DOUBLE_VFP;
    128             break;
    129         case OP_MUL_DOUBLE_2ADDR:
    130         case OP_MUL_DOUBLE:
    131             opcode = TEMPLATE_MUL_DOUBLE_VFP;
    132             break;
    133         case OP_REM_DOUBLE_2ADDR:
    134         case OP_REM_DOUBLE:
    135         case OP_NEG_DOUBLE: {
    136             return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1,
    137                                                rlSrc2);
    138         }
    139         default:
    140             return true;
    141     }
    142     loadValueAddressDirect(cUnit, rlDest, r0);
    143     loadValueAddressDirect(cUnit, rlSrc1, r1);
    144     loadValueAddressDirect(cUnit, rlSrc2, r2);
    145     genDispatchToHandler(cUnit, opcode);
    146     rlDest = dvmCompilerUpdateLocWide(cUnit, rlDest);
    147     if (rlDest.location == kLocPhysReg) {
    148         dvmCompilerClobber(cUnit, rlDest.lowReg);
    149         dvmCompilerClobber(cUnit, rlDest.highReg);
    150     }
    151     return false;
    152 }
    153 
    154 static bool genConversion(CompilationUnit *cUnit, MIR *mir)
    155 {
    156     Opcode opcode = mir->dalvikInsn.opcode;
    157     bool longSrc = false;
    158     bool longDest = false;
    159     RegLocation rlSrc;
    160     RegLocation rlDest;
    161     TemplateOpcode templateOpcode;
    162     switch (opcode) {
    163         case OP_INT_TO_FLOAT:
    164             longSrc = false;
    165             longDest = false;
    166             templateOpcode = TEMPLATE_INT_TO_FLOAT_VFP;
    167             break;
    168         case OP_FLOAT_TO_INT:
    169             longSrc = false;
    170             longDest = false;
    171             templateOpcode = TEMPLATE_FLOAT_TO_INT_VFP;
    172             break;
    173         case OP_DOUBLE_TO_FLOAT:
    174             longSrc = true;
    175             longDest = false;
    176             templateOpcode = TEMPLATE_DOUBLE_TO_FLOAT_VFP;
    177             break;
    178         case OP_FLOAT_TO_DOUBLE:
    179             longSrc = false;
    180             longDest = true;
    181             templateOpcode = TEMPLATE_FLOAT_TO_DOUBLE_VFP;
    182             break;
    183         case OP_INT_TO_DOUBLE:
    184             longSrc = false;
    185             longDest = true;
    186             templateOpcode = TEMPLATE_INT_TO_DOUBLE_VFP;
    187             break;
    188         case OP_DOUBLE_TO_INT:
    189             longSrc = true;
    190             longDest = false;
    191             templateOpcode = TEMPLATE_DOUBLE_TO_INT_VFP;
    192             break;
    193         case OP_LONG_TO_DOUBLE:
    194         case OP_FLOAT_TO_LONG:
    195         case OP_LONG_TO_FLOAT:
    196         case OP_DOUBLE_TO_LONG:
    197             return genConversionPortable(cUnit, mir);
    198         default:
    199             return true;
    200     }
    201 
    202     if (longSrc) {
    203         rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
    204     } else {
    205         rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
    206     }
    207 
    208     if (longDest) {
    209         rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
    210     } else {
    211         rlDest = dvmCompilerGetDest(cUnit, mir, 0);
    212     }
    213     loadValueAddressDirect(cUnit, rlDest, r0);
    214     loadValueAddressDirect(cUnit, rlSrc, r1);
    215     genDispatchToHandler(cUnit, templateOpcode);
    216     if (rlDest.wide) {
    217         rlDest = dvmCompilerUpdateLocWide(cUnit, rlDest);
    218         dvmCompilerClobber(cUnit, rlDest.highReg);
    219     } else {
    220         rlDest = dvmCompilerUpdateLoc(cUnit, rlDest);
    221     }
    222     dvmCompilerClobber(cUnit, rlDest.lowReg);
    223     return false;
    224 }
    225 
    226 static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
    227                      RegLocation rlSrc1, RegLocation rlSrc2)
    228 {
    229     TemplateOpcode templateOpcode;
    230     RegLocation rlResult = dvmCompilerGetReturn(cUnit);
    231     bool wide = true;
    232 
    233     switch(mir->dalvikInsn.opcode) {
    234         case OP_CMPL_FLOAT:
    235             templateOpcode = TEMPLATE_CMPL_FLOAT_VFP;
    236             wide = false;
    237             break;
    238         case OP_CMPG_FLOAT:
    239             templateOpcode = TEMPLATE_CMPG_FLOAT_VFP;
    240             wide = false;
    241             break;
    242         case OP_CMPL_DOUBLE:
    243             templateOpcode = TEMPLATE_CMPL_DOUBLE_VFP;
    244             break;
    245         case OP_CMPG_DOUBLE:
    246             templateOpcode = TEMPLATE_CMPG_DOUBLE_VFP;
    247             break;
    248         default:
    249             return true;
    250     }
    251     loadValueAddressDirect(cUnit, rlSrc1, r0);
    252     loadValueAddressDirect(cUnit, rlSrc2, r1);
    253     genDispatchToHandler(cUnit, templateOpcode);
    254     storeValue(cUnit, rlDest, rlResult);
    255     return false;
    256 }
    257