fix(asm): correct RISC-V operand order and complete RVC compression

Assisted-by: DeepSeek V4 Pro
This commit is contained in:
2026-08-13 15:13:31 +02:00
parent b78b6c5004
commit 373c09f725
8 changed files with 212 additions and 77 deletions
+23 -35
View File
@@ -90,10 +90,10 @@ TEXT ·mem(SB), NOSPLIT, $0
func TestRISCV_immediate(t *testing.T) {
fn := firstTextRISCV(t, `#include "textflag.h"
TEXT ·imm(SB), NOSPLIT, $0
ADDI X10, $42, X11
ANDI X11, $0xFF, X12
ORI X12, $1, X13
XORI X13, $0, X14
ADDI $42, X10, X11
ANDI $0xFF, X11, X12
ORI $1, X12, X13
XORI $0, X13, X14
RET
`)
code := assembleRISCVHelper(t, fn)
@@ -106,10 +106,10 @@ TEXT ·imm(SB), NOSPLIT, $0
func TestRISCV_branches(t *testing.T) {
fn := firstTextRISCV(t, `#include "textflag.h"
TEXT ·br(SB), NOSPLIT, $0
ADDI X10, $1, X10
ADDI $1, X10, X10
loop:
BEQ X10, X11, done
ADDI X10, $1, X10
ADDI $1, X10, X10
JMP loop
done:
RET
@@ -291,9 +291,9 @@ func TestRISCV_forwardBranch(t *testing.T) {
// Forward label reference — must not fail.
fn := firstTextRISCV(t, `#include "textflag.h"
TEXT ·fwd(SB), NOSPLIT, $0
ADDI X10, $1, X10
ADDI $1, X10, X10
BEQ X10, X11, done
ADDI X10, $1, X10
ADDI $1, X10, X10
done:
RET
`)
@@ -308,7 +308,7 @@ func TestRISCV_RVC_ADDI(t *testing.T) {
// ADDI where rd=rs1 and small imm → C.ADDI
fn := firstTextRISCV(t, `#include "textflag.h"
TEXT ·caddi(SB), NOSPLIT, $0
ADDI X10, $5, X10
ADDI $5, X10, X10
RET
`)
code := assembleRISCVHelper(t, fn)
@@ -322,7 +322,7 @@ func TestRISCV_RVC_LI(t *testing.T) {
// ADDI X0, $imm, rd → C.LI
fn := firstTextRISCV(t, `#include "textflag.h"
TEXT ·cli(SB), NOSPLIT, $0
ADDI X0, $7, X10
ADDI $7, X0, X10
RET
`)
code := assembleRISCVHelper(t, fn)
@@ -389,10 +389,10 @@ func TestRISCV_encodings(t *testing.T) {
{"MUL", "MUL X10, X11, X12\nRET\n", 8},
{"DIVW", "DIVW X10, X11, X12\nRET\n", 8},
{"REMUW", "REMUW X10, X11, X12\nRET\n", 8},
{"ADDIW", "ADDIW X10, $5, X11\nRET\n", 8},
{"SLLI", "SLLI X10, $3, X11\nRET\n", 8}, // ADDI+SLLI? No, SLLI uses I-type
{"SRLI", "SRLI X10, $2, X11\nRET\n", 8},
{"SRAI", "SRAI X10, $1, X11\nRET\n", 8},
{"ADDIW", "ADDIW $5, X10, X11\nRET\n", 8},
{"SLLI", "SLLI $3, X10, X11\nRET\n", 8}, // ADDI+SLLI? No, SLLI uses I-type
{"SRLI", "SRLI $2, X10, X11\nRET\n", 8},
{"SRAI", "SRAI $1, X10, X11\nRET\n", 8},
{"LB", "LB (X10), X11\nRET\n", 8},
{"LBU", "LBU (X10), X11\nRET\n", 8},
{"LH", "LH (X10), X11\nRET\n", 8},
@@ -431,9 +431,9 @@ func TestRISCV_RVC_branch(t *testing.T) {
// BEQ rs, X0, target → C.BEQZ when rs is in prime regs and offset fits.
fn := firstTextRISCV(t, `#include "textflag.h"
TEXT ·cbeqz(SB), NOSPLIT, $0
ADDI X10, $1, X10
ADDI $1, X10, X10
BEQ X10, X0, done
ADDI X10, $1, X10
ADDI $1, X10, X10
done:
RET
`)
@@ -488,28 +488,16 @@ func TestRISCV_RVC_CADD_commute(t *testing.T) {
}
func TestRISCV_RVC_CSUB(t *testing.T) {
// SUB where rd==rs1 and both in prime regs → C.SUB.
// SUB rs2, rs1, rd → C.SUB when rd == rs1 and both in prime regs.
fn := firstTextRISCV(t, `#include "textflag.h"
TEXT ·csub(SB), NOSPLIT, $0
SUB X11, X10, X10
RET
`)
code := assembleRISCVHelper(t, fn)
// SUB X11,X10,X10 → rd=X10, rs1=X11 ≠ rd → no C.SUB.
// Plan9: INSTR src1, src2, dst. For C.SUB: rd must equal rs1.
// So: SUB X10, X11, X10 → rd=10, rs1=10, rs2=11 ✓
if len(code) == 4 {
return // compressed
}
// Try with correct operand order.
fn2 := firstTextRISCV(t, `#include "textflag.h"
TEXT ·csub2(SB), NOSPLIT, $0
SUB X10, X11, X10
RET
`)
code2 := assembleRISCVHelper(t, fn2)
if len(code2) != 6 {
t.Errorf("expected 6 bytes with C.SUB, got %d (% x)", len(code2), code2)
// SUB X11, X10, X10 → rs2=X11, rs1=X10, rd=X10; rd==rs1 → C.SUB (2B) + JALR (4B) = 6.
if len(code) != 6 {
t.Errorf("expected 6 bytes with C.SUB, got %d (% x)", len(code), code)
}
}
@@ -712,9 +700,9 @@ TEXT ·sys(SB), NOSPLIT, $0
RET
`)
code := assembleRISCVHelper(t, fn)
// 3 system instructions × 4 bytes + JALR(4) = 16
if len(code) != 16 {
t.Errorf("expected 16 bytes, got %d (% x)", len(code), code)
// FENCE(4) + ECALL(4) + C.EBREAK(2) + JALR(4) = 14
if len(code) != 14 {
t.Errorf("expected 14 bytes, got %d (% x)", len(code), code)
}
}