feat(asm): add RVC compression for branches, arithmetic, and FP
Assisted-by: DeepSeek V4 Pro
This commit is contained in:
@@ -426,3 +426,151 @@ TEXT ·`+tt.name+`(SB), NOSPLIT, $0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
BEQ X10, X0, done
|
||||
ADDI X10, $1, X10
|
||||
done:
|
||||
RET
|
||||
`)
|
||||
code := assembleRISCVHelper(t, fn)
|
||||
// C.ADDI(2) + C.BEQZ(2) + C.ADDI(2) + C.JR(2) = 8 (all compress)
|
||||
if len(code) != 8 {
|
||||
t.Errorf("expected 8 bytes with C.BEQZ, got %d", len(code))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRISCV_RVC_CJ(t *testing.T) {
|
||||
// JMP target → C.J when offset fits.
|
||||
fn := firstTextRISCV(t, `#include "textflag.h"
|
||||
TEXT ·cj(SB), NOSPLIT, $0
|
||||
JMP done
|
||||
done:
|
||||
RET
|
||||
`)
|
||||
code := assembleRISCVHelper(t, fn)
|
||||
// C.J(2) + C.JR(2) = 4
|
||||
if len(code) != 4 {
|
||||
t.Errorf("expected 4 bytes with C.J, got %d", len(code))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRISCV_RVC_CADD(t *testing.T) {
|
||||
// ADD where rd==rs1 and both in prime regs → C.ADD.
|
||||
fn := firstTextRISCV(t, `#include "textflag.h"
|
||||
TEXT ·cadd(SB), NOSPLIT, $0
|
||||
ADD X10, X11, X10
|
||||
RET
|
||||
`)
|
||||
code := assembleRISCVHelper(t, fn)
|
||||
// C.ADD(2) + C.JR(2) = 4
|
||||
if len(code) != 4 {
|
||||
t.Errorf("expected 4 bytes with C.ADD, got %d", len(code))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRISCV_RVC_CADD_commute(t *testing.T) {
|
||||
// ADD where rd==rs2 (commutative swap) → C.ADD.
|
||||
fn := firstTextRISCV(t, `#include "textflag.h"
|
||||
TEXT ·cadd2(SB), NOSPLIT, $0
|
||||
ADD X11, X10, X10
|
||||
RET
|
||||
`)
|
||||
code := assembleRISCVHelper(t, fn)
|
||||
// C.ADD(2) + C.JR(2) = 4
|
||||
if len(code) != 4 {
|
||||
t.Errorf("expected 4 bytes with C.ADD (commuted), got %d", len(code))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRISCV_RVC_CSUB(t *testing.T) {
|
||||
// SUB where rd==rs1 and both in prime regs → C.SUB.
|
||||
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) != 4 {
|
||||
t.Errorf("expected 4 bytes with C.SUB, got %d (% x)", len(code2), code2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRISCV_RVC_CXOR(t *testing.T) {
|
||||
fn := firstTextRISCV(t, `#include "textflag.h"
|
||||
TEXT ·cxor(SB), NOSPLIT, $0
|
||||
XOR X10, X11, X10
|
||||
RET
|
||||
`)
|
||||
code := assembleRISCVHelper(t, fn)
|
||||
if len(code) != 4 {
|
||||
t.Errorf("expected 4 bytes with C.XOR, got %d", len(code))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRISCV_RVC_COR(t *testing.T) {
|
||||
fn := firstTextRISCV(t, `#include "textflag.h"
|
||||
TEXT ·cor(SB), NOSPLIT, $0
|
||||
OR X10, X11, X10
|
||||
RET
|
||||
`)
|
||||
code := assembleRISCVHelper(t, fn)
|
||||
if len(code) != 4 {
|
||||
t.Errorf("expected 4 bytes with C.OR, got %d", len(code))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRISCV_RVC_CAND(t *testing.T) {
|
||||
fn := firstTextRISCV(t, `#include "textflag.h"
|
||||
TEXT ·cand(SB), NOSPLIT, $0
|
||||
AND X10, X11, X10
|
||||
RET
|
||||
`)
|
||||
code := assembleRISCVHelper(t, fn)
|
||||
if len(code) != 4 {
|
||||
t.Errorf("expected 4 bytes with C.AND, got %d", len(code))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRISCV_RVC_CFLDSP(t *testing.T) {
|
||||
fn := firstTextRISCV(t, `#include "textflag.h"
|
||||
TEXT ·cfldsp(SB), NOSPLIT, $0-8
|
||||
FLD a+0(FP), F10
|
||||
RET
|
||||
`)
|
||||
code := assembleRISCVHelper(t, fn)
|
||||
// C.FLDSP(2) + C.JR(2) = 4
|
||||
if len(code) != 4 {
|
||||
t.Errorf("expected 4 bytes with C.FLDSP, got %d", len(code))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRISCV_RVC_CFSDSP(t *testing.T) {
|
||||
fn := firstTextRISCV(t, `#include "textflag.h"
|
||||
TEXT ·cfsdsp(SB), NOSPLIT, $0-8
|
||||
FSD F10, ret+0(FP)
|
||||
RET
|
||||
`)
|
||||
code := assembleRISCVHelper(t, fn)
|
||||
// C.FSDSP(2) + C.JR(2) = 4
|
||||
if len(code) != 4 {
|
||||
t.Errorf("expected 4 bytes with C.FSDSP, got %d", len(code))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user