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 */ HighRegisterPrefix(SourcePosition position, RegisterSpecList registers)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 codeSize()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 writeTo(AnnotatedOutput out)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 */ calculateInsnsIfNecessary()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 withRegisters(RegisterSpecList registers)101 public DalvInsn withRegisters(RegisterSpecList registers) { 102 return new HighRegisterPrefix(getPosition(), registers); 103 } 104 105 /** {@inheritDoc} */ 106 @Override argString()107 protected String argString() { 108 return null; 109 } 110 111 /** {@inheritDoc} */ 112 @Override listingString0(boolean noteIndices)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 */ moveInsnFor(RegisterSpec src, int destIndex)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