Repository navigation
Implement RVV floating-point scalar moves #769
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6828,6 +6828,35 @@ static inline void rvv_exec_fp32_vf(riscv_t *rv, | |
| rv->csr_vstart = 0; | ||
| } | ||
|
|
||
| /* Floating-point scalar moves (V 1.0 §16.3). Both ignore LMUL and touch | ||
| * only element 0. | ||
| */ | ||
| static inline void rvv_exec_vfmv_f_s(riscv_t *rv, const rv_insn_t *ir) | ||
| { | ||
| /* vfmv.f.s performs its operation even if vstart >= vl or vl == 0. */ | ||
| rv->F[ir->rd].v = rvv_get_elem(rv, ir->vs2, 0, 32); | ||
| rv->csr_vstart = 0; | ||
| } | ||
|
|
||
| static inline void rvv_exec_vfmv_s_f(riscv_t *rv, const rv_insn_t *ir) | ||
| { | ||
| /* If vstart >= vl nothing is written; with vl == 0 that covers every | ||
| * vstart, so the destination is left alone. Remaining elements are | ||
| * tail elements governed by the usual vta policy. | ||
| */ | ||
| if (rv->csr_vstart < rv->csr_vl) { | ||
| uint32_t vlmax = rvv_vlmax(rv->csr_vtype); | ||
| uint8_t vta = (rv->csr_vtype >> 6) & 0x1; | ||
|
|
||
| rvv_set_elem(rv, ir->vd, 0, 32, rv->F[ir->rs1].v); | ||
| if (vta) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: When Prompt for AI agents |
||
| for (uint32_t elem = rv->csr_vl; elem < vlmax; elem++) | ||
| rvv_set_elem(rv, ir->vd, elem, 32, 0xFFFFFFFFU); | ||
| } | ||
| } | ||
| rv->csr_vstart = 0; | ||
| } | ||
|
|
||
| static inline void rvv_exec_fp32_mask_vv(riscv_t *rv, | ||
| const rv_insn_t *ir, | ||
| uint32_t dest, | ||
|
|
@@ -7448,6 +7477,22 @@ static inline void rvv_exec_vfmv_v_f(riscv_t *rv, | |
| set_fflag(rv); \ | ||
| }) | ||
|
|
||
| RVOP(vfmv_f_s, { | ||
| if (rvv_require_operable(rv)) | ||
| return false; | ||
| if (rvv_sew_bits(rv->csr_vtype) != 32) | ||
| return rvv_trap_illegal_state(rv, 0); | ||
| rvv_exec_vfmv_f_s(rv, ir); | ||
| }) | ||
|
|
||
| RVOP(vfmv_s_f, { | ||
| if (rvv_require_operable(rv)) | ||
| return false; | ||
| if (rvv_sew_bits(rv->csr_vtype) != 32) | ||
| return rvv_trap_illegal_state(rv, 0); | ||
| rvv_exec_vfmv_s_f(rv, ir); | ||
| }) | ||
|
|
||
| RVV_FP32_VV_OP(vfadd_vv, rvv_fp_add32, true); | ||
| RVV_FP32_VF_OP(vfadd_vf, rvv_fp_add32, true); | ||
| RVV_FP32_RED_OP(vfredusum_vs, rvv_fp_add32, true); | ||
|
|
@@ -7619,6 +7664,8 @@ RVV_FP64_MAC_VF_OP(vfwmsac_vf, rvv_fp_wmsac64); | |
| RVV_FP64_MAC_VV_OP(vfwnmsac_vv, rvv_fp_wnmsac64); | ||
| RVV_FP64_MAC_VF_OP(vfwnmsac_vf, rvv_fp_wnmsac64); | ||
| #else | ||
| RVOP(vfmv_f_s, { V_NOP; }) | ||
| RVOP(vfmv_s_f, { V_NOP; }) | ||
| RVOP(vfadd_vv, { V_NOP; }) | ||
| RVOP(vfadd_vf, { V_NOP; }) | ||
| RVOP(vfredusum_vs, { V_NOP; }) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -98,6 +98,9 @@ mulfix_lhs: | |
| mulfix_rhs: | ||
| .byte 0x40, 0x80, 0x40, 0x20 | ||
|
|
||
| vfmv_src: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: Prompt for AI agents |
||
| .word 0x40490fdb, 0x3f800000, 0xc0000000, 0x00000000 | ||
|
|
||
| narrow16_a: | ||
| .short 0x8000, 0x0002 | ||
|
|
||
|
|
@@ -296,6 +299,8 @@ fixed_out: | |
| .space 16 | ||
| wide_out: | ||
| .space 32 | ||
| vfmv_out: | ||
| .space 32 | ||
| red_out: | ||
| .space 16 | ||
| wide_red_out: | ||
|
|
@@ -1813,6 +1818,65 @@ _start: | |
| csrr t1, vl | ||
| assert_reg_imm t1, 4, fail_fractional | ||
|
|
||
| # Floating-point scalar moves (V 1.0 16.3). Both ignore LMUL and only | ||
| # touch element 0. | ||
| li a0, 4 | ||
| vsetvli t0, a0, e32, m1, tu, mu | ||
| # Stage the source through the scratch buffer so every address in this | ||
| # block comes from the same base register. | ||
| la a2, vfmv_out | ||
| li t2, 0x40490fdb | ||
| sw t2, 0(a2) | ||
| li t2, 0x3f800000 | ||
| sw t2, 4(a2) | ||
| vle32.v v20, (a2) | ||
|
|
||
| # vfmv.f.s: element 0 (0x40490fdb) lands in an f register. Spill it back | ||
| # to the scratch buffer to compare the bits. | ||
| vfmv.f.s ft0, v20 | ||
| fmv.x.w t1, ft0 | ||
| li t6, 0x40490fdb | ||
| bne t1, t6, fail_vfmv_f_s | ||
|
|
||
| # vfmv.s.f writes element 0 only; element 1 must keep its old value | ||
| # under the tail-undisturbed policy selected above. | ||
| la a1, vfmv_out | ||
| li t2, 0x11111111 | ||
| sw t2, 0(a1) | ||
| sw t2, 4(a1) | ||
| sw t2, 8(a1) | ||
| sw t2, 12(a1) | ||
| vle32.v v22, (a1) | ||
| li t2, 0x3f800000 | ||
| fmv.w.x ft1, t2 | ||
| vfmv.s.f v22, ft1 | ||
| vse32.v v22, (a1) | ||
| lw t1, 0(a1) | ||
| li t6, 0x3f800000 | ||
| bne t1, t6, fail_vfmv_s_f | ||
| lw t1, 4(a1) | ||
| li t6, 0x11111111 | ||
| bne t1, t6, fail_vfmv_s_f | ||
|
|
||
| # Per spec, vfmv.s.f performs no update when vstart >= vl; with vl = 0 | ||
| # that holds for every vstart, so element 0 keeps its previous value. | ||
| la a1, vfmv_out | ||
| li t2, 0x22222222 | ||
| sw t2, 0(a1) | ||
| vle32.v v22, (a1) | ||
| li a0, 0 | ||
| vsetvli t0, a0, e32, m1, tu, mu | ||
| csrr t1, vl | ||
| assert_reg_imm t1, 0, fail_vfmv_vl0 | ||
| vfmv.s.f v22, ft1 | ||
| li a0, 4 | ||
| vsetvli t0, a0, e32, m1, tu, mu | ||
| la a1, vfmv_out | ||
| vse32.v v22, (a1) | ||
| lw t1, 0(a1) | ||
| li t6, 0x22222222 | ||
| bne t1, t6, fail_vfmv_vl0 | ||
|
|
||
| la a1, ok_msg | ||
| li a2, ok_msg_len | ||
| j write_and_exit_ok | ||
|
|
@@ -1911,6 +1975,15 @@ fail_vsmul4: | |
| fail_vwadd: | ||
| li a3, 0xd5 | ||
| j write_and_exit_fail | ||
| fail_vfmv_f_s: | ||
| li a3, 0x97 | ||
| j write_and_exit_fail | ||
| fail_vfmv_s_f: | ||
| li a3, 0x98 | ||
| j write_and_exit_fail | ||
| fail_vfmv_vl0: | ||
| li a3, 0x99 | ||
| j write_and_exit_fail | ||
| fail_vwmulu: | ||
| li a3, 0xd6 | ||
| j write_and_exit_fail | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: In an RV32E+V build, valid upper floating-point registers are rejected for these new moves. The post-decode RV32E check treats
op_010000operands as integer registers, even though these fields are floating-point registers; extend that check to recognize these vector FP moves.Prompt for AI agents