OSDN Git Service

d987ef42f1056414d66eff7f359555cf133533c7
[android-x86/dalvik.git] / libdex / InstrUtils.h
1 /*
2  * Copyright (C) 2008 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
17 /*
18  * Dalvik instruction utility functions.
19  */
20 #ifndef _LIBDEX_INSTRUTILS
21 #define _LIBDEX_INSTRUTILS
22
23 #include "DexFile.h"
24 #include "OpCode.h"
25
26 /*
27  * Dalvik-defined instruction formats.
28  *
29  * (This defines InstructionFormat as an unsigned char to reduce the size
30  * of the table.  This isn't necessary with some compilers, which use an
31  * integer width appropriate for the number of enum values.)
32  *
33  * If you add or delete a format, you have to change some or all of:
34  *  - this enum
35  *  - the switch inside dexDecodeInstruction() in InstrUtils.c
36  *  - the switch inside dumpInstruction() in DexDump.c
37  */
38 typedef unsigned char InstructionFormat;
39 enum InstructionFormat {
40     kFmtUnknown = 0,
41     kFmt10x,        // op
42     kFmt12x,        // op vA, vB
43     kFmt11n,        // op vA, #+B
44     kFmt11x,        // op vAA
45     kFmt10t,        // op +AA
46     kFmt20bc,       // [opt] op AA, thing@BBBB
47     kFmt20t,        // op +AAAA
48     kFmt22x,        // op vAA, vBBBB
49     kFmt21t,        // op vAA, +BBBB
50     kFmt21s,        // op vAA, #+BBBB
51     kFmt21h,        // op vAA, #+BBBB00000[00000000]
52     kFmt21c,        // op vAA, thing@BBBB
53     kFmt23x,        // op vAA, vBB, vCC
54     kFmt22b,        // op vAA, vBB, #+CC
55     kFmt22t,        // op vA, vB, +CCCC
56     kFmt22s,        // op vA, vB, #+CCCC
57     kFmt22c,        // op vA, vB, thing@CCCC
58     kFmt22cs,       // [opt] op vA, vB, field offset CCCC
59     kFmt30t,        // op +AAAAAAAA
60     kFmt32x,        // op vAAAA, vBBBB
61     kFmt31i,        // op vAA, #+BBBBBBBB
62     kFmt31t,        // op vAA, +BBBBBBBB
63     kFmt31c,        // op vAA, string@BBBBBBBB
64     kFmt35c,        // op {vD, vE, vF, vG, vA}, thing@CCCC (decoded differently)
65     kFmt35ms,       // [opt] invoke-virtual+super
66     kFmt35fs,       // [opt] invoke-interface
67     kFmt3rc,        // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
68     kFmt3rms,       // [opt] invoke-virtual+super/range
69     kFmt51l,        // op vAA, #+BBBBBBBBBBBBBBBB
70     kFmt3inline,    // [opt] inline invoke
71     kFmt3rinline,   // [opt] inline invoke/range
72 };
73
74 /*
75  * Holds the contents of a decoded instruction.
76  */
77 typedef struct DecodedInstruction {
78     u4      vA;
79     u4      vB;
80     u8      vB_wide;        /* for kFmt51l */
81     u4      vC;
82     u4      arg[5];         /* vC/D/E/F/G in invoke or filled-new-array */
83     OpCode  opCode;
84 } DecodedInstruction;
85
86 /*
87  * Instruction width, a value in the range -3 to 5.
88  */
89 typedef signed char InstructionWidth;
90
91 /*
92  * Instruction flags, used by the verifier and JIT to determine where
93  * control can flow to next.  Expected to fit in 8 bits.
94  */
95 typedef unsigned char InstructionFlags;
96 enum InstructionFlags {
97     kInstrCanBranch     = 1,        // conditional or unconditional branch
98     kInstrCanContinue   = 1 << 1,   // flow can continue to next statement
99     kInstrCanSwitch     = 1 << 2,   // switch statement
100     kInstrCanThrow      = 1 << 3,   // could cause an exception to be thrown
101     kInstrCanReturn     = 1 << 4,   // returns, no additional statements
102     kInstrInvoke        = 1 << 5,   // a flavor of invoke
103     kInstrUnconditional = 1 << 6,   // unconditional branch
104 };
105
106
107 /*
108  * Allocate and populate a 256-element array with instruction widths.  A
109  * width of zero means the entry does not exist.
110  */
111 InstructionWidth* dexCreateInstrWidthTable(void);
112
113 #if 0       // no longer used
114 /*
115  * Returns the width of the specified instruction, or 0 if not defined.
116  * Optimized instructions use negative values.
117  */
118 DEX_INLINE int dexGetInstrWidth(const InstructionWidth* widths, OpCode opCode)
119 {
120    // assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
121     return widths[opCode];
122 }
123 #endif
124
125 /*
126  * Return the width of the specified instruction, or 0 if not defined.
127  */
128 DEX_INLINE size_t dexGetInstrWidthAbs(const InstructionWidth* widths,
129     OpCode opCode)
130 {
131     //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
132
133     int val = widths[opCode];
134     if (val < 0)
135         val = -val;
136     /* XXX - the no-compare trick may be a cycle slower on ARM */
137     return val;
138 }
139
140 /*
141  * Return the width of the specified instruction, or 0 if not defined.  Also
142  * works for special OP_NOP entries, including switch statement data tables
143  * and array data.
144  */
145 size_t dexGetInstrOrTableWidthAbs(const InstructionWidth* widths,
146     const u2* insns);
147
148
149 /*
150  * Allocate and populate a 256-element array with instruction flags.
151  */
152 InstructionFlags* dexCreateInstrFlagsTable(void);
153
154 /*
155  * Returns the flags for the specified opcode.
156  */
157 DEX_INLINE int dexGetInstrFlags(const InstructionFlags* flags, OpCode opCode)
158 {
159     //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
160     return flags[opCode];
161 }
162
163
164 /*
165  * Allocate and populate a 256-element array with instruction formats.
166  */
167 InstructionFormat* dexCreateInstrFormatTable(void);
168
169 /*
170  * Return the instruction format for the specified opcode.
171  */
172 DEX_INLINE InstructionFormat dexGetInstrFormat(const InstructionFormat* fmts,
173     OpCode opCode)
174 {
175     //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
176     return fmts[opCode];
177 }
178
179 /*
180  * Decode the instruction pointed to by "insns".
181  */
182 void dexDecodeInstruction(const InstructionFormat* fmts, const u2* insns,
183     DecodedInstruction* pDec);
184
185 #endif /*_LIBDEX_INSTRUTILS*/