RISC-V: Move all global static target stuff into private data for disassembler.

Message ID 20250206134737.80170-1-nelson@rivosinc.com
State New
Headers
Series RISC-V: Move all global static target stuff into private data for disassembler. |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

Nelson Chu Feb. 6, 2025, 1:47 p.m. UTC
  I got a request said that the JDK multi-thread compiler may be broken
if two or more threads are trying to print/disassemble stuff, and filling
the disassemble_info, setting callbacks, and grabbing the function pointer
to disasm at the same time.  Since such as the target global static stuff,
including subset of extensions and mapping symbol stuff, seems to only be
one globally.  Ideally, for dis-assembler, all global static target stuff
should/can be better to be defined into the target private data, since they
are target-dependency.

opcodes/
	* riscv-dis.c: Moved all global static target-dependency stuff into
	riscv_private_data, including architecture and mapping symbol stuff.
	(set_default_riscv_dis_options): Updated since global static target-
	dependency stuff are moved into riscv_private_data.
	(parse_riscv_dis_option_without_args): Likewise.
	(parse_riscv_dis_option): Likewise.
	(parse_riscv_dis_options): Likewise.
	(maybe_print_address): Likewise.
	(print_reg_list): Likewise.
	(riscv_get_spimm): Likewise.
	(print_insn_args): Likewise.
	(riscv_disassemble_insn): Likewise.
	(riscv_update_map_state): Likewise.
	(riscv_search_mapping_symbol): Likewise.
	(riscv_data_length): Likewise.
	(print_insn_riscv): Likewise.  Call the riscv_init_disasm_info before
	parsing any disassembler options, since the related stuff are moved
	into riscv_private_data.
	(riscv_init_disasm_info): Likewise.  Parse and set the architecture
	string and privileged spec version since riscv_get_disassembler is
	no longer needed.
	(riscv_get_disassembler): Removed.
	(disassemble_free_riscv): Only free the subset_list if
	riscv_private_data exsits.
	* disassemble.c (disassembler): Since riscv_get_disassembler is
	removed, call to print_insn_riscv.
	* disassemble.h: Removed extern riscv_get_disassembler.
---
 opcodes/disassemble.c |   2 +-
 opcodes/disassemble.h |   1 -
 opcodes/riscv-dis.c   | 336 ++++++++++++++++++++++--------------------
 3 files changed, 178 insertions(+), 161 deletions(-)
  

Comments

Jan Beulich Feb. 7, 2025, 8:57 a.m. UTC | #1
On 06.02.2025 14:47, Nelson Chu wrote:
> I got a request said that the JDK multi-thread compiler may be broken
> if two or more threads are trying to print/disassemble stuff, and filling
> the disassemble_info, setting callbacks, and grabbing the function pointer
> to disasm at the same time.  Since such as the target global static stuff,
> including subset of extensions and mapping symbol stuff, seems to only be
> one globally.  Ideally, for dis-assembler, all global static target stuff
> should/can be better to be defined into the target private data, since they
> are target-dependency.
> 
> opcodes/
> 	* riscv-dis.c: Moved all global static target-dependency stuff into
> 	riscv_private_data, including architecture and mapping symbol stuff.
> 	(set_default_riscv_dis_options): Updated since global static target-
> 	dependency stuff are moved into riscv_private_data.
> 	(parse_riscv_dis_option_without_args): Likewise.
> 	(parse_riscv_dis_option): Likewise.
> 	(parse_riscv_dis_options): Likewise.
> 	(maybe_print_address): Likewise.
> 	(print_reg_list): Likewise.
> 	(riscv_get_spimm): Likewise.
> 	(print_insn_args): Likewise.
> 	(riscv_disassemble_insn): Likewise.
> 	(riscv_update_map_state): Likewise.
> 	(riscv_search_mapping_symbol): Likewise.
> 	(riscv_data_length): Likewise.
> 	(print_insn_riscv): Likewise.  Call the riscv_init_disasm_info before
> 	parsing any disassembler options, since the related stuff are moved
> 	into riscv_private_data.
> 	(riscv_init_disasm_info): Likewise.  Parse and set the architecture
> 	string and privileged spec version since riscv_get_disassembler is
> 	no longer needed.
> 	(riscv_get_disassembler): Removed.
> 	(disassemble_free_riscv): Only free the subset_list if
> 	riscv_private_data exsits.
> 	* disassemble.c (disassembler): Since riscv_get_disassembler is
> 	removed, call to print_insn_riscv.
> 	* disassemble.h: Removed extern riscv_get_disassembler.
> ---
>  opcodes/disassemble.c |   2 +-
>  opcodes/disassemble.h |   1 -
>  opcodes/riscv-dis.c   | 336 ++++++++++++++++++++++--------------------
>  3 files changed, 178 insertions(+), 161 deletions(-)

Lgtm, fwiw.

Jan
  
Nelson Chu Feb. 11, 2025, 6:39 a.m. UTC | #2
Thanks Jan, committed.

Nelson

On Fri, Feb 7, 2025 at 4:57 PM Jan Beulich <jbeulich@suse.com> wrote:

> On 06.02.2025 14:47, Nelson Chu wrote:
> > I got a request said that the JDK multi-thread compiler may be broken
> > if two or more threads are trying to print/disassemble stuff, and filling
> > the disassemble_info, setting callbacks, and grabbing the function
> pointer
> > to disasm at the same time.  Since such as the target global static
> stuff,
> > including subset of extensions and mapping symbol stuff, seems to only be
> > one globally.  Ideally, for dis-assembler, all global static target stuff
> > should/can be better to be defined into the target private data, since
> they
> > are target-dependency.
> >
> > opcodes/
> >       * riscv-dis.c: Moved all global static target-dependency stuff into
> >       riscv_private_data, including architecture and mapping symbol
> stuff.
> >       (set_default_riscv_dis_options): Updated since global static
> target-
> >       dependency stuff are moved into riscv_private_data.
> >       (parse_riscv_dis_option_without_args): Likewise.
> >       (parse_riscv_dis_option): Likewise.
> >       (parse_riscv_dis_options): Likewise.
> >       (maybe_print_address): Likewise.
> >       (print_reg_list): Likewise.
> >       (riscv_get_spimm): Likewise.
> >       (print_insn_args): Likewise.
> >       (riscv_disassemble_insn): Likewise.
> >       (riscv_update_map_state): Likewise.
> >       (riscv_search_mapping_symbol): Likewise.
> >       (riscv_data_length): Likewise.
> >       (print_insn_riscv): Likewise.  Call the riscv_init_disasm_info
> before
> >       parsing any disassembler options, since the related stuff are moved
> >       into riscv_private_data.
> >       (riscv_init_disasm_info): Likewise.  Parse and set the architecture
> >       string and privileged spec version since riscv_get_disassembler is
> >       no longer needed.
> >       (riscv_get_disassembler): Removed.
> >       (disassemble_free_riscv): Only free the subset_list if
> >       riscv_private_data exsits.
> >       * disassemble.c (disassembler): Since riscv_get_disassembler is
> >       removed, call to print_insn_riscv.
> >       * disassemble.h: Removed extern riscv_get_disassembler.
> > ---
> >  opcodes/disassemble.c |   2 +-
> >  opcodes/disassemble.h |   1 -
> >  opcodes/riscv-dis.c   | 336 ++++++++++++++++++++++--------------------
> >  3 files changed, 178 insertions(+), 161 deletions(-)
>
> Lgtm, fwiw.
>
> Jan
>
  

Patch

diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index 98de1a772f9..53ee1ecf38b 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -382,7 +382,7 @@  disassembler (enum bfd_architecture a,
 #endif
 #ifdef ARCH_riscv
     case bfd_arch_riscv:
-      disassemble = riscv_get_disassembler (abfd);
+      disassemble = print_insn_riscv;
       break;
 #endif
 #ifdef ARCH_rl78
diff --git a/opcodes/disassemble.h b/opcodes/disassemble.h
index 5fcd45ea5ae..a6c7d8fb756 100644
--- a/opcodes/disassemble.h
+++ b/opcodes/disassemble.h
@@ -102,7 +102,6 @@  extern int print_insn_loongarch		(bfd_vma, disassemble_info *);
 
 extern disassembler_ftype csky_get_disassembler (bfd *);
 extern disassembler_ftype rl78_get_disassembler (bfd *);
-extern disassembler_ftype riscv_get_disassembler (bfd *);
 
 extern void disassemble_free_riscv (disassemble_info *);
 extern void disassemble_free_powerpc (disassemble_info *);
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index 367004d3341..d67b2c2aaf0 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -37,26 +37,6 @@ 
    disassemble_info::fprintf_func which is for unstyled output.  */
 #define fprintf_func please_use_fprintf_styled_func_instead
 
-/* Current XLEN for the disassembler.  */
-static unsigned xlen = 0;
-
-/* Default ISA specification version (constant as of now).  */
-static enum riscv_spec_class default_isa_spec = ISA_SPEC_CLASS_DRAFT - 1;
-
-/* Default privileged specification
-   (as specified by the ELF attributes or the `priv-spec' option).  */
-static enum riscv_spec_class default_priv_spec = PRIV_SPEC_CLASS_NONE;
-
-static riscv_subset_list_t riscv_subsets;
-static riscv_parse_subset_t riscv_rps_dis =
-{
-  &riscv_subsets,	/* subset_list.  */
-  opcodes_error_handler,/* error_handler.  */
-  &xlen,		/* xlen.  */
-  &default_isa_spec,	/* isa_spec.  */
-  false,		/* check_unknown_prefixed_ext.  */
-};
-
 struct riscv_private_data
 {
   bfd_vma gp;
@@ -64,50 +44,57 @@  struct riscv_private_data
   bfd_vma hi_addr[OP_MASK_RD + 1];
   bool to_print_addr;
   bool has_gp;
+  /* Current XLEN for the disassembler.  */
+  unsigned xlen;
+  /* Default ISA specification version.  */
+  enum riscv_spec_class default_isa_spec;
+  /* Default privileged specification.  */
+  enum riscv_spec_class default_priv_spec;
+  /* Used for architecture parser.  */
+  riscv_parse_subset_t riscv_rps_dis;
+  /* Used for mapping symbols.  */
+  int last_map_symbol;
+  bfd_vma last_stop_offset;
+  bfd_vma last_map_symbol_boundary;
+  enum riscv_seg_mstate last_map_state;
+  asection *last_map_section;
+  /* Register names as used by the disassembler.  */
+  const char (*riscv_gpr_names)[NRC];
+  const char (*riscv_fpr_names)[NRC];
+  /* If set, disassemble as most general instruction.  */
+  bool no_aliases;
+  /* If set, disassemble without checking architectire string, just like what
+     we did at the beginning.  */
+  bool all_ext;
 };
 
-/* Used for mapping symbols.  */
-static int last_map_symbol = -1;
-static bfd_vma last_stop_offset = 0;
-static bfd_vma last_map_symbol_boundary = 0;
-static enum riscv_seg_mstate last_map_state = MAP_NONE;
-static asection *last_map_section = NULL;
-
-/* Register names as used by the disassembler.  */
-static const char (*riscv_gpr_names)[NRC];
-static const char (*riscv_fpr_names)[NRC];
-
-/* If set, disassemble as most general instruction.  */
-static bool no_aliases = false;
-
-/* If set, disassemble without checking architectire string, just like what
-   we did at the beginning.  */
-static bool all_ext = false;
-
 /* Set default RISC-V disassembler options.  */
 
 static void
-set_default_riscv_dis_options (void)
+set_default_riscv_dis_options (struct disassemble_info *info)
 {
-  riscv_gpr_names = riscv_gpr_names_abi;
-  riscv_fpr_names = riscv_fpr_names_abi;
-  no_aliases = false;
+  struct riscv_private_data *pd = info->private_data;
+  pd->riscv_gpr_names = riscv_gpr_names_abi;
+  pd->riscv_fpr_names = riscv_fpr_names_abi;
+  pd->no_aliases = false;
 }
 
 /* Parse RISC-V disassembler option (without arguments).  */
 
 static bool
-parse_riscv_dis_option_without_args (const char *option)
+parse_riscv_dis_option_without_args (const char *option,
+				     struct disassemble_info *info)
 {
+  struct riscv_private_data *pd = info->private_data;
   if (strcmp (option, "no-aliases") == 0)
-    no_aliases = true;
+    pd->no_aliases = true;
   else if (strcmp (option, "numeric") == 0)
     {
-      riscv_gpr_names = riscv_gpr_names_numeric;
-      riscv_fpr_names = riscv_fpr_names_numeric;
+      pd->riscv_gpr_names = riscv_gpr_names_numeric;
+      pd->riscv_fpr_names = riscv_fpr_names_numeric;
     }
   else if (strcmp (option, "max") == 0)
-    all_ext = true;
+    pd->all_ext = true;
   else
     return false;
   return true;
@@ -116,11 +103,11 @@  parse_riscv_dis_option_without_args (const char *option)
 /* Parse RISC-V disassembler option (possibly with arguments).  */
 
 static void
-parse_riscv_dis_option (const char *option)
+parse_riscv_dis_option (const char *option, struct disassemble_info *info)
 {
   char *equal, *value;
 
-  if (parse_riscv_dis_option_without_args (option))
+  if (parse_riscv_dis_option_without_args (option, info))
     return;
 
   equal = strchr (option, '=');
@@ -144,6 +131,7 @@  parse_riscv_dis_option (const char *option)
   value = equal + 1;
   if (strcmp (option, "priv-spec") == 0)
     {
+      struct riscv_private_data *pd = info->private_data;
       enum riscv_spec_class priv_spec = PRIV_SPEC_CLASS_NONE;
       const char *name = NULL;
 
@@ -151,11 +139,11 @@  parse_riscv_dis_option (const char *option)
       if (priv_spec == PRIV_SPEC_CLASS_NONE)
 	opcodes_error_handler (_("unknown privileged spec set by %s=%s"),
 			       option, value);
-      else if (default_priv_spec == PRIV_SPEC_CLASS_NONE)
-	default_priv_spec = priv_spec;
-      else if (default_priv_spec != priv_spec)
+      else if (pd->default_priv_spec == PRIV_SPEC_CLASS_NONE)
+	pd->default_priv_spec = priv_spec;
+      else if (pd->default_priv_spec != priv_spec)
 	{
-	  RISCV_GET_PRIV_SPEC_NAME (name, default_priv_spec);
+	  RISCV_GET_PRIV_SPEC_NAME (name, pd->default_priv_spec);
 	  opcodes_error_handler (_("mis-matched privilege spec set by %s=%s, "
 				   "the elf privilege attribute is %s"),
 				 option, value, name);
@@ -171,17 +159,17 @@  parse_riscv_dis_option (const char *option)
 /* Parse RISC-V disassembler options.  */
 
 static void
-parse_riscv_dis_options (const char *opts_in)
+parse_riscv_dis_options (const char *opts_in, struct disassemble_info *info)
 {
   char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts;
 
-  set_default_riscv_dis_options ();
+  set_default_riscv_dis_options (info);
 
   for ( ; opt_end != NULL; opt = opt_end + 1)
     {
       if ((opt_end = strchr (opt, ',')) != NULL)
 	*opt_end = 0;
-      parse_riscv_dis_option (opt);
+      parse_riscv_dis_option (opt, info);
     }
 
   free (opts);
@@ -221,7 +209,7 @@  maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset,
     pd->print_addr = (bfd_vma)(int32_t) pd->print_addr;
 
   /* Fit into a 32-bit value on RV32.  */
-  if (xlen == 32)
+  if (pd->xlen == 32)
     pd->print_addr = (bfd_vma)(uint32_t)pd->print_addr;
 }
 
@@ -230,60 +218,61 @@  maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset,
 static void
 print_reg_list (disassemble_info *info, insn_t l)
 {
-  bool numeric = riscv_gpr_names == riscv_gpr_names_numeric;
+  struct riscv_private_data *pd = info->private_data;
+  bool numeric = pd->riscv_gpr_names == riscv_gpr_names_numeric;
   unsigned reg_list = (int)EXTRACT_OPERAND (REG_LIST, l);
   unsigned r_start = numeric ? X_S2 : X_S0;
   info->fprintf_styled_func (info->stream, dis_style_register,
-			     "%s", riscv_gpr_names[X_RA]);
+			     "%s", pd->riscv_gpr_names[X_RA]);
 
   if (reg_list == 5)
     {
       info->fprintf_styled_func (info->stream, dis_style_text, ",");
       info->fprintf_styled_func (info->stream, dis_style_register,
-				 "%s", riscv_gpr_names[X_S0]);
+				 "%s", pd->riscv_gpr_names[X_S0]);
     }
   else if (reg_list == 6 || (numeric && reg_list > 6))
     {
       info->fprintf_styled_func (info->stream, dis_style_text, ",");
       info->fprintf_styled_func (info->stream, dis_style_register,
-				 "%s", riscv_gpr_names[X_S0]);
+				 "%s", pd->riscv_gpr_names[X_S0]);
       info->fprintf_styled_func (info->stream, dis_style_text, "-");
       info->fprintf_styled_func (info->stream, dis_style_register,
-				 "%s", riscv_gpr_names[X_S1]);
+				 "%s", pd->riscv_gpr_names[X_S1]);
     }
 
   if (reg_list == 15)
     {
       info->fprintf_styled_func (info->stream, dis_style_text, ",");
       info->fprintf_styled_func (info->stream, dis_style_register,
-				 "%s", riscv_gpr_names[r_start]);
+				 "%s", pd->riscv_gpr_names[r_start]);
       info->fprintf_styled_func (info->stream, dis_style_text, "-");
       info->fprintf_styled_func (info->stream, dis_style_register,
-				 "%s", riscv_gpr_names[X_S11]);
+				 "%s", pd->riscv_gpr_names[X_S11]);
     }
   else if (reg_list == 7 && numeric)
     {
       info->fprintf_styled_func (info->stream, dis_style_text, ",");
       info->fprintf_styled_func (info->stream, dis_style_register,
-				 "%s", riscv_gpr_names[X_S2]);
+				 "%s", pd->riscv_gpr_names[X_S2]);
     }
   else if (reg_list > 6)
     {
       info->fprintf_styled_func (info->stream, dis_style_text, ",");
       info->fprintf_styled_func (info->stream, dis_style_register,
-				 "%s", riscv_gpr_names[r_start]);
+				 "%s", pd->riscv_gpr_names[r_start]);
       info->fprintf_styled_func (info->stream, dis_style_text, "-");
       info->fprintf_styled_func (info->stream, dis_style_register,
-				 "%s", riscv_gpr_names[reg_list + 11]);
+				 "%s", pd->riscv_gpr_names[reg_list + 11]);
     }
 }
 
 /* Get Zcmp sp adjustment immediate.  */
 
 static int
-riscv_get_spimm (insn_t l)
+riscv_get_spimm (insn_t l, int xlen)
 {
-  int spimm = riscv_get_sp_base(l, *riscv_rps_dis.xlen);
+  int spimm = riscv_get_sp_base(l, xlen);
   spimm += EXTRACT_ZCMP_SPIMM (l);
   if (((l ^ MATCH_CM_PUSH) & MASK_CM_PUSH) == 0)
     spimm *= -1;
@@ -326,24 +315,24 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 	    case 's': /* RS1 x8-x15.  */
 	    case 'w': /* RS1 x8-x15.  */
 	      print (info->stream, dis_style_register, "%s",
-		     riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]);
+		     pd->riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]);
 	      break;
 	    case 't': /* RS2 x8-x15.  */
 	    case 'x': /* RS2 x8-x15.  */
 	      print (info->stream, dis_style_register, "%s",
-		     riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
+		     pd->riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
 	      break;
 	    case 'U': /* RS1, constrained to equal RD.  */
 	      print (info->stream, dis_style_register,
-		     "%s", riscv_gpr_names[rd]);
+		     "%s", pd->riscv_gpr_names[rd]);
 	      break;
 	    case 'c': /* RS1, constrained to equal sp.  */
 	      print (info->stream, dis_style_register, "%s",
-		     riscv_gpr_names[X_SP]);
+		     pd->riscv_gpr_names[X_SP]);
 	      break;
 	    case 'V': /* RS2 */
 	      print (info->stream, dis_style_register, "%s",
-		     riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]);
+		     pd->riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]);
 	      break;
 	    case 'o':
 	    case 'j':
@@ -409,11 +398,11 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 	      break;
 	    case 'T': /* Floating-point RS2.  */
 	      print (info->stream, dis_style_register, "%s",
-		     riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]);
+		     pd->riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]);
 	      break;
 	    case 'D': /* Floating-point RS2 x8-x15.  */
 	      print (info->stream, dis_style_register, "%s",
-		     riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
+		     pd->riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
 	      break;
 	    }
 	  break;
@@ -429,7 +418,7 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 	    case 'e':
 	      if (!EXTRACT_OPERAND (VWD, l))
 		print (info->stream, dis_style_register, "%s",
-		       riscv_gpr_names[0]);
+		       pd->riscv_gpr_names[0]);
 	      else
 		print (info->stream, dis_style_register, "%s",
 		       riscv_vecr_names_numeric[EXTRACT_OPERAND (VD, l)]);
@@ -520,12 +509,13 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 	case 's':
 	  if ((l & MASK_JALR) == MATCH_JALR)
 	    maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0);
-	  print (info->stream, dis_style_register, "%s", riscv_gpr_names[rs1]);
+	  print (info->stream, dis_style_register, "%s",
+		 pd->riscv_gpr_names[rs1]);
 	  break;
 
 	case 't':
 	  print (info->stream, dis_style_register, "%s",
-		 riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]);
+		 pd->riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]);
 	  break;
 
 	case 'u':
@@ -585,7 +575,8 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 	    pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l);
 	  else if ((l & MASK_C_LUI) == MATCH_C_LUI)
 	    pd->hi_addr[rd] = EXTRACT_CITYPE_LUI_IMM (l);
-	  print (info->stream, dis_style_register, "%s", riscv_gpr_names[rd]);
+	  print (info->stream, dis_style_register, "%s",
+		 pd->riscv_gpr_names[rd]);
 	  break;
 
 	case 'y':
@@ -594,7 +585,8 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 	  break;
 
 	case 'z':
-	  print (info->stream, dis_style_register, "%s", riscv_gpr_names[0]);
+	  print (info->stream, dis_style_register, "%s",
+		 pd->riscv_gpr_names[0]);
 	  break;
 
 	case '>':
@@ -609,21 +601,23 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 
 	case 'S':
 	case 'U':
-	  print (info->stream, dis_style_register, "%s", riscv_fpr_names[rs1]);
+	  print (info->stream, dis_style_register, "%s",
+		 pd->riscv_fpr_names[rs1]);
 	  break;
 
 	case 'T':
 	  print (info->stream, dis_style_register, "%s",
-		 riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]);
+		 pd->riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]);
 	  break;
 
 	case 'D':
-	  print (info->stream, dis_style_register, "%s", riscv_fpr_names[rd]);
+	  print (info->stream, dis_style_register, "%s",
+		 pd->riscv_fpr_names[rd]);
 	  break;
 
 	case 'R':
 	  print (info->stream, dis_style_register, "%s",
-		 riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]);
+		 pd->riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]);
 	  break;
 
 	case 'E':
@@ -639,15 +633,15 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 		  riscv_csr_hash[i] = NULL;
 
 		/* Set to the newest privileged version.  */
-		if (default_priv_spec == PRIV_SPEC_CLASS_NONE)
-		  default_priv_spec = PRIV_SPEC_CLASS_DRAFT - 1;
+		if (pd->default_priv_spec == PRIV_SPEC_CLASS_NONE)
+		  pd->default_priv_spec = PRIV_SPEC_CLASS_DRAFT - 1;
 
 #define DECLARE_CSR(name, num, class, define_version, abort_version)	\
 		if (riscv_csr_hash[num] == NULL 			\
 		    && ((define_version == PRIV_SPEC_CLASS_NONE 	\
 			 && abort_version == PRIV_SPEC_CLASS_NONE)	\
-			|| (default_priv_spec >= define_version 	\
-			    && default_priv_spec < abort_version)))	\
+			|| (pd->default_priv_spec >= define_version 	\
+			    && pd->default_priv_spec < abort_version)))	\
 		  riscv_csr_hash[num] = #name;
 #define DECLARE_CSR_ALIAS(name, num, class, define_version, abort_version) \
 		DECLARE_CSR (name, num, class, define_version, abort_version)
@@ -656,7 +650,7 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 	      }
 
 	    if (riscv_csr_hash[csr] != NULL)
-	      if (riscv_subset_supports (&riscv_rps_dis, "xtheadvector")
+	      if (riscv_subset_supports (&pd->riscv_rps_dis, "xtheadvector")
 		  && (csr == CSR_VSTART
 		      || csr == CSR_VXSAT
 		      || csr == CSR_VXRM
@@ -716,11 +710,11 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 		{
 		case '1':
 		    print (info->stream, dis_style_register, "%s",
-		      riscv_gpr_names[riscv_zcmp_get_sregno (EXTRACT_OPERAND (SREG1, l))]);
+		      pd->riscv_gpr_names[riscv_zcmp_get_sregno (EXTRACT_OPERAND (SREG1, l))]);
 		    break;
 		case '2':
 		    print (info->stream, dis_style_register, "%s",
-		      riscv_gpr_names[riscv_zcmp_get_sregno (EXTRACT_OPERAND (SREG2, l))]);
+		      pd->riscv_gpr_names[riscv_zcmp_get_sregno (EXTRACT_OPERAND (SREG2, l))]);
 		    break;
 		case 'b':
 		  print (info->stream, dis_style_immediate, "%d",
@@ -735,7 +729,7 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 		  break;
 		case 'p':
 		  print (info->stream, dis_style_immediate, "%d",
-			 riscv_get_spimm (l));
+			 riscv_get_spimm (l, pd->xlen));
 		  break;
 		case 'i':
 		case 'I':
@@ -947,21 +941,21 @@  riscv_disassemble_insn (bfd_vma memaddr,
     {
       /* If XLEN is not known, get its value from the ELF class.  */
       if (info->mach == bfd_mach_riscv64)
-	xlen = 64;
+	pd->xlen = 64;
       else if (info->mach == bfd_mach_riscv32)
-	xlen = 32;
+	pd->xlen = 32;
       else if (info->section != NULL)
 	{
 	  Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner);
-	  xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32;
+	  pd->xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32;
 	}
 
       /* If arch has the Zfinx extension, replace FPR with GPR.  */
-      if (riscv_subset_supports (&riscv_rps_dis, "zfinx"))
-	riscv_fpr_names = riscv_gpr_names;
+      if (riscv_subset_supports (&pd->riscv_rps_dis, "zfinx"))
+	pd->riscv_fpr_names = pd->riscv_gpr_names;
       else
-	riscv_fpr_names = riscv_gpr_names == riscv_gpr_names_abi ?
-			  riscv_fpr_names_abi : riscv_fpr_names_numeric;
+	pd->riscv_fpr_names = pd->riscv_gpr_names == riscv_gpr_names_abi ?
+			      riscv_fpr_names_abi : riscv_fpr_names_numeric;
 
       for (; op->name; op++)
 	{
@@ -972,14 +966,16 @@  riscv_disassemble_insn (bfd_vma memaddr,
 	  if (! (op->match_func) (op, word))
 	    continue;
 	  /* Is this a pseudo-instruction and may we print it as such?  */
-	  if (no_aliases && (op->pinfo & INSN_ALIAS))
+	  if (pd->no_aliases && (op->pinfo & INSN_ALIAS))
 	    continue;
 	  /* Is this instruction restricted to a certain value of XLEN?  */
-	  if ((op->xlen_requirement != 0) && (op->xlen_requirement != xlen))
+	  if ((op->xlen_requirement != 0)
+	      && (op->xlen_requirement != pd->xlen))
 	    continue;
 	  /* Is this instruction supported by the current architecture?  */
-	  if (!all_ext
-	      && !riscv_multi_subset_supports (&riscv_rps_dis, op->insn_class))
+	  if (!pd->all_ext
+	      && !riscv_multi_subset_supports (&pd->riscv_rps_dis,
+					       op->insn_class))
 	    continue;
 
 	  /* It's a match.  */
@@ -1060,6 +1056,7 @@  riscv_update_map_state (int n,
 			enum riscv_seg_mstate *state,
 			struct disassemble_info *info)
 {
+  struct riscv_private_data *pd = info->private_data;
   const char *name;
 
   /* If the symbol is in a different section, ignore it.  */
@@ -1075,7 +1072,7 @@  riscv_update_map_state (int n,
   else if (strncmp (name, "$xrv", 4) == 0)
     {
       *state = MAP_INSN;
-      riscv_release_subset_list (&riscv_subsets);
+      riscv_release_subset_list (pd->riscv_rps_dis.subset_list);
 
       /* ISA mapping string may be numbered, suffixed with '.n'. Do not
 	 consider this as part of the ISA string.  */
@@ -1086,11 +1083,11 @@  riscv_update_map_state (int n,
 	  char *name_substr = xmalloc (suffix_index + 1);
 	  strncpy (name_substr, name, suffix_index);
 	  name_substr[suffix_index] = '\0';
-	  riscv_parse_subset (&riscv_rps_dis, name_substr + 2);
+	  riscv_parse_subset (&pd->riscv_rps_dis, name_substr + 2);
 	  free (name_substr);
 	}
       else
-	riscv_parse_subset (&riscv_rps_dis, name + 2);
+	riscv_parse_subset (&pd->riscv_rps_dis, name + 2);
     }
 }
 
@@ -1119,6 +1116,7 @@  static enum riscv_seg_mstate
 riscv_search_mapping_symbol (bfd_vma memaddr,
 			     struct disassemble_info *info)
 {
+  struct riscv_private_data *pd = info->private_data;
   enum riscv_seg_mstate mstate;
   bool from_last_map_symbol;
   bool found = false;
@@ -1127,11 +1125,11 @@  riscv_search_mapping_symbol (bfd_vma memaddr,
 
   /* Return the last map state if the address is still within the range of the
      last mapping symbol.  */
-  if (last_map_section == info->section
-      && (memaddr < last_map_symbol_boundary))
-    return last_map_state;
+  if (pd->last_map_section == info->section
+      && (memaddr < pd->last_map_symbol_boundary))
+    return pd->last_map_state;
 
-  last_map_section = info->section;
+  pd->last_map_section = info->section;
 
   /* Decide whether to print the data or instruction by default, in case
      we can not find the corresponding mapping symbols.  */
@@ -1147,17 +1145,17 @@  riscv_search_mapping_symbol (bfd_vma memaddr,
 
   /* Reset the last_map_symbol if we start to dump a new section.  */
   if (memaddr <= 0)
-    last_map_symbol = -1;
+    pd->last_map_symbol = -1;
 
   /* If the last stop offset is different from the current one, then
      don't use the last_map_symbol to search.  We usually reset the
      info->stop_offset when handling a new section.  */
-  from_last_map_symbol = (last_map_symbol >= 0
-			  && info->stop_offset == last_stop_offset);
+  from_last_map_symbol = (pd->last_map_symbol >= 0
+			  && info->stop_offset == pd->last_stop_offset);
 
   /* Start scanning from wherever we finished last time, or the start
      of the function.  */
-  n = from_last_map_symbol ? last_map_symbol : info->symtab_pos + 1;
+  n = from_last_map_symbol ? pd->last_map_symbol : info->symtab_pos + 1;
 
   /* Find the suitable mapping symbol to dump.  */
   for (; n < info->symtab_size; n++)
@@ -1182,7 +1180,7 @@  riscv_search_mapping_symbol (bfd_vma memaddr,
      can pick up a text mapping symbol of a preceeding section.  */
   if (!found)
     {
-      n = from_last_map_symbol ? last_map_symbol : info->symtab_pos;
+      n = from_last_map_symbol ? pd->last_map_symbol : info->symtab_pos;
 
       for (; n >= 0; n--)
 	{
@@ -1221,7 +1219,7 @@  riscv_search_mapping_symbol (bfd_vma memaddr,
 	      /* The next mapping symbol has been found, and it represents the
 		 boundary of this mapping symbol.  */
 	      found_next = true;
-	      last_map_symbol_boundary = addr;
+	      pd->last_map_symbol_boundary = addr;
 	      break;
 	    }
 	}
@@ -1229,12 +1227,13 @@  riscv_search_mapping_symbol (bfd_vma memaddr,
       /* No further mapping symbol has been found, indicating that the boundary
 	 of the current mapping symbol is the end of this section.  */
       if (!found_next)
-	last_map_symbol_boundary = info->section->vma + info->section->size;
+	pd->last_map_symbol_boundary = info->section->vma
+				       + info->section->size;
     }
 
   /* Save the information for next use.  */
-  last_map_symbol = symbol;
-  last_stop_offset = info->stop_offset;
+  pd->last_map_symbol = symbol;
+  pd->last_stop_offset = info->stop_offset;
 
   return mstate;
 }
@@ -1245,17 +1244,18 @@  static bfd_vma
 riscv_data_length (bfd_vma memaddr,
 		   disassemble_info *info)
 {
+  struct riscv_private_data *pd = info->private_data;
   bfd_vma length;
   bool found = false;
 
   length = 4;
   if (info->symtab_size != 0
       && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour
-      && last_map_symbol >= 0)
+      && pd->last_map_symbol >= 0)
     {
       int n;
       enum riscv_seg_mstate m = MAP_NONE;
-      for (n = last_map_symbol + 1; n < info->symtab_size; n++)
+      for (n = pd->last_map_symbol + 1; n < info->symtab_size; n++)
 	{
 	  bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
 	  if (addr > memaddr
@@ -1344,7 +1344,6 @@  static bool
 riscv_init_disasm_info (struct disassemble_info *info)
 {
   int i;
-
   struct riscv_private_data *pd =
 	xcalloc (1, sizeof (struct riscv_private_data));
   pd->gp = 0;
@@ -1352,8 +1351,8 @@  riscv_init_disasm_info (struct disassemble_info *info)
   for (i = 0; i < (int) ARRAY_SIZE (pd->hi_addr); i++)
     pd->hi_addr[i] = -1;
   pd->to_print_addr = false;
-  pd->has_gp = false;
 
+  pd->has_gp = false;
   for (i = 0; i < info->symtab_size; i++)
     {
       asymbol *sym = info->symtab[i];
@@ -1364,6 +1363,50 @@  riscv_init_disasm_info (struct disassemble_info *info)
 	}
     }
 
+  pd->xlen = 0;
+  pd->default_isa_spec = ISA_SPEC_CLASS_DRAFT - 1;
+  pd->default_priv_spec = PRIV_SPEC_CLASS_NONE;
+
+  pd->riscv_rps_dis.subset_list = xcalloc (1, sizeof (riscv_parse_subset_t));
+  pd->riscv_rps_dis.error_handler = opcodes_error_handler;
+  pd->riscv_rps_dis.xlen = &pd->xlen;
+  pd->riscv_rps_dis.isa_spec = &pd->default_isa_spec;
+  pd->riscv_rps_dis.check_unknown_prefixed_ext = false;
+  const char *default_arch = "rv64gc";
+  if (info->section != NULL)
+    {
+      bfd *abfd = info->section->owner;
+      if (abfd && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+	{
+	  const char *sec_name =
+		get_elf_backend_data (abfd)->obj_attrs_section;
+	  if (bfd_get_section_by_name (abfd, sec_name) != NULL)
+	    {
+	      obj_attribute *attr = elf_known_obj_attributes_proc (abfd);
+	      unsigned int Tag_a = Tag_RISCV_priv_spec;
+	      unsigned int Tag_b = Tag_RISCV_priv_spec_minor;
+	      unsigned int Tag_c = Tag_RISCV_priv_spec_revision;
+	      riscv_get_priv_spec_class_from_numbers (attr[Tag_a].i,
+						      attr[Tag_b].i,
+						      attr[Tag_c].i,
+						      &pd->default_priv_spec);
+	      default_arch = attr[Tag_RISCV_arch].s;
+	    }
+	}
+    }
+  riscv_release_subset_list (pd->riscv_rps_dis.subset_list);
+  riscv_parse_subset (&pd->riscv_rps_dis, default_arch);
+
+  pd->last_map_symbol = -1;
+  pd->last_stop_offset = 0;
+  pd->last_map_symbol_boundary = 0;
+  pd->last_map_state = MAP_NONE;
+  pd->last_map_section = NULL;
+  pd->riscv_gpr_names = NULL;
+  pd->riscv_fpr_names = NULL;
+  pd->no_aliases = false;
+  pd->all_ext = false;
+
   info->private_data = pd;
   return true;
 }
@@ -1398,21 +1441,21 @@  print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
   int (*riscv_disassembler) (bfd_vma, insn_t, const bfd_byte *,
 			     struct disassemble_info *);
 
+  if (info->private_data == NULL && !riscv_init_disasm_info (info))
+    return -1;
+
   if (info->disassembler_options != NULL)
     {
-      parse_riscv_dis_options (info->disassembler_options);
+      parse_riscv_dis_options (info->disassembler_options, info);
       /* Avoid repeatedly parsing the options.  */
       info->disassembler_options = NULL;
     }
-  else if (riscv_gpr_names == NULL)
-    set_default_riscv_dis_options ();
-
-  if (info->private_data == NULL && !riscv_init_disasm_info (info))
-    return -1;
+  else if (((struct riscv_private_data *) info->private_data)->riscv_gpr_names == NULL)
+    set_default_riscv_dis_options (info);
 
   mstate = riscv_search_mapping_symbol (memaddr, info);
   /* Save the last mapping state.  */
-  last_map_state = mstate;
+  ((struct riscv_private_data *) info->private_data)->last_map_state = mstate;
 
   /* Set the size to dump.  */
   if (mstate == MAP_DATA
@@ -1466,33 +1509,6 @@  print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
   return (*riscv_disassembler) (memaddr, insn, packet, info);
 }
 
-disassembler_ftype
-riscv_get_disassembler (bfd *abfd)
-{
-  const char *default_arch = "rv64gc";
-
-  if (abfd && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
-    {
-      const char *sec_name = get_elf_backend_data (abfd)->obj_attrs_section;
-      if (bfd_get_section_by_name (abfd, sec_name) != NULL)
-	{
-	  obj_attribute *attr = elf_known_obj_attributes_proc (abfd);
-	  unsigned int Tag_a = Tag_RISCV_priv_spec;
-	  unsigned int Tag_b = Tag_RISCV_priv_spec_minor;
-	  unsigned int Tag_c = Tag_RISCV_priv_spec_revision;
-	  riscv_get_priv_spec_class_from_numbers (attr[Tag_a].i,
-						  attr[Tag_b].i,
-						  attr[Tag_c].i,
-						  &default_priv_spec);
-	  default_arch = attr[Tag_RISCV_arch].s;
-	}
-    }
-
-  riscv_release_subset_list (&riscv_subsets);
-  riscv_parse_subset (&riscv_rps_dis, default_arch);
-  return print_insn_riscv;
-}
-
 /* Prevent use of the fake labels that are generated as part of the DWARF
    and for relaxable relocations in the assembler.  */
 
@@ -1665,5 +1681,7 @@  with the -M switch (multiple options should be separated by commas):\n"));
 
 void disassemble_free_riscv (struct disassemble_info *info ATTRIBUTE_UNUSED)
 {
-  riscv_release_subset_list (&riscv_subsets);
+  struct riscv_private_data *pd = info->private_data;
+  if (pd)
+    riscv_release_subset_list (pd->riscv_rps_dis.subset_list);
 }