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