13c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein/*
23c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein * Copyright (C) 2011 The Android Open Source Project
33c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein *
43c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein * Licensed under the Apache License, Version 2.0 (the "License");
53c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein * you may not use this file except in compliance with the License.
63c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein * You may obtain a copy of the License at
73c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein *
83c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein *      http://www.apache.org/licenses/LICENSE-2.0
93c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein *
103c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein * Unless required by applicable law or agreed to in writing, software
113c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein * distributed under the License is distributed on an "AS IS" BASIS,
123c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein * See the License for the specific language governing permissions and
143c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein * limitations under the License.
153c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein */
163c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
17537939ca06a47668f719ee06159303bcd3175c69Dan Bornsteinpackage com.android.dx.io.instructions;
183c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
19fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dex.DexException;
20537939ca06a47668f719ee06159303bcd3175c69Dan Bornsteinimport com.android.dx.io.IndexType;
21537939ca06a47668f719ee06159303bcd3175c69Dan Bornsteinimport com.android.dx.io.OpcodeInfo;
22537939ca06a47668f719ee06159303bcd3175c69Dan Bornsteinimport com.android.dx.io.Opcodes;
23740fce415cf1a982e9b035604f432eed378fbd05Dan Bornsteinimport com.android.dx.util.Hex;
2419cefdcde26ea31d06cef031032b2ef78013d976Dan Bornsteinimport java.io.EOFException;
2519cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein
263c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein/**
273c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein * Representation of an instruction format, which knows how to decode into
283c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein * and encode from instances of {@link DecodedInstruction}.
293c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein */
303c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornsteinpublic enum InstructionCodec {
313c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_00X() {
323c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
3319cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
34740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new ZeroRegisterDecodedInstruction(
35740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcodeUnit, 0, null,
36d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, 0L);
373c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
383c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
393c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
403c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(insn.getOpcodeUnit());
413c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
423c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
433c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
443c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_10X() {
453c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
4619cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
473c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
483c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int literal = byte1(opcodeUnit); // should be zero
49740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new ZeroRegisterDecodedInstruction(
50740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
51d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, literal);
523c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
533c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
543c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
553c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(insn.getOpcodeUnit());
563c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
573c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
583c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
593c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_12X() {
603c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
6119cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
623c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
633c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = nibble2(opcodeUnit);
643c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int b = nibble3(opcodeUnit);
65740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new TwoRegisterDecodedInstruction(
66740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
67d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, 0L,
68740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a, b);
693c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
703c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
713c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
723c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
733c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcodeUnit(),
743c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                             makeByte(insn.getA(), insn.getB())));
753c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
763c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
773c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
783c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_11N() {
793c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
8019cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
813c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
823c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = nibble2(opcodeUnit);
833c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int literal = (nibble3(opcodeUnit) << 28) >> 28; // sign-extend
84740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new OneRegisterDecodedInstruction(
85740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
86d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, literal,
87740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a);
883c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
893c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
903c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
913c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
923c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcodeUnit(),
933c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                             makeByte(insn.getA(), insn.getLiteralNibble())));
943c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
953c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
963c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
973c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_11X() {
983c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
9919cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
1003c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
1013c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = byte1(opcodeUnit);
102740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new OneRegisterDecodedInstruction(
103740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
104d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, 0L,
105740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a);
1063c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
1073c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
1083c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
1093c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(codeUnit(insn.getOpcode(), insn.getA()));
1103c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
1113c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
1123c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
1133c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_10T() {
1143c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
11519cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
116d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int baseAddress = in.cursor() - 1;
1173c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
11832dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein            int target = (byte) byte1(opcodeUnit); // sign-extend
119740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new ZeroRegisterDecodedInstruction(
120740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
121d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    baseAddress + target, 0L);
1223c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
1233c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
1243c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
125d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int relativeTarget = insn.getTargetByte(out.cursor());
126d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            out.write(codeUnit(insn.getOpcode(), relativeTarget));
1273c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
1283c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
1293c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
1303c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_20T() {
1313c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
13219cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
133d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int baseAddress = in.cursor() - 1;
1343c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
1353c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int literal = byte1(opcodeUnit); // should be zero
1363c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int target = (short) in.read(); // sign-extend
137740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new ZeroRegisterDecodedInstruction(
138740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
139d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    baseAddress + target, literal);
1403c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
1413c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
1423c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
143d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            short relativeTarget = insn.getTargetUnit(out.cursor());
144d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            out.write(insn.getOpcodeUnit(), relativeTarget);
1453c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
1463c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
1473c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
1483c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_20BC() {
1493c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
15019cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
1513c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            // Note: We use the literal field to hold the decoded AA value.
1523c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
1533c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int literal = byte1(opcodeUnit);
1543c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int index = in.read();
155740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new ZeroRegisterDecodedInstruction(
156740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, index, IndexType.VARIES,
157d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, literal);
1583c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
1593c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
1603c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
1613c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
1623c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcode(), insn.getLiteralByte()),
1633c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    insn.getIndexUnit());
1643c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
1653c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
1663c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
1673c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_22X() {
1683c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
16919cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
1703c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
1713c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = byte1(opcodeUnit);
1723c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int b = in.read();
173740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new TwoRegisterDecodedInstruction(
174740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
175d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, 0L,
176740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a, b);
1773c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
1783c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
1793c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
1803c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
1813c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcode(), insn.getA()),
1823c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    insn.getBUnit());
1833c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
1843c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
1853c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
1863c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_21T() {
1873c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
18819cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
189d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int baseAddress = in.cursor() - 1;
1903c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
1913c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = byte1(opcodeUnit);
1923c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int target = (short) in.read(); // sign-extend
193740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new OneRegisterDecodedInstruction(
194740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
195d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    baseAddress + target, 0L,
196740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a);
1973c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
1983c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
1993c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
200d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            short relativeTarget = insn.getTargetUnit(out.cursor());
201d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            out.write(codeUnit(insn.getOpcode(), insn.getA()), relativeTarget);
2023c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
2033c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
2043c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
2053c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_21S() {
2063c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
20719cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
2083c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
2093c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = byte1(opcodeUnit);
2103c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int literal = (short) in.read(); // sign-extend
211740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new OneRegisterDecodedInstruction(
212740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
213d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, literal,
214740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a);
2153c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
2163c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
2173c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
2183c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
2193c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcode(), insn.getA()),
2203c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    insn.getLiteralUnit());
2213c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
2223c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
2233c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
2243c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_21H() {
2253c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
22619cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
2273c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
2283c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = byte1(opcodeUnit);
2290ebdfc22385095c75fbced79edc1d1e75b504213Jesse Wilson            long literal = (short) in.read(); // sign-extend
2303c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
2313c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            /*
2323c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein             * Format 21h decodes differently depending on the opcode,
2333c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein             * because the "signed hat" might represent either a 32-
2343c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein             * or 64- bit value.
2353c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein             */
2367ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein            literal <<= (opcode == Opcodes.CONST_HIGH16) ? 16 : 48;
2373c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
238740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new OneRegisterDecodedInstruction(
239740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
240d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, literal,
241740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a);
2423c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
2433c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
2443c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
2453c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            // See above.
2463c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = insn.getOpcode();
2477ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein            int shift = (opcode == Opcodes.CONST_HIGH16) ? 16 : 48;
2483c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            short literal = (short) (insn.getLiteral() >> shift);
2493c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
2503c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(codeUnit(opcode, insn.getA()), literal);
2513c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
2523c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
2533c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
2543c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_21C() {
2553c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
25619cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
2573c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
2583c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = byte1(opcodeUnit);
2593c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int index = in.read();
2603c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            IndexType indexType = OpcodeInfo.getIndexType(opcode);
261740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new OneRegisterDecodedInstruction(
262740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, index, indexType,
263d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, 0L,
264740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a);
2653c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
2663c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
2673c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
2683c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
2693c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcode(), insn.getA()),
2701bbb3378b108329c7ab75713fe9507b7ffc7f885Jesse Wilson                    insn.getIndexUnit());
2713c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
2723c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
2733c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
2743c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_23X() {
2753c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
27619cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
2773c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
2783c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = byte1(opcodeUnit);
2793c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int bc = in.read();
2803c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int b = byte0(bc);
2813c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int c = byte1(bc);
282740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new ThreeRegisterDecodedInstruction(
283740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
284d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, 0L,
285740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a, b, c);
2863c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
2873c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
2883c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
2893c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
2903c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcode(), insn.getA()),
2913c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getB(), insn.getC()));
2923c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
2933c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
2943c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
2953c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_22B() {
2963c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
29719cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
2983c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
2993c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = byte1(opcodeUnit);
3003c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int bc = in.read();
3013c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int b = byte0(bc);
3023c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int literal = (byte) byte1(bc); // sign-extend
303740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new TwoRegisterDecodedInstruction(
304740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
305d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, literal,
306740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a, b);
3073c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
3083c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
3093c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
3103c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
3113c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcode(), insn.getA()),
3123c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getB(),
3133c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                             insn.getLiteralByte()));
3143c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
3153c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
3163c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
3173c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_22T() {
3183c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
31919cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
320d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int baseAddress = in.cursor() - 1;
3213c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
3223c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = nibble2(opcodeUnit);
3233c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int b = nibble3(opcodeUnit);
3243c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int target = (short) in.read(); // sign-extend
325740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new TwoRegisterDecodedInstruction(
326740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
327d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    baseAddress + target, 0L,
328740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a, b);
3293c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
3303c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
3313c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
332d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            short relativeTarget = insn.getTargetUnit(out.cursor());
3333c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
3343c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcode(),
3353c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                             makeByte(insn.getA(), insn.getB())),
336d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    relativeTarget);
3373c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
3383c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
3393c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
3403c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_22S() {
3413c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
34219cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
3433c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
3443c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = nibble2(opcodeUnit);
3453c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int b = nibble3(opcodeUnit);
3463c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int literal = (short) in.read(); // sign-extend
347740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new TwoRegisterDecodedInstruction(
348740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
349d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, literal,
350740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a, b);
3513c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
3523c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
3533c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
3543c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
3553c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcode(),
3563c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                             makeByte(insn.getA(), insn.getB())),
3573c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    insn.getLiteralUnit());
3583c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
3593c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
3603c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
3613c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_22C() {
3623c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
36319cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
3643c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
3653c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = nibble2(opcodeUnit);
3663c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int b = nibble3(opcodeUnit);
3673c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int index = in.read();
3683c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            IndexType indexType = OpcodeInfo.getIndexType(opcode);
369740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new TwoRegisterDecodedInstruction(
370740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, index, indexType,
371d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, 0L,
372740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a, b);
3733c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
3743c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
3753c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
3763c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
3773c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcode(),
3783c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                             makeByte(insn.getA(), insn.getB())),
3793c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    insn.getIndexUnit());
3803c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
3813c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
3823c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
3833c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_22CS() {
3843c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
38519cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
3863c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
3873c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = nibble2(opcodeUnit);
3883c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int b = nibble3(opcodeUnit);
3893c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int index = in.read();
390740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new TwoRegisterDecodedInstruction(
391740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, index, IndexType.FIELD_OFFSET,
392d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, 0L,
393740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a, b);
3943c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
3953c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
3963c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
3973c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
3983c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcode(),
3993c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                             makeByte(insn.getA(), insn.getB())),
4003c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    insn.getIndexUnit());
4013c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
4023c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
4033c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
4043c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_30T() {
4053c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
40619cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
407d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int baseAddress = in.cursor() - 1;
4083c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
4093c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int literal = byte1(opcodeUnit); // should be zero
4103c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int target = in.readInt();
411740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new ZeroRegisterDecodedInstruction(
412740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
413d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    baseAddress + target, literal);
4143c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
4153c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
4163c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
417d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int relativeTarget = insn.getTarget(out.cursor());
418d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            out.write(insn.getOpcodeUnit(),
419d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    unit0(relativeTarget), unit1(relativeTarget));
4203c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
4213c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
4223c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
4233c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_32X() {
4243c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
42519cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
4263c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
4273c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int literal = byte1(opcodeUnit); // should be zero
4283c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = in.read();
4293c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int b = in.read();
430740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new TwoRegisterDecodedInstruction(
431740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
432d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, literal,
433740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a, b);
4343c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
4353c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
4363c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
4373c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(insn.getOpcodeUnit(), insn.getAUnit(), insn.getBUnit());
4383c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
4393c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
4403c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
4413c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_31I() {
4423c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
44319cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
4443c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
4453c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = byte1(opcodeUnit);
4463c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int literal = in.readInt();
447740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new OneRegisterDecodedInstruction(
448740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
449d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, literal,
450740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a);
4513c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
4523c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
4533c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
4543c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int literal = insn.getLiteralInt();
4553c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
4563c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcode(), insn.getA()),
4573c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    unit0(literal),
4583c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    unit1(literal));
4593c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
4603c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
4613c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
4623c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_31T() {
4633c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
46419cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
465d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int baseAddress = in.cursor() - 1;
4663c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
4673c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = byte1(opcodeUnit);
468d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int target = baseAddress + in.readInt();
469d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein
470d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            /*
471d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein             * Switch instructions need to "forward" their addresses to their
472d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein             * payload target instructions.
473d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein             */
474d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            switch (opcode) {
475d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                case Opcodes.PACKED_SWITCH:
476d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                case Opcodes.SPARSE_SWITCH: {
477d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    in.setBaseAddress(target, baseAddress);
478d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    break;
479d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                }
480d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            }
481d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein
482740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new OneRegisterDecodedInstruction(
483740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
484d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    target, 0L,
485740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a);
4863c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
4873c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
4883c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
489d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int relativeTarget = insn.getTarget(out.cursor());
4903c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
4913c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcode(), insn.getA()),
492d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    unit0(relativeTarget), unit1(relativeTarget));
4933c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
4943c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
4953c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
4963c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_31C() {
4973c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
49819cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
4993c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
5003c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = byte1(opcodeUnit);
5013c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int index = in.readInt();
5023c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            IndexType indexType = OpcodeInfo.getIndexType(opcode);
503740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new OneRegisterDecodedInstruction(
504740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, index, indexType,
505d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, 0L,
506740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a);
5073c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5083c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5093c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
5103c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int index = insn.getIndex();
5113c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
5123c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcode(), insn.getA()),
5133c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    unit0(index),
5143c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    unit1(index));
5153c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5163c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
5173c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5183c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_35C() {
5193c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
52019cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
5213c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            return decodeRegisterList(this, opcodeUnit, in);
5223c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5233c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5243c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
5253c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            encodeRegisterList(insn, out);
5263c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5273c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
5283c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5293c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_35MS() {
5303c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
53119cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
5323c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            return decodeRegisterList(this, opcodeUnit, in);
5333c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5343c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5353c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
5363c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            encodeRegisterList(insn, out);
5373c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5383c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
5393c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5403c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_35MI() {
5413c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
54219cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
5433c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            return decodeRegisterList(this, opcodeUnit, in);
5443c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5453c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5463c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
5473c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            encodeRegisterList(insn, out);
5483c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5493c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
5503c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5513c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_3RC() {
5523c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
55319cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
5543c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            return decodeRegisterRange(this, opcodeUnit, in);
5553c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5563c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5573c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
5583c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            encodeRegisterRange(insn, out);
5593c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5603c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
5613c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5623c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_3RMS() {
5633c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
56419cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
5653c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            return decodeRegisterRange(this, opcodeUnit, in);
5663c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5673c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5683c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
5693c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            encodeRegisterRange(insn, out);
5703c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5713c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
5723c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5733c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_3RMI() {
5743c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
57519cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
5763c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            return decodeRegisterRange(this, opcodeUnit, in);
5773c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5783c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5793c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
5803c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            encodeRegisterRange(insn, out);
5813c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5823c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
5833c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5843c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    FORMAT_51L() {
5853c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
58619cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein                CodeInput in) throws EOFException {
5873c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int opcode = byte0(opcodeUnit);
5883c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int a = byte1(opcodeUnit);
5893c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            long literal = in.readLong();
590740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            return new OneRegisterDecodedInstruction(
591740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    this, opcode, 0, null,
592d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    0, literal,
593740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                    a);
5943c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
5953c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
5963c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
5971bbb3378b108329c7ab75713fe9507b7ffc7f885Jesse Wilson            long literal = insn.getLiteral();
5983c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            out.write(
5993c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    codeUnit(insn.getOpcode(), insn.getA()),
6003c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    unit0(literal),
6013c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    unit1(literal),
6023c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    unit2(literal),
6033c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                    unit3(literal));
6043c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
6053c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    },
6063c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
60732dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein    FORMAT_PACKED_SWITCH_PAYLOAD() {
60832dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
60932dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein                CodeInput in) throws EOFException {
6100ebdfc22385095c75fbced79edc1d1e75b504213Jesse Wilson            int baseAddress = in.baseAddressForCursor() - 1; // already read opcode
61132dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein            int size = in.read();
612d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int firstKey = in.readInt();
613d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int[] targets = new int[size];
61432dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein
615d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            for (int i = 0; i < size; i++) {
616d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                targets[i] = baseAddress + in.readInt();
61732dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein            }
61832dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein
619d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            return new PackedSwitchPayloadDecodedInstruction(
620d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    this, opcodeUnit, firstKey, targets);
62132dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein        }
62232dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein
62332dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
624d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            PackedSwitchPayloadDecodedInstruction payload =
625d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                (PackedSwitchPayloadDecodedInstruction) insn;
626d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int[] targets = payload.getTargets();
627d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int baseAddress = out.baseAddressForCursor();
628d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein
629d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            out.write(payload.getOpcodeUnit());
630d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            out.write(asUnsignedUnit(targets.length));
631d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            out.writeInt(payload.getFirstKey());
632d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein
633d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            for (int target : targets) {
634d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                out.writeInt(target - baseAddress);
635d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            }
63632dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein        }
63732dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein    },
63832dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein
63932dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein    FORMAT_SPARSE_SWITCH_PAYLOAD() {
64032dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
64132dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein                CodeInput in) throws EOFException {
6420ebdfc22385095c75fbced79edc1d1e75b504213Jesse Wilson            int baseAddress = in.baseAddressForCursor() - 1; // already read opcode
64332dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein            int size = in.read();
644d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int[] keys = new int[size];
645d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int[] targets = new int[size];
64632dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein
647d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            for (int i = 0; i < size; i++) {
648d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                keys[i] = in.readInt();
649d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            }
65032dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein
651d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            for (int i = 0; i < size; i++) {
652d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                targets[i] = baseAddress + in.readInt();
65332dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein            }
65432dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein
655d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            return new SparseSwitchPayloadDecodedInstruction(
656d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    this, opcodeUnit, keys, targets);
65732dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein        }
65832dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein
65932dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
660d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            SparseSwitchPayloadDecodedInstruction payload =
661d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                (SparseSwitchPayloadDecodedInstruction) insn;
662d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int[] keys = payload.getKeys();
663d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int[] targets = payload.getTargets();
664d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            int baseAddress = out.baseAddressForCursor();
665d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein
666d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            out.write(payload.getOpcodeUnit());
667d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            out.write(asUnsignedUnit(targets.length));
668d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein
669d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            for (int key : keys) {
670d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                out.writeInt(key);
671d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            }
672d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein
673d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            for (int target : targets) {
674d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                out.writeInt(target - baseAddress);
675d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            }
67632dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein        }
67732dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein    },
67832dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein
67932dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein    FORMAT_FILL_ARRAY_DATA_PAYLOAD() {
68032dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein        @Override public DecodedInstruction decode(int opcodeUnit,
68132dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein                CodeInput in) throws EOFException {
68232dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein            int elementWidth = in.read();
68332dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein            int size = in.readInt();
68432dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein
685d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            switch (elementWidth) {
686d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                case 1: {
687d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    byte[] array = new byte[size];
688d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    boolean even = true;
689d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    for (int i = 0, value = 0; i < size; i++, even = !even) {
690d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                        if (even) {
691d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                            value = in.read();
692d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                        }
693d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                        array[i] = (byte) (value & 0xff);
694d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                        value >>= 8;
695d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    }
696d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    return new FillArrayDataPayloadDecodedInstruction(
697d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                            this, opcodeUnit, array);
698d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                }
699d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                case 2: {
700d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    short[] array = new short[size];
701d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    for (int i = 0; i < size; i++) {
702d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                        array[i] = (short) in.read();
703d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    }
704d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    return new FillArrayDataPayloadDecodedInstruction(
705d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                            this, opcodeUnit, array);
706d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                }
707d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                case 4: {
708d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    int[] array = new int[size];
709d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    for (int i = 0; i < size; i++) {
710d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                        array[i] = in.readInt();
711d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    }
712d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    return new FillArrayDataPayloadDecodedInstruction(
713d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                            this, opcodeUnit, array);
714d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                }
715d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                case 8: {
716d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    long[] array = new long[size];
717d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    for (int i = 0; i < size; i++) {
718d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                        array[i] = in.readLong();
719d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    }
720d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    return new FillArrayDataPayloadDecodedInstruction(
721d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                            this, opcodeUnit, array);
722d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                }
72332dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein            }
72432dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein
725d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            throw new DexException("bogus element_width: "
726d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    + Hex.u2(elementWidth));
72732dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein        }
72832dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein
72932dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein        @Override public void encode(DecodedInstruction insn, CodeOutput out) {
730d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            FillArrayDataPayloadDecodedInstruction payload =
731d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                (FillArrayDataPayloadDecodedInstruction) insn;
732d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            short elementWidth = payload.getElementWidthUnit();
733d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            Object data = payload.getData();
734d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein
735d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            out.write(payload.getOpcodeUnit());
736d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            out.write(elementWidth);
737d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            out.writeInt(payload.getSize());
738d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein
739d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            switch (elementWidth) {
740d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                case 1: out.write((byte[]) data);  break;
741d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                case 2: out.write((short[]) data); break;
742d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                case 4: out.write((int[]) data);   break;
743d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                case 8: out.write((long[]) data);  break;
744d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                default: {
745d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                    throw new DexException("bogus element_width: "
746d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                            + Hex.u2(elementWidth));
747d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                }
748d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            }
74932dd826ad1742993cf0627448cd083a5021d71bbDan Bornstein        }
7503c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    };
7513c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
7523c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    /**
7533c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein     * Decodes an instruction specified by the given opcode unit, reading
7543c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein     * any required additional code units from the given input source.
7553c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein     */
75619cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein    public abstract DecodedInstruction decode(int opcodeUnit, CodeInput in)
75719cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein        throws EOFException;
7583c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
7593c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    /**
7603c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein     * Encodes the given instruction.
7613c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein     */
7623c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    public abstract void encode(DecodedInstruction insn, CodeOutput out);
7633c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
7643c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    /**
7653c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein     * Helper method that decodes any of the register-list formats.
7663c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein     */
7673c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static DecodedInstruction decodeRegisterList(
76819cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein            InstructionCodec format, int opcodeUnit, CodeInput in)
76919cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein            throws EOFException {
7703c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        int opcode = byte0(opcodeUnit);
7713c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        int e = nibble2(opcodeUnit);
7723c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        int registerCount = nibble3(opcodeUnit);
7733c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        int index = in.read();
7743c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        int abcd = in.read();
7753c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        int a = nibble0(abcd);
7763c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        int b = nibble1(abcd);
7773c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        int c = nibble2(abcd);
7783c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        int d = nibble3(abcd);
7793c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        IndexType indexType = OpcodeInfo.getIndexType(opcode);
780740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein
781740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein        // TODO: Having to switch like this is less than ideal.
782740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein        switch (registerCount) {
783740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            case 0:
784740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                return new ZeroRegisterDecodedInstruction(
785740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                        format, opcode, index, indexType,
786d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                        0, 0L);
787740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            case 1:
788740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                return new OneRegisterDecodedInstruction(
789740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                        format, opcode, index, indexType,
790d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                        0, 0L,
791740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                        a);
792740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            case 2:
793740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                return new TwoRegisterDecodedInstruction(
794740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                        format, opcode, index, indexType,
795d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                        0, 0L,
796740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                        a, b);
797740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            case 3:
798740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                return new ThreeRegisterDecodedInstruction(
799740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                        format, opcode, index, indexType,
800d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                        0, 0L,
801740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                        a, b, c);
802740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            case 4:
803740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                return new FourRegisterDecodedInstruction(
804740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                        format, opcode, index, indexType,
805d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                        0, 0L,
806740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                        a, b, c, d);
807740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein            case 5:
808740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                return new FiveRegisterDecodedInstruction(
809740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                        format, opcode, index, indexType,
810d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                        0, 0L,
811740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                        a, b, c, d, e);
812740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein        }
813740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein
814740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein        throw new DexException("bogus registerCount: "
815740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                + Hex.uNibble(registerCount));
8163c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
8173c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
8183c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    /**
8193c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein     * Helper method that encodes any of the register-list formats.
8203c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein     */
8213c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static void encodeRegisterList(DecodedInstruction insn,
8223c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            CodeOutput out) {
8233c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        out.write(codeUnit(insn.getOpcode(),
8243c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                        makeByte(insn.getE(), insn.getRegisterCount())),
8253c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                insn.getIndexUnit(),
8263c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                codeUnit(insn.getA(), insn.getB(), insn.getC(), insn.getD()));
8273c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
8283c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
8293c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    /**
8303c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein     * Helper method that decodes any of the three-unit register-range formats.
8313c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein     */
8323c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static DecodedInstruction decodeRegisterRange(
83319cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein            InstructionCodec format, int opcodeUnit, CodeInput in)
83419cefdcde26ea31d06cef031032b2ef78013d976Dan Bornstein            throws EOFException {
8353c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        int opcode = byte0(opcodeUnit);
8363c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        int registerCount = byte1(opcodeUnit);
8373c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        int index = in.read();
8383c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        int a = in.read();
8393c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        IndexType indexType = OpcodeInfo.getIndexType(opcode);
840740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein        return new RegisterRangeDecodedInstruction(
841740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                format, opcode, index, indexType,
842d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein                0, 0L,
843740fce415cf1a982e9b035604f432eed378fbd05Dan Bornstein                a, registerCount);
8443c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
8453c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
8463c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    /**
8473c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein     * Helper method that encodes any of the three-unit register-range formats.
8483c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein     */
8493c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static void encodeRegisterRange(DecodedInstruction insn,
8503c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            CodeOutput out) {
8513c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        out.write(codeUnit(insn.getOpcode(), insn.getRegisterCount()),
8523c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                insn.getIndexUnit(),
8533c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                insn.getAUnit());
8543c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
8553c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
8563c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static short codeUnit(int lowByte, int highByte) {
8573c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        if ((lowByte & ~0xff) != 0) {
8583c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            throw new IllegalArgumentException("bogus lowByte");
8593c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
8603c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
8613c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        if ((highByte & ~0xff) != 0) {
8623c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            throw new IllegalArgumentException("bogus highByte");
8633c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
8643c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
8653c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return (short) (lowByte | (highByte << 8));
8663c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
8673c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
8683c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static short codeUnit(int nibble0, int nibble1, int nibble2,
8693c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            int nibble3) {
8703c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        if ((nibble0 & ~0xf) != 0) {
8713c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            throw new IllegalArgumentException("bogus nibble0");
8723c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
8733c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
8743c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        if ((nibble1 & ~0xf) != 0) {
8753c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            throw new IllegalArgumentException("bogus nibble1");
8763c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
8773c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
8783c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        if ((nibble2 & ~0xf) != 0) {
8793c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            throw new IllegalArgumentException("bogus nibble2");
8803c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
8813c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
8823c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        if ((nibble3 & ~0xf) != 0) {
8833c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            throw new IllegalArgumentException("bogus nibble3");
8843c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
8853c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
8863c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return (short) (nibble0 | (nibble1 << 4)
8873c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein                | (nibble2 << 8) | (nibble3 << 12));
8883c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
8893c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
8903c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static int makeByte(int lowNibble, int highNibble) {
8913c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        if ((lowNibble & ~0xf) != 0) {
8923c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            throw new IllegalArgumentException("bogus lowNibble");
8933c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
8943c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
8953c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        if ((highNibble & ~0xf) != 0) {
8963c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein            throw new IllegalArgumentException("bogus highNibble");
8973c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        }
8983c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
8993c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return lowNibble | (highNibble << 4);
9003c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9013c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
902d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein    private static short asUnsignedUnit(int value) {
903d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein        if ((value & ~0xffff) != 0) {
904d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein            throw new IllegalArgumentException("bogus unsigned code unit");
905d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein        }
906d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein
907d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein        return (short) value;
908d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein    }
909d63837a6a16a19e3ae943cdfad52b6f6c8d04a22Dan Bornstein
9103c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static short unit0(int value) {
9113c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return (short) value;
9123c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9133c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
9143c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static short unit1(int value) {
9153c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return (short) (value >> 16);
9163c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9173c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
9183c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static short unit0(long value) {
9193c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return (short) value;
9203c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9213c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
9223c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static short unit1(long value) {
9233c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return (short) (value >> 16);
9243c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9253c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
9263c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static short unit2(long value) {
9273c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return (short) (value >> 32);
9283c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9293c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
9303c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static short unit3(long value) {
9313c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return (short) (value >> 48);
9323c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9333c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
9343c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static int byte0(int value) {
9353c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return value & 0xff;
9363c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9373c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
9383c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static int byte1(int value) {
9393c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return (value >> 8) & 0xff;
9403c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9413c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
9423c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static int byte2(int value) {
9433c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return (value >> 16) & 0xff;
9443c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9453c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
9463c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static int byte3(int value) {
9473c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return value >>> 24;
9483c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9493c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
9503c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static int nibble0(int value) {
9513c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return value & 0xf;
9523c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9533c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
9543c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static int nibble1(int value) {
9553c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return (value >> 4) & 0xf;
9563c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9573c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
9583c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static int nibble2(int value) {
9593c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return (value >> 8) & 0xf;
9603c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9613c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein
9623c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    private static int nibble3(int value) {
9633c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein        return (value >> 12) & 0xf;
9643c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein    }
9653c5df37a2df7368eb274eb097e9cfa2ccc7fffb6Dan Bornstein}
966