lib/std/arch/rv64/asm/tests.rad 6.3 KiB raw
1
//! RV64 assembler tests.
2
3
use std::testing;
4
use std::mem;
5
use std::lang::alloc;
6
use std::lang::sexpr;
7
use std::lang::strings;
8
use std::arch::rv64;
9
use std::arch::rv64::encode;
10
use std::arch::rv64::printer;
11
12
use super::scanner;
13
14
static ASM_ARENA_STORAGE: [u8; 65536] = undefined;
15
static ASM_TEXT_STORAGE: [u32; 256] = undefined;
16
static ASM_DATA_STORAGE: [u8; 1024] = undefined;
17
static ASM_STRING_POOL: strings::Pool = strings::Pool { table: undefined, count: 0 };
18
static PRINT_ARENA_STORAGE: [u8; 1024] = undefined;
19
static PRINT_BUFFER: [u8; 128] = undefined;
20
21
fn assembleSource(source: *[u8]) -> super::Program throws (testing::TestError) {
22
    let mut arena = alloc::new(&mut ASM_ARENA_STORAGE[..]);
23
    return try super::assemble(
24
        scanner::SourceKind::String,
25
        source,
26
        &mut ASM_TEXT_STORAGE[..],
27
        &mut ASM_DATA_STORAGE[..],
28
        &mut arena,
29
        &mut ASM_STRING_POOL,
30
        rv64::RO_DATA_BASE
31
    ) catch {
32
        throw testing::TestError::Failed;
33
    };
34
}
35
36
fn expectAssembleFail(source: *[u8]) throws (testing::TestError) {
37
    let mut arena = alloc::new(&mut ASM_ARENA_STORAGE[..]);
38
    try super::assemble(
39
        scanner::SourceKind::String,
40
        source,
41
        &mut ASM_TEXT_STORAGE[..],
42
        &mut ASM_DATA_STORAGE[..],
43
        &mut arena,
44
        &mut ASM_STRING_POOL,
45
        rv64::RO_DATA_BASE
46
    ) catch {
47
        return;
48
    };
49
    throw testing::TestError::Failed;
50
}
51
52
fn printInstrText(instr: u32) -> *[u8] {
53
    let mut arena = alloc::new(&mut PRINT_ARENA_STORAGE[..]);
54
    let mut pos: u32 = 0;
55
    let mut out = sexpr::Output::Buffer { buf: &mut PRINT_BUFFER[..], pos: &mut pos };
56
    printer::printInstr(&mut out, &mut arena, instr);
57
    return &PRINT_BUFFER[..pos];
58
}
59
60
@test fn testAssemblePercentPrefixedRegisters() throws (testing::TestError) {
61
    let program = try assembleSource(
62
        ".text;\naddi %a0 %zero 42;\nsd %a0 8(%sp);\n"
63
    );
64
    try testing::expect(program.text.len == 2);
65
    try testing::expect(program.text[0] == encode::addi(rv64::A0, rv64::ZERO, 42));
66
    try testing::expect(program.text[1] == encode::sd(rv64::A0, rv64::SP, 8));
67
}
68
69
@test fn testAssembleDataAddressUsesRoDataBase() throws (testing::TestError) {
70
    let program = try assembleSource(
71
        ".text;\nla %t0 @value;\n.data;\n.byte 0;\n@value\n.byte 1;\n"
72
    );
73
    try testing::expect(program.text.len == 2);
74
    try testing::expect(program.text[0] == encode::lui(rv64::T0, 0x10));
75
    try testing::expect(program.text[1] == encode::addi(rv64::T0, rv64::T0, 1));
76
}
77
78
@test fn testAssembleTextAddressUsesPcRelative() throws (testing::TestError) {
79
    let program = try assembleSource(
80
        ".text;\nla %t0 @target;\n@target\nret;\n"
81
    );
82
    try testing::expect(program.text.len == 3);
83
    try testing::expect(program.text[0] == encode::auipc(rv64::T0, 0));
84
    try testing::expect(program.text[1] == encode::addi(rv64::T0, rv64::T0, 8));
85
}
86
87
@test fn testAssembleQuotedLabelNames() throws (testing::TestError) {
88
    let program = try assembleSource(
89
        ".text;\nj @\"foo.bar.baz\";\n@\"foo.bar.baz\"\nret;\n"
90
    );
91
    try testing::expect(program.text.len == 2);
92
    try testing::expect(program.text[0] == encode::jal(rv64::ZERO, 4));
93
    try testing::expect(program.text[1] == encode::jalr(rv64::ZERO, rv64::RA, 0));
94
}
95
96
@test fn testAssembleGlobalMarksOnlyDeclaredSymbols() throws (testing::TestError) {
97
    let program = try assembleSource(
98
        ".text;\n.export @exported;\n@local\nret;\n@exported\nret;\n@late\n.export @late;\nret;\n"
99
    );
100
    try testing::expect(program.symbols.len == 3);
101
    try testing::expect(not program.symbols[0].isExported);
102
    try testing::expect(program.symbols[1].isExported);
103
    try testing::expect(program.symbols[2].isExported);
104
}
105
106
@test fn testAssembleInvalidOperandsFail() throws (testing::TestError) {
107
    try expectAssembleFail(
108
        ".text;\nbeq %a0 %a1 @missing;\n"
109
    );
110
    try expectAssembleFail(
111
        ".text;\naddi a0 zero 1;\n"
112
    );
113
    try expectAssembleFail(
114
        ".text;\naddi % a0 %zero 1;\n"
115
    );
116
    try expectAssembleFail(
117
        ".text;\nli %a0 UNKNOWN;\n"
118
    );
119
    try expectAssembleFail(
120
        ".text;\n@start\nj start;\n"
121
    );
122
}
123
124
@test fn testAssembleInvalidSyntaxFails() throws (testing::TestError) {
125
    try expectAssembleFail(
126
        ".text;\n@dup\n@dup\nret;\n"
127
    );
128
    try expectAssembleFail(
129
        ".text;\naddi %a0, %zero, 1\n"
130
    );
131
    try expectAssembleFail(
132
        ".constant PAGE, 4096;\n"
133
    );
134
    try expectAssembleFail(
135
        ".text;\naddi %a0, %zero, 1;\n"
136
    );
137
    try expectAssembleFail(
138
        ".export @kernel::main, @data::sym;\n"
139
    );
140
}
141
142
@test fn testAssembleInvalidSectionsFail() throws (testing::TestError) {
143
    try expectAssembleFail(
144
        ".data;\n.dword @target;\n.text;\n@target\nret;\n"
145
    );
146
    try expectAssembleFail(
147
        ".data;\naddi %a0 %zero 1;\n"
148
    );
149
    try expectAssembleFail(
150
        ".text;\n.byte 1;\n"
151
    );
152
    try expectAssembleFail(
153
        ".text;\n.word 1;\n"
154
    );
155
    try expectAssembleFail(
156
        ".text;\n.dword 1;\n"
157
    );
158
    try expectAssembleFail(
159
        ".text;\n.ascii \"x\";\n"
160
    );
161
    try expectAssembleFail(
162
        ".data;\n@value\n.byte 1;\n.text;\nj @value;\n"
163
    );
164
}
165
166
@test fn testAssembleInvalidDirectivesFail() throws (testing::TestError) {
167
    try expectAssembleFail(
168
        ".data;\n.ascii 'x';\n"
169
    );
170
    try expectAssembleFail(
171
        ".data;\n.byte 1 + 2;\n"
172
    );
173
    try expectAssembleFail(
174
        ".data;\n.byte 256;\n"
175
    );
176
    try expectAssembleFail(
177
        ".data;\n.word 2147483648;\n"
178
    );
179
    try expectAssembleFail(
180
        ".data;\n.space 4294967296;\n"
181
    );
182
    try expectAssembleFail(
183
        ".data;\n.align 3;\n"
184
    );
185
    try expectAssembleFail(
186
        ".text;\n.align 12;\n"
187
    );
188
    try expectAssembleFail(
189
        ".data;\n.align 4294967296;\n"
190
    );
191
}
192
193
@test fn testAssembleInvalidImmediateRangesFail() throws (testing::TestError) {
194
    try expectAssembleFail(
195
        ".text;\nslli %a0 %a1 64;\n"
196
    );
197
    try expectAssembleFail(
198
        ".text;\nslli %a0 %a1 4294967296;\n"
199
    );
200
    try expectAssembleFail(
201
        ".text;\nslliw %a0 %a1 2147483648;\n"
202
    );
203
    try expectAssembleFail(
204
        ".text;\ncsrsi mstatus 32;\n"
205
    );
206
}
207
208
@test fn testPrintInstrUsesPercentPrefixedRegisters() throws (testing::TestError) {
209
    let text = printInstrText(encode::addi(rv64::A0, rv64::SP, 42));
210
    try testing::expect(mem::eq(text, "addi    %a0, %sp, 42"));
211
}