1 package serp.bytecode;
2
3 import serp.bytecode.visitor.*;
4
5
6
7
8
9
10
11 public class CmpInstruction extends TypedInstruction {
12 private static Class[][] _mappings = new Class[][] {
13 { int.class, long.class },
14 { byte.class, long.class },
15 { char.class, long.class },
16 { short.class, long.class },
17 { boolean.class, long.class },
18 { void.class, long.class },
19 { Object.class, long.class },
20 };
21
22 CmpInstruction(Code owner) {
23 super(owner);
24 }
25
26 CmpInstruction(Code owner, int opcode) {
27 super(owner, opcode);
28 }
29
30 public int getLogicalStackChange() {
31 switch (getOpcode()) {
32 case Constants.NOP:
33 return 0;
34 default:
35 return -1;
36 }
37 }
38
39 public int getStackChange() {
40 switch (getOpcode()) {
41 case Constants.LCMP:
42 case Constants.DCMPL:
43 case Constants.DCMPG:
44 return -3;
45 case Constants.NOP:
46 return 0;
47 default:
48 return -1;
49 }
50 }
51
52 public String getTypeName() {
53 switch (getOpcode()) {
54 case Constants.LCMP:
55 return long.class.getName();
56 case Constants.FCMPL:
57 case Constants.FCMPG:
58 return float.class.getName();
59 case Constants.DCMPL:
60 case Constants.DCMPG:
61 return double.class.getName();
62 default:
63 return null;
64 }
65 }
66
67 public TypedInstruction setType(String type) {
68 type = mapType(type, _mappings, true);
69 if (type == null)
70 return (TypedInstruction) setOpcode(Constants.NOP);
71
72 int opcode = getOpcode();
73 switch (type.charAt(0)) {
74 case 'l':
75 return (TypedInstruction) setOpcode(Constants.LCMP);
76 case 'f':
77 if ((opcode == Constants.FCMPL) || (opcode == Constants.DCMPL))
78 return (TypedInstruction) setOpcode(Constants.FCMPL);
79 return (TypedInstruction) setOpcode(Constants.FCMPG);
80 case 'd':
81 if ((opcode == Constants.FCMPL) || (opcode == Constants.DCMPL))
82 return (TypedInstruction) setOpcode(Constants.DCMPL);
83 return (TypedInstruction) setOpcode(Constants.DCMPG);
84 default:
85 throw new IllegalStateException();
86 }
87 }
88
89
90
91
92
93
94
95 public int getNaNValue() {
96 switch (getOpcode()) {
97 case Constants.FCMPL:
98 case Constants.DCMPL:
99 return -1;
100 case Constants.FCMPG:
101 case Constants.DCMPG:
102 return 1;
103 default:
104 return 0;
105 }
106 }
107
108
109
110
111
112
113
114
115
116 public CmpInstruction setNaNValue(int nan) {
117 switch (getOpcode()) {
118 case Constants.FCMPL:
119 case Constants.FCMPG:
120 if (nan == 1)
121 setOpcode(Constants.FCMPG);
122 else if (nan == -1)
123 setOpcode(Constants.FCMPL);
124 else
125 throw new IllegalArgumentException("Invalid nan for type");
126 case Constants.DCMPL:
127 case Constants.DCMPG:
128 if (nan == 1)
129 setOpcode(Constants.DCMPG);
130 else if (nan == -1)
131 setOpcode(Constants.DCMPL);
132 else
133 throw new IllegalArgumentException("Invalid nan for type");
134 default:
135 if (nan != 0)
136 throw new IllegalArgumentException("Invalid nan for type");
137 }
138 return this;
139 }
140
141 public void acceptVisit(BCVisitor visit) {
142 visit.enterCmpInstruction(this);
143 visit.exitCmpInstruction(this);
144 }
145 }