blob: a36d7c51666e128252a26117f3a5785ced101911 [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) \
Brian Carlstromdf629502013-07-17 22:39:56 -070059 ((opcode == NOP) ? -1 : \
Ian Rogersa75a0132012-09-28 11:41:42 -070060 ((format >= k10x) && (format <= k10t)) ? 1 : \
61 ((format >= k20t) && (format <= k22c)) ? 2 : \
62 ((format >= k32x) && (format <= k3rc)) ? 3 : \
Brian Carlstromdf629502013-07-17 22:39:56 -070063 (format == k51l) ? 5 : -1),
Ian Rogersa75a0132012-09-28 11:41:42 -070064#include "dex_instruction_list.h"
65 DEX_INSTRUCTION_LIST(INSTRUCTION_SIZE)
66#undef DEX_INSTRUCTION_LIST
67#undef INSTRUCTION_SIZE
68};
69
jeffhaoba5ebb92011-08-25 17:24:37 -070070/*
71 * Handy macros for helping decode instructions.
72 */
73#define FETCH(_offset) (insns[(_offset)])
Sebastien Hertz807a2562013-04-15 09:33:39 +020074#define FETCH_uint32(_offset) (fetch_uint32_impl((_offset), insns))
jeffhaoba5ebb92011-08-25 17:24:37 -070075#define INST_A(_insn) (((uint16_t)(_insn) >> 8) & 0x0f)
76#define INST_B(_insn) ((uint16_t)(_insn) >> 12)
77#define INST_AA(_insn) ((_insn) >> 8)
78
Sebastien Hertz807a2562013-04-15 09:33:39 +020079/* Helper for FETCH_uint32, above. */
80static inline uint32_t fetch_uint32_impl(uint32_t offset, const uint16_t* insns) {
jeffhaoba5ebb92011-08-25 17:24:37 -070081 return insns[offset] | ((uint32_t) insns[offset+1] << 16);
82}
83
Dragos Sbirlea39f99272013-06-25 13:17:36 -070084int32_t Instruction::VRegC() const {
85 switch (FormatOf(Opcode())) {
86 case k22b: return VRegC_22b();
87 case k22c: return VRegC_22c();
88 case k22s: return VRegC_22s();
89 case k22t: return VRegC_22t();
90 case k23x: return VRegC_23x();
91 case k35c: return VRegC_35c();
92 case k3rc: return VRegC_3rc();
93 default: LOG(FATAL) << "Tried to access vC of instruction " << Name() <<
94 " which has no C operand.";
95 }
96 return 0;
97}
98
99int32_t Instruction::VRegB() const {
100 switch (FormatOf(Opcode())) {
101 case k11n: return VRegB_11n();
102 case k12x: return VRegB_12x();
103 case k21c: return VRegB_21c();
104 case k21h: return VRegB_21h();
105 case k21t: return VRegB_21t();
106 case k22b: return VRegB_22b();
107 case k22c: return VRegB_22c();
108 case k22s: return VRegB_22s();
109 case k22t: return VRegB_22t();
110 case k22x: return VRegB_22x();
111 case k31c: return VRegB_31c();
112 case k31i: return VRegB_31i();
113 case k31t: return VRegB_31t();
114 case k32x: return VRegB_32x();
115 case k35c: return VRegB_35c();
116 case k3rc: return VRegB_3rc();
117 case k51l: return VRegB_51l();
118 default: LOG(FATAL) << "Tried to access vB of instruction " << Name() <<
119 " which has no B operand.";
120 }
121 return 0;
122}
123
Dragos Sbirlead25de7a2013-06-21 09:20:34 -0700124int32_t Instruction::VRegA() const {
125 switch (FormatOf(Opcode())) {
126 case k10t: return VRegA_10t();
127 case k10x: return VRegA_10x();
128 case k11n: return VRegA_11n();
129 case k11x: return VRegA_11x();
130 case k12x: return VRegA_12x();
131 case k20t: return VRegA_20t();
132 case k21c: return VRegA_21c();
133 case k21h: return VRegA_21h();
134 case k21s: return VRegA_21s();
135 case k21t: return VRegA_21t();
136 case k22b: return VRegA_22b();
137 case k22c: return VRegA_22c();
138 case k22s: return VRegA_22s();
139 case k22t: return VRegA_22t();
140 case k22x: return VRegA_22x();
141 case k23x: return VRegA_23x();
142 case k30t: return VRegA_30t();
143 case k31c: return VRegA_31c();
144 case k31i: return VRegA_31i();
145 case k31t: return VRegA_31t();
146 case k32x: return VRegA_32x();
147 case k35c: return VRegA_35c();
148 case k3rc: return VRegA_3rc();
149 case k51l: return VRegA_51l();
150 default: LOG(FATAL) << "Tried to access vA of instruction "<< Name() <<
151 " which has no A operand.";
152 }
153 return 0;
154}
155
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700156int32_t Instruction::GetTargetOffset() const {
157 switch (FormatOf(Opcode())) {
158 // Cases for conditional branches follow.
159 case k22t: return VRegC_22t();
160 case k21t: return VRegB_21t();
161 // Cases for unconditional branches follow.
162 case k10t: return VRegA_10t();
163 case k20t: return VRegA_20t();
164 case k30t: return VRegA_30t();
165 default: LOG(FATAL) << "Tried to access the branch offset of an instruction " << Name() <<
166 " which does not have a target operand.";
167 }
168 return 0;
169}
170
171bool Instruction::CanFlowThrough() const {
172 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
173 uint16_t insn = *insns;
174 Code opcode = static_cast<Code>(insn & 0xFF);
175 return FlagsOf(opcode) & Instruction::kContinue;
176}
177
jeffhaoba5ebb92011-08-25 17:24:37 -0700178void Instruction::Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const {
179 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
180 uint16_t insn = *insns;
Ian Rogersa75a0132012-09-28 11:41:42 -0700181 Code opcode = static_cast<Code>(insn & 0xFF);
jeffhaoba5ebb92011-08-25 17:24:37 -0700182
Ian Rogersa75a0132012-09-28 11:41:42 -0700183 switch (FormatOf(opcode)) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700184 case k10x: // op
185 /* nothing to do; copy the AA bits out for the verifier */
186 vA = INST_AA(insn);
187 break;
188 case k12x: // op vA, vB
189 vA = INST_A(insn);
190 vB = INST_B(insn);
191 break;
192 case k11n: // op vA, #+B
193 vA = INST_A(insn);
194 vB = (int32_t) (INST_B(insn) << 28) >> 28; // sign extend 4-bit value
195 break;
196 case k11x: // op vAA
197 vA = INST_AA(insn);
198 break;
199 case k10t: // op +AA
200 vA = (int8_t) INST_AA(insn); // sign-extend 8-bit value
201 break;
202 case k20t: // op +AAAA
203 vA = (int16_t) FETCH(1); // sign-extend 16-bit value
204 break;
205 case k21c: // op vAA, thing@BBBB
206 case k22x: // op vAA, vBBBB
207 vA = INST_AA(insn);
208 vB = FETCH(1);
209 break;
210 case k21s: // op vAA, #+BBBB
211 case k21t: // op vAA, +BBBB
212 vA = INST_AA(insn);
213 vB = (int16_t) FETCH(1); // sign-extend 16-bit value
214 break;
215 case k21h: // op vAA, #+BBBB0000[00000000]
216 vA = INST_AA(insn);
217 /*
218 * The value should be treated as right-zero-extended, but we don't
219 * actually do that here. Among other things, we don't know if it's
220 * the top bits of a 32- or 64-bit value.
221 */
222 vB = FETCH(1);
223 break;
224 case k23x: // op vAA, vBB, vCC
225 vA = INST_AA(insn);
226 vB = FETCH(1) & 0xff;
227 vC = FETCH(1) >> 8;
228 break;
229 case k22b: // op vAA, vBB, #+CC
230 vA = INST_AA(insn);
231 vB = FETCH(1) & 0xff;
232 vC = (int8_t) (FETCH(1) >> 8); // sign-extend 8-bit value
233 break;
234 case k22s: // op vA, vB, #+CCCC
235 case k22t: // op vA, vB, +CCCC
236 vA = INST_A(insn);
237 vB = INST_B(insn);
238 vC = (int16_t) FETCH(1); // sign-extend 16-bit value
239 break;
240 case k22c: // op vA, vB, thing@CCCC
241 vA = INST_A(insn);
242 vB = INST_B(insn);
243 vC = FETCH(1);
244 break;
245 case k30t: // op +AAAAAAAA
Sebastien Hertz807a2562013-04-15 09:33:39 +0200246 vA = FETCH_uint32(1); // signed 32-bit value
jeffhaoba5ebb92011-08-25 17:24:37 -0700247 break;
248 case k31t: // op vAA, +BBBBBBBB
249 case k31c: // op vAA, string@BBBBBBBB
250 vA = INST_AA(insn);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200251 vB = FETCH_uint32(1); // 32-bit value
jeffhaoba5ebb92011-08-25 17:24:37 -0700252 break;
253 case k32x: // op vAAAA, vBBBB
254 vA = FETCH(1);
255 vB = FETCH(2);
256 break;
257 case k31i: // op vAA, #+BBBBBBBB
258 vA = INST_AA(insn);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200259 vB = FETCH_uint32(1); // signed 32-bit value
jeffhaoba5ebb92011-08-25 17:24:37 -0700260 break;
261 case k35c: // op {vC, vD, vE, vF, vG}, thing@BBBB
262 {
263 /*
264 * Note that the fields mentioned in the spec don't appear in
265 * their "usual" positions here compared to most formats. This
266 * was done so that the field names for the argument count and
267 * reference index match between this format and the corresponding
268 * range formats (3rc and friends).
269 *
270 * Bottom line: The argument count is always in vA, and the
271 * method constant (or equivalent) is always in vB.
272 */
273 uint16_t regList;
274 int count;
275
276 vA = INST_B(insn); // This is labeled A in the spec.
277 vB = FETCH(1);
278 regList = FETCH(2);
279
280 count = vA;
281
282 /*
283 * Copy the argument registers into the arg[] array, and
284 * also copy the first argument (if any) into vC. (The
285 * DecodedInstruction structure doesn't have separate
286 * fields for {vD, vE, vF, vG}, so there's no need to make
287 * copies of those.) Note that cases 5..2 fall through.
288 */
289 switch (count) {
290 case 5: arg[4] = INST_A(insn);
291 case 4: arg[3] = (regList >> 12) & 0x0f;
292 case 3: arg[2] = (regList >> 8) & 0x0f;
293 case 2: arg[1] = (regList >> 4) & 0x0f;
294 case 1: vC = arg[0] = regList & 0x0f; break;
295 case 0: break; // Valid, but no need to do anything.
296 default:
297 LOG(ERROR) << "Invalid arg count in 35c (" << count << ")";
298 return;
299 }
300 }
301 break;
302 case k3rc: // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
303 vA = INST_AA(insn);
304 vB = FETCH(1);
305 vC = FETCH(2);
306 break;
307 case k51l: // op vAA, #+BBBBBBBBBBBBBBBB
308 vA = INST_AA(insn);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200309 vB_wide = FETCH_uint32(1) | ((uint64_t) FETCH_uint32(3) << 32);
jeffhaoba5ebb92011-08-25 17:24:37 -0700310 break;
311 default:
Ian Rogersa75a0132012-09-28 11:41:42 -0700312 LOG(ERROR) << "Can't decode unexpected format " << FormatOf(opcode) << " (op=" << opcode << ")";
jeffhaoba5ebb92011-08-25 17:24:37 -0700313 return;
314 }
315}
316
Ian Rogersa75a0132012-09-28 11:41:42 -0700317size_t Instruction::SizeInCodeUnitsComplexOpcode() const {
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700318 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
Ian Rogersa75a0132012-09-28 11:41:42 -0700319 // Handle special NOP encoded variable length sequences.
320 switch (*insns) {
321 case kPackedSwitchSignature:
322 return (4 + insns[1] * 2);
323 case kSparseSwitchSignature:
324 return (2 + insns[1] * 4);
325 case kArrayDataSignature: {
326 uint16_t element_size = insns[1];
327 uint32_t length = insns[2] | (((uint32_t)insns[3]) << 16);
328 // The plus 1 is to round up for odd size and width.
329 return (4 + (element_size * length + 1) / 2);
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700330 }
Ian Rogersa75a0132012-09-28 11:41:42 -0700331 default:
332 if ((*insns & 0xFF) == 0) {
333 return 1; // NOP.
334 } else {
335 LOG(FATAL) << "Unreachable: " << DumpString(NULL);
336 return 0;
337 }
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700338 }
Ian Rogersd81871c2011-10-03 13:57:23 -0700339}
340
Ian Rogers2c8a8572011-10-24 17:11:36 -0700341std::string Instruction::DumpHex(size_t code_units) const {
Ian Rogersd81871c2011-10-03 13:57:23 -0700342 size_t inst_length = SizeInCodeUnits();
343 if (inst_length > code_units) {
344 inst_length = code_units;
345 }
Ian Rogers2c8a8572011-10-24 17:11:36 -0700346 std::ostringstream os;
Ian Rogersd81871c2011-10-03 13:57:23 -0700347 const uint16_t* insn = reinterpret_cast<const uint16_t*>(this);
348 for (size_t i = 0; i < inst_length; i++) {
Ian Rogers2c8a8572011-10-24 17:11:36 -0700349 os << StringPrintf("0x%04x", insn[i]) << " ";
Ian Rogersd81871c2011-10-03 13:57:23 -0700350 }
351 for (size_t i = inst_length; i < code_units; i++) {
352 os << " ";
353 }
Ian Rogers2c8a8572011-10-24 17:11:36 -0700354 return os.str();
Ian Rogersd81871c2011-10-03 13:57:23 -0700355}
356
Ian Rogers2c8a8572011-10-24 17:11:36 -0700357std::string Instruction::DumpString(const DexFile* file) const {
Ian Rogers2c8a8572011-10-24 17:11:36 -0700358 std::ostringstream os;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200359 const char* opcode = kInstructionNames[Opcode()];
Elliott Hughesadb8c672012-03-06 16:49:32 -0800360 switch (FormatOf(Opcode())) {
Elliott Hughese3c845c2012-02-28 17:23:01 -0800361 case k10x: os << opcode; break;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200362 case k12x: os << StringPrintf("%s v%d, v%d", opcode, VRegA_12x(), VRegB_12x()); break;
363 case k11n: os << StringPrintf("%s v%d, #%+d", opcode, VRegA_11n(), VRegB_11n()); break;
364 case k11x: os << StringPrintf("%s v%d", opcode, VRegA_11x()); break;
365 case k10t: os << StringPrintf("%s %+d", opcode, VRegA_10t()); break;
366 case k20t: os << StringPrintf("%s %+d", opcode, VRegA_20t()); break;
367 case k22x: os << StringPrintf("%s v%d, v%d", opcode, VRegA_22x(), VRegB_22x()); break;
368 case k21t: os << StringPrintf("%s v%d, %+d", opcode, VRegA_21t(), VRegB_21t()); break;
369 case k21s: os << StringPrintf("%s v%d, #%+d", opcode, VRegA_21s(), VRegB_21s()); break;
Elliott Hughes1b3d6ca2012-04-25 13:00:14 -0700370 case k21h: {
371 // op vAA, #+BBBB0000[00000000]
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200372 if (Opcode() == CONST_HIGH16) {
373 uint32_t value = VRegB_21h() << 16;
374 os << StringPrintf("%s v%d, #int %+d // 0x%x", opcode, VRegA_21h(), value, value);
Elliott Hughes1b3d6ca2012-04-25 13:00:14 -0700375 } else {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200376 uint64_t value = static_cast<uint64_t>(VRegB_21h()) << 48;
377 os << StringPrintf("%s v%d, #long %+lld // 0x%llx", opcode, VRegA_21h(), value, value);
Elliott Hughes1b3d6ca2012-04-25 13:00:14 -0700378 }
379 }
380 break;
Ian Rogers90334e52012-06-06 20:22:20 -0700381 case k21c: {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200382 switch (Opcode()) {
Ian Rogers90334e52012-06-06 20:22:20 -0700383 case CONST_STRING:
384 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200385 uint32_t string_idx = VRegB_21c();
386 os << StringPrintf("const-string v%d, %s // string@%d", VRegA_21c(),
387 PrintableString(file->StringDataByIdx(string_idx)).c_str(), string_idx);
Ian Rogers90334e52012-06-06 20:22:20 -0700388 break;
389 } // else fall-through
Mathieu Chartier18c24b62012-09-10 08:54:25 -0700390 case CHECK_CAST:
391 case CONST_CLASS:
Ian Rogers90334e52012-06-06 20:22:20 -0700392 case NEW_INSTANCE:
393 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200394 uint32_t type_idx = VRegB_21c();
Dragos Sbirleab43cef32013-05-23 11:59:20 -0700395 os << opcode << " v" << static_cast<int>(VRegA_21c()) << ", " << PrettyType(type_idx, *file)
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200396 << " // type@" << type_idx;
Ian Rogers90334e52012-06-06 20:22:20 -0700397 break;
398 } // else fall-through
399 case SGET:
400 case SGET_WIDE:
401 case SGET_OBJECT:
402 case SGET_BOOLEAN:
403 case SGET_BYTE:
404 case SGET_CHAR:
405 case SGET_SHORT:
406 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200407 uint32_t field_idx = VRegB_21c();
Dragos Sbirleab43cef32013-05-23 11:59:20 -0700408 os << opcode << " v" << static_cast<int>(VRegA_21c()) << ", " << PrettyField(field_idx, *file, true)
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200409 << " // field@" << field_idx;
Ian Rogers90334e52012-06-06 20:22:20 -0700410 break;
411 } // else fall-through
412 case SPUT:
413 case SPUT_WIDE:
414 case SPUT_OBJECT:
415 case SPUT_BOOLEAN:
416 case SPUT_BYTE:
417 case SPUT_CHAR:
418 case SPUT_SHORT:
419 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200420 uint32_t field_idx = VRegB_21c();
Dragos Sbirleab43cef32013-05-23 11:59:20 -0700421 os << opcode << " v" << static_cast<int>(VRegA_21c()) << ", " << PrettyField(field_idx, *file, true)
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200422 << " // field@" << field_idx;
Ian Rogers90334e52012-06-06 20:22:20 -0700423 break;
424 } // else fall-through
425 default:
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200426 os << StringPrintf("%s v%d, thing@%d", opcode, VRegA_21c(), VRegB_21c());
Ian Rogers90334e52012-06-06 20:22:20 -0700427 break;
428 }
429 break;
430 }
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200431 case k23x: os << StringPrintf("%s v%d, v%d, v%d", opcode, VRegA_23x(), VRegB_23x(), VRegC_23x()); break;
432 case k22b: os << StringPrintf("%s v%d, v%d, #%+d", opcode, VRegA_22b(), VRegB_22b(), VRegC_22b()); break;
433 case k22t: os << StringPrintf("%s v%d, v%d, %+d", opcode, VRegA_22t(), VRegB_22t(), VRegC_22t()); break;
434 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 -0700435 case k22c: {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200436 switch (Opcode()) {
Ian Rogers90334e52012-06-06 20:22:20 -0700437 case IGET:
438 case IGET_WIDE:
439 case IGET_OBJECT:
440 case IGET_BOOLEAN:
441 case IGET_BYTE:
442 case IGET_CHAR:
443 case IGET_SHORT:
444 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200445 uint32_t field_idx = VRegC_22c();
Dragos Sbirleab43cef32013-05-23 11:59:20 -0700446 os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200447 << PrettyField(field_idx, *file, true) << " // field@" << field_idx;
Ian Rogers90334e52012-06-06 20:22:20 -0700448 break;
449 } // else fall-through
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200450 case IGET_QUICK:
451 case IGET_OBJECT_QUICK:
452 if (file != NULL) {
453 uint32_t field_idx = VRegC_22c();
454 os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
455 << "// offset@" << field_idx;
456 break;
457 } // else fall-through
Ian Rogers90334e52012-06-06 20:22:20 -0700458 case IPUT:
459 case IPUT_WIDE:
460 case IPUT_OBJECT:
461 case IPUT_BOOLEAN:
462 case IPUT_BYTE:
463 case IPUT_CHAR:
464 case IPUT_SHORT:
465 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200466 uint32_t field_idx = VRegC_22c();
Dragos Sbirleab43cef32013-05-23 11:59:20 -0700467 os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200468 << PrettyField(field_idx, *file, true) << " // field@" << field_idx;
Ian Rogers90334e52012-06-06 20:22:20 -0700469 break;
470 } // else fall-through
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200471 case IPUT_QUICK:
472 case IPUT_OBJECT_QUICK:
473 if (file != NULL) {
474 uint32_t field_idx = VRegC_22c();
475 os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
476 << "// offset@" << field_idx;
477 break;
478 } // else fall-through
Ian Rogers90334e52012-06-06 20:22:20 -0700479 case INSTANCE_OF:
480 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200481 uint32_t type_idx = VRegC_22c();
Dragos Sbirlead4e868a2013-05-23 09:44:17 -0700482 os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200483 << PrettyType(type_idx, *file) << " // type@" << type_idx;
Mathieu Chartier18c24b62012-09-10 08:54:25 -0700484 break;
485 }
486 case NEW_ARRAY:
487 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200488 uint32_t type_idx = VRegC_22c();
Dragos Sbirleab43cef32013-05-23 11:59:20 -0700489 os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200490 << PrettyType(type_idx, *file) << " // type@" << type_idx;
Ian Rogers90334e52012-06-06 20:22:20 -0700491 break;
492 } // else fall-through
493 default:
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200494 os << StringPrintf("%s v%d, v%d, thing@%d", opcode, VRegA_22c(), VRegB_22c(), VRegC_22c());
Ian Rogers90334e52012-06-06 20:22:20 -0700495 break;
496 }
497 break;
498 }
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200499 case k32x: os << StringPrintf("%s v%d, v%d", opcode, VRegA_32x(), VRegB_32x()); break;
500 case k30t: os << StringPrintf("%s %+d", opcode, VRegA_30t()); break;
501 case k31t: os << StringPrintf("%s v%d, %+d", opcode, VRegA_31t(), VRegB_31t()); break;
502 case k31i: os << StringPrintf("%s v%d, #%+d", opcode, VRegA_31i(), VRegB_31i()); break;
503 case k31c: os << StringPrintf("%s v%d, thing@%d", opcode, VRegA_31c(), VRegB_31c()); break;
Ian Rogersd81871c2011-10-03 13:57:23 -0700504 case k35c: {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200505 uint32_t arg[5];
506 GetArgs(arg);
507 switch (Opcode()) {
Ian Rogersd81871c2011-10-03 13:57:23 -0700508 case INVOKE_VIRTUAL:
509 case INVOKE_SUPER:
510 case INVOKE_DIRECT:
511 case INVOKE_STATIC:
512 case INVOKE_INTERFACE:
513 if (file != NULL) {
Elliott Hughese3c845c2012-02-28 17:23:01 -0800514 os << opcode << " {";
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200515 uint32_t method_idx = VRegB_35c();
516 for (size_t i = 0; i < VRegA_35c(); ++i) {
Elliott Hughese3c845c2012-02-28 17:23:01 -0800517 if (i != 0) {
518 os << ", ";
519 }
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200520 os << "v" << arg[i];
Elliott Hughese3c845c2012-02-28 17:23:01 -0800521 }
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200522 os << "}, " << PrettyMethod(method_idx, *file) << " // method@" << method_idx;
Ian Rogersd81871c2011-10-03 13:57:23 -0700523 break;
524 } // else fall-through
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200525 case INVOKE_VIRTUAL_QUICK:
526 if (file != NULL) {
527 os << opcode << " {";
528 uint32_t method_idx = VRegB_35c();
529 for (size_t i = 0; i < VRegA_35c(); ++i) {
530 if (i != 0) {
531 os << ", ";
532 }
533 os << "v" << arg[i];
534 }
535 os << "}, // vtable@" << method_idx;
536 break;
537 } // else fall-through
Ian Rogersd81871c2011-10-03 13:57:23 -0700538 default:
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200539 os << opcode << " {v" << arg[0] << ", v" << arg[1] << ", v" << arg[2]
540 << ", v" << arg[3] << ", v" << arg[4] << "}, thing@" << VRegB_35c();
Ian Rogersd81871c2011-10-03 13:57:23 -0700541 break;
542 }
543 break;
544 }
Ian Rogers4c5dd5a2012-09-07 11:27:28 -0700545 case k3rc: {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200546 switch (Opcode()) {
Ian Rogers4c5dd5a2012-09-07 11:27:28 -0700547 case INVOKE_VIRTUAL_RANGE:
548 case INVOKE_SUPER_RANGE:
549 case INVOKE_DIRECT_RANGE:
550 case INVOKE_STATIC_RANGE:
551 case INVOKE_INTERFACE_RANGE:
552 if (file != NULL) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200553 uint32_t method_idx = VRegB_3rc();
554 os << StringPrintf("%s, {v%d .. v%d}, ", opcode, VRegC_3rc(), (VRegC_3rc() + VRegA_3rc() - 1))
555 << PrettyMethod(method_idx, *file) << " // method@" << method_idx;
Ian Rogers4c5dd5a2012-09-07 11:27:28 -0700556 break;
557 } // else fall-through
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200558 case INVOKE_VIRTUAL_RANGE_QUICK:
559 if (file != NULL) {
560 uint32_t method_idx = VRegB_3rc();
561 os << StringPrintf("%s, {v%d .. v%d}, ", opcode, VRegC_3rc(), (VRegC_3rc() + VRegA_3rc() - 1))
562 << "// vtable@" << method_idx;
563 break;
564 } // else fall-through
Ian Rogers4c5dd5a2012-09-07 11:27:28 -0700565 default:
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200566 os << StringPrintf("%s, {v%d .. v%d}, thing@%d", opcode, VRegC_3rc(),
567 (VRegC_3rc() + VRegA_3rc() - 1), VRegB_3rc());
Ian Rogers4c5dd5a2012-09-07 11:27:28 -0700568 break;
569 }
570 break;
571 }
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200572 case k51l: os << StringPrintf("%s v%d, #%+lld", opcode, VRegA_51l(), VRegB_51l()); break;
Ian Rogers2c8a8572011-10-24 17:11:36 -0700573 default: os << " unknown format (" << DumpHex(5) << ")"; break;
Ian Rogersd81871c2011-10-03 13:57:23 -0700574 }
Ian Rogers2c8a8572011-10-24 17:11:36 -0700575 return os.str();
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700576}
577
Ian Rogersa75a0132012-09-28 11:41:42 -0700578std::ostream& operator<<(std::ostream& os, const Instruction::Code& code) {
579 return os << Instruction::Name(code);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800580}
581
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700582} // namespace art