decode_test.gno
2.66 Kb · 61 lines
1package riscv
2
3import (
4 "testing"
5
6 "gno.land/p/nt/uassert/v0"
7)
8
9// jal is only needed to exercise immJ, the one format no program in
10// riscv_test.gno reaches for.
11func jal(rd, imm uint32) uint32 { return jType(imm, rd, opJAL) }
12
13// The assembler in riscv_test.gno and the decoders here were written from the
14// spec independently, so encoding a known field and reading it back is a real
15// cross-check rather than a tautology: a field in the wrong place fails unless
16// both files put it in the same wrong place.
17func TestDecodeRoundTripsTheAssembler(t *testing.T) {
18 inst := add(5, 6, 7)
19 uassert.Equal(t, uint64(opReg), uint64(opcode(inst)))
20 uassert.Equal(t, uint64(5), uint64(rd(inst)))
21 uassert.Equal(t, uint64(6), uint64(rs1(inst)))
22 uassert.Equal(t, uint64(7), uint64(rs2(inst)))
23 uassert.Equal(t, uint64(0), uint64(funct3(inst)))
24 uassert.Equal(t, uint64(0), uint64(funct7(inst)))
25 uassert.Equal(t, uint64(0x20), uint64(funct7(sub(5, 6, 7))))
26 uassert.Equal(t, uint64(0x01), uint64(funct7(mul(5, 6, 7))))
27}
28
29// Every immediate in the base set is sign extended from its own top bit, and
30// the top bit is in a different place in each of the five formats. These are
31// the boundary values: the largest positive, the value one past it that must
32// come back negative, and all-ones for minus one.
33func TestImmediatesSignExtend(t *testing.T) {
34 // I-type, 12 bits.
35 uassert.Equal(t, uint64(0x7FF), uint64(immI(addi(1, 2, 0x7FF))))
36 uassert.Equal(t, uint64(0xFFFFF800), uint64(immI(addi(1, 2, 0x800))))
37 uassert.Equal(t, uint64(0xFFFFFFFF), uint64(immI(addi(1, 2, 0xFFF))))
38
39 // S-type, 12 bits split across two fields.
40 uassert.Equal(t, uint64(0x7FF), uint64(immS(sw(3, 4, 0x7FF))))
41 uassert.Equal(t, uint64(0xFFFFF800), uint64(immS(sw(3, 4, 0x800))))
42 uassert.Equal(t, uint64(0xFFFFFFFF), uint64(immS(sw(3, 4, 0xFFF))))
43
44 // B-type, 13 bits with bit 0 always zero. -12 is the encoding the
45 // benchmark's loop branch uses, and getting its width wrong is what makes
46 // a backward branch jump forward instead.
47 uassert.Equal(t, uint64(0x7FE), uint64(immB(bne(1, 2, 0x7FE))))
48 uassert.Equal(t, uint64(0xFFFFF000), uint64(immB(bne(1, 2, 0x1000))))
49 uassert.Equal(t, uint64(0xFFFFFFF4), uint64(immB(bne(1, 2, 0x1FF4))))
50
51 // U-type is the only one that is not sign extended, because it is already
52 // the top 20 bits.
53 uassert.Equal(t, uint64(0xDEADB000), uint64(immU(lui(1, 0xDEADB000))))
54
55 // J-type, 21 bits with bit 0 always zero.
56 uassert.Equal(t, uint64(0x7FE), uint64(immJ(jal(1, 0x7FE))))
57 uassert.Equal(t, uint64(0xFFF00000), uint64(immJ(jal(1, 0x100000))))
58 uassert.Equal(t, uint64(0xFFFFFFFE), uint64(immJ(jal(1, 0x1FFFFE))))
59}
60
61func jalr(rd, rs1, imm uint32) uint32 { return iType(imm, rs1, 0x0, rd, opJALR) }