diff --git a/ChangeLog.md b/ChangeLog.md index 084ca74..f4e8baf 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -11,6 +11,45 @@ NOTE: X-commit messages below refer to git commits in the following I-commit: https://github.com/riscv/riscv-isa-manual V-commit: https://github.com/riscv/riscv-v-spec +- EBREAK and ECALL no longer count as retired instructions if priv_version + is set to master. +- SC instruction behavior has been changed so that store address alignment is + validated even if the reservation check fails (previously, alignment was + validated only if the reservation check succeeded). +- Masking of the mcountinhibit CSR has been corrected - previously, bit 1 and + bits 63...32 were writeable when they should have been 0. +- The nmi signal has been corrected to match the documented behavior, execution + resumes at the nmi_address parameter value when the nmi signal goes high +- The optional Core-Local Interrupt Controller (CLIC) has been implemented + (version 0.9-draft-20191208). +- Vector version 0.9 has been added, and is now used by default. Differences + compared to the previous 0.8 version are as follows (with the associated + specification V-commit identifiers): + - V-commit bdb8b55: mstatus.VS and sstatus.VS fields have moved to bits 10:9; + - V-commit b25b643: new CSR vcsr has been added and fields VXSAT and VXRM + fields relocated there from CSR fcsr; + - V-commit 951b64f: mirrors of fcsr fields have been removed from vcsr. + - V-commit 1aceea2: vfslide1up.vf and vfslide1down.vf instructions added. + - V-commit e256d65: vfcvt.rtz.xu.f.v, vfcvt.rtz.x.f.v, vfwcvt.rtz.xu.f.v, + vfwcvt.rtz.x.f.v, vfncvt.rtz.xu.f.v and vfncvt.rtz.x.f.v instructions added; + - V-commit 8a9fbce (and others): fractional LMUL support added, controlled by + an extended vtype.vlmul CSR field; + - V-commit f414f4d (and others): vector tail agnostic and vector mask agnostic + fields added to the vtype CSR; + - V-commit a526fb9 (and others): all vector load/store instructions replaced + with new instructions that explicitly encode EEW of data or index; + - V-commit ef531ea: whole register load and store operation encodings changed; + - V-commit bdc85cd: vzext.vf2, vsext.vf2, vzext.vf4, vsext.vf4, vzext.vf8 and + vsext.vf8 instructions added; + - V-commit 9a77e12: MLEN is always 1. +- Some Vector Extension issues have been corrected: + - Instructions vfmv.s.f and vfmv.f.s now require that SEW is a supported + floating point size (pending vector specification clarification). + +Date 2020-March-31 +Release 20200330.0 +=== + - The priority order for handling simultaneous interrupts destined for the same privilege level has been corrected (previously, these were handled so that higher interrupt numbers were higher priority). diff --git a/LICENSE.pdf b/LICENSE.pdf index 6951351..81fa8c6 100644 Binary files a/LICENSE.pdf and b/LICENSE.pdf differ diff --git a/README.md b/README.md index 3f6f07b..a373578 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ A Complete, Fully Functional, Configurable RISC-V Simulator === Author: Imperas Software, Ltd., using OVP Open Standard APIs -Date : 30 Mar 2020 -Version: 20200330.0 +Date : 18 May 2020 +Version: 20200518.0 License: Model source included under Apache 2.0 open source license License: Simulator riscvOVPsim licensed under Open Virtual Platforms (OVP) Fixed Platform Kits license RISC-V Specifications currently supported: - RISC-V Instruction Set Manual, Volume I: User-Level ISA (User Architecture Version 20190305-Base-Ratification) - RISC-V Instruction Set Manual, Volume II: Privileged Architecture (Privileged Architecture Version 20190405-Priv-MSU-Ratification) -- RISC-V Instruction Set Manual, RISC-V "V" Vector Extension (with version configurable in the model using the 'vector_version' parameter. 'master' version conforms to specification changes up to 4 March 2020 and is regularly updated to track the evolving specification.) +- RISC-V Instruction Set Manual, RISC-V "V" Vector Extension (with version configurable in the model using the 'vector_version' parameter. 'master' version conforms to specification changes up to 15 May 2020 and is regularly updated to track the evolving specification.) - RISCV Extension B (Bit Manipulation) - Run command: riscvOVPsim.exe --override riscvOVPsim/cpu/add_Extensions=B --showoverrides - This will produce a formatted string, similar to 'Info (Bit Manipulation) extB Version(0.92) November 08 2019' diff --git a/bin/Linux64/riscvOVPsim.exe b/bin/Linux64/riscvOVPsim.exe index 850ec9c..246919e 100755 Binary files a/bin/Linux64/riscvOVPsim.exe and b/bin/Linux64/riscvOVPsim.exe differ diff --git a/bin/Windows64/riscvOVPsim.exe b/bin/Windows64/riscvOVPsim.exe index 8bbade2..877d5a6 100755 Binary files a/bin/Windows64/riscvOVPsim.exe and b/bin/Windows64/riscvOVPsim.exe differ diff --git a/doc/OVP_Model_Specific_Information_riscv_RV64GCV.pdf b/doc/OVP_Model_Specific_Information_riscv_RV64GCV.pdf index 4a81f9f..d150d2d 100644 Binary files a/doc/OVP_Model_Specific_Information_riscv_RV64GCV.pdf and b/doc/OVP_Model_Specific_Information_riscv_RV64GCV.pdf differ diff --git a/doc/riscvOVPsim_User_Guide.pdf b/doc/riscvOVPsim_User_Guide.pdf index 84555b9..f7ba110 100644 Binary files a/doc/riscvOVPsim_User_Guide.pdf and b/doc/riscvOVPsim_User_Guide.pdf differ diff --git a/source/riscvAttrs.c b/source/riscvAttrs.c index 8f66626..7ea9d6a 100644 --- a/source/riscvAttrs.c +++ b/source/riscvAttrs.c @@ -66,6 +66,7 @@ const vmiIASAttr modelAttrs = { // CONSTRUCTOR/DESTRUCTOR ROUTINES //////////////////////////////////////////////////////////////////////// + .smpNameCB = riscvGetSMPName, .constructorCB = riscvConstructor, .postConstructorCB = riscvPostConstructor, .vmInitCB = riscvVMInit, @@ -79,6 +80,8 @@ const vmiIASAttr modelAttrs = { .endBlockCB = riscvEndBlock, .morphCB = riscvMorph, .fetchSnapCB = riscvFetchSnap, + .rdSnapCB = riscvRdSnap, + .wrSnapCB = riscvWrSnap, //////////////////////////////////////////////////////////////////////// // SIMULATION SUPPORT ROUTINES @@ -99,6 +102,8 @@ const vmiIASAttr modelAttrs = { .wrAlignExceptCB = riscvWrAlignExcept, .rdAbortExceptCB = riscvRdAbortExcept, .wrAbortExceptCB = riscvWrAbortExcept, + .rdDeviceExceptCB = riscvRdDeviceExcept, + .wrDeviceExceptCB = riscvWrDeviceExcept, .ifetchExceptCB = riscvIFetchExcept, .arithResultCB = riscvArithResult, diff --git a/source/riscvBlockState.h b/source/riscvBlockState.h index 142dc32..d372cfb 100644 --- a/source/riscvBlockState.h +++ b/source/riscvBlockState.h @@ -39,15 +39,18 @@ typedef enum riscvSEWMtE { } riscvSEWMt; // -// This indicates the known active vector length multiplier (VLMUL) +// This indicates 8x the known active vector length multiplier (VLMUL) // -typedef enum riscvVLMULMtE { - VLMULMT_UNKNOWN = 0, - VLMULMT_1 = 1, - VLMULMT_2 = 2, - VLMULMT_4 = 4, - VLMULMT_8 = 8, -} riscvVLMULMt; +typedef enum riscvVLMULx8MtE { + VLMULx8MT_UNKNOWN = 0, + VLMULx8MT_0125 = 1, + VLMULx8MT_025 = 2, + VLMULx8MT_05 = 4, + VLMULx8MT_1 = 8, + VLMULx8MT_2 = 16, + VLMULx8MT_4 = 32, + VLMULx8MT_8 = 64, +} riscvVLMULx8Mt; // // This indicates the known active vector length zero/non-zero state @@ -73,7 +76,7 @@ typedef enum riscvTZE { // and transaction mode // typedef enum riscvPMKE { - PMK_VECTOR = 0x00ff, + PMK_VECTOR = 0x03ff, PMK_TRANSACTION = 0x8000, } riscvPMK; @@ -87,10 +90,33 @@ typedef struct riscvBlockStateS { Bool FSDirty; // is status.FS known to be dirty? Bool VSDirty; // is status.VS known to be dirty? riscvSEWMt SEWMt; // known active vector SEW - riscvVLMULMt VLMULMt; // known active vector VLMUL + riscvVLMULx8Mt VLMULx8Mt; // known active vector VLMULx8 riscvVLClassMt VLClassMt; // known active vector VL zero/non-zero/max Uns32 VZeroTopMt[2]; // known vector registers with zero top Bool VStartZeroMt; // vstart known to be zero? } riscvBlockState; +// +// Convert vsew value to riscvSEWMt type +// +inline static riscvSEWMt vsewToSEW(Uns32 vsew) { + return 8<inSaveRestore && + (oldValue&ISA_C) && + !(newValue&ISA_C) && + ((pc=getPC(riscv))&3) + ) { vmiMessage("W", CPU_PREFIX "_IN4BA", SRCREF_FMT "Write ignored (attempt to clear C bit when instruction " "not 4-byte aligned)", @@ -594,7 +598,7 @@ static void statusW(riscvP riscv, Uns64 newValue, Uns64 mask) { // changes in MSTATUS.MPRV affect current data domain riscvVMRefreshMPRVDomain(riscv); - // handle and exceptions that have been enabled + // handle any exceptions that have been enabled if(newIE & ~oldIE) { riscvTestInterrupt(riscv); } @@ -750,7 +754,7 @@ static RISCV_CSR_READFN(uepcR) { //////////////////////////////////////////////////////////////////////////////// -// INTERRUPT ENABLE/PENDING/DELEGATION REGISTERS +// INTERRUPT CONTROL REGISTERS //////////////////////////////////////////////////////////////////////////////// // @@ -760,6 +764,13 @@ inline static RISCV_CSR_PRESENTFN(clicP) { return CLICPresent(riscv); } +// +// Are CLIC scratch swap registers present? +// +inline static RISCV_CSR_PRESENTFN(clicSWP) { + return CLICPresent(riscv) && riscv->configInfo.CLICMCSW; +} + // // Return mask of interrupts visible in Supervisor mode // @@ -936,7 +947,7 @@ static Uns32 ieW(riscvP riscv, Uns32 newValue, Uns32 rMask, Bool useCLIC) { WR_CSR(riscv, mie, newValue); // handle any interrupts that are now pending and enabled - if(oldValue!=newValue) { + if(!useCLIC && (oldValue!=newValue)) { riscvTestInterrupt(riscv); } @@ -1032,6 +1043,471 @@ static RISCV_CSR_WRITEFN(sidelegW) { return newValue; } +// +// Read mcause +// +static RISCV_CSR_READFN(mcauseR) { + + if(!CLICPresent(riscv)) { + // no further action + } else if(useCLICM(riscv)) { + // mirror mcause.pp and mcause.pie from masters in mstatus + WR_CSR_FIELD(riscv, mcause, pp, RD_CSR_FIELD(riscv, mstatus, MPP)); + WR_CSR_FIELD(riscv, mcause, pie, RD_CSR_FIELD(riscv, mstatus, MPIE)); + } else { + // clear mcause.pp and mcause.pie + WR_CSR_FIELD(riscv, mcause, pp, 0); + WR_CSR_FIELD(riscv, mcause, pie, 0); + } + + // return value + return RD_CSR(riscv, mcause); +} + +// +// Write mcause +// +static RISCV_CSR_WRITEFN(mcauseW) { + + // update the CSR + WR_CSR(riscv, mcause, newValue & RD_CSR_MASK(riscv, mcause)); + + if(!CLICPresent(riscv)) { + // no further action + } else if(useCLICM(riscv)) { + // mirror mcause.pp and mcause.pie to masters in mstatus + WR_CSR_FIELD(riscv, mstatus, MPP, RD_CSR_FIELD(riscv, mcause, pp)); + WR_CSR_FIELD(riscv, mstatus, MPIE, RD_CSR_FIELD(riscv, mcause, pie)); + } else if(!riscv->inSaveRestore) { + // clear fields that appear hard-wired to zero in basic mode + WR_CSR_FIELD(riscv, mcause, inhv, 0); + WR_CSR_FIELD(riscv, mcause, pp, 0); + WR_CSR_FIELD(riscv, mcause, pie, 0); + WR_CSR_FIELD(riscv, mcause, pil, 0); + } + + // return written value + return RD_CSR(riscv, mcause); +} + +// +// Read scause +// +static RISCV_CSR_READFN(scauseR) { + + if(!CLICPresent(riscv)) { + // no further action + } else if(useCLICS(riscv)) { + // mirror scause.pp and scause.pie from masters in mstatus + WR_CSR_FIELD(riscv, scause, pp, RD_CSR_FIELD(riscv, mstatus, SPP)); + WR_CSR_FIELD(riscv, scause, pie, RD_CSR_FIELD(riscv, mstatus, SPIE)); + } else { + // clear scause.pp and scause.pie + WR_CSR_FIELD(riscv, scause, pp, 0); + WR_CSR_FIELD(riscv, scause, pie, 0); + } + + // return value + return RD_CSR(riscv, scause); +} + +// +// Write scause +// +static RISCV_CSR_WRITEFN(scauseW) { + + // update the CSR + WR_CSR(riscv, scause, newValue & RD_CSR_MASK(riscv, scause)); + + if(!CLICPresent(riscv)) { + // no further action + } else if(useCLICS(riscv)) { + // mirror scause.pp and scause.pie to masters in mstatus + WR_CSR_FIELD(riscv, mstatus, SPP, RD_CSR_FIELD(riscv, scause, pp)); + WR_CSR_FIELD(riscv, mstatus, SPIE, RD_CSR_FIELD(riscv, scause, pie)); + } else if(!riscv->inSaveRestore) { + // clear fields that appear hard-wired to zero in basic mode + WR_CSR_FIELD(riscv, scause, inhv, 0); + WR_CSR_FIELD(riscv, scause, pp, 0); + WR_CSR_FIELD(riscv, scause, pie, 0); + WR_CSR_FIELD(riscv, scause, pil, 0); + } + + // return written value + return RD_CSR(riscv, scause); +} + +// +// Read ucause +// +static RISCV_CSR_READFN(ucauseR) { + + if(!CLICPresent(riscv)) { + // no further action + } else if(useCLICU(riscv)) { + // mirror ucause.pie from master in mstatus + WR_CSR_FIELD(riscv, ucause, pie, RD_CSR_FIELD(riscv, mstatus, UPIE)); + } else { + // clear ucause.pie + WR_CSR_FIELD(riscv, ucause, pie, 0); + } + + // return value + return RD_CSR(riscv, ucause); +} + +// +// Write ucause +// +static RISCV_CSR_WRITEFN(ucauseW) { + + // update the CSR + WR_CSR(riscv, ucause, newValue & RD_CSR_MASK(riscv, ucause)); + + if(!CLICPresent(riscv)) { + // no further action + } else if(useCLICU(riscv)) { + // mirror ucause.pie to master in mstatus + WR_CSR_FIELD(riscv, mstatus, UPIE, RD_CSR_FIELD(riscv, ucause, pie)); + } else if(!riscv->inSaveRestore) { + // clear fields that appear hard-wired to zero in basic mode + WR_CSR_FIELD(riscv, ucause, inhv, 0); + WR_CSR_FIELD(riscv, ucause, pie, 0); + WR_CSR_FIELD(riscv, ucause, pil, 0); + } + + // return written value + return RD_CSR(riscv, ucause); +} + +// +// Perform actions when reading xnxti CSR +// +#define READ_NXTI(_RESULT, _P, _x, _MODE) \ + \ + /* initially assume no horizontal interrupt */ \ + _RESULT = 0; \ + \ + if( \ + (_P->clic.sel.priv==_MODE) && \ + (_P->clic.sel.level > RD_CSR_FIELD(riscv, _x##cause, pil)) && \ + (!_P->clic.sel.shv) \ + ) { \ + /* get horizontal interrupt address */ \ + Uns32 bytes = RISCV_XLEN_BYTES(_P); \ + _RESULT = RD_CSR(_P, _x##tvt) + (bytes*_P->clic.sel.id); \ + } + +// +// Perform actions when writing xnxti CSR +// +#define WRITE_NXTI(_RESULT, _NEWVALUE, _P, _x, _MODE) \ + \ + /* update status register regardless of interrupt readiness */ \ + _x##statusW(0, _P, _NEWVALUE); \ + \ + /* read xntxi CSR */ \ + READ_NXTI(_RESULT, _P, _x, _MODE); \ + \ + /* update state if horizontal interrupt requires service */ \ + if(_RESULT) { \ + WR_CSR_FIELD(_P, mintstatus, _x##il, _P->clic.sel.level); \ + WR_CSR_FIELD(_P, _x##cause, ExceptionCode, _P->clic.sel.id); \ + WR_CSR_FIELD(_P, _x##cause, Interrupt, 1); \ + riscvAcknowledgeCLICInt(_P, _P->clic.sel.id); \ + } + +// +// Read mnxti +// +static RISCV_CSR_READFN(mnxtiR) { + + Uns64 result; + + READ_NXTI(result, riscv, m, RISCV_MODE_MACHINE); + + return result; +} + +// +// Write mnxti +// +static RISCV_CSR_WRITEFN(mnxtiW) { + + Uns64 result; + + WRITE_NXTI(result, newValue, riscv, m, RISCV_MODE_MACHINE); + + return result; +} + +// +// Read snxti +// +static RISCV_CSR_READFN(snxtiR) { + + Uns64 result; + + READ_NXTI(result, riscv, s, RISCV_MODE_SUPERVISOR); + + return result; +} + +// +// Write snxti +// +static RISCV_CSR_WRITEFN(snxtiW) { + + Uns64 result; + + WRITE_NXTI(result, newValue, riscv, s, RISCV_MODE_SUPERVISOR); + + return result; +} + +// +// Read unxti +// +static RISCV_CSR_READFN(unxtiR) { + + Uns64 result; + + READ_NXTI(result, riscv, u, RISCV_MODE_USER); + + return result; +} + +// +// Write unxti +// +static RISCV_CSR_WRITEFN(unxtiW) { + + Uns64 result; + + WRITE_NXTI(result, newValue, riscv, u, RISCV_MODE_USER); + + return result; +} + +// +// Read sintstatus +// +static RISCV_CSR_READFN(sintstatusR) { + return RD_CSR(riscv, mintstatus) & RM32_sintstatus; +} + +// +// Read uintstatus +// +static RISCV_CSR_READFN(uintstatusR) { + return RD_CSR(riscv, mintstatus) & RM32_uintstatus; +} + +// +// Perform actions when reading scratchcsw CSR +// +#define READ_SCRATCHCSW(_P, _x, _MODE) { \ + \ + Uns64 result = 0; \ + \ + /* refresh cause.xpp */ \ + _x##causeR(0, _P); \ + \ + /* return scratch register if cause.xpp matches required mode */ \ + if(RD_CSR_FIELD(_P, _x##cause, pp)==_MODE) { \ + result = RD_CSR(riscv, _x##scratch); \ + } \ + \ + return result; \ +} + +// +// Perform actions when writing scratchcsw CSR +// +#define WRITE_SCRATCHCSW(_NEWVALUE, _P, _x, _MODE) { \ + \ + Uns64 result = _NEWVALUE; \ + \ + /* refresh cause.xpp */ \ + _x##causeR(0, _P); \ + \ + /* update scratch register if cause.xpp matches required mode */ \ + if(RD_CSR_FIELD(_P, _x##cause, pp)==_MODE) { \ + result = RD_CSR(riscv, _x##scratch); \ + WR_CSR(riscv, _x##scratch, _NEWVALUE); \ + } \ + \ + return result; \ +} + +// +// Read mscratchcsw +// +static RISCV_CSR_READFN(mscratchcswR) { + READ_SCRATCHCSW(riscv, m, RISCV_MODE_MACHINE); +} + +// +// Write mscratchcsw +// +static RISCV_CSR_WRITEFN(mscratchcswW) { + WRITE_SCRATCHCSW(newValue, riscv, m, RISCV_MODE_MACHINE); +} + +// +// Read sscratchcsw +// +static RISCV_CSR_READFN(sscratchcswR) { + READ_SCRATCHCSW(riscv, s, RISCV_MODE_SUPERVISOR); +} + +// +// Write sscratchcsw +// +static RISCV_CSR_WRITEFN(sscratchcswW) { + WRITE_SCRATCHCSW(newValue, riscv, s, RISCV_MODE_SUPERVISOR); +} + +// +// Perform actions when reading scratchcswl CSR +// +#define READ_SCRATCHCSWL(_P, _x) { \ + \ + Uns64 result = 0; \ + \ + /* refresh cause.xpp */ \ + _x##causeR(0, _P); \ + \ + /* return scratch register if interrupter and interruptee not */ \ + /* both application tasks or interrupt handlers */ \ + if( \ + (RD_CSR_FIELD(_P, _x##cause, pil)==0) != \ + (RD_CSR_FIELD(_P, mintstatus, _x##il)==0) \ + ) { \ + result = RD_CSR(riscv, _x##scratch); \ + } \ + \ + return result; \ +} + +// +// Perform actions when writing scratchcswl CSR +// +#define WRITE_SCRATCHCSWL(_NEWVALUE, _P, _x) { \ + \ + Uns64 result = _NEWVALUE; \ + \ + /* refresh cause.xpp */ \ + _x##causeR(0, _P); \ + \ + /* update scratch register if interrupter and interruptee not */ \ + /* both application tasks or interrupt handlers */ \ + if( \ + (RD_CSR_FIELD(_P, _x##cause, pil)==0) != \ + (RD_CSR_FIELD(_P, mintstatus, _x##il)==0) \ + ) { \ + result = RD_CSR(riscv, _x##scratch); \ + WR_CSR(riscv, _x##scratch, _NEWVALUE); \ + } \ + \ + return result; \ +} + +// +// Read mscratchcswl +// +static RISCV_CSR_READFN(mscratchcswlR) { + READ_SCRATCHCSWL(riscv, m); +} + +// +// Write mscratchcswl +// +static RISCV_CSR_WRITEFN(mscratchcswlW) { + WRITE_SCRATCHCSWL(newValue, riscv, m); +} + +// +// Read sscratchcswl +// +static RISCV_CSR_READFN(sscratchcswlR) { + READ_SCRATCHCSWL(riscv, s); +} + +// +// Write sscratchcswl +// +static RISCV_CSR_WRITEFN(sscratchcswlW) { + WRITE_SCRATCHCSWL(newValue, riscv, s); +} + +// +// Read uscratchcswl +// +static RISCV_CSR_READFN(uscratchcswlR) { + READ_SCRATCHCSWL(riscv, u); +} + +// +// Write uscratchcswl +// +static RISCV_CSR_WRITEFN(uscratchcswlW) { + WRITE_SCRATCHCSWL(newValue, riscv, u); +} + +// +// Perform actions when writing intthresh CSR +// +#define WRITE_INTTHRESH(_NEWVALUE, _P, _x) { \ + \ + /* update threshold level */ \ + Uns32 oldLevel = RD_CSR_FIELD(_P, _x##intthresh, th); \ + WR_CSR_FIELD(_P, _x##intthresh, th, newValue); \ + Uns32 newLevel = RD_CSR_FIELD(_P, _x##intthresh, th); \ + \ + /* check for pending interrupts if threshold level drops */ \ + if(newLevelconfigInfo.VLEN * LMUL/SEW; + return riscvGetMaxVL(riscv, vtype); } // @@ -1785,11 +2268,10 @@ void riscvRefreshVectorPMKey(riscvP riscv) { // // Update vtype CSR // -void riscvSetVType(riscvP riscv, Bool vill, Uns32 vsew, Uns32 vlmul) { +void riscvSetVType(riscvP riscv, Bool vill, riscvVType vtype) { - WR_CSR_FIELD(riscv, vtype, vsew, vsew); - WR_CSR_FIELD(riscv, vtype, vlmul, vlmul); - WR_CSR_FIELD(riscv, vtype, vill, vill); + WR_CSR(riscv, vtype, vtype.u32); + WR_CSR_FIELD(riscv, vtype, vill, vill); } // @@ -1816,7 +2298,8 @@ static void resetVLVType(riscvP riscv) { if(riscv->configInfo.arch & ISA_V) { // reset vtype CSR - riscvSetVType(riscv, !riscvValidSEW(riscv, 0), 0, 0); + riscvVType vtype = {0}; + riscvSetVType(riscv, !riscvValidVType(riscv, vtype), vtype); // reset VL CSR riscvSetVL(riscv, 0); @@ -1886,7 +2369,7 @@ static RISCV_CSR_WRITEFN(dcsrW) { // Unimplemented (ignore reads and writes) // #define CSR_ATTR_NIP( \ - _ID, _NUM, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC \ + _ID, _NUM, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC \ ) [CSR_ID(_ID)] = { \ name : #_ID, \ desc : _DESC" (not implemented)", \ @@ -1897,6 +2380,7 @@ static RISCV_CSR_WRITEFN(dcsrW) { wEndBlock : _ENDB, \ noTraceChange : _NOTR, \ TVMT : _TVMT, \ + writeRd : _WRD, \ } @@ -1908,8 +2392,9 @@ static RISCV_CSR_WRITEFN(dcsrW) { // Implemented using vmiReg and optional callbacks, no mask // #define CSR_ATTR_T__( \ - _ID, _NUM, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, \ - _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ + _ID, _NUM, _ARCH, _ACCESS, _VERSION, \ + _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, \ + _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ ) [CSR_ID(_ID)] = { \ name : #_ID, \ desc : _DESC, \ @@ -1918,8 +2403,10 @@ static RISCV_CSR_WRITEFN(dcsrW) { access : _ACCESS, \ version : RVPV_##_VERSION, \ wEndBlock : _ENDB, \ + noSaveRestore : _NOSR, \ noTraceChange : _NOTR, \ TVMT : _TVMT, \ + writeRd : _WRD, \ presentCB : _PRESENT, \ readCB : _RCB, \ readWriteCB : _RWCB, \ @@ -1933,8 +2420,9 @@ static RISCV_CSR_WRITEFN(dcsrW) { // Implemented using vmiReg and optional callbacks, constant write mask // #define CSR_ATTR_TC_( \ - _ID, _NUM, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, \ - _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ + _ID, _NUM, _ARCH, _ACCESS, _VERSION, \ + _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, \ + _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ ) [CSR_ID(_ID)] = { \ name : #_ID, \ desc : _DESC, \ @@ -1943,8 +2431,10 @@ static RISCV_CSR_WRITEFN(dcsrW) { access : _ACCESS, \ version : RVPV_##_VERSION, \ wEndBlock : _ENDB, \ + noSaveRestore : _NOSR, \ noTraceChange : _NOTR, \ TVMT : _TVMT, \ + writeRd : _WRD, \ presentCB : _PRESENT, \ readCB : _RCB, \ readWriteCB : _RWCB, \ @@ -1960,8 +2450,9 @@ static RISCV_CSR_WRITEFN(dcsrW) { // Implemented using vmiReg and optional callbacks, variable write mask // #define CSR_ATTR_TV_( \ - _ID, _NUM, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, \ - _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ + _ID, _NUM, _ARCH, _ACCESS, _VERSION, \ + _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, \ + _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ ) [CSR_ID(_ID)] = { \ name : #_ID, \ desc : _DESC, \ @@ -1970,8 +2461,10 @@ static RISCV_CSR_WRITEFN(dcsrW) { access : _ACCESS, \ version : RVPV_##_VERSION, \ wEndBlock : _ENDB, \ + noSaveRestore : _NOSR, \ noTraceChange : _NOTR, \ TVMT : _TVMT, \ + writeRd : _WRD, \ presentCB : _PRESENT, \ readCB : _RCB, \ readWriteCB : _RWCB, \ @@ -1987,8 +2480,9 @@ static RISCV_CSR_WRITEFN(dcsrW) { // Implemented using callbacks only // #define CSR_ATTR_P__( \ - _ID, _NUM, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, \ - _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ + _ID, _NUM, _ARCH, _ACCESS, _VERSION, \ + _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, \ + _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ ) [CSR_ID(_ID)] = { \ name : #_ID, \ desc : _DESC, \ @@ -1997,8 +2491,11 @@ static RISCV_CSR_WRITEFN(dcsrW) { access : _ACCESS, \ version : RVPV_##_VERSION, \ wEndBlock : _ENDB, \ + noSaveRestore : _NOSR, \ noTraceChange : _NOTR, \ TVMT : _TVMT, \ + writeRd : _WRD, \ + presentCB : _PRESENT, \ readCB : _RCB, \ readWriteCB : _RWCB, \ writeCB : _WCB, \ @@ -2009,11 +2506,13 @@ static RISCV_CSR_WRITEFN(dcsrW) { // Implemented using callbacks only, append number // #define CSR_ATTR_P__NUM( \ - _ID, _NUM, _I, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, \ - _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ + _ID, _NUM, _I, _ARCH, _ACCESS, _VERSION, \ + _ENDB,_NOTR,_TVMT,_WRD,_NOSR, \ + _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ ) \ CSR_ATTR_P__( \ - _ID##_I, _NUM+_I, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, \ + _ID##_I, _NUM+_I, _ARCH, _ACCESS, _VERSION, \ + _ENDB,_NOTR,_TVMT,_WRD,_NOSR, \ _DESC#_I, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ ) @@ -2021,62 +2520,62 @@ static RISCV_CSR_WRITEFN(dcsrW) { // Implemented using callbacks only, numbers 0..15 // #define CSR_ATTR_P__0_15( \ - _ID, _NUM, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, \ - _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ + _ID, _NUM, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, \ + _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ ) \ - CSR_ATTR_P__NUM(_ID, _NUM, 0, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 1, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 2, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 3, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 4, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 5, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 6, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 7, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 8, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 9, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 10, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 11, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 12, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 13, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 14, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 15, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB) + CSR_ATTR_P__NUM(_ID, _NUM, 0, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 1, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 2, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 3, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 4, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 5, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 6, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 7, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 8, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 9, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 10, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 11, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 12, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 13, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 14, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 15, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB) // // Implemented using callbacks only, numbers 0..9 // #define CSR_ATTR_P__0_9( \ - _ID, _NUM, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, \ - _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ + _ID, _NUM, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, \ + _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ ) \ - CSR_ATTR_P__NUM(_ID, _NUM, 0, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 1, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 2, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 3, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 4, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 5, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 6, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 7, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 8, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 9, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB) + CSR_ATTR_P__NUM(_ID, _NUM, 0, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 1, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 2, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 3, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 4, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 5, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 6, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 7, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 8, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 9, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB) // // Implemented using callbacks only, numbers 3..31 // #define CSR_ATTR_P__3_31( \ - _ID, _NUM, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, \ - _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ + _ID, _NUM, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, \ + _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB \ ) \ - CSR_ATTR_P__NUM(_ID, _NUM, 3, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 4, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 5, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 6, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 7, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 8, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM, 9, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__0_9(_ID##1, _NUM+10, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC"1", _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__0_9(_ID##2, _NUM+20, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC"2", _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM,30, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ - CSR_ATTR_P__NUM(_ID, _NUM,31, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB) + CSR_ATTR_P__NUM(_ID, _NUM, 3, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 4, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 5, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 6, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 7, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 8, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM, 9, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__0_9(_ID##1, _NUM+10, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC"1", _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__0_9(_ID##2, _NUM+20, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC"2", _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM,30, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB), \ + CSR_ATTR_P__NUM(_ID, _NUM,31, _ARCH, _ACCESS, _VERSION, _ENDB,_NOTR,_TVMT,_WRD,_NOSR, _DESC, _PRESENT, _WSTATE, _RCB, _RWCB, _WCB) // @@ -2084,98 +2583,113 @@ static RISCV_CSR_WRITEFN(dcsrW) { // static const riscvCSRAttrs csrs[CSR_ID(LAST)] = { - // name num arch access version attrs description present wState rCB rwCB wCB - CSR_ATTR_P__ (ustatus, 0x000, ISA_N, 0, 1_10, 0,0,0, "User Status", 0, 0, ustatusR, 0, ustatusW ), - CSR_ATTR_P__ (fflags, 0x001, ISA_DF, 0, 1_10, 0,0,0, "Floating-Point Flags", 0, riscvWFS, fflagsR, 0, fflagsW ), - CSR_ATTR_P__ (frm, 0x002, ISA_DF, 0, 1_10, 1,0,0, "Floating-Point Rounding Mode", 0, riscvWFS, frmR, 0, frmW ), - CSR_ATTR_P__ (fcsr, 0x003, ISA_DFV, ISA_FS, 1_10, 1,0,0, "Floating-Point Control and Status", 0, riscvWFS, fcsrR, 0, fcsrW ), - CSR_ATTR_P__ (uie, 0x004, ISA_N, 0, 1_10, 1,0,0, "User Interrupt Enable", 0, 0, uieR, 0, uieW ), - CSR_ATTR_T__ (utvec, 0x005, ISA_N, 0, 1_10, 0,0,0, "User Trap-Vector Base-Address", 0, 0, 0, 0, utvecW ), - CSR_ATTR_TV_ (utvt, 0x007, ISA_N, 0, 1_10, 0,0,0, "User CLIC Trap-Vector Base-Address", clicP, 0, 0, 0, 0 ), - CSR_ATTR_TV_ (vstart, 0x008, ISA_V, 0, 1_10, 0,0,0, "Vector Start Index", 0, riscvWVStart,0, 0, 0 ), - CSR_ATTR_TC_ (vxsat, 0x009, ISA_V, ISA_FSandV, 1_10, 0,0,0, "Fixed-Point Saturate Flag", 0, riscvWFSVS, vxsatR, 0, vxsatW ), - CSR_ATTR_TC_ (vxrm, 0x00A, ISA_V, ISA_FSandV, 1_10, 0,0,0, "Fixed-Point Rounding Mode", 0, riscvWFSVS, 0, 0, vxrmW ), - CSR_ATTR_T__ (vcsr, 0x00F, ISA_V, 0, 1_10, 1,0,0, "Vector Control and Status", vcsrP, riscvWVCSR, vcsrR, 0, vcsrW ), - CSR_ATTR_T__ (uscratch, 0x040, ISA_N, 0, 1_10, 0,0,0, "User Scratch", 0, 0, 0, 0, 0 ), - CSR_ATTR_TV_ (uepc, 0x041, ISA_N, 0, 1_10, 0,0,0, "User Exception Program Counter", 0, 0, uepcR, 0, 0 ), - CSR_ATTR_TV_ (ucause, 0x042, ISA_N, 0, 1_10, 0,0,0, "User Cause", 0, 0, 0, 0, 0 ), - CSR_ATTR_T__ (utval, 0x043, ISA_N, 0, 1_10, 0,0,0, "User Trap Value", 0, 0, 0, 0, 0 ), - CSR_ATTR_P__ (uip, 0x044, ISA_N, 0, 1_10, 0,0,0, "User Interrupt Pending", 0, 0, uipR, uipRW, uipW ), - CSR_ATTR_P__ (cycle, 0xC00, 0, 0, 1_10, 0,1,0, "Cycle Counter", 0, 0, mcycleR, 0, 0 ), - CSR_ATTR_P__ (time, 0xC01, 0, 0, 1_10, 0,1,0, "Timer", 0, 0, mtimeR, 0, 0 ), - CSR_ATTR_P__ (instret, 0xC02, 0, 0, 1_10, 0,1,0, "Instructions Retired", 0, 0, minstretR, 0, 0 ), - CSR_ATTR_P__3_31 (hpmcounter, 0xC00, 0, 0, 1_10, 0,0,0, "Performance Monitor Counter ", 0, 0, mhpmR, 0, mhpmW ), - CSR_ATTR_T__ (vl, 0xC20, ISA_V, 0, 1_10, 0,0,0, "Vector Length", 0, 0, 0, 0, 0 ), - CSR_ATTR_T__ (vtype, 0xC21, ISA_V, 0, 1_10, 0,0,0, "Vector Type", 0, 0, 0, 0, 0 ), - CSR_ATTR_T__ (vlenb, 0xC22, ISA_V, 0, 1_10, 0,0,0, "Vector Length in Bytes", vlenbP, 0, 0, 0, 0 ), - CSR_ATTR_P__ (cycleh, 0xC80, ISA_XLEN_32, 0, 1_10, 0,1,0, "Cycle Counter High", 0, 0, mcyclehR, 0, 0 ), - CSR_ATTR_P__ (timeh, 0xC81, ISA_XLEN_32, 0, 1_10, 0,1,0, "Timer High", 0, 0, mtimehR, 0, 0 ), - CSR_ATTR_P__ (instreth, 0xC82, ISA_XLEN_32, 0, 1_10, 0,1,0, "Instructions Retired High", 0, 0, minstrethR, 0, 0 ), - CSR_ATTR_P__3_31 (hpmcounterh, 0xC80, ISA_XLEN_32, 0, 1_10, 0,0,0, "Performance Monitor High ", 0, 0, mhpmR, 0, mhpmW ), - - // name num arch access version attrs description present wState rCB rwCB wCB - CSR_ATTR_P__ (sstatus, 0x100, ISA_S, 0, 1_10, 0,0,0, "Supervisor Status", 0, riscvRstFS, sstatusR, 0, sstatusW ), - CSR_ATTR_TV_ (sedeleg, 0x102, ISA_SandN, 0, 1_10, 0,0,0, "Supervisor Exception Delegation", 0, 0, 0, 0, 0 ), - CSR_ATTR_T__ (sideleg, 0x103, ISA_SandN, 0, 1_10, 1,0,0, "Supervisor Interrupt Delegation", 0, 0, 0, 0, sidelegW ), - CSR_ATTR_P__ (sie, 0x104, ISA_S, 0, 1_10, 1,0,0, "Supervisor Interrupt Enable", 0, 0, sieR, 0, sieW ), - CSR_ATTR_T__ (stvec, 0x105, ISA_S, 0, 1_10, 0,0,0, "Supervisor Trap-Vector Base-Address", 0, 0, 0, 0, stvecW ), - CSR_ATTR_TV_ (scounteren, 0x106, ISA_S, 0, 1_10, 0,0,0, "Supervisor Counter Enable", 0, 0, 0, 0, 0 ), - CSR_ATTR_TV_ (stvt, 0x107, ISA_S, 0, 1_10, 0,0,0, "Supervisor CLIC Trap-Vector Base-Address", clicP, 0, 0, 0, 0 ), - CSR_ATTR_T__ (sscratch, 0x140, ISA_S, 0, 1_10, 0,0,0, "Supervisor Scratch", 0, 0, 0, 0, 0 ), - CSR_ATTR_TV_ (sepc, 0x141, ISA_S, 0, 1_10, 0,0,0, "Supervisor Exception Program Counter", 0, 0, sepcR, 0, 0 ), - CSR_ATTR_TV_ (scause, 0x142, ISA_S, 0, 1_10, 0,0,0, "Supervisor Cause", 0, 0, 0, 0, 0 ), - CSR_ATTR_T__ (stval, 0x143, ISA_S, 0, 1_10, 0,0,0, "Supervisor Trap Value", 0, 0, 0, 0, 0 ), - CSR_ATTR_P__ (sip, 0x144, ISA_S, 0, 1_10, 0,0,0, "Supervisor Interrupt Pending", 0, 0, sipR, sipRW, sipW ), - CSR_ATTR_T__ (satp, 0x180, ISA_S, 0, 1_10, 0,0,1, "Supervisor Address Translation and Protection", 0, 0, 0, 0, satpW ), - - // name num arch access version attrs description present wState rCB rwCB wCB - CSR_ATTR_T__ (mvendorid, 0xF11, 0, 0, 1_10, 0,0,0, "Vendor ID", 0, 0, 0, 0, 0 ), - CSR_ATTR_T__ (marchid, 0xF12, 0, 0, 1_10, 0,0,0, "Architecture ID", 0, 0, 0, 0, 0 ), - CSR_ATTR_T__ (mimpid, 0xF13, 0, 0, 1_10, 0,0,0, "Implementation ID", 0, 0, 0, 0, 0 ), - CSR_ATTR_T__ (mhartid, 0xF14, 0, 0, 1_10, 0,0,0, "Hardware Thread ID", 0, 0, 0, 0, 0 ), - CSR_ATTR_TV_ (mstatus, 0x300, 0, 0, 1_10, 0,0,0, "Machine Status", 0, riscvRstFS, mstatusR, 0, mstatusW ), - CSR_ATTR_T__ (misa, 0x301, 0, 0, 1_10, 1,0,0, "ISA and Extensions", 0, 0, 0, 0, misaW ), - CSR_ATTR_TV_ (medeleg, 0x302, ISA_SorN, 0, 1_10, 0,0,0, "Machine Exception Delegation", 0, 0, 0, 0, 0 ), - CSR_ATTR_T__ (mideleg, 0x303, ISA_SorN, 0, 1_10, 1,0,0, "Machine Interrupt Delegation", 0, 0, 0, 0, midelegW ), - CSR_ATTR_T__ (mie, 0x304, 0, 0, 1_10, 1,0,0, "Machine Interrupt Enable", 0, 0, mieR, 0, mieW ), - CSR_ATTR_T__ (mtvec, 0x305, 0, 0, 1_10, 0,0,0, "Machine Trap-Vector Base-Address", 0, 0, 0, 0, mtvecW ), - CSR_ATTR_TV_ (mcounteren, 0x306, ISA_SorU, 0, 1_10, 0,0,0, "Machine Counter Enable", 0, 0, 0, 0, 0 ), - CSR_ATTR_TV_ (mtvt, 0x307, 0, 0, 1_10, 0,0,0, "Machine CLIC Trap-Vector Base-Address", clicP, 0, 0, 0, 0 ), - CSR_ATTR_TV_ (mstatush, 0x310, ISA_XLEN_32, 0, 1_12, 0,0,0, "Machine Status High", 0, 0, 0, 0, mstatushW ), - CSR_ATTR_TV_ (mcountinhibit,0x320, 0, 0, 1_11, 0,0,0, "Machine Counter Inhibit", 0, 0, 0, 0, mcountinhibitW), - CSR_ATTR_T__ (mscratch, 0x340, 0, 0, 1_10, 0,0,0, "Machine Scratch", 0, 0, 0, 0, 0 ), - CSR_ATTR_TV_ (mepc, 0x341, 0, 0, 1_10, 0,0,0, "Machine Exception Program Counter", 0, 0, mepcR, 0, 0 ), - CSR_ATTR_TV_ (mcause, 0x342, 0, 0, 1_10, 0,0,0, "Machine Cause", 0, 0, 0, 0, 0 ), - CSR_ATTR_T__ (mtval, 0x343, 0, 0, 1_10, 0,0,0, "Machine Trap Value", 0, 0, 0, 0, 0 ), - CSR_ATTR_T__ (mip, 0x344, 0, 0, 1_10, 0,0,0, "Machine Interrupt Pending", 0, 0, mipR, mipRW, mipW ), - - // name num arch access version attrs description present wState rCB rwCB wCB - CSR_ATTR_P__ (pmpcfg0, 0x3A0, 0, 0, 1_10, 0,0,0, "Physical Memory Protection Configuration 0", 0, 0, pmpcfgR, 0, pmpcfgW ), - CSR_ATTR_P__ (pmpcfg1, 0x3A1, ISA_XLEN_32, 0, 1_10, 0,0,0, "Physical Memory Protection Configuration 1", 0, 0, pmpcfgR, 0, pmpcfgW ), - CSR_ATTR_P__ (pmpcfg2, 0x3A2, 0, 0, 1_10, 0,0,0, "Physical Memory Protection Configuration 2", 0, 0, pmpcfgR, 0, pmpcfgW ), - CSR_ATTR_P__ (pmpcfg3, 0x3A3, ISA_XLEN_32, 0, 1_10, 0,0,0, "Physical Memory Protection Configuration 3", 0, 0, pmpcfgR, 0, pmpcfgW ), - CSR_ATTR_P__0_15 (pmpaddr, 0x3B0, 0, 0, 1_10, 0,0,0, "Physical Memory Protection Address ", 0, 0, pmpaddrR, 0, pmpaddrW ), - - // name num arch access version attrs description present wState rCB rwCB wCB - CSR_ATTR_P__ (mcycle, 0xB00, 0, 0, 1_10, 0,1,0, "Machine Cycle Counter", 0, 0, mcycleR, 0, mcycleW ), - CSR_ATTR_P__ (minstret, 0xB02, 0, 0, 1_10, 0,1,0, "Machine Instructions Retired", 0, 0, minstretR, 0, minstretW ), - CSR_ATTR_P__3_31 (mhpmcounter, 0xB00, 0, 0, 1_10, 0,0,0, "Machine Performance Monitor Counter ", 0, 0, mhpmR, 0, mhpmW ), - CSR_ATTR_P__ (mcycleh, 0xB80, ISA_XLEN_32, 0, 1_10, 0,1,0, "Machine Cycle Counter High", 0, 0, mcyclehR, 0, mcyclehW ), - CSR_ATTR_P__ (minstreth, 0xB82, ISA_XLEN_32, 0, 1_10, 0,1,0, "Machine Instructions Retired High", 0, 0, minstrethR, 0, minstrethW ), - CSR_ATTR_P__3_31 (mhpmcounterh, 0xB80, ISA_XLEN_32, 0, 1_10, 0,0,0, "Machine Performance Monitor Counter High ", 0, 0, mhpmR, 0, mhpmW ), - CSR_ATTR_P__3_31 (mhpmevent, 0x320, 0, 0, 1_10, 0,0,0, "Machine Performance Monitor Event Select ", 0, 0, mhpmR, 0, mhpmW ), - - // name num arch access version attrs description present wState rCB rwCB wCB - CSR_ATTR_NIP (tselect, 0x7A0, 0, 0, 1_10, 0,0,0, "Debug/Trace Trigger Register Select" ), - CSR_ATTR_NIP (tdata1, 0x7A1, 0, 0, 1_10, 0,0,0, "Debug/Trace Trigger Data 1" ), - CSR_ATTR_NIP (tdata2, 0x7A2, 0, 0, 1_10, 0,0,0, "Debug/Trace Trigger Data 2" ), - CSR_ATTR_NIP (tdata3, 0x7A3, 0, 0, 1_10, 0,0,0, "Debug/Trace Trigger Data 3" ), - - // name num arch access version attrs description present wState rCB rwCB wCB - CSR_ATTR_TV_ (dcsr, 0x7B0, 0, 0, 1_10, 0,0,0, "Debug Control and Status", debugP, 0, 0, 0, dcsrW ), - CSR_ATTR_T__ (dpc, 0x7B1, 0, 0, 1_10, 0,0,0, "Debug PC", debugP, 0, 0, 0, 0 ), - CSR_ATTR_T__ (dscratch0, 0x7B2, 0, 0, 1_10, 0,0,0, "Debug Scratch 0", debugP, 0, 0, 0, 0 ), - CSR_ATTR_T__ (dscratch1, 0x7B3, 0, 0, 1_10, 0,0,0, "Debug Scratch 1", debugP, 0, 0, 0, 0 ), + // name num arch access version attrs description present wState rCB rwCB wCB + CSR_ATTR_P__ (ustatus, 0x000, ISA_N, 0, 1_10, 0,0,0,0,0, "User Status", 0, 0, ustatusR, 0, ustatusW ), + CSR_ATTR_P__ (fflags, 0x001, ISA_DF, 0, 1_10, 0,0,0,0,0, "Floating-Point Flags", 0, riscvWFS, fflagsR, 0, fflagsW ), + CSR_ATTR_P__ (frm, 0x002, ISA_DF, 0, 1_10, 1,0,0,0,0, "Floating-Point Rounding Mode", 0, riscvWFS, frmR, 0, frmW ), + CSR_ATTR_P__ (fcsr, 0x003, ISA_DFV, ISA_FS, 1_10, 1,0,0,0,0, "Floating-Point Control and Status", 0, riscvWFS, fcsrR, 0, fcsrW ), + CSR_ATTR_P__ (uie, 0x004, ISA_N, 0, 1_10, 1,0,0,0,0, "User Interrupt Enable", 0, 0, uieR, 0, uieW ), + CSR_ATTR_T__ (utvec, 0x005, ISA_N, 0, 1_10, 0,0,0,0,0, "User Trap-Vector Base-Address", 0, 0, 0, 0, utvecW ), + CSR_ATTR_TV_ (utvt, 0x007, ISA_N, 0, 1_10, 0,0,0,0,0, "User CLIC Trap-Vector Base-Address", clicP, 0, 0, 0, 0 ), + CSR_ATTR_TV_ (vstart, 0x008, ISA_V, 0, 1_10, 0,0,0,0,0, "Vector Start Index", 0, riscvWVStart,0, 0, 0 ), + CSR_ATTR_TC_ (vxsat, 0x009, ISA_V, ISA_FSandV, 1_10, 0,0,0,0,0, "Fixed-Point Saturate Flag", 0, riscvWFSVS, vxsatR, 0, vxsatW ), + CSR_ATTR_TC_ (vxrm, 0x00A, ISA_V, ISA_FSandV, 1_10, 0,0,0,0,0, "Fixed-Point Rounding Mode", 0, riscvWFSVS, 0, 0, vxrmW ), + CSR_ATTR_T__ (vcsr, 0x00F, ISA_V, 0, 1_10, 1,0,0,0,0, "Vector Control and Status", vcsrP, riscvWVCSR, vcsrR, 0, vcsrW ), + CSR_ATTR_T__ (uscratch, 0x040, ISA_N, 0, 1_10, 0,0,0,0,0, "User Scratch", 0, 0, 0, 0, 0 ), + CSR_ATTR_TV_ (uepc, 0x041, ISA_N, 0, 1_10, 0,0,0,0,0, "User Exception Program Counter", 0, 0, uepcR, 0, 0 ), + CSR_ATTR_T__ (ucause, 0x042, ISA_N, 0, 1_10, 0,0,0,0,0, "User Cause", 0, 0, ucauseR, 0, ucauseW ), + CSR_ATTR_TV_ (utval, 0x043, ISA_N, 0, 1_10, 0,0,0,0,0, "User Trap Value", 0, 0, 0, 0, 0 ), + CSR_ATTR_P__ (uip, 0x044, ISA_N, 0, 1_10, 0,0,0,0,0, "User Interrupt Pending", 0, 0, uipR, uipRW, uipW ), + CSR_ATTR_P__ (unxti, 0x045, ISA_N, 0, 1_10, 0,0,0,1,1, "User Interrupt Handler Address/Enable", clicP, 0, unxtiR, ustatusR, unxtiW ), + CSR_ATTR_P__ (uintstatus, 0xC46, ISA_N, 0, 1_10, 0,0,0,0,0, "User Interrupt Status", clicP, 0, uintstatusR, 0, 0 ), + CSR_ATTR_P__ (uscratchcswl, 0x049, ISA_N, 0, 1_10, 0,1,0,1,1, "User Conditional Scratch Swap, Level", clicSWP,0, uscratchcswlR,0, uscratchcswlW ), + CSR_ATTR_T__ (uintthresh, 0x04A, ISA_N, 0, 1_10, 0,0,0,0,0, "User Interrupt Level Threshold", clicP, 0, 0, 0, uintthreshW ), + CSR_ATTR_P__ (cycle, 0xC00, 0, 0, 1_10, 0,1,0,0,0, "Cycle Counter", 0, 0, mcycleR, 0, 0 ), + CSR_ATTR_P__ (time, 0xC01, 0, 0, 1_10, 0,1,0,0,0, "Timer", 0, 0, mtimeR, 0, 0 ), + CSR_ATTR_P__ (instret, 0xC02, 0, 0, 1_10, 0,1,0,0,0, "Instructions Retired", 0, 0, minstretR, 0, 0 ), + CSR_ATTR_P__3_31 (hpmcounter, 0xC00, 0, 0, 1_10, 0,0,0,0,0, "Performance Monitor Counter ", 0, 0, mhpmR, 0, 0 ), + CSR_ATTR_T__ (vl, 0xC20, ISA_V, 0, 1_10, 0,0,0,0,0, "Vector Length", 0, 0, 0, 0, 0 ), + CSR_ATTR_T__ (vtype, 0xC21, ISA_V, 0, 1_10, 0,0,0,0,0, "Vector Type", 0, 0, 0, 0, 0 ), + CSR_ATTR_T__ (vlenb, 0xC22, ISA_V, 0, 1_10, 0,0,0,0,0, "Vector Length in Bytes", vlenbP, 0, 0, 0, 0 ), + CSR_ATTR_P__ (cycleh, 0xC80, ISA_XLEN_32, 0, 1_10, 0,1,0,0,0, "Cycle Counter High", 0, 0, mcyclehR, 0, 0 ), + CSR_ATTR_P__ (timeh, 0xC81, ISA_XLEN_32, 0, 1_10, 0,1,0,0,0, "Timer High", 0, 0, mtimehR, 0, 0 ), + CSR_ATTR_P__ (instreth, 0xC82, ISA_XLEN_32, 0, 1_10, 0,1,0,0,0, "Instructions Retired High", 0, 0, minstrethR, 0, 0 ), + CSR_ATTR_P__3_31 (hpmcounterh, 0xC80, ISA_XLEN_32, 0, 1_10, 0,0,0,0,0, "Performance Monitor High ", 0, 0, mhpmR, 0, 0 ), + + // name num arch access version attrs description present wState rCB rwCB wCB + CSR_ATTR_P__ (sstatus, 0x100, ISA_S, 0, 1_10, 0,0,0,0,0, "Supervisor Status", 0, riscvRstFS, sstatusR, 0, sstatusW ), + CSR_ATTR_TV_ (sedeleg, 0x102, ISA_SandN, 0, 1_10, 0,0,0,0,0, "Supervisor Exception Delegation", 0, 0, 0, 0, 0 ), + CSR_ATTR_T__ (sideleg, 0x103, ISA_SandN, 0, 1_10, 1,0,0,0,0, "Supervisor Interrupt Delegation", 0, 0, 0, 0, sidelegW ), + CSR_ATTR_P__ (sie, 0x104, ISA_S, 0, 1_10, 1,0,0,0,0, "Supervisor Interrupt Enable", 0, 0, sieR, 0, sieW ), + CSR_ATTR_T__ (stvec, 0x105, ISA_S, 0, 1_10, 0,0,0,0,0, "Supervisor Trap-Vector Base-Address", 0, 0, 0, 0, stvecW ), + CSR_ATTR_TV_ (scounteren, 0x106, ISA_S, 0, 1_10, 0,0,0,0,0, "Supervisor Counter Enable", 0, 0, 0, 0, 0 ), + CSR_ATTR_TV_ (stvt, 0x107, ISA_S, 0, 1_10, 0,0,0,0,0, "Supervisor CLIC Trap-Vector Base-Address", clicP, 0, 0, 0, 0 ), + CSR_ATTR_T__ (sscratch, 0x140, ISA_S, 0, 1_10, 0,0,0,0,0, "Supervisor Scratch", 0, 0, 0, 0, 0 ), + CSR_ATTR_TV_ (sepc, 0x141, ISA_S, 0, 1_10, 0,0,0,0,0, "Supervisor Exception Program Counter", 0, 0, sepcR, 0, 0 ), + CSR_ATTR_T__ (scause, 0x142, ISA_S, 0, 1_10, 0,0,0,0,0, "Supervisor Cause", 0, 0, scauseR, 0, scauseW ), + CSR_ATTR_TV_ (stval, 0x143, ISA_S, 0, 1_10, 0,0,0,0,0, "Supervisor Trap Value", 0, 0, 0, 0, 0 ), + CSR_ATTR_P__ (sip, 0x144, ISA_S, 0, 1_10, 0,0,0,0,0, "Supervisor Interrupt Pending", 0, 0, sipR, sipRW, sipW ), + CSR_ATTR_P__ (snxti, 0x145, ISA_S, 0, 1_10, 0,0,0,1,1, "Supervisor Interrupt Handler Address/Enable", clicP, 0, snxtiR, sstatusR, snxtiW ), + CSR_ATTR_P__ (sintstatus, 0xD46, ISA_S, 0, 1_10, 0,0,0,0,0, "Supervisor Interrupt Status", clicP, 0, sintstatusR, 0, 0 ), + CSR_ATTR_P__ (sscratchcsw, 0x148, ISA_S, 0, 1_10, 0,1,0,1,1, "Supervisor Conditional Scratch Swap, Priv", clicSWP,0, sscratchcswR, 0, sscratchcswW ), + CSR_ATTR_P__ (sscratchcswl, 0x149, ISA_S, 0, 1_10, 0,1,0,1,1, "Supervisor Conditional Scratch Swap, Level", clicSWP,0, sscratchcswlR,0, sscratchcswlW ), + CSR_ATTR_T__ (sintthresh, 0x14A, ISA_S, 0, 1_10, 0,0,0,0,0, "Supervisor Interrupt Level Threshold", clicP, 0, 0, 0, sintthreshW ), + CSR_ATTR_T__ (satp, 0x180, ISA_S, 0, 1_10, 0,0,1,0,0, "Supervisor Address Translation and Protection", 0, 0, 0, 0, satpW ), + + // name num arch access version attrs description present wState rCB rwCB wCB + CSR_ATTR_T__ (mvendorid, 0xF11, 0, 0, 1_10, 0,0,0,0,0, "Vendor ID", 0, 0, 0, 0, 0 ), + CSR_ATTR_T__ (marchid, 0xF12, 0, 0, 1_10, 0,0,0,0,0, "Architecture ID", 0, 0, 0, 0, 0 ), + CSR_ATTR_T__ (mimpid, 0xF13, 0, 0, 1_10, 0,0,0,0,0, "Implementation ID", 0, 0, 0, 0, 0 ), + CSR_ATTR_T__ (mhartid, 0xF14, 0, 0, 1_10, 0,0,0,0,0, "Hardware Thread ID", 0, 0, 0, 0, 0 ), + CSR_ATTR_TV_ (mstatus, 0x300, 0, 0, 1_10, 0,0,0,0,0, "Machine Status", 0, riscvRstFS, mstatusR, 0, mstatusW ), + CSR_ATTR_T__ (misa, 0x301, 0, 0, 1_10, 1,0,0,0,0, "ISA and Extensions", 0, 0, 0, 0, misaW ), + CSR_ATTR_TV_ (medeleg, 0x302, ISA_SorN, 0, 1_10, 0,0,0,0,0, "Machine Exception Delegation", 0, 0, 0, 0, 0 ), + CSR_ATTR_T__ (mideleg, 0x303, ISA_SorN, 0, 1_10, 1,0,0,0,0, "Machine Interrupt Delegation", 0, 0, 0, 0, midelegW ), + CSR_ATTR_T__ (mie, 0x304, 0, 0, 1_10, 1,0,0,0,0, "Machine Interrupt Enable", 0, 0, mieR, 0, mieW ), + CSR_ATTR_T__ (mtvec, 0x305, 0, 0, 1_10, 0,0,0,0,0, "Machine Trap-Vector Base-Address", 0, 0, 0, 0, mtvecW ), + CSR_ATTR_TV_ (mcounteren, 0x306, ISA_U, 0, 1_10, 0,0,0,0,0, "Machine Counter Enable", 0, 0, 0, 0, 0 ), + CSR_ATTR_TV_ (mtvt, 0x307, 0, 0, 1_10, 0,0,0,0,0, "Machine CLIC Trap-Vector Base-Address", clicP, 0, 0, 0, 0 ), + CSR_ATTR_TV_ (mstatush, 0x310, ISA_XLEN_32, 0, 1_12, 0,0,0,0,0, "Machine Status High", 0, 0, 0, 0, mstatushW ), + CSR_ATTR_TV_ (mcountinhibit,0x320, 0, 0, 1_11, 0,0,0,0,0, "Machine Counter Inhibit", 0, 0, 0, 0, mcountinhibitW), + CSR_ATTR_T__ (mscratch, 0x340, 0, 0, 1_10, 0,0,0,0,0, "Machine Scratch", 0, 0, 0, 0, 0 ), + CSR_ATTR_TV_ (mepc, 0x341, 0, 0, 1_10, 0,0,0,0,0, "Machine Exception Program Counter", 0, 0, mepcR, 0, 0 ), + CSR_ATTR_T__ (mcause, 0x342, 0, 0, 1_10, 0,0,0,0,0, "Machine Cause", 0, 0, mcauseR, 0, mcauseW ), + CSR_ATTR_TV_ (mtval, 0x343, 0, 0, 1_10, 0,0,0,0,0, "Machine Trap Value", 0, 0, 0, 0, 0 ), + CSR_ATTR_T__ (mip, 0x344, 0, 0, 1_10, 0,0,0,0,0, "Machine Interrupt Pending", 0, 0, mipR, mipRW, mipW ), + CSR_ATTR_P__ (mnxti, 0x345, 0, 0, 1_10, 0,0,0,1,1, "Machine Interrupt Handler Address/Enable", clicP, 0, mnxtiR, mstatusR, mnxtiW ), + CSR_ATTR_T__ (mintstatus, 0xF46, 0, 0, 1_10, 0,0,0,0,0, "Machine Interrupt Status", clicP, 0, 0, 0, 0 ), + CSR_ATTR_P__ (mscratchcsw, 0x348, ISA_U, 0, 1_10, 0,1,0,1,1, "Machine Conditional Scratch Swap, Priv", clicSWP,0, mscratchcswR, 0, mscratchcswW ), + CSR_ATTR_P__ (mscratchcswl, 0x349, 0, 0, 1_10, 0,1,0,1,1, "Machine Conditional Scratch Swap, Level", clicSWP,0, mscratchcswlR,0, mscratchcswlW ), + CSR_ATTR_T__ (mintthresh, 0x34A, 0, 0, 1_10, 0,0,0,0,0, "Machine Interrupt Level Threshold", clicP, 0, 0, 0, mintthreshW ), + CSR_ATTR_T__ (mclicbase, 0x34B, 0, 0, 1_10, 0,0,0,0,0, "Machine CLIC Base Address", clicP, 0, 0, 0, mclicbaseW ), + + // name num arch access version attrs description present wState rCB rwCB wCB + CSR_ATTR_P__ (pmpcfg0, 0x3A0, 0, 0, 1_10, 0,0,0,0,0, "Physical Memory Protection Configuration 0", 0, 0, pmpcfgR, 0, pmpcfgW ), + CSR_ATTR_P__ (pmpcfg1, 0x3A1, ISA_XLEN_32, 0, 1_10, 0,0,0,0,0, "Physical Memory Protection Configuration 1", 0, 0, pmpcfgR, 0, pmpcfgW ), + CSR_ATTR_P__ (pmpcfg2, 0x3A2, 0, 0, 1_10, 0,0,0,0,0, "Physical Memory Protection Configuration 2", 0, 0, pmpcfgR, 0, pmpcfgW ), + CSR_ATTR_P__ (pmpcfg3, 0x3A3, ISA_XLEN_32, 0, 1_10, 0,0,0,0,0, "Physical Memory Protection Configuration 3", 0, 0, pmpcfgR, 0, pmpcfgW ), + CSR_ATTR_P__0_15 (pmpaddr, 0x3B0, 0, 0, 1_10, 0,0,0,0,0, "Physical Memory Protection Address ", 0, 0, pmpaddrR, 0, pmpaddrW ), + + // name num arch access version attrs description present wState rCB rwCB wCB + CSR_ATTR_P__ (mcycle, 0xB00, 0, 0, 1_10, 0,1,0,0,0, "Machine Cycle Counter", 0, 0, mcycleR, 0, mcycleW ), + CSR_ATTR_P__ (minstret, 0xB02, 0, 0, 1_10, 0,1,0,0,0, "Machine Instructions Retired", 0, 0, minstretR, 0, minstretW ), + CSR_ATTR_P__3_31 (mhpmcounter, 0xB00, 0, 0, 1_10, 0,0,0,0,0, "Machine Performance Monitor Counter ", 0, 0, mhpmR, 0, mhpmW ), + CSR_ATTR_P__ (mcycleh, 0xB80, ISA_XLEN_32, 0, 1_10, 0,1,0,0,0, "Machine Cycle Counter High", 0, 0, mcyclehR, 0, mcyclehW ), + CSR_ATTR_P__ (minstreth, 0xB82, ISA_XLEN_32, 0, 1_10, 0,1,0,0,0, "Machine Instructions Retired High", 0, 0, minstrethR, 0, minstrethW ), + CSR_ATTR_P__3_31 (mhpmcounterh, 0xB80, ISA_XLEN_32, 0, 1_10, 0,0,0,0,0, "Machine Performance Monitor Counter High ", 0, 0, mhpmR, 0, mhpmW ), + CSR_ATTR_P__3_31 (mhpmevent, 0x320, 0, 0, 1_10, 0,0,0,0,0, "Machine Performance Monitor Event Select ", 0, 0, mhpmR, 0, mhpmW ), + + // name num arch access version attrs description present wState rCB rwCB wCB + CSR_ATTR_NIP (tselect, 0x7A0, 0, 0, 1_10, 0,0,0,0,0, "Debug/Trace Trigger Register Select" ), + CSR_ATTR_NIP (tdata1, 0x7A1, 0, 0, 1_10, 0,0,0,0,0, "Debug/Trace Trigger Data 1" ), + CSR_ATTR_NIP (tdata2, 0x7A2, 0, 0, 1_10, 0,0,0,0,0, "Debug/Trace Trigger Data 2" ), + CSR_ATTR_NIP (tdata3, 0x7A3, 0, 0, 1_10, 0,0,0,0,0, "Debug/Trace Trigger Data 3" ), + + // name num arch access version attrs description present wState rCB rwCB wCB + CSR_ATTR_TV_ (dcsr, 0x7B0, 0, 0, 1_10, 0,0,0,0,0, "Debug Control and Status", debugP, 0, 0, 0, dcsrW ), + CSR_ATTR_T__ (dpc, 0x7B1, 0, 0, 1_10, 0,0,0,0,0, "Debug PC", debugP, 0, 0, 0, 0 ), + CSR_ATTR_T__ (dscratch0, 0x7B2, 0, 0, 1_10, 0,0,0,0,0, "Debug Scratch 0", debugP, 0, 0, 0, 0 ), + CSR_ATTR_T__ (dscratch1, 0x7B3, 0, 0, 1_10, 0,0,0,0,0, "Debug Scratch 1", debugP, 0, 0, 0, 0 ), }; @@ -2212,13 +2726,16 @@ static Uns32 getCSRNum(riscvCSRAttrsCP attrs) { } // -// Return read/write access constraints for the register +// Return read/write access constraints for the register (determined by address +// in the base model, but also allow write access if a write callback is +// specified for a register in a normally read-only location by a custom +// extension) // -inline static vmiRegAccess getAccess(riscvCSRAttrsCP attrs) { +static vmiRegAccess getAccess(riscvCSRAttrsCP attrs) { CSRFields fields = {attrs->csrNum}; - return (fields.access==3) ? vmi_RA_R : vmi_RA_RW; + return (fields.access==3) && !attrs->writeCB ? vmi_RA_R : vmi_RA_RW; } // @@ -2706,6 +3223,14 @@ static void fromConfiguredArch(riscvCSRAttrsCP attrs, riscvP riscv) { #define SET_CSR_MASK_V_64(_CPU, _RNAME, _VALUE) \ (_CPU)->csrMask._RNAME.u64.bits = _VALUE +// bitwise-and mask with the given value in 32-bit CSR mask +#define AND_CSR_MASK_V_32(_CPU, _RNAME, _VALUE) \ + (_CPU)->csrMask._RNAME.u32.bits &= _VALUE + +// bitwise-and mask with the given value in 64-bit CSR mask +#define AND_CSR_MASK_V_64(_CPU, _RNAME, _VALUE) \ + (_CPU)->csrMask._RNAME.u64.bits &= _VALUE + // set mask to the given value in all CSR masks #define SET_CSR_MASK_V(_CPU, _RNAME, _VALUE) \ SET_CSR_MASK_V_32(_CPU, _RNAME, _VALUE); \ @@ -2818,7 +3343,7 @@ static void riscvCSRInitialReset(riscvP riscv) { // static Uns64 getExceptionMask(riscvException code) { - VMI_ASSERT(code=riscv_E_Interrupt, "bad interrupt id %u", code); + VMI_ASSERT(isInterrupt(code), "bad interrupt id %u", code); - return 1ULL << (code-riscv_E_Interrupt); + return 1ULL << exceptionToInt(code); } // @@ -2868,13 +3393,14 @@ void riscvCSRInit(riscvP riscv, Uns32 index) { riscvCSRInitialReset(riscv); //-------------------------------------------------------------------------- - // mvendorid, marchid, mimpid, mhartid values + // mvendorid, marchid, mimpid, mhartid, mclicbase values //-------------------------------------------------------------------------- WR_CSR(riscv, mvendorid, cfg->csr.mvendorid.u64.bits); WR_CSR(riscv, marchid, cfg->csr.marchid.u64.bits); WR_CSR(riscv, mimpid, cfg->csr.mimpid.u64.bits); WR_CSR(riscv, mhartid, cfg->csr.mhartid.u64.bits+index); + WR_CSR(riscv, mclicbase, cfg->csr.mclicbase.u64.bits & ~0xfffULL); //-------------------------------------------------------------------------- // misa mask @@ -2993,7 +3519,7 @@ void riscvCSRInit(riscvP riscv, Uns32 index) { // exception and interrupt masks //-------------------------------------------------------------------------- - // get mask of implemented exceptions/interrupts visible in Monitor mode + // get mask of implemented exceptions/interrupts visible in Machine mode Uns64 mExceptions = riscv->exceptionMask; Uns64 mInterrupts = riscv->interruptMask; @@ -3117,6 +3643,16 @@ void riscvCSRInit(riscvP riscv, Uns32 index) { WR_CSR_FIELD(riscv, utvec, MODE, riscv_int_CLIC); } + //-------------------------------------------------------------------------- + // mtval, stval, utval masks + //-------------------------------------------------------------------------- + + if(!cfg->tval_zero) { + SET_CSR_MASK_V(riscv, mtval, -1); + SET_CSR_MASK_V(riscv, stval, -1); + SET_CSR_MASK_V(riscv, utval, -1); + } + //-------------------------------------------------------------------------- // mtvt, stvt, utvt masks //-------------------------------------------------------------------------- @@ -3135,23 +3671,58 @@ void riscvCSRInit(riscvP riscv, Uns32 index) { // mcause, scause, ucause masks //-------------------------------------------------------------------------- - // use defined masks from configuration - Uns32 causeMask32 = cfg->csrMask.cause.u32.bits ? : -1; - Uns64 causeMask64 = cfg->csrMask.cause.u64.bits ? : -1; + // enable writable bits (either all bits or restricted ExceptionCode bits) + if(!CLICPresent(riscv)) { + SET_CSR_MASK_V(riscv, mcause, -1); + SET_CSR_MASK_V(riscv, scause, -1); + SET_CSR_MASK_V(riscv, ucause, -1); + } else { + SET_CSR_FIELD_MASK_V(riscv, mcause, ExceptionCode, -1); + SET_CSR_FIELD_MASK_V(riscv, scause, ExceptionCode, -1); + SET_CSR_FIELD_MASK_V(riscv, ucause, ExceptionCode, -1); + } + + // bitwise-and mcause, scause, ucause masks (per instruction length) + AND_CSR_MASK_V_32(riscv, mcause, cfg->ecode_mask); + AND_CSR_MASK_V_32(riscv, scause, cfg->ecode_mask); + AND_CSR_MASK_V_32(riscv, ucause, cfg->ecode_mask); + AND_CSR_MASK_V_64(riscv, mcause, cfg->ecode_mask); + AND_CSR_MASK_V_64(riscv, scause, cfg->ecode_mask); + AND_CSR_MASK_V_64(riscv, ucause, cfg->ecode_mask); + + // enable interrupt bits irrespective of mask + SET_CSR_FIELD_MASK_V(riscv, mcause, Interrupt, -1); + SET_CSR_FIELD_MASK_V(riscv, scause, Interrupt, -1); + SET_CSR_FIELD_MASK_V(riscv, ucause, Interrupt, -1); + + // enable CLIC-specific bits irrespective of mask + if(CLICPresent(riscv)) { - // set mcause, scause, ucause masks (per instruction length) - SET_CSR_MASK_V_32(riscv, mcause, causeMask32); - SET_CSR_MASK_V_32(riscv, scause, causeMask32); - SET_CSR_MASK_V_32(riscv, ucause, causeMask32); - SET_CSR_MASK_V_64(riscv, mcause, causeMask64); - SET_CSR_MASK_V_64(riscv, scause, causeMask64); - SET_CSR_MASK_V_64(riscv, ucause, causeMask64); + // enable pil bits + SET_CSR_FIELD_MASK_V(riscv, mcause, pil, -1); + SET_CSR_FIELD_MASK_V(riscv, scause, pil, -1); + SET_CSR_FIELD_MASK_V(riscv, ucause, pil, -1); + + // enable pie bits + SET_CSR_FIELD_MASK_V(riscv, mcause, pie, -1); + SET_CSR_FIELD_MASK_V(riscv, scause, pie, -1); + SET_CSR_FIELD_MASK_V(riscv, ucause, pie, -1); + + // enable inhv bits + SET_CSR_FIELD_MASK_V(riscv, mcause, inhv, -1); + SET_CSR_FIELD_MASK_V(riscv, scause, inhv, -1); + SET_CSR_FIELD_MASK_V(riscv, ucause, inhv, -1); + + // enable pp bits + SET_CSR_FIELD_MASK_V(riscv, mcause, pp, 3); + SET_CSR_FIELD_MASK_V(riscv, scause, pp, 1); + } //-------------------------------------------------------------------------- // mcounteren, scounteren masks //-------------------------------------------------------------------------- - Uns32 counterenMask = WM32_counteren_HPM; + Uns32 counterenMask = cfg->counteren_mask & WM32_counteren_HPM; // CY, TM and IR bits are writable only if the cycle, time and instret // registers are defined @@ -3168,7 +3739,7 @@ void riscvCSRInit(riscvP riscv, Uns32 index) { // set mcounteren, scounteren, mcountinhibit masks SET_CSR_MASK_V(riscv, mcounteren, counterenMask); SET_CSR_MASK_V(riscv, scounteren, counterenMask); - SET_CSR_MASK_V(riscv, mcountinhibit, counterenMask); + SET_CSR_MASK_V(riscv, mcountinhibit, counterenMask & ~WM32_counteren_TM); //-------------------------------------------------------------------------- // scounteren implied value @@ -3279,7 +3850,7 @@ const char *riscvGetCSRName(riscvP riscv, Uns32 csrNum) { //////////////////////////////////////////////////////////////////////////////// // -// Read a CSR given its id +// Read a CSR given its attributes object // Bool riscvReadCSR(riscvCSRAttrsCP attrs, riscvP riscv, void *buffer) { @@ -3300,10 +3871,8 @@ Bool riscvReadCSR(riscvCSRAttrsCP attrs, riscvP riscv, void *buffer) { // this function should only be used when there is a read callback VMI_ASSERT(readCB, "require read callback"); - // read value, indicating an artifact access - riscv->artifactAccess = True; + // read value Uns64 value = readCB(attrs, riscv); - riscv->artifactAccess = False; // assign to buffer of correct size if(is64Bit) { @@ -3340,7 +3909,7 @@ Bool riscvReadCSR(riscvCSRAttrsCP attrs, riscvP riscv, void *buffer) { } // -// Write a CSR given its id +// Write a CSR given its attributes object // Bool riscvWriteCSR(riscvCSRAttrsCP attrs, riscvP riscv, const void *buffer) { @@ -3369,10 +3938,8 @@ Bool riscvWriteCSR(riscvCSRAttrsCP attrs, riscvP riscv, const void *buffer) { if(writeCB) { - // write value using callback, indicating an artifact access - riscv->artifactAccess = True; + // write value using callback writeCB(attrs, riscv, newValue); - riscv->artifactAccess = False; } else if(rawValue) { @@ -3414,6 +3981,33 @@ Bool riscvWriteCSR(riscvCSRAttrsCP attrs, riscvP riscv, const void *buffer) { } +//////////////////////////////////////////////////////////////////////////////// +// LINKED MODEL ACCESS FUNCTIONS +//////////////////////////////////////////////////////////////////////////////// + +// +// Read a CSR in the base model given its id +// +Uns64 riscvReadBaseCSR(riscvP riscv, riscvCSRId id) { + + Uns64 result = 0; + + riscvReadCSR(&csrs[id], riscv, &result); + + return result; +} + +// +// Write a CSR in the base model given its id +// +Uns64 riscvWriteBaseCSR(riscvP riscv, riscvCSRId id, Uns64 newValue) { + + riscvWriteCSR(&csrs[id], riscv, &newValue); + + return newValue; +} + + //////////////////////////////////////////////////////////////////////////////// // MORPH-TIME INTERFACE ACCESS FUNCTIONS //////////////////////////////////////////////////////////////////////////////// @@ -3581,6 +4175,7 @@ void riscvEmitCSRRead( void riscvEmitCSRWrite( riscvCSRAttrsCP attrs, riscvP riscv, + vmiReg rd, vmiReg rs, vmiReg tmp ) { @@ -3598,7 +4193,7 @@ void riscvEmitCSRWrite( // if CSR is implemented externally, mirror the result into any raw // register in the model (otherwise discard the result) if(!csrImplementExternalWrite(attrs, riscv)) { - raw = VMI_NOREG; + raw = attrs->writeRd ? rd : VMI_NOREG; } // emit code to call the write function (NOTE: argument is always 64 @@ -3719,6 +4314,11 @@ void riscvCSRSave( VMIRT_SAVE_FIELD(cxt, riscv, csr.vtype); } + // read-only CLIC register state requires explicit save + if(CLICPresent(riscv)) { + VMIRT_SAVE_FIELD(cxt, riscv, csr.mintstatus); + } + break; case SRT_END: @@ -3763,6 +4363,11 @@ void riscvCSRRestore( riscvRefreshVectorPMKey(riscv); } + // read-only CLIC register state requires explicit restore + if(CLICPresent(riscv)) { + VMIRT_RESTORE_FIELD(cxt, riscv, csr.mintstatus); + } + break; case SRT_END: diff --git a/source/riscvCSR.h b/source/riscvCSR.h index fb18d1f..3d649c8 100644 --- a/source/riscvCSR.h +++ b/source/riscvCSR.h @@ -27,6 +27,7 @@ #include "riscvMode.h" #include "riscvRegisters.h" #include "riscvTypeRefs.h" +#include "riscvTypes.h" #include "riscvVariant.h" @@ -112,6 +113,11 @@ typedef enum riscvCSRIdE { CSR_ID (ucause), // 0x042 CSR_ID (utval), // 0x043 CSR_ID (uip), // 0x044 + CSR_ID (unxti), // 0x045 + CSR_ID (uintstatus), // 0xC46 + CSR_ID (uscratchcswl), // 0x049 + CSR_ID (uintthresh), // 0x04A + CSR_ID (cycle), // 0xC00 CSR_ID (time), // 0xC01 CSR_ID (instret), // 0xC02 @@ -136,6 +142,11 @@ typedef enum riscvCSRIdE { CSR_ID (scause), // 0x142 CSR_ID (stval), // 0x143 CSR_ID (sip), // 0x144 + CSR_ID (snxti), // 0x145 + CSR_ID (sintstatus), // 0xD46 + CSR_ID (sscratchcsw), // 0x148 + CSR_ID (sscratchcswl), // 0x149 + CSR_ID (sintthresh), // 0x14A CSR_ID (satp), // 0x180 CSR_ID (mvendorid), // 0xF11 @@ -157,6 +168,12 @@ typedef enum riscvCSRIdE { CSR_ID (mcause), // 0x342 CSR_ID (mtval), // 0x343 CSR_ID (mip), // 0x344 + CSR_ID (mnxti), // 0x345 + CSR_ID (mintstatus), // 0xF46 + CSR_ID (mscratchcsw), // 0x348 + CSR_ID (mscratchcswl), // 0x349 + CSR_ID (mintthresh), // 0x34A + CSR_ID (mclicbase), // 0x34B CSR_ID_0_3 (pmpcfg), // 0x3A0-0x3A3 CSR_ID_0_15 (pmpaddr), // 0x3B0-0x3BF CSR_ID (mcycle), // 0xB00 @@ -235,6 +252,21 @@ Bool riscvReadCSR(riscvCSRAttrsCP attrs, riscvP riscv, void *buffer); Bool riscvWriteCSR(riscvCSRAttrsCP attrs, riscvP riscv, const void *buffer); +//////////////////////////////////////////////////////////////////////////////// +// LINKED MODEL ACCESS FUNCTIONS +//////////////////////////////////////////////////////////////////////////////// + +// +// Read a CSR in the base model given its id +// +Uns64 riscvReadBaseCSR(riscvP riscv, riscvCSRId id); + +// +// Write a CSR in the base model given its id +// +Uns64 riscvWriteBaseCSR(riscvP riscv, riscvCSRId id, Uns64 newValue); + + //////////////////////////////////////////////////////////////////////////////// // MORPH-TIME INTERFACE ACCESS FUNCTIONS //////////////////////////////////////////////////////////////////////////////// @@ -266,6 +298,7 @@ void riscvEmitCSRRead( void riscvEmitCSRWrite( riscvCSRAttrsCP attrs, riscvP riscv, + vmiReg rd, vmiReg rs, vmiReg tmp ); @@ -370,7 +403,7 @@ void riscvRefreshVectorPMKey(riscvP riscv); // // Update vtype CSR // -void riscvSetVType(riscvP riscv, Bool vill, Uns32 vsew, Uns32 vlmul); +void riscvSetVType(riscvP riscv, Bool vill, riscvVType vtype); // // Update vl CSR and aliases of it @@ -849,13 +882,24 @@ typedef CSR_REG_TYPE(genericXLEN) CSR_REG_TYPE(mepc); // 32-bit view typedef struct { - Uns32 ExceptionCode : 31; + Uns32 ExceptionCode : 16; + Uns32 pil : 8; + Uns32 _u1 : 3; + Uns32 pie : 1; + Uns32 pp : 2; + Uns32 inhv : 1; Uns32 Interrupt : 1; } CSR_REG_TYPE_32(cause); // 64-bit view typedef struct { - Uns64 ExceptionCode : 63; + Uns64 ExceptionCode : 16; + Uns64 pil : 8; + Uns64 _u1 : 3; + Uns64 pie : 1; + Uns64 pp : 2; + Uns64 inhv : 1; + Uns64 _u2 : 32; Uns64 Interrupt : 1; } CSR_REG_TYPE_64(cause); @@ -916,6 +960,83 @@ typedef CSR_REG_TYPE(ip) CSR_REG_TYPE(mip); #define WM32_sip 0x00000103 #define WM32_uip 0x00000001 +// ----------------------------------------------------------------------------- +// uintstatus (id 0xC46) +// sintstatus (id 0xD46) +// mintstatus (id 0xF46) +// ----------------------------------------------------------------------------- + +// 32-bit view +typedef struct { + Uns32 uil : 8; + Uns32 sil : 8; + Uns32 _u1 : 8; + Uns32 mil : 8; +} CSR_REG_TYPE_32(mintstatus); + +// define 32 bit type +CSR_REG_STRUCT_DECL_32(mintstatus); + +// define write masks +#define WM32_mintstatus 0x00000000 +#define WM32_sintstatus 0x00000000 +#define WM32_uintstatus 0x00000000 + +// define read masks +#define RM32_sintstatus 0x0000ffff +#define RM32_uintstatus 0x000000ff + +// ----------------------------------------------------------------------------- +// sscratchcsw (id 0x148) +// mscratchcsw (id 0x348) +// ----------------------------------------------------------------------------- + +// define alias types +typedef CSR_REG_TYPE(genericXLEN) CSR_REG_TYPE(sscratchcsw); +typedef CSR_REG_TYPE(genericXLEN) CSR_REG_TYPE(mscratchcsw); + +// ----------------------------------------------------------------------------- +// uscratchcswl (id 0x049) +// sscratchcswl (id 0x149) +// mscratchcswl (id 0x349) +// ----------------------------------------------------------------------------- + +// define alias types +typedef CSR_REG_TYPE(genericXLEN) CSR_REG_TYPE(uscratchcswl); +typedef CSR_REG_TYPE(genericXLEN) CSR_REG_TYPE(sscratchcswl); +typedef CSR_REG_TYPE(genericXLEN) CSR_REG_TYPE(mscratchcswl); + +// ----------------------------------------------------------------------------- +// uintthresh (id 0x04A) +// sintthresh (id 0x14A) +// mintthresh (id 0x34A) +// ----------------------------------------------------------------------------- + +// 32-bit view +typedef struct { + Uns32 th : 8; + Uns32 _u1 : 24; +} CSR_REG_TYPE_32(intthresh); + +// define 32 bit type +CSR_REG_STRUCT_DECL_32(intthresh); + +// define alias types +typedef CSR_REG_TYPE(intthresh) CSR_REG_TYPE(uintthresh); +typedef CSR_REG_TYPE(intthresh) CSR_REG_TYPE(sintthresh); +typedef CSR_REG_TYPE(intthresh) CSR_REG_TYPE(mintthresh); + +// ----------------------------------------------------------------------------- +// mclicbase (id 0x34B) +// ----------------------------------------------------------------------------- + +// define alias types +typedef CSR_REG_TYPE(genericXLEN) CSR_REG_TYPE(mclicbase); + +// define write masks +#define WM32_mclicbase 0x00000000 +#define WM64_mclicbase 0x00000000 + // ----------------------------------------------------------------------------- // pmpcfg (id 0x3A0-0x3A3) // ----------------------------------------------------------------------------- @@ -1241,18 +1362,24 @@ typedef CSR_REG_TYPE(genericXLEN) CSR_REG_TYPE(vl); // 32-bit view typedef struct { - Uns32 vlmul : 2; - Uns32 vsew : 3; - Uns32 _u1 : 26; - Uns32 vill : 1; + Uns32 vlmul : 2; + Uns32 vsew : 3; + Uns32 vlmulf : 1; + Uns32 vta : 1; + Uns32 vma : 1; + Uns32 _u1 : 23; + Uns32 vill : 1; } CSR_REG_TYPE_32(vtype); // 64-bit view typedef struct { - Uns64 vlmul : 2; - Uns64 vsew : 3; - Uns64 _u1 : 58; - Uns64 vill : 1; + Uns64 vlmul : 2; + Uns64 vsew : 3; + Uns32 vlmulf : 1; + Uns32 vta : 1; + Uns32 vma : 1; + Uns64 _u1 : 55; + Uns64 vill : 1; } CSR_REG_TYPE_64(vtype); // define 32/64 bit type @@ -1278,8 +1405,7 @@ typedef CSR_REG_TYPE(genericXLEN) CSR_REG_TYPE(vlenb); //////////////////////////////////////////////////////////////////////////////// // -// Use this to define a register entry in riscvCSRs -// below +// Use this to define a register entry in riscvCSRs below // #define CSR_REG_DECL(_N) CSR_REG_TYPE(_N) _N @@ -1301,6 +1427,7 @@ typedef struct riscvCSRsS { CSR_REG_DECL(uepc); // 0x041 CSR_REG_DECL(ucause); // 0x042 CSR_REG_DECL(utval); // 0x043 + CSR_REG_DECL(uintthresh); // 0x04A CSR_REG_DECL(vl); // 0xC20 CSR_REG_DECL(vtype); // 0xC21 CSR_REG_DECL(vlenb); // 0xC22 @@ -1315,6 +1442,7 @@ typedef struct riscvCSRsS { CSR_REG_DECL(sepc); // 0x141 CSR_REG_DECL(scause); // 0x142 CSR_REG_DECL(stval); // 0x143 + CSR_REG_DECL(sintthresh); // 0x14A CSR_REG_DECL(satp); // 0x180 // MACHINE MODE CSRS @@ -1337,6 +1465,9 @@ typedef struct riscvCSRsS { CSR_REG_DECL(mcause); // 0x342 CSR_REG_DECL(mtval); // 0x343 CSR_REG_DECL(mip); // 0x344 + CSR_REG_DECL(mintthresh); // 0x34A + CSR_REG_DECL(mclicbase); // 0x34B + CSR_REG_DECL(mintstatus); // 0xF46 // DEBUG MODE CSRS CSR_REG_DECL(dcsr); // 0x7B0 @@ -1363,6 +1494,7 @@ typedef struct riscvCSRMasksS { CSR_REG_DECL(vstart); // 0x008 CSR_REG_DECL(uepc); // 0x041 CSR_REG_DECL(ucause); // 0x042 + CSR_REG_DECL(utval); // 0x043 // SUPERVISOR MODE CSRS CSR_REG_DECL(sedeleg); // 0x102 @@ -1372,6 +1504,7 @@ typedef struct riscvCSRMasksS { CSR_REG_DECL(scounteren); // 0x106 CSR_REG_DECL(sepc); // 0x141 CSR_REG_DECL(scause); // 0x142 + CSR_REG_DECL(stval); // 0x143 // MACHINE MODE CSRS CSR_REG_DECL(mstatus); // 0x300 @@ -1386,6 +1519,7 @@ typedef struct riscvCSRMasksS { CSR_REG_DECL(mcountinhibit);// 0x320 CSR_REG_DECL(mepc); // 0x341 CSR_REG_DECL(mcause); // 0x342 + CSR_REG_DECL(mtval); // 0x343 // DEBUG MODE CSRS CSR_REG_DECL(dcsr); // 0x7B0 diff --git a/source/riscvCSRTypes.h b/source/riscvCSRTypes.h index b225548..06c16b7 100644 --- a/source/riscvCSRTypes.h +++ b/source/riscvCSRTypes.h @@ -100,8 +100,10 @@ typedef struct riscvCSRAttrsS { riscvPrivVer version; // minimum specification version Bool wEndBlock; // whether write terminates this block Bool wEndRM; // whether write invalidates RM assumption + Bool noSaveRestore; // whether to exclude from save/restore Bool noTraceChange; // whether to exclude from trace change Bool TVMT; // whether trapped by mstatus.TVM + Bool writeRd; // whether write updates Rd riscvCSRPresentFn presentCB; // CSR present callback riscvCSRReadFn readCB; // read callback riscvCSRReadFn readWriteCB; // read callback (in r/w context) diff --git a/source/riscvConfig.h b/source/riscvConfig.h index d4e81c7..dc70970 100644 --- a/source/riscvConfig.h +++ b/source/riscvConfig.h @@ -30,6 +30,11 @@ #include "riscvTypeRefs.h" #include "riscvVariant.h" +// +// This default value indicates all bits writable in arch except E, S and U +// +#define RV_ARCH_MASK_DEFAULT (~(ISA_XLEN_ANY|ISA_E|ISA_S|ISA_U)) + // // Function type for adding documentation // @@ -73,9 +78,14 @@ typedef struct riscvConfigS { // configuration not visible in CSR state Uns64 reset_address; // reset vector address Uns64 nmi_address; // NMI address + Uns64 debug_address; // debug vector address + Uns64 dexc_address; // debug exception address Uns64 unimp_int_mask; // mask of unimplemented interrupts Uns64 no_ideleg; // non-delegated interrupts Uns64 no_edeleg; // non-delegated exceptions + Uns64 ecode_mask; // implemented bits in xcause.ecode + Uns64 ecode_nmi; // exception code for NMI + Uns32 counteren_mask; // counter-enable implemented mask Uns32 local_int_num; // number of local interrupts Uns32 lr_sc_grain; // LR/SC region grain size Uns32 ASID_bits; // number of implemented ASID bits @@ -108,12 +118,14 @@ typedef struct riscvConfigS { Bool require_vstart0; // require vstart 0 if uninterruptible? Bool enable_CSR_bus; // enable CSR implementation bus Bool external_int_id; // enable external interrupt ID ports - Bool tval_ii_code; // instruction bits in [sm]tval for + Bool tval_zero; // whether [smu]tval are always zero + Bool tval_ii_code; // instruction bits in [smu]tval for // illegal instruction exception? // CLIC configuration Uns32 CLICLEVELS; // number of CLIC interrupt levels - Bool CLICANDBASIC; // implements basic mode also + Bool CLICANDBASIC; // whether implements basic mode also + Uns8 CLICVERSION; // CLIC version Uns8 CLICINTCTLBITS; // bits implemented in clicintctl[i] Uns8 CLICCFGMBITS; // bits implemented for cliccfg.nmbits Uns8 CLICCFGLBITS; // bits implemented for cliccfg.nlbits @@ -129,6 +141,7 @@ typedef struct riscvConfigS { CSR_REG_DECL (mhartid); // mhartid value CSR_REG_DECL (mtvec); // mtvec value CSR_REG_DECL (mstatus); // mstatus reset value + CSR_REG_DECL (mclicbase); // mclicbase value } csr; // CSR register masks @@ -139,7 +152,6 @@ typedef struct riscvConfigS { CSR_REG_DECL (mtvt); // mtvec mask CSR_REG_DECL (stvt); // stvec mask CSR_REG_DECL (utvt); // utvec mask - CSR_REG_DECL (cause); // cause mask } csrMask; // custom documentation diff --git a/source/riscvConfigList.c b/source/riscvConfigList.c index 146c1e1..16b6d41 100644 --- a/source/riscvConfigList.c +++ b/source/riscvConfigList.c @@ -26,19 +26,21 @@ // Specify named variant // #define RISC_VARIANT(_NAME, _PMP_REGS, _ARCH) { \ - .name = _NAME, \ - .arch = _ARCH, \ - .user_version = RVUV_DEFAULT, \ - .priv_version = RVPV_DEFAULT, \ - .vect_version = RVVV_DEFAULT, \ - .Zvlsseg = 1, \ - .Zvamo = 1, \ - .Zvediv = 0, \ - .Zvqmac = 1, \ - .PMP_registers = _PMP_REGS, \ - .tval_ii_code = True, \ - .ASID_bits = ((_ARCH)&RV64) ? 16 : 9, \ - .numHarts = RV_NUMHARTS_0 \ + .name = _NAME, \ + .arch = _ARCH, \ + .archMask = RV_ARCH_MASK_DEFAULT, \ + .counteren_mask = -1, \ + .user_version = RVUV_DEFAULT, \ + .priv_version = RVPV_DEFAULT, \ + .vect_version = RVVV_DEFAULT, \ + .Zvlsseg = 1, \ + .Zvamo = 1, \ + .Zvediv = 0, \ + .Zvqmac = 1, \ + .PMP_registers = _PMP_REGS, \ + .tval_ii_code = True, \ + .ASID_bits = ((_ARCH)&RV64) ? 16 : 9, \ + .numHarts = RV_NUMHARTS_0 \ } // diff --git a/source/riscvDebug.c b/source/riscvDebug.c index 4b93ca4..eb5a0f9 100644 --- a/source/riscvDebug.c +++ b/source/riscvDebug.c @@ -154,9 +154,9 @@ static VMI_REG_WRITE_FN(writeDMStall) { // static const isrDetails isRegs[] = { - {"LRSCAddress", "LR/SC active lock address", ISA_A, 0, 0, RISCV_EA_TAG, 0, 0, vmi_RA_RW, 0, 0 }, - {"DM", "Debug mode active", 0, 1, 8, RISCV_DM, 0, writeDM, vmi_RA_RW, 0, RVDM_INTERRUPT}, - {"DMStall", "Debug mode stalled", 0, 1, 8, RISCV_DM_STALL, 0, writeDMStall, vmi_RA_RW, 0, RVDM_HALT }, + {"LRSCAddress", "LR/SC active lock address", ISA_A, 0, 0, RISCV_EA_TAG, 0, 0, vmi_RA_RW, 0, 0 }, + {"DM", "Debug mode active", 0, 1, 8, RISCV_DM, 0, writeDM, vmi_RA_RW, 0, RVDM_VECTOR}, + {"DMStall", "Debug mode stalled", 0, 1, 8, RISCV_DM_STALL, 0, writeDMStall, vmi_RA_RW, 0, RVDM_HALT }, // KEEP LAST {0} @@ -253,8 +253,13 @@ inline static riscvCSRAttrsCP getCSRAttrs(vmiRegInfoCP reg) { static VMI_REG_READ_FN(readCSR) { riscvP riscv = (riscvP)processor; + Bool old = riscv->artifactAccess; - return riscvReadCSR(getCSRAttrs(reg), riscv, buffer); + riscv->artifactAccess = True; + Bool ok = riscvReadCSR(getCSRAttrs(reg), riscv, buffer); + riscv->artifactAccess = old; + + return ok; } // @@ -263,8 +268,13 @@ static VMI_REG_READ_FN(readCSR) { static VMI_REG_WRITE_FN(writeCSR) { riscvP riscv = (riscvP)processor; + Bool old = riscv->artifactAccess; + + riscv->artifactAccess = True; + Bool ok = riscvWriteCSR(getCSRAttrs(reg), riscv, buffer); + riscv->artifactAccess = old; - return riscvWriteCSR(getCSRAttrs(reg), riscv, buffer); + return ok; } // @@ -404,6 +414,7 @@ static vmiRegInfoCP getRegisters(riscvP riscv, Bool normal) { dst->readCB = csrDetails.rdRaw ? 0 : readCSR; dst->writeCB = csrDetails.wrRaw ? 0 : writeCSR; dst->userData = (void *)attrs; + dst->noSaveRestore = attrs->noSaveRestore; dst->noTraceChange = attrs->noTraceChange; dst->extension = csrDetails.extension; dst++; @@ -559,30 +570,12 @@ void riscvFreeRegInfo(riscvP riscv) { #define RISCV_FIELD_IMPL_IGNORE(_FIELD) \ RISCV_FIELD_IMPL_RAW(0, _FIELD) -// -// Ignore register definitions for artifact vector index tables -// -static void offsetRegIgnore(riscvP riscv, riscvStrideOffset *base, Uns32 mul) { - - vmiProcessorP processor = (vmiProcessorP)riscv; - Uns32 vRegBytes = riscv->configInfo.VLEN/8; - - vmirtRegImplRaw( - processor, - 0, - vmimtGetExtReg(processor, base), - vRegBytes*sizeof(*base)*8*mul - ); -} - // // Specify vmiReg-to-vmiRegInfoCP correspondence for registers for which this // cannot be automatically derived // VMI_REG_IMPL_FN(riscvRegImpl) { - riscvP riscv = (riscvP)processor; - // specify that fpFlags is in fflags vmiRegInfoCP fflags = vmirtGetRegByName(processor, "fflags"); RISCV_FIELD_IMPL_RAW(fflags, fpFlagsMT); @@ -595,17 +588,7 @@ VMI_REG_IMPL_FN(riscvRegImpl) { RISCV_FIELD_IMPL_IGNORE(pmKey); RISCV_FIELD_IMPL_IGNORE(vFirstFault); RISCV_FIELD_IMPL_IGNORE(vBase); - RISCV_FIELD_IMPL_IGNORE(offsetsLMULx2); - RISCV_FIELD_IMPL_IGNORE(offsetsLMULx4); - RISCV_FIELD_IMPL_IGNORE(offsetsLMULx8); RISCV_FIELD_IMPL_IGNORE(jumpBase); - - // exclude artifact vector index registers - if(riscv->offsetsLMULx2) { - offsetRegIgnore(riscv, riscv->offsetsLMULx2, 2); - offsetRegIgnore(riscv, riscv->offsetsLMULx4, 4); - offsetRegIgnore(riscv, riscv->offsetsLMULx8, 8); - } } diff --git a/source/riscvDecode.c b/source/riscvDecode.c index 4364d42..e5f0dfb 100644 --- a/source/riscvDecode.c +++ b/source/riscvDecode.c @@ -141,22 +141,22 @@ static riscvArchitecture getXLenArch(riscvP riscv) { #define U_14(_I) UBITS(1, (_I)>>14) #define U_14_12(_I) UBITS(3, (_I)>>12) #define U_17_15(_I) UBITS(3, (_I)>>15) +#define U_17_16(_I) UBITS(2, (_I)>>16) #define U_19_12(_I) UBITS(8, (_I)>>12) #define U_19_15(_I) UBITS(5, (_I)>>15) #define U_20(_I) UBITS(1, (_I)>>20) #define U_21(_I) UBITS(1, (_I)>>21) -#define U_21_20(_I) UBITS(2, (_I)>>20) #define U_23_20(_I) UBITS(4, (_I)>>20) #define U_23(_I) UBITS(1, (_I)>>23) #define U_24(_I) UBITS(1, (_I)>>24) #define U_24_20(_I) UBITS(5, (_I)>>20) -#define U_24_22(_I) UBITS(3, (_I)>>22) #define U_25(_I) UBITS(1, (_I)>>25) #define U_25_20(_I) UBITS(6, (_I)>>20) #define U_26(_I) UBITS(1, (_I)>>26) #define U_26_25(_I) UBITS(2, (_I)>>25) #define U_27_24(_I) UBITS(4, (_I)>>24) #define U_28(_I) UBITS(1, (_I)>>28) +#define U_30_20(_I) UBITS(11,(_I)>>20) #define U_30_21(_I) UBITS(10,(_I)>>21) #define U_30_25(_I) UBITS(6, (_I)>>25) #define U_31_20(_I) UBITS(12,(_I)>>20) @@ -201,6 +201,23 @@ typedef enum fenceSpecE { FENCES_27_24, // fence specification in bits 27:24 } fenceSpec; +// +// Define the encoding of EEW in an instruction +// +typedef enum eewSpecE { + EEW_NA, // instruction has no EEW + EEW_14_12, // EEW in bits 14:12 (vector instructions) + EEW_28_14_12, // EEW in bits 28,14:12 (vector instructions) +} eewSpec; + +// +// Define the encoding of an EEW divisor in an instruction +// +typedef enum eewDivSpecE { + EEWD_NA, // instruction has no EEW divisor + EEWD_17_16, // EEW divisor in bits 17:16 +} eewDivSpec; + // // Define the encoding of memory bit size in an instruction // @@ -210,6 +227,8 @@ typedef enum memBitsSpecE { MBS_12_VAMO, // memory bit size in bit 12 (vector AMO instructions) MBS_13_12, // memory bit size in bits 13:12 MBS_14_12_V, // memory bit size in bits 14:12 (vector instructions) + MBS_EEW, // memory bit size in bits 28,14:12 (vector instructions) + MBS_SEW, // memory bit size of SEW (vector instructions) MBS_W, // memory bit size 32 (word) MBS_D, // memory bit size 64 (double) } memBitsSpec; @@ -320,25 +339,18 @@ typedef enum aqrlSpecE { // typedef enum rmSpecE { RM_NA, // no rounding mode (or current mode) + RM_RTZ, // round to zero RM_ROD, // round to odd RM_14_12, // rounding mode in bits 14:12 } rmSpec; // -// Define the encoding of vector vsew specifier in an instruction +// Define the encoding of vector type specifier in an instruction // -typedef enum vsewSpecE { - VSEW_NA, // no vsew - VSEW_24_22, // vsew in bits 24:22 -} vsewSpec; - -// -// Define the encoding of vector vlmul specifier in an instruction -// -typedef enum vlmulSpecE { - VLMUL_NA, // no vlmul - VLMUL_21_20, // vlmul in bits 21:20 -} vlmulSpec; +typedef enum vtypeSpecE { + VTYPE_NA, // no vtype + VTYPE_30_20, // vtype in bits 30:20 +} vtypeSpec; // // Define the encoding of vector vlmul specifier in an instruction @@ -387,16 +399,17 @@ typedef struct opAttrsS { wfSpec wF : 4; // F register width specification fenceSpec pred : 4; // predecessor fence specification fenceSpec succ : 4; // successor fence specification + eewSpec eew : 4; // EEW specification memBitsSpec memBits : 4; // load/store size specification unsExtSpec unsExt : 4; // unsigned extend specification Uns32 priDelta : 4; // decode priority delta rmSpec rm : 4; // rounding mode specification numFieldsSpec nf : 4; // nf specification wholeSpec whole : 4; // whole register specification + vtypeSpec vtype : 4; // vtype specification aqrlSpec aqrl : 1; // acquire/release specification - vsewSpec vsew : 1; // vsew specification - vlmulSpec vlmul : 1; // vlmul specification firstFaultSpec ff : 1; // first fault specification + eewDivSpec eewDiv : 1; // EEW divisor specification Bool csrInOp : 1; // whether to emit CSR as part of opcode Bool xQuiet : 1; // are X registers type-quiet? } opAttrs; @@ -597,43 +610,25 @@ typedef enum riscvIType32E { // V-extension I-type instructions IT32_VSETVL_I, - // V-extension load/store instructions (byte elements) - IT32_VLB_I, - IT32_VLSB_I, - IT32_VLXB_I, - IT32_VSB_I, - IT32_VSSB_I, - IT32_VSXB_I, - IT32_VSUXB_I, + // V-extension load/store instructions (pre-0.9) + IT32_VL_I, + IT32_VLS_I, + IT32_VLX_I, + IT32_VS_I, + IT32_VSS_I, + IT32_VSX_I, + IT32_VSUX_I, - // V-extension load/store instructions (halfword elements) - IT32_VLH_I, - IT32_VLSH_I, - IT32_VLXH_I, - IT32_VSH_I, - IT32_VSSH_I, - IT32_VSXH_I, - IT32_VSUXH_I, - - // V-extension load/store instructions (word elements) - IT32_VLW_I, - IT32_VLSW_I, - IT32_VLXW_I, - IT32_VSW_I, - IT32_VSSW_I, - IT32_VSXW_I, - IT32_VSUXW_I, - - // V-extension load/store instructions (SEW elements) + // V-extension load/store instructions (0.9 and later) IT32_VLE_I, IT32_VLSE_I, - IT32_VLXE_I, + IT32_VLXEI_I, IT32_VSE_I, IT32_VSSE_I, - IT32_VSXE_I, - IT32_VSUXE_I, + IT32_VSXEI_I, + IT32_VSUXEI_I, - // V-extension AMO operations (Zvamo) + // V-extension AMO operations (Zvamo, pre-0.9) IT32_VAMOADD_R, IT32_VAMOAND_R, IT32_VAMOMAX_R, @@ -644,6 +639,17 @@ typedef enum riscvIType32E { IT32_VAMOSWAP_R, IT32_VAMOXOR_R, + // V-extension AMO operations (Zvamo, 0.9 and later) + IT32_VAMOADDEI_R, + IT32_VAMOANDEI_R, + IT32_VAMOMAXEI_R, + IT32_VAMOMAXUEI_R, + IT32_VAMOMINEI_R, + IT32_VAMOMINUEI_R, + IT32_VAMOOREI_R, + IT32_VAMOSWAPEI_R, + IT32_VAMOXOREI_R, + // V-extension IVV-type instructions IT32_VADD_VV, IT32_VSUB_VV, @@ -713,16 +719,22 @@ typedef enum riscvIType32E { IT32_VFNE_VV, IT32_VFDIV_VV, IT32_VFCVT_XUF_V, + IT32_VFCVTRTZ_XUF_V, IT32_VFCVT_XF_V, + IT32_VFCVTRTZ_XF_V, IT32_VFCVT_FXU_V, IT32_VFCVT_FX_V, IT32_VFWCVT_XUF_V, + IT32_VFWCVTRTZ_XUF_V, IT32_VFWCVT_XF_V, + IT32_VFWCVTRTZ_XF_V, IT32_VFWCVT_FXU_V, IT32_VFWCVT_FX_V, IT32_VFWCVT_FF_V, IT32_VFNCVT_XUF_V, + IT32_VFNCVTRTZ_XUF_V, IT32_VFNCVT_XF_V, + IT32_VFNCVTRTZ_XF_V, IT32_VFNCVT_FXU_V, IT32_VFNCVT_FX_V, IT32_VFNCVT_FF_V, @@ -900,6 +912,8 @@ typedef enum riscvIType32E { IT32_VFSGNJ_VF, IT32_VFSGNJN_VF, IT32_VFSGNJX_VF, + IT32_VFSLIDE1UP_VF, + IT32_VFSLIDE1DOWN_VF, IT32_VFMV_S_F, IT32_VFMERGE_VF, IT32_VFMV_V_F, @@ -936,6 +950,8 @@ typedef enum riscvIType32E { IT32_VMV_S_X, IT32_VSLIDE1UP_VX, IT32_VSLIDE1DOWN_VX, + IT32_VZEXT_V, + IT32_VSEXT_V, IT32_VDIVU_VX, IT32_VDIV_VX, IT32_VREMU_VX, @@ -1200,60 +1216,8 @@ const static decodeEntry32 decodeCommon32[] = { DECODE32_ENTRY( VSETVL_R, "|1000000|.....|.....|111|.....|1010111|"), // V-extension I-type - // | imm32| rs1|fun| rd| opcode| - DECODE32_ENTRY( VSETVL_I, "|0000000.....|.....|111|.....|1010111|"), - - // V-extension load/store instructions (byte elements) - // | nf|mop|m| xs2| rs1|wth| vs3| opcode| - DECODE32_ENTRY( VLB_I, "|...|.00|.|.0000|.....|000|.....|0000111|"), - DECODE32_ENTRY( VLSB_I, "|...|.10|.|.....|.....|000|.....|0000111|"), - DECODE32_ENTRY( VLXB_I, "|...|.11|.|.....|.....|000|.....|0000111|"), - DECODE32_ENTRY( VSB_I, "|...|000|.|00000|.....|000|.....|0100111|"), - DECODE32_ENTRY( VSSB_I, "|...|010|.|.....|.....|000|.....|0100111|"), - DECODE32_ENTRY( VSXB_I, "|...|011|.|.....|.....|000|.....|0100111|"), - DECODE32_ENTRY( VSUXB_I, "|...|111|.|.....|.....|000|.....|0100111|"), - - // V-extension load/store instructions (halfword elements) - // | nf|mop|m| xs2| rs1|wth| vs3| opcode| - DECODE32_ENTRY( VLH_I, "|...|.00|.|.0000|.....|101|.....|0000111|"), - DECODE32_ENTRY( VLSH_I, "|...|.10|.|.....|.....|101|.....|0000111|"), - DECODE32_ENTRY( VLXH_I, "|...|.11|.|.....|.....|101|.....|0000111|"), - DECODE32_ENTRY( VSH_I, "|...|000|.|00000|.....|101|.....|0100111|"), - DECODE32_ENTRY( VSSH_I, "|...|010|.|.....|.....|101|.....|0100111|"), - DECODE32_ENTRY( VSXH_I, "|...|011|.|.....|.....|101|.....|0100111|"), - DECODE32_ENTRY( VSUXH_I, "|...|111|.|.....|.....|101|.....|0100111|"), - - // V-extension load/store instructions (word elements) - // | nf|mop|m| xs2| rs1|wth| vs3| opcode| - DECODE32_ENTRY( VLW_I, "|...|.00|.|.0000|.....|110|.....|0000111|"), - DECODE32_ENTRY( VLSW_I, "|...|.10|.|.....|.....|110|.....|0000111|"), - DECODE32_ENTRY( VLXW_I, "|...|.11|.|.....|.....|110|.....|0000111|"), - DECODE32_ENTRY( VSW_I, "|...|000|.|00000|.....|110|.....|0100111|"), - DECODE32_ENTRY( VSSW_I, "|...|010|.|.....|.....|110|.....|0100111|"), - DECODE32_ENTRY( VSXW_I, "|...|011|.|.....|.....|110|.....|0100111|"), - DECODE32_ENTRY( VSUXW_I, "|...|111|.|.....|.....|110|.....|0100111|"), - - // V-extension load/store instructions (SEW elements) - // | nf|mop|m| xs2| rs1|wth| vs3| opcode| - DECODE32_ENTRY( VLE_I, "|...|000|.|.0000|.....|111|.....|0000111|"), - DECODE32_ENTRY( VLSE_I, "|...|010|.|.....|.....|111|.....|0000111|"), - DECODE32_ENTRY( VLXE_I, "|...|011|.|.....|.....|111|.....|0000111|"), - DECODE32_ENTRY( VSE_I, "|...|000|.|00000|.....|111|.....|0100111|"), - DECODE32_ENTRY( VSSE_I, "|...|010|.|.....|.....|111|.....|0100111|"), - DECODE32_ENTRY( VSXE_I, "|...|011|.|.....|.....|111|.....|0100111|"), - DECODE32_ENTRY( VSUXE_I, "|...|111|.|.....|.....|111|.....|0100111|"), - - // V-extension AMO operations (Zvamo) - // | funct7| rs2| rs1|fun| rd| opcode| - DECODE32_ENTRY( VAMOADD_R, "|00000..|.....|.....|11.|.....|0101111|"), - DECODE32_ENTRY( VAMOAND_R, "|01100..|.....|.....|11.|.....|0101111|"), - DECODE32_ENTRY( VAMOMAX_R, "|10100..|.....|.....|11.|.....|0101111|"), - DECODE32_ENTRY( VAMOMAXU_R, "|11100..|.....|.....|11.|.....|0101111|"), - DECODE32_ENTRY( VAMOMIN_R, "|10000..|.....|.....|11.|.....|0101111|"), - DECODE32_ENTRY( VAMOMINU_R, "|11000..|.....|.....|11.|.....|0101111|"), - DECODE32_ENTRY( VAMOOR_R, "|01000..|.....|.....|11.|.....|0101111|"), - DECODE32_ENTRY( VAMOSWAP_R, "|00001..|.....|.....|11.|.....|0101111|"), - DECODE32_ENTRY( VAMOXOR_R, "|00100..|.....|.....|11.|.....|0101111|"), + // | imm32| rs1|fun| rd| opcode| + DECODE32_ENTRY( VSETVL_I, "|0......|.....|.....|111|.....|1010111|"), // V-extension IVV-type instructions // |funct6|m| vs2| vs1|IVV| vs3| opcode| @@ -1682,11 +1646,6 @@ const static decodeEntry32 decode20191004[] = { // const static decodeEntry32 decodePost20191004[] = { - // V-extension load/store instructions (whole registers) - // | nf|mop|m| xs2| rs1|wth| vs3| opcode| - DECODE32_ENTRY( VLE_I, "|...|000|1|01000|.....|111|.....|0000111|"), - DECODE32_ENTRY( VSE_I, "|...|000|1|01000|.....|111|.....|0100111|"), - // V-extension IVV-type instructions // |funct6|m| vs2| vs1|IVV| vs3| opcode| DECODE32_ENTRY( VADC_VV, "|010000|0|.....|.....|000|.....|1010111|"), @@ -1770,18 +1729,198 @@ const static decodeEntry32 decodePre20191004[] = { }; // -// This specifies decodes *after* 17 November 2019 +// This specifies decodes specific to late 0.8 versions // -const static decodeEntry32 decodePost20191117[] = { +const static decodeEntry32 decodeLate08[] = { + + // V-extension load/store instructions (whole registers) + // | nf|mop|m| xs2| rs1|wth| vs3| opcode| + DECODE32_ENTRY( VL_I, "|...|000|1|01000|.....|111|.....|0000111|"), + DECODE32_ENTRY( VS_I, "|...|000|1|01000|.....|111|.....|0100111|"), // table termination entry {0} }; // -// This specifies decodes *before* 17 November 2019 +// This specifies decodes *before* release 0.9 // -const static decodeEntry32 decodePre20191117[] = { +const static decodeEntry32 decodePre09[] = { + + // V-extension load/store instructions (byte elements) + // | nf|mop|m| xs2| rs1|wth| vs3| opcode| + DECODE32_ENTRY( VL_I, "|...|.00|.|.0000|.....|000|.....|0000111|"), + DECODE32_ENTRY( VLS_I, "|...|.10|.|.....|.....|000|.....|0000111|"), + DECODE32_ENTRY( VLX_I, "|...|.11|.|.....|.....|000|.....|0000111|"), + DECODE32_ENTRY( VS_I, "|...|000|.|00000|.....|000|.....|0100111|"), + DECODE32_ENTRY( VSS_I, "|...|010|.|.....|.....|000|.....|0100111|"), + DECODE32_ENTRY( VSX_I, "|...|011|.|.....|.....|000|.....|0100111|"), + DECODE32_ENTRY( VSUX_I, "|...|111|.|.....|.....|000|.....|0100111|"), + + // V-extension load/store instructions (halfword elements) + // | nf|mop|m| xs2| rs1|wth| vs3| opcode| + DECODE32_ENTRY( VL_I, "|...|.00|.|.0000|.....|101|.....|0000111|"), + DECODE32_ENTRY( VLS_I, "|...|.10|.|.....|.....|101|.....|0000111|"), + DECODE32_ENTRY( VLX_I, "|...|.11|.|.....|.....|101|.....|0000111|"), + DECODE32_ENTRY( VS_I, "|...|000|.|00000|.....|101|.....|0100111|"), + DECODE32_ENTRY( VSS_I, "|...|010|.|.....|.....|101|.....|0100111|"), + DECODE32_ENTRY( VSX_I, "|...|011|.|.....|.....|101|.....|0100111|"), + DECODE32_ENTRY( VSUX_I, "|...|111|.|.....|.....|101|.....|0100111|"), + + // V-extension load/store instructions (word elements) + // | nf|mop|m| xs2| rs1|wth| vs3| opcode| + DECODE32_ENTRY( VL_I, "|...|.00|.|.0000|.....|110|.....|0000111|"), + DECODE32_ENTRY( VLS_I, "|...|.10|.|.....|.....|110|.....|0000111|"), + DECODE32_ENTRY( VLX_I, "|...|.11|.|.....|.....|110|.....|0000111|"), + DECODE32_ENTRY( VS_I, "|...|000|.|00000|.....|110|.....|0100111|"), + DECODE32_ENTRY( VSS_I, "|...|010|.|.....|.....|110|.....|0100111|"), + DECODE32_ENTRY( VSX_I, "|...|011|.|.....|.....|110|.....|0100111|"), + DECODE32_ENTRY( VSUX_I, "|...|111|.|.....|.....|110|.....|0100111|"), + + // V-extension load/store instructions (SEW elements) + // | nf|mop|m| xs2| rs1|wth| vs3| opcode| + DECODE32_ENTRY( VL_I, "|...|000|.|.0000|.....|111|.....|0000111|"), + DECODE32_ENTRY( VLS_I, "|...|010|.|.....|.....|111|.....|0000111|"), + DECODE32_ENTRY( VLX_I, "|...|011|.|.....|.....|111|.....|0000111|"), + DECODE32_ENTRY( VS_I, "|...|000|.|00000|.....|111|.....|0100111|"), + DECODE32_ENTRY( VSS_I, "|...|010|.|.....|.....|111|.....|0100111|"), + DECODE32_ENTRY( VSX_I, "|...|011|.|.....|.....|111|.....|0100111|"), + DECODE32_ENTRY( VSUX_I, "|...|111|.|.....|.....|111|.....|0100111|"), + + // V-extension AMO operations (Zvamo) + // | funct7| rs2| rs1|fun| rd| opcode| + DECODE32_ENTRY( VAMOADD_R, "|00000..|.....|.....|11.|.....|0101111|"), + DECODE32_ENTRY( VAMOAND_R, "|01100..|.....|.....|11.|.....|0101111|"), + DECODE32_ENTRY( VAMOMAX_R, "|10100..|.....|.....|11.|.....|0101111|"), + DECODE32_ENTRY( VAMOMAXU_R, "|11100..|.....|.....|11.|.....|0101111|"), + DECODE32_ENTRY( VAMOMIN_R, "|10000..|.....|.....|11.|.....|0101111|"), + DECODE32_ENTRY( VAMOMINU_R, "|11000..|.....|.....|11.|.....|0101111|"), + DECODE32_ENTRY( VAMOOR_R, "|01000..|.....|.....|11.|.....|0101111|"), + DECODE32_ENTRY( VAMOSWAP_R, "|00001..|.....|.....|11.|.....|0101111|"), + DECODE32_ENTRY( VAMOXOR_R, "|00100..|.....|.....|11.|.....|0101111|"), + + // table termination entry + {0} +}; + +// +// This specifies decodes *after* release 0.8 +// +const static decodeEntry32 decodeInitial09[] = { + + // V-extension load/store instructions (whole registers) + // | nf|mop|m| xs2| rs1|wth| vs3| opcode| + DECODE32_ENTRY( VLE_I, "|...|000|1|01000|.....|000|.....|0000111|"), + DECODE32_ENTRY( VSE_I, "|...|000|1|01000|.....|000|.....|0100111|"), + + // V-extension load/store instructions (8/128-bit elements) + // | nf|mop|m| xs2| rs1|wth| vs3| opcode| + DECODE32_ENTRY( VLE_I, "|...|.00|.|.0000|.....|000|.....|0000111|"), + DECODE32_ENTRY( VLSE_I, "|...|.10|.|.....|.....|000|.....|0000111|"), + DECODE32_ENTRY( VLXEI_I, "|...|.11|.|.....|.....|000|.....|0000111|"), + DECODE32_ENTRY( VSE_I, "|...|.00|.|00000|.....|000|.....|0100111|"), + DECODE32_ENTRY( VSSE_I, "|...|.10|.|.....|.....|000|.....|0100111|"), + DECODE32_ENTRY( VSXEI_I, "|...|.11|.|.....|.....|000|.....|0100111|"), + DECODE32_ENTRY( VSUXEI_I, "|...|.01|.|.....|.....|000|.....|0100111|"), + + // V-extension load/store instructions (16/256-bit elements) + // | nf|mop|m| xs2| rs1|wth| vs3| opcode| + DECODE32_ENTRY( VLE_I, "|...|.00|.|.0000|.....|101|.....|0000111|"), + DECODE32_ENTRY( VLSE_I, "|...|.10|.|.....|.....|101|.....|0000111|"), + DECODE32_ENTRY( VLXEI_I, "|...|.11|.|.....|.....|101|.....|0000111|"), + DECODE32_ENTRY( VSE_I, "|...|.00|.|00000|.....|101|.....|0100111|"), + DECODE32_ENTRY( VSSE_I, "|...|.10|.|.....|.....|101|.....|0100111|"), + DECODE32_ENTRY( VSXEI_I, "|...|.11|.|.....|.....|101|.....|0100111|"), + DECODE32_ENTRY( VSUXEI_I, "|...|.01|.|.....|.....|101|.....|0100111|"), + + // V-extension load/store instructions (32/512-bit elements) + // | nf|mop|m| xs2| rs1|wth| vs3| opcode| + DECODE32_ENTRY( VLE_I, "|...|.00|.|.0000|.....|110|.....|0000111|"), + DECODE32_ENTRY( VLSE_I, "|...|.10|.|.....|.....|110|.....|0000111|"), + DECODE32_ENTRY( VLXEI_I, "|...|.11|.|.....|.....|110|.....|0000111|"), + DECODE32_ENTRY( VSE_I, "|...|.00|.|00000|.....|110|.....|0100111|"), + DECODE32_ENTRY( VSSE_I, "|...|.10|.|.....|.....|110|.....|0100111|"), + DECODE32_ENTRY( VSXEI_I, "|...|.11|.|.....|.....|110|.....|0100111|"), + DECODE32_ENTRY( VSUXEI_I, "|...|.01|.|.....|.....|110|.....|0100111|"), + + // V-extension load/store instructions (64/1024-bit elements) + // | nf|mop|m| xs2| rs1|wth| vs3| opcode| + DECODE32_ENTRY( VLE_I, "|...|.00|.|.0000|.....|111|.....|0000111|"), + DECODE32_ENTRY( VLSE_I, "|...|.10|.|.....|.....|111|.....|0000111|"), + DECODE32_ENTRY( VLXEI_I, "|...|.11|.|.....|.....|111|.....|0000111|"), + DECODE32_ENTRY( VSE_I, "|...|.00|.|00000|.....|111|.....|0100111|"), + DECODE32_ENTRY( VSSE_I, "|...|.10|.|.....|.....|111|.....|0100111|"), + DECODE32_ENTRY( VSXEI_I, "|...|.11|.|.....|.....|111|.....|0100111|"), + DECODE32_ENTRY( VSUXEI_I, "|...|.01|.|.....|.....|111|.....|0100111|"), + + // V-extension AMO operations (8-bit elements, Zvamo) + // |amoop|dm| xs2| rs1|wth| vs3| opcode| + DECODE32_ENTRY( VAMOADDEI_R, "|00000|..|.....|.....|000|.....|0101111|"), + DECODE32_ENTRY( VAMOANDEI_R, "|01100|..|.....|.....|000|.....|0101111|"), + DECODE32_ENTRY( VAMOMAXEI_R, "|10100|..|.....|.....|000|.....|0101111|"), + DECODE32_ENTRY( VAMOMAXUEI_R, "|11100|..|.....|.....|000|.....|0101111|"), + DECODE32_ENTRY( VAMOMINEI_R, "|10000|..|.....|.....|000|.....|0101111|"), + DECODE32_ENTRY( VAMOMINUEI_R, "|11000|..|.....|.....|000|.....|0101111|"), + DECODE32_ENTRY( VAMOOREI_R, "|01000|..|.....|.....|000|.....|0101111|"), + DECODE32_ENTRY( VAMOSWAPEI_R, "|00001|..|.....|.....|000|.....|0101111|"), + DECODE32_ENTRY( VAMOXOREI_R, "|00100|..|.....|.....|000|.....|0101111|"), + + // V-extension AMO operations (16-bit elements, Zvamo) + // |amoop|dm| xs2| rs1|wth| vs3| opcode| + DECODE32_ENTRY( VAMOADDEI_R, "|00000|..|.....|.....|101|.....|0101111|"), + DECODE32_ENTRY( VAMOANDEI_R, "|01100|..|.....|.....|101|.....|0101111|"), + DECODE32_ENTRY( VAMOMAXEI_R, "|10100|..|.....|.....|101|.....|0101111|"), + DECODE32_ENTRY( VAMOMAXUEI_R, "|11100|..|.....|.....|101|.....|0101111|"), + DECODE32_ENTRY( VAMOMINEI_R, "|10000|..|.....|.....|101|.....|0101111|"), + DECODE32_ENTRY( VAMOMINUEI_R, "|11000|..|.....|.....|101|.....|0101111|"), + DECODE32_ENTRY( VAMOOREI_R, "|01000|..|.....|.....|101|.....|0101111|"), + DECODE32_ENTRY( VAMOSWAPEI_R, "|00001|..|.....|.....|101|.....|0101111|"), + DECODE32_ENTRY( VAMOXOREI_R, "|00100|..|.....|.....|101|.....|0101111|"), + + // V-extension AMO operations (32-bit elements, Zvamo) + // |amoop|dm| xs2| rs1|wth| vs3| opcode| + DECODE32_ENTRY( VAMOADDEI_R, "|00000|..|.....|.....|110|.....|0101111|"), + DECODE32_ENTRY( VAMOANDEI_R, "|01100|..|.....|.....|110|.....|0101111|"), + DECODE32_ENTRY( VAMOMAXEI_R, "|10100|..|.....|.....|110|.....|0101111|"), + DECODE32_ENTRY( VAMOMAXUEI_R, "|11100|..|.....|.....|110|.....|0101111|"), + DECODE32_ENTRY( VAMOMINEI_R, "|10000|..|.....|.....|110|.....|0101111|"), + DECODE32_ENTRY( VAMOMINUEI_R, "|11000|..|.....|.....|110|.....|0101111|"), + DECODE32_ENTRY( VAMOOREI_R, "|01000|..|.....|.....|110|.....|0101111|"), + DECODE32_ENTRY( VAMOSWAPEI_R, "|00001|..|.....|.....|110|.....|0101111|"), + DECODE32_ENTRY( VAMOXOREI_R, "|00100|..|.....|.....|110|.....|0101111|"), + + // V-extension AMO operations (64-bit elements, Zvamo) + // |amoop|dm| xs2| rs1|wth| vs3| opcode| + DECODE32_ENTRY( VAMOADDEI_R, "|00000|..|.....|.....|111|.....|0101111|"), + DECODE32_ENTRY( VAMOANDEI_R, "|01100|..|.....|.....|111|.....|0101111|"), + DECODE32_ENTRY( VAMOMAXEI_R, "|10100|..|.....|.....|111|.....|0101111|"), + DECODE32_ENTRY( VAMOMAXUEI_R, "|11100|..|.....|.....|111|.....|0101111|"), + DECODE32_ENTRY( VAMOMINEI_R, "|10000|..|.....|.....|111|.....|0101111|"), + DECODE32_ENTRY( VAMOMINUEI_R, "|11000|..|.....|.....|111|.....|0101111|"), + DECODE32_ENTRY( VAMOOREI_R, "|01000|..|.....|.....|111|.....|0101111|"), + DECODE32_ENTRY( VAMOSWAPEI_R, "|00001|..|.....|.....|111|.....|0101111|"), + DECODE32_ENTRY( VAMOXOREI_R, "|00100|..|.....|.....|111|.....|0101111|"), + + // V-extension FVV-type instructions + // |funct6|m| vs2| vs1|FVV| vs3| opcode| + DECODE32_ENTRY( VFCVTRTZ_XUF_V, "|100010|.|.....|00110|001|.....|1010111|"), + DECODE32_ENTRY( VFCVTRTZ_XF_V, "|100010|.|.....|00111|001|.....|1010111|"), + DECODE32_ENTRY(VFWCVTRTZ_XUF_V, "|100010|.|.....|01110|001|.....|1010111|"), + DECODE32_ENTRY( VFWCVTRTZ_XF_V, "|100010|.|.....|01111|001|.....|1010111|"), + DECODE32_ENTRY(VFNCVTRTZ_XUF_V, "|100010|.|.....|10110|001|.....|1010111|"), + DECODE32_ENTRY( VFNCVTRTZ_XF_V, "|100010|.|.....|10111|001|.....|1010111|"), + + // V-extension FVF-type instructions + // |funct6|m| vs2| fs1|FVF| vs3| opcode| + DECODE32_ENTRY( VFSLIDE1UP_VF, "|001110|.|.....|.....|101|.....|1010111|"), + DECODE32_ENTRY(VFSLIDE1DOWN_VF, "|001111|.|.....|.....|101|.....|1010111|"), + + // V-extension MVX-type instructions + // |funct6|m| vs2| vs1|MVX| vs3| opcode| + DECODE32_ENTRY( VZEXT_V, "|010010|.|.....|00010|110|.....|1010111|"), + DECODE32_ENTRY( VZEXT_V, "|010010|.|.....|001.0|110|.....|1010111|"), + DECODE32_ENTRY( VSEXT_V, "|010010|.|.....|00011|110|.....|1010111|"), + DECODE32_ENTRY( VSEXT_V, "|010010|.|.....|001.1|110|.....|1010111|"), // table termination entry {0} @@ -1793,562 +1932,566 @@ const static decodeEntry32 decodePre20191117[] = { const static opAttrs attrsArray32[] = { // base R-type - ATTR32_ADD ( ADD_R, ADD_R, RVANY, "add" ), - ATTR32_ADD ( AND_R, AND_R, RVANY, "and" ), - ATTR32_NEG ( NEG_R, SUB_R, RVANY, "neg" ), - ATTR32_ADD ( OR_R, OR_R, RVANY, "or" ), - ATTR32_NEG ( SGTZ_R, SLT_R, RVANY, "sgtz"), - ATTR32_ADD ( SLL_R, SLL_R, RVANY, "sll" ), - ATTR32_ADD ( SLT_R, SLT_R, RVANY, "slt" ), - ATTR32_ADD ( SLTU_R, SLTU_R, RVANY, "sltu"), - ATTR32_SLTZ ( SLTZ_R, SLT_R, RVANY, "sltz"), - ATTR32_NEG ( SNEZ_R, SLTU_R, RVANY, "snez"), - ATTR32_ADD ( SRA_R, SRA_R, RVANY, "sra" ), - ATTR32_ADD ( SRL_R, SRL_R, RVANY, "srl" ), - ATTR32_ADD ( SUB_R, SUB_R, RVANY, "sub" ), - ATTR32_ADD ( XOR_R, XOR_R, RVANY, "xor" ), + ATTR32_ADD ( ADD_R, ADD_R, RVANY, "add" ), + ATTR32_ADD ( AND_R, AND_R, RVANY, "and" ), + ATTR32_NEG ( NEG_R, SUB_R, RVANY, "neg" ), + ATTR32_ADD ( OR_R, OR_R, RVANY, "or" ), + ATTR32_NEG ( SGTZ_R, SLT_R, RVANY, "sgtz"), + ATTR32_ADD ( SLL_R, SLL_R, RVANY, "sll" ), + ATTR32_ADD ( SLT_R, SLT_R, RVANY, "slt" ), + ATTR32_ADD ( SLTU_R, SLTU_R, RVANY, "sltu"), + ATTR32_SLTZ ( SLTZ_R, SLT_R, RVANY, "sltz"), + ATTR32_NEG ( SNEZ_R, SLTU_R, RVANY, "snez"), + ATTR32_ADD ( SRA_R, SRA_R, RVANY, "sra" ), + ATTR32_ADD ( SRL_R, SRL_R, RVANY, "srl" ), + ATTR32_ADD ( SUB_R, SUB_R, RVANY, "sub" ), + ATTR32_ADD ( XOR_R, XOR_R, RVANY, "xor" ), // M-extension R-type - ATTR32_ADD ( DIV_R, DIV_R, RVANYM, "div" ), - ATTR32_ADD ( DIVU_R, DIVU_R, RVANYM, "divu" ), - ATTR32_ADD ( MUL_R, MUL_R, RVANYM, "mul" ), - ATTR32_ADD ( MULH_R, MULH_R, RVANYM, "mulh" ), - ATTR32_ADD ( MULHSU_R, MULHSU_R, RVANYM, "mulhsu"), - ATTR32_ADD ( MULHU_R, MULHU_R, RVANYM, "mulhu" ), - ATTR32_ADD ( REM_R, REM_R, RVANYM, "rem" ), - ATTR32_ADD ( REMU_R, REMU_R, RVANYM, "remu" ), + ATTR32_ADD ( DIV_R, DIV_R, RVANYM, "div" ), + ATTR32_ADD ( DIVU_R, DIVU_R, RVANYM, "divu" ), + ATTR32_ADD ( MUL_R, MUL_R, RVANYM, "mul" ), + ATTR32_ADD ( MULH_R, MULH_R, RVANYM, "mulh" ), + ATTR32_ADD ( MULHSU_R, MULHSU_R, RVANYM, "mulhsu"), + ATTR32_ADD ( MULHU_R, MULHU_R, RVANYM, "mulhu" ), + ATTR32_ADD ( REM_R, REM_R, RVANYM, "rem" ), + ATTR32_ADD ( REMU_R, REMU_R, RVANYM, "remu" ), // base I-type - ATTR32_ADDI ( ADDI_I, ADDI_I, RVANY, "addi" ), - ATTR32_ADDI ( ANDI_I, ANDI_I, RVANY, "andi" ), - ATTR32_JR ( JR_I, JALR_I, RVANY, "jr" ), - ATTR32_JR0 ( JR0_I, JALR_I, RVANY, "jr" ), - ATTR32_JALR ( JALR_I, JALR_I, RVANY, "jalr" ), - ATTR32_NOT ( JALR0_I, JALR_I, RVANY, "jalr" ), - ATTR32_NOT ( MV_I, MV_R, RVANY, "mv" ), - ATTR32_NOPI ( NOP_I, ADDI_I, RVANY, "nop" ), - ATTR32_NOT ( NOT_I, XORI_I, RVANY, "not" ), - ATTR32_ADDI ( ORI_I, ORI_I, RVANY, "ori" ), - ATTR32_NOPI ( RET_I, JALR_I, RVANY, "ret" ), - ATTR32_NOT ( SEQZ_I, SLTIU_I, RVANY, "seqz" ), - ATTR32_NOT ( SEXTW_I, ADDI_I, RVANY, "sext."), - ATTR32_SLLI ( SLLI_I, SLLI_I, RVANY, "slli" ), - ATTR32_ADDI ( SLTI_I, SLTI_I, RVANY, "slti" ), - ATTR32_ADDI ( SLTIU_I, SLTIU_I, RVANY, "sltiu"), - ATTR32_SLLI ( SRAI_I, SRAI_I, RVANY, "srai" ), - ATTR32_SLLI ( SRLI_I, SRLI_I, RVANY, "srli" ), - ATTR32_ADDI ( XORI_I, XORI_I, RVANY, "xori" ), + ATTR32_ADDI ( ADDI_I, ADDI_I, RVANY, "addi" ), + ATTR32_ADDI ( ANDI_I, ANDI_I, RVANY, "andi" ), + ATTR32_JR ( JR_I, JALR_I, RVANY, "jr" ), + ATTR32_JR0 ( JR0_I, JALR_I, RVANY, "jr" ), + ATTR32_JALR ( JALR_I, JALR_I, RVANY, "jalr" ), + ATTR32_NOT ( JALR0_I, JALR_I, RVANY, "jalr" ), + ATTR32_NOT ( MV_I, MV_R, RVANY, "mv" ), + ATTR32_NOPI ( NOP_I, ADDI_I, RVANY, "nop" ), + ATTR32_NOT ( NOT_I, XORI_I, RVANY, "not" ), + ATTR32_ADDI ( ORI_I, ORI_I, RVANY, "ori" ), + ATTR32_NOPI ( RET_I, JALR_I, RVANY, "ret" ), + ATTR32_NOT ( SEQZ_I, SLTIU_I, RVANY, "seqz" ), + ATTR32_NOT ( SEXTW_I, ADDI_I, RVANY, "sext."), + ATTR32_SLLI ( SLLI_I, SLLI_I, RVANY, "slli" ), + ATTR32_ADDI ( SLTI_I, SLTI_I, RVANY, "slti" ), + ATTR32_ADDI ( SLTIU_I, SLTIU_I, RVANY, "sltiu"), + ATTR32_SLLI ( SRAI_I, SRAI_I, RVANY, "srai" ), + ATTR32_SLLI ( SRLI_I, SRLI_I, RVANY, "srli" ), + ATTR32_ADDI ( XORI_I, XORI_I, RVANY, "xori" ), // base I-type instructions for load - ATTR32_LB ( LB_I, L_I, RVANY, "l"), - ATTR32_LB ( LBU_I, L_I, RVANY, "l"), - ATTR32_LB ( LH_I, L_I, RVANY, "l"), - ATTR32_LB ( LHU_I, L_I, RVANY, "l"), - ATTR32_LB ( LW_I, L_I, RVANY, "l"), - ATTR32_LB ( LWU_I, L_I, RV64, "l"), - ATTR32_LB ( LD_I, L_I, RV64, "l"), + ATTR32_LB ( LB_I, L_I, RVANY, "l"), + ATTR32_LB ( LBU_I, L_I, RVANY, "l"), + ATTR32_LB ( LH_I, L_I, RVANY, "l"), + ATTR32_LB ( LHU_I, L_I, RVANY, "l"), + ATTR32_LB ( LW_I, L_I, RVANY, "l"), + ATTR32_LB ( LWU_I, L_I, RV64, "l"), + ATTR32_LB ( LD_I, L_I, RV64, "l"), // base S-type instructions for store - ATTR32_SB ( SB_I, S_I, RVANY, "s"), - ATTR32_SB ( SH_I, S_I, RVANY, "s"), - ATTR32_SB ( SW_I, S_I, RVANY, "s"), - ATTR32_SB ( SD_I, S_I, RV64, "s"), + ATTR32_SB ( SB_I, S_I, RVANY, "s"), + ATTR32_SB ( SH_I, S_I, RVANY, "s"), + ATTR32_SB ( SW_I, S_I, RVANY, "s"), + ATTR32_SB ( SD_I, S_I, RV64, "s"), // base I-type instructions for CSR access (register) - ATTR32_CSRRC ( CSRRC_I, CSRR_I, RVANY, "csrrc"), - ATTR32_CSRRC ( CSRRS_I, CSRR_I, RVANY, "csrrs"), - ATTR32_CSRRC ( CSRRW_I, CSRR_I, RVANY, "csrrw"), - ATTR32_CSRR ( CSRR_I, CSRR_I, RVANY, "csrr" ), - ATTR32_CSRC ( CSRC_I, CSRR_I, RVANY, "csrc" ), - ATTR32_CSRC ( CSRS_I, CSRR_I, RVANY, "csrs" ), - ATTR32_CSRC ( CSRW_I, CSRR_I, RVANY, "csrw" ), - ATTR32_RDX1 ( RDX1_I, CSRR_I, RVANY, "rd" ), - ATTR32_RDX1 ( RDX2_I, CSRR_I, RVANY, "rd" ), + ATTR32_CSRRC ( CSRRC_I, CSRR_I, RVANY, "csrrc"), + ATTR32_CSRRC ( CSRRS_I, CSRR_I, RVANY, "csrrs"), + ATTR32_CSRRC ( CSRRW_I, CSRR_I, RVANY, "csrrw"), + ATTR32_CSRR ( CSRR_I, CSRR_I, RVANY, "csrr" ), + ATTR32_CSRC ( CSRC_I, CSRR_I, RVANY, "csrc" ), + ATTR32_CSRC ( CSRS_I, CSRR_I, RVANY, "csrs" ), + ATTR32_CSRC ( CSRW_I, CSRR_I, RVANY, "csrw" ), + ATTR32_RDX1 ( RDX1_I, CSRR_I, RVANY, "rd" ), + ATTR32_RDX1 ( RDX2_I, CSRR_I, RVANY, "rd" ), // base I-type instructions for CSR access (constant) - ATTR32_CSRRCI ( CSRRCI_I, CSRRI_I, RVANY, "csrrci"), - ATTR32_CSRRCI ( CSRRSI_I, CSRRI_I, RVANY, "csrrsi"), - ATTR32_CSRRCI ( CSRRWI_I, CSRRI_I, RVANY, "csrrwi"), - ATTR32_CSRCI ( CSRCI_I, CSRRI_I, RVANY, "csrci" ), - ATTR32_CSRCI ( CSRSI_I, CSRRI_I, RVANY, "csrsi" ), - ATTR32_CSRCI ( CSRWI_I, CSRRI_I, RVANY, "csrwi" ), + ATTR32_CSRRCI ( CSRRCI_I, CSRRI_I, RVANY, "csrrci"), + ATTR32_CSRRCI ( CSRRSI_I, CSRRI_I, RVANY, "csrrsi"), + ATTR32_CSRRCI ( CSRRWI_I, CSRRI_I, RVANY, "csrrwi"), + ATTR32_CSRCI ( CSRCI_I, CSRRI_I, RVANY, "csrci" ), + ATTR32_CSRCI ( CSRSI_I, CSRRI_I, RVANY, "csrsi" ), + ATTR32_CSRCI ( CSRWI_I, CSRRI_I, RVANY, "csrwi" ), // miscellaneous system I-type instructions - ATTR32_NOP ( EBREAK_I, EBREAK_I, RVANY, "ebreak" ), - ATTR32_NOP ( ECALL_I, ECALL_I, RVANY, "ecall" ), - ATTR32_NOP ( FENCEI_I, FENCEI_I, RVANY, "fence.i"), - ATTR32_NOP ( MRET_I, MRET_I, RVANY, "mret" ), - ATTR32_NOP ( SRET_I, SRET_I, RVANY, "sret" ), - ATTR32_NOP ( URET_I, URET_I, RVANYN, "uret" ), - ATTR32_NOP ( DRET_I, DRET_I, RVANY, "dret" ), - ATTR32_NOP ( WFI_I, WFI_I, RVANY, "wfi" ), + ATTR32_NOP ( EBREAK_I, EBREAK_I, RVANY, "ebreak" ), + ATTR32_NOP ( ECALL_I, ECALL_I, RVANY, "ecall" ), + ATTR32_NOP ( FENCEI_I, FENCEI_I, RVANY, "fence.i"), + ATTR32_NOP ( MRET_I, MRET_I, RVANY, "mret" ), + ATTR32_NOP ( SRET_I, SRET_I, RVANY, "sret" ), + ATTR32_NOP ( URET_I, URET_I, RVANYN, "uret" ), + ATTR32_NOP ( DRET_I, DRET_I, RVANY, "dret" ), + ATTR32_NOP ( WFI_I, WFI_I, RVANY, "wfi" ), // system fence I-type instruction - ATTR32_FENCE ( FENCE_I, FENCE_I, RVANY, "fence"), + ATTR32_FENCE ( FENCE_I, FENCE_I, RVANY, "fence"), // system fence R-type instruction - ATTR32_FENCE_VMA ( FENCE_VMA_R, FENCE_VMA_R, RVANY, "sfence.vma"), + ATTR32_FENCE_VMA ( FENCE_VMA_R, FENCE_VMA_R, RVANY, "sfence.vma"), // base U-type - ATTR32_AUIPC ( AUIPC_U, AUIPC_U, RVANY, "auipc"), - ATTR32_AUIPC ( LUI_U, MV_C, RVANY, "lui" ), + ATTR32_AUIPC ( AUIPC_U, AUIPC_U, RVANY, "auipc"), + ATTR32_AUIPC ( LUI_U, MV_C, RVANY, "lui" ), // base B-type - ATTR32_BEQ ( BEQ_B, BEQ_B, RVANY, "beq" ), - ATTR32_BEQZ ( BEQZ_B, BEQ_B, RVANY, "beqz"), - ATTR32_BEQ ( BGE_B, BGE_B, RVANY, "bge" ), - ATTR32_BEQZ ( BGEZ_B, BGE_B, RVANY, "bgez"), - ATTR32_BGTZ ( BLEZ_B, BGE_B, RVANY, "blez"), - ATTR32_BEQ ( BGEU_B, BGEU_B, RVANY, "bgeu"), - ATTR32_BEQ ( BLT_B, BLT_B, RVANY, "blt" ), - ATTR32_BEQZ ( BLTZ_B, BLT_B, RVANY, "bltz"), - ATTR32_BGTZ ( BGTZ_B, BLT_B, RVANY, "bgtz"), - ATTR32_BEQ ( BLTU_B, BLTU_B, RVANY, "bltu"), - ATTR32_BEQ ( BNE_B, BNE_B, RVANY, "bne" ), - ATTR32_BEQZ ( BNEZ_B, BNE_B, RVANY, "bnez"), + ATTR32_BEQ ( BEQ_B, BEQ_B, RVANY, "beq" ), + ATTR32_BEQZ ( BEQZ_B, BEQ_B, RVANY, "beqz"), + ATTR32_BEQ ( BGE_B, BGE_B, RVANY, "bge" ), + ATTR32_BEQZ ( BGEZ_B, BGE_B, RVANY, "bgez"), + ATTR32_BGTZ ( BLEZ_B, BGE_B, RVANY, "blez"), + ATTR32_BEQ ( BGEU_B, BGEU_B, RVANY, "bgeu"), + ATTR32_BEQ ( BLT_B, BLT_B, RVANY, "blt" ), + ATTR32_BEQZ ( BLTZ_B, BLT_B, RVANY, "bltz"), + ATTR32_BGTZ ( BGTZ_B, BLT_B, RVANY, "bgtz"), + ATTR32_BEQ ( BLTU_B, BLTU_B, RVANY, "bltu"), + ATTR32_BEQ ( BNE_B, BNE_B, RVANY, "bne" ), + ATTR32_BEQZ ( BNEZ_B, BNE_B, RVANY, "bnez"), // base J-type - ATTR32_J ( J_J, JAL_J, RVANY, "j" ), - ATTR32_JAL ( JAL_J, JAL_J, RVANY, "jal"), + ATTR32_J ( J_J, JAL_J, RVANY, "j" ), + ATTR32_JAL ( JAL_J, JAL_J, RVANY, "jal"), // A-extension R-type - ATTR32_AMOADD ( AMOADD_R, AMOADD_R, RVANYA, "amoadd" ), - ATTR32_AMOADD ( AMOAND_R, AMOAND_R, RVANYA, "amoand" ), - ATTR32_AMOADD ( AMOMAX_R, AMOMAX_R, RVANYA, "amomax" ), - ATTR32_AMOADD ( AMOMAXU_R, AMOMAXU_R, RVANYA, "amomaxu"), - ATTR32_AMOADD ( AMOMIN_R, AMOMIN_R, RVANYA, "amomin" ), - ATTR32_AMOADD ( AMOMINU_R, AMOMINU_R, RVANYA, "amominu"), - ATTR32_AMOADD ( AMOOR_R, AMOOR_R, RVANYA, "amoor" ), - ATTR32_AMOADD ( AMOSWAP_R, AMOSWAP_R, RVANYA, "amoswap"), - ATTR32_AMOADD ( AMOXOR_R, AMOXOR_R, RVANYA, "amoxor" ), - ATTR32_LR ( LR_R, LR_R, RVANYA, "lr" ), - ATTR32_AMOADD ( SC_R, SC_R, RVANYA, "sc" ), + ATTR32_AMOADD ( AMOADD_R, AMOADD_R, RVANYA, "amoadd" ), + ATTR32_AMOADD ( AMOAND_R, AMOAND_R, RVANYA, "amoand" ), + ATTR32_AMOADD ( AMOMAX_R, AMOMAX_R, RVANYA, "amomax" ), + ATTR32_AMOADD ( AMOMAXU_R, AMOMAXU_R, RVANYA, "amomaxu"), + ATTR32_AMOADD ( AMOMIN_R, AMOMIN_R, RVANYA, "amomin" ), + ATTR32_AMOADD ( AMOMINU_R, AMOMINU_R, RVANYA, "amominu"), + ATTR32_AMOADD ( AMOOR_R, AMOOR_R, RVANYA, "amoor" ), + ATTR32_AMOADD ( AMOSWAP_R, AMOSWAP_R, RVANYA, "amoswap"), + ATTR32_AMOADD ( AMOXOR_R, AMOXOR_R, RVANYA, "amoxor" ), + ATTR32_LR ( LR_R, LR_R, RVANYA, "lr" ), + ATTR32_AMOADD ( SC_R, SC_R, RVANYA, "sc" ), // F-extension and D-extension R-type instructions - ATTR32_FADD ( FADD_R, FADD_R, RVANY, "fadd" ), - ATTR32_FCLASS ( FCLASS_R, FCLASS_R, RVANY, "fclass"), - ATTR32_FCVT ( FCVT_F_X_R, FCVT_R, RVANY, "fcvt", F, XWL), - ATTR32_FCVT ( FCVT_X_F_R, FCVT_R, RVANY, "fcvt", XWL, F ), - ATTR32_FCVT ( FCVT_D_S_R, FCVT_R, RVANY, "fcvt", F, S ), - ATTR32_FCVT ( FCVT_S_D_R, FCVT_R, RVANY, "fcvt", F, D ), - ATTR32_FADD ( FDIV_R, FDIV_R, RVANY, "fdiv" ), - ATTR32_FEQ ( FEQ_R, FEQ_R, RVANY, "feq" ), - ATTR32_FEQ ( FLE_R, FLE_R, RVANY, "fle" ), - ATTR32_FEQ ( FLT_R, FLT_R, RVANY, "flt" ), - ATTR32_FMAX ( FMAX_R, FMAX_R, RVANY, "fmax" ), - ATTR32_FMAX ( FMIN_R, FMIN_R, RVANY, "fmin" ), - ATTR32_FADD ( FMUL_R, FMUL_R, RVANY, "fmul" ), - ATTR32_FMAX ( FSGNJ_R, FSGNJ_R, RVANY, "fsgnj" ), - ATTR32_FMAX ( FSGNJN_R, FSGNJN_R, RVANY, "fsgnjn"), - ATTR32_FMAX ( FSGNJX_R, FSGNJX_R, RVANY, "fsgnjx"), - ATTR32_FMVFX ( FMVFX_R, MV_R, RVANY, "fmv" ), - ATTR32_FMVXF ( FMVXF_R, MV_R, RVANY, "fmv" ), - ATTR32_FSQRT ( FSQRT_R, FSQRT_R, RVANY, "fsqrt" ), - ATTR32_FADD ( FSUB_R, FSUB_R, RVANY, "fsub" ), + ATTR32_FADD ( FADD_R, FADD_R, RVANY, "fadd" ), + ATTR32_FCLASS ( FCLASS_R, FCLASS_R, RVANY, "fclass"), + ATTR32_FCVT ( FCVT_F_X_R, FCVT_R, RVANY, "fcvt", F, XWL), + ATTR32_FCVT ( FCVT_X_F_R, FCVT_R, RVANY, "fcvt", XWL, F ), + ATTR32_FCVT ( FCVT_D_S_R, FCVT_R, RVANY, "fcvt", F, S ), + ATTR32_FCVT ( FCVT_S_D_R, FCVT_R, RVANY, "fcvt", F, D ), + ATTR32_FADD ( FDIV_R, FDIV_R, RVANY, "fdiv" ), + ATTR32_FEQ ( FEQ_R, FEQ_R, RVANY, "feq" ), + ATTR32_FEQ ( FLE_R, FLE_R, RVANY, "fle" ), + ATTR32_FEQ ( FLT_R, FLT_R, RVANY, "flt" ), + ATTR32_FMAX ( FMAX_R, FMAX_R, RVANY, "fmax" ), + ATTR32_FMAX ( FMIN_R, FMIN_R, RVANY, "fmin" ), + ATTR32_FADD ( FMUL_R, FMUL_R, RVANY, "fmul" ), + ATTR32_FMAX ( FSGNJ_R, FSGNJ_R, RVANY, "fsgnj" ), + ATTR32_FMAX ( FSGNJN_R, FSGNJN_R, RVANY, "fsgnjn"), + ATTR32_FMAX ( FSGNJX_R, FSGNJX_R, RVANY, "fsgnjx"), + ATTR32_FMVFX ( FMVFX_R, MV_R, RVANY, "fmv" ), + ATTR32_FMVXF ( FMVXF_R, MV_R, RVANY, "fmv" ), + ATTR32_FSQRT ( FSQRT_R, FSQRT_R, RVANY, "fsqrt" ), + ATTR32_FADD ( FSUB_R, FSUB_R, RVANY, "fsub" ), // F-extension and D-extension R4-type instructions - ATTR32_FMADD ( FMADD_R4, FMADD_R4, RVANY, "fmadd" ), - ATTR32_FMADD ( FMSUB_R4, FMSUB_R4, RVANY, "fmsub" ), - ATTR32_FMADD ( FNMADD_R4, FNMADD_R4, RVANY, "fnmadd"), - ATTR32_FMADD ( FNMSUB_R4, FNMSUB_R4, RVANY, "fnmsub"), + ATTR32_FMADD ( FMADD_R4, FMADD_R4, RVANY, "fmadd" ), + ATTR32_FMADD ( FMSUB_R4, FMSUB_R4, RVANY, "fmsub" ), + ATTR32_FMADD ( FNMADD_R4, FNMADD_R4, RVANY, "fnmadd"), + ATTR32_FMADD ( FNMSUB_R4, FNMSUB_R4, RVANY, "fnmsub"), // F-extension and D-extension I-type instructions - ATTR32_FL ( FL_I, L_I, RVANY, "fl"), - ATTR32_FS ( FS_I, S_I, RVANY, "fs"), + ATTR32_FL ( FL_I, L_I, RVANY, "fl"), + ATTR32_FS ( FS_I, S_I, RVANY, "fs"), // F-extension and D-extension I-type instructions for CSR access - ATTR32_FRSR ( FRSR_I, CSRR_I, RVANY, "frsr" ), - ATTR32_FRSR ( FRFLAGS_I, CSRR_I, RVANY, "frflags"), - ATTR32_FRSR ( FRRM_I, CSRR_I, RVANY, "frrm" ), - ATTR32_FSSR ( FSSR_I, CSRR_I, RVANY, "fssr" ), - ATTR32_FSSR ( FSFLAGS_I, CSRR_I, RVANY, "fsflags"), - ATTR32_FSSR ( FSRM_I, CSRR_I, RVANY, "fsrm" ), + ATTR32_FRSR ( FRSR_I, CSRR_I, RVANY, "frsr" ), + ATTR32_FRSR ( FRFLAGS_I, CSRR_I, RVANY, "frflags"), + ATTR32_FRSR ( FRRM_I, CSRR_I, RVANY, "frrm" ), + ATTR32_FSSR ( FSSR_I, CSRR_I, RVANY, "fssr" ), + ATTR32_FSSR ( FSFLAGS_I, CSRR_I, RVANY, "fsflags"), + ATTR32_FSSR ( FSRM_I, CSRR_I, RVANY, "fsrm" ), // X-extension Type, custom instructions - ATTR32_CUSTOM ( CUSTOM1, CUSTOM, RVANY, "custom1"), - ATTR32_CUSTOM ( CUSTOM2, CUSTOM, RVANY, "custom2"), - ATTR32_CUSTOM ( CUSTOM3, CUSTOM, RVANY, "custom3"), - ATTR32_CUSTOM ( CUSTOM4, CUSTOM, RVANY, "custom4"), + ATTR32_CUSTOM ( CUSTOM1, CUSTOM, RVANY, "custom1"), + ATTR32_CUSTOM ( CUSTOM2, CUSTOM, RVANY, "custom2"), + ATTR32_CUSTOM ( CUSTOM3, CUSTOM, RVANY, "custom3"), + ATTR32_CUSTOM ( CUSTOM4, CUSTOM, RVANY, "custom4"), // V-extension R-type - ATTR32_ADD ( VSETVL_R, VSETVL_R, RVANYV, "vsetvl"), + ATTR32_ADD ( VSETVL_R, VSETVL_R, RVANYV, "vsetvl"), // V-extension I-type - ATTR32_VSETVLI ( VSETVL_I, VSETVL_I, RVANYV, "vsetvli"), - - // V-extension load/store instructions (byte elements) - ATTR32_VL ( VLB_I, VL_I, RVANYV, "vl", 1), - ATTR32_VLS ( VLSB_I, VLS_I, RVANYV, "vls", 1), - ATTR32_VLX ( VLXB_I, VLX_I, RVANYV, "vlx", 1), - ATTR32_VL ( VSB_I, VS_I, RVANYV, "vs", 0), - ATTR32_VLS ( VSSB_I, VSS_I, RVANYV, "vss", 0), - ATTR32_VLX ( VSXB_I, VSX_I, RVANYV, "vsx", 0), - ATTR32_VLX ( VSUXB_I, VSX_I, RVANYV, "vsux", 0), - - // V-extension load/store instructions (halfword elements) - ATTR32_VL ( VLH_I, VL_I, RVANYV, "vl", 1), - ATTR32_VLS ( VLSH_I, VLS_I, RVANYV, "vls", 1), - ATTR32_VLX ( VLXH_I, VLX_I, RVANYV, "vlx", 1), - ATTR32_VL ( VSH_I, VS_I, RVANYV, "vs", 0), - ATTR32_VLS ( VSSH_I, VSS_I, RVANYV, "vss", 0), - ATTR32_VLX ( VSXH_I, VSX_I, RVANYV, "vsx", 0), - ATTR32_VLX ( VSUXH_I, VSX_I, RVANYV, "vsux", 0), - - // V-extension load/store instructions (word elements) - ATTR32_VL ( VLW_I, VL_I, RVANYV, "vl", 1), - ATTR32_VLS ( VLSW_I, VLS_I, RVANYV, "vls", 1), - ATTR32_VLX ( VLXW_I, VLX_I, RVANYV, "vlx", 1), - ATTR32_VL ( VSW_I, VS_I, RVANYV, "vs", 0), - ATTR32_VLS ( VSSW_I, VSS_I, RVANYV, "vss", 0), - ATTR32_VLX ( VSXW_I, VSX_I, RVANYV, "vsx", 0), - ATTR32_VLX ( VSUXW_I, VSX_I, RVANYV, "vsux", 0), - - // V-extension load/store instructions (SEW elements) - ATTR32_VL ( VLE_I, VL_I, RVANYV, "vl", 0), - ATTR32_VLS ( VLSE_I, VLS_I, RVANYV, "vls", 0), - ATTR32_VLX ( VLXE_I, VLX_I, RVANYV, "vlx", 0), - ATTR32_VL ( VSE_I, VS_I, RVANYV, "vs", 0), - ATTR32_VLS ( VSSE_I, VSS_I, RVANYV, "vss", 0), - ATTR32_VLX ( VSXE_I, VSX_I, RVANYV, "vsx", 0), - ATTR32_VLX ( VSUXE_I, VSX_I, RVANYV, "vsux", 0), - - // V-extension AMO operations (Zvamo) - ATTR32_VAMOADD ( VAMOADD_R, VAMOADD_R, RVANYVA, "vamoadd" ), - ATTR32_VAMOADD ( VAMOAND_R, VAMOAND_R, RVANYVA, "vamoand" ), - ATTR32_VAMOADD ( VAMOMAX_R, VAMOMAX_R, RVANYVA, "vamomax" ), - ATTR32_VAMOADD ( VAMOMAXU_R, VAMOMAXU_R, RVANYVA, "vamomaxu"), - ATTR32_VAMOADD ( VAMOMIN_R, VAMOMIN_R, RVANYVA, "vamomin" ), - ATTR32_VAMOADD ( VAMOMINU_R, VAMOMINU_R, RVANYVA, "vamominu"), - ATTR32_VAMOADD ( VAMOOR_R, VAMOOR_R, RVANYVA, "vamoor" ), - ATTR32_VAMOADD ( VAMOSWAP_R, VAMOSWAP_R, RVANYVA, "vamoswap"), - ATTR32_VAMOADD ( VAMOXOR_R, VAMOXOR_R, RVANYVA, "vamoxor" ), + ATTR32_VSETVLI ( VSETVL_I, VSETVL_I, RVANYV, "vsetvli"), + + // V-extension load/store instructions (pre-0.9) + ATTR32_VL ( VL_I, VL_I, RVANYV, "vl", 1), + ATTR32_VLS ( VLS_I, VLS_I, RVANYV, "vls", 1), + ATTR32_VLX ( VLX_I, VLX_I, RVANYV, "vlx", 1), + ATTR32_VL ( VS_I, VS_I, RVANYV, "vs", 0), + ATTR32_VLS ( VSS_I, VSS_I, RVANYV, "vss", 0), + ATTR32_VLX ( VSX_I, VSX_I, RVANYV, "vsx", 0), + ATTR32_VLX ( VSUX_I, VSX_I, RVANYV, "vsux", 0), + + // V-extension load/store instructions (0.9 and later) + ATTR32_VLE ( VLE_I, VL_I, RVANYV, "vl" ), + ATTR32_VLSE ( VLSE_I, VLS_I, RVANYV, "vls" ), + ATTR32_VLXEI ( VLXEI_I, VLX_I, RVANYV, "vlx" ), + ATTR32_VLE ( VSE_I, VS_I, RVANYV, "vs" ), + ATTR32_VLSE ( VSSE_I, VSS_I, RVANYV, "vss" ), + ATTR32_VLXEI ( VSXEI_I, VSX_I, RVANYV, "vsx" ), + ATTR32_VLXEI ( VSUXEI_I, VSX_I, RVANYV, "vsux"), + + // V-extension AMO operations (Zvamo, pre-0.9) + ATTR32_VAMOADD ( VAMOADD_R, VAMOADD_R, RVANYVA, "vamoadd" ), + ATTR32_VAMOADD ( VAMOAND_R, VAMOAND_R, RVANYVA, "vamoand" ), + ATTR32_VAMOADD ( VAMOMAX_R, VAMOMAX_R, RVANYVA, "vamomax" ), + ATTR32_VAMOADD ( VAMOMAXU_R, VAMOMAXU_R, RVANYVA, "vamomaxu"), + ATTR32_VAMOADD ( VAMOMIN_R, VAMOMIN_R, RVANYVA, "vamomin" ), + ATTR32_VAMOADD ( VAMOMINU_R, VAMOMINU_R, RVANYVA, "vamominu"), + ATTR32_VAMOADD ( VAMOOR_R, VAMOOR_R, RVANYVA, "vamoor" ), + ATTR32_VAMOADD ( VAMOSWAP_R, VAMOSWAP_R, RVANYVA, "vamoswap"), + ATTR32_VAMOADD ( VAMOXOR_R, VAMOXOR_R, RVANYVA, "vamoxor" ), + + // V-extension AMO operations (Zvamo, 0.9 and later) + ATTR32_VAMOADDEI ( VAMOADDEI_R, VAMOADD_R, RVANYVA, "vamoadd" ), + ATTR32_VAMOADDEI ( VAMOANDEI_R, VAMOAND_R, RVANYVA, "vamoand" ), + ATTR32_VAMOADDEI ( VAMOMAXEI_R, VAMOMAX_R, RVANYVA, "vamomax" ), + ATTR32_VAMOADDEI ( VAMOMAXUEI_R, VAMOMAXU_R, RVANYVA, "vamomaxu"), + ATTR32_VAMOADDEI ( VAMOMINEI_R, VAMOMIN_R, RVANYVA, "vamomin" ), + ATTR32_VAMOADDEI ( VAMOMINUEI_R, VAMOMINU_R, RVANYVA, "vamominu"), + ATTR32_VAMOADDEI ( VAMOOREI_R, VAMOOR_R, RVANYVA, "vamoor" ), + ATTR32_VAMOADDEI ( VAMOSWAPEI_R, VAMOSWAP_R, RVANYVA, "vamoswap"), + ATTR32_VAMOADDEI ( VAMOXOREI_R, VAMOXOR_R, RVANYVA, "vamoxor" ), // V-extension IVV-type instructions - ATTR32_VV ( VADD_VV, VADD_VR, RVANYV, "vadd" ), - ATTR32_VV ( VSUB_VV, VSUB_VR, RVANYV, "vsub" ), - ATTR32_VV ( VMINU_VV, VMINU_VR, RVANYV, "vminu" ), - ATTR32_VV ( VMIN_VV, VMIN_VR, RVANYV, "vmin" ), - ATTR32_VV ( VMAXU_VV, VMAXU_VR, RVANYV, "vmaxu" ), - ATTR32_VV ( VMAX_VV, VMAX_VR, RVANYV, "vmax" ), - ATTR32_VV ( VAND_VV, VAND_VR, RVANYV, "vand" ), - ATTR32_VV ( VOR_VV, VOR_VR, RVANYV, "vor" ), - ATTR32_VV ( VXOR_VV, VXOR_VR, RVANYV, "vxor" ), - ATTR32_VV ( VRGATHER_VV, VRGATHER_VR, RVANYV, "vrgather" ), - ATTR32_VVM_CIN ( VADC_VV, VADC_VR, RVANYV, "vadc" ), - ATTR32_VVM_CIN ( VMADC_VV, VMADC_VR, RVANYV, "vmadc" ), - ATTR32_VVM_CIN ( VSBC_VV, VSBC_VR, RVANYV, "vsbc" ), - ATTR32_VVM_CIN ( VMSBC_VV, VMSBC_VR, RVANYV, "vmsbc" ), - ATTR32_VVM ( VMERGE_VV, VMERGE_VR, RVANYV, "vmerge" ), - ATTR32_VMV_V_V ( VMV_V_V, VMERGE_VR, RVANYV, "vmv.v.v" ), - ATTR32_VV ( VSEQ_VV, VSEQ_VR, RVANYV, "vmseq" ), - ATTR32_VV ( VSNE_VV, VSNE_VR, RVANYV, "vmsne" ), - ATTR32_VV ( VSLTU_VV, VSLTU_VR, RVANYV, "vmsltu" ), - ATTR32_VV ( VSLT_VV, VSLT_VR, RVANYV, "vmslt" ), - ATTR32_VV ( VSLEU_VV, VSLEU_VR, RVANYV, "vmsleu" ), - ATTR32_VV ( VSLE_VV, VSLE_VR, RVANYV, "vmsle" ), - ATTR32_VV ( VSADDU_VV, VSADDU_VR, RVANYV, "vsaddu" ), - ATTR32_VV ( VSADD_VV, VSADD_VR, RVANYV, "vsadd" ), - ATTR32_VV ( VSSUBU_VV, VSSUBU_VR, RVANYV, "vssubu" ), - ATTR32_VV ( VSSUB_VV, VSSUB_VR, RVANYV, "vssub" ), - ATTR32_VV ( VAADDU_VV, VAADDU_VR, RVANYV, "vaaddu" ), - ATTR32_VV ( VAADD_VV, VAADD_VR, RVANYV, "vaadd" ), - ATTR32_VV ( VSLL_VV, VSLL_VR, RVANYV, "vsll" ), - ATTR32_VV ( VASUBU_VV, VASUBU_VR, RVANYV, "vasubu" ), - ATTR32_VV ( VASUB_VV, VASUB_VR, RVANYV, "vasub" ), - ATTR32_VV ( VSMUL_VV, VSMUL_VR, RVANYV, "vsmul" ), - ATTR32_VV ( VSRL_VV, VSRL_VR, RVANYV, "vsrl" ), - ATTR32_VV ( VSRA_VV, VSRA_VR, RVANYV, "vsra" ), - ATTR32_VV ( VSSRL_VV, VSSRL_VR, RVANYV, "vssrl" ), - ATTR32_VV ( VSSRA_VV, VSSRA_VR, RVANYV, "vssra" ), - ATTR32_VVN ( VNSRL_VV, VNSRL_VR, RVANYV, "vnsrl" ), - ATTR32_VVN ( VNSRA_VV, VNSRA_VR, RVANYV, "vnsra" ), - ATTR32_VVN ( VNCLIPU_VV, VNCLIPU_VR, RVANYV, "vnclipu" ), - ATTR32_VVN ( VNCLIP_VV, VNCLIP_VR, RVANYV, "vnclip" ), - ATTR32_VS ( VWREDSUMU_VS, VWREDSUMU_VS, RVANYV, "vwredsumu"), - ATTR32_VS ( VWREDSUM_VS, VWREDSUM_VS, RVANYV, "vwredsum" ), - ATTR32_VV ( VDOTU_VV, VDOTU_VV, RVANYV, "vdotu" ), - ATTR32_VV ( VDOT_VV, VDOT_VV, RVANYV, "vdot" ), - ATTR32_VV3 ( VWSMACCU_VV, VWSMACCU_VR, RVANYV, "vwsmaccu" ), - ATTR32_VV3 ( VWSMACC_VV, VWSMACC_VR, RVANYV, "vwsmacc" ), - ATTR32_VV3 ( VWSMACCSU_VV, VWSMACCSU_VR, RVANYV, "vwsmaccsu"), - ATTR32_VV3 ( VQMACCU_VV, VQMACCU_VR, RVANYV, "vqmaccu" ), - ATTR32_VV3 ( VQMACC_VV, VQMACC_VR, RVANYV, "vqmacc" ), - ATTR32_VV3 ( VQMACCSU_VV, VQMACCSU_VR, RVANYV, "vqmaccsu" ), + ATTR32_VV ( VADD_VV, VADD_VR, RVANYV, "vadd" ), + ATTR32_VV ( VSUB_VV, VSUB_VR, RVANYV, "vsub" ), + ATTR32_VV ( VMINU_VV, VMINU_VR, RVANYV, "vminu" ), + ATTR32_VV ( VMIN_VV, VMIN_VR, RVANYV, "vmin" ), + ATTR32_VV ( VMAXU_VV, VMAXU_VR, RVANYV, "vmaxu" ), + ATTR32_VV ( VMAX_VV, VMAX_VR, RVANYV, "vmax" ), + ATTR32_VV ( VAND_VV, VAND_VR, RVANYV, "vand" ), + ATTR32_VV ( VOR_VV, VOR_VR, RVANYV, "vor" ), + ATTR32_VV ( VXOR_VV, VXOR_VR, RVANYV, "vxor" ), + ATTR32_VV ( VRGATHER_VV, VRGATHER_VR, RVANYV, "vrgather" ), + ATTR32_VVM_CIN ( VADC_VV, VADC_VR, RVANYV, "vadc" ), + ATTR32_VVM_CIN ( VMADC_VV, VMADC_VR, RVANYV, "vmadc" ), + ATTR32_VVM_CIN ( VSBC_VV, VSBC_VR, RVANYV, "vsbc" ), + ATTR32_VVM_CIN ( VMSBC_VV, VMSBC_VR, RVANYV, "vmsbc" ), + ATTR32_VVM ( VMERGE_VV, VMERGE_VR, RVANYV, "vmerge" ), + ATTR32_VMV_V_V ( VMV_V_V, VMERGE_VR, RVANYV, "vmv.v.v" ), + ATTR32_VV ( VSEQ_VV, VSEQ_VR, RVANYV, "vmseq" ), + ATTR32_VV ( VSNE_VV, VSNE_VR, RVANYV, "vmsne" ), + ATTR32_VV ( VSLTU_VV, VSLTU_VR, RVANYV, "vmsltu" ), + ATTR32_VV ( VSLT_VV, VSLT_VR, RVANYV, "vmslt" ), + ATTR32_VV ( VSLEU_VV, VSLEU_VR, RVANYV, "vmsleu" ), + ATTR32_VV ( VSLE_VV, VSLE_VR, RVANYV, "vmsle" ), + ATTR32_VV ( VSADDU_VV, VSADDU_VR, RVANYV, "vsaddu" ), + ATTR32_VV ( VSADD_VV, VSADD_VR, RVANYV, "vsadd" ), + ATTR32_VV ( VSSUBU_VV, VSSUBU_VR, RVANYV, "vssubu" ), + ATTR32_VV ( VSSUB_VV, VSSUB_VR, RVANYV, "vssub" ), + ATTR32_VV ( VAADDU_VV, VAADDU_VR, RVANYV, "vaaddu" ), + ATTR32_VV ( VAADD_VV, VAADD_VR, RVANYV, "vaadd" ), + ATTR32_VV ( VSLL_VV, VSLL_VR, RVANYV, "vsll" ), + ATTR32_VV ( VASUBU_VV, VASUBU_VR, RVANYV, "vasubu" ), + ATTR32_VV ( VASUB_VV, VASUB_VR, RVANYV, "vasub" ), + ATTR32_VV ( VSMUL_VV, VSMUL_VR, RVANYV, "vsmul" ), + ATTR32_VV ( VSRL_VV, VSRL_VR, RVANYV, "vsrl" ), + ATTR32_VV ( VSRA_VV, VSRA_VR, RVANYV, "vsra" ), + ATTR32_VV ( VSSRL_VV, VSSRL_VR, RVANYV, "vssrl" ), + ATTR32_VV ( VSSRA_VV, VSSRA_VR, RVANYV, "vssra" ), + ATTR32_VVN ( VNSRL_VV, VNSRL_VR, RVANYV, "vnsrl" ), + ATTR32_VVN ( VNSRA_VV, VNSRA_VR, RVANYV, "vnsra" ), + ATTR32_VVN ( VNCLIPU_VV, VNCLIPU_VR, RVANYV, "vnclipu" ), + ATTR32_VVN ( VNCLIP_VV, VNCLIP_VR, RVANYV, "vnclip" ), + ATTR32_VS ( VWREDSUMU_VS, VWREDSUMU_VS, RVANYV, "vwredsumu"), + ATTR32_VS ( VWREDSUM_VS, VWREDSUM_VS, RVANYV, "vwredsum" ), + ATTR32_VV ( VDOTU_VV, VDOTU_VV, RVANYV, "vdotu" ), + ATTR32_VV ( VDOT_VV, VDOT_VV, RVANYV, "vdot" ), + ATTR32_VV3 ( VWSMACCU_VV, VWSMACCU_VR, RVANYV, "vwsmaccu" ), + ATTR32_VV3 ( VWSMACC_VV, VWSMACC_VR, RVANYV, "vwsmacc" ), + ATTR32_VV3 ( VWSMACCSU_VV, VWSMACCSU_VR, RVANYV, "vwsmaccsu"), + ATTR32_VV3 ( VQMACCU_VV, VQMACCU_VR, RVANYV, "vqmaccu" ), + ATTR32_VV3 ( VQMACC_VV, VQMACC_VR, RVANYV, "vqmacc" ), + ATTR32_VV3 ( VQMACCSU_VV, VQMACCSU_VR, RVANYV, "vqmaccsu" ), // V-extension FVV-type instructions - ATTR32_VV ( VFADD_VV, VFADD_VR, RVANYV, "vfadd" ), - ATTR32_VS ( VFREDSUM_VS, VFREDSUM_VS, RVANYV, "vfredsum" ), - ATTR32_VV ( VFSUB_VV, VFSUB_VR, RVANYV, "vfsub" ), - ATTR32_VS ( VFREDOSUM_VS, VFREDOSUM_VS, RVANYV, "vfredosum" ), - ATTR32_VV ( VFMIN_VV, VFMIN_VR, RVANYV, "vfmin" ), - ATTR32_VS ( VFREDMIN_VS, VFREDMIN_VS, RVANYV, "vfredmin" ), - ATTR32_VV ( VFMAX_VV, VFMAX_VR, RVANYV, "vfmax" ), - ATTR32_VS ( VFREDMAX_VS, VFREDMAX_VS, RVANYV, "vfredmax" ), - ATTR32_VV ( VFSGNJ_VV, VFSGNJ_VR, RVANYV, "vfsgnj" ), - ATTR32_VV ( VFSGNJN_VV, VFSGNJN_VR, RVANYV, "vfsgnjn" ), - ATTR32_VV ( VFSGNJX_VV, VFSGNJX_VR, RVANYV, "vfsgnjx" ), - ATTR32_VFMV_F_S ( VFMV_F_S, VFMV_F_S, RVANYV, "vfmv.f.s" ), - ATTR32_VV ( VFEQ_VV, VFEQ_VR, RVANYV, "vmfeq" ), - ATTR32_VV ( VFLTE_VV, VFLE_VR, RVANYV, "vmfle" ), - ATTR32_VV ( VFORD_VV, VFORD_VR, RVANYV, "vmford" ), - ATTR32_VV ( VFLT_VV, VFLT_VR, RVANYV, "vmflt" ), - ATTR32_VV ( VFNE_VV, VFNE_VR, RVANYV, "vmfne" ), - ATTR32_VV ( VFDIV_VV, VFDIV_VR, RVANYV, "vfdiv" ), - ATTR32_V ( VFCVT_XUF_V, VFCVT_XUF_V, RVANYV, "vfcvt.xu.f" ), - ATTR32_V ( VFCVT_XF_V, VFCVT_XF_V, RVANYV, "vfcvt.x.f" ), - ATTR32_V ( VFCVT_FXU_V, VFCVT_FXU_V, RVANYV, "vfcvt.f.xu" ), - ATTR32_V ( VFCVT_FX_V, VFCVT_FX_V, RVANYV, "vfcvt.f.x" ), - ATTR32_V ( VFWCVT_XUF_V, VFWCVT_XUF_V, RVANYV, "vfwcvt.xu.f"), - ATTR32_V ( VFWCVT_XF_V, VFWCVT_XF_V, RVANYV, "vfwcvt.x.f" ), - ATTR32_V ( VFWCVT_FXU_V, VFWCVT_FXU_V, RVANYV, "vfwcvt.f.xu"), - ATTR32_V ( VFWCVT_FX_V, VFWCVT_FX_V, RVANYV, "vfwcvt.f.x" ), - ATTR32_V ( VFWCVT_FF_V, VFWCVT_FF_V, RVANYV, "vfwcvt.f.f" ), - ATTR32_VN ( VFNCVT_XUF_V, VFNCVT_XUF_V, RVANYV, "vfncvt.xu.f"), - ATTR32_VN ( VFNCVT_XF_V, VFNCVT_XF_V, RVANYV, "vfncvt.x.f" ), - ATTR32_VN ( VFNCVT_FXU_V, VFNCVT_FXU_V, RVANYV, "vfncvt.f.xu"), - ATTR32_VN ( VFNCVT_FX_V, VFNCVT_FX_V, RVANYV, "vfncvt.f.x" ), - ATTR32_VN ( VFNCVT_FF_V, VFNCVT_FF_V, RVANYV, "vfncvt.f.f" ), - ATTR32_W_ROD (VFNCVTROD_FF_V, VFNCVT_FF_V, RVANYV, "vfncvt.rod.f.f"), - ATTR32_V ( VFSQRT_V, VFSQRT_V, RVANYV, "vfsqrt" ), - ATTR32_V ( VFCLASS_V, VFCLASS_V, RVANYV, "vfclass" ), - ATTR32_VV ( VFMUL_VV, VFMUL_VR, RVANYV, "vfmul" ), - ATTR32_VV3 ( VFMADD_VV, VFMADD_VR, RVANYV, "vfmadd" ), - ATTR32_VV3 ( VFNMADD_VV, VFNMADD_VR, RVANYV, "vfnmadd" ), - ATTR32_VV3 ( VFMSUB_VV, VFMSUB_VR, RVANYV, "vfmsub" ), - ATTR32_VV3 ( VFNMSUB_VV, VFNMSUB_VR, RVANYV, "vfnmsub" ), - ATTR32_VV3 ( VFMACC_VV, VFMACC_VR, RVANYV, "vfmacc" ), - ATTR32_VV3 ( VFNMACC_VV, VFNMACC_VR, RVANYV, "vfnmacc" ), - ATTR32_VV3 ( VFMSAC_VV, VFMSAC_VR, RVANYV, "vfmsac" ), - ATTR32_VV3 ( VFNMSAC_VV, VFNMSAC_VR, RVANYV, "vfnmsac" ), - ATTR32_VV ( VFWADD_VV, VFWADD_VR, RVANYV, "vfwadd" ), - ATTR32_VS ( VFWREDSUM_VS, VFWREDSUM_VS, RVANYV, "vfwredsum" ), - ATTR32_VV ( VFWSUB_VV, VFWSUB_VR, RVANYV, "vfwsub" ), - ATTR32_VS ( VFWREDOSUM_VS, VFWREDOSUM_VS, RVANYV, "vfwredosum" ), - ATTR32_WV ( VFWADD_WV, VFWADD_WR, RVANYV, "vfwadd" ), - ATTR32_WV ( VFWSUB_WV, VFWSUB_WR, RVANYV, "vfwsub" ), - ATTR32_VV ( VFWMUL_VV, VFWMUL_VR, RVANYV, "vfwmul" ), - ATTR32_VV ( VFDOT_VV, VFDOT_VV, RVANYV, "vfdot" ), - ATTR32_VV3 ( VFWMACC_VV, VFWMACC_VR, RVANYV, "vfwmacc" ), - ATTR32_VV3 ( VFWNMACC_VV, VFWNMACC_VR, RVANYV, "vfwnmacc" ), - ATTR32_VV3 ( VFWMSAC_VV, VFWMSAC_VR, RVANYV, "vfwmsac" ), - ATTR32_VV3 ( VFWNMSAC_VV, VFWNMSAC_VR, RVANYV, "vfwnmsac" ), + ATTR32_VV ( VFADD_VV, VFADD_VR, RVANYV, "vfadd" ), + ATTR32_VS ( VFREDSUM_VS, VFREDSUM_VS, RVANYV, "vfredsum" ), + ATTR32_VV ( VFSUB_VV, VFSUB_VR, RVANYV, "vfsub" ), + ATTR32_VS ( VFREDOSUM_VS, VFREDOSUM_VS, RVANYV, "vfredosum" ), + ATTR32_VV ( VFMIN_VV, VFMIN_VR, RVANYV, "vfmin" ), + ATTR32_VS ( VFREDMIN_VS, VFREDMIN_VS, RVANYV, "vfredmin" ), + ATTR32_VV ( VFMAX_VV, VFMAX_VR, RVANYV, "vfmax" ), + ATTR32_VS ( VFREDMAX_VS, VFREDMAX_VS, RVANYV, "vfredmax" ), + ATTR32_VV ( VFSGNJ_VV, VFSGNJ_VR, RVANYV, "vfsgnj" ), + ATTR32_VV ( VFSGNJN_VV, VFSGNJN_VR, RVANYV, "vfsgnjn" ), + ATTR32_VV ( VFSGNJX_VV, VFSGNJX_VR, RVANYV, "vfsgnjx" ), + ATTR32_VFMV_F_S ( VFMV_F_S, VFMV_F_S, RVANYV, "vfmv.f.s" ), + ATTR32_VV ( VFEQ_VV, VFEQ_VR, RVANYV, "vmfeq" ), + ATTR32_VV ( VFLTE_VV, VFLE_VR, RVANYV, "vmfle" ), + ATTR32_VV ( VFORD_VV, VFORD_VR, RVANYV, "vmford" ), + ATTR32_VV ( VFLT_VV, VFLT_VR, RVANYV, "vmflt" ), + ATTR32_VV ( VFNE_VV, VFNE_VR, RVANYV, "vmfne" ), + ATTR32_VV ( VFDIV_VV, VFDIV_VR, RVANYV, "vfdiv" ), + ATTR32_V ( VFCVT_XUF_V, VFCVT_XUF_V, RVANYV, "vfcvt.xu.f" ), + ATTR32_V_RTZ ( VFCVTRTZ_XUF_V, VFCVT_XUF_V, RVANYV, "vfcvt.rtz.xu.f" ), + ATTR32_V ( VFCVT_XF_V, VFCVT_XF_V, RVANYV, "vfcvt.x.f" ), + ATTR32_V_RTZ ( VFCVTRTZ_XF_V, VFCVT_XF_V, RVANYV, "vfcvt.rtz.x.f" ), + ATTR32_V ( VFCVT_FXU_V, VFCVT_FXU_V, RVANYV, "vfcvt.f.xu" ), + ATTR32_V ( VFCVT_FX_V, VFCVT_FX_V, RVANYV, "vfcvt.f.x" ), + ATTR32_V ( VFWCVT_XUF_V, VFWCVT_XUF_V, RVANYV, "vfwcvt.xu.f" ), + ATTR32_V_RTZ (VFWCVTRTZ_XUF_V, VFWCVT_XUF_V, RVANYV, "vfwcvt.rtz.xu.f"), + ATTR32_V ( VFWCVT_XF_V, VFWCVT_XF_V, RVANYV, "vfwcvt.x.f" ), + ATTR32_V_RTZ ( VFWCVTRTZ_XF_V, VFWCVT_XF_V, RVANYV, "vfwcvt.rtz.x.f" ), + ATTR32_V ( VFWCVT_FXU_V, VFWCVT_FXU_V, RVANYV, "vfwcvt.f.xu" ), + ATTR32_V ( VFWCVT_FX_V, VFWCVT_FX_V, RVANYV, "vfwcvt.f.x" ), + ATTR32_V ( VFWCVT_FF_V, VFWCVT_FF_V, RVANYV, "vfwcvt.f.f" ), + ATTR32_VN ( VFNCVT_XUF_V, VFNCVT_XUF_V, RVANYV, "vfncvt.xu.f" ), + ATTR32_VN_RTZ (VFNCVTRTZ_XUF_V, VFNCVT_XUF_V, RVANYV, "vfncvt.rtz.xu.f"), + ATTR32_VN ( VFNCVT_XF_V, VFNCVT_XF_V, RVANYV, "vfncvt.x.f" ), + ATTR32_VN_RTZ ( VFNCVTRTZ_XF_V, VFNCVT_XF_V, RVANYV, "vfncvt.rtz.x.f" ), + ATTR32_VN ( VFNCVT_FXU_V, VFNCVT_FXU_V, RVANYV, "vfncvt.f.xu" ), + ATTR32_VN ( VFNCVT_FX_V, VFNCVT_FX_V, RVANYV, "vfncvt.f.x" ), + ATTR32_VN ( VFNCVT_FF_V, VFNCVT_FF_V, RVANYV, "vfncvt.f.f" ), + ATTR32_VN_ROD ( VFNCVTROD_FF_V, VFNCVT_FF_V, RVANYV, "vfncvt.rod.f.f" ), + ATTR32_V ( VFSQRT_V, VFSQRT_V, RVANYV, "vfsqrt" ), + ATTR32_V ( VFCLASS_V, VFCLASS_V, RVANYV, "vfclass" ), + ATTR32_VV ( VFMUL_VV, VFMUL_VR, RVANYV, "vfmul" ), + ATTR32_VV3 ( VFMADD_VV, VFMADD_VR, RVANYV, "vfmadd" ), + ATTR32_VV3 ( VFNMADD_VV, VFNMADD_VR, RVANYV, "vfnmadd" ), + ATTR32_VV3 ( VFMSUB_VV, VFMSUB_VR, RVANYV, "vfmsub" ), + ATTR32_VV3 ( VFNMSUB_VV, VFNMSUB_VR, RVANYV, "vfnmsub" ), + ATTR32_VV3 ( VFMACC_VV, VFMACC_VR, RVANYV, "vfmacc" ), + ATTR32_VV3 ( VFNMACC_VV, VFNMACC_VR, RVANYV, "vfnmacc" ), + ATTR32_VV3 ( VFMSAC_VV, VFMSAC_VR, RVANYV, "vfmsac" ), + ATTR32_VV3 ( VFNMSAC_VV, VFNMSAC_VR, RVANYV, "vfnmsac" ), + ATTR32_VV ( VFWADD_VV, VFWADD_VR, RVANYV, "vfwadd" ), + ATTR32_VS ( VFWREDSUM_VS, VFWREDSUM_VS, RVANYV, "vfwredsum" ), + ATTR32_VV ( VFWSUB_VV, VFWSUB_VR, RVANYV, "vfwsub" ), + ATTR32_VS ( VFWREDOSUM_VS, VFWREDOSUM_VS, RVANYV, "vfwredosum" ), + ATTR32_WV ( VFWADD_WV, VFWADD_WR, RVANYV, "vfwadd" ), + ATTR32_WV ( VFWSUB_WV, VFWSUB_WR, RVANYV, "vfwsub" ), + ATTR32_VV ( VFWMUL_VV, VFWMUL_VR, RVANYV, "vfwmul" ), + ATTR32_VV ( VFDOT_VV, VFDOT_VV, RVANYV, "vfdot" ), + ATTR32_VV3 ( VFWMACC_VV, VFWMACC_VR, RVANYV, "vfwmacc" ), + ATTR32_VV3 ( VFWNMACC_VV, VFWNMACC_VR, RVANYV, "vfwnmacc" ), + ATTR32_VV3 ( VFWMSAC_VV, VFWMSAC_VR, RVANYV, "vfwmsac" ), + ATTR32_VV3 ( VFWNMSAC_VV, VFWNMSAC_VR, RVANYV, "vfwnmsac" ), // V-extension MVV-type instructions - ATTR32_VV ( VWADD_VV, VWADD_VR, RVANYV, "vwadd" ), - ATTR32_VV ( VWADDU_VV, VWADDU_VR, RVANYV, "vwaddu" ), - ATTR32_VV ( VWSUB_VV, VWSUB_VR, RVANYV, "vwsub" ), - ATTR32_VV ( VWSUBU_VV, VWSUBU_VR, RVANYV, "vwsubu" ), - ATTR32_WV ( VWADD_WV, VWADD_WR, RVANYV, "vwadd" ), - ATTR32_WV ( VWADDU_WV, VWADDU_WR, RVANYV, "vwaddu" ), - ATTR32_WV ( VWSUB_WV, VWSUB_WR, RVANYV, "vwsub" ), - ATTR32_WV ( VWSUBU_WV, VWSUBU_WR, RVANYV, "vwsubu" ), - ATTR32_VV ( VMUL_VV, VMUL_VR, RVANYV, "vmul" ), - ATTR32_VV ( VMULH_VV, VMULH_VR, RVANYV, "vmulh" ), - ATTR32_VV ( VMULHU_VV, VMULHU_VR, RVANYV, "vmulhu" ), - ATTR32_VV ( VMULHSU_VV, VMULHSU_VR, RVANYV, "vmulhsu" ), - ATTR32_VV ( VWMUL_VV, VWMUL_VR, RVANYV, "vwmul" ), - ATTR32_VV ( VWMULU_VV, VWMULU_VR, RVANYV, "vwmulu" ), - ATTR32_VV ( VWMULSU_VV, VWMULSU_VR, RVANYV, "vwmulsu" ), - ATTR32_VV3 ( VMACC_VV, VMACC_VR, RVANYV, "vmacc" ), - ATTR32_VV3 ( VNMSAC_VV, VNMSAC_VR, RVANYV, "vnmsac" ), - ATTR32_VV3 ( VMADD_VV, VMADD_VR, RVANYV, "vmadd" ), - ATTR32_VV3 ( VNMSUB_VV, VNMSUB_VR, RVANYV, "vnmsub" ), - ATTR32_VV3 ( VWMACCU_VV, VWMACCU_VR, RVANYV, "vwmaccu" ), - ATTR32_VV3 ( VWMACC_VV, VWMACC_VR, RVANYV, "vwmacc" ), - ATTR32_VV3 ( VWMACCSU_VV, VWMACCSU_VR, RVANYV, "vwmaccsu" ), - ATTR32_VV ( VDIVU_VV, VDIVU_VR, RVANYV, "vdivu" ), - ATTR32_VV ( VDIV_VV, VDIV_VR, RVANYV, "vdiv" ), - ATTR32_VV ( VREMU_VV, VREMU_VR, RVANYV, "vremu" ), - ATTR32_VV ( VREM_VV, VREM_VR, RVANYV, "vrem" ), - ATTR32_VS ( VREDSUM_VS, VREDSUM_VS, RVANYV, "vredsum" ), - ATTR32_VS ( VREDAND_VS, VREDAND_VS, RVANYV, "vredand" ), - ATTR32_VS ( VREDOR_VS, VREDOR_VS, RVANYV, "vredor" ), - ATTR32_VS ( VREDXOR_VS, VREDXOR_VS, RVANYV, "vredxor" ), - ATTR32_VS ( VREDMINU_VS, VREDMINU_VS, RVANYV, "vredminu" ), - ATTR32_VS ( VREDMIN_VS, VREDMIN_VS, RVANYV, "vredmin" ), - ATTR32_VS ( VREDMAXU_VS, VREDMAXU_VS, RVANYV, "vredmaxu" ), - ATTR32_VS ( VREDMAX_VS, VREDMAX_VS, RVANYV, "vredmax" ), - ATTR32_MM ( VMAND_MM, VMAND_MM, RVANYV, "vmand" ), - ATTR32_MM ( VMNAND_MM, VMNAND_MM, RVANYV, "vmnand" ), - ATTR32_MM ( VMANDNOT_MM, VMANDNOT_MM, RVANYV, "vmandnot" ), - ATTR32_MM ( VMXOR_MM, VMXOR_MM, RVANYV, "vmxor" ), - ATTR32_MM ( VMOR_MM, VMOR_MM, RVANYV, "vmor" ), - ATTR32_MM ( VMNOR_MM, VMNOR_MM, RVANYV, "vmnor" ), - ATTR32_MM ( VMORNOT_MM, VMORNOT_MM, RVANYV, "vmornot" ), - ATTR32_MM ( VMXNOR_MM, VMXNOR_MM, RVANYV, "vmxnor" ), - ATTR32_MX ( VPOPC_M, VPOPC_M, RVANYV, "vpopc" ), - ATTR32_MX ( VFIRST_M, VFIRST_M, RVANYV, "vfirst" ), - ATTR32_MV ( VMSBF_M, VMSBF_M, RVANYV, "vmsbf" ), - ATTR32_MV ( VMSIF_M, VMSIF_M, RVANYV, "vmsif" ), - ATTR32_MV ( VMSOF_M, VMSOF_M, RVANYV, "vmsof" ), - ATTR32_MV ( VIOTA_M, VIOTA_M, RVANYV, "viota" ), - ATTR32_VID ( VID_V, VID_V, RVANYV, "vid" ), - ATTR32_VMV_X_S ( VMV_X_S, VEXT_X_V, RVANYV, "vmv.x.s" ), - ATTR32_VEXT ( VEXT_X_V, VEXT_X_V, RVANYV, "vext.x" ), - ATTR32_VM ( VCOMPRESS_VM, VCOMPRESS_VM, RVANYV, "vcompress"), + ATTR32_VV ( VWADD_VV, VWADD_VR, RVANYV, "vwadd" ), + ATTR32_VV ( VWADDU_VV, VWADDU_VR, RVANYV, "vwaddu" ), + ATTR32_VV ( VWSUB_VV, VWSUB_VR, RVANYV, "vwsub" ), + ATTR32_VV ( VWSUBU_VV, VWSUBU_VR, RVANYV, "vwsubu" ), + ATTR32_WV ( VWADD_WV, VWADD_WR, RVANYV, "vwadd" ), + ATTR32_WV ( VWADDU_WV, VWADDU_WR, RVANYV, "vwaddu" ), + ATTR32_WV ( VWSUB_WV, VWSUB_WR, RVANYV, "vwsub" ), + ATTR32_WV ( VWSUBU_WV, VWSUBU_WR, RVANYV, "vwsubu" ), + ATTR32_VV ( VMUL_VV, VMUL_VR, RVANYV, "vmul" ), + ATTR32_VV ( VMULH_VV, VMULH_VR, RVANYV, "vmulh" ), + ATTR32_VV ( VMULHU_VV, VMULHU_VR, RVANYV, "vmulhu" ), + ATTR32_VV ( VMULHSU_VV, VMULHSU_VR, RVANYV, "vmulhsu" ), + ATTR32_VV ( VWMUL_VV, VWMUL_VR, RVANYV, "vwmul" ), + ATTR32_VV ( VWMULU_VV, VWMULU_VR, RVANYV, "vwmulu" ), + ATTR32_VV ( VWMULSU_VV, VWMULSU_VR, RVANYV, "vwmulsu" ), + ATTR32_VV3 ( VMACC_VV, VMACC_VR, RVANYV, "vmacc" ), + ATTR32_VV3 ( VNMSAC_VV, VNMSAC_VR, RVANYV, "vnmsac" ), + ATTR32_VV3 ( VMADD_VV, VMADD_VR, RVANYV, "vmadd" ), + ATTR32_VV3 ( VNMSUB_VV, VNMSUB_VR, RVANYV, "vnmsub" ), + ATTR32_VV3 ( VWMACCU_VV, VWMACCU_VR, RVANYV, "vwmaccu" ), + ATTR32_VV3 ( VWMACC_VV, VWMACC_VR, RVANYV, "vwmacc" ), + ATTR32_VV3 ( VWMACCSU_VV, VWMACCSU_VR, RVANYV, "vwmaccsu" ), + ATTR32_VV ( VDIVU_VV, VDIVU_VR, RVANYV, "vdivu" ), + ATTR32_VV ( VDIV_VV, VDIV_VR, RVANYV, "vdiv" ), + ATTR32_VV ( VREMU_VV, VREMU_VR, RVANYV, "vremu" ), + ATTR32_VV ( VREM_VV, VREM_VR, RVANYV, "vrem" ), + ATTR32_VS ( VREDSUM_VS, VREDSUM_VS, RVANYV, "vredsum" ), + ATTR32_VS ( VREDAND_VS, VREDAND_VS, RVANYV, "vredand" ), + ATTR32_VS ( VREDOR_VS, VREDOR_VS, RVANYV, "vredor" ), + ATTR32_VS ( VREDXOR_VS, VREDXOR_VS, RVANYV, "vredxor" ), + ATTR32_VS ( VREDMINU_VS, VREDMINU_VS, RVANYV, "vredminu" ), + ATTR32_VS ( VREDMIN_VS, VREDMIN_VS, RVANYV, "vredmin" ), + ATTR32_VS ( VREDMAXU_VS, VREDMAXU_VS, RVANYV, "vredmaxu" ), + ATTR32_VS ( VREDMAX_VS, VREDMAX_VS, RVANYV, "vredmax" ), + ATTR32_MM ( VMAND_MM, VMAND_MM, RVANYV, "vmand" ), + ATTR32_MM ( VMNAND_MM, VMNAND_MM, RVANYV, "vmnand" ), + ATTR32_MM ( VMANDNOT_MM, VMANDNOT_MM, RVANYV, "vmandnot" ), + ATTR32_MM ( VMXOR_MM, VMXOR_MM, RVANYV, "vmxor" ), + ATTR32_MM ( VMOR_MM, VMOR_MM, RVANYV, "vmor" ), + ATTR32_MM ( VMNOR_MM, VMNOR_MM, RVANYV, "vmnor" ), + ATTR32_MM ( VMORNOT_MM, VMORNOT_MM, RVANYV, "vmornot" ), + ATTR32_MM ( VMXNOR_MM, VMXNOR_MM, RVANYV, "vmxnor" ), + ATTR32_MX ( VPOPC_M, VPOPC_M, RVANYV, "vpopc" ), + ATTR32_MX ( VFIRST_M, VFIRST_M, RVANYV, "vfirst" ), + ATTR32_MV ( VMSBF_M, VMSBF_M, RVANYV, "vmsbf" ), + ATTR32_MV ( VMSIF_M, VMSIF_M, RVANYV, "vmsif" ), + ATTR32_MV ( VMSOF_M, VMSOF_M, RVANYV, "vmsof" ), + ATTR32_MV ( VIOTA_M, VIOTA_M, RVANYV, "viota" ), + ATTR32_VID ( VID_V, VID_V, RVANYV, "vid" ), + ATTR32_VMV_X_S ( VMV_X_S, VEXT_X_V, RVANYV, "vmv.x.s" ), + ATTR32_VEXT ( VEXT_X_V, VEXT_X_V, RVANYV, "vext.x" ), + ATTR32_VM ( VCOMPRESS_VM, VCOMPRESS_VM, RVANYV, "vcompress"), // V-extension IVI-type instructions - ATTR32_VI ( VADD_VI, VADD_VI, RVANYV, "vadd" ), - ATTR32_VI ( VRSUB_VI, VRSUB_VI, RVANYV, "vrsub" ), - ATTR32_VI ( VAND_VI, VAND_VI, RVANYV, "vand" ), - ATTR32_VI ( VOR_VI, VOR_VI, RVANYV, "vor" ), - ATTR32_VI ( VXOR_VI, VXOR_VI, RVANYV, "vxor" ), - ATTR32_VU ( VRGATHER_VI, VRGATHER_VI, RVANYV, "vrgather" ), - ATTR32_VU ( VSLIDEUP_VI, VSLIDEUP_VI, RVANYV, "vslideup" ), - ATTR32_VU ( VSLIDEDOWN_VI, VSLIDEDOWN_VI, RVANYV, "vslidedown"), - ATTR32_VIM_CIN ( VADC_VI, VADC_VI, RVANYV, "vadc" ), - ATTR32_VIM_CIN ( VMADC_VI, VMADC_VI, RVANYV, "vmadc" ), - ATTR32_VIM ( VMERGE_VI, VMERGE_VI, RVANYV, "vmerge" ), - ATTR32_VMV_V_I ( VMV_V_I, VMERGE_VI, RVANYV, "vmv.v.i" ), - ATTR32_VI ( VSEQ_VI, VSEQ_VI, RVANYV, "vmseq" ), - ATTR32_VI ( VSNE_VI, VSNE_VI, RVANYV, "vmsne" ), - ATTR32_VI ( VSLEU_VI, VSLEU_VI, RVANYV, "vmsleu" ), - ATTR32_VI ( VSLE_VI, VSLE_VI, RVANYV, "vmsle" ), - ATTR32_VI ( VSGTU_VI, VSGTU_VI, RVANYV, "vmsgtu" ), - ATTR32_VI ( VSGT_VI, VSGT_VI, RVANYV, "vmsgt" ), - ATTR32_VI ( VSADDU_VI, VSADDU_VI, RVANYV, "vsaddu" ), - ATTR32_VI ( VSADD_VI, VSADD_VI, RVANYV, "vsadd" ), - ATTR32_VI ( VAADD_VI, VAADD_VI, RVANYV, "vaadd" ), - ATTR32_VU ( VSLL_VI, VSLL_VI, RVANYV, "vsll" ), - ATTR32_VMVR ( VMVR_VI, VMVR_VI, RVANYV, "vmv" ), - ATTR32_VU ( VSRL_VI, VSRL_VI, RVANYV, "vsrl" ), - ATTR32_VU ( VSRA_VI, VSRA_VI, RVANYV, "vsra" ), - ATTR32_VU ( VSSRL_VI, VSSRL_VI, RVANYV, "vssrl" ), - ATTR32_VU ( VSSRA_VI, VSSRA_VI, RVANYV, "vssra" ), - ATTR32_VUN ( VNSRL_VI, VNSRL_VI, RVANYV, "vnsrl" ), - ATTR32_VUN ( VNSRA_VI, VNSRA_VI, RVANYV, "vnsra" ), - ATTR32_VUN ( VNCLIPU_VI, VNCLIPU_VI, RVANYV, "vnclipu" ), - ATTR32_VUN ( VNCLIP_VI, VNCLIP_VI, RVANYV, "vnclip" ), + ATTR32_VI ( VADD_VI, VADD_VI, RVANYV, "vadd" ), + ATTR32_VI ( VRSUB_VI, VRSUB_VI, RVANYV, "vrsub" ), + ATTR32_VI ( VAND_VI, VAND_VI, RVANYV, "vand" ), + ATTR32_VI ( VOR_VI, VOR_VI, RVANYV, "vor" ), + ATTR32_VI ( VXOR_VI, VXOR_VI, RVANYV, "vxor" ), + ATTR32_VU ( VRGATHER_VI, VRGATHER_VI, RVANYV, "vrgather" ), + ATTR32_VU ( VSLIDEUP_VI, VSLIDEUP_VI, RVANYV, "vslideup" ), + ATTR32_VU ( VSLIDEDOWN_VI, VSLIDEDOWN_VI, RVANYV, "vslidedown"), + ATTR32_VIM_CIN ( VADC_VI, VADC_VI, RVANYV, "vadc" ), + ATTR32_VIM_CIN ( VMADC_VI, VMADC_VI, RVANYV, "vmadc" ), + ATTR32_VIM ( VMERGE_VI, VMERGE_VI, RVANYV, "vmerge" ), + ATTR32_VMV_V_I ( VMV_V_I, VMERGE_VI, RVANYV, "vmv.v.i" ), + ATTR32_VI ( VSEQ_VI, VSEQ_VI, RVANYV, "vmseq" ), + ATTR32_VI ( VSNE_VI, VSNE_VI, RVANYV, "vmsne" ), + ATTR32_VI ( VSLEU_VI, VSLEU_VI, RVANYV, "vmsleu" ), + ATTR32_VI ( VSLE_VI, VSLE_VI, RVANYV, "vmsle" ), + ATTR32_VI ( VSGTU_VI, VSGTU_VI, RVANYV, "vmsgtu" ), + ATTR32_VI ( VSGT_VI, VSGT_VI, RVANYV, "vmsgt" ), + ATTR32_VI ( VSADDU_VI, VSADDU_VI, RVANYV, "vsaddu" ), + ATTR32_VI ( VSADD_VI, VSADD_VI, RVANYV, "vsadd" ), + ATTR32_VI ( VAADD_VI, VAADD_VI, RVANYV, "vaadd" ), + ATTR32_VU ( VSLL_VI, VSLL_VI, RVANYV, "vsll" ), + ATTR32_VMVR ( VMVR_VI, VMVR_VI, RVANYV, "vmv" ), + ATTR32_VU ( VSRL_VI, VSRL_VI, RVANYV, "vsrl" ), + ATTR32_VU ( VSRA_VI, VSRA_VI, RVANYV, "vsra" ), + ATTR32_VU ( VSSRL_VI, VSSRL_VI, RVANYV, "vssrl" ), + ATTR32_VU ( VSSRA_VI, VSSRA_VI, RVANYV, "vssra" ), + ATTR32_VUN ( VNSRL_VI, VNSRL_VI, RVANYV, "vnsrl" ), + ATTR32_VUN ( VNSRA_VI, VNSRA_VI, RVANYV, "vnsra" ), + ATTR32_VUN ( VNCLIPU_VI, VNCLIPU_VI, RVANYV, "vnclipu" ), + ATTR32_VUN ( VNCLIP_VI, VNCLIP_VI, RVANYV, "vnclip" ), // V-extension IVX-type instructions - ATTR32_VX ( VADD_VX, VADD_VR, RVANYV, "vadd" ), - ATTR32_VX ( VSUB_VX, VSUB_VR, RVANYV, "vsub" ), - ATTR32_VX ( VRSUB_VX, VRSUB_VR, RVANYV, "vrsub" ), - ATTR32_VX ( VMINU_VX, VMINU_VR, RVANYV, "vminu" ), - ATTR32_VX ( VMIN_VX, VMIN_VR, RVANYV, "vmin" ), - ATTR32_VX ( VMAXU_VX, VMAXU_VR, RVANYV, "vmaxu" ), - ATTR32_VX ( VMAX_VX, VMAX_VR, RVANYV, "vmax" ), - ATTR32_VX ( VAND_VX, VAND_VR, RVANYV, "vand" ), - ATTR32_VX ( VOR_VX, VOR_VR, RVANYV, "vor" ), - ATTR32_VX ( VXOR_VX, VXOR_VR, RVANYV, "vxor" ), - ATTR32_VX ( VRGATHER_VX, VRGATHER_VR, RVANYV, "vrgather" ), - ATTR32_VX ( VSLIDEUP_VX, VSLIDEUP_VR, RVANYV, "vslideup" ), - ATTR32_VX ( VSLIDEDOWN_VX, VSLIDEDOWN_VR, RVANYV, "vslidedown"), - ATTR32_VXM_CIN ( VADC_VX, VADC_VR, RVANYV, "vadc" ), - ATTR32_VXM_CIN ( VMADC_VX, VMADC_VR, RVANYV, "vmadc" ), - ATTR32_VXM_CIN ( VSBC_VX, VSBC_VR, RVANYV, "vsbc" ), - ATTR32_VXM_CIN ( VMSBC_VX, VMSBC_VR, RVANYV, "vmsbc" ), - ATTR32_VXM ( VMERGE_VX, VMERGE_VR, RVANYV, "vmerge" ), - ATTR32_VMV_V_X ( VMV_V_X, VMERGE_VR, RVANYV, "vmv.v.x" ), - ATTR32_VX ( VSEQ_VX, VSEQ_VR, RVANYV, "vmseq" ), - ATTR32_VX ( VSNE_VX, VSNE_VR, RVANYV, "vmsne" ), - ATTR32_VX ( VSLTU_VX, VSLTU_VR, RVANYV, "vmsltu" ), - ATTR32_VX ( VSLT_VX, VSLT_VR, RVANYV, "vmslt" ), - ATTR32_VX ( VSLEU_VX, VSLEU_VR, RVANYV, "vmsleu" ), - ATTR32_VX ( VSLE_VX, VSLE_VR, RVANYV, "vmsle" ), - ATTR32_VX ( VSGTU_VX, VSGTU_VR, RVANYV, "vmsgtu" ), - ATTR32_VX ( VSGT_VX, VSGT_VR, RVANYV, "vmsgt" ), - ATTR32_VX ( VSADDU_VX, VSADDU_VR, RVANYV, "vsaddu" ), - ATTR32_VX ( VSADD_VX, VSADD_VR, RVANYV, "vsadd" ), - ATTR32_VX ( VSSUBU_VX, VSSUBU_VR, RVANYV, "vssubu" ), - ATTR32_VX ( VSSUB_VX, VSSUB_VR, RVANYV, "vssub" ), - ATTR32_VX ( VAADDU_VX, VAADDU_VR, RVANYV, "vaaddu" ), - ATTR32_VX ( VAADD_VX, VAADD_VR, RVANYV, "vaadd" ), - ATTR32_VX ( VSLL_VX, VSLL_VR, RVANYV, "vsll" ), - ATTR32_VX ( VASUBU_VX, VASUBU_VR, RVANYV, "vasubu" ), - ATTR32_VX ( VASUB_VX, VASUB_VR, RVANYV, "vasub" ), - ATTR32_VX ( VSMUL_VX, VSMUL_VR, RVANYV, "vsmul" ), - ATTR32_VX ( VSRL_VX, VSRL_VR, RVANYV, "vsrl" ), - ATTR32_VX ( VSRA_VX, VSRA_VR, RVANYV, "vsra" ), - ATTR32_VX ( VSSRL_VX, VSSRL_VR, RVANYV, "vssrl" ), - ATTR32_VX ( VSSRA_VX, VSSRA_VR, RVANYV, "vssra" ), - ATTR32_VXN ( VNSRL_VX, VNSRL_VR, RVANYV, "vnsrl" ), - ATTR32_VXN ( VNSRA_VX, VNSRA_VR, RVANYV, "vnsra" ), - ATTR32_VXN ( VNCLIPU_VX, VNCLIPU_VR, RVANYV, "vnclipu" ), - ATTR32_VXN ( VNCLIP_VX, VNCLIP_VR, RVANYV, "vnclip" ), - ATTR32_VX3 ( VWSMACCU_VX, VWSMACCU_VR, RVANYV, "vwsmaccu" ), - ATTR32_VX3 ( VWSMACC_VX, VWSMACC_VR, RVANYV, "vwsmacc" ), - ATTR32_VX3 ( VWSMACCSU_VX, VWSMACCSU_VR, RVANYV, "vwsmaccsu" ), - ATTR32_VX3 ( VWSMACCUS_VX, VWSMACCUS_VR, RVANYV, "vwsmaccus" ), - ATTR32_VX3 ( VQMACCU_VX, VQMACCU_VR, RVANYV, "vqmaccu" ), - ATTR32_VX3 ( VQMACC_VX, VQMACC_VR, RVANYV, "vqmacc" ), - ATTR32_VX3 ( VQMACCSU_VX, VQMACCSU_VR, RVANYV, "vqmaccsu" ), - ATTR32_VX3 ( VQMACCUS_VX, VQMACCUS_VR, RVANYV, "vqmaccus" ), + ATTR32_VX ( VADD_VX, VADD_VR, RVANYV, "vadd" ), + ATTR32_VX ( VSUB_VX, VSUB_VR, RVANYV, "vsub" ), + ATTR32_VX ( VRSUB_VX, VRSUB_VR, RVANYV, "vrsub" ), + ATTR32_VX ( VMINU_VX, VMINU_VR, RVANYV, "vminu" ), + ATTR32_VX ( VMIN_VX, VMIN_VR, RVANYV, "vmin" ), + ATTR32_VX ( VMAXU_VX, VMAXU_VR, RVANYV, "vmaxu" ), + ATTR32_VX ( VMAX_VX, VMAX_VR, RVANYV, "vmax" ), + ATTR32_VX ( VAND_VX, VAND_VR, RVANYV, "vand" ), + ATTR32_VX ( VOR_VX, VOR_VR, RVANYV, "vor" ), + ATTR32_VX ( VXOR_VX, VXOR_VR, RVANYV, "vxor" ), + ATTR32_VX ( VRGATHER_VX, VRGATHER_VR, RVANYV, "vrgather" ), + ATTR32_VX ( VSLIDEUP_VX, VSLIDEUP_VR, RVANYV, "vslideup" ), + ATTR32_VX ( VSLIDEDOWN_VX, VSLIDEDOWN_VR, RVANYV, "vslidedown"), + ATTR32_VXM_CIN ( VADC_VX, VADC_VR, RVANYV, "vadc" ), + ATTR32_VXM_CIN ( VMADC_VX, VMADC_VR, RVANYV, "vmadc" ), + ATTR32_VXM_CIN ( VSBC_VX, VSBC_VR, RVANYV, "vsbc" ), + ATTR32_VXM_CIN ( VMSBC_VX, VMSBC_VR, RVANYV, "vmsbc" ), + ATTR32_VXM ( VMERGE_VX, VMERGE_VR, RVANYV, "vmerge" ), + ATTR32_VMV_V_X ( VMV_V_X, VMERGE_VR, RVANYV, "vmv.v.x" ), + ATTR32_VX ( VSEQ_VX, VSEQ_VR, RVANYV, "vmseq" ), + ATTR32_VX ( VSNE_VX, VSNE_VR, RVANYV, "vmsne" ), + ATTR32_VX ( VSLTU_VX, VSLTU_VR, RVANYV, "vmsltu" ), + ATTR32_VX ( VSLT_VX, VSLT_VR, RVANYV, "vmslt" ), + ATTR32_VX ( VSLEU_VX, VSLEU_VR, RVANYV, "vmsleu" ), + ATTR32_VX ( VSLE_VX, VSLE_VR, RVANYV, "vmsle" ), + ATTR32_VX ( VSGTU_VX, VSGTU_VR, RVANYV, "vmsgtu" ), + ATTR32_VX ( VSGT_VX, VSGT_VR, RVANYV, "vmsgt" ), + ATTR32_VX ( VSADDU_VX, VSADDU_VR, RVANYV, "vsaddu" ), + ATTR32_VX ( VSADD_VX, VSADD_VR, RVANYV, "vsadd" ), + ATTR32_VX ( VSSUBU_VX, VSSUBU_VR, RVANYV, "vssubu" ), + ATTR32_VX ( VSSUB_VX, VSSUB_VR, RVANYV, "vssub" ), + ATTR32_VX ( VAADDU_VX, VAADDU_VR, RVANYV, "vaaddu" ), + ATTR32_VX ( VAADD_VX, VAADD_VR, RVANYV, "vaadd" ), + ATTR32_VX ( VSLL_VX, VSLL_VR, RVANYV, "vsll" ), + ATTR32_VX ( VASUBU_VX, VASUBU_VR, RVANYV, "vasubu" ), + ATTR32_VX ( VASUB_VX, VASUB_VR, RVANYV, "vasub" ), + ATTR32_VX ( VSMUL_VX, VSMUL_VR, RVANYV, "vsmul" ), + ATTR32_VX ( VSRL_VX, VSRL_VR, RVANYV, "vsrl" ), + ATTR32_VX ( VSRA_VX, VSRA_VR, RVANYV, "vsra" ), + ATTR32_VX ( VSSRL_VX, VSSRL_VR, RVANYV, "vssrl" ), + ATTR32_VX ( VSSRA_VX, VSSRA_VR, RVANYV, "vssra" ), + ATTR32_VXN ( VNSRL_VX, VNSRL_VR, RVANYV, "vnsrl" ), + ATTR32_VXN ( VNSRA_VX, VNSRA_VR, RVANYV, "vnsra" ), + ATTR32_VXN ( VNCLIPU_VX, VNCLIPU_VR, RVANYV, "vnclipu" ), + ATTR32_VXN ( VNCLIP_VX, VNCLIP_VR, RVANYV, "vnclip" ), + ATTR32_VX3 ( VWSMACCU_VX, VWSMACCU_VR, RVANYV, "vwsmaccu" ), + ATTR32_VX3 ( VWSMACC_VX, VWSMACC_VR, RVANYV, "vwsmacc" ), + ATTR32_VX3 ( VWSMACCSU_VX, VWSMACCSU_VR, RVANYV, "vwsmaccsu" ), + ATTR32_VX3 ( VWSMACCUS_VX, VWSMACCUS_VR, RVANYV, "vwsmaccus" ), + ATTR32_VX3 ( VQMACCU_VX, VQMACCU_VR, RVANYV, "vqmaccu" ), + ATTR32_VX3 ( VQMACC_VX, VQMACC_VR, RVANYV, "vqmacc" ), + ATTR32_VX3 ( VQMACCSU_VX, VQMACCSU_VR, RVANYV, "vqmaccsu" ), + ATTR32_VX3 ( VQMACCUS_VX, VQMACCUS_VR, RVANYV, "vqmaccus" ), // V-extension FVF-type instructions - ATTR32_VF ( VFADD_VF, VFADD_VR, RVANYV, "vfadd" ), - ATTR32_VF ( VFSUB_VF, VFSUB_VR, RVANYV, "vfsub" ), - ATTR32_VF ( VFMIN_VF, VFMIN_VR, RVANYV, "vfmin" ), - ATTR32_VF ( VFMAX_VF, VFMAX_VR, RVANYV, "vfmax" ), - ATTR32_VF ( VFSGNJ_VF, VFSGNJ_VR, RVANYV, "vfsgnj" ), - ATTR32_VF ( VFSGNJN_VF, VFSGNJN_VR, RVANYV, "vfsgnjn" ), - ATTR32_VF ( VFSGNJX_VF, VFSGNJX_VR, RVANYV, "vfsgnjx" ), - ATTR32_VFMV_S_F ( VFMV_S_F, VFMV_S_F, RVANYV, "vfmv.s.f"), - ATTR32_VFM ( VFMERGE_VF, VFMERGE_VR, RVANYV, "vfmerge" ), - ATTR32_VFMV_V_F ( VFMV_V_F, VFMERGE_VR, RVANYV, "vfmv.v.f"), - ATTR32_VF ( VFEQ_VF, VFEQ_VR, RVANYV, "vmfeq" ), - ATTR32_VF ( VFLTE_VF, VFLE_VR, RVANYV, "vmfle" ), - ATTR32_VF ( VFORD_VF, VFORD_VR, RVANYV, "vmford" ), - ATTR32_VF ( VFLT_VF, VFLT_VR, RVANYV, "vmflt" ), - ATTR32_VF ( VFNE_VF, VFNE_VR, RVANYV, "vmfne" ), - ATTR32_VF ( VFGT_VF, VFGT_VR, RVANYV, "vmfgt" ), - ATTR32_VF ( VFGTE_VF, VFGE_VR, RVANYV, "vmfge" ), - ATTR32_VF ( VFDIV_VF, VFDIV_VR, RVANYV, "vfdiv" ), - ATTR32_VF ( VFRDIV_VF, VFRDIV_VR, RVANYV, "vfrdiv" ), - ATTR32_VF ( VFMUL_VF, VFMUL_VR, RVANYV, "vfmul" ), - ATTR32_VF ( VFRSUB_VF, VFRSUB_VR, RVANYV, "vfrsub" ), - ATTR32_VF3 ( VFMADD_VF, VFMADD_VR, RVANYV, "vfmadd" ), - ATTR32_VF3 ( VFNMADD_VF, VFNMADD_VR, RVANYV, "vfnmadd" ), - ATTR32_VF3 ( VFMSUB_VF, VFMSUB_VR, RVANYV, "vfmsub" ), - ATTR32_VF3 ( VFNMSUB_VF, VFNMSUB_VR, RVANYV, "vfnmsub" ), - ATTR32_VF3 ( VFMACC_VF, VFMACC_VR, RVANYV, "vfmacc" ), - ATTR32_VF3 ( VFNMACC_VF, VFNMACC_VR, RVANYV, "vfnmacc" ), - ATTR32_VF3 ( VFMSAC_VF, VFMSAC_VR, RVANYV, "vfmsac" ), - ATTR32_VF3 ( VFNMSAC_VF, VFNMSAC_VR, RVANYV, "vfnmsac" ), - ATTR32_VF ( VFWADD_VF, VFWADD_VR, RVANYV, "vfwadd" ), - ATTR32_VF ( VFWSUB_VF, VFWSUB_VR, RVANYV, "vfwsub" ), - ATTR32_WF ( VFWADD_WF, VFWADD_WR, RVANYV, "vfwadd" ), - ATTR32_WF ( VFWSUB_WF, VFWSUB_WR, RVANYV, "vfwsub" ), - ATTR32_VF ( VFWMUL_VF, VFWMUL_VR, RVANYV, "vfwmul" ), - ATTR32_VF3 ( VFWMACC_VF, VFWMACC_VR, RVANYV, "vfwmacc" ), - ATTR32_VF3 ( VFWNMACC_VF, VFWNMACC_VR, RVANYV, "vfwnmacc"), - ATTR32_VF3 ( VFWMSAC_VF, VFWMSAC_VR, RVANYV, "vfwmsac" ), - ATTR32_VF3 ( VFWNMSAC_VF, VFWNMSAC_VR, RVANYV, "vfwnmsac"), + ATTR32_VF ( VFADD_VF, VFADD_VR, RVANYV, "vfadd" ), + ATTR32_VF ( VFSUB_VF, VFSUB_VR, RVANYV, "vfsub" ), + ATTR32_VF ( VFMIN_VF, VFMIN_VR, RVANYV, "vfmin" ), + ATTR32_VF ( VFMAX_VF, VFMAX_VR, RVANYV, "vfmax" ), + ATTR32_VF ( VFSGNJ_VF, VFSGNJ_VR, RVANYV, "vfsgnj" ), + ATTR32_VF ( VFSGNJN_VF, VFSGNJN_VR, RVANYV, "vfsgnjn" ), + ATTR32_VF ( VFSGNJX_VF, VFSGNJX_VR, RVANYV, "vfsgnjx" ), + ATTR32_VF ( VFSLIDE1UP_VF, VFSLIDE1UP_VF, RVANYV, "vfslide1up" ), + ATTR32_VF (VFSLIDE1DOWN_VF, VFSLIDE1DOWN_VF, RVANYV, "vfslide1down"), + ATTR32_VF ( VFSGNJX_VF, VFSGNJX_VR, RVANYV, "vfsgnjx" ), + ATTR32_VFMV_S_F ( VFMV_S_F, VFMV_S_F, RVANYV, "vfmv.s.f" ), + ATTR32_VFM ( VFMERGE_VF, VFMERGE_VR, RVANYV, "vfmerge" ), + ATTR32_VFMV_V_F ( VFMV_V_F, VFMERGE_VR, RVANYV, "vfmv.v.f" ), + ATTR32_VF ( VFEQ_VF, VFEQ_VR, RVANYV, "vmfeq" ), + ATTR32_VF ( VFLTE_VF, VFLE_VR, RVANYV, "vmfle" ), + ATTR32_VF ( VFORD_VF, VFORD_VR, RVANYV, "vmford" ), + ATTR32_VF ( VFLT_VF, VFLT_VR, RVANYV, "vmflt" ), + ATTR32_VF ( VFNE_VF, VFNE_VR, RVANYV, "vmfne" ), + ATTR32_VF ( VFGT_VF, VFGT_VR, RVANYV, "vmfgt" ), + ATTR32_VF ( VFGTE_VF, VFGE_VR, RVANYV, "vmfge" ), + ATTR32_VF ( VFDIV_VF, VFDIV_VR, RVANYV, "vfdiv" ), + ATTR32_VF ( VFRDIV_VF, VFRDIV_VR, RVANYV, "vfrdiv" ), + ATTR32_VF ( VFMUL_VF, VFMUL_VR, RVANYV, "vfmul" ), + ATTR32_VF ( VFRSUB_VF, VFRSUB_VR, RVANYV, "vfrsub" ), + ATTR32_VF3 ( VFMADD_VF, VFMADD_VR, RVANYV, "vfmadd" ), + ATTR32_VF3 ( VFNMADD_VF, VFNMADD_VR, RVANYV, "vfnmadd" ), + ATTR32_VF3 ( VFMSUB_VF, VFMSUB_VR, RVANYV, "vfmsub" ), + ATTR32_VF3 ( VFNMSUB_VF, VFNMSUB_VR, RVANYV, "vfnmsub" ), + ATTR32_VF3 ( VFMACC_VF, VFMACC_VR, RVANYV, "vfmacc" ), + ATTR32_VF3 ( VFNMACC_VF, VFNMACC_VR, RVANYV, "vfnmacc" ), + ATTR32_VF3 ( VFMSAC_VF, VFMSAC_VR, RVANYV, "vfmsac" ), + ATTR32_VF3 ( VFNMSAC_VF, VFNMSAC_VR, RVANYV, "vfnmsac" ), + ATTR32_VF ( VFWADD_VF, VFWADD_VR, RVANYV, "vfwadd" ), + ATTR32_VF ( VFWSUB_VF, VFWSUB_VR, RVANYV, "vfwsub" ), + ATTR32_WF ( VFWADD_WF, VFWADD_WR, RVANYV, "vfwadd" ), + ATTR32_WF ( VFWSUB_WF, VFWSUB_WR, RVANYV, "vfwsub" ), + ATTR32_VF ( VFWMUL_VF, VFWMUL_VR, RVANYV, "vfwmul" ), + ATTR32_VF3 ( VFWMACC_VF, VFWMACC_VR, RVANYV, "vfwmacc" ), + ATTR32_VF3 ( VFWNMACC_VF, VFWNMACC_VR, RVANYV, "vfwnmacc" ), + ATTR32_VF3 ( VFWMSAC_VF, VFWMSAC_VR, RVANYV, "vfwmsac" ), + ATTR32_VF3 ( VFWNMSAC_VF, VFWNMSAC_VR, RVANYV, "vfwnmsac" ), // V-extension MVX-type instructions - ATTR32_VMV_S_X ( VMV_S_X, VMV_S_X, RVANYV, "vmv.s.x" ), - ATTR32_VX ( VSLIDE1UP_VX, VSLIDE1UP_VX, RVANYV, "vslide1up" ), - ATTR32_VX (VSLIDE1DOWN_VX, VSLIDE1DOWN_VX, RVANYV, "vslide1down"), - ATTR32_VX ( VDIVU_VX, VDIVU_VR, RVANYV, "vdivu" ), - ATTR32_VX ( VDIV_VX, VDIV_VR, RVANYV, "vdiv" ), - ATTR32_VX ( VREMU_VX, VREMU_VR, RVANYV, "vremu" ), - ATTR32_VX ( VREM_VX, VREM_VR, RVANYV, "vrem" ), - ATTR32_VX ( VMULHU_VX, VMULHU_VR, RVANYV, "vmulhu" ), - ATTR32_VX ( VMUL_VX, VMUL_VR, RVANYV, "vmul" ), - ATTR32_VX ( VMULHSU_VX, VMULHSU_VR, RVANYV, "vmulhsu" ), - ATTR32_VX ( VMULH_VX, VMULH_VR, RVANYV, "vmulh" ), - ATTR32_VX3 ( VMADD_VX, VMADD_VR, RVANYV, "vmadd" ), - ATTR32_VX3 ( VNMSUB_VX, VNMSUB_VR, RVANYV, "vnmsub" ), - ATTR32_VX3 ( VMACC_VX, VMACC_VR, RVANYV, "vmacc" ), - ATTR32_VX3 ( VNMSAC_VX, VNMSAC_VR, RVANYV, "vnmsac" ), - ATTR32_VX ( VWADDU_VX, VWADDU_VR, RVANYV, "vwaddu" ), - ATTR32_VX ( VWADD_VX, VWADD_VR, RVANYV, "vwadd" ), - ATTR32_VX ( VWSUBU_VX, VWSUBU_VR, RVANYV, "vwsubu" ), - ATTR32_VX ( VWSUB_VX, VWSUB_VR, RVANYV, "vwsub" ), - ATTR32_WX ( VWADDU_WX, VWADDU_WR, RVANYV, "vwaddu" ), - ATTR32_WX ( VWADD_WX, VWADD_WR, RVANYV, "vwadd" ), - ATTR32_WX ( VWSUBU_WX, VWSUBU_WR, RVANYV, "vwsubu" ), - ATTR32_WX ( VWSUB_WX, VWSUB_WR, RVANYV, "vwsub" ), - ATTR32_VX ( VWMULU_VX, VWMULU_VR, RVANYV, "vwmulu" ), - ATTR32_VX ( VWMULSU_VX, VWMULSU_VR, RVANYV, "vwmulsu" ), - ATTR32_VX ( VWMUL_VX, VWMUL_VR, RVANYV, "vwmul" ), - ATTR32_VX3 ( VWMACCU_VX, VWMACCU_VR, RVANYV, "vwmaccu" ), - ATTR32_VX3 ( VWMACC_VX, VWMACC_VR, RVANYV, "vwmacc" ), - ATTR32_VX3 ( VWMACCSU_VX, VWMACCSU_VR, RVANYV, "vwmaccsu" ), - ATTR32_VX3 ( VWMACCUS_VX, VWMACCUS_VR, RVANYV, "vwmaccus" ), + ATTR32_VMV_S_X ( VMV_S_X, VMV_S_X, RVANYV, "vmv.s.x" ), + ATTR32_VX ( VSLIDE1UP_VX, VSLIDE1UP_VX, RVANYV, "vslide1up" ), + ATTR32_VX ( VSLIDE1DOWN_VX, VSLIDE1DOWN_VX, RVANYV, "vslide1down"), + ATTR32_VEXT_V ( VZEXT_V, VZEXT_V, RVANYV, "vzext" ), + ATTR32_VEXT_V ( VSEXT_V, VSEXT_V, RVANYV, "vsext" ), + ATTR32_VX ( VDIVU_VX, VDIVU_VR, RVANYV, "vdivu" ), + ATTR32_VX ( VDIV_VX, VDIV_VR, RVANYV, "vdiv" ), + ATTR32_VX ( VREMU_VX, VREMU_VR, RVANYV, "vremu" ), + ATTR32_VX ( VREM_VX, VREM_VR, RVANYV, "vrem" ), + ATTR32_VX ( VMULHU_VX, VMULHU_VR, RVANYV, "vmulhu" ), + ATTR32_VX ( VMUL_VX, VMUL_VR, RVANYV, "vmul" ), + ATTR32_VX ( VMULHSU_VX, VMULHSU_VR, RVANYV, "vmulhsu" ), + ATTR32_VX ( VMULH_VX, VMULH_VR, RVANYV, "vmulh" ), + ATTR32_VX3 ( VMADD_VX, VMADD_VR, RVANYV, "vmadd" ), + ATTR32_VX3 ( VNMSUB_VX, VNMSUB_VR, RVANYV, "vnmsub" ), + ATTR32_VX3 ( VMACC_VX, VMACC_VR, RVANYV, "vmacc" ), + ATTR32_VX3 ( VNMSAC_VX, VNMSAC_VR, RVANYV, "vnmsac" ), + ATTR32_VX ( VWADDU_VX, VWADDU_VR, RVANYV, "vwaddu" ), + ATTR32_VX ( VWADD_VX, VWADD_VR, RVANYV, "vwadd" ), + ATTR32_VX ( VWSUBU_VX, VWSUBU_VR, RVANYV, "vwsubu" ), + ATTR32_VX ( VWSUB_VX, VWSUB_VR, RVANYV, "vwsub" ), + ATTR32_WX ( VWADDU_WX, VWADDU_WR, RVANYV, "vwaddu" ), + ATTR32_WX ( VWADD_WX, VWADD_WR, RVANYV, "vwadd" ), + ATTR32_WX ( VWSUBU_WX, VWSUBU_WR, RVANYV, "vwsubu" ), + ATTR32_WX ( VWSUB_WX, VWSUB_WR, RVANYV, "vwsub" ), + ATTR32_VX ( VWMULU_VX, VWMULU_VR, RVANYV, "vwmulu" ), + ATTR32_VX ( VWMULSU_VX, VWMULSU_VR, RVANYV, "vwmulsu" ), + ATTR32_VX ( VWMUL_VX, VWMUL_VR, RVANYV, "vwmul" ), + ATTR32_VX3 ( VWMACCU_VX, VWMACCU_VR, RVANYV, "vwmaccu" ), + ATTR32_VX3 ( VWMACC_VX, VWMACC_VR, RVANYV, "vwmacc" ), + ATTR32_VX3 ( VWMACCSU_VX, VWMACCSU_VR, RVANYV, "vwmaccsu" ), + ATTR32_VX3 ( VWMACCUS_VX, VWMACCUS_VR, RVANYV, "vwmaccus" ), // dummy entry for undecoded instruction - ATTR32_LAST ( LAST, LAST, "undef") + ATTR32_LAST ( LAST, LAST, "undef") }; // @@ -2417,11 +2560,17 @@ static vmidDecodeTableP createDecodeTable32(riscvVectVer vect_version) { insertEntries32(table, &decodePre20191004[0]); } - // insert vector-extension-dependent table entries before/after 20191117 - if(vect_version>RVVV_0_8_20191117) { - insertEntries32(table, &decodePost20191117[0]); + // insert vector-extension-dependent table entries introduced with 20191117 + // but deleted after 0.8 + if((vect_version>=RVVV_0_8_20191117) && (vect_version<=RVVV_0_8)) { + insertEntries32(table, &decodeLate08[0]); + } + + // insert vector-extension-dependent table entries before/after 0.8 + if(vect_version<=RVVV_0_8) { + insertEntries32(table, &decodePre09[0]); } else { - insertEntries32(table, &decodePre20191117[0]); + insertEntries32(table, &decodeInitial09[0]); } return table; @@ -3224,6 +3373,36 @@ static riscvFenceDesc getFence(riscvInstrInfoP info, fenceSpec fence) { } +// +// Return EEW encoded in the instruction +// +static Uns32 getEEW(riscvInstrInfoP info, eewSpec eew) { + + Uns32 result = 0; + Uns32 instr = info->instruction; + + // table mapping to vector element bits for vector versions from 0.9 + const static Uns32 mapVectorBits09[16] = { + 8, 0, 0, 0, 0, 16, 32, 64, 128, 0, 0, 0, 0, 256, 512, 1024 + }; + + switch(eew) { + case EEW_NA: + break; + case EEW_14_12: + result = mapVectorBits09[U_14_12(instr)]; + break; + case EEW_28_14_12: + result = mapVectorBits09[(U_28(instr)<<3)+U_14_12(instr)]; + break; + default: + VMI_ABORT("unimplemented case"); // LCOV_EXCL_LINE + break; + } + + return result; +} + // // Return width specifier encoded in the instruction // @@ -3235,8 +3414,11 @@ static Uns32 getMemBits( Uns32 result = 0; Uns32 instr = info->instruction; - // table mapping to vector element bits (NOTE: -1 is SEW) - const static Int8 mapVectorBits[] = {8, 0, 0, 0, 0, 16, 32, -1}; + // table mapping to vector element bits for vector versions before 0.9 + // (NOTE: -1 is SEW) + const static Int8 mapVectorBits08[8] = { + 8, 0, 0, 0, 0, 16, 32, -1 + }; switch(memBits) { case MBS_NA: @@ -3255,7 +3437,13 @@ static Uns32 getMemBits( result = 8<eew; + break; + case MBS_SEW: + result = -1; break; case MBS_W: result = 32; @@ -3286,7 +3474,7 @@ static Bool getUnsExt(riscvInstrInfoP info, unsExtSpec unsExt) { result = U_14(instr); break; case USX_28: - result = !U_28(instr); + result = !U_28(instr) && (info->memBits!=-1); break; default: VMI_ABORT("unimplemented case"); // LCOV_EXCL_LINE @@ -3312,6 +3500,9 @@ static riscvRMDesc getRM(riscvInstrInfoP info, rmSpec rm) { switch(rm) { case RM_NA: break; + case RM_RTZ: + result = RV_RM_RTZ; + break; case RM_ROD: result = RV_RM_ROD; break; @@ -3327,41 +3518,25 @@ static riscvRMDesc getRM(riscvInstrInfoP info, rmSpec rm) { } // -// Return vector VSEW encoded in the instruction +// Return vector type encoded in the instruction // -static Uns8 getVSEW(riscvInstrInfoP info, vsewSpec vsew) { +static riscvVType getVType( + riscvP riscv, + riscvInstrInfoP info, + vtypeSpec vtype +) { + riscvVType result = {0}; + Uns32 instr = info->instruction; - Uns8 result = 0; - Uns32 instr = info->instruction; + switch(vtype) { - switch(vsew) { - case VSEW_NA: - break; - case VSEW_24_22: - result = U_24_22(instr); + case VTYPE_NA: break; - default: - VMI_ABORT("unimplemented case"); // LCOV_EXCL_LINE - break; - } - - return result; -} - -// -// Return vector VLMUL encoded in the instruction -// -static Uns8 getVLMUL(riscvInstrInfoP info, vlmulSpec vlmul) { - Uns8 result = 0; - Uns32 instr = info->instruction; - - switch(vlmul) { - case VLMUL_NA: - break; - case VLMUL_21_20: - result = U_21_20(instr); + case VTYPE_30_20: + result.u32 = U_30_20(instr); break; + default: VMI_ABORT("unimplemented case"); // LCOV_EXCL_LINE break; @@ -3442,6 +3617,28 @@ static Uns32 getNumFields(riscvInstrInfoP info, numFieldsSpec nf) { return result; } +// +// Return EEW divisor specification encoded in the instruction +// +static Uns32 getEEWDivisor(riscvInstrInfoP info, eewDivSpec eewDiv) { + + Uns32 result = 0; + Uns32 instr = info->instruction; + + switch(eewDiv) { + case EEWD_NA: + break; + case EEWD_17_16: + result = 1<<(4-U_17_16(instr)); + break; + default: + VMI_ABORT("unimplemented case"); // LCOV_EXCL_LINE + break; + } + + return result; +} + // // Fix floating point instructions that cannot be determined by decode alone // @@ -3531,6 +3728,7 @@ static void interpretInstruction( info->csrInOp = attrs->csrInOp; // get memory width encoded in instruction (prerequisite for getFWidth) + info->eew = getEEW(info, attrs->eew); info->memBits = getMemBits(riscv, info, attrs->memBits); // get register widths encoded in instruction @@ -3551,12 +3749,12 @@ static void interpretInstruction( info->pred = getFence(info, attrs->pred); info->succ = getFence(info, attrs->succ); info->rm = getRM(info, attrs->rm); - info->vsew = getVSEW(info, attrs->vsew); - info->vlmul = getVLMUL(info, attrs->vlmul); + info->vtype = getVType(riscv, info, attrs->vtype); info->VIType = getVIType(riscv, info, attrs->VIType); info->isWhole = getWholeReg(info, attrs->whole); info->isFF = getFirstFault(info, attrs->ff); info->nf = getNumFields(info, attrs->nf); + info->eewDiv = getEEWDivisor(info, attrs->eewDiv); // fix up floating point pseudo-instructions fixFPPseudoInstructions(info); diff --git a/source/riscvDecodeTypes.h b/source/riscvDecodeTypes.h index 09cbca8..4fc818b 100644 --- a/source/riscvDecodeTypes.h +++ b/source/riscvDecodeTypes.h @@ -394,19 +394,15 @@ typedef enum riscvITypeE { // V-extension FVF-type instructions RV_IT_VFMV_S_F, + RV_IT_VFSLIDE1UP_VF, + RV_IT_VFSLIDE1DOWN_VF, // V-extension MVX-type instructions RV_IT_VMV_S_X, RV_IT_VSLIDE1UP_VX, RV_IT_VSLIDE1DOWN_VX, - RV_IT_VWADDU_VX, - RV_IT_VWADD_VX, - RV_IT_VWSUBU_VX, - RV_IT_VWSUB_VX, - RV_IT_VWADDU_WX, - RV_IT_VWADD_WX, - RV_IT_VWSUBU_WX, - RV_IT_VWSUB_WX, + RV_IT_VZEXT_V, + RV_IT_VSEXT_V, // KEEP LAST RV_IT_LAST @@ -518,6 +514,7 @@ typedef struct riscvInstrInfoS { Bool unsExt; // whether to extend unsigned Bool csrInOp; // whether to emit CSR as part of opcode Uns32 memBits; // load/store size + Uns32 eew; // explicit EEW encoding Uns64 c; // constant value riscvRegDesc r[RV_MAX_AREGS]; // argument registers @@ -528,10 +525,10 @@ typedef struct riscvInstrInfoS { riscvRMDesc rm; // rounding mode riscvCSRUDesc csrUpdate; // CSR update semantics riscvWholeDesc isWhole; // is this a whole-register instruction? + riscvVType vtype; // vector type information Uns32 csr; // CSR index - Uns8 vsew; // vsew value - Uns8 vlmul; // vmul value Uns8 nf; // nf value + Uns8 eewDiv; // explicit EEW divisor Bool isFF; // is this a first-fault instruction? } riscvInstrInfo; diff --git a/source/riscvDisassemble.c b/source/riscvDisassemble.c index 4b3ee12..b3e1337 100644 --- a/source/riscvDisassemble.c +++ b/source/riscvDisassemble.c @@ -117,8 +117,13 @@ static void putInstruction(riscvInstrInfoP info, char **result) { fmt = "%08x "; } + // mask raw instruction pattern to instruction byte size (prevents + // misleading disassembly when compressed instruction encountered by + // processor that does not support such instructions) + Uns32 instruction = info->instruction & ((1ULL<<(info->bytes*8))-1); + // emit basic opcode string - *result += sprintf(*result, fmt, info->instruction); + *result += sprintf(*result, fmt, instruction); } // @@ -272,12 +277,25 @@ static void putOptRM(char **result, riscvRMDesc rm, Bool uncooked) { // // Emit VType argument // -static void putVType(char **result, Uns8 vsew, Uns8 vlmul) { +static void putVType(char **result, riscvP riscv, riscvVType vtype) { + + const char *mulString = vtype.vlmulf ? "mf" : "m"; + Uns32 vlmul = vtype.vlmulf ? 4-vtype.vlmul : vtype.vlmul; + // put common fields putChar(result, 'e'); - putD(result, 8<nf+1); } - // emit size modifier if required - switch(info->memBits) { + if(info->eew) { + + // version 0.9 EEW + putChar(result, 'e'); + if(info->memBits==-1) {putChar(result, 'i');} + putD(result, info->eew); + + } else switch(info->memBits) { + + // version 0.8 memBits case 8: putChar(result, 'b'); break; case 16: putChar(result, 'h'); break; case 32: putChar(result, 'w'); break; @@ -421,6 +447,12 @@ static void putOpcode(char **result, riscvP riscv, riscvInstrInfoP info) { putChar(result, 'm'); } + // add EEW divisor if specified + if(info->eewDiv) { + putChar(result, 'f'); + putD(result, info->eewDiv); + } + // acquire/release modifier suffixes static const char *aqrlDescs[] = { [RV_AQRL_NA] = "", @@ -533,7 +565,7 @@ static void disassembleFormat( break; case EMIT_VTYPE: putUncookedKey(result, " VTYPE", uncooked); - putVType(result, info->vsew, info->vlmul); + putVType(result, riscv, info->vtype); break; case EMIT_RM: putOptMask(result, info->mask, ".t", uncooked); diff --git a/source/riscvDoc.c b/source/riscvDoc.c index 381c3a6..5782eb9 100644 --- a/source/riscvDoc.c +++ b/source/riscvDoc.c @@ -1074,62 +1074,244 @@ void riscvDoc(riscvP rootProcessor) { } //////////////////////////////////////////////////////////////////////// - // VECTOR EXTENSION VERSION master + // VECTOR EXTENSION VERSION 0.9 //////////////////////////////////////////////////////////////////////// { vmiDocNodeP Version = vmidocAddSection( - Vector, "Version master" + Vector, "Version 0.9" ); vmidocAddText( Version, - "Unstable master version as of "RVVV_MASTER_DATE" (commit " - RVVV_MASTER_TAG"), with these changes compared to version 0.8:" + "Stable 0.9 official release (commit cb7d225), with these " + "significant changes compared to version 0.8:" ); vmidocAddText( Version, - "- mstatus.VS and sstatus.VS fields have moved to bits 10:9;" + "- mstatus.VS and sstatus.VS fields moved to bits 10:9;" ); vmidocAddText( Version, - "- new CSR vcsr has been added and fields VXSAT and VXRM " - "relocated there from CSR fcsr;" + "- new CSR vcsr added and fields VXSAT and VXRM relocated " + "there from CSR fcsr;" + ); + vmidocAddText( + Version, + "- vfcvt.rtz.xu.f.v, vfcvt.rtz.x.f.v, vfwcvt.rtz.xu.f.v, " + "vfwcvt.rtz.x.f.v, vfncvt.rtz.xu.f.v and vfncvt.rtz.x.f.v " + "instructions added;" + ); + vmidocAddText( + Version, + "- fractional LMUL support added, controlled by an extended " + "vtype.vlmul CSR field;" + ); + vmidocAddText( + Version, + "- vector tail agnostic and vector mask agnostic fields " + "added to the vtype CSR;" + ); + vmidocAddText( + Version, + "- all vector load/store instructions replaced with new " + "instructions that explicitly encode EEW of data or index;" + ); + vmidocAddText( + Version, + "- whole register load and store operation encodings changed;" + ); + vmidocAddText( + Version, + "- vzext.vf2, vsext.vf2, vzext.vf4, vsext.vf4, vzext.vf8 and " + "vsext.vf8 instructions added;" + ); + vmidocAddText( + Version, + "- MLEN is always 1." + ); + } + + //////////////////////////////////////////////////////////////////////// + // VECTOR EXTENSION VERSION master + //////////////////////////////////////////////////////////////////////// + + { + vmiDocNodeP Version = vmidocAddSection( + Vector, "Version master" ); + vmidocAddText( Version, - "- segment loads and stores have been restricted to SEW " - "element size only." + "Unstable master version as of "RVVV_MASTER_DATE" (commit " + RVVV_MASTER_TAG"). This is currently identical to version 0.9." ); } } //////////////////////////////////////////////////////////////////////////// - // PORTS + // CLIC + //////////////////////////////////////////////////////////////////////////// + + { + vmiDocNodeP CLIC = vmidocAddSection(Root, "CLIC"); + + vmidocAddText( + CLIC, + "The model can be configured to implement a Core Local Interrupt " + "Controller (CLIC) using parameter \"CLICLEVELS\"; when non-zero, " + "the CLIC is present with the specified number of interrupt " + "levels (2-256), as described in the RISC-V Core-Local Interrupt " + "Controller specification (see references). When non-zero, " + "further parameters are made available to configure other aspects " + "of the CLIC. These are:" + ); + vmidocAddText( + CLIC, + "\"CLICANDBASIC\": this Boolean parameter indicates whether both " + "CLIC and basic interrupt controller are present (if True) or " + "whether only the CLIC is present (if False)." + ); + vmidocAddText( + CLIC, + "\"CLICCFGMBITS\": this Uns32 parameter indicates the number of " + "bits implemented in cliccfg.nmbits, and also indirectly defines " + "CLICPRIVMODES. For cores which implement only Machine mode, " + "or which implement Machine and User modes but not the N " + "extension, the parameter is absent (\"CLICCFGMBITS\" must be " + "zero in these cases)." + ); + vmidocAddText( + CLIC, + "\"CLICCFGLBITS\": this Uns32 parameter indicates the number of " + "bits implemented in cliccfg.nlbits." + ); + vmidocAddText( + CLIC, + "\"CLICSELHVEC\": this Boolean parameter indicates whether " + "Selective Hardware Vectoring is supported (if True) or " + "unsupported (if False)." + ); + vmidocAddText( + CLIC, + "\"CLICMNXTI\": this Boolean parameter indicates whether mnxti " + "CSRs are implemented (if True) or unimplemented (if False)." + ); + vmidocAddText( + CLIC, + "\"CLICMCSW\": this Boolean parameter indicates whether " + "xscratchcsw and xscratchcswl CSRs registers are implemented " + "(if True) or unimplemented (if False)." + ); + vmidocAddText( + CLIC, + "\"mclicbase\": this parameter specifies the CLIC base address " + "in physical memory." + ); + } + + //////////////////////////////////////////////////////////////////////////// + // LR/SC LOCKING + //////////////////////////////////////////////////////////////////////////// + + if(cfg->arch&ISA_A) { + + vmiDocNodeP LRSC = vmidocAddSection( + Root, "Load-Reserved/Store-Conditional Locking" + ); + + vmidocAddText( + LRSC, + "By default, LR/SC locking is implemented automatically by the " + "model and simulator, with a reservation granule defined by the " + "\"lr_sc_grain\" parameter. It is also possible to implement " + "locking externally to the model in a platform component, using " + "the \"LR_address\", \"SC_address\" and \"SC_valid\" net ports, " + "as described below." + ); + vmidocAddText( + LRSC, + "The \"LR_address\" output net port is written by the model with " + "the address used by a load-reserved instruction as it executes. " + "This port should be connected as an input to the external lock " + "management component, which should record the address, and also " + "that an LR/SC transaction is active." + ); + vmidocAddText( + LRSC, + "The \"SC_address\" output net port is written by the model with " + "the address used by a store-conditional instruction as it " + "executes. This should be connected as an input to the external " + "lock management component, which should compare the address with " + "the previously-recorded load-reserved address, and determine " + "from this (and other implementation-specific constraints) whether " + "the store should succeed. It should then immediately write the " + "Boolean success/fail code to the \"SC_valid\" input net port of " + "the model. Finally, it should update state to indicate that " + "an LR/SC transaction is no longer active." + ); + vmidocAddText( + LRSC, + "It is also possible to write zero to the \"SC_valid\" input net " + "port at any time outside the context of a store-conditional " + "instruction, which will mark any active LR/SC transaction as " + "invalid." + ); + vmidocAddText( + LRSC, + "Irrespective of whether LR/SC locking is implemented internally " + "or externally, taking any exception or interrupt or executing " + "exception-return instructions (e.g. MRET) will always mark any " + "active LR/SC transaction as invalid." + ); + + vmiDocNodeP ACODE = vmidocAddSection( + Root, "Active Atomic Operation Indication" + ); + vmidocAddText( + ACODE, + "The \"AMO_active\" output net port is written by the model with " + "a code indicating any current atomic memory operation while the " + "instruction is active. The written codes are:" + ); + vmidocAddText(ACODE, "0: no atomic instruction active"); + vmidocAddText(ACODE, "1: AMOMIN active"); + vmidocAddText(ACODE, "2: AMOMAX active"); + vmidocAddText(ACODE, "3: AMOMINU active"); + vmidocAddText(ACODE, "4: AMOMAXU active"); + vmidocAddText(ACODE, "5: AMOADD active"); + vmidocAddText(ACODE, "6: AMOXOR active"); + vmidocAddText(ACODE, "7: AMOOR active"); + vmidocAddText(ACODE, "8: AMOAND active"); + vmidocAddText(ACODE, "9: AMOSWAP active"); + vmidocAddText(ACODE, "10: LR active"); + vmidocAddText(ACODE, "11: SC active"); + } + + //////////////////////////////////////////////////////////////////////////// + // INTERRUPTS //////////////////////////////////////////////////////////////////////////// { - vmiDocNodeP Ports = vmidocAddSection(Root, "Interrupts"); + vmiDocNodeP Interrupts = vmidocAddSection(Root, "Interrupts"); vmidocAddText( - Ports, + Interrupts, "The \"reset\" port is an active-high reset input. The processor " "is halted when \"reset\" goes high and resumes execution from the " "reset address specified using the \"reset_address\" parameter " "when the signal goes low. The \"mcause\" register is cleared " "to zero." ); - vmidocAddText( - Ports, + Interrupts, "The \"nmi\" port is an active-high NMI input. The processor " - "is halted when \"nmi\" goes high and resumes execution from the " - "address specified using the \"nmi_address\" parameter when the " - "signal goes low. The \"mcause\" register is cleared to zero." + "resumes execution from the address specified using the " + "\"nmi_address\" parameter when the NMI signal goes high. The " + "\"mcause\" register is cleared to zero." ); - vmidocAddText( - Ports, + Interrupts, "All other interrupt ports are active high. For each implemented " "privileged execution level, there are by default input ports for " "software interrupt, timer interrupt and external interrupt; for " @@ -1144,9 +1326,8 @@ void riscvDoc(riscvP rootProcessor) { "\"mie\" and \"mideleg\" CSRs (and Supervisor and User mode " "equivalents if implemented)." ); - vmidocAddText( - Ports, + Interrupts, "Parameter \"external_int_id\" can be used to enable extra " "interrupt ID input ports on each hart. If the parameter is True " "then when an external interrupt is applied the value on the " @@ -1155,6 +1336,15 @@ void riscvDoc(riscvP rootProcessor) { "levels). For Machine mode, the extra interrupt ID port is called " "\"MExternalInterruptID\"." ); + vmidocAddText( + Interrupts, + "The \"deferint\" port is an active-high artifact input that, " + "when written to 1, prevents any pending-and-enabled interrupt " + "being taken (normally, such an interrupt would be taken on the " + "next instruction after it becomes pending-and-enabled). The " + "purpose of this signal is to enable alignment with hardware " + "models in step-and-compare usage." + ); } //////////////////////////////////////////////////////////////////////////// @@ -1175,22 +1365,37 @@ void riscvDoc(riscvP rootProcessor) { "Debug Module using a custom harness. Features added are described " "below." ); - vmidocAddText( debugMode, - "Parameter \"debug_mode\" can be used to specify two different " - "behaviors. If set to value \"interrupt\", then operations that " - "would cause entry to Debug mode result in the processor " - "simulation call (e.g. opProcessorSimulate) returning, with a " - "stop reason of OP_SR_INTERRUPT. In this usage scenario, the " - "Debug Module is implemented in the simulation harness. If " - "parameter \"debug_mode\" is set to value \"halt\", then " - "operations that would cause entry to Debug mode result in the " - "processor halting. Depending on the simulation environment, " - "this might cause a return from the simulation call with a stop " - "reason of OP_SR_HALT, or debug mode might be implemented by " - "another platform component which then restarts the debugged " - "processor again." + "Parameter \"debug_mode\" can be used to specify three different " + "behaviors, as follows:" + ); + vmidocAddText( + debugMode, + "1. If set to value \"vector\", then operations that would cause " + "entry to Debug mode result in the processor jumping to the " + "address specified by the \"debug_address\" parameter. It will " + "execute at this address, in Debug mode, until a \"dret\" " + "instruction causes return to non-Debug mode. Any exception " + "generated during this execution will cause a jump to the address " + "specified by the \"dexc_address\" parameter." + ); + vmidocAddText( + debugMode, + "2. If set to value \"interrupt\", then operations that would " + "cause entry to Debug mode result in the processor simulation call " + "(e.g. opProcessorSimulate) returning, with a stop reason of " + "OP_SR_INTERRUPT. In this usage scenario, the Debug Module is " + "implemented in the simulation harness." + ); + vmidocAddText( + debugMode, + "3. If set to value \"halt\", then operations that would cause " + "entry to Debug mode result in the processor halting. Depending on " + "the simulation environment, this might cause a return from the " + "simulation call with a stop reason of OP_SR_HALT, or debug mode " + "might be implemented by another platform component which then " + "restarts the debugged processor again." ); //////////////////////////////////////////////////////////////////////// @@ -1242,11 +1447,8 @@ void riscvDoc(riscvP rootProcessor) { vmidocAddText( StateEntry, "In all cases, the processor will save required state in " - "\"dpc\" and \"dcsr\" and then either return control " - "immediately to the harness, with stopReason of " - "OP_SR_INTERRUPT, or perform a halt, depending on the value " - "of the \"debug_mode\" parameter. The Debug Module can then " - "manipulate the processor in Debug state as described below." + "\"dpc\" and \"dcsr\" and then perform actions described " + "above, depending in the value of the \"debug_mode\" parameter." ); } @@ -1293,12 +1495,13 @@ void riscvDoc(riscvP rootProcessor) { Registers, "When Debug mode is enabled, registers \"dcsr\", \"dpc\", " "\"dscratch0\" and \"dscratch1\" are implemented as described " - "in the specification. These may be manipulated by the " - "Debug Module using opProcessorRegRead or opProcessorRegWrite; " - "for example, the Debug Module could write \"dcsr\" to enable " - "\"ebreak\" instruction behavior as described above, or read " - "and write \"dpc\" to emulate stepping over an \"ebreak\" " - "instruction prior to resumption from Debug mode." + "in the specification. These may be manipulated externally by " + "a Debug Module using opProcessorRegRead or " + "opProcessorRegWrite; for example, the Debug Module could " + "write \"dcsr\" to enable \"ebreak\" instruction behavior as " + "described above, or read and write \"dpc\" to emulate " + "stepping over an \"ebreak\" instruction prior to resumption " + "from Debug mode." ); } @@ -1347,10 +1550,10 @@ void riscvDoc(riscvP rootProcessor) { ); vmidocAddText( DebugExecution, - "In both cases, the processor will either return control " - "immediately to the harness, with stopReason of " - "OP_SR_INTERRUPT, or perform a halt, depending on the value " - "of the \"debug_mode\" parameter." + "In both cases, the processor will either jump to the " + "debug exception address, or return control immediately to the " + "harness, with stopReason of OP_SR_INTERRUPT, or perform a " + "halt, depending on the value of the \"debug_mode\" parameter." ); } @@ -1365,11 +1568,9 @@ void riscvDoc(riscvP rootProcessor) { vmidocAddText( DebugExecution, - "When in Debug mode, the harness can cause a single " - "instruction to be executed on return from that mode by using " - "opProcessorRegWrite to set dcsr.step, writing False to " - "register \"DM\" and then simulation of at least one cycle " - "(e.g. using opProcessorSimulate). After one instruction " + "When in Debug mode, the processor or harness can cause a " + "single instruction to be executed on return from that mode by " + "setting dcsr.step. After one non-Debug-mode instruction " "has been executed, control will be returned to the harness. " "The processor will remain in single-step mode until dcsr.step " "is cleared." @@ -1481,7 +1682,8 @@ void riscvDoc(riscvP rootProcessor) { leafSection, "Artifact register \"LRSCAddress\" shows the active LR/SC " "lock address. The register holds all-ones if there is no " - "LR/SC operation active." + "LR/SC operation active or if LR/SC locking is implemented " + "externally as described above." ); } } @@ -1641,6 +1843,12 @@ void riscvDoc(riscvP rootProcessor) { vmidocAddText(References, string); } + vmidocAddText( + References, + "RISC-V Core-Local Interrupt Controller (CLIC) Version " + "0.9-draft-20191208" + ); + vmidocAddText( References, "RISC-V External Debug Support Version 0.14.0-DRAFT" diff --git a/source/riscvExceptionTypes.h b/source/riscvExceptionTypes.h index 40ec129..8d3660d 100644 --- a/source/riscvExceptionTypes.h +++ b/source/riscvExceptionTypes.h @@ -68,12 +68,14 @@ typedef enum riscvExceptionS { riscv_E_SW = 0x00, riscv_E_Timer = 0x04, riscv_E_External = 0x08, + riscv_E_CLIC = 0x0c, riscv_E_Local = 0x10, // these are interrupt type groups riscv_E_SWInterrupt = riscv_E_SW | riscv_E_Interrupt, riscv_E_TimerInterrupt = riscv_E_Timer | riscv_E_Interrupt, riscv_E_ExternalInterrupt = riscv_E_External | riscv_E_Interrupt, + riscv_E_CLICInterrupt = riscv_E_CLIC | riscv_E_Interrupt, riscv_E_LocalInterrupt = riscv_E_Local | riscv_E_Interrupt, // interrupts defined by architectural specification @@ -90,6 +92,9 @@ typedef enum riscvExceptionS { riscv_E_HExternalInterrupt = riscv_E_ExternalInterrupt | RISCV_MODE_HYPERVISOR, riscv_E_MExternalInterrupt = riscv_E_ExternalInterrupt | RISCV_MODE_MACHINE, + // interrupts defined when CLIC is present + riscv_E_CSIP = riscv_E_CLICInterrupt, + //////////////////////////////////////////////////////////////////// // KEEP LAST: for sizing (local interrupts follow) //////////////////////////////////////////////////////////////////// @@ -105,8 +110,9 @@ typedef enum riscvAccessFaultS { riscv_AFault_None, // not an access fault riscv_AFault_PMP, // access fault because of PMP permission error riscv_AFault_Bus, // access fault because of bus error - riscv_AFault_PMA_Code, // access fault because of PMA fetch error - riscv_AFault_PMA_Data, // access fault because of PMA load/store error + riscv_AFault_Device, // access fault because of device error + riscv_AFault_Custom1, // access fault because of custom reason (1) + riscv_AFault_Custom2, // access fault because of custom reason (2) riscv_AFault_Explicit, // explicit Access Fault value } riscvAccessFault; @@ -120,3 +126,32 @@ typedef enum riscvICModeE { riscv_int_CLIC = 3, // CLIC interrupt mode } riscvICMode; +// +// Return exception code for interrupt number +// +inline static riscvException intToException(Uns32 intIndex) { + return intIndex+riscv_E_Interrupt; +} + +// +// Return interrupt number for exception code +// +inline static Uns32 exceptionToInt(riscvException exception) { + return exception-riscv_E_Interrupt; +} + +// +// Is the exception an interrupt +// +inline static Bool isInterrupt(riscvException exception) { + return exception>=riscv_E_Interrupt; +} + +// +// Get code from an exception +// +inline static Uns32 getExceptionCode(riscvException exception) { + return isInterrupt(exception) ? exceptionToInt(exception) : exception; +} + + diff --git a/source/riscvExceptions.c b/source/riscvExceptions.c index d840bed..5fefcca 100644 --- a/source/riscvExceptions.c +++ b/source/riscvExceptions.c @@ -29,6 +29,7 @@ #include "vmi/vmiRt.h" // model header files +#include "riscvCLICTypes.h" #include "riscvCSR.h" #include "riscvDecode.h" #include "riscvExceptions.h" @@ -91,6 +92,12 @@ static const riscvExceptionDesc exceptions[] = { RISCV_EXCEPTION (SExternalInterrupt, ISA_S, "Supervisor external interrupt"), RISCV_EXCEPTION (MExternalInterrupt, 0, "Machine external interrupt"), + //////////////////////////////////////////////////////////////////// + // CLIC INTERRUPTS + //////////////////////////////////////////////////////////////////// + + RISCV_EXCEPTION (CSIP, 0, "CLIC software interrupt"), + //////////////////////////////////////////////////////////////////// // TERMINATOR //////////////////////////////////////////////////////////////////// @@ -110,6 +117,13 @@ inline static Uns64 getPC(riscvP riscv) { return vmirtGetPC((vmiProcessorP)riscv); } +// +// Return current data domain +// +inline static memDomainP getDataDomain(riscvP riscv) { + return vmirtGetProcessorDataDomain((vmiProcessorP)riscv); +} + // // Set current PC // @@ -172,16 +186,34 @@ static Bool handleFF(riscvP riscv) { return suppress; } +// +// Notify a derived model of halt/restart if required +// +static void notifyHaltRestart(riscvP riscv) { + + riscvExtCBP extCB; + + // notify dependent model of halt/restart event + for(extCB=riscv->extCBs; extCB; extCB=extCB->next) { + if(extCB->haltRestartNotifier) { + extCB->haltRestartNotifier(riscv, extCB->clientData); + } + } +} + // // Halt the passed processor // static void haltProcessor(riscvP riscv, riscvDisableReason reason) { - if(!riscv->disable) { - vmirtHalt((vmiProcessorP)riscv); - } + Bool disabled = riscv->disable; riscv->disable |= reason; + + if(!disabled) { + vmirtHalt((vmiProcessorP)riscv); + notifyHaltRestart(riscv); + } } // @@ -195,6 +227,7 @@ static void restartProcessor(riscvP riscv, riscvDisableReason reason) { // disable code) if(!riscv->disable) { vmirtRestartNext((vmiProcessorP)riscv); + notifyHaltRestart(riscv); } } @@ -260,16 +293,6 @@ static riscvMode getExceptionModeX(riscvP riscv, riscvException ecode) { return getModeX(riscv, RD_CSR(riscv, medeleg), RD_CSR(riscv, sedeleg), ecode); } -// -// Is exception an interrupt? -// -#define IS_INTERRUPT(_EXCEPTION) ((_EXCEPTION) & riscv_E_Interrupt) - -// -// Get code from exception -// -#define GET_ECODE(_EXCEPTION) ((_EXCEPTION) & ~riscv_E_Interrupt) - // // Return interrupt mode (0:direct, 1:vectored) - from privileged ISA version // 1.10 this is encoded in the [msu]tvec register, but previous versions did @@ -283,35 +306,98 @@ inline static riscvICMode getIMode(riscvICMode customMode, riscvICMode tvecMode) // // Update exception state when taking exception to mode X from mode Y // -#define TARGET_MODE_X(_P, _X, _x, _IS_INT, _ECODE, _EPC, _BASE, _MODE, _TVAL) { \ - \ - /* get interrupt enable bit for mode X */ \ - Uns8 _IE = RD_CSR_FIELD(riscv, mstatus, _X##IE); \ +#define TARGET_MODE_X( \ + _P, _X, _x, _IS_INT, _ECODE, _EPC, _BASE, _MODE, _TVAL, _LEVEL \ +) { \ + /* get interrupt enable and level bits for mode X */ \ + Uns8 _IE = RD_CSR_FIELD(_P, mstatus, _X##IE); \ + Uns8 _IL = RD_CSR_FIELD(_P, mintstatus, _x##il); \ \ /* update interrupt enable and interrupt enable stack */ \ - WR_CSR_FIELD(riscv, mstatus, _X##PIE, _IE); \ - WR_CSR_FIELD(riscv, mstatus, _X##IE, 0); \ + WR_CSR_FIELD(_P, mstatus, _X##PIE, _IE); \ + WR_CSR_FIELD(_P, mstatus, _X##IE, 0); \ + \ + /* clear cause register if not in CLIC mode */ \ + if(!useCLICM(_P)) { \ + WR_CSR(_P, _x##cause, 0); \ + } \ \ /* update cause register */ \ - WR_CSR_FIELD(riscv, _x##cause, ExceptionCode, _ECODE); \ - WR_CSR_FIELD(riscv, _x##cause, Interrupt, _IS_INT); \ + WR_CSR_FIELD(_P, _x##cause, ExceptionCode, _ECODE); \ + WR_CSR_FIELD(_P, _x##cause, Interrupt, _IS_INT); \ + WR_CSR_FIELD(_P, _x##cause, pil, _IL); \ \ /* update writable bits in epc register */ \ - Uns64 epcMask = RD_CSR_MASK(riscv, _x##epc); \ - WR_CSR_FIELD(riscv, _x##epc, value, (_EPC) & epcMask); \ + Uns64 epcMask = RD_CSR_MASK(_P, _x##epc); \ + WR_CSR_FIELD(_P, _x##epc, value, (_EPC) & epcMask); \ \ /* update tval register */ \ - WR_CSR_FIELD(riscv, _x##tval, value, _TVAL); \ + WR_CSR_FIELD(_P, _x##tval, value, _TVAL); \ \ /* get exception base address and mode */ \ - _BASE = (Addr)RD_CSR_FIELD(riscv, _x##tvec, BASE) << 2; \ - _MODE = getIMode(riscv->_X##IMode, RD_CSR_FIELD(riscv, _x##tvec, MODE)); \ + _BASE = (Addr)RD_CSR_FIELD(_P, _x##tvec, BASE) << 2; \ + _MODE = getIMode(_P->_X##IMode, RD_CSR_FIELD(_P, _x##tvec, MODE)); \ + \ + /* update exception level */ \ + if(_LEVEL>=0) { \ + WR_CSR_FIELD(_P, mintstatus, _x##il, _LEVEL); \ + } \ +} + +// +// Handle CLIC Vectored Interrupt +// +#define GET_CLIC_VECTORED_HANDLER_PC(_P, _HANDLER_PC, _X, _x, _INTNUM, _MODE) { \ + \ + Uns64 TBASE = RD_CSR(_P, _x##tvt); \ + \ + /* set xcause.inhv=1 before vector lookup */ \ + WR_CSR_FIELD(_P, _x##cause, inhv, 1); \ + \ + /* validate the memory access */ \ + if(!readCLICVectorTableEntry(_P, _INTNUM, _MODE, TBASE, &_HANDLER_PC)) { \ + return; \ + } \ + \ + /* set xcause.inhv=0 after vector lookup */ \ + WR_CSR_FIELD(_P, _x##cause, inhv, 0); \ +} + +// +// Get CLIC Vectored Interrupt table entry +// +static Bool readCLICVectorTableEntry( + riscvP riscv, + Uns32 intNum, + riscvMode mode, + Uns64 TBASE, + Uns64 *handlerPCP +) { + memEndian endian = riscvGetDataEndian(riscv, mode); + memDomainP domain = getDataDomain(riscv); + memAccessAttrs memAttrs = MEM_AA_TRUE; + Uns32 ptrBytes = riscvGetXlenArch(riscv)/8; + Uns64 address = TBASE + (ptrBytes*intNum); + Uns64 handlerPC; + + // read 4-byte or 8-byte entry + if(ptrBytes==4) { + handlerPC = vmirtRead4ByteDomain(domain, address, endian, memAttrs); + } else { + handlerPC = vmirtRead8ByteDomain(domain, address, endian, memAttrs); + } + + // mask off LSB + *handlerPCP = handlerPC & -2; + + // indicate whether there was a nested exception + return isInterrupt(riscv->exception); } // // Does this exception code correspond to a retired instruction? // -static Bool retiredCode(riscvException exception) { +static Bool retiredCode(riscvP riscv, riscvException exception) { switch(exception) { @@ -320,7 +406,7 @@ static Bool retiredCode(riscvException exception) { case riscv_E_EnvironmentCallFromSMode: case riscv_E_EnvironmentCallFromHMode: case riscv_E_EnvironmentCallFromMMode: - return True; + return (RISCV_PRIV_VERSION(riscv) < RVPV_1_12); default: return False; @@ -365,7 +451,6 @@ inline static void notifyERETDerived(riscvP riscv, riscvMode mode) { riscvExtCBP extCB; - // call derived model preMorph functions if required for(extCB=riscv->extCBs; extCB; extCB=extCB->next) { notifyTrapDerived(riscv, mode, extCB->ERETNotifier, extCB->clientData); } @@ -397,11 +482,13 @@ void riscvTakeException( } else { - Bool isInt = IS_INTERRUPT(exception); - Uns32 ecode = GET_ECODE(exception); + Bool shv = riscv->clic.sel.shv; + Bool isInt = isInterrupt(exception); + Uns32 ecode = getExceptionCode(exception); Uns32 ecodeMod = ecode; Uns64 EPC = getEPC(riscv); Uns64 handlerPC = 0; + Int32 level = -1; riscvMode modeY = getCurrentMode(riscv); riscvMode modeX; riscvExtCBP extCB; @@ -411,7 +498,7 @@ void riscvTakeException( // adjust baseInstructions based on the exception code to take into // account whether the previous instruction has retired, unless // inhibited by mcountinhibit.IR - if(!retiredCode(exception) && !riscvInhibitInstret(riscv)) { + if(!retiredCode(riscv, exception) && !riscvInhibitInstret(riscv)) { riscv->baseInstructions++; } @@ -426,10 +513,12 @@ void riscvTakeException( clearEA(riscv); // get exception target mode (X) - if(isInt) { - modeX = getInterruptModeX(riscv, ecode); - } else { + if(!isInt) { modeX = getExceptionModeX(riscv, ecode); + } else if(riscv->pendEnab.isCLIC) { + modeX = riscv->pendEnab.priv; + } else { + modeX = getInterruptModeX(riscv, ecode); } // modify code reported for external interrupts if required @@ -438,37 +527,87 @@ void riscvTakeException( ecodeMod = riscv->extInt[offset] ? : ecode; } + // CLIC mode: horizontal synchronous exception traps, which stay within + // a privilege mode, are serviced with the same interrupt level as the + // instruction that raised the exception. Vertical synchronous exception + // traps, which are serviced at a higher privilege mode, are taken at + // interrupt level 0 in the higher privilege mode. + if(isInt) { + level = riscv->pendEnab.level; + } else if(modeX != modeY) { + level = 0; + } + + // force trap value to zero if required + if(riscv->configInfo.tval_zero) { + tval = 0; + } + // update state dependent on target exception level if(modeX==RISCV_MODE_USER) { // target user mode - TARGET_MODE_X(riscv, U, u, isInt, ecodeMod, EPC, base, mode, tval); + TARGET_MODE_X( + riscv, U, u, isInt, ecodeMod, EPC, base, mode, tval, level + ); } else if(modeX==RISCV_MODE_SUPERVISOR) { // target supervisor mode - TARGET_MODE_X(riscv, S, s, isInt, ecodeMod, EPC, base, mode, tval); + TARGET_MODE_X( + riscv, S, s, isInt, ecodeMod, EPC, base, mode, tval, level + ); + WR_CSR_FIELD(riscv, mstatus, SPP, modeY); } else { // target machine mode - TARGET_MODE_X(riscv, M, m, isInt, ecodeMod, EPC, base, mode, tval); + TARGET_MODE_X( + riscv, M, m, isInt, ecodeMod, EPC, base, mode, tval, level + ); + WR_CSR_FIELD(riscv, mstatus, MPP, modeY); } + // switch to target mode + riscvSetMode(riscv, modeX); + + // indicate the taken exception + riscv->exception = exception; + // handle direct or vectored exception if((mode == riscv_int_Direct) || !isInt) { + handlerPC = base; - } else { + + } else if(mode!=riscv_int_CLIC) { + handlerPC = base + (4 * ecode); - } - // switch to target mode - riscvSetMode(riscv, modeX); + } else if(!shv) { - // indicate the taken exception - riscv->exception = exception; + handlerPC = base & -64; + + } else { + + // SHV interrupts are acknowledged automatically + riscvAcknowledgeCLICInt(riscv, ecode); + + if(modeX==RISCV_MODE_USER) { + GET_CLIC_VECTORED_HANDLER_PC( + riscv, handlerPC, U, u, ecodeMod, modeX + ); + } else if(modeX==RISCV_MODE_SUPERVISOR) { + GET_CLIC_VECTORED_HANDLER_PC( + riscv, handlerPC, S, s, ecodeMod, modeX + ); + } else { + GET_CLIC_VECTORED_HANDLER_PC( + riscv, handlerPC, M, m, ecodeMod, modeX + ); + } + } // set address at which to execute vmirtSetPCException((vmiProcessorP)riscv, handlerPC); @@ -553,7 +692,7 @@ void riscvIllegalInstruction(riscvP riscv) { Uns64 tval = 0; // tval is either 0 or the instruction pattern - if(riscv->configInfo.tval_ii_code) { + if(riscv->configInfo.tval_ii_code && !riscv->configInfo.tval_zero) { tval = riscvGetInstruction(riscv, getPC(riscv)); } @@ -647,6 +786,11 @@ void riscvMRET(riscvP riscv) { // clear any active exclusive access clearEAxRET(riscv); + // restore previous mintstatus.mil (CLIC mode) + if(useCLICM(riscv)) { + WR_CSR_FIELD(riscv, mintstatus, mil, RD_CSR_FIELD(riscv, mcause, pil)); + } + // restore previous MIE WR_CSR_FIELD(riscv, mstatus, MIE, RD_CSR_FIELD(riscv, mstatus, MPIE)) @@ -680,6 +824,11 @@ void riscvSRET(riscvP riscv) { // clear any active exclusive access clearEAxRET(riscv); + // restore previous mintstatus.sil (CLIC mode) + if(useCLICS(riscv)) { + WR_CSR_FIELD(riscv, mintstatus, sil, RD_CSR_FIELD(riscv, scause, pil)); + } + // restore previous SIE WR_CSR_FIELD(riscv, mstatus, SIE, RD_CSR_FIELD(riscv, mstatus, SPIE)) @@ -711,6 +860,11 @@ void riscvURET(riscvP riscv) { // clear any active exclusive access clearEAxRET(riscv); + // restore previous mintstatus.uil (CLIC mode) + if(useCLICU(riscv)) { + WR_CSR_FIELD(riscv, mintstatus, uil, RD_CSR_FIELD(riscv, ucause, pil)); + } + // restore previous UIE WR_CSR_FIELD(riscv, mstatus, UIE, RD_CSR_FIELD(riscv, mstatus, UPIE)) @@ -732,15 +886,16 @@ void riscvURET(riscvP riscv) { // inline static void updateDMStall(riscvP riscv, Bool DMStall) { - riscv->DMStall = DMStall; - // halt or restart processor if required - if(riscv->configInfo.debug_mode==RVDM_INTERRUPT) { - // no action - } else if(DMStall) { - haltProcessor(riscv, RVD_DEBUG); - } else { - restartProcessor(riscv, RVD_DEBUG); + if(riscv->configInfo.debug_mode==RVDM_HALT) { + + riscv->DMStall = DMStall; + + if(DMStall) { + haltProcessor(riscv, RVD_DEBUG); + } else { + restartProcessor(riscv, RVD_DEBUG); + } } } @@ -760,7 +915,9 @@ inline static void setDM(riscvP riscv, Bool DM) { // static void enterDM(riscvP riscv, dmCause cause) { - if(!inDebugMode(riscv)) { + Bool DM = inDebugMode(riscv); + + if(!DM) { riscvCountState state; @@ -786,12 +943,28 @@ static void enterDM(riscvP riscv, dmCause cause) { riscvPostInhibit(riscv, &state, False); } - // halt or restart processor if required - updateDMStall(riscv, True); - - // interrupt the processor if required if(riscv->configInfo.debug_mode==RVDM_INTERRUPT) { + + // interrupt the processor vmirtInterrupt((vmiProcessorP)riscv); + + } else if(riscv->configInfo.debug_mode==RVDM_VECTOR) { + + Uns64 address; + + // use either debug entry address or debug exception address + if(DM) { + address = riscv->configInfo.dexc_address; + } else { + address = riscv->configInfo.debug_address; + } + + vmirtSetPCException((vmiProcessorP)riscv, address); + + } else { + + // halt or restart processor if required + updateDMStall(riscv, True); } } @@ -1015,6 +1188,32 @@ VMI_WR_ABORT_EXCEPT_FN(riscvWrAbortExcept) { } } +// +// Read device exception handler +// +VMI_RD_DEVICE_EXCEPT_FN(riscvRdDeviceExcept) { + + riscvP riscv = (riscvP)processor; + + riscv->AFErrorIn = riscv_AFault_Device; + riscvTakeMemoryException(riscv, riscv_E_LoadAccessFault, address); + + return 0; +} + +// +// Write device exception handler +// +VMI_WR_DEVICE_EXCEPT_FN(riscvWrDeviceExcept) { + + riscvP riscv = (riscvP)processor; + + riscv->AFErrorIn = riscv_AFault_Device; + riscvTakeMemoryException(riscv, riscv_E_StoreAMOAccessFault, address); + + return 0; +} + // // Fetch addresses are always snapped to a 2-byte boundary, irrespective of // whether compressed instructions are implemented (see comments associated @@ -1025,6 +1224,42 @@ VMI_FETCH_SNAP_FN(riscvFetchSnap) { return thisPC & -2; } +// +// Snap read address if required +// +VMI_RD_WR_SNAP_FN(riscvRdSnap) { + + riscvP riscv = (riscvP)processor; + Uns32 snap = MEM_SNAP(0, 0); + riscvExtCBP extCB; + + for(extCB=riscv->extCBs; extCB && !snap; extCB=extCB->next) { + if(extCB->rdSnapCB) { + snap = extCB->rdSnapCB(riscv, address, bytes); + } + } + + return snap; +} + +// +// Snap write address if required +// +VMI_RD_WR_SNAP_FN(riscvWrSnap) { + + riscvP riscv = (riscvP)processor; + Uns32 snap = MEM_SNAP(0, 0); + riscvExtCBP extCB; + + for(extCB=riscv->extCBs; extCB && !snap; extCB=extCB->next) { + if(extCB->wrSnapCB) { + snap = extCB->wrSnapCB(riscv, address, bytes); + } + } + + return snap; +} + // // Validate instruction fetch from the passed address // @@ -1103,57 +1338,37 @@ static Bool validateFetchAddress( // Return interrupt enable for the passed mode, given a raw interrupt enable // bit // -inline static Bool getIE(riscvP riscv, Bool IE, riscvMode modeIE) { +static Bool getIE(riscvP riscv, Bool IE, riscvMode modeIE, Bool useCLIC) { riscvMode mode = getCurrentMode(riscv); - return (modemodeIE) ? False : IE; + return useCLIC ? False : (modemodeIE) ? False : IE; } // -// Return mask of pending interrupts that would cause resumption from WFI (note -// that these could however be masked by global interrupt bits or delegation -// bits - see the Privileged Architecture specification) +// Return mask of pending basic mode interrupts that would cause resumption from +// WFI (note that these could however be masked by global interrupt bits or +// delegation bits - see the Privileged Architecture specification) // -inline static Uns64 getPendingInterrupts(riscvP riscv) { +inline static Uns64 getPendingBasic(riscvP riscv) { return RD_CSR(riscv, mie) & RD_CSR(riscv, mip); } // -// Return mask of pending-and-enabled interrupts +// Return an indication of whether any CLIC mode interrupt is pending that would +// cause resumption from WFI (note that these could however be masked by global +// interrupt bits - see the Privileged Architecture specification) // -static Uns64 getPendingAndEnabledInterrupts(riscvP riscv) { - - // NOTE: all interrupts are disabled in Debug mode - Uns64 result = inDebugMode(riscv) ? 0 : getPendingInterrupts(riscv); - - if(result) { - - // get raw interrupt enable bits - Bool MIE = RD_CSR_FIELD(riscv, mstatus, MIE); - Bool SIE = RD_CSR_FIELD(riscv, mstatus, SIE); - Bool UIE = RD_CSR_FIELD(riscv, mstatus, UIE); - - // modify effective interrupt enables based on current mode - MIE = getIE(riscv, MIE, RISCV_MODE_MACHINE); - SIE = getIE(riscv, SIE, RISCV_MODE_SUPERVISOR); - UIE = getIE(riscv, UIE, RISCV_MODE_USER); - - // get interrupt mask applicable for each mode - Uns64 mideleg = RD_CSR(riscv, mideleg); - Uns64 sideleg = RD_CSR(riscv, sideleg) & mideleg; - Uns64 mMask = ~mideleg; - Uns64 sMask = mideleg & ~sideleg; - Uns64 uMask = sideleg; - - // handle masked interrupts - if(!MIE) {result &= ~mMask;} - if(!SIE) {result &= ~sMask;} - if(!UIE) {result &= ~uMask;} - } +inline static Bool getPendingCLIC(riscvP riscv) { + return riscv->clic.sel.id!=RV_NO_INT; +} - // return pending and enabled interrupts - return result; +// +// Return indication if whether any interrupt is pending (either basic mode or +// CLIC mode) +// +inline static Bool getPending(riscvP riscv) { + return getPendingBasic(riscv) || getPendingCLIC(riscv); } // @@ -1182,87 +1397,202 @@ static Uns32 getIntPri(Uns32 intNum) { } // -// Descriptor for pending-and-enabled interrupt -// -typedef struct intDescS { - Uns32 ecode; // exception code - riscvMode emode; // mode to which taken -} intDesc; - -// -// Process highest-priority interrupt in the given mask of pending-and-enabled -// interrupts +// Refresh pending basic interrupt state // -static void doInterrupt(riscvP riscv, Uns64 intMask) { +static void refreshPendingAndEnabledBasic(riscvP riscv) { - Uns32 ecode = 0; - intDesc selected = {ecode:-1}; + Uns64 pendingEnabled = getPendingBasic(riscv); - // sanity check there are pending-and-enabled interrupts - VMI_ASSERT(intMask, "expected pending-and-enabled interrupts"); - - // find the highest priority pending-and-enabled interrupt - do { - - if(intMask&1) { - - intDesc try = {ecode:ecode, emode:getInterruptModeX(riscv, ecode)}; - - if(selected.ecode==-1) { - // first pending-and-enabled interrupt - selected = try; - } else if(selected.emode < try.emode) { - // higher destination privilege mode - selected = try; - } else if(selected.emode > try.emode) { - // lower destination privilege mode - } else if(getIntPri(selected.ecode)<=getIntPri(try.ecode)) { - // higher fixed priority order and same destination mode - selected = try; - } - } + // apply interrupt masks + if(pendingEnabled) { - // step to next potential pending-and-enabled interrupt - intMask >>= 1; - ecode++; + // get raw interrupt enable bits + Bool MIE = RD_CSR_FIELD(riscv, mstatus, MIE); + Bool SIE = RD_CSR_FIELD(riscv, mstatus, SIE); + Bool UIE = RD_CSR_FIELD(riscv, mstatus, UIE); - } while(intMask); + // modify effective interrupt enables based on current mode + MIE = getIE(riscv, MIE, RISCV_MODE_MACHINE, useCLICM(riscv)); + SIE = getIE(riscv, SIE, RISCV_MODE_SUPERVISOR, useCLICS(riscv)); + UIE = getIE(riscv, UIE, RISCV_MODE_USER, useCLICU(riscv)); - // take the interrupt - riscvTakeException(riscv, riscv_E_Interrupt+selected.ecode, 0); -} + // get interrupt mask applicable for each mode + Uns64 mideleg = RD_CSR(riscv, mideleg); + Uns64 sideleg = RD_CSR(riscv, sideleg) & mideleg; + Uns64 mMask = ~mideleg; + Uns64 sMask = mideleg & ~sideleg; + Uns64 uMask = sideleg; -// -// This is called by the simulator when fetching from an instruction address. -// It gives the model an opportunity to take an exception instead. -// -VMI_IFETCH_FN(riscvIFetchExcept) { + // handle masked interrupts + if(!MIE) {pendingEnabled &= ~mMask;} + if(!SIE) {pendingEnabled &= ~sMask;} + if(!UIE) {pendingEnabled &= ~uMask;} + } - riscvP riscv = (riscvP)processor; - Uns64 thisPC = address; - Bool fetchOK = False; - Uns64 intMask = getPendingAndEnabledInterrupts(riscv); + // print exception status + if(RISCV_DEBUG_EXCEPT(riscv)) { - if(riscv->netValue.resethaltreqS) { + // get factors contributing to interrupt state + riscvBasicIntState intState = { + .pendingEnabled = pendingEnabled, + .pending = RD_CSR(riscv, mip), + .pendingExternal = riscv->ip[0], + .pendingInternal = riscv->swip, + .mideleg = RD_CSR(riscv, mideleg), + .sideleg = RD_CSR(riscv, sideleg), + .mie = RD_CSR_FIELD(riscv, mstatus, MIE), + .sie = RD_CSR_FIELD(riscv, mstatus, SIE), + .uie = RD_CSR_FIELD(riscv, mstatus, UIE), + }; - // enter Debug mode out of reset - if(complete) { - riscv->netValue.resethaltreqS = False; - enterDM(riscv, DMC_RESETHALTREQ); - } + // report only if interrupt state changes + if(memcmp(&riscv->intState, &intState, sizeof(intState))) { - } else if(riscv->netValue.haltreq && !inDebugMode(riscv)) { + vmiMessage("I", CPU_PREFIX "_IS", + SRCREF_FMT + "PENDING+ENABLED="FMT_A08x" PENDING="FMT_A08x" " + "[EXTERNAL_IP="FMT_A08x",SW_IP=%08x] " + "MIDELEG=%08x SIDELEG=%08x MSTATUS.[MSU]IE=%u%u%u", + SRCREF_ARGS(riscv, getPC(riscv)), + intState.pendingEnabled, + intState.pending, + intState.pendingExternal, + intState.pendingInternal, + intState.mideleg, + intState.sideleg, + intState.mie, + intState.sie, + intState.uie + ); - // enter Debug mode - if(complete) { - enterDM(riscv, DMC_HALTREQ); + // track previous pending state + riscv->intState = intState; } + } - } else if(intMask) { + // select highest-priority pending-and-enabled interrupt + if(pendingEnabled) { + + riscvPendEnabP selected = &riscv->pendEnab; + Int32 id = 0; + + do { + + if(pendingEnabled&1) { + + riscvPendEnab try = { + id : id, + priv : getInterruptModeX(riscv, id) + }; + + if(selected->id==RV_NO_INT) { + // first pending-and-enabled interrupt + *selected = try; + } else if(selected->priv < try.priv) { + // higher destination privilege mode + *selected = try; + } else if(selected->priv > try.priv) { + // lower destination privilege mode + } else if(getIntPri(selected->id)<=getIntPri(try.id)) { + // higher fixed priority order and same destination mode + *selected = try; + } + } + + // step to next potential pending-and-enabled interrupt + pendingEnabled >>= 1; + id++; + + } while(pendingEnabled); + } +} + +// +// Forward reference +// +static void refreshPendingAndEnabledCLIC(riscvP hart); + +// +// Refresh pending interrupt state +// +static void refreshPendingAndEnabled(riscvP riscv) { + + // reset pending and enabled interrupt details + riscv->pendEnab.id = RV_NO_INT; + riscv->pendEnab.priv = 0; + riscv->pendEnab.level = 0; + riscv->pendEnab.isCLIC = False; + + // get highest-priority basic-mode pending interrupt + if(basicICPresent(riscv)) { + refreshPendingAndEnabledBasic(riscv); + } + + // get highest-priority CLIC-mode pending interrupt + if(CLICPresent(riscv)) { + refreshPendingAndEnabledCLIC(riscv); + } +} + +// +// Return an indication of whether there are any pending-and-enabled interrupts +// without refreshing state +// +inline static Bool getPendingAndEnabled(riscvP riscv) { + return ( + (riscv->pendEnab.id!=RV_NO_INT) && + !inDebugMode(riscv) && + !riscv->netValue.deferint + ); +} + +// +// Process highest-priority interrupt in the given mask of pending-and-enabled +// interrupts +// +static void doInterrupt(riscvP riscv) { + + // get the highest-priority interrupt and unregister it + Uns32 id = riscv->pendEnab.id; + riscv->pendEnab.id = RV_NO_INT; + + // sanity check there are pending-and-enabled interrupts + VMI_ASSERT(id!=RV_NO_INT, "expected pending-and-enabled interrupt"); + + // take the interrupt + riscvTakeException(riscv, intToException(id), 0); +} + +// +// This is called by the simulator when fetching from an instruction address. +// It gives the model an opportunity to take an exception instead. +// +VMI_IFETCH_FN(riscvIFetchExcept) { + + riscvP riscv = (riscvP)processor; + Uns64 thisPC = address; + Bool fetchOK = False; + + if(riscv->netValue.resethaltreqS) { + + // enter Debug mode out of reset + if(complete) { + riscv->netValue.resethaltreqS = False; + enterDM(riscv, DMC_RESETHALTREQ); + } + + } else if(riscv->netValue.haltreq && !inDebugMode(riscv)) { + + // enter Debug mode + if(complete) { + enterDM(riscv, DMC_HALTREQ); + } + + } else if(getPendingAndEnabled(riscv)) { // handle pending interrupt if(complete) { - doInterrupt(riscv, intMask); + doInterrupt(riscv); } } else if(!validateFetchAddress(riscv, domain, thisPC, complete)) { @@ -1289,10 +1619,12 @@ VMI_IFETCH_FN(riscvIFetchExcept) { // static Bool hasException(riscvP riscv, riscvException code) { - if(codeexceptionMask & (1ULL<interruptMask & (1ULL<<(code-riscv_E_Interrupt)); + return riscv->interruptMask & (1ULL<configInfo.local_int_num+16; + return riscv->configInfo.local_int_num+riscv_E_Local; } // @@ -1431,217 +1763,1166 @@ Uns64 riscvGetLocalIntMask(riscvP riscv) { Uns32 localShift = (localIntNum<48) ? localIntNum : 48; Uns64 local_int_mask = (1ULL<configInfo.arch; + Uns64 exceptionMask = 0; + Uns64 interruptMask = 0; + riscvExceptionDescCP thisDesc; + + // get exceptions and standard interrupts supported on the current + // architecture + for(thisDesc=exceptions; thisDesc->vmiInfo.name; thisDesc++) { + + riscvException code = thisDesc->vmiInfo.code; + + if(code==riscv_E_CSIP) { + // never present in interrupt mask + } else if((arch&thisDesc->arch)!=thisDesc->arch) { + // not implemented by this variant + } else if(!isInterrupt(code)) { + exceptionMask |= 1ULL<exceptionMask = exceptionMask; + + // save composed interrupt mask result (including extra local interrupts + // and excluding interrupts that are explicitly absent) + riscv->interruptMask = ( + (interruptMask | riscvGetLocalIntMask(riscv)) & + ~riscv->configInfo.unimp_int_mask + ); +} + +// +// Free exception state +// +void riscvExceptFree(riscvP riscv) { + + if(riscv->exceptions) { + + Uns32 numLocal = getLocalIntNum(riscv); + Uns32 numNotLocal = riscv->exceptionNum - numLocal; + vmiExceptionInfoCP local = &riscv->exceptions[numNotLocal]; + Uns32 i; + + // free local exception description strings + for(i=0; iexceptions); + riscv->exceptions = 0; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// EXTERNAL INTERRUPT UTILITIES +//////////////////////////////////////////////////////////////////////////////// + +// +// Forward reference +// +static void resetCLIC(riscvP riscv); + +// +// Detect rising edge +// +inline static Bool posedge(Bool old, Bool new) { + return !old && new; +} + +// +// Detect falling edge +// +inline static Bool negedge(Uns32 old, Uns32 new) { + return old && !new; +} + +// +// Halt the processor in WFI state if required +// +void riscvWFI(riscvP riscv) { + + if(!(inDebugMode(riscv) || getPending(riscv))) { + haltProcessor(riscv, RVD_WFI); + } +} + +// +// Handle any pending and enabled interrupts +// +inline static void handlePendingAndEnabled(riscvP riscv) { + + if(getPendingAndEnabled(riscv)) { + vmirtDoSynchronousInterrupt((vmiProcessorP)riscv); + } +} + +// +// Check for pending interrupts +// +void riscvTestInterrupt(riscvP riscv) { + + // refresh pending and pending-and-enabled interrupt state + refreshPendingAndEnabled(riscv); + + // restart processor if it is halted in WFI state and local interrupts are + // pending (even if masked) + if(getPending(riscv)) { + restartProcessor(riscv, RVD_RESTART_WFI); + } + + // schedule asynchronous interrupt handling if interrupts are pending and + // enabled + handlePendingAndEnabled(riscv); +} + +// +// Reset the processor +// +void riscvReset(riscvP riscv) { + + riscvExtCBP extCB; + + // restart the processor from any halted state + restartProcessor(riscv, RVD_RESTART_RESET); + + // exit Debug mode + riscvSetDM(riscv, False); + + // switch to Machine mode + riscvSetMode(riscv, RISCV_MODE_MACHINE); + + // reset CSR state + riscvCSRReset(riscv); + + // reset CLIC state + resetCLIC(riscv); + + // notify dependent model of reset event + for(extCB=riscv->extCBs; extCB; extCB=extCB->next) { + if(extCB->resetNotifier) { + extCB->resetNotifier(riscv, extCB->clientData); + } + } + + // indicate the taken exception + riscv->exception = 0; + + // set address at which to execute + vmirtSetPCException((vmiProcessorP)riscv, riscv->configInfo.reset_address); + + // enter Debug mode out of reset if required + riscv->netValue.resethaltreqS = riscv->netValue.resethaltreq; +} + +// +// Do NMI interrupt +// +static void doNMI(riscvP riscv) { + + // restart the processor from any halted state + restartProcessor(riscv, RVD_RESTART_NMI); + + // switch to Machine mode + riscvSetMode(riscv, RISCV_MODE_MACHINE); + + // update cause register (to zero) + WR_CSR(riscv, mcause, riscv->configInfo.ecode_nmi); + + // update mepc to hold next instruction address + WR_CSR(riscv, mepc, getEPC(riscv)); + + // indicate the taken exception + riscv->exception = 0; + + // set address at which to execute + vmirtSetPCException((vmiProcessorP)riscv, riscv->configInfo.nmi_address); +} + + +//////////////////////////////////////////////////////////////////////////////// +// CLIC FUNCTIONS +//////////////////////////////////////////////////////////////////////////////// + +// +// Type of CLIC page being accessed +// +typedef enum CLICPageTypeE { + CPT_C, // control page + CPT_M, // Machine mode page + CPT_S, // Supervisor mode page + CPT_U, // User mode page +} CLICPageType; + +// +// This enumerates byte-sized CLIC interrupt control fields +// +typedef enum CLICIntFieldTypeE { + CIT_clicintip = 0, + CIT_clicintie = 1, + CIT_clicintattr = 2, + CIT_clicintctl = 3, + CIT_LAST +} CLICIntFieldType; + +// +// State for a single interrupt +// +typedef union riscvCLICIntStateU { + Uns8 fields[CIT_LAST]; + Uns32 value32; +} riscvCLICIntState; + +// +// Return page type name +// +static const char *mapCLICPageTypeName(CLICPageType type) { + + static const char *map[] = { + [CPT_C] = "Control", + [CPT_M] = "Machine", + [CPT_S] = "Supervisor", + [CPT_U] = "User", + }; + + return map[type]; +} + +// +// Return the number of hart contexts in a cluster +// +inline static Uns32 getNumHarts(riscvP root) { + return root->numHarts ? : 1; +} + +// +// Return the base address of the cluster CLIC block +// +inline static Uns64 getCLICLow(riscvP root) { + return root->configInfo.csr.mclicbase.u64.bits; +} + +// +// Return the page index of the given offset +// +inline static Uns32 getCLICPage(Uns32 offset) { + return offset/4096; +} + +// +// Return the word index of the offset within a page +// +inline static Uns32 getCLICPageWord(Uns32 offset) { + return (offset%4096)/4; +} + +// +// Return the word index of the offset within a page +// +inline static Uns32 getCLICIntIndex(Uns32 offset) { + return ((offset-4096)/4)%4096; +} + +// +// Return the byte index of the offset within a word +// +inline static Uns32 getCLICWordByte(Uns32 offset) { + return offset%4; +} + +// +// Return type of an interrupt field accesed at the given offset +// +inline static CLICIntFieldType getCLICIntFieldType(Uns32 offset) { + return getCLICWordByte(offset); +} + +// +// Convert from 1k CLIC page index to 4k interrupt page index +// +inline static Uns32 get4kIntPage(Uns32 page) { + return (page-1)/4; +} + +// +// Return the CLIC page type being accessed at the given offset +// +static CLICPageType getCLICPageType(riscvP root, Uns32 offset) { + + Uns32 page = getCLICPage(offset); + CLICPageType type = CPT_C; + + if(page) { + + // calculate page type from offset + type = CPT_M + get4kIntPage(page)/getNumHarts(root); + + // sanity check result + VMI_ASSERT((type>=CPT_M) && (type<=CPT_U), "illegal page type %u", type); + } + + return type; +} + +// +// Return the CLIC page mode being accessed at the given offset +// +static riscvMode getCLICPageMode(riscvP root, Uns32 offset) { + + CLICPageType type = getCLICPageType(root, offset); + + VMI_ASSERT(type!=CPT_C, "expected interrupt page"); + + static const riscvMode map[] = { + [CPT_M] = RISCV_MODE_MACHINE, + [CPT_S] = RISCV_MODE_SUPERVISOR, + [CPT_U] = RISCV_MODE_USER + }; + + return map[type]; +} + +// +// Return the CLIC hart index being accessed at the given offset +// +static Int32 getCLICHartIndex(riscvP root, Uns32 offset) { + + Uns32 page = getCLICPage(offset); + Int32 index = -1; + + if(page) { + index = get4kIntPage(page)%getNumHarts(root); + } + + return index; +} + +// +// Return the hart being accessed at the given offset +// +static riscvP getCLICHart(riscvP root, Uns32 offset) { + + Int32 index = getCLICHartIndex(root, offset); + + VMI_ASSERT(index>=0, "illegal hart index"); + + return root->clic.harts[index]; +} + +// +// Emit debug for CLIC region access +// +static void debugCLICAccess(riscvP root, Uns32 offset, const char *access) { + + CLICPageType type = getCLICPageType(root, offset); + Int32 hart = getCLICHartIndex(root, offset); + const char *name = mapCLICPageTypeName(type); + + if(type==CPT_C) { + + // control page access + vmiPrintf( + "CLIC %s offset=0x%x %s\n", + access, offset, name + ); + + } else { + + // interrupt page access + vmiPrintf( + "CLIC %s offset=0x%x %s (hart %d)\n", + access, offset, name, hart + ); + } +} + +// +// Return mask of always-1 bits in clicintctl +// +static Uns32 getCLICIntCtl1Bits(riscvP hart) { + + riscvP root = hart->smpRoot; + Uns32 CLICINTCTLBITS = root->clic.clicinfo.fields.CLICINTCTLBITS; + + return ((1<<(8-CLICINTCTLBITS))-1); +} + +// +// Return the composed value for the indexed interrupt +// +inline static Uns32 getCLICInterruptValue(riscvP hart, Uns32 index) { + return hart->clic.intState[index].value32; +} + +// +// Return the indicated field for the indexed interrupt +// +inline static Uns8 getCLICInterruptField( + riscvP hart, + Uns32 intIndex, + CLICIntFieldType type +) { + return hart->clic.intState[intIndex].fields[type]; +} + +// +// Set the indicated field for the indexed interrupt +// +inline static void setCLICInterruptField( + riscvP hart, + Uns32 intIndex, + CLICIntFieldType type, + Uns8 newValue +) { + hart->clic.intState[intIndex].fields[type] = newValue; +} + +// +// Update the indicated field for the indexed interrupt and refresh interrupt +// stte f it has changed +// +static void updateCLICInterruptField( + riscvP hart, + Uns32 intIndex, + CLICIntFieldType type, + Uns8 newValue +) { + if(getCLICInterruptField(hart, intIndex, type) != newValue) { + setCLICInterruptField(hart, intIndex, type, newValue); + riscvTestInterrupt(hart); + } +} + +// +// Return rending for the indexed interrupt +// +inline static Bool getCLICInterruptPending(riscvP hart, Uns32 intIndex) { + return getCLICInterruptField(hart, intIndex, CIT_clicintip); +} + +// +// Return enable for the indexed interrupt +// +inline static Bool getCLICInterruptEnable(riscvP hart, Uns32 intIndex) { + return getCLICInterruptField(hart, intIndex, CIT_clicintie); +} + +// +// Return clicintattr for the indexed interrupt +// +inline static CLIC_REG_TYPE(clicintattr) getCLICInterruptAttr( + riscvP hart, + Uns32 intIndex +) { + CLIC_REG_DECL(clicintattr) = { + bits:getCLICInterruptField(hart, intIndex, CIT_clicintattr) + }; + + return clicintattr; +} + +// +// Update state when CLIC pending+enabled state changes for the given interrupt +// +static void updateCLICPendingEnable(riscvP hart, Uns32 intIndex, Bool newIPE) { + + Uns32 wordIndex = intIndex/64; + Uns32 bitIndex = intIndex%64; + Uns64 mask = (1ULL<clic.ipe[wordIndex] |= mask; + } else { + hart->clic.ipe[wordIndex] &= ~mask; + } + + riscvTestInterrupt(hart); +} + +// +// Write clicintip for the indexed interrupt +// +static void writeCLICInterruptPending( + riscvP hart, + Uns32 intIndex, + Uns8 newValue +) { + riscvCLICIntStateP intState = &hart->clic.intState[intIndex]; + Bool oldIE = intState->fields[CIT_clicintie]; + Bool newIP = newValue&1; + + // update field, detecting change in pending+enabled + Bool oldIPE = oldIE && intState->fields[CIT_clicintip]; + intState->fields[CIT_clicintip] = newIP; + Bool newIPE = oldIE && newIP; + + // update state if pending+enabled has changed + if(oldIPE!=newIPE) { + updateCLICPendingEnable(hart, intIndex, newIPE); + } +} + +// +// Write clicintie for the indexed interrupt +// +static void writeCLICInterruptEnable( + riscvP hart, + Uns32 intIndex, + Uns8 newValue +) { + riscvCLICIntStateP intState = &hart->clic.intState[intIndex]; + Bool oldIP = intState->fields[CIT_clicintip]; + Bool newIE = newValue&1; + + // update field, detecting change in pending+enabled + Bool oldIPE = oldIP && intState->fields[CIT_clicintie]; + intState->fields[CIT_clicintie] = newIE; + Bool newIPE = oldIP && newIE; + + // update state if pending+enabled has changed + if(oldIPE!=newIPE) { + updateCLICPendingEnable(hart, intIndex, newIPE); + } +} + +// +// Write clicintattr for the indexed interrupt +// +static void writeCLICInterruptAttr( + riscvP hart, + Uns32 intIndex, + Uns8 newValue, + riscvMode pageMode +) { + CLIC_REG_DECL(clicintattr) = {bits:newValue}; + riscvP root = hart->smpRoot; + Uns32 CLICCFGMBITS = root->configInfo.CLICCFGMBITS; + riscvMode intMode = clicintattr.fields.mode; + + // clear WPRI field + clicintattr.fields._u1 = 0; + + // clear shv field if Selective Hardware Vectoring is not implemented + if(!root->clic.cliccfg.fields.nvbits) { + clicintattr.fields.shv = 0; + } + + // clamp mode to legal values + if( + // do not allow mode to be greater than page mode + (intMode>pageMode) || + // if CLICCFGMBITS is zero do not allow mode change from Machine + (CLICCFGMBITS==0) || + // do not allow mode change to illegal H mode + (intMode==RISCV_MODE_HYPERVISOR) || + // do not allow mode change to S mode if only M and U supported + ((CLICCFGMBITS<2) && (intMode==RISCV_MODE_SUPERVISOR)) || + // do not allow mode change to U mode if N extension is absent + ((intMode==RISCV_MODE_USER) && !(hart->configInfo.arch&ISA_N)) + ) { + intMode = pageMode; + } + + // set mode field + clicintattr.fields.mode = intMode; + + // update field with corrected attributes + updateCLICInterruptField(hart, intIndex, CIT_clicintattr, clicintattr.bits); +} + +// +// Write clicintctl for the indexed interrupt +// +static void writeCLICInterruptCtl( + riscvP hart, + Uns32 intIndex, + Uns8 newValue +) { + newValue |= getCLICIntCtl1Bits(hart); + + // update field with corrected value + updateCLICInterruptField(hart, intIndex, CIT_clicintctl, newValue); +} + +// +// Return the privilege mode for the interrupt with the given index +// +static riscvMode getCLICInterruptMode(riscvP hart, Uns32 intIndex) { + + CLIC_REG_DECL(clicintattr) = getCLICInterruptAttr(hart, intIndex); + riscvP root = hart->smpRoot; + Uns8 attr_mode = clicintattr.fields.mode; + Uns32 nmbits = root->clic.cliccfg.fields.nmbits; + riscvMode intMode = RISCV_MODE_MACHINE; + + if(nmbits == 0) { + + // priv-modes nmbits clicintattr[i].mode Interpretation + // --- 0 xx M-mode interrupt + + } else if(root->configInfo.CLICCFGMBITS == 1) { + + // priv-modes nmbits clicintattr[i].mode Interpretation + // M/U 1 0x U-mode interrupt + // M/U 1 1x M-mode interrupt + intMode = (attr_mode&2) ? RISCV_MODE_MACHINE : RISCV_MODE_USER; + + } else { + + // priv-modes nmbits clicintattr[i].mode Interpretation + // M/S/U 1 0x S-mode interrupt + // M/S/U 1 1x M-mode interrupt + // M/S/U 2 00 U-mode interrupt + // M/S/U 2 01 S-mode interrupt + // M/S/U 2 10 Reserved (or extended S-mode) + // M/S/U 2 11 M-mode interrupt + intMode = attr_mode | (nmbits==1); + } + + return intMode; +} + +// +// Is the interrupt accessed at the given offset visible? +// +static Bool accessCLICInterrupt(riscvP root, Uns32 offset) { + + riscvP hart = getCLICHart(root, offset); + Uns32 intIndex = getCLICIntIndex(offset); + riscvException intCode = intToException(intIndex); + Bool ok = False; + + if((intIndex RD_CSR_FIELD(_P, mintstatus, _x##il)) && \ + (_LEVEL > RD_CSR_FIELD(_P, _x##intthresh, th)) \ + ) \ + ) \ +) + +// +// Refresh pending CLIC interrupt when state changes +// +static void refreshPendingAndEnabledCLIC(riscvP hart) { + + riscvP root = hart->smpRoot; + Uns32 maxRank = 0; + Int32 id = RV_NO_INT; + Uns32 wordIndex; + + // reset presented interrupt details + hart->clic.sel.priv = 0; + hart->clic.sel.id = id; + hart->clic.sel.level = 0; + hart->clic.sel.shv = False; + + // scan for pending+enabled interrupts + for(wordIndex=0; wordIndexipDWords; wordIndex++) { + + Uns64 pendingEnabled = hart->clic.ipe[wordIndex]; + + // select highest-priority pending-and-enabled interrupt + if(pendingEnabled) { + + Uns32 i = 0; + + do { + + if(pendingEnabled&1) { + + Uns32 intIndex = wordIndex*64+i; + + // get control fields for the indexed interrupt + Uns8 clicintctl = getCLICInterruptField( + hart, intIndex, CIT_clicintctl + ); + + // get target mode for the indexed interrupt + riscvMode mode = getCLICInterruptMode(hart, intIndex); + + // construct rank (where target mode is most-significant + // part) + Uns32 rank = (mode<<8) | clicintctl; + + // select highest-priority interrupt (highest-numbered + // interrupt wins in a tie) + if(maxRank<=rank) { + maxRank = rank; + id = intIndex; + } + } + + // step to next potential pending-and-enabled interrupt + pendingEnabled >>= 1; + i++; + + } while(pendingEnabled); + } + } + + // handle highest-priority enabled interrupt + if(id != RV_NO_INT) { + + // get control fields for highest-priority pending interrupt + CLIC_REG_DECL(clicintattr) = getCLICInterruptAttr(hart, id); + Uns8 clicintctl = getCLICInterruptField(hart, id, CIT_clicintctl); + + // get mask of bits in clicintctl representing level + Uns32 nlbits = root->clic.cliccfg.fields.nlbits; + Uns8 nlbitsMask = ~((1<<(8-nlbits)) - 1); + + // get interrupt target mode + riscvMode priv = getCLICInterruptMode(hart, id); + + // get interrupt level with least-significant bits set to 1 + Uns8 level = (clicintctl & nlbitsMask) | ~nlbitsMask; + + // update presented interrupt + hart->clic.sel.priv = priv; + hart->clic.sel.id = id; + hart->clic.sel.level = level; + hart->clic.sel.shv = clicintattr.fields.shv; + + Bool enable = False; + riscvMode mode = getCurrentMode(hart); + + // determine whether presented interrupt is enabled + if(hart->pendEnab.priv>priv) { + // basic mode interrupt is higher priority + } else if(mode>priv) { + // execution priority is higher than interrupt priority + } else if(priv==RISCV_MODE_MACHINE) { + enable = PRESENT_INT_CLIC(hart, M, m, level, mode); + } else if(priv==RISCV_MODE_SUPERVISOR) { + enable = PRESENT_INT_CLIC(hart, S, s, level, mode); + } else if(priv==RISCV_MODE_USER) { + enable = PRESENT_INT_CLIC(hart, U, u, level, mode); + } else { + VMI_ABORT("unimplemented case"); // LCOV_EXCL_LINE + } + + // update pending and enabled interrupt if required + if(enable) { + hart->pendEnab.id = id; + hart->pendEnab.priv = priv; + hart->pendEnab.level = level; + hart->pendEnab.isCLIC = True; + } + } + + // print exception status + if(RISCV_DEBUG_EXCEPT(hart)) { + + // report only if interrupt state changes + if(memcmp(&hart->clicState, &hart->clic.sel, sizeof(hart->clicState))) { + + vmiMessage("I", CPU_PREFIX "_ISC", + SRCREF_FMT + "CLIC ID:%d MODE:%u LEVEL:%u SHV:%u", + SRCREF_ARGS(hart, getPC(hart)), + hart->clic.sel.id, + hart->clic.sel.priv, + hart->clic.sel.level, + hart->clic.sel.shv + ); + + // track previous pending state + hart->clicState = hart->clic.sel; + } + } +} + +// +// Refresh CliC pending+enable mask (after restore) +// +static void refreshCLICIPE(riscvP hart) { + + Uns32 intNum = getIntNum(hart); + Uns32 i; + + // clear current pending+enabled state + for(i=0; iipDWords; i++) { + hart->clic.ipe[i] = 0; + } + + // reinstate pending+enabled state from interrupt state + for(i=0; iclic.ipe[wordIndex] |= mask; + } + } +} + +// +// Acknowledge CLIC-sourced interrupt +// +void riscvAcknowledgeCLICInt(riscvP hart, Uns32 intIndex) { + + CLIC_REG_DECL(clicintattr) = getCLICInterruptAttr(hart, intIndex); + + // determine interrupt configuration + Bool isEdge = clicintattr.fields.trig&1; + + // deassert interrupt if edge triggered, or refresh pending state if not + if(isEdge) { + writeCLICInterruptPending(hart, intIndex, 0); + } else { + refreshPendingAndEnabled(hart); + } +} + +// +// Update CLIC state on input signal change +// +static void updateCLICInput(riscvP hart, Uns32 intIndex, Bool newValue) { + + CLIC_REG_DECL(clicintattr) = getCLICInterruptAttr(hart, intIndex); + + // determine interrupt configuration + Bool isEdge = clicintattr.fields.trig&1; + Bool activeLow = clicintattr.fields.trig&2; + + // handle active low inputs + newValue ^= activeLow; + + // apply new value if either level triggered or edge triggered and asserted + if(!isEdge || newValue) { + writeCLICInterruptPending(hart, intIndex, newValue); + } +} + +// +// Update CLIC pending interrupt state for a leaf processor +// +static VMI_SMP_ITER_FN(refreshCCLICInterruptAllCB) { + if(vmirtGetSMPCpuType(processor)==SMP_TYPE_LEAF) { + riscvTestInterrupt((riscvP)processor); + } +} + +// +// Refresh CLIC pending interrupt state for all processors +// +static void refreshCCLICInterruptAll(riscvP riscv) { + vmirtIterAllProcessors( + (vmiProcessorP)riscv->smpRoot, + refreshCCLICInterruptAllCB, + 0 + ); } // -// Initialize mask of implemented exceptions +// Update the value of cliccfg // -void riscvSetExceptionMask(riscvP riscv) { +static void cliccfgW(riscvP root, Uns8 newValue) { - riscvArchitecture arch = riscv->configInfo.arch; - Uns64 exceptionMask = 0; - Uns64 interruptMask = 0; - riscvExceptionDescCP thisDesc; + CLIC_REG_DECL(cliccfg) = {bits:newValue}; - // get exceptions and standard interrupts supported on the current - // architecture - for(thisDesc=exceptions; thisDesc->vmiInfo.name; thisDesc++) { + // clear WPRI bits in the new value + cliccfg.fields._u1 = 0; - riscvException code = thisDesc->vmiInfo.code; + // clamp nmbits in the new value to legal maximum + if(cliccfg.fields.nmbits>root->configInfo.CLICCFGMBITS) { + cliccfg.fields.nmbits = root->configInfo.CLICCFGMBITS; + } - if((arch&thisDesc->arch)!=thisDesc->arch) { - // not implemented by this variant - } else if(code8) { + cliccfg.fields.nlbits = 8; } - // save composed exception mask result - riscv->exceptionMask = exceptionMask; + // preserve read-only nvbits field + cliccfg.fields.nvbits = root->configInfo.CLICSELHVEC; - // save composed interrupt mask result (including extra local interrupts - // and excluding interrupts that are explicitly absent) - riscv->interruptMask = ( - (interruptMask | riscvGetLocalIntMask(riscv)) & - ~riscv->configInfo.unimp_int_mask - ); + // update register and refresh interrupt state if changed + if(root->clic.cliccfg.bits!=cliccfg.bits) { + root->clic.cliccfg.bits = cliccfg.bits; + refreshCCLICInterruptAll(root); + } } // -// Free exception state +// Read one byte from the CLIC // -void riscvExceptFree(riscvP riscv) { - - if(riscv->exceptions) { - - Uns32 numLocal = getLocalIntNum(riscv); - Uns32 numNotLocal = riscv->exceptionNum - numLocal; - vmiExceptionInfoCP local = &riscv->exceptions[numNotLocal]; - Uns32 i; +static Uns8 readCLICInt(riscvP root, Uns32 offset) { - // free local exception description strings - for(i=0; iexceptions); - riscv->exceptions = 0; + // debug access if required + if(RISCV_DEBUG_EXCEPT(root)) { + debugCLICAccess(root, offset, "READ"); } -} + // direct access either to interrupt or control page + if(getCLICPage(offset)) { + result = readCLICInterrupt(root, offset); + } else if(word==0) { + result = root->clic.cliccfg.bits; + } else if(word==1) { + result = root->clic.clicinfo.bits; + } -//////////////////////////////////////////////////////////////////////////////// -// EXTERNAL INTERRUPT UTILITIES -//////////////////////////////////////////////////////////////////////////////// + // extract byte from result + return result >> (byte*8); +} // -// Detect rising edge +// Write one byte to the CLIC // -inline static Bool posedge(Bool old, Bool new) { - return !old && new; +static void writeCLICInt(riscvP root, Uns32 offset, Uns8 newValue) { + + // debug access if required + if(RISCV_DEBUG_EXCEPT(root)) { + debugCLICAccess(root, offset, "WRITE"); + } + + // direct access either to interrupt or control page + if(getCLICPage(offset)) { + writeCLICInterrupt(root, offset, newValue); + } else if(offset==0) { + cliccfgW(root, newValue); + } } // -// Detect falling edge +// Read CLIC register // -inline static Bool negedge(Uns32 old, Uns32 new) { - return old && !new; +static VMI_MEM_READ_FN(readCLIC) { + + riscvP root = userData; + Uns8 *value8 = value; + Uns64 lowAddr = getCLICLow(root); + Uns32 i; + + for(i=0; iip[0], - .pendingInternal = riscv->swip, - .mideleg = RD_CSR(riscv, mideleg), - .sideleg = RD_CSR(riscv, sideleg), - .mie = RD_CSR_FIELD(riscv, mstatus, MIE), - .sie = RD_CSR_FIELD(riscv, mstatus, SIE), - .uie = RD_CSR_FIELD(riscv, mstatus, UIE), - }; +// +// Allocate CLIC data structures +// +void riscvNewCLIC(riscvP riscv, Uns32 index) { - // report only if interrupt state changes - if(memcmp(&riscv->intState, &intState, sizeof(intState))) { + // indicate no CLIC interrupt is pending initially (or CLIC is absent) + riscv->clic.sel.id = RV_NO_INT; - vmiMessage("I", CPU_PREFIX "_IS", - SRCREF_FMT - "PENDING+ENABLED="FMT_A08x" PENDING="FMT_A08x" " - "[EXTERNAL_IP="FMT_A08x",SW_IP=%08x] " - "MIDELEG=%08x SIDELEG=%08x MSTATUS.[MSU]IE=%u%u%u", - SRCREF_ARGS(riscv, getPC(riscv)), - intState.pendingEnabled, - intState.pending, - intState.pendingExternal, - intState.pendingInternal, - intState.mideleg, - intState.sideleg, - intState.mie, - intState.sie, - intState.uie - ); + // remaining structures are allocated only if CLIC is present + if(CLICPresent(riscv)) { - // track previous pending state - riscv->intState = intState; - } - } + riscvP root = riscv->smpRoot; + riscvPP table = root->clic.harts; + Uns32 numHarts = getNumHarts(root); + Uns32 intNum = getIntNum(riscv); + Uns32 i; - // restart processor if it is halted in WFI state and local interrupts are - // pending (even if masked) - if(getPendingInterrupts(riscv)) { - restartProcessor(riscv, RVD_RESTART_WFI); - } + // do actions required when first leaf hart is encountered + if(!table) { - // schedule asynchronous interrupt handling if interrupts are pending and - // enabled - if(pendingEnabled) { - vmirtDoSynchronousInterrupt((vmiProcessorP)riscv); - } -} + // initialise read-only fields in cliccfg using configuration options + root->clic.cliccfg.fields.nvbits = root->configInfo.CLICSELHVEC; -// -// Reset the processor -// -void riscvReset(riscvP riscv) { + // initialise read-only fields in clicinfo using configuration options + root->clic.clicinfo.fields.num_interrupt = getIntNum(root); + root->clic.clicinfo.fields.version = root->configInfo.CLICVERSION; + root->clic.clicinfo.fields.CLICINTCTLBITS = root->configInfo.CLICINTCTLBITS; - riscvExtCBP extCB; + // allocate hart table + table = root->clic.harts = STYPE_CALLOC_N(riscvP, numHarts); + } - // restart the processor from any halted state - restartProcessor(riscv, RVD_RESTART_RESET); + // sanity check hart index and table + VMI_ASSERT( + indexclic.intState = STYPE_CALLOC_N(riscvCLICIntState, intNum); + riscv->clic.ipe = STYPE_CALLOC_N(Uns64, riscv->ipDWords); - // reset CSR state - riscvCSRReset(riscv); + // define default values for interrupt control state + CLIC_REG_DECL(clicintattr) = {fields:{mode:RISCV_MODE_MACHINE}}; + Uns32 clicintctl = getCLICIntCtl1Bits(riscv); - // notify dependent model of reset event - for(extCB=riscv->extCBs; extCB; extCB=extCB->next) { - if(extCB->resetNotifier) { - extCB->resetNotifier(riscv, extCB->clientData); + // initialise control state for interrupts + for(i=0; iexception = 0; - - // set address at which to execute - vmirtSetPCException((vmiProcessorP)riscv, riscv->configInfo.reset_address); - - // enter Debug mode out of reset if required - riscv->netValue.resethaltreqS = riscv->netValue.resethaltreq; } // -// Do NMI interrupt +// Free field in CLIC structure if required // -static void doNMI(riscvP riscv) { - - // restart the processor from any halted state - restartProcessor(riscv, RVD_RESTART_NMI); - - // switch to Machine mode - riscvSetMode(riscv, RISCV_MODE_MACHINE); - - // update cause register (to zero) - WR_CSR(riscv, mcause, 0); +#define CLIC_FREE(_P, _F) if(_P->clic._F) { \ + STYPE_FREE(_P->clic._F); \ + _P->clic._F = 0; \ +} - // update mepc to hold next instruction address - WR_CSR(riscv, mepc, getEPC(riscv)); +// +// Free CLIC data structures +// +void riscvFreeCLIC(riscvP riscv) { + CLIC_FREE(riscv, harts); + CLIC_FREE(riscv, intState); + CLIC_FREE(riscv, ipe); +} - // indicate the taken exception - riscv->exception = 0; +// +// Reset CLIC +// +static void resetCLIC(riscvP riscv) { - // set address at which to execute - vmirtSetPCException((vmiProcessorP)riscv, riscv->configInfo.nmi_address); + if(riscv->clic.intState) { + cliccfgW(riscv, 0); + } } @@ -1699,8 +2980,8 @@ static VMI_NET_CHANGE_FN(nmiPortCB) { riscvP riscv = ii->hart; Bool oldValue = riscv->netValue.nmi; - // do NMI actions when signal goes low unless in Debug mode - if(!inDebugMode(riscv) && negedge(oldValue, newValue)) { + // do NMI actions when signal goes high unless in Debug mode + if(!inDebugMode(riscv) && posedge(oldValue, newValue)) { doNMI(riscv); } @@ -1738,6 +3019,19 @@ static VMI_NET_CHANGE_FN(resethaltreqPortCB) { riscv->netValue.resethaltreq = newValue; } +// +// SC_valid signal +// +static VMI_NET_CHANGE_FN(SCValidPortCB) { + + riscvInterruptInfoP ii = userData; + riscvP riscv = ii->hart; + + if(!newValue) { + clearEA(riscv); + } +} + // // Generic interrupt signal // @@ -1757,13 +3051,22 @@ static VMI_NET_CHANGE_FN(interruptPortCB) { index, maxNum-1 ); + // update pending bit if(newValue) { riscv->ip[offset] |= mask; } else { riscv->ip[offset] &= ~mask; } - riscvUpdatePending(riscv); + // update CLIC interrupt controller if required + if(CLICPresent(riscv)) { + updateCLICInput(riscv, index, newValue); + } + + // update basic interrupt controller if required + if(basicICPresent(riscv)) { + riscvUpdatePending(riscv); + } } // @@ -1785,6 +3088,23 @@ static VMI_NET_CHANGE_FN(interruptIDPortCB) { riscv->extInt[offset] = newValue; } +// +// Artifact signal deferring taking of interrupts when high +// +static VMI_NET_CHANGE_FN(deferintPortCB) { + + riscvInterruptInfoP ii = userData; + riscvP riscv = ii->hart; + Bool oldValue = riscv->netValue.deferint; + + riscv->netValue.deferint = newValue; + + // handle possible interrupt when signal is released + if(negedge(oldValue, newValue)) { + handlePendingAndEnabled(riscv); + } +} + //////////////////////////////////////////////////////////////////////////////// // NET PORT CREATION @@ -1876,7 +3196,7 @@ void riscvNewNetPorts(riscvP riscv) { vmiExceptionInfoCP info = &this->vmiInfo; riscvException code = info->code; - if((code>=riscv_E_Interrupt) && hasException(riscv, code)) { + if(isInterrupt(code) && hasException(riscv, code)) { tail = newNetPort( riscv, @@ -1885,7 +3205,7 @@ void riscvNewNetPorts(riscvP riscv) { vmi_NP_INPUT, interruptPortCB, info->description, - code - riscv_E_Interrupt, + exceptionToInt(code), 0 ); @@ -1945,7 +3265,7 @@ void riscvNewNetPorts(riscvP riscv) { vmi_NP_INPUT, interruptPortCB, desc, - code - riscv_E_Interrupt, + exceptionToInt(code), 0 ); } @@ -1989,6 +3309,70 @@ void riscvNewNetPorts(riscvP riscv) { 0 ); } + + // add ports for external management of LR/SC locking if required + if(riscv->configInfo.arch&ISA_A) { + + // allocate LR_address port + tail = newNetPort( + riscv, + tail, + "LR_address", + vmi_NP_OUTPUT, + 0, + "Port written with effective address for LR instruction", + 0, + &riscv->LRAddressHandle + ); + + // allocate SC_address port + tail = newNetPort( + riscv, + tail, + "SC_address", + vmi_NP_OUTPUT, + 0, + "Port written with effective address for SC instruction", + 0, + &riscv->SCAddressHandle + ); + + // allocate SC_valid port + tail = newNetPort( + riscv, + tail, + "SC_valid", + vmi_NP_INPUT, + SCValidPortCB, + "SC_address valid input signal", + 0, + 0 + ); + + // allocate SC_valid port + tail = newNetPort( + riscv, + tail, + "AMO_active", + vmi_NP_OUTPUT, + 0, + "Port written with code indicating active AMO", + 0, + &riscv->AMOActiveHandle + ); + } + + // allocate deferint port + tail = newNetPort( + riscv, + tail, + "deferint", + vmi_NP_INPUT, + deferintPortCB, + "Artifact signal causing interrupts to be held off when high", + 0, + 0 + ); } // @@ -2066,6 +3450,13 @@ void riscvFreeTimers(riscvP riscv) { // SAVE/RESTORE SUPPORT //////////////////////////////////////////////////////////////////////////////// +// +// Save/restore field keys +// +#define RV_IP "ip" +#define RV_CLIC_INTSTATE "clic.intState" +#define RV_STEP_TIMER "stepTimer" + // // Save net state not covered by register read/write API // @@ -2077,11 +3468,30 @@ void riscvNetSave( if(phase==SRT_END_CORE) { // save pending interrupt state - vmirtSave(cxt, "ip", riscv->ip, riscv->ipDWords*8); + vmirtSave(cxt, RV_IP, riscv->ip, riscv->ipDWords*8); // save latched control input state VMIRT_SAVE_FIELD(cxt, riscv, netValue); - VMIRT_SAVE_FIELD(cxt, riscv, intState); + + // restore basic-mode interrupt state + if(basicICPresent(riscv)) { + VMIRT_SAVE_FIELD(cxt, riscv, intState); + } + + // restore CLIC-mode interrupt state + if(CLICPresent(riscv)) { + + // save CLIC configuration (root level) + VMIRT_SAVE_FIELD(cxt, riscv->smpRoot, clic.cliccfg); + + // save CLIC interrupt state + vmirtSave( + cxt, + RV_CLIC_INTSTATE, + riscv->clic.intState, + sizeof(*riscv->clic.intState)*getIntNum(riscv) + ); + } } } @@ -2096,11 +3506,33 @@ void riscvNetRestore( if(phase==SRT_END_CORE) { // restore pending interrupt state - vmirtRestore(cxt, "ip", riscv->ip, riscv->ipDWords*8); + vmirtRestore(cxt, RV_IP, riscv->ip, riscv->ipDWords*8); // restore latched control input state VMIRT_RESTORE_FIELD(cxt, riscv, netValue); - VMIRT_RESTORE_FIELD(cxt, riscv, intState); + + // restore basic-mode interrupt state + if(basicICPresent(riscv)) { + VMIRT_RESTORE_FIELD(cxt, riscv, intState); + } + + // restore CLIC-mode interrupt state + if(CLICPresent(riscv)) { + + // restore CLIC configuration (root level) + VMIRT_RESTORE_FIELD(cxt, riscv->smpRoot, clic.cliccfg); + + // restore CLIC interrupt state + vmirtRestore( + cxt, + RV_CLIC_INTSTATE, + riscv->clic.intState, + sizeof(*riscv->clic.intState)*getIntNum(riscv) + ); + + // refresh CliC pending+enable mask + refreshCLICIPE(riscv); + } // refresh core state riscvTestInterrupt(riscv); @@ -2118,7 +3550,7 @@ void riscvTimerSave( if(phase==SRT_END_CORE) { if(riscv->stepTimer) { - vmirtSaveModelTimer(cxt, "stepTimer", riscv->stepTimer); + vmirtSaveModelTimer(cxt, RV_STEP_TIMER, riscv->stepTimer); } } } @@ -2134,7 +3566,7 @@ void riscvTimerRestore( if(phase==SRT_END_CORE) { if(riscv->stepTimer) { - vmirtRestoreModelTimer(cxt, "stepTimer", riscv->stepTimer); + vmirtRestoreModelTimer(cxt, RV_STEP_TIMER, riscv->stepTimer); } } } diff --git a/source/riscvExceptions.h b/source/riscvExceptions.h index 1980d77..9020fd9 100644 --- a/source/riscvExceptions.h +++ b/source/riscvExceptions.h @@ -157,6 +157,26 @@ void riscvNewTimers(riscvP riscv); // void riscvFreeTimers(riscvP riscv); +// +// Acknowledge CLIC-sourced interrupt +// +void riscvAcknowledgeCLICInt(riscvP hart, Uns32 intIndex); + +// +// Create CLIC memory-mapped block and data structures +// +void riscvMapCLICDomain(riscvP root, memDomainP CLICDomain); + +// +// Allocate CLIC data structures +// +void riscvNewCLIC(riscvP riscv, Uns32 index); + +// +// Free CLIC data structures +// +void riscvFreeCLIC(riscvP riscv); + // // Save net state not covered by register read/write API // diff --git a/source/riscvFunctions.h b/source/riscvFunctions.h index 88ec785..4459d21 100644 --- a/source/riscvFunctions.h +++ b/source/riscvFunctions.h @@ -28,6 +28,7 @@ // constructor & destructor +VMI_SMP_NAME_FN(riscvGetSMPName); VMI_CONSTRUCTOR_FN(riscvConstructor); VMI_POST_CONSTRUCTOR_FN(riscvPostConstructor); VMI_VMINIT_FN(riscvVMInit); @@ -62,6 +63,10 @@ VMI_RD_ALIGN_EXCEPT_FN(riscvRdAlignExcept); VMI_WR_ALIGN_EXCEPT_FN(riscvWrAlignExcept); VMI_RD_ABORT_EXCEPT_FN(riscvRdAbortExcept); VMI_WR_ABORT_EXCEPT_FN(riscvWrAbortExcept); +VMI_RD_DEVICE_EXCEPT_FN(riscvRdDeviceExcept); +VMI_WR_DEVICE_EXCEPT_FN(riscvWrDeviceExcept); +VMI_RD_WR_SNAP_FN(riscvRdSnap); +VMI_RD_WR_SNAP_FN(riscvWrSnap); VMI_IFETCH_FN(riscvIFetchExcept); VMI_ARITH_RESULT_FN(riscvArithResult); diff --git a/source/riscvInstructionInfo.h b/source/riscvInstructionInfo.h index 4158670..f13869f 100644 --- a/source/riscvInstructionInfo.h +++ b/source/riscvInstructionInfo.h @@ -626,8 +626,7 @@ arch : _ARCH, \ r1 : RS_X_11_7, \ r2 : RS_X_19_15, \ - vsew : VSEW_24_22, \ - vlmul : VLMUL_21_20, \ + vtype : VTYPE_30_20, \ wX : WX_3, \ } @@ -703,6 +702,79 @@ VIType : RV_VIT_V, \ } +// +// Attribute entries for 32-bit instructions like VLE8 +// +#define ATTR32_VLE(_NAME, _GENERIC, _ARCH, _OPCODE) [IT32_##_NAME] = { \ + opcode : _OPCODE, \ + format : FMT_R1_MEM2_RM, \ + type : RV_IT_##_GENERIC, \ + arch : _ARCH, \ + r1 : RS_V_11_7, \ + r2 : RS_X_19_15, \ + mask : RS_V_M_25, \ + memBits : MBS_EEW, \ + whole : WR_23, \ + ff : FF_24, \ + nf : NF_31_29, \ + VIType : RV_VIT_V, \ + eew : EEW_28_14_12, \ +} + +// +// Attribute entries for 32-bit instructions like VLSE8 +// +#define ATTR32_VLSE(_NAME, _GENERIC, _ARCH, _OPCODE) [IT32_##_NAME] = { \ + opcode : _OPCODE, \ + format : FMT_R1_MEM2_R3_RM, \ + type : RV_IT_##_GENERIC, \ + arch : _ARCH, \ + r1 : RS_V_11_7, \ + r2 : RS_X_19_15, \ + r3 : RS_X_24_20, \ + mask : RS_V_M_25, \ + memBits : MBS_EEW, \ + nf : NF_31_29, \ + VIType : RV_VIT_V, \ + eew : EEW_28_14_12, \ +} + +// +// Attribute entries for 32-bit instructions like VLXEI8 +// +#define ATTR32_VLXEI(_NAME, _GENERIC, _ARCH, _OPCODE) [IT32_##_NAME] = { \ + opcode : _OPCODE, \ + format : FMT_R1_MEM2_R3_RM, \ + type : RV_IT_##_GENERIC, \ + arch : _ARCH, \ + r1 : RS_V_11_7, \ + r2 : RS_X_19_15, \ + r3 : RS_V_24_20, \ + mask : RS_V_M_25, \ + memBits : MBS_SEW, \ + nf : NF_31_29, \ + VIType : RV_VIT_V, \ + eew : EEW_28_14_12, \ +} + +// +// Attribute entries for 32-bit instructions like VAMOADDEI8 +// +#define ATTR32_VAMOADDEI(_NAME, _GENERIC, _ARCH, _OPCODE) [IT32_##_NAME] = { \ + opcode : _OPCODE, \ + format : FMT_R1_R3_MEM2_R4_RM,\ + type : RV_IT_##_GENERIC, \ + arch : _ARCH, \ + r1 : RS_V_11_7_Z26, \ + r2 : RS_X_19_15, \ + r3 : RS_V_24_20, \ + r4 : RS_V_11_7, \ + mask : RS_V_M_25, \ + memBits : MBS_SEW, \ + VIType : RV_VIT_V, \ + eew : EEW_14_12, \ +} + // // Attribute entries for 32-bit instructions like VFSQRT.V // @@ -717,6 +789,21 @@ VIType : RV_VIT_V, \ } +// +// Attribute entries for 32-bit instructions like VFCVT.RTZ.X.F.V +// +#define ATTR32_V_RTZ(_NAME, _GENERIC, _ARCH, _OPCODE) [IT32_##_NAME] = { \ + opcode : _OPCODE, \ + format : FMT_R1_R2_RM, \ + type : RV_IT_##_GENERIC, \ + arch : _ARCH, \ + r1 : RS_V_11_7, \ + r2 : RS_V_24_20, \ + mask : RS_V_M_25, \ + VIType : RV_VIT_V, \ + rm : RM_RTZ, \ +} + // // Attribute entries for 32-bit instructions like VFWNCVT.F.F.V/VFWNCVT.F.F.W // depending on version) @@ -732,10 +819,25 @@ VIType : RV_VIT_VN, \ } +// +// Attribute entries for 32-bit instructions like VFNCVT.RTZ.X.F.W +// +#define ATTR32_VN_RTZ(_NAME, _GENERIC, _ARCH, _OPCODE) [IT32_##_NAME] = { \ + opcode : _OPCODE, \ + format : FMT_R1_R2_RM, \ + type : RV_IT_##_GENERIC, \ + arch : _ARCH, \ + r1 : RS_V_11_7, \ + r2 : RS_V_24_20, \ + mask : RS_V_M_25, \ + VIType : RV_VIT_W, \ + rm : RM_RTZ, \ +} + // // Attribute entries for 32-bit instructions like VFNCVT.ROD.F.F.W // -#define ATTR32_W_ROD(_NAME, _GENERIC, _ARCH, _OPCODE) [IT32_##_NAME] = { \ +#define ATTR32_VN_ROD(_NAME, _GENERIC, _ARCH, _OPCODE) [IT32_##_NAME] = { \ opcode : _OPCODE, \ format : FMT_R1_R2_RM, \ type : RV_IT_##_GENERIC, \ @@ -1309,7 +1411,7 @@ } // -// Attribute entries for 32-bit instructions like VLB +// Attribute entries for 32-bit instructions like VMVR // #define ATTR32_VMVR(_NAME, _GENERIC, _ARCH, _OPCODE) [IT32_##_NAME] = { \ opcode : _OPCODE, \ @@ -1324,6 +1426,21 @@ VIType : RV_VIT_V, \ } +// +// Attribute entries for 32-bit instructions like VADD.VX +// +#define ATTR32_VEXT_V(_NAME, _GENERIC, _ARCH, _OPCODE) [IT32_##_NAME] = { \ + opcode : _OPCODE, \ + format : FMT_R1_R2_RM, \ + type : RV_IT_##_GENERIC, \ + arch : _ARCH, \ + r1 : RS_V_11_7, \ + r2 : RS_V_24_20, \ + mask : RS_V_M_25, \ + eewDiv : EEWD_17_16, \ + VIType : RV_VIT_V, \ +} + // // Attribute entries for 32-bit instructions like LAST // diff --git a/source/riscvMain.c b/source/riscvMain.c index 151c24a..e648764 100644 --- a/source/riscvMain.c +++ b/source/riscvMain.c @@ -69,8 +69,11 @@ static void initLeafModelCBs(riscvP riscv) { riscv->cb.setTMode = riscvSetTMode; riscv->cb.getTMode = riscvGetTMode; riscv->cb.getDataEndian = riscvGetDataEndian; + riscv->cb.readBaseCSR = riscvReadBaseCSR; + riscv->cb.writeBaseCSR = riscvWriteBaseCSR; // from riscvExceptions.h + riscv->cb.testInterrupt = riscvTestInterrupt; riscv->cb.illegalInstruction = riscvIllegalInstruction; riscv->cb.takeException = riscvTakeException; @@ -134,37 +137,19 @@ inline static Uns32 getNumChildren(riscvP riscv) { } // -// Is the processor a cluster container? +// Give each sub-processor a unique name // -inline static void setName(riscvP hart, const char *name) { - vmirtSetProcessorName((vmiProcessorP)hart, name); -} - -// -// Set name for an AMP cluster member -// -static void setAMPMemberName(riscvP hart, riscvP parent, const char *AMPName) { - - const char *baseName = vmirtProcessorName((vmiProcessorP)parent); - char name[strlen(baseName)+strlen(AMPName)+2]; - - sprintf(name, "%s_%s", baseName, AMPName); - - setName(hart, name); -} - -// -// Set name for a cluster member -// -static void setClusterMemberName(riscvP hart, riscvP cluster) { - - const char *baseName = vmirtProcessorName((vmiProcessorP)cluster); - Uns32 index = RD_CSR(hart, mhartid); - char name[strlen(baseName)+16]; +VMI_SMP_NAME_FN(riscvGetSMPName) { - sprintf(name, "%s_hart%u", baseName, index); + const char *baseName = vmirtProcessorName(parent); + riscvP rvParent = (riscvP)parent; + riscvConfigCP cfg = &rvParent->configInfo; - setName(hart, name); + if(riscvIsCluster(rvParent)) { + sprintf(name, "%s_%s", baseName, cfg->members[smpIndex]); + } else { + sprintf(name, "%s_hart%u", baseName, cfg->csr.mhartid.u32.bits+smpIndex); + } } // @@ -217,6 +202,7 @@ static void applyParamsSMP(riscvP riscv, riscvParamValuesP params) { cfg->csr.mhartid.u64.bits = params->mhartid; cfg->csr.mtvec.u64.bits = params->mtvec; cfg->csr.mstatus.u64.fields.FS = params->mstatus_FS; + cfg->csr.mclicbase.u64.bits = params->mclicbase; // get uninterpreted CSR mask configuration parameters cfg->csrMask.mtvec.u64.bits = params->mtvec_mask; @@ -240,18 +226,24 @@ static void applyParamsSMP(riscvP riscv, riscvParamValuesP params) { cfg->Sv_modes = params->Sv_modes | RISCV_VMM_BARE; cfg->local_int_num = params->local_int_num; cfg->unimp_int_mask = params->unimp_int_mask; + cfg->ecode_mask = params->ecode_mask; + cfg->ecode_nmi = params->ecode_nmi; cfg->external_int_id = params->external_int_id; cfg->no_ideleg = params->no_ideleg; cfg->no_edeleg = params->no_edeleg; cfg->lr_sc_grain = powerOfTwo(params->lr_sc_grain, "lr_sc_grain"); cfg->debug_mode = params->debug_mode; + cfg->debug_address = params->debug_address; + cfg->dexc_address = params->dexc_address; cfg->updatePTEA = params->updatePTEA; cfg->updatePTED = params->updatePTED; cfg->unaligned = params->unaligned; cfg->unalignedAMO = params->unalignedAMO; cfg->wfi_is_nop = params->wfi_is_nop; cfg->mtvec_is_ro = params->mtvec_is_ro; + cfg->counteren_mask = params->counteren_mask; cfg->tvec_align = params->tvec_align; + cfg->tval_zero = params->tval_zero; cfg->tval_ii_code = params->tval_ii_code; cfg->cycle_undefined = params->cycle_undefined; cfg->time_undefined = params->time_undefined; @@ -269,6 +261,7 @@ static void applyParamsSMP(riscvP riscv, riscvParamValuesP params) { cfg->Zvediv = params->Zvediv; cfg->CLICLEVELS = params->CLICLEVELS; cfg->CLICANDBASIC = params->CLICANDBASIC; + cfg->CLICVERSION = params->CLICVERSION; cfg->CLICINTCTLBITS = params->CLICINTCTLBITS; cfg->CLICCFGMBITS = params->CLICCFGMBITS; cfg->CLICCFGLBITS = params->CLICCFGLBITS; @@ -379,6 +372,10 @@ VMI_CONSTRUCTOR_FN(riscvConstructor) { riscvP riscv = (riscvP)processor; riscvP parent = getParent(riscv); + // indicate no interrupts are pending and enabled initially + riscv->pendEnab.id = RV_NO_INT; + riscv->clicState.id = RV_NO_INT; + // initialize enhanced model support callbacks that apply at all levels initAllModelCBs(riscv); @@ -408,6 +405,9 @@ VMI_CONSTRUCTOR_FN(riscvConstructor) { // save parameters for use in child riscv->paramValues = parameterValues; + // save the number of child harts + riscv->numHarts = numChildren; + } else { // initialize enhanced model support callbacks that apply at leaf levels @@ -440,18 +440,12 @@ VMI_CONSTRUCTOR_FN(riscvConstructor) { // allocate timers riscvNewTimers(riscv); + // allocate CLIC data structures + riscvNewCLIC(riscv, smpContext->index); + // do initial reset riscvReset(riscv); } - - // set name if this is a cluster member - if(!parent) { - // not a cluster member - } else if(riscvIsCluster(parent)) { - setAMPMemberName(riscv, parent, riscv->configInfo.name); - } else { - setClusterMemberName(riscv, parent); - } } // @@ -501,6 +495,9 @@ VMI_DESTRUCTOR_FN(riscvDestructor) { // free timers riscvFreeTimers(riscv); + + // free CLIC data structures + riscvFreeCLIC(riscv); } @@ -614,6 +611,9 @@ VMI_SAVE_STATE_FN(riscvSaveState) { // save net state not covered by register read/write API riscvNetSave(riscv, cxt, phase); + // save timer state not covered by register read/write API + riscvTimerSave(riscv, cxt, phase); + // end of SMP cluster if(phase==SRT_END) { vmirtIterAllProcessors(processor, endSave, 0); @@ -666,6 +666,9 @@ VMI_RESTORE_STATE_FN(riscvRestoreState) { // restore net state not covered by register read/write API riscvNetRestore(riscv, cxt, phase); + // restore timer state not covered by register read/write API + riscvTimerRestore(riscv, cxt, phase); + // end of SMP cluster if(phase==SRT_END) { vmirtIterAllProcessors(processor, endRestore, 0); diff --git a/source/riscvMode.h b/source/riscvMode.h index 8322510..2b24c4c 100644 --- a/source/riscvMode.h +++ b/source/riscvMode.h @@ -24,9 +24,13 @@ // typedef enum riscvModeS { RISCV_MODE_USER = 0, + RISCV_MODE_U = RISCV_MODE_USER, RISCV_MODE_SUPERVISOR = 1, - RISCV_MODE_HYPERVISOR = 2, // not currently in use + RISCV_MODE_S = RISCV_MODE_SUPERVISOR, + RISCV_MODE_HYPERVISOR = 2, // not currently in use + RISCV_MODE_H = RISCV_MODE_HYPERVISOR, // not currently in use RISCV_MODE_MACHINE = 3, + RISCV_MODE_M = RISCV_MODE_MACHINE, RISCV_MODE_LAST, RISCV_MODE_DEBUG = 4 // pseudo-mode (uses M-mode privileges) } riscvMode; diff --git a/source/riscvModelCallbacks.h b/source/riscvModelCallbacks.h index 5688725..40add51 100644 --- a/source/riscvModelCallbacks.h +++ b/source/riscvModelCallbacks.h @@ -26,6 +26,7 @@ #include "vmi/vmiDbg.h" // model header files +#include "riscvCSR.h" #include "riscvDerivedMorph.h" #include "riscvExceptionTypes.h" #include "riscvMode.h" @@ -103,6 +104,12 @@ typedef RISCV_GET_DATA_ENDIAN_FN((*riscvGetDataEndianFn)); #define RISCV_SET_TMODE_FN(_NAME) void _NAME(riscvP riscv, Bool enable) typedef RISCV_SET_TMODE_FN((*riscvSetTModeFn)); +// +// Check for pending interrupts +// +#define RISCV_TEST_INTERRUPT_FN(_NAME) void _NAME(riscvP riscv) +typedef RISCV_TEST_INTERRUPT_FN((*riscvTestInterruptFn)); + // // Take Illegal Instruction exception // @@ -218,6 +225,21 @@ typedef RISCV_NEW_CSR_FN((*riscvNewCSRFn)); // IMPLEMENTED BY DERIVED MODEL //////////////////////////////////////////////////////////////////////////////// +// +// Callback to handle misaligned read or write accesses when these should either +// cause the read/write address to be snapped or cause the read/written value to +// be rotated, or both. The return value should be constructed using the +// MEM_SNAP macro defined in vmiTypes.h. A return value of zero indicates no +// address snapping or rotation is required and that the read alignment +// exception handler should be called. +// +#define RISCV_RD_WR_SNAP_FN(_NAME) Uns32 _NAME( \ + riscvP riscv, \ + Addr address, \ + Uns32 bytes \ +) +typedef RISCV_RD_WR_SNAP_FN((*riscvRdWrSnapFn)); + // // Notifier called on trap entry or exception return // @@ -246,6 +268,15 @@ typedef RISCV_RESET_NOTIFIER_FN((*riscvResetNotifierFn)); ) typedef RISCV_FIRST_EXCEPTION_FN((*riscvFirstExceptionFn)); +// +// Called when core has either halted or restarted +// +#define RISCV_HR_NOTIFIER_FN(_NAME) void _NAME( \ + riscvP riscv, \ + void *clientData \ +) +typedef RISCV_HR_NOTIFIER_FN((*riscvHRNotifierFn)); + // // Notifier called on a model context switch. 'state' describes the new state. // @@ -295,6 +326,25 @@ typedef RISCV_TSTORE_FN((*riscvTStoreFn)); ) typedef RISCV_PMA_CHECK_FN((*riscvPMACheckFn)); +// +// Read a CSR in the base model given its id +// +#define RISCV_READ_BASE_CSR_FN(_NAME) Uns64 _NAME( \ + riscvP riscv, \ + riscvCSRId id \ +) +typedef RISCV_READ_BASE_CSR_FN((*riscvReadBaseCSRFn)); + +// +// Write a CSR in the base model given its id +// +#define RISCV_WRITE_BASE_CSR_FN(_NAME) Uns64 _NAME( \ + riscvP riscv, \ + riscvCSRId id, \ + Uns64 newValue \ +) +typedef RISCV_WRITE_BASE_CSR_FN((*riscvWriteBaseCSRFn)); + // // Container structure for all callbacks implemented by the base model // @@ -312,8 +362,11 @@ typedef struct riscvModelCBS { riscvSetTModeFn setTMode; riscvGetTModeFn getTMode; riscvGetDataEndianFn getDataEndian; + riscvReadBaseCSRFn readBaseCSR; + riscvWriteBaseCSRFn writeBaseCSR; // from riscvExceptions.h + riscvTestInterruptFn testInterrupt; riscvIllegalInstructionFn illegalInstruction; riscvTakeExceptionFn takeException; @@ -345,12 +398,19 @@ typedef struct riscvExtCBS { // handle back to client data void *clientData; + // exception modification + riscvRdWrSnapFn rdSnapCB; + riscvRdWrSnapFn wrSnapCB; + // exception actions riscvTrapNotifierFn trapNotifier; riscvTrapNotifierFn ERETNotifier; riscvResetNotifierFn resetNotifier; riscvFirstExceptionFn firstException; + // halt/restart actions + riscvHRNotifierFn haltRestartNotifier; + // code generation actions riscvDerivedMorphFn preMorph; riscvDerivedMorphFn postMorph; diff --git a/source/riscvMorph.c b/source/riscvMorph.c index 3e7c07d..b5b8891 100644 --- a/source/riscvMorph.c +++ b/source/riscvMorph.c @@ -260,10 +260,24 @@ inline static Bool vectorSignExtVMVXS(riscvP riscv) { } // -// Are segmented load/store instructions restricted to SEW size? +// Is fractional LMUL supported? // -inline static Bool vectorSegOnlySEW(riscvP riscv) { - return riscvVFSupport(riscv, RVVF_SEG_ONLY_SEW); +inline static Bool vectorFractLMUL(riscvP riscv) { + return riscvVFSupport(riscv, RVVF_FRACT_LMUL); +} + +// +// Are agnostic mask and tail supported? +// +inline static Bool vectorAgnostic(riscvP riscv) { + return riscvVFSupport(riscv, RVVF_AGNOSTIC); +} + +// +// is MLEN always 1? +// +inline static Bool vectorMLEN1(riscvP riscv) { + return riscvVFSupport(riscv, RVVF_MLEN1); } // @@ -313,6 +327,42 @@ void riscvEmitIllegalInstructionMessageDesc(riscvP riscv, illegalDescP desc) { emitIllegalInstruction(); } +// +// Emit Illegal Instruction description message +// +static void illegalOperandMessageDesc( + riscvP riscv, + illegalDescP desc, + Uns32 operand +) { + vmiMessage("W", desc->id, + SRCREF_FMT "%s (operand %u)", + SRCREF_ARGS(riscv, getPC(riscv)), + desc->detail, + operand + ); +} + +// +// Emit Illegal Operand message and take Illegal Instruction exception +// +void riscvEmitIllegalOperandMessageDesc( + riscvP riscv, + illegalDescP desc, + Uns32 operand +) { + // emit message in verbose mode + if(riscv->verbose) { + vmimtArgProcessor(); + vmimtArgNatAddress(desc); + vmimtArgUns32(operand+1); + vmimtCall((vmiCallFn)illegalOperandMessageDesc); + } + + // take Illegal Instruction exception + emitIllegalInstruction(); +} + // // Get description for the first feature identified by the given feature id // @@ -785,6 +835,17 @@ inline static riscvRegDesc getRVReg(riscvMorphStateP state, Uns32 argNum) { return state->info.r[argNum]; } +// +// Update riscvRegDesc for the indexed register +// +inline static void setRVReg( + riscvMorphStateP state, + Uns32 argNum, + riscvRegDesc rA +) { + state->info.r[argNum] = rA; +} + // // Get mask for the register in a 32-bit word // @@ -1406,6 +1467,20 @@ static RISCV_MORPH_FN(emitCmpopRRC) { writeRegSize(riscv, rdA, 8); } +// +// Get alignment constraint +// +inline static memConstraint doAligned(Bool unaligned) { + return unaligned ? MEM_CONSTRAINT_NONE : MEM_CONSTRAINT_ALIGNED; +} + +// +// Mark memory access constraint as atomic +// +inline static memConstraint markAtomic(memConstraint constraint) { + return constraint | MEM_CONSTRAINT_USER1; +} + // // Get alignment constraint for load/store operations // @@ -1414,12 +1489,12 @@ static memConstraint getLoadStoreConstraint(riscvMorphStateP state) { riscvP riscv = state->riscv; Bool unaligned = riscv->configInfo.unaligned; - return unaligned ? MEM_CONSTRAINT_NONE : MEM_CONSTRAINT_ALIGNED; + return doAligned(unaligned); } // // Get alignment constraint for atomic operations (must be aligned prior to -// version 2.3) +// version 2.3, marked as atomics using MEM_CONSTRAINT_USER1) // static memConstraint getLoadStoreConstraintAMO(riscvMorphStateP state) { @@ -1427,7 +1502,7 @@ static memConstraint getLoadStoreConstraintAMO(riscvMorphStateP state) { Bool unaligned = riscv->configInfo.unaligned; Bool unalignedAMO = riscv->configInfo.unalignedAMO && unaligned; - return unalignedAMO ? MEM_CONSTRAINT_NONE : MEM_CONSTRAINT_ALIGNED; + return markAtomic(doAligned(unalignedAMO)); } // @@ -1435,7 +1510,7 @@ static memConstraint getLoadStoreConstraintAMO(riscvMorphStateP state) { // static memConstraint getLoadStoreConstraintLR(riscvMorphStateP state) { - return MEM_CONSTRAINT_ALIGNED; + return markAtomic(MEM_CONSTRAINT_ALIGNED); } // @@ -1661,6 +1736,59 @@ static RISCV_MORPH_FN(emitJALR) { // ATOMIC MEMORY OPERATIONS //////////////////////////////////////////////////////////////////////////////// +// +// Code indicating active atomic memory operation +// +typedef enum atomicCodeE { + ACODE_NONE, + ACODE_MIN, + ACODE_MAX, + ACODE_MINU, + ACODE_MAXU, + ACODE_ADD, + ACODE_XOR, + ACODE_OR, + ACODE_AND, + ACODE_SWAP, + ACODE_LR, + ACODE_SC, +} atomicCode; + +// +// Get atomic operation code for current binop +// +static atomicCode getBinopAtomicCode(riscvMorphStateP state) { + + static const atomicCode map[] = { + [vmi_IMIN] = ACODE_MIN, + [vmi_IMAX] = ACODE_MAX, + [vmi_MIN] = ACODE_MINU, + [vmi_MAX] = ACODE_MAXU, + [vmi_ADD] = ACODE_ADD, + [vmi_XOR] = ACODE_XOR, + [vmi_OR] = ACODE_OR, + [vmi_AND] = ACODE_AND, + }; + + return map[state->attrs->binop]; +} + +// +// Emit atomic code operation if required +// +static void emitAtomicCode(riscvMorphStateP state, atomicCode code) { + + riscvP riscv = state->riscv; + Uns32 handle = riscv->AMOActiveHandle; + + if(handle) { + vmimtArgProcessor(); + vmimtArgUns32(handle); + vmimtArgUns32(code); + vmimtCallAttrs((vmiCallFn)vmirtWriteNetPort, VMCA_NO_INVALIDATE); + } +} + // // Function type implement generic AMO operation // @@ -1682,12 +1810,16 @@ static void emitAMOCommonInt( vmiReg rd, vmiReg rs, vmiReg ra, - Uns32 bits + Uns32 bits, + atomicCode code ) { memConstraint constraint = getLoadStoreConstraintAMO(state); vmiReg tmp1 = newTmp(state); vmiReg tmp2 = newTmp(state); + // emit operation atomic code + emitAtomicCode(state, code); + // for this instruction, memBits is bits if unspecified or SEW if(!state->info.memBits || (state->info.memBits==-1)) { state->info.memBits = bits; @@ -1708,13 +1840,19 @@ static void emitAMOCommonInt( // free temporaries freeTmp(state); freeTmp(state); + + // indicate end of atomic operation + emitAtomicCode(state, ACODE_NONE); } // // Atomic memory operation (GPR arguments) // -static void emitAMOCommonRRR(riscvMorphStateP state, amoCB opCB) { - +static void emitAMOCommonRRR( + riscvMorphStateP state, + amoCB opCB, + atomicCode code +) { riscvP riscv = state->riscv; riscvRegDesc rdA = getRVReg(state, 0); riscvRegDesc rsA = getRVReg(state, 1); @@ -1724,7 +1862,7 @@ static void emitAMOCommonRRR(riscvMorphStateP state, amoCB opCB) { vmiReg ra = getVMIReg(riscv, raA); Uns32 bits = getRBits(rdA); - emitAMOCommonInt(state, opCB, rd, rs, ra, bits); + emitAMOCommonInt(state, opCB, rd, rs, ra, bits, code); writeReg(riscv, rdA); } @@ -1747,14 +1885,14 @@ static AMO_FN(emitAMOSwapRRRCB) { // Atomic memory operation using defined VMI binop // static RISCV_MORPH_FN(emitAMOBinopRRR) { - emitAMOCommonRRR(state, emitAMOBinopRRRCB); + emitAMOCommonRRR(state, emitAMOBinopRRRCB, getBinopAtomicCode(state)); } // // Atomic memory operation using swap // static RISCV_MORPH_FN(emitAMOSwapRRR) { - emitAMOCommonRRR(state, emitAMOSwapRRRCB); + emitAMOCommonRRR(state, emitAMOSwapRRRCB, ACODE_SWAP); } @@ -1762,6 +1900,12 @@ static RISCV_MORPH_FN(emitAMOSwapRRR) { // LR/SC INSTRUCTIONS //////////////////////////////////////////////////////////////////////////////// +// +// Check function for externally-implemented LR/SC +// +#define RV_LR_SC_FN(_NAME) void _NAME(riscvP riscv, Uns64 address) +typedef RV_LR_SC_FN((*riscvLRSCFn)); + // // This defines exclusive tag bits // @@ -1777,15 +1921,59 @@ inline static Uns32 getModeBits(riscvMorphStateP state) { } // -// Generate exclusive access tag address ra in register rtag +// Is LR/SC locking implemented externally? +// +static Bool isLockExternal(riscvMorphStateP state) { + return state->riscv->LRAddressHandle && state->riscv->SCAddressHandle; +} + +// +// Write exclusive address to the given port // -static void generateEATag(riscvMorphStateP state, vmiReg rtag, vmiReg ra) { +static void writeNetPortExclusive(riscvP riscv, Uns32 port, Uns64 address) { + + Uns32 bits = riscvGetXlenMode(riscv); + Uns64 mask = (bits==64) ? -1 : ((1ULL<LRAddressHandle, address); +} +// +// Callback to complete externally-managed lock for SC instruction +// +static void externalSC(riscvP riscv, Uns64 address) { + writeNetPortExclusive(riscv, riscv->SCAddressHandle, address); +} + +// +// Generate exclusive access tag address ra in register rtag +// +static void generateEATag( + riscvMorphStateP state, + vmiReg rtag, + vmiReg ra, + riscvLRSCFn checkCB +) { Uns32 bits = getEABits(state); Uns32 raBits = getModeBits(state); + // generate tag vmimtMoveExtendRR(bits, rtag, raBits, ra, False); vmimtBinopRC(bits, vmi_AND, rtag, state->riscv->exclusiveTagMask, 0); + + // emit call to external check function if required + if(isLockExternal(state)) { + vmimtArgProcessor(); + vmimtArgReg(64, ra); + vmimtCallAttrs((vmiCallFn)checkCB, VMCA_NO_INVALIDATE); + } } // @@ -1799,7 +1987,43 @@ static void startEA(riscvMorphStateP state, vmiReg ra) { vmimtInstructionClassSub(OCL_IC_ATOMIC); // generate exclusive access tag for this address - generateEATag(state, RISCV_EA_TAG, ra); + generateEATag(state, RISCV_EA_TAG, ra, externalLR); +} + +// +// Handle misaligned SC address +// +static void invalidSCAlign(riscvP riscv, Uns64 address) { + riscvTakeMemoryException(riscv, riscv_E_StoreAMOAddressMisaligned, address); +} + +// +// Emit code to check SC address alignment +// +static void emitValidateSCAlign( + riscvMorphStateP state, + vmiReg t, + vmiReg ra, + Uns32 rdBits +) { + if(getLoadStoreConstraintLR(state) & MEM_CONSTRAINT_ALIGNED) { + + vmiLabelP aligned = vmimtNewLabel(); + Uns32 raBits = getModeBits(state); + Uns32 mask = (rdBits/8)-1; + + // check address alignment + vmimtTestRCJumpLabel(raBits, vmi_COND_Z, ra, mask, aligned); + + // take misaligned address exception if required + vmimtMoveExtendRR(64, t, raBits, ra, False); + vmimtArgProcessor(); + vmimtArgReg(64, t); + vmimtCallAttrs((vmiCallFn)invalidSCAlign, VMCA_EXCEPTION); + + // here if alignment is ok + vmimtInsertLabel(aligned); + } } // @@ -1816,8 +2040,11 @@ static vmiLabelP validateEA( vmiLabelP ok = vmimtNewLabel(); vmiReg t = newTmp(state); + // validate address alignment + emitValidateSCAlign(state, t, ra, rdBits); + // generate exclusive access tag for this address - generateEATag(state, t, ra); + generateEATag(state, t, ra, externalSC); // do load and store tags match? vmimtCompareRR(getEABits(state), vmi_COND_EQ, RISCV_EA_TAG, t, t); @@ -1878,6 +2105,9 @@ static RISCV_MORPH_FN(emitLR) { Uns32 rdBits = getRBits(rdA); memConstraint constraint = getLoadStoreConstraintLR(state); + // emit operation atomic code + emitAtomicCode(state, ACODE_LR); + // for this instruction, memBits is rdBits state->info.memBits = rdBits; @@ -1888,6 +2118,9 @@ static RISCV_MORPH_FN(emitLR) { emitLoadCommon(state, rd, rdBits, ra, constraint); writeReg(riscv, rdA); + + // indicate end of atomic operation + emitAtomicCode(state, ACODE_NONE); } // @@ -1905,6 +2138,9 @@ static RISCV_MORPH_FN(emitSC) { Uns32 rdBits = getRBits(rdA); memConstraint constraint = getLoadStoreConstraintLR(state); + // emit operation atomic code + emitAtomicCode(state, ACODE_SC); + // for this instruction, memBits is rsBits state->info.memBits = getRBits(rsA); @@ -1918,6 +2154,9 @@ static RISCV_MORPH_FN(emitSC) { endEA(state, rd, rdBits, done); writeReg(riscv, rdA); + + // indicate end of atomic operation + emitAtomicCode(state, ACODE_NONE); } @@ -2142,7 +2381,7 @@ static void emitCSRRCommon(riscvMorphStateP state, vmiReg rs1, Bool write) { // emit code to write the CSR if required if(write) { - vmiReg rs1Tmp = write ? newTmp(state) : VMI_NOREG; + vmiReg rs1Tmp = newTmp(state); vmiReg cbTmp = newTmp(state); Bool useRS1 = !VMI_ISNOREG(rs1); Uns64 c = state->info.c; @@ -2178,7 +2417,7 @@ static void emitCSRRCommon(riscvMorphStateP state, vmiReg rs1, Bool write) { } // do the write - riscvEmitCSRWrite(attrs, riscv, rs1Tmp, cbTmp); + riscvEmitCSRWrite(attrs, riscv, rdTmp, rs1Tmp, cbTmp); // adjust code generator state after CSR write if required if(attrs->wstateCB) { @@ -3602,98 +3841,12 @@ static RISCV_MORPH_FN(emitFClass) { // void riscvConfigureVector(riscvP riscv) { - Uns32 vRegBytes = riscv->configInfo.VLEN/8; - Uns32 stripeBytes = riscv->configInfo.SLEN/8; + Uns32 vRegBytes = riscv->configInfo.VLEN/8; // allocate vector registers if required if(riscv->configInfo.arch & ISA_V) { riscv->v = STYPE_CALLOC_N(Uns32, (vRegBytes/4)*VREG_NUM); } - - // allocate LMULx2, LMULx4 and LMULx8 index tables if required - if((riscv->configInfo.arch & ISA_V) && (vRegBytes!=stripeBytes)) { - - Uns32 stripes = vRegBytes/stripeBytes; - Uns32 stripe; - Uns32 byte; - Uns32 i; - - // allocate LMULx2, LMULx4 and LMULx8 index tables - riscv->offsetsLMULx2 = STYPE_ALLOC_N(riscvStrideOffset, vRegBytes*2); - riscv->offsetsLMULx4 = STYPE_ALLOC_N(riscvStrideOffset, vRegBytes*4); - riscv->offsetsLMULx8 = STYPE_ALLOC_N(riscvStrideOffset, vRegBytes*8); - - // iterate over stripes - for(stripe=0; stripeoffsetsLMULx2[index] = value; - } - - // initialize LMULx4 index table - for(i=0; i<4; i++) { - - Uns32 index = byte + (stripeBytes*i) + (stripe*stripeBytes*4); - Uns32 value = byte + (vRegBytes*i) + (stripe*stripeBytes); - - riscv->offsetsLMULx4[index] = value; - } - - // initialize LMULx8 index table - for(i=0; i<8; i++) { - - Uns32 index = byte + (stripeBytes*i) + (stripe*stripeBytes*8); - Uns32 value = byte + (vRegBytes*i) + (stripe*stripeBytes); - - riscv->offsetsLMULx8[index] = value; - } - } - } - - // show derived vector indices if required - if(RISCV_DEBUG_VECTIDX(riscv)) { - - vmiPrintf( - "\nVLEN=%u SLEN=%u\n", - riscv->configInfo.VLEN, - riscv->configInfo.SLEN - ); - - vmiPrintf("\nLMULx2 TABLE\n"); - for(i=0; i<2; i++) { - for(byte=0; byteoffsetsLMULx2[i*vRegBytes+byte]); - } - vmiPrintf("\n"); - } - - vmiPrintf("\nLMULx4 TABLE\n"); - for(i=0; i<4; i++) { - for(byte=0; byteoffsetsLMULx4[i*vRegBytes+byte]); - } - vmiPrintf("\n"); - } - - vmiPrintf("\nLMULx8 TABLE\n"); - for(i=0; i<8; i++) { - for(byte=0; byteoffsetsLMULx8[i*vRegBytes+byte]); - } - vmiPrintf("\n"); - } - - vmiPrintf("\n"); - } - } } // @@ -3705,13 +3858,6 @@ void riscvFreeVector(riscvP riscv) { if(riscv->v) { STYPE_FREE(riscv->v); } - - // free LMULx2, LMULx4 and LMULx8 index tables if required - if(riscv->offsetsLMULx2) { - STYPE_FREE(riscv->offsetsLMULx2); - STYPE_FREE(riscv->offsetsLMULx4); - STYPE_FREE(riscv->offsetsLMULx8); - } } @@ -3719,34 +3865,58 @@ void riscvFreeVector(riscvP riscv) { // VECTOR OPERATION DISPATCH //////////////////////////////////////////////////////////////////////////////// +// +// This indicates the type of a vector register +// +typedef enum vrTypeE { + VRT_NONE, // no register + VRT_XF, // X or F register + VRT_MASK, // mask register + VRT_SCALAR, // scalar register + VRT_VECTOR, // vector register +} vrType; + +// +// This type holds information about a single vector register +// +typedef struct vrDescS { + vrType type; // register type + riscvVLMULx8Mt EMULx8; // effective EMULx8 + riscvSEWMt EEW; // effective EEW + Uns32 EMUL; // effective VLMUL (1 if fractional) + Bool forceEEW; // force EEW for this operand +} vrDesc, *vrDescP; + // // This type describes a base register of a given size // typedef struct baseDescS { - vmiReg reg; // base register - vmiReg index; // index register - Uns32 elemBits; // element size in bits - Bool striped; // whether a striped base + vmiReg reg; // base register + vmiReg index; // index register + riscvVLMULx8Mt EMULx8; // effective EMULx8 + Uns32 EBITS; // element size in bits + Bool striped; // whether a striped base } baseDesc, *baseDescP; // // Context for generic vector operation // typedef struct iterDescS { - riscvVLMULMt VLMUL; // effective VLMUL - riscvSEWMt SEW; // effective SEW - Uns32 MLEN; // effective MLEN - Uns32 SLEN; // effective SLEN - Uns32 VLEN; // effective VLEN - Uns32 nf; // effective number of fields - riscvRegDesc PdA; // predicate abstract target register - vmiReg mask; // mask register - vmiReg rdNarrow; // narrow destination register - vmiReg r[RV_MAX_AREGS]; // argument registers - baseDesc base[NUM_BASE_REGS]; // base registers - Uns32 vBytesMax; // vector size (including padding) - vmiLabelP maskF; // target if mask=0 - vmiLabelP skip; // target if body is skipped + riscvVLMULx8Mt VLMULx8; // effective VLMULx8 + riscvSEWMt SEW; // effective SEW + Uns32 MLEN; // effective MLEN + Uns32 SLEN; // effective SLEN + Uns32 VLEN; // effective VLEN + Uns32 nf; // effective number of fields + riscvRegDesc PdA; // predicate abstract target register + vmiReg mask; // mask register + vmiReg rdNarrow; // narrow destination register + vrDesc vr[RV_MAX_AREGS]; // vector register descriptions + vmiReg r[RV_MAX_AREGS]; // argument registers + baseDesc base[NUM_BASE_REGS]; // base registers + Uns32 vBytesMax; // vector size (including padding) + vmiLabelP maskF; // target if mask=0 + vmiLabelP skip; // target if body is skipped } iterDesc; // @@ -3789,6 +3959,68 @@ static Uns32 getMaskBaseShift(iterDescP id) { return 3-shift; } +// +// Given source index of size allBits, create result in which subfield of size +// loBits+hiBits at offset fieldLSB is rotated right by loBits +// +static vmiReg rotateSubfield( + riscvMorphStateP state, + vmiReg offset, + vmiReg index, + Uns32 allBits, + Uns32 fieldLSB, + Uns32 loBits, + Uns32 hiBits +) { + if(!loBits || !hiBits) { + + // no rotation - use given index as offset + offset = index; + + } else { + + // rotation required + Uns32 loMask = ((1<MLEN); + vmiReg result = count; + Uns32 shiftMLEN = mulToShiftP2(id->MLEN); + Uns32 shiftSLEN = mulToShiftP2(id->VLEN/id->SLEN); - if(shift) { - vmimtBinopRRC(8, vmi_SHL, tRotate, result, shift, 0); + // mask bits are striped when fractional LMUL is implemented + if(shiftSLEN && vectorFractLMUL(state->riscv)) { + vmimtBinopRRC(32, vmi_SHR, tRotate, result, shiftSLEN, 0); + result = tRotate; + } + + // multiply by MLEN + if(shiftMLEN) { + vmimtBinopRRC(8, vmi_SHL, tRotate, result, shiftMLEN, 0); result = tRotate; } @@ -3871,20 +4111,6 @@ inline static void dispatchVector( } } -// -// Convert vsew field to riscvSEWMt type -// -inline static riscvSEWMt vsewToSEW(Uns32 vsew) { - return 8<riscv; - Uns32 eScale = eBytes*8/id->SEW; - riscvVLMULMt VLMUL = id->VLMUL*eScale; - vmiReg offsetIdx = VMI_NOREG; - riscvStrideOffset *base = 0; - Uns32 tableBytes = id->vBytesMax*eScale * sizeof(*base); - - // get table for the given VLMUL - if(VLMUL==VLMULMT_2) { - base = riscv->offsetsLMULx2; - } else if(VLMUL==VLMULMT_4) { - base = riscv->offsetsLMULx4; - } else if(VLMUL==VLMULMT_8) { - base = riscv->offsetsLMULx8; + // get bits required to represent register, stripe and field + Uns32 regBits = mulToShiftP2(regNum); + Uns32 stripeBits = mulToShiftP2(stripeNum); + Uns32 elemBits = mulToShiftP2(elemNum); + Uns32 allBits = regBits+stripeBits+elemBits; + + if(vectorFractLMUL(state->riscv)) { + + // convert index from register-field-stripe to register-stripe-field + offset = rotateSubfield( + state, offset, index, allBits, 0, stripeBits, elemBits + ); + } else { - VMI_ABORT("Unexpected VLMUL %u", VLMUL); // LCOV_EXCL_LINE + + // convert index from stripe-register-field to register-stripe-field + offset = rotateSubfield( + state, offset, index, allBits, elemBits, regBits, stripeBits + ); } - // get vmiReg for the given VLMUL base - offsetIdx = vmimtGetExtReg((vmiProcessorP)riscv, base); + return offset; +} + +// +// Construct index to access field of a mask register if required (only when +// fractional LMUL is implemented) +// +static vmiReg getStripedIndexM( + riscvMorphStateP state, + iterDescP id, + vmiReg offset, + vmiReg index +) { + if(vectorFractLMUL(state->riscv)) { + + // get number of registers, stripes and elements per stripe + Uns32 regNum = 1; + Uns32 stripeNum = id->VLEN/id->SLEN; + Uns32 elemNum = id->SLEN/id->MLEN; + + // convert index to format register-stripe-field + offset = getStripedIndex( + state, offset, index, regNum, stripeNum, elemNum + ); + + } else { - // convert to indexed register - getIndexedRegisterInt(&offsetIdx, offsetBaseP, tableBytes); + // use given index as offset + offset = index; + } - return offsetIdx; + return offset; } // @@ -3965,47 +4222,12 @@ static void initializeBase( Uns32 offsetBits = IMPERAS_POINTER_BITS; vmiReg offset = newTmp(state); vmiReg index = base->index; - Uns32 elemBytes = base->elemBits/8; - - if(base->striped) { - - // striped base register - Uns32 lutEBytes = sizeof(riscvStrideOffset); - Uns32 lutEBits = lutEBytes * 8; - vmiReg offsetBase = base->reg; - Uns32 scale = elemBytes*lutEBytes; - Uns32 eScale = elemBytes*8/id->SEW; - Uns32 vRegBytes = state->riscv->configInfo.VLEN/8; - Uns32 lutBytes = vRegBytes * lutEBytes * id->VLMUL * eScale; - - // handle table offset scale > 8 - if(scale>8) { - Uns32 shift = mulToShiftP2(scale); - vmimtBinopRRC(offsetBits, vmi_SHL, offset, index, shift, 0); - index = offset; - scale = 1; - } - - // adjust table base using scaled index - vmiReg offsetIdx = getOffsetIndexTable( - state, id, &offsetBase, elemBytes - ); - vmimtAddBaseR(offsetBase, index, scale, lutBytes, False, False); - - // get offset from table - vmimtMoveExtendRR(offsetBits, offset, lutEBits, offsetIdx, False); - - // initialize base register - getIndexedRegisterInt(rP, &base->reg, vecBytes); - vmimtAddBaseR(base->reg, offset, 1, vecBytes, False, False); - - } else if(elemBytes) { + Uns32 elemBytes = base->EBITS/8; - // initialize base register - getIndexedRegisterInt(rP, &base->reg, vecBytes); - vmimtAddBaseR(base->reg, index, elemBytes, vecBytes, False, False); + if(!elemBytes) { - } else { + // sub-byte reference - handle mask register striping if required + index = getStripedIndexM(state, id, offset, index); // sub-byte reference Uns32 baseShift = getMaskBaseShift(id); @@ -4013,11 +4235,39 @@ static void initializeBase( // calculate byte offset vmimtBinopRRC(offsetBits, vmi_SHR, offset, index, baseShift, 0); - // initialize base register - getIndexedRegisterInt(rP, &base->reg, vecBytes); - vmimtAddBaseR(base->reg, offset, 1, vecBytes, False, False); + // use byte-sized offset + elemBytes = 1; + + } else if(base->striped) { + + // striped base register - calculate effective VLMULx8 for this element + Uns32 SLEN = id->SLEN; + + // if SEW>SLEN, the packing operates as if SLEN was increased to SEW + if(SLENEBITS) { + SLEN = base->EBITS; + } + + // get number of registers, stripes and elements per stripe + Uns32 regNum = base->EMULx8/VLMULx8MT_1 ? : 1; + Uns32 stripeNum = id->VLEN/SLEN; + Uns32 elemNum = SLEN/base->EBITS; + + // convert index to format register-stripe-field + offset = getStripedIndex( + state, offset, index, regNum, stripeNum, elemNum + ); + + } else { + + // use index as offset + offset = index; } + // initialize base register + getIndexedRegisterInt(rP, &base->reg, vecBytes); + vmimtAddBaseR(base->reg, offset, elemBytes, vecBytes, False, False); + // free temporary offset freeTmp(state); } @@ -4030,7 +4280,8 @@ static void getIndexedRegister( iterDescP id, vmiReg *rP, vmiReg index, - Uns32 elemBits, + riscvVLMULx8Mt EMULx8, + Uns32 EBITS, Uns32 vecBytes, Bool striped ) { @@ -4046,11 +4297,12 @@ static void getIndexedRegister( base = &id->base[i]; found = ( - !base->elemBits || + !base->EBITS || ( (base->striped==striped) && - VMI_REG_EQUAL(base->index, index) && - (base->elemBits==elemBits) + (base->EMULx8==EMULx8) && + (base->EBITS==EBITS) && + VMI_REG_EQUAL(base->index, index) ) ); } @@ -4058,7 +4310,7 @@ static void getIndexedRegister( // expect either to find a match or a free descriptor VMI_ASSERT(found, "too many base registers"); - if(base->elemBits) { + if(base->EBITS) { // reuse a previously-initialized base getIndexedRegisterInt(rP, &base->reg, vecBytes); @@ -4069,10 +4321,11 @@ static void getIndexedRegister( Uns32 baseIndex = base - id->base; // create a new base - base->reg = RISCV_CPU_VBASE(baseIndex); - base->index = index; - base->elemBits = elemBits; - base->striped = striped; + base->reg = RISCV_CPU_VBASE(baseIndex); + base->index = index; + base->EMULx8 = EMULx8; + base->EBITS = EBITS; + base->striped = striped; // initialize the base initializeBase(state, id, rP, base, vecBytes); @@ -4120,6 +4373,7 @@ typedef enum overlapTypeE { // typedef struct shapeInfoS { Uns8 argMul [3]; // width multipliers (result, arg0, argN) + Bool argDiv [3]; // divided-width operand (result, arg0, argN) Bool isFloat [3]; // are operands floating point? Bool isMask [3]; // are operands masks? Bool isScalar [3]; // are operands scalar? @@ -4139,47 +4393,74 @@ typedef struct shapeInfoS { // Information for each vector operation shape // static const shapeInfo shapeDetails[RVVW_LAST] = { - [RVVW_111_II] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_111_IIXSM] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT_XSM }, - [RVVW_111_IIS] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 1, 1, 0, 0, 0, OT___ }, - [RVVW_111_IIX] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 1, 0, 0, 0, OT___ }, - [RVVW_BBB_II] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 1, 0, OT___ }, - [RVVW_111_IS] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,1,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 1, OT___ }, - [RVVW_111_SI] = {{1,1,1}, {0,0,0}, {0,0,0}, {1,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_111_PI] = {{1,1,1}, {0,0,0}, {1,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_111_SIS] = {{1,1,1}, {0,0,0}, {0,0,0}, {1,0,1}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_CIN_II] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 1, 0, 0, OT___ }, - [RVVW_CIN_PI] = {{1,1,1}, {0,0,0}, {1,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 1, 0, 0, OT___ }, - [RVVW_212_SIS] = {{2,1,2}, {0,0,0}, {0,0,0}, {1,0,1}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_121_II] = {{1,2,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 1, 0, 0, 0, 0, 0, OT___ }, - [RVVW_121_IIS] = {{1,2,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 1, 1, 1, 0, 0, 0, OT___ }, - [RVVW_211_IIQ] = {{2,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 1, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_211_II] = {{2,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_211_IIS] = {{2,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 1, 1, 0, 0, 0, OT___ }, - [RVVW_411_II] = {{4,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_221_II] = {{2,2,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_111_FF] = {{1,1,1}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_111_PF] = {{1,1,1}, {1,1,1}, {1,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_111_SFS] = {{1,1,1}, {1,1,1}, {0,0,0}, {1,0,1}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_212_SFS] = {{2,1,2}, {1,1,1}, {0,0,0}, {1,0,1}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_121_FFQ] = {{1,2,1}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 1, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_211_FFQ] = {{2,1,1}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 1, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_211_FF] = {{2,1,1}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_221_FF] = {{2,2,1}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_111_FI] = {{1,1,1}, {1,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_111_IF] = {{1,1,1}, {0,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_21_FIQ] = {{2,1,0}, {1,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 1, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_21_IFQ] = {{2,1,0}, {0,1,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 1, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_12_FIQ] = {{1,2,0}, {1,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 1, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_12_IFQ] = {{1,2,0}, {0,1,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 1, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_111_PP] = {{1,1,1}, {0,0,0}, {1,1,1}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, - [RVVW_111_IP] = {{1,1,1}, {0,0,0}, {0,1,1}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT_SM }, - [RVVW_111_GR] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,1,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT_SM }, - [RVVW_111_UP] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,1,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT_SM71}, - [RVVW_111_DN] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,1,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT__M71}, - [RVVW_111_CMP] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT_SM }, + + // INTEGER ARGUMENTS + [RVVW_V1I_V1I_V1I] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V1I_V1I_V1I_XSM] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT_XSM }, + [RVVW_V1I_V1I_V1I_SAT] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 1, 1, 0, 0, 0, OT___ }, + [RVVW_V1I_V1I_V1I_VXRM] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 1, 0, 0, 0, OT___ }, + [RVVW_V1I_V1I_V1I_SEW8] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 1, 0, OT___ }, + [RVVW_V1I_S1I_V1I] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,1,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 1, OT___ }, + [RVVW_S1I_V1I_V1I] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_P1I_V1I_V1I] = {{1,1,1}, {0,0,0}, {0,0,0}, {1,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_S1I_V1I_S1I] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,1}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V1I_V1I_V1I_CIN] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 1, 0, 0, OT___ }, + [RVVW_P1I_V1I_V1I_CIN] = {{1,1,1}, {0,0,0}, {0,0,0}, {1,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 1, 0, 0, OT___ }, + [RVVW_S2I_V1I_S2I] = {{2,1,2}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,1}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V1I_V2I_V1I] = {{1,2,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 1, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V1I_V2I_V1I_SAT] = {{1,2,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 1, 1, 1, 0, 0, 0, OT___ }, + [RVVW_V2I_V1I_V1I_IW] = {{2,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 1, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V2I_V1I_V1I] = {{2,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V2I_V1I_V1I_SAT] = {{2,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 1, 1, 0, 0, 0, OT___ }, + [RVVW_V4I_V1I_V1I] = {{4,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V2I_V2I_V1I] = {{2,2,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V1I_V2I_FN] = {{1,1,1}, {0,1,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + + // FLOATING POINT ARGUMENTS + [RVVW_V1F_V1F_V1F] = {{1,1,1}, {0,0,0}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V1F_S1F_V1F] = {{1,1,1}, {0,0,0}, {1,1,1}, {0,0,0}, {0,1,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 1, OT___ }, + [RVVW_S1F_V1I_V1I] = {{1,1,1}, {0,0,0}, {1,1,1}, {0,0,0}, {1,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_P1I_V1F_V1F] = {{1,1,1}, {0,0,0}, {0,1,1}, {1,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_S1F_V1F_S1F] = {{1,1,1}, {0,0,0}, {1,1,1}, {0,0,0}, {1,0,1}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_S2F_V1F_S2F] = {{2,1,2}, {0,0,0}, {1,1,1}, {0,0,0}, {1,0,1}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V1F_V2F_V1F_IW] = {{1,2,1}, {0,0,0}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 1, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V2F_V1F_V1F_IW] = {{2,1,1}, {0,0,0}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 1, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V2F_V1F_V1F] = {{2,1,1}, {0,0,0}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V2F_V2F_V1F] = {{2,2,1}, {0,0,0}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + + // CONVERSIONS + [RVVW_V1F_V1I] = {{1,1,1}, {0,0,0}, {1,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V1I_V1F] = {{1,1,1}, {0,0,0}, {0,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V2F_V1I] = {{2,1,0}, {0,0,0}, {1,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 1, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V2I_V1F] = {{2,1,0}, {0,0,0}, {0,1,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 1, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V1F_V2I_IW] = {{1,2,0}, {0,0,0}, {1,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 1, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V1I_V2F_IW] = {{1,2,0}, {0,0,0}, {0,1,0}, {0,0,0}, {0,0,0}, {0,0,0}, 0, 1, 0, 0, 0, 0, 0, 0, OT___ }, + + // MASK ARGUMENTS + [RVVW_P1I_P1I_P1I] = {{1,1,1}, {0,0,0}, {0,0,0}, {1,1,1}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT___ }, + [RVVW_V1I_P1I_P1I] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,1,1}, {0,0,0}, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT_SM }, + + // SLIDING ARGUMENTS + [RVVW_V1I_V1I_V1I_GR] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,1,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT_SM }, + [RVVW_V1I_V1I_V1I_UP] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,1,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT_SM71}, + [RVVW_V1I_V1I_V1I_DN] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,1,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT__M71}, + [RVVW_V1I_V1I_V1I_CMP] = {{1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, OT_SM }, }; +// +// Clamp argument index to maximum +// +inline static Uns32 clampArgIndex(Uns32 argIndex) { + return (argIndex>2) ? 2 : argIndex; +} + +// +// Return width multiplier for operation Nth vector argument +// +inline static Uns32 getWidthMultiplierN(riscvVShape vShape, Uns32 argIndex) { + return shapeDetails[vShape].argMul[clampArgIndex(argIndex)]; +} + // // Return width multiplier for a vector operation // @@ -4190,7 +4471,7 @@ static Uns32 getWidthMultiplier(riscvVShape vShape) { for(i=0; i2) ? 2 : argIndex; +inline static Bool isDividedN(riscvVShape vShape, Uns32 argIndex) { + return shapeDetails[vShape].argDiv[clampArgIndex(argIndex)]; } // @@ -4235,13 +4516,6 @@ inline static Bool isUnindexedN(riscvVShape vShape, Uns32 argIndex) { return shapeDetails[vShape].unindexed[clampArgIndex(argIndex)]; } -// -// Return width multiplier for operation Nth vector argument -// -inline static Uns32 getWidthMultiplierN(riscvVShape vShape, Uns32 argIndex) { - return shapeDetails[vShape].argMul[clampArgIndex(argIndex)]; -} - // // Does this shape implement implicit argument widening? // @@ -4305,13 +4579,6 @@ inline static Uns32 getSEWMultiplier(riscvVShape vShape) { return isWideningImplicit(vShape) ? 1 : getWidthMultiplier(vShape); } -// -// Is the indexed argument potentially a group member? -// -static Bool argIsGroup(riscvVShape vShape, Uns32 argIndex) { - return !(isMaskN(vShape, argIndex) || isScalarN(vShape, argIndex)); -} - // // Is the current SEW unequal to but forced to 8? // @@ -4337,20 +4604,21 @@ static Bool isFloat(riscvVShape vShape) { // // Get effective vector length multiplier // -static riscvVLMULMt getVLMULMt(riscvMorphStateP state) { +static riscvVLMULx8Mt getVLMULMt(riscvMorphStateP state) { riscvP riscv = state->riscv; riscvBlockStateP blockState = riscv->blockState; - riscvVLMULMt VLMUL = blockState->VLMULMt; + riscvVLMULx8Mt VLMULx8 = blockState->VLMULx8Mt; - if(VLMUL==VLMULMT_UNKNOWN) { + if(VLMULx8==VLMULx8MT_UNKNOWN) { emitCheckPolymorphic(); - blockState->VLMULMt = VLMUL = vlmulToVLMUL(RD_CSR_FIELD(riscv, vtype, vlmul)); + VLMULx8 = svlmulToVLMULx8(getSVLMUL(riscv)); + blockState->VLMULx8Mt = VLMULx8; } - return VLMUL; + return VLMULx8; } // @@ -4383,10 +4651,10 @@ static riscvVLClassMt getVLClassMt(riscvMorphStateP state, iterDescP id) { if(vlClass==VLCLASSMT_UNKNOWN) { - riscvSEWMt SEW = id->SEW; - riscvVLMULMt VLMUL = id->VLMUL; - Uns32 vl = RD_CSR(riscv, vl); - Uns32 vlMax = id->VLEN*VLMUL/SEW; + riscvSEWMt SEW = id->SEW; + riscvVLMULx8Mt VLMULx8 = id->VLMULx8; + Uns32 vl = RD_CSR(riscv, vl); + Uns32 vlMax = id->VLEN*VLMULx8/(SEW*8); emitCheckPolymorphic(); @@ -4408,75 +4676,54 @@ static riscvVLClassMt getVLClassMt(riscvMorphStateP state, iterDescP id) { // Get effective maximum vector length for this operation // inline static Uns32 getVLMAXOp(iterDescP id) { - return id->VLEN*id->VLMUL/id->SEW; + return id->VLEN * id->VLMULx8 / (id->SEW*8); } // -// Return effective VLMUL for operation Nth vector argument +// Return type for operation Nth vector argument // -static Uns32 getVLMULMtN(riscvMorphStateP state, iterDescP id, Uns32 argIndex) { - - riscvVShape vShape = state->attrs->vShape; - - return argIsGroup(vShape, argIndex) ? id->VLMUL : 1; +inline static vrType getEType(iterDescP id, Uns32 argIndex) { + return id->vr[argIndex].type; } // -// Return number of vector registers accessed by operation Nth vector argument +// Return EEW for operation Nth vector argument // -static riscvVLMULMt getVRegNumN( - riscvMorphStateP state, - iterDescP id, - Uns32 argIndex -) { - riscvVShape vShape = state->attrs->vShape; - riscvVLMULMt result = 1; - - if(argIsGroup(vShape, argIndex)) { - result = id->VLMUL * getWidthMultiplierN(vShape, argIndex); - } - - return result; +inline static riscvSEWMt getEEW(iterDescP id, Uns32 argIndex) { + return id->vr[argIndex].EEW; } // -// Return the maximum number of vector registers targeted by any vector -// argument +// Return EMULx8 for operation Nth vector argument // -static riscvVLMULMt getVRegNumMax( - riscvMorphStateP state, - iterDescP id, - riscvVShape vShape -) { - riscvVLMULMt result = 0; - Uns32 i; - - for(i=0; ivr[argIndex].EMULx8; +} - if(resultvr[argIndex].EMUL; +} - return result; +// +// Is EEW forced for operation Nth vector argument? +// +inline static Bool forceEEW(iterDescP id, Uns32 argIndex) { + return id->vr[argIndex].forceEEW; } // // Return the number of vector registers affected by a vector operation // -static Uns32 getVRegNum(riscvMorphStateP state, iterDescP id) { +static Uns32 getVRegNum(riscvMorphStateP state, iterDescP id, Uns32 index) { - Uns32 fieldNum = state->info.nf+1; - riscvVLMULMt VLMUL = id->VLMUL; + Uns32 fieldNum = state->info.nf+1; + riscvVLMULx8Mt EMULx8 = getEMULx8(id, index); + Uns32 result = EMULx8*fieldNum/8; - return VLMUL*fieldNum; + return result ? : 1; } // @@ -4489,7 +4736,7 @@ static Bool legalVRegIndex( Uns32 index ) { riscvRegDesc rv = getRVReg(state, index); - Uns32 numRegs = getVRegNum(state, id); + Uns32 numRegs = getVRegNum(state, id, index); Uns32 last = getRIndex(rv)+numRegs-1; return lastriscv; riscvRegDesc mask = state->info.mask; Uns32 index = getRIndex(rD); - riscvVLMULMt dstRegNum = getVRegNumN(state, id, 0); + Uns32 dstRegNum = getEMUL(id, 0); overlapType ot = getOverlapType(vShape); Uns32 badMask = 0; Uns32 i; @@ -4566,24 +4813,27 @@ static Bool validateNoOverlap(riscvMorphStateP state, iterDescP id) { } // validate overlap with mask if required - if(mask && ((ot&OT_M) || (dstRegNum!=VLMULMT_1))) { + if(mask && ((ot&OT_M) || (id->MLEN!=getEEW(id, 0)))) { Uns32 index = getRIndex(mask); - if(mask && indexInMask(index, badMask)) { - ok = False; + if(indexInMask(index, badMask)) { + ILLEGAL_INSTRUCTION_MESSAGE( + riscv, "IOVP", "Illegal overlap of Vd and mask" + ); + return False; } } // validate overlap with sources if required - for(srcNum=1; srcNumriscv; riscvVShape vShape = state->attrs->vShape; - Uns32 mul = getWidthMultiplier(vShape); - riscvSEWMt SEW = id->SEW; Bool ok = validateNoOverlap(state, id); Uns32 i; - // validate widening/narrowing constraints - if(ok && (mul!=1)) { + for(i=0; ok && (iriscv->configInfo.ELEN) { - ILLEGAL_INSTRUCTION_MESSAGE(riscv, "ISEW", "Illegal widened SEW"); - ok = False; - } else if(VLMULxN>VLMULMT_8) { - ILLEGAL_INSTRUCTION_MESSAGE(riscv, "IVLMUL", "Illegal widened VLMUL"); - ok = False; - } - } + if(type) { - // validate supported floating point argument widths - for(i=0; ok && (i<=2); i++) { + riscvSEWMt EEW = getEEW(id, i); + riscvVLMULx8Mt EMULx8 = getEMULx8(id, i); - if(isFloatN(vShape, i)) { + if(EEW>riscv->configInfo.ELEN) { - Uns32 mulN = getWidthMultiplierN(vShape, i); - riscvSEWMt SEWxN = mulN * SEW; + ILLEGAL_OPERAND_MESSAGE(riscv, "IEEW", "Illegal EEW>ELEN", i); - ok = validateFPArgWidth(riscv, SEWxN); + ok = False; + + } else if((EEWconfigInfo.SEW_min) && (type!=VRT_MASK)) { + + if(riscv->configInfo.SEW_min==8) { + ILLEGAL_OPERAND_MESSAGE(riscv, "IEEW", "Illegal EEW<8", i); + } else { + ILLEGAL_OPERAND_MESSAGE(riscv, "IEEW", "Illegal EEWVLMULx8MT_8) { + + ILLEGAL_OPERAND_MESSAGE(riscv, "IEMUL", "Illegal EMUL>8", i); + + ok = False; + + } else if(isFloatN(vShape, i)) { + + ok = validateFPArgWidth(riscv, EEW); + } } } @@ -4701,25 +4967,18 @@ static void widenOperands(riscvMorphStateP state, iterDescP id) { id->rdNarrow = id->r[0]; id->r[0] = newTmp(state); - } else if(isWideningImplicit(vShape)) { - - // arguments implicitly widened - } else { - Uns32 mul = getWidthMultiplier(vShape); Uns32 i; for(i=1; iSEW) && !(forceEEW(id, i) || isMaskN(vShape, i))) { - riscvSEWMt srcSEW = id->SEW; - riscvSEWMt dstSEW = srcSEW * mul; - vmiReg tmpA = newTmp(state); + vmiReg tmpA = newTmp(state); if(!isFloatN(vShape, i)) { @@ -4727,14 +4986,14 @@ static void widenOperands(riscvMorphStateP state, iterDescP id) { Bool sExtend = isVArgSigned(state, i); // extend to temporary - vmimtMoveExtendRR(dstSEW, tmpA, srcSEW, id->r[i], sExtend); + vmimtMoveExtendRR(id->SEW, tmpA, EEW, id->r[i], sExtend); } else { // floating point argument vmiReg flags = riscvGetFPFlagsMT(state->riscv); - vmiFType typeD = getSEWFType(state, dstSEW); - vmiFType typeS = getSEWFType(state, srcSEW); + vmiFType typeD = getSEWFType(state, id->SEW); + vmiFType typeS = getSEWFType(state, EEW); vmiFPRC rc = vmi_FPR_NEAREST; vmiFPConfigCP ctrl = getFPControl(state); @@ -4826,15 +5085,14 @@ static vmiReg getVMIRegV( riscvRegDesc r, Uns32 i ) { - riscvP riscv = state->riscv; - riscvVShape vShape = state->attrs->vShape; - Uns32 mulE = getWidthMultiplierN(vShape, i); - riscvVLMULMt VLMUL = getVLMULMtN(state, id, i)*mulE; - Uns32 index = getRIndex(r); + riscvP riscv = state->riscv; + riscvVLMULx8Mt EMULx8 = getEMULx8(id, i); + Uns32 index = getRIndex(r); - // validate register index is a multiple of the current VLMUL - if(index & (VLMUL-1)) { - ILLEGAL_INSTRUCTION_MESSAGE(riscv, "IVI", "Illegal vector register index"); + // validate register index is a multiple of the current EMUL, ignoring + // the case when EMULx8 is zero for which a better message is emitted later + if(EMULx8 && ((index*8) & (EMULx8-1))) { + ILLEGAL_OPERAND_MESSAGE(riscv, "IVI", "Illegal vector register index", i); } return getVMIReg(riscv, r); @@ -4893,9 +5151,15 @@ static Bool requireTopZero( // point argument is sometimes not encoded in the instruction itself but instead // depends on the current SEW, so this needs to be filled when SEW is known // -static riscvRegDesc setSEWBits(iterDescP id, riscvRegDesc rA) { +static riscvRegDesc setSEWBits( + riscvMorphStateP state, + iterDescP id, + Uns32 argNum, + riscvRegDesc rA +) { if(isFReg(rA) && !getRBits(rA)) { rA = setRBits(rA, id->SEW); + setRVReg(state, argNum, rA); } return rA; @@ -4918,16 +5182,67 @@ static void getVectorOpRegisters(riscvMorphStateP state, iterDescP id) { riscvRegDesc rA = getRVReg(state, i); vmiReg r = VMI_NOREG; + vrDescP vr = &id->vr[i]; + // determine vector argument type if(!rA) { // no action } else if(!isVReg(rA)) { - r = getVMIRegFS(state, setSEWBits(id, rA)); + vr->type = VRT_XF; } else if(isScalarN(vShape, i)) { - r = getVMIReg(riscv, rA); + vr->type = VRT_SCALAR; } else if(!isMaskN(vShape, i)) { - r = getVMIRegV(state, id, rA, i); + vr->type = VRT_VECTOR; } else { + vr->type = VRT_MASK; + } + + // seed operand EEW and EMUL + vr->EEW = (vr->type==VRT_MASK) ? id->MLEN : id->SEW; + vr->EMULx8 = (vr->type==VRT_VECTOR) ? id->VLMULx8 : VLMULx8MT_1; + + // divide operand size and multiplier if required + if(isDividedN(vShape, i)) { + vr->EEW /= state->info.eewDiv; + vr->EMULx8 /= state->info.eewDiv; + } + + // determine effective operand SEW and multiplier + if((vr->type==VRT_SCALAR) || (vr->type==VRT_VECTOR)) { + + Uns32 mulN = getWidthMultiplierN(vShape, i); + + if(state->info.eew && ((i==2) || (state->info.memBits!=-1))) { + + // take into account EEW encoded in the instruction + VMI_ASSERT(mulN==1, "unexpected widened operand"); + vr->EEW = state->info.eew; + vr->forceEEW = True; + + } else { + + // take into account EEW widening + vr->EEW *= mulN; + + // take into account EMUL widening + if(vr->type==VRT_VECTOR) { + vr->EMULx8 *= mulN; + } + } + } + + // determine effective operand multiplier (1 if fractional) + vr->EMUL = (vr->EMULx8/VLMULx8MT_1) ? : 1; + + // get VMI register for the operand + if(vr->type==VRT_XF) { + r = getVMIRegFS(state, setSEWBits(state, id, i, rA)); + } else if(vr->type==VRT_SCALAR) { + r = getVMIReg(riscv, rA); + } else if(vr->type==VRT_VECTOR) { + vr->type = VRT_VECTOR; + r = getVMIRegV(state, id, rA, i); + } else if(vr->type==VRT_MASK) { r = getVMIReg(riscv, rA); if(!i) {id->PdA = rA;} } @@ -4939,18 +5254,13 @@ static void getVectorOpRegisters(riscvMorphStateP state, iterDescP id) { // // Is the indexed vector register striped? // -static Bool isIndexedVRegisterStriped( - riscvMorphStateP state, - iterDescP id, - Uns32 i -) { - riscvVShape vShape = state->attrs->vShape; - Uns32 mulE = getWidthMultiplierN(vShape, i); - Uns32 VLEN = id->VLEN; - riscvVLMULMt VLMUL = id->VLMUL*mulE; - Uns32 SLEN = id->SLEN; +static Bool isIndexedVRegisterStriped(iterDescP id, Uns32 i) { - return (VLMUL>1) && (VLEN>SLEN); + Uns32 VLEN = id->VLEN; + Uns32 SLEN = id->SLEN; + riscvVLMULx8Mt EMULx8 = getEMULx8(id, i); + + return (EMULx8>VLMULx8MT_1) && (VLEN>SLEN); } // @@ -4962,17 +5272,23 @@ static void getIndexedVRegisterInt( Uns32 i, vmiReg index ) { - riscvVShape vShape = state->attrs->vShape; - Uns32 mulE = getWidthMultiplierN(vShape, i); - riscvVLMULMt VLMUL = getVLMULMtN(state, id, i)*mulE; - Uns32 VLEN = id->VLEN; - Uns32 SLEN = id->SLEN; - riscvSEWMt SEW = id->SEW*mulE; - Bool striped = (VLMUL>1) && (VLEN>SLEN); - Uns32 fieldNum = id->nf+1; - Uns32 vecBytes = VLEN/8*VLMUL*fieldNum; - - getIndexedRegister(state, id, &id->r[i], index, SEW, vecBytes, striped); + Uns32 VLEN = id->VLEN; + Uns32 SLEN = id->SLEN; + riscvVLMULx8Mt EMULx8 = getEMULx8(id, i); + riscvSEWMt EEW = getEEW(id, i); + Bool striped = (VLEN>SLEN); + Uns32 fieldNum = id->nf+1; + Uns32 vecBytes = VLEN*EMULx8*fieldNum/64; + + // if fractional LMUL is not implemented, only registers accessed with + // EMUL>1 are striped + if(!vectorFractLMUL(state->riscv)) { + striped &= (EMULx8>VLMULx8MT_1); + } + + getIndexedRegister( + state, id, &id->r[i], index, EMULx8, EEW, vecBytes, striped + ); } // @@ -4981,10 +5297,19 @@ static void getIndexedVRegisterInt( static void getIndexedMVMIReg(riscvMorphStateP state, iterDescP id, vmiReg *rP) { Uns32 VLEN = id->VLEN; + Uns32 SLEN = id->SLEN; Uns32 vecBytes = VLEN/8; vmiReg index = CSR_REG_MT(vstart); + Bool striped = (VLEN>SLEN); + + // if fractional LMUL is not implemented, mask registers are not striped + if(!vectorFractLMUL(state->riscv)) { + striped = False; + } - getIndexedRegister(state, id, rP, index, id->MLEN, vecBytes, False); + getIndexedRegister( + state, id, rP, index, VLMULx8MT_1, id->MLEN, vecBytes, striped + ); } // @@ -5029,7 +5354,7 @@ static void getIndexedVRegisters(riscvMorphStateP state, iterDescP id) { // vector register // static Uns32 getSegmentRegisterIndex(iterDescP id, riscvRegDesc rv, Uns32 i) { - return (getRIndex(rv) + (i*id->VLMUL)) % VREG_NUM; + return (getRIndex(rv) + (i*getEMUL(id, 0))) % VREG_NUM; } // @@ -5261,19 +5586,24 @@ static void skipIfMask0(riscvMorphStateP state, iterDescP id) { } else { // mask stride is not a byte multiple: bit test and jump - Uns32 VLEN = id->VLEN; - vmiReg vstart = CSR_REG_MT(vstart); - vmiReg mbit = vstart; - Uns32 shift = mulToShiftP2(id->MLEN); + vmiReg mbit = CSR_REG_MT(vstart); + vmiReg t = newTmp(state); + Uns32 shiftMLEN = mulToShiftP2(id->MLEN); + + // handle mask register striping if required + mbit = getStripedIndexM(state, id, t, mbit); // scale bit index if required - if(shift) { - mbit = newTmp(state); - vmimtBinopRRC(32, vmi_SHL, mbit, vstart, shift, 0); + if(shiftMLEN) { + vmimtBinopRRC(32, vmi_SHL, t, mbit, shiftMLEN, 0); + mbit = t; } // go if mask bit not set - vmimtTestBitVRJumpLabel(VLEN, 32, False, id->mask, mbit, id->maskF); + vmimtTestBitVRJumpLabel(id->VLEN, 32, False, id->mask, mbit, id->maskF); + + // free allocated temporary + freeTmp(state); } } @@ -5442,7 +5772,7 @@ static void zeroVdPdTopBLT( if(zeroVd) { - Uns32 VLENxN = VLEN*id->VLMUL; + Uns32 VLENxN = VLEN*getEMUL(id,0); Uns32 i; // get indexed vector register target @@ -5486,7 +5816,7 @@ static vmiLabelP zeroVdPdTop(riscvMorphStateP state, iterDescP id) { if((VdA!=PdA) && isVReg(VdA)) { for(i=0; i<=id->nf; i++) { riscvRegDesc sr = getSegmentRegister(id, VdA, i); - if(requireTopZero(state, id, sr, id->VLMUL)) { + if(requireTopZero(state, id, sr, getEMUL(id,0))) { zeroVd |= getTopZeroVdMask(i); } } @@ -5508,7 +5838,7 @@ static vmiLabelP zeroVdPdTop(riscvMorphStateP state, iterDescP id) { // determine whether per-element or block-transfer algorithm is needed if( (zeroPd && (id->MLEN<8)) || - (zeroVd && isIndexedVRegisterStriped(state, id, 0)) + (zeroVd && isIndexedVRegisterStriped(id, 0)) ) { zeroVdPdTopPE(state, id, zeroPd, zeroVd); } else { @@ -5632,19 +5962,19 @@ static riscvVLClassMt fillVectorOperationData( // configure either for normal or whole-register operations if(state->info.isWhole) { - id->VLMUL = 1; - id->VLEN = riscv->configInfo.VLEN * (state->info.nf+1); - id->SEW = SEWMT_8; - id->SLEN = id->VLEN; - id->nf = 0; - vlClass = VLCLASSMT_MAX; + id->VLMULx8 = VLMULx8MT_1; + id->VLEN = riscv->configInfo.VLEN * (state->info.nf+1); + id->SEW = SEWMT_8; + id->SLEN = vectorFractLMUL(riscv) ? riscv->configInfo.SLEN : id->VLEN; + id->nf = 0; + vlClass = VLCLASSMT_MAX; } else { - id->VLMUL = getVLMULMt(state); - id->VLEN = riscv->configInfo.VLEN; - id->SEW = getSEWMt(state); - id->SLEN = riscv->configInfo.SLEN; - id->nf = state->info.nf; - vlClass = getVLClassMt(state, id); + id->VLMULx8 = getVLMULMt(state); + id->VLEN = riscv->configInfo.VLEN; + id->SEW = getSEWMt(state); + id->SLEN = riscv->configInfo.SLEN; + id->nf = state->info.nf; + vlClass = getVLClassMt(state, id); } // do actions required when SEW is forced to 8 @@ -5660,8 +5990,9 @@ static riscvVLClassMt fillVectorOperationData( } // set derived fields - id->MLEN = id->SEW / id->VLMUL; - id->vBytesMax = id->VLEN * id->VLMUL / 8; + Uns32 VLMUL = (id->VLMULx8/VLMULx8MT_1) ? : 1; + id->MLEN = vectorMLEN1(riscv) ? 1 : (id->SEW / VLMUL); + id->vBytesMax = id->VLEN * id->VLMULx8 / 64; // return effective class for this operation return vlClass; @@ -5711,11 +6042,9 @@ static RISCV_MORPH_FN(emitVectorOp) { // update base registers for this iteration getIndexedVRegisters(state, &id); - // widen source operands if required - widenOperands(state, &id); - // do operation on one element, scaling the SEW if required id.SEW *= SEWMul; + widenOperands(state, &id); doPerElementOp(state, &id); id.SEW /= SEWMul; @@ -5855,13 +6184,40 @@ void riscvWVStart(riscvMorphStateP state, Bool useRS1) { } // -// Is the specified SEW valid? +// Return maximum vector length for the given vector type settings +// +Uns32 riscvGetMaxVL(riscvP riscv, riscvVType vtype) { + + Uns32 VLEN = riscv->configInfo.VLEN; + riscvSEWMt SEW = vsewToSEW(vtype.vsew); + riscvVLMULx8Mt VLMULx8 = vtypeToVLMULx8(vtype); + + return (VLMULx8*VLEN)/(SEW*8); +} + +// +// If the specified vtype is valid, return the SEW, otherwise return +// SEWMT_UNKNOWN // -riscvSEWMt riscvValidSEW(riscvP riscv, Uns8 vsew) { +riscvSEWMt riscvValidVType(riscvP riscv, riscvVType vtype) { - Uns32 SEW = vsewToSEW(vsew); + riscvSEWMt SEW_min = riscv->configInfo.SEW_min; + riscvSEWMt ELEN = riscv->configInfo.ELEN; + riscvSEWMt SEW = vsewToSEW(vtype.vsew); + riscvVLMULx8Mt VLMULx8 = vtypeToVLMULx8(vtype); - if((SEWconfigInfo.SEW_min) || (SEW>riscv->configInfo.ELEN)) { + if( + // validate fields that must be zero + vtype._u1 || + // validate vlmulf setting + (vtype.vlmulf && !vectorFractLMUL(riscv)) || + // validate agnostic settings + ((vtype.vta||vtype.vma) && !vectorAgnostic(riscv)) || + // validate SEW is supported + (SEWELEN) || + // validate LMUL>=(SEW/ELEN) + !(VLMULx8>=((SEW*8)/ELEN)) + ) { SEW = SEWMT_UNKNOWN; } @@ -5869,19 +6225,20 @@ riscvSEWMt riscvValidSEW(riscvP riscv, Uns8 vsew) { } // -// Update VL, SEW and VLMUL +// Update VL, and VTYPE // -static Uns32 setVLSEWLMULInt(riscvP riscv, Uns64 vl, Uns32 vsew, Uns32 vlmul) { +static Uns32 setVLSEWLMUL(riscvP riscv, Uns64 vl, Uns32 vtypeBits) { - Bool vill = !riscvValidSEW(riscv, vsew); + riscvVType vtype = {vtypeBits}; + Bool vill = !riscvValidVType(riscv, vtype); // handle illegal vtype setting if(vill) { - vl = vsew = vlmul = 0; + vtype.u32 = 0; } // update vtype CSR - riscvSetVType(riscv, vill, vsew, vlmul); + riscvSetVType(riscv, vill, vtype); // update vl CSR riscvSetVL(riscv, vl); @@ -5892,36 +6249,17 @@ static Uns32 setVLSEWLMULInt(riscvP riscv, Uns64 vl, Uns32 vsew, Uns32 vlmul) { return RD_CSR(riscv, vl); } -// -// VSetVL to specified size -// -static Uns32 setVLSEWLMUL(riscvP riscv, Uns64 vl, Uns32 vtypeBits) { - - CSR_REG_DECL(vtype) = {u32 : {bits:vtypeBits}}; - - Uns32 vsew = vtype.u32.fields.vsew; - Uns32 vlmul = vtype.u32.fields.vlmul; - - return setVLSEWLMULInt(riscv, vl, vsew, vlmul); -} - // // VSetVL to maximum supported size // static Uns32 setMaxVLSEWLMUL(riscvP riscv, Uns32 vtypeBits) { - CSR_REG_DECL(vtype) = {u32 : {bits:vtypeBits}}; - - Uns32 vsew = vtype.u32.fields.vsew; - Uns32 vlmul = vtype.u32.fields.vlmul; + riscvVType vtype = {u32:vtypeBits}; // compute effective VLMAX - Uns32 VLEN = riscv->configInfo.VLEN; - riscvSEWMt SEW = vsewToSEW(vsew); - riscvVLMULMt VLMUL = vlmulToVLMUL(vlmul); - Uns32 VLMAX = (VLMUL*VLEN)/SEW; + Uns32 VLMAX = riscvGetMaxVL(riscv, vtype); - return setVLSEWLMULInt(riscv, VLMAX, vsew, vlmul); + return setVLSEWLMUL(riscv, VLMAX, vtypeBits); } // @@ -6003,17 +6341,16 @@ static void emitVSetVLRRRCB(riscvMorphStateP state) { // static void emitVSetVLRRCCB(riscvMorphStateP state) { - riscvP riscv = state->riscv; - riscvRegDesc rdA = getRVReg(state, 0); - vmiReg rd = getVMIReg(riscv, rdA); - Uns8 vsew = state->info.vsew; - Uns8 vlmul = state->info.vlmul; - Uns32 dBits = 32; + riscvP riscv = state->riscv; + riscvRegDesc rdA = getRVReg(state, 0); + vmiReg rd = getVMIReg(riscv, rdA); + riscvVType vtype = state->info.vtype; + Uns32 dBits = 32; // call update function (SEW is known to be valid) vmimtArgProcessor(); vmiCallFn cb = handleVSetVLArg1(state); - vmimtArgUns32((vsew<<2)+vlmul); + vmimtArgUns32(vtype.u32); vmimtCallResultAttrs(cb, dBits, rd, VMCA_NO_INVALIDATE); writeRegSize(riscv, rdA, dBits); @@ -6023,24 +6360,23 @@ static void emitVSetVLRRCCB(riscvMorphStateP state) { } // -// Implement VSetVL , , operation with invalid SEW +// Implement VSetVL , , operation with invalid SEW or LMUL // -static void emitVSetVLRRCBadSEW(riscvMorphStateP state) { +static void emitVSetVLRRCBadSEWLMUL(riscvMorphStateP state) { - riscvP riscv = state->riscv; - riscvRegDesc rdA = getRVReg(state, 0); - vmiReg rd = getVMIReg(riscv, rdA); - Uns8 vsew = state->info.vsew; - Uns32 dBits = 32; + riscvP riscv = state->riscv; + riscvRegDesc rdA = getRVReg(state, 0); + vmiReg rd = getVMIReg(riscv, rdA); + riscvVType vtype = state->info.vtype; + Uns32 dBits = 32; // update using invalid SEW - vmiCallFn cb = (vmiCallFn)setVLSEWLMULInt; + vmiCallFn cb = (vmiCallFn)setVLSEWLMUL; // use embedded call vmimtArgProcessor(); - vmimtArgUns64(0); // vl (ignored) - vmimtArgUns32(vsew); // sew - vmimtArgUns32(0); // vlmul (ignored) + vmimtArgUns64(0); // vl (ignored) + vmimtArgUns32(vtype.u32); // vtype vmimtCallResultAttrs(cb, dBits, rd, VMCA_NO_INVALIDATE); writeRegSize(riscv, rdA, dBits); @@ -6056,14 +6392,13 @@ static void emitVSetVLRR0MaxVL(riscvMorphStateP state) { riscvP riscv = state->riscv; riscvBlockStateP blockState = riscv->blockState; - Uns8 vsew = state->info.vsew; - Uns8 vlmul = state->info.vlmul; - riscvSEWMt SEW = riscvValidSEW(riscv, vsew); - riscvVLMULMt VLMUL = vlmulToVLMUL(vlmul); + riscvVType vtype = state->info.vtype; + riscvSEWMt SEW = riscvValidVType(riscv, vtype); + riscvVLMULx8Mt VLMULx8 = vtypeToVLMULx8(vtype); if( (blockState->SEWMt == SEW) && - (blockState->VLMULMt == VLMUL) && + (blockState->VLMULx8Mt == VLMULx8) && (blockState->VLClassMt == VLCLASSMT_MAX) ) { // no change to previous state @@ -6085,7 +6420,7 @@ static void emitVSetVLRR0MaxVL(riscvMorphStateP state) { // maximum size if( (blockState->VLClassMt != VLCLASSMT_MAX) || - (blockState->VLMULMt != VLMUL) + (blockState->VLMULx8Mt != VLMULx8) ) { blockState->VZeroTopMt[VTZ_SINGLE] = 0; blockState->VZeroTopMt[VTZ_GROUP] = 0; @@ -6094,7 +6429,7 @@ static void emitVSetVLRR0MaxVL(riscvMorphStateP state) { // update morph-time VLClass, SEW and VLMUL, which are now known blockState->VLClassMt = VLCLASSMT_MAX; blockState->SEWMt = SEW; - blockState->VLMULMt = VLMUL; + blockState->VLMULx8Mt = VLMULx8; } } @@ -6105,12 +6440,11 @@ static void emitVSetVLRR0SameVL(riscvMorphStateP state) { riscvP riscv = state->riscv; riscvBlockStateP blockState = riscv->blockState; - Uns8 vsew = state->info.vsew; - Uns8 vlmul = state->info.vlmul; - riscvSEWMt SEW = riscvValidSEW(riscv, vsew); - riscvVLMULMt VLMUL = vlmulToVLMUL(vlmul); + riscvVType vtype = state->info.vtype; + riscvSEWMt SEW = riscvValidVType(riscv, vtype); + riscvVLMULx8Mt VLMULx8 = vtypeToVLMULx8(vtype); - if((blockState->SEWMt == SEW) && (blockState->VLMULMt == VLMUL)) { + if((blockState->SEWMt == SEW) && (blockState->VLMULx8Mt == VLMULx8)) { // no change to previous state riscvRegDesc rdA = getRVReg(state, 0); @@ -6148,18 +6482,18 @@ static RISCV_MORPH_FN(emitVSetVLRRR) { // static RISCV_MORPH_FN(emitVSetVLRRC) { - riscvP riscv = state->riscv; - Uns8 vsew = state->info.vsew; - riscvSEWMt SEW = riscvValidSEW(riscv, vsew); - setVLOption option = getSetVLOption(state); + riscvP riscv = state->riscv; + riscvVType vtype = state->info.vtype; + riscvSEWMt SEW = riscvValidVType(riscv, vtype); + setVLOption option = getSetVLOption(state); // this instruction updates vtype and vl emitUpdateVTypeVL(state); if(!SEW) { - // update using invalid SEW - emitVSetVLRRCBadSEW(state); + // update using invalid SEW or LMUL + emitVSetVLRRCBadSEWLMUL(state); } else if(option==SVT_SET) { @@ -6238,12 +6572,6 @@ static Bool emitVLdStCheckSeg(riscvMorphStateP state, iterDescP id) { // Zvlsseg extension not configured ILLEGAL_INSTRUCTION_MESSAGE(riscv, "IVLSEG", "Zvlsseg extension not configured"); ok = False; - - } else if(!isMemBitsSEW(state->info.memBits) && vectorSegOnlySEW(riscv)) { - - // only SEW-byte element segment loads/stores supported - ILLEGAL_INSTRUCTION_MESSAGE(riscv, "IVSEGMB", "Illegal non-SEW segment load/store"); - ok = False; } return ok; @@ -6276,14 +6604,15 @@ static Bool emitVLdStCheckWhole(riscvMorphStateP state, iterDescP id) { // static RISCV_CHECKV_FN(emitVLdStCheckCB) { - riscvP riscv = state->riscv; - Uns32 memBits = getVMemBits(state, id); - Bool ok = True; + riscvP riscv = state->riscv; + Uns32 memBits = getVMemBits(state, id); + riscvSEWMt EEW = getEEW(id, 0); + Bool ok = True; - if(!legalVMemBits(id->SEW, memBits)) { + if(!legalVMemBits(EEW, memBits)) { - // Illegal Instruction for invalid SEW/memBits combination - ILLEGAL_INSTRUCTION_MESSAGE(riscv, "IMB", "SEW < memory element bits"); + // Illegal Instruction for invalid EEW/memBits combination + ILLEGAL_INSTRUCTION_MESSAGE(riscv, "IMB", "EEW < memory element bits"); ok = False; } else if(state->info.isFF && vectorNoFaultOnlyFirst(riscv)) { @@ -6306,7 +6635,7 @@ static RISCV_CHECKV_FN(emitVLdStCheckCB) { // whole register loads/store check failed ok = False; - } else if(getVRegNum(state, id)>8) { + } else if(getVRegNum(state, id, 0)>8) { // VLMUL*NFIELDS must not exceed 8 for load/store segment instructions ILLEGAL_INSTRUCTION_MESSAGE(riscv, "IVLMUL", "Illegal VLMUL*NFIELDS>8"); @@ -6367,7 +6696,7 @@ static RISCV_CHECKV_FN(emitVMVRCheckCB) { riscvRegDesc rsA = getRVReg(state, 1); Uns32 dIndex = getRIndex(rdA); Uns32 sIndex = getRIndex(rsA); - Uns32 regNum = getVRegNum(state, id); + Uns32 regNum = getVRegNum(state, id, 0); Bool ok = True; if(!legalVRegIndex(state, id, 0)) { @@ -6487,7 +6816,8 @@ static vmiReg emitVLdStIOffset(riscvMorphStateP state, iterDescP id) { riscvRegDesc rs1A = getRVReg(state, 1); vmiReg ra = newTmp(state); Uns32 raBits = getRBits(rs1A); - Uns32 iBits = (id->SEWSEW : raBits; + riscvSEWMt EEW = getEEW(id, 2); + Uns32 iBits = (EEWriscv, RVVF_SEXT_IOFFSET); vmimtMoveExtendRR(raBits, ra, iBits, id->r[2], sExtend); @@ -6510,14 +6840,15 @@ static void emitVLdInt(riscvMorphStateP state, iterDescP id, vmiReg ra) { for(i=0; i<=id->nf; i++) { - vmiReg vd = getSegmentRegisterV0(state, id, i); - vmiReg vdTmp = skip ? newTmp(state) : vd; + riscvSEWMt EEW = getEEW(id, 0); + vmiReg vd = getSegmentRegisterV0(state, id, i); + vmiReg vdTmp = skip ? newTmp(state) : vd; // do load (either directly to result location or to temporary) emitLoadCommonMBO( state, vdTmp, - id->SEW, + EEW, ra, memBits, memBytes*i, @@ -6527,7 +6858,7 @@ static void emitVLdInt(riscvMorphStateP state, iterDescP id, vmiReg ra) { // for a fault-only-first load, only commit the value if no fault if(skip) { vmimtCondJumpLabel(RISCV_FF, False, skip); - vmimtMoveRR(id->SEW, vd, vdTmp); + vmimtMoveRR(EEW, vd, vdTmp); freeTmp(state); } } @@ -6570,54 +6901,42 @@ static void emitVStInt(riscvMorphStateP state, iterDescP id, vmiReg ra) { // Per-element callback for unit-stride loads // static RISCV_MORPHV_FN(emitVLdUCB) { - if(legalVMemBits(id->SEW, getVMemBits(state, id))) { - emitVLdInt(state, id, emitVLdStUOffset(state, id)); - } + emitVLdInt(state, id, emitVLdStUOffset(state, id)); } // // Per-element callback for unit-stride stores // static RISCV_MORPHV_FN(emitVStUCB) { - if(legalVMemBits(id->SEW, getVMemBits(state, id))) { - emitVStInt(state, id, emitVLdStUOffset(state, id)); - } + emitVStInt(state, id, emitVLdStUOffset(state, id)); } // // Per-element callback for strided loads // static RISCV_MORPHV_FN(emitVLdSCB) { - if(legalVMemBits(id->SEW, getVMemBits(state, id))) { - emitVLdInt(state, id, emitVLdStSOffset(state, id)); - } + emitVLdInt(state, id, emitVLdStSOffset(state, id)); } // // Per-element callback for strided stores // static RISCV_MORPHV_FN(emitVStSCB) { - if(legalVMemBits(id->SEW, getVMemBits(state, id))) { - emitVStInt(state, id, emitVLdStSOffset(state, id)); - } + emitVStInt(state, id, emitVLdStSOffset(state, id)); } // // Per-element callback for indexed loads // static RISCV_MORPHV_FN(emitVLdICB) { - if(legalVMemBits(id->SEW, getVMemBits(state, id))) { - emitVLdInt(state, id, emitVLdStIOffset(state, id)); - } + emitVLdInt(state, id, emitVLdStIOffset(state, id)); } // // Per-element callback for indexed stores // static RISCV_MORPHV_FN(emitVStICB) { - if(legalVMemBits(id->SEW, getVMemBits(state, id))) { - emitVStInt(state, id, emitVLdStIOffset(state, id)); - } + emitVStInt(state, id, emitVLdStIOffset(state, id)); } @@ -6630,16 +6949,17 @@ static RISCV_MORPHV_FN(emitVStICB) { // static Bool doVAMOCheck(riscvMorphStateP state, iterDescP id, Bool verbose) { - riscvP riscv = state->riscv; - Uns32 XLEN = riscvGetXlenMode(riscv); - Uns32 memBits = getVMemBits(state, id); - Bool ok = True; + riscvP riscv = state->riscv; + Uns32 XLEN = riscvGetXlenMode(riscv); + Uns32 memBits = getVMemBits(state, id); + riscvSEWMt EEW = getEEW(id, 3); + Bool ok = True; - if(!legalVMemBits(id->SEW, memBits)) { + if(!legalVMemBits(EEW, memBits)) { // Illegal Instruction if SEW < memory element bits if(verbose) { - ILLEGAL_INSTRUCTION_MESSAGE(riscv, "IMB", "SEW < memory element bits"); + ILLEGAL_INSTRUCTION_MESSAGE(riscv, "IMB", "EEW < memory element bits"); } ok = False; @@ -6653,11 +6973,11 @@ static Bool doVAMOCheck(riscvMorphStateP state, iterDescP id, Bool verbose) { ok = False; - } else if(id->SEW > XLEN) { + } else if(EEW > XLEN) { - // Illegal Instruction if SEW > XLEN + // Illegal Instruction if EEW > XLEN if(verbose) { - ILLEGAL_INSTRUCTION_MESSAGE(riscv, "IXL", "SEW > XLEN"); + ILLEGAL_INSTRUCTION_MESSAGE(riscv, "IXL", "EEW > XLEN"); } ok = False; @@ -6685,15 +7005,20 @@ static RISCV_CHECKV_FN(emitVAMOCheckCB) { // // Atomic memory operation (vector arguments) // -static void emitVAMOCommonRRR(riscvMorphStateP state, iterDescP id, amoCB opCB) { - +static void emitVAMOCommonRRR( + riscvMorphStateP state, + iterDescP id, + amoCB opCB, + atomicCode code +) { if(doVAMOCheck(state, id, False)) { - vmiReg ra = emitVLdStIOffset(state, id); + vmiReg ra = emitVLdStIOffset(state, id); + riscvSEWMt EEW = getEEW(id, 3); emitVLdStAddBase(state, id, ra); - emitAMOCommonInt(state, opCB, id->r[0], id->r[3], ra, id->SEW); + emitAMOCommonInt(state, opCB, id->r[0], id->r[3], ra, EEW, code); } } @@ -6701,14 +7026,14 @@ static void emitVAMOCommonRRR(riscvMorphStateP state, iterDescP id, amoCB opCB) // Atomic memory operation using defined VMI binop // static RISCV_MORPHV_FN(emitVAMOBinopRRR) { - emitVAMOCommonRRR(state, id, emitAMOBinopRRRCB); + emitVAMOCommonRRR(state, id, emitAMOBinopRRRCB, getBinopAtomicCode(state)); } // // Atomic memory operation using swap // static RISCV_MORPHV_FN(emitVAMOSwapRRR) { - emitVAMOCommonRRR(state, id, emitAMOSwapRRRCB); + emitVAMOCommonRRR(state, id, emitAMOSwapRRRCB, ACODE_SWAP); } @@ -7469,7 +7794,7 @@ static void emitFixedPointRounding( // get rounding amount to add emitGetFixedPointRoundingAdjust(id, rd, discard); - // do addition of rounding amount + // do addition of rounding amount vmimtBinopRR(id->SEW, vmi_ADD, rd, discard, 0); } @@ -7712,10 +8037,7 @@ static RISCV_MORPHV_FN(emitVRSMAccIntCB) { // static RISCV_MORPHV_FN(initVRedCB) { - riscvVShape vShape = state->attrs->vShape; - Uns32 mulE = getWidthMultiplierN(vShape, 2); - - vmimtMoveRR(id->SEW*mulE, RISCV_VTMP, id->r[2]); + vmimtMoveRR(getEEW(id, 2), RISCV_VTMP, id->r[2]); } // @@ -7723,7 +8045,7 @@ static RISCV_MORPHV_FN(initVRedCB) { // static RISCV_MORPHV_FN(emitVRedBinaryIntCB) { - vmimtBinopRR(id->SEW, state->attrs->binop, RISCV_VTMP, id->r[1], 0); + vmimtBinopRR(getEEW(id, 0), state->attrs->binop, RISCV_VTMP, id->r[1], 0); } // @@ -7731,15 +8053,11 @@ static RISCV_MORPHV_FN(emitVRedBinaryIntCB) { // static RISCV_MORPHV_FN(endVRedCB) { - riscvP riscv = state->riscv; - riscvVShape vShape = state->attrs->vShape; - Uns32 mulE = getWidthMultiplierN(vShape, 0); - // zero target register - zeroTail(riscv, id->VLEN, id->r[0]); + zeroTail(state->riscv, id->VLEN, id->r[0]); // set element 0 of target register - vmimtMoveRR(id->SEW*mulE, id->r[0], RISCV_VTMP); + vmimtMoveRR(getEEW(id, 0), id->r[0], RISCV_VTMP); } @@ -7887,7 +8205,6 @@ static vmiFType getVConvertType( Uns32 argIndex ) { riscvVShape vShape = state->attrs->vShape; - riscvSEWMt SEWxN = id->SEW * getWidthMultiplierN(vShape, argIndex); vmiFType result; // get basic operand type @@ -7899,8 +8216,8 @@ static vmiFType getVConvertType( result = VMI_FT_UNS; } - // include size - result |= SEWxN; + // include element width + result |= getEEW(id, argIndex); // use BFLOAT16 type if required if((result==vmi_FT_16_IEEE_754) && enableBFLOAT16(state->riscv)) { @@ -8088,6 +8405,15 @@ static RISCV_MORPHV_FN(emitVFMVFS) { writeRegSize(riscv, fdA, eBits); } +// +// Handle explicit NaN-boxing of scalar floating point input register +// +inline static void emitVFNaNBox(iterDescP id, Uns32 sBits, vmiReg vd) { + if(id->SEW>sBits) { + vmimtMoveRC(id->SEW-sBits, VMI_REG_DELTA(vd,sBits/8), -1); + } +} + // // Per-element callback for VFMV.S.F // @@ -8106,9 +8432,7 @@ static RISCV_MORPHV_FN(emitVFMVSF) { vmimtMoveRR(sBits, vd, fs1); // handle NaN boxing if required - if(id->SEW>sBits) { - vmimtMoveRC(id->SEW-sBits, VMI_REG_DELTA(vd,sBits/8), -1); - } + emitVFNaNBox(id, sBits, vd); } // @@ -8220,10 +8544,26 @@ static RISCV_MORPHV_FN(emitVISLIDEDOWNCB) { emitVRSLIDEDOWNInt(state, id, index, 32); } +// +// Initialization callback for VFSLIDE1UP.VF/VFSLIDE1DOWN.VF +// +static RISCV_MORPHV_FN(initVFSLIDE1CB) { + + riscvRegDesc fs1A = getRVReg(state, 2); + Uns32 sBits = getMinBits(id, getRBits(fs1A)); + vmiReg fs1 = getVMIRegFS(state, setRBits(fs1A, sBits)); + + // prepare unextended input + vmimtMoveRR(sBits, RISCV_VTMP, fs1); + + // handle NaN boxing if required + emitVFNaNBox(id, sBits, RISCV_VTMP); +} + // // Initialization callback for VSLIDE1UP.VX/VSLIDE1DOWN.VX // -static RISCV_MORPHV_FN(initVRSLIDE1CB) { +static RISCV_MORPHV_FN(initVXSLIDE1CB) { riscvRegDesc rs1A = getRVReg(state, 2); Uns32 sBits = getMinBits(id, getRBits(rs1A)); @@ -8234,7 +8574,7 @@ static RISCV_MORPHV_FN(initVRSLIDE1CB) { } // -// Per-element callback for VSLIDE1UP.VX +// Per-element callback for VSLIDE1UP.VX/VFSLIDE1UP.VF // static RISCV_MORPHV_FN(emitVRSLIDE1UPCB) { @@ -8257,7 +8597,7 @@ static RISCV_MORPHV_FN(emitVRSLIDE1UPCB) { } // -// Per-element callback for VSLIDE1DOWN.VX +// Per-element callback for VSLIDE1DOWN.VX/VFSLIDE1DOWN.VF // static RISCV_MORPHV_FN(emitVRSLIDE1DOWNCB) { @@ -8355,12 +8695,12 @@ static RISCV_MORPHV_FN(emitVIRGATHERCB) { // static RISCV_MORPHV_FN(initVCOMPRESSCB) { - riscvP riscv = state->riscv; - Uns32 offsetBits = IMPERAS_POINTER_BITS; - riscvVLMULMt VLMUL = getVLMULMtN(state, id, 0); + riscvP riscv = state->riscv; + Uns32 offsetBits = IMPERAS_POINTER_BITS; + Uns32 EMUL = getEMUL(id, 0); // zero target register - zeroTail(riscv, id->VLEN*VLMUL, id->r[0]); + zeroTail(riscv, id->VLEN*EMUL, id->r[0]); // zero target index vmimtMoveRC(offsetBits, RISCV_VTMP, 0); @@ -8593,12 +8933,12 @@ const static riscvMorphAttr dispatchTable[] = { [RV_IT_VSETVL_I] = {morph:emitVSetVLRRC}, // V-extension load/store instructions - [RV_IT_VL_I] = {morph:emitVectorOp, opTCB:emitVLdUCB, checkCB:emitVLdStCheckUCB, initCB:emitVLdStInitCB, vstart0:RVVS_ANY, vShape:RVVW_111_IIXSM}, - [RV_IT_VLS_I] = {morph:emitVectorOp, opTCB:emitVLdSCB, checkCB:emitVLdStCheckSCB, initCB:emitVLdStInitCB, vstart0:RVVS_ANY, vShape:RVVW_111_IIXSM}, - [RV_IT_VLX_I] = {morph:emitVectorOp, opTCB:emitVLdICB, checkCB:emitVLdStCheckXCB, initCB:emitVLdStInitCB, vstart0:RVVS_ANY, vShape:RVVW_111_IIXSM}, - [RV_IT_VS_I] = {morph:emitVectorOp, opTCB:emitVStUCB, checkCB:emitVLdStCheckUCB, initCB:emitVLdStInitCB, vstart0:RVVS_ANY, vShape:RVVW_111_II }, - [RV_IT_VSS_I] = {morph:emitVectorOp, opTCB:emitVStSCB, checkCB:emitVLdStCheckSCB, initCB:emitVLdStInitCB, vstart0:RVVS_ANY, vShape:RVVW_111_II }, - [RV_IT_VSX_I] = {morph:emitVectorOp, opTCB:emitVStICB, checkCB:emitVLdStCheckXCB, initCB:emitVLdStInitCB, vstart0:RVVS_ANY, vShape:RVVW_111_II }, + [RV_IT_VL_I] = {morph:emitVectorOp, opTCB:emitVLdUCB, checkCB:emitVLdStCheckUCB, initCB:emitVLdStInitCB, vstart0:RVVS_ANY, vShape:RVVW_V1I_V1I_V1I_XSM}, + [RV_IT_VLS_I] = {morph:emitVectorOp, opTCB:emitVLdSCB, checkCB:emitVLdStCheckSCB, initCB:emitVLdStInitCB, vstart0:RVVS_ANY, vShape:RVVW_V1I_V1I_V1I_XSM}, + [RV_IT_VLX_I] = {morph:emitVectorOp, opTCB:emitVLdICB, checkCB:emitVLdStCheckXCB, initCB:emitVLdStInitCB, vstart0:RVVS_ANY, vShape:RVVW_V1I_V1I_V1I_XSM}, + [RV_IT_VS_I] = {morph:emitVectorOp, opTCB:emitVStUCB, checkCB:emitVLdStCheckUCB, initCB:emitVLdStInitCB, vstart0:RVVS_ANY, vShape:RVVW_V1I_V1I_V1I }, + [RV_IT_VSS_I] = {morph:emitVectorOp, opTCB:emitVStSCB, checkCB:emitVLdStCheckSCB, initCB:emitVLdStInitCB, vstart0:RVVS_ANY, vShape:RVVW_V1I_V1I_V1I }, + [RV_IT_VSX_I] = {morph:emitVectorOp, opTCB:emitVStICB, checkCB:emitVLdStCheckXCB, initCB:emitVLdStInitCB, vstart0:RVVS_ANY, vShape:RVVW_V1I_V1I_V1I }, // V-extension AMO operations (Zvamo) [RV_IT_VAMOADD_R] = {morph:emitVectorOp, opTCB:emitVAMOBinopRRR, checkCB:emitVAMOCheckCB, binop:vmi_ADD, vstart0:RVVS_ANY}, @@ -8623,43 +8963,43 @@ const static riscvMorphAttr dispatchTable[] = { [RV_IT_VAND_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_AND }, [RV_IT_VOR_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_OR }, [RV_IT_VXOR_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_XOR }, - [RV_IT_VADC_VR] = {morph:emitVectorOp, opTCB:emitVRAdcIntCB, binop:vmi_ADC, vShape:RVVW_CIN_II}, - [RV_IT_VMADC_VR] = {morph:emitVectorOp, opTCB:emitVRAdcIntCB, binop:vmi_ADC, vShape:RVVW_CIN_PI}, - [RV_IT_VSBC_VR] = {morph:emitVectorOp, opTCB:emitVRAdcIntCB, binop:vmi_SBB, vShape:RVVW_CIN_II}, - [RV_IT_VMSBC_VR] = {morph:emitVectorOp, opTCB:emitVRAdcIntCB, binop:vmi_SBB, vShape:RVVW_CIN_PI}, + [RV_IT_VADC_VR] = {morph:emitVectorOp, opTCB:emitVRAdcIntCB, binop:vmi_ADC, vShape:RVVW_V1I_V1I_V1I_CIN}, + [RV_IT_VMADC_VR] = {morph:emitVectorOp, opTCB:emitVRAdcIntCB, binop:vmi_ADC, vShape:RVVW_P1I_V1I_V1I_CIN}, + [RV_IT_VSBC_VR] = {morph:emitVectorOp, opTCB:emitVRAdcIntCB, binop:vmi_SBB, vShape:RVVW_V1I_V1I_V1I_CIN}, + [RV_IT_VMSBC_VR] = {morph:emitVectorOp, opTCB:emitVRAdcIntCB, binop:vmi_SBB, vShape:RVVW_P1I_V1I_V1I_CIN}, [RV_IT_VSLL_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SHL }, [RV_IT_VSRL_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SHR }, [RV_IT_VSRA_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SAR }, - [RV_IT_VNSRL_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SHR, vShape:RVVW_121_II}, - [RV_IT_VNSRA_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SAR, vShape:RVVW_121_II}, - [RV_IT_VSEQ_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_EQ, vShape:RVVW_111_PI}, - [RV_IT_VSNE_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_NE, vShape:RVVW_111_PI}, - [RV_IT_VSLTU_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_B, vShape:RVVW_111_PI}, - [RV_IT_VSLT_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_L, vShape:RVVW_111_PI}, - [RV_IT_VSLEU_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_BE, vShape:RVVW_111_PI}, - [RV_IT_VSLE_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_LE, vShape:RVVW_111_PI}, - [RV_IT_VSGTU_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_NBE, vShape:RVVW_111_PI}, - [RV_IT_VSGT_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_NLE, vShape:RVVW_111_PI}, - [RV_IT_VRGATHER_VR] = {morph:emitVectorOp, opTCB:emitVRRGATHERCB, vShape:RVVW_111_GR}, - [RV_IT_VSLIDEUP_VR] = {morph:emitVectorOp, opTCB:emitVRSLIDEUPCB, vShape:RVVW_111_UP}, - [RV_IT_VSLIDEDOWN_VR] = {morph:emitVectorOp, opTCB:emitVRSLIDEDOWNCB, vShape:RVVW_111_DN}, - [RV_IT_VSADDU_VR] = {morph:emitVectorOp, opTCB:emitVRSBinaryCB, binop:vmi_ADDUQ, vShape:RVVW_111_IIS, argType:RVVX_UU}, - [RV_IT_VSADD_VR] = {morph:emitVectorOp, opTCB:emitVRSBinaryCB, binop:vmi_ADDSQ, vShape:RVVW_111_IIS, argType:RVVX_SS}, - [RV_IT_VSSUBU_VR] = {morph:emitVectorOp, opTCB:emitVRSBinaryCB, binop:vmi_SUBUQ, vShape:RVVW_111_IIS, argType:RVVX_UU}, - [RV_IT_VSSUB_VR] = {morph:emitVectorOp, opTCB:emitVRSBinaryCB, binop:vmi_SUBSQ, vShape:RVVW_111_IIS, argType:RVVX_SS}, - [RV_IT_VAADDU_VR] = {morph:emitVectorOp, opTCB:emitVRABinaryCB, binop:vmi_ADDUH, vShape:RVVW_111_IIX, argType:RVVX_UU}, - [RV_IT_VAADD_VR] = {morph:emitVectorOp, opTCB:emitVRABinaryCB, binop:vmi_ADDSH, vShape:RVVW_111_IIX, argType:RVVX_SS}, - [RV_IT_VASUBU_VR] = {morph:emitVectorOp, opTCB:emitVRABinaryCB, binop:vmi_SUBUH, vShape:RVVW_111_IIX, argType:RVVX_UU}, - [RV_IT_VASUB_VR] = {morph:emitVectorOp, opTCB:emitVRABinaryCB, binop:vmi_SUBSH, vShape:RVVW_111_IIX, argType:RVVX_SS}, - [RV_IT_VSMUL_VR] = {morph:emitVectorOp, opTCB:emitVRSMULCB, binop:vmi_IMUL, vShape:RVVW_111_IIS, argType:RVVX_SS}, - [RV_IT_VWSMACCU_VR] = {morph:emitVectorOp, opTCB:emitVRSMAccIntCB, binop:vmi_ADDUQ, vShape:RVVW_211_IIS, argType:RVVX_UU}, - [RV_IT_VWSMACC_VR] = {morph:emitVectorOp, opTCB:emitVRSMAccIntCB, binop:vmi_ADDSQ, vShape:RVVW_211_IIS, argType:RVVX_SS}, - [RV_IT_VWSMACCSU_VR] = {morph:emitVectorOp, opTCB:emitVRSMAccIntCB, binop:vmi_ADDSQ, vShape:RVVW_211_IIS, argType:RVVX_SU}, - [RV_IT_VWSMACCUS_VR] = {morph:emitVectorOp, opTCB:emitVRSMAccIntCB, binop:vmi_ADDSQ, vShape:RVVW_211_IIS, argType:RVVX_US}, - [RV_IT_VSSRL_VR] = {morph:emitVectorOp, opTCB:emitVRRShiftIntCB, binop:vmi_SHR, vShape:RVVW_111_IIX}, - [RV_IT_VSSRA_VR] = {morph:emitVectorOp, opTCB:emitVRRShiftIntCB, binop:vmi_SAR, vShape:RVVW_111_IIX}, - [RV_IT_VNCLIPU_VR] = {morph:emitVectorOp, opTCB:emitVRRShiftIntCB, binop:vmi_SHR, vShape:RVVW_121_IIS, argType:RVVX_UU}, - [RV_IT_VNCLIP_VR] = {morph:emitVectorOp, opTCB:emitVRRShiftIntCB, binop:vmi_SAR, vShape:RVVW_121_IIS, argType:RVVX_SS}, + [RV_IT_VNSRL_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SHR, vShape:RVVW_V1I_V2I_V1I}, + [RV_IT_VNSRA_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SAR, vShape:RVVW_V1I_V2I_V1I}, + [RV_IT_VSEQ_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_EQ, vShape:RVVW_P1I_V1I_V1I}, + [RV_IT_VSNE_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_NE, vShape:RVVW_P1I_V1I_V1I}, + [RV_IT_VSLTU_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_B, vShape:RVVW_P1I_V1I_V1I}, + [RV_IT_VSLT_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_L, vShape:RVVW_P1I_V1I_V1I}, + [RV_IT_VSLEU_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_BE, vShape:RVVW_P1I_V1I_V1I}, + [RV_IT_VSLE_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_LE, vShape:RVVW_P1I_V1I_V1I}, + [RV_IT_VSGTU_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_NBE, vShape:RVVW_P1I_V1I_V1I}, + [RV_IT_VSGT_VR] = {morph:emitVectorOp, opTCB:emitVRCmpIntCB, cond :vmi_COND_NLE, vShape:RVVW_P1I_V1I_V1I}, + [RV_IT_VRGATHER_VR] = {morph:emitVectorOp, opTCB:emitVRRGATHERCB, vShape:RVVW_V1I_V1I_V1I_GR}, + [RV_IT_VSLIDEUP_VR] = {morph:emitVectorOp, opTCB:emitVRSLIDEUPCB, vShape:RVVW_V1I_V1I_V1I_UP}, + [RV_IT_VSLIDEDOWN_VR] = {morph:emitVectorOp, opTCB:emitVRSLIDEDOWNCB, vShape:RVVW_V1I_V1I_V1I_DN}, + [RV_IT_VSADDU_VR] = {morph:emitVectorOp, opTCB:emitVRSBinaryCB, binop:vmi_ADDUQ, vShape:RVVW_V1I_V1I_V1I_SAT, argType:RVVX_UU}, + [RV_IT_VSADD_VR] = {morph:emitVectorOp, opTCB:emitVRSBinaryCB, binop:vmi_ADDSQ, vShape:RVVW_V1I_V1I_V1I_SAT, argType:RVVX_SS}, + [RV_IT_VSSUBU_VR] = {morph:emitVectorOp, opTCB:emitVRSBinaryCB, binop:vmi_SUBUQ, vShape:RVVW_V1I_V1I_V1I_SAT, argType:RVVX_UU}, + [RV_IT_VSSUB_VR] = {morph:emitVectorOp, opTCB:emitVRSBinaryCB, binop:vmi_SUBSQ, vShape:RVVW_V1I_V1I_V1I_SAT, argType:RVVX_SS}, + [RV_IT_VAADDU_VR] = {morph:emitVectorOp, opTCB:emitVRABinaryCB, binop:vmi_ADDUH, vShape:RVVW_V1I_V1I_V1I_VXRM, argType:RVVX_UU}, + [RV_IT_VAADD_VR] = {morph:emitVectorOp, opTCB:emitVRABinaryCB, binop:vmi_ADDSH, vShape:RVVW_V1I_V1I_V1I_VXRM, argType:RVVX_SS}, + [RV_IT_VASUBU_VR] = {morph:emitVectorOp, opTCB:emitVRABinaryCB, binop:vmi_SUBUH, vShape:RVVW_V1I_V1I_V1I_VXRM, argType:RVVX_UU}, + [RV_IT_VASUB_VR] = {morph:emitVectorOp, opTCB:emitVRABinaryCB, binop:vmi_SUBSH, vShape:RVVW_V1I_V1I_V1I_VXRM, argType:RVVX_SS}, + [RV_IT_VSMUL_VR] = {morph:emitVectorOp, opTCB:emitVRSMULCB, binop:vmi_IMUL, vShape:RVVW_V1I_V1I_V1I_SAT, argType:RVVX_SS}, + [RV_IT_VWSMACCU_VR] = {morph:emitVectorOp, opTCB:emitVRSMAccIntCB, binop:vmi_ADDUQ, vShape:RVVW_V2I_V1I_V1I_SAT, argType:RVVX_UU}, + [RV_IT_VWSMACC_VR] = {morph:emitVectorOp, opTCB:emitVRSMAccIntCB, binop:vmi_ADDSQ, vShape:RVVW_V2I_V1I_V1I_SAT, argType:RVVX_SS}, + [RV_IT_VWSMACCSU_VR] = {morph:emitVectorOp, opTCB:emitVRSMAccIntCB, binop:vmi_ADDSQ, vShape:RVVW_V2I_V1I_V1I_SAT, argType:RVVX_SU}, + [RV_IT_VWSMACCUS_VR] = {morph:emitVectorOp, opTCB:emitVRSMAccIntCB, binop:vmi_ADDSQ, vShape:RVVW_V2I_V1I_V1I_SAT, argType:RVVX_US}, + [RV_IT_VSSRL_VR] = {morph:emitVectorOp, opTCB:emitVRRShiftIntCB, binop:vmi_SHR, vShape:RVVW_V1I_V1I_V1I_VXRM}, + [RV_IT_VSSRA_VR] = {morph:emitVectorOp, opTCB:emitVRRShiftIntCB, binop:vmi_SAR, vShape:RVVW_V1I_V1I_V1I_VXRM}, + [RV_IT_VNCLIPU_VR] = {morph:emitVectorOp, opTCB:emitVRRShiftIntCB, binop:vmi_SHR, vShape:RVVW_V1I_V2I_V1I_SAT, argType:RVVX_UU}, + [RV_IT_VNCLIP_VR] = {morph:emitVectorOp, opTCB:emitVRRShiftIntCB, binop:vmi_SAR, vShape:RVVW_V1I_V2I_V1I_SAT, argType:RVVX_SS}, // V-extension MVV/MVX-type common instructions [RV_IT_VDIVU_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_DIV }, @@ -8670,128 +9010,128 @@ const static riscvMorphAttr dispatchTable[] = { [RV_IT_VMULHU_VR] = {morph:emitVectorOp, opTCB:emitVRMulHIntCB, binop:vmi_MUL }, [RV_IT_VMULHSU_VR] = {morph:emitVectorOp, opTCB:emitVRMulHIntCB, binop:vmi_IMULSU}, [RV_IT_VMULH_VR] = {morph:emitVectorOp, opTCB:emitVRMulHIntCB, binop:vmi_IMUL}, - [RV_IT_VWMULU_VR] = {morph:emitVectorOp, opTCB:emitVRWMulHIntCB, binop:vmi_MUL, vShape:RVVW_211_IIQ, argType:RVVX_UU}, - [RV_IT_VWMULSU_VR] = {morph:emitVectorOp, opTCB:emitVRWMulHIntCB, binop:vmi_IMULSU, vShape:RVVW_211_IIQ, argType:RVVX_SU}, - [RV_IT_VWMUL_VR] = {morph:emitVectorOp, opTCB:emitVRWMulHIntCB, binop:vmi_IMUL, vShape:RVVW_211_IIQ, argType:RVVX_SS}, - [RV_IT_VWADDU_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_ADD, vShape:RVVW_211_II, argType:RVVX_UU}, - [RV_IT_VWADD_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_ADD, vShape:RVVW_211_II, argType:RVVX_SS}, - [RV_IT_VWSUBU_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SUB, vShape:RVVW_211_II, argType:RVVX_UU}, - [RV_IT_VWSUB_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SUB, vShape:RVVW_211_II, argType:RVVX_SS}, - [RV_IT_VWADDU_WR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_ADD, vShape:RVVW_221_II, argType:RVVX_UU}, - [RV_IT_VWADD_WR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_ADD, vShape:RVVW_221_II, argType:RVVX_SS}, - [RV_IT_VWSUBU_WR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SUB, vShape:RVVW_221_II, argType:RVVX_UU}, - [RV_IT_VWSUB_WR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SUB, vShape:RVVW_221_II, argType:RVVX_SS}, - [RV_IT_VMADD_VR] = {morph:emitVectorOp, opTCB:emitVRMAddIntCB, binop:vmi_ADD, }, - [RV_IT_VNMSUB_VR] = {morph:emitVectorOp, opTCB:emitVRMAddIntCB, binop:vmi_SUB, }, - [RV_IT_VMACC_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, binop:vmi_ADD, }, - [RV_IT_VNMSAC_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, binop:vmi_SUB, }, - [RV_IT_VWMACCU_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, binop:vmi_ADD, vShape:RVVW_211_II, argType:RVVX_UU}, - [RV_IT_VWMACC_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, binop:vmi_ADD, vShape:RVVW_211_II, argType:RVVX_SS}, - [RV_IT_VWMACCSU_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, binop:vmi_ADD, vShape:RVVW_211_II, argType:RVVX_SU}, - [RV_IT_VWMACCUS_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, binop:vmi_ADD, vShape:RVVW_211_II, argType:RVVX_US}, + [RV_IT_VWMULU_VR] = {morph:emitVectorOp, opTCB:emitVRWMulHIntCB, binop:vmi_MUL, vShape:RVVW_V2I_V1I_V1I_IW, argType:RVVX_UU}, + [RV_IT_VWMULSU_VR] = {morph:emitVectorOp, opTCB:emitVRWMulHIntCB, binop:vmi_IMULSU, vShape:RVVW_V2I_V1I_V1I_IW, argType:RVVX_SU}, + [RV_IT_VWMUL_VR] = {morph:emitVectorOp, opTCB:emitVRWMulHIntCB, binop:vmi_IMUL, vShape:RVVW_V2I_V1I_V1I_IW, argType:RVVX_SS}, + [RV_IT_VWADDU_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_ADD, vShape:RVVW_V2I_V1I_V1I, argType:RVVX_UU}, + [RV_IT_VWADD_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_ADD, vShape:RVVW_V2I_V1I_V1I, argType:RVVX_SS}, + [RV_IT_VWSUBU_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SUB, vShape:RVVW_V2I_V1I_V1I, argType:RVVX_UU}, + [RV_IT_VWSUB_VR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SUB, vShape:RVVW_V2I_V1I_V1I, argType:RVVX_SS}, + [RV_IT_VWADDU_WR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_ADD, vShape:RVVW_V2I_V2I_V1I, argType:RVVX_UU}, + [RV_IT_VWADD_WR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_ADD, vShape:RVVW_V2I_V2I_V1I, argType:RVVX_SS}, + [RV_IT_VWSUBU_WR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SUB, vShape:RVVW_V2I_V2I_V1I, argType:RVVX_UU}, + [RV_IT_VWSUB_WR] = {morph:emitVectorOp, opTCB:emitVRBinaryIntCB, binop:vmi_SUB, vShape:RVVW_V2I_V2I_V1I, argType:RVVX_SS}, + [RV_IT_VMADD_VR] = {morph:emitVectorOp, opTCB:emitVRMAddIntCB, binop:vmi_ADD, }, + [RV_IT_VNMSUB_VR] = {morph:emitVectorOp, opTCB:emitVRMAddIntCB, binop:vmi_SUB, }, + [RV_IT_VMACC_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, binop:vmi_ADD, }, + [RV_IT_VNMSAC_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, binop:vmi_SUB, }, + [RV_IT_VWMACCU_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, binop:vmi_ADD, vShape:RVVW_V2I_V1I_V1I, argType:RVVX_UU}, + [RV_IT_VWMACC_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, binop:vmi_ADD, vShape:RVVW_V2I_V1I_V1I, argType:RVVX_SS}, + [RV_IT_VWMACCSU_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, binop:vmi_ADD, vShape:RVVW_V2I_V1I_V1I, argType:RVVX_SU}, + [RV_IT_VWMACCUS_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, binop:vmi_ADD, vShape:RVVW_V2I_V1I_V1I, argType:RVVX_US}, // V-extension MVV/MVX-type common instructions (Zvqmac extension) - [RV_IT_VQMACCU_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, checkCB:emitQMACCheckCB, binop:vmi_ADD, vShape:RVVW_411_II, argType:RVVX_UU}, - [RV_IT_VQMACC_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, checkCB:emitQMACCheckCB, binop:vmi_ADD, vShape:RVVW_411_II, argType:RVVX_SS}, - [RV_IT_VQMACCSU_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, checkCB:emitQMACCheckCB, binop:vmi_ADD, vShape:RVVW_411_II, argType:RVVX_SU}, - [RV_IT_VQMACCUS_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, checkCB:emitQMACCheckCB, binop:vmi_ADD, vShape:RVVW_411_II, argType:RVVX_US}, + [RV_IT_VQMACCU_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, checkCB:emitQMACCheckCB, binop:vmi_ADD, vShape:RVVW_V4I_V1I_V1I, argType:RVVX_UU}, + [RV_IT_VQMACC_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, checkCB:emitQMACCheckCB, binop:vmi_ADD, vShape:RVVW_V4I_V1I_V1I, argType:RVVX_SS}, + [RV_IT_VQMACCSU_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, checkCB:emitQMACCheckCB, binop:vmi_ADD, vShape:RVVW_V4I_V1I_V1I, argType:RVVX_SU}, + [RV_IT_VQMACCUS_VR] = {morph:emitVectorOp, opTCB:emitVRMAccIntCB, checkCB:emitQMACCheckCB, binop:vmi_ADD, vShape:RVVW_V4I_V1I_V1I, argType:RVVX_US}, // V-extension IVV-type instructions - [RV_IT_VWREDSUMU_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_ADD, vShape:RVVW_212_SIS, argType:RVVX_UU, vstart0:RVVS_ZERO}, - [RV_IT_VWREDSUM_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_ADD, vShape:RVVW_212_SIS, argType:RVVX_SS, vstart0:RVVS_ZERO}, + [RV_IT_VWREDSUMU_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_ADD, vShape:RVVW_S2I_V1I_S2I, argType:RVVX_UU, vstart0:RVVS_ZERO}, + [RV_IT_VWREDSUM_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_ADD, vShape:RVVW_S2I_V1I_S2I, argType:RVVX_SS, vstart0:RVVS_ZERO}, [RV_IT_VDOTU_VV] = {morph:emitVectorOp, checkCB:emitEDIVCheckCB}, [RV_IT_VDOT_VV] = {morph:emitVectorOp, checkCB:emitEDIVCheckCB}, // V-extension FVV/FVF-type common instructions - [RV_IT_VFMERGE_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMERGETCB, opFCB:emitVRMERGEFCB, vShape:RVVW_111_FF}, - [RV_IT_VFADD_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FADD, vShape:RVVW_111_FF}, - [RV_IT_VFSUB_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FSUB, vShape:RVVW_111_FF}, - [RV_IT_VFRSUB_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltRCB, fpBinop: vmi_FSUB, vShape:RVVW_111_FF}, - [RV_IT_VFMUL_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FMUL, vShape:RVVW_111_FF}, - [RV_IT_VFDIV_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FDIV, vShape:RVVW_111_FF}, - [RV_IT_VFRDIV_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltRCB, fpBinop: vmi_FDIV, vShape:RVVW_111_FF}, - [RV_IT_VFWADD_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FADD, vShape:RVVW_211_FF}, - [RV_IT_VFWSUB_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FSUB, vShape:RVVW_211_FF}, - [RV_IT_VFWADD_WR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FADD, vShape:RVVW_221_FF}, - [RV_IT_VFWSUB_WR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FSUB, vShape:RVVW_221_FF}, - [RV_IT_VFWMUL_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FMUL, vShape:RVVW_211_FF}, - [RV_IT_VFMADD_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAddFltCB, fpTernop:vmi_FMADD, vShape:RVVW_111_FF}, - [RV_IT_VFNMADD_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAddFltCB, fpTernop:vmi_FNMADD, vShape:RVVW_111_FF}, - [RV_IT_VFMSUB_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAddFltCB, fpTernop:vmi_FMSUB, vShape:RVVW_111_FF}, - [RV_IT_VFNMSUB_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAddFltCB, fpTernop:vmi_FNMSUB, vShape:RVVW_111_FF}, - [RV_IT_VFMACC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FMADD, vShape:RVVW_111_FF}, - [RV_IT_VFNMACC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FNMADD, vShape:RVVW_111_FF}, - [RV_IT_VFMSAC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FMSUB, vShape:RVVW_111_FF}, - [RV_IT_VFNMSAC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FNMSUB, vShape:RVVW_111_FF}, - [RV_IT_VFWMACC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FMADD, vShape:RVVW_211_FF}, - [RV_IT_VFWNMACC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FNMADD, vShape:RVVW_211_FF}, - [RV_IT_VFWMSAC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FMSUB, vShape:RVVW_211_FF}, - [RV_IT_VFWNMSAC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FNMSUB, vShape:RVVW_211_FF}, - [RV_IT_VFSQRT_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRUnaryFltCB, fpUnop: vmi_FSQRT, vShape:RVVW_111_FF}, - [RV_IT_VFMIN_VR] = {fpConfig:RVFP_FMIN, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FMIN, vShape:RVVW_111_FF}, - [RV_IT_VFMAX_VR] = {fpConfig:RVFP_FMAX, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FMAX, vShape:RVVW_111_FF}, - [RV_IT_VFSGNJ_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFSgnFltCB, clearFS1:1,negFS2:0, vShape:RVVW_111_FF}, - [RV_IT_VFSGNJN_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFSgnFltCB, clearFS1:1,negFS2:1, vShape:RVVW_111_FF}, - [RV_IT_VFSGNJX_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFSgnFltCB, clearFS1:0,negFS2:0, vShape:RVVW_111_FF}, - [RV_IT_VFORD_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFCmpFltCB, fpRel:RVFCMP_ORD, vShape:RVVW_111_PF}, - [RV_IT_VFEQ_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFCmpFltCB, fpRel:RVFCMP_EQ, vShape:RVVW_111_PF}, - [RV_IT_VFNE_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFCmpFltCB, fpRel:RVFCMP_NE, vShape:RVVW_111_PF}, - [RV_IT_VFLE_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFCmpFltCB, fpRel:RVFCMP_LE, vShape:RVVW_111_PF}, - [RV_IT_VFLT_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFCmpFltCB, fpRel:RVFCMP_LT, vShape:RVVW_111_PF}, - [RV_IT_VFGE_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFCmpFltCB, fpRel:RVFCMP_GE, vShape:RVVW_111_PF}, - [RV_IT_VFGT_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFCmpFltCB, fpRel:RVFCMP_GT, vShape:RVVW_111_PF}, + [RV_IT_VFMERGE_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMERGETCB, opFCB:emitVRMERGEFCB, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFADD_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FADD, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFSUB_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FSUB, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFRSUB_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltRCB, fpBinop: vmi_FSUB, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFMUL_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FMUL, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFDIV_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FDIV, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFRDIV_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltRCB, fpBinop: vmi_FDIV, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFWADD_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FADD, vShape:RVVW_V2F_V1F_V1F}, + [RV_IT_VFWSUB_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FSUB, vShape:RVVW_V2F_V1F_V1F}, + [RV_IT_VFWADD_WR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FADD, vShape:RVVW_V2F_V2F_V1F}, + [RV_IT_VFWSUB_WR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FSUB, vShape:RVVW_V2F_V2F_V1F}, + [RV_IT_VFWMUL_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FMUL, vShape:RVVW_V2F_V1F_V1F}, + [RV_IT_VFMADD_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAddFltCB, fpTernop:vmi_FMADD, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFNMADD_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAddFltCB, fpTernop:vmi_FNMADD, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFMSUB_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAddFltCB, fpTernop:vmi_FMSUB, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFNMSUB_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAddFltCB, fpTernop:vmi_FNMSUB, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFMACC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FMADD, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFNMACC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FNMADD, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFMSAC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FMSUB, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFNMSAC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FNMSUB, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFWMACC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FMADD, vShape:RVVW_V2F_V1F_V1F}, + [RV_IT_VFWNMACC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FNMADD, vShape:RVVW_V2F_V1F_V1F}, + [RV_IT_VFWMSAC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FMSUB, vShape:RVVW_V2F_V1F_V1F}, + [RV_IT_VFWNMSAC_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRMAccFltCB, fpTernop:vmi_FNMSUB, vShape:RVVW_V2F_V1F_V1F}, + [RV_IT_VFSQRT_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRUnaryFltCB, fpUnop: vmi_FSQRT, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFMIN_VR] = {fpConfig:RVFP_FMIN, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FMIN, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFMAX_VR] = {fpConfig:RVFP_FMAX, morph:emitVectorOp, opTCB:emitVRBinaryFltCB, fpBinop: vmi_FMAX, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFSGNJ_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFSgnFltCB, clearFS1:1,negFS2:0, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFSGNJN_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFSgnFltCB, clearFS1:1,negFS2:1, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFSGNJX_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFSgnFltCB, clearFS1:0,negFS2:0, vShape:RVVW_V1F_V1F_V1F}, + [RV_IT_VFORD_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFCmpFltCB, fpRel:RVFCMP_ORD, vShape:RVVW_P1I_V1F_V1F}, + [RV_IT_VFEQ_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFCmpFltCB, fpRel:RVFCMP_EQ, vShape:RVVW_P1I_V1F_V1F}, + [RV_IT_VFNE_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFCmpFltCB, fpRel:RVFCMP_NE, vShape:RVVW_P1I_V1F_V1F}, + [RV_IT_VFLE_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFCmpFltCB, fpRel:RVFCMP_LE, vShape:RVVW_P1I_V1F_V1F}, + [RV_IT_VFLT_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFCmpFltCB, fpRel:RVFCMP_LT, vShape:RVVW_P1I_V1F_V1F}, + [RV_IT_VFGE_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFCmpFltCB, fpRel:RVFCMP_GE, vShape:RVVW_P1I_V1F_V1F}, + [RV_IT_VFGT_VR] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFCmpFltCB, fpRel:RVFCMP_GT, vShape:RVVW_P1I_V1F_V1F}, // V-extension FVV-type instructions - [RV_IT_VFREDSUM_VS] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRedBinaryFltCB, initCB:initVRedCB, endCB:endVRedCB, fpBinop:vmi_FADD, vShape:RVVW_111_SFS, vstart0:RVVS_ZERO}, - [RV_IT_VFREDOSUM_VS] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRedBinaryFltCB, initCB:initVRedCB, endCB:endVRedCB, fpBinop:vmi_FADD, vShape:RVVW_111_SFS, vstart0:RVVS_ZERO}, - [RV_IT_VFREDMIN_VS] = {fpConfig:RVFP_FMIN, morph:emitVectorOp, opTCB:emitVRedBinaryFltCB, initCB:initVRedCB, endCB:endVRedCB, fpBinop:vmi_FMIN, vShape:RVVW_111_SFS, vstart0:RVVS_ZERO}, - [RV_IT_VFREDMAX_VS] = {fpConfig:RVFP_FMAX, morph:emitVectorOp, opTCB:emitVRedBinaryFltCB, initCB:initVRedCB, endCB:endVRedCB, fpBinop:vmi_FMAX, vShape:RVVW_111_SFS, vstart0:RVVS_ZERO}, - [RV_IT_VFMV_F_S] = { morph:emitScalarOp, opTCB:emitVFMVFS, vShape:RVVW_111_IS}, - [RV_IT_VFCVT_XUF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_111_IF, argType:RVVX_UU}, - [RV_IT_VFCVT_XF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_111_IF, argType:RVVX_SS}, - [RV_IT_VFCVT_FXU_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_111_FI, argType:RVVX_UU}, - [RV_IT_VFCVT_FX_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_111_FI, argType:RVVX_SS}, - [RV_IT_VFWCVT_XUF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_21_IFQ, argType:RVVX_UU}, - [RV_IT_VFWCVT_XF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_21_IFQ, argType:RVVX_SS}, - [RV_IT_VFWCVT_FXU_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_21_FIQ, argType:RVVX_UU}, - [RV_IT_VFWCVT_FX_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_21_FIQ, argType:RVVX_SS}, - [RV_IT_VFWCVT_FF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_211_FFQ }, - [RV_IT_VFNCVT_XUF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_12_IFQ, argType:RVVX_UU}, - [RV_IT_VFNCVT_XF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_12_IFQ, argType:RVVX_SS}, - [RV_IT_VFNCVT_FXU_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_12_FIQ, argType:RVVX_UU}, - [RV_IT_VFNCVT_FX_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_12_FIQ, argType:RVVX_SS}, - [RV_IT_VFNCVT_FF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_121_FFQ }, - [RV_IT_VFCLASS_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFClassFltCB, vShape:RVVW_111_FF }, - [RV_IT_VFWREDSUM_VS] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRedBinaryFltCB, initCB:initVRedCB, endCB:endVRedCB, fpBinop:vmi_FADD, vShape:RVVW_212_SFS, vstart0:RVVS_ZERO}, - [RV_IT_VFWREDOSUM_VS] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRedBinaryFltCB, initCB:initVRedCB, endCB:endVRedCB, fpBinop:vmi_FADD, vShape:RVVW_212_SFS, vstart0:RVVS_ZERO}, - [RV_IT_VFDOT_VV] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, checkCB:emitEDIVCheckCB, vShape:RVVW_111_FF }, + [RV_IT_VFREDSUM_VS] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRedBinaryFltCB, initCB:initVRedCB, endCB:endVRedCB, fpBinop:vmi_FADD, vShape:RVVW_S1F_V1F_S1F, vstart0:RVVS_ZERO}, + [RV_IT_VFREDOSUM_VS] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRedBinaryFltCB, initCB:initVRedCB, endCB:endVRedCB, fpBinop:vmi_FADD, vShape:RVVW_S1F_V1F_S1F, vstart0:RVVS_ZERO}, + [RV_IT_VFREDMIN_VS] = {fpConfig:RVFP_FMIN, morph:emitVectorOp, opTCB:emitVRedBinaryFltCB, initCB:initVRedCB, endCB:endVRedCB, fpBinop:vmi_FMIN, vShape:RVVW_S1F_V1F_S1F, vstart0:RVVS_ZERO}, + [RV_IT_VFREDMAX_VS] = {fpConfig:RVFP_FMAX, morph:emitVectorOp, opTCB:emitVRedBinaryFltCB, initCB:initVRedCB, endCB:endVRedCB, fpBinop:vmi_FMAX, vShape:RVVW_S1F_V1F_S1F, vstart0:RVVS_ZERO}, + [RV_IT_VFMV_F_S] = { morph:emitScalarOp, opTCB:emitVFMVFS, vShape:RVVW_V1F_S1F_V1F }, + [RV_IT_VFCVT_XUF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_V1I_V1F, argType:RVVX_UU}, + [RV_IT_VFCVT_XF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_V1I_V1F, argType:RVVX_SS}, + [RV_IT_VFCVT_FXU_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_V1F_V1I, argType:RVVX_UU}, + [RV_IT_VFCVT_FX_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_V1F_V1I, argType:RVVX_SS}, + [RV_IT_VFWCVT_XUF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_V2I_V1F, argType:RVVX_UU}, + [RV_IT_VFWCVT_XF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_V2I_V1F, argType:RVVX_SS}, + [RV_IT_VFWCVT_FXU_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_V2F_V1I, argType:RVVX_UU}, + [RV_IT_VFWCVT_FX_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_V2F_V1I, argType:RVVX_SS}, + [RV_IT_VFWCVT_FF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_V2F_V1F_V1F_IW }, + [RV_IT_VFNCVT_XUF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_V1I_V2F_IW, argType:RVVX_UU}, + [RV_IT_VFNCVT_XF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_V1I_V2F_IW, argType:RVVX_SS}, + [RV_IT_VFNCVT_FXU_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_V1F_V2I_IW, argType:RVVX_UU}, + [RV_IT_VFNCVT_FX_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_V1F_V2I_IW, argType:RVVX_SS}, + [RV_IT_VFNCVT_FF_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRConvertFltCB, vShape:RVVW_V1F_V2F_V1F_IW }, + [RV_IT_VFCLASS_V] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRFClassFltCB, vShape:RVVW_V1F_V1F_V1F }, + [RV_IT_VFWREDSUM_VS] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRedBinaryFltCB, initCB:initVRedCB, endCB:endVRedCB, fpBinop:vmi_FADD, vShape:RVVW_S2F_V1F_S2F, vstart0:RVVS_ZERO}, + [RV_IT_VFWREDOSUM_VS] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, opTCB:emitVRedBinaryFltCB, initCB:initVRedCB, endCB:endVRedCB, fpBinop:vmi_FADD, vShape:RVVW_S2F_V1F_S2F, vstart0:RVVS_ZERO}, + [RV_IT_VFDOT_VV] = {fpConfig:RVFP_NORMAL, morph:emitVectorOp, checkCB:emitEDIVCheckCB, vShape:RVVW_V1F_V1F_V1F }, // V-extension MVV-type instructions - [RV_IT_VREDSUM_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_ADD, vShape:RVVW_111_SIS, vstart0:RVVS_ZERO}, - [RV_IT_VREDAND_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_AND, vShape:RVVW_111_SIS, vstart0:RVVS_ZERO}, - [RV_IT_VREDOR_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_OR, vShape:RVVW_111_SIS, vstart0:RVVS_ZERO}, - [RV_IT_VREDXOR_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_XOR, vShape:RVVW_111_SIS, vstart0:RVVS_ZERO}, - [RV_IT_VREDMINU_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_MIN, vShape:RVVW_111_SIS, vstart0:RVVS_ZERO}, - [RV_IT_VREDMIN_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_IMIN, vShape:RVVW_111_SIS, vstart0:RVVS_ZERO}, - [RV_IT_VREDMAXU_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_MAX, vShape:RVVW_111_SIS, vstart0:RVVS_ZERO}, - [RV_IT_VREDMAX_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_IMAX, vShape:RVVW_111_SIS, vstart0:RVVS_ZERO}, - [RV_IT_VEXT_X_V] = {morph:emitScalarOp, opTCB:emitVEXTXV, vShape:RVVW_111_IS, }, - [RV_IT_VPOPC_M] = {morph:emitVectorOp, opTCB:emitVPOPCCB, checkCB:initVPOPCCB, vShape:RVVW_111_PP, vstart0:RVVS_ZERO}, - [RV_IT_VFIRST_M] = {morph:emitVectorOp, opTCB:emitVFIRSTCB, checkCB:initVFIRSTCB, vShape:RVVW_111_PP, vstart0:RVVS_ZERO}, - [RV_IT_VMSBF_M] = {morph:emitVectorOp, opTCB:emitVMSBFCB, initCB:initVMSFCB, vShape:RVVW_111_PP, vstart0:RVVS_ZERO}, - [RV_IT_VMSOF_M] = {morph:emitVectorOp, opTCB:emitVMSOFCB, initCB:initVMSFCB, vShape:RVVW_111_PP, vstart0:RVVS_ZERO}, - [RV_IT_VMSIF_M] = {morph:emitVectorOp, opTCB:emitVMSIFCB, initCB:initVMSFCB, vShape:RVVW_111_PP, vstart0:RVVS_ZERO}, - [RV_IT_VIOTA_M] = {morph:emitVectorOp, opTCB:emitVIOTACB, initCB:initVIOTACB, vShape:RVVW_111_IP, vstart0:RVVS_ZERO}, - [RV_IT_VID_V] = {morph:emitVectorOp, opTCB:emitVIDTCB, opFCB:emitVIDFCB, initCB:initVIOTACB, vShape:RVVW_111_IP, }, - [RV_IT_VCOMPRESS_VM] = {morph:emitVectorOp, opTCB:emitVCOMPRESSCB, initCB:initVCOMPRESSCB, vShape:RVVW_111_CMP, vstart0:RVVS_ZERO, implicitTZ:1}, - [RV_IT_VMAND_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_AND, vShape:RVVW_111_PP}, - [RV_IT_VMANDNOT_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_ANDN, vShape:RVVW_111_PP}, - [RV_IT_VMOR_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_OR, vShape:RVVW_111_PP}, - [RV_IT_VMXOR_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_XOR, vShape:RVVW_111_PP}, - [RV_IT_VMORNOT_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_ORN, vShape:RVVW_111_PP}, - [RV_IT_VMNAND_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_NAND, vShape:RVVW_111_PP}, - [RV_IT_VMNOR_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_NOR, vShape:RVVW_111_PP}, - [RV_IT_VMXNOR_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_XNOR, vShape:RVVW_111_PP}, + [RV_IT_VREDSUM_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_ADD, vShape:RVVW_S1I_V1I_S1I, vstart0:RVVS_ZERO}, + [RV_IT_VREDAND_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_AND, vShape:RVVW_S1I_V1I_S1I, vstart0:RVVS_ZERO}, + [RV_IT_VREDOR_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_OR, vShape:RVVW_S1I_V1I_S1I, vstart0:RVVS_ZERO}, + [RV_IT_VREDXOR_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_XOR, vShape:RVVW_S1I_V1I_S1I, vstart0:RVVS_ZERO}, + [RV_IT_VREDMINU_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_MIN, vShape:RVVW_S1I_V1I_S1I, vstart0:RVVS_ZERO}, + [RV_IT_VREDMIN_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_IMIN, vShape:RVVW_S1I_V1I_S1I, vstart0:RVVS_ZERO}, + [RV_IT_VREDMAXU_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_MAX, vShape:RVVW_S1I_V1I_S1I, vstart0:RVVS_ZERO}, + [RV_IT_VREDMAX_VS] = {morph:emitVectorOp, opTCB:emitVRedBinaryIntCB, initCB:initVRedCB, endCB:endVRedCB, binop:vmi_IMAX, vShape:RVVW_S1I_V1I_S1I, vstart0:RVVS_ZERO}, + [RV_IT_VEXT_X_V] = {morph:emitScalarOp, opTCB:emitVEXTXV, vShape:RVVW_V1I_S1I_V1I, }, + [RV_IT_VPOPC_M] = {morph:emitVectorOp, opTCB:emitVPOPCCB, checkCB:initVPOPCCB, vShape:RVVW_P1I_P1I_P1I, vstart0:RVVS_ZERO}, + [RV_IT_VFIRST_M] = {morph:emitVectorOp, opTCB:emitVFIRSTCB, checkCB:initVFIRSTCB, vShape:RVVW_P1I_P1I_P1I, vstart0:RVVS_ZERO}, + [RV_IT_VMSBF_M] = {morph:emitVectorOp, opTCB:emitVMSBFCB, initCB:initVMSFCB, vShape:RVVW_P1I_P1I_P1I, vstart0:RVVS_ZERO}, + [RV_IT_VMSOF_M] = {morph:emitVectorOp, opTCB:emitVMSOFCB, initCB:initVMSFCB, vShape:RVVW_P1I_P1I_P1I, vstart0:RVVS_ZERO}, + [RV_IT_VMSIF_M] = {morph:emitVectorOp, opTCB:emitVMSIFCB, initCB:initVMSFCB, vShape:RVVW_P1I_P1I_P1I, vstart0:RVVS_ZERO}, + [RV_IT_VIOTA_M] = {morph:emitVectorOp, opTCB:emitVIOTACB, initCB:initVIOTACB, vShape:RVVW_V1I_P1I_P1I, vstart0:RVVS_ZERO}, + [RV_IT_VID_V] = {morph:emitVectorOp, opTCB:emitVIDTCB, opFCB:emitVIDFCB, initCB:initVIOTACB, vShape:RVVW_V1I_P1I_P1I, }, + [RV_IT_VCOMPRESS_VM] = {morph:emitVectorOp, opTCB:emitVCOMPRESSCB, initCB:initVCOMPRESSCB, vShape:RVVW_V1I_V1I_V1I_CMP, vstart0:RVVS_ZERO, implicitTZ:1}, + [RV_IT_VMAND_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_AND, vShape:RVVW_P1I_P1I_P1I}, + [RV_IT_VMANDNOT_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_ANDN, vShape:RVVW_P1I_P1I_P1I}, + [RV_IT_VMOR_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_OR, vShape:RVVW_P1I_P1I_P1I}, + [RV_IT_VMXOR_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_XOR, vShape:RVVW_P1I_P1I_P1I}, + [RV_IT_VMORNOT_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_ORN, vShape:RVVW_P1I_P1I_P1I}, + [RV_IT_VMNAND_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_NAND, vShape:RVVW_P1I_P1I_P1I}, + [RV_IT_VMNOR_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_NOR, vShape:RVVW_P1I_P1I_P1I}, + [RV_IT_VMXNOR_MM] = {morph:emitVectorOp, opTCB:emitMBinaryCB, binop:vmi_XNOR, vShape:RVVW_P1I_P1I_P1I}, // V-extension IVI-type instructions [RV_IT_VMERGE_VI] = {morph:emitVectorOp, opTCB:emitVIMERGETCB, opFCB:emitVRMERGEFCB}, @@ -8800,38 +9140,42 @@ const static riscvMorphAttr dispatchTable[] = { [RV_IT_VAND_VI] = {morph:emitVectorOp, opTCB:emitVIBinaryIntCB, binop:vmi_AND}, [RV_IT_VOR_VI] = {morph:emitVectorOp, opTCB:emitVIBinaryIntCB, binop:vmi_OR }, [RV_IT_VXOR_VI] = {morph:emitVectorOp, opTCB:emitVIBinaryIntCB, binop:vmi_XOR}, - [RV_IT_VRGATHER_VI] = {morph:emitVectorOp, opTCB:emitVIRGATHERCB, initCB:initVIRGATHERCB, vShape:RVVW_111_GR}, - [RV_IT_VSLIDEUP_VI] = {morph:emitVectorOp, opTCB:emitVISLIDEUPCB, vShape:RVVW_111_UP}, - [RV_IT_VSLIDEDOWN_VI] = {morph:emitVectorOp, opTCB:emitVISLIDEDOWNCB, vShape:RVVW_111_DN}, - [RV_IT_VADC_VI] = {morph:emitVectorOp, opTCB:emitVIAdcIntCB, binop:vmi_ADC, vShape:RVVW_CIN_II}, - [RV_IT_VMADC_VI] = {morph:emitVectorOp, opTCB:emitVIAdcIntCB, binop:vmi_ADC, vShape:RVVW_CIN_PI}, - [RV_IT_VSEQ_VI] = {morph:emitVectorOp, opTCB:emitVICmpIntCB, cond :vmi_COND_EQ, vShape:RVVW_111_PI}, - [RV_IT_VSNE_VI] = {morph:emitVectorOp, opTCB:emitVICmpIntCB, cond :vmi_COND_NE, vShape:RVVW_111_PI}, - [RV_IT_VSLEU_VI] = {morph:emitVectorOp, opTCB:emitVICmpIntCB, cond :vmi_COND_BE, vShape:RVVW_111_PI}, - [RV_IT_VSLE_VI] = {morph:emitVectorOp, opTCB:emitVICmpIntCB, cond :vmi_COND_LE, vShape:RVVW_111_PI}, - [RV_IT_VSGTU_VI] = {morph:emitVectorOp, opTCB:emitVICmpIntCB, cond :vmi_COND_NBE, vShape:RVVW_111_PI}, - [RV_IT_VSGT_VI] = {morph:emitVectorOp, opTCB:emitVICmpIntCB, cond :vmi_COND_NLE, vShape:RVVW_111_PI}, - [RV_IT_VSADDU_VI] = {morph:emitVectorOp, opTCB:emitVISBinaryCB, binop:vmi_ADDUQ, vShape:RVVW_111_IIS, argType:RVVX_UU}, - [RV_IT_VSADD_VI] = {morph:emitVectorOp, opTCB:emitVISBinaryCB, binop:vmi_ADDSQ, vShape:RVVW_111_IIS, argType:RVVX_SS}, - [RV_IT_VAADD_VI] = {morph:emitVectorOp, opTCB:emitVIABinaryCB, binop:vmi_ADDSH, vShape:RVVW_111_IIS, argType:RVVX_SS}, + [RV_IT_VRGATHER_VI] = {morph:emitVectorOp, opTCB:emitVIRGATHERCB, initCB:initVIRGATHERCB, vShape:RVVW_V1I_V1I_V1I_GR}, + [RV_IT_VSLIDEUP_VI] = {morph:emitVectorOp, opTCB:emitVISLIDEUPCB, vShape:RVVW_V1I_V1I_V1I_UP}, + [RV_IT_VSLIDEDOWN_VI] = {morph:emitVectorOp, opTCB:emitVISLIDEDOWNCB, vShape:RVVW_V1I_V1I_V1I_DN}, + [RV_IT_VADC_VI] = {morph:emitVectorOp, opTCB:emitVIAdcIntCB, binop:vmi_ADC, vShape:RVVW_V1I_V1I_V1I_CIN}, + [RV_IT_VMADC_VI] = {morph:emitVectorOp, opTCB:emitVIAdcIntCB, binop:vmi_ADC, vShape:RVVW_P1I_V1I_V1I_CIN}, + [RV_IT_VSEQ_VI] = {morph:emitVectorOp, opTCB:emitVICmpIntCB, cond :vmi_COND_EQ, vShape:RVVW_P1I_V1I_V1I}, + [RV_IT_VSNE_VI] = {morph:emitVectorOp, opTCB:emitVICmpIntCB, cond :vmi_COND_NE, vShape:RVVW_P1I_V1I_V1I}, + [RV_IT_VSLEU_VI] = {morph:emitVectorOp, opTCB:emitVICmpIntCB, cond :vmi_COND_BE, vShape:RVVW_P1I_V1I_V1I}, + [RV_IT_VSLE_VI] = {morph:emitVectorOp, opTCB:emitVICmpIntCB, cond :vmi_COND_LE, vShape:RVVW_P1I_V1I_V1I}, + [RV_IT_VSGTU_VI] = {morph:emitVectorOp, opTCB:emitVICmpIntCB, cond :vmi_COND_NBE, vShape:RVVW_P1I_V1I_V1I}, + [RV_IT_VSGT_VI] = {morph:emitVectorOp, opTCB:emitVICmpIntCB, cond :vmi_COND_NLE, vShape:RVVW_P1I_V1I_V1I}, + [RV_IT_VSADDU_VI] = {morph:emitVectorOp, opTCB:emitVISBinaryCB, binop:vmi_ADDUQ, vShape:RVVW_V1I_V1I_V1I_SAT, argType:RVVX_UU}, + [RV_IT_VSADD_VI] = {morph:emitVectorOp, opTCB:emitVISBinaryCB, binop:vmi_ADDSQ, vShape:RVVW_V1I_V1I_V1I_SAT, argType:RVVX_SS}, + [RV_IT_VAADD_VI] = {morph:emitVectorOp, opTCB:emitVIABinaryCB, binop:vmi_ADDSH, vShape:RVVW_V1I_V1I_V1I_SAT, argType:RVVX_SS}, [RV_IT_VSLL_VI] = {morph:emitVectorOp, opTCB:emitVIShiftIntCB, binop:vmi_SHL}, [RV_IT_VMVR_VI] = {morph:emitVectorOp, opTCB:emitVRUnaryIntCB, unop :vmi_MOV, checkCB:emitVMVRCheckCB}, [RV_IT_VSRL_VI] = {morph:emitVectorOp, opTCB:emitVIShiftIntCB, binop:vmi_SHR}, [RV_IT_VSRA_VI] = {morph:emitVectorOp, opTCB:emitVIShiftIntCB, binop:vmi_SAR}, - [RV_IT_VSSRL_VI] = {morph:emitVectorOp, opTCB:emitVIRShiftIntCB, binop:vmi_SHR, vShape:RVVW_111_IIX}, - [RV_IT_VSSRA_VI] = {morph:emitVectorOp, opTCB:emitVIRShiftIntCB, binop:vmi_SAR, vShape:RVVW_111_IIX}, - [RV_IT_VNSRL_VI] = {morph:emitVectorOp, opTCB:emitVIShiftIntCB, binop:vmi_SHR, vShape:RVVW_121_II}, - [RV_IT_VNSRA_VI] = {morph:emitVectorOp, opTCB:emitVIShiftIntCB, binop:vmi_SAR, vShape:RVVW_121_II}, - [RV_IT_VNCLIPU_VI] = {morph:emitVectorOp, opTCB:emitVIRShiftIntCB, binop:vmi_SHR, vShape:RVVW_121_IIS, argType:RVVX_UU}, - [RV_IT_VNCLIP_VI] = {morph:emitVectorOp, opTCB:emitVIRShiftIntCB, binop:vmi_SAR, vShape:RVVW_121_IIS, argType:RVVX_SS}, + [RV_IT_VSSRL_VI] = {morph:emitVectorOp, opTCB:emitVIRShiftIntCB, binop:vmi_SHR, vShape:RVVW_V1I_V1I_V1I_VXRM}, + [RV_IT_VSSRA_VI] = {morph:emitVectorOp, opTCB:emitVIRShiftIntCB, binop:vmi_SAR, vShape:RVVW_V1I_V1I_V1I_VXRM}, + [RV_IT_VNSRL_VI] = {morph:emitVectorOp, opTCB:emitVIShiftIntCB, binop:vmi_SHR, vShape:RVVW_V1I_V2I_V1I}, + [RV_IT_VNSRA_VI] = {morph:emitVectorOp, opTCB:emitVIShiftIntCB, binop:vmi_SAR, vShape:RVVW_V1I_V2I_V1I}, + [RV_IT_VNCLIPU_VI] = {morph:emitVectorOp, opTCB:emitVIRShiftIntCB, binop:vmi_SHR, vShape:RVVW_V1I_V2I_V1I_SAT, argType:RVVX_UU}, + [RV_IT_VNCLIP_VI] = {morph:emitVectorOp, opTCB:emitVIRShiftIntCB, binop:vmi_SAR, vShape:RVVW_V1I_V2I_V1I_SAT, argType:RVVX_SS}, // V-extension FVF-type instructions - [RV_IT_VFMV_S_F] = {morph:emitScalarOp, opTCB:emitVFMVSF, vShape:RVVW_111_SI}, + [RV_IT_VFMV_S_F] = {morph:emitScalarOp, opTCB:emitVFMVSF, vShape:RVVW_S1F_V1I_V1I}, + [RV_IT_VFSLIDE1UP_VF] = {morph:emitVectorOp, opTCB:emitVRSLIDE1UPCB, initCB:initVFSLIDE1CB, vShape:RVVW_V1I_V1I_V1I_UP}, + [RV_IT_VFSLIDE1DOWN_VF] = {morph:emitVectorOp, opTCB:emitVRSLIDE1DOWNCB, initCB:initVFSLIDE1CB, vShape:RVVW_V1I_V1I_V1I_DN}, // V-extension MVX-type instructions - [RV_IT_VMV_S_X] = {morph:emitScalarOp, opTCB:emitVMVSX, vShape:RVVW_111_SI}, - [RV_IT_VSLIDE1UP_VX] = {morph:emitVectorOp, opTCB:emitVRSLIDE1UPCB, initCB:initVRSLIDE1CB, vShape:RVVW_111_UP}, - [RV_IT_VSLIDE1DOWN_VX] = {morph:emitVectorOp, opTCB:emitVRSLIDE1DOWNCB, initCB:initVRSLIDE1CB, vShape:RVVW_111_DN}, + [RV_IT_VMV_S_X] = {morph:emitScalarOp, opTCB:emitVMVSX, vShape:RVVW_S1I_V1I_V1I}, + [RV_IT_VSLIDE1UP_VX] = {morph:emitVectorOp, opTCB:emitVRSLIDE1UPCB, initCB:initVXSLIDE1CB, vShape:RVVW_V1I_V1I_V1I_UP}, + [RV_IT_VSLIDE1DOWN_VX] = {morph:emitVectorOp, opTCB:emitVRSLIDE1DOWNCB, initCB:initVXSLIDE1CB, vShape:RVVW_V1I_V1I_V1I_DN}, + [RV_IT_VZEXT_V] = {morph:emitVectorOp, opTCB:emitVRUnaryIntCB, unop :vmi_MOV, vShape:RVVW_V1I_V2I_FN, argType:RVVX_UU}, + [RV_IT_VSEXT_V] = {morph:emitVectorOp, opTCB:emitVRUnaryIntCB, unop :vmi_MOV, vShape:RVVW_V1I_V2I_FN, argType:RVVX_SS}, // KEEP LAST [RV_IT_LAST] = {0} @@ -8860,7 +9204,7 @@ VMI_START_END_BLOCK_FN(riscvStartBlock) { // current vector configuration is not known initially thisState->SEWMt = SEWMT_UNKNOWN; - thisState->VLMULMt = VLMULMT_UNKNOWN; + thisState->VLMULx8Mt = VLMULx8MT_UNKNOWN; thisState->VLClassMt = VLCLASSMT_UNKNOWN; thisState->VZeroTopMt[VTZ_SINGLE] = 0; thisState->VZeroTopMt[VTZ_GROUP] = 0; @@ -8869,7 +9213,7 @@ VMI_START_END_BLOCK_FN(riscvStartBlock) { // inherit any previously-active SEW, VLMUL and VLClass if(prevState) { thisState->SEWMt = prevState->SEWMt; - thisState->VLMULMt = prevState->VLMULMt; + thisState->VLMULx8Mt = prevState->VLMULx8Mt; thisState->VLClassMt = prevState->VLClassMt; } } diff --git a/source/riscvMorph.h b/source/riscvMorph.h index 7f1780e..0a435bc 100644 --- a/source/riscvMorph.h +++ b/source/riscvMorph.h @@ -23,6 +23,7 @@ #include "riscvBlockState.h" #include "riscvRegisterTypes.h" #include "riscvTypeRefs.h" +#include "riscvTypes.h" #include "riscvVectorTypes.h" #include "riscvVariant.h" @@ -48,6 +49,15 @@ typedef struct illegalDescS { riscvEmitIllegalInstructionMessageDesc(_RISCV, &_DESC); \ } +// +// Macro used to define illegalDesc structure and emit an Illegal Instruction +// using it (operand check) +// +#define ILLEGAL_OPERAND_MESSAGE(_RISCV, _ID, _DETAIL, _OPERAND) { \ + static illegalDesc _DESC = { .id=CPU_PREFIX"_"_ID, .detail=_DETAIL}; \ + riscvEmitIllegalOperandMessageDesc(_RISCV, &_DESC, _OPERAND); \ +} + // // Emit Illegal Instruction because the current mode has insufficient // privilege @@ -59,6 +69,15 @@ void riscvEmitIllegalInstructionMode(riscvP riscv); // void riscvEmitIllegalInstructionMessageDesc(riscvP riscv, illegalDescP desc); +// +// Emit Illegal Operand message and take Illegal Instruction exception +// +void riscvEmitIllegalOperandMessageDesc( + riscvP riscv, + illegalDescP desc, + Uns32 operand +); + // // Validate that the given required feature is present and enabled (using // blockMask if necessary) @@ -180,9 +199,15 @@ void riscvFreeVector(riscvP riscv); void riscvWVStart(riscvMorphStateP state, Bool useRS1); // -// Is the specified SEW valid? +// Return maximum vector length for the given vector type settings +// +Uns32 riscvGetMaxVL(riscvP riscv, riscvVType vtype); + +// +// If the specified vtype is valid, return the SEW, otherwise return +// SEWMT_UNKNOWN // -riscvSEWMt riscvValidSEW(riscvP riscv, Uns8 vsew); +riscvSEWMt riscvValidVType(riscvP riscv, riscvVType vtype); // // Emit externally-implemented vector operation diff --git a/source/riscvParameters.c b/source/riscvParameters.c index 5b3ed9c..a3a0232 100644 --- a/source/riscvParameters.c +++ b/source/riscvParameters.c @@ -159,6 +159,11 @@ static vmiEnumParameter vectorVariants[] = { .value = RVVV_0_8, .description = "Vector Architecture Version 0.8", }, + [RVVV_0_9] = { + .name = "0.9", + .value = RVVV_0_9, + .description = "Vector Architecture Version 0.9", + }, [RVVV_MASTER] = { .name = "master", .value = RVVV_MASTER, @@ -224,6 +229,11 @@ static vmiEnumParameter DMModes[] = { .value = RVDM_NONE, .description = "Debug mode not implemented", }, + [RVDM_VECTOR] = { + .name = "vector", + .value = RVDM_VECTOR, + .description = "Debug mode implemented by execution at vector", + }, [RVDM_INTERRUPT] = { .name = "interrupt", .value = RVDM_INTERRUPT, @@ -360,6 +370,7 @@ static RISCV_BOOL_PDEFAULT_CFG_FN(unaligned); static RISCV_BOOL_PDEFAULT_CFG_FN(unalignedAMO); static RISCV_BOOL_PDEFAULT_CFG_FN(wfi_is_nop); static RISCV_BOOL_PDEFAULT_CFG_FN(mtvec_is_ro); +static RISCV_BOOL_PDEFAULT_CFG_FN(tval_zero); static RISCV_BOOL_PDEFAULT_CFG_FN(tval_ii_code); static RISCV_BOOL_PDEFAULT_CFG_FN(cycle_undefined); static RISCV_BOOL_PDEFAULT_CFG_FN(time_undefined); @@ -378,6 +389,7 @@ static RISCV_BOOL_PDEFAULT_CFG_FN(CLICMCSW); // Set default value of raw Uns32 parameters // static RISCV_UNS32_PDEFAULT_CFG_FN(tvec_align); +static RISCV_UNS32_PDEFAULT_CFG_FN(counteren_mask); static RISCV_UNS32_PDEFAULT_CFG_FN(PMP_grain) static RISCV_UNS32_PDEFAULT_CFG_FN(PMP_registers); static RISCV_UNS32_PDEFAULT_CFG_FN(CLICLEVELS); @@ -388,6 +400,8 @@ static RISCV_UNS32_PDEFAULT_CFG_FN(CLICCFGLBITS); // static RISCV_UNS64_PDEFAULT_CFG_FN(reset_address) static RISCV_UNS64_PDEFAULT_CFG_FN(nmi_address) +static RISCV_UNS64_PDEFAULT_CFG_FN(debug_address) +static RISCV_UNS64_PDEFAULT_CFG_FN(dexc_address) static RISCV_UNS64_PDEFAULT_CFG_FN(unimp_int_mask) static RISCV_UNS64_PDEFAULT_CFG_FN(no_ideleg) static RISCV_UNS64_PDEFAULT_CFG_FN(no_edeleg) @@ -449,11 +463,8 @@ static RISCV_PDEFAULT_FN(default_misa_Extensions) { // static RISCV_PDEFAULT_FN(default_misa_Extensions_mask) { - // if archMask is zero, assume all bits except E, S and U are writable - Uns32 mask = cfg->archMask ? : ~(ISA_XLEN_ANY|ISA_E|ISA_S|ISA_U); - // only bits that are non-zero in arch are writable - setUns32ParamDefault(param, cfg->arch & mask); + setUns32ParamDefault(param, cfg->arch & cfg->archMask); } // @@ -475,6 +486,42 @@ static RISCV_PDEFAULT_FN(default_local_int_num) { setUns32ParamMax(param, maxLocal); } +// +// Set default value of ecode_mask +// +static RISCV_PDEFAULT_FN(default_ecode_mask) { + + Uns64 ecode_mask = cfg->ecode_mask; + + if(ecode_mask) { + // use specified mask + } else if(cfg->CLICLEVELS) { + ecode_mask = 0xfff; + } else if(cfg->arch & ISA_XLEN_64) { + ecode_mask = (1ULL<<63)-1; + } else { + ecode_mask = (1ULL<<31)-1; + } + + setUns64ParamDefault(param, ecode_mask); +} + +// +// Set default value of ecode_nmi +// +static RISCV_PDEFAULT_FN(default_ecode_nmi) { + + Uns64 ecode_nmi = cfg->ecode_nmi; + + if(ecode_nmi) { + // use specified mask + } else if(cfg->CLICLEVELS) { + ecode_nmi = 0xfff; + } + + setUns64ParamDefault(param, ecode_nmi); +} + // // Set default and maximum value of ASID_bits // @@ -492,6 +539,14 @@ static RISCV_PDEFAULT_FN(default_CLICINTCTLBITS) { setUns32ParamDefault(param, cfg->CLICINTCTLBITS ? : 2); } +// +// Set default and maximum value of CLICVERSION +// +static RISCV_PDEFAULT_FN(default_CLICVERSION) { + + setUns32ParamDefault(param, cfg->CLICVERSION ? : 0x11); +} + // // Set default and maximum value of CLICCFGMBITS // @@ -517,6 +572,7 @@ static RISCV_CSR_PDEFAULT_CFG_FN(marchid) static RISCV_CSR_PDEFAULT_CFG_FN(mimpid) static RISCV_CSR_PDEFAULT_CFG_FN(mhartid) static RISCV_CSR_PDEFAULT_CFG_FN(mtvec) +static RISCV_CSR_PDEFAULT_CFG_FN(mclicbase) // // Macro to define a function to set an Uns64 CSR mask value from the @@ -573,6 +629,8 @@ static riscvParameter parameters[] = { { RVPV_FPV, default_fp16_version, VMI_ENUM_PARAM_SPEC (riscvParamValues, fp16_version, fp16Variants, "Specify required 16-bit floating point format")}, { RVPV_FP, default_mstatus_fs_mode, VMI_ENUM_PARAM_SPEC (riscvParamValues, mstatus_fs_mode, FSModes, "Specify conditions causing update of mstatus.FS to dirty")}, { RVPV_ALL, default_debug_mode, VMI_ENUM_PARAM_SPEC (riscvParamValues, debug_mode, DMModes, "Specify how Debug mode is implemented")}, + { RVPV_ALL, default_debug_address, VMI_UNS64_PARAM_SPEC (riscvParamValues, debug_address, 0, 0, -1, "Specify address to which to jump to enter debug in vectored mode")}, + { RVPV_ALL, default_dexc_address, VMI_UNS64_PARAM_SPEC (riscvParamValues, dexc_address, 0, 0, -1, "Specify address to which to jump on debug exception in vectored mode")}, { RVPV_ALL, 0, VMI_BOOL_PARAM_SPEC (riscvParamValues, verbose, False, "Specify verbose output messages")}, { RVPV_MPCORE, default_numHarts, VMI_UNS32_PARAM_SPEC (riscvParamValues, numHarts, 0, 0, 32, "Specify the number of hart contexts in a multiprocessor")}, { RVPV_S, default_updatePTEA, VMI_BOOL_PARAM_SPEC (riscvParamValues, updatePTEA, False, "Specify whether hardware update of PTE A bit is supported")}, @@ -582,19 +640,23 @@ static riscvParameter parameters[] = { { RVPV_ALL, default_wfi_is_nop, VMI_BOOL_PARAM_SPEC (riscvParamValues, wfi_is_nop, False, "Specify whether WFI should be treated as a NOP (if not, halt while waiting for interrupts)")}, { RVPV_ALL, default_mtvec_is_ro, VMI_BOOL_PARAM_SPEC (riscvParamValues, mtvec_is_ro, False, "Specify whether mtvec CSR is read-only")}, { RVPV_ALL, default_tvec_align, VMI_UNS32_PARAM_SPEC (riscvParamValues, tvec_align, 0, 0, (1<<16), "Specify hardware-enforced alignment of mtvec/stvec/utvec when Vectored interrupt mode enabled")}, + { RVPV_ALL, default_counteren_mask, VMI_UNS32_PARAM_SPEC (riscvParamValues, counteren_mask, 0, 0, -1, "Specify hardware-enforced mask of writable bits in mcounteren/scounteren registers")}, { RVPV_ALL, default_mtvec_mask, VMI_UNS64_PARAM_SPEC (riscvParamValues, mtvec_mask, 0, 0, -1, "Specify hardware-enforced mask of writable bits in mtvec register")}, { RVPV_S, default_stvec_mask, VMI_UNS64_PARAM_SPEC (riscvParamValues, stvec_mask, 0, 0, -1, "Specify hardware-enforced mask of writable bits in stvec register")}, { RVPV_N, default_utvec_mask, VMI_UNS64_PARAM_SPEC (riscvParamValues, utvec_mask, 0, 0, -1, "Specify hardware-enforced mask of writable bits in utvec register")}, { RVPV_CLIC, default_mtvt_mask, VMI_UNS64_PARAM_SPEC (riscvParamValues, mtvt_mask, 0, 0, -1, "Specify hardware-enforced mask of writable bits in CLIC mtvt register")}, { RVPV_CLIC_S, default_stvt_mask, VMI_UNS64_PARAM_SPEC (riscvParamValues, stvt_mask, 0, 0, -1, "Specify hardware-enforced mask of writable bits in CLIC stvt register")}, { RVPV_CLIC_N, default_utvt_mask, VMI_UNS64_PARAM_SPEC (riscvParamValues, utvt_mask, 0, 0, -1, "Specify hardware-enforced mask of writable bits in CLIC utvt register")}, + { RVPV_ALL, default_ecode_mask, VMI_UNS64_PARAM_SPEC (riscvParamValues, ecode_mask, 0, 0, -1, "Specify hardware-enforced mask of writable bits in xcause.ExceptionCode")}, + { RVPV_ALL, default_ecode_nmi, VMI_UNS64_PARAM_SPEC (riscvParamValues, ecode_nmi, 0, 0, -1, "Specify xcause.ExceptionCode for NMI")}, + { RVPV_ALL, default_tval_zero, VMI_BOOL_PARAM_SPEC (riscvParamValues, tval_zero, False, "Specify whether mtval/stval/utval are hard wired to zero")}, { RVPV_ALL, default_tval_ii_code, VMI_BOOL_PARAM_SPEC (riscvParamValues, tval_ii_code, False, "Specify whether mtval/stval contain faulting instruction bits on illegal instruction exception")}, { RVPV_ALL, default_cycle_undefined, VMI_BOOL_PARAM_SPEC (riscvParamValues, cycle_undefined, False, "Specify that the cycle CSR is undefined (reads to it are emulated by a Machine mode trap)")}, { RVPV_ALL, default_time_undefined, VMI_BOOL_PARAM_SPEC (riscvParamValues, time_undefined, False, "Specify that the time CSR is undefined (reads to it are emulated by a Machine mode trap)")}, { RVPV_ALL, default_instret_undefined, VMI_BOOL_PARAM_SPEC (riscvParamValues, instret_undefined, False, "Specify that the instret CSR is undefined (reads to it are emulated by a Machine mode trap)")}, { RVPV_ALL, default_enable_CSR_bus, VMI_BOOL_PARAM_SPEC (riscvParamValues, enable_CSR_bus, False, "Add artifact CSR bus port, allowing CSR registers to be externally implemented")}, { RVPV_FP, default_d_requires_f, VMI_BOOL_PARAM_SPEC (riscvParamValues, d_requires_f, False, "If D and F extensions are separately enabled in the misa CSR, whether D is enabled only if F is enabled")}, - { RVPV_A, default_xret_preserves_lr, VMI_BOOL_PARAM_SPEC (riscvParamValues, xret_preserves_lr, False, "Whether an xRET instruction preserves the value of LR")}, + { RVPV_ALL, default_xret_preserves_lr, VMI_BOOL_PARAM_SPEC (riscvParamValues, xret_preserves_lr, False, "Whether an xRET instruction preserves the value of LR")}, { RVPV_V, default_require_vstart0, VMI_BOOL_PARAM_SPEC (riscvParamValues, require_vstart0, False, "Whether CSR vstart must be 0 for non-interruptible vector instructions")}, { RVPV_S, default_ASID_bits, VMI_UNS32_PARAM_SPEC (riscvParamValues, ASID_bits, 0, 0, 0, "Specify the number of implemented ASID bits")}, { RVPV_A, default_lr_sc_grain, VMI_UNS32_PARAM_SPEC (riscvParamValues, lr_sc_grain, 1, 1, (1<<16), "Specify byte granularity of ll/sc lock region (constrained to a power of two)")}, @@ -624,6 +686,7 @@ static riscvParameter parameters[] = { { RVPV_ALL, default_mimpid, VMI_UNS64_PARAM_SPEC (riscvParamValues, mimpid, 0, 0, -1, "Override mimpid register")}, { RVPV_ALL, default_mhartid, VMI_UNS64_PARAM_SPEC (riscvParamValues, mhartid, 0, 0, -1, "Override mhartid register (or first mhartid of an incrementing sequence if this is an SMP variant)")}, { RVPV_ALL, default_mtvec, VMI_UNS64_PARAM_SPEC (riscvParamValues, mtvec, 0, 0, -1, "Override mtvec register")}, + { RVPV_CLIC, default_mclicbase, VMI_UNS64_PARAM_SPEC (riscvParamValues, mclicbase, 0, 0, -1, "Override mclicbase register")}, { RVPV_FP, 0, VMI_UNS32_PARAM_SPEC (riscvParamValues, mstatus_FS, 0, 0, 3, "Override default value of mstatus.FS (initial state of floating point unit)")}, { RVPV_V, default_ELEN, VMI_UNS32_PARAM_SPEC (riscvParamValues, ELEN, 0, ELEN_MIN, ELEN_MAX, "Override ELEN (vector extension)")}, { RVPV_V, default_SLEN, VMI_UNS32_PARAM_SPEC (riscvParamValues, SLEN, 0, SLEN_MIN, VLEN_MAX, "Override SLEN (vector extension)")}, @@ -635,14 +698,15 @@ static riscvParameter parameters[] = { { RVPV_V, default_Zvqmac, VMI_BOOL_PARAM_SPEC (riscvParamValues, Zvqmac, False, "Specify that Zvqmac is implemented (vector extension)")}, // CLIC configuration - { RVPV_INT_CFG, default_CLICLEVELS, VMI_UNS32_PARAM_SPEC (riscvParamValues, CLICLEVELS, 0, 0, 256, "Specify number of interrupt levels implemented by CLIC, or 0 if CLIC absent (NOTE: do not use, feature under development)")}, + { RVPV_INT_CFG, default_CLICLEVELS, VMI_UNS32_PARAM_SPEC (riscvParamValues, CLICLEVELS, 0, 0, 256, "Specify number of interrupt levels implemented by CLIC, or 0 if CLIC absent")}, { RVPV_CLIC, default_CLICANDBASIC, VMI_BOOL_PARAM_SPEC (riscvParamValues, CLICANDBASIC, False, "Whether original basic mode is also implemented")}, + { RVPV_CLIC, default_CLICVERSION, VMI_UNS32_PARAM_SPEC (riscvParamValues, CLICVERSION, 0, 0, 255, "Specify CLIC version")}, { RVPV_CLIC, default_CLICINTCTLBITS, VMI_UNS32_PARAM_SPEC (riscvParamValues, CLICINTCTLBITS, 2, 2, 8, "Specify number of bits implemented in clicintctl[i]")}, { RVPV_CLIC_NM, default_CLICCFGMBITS, VMI_UNS32_PARAM_SPEC (riscvParamValues, CLICCFGMBITS, 0, 0, 0, "Specify number of bits implemented for cliccfg.nmbits (also defines CLICPRIVMODES)")}, { RVPV_CLIC, default_CLICCFGLBITS, VMI_UNS32_PARAM_SPEC (riscvParamValues, CLICCFGLBITS, 0, 0, 8, "Specify number of bits implemented for cliccfg.nlbits")}, { RVPV_CLIC, default_CLICSELHVEC, VMI_BOOL_PARAM_SPEC (riscvParamValues, CLICSELHVEC, False, "Whether selective hardware vectoring supported")}, - { RVPV_CLIC, default_CLICMNXTI, VMI_BOOL_PARAM_SPEC (riscvParamValues, CLICMNXTI, False, "Whether mnxti CSR implemented")}, - { RVPV_CLIC, default_CLICMCSW, VMI_BOOL_PARAM_SPEC (riscvParamValues, CLICMCSW, False, "Whether mscratchcsw/mscratchcswl CSRs implemented")}, + { RVPV_CLIC, default_CLICMNXTI, VMI_BOOL_PARAM_SPEC (riscvParamValues, CLICMNXTI, False, "Whether xnxti CSRs implemented")}, + { RVPV_CLIC, default_CLICMCSW, VMI_BOOL_PARAM_SPEC (riscvParamValues, CLICMCSW, False, "Whether xscratchcsw/xscratchcswl CSRs implemented")}, // KEEP LAST { RVPV_ALL, 0, VMI_END_PARAM} diff --git a/source/riscvParameters.h b/source/riscvParameters.h index 3037890..30aaea9 100644 --- a/source/riscvParameters.h +++ b/source/riscvParameters.h @@ -42,12 +42,15 @@ typedef struct riscvParamValuesS { VMI_BOOL_PARAM(verbose); VMI_UNS32_PARAM(numHarts); VMI_BOOL_PARAM(debug_mode); + VMI_UNS64_PARAM(debug_address); + VMI_UNS64_PARAM(dexc_address); VMI_BOOL_PARAM(updatePTEA); VMI_BOOL_PARAM(updatePTED); VMI_BOOL_PARAM(unaligned); VMI_BOOL_PARAM(unalignedAMO); VMI_BOOL_PARAM(wfi_is_nop); VMI_BOOL_PARAM(mtvec_is_ro); + VMI_UNS32_PARAM(counteren_mask); VMI_UNS32_PARAM(tvec_align); VMI_UNS64_PARAM(mtvec_mask); VMI_UNS64_PARAM(stvec_mask); @@ -55,6 +58,9 @@ typedef struct riscvParamValuesS { VMI_UNS64_PARAM(mtvt_mask); VMI_UNS64_PARAM(stvt_mask); VMI_UNS64_PARAM(utvt_mask); + VMI_UNS64_PARAM(ecode_mask); + VMI_UNS64_PARAM(ecode_nmi); + VMI_BOOL_PARAM(tval_zero); VMI_BOOL_PARAM(tval_ii_code); VMI_BOOL_PARAM(time_undefined); VMI_BOOL_PARAM(cycle_undefined); @@ -102,8 +108,10 @@ typedef struct riscvParamValuesS { VMI_BOOL_PARAM(Zvqmac); // CLIC configuration + VMI_UNS64_PARAM(mclicbase); VMI_UNS32_PARAM(CLICLEVELS); VMI_BOOL_PARAM(CLICANDBASIC); + VMI_UNS32_PARAM(CLICVERSION); VMI_UNS32_PARAM(CLICINTCTLBITS); VMI_UNS32_PARAM(CLICCFGMBITS); VMI_UNS32_PARAM(CLICCFGLBITS); diff --git a/source/riscvRegisters.h b/source/riscvRegisters.h index 11d6467..ae5aa71 100644 --- a/source/riscvRegisters.h +++ b/source/riscvRegisters.h @@ -45,6 +45,7 @@ #define RISCV_FPR(_I) RISCV_CPU_REG(f[_I]) #define RISCV_SF_TMP RISCV_CPU_TEMP(SF) #define RISCV_LR RISCV_CPU_REG(x[RV_REG_X_RA]) +#define RISCV_EA_ADDR RISCV_CPU_REG(exclusiveAddr) #define RISCV_EA_TAG RISCV_CPU_REG(exclusiveTag) #define RISCV_DM RISCV_CPU_REG(DM) #define RISCV_DM_STALL RISCV_CPU_REG(DMStall) diff --git a/source/riscvStructure.h b/source/riscvStructure.h index 8a7b212..2779553 100644 --- a/source/riscvStructure.h +++ b/source/riscvStructure.h @@ -24,6 +24,7 @@ #include "vmi/vmiPorts.h" // model header files +#include "riscvCLICTypes.h" #include "riscvConfig.h" #include "riscvCSR.h" #include "riscvExceptionTypes.h" @@ -40,7 +41,6 @@ #define RISCV_DISASSEMBLE_MASK 0x00000001 #define RISCV_DEBUG_MMU_MASK 0x00000002 #define RISCV_DEBUG_EXCEPT_MASK 0x00000004 -#define RISCV_DEBUG_VECTIDX_MASK 0x00000008 // // Processor flag selection macros @@ -48,7 +48,6 @@ #define RISCV_DISASSEMBLE(_P) ((_P)->flags & RISCV_DISASSEMBLE_MASK) #define RISCV_DEBUG_MMU(_P) ((_P)->flags & RISCV_DEBUG_MMU_MASK) #define RISCV_DEBUG_EXCEPT(_P) ((_P)->flags & RISCV_DEBUG_EXCEPT_MASK) -#define RISCV_DEBUG_VECTIDX(_P) ((_P)->flags & RISCV_DEBUG_VECTIDX_MASK) // // Debug flags that should be disabled during save/restore @@ -72,7 +71,8 @@ typedef struct riscvNetValueS { Bool haltreq; // haltreq (Debug mode) Bool resethaltreq; // resethaltreq (Debug mode) Bool resethaltreqS; // resethaltreq (Debug mode, sampled at reset) - Bool _u1[3]; // (for alignment) + Bool deferint; // defer taking interrupts (artifact) + Bool _u1[2]; // (for alignment) } riscvNetValue; // @@ -90,9 +90,24 @@ typedef union riscvPMPCFGU { } riscvPMPCFG; // -// This holds all state contributing to an interrupt (for debug messages) +// This code indicates no interrupt is pending // -typedef struct riscvIntStateS { +#define RV_NO_INT -1 + +// +// This holds information about a pending-and-enabled interrupt +// +typedef struct riscvPendEnabS { + riscvMode priv; // mode to which taken + Int32 id; // interrupt id + Uns8 level; // interrupt level + Bool isCLIC; // whether CLIC mode interrupt +} riscvPendEnab; + +// +// This holds all state contributing to a basic mode interrupt (for debug) +// +typedef struct riscvBasicIntStateS { Uns64 pendingEnabled; // pending-and-enabled state Uns64 pending; // pending state Uns64 pendingExternal; // pending external interrupts @@ -103,7 +118,30 @@ typedef struct riscvIntStateS { Bool sie; // mstatus.sie Bool uie; // mstatus.uie Bool _u1; // (for alignment) -} riscvIntState; +} riscvBasicIntState; + +// +// This holds state for a pending CLIC interrupt +// +typedef struct riscvCLICOutStateS { + riscvMode priv; // privilege mode + Int32 id; // interrupt id + Uns8 level; // interrupt level + Bool shv; // whether selectively hardware vectored + Bool _u1[6]; // (for alignment) +} riscvCLICOutState; + +// +// This holds CLIC state +// +typedef struct riscvCLICS { + riscvCLICOutState sel; // selected interrupt state + CLIC_REG_DECL (cliccfg); // cliccfg register value + CLIC_REG_DECL (clicinfo); // clicinfo register value + riscvPP harts; // member harts + riscvCLICIntStateP intState; // state for each interrupt + Uns64 *ipe; // mask of pending-and-enabled interrupts +} riscvCLIC; // // This holds processor and vector information for an interrupt @@ -138,12 +176,6 @@ typedef struct riscvNetPortS { #define LMUL_MAX 8 #define NUM_BASE_REGS 4 -// -// This defines the type of elements of the stride tables used to handle -// striping -// -typedef Uns16 riscvStrideOffset; - // // Processor model structure // @@ -162,6 +194,7 @@ typedef struct riscvS { riscvArchitecture currentArch; // current enabled features riscvDMode mode; // current processor mode riscvDisableReason disable; // reason why processor is disabled + Uns32 numHarts; // numer of hart contexts in container Bool verbose :1;// whether verbose output enabled Bool artifactAccess:1;// whether current access is an artifact Bool externalActive:1;// whether external CSR access active @@ -195,7 +228,9 @@ typedef struct riscvS { Uns32 swip; // software interrupt pending bits Uns64 exceptionMask; // mask of all implemented exceptions Uns64 interruptMask; // mask of all implemented interrupts + riscvPendEnab pendEnab; // pending and enabled interrupt Uns32 extInt[RISCV_MODE_LAST]; // external interrupt override + riscvCLIC clic; // source interrupt indicated from CLIC riscvException exception : 16; // last activated exception riscvICMode MIMode : 2; // custom M interrupt mode riscvICMode SIMode : 2; // custom S interrupt mode @@ -226,6 +261,9 @@ typedef struct riscvS { Uns32 ipDWords; // size of ip in words Uns64 *ip; // interrupt port values Uns32 DMPortHandle; // DM port handle (debug mode) + Uns32 LRAddressHandle; // LR address port handle (locking) + Uns32 SCAddressHandle; // SC address port handle (locking) + Uns32 AMOActiveHandle; // active AMO operation // Timers vmiModelTimerP stepTimer; // Debug mode single-step timer @@ -239,6 +277,7 @@ typedef struct riscvS { memDomainP vmDomains [RISCV_MODE_LAST][2]; // mapped domains memDomainP pmpDomains [RISCV_MODE_LAST][2]; // pmp domains memDomainP physDomains[RISCV_MODE_LAST][2]; // physical domains + memDomainP CLICDomain; // CLIC domain riscvPMPCFG pmpcfg; // pmpcfg registers Uns64 pmpaddr[NUM_PMPS]; // pmpaddr registers riscvTLBP tlb; // TLB cache @@ -247,7 +286,8 @@ typedef struct riscvS { Bool PTWBadAddr : 1; // page table walk address was bad // Messages - riscvIntState intState; // for exception debug + riscvBasicIntState intState; // basic interrupt state + riscvCLICOutState clicState; // CLIC interrupt state // JIT code translation control riscvBlockStateP blockState; // active block state @@ -263,9 +303,6 @@ typedef struct riscvS { Uns64 vTmp; // vector operation temporary UnsPS vBase[NUM_BASE_REGS]; // indexed base registers Uns32 *v; // vector registers (configurable size) - riscvStrideOffset *offsetsLMULx2; // LMULx2 stride offsets - riscvStrideOffset *offsetsLMULx4; // LMULx4 stride offsets - riscvStrideOffset *offsetsLMULx8; // LMULx8 stride offsets } riscv; @@ -317,23 +354,35 @@ inline static Bool basicICPresent(riscvP riscv) { } // -// Should CLIC be used for M-mode interrupts?? +// Should CLIC be used for M-mode interrupts? // inline static Bool useCLICM(riscvP riscv) { return RD_CSR_FIELD(riscv, mtvec, MODE)==riscv_int_CLIC; } // -// Should CLIC be used for S-mode interrupts?? +// Should CLIC be used for S-mode interrupts? // inline static Bool useCLICS(riscvP riscv) { return RD_CSR_FIELD(riscv, stvec, MODE)==riscv_int_CLIC; } // -// Should CLIC be used for U-mode interrupts?? +// Should CLIC be used for U-mode interrupts? // inline static Bool useCLICU(riscvP riscv) { return RD_CSR_FIELD(riscv, utvec, MODE)==riscv_int_CLIC; } +// +// Return current vector signed vlmul +// +inline static Int32 getSVLMUL(riscvP riscv) { + + Uns32 vlmul = RD_CSR_FIELD(riscv, vtype, vlmul); + Bool vlmulf = RD_CSR_FIELD(riscv, vtype, vlmulf); + + return getSignedVLMUL(vlmul, vlmulf); +} + + diff --git a/source/riscvTypeRefs.h b/source/riscvTypeRefs.h index b1ba631..3ecbdf7 100644 --- a/source/riscvTypeRefs.h +++ b/source/riscvTypeRefs.h @@ -25,6 +25,8 @@ DEFINE_S (riscv); DEFINE_S (riscvBlockState); DEFINE_S (riscvBusPort); +DEFINE_U (riscvCLICIntState); +DEFINE_S (riscvCLICOutState); DEFINE_S (riscvConfig); DEFINE_CS(riscvConfig); DEFINE_CS(riscvCSRAttrs); @@ -37,5 +39,6 @@ DEFINE_S (riscvNetPort); DEFINE_CS(riscvMorphAttr); DEFINE_S (riscvMorphState); DEFINE_S (riscvParamValues); +DEFINE_S (riscvPendEnab); DEFINE_S (riscvTLB); diff --git a/source/riscvTypes.h b/source/riscvTypes.h index 2eb7f4e..5c44ab8 100644 --- a/source/riscvTypes.h +++ b/source/riscvTypes.h @@ -44,3 +44,26 @@ typedef enum riscvRMDescE { } riscvRMDesc; +// +// This holds field information for the VSETVLI instruction +// +typedef union riscvVTypeU { + Uns32 u32; + struct { + Uns32 vlmul : 2; + Uns32 vsew : 3; + Uns32 vlmulf : 1; + Uns32 vta : 1; + Uns32 vma : 1; + Uns32 _u1 : 24; + }; +} riscvVType; + +// +// Form signed vlmul from unsigned base and fractional indication +// +inline static Int32 getSignedVLMUL(Uns32 vlmul, Bool vlmulf) { + return vlmul | (vlmulf ? -4 : 0); +} + + diff --git a/source/riscvUtils.c b/source/riscvUtils.c index 757c1f3..9b0d1d5 100644 --- a/source/riscvUtils.c +++ b/source/riscvUtils.c @@ -596,6 +596,7 @@ const char *riscvGetFeatureName(riscvArchitecture feature) { [RISCV_FEATURE_INDEX(XLEN32_CHAR)] = "32-bit XLEN", [RISCV_FEATURE_INDEX(XLEN64_CHAR)] = "64-bit XLEN", [RISCV_FEATURE_INDEX('A')] = "extension A (atomic instructions)", + [RISCV_FEATURE_INDEX('B')] = "extension B (Tentatively reserved for Bit-Manipulation extension)", [RISCV_FEATURE_INDEX('C')] = "extension C (compressed instructions)", [RISCV_FEATURE_INDEX('E')] = "RV32E base ISA", [RISCV_FEATURE_INDEX('D')] = "extension D (double-precision floating point)", @@ -664,8 +665,10 @@ static VMI_MEM_WATCH_FN(abortEA) { static void updateExclusiveAccessCallback(riscvP riscv, Bool install) { memDomainP domain = vmirtGetProcessorDataDomain((vmiProcessorP)riscv); - Uns64 simLow = riscv->exclusiveTag; - Uns64 simHigh = simLow + ~riscv->exclusiveTagMask; + Uns32 bits = vmirtGetDomainAddressBits(domain); + Uns64 mask = (bits==64) ? -1 : ((1ULL<exclusiveTag; + Uns64 simHigh = mask & (simLow + ~riscv->exclusiveTagMask); // install or remove a watchpoint on the current exclusive access address if(install) { diff --git a/source/riscvVM.c b/source/riscvVM.c index c2c0ed0..bc09d6e 100644 --- a/source/riscvVM.c +++ b/source/riscvVM.c @@ -1680,6 +1680,37 @@ static void createVirtualDomain( ); } +// +// Create new CLIC domain at cluster root level +// +static memDomainP createCLICDomain(riscvP riscv, memDomainP dataDomain) { + + riscvP root = riscv->smpRoot; + + // CLIC memory map is shared by all harts in a cluster + if(!root->CLICDomain) { + + Uns32 bits = vmirtGetDomainAddressBits(dataDomain); + Uns64 mask = getAddressMask(bits); + + // create domain of width bits + memDomainP CLICDomain = createDomain( + RISCV_MODE_MACHINE, "CLIC", bits, False, False + ); + + // create mapping to data domain + vmirtAliasMemory(dataDomain, CLICDomain, 0, mask, 0, 0); + + // create CLIC memory-mapped block + riscvMapCLICDomain(root, CLICDomain); + + // save CLIC domain on cluster root + root->CLICDomain = CLICDomain; + } + + return root->CLICDomain; +} + // // Dump the contents of the TLBs // @@ -1711,6 +1742,12 @@ VMI_VMINIT_FN(riscvVMInit) { // save size of physical domain riscv->extBits = (codeBitscurrentArch & ISA_XLEN_64) +// macro returning XLEN in bytes +#define RISCV_XLEN_BYTES(_CPU) (RISCV_XLEN_IS_32(_CPU) ? 4 : 8) + // // Supported User Architecture versions // @@ -165,8 +168,8 @@ typedef enum riscvPrivVerE { // // date and tag of master version // -#define RVVV_MASTER_DATE "4 Match 2020" -#define RVVV_MASTER_TAG "45da90d" +#define RVVV_MASTER_DATE "15 May 2020" +#define RVVV_MASTER_TAG "72a8e0c" // // Supported Vector Architecture versions @@ -179,9 +182,10 @@ typedef enum riscvVectVerE { RVVV_0_8_20191117, // version 0.8-draft-20191117 RVVV_0_8_20191118, // version 0.8-draft-20191118 RVVV_0_8, // version 0.8 + RVVV_0_9, // version 0.9 RVVV_MASTER, // master branch RVVV_LAST, // for sizing - RVVV_DEFAULT = RVVV_0_8, // default version + RVVV_DEFAULT = RVVV_0_9, // default version } riscvVectVer; // @@ -216,6 +220,7 @@ typedef enum riscvIntCfgE { // typedef enum riscvDMModeE { RVDM_NONE, // Debug mode not implemented + RVDM_VECTOR, // Debug mode causes execution at vector RVDM_INTERRUPT, // Debug mode implemented as interrupt RVDM_HALT, // Debug mode implemented as halt } riscvDMMode; @@ -255,7 +260,9 @@ typedef enum riscvVFeatureE { RVVF_VS_STATUS_8, // is [ms]status.VS field in version 0.8 location? RVVF_VS_STATUS_9, // is [ms]status.VS field in version 0.9 location? RVVF_FP_RESTRICT_WHOLE, // whole register load/store/move restricted? - RVVF_SEG_ONLY_SEW, // are segment loads/stores restricted to SEW? + RVVF_FRACT_LMUL, // is fractional LMUL implemented? + RVVF_AGNOSTIC, // are agnostic bits implemented? + RVVF_MLEN1, // is MLEN always 1? RVVF_LAST, // for sizing } riscvVFeature; diff --git a/source/riscvVectorTypes.h b/source/riscvVectorTypes.h index 1ebdc84..b7122d2 100644 --- a/source/riscvVectorTypes.h +++ b/source/riscvVectorTypes.h @@ -27,60 +27,69 @@ // -// Vector width control +// Vector shape description. Each name is composed of: +// - prefix (RVVW) +// - two or three operand descriptors, each three letters: +// 1. argument type (V=vector, S=scalar, P=predicate); +// 2. VLMUL multiplier (1, 2 or 4); +// 3. element type (I=integer, F=float) +// - an optional generic suffix // typedef enum riscvVShapeE { - // INTEGER ARGUMENTS - RVVW_111_II, // SEW - RVVW_111_IIXSM, // SEW, no overlap if segmented - RVVW_111_IIS, // SEW, saturating result - RVVW_111_IIX, // SEW, uses vxrm - RVVW_BBB_II, // SEW8 - RVVW_111_IS, // SEW, src1 is scalar - RVVW_111_SI, // SEW, Vd is scalar - RVVW_111_PI, // SEW, Vd is predicate - RVVW_111_SIS, // SEW, Vd and src2 are scalar - RVVW_CIN_II, // SEW, mask is carry-in (VADC etc) - RVVW_CIN_PI, // SEW, Vd is predicate, mask is carry-in (VMADC etc) - RVVW_212_SIS, // 2*SEW = SEW op 2*SEW, Vd and src2 are scalar - RVVW_121_II, // SEW = 2*SEW op SEW - RVVW_121_IIS, // SEW = 2*SEW op SEW, saturating result - RVVW_211_IIQ, // 2*SEW = SEW op SEW, implicit widening - RVVW_211_II, // 2*SEW = SEW op SEW - RVVW_211_IIS, // 2*SEW = SEW op SEW, saturating result - RVVW_411_II, // 4*SEW = SEW op SEW - RVVW_221_II, // 2*SEW = 2*SEW op SEW + // INTEGER ARGUMENTS + RVVW_V1I_V1I_V1I, // SEW = SEW op SEW + RVVW_V1I_V1I_V1I_XSM, // no overlap if segmented + RVVW_V1I_V1I_V1I_SAT, // saturating result + RVVW_V1I_V1I_V1I_VXRM, // uses vxrm + RVVW_V1I_V1I_V1I_SEW8, // uses SEW8 + RVVW_V1I_S1I_V1I, // src1 is scalar + RVVW_S1I_V1I_V1I, // Vd is scalar + RVVW_P1I_V1I_V1I, // Vd is predicate + RVVW_S1I_V1I_S1I, // Vd and src2 are scalar + RVVW_V1I_V1I_V1I_CIN, // mask is carry-in (VADC etc) + RVVW_P1I_V1I_V1I_CIN, // Vd is predicate, mask is carry-in (VMADC etc) + RVVW_S2I_V1I_S2I, // 2*SEW = SEW op 2*SEW, Vd and src2 are scalar + RVVW_V1I_V2I_V1I, // SEW = 2*SEW op SEW + RVVW_V1I_V2I_V1I_SAT, // SEW = 2*SEW op SEW, saturating result + RVVW_V2I_V1I_V1I_IW, // 2*SEW = SEW op SEW, implicit widening + RVVW_V2I_V1I_V1I, // 2*SEW = SEW op SEW + RVVW_V2I_V1I_V1I_SAT, // 2*SEW = SEW op SEW, saturating result + RVVW_V4I_V1I_V1I, // 4*SEW = SEW op SEW + RVVW_V2I_V2I_V1I, // 2*SEW = 2*SEW op SEW + RVVW_V1I_V2I_FN, // SEW = SEW/FN - // FLOATING POINT ARGUMENTS - RVVW_111_FF, // SEW - RVVW_111_PF, // SEW, Vd is predicate - RVVW_111_SFS, // SEW, Vd and src2 are scalar - RVVW_212_SFS, // 2*SEW = SEW op 2*SEW, Vd and src2 are scalar - RVVW_121_FFQ, // SEW = 2*SEW op SEW, implicit widening - RVVW_211_FFQ, // 2*SEW = SEW op SEW, implicit widening - RVVW_211_FF, // 2*SEW = SEW op SEW - RVVW_221_FF, // 2*SEW = 2*SEW op SEW + // FLOATING POINT ARGUMENTS + RVVW_V1F_V1F_V1F, // SEW = SEW op SEW + RVVW_V1F_S1F_V1F, // src1 is scalar + RVVW_S1F_V1I_V1I, // Vd is scalar + RVVW_P1I_V1F_V1F, // Vd is predicate + RVVW_S1F_V1F_S1F, // Vd and src2 are scalar + RVVW_S2F_V1F_S2F, // 2*SEW = SEW op 2*SEW, Vd and src2 are scalar + RVVW_V1F_V2F_V1F_IW, // SEW = 2*SEW op SEW, implicit widening + RVVW_V2F_V1F_V1F_IW, // 2*SEW = SEW op SEW, implicit widening + RVVW_V2F_V1F_V1F, // 2*SEW = SEW op SEW + RVVW_V2F_V2F_V1F, // 2*SEW = 2*SEW op SEW - // MIXED ARGUMENTS - RVVW_111_FI, // SEW, Fd=Is - RVVW_111_IF, // SEW, Id=Fs - RVVW_21_FIQ, // 2*SEW = SEW, Fd=Is - RVVW_21_IFQ, // 2*SEW = SEW, Id=Fs - RVVW_12_FIQ, // SEW = 2*SEW, implicit widening - RVVW_12_IFQ, // SEW = 2*SEW, implicit widening + // CONVERSIONS + RVVW_V1F_V1I, // SEW = SEW, Fd=Is + RVVW_V1I_V1F, // SEW = SEW, Id=Fs + RVVW_V2F_V1I, // 2*SEW = SEW, Fd=Is + RVVW_V2I_V1F, // 2*SEW = SEW, Id=Fs + RVVW_V1F_V2I_IW, // SEW = 2*SEW, Fd=Is, implicit widening + RVVW_V1I_V2F_IW, // SEW = 2*SEW, Id=Fs, implicit widening - // MASK ARGUMENTS - RVVW_111_PP, // SEW - RVVW_111_IP, // SEW + // MASK ARGUMENTS + RVVW_P1I_P1I_P1I, // SEW = SEW op SEW + RVVW_V1I_P1I_P1I, // SEW = SEW op SEW - // SLIDING ARGUMENTS - RVVW_111_GR, // SEW, VRGATHER instructions - RVVW_111_UP, // SEW, VSLIDEUP instructions - RVVW_111_DN, // SEW, VSLIDEDOWN instructions - RVVW_111_CMP, // SEW, VCOMPRESS instruction + // SLIDING ARGUMENTS + RVVW_V1I_V1I_V1I_GR, // SEW, VRGATHER instructions + RVVW_V1I_V1I_V1I_UP, // SEW, VSLIDEUP instructions + RVVW_V1I_V1I_V1I_DN, // SEW, VSLIDEDOWN instructions + RVVW_V1I_V1I_V1I_CMP, // SEW, VCOMPRESS instruction - RVVW_LAST // KEEP LAST: for sizing + RVVW_LAST // KEEP LAST: for sizing } riscvVShape;