disas: Clean up CPUDebug initialization
[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 /*
20 * Get LENGTH bytes from info's buffer, at host address memaddr.
21 * Transfer them to myaddr.
22 */
23 static int host_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
24 struct disassemble_info *info)
25 {
26 if (memaddr < info->buffer_vma
27 || memaddr + length > info->buffer_vma + info->buffer_length) {
28 /* Out of bounds. Use EIO because GDB uses it. */
29 return EIO;
30 }
31 memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length);
32 return 0;
33 }
34
35 /*
36 * Get LENGTH bytes from info's buffer, at target address memaddr.
37 * Transfer them to myaddr.
38 */
39 static int target_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
40 struct disassemble_info *info)
41 {
42 CPUDebug *s = container_of(info, CPUDebug, info);
43 int r = cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
44 return r ? EIO : 0;
45 }
46
47 /*
48 * Print an error message. We can assume that this is in response to
49 * an error return from {host,target}_read_memory.
50 */
51 static void perror_memory(int status, bfd_vma memaddr,
52 struct disassemble_info *info)
53 {
54 if (status != EIO) {
55 /* Can't happen. */
56 info->fprintf_func(info->stream, "Unknown error %d\n", status);
57 } else {
58 /* Address between memaddr and memaddr + len was out of bounds. */
59 info->fprintf_func(info->stream,
60 "Address 0x%" PRIx64 " is out of bounds.\n",
61 memaddr);
62 }
63 }
64
65 /* Print address in hex. */
66 static void print_address(bfd_vma addr, struct disassemble_info *info)
67 {
68 info->fprintf_func(info->stream, "0x%" PRIx64, addr);
69 }
70
71 /* Print address in hex, truncated to the width of a host virtual address. */
72 static void host_print_address(bfd_vma addr, struct disassemble_info *info)
73 {
74 print_address((uintptr_t)addr, info);
75 }
76
77 /* Stub prevents some fruitless earching in optabs disassemblers. */
78 static int symbol_at_address(bfd_vma addr, struct disassemble_info *info)
79 {
80 return 1;
81 }
82
83 bfd_vma bfd_getl64 (const bfd_byte *addr)
84 {
85 unsigned long long v;
86
87 v = (unsigned long long) addr[0];
88 v |= (unsigned long long) addr[1] << 8;
89 v |= (unsigned long long) addr[2] << 16;
90 v |= (unsigned long long) addr[3] << 24;
91 v |= (unsigned long long) addr[4] << 32;
92 v |= (unsigned long long) addr[5] << 40;
93 v |= (unsigned long long) addr[6] << 48;
94 v |= (unsigned long long) addr[7] << 56;
95 return (bfd_vma) v;
96 }
97
98 bfd_vma bfd_getl32 (const bfd_byte *addr)
99 {
100 unsigned long v;
101
102 v = (unsigned long) addr[0];
103 v |= (unsigned long) addr[1] << 8;
104 v |= (unsigned long) addr[2] << 16;
105 v |= (unsigned long) addr[3] << 24;
106 return (bfd_vma) v;
107 }
108
109 bfd_vma bfd_getb32 (const bfd_byte *addr)
110 {
111 unsigned long v;
112
113 v = (unsigned long) addr[0] << 24;
114 v |= (unsigned long) addr[1] << 16;
115 v |= (unsigned long) addr[2] << 8;
116 v |= (unsigned long) addr[3];
117 return (bfd_vma) v;
118 }
119
120 bfd_vma bfd_getl16 (const bfd_byte *addr)
121 {
122 unsigned long v;
123
124 v = (unsigned long) addr[0];
125 v |= (unsigned long) addr[1] << 8;
126 return (bfd_vma) v;
127 }
128
129 bfd_vma bfd_getb16 (const bfd_byte *addr)
130 {
131 unsigned long v;
132
133 v = (unsigned long) addr[0] << 24;
134 v |= (unsigned long) addr[1] << 16;
135 return (bfd_vma) v;
136 }
137
138 static int print_insn_objdump(bfd_vma pc, disassemble_info *info,
139 const char *prefix)
140 {
141 int i, n = info->buffer_length;
142 uint8_t *buf = g_malloc(n);
143
144 info->read_memory_func(pc, buf, n, info);
145
146 for (i = 0; i < n; ++i) {
147 if (i % 32 == 0) {
148 info->fprintf_func(info->stream, "\n%s: ", prefix);
149 }
150 info->fprintf_func(info->stream, "%02x", buf[i]);
151 }
152
153 g_free(buf);
154 return n;
155 }
156
157 static int print_insn_od_host(bfd_vma pc, disassemble_info *info)
158 {
159 return print_insn_objdump(pc, info, "OBJD-H");
160 }
161
162 static int print_insn_od_target(bfd_vma pc, disassemble_info *info)
163 {
164 return print_insn_objdump(pc, info, "OBJD-T");
165 }
166
167 #ifdef CONFIG_CAPSTONE
168 /* Temporary storage for the capstone library. This will be alloced via
169 malloc with a size private to the library; thus there's no reason not
170 to share this across calls and across host vs target disassembly. */
171 static __thread cs_insn *cap_insn;
172
173 /* Initialize the Capstone library. */
174 /* ??? It would be nice to cache this. We would need one handle for the
175 host and one for the target. For most targets we can reset specific
176 parameters via cs_option(CS_OPT_MODE, new_mode), but we cannot change
177 CS_ARCH_* in this way. Thus we would need to be able to close and
178 re-open the target handle with a different arch for the target in order
179 to handle AArch64 vs AArch32 mode switching. */
180 static cs_err cap_disas_start(disassemble_info *info, csh *handle)
181 {
182 cs_mode cap_mode = info->cap_mode;
183 cs_err err;
184
185 cap_mode += (info->endian == BFD_ENDIAN_BIG ? CS_MODE_BIG_ENDIAN
186 : CS_MODE_LITTLE_ENDIAN);
187
188 err = cs_open(info->cap_arch, cap_mode, handle);
189 if (err != CS_ERR_OK) {
190 return err;
191 }
192
193 /* ??? There probably ought to be a better place to put this. */
194 if (info->cap_arch == CS_ARCH_X86) {
195 /* We don't care about errors (if for some reason the library
196 is compiled without AT&T syntax); the user will just have
197 to deal with the Intel syntax. */
198 cs_option(*handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
199 }
200
201 /* "Disassemble" unknown insns as ".byte W,X,Y,Z". */
202 cs_option(*handle, CS_OPT_SKIPDATA, CS_OPT_ON);
203
204 /* Allocate temp space for cs_disasm_iter. */
205 if (cap_insn == NULL) {
206 cap_insn = cs_malloc(*handle);
207 if (cap_insn == NULL) {
208 cs_close(handle);
209 return CS_ERR_MEM;
210 }
211 }
212 return CS_ERR_OK;
213 }
214
215 static void cap_dump_insn_units(disassemble_info *info, cs_insn *insn,
216 int i, int n)
217 {
218 fprintf_function print = info->fprintf_func;
219 FILE *stream = info->stream;
220
221 switch (info->cap_insn_unit) {
222 case 4:
223 if (info->endian == BFD_ENDIAN_BIG) {
224 for (; i < n; i += 4) {
225 print(stream, " %08x", ldl_be_p(insn->bytes + i));
226
227 }
228 } else {
229 for (; i < n; i += 4) {
230 print(stream, " %08x", ldl_le_p(insn->bytes + i));
231 }
232 }
233 break;
234
235 case 2:
236 if (info->endian == BFD_ENDIAN_BIG) {
237 for (; i < n; i += 2) {
238 print(stream, " %04x", lduw_be_p(insn->bytes + i));
239 }
240 } else {
241 for (; i < n; i += 2) {
242 print(stream, " %04x", lduw_le_p(insn->bytes + i));
243 }
244 }
245 break;
246
247 default:
248 for (; i < n; i++) {
249 print(stream, " %02x", insn->bytes[i]);
250 }
251 break;
252 }
253 }
254
255 static void cap_dump_insn(disassemble_info *info, cs_insn *insn)
256 {
257 fprintf_function print = info->fprintf_func;
258 int i, n, split;
259
260 print(info->stream, "0x%08" PRIx64 ": ", insn->address);
261
262 n = insn->size;
263 split = info->cap_insn_split;
264
265 /* Dump the first SPLIT bytes of the instruction. */
266 cap_dump_insn_units(info, insn, 0, MIN(n, split));
267
268 /* Add padding up to SPLIT so that mnemonics line up. */
269 if (n < split) {
270 int width = (split - n) / info->cap_insn_unit;
271 width *= (2 * info->cap_insn_unit + 1);
272 print(info->stream, "%*s", width, "");
273 }
274
275 /* Print the actual instruction. */
276 print(info->stream, " %-8s %s\n", insn->mnemonic, insn->op_str);
277
278 /* Dump any remaining part of the insn on subsequent lines. */
279 for (i = split; i < n; i += split) {
280 print(info->stream, "0x%08" PRIx64 ": ", insn->address + i);
281 cap_dump_insn_units(info, insn, i, MIN(n, i + split));
282 print(info->stream, "\n");
283 }
284 }
285
286 /* Disassemble SIZE bytes at PC for the target. */
287 static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size)
288 {
289 uint8_t cap_buf[1024];
290 csh handle;
291 cs_insn *insn;
292 size_t csize = 0;
293
294 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
295 return false;
296 }
297 insn = cap_insn;
298
299 while (1) {
300 size_t tsize = MIN(sizeof(cap_buf) - csize, size);
301 const uint8_t *cbuf = cap_buf;
302
303 target_read_memory(pc + csize, cap_buf + csize, tsize, info);
304 csize += tsize;
305 size -= tsize;
306
307 while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
308 cap_dump_insn(info, insn);
309 }
310
311 /* If the target memory is not consumed, go back for more... */
312 if (size != 0) {
313 /* ... taking care to move any remaining fractional insn
314 to the beginning of the buffer. */
315 if (csize != 0) {
316 memmove(cap_buf, cbuf, csize);
317 }
318 continue;
319 }
320
321 /* Since the target memory is consumed, we should not have
322 a remaining fractional insn. */
323 if (csize != 0) {
324 (*info->fprintf_func)(info->stream,
325 "Disassembler disagrees with translator "
326 "over instruction decoding\n"
327 "Please report this to qemu-devel@nongnu.org\n");
328 }
329 break;
330 }
331
332 cs_close(&handle);
333 return true;
334 }
335
336 /* Disassemble SIZE bytes at CODE for the host. */
337 static bool cap_disas_host(disassemble_info *info, void *code, size_t size)
338 {
339 csh handle;
340 const uint8_t *cbuf;
341 cs_insn *insn;
342 uint64_t pc;
343
344 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
345 return false;
346 }
347 insn = cap_insn;
348
349 cbuf = code;
350 pc = (uintptr_t)code;
351
352 while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) {
353 cap_dump_insn(info, insn);
354 }
355 if (size != 0) {
356 (*info->fprintf_func)(info->stream,
357 "Disassembler disagrees with TCG over instruction encoding\n"
358 "Please report this to qemu-devel@nongnu.org\n");
359 }
360
361 cs_close(&handle);
362 return true;
363 }
364
365 #if !defined(CONFIG_USER_ONLY)
366 /* Disassemble COUNT insns at PC for the target. */
367 static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count)
368 {
369 uint8_t cap_buf[32];
370 csh handle;
371 cs_insn *insn;
372 size_t csize = 0;
373
374 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
375 return false;
376 }
377 insn = cap_insn;
378
379 while (1) {
380 /* We want to read memory for one insn, but generically we do not
381 know how much memory that is. We have a small buffer which is
382 known to be sufficient for all supported targets. Try to not
383 read beyond the page, Just In Case. For even more simplicity,
384 ignore the actual target page size and use a 1k boundary. If
385 that turns out to be insufficient, we'll come back around the
386 loop and read more. */
387 uint64_t epc = QEMU_ALIGN_UP(pc + csize + 1, 1024);
388 size_t tsize = MIN(sizeof(cap_buf) - csize, epc - pc);
389 const uint8_t *cbuf = cap_buf;
390
391 /* Make certain that we can make progress. */
392 assert(tsize != 0);
393 info->read_memory_func(pc, cap_buf + csize, tsize, info);
394 csize += tsize;
395
396 if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
397 cap_dump_insn(info, insn);
398 if (--count <= 0) {
399 break;
400 }
401 }
402 memmove(cap_buf, cbuf, csize);
403 }
404
405 cs_close(&handle);
406 return true;
407 }
408 #endif /* !CONFIG_USER_ONLY */
409 #else
410 # define cap_disas_target(i, p, s) false
411 # define cap_disas_host(i, p, s) false
412 # define cap_disas_monitor(i, p, c) false
413 # define cap_disas_plugin(i, p, c) false
414 #endif /* CONFIG_CAPSTONE */
415
416 static void initialize_debug(CPUDebug *s)
417 {
418 memset(s, 0, sizeof(*s));
419 s->info.arch = bfd_arch_unknown;
420 s->info.cap_arch = -1;
421 s->info.cap_insn_unit = 4;
422 s->info.cap_insn_split = 4;
423 s->info.memory_error_func = perror_memory;
424 s->info.symbol_at_address_func = symbol_at_address;
425 }
426
427 static void initialize_debug_target(CPUDebug *s, CPUState *cpu)
428 {
429 initialize_debug(s);
430
431 s->cpu = cpu;
432 s->info.read_memory_func = target_read_memory;
433 s->info.print_address_func = print_address;
434 #ifdef TARGET_WORDS_BIGENDIAN
435 s->info.endian = BFD_ENDIAN_BIG;
436 #else
437 s->info.endian = BFD_ENDIAN_LITTLE;
438 #endif
439
440 CPUClass *cc = CPU_GET_CLASS(cpu);
441 if (cc->disas_set_info) {
442 cc->disas_set_info(cpu, &s->info);
443 }
444 }
445
446 static void initialize_debug_host(CPUDebug *s)
447 {
448 initialize_debug(s);
449
450 s->info.read_memory_func = host_read_memory;
451 s->info.print_address_func = host_print_address;
452 #ifdef HOST_WORDS_BIGENDIAN
453 s->info.endian = BFD_ENDIAN_BIG;
454 #else
455 s->info.endian = BFD_ENDIAN_LITTLE;
456 #endif
457 #if defined(CONFIG_TCG_INTERPRETER)
458 s->info.print_insn = print_insn_tci;
459 #elif defined(__i386__)
460 s->info.mach = bfd_mach_i386_i386;
461 s->info.print_insn = print_insn_i386;
462 s->info.cap_arch = CS_ARCH_X86;
463 s->info.cap_mode = CS_MODE_32;
464 s->info.cap_insn_unit = 1;
465 s->info.cap_insn_split = 8;
466 #elif defined(__x86_64__)
467 s->info.mach = bfd_mach_x86_64;
468 s->info.print_insn = print_insn_i386;
469 s->info.cap_arch = CS_ARCH_X86;
470 s->info.cap_mode = CS_MODE_64;
471 s->info.cap_insn_unit = 1;
472 s->info.cap_insn_split = 8;
473 #elif defined(_ARCH_PPC)
474 s->info.disassembler_options = (char *)"any";
475 s->info.print_insn = print_insn_ppc;
476 s->info.cap_arch = CS_ARCH_PPC;
477 # ifdef _ARCH_PPC64
478 s->info.cap_mode = CS_MODE_64;
479 # endif
480 #elif defined(__riscv) && defined(CONFIG_RISCV_DIS)
481 #if defined(_ILP32) || (__riscv_xlen == 32)
482 s->info.print_insn = print_insn_riscv32;
483 #elif defined(_LP64)
484 s->info.print_insn = print_insn_riscv64;
485 #else
486 #error unsupported RISC-V ABI
487 #endif
488 #elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
489 s->info.print_insn = print_insn_arm_a64;
490 s->info.cap_arch = CS_ARCH_ARM64;
491 #elif defined(__alpha__)
492 s->info.print_insn = print_insn_alpha;
493 #elif defined(__sparc__)
494 s->info.print_insn = print_insn_sparc;
495 s->info.mach = bfd_mach_sparc_v9b;
496 #elif defined(__arm__)
497 /* TCG only generates code for arm mode. */
498 s->info.print_insn = print_insn_arm;
499 s->info.cap_arch = CS_ARCH_ARM;
500 #elif defined(__MIPSEB__)
501 s->info.print_insn = print_insn_big_mips;
502 #elif defined(__MIPSEL__)
503 s->info.print_insn = print_insn_little_mips;
504 #elif defined(__m68k__)
505 s->info.print_insn = print_insn_m68k;
506 #elif defined(__s390__)
507 s->info.print_insn = print_insn_s390;
508 #elif defined(__hppa__)
509 s->info.print_insn = print_insn_hppa;
510 #endif
511 }
512
513 /* Disassemble this for me please... (debugging). */
514 void target_disas(FILE *out, CPUState *cpu, target_ulong code,
515 target_ulong size)
516 {
517 target_ulong pc;
518 int count;
519 CPUDebug s;
520
521 initialize_debug_target(&s, cpu);
522 s.info.fprintf_func = fprintf;
523 s.info.stream = out;
524 s.info.buffer_vma = code;
525 s.info.buffer_length = size;
526
527 if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) {
528 return;
529 }
530
531 if (s.info.print_insn == NULL) {
532 s.info.print_insn = print_insn_od_target;
533 }
534
535 for (pc = code; size > 0; pc += count, size -= count) {
536 fprintf(out, "0x" TARGET_FMT_lx ": ", pc);
537 count = s.info.print_insn(pc, &s.info);
538 fprintf(out, "\n");
539 if (count < 0)
540 break;
541 if (size < count) {
542 fprintf(out,
543 "Disassembler disagrees with translator over instruction "
544 "decoding\n"
545 "Please report this to qemu-devel@nongnu.org\n");
546 break;
547 }
548 }
549 }
550
551 static __thread GString plugin_disas_output;
552
553 static int plugin_printf(FILE *stream, const char *fmt, ...)
554 {
555 va_list va;
556 GString *s = &plugin_disas_output;
557 int initial_len = s->len;
558
559 va_start(va, fmt);
560 g_string_append_vprintf(s, fmt, va);
561 va_end(va);
562
563 return s->len - initial_len;
564 }
565
566 static void plugin_print_address(bfd_vma addr, struct disassemble_info *info)
567 {
568 /* does nothing */
569 }
570
571
572 #ifdef CONFIG_CAPSTONE
573 /* Disassemble a single instruction directly into plugin output */
574 static
575 bool cap_disas_plugin(disassemble_info *info, uint64_t pc, size_t size)
576 {
577 uint8_t cap_buf[1024];
578 csh handle;
579 cs_insn *insn;
580 size_t csize = 0;
581 int count;
582 GString *s = &plugin_disas_output;
583
584 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
585 return false;
586 }
587 insn = cap_insn;
588
589 size_t tsize = MIN(sizeof(cap_buf) - csize, size);
590 const uint8_t *cbuf = cap_buf;
591 target_read_memory(pc, cap_buf, tsize, info);
592
593 count = cs_disasm(handle, cbuf, size, 0, 1, &insn);
594
595 if (count) {
596 g_string_printf(s, "%s %s", insn->mnemonic, insn->op_str);
597 } else {
598 g_string_printf(s, "cs_disasm failed");
599 }
600
601 cs_close(&handle);
602 return true;
603 }
604 #endif
605
606 /*
607 * We should only be dissembling one instruction at a time here. If
608 * there is left over it usually indicates the front end has read more
609 * bytes than it needed.
610 */
611 char *plugin_disas(CPUState *cpu, uint64_t addr, size_t size)
612 {
613 int count;
614 CPUDebug s;
615 GString *ds = g_string_set_size(&plugin_disas_output, 0);
616
617 g_assert(ds == &plugin_disas_output);
618
619 initialize_debug_target(&s, cpu);
620 s.info.fprintf_func = plugin_printf;
621 s.info.buffer_vma = addr;
622 s.info.buffer_length = size;
623 s.info.print_address_func = plugin_print_address;
624
625 if (s.info.cap_arch >= 0 && cap_disas_plugin(&s.info, addr, size)) {
626 return g_strdup(ds->str);
627 }
628
629 if (s.info.print_insn == NULL) {
630 s.info.print_insn = print_insn_od_target;
631 }
632
633 count = s.info.print_insn(addr, &s.info);
634
635 /* The decoder probably read more than it needed it's not critical */
636 if (count < size) {
637 warn_report("%s: %zu bytes left over", __func__, size - count);
638 }
639
640 return g_strdup(ds->str);
641 }
642
643 /* Disassemble this for me please... (debugging). */
644 void disas(FILE *out, void *code, unsigned long size)
645 {
646 uintptr_t pc;
647 int count;
648 CPUDebug s;
649
650 initialize_debug_host(&s);
651 s.info.fprintf_func = fprintf;
652 s.info.stream = out;
653 s.info.buffer = code;
654 s.info.buffer_vma = (uintptr_t)code;
655 s.info.buffer_length = size;
656
657 if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) {
658 return;
659 }
660
661 if (s.info.print_insn == NULL) {
662 s.info.print_insn = print_insn_od_host;
663 }
664 for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
665 fprintf(out, "0x%08" PRIxPTR ": ", pc);
666 count = s.info.print_insn(pc, &s.info);
667 fprintf(out, "\n");
668 if (count < 0) {
669 break;
670 }
671 }
672
673 }
674
675 /* Look up symbol for debugging purpose. Returns "" if unknown. */
676 const char *lookup_symbol(target_ulong orig_addr)
677 {
678 const char *symbol = "";
679 struct syminfo *s;
680
681 for (s = syminfos; s; s = s->next) {
682 symbol = s->lookup_symbol(s, orig_addr);
683 if (symbol[0] != '\0') {
684 break;
685 }
686 }
687
688 return symbol;
689 }
690
691 #if !defined(CONFIG_USER_ONLY)
692
693 #include "monitor/monitor.h"
694
695 static int
696 physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
697 struct disassemble_info *info)
698 {
699 CPUDebug *s = container_of(info, CPUDebug, info);
700 MemTxResult res;
701
702 res = address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED,
703 myaddr, length);
704 return res == MEMTX_OK ? 0 : EIO;
705 }
706
707 /* Disassembler for the monitor. */
708 void monitor_disas(Monitor *mon, CPUState *cpu,
709 target_ulong pc, int nb_insn, int is_physical)
710 {
711 int count, i;
712 CPUDebug s;
713
714 initialize_debug_target(&s, cpu);
715 s.info.fprintf_func = qemu_fprintf;
716 if (is_physical) {
717 s.info.read_memory_func = physical_read_memory;
718 }
719 s.info.buffer_vma = pc;
720
721 if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) {
722 return;
723 }
724
725 if (!s.info.print_insn) {
726 monitor_printf(mon, "0x" TARGET_FMT_lx
727 ": Asm output not supported on this arch\n", pc);
728 return;
729 }
730
731 for(i = 0; i < nb_insn; i++) {
732 monitor_printf(mon, "0x" TARGET_FMT_lx ": ", pc);
733 count = s.info.print_insn(pc, &s.info);
734 monitor_printf(mon, "\n");
735 if (count < 0)
736 break;
737 pc += count;
738 }
739 }
740 #endif