blob: 36ea2955629ff6882e0abbbf1763bb868990d732 [file] [log] [blame]
Carl Shapiro12eb78e2011-06-24 14:51:06 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#ifndef ART_SRC_DEX_INSTRUCTION_H_
4#define ART_SRC_DEX_INSTRUCTION_H_
5
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07006#include "globals.h"
7#include "logging.h"
8#include "macros.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -07009
10namespace art {
11
Ian Rogersd81871c2011-10-03 13:57:23 -070012class DexFile;
13
Carl Shapiro12eb78e2011-06-24 14:51:06 -070014class Instruction {
15 public:
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070016 // NOP-encoded switch-statement signatures.
17 enum {
18 kPackedSwitchSignature = 0x0100,
19 kSparseSwitchSignature = 0x0200,
20 kArrayDataSignature = 0x0300
21 };
22
Carl Shapiro12eb78e2011-06-24 14:51:06 -070023 enum Code {
jeffhaoba5ebb92011-08-25 17:24:37 -070024#define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a, v) cname = opcode,
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070025#include "dex_instruction_list.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070026 DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
Carl Shapirod84f49c2011-06-29 00:27:46 -070027#undef DEX_INSTRUCTION_LIST
Carl Shapiro12eb78e2011-06-24 14:51:06 -070028#undef INSTRUCTION_ENUM
Carl Shapirod84f49c2011-06-29 00:27:46 -070029 };
Carl Shapiro12eb78e2011-06-24 14:51:06 -070030
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070031 enum InstructionFormat {
32 k10x, // op
33 k12x, // op vA, vB
34 k11n, // op vA, #+B
35 k11x, // op vAA
36 k10t, // op +AA
jeffhaob4df5142011-09-19 20:25:32 -070037 k20bc, // op AA, kind@BBBB
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070038 k20t, // op +AAAA
39 k22x, // op vAA, vBBBB
40 k21t, // op vAA, +BBBB
41 k21s, // op vAA, #+BBBB
42 k21h, // op vAA, #+BBBB00000[00000000]
43 k21c, // op vAA, thing@BBBB
44 k23x, // op vAA, vBB, vCC
45 k22b, // op vAA, vBB, #+CC
46 k22t, // op vA, vB, +CCCC
47 k22s, // op vA, vB, #+CCCC
48 k22c, // op vA, vB, thing@CCCC
49 k32x, // op vAAAA, vBBBB
50 k30t, // op +AAAAAAAA
51 k31t, // op vAA, +BBBBBBBB
52 k31i, // op vAA, #+BBBBBBBB
53 k31c, // op vAA, thing@BBBBBBBB
54 k35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
55 k3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
56 k51l, // op vAA, #+BBBBBBBBBBBBBBBB
57 };
58
59 enum Flags {
60 kBranch = 0x01, // conditional or unconditional branch
61 kContinue = 0x02, // flow can continue to next statement
62 kSwitch = 0x04, // switch statement
63 kThrow = 0x08, // could cause an exception to be thrown
64 kReturn = 0x10, // returns, no additional statements
65 kInvoke = 0x20, // a flavor of invoke
66 // TODO: kUnconditional
67 };
68
jeffhaoba5ebb92011-08-25 17:24:37 -070069 enum VerifyFlag {
70 kVerifyNone = 0x00000,
71 kVerifyRegA = 0x00001,
72 kVerifyRegAWide = 0x00002,
73 kVerifyRegB = 0x00004,
74 kVerifyRegBField = 0x00008,
75 kVerifyRegBMethod = 0x00010,
76 kVerifyRegBNewInstance = 0x00020,
77 kVerifyRegBString = 0x00040,
78 kVerifyRegBType = 0x00080,
79 kVerifyRegBWide = 0x00100,
80 kVerifyRegC = 0x00200,
81 kVerifyRegCField = 0x00400,
82 kVerifyRegCNewArray = 0x00800,
83 kVerifyRegCType = 0x01000,
84 kVerifyRegCWide = 0x02000,
85 kVerifyArrayData = 0x04000,
86 kVerifyBranchTarget = 0x08000,
87 kVerifySwitchTargets = 0x10000,
88 kVerifyVarArg = 0x20000,
89 kVerifyVarArgRange = 0x40000,
90 kVerifyError = 0x80000,
91 };
92
jeffhaobdb76512011-09-07 11:43:16 -070093 /*
94 * Holds the contents of a decoded instruction.
95 */
96 struct DecodedInstruction {
97 uint32_t vA_;
98 uint32_t vB_;
99 uint64_t vB_wide_; /* for kFmt51l */
100 uint32_t vC_;
101 uint32_t arg_[5]; /* vC/D/E/F/G in invoke or filled-new-array */
102 Code opcode_;
103
Elliott Hughesa51a3dd2011-10-17 15:19:26 -0700104 explicit DecodedInstruction(const Instruction* inst) {
jeffhaobdb76512011-09-07 11:43:16 -0700105 inst->Decode(vA_, vB_, vB_wide_, vC_, arg_);
106 opcode_ = inst->Opcode();
107 }
108 };
109
jeffhaoba5ebb92011-08-25 17:24:37 -0700110 // Decodes this instruction, populating its arguments.
111 void Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const;
112
Ian Rogersd81871c2011-10-03 13:57:23 -0700113 // Returns the size in 2 byte code units, for this instruction.
114 size_t SizeInCodeUnits() const;
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700115
116 // Returns a pointer to the next instruction in the stream.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700117 const Instruction* Next() const;
118
119 // Name of the instruction.
120 const char* Name() const {
121 return kInstructionNames[Opcode()];
122 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700123
124 // Returns the opcode field of the instruction.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700125 Code Opcode() const;
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700126
127 // Reads an instruction out of the stream at the specified address.
Ian Rogersd81871c2011-10-03 13:57:23 -0700128 static const Instruction* At(const uint16_t* code) {
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700129 CHECK(code != NULL);
jeffhaoba5ebb92011-08-25 17:24:37 -0700130 return reinterpret_cast<const Instruction*>(code);
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700131 }
132
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700133 // Returns the format of the current instruction.
134 InstructionFormat Format() const {
135 return kInstructionFormats[Opcode()];
136 }
137
jeffhaobdb76512011-09-07 11:43:16 -0700138 // Returns the flags for the current instruction.
139 int Flag() const {
140 return kInstructionFlags[Opcode()];
141 }
142
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700143 // Returns true if this instruction is a branch.
144 bool IsBranch() const {
145 return (kInstructionFlags[Opcode()] & kBranch) != 0;
146 }
147
jeffhaoba5ebb92011-08-25 17:24:37 -0700148 // Returns true if this instruction is a switch.
149 bool IsSwitch() const {
150 return (kInstructionFlags[Opcode()] & kSwitch) != 0;
151 }
152
153 // Returns true if this instruction can throw.
154 bool IsThrow() const {
155 return (kInstructionFlags[Opcode()] & kThrow) != 0;
156 }
157
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700158 // Determine if the instruction is any of 'return' instructions.
159 bool IsReturn() const {
160 return (kInstructionFlags[Opcode()] & kReturn) != 0;
161 }
162
163 // Determine if this instruction ends execution of its basic block.
164 bool IsBasicBlockEnd() const {
165 return IsBranch() || IsReturn() || Opcode() == THROW;
166 }
167
168 // Determine if this instruction is an invoke.
169 bool IsInvoke() const {
170 return (kInstructionFlags[Opcode()] & kInvoke) != 0;
171 }
172
jeffhaoba5ebb92011-08-25 17:24:37 -0700173 int GetVerifyTypeArgumentA() const {
174 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
175 }
176
177 int GetVerifyTypeArgumentB() const {
178 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod |
179 kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide));
180 }
181
182 int GetVerifyTypeArgumentC() const {
183 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
184 kVerifyRegCNewArray | kVerifyRegBType | kVerifyRegBWide));
185 }
186
187 int GetVerifyExtraFlags() const {
188 return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget |
189 kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError));
190 }
191
Ian Rogersd81871c2011-10-03 13:57:23 -0700192 // Dump code_units worth of this instruction, padding to code_units for shorter instructions
193 void DumpHex(std::ostream& os, size_t code_units) const;
194
195 // Dump decoded version of instruction
196 void Dump(std::ostream& os, const DexFile*) const;
197
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700198 private:
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700199 static const char* const kInstructionNames[];
200 static InstructionFormat const kInstructionFormats[];
201 static int const kInstructionFlags[];
jeffhaoba5ebb92011-08-25 17:24:37 -0700202 static int const kInstructionVerifyFlags[];
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700203 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
204};
Ian Rogersd81871c2011-10-03 13:57:23 -0700205std::ostream& operator<<(std::ostream& os, const Instruction& rhs);
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700206
207} // namespace art
208
209#endif // ART_SRC_DEX_INSTRUCTION_H_