blob: 48dbb0c949ac9740fac22dfc3224b8edef8d8629 [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
Ian Rogersdf1ce912012-11-27 17:07:11 -080041 struct PACKED(4) PackedSwitchPayload {
Logan Chien19c350a2012-05-01 19:21:32 +080042 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
Ian Rogersdf1ce912012-11-27 17:07:11 -080050 struct PACKED(4) SparseSwitchPayload {
Logan Chien19c350a2012-05-01 19:21:32 +080051 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
Ian Rogersdf1ce912012-11-27 17:07:11 -080068 struct PACKED(4) ArrayDataPayload {
Logan Chien19c350a2012-05-01 19:21:32 +080069 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
Ian Rogersa75a0132012-09-28 11:41:42 -070077 // TODO: the code layout below is deliberate to avoid this enum being picked up by
78 // generate-operator-out.py.
79 enum Code
80 {
jeffhaoba5ebb92011-08-25 17:24:37 -070081#define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a, v) cname = opcode,
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070082#include "dex_instruction_list.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070083 DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
Carl Shapirod84f49c2011-06-29 00:27:46 -070084#undef DEX_INSTRUCTION_LIST
Carl Shapiro12eb78e2011-06-24 14:51:06 -070085#undef INSTRUCTION_ENUM
Ian Rogersa75a0132012-09-28 11:41:42 -070086 } ;
Carl Shapiro12eb78e2011-06-24 14:51:06 -070087
Elliott Hughesadb8c672012-03-06 16:49:32 -080088 enum Format {
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070089 k10x, // op
90 k12x, // op vA, vB
91 k11n, // op vA, #+B
92 k11x, // op vAA
93 k10t, // op +AA
94 k20t, // op +AAAA
95 k22x, // op vAA, vBBBB
96 k21t, // op vAA, +BBBB
97 k21s, // op vAA, #+BBBB
98 k21h, // op vAA, #+BBBB00000[00000000]
99 k21c, // op vAA, thing@BBBB
100 k23x, // op vAA, vBB, vCC
101 k22b, // op vAA, vBB, #+CC
102 k22t, // op vA, vB, +CCCC
103 k22s, // op vA, vB, #+CCCC
104 k22c, // op vA, vB, thing@CCCC
105 k32x, // op vAAAA, vBBBB
106 k30t, // op +AAAAAAAA
107 k31t, // op vAA, +BBBBBBBB
108 k31i, // op vAA, #+BBBBBBBB
109 k31c, // op vAA, thing@BBBBBBBB
110 k35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
111 k3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
112 k51l, // op vAA, #+BBBBBBBBBBBBBBBB
113 };
114
115 enum Flags {
116 kBranch = 0x01, // conditional or unconditional branch
117 kContinue = 0x02, // flow can continue to next statement
118 kSwitch = 0x04, // switch statement
119 kThrow = 0x08, // could cause an exception to be thrown
120 kReturn = 0x10, // returns, no additional statements
121 kInvoke = 0x20, // a flavor of invoke
TDYa127526643e2012-05-26 01:01:48 -0700122 kUnconditional = 0x40, // unconditional branch
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700123 };
124
jeffhaoba5ebb92011-08-25 17:24:37 -0700125 enum VerifyFlag {
126 kVerifyNone = 0x00000,
127 kVerifyRegA = 0x00001,
128 kVerifyRegAWide = 0x00002,
129 kVerifyRegB = 0x00004,
130 kVerifyRegBField = 0x00008,
131 kVerifyRegBMethod = 0x00010,
132 kVerifyRegBNewInstance = 0x00020,
133 kVerifyRegBString = 0x00040,
134 kVerifyRegBType = 0x00080,
135 kVerifyRegBWide = 0x00100,
136 kVerifyRegC = 0x00200,
137 kVerifyRegCField = 0x00400,
138 kVerifyRegCNewArray = 0x00800,
139 kVerifyRegCType = 0x01000,
140 kVerifyRegCWide = 0x02000,
141 kVerifyArrayData = 0x04000,
142 kVerifyBranchTarget = 0x08000,
143 kVerifySwitchTargets = 0x10000,
144 kVerifyVarArg = 0x20000,
145 kVerifyVarArgRange = 0x40000,
146 kVerifyError = 0x80000,
147 };
148
149 // Decodes this instruction, populating its arguments.
150 void Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const;
151
Elliott Hughesadb8c672012-03-06 16:49:32 -0800152 // Returns the size (in 2 byte code units) of this instruction.
Ian Rogersa75a0132012-09-28 11:41:42 -0700153 size_t SizeInCodeUnits() const {
154 int result = kInstructionSizeInCodeUnits[Opcode()];
155 if (UNLIKELY(result < 0)) {
156 return SizeInCodeUnitsComplexOpcode();
157 } else {
158 return static_cast<size_t>(result);
159 }
160 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700161
162 // Returns a pointer to the next instruction in the stream.
Ian Rogersa75a0132012-09-28 11:41:42 -0700163 const Instruction* Next() const {
164 size_t current_size_in_bytes = SizeInCodeUnits() * sizeof(uint16_t);
165 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
166 return reinterpret_cast<const Instruction*>(ptr + current_size_in_bytes);
167 }
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700168
Elliott Hughesadb8c672012-03-06 16:49:32 -0800169 // Returns the name of this instruction's opcode.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700170 const char* Name() const {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800171 return Instruction::Name(Opcode());
172 }
173
174 // Returns the name of the given opcode.
175 static const char* Name(Code opcode) {
176 return kInstructionNames[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700177 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700178
179 // Returns the opcode field of the instruction.
Ian Rogersa75a0132012-09-28 11:41:42 -0700180 Code Opcode() const {
181 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
182 int opcode = *insns & 0xFF;
183 return static_cast<Code>(opcode);
184 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700185
186 // Reads an instruction out of the stream at the specified address.
Ian Rogersd81871c2011-10-03 13:57:23 -0700187 static const Instruction* At(const uint16_t* code) {
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700188 CHECK(code != NULL);
jeffhaoba5ebb92011-08-25 17:24:37 -0700189 return reinterpret_cast<const Instruction*>(code);
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700190 }
191
Elliott Hughesadb8c672012-03-06 16:49:32 -0800192 // Returns the format of the given opcode.
193 static Format FormatOf(Code opcode) {
194 return kInstructionFormats[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700195 }
196
Elliott Hughesadb8c672012-03-06 16:49:32 -0800197 // Returns the flags for the given opcode.
Ian Rogersa75a0132012-09-28 11:41:42 -0700198 static int FlagsOf(Code opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800199 return kInstructionFlags[opcode];
jeffhaobdb76512011-09-07 11:43:16 -0700200 }
201
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700202 // Returns true if this instruction is a branch.
203 bool IsBranch() const {
204 return (kInstructionFlags[Opcode()] & kBranch) != 0;
205 }
206
TDYa127526643e2012-05-26 01:01:48 -0700207 // Returns true if this instruction is a unconditional branch.
208 bool IsUnconditional() const {
209 return (kInstructionFlags[Opcode()] & kUnconditional) != 0;
210 }
211
jeffhaoba5ebb92011-08-25 17:24:37 -0700212 // Returns true if this instruction is a switch.
213 bool IsSwitch() const {
214 return (kInstructionFlags[Opcode()] & kSwitch) != 0;
215 }
216
217 // Returns true if this instruction can throw.
218 bool IsThrow() const {
219 return (kInstructionFlags[Opcode()] & kThrow) != 0;
220 }
221
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700222 // Determine if the instruction is any of 'return' instructions.
223 bool IsReturn() const {
224 return (kInstructionFlags[Opcode()] & kReturn) != 0;
225 }
226
227 // Determine if this instruction ends execution of its basic block.
228 bool IsBasicBlockEnd() const {
229 return IsBranch() || IsReturn() || Opcode() == THROW;
230 }
231
232 // Determine if this instruction is an invoke.
233 bool IsInvoke() const {
234 return (kInstructionFlags[Opcode()] & kInvoke) != 0;
235 }
236
jeffhaoba5ebb92011-08-25 17:24:37 -0700237 int GetVerifyTypeArgumentA() const {
238 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
239 }
240
241 int GetVerifyTypeArgumentB() const {
242 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod |
243 kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide));
244 }
245
246 int GetVerifyTypeArgumentC() const {
247 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
jeffhao3bb32462012-02-01 16:12:27 -0800248 kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide));
jeffhaoba5ebb92011-08-25 17:24:37 -0700249 }
250
251 int GetVerifyExtraFlags() const {
252 return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget |
253 kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError));
254 }
255
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700256 // Get the dex PC of this instruction as a offset in code units from the beginning of insns.
257 uint32_t GetDexPc(const uint16_t* insns) const {
258 return (reinterpret_cast<const uint16_t*>(this) - insns);
259 }
260
Ian Rogersd81871c2011-10-03 13:57:23 -0700261 // Dump decoded version of instruction
Ian Rogers2c8a8572011-10-24 17:11:36 -0700262 std::string DumpString(const DexFile*) const;
263
264 // Dump code_units worth of this instruction, padding to code_units for shorter instructions
265 std::string DumpHex(size_t code_units) const;
Ian Rogersd81871c2011-10-03 13:57:23 -0700266
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700267 private:
Ian Rogersa75a0132012-09-28 11:41:42 -0700268 size_t SizeInCodeUnitsComplexOpcode() const;
269
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700270 static const char* const kInstructionNames[];
Elliott Hughesadb8c672012-03-06 16:49:32 -0800271 static Format const kInstructionFormats[];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700272 static int const kInstructionFlags[];
jeffhaoba5ebb92011-08-25 17:24:37 -0700273 static int const kInstructionVerifyFlags[];
Ian Rogersa75a0132012-09-28 11:41:42 -0700274 static int const kInstructionSizeInCodeUnits[];
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700275 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
276};
Ian Rogersa75a0132012-09-28 11:41:42 -0700277std::ostream& operator<<(std::ostream& os, const Instruction::Code& code);
278std::ostream& operator<<(std::ostream& os, const Instruction::Format& format);
279std::ostream& operator<<(std::ostream& os, const Instruction::Flags& flags);
280std::ostream& operator<<(std::ostream& os, const Instruction::VerifyFlag& vflags);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800281
282/*
283 * Holds the contents of a decoded instruction.
284 */
285struct DecodedInstruction {
286 uint32_t vA;
287 uint32_t vB;
288 uint64_t vB_wide; /* for k51l */
289 uint32_t vC;
290 uint32_t arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */
291 Instruction::Code opcode;
292
Ian Rogersa75a0132012-09-28 11:41:42 -0700293 explicit DecodedInstruction(const Instruction* inst) {
294 inst->Decode(vA, vB, vB_wide, vC, arg);
295 opcode = inst->Opcode();
296 }
Elliott Hughesadb8c672012-03-06 16:49:32 -0800297};
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700298
299} // namespace art
300
301#endif // ART_SRC_DEX_INSTRUCTION_H_