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