From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-sender-0.a4lg.com (mail-sender-0.a4lg.com [IPv6:2401:2500:203:30b:4000:6bfe:4757:0]) by sourceware.org (Postfix) with ESMTPS id E6C94385E012 for ; Tue, 1 Feb 2022 13:52:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E6C94385E012 From: Tsukasa OI To: Tsukasa OI Cc: binutils@sourceware.org Subject: [RFC PATCH 2/2] RISC-V: Validate Zdinx/Zqinx register pairs Date: Tue, 1 Feb 2022 22:52:45 +0900 Message-Id: <77833bfe4b6f33b6fc35ee7d248e857fe9dca027.1643723532.git.research_trasio@irq.a4lg.com> In-Reply-To: References: Mime-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-13.3 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_NONE, SPF_PASS, TO_EQ_FM_DIRECT_MX, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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-List-Received-Date: Tue, 01 Feb 2022 13:52:55 -0000 This commit adds floating point register validation on Zdinx/Zqinx extensions enabled. Assembler only. gas/ChangeLog: * config/tc-riscv.c (reg_lookup_fp): New function to look up and validate floating point register operands. (riscv_ip): Use `reg_lookup_fp' to look up FPRs. --- gas/config/tc-riscv.c | 65 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index 25908597436..bfb2f94b061 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -2137,6 +2137,61 @@ riscv_handle_implicit_zero_offset (expressionS *ep, const char *s) return false; } +/* Look up floating point register and validate against operand type. + This function checks invalid register such as "x1" on a FP64 operand + in RV32_Zdinx. */ + +static bool +reg_lookup_fp (char operand, char **str, + struct riscv_opcode *insn, unsigned int *regno) +{ + bool is_zfinx = riscv_subset_supports (&riscv_rps_as, "zfinx"); + unsigned int float_size = insn->pinfo & INSN_FLOAT; + if (!reg_lookup (str, (is_zfinx ? RCLASS_GPR : RCLASS_FPR), regno)) + return false; + if (!is_zfinx || (insn->pinfo & INSN_FLOAT_VAR)) + return true; + /* Source operand for fcvt.[FLOAT].[FLOAT] instructions requires + different float_size than the destination. */ + if ((insn->pinfo & INSN_FCVT_F_F) && operand == 'S') + float_size = (insn->pinfo & INSN_FCVT_SRC) >> INSN_FCVT_SRC_SHIFT; + /* Check register index for Zdinx/Zqinx. */ + switch (float_size) + { + case INSN_FLOAT_S: + return true; + case INSN_FLOAT_D: + switch (xlen) + { + case 32: + if (*regno & 0x01) + break; + return true; + default: + return true; + } + break; + case INSN_FLOAT_Q: + switch (xlen) + { + case 32: + if (*regno & 0x03) + break; + return true; + case 64: + if (*regno & 0x01) + break; + return true; + default: + return true; + } + break; + default: + return false; + } + return false; +} + /* All RISC-V CSR instructions belong to one of these classes. */ enum csr_insn_type { @@ -2518,19 +2573,19 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr, case 'a': goto jump; case 'S': /* Floating-point RS1 x8-x15. */ - if (!reg_lookup (&asarg, RCLASS_FPR, ®no) + if (!reg_lookup_fp(*oparg, &asarg, insn, ®no) || !(regno >= 8 && regno <= 15)) break; INSERT_OPERAND (CRS1S, *ip, regno % 8); continue; case 'D': /* Floating-point RS2 x8-x15. */ - if (!reg_lookup (&asarg, RCLASS_FPR, ®no) + if (!reg_lookup_fp(*oparg, &asarg, insn, ®no) || !(regno >= 8 && regno <= 15)) break; INSERT_OPERAND (CRS2S, *ip, regno % 8); continue; case 'T': /* Floating-point RS2. */ - if (!reg_lookup (&asarg, RCLASS_FPR, ®no)) + if (!reg_lookup_fp(*oparg, &asarg, insn, ®no)) break; INSERT_OPERAND (CRS2, *ip, regno); continue; @@ -2897,9 +2952,7 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr, case 'T': /* Floating point RS2. */ case 'U': /* Floating point RS1 and RS2. */ case 'R': /* Floating point RS3. */ - if (reg_lookup (&asarg, - (riscv_subset_supports (&riscv_rps_as, "zfinx") - ? RCLASS_GPR : RCLASS_FPR), ®no)) + if (reg_lookup_fp(*oparg, &asarg, insn, ®no)) { char c = *oparg; if (*asarg == ' ') -- 2.32.0