s390x/tcg: Implement VECTOR ELEMENT COMPARE *
[qemu/ar7.git] / disas.c
blob41ad0102e2b61d5892a3158d2cf0c35d7c8d758d
1 /* General "disassemble this chunk" code. Used for debugging. */
2 #include "qemu/osdep.h"
3 #include "qemu-common.h"
4 #include "disas/dis-asm.h"
5 #include "elf.h"
6 #include "qemu/qemu-print.h"
8 #include "cpu.h"
9 #include "disas/disas.h"
10 #include "disas/capstone.h"
12 typedef struct CPUDebug {
13 struct disassemble_info info;
14 CPUState *cpu;
15 } CPUDebug;
17 /* Filled in by elfload.c. Simplistic, but will do for now. */
18 struct syminfo *syminfos = NULL;
20 /* Get LENGTH bytes from info's buffer, at target address memaddr.
21 Transfer them to myaddr. */
22 int
23 buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
24 struct disassemble_info *info)
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;
34 /* Get LENGTH bytes from info's buffer, at target address memaddr.
35 Transfer them to myaddr. */
36 static int
37 target_read_memory (bfd_vma memaddr,
38 bfd_byte *myaddr,
39 int length,
40 struct disassemble_info *info)
42 CPUDebug *s = container_of(info, CPUDebug, info);
44 cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
45 return 0;
48 /* Print an error message. We can assume that this is in response to
49 an error return from buffer_read_memory. */
50 void
51 perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info)
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,
60 "Address 0x%" PRIx64 " is out of bounds.\n", memaddr);
63 /* This could be in a separate file, to save minuscule amounts of space
64 in statically linked executables. */
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). */
70 void
71 generic_print_address (bfd_vma addr, struct disassemble_info *info)
73 (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
76 /* Print address in hex, truncated to the width of a host virtual address. */
77 static void
78 generic_print_host_address(bfd_vma addr, struct disassemble_info *info)
80 uint64_t mask = ~0ULL >> (64 - (sizeof(void *) * 8));
81 generic_print_address(addr & mask, info);
84 /* Just return the given address. */
86 int
87 generic_symbol_at_address (bfd_vma addr, struct disassemble_info *info)
89 return 1;
92 bfd_vma bfd_getl64 (const bfd_byte *addr)
94 unsigned long long v;
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;
107 bfd_vma bfd_getl32 (const bfd_byte *addr)
109 unsigned long v;
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;
118 bfd_vma bfd_getb32 (const bfd_byte *addr)
120 unsigned long v;
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;
129 bfd_vma bfd_getl16 (const bfd_byte *addr)
131 unsigned long v;
133 v = (unsigned long) addr[0];
134 v |= (unsigned long) addr[1] << 8;
135 return (bfd_vma) v;
138 bfd_vma bfd_getb16 (const bfd_byte *addr)
140 unsigned long v;
142 v = (unsigned long) addr[0] << 24;
143 v |= (unsigned long) addr[1] << 16;
144 return (bfd_vma) v;
147 static int print_insn_objdump(bfd_vma pc, disassemble_info *info,
148 const char *prefix)
150 int i, n = info->buffer_length;
151 uint8_t *buf = g_malloc(n);
153 info->read_memory_func(pc, buf, n, info);
155 for (i = 0; i < n; ++i) {
156 if (i % 32 == 0) {
157 info->fprintf_func(info->stream, "\n%s: ", prefix);
159 info->fprintf_func(info->stream, "%02x", buf[i]);
162 g_free(buf);
163 return n;
166 static int print_insn_od_host(bfd_vma pc, disassemble_info *info)
168 return print_insn_objdump(pc, info, "OBJD-H");
171 static int print_insn_od_target(bfd_vma pc, disassemble_info *info)
173 return print_insn_objdump(pc, info, "OBJD-T");
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. */
180 static __thread cs_insn *cap_insn;
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. */
189 static cs_err cap_disas_start(disassemble_info *info, csh *handle)
191 cs_mode cap_mode = info->cap_mode;
192 cs_err err;
194 cap_mode += (info->endian == BFD_ENDIAN_BIG ? CS_MODE_BIG_ENDIAN
195 : CS_MODE_LITTLE_ENDIAN);
197 err = cs_open(info->cap_arch, cap_mode, handle);
198 if (err != CS_ERR_OK) {
199 return err;
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);
210 /* "Disassemble" unknown insns as ".byte W,X,Y,Z". */
211 cs_option(*handle, CS_OPT_SKIPDATA, CS_OPT_ON);
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;
221 return CS_ERR_OK;
224 static void cap_dump_insn_units(disassemble_info *info, cs_insn *insn,
225 int i, int n)
227 fprintf_function print = info->fprintf_func;
228 FILE *stream = info->stream;
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));
237 } else {
238 for (; i < n; i += 4) {
239 print(stream, " %08x", ldl_le_p(insn->bytes + i));
242 break;
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));
249 } else {
250 for (; i < n; i += 2) {
251 print(stream, " %04x", lduw_le_p(insn->bytes + i));
254 break;
256 default:
257 for (; i < n; i++) {
258 print(stream, " %02x", insn->bytes[i]);
260 break;
264 static void cap_dump_insn(disassemble_info *info, cs_insn *insn)
266 fprintf_function print = info->fprintf_func;
267 int i, n, split;
269 print(info->stream, "0x%08" PRIx64 ": ", insn->address);
271 n = insn->size;
272 split = info->cap_insn_split;
274 /* Dump the first SPLIT bytes of the instruction. */
275 cap_dump_insn_units(info, insn, 0, MIN(n, split));
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, "");
284 /* Print the actual instruction. */
285 print(info->stream, " %-8s %s\n", insn->mnemonic, insn->op_str);
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");
295 /* Disassemble SIZE bytes at PC for the target. */
296 static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size)
298 uint8_t cap_buf[1024];
299 csh handle;
300 cs_insn *insn;
301 size_t csize = 0;
303 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
304 return false;
306 insn = cap_insn;
308 while (1) {
309 size_t tsize = MIN(sizeof(cap_buf) - csize, size);
310 const uint8_t *cbuf = cap_buf;
312 target_read_memory(pc + csize, cap_buf + csize, tsize, info);
313 csize += tsize;
314 size -= tsize;
316 while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
317 cap_dump_insn(info, insn);
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);
327 continue;
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");
338 break;
341 cs_close(&handle);
342 return true;
345 /* Disassemble SIZE bytes at CODE for the host. */
346 static bool cap_disas_host(disassemble_info *info, void *code, size_t size)
348 csh handle;
349 const uint8_t *cbuf;
350 cs_insn *insn;
351 uint64_t pc;
353 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
354 return false;
356 insn = cap_insn;
358 cbuf = code;
359 pc = (uintptr_t)code;
361 while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) {
362 cap_dump_insn(info, insn);
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");
370 cs_close(&handle);
371 return true;
374 #if !defined(CONFIG_USER_ONLY)
375 /* Disassemble COUNT insns at PC for the target. */
376 static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count)
378 uint8_t cap_buf[32];
379 csh handle;
380 cs_insn *insn;
381 size_t csize = 0;
383 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
384 return false;
386 insn = cap_insn;
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;
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;
405 if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
406 cap_dump_insn(info, insn);
407 if (--count <= 0) {
408 break;
411 memmove(cap_buf, cbuf, csize);
414 cs_close(&handle);
415 return true;
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 */
424 /* Disassemble this for me please... (debugging). */
425 void target_disas(FILE *out, CPUState *cpu, target_ulong code,
426 target_ulong size)
428 CPUClass *cc = CPU_GET_CLASS(cpu);
429 target_ulong pc;
430 int count;
431 CPUDebug s;
433 INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
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;
445 #ifdef TARGET_WORDS_BIGENDIAN
446 s.info.endian = BFD_ENDIAN_BIG;
447 #else
448 s.info.endian = BFD_ENDIAN_LITTLE;
449 #endif
451 if (cc->disas_set_info) {
452 cc->disas_set_info(cpu, &s.info);
455 if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) {
456 return;
459 if (s.info.print_insn == NULL) {
460 s.info.print_insn = print_insn_od_target;
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;
479 /* Disassemble this for me please... (debugging). */
480 void disas(FILE *out, void *code, unsigned long size)
482 uintptr_t pc;
483 int count;
484 CPUDebug s;
485 int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL;
487 INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
488 s.info.print_address_func = generic_print_host_address;
490 s.info.buffer = code;
491 s.info.buffer_vma = (uintptr_t)code;
492 s.info.buffer_length = size;
493 s.info.cap_arch = -1;
494 s.info.cap_mode = 0;
495 s.info.cap_insn_unit = 4;
496 s.info.cap_insn_split = 4;
498 #ifdef HOST_WORDS_BIGENDIAN
499 s.info.endian = BFD_ENDIAN_BIG;
500 #else
501 s.info.endian = BFD_ENDIAN_LITTLE;
502 #endif
503 #if defined(CONFIG_TCG_INTERPRETER)
504 print_insn = print_insn_tci;
505 #elif defined(__i386__)
506 s.info.mach = bfd_mach_i386_i386;
507 print_insn = print_insn_i386;
508 s.info.cap_arch = CS_ARCH_X86;
509 s.info.cap_mode = CS_MODE_32;
510 s.info.cap_insn_unit = 1;
511 s.info.cap_insn_split = 8;
512 #elif defined(__x86_64__)
513 s.info.mach = bfd_mach_x86_64;
514 print_insn = print_insn_i386;
515 s.info.cap_arch = CS_ARCH_X86;
516 s.info.cap_mode = CS_MODE_64;
517 s.info.cap_insn_unit = 1;
518 s.info.cap_insn_split = 8;
519 #elif defined(_ARCH_PPC)
520 s.info.disassembler_options = (char *)"any";
521 print_insn = print_insn_ppc;
522 s.info.cap_arch = CS_ARCH_PPC;
523 # ifdef _ARCH_PPC64
524 s.info.cap_mode = CS_MODE_64;
525 # endif
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
534 #elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
535 print_insn = print_insn_arm_a64;
536 s.info.cap_arch = CS_ARCH_ARM64;
537 #elif defined(__alpha__)
538 print_insn = print_insn_alpha;
539 #elif defined(__sparc__)
540 print_insn = print_insn_sparc;
541 s.info.mach = bfd_mach_sparc_v9b;
542 #elif defined(__arm__)
543 print_insn = print_insn_arm;
544 s.info.cap_arch = CS_ARCH_ARM;
545 /* TCG only generates code for arm mode. */
546 #elif defined(__MIPSEB__)
547 print_insn = print_insn_big_mips;
548 #elif defined(__MIPSEL__)
549 print_insn = print_insn_little_mips;
550 #elif defined(__m68k__)
551 print_insn = print_insn_m68k;
552 #elif defined(__s390__)
553 print_insn = print_insn_s390;
554 #elif defined(__hppa__)
555 print_insn = print_insn_hppa;
556 #endif
558 if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) {
559 return;
562 if (print_insn == NULL) {
563 print_insn = print_insn_od_host;
565 for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
566 fprintf(out, "0x%08" PRIxPTR ": ", pc);
567 count = print_insn(pc, &s.info);
568 fprintf(out, "\n");
569 if (count < 0)
570 break;
574 /* Look up symbol for debugging purpose. Returns "" if unknown. */
575 const char *lookup_symbol(target_ulong orig_addr)
577 const char *symbol = "";
578 struct syminfo *s;
580 for (s = syminfos; s; s = s->next) {
581 symbol = s->lookup_symbol(s, orig_addr);
582 if (symbol[0] != '\0') {
583 break;
587 return symbol;
590 #if !defined(CONFIG_USER_ONLY)
592 #include "monitor/monitor.h"
594 static int
595 physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
596 struct disassemble_info *info)
598 CPUDebug *s = container_of(info, CPUDebug, info);
600 address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED,
601 myaddr, length);
602 return 0;
605 /* Disassembler for the monitor. */
606 void monitor_disas(Monitor *mon, CPUState *cpu,
607 target_ulong pc, int nb_insn, int is_physical)
609 CPUClass *cc = CPU_GET_CLASS(cpu);
610 int count, i;
611 CPUDebug s;
613 INIT_DISASSEMBLE_INFO(s.info, NULL, qemu_fprintf);
615 s.cpu = cpu;
616 s.info.read_memory_func
617 = (is_physical ? physical_read_memory : target_read_memory);
618 s.info.print_address_func = generic_print_address;
619 s.info.buffer_vma = pc;
620 s.info.cap_arch = -1;
621 s.info.cap_mode = 0;
622 s.info.cap_insn_unit = 4;
623 s.info.cap_insn_split = 4;
625 #ifdef TARGET_WORDS_BIGENDIAN
626 s.info.endian = BFD_ENDIAN_BIG;
627 #else
628 s.info.endian = BFD_ENDIAN_LITTLE;
629 #endif
631 if (cc->disas_set_info) {
632 cc->disas_set_info(cpu, &s.info);
635 if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) {
636 return;
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;
645 for(i = 0; i < nb_insn; i++) {
646 monitor_printf(mon, "0x" TARGET_FMT_lx ": ", pc);
647 count = s.info.print_insn(pc, &s.info);
648 monitor_printf(mon, "\n");
649 if (count < 0)
650 break;
651 pc += count;
654 #endif