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.RegisterSpecList; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.Constant; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstInteger; 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstKnownNull; 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstLiteral64; 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstLiteralBits; 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.AnnotatedOutput; 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.Hex; 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Base class for all instruction format handlers. Instruction format 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * handlers know how to translate {@link DalvInsn} instances into 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * streams of code words, as well as human-oriented listing strings 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * representing such translations. 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic abstract class InsnFormat { 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns the string form, suitable for inclusion in a listing 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * dump, of the given instruction. The instruction must be of this 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance's format for proper operation. 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param noteIndices whether to include an explicit notation of 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * constant pool indices 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the string form 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final String listingString(DalvInsn insn, boolean noteIndices) { 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String op = insn.getOpcode().getName(); 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String arg = insnArgString(insn); 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String comment = insnCommentString(insn, noteIndices); 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuilder sb = new StringBuilder(100); 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(op); 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (arg.length() != 0) { 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(' '); 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(arg); 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (comment.length() != 0) { 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(" // "); 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(comment); 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns the string form of the arguments to the given instruction. 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * The instruction must be of this instance's format. If the instruction 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * has no arguments, then the result should be {@code ""}, not 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null}. 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>Subclasses must override this method.</p> 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the string form 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public abstract String insnArgString(DalvInsn insn); 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns the associated comment for the given instruction, if any. 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * The instruction must be of this instance's format. If the instruction 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * has no comment, then the result should be {@code ""}, not 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null}. 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>Subclasses must override this method.</p> 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param noteIndices whether to include an explicit notation of 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * constant pool indices 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the string form 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public abstract String insnCommentString(DalvInsn insn, 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul boolean noteIndices); 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the code size of instructions that use this format. The 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * size is a number of 16-bit code units, not bytes. This should 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * throw an exception if this format is of variable size. 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the instruction length in 16-bit code units 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public abstract int codeSize(); 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns whether or not the given instruction's arguments will 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * fit in this instance's format. This includes such things as 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * counting register arguments, checking register ranges, and 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * making sure that additional arguments are of appropriate types 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * and are in-range. If this format has a branch target but the 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instruction's branch offset is unknown, this method will simply 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * not check the offset. 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>Subclasses must override this method.</p> 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction to check 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff the instruction's arguments are 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * appropriate for this instance, or {@code false} if not 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public abstract boolean isCompatible(DalvInsn insn); 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns whether or not the given instruction's branch offset will 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * fit in this instance's format. This always returns {@code false} 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * for formats that don't include a branch offset. 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>The default implementation of this method always returns 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code false}. Subclasses must override this method if they 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * include branch offsets.</p> 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction to check 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff the instruction's branch offset is 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * appropriate for this instance, or {@code false} if not 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean branchFits(TargetInsn insn) { 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns the next instruction format to try to match an instruction 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * with, presuming that this instance isn't compatible, if any. 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>Subclasses must override this method.</p> 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} the next format to try, or {@code null} if 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * there are no suitable alternatives 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public abstract InsnFormat nextUp(); 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Writes the code units for the given instruction to the given 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * output destination. The instruction must be of this instance's format. 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>Subclasses must override this method.</p> 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} the output destination to write to 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction to write 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public abstract void writeTo(AnnotatedOutput out, DalvInsn insn); 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to return a register list string. 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param list {@code non-null;} the list of registers 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the string form 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static String regListString(RegisterSpecList list) { 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = list.size(); 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuffer sb = new StringBuffer(sz * 5 + 2); 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append('{'); 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (i != 0) { 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(", "); 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(list.get(i).regString()); 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append('}'); 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to return a literal bits argument string. 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param value the value 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the string form 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static String literalBitsString(CstLiteralBits value) { 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuffer sb = new StringBuffer(100); 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append('#'); 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (value instanceof CstKnownNull) { 196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append("null"); 197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(value.typeName()); 199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(' '); 200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(value.toHuman()); 201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to return a literal bits comment string. 208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param value the value 210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param width the width of the constant, in bits (used for displaying 211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the uninterpreted bits; one of: {@code 4 8 16 32 64} 212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the comment 213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static String literalBitsComment(CstLiteralBits value, 215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int width) { 216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuffer sb = new StringBuffer(20); 217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append("#"); 219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul long bits; 221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (value instanceof CstLiteral64) { 223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul bits = ((CstLiteral64) value).getLongBits(); 224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul bits = value.getIntBits(); 226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul switch (width) { 229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case 4: sb.append(Hex.uNibble((int) bits)); break; 230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case 8: sb.append(Hex.u1((int) bits)); break; 231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case 16: sb.append(Hex.u2((int) bits)); break; 232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case 32: sb.append(Hex.u4((int) bits)); break; 233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case 64: sb.append(Hex.u8(bits)); break; 234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul default: { 235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("shouldn't happen"); 236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to return a branch address string. 244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction in question 246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the string form of the instruction's branch target 247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static String branchString(DalvInsn insn) { 249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul TargetInsn ti = (TargetInsn) insn; 250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int address = ti.getTargetAddress(); 251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (address == (char) address) ? Hex.u2(address) : Hex.u4(address); 253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to return the comment for a branch. 257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction in question 259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the comment 260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static String branchComment(DalvInsn insn) { 262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul TargetInsn ti = (TargetInsn) insn; 263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int offset = ti.getTargetOffset(); 264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (offset == (short) offset) ? Hex.s2(offset) : Hex.s4(offset); 266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to return a constant string. 270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} a constant-bearing instruction 272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the string form of the contained constant 273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static String cstString(DalvInsn insn) { 275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul CstInsn ci = (CstInsn) insn; 276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Constant cst = ci.getConstant(); 277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return cst.toHuman(); 279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to return an instruction comment for a constant. 283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} a constant-bearing instruction 285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} comment string representing the constant 286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static String cstComment(DalvInsn insn) { 288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul CstInsn ci = (CstInsn) insn; 289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (! ci.hasIndex()) { 291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return ""; 292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuilder sb = new StringBuilder(20); 295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int index = ci.getIndex(); 296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(ci.getConstant().typeName()); 298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append('@'); 299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (index < 65536) { 301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(Hex.u2(index)); 302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(Hex.u4(index)); 304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to determine if a signed int value fits in a nibble. 311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param value the value in question 313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff it's in the range -8..+7 314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static boolean signedFitsInNibble(int value) { 316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (value >= -8) && (value <= 7); 317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to determine if an unsigned int value fits in a nibble. 321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param value the value in question 323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff it's in the range 0..0xf 324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static boolean unsignedFitsInNibble(int value) { 326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return value == (value & 0xf); 327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to determine if a signed int value fits in a byte. 331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param value the value in question 333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff it's in the range -0x80..+0x7f 334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static boolean signedFitsInByte(int value) { 336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (byte) value == value; 337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to determine if an unsigned int value fits in a byte. 341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param value the value in question 343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff it's in the range 0..0xff 344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static boolean unsignedFitsInByte(int value) { 346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return value == (value & 0xff); 347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to determine if a signed int value fits in a short. 351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param value the value in question 353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff it's in the range -0x8000..+0x7fff 354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static boolean signedFitsInShort(int value) { 356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (short) value == value; 357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to determine if an unsigned int value fits in a short. 361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param value the value in question 363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff it's in the range 0..0xffff 364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static boolean unsignedFitsInShort(int value) { 366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return value == (value & 0xffff); 367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to determine if a signed int value fits in three bytes. 371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param value the value in question 373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff it's in the range -0x800000..+0x7fffff 374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static boolean signedFitsIn3Bytes(int value) { 376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return value == ((value << 8) >> 8); 377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to extract the callout-argument index from an 381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * appropriate instruction. 382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction 384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the callout argument index 385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 386917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static int argIndex(DalvInsn insn) { 387917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int arg = ((CstInteger) ((CstInsn) insn).getConstant()).getValue(); 388917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 389917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (arg < 0) { 390917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("bogus insn"); 391917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 392917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 393917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return arg; 394917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 395917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 396917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 397917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to combine an opcode and a second byte of data into 398917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the appropriate form for emitting into a code buffer. 399917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 400917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction containing the opcode 401917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param arg {@code 0..255;} arbitrary other byte value 402917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return combined value 403917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 404917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static short opcodeUnit(DalvInsn insn, int arg) { 405917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((arg & 0xff) != arg) { 406917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("arg out of range 0..255"); 407917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 408917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 409917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int opcode = insn.getOpcode().getOpcode(); 410917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 411917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((opcode & 0xff) != opcode) { 412917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("opcode out of range 0..255"); 413917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 414917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 415917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (short) (opcode | (arg << 8)); 416917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 417917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 418917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 419917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to combine two bytes into a code unit. 420917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 421917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param low {@code 0..255;} low byte 422917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param high {@code 0..255;} high byte 423917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return combined value 424917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 425917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static short codeUnit(int low, int high) { 426917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((low & 0xff) != low) { 427917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("low out of range 0..255"); 428917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 429917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 430917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((high & 0xff) != high) { 431917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("high out of range 0..255"); 432917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 433917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 434917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (short) (low | (high << 8)); 435917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 436917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 437917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 438917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to combine four nibbles into a code unit. 439917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 440917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param n0 {@code 0..15;} low nibble 441917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param n1 {@code 0..15;} medium-low nibble 442917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param n2 {@code 0..15;} medium-high nibble 443917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param n3 {@code 0..15;} high nibble 444917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return combined value 445917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 446917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static short codeUnit(int n0, int n1, int n2, int n3) { 447917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((n0 & 0xf) != n0) { 448917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("n0 out of range 0..15"); 449917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 450917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 451917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((n1 & 0xf) != n1) { 452917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("n1 out of range 0..15"); 453917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 454917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 455917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((n2 & 0xf) != n2) { 456917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("n2 out of range 0..15"); 457917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 458917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 459917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((n3 & 0xf) != n3) { 460917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("n3 out of range 0..15"); 461917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 462917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 463917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (short) (n0 | (n1 << 4) | (n2 << 8) | (n3 << 12)); 464917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 465917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 466917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 467917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper method to combine two nibbles into a byte. 468917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 469917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param low {@code 0..15;} low nibble 470917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param high {@code 0..15;} high nibble 471917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code 0..255;} combined value 472917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 473917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static int makeByte(int low, int high) { 474917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((low & 0xf) != low) { 475917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("low out of range 0..15"); 476917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 477917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 478917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((high & 0xf) != high) { 479917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("high out of range 0..15"); 480917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 481917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 482917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return low | (high << 4); 483917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 484917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 485917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 486917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Writes one code unit to the given output destination. 487917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 488917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} where to write to 489917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c0 code unit to write 490917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 491917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static void write(AnnotatedOutput out, short c0) { 492917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c0); 493917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 494917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 495917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 496917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Writes two code units to the given output destination. 497917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 498917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} where to write to 499917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c0 code unit to write 500917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c1 code unit to write 501917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 502917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static void write(AnnotatedOutput out, short c0, short c1) { 503917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c0); 504917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c1); 505917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 506917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 507917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 508917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Writes three code units to the given output destination. 509917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 510917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} where to write to 511917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c0 code unit to write 512917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c1 code unit to write 513917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c2 code unit to write 514917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 515917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static void write(AnnotatedOutput out, short c0, short c1, 516917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul short c2) { 517917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c0); 518917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c1); 519917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c2); 520917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 521917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 522917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 523917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Writes four code units to the given output destination. 524917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 525917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} where to write to 526917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c0 code unit to write 527917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c1 code unit to write 528917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c2 code unit to write 529917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c3 code unit to write 530917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 531917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static void write(AnnotatedOutput out, short c0, short c1, 532917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul short c2, short c3) { 533917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c0); 534917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c1); 535917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c2); 536917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c3); 537917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 538917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 539917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 540917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Writes five code units to the given output destination. 541917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 542917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} where to write to 543917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c0 code unit to write 544917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c1 code unit to write 545917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c2 code unit to write 546917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c3 code unit to write 547917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c4 code unit to write 548917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 549917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static void write(AnnotatedOutput out, short c0, short c1, 550917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul short c2, short c3, short c4) { 551917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c0); 552917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c1); 553917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c2); 554917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c3); 555917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c4); 556917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 557917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 558917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 559917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Writes six code units to the given output destination. 560917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 561917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} where to write to 562917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c0 code unit to write 563917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c1 code unit to write 564917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c2 code unit to write 565917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c3 code unit to write 566917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c4 code unit to write 567917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param c5 code unit to write 568917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 569917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected static void write(AnnotatedOutput out, short c0, short c1, 570917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul short c2, short c3, short c4, short c5) { 571917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c0); 572917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c1); 573917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c2); 574917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c3); 575917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c4); 576917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeShort(c5); 577917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 578917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 579