From patchwork Mon Nov 28 04:43:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tsukasa OI X-Patchwork-Id: 26506 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp5434540wrr; Sun, 27 Nov 2022 20:53:13 -0800 (PST) X-Google-Smtp-Source: AA0mqf4Tocy09Bq5QlJ/88jr3dFtrVeaoqITHUDFQ7dBQl1iNFEJSxiSmstwm6u/ip+fNKiH3yig X-Received: by 2002:a17:906:c35a:b0:78d:2af:a818 with SMTP id ci26-20020a170906c35a00b0078d02afa818mr31003465ejb.675.1669611193264; Sun, 27 Nov 2022 20:53:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669611193; cv=none; d=google.com; s=arc-20160816; b=EChlmLaykC01KQRxUTFyNKQxGWKo96QU6hmYCUT32wohinNa/KBTuBdsIB1bs5ci5Q Zh4CgG5LE42/8PpmdiqA8CNM4oaVajf8brz5B2/ux1eLpzylqTsslV0YbhM93GeAcRtn uJqChEgis/QCaA7m2z/+8U0DZ1sEQh5DUzEyoecJPmhLq49JIHGWyVVFADXLD+fb+N5W dgYpMaiib+Uu85HcHllj26C+EwwubxCdKZPFteslRfyvjFFvLWVPc7bC73TkrYJCcJsl oJYjNN/GZjYzeYXIdNk7tWRCK/+zWWhk7IugIFfSPw/VFkFSEHvXQuBxJbVGSZd6O9oI DEKg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:dmarc-filter:delivered-to :dkim-signature:dkim-filter; bh=eJTBxZJ07t9eLkFU54I2JG47TRjQviaHdqcrHVUVufc=; b=CHLSKLLavl4SGtlOEhx57bOZwASy6X3I/5XI2Krksz3OxAvA5xiYWWwCkH886LMi44 XmsvFvMOz1MKP7zE8pH+d/Yn2pHbY8xnpfyUbycvsca3f2pH4AiG21gtu4P/PsIaG4oD XA6E73YYjskxLeQqsINY1gkAojPd6kUvGlHPc5qewFH3yz/m9M1BYoOnDQ0E97yLII0p 4GB1U6h9Zl4hlcVJ96DmSKA/fafcFSworOZB5QHHRA2av3ETjPl7K+vrBRJUxvYjSuEf JgXx5it9XgXpBsN7QDPaqSdbJDkzSyBapy6Pzub0EKWDOzsgEyHlBP4f0IwouhYG45Ir yTHw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=k3JCP9ZB; spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=sourceware.org Received: from sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id ji9-20020a170907980900b007a46fa50b26si10400365ejc.517.2022.11.27.20.53.13 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 27 Nov 2022 20:53:13 -0800 (PST) Received-SPF: pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=k3JCP9ZB; spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 49364395B06F for ; Mon, 28 Nov 2022 04:48:43 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 49364395B06F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1669610923; bh=eJTBxZJ07t9eLkFU54I2JG47TRjQviaHdqcrHVUVufc=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=k3JCP9ZB0fY5BhlJ6o7hts3sdKSg2A3XlfHUab7XyFnCDdVY/icUJAAF2KiTiXHK6 dYD3YwHcNCkHQbPL35HdoUBsH15xRS7SINbDnbfaEvvvdxvyJyVVx8QdTcbIE1lwya 09slZALczFCDR6sbJQlmLPIR7rjOkvnucsbbOwzI= X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-sender-0.a4lg.com (mail-sender.a4lg.com [153.120.152.154]) by sourceware.org (Postfix) with ESMTPS id 4712A3888C45 for ; Mon, 28 Nov 2022 04:45:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 4712A3888C45 Received: from [127.0.0.1] (localhost [127.0.0.1]) by mail-sender-0.a4lg.com (Postfix) with ESMTPSA id 9A539300089; Mon, 28 Nov 2022 04:45:39 +0000 (UTC) To: Tsukasa OI , Nelson Chu , Kito Cheng , Palmer Dabbelt Cc: binutils@sourceware.org Subject: [PATCH v2 09/11] RISC-V: Reorganize disassembler state initialization Date: Mon, 28 Nov 2022 04:43:44 +0000 Message-Id: In-Reply-To: References: Mime-Version: 1.0 X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Tsukasa OI via Binutils From: Tsukasa OI Reply-To: Tsukasa OI Errors-To: binutils-bounces+ouuuleilei=gmail.com@sourceware.org Sender: "Binutils" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749536954487615344?= X-GMAIL-MSGID: =?utf-8?q?1750714226563932149?= From: Tsukasa OI The current disassembler repeatedly checks current state per instruction: - Whether riscv_gpr_names is initialized to a non-NULL value - Whether the Zfinx extension is available - Whether the hash table is initialized ... but they are not frequently changed. riscv_gpr_names is initialized to a non-NULL value when - The first disassembler option is specified, or - Not initialized with disassembler options (in the first print_insn_riscv function call). We can safely initialize the default disassembler options prior to the print_insn_riscv function call and this per-instruction checking of riscv_gpr_names can be safely removed. The opcode hash table initialization will be taken care with a later commit. To group disassembler state initialization, this commit utilizes the disassemble_init_for_target function. As a side effect, this will also fix a potential issue when disassembler options is set and then unset on GDB. This idea is based on opcodes/ppc-dis.c and opcodes/wasm32-dis.c. New callback function init_riscv_dis_state_for_arch_and_options is called when either the architecture string or an option is possibly changed. We can now group the disassembler state initialization together. It makes state initialization clearer and makes further changes easier. In performance perspective, this commit has various effects (-5% to 6%). However, this commit makes implementing large optimizations easier as well as "RISC-V: Split match/print steps on disassembler". include/ChangeLog: * dis-asm.h (disassemble_init_riscv): Add declaration of disassemble_init_riscv. opcodes/ChangeLog: * disassemble.c (disassemble_init_for_target): Call disassemble_init_riscv to group state initialization together. * riscv-dis.c (xlen_by_mach, xlen_by_elf): New variables to store environment-inferred XLEN. (is_numeric): New. Instead of directly setting riscv_{gpr,fpr}_names, use this to store an option. (update_riscv_dis_xlen): New function to set actual XLEN from xlen_by_mach and xlen_by_elf variables. (init_riscv_dis_state_for_arch_and_options): New callback function called when either the architecture or an option is changed. Set riscv_{gpr,fpr}_names here. (set_default_riscv_dis_options): Initialize is_numeric instead of riscv_gpr_names and riscv_fpr_names. (parse_riscv_dis_option_without_args): When the "numeric" option is specified, write to is_numeric instead of register names. (parse_riscv_dis_options): Suppress setting the default options here and let disassemble_init_riscv to initialize them. (riscv_disassemble_insn): Move probing Zfinx and setting XLEN portions to init_riscv_dis_state_for_arch_and_options and update_riscv_dis_xlen. (riscv_get_map_state): If a mapping symbol with ISA string is suitable, call init_riscv_dis_state_for_arch_and_options function to update disassembler state. (print_insn_riscv): Update XLEN only if we haven't guessed correct XLEN for the disassembler. Stop checking disassembler options for every instruction and let disassemble_init_riscv to parse options. (riscv_get_disassembler): Call init_riscv_dis_state_for_arch_and_options because the architecture string is updated here. (disassemble_init_riscv): New function to initialize the structure, reset/guess correct XLEN and reset/parse disassembler options. --- include/dis-asm.h | 1 + opcodes/disassemble.c | 2 +- opcodes/riscv-dis.c | 112 +++++++++++++++++++++++++++++------------- 3 files changed, 79 insertions(+), 36 deletions(-) diff --git a/include/dis-asm.h b/include/dis-asm.h index 4921c0407102..11537b432ff0 100644 --- a/include/dis-asm.h +++ b/include/dis-asm.h @@ -393,6 +393,7 @@ extern bool arm_symbol_is_valid (asymbol *, struct disassemble_info *); extern bool csky_symbol_is_valid (asymbol *, struct disassemble_info *); extern bool riscv_symbol_is_valid (asymbol *, struct disassemble_info *); extern void disassemble_init_powerpc (struct disassemble_info *); +extern void disassemble_init_riscv (struct disassemble_info *); extern void disassemble_init_s390 (struct disassemble_info *); extern void disassemble_init_wasm32 (struct disassemble_info *); extern void disassemble_init_nds32 (struct disassemble_info *); diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c index 0a8f2da629f3..704fb476ea9f 100644 --- a/opcodes/disassemble.c +++ b/opcodes/disassemble.c @@ -717,7 +717,7 @@ disassemble_init_for_target (struct disassemble_info * info) #endif #ifdef ARCH_riscv case bfd_arch_riscv: - info->symbol_is_valid = riscv_symbol_is_valid; + disassemble_init_riscv (info); info->created_styled_output = true; break; #endif diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index c74827ed19df..174b6e180543 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -35,6 +35,12 @@ /* Current XLEN for the disassembler. */ static unsigned xlen = 0; +/* XLEN as inferred by the machine architecture. */ +static unsigned xlen_by_mach = 0; + +/* XLEN as inferred by ELF header. */ +static unsigned xlen_by_elf = 0; + /* Default ISA specification version (constant as of now). */ static enum riscv_spec_class default_isa_spec = ISA_SPEC_CLASS_DRAFT - 1; @@ -72,6 +78,48 @@ static const char * const *riscv_fpr_names; /* If set, disassemble as most general instruction. */ static bool no_aliases = false; + +/* If set, disassemble with numeric register names. */ +static bool is_numeric = false; + + +/* Guess and update current XLEN. */ + +static void +update_riscv_dis_xlen (struct disassemble_info *info) +{ + /* Set XLEN with following precedence rules: + 1. BFD machine architecture set by either: + a. -m riscv:rv[32|64] option (GDB: set arch riscv:rv[32|64]) + b. ELF class in actual ELF header (only on RISC-V ELF) + This is only effective if XLEN-specific BFD machine architecture is + chosen. If XLEN-neutral (like riscv), BFD machine architecture is + ignored on XLEN selection. + 2. ELF class in dummy ELF header. */ + if (xlen_by_mach != 0) + xlen = xlen_by_mach; + else if (xlen_by_elf != 0) + xlen = xlen_by_elf; + else if (info != NULL && info->section != NULL) + { + Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner); + xlen = xlen_by_elf = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32; + } +} + +/* Initialization (for arch and options). */ + +static void +init_riscv_dis_state_for_arch_and_options (void) +{ + /* Set GPR register names to disassemble. */ + riscv_gpr_names = is_numeric ? riscv_gpr_names_numeric : riscv_gpr_names_abi; + /* Set FPR register names to disassemble. */ + riscv_fpr_names + = !riscv_subset_supports (&riscv_rps_dis, "zfinx") + ? (is_numeric ? riscv_fpr_names_numeric : riscv_fpr_names_abi) + : riscv_gpr_names; +} /* Set default RISC-V disassembler options. */ @@ -79,9 +127,8 @@ static bool no_aliases = false; static void set_default_riscv_dis_options (void) { - riscv_gpr_names = riscv_gpr_names_abi; - riscv_fpr_names = riscv_fpr_names_abi; no_aliases = false; + is_numeric = false; } /* Parse RISC-V disassembler option (without arguments). */ @@ -92,10 +139,7 @@ parse_riscv_dis_option_without_args (const char *option) if (strcmp (option, "no-aliases") == 0) no_aliases = true; else if (strcmp (option, "numeric") == 0) - { - riscv_gpr_names = riscv_gpr_names_numeric; - riscv_fpr_names = riscv_fpr_names_numeric; - } + is_numeric = true; else return false; return true; @@ -163,8 +207,6 @@ parse_riscv_dis_options (const char *opts_in) { char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts; - set_default_riscv_dis_options (); - for ( ; opt_end != NULL; opt = opt_end + 1) { if ((opt_end = strchr (opt, ',')) != NULL) @@ -708,25 +750,6 @@ riscv_disassemble_insn (bfd_vma memaddr, matched_op = NULL; op = riscv_hash[OP_HASH_IDX (word)]; - /* If XLEN is not known, get its value from the ELF class. */ - if (info->mach == bfd_mach_riscv64) - xlen = 64; - else if (info->mach == bfd_mach_riscv32) - 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; - } - - /* If arch has the Zfinx extension, replace FPR with GPR. */ - if (riscv_subset_supports (&riscv_rps_dis, "zfinx")) - riscv_fpr_names = riscv_gpr_names; - else - riscv_fpr_names = riscv_gpr_names == riscv_gpr_names_abi - ? riscv_fpr_names_abi - : riscv_fpr_names_numeric; - for (; op && op->name; op++) { /* Does the opcode match? */ @@ -869,6 +892,7 @@ riscv_get_map_state (int n, { riscv_release_subset_list (&riscv_subsets); riscv_parse_subset (&riscv_rps_dis, arch); + init_riscv_dis_state_for_arch_and_options (); } return true; } @@ -1067,14 +1091,9 @@ 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->disassembler_options != NULL) - { - parse_riscv_dis_options (info->disassembler_options); - /* Avoid repeatedly parsing the options. */ - info->disassembler_options = NULL; - } - else if (riscv_gpr_names == NULL) - set_default_riscv_dis_options (); + /* Guess and update XLEN if we haven't determined it yet. */ + if (xlen == 0) + update_riscv_dis_xlen (info); mstate = riscv_search_mapping_symbol (memaddr, info); @@ -1136,9 +1155,32 @@ riscv_get_disassembler (bfd *abfd) riscv_release_subset_list (&riscv_subsets); riscv_parse_subset (&riscv_rps_dis, default_arch); + init_riscv_dis_state_for_arch_and_options (); return print_insn_riscv; } +/* Initialize disassemble_info and parse options. */ + +void +disassemble_init_riscv (struct disassemble_info *info) +{ + info->symbol_is_valid = riscv_symbol_is_valid; + /* Clear previous XLEN and guess by mach. */ + xlen = 0; + xlen_by_mach = 0; + xlen_by_elf = 0; + if (info->mach == bfd_mach_riscv64) + xlen_by_mach = 64; + else if (info->mach == bfd_mach_riscv32) + xlen_by_mach = 32; + update_riscv_dis_xlen (info); + /* Parse disassembler options. */ + set_default_riscv_dis_options (); + if (info->disassembler_options != NULL) + parse_riscv_dis_options (info->disassembler_options); + init_riscv_dis_state_for_arch_and_options (); +} + /* Prevent use of the fake labels that are generated as part of the DWARF and for relaxable relocations in the assembler. */