blob: 26e5653b5a19c0fef599dfb3da858bc57b011292 [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
Carl Shapiro12eb78e2011-06-24 14:51:06 -070028class Instruction {
29 public:
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070030 // NOP-encoded switch-statement signatures.
31 enum {
32 kPackedSwitchSignature = 0x0100,
33 kSparseSwitchSignature = 0x0200,
34 kArrayDataSignature = 0x0300
35 };
36
Carl Shapiro12eb78e2011-06-24 14:51:06 -070037 enum Code {
jeffhaoba5ebb92011-08-25 17:24:37 -070038#define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a, v) cname = opcode,
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070039#include "dex_instruction_list.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070040 DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
Carl Shapirod84f49c2011-06-29 00:27:46 -070041#undef DEX_INSTRUCTION_LIST
Carl Shapiro12eb78e2011-06-24 14:51:06 -070042#undef INSTRUCTION_ENUM
Carl Shapirod84f49c2011-06-29 00:27:46 -070043 };
Carl Shapiro12eb78e2011-06-24 14:51:06 -070044
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070045 enum InstructionFormat {
46 k10x, // op
47 k12x, // op vA, vB
48 k11n, // op vA, #+B
49 k11x, // op vAA
50 k10t, // op +AA
jeffhaob4df5142011-09-19 20:25:32 -070051 k20bc, // op AA, kind@BBBB
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070052 k20t, // op +AAAA
53 k22x, // op vAA, vBBBB
54 k21t, // op vAA, +BBBB
55 k21s, // op vAA, #+BBBB
56 k21h, // op vAA, #+BBBB00000[00000000]
57 k21c, // op vAA, thing@BBBB
58 k23x, // op vAA, vBB, vCC
59 k22b, // op vAA, vBB, #+CC
60 k22t, // op vA, vB, +CCCC
61 k22s, // op vA, vB, #+CCCC
62 k22c, // op vA, vB, thing@CCCC
63 k32x, // op vAAAA, vBBBB
64 k30t, // op +AAAAAAAA
65 k31t, // op vAA, +BBBBBBBB
66 k31i, // op vAA, #+BBBBBBBB
67 k31c, // op vAA, thing@BBBBBBBB
68 k35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
69 k3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
70 k51l, // op vAA, #+BBBBBBBBBBBBBBBB
71 };
72
73 enum Flags {
74 kBranch = 0x01, // conditional or unconditional branch
75 kContinue = 0x02, // flow can continue to next statement
76 kSwitch = 0x04, // switch statement
77 kThrow = 0x08, // could cause an exception to be thrown
78 kReturn = 0x10, // returns, no additional statements
79 kInvoke = 0x20, // a flavor of invoke
80 // TODO: kUnconditional
81 };
82
jeffhaoba5ebb92011-08-25 17:24:37 -070083 enum VerifyFlag {
84 kVerifyNone = 0x00000,
85 kVerifyRegA = 0x00001,
86 kVerifyRegAWide = 0x00002,
87 kVerifyRegB = 0x00004,
88 kVerifyRegBField = 0x00008,
89 kVerifyRegBMethod = 0x00010,
90 kVerifyRegBNewInstance = 0x00020,
91 kVerifyRegBString = 0x00040,
92 kVerifyRegBType = 0x00080,
93 kVerifyRegBWide = 0x00100,
94 kVerifyRegC = 0x00200,
95 kVerifyRegCField = 0x00400,
96 kVerifyRegCNewArray = 0x00800,
97 kVerifyRegCType = 0x01000,
98 kVerifyRegCWide = 0x02000,
99 kVerifyArrayData = 0x04000,
100 kVerifyBranchTarget = 0x08000,
101 kVerifySwitchTargets = 0x10000,
102 kVerifyVarArg = 0x20000,
103 kVerifyVarArgRange = 0x40000,
104 kVerifyError = 0x80000,
105 };
106
jeffhaobdb76512011-09-07 11:43:16 -0700107 /*
108 * Holds the contents of a decoded instruction.
109 */
110 struct DecodedInstruction {
111 uint32_t vA_;
112 uint32_t vB_;
113 uint64_t vB_wide_; /* for kFmt51l */
114 uint32_t vC_;
115 uint32_t arg_[5]; /* vC/D/E/F/G in invoke or filled-new-array */
116 Code opcode_;
117
Elliott Hughesa51a3dd2011-10-17 15:19:26 -0700118 explicit DecodedInstruction(const Instruction* inst) {
jeffhaobdb76512011-09-07 11:43:16 -0700119 inst->Decode(vA_, vB_, vB_wide_, vC_, arg_);
120 opcode_ = inst->Opcode();
121 }
122 };
123
jeffhaoba5ebb92011-08-25 17:24:37 -0700124 // Decodes this instruction, populating its arguments.
125 void Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const;
126
Ian Rogersd81871c2011-10-03 13:57:23 -0700127 // Returns the size in 2 byte code units, for this instruction.
128 size_t SizeInCodeUnits() const;
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700129
130 // Returns a pointer to the next instruction in the stream.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700131 const Instruction* Next() const;
132
133 // Name of the instruction.
134 const char* Name() const {
135 return kInstructionNames[Opcode()];
136 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700137
138 // Returns the opcode field of the instruction.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700139 Code Opcode() const;
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700140
141 // Reads an instruction out of the stream at the specified address.
Ian Rogersd81871c2011-10-03 13:57:23 -0700142 static const Instruction* At(const uint16_t* code) {
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700143 CHECK(code != NULL);
jeffhaoba5ebb92011-08-25 17:24:37 -0700144 return reinterpret_cast<const Instruction*>(code);
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700145 }
146
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700147 // Returns the format of the current instruction.
148 InstructionFormat Format() const {
149 return kInstructionFormats[Opcode()];
150 }
151
jeffhaobdb76512011-09-07 11:43:16 -0700152 // Returns the flags for the current instruction.
153 int Flag() const {
154 return kInstructionFlags[Opcode()];
155 }
156
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700157 // Returns true if this instruction is a branch.
158 bool IsBranch() const {
159 return (kInstructionFlags[Opcode()] & kBranch) != 0;
160 }
161
jeffhaoba5ebb92011-08-25 17:24:37 -0700162 // Returns true if this instruction is a switch.
163 bool IsSwitch() const {
164 return (kInstructionFlags[Opcode()] & kSwitch) != 0;
165 }
166
167 // Returns true if this instruction can throw.
168 bool IsThrow() const {
169 return (kInstructionFlags[Opcode()] & kThrow) != 0;
170 }
171
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700172 // Determine if the instruction is any of 'return' instructions.
173 bool IsReturn() const {
174 return (kInstructionFlags[Opcode()] & kReturn) != 0;
175 }
176
177 // Determine if this instruction ends execution of its basic block.
178 bool IsBasicBlockEnd() const {
179 return IsBranch() || IsReturn() || Opcode() == THROW;
180 }
181
182 // Determine if this instruction is an invoke.
183 bool IsInvoke() const {
184 return (kInstructionFlags[Opcode()] & kInvoke) != 0;
185 }
186
jeffhaoba5ebb92011-08-25 17:24:37 -0700187 int GetVerifyTypeArgumentA() const {
188 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
189 }
190
191 int GetVerifyTypeArgumentB() const {
192 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod |
193 kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide));
194 }
195
196 int GetVerifyTypeArgumentC() const {
197 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
198 kVerifyRegCNewArray | kVerifyRegBType | kVerifyRegBWide));
199 }
200
201 int GetVerifyExtraFlags() const {
202 return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget |
203 kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError));
204 }
205
Ian Rogersd81871c2011-10-03 13:57:23 -0700206 // Dump decoded version of instruction
Ian Rogers2c8a8572011-10-24 17:11:36 -0700207 std::string DumpString(const DexFile*) const;
208
209 // Dump code_units worth of this instruction, padding to code_units for shorter instructions
210 std::string DumpHex(size_t code_units) const;
Ian Rogersd81871c2011-10-03 13:57:23 -0700211
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700212 private:
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700213 static const char* const kInstructionNames[];
214 static InstructionFormat const kInstructionFormats[];
215 static int const kInstructionFlags[];
jeffhaoba5ebb92011-08-25 17:24:37 -0700216 static int const kInstructionVerifyFlags[];
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700217 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
218};
Ian Rogersd81871c2011-10-03 13:57:23 -0700219std::ostream& operator<<(std::ostream& os, const Instruction& rhs);
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700220
221} // namespace art
222
223#endif // ART_SRC_DEX_INSTRUCTION_H_