Skip to content

Implement RVV whole vector register move - #768

Open
alanhc wants to merge 1 commit into
sysprog21:masterfrom
alanhc:rvv-vmvnr
Open

alanhc wants to merge 1 commit into
sysprog21:masterfrom
alanhc:rvv-vmvnr

Conversation

@alanhc

@alanhc alanhc commented Sep 10, 2026

Copy link
Copy Markdown

Implements the whole-register move family from #734.

Adds vmv<nr>r.v (V 1.0 §16.6) at the OPIVI site of funct6=0x27, which was
previously rejected with a FIXME so the encoding would not fall through to
vsmul.vx.

These copy NREG whole vector registers — all VLEN bits each — operating as
if EEW=SEW and EMUL=NREG. Three details from the spec are worth calling out:

  • the effective length is evl = NREG * VLEN/SEW, so the guard is
    vstart >= evl, not the usual vstart >= vl;
  • vd == vs2 is an architectural NOP;
  • only simm[2:0] values 0, 1, 3 and 7 encode NREG-1. Every other
    simm[4:0] is reserved, as is the masked form.

Encodings checked against riscv-opcodes. Decode tests cover the four valid
forms, seven reserved simm values, the masked forms, and confirm
vsmul.vx still decodes from the same funct6.

Smoke coverage exercises vmv1r.v, the second register of a vmv2r.v group
(so a copy that moves only one register is caught), and the vd == vs2 NOP.
make check passes; the build was checked in the default, EXT_V,
JIT+EXT_V and EXT_V-without-EXT_F configurations. clang-format 20.1.7
clean.


Summary by cubic

Implements the vmv<nr>r.v whole-register move family (V 1.0 §16.6) for RVV. Previously these encodings were rejected to prevent falling through to vsmul.vx; now they decode and execute correctly, including the special effective-length guard and the architectural NOP when vd == vs2.

  • Only simm[2:0] values 0, 1, 3, and 7 are valid; all other simm[4:0] values and the masked form are reserved.
  • The effective length is evl = NREG * VLEN/SEW, so the guard is vstart >= evl, not vstart >= vl.
  • Decode tests cover the four valid forms, seven reserved simm values, masked forms, and confirm vsmul.vx still decodes from the same funct6.
  • Smoke tests exercise vmv1r.v, the second register of a vmv2r.v group, and the vd == vs2 NOP.
  • make check passes across the default, EXT_V, JIT+EXT_V, and EXT_V-without-EXT_F configurations.

Written for commit fdfadf8. Summary will update on new commits.

Review in cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/rv32_v_template.c">

<violation number="1" location="src/rv32_v_template.c:6459">
P3: The new vmv<nr>r.v handlers call rvv_require_operable(rv), which raises an illegal-instruction trap when vtype.vill is set. That is inconsistent with this file's existing whole-register instructions (vs1r.v/vs2r.v/vs4r.v/vs8r.v, lines ~4272-4294), which deliberately do NOT gate on vtype/vill and only validate register span. Per the V 1.0 spec note, whole-register operations do not depend on vtype. If vill is expected to be tolerated for whole-register ops here, this gate will trap where the sibling instructions would not. Confirm the intended vill behavior for the move family and align it with the load/store whole-register paths.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/rv32_v_template.c
})

RVOP(vmv1r_v, {
if (rvv_require_operable(rv))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The new vmv<nr>r.v handlers call rvv_require_operable(rv), which raises an illegal-instruction trap when vtype.vill is set. That is inconsistent with this file's existing whole-register instructions (vs1r.v/vs2r.v/vs4r.v/vs8r.v, lines ~4272-4294), which deliberately do NOT gate on vtype/vill and only validate register span. Per the V 1.0 spec note, whole-register operations do not depend on vtype. If vill is expected to be tolerated for whole-register ops here, this gate will trap where the sibling instructions would not. Confirm the intended vill behavior for the move family and align it with the load/store whole-register paths.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/rv32_v_template.c, line 6459:

<comment>The new vmv<nr>r.v handlers call rvv_require_operable(rv), which raises an illegal-instruction trap when vtype.vill is set. That is inconsistent with this file's existing whole-register instructions (vs1r.v/vs2r.v/vs4r.v/vs8r.v, lines ~4272-4294), which deliberately do NOT gate on vtype/vill and only validate register span. Per the V 1.0 spec note, whole-register operations do not depend on vtype. If vill is expected to be tolerated for whole-register ops here, this gate will trap where the sibling instructions would not. Confirm the intended vill behavior for the move family and align it with the load/store whole-register paths.</comment>

<file context>
@@ -6429,6 +6455,34 @@ RVOP(vmv_s_x, {
 })
 
+RVOP(vmv1r_v, {
+    if (rvv_require_operable(rv))
+        return false;
+    if (!rvv_exec_whole_reg_move(rv, ir, 1))
</file context>

Add vmv<nr>r.v (V 1.0 section 16.6), which copies NREG whole vector
registers. These operate as if EEW=SEW and EMUL=NREG with an effective
length of NREG*VLEN/SEW, so the guard is vstart >= evl rather than the
usual vstart >= vl. vd == vs2 is an architectural NOP.

Only simm values 0, 1, 3 and 7 encode NREG-1; every other simm[4:0] is
reserved, as is the masked form.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant