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.dexgen.dex.code;
18
19/**
20 * Representation of an opcode.
21 */
22public final class Dop {
23    /** DalvOps.MIN_VALUE..DalvOps.MAX_VALUE; the opcode value itself */
24    private final int opcode;
25
26    /** DalvOps.MIN_VALUE..DalvOps.MAX_VALUE; the opcode family */
27    private final int family;
28
29    /** {@code non-null;} the instruction format */
30    private final InsnFormat format;
31
32    /** whether this opcode uses a result register */
33    private final boolean hasResult;
34
35    /** {@code non-null;} the name */
36    private final String name;
37
38    /**
39     * Constructs an instance.
40     *
41     * @param opcode {@code DalvOps.MIN_VALUE..DalvOps.MAX_VALUE;} the opcode
42     * value itself
43     * @param family {@code DalvOps.MIN_VALUE..DalvOps.MAX_VALUE;} the opcode family
44     * @param format {@code non-null;} the instruction format
45     * @param hasResult whether the opcode has a result register; if so it
46     * is always the first register
47     * @param name {@code non-null;} the name
48     */
49    public Dop(int opcode, int family, InsnFormat format,
50               boolean hasResult, String name) {
51        if ((opcode < DalvOps.MIN_VALUE) || (opcode > DalvOps.MAX_VALUE)) {
52            throw new IllegalArgumentException("bogus opcode");
53        }
54
55        if ((family < DalvOps.MIN_VALUE) || (family > DalvOps.MAX_VALUE)) {
56            throw new IllegalArgumentException("bogus family");
57        }
58
59        if (format == null) {
60            throw new NullPointerException("format == null");
61        }
62
63        if (name == null) {
64            throw new NullPointerException("name == null");
65        }
66
67        this.opcode = opcode;
68        this.family = family;
69        this.format = format;
70        this.hasResult = hasResult;
71        this.name = name;
72    }
73
74    /** {@inheritDoc} */
75    @Override
76    public String toString() {
77        return name;
78    }
79
80    /**
81     * Gets the opcode value.
82     *
83     * @return {@code DalvOps.MIN_VALUE..DalvOps.MAX_VALUE;} the opcode value
84     */
85    public int getOpcode() {
86        return opcode;
87    }
88
89    /**
90     * Gets the opcode family. The opcode family is the unmarked (no
91     * "/...") opcode that has equivalent semantics to this one.
92     *
93     * @return {@code DalvOps.MIN_VALUE..DalvOps.MAX_VALUE;} the opcode family
94     */
95    public int getFamily() {
96        return family;
97    }
98
99    /**
100     * Gets the instruction format.
101     *
102     * @return {@code non-null;} the instruction format
103     */
104    public InsnFormat getFormat() {
105        return format;
106    }
107
108    /**
109     * Returns whether this opcode uses a result register.
110     *
111     * @return {@code true} iff this opcode uses a result register
112     */
113    public boolean hasResult() {
114        return hasResult;
115    }
116
117    /**
118     * Gets the opcode name.
119     *
120     * @return {@code non-null;} the opcode name
121     */
122    public String getName() {
123        return name;
124    }
125
126    /**
127     * Gets the opcode for the opposite test of this instance. This is only
128     * valid for opcodes which are in fact tests.
129     *
130     * @return {@code non-null;} the opposite test
131     */
132    public Dop getOppositeTest() {
133        switch (opcode) {
134            case DalvOps.IF_EQ:  return Dops.IF_NE;
135            case DalvOps.IF_NE:  return Dops.IF_EQ;
136            case DalvOps.IF_LT:  return Dops.IF_GE;
137            case DalvOps.IF_GE:  return Dops.IF_LT;
138            case DalvOps.IF_GT:  return Dops.IF_LE;
139            case DalvOps.IF_LE:  return Dops.IF_GT;
140            case DalvOps.IF_EQZ: return Dops.IF_NEZ;
141            case DalvOps.IF_NEZ: return Dops.IF_EQZ;
142            case DalvOps.IF_LTZ: return Dops.IF_GEZ;
143            case DalvOps.IF_GEZ: return Dops.IF_LTZ;
144            case DalvOps.IF_GTZ: return Dops.IF_LEZ;
145            case DalvOps.IF_LEZ: return Dops.IF_GTZ;
146        }
147
148        throw new IllegalArgumentException("bogus opcode: " + this);
149    }
150}
151