1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/* 2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2007 The Android Open Source Project 3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License. 6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at 7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and 14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License. 15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.dex.code; 18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.RegisterSpec; 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.RegisterSpecList; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.SourcePosition; 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.Type; 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.AnnotatedOutput; 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Combination instruction which turns into a variable number of 27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code move*} instructions to move a set of registers into 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * registers starting at {@code 0} sequentially. This is used 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * in translating an instruction whose register requirements cannot 30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * be met using a straightforward choice of a single opcode. 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic final class HighRegisterPrefix extends VariableSizeInsn { 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code null-ok;} cached instructions, if constructed */ 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private SimpleInsn[] insns; 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Constructs an instance. The output address of this instance is initially 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * unknown ({@code -1}). 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param position {@code non-null;} source position 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param registers {@code non-null;} source registers 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public HighRegisterPrefix(SourcePosition position, 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpecList registers) { 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson super(position, registers); 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (registers.size() == 0) { 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IllegalArgumentException("registers.size() == 0"); 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson insns = null; 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int codeSize() { 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int result = 0; 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson calculateInsnsIfNecessary(); 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (SimpleInsn insn : insns) { 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson result += insn.codeSize(); 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return result; 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void writeTo(AnnotatedOutput out) { 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson calculateInsnsIfNecessary(); 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (SimpleInsn insn : insns) { 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson insn.writeTo(out); 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Helper for {@link #codeSize} and {@link #writeTo} which sets up 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@link #insns} if not already done. 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private void calculateInsnsIfNecessary() { 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (insns != null) { 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return; 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpecList registers = getRegisters(); 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int sz = registers.size(); 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson insns = new SimpleInsn[sz]; 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0, outAt = 0; i < sz; i++) { 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec src = registers.get(i); 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson insns[i] = moveInsnFor(src, outAt); 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson outAt += src.getCategory(); 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public DalvInsn withRegisters(RegisterSpecList registers) { 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return new HighRegisterPrefix(getPosition(), registers); 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protected String argString() { 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return null; 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protected String listingString0(boolean noteIndices) { 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpecList registers = getRegisters(); 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int sz = registers.size(); 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson StringBuffer sb = new StringBuffer(100); 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0, outAt = 0; i < sz; i++) { 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec src = registers.get(i); 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson SimpleInsn insn = moveInsnFor(src, outAt); 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (i != 0) { 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append('\n'); 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(insn.listingString0(noteIndices)); 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson outAt += src.getCategory(); 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return sb.toString(); 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns the proper move instruction for the given source spec 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * and destination index. 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param src {@code non-null;} the source register spec 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param destIndex {@code >= 0;} the destination register index 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the appropriate move instruction 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static SimpleInsn moveInsnFor(RegisterSpec src, int destIndex) { 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return DalvInsn.makeMove(SourcePosition.NO_INFO, 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec.make(destIndex, src.getType()), 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson src); 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 148