Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
[qemu.git] / disas.c
1 /* General "disassemble this chunk" code. Used for debugging. */
2 #include "qemu/osdep.h"
3 #include "disas/dis-asm.h"
4 #include "elf.h"
5 #include "qemu/qemu-print.h"
6
7 #include "cpu.h"
8 #include "disas/disas.h"
9 #include "disas/capstone.h"
10
11 typedef struct CPUDebug {
12 struct disassemble_info info;
13 CPUState *cpu;
14 } CPUDebug;
15
16 /* Filled in by elfload.c. Simplistic, but will do for now. */
17 struct syminfo *syminfos = NULL;
18
19 /* Get LENGTH bytes from info's buffer, at target address memaddr.
20 Transfer them to myaddr. */
21 int
22 buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
23 struct disassemble_info *info)
24 {
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;
31 }
32
33 /* Get LENGTH bytes from info's buffer, at target address memaddr.
34 Transfer them to myaddr. */
35 static int
36 target_read_memory (bfd_vma memaddr,
37 bfd_byte *myaddr,
38 int length,
39 struct disassemble_info *info)
40 {
41 CPUDebug *s = container_of(info, CPUDebug, info);
42
43 cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
44 return 0;
45 }
46
47 /* Print an error message. We can assume that this is in response to
48 an error return from buffer_read_memory. */
49 void
50 perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info)
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,
59 "Address 0x%" PRIx64 " is out of bounds.\n", memaddr);
60 }
61
62 /* This could be in a separate file, to save minuscule amounts of space
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
69 void
70 generic_print_address (bfd_vma addr, struct disassemble_info *info)
71 {
72 (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
73 }
74
75 /* Print address in hex, truncated to the width of a host virtual address. */
76 static void
77 generic_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
83 /* Just return the given address. */
84
85 int
86 generic_symbol_at_address (bfd_vma addr, struct disassemble_info *info)
87 {
88 return 1;
89 }
90
91 bfd_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
106 bfd_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
117 bfd_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
128 bfd_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
137 bfd_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
146 static 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
165 static int print_insn_od_host(bfd_vma pc, disassemble_info *info)
166 {
167 return print_insn_objdump(pc, info, "OBJD-H");
168 }
169
170 static int print_insn_od_target(bfd_vma pc, disassemble_info *info)
171 {
172 return print_insn_objdump(pc, info, "OBJD-T");
173 }
174
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. */
179 static __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. */
188 static 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
223 static 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
263 static 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
294 /* Disassemble SIZE bytes at PC for the target. */
295 static 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)) {
316 cap_dump_insn(info, insn);
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. */
345 static 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)) {
361 cap_dump_insn(info, insn);
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. */
375 static 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)) {
405 cap_dump_insn(info, insn);
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 # define cap_disas_plugin(i, p, c) false
422 #endif /* CONFIG_CAPSTONE */
423
424 /* Disassemble this for me please... (debugging). */
425 void target_disas(FILE *out, CPUState *cpu, target_ulong code,
426 target_ulong size)
427 {
428 CPUClass *cc = CPU_GET_CLASS(cpu);
429 target_ulong pc;
430 int count;
431 CPUDebug s;
432
433 INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
434
435 s.cpu = cpu;
436 s.info.read_memory_func = target_read_memory;
437 s.info.buffer_vma = code;
438 s.info.buffer_length = size;
439 s.info.print_address_func = generic_print_address;
440 s.info.cap_arch = -1;
441 s.info.cap_mode = 0;
442 s.info.cap_insn_unit = 4;
443 s.info.cap_insn_split = 4;
444
445 #ifdef TARGET_WORDS_BIGENDIAN
446 s.info.endian = BFD_ENDIAN_BIG;
447 #else
448 s.info.endian = BFD_ENDIAN_LITTLE;
449 #endif
450
451 if (cc->disas_set_info) {
452 cc->disas_set_info(cpu, &s.info);
453 }
454
455 if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) {
456 return;
457 }
458
459 if (s.info.print_insn == NULL) {
460 s.info.print_insn = print_insn_od_target;
461 }
462
463 for (pc = code; size > 0; pc += count, size -= count) {
464 fprintf(out, "0x" TARGET_FMT_lx ": ", pc);
465 count = s.info.print_insn(pc, &s.info);
466 fprintf(out, "\n");
467 if (count < 0)
468 break;
469 if (size < count) {
470 fprintf(out,
471 "Disassembler disagrees with translator over instruction "
472 "decoding\n"
473 "Please report this to qemu-devel@nongnu.org\n");
474 break;
475 }
476 }
477 }
478
479 static __thread GString plugin_disas_output;
480
481 static int plugin_printf(FILE *stream, const char *fmt, ...)
482 {
483 va_list va;
484 GString *s = &plugin_disas_output;
485 int initial_len = s->len;
486
487 va_start(va, fmt);
488 g_string_append_vprintf(s, fmt, va);
489 va_end(va);
490
491 return s->len - initial_len;
492 }
493
494 static void plugin_print_address(bfd_vma addr, struct disassemble_info *info)
495 {
496 /* does nothing */
497 }
498
499
500 #ifdef CONFIG_CAPSTONE
501 /* Disassemble a single instruction directly into plugin output */
502 static
503 bool cap_disas_plugin(disassemble_info *info, uint64_t pc, size_t size)
504 {
505 uint8_t cap_buf[1024];
506 csh handle;
507 cs_insn *insn;
508 size_t csize = 0;
509 int count;
510 GString *s = &plugin_disas_output;
511
512 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
513 return false;
514 }
515 insn = cap_insn;
516
517 size_t tsize = MIN(sizeof(cap_buf) - csize, size);
518 const uint8_t *cbuf = cap_buf;
519 target_read_memory(pc, cap_buf, tsize, info);
520
521 count = cs_disasm(handle, cbuf, size, 0, 1, &insn);
522
523 if (count) {
524 g_string_printf(s, "%s %s", insn->mnemonic, insn->op_str);
525 } else {
526 g_string_printf(s, "cs_disasm failed");
527 }
528
529 cs_close(&handle);
530 return true;
531 }
532 #endif
533
534 /*
535 * We should only be dissembling one instruction at a time here. If
536 * there is left over it usually indicates the front end has read more
537 * bytes than it needed.
538 */
539 char *plugin_disas(CPUState *cpu, uint64_t addr, size_t size)
540 {
541 CPUClass *cc = CPU_GET_CLASS(cpu);
542 int count;
543 CPUDebug s;
544 GString *ds = g_string_set_size(&plugin_disas_output, 0);
545
546 g_assert(ds == &plugin_disas_output);
547
548 INIT_DISASSEMBLE_INFO(s.info, NULL, plugin_printf);
549
550 s.cpu = cpu;
551 s.info.read_memory_func = target_read_memory;
552 s.info.buffer_vma = addr;
553 s.info.buffer_length = size;
554 s.info.print_address_func = plugin_print_address;
555 s.info.cap_arch = -1;
556 s.info.cap_mode = 0;
557 s.info.cap_insn_unit = 4;
558 s.info.cap_insn_split = 4;
559
560 #ifdef TARGET_WORDS_BIGENDIAN
561 s.info.endian = BFD_ENDIAN_BIG;
562 #else
563 s.info.endian = BFD_ENDIAN_LITTLE;
564 #endif
565
566 if (cc->disas_set_info) {
567 cc->disas_set_info(cpu, &s.info);
568 }
569
570 if (s.info.cap_arch >= 0 && cap_disas_plugin(&s.info, addr, size)) {
571 return g_strdup(ds->str);
572 }
573
574 if (s.info.print_insn == NULL) {
575 s.info.print_insn = print_insn_od_target;
576 }
577
578 count = s.info.print_insn(addr, &s.info);
579
580 /* The decoder probably read more than it needed it's not critical */
581 if (count < size) {
582 warn_report("%s: %zu bytes left over", __func__, size - count);
583 }
584
585 return g_strdup(ds->str);
586 }
587
588 /* Disassemble this for me please... (debugging). */
589 void disas(FILE *out, void *code, unsigned long size)
590 {
591 uintptr_t pc;
592 int count;
593 CPUDebug s;
594 int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL;
595
596 INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
597 s.info.print_address_func = generic_print_host_address;
598
599 s.info.buffer = code;
600 s.info.buffer_vma = (uintptr_t)code;
601 s.info.buffer_length = size;
602 s.info.cap_arch = -1;
603 s.info.cap_mode = 0;
604 s.info.cap_insn_unit = 4;
605 s.info.cap_insn_split = 4;
606
607 #ifdef HOST_WORDS_BIGENDIAN
608 s.info.endian = BFD_ENDIAN_BIG;
609 #else
610 s.info.endian = BFD_ENDIAN_LITTLE;
611 #endif
612 #if defined(CONFIG_TCG_INTERPRETER)
613 print_insn = print_insn_tci;
614 #elif defined(__i386__)
615 s.info.mach = bfd_mach_i386_i386;
616 print_insn = print_insn_i386;
617 s.info.cap_arch = CS_ARCH_X86;
618 s.info.cap_mode = CS_MODE_32;
619 s.info.cap_insn_unit = 1;
620 s.info.cap_insn_split = 8;
621 #elif defined(__x86_64__)
622 s.info.mach = bfd_mach_x86_64;
623 print_insn = print_insn_i386;
624 s.info.cap_arch = CS_ARCH_X86;
625 s.info.cap_mode = CS_MODE_64;
626 s.info.cap_insn_unit = 1;
627 s.info.cap_insn_split = 8;
628 #elif defined(_ARCH_PPC)
629 s.info.disassembler_options = (char *)"any";
630 print_insn = print_insn_ppc;
631 s.info.cap_arch = CS_ARCH_PPC;
632 # ifdef _ARCH_PPC64
633 s.info.cap_mode = CS_MODE_64;
634 # endif
635 #elif defined(__riscv) && defined(CONFIG_RISCV_DIS)
636 #if defined(_ILP32) || (__riscv_xlen == 32)
637 print_insn = print_insn_riscv32;
638 #elif defined(_LP64)
639 print_insn = print_insn_riscv64;
640 #else
641 #error unsupported RISC-V ABI
642 #endif
643 #elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
644 print_insn = print_insn_arm_a64;
645 s.info.cap_arch = CS_ARCH_ARM64;
646 #elif defined(__alpha__)
647 print_insn = print_insn_alpha;
648 #elif defined(__sparc__)
649 print_insn = print_insn_sparc;
650 s.info.mach = bfd_mach_sparc_v9b;
651 #elif defined(__arm__)
652 print_insn = print_insn_arm;
653 s.info.cap_arch = CS_ARCH_ARM;
654 /* TCG only generates code for arm mode. */
655 #elif defined(__MIPSEB__)
656 print_insn = print_insn_big_mips;
657 #elif defined(__MIPSEL__)
658 print_insn = print_insn_little_mips;
659 #elif defined(__m68k__)
660 print_insn = print_insn_m68k;
661 #elif defined(__s390__)
662 print_insn = print_insn_s390;
663 #elif defined(__hppa__)
664 print_insn = print_insn_hppa;
665 #endif
666
667 if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) {
668 return;
669 }
670
671 if (print_insn == NULL) {
672 print_insn = print_insn_od_host;
673 }
674 for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
675 fprintf(out, "0x%08" PRIxPTR ": ", pc);
676 count = print_insn(pc, &s.info);
677 fprintf(out, "\n");
678 if (count < 0)
679 break;
680 }
681 }
682
683 /* Look up symbol for debugging purpose. Returns "" if unknown. */
684 const char *lookup_symbol(target_ulong orig_addr)
685 {
686 const char *symbol = "";
687 struct syminfo *s;
688
689 for (s = syminfos; s; s = s->next) {
690 symbol = s->lookup_symbol(s, orig_addr);
691 if (symbol[0] != '\0') {
692 break;
693 }
694 }
695
696 return symbol;
697 }
698
699 #if !defined(CONFIG_USER_ONLY)
700
701 #include "monitor/monitor.h"
702
703 static int
704 physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
705 struct disassemble_info *info)
706 {
707 CPUDebug *s = container_of(info, CPUDebug, info);
708
709 address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED,
710 myaddr, length);
711 return 0;
712 }
713
714 /* Disassembler for the monitor. */
715 void monitor_disas(Monitor *mon, CPUState *cpu,
716 target_ulong pc, int nb_insn, int is_physical)
717 {
718 CPUClass *cc = CPU_GET_CLASS(cpu);
719 int count, i;
720 CPUDebug s;
721
722 INIT_DISASSEMBLE_INFO(s.info, NULL, qemu_fprintf);
723
724 s.cpu = cpu;
725 s.info.read_memory_func
726 = (is_physical ? physical_read_memory : target_read_memory);
727 s.info.print_address_func = generic_print_address;
728 s.info.buffer_vma = pc;
729 s.info.cap_arch = -1;
730 s.info.cap_mode = 0;
731 s.info.cap_insn_unit = 4;
732 s.info.cap_insn_split = 4;
733
734 #ifdef TARGET_WORDS_BIGENDIAN
735 s.info.endian = BFD_ENDIAN_BIG;
736 #else
737 s.info.endian = BFD_ENDIAN_LITTLE;
738 #endif
739
740 if (cc->disas_set_info) {
741 cc->disas_set_info(cpu, &s.info);
742 }
743
744 if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) {
745 return;
746 }
747
748 if (!s.info.print_insn) {
749 monitor_printf(mon, "0x" TARGET_FMT_lx
750 ": Asm output not supported on this arch\n", pc);
751 return;
752 }
753
754 for(i = 0; i < nb_insn; i++) {
755 monitor_printf(mon, "0x" TARGET_FMT_lx ": ", pc);
756 count = s.info.print_insn(pc, &s.info);
757 monitor_printf(mon, "\n");
758 if (count < 0)
759 break;
760 pc += count;
761 }
762 }
763 #endif