1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.dex.code;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornsteinimport com.android.dx.io.OpcodeInfo;
207ba91291bb6ce64691398a8751656207e8e3e98dDan Bornsteinimport com.android.dx.io.Opcodes;
217ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Representation of an opcode.
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class Dop {
267ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein    /** {@code Opcodes.isValid();} the opcode value itself */
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int opcode;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
297ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein    /** {@code Opcodes.isValid();} the opcode family */
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int family;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
32ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein    /**
337ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein     * {@code Opcodes.isValid();} what opcode (by number) to try next
3425f7980a51488db2ebcd7822c83c3f4b25a2a730Dan Bornstein     * when attempting to match an opcode to particular arguments;
357ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein     * {@code Opcodes.NO_NEXT} to indicate that this is the last
3625f7980a51488db2ebcd7822c83c3f4b25a2a730Dan Bornstein     * opcode to try in a particular chain
37ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein     */
38ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein    private final int nextOpcode;
39ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein
4099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} the instruction format */
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final InsnFormat format;
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** whether this opcode uses a result register */
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final boolean hasResult;
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance.
48de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
497ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein     * @param opcode {@code Opcodes.isValid();} the opcode value
5025f7980a51488db2ebcd7822c83c3f4b25a2a730Dan Bornstein     * itself
517ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein     * @param family {@code Opcodes.isValid();} the opcode family
527ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein     * @param nextOpcode {@code Opcodes.isValid();} what opcode (by
5325f7980a51488db2ebcd7822c83c3f4b25a2a730Dan Bornstein     * number) to try next when attempting to match an opcode to
547ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein     * particular arguments; {@code Opcodes.NO_NEXT} to indicate that
5525f7980a51488db2ebcd7822c83c3f4b25a2a730Dan Bornstein     * this is the last opcode to try in a particular chain
5699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param format {@code non-null;} the instruction format
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param hasResult whether the opcode has a result register; if so it
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is always the first register
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
60ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein    public Dop(int opcode, int family, int nextOpcode, InsnFormat format,
61a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein            boolean hasResult) {
627ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein        if (!Opcodes.isValidShape(opcode)) {
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("bogus opcode");
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
667ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein        if (!Opcodes.isValidShape(family)) {
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("bogus family");
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
707ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein        if (!Opcodes.isValidShape(nextOpcode)) {
71ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein            throw new IllegalArgumentException("bogus nextOpcode");
72ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein        }
73ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (format == null) {
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("format == null");
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.opcode = opcode;
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.family = family;
80ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein        this.nextOpcode = nextOpcode;
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.format = format;
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.hasResult = hasResult;
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String toString() {
88a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein        return getName();
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the opcode value.
93de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
947ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein     * @return {@code Opcodes.MIN_VALUE..Opcodes.MAX_VALUE;} the opcode value
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getOpcode() {
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return opcode;
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the opcode family. The opcode family is the unmarked (no
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "/...") opcode that has equivalent semantics to this one.
103de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
1047ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein     * @return {@code Opcodes.MIN_VALUE..Opcodes.MAX_VALUE;} the opcode family
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getFamily() {
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return family;
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the instruction format.
112de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
11399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the instruction format
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public InsnFormat getFormat() {
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return format;
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns whether this opcode uses a result register.
121de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
12299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code true} iff this opcode uses a result register
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean hasResult() {
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return hasResult;
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the opcode name.
130de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
13199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the opcode name
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String getName() {
134a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein        return OpcodeInfo.getName(opcode);
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
138ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein     * Gets the opcode value to try next when attempting to match an
139ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein     * opcode to particular arguments. This returns {@code
1407ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein     * Opcodes.NO_NEXT} to indicate that this is the last opcode to
141ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein     * try in a particular chain.
142ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein     *
1437ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein     * @return {@code Opcodes.MIN_VALUE..Opcodes.MAX_VALUE;} the opcode value
144ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein     */
145ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein    public int getNextOpcode() {
146ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein        return nextOpcode;
147ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein    }
148ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein
149ec85aa98842a86cb68664de8149f8ff495babe79Dan Bornstein    /**
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the opcode for the opposite test of this instance. This is only
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * valid for opcodes which are in fact tests.
152de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
15399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the opposite test
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Dop getOppositeTest() {
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (opcode) {
1577ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein            case Opcodes.IF_EQ:  return Dops.IF_NE;
1587ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein            case Opcodes.IF_NE:  return Dops.IF_EQ;
1597ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein            case Opcodes.IF_LT:  return Dops.IF_GE;
1607ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein            case Opcodes.IF_GE:  return Dops.IF_LT;
1617ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein            case Opcodes.IF_GT:  return Dops.IF_LE;
1627ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein            case Opcodes.IF_LE:  return Dops.IF_GT;
1637ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein            case Opcodes.IF_EQZ: return Dops.IF_NEZ;
1647ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein            case Opcodes.IF_NEZ: return Dops.IF_EQZ;
1657ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein            case Opcodes.IF_LTZ: return Dops.IF_GEZ;
1667ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein            case Opcodes.IF_GEZ: return Dops.IF_LTZ;
1677ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein            case Opcodes.IF_GTZ: return Dops.IF_LEZ;
1687ba91291bb6ce64691398a8751656207e8e3e98dDan Bornstein            case Opcodes.IF_LEZ: return Dops.IF_GTZ;
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throw new IllegalArgumentException("bogus opcode: " + this);
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
174