1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.dex.code;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.RegisterSpecList;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.Constant;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstInteger;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstKnownNull;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstLiteral64;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstLiteralBits;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.AnnotatedOutput;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Base class for all instruction format handlers. Instruction format
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * handlers know how to translate {@link DalvInsn} instances into
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * streams of code words, as well as human-oriented listing strings
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * representing such translations.
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic abstract class InsnFormat {
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the string form, suitable for inclusion in a listing
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * dump, of the given instruction. The instruction must be of this
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instance's format for proper operation.
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
4099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param insn {@code non-null;} the instruction
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param noteIndices whether to include an explicit notation of
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constant pool indices
4399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the string form
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final String listingString(DalvInsn insn, boolean noteIndices) {
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String op = insn.getOpcode().getName();
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String arg = insnArgString(insn);
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String comment = insnCommentString(insn, noteIndices);
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuilder sb = new StringBuilder(100);
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(op);
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (arg.length() != 0) {
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(' ');
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(arg);
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (comment.length() != 0) {
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(" // ");
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(comment);
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sb.toString();
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the string form of the arguments to the given instruction.
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The instruction must be of this instance's format. If the instruction
6999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * has no arguments, then the result should be {@code ""}, not
7099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code null}.
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>Subclasses must override this method.</p>
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
7499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param insn {@code non-null;} the instruction
7599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the string form
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public abstract String insnArgString(DalvInsn insn);
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the associated comment for the given instruction, if any.
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The instruction must be of this instance's format. If the instruction
8299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * has no comment, then the result should be {@code ""}, not
8399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code null}.
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>Subclasses must override this method.</p>
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
8799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param insn {@code non-null;} the instruction
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param noteIndices whether to include an explicit notation of
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constant pool indices
9099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the string form
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public abstract String insnCommentString(DalvInsn insn,
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean noteIndices);
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the code size of instructions that use this format. The
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * size is a number of 16-bit code units, not bytes. This should
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * throw an exception if this format is of variable size.
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
10099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= 0;} the instruction length in 16-bit code units
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public abstract int codeSize();
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns whether or not the given instruction's arguments will
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * fit in this instance's format. This includes such things as
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * counting register arguments, checking register ranges, and
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * making sure that additional arguments are of appropriate types
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and are in-range. If this format has a branch target but the
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instruction's branch offset is unknown, this method will simply
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * not check the offset.
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>Subclasses must override this method.</p>
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
11599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param insn {@code non-null;} the instruction to check
11699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code true} iff the instruction's arguments are
11799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * appropriate for this instance, or {@code false} if not
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public abstract boolean isCompatible(DalvInsn insn);
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns whether or not the given instruction's branch offset will
12399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * fit in this instance's format. This always returns {@code false}
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for formats that don't include a branch offset.
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>The default implementation of this method always returns
12799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code false}. Subclasses must override this method if they
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * include branch offsets.</p>
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
13099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param insn {@code non-null;} the instruction to check
13199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code true} iff the instruction's branch offset is
13299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * appropriate for this instance, or {@code false} if not
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean branchFits(TargetInsn insn) {
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the next instruction format to try to match an instruction
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * with, presuming that this instance isn't compatible, if any.
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>Subclasses must override this method.</p>
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
14499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code null-ok;} the next format to try, or {@code null} if
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * there are no suitable alternatives
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public abstract InsnFormat nextUp();
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes the code units for the given instruction to the given
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * output destination. The instruction must be of this instance's format.
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>Subclasses must override this method.</p>
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
15599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param out {@code non-null;} the output destination to write to
15699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param insn {@code non-null;} the instruction to write
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public abstract void writeTo(AnnotatedOutput out, DalvInsn insn);
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to return a register list string.
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
16399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param list {@code non-null;} the list of registers
16499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the string form
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static String regListString(RegisterSpecList list) {
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sz = list.size();
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuffer sb = new StringBuffer(sz * 5 + 2);
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append('{');
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < sz; i++) {
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (i != 0) {
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sb.append(", ");
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(list.get(i).regString());
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append('}');
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sb.toString();
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to return a literal bits argument string.
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param value the value
18899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the string form
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static String literalBitsString(CstLiteralBits value) {
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuffer sb = new StringBuffer(100);
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append('#');
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (value instanceof CstKnownNull) {
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append("null");
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(value.typeName());
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(' ');
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(value.toHuman());
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sb.toString();
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to return a literal bits comment string.
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param value the value
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param width the width of the constant, in bits (used for displaying
21199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * the uninterpreted bits; one of: {@code 4 8 16 32 64}
21299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the comment
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static String literalBitsComment(CstLiteralBits value,
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int width) {
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuffer sb = new StringBuffer(20);
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append("#");
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        long bits;
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (value instanceof CstLiteral64) {
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bits = ((CstLiteral64) value).getLongBits();
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bits = value.getIntBits();
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (width) {
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 4:  sb.append(Hex.uNibble((int) bits)); break;
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 8:  sb.append(Hex.u1((int) bits));      break;
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 16: sb.append(Hex.u2((int) bits));      break;
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 32: sb.append(Hex.u4((int) bits));      break;
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 64: sb.append(Hex.u8(bits));            break;
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default: {
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new RuntimeException("shouldn't happen");
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sb.toString();
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to return a branch address string.
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
24599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param insn {@code non-null;} the instruction in question
24699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the string form of the instruction's branch target
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static String branchString(DalvInsn insn) {
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TargetInsn ti = (TargetInsn) insn;
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int address = ti.getTargetAddress();
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (address == (char) address) ? Hex.u2(address) : Hex.u4(address);
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to return the comment for a branch.
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
25899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param insn {@code non-null;} the instruction in question
25999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the comment
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static String branchComment(DalvInsn insn) {
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TargetInsn ti = (TargetInsn) insn;
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int offset = ti.getTargetOffset();
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (offset == (short) offset) ? Hex.s2(offset) : Hex.s4(offset);
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to return a constant string.
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
27199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param insn {@code non-null;} a constant-bearing instruction
27299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the string form of the contained constant
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static String cstString(DalvInsn insn) {
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CstInsn ci = (CstInsn) insn;
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Constant cst = ci.getConstant();
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return cst.toHuman();
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to return an instruction comment for a constant.
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
28499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param insn {@code non-null;} a constant-bearing instruction
28599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} comment string representing the constant
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static String cstComment(DalvInsn insn) {
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CstInsn ci = (CstInsn) insn;
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (! ci.hasIndex()) {
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return "";
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuilder sb = new StringBuilder(20);
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int index = ci.getIndex();
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(ci.getConstant().typeName());
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append('@');
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (index < 65536) {
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(Hex.u2(index));
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(Hex.u4(index));
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sb.toString();
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to determine if a signed int value fits in a nibble.
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param value the value in question
31399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code true} iff it's in the range -8..+7
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static boolean signedFitsInNibble(int value) {
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (value >= -8) && (value <= 7);
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to determine if an unsigned int value fits in a nibble.
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param value the value in question
32399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code true} iff it's in the range 0..0xf
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static boolean unsignedFitsInNibble(int value) {
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return value == (value & 0xf);
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to determine if a signed int value fits in a byte.
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param value the value in question
33399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code true} iff it's in the range -0x80..+0x7f
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static boolean signedFitsInByte(int value) {
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (byte) value == value;
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to determine if an unsigned int value fits in a byte.
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param value the value in question
34399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code true} iff it's in the range 0..0xff
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static boolean unsignedFitsInByte(int value) {
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return value == (value & 0xff);
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to determine if a signed int value fits in a short.
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param value the value in question
35399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code true} iff it's in the range -0x8000..+0x7fff
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static boolean signedFitsInShort(int value) {
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (short) value == value;
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to determine if an unsigned int value fits in a short.
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param value the value in question
36399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code true} iff it's in the range 0..0xffff
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static boolean unsignedFitsInShort(int value) {
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return value == (value & 0xffff);
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to determine if a signed int value fits in three bytes.
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param value the value in question
37399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code true} iff it's in the range -0x800000..+0x7fffff
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static boolean signedFitsIn3Bytes(int value) {
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return value == ((value << 8) >> 8);
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to extract the callout-argument index from an
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * appropriate instruction.
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
38399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param insn {@code non-null;} the instruction
38499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= 0;} the callout argument index
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static int argIndex(DalvInsn insn) {
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int arg = ((CstInteger) ((CstInsn) insn).getConstant()).getValue();
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (arg < 0) {
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("bogus insn");
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return arg;
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to combine an opcode and a second byte of data into
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the appropriate form for emitting into a code buffer.
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
40099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param insn {@code non-null;} the instruction containing the opcode
40199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param arg {@code 0..255;} arbitrary other byte value
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return combined value
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static short opcodeUnit(DalvInsn insn, int arg) {
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((arg & 0xff) != arg) {
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("arg out of range 0..255");
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int opcode = insn.getOpcode().getOpcode();
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((opcode & 0xff) != opcode) {
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("opcode out of range 0..255");
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (short) (opcode | (arg << 8));
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to combine two bytes into a code unit.
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
42199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param low {@code 0..255;} low byte
42299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param high {@code 0..255;} high byte
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return combined value
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static short codeUnit(int low, int high) {
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((low & 0xff) != low) {
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("low out of range 0..255");
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((high & 0xff) != high) {
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("high out of range 0..255");
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (short) (low | (high << 8));
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to combine four nibbles into a code unit.
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
44099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param n0 {@code 0..15;} low nibble
44199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param n1 {@code 0..15;} medium-low nibble
44299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param n2 {@code 0..15;} medium-high nibble
44399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param n3 {@code 0..15;} high nibble
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return combined value
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static short codeUnit(int n0, int n1, int n2, int n3) {
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((n0 & 0xf) != n0) {
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("n0 out of range 0..15");
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((n1 & 0xf) != n1) {
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("n1 out of range 0..15");
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((n2 & 0xf) != n2) {
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("n2 out of range 0..15");
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((n3 & 0xf) != n3) {
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("n3 out of range 0..15");
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (short) (n0 | (n1 << 4) | (n2 << 8) | (n3 << 12));
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to combine two nibbles into a byte.
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
46999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param low {@code 0..15;} low nibble
47099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param high {@code 0..15;} high nibble
47199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code 0..255;} combined value
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static int makeByte(int low, int high) {
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((low & 0xf) != low) {
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("low out of range 0..15");
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((high & 0xf) != high) {
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("high out of range 0..15");
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return low | (high << 4);
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes one code unit to the given output destination.
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
48899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param out {@code non-null;} where to write to
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c0 code unit to write
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static void write(AnnotatedOutput out, short c0) {
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c0);
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes two code units to the given output destination.
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
49899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param out {@code non-null;} where to write to
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c0 code unit to write
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c1 code unit to write
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static void write(AnnotatedOutput out, short c0, short c1) {
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c0);
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c1);
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes three code units to the given output destination.
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
51099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param out {@code non-null;} where to write to
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c0 code unit to write
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c1 code unit to write
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c2 code unit to write
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static void write(AnnotatedOutput out, short c0, short c1,
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                short c2) {
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c0);
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c1);
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c2);
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes four code units to the given output destination.
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
52599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param out {@code non-null;} where to write to
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c0 code unit to write
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c1 code unit to write
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c2 code unit to write
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c3 code unit to write
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static void write(AnnotatedOutput out, short c0, short c1,
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                short c2, short c3) {
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c0);
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c1);
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c2);
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c3);
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes five code units to the given output destination.
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
54299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param out {@code non-null;} where to write to
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c0 code unit to write
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c1 code unit to write
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c2 code unit to write
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c3 code unit to write
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c4 code unit to write
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static void write(AnnotatedOutput out, short c0, short c1,
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                short c2, short c3, short c4) {
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c0);
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c1);
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c2);
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c3);
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c4);
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes six code units to the given output destination.
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
56199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param out {@code non-null;} where to write to
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c0 code unit to write
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c1 code unit to write
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c2 code unit to write
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c3 code unit to write
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c4 code unit to write
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c5 code unit to write
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected static void write(AnnotatedOutput out, short c0, short c1,
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                short c2, short c3, short c4, short c5) {
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c0);
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c1);
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c2);
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c3);
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c4);
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeShort(c5);
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
579