Home | History | Annotate | Download | only in code
      1 /*
      2  * Copyright (C) 2007 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 package com.android.dexgen.dex.code;
     18 
     19 import com.android.dexgen.rop.code.RegisterSpec;
     20 import com.android.dexgen.rop.code.RegisterSpecList;
     21 import com.android.dexgen.rop.code.SourcePosition;
     22 import com.android.dexgen.rop.type.Type;
     23 import com.android.dexgen.util.AnnotatedOutput;
     24 
     25 /**
     26  * Combination instruction which turns into a variable number of
     27  * {@code move*} instructions to move a set of registers into
     28  * registers starting at {@code 0} sequentially. This is used
     29  * in translating an instruction whose register requirements cannot
     30  * be met using a straightforward choice of a single opcode.
     31  */
     32 public final class HighRegisterPrefix extends VariableSizeInsn {
     33     /** {@code null-ok;} cached instructions, if constructed */
     34     private SimpleInsn[] insns;
     35 
     36     /**
     37      * Constructs an instance. The output address of this instance is initially
     38      * unknown ({@code -1}).
     39      *
     40      * @param position {@code non-null;} source position
     41      * @param registers {@code non-null;} source registers
     42      */
     43     public HighRegisterPrefix(SourcePosition position,
     44                               RegisterSpecList registers) {
     45         super(position, registers);
     46 
     47         if (registers.size() == 0) {
     48             throw new IllegalArgumentException("registers.size() == 0");
     49         }
     50 
     51         insns = null;
     52     }
     53 
     54     /** {@inheritDoc} */
     55     @Override
     56     public int codeSize() {
     57         int result = 0;
     58 
     59         calculateInsnsIfNecessary();
     60 
     61         for (SimpleInsn insn : insns) {
     62             result += insn.codeSize();
     63         }
     64 
     65         return result;
     66     }
     67 
     68     /** {@inheritDoc} */
     69     @Override
     70     public void writeTo(AnnotatedOutput out) {
     71         calculateInsnsIfNecessary();
     72 
     73         for (SimpleInsn insn : insns) {
     74             insn.writeTo(out);
     75         }
     76     }
     77 
     78     /**
     79      * Helper for {@link #codeSize} and {@link #writeTo} which sets up
     80      * {@link #insns} if not already done.
     81      */
     82     private void calculateInsnsIfNecessary() {
     83         if (insns != null) {
     84             return;
     85         }
     86 
     87         RegisterSpecList registers = getRegisters();
     88         int sz = registers.size();
     89 
     90         insns = new SimpleInsn[sz];
     91 
     92         for (int i = 0, outAt = 0; i < sz; i++) {
     93             RegisterSpec src = registers.get(i);
     94             insns[i] = moveInsnFor(src, outAt);
     95             outAt += src.getCategory();
     96         }
     97     }
     98 
     99     /** {@inheritDoc} */
    100     @Override
    101     public DalvInsn withRegisters(RegisterSpecList registers) {
    102         return new HighRegisterPrefix(getPosition(), registers);
    103     }
    104 
    105     /** {@inheritDoc} */
    106     @Override
    107     protected String argString() {
    108         return null;
    109     }
    110 
    111     /** {@inheritDoc} */
    112     @Override
    113     protected String listingString0(boolean noteIndices) {
    114         RegisterSpecList registers = getRegisters();
    115         int sz = registers.size();
    116         StringBuffer sb = new StringBuffer(100);
    117 
    118         for (int i = 0, outAt = 0; i < sz; i++) {
    119             RegisterSpec src = registers.get(i);
    120             SimpleInsn insn = moveInsnFor(src, outAt);
    121 
    122             if (i != 0) {
    123                 sb.append('\n');
    124             }
    125 
    126             sb.append(insn.listingString0(noteIndices));
    127 
    128             outAt += src.getCategory();
    129         }
    130 
    131         return sb.toString();
    132     }
    133 
    134     /**
    135      * Returns the proper move instruction for the given source spec
    136      * and destination index.
    137      *
    138      * @param src {@code non-null;} the source register spec
    139      * @param destIndex {@code >= 0;} the destination register index
    140      * @return {@code non-null;} the appropriate move instruction
    141      */
    142     private static SimpleInsn moveInsnFor(RegisterSpec src, int destIndex) {
    143         return DalvInsn.makeMove(SourcePosition.NO_INFO,
    144                 RegisterSpec.make(destIndex, src.getType()),
    145                 src);
    146     }
    147 }
    148