// RISC-V Compliance Test Header File // Copyright (c) 2017, Codasip Ltd. All Rights Reserved. // See LICENSE for license details. // // Description: Common header file for RV32I tests #ifndef _TEST_MACROS_H #define _TEST_MACROS_H #include "riscv_macros.h" // RISC-V Compliance IO Test Header File /* * Copyright (c) 2005-2018 Imperas Software Ltd., www.imperas.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * * See the License for the specific language governing permissions and * limitations under the License. * */ // // In general the following registers are reserved // ra, a0, t0, t1 // Additionally on an assertion violation, t1, t2 are overwritten // x1, x10, x5, x6, x7 respectively // Floating registers reserved // f5 // #define MASK_XLEN(x) ((x) & ((1 << (__riscv_xlen - 1) << 1) - 1)) #define SEXT_IMM(x) ((x) | (-(((x) >> 11) & 1) << 11)) // Base function for integer operations #define TEST_CASE(destreg, correctval, swreg, offset, code... ) \ code; \ sw destreg, offset(swreg); \ RVTEST_IO_ASSERT_GPR_EQ(x31, destreg, correctval) \ // Base functions for single precision floating point operations #define TEST_CASE_FP(test_num, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, code... ) \ la a0, test_ ## test_num ## _data; \ flw reg1, 0(a0); \ flw reg2, 4(a0); \ lw t1, 8(a0); \ code; \ fsw destreg, offset(swreg); \ RVTEST_IO_ASSERT_SFPR_EQ(destreg, t1, correctval) \ .pushsection .data; \ .balign 8; \ test_ ## test_num ## _data: \ .float val1; \ .float val2; \ .word correctval; \ .popsection #define TEST_CASE_FP_I(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \ la a0, test_ ## test_num ## _data; \ lw t1, 0(a0); \ code; \ fsw destreg, offset(swreg); \ RVTEST_IO_ASSERT_SFPR_EQ(destreg, t1, correctval) \ .pushsection .data; \ .balign 2; \ test_ ## test_num ## _data: \ .word correctval; \ .popsection #define TEST_CASE_FP_I2(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \ la a0, test_ ## test_num ## _data; \ flw reg, 0(a0); \ lw t1, 4(a0); \ code; \ sw destreg, offset(swreg); \ RVTEST_IO_ASSERT_GPR_EQ(x31, destreg, correctval) \ .pushsection .data; \ .balign 4; \ test_ ## test_num ## _data: \ .float val; \ .word correctval; \ .popsection #define TEST_CASE_FP_4REG(test_num, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset, code... ) \ la a0, test_ ## test_num ## _data; \ flw reg1, 0(a0); \ flw reg2, 4(a0); \ flw reg3, 8(a0); \ lw t1, 12(a0); \ code; \ fsw destreg, offset(swreg); \ RVTEST_IO_ASSERT_SFPR_EQ(destreg, t1, correctval) \ .pushsection .data; \ .balign 16; \ test_ ## test_num ## _data: \ .float val1; \ .float val2; \ .float val3; \ .word correctval; \ .popsection #define TEST_CASE_FP_FMVXS(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \ la a0, test_ ## test_num ## _data; \ flw reg, 0(a0); \ code; \ sw destreg, offset(swreg); \ RVTEST_IO_ASSERT_GPR_EQ(x31, destreg, correctval) \ .pushsection .data; \ .balign 2; \ test_ ## test_num ## _data: \ .float val; \ .popsection #define TEST_CASE_FP_FMVSX(test_num, destreg, reg, correctval, val, swreg, offset, code...) \ la a0, test_ ## test_num ## _data; \ li reg, val; \ code; \ fsw destreg, offset(swreg); \ lw a1, 0(a0); \ RVTEST_IO_ASSERT_SFPR_EQ(destreg, a1, correctval) \ .pushsection .data; \ .balign 2; \ test_ ## test_num ## _data: \ .word correctval; \ .popsection // Base functions for double precision floating point operations - rv32d #define TEST_CASE_FPD(test_num, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, code... ) \ la a0, test_ ## test_num ## _data; \ fld reg1, 0(a0); \ fld reg2, 8(a0); \ code; \ fsd destreg, offset(swreg); \ lw t1, 16(a0); \ lw t2, 20(a0); \ la a0, store_ ## test_num ## _data; \ fsd destreg, 0(a0); \ lw a1, 0(a0); \ lw a2, 4(a0); \ RVTEST_IO_ASSERT_DFPR_EQ(destreg, t2, t1, a2, a1, correctval) \ .pushsection .data; \ .balign 8; \ test_ ## test_num ## _data: \ .double val1; \ .double val2; \ .dword correctval; \ .popsection; \ .pushsection .data; \ store_ ## test_num ## _data: \ .fill 1, 8, -1; \ .popsection #define TEST_CASE_FPD_I(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \ la a0, test_ ## test_num ## _data; \ code; \ fsd destreg, offset(swreg); \ lw t1, 0(a0); \ lw t2, 4(a0); \ la a0, store_ ## test_num ## _data; \ fsd destreg, 0(a0); \ lw a1, 0(a0); \ lw a2, 4(a0); \ RVTEST_IO_ASSERT_DFPR_EQ(destreg, t2, t1, a2, a1, correctval) \ .pushsection .data; \ .balign 2; \ test_ ## test_num ## _data: \ .dword correctval; \ .popsection; \ store_ ## test_num ## _data: \ .fill 1, 8, -1; \ .popsection #define TEST_CASE_FPD_I2(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \ la a0, test_ ## test_num ## _data; \ fld reg, 0(a0); \ lw t1, 8(a0); \ code; \ sw destreg, offset(swreg); \ RVTEST_IO_ASSERT_GPR_EQ(x31, destreg, correctval) \ .pushsection .data; \ .balign 4; \ test_ ## test_num ## _data: \ .double val; \ .word correctval; \ .popsection #define TEST_CASE_FPD_4REG(test_num, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset, code... ) \ la a0, test_ ## test_num ## _data; \ fld reg1, 0(a0); \ fld reg2, 8(a0); \ fld reg3, 16(a0); \ code; \ fsd destreg, offset(swreg); \ lw t1, 24(a0); \ lw t2, 28(a0); \ la a0, store_ ## test_num ## _data; \ fsd destreg, 0(a0); \ lw a1, 0(a0); \ lw a2, 4(a0); \ RVTEST_IO_ASSERT_DFPR_EQ(destreg, t2, t1, a2, a1, correctval) \ .pushsection .data; \ .balign 16; \ test_ ## test_num ## _data: \ .double val1; \ .double val2; \ .double val3; \ .dword correctval; \ .popsection; \ .pushsection .data; \ store_ ## test_num ## _data: \ .fill 1, 8, -1; \ .popsection //Tests for a instructions with register-register operand #define TEST_RR_OP(inst, destreg, reg1, reg2, correctval, val1, val2, swreg, offset) \ TEST_CASE( destreg, correctval, swreg, offset, \ li reg1, MASK_XLEN(val1); \ li reg2, MASK_XLEN(val2); \ inst destreg, reg1, reg2; \ ) #define TEST_RR_SRC1( inst, destreg, reg, correctval, val1, val2, swreg, offset) \ TEST_CASE( destreg, correctval, swreg, offset, \ li destreg, MASK_XLEN(val1); \ li reg, MASK_XLEN(val2); \ inst destreg, destreg, reg; \ ) #define TEST_RR_SRC2( inst, destreg, reg, correctval, val1, val2, swreg, offset) \ TEST_CASE( destreg, correctval, swreg, offset, \ li reg, MASK_XLEN(val1); \ li destreg, MASK_XLEN(val2); \ inst destreg, reg, destreg; \ ) #define TEST_RR_SRC12( inst, destreg, correctval, val, swreg, offset) \ TEST_CASE( destreg, correctval, swreg, offset, \ li destreg, MASK_XLEN(val1); \ inst destreg, destreg, destreg; \ ) #define TEST_RR_ZERO1( inst, destreg, reg, correctval, val, swreg, offset) \ TEST_CASE( destreg, correctval, swreg, offset, \ li reg, MASK_XLEN(val); \ inst destreg, x0, reg; \ ) #define TEST_RR_ZERO2( inst, destreg, reg, correctval, val, swreg, offset) \ TEST_CASE( destreg, correctval, swreg, offset, \ li reg, MASK_XLEN(val); \ inst destreg, reg, x0; \ ) #define TEST_RR_ZERO12( inst, destreg, correctval, swreg, offset) \ TEST_CASE( destreg, correctval, swreg, offset, \ inst destreg, x0, x0; \ ) #define TEST_RR_ZERODEST( inst, reg1, reg2, val1, val2, swreg, offset) \ TEST_CASE( x0, 0, swreg, offset, \ li reg1, MASK_XLEN(val1); \ li reg2, MASK_XLEN(val2); \ inst x0, reg1, reg2; \ ) //Tests for a instructions with register-immediate operand #define TEST_IMM_OP( inst, destreg, reg, correctval, val, imm, swreg, offset) \ TEST_CASE ( destreg, correctval, swreg, offset, \ li reg, MASK_XLEN(val); \ inst destreg, reg, SEXT_IMM(imm); \ ) #define TEST_IMM_SRC( inst, destreg, correctval, val, imm, swreg, offset) \ TEST_CASE ( destreg, correctval, swreg, offset, \ li destreg, MASK_XLEN(val); \ inst destreg, destreg, SEXT_IMM(imm); \ ) #define TEST_IMM_ZEROSRC( inst, destreg, correctval, imm, swreg, offset) \ TEST_CASE ( destreg, correctval, swreg, offset, \ inst destreg, x0, SEXT_IMM(imm); \ ) #define TEST_IMM_ZERODEST( inst, reg, val, imm, swreg, offset) \ TEST_CASE ( x0, 0, swreg, offset, \ li reg, MASK_XLEN(val); \ inst x0, reg, SEXT_IMM(imm); \ ) #define TEST_IMM_ONEREG( inst, destreg, correctval, imm, swreg, offset) \ TEST_CASE ( destreg, correctval, swreg, offset, \ inst destreg, SEXT_IMM(imm); \ ) #define TEST_AUIPC(inst, destreg, correctval, imm, swreg, offset) \ TEST_CASE ( destreg, correctval, swreg, offset, \ 1: \ inst destreg, SEXT_IMM(imm); \ la swreg, 1b; \ sub destreg, destreg, swreg; \ ) //Tests for a compressed instruction #define TEST_CR_OP( inst, destreg, reg, correctval, val1, val2, swreg, offset) \ TEST_CASE ( destreg, correctval, swreg, offset, \ li reg, MASK_XLEN(val1); \ li destreg, MASK_XLEN(val2); \ inst destreg, reg; \ ) #define TEST_CI_OP( inst, destreg, correctval, val, imm, swreg, offset) \ TEST_CASE( destreg, correctval, swreg, offset, \ li destreg, MASK_XLEN(val); \ inst destreg, imm; \ ) #define TEST_CI_OP_NOREG(inst, correctval, imm, swreg, offset) \ TEST_CASE (x0, correctval, swreg, offset, \ inst imm; \ ) //Tests for floating point instructions - single precision #define TEST_FP_OP(test_num, inst, destreg, reg1, reg2, correctval, val1, val2, swreg, offset) \ TEST_CASE_FP(test_num, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, \ inst destreg, reg1, reg2; \ ) #define TEST_FP_ONEREG(test_num, inst, destreg, reg, correctval, val, swreg, offset) \ TEST_CASE_FP(test_num, destreg, reg, reg, correctval, val, val, swreg, offset, \ inst destreg, reg; \ ) #define TEST_FP_4REG(test_num, inst, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset) \ TEST_CASE_FP_4REG(test_num, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset, \ inst destreg, reg1, reg2, reg3; \ ) #define TEST_FP_I(test_num, inst, destreg, reg, correctval, val, swreg, offset) \ TEST_CASE_FP_I(test_num, destreg, reg, correctval, val, swreg, offset, \ li reg, MASK_XLEN(val); \ inst destreg, reg; \ ) #define TEST_FP_I2(test_num, inst, destreg, reg, correctval, val, swreg, offset) \ TEST_CASE_FP_I2(test_num, destreg, reg, correctval, val, swreg, offset, \ inst destreg, reg; \ ) //Tests for floating point instructions - double precision #define TEST_FPD_OP(test_num, inst, destreg, reg1, reg2, correctval, val1, val2, swreg, offset) \ TEST_CASE_FPD(test_num, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, \ inst destreg, reg1, reg2; \ ) #define TEST_FPD_ONEREG(test_num, inst, destreg, reg, correctval, val, swreg, offset) \ TEST_CASE_FPD(test_num, destreg, reg, reg, correctval, val, val, swreg, offset, \ inst destreg, reg; \ ) #define TEST_FPD_4REG(test_num, inst, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset) \ TEST_CASE_FPD_4REG(test_num, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset, \ inst destreg, reg1, reg2, reg3; \ ) #define TEST_FPD_I(test_num, inst, destreg, reg, correctval, val, swreg, offset) \ TEST_CASE_FPD_I(test_num, destreg, reg, correctval, val, swreg, offset, \ li reg, MASK_XLEN(val); \ inst destreg, reg; \ ) #define TEST_FPD_I2(test_num, inst, destreg, reg, correctval, val, swreg, offset) \ TEST_CASE_FPD_I2(test_num, destreg, reg, correctval, val, swreg, offset, \ inst destreg, reg; \ ) #define TEST_CADDI16SP(correctval, imm, swreg, offset) \ TEST_CASE(x2, correctval, swreg, offset, \ c.addi16sp x2, imm; \ ) #define TEST_CADDI4SPN(destreg, correctval, imm, swreg, offset) \ TEST_CASE(destreg, correctval, swreg, offset, \ c.addi4spn destreg, x2, SEXT_IMM(imm); \ ) #define TEST_CJL(inst, reg, val, swreg, offset) \ li x10, val; \ la reg, 1f; \ inst reg; \ li x10, 0x123ab; \ 1: \ sw x10, offset(swreg); \ RVTEST_IO_ASSERT_GPR_EQ(x31, x10, val); \ #define ABS(x) ((x >> 11) ^ x) - (x >> 11) #define TEST_CJ(inst, reg, val, swreg, offset) \ li reg, val; \ inst 1f; \ li reg, 0x123ab; \ 1: \ sw reg, offset(swreg); \ RVTEST_IO_ASSERT_GPR_EQ(x31, reg, val); \ #define TEST_CL(inst, reg, imm, swreg, offset) \ la reg, test_data; \ inst reg, imm(reg); \ sw reg, offset(swreg); \ // lw reg, imm(x2) // c.lwsp reg, imm(x2) #define TEST_CLWSP(reg, imm, swreg, offset) \ la x2, test_data; \ c.lwsp reg, imm(x2); \ sw reg, offset(swreg); \ #define TEST_CSW(test_data, inst, reg1, reg2, val, imm, swreg, offset) \ li reg1, val; \ la reg2, test_data; \ inst reg1, imm(reg2); \ lw reg1, imm(reg2); \ sw reg1, offset(swreg); \ RVTEST_IO_ASSERT_GPR_EQ(x31, reg1, val); \ #define TEST_CSWSP(test_data, reg, val, imm, swreg, offset) \ la x2, test_data; \ li reg, val; \ c.swsp reg, imm(x2); \ lw reg, imm(x2); \ sw reg, offset(swreg); \ RVTEST_IO_ASSERT_GPR_EQ(x31, reg, val); \ #define TEST_CBEQZ(reg, val, swreg, offset) \ li reg, val; \ c.sub reg, reg; \ c.beqz reg, 3f; \ li reg, 0x123ab; \ 3: \ sw reg, offset(swreg); \ RVTEST_IO_ASSERT_GPR_EQ(x31, reg, 0x0); \ #define TEST_CBNEZ(reg, val, swreg, offset) \ li reg, val; \ c.bnez reg, 4f; \ li reg, 0x0; \ 4: \ sw reg, offset(swreg); \ RVTEST_IO_ASSERT_GPR_EQ(x31, reg, val); \ #define TEST_FMVXS(test_num, destreg, reg, correctval, val, swreg, offset) \ TEST_CASE_FP_FMVXS(test_num, destreg, reg, correctval, val, swreg, offset, \ fmv.x.s destreg, reg; \ ) #define TEST_FMVSX(test_num, destreg, reg, correctval, val, swreg, offset) \ TEST_CASE_FP_FMVSX(test_num, destreg, reg, correctval, val, swreg, offset, \ fmv.s.x destreg, reg; \ ) #define SWSIG(a,b) #if __riscv_xlen == 64 #define SATP_MODE SATP64_MODE #else #define SATP_MODE SATP32_MODE #endif #define SATP32_MODE 0x80000000 #define SATP32_ASID 0x7FC00000 #define SATP32_PPN 0x003FFFFF #define SATP64_MODE 0xF000000000000000 #define SATP64_ASID 0x0FFFF00000000000 #define SATP64_PPN 0x00000FFFFFFFFFFF #define SATP_MODE_OFF 0 #define SATP_MODE_SV32 1 #define SATP_MODE_SV39 8 #define SATP_MODE_SV48 9 #define SATP_MODE_SV57 10 #define SATP_MODE_SV64 11 #define TEST_FP_OP2_D32( testnum, inst, flags, result, val1, val2 ) \ TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, val1, val2, 0.0, \ inst f3, f0, f1; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0)) #define TEST_CASE_D32( testnum, testreg1, testreg2, correctval, code... ) \ test_ ## testnum: \ code; \ la x31, test_ ## testnum ## _data ; \ lw x29, 0(x31); \ lw x31, 4(x31); \ li TESTNUM, testnum; \ bne testreg1, x29, fail;\ bne testreg2, x31, fail;\ .pushsection .data; \ .balign 8; \ test_ ## testnum ## _data: \ .dword correctval; \ .popsection #define TEST_FP_OP_D32_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \ test_ ## testnum: \ li TESTNUM, testnum; \ la a0, test_ ## testnum ## _data ;\ fld f0, 0(a0); \ fld f1, 8(a0); \ fld f2, 16(a0); \ lw a3, 24(a0); \ lw t1, 28(a0); \ code; \ fsflags a1, x0; \ li a2, flags; \ bne a0, a3, fail; \ bne t1, t2, fail; \ bne a1, a2, fail; \ .pushsection .data; \ .balign 8; \ test_ ## testnum ## _data: \ .double val1; \ .double val2; \ .double val3; \ .result; \ .popsection #define TEST_FP_OP1_D32( testnum, inst, flags, result, val1 ) \ TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, val1, 0.0, 0.0, \ inst f3, f0; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0)) #define TEST_FCLASS_D32(testnum, correct, input) \ TEST_CASE(testnum, a0, correct, \ la a0, test_ ## testnum ## _data ;\ fld fa0, 0(a0); \ fclass.d a0, fa0) \ .pushsection .data; \ .balign 8; \ test_ ## testnum ## _data: \ .dword input; \ .popsection #define TEST_FP_CMP_OP_D32( testnum, inst, flags, result, val1, val2 ) \ TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, val1, val2, 0.0, \ inst a0, f0, f1; li t2, 0) #define TEST_INT_FP_OP_D32( testnum, inst, result, val1 ) \ test_ ## testnum: \ li TESTNUM, testnum; \ la a0, test_ ## testnum ## _data ;\ lw a3, 0(a0); \ lw a4, 4(a0); \ li a1, val1; \ inst f0, a1; \ \ fsd f0, 0(a0); \ lw a1, 4(a0); \ lw a0, 0(a0); \ \ fsflags x0; \ bne a0, a3, fail; \ bne a1, a4, fail; \ .pushsection .data; \ .balign 8; \ test_ ## testnum ## _data: \ .double result; \ .popsection #define TEST_FCVT_S_D32( testnum, result, val1 ) \ TEST_FP_OP_D32_INTERNAL( testnum, 0, double result, val1, 0.0, 0.0, \ fcvt.s.d f3, f0; fcvt.d.s f3, f3; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0)) #define TEST_FP_OP3_D32( testnum, inst, flags, result, val1, val2, val3 ) \ TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, val1, val2, val3, \ inst f3, f0, f1, f2; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0)) #define TEST_FP_OP1_D32_DWORD_RESULT( testnum, inst, flags, result, val1 ) \ TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \ inst f3, f0; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0)) #endif