lib/std/arch/rv64/tests.rad 17.2 KiB raw
1
//! RV64I+M instruction encoding tests.
2
//!
3
//! These tests verify that instruction encodings match the RISC-V specification
4
//! by comparing against known-good values.
5
6
use std::testing;
7
use std::lang::alloc;
8
use std::collections::dict;
9
10
use super::encode;
11
use super::asm;
12
13
static ASSEMBLY_ARENA_STORAGE: [u8; 16777216] = [0; 16777216];
14
static ASSEMBLY_TEXT_STORAGE: [u32; 2] = [0; 2];
15
16
/// Helper to check encoding equals expected value.
17
fn expectEncoding(actual: u32, expected: u32) throws (testing::TestError) {
18
    try testing::expect(actual == expected);
19
}
20
21
@test unsafe fn testAddAssemblyExportsOnlyGlobalTextSymbols() throws (testing::TestError) {
22
    let mut arena = alloc::new(&mut ASSEMBLY_ARENA_STORAGE[..]);
23
    let symbols = try alloc::allocSlice(&mut arena, @sizeOf(asm::Symbol), @alignOf(asm::Symbol), 2) catch {
24
        throw testing::TestError::Failed;
25
    };
26
    let symbolSlice = symbols as *mut [asm::Symbol];
27
    set symbolSlice[0] = asm::Symbol {
28
        name: "local",
29
        section: asm::Section::Text,
30
        offset: 0,
31
        isExported: false,
32
    };
33
    set symbolSlice[1] = asm::Symbol {
34
        name: "exported",
35
        section: asm::Section::Text,
36
        offset: super::INSTR_SIZE,
37
        isExported: true,
38
    };
39
40
    let mut generator = try! super::beginProgram(
41
        super::ProgramOptions { entryPatch: super::EntryPatch::None, debug: false, placement: super::image::Placement::Hosted },
42
        &mut arena
43
    );
44
    super::addAssembly(
45
        &mut generator,
46
        asm::Program {
47
            text: &ASSEMBLY_TEXT_STORAGE[..],
48
            data: &[],
49
            symbols: symbolSlice,
50
            externalFixups: &[],
51
        }
52
    );
53
54
    try testing::expect(dict::get(&generator.e.labels.funcs, "local") == nil);
55
    let exportedOffset = dict::get(&generator.e.labels.funcs, "exported") else {
56
        throw testing::TestError::Failed;
57
    };
58
    try testing::expect(exportedOffset == super::INSTR_SIZE);
59
}
60
61
///////////////////////
62
// R-type ALU tests  //
63
///////////////////////
64
65
@test fn testEncodeAdd() throws (testing::TestError) {
66
    let enc = encode::add(super::reg(1), super::reg(2), super::reg(3));
67
    try expectEncoding(enc, 0x003100B3);
68
}
69
70
@test fn testEncodeSub() throws (testing::TestError) {
71
    let enc = encode::sub(super::reg(5), super::reg(6), super::reg(7));
72
    try expectEncoding(enc, 0x407302B3);
73
}
74
75
@test fn testEncodeSll() throws (testing::TestError) {
76
    let enc = encode::sll(super::reg(1), super::reg(2), super::reg(3));
77
    try expectEncoding(enc, 0x003110B3);
78
}
79
80
@test fn testEncodeSlt() throws (testing::TestError) {
81
    let enc = encode::slt(super::reg(1), super::reg(2), super::reg(3));
82
    try expectEncoding(enc, 0x003120B3);
83
}
84
85
@test fn testEncodeSltu() throws (testing::TestError) {
86
    let enc = encode::sltu(super::reg(1), super::reg(2), super::reg(3));
87
    try expectEncoding(enc, 0x003130B3);
88
}
89
90
@test fn testEncodeXor() throws (testing::TestError) {
91
    let enc = encode::xor(super::reg(1), super::reg(2), super::reg(3));
92
    try expectEncoding(enc, 0x003140B3);
93
}
94
95
@test fn testEncodeSrl() throws (testing::TestError) {
96
    let enc = encode::srl(super::reg(1), super::reg(2), super::reg(3));
97
    try expectEncoding(enc, 0x003150B3);
98
}
99
100
@test fn testEncodeSra() throws (testing::TestError) {
101
    let enc = encode::sra(super::reg(1), super::reg(2), super::reg(3));
102
    try expectEncoding(enc, 0x403150B3);
103
}
104
105
@test fn testEncodeOr() throws (testing::TestError) {
106
    let enc = encode::or_(super::reg(1), super::reg(2), super::reg(3));
107
    try expectEncoding(enc, 0x003160B3);
108
}
109
110
@test fn testEncodeAnd() throws (testing::TestError) {
111
    let enc = encode::and_(super::reg(1), super::reg(2), super::reg(3));
112
    try expectEncoding(enc, 0x003170B3);
113
}
114
115
///////////////////////
116
// I-type ALU tests  //
117
///////////////////////
118
119
@test fn testEncodeAddi() throws (testing::TestError) {
120
    let enc = encode::addi(super::reg(1), super::ZERO, 42);
121
    try expectEncoding(enc, 0x02A00093);
122
}
123
124
@test fn testEncodeAddiNegative() throws (testing::TestError) {
125
    let enc = encode::addi(super::reg(1), super::ZERO, -1);
126
    try expectEncoding(enc, 0xFFF00093);
127
}
128
129
@test fn testEncodeSlti() throws (testing::TestError) {
130
    let enc = encode::slti(super::reg(1), super::reg(2), 100);
131
    try expectEncoding(enc, 0x06412093);
132
}
133
134
@test fn testEncodeSltiu() throws (testing::TestError) {
135
    let enc = encode::sltiu(super::reg(1), super::reg(2), 100);
136
    try expectEncoding(enc, 0x06413093);
137
}
138
139
@test fn testEncodeXori() throws (testing::TestError) {
140
    let enc = encode::xori(super::reg(1), super::reg(2), 0xFF);
141
    try expectEncoding(enc, 0x0FF14093);
142
}
143
144
@test fn testEncodeOri() throws (testing::TestError) {
145
    let enc = encode::ori(super::reg(1), super::reg(2), 0xFF);
146
    try expectEncoding(enc, 0x0FF16093);
147
}
148
149
@test fn testEncodeAndi() throws (testing::TestError) {
150
    let enc = encode::andi(super::reg(1), super::reg(2), 0xFF);
151
    try expectEncoding(enc, 0x0FF17093);
152
}
153
154
@test fn testEncodeSlli() throws (testing::TestError) {
155
    let enc = encode::slli(super::reg(1), super::reg(2), 5);
156
    try expectEncoding(enc, 0x00511093);
157
}
158
159
@test fn testEncodeSrli() throws (testing::TestError) {
160
    let enc = encode::srli(super::reg(1), super::reg(2), 5);
161
    try expectEncoding(enc, 0x00515093);
162
}
163
164
@test fn testEncodeSrai() throws (testing::TestError) {
165
    let enc = encode::srai(super::reg(1), super::reg(2), 5);
166
    try expectEncoding(enc, 0x40515093);
167
}
168
169
//////////////////
170
// Load tests   //
171
//////////////////
172
173
@test fn testEncodeLb() throws (testing::TestError) {
174
    let enc = encode::lb(super::reg(1), super::reg(2), 8);
175
    try expectEncoding(enc, 0x00810083);
176
}
177
178
@test fn testEncodeLh() throws (testing::TestError) {
179
    let enc = encode::lh(super::reg(1), super::reg(2), 8);
180
    try expectEncoding(enc, 0x00811083);
181
}
182
183
@test fn testEncodeLw() throws (testing::TestError) {
184
    let enc = encode::lw(super::reg(1), super::reg(2), 8);
185
    try expectEncoding(enc, 0x00812083);
186
}
187
188
@test fn testEncodeLbu() throws (testing::TestError) {
189
    let enc = encode::lbu(super::reg(1), super::reg(2), 8);
190
    try expectEncoding(enc, 0x00814083);
191
}
192
193
@test fn testEncodeLhu() throws (testing::TestError) {
194
    let enc = encode::lhu(super::reg(1), super::reg(2), 8);
195
    try expectEncoding(enc, 0x00815083);
196
}
197
198
@test fn testEncodeLwu() throws (testing::TestError) {
199
    let enc = encode::lwu(super::reg(1), super::reg(2), 8);
200
    try expectEncoding(enc, 0x00816083);
201
}
202
203
@test fn testEncodeLd() throws (testing::TestError) {
204
    let enc = encode::ld(super::reg(1), super::reg(2), 8);
205
    try expectEncoding(enc, 0x00813083);
206
}
207
208
//////////////////
209
// Store tests  //
210
//////////////////
211
212
@test fn testEncodeSb() throws (testing::TestError) {
213
    let enc = encode::sb(super::reg(3), super::reg(2), 8);
214
    try expectEncoding(enc, 0x00310423);
215
}
216
217
@test fn testEncodeSh() throws (testing::TestError) {
218
    let enc = encode::sh(super::reg(3), super::reg(2), 8);
219
    try expectEncoding(enc, 0x00311423);
220
}
221
222
@test fn testEncodeSw() throws (testing::TestError) {
223
    let enc = encode::sw(super::reg(3), super::reg(2), 8);
224
    try expectEncoding(enc, 0x00312423);
225
}
226
227
@test fn testEncodeSd() throws (testing::TestError) {
228
    let enc = encode::sd(super::reg(3), super::reg(2), 8);
229
    try expectEncoding(enc, 0x00313423);
230
}
231
232
@test fn testEncodeSwNegativeOffset() throws (testing::TestError) {
233
    let enc = encode::sw(super::reg(3), super::reg(2), -4);
234
    try expectEncoding(enc, 0xFE312E23);
235
}
236
237
//////////////////
238
// Branch tests //
239
//////////////////
240
241
@test fn testEncodeBeq() throws (testing::TestError) {
242
    let enc = encode::beq(super::reg(1), super::reg(2), 8);
243
    try expectEncoding(enc, 0x00208463);
244
}
245
246
@test fn testEncodeBne() throws (testing::TestError) {
247
    let enc = encode::bne(super::reg(1), super::reg(2), 8);
248
    try expectEncoding(enc, 0x00209463);
249
}
250
251
@test fn testEncodeBlt() throws (testing::TestError) {
252
    let enc = encode::blt(super::reg(1), super::reg(2), 8);
253
    try expectEncoding(enc, 0x0020C463);
254
}
255
256
@test fn testEncodeBge() throws (testing::TestError) {
257
    let enc = encode::bge(super::reg(1), super::reg(2), 8);
258
    try expectEncoding(enc, 0x0020D463);
259
}
260
261
@test fn testEncodeBltu() throws (testing::TestError) {
262
    let enc = encode::bltu(super::reg(1), super::reg(2), 8);
263
    try expectEncoding(enc, 0x0020E463);
264
}
265
266
@test fn testEncodeBgeu() throws (testing::TestError) {
267
    let enc = encode::bgeu(super::reg(1), super::reg(2), 8);
268
    try expectEncoding(enc, 0x0020F463);
269
}
270
271
@test fn testEncodeBranchNegative() throws (testing::TestError) {
272
    let enc = encode::beq(super::reg(1), super::reg(2), -8);
273
    try expectEncoding(enc, 0xFE208CE3);
274
}
275
276
//////////////////
277
// Jump tests   //
278
//////////////////
279
280
@test fn testEncodeJal() throws (testing::TestError) {
281
    let enc = encode::jal(super::reg(1), 8);
282
    try expectEncoding(enc, 0x008000EF);
283
}
284
285
@test fn testEncodeJalr() throws (testing::TestError) {
286
    let enc = encode::jalr(super::reg(1), super::reg(2), 8);
287
    try expectEncoding(enc, 0x008100E7);
288
}
289
290
///////////////////////////
291
// Upper immediate tests //
292
///////////////////////////
293
294
@test fn testEncodeLui() throws (testing::TestError) {
295
    let enc = encode::lui(super::reg(1), 0x12345);
296
    try expectEncoding(enc, 0x123450B7);
297
}
298
299
@test fn testEncodeAuipc() throws (testing::TestError) {
300
    let enc = encode::auipc(super::reg(1), 0x12345);
301
    try expectEncoding(enc, 0x12345097);
302
}
303
304
//////////////////
305
// System tests //
306
//////////////////
307
308
@test fn testEncodeEcall() throws (testing::TestError) {
309
    let enc = encode::ecall();
310
    try expectEncoding(enc, 0x00000073);
311
}
312
313
@test fn testEncodeEbreak() throws (testing::TestError) {
314
    let enc = encode::ebreak();
315
    try expectEncoding(enc, 0x00100073);
316
}
317
318
/////////////////////
319
// M extension tests
320
/////////////////////
321
322
@test fn testEncodeMul() throws (testing::TestError) {
323
    let enc = encode::mul(super::reg(1), super::reg(2), super::reg(3));
324
    try expectEncoding(enc, 0x023100B3);
325
}
326
327
@test fn testEncodeMulh() throws (testing::TestError) {
328
    let enc = encode::mulh(super::reg(1), super::reg(2), super::reg(3));
329
    try expectEncoding(enc, 0x023110B3);
330
}
331
332
@test fn testEncodeMulhsu() throws (testing::TestError) {
333
    let enc = encode::mulhsu(super::reg(1), super::reg(2), super::reg(3));
334
    try expectEncoding(enc, 0x023120B3);
335
}
336
337
@test fn testEncodeMulhu() throws (testing::TestError) {
338
    let enc = encode::mulhu(super::reg(1), super::reg(2), super::reg(3));
339
    try expectEncoding(enc, 0x023130B3);
340
}
341
342
@test fn testEncodeDiv() throws (testing::TestError) {
343
    let enc = encode::div(super::reg(1), super::reg(2), super::reg(3));
344
    try expectEncoding(enc, 0x023140B3);
345
}
346
347
@test fn testEncodeDivu() throws (testing::TestError) {
348
    let enc = encode::divu(super::reg(1), super::reg(2), super::reg(3));
349
    try expectEncoding(enc, 0x023150B3);
350
}
351
352
@test fn testEncodeRem() throws (testing::TestError) {
353
    let enc = encode::rem(super::reg(1), super::reg(2), super::reg(3));
354
    try expectEncoding(enc, 0x023160B3);
355
}
356
357
@test fn testEncodeRemu() throws (testing::TestError) {
358
    let enc = encode::remu(super::reg(1), super::reg(2), super::reg(3));
359
    try expectEncoding(enc, 0x023170B3);
360
}
361
362
////////////////////////////
363
// RV64 Word operation tests
364
////////////////////////////
365
366
@test fn testEncodeAddiw() throws (testing::TestError) {
367
    let enc = encode::addiw(super::reg(1), super::reg(2), 42);
368
    try expectEncoding(enc, 0x02A1009B);
369
}
370
371
@test fn testEncodeSlliw() throws (testing::TestError) {
372
    let enc = encode::slliw(super::reg(1), super::reg(2), 5);
373
    try expectEncoding(enc, 0x0051109B);
374
}
375
376
@test fn testEncodeSrliw() throws (testing::TestError) {
377
    let enc = encode::srliw(super::reg(1), super::reg(2), 5);
378
    try expectEncoding(enc, 0x0051509B);
379
}
380
381
@test fn testEncodeSraiw() throws (testing::TestError) {
382
    let enc = encode::sraiw(super::reg(1), super::reg(2), 5);
383
    try expectEncoding(enc, 0x4051509B);
384
}
385
386
@test fn testEncodeAddw() throws (testing::TestError) {
387
    let enc = encode::addw(super::reg(1), super::reg(2), super::reg(3));
388
    try expectEncoding(enc, 0x003100BB);
389
}
390
391
@test fn testEncodeSubw() throws (testing::TestError) {
392
    let enc = encode::subw(super::reg(1), super::reg(2), super::reg(3));
393
    try expectEncoding(enc, 0x403100BB);
394
}
395
396
@test fn testEncodeSllw() throws (testing::TestError) {
397
    let enc = encode::sllw(super::reg(1), super::reg(2), super::reg(3));
398
    try expectEncoding(enc, 0x003110BB);
399
}
400
401
@test fn testEncodeSrlw() throws (testing::TestError) {
402
    let enc = encode::srlw(super::reg(1), super::reg(2), super::reg(3));
403
    try expectEncoding(enc, 0x003150BB);
404
}
405
406
@test fn testEncodeSraw() throws (testing::TestError) {
407
    let enc = encode::sraw(super::reg(1), super::reg(2), super::reg(3));
408
    try expectEncoding(enc, 0x403150BB);
409
}
410
411
@test fn testEncodeMulw() throws (testing::TestError) {
412
    let enc = encode::mulw(super::reg(1), super::reg(2), super::reg(3));
413
    try expectEncoding(enc, 0x023100BB);
414
}
415
416
@test fn testEncodeDivw() throws (testing::TestError) {
417
    let enc = encode::divw(super::reg(1), super::reg(2), super::reg(3));
418
    try expectEncoding(enc, 0x023140BB);
419
}
420
421
@test fn testEncodeDivuw() throws (testing::TestError) {
422
    let enc = encode::divuw(super::reg(1), super::reg(2), super::reg(3));
423
    try expectEncoding(enc, 0x023150BB);
424
}
425
426
@test fn testEncodeRemw() throws (testing::TestError) {
427
    let enc = encode::remw(super::reg(1), super::reg(2), super::reg(3));
428
    try expectEncoding(enc, 0x023160BB);
429
}
430
431
@test fn testEncodeRemuw() throws (testing::TestError) {
432
    let enc = encode::remuw(super::reg(1), super::reg(2), super::reg(3));
433
    try expectEncoding(enc, 0x023170BB);
434
}
435
436
/////////////////////////////////
437
// RV64 6-bit shift amount tests
438
/////////////////////////////////
439
440
@test fn testEncodeSlli64() throws (testing::TestError) {
441
    let enc = encode::slli(super::reg(1), super::reg(2), 32);
442
    try expectEncoding(enc, 0x02011093);
443
}
444
445
@test fn testEncodeSrli64() throws (testing::TestError) {
446
    let enc = encode::srli(super::reg(1), super::reg(2), 32);
447
    try expectEncoding(enc, 0x02015093);
448
}
449
450
@test fn testEncodeSrai64() throws (testing::TestError) {
451
    let enc = encode::srai(super::reg(1), super::reg(2), 32);
452
    try expectEncoding(enc, 0x42015093);
453
}
454
455
///////////////////////////
456
// Pseudo-instruction tests
457
///////////////////////////
458
459
@test fn testEncodeNop() throws (testing::TestError) {
460
    let enc = encode::nop();
461
    try expectEncoding(enc, 0x00000013);
462
}
463
464
@test fn testEncodeMv() throws (testing::TestError) {
465
    let enc = encode::mv(super::reg(1), super::reg(2));
466
    try expectEncoding(enc, 0x00010093);
467
}
468
469
@test fn testEncodeNot() throws (testing::TestError) {
470
    let enc = encode::not_(super::reg(1), super::reg(2));
471
    try expectEncoding(enc, 0xFFF14093);
472
}
473
474
@test fn testEncodeNeg() throws (testing::TestError) {
475
    let enc = encode::neg(super::reg(1), super::reg(2));
476
    try expectEncoding(enc, 0x402000B3);
477
}
478
479
@test fn testEncodeRet() throws (testing::TestError) {
480
    let enc = encode::ret();
481
    try expectEncoding(enc, 0x00008067);
482
}
483
484
@test fn testEncodeJ() throws (testing::TestError) {
485
    let enc = encode::j(8);
486
    try expectEncoding(enc, 0x0080006F);
487
}
488
489
@test fn testEncodeBle() throws (testing::TestError) {
490
    let enc = encode::ble(super::reg(1), super::reg(2), 8);
491
    try expectEncoding(enc, 0x00115463);
492
}
493
494
@test fn testEncodeBgt() throws (testing::TestError) {
495
    let enc = encode::bgt(super::reg(1), super::reg(2), 8);
496
    try expectEncoding(enc, 0x00114463);
497
}
498
499
@test fn testEncodeSeqz() throws (testing::TestError) {
500
    let enc = encode::seqz(super::reg(1), super::reg(2));
501
    try expectEncoding(enc, 0x00113093);
502
}
503
504
@test fn testEncodeSnez() throws (testing::TestError) {
505
    let enc = encode::snez(super::reg(1), super::reg(2));
506
    try expectEncoding(enc, 0x002030B3);
507
}
508
509
@test fn testEncodeBeqz() throws (testing::TestError) {
510
    let enc = encode::beqz(super::reg(1), 8);
511
    try expectEncoding(enc, 0x00008463);
512
}
513
514
@test fn testEncodeBnez() throws (testing::TestError) {
515
    let enc = encode::bnez(super::reg(1), 8);
516
    try expectEncoding(enc, 0x00009463);
517
}
518
519
@test fn testEncodeCall() throws (testing::TestError) {
520
    let enc = encode::call(8);
521
    try expectEncoding(enc, 0x008000EF);
522
}
523
524
/////////////////////////////
525
// Validation helper tests //
526
/////////////////////////////
527
528
@test fn testIsSmallImm() throws (testing::TestError) {
529
    try testing::expect(encode::isSmallImm(0));
530
    try testing::expect(encode::isSmallImm(2047));
531
    try testing::expect(encode::isSmallImm(-2048));
532
    try testing::expect(encode::isSmallImm(-1));
533
    try testing::expectNot(encode::isSmallImm(2048));
534
    try testing::expectNot(encode::isSmallImm(-2049));
535
}
536
537
@test fn testIsBranchImm() throws (testing::TestError) {
538
    try testing::expect(encode::isBranchImm(0));
539
    try testing::expect(encode::isBranchImm(8));
540
    try testing::expect(encode::isBranchImm(-8));
541
    try testing::expect(encode::isBranchImm(4094));
542
    try testing::expect(encode::isBranchImm(-4096));
543
    try testing::expectNot(encode::isBranchImm(1));     // Must be even
544
    try testing::expectNot(encode::isBranchImm(4096));  // Out of range
545
}
546
547
@test fn testIsJumpImm() throws (testing::TestError) {
548
    try testing::expect(encode::isJumpImm(0));
549
    try testing::expect(encode::isJumpImm(8));
550
    try testing::expect(encode::isJumpImm(-8));
551
    try testing::expect(encode::isJumpImm(1048574));    // Max positive even
552
    try testing::expect(encode::isJumpImm(-1048576));   // Min negative
553
    try testing::expectNot(encode::isJumpImm(1));       // Must be even
554
    try testing::expectNot(encode::isJumpImm(1048576)); // Out of range
555
}