From patchwork Mon Feb 26 14:22:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bhushan Attarde X-Patchwork-Id: 86379 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 16CED38582AC for ; Mon, 26 Feb 2024 14:23:49 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mx08-00376f01.pphosted.com (mx08-00376f01.pphosted.com [91.207.212.86]) by sourceware.org (Postfix) with ESMTPS id EBB693858C55 for ; Mon, 26 Feb 2024 14:23:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org EBB693858C55 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=imgtec.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=imgtec.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org EBB693858C55 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=91.207.212.86 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1708957386; cv=none; b=ShzMUn6Ogb/9Xa1Rz41Lk8Ki2l9qZ40rNOd1d+MCHZjZ3JLZxT71Lp5xkV+cN1NPa6EQsLEA5rQj9x0lGj8j1G51WufErAawoxOh3ecwubLbdXygkSLEdIuEYTcyyODUXTeH9U4cTMfHTYAe56Sew5GFTmiWMX9/eIbV47lFncw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1708957386; c=relaxed/simple; bh=5E/UTWrOZZP2dvQnbfFMmID1S1ebiRK+R+FzKg2fYmc=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=wW565lugU4v8+I2IFbuQ/WNb1cAijnBEl3PFNPoZ5O6pym19BRTteJnO5EVmDCGzTXeS6yYlFOH0PyV0O4sHxPpgMykAu4lNTa7yiT2VD/zmZL2V+DjGd+LVsI8pkoRdmM8rK7O2AKyHVUa3ZWLQsTaCi58pR5wyApz8dx8WuI8= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from pps.filterd (m0168888.ppops.net [127.0.0.1]) by mx08-00376f01.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 41Q8CPdI013671; Mon, 26 Feb 2024 14:22:50 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=imgtec.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= dk201812; bh=N/FcUTpJ098zIX9GuyoR99MMDIecEv9slbxJGY8GhIM=; b=mzU zyk/uQgcpyvcQU6IwcSE8wQwU3KQljREl5BHJzCnZQTBO7u6Z9Oilh91lbGcr992 FyLa5UmwSu3JiDPe8Q/zW2eLG6SanwXpl+HRxYerpD2ege/MeWGf2QaVCdwqFtGd SqCIfx5csylPrRCDqn7HOFr30oS57vOc/MlqalAHjZvaE1imf2/1zpowq1I6nvCf +3nU5fFYQ+9BmoTbaVZIJXWAlAznNGeS+fjVPO6c4+/A2oIWdWIAqcOS/nPsG2Wv sWu+t1Csu4AOT4kH/z4prAK4F7Ujg2lgsaQLxz1yz5ItYe0bd0iEgwc6NXv7Jwxt rANnyanpHNG1JGUsfkA== Received: from hhmail05.hh.imgtec.org ([217.156.249.195]) by mx08-00376f01.pphosted.com (PPS) with ESMTPS id 3wf7kssr3e-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Mon, 26 Feb 2024 14:22:50 +0000 (GMT) Received: from hhbattarde.hh.imgtec.org (10.100.136.78) by HHMAIL05.hh.imgtec.org (10.100.10.120) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 26 Feb 2024 14:22:48 +0000 From: To: CC: , , , Bhushan Attarde Subject: [PATCH 01/11] sim: riscv: Add single precision floating-point load-store, move, compare and classify instructions Date: Mon, 26 Feb 2024 14:22:24 +0000 Message-ID: <20240226142234.1628932-2-bhushan.attarde@imgtec.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240226142234.1628932-1-bhushan.attarde@imgtec.com> References: <20240226142234.1628932-1-bhushan.attarde@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [10.100.136.78] X-ClientProxiedBy: HHMAIL05.hh.imgtec.org (10.100.10.120) To HHMAIL05.hh.imgtec.org (10.100.10.120) X-EXCLAIMER-MD-CONFIG: 15a78312-3e47-46eb-9010-2e54d84a9631 X-Proofpoint-GUID: 3D-hVF74KzcPSJaA0OjEv_AvCqd7ESRz X-Proofpoint-ORIG-GUID: 3D-hVF74KzcPSJaA0OjEv_AvCqd7ESRz X-Spam-Status: No, score=-12.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org From: Bhushan Attarde Added simulation of following single precision floating-point instructions flw, fsw, fmv.x.w, fmv.w.x, fsgnj.s, feq.s, flt.s, fle.s and fclass.s. Added test files s-fp-compare.s, s-fp-load-store.s and s-fp-sign-inject.s in sim/testsuite/riscv/ to test these instructions. --- sim/riscv/model_list.def | 4 + sim/riscv/sim-main.c | 214 +++++++++++++++++++++++++ sim/testsuite/riscv/s-fp-compare.s | 75 +++++++++ sim/testsuite/riscv/s-fp-load-store.s | 62 +++++++ sim/testsuite/riscv/s-fp-sign-inject.s | 52 ++++++ 5 files changed, 407 insertions(+) create mode 100644 sim/testsuite/riscv/s-fp-compare.s create mode 100644 sim/testsuite/riscv/s-fp-load-store.s create mode 100644 sim/testsuite/riscv/s-fp-sign-inject.s diff --git a/sim/riscv/model_list.def b/sim/riscv/model_list.def index b83557e5539..265b1714faf 100644 --- a/sim/riscv/model_list.def +++ b/sim/riscv/model_list.def @@ -5,6 +5,8 @@ M(IMA) M(IA) M(GC) M(IC) +M(IF) +M(ID) M(IMC) M(IMAC) M(IAC) @@ -13,6 +15,8 @@ M(EM) M(EMA) M(EA) M(EC) +M(EF) +M(ED) M(EMC) M(EMAC) M(EAC) diff --git a/sim/riscv/sim-main.c b/sim/riscv/sim-main.c index adff99921c6..d3a07585944 100644 --- a/sim/riscv/sim-main.c +++ b/sim/riscv/sim-main.c @@ -24,6 +24,7 @@ /* This must come before any other includes. */ #include "defs.h" +#include #include #include @@ -64,6 +65,17 @@ static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1]; } \ } while (0) +#define FCSR_NX 0x1 /* Inexact. */ +#define FCSR_UF 0x2 /* Underflow. */ +#define FCSR_OF 0x4 /* Overflow. */ +#define FCSR_DZ 0x8 /* Divide by zero. */ +#define FCSR_NV 0x10 /* Invalid Operation. */ + +#define FEQ 1 +#define FLT 2 +#define FLE 3 +#define FCLASS 4 + static INLINE void store_rd (SIM_CPU *cpu, int rd, unsigned_word val) { @@ -76,6 +88,16 @@ store_rd (SIM_CPU *cpu, int rd, unsigned_word val) } } +/* Store a value into floating point register. */ +static INLINE void +store_fp (SIM_CPU *cpu, int rd, unsigned_word val) +{ + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + + riscv_cpu->fpregs[rd] = val; + TRACE_REG (cpu, rd); +} + static INLINE unsigned_word fetch_csr (SIM_CPU *cpu, const char *name, int csr, unsigned_word *reg) { @@ -682,6 +704,195 @@ mulhsu (int64_t a, uint64_t b) return negate ? ~res + (a * b == 0) : res; } +/* Handle single precision floating point compare instructions. */ +static void +float32_compare (SIM_CPU *cpu, int rd, int rs1, int rs2, int flags) +{ + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + float a, b = .0f; + uint32_t result = 0, exception = 0, sign = 0, bit_pos; + uint32_t rs1_bits, rs2_bits; + const char *rd_name = riscv_gpr_names_abi[rd]; + const char *frs1_name = riscv_fpr_names_abi[rs1]; + const char *frs2_name = riscv_fpr_names_abi[rs2]; + + rs1_bits = (uint32_t) riscv_cpu->fpregs[rs1]; + memcpy (&a, &rs1_bits, sizeof (a)); + + if (flags != FCLASS) + { + rs2_bits = (uint32_t) riscv_cpu->fpregs[rs2]; + memcpy (&b, &rs2_bits, sizeof (b)); + } + + switch (flags) + { + case FEQ: + TRACE_INSN (cpu, "feq.s %s, %s, %s;", rd_name, frs1_name, frs2_name); + if (__isnanf (a) || __isnanf (b)) + { + result = 0; + if (__issignalingf (a) || __issignalingf (b)) + exception = 1; + } + else + result = (a == b); + break; + case FLT: + TRACE_INSN (cpu, "flt.s %s, %s, %s;", rd_name, frs1_name, frs2_name); + if (__isnanf (a) || __isnanf (b)) + { + result = 0; + exception = 1; + } + else + result = (a < b); + break; + case FLE: + TRACE_INSN (cpu, "fle.s %s, %s, %s;", rd_name, frs1_name, frs2_name); + if (__isnanf (a) || __isnanf (b)) + { + result = 0; + exception = 1; + } + else + result = (a <= b); + break; + case FCLASS: + TRACE_INSN (cpu, "fclass.s %s, %s;", rd_name, frs1_name); + bit_pos = 0; + exception = 0; + result = riscv_cpu->regs[rd]; + sign = __signbitf (a); + if (__isinff (a)) + { + if (sign) + bit_pos = 0; /* -INF. */ + else + bit_pos = 7; /* +INF. */ + } + else if (fpclassify (a) == FP_SUBNORMAL) + { + if (sign) + bit_pos = 2; /* -SUBNORMAL. */ + else + bit_pos = 5; /* +SUBNORMAL. */ + } + else if (fpclassify (a) == FP_ZERO) + { + if (sign) + bit_pos = 3; /* -ZERO. */ + else + bit_pos = 4; /* +ZERO. */ + } + else if (__issignalingf (a)) + bit_pos = 8; /* signaling NaN. */ + else if (__isnanf (a)) + bit_pos = 9; /* quiet NaN. */ + else + { + if (sign) + bit_pos = 1; /* -NORMAL. */ + else + bit_pos = 6; /* +NORMAL. */ + } + result |= (1 << bit_pos); + break; + } + + store_rd (cpu, rd, result); + + if (exception) + { + riscv_cpu->csr.fcsr |= FCSR_NV; + riscv_cpu->csr.fflags |= FCSR_NV; + TRACE_REGISTER (cpu, "wrote CSR fcsr |= NV"); + } +} + +/* Simulate single precision floating point instructions. */ +static sim_cia +execute_f (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op) +{ + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + SIM_DESC sd = CPU_STATE (cpu); + int rd = (iw >> OP_SH_RD) & OP_MASK_RD; + int rs1 = (iw >> OP_SH_RS1) & OP_MASK_RS1; + int rs2 = (iw >> OP_SH_RS2) & OP_MASK_RS2; + const char *frd_name = riscv_fpr_names_abi[rd]; + const char *rd_name = riscv_gpr_names_abi[rd]; + const char *frs1_name = riscv_fpr_names_abi[rs1]; + const char *frs2_name = riscv_fpr_names_abi[rs2]; + const char *rs1_name = riscv_gpr_names_abi[rs1]; + signed_word i_imm = EXTRACT_ITYPE_IMM (iw); + signed_word s_imm = EXTRACT_STYPE_IMM (iw); + int is_32bit = (RISCV_XLEN (cpu) == 32); + + sim_cia pc = riscv_cpu->pc + 4; + + switch (op->match) + { + case MATCH_FLW: + TRACE_INSN (cpu, "flw %s, %" PRIiTW "(%s);", + frd_name, i_imm, rs1_name); + store_fp (cpu, rd, sim_core_read_unaligned_4 (cpu, riscv_cpu->pc, + read_map, riscv_cpu->regs[rs1] + i_imm)); + break; + case MATCH_FSW: + TRACE_INSN (cpu, "fsw %s, %" PRIiTW "(%s);", + frs2_name, s_imm, rs1_name); + sim_core_write_unaligned_4 (cpu, riscv_cpu->pc, write_map, + riscv_cpu->regs[rs1] + s_imm, + riscv_cpu->fpregs[rs2]); + break; + case MATCH_FMV_X_S: + TRACE_INSN (cpu, "fmv.x.w %s, %s;", rd_name, frs1_name); + if (is_32bit) + store_rd (cpu, rd, riscv_cpu->fpregs[rs1]); + else + { + uint64_t f64bits; + f64bits = (uint64_t) ((uint32_t) riscv_cpu->fpregs[rs1]); + if (f64bits & 0x80000000) + f64bits = (uint64_t) (0xffffffff00000000ull | (uint32_t) f64bits); + store_rd (cpu, rd, f64bits); + } + break; + case MATCH_FMV_S_X: + TRACE_INSN (cpu, "fmv.w.x %s, %s;", frd_name, rs1_name); + store_fp (cpu, rd, riscv_cpu->regs[rs1]); + break; + case MATCH_FSGNJ_S: + { + uint32_t rs1_bits, rs2_bits; + TRACE_INSN (cpu, "fsgnj.s %s, %s, %s;", + frd_name, frs1_name, frs2_name); + rs1_bits = (uint32_t) riscv_cpu->fpregs[rs1]; + rs2_bits = (uint32_t) riscv_cpu->fpregs[rs2]; + rs1_bits = (rs2_bits & 0x80000000) | (rs1_bits & 0x7fffffff); + store_fp (cpu, rd, rs1_bits); + break; + } + case MATCH_FEQ_S: + float32_compare (cpu, rd, rs1, rs2, FEQ); + break; + case MATCH_FLT_S: + float32_compare (cpu, rd, rs1, rs2, FLT); + break; + case MATCH_FLE_S: + float32_compare (cpu, rd, rs1, rs2, FLE); + break; + case MATCH_FCLASS_S: + float32_compare (cpu, rd, rs1, 0, FCLASS); + break; + default: + TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name); + sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled, SIM_SIGILL); + } + + return pc; +} + static sim_cia execute_m (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op) { @@ -1313,6 +1524,9 @@ execute_one (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op) sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled, SIM_SIGILL); } + case INSN_CLASS_F: + case INSN_CLASS_F_INX: + return execute_f (cpu, iw, op); case INSN_CLASS_I: return execute_i (cpu, iw, op); case INSN_CLASS_M: diff --git a/sim/testsuite/riscv/s-fp-compare.s b/sim/testsuite/riscv/s-fp-compare.s new file mode 100644 index 00000000000..d5b98b30233 --- /dev/null +++ b/sim/testsuite/riscv/s-fp-compare.s @@ -0,0 +1,75 @@ +# Single precision compare and classify tests. +# mach: riscv32 riscv64 +# sim(riscv32): --model RV32IF +# sim(riscv64): --model RV64ID +# ld(riscv32): -m elf32lriscv +# ld(riscv64): -m elf64lriscv +# as(riscv32): -march=rv32if +# as(riscv64): -march=rv64id + +.include "testutils.inc" + + .section .data + .align 2 + +_arg1: + .float 0.5 + .float 1.1 + .word 0xff800000 # -INF + .word 0x7faaaaaa # sNAN + .word 0x7feaaaaa # qNAN + +_arg2: + .float 0.5 + .float 2.2 + + start + .option push + .option norelax + la a0,_arg1 + la a1,_arg2 + li a3,1 + .option pop + + # Test feq instruction. + flw fa0,0(a0) + flw fa1,0(a1) + feq.s a4,fa0,fa1 + bne a4,a3,test_fail + + # Test flt instruction. + flw fa0,4(a0) + flw fa1,4(a1) + mv a4,x0 + flt.s a4,fa0,fa1 + bne a4,a3,test_fail + + # Test fle instruction. + flw fa0,4(a0) + flw fa1,4(a1) + mv a4,x0 + fle.s a4,fa0,fa1 + bne a4,a3,test_fail + + # Test fclass instruction. + flw fa0,8(a0) + mv a4,x0 + li a3,0x1 # 1 << 0 + fclass.s a4,fa0 + bne a3,a4,test_fail + flw fa0,12(a0) + mv a4,x0 + li a3,0x100 # 1 << 8 + fclass.s a4,fa0 + bne a3,a4,test_fail + flw fa0,16(a0) + mv a4,x0 + li a3,0x200 # 1 << 9 + fclass.s a4,fa0 + bne a3,a4,test_fail + +test_pass: + pass + +test_fail: + fail diff --git a/sim/testsuite/riscv/s-fp-load-store.s b/sim/testsuite/riscv/s-fp-load-store.s new file mode 100644 index 00000000000..0a979d10e70 --- /dev/null +++ b/sim/testsuite/riscv/s-fp-load-store.s @@ -0,0 +1,62 @@ +# Single precision load-store and move tests. +# mach: riscv32 riscv64 +# sim(riscv32): --model RV32IF +# sim(riscv64): --model RV64ID +# ld(riscv32): -m elf32lriscv +# ld(riscv64): -m elf64lriscv +# as(riscv32): -march=rv32if +# as(riscv64): -march=rv64id + +.include "testutils.inc" + + .section .data + .align 2 + +_src: + .float 0.5 + +_dst: + .float 0.5 + .float 0 + .word 0x3f000000 # 0.5 + + start + .option push + .option norelax + la a0,_src + la a1,_dst + li a3,1 + .option pop + + # Test load instruction. + flw fa0,0(a0) + flw fa1,0(a1) + feq.s a4,fa0,fa1 + bne a4,a3,test_fail + + # Test store instruction. + flw fa0,0(a0) + fsw fa0,4(a1) + flw fa1,4(a1) + feq.s a4,fa0,fa1 + bne a4,a3,test_fail + + # Test convert float value to integer encoding instruction. + flw fa0,0(a0) # load float value. + lw a4,8(a1) # load expected result. + fmv.x.w a2,fa0 # convert bit pattern into integer register. + bne a4,a2,test_fail # compare result with expected. + + # Test convert integer encoding to float value instruction. + lw a4,8(a1) # load integer encoding. + fmv.w.x fa1,a4 # convert encoding into float value. + flw fa0,0(a0) # load expected float value. + feq.s a5,fa0,fa1 # compare result with expected. + bne a5,a3,test_fail + + +test_pass: + pass + +test_fail: + fail diff --git a/sim/testsuite/riscv/s-fp-sign-inject.s b/sim/testsuite/riscv/s-fp-sign-inject.s new file mode 100644 index 00000000000..733756a2197 --- /dev/null +++ b/sim/testsuite/riscv/s-fp-sign-inject.s @@ -0,0 +1,52 @@ +# Single precision sign-injection instructions. +# mach: riscv32 riscv64 +# sim(riscv32): --model RV32IF +# sim(riscv64): --model RV64ID +# ld(riscv32): -m elf32lriscv +# ld(riscv64): -m elf64lriscv +# as(riscv32): -march=rv32if +# as(riscv64): -march=rv64id + +.include "testutils.inc" + + .section .data + .align 2 + +_arg1: + .float 2.0 + +_arg2: + .float 1.0 + .float -1.0 + +_expected: + .float 2.0 + .float -2.0 + + start + .option push + .option norelax + la a0,_arg1 + la a1,_arg2 + la a2,_expected + li a3,1 + .option pop + + # Test fsgnj.s instruction. + flw fa0,0(a0) + flw fa1,0(a1) + flw fa2,0(a2) + fsgnj.s fa3,fa0,fa1 + feq.s a4,fa3,fa2 + bne a4,a3,test_fail + flw fa1,4(a1) + flw fa2,4(a2) + fsgnj.s fa3,fa0,fa1 + feq.s a4,fa3,fa2 + bne a4,a3,test_fail + +test_pass: + pass + +test_fail: + fail