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