blob: 3934d7d5ac58e3c3a61654887a25d80616a433dc [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
35 k20t, // op +AAAA
36 k22x, // op vAA, vBBBB
37 k21t, // op vAA, +BBBB
38 k21s, // op vAA, #+BBBB
39 k21h, // op vAA, #+BBBB00000[00000000]
40 k21c, // op vAA, thing@BBBB
41 k23x, // op vAA, vBB, vCC
42 k22b, // op vAA, vBB, #+CC
43 k22t, // op vA, vB, +CCCC
44 k22s, // op vA, vB, #+CCCC
45 k22c, // op vA, vB, thing@CCCC
46 k32x, // op vAAAA, vBBBB
47 k30t, // op +AAAAAAAA
48 k31t, // op vAA, +BBBBBBBB
49 k31i, // op vAA, #+BBBBBBBB
50 k31c, // op vAA, thing@BBBBBBBB
51 k35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
52 k3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
53 k51l, // op vAA, #+BBBBBBBBBBBBBBBB
54 };
55
56 enum Flags {
57 kBranch = 0x01, // conditional or unconditional branch
58 kContinue = 0x02, // flow can continue to next statement
59 kSwitch = 0x04, // switch statement
60 kThrow = 0x08, // could cause an exception to be thrown
61 kReturn = 0x10, // returns, no additional statements
62 kInvoke = 0x20, // a flavor of invoke
63 // TODO: kUnconditional
64 };
65
jeffhaoba5ebb92011-08-25 17:24:37 -070066 enum VerifyFlag {
67 kVerifyNone = 0x00000,
68 kVerifyRegA = 0x00001,
69 kVerifyRegAWide = 0x00002,
70 kVerifyRegB = 0x00004,
71 kVerifyRegBField = 0x00008,
72 kVerifyRegBMethod = 0x00010,
73 kVerifyRegBNewInstance = 0x00020,
74 kVerifyRegBString = 0x00040,
75 kVerifyRegBType = 0x00080,
76 kVerifyRegBWide = 0x00100,
77 kVerifyRegC = 0x00200,
78 kVerifyRegCField = 0x00400,
79 kVerifyRegCNewArray = 0x00800,
80 kVerifyRegCType = 0x01000,
81 kVerifyRegCWide = 0x02000,
82 kVerifyArrayData = 0x04000,
83 kVerifyBranchTarget = 0x08000,
84 kVerifySwitchTargets = 0x10000,
85 kVerifyVarArg = 0x20000,
86 kVerifyVarArgRange = 0x40000,
87 kVerifyError = 0x80000,
88 };
89
jeffhaobdb76512011-09-07 11:43:16 -070090 /*
91 * Holds the contents of a decoded instruction.
92 */
93 struct DecodedInstruction {
94 uint32_t vA_;
95 uint32_t vB_;
96 uint64_t vB_wide_; /* for kFmt51l */
97 uint32_t vC_;
98 uint32_t arg_[5]; /* vC/D/E/F/G in invoke or filled-new-array */
99 Code opcode_;
100
101 DecodedInstruction(const Instruction* inst) {
102 inst->Decode(vA_, vB_, vB_wide_, vC_, arg_);
103 opcode_ = inst->Opcode();
104 }
105 };
106
jeffhaoba5ebb92011-08-25 17:24:37 -0700107 // Decodes this instruction, populating its arguments.
108 void Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const;
109
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700110 // Returns the size in bytes of this instruction.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700111 size_t Size() const;
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700112
113 // Returns a pointer to the next instruction in the stream.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700114 const Instruction* Next() const;
115
116 // Name of the instruction.
117 const char* Name() const {
118 return kInstructionNames[Opcode()];
119 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700120
121 // Returns the opcode field of the instruction.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700122 Code Opcode() const;
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700123
124 // Reads an instruction out of the stream at the specified address.
jeffhaoba5ebb92011-08-25 17:24:37 -0700125 static const Instruction* At(const byte* code) {
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700126 CHECK(code != NULL);
jeffhaoba5ebb92011-08-25 17:24:37 -0700127 return reinterpret_cast<const Instruction*>(code);
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700128 }
129
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700130 // Returns the format of the current instruction.
131 InstructionFormat Format() const {
132 return kInstructionFormats[Opcode()];
133 }
134
jeffhaobdb76512011-09-07 11:43:16 -0700135 // Returns the flags for the current instruction.
136 int Flag() const {
137 return kInstructionFlags[Opcode()];
138 }
139
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700140 // Returns true if this instruction is a branch.
141 bool IsBranch() const {
142 return (kInstructionFlags[Opcode()] & kBranch) != 0;
143 }
144
jeffhaoba5ebb92011-08-25 17:24:37 -0700145 // Returns true if this instruction is a switch.
146 bool IsSwitch() const {
147 return (kInstructionFlags[Opcode()] & kSwitch) != 0;
148 }
149
150 // Returns true if this instruction can throw.
151 bool IsThrow() const {
152 return (kInstructionFlags[Opcode()] & kThrow) != 0;
153 }
154
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700155 // Determine if the instruction is any of 'return' instructions.
156 bool IsReturn() const {
157 return (kInstructionFlags[Opcode()] & kReturn) != 0;
158 }
159
160 // Determine if this instruction ends execution of its basic block.
161 bool IsBasicBlockEnd() const {
162 return IsBranch() || IsReturn() || Opcode() == THROW;
163 }
164
165 // Determine if this instruction is an invoke.
166 bool IsInvoke() const {
167 return (kInstructionFlags[Opcode()] & kInvoke) != 0;
168 }
169
jeffhaoba5ebb92011-08-25 17:24:37 -0700170 int GetVerifyTypeArgumentA() const {
171 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
172 }
173
174 int GetVerifyTypeArgumentB() const {
175 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod |
176 kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide));
177 }
178
179 int GetVerifyTypeArgumentC() const {
180 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
181 kVerifyRegCNewArray | kVerifyRegBType | kVerifyRegBWide));
182 }
183
184 int GetVerifyExtraFlags() const {
185 return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget |
186 kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError));
187 }
188
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700189 private:
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700190 static const char* const kInstructionNames[];
191 static InstructionFormat const kInstructionFormats[];
192 static int const kInstructionFlags[];
jeffhaoba5ebb92011-08-25 17:24:37 -0700193 static int const kInstructionVerifyFlags[];
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700194 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
195};
196
197} // namespace art
198
199#endif // ART_SRC_DEX_INSTRUCTION_H_