/* * Copyright (C) 2010-2013 JPEXS * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.jpexs.asdec.abc.avm2.instructions; import com.jpexs.asdec.abc.ABCOutputStream; import com.jpexs.asdec.abc.avm2.AVM2Code; import com.jpexs.asdec.abc.avm2.ConstantPool; import com.jpexs.asdec.helpers.Helper; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.List; public class AVM2Instruction implements Serializable{ public InstructionDefinition definition; public int operands[]; public long offset; public byte bytes[]; public String comment; public boolean ignored = false; public String labelname; public long mappedOffset=-1; public AVM2Instruction(long offset, InstructionDefinition definition, int[] operands, byte bytes[]) { this.definition = definition; this.operands = operands; this.offset = offset; this.bytes = bytes; } public byte[] getBytes() { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { ABCOutputStream aos = new ABCOutputStream(bos); aos.write(definition.instructionCode); for (int i = 0; i < definition.operands.length; i++) { int opt = definition.operands[i] & 0xff00; switch (opt) { case AVM2Code.OPT_S24: aos.writeS24(operands[i]); break; case AVM2Code.OPT_U30: aos.writeU30(operands[i]); break; case AVM2Code.OPT_U8: aos.writeU8(operands[i]); break; case AVM2Code.OPT_BYTE: aos.writeU8(0xff & operands[i]); break; case AVM2Code.OPT_CASE_OFFSETS: aos.writeU30(operands[i]); //case count for (int j = i + 1; j < operands.length; j++) { aos.writeS24(operands[j]); } break; } } } catch (IOException ex) { //ignored } return bos.toByteArray(); } @Override public String toString() { String s = definition.instructionName; for (int i = 0; i < operands.length; i++) { s += " " + operands[i]; } return s; } public List getOffsets() { List ret = new ArrayList(); String s = ""; for (int i = 0; i < definition.operands.length; i++) { switch (definition.operands[i]) { case AVM2Code.DAT_OFFSET: ret.add(offset + operands[i] + getBytes().length); break; case AVM2Code.DAT_CASE_BASEOFFSET: ret.add(offset + operands[i]); break; case AVM2Code.OPT_CASE_OFFSETS: for (int j = i + 1; j < operands.length; j++) { ret.add(offset + operands[j]); } break; } } return ret; } public List getParamsAsList(ConstantPool constants) { List s = new ArrayList(); for (int i = 0; i < definition.operands.length; i++) { switch (definition.operands[i]) { case AVM2Code.DAT_MULTINAME_INDEX: s.add(constants.constant_multiname[operands[i]]); break; case AVM2Code.DAT_STRING_INDEX: s.add(constants.constant_string[operands[i]]); break; case AVM2Code.DAT_INT_INDEX: s.add(new Long(constants.constant_int[operands[i]])); break; case AVM2Code.DAT_UINT_INDEX: s.add(new Long(constants.constant_uint[operands[i]])); break; case AVM2Code.DAT_DOUBLE_INDEX: s.add(new Double(constants.constant_double[operands[i]])); break; case AVM2Code.DAT_OFFSET: s.add(new Long(offset + operands[i] + getBytes().length)); break; case AVM2Code.DAT_CASE_BASEOFFSET: s.add(new Long(offset + operands[i])); break; case AVM2Code.OPT_CASE_OFFSETS: s.add(new Long(operands[i])); for (int j = i + 1; j < operands.length; j++) { s.add(new Long(offset + operands[j])); } break; default: s.add(new Long(operands[i])); } } return s; } public String getParams(ConstantPool constants, List fullyQualifiedNames) { String s = ""; for (int i = 0; i < definition.operands.length; i++) { switch (definition.operands[i]) { case AVM2Code.DAT_MULTINAME_INDEX: s += " m[" + operands[i] + "]\"" + Helper.escapeString(constants.constant_multiname[operands[i]].toString(constants, fullyQualifiedNames)) + "\""; break; case AVM2Code.DAT_STRING_INDEX: s += " \"" + Helper.escapeString(constants.constant_string[operands[i]]) + "\""; break; case AVM2Code.DAT_INT_INDEX: s += " " + constants.constant_int[operands[i]] + ""; break; case AVM2Code.DAT_UINT_INDEX: s += " " + constants.constant_uint[operands[i]] + ""; break; case AVM2Code.DAT_DOUBLE_INDEX: s += " " + constants.constant_double[operands[i]] + ""; break; case AVM2Code.DAT_OFFSET: s += " "; if (operands[i] > 0) { //s += "+"; }//operands[i] s += "ofs" + Helper.formatAddress(offset + operands[i] + getBytes().length) + ""; break; case AVM2Code.DAT_CASE_BASEOFFSET: s += " "; if (operands[i] > 0) { //s += "+"; }//operands[i] s += "ofs" + Helper.formatAddress(offset + operands[i]) + ""; break; case AVM2Code.OPT_CASE_OFFSETS: s += " " + operands[i]; for (int j = i + 1; j < operands.length; j++) { s += " "; if (operands[j] > 0) { //s += "+"; }//operands[j] s += "ofs" + Helper.formatAddress(offset + operands[j]) + ""; } break; default: s += " " + operands[i]; } } return s; } public String getComment() { if (ignored) { return " ;ignored"; } if ((comment == null) || comment.equals("")) { return ""; } return " ;" + comment; } public boolean isIgnored() { return ignored; } public String toString(ConstantPool constants, List fullyQualifiedNames) { String s = Helper.formatAddress(offset) + " " + Helper.padSpaceRight(Helper.byteArrToString(getBytes()), 30) + definition.instructionName; s += getParams(constants, fullyQualifiedNames) + getComment(); return s; } public String toStringNoAddress(ConstantPool constants, List fullyQualifiedNames) { String s = definition.instructionName; s += getParams(constants, fullyQualifiedNames) + getComment(); return s; } public List replaceWith; }