1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.dx.rop.code;
18
19import com.android.dx.rop.cst.Constant;
20import com.android.dx.rop.cst.CstBaseMethodRef;
21import com.android.dx.rop.cst.CstMethodRef;
22import com.android.dx.rop.cst.CstType;
23import com.android.dx.rop.type.Prototype;
24import com.android.dx.rop.type.StdTypeList;
25import com.android.dx.rop.type.Type;
26import com.android.dx.rop.type.TypeBearer;
27import com.android.dx.rop.type.TypeList;
28
29/**
30 * Standard instances of {@link Rop}.
31 */
32public final class Rops {
33    /** {@code nop()} */
34    public static final Rop NOP =
35        new Rop(RegOps.NOP, Type.VOID, StdTypeList.EMPTY, "nop");
36
37    /** {@code r,x: int :: r = x;} */
38    public static final Rop MOVE_INT =
39        new Rop(RegOps.MOVE, Type.INT, StdTypeList.INT, "move-int");
40
41    /** {@code r,x: long :: r = x;} */
42    public static final Rop MOVE_LONG =
43        new Rop(RegOps.MOVE, Type.LONG, StdTypeList.LONG, "move-long");
44
45    /** {@code r,x: float :: r = x;} */
46    public static final Rop MOVE_FLOAT =
47        new Rop(RegOps.MOVE, Type.FLOAT, StdTypeList.FLOAT, "move-float");
48
49    /** {@code r,x: double :: r = x;} */
50    public static final Rop MOVE_DOUBLE =
51        new Rop(RegOps.MOVE, Type.DOUBLE, StdTypeList.DOUBLE, "move-double");
52
53    /** {@code r,x: Object :: r = x;} */
54    public static final Rop MOVE_OBJECT =
55        new Rop(RegOps.MOVE, Type.OBJECT, StdTypeList.OBJECT, "move-object");
56
57    /**
58     * {@code r,x: ReturnAddress :: r = x;}
59     *
60     * Note that this rop-form instruction has no dex-form equivilent and
61     * must be removed before the dex conversion.
62     */
63    public static final Rop MOVE_RETURN_ADDRESS =
64        new Rop(RegOps.MOVE, Type.RETURN_ADDRESS,
65                StdTypeList.RETURN_ADDRESS, "move-return-address");
66
67    /** {@code r,param(x): int :: r = param(x);} */
68    public static final Rop MOVE_PARAM_INT =
69        new Rop(RegOps.MOVE_PARAM, Type.INT, StdTypeList.EMPTY,
70                "move-param-int");
71
72    /** {@code r,param(x): long :: r = param(x);} */
73    public static final Rop MOVE_PARAM_LONG =
74        new Rop(RegOps.MOVE_PARAM, Type.LONG, StdTypeList.EMPTY,
75                "move-param-long");
76
77    /** {@code r,param(x): float :: r = param(x);} */
78    public static final Rop MOVE_PARAM_FLOAT =
79        new Rop(RegOps.MOVE_PARAM, Type.FLOAT, StdTypeList.EMPTY,
80                "move-param-float");
81
82    /** {@code r,param(x): double :: r = param(x);} */
83    public static final Rop MOVE_PARAM_DOUBLE =
84        new Rop(RegOps.MOVE_PARAM, Type.DOUBLE, StdTypeList.EMPTY,
85                "move-param-double");
86
87    /** {@code r,param(x): Object :: r = param(x);} */
88    public static final Rop MOVE_PARAM_OBJECT =
89        new Rop(RegOps.MOVE_PARAM, Type.OBJECT, StdTypeList.EMPTY,
90                "move-param-object");
91
92    /** {@code r, literal: int :: r = literal;} */
93    public static final Rop CONST_INT =
94        new Rop(RegOps.CONST, Type.INT, StdTypeList.EMPTY, "const-int");
95
96    /** {@code r, literal: long :: r = literal;} */
97    public static final Rop CONST_LONG =
98        new Rop(RegOps.CONST, Type.LONG, StdTypeList.EMPTY, "const-long");
99
100    /** {@code r, literal: float :: r = literal;} */
101    public static final Rop CONST_FLOAT =
102        new Rop(RegOps.CONST, Type.FLOAT, StdTypeList.EMPTY, "const-float");
103
104    /** {@code r, literal: double :: r = literal;} */
105    public static final Rop CONST_DOUBLE =
106        new Rop(RegOps.CONST, Type.DOUBLE, StdTypeList.EMPTY, "const-double");
107
108    /** {@code r, literal: Object :: r = literal;} */
109    public static final Rop CONST_OBJECT =
110        new Rop(RegOps.CONST, Type.OBJECT, StdTypeList.EMPTY,
111                Exceptions.LIST_Error, "const-object");
112
113    /** {@code r, literal: Object :: r = literal;} */
114    public static final Rop CONST_OBJECT_NOTHROW =
115        new Rop(RegOps.CONST, Type.OBJECT, StdTypeList.EMPTY,
116                "const-object-nothrow");
117
118    /** {@code goto label} */
119    public static final Rop GOTO =
120        new Rop(RegOps.GOTO, Type.VOID, StdTypeList.EMPTY, Rop.BRANCH_GOTO,
121                "goto");
122
123    /** {@code x: int :: if (x == 0) goto label} */
124    public static final Rop IF_EQZ_INT =
125        new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
126                "if-eqz-int");
127
128    /** {@code x: int :: if (x != 0) goto label} */
129    public static final Rop IF_NEZ_INT =
130        new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
131                "if-nez-int");
132
133    /** {@code x: int :: if (x < 0) goto label} */
134    public static final Rop IF_LTZ_INT =
135        new Rop(RegOps.IF_LT, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
136                "if-ltz-int");
137
138    /** {@code x: int :: if (x >= 0) goto label} */
139    public static final Rop IF_GEZ_INT =
140        new Rop(RegOps.IF_GE, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
141                "if-gez-int");
142
143    /** {@code x: int :: if (x <= 0) goto label} */
144    public static final Rop IF_LEZ_INT =
145        new Rop(RegOps.IF_LE, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
146                "if-lez-int");
147
148    /** {@code x: int :: if (x > 0) goto label} */
149    public static final Rop IF_GTZ_INT =
150        new Rop(RegOps.IF_GT, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
151                "if-gtz-int");
152
153    /** {@code x: Object :: if (x == null) goto label} */
154    public static final Rop IF_EQZ_OBJECT =
155        new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.OBJECT, Rop.BRANCH_IF,
156                "if-eqz-object");
157
158    /** {@code x: Object :: if (x != null) goto label} */
159    public static final Rop IF_NEZ_OBJECT =
160        new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.OBJECT, Rop.BRANCH_IF,
161                "if-nez-object");
162
163    /** {@code x,y: int :: if (x == y) goto label} */
164    public static final Rop IF_EQ_INT =
165        new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
166                "if-eq-int");
167
168    /** {@code x,y: int :: if (x != y) goto label} */
169    public static final Rop IF_NE_INT =
170        new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
171                "if-ne-int");
172
173    /** {@code x,y: int :: if (x < y) goto label} */
174    public static final Rop IF_LT_INT =
175        new Rop(RegOps.IF_LT, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
176                "if-lt-int");
177
178    /** {@code x,y: int :: if (x >= y) goto label} */
179    public static final Rop IF_GE_INT =
180        new Rop(RegOps.IF_GE, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
181                "if-ge-int");
182
183    /** {@code x,y: int :: if (x <= y) goto label} */
184    public static final Rop IF_LE_INT =
185        new Rop(RegOps.IF_LE, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
186                "if-le-int");
187
188    /** {@code x,y: int :: if (x > y) goto label} */
189    public static final Rop IF_GT_INT =
190        new Rop(RegOps.IF_GT, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
191                "if-gt-int");
192
193    /** {@code x,y: Object :: if (x == y) goto label} */
194    public static final Rop IF_EQ_OBJECT =
195        new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.OBJECT_OBJECT,
196                Rop.BRANCH_IF, "if-eq-object");
197
198    /** {@code x,y: Object :: if (x != y) goto label} */
199    public static final Rop IF_NE_OBJECT =
200        new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.OBJECT_OBJECT,
201                Rop.BRANCH_IF, "if-ne-object");
202
203    /** {@code x: int :: goto switchtable[x]} */
204    public static final Rop SWITCH =
205        new Rop(RegOps.SWITCH, Type.VOID, StdTypeList.INT, Rop.BRANCH_SWITCH,
206                "switch");
207
208    /** {@code r,x,y: int :: r = x + y;} */
209    public static final Rop ADD_INT =
210        new Rop(RegOps.ADD, Type.INT, StdTypeList.INT_INT, "add-int");
211
212    /** {@code r,x,y: long :: r = x + y;} */
213    public static final Rop ADD_LONG =
214        new Rop(RegOps.ADD, Type.LONG, StdTypeList.LONG_LONG, "add-long");
215
216    /** {@code r,x,y: float :: r = x + y;} */
217    public static final Rop ADD_FLOAT =
218        new Rop(RegOps.ADD, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "add-float");
219
220    /** {@code r,x,y: double :: r = x + y;} */
221    public static final Rop ADD_DOUBLE =
222        new Rop(RegOps.ADD, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
223                Rop.BRANCH_NONE, "add-double");
224
225    /** {@code r,x,y: int :: r = x - y;} */
226    public static final Rop SUB_INT =
227        new Rop(RegOps.SUB, Type.INT, StdTypeList.INT_INT, "sub-int");
228
229    /** {@code r,x,y: long :: r = x - y;} */
230    public static final Rop SUB_LONG =
231        new Rop(RegOps.SUB, Type.LONG, StdTypeList.LONG_LONG, "sub-long");
232
233    /** {@code r,x,y: float :: r = x - y;} */
234    public static final Rop SUB_FLOAT =
235        new Rop(RegOps.SUB, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "sub-float");
236
237    /** {@code r,x,y: double :: r = x - y;} */
238    public static final Rop SUB_DOUBLE =
239        new Rop(RegOps.SUB, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
240                Rop.BRANCH_NONE, "sub-double");
241
242    /** {@code r,x,y: int :: r = x * y;} */
243    public static final Rop MUL_INT =
244        new Rop(RegOps.MUL, Type.INT, StdTypeList.INT_INT, "mul-int");
245
246    /** {@code r,x,y: long :: r = x * y;} */
247    public static final Rop MUL_LONG =
248        new Rop(RegOps.MUL, Type.LONG, StdTypeList.LONG_LONG, "mul-long");
249
250    /** {@code r,x,y: float :: r = x * y;} */
251    public static final Rop MUL_FLOAT =
252        new Rop(RegOps.MUL, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "mul-float");
253
254    /** {@code r,x,y: double :: r = x * y;} */
255    public static final Rop MUL_DOUBLE =
256        new Rop(RegOps.MUL, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
257                Rop.BRANCH_NONE, "mul-double");
258
259    /** {@code r,x,y: int :: r = x / y;} */
260    public static final Rop DIV_INT =
261        new Rop(RegOps.DIV, Type.INT, StdTypeList.INT_INT,
262                Exceptions.LIST_Error_ArithmeticException, "div-int");
263
264    /** {@code r,x,y: long :: r = x / y;} */
265    public static final Rop DIV_LONG =
266        new Rop(RegOps.DIV, Type.LONG, StdTypeList.LONG_LONG,
267                Exceptions.LIST_Error_ArithmeticException, "div-long");
268
269    /** {@code r,x,y: float :: r = x / y;} */
270    public static final Rop DIV_FLOAT =
271        new Rop(RegOps.DIV, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "div-float");
272
273    /** {@code r,x,y: double :: r = x / y;} */
274    public static final Rop DIV_DOUBLE =
275        new Rop(RegOps.DIV, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
276                "div-double");
277
278    /** {@code r,x,y: int :: r = x % y;} */
279    public static final Rop REM_INT =
280        new Rop(RegOps.REM, Type.INT, StdTypeList.INT_INT,
281                Exceptions.LIST_Error_ArithmeticException, "rem-int");
282
283    /** {@code r,x,y: long :: r = x % y;} */
284    public static final Rop REM_LONG =
285        new Rop(RegOps.REM, Type.LONG, StdTypeList.LONG_LONG,
286                Exceptions.LIST_Error_ArithmeticException, "rem-long");
287
288    /** {@code r,x,y: float :: r = x % y;} */
289    public static final Rop REM_FLOAT =
290        new Rop(RegOps.REM, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "rem-float");
291
292    /** {@code r,x,y: double :: r = x % y;} */
293    public static final Rop REM_DOUBLE =
294        new Rop(RegOps.REM, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
295                "rem-double");
296
297    /** {@code r,x: int :: r = -x;} */
298    public static final Rop NEG_INT =
299        new Rop(RegOps.NEG, Type.INT, StdTypeList.INT, "neg-int");
300
301    /** {@code r,x: long :: r = -x;} */
302    public static final Rop NEG_LONG =
303        new Rop(RegOps.NEG, Type.LONG, StdTypeList.LONG, "neg-long");
304
305    /** {@code r,x: float :: r = -x;} */
306    public static final Rop NEG_FLOAT =
307        new Rop(RegOps.NEG, Type.FLOAT, StdTypeList.FLOAT, "neg-float");
308
309    /** {@code r,x: double :: r = -x;} */
310    public static final Rop NEG_DOUBLE =
311        new Rop(RegOps.NEG, Type.DOUBLE, StdTypeList.DOUBLE, "neg-double");
312
313    /** {@code r,x,y: int :: r = x & y;} */
314    public static final Rop AND_INT =
315        new Rop(RegOps.AND, Type.INT, StdTypeList.INT_INT, "and-int");
316
317    /** {@code r,x,y: long :: r = x & y;} */
318    public static final Rop AND_LONG =
319        new Rop(RegOps.AND, Type.LONG, StdTypeList.LONG_LONG, "and-long");
320
321    /** {@code r,x,y: int :: r = x | y;} */
322    public static final Rop OR_INT =
323        new Rop(RegOps.OR, Type.INT, StdTypeList.INT_INT, "or-int");
324
325    /** {@code r,x,y: long :: r = x | y;} */
326    public static final Rop OR_LONG =
327        new Rop(RegOps.OR, Type.LONG, StdTypeList.LONG_LONG, "or-long");
328
329    /** {@code r,x,y: int :: r = x ^ y;} */
330    public static final Rop XOR_INT =
331        new Rop(RegOps.XOR, Type.INT, StdTypeList.INT_INT, "xor-int");
332
333    /** {@code r,x,y: long :: r = x ^ y;} */
334    public static final Rop XOR_LONG =
335        new Rop(RegOps.XOR, Type.LONG, StdTypeList.LONG_LONG, "xor-long");
336
337    /** {@code r,x,y: int :: r = x << y;} */
338    public static final Rop SHL_INT =
339        new Rop(RegOps.SHL, Type.INT, StdTypeList.INT_INT, "shl-int");
340
341    /** {@code r,x: long; y: int :: r = x << y;} */
342    public static final Rop SHL_LONG =
343        new Rop(RegOps.SHL, Type.LONG, StdTypeList.LONG_INT, "shl-long");
344
345    /** {@code r,x,y: int :: r = x >> y;} */
346    public static final Rop SHR_INT =
347        new Rop(RegOps.SHR, Type.INT, StdTypeList.INT_INT, "shr-int");
348
349    /** {@code r,x: long; y: int :: r = x >> y;} */
350    public static final Rop SHR_LONG =
351        new Rop(RegOps.SHR, Type.LONG, StdTypeList.LONG_INT, "shr-long");
352
353    /** {@code r,x,y: int :: r = x >>> y;} */
354    public static final Rop USHR_INT =
355        new Rop(RegOps.USHR, Type.INT, StdTypeList.INT_INT, "ushr-int");
356
357    /** {@code r,x: long; y: int :: r = x >>> y;} */
358    public static final Rop USHR_LONG =
359        new Rop(RegOps.USHR, Type.LONG, StdTypeList.LONG_INT, "ushr-long");
360
361    /** {@code r,x: int :: r = ~x;} */
362    public static final Rop NOT_INT =
363        new Rop(RegOps.NOT, Type.INT, StdTypeList.INT, "not-int");
364
365    /** {@code r,x: long :: r = ~x;} */
366    public static final Rop NOT_LONG =
367        new Rop(RegOps.NOT, Type.LONG, StdTypeList.LONG, "not-long");
368
369    /** {@code r,x,c: int :: r = x + c;} */
370    public static final Rop ADD_CONST_INT =
371        new Rop(RegOps.ADD, Type.INT, StdTypeList.INT, "add-const-int");
372
373    /** {@code r,x,c: long :: r = x + c;} */
374    public static final Rop ADD_CONST_LONG =
375        new Rop(RegOps.ADD, Type.LONG, StdTypeList.LONG, "add-const-long");
376
377    /** {@code r,x,c: float :: r = x + c;} */
378    public static final Rop ADD_CONST_FLOAT =
379        new Rop(RegOps.ADD, Type.FLOAT, StdTypeList.FLOAT, "add-const-float");
380
381    /** {@code r,x,c: double :: r = x + c;} */
382    public static final Rop ADD_CONST_DOUBLE =
383        new Rop(RegOps.ADD, Type.DOUBLE, StdTypeList.DOUBLE,
384                "add-const-double");
385
386    /** {@code r,x,c: int :: r = x - c;} */
387    public static final Rop SUB_CONST_INT =
388        new Rop(RegOps.SUB, Type.INT, StdTypeList.INT, "sub-const-int");
389
390    /** {@code r,x,c: long :: r = x - c;} */
391    public static final Rop SUB_CONST_LONG =
392        new Rop(RegOps.SUB, Type.LONG, StdTypeList.LONG, "sub-const-long");
393
394    /** {@code r,x,c: float :: r = x - c;} */
395    public static final Rop SUB_CONST_FLOAT =
396        new Rop(RegOps.SUB, Type.FLOAT, StdTypeList.FLOAT, "sub-const-float");
397
398    /** {@code r,x,c: double :: r = x - c;} */
399    public static final Rop SUB_CONST_DOUBLE =
400        new Rop(RegOps.SUB, Type.DOUBLE, StdTypeList.DOUBLE,
401                "sub-const-double");
402
403    /** {@code r,x,c: int :: r = x * c;} */
404    public static final Rop MUL_CONST_INT =
405        new Rop(RegOps.MUL, Type.INT, StdTypeList.INT, "mul-const-int");
406
407    /** {@code r,x,c: long :: r = x * c;} */
408    public static final Rop MUL_CONST_LONG =
409        new Rop(RegOps.MUL, Type.LONG, StdTypeList.LONG, "mul-const-long");
410
411    /** {@code r,x,c: float :: r = x * c;} */
412    public static final Rop MUL_CONST_FLOAT =
413        new Rop(RegOps.MUL, Type.FLOAT, StdTypeList.FLOAT, "mul-const-float");
414
415    /** {@code r,x,c: double :: r = x * c;} */
416    public static final Rop MUL_CONST_DOUBLE =
417        new Rop(RegOps.MUL, Type.DOUBLE, StdTypeList.DOUBLE,
418                "mul-const-double");
419
420    /** {@code r,x,c: int :: r = x / c;} */
421    public static final Rop DIV_CONST_INT =
422        new Rop(RegOps.DIV, Type.INT, StdTypeList.INT,
423                Exceptions.LIST_Error_ArithmeticException, "div-const-int");
424
425    /** {@code r,x,c: long :: r = x / c;} */
426    public static final Rop DIV_CONST_LONG =
427        new Rop(RegOps.DIV, Type.LONG, StdTypeList.LONG,
428                Exceptions.LIST_Error_ArithmeticException, "div-const-long");
429
430    /** {@code r,x,c: float :: r = x / c;} */
431    public static final Rop DIV_CONST_FLOAT =
432        new Rop(RegOps.DIV, Type.FLOAT, StdTypeList.FLOAT, "div-const-float");
433
434    /** {@code r,x,c: double :: r = x / c;} */
435    public static final Rop DIV_CONST_DOUBLE =
436        new Rop(RegOps.DIV, Type.DOUBLE, StdTypeList.DOUBLE,
437                "div-const-double");
438
439    /** {@code r,x,c: int :: r = x % c;} */
440    public static final Rop REM_CONST_INT =
441        new Rop(RegOps.REM, Type.INT, StdTypeList.INT,
442                Exceptions.LIST_Error_ArithmeticException, "rem-const-int");
443
444    /** {@code r,x,c: long :: r = x % c;} */
445    public static final Rop REM_CONST_LONG =
446        new Rop(RegOps.REM, Type.LONG, StdTypeList.LONG,
447                Exceptions.LIST_Error_ArithmeticException, "rem-const-long");
448
449    /** {@code r,x,c: float :: r = x % c;} */
450    public static final Rop REM_CONST_FLOAT =
451        new Rop(RegOps.REM, Type.FLOAT, StdTypeList.FLOAT, "rem-const-float");
452
453    /** {@code r,x,c: double :: r = x % c;} */
454    public static final Rop REM_CONST_DOUBLE =
455        new Rop(RegOps.REM, Type.DOUBLE, StdTypeList.DOUBLE,
456                "rem-const-double");
457
458    /** {@code r,x,c: int :: r = x & c;} */
459    public static final Rop AND_CONST_INT =
460        new Rop(RegOps.AND, Type.INT, StdTypeList.INT, "and-const-int");
461
462    /** {@code r,x,c: long :: r = x & c;} */
463    public static final Rop AND_CONST_LONG =
464        new Rop(RegOps.AND, Type.LONG, StdTypeList.LONG, "and-const-long");
465
466    /** {@code r,x,c: int :: r = x | c;} */
467    public static final Rop OR_CONST_INT =
468        new Rop(RegOps.OR, Type.INT, StdTypeList.INT, "or-const-int");
469
470    /** {@code r,x,c: long :: r = x | c;} */
471    public static final Rop OR_CONST_LONG =
472        new Rop(RegOps.OR, Type.LONG, StdTypeList.LONG, "or-const-long");
473
474    /** {@code r,x,c: int :: r = x ^ c;} */
475    public static final Rop XOR_CONST_INT =
476        new Rop(RegOps.XOR, Type.INT, StdTypeList.INT, "xor-const-int");
477
478    /** {@code r,x,c: long :: r = x ^ c;} */
479    public static final Rop XOR_CONST_LONG =
480        new Rop(RegOps.XOR, Type.LONG, StdTypeList.LONG, "xor-const-long");
481
482    /** {@code r,x,c: int :: r = x << c;} */
483    public static final Rop SHL_CONST_INT =
484        new Rop(RegOps.SHL, Type.INT, StdTypeList.INT, "shl-const-int");
485
486    /** {@code r,x: long; c: int :: r = x << c;} */
487    public static final Rop SHL_CONST_LONG =
488        new Rop(RegOps.SHL, Type.LONG, StdTypeList.INT, "shl-const-long");
489
490    /** {@code r,x,c: int :: r = x >> c;} */
491    public static final Rop SHR_CONST_INT =
492        new Rop(RegOps.SHR, Type.INT, StdTypeList.INT, "shr-const-int");
493
494    /** {@code r,x: long; c: int :: r = x >> c;} */
495    public static final Rop SHR_CONST_LONG =
496        new Rop(RegOps.SHR, Type.LONG, StdTypeList.INT, "shr-const-long");
497
498    /** {@code r,x,c: int :: r = x >>> c;} */
499    public static final Rop USHR_CONST_INT =
500        new Rop(RegOps.USHR, Type.INT, StdTypeList.INT, "ushr-const-int");
501
502    /** {@code r,x: long; c: int :: r = x >>> c;} */
503    public static final Rop USHR_CONST_LONG =
504        new Rop(RegOps.USHR, Type.LONG, StdTypeList.INT, "ushr-const-long");
505
506    /** {@code r: int; x,y: long :: r = cmp(x, y);} */
507    public static final Rop CMPL_LONG =
508        new Rop(RegOps.CMPL, Type.INT, StdTypeList.LONG_LONG, "cmpl-long");
509
510    /** {@code r: int; x,y: float :: r = cmpl(x, y);} */
511    public static final Rop CMPL_FLOAT =
512        new Rop(RegOps.CMPL, Type.INT, StdTypeList.FLOAT_FLOAT, "cmpl-float");
513
514    /** {@code r: int; x,y: double :: r = cmpl(x, y);} */
515    public static final Rop CMPL_DOUBLE =
516        new Rop(RegOps.CMPL, Type.INT, StdTypeList.DOUBLE_DOUBLE,
517                "cmpl-double");
518
519    /** {@code r: int; x,y: float :: r = cmpg(x, y);} */
520    public static final Rop CMPG_FLOAT =
521        new Rop(RegOps.CMPG, Type.INT, StdTypeList.FLOAT_FLOAT, "cmpg-float");
522
523    /** {@code r: int; x,y: double :: r = cmpg(x, y);} */
524    public static final Rop CMPG_DOUBLE =
525        new Rop(RegOps.CMPG, Type.INT, StdTypeList.DOUBLE_DOUBLE,
526                "cmpg-double");
527
528    /** {@code r: int; x: long :: r = (int) x} */
529    public static final Rop CONV_L2I =
530        new Rop(RegOps.CONV, Type.INT, StdTypeList.LONG, "conv-l2i");
531
532    /** {@code r: int; x: float :: r = (int) x} */
533    public static final Rop CONV_F2I =
534        new Rop(RegOps.CONV, Type.INT, StdTypeList.FLOAT, "conv-f2i");
535
536    /** {@code r: int; x: double :: r = (int) x} */
537    public static final Rop CONV_D2I =
538        new Rop(RegOps.CONV, Type.INT, StdTypeList.DOUBLE, "conv-d2i");
539
540    /** {@code r: long; x: int :: r = (long) x} */
541    public static final Rop CONV_I2L =
542        new Rop(RegOps.CONV, Type.LONG, StdTypeList.INT, "conv-i2l");
543
544    /** {@code r: long; x: float :: r = (long) x} */
545    public static final Rop CONV_F2L =
546        new Rop(RegOps.CONV, Type.LONG, StdTypeList.FLOAT, "conv-f2l");
547
548    /** {@code r: long; x: double :: r = (long) x} */
549    public static final Rop CONV_D2L =
550        new Rop(RegOps.CONV, Type.LONG, StdTypeList.DOUBLE, "conv-d2l");
551
552    /** {@code r: float; x: int :: r = (float) x} */
553    public static final Rop CONV_I2F =
554        new Rop(RegOps.CONV, Type.FLOAT, StdTypeList.INT, "conv-i2f");
555
556    /** {@code r: float; x: long :: r = (float) x} */
557    public static final Rop CONV_L2F =
558        new Rop(RegOps.CONV, Type.FLOAT, StdTypeList.LONG, "conv-l2f");
559
560    /** {@code r: float; x: double :: r = (float) x} */
561    public static final Rop CONV_D2F =
562        new Rop(RegOps.CONV, Type.FLOAT, StdTypeList.DOUBLE, "conv-d2f");
563
564    /** {@code r: double; x: int :: r = (double) x} */
565    public static final Rop CONV_I2D =
566        new Rop(RegOps.CONV, Type.DOUBLE, StdTypeList.INT, "conv-i2d");
567
568    /** {@code r: double; x: long :: r = (double) x} */
569    public static final Rop CONV_L2D =
570        new Rop(RegOps.CONV, Type.DOUBLE, StdTypeList.LONG, "conv-l2d");
571
572    /** {@code r: double; x: float :: r = (double) x} */
573    public static final Rop CONV_F2D =
574        new Rop(RegOps.CONV, Type.DOUBLE, StdTypeList.FLOAT, "conv-f2d");
575
576    /**
577     * {@code r,x: int :: r = (x << 24) >> 24} (Java-style
578     * convert int to byte)
579     */
580    public static final Rop TO_BYTE =
581        new Rop(RegOps.TO_BYTE, Type.INT, StdTypeList.INT, "to-byte");
582
583    /**
584     * {@code r,x: int :: r = x & 0xffff} (Java-style
585     * convert int to char)
586     */
587    public static final Rop TO_CHAR =
588        new Rop(RegOps.TO_CHAR, Type.INT, StdTypeList.INT, "to-char");
589
590    /**
591     * {@code r,x: int :: r = (x << 16) >> 16} (Java-style
592     * convert int to short)
593     */
594    public static final Rop TO_SHORT =
595        new Rop(RegOps.TO_SHORT, Type.INT, StdTypeList.INT, "to-short");
596
597    /** {@code return void} */
598    public static final Rop RETURN_VOID =
599        new Rop(RegOps.RETURN, Type.VOID, StdTypeList.EMPTY, Rop.BRANCH_RETURN,
600                "return-void");
601
602    /** {@code x: int; return x} */
603    public static final Rop RETURN_INT =
604        new Rop(RegOps.RETURN, Type.VOID, StdTypeList.INT, Rop.BRANCH_RETURN,
605                "return-int");
606
607    /** {@code x: long; return x} */
608    public static final Rop RETURN_LONG =
609        new Rop(RegOps.RETURN, Type.VOID, StdTypeList.LONG, Rop.BRANCH_RETURN,
610                "return-long");
611
612    /** {@code x: float; return x} */
613    public static final Rop RETURN_FLOAT =
614        new Rop(RegOps.RETURN, Type.VOID, StdTypeList.FLOAT, Rop.BRANCH_RETURN,
615                "return-float");
616
617    /** {@code x: double; return x} */
618    public static final Rop RETURN_DOUBLE =
619        new Rop(RegOps.RETURN, Type.VOID, StdTypeList.DOUBLE,
620                Rop.BRANCH_RETURN, "return-double");
621
622    /** {@code x: Object; return x} */
623    public static final Rop RETURN_OBJECT =
624        new Rop(RegOps.RETURN, Type.VOID, StdTypeList.OBJECT,
625                Rop.BRANCH_RETURN, "return-object");
626
627    /** {@code T: any type; r: int; x: T[]; :: r = x.length} */
628    public static final Rop ARRAY_LENGTH =
629        new Rop(RegOps.ARRAY_LENGTH, Type.INT, StdTypeList.OBJECT,
630                Exceptions.LIST_Error_NullPointerException, "array-length");
631
632    /** {@code x: Throwable :: throw(x)} */
633    public static final Rop THROW =
634        new Rop(RegOps.THROW, Type.VOID, StdTypeList.THROWABLE,
635                StdTypeList.THROWABLE, "throw");
636
637    /** {@code x: Object :: monitorenter(x)} */
638    public static final Rop MONITOR_ENTER =
639        new Rop(RegOps.MONITOR_ENTER, Type.VOID, StdTypeList.OBJECT,
640                Exceptions.LIST_Error_NullPointerException, "monitor-enter");
641
642    /** {@code x: Object :: monitorexit(x)} */
643    public static final Rop MONITOR_EXIT =
644        new Rop(RegOps.MONITOR_EXIT, Type.VOID, StdTypeList.OBJECT,
645                Exceptions.LIST_Error_Null_IllegalMonitorStateException,
646                "monitor-exit");
647
648    /** {@code r,y: int; x: int[] :: r = x[y]} */
649    public static final Rop AGET_INT =
650        new Rop(RegOps.AGET, Type.INT, StdTypeList.INTARR_INT,
651                Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
652                "aget-int");
653
654    /** {@code r: long; x: long[]; y: int :: r = x[y]} */
655    public static final Rop AGET_LONG =
656        new Rop(RegOps.AGET, Type.LONG, StdTypeList.LONGARR_INT,
657                Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
658                "aget-long");
659
660    /** {@code r: float; x: float[]; y: int :: r = x[y]} */
661    public static final Rop AGET_FLOAT =
662        new Rop(RegOps.AGET, Type.FLOAT, StdTypeList.FLOATARR_INT,
663                Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
664                "aget-float");
665
666    /** {@code r: double; x: double[]; y: int :: r = x[y]} */
667    public static final Rop AGET_DOUBLE =
668        new Rop(RegOps.AGET, Type.DOUBLE, StdTypeList.DOUBLEARR_INT,
669                Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
670                "aget-double");
671
672    /** {@code r: Object; x: Object[]; y: int :: r = x[y]} */
673    public static final Rop AGET_OBJECT =
674        new Rop(RegOps.AGET, Type.OBJECT, StdTypeList.OBJECTARR_INT,
675                Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
676                "aget-object");
677
678    /** {@code r: boolean; x: boolean[]; y: int :: r = x[y]} */
679    public static final Rop AGET_BOOLEAN =
680        new Rop(RegOps.AGET, Type.INT, StdTypeList.BOOLEANARR_INT,
681                Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
682                "aget-boolean");
683
684    /** {@code r: byte; x: byte[]; y: int :: r = x[y]} */
685    public static final Rop AGET_BYTE =
686        new Rop(RegOps.AGET, Type.INT, StdTypeList.BYTEARR_INT,
687                Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aget-byte");
688
689    /** {@code r: char; x: char[]; y: int :: r = x[y]} */
690    public static final Rop AGET_CHAR =
691        new Rop(RegOps.AGET, Type.INT, StdTypeList.CHARARR_INT,
692                Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aget-char");
693
694    /** {@code r: short; x: short[]; y: int :: r = x[y]} */
695    public static final Rop AGET_SHORT =
696        new Rop(RegOps.AGET, Type.INT, StdTypeList.SHORTARR_INT,
697                Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
698                "aget-short");
699
700    /** {@code x,z: int; y: int[] :: y[z] = x} */
701    public static final Rop APUT_INT =
702        new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_INTARR_INT,
703                Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aput-int");
704
705    /** {@code x: long; y: long[]; z: int :: y[z] = x} */
706    public static final Rop APUT_LONG =
707        new Rop(RegOps.APUT, Type.VOID, StdTypeList.LONG_LONGARR_INT,
708                Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aput-long");
709
710    /** {@code x: float; y: float[]; z: int :: y[z] = x} */
711    public static final Rop APUT_FLOAT =
712        new Rop(RegOps.APUT, Type.VOID, StdTypeList.FLOAT_FLOATARR_INT,
713                Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
714                "aput-float");
715
716    /** {@code x: double; y: double[]; z: int :: y[z] = x} */
717    public static final Rop APUT_DOUBLE =
718        new Rop(RegOps.APUT, Type.VOID, StdTypeList.DOUBLE_DOUBLEARR_INT,
719                Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
720                "aput-double");
721
722    /** {@code x: Object; y: Object[]; z: int :: y[z] = x} */
723    public static final Rop APUT_OBJECT =
724        new Rop(RegOps.APUT, Type.VOID, StdTypeList.OBJECT_OBJECTARR_INT,
725                Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore,
726                "aput-object");
727
728    /** {@code x: boolean; y: boolean[]; z: int :: y[z] = x} */
729    public static final Rop APUT_BOOLEAN =
730        new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_BOOLEANARR_INT,
731                Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore,
732                "aput-boolean");
733
734    /** {@code x: byte; y: byte[]; z: int :: y[z] = x} */
735    public static final Rop APUT_BYTE =
736        new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_BYTEARR_INT,
737                Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore, "aput-byte");
738
739    /** {@code x: char; y: char[]; z: int :: y[z] = x} */
740    public static final Rop APUT_CHAR =
741        new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_CHARARR_INT,
742                Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore, "aput-char");
743
744    /** {@code x: short; y: short[]; z: int :: y[z] = x} */
745    public static final Rop APUT_SHORT =
746        new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_SHORTARR_INT,
747                Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore,
748                "aput-short");
749
750    /**
751     * {@code T: any non-array object type :: r =
752     * alloc(T)} (allocate heap space for an object)
753     */
754    public static final Rop NEW_INSTANCE =
755        new Rop(RegOps.NEW_INSTANCE, Type.OBJECT, StdTypeList.EMPTY,
756                Exceptions.LIST_Error, "new-instance");
757
758    /** {@code r: int[]; x: int :: r = new int[x]} */
759    public static final Rop NEW_ARRAY_INT =
760        new Rop(RegOps.NEW_ARRAY, Type.INT_ARRAY, StdTypeList.INT,
761                Exceptions.LIST_Error_NegativeArraySizeException,
762                "new-array-int");
763
764    /** {@code r: long[]; x: int :: r = new long[x]} */
765    public static final Rop NEW_ARRAY_LONG =
766        new Rop(RegOps.NEW_ARRAY, Type.LONG_ARRAY, StdTypeList.INT,
767                Exceptions.LIST_Error_NegativeArraySizeException,
768                "new-array-long");
769
770    /** {@code r: float[]; x: int :: r = new float[x]} */
771    public static final Rop NEW_ARRAY_FLOAT =
772        new Rop(RegOps.NEW_ARRAY, Type.FLOAT_ARRAY, StdTypeList.INT,
773                Exceptions.LIST_Error_NegativeArraySizeException,
774                "new-array-float");
775
776    /** {@code r: double[]; x: int :: r = new double[x]} */
777    public static final Rop NEW_ARRAY_DOUBLE =
778        new Rop(RegOps.NEW_ARRAY, Type.DOUBLE_ARRAY, StdTypeList.INT,
779                Exceptions.LIST_Error_NegativeArraySizeException,
780                "new-array-double");
781
782    /** {@code r: boolean[]; x: int :: r = new boolean[x]} */
783    public static final Rop NEW_ARRAY_BOOLEAN =
784        new Rop(RegOps.NEW_ARRAY, Type.BOOLEAN_ARRAY, StdTypeList.INT,
785                Exceptions.LIST_Error_NegativeArraySizeException,
786                "new-array-boolean");
787
788    /** {@code r: byte[]; x: int :: r = new byte[x]} */
789    public static final Rop NEW_ARRAY_BYTE =
790        new Rop(RegOps.NEW_ARRAY, Type.BYTE_ARRAY, StdTypeList.INT,
791                Exceptions.LIST_Error_NegativeArraySizeException,
792                "new-array-byte");
793
794    /** {@code r: char[]; x: int :: r = new char[x]} */
795    public static final Rop NEW_ARRAY_CHAR =
796        new Rop(RegOps.NEW_ARRAY, Type.CHAR_ARRAY, StdTypeList.INT,
797                Exceptions.LIST_Error_NegativeArraySizeException,
798                "new-array-char");
799
800    /** {@code r: short[]; x: int :: r = new short[x]} */
801    public static final Rop NEW_ARRAY_SHORT =
802        new Rop(RegOps.NEW_ARRAY, Type.SHORT_ARRAY, StdTypeList.INT,
803                Exceptions.LIST_Error_NegativeArraySizeException,
804                "new-array-short");
805
806    /**
807     * {@code T: any non-array object type; x: Object :: (T) x} (can
808     * throw {@code ClassCastException})
809     */
810    public static final Rop CHECK_CAST =
811        new Rop(RegOps.CHECK_CAST, Type.VOID, StdTypeList.OBJECT,
812                Exceptions.LIST_Error_ClassCastException, "check-cast");
813
814    /**
815     * {@code T: any non-array object type; x: Object :: x instanceof
816     * T}. Note: This is listed as throwing {@code Error}
817     * explicitly because the op <i>can</i> throw, but there are no
818     * other predefined exceptions for it.
819     */
820    public static final Rop INSTANCE_OF =
821        new Rop(RegOps.INSTANCE_OF, Type.INT, StdTypeList.OBJECT,
822                Exceptions.LIST_Error, "instance-of");
823
824    /**
825     * {@code r: int; x: Object; f: instance field spec of
826     * type int :: r = x.f}
827     */
828    public static final Rop GET_FIELD_INT =
829        new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
830                Exceptions.LIST_Error_NullPointerException, "get-field-int");
831
832    /**
833     * {@code r: long; x: Object; f: instance field spec of
834     * type long :: r = x.f}
835     */
836    public static final Rop GET_FIELD_LONG =
837        new Rop(RegOps.GET_FIELD, Type.LONG, StdTypeList.OBJECT,
838                Exceptions.LIST_Error_NullPointerException, "get-field-long");
839
840    /**
841     * {@code r: float; x: Object; f: instance field spec of
842     * type float :: r = x.f}
843     */
844    public static final Rop GET_FIELD_FLOAT =
845        new Rop(RegOps.GET_FIELD, Type.FLOAT, StdTypeList.OBJECT,
846                Exceptions.LIST_Error_NullPointerException,
847                "get-field-float");
848
849    /**
850     * {@code r: double; x: Object; f: instance field spec of
851     * type double :: r = x.f}
852     */
853    public static final Rop GET_FIELD_DOUBLE =
854        new Rop(RegOps.GET_FIELD, Type.DOUBLE, StdTypeList.OBJECT,
855                Exceptions.LIST_Error_NullPointerException,
856                "get-field-double");
857
858    /**
859     * {@code r: Object; x: Object; f: instance field spec of
860     * type Object :: r = x.f}
861     */
862    public static final Rop GET_FIELD_OBJECT =
863        new Rop(RegOps.GET_FIELD, Type.OBJECT, StdTypeList.OBJECT,
864                Exceptions.LIST_Error_NullPointerException,
865                "get-field-object");
866
867    /**
868     * {@code r: boolean; x: Object; f: instance field spec of
869     * type boolean :: r = x.f}
870     */
871    public static final Rop GET_FIELD_BOOLEAN =
872        new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
873                Exceptions.LIST_Error_NullPointerException,
874                "get-field-boolean");
875
876    /**
877     * {@code r: byte; x: Object; f: instance field spec of
878     * type byte :: r = x.f}
879     */
880    public static final Rop GET_FIELD_BYTE =
881        new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
882                Exceptions.LIST_Error_NullPointerException,
883                "get-field-byte");
884
885    /**
886     * {@code r: char; x: Object; f: instance field spec of
887     * type char :: r = x.f}
888     */
889    public static final Rop GET_FIELD_CHAR =
890        new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
891                Exceptions.LIST_Error_NullPointerException,
892                "get-field-char");
893
894    /**
895     * {@code r: short; x: Object; f: instance field spec of
896     * type short :: r = x.f}
897     */
898    public static final Rop GET_FIELD_SHORT =
899        new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
900                Exceptions.LIST_Error_NullPointerException,
901                "get-field-short");
902
903    /** {@code r: int; f: static field spec of type int :: r = f} */
904    public static final Rop GET_STATIC_INT =
905        new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
906                Exceptions.LIST_Error, "get-static-int");
907
908    /** {@code r: long; f: static field spec of type long :: r = f} */
909    public static final Rop GET_STATIC_LONG =
910        new Rop(RegOps.GET_STATIC, Type.LONG, StdTypeList.EMPTY,
911                Exceptions.LIST_Error, "get-static-long");
912
913    /** {@code r: float; f: static field spec of type float :: r = f} */
914    public static final Rop GET_STATIC_FLOAT =
915        new Rop(RegOps.GET_STATIC, Type.FLOAT, StdTypeList.EMPTY,
916                Exceptions.LIST_Error, "get-static-float");
917
918    /** {@code r: double; f: static field spec of type double :: r = f} */
919    public static final Rop GET_STATIC_DOUBLE =
920        new Rop(RegOps.GET_STATIC, Type.DOUBLE, StdTypeList.EMPTY,
921                Exceptions.LIST_Error, "get-static-double");
922
923    /** {@code r: Object; f: static field spec of type Object :: r = f} */
924    public static final Rop GET_STATIC_OBJECT =
925        new Rop(RegOps.GET_STATIC, Type.OBJECT, StdTypeList.EMPTY,
926                Exceptions.LIST_Error, "get-static-object");
927
928    /** {@code r: boolean; f: static field spec of type boolean :: r = f} */
929    public static final Rop GET_STATIC_BOOLEAN =
930        new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
931                Exceptions.LIST_Error, "get-field-boolean");
932
933    /** {@code r: byte; f: static field spec of type byte :: r = f} */
934    public static final Rop GET_STATIC_BYTE =
935        new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
936                Exceptions.LIST_Error, "get-field-byte");
937
938    /** {@code r: char; f: static field spec of type char :: r = f} */
939    public static final Rop GET_STATIC_CHAR =
940        new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
941                Exceptions.LIST_Error, "get-field-char");
942
943    /** {@code r: short; f: static field spec of type short :: r = f} */
944    public static final Rop GET_STATIC_SHORT =
945        new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
946                Exceptions.LIST_Error, "get-field-short");
947
948    /**
949     * {@code x: int; y: Object; f: instance field spec of type
950     * int :: y.f = x}
951     */
952    public static final Rop PUT_FIELD_INT =
953        new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
954                Exceptions.LIST_Error_NullPointerException, "put-field-int");
955
956    /**
957     * {@code x: long; y: Object; f: instance field spec of type
958     * long :: y.f = x}
959     */
960    public static final Rop PUT_FIELD_LONG =
961        new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.LONG_OBJECT,
962                Exceptions.LIST_Error_NullPointerException, "put-field-long");
963
964    /**
965     * {@code x: float; y: Object; f: instance field spec of type
966     * float :: y.f = x}
967     */
968    public static final Rop PUT_FIELD_FLOAT =
969        new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.FLOAT_OBJECT,
970                Exceptions.LIST_Error_NullPointerException,
971                "put-field-float");
972
973    /**
974     * {@code x: double; y: Object; f: instance field spec of type
975     * double :: y.f = x}
976     */
977    public static final Rop PUT_FIELD_DOUBLE =
978        new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.DOUBLE_OBJECT,
979                Exceptions.LIST_Error_NullPointerException,
980                "put-field-double");
981
982    /**
983     * {@code x: Object; y: Object; f: instance field spec of type
984     * Object :: y.f = x}
985     */
986    public static final Rop PUT_FIELD_OBJECT =
987        new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.OBJECT_OBJECT,
988                Exceptions.LIST_Error_NullPointerException,
989                "put-field-object");
990
991    /**
992     * {@code x: int; y: Object; f: instance field spec of type
993     * boolean :: y.f = x}
994     */
995    public static final Rop PUT_FIELD_BOOLEAN =
996        new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
997                Exceptions.LIST_Error_NullPointerException,
998                "put-field-boolean");
999
1000    /**
1001     * {@code x: int; y: Object; f: instance field spec of type
1002     * byte :: y.f = x}
1003     */
1004    public static final Rop PUT_FIELD_BYTE =
1005        new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
1006                Exceptions.LIST_Error_NullPointerException,
1007                "put-field-byte");
1008
1009    /**
1010     * {@code x: int; y: Object; f: instance field spec of type
1011     * char :: y.f = x}
1012     */
1013    public static final Rop PUT_FIELD_CHAR =
1014        new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
1015                Exceptions.LIST_Error_NullPointerException,
1016                "put-field-char");
1017
1018    /**
1019     * {@code x: int; y: Object; f: instance field spec of type
1020     * short :: y.f = x}
1021     */
1022    public static final Rop PUT_FIELD_SHORT =
1023        new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
1024                Exceptions.LIST_Error_NullPointerException,
1025                "put-field-short");
1026
1027    /** {@code f: static field spec of type int; x: int :: f = x} */
1028    public static final Rop PUT_STATIC_INT =
1029        new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
1030                Exceptions.LIST_Error, "put-static-int");
1031
1032    /** {@code f: static field spec of type long; x: long :: f = x} */
1033    public static final Rop PUT_STATIC_LONG =
1034        new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.LONG,
1035                Exceptions.LIST_Error, "put-static-long");
1036
1037    /** {@code f: static field spec of type float; x: float :: f = x} */
1038    public static final Rop PUT_STATIC_FLOAT =
1039        new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.FLOAT,
1040                Exceptions.LIST_Error, "put-static-float");
1041
1042    /** {@code f: static field spec of type double; x: double :: f = x} */
1043    public static final Rop PUT_STATIC_DOUBLE =
1044        new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.DOUBLE,
1045                Exceptions.LIST_Error, "put-static-double");
1046
1047    /** {@code f: static field spec of type Object; x: Object :: f = x} */
1048    public static final Rop PUT_STATIC_OBJECT =
1049        new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.OBJECT,
1050                Exceptions.LIST_Error, "put-static-object");
1051
1052    /**
1053     * {@code f: static field spec of type boolean; x: boolean :: f =
1054     * x}
1055     */
1056    public static final Rop PUT_STATIC_BOOLEAN =
1057        new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
1058                Exceptions.LIST_Error, "put-static-boolean");
1059
1060    /** {@code f: static field spec of type byte; x: byte :: f = x} */
1061    public static final Rop PUT_STATIC_BYTE =
1062        new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
1063                Exceptions.LIST_Error, "put-static-byte");
1064
1065    /** {@code f: static field spec of type char; x: char :: f = x} */
1066    public static final Rop PUT_STATIC_CHAR =
1067        new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
1068                Exceptions.LIST_Error, "put-static-char");
1069
1070    /** {@code f: static field spec of type short; x: short :: f = x} */
1071    public static final Rop PUT_STATIC_SHORT =
1072        new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
1073                Exceptions.LIST_Error, "put-static-short");
1074
1075    /** {@code x: Int :: local variable begins in x} */
1076    public static final Rop MARK_LOCAL_INT =
1077            new Rop (RegOps.MARK_LOCAL, Type.VOID,
1078                    StdTypeList.INT, "mark-local-int");
1079
1080    /** {@code x: Long :: local variable begins in x} */
1081    public static final Rop MARK_LOCAL_LONG =
1082            new Rop (RegOps.MARK_LOCAL, Type.VOID,
1083                    StdTypeList.LONG, "mark-local-long");
1084
1085    /** {@code x: Float :: local variable begins in x} */
1086    public static final Rop MARK_LOCAL_FLOAT =
1087            new Rop (RegOps.MARK_LOCAL, Type.VOID,
1088                    StdTypeList.FLOAT, "mark-local-float");
1089
1090    /** {@code x: Double :: local variable begins in x} */
1091    public static final Rop MARK_LOCAL_DOUBLE =
1092            new Rop (RegOps.MARK_LOCAL, Type.VOID,
1093                    StdTypeList.DOUBLE, "mark-local-double");
1094
1095    /** {@code x: Object :: local variable begins in x} */
1096    public static final Rop MARK_LOCAL_OBJECT =
1097            new Rop (RegOps.MARK_LOCAL, Type.VOID,
1098                    StdTypeList.OBJECT, "mark-local-object");
1099
1100    /** {@code T: Any primitive type; v0..vx: T :: {v0, ..., vx}} */
1101    public static final Rop FILL_ARRAY_DATA =
1102        new Rop(RegOps.FILL_ARRAY_DATA, Type.VOID, StdTypeList.EMPTY,
1103                "fill-array-data");
1104
1105    /**
1106     * Returns the appropriate rop for the given opcode, destination,
1107     * and sources. The result is typically, but not necessarily, a
1108     * shared instance.
1109     *
1110     * <p><b>Note:</b> This method does not do complete error checking on
1111     * its arguments, and so it may return an instance which seemed "right
1112     * enough" even though in actuality the passed arguments don't quite
1113     * match what is returned. TODO: Revisit this issue.</p>
1114     *
1115     * @param opcode the opcode
1116     * @param dest {@code non-null;} destination (result) type, or
1117     * {@link Type#VOID} if none
1118     * @param sources {@code non-null;} list of source types
1119     * @param cst {@code null-ok;} associated constant, if any
1120     * @return {@code non-null;} an appropriate instance
1121     */
1122    public static Rop ropFor(int opcode, TypeBearer dest, TypeList sources,
1123            Constant cst) {
1124        switch (opcode) {
1125            case RegOps.NOP: return NOP;
1126            case RegOps.MOVE: return opMove(dest);
1127            case RegOps.MOVE_PARAM: return opMoveParam(dest);
1128            case RegOps.MOVE_EXCEPTION: return opMoveException(dest);
1129            case RegOps.CONST: return opConst(dest);
1130            case RegOps.GOTO: return GOTO;
1131            case RegOps.IF_EQ: return opIfEq(sources);
1132            case RegOps.IF_NE: return opIfNe(sources);
1133            case RegOps.IF_LT: return opIfLt(sources);
1134            case RegOps.IF_GE: return opIfGe(sources);
1135            case RegOps.IF_LE: return opIfLe(sources);
1136            case RegOps.IF_GT: return opIfGt(sources);
1137            case RegOps.SWITCH: return SWITCH;
1138            case RegOps.ADD: return opAdd(sources);
1139            case RegOps.SUB: return opSub(sources);
1140            case RegOps.MUL: return opMul(sources);
1141            case RegOps.DIV: return opDiv(sources);
1142            case RegOps.REM: return opRem(sources);
1143            case RegOps.NEG: return opNeg(dest);
1144            case RegOps.AND: return opAnd(sources);
1145            case RegOps.OR: return opOr(sources);
1146            case RegOps.XOR: return opXor(sources);
1147            case RegOps.SHL: return opShl(sources);
1148            case RegOps.SHR: return opShr(sources);
1149            case RegOps.USHR: return opUshr(sources);
1150            case RegOps.NOT: return opNot(dest);
1151            case RegOps.CMPL: return opCmpl(sources.getType(0));
1152            case RegOps.CMPG: return opCmpg(sources.getType(0));
1153            case RegOps.CONV: return opConv(dest, sources.getType(0));
1154            case RegOps.TO_BYTE: return TO_BYTE;
1155            case RegOps.TO_CHAR: return TO_CHAR;
1156            case RegOps.TO_SHORT: return TO_SHORT;
1157            case RegOps.RETURN: {
1158                if (sources.size() == 0) {
1159                    return RETURN_VOID;
1160                }
1161                return opReturn(sources.getType(0));
1162            }
1163            case RegOps.ARRAY_LENGTH: return ARRAY_LENGTH;
1164            case RegOps.THROW: return THROW;
1165            case RegOps.MONITOR_ENTER: return MONITOR_ENTER;
1166            case RegOps.MONITOR_EXIT: return MONITOR_EXIT;
1167            case RegOps.AGET: {
1168                Type source = sources.getType(0);
1169                Type componentType;
1170                if (source == Type.KNOWN_NULL) {
1171                    /*
1172                     * Treat a known-null as an array of the expected
1173                     * result type.
1174                     */
1175                    componentType = dest.getType();
1176                } else {
1177                    componentType = source.getComponentType();
1178                }
1179                return opAget(componentType);
1180            }
1181            case RegOps.APUT: {
1182                Type source = sources.getType(1);
1183                Type componentType;
1184                if (source == Type.KNOWN_NULL) {
1185                    /*
1186                     * Treat a known-null as an array of the type being
1187                     * stored.
1188                     */
1189                    componentType = sources.getType(0);
1190                } else {
1191                    componentType = source.getComponentType();
1192                }
1193                return opAput(componentType);
1194            }
1195            case RegOps.NEW_INSTANCE: return NEW_INSTANCE;
1196            case RegOps.NEW_ARRAY: return opNewArray(dest.getType());
1197            case RegOps.CHECK_CAST: return CHECK_CAST;
1198            case RegOps.INSTANCE_OF: return INSTANCE_OF;
1199            case RegOps.GET_FIELD: return opGetField(dest);
1200            case RegOps.GET_STATIC: return opGetStatic(dest);
1201            case RegOps.PUT_FIELD: return opPutField(sources.getType(0));
1202            case RegOps.PUT_STATIC: return opPutStatic(sources.getType(0));
1203            case RegOps.INVOKE_STATIC: {
1204                return opInvokeStatic(((CstMethodRef) cst).getPrototype());
1205            }
1206            case RegOps.INVOKE_VIRTUAL: {
1207                CstBaseMethodRef cstMeth = (CstMethodRef) cst;
1208                Prototype meth = cstMeth.getPrototype();
1209                CstType definer = cstMeth.getDefiningClass();
1210                meth = meth.withFirstParameter(definer.getClassType());
1211                return opInvokeVirtual(meth);
1212            }
1213            case RegOps.INVOKE_SUPER: {
1214                CstBaseMethodRef cstMeth = (CstMethodRef) cst;
1215                Prototype meth = cstMeth.getPrototype();
1216                CstType definer = cstMeth.getDefiningClass();
1217                meth = meth.withFirstParameter(definer.getClassType());
1218                return opInvokeSuper(meth);
1219            }
1220            case RegOps.INVOKE_DIRECT: {
1221                CstBaseMethodRef cstMeth = (CstMethodRef) cst;
1222                Prototype meth = cstMeth.getPrototype();
1223                CstType definer = cstMeth.getDefiningClass();
1224                meth = meth.withFirstParameter(definer.getClassType());
1225                return opInvokeDirect(meth);
1226            }
1227            case RegOps.INVOKE_INTERFACE: {
1228                CstBaseMethodRef cstMeth = (CstMethodRef) cst;
1229                Prototype meth = cstMeth.getPrototype();
1230                CstType definer = cstMeth.getDefiningClass();
1231                meth = meth.withFirstParameter(definer.getClassType());
1232                return opInvokeInterface(meth);
1233            }
1234        }
1235
1236        throw new RuntimeException("unknown opcode " + RegOps.opName(opcode));
1237    }
1238
1239    /**
1240     * Returns the appropriate {@code move} rop for the given type. The
1241     * result is a shared instance.
1242     *
1243     * @param type {@code non-null;} type of value being moved
1244     * @return {@code non-null;} an appropriate instance
1245     */
1246    public static Rop opMove(TypeBearer type) {
1247        switch (type.getBasicFrameType()) {
1248            case Type.BT_INT:    return MOVE_INT;
1249            case Type.BT_LONG:   return MOVE_LONG;
1250            case Type.BT_FLOAT:  return MOVE_FLOAT;
1251            case Type.BT_DOUBLE: return MOVE_DOUBLE;
1252            case Type.BT_OBJECT: return MOVE_OBJECT;
1253            case Type.BT_ADDR:   return MOVE_RETURN_ADDRESS;
1254        }
1255
1256        return throwBadType(type);
1257    }
1258
1259    /**
1260     * Returns the appropriate {@code move-param} rop for the
1261     * given type. The result is a shared instance.
1262     *
1263     * @param type {@code non-null;} type of value being moved
1264     * @return {@code non-null;} an appropriate instance
1265     */
1266    public static Rop opMoveParam(TypeBearer type) {
1267        switch (type.getBasicFrameType()) {
1268            case Type.BT_INT:    return MOVE_PARAM_INT;
1269            case Type.BT_LONG:   return MOVE_PARAM_LONG;
1270            case Type.BT_FLOAT:  return MOVE_PARAM_FLOAT;
1271            case Type.BT_DOUBLE: return MOVE_PARAM_DOUBLE;
1272            case Type.BT_OBJECT: return MOVE_PARAM_OBJECT;
1273        }
1274
1275        return throwBadType(type);
1276    }
1277
1278    /**
1279     * Returns the appropriate {@code move-exception} rop for the
1280     * given type. The result may be a shared instance.
1281     *
1282     * @param type {@code non-null;} type of the exception
1283     * @return {@code non-null;} an appropriate instance
1284     */
1285    public static Rop opMoveException(TypeBearer type) {
1286        return new Rop(RegOps.MOVE_EXCEPTION, type.getType(),
1287                       StdTypeList.EMPTY, (String) null);
1288    }
1289
1290    /**
1291     * Returns the appropriate {@code move-result} rop for the
1292     * given type. The result may be a shared instance.
1293     *
1294     * @param type {@code non-null;} type of the parameter
1295     * @return {@code non-null;} an appropriate instance
1296     */
1297    public static Rop opMoveResult(TypeBearer type) {
1298        return new Rop(RegOps.MOVE_RESULT, type.getType(),
1299                       StdTypeList.EMPTY, (String) null);
1300    }
1301
1302    /**
1303     * Returns the appropriate {@code move-result-pseudo} rop for the
1304     * given type. The result may be a shared instance.
1305     *
1306     * @param type {@code non-null;} type of the parameter
1307     * @return {@code non-null;} an appropriate instance
1308     */
1309    public static Rop opMoveResultPseudo(TypeBearer type) {
1310        return new Rop(RegOps.MOVE_RESULT_PSEUDO, type.getType(),
1311                       StdTypeList.EMPTY, (String) null);
1312    }
1313
1314    /**
1315     * Returns the appropriate {@code const} rop for the given
1316     * type. The result is a shared instance.
1317     *
1318     * @param type {@code non-null;} type of the constant
1319     * @return {@code non-null;} an appropriate instance
1320     */
1321    public static Rop opConst(TypeBearer type) {
1322        if (type.getType() == Type.KNOWN_NULL) {
1323            return CONST_OBJECT_NOTHROW;
1324        }
1325
1326        switch (type.getBasicFrameType()) {
1327            case Type.BT_INT:    return CONST_INT;
1328            case Type.BT_LONG:   return CONST_LONG;
1329            case Type.BT_FLOAT:  return CONST_FLOAT;
1330            case Type.BT_DOUBLE: return CONST_DOUBLE;
1331            case Type.BT_OBJECT: return CONST_OBJECT;
1332        }
1333
1334        return throwBadType(type);
1335    }
1336
1337    /**
1338     * Returns the appropriate {@code if-eq} rop for the given
1339     * sources. The result is a shared instance.
1340     *
1341     * @param types {@code non-null;} source types
1342     * @return {@code non-null;} an appropriate instance
1343     */
1344    public static Rop opIfEq(TypeList types) {
1345        return pickIf(types, IF_EQZ_INT, IF_EQZ_OBJECT,
1346                      IF_EQ_INT, IF_EQ_OBJECT);
1347    }
1348
1349    /**
1350     * Returns the appropriate {@code if-ne} rop for the given
1351     * sources. The result is a shared instance.
1352     *
1353     * @param types {@code non-null;} source types
1354     * @return {@code non-null;} an appropriate instance
1355     */
1356    public static Rop opIfNe(TypeList types) {
1357        return pickIf(types, IF_NEZ_INT, IF_NEZ_OBJECT,
1358                      IF_NE_INT, IF_NE_OBJECT);
1359    }
1360
1361    /**
1362     * Returns the appropriate {@code if-lt} rop for the given
1363     * sources. The result is a shared instance.
1364     *
1365     * @param types {@code non-null;} source types
1366     * @return {@code non-null;} an appropriate instance
1367     */
1368    public static Rop opIfLt(TypeList types) {
1369        return pickIf(types, IF_LTZ_INT, null, IF_LT_INT, null);
1370    }
1371
1372    /**
1373     * Returns the appropriate {@code if-ge} rop for the given
1374     * sources. The result is a shared instance.
1375     *
1376     * @param types {@code non-null;} source types
1377     * @return {@code non-null;} an appropriate instance
1378     */
1379    public static Rop opIfGe(TypeList types) {
1380        return pickIf(types, IF_GEZ_INT, null, IF_GE_INT, null);
1381    }
1382
1383    /**
1384     * Returns the appropriate {@code if-gt} rop for the given
1385     * sources. The result is a shared instance.
1386     *
1387     * @param types {@code non-null;} source types
1388     * @return {@code non-null;} an appropriate instance
1389     */
1390    public static Rop opIfGt(TypeList types) {
1391        return pickIf(types, IF_GTZ_INT, null, IF_GT_INT, null);
1392    }
1393
1394    /**
1395     * Returns the appropriate {@code if-le} rop for the given
1396     * sources. The result is a shared instance.
1397     *
1398     * @param types {@code non-null;} source types
1399     * @return {@code non-null;} an appropriate instance
1400     */
1401    public static Rop opIfLe(TypeList types) {
1402        return pickIf(types, IF_LEZ_INT, null, IF_LE_INT, null);
1403    }
1404
1405    /**
1406     * Helper for all the {@code if*}-related methods, which
1407     * checks types and picks one of the four variants, throwing if
1408     * there's a problem.
1409     *
1410     * @param types {@code non-null;} the types
1411     * @param intZ {@code non-null;} the int-to-0 comparison
1412     * @param objZ {@code null-ok;} the object-to-null comparison
1413     * @param intInt {@code non-null;} the int-to-int comparison
1414     * @param objObj {@code non-null;} the object-to-object comparison
1415     * @return {@code non-null;} the appropriate instance
1416     */
1417    private static Rop pickIf(TypeList types, Rop intZ, Rop objZ, Rop intInt,
1418                              Rop objObj) {
1419        switch(types.size()) {
1420            case 1: {
1421                switch (types.getType(0).getBasicFrameType()) {
1422                    case Type.BT_INT: {
1423                        return intZ;
1424                    }
1425                    case Type.BT_OBJECT: {
1426                        if (objZ != null) {
1427                            return objZ;
1428                        }
1429                    }
1430                }
1431                break;
1432            }
1433            case 2: {
1434                int bt = types.getType(0).getBasicFrameType();
1435                if (bt == types.getType(1).getBasicFrameType()) {
1436                    switch (bt) {
1437                        case Type.BT_INT: {
1438                            return intInt;
1439                        }
1440                        case Type.BT_OBJECT: {
1441                            if (objObj != null) {
1442                                return objObj;
1443                            }
1444                        }
1445                    }
1446                }
1447                break;
1448            }
1449        }
1450
1451        return throwBadTypes(types);
1452    }
1453
1454    /**
1455     * Returns the appropriate {@code add} rop for the given
1456     * types. The result is a shared instance.
1457     *
1458     * @param types {@code non-null;} types of the sources
1459     * @return {@code non-null;} an appropriate instance
1460     */
1461    public static Rop opAdd(TypeList types) {
1462        return pickBinaryOp(types, ADD_CONST_INT, ADD_CONST_LONG,
1463                            ADD_CONST_FLOAT, ADD_CONST_DOUBLE, ADD_INT,
1464                            ADD_LONG, ADD_FLOAT, ADD_DOUBLE);
1465    }
1466
1467    /**
1468     * Returns the appropriate {@code sub} rop for the given
1469     * types. The result is a shared instance.
1470     *
1471     * @param types {@code non-null;} types of the sources
1472     * @return {@code non-null;} an appropriate instance
1473     */
1474    public static Rop opSub(TypeList types) {
1475        return pickBinaryOp(types, SUB_CONST_INT, SUB_CONST_LONG,
1476                            SUB_CONST_FLOAT, SUB_CONST_DOUBLE, SUB_INT,
1477                            SUB_LONG, SUB_FLOAT, SUB_DOUBLE);
1478    }
1479
1480    /**
1481     * Returns the appropriate {@code mul} rop for the given
1482     * types. The result is a shared instance.
1483     *
1484     * @param types {@code non-null;} types of the sources
1485     * @return {@code non-null;} an appropriate instance
1486     */
1487    public static Rop opMul(TypeList types) {
1488        return pickBinaryOp(types, MUL_CONST_INT, MUL_CONST_LONG,
1489                            MUL_CONST_FLOAT, MUL_CONST_DOUBLE, MUL_INT,
1490                            MUL_LONG, MUL_FLOAT, MUL_DOUBLE);
1491    }
1492
1493    /**
1494     * Returns the appropriate {@code div} rop for the given
1495     * types. The result is a shared instance.
1496     *
1497     * @param types {@code non-null;} types of the sources
1498     * @return {@code non-null;} an appropriate instance
1499     */
1500    public static Rop opDiv(TypeList types) {
1501        return pickBinaryOp(types, DIV_CONST_INT, DIV_CONST_LONG,
1502                            DIV_CONST_FLOAT, DIV_CONST_DOUBLE, DIV_INT,
1503                            DIV_LONG, DIV_FLOAT, DIV_DOUBLE);
1504    }
1505
1506    /**
1507     * Returns the appropriate {@code rem} rop for the given
1508     * types. The result is a shared instance.
1509     *
1510     * @param types {@code non-null;} types of the sources
1511     * @return {@code non-null;} an appropriate instance
1512     */
1513    public static Rop opRem(TypeList types) {
1514        return pickBinaryOp(types, REM_CONST_INT, REM_CONST_LONG,
1515                            REM_CONST_FLOAT, REM_CONST_DOUBLE, REM_INT,
1516                            REM_LONG, REM_FLOAT, REM_DOUBLE);
1517    }
1518
1519    /**
1520     * Returns the appropriate {@code and} rop for the given
1521     * types. The result is a shared instance.
1522     *
1523     * @param types {@code non-null;} types of the sources
1524     * @return {@code non-null;} an appropriate instance
1525     */
1526    public static Rop opAnd(TypeList types) {
1527        return pickBinaryOp(types, AND_CONST_INT, AND_CONST_LONG, null, null,
1528                            AND_INT, AND_LONG, null, null);
1529    }
1530
1531    /**
1532     * Returns the appropriate {@code or} rop for the given
1533     * types. The result is a shared instance.
1534     *
1535     * @param types {@code non-null;} types of the sources
1536     * @return {@code non-null;} an appropriate instance
1537     */
1538    public static Rop opOr(TypeList types) {
1539        return pickBinaryOp(types, OR_CONST_INT, OR_CONST_LONG, null, null,
1540                            OR_INT, OR_LONG, null, null);
1541    }
1542
1543    /**
1544     * Returns the appropriate {@code xor} rop for the given
1545     * types. The result is a shared instance.
1546     *
1547     * @param types {@code non-null;} types of the sources
1548     * @return {@code non-null;} an appropriate instance
1549     */
1550    public static Rop opXor(TypeList types) {
1551        return pickBinaryOp(types, XOR_CONST_INT, XOR_CONST_LONG, null, null,
1552                            XOR_INT, XOR_LONG, null, null);
1553    }
1554
1555    /**
1556     * Returns the appropriate {@code shl} rop for the given
1557     * types. The result is a shared instance.
1558     *
1559     * @param types {@code non-null;} types of the sources
1560     * @return {@code non-null;} an appropriate instance
1561     */
1562    public static Rop opShl(TypeList types) {
1563        return pickBinaryOp(types, SHL_CONST_INT, SHL_CONST_LONG, null, null,
1564                            SHL_INT, SHL_LONG, null, null);
1565    }
1566
1567    /**
1568     * Returns the appropriate {@code shr} rop for the given
1569     * types. The result is a shared instance.
1570     *
1571     * @param types {@code non-null;} types of the sources
1572     * @return {@code non-null;} an appropriate instance
1573     */
1574    public static Rop opShr(TypeList types) {
1575        return pickBinaryOp(types, SHR_CONST_INT, SHR_CONST_LONG, null, null,
1576                            SHR_INT, SHR_LONG, null, null);
1577    }
1578
1579    /**
1580     * Returns the appropriate {@code ushr} rop for the given
1581     * types. The result is a shared instance.
1582     *
1583     * @param types {@code non-null;} types of the sources
1584     * @return {@code non-null;} an appropriate instance
1585     */
1586    public static Rop opUshr(TypeList types) {
1587        return pickBinaryOp(types, USHR_CONST_INT, USHR_CONST_LONG, null, null,
1588                            USHR_INT, USHR_LONG, null, null);
1589    }
1590
1591    /**
1592     * Returns the appropriate binary arithmetic rop for the given type
1593     * and arguments. The result is a shared instance.
1594     *
1595     * @param types {@code non-null;} sources of the operation
1596     * @param int1 {@code non-null;} the int-to-constant rop
1597     * @param long1 {@code non-null;} the long-to-constant rop
1598     * @param float1 {@code null-ok;} the float-to-constant rop, if any
1599     * @param double1 {@code null-ok;} the double-to-constant rop, if any
1600     * @param int2 {@code non-null;} the int-to-int rop
1601     * @param long2 {@code non-null;} the long-to-long or long-to-int rop
1602     * @param float2 {@code null-ok;} the float-to-float rop, if any
1603     * @param double2 {@code null-ok;} the double-to-double rop, if any
1604     * @return {@code non-null;} an appropriate instance
1605     */
1606    private static Rop pickBinaryOp(TypeList types, Rop int1, Rop long1,
1607                                    Rop float1, Rop double1, Rop int2,
1608                                    Rop long2, Rop float2, Rop double2) {
1609        int bt1 = types.getType(0).getBasicFrameType();
1610        Rop result = null;
1611
1612        switch (types.size()) {
1613            case 1: {
1614                switch(bt1) {
1615                    case Type.BT_INT:    return int1;
1616                    case Type.BT_LONG:   return long1;
1617                    case Type.BT_FLOAT:  result = float1; break;
1618                    case Type.BT_DOUBLE: result = double1; break;
1619                }
1620                break;
1621            }
1622            case 2: {
1623                switch(bt1) {
1624                    case Type.BT_INT:    return int2;
1625                    case Type.BT_LONG:   return long2;
1626                    case Type.BT_FLOAT:  result = float2; break;
1627                    case Type.BT_DOUBLE: result = double2; break;
1628                }
1629                break;
1630            }
1631        }
1632
1633        if (result == null) {
1634            return throwBadTypes(types);
1635        }
1636
1637        return result;
1638    }
1639
1640    /**
1641     * Returns the appropriate {@code neg} rop for the given type. The
1642     * result is a shared instance.
1643     *
1644     * @param type {@code non-null;} type of value being operated on
1645     * @return {@code non-null;} an appropriate instance
1646     */
1647    public static Rop opNeg(TypeBearer type) {
1648        switch (type.getBasicFrameType()) {
1649            case Type.BT_INT:    return NEG_INT;
1650            case Type.BT_LONG:   return NEG_LONG;
1651            case Type.BT_FLOAT:  return NEG_FLOAT;
1652            case Type.BT_DOUBLE: return NEG_DOUBLE;
1653        }
1654
1655        return throwBadType(type);
1656    }
1657
1658    /**
1659     * Returns the appropriate {@code not} rop for the given type. The
1660     * result is a shared instance.
1661     *
1662     * @param type {@code non-null;} type of value being operated on
1663     * @return {@code non-null;} an appropriate instance
1664     */
1665    public static Rop opNot(TypeBearer type) {
1666        switch (type.getBasicFrameType()) {
1667            case Type.BT_INT:  return NOT_INT;
1668            case Type.BT_LONG: return NOT_LONG;
1669        }
1670
1671        return throwBadType(type);
1672    }
1673
1674    /**
1675     * Returns the appropriate {@code cmpl} rop for the given type. The
1676     * result is a shared instance.
1677     *
1678     * @param type {@code non-null;} type of value being compared
1679     * @return {@code non-null;} an appropriate instance
1680     */
1681    public static Rop opCmpl(TypeBearer type) {
1682        switch (type.getBasicType()) {
1683            case Type.BT_LONG:   return CMPL_LONG;
1684            case Type.BT_FLOAT:  return CMPL_FLOAT;
1685            case Type.BT_DOUBLE: return CMPL_DOUBLE;
1686        }
1687
1688        return throwBadType(type);
1689    }
1690
1691    /**
1692     * Returns the appropriate {@code cmpg} rop for the given type. The
1693     * result is a shared instance.
1694     *
1695     * @param type {@code non-null;} type of value being compared
1696     * @return {@code non-null;} an appropriate instance
1697     */
1698    public static Rop opCmpg(TypeBearer type) {
1699        switch (type.getBasicType()) {
1700            case Type.BT_FLOAT:  return CMPG_FLOAT;
1701            case Type.BT_DOUBLE: return CMPG_DOUBLE;
1702        }
1703
1704        return throwBadType(type);
1705    }
1706
1707    /**
1708     * Returns the appropriate {@code conv} rop for the given types. The
1709     * result is a shared instance.
1710     *
1711     * @param dest {@code non-null;} target value type
1712     * @param source {@code non-null;} source value type
1713     * @return {@code non-null;} an appropriate instance
1714     */
1715    public static Rop opConv(TypeBearer dest, TypeBearer source) {
1716        int dbt = dest.getBasicFrameType();
1717        switch (source.getBasicFrameType()) {
1718            case Type.BT_INT: {
1719                switch (dbt) {
1720                    case Type.BT_LONG:   return CONV_I2L;
1721                    case Type.BT_FLOAT:  return CONV_I2F;
1722                    case Type.BT_DOUBLE: return CONV_I2D;
1723                    default:             break;
1724                }
1725            }
1726            case Type.BT_LONG: {
1727                switch (dbt) {
1728                    case Type.BT_INT:    return CONV_L2I;
1729                    case Type.BT_FLOAT:  return CONV_L2F;
1730                    case Type.BT_DOUBLE: return CONV_L2D;
1731                    default:             break;
1732                }
1733            }
1734            case Type.BT_FLOAT: {
1735                switch (dbt) {
1736                    case Type.BT_INT:    return CONV_F2I;
1737                    case Type.BT_LONG:   return CONV_F2L;
1738                    case Type.BT_DOUBLE: return CONV_F2D;
1739                    default:             break;
1740                }
1741            }
1742            case Type.BT_DOUBLE: {
1743                switch (dbt) {
1744                    case Type.BT_INT:    return CONV_D2I;
1745                    case Type.BT_LONG:   return CONV_D2L;
1746                    case Type.BT_FLOAT:  return CONV_D2F;
1747                    default:             break;
1748                }
1749            }
1750        }
1751
1752        return throwBadTypes(StdTypeList.make(dest.getType(),
1753                                              source.getType()));
1754    }
1755
1756    /**
1757     * Returns the appropriate {@code return} rop for the given type. The
1758     * result is a shared instance.
1759     *
1760     * @param type {@code non-null;} type of value being returned
1761     * @return {@code non-null;} an appropriate instance
1762     */
1763    public static Rop opReturn(TypeBearer type) {
1764        switch (type.getBasicFrameType()) {
1765            case Type.BT_INT:    return RETURN_INT;
1766            case Type.BT_LONG:   return RETURN_LONG;
1767            case Type.BT_FLOAT:  return RETURN_FLOAT;
1768            case Type.BT_DOUBLE: return RETURN_DOUBLE;
1769            case Type.BT_OBJECT: return RETURN_OBJECT;
1770            case Type.BT_VOID:   return RETURN_VOID;
1771        }
1772
1773        return throwBadType(type);
1774    }
1775
1776    /**
1777     * Returns the appropriate {@code aget} rop for the given type. The
1778     * result is a shared instance.
1779     *
1780     * @param type {@code non-null;} element type of array being accessed
1781     * @return {@code non-null;} an appropriate instance
1782     */
1783    public static Rop opAget(TypeBearer type) {
1784        switch (type.getBasicType()) {
1785            case Type.BT_INT:     return AGET_INT;
1786            case Type.BT_LONG:    return AGET_LONG;
1787            case Type.BT_FLOAT:   return AGET_FLOAT;
1788            case Type.BT_DOUBLE:  return AGET_DOUBLE;
1789            case Type.BT_OBJECT:  return AGET_OBJECT;
1790            case Type.BT_BOOLEAN: return AGET_BOOLEAN;
1791            case Type.BT_BYTE:    return AGET_BYTE;
1792            case Type.BT_CHAR:    return AGET_CHAR;
1793            case Type.BT_SHORT:   return AGET_SHORT;
1794        }
1795
1796        return throwBadType(type);
1797    }
1798
1799    /**
1800     * Returns the appropriate {@code aput} rop for the given type. The
1801     * result is a shared instance.
1802     *
1803     * @param type {@code non-null;} element type of array being accessed
1804     * @return {@code non-null;} an appropriate instance
1805     */
1806    public static Rop opAput(TypeBearer type) {
1807        switch (type.getBasicType()) {
1808            case Type.BT_INT:     return APUT_INT;
1809            case Type.BT_LONG:    return APUT_LONG;
1810            case Type.BT_FLOAT:   return APUT_FLOAT;
1811            case Type.BT_DOUBLE:  return APUT_DOUBLE;
1812            case Type.BT_OBJECT:  return APUT_OBJECT;
1813            case Type.BT_BOOLEAN: return APUT_BOOLEAN;
1814            case Type.BT_BYTE:    return APUT_BYTE;
1815            case Type.BT_CHAR:    return APUT_CHAR;
1816            case Type.BT_SHORT:   return APUT_SHORT;
1817        }
1818
1819        return throwBadType(type);
1820    }
1821
1822    /**
1823     * Returns the appropriate {@code new-array} rop for the given
1824     * type. The result is a shared instance.
1825     *
1826     * @param arrayType {@code non-null;} array type of array being created
1827     * @return {@code non-null;} an appropriate instance
1828     */
1829    public static Rop opNewArray(TypeBearer arrayType) {
1830        Type type = arrayType.getType();
1831        Type elementType = type.getComponentType();
1832
1833        switch (elementType.getBasicType()) {
1834            case Type.BT_INT:     return NEW_ARRAY_INT;
1835            case Type.BT_LONG:    return NEW_ARRAY_LONG;
1836            case Type.BT_FLOAT:   return NEW_ARRAY_FLOAT;
1837            case Type.BT_DOUBLE:  return NEW_ARRAY_DOUBLE;
1838            case Type.BT_BOOLEAN: return NEW_ARRAY_BOOLEAN;
1839            case Type.BT_BYTE:    return NEW_ARRAY_BYTE;
1840            case Type.BT_CHAR:    return NEW_ARRAY_CHAR;
1841            case Type.BT_SHORT:   return NEW_ARRAY_SHORT;
1842            case Type.BT_OBJECT: {
1843                return new Rop(RegOps.NEW_ARRAY, type, StdTypeList.INT,
1844                        Exceptions.LIST_Error_NegativeArraySizeException,
1845                        "new-array-object");
1846            }
1847        }
1848
1849        return throwBadType(type);
1850    }
1851
1852    /**
1853     * Returns the appropriate {@code filled-new-array} rop for the given
1854     * type. The result may be a shared instance.
1855     *
1856     * @param arrayType {@code non-null;} type of array being created
1857     * @param count {@code >= 0;} number of elements that the array should have
1858     * @return {@code non-null;} an appropriate instance
1859     */
1860    public static Rop opFilledNewArray(TypeBearer arrayType, int count) {
1861        Type type = arrayType.getType();
1862        Type elementType = type.getComponentType();
1863
1864        if (elementType.isCategory2()) {
1865            return throwBadType(arrayType);
1866        }
1867
1868        if (count < 0) {
1869            throw new IllegalArgumentException("count < 0");
1870        }
1871
1872        StdTypeList sourceTypes = new StdTypeList(count);
1873
1874        for (int i = 0; i < count; i++) {
1875            sourceTypes.set(i, elementType);
1876        }
1877
1878        // Note: The resulting rop is considered call-like.
1879        return new Rop(RegOps.FILLED_NEW_ARRAY,
1880                       sourceTypes,
1881                       Exceptions.LIST_Error);
1882    }
1883
1884    /**
1885     * Returns the appropriate {@code get-field} rop for the given
1886     * type. The result is a shared instance.
1887     *
1888     * @param type {@code non-null;} type of the field in question
1889     * @return {@code non-null;} an appropriate instance
1890     */
1891    public static Rop opGetField(TypeBearer type) {
1892        switch (type.getBasicType()) {
1893            case Type.BT_INT:     return GET_FIELD_INT;
1894            case Type.BT_LONG:    return GET_FIELD_LONG;
1895            case Type.BT_FLOAT:   return GET_FIELD_FLOAT;
1896            case Type.BT_DOUBLE:  return GET_FIELD_DOUBLE;
1897            case Type.BT_OBJECT:  return GET_FIELD_OBJECT;
1898            case Type.BT_BOOLEAN: return GET_FIELD_BOOLEAN;
1899            case Type.BT_BYTE:    return GET_FIELD_BYTE;
1900            case Type.BT_CHAR:    return GET_FIELD_CHAR;
1901            case Type.BT_SHORT:   return GET_FIELD_SHORT;
1902        }
1903
1904        return throwBadType(type);
1905    }
1906
1907    /**
1908     * Returns the appropriate {@code put-field} rop for the given
1909     * type. The result is a shared instance.
1910     *
1911     * @param type {@code non-null;} type of the field in question
1912     * @return {@code non-null;} an appropriate instance
1913     */
1914    public static Rop opPutField(TypeBearer type) {
1915        switch (type.getBasicType()) {
1916            case Type.BT_INT:     return PUT_FIELD_INT;
1917            case Type.BT_LONG:    return PUT_FIELD_LONG;
1918            case Type.BT_FLOAT:   return PUT_FIELD_FLOAT;
1919            case Type.BT_DOUBLE:  return PUT_FIELD_DOUBLE;
1920            case Type.BT_OBJECT:  return PUT_FIELD_OBJECT;
1921            case Type.BT_BOOLEAN: return PUT_FIELD_BOOLEAN;
1922            case Type.BT_BYTE:    return PUT_FIELD_BYTE;
1923            case Type.BT_CHAR:    return PUT_FIELD_CHAR;
1924            case Type.BT_SHORT:   return PUT_FIELD_SHORT;
1925        }
1926
1927        return throwBadType(type);
1928    }
1929
1930    /**
1931     * Returns the appropriate {@code get-static} rop for the given
1932     * type. The result is a shared instance.
1933     *
1934     * @param type {@code non-null;} type of the field in question
1935     * @return {@code non-null;} an appropriate instance
1936     */
1937    public static Rop opGetStatic(TypeBearer type) {
1938        switch (type.getBasicType()) {
1939            case Type.BT_INT:     return GET_STATIC_INT;
1940            case Type.BT_LONG:    return GET_STATIC_LONG;
1941            case Type.BT_FLOAT:   return GET_STATIC_FLOAT;
1942            case Type.BT_DOUBLE:  return GET_STATIC_DOUBLE;
1943            case Type.BT_OBJECT:  return GET_STATIC_OBJECT;
1944            case Type.BT_BOOLEAN: return GET_STATIC_BOOLEAN;
1945            case Type.BT_BYTE:    return GET_STATIC_BYTE;
1946            case Type.BT_CHAR:    return GET_STATIC_CHAR;
1947            case Type.BT_SHORT:   return GET_STATIC_SHORT;
1948        }
1949
1950        return throwBadType(type);
1951    }
1952
1953    /**
1954     * Returns the appropriate {@code put-static} rop for the given
1955     * type. The result is a shared instance.
1956     *
1957     * @param type {@code non-null;} type of the field in question
1958     * @return {@code non-null;} an appropriate instance
1959     */
1960    public static Rop opPutStatic(TypeBearer type) {
1961        switch (type.getBasicType()) {
1962            case Type.BT_INT:     return PUT_STATIC_INT;
1963            case Type.BT_LONG:    return PUT_STATIC_LONG;
1964            case Type.BT_FLOAT:   return PUT_STATIC_FLOAT;
1965            case Type.BT_DOUBLE:  return PUT_STATIC_DOUBLE;
1966            case Type.BT_OBJECT:  return PUT_STATIC_OBJECT;
1967            case Type.BT_BOOLEAN: return PUT_STATIC_BOOLEAN;
1968            case Type.BT_BYTE:    return PUT_STATIC_BYTE;
1969            case Type.BT_CHAR:    return PUT_STATIC_CHAR;
1970            case Type.BT_SHORT:   return PUT_STATIC_SHORT;
1971        }
1972
1973        return throwBadType(type);
1974    }
1975
1976    /**
1977     * Returns the appropriate {@code invoke-static} rop for the
1978     * given type. The result is typically a newly-allocated instance.
1979     *
1980     * @param meth {@code non-null;} descriptor of the method
1981     * @return {@code non-null;} an appropriate instance
1982     */
1983    public static Rop opInvokeStatic(Prototype meth) {
1984        return new Rop(RegOps.INVOKE_STATIC,
1985                       meth.getParameterFrameTypes(),
1986                       StdTypeList.THROWABLE);
1987    }
1988
1989    /**
1990     * Returns the appropriate {@code invoke-virtual} rop for the
1991     * given type. The result is typically a newly-allocated instance.
1992     *
1993     * @param meth {@code non-null;} descriptor of the method, including the
1994     * {@code this} parameter
1995     * @return {@code non-null;} an appropriate instance
1996     */
1997    public static Rop opInvokeVirtual(Prototype meth) {
1998        return new Rop(RegOps.INVOKE_VIRTUAL,
1999                       meth.getParameterFrameTypes(),
2000                       StdTypeList.THROWABLE);
2001    }
2002
2003    /**
2004     * Returns the appropriate {@code invoke-super} rop for the
2005     * given type. The result is typically a newly-allocated instance.
2006     *
2007     * @param meth {@code non-null;} descriptor of the method, including the
2008     * {@code this} parameter
2009     * @return {@code non-null;} an appropriate instance
2010     */
2011    public static Rop opInvokeSuper(Prototype meth) {
2012        return new Rop(RegOps.INVOKE_SUPER,
2013                       meth.getParameterFrameTypes(),
2014                       StdTypeList.THROWABLE);
2015    }
2016
2017    /**
2018     * Returns the appropriate {@code invoke-direct} rop for the
2019     * given type. The result is typically a newly-allocated instance.
2020     *
2021     * @param meth {@code non-null;} descriptor of the method, including the
2022     * {@code this} parameter
2023     * @return {@code non-null;} an appropriate instance
2024     */
2025    public static Rop opInvokeDirect(Prototype meth) {
2026        return new Rop(RegOps.INVOKE_DIRECT,
2027                       meth.getParameterFrameTypes(),
2028                       StdTypeList.THROWABLE);
2029    }
2030
2031    /**
2032     * Returns the appropriate {@code invoke-interface} rop for the
2033     * given type. The result is typically a newly-allocated instance.
2034     *
2035     * @param meth {@code non-null;} descriptor of the method, including the
2036     * {@code this} parameter
2037     * @return {@code non-null;} an appropriate instance
2038     */
2039    public static Rop opInvokeInterface(Prototype meth) {
2040        return new Rop(RegOps.INVOKE_INTERFACE,
2041                       meth.getParameterFrameTypes(),
2042                       StdTypeList.THROWABLE);
2043    }
2044
2045    /**
2046     * Returns the appropriate {@code mark-local} rop for the given type.
2047     * The result is a shared instance.
2048     *
2049     * @param type {@code non-null;} type of value being marked
2050     * @return {@code non-null;} an appropriate instance
2051     */
2052    public static Rop opMarkLocal(TypeBearer type) {
2053        switch (type.getBasicFrameType()) {
2054            case Type.BT_INT:    return MARK_LOCAL_INT;
2055            case Type.BT_LONG:   return MARK_LOCAL_LONG;
2056            case Type.BT_FLOAT:  return MARK_LOCAL_FLOAT;
2057            case Type.BT_DOUBLE: return MARK_LOCAL_DOUBLE;
2058            case Type.BT_OBJECT: return MARK_LOCAL_OBJECT;
2059        }
2060
2061        return throwBadType(type);
2062    }
2063
2064    /**
2065     * This class is uninstantiable.
2066     */
2067    private Rops() {
2068        // This space intentionally left blank.
2069    }
2070
2071    /**
2072     * Throws the right exception to complain about a bogus type.
2073     *
2074     * @param type {@code non-null;} the bad type
2075     * @return never
2076     */
2077    private static Rop throwBadType(TypeBearer type) {
2078        throw new IllegalArgumentException("bad type: " + type);
2079    }
2080
2081    /**
2082     * Throws the right exception to complain about a bogus list of types.
2083     *
2084     * @param types {@code non-null;} the bad types
2085     * @return never
2086     */
2087    private static Rop throwBadTypes(TypeList types) {
2088        throw new IllegalArgumentException("bad types: " + types);
2089    }
2090}
2091