blob: b33b0017ae1960d2c63857f4a4af44ea19d0154d [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 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 */
Carl Shapiro12eb78e2011-06-24 14:51:06 -070016
17#ifndef ART_SRC_DEX_INSTRUCTION_H_
18#define ART_SRC_DEX_INSTRUCTION_H_
19
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070020#include "globals.h"
21#include "logging.h"
22#include "macros.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070023
24namespace art {
25
Ian Rogersd81871c2011-10-03 13:57:23 -070026class DexFile;
27
Elliott Hughesadb8c672012-03-06 16:49:32 -080028enum {
29 kNumPackedOpcodes = 0x100
30};
31
Carl Shapiro12eb78e2011-06-24 14:51:06 -070032class Instruction {
33 public:
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070034 // NOP-encoded switch-statement signatures.
35 enum {
36 kPackedSwitchSignature = 0x0100,
37 kSparseSwitchSignature = 0x0200,
Elliott Hughesadb8c672012-03-06 16:49:32 -080038 kArrayDataSignature = 0x0300,
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070039 };
40
Logan Chien19c350a2012-05-01 19:21:32 +080041 struct PACKED PackedSwitchPayload {
42 const uint16_t ident;
43 const uint16_t case_count;
44 const int32_t first_key;
45 const int32_t targets[];
46 private:
47 DISALLOW_COPY_AND_ASSIGN(PackedSwitchPayload);
48 };
49
50 struct PACKED SparseSwitchPayload {
51 const uint16_t ident;
52 const uint16_t case_count;
53 const int32_t keys_and_targets[];
54
55 public:
56 const int32_t* GetKeys() const {
57 return keys_and_targets;
58 }
59
60 const int32_t* GetTargets() const {
61 return keys_and_targets + case_count;
62 }
63
64 private:
65 DISALLOW_COPY_AND_ASSIGN(SparseSwitchPayload);
66 };
67
68 struct PACKED ArrayDataPayload {
69 const uint16_t ident;
70 const uint16_t element_width;
71 const uint32_t element_count;
72 const uint8_t data[];
73 private:
74 DISALLOW_COPY_AND_ASSIGN(ArrayDataPayload);
75 };
76
Carl Shapiro12eb78e2011-06-24 14:51:06 -070077 enum Code {
jeffhaoba5ebb92011-08-25 17:24:37 -070078#define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a, v) cname = opcode,
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070079#include "dex_instruction_list.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070080 DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
Carl Shapirod84f49c2011-06-29 00:27:46 -070081#undef DEX_INSTRUCTION_LIST
Carl Shapiro12eb78e2011-06-24 14:51:06 -070082#undef INSTRUCTION_ENUM
Carl Shapirod84f49c2011-06-29 00:27:46 -070083 };
Carl Shapiro12eb78e2011-06-24 14:51:06 -070084
Elliott Hughesadb8c672012-03-06 16:49:32 -080085 enum Format {
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070086 k10x, // op
87 k12x, // op vA, vB
88 k11n, // op vA, #+B
89 k11x, // op vAA
90 k10t, // op +AA
jeffhaob4df5142011-09-19 20:25:32 -070091 k20bc, // op AA, kind@BBBB
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070092 k20t, // op +AAAA
93 k22x, // op vAA, vBBBB
94 k21t, // op vAA, +BBBB
95 k21s, // op vAA, #+BBBB
96 k21h, // op vAA, #+BBBB00000[00000000]
97 k21c, // op vAA, thing@BBBB
98 k23x, // op vAA, vBB, vCC
99 k22b, // op vAA, vBB, #+CC
100 k22t, // op vA, vB, +CCCC
101 k22s, // op vA, vB, #+CCCC
102 k22c, // op vA, vB, thing@CCCC
103 k32x, // op vAAAA, vBBBB
104 k30t, // op +AAAAAAAA
105 k31t, // op vAA, +BBBBBBBB
106 k31i, // op vAA, #+BBBBBBBB
107 k31c, // op vAA, thing@BBBBBBBB
108 k35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
109 k3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
110 k51l, // op vAA, #+BBBBBBBBBBBBBBBB
111 };
112
113 enum Flags {
114 kBranch = 0x01, // conditional or unconditional branch
115 kContinue = 0x02, // flow can continue to next statement
116 kSwitch = 0x04, // switch statement
117 kThrow = 0x08, // could cause an exception to be thrown
118 kReturn = 0x10, // returns, no additional statements
119 kInvoke = 0x20, // a flavor of invoke
120 // TODO: kUnconditional
121 };
122
jeffhaoba5ebb92011-08-25 17:24:37 -0700123 enum VerifyFlag {
124 kVerifyNone = 0x00000,
125 kVerifyRegA = 0x00001,
126 kVerifyRegAWide = 0x00002,
127 kVerifyRegB = 0x00004,
128 kVerifyRegBField = 0x00008,
129 kVerifyRegBMethod = 0x00010,
130 kVerifyRegBNewInstance = 0x00020,
131 kVerifyRegBString = 0x00040,
132 kVerifyRegBType = 0x00080,
133 kVerifyRegBWide = 0x00100,
134 kVerifyRegC = 0x00200,
135 kVerifyRegCField = 0x00400,
136 kVerifyRegCNewArray = 0x00800,
137 kVerifyRegCType = 0x01000,
138 kVerifyRegCWide = 0x02000,
139 kVerifyArrayData = 0x04000,
140 kVerifyBranchTarget = 0x08000,
141 kVerifySwitchTargets = 0x10000,
142 kVerifyVarArg = 0x20000,
143 kVerifyVarArgRange = 0x40000,
144 kVerifyError = 0x80000,
145 };
146
147 // Decodes this instruction, populating its arguments.
148 void Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const;
149
Elliott Hughesadb8c672012-03-06 16:49:32 -0800150 // Returns the size (in 2 byte code units) of this instruction.
Ian Rogersd81871c2011-10-03 13:57:23 -0700151 size_t SizeInCodeUnits() const;
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700152
153 // Returns a pointer to the next instruction in the stream.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700154 const Instruction* Next() const;
155
Elliott Hughesadb8c672012-03-06 16:49:32 -0800156 // Returns the name of this instruction's opcode.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700157 const char* Name() const {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800158 return Instruction::Name(Opcode());
159 }
160
161 // Returns the name of the given opcode.
162 static const char* Name(Code opcode) {
163 return kInstructionNames[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700164 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700165
166 // Returns the opcode field of the instruction.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700167 Code Opcode() const;
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700168
169 // Reads an instruction out of the stream at the specified address.
Ian Rogersd81871c2011-10-03 13:57:23 -0700170 static const Instruction* At(const uint16_t* code) {
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700171 CHECK(code != NULL);
jeffhaoba5ebb92011-08-25 17:24:37 -0700172 return reinterpret_cast<const Instruction*>(code);
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700173 }
174
Elliott Hughesadb8c672012-03-06 16:49:32 -0800175 // Returns the format of the given opcode.
176 static Format FormatOf(Code opcode) {
177 return kInstructionFormats[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700178 }
179
Elliott Hughesadb8c672012-03-06 16:49:32 -0800180 // Returns the flags for the given opcode.
181 static int Flags(Code opcode) {
182 return kInstructionFlags[opcode];
jeffhaobdb76512011-09-07 11:43:16 -0700183 }
184
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700185 // Returns true if this instruction is a branch.
186 bool IsBranch() const {
187 return (kInstructionFlags[Opcode()] & kBranch) != 0;
188 }
189
jeffhaoba5ebb92011-08-25 17:24:37 -0700190 // Returns true if this instruction is a switch.
191 bool IsSwitch() const {
192 return (kInstructionFlags[Opcode()] & kSwitch) != 0;
193 }
194
195 // Returns true if this instruction can throw.
196 bool IsThrow() const {
197 return (kInstructionFlags[Opcode()] & kThrow) != 0;
198 }
199
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700200 // Determine if the instruction is any of 'return' instructions.
201 bool IsReturn() const {
202 return (kInstructionFlags[Opcode()] & kReturn) != 0;
203 }
204
205 // Determine if this instruction ends execution of its basic block.
206 bool IsBasicBlockEnd() const {
207 return IsBranch() || IsReturn() || Opcode() == THROW;
208 }
209
210 // Determine if this instruction is an invoke.
211 bool IsInvoke() const {
212 return (kInstructionFlags[Opcode()] & kInvoke) != 0;
213 }
214
jeffhaoba5ebb92011-08-25 17:24:37 -0700215 int GetVerifyTypeArgumentA() const {
216 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
217 }
218
219 int GetVerifyTypeArgumentB() const {
220 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod |
221 kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide));
222 }
223
224 int GetVerifyTypeArgumentC() const {
225 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
jeffhao3bb32462012-02-01 16:12:27 -0800226 kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide));
jeffhaoba5ebb92011-08-25 17:24:37 -0700227 }
228
229 int GetVerifyExtraFlags() const {
230 return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget |
231 kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError));
232 }
233
Ian Rogersd81871c2011-10-03 13:57:23 -0700234 // Dump decoded version of instruction
Ian Rogers2c8a8572011-10-24 17:11:36 -0700235 std::string DumpString(const DexFile*) const;
236
237 // Dump code_units worth of this instruction, padding to code_units for shorter instructions
238 std::string DumpHex(size_t code_units) const;
Ian Rogersd81871c2011-10-03 13:57:23 -0700239
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700240 private:
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700241 static const char* const kInstructionNames[];
Elliott Hughesadb8c672012-03-06 16:49:32 -0800242 static Format const kInstructionFormats[];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700243 static int const kInstructionFlags[];
jeffhaoba5ebb92011-08-25 17:24:37 -0700244 static int const kInstructionVerifyFlags[];
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700245 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
246};
Elliott Hughesadb8c672012-03-06 16:49:32 -0800247
248/*
249 * Holds the contents of a decoded instruction.
250 */
251struct DecodedInstruction {
252 uint32_t vA;
253 uint32_t vB;
254 uint64_t vB_wide; /* for k51l */
255 uint32_t vC;
256 uint32_t arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */
257 Instruction::Code opcode;
258
259 explicit DecodedInstruction(const Instruction* inst);
260};
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700261
262} // namespace art
263
264#endif // ART_SRC_DEX_INSTRUCTION_H_