]> git.proxmox.com Git - mirror_qemu.git/blame - disas.c
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
[mirror_qemu.git] / disas.c
CommitLineData
b9adb4a6 1/* General "disassemble this chunk" code. Used for debugging. */
d38ea87a 2#include "qemu/osdep.h"
3979fca4 3#include "disas/dis-asm.h"
b9adb4a6 4#include "elf.h"
30cc9831 5#include "qemu/qemu-print.h"
b9adb4a6 6
c6105c0a 7#include "cpu.h"
76cad711 8#include "disas/disas.h"
8ca80760 9#include "disas/capstone.h"
c6105c0a 10
f4359b9f
BS
11typedef struct CPUDebug {
12 struct disassemble_info info;
d49190c4 13 CPUState *cpu;
f4359b9f
BS
14} CPUDebug;
15
b9adb4a6 16/* Filled in by elfload.c. Simplistic, but will do for now. */
e80cfcfc 17struct syminfo *syminfos = NULL;
b9adb4a6 18
aa0aa4fa
FB
19/* Get LENGTH bytes from info's buffer, at target address memaddr.
20 Transfer them to myaddr. */
21int
3a742b76
PB
22buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
23 struct disassemble_info *info)
aa0aa4fa 24{
c6105c0a
FB
25 if (memaddr < info->buffer_vma
26 || memaddr + length > info->buffer_vma + info->buffer_length)
27 /* Out of bounds. Use EIO because GDB uses it. */
28 return EIO;
29 memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length);
30 return 0;
aa0aa4fa
FB
31}
32
c6105c0a
FB
33/* Get LENGTH bytes from info's buffer, at target address memaddr.
34 Transfer them to myaddr. */
35static int
c27004ec
FB
36target_read_memory (bfd_vma memaddr,
37 bfd_byte *myaddr,
38 int length,
39 struct disassemble_info *info)
c6105c0a 40{
f4359b9f
BS
41 CPUDebug *s = container_of(info, CPUDebug, info);
42
d49190c4 43 cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
c6105c0a
FB
44 return 0;
45}
c6105c0a 46
aa0aa4fa
FB
47/* Print an error message. We can assume that this is in response to
48 an error return from buffer_read_memory. */
49void
3a742b76 50perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info)
aa0aa4fa
FB
51{
52 if (status != EIO)
53 /* Can't happen. */
54 (*info->fprintf_func) (info->stream, "Unknown error %d\n", status);
55 else
56 /* Actually, address between memaddr and memaddr + len was
57 out of bounds. */
58 (*info->fprintf_func) (info->stream,
26a76461 59 "Address 0x%" PRIx64 " is out of bounds.\n", memaddr);
aa0aa4fa
FB
60}
61
a31f0531 62/* This could be in a separate file, to save minuscule amounts of space
aa0aa4fa
FB
63 in statically linked executables. */
64
65/* Just print the address is hex. This is included for completeness even
66 though both GDB and objdump provide their own (to print symbolic
67 addresses). */
68
69void
3a742b76 70generic_print_address (bfd_vma addr, struct disassemble_info *info)
aa0aa4fa 71{
26a76461 72 (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
aa0aa4fa
FB
73}
74
636bd289
PM
75/* Print address in hex, truncated to the width of a host virtual address. */
76static void
77generic_print_host_address(bfd_vma addr, struct disassemble_info *info)
78{
79 uint64_t mask = ~0ULL >> (64 - (sizeof(void *) * 8));
80 generic_print_address(addr & mask, info);
81}
82
aa0aa4fa
FB
83/* Just return the given address. */
84
85int
3a742b76 86generic_symbol_at_address (bfd_vma addr, struct disassemble_info *info)
aa0aa4fa
FB
87{
88 return 1;
89}
90
903ec55c
AJ
91bfd_vma bfd_getl64 (const bfd_byte *addr)
92{
93 unsigned long long v;
94
95 v = (unsigned long long) addr[0];
96 v |= (unsigned long long) addr[1] << 8;
97 v |= (unsigned long long) addr[2] << 16;
98 v |= (unsigned long long) addr[3] << 24;
99 v |= (unsigned long long) addr[4] << 32;
100 v |= (unsigned long long) addr[5] << 40;
101 v |= (unsigned long long) addr[6] << 48;
102 v |= (unsigned long long) addr[7] << 56;
103 return (bfd_vma) v;
104}
105
aa0aa4fa
FB
106bfd_vma bfd_getl32 (const bfd_byte *addr)
107{
108 unsigned long v;
109
110 v = (unsigned long) addr[0];
111 v |= (unsigned long) addr[1] << 8;
112 v |= (unsigned long) addr[2] << 16;
113 v |= (unsigned long) addr[3] << 24;
114 return (bfd_vma) v;
115}
116
117bfd_vma bfd_getb32 (const bfd_byte *addr)
118{
119 unsigned long v;
120
121 v = (unsigned long) addr[0] << 24;
122 v |= (unsigned long) addr[1] << 16;
123 v |= (unsigned long) addr[2] << 8;
124 v |= (unsigned long) addr[3];
125 return (bfd_vma) v;
126}
127
6af0bf9c
FB
128bfd_vma bfd_getl16 (const bfd_byte *addr)
129{
130 unsigned long v;
131
132 v = (unsigned long) addr[0];
133 v |= (unsigned long) addr[1] << 8;
134 return (bfd_vma) v;
135}
136
137bfd_vma bfd_getb16 (const bfd_byte *addr)
138{
139 unsigned long v;
140
141 v = (unsigned long) addr[0] << 24;
142 v |= (unsigned long) addr[1] << 16;
143 return (bfd_vma) v;
144}
145
c46ffd57
RH
146static int print_insn_objdump(bfd_vma pc, disassemble_info *info,
147 const char *prefix)
148{
149 int i, n = info->buffer_length;
150 uint8_t *buf = g_malloc(n);
151
152 info->read_memory_func(pc, buf, n, info);
153
154 for (i = 0; i < n; ++i) {
155 if (i % 32 == 0) {
156 info->fprintf_func(info->stream, "\n%s: ", prefix);
157 }
158 info->fprintf_func(info->stream, "%02x", buf[i]);
159 }
160
161 g_free(buf);
162 return n;
163}
164
165static int print_insn_od_host(bfd_vma pc, disassemble_info *info)
166{
167 return print_insn_objdump(pc, info, "OBJD-H");
168}
169
170static int print_insn_od_target(bfd_vma pc, disassemble_info *info)
171{
172 return print_insn_objdump(pc, info, "OBJD-T");
173}
174
8ca80760
RH
175#ifdef CONFIG_CAPSTONE
176/* Temporary storage for the capstone library. This will be alloced via
177 malloc with a size private to the library; thus there's no reason not
178 to share this across calls and across host vs target disassembly. */
179static __thread cs_insn *cap_insn;
180
181/* Initialize the Capstone library. */
182/* ??? It would be nice to cache this. We would need one handle for the
183 host and one for the target. For most targets we can reset specific
184 parameters via cs_option(CS_OPT_MODE, new_mode), but we cannot change
185 CS_ARCH_* in this way. Thus we would need to be able to close and
186 re-open the target handle with a different arch for the target in order
187 to handle AArch64 vs AArch32 mode switching. */
188static cs_err cap_disas_start(disassemble_info *info, csh *handle)
189{
190 cs_mode cap_mode = info->cap_mode;
191 cs_err err;
192
193 cap_mode += (info->endian == BFD_ENDIAN_BIG ? CS_MODE_BIG_ENDIAN
194 : CS_MODE_LITTLE_ENDIAN);
195
196 err = cs_open(info->cap_arch, cap_mode, handle);
197 if (err != CS_ERR_OK) {
198 return err;
199 }
200
201 /* ??? There probably ought to be a better place to put this. */
202 if (info->cap_arch == CS_ARCH_X86) {
203 /* We don't care about errors (if for some reason the library
204 is compiled without AT&T syntax); the user will just have
205 to deal with the Intel syntax. */
206 cs_option(*handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
207 }
208
209 /* "Disassemble" unknown insns as ".byte W,X,Y,Z". */
210 cs_option(*handle, CS_OPT_SKIPDATA, CS_OPT_ON);
211
212 /* Allocate temp space for cs_disasm_iter. */
213 if (cap_insn == NULL) {
214 cap_insn = cs_malloc(*handle);
215 if (cap_insn == NULL) {
216 cs_close(handle);
217 return CS_ERR_MEM;
218 }
219 }
220 return CS_ERR_OK;
221}
222
15fa1a0a
RH
223static void cap_dump_insn_units(disassemble_info *info, cs_insn *insn,
224 int i, int n)
225{
226 fprintf_function print = info->fprintf_func;
227 FILE *stream = info->stream;
228
229 switch (info->cap_insn_unit) {
230 case 4:
231 if (info->endian == BFD_ENDIAN_BIG) {
232 for (; i < n; i += 4) {
233 print(stream, " %08x", ldl_be_p(insn->bytes + i));
234
235 }
236 } else {
237 for (; i < n; i += 4) {
238 print(stream, " %08x", ldl_le_p(insn->bytes + i));
239 }
240 }
241 break;
242
243 case 2:
244 if (info->endian == BFD_ENDIAN_BIG) {
245 for (; i < n; i += 2) {
246 print(stream, " %04x", lduw_be_p(insn->bytes + i));
247 }
248 } else {
249 for (; i < n; i += 2) {
250 print(stream, " %04x", lduw_le_p(insn->bytes + i));
251 }
252 }
253 break;
254
255 default:
256 for (; i < n; i++) {
257 print(stream, " %02x", insn->bytes[i]);
258 }
259 break;
260 }
261}
262
263static void cap_dump_insn(disassemble_info *info, cs_insn *insn)
264{
265 fprintf_function print = info->fprintf_func;
266 int i, n, split;
267
268 print(info->stream, "0x%08" PRIx64 ": ", insn->address);
269
270 n = insn->size;
271 split = info->cap_insn_split;
272
273 /* Dump the first SPLIT bytes of the instruction. */
274 cap_dump_insn_units(info, insn, 0, MIN(n, split));
275
276 /* Add padding up to SPLIT so that mnemonics line up. */
277 if (n < split) {
278 int width = (split - n) / info->cap_insn_unit;
279 width *= (2 * info->cap_insn_unit + 1);
280 print(info->stream, "%*s", width, "");
281 }
282
283 /* Print the actual instruction. */
284 print(info->stream, " %-8s %s\n", insn->mnemonic, insn->op_str);
285
286 /* Dump any remaining part of the insn on subsequent lines. */
287 for (i = split; i < n; i += split) {
288 print(info->stream, "0x%08" PRIx64 ": ", insn->address + i);
289 cap_dump_insn_units(info, insn, i, MIN(n, i + split));
290 print(info->stream, "\n");
291 }
292}
293
8ca80760
RH
294/* Disassemble SIZE bytes at PC for the target. */
295static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size)
296{
297 uint8_t cap_buf[1024];
298 csh handle;
299 cs_insn *insn;
300 size_t csize = 0;
301
302 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
303 return false;
304 }
305 insn = cap_insn;
306
307 while (1) {
308 size_t tsize = MIN(sizeof(cap_buf) - csize, size);
309 const uint8_t *cbuf = cap_buf;
310
311 target_read_memory(pc + csize, cap_buf + csize, tsize, info);
312 csize += tsize;
313 size -= tsize;
314
315 while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
15fa1a0a 316 cap_dump_insn(info, insn);
8ca80760
RH
317 }
318
319 /* If the target memory is not consumed, go back for more... */
320 if (size != 0) {
321 /* ... taking care to move any remaining fractional insn
322 to the beginning of the buffer. */
323 if (csize != 0) {
324 memmove(cap_buf, cbuf, csize);
325 }
326 continue;
327 }
328
329 /* Since the target memory is consumed, we should not have
330 a remaining fractional insn. */
331 if (csize != 0) {
332 (*info->fprintf_func)(info->stream,
333 "Disassembler disagrees with translator "
334 "over instruction decoding\n"
335 "Please report this to qemu-devel@nongnu.org\n");
336 }
337 break;
338 }
339
340 cs_close(&handle);
341 return true;
342}
343
344/* Disassemble SIZE bytes at CODE for the host. */
345static bool cap_disas_host(disassemble_info *info, void *code, size_t size)
346{
347 csh handle;
348 const uint8_t *cbuf;
349 cs_insn *insn;
350 uint64_t pc;
351
352 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
353 return false;
354 }
355 insn = cap_insn;
356
357 cbuf = code;
358 pc = (uintptr_t)code;
359
360 while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) {
15fa1a0a 361 cap_dump_insn(info, insn);
8ca80760
RH
362 }
363 if (size != 0) {
364 (*info->fprintf_func)(info->stream,
365 "Disassembler disagrees with TCG over instruction encoding\n"
366 "Please report this to qemu-devel@nongnu.org\n");
367 }
368
369 cs_close(&handle);
370 return true;
371}
372
373#if !defined(CONFIG_USER_ONLY)
374/* Disassemble COUNT insns at PC for the target. */
375static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count)
376{
377 uint8_t cap_buf[32];
378 csh handle;
379 cs_insn *insn;
380 size_t csize = 0;
381
382 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
383 return false;
384 }
385 insn = cap_insn;
386
387 while (1) {
388 /* We want to read memory for one insn, but generically we do not
389 know how much memory that is. We have a small buffer which is
390 known to be sufficient for all supported targets. Try to not
391 read beyond the page, Just In Case. For even more simplicity,
392 ignore the actual target page size and use a 1k boundary. If
393 that turns out to be insufficient, we'll come back around the
394 loop and read more. */
395 uint64_t epc = QEMU_ALIGN_UP(pc + csize + 1, 1024);
396 size_t tsize = MIN(sizeof(cap_buf) - csize, epc - pc);
397 const uint8_t *cbuf = cap_buf;
398
399 /* Make certain that we can make progress. */
400 assert(tsize != 0);
401 info->read_memory_func(pc, cap_buf + csize, tsize, info);
402 csize += tsize;
403
404 if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
15fa1a0a 405 cap_dump_insn(info, insn);
8ca80760
RH
406 if (--count <= 0) {
407 break;
408 }
409 }
410 memmove(cap_buf, cbuf, csize);
411 }
412
413 cs_close(&handle);
414 return true;
415}
416#endif /* !CONFIG_USER_ONLY */
417#else
418# define cap_disas_target(i, p, s) false
419# define cap_disas_host(i, p, s) false
420# define cap_disas_monitor(i, p, c) false
421#endif /* CONFIG_CAPSTONE */
422
1d48474d 423/* Disassemble this for me please... (debugging). */
d49190c4 424void target_disas(FILE *out, CPUState *cpu, target_ulong code,
1d48474d 425 target_ulong size)
b9adb4a6 426{
37b9de46 427 CPUClass *cc = CPU_GET_CLASS(cpu);
c27004ec 428 target_ulong pc;
b9adb4a6 429 int count;
f4359b9f 430 CPUDebug s;
b9adb4a6 431
f4359b9f 432 INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
b9adb4a6 433
d49190c4 434 s.cpu = cpu;
f4359b9f
BS
435 s.info.read_memory_func = target_read_memory;
436 s.info.buffer_vma = code;
437 s.info.buffer_length = size;
9504c544 438 s.info.print_address_func = generic_print_address;
8ca80760
RH
439 s.info.cap_arch = -1;
440 s.info.cap_mode = 0;
15fa1a0a
RH
441 s.info.cap_insn_unit = 4;
442 s.info.cap_insn_split = 4;
c27004ec
FB
443
444#ifdef TARGET_WORDS_BIGENDIAN
f4359b9f 445 s.info.endian = BFD_ENDIAN_BIG;
c27004ec 446#else
f4359b9f 447 s.info.endian = BFD_ENDIAN_LITTLE;
c27004ec 448#endif
37b9de46
PC
449
450 if (cc->disas_set_info) {
451 cc->disas_set_info(cpu, &s.info);
452 }
453
8ca80760
RH
454 if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) {
455 return;
456 }
457
2de295c5
PC
458 if (s.info.print_insn == NULL) {
459 s.info.print_insn = print_insn_od_target;
c46ffd57 460 }
c6105c0a 461
7e000c2e 462 for (pc = code; size > 0; pc += count, size -= count) {
fa15e030 463 fprintf(out, "0x" TARGET_FMT_lx ": ", pc);
2de295c5 464 count = s.info.print_insn(pc, &s.info);
c27004ec
FB
465 fprintf(out, "\n");
466 if (count < 0)
467 break;
754d00ae 468 if (size < count) {
469 fprintf(out,
470 "Disassembler disagrees with translator over instruction "
471 "decoding\n"
472 "Please report this to qemu-devel@nongnu.org\n");
473 break;
474 }
c27004ec
FB
475 }
476}
477
478/* Disassemble this for me please... (debugging). */
479void disas(FILE *out, void *code, unsigned long size)
480{
b0b0f1c9 481 uintptr_t pc;
c27004ec 482 int count;
f4359b9f 483 CPUDebug s;
c46ffd57 484 int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL;
c27004ec 485
f4359b9f
BS
486 INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
487 s.info.print_address_func = generic_print_host_address;
c27004ec 488
f4359b9f
BS
489 s.info.buffer = code;
490 s.info.buffer_vma = (uintptr_t)code;
491 s.info.buffer_length = size;
8ca80760
RH
492 s.info.cap_arch = -1;
493 s.info.cap_mode = 0;
15fa1a0a
RH
494 s.info.cap_insn_unit = 4;
495 s.info.cap_insn_split = 4;
b9adb4a6 496
e2542fe2 497#ifdef HOST_WORDS_BIGENDIAN
f4359b9f 498 s.info.endian = BFD_ENDIAN_BIG;
b9adb4a6 499#else
f4359b9f 500 s.info.endian = BFD_ENDIAN_LITTLE;
b9adb4a6 501#endif
5826e519
SW
502#if defined(CONFIG_TCG_INTERPRETER)
503 print_insn = print_insn_tci;
504#elif defined(__i386__)
f4359b9f 505 s.info.mach = bfd_mach_i386_i386;
c27004ec 506 print_insn = print_insn_i386;
b666d2a4
RH
507 s.info.cap_arch = CS_ARCH_X86;
508 s.info.cap_mode = CS_MODE_32;
15fa1a0a
RH
509 s.info.cap_insn_unit = 1;
510 s.info.cap_insn_split = 8;
bc51c5c9 511#elif defined(__x86_64__)
f4359b9f 512 s.info.mach = bfd_mach_x86_64;
c27004ec 513 print_insn = print_insn_i386;
b666d2a4
RH
514 s.info.cap_arch = CS_ARCH_X86;
515 s.info.cap_mode = CS_MODE_64;
15fa1a0a
RH
516 s.info.cap_insn_unit = 1;
517 s.info.cap_insn_split = 8;
e58ffeb3 518#elif defined(_ARCH_PPC)
66d4f6a3 519 s.info.disassembler_options = (char *)"any";
c27004ec 520 print_insn = print_insn_ppc;
ac226899
RH
521 s.info.cap_arch = CS_ARCH_PPC;
522# ifdef _ARCH_PPC64
523 s.info.cap_mode = CS_MODE_64;
524# endif
91468b27
AF
525#elif defined(__riscv) && defined(CONFIG_RISCV_DIS)
526#if defined(_ILP32) || (__riscv_xlen == 32)
527 print_insn = print_insn_riscv32;
528#elif defined(_LP64)
529 print_insn = print_insn_riscv64;
530#else
531#error unsupported RISC-V ABI
532#endif
999b53ec
CF
533#elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
534 print_insn = print_insn_arm_a64;
110f6c70 535 s.info.cap_arch = CS_ARCH_ARM64;
a993ba85 536#elif defined(__alpha__)
c27004ec 537 print_insn = print_insn_alpha;
aa0aa4fa 538#elif defined(__sparc__)
c27004ec 539 print_insn = print_insn_sparc;
f4359b9f 540 s.info.mach = bfd_mach_sparc_v9b;
5fafdf24 541#elif defined(__arm__)
c27004ec 542 print_insn = print_insn_arm;
110f6c70
RH
543 s.info.cap_arch = CS_ARCH_ARM;
544 /* TCG only generates code for arm mode. */
6af0bf9c
FB
545#elif defined(__MIPSEB__)
546 print_insn = print_insn_big_mips;
547#elif defined(__MIPSEL__)
548 print_insn = print_insn_little_mips;
48024e4a
FB
549#elif defined(__m68k__)
550 print_insn = print_insn_m68k;
8f860bb8
TS
551#elif defined(__s390__)
552 print_insn = print_insn_s390;
429b31a2
RH
553#elif defined(__hppa__)
554 print_insn = print_insn_hppa;
b9adb4a6 555#endif
8ca80760
RH
556
557 if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) {
558 return;
559 }
560
c46ffd57
RH
561 if (print_insn == NULL) {
562 print_insn = print_insn_od_host;
563 }
b0b0f1c9
SW
564 for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
565 fprintf(out, "0x%08" PRIxPTR ": ", pc);
f4359b9f 566 count = print_insn(pc, &s.info);
b9adb4a6
FB
567 fprintf(out, "\n");
568 if (count < 0)
569 break;
570 }
571}
572
573/* Look up symbol for debugging purpose. Returns "" if unknown. */
c27004ec 574const char *lookup_symbol(target_ulong orig_addr)
b9adb4a6 575{
49918a75 576 const char *symbol = "";
e80cfcfc 577 struct syminfo *s;
3b46e624 578
e80cfcfc 579 for (s = syminfos; s; s = s->next) {
49918a75
PB
580 symbol = s->lookup_symbol(s, orig_addr);
581 if (symbol[0] != '\0') {
582 break;
583 }
b9adb4a6 584 }
49918a75
PB
585
586 return symbol;
b9adb4a6 587}
9307c4c1
FB
588
589#if !defined(CONFIG_USER_ONLY)
590
83c9089e 591#include "monitor/monitor.h"
3d2cfdf1 592
9307c4c1 593static int
b8d87208 594physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
a5f1b965 595 struct disassemble_info *info)
9307c4c1 596{
f2c6abc8
PM
597 CPUDebug *s = container_of(info, CPUDebug, info);
598
599 address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED,
600 myaddr, length);
9307c4c1
FB
601 return 0;
602}
603
1d48474d 604/* Disassembler for the monitor. */
d49190c4 605void monitor_disas(Monitor *mon, CPUState *cpu,
1d48474d 606 target_ulong pc, int nb_insn, int is_physical)
9307c4c1 607{
37b9de46 608 CPUClass *cc = CPU_GET_CLASS(cpu);
9307c4c1 609 int count, i;
f4359b9f 610 CPUDebug s;
9307c4c1 611
30cc9831 612 INIT_DISASSEMBLE_INFO(s.info, NULL, qemu_fprintf);
9307c4c1 613
d49190c4 614 s.cpu = cpu;
b8d87208
RH
615 s.info.read_memory_func
616 = (is_physical ? physical_read_memory : target_read_memory);
9504c544 617 s.info.print_address_func = generic_print_address;
f4359b9f 618 s.info.buffer_vma = pc;
8ca80760
RH
619 s.info.cap_arch = -1;
620 s.info.cap_mode = 0;
15fa1a0a
RH
621 s.info.cap_insn_unit = 4;
622 s.info.cap_insn_split = 4;
9307c4c1
FB
623
624#ifdef TARGET_WORDS_BIGENDIAN
f4359b9f 625 s.info.endian = BFD_ENDIAN_BIG;
9307c4c1 626#else
f4359b9f 627 s.info.endian = BFD_ENDIAN_LITTLE;
9307c4c1 628#endif
37b9de46
PC
629
630 if (cc->disas_set_info) {
631 cc->disas_set_info(cpu, &s.info);
632 }
633
8ca80760
RH
634 if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) {
635 return;
636 }
637
37b9de46
PC
638 if (!s.info.print_insn) {
639 monitor_printf(mon, "0x" TARGET_FMT_lx
640 ": Asm output not supported on this arch\n", pc);
641 return;
642 }
9307c4c1
FB
643
644 for(i = 0; i < nb_insn; i++) {
376253ec 645 monitor_printf(mon, "0x" TARGET_FMT_lx ": ", pc);
2de295c5 646 count = s.info.print_insn(pc, &s.info);
376253ec 647 monitor_printf(mon, "\n");
9307c4c1
FB
648 if (count < 0)
649 break;
650 pc += count;
651 }
652}
653#endif