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.form; 18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.dex.code.CstInsn; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.dex.code.DalvInsn; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.dex.code.InsnFormat; 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.RegisterSpec; 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.RegisterSpecList; 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.Constant; 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstMethodRef; 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstType; 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.AnnotatedOutput; 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Instruction format {@code 3rc}. See the instruction format spec 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * for details. 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class Form3rc extends InsnFormat { 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} unique instance of this class */ 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static final InsnFormat THE_ONE = new Form3rc(); 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. This class is not publicly 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instantiable. Use {@link #THE_ONE}. 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private Form3rc() { 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // This space intentionally left blank. 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public String insnArgString(DalvInsn insn) { 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList regs = insn.getRegisters(); 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int size = regs.size(); 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuilder sb = new StringBuilder(30); 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append("{"); 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul switch (size) { 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case 0: { 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Nothing to do. 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case 1: { 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(regs.get(0).regString()); 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul default: { 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec lastReg = regs.get(size - 1); 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (lastReg.getCategory() == 2) { 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Add one to properly represent a list-final 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * category-2 register. 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul lastReg = lastReg.withOffset(1); 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(regs.get(0).regString()); 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(".."); 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(lastReg.regString()); 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append("}, "); 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(cstString(insn)); 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public String insnCommentString(DalvInsn insn, boolean noteIndices) { 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (noteIndices) { 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return cstComment(insn); 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return ""; 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int codeSize() { 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return 3; 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean isCompatible(DalvInsn insn) { 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!(insn instanceof CstInsn)) { 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul CstInsn ci = (CstInsn) insn; 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int cpi = ci.getIndex(); 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (! unsignedFitsInShort(cpi)) { 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Constant cst = ci.getConstant(); 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!((cst instanceof CstMethodRef) || 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul (cst instanceof CstType))) { 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList regs = ci.getRegisters(); 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = regs.size(); 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (sz == 0) { 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return true; 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int first = regs.get(0).getReg(); 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int next = first; 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!unsignedFitsInShort(first)) { 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec one = regs.get(i); 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (one.getReg() != next) { 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul next += one.getCategory(); 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return unsignedFitsInByte(next - first); 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public InsnFormat nextUp() { 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void writeTo(AnnotatedOutput out, DalvInsn insn) { 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList regs = insn.getRegisters(); 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = regs.size(); 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int cpi = ((CstInsn) insn).getIndex(); 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int firstReg; 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int count; 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (sz == 0) { 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul firstReg = 0; 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul count = 0; 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int lastReg = regs.get(sz - 1).getNextReg(); 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul firstReg = regs.get(0).getReg(); 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul count = lastReg - firstReg; 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul write(out, 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul opcodeUnit(insn, count), 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul (short) cpi, 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul (short) firstReg); 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 176