Commit 84dd090703 for qemu.org
commit 84dd090703e4164e209e0729333cfd30d8f9c9f8
Author: Richard Henderson <richard.henderson@linaro.org>
Date: Sat Aug 8 17:28:46 2026 -0700
target/mips: Enable disassembly via capstone
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
diff --git a/include/disas/capstone.h b/include/disas/capstone.h
index 3d6f90d816..e72faf8179 100644
--- a/include/disas/capstone.h
+++ b/include/disas/capstone.h
@@ -29,6 +29,7 @@
#define CS_MODE_THUMB 0
#define CS_MODE_MCLASS 0
#define CS_MODE_V8 0
+#define CS_MODE_V9 0
#define CS_MODE_M68K_000 0
#define CS_MODE_M68K_010 0
#define CS_MODE_M68K_020 0
@@ -36,11 +37,10 @@
#define CS_MODE_M68K_040 0
#define CS_MODE_M68K_060 0
#define CS_MODE_MICRO 0
+#define CS_MODE_MIPS2 0
#define CS_MODE_MIPS3 0
-#define CS_MODE_MIPS32R6 0
-#define CS_MODE_MIPSGP64 0
-#define CS_MODE_V9 0
#define CS_MODE_MIPS32 0
+#define CS_MODE_MIPS32R6 0
#define CS_MODE_MIPS64 0
#endif /* CONFIG_CAPSTONE */
@@ -64,6 +64,24 @@
#define CS_MODE_M68K_CF_FPU 0
#endif
+#if CS_API_MAJOR < 6
+#define CS_MODE_MIPS16 0
+#define CS_MODE_MIPS1 0
+#define CS_MODE_MIPS32R2 0
+#define CS_MODE_MIPS32R3 0
+#define CS_MODE_MIPS32R5 0
+#define CS_MODE_MIPS4 0
+#define CS_MODE_MIPS5 0
+#define CS_MODE_MIPS64R2 0
+#define CS_MODE_MIPS64R3 0
+#define CS_MODE_MIPS64R5 0
+#define CS_MODE_MIPS64R6 0
+#define CS_MODE_OCTEON 0
+#define CS_MODE_OCTEONP 0
+#define CS_MODE_NANOMIPS 0
+#define CS_MODE_MIPS_PTR64 0
+#endif
+
#if CS_API_MAJOR < 5
#define CS_ARCH_RISCV -1
#define CS_MODE_RISCV32 0
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index 669c7d99bb..0fead20d65 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -30,6 +30,7 @@
#include "system/qtest.h"
#include "hw/core/qdev-properties.h"
#include "hw/core/qdev-clock.h"
+#include "disas/capstone.h"
#include "fpu_helper.h"
#ifndef CONFIG_USER_ONLY
#include "semihosting/semihost.h"
@@ -488,15 +489,66 @@ static void mips_cpu_disas_set_info(const CPUState *cs, disassemble_info *info)
{
const MIPSCPU *cpu = MIPS_CPU(cs);
const CPUMIPSState *env = &cpu->env;
+ bool is64 = env->hflags & MIPS_HFLAG_64;
+ int cap_mode = 0;
- if (!(env->insn_flags & ISA_NANOMIPS32)) {
+ if (env->insn_flags & ISA_NANOMIPS32) {
+ info->print_insn = print_insn_nanomips;
+ info->endian = BFD_ENDIAN_LITTLE;
+ /* nanomips has 16, 32 and 48-bit insns */
+ info->cap_insn_unit = 2;
+ info->cap_insn_split = 6;
+ cap_mode = CS_MODE_NANOMIPS;
+ } else {
info->endian = TARGET_BIG_ENDIAN ? BFD_ENDIAN_BIG
: BFD_ENDIAN_LITTLE;
info->print_insn = TARGET_BIG_ENDIAN ? print_insn_big_mips
: print_insn_little_mips;
- } else {
- info->print_insn = print_insn_nanomips;
- info->endian = BFD_ENDIAN_LITTLE;
+
+ if (env->hflags & MIPS_HFLAG_M16) {
+ cap_mode = (env->insn_flags & ASE_MICROMIPS
+ ? CS_MODE_MICRO : CS_MODE_MIPS16);
+ /* Beware unsupported capstone mode */
+ if (cap_mode == 0) {
+ return;
+ }
+ info->cap_insn_unit = 2;
+ } else {
+ info->cap_insn_unit = 4;
+ }
+ info->cap_insn_split = 4;
+
+ cap_mode |= is64 ? CS_MODE_MIPS64 : CS_MODE_MIPS32;
+ if (env->insn_flags & ISA_MIPS_R6) {
+ cap_mode |= is64 ? CS_MODE_MIPS64R6 : CS_MODE_MIPS32R6;
+ } else if (env->insn_flags & ISA_MIPS_R5) {
+ cap_mode |= is64 ? CS_MODE_MIPS64R5 : CS_MODE_MIPS32R5;
+ } else if (env->insn_flags & ISA_MIPS_R3) {
+ cap_mode |= is64 ? CS_MODE_MIPS64R3 : CS_MODE_MIPS32R3;
+ } else if (env->insn_flags & ISA_MIPS_R2) {
+ cap_mode |= is64 ? CS_MODE_MIPS64R2 : CS_MODE_MIPS32R2;
+ } else if (env->insn_flags & ISA_MIPS5) {
+ cap_mode |= CS_MODE_MIPS5;
+ } else if (env->insn_flags & ISA_MIPS4) {
+ cap_mode |= CS_MODE_MIPS4;
+ } else if (env->insn_flags & ISA_MIPS3) {
+ cap_mode |= CS_MODE_MIPS3;
+ } else if (env->insn_flags & ISA_MIPS2) {
+ cap_mode |= CS_MODE_MIPS2;
+ } else if (env->insn_flags & ISA_MIPS1) {
+ cap_mode |= CS_MODE_MIPS1;
+ }
+ if (env->insn_flags & INSN_OCTEON) {
+ cap_mode |= CS_MODE_OCTEON | CS_MODE_OCTEONP;
+ }
+ if (is64 && !(env->hflags & MIPS_HFLAG_AWRAP)) {
+ cap_mode |= CS_MODE_MIPS_PTR64;
+ }
+ }
+ /* Beware unsupported capstone mode */
+ if (cap_mode) {
+ info->cap_arch = CS_ARCH_MIPS;
+ info->cap_mode = cap_mode;
}
}