mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-03 02:05:21 +00:00
1140 lines
46 KiB
C
1140 lines
46 KiB
C
/* These are macros to manage storing signatures, selecting what to save */
|
|
/* keeping track of the hidden offset, and ensuring it doesn't overflow */
|
|
/* They're useful across many tests, but generally for specific classes of ops */
|
|
|
|
|
|
/* This function set up the Page table entry for Sv32 Translation scheme
|
|
Arguments:
|
|
_PAR: Register containing Physical Address
|
|
_PR: Register containing Permissions for Leaf PTE.
|
|
(Note: No-leaf PTE (if-any) has only valid permssion (pte.v) set)
|
|
_TR0, _TR1, _TR2: Temporary registers used and modified by function
|
|
VA: Virtual address
|
|
level: Level at which PTE would be setup
|
|
0: Two level translation
|
|
1: Superpage
|
|
*/
|
|
|
|
#define LEVEL0 0x00
|
|
#define LEVEL1 0x01
|
|
#define LEVEL2 0x02
|
|
#define LEVEL3 0x03
|
|
#define LEVEL4 0x04
|
|
|
|
#define sv39 0x00
|
|
#define sv48 0x01
|
|
#define sv57 0x02
|
|
|
|
#define CODE code_bgn_off
|
|
#define DATA data_bgn_off
|
|
#define SIG sig_bgn_off
|
|
#define VMEM vmem_bgn_off
|
|
|
|
#define ALL_MEM_PMP ;\
|
|
li t2, -1 ;\
|
|
csrw pmpaddr0, t2 ;\
|
|
li t2, 0x0F ;\
|
|
csrw pmpcfg0, t2 ;\
|
|
sfence.vma ;
|
|
|
|
#define SIGNATURE_AREA(TYPE,ARG1,ARG2, ...) ;\
|
|
LI (t0, ARG1) ;\
|
|
.if(TYPE == CODE) ;\
|
|
LI (t1, ARG2) ;\
|
|
sub t0, t0, t1 ;\
|
|
csrr sp, mscratch ;\
|
|
add t1,sp,t0 ;\
|
|
csrw sscratch, t1 ;\
|
|
.else ;\
|
|
LA (t1, ARG2) ;\
|
|
sub t0, t0, t1 ;\
|
|
.endif ;\
|
|
LREG t1, TYPE+0*sv_area_sz(sp) ;\
|
|
add t2, t1, t0 ;\
|
|
SREG t2, TYPE+1*sv_area_sz(sp) ;
|
|
|
|
//****NOTE: label `rvtest_Sroot_pg_tbl` must be declared after RVTEST_DATA_END
|
|
// in the test aligned at 4kiB (use .align 12)
|
|
|
|
#define PTE_SETUP_RV32(_PAR, _PR, _TR0, _TR1, VA, level) ;\
|
|
srli _PAR, _PAR, 12 ;\
|
|
slli _PAR, _PAR, 10 ;\
|
|
or _PAR, _PAR, _PR ;\
|
|
.if (level==1) ;\
|
|
LA(_TR1, rvtest_Sroot_pg_tbl) ;\
|
|
.set vpn, ((VA>>22)&0x3FF)<<2 ;\
|
|
.endif ;\
|
|
.if (level==0) ;\
|
|
LA(_TR1, rvtest_slvl1_pg_tbl) ;\
|
|
.set vpn, ((VA>>12)&0x3FF)<<2 ;\
|
|
.endif ;\
|
|
LI(_TR0, vpn) ;\
|
|
add _TR1, _TR1, _TR0 ;\
|
|
SREG _PAR, 0(_TR1);
|
|
|
|
#define PTE_SETUP_RV64(_PAR, _PR, _TR0, _TR1, VA, level, mode) ;\
|
|
srli _PAR, _PAR, 12 ;\
|
|
slli _PAR, _PAR, 10 ;\
|
|
or _PAR, _PAR, _PR ;\
|
|
.if (mode == sv39) ;\
|
|
.if (level == 2) ;\
|
|
LA(_TR1, rvtest_Sroot_pg_tbl) ;\
|
|
.set vpn, ((VA >> 30) & 0x1FF) << 3 ;\
|
|
.endif ;\
|
|
.if (level == 1) ;\
|
|
LA(_TR1, rvtest_slvl1_pg_tbl) ;\
|
|
.set vpn, ((VA >> 21) & 0x1FF) << 3 ;\
|
|
.endif ;\
|
|
.if (level == 0) ;\
|
|
LA(_TR1, rvtest_slvl2_pg_tbl) ;\
|
|
.set vpn, ((VA >> 12) & 0x1FF) << 3 ;\
|
|
.endif ;\
|
|
.endif ;\
|
|
.if (mode == sv48) ;\
|
|
.if (level == 3) ;\
|
|
LA(_TR1, rvtest_Sroot_pg_tbl) ;\
|
|
.set vpn, ((VA >> 39) & 0x1FF) << 3 ;\
|
|
.endif ;\
|
|
.if (level == 2) ;\
|
|
LA(_TR1, rvtest_slvl1_pg_tbl) ;\
|
|
.set vpn, ((VA >> 30) & 0x1FF) << 3 ;\
|
|
.endif ;\
|
|
.if (level == 1) ;\
|
|
LA(_TR1, rvtest_slvl2_pg_tbl) ;\
|
|
.set vpn, ((VA >> 21) & 0x1FF) << 3 ;\
|
|
.endif ;\
|
|
.if (level == 0) ;\
|
|
LA(_TR1, rvtest_slvl3_pg_tbl) ;\
|
|
.set vpn, ((VA >> 12) & 0x1FF) << 3 ;\
|
|
.endif ;\
|
|
.endif ;\
|
|
.if (mode == sv57) ;\
|
|
.if (level == 4) ;\
|
|
LA(_TR1, rvtest_Sroot_pg_tbl) ;\
|
|
.set vpn, ((VA >> 48) & 0x1FF) << 3 ;\
|
|
.endif ;\
|
|
.if (level == 3) ;\
|
|
LA(_TR1, rvtest_slvl1_pg_tbl) ;\
|
|
.set vpn, ((VA >> 39) & 0x1FF) << 3 ;\
|
|
.endif ;\
|
|
.if (level == 2) ;\
|
|
LA(_TR1, rvtest_slvl2_pg_tbl) ;\
|
|
.set vpn, ((VA >> 30) & 0x1FF) << 3 ;\
|
|
.endif ;\
|
|
.if (level == 1) ;\
|
|
LA(_TR1, rvtest_slvl3_pg_tbl) ;\
|
|
.set vpn, ((VA >> 21) & 0x1FF) << 3 ;\
|
|
.endif ;\
|
|
.if (level == 0) ;\
|
|
LA(_TR1, rvtest_slvl3_pg_tbl) ;\
|
|
.set vpn, ((VA >> 12) & 0x1FF) << 3 ;\
|
|
.endif ;\
|
|
.endif ;\
|
|
LI(_TR0, vpn) ;\
|
|
add _TR1, _TR1, _TR0 ;\
|
|
SREG _PAR, 0(_TR1) ;
|
|
|
|
#define PTE_PERMUPD_RV32(_PR, _TR0, _TR1, VA, level) ;\
|
|
.if (level==1) ;\
|
|
LA(_TR1, rvtest_Sroot_pg_tbl) ;\
|
|
.set vpn, ((VA>>22)&0x3FF)<<2 ;\
|
|
.endif ;\
|
|
.if (level==0) ;\
|
|
LA(_TR1, rvtest_slvl1_pg_tbl) ;\
|
|
.set vpn, ((VA>>12)&0x3FF)<<2 ;\
|
|
.endif ;\
|
|
LI(_TR0, vpn) ;\
|
|
add _TR1, _TR1, _TR0 ;\
|
|
LREG _TR0, 0(_TR1) ;\
|
|
srli _TR0, _TR0, 10 ;\
|
|
slli _TR0, _TR0, 10 ;\
|
|
or _TR0, _TR0, _PR ;\
|
|
SREG _TR0, 0(_TR1) ;
|
|
|
|
#define SATP_SETUP_SV32 ;\
|
|
LA(t6, rvtest_Sroot_pg_tbl) ;\
|
|
LI(t5, SATP32_MODE) ;\
|
|
srli t6, t6, 12 ;\
|
|
or t6, t6, t5 ;\
|
|
csrw satp, t6 ;
|
|
|
|
#define SATP_SETUP_RV64(MODE) ;\
|
|
LA(t6, rvtest_Sroot_pg_tbl) ;\
|
|
.if (MODE == sv39) ;\
|
|
LI(t5, (SATP64_MODE) & (SATP_MODE_SV39 << 60)) ;\
|
|
.endif ;\
|
|
.if (MODE == sv48) ;\
|
|
LI(t5, (SATP64_MODE) & (SATP_MODE_SV48 << 60)) ;\
|
|
.endif ;\
|
|
.if (MODE == sv57) ;\
|
|
LI(t5, (SATP64_MODE) & (SATP_MODE_SV57 << 60)) ;\
|
|
.endif ;\
|
|
.if (MODE == sv64) ;\
|
|
LI(t5, (SATP64_MODE) & (SATP_MODE_SV64 << 60)) ;\
|
|
.endif ;\
|
|
srli t6, t6, 12 ;\
|
|
or t6, t6, t5 ;\
|
|
csrw satp, t6 ;
|
|
|
|
//Tests for atomic memory operation(AMO) instructions
|
|
#define TEST_AMO_OP(inst, destreg, origptr, reg2, origval, updval, sigptr, ...) ;\
|
|
.if NARG(__VA_ARGS__) == 1 ;\
|
|
.set offset,_ARG1(__VA_OPT__(__VA_ARGS__,0)) ;\
|
|
.endif ;\
|
|
LI(reg2, MASK_XLEN(origval)) ;\
|
|
RVTEST_SIGUPD(sigptr, reg2) /*Write original AMO src */ ;\
|
|
LI(reg2, MASK_XLEN(updval)) ;\
|
|
addi origptr, sigptr, offset-REGWIDTH /* Calculate where orig AMO src is stored */ ;\
|
|
inst destreg, reg2, (origptr) /*origval -> destreg; updated val -> (origptr) */ ;\
|
|
RVTEST_SIGUPD(sigptr, destreg) /* write original AMO val */
|
|
|
|
|
|
|
|
#define NAN_BOXED(__val__,__width__,__max__) ;\
|
|
.if __width__ == 32 ;\
|
|
.word __val__ ;\
|
|
.else ;\
|
|
.dword __val__ ;\
|
|
.endif ;\
|
|
.if __max__ > __width__ ;\
|
|
.set pref_bytes,(__max__-__width__)/32 ;\
|
|
.else ;\
|
|
.set pref_bytes, 0 ;\
|
|
.endif ;\
|
|
.rept pref_bytes ;\
|
|
.word 0xffffffff ;\
|
|
.endr ;
|
|
|
|
#define ZERO_EXTEND(__val__,__width__,__max__) ;\
|
|
.if __max__ > __width__ ;\
|
|
.set pref_bytes,(__max__-__width__)/32 ;\
|
|
.else ;\
|
|
.set pref_bytes, 0 ;\
|
|
.endif ;\
|
|
.rept pref_bytes ;\
|
|
.word 0 ;\
|
|
.endr ;\
|
|
.if __width__ == 32 ;\
|
|
.word __val__ ;\
|
|
.else ;\
|
|
.dword __val__ ;\
|
|
.endif;
|
|
|
|
#define RVTEST_FP_ENABLE() ;\
|
|
LI(a0, (MSTATUS_FS & (MSTATUS_FS >> 1))) ;\
|
|
csrs mstatus, a0 ;\
|
|
csrwi fcsr, 0
|
|
|
|
// This macro is for vector
|
|
#define RVTEST_VXSAT_ENABLE() ;\
|
|
LI(a0, (MSTATUS_VS & (MSTATUS_VS >> 1))) ;\
|
|
csrs mstatus, a0 ;\
|
|
clrov
|
|
|
|
/* RVTEST_SIGBASE(reg, label) initializes to label and clears offset */
|
|
#define RVTEST_SIGBASE(_R,_TAG) ;\
|
|
LA(_R,_TAG) ;\
|
|
.set offset,0
|
|
|
|
// This macro is loading data from memory with any offset value
|
|
// This macro is loading data from memory with any offset value
|
|
#define LOAD_MEM_VAL(_LINST, _AREG, _RD, _OFF, _TREG) ;\
|
|
.if (((_OFF & ~0x07FF)== 0) |((_OFF | 0x07FF)== -1)) ;\
|
|
_LINST _RD, _OFF(_AREG) /* yes, it fits */ ;\
|
|
.else /* no, needs base adj */ ;\
|
|
.set _off, SEXT_IMM(_OFF) /* strip off hi bits */ ;\
|
|
.set cry, BIT(_off,11)<<12 ;\
|
|
LI( _TREG, (_OFF & ~0x0FFF)+cry) /* strip off hi bits*/ ;\
|
|
add _AREG, _AREG, _TREG /* modified temp base*/ ;\
|
|
_LINST _RD, _off(_AREG) ;\
|
|
sub _AREG, _AREG, _TREG /* undo modification */ ;\
|
|
.endif
|
|
/* this function ensures individual sig stores don't exceed offset limits */
|
|
/* if they would, update the base and reduce offset by 2048 - _SZ */
|
|
/* an option is to pre-incr offset if there was a previous signature store */
|
|
#define CHK_OFFSET(_BREG, _SZ, _PRE_INC) ;\
|
|
.if (_PRE_INC!=0) ;\
|
|
.set offset, offset+_SZ ;\
|
|
.endif ;\
|
|
.if offset >= 2048 ;\
|
|
addi _BREG, _BREG, (2048 - _SZ) ;\
|
|
.set offset, offset - (2048 - _SZ) ;\
|
|
.endif
|
|
|
|
/* automatically adjust base and offset if offset gets too big, resetting offset */
|
|
/* RVTEST_SIGUPD(basereg, sigreg) stores sigreg at offset(basereg) and updates offset by regwidth */
|
|
/* RVTEST_SIGUPD(basereg, sigreg,newoff) stores sigreg at newoff(basereg) and updates offset to regwidth+newoff */
|
|
#define RVTEST_SIGUPD(_BR,_R,...) ;\
|
|
.if NARG(__VA_ARGS__) == 1 ;\
|
|
.set offset,_ARG1(__VA_OPT__(__VA_ARGS__,0)) ;\
|
|
.endif ;\
|
|
CHK_OFFSET(_BR, REGWIDTH,0) ;\
|
|
SREG _R,offset(_BR) ;\
|
|
.set offset,offset+REGWIDTH
|
|
|
|
/* RVTEST_SIGUPD_F(basereg, sigreg,flagreg,newoff) */
|
|
/* This macro is used to store the signature values of (32 & 64) F and D */
|
|
/* teats which use TEST_(FPSR_OP, FPIO_OP, FPRR_OP, FPR4_OP) opcodes */
|
|
/* It stores both an Xreg and an Freg, first adjusting base & offset to */
|
|
/* to keep offset < 2048. SIGALIGN is set to the max(FREGWIDTH, REGWIDTH)*/
|
|
/* _BR - Base Reg, _R - FReg, _F - Fstatus Xreg */
|
|
#define RVTEST_SIGUPD_F(_BR,_R,_F,...) ;\
|
|
.if NARG(__VA_ARGS__) == 1 ;\
|
|
.set offset,_ARG1(__VA_OPT__(__VA_ARGS__,0)) ;\
|
|
.endif ;\
|
|
.if (offset&(SIGALIGN-1))!=0 ;\
|
|
/* Throw warnings then modify offset to target */ ;\
|
|
.warning "Incorrect signature Offset Alignment." ;\
|
|
.set offset, offset&(SIGALIGN-1)+SIGALIGN ;\
|
|
.endif ;\
|
|
CHK_OFFSET(_BR, SIGALIGN, 0) ;\
|
|
FSREG _R,offset(_BR) ;\
|
|
CHK_OFFSET(_BR, SIGALIGN, 1) ;\
|
|
SREG _F,offset(_BR) ;\
|
|
.set offset,offset+SIGALIGN
|
|
|
|
/* RVTEST_SIGUPD_FID(basereg, sigreg,flagreg,newoff) */
|
|
/* This macro stores the signature values of (32 & 64) F & D insts */
|
|
/* which uses TEST_(FPID_OP, FCMP_OP) ops */
|
|
/* It stores two integer registers. SigReg is stored @offset[BaseReg], */
|
|
/* FlagReg at offset+Regwidth[BaseReg]. It updates offset by 2*regwidth */
|
|
/* and post increments so repeated uses store sig values sequentially */
|
|
/* _BR - Base Reg, _R - Signature reg, _F - Flag reg */
|
|
#define RVTEST_SIGUPD_FID(_BR,_R,_F,...) ;\
|
|
.if NARG(__VA_ARGS__) == 1 ;\
|
|
.set offset,_ARG1(__VA_OPT__(__VA_ARGS__,0)) ;\
|
|
.endif ;\
|
|
.if (offset&(SIGALIGN-1))!=0 ;\
|
|
/* Throw warnings then modify offset to target */ ;\
|
|
.warning "Signature Incorrect Offset Alignment." ;\
|
|
.set offset, offset&(SIGALIGN-1)+SIGALIGN ;\
|
|
.endif ;\
|
|
CHK_OFFSET(_BR, REGWIDTH, 0) ;\
|
|
SREG _R,offset(_BR) ;\
|
|
CHK_OFFSET(_BR, REGWIDTH, 1) ;\
|
|
SREG _F,offset(_BR) ;\
|
|
.set offset,offset+REGWIDTH
|
|
|
|
|
|
// for updating signatures that include flagreg for P-ext saturation instructions (RV32/RV64).
|
|
#define RVTEST_SIGUPD_PK(_BR,_R,_F,...) ;\
|
|
.if NARG(__VA_ARGS__) == 1 ;\
|
|
.set offset,_ARG1(__VA_OPT__(__VA_ARGS__,0)) ;\
|
|
.endif ;\
|
|
.if (offset & (REGWIDTH-1)) != 0 ;\
|
|
.warning "Signature Incorrect Offset Alignment." ;\
|
|
.set offset, offset&(SIGALIGN-1)+SIGALIGN ;\
|
|
.endif ;\
|
|
CHK_OFFSET(_BR,REGWIDTH,0) ;\
|
|
SREG _R,offset(_BR) ;\
|
|
CHK_OFFSET(_BR,REGWIDTH,1) ;\
|
|
SREG _F,offset(_BR) ;\
|
|
.set offset,offset+(REGWIDTH)
|
|
|
|
// for updating signatures when 'rd' is a paired register (64-bit)
|
|
// in Zpsfoperand extension in RV32; this reuses RVTEST_SIGUPD_PK()
|
|
#define RVTEST_SIGUPD_P64(_BR,_R,_R_HI,...) ;\
|
|
.if NARG(__VA_ARGS__) == 0 ;\
|
|
RVTEST_SIGUPD_PK(_BR,_R,_R_HI) ;\
|
|
.else ;\
|
|
RVTEST_SIGUPD_PK(_BR,_R,_R_HI,_ARG1(__VA_OPT__(__VA_ARGS__,0))) ;\
|
|
.endif
|
|
|
|
// for updating signatures that include flagreg when 'rd' is a
|
|
// paired register (64-bit) in Zpsfoperand extension in RV32.
|
|
#define RVTEST_SIGUPD_PK64(_BR,_R,_R_HI,_F,...) ;\
|
|
rdov _F ;\
|
|
.if NARG(__VA_ARGS__) == 1 ;\
|
|
.set offset,_ARG1(__VA_OPT__(__VA_ARGS__,0)) ;\
|
|
.endif ;\
|
|
.if (offset & (REGWIDTH-1)) != 0 ;\
|
|
.warning "Incorrect Offset Alignment for Signature." ;\
|
|
.set offset, offset&(SIGALIGN-1)+SIGALIGN ;\
|
|
.endif ;\
|
|
CHK_OFFSET(_BR,REGWIDTH,0) ;\
|
|
SREG _R,offset(_BR) ;\
|
|
CHK_OFFSET(_BR,REGWIDTH,1) ;\
|
|
SREG _R_HI,offset(_BR) ;\
|
|
CHK_OFFSET(_BR,REGWIDTH,1) ;\
|
|
SREG _F,offset(_BR) ;\
|
|
.set offset,offset+(REGWIDTH)
|
|
|
|
|
|
|
|
/* DEPRECATE this is redundant with RVTEST_BASEUPD(BR,_NR), */
|
|
/* except it doesn't correct for offset overflow while moving */
|
|
#define RVTEST_VALBASEMOV(_NR,_BR) ;\
|
|
add _NR, _BR, x0;
|
|
|
|
#define RVTEST_VALBASEUPD(_BR,...) ;\
|
|
.if NARG(__VA_ARGS__) == 0 ;\
|
|
addi _BR,_BR,2040 ;\
|
|
.endif ;\
|
|
.if NARG(__VA_ARGS__) == 1 ;\
|
|
LA(_BR,_ARG1(__VA_ARGS__,x0)) ;\
|
|
.endif
|
|
|
|
/*
|
|
* RVTEST_BASEUPD(base reg) - updates the base register the last signature address + REGWIDTH
|
|
* RVTEST_BASEUPD(base reg, new reg) - moves value of the next signature region to update into new reg
|
|
* The hidden variable offset is reset always
|
|
*/
|
|
|
|
#define RVTEST_BASEUPD(_BR,...) ;\
|
|
/* deal with case where offset>=2047 */ ;\
|
|
.set corr 2048-REGWIDTH ;\
|
|
.if offset <2048 ;\
|
|
.set corr offset ;\
|
|
.endif ;\
|
|
.set offset, offset-corr ;\
|
|
;\
|
|
.if NARG(__VA_ARGS__) == 0 ;\
|
|
addi _BR, _BR, corr ;\
|
|
.else ;\
|
|
addi _ARG1(__VA_ARGS__,x0) ,_BR, corr ;\
|
|
.endif
|
|
|
|
//==============================================================================
|
|
// This section borrows from Andrew's from Andrew Waterman's risc-v test macros
|
|
// They are used to generate tests; some are op specific, some format specific
|
|
//==============================================================================
|
|
|
|
#define TEST_JALR_OP(tempreg, rd, rs1, imm, swreg, offset,adj) ;\
|
|
5: ;\
|
|
LA(rd,5b) ;\
|
|
.if adj & 1 == 1 ;\
|
|
LA(rs1, 3f-imm+adj-1) ;\
|
|
jalr rd, imm+1(rs1) ;\
|
|
.else ;\
|
|
LA(rs1, 3f-imm+adj) ;\
|
|
jalr rd, imm(rs1) ;\
|
|
.endif ;\
|
|
nop ;\
|
|
nop ;\
|
|
xori rd,rd, 0x2 ;\
|
|
j 4f ;\
|
|
;\
|
|
3: .if adj & 2 == 2 ;\
|
|
.fill 2,1,0x00 ;\
|
|
.endif ;\
|
|
xori rd,rd, 0x3 ;\
|
|
j 4f ;\
|
|
.if adj&2 == 2 ;\
|
|
.fill 2,1,0x00 ;\
|
|
.endif ;\
|
|
;\
|
|
4: LA(tempreg, 5b) ;\
|
|
andi tempreg,tempreg,~(3) ;\
|
|
sub rd,rd,tempreg ;\
|
|
RVTEST_SIGUPD(swreg,rd,offset)
|
|
|
|
|
|
#define TEST_JAL_OP(tempreg, rd, imm, label, swreg, offset, adj) ;\
|
|
5: ;\
|
|
LA(tempreg, 2f) ;\
|
|
jalr x0,0(tempreg) ;\
|
|
6: LA(tempreg, 4f) ;\
|
|
jalr x0,0(tempreg) ;\
|
|
1: .if adj & 2 == 2 ;\
|
|
.ifc label, 1b ;\
|
|
.fill 2,1,0x00 ;\
|
|
.endif ;\
|
|
.endif ;\
|
|
xori rd,rd, 0x1 ;\
|
|
beq x0,x0,6b ;\
|
|
.if adj & 2 == 2 ;\
|
|
.ifc label, 1b ;\
|
|
.fill 2,1,0x00 ;\
|
|
.endif ;\
|
|
.endif ;\
|
|
.if (imm/2) - 2 >= 0 ;\
|
|
.set num,(imm/2)-2 ;\
|
|
.else ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.ifc label, 3f ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.rept num ;\
|
|
nop ;\
|
|
.endr ;\
|
|
;\
|
|
2: jal rd, label+(adj) ;\
|
|
.if adj & 2 == 2 ;\
|
|
nop ;\
|
|
nop ;\
|
|
.endif ;\
|
|
xori rd,rd, 0x2 ;\
|
|
j 4f ;\
|
|
.if (imm/2) - 3 >= 0 ;\
|
|
.set num,(imm/2)-3 ;\
|
|
.else ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.ifc label, 1b ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.rept num ;\
|
|
nop ;\
|
|
.endr ;\
|
|
3: .if adj & 2 == 2 ;\
|
|
.ifc label, 3f ;\
|
|
.fill 2,1,0x00 ;\
|
|
.endif ;\
|
|
.endif ;\
|
|
xori rd,rd, 0x3 ;\
|
|
LA(tempreg, 4f) ;\
|
|
jalr x0,0(tempreg) ;\
|
|
.if adj & 2 == 2 ;\
|
|
.ifc label, 3f ;\
|
|
.fill 2,1,0x00 ;\
|
|
.endif ;\
|
|
.endif ;\
|
|
4: LA(tempreg, 5b) ;\
|
|
andi tempreg,tempreg,~(3) ;\
|
|
sub rd,rd,tempreg ;\
|
|
RVTEST_SIGUPD(swreg,rd,offset)
|
|
//SREG rd, offset(swreg);
|
|
|
|
#define TEST_BRANCH_OP(inst, tempreg, reg1, reg2, val1, val2, imm, label, swreg, offset,adj) \
|
|
LI(reg1, MASK_XLEN(val1)) ;\
|
|
LI(reg2, MASK_XLEN(val2)) ;\
|
|
addi tempreg,x0,0 ;\
|
|
j 2f ;\
|
|
;\
|
|
1: .if adj & 2 == 2 ;\
|
|
.fill 2,1,0x00 ;\
|
|
.endif ;\
|
|
addi tempreg,tempreg, 0x1 ;\
|
|
j 4f ;\
|
|
.if adj & 2 == 2 ;\
|
|
.fill 2,1,0x00 ;\
|
|
.endif ;\
|
|
.if (imm/2) - 2 >= 0 ;\
|
|
.set num,(imm/2)-2 ;\
|
|
.else ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.ifc label, 3f ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.rept num ;\
|
|
nop ;\
|
|
.endr ;\
|
|
;\
|
|
2: inst reg1, reg2, label+adj ;\
|
|
addi tempreg, tempreg,0x2 ;\
|
|
j 4f ;\
|
|
.if (imm/4) - 3 >= 0 ;\
|
|
.set num,(imm/4)-3 ;\
|
|
.else ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.ifc label, 1b ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.rept num ;\
|
|
nop ;\
|
|
.endr ;\
|
|
;\
|
|
3: .if adj & 2 == 2 ;\
|
|
.fill 2,1,0x00 ;\
|
|
.endif ;\
|
|
addi tempreg, tempreg,0x3 ;\
|
|
j 4f ;\
|
|
.if adj&2 == 2 ;\
|
|
.fill 2,1,0x00 ;\
|
|
.endif ;\
|
|
;\
|
|
4: RVTEST_SIGUPD(swreg,tempreg,offset)
|
|
|
|
|
|
#define TEST_STORE(swreg,testreg,index,rs1,rs2,rs2_val,imm_val,offset,inst,adj) ;\
|
|
LI(rs2,rs2_val) ;\
|
|
addi rs1,swreg,offset+adj ;\
|
|
LI(testreg,imm_val) ;\
|
|
sub rs1,rs1,testreg ;\
|
|
inst rs2, imm_val(rs1) ;\
|
|
nop ;\
|
|
nop
|
|
|
|
#define TEST_LOAD(swreg,testreg,index,rs1,destreg,imm_val,offset,inst,adj);\
|
|
LA(rs1,rvtest_data+(index*4)+adj-imm_val);\
|
|
inst destreg, imm_val(rs1) ;\
|
|
nop ;\
|
|
nop ;\
|
|
RVTEST_SIGUPD(swreg,destreg,offset)
|
|
|
|
#define TEST_STORE_F(swreg,testreg,fcsr_val,rs1,rs2,imm_val,offset,inst,adj,flagreg,valaddr_reg, val_offset);\
|
|
LOAD_MEM_VAL(FLREG, valaddr_reg, rs2, val_offset, testreg);\
|
|
addi rs1,swreg,offset+adj ;\
|
|
LI(testreg,imm_val) ;\
|
|
sub rs1,rs1,testreg ;\
|
|
inst rs2, imm_val(rs1) ;\
|
|
nop ;\
|
|
nop ;\
|
|
csrr flagreg, fcsr ;\
|
|
RVTEST_SIGUPD(swreg,flagreg,offset+SIGALIGN)
|
|
|
|
#define TEST_LOAD_F(swreg,testreg,fcsr_val,rs1,destreg,imm_val,inst,adj,flagreg) ;\
|
|
LA(rs1,rvtest_data+adj-imm_val) ;\
|
|
LI(testreg, fcsr_val) ;\
|
|
csrw fcsr, testreg ;\
|
|
inst destreg, imm_val(rs1) ;\
|
|
nop ;\
|
|
nop ;\
|
|
csrr flagreg, fcsr ;\
|
|
RVTEST_SIGUPD_F(swreg,destreg,flagreg)
|
|
|
|
#define TEST_CBO_ZERO(swreg,rs1,inst,imm_val) ;\
|
|
LI(rs1,imm_val&(RVMODEL_CBZ_BLOCKSIZE-1)) ;\
|
|
add rs1,rs1,swreg ;\
|
|
inst (rs1) ;\
|
|
nop ;\
|
|
nop ;\
|
|
ADDI(swreg, swreg, RVMODEL_CBZ_BLOCKSIZE)
|
|
|
|
#define TEST_CSR_FIELD(ADDRESS,TEMP_REG,MASK_REG,NEG_MASK_REG,VAL,DEST_REG,OFFSET,BASE_REG) ;\
|
|
LI(TEMP_REG,VAL) ;\
|
|
and TEMP_REG,TEMP_REG,MASK_REG ;\
|
|
csrr DEST_REG,ADDRESS ;\
|
|
and DEST_REG,DEST_REG,NEG_MASK_REG ;\
|
|
or TEMP_REG,TEMP_REG,DEST_REG ;\
|
|
csrw ADDRESS,TEMP_REG ;\
|
|
csrr DEST_REG,ADDRESS ;\
|
|
RVTEST_SIGUPD(BASE_REG,DEST_REG,OFFSET)
|
|
|
|
|
|
#define TEST_CASE(testreg, destreg, correctval, swreg, offset, code... ) ;\
|
|
code ;\
|
|
RVTEST_SIGUPD(swreg,destreg,offset) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval)
|
|
|
|
#define TEST_CASE_F(testreg, destreg, correctval, swreg, flagreg, code... ) ;\
|
|
code ;\
|
|
RVTEST_SIGUPD_F(swreg,destreg,flagreg) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval)
|
|
|
|
#define TEST_CASE_FID(testreg, destreg, correctval, swreg, flagreg, code... ) ;\
|
|
code; \
|
|
RVTEST_SIGUPD_FID(swreg,destreg,flagreg) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval)
|
|
|
|
#define TEST_AUIPC(inst, destreg, correctval, imm, swreg, offset, testreg) ;\
|
|
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
|
LA testreg, 1f ;\
|
|
1: ;\
|
|
inst destreg, imm ;\
|
|
sub destreg, destreg, testreg ;\
|
|
)
|
|
|
|
//Tests for instructions with register-immediate operand
|
|
#define TEST_IMM_OP( inst, destreg, reg, correctval, val, imm, swreg, offset, testreg) ;\
|
|
TEST_CASE(testreg, destreg, correctval, swreg, offset, ;\
|
|
LI(reg, MASK_XLEN(val)) ;\
|
|
inst destreg, reg, SEXT_IMM(imm) ;\
|
|
)
|
|
|
|
//Tests for floating-point instructions with a single register operand
|
|
#define TEST_FPSR_OP( inst, destreg, freg, rm, fcsr_val, correctval, valaddr_reg, val_offset, flagreg, swreg, testreg) \
|
|
TEST_CASE_F(testreg, destreg, correctval, swreg, flagreg, \
|
|
LOAD_MEM_VAL(FLREG, valaddr_reg, freg, val_offset, testreg); \
|
|
LI(testreg, fcsr_val) ;\
|
|
csrw fcsr, testreg ;\
|
|
inst destreg, freg, rm ;\
|
|
csrr flagreg, fcsr ;\
|
|
)
|
|
|
|
//Tests for floating-point instructions with a single register operand
|
|
//This variant does not take the rm field and set it while writing the instruction
|
|
#define TEST_FPSR_OP_NRM( inst, destreg, freg, fcsr_val, correctval, valaddr_reg, val_offset, flagreg, swreg, testreg) \
|
|
TEST_CASE_F(testreg, destreg, correctval, swreg, flagreg, \
|
|
LOAD_MEM_VAL(FLREG, valaddr_reg, freg, val_offset, testreg) ;\
|
|
li testreg, fcsr_val; csrw fcsr, testreg ;\
|
|
inst destreg, freg ;\
|
|
csrr flagreg, fcsr ;\
|
|
)
|
|
|
|
//Tests for floating-point instructions with a single register operand and integer destination register
|
|
#define TEST_FPID_OP( inst, destreg, freg, rm, fcsr_val, correctval, valaddr_reg, val_offset, flagreg, swreg, testreg,load_instr) \
|
|
TEST_CASE_FID(testreg, destreg, correctval, swreg, flagreg, \
|
|
LOAD_MEM_VAL(load_instr, valaddr_reg, freg, val_offset, testreg) ;\
|
|
li testreg, fcsr_val; csrw fcsr, testreg ;\
|
|
inst destreg, freg, rm ;\
|
|
csrr flagreg, fcsr ;\
|
|
)
|
|
|
|
//Tests for floating-point instructions with a single register operand and integer operand register
|
|
#define TEST_FPIO_OP( inst, destreg, freg, rm, fcsr_val, correctval, valaddr_reg, val_offset, flagreg, swreg, testreg, load_instr) \
|
|
TEST_CASE_F(testreg, destreg, correctval, swreg, flagreg, \
|
|
LOAD_MEM_VAL(load_instr, valaddr_reg, freg, val_offset, testreg) ;\
|
|
li testreg, fcsr_val; csrw fcsr, testreg ;\
|
|
inst destreg, freg, rm ;\
|
|
csrr flagreg, fcsr ;\
|
|
)
|
|
|
|
//Tests for floating-point instructions with a single register operand and integer destination register
|
|
//This variant does not take the rm field and set it while writing the instruction
|
|
#define TEST_FPID_OP_NRM( inst, destreg, freg, fcsr_val, correctval, valaddr_reg, val_offset, flagreg, swreg, testreg) \
|
|
TEST_CASE_FID(testreg, destreg, correctval, swreg, flagreg, \
|
|
LOAD_MEM_VAL(FLREG, valaddr_reg, freg, val_offset, testreg) ;\
|
|
li testreg, fcsr_val; csrw fcsr, testreg ;\
|
|
inst destreg, freg ;\
|
|
csrr flagreg, fcsr ;\
|
|
)
|
|
|
|
//Tests for floating-point instructions with a single register operand and integer operand register
|
|
//This variant does not take the rm field and set it while writing the instruction
|
|
#define TEST_FPIO_OP_NRM( inst, destreg, freg, fcsr_val, correctval, valaddr_reg, val_offset, flagreg, swreg, testreg, load_instr) \
|
|
TEST_CASE_F(testreg, destreg, correctval, swreg, flagreg, \
|
|
LOAD_MEM_VAL(load_instr, valaddr_reg, freg, val_offset, testreg) ;\
|
|
li testreg, fcsr_val; csrw fcsr, testreg ;\
|
|
inst destreg, freg ;\
|
|
csrr flagreg, fcsr ;\
|
|
)
|
|
|
|
//Tests for instructions with register-register-immediate operands
|
|
#define TEST_RRI_OP(inst, destreg, reg1, reg2, imm, correctval, val1, val2, swreg, offset, testreg) \
|
|
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
|
LI(reg1, MASK_XLEN(val1)) ;\
|
|
LI(reg2, MASK_XLEN(val2)) ;\
|
|
inst destreg, reg1, reg2, imm ;\
|
|
)
|
|
|
|
//Tests for a instructions with register-register operand
|
|
#define TEST_RI_OP(inst, destreg, reg1, reg2, imm, correctval, val1, val2, swreg, offset, testreg) \
|
|
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
|
LI(reg1, MASK_XLEN(val1)) ;\
|
|
LI(reg2, MASK_XLEN(val2)) ;\
|
|
inst destreg, reg1, reg2, imm ;\
|
|
)
|
|
|
|
//Tests for a instructions with register-register operand
|
|
#define TEST_RR_OP(inst, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, testreg) \
|
|
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
|
LI(reg1, MASK_XLEN(val1)) ;\
|
|
LI(reg2, MASK_XLEN(val2)) ;\
|
|
inst destreg, reg1, reg2 ;\
|
|
)
|
|
//Tests for floating-point instructions with register-register operand
|
|
//This variant does not take the rm field and set it while writing the instruction
|
|
#define TEST_FPRR_OP_NRM(inst, destreg, freg1, freg2, fcsr_val, correctval, valaddr_reg, val_offset, flagreg, swreg, testreg) \
|
|
TEST_CASE_F(testreg, destreg, correctval, swreg, flagreg, \
|
|
LOAD_MEM_VAL(FLREG, valaddr_reg, freg1, val_offset, testreg) ;\
|
|
LOAD_MEM_VAL(FLREG, valaddr_reg, freg2, (val_offset+FREGWIDTH), testreg) ;\
|
|
li testreg, fcsr_val; csrw fcsr, testreg ;\
|
|
inst destreg, freg1, freg2 ;\
|
|
csrr flagreg, fcsr ;\
|
|
)
|
|
|
|
//Tests for floating-point instructions with register-register operand
|
|
#define TEST_FPRR_OP(inst, destreg, freg1, freg2, rm, fcsr_val, correctval, valaddr_reg, val_offset, flagreg, swreg, testreg) \
|
|
TEST_CASE_F(testreg, destreg, correctval, swreg, flagreg, \
|
|
LOAD_MEM_VAL(FLREG, valaddr_reg, freg1, val_offset, testreg) ;\
|
|
LOAD_MEM_VAL(FLREG, valaddr_reg, freg2, (val_offset+FREGWIDTH), testreg) ;\
|
|
li testreg, fcsr_val; csrw fcsr, testreg ;\
|
|
inst destreg, freg1, freg2, rm ;\
|
|
csrr flagreg, fcsr ;\
|
|
)
|
|
|
|
//Tests for floating-point CMP instructions with register-register operand
|
|
#define TEST_FCMP_OP(inst, destreg, freg1, freg2, fcsr_val, correctval, valaddr_reg, val_offset, flagreg, swreg, testreg) \
|
|
TEST_CASE_FID(testreg, destreg, correctval, swreg, flagreg, \
|
|
LOAD_MEM_VAL(FLREG, valaddr_reg, freg1, val_offset, testreg) ;\
|
|
LOAD_MEM_VAL(FLREG, valaddr_reg, freg2, (val_offset+FREGWIDTH), testreg) ;\
|
|
li testreg, fcsr_val; csrw fcsr, testreg ;\
|
|
inst destreg, freg1, freg2 ;\
|
|
csrr flagreg, fcsr ;\
|
|
)
|
|
|
|
//Tests for floating-point R4 type instructions
|
|
#define TEST_FPR4_OP(inst, destreg, freg1, freg2, freg3, rm , fcsr_val, correctval, valaddr_reg, val_offset, flagreg, swreg, testreg) \
|
|
TEST_CASE_F(testreg, destreg, correctval, swreg, flagreg, \
|
|
LOAD_MEM_VAL(FLREG, valaddr_reg, freg1, val_offset, testreg) ;\
|
|
LOAD_MEM_VAL(FLREG, valaddr_reg, freg2, (val_offset+FREGWIDTH), testreg) ;\
|
|
LOAD_MEM_VAL(FLREG, valaddr_reg, freg3, (val_offset+2*FREGWIDTH), testreg);\
|
|
li testreg, fcsr_val; csrw fcsr, testreg ;\
|
|
inst destreg, freg1, freg2, freg3, rm ;\
|
|
csrr flagreg, fcsr ;\
|
|
)
|
|
|
|
#define TEST_CNOP_OP( inst, testreg, imm_val, swreg, offset) \
|
|
TEST_CASE(testreg, x0, 0, swreg, offset, \
|
|
inst imm_val ;\
|
|
)
|
|
|
|
//Tests for instructions with register-immediate operand and update the saturation flag
|
|
#define TEST_PKIMM_OP( inst, destreg, reg, correctval, val, imm, flagreg, swreg, offset, testreg) \
|
|
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
|
LI(reg, MASK_XLEN(val)) ;\
|
|
inst destreg, reg, SEXT_IMM(imm) ;\
|
|
rdov flagreg ;\
|
|
)
|
|
|
|
//Tests for instructions with register-register operand and update the saturation flag
|
|
#define TEST_PKRR_OP(inst, destreg, reg1, reg2, correctval, val1, val2, flagreg, swreg, offset, testreg) \
|
|
LI(reg1, MASK_XLEN(val1)) ;\
|
|
LI(reg2, MASK_XLEN(val2)) ;\
|
|
inst destreg, reg1, reg2 ;\
|
|
rdov flagreg ;\
|
|
RVTEST_SIGUPD_PK(swreg, destreg, flagreg, offset) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval)
|
|
|
|
//Tests for instructions with a single register operand and update the saturation flag
|
|
#define TEST_PKR_OP( inst, destreg, reg, correctval, val, flagreg, swreg, offset, testreg) \
|
|
LI(reg, MASK_XLEN(val)) ;\
|
|
inst destreg, reg ;\
|
|
rdov flagreg ;\
|
|
RVTEST_SIGUPD_PK(swreg,destreg,flagreg,offset) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval)
|
|
|
|
#if __riscv_xlen == 32
|
|
//Tests for a instruction with register pair operands for all its three operands
|
|
#define TEST_P64_PPP_OP_32(inst, destreg, destreg_hi, reg1, reg1_hi, reg2, reg2_hi, correctval, correctval_hi, val1, val1_hi, val2, val2_hi, swreg, offset, testreg) \
|
|
LI(reg1, MASK_XLEN(val1)) ;\
|
|
LI(reg1_hi, MASK_XLEN(val1_hi)) ;\
|
|
LI(reg2, MASK_XLEN(val2)) ;\
|
|
LI(reg2_hi, MASK_XLEN(val2_hi)) ;\
|
|
inst destreg, reg1, reg2 ;\
|
|
RVTEST_SIGUPD_P64(swreg,destreg, destreg_hi, offset) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg_hi, correctval_hi)
|
|
|
|
#define TEST_PK64_PPP_OP_32(inst, destreg, destreg_hi, reg1, reg1_hi, reg2, reg2_hi, correctval, correctval_hi, val1, val1_hi, val2, val2_hi, flagreg, swreg, offset, testreg) \
|
|
LI(reg1, MASK_XLEN(val1)) ;\
|
|
LI(reg1_hi, MASK_XLEN(val1_hi)) ;\
|
|
LI(reg2, MASK_XLEN(val2)) ;\
|
|
LI(reg2_hi, MASK_XLEN(val2_hi)) ;\
|
|
inst destreg, reg1, reg2 ;\
|
|
RVTEST_SIGUPD_PK64(swreg,destreg, destreg_hi, flagreg, offset) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg_hi, correctval_hi)
|
|
|
|
#define TEST_P64_PPN_OP_32(inst, destreg, destreg_hi, reg1, reg1_hi, reg2, correctval, correctval_hi, val1, val1_hi, val2, swreg, offset, testreg) \
|
|
LI(reg1, MASK_XLEN(val1)) ;\
|
|
LI(reg1_hi, MASK_XLEN(val1_hi)) ;\
|
|
LI(reg2, MASK_XLEN(val2)) ;\
|
|
inst destreg, reg1, reg2 ;\
|
|
RVTEST_SIGUPD_P64(swreg, destreg, destreg_hi, offset) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg_hi, correctval_hi)
|
|
|
|
#define TEST_P64_PNN_OP_32(inst, destreg, destreg_hi, reg1, reg2, correctval, correctval_hi, val1, val2, swreg, offset, testreg) \
|
|
LI(reg1, MASK_XLEN(val1)) ;\
|
|
LI(reg2, MASK_XLEN(val2)) ;\
|
|
inst destreg, reg1, reg2 ;\
|
|
RVTEST_SIGUPD_P64(swreg, destreg, destreg_hi, offset) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg_hi, correctval_hi)
|
|
|
|
#define TEST_PK64_PNN_OP_32(inst, destreg, destreg_hi, reg1, reg2, correctval, correctval_hi, val1, val2, flagreg, swreg, offset, testreg) \
|
|
LI(reg1, MASK_XLEN(val1)) ;\
|
|
LI(reg2, MASK_XLEN(val2)) ;\
|
|
inst destreg, reg1, reg2 ;\
|
|
RVTEST_SIGUPD_PK64(swreg, destreg, destreg_hi, flagreg, offset) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg_hi, correctval_hi)
|
|
|
|
#define TEST_P64_NPN_OP_32(inst, destreg, reg1, reg1_hi, reg2, correctval, val1, val1_hi, val2, swreg, offset, testreg) \
|
|
LI(reg1, MASK_XLEN(val1)) ;\
|
|
LI(reg1_hi, MASK_XLEN(val1_hi)) ;\
|
|
LI(reg2, MASK_XLEN(val2)) ;\
|
|
inst destreg, reg1, reg2 ;\
|
|
RVTEST_SIGUPD(swreg,destreg,offset) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval);
|
|
|
|
#define TEST_P64_NP_OP_32(inst, destreg, reg1, reg1_hi, correctval, val1, val1_hi, imm_val, swreg, offset, testreg) \
|
|
LI(reg1, MASK_XLEN(val1)) ;\
|
|
LI(reg1_hi, MASK_XLEN(val1_hi)) ;\
|
|
inst destreg, reg1, imm_val ;\
|
|
RVTEST_SIGUPD(swreg,destreg,offset) ;\
|
|
RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval);
|
|
|
|
//Tests for a instruction with pair register rd, pair register rs1 and pair register rs2
|
|
#define TEST_P64_PPP_OP(inst, rd, rd_hi, rs1, rs1_hi, rs2, rs2_hi, correctval, correctval_hi, rs1_val, rs1_val_hi, rs2_val, rs2_val_hi, swreg, offset, testreg) \
|
|
TEST_P64_PPP_OP_32(inst, rd, rd_hi, rs1, rs1_hi, rs2, rs2_hi, correctval, correctval_hi, rs1_val, rs1_val_hi, rs2_val, rs2_val_hi, swreg, offset, testreg)
|
|
#define TEST_PK64_PPP_OP(inst, rd, rd_hi, rs1, rs1_hi, rs2, rs2_hi, correctval, correctval_hi, rs1_val, rs1_val_hi, rs2_val, rs2_val_hi, flagreg, swreg, offset, testreg) \
|
|
TEST_PK64_PPP_OP_32(inst, rd, rd_hi, rs1, rs1_hi, rs2, rs2_hi, correctval, correctval_hi, rs1_val, rs1_val_hi, rs2_val, rs2_val_hi, flagreg, swreg, offset, testreg)
|
|
//Tests for a instruction with pair register rd, pair register rs1 and normal register rs2
|
|
#define TEST_P64_PPN_OP(inst, rd, rd_hi, rs1, rs1_hi, rs2, correctval, correctval_hi, rs1_val, rs1_val_hi, rs2_val, swreg, offset, testreg) \
|
|
TEST_P64_PPN_OP_32(inst, rd, rd_hi, rs1, rs1_hi, rs2, correctval, correctval_hi, rs1_val, rs1_val_hi, rs2_val, swreg, offset, testreg)
|
|
//Tests for a instruction with pair register rd, normal register rs1 and normal register rs2
|
|
#define TEST_P64_PNN_OP(inst, rd, rd_hi, rs1, rs2, correctval, correctval_hi, rs1_val, rs2_val, swreg, offset, testreg) \
|
|
TEST_P64_PNN_OP_32(inst, rd, rd_hi, rs1, rs2, correctval, correctval_hi, rs1_val, rs2_val, swreg, offset, testreg)
|
|
//Tests for a instruction with pair register rd, normal register rs1 and normal register rs2
|
|
#define TEST_PK64_PNN_OP(inst, rd, rd_hi, rs1, rs2, correctval, correctval_hi, rs1_val, rs2_val, flagreg, swreg, offset, testreg) \
|
|
TEST_PK64_PNN_OP_32(inst, rd, rd_hi, rs1, rs2, correctval, correctval_hi, rs1_val, rs2_val, flagreg, swreg, offset, testreg)
|
|
//Tests for a instruction with normal register rd, pair register rs1 and normal register rs2
|
|
#define TEST_P64_NPN_OP(inst, rd, rs1, rs1_hi, rs2, correctval, correctval_hi, rs1_val, rs1_val_hi, rs2_val, swreg, offset, testreg) \
|
|
TEST_P64_NPN_OP_32(inst, rd, rs1, rs1_hi, rs2, correctval, correctval_hi, rs1_val, rs1_val_hi, rs2_val, swreg, offset, testreg)
|
|
//Tests for a instruction with normal register rd, pair register rs1
|
|
#define TEST_P64_NP_OP(inst, rd, rs1, rs1_hi, correctval, correctval_hi, rs1_val, rs1_val_hi, imm_val, swreg, offset, testreg) \
|
|
TEST_P64_NP_OP_32(inst, rd, rs1, rs1_hi, correctval, correctval_hi, rs1_val, rs1_val_hi, imm_val, swreg, offset, testreg)
|
|
|
|
#else
|
|
|
|
// When in rv64, there are no instructions with pair operand, so Macro is redefined to normal TEST_RR_OP
|
|
#define TEST_P64_PPP_OP(inst, rd, rd_hi, rs1, rs1_hi, rs2, rs2_hi, correctval, correctval_hi, rs1_val, rs1_val_hi, rs2_val, rs2_val_hi, swreg, offset, testreg) \
|
|
TEST_RR_OP(inst, rd, rs1, rs2, correctval, rs1_val, rs2_val, swreg, offset, testreg)
|
|
#define TEST_PK64_PPP_OP(inst, rd, rd_hi, rs1, rs1_hi, rs2, rs2_hi, correctval, correctval_hi, rs1_val, rs1_val_hi, rs2_val, rs2_val_hi, flagreg, swreg, offset, testreg) \
|
|
TEST_PKRR_OP(inst, rd, rs1, rs2, correctval, rs1_val, rs2_val, flagreg, swreg, offset, testreg)
|
|
#define TEST_P64_PPN_OP(inst, rd, rd_hi, rs1, rs1_hi, rs2, correctval, correctval_hi, rs1_val, rs1_val_hi, rs2_val, swreg, offset, testreg) \
|
|
TEST_RR_OP(inst, rd, rs1, rs2, correctval, rs1_val, rs2_val, swreg, offset, testreg)
|
|
#define TEST_P64_PNN_OP(inst, rd, rd_hi, rs1, rs2, correctval, correctval_hi, rs1_val, rs2_val, swreg, offset, testreg) \
|
|
TEST_RR_OP(inst, rd, rs1, rs2, correctval, rs1_val, rs2_val, swreg, offset, testreg)
|
|
#define TEST_PK64_PNN_OP(inst, rd, rd_hi, rs1, rs2, correctval, correctval_hi, rs1_val, rs2_val, flagreg, swreg, offset, testreg) \
|
|
TEST_PKRR_OP(inst, rd, rs1, rs2, correctval, rs1_val, rs2_val, flagreg, swreg, offset, testreg)
|
|
#define TEST_P64_NPN_OP(inst, rd, rs1, rs1_hi, rs2, correctval, correctval_hi, rs1_val, rs1_val_hi, rs2_val, swreg, offset, testreg) \
|
|
TEST_RR_OP(inst, rd, rs1, rs2, correctval, rs1_val, rs2_val, swreg, offset, testreg)
|
|
#define TEST_P64_NP_OP(inst, rd, rs1, rs1_hi, correctval, correctval_hi, rs1_val, rs1_val_hi, imm_val, swreg, offset, testreg) \
|
|
TEST_IMM_OP(inst, rd, rs1, correctval, rs1_val, imm_val, swreg, offset, testreg)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define TEST_CMV_OP( inst, destreg, reg, correctval, val2, swreg, offset, testreg) \
|
|
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
|
LI(reg, MASK_XLEN(val2)) ;\
|
|
inst destreg, reg ;\
|
|
)
|
|
|
|
#define TEST_CR_OP( inst, destreg, reg, correctval, val1, val2, swreg, offset, testreg) \
|
|
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
|
LI(reg, MASK_XLEN(val2)) ;\
|
|
LI(destreg, MASK_XLEN(val1)) ;\
|
|
inst destreg, reg ;\
|
|
)
|
|
|
|
#define TEST_CI_OP( inst, destreg, correctval, val, imm, swreg, offset, testreg) \
|
|
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
|
LI(destreg, MASK_XLEN(val)) ;\
|
|
inst destreg, imm ;\
|
|
)
|
|
|
|
#define TEST_CADDI4SPN_OP( inst, destreg, correctval, imm, swreg, offset, testreg) \
|
|
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
|
LI(x2, 0) ;\
|
|
inst destreg, x2,imm ;\
|
|
)
|
|
|
|
//Tests for instructions with single (rd/rs1) register operand.
|
|
#define TEST_CRD_OP(inst, destreg, correctval, val1, swreg, offset, testreg) \
|
|
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
|
LI(destreg, MASK_XLEN(val1)) ;\
|
|
inst destreg ;\
|
|
)
|
|
|
|
//Tests for instructions with a destination and single source register operand
|
|
#define TEST_RD_OP(inst, destreg, reg1, correctval, val1, swreg, offset, testreg) \
|
|
TEST_CMV_OP(inst, destreg, reg1, correctval, val1, swreg, offset, testreg)
|
|
|
|
#define TEST_CBRANCH_OP(inst, tempreg, reg2, val2, imm, label, swreg, offset) \
|
|
LI(reg2, MASK_XLEN(val2)) ;\
|
|
j 2f ;\
|
|
addi tempreg, x0,0 ;\
|
|
.option push ;\
|
|
.option norvc ;\
|
|
1: addi tempreg, tempreg,0x1 ;\
|
|
j 4f ;\
|
|
.option pop ;\
|
|
.if (imm/2) - 4 >= 0 ;\
|
|
.set num,(imm/2)-4 ;\
|
|
.else ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.ifc label, 3f ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.rept num ;\
|
|
c.nop ;\
|
|
.endr ;\
|
|
2: inst reg2, label ;\
|
|
.option push ;\
|
|
.option norvc ;\
|
|
addi tempreg, tempreg, 0x2 ;\
|
|
j 4f ;\
|
|
.option pop ;\
|
|
.if (imm/2) - 5 >= 0 ;\
|
|
.set num,(imm/2)-5 ;\
|
|
.else ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.ifc label, 1b ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.rept num ;\
|
|
c.nop ;\
|
|
.endr ;\
|
|
;\
|
|
3: addi tempreg, tempreg ,0x3 ;\
|
|
;\
|
|
4: RVTEST_SIGUPD(swreg,tempreg,offset)
|
|
|
|
#define TEST_CJ_OP(inst, tempreg, imm, label, swreg, offset) \
|
|
.option push ;\
|
|
.option norvc ;\
|
|
j 2f ;\
|
|
addi tempreg,x0,0 ;\
|
|
1: addi tempreg, tempreg,0x1 ;\
|
|
j 4f ;\
|
|
.option pop ;\
|
|
.if (imm/2) - 4 >= 0 ;\
|
|
.set num,(imm/2)-4 ;\
|
|
.else ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.ifc label, 3f ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.rept num ;\
|
|
c.nop ;\
|
|
.endr ;\
|
|
2: inst label ;\
|
|
.option push ;\
|
|
.option norvc ;\
|
|
addi tempreg, tempreg, 0x2 ;\
|
|
j 4f ;\
|
|
.option pop ;\
|
|
.if (imm/2) - 5 >= 0 ;\
|
|
.set num,(imm/2)-5 ;\
|
|
.else ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.ifc label, 1b ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.rept num ;\
|
|
c.nop ;\
|
|
.endr ;\
|
|
;\
|
|
3: addi tempreg, tempreg, 0x3 ;\
|
|
;\
|
|
4: RVTEST_SIGUPD(swreg,tempreg,offset)
|
|
|
|
#define TEST_CJAL_OP(inst, tempreg, imm, label, swreg, offset) \
|
|
5: ;\
|
|
j 2f ;\
|
|
;\
|
|
.option push ;\
|
|
.option norvc ;\
|
|
1: xori x1,x1, 0x1 ;\
|
|
j 4f ;\
|
|
.option pop ;\
|
|
.if (imm/2) - 4 >= 0 ;\
|
|
.set num,(imm/2)-4 ;\
|
|
.else ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.ifc label, 3f ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.rept num ;\
|
|
c.nop ;\
|
|
.endr ;\
|
|
2: inst label ;\
|
|
.option push ;\
|
|
.option norvc ;\
|
|
xori x1,x1, 0x2 ;\
|
|
j 4f ;\
|
|
.option pop ;\
|
|
.if (imm/2) - 5 >= 0 ;\
|
|
.set num,(imm/2)-5 ;\
|
|
.else ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.ifc label, 1b ;\
|
|
.set num,0 ;\
|
|
.endif ;\
|
|
.rept num ;\
|
|
c.nop ;\
|
|
.endr ;\
|
|
;\
|
|
3: xori x1,x1, 0x3 ;\
|
|
;\
|
|
4: LA(tempreg, 5b) ;\
|
|
andi tempreg,tempreg,~(3) ;\
|
|
sub x1,x1,tempreg ;\
|
|
RVTEST_SIGUPD(swreg,x1,offset)
|
|
|
|
#define TEST_CJR_OP(tempreg, rs1, swreg, offset) \
|
|
5: ;\
|
|
LA(rs1, 3f) ;\
|
|
;\
|
|
2: c.jr rs1 ;\
|
|
xori rs1,rs1, 0x2 ;\
|
|
j 4f ;\
|
|
;\
|
|
3: xori rs1,rs1, 0x3 ;\
|
|
;\
|
|
4: LA(tempreg, 5b) ;\
|
|
andi tempreg,tempreg,~(3) ;\
|
|
sub rs1,rs1,tempreg ;\
|
|
RVTEST_SIGUPD(swreg,rs1,offset)
|
|
|
|
#define TEST_CJALR_OP(tempreg, rs1, swreg, offset) \
|
|
5: ;\
|
|
LA(rs1, 3f) ;\
|
|
;\
|
|
2: c.jalr rs1 ;\
|
|
xori x1,x1, 0x2 ;\
|
|
j 4f ;\
|
|
;\
|
|
3: xori x1,x1, 0x3 ;\
|
|
;\
|
|
4: LA(tempreg, 5b) ;\
|
|
andi tempreg,tempreg,~(3) ;\
|
|
sub x1,x1,tempreg ;\
|
|
RVTEST_SIGUPD(swreg,x1,offset)
|
|
|
|
|
|
//--------------------------------- Migration aliases ------------------------------------------
|
|
#ifdef RV_COMPLIANCE_RV32M
|
|
#warning "RV_COMPLIANCE_RV32M macro will be deprecated."
|
|
#define RVMODEL_BOOT \
|
|
RVTEST_IO_INIT ;\
|
|
RV_COMPLIANCE_RV32M ;\
|
|
RV_COMPLIANCE_CODE_BEGIN
|
|
#endif
|
|
|
|
#define SWSIG(a, b)
|
|
|
|
#ifdef RV_COMPLIANCE_DATA_BEGIN
|
|
#warning "RV_COMPLIANCE_DATA_BEGIN macro deprecated in v0.2. Please use RVMODEL_DATA_BEGIN instead"
|
|
#define RVMODEL_DATA_BEGIN \
|
|
RV_COMPLIANCE_DATA_BEGIN
|
|
#endif
|
|
|
|
#ifdef RV_COMPLIANCE_DATA_END
|
|
#warning "RV_COMPLIANCE_DATA_END macro deprecated in v0.2. Please use RVMODEL_DATA_END instead"
|
|
#define RVMODEL_DATA_END \
|
|
RV_COMPLIANCE_DATA_END
|
|
#endif
|
|
|
|
#ifdef RV_COMPLIANCE_HALT
|
|
#warning "RV_COMPLIANCE_HALT macro deprecated in v0.2. Please use RVMODEL_HALT instead"
|
|
#define RVMODEL_HALT \
|
|
RV_COMPLIANCE_HALT
|
|
#endif
|
|
|
|
#ifdef RVTEST_IO_ASSERT_GPR_EQ
|
|
#warning "RVTEST_IO_ASSERT_GPR_EQ macro deprecated in v0.2. Please use RVMODEL_IO_ASSERT_GPR_EQ instead"
|
|
#define RVMODEL_IO_ASSERT_GPR_EQ(_SP, _R, _I) \
|
|
RVTEST_IO_ASSERT_GPR_EQ(_SP,_R, _I)
|
|
#endif
|
|
|
|
#ifdef RVTEST_IO_WRITE_STR
|
|
#warning "RVTEST_IO_WRITE_STR macro deprecated in v0.2. Please use RVMODEL_IO_WRITE_STR instead"
|
|
#define RVMODEL_IO_WRITE_STR(_SP, _STR) \
|
|
RVTEST_IO_WRITE_STR(_SP, _STR)
|
|
#endif
|
|
|
|
#ifdef RVTEST_IO_INIT
|
|
#warning "RVTEST_IO_INIT is deprecated in v0.2. Please use RVMODEL_BOOT for initialization"
|
|
#endif
|
|
|
|
#ifdef RVTEST_IO_CHECK
|
|
#warning "RVTEST_IO_CHECK is deprecated in v0.2.
|
|
#endif
|