blob: 2c1a3974f2bed909762d40b26bde61e33ed6efb5 [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
Carl Shapiro12eb78e2011-06-24 14:51:06 -070012class Instruction {
13 public:
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070014 // NOP-encoded switch-statement signatures.
15 enum {
16 kPackedSwitchSignature = 0x0100,
17 kSparseSwitchSignature = 0x0200,
18 kArrayDataSignature = 0x0300
19 };
20
Carl Shapiro12eb78e2011-06-24 14:51:06 -070021 enum Code {
jeffhaoba5ebb92011-08-25 17:24:37 -070022#define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a, v) cname = opcode,
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070023#include "dex_instruction_list.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070024 DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
Carl Shapirod84f49c2011-06-29 00:27:46 -070025#undef DEX_INSTRUCTION_LIST
Carl Shapiro12eb78e2011-06-24 14:51:06 -070026#undef INSTRUCTION_ENUM
Carl Shapirod84f49c2011-06-29 00:27:46 -070027 };
Carl Shapiro12eb78e2011-06-24 14:51:06 -070028
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070029 enum InstructionFormat {
30 k10x, // op
31 k12x, // op vA, vB
32 k11n, // op vA, #+B
33 k11x, // op vAA
34 k10t, // op +AA
jeffhaob4df5142011-09-19 20:25:32 -070035 k20bc, // op AA, kind@BBBB
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070036 k20t, // op +AAAA
37 k22x, // op vAA, vBBBB
38 k21t, // op vAA, +BBBB
39 k21s, // op vAA, #+BBBB
40 k21h, // op vAA, #+BBBB00000[00000000]
41 k21c, // op vAA, thing@BBBB
42 k23x, // op vAA, vBB, vCC
43 k22b, // op vAA, vBB, #+CC
44 k22t, // op vA, vB, +CCCC
45 k22s, // op vA, vB, #+CCCC
46 k22c, // op vA, vB, thing@CCCC
47 k32x, // op vAAAA, vBBBB
48 k30t, // op +AAAAAAAA
49 k31t, // op vAA, +BBBBBBBB
50 k31i, // op vAA, #+BBBBBBBB
51 k31c, // op vAA, thing@BBBBBBBB
52 k35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
53 k3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
54 k51l, // op vAA, #+BBBBBBBBBBBBBBBB
55 };
56
57 enum Flags {
58 kBranch = 0x01, // conditional or unconditional branch
59 kContinue = 0x02, // flow can continue to next statement
60 kSwitch = 0x04, // switch statement
61 kThrow = 0x08, // could cause an exception to be thrown
62 kReturn = 0x10, // returns, no additional statements
63 kInvoke = 0x20, // a flavor of invoke
64 // TODO: kUnconditional
65 };
66
jeffhaoba5ebb92011-08-25 17:24:37 -070067 enum VerifyFlag {
68 kVerifyNone = 0x00000,
69 kVerifyRegA = 0x00001,
70 kVerifyRegAWide = 0x00002,
71 kVerifyRegB = 0x00004,
72 kVerifyRegBField = 0x00008,
73 kVerifyRegBMethod = 0x00010,
74 kVerifyRegBNewInstance = 0x00020,
75 kVerifyRegBString = 0x00040,
76 kVerifyRegBType = 0x00080,
77 kVerifyRegBWide = 0x00100,
78 kVerifyRegC = 0x00200,
79 kVerifyRegCField = 0x00400,
80 kVerifyRegCNewArray = 0x00800,
81 kVerifyRegCType = 0x01000,
82 kVerifyRegCWide = 0x02000,
83 kVerifyArrayData = 0x04000,
84 kVerifyBranchTarget = 0x08000,
85 kVerifySwitchTargets = 0x10000,
86 kVerifyVarArg = 0x20000,
87 kVerifyVarArgRange = 0x40000,
88 kVerifyError = 0x80000,
89 };
90
jeffhaobdb76512011-09-07 11:43:16 -070091 /*
92 * Holds the contents of a decoded instruction.
93 */
94 struct DecodedInstruction {
95 uint32_t vA_;
96 uint32_t vB_;
97 uint64_t vB_wide_; /* for kFmt51l */
98 uint32_t vC_;
99 uint32_t arg_[5]; /* vC/D/E/F/G in invoke or filled-new-array */
100 Code opcode_;
101
Elliott Hughesa51a3dd2011-10-17 15:19:26 -0700102 explicit DecodedInstruction(const Instruction* inst) {
jeffhaobdb76512011-09-07 11:43:16 -0700103 inst->Decode(vA_, vB_, vB_wide_, vC_, arg_);
104 opcode_ = inst->Opcode();
105 }
106 };
107
jeffhaoba5ebb92011-08-25 17:24:37 -0700108 // Decodes this instruction, populating its arguments.
109 void Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const;
110
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700111 // Returns the size in bytes of this instruction.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700112 size_t Size() const;
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700113
114 // Returns a pointer to the next instruction in the stream.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700115 const Instruction* Next() const;
116
117 // Name of the instruction.
118 const char* Name() const {
119 return kInstructionNames[Opcode()];
120 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700121
122 // Returns the opcode field of the instruction.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700123 Code Opcode() const;
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700124
125 // Reads an instruction out of the stream at the specified address.
jeffhaoba5ebb92011-08-25 17:24:37 -0700126 static const Instruction* At(const byte* code) {
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700127 CHECK(code != NULL);
jeffhaoba5ebb92011-08-25 17:24:37 -0700128 return reinterpret_cast<const Instruction*>(code);
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700129 }
130
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700131 // Returns the format of the current instruction.
132 InstructionFormat Format() const {
133 return kInstructionFormats[Opcode()];
134 }
135
jeffhaobdb76512011-09-07 11:43:16 -0700136 // Returns the flags for the current instruction.
137 int Flag() const {
138 return kInstructionFlags[Opcode()];
139 }
140
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700141 // Returns true if this instruction is a branch.
142 bool IsBranch() const {
143 return (kInstructionFlags[Opcode()] & kBranch) != 0;
144 }
145
jeffhaoba5ebb92011-08-25 17:24:37 -0700146 // Returns true if this instruction is a switch.
147 bool IsSwitch() const {
148 return (kInstructionFlags[Opcode()] & kSwitch) != 0;
149 }
150
151 // Returns true if this instruction can throw.
152 bool IsThrow() const {
153 return (kInstructionFlags[Opcode()] & kThrow) != 0;
154 }
155
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700156 // Determine if the instruction is any of 'return' instructions.
157 bool IsReturn() const {
158 return (kInstructionFlags[Opcode()] & kReturn) != 0;
159 }
160
161 // Determine if this instruction ends execution of its basic block.
162 bool IsBasicBlockEnd() const {
163 return IsBranch() || IsReturn() || Opcode() == THROW;
164 }
165
166 // Determine if this instruction is an invoke.
167 bool IsInvoke() const {
168 return (kInstructionFlags[Opcode()] & kInvoke) != 0;
169 }
170
jeffhaoba5ebb92011-08-25 17:24:37 -0700171 int GetVerifyTypeArgumentA() const {
172 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
173 }
174
175 int GetVerifyTypeArgumentB() const {
176 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod |
177 kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide));
178 }
179
180 int GetVerifyTypeArgumentC() const {
181 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
182 kVerifyRegCNewArray | kVerifyRegBType | kVerifyRegBWide));
183 }
184
185 int GetVerifyExtraFlags() const {
186 return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget |
187 kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError));
188 }
189
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700190 private:
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700191 static const char* const kInstructionNames[];
192 static InstructionFormat const kInstructionFormats[];
193 static int const kInstructionFlags[];
jeffhaoba5ebb92011-08-25 17:24:37 -0700194 static int const kInstructionVerifyFlags[];
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700195 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
196};
197
198} // namespace art
199
200#endif // ART_SRC_DEX_INSTRUCTION_H_