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.form; 18 19 import com.android.dx.dex.code.CstInsn; 20 import com.android.dx.dex.code.DalvInsn; 21 import com.android.dx.dex.code.InsnFormat; 22 import com.android.dx.rop.code.RegisterSpec; 23 import com.android.dx.rop.code.RegisterSpecList; 24 import com.android.dx.rop.cst.Constant; 25 import com.android.dx.rop.cst.CstMethodRef; 26 import com.android.dx.rop.cst.CstType; 27 import com.android.dx.util.AnnotatedOutput; 28 29 /** 30 * Instruction format {@code 3rc}. See the instruction format spec 31 * for details. 32 */ 33 public final class Form3rc extends InsnFormat { 34 /** {@code non-null;} unique instance of this class */ 35 public static final InsnFormat THE_ONE = new Form3rc(); 36 37 /** 38 * Constructs an instance. This class is not publicly 39 * instantiable. Use {@link #THE_ONE}. 40 */ 41 private Form3rc() { 42 // This space intentionally left blank. 43 } 44 45 /** {@inheritDoc} */ 46 @Override 47 public String insnArgString(DalvInsn insn) { 48 RegisterSpecList regs = insn.getRegisters(); 49 int size = regs.size(); 50 StringBuilder sb = new StringBuilder(30); 51 52 sb.append("{"); 53 54 switch (size) { 55 case 0: { 56 // Nothing to do. 57 break; 58 } 59 case 1: { 60 sb.append(regs.get(0).regString()); 61 break; 62 } 63 default: { 64 RegisterSpec lastReg = regs.get(size - 1); 65 if (lastReg.getCategory() == 2) { 66 /* 67 * Add one to properly represent a list-final 68 * category-2 register. 69 */ 70 lastReg = lastReg.withOffset(1); 71 } 72 73 sb.append(regs.get(0).regString()); 74 sb.append(".."); 75 sb.append(lastReg.regString()); 76 } 77 } 78 79 sb.append("}, "); 80 sb.append(cstString(insn)); 81 82 return sb.toString(); 83 } 84 85 /** {@inheritDoc} */ 86 @Override 87 public String insnCommentString(DalvInsn insn, boolean noteIndices) { 88 if (noteIndices) { 89 return cstComment(insn); 90 } else { 91 return ""; 92 } 93 } 94 95 /** {@inheritDoc} */ 96 @Override 97 public int codeSize() { 98 return 3; 99 } 100 101 /** {@inheritDoc} */ 102 @Override 103 public boolean isCompatible(DalvInsn insn) { 104 if (!(insn instanceof CstInsn)) { 105 return false; 106 } 107 108 CstInsn ci = (CstInsn) insn; 109 int cpi = ci.getIndex(); 110 111 if (! unsignedFitsInShort(cpi)) { 112 return false; 113 } 114 115 Constant cst = ci.getConstant(); 116 if (!((cst instanceof CstMethodRef) || 117 (cst instanceof CstType))) { 118 return false; 119 } 120 121 RegisterSpecList regs = ci.getRegisters(); 122 int sz = regs.size(); 123 124 if (sz == 0) { 125 return true; 126 } 127 128 int first = regs.get(0).getReg(); 129 int next = first; 130 131 if (!unsignedFitsInShort(first)) { 132 return false; 133 } 134 135 for (int i = 0; i < sz; i++) { 136 RegisterSpec one = regs.get(i); 137 if (one.getReg() != next) { 138 return false; 139 } 140 next += one.getCategory(); 141 } 142 143 return unsignedFitsInByte(next - first); 144 } 145 146 /** {@inheritDoc} */ 147 @Override 148 public InsnFormat nextUp() { 149 return null; 150 } 151 152 /** {@inheritDoc} */ 153 @Override 154 public void writeTo(AnnotatedOutput out, DalvInsn insn) { 155 RegisterSpecList regs = insn.getRegisters(); 156 int sz = regs.size(); 157 int cpi = ((CstInsn) insn).getIndex(); 158 int firstReg; 159 int count; 160 161 if (sz == 0) { 162 firstReg = 0; 163 count = 0; 164 } else { 165 int lastReg = regs.get(sz - 1).getNextReg(); 166 firstReg = regs.get(0).getReg(); 167 count = lastReg - firstReg; 168 } 169 170 write(out, 171 opcodeUnit(insn, count), 172 (short) cpi, 173 (short) firstReg); 174 } 175 } 176