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 }