1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/* 2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project 3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License"); 5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License. 6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at 7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * http://www.apache.org/licenses/LICENSE-2.0 9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software 11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS, 12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and 14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License. 15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.dex.code; 18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.RegisterSpec; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.RegisterSpecList; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.SourcePosition; 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.Type; 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.AnnotatedOutput; 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Combination instruction which turns into a variable number of 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code move*} instructions to move a set of registers into 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * registers starting at {@code 0} sequentially. This is used 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * in translating an instruction whose register requirements cannot 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * be met using a straightforward choice of a single opcode. 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class HighRegisterPrefix extends VariableSizeInsn { 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code null-ok;} cached instructions, if constructed */ 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private SimpleInsn[] insns; 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. The output address of this instance is initially 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * unknown ({@code -1}). 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param position {@code non-null;} source position 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param registers {@code non-null;} source registers 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public HighRegisterPrefix(SourcePosition position, 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList registers) { 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super(position, registers); 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (registers.size() == 0) { 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("registers.size() == 0"); 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul insns = null; 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int codeSize() { 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int result = 0; 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul calculateInsnsIfNecessary(); 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (SimpleInsn insn : insns) { 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result += insn.codeSize(); 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void writeTo(AnnotatedOutput out) { 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul calculateInsnsIfNecessary(); 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (SimpleInsn insn : insns) { 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul insn.writeTo(out); 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper for {@link #codeSize} and {@link #writeTo} which sets up 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link #insns} if not already done. 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void calculateInsnsIfNecessary() { 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (insns != null) { 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return; 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList registers = getRegisters(); 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = registers.size(); 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul insns = new SimpleInsn[sz]; 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0, outAt = 0; i < sz; i++) { 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec src = registers.get(i); 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul insns[i] = moveInsnFor(src, outAt); 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul outAt += src.getCategory(); 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public DalvInsn withRegisters(RegisterSpecList registers) { 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return new HighRegisterPrefix(getPosition(), registers); 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected String argString() { 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected String listingString0(boolean noteIndices) { 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList registers = getRegisters(); 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = registers.size(); 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuffer sb = new StringBuffer(100); 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0, outAt = 0; i < sz; i++) { 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec src = registers.get(i); 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul SimpleInsn insn = moveInsnFor(src, outAt); 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (i != 0) { 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append('\n'); 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(insn.listingString0(noteIndices)); 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul outAt += src.getCategory(); 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns the proper move instruction for the given source spec 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * and destination index. 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param src {@code non-null;} the source register spec 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param destIndex {@code >= 0;} the destination register index 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the appropriate move instruction 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static SimpleInsn moveInsnFor(RegisterSpec src, int destIndex) { 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return DalvInsn.makeMove(SourcePosition.NO_INFO, 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec.make(destIndex, src.getType()), 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul src); 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 148