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