001 package sysModel.classFile.code.instructions; 002 003 import sysModel.classFile.code.Opcode; 004 005 import java.util.Arrays; 006 007 /** 008 * Generic Java instruction. 009 * 010 * @author Mathias Ricken 011 */ 012 public class GenericInstruction extends AInstruction { 013 /** 014 * Bytecode. 015 */ 016 protected byte[] _code; 017 018 /** 019 * Constructor. 020 * 021 * @param code bytecode for generic instruction 022 */ 023 public GenericInstruction(byte[] code) { 024 switch(code[0]) { 025 case Opcode.TABLESWITCH: 026 case Opcode.LOOKUPSWITCH: 027 case Opcode.IFEQ: 028 case Opcode.IFNE: 029 case Opcode.IFLT: 030 case Opcode.IFGE: 031 case Opcode.IFGT: 032 case Opcode.IFLE: 033 case Opcode.IF_ICMPEQ: 034 case Opcode.IF_ICMPNE: 035 case Opcode.IF_ICMPLT: 036 case Opcode.IF_ICMPGE: 037 case Opcode.IF_ICMPGT: 038 case Opcode.IF_ICMPLE: 039 case Opcode.IF_ACMPEQ: 040 case Opcode.IF_ACMPNE: 041 case Opcode.GOTO: 042 case Opcode.JSR: 043 case Opcode.IFNULL: 044 case Opcode.IFNONNULL: 045 case Opcode.GOTO_W: 046 case Opcode.JSR_W: 047 case Opcode.WIDE: 048 throw new IllegalArgumentException("Invalid generic opcode"); 049 } 050 _code = code; 051 } 052 053 /** 054 * Get the opcode of this instruction. 055 * 056 * @return opcode 057 */ 058 public byte getOpcode() { 059 return _code[0]; 060 } 061 062 /** 063 * Get the length bytecode for this instruction, padded for the specified program counter value. 064 * 065 * @param pc PC for padding 066 * 067 * @return bytecode length 068 */ 069 public short getBytecodeLength(short pc) { 070 return (short)Opcode.getInstrSize(_code, 0, 0); 071 } 072 073 /** 074 * Make a new generic instruction from the bytecode stating at pc, padded using paddingPC, and use the line number 075 * table for branches. 076 * 077 * @param bytecode bytecode 078 * @param pc starting index in bytecode 079 * @param paddingPC PC for padding 080 * @param lnt line number table for branches 081 */ 082 public GenericInstruction(byte[] bytecode, short pc, short paddingPC, LineNumberTable lnt) { 083 _code = new byte[Opcode.getInstrSize(bytecode, pc, paddingPC)]; 084 System.arraycopy(bytecode, pc, _code, 0, _code.length); 085 } 086 087 /** 088 * Get the bytecode for this instruction, padded for the specified program counter value, with branch targets 089 * according to the specified line number table 090 * 091 * @param pc PC for padding 092 * @param lnt line number table for branches 093 * 094 * @return bytecode 095 */ 096 public byte[] getBytecode(short pc, LineNumberTable lnt) { 097 return getBytecode(); 098 } 099 100 /** 101 * Get the bytecode for this instruction. 102 * 103 * @return bytecode 104 */ 105 public byte[] getBytecode() { 106 byte[] b = new byte[_code.length]; 107 System.arraycopy(_code, 0, b, 0, _code.length); 108 return b; 109 } 110 111 /** 112 * Return true of this instruction and the other object are equal. 113 * 114 * @param o other object 115 * 116 * @return true if equal 117 */ 118 public boolean equals(Object o) { 119 if (this == o) { 120 return true; 121 } 122 if (!(o instanceof GenericInstruction)) { 123 return false; 124 } 125 126 GenericInstruction genericInstruction = (GenericInstruction)o; 127 return Arrays.equals(_code, genericInstruction._code); 128 129 } 130 131 /** 132 * Return hash code. 133 * 134 * @return hash code 135 */ 136 public int hashCode() { 137 return _code[0]; 138 } 139 140 /** 141 * Return an array of target indices. 142 * 143 * @return array of target indices. 144 */ 145 public short[] getBranchTargets() { 146 return new short[0]; 147 } 148 149 /** 150 * Set the branch target indices. 151 * 152 * @param branchTargets array of target indices 153 */ 154 public void setBranchTargets(short[] branchTargets) { 155 if (0 != branchTargets.length) { 156 throw new IllegalArgumentException("Generic instruction cannot have a target"); 157 } 158 } 159 160 /** 161 * Return instruction in human-readable form. 162 * 163 * @return string representation 164 */ 165 public String toString() { 166 StringBuffer x = new StringBuffer(); 167 x.append(Opcode.getOpcodeName(_code[0])); 168 x.append(' '); 169 for(int i = 1; i < _code.length; ++i) { 170 x.append(String.format("%02x", new Object[]{new Byte(_code[i])})).append(' '); 171 } 172 return x.toString(); 173 } 174 } 175