Line 5... |
Line 5... |
* @brief Base ISA implementation (extension I, privileged level).
|
* @brief Base ISA implementation (extension I, privileged level).
|
*/
|
*/
|
|
|
#include "api_utils.h"
|
#include "api_utils.h"
|
#include "riscv-isa.h"
|
#include "riscv-isa.h"
|
#include "instructions.h"
|
#include "cpu_riscv_func.h"
|
|
|
namespace debugger {
|
namespace debugger {
|
|
|
void generateException(uint64_t code, CpuContextType *data);
|
|
void generateInterrupt(uint64_t code, CpuContextType *data);
|
|
|
|
uint64_t readCSR(uint32_t idx, CpuContextType *data) {
|
|
uint64_t ret = data->csr[idx];
|
|
switch (idx) {
|
|
case CSR_mtime:
|
|
ret = data->step_cnt;
|
|
break;
|
|
default:;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void writeCSR(uint32_t idx, uint64_t val, CpuContextType *data) {
|
|
switch (idx) {
|
|
// Read-Only registers
|
|
case CSR_misa:
|
|
case CSR_mvendorid:
|
|
case CSR_marchid:
|
|
case CSR_mimplementationid:
|
|
case CSR_mhartid:
|
|
break;
|
|
case CSR_mtime:
|
|
break;
|
|
default:
|
|
data->csr[idx] = val;
|
|
}
|
|
}
|
|
|
|
/**
|
/**
|
* @brief The CSRRC (Atomic Read and Clear Bit in CSR).
|
* @brief The CSRRC (Atomic Read and Clear Bit in CSR).
|
*
|
*
|
* Instruction reads the value of the CSR, zeroextends the value to XLEN bits,
|
* Instruction reads the value of the CSR, zeroextends the value to XLEN bits,
|
* and writes it to integer register rd. The initial value in integer
|
* and writes it to integer register rd. The initial value in integer
|
* register rs1 specifies bit positions to be cleared in the CSR. Any bit that
|
* register rs1 specifies bit positions to be cleared in the CSR. Any bit that
|
* is high in rs1 will cause the corresponding bit to be cleared in the CSR,
|
* is high in rs1 will cause the corresponding bit to be cleared in the CSR,
|
* if that CSR bit is writable. Other bits in the CSR are unaffected.
|
* if that CSR bit is writable. Other bits in the CSR are unaffected.
|
*/
|
*/
|
class CSRRC : public IsaProcessor {
|
class CSRRC : public RiscvInstruction {
|
public:
|
public:
|
CSRRC() : IsaProcessor("CSRRC", "?????????????????011?????1110011") {}
|
CSRRC(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "CSRRC", "?????????????????011?????1110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_I_type u;
|
ISA_I_type u;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
|
|
uint64_t clr_mask = ~data->regs[u.bits.rs1];
|
uint64_t clr_mask = ~R[u.bits.rs1];
|
uint64_t csr = readCSR(u.bits.imm, data);
|
uint64_t csr = icpu_->readCSR(u.bits.imm);
|
if (u.bits.rd) {
|
if (u.bits.rd) {
|
data->regs[u.bits.rd] = csr;
|
R[u.bits.rd] = csr;
|
}
|
}
|
writeCSR(u.bits.imm, (csr & clr_mask), data);
|
icpu_->writeCSR(u.bits.imm, (csr & clr_mask));
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief The CSRRCI (Atomic Read and Clear Bit in CSR immediate).
|
* @brief The CSRRCI (Atomic Read and Clear Bit in CSR immediate).
|
*
|
*
|
* Similar to CSRRC except it updates the CSR using a 5-bit zero-extended
|
* Similar to CSRRC except it updates the CSR using a 5-bit zero-extended
|
* immediate (zimm[4:0]) encoded in the rs1 field instead of a value from
|
* immediate (zimm[4:0]) encoded in the rs1 field instead of a value from
|
* an integer register.
|
* an integer register.
|
*/
|
*/
|
class CSRRCI : public IsaProcessor {
|
class CSRRCI : public RiscvInstruction {
|
public:
|
public:
|
CSRRCI() : IsaProcessor("CSRRCI", "?????????????????111?????1110011") {}
|
CSRRCI(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "CSRRCI", "?????????????????111?????1110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_I_type u;
|
ISA_I_type u;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
|
|
uint64_t clr_mask = ~static_cast<uint64_t>((u.bits.rs1));
|
uint64_t clr_mask = ~static_cast<uint64_t>((u.bits.rs1));
|
uint64_t csr = readCSR(u.bits.imm, data);
|
uint64_t csr = icpu_->readCSR(u.bits.imm);
|
if (u.bits.rd) {
|
if (u.bits.rd) {
|
data->regs[u.bits.rd] = csr;
|
R[u.bits.rd] = csr;
|
}
|
}
|
writeCSR(u.bits.imm, (csr & clr_mask), data);
|
icpu_->writeCSR(u.bits.imm, (csr & clr_mask));
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief The CSRRS (Atomic Read and Set Bit in CSR).
|
* @brief The CSRRS (Atomic Read and Set Bit in CSR).
|
Line 102... |
Line 74... |
* high in rs1 will cause the corresponding bit to be set in the CSR, if that
|
* high in rs1 will cause the corresponding bit to be set in the CSR, if that
|
* CSR bit is writable. Other bits in the CSR are unaffected (though CSRs
|
* CSR bit is writable. Other bits in the CSR are unaffected (though CSRs
|
* might have side effects when written).
|
* might have side effects when written).
|
* The CSRR pseudo instruction (read CSR), when rs1 = 0.
|
* The CSRR pseudo instruction (read CSR), when rs1 = 0.
|
*/
|
*/
|
class CSRRS : public IsaProcessor {
|
class CSRRS : public RiscvInstruction {
|
public:
|
public:
|
CSRRS() : IsaProcessor("CSRRS", "?????????????????010?????1110011") {}
|
CSRRS(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "CSRRS", "?????????????????010?????1110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_I_type u;
|
ISA_I_type u;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
|
|
uint64_t set_mask = data->regs[u.bits.rs1];
|
uint64_t set_mask = R[u.bits.rs1];
|
uint64_t csr = readCSR(u.bits.imm, data);
|
uint64_t csr = icpu_->readCSR(u.bits.imm);
|
if (u.bits.rd) {
|
if (u.bits.rd) {
|
data->regs[u.bits.rd] = csr;
|
R[u.bits.rd] = csr;
|
}
|
}
|
writeCSR(u.bits.imm, (csr | set_mask), data);
|
icpu_->writeCSR(u.bits.imm, (csr | set_mask));
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief The CSRRSI (Atomic Read and Set Bit in CSR immediate).
|
* @brief The CSRRSI (Atomic Read and Set Bit in CSR immediate).
|
*
|
*
|
* Similar to CSRRS except it updates the CSR using a 5-bit zero-extended
|
* Similar to CSRRS except it updates the CSR using a 5-bit zero-extended
|
* immediate (zimm[4:0]) encoded in the rs1 field instead of a value from
|
* immediate (zimm[4:0]) encoded in the rs1 field instead of a value from
|
* an integer register.
|
* an integer register.
|
*/
|
*/
|
class CSRRSI : public IsaProcessor {
|
class CSRRSI : public RiscvInstruction {
|
public:
|
public:
|
CSRRSI() : IsaProcessor("CSRRSI", "?????????????????110?????1110011") {}
|
CSRRSI(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "CSRRSI", "?????????????????110?????1110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_I_type u;
|
ISA_I_type u;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
|
|
uint64_t set_mask = u.bits.rs1;
|
uint64_t set_mask = u.bits.rs1;
|
uint64_t csr = readCSR(u.bits.imm, data);
|
uint64_t csr = icpu_->readCSR(u.bits.imm);
|
if (u.bits.rd) {
|
if (u.bits.rd) {
|
data->regs[u.bits.rd] = csr;
|
R[u.bits.rd] = csr;
|
}
|
}
|
writeCSR(u.bits.imm, (csr | set_mask), data);
|
icpu_->writeCSR(u.bits.imm, (csr | set_mask));
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief The CSRRW (Atomic Read/Write CSR).
|
* @brief The CSRRW (Atomic Read/Write CSR).
|
Line 154... |
Line 128... |
* CSRRW reads the old value of the CSR, zero-extends the value to XLEN bits,
|
* CSRRW reads the old value of the CSR, zero-extends the value to XLEN bits,
|
* then writes it to integer register rd. The initial value in rs1 is written
|
* then writes it to integer register rd. The initial value in rs1 is written
|
* to the CSR.
|
* to the CSR.
|
* The CSRW pseudo instruction (write CSR), when rs1 = 0.
|
* The CSRW pseudo instruction (write CSR), when rs1 = 0.
|
*/
|
*/
|
class CSRRW : public IsaProcessor {
|
class CSRRW : public RiscvInstruction {
|
public:
|
public:
|
CSRRW() : IsaProcessor("CSRRW", "?????????????????001?????1110011") {}
|
CSRRW(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "CSRRW", "?????????????????001?????1110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_I_type u;
|
ISA_I_type u;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
|
|
uint64_t wr_value = data->regs[u.bits.rs1];
|
uint64_t wr_value = R[u.bits.rs1];
|
if (u.bits.rd) {
|
if (u.bits.rd) {
|
data->regs[u.bits.rd] = readCSR(u.bits.imm, data);
|
R[u.bits.rd] = icpu_->readCSR(u.bits.imm);
|
}
|
}
|
writeCSR(u.bits.imm, wr_value, data);
|
icpu_->writeCSR(u.bits.imm, wr_value);
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief The CSRRWI (Atomic Read/Write CSR immediate).
|
* @brief The CSRRWI (Atomic Read/Write CSR immediate).
|
*
|
*
|
* Similar to CSRRW except it updates the CSR using a 5-bit zero-extended
|
* Similar to CSRRW except it updates the CSR using a 5-bit zero-extended
|
* immediate (zimm[4:0]) encoded in the rs1 field instead of a value from
|
* immediate (zimm[4:0]) encoded in the rs1 field instead of a value from
|
* an integer register.
|
* an integer register.
|
*/
|
*/
|
class CSRRWI : public IsaProcessor {
|
class CSRRWI : public RiscvInstruction {
|
public:
|
public:
|
CSRRWI() : IsaProcessor("CSRRWI", "?????????????????101?????1110011") {}
|
CSRRWI(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "CSRRWI", "?????????????????101?????1110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_I_type u;
|
ISA_I_type u;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
|
|
uint64_t wr_value = u.bits.rs1;
|
uint64_t wr_value = u.bits.rs1;
|
if (u.bits.rd) {
|
if (u.bits.rd) {
|
data->regs[u.bits.rd] = readCSR(u.bits.imm, data);
|
R[u.bits.rd] = icpu_->readCSR(u.bits.imm);
|
}
|
}
|
writeCSR(u.bits.imm, wr_value, data);
|
icpu_->writeCSR(u.bits.imm, wr_value);
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief MRET, HRET, SRET, or URET
|
* @brief MRET, HRET, SRET, or URET
|
Line 209... |
Line 185... |
* User-level interrupts are an optional extension and have been allocated
|
* User-level interrupts are an optional extension and have been allocated
|
* the ISA extension letter N. If user-level interrupts are omitted, the UIE
|
* the ISA extension letter N. If user-level interrupts are omitted, the UIE
|
* and UPIE bits are hardwired to zero. For all other supported privilege
|
* and UPIE bits are hardwired to zero. For all other supported privilege
|
* modes x, the x IE, x PIE, and x PP fields are required to be implemented.
|
* modes x, the x IE, x PIE, and x PP fields are required to be implemented.
|
*/
|
*/
|
class URET : public IsaProcessor {
|
class URET : public RiscvInstruction {
|
public:
|
public:
|
URET() : IsaProcessor("URET", "00000000001000000000000001110011") {}
|
URET(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "URET", "00000000001000000000000001110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
if (data->cur_prv_level != PRV_U) {
|
if (icpu_->getPrvLevel() != PRV_U) {
|
generateException(EXCEPTION_InstrIllegal, data);
|
icpu_->raiseSignal(EXCEPTION_InstrIllegal);
|
return;
|
return 4;
|
}
|
}
|
csr_mstatus_type mstatus;
|
csr_mstatus_type mstatus;
|
mstatus.value = readCSR(CSR_mstatus, data);
|
mstatus.value = icpu_->readCSR(CSR_mstatus);
|
|
|
uint64_t xepc = (PRV_U << 8) + 0x41;
|
uint64_t xepc = (PRV_U << 8) + 0x41;
|
data->npc = readCSR(static_cast<uint32_t>(xepc), data);
|
icpu_->setBranch(icpu_->readCSR(static_cast<uint32_t>(xepc)));
|
|
|
bool is_N_extension = false;
|
bool is_N_extension = false;
|
if (is_N_extension) {
|
if (is_N_extension) {
|
mstatus.bits.UIE = mstatus.bits.UPIE;
|
mstatus.bits.UIE = mstatus.bits.UPIE;
|
mstatus.bits.UPIE = 1;
|
mstatus.bits.UPIE = 1;
|
// User mode not changed.
|
// User mode not changed.
|
} else {
|
} else {
|
mstatus.bits.UIE = 0;
|
mstatus.bits.UIE = 0;
|
mstatus.bits.UPIE = 0;
|
mstatus.bits.UPIE = 0;
|
}
|
}
|
data->cur_prv_level = PRV_U;
|
icpu_->setPrvLevel(PRV_U);
|
writeCSR(CSR_mstatus, mstatus.value, data);
|
icpu_->writeCSR(CSR_mstatus, mstatus.value);
|
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief SRET return from super-user mode
|
* @brief SRET return from super-user mode
|
*/
|
*/
|
class SRET : public IsaProcessor {
|
class SRET : public RiscvInstruction {
|
public:
|
public:
|
SRET() : IsaProcessor("SRET", "00010000001000000000000001110011") {}
|
SRET(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "SRET", "00010000001000000000000001110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
if (data->cur_prv_level != PRV_S) {
|
if (icpu_->getPrvLevel() != PRV_S) {
|
generateException(EXCEPTION_InstrIllegal, data);
|
icpu_->raiseSignal(EXCEPTION_InstrIllegal);
|
return;
|
return 4;
|
}
|
}
|
csr_mstatus_type mstatus;
|
csr_mstatus_type mstatus;
|
mstatus.value = readCSR(CSR_mstatus, data);
|
mstatus.value = icpu_->readCSR(CSR_mstatus);
|
|
|
uint64_t xepc = (PRV_S << 8) + 0x41;
|
uint64_t xepc = (PRV_S << 8) + 0x41;
|
data->npc = readCSR(static_cast<uint32_t>(xepc), data);
|
icpu_->setBranch(icpu_->readCSR(static_cast<uint32_t>(xepc)));
|
|
|
mstatus.bits.SIE = mstatus.bits.SPIE;
|
mstatus.bits.SIE = mstatus.bits.SPIE;
|
mstatus.bits.SPIE = 1;
|
mstatus.bits.SPIE = 1;
|
data->cur_prv_level = mstatus.bits.SPP;
|
icpu_->setPrvLevel(mstatus.bits.SPP);
|
mstatus.bits.SPP = PRV_U;
|
mstatus.bits.SPP = PRV_U;
|
|
|
writeCSR(CSR_mstatus, mstatus.value, data);
|
icpu_->writeCSR(CSR_mstatus, mstatus.value);
|
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief HRET return from hypervisor mode
|
* @brief HRET return from hypervisor mode
|
*/
|
*/
|
class HRET : public IsaProcessor {
|
class HRET : public RiscvInstruction {
|
public:
|
public:
|
HRET() : IsaProcessor("HRET", "00100000001000000000000001110011") {}
|
HRET(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "HRET", "00100000001000000000000001110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
if (data->cur_prv_level != PRV_H) {
|
if (icpu_->getPrvLevel() != PRV_H) {
|
generateException(EXCEPTION_InstrIllegal, data);
|
icpu_->raiseSignal(EXCEPTION_InstrIllegal);
|
return;
|
return 4;
|
}
|
}
|
csr_mstatus_type mstatus;
|
csr_mstatus_type mstatus;
|
mstatus.value = readCSR(CSR_mstatus, data);
|
mstatus.value = icpu_->readCSR(CSR_mstatus);
|
|
|
uint64_t xepc = (PRV_H << 8) + 0x41;
|
uint64_t xepc = (PRV_H << 8) + 0x41;
|
data->npc = readCSR(static_cast<uint32_t>(xepc), data);
|
icpu_->setBranch(icpu_->readCSR(static_cast<uint32_t>(xepc)));
|
|
|
mstatus.bits.HIE = mstatus.bits.HPIE;
|
mstatus.bits.HIE = mstatus.bits.HPIE;
|
mstatus.bits.HPIE = 1;
|
mstatus.bits.HPIE = 1;
|
data->cur_prv_level = mstatus.bits.HPP;
|
icpu_->setPrvLevel(mstatus.bits.HPP);
|
mstatus.bits.HPP = PRV_U;
|
mstatus.bits.HPP = PRV_U;
|
|
|
writeCSR(CSR_mstatus, mstatus.value, data);
|
icpu_->writeCSR(CSR_mstatus, mstatus.value);
|
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief MRET return from machine mode
|
* @brief MRET return from machine mode
|
*/
|
*/
|
class MRET : public IsaProcessor {
|
class MRET : public RiscvInstruction {
|
public:
|
public:
|
MRET() : IsaProcessor("MRET", "00110000001000000000000001110011") {}
|
MRET(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "MRET", "00110000001000000000000001110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
if (data->cur_prv_level != PRV_M) {
|
if (icpu_->getPrvLevel() != PRV_M) {
|
generateException(EXCEPTION_InstrIllegal, data);
|
icpu_->raiseSignal(EXCEPTION_InstrIllegal);
|
return;
|
return 4;
|
}
|
}
|
csr_mstatus_type mstatus;
|
csr_mstatus_type mstatus;
|
mstatus.value = readCSR(CSR_mstatus, data);
|
mstatus.value = icpu_->readCSR(CSR_mstatus);
|
|
|
uint64_t xepc = (PRV_M << 8) + 0x41;
|
uint64_t xepc = (PRV_M << 8) + 0x41;
|
data->npc = readCSR(static_cast<uint32_t>(xepc), data);
|
icpu_->setBranch(icpu_->readCSR(static_cast<uint32_t>(xepc)));
|
|
|
mstatus.bits.MIE = mstatus.bits.MPIE;
|
mstatus.bits.MIE = mstatus.bits.MPIE;
|
mstatus.bits.MPIE = 1;
|
mstatus.bits.MPIE = 1;
|
data->cur_prv_level = mstatus.bits.MPP;
|
icpu_->setPrvLevel(mstatus.bits.MPP);
|
mstatus.bits.MPP = PRV_U;
|
mstatus.bits.MPP = PRV_U;
|
|
|
// Emulating interrupt strob (not pulse from external controller)
|
icpu_->writeCSR(CSR_mstatus, mstatus.value);
|
if (data->interrupt_pending) {
|
return 4;
|
generateInterrupt(INTERRUPT_MExternal, data);
|
|
}
|
|
|
|
writeCSR(CSR_mstatus, mstatus.value, data);
|
|
}
|
}
|
};
|
};
|
|
|
|
|
/**
|
/**
|
* @brief FENCE (memory barrier)
|
* @brief FENCE (memory barrier)
|
*
|
*
|
* Not used in functional model so that cache is not modeling.
|
* Not used in functional model so that cache is not modeling.
|
*/
|
*/
|
class FENCE : public IsaProcessor {
|
class FENCE : public RiscvInstruction {
|
public:
|
public:
|
FENCE() : IsaProcessor("FENCE", "?????????????????000?????0001111") {}
|
FENCE(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "FENCE", "?????????????????000?????0001111") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief FENCE_I (memory barrier)
|
* @brief FENCE_I (memory barrier)
|
*
|
*
|
* Not used in functional model so that cache is not modeling.
|
* Not used in functional model so that cache is not modeling.
|
*/
|
*/
|
class FENCE_I : public IsaProcessor {
|
class FENCE_I : public RiscvInstruction {
|
public:
|
public:
|
FENCE_I() : IsaProcessor("FENCE_I", "?????????????????001?????0001111") {}
|
FENCE_I(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "FENCE_I", "?????????????????001?????0001111") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief EBREAK (breakpoint instruction)
|
* @brief EBREAK (breakpoint instruction)
|
*
|
*
|
* The EBREAK instruction is used by debuggers to cause control to be
|
* The EBREAK instruction is used by debuggers to cause control to be
|
* transferred back to a debug-ging environment.
|
* transferred back to a debug-ging environment.
|
*/
|
*/
|
class EBREAK : public IsaProcessor {
|
class EBREAK : public RiscvInstruction {
|
public:
|
public:
|
EBREAK() : IsaProcessor("EBREAK", "00000000000100000000000001110011") {}
|
EBREAK(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "EBREAK", "00000000000100000000000001110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
data->npc = data->pc + 4;
|
icpu_->raiseSignal(EXCEPTION_Breakpoint);
|
data->br_status_ena = true;
|
return 4;
|
generateException(EXCEPTION_Breakpoint, data);
|
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief ECALL (environment call instruction)
|
* @brief ECALL (environment call instruction)
|
Line 378... |
Line 359... |
* The ECALL instruction is used to make a request to the supporting execution
|
* The ECALL instruction is used to make a request to the supporting execution
|
* environment, which isusually an operating system. The ABI for the system
|
* environment, which isusually an operating system. The ABI for the system
|
* will define how parameters for the environment request are passed, but usually
|
* will define how parameters for the environment request are passed, but usually
|
* these will be in defined locations in the integer register file.
|
* these will be in defined locations in the integer register file.
|
*/
|
*/
|
class ECALL : public IsaProcessor {
|
class ECALL : public RiscvInstruction {
|
public:
|
public:
|
ECALL() : IsaProcessor("ECALL", "00000000000000000000000001110011") {}
|
ECALL(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "ECALL", "00000000000000000000000001110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
data->npc = data->pc + 4;
|
switch (icpu_->getPrvLevel()) {
|
switch (data->cur_prv_level) {
|
|
case PRV_M:
|
case PRV_M:
|
generateException(EXCEPTION_CallFromMmode, data);
|
icpu_->raiseSignal(EXCEPTION_CallFromMmode);
|
break;
|
break;
|
case PRV_U:
|
case PRV_U:
|
generateException(EXCEPTION_CallFromUmode, data);
|
icpu_->raiseSignal(EXCEPTION_CallFromUmode);
|
break;
|
break;
|
default:;
|
default:;
|
}
|
}
|
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
|
|
void addIsaPrivilegedRV64I(CpuContextType *data, AttributeType *out) {
|
void CpuRiver_Functional::addIsaPrivilegedRV64I() {
|
addSupportedInstruction(new CSRRC, out);
|
addSupportedInstruction(new CSRRC(this));
|
addSupportedInstruction(new CSRRCI, out);
|
addSupportedInstruction(new CSRRCI(this));
|
addSupportedInstruction(new CSRRS, out);
|
addSupportedInstruction(new CSRRS(this));
|
addSupportedInstruction(new CSRRSI, out);
|
addSupportedInstruction(new CSRRSI(this));
|
addSupportedInstruction(new CSRRW, out);
|
addSupportedInstruction(new CSRRW(this));
|
addSupportedInstruction(new CSRRWI, out);
|
addSupportedInstruction(new CSRRWI(this));
|
addSupportedInstruction(new URET, out);
|
addSupportedInstruction(new URET(this));
|
addSupportedInstruction(new SRET, out);
|
addSupportedInstruction(new SRET(this));
|
addSupportedInstruction(new HRET, out);
|
addSupportedInstruction(new HRET(this));
|
addSupportedInstruction(new MRET, out);
|
addSupportedInstruction(new MRET(this));
|
addSupportedInstruction(new FENCE, out);
|
addSupportedInstruction(new FENCE(this));
|
addSupportedInstruction(new FENCE_I, out);
|
addSupportedInstruction(new FENCE_I(this));
|
addSupportedInstruction(new ECALL, out);
|
addSupportedInstruction(new ECALL(this));
|
addSupportedInstruction(new EBREAK, out);
|
addSupportedInstruction(new EBREAK(this));
|
|
|
// TODO:
|
// TODO:
|
/*
|
/*
|
def DRET = BitPat("b01111011001000000000000001110011")
|
def DRET = BitPat("b01111011001000000000000001110011")
|
def SFENCE_VM = BitPat("b000100000100?????000000001110011")
|
def SFENCE_VMA = BitPat("b0001001??????????000000001110011")
|
def WFI = BitPat("b00010000010100000000000001110011") // wait for interrupt
|
def WFI = BitPat("b00010000010100000000000001110011") // wait for interrupt
|
|
|
def RDCYCLE = BitPat("b11000000000000000010?????1110011")
|
def RDCYCLE = BitPat("b11000000000000000010?????1110011")
|
def RDTIME = BitPat("b11000000000100000010?????1110011")
|
def RDTIME = BitPat("b11000000000100000010?????1110011")
|
def RDINSTRET = BitPat("b11000000001000000010?????1110011")
|
def RDINSTRET = BitPat("b11000000001000000010?????1110011")
|
def RDCYCLEH = BitPat("b11001000000000000010?????1110011")
|
def RDCYCLEH = BitPat("b11001000000000000010?????1110011")
|
def RDTIMEH = BitPat("b11001000000100000010?????1110011")
|
def RDTIMEH = BitPat("b11001000000100000010?????1110011")
|
def RDINSTRETH = BitPat("b11001000001000000010?????1110011")
|
def RDINSTRETH = BitPat("b11001000001000000010?????1110011")
|
def ECALL = BitPat("b00000000000000000000000001110011")
|
|
def EBREAK = BitPat("b00000000000100000000000001110011")
|
|
*/
|
*/
|
|
|
/**
|
/**
|
* The 'U', 'S', and 'H' bits will be set if there is support for
|
* The 'U', 'S', and 'H' bits will be set if there is support for
|
* user, supervisor, and hypervisor privilege modes respectively.
|
* user, supervisor, and hypervisor privilege modes respectively.
|
*/
|
*/
|
data->csr[CSR_misa] |= (1LL << ('U' - 'A'));
|
uint64_t isa = portCSR_.read(CSR_misa).val;
|
data->csr[CSR_misa] |= (1LL << ('S' - 'A'));
|
isa |= (1LL << ('U' - 'A'));
|
data->csr[CSR_misa] |= (1LL << ('H' - 'A'));
|
isa |= (1LL << ('S' - 'A'));
|
|
isa |= (1LL << ('H' - 'A'));
|
|
portCSR_.write(CSR_misa, isa);
|
}
|
}
|
|
|
} // namespace debugger
|
} // namespace debugger
|
|
|
No newline at end of file
|
No newline at end of file
|