blob: 278a61d29dbf60740d0a5e5cb8fa176fde2313aa [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
Carl Shapiro12eb78e2011-06-24 14:51:06 -070041 enum Code {
jeffhaoba5ebb92011-08-25 17:24:37 -070042#define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a, v) cname = opcode,
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070043#include "dex_instruction_list.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070044 DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
Carl Shapirod84f49c2011-06-29 00:27:46 -070045#undef DEX_INSTRUCTION_LIST
Carl Shapiro12eb78e2011-06-24 14:51:06 -070046#undef INSTRUCTION_ENUM
Carl Shapirod84f49c2011-06-29 00:27:46 -070047 };
Carl Shapiro12eb78e2011-06-24 14:51:06 -070048
Elliott Hughesadb8c672012-03-06 16:49:32 -080049 enum Format {
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070050 k10x, // op
51 k12x, // op vA, vB
52 k11n, // op vA, #+B
53 k11x, // op vAA
54 k10t, // op +AA
jeffhaob4df5142011-09-19 20:25:32 -070055 k20bc, // op AA, kind@BBBB
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070056 k20t, // op +AAAA
57 k22x, // op vAA, vBBBB
58 k21t, // op vAA, +BBBB
59 k21s, // op vAA, #+BBBB
60 k21h, // op vAA, #+BBBB00000[00000000]
61 k21c, // op vAA, thing@BBBB
62 k23x, // op vAA, vBB, vCC
63 k22b, // op vAA, vBB, #+CC
64 k22t, // op vA, vB, +CCCC
65 k22s, // op vA, vB, #+CCCC
66 k22c, // op vA, vB, thing@CCCC
67 k32x, // op vAAAA, vBBBB
68 k30t, // op +AAAAAAAA
69 k31t, // op vAA, +BBBBBBBB
70 k31i, // op vAA, #+BBBBBBBB
71 k31c, // op vAA, thing@BBBBBBBB
72 k35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
73 k3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
74 k51l, // op vAA, #+BBBBBBBBBBBBBBBB
75 };
76
77 enum Flags {
78 kBranch = 0x01, // conditional or unconditional branch
79 kContinue = 0x02, // flow can continue to next statement
80 kSwitch = 0x04, // switch statement
81 kThrow = 0x08, // could cause an exception to be thrown
82 kReturn = 0x10, // returns, no additional statements
83 kInvoke = 0x20, // a flavor of invoke
84 // TODO: kUnconditional
85 };
86
jeffhaoba5ebb92011-08-25 17:24:37 -070087 enum VerifyFlag {
88 kVerifyNone = 0x00000,
89 kVerifyRegA = 0x00001,
90 kVerifyRegAWide = 0x00002,
91 kVerifyRegB = 0x00004,
92 kVerifyRegBField = 0x00008,
93 kVerifyRegBMethod = 0x00010,
94 kVerifyRegBNewInstance = 0x00020,
95 kVerifyRegBString = 0x00040,
96 kVerifyRegBType = 0x00080,
97 kVerifyRegBWide = 0x00100,
98 kVerifyRegC = 0x00200,
99 kVerifyRegCField = 0x00400,
100 kVerifyRegCNewArray = 0x00800,
101 kVerifyRegCType = 0x01000,
102 kVerifyRegCWide = 0x02000,
103 kVerifyArrayData = 0x04000,
104 kVerifyBranchTarget = 0x08000,
105 kVerifySwitchTargets = 0x10000,
106 kVerifyVarArg = 0x20000,
107 kVerifyVarArgRange = 0x40000,
108 kVerifyError = 0x80000,
109 };
110
111 // Decodes this instruction, populating its arguments.
112 void Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const;
113
Elliott Hughesadb8c672012-03-06 16:49:32 -0800114 // Returns the size (in 2 byte code units) of this instruction.
Ian Rogersd81871c2011-10-03 13:57:23 -0700115 size_t SizeInCodeUnits() const;
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700116
117 // Returns a pointer to the next instruction in the stream.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700118 const Instruction* Next() const;
119
Elliott Hughesadb8c672012-03-06 16:49:32 -0800120 // Returns the name of this instruction's opcode.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700121 const char* Name() const {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800122 return Instruction::Name(Opcode());
123 }
124
125 // Returns the name of the given opcode.
126 static const char* Name(Code opcode) {
127 return kInstructionNames[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700128 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700129
130 // Returns the opcode field of the instruction.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700131 Code Opcode() const;
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700132
133 // Reads an instruction out of the stream at the specified address.
Ian Rogersd81871c2011-10-03 13:57:23 -0700134 static const Instruction* At(const uint16_t* code) {
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700135 CHECK(code != NULL);
jeffhaoba5ebb92011-08-25 17:24:37 -0700136 return reinterpret_cast<const Instruction*>(code);
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700137 }
138
Elliott Hughesadb8c672012-03-06 16:49:32 -0800139 // Returns the format of the given opcode.
140 static Format FormatOf(Code opcode) {
141 return kInstructionFormats[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700142 }
143
Elliott Hughesadb8c672012-03-06 16:49:32 -0800144 // Returns the flags for the given opcode.
145 static int Flags(Code opcode) {
146 return kInstructionFlags[opcode];
jeffhaobdb76512011-09-07 11:43:16 -0700147 }
148
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700149 // Returns true if this instruction is a branch.
150 bool IsBranch() const {
151 return (kInstructionFlags[Opcode()] & kBranch) != 0;
152 }
153
jeffhaoba5ebb92011-08-25 17:24:37 -0700154 // Returns true if this instruction is a switch.
155 bool IsSwitch() const {
156 return (kInstructionFlags[Opcode()] & kSwitch) != 0;
157 }
158
159 // Returns true if this instruction can throw.
160 bool IsThrow() const {
161 return (kInstructionFlags[Opcode()] & kThrow) != 0;
162 }
163
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700164 // Determine if the instruction is any of 'return' instructions.
165 bool IsReturn() const {
166 return (kInstructionFlags[Opcode()] & kReturn) != 0;
167 }
168
169 // Determine if this instruction ends execution of its basic block.
170 bool IsBasicBlockEnd() const {
171 return IsBranch() || IsReturn() || Opcode() == THROW;
172 }
173
174 // Determine if this instruction is an invoke.
175 bool IsInvoke() const {
176 return (kInstructionFlags[Opcode()] & kInvoke) != 0;
177 }
178
jeffhaoba5ebb92011-08-25 17:24:37 -0700179 int GetVerifyTypeArgumentA() const {
180 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
181 }
182
183 int GetVerifyTypeArgumentB() const {
184 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod |
185 kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide));
186 }
187
188 int GetVerifyTypeArgumentC() const {
189 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
jeffhao3bb32462012-02-01 16:12:27 -0800190 kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide));
jeffhaoba5ebb92011-08-25 17:24:37 -0700191 }
192
193 int GetVerifyExtraFlags() const {
194 return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget |
195 kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError));
196 }
197
Ian Rogersd81871c2011-10-03 13:57:23 -0700198 // Dump decoded version of instruction
Ian Rogers2c8a8572011-10-24 17:11:36 -0700199 std::string DumpString(const DexFile*) const;
200
201 // Dump code_units worth of this instruction, padding to code_units for shorter instructions
202 std::string DumpHex(size_t code_units) const;
Ian Rogersd81871c2011-10-03 13:57:23 -0700203
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700204 private:
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700205 static const char* const kInstructionNames[];
Elliott Hughesadb8c672012-03-06 16:49:32 -0800206 static Format const kInstructionFormats[];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700207 static int const kInstructionFlags[];
jeffhaoba5ebb92011-08-25 17:24:37 -0700208 static int const kInstructionVerifyFlags[];
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700209 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
210};
Elliott Hughesadb8c672012-03-06 16:49:32 -0800211
212/*
213 * Holds the contents of a decoded instruction.
214 */
215struct DecodedInstruction {
216 uint32_t vA;
217 uint32_t vB;
218 uint64_t vB_wide; /* for k51l */
219 uint32_t vC;
220 uint32_t arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */
221 Instruction::Code opcode;
222
223 explicit DecodedInstruction(const Instruction* inst);
224};
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700225
226} // namespace art
227
228#endif // ART_SRC_DEX_INSTRUCTION_H_