rv32g-core

Pipelined, synthesizable, and fabricable RISC-V core in SystemVerilog+Yosys+OpenROAD
Log | Files | Refs | LICENSE

test_macros.h (29581B)


      1 // See LICENSE for license details.
      2 
      3 #ifndef __TEST_MACROS_SCALAR_H
      4 #define __TEST_MACROS_SCALAR_H
      5 
      6 
      7 #-----------------------------------------------------------------------
      8 # Helper macros
      9 #-----------------------------------------------------------------------
     10 
     11 #define MASK_XLEN(x) ((x) & ((1 << (__riscv_xlen - 1) << 1) - 1))
     12 
     13 #define TEST_CASE( testnum, testreg, correctval, code... ) \
     14 test_ ## testnum: \
     15     li  TESTNUM, testnum; \
     16     code; \
     17     li  x7, MASK_XLEN(correctval); \
     18     bne testreg, x7, fail;
     19 
     20 # We use a macro hack to simpify code generation for various numbers
     21 # of bubble cycles.
     22 
     23 #define TEST_INSERT_NOPS_0
     24 #define TEST_INSERT_NOPS_1  nop; TEST_INSERT_NOPS_0
     25 #define TEST_INSERT_NOPS_2  nop; TEST_INSERT_NOPS_1
     26 #define TEST_INSERT_NOPS_3  nop; TEST_INSERT_NOPS_2
     27 #define TEST_INSERT_NOPS_4  nop; TEST_INSERT_NOPS_3
     28 #define TEST_INSERT_NOPS_5  nop; TEST_INSERT_NOPS_4
     29 #define TEST_INSERT_NOPS_6  nop; TEST_INSERT_NOPS_5
     30 #define TEST_INSERT_NOPS_7  nop; TEST_INSERT_NOPS_6
     31 #define TEST_INSERT_NOPS_8  nop; TEST_INSERT_NOPS_7
     32 #define TEST_INSERT_NOPS_9  nop; TEST_INSERT_NOPS_8
     33 #define TEST_INSERT_NOPS_10 nop; TEST_INSERT_NOPS_9
     34 
     35 #if __riscv_xlen == 64
     36 #define LOAD_PTR ld
     37 #define STORE_PTR sd
     38 #else
     39 #define LOAD_PTR lw
     40 #define STORE_PTR sw
     41 #endif
     42 
     43 #-----------------------------------------------------------------------
     44 # RV64UI MACROS
     45 #-----------------------------------------------------------------------
     46 
     47 #-----------------------------------------------------------------------
     48 # Tests for instructions with immediate operand
     49 #-----------------------------------------------------------------------
     50 
     51 #define SEXT_IMM(x) ((x) | (-(((x) >> 11) & 1) << 11))
     52 
     53 #define TEST_IMM_OP( testnum, inst, result, val1, imm ) \
     54     TEST_CASE( testnum, x14, result, \
     55       li  x13, MASK_XLEN(val1); \
     56       inst x14, x13, SEXT_IMM(imm); \
     57     )
     58 
     59 #define TEST_IMM_OP_VXSAT( testnum, inst, result, val1, imm, expected_vxsat ) \
     60     TEST_CASE( testnum, x14, result, \
     61       TEST_VXSAT_CLEAR; \
     62       li  x13, MASK_XLEN(val1); \
     63       inst x14, x13, SEXT_IMM(imm); \
     64     ) \
     65     TEST_VXSAT_CHECK( expected_vxsat )
     66 
     67 # RV32 P-extension register-pair immediate-op tests.
     68 # rs1 pair = {x13, x12} (even base), rd pair = {x15, x14}.
     69 # Both halves of result are checked; on mismatch we jump to the same fail
     70 # label as TEST_CASE, so the reported testnum matches.
     71 #define TEST_IMM_OP_PAIR( testnum, inst, result, val1, imm ) \
     72     TEST_CASE( testnum, x14, ((result) & 0xFFFFFFFF), \
     73       li  x12, ((val1) & 0xFFFFFFFF); \
     74       li  x13, (((val1) >> 32) & 0xFFFFFFFF); \
     75       inst x14, x12, SEXT_IMM(imm); \
     76     ) \
     77     li  x7, (((result) >> 32) & 0xFFFFFFFF); \
     78     bne x15, x7, fail;
     79 
     80 #define TEST_IMM_SRC1_EQ_DEST( testnum, inst, result, val1, imm ) \
     81     TEST_CASE( testnum, x11, result, \
     82       li  x11, MASK_XLEN(val1); \
     83       inst x11, x11, SEXT_IMM(imm); \
     84     )
     85 
     86 #define TEST_IMM_DEST_BYPASS( testnum, nop_cycles, inst, result, val1, imm ) \
     87     TEST_CASE( testnum, x6, result, \
     88       li  x4, 0; \
     89 1:    li  x1, MASK_XLEN(val1); \
     90       inst x14, x1, SEXT_IMM(imm); \
     91       TEST_INSERT_NOPS_ ## nop_cycles \
     92       addi  x6, x14, 0; \
     93       addi  x4, x4, 1; \
     94       li  x5, 2; \
     95       bne x4, x5, 1b \
     96     )
     97 
     98 #define TEST_IMM_SRC1_BYPASS( testnum, nop_cycles, inst, result, val1, imm ) \
     99     TEST_CASE( testnum, x14, result, \
    100       li  x4, 0; \
    101 1:    li  x1, MASK_XLEN(val1); \
    102       TEST_INSERT_NOPS_ ## nop_cycles \
    103       inst x14, x1, SEXT_IMM(imm); \
    104       addi  x4, x4, 1; \
    105       li  x5, 2; \
    106       bne x4, x5, 1b \
    107     )
    108 
    109 #define TEST_IMM_ZEROSRC1( testnum, inst, result, imm ) \
    110     TEST_CASE( testnum, x1, result, \
    111       inst x1, x0, SEXT_IMM(imm); \
    112     )
    113 
    114 #define TEST_IMM_ZERODEST( testnum, inst, val1, imm ) \
    115     TEST_CASE( testnum, x0, 0, \
    116       li  x1, MASK_XLEN(val1); \
    117       inst x0, x1, SEXT_IMM(imm); \
    118     )
    119 
    120 #-----------------------------------------------------------------------
    121 # Tests for an instruction with register operands
    122 #-----------------------------------------------------------------------
    123 
    124 #define TEST_R_OP( testnum, inst, result, val1 ) \
    125     TEST_CASE( testnum, x14, result, \
    126       li  x1, val1; \
    127       inst x14, x1; \
    128     )
    129 
    130 # P-extension vxsat helpers.
    131 # vxsat is a sticky CSR (0x009): set to 1 whenever an instruction saturates,
    132 # never auto-cleared. To verify it deterministically per test we clear it
    133 # before the instruction and check the expected post-value after.
    134 # Using the literal CSR address keeps these macros toolchain-independent.
    135 #define VXSAT_CSR 0x009
    136 #define TEST_VXSAT_CLEAR  csrwi VXSAT_CSR, 0
    137 #define TEST_VXSAT_CHECK( expected_vxsat ) \
    138       csrr x6, VXSAT_CSR; \
    139       li   x7, (expected_vxsat); \
    140       bne  x6, x7, fail;
    141 
    142 #define TEST_R_OP_VXSAT( testnum, inst, result, val1, expected_vxsat ) \
    143     TEST_CASE( testnum, x14, result, \
    144       TEST_VXSAT_CLEAR; \
    145       li  x1, val1; \
    146       inst x14, x1; \
    147     ) \
    148     TEST_VXSAT_CHECK( expected_vxsat )
    149 
    150 #define TEST_R_SRC1_EQ_DEST( testnum, inst, result, val1 ) \
    151     TEST_CASE( testnum, x1, result, \
    152       li  x1, val1; \
    153       inst x1, x1; \
    154     )
    155 
    156 #define TEST_R_DEST_BYPASS( testnum, nop_cycles, inst, result, val1 ) \
    157     TEST_CASE( testnum, x6, result, \
    158       li  x4, 0; \
    159 1:    li  x1, val1; \
    160       inst x14, x1; \
    161       TEST_INSERT_NOPS_ ## nop_cycles \
    162       addi  x6, x14, 0; \
    163       addi  x4, x4, 1; \
    164       li  x5, 2; \
    165       bne x4, x5, 1b \
    166     )
    167 
    168 #-----------------------------------------------------------------------
    169 # Tests for an instruction with register-register operands
    170 #-----------------------------------------------------------------------
    171 
    172 #define TEST_RR_OP( testnum, inst, result, val1, val2 ) \
    173     TEST_CASE( testnum, x14, result, \
    174       li  x11, MASK_XLEN(val1); \
    175       li  x12, MASK_XLEN(val2); \
    176       inst x14, x11, x12; \
    177     )
    178 
    179 #define TEST_RR_OP_VXSAT( testnum, inst, result, val1, val2, expected_vxsat ) \
    180     TEST_CASE( testnum, x14, result, \
    181       TEST_VXSAT_CLEAR; \
    182       li  x11, MASK_XLEN(val1); \
    183       li  x12, MASK_XLEN(val2); \
    184       inst x14, x11, x12; \
    185     ) \
    186     TEST_VXSAT_CHECK( expected_vxsat )
    187 
    188 # RV32 P-extension register-pair register-register tests.
    189 # rs1 pair = {x13, x12} (even base), rd pair = {x15, x14}, rs2 = x11.
    190 # Both halves of result are checked; on mismatch we jump to the same fail
    191 # label as TEST_CASE, so the reported testnum matches.
    192 #define TEST_RR_OP_PAIR( testnum, inst, result, val1, val2 ) \
    193     TEST_CASE( testnum, x14, ((result) & 0xFFFFFFFF), \
    194       li  x12, ((val1) & 0xFFFFFFFF); \
    195       li  x13, (((val1) >> 32) & 0xFFFFFFFF); \
    196       li  x11, MASK_XLEN(val2); \
    197       inst x14, x12, x11; \
    198     ) \
    199     li  x7, (((result) >> 32) & 0xFFFFFFFF); \
    200     bne x15, x7, fail;
    201 
    202 #define TEST_RR_SRC1_EQ_DEST( testnum, inst, result, val1, val2 ) \
    203     TEST_CASE( testnum, x11, result, \
    204       li  x11, MASK_XLEN(val1); \
    205       li  x12, MASK_XLEN(val2); \
    206       inst x11, x11, x12; \
    207     )
    208 
    209 #define TEST_RR_SRC2_EQ_DEST( testnum, inst, result, val1, val2 ) \
    210     TEST_CASE( testnum, x12, result, \
    211       li  x11, MASK_XLEN(val1); \
    212       li  x12, MASK_XLEN(val2); \
    213       inst x12, x11, x12; \
    214     )
    215 
    216 #define TEST_RR_SRC12_EQ_DEST( testnum, inst, result, val1 ) \
    217     TEST_CASE( testnum, x11, result, \
    218       li  x11, MASK_XLEN(val1); \
    219       inst x11, x11, x11; \
    220     )
    221 
    222 #define TEST_RR_DEST_BYPASS( testnum, nop_cycles, inst, result, val1, val2 ) \
    223     TEST_CASE( testnum, x6, result, \
    224       li  x4, 0; \
    225 1:    li  x1, MASK_XLEN(val1); \
    226       li  x2, MASK_XLEN(val2); \
    227       inst x14, x1, x2; \
    228       TEST_INSERT_NOPS_ ## nop_cycles \
    229       addi  x6, x14, 0; \
    230       addi  x4, x4, 1; \
    231       li  x5, 2; \
    232       bne x4, x5, 1b \
    233     )
    234 
    235 #define TEST_RR_SRC12_BYPASS( testnum, src1_nops, src2_nops, inst, result, val1, val2 ) \
    236     TEST_CASE( testnum, x14, result, \
    237       li  x4, 0; \
    238 1:    li  x1, MASK_XLEN(val1); \
    239       TEST_INSERT_NOPS_ ## src1_nops \
    240       li  x2, MASK_XLEN(val2); \
    241       TEST_INSERT_NOPS_ ## src2_nops \
    242       inst x14, x1, x2; \
    243       addi  x4, x4, 1; \
    244       li  x5, 2; \
    245       bne x4, x5, 1b \
    246     )
    247 
    248 #define TEST_RR_SRC21_BYPASS( testnum, src1_nops, src2_nops, inst, result, val1, val2 ) \
    249     TEST_CASE( testnum, x14, result, \
    250       li  x4, 0; \
    251 1:    li  x2, MASK_XLEN(val2); \
    252       TEST_INSERT_NOPS_ ## src1_nops \
    253       li  x1, MASK_XLEN(val1); \
    254       TEST_INSERT_NOPS_ ## src2_nops \
    255       inst x14, x1, x2; \
    256       addi  x4, x4, 1; \
    257       li  x5, 2; \
    258       bne x4, x5, 1b \
    259     )
    260 
    261 #define TEST_RR_ZEROSRC1( testnum, inst, result, val ) \
    262     TEST_CASE( testnum, x2, result, \
    263       li x1, MASK_XLEN(val); \
    264       inst x2, x0, x1; \
    265     )
    266 
    267 #define TEST_RR_ZEROSRC2( testnum, inst, result, val ) \
    268     TEST_CASE( testnum, x2, result, \
    269       li x1, MASK_XLEN(val); \
    270       inst x2, x1, x0; \
    271     )
    272 
    273 #define TEST_RR_ZEROSRC12( testnum, inst, result ) \
    274     TEST_CASE( testnum, x1, result, \
    275       inst x1, x0, x0; \
    276     )
    277 
    278 #define TEST_RR_ZERODEST( testnum, inst, val1, val2 ) \
    279     TEST_CASE( testnum, x0, 0, \
    280       li x1, MASK_XLEN(val1); \
    281       li x2, MASK_XLEN(val2); \
    282       inst x0, x1, x2; \
    283     )
    284 
    285 #-----------------------------------------------------------------------
    286 # Test memory instructions
    287 #-----------------------------------------------------------------------
    288 
    289 #define TEST_LD_OP( testnum, inst, result, offset, base ) \
    290     TEST_CASE( testnum, x14, result, \
    291       li  x15, result; /* Tell the exception handler the expected result. */ \
    292       la  x2, base; \
    293       inst x14, offset(x2); \
    294     )
    295 
    296 #define TEST_ST_OP( testnum, load_inst, store_inst, result, offset, base ) \
    297     TEST_CASE( testnum, x14, result, \
    298       la  x2, base; \
    299       li  x1, result; \
    300       la  x15, 7f; /* Tell the exception handler how to skip this test. */ \
    301       store_inst x1, offset(x2); \
    302       load_inst x14, offset(x2); \
    303       j 8f; \
    304 7:    \
    305       /* Set up the correct result for TEST_CASE(). */ \
    306       mv x14, x1; \
    307 8:    \
    308     )
    309 
    310 #define TEST_LD_DEST_BYPASS( testnum, nop_cycles, inst, result, offset, base ) \
    311 test_ ## testnum: \
    312     li  TESTNUM, testnum; \
    313     li  x4, 0; \
    314 1:  la  x13, base; \
    315     inst x14, offset(x13); \
    316     TEST_INSERT_NOPS_ ## nop_cycles \
    317     addi  x6, x14, 0; \
    318     li  x7, result; \
    319     bne x6, x7, fail; \
    320     addi  x4, x4, 1; \
    321     li  x5, 2; \
    322     bne x4, x5, 1b; \
    323 
    324 #define TEST_LD_SRC1_BYPASS( testnum, nop_cycles, inst, result, offset, base ) \
    325 test_ ## testnum: \
    326     li  TESTNUM, testnum; \
    327     li  x4, 0; \
    328 1:  la  x13, base; \
    329     TEST_INSERT_NOPS_ ## nop_cycles \
    330     inst x14, offset(x13); \
    331     li  x7, result; \
    332     bne x14, x7, fail; \
    333     addi  x4, x4, 1; \
    334     li  x5, 2; \
    335     bne x4, x5, 1b \
    336 
    337 #define TEST_ST_SRC12_BYPASS( testnum, src1_nops, src2_nops, load_inst, store_inst, result, offset, base ) \
    338 test_ ## testnum: \
    339     li  TESTNUM, testnum; \
    340     li  x4, 0; \
    341 1:  li  x13, result; \
    342     TEST_INSERT_NOPS_ ## src1_nops \
    343     la  x12, base; \
    344     TEST_INSERT_NOPS_ ## src2_nops \
    345     store_inst x13, offset(x12); \
    346     load_inst x14, offset(x12); \
    347     li  x7, result; \
    348     bne x14, x7, fail; \
    349     addi  x4, x4, 1; \
    350     li  x5, 2; \
    351     bne x4, x5, 1b \
    352 
    353 #define TEST_ST_SRC21_BYPASS( testnum, src1_nops, src2_nops, load_inst, store_inst, result, offset, base ) \
    354 test_ ## testnum: \
    355     li  TESTNUM, testnum; \
    356     li  x4, 0; \
    357 1:  la  x2, base; \
    358     TEST_INSERT_NOPS_ ## src1_nops \
    359     li  x1, result; \
    360     TEST_INSERT_NOPS_ ## src2_nops \
    361     store_inst x1, offset(x2); \
    362     load_inst x14, offset(x2); \
    363     li  x7, result; \
    364     bne x14, x7, fail; \
    365     addi  x4, x4, 1; \
    366     li  x5, 2; \
    367     bne x4, x5, 1b \
    368 
    369 #define TEST_LD_ST_BYPASS(testnum, load_inst, store_inst, result, offset, base) \
    370 test_ ## testnum: \
    371     li  TESTNUM, testnum; \
    372     la  x2, base;        \
    373     li x1, result; \
    374     store_inst x1, offset(x2); \
    375     load_inst x14, offset(x2);  \
    376     store_inst x14, offset(x2); \
    377     load_inst x2, offset(x2);  \
    378     li  x7, result; \
    379     bne x2, x7, fail;  \
    380     la  x2, base;        \
    381     STORE_PTR x2,8(x2); \
    382     LOAD_PTR x4,8(x2); \
    383     store_inst x1, offset(x4); \
    384     bne x4, x2, fail;  \
    385     load_inst x14, offset(x4);  \
    386     bne x14, x7, fail;  \
    387 
    388 #define TEST_ST_LD_BYPASS(testnum, load_inst, store_inst, result, offset, base) \
    389 test_ ## testnum: \
    390     li  TESTNUM, testnum;            \
    391     la  x2, base;                    \
    392     li  x1, result;                  \
    393     store_inst x1, offset(x2);       \
    394     load_inst x14, offset(x2);       \
    395     li  x7, result;                  \
    396     bne x14, x7, fail;               \
    397 
    398 #define TEST_BR2_OP_TAKEN(testnum, inst, val1, val2 ) \
    399 test_ ## testnum: \
    400     li  TESTNUM, testnum; \
    401     li  x1, val1; \
    402     li  x2, val2; \
    403     inst x1, x2, 2f; \
    404     bne x0, TESTNUM, fail; \
    405 1:  bne x0, TESTNUM, 3f; \
    406 2:  inst x1, x2, 1b; \
    407     bne x0, TESTNUM, fail; \
    408 3:
    409 
    410 #define TEST_BR2_OP_NOTTAKEN( testnum, inst, val1, val2 ) \
    411 test_ ## testnum: \
    412     li  TESTNUM, testnum; \
    413     li  x1, val1; \
    414     li  x2, val2; \
    415     inst x1, x2, 1f; \
    416     bne x0, TESTNUM, 2f; \
    417 1:  bne x0, TESTNUM, fail; \
    418 2:  inst x1, x2, 1b; \
    419 3:
    420 
    421 #define TEST_BR2_SRC12_BYPASS( testnum, src1_nops, src2_nops, inst, val1, val2 ) \
    422 test_ ## testnum: \
    423     li  TESTNUM, testnum; \
    424     li  x4, 0; \
    425 1:  li  x1, val1; \
    426     TEST_INSERT_NOPS_ ## src1_nops \
    427     li  x2, val2; \
    428     TEST_INSERT_NOPS_ ## src2_nops \
    429     inst x1, x2, fail; \
    430     addi  x4, x4, 1; \
    431     li  x5, 2; \
    432     bne x4, x5, 1b \
    433 
    434 #define TEST_BR2_SRC21_BYPASS( testnum, src1_nops, src2_nops, inst, val1, val2 ) \
    435 test_ ## testnum: \
    436     li  TESTNUM, testnum; \
    437     li  x4, 0; \
    438 1:  li  x2, val2; \
    439     TEST_INSERT_NOPS_ ## src1_nops \
    440     li  x1, val1; \
    441     TEST_INSERT_NOPS_ ## src2_nops \
    442     inst x1, x2, fail; \
    443     addi  x4, x4, 1; \
    444     li  x5, 2; \
    445     bne x4, x5, 1b \
    446 
    447 #-----------------------------------------------------------------------
    448 # Test jump instructions
    449 #-----------------------------------------------------------------------
    450 
    451 #define TEST_JR_SRC1_BYPASS( testnum, nop_cycles, inst ) \
    452 test_ ## testnum: \
    453     li  TESTNUM, testnum; \
    454     li  x4, 0; \
    455 1:  la  x6, 2f; \
    456     TEST_INSERT_NOPS_ ## nop_cycles \
    457     inst x6; \
    458     bne x0, TESTNUM, fail; \
    459 2:  addi  x4, x4, 1; \
    460     li  x5, 2; \
    461     bne x4, x5, 1b \
    462 
    463 #define TEST_JALR_SRC1_BYPASS( testnum, nop_cycles, inst ) \
    464 test_ ## testnum: \
    465     li  TESTNUM, testnum; \
    466     li  x4, 0; \
    467 1:  la  x6, 2f; \
    468     TEST_INSERT_NOPS_ ## nop_cycles \
    469     inst x13, x6, 0; \
    470     bne x0, TESTNUM, fail; \
    471 2:  addi  x4, x4, 1; \
    472     li  x5, 2; \
    473     bne x4, x5, 1b \
    474 
    475 
    476 #-----------------------------------------------------------------------
    477 # RV64UF MACROS
    478 #-----------------------------------------------------------------------
    479 
    480 #-----------------------------------------------------------------------
    481 # Tests floating-point instructions
    482 #-----------------------------------------------------------------------
    483 
    484 # 16-bit half precision (float16)
    485 #define qNaNh     0x7e00
    486 #define sNaNh     0x7c01
    487 #define Infh      0x7c00
    488 #define nInfh     0xfc00
    489 
    490 # 32-bit single precision (float)
    491 #define qNaNf     0x7fc00000
    492 #define sNaNf     0x7f800001
    493 #define Inff      0x7f800000
    494 #define nInff     0xff800000
    495 
    496 # 64-bit double precision (double)
    497 #define qNaNd     0x7ff8000000000000
    498 #define sNaNd     0x7ff0000000000001
    499 #define Infd      0x7ff0000000000000
    500 #define nInfd     0xfff0000000000000
    501 
    502 #define TEST_FP_OP_H_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
    503 test_ ## testnum: \
    504   li  TESTNUM, testnum; \
    505   la  a0, test_ ## testnum ## _data ;\
    506   flh f10, 0(a0); \
    507   flh f11, 2(a0); \
    508   flh f12, 4(a0); \
    509   lh  a3, 6(a0); \
    510   code; \
    511   fsflags a1, x0; \
    512   li a2, flags; \
    513   bne a0, a3, fail; \
    514   bne a1, a2, fail; \
    515   .pushsection .data; \
    516   .align 1; \
    517   test_ ## testnum ## _data: \
    518   .val1; \
    519   .val2; \
    520   .val3; \
    521   .result; \
    522   .popsection
    523 
    524 #define TEST_FP_OP_S_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
    525 test_ ## testnum: \
    526   li  TESTNUM, testnum; \
    527   la  a0, test_ ## testnum ## _data ;\
    528   flw f10, 0(a0); \
    529   flw f11, 4(a0); \
    530   flw f12, 8(a0); \
    531   lw  a3, 12(a0); \
    532   code; \
    533   fsflags a1, x0; \
    534   li a2, flags; \
    535   bne a0, a3, fail; \
    536   bne a1, a2, fail; \
    537   .pushsection .data; \
    538   .align 2; \
    539   test_ ## testnum ## _data: \
    540   .val1; \
    541   .val2; \
    542   .val3; \
    543   .result; \
    544   .popsection
    545 
    546 #define TEST_FP_OP_D_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
    547 test_ ## testnum: \
    548   li  TESTNUM, testnum; \
    549   la  a0, test_ ## testnum ## _data ;\
    550   fld f10, 0(a0); \
    551   fld f11, 8(a0); \
    552   fld f12, 16(a0); \
    553   ld  a3, 24(a0); \
    554   code; \
    555   fsflags a1, x0; \
    556   li a2, flags; \
    557   bne a0, a3, fail; \
    558   bne a1, a2, fail; \
    559   .pushsection .data; \
    560   .align 3; \
    561   test_ ## testnum ## _data: \
    562   .val1; \
    563   .val2; \
    564   .val3; \
    565   .result; \
    566   .popsection
    567 
    568 // TODO: assign a separate mem location for the comparison address?
    569 #define TEST_FP_OP_D32_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
    570 test_ ## testnum: \
    571   li  TESTNUM, testnum; \
    572   la  a0, test_ ## testnum ## _data ;\
    573   fld f10, 0(a0); \
    574   fld f11, 8(a0); \
    575   fld f12, 16(a0); \
    576   lw  a3, 24(a0); \
    577   lw  t1, 28(a0); \
    578   code; \
    579   fsflags a1, x0; \
    580   li a2, flags; \
    581   bne a0, a3, fail; \
    582   bne t1, t2, fail; \
    583   bne a1, a2, fail; \
    584   .pushsection .data; \
    585   .align 3; \
    586   test_ ## testnum ## _data: \
    587   .val1; \
    588   .val2; \
    589   .val3; \
    590   .result; \
    591   .popsection
    592 
    593 #define TEST_FCVT_S_D32( testnum, result, val1 ) \
    594   TEST_FP_OP_D32_INTERNAL( testnum, 0, double result, double val1, double 0, double 0, \
    595                     fcvt.s.d f13, f10; fcvt.d.s f13, f13; fsd f13, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
    596 
    597 #define TEST_FCVT_S_D( testnum, result, val1 ) \
    598   TEST_FP_OP_D_INTERNAL( testnum, 0, double result, double val1, double 0, double 0, \
    599                     fcvt.s.d f13, f10; fcvt.d.s f13, f13; fmv.x.d a0, f13)
    600 
    601 #define TEST_FCVT_D_S( testnum, result, val1 ) \
    602   TEST_FP_OP_S_INTERNAL( testnum, 0, float result, float val1, float 0, float 0, \
    603                     fcvt.d.s f13, f10; fcvt.s.d f13, f13; fmv.x.s a0, f13)
    604 
    605 #define TEST_FCVT_H_S( testnum, result, val1 ) \
    606   TEST_FP_OP_H_INTERNAL( testnum, 0, float16 result, float16 val1, float16 0, float16 0, \
    607                     fcvt.s.h f13, f10; fcvt.h.s f13, f13; fmv.x.h a0, f13)
    608 
    609 #define TEST_FCVT_H_D( testnum, result, val1 ) \
    610   TEST_FP_OP_H_INTERNAL( testnum, 0, float16 result, float16 val1, float16 0, float16 0, \
    611                     fcvt.d.h f13, f10; fcvt.h.d f13, f13; fmv.x.h a0, f13)
    612 
    613 
    614 #define TEST_FP_OP1_H( testnum, inst, flags, result, val1 ) \
    615   TEST_FP_OP_H_INTERNAL( testnum, flags, float16 result, float16 val1, float16 0, float16 0, \
    616                     inst f13, f10; fmv.x.h a0, f13;)
    617 
    618 #define TEST_FP_OP1_S( testnum, inst, flags, result, val1 ) \
    619   TEST_FP_OP_S_INTERNAL( testnum, flags, float result, float val1, float 0, float 0, \
    620                     inst f13, f10; fmv.x.s a0, f13)
    621 
    622 #define TEST_FP_OP1_D32( testnum, inst, flags, result, val1 ) \
    623   TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, double val1, double 0, double 0, \
    624                     inst f13, f10; fsd f13, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
    625 // ^: store computation result in address from a0, load high-word into t2
    626 
    627 #define TEST_FP_OP1_D( testnum, inst, flags, result, val1 ) \
    628   TEST_FP_OP_D_INTERNAL( testnum, flags, double result, double val1, double 0, double 0, \
    629                     inst f13, f10; fmv.x.d a0, f13)
    630 
    631 #define TEST_FP_OP1_S_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
    632   TEST_FP_OP_S_INTERNAL( testnum, flags, dword result, float val1, float 0, float 0, \
    633                     inst f13, f10; fmv.x.s a0, f13)
    634 
    635 #define TEST_FP_OP1_H_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
    636   TEST_FP_OP_H_INTERNAL( testnum, flags, word result, float16 val1, float16 0, float16 0, \
    637                     inst f13, f10; fmv.x.h a0, f13)
    638 
    639 #define TEST_FP_OP1_D32_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
    640   TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, double val1, double 0, double 0, \
    641                     inst f13, f10; fsd f13, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
    642 // ^: store computation result in address from a0, load high-word into t2
    643 
    644 #define TEST_FP_OP1_D_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
    645   TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, double val1, double 0, double 0, \
    646                     inst f13, f10; fmv.x.d a0, f13)
    647 
    648 #define TEST_FP_OP2_S( testnum, inst, flags, result, val1, val2 ) \
    649   TEST_FP_OP_S_INTERNAL( testnum, flags, float result, float val1, float val2, float 0, \
    650                     inst f13, f10, f11; fmv.x.s a0, f13)
    651 
    652 #define TEST_FP_OP2_S_HEX( testnum, inst, flags, result, val1, val2 ) \
    653   TEST_FP_OP_S_INTERNAL( testnum, flags, word result, word val1, word val2, float 0, \
    654                     inst f13, f10, f11; fmv.x.s a0, f13)
    655 
    656 #define TEST_FP_OP2_H( testnum, inst, flags, result, val1, val2 ) \
    657   TEST_FP_OP_H_INTERNAL( testnum, flags, float16 result, float16 val1, float16 val2, float16 0, \
    658                     inst f13, f10, f11; fmv.x.h a0, f13)
    659 
    660 #define TEST_FP_OP2_H_HEX( testnum, inst, flags, result, val1, val2 ) \
    661   TEST_FP_OP_H_INTERNAL( testnum, flags, half result, half val1, half val2, float16 0, \
    662                     inst f13, f10, f11; fmv.x.h a0, f13)
    663 
    664 #define TEST_FP_OP2_D32( testnum, inst, flags, result, val1, val2 ) \
    665   TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, double val1, double val2, double 0, \
    666                     inst f13, f10, f11; fsd f13, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
    667 // ^: store computation result in address from a0, load high-word into t2
    668 
    669 #define TEST_FP_OP2_D32_HEX( testnum, inst, flags, result, val1, val2 ) \
    670   TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, dword val1, dword val2, double 0, \
    671                     inst f13, f10, f11; fsd f13, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
    672 
    673 #define TEST_FP_OP2_D( testnum, inst, flags, result, val1, val2 ) \
    674   TEST_FP_OP_D_INTERNAL( testnum, flags, double result, double val1, double val2, double 0, \
    675                     inst f13, f10, f11; fmv.x.d a0, f13)
    676 
    677 #define TEST_FP_OP2_D_HEX( testnum, inst, flags, result, val1, val2 ) \
    678   TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, dword val1, dword val2, double 0, \
    679                     inst f13, f10, f11; fmv.x.d a0, f13)
    680 
    681 #define TEST_FP_OP3_S( testnum, inst, flags, result, val1, val2, val3 ) \
    682   TEST_FP_OP_S_INTERNAL( testnum, flags, float result, float val1, float val2, float val3, \
    683                     inst f13, f10, f11, f12; fmv.x.s a0, f13)
    684 
    685 #define TEST_FP_OP3_H( testnum, inst, flags, result, val1, val2, val3 ) \
    686   TEST_FP_OP_H_INTERNAL( testnum, flags, float16 result, float16 val1, float16 val2, float16 val3, \
    687                     inst f13, f10, f11, f12; fmv.x.h a0, f13)
    688 
    689 #define TEST_FP_OP3_D32( testnum, inst, flags, result, val1, val2, val3 ) \
    690   TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, double val1, double val2, double val3, \
    691                     inst f13, f10, f11, f12; fsd f13, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
    692 // ^: store computation result in address from a0, load high-word into t2
    693 
    694 #define TEST_FP_OP3_D( testnum, inst, flags, result, val1, val2, val3 ) \
    695   TEST_FP_OP_D_INTERNAL( testnum, flags, double result, double val1, double val2, double val3, \
    696                     inst f13, f10, f11, f12; fmv.x.d a0, f13)
    697 
    698 #define TEST_FP_INT_OP_S( testnum, inst, flags, result, val1, rm ) \
    699   TEST_FP_OP_S_INTERNAL( testnum, flags, word result, float val1, float 0, float 0, \
    700                     inst a0, f10, rm)
    701 
    702 #define TEST_FP_INT_OP_H( testnum, inst, flags, result, val1, rm ) \
    703   TEST_FP_OP_H_INTERNAL( testnum, flags, word result, float16 val1, float16 0, float16 0, \
    704                     inst a0, f10, rm)
    705 
    706 #define TEST_FP_INT_OP_D32( testnum, inst, flags, result, val1, rm ) \
    707   TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, double val1, double 0, double 0, \
    708                     inst a0, f10, rm; li t2, ((result) << 32 >> 63) * -1)
    709 
    710 /* #define TEST_FP_INT_OP_D( testnum, inst, flags, result, val1, rm ) \
    711    TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, double val1, double 0, double 0, \
    712                      inst a0, f10, rm) */
    713 
    714 #define TEST_FP_CMP_OP_S( testnum, inst, flags, result, val1, val2 ) \
    715   TEST_FP_OP_S_INTERNAL( testnum, flags, word result, float val1, float val2, float 0, \
    716                     inst a0, f10, f11)
    717 
    718 #define TEST_FP_CMP_OP_S_HEX( testnum, inst, flags, result, val1, val2 ) \
    719   TEST_FP_OP_S_INTERNAL( testnum, flags, word result, word val1, word val2, float 0, \
    720                     inst a0, f10, f11)
    721 
    722 #define TEST_FP_CMP_OP_H( testnum, inst, flags, result, val1, val2 ) \
    723   TEST_FP_OP_H_INTERNAL( testnum, flags, hword result, float16 val1, float16 val2, float16 0, \
    724                     inst a0, f10, f11)
    725 
    726 #define TEST_FP_CMP_OP_H_HEX( testnum, inst, flags, result, val1, val2 ) \
    727   TEST_FP_OP_H_INTERNAL( testnum, flags, hword result, half val1, half val2, float16 0, \
    728                     inst a0, f10, f11)
    729 
    730 #define TEST_FP_CMP_OP_D32( testnum, inst, flags, result, val1, val2 ) \
    731   TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, double val1, double val2, double 0, \
    732                     inst a0, f10, f11; li t2, 0)
    733 
    734 #define TEST_FP_CMP_OP_D32_HEX( testnum, inst, flags, result, val1, val2 ) \
    735   TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, dword val1, dword val2, double 0, \
    736                     inst a0, f10, f11; li t2, 0)
    737 
    738 #define TEST_FP_CMP_OP_D( testnum, inst, flags, result, val1, val2 ) \
    739   TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, double val1, double val2, double 0, \
    740                     inst a0, f10, f11)
    741 
    742 #define TEST_FP_CMP_OP_D_HEX( testnum, inst, flags, result, val1, val2 ) \
    743   TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, dword val1, dword val2, double 0, \
    744                     inst a0, f10, f11)
    745 
    746 #define TEST_FCLASS_S(testnum, correct, input) \
    747   TEST_CASE(testnum, a0, correct, li a0, input; fmv.s.x f10, a0; \
    748                     fclass.s a0, f10)
    749 
    750 #define TEST_FCLASS_D32(testnum, correct, input) \
    751   TEST_CASE(testnum, a0, correct, \
    752             la a0, test_ ## testnum ## _data ;\
    753             fld f10, 0(a0); \
    754             fclass.d a0, f10) \
    755     .pushsection .data; \
    756     .align 3; \
    757     test_ ## testnum ## _data: \
    758     .dword input; \
    759     .popsection
    760 
    761 #define TEST_FCLASS_D(testnum, correct, input) \
    762   TEST_CASE(testnum, a0, correct, li a0, input; fmv.d.x f10, a0; \
    763                     fclass.d a0, f10)
    764 
    765 #define TEST_INT_FP_OP_S( testnum, inst, result, val1 ) \
    766 test_ ## testnum: \
    767   li  TESTNUM, testnum; \
    768   la  a0, test_ ## testnum ## _data ;\
    769   lw  a3, 0(a0); \
    770   li  a0, val1; \
    771   inst f10, a0; \
    772   fsflags x0; \
    773   fmv.x.s a0, f10; \
    774   bne a0, a3, fail; \
    775   .pushsection .data; \
    776   .align 2; \
    777   test_ ## testnum ## _data: \
    778   .float result; \
    779   .popsection
    780 
    781 #define TEST_INT_FP_OP_H( testnum, inst, result, val1 ) \
    782 test_ ## testnum: \
    783   li  TESTNUM, testnum; \
    784   la  a0, test_ ## testnum ## _data ;\
    785   lh  a3, 0(a0); \
    786   li  a0, val1; \
    787   inst f10, a0; \
    788   fsflags x0; \
    789   fmv.x.h a0, f10; \
    790   bne a0, a3, fail; \
    791   .pushsection .data; \
    792   .align 1; \
    793   test_ ## testnum ## _data: \
    794   .float16 result; \
    795   .popsection
    796 
    797 #define TEST_INT_FP_OP_D32( testnum, inst, result, val1 ) \
    798 test_ ## testnum: \
    799   li  TESTNUM, testnum; \
    800   la  a0, test_ ## testnum ## _data ;\
    801   lw  a3, 0(a0); \
    802   lw  a4, 4(a0); \
    803   li  a1, val1; \
    804   inst f10, a1; \
    805   \
    806   fsd f10, 0(a0); \
    807   lw a1, 4(a0); \
    808   lw a0, 0(a0); \
    809   \
    810   fsflags x0; \
    811   bne a0, a3, fail; \
    812   bne a1, a4, fail; \
    813   .pushsection .data; \
    814   .align 3; \
    815   test_ ## testnum ## _data: \
    816   .double result; \
    817   .popsection
    818 
    819 #define TEST_INT_FP_OP_D( testnum, inst, result, val1 ) \
    820 test_ ## testnum: \
    821   li  TESTNUM, testnum; \
    822   la  a0, test_ ## testnum ## _data ;\
    823   ld  a3, 0(a0); \
    824   li  a0, val1; \
    825   inst f10, a0; \
    826   fsflags x0; \
    827   fmv.x.d a0, f10; \
    828   bne a0, a3, fail; \
    829   .pushsection .data; \
    830   .align 3; \
    831   test_ ## testnum ## _data: \
    832   .double result; \
    833   .popsection
    834 
    835 // We need some special handling here to allow 64-bit comparison in 32-bit arch
    836 // TODO: find a better name and clean up when intended for general usage?
    837 #define TEST_CASE_D32( testnum, testreg1, testreg2, correctval, code... ) \
    838 test_ ## testnum: \
    839     code; \
    840     la  x15, test_ ## testnum ## _data ; \
    841     lw  x7, 0(x15); \
    842     lw  x15, 4(x15); \
    843     li  TESTNUM, testnum; \
    844     bne testreg1, x7, fail;\
    845     bne testreg2, x15, fail;\
    846     .pushsection .data; \
    847     .align 3; \
    848     test_ ## testnum ## _data: \
    849     .dword correctval; \
    850     .popsection
    851 
    852 // ^ x14 is used in some other macros, to avoid issues we use x15 for upper word
    853 
    854 #define MISALIGNED_LOAD_HANDLER \
    855   li t0, CAUSE_MISALIGNED_LOAD; \
    856   csrr t1, mcause; \
    857   bne t0, t1, fail; \
    858   \
    859   /* We got a misaligned exception. Pretend we handled it in software */ \
    860   /* by loading the correct result here. */ \
    861   mv  a4, a5; \
    862   \
    863   /* And skip this instruction */ \
    864   csrr t0, mepc; \
    865   addi t0, t0, 4; \
    866   csrw mepc, t0; \
    867   mret
    868 
    869 #define MISALIGNED_STORE_HANDLER \
    870   li t0, CAUSE_MISALIGNED_STORE; \
    871   csrr t1, mcause; \
    872   bne t0, t1, fail; \
    873   \
    874   /* We got a misaligned exception. Skip this test. */ \
    875   csrw mepc, x15; \
    876   mret
    877 
    878 #-----------------------------------------------------------------------
    879 # Pass and fail code (assumes test num is in TESTNUM)
    880 #-----------------------------------------------------------------------
    881 
    882 #define TEST_PASSFAIL \
    883         bne x0, TESTNUM, pass; \
    884 fail: \
    885         RVTEST_FAIL; \
    886 pass: \
    887         RVTEST_PASS \
    888 
    889 
    890 #-----------------------------------------------------------------------
    891 # Test data section
    892 #-----------------------------------------------------------------------
    893 
    894 #define TEST_DATA
    895 
    896 #endif