143 lines
4.1 KiB
Go
143 lines
4.1 KiB
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package asm
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
// TestRISCVCompressedDifferential proves the explicit compressed-instruction
|
|
// mnemonics against the toolchain: the "C" extension block of the toolchain's
|
|
// own testdata (every stack, register, control-transfer, constant-generation,
|
|
// shift and register-register spelling it carries) assembled by gasm and by
|
|
// go tool asm must agree halfword for halfword. The lines are the oracle's
|
|
// own, so a wrong bit pattern, scale or register field names itself through
|
|
// the first differing halfword.
|
|
func TestRISCVCompressedDifferential(t *testing.T) {
|
|
src := `#include "textflag.h"
|
|
|
|
TEXT ·compressed(SB), NOSPLIT, $0
|
|
CLWSP 20(SP), X10
|
|
CLDSP 24(SP), X10
|
|
CFLDSP 32(SP), F10
|
|
CSWSP X10, 20(SP)
|
|
CSDSP X10, 24(SP)
|
|
CFSDSP F10, 32(SP)
|
|
CLW 20(X10), X11
|
|
CLD 24(X10), X11
|
|
CFLD 32(X10), F11
|
|
CSW X11, 20(X10)
|
|
CSD X11, 24(X10)
|
|
CFSD F11, 32(X10)
|
|
CJ 1(PC)
|
|
CJR X5
|
|
CJALR X5
|
|
CBEQZ X10, 1(PC)
|
|
CBNEZ X10, 1(PC)
|
|
CLI $-32, X5
|
|
CLI $31, X5
|
|
CLUI $-32, X5
|
|
CLUI $31, X5
|
|
CADD $-32, X5
|
|
CADD $31, X5
|
|
CADDI $-32, X5
|
|
CADDI $31, X5
|
|
CADDW $-32, X5
|
|
CADDW $31, X5
|
|
CADDIW $-32, X5
|
|
CADDIW $31, X5
|
|
CADDI16SP $-512, SP
|
|
CADDI16SP $496, SP
|
|
CADDI4SPN $4, SP, X10
|
|
CADDI4SPN $1020, SP, X10
|
|
CSLLI $63, X5
|
|
CSRLI $63, X10
|
|
CSRAI $63, X10
|
|
CAND $-32, X10
|
|
CAND $31, X10
|
|
CANDI $-32, X10
|
|
CANDI $31, X10
|
|
CMV X6, X5
|
|
CADD X9, X8
|
|
CAND X9, X8
|
|
COR X9, X8
|
|
CXOR X9, X8
|
|
CSUB X9, X8
|
|
CADDW X9, X8
|
|
CSUBW X9, X8
|
|
CNOP
|
|
CEBREAK
|
|
RET
|
|
`
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "compressed_riscv64.s")
|
|
if err := os.WriteFile(path, []byte(src), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
assertRISCVDifferential(t, path, src, "compressed")
|
|
}
|
|
|
|
// TestRISCVCompressedRange pins the compressed immediate and offset ranges at
|
|
// the toolchain's own boundaries: a stack load off the scale or range, a
|
|
// non-prime register in the CL/CS and CA shapes, a zero immediate where the
|
|
// toolchain forbids one and a CLUI into SP are all rejected on sight.
|
|
func TestRISCVCompressedRange(t *testing.T) {
|
|
asmOne := func(t *testing.T, stmt string) error {
|
|
t.Helper()
|
|
fn := firstTextRISCV(t, "#include \"textflag.h\"\nTEXT ·c(SB), NOSPLIT, $0\n\t"+stmt+"\n\tRET\n")
|
|
_, _, _, _, _, _, err := assembleRISCV(fn, nil)
|
|
return err
|
|
}
|
|
for _, s := range []string{
|
|
"CLWSP $0(SP), X10", // never spelled; the parser rejects the shape
|
|
} {
|
|
if err := asmOne(t, s); err == nil {
|
|
t.Errorf("%s must be rejected", s)
|
|
}
|
|
}
|
|
for _, s := range []string{
|
|
"CLWSP 21(SP), X10", // not a multiple of 4
|
|
"CLWSP 256(SP), X10", // out of range
|
|
"CLDSP 25(SP), X10", // not a multiple of 8
|
|
"CFLDSP 33(SP), F10", // not a multiple of 8
|
|
"CLWSP 20(X10), X10", // base must be SP
|
|
"CLW 22(X10), X11", // not a multiple of 4
|
|
"CLW 128(X10), X11", // out of range
|
|
"CLW 20(X5), X11", // base must be prime
|
|
"CLW 20(X10), X5", // rd must be prime
|
|
"CLI $32, X5", // out of range
|
|
"CLI $-33, X5", // out of range
|
|
"CLUI $0, X5", // zero
|
|
"CLUI $3, X2", // SP as destination
|
|
"CSLLI $0, X5", // zero shift
|
|
"CSLLI $64, X5", // out of range
|
|
"CSRLI $63, X5", // rd must be prime
|
|
"CANDI $63, X10", // out of range
|
|
"CMV X0, X5", // X0 in rd
|
|
"CMV X5, X0", // X0 in rs2
|
|
"CADD X5, X0", // X0 in rs2
|
|
"CSUB X5, X5", // X0-free but rd prime required
|
|
"CADDI4SPN $4, X5, X10", /* base must be SP */
|
|
} {
|
|
if err := asmOne(t, s); err == nil {
|
|
t.Errorf("%s must be rejected, as go tool asm rejects it", s)
|
|
}
|
|
}
|
|
for _, s := range []string{
|
|
"CLWSP 20(SP), X10", "CLDSP 24(SP), X10",
|
|
"CLW 20(X10), X11", "CSD X11, 24(X10)",
|
|
"CLI $-32, X5", "CLUI $-32, X5",
|
|
"CADD $-32, X5", "CADDIW $31, X5",
|
|
"CSLLI $63, X5", "CSRLI $63, X10", "CANDI $-32, X10",
|
|
"CMV X6, X5", "CADD X9, X8", "CSUB X9, X8", "CADDW X9, X8",
|
|
"CADDI16SP $496, SP", "CADDI4SPN $1020, SP, X10",
|
|
} {
|
|
if err := asmOne(t, s); err != nil {
|
|
t.Errorf("%s must assemble: %v", s, err)
|
|
}
|
|
}
|
|
}
|