]> git.ipfire.org Git - thirdparty/qemu.git/blame - disas.c
tcg: Implement gvec support for rotate by scalar
[thirdparty/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
16b22e02
AB
263static void cap_dump_insn(disassemble_info *info, cs_insn *insn,
264 const char *note)
15fa1a0a
RH
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. */
16b22e02
AB
285 print(info->stream, " %-8s %s", insn->mnemonic, insn->op_str);
286 if (note) {
287 print(info->stream, "\t\t%s", note);
288 }
289 print(info->stream, "\n");
15fa1a0a
RH
290
291 /* Dump any remaining part of the insn on subsequent lines. */
292 for (i = split; i < n; i += split) {
293 print(info->stream, "0x%08" PRIx64 ": ", insn->address + i);
294 cap_dump_insn_units(info, insn, i, MIN(n, i + split));
295 print(info->stream, "\n");
296 }
297}
298
8ca80760
RH
299/* Disassemble SIZE bytes at PC for the target. */
300static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size)
301{
302 uint8_t cap_buf[1024];
303 csh handle;
304 cs_insn *insn;
305 size_t csize = 0;
306
307 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
308 return false;
309 }
310 insn = cap_insn;
311
312 while (1) {
313 size_t tsize = MIN(sizeof(cap_buf) - csize, size);
314 const uint8_t *cbuf = cap_buf;
315
316 target_read_memory(pc + csize, cap_buf + csize, tsize, info);
317 csize += tsize;
318 size -= tsize;
319
320 while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
16b22e02 321 cap_dump_insn(info, insn, NULL);
8ca80760
RH
322 }
323
324 /* If the target memory is not consumed, go back for more... */
325 if (size != 0) {
326 /* ... taking care to move any remaining fractional insn
327 to the beginning of the buffer. */
328 if (csize != 0) {
329 memmove(cap_buf, cbuf, csize);
330 }
331 continue;
332 }
333
334 /* Since the target memory is consumed, we should not have
335 a remaining fractional insn. */
336 if (csize != 0) {
337 (*info->fprintf_func)(info->stream,
338 "Disassembler disagrees with translator "
339 "over instruction decoding\n"
340 "Please report this to qemu-devel@nongnu.org\n");
341 }
342 break;
343 }
344
345 cs_close(&handle);
346 return true;
347}
348
349/* Disassemble SIZE bytes at CODE for the host. */
16b22e02
AB
350static bool cap_disas_host(disassemble_info *info, void *code, size_t size,
351 const char *note)
8ca80760
RH
352{
353 csh handle;
354 const uint8_t *cbuf;
355 cs_insn *insn;
356 uint64_t pc;
357
358 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
359 return false;
360 }
361 insn = cap_insn;
362
363 cbuf = code;
364 pc = (uintptr_t)code;
365
366 while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) {
16b22e02
AB
367 cap_dump_insn(info, insn, note);
368 note = NULL;
8ca80760
RH
369 }
370 if (size != 0) {
371 (*info->fprintf_func)(info->stream,
372 "Disassembler disagrees with TCG over instruction encoding\n"
373 "Please report this to qemu-devel@nongnu.org\n");
374 }
375
376 cs_close(&handle);
377 return true;
378}
379
380#if !defined(CONFIG_USER_ONLY)
381/* Disassemble COUNT insns at PC for the target. */
382static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count)
383{
384 uint8_t cap_buf[32];
385 csh handle;
386 cs_insn *insn;
387 size_t csize = 0;
388
389 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
390 return false;
391 }
392 insn = cap_insn;
393
394 while (1) {
395 /* We want to read memory for one insn, but generically we do not
396 know how much memory that is. We have a small buffer which is
397 known to be sufficient for all supported targets. Try to not
398 read beyond the page, Just In Case. For even more simplicity,
399 ignore the actual target page size and use a 1k boundary. If
400 that turns out to be insufficient, we'll come back around the
401 loop and read more. */
402 uint64_t epc = QEMU_ALIGN_UP(pc + csize + 1, 1024);
403 size_t tsize = MIN(sizeof(cap_buf) - csize, epc - pc);
404 const uint8_t *cbuf = cap_buf;
405
406 /* Make certain that we can make progress. */
407 assert(tsize != 0);
408 info->read_memory_func(pc, cap_buf + csize, tsize, info);
409 csize += tsize;
410
411 if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
16b22e02 412 cap_dump_insn(info, insn, NULL);
8ca80760
RH
413 if (--count <= 0) {
414 break;
415 }
416 }
417 memmove(cap_buf, cbuf, csize);
418 }
419
420 cs_close(&handle);
421 return true;
422}
423#endif /* !CONFIG_USER_ONLY */
424#else
425# define cap_disas_target(i, p, s) false
16b22e02 426# define cap_disas_host(i, p, s, n) false
8ca80760 427# define cap_disas_monitor(i, p, c) false
cbafa236 428# define cap_disas_plugin(i, p, c) false
8ca80760
RH
429#endif /* CONFIG_CAPSTONE */
430
1d48474d 431/* Disassemble this for me please... (debugging). */
d49190c4 432void target_disas(FILE *out, CPUState *cpu, target_ulong code,
1d48474d 433 target_ulong size)
b9adb4a6 434{
37b9de46 435 CPUClass *cc = CPU_GET_CLASS(cpu);
c27004ec 436 target_ulong pc;
b9adb4a6 437 int count;
f4359b9f 438 CPUDebug s;
b9adb4a6 439
f4359b9f 440 INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
b9adb4a6 441
d49190c4 442 s.cpu = cpu;
f4359b9f
BS
443 s.info.read_memory_func = target_read_memory;
444 s.info.buffer_vma = code;
445 s.info.buffer_length = size;
9504c544 446 s.info.print_address_func = generic_print_address;
8ca80760
RH
447 s.info.cap_arch = -1;
448 s.info.cap_mode = 0;
15fa1a0a
RH
449 s.info.cap_insn_unit = 4;
450 s.info.cap_insn_split = 4;
c27004ec
FB
451
452#ifdef TARGET_WORDS_BIGENDIAN
f4359b9f 453 s.info.endian = BFD_ENDIAN_BIG;
c27004ec 454#else
f4359b9f 455 s.info.endian = BFD_ENDIAN_LITTLE;
c27004ec 456#endif
37b9de46
PC
457
458 if (cc->disas_set_info) {
459 cc->disas_set_info(cpu, &s.info);
460 }
461
8ca80760
RH
462 if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) {
463 return;
464 }
465
2de295c5
PC
466 if (s.info.print_insn == NULL) {
467 s.info.print_insn = print_insn_od_target;
c46ffd57 468 }
c6105c0a 469
7e000c2e 470 for (pc = code; size > 0; pc += count, size -= count) {
fa15e030 471 fprintf(out, "0x" TARGET_FMT_lx ": ", pc);
2de295c5 472 count = s.info.print_insn(pc, &s.info);
c27004ec
FB
473 fprintf(out, "\n");
474 if (count < 0)
475 break;
754d00ae 476 if (size < count) {
477 fprintf(out,
478 "Disassembler disagrees with translator over instruction "
479 "decoding\n"
480 "Please report this to qemu-devel@nongnu.org\n");
481 break;
482 }
c27004ec
FB
483 }
484}
485
cbafa236
AB
486static __thread GString plugin_disas_output;
487
488static int plugin_printf(FILE *stream, const char *fmt, ...)
489{
490 va_list va;
491 GString *s = &plugin_disas_output;
492 int initial_len = s->len;
493
494 va_start(va, fmt);
495 g_string_append_vprintf(s, fmt, va);
496 va_end(va);
497
498 return s->len - initial_len;
499}
500
501static void plugin_print_address(bfd_vma addr, struct disassemble_info *info)
502{
503 /* does nothing */
504}
505
506
507#ifdef CONFIG_CAPSTONE
508/* Disassemble a single instruction directly into plugin output */
509static
510bool cap_disas_plugin(disassemble_info *info, uint64_t pc, size_t size)
511{
512 uint8_t cap_buf[1024];
513 csh handle;
514 cs_insn *insn;
515 size_t csize = 0;
516 int count;
517 GString *s = &plugin_disas_output;
518
519 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
520 return false;
521 }
522 insn = cap_insn;
523
524 size_t tsize = MIN(sizeof(cap_buf) - csize, size);
525 const uint8_t *cbuf = cap_buf;
526 target_read_memory(pc, cap_buf, tsize, info);
527
528 count = cs_disasm(handle, cbuf, size, 0, 1, &insn);
529
530 if (count) {
531 g_string_printf(s, "%s %s", insn->mnemonic, insn->op_str);
532 } else {
533 g_string_printf(s, "cs_disasm failed");
534 }
535
536 cs_close(&handle);
537 return true;
538}
539#endif
540
541/*
542 * We should only be dissembling one instruction at a time here. If
543 * there is left over it usually indicates the front end has read more
544 * bytes than it needed.
545 */
546char *plugin_disas(CPUState *cpu, uint64_t addr, size_t size)
547{
548 CPUClass *cc = CPU_GET_CLASS(cpu);
549 int count;
550 CPUDebug s;
551 GString *ds = g_string_set_size(&plugin_disas_output, 0);
552
553 g_assert(ds == &plugin_disas_output);
554
555 INIT_DISASSEMBLE_INFO(s.info, NULL, plugin_printf);
556
557 s.cpu = cpu;
558 s.info.read_memory_func = target_read_memory;
559 s.info.buffer_vma = addr;
560 s.info.buffer_length = size;
561 s.info.print_address_func = plugin_print_address;
562 s.info.cap_arch = -1;
563 s.info.cap_mode = 0;
564 s.info.cap_insn_unit = 4;
565 s.info.cap_insn_split = 4;
566
567#ifdef TARGET_WORDS_BIGENDIAN
568 s.info.endian = BFD_ENDIAN_BIG;
569#else
570 s.info.endian = BFD_ENDIAN_LITTLE;
571#endif
572
573 if (cc->disas_set_info) {
574 cc->disas_set_info(cpu, &s.info);
575 }
576
577 if (s.info.cap_arch >= 0 && cap_disas_plugin(&s.info, addr, size)) {
578 return g_strdup(ds->str);
579 }
580
581 if (s.info.print_insn == NULL) {
582 s.info.print_insn = print_insn_od_target;
583 }
584
585 count = s.info.print_insn(addr, &s.info);
586
587 /* The decoder probably read more than it needed it's not critical */
588 if (count < size) {
589 warn_report("%s: %zu bytes left over", __func__, size - count);
590 }
591
592 return g_strdup(ds->str);
593}
594
c27004ec 595/* Disassemble this for me please... (debugging). */
e5ef4ec2 596void disas(FILE *out, void *code, unsigned long size, const char *note)
c27004ec 597{
b0b0f1c9 598 uintptr_t pc;
c27004ec 599 int count;
f4359b9f 600 CPUDebug s;
c46ffd57 601 int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL;
c27004ec 602
f4359b9f
BS
603 INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
604 s.info.print_address_func = generic_print_host_address;
c27004ec 605
f4359b9f
BS
606 s.info.buffer = code;
607 s.info.buffer_vma = (uintptr_t)code;
608 s.info.buffer_length = size;
8ca80760
RH
609 s.info.cap_arch = -1;
610 s.info.cap_mode = 0;
15fa1a0a
RH
611 s.info.cap_insn_unit = 4;
612 s.info.cap_insn_split = 4;
b9adb4a6 613
e2542fe2 614#ifdef HOST_WORDS_BIGENDIAN
f4359b9f 615 s.info.endian = BFD_ENDIAN_BIG;
b9adb4a6 616#else
f4359b9f 617 s.info.endian = BFD_ENDIAN_LITTLE;
b9adb4a6 618#endif
5826e519
SW
619#if defined(CONFIG_TCG_INTERPRETER)
620 print_insn = print_insn_tci;
621#elif defined(__i386__)
f4359b9f 622 s.info.mach = bfd_mach_i386_i386;
c27004ec 623 print_insn = print_insn_i386;
b666d2a4
RH
624 s.info.cap_arch = CS_ARCH_X86;
625 s.info.cap_mode = CS_MODE_32;
15fa1a0a
RH
626 s.info.cap_insn_unit = 1;
627 s.info.cap_insn_split = 8;
bc51c5c9 628#elif defined(__x86_64__)
f4359b9f 629 s.info.mach = bfd_mach_x86_64;
c27004ec 630 print_insn = print_insn_i386;
b666d2a4
RH
631 s.info.cap_arch = CS_ARCH_X86;
632 s.info.cap_mode = CS_MODE_64;
15fa1a0a
RH
633 s.info.cap_insn_unit = 1;
634 s.info.cap_insn_split = 8;
e58ffeb3 635#elif defined(_ARCH_PPC)
66d4f6a3 636 s.info.disassembler_options = (char *)"any";
c27004ec 637 print_insn = print_insn_ppc;
ac226899
RH
638 s.info.cap_arch = CS_ARCH_PPC;
639# ifdef _ARCH_PPC64
640 s.info.cap_mode = CS_MODE_64;
641# endif
91468b27
AF
642#elif defined(__riscv) && defined(CONFIG_RISCV_DIS)
643#if defined(_ILP32) || (__riscv_xlen == 32)
644 print_insn = print_insn_riscv32;
645#elif defined(_LP64)
646 print_insn = print_insn_riscv64;
647#else
648#error unsupported RISC-V ABI
649#endif
999b53ec
CF
650#elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
651 print_insn = print_insn_arm_a64;
110f6c70 652 s.info.cap_arch = CS_ARCH_ARM64;
a993ba85 653#elif defined(__alpha__)
c27004ec 654 print_insn = print_insn_alpha;
aa0aa4fa 655#elif defined(__sparc__)
c27004ec 656 print_insn = print_insn_sparc;
f4359b9f 657 s.info.mach = bfd_mach_sparc_v9b;
5fafdf24 658#elif defined(__arm__)
c27004ec 659 print_insn = print_insn_arm;
110f6c70
RH
660 s.info.cap_arch = CS_ARCH_ARM;
661 /* TCG only generates code for arm mode. */
6af0bf9c
FB
662#elif defined(__MIPSEB__)
663 print_insn = print_insn_big_mips;
664#elif defined(__MIPSEL__)
665 print_insn = print_insn_little_mips;
48024e4a
FB
666#elif defined(__m68k__)
667 print_insn = print_insn_m68k;
8f860bb8
TS
668#elif defined(__s390__)
669 print_insn = print_insn_s390;
429b31a2
RH
670#elif defined(__hppa__)
671 print_insn = print_insn_hppa;
b9adb4a6 672#endif
8ca80760 673
16b22e02 674 if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size, note)) {
8ca80760
RH
675 return;
676 }
677
c46ffd57
RH
678 if (print_insn == NULL) {
679 print_insn = print_insn_od_host;
680 }
b0b0f1c9
SW
681 for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
682 fprintf(out, "0x%08" PRIxPTR ": ", pc);
f4359b9f 683 count = print_insn(pc, &s.info);
e5ef4ec2
AB
684 if (note) {
685 fprintf(out, "\t\t%s", note);
686 note = NULL;
687 }
688 fprintf(out, "\n");
689 if (count < 0) {
690 break;
691 }
b9adb4a6 692 }
e5ef4ec2 693
b9adb4a6
FB
694}
695
696/* Look up symbol for debugging purpose. Returns "" if unknown. */
c27004ec 697const char *lookup_symbol(target_ulong orig_addr)
b9adb4a6 698{
49918a75 699 const char *symbol = "";
e80cfcfc 700 struct syminfo *s;
3b46e624 701
e80cfcfc 702 for (s = syminfos; s; s = s->next) {
49918a75
PB
703 symbol = s->lookup_symbol(s, orig_addr);
704 if (symbol[0] != '\0') {
705 break;
706 }
b9adb4a6 707 }
49918a75
PB
708
709 return symbol;
b9adb4a6 710}
9307c4c1
FB
711
712#if !defined(CONFIG_USER_ONLY)
713
83c9089e 714#include "monitor/monitor.h"
3d2cfdf1 715
9307c4c1 716static int
b8d87208 717physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
a5f1b965 718 struct disassemble_info *info)
9307c4c1 719{
f2c6abc8
PM
720 CPUDebug *s = container_of(info, CPUDebug, info);
721
722 address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED,
723 myaddr, length);
9307c4c1
FB
724 return 0;
725}
726
1d48474d 727/* Disassembler for the monitor. */
d49190c4 728void monitor_disas(Monitor *mon, CPUState *cpu,
1d48474d 729 target_ulong pc, int nb_insn, int is_physical)
9307c4c1 730{
37b9de46 731 CPUClass *cc = CPU_GET_CLASS(cpu);
9307c4c1 732 int count, i;
f4359b9f 733 CPUDebug s;
9307c4c1 734
30cc9831 735 INIT_DISASSEMBLE_INFO(s.info, NULL, qemu_fprintf);
9307c4c1 736
d49190c4 737 s.cpu = cpu;
b8d87208
RH
738 s.info.read_memory_func
739 = (is_physical ? physical_read_memory : target_read_memory);
9504c544 740 s.info.print_address_func = generic_print_address;
f4359b9f 741 s.info.buffer_vma = pc;
8ca80760
RH
742 s.info.cap_arch = -1;
743 s.info.cap_mode = 0;
15fa1a0a
RH
744 s.info.cap_insn_unit = 4;
745 s.info.cap_insn_split = 4;
9307c4c1
FB
746
747#ifdef TARGET_WORDS_BIGENDIAN
f4359b9f 748 s.info.endian = BFD_ENDIAN_BIG;
9307c4c1 749#else
f4359b9f 750 s.info.endian = BFD_ENDIAN_LITTLE;
9307c4c1 751#endif
37b9de46
PC
752
753 if (cc->disas_set_info) {
754 cc->disas_set_info(cpu, &s.info);
755 }
756
8ca80760
RH
757 if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) {
758 return;
759 }
760
37b9de46
PC
761 if (!s.info.print_insn) {
762 monitor_printf(mon, "0x" TARGET_FMT_lx
763 ": Asm output not supported on this arch\n", pc);
764 return;
765 }
9307c4c1
FB
766
767 for(i = 0; i < nb_insn; i++) {
376253ec 768 monitor_printf(mon, "0x" TARGET_FMT_lx ": ", pc);
2de295c5 769 count = s.info.print_insn(pc, &s.info);
376253ec 770 monitor_printf(mon, "\n");
9307c4c1
FB
771 if (count < 0)
772 break;
773 pc += count;
774 }
775}
776#endif