blob: 6527f103ebc658f6560fc42a31d3955571c95dbd [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
Sebastien Hertz807a2562013-04-15 09:33:39 +020017#include "dex_instruction-inl.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070018
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070019#include "dex_file-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080020#include "utils.h"
Ian Rogersd81871c2011-10-03 13:57:23 -070021#include <iomanip>
22
Carl Shapiro12eb78e2011-06-24 14:51:06 -070023namespace art {
24
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070025const char* const Instruction::kInstructionNames[] = {
jeffhaoba5ebb92011-08-25 17:24:37 -070026#define INSTRUCTION_NAME(o, c, pname, f, r, i, a, v) pname,
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070027#include "dex_instruction_list.h"
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070028 DEX_INSTRUCTION_LIST(INSTRUCTION_NAME)
29#undef DEX_INSTRUCTION_LIST
30#undef INSTRUCTION_NAME
31};
32
Elliott Hughesadb8c672012-03-06 16:49:32 -080033Instruction::Format const Instruction::kInstructionFormats[] = {
jeffhaoba5ebb92011-08-25 17:24:37 -070034#define INSTRUCTION_FORMAT(o, c, p, format, r, i, a, v) format,
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070035#include "dex_instruction_list.h"
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070036 DEX_INSTRUCTION_LIST(INSTRUCTION_FORMAT)
37#undef DEX_INSTRUCTION_LIST
38#undef INSTRUCTION_FORMAT
39};
40
41int const Instruction::kInstructionFlags[] = {
jeffhaoba5ebb92011-08-25 17:24:37 -070042#define INSTRUCTION_FLAGS(o, c, p, f, r, i, flags, v) flags,
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070043#include "dex_instruction_list.h"
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070044 DEX_INSTRUCTION_LIST(INSTRUCTION_FLAGS)
45#undef DEX_INSTRUCTION_LIST
46#undef INSTRUCTION_FLAGS
47};
48
jeffhaoba5ebb92011-08-25 17:24:37 -070049int const Instruction::kInstructionVerifyFlags[] = {
50#define INSTRUCTION_VERIFY_FLAGS(o, c, p, f, r, i, a, vflags) vflags,
51#include "dex_instruction_list.h"
52 DEX_INSTRUCTION_LIST(INSTRUCTION_VERIFY_FLAGS)
53#undef DEX_INSTRUCTION_LIST
54#undef INSTRUCTION_VERIFY_FLAGS
55};
56
Ian Rogersa75a0132012-09-28 11:41:42 -070057int const Instruction::kInstructionSizeInCodeUnits[] = {
58#define INSTRUCTION_SIZE(opcode, c, p, format, r, i, a, v) \
59 (( opcode == NOP ) ? -1 : \
60 ((format >= k10x) && (format <= k10t)) ? 1 : \
61 ((format >= k20t) && (format <= k22c)) ? 2 : \
62 ((format >= k32x) && (format <= k3rc)) ? 3 : \
63 ( format == k51l ) ? 5 : -1 \
64 ),
65#include "dex_instruction_list.h"
66 DEX_INSTRUCTION_LIST(INSTRUCTION_SIZE)
67#undef DEX_INSTRUCTION_LIST
68#undef INSTRUCTION_SIZE
69};
70
jeffhaoba5ebb92011-08-25 17:24:37 -070071/*
72 * Handy macros for helping decode instructions.
73 */
74#define FETCH(_offset) (insns[(_offset)])
Sebastien Hertz807a2562013-04-15 09:33:39 +020075#define FETCH_uint32(_offset) (fetch_uint32_impl((_offset), insns))
jeffhaoba5ebb92011-08-25 17:24:37 -070076#define INST_A(_insn) (((uint16_t)(_insn) >> 8) & 0x0f)
77#define INST_B(_insn) ((uint16_t)(_insn) >> 12)
78#define INST_AA(_insn) ((_insn) >> 8)
79
Sebastien Hertz807a2562013-04-15 09:33:39 +020080/* Helper for FETCH_uint32, above. */
81static inline uint32_t fetch_uint32_impl(uint32_t offset, const uint16_t* insns) {
jeffhaoba5ebb92011-08-25 17:24:37 -070082 return insns[offset] | ((uint32_t) insns[offset+1] << 16);
83}
84
Dragos Sbirlea39f99272013-06-25 13:17:36 -070085int32_t Instruction::VRegC() const {
86 switch (FormatOf(Opcode())) {
87 case k22b: return VRegC_22b();
88 case k22c: return VRegC_22c();
89 case k22s: return VRegC_22s();
90 case k22t: return VRegC_22t();
91 case k23x: return VRegC_23x();
92 case k35c: return VRegC_35c();
93 case k3rc: return VRegC_3rc();
94 default: LOG(FATAL) << "Tried to access vC of instruction " << Name() <<
95 " which has no C operand.";
96 }
97 return 0;
98}
99
100int32_t Instruction::VRegB() const {
101 switch (FormatOf(Opcode())) {
102 case k11n: return VRegB_11n();
103 case k12x: return VRegB_12x();
104 case k21c: return VRegB_21c();
105 case k21h: return VRegB_21h();
106 case k21t: return VRegB_21t();
107 case k22b: return VRegB_22b();
108 case k22c: return VRegB_22c();
109 case k22s: return VRegB_22s();
110 case k22t: return VRegB_22t();
111 case k22x: return VRegB_22x();
112 case k31c: return VRegB_31c();
113 case k31i: return VRegB_31i();
114 case k31t: return VRegB_31t();
115 case k32x: return VRegB_32x();
116 case k35c: return VRegB_35c();
117 case k3rc: return VRegB_3rc();
118 case k51l: return VRegB_51l();
119 default: LOG(FATAL) << "Tried to access vB of instruction " << Name() <<
120 " which has no B operand.";
121 }
122 return 0;
123}
124
Dragos Sbirlead25de7a2013-06-21 09:20:34 -0700125int32_t Instruction::VRegA() const {
126 switch (FormatOf(Opcode())) {
127 case k10t: return VRegA_10t();
128 case k10x: return VRegA_10x();
129 case k11n: return VRegA_11n();
130 case k11x: return VRegA_11x();
131 case k12x: return VRegA_12x();
132 case k20t: return VRegA_20t();
133 case k21c: return VRegA_21c();
134 case k21h: return VRegA_21h();
135 case k21s: return VRegA_21s();
136 case k21t: return VRegA_21t();
137 case k22b: return VRegA_22b();
138 case k22c: return VRegA_22c();
139 case k22s: return VRegA_22s();
140 case k22t: return VRegA_22t();
141 case k22x: return VRegA_22x();
142 case k23x: return VRegA_23x();
143 case k30t: return VRegA_30t();
144 case k31c: return VRegA_31c();
145 case k31i: return VRegA_31i();
146 case k31t: return VRegA_31t();
147 case k32x: return VRegA_32x();
148 case k35c: return VRegA_35c();
149 case k3rc: return VRegA_3rc();
150 case k51l: return VRegA_51l();
151 default: LOG(FATAL) << "Tried to access vA of instruction "<< Name() <<
152 " which has no A operand.";
153 }
154 return 0;
155}
156
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700157int32_t Instruction::GetTargetOffset() const {
158 switch (FormatOf(Opcode())) {
159 // Cases for conditional branches follow.
160 case k22t: return VRegC_22t();
161 case k21t: return VRegB_21t();
162 // Cases for unconditional branches follow.
163 case k10t: return VRegA_10t();
164 case k20t: return VRegA_20t();
165 case k30t: return VRegA_30t();
166 default: LOG(FATAL) << "Tried to access the branch offset of an instruction " << Name() <<
167 " which does not have a target operand.";
168 }
169 return 0;
170}
171
172bool Instruction::CanFlowThrough() const {
173 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
174 uint16_t insn = *insns;
175 Code opcode = static_cast<Code>(insn & 0xFF);
176 return FlagsOf(opcode) & Instruction::kContinue;
177}
178
jeffhaoba5ebb92011-08-25 17:24:37 -0700179void Instruction::Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const {
180 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
181 uint16_t insn = *insns;
Ian Rogersa75a0132012-09-28 11:41:42 -0700182 Code opcode = static_cast<Code>(insn & 0xFF);
jeffhaoba5ebb92011-08-25 17:24:37 -0700183
Ian Rogersa75a0132012-09-28 11:41:42 -0700184 switch (FormatOf(opcode)) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700185 case k10x: // op
186 /* nothing to do; copy the AA bits out for the verifier */
187 vA = INST_AA(insn);
188 break;
189 case k12x: // op vA, vB
190 vA = INST_A(insn);
191 vB = INST_B(insn);
192 break;
193 case k11n: // op vA, #+B
194 vA = INST_A(insn);
195 vB = (int32_t) (INST_B(insn) << 28) >> 28; // sign extend 4-bit value
196 break;
197 case k11x: // op vAA
198 vA = INST_AA(insn);
199 break;
200 case k10t: // op +AA
201 vA = (int8_t) INST_AA(insn); // sign-extend 8-bit value
202 break;
203 case k20t: // op +AAAA
204 vA = (int16_t) FETCH(1); // sign-extend 16-bit value
205 break;
206 case k21c: // op vAA, thing@BBBB
207 case k22x: // op vAA, vBBBB
208 vA = INST_AA(insn);
209 vB = FETCH(1);
210 break;
211 case k21s: // op vAA, #+BBBB
212 case k21t: // op vAA, +BBBB
213 vA = INST_AA(insn);
214 vB = (int16_t) FETCH(1); // sign-extend 16-bit value
215 break;
216 case k21h: // op vAA, #+BBBB0000[00000000]
217 vA = INST_AA(insn);
218 /*
219 * The value should be treated as right-zero-extended, but we don't
220 * actually do that here. Among other things, we don't know if it's
221 * the top bits of a 32- or 64-bit value.
222 */
223 vB = FETCH(1);
224 break;
225 case k23x: // op vAA, vBB, vCC
226 vA = INST_AA(insn);
227 vB = FETCH(1) & 0xff;
228 vC = FETCH(1) >> 8;
229 break;
230 case k22b: // op vAA, vBB, #+CC
231 vA = INST_AA(insn);
232 vB = FETCH(1) & 0xff;
233 vC = (int8_t) (FETCH(1) >> 8); // sign-extend 8-bit value
234 break;
235 case k22s: // op vA, vB, #+CCCC
236 case k22t: // op vA, vB, +CCCC
237 vA = INST_A(insn);
238 vB = INST_B(insn);
239 vC = (int16_t) FETCH(1); // sign-extend 16-bit value
240 break;
241 case k22c: // op vA, vB, thing@CCCC
242 vA = INST_A(insn);
243 vB = INST_B(insn);
244 vC = FETCH(1);
245 break;
246 case k30t: // op +AAAAAAAA
Sebastien Hertz807a2562013-04-15 09:33:39 +0200247 vA = FETCH_uint32(1); // signed 32-bit value
jeffhaoba5ebb92011-08-25 17:24:37 -0700248 break;
249 case k31t: // op vAA, +BBBBBBBB
250 case k31c: // op vAA, string@BBBBBBBB
251 vA = INST_AA(insn);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200252 vB = FETCH_uint32(1); // 32-bit value
jeffhaoba5ebb92011-08-25 17:24:37 -0700253 break;
254 case k32x: // op vAAAA, vBBBB
255 vA = FETCH(1);
256 vB = FETCH(2);
257 break;
258 case k31i: // op vAA, #+BBBBBBBB
259 vA = INST_AA(insn);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200260 vB = FETCH_uint32(1); // signed 32-bit value
jeffhaoba5ebb92011-08-25 17:24:37 -0700261 break;
262 case k35c: // op {vC, vD, vE, vF, vG}, thing@BBBB
263 {
264 /*
265 * Note that the fields mentioned in the spec don't appear in
266 * their "usual" positions here compared to most formats. This
267 * was done so that the field names for the argument count and
268 * reference index match between this format and the corresponding
269 * range formats (3rc and friends).
270 *
271 * Bottom line: The argument count is always in vA, and the
272 * method constant (or equivalent) is always in vB.
273 */
274 uint16_t regList;
275 int count;
276
277 vA = INST_B(insn); // This is labeled A in the spec.
278 vB = FETCH(1);
279 regList = FETCH(2);
280
281 count = vA;
282
283 /*
284 * Copy the argument registers into the arg[] array, and
285 * also copy the first argument (if any) into vC. (The
286 * DecodedInstruction structure doesn't have separate
287 * fields for {vD, vE, vF, vG}, so there's no need to make
288 * copies of those.) Note that cases 5..2 fall through.
289 */
290 switch (count) {
291 case 5: arg[4] = INST_A(insn);
292 case 4: arg[3] = (regList >> 12) & 0x0f;
293 case 3: arg[2] = (regList >> 8) & 0x0f;
294 case 2: arg[1] = (regList >> 4) & 0x0f;
295 case 1: vC = arg[0] = regList & 0x0f; break;
296 case 0: break; // Valid, but no need to do anything.
297 default:
298 LOG(ERROR) << "Invalid arg count in 35c (" << count << ")";
299 return;
300 }
301 }
302 break;
303 case k3rc: // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
304 vA = INST_AA(insn);
305 vB = FETCH(1);
306 vC = FETCH(2);
307 break;
308 case k51l: // op vAA, #+BBBBBBBBBBBBBBBB
309 vA = INST_AA(insn);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200310 vB_wide = FETCH_uint32(1) | ((uint64_t) FETCH_uint32(3) << 32);
jeffhaoba5ebb92011-08-25 17:24:37 -0700311 break;
312 default:
Ian Rogersa75a0132012-09-28 11:41:42 -0700313 LOG(ERROR) << "Can't decode unexpected format " << FormatOf(opcode) << " (op=" << opcode << ")";
jeffhaoba5ebb92011-08-25 17:24:37 -0700314 return;
315 }
316}
317
Ian Rogersa75a0132012-09-28 11:41:42 -0700318size_t Instruction::SizeInCodeUnitsComplexOpcode() const {
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700319 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
Ian Rogersa75a0132012-09-28 11:41:42 -0700320 // Handle special NOP encoded variable length sequences.
321 switch (*insns) {
322 case kPackedSwitchSignature:
323 return (4 + insns[1] * 2);
324 case kSparseSwitchSignature:
325 return (2 + insns[1] * 4);
326 case kArrayDataSignature: {
327 uint16_t element_size = insns[1];
328 uint32_t length = insns[2] | (((uint32_t)insns[3]) << 16);
329 // The plus 1 is to round up for odd size and width.
330 return (4 + (element_size * length + 1) / 2);
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700331 }
Ian Rogersa75a0132012-09-28 11:41:42 -0700332 default:
333 if ((*insns & 0xFF) == 0) {
334 return 1; // NOP.
335 } else {
336 LOG(FATAL) << "Unreachable: " << DumpString(NULL);
337 return 0;
338 }
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700339 }
Ian Rogersd81871c2011-10-03 13:57:23 -0700340}
341
Ian Rogers2c8a8572011-10-24 17:11:36 -0700342std::string Instruction::DumpHex(size_t code_units) const {
Ian Rogersd81871c2011-10-03 13:57:23 -0700343 size_t inst_length = SizeInCodeUnits();
344 if (inst_length > code_units) {
345 inst_length = code_units;
346 }
Ian Rogers2c8a8572011-10-24 17:11:36 -0700347 std::ostringstream os;
Ian Rogersd81871c2011-10-03 13:57:23 -0700348 const uint16_t* insn = reinterpret_cast<const uint16_t*>(this);
349 for (size_t i = 0; i < inst_length; i++) {
Ian Rogers2c8a8572011-10-24 17:11:36 -0700350 os << StringPrintf("0x%04x", insn[i]) << " ";
Ian Rogersd81871c2011-10-03 13:57:23 -0700351 }
352 for (size_t i = inst_length; i < code_units; i++) {
353 os << " ";
354 }
Ian Rogers2c8a8572011-10-24 17:11:36 -0700355 return os.str();
Ian Rogersd81871c2011-10-03 13:57:23 -0700356}
357
Ian Rogers2c8a8572011-10-24 17:11:36 -0700358std::string Instruction::DumpString(const DexFile* file) const {
Ian Rogers2c8a8572011-10-24 17:11:36 -0700359 std::ostringstream os;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200360 const char* opcode = kInstructionNames[Opcode()];
Elliott Hughesadb8c672012-03-06 16:49:32 -0800361 switch (FormatOf(Opcode())) {
Elliott Hughese3c845c2012-02-28 17:23:01 -0800362 case k10x: os << opcode; break;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200363 case k12x: os << StringPrintf("%s v%d, v%d", opcode, VRegA_12x(), VRegB_12x()); break;
364 case k11n: os << StringPrintf("%s v%d, #%+d", opcode, VRegA_11n(), VRegB_11n()); break;
365 case k11x: os << StringPrintf("%s v%d", opcode, VRegA_11x()); break;
366 case k10t: os << StringPrintf("%s %+d", opcode, VRegA_10t()); break;
367 case k20t: os << StringPrintf("%s %+d", opcode, VRegA_20t()); break;
368 case k22x: os << StringPrintf("%s v%d, v%d", opcode, VRegA_22x(), VRegB_22x()); break;
369 case k21t: os << StringPrintf("%s v%d, %+d", opcode, VRegA_21t(), VRegB_21t()); break;
370 case k21s: os << StringPrintf("%s v%d, #%+d", opcode, VRegA_21s(), VRegB_21s()); break;
Elliott Hughes1b3d6ca2012-04-25 13:00:14 -0700371 case k21h: {
372 // op vAA, #+BBBB0000[00000000]
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200373 if (Opcode() == CONST_HIGH16) {
374 uint32_t value = VRegB_21h() << 16;
375 os << StringPrintf("%s v%d, #int %+d // 0x%x", opcode, VRegA_21h(), value, value);
Elliott Hughes1b3d6ca2012-04-25 13:00:14 -0700376 } else {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200377 uint64_t value = static_cast<uint64_t>(VRegB_21h()) << 48;
378 os << StringPrintf("%s v%d, #long %+lld // 0x%llx", opcode, VRegA_21h(), value, value);
Elliott Hughes1b3d6ca2012-04-25 13:00:14 -0700379 }
380 }
381 break;
Ian Rogers90334e52012-06-06 20:22:20 -0700382 case k21c: {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200383 switch (Opcode()) {
Ian Rogers90334e52012-06-06 20:22:20 -0700384 case CONST_STRING:
385 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200386 uint32_t string_idx = VRegB_21c();
387 os << StringPrintf("const-string v%d, %s // string@%d", VRegA_21c(),
388 PrintableString(file->StringDataByIdx(string_idx)).c_str(), string_idx);
Ian Rogers90334e52012-06-06 20:22:20 -0700389 break;
390 } // else fall-through
Mathieu Chartier18c24b62012-09-10 08:54:25 -0700391 case CHECK_CAST:
392 case CONST_CLASS:
Ian Rogers90334e52012-06-06 20:22:20 -0700393 case NEW_INSTANCE:
394 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200395 uint32_t type_idx = VRegB_21c();
Dragos Sbirleab43cef32013-05-23 11:59:20 -0700396 os << opcode << " v" << static_cast<int>(VRegA_21c()) << ", " << PrettyType(type_idx, *file)
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200397 << " // type@" << type_idx;
Ian Rogers90334e52012-06-06 20:22:20 -0700398 break;
399 } // else fall-through
400 case SGET:
401 case SGET_WIDE:
402 case SGET_OBJECT:
403 case SGET_BOOLEAN:
404 case SGET_BYTE:
405 case SGET_CHAR:
406 case SGET_SHORT:
407 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200408 uint32_t field_idx = VRegB_21c();
Dragos Sbirleab43cef32013-05-23 11:59:20 -0700409 os << opcode << " v" << static_cast<int>(VRegA_21c()) << ", " << PrettyField(field_idx, *file, true)
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200410 << " // field@" << field_idx;
Ian Rogers90334e52012-06-06 20:22:20 -0700411 break;
412 } // else fall-through
413 case SPUT:
414 case SPUT_WIDE:
415 case SPUT_OBJECT:
416 case SPUT_BOOLEAN:
417 case SPUT_BYTE:
418 case SPUT_CHAR:
419 case SPUT_SHORT:
420 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200421 uint32_t field_idx = VRegB_21c();
Dragos Sbirleab43cef32013-05-23 11:59:20 -0700422 os << opcode << " v" << static_cast<int>(VRegA_21c()) << ", " << PrettyField(field_idx, *file, true)
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200423 << " // field@" << field_idx;
Ian Rogers90334e52012-06-06 20:22:20 -0700424 break;
425 } // else fall-through
426 default:
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200427 os << StringPrintf("%s v%d, thing@%d", opcode, VRegA_21c(), VRegB_21c());
Ian Rogers90334e52012-06-06 20:22:20 -0700428 break;
429 }
430 break;
431 }
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200432 case k23x: os << StringPrintf("%s v%d, v%d, v%d", opcode, VRegA_23x(), VRegB_23x(), VRegC_23x()); break;
433 case k22b: os << StringPrintf("%s v%d, v%d, #%+d", opcode, VRegA_22b(), VRegB_22b(), VRegC_22b()); break;
434 case k22t: os << StringPrintf("%s v%d, v%d, %+d", opcode, VRegA_22t(), VRegB_22t(), VRegC_22t()); break;
435 case k22s: os << StringPrintf("%s v%d, v%d, #%+d", opcode, VRegA_22s(), VRegB_22s(), VRegC_22s()); break;
Ian Rogers90334e52012-06-06 20:22:20 -0700436 case k22c: {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200437 switch (Opcode()) {
Ian Rogers90334e52012-06-06 20:22:20 -0700438 case IGET:
439 case IGET_WIDE:
440 case IGET_OBJECT:
441 case IGET_BOOLEAN:
442 case IGET_BYTE:
443 case IGET_CHAR:
444 case IGET_SHORT:
445 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200446 uint32_t field_idx = VRegC_22c();
Dragos Sbirleab43cef32013-05-23 11:59:20 -0700447 os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200448 << PrettyField(field_idx, *file, true) << " // field@" << field_idx;
Ian Rogers90334e52012-06-06 20:22:20 -0700449 break;
450 } // else fall-through
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200451 case IGET_QUICK:
452 case IGET_OBJECT_QUICK:
453 if (file != NULL) {
454 uint32_t field_idx = VRegC_22c();
455 os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
456 << "// offset@" << field_idx;
457 break;
458 } // else fall-through
Ian Rogers90334e52012-06-06 20:22:20 -0700459 case IPUT:
460 case IPUT_WIDE:
461 case IPUT_OBJECT:
462 case IPUT_BOOLEAN:
463 case IPUT_BYTE:
464 case IPUT_CHAR:
465 case IPUT_SHORT:
466 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200467 uint32_t field_idx = VRegC_22c();
Dragos Sbirleab43cef32013-05-23 11:59:20 -0700468 os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200469 << PrettyField(field_idx, *file, true) << " // field@" << field_idx;
Ian Rogers90334e52012-06-06 20:22:20 -0700470 break;
471 } // else fall-through
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200472 case IPUT_QUICK:
473 case IPUT_OBJECT_QUICK:
474 if (file != NULL) {
475 uint32_t field_idx = VRegC_22c();
476 os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
477 << "// offset@" << field_idx;
478 break;
479 } // else fall-through
Ian Rogers90334e52012-06-06 20:22:20 -0700480 case INSTANCE_OF:
481 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200482 uint32_t type_idx = VRegC_22c();
Dragos Sbirlead4e868a2013-05-23 09:44:17 -0700483 os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200484 << PrettyType(type_idx, *file) << " // type@" << type_idx;
Mathieu Chartier18c24b62012-09-10 08:54:25 -0700485 break;
486 }
487 case NEW_ARRAY:
488 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200489 uint32_t type_idx = VRegC_22c();
Dragos Sbirleab43cef32013-05-23 11:59:20 -0700490 os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200491 << PrettyType(type_idx, *file) << " // type@" << type_idx;
Ian Rogers90334e52012-06-06 20:22:20 -0700492 break;
493 } // else fall-through
494 default:
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200495 os << StringPrintf("%s v%d, v%d, thing@%d", opcode, VRegA_22c(), VRegB_22c(), VRegC_22c());
Ian Rogers90334e52012-06-06 20:22:20 -0700496 break;
497 }
498 break;
499 }
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200500 case k32x: os << StringPrintf("%s v%d, v%d", opcode, VRegA_32x(), VRegB_32x()); break;
501 case k30t: os << StringPrintf("%s %+d", opcode, VRegA_30t()); break;
502 case k31t: os << StringPrintf("%s v%d, %+d", opcode, VRegA_31t(), VRegB_31t()); break;
503 case k31i: os << StringPrintf("%s v%d, #%+d", opcode, VRegA_31i(), VRegB_31i()); break;
504 case k31c: os << StringPrintf("%s v%d, thing@%d", opcode, VRegA_31c(), VRegB_31c()); break;
Ian Rogersd81871c2011-10-03 13:57:23 -0700505 case k35c: {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200506 uint32_t arg[5];
507 GetArgs(arg);
508 switch (Opcode()) {
Ian Rogersd81871c2011-10-03 13:57:23 -0700509 case INVOKE_VIRTUAL:
510 case INVOKE_SUPER:
511 case INVOKE_DIRECT:
512 case INVOKE_STATIC:
513 case INVOKE_INTERFACE:
514 if (file != NULL) {
Elliott Hughese3c845c2012-02-28 17:23:01 -0800515 os << opcode << " {";
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200516 uint32_t method_idx = VRegB_35c();
517 for (size_t i = 0; i < VRegA_35c(); ++i) {
Elliott Hughese3c845c2012-02-28 17:23:01 -0800518 if (i != 0) {
519 os << ", ";
520 }
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200521 os << "v" << arg[i];
Elliott Hughese3c845c2012-02-28 17:23:01 -0800522 }
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200523 os << "}, " << PrettyMethod(method_idx, *file) << " // method@" << method_idx;
Ian Rogersd81871c2011-10-03 13:57:23 -0700524 break;
525 } // else fall-through
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200526 case INVOKE_VIRTUAL_QUICK:
527 if (file != NULL) {
528 os << opcode << " {";
529 uint32_t method_idx = VRegB_35c();
530 for (size_t i = 0; i < VRegA_35c(); ++i) {
531 if (i != 0) {
532 os << ", ";
533 }
534 os << "v" << arg[i];
535 }
536 os << "}, // vtable@" << method_idx;
537 break;
538 } // else fall-through
Ian Rogersd81871c2011-10-03 13:57:23 -0700539 default:
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200540 os << opcode << " {v" << arg[0] << ", v" << arg[1] << ", v" << arg[2]
541 << ", v" << arg[3] << ", v" << arg[4] << "}, thing@" << VRegB_35c();
Ian Rogersd81871c2011-10-03 13:57:23 -0700542 break;
543 }
544 break;
545 }
Ian Rogers4c5dd5a2012-09-07 11:27:28 -0700546 case k3rc: {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200547 switch (Opcode()) {
Ian Rogers4c5dd5a2012-09-07 11:27:28 -0700548 case INVOKE_VIRTUAL_RANGE:
549 case INVOKE_SUPER_RANGE:
550 case INVOKE_DIRECT_RANGE:
551 case INVOKE_STATIC_RANGE:
552 case INVOKE_INTERFACE_RANGE:
553 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200554 uint32_t method_idx = VRegB_3rc();
555 os << StringPrintf("%s, {v%d .. v%d}, ", opcode, VRegC_3rc(), (VRegC_3rc() + VRegA_3rc() - 1))
556 << PrettyMethod(method_idx, *file) << " // method@" << method_idx;
Ian Rogers4c5dd5a2012-09-07 11:27:28 -0700557 break;
558 } // else fall-through
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200559 case INVOKE_VIRTUAL_RANGE_QUICK:
560 if (file != NULL) {
561 uint32_t method_idx = VRegB_3rc();
562 os << StringPrintf("%s, {v%d .. v%d}, ", opcode, VRegC_3rc(), (VRegC_3rc() + VRegA_3rc() - 1))
563 << "// vtable@" << method_idx;
564 break;
565 } // else fall-through
Ian Rogers4c5dd5a2012-09-07 11:27:28 -0700566 default:
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200567 os << StringPrintf("%s, {v%d .. v%d}, thing@%d", opcode, VRegC_3rc(),
568 (VRegC_3rc() + VRegA_3rc() - 1), VRegB_3rc());
Ian Rogers4c5dd5a2012-09-07 11:27:28 -0700569 break;
570 }
571 break;
572 }
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200573 case k51l: os << StringPrintf("%s v%d, #%+lld", opcode, VRegA_51l(), VRegB_51l()); break;
Ian Rogers2c8a8572011-10-24 17:11:36 -0700574 default: os << " unknown format (" << DumpHex(5) << ")"; break;
Ian Rogersd81871c2011-10-03 13:57:23 -0700575 }
Ian Rogers2c8a8572011-10-24 17:11:36 -0700576 return os.str();
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700577}
578
Ian Rogersa75a0132012-09-28 11:41:42 -0700579std::ostream& operator<<(std::ostream& os, const Instruction::Code& code) {
580 return os << Instruction::Name(code);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800581}
582
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700583} // namespace art