InstructionMethodItem.java revision eb0b009971653400809fa43c51d2ce99cb5c52b9
16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * [The "BSD licence"]
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Copyright (c) 2010 Ben Gruver (JesusFreke)
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * All rights reserved.
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Redistribution and use in source and binary forms, with or without
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * modification, are permitted provided that the following conditions
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * are met:
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * 1. Redistributions of source code must retain the above copyright
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *    notice, this list of conditions and the following disclaimer.
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * 2. Redistributions in binary form must reproduce the above copyright
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *    notice, this list of conditions and the following disclaimer in the
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *    documentation and/or other materials provided with the distribution.
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * 3. The name of the author may not be used to endorse or promote products
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *    derived from this software without specific prior written permission.
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgpackage org.jf.baksmali.Adaptors.Format;
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport org.jf.baksmali.Adaptors.MethodDefinition;
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport org.jf.baksmali.Adaptors.MethodItem;
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport org.jf.baksmali.Adaptors.ReferenceFormatter;
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport org.jf.baksmali.Renderers.LongRenderer;
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport org.jf.dexlib2.ReferenceType;
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport org.jf.dexlib2.VerificationError;
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport org.jf.dexlib2.dexbacked.DexBackedDexFile.InvalidItemIndex;
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport org.jf.dexlib2.iface.instruction.*;
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport org.jf.dexlib2.iface.instruction.formats.Instruction20bc;
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport org.jf.dexlib2.iface.instruction.formats.UnknownInstruction;
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport org.jf.dexlib2.iface.reference.Reference;
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport org.jf.util.IndentingWriter;
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport javax.annotation.Nonnull;
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport java.io.IOException;
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgimport java.util.Map;
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgpublic class InstructionMethodItem<T extends Instruction> extends MethodItem {
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    @Nonnull protected final MethodDefinition methodDef;
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    @Nonnull protected final T instruction;
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    public InstructionMethodItem(@Nonnull MethodDefinition methodDef, int codeAddress, @Nonnull T instruction) {
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        super(codeAddress);
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        this.methodDef = methodDef;
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        this.instruction = instruction;
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    public double getSortOrder() {
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        //instructions should appear after everything except an "end try" label and .catch directive
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 100;
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    @Override
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    public boolean writeTo(IndentingWriter writer) throws IOException {
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        boolean invalidReference = false;
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (instruction instanceof ReferenceInstruction) {
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            try {
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                Reference reference = ((ReferenceInstruction)instruction).getReference();
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } catch (InvalidItemIndex ex) {
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                invalidReference = true;
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write("#invalid ");
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(ReferenceType.toString(instruction.getOpcode().referenceType));
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(" index: ");
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.printSignedIntAsDec(ex.getInvalidIndex());
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write("\n#");
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        switch (instruction.getOpcode().format) {
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format10t:
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeOpcode(writer);
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(' ');
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeTargetLabel(writer);
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return true;
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format10x:
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (instruction instanceof UnknownInstruction) {
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    writer.write("#unknown opcode: 0x");
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    writer.printUnsignedLongAsHex(((UnknownInstruction)instruction).getOriginalOpcode());
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    writer.write('\n');
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeOpcode(writer);
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return true;
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format11n:
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeOpcode(writer);
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(' ');
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeFirstRegister(writer);
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(", ");
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeLiteral(writer);
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return true;
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format11x:
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeOpcode(writer);
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(' ');
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeFirstRegister(writer);
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return true;
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format12x:
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeOpcode(writer);
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(' ');
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeFirstRegister(writer);
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(", ");
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeSecondRegister(writer);
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return true;
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format20bc:
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeOpcode(writer);
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(' ');
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeVerificationErrorType(writer);
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(", ");
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeReference(writer);
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return true;
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format20t:
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format30t:
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeOpcode(writer);
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(' ');
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeTargetLabel(writer);
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return true;
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format21c:
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format31c:
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeOpcode(writer);
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(' ');
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeFirstRegister(writer);
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(", ");
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeReference(writer);
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return true;
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format21ih:
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format21lh:
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format21s:
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format31i:
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format51l:
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeOpcode(writer);
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(' ');
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeFirstRegister(writer);
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(", ");
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeLiteral(writer);
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (instruction.getOpcode().setsWideRegister() == false)
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    writeResourceId(writer);
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return true;
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format21t:
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format31t:
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeOpcode(writer);
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(' ');
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeFirstRegister(writer);
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(", ");
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeTargetLabel(writer);
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return true;
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format22b:
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format22s:
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeOpcode(writer);
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(' ');
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeFirstRegister(writer);
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(", ");
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeSecondRegister(writer);
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(", ");
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeLiteral(writer);
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return true;
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format22c:
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeOpcode(writer);
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(' ');
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeFirstRegister(writer);
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(", ");
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeSecondRegister(writer);
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(", ");
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeReference(writer);
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return true;
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case Format22cs:
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeOpcode(writer);
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(' ');
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeFirstRegister(writer);
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writer.write(", ");
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                writeSecondRegister(writer);
180                writer.write(", ");
181                writeFieldOffset(writer);
182                return true;
183            case Format22t:
184                writeOpcode(writer);
185                writer.write(' ');
186                writeFirstRegister(writer);
187                writer.write(", ");
188                writeSecondRegister(writer);
189                writer.write(", ");
190                writeTargetLabel(writer);
191                return true;
192            case Format22x:
193            case Format32x:
194                writeOpcode(writer);
195                writer.write(' ');
196                writeFirstRegister(writer);
197                writer.write(", ");
198                writeSecondRegister(writer);
199                return true;
200            case Format23x:
201                writeOpcode(writer);
202                writer.write(' ');
203                writeFirstRegister(writer);
204                writer.write(", ");
205                writeSecondRegister(writer);
206                writer.write(", ");
207                writeThirdRegister(writer);
208                return true;
209            case Format35c:
210                writeOpcode(writer);
211                writer.write(' ');
212                writeInvokeRegisters(writer);
213                writer.write(", ");
214                writeReference(writer);
215                return true;
216            case Format35mi:
217                writeOpcode(writer);
218                writer.write(' ');
219                writeInvokeRegisters(writer);
220                writer.write(", ");
221                writeInlineIndex(writer);
222                return true;
223            case Format35ms:
224                writeOpcode(writer);
225                writer.write(' ');
226                writeInvokeRegisters(writer);
227                writer.write(", ");
228                writeVtableIndex(writer);
229                return true;
230            case Format3rc:
231                writeOpcode(writer);
232                writer.write(' ');
233                writeInvokeRangeRegisters(writer);
234                writer.write(", ");
235                writeReference(writer);
236                return true;
237            case Format3rmi:
238                writeOpcode(writer);
239                writer.write(' ');
240                writeInvokeRangeRegisters(writer);
241                writer.write(", ");
242                writeInlineIndex(writer);
243                return true;
244            case Format3rms:
245                writeOpcode(writer);
246                writer.write(' ');
247                writeInvokeRangeRegisters(writer);
248                writer.write(", ");
249                writeVtableIndex(writer);
250                return true;
251        }
252        assert false;
253        return false;
254    }
255
256    protected void writeOpcode(IndentingWriter writer) throws IOException {
257        writer.write(instruction.getOpcode().name);
258    }
259
260    protected void writeTargetLabel(IndentingWriter writer) throws IOException {
261        //this method is overridden by OffsetInstructionMethodItem, and should only be called for the formats that
262        //have a target
263        throw new RuntimeException();
264    }
265
266    protected void writeRegister(IndentingWriter writer, int registerNumber) throws IOException {
267        methodDef.registerFormatter.writeTo(writer, registerNumber);
268    }
269
270    protected void writeFirstRegister(IndentingWriter writer) throws IOException {
271        writeRegister(writer, ((OneRegisterInstruction)instruction).getRegisterA());
272    }
273
274    protected void writeSecondRegister(IndentingWriter writer) throws IOException {
275        writeRegister(writer, ((TwoRegisterInstruction)instruction).getRegisterB());
276    }
277
278    protected void writeThirdRegister(IndentingWriter writer) throws IOException {
279        writeRegister(writer, ((ThreeRegisterInstruction) instruction).getRegisterC());
280    }
281
282    protected void writeInvokeRegisters(IndentingWriter writer) throws IOException {
283        FiveRegisterInstruction instruction = (FiveRegisterInstruction)this.instruction;
284        final int regCount = instruction.getRegisterCount();
285
286        writer.write('{');
287        switch (regCount) {
288            case 1:
289                writeRegister(writer, instruction.getRegisterC());
290                break;
291            case 2:
292                writeRegister(writer, instruction.getRegisterC());
293                writer.write(", ");
294                writeRegister(writer, instruction.getRegisterD());
295                break;
296            case 3:
297                writeRegister(writer, instruction.getRegisterC());
298                writer.write(", ");
299                writeRegister(writer, instruction.getRegisterD());
300                writer.write(", ");
301                writeRegister(writer, instruction.getRegisterE());
302                break;
303            case 4:
304                writeRegister(writer, instruction.getRegisterC());
305                writer.write(", ");
306                writeRegister(writer, instruction.getRegisterD());
307                writer.write(", ");
308                writeRegister(writer, instruction.getRegisterE());
309                writer.write(", ");
310                writeRegister(writer, instruction.getRegisterF());
311                break;
312            case 5:
313                writeRegister(writer, instruction.getRegisterC());
314                writer.write(", ");
315                writeRegister(writer, instruction.getRegisterD());
316                writer.write(", ");
317                writeRegister(writer, instruction.getRegisterE());
318                writer.write(", ");
319                writeRegister(writer, instruction.getRegisterF());
320                writer.write(", ");
321                writeRegister(writer, instruction.getRegisterG());
322                break;
323        }
324        writer.write('}');
325    }
326
327    protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException {
328        RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction;
329
330        int regCount = instruction.getRegisterCount();
331        if (regCount == 0) {
332            writer.write("{}");
333        } else {
334            int startRegister = instruction.getStartRegister();
335            methodDef.registerFormatter.writeRegisterRange(writer, startRegister, startRegister+regCount-1);
336        }
337    }
338
339    protected void writeLiteral(IndentingWriter writer) throws IOException {
340        LongRenderer.writeSignedIntOrLongTo(writer, ((WideLiteralInstruction)instruction).getWideLiteral());
341    }
342
343    protected void writeResourceId(IndentingWriter writer) throws IOException {
344        writeResourceId(writer, ((NarrowLiteralInstruction)instruction).getNarrowLiteral());
345    }
346
347    protected void writeResourceId(IndentingWriter writer, int val) throws IOException {
348        Map<Integer,String> resourceIds = methodDef.classDef.options.resourceIds;
349        if (resourceIds.containsKey(Integer.valueOf(val))) {
350            writer.write("    # ");
351            writer.write(resourceIds.get(Integer.valueOf(val)));
352        }
353    }
354
355    protected void writeFieldOffset(IndentingWriter writer) throws IOException {
356        writer.write("field@0x");
357        writer.printUnsignedLongAsHex(((FieldOffsetInstruction)instruction).getFieldOffset());
358    }
359
360    protected void writeInlineIndex(IndentingWriter writer) throws IOException {
361        writer.write("inline@");
362        writer.printSignedIntAsDec(((InlineIndexInstruction)instruction).getInlineIndex());
363    }
364
365    protected void writeVtableIndex(IndentingWriter writer) throws IOException {
366        writer.write("vtable@");
367        writer.printSignedIntAsDec(((VtableIndexInstruction)instruction).getVtableIndex());
368    }
369
370    protected void writeReference(IndentingWriter writer) throws IOException {
371        try {
372            ReferenceFormatter.writeReference(writer, instruction.getOpcode().referenceType,
373                    ((ReferenceInstruction)instruction).getReference());
374        } catch (InvalidItemIndex ex) {
375            writer.write(ReferenceType.toString(instruction.getOpcode().referenceType));
376            writer.write("@");
377            writer.printSignedIntAsDec(ex.getInvalidIndex());
378        }
379    }
380
381    protected void writeVerificationErrorType(IndentingWriter writer) throws IOException {
382        int verificationError = ((Instruction20bc)instruction).getVerificationError();
383        writer.write(VerificationError.getVerificationErrorName(verificationError));
384    }
385}
386