001 package edu.rice.cs.cunit.classFile.code.instructions; 002 003 import edu.rice.cs.cunit.classFile.code.Opcode; 004 005 /** 006 * Wide Java instruction. 007 * 008 * @author Mathias Ricken 009 */ 010 public class WideInstruction extends GenericInstruction { 011 /** 012 * Constructor. 013 * 014 * @param code bytecode for generic instruction, excluding the WIDE opcode 015 */ 016 public WideInstruction(byte[] code) { 017 super(new byte[]{Opcode.NOP}); 018 019 switch(code[0]) { 020 case Opcode.ALOAD: 021 case Opcode.DLOAD: 022 case Opcode.ILOAD: 023 case Opcode.FLOAD: 024 case Opcode.LLOAD: 025 case Opcode.ASTORE: 026 case Opcode.DSTORE: 027 case Opcode.ISTORE: 028 case Opcode.FSTORE: 029 case Opcode.LSTORE: 030 case Opcode.RET: 031 case Opcode.IINC: 032 break; 033 default: 034 throw new IllegalArgumentException("Illegal wide instruction"); 035 } 036 037 _code = new byte[code.length + 1]; 038 _code[0] = Opcode.WIDE; 039 System.arraycopy(code, 0, _code, 1, code.length); 040 } 041 042 /** 043 * Get the opcode of this instruction. 044 * 045 * @return opcode 046 */ 047 public byte getOpcode() { 048 return Opcode.WIDE; 049 } 050 051 /** 052 * Get the length bytecode for this instruction, padded for the specified program counter value. 053 * 054 * @param pc PC for padding 055 * 056 * @return bytecode length 057 */ 058 public int getBytecodeLength(int pc) { 059 switch(_code[1]) { 060 case Opcode.ALOAD: 061 case Opcode.DLOAD: 062 case Opcode.ILOAD: 063 case Opcode.FLOAD: 064 case Opcode.LLOAD: 065 case Opcode.ASTORE: 066 case Opcode.DSTORE: 067 case Opcode.ISTORE: 068 case Opcode.FSTORE: 069 case Opcode.LSTORE: 070 case Opcode.RET: 071 return 4; 072 case Opcode.IINC: 073 return 6; 074 default: 075 throw new IllegalArgumentException("Illegal wide instruction"); 076 } 077 } 078 079 /** 080 * Make a new generic instruction from the bytecode stating at pc, padded using paddingPC, and use the line number 081 * table for branches. 082 * 083 * @param bytecode bytecode 084 * @param pc starting index in bytecode 085 * @param paddingPC PC for padding 086 * @param lnt line number table for branches 087 */ 088 public WideInstruction(byte[] bytecode, int pc, int paddingPC, LineNumberTable lnt) { 089 super(bytecode, pc, paddingPC, lnt); 090 } 091 092 /** 093 * Return hash code. 094 * 095 * @return hash code 096 */ 097 public int hashCode() { 098 return _code[2]; 099 } 100 101 /** 102 * Set the branch target indices. 103 * 104 * @param branchTargets array of target indices 105 */ 106 public void setBranchTargets(int[] branchTargets) { 107 if (branchTargets.length != 0) { 108 throw new IllegalArgumentException("Wide instruction cannot have a target"); 109 } 110 } 111 112 /** 113 * Return instruction in human-readable form. 114 * 115 * @return string representation 116 */ 117 public String toString() { 118 StringBuilder x = new StringBuilder(); 119 x.append(Opcode.getOpcodeName(Opcode.WIDE)); 120 x.append(" "); 121 x.append(Opcode.getOpcodeName(_code[1])); 122 x.append(" "); 123 for(int i = 2; i < _code.length; ++i) { 124 x.append(String.format("%02x", new Object[]{new Byte(_code[i])}) + " "); 125 } 126 return x.toString(); 127 } 128 }