compiler/
lib/
examples/
std/
arch/
rv64/
asm/
scanner/
emit.rad
8.2 KiB
parser.rad
29.8 KiB
scanner.rad
9.0 KiB
tests.rad
6.3 KiB
asm.rad
22.6 KiB
decode.rad
14.3 KiB
emit.rad
26.0 KiB
encode.rad
21.5 KiB
isel.rad
47.0 KiB
printer.rad
12.6 KiB
tests.rad
17.1 KiB
rv64.rad
11.9 KiB
char/
collections/
lang/
sys/
arch.rad
68 B
char.rad
855 B
collections.rad
39 B
fmt.rad
8.5 KiB
intrinsics.rad
391 B
io.rad
1.3 KiB
lang.rad
258 B
mem.rad
2.2 KiB
sys.rad
173 B
testing.rad
2.4 KiB
tests.rad
14.8 KiB
vec.rad
3.2 KiB
std.rad
281 B
scripts/
seed/
sublime/
test/
vim/
.gitignore
366 B
.gitsigners
112 B
LICENSE
1.1 KiB
Makefile
3.6 KiB
README
2.5 KiB
STYLE
2.5 KiB
std.lib
1.2 KiB
std.lib.test
347 B
lib/std/arch/rv64/asm/tests.rad
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 | } |