Line 5... |
Line 5... |
* @brief RISC-V extension-M.
|
* @brief RISC-V extension-M.
|
*/
|
*/
|
|
|
#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 {
|
|
|
/**
|
/**
|
* @brief The DIV signed division
|
* @brief The DIV signed division
|
*/
|
*/
|
class DIV : public IsaProcessor {
|
class DIV : public RiscvInstruction {
|
public:
|
public:
|
DIV() : IsaProcessor("DIV", "0000001??????????100?????0110011") {}
|
DIV(CpuRiver_Functional *icpu)
|
|
: RiscvInstruction(icpu, "DIV", "0000001??????????100?????0110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_R_type u;
|
ISA_R_type u;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
if (data->regs[u.bits.rs2]) {
|
if (R[u.bits.rs2]) {
|
data->regs[u.bits.rd] = static_cast<int64_t>(data->regs[u.bits.rs1])
|
R[u.bits.rd] = static_cast<int64_t>(R[u.bits.rs1])
|
/ static_cast<int64_t>(data->regs[u.bits.rs2]);
|
/ static_cast<int64_t>(R[u.bits.rs2]);
|
} else {
|
} else {
|
data->regs[u.bits.rd] = 0;
|
R[u.bits.rd] = 0;
|
}
|
}
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief DIVU unsigned division
|
* @brief DIVU unsigned division
|
*/
|
*/
|
class DIVU : public IsaProcessor {
|
class DIVU : public RiscvInstruction {
|
public:
|
public:
|
DIVU() : IsaProcessor("DIVU", "0000001??????????101?????0110011") {}
|
DIVU(CpuRiver_Functional *icpu)
|
|
: RiscvInstruction(icpu, "DIVU", "0000001??????????101?????0110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_R_type u;
|
ISA_R_type u;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
if (data->regs[u.bits.rs2]) {
|
if (R[u.bits.rs2]) {
|
data->regs[u.bits.rd] =
|
R[u.bits.rd] = R[u.bits.rs1] / R[u.bits.rs2];
|
data->regs[u.bits.rs1] / data->regs[u.bits.rs2];
|
|
} else {
|
} else {
|
data->regs[u.bits.rd] = 0;
|
R[u.bits.rd] = 0;
|
}
|
}
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief DIVUW 32-bits unsigned division (RV64I)
|
* @brief DIVUW 32-bits unsigned division (RV64I)
|
*/
|
*/
|
class DIVUW : public IsaProcessor {
|
class DIVUW : public RiscvInstruction {
|
public:
|
public:
|
DIVUW() : IsaProcessor("DIVUW", "0000001??????????101?????0111011") {}
|
DIVUW(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "DIVUW", "0000001??????????101?????0111011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_R_type u;
|
ISA_R_type u;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
if (static_cast<uint32_t>(data->regs[u.bits.rs2])) {
|
if (static_cast<uint32_t>(R[u.bits.rs2])) {
|
data->regs[u.bits.rd] =
|
R[u.bits.rd] =
|
static_cast<uint32_t>(data->regs[u.bits.rs1]) /
|
static_cast<uint32_t>(R[u.bits.rs1]) /
|
static_cast<uint32_t>(data->regs[u.bits.rs2]);
|
static_cast<uint32_t>(R[u.bits.rs2]);
|
} else {
|
} else {
|
data->regs[u.bits.rd] = 0;
|
R[u.bits.rd] = 0;
|
}
|
}
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief DIVW 32-bits signed division (RV64I)
|
* @brief DIVW 32-bits signed division (RV64I)
|
*/
|
*/
|
class DIVW : public IsaProcessor {
|
class DIVW : public RiscvInstruction {
|
public:
|
public:
|
DIVW() : IsaProcessor("DIVW", "0000001??????????100?????0111011") {}
|
DIVW(CpuRiver_Functional *icpu)
|
|
: RiscvInstruction(icpu, "DIVW", "0000001??????????100?????0111011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_R_type u;
|
ISA_R_type u;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
int32_t divident = static_cast<int32_t>(data->regs[u.bits.rs1]);
|
int32_t divident = static_cast<int32_t>(R[u.bits.rs1]);
|
int32_t divisor = static_cast<int32_t>(data->regs[u.bits.rs2]);
|
int32_t divisor = static_cast<int32_t>(R[u.bits.rs2]);
|
if (divisor) {
|
if (divisor) {
|
data->regs[u.bits.rd] = static_cast<int64_t>(divident / divisor);
|
R[u.bits.rd] = static_cast<int64_t>(divident / divisor);
|
} else {
|
} else {
|
data->regs[u.bits.rd] = 0;
|
R[u.bits.rd] = 0;
|
}
|
}
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief The MUL signed multiplication
|
* @brief The MUL signed multiplication
|
*
|
*
|
* MUL performs an XLEN-bit XLEN-bit multiplication and places the lower XLEN
|
* MUL performs an XLEN-bit XLEN-bit multiplication and places the lower XLEN
|
* bits in the destination register.
|
* bits in the destination register.
|
*/
|
*/
|
class MUL : public IsaProcessor {
|
class MUL : public RiscvInstruction {
|
public:
|
public:
|
MUL() : IsaProcessor("MUL", "0000001??????????000?????0110011") {}
|
MUL(CpuRiver_Functional *icpu)
|
|
: RiscvInstruction(icpu, "MUL", "0000001??????????000?????0110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_R_type u;
|
ISA_R_type u;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
data->regs[u.bits.rd] = static_cast<int64_t>(data->regs[u.bits.rs1])
|
R[u.bits.rd] = static_cast<int64_t>(R[u.bits.rs1])
|
* static_cast<int64_t>(data->regs[u.bits.rs2]);
|
* static_cast<int64_t>(R[u.bits.rs2]);
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief The MULW 32-bits signed multiplication (RV64I)
|
* @brief The MULW 32-bits signed multiplication (RV64I)
|
Line 119... |
Line 123... |
* registers, placing the sign-extension of the lower 32 bits of the result
|
* registers, placing the sign-extension of the lower 32 bits of the result
|
* into the destination register. MUL can be used to obtain the upper 32 bits
|
* into the destination register. MUL can be used to obtain the upper 32 bits
|
* of the 64-bit product, but signed arguments must be proper 32-bit signed
|
* of the 64-bit product, but signed arguments must be proper 32-bit signed
|
* values, whereas unsigned arguments must have their upper 32 bits clear.
|
* values, whereas unsigned arguments must have their upper 32 bits clear.
|
*/
|
*/
|
class MULW : public IsaProcessor {
|
class MULW : public RiscvInstruction {
|
public:
|
public:
|
MULW() : IsaProcessor("MULW", "0000001??????????000?????0111011") {}
|
MULW(CpuRiver_Functional *icpu)
|
|
: RiscvInstruction(icpu, "MULW", "0000001??????????000?????0111011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_R_type u;
|
ISA_R_type u;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
int32_t m1 = static_cast<int32_t>(data->regs[u.bits.rs1]);
|
int32_t m1 = static_cast<int32_t>(R[u.bits.rs1]);
|
int32_t m2 = static_cast<int32_t>(data->regs[u.bits.rs2]);
|
int32_t m2 = static_cast<int32_t>(R[u.bits.rs2]);
|
|
|
data->regs[u.bits.rd] = static_cast<int64_t>(m1 * m2);
|
R[u.bits.rd] = static_cast<int64_t>(m1 * m2);
|
if (data->regs[u.bits.rd] & (1LL << 31)) {
|
if (R[u.bits.rd] & (1LL << 31)) {
|
data->regs[u.bits.rd] |= EXT_SIGN_32;
|
R[u.bits.rd] |= EXT_SIGN_32;
|
}
|
}
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief The REM (remainder of the corresponding signed division operation)
|
* @brief The REM (remainder of the corresponding signed division operation)
|
*/
|
*/
|
class REM : public IsaProcessor {
|
class REM : public RiscvInstruction {
|
public:
|
public:
|
REM() : IsaProcessor("REM", "0000001??????????110?????0110011") {}
|
REM(CpuRiver_Functional *icpu)
|
|
: RiscvInstruction(icpu, "REM", "0000001??????????110?????0110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_R_type u;
|
ISA_R_type u;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
data->regs[u.bits.rd] = static_cast<int64_t>(data->regs[u.bits.rs1])
|
R[u.bits.rd] = static_cast<int64_t>(R[u.bits.rs1])
|
% static_cast<int64_t>(data->regs[u.bits.rs2]);
|
% static_cast<int64_t>(R[u.bits.rs2]);
|
data->npc = data->pc + 4;
|
return 4;
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief The REMU (remainder of the corresponding unsgined division operation)
|
* @brief The REMU (remainder of the corresponding unsgined division operation)
|
*/
|
*/
|
class REMU : public IsaProcessor {
|
class REMU : public RiscvInstruction {
|
public:
|
public:
|
REMU() : IsaProcessor("REMU", "0000001??????????111?????0110011") {}
|
REMU(CpuRiver_Functional *icpu)
|
|
: RiscvInstruction(icpu, "REMU", "0000001??????????111?????0110011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_R_type u;
|
ISA_R_type u;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
data->regs[u.bits.rd] =
|
R[u.bits.rd] = R[u.bits.rs1] % R[u.bits.rs2];
|
data->regs[u.bits.rs1] % data->regs[u.bits.rs2];
|
return 4;
|
data->npc = data->pc + 4;
|
|
}
|
}
|
};
|
};
|
|
|
/**
|
/**
|
* @brief REMW signed reminder operation
|
* @brief REMW signed reminder operation
|
Line 177... |
Line 183... |
* REMW and REMUW instructions are only valid
|
* REMW and REMUW instructions are only valid
|
* for RV64, and provide the corresponding signed and unsigned remainder
|
* for RV64, and provide the corresponding signed and unsigned remainder
|
* operations respectively.
|
* operations respectively.
|
* Both REMW and REMUW sign-extend the 32-bit result to 64 bits.
|
* Both REMW and REMUW sign-extend the 32-bit result to 64 bits.
|
*/
|
*/
|
class REMW : public IsaProcessor {
|
class REMW : public RiscvInstruction {
|
public:
|
public:
|
REMW() : IsaProcessor("REMW", "0000001??????????110?????0111011") {}
|
REMW(CpuRiver_Functional *icpu)
|
|
: RiscvInstruction(icpu, "REMW", "0000001??????????110?????0111011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_R_type u;
|
ISA_R_type u;
|
int32_t tmp;
|
int32_t tmp;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
tmp = static_cast<int32_t>(data->regs[u.bits.rs1])
|
tmp = static_cast<int32_t>(R[u.bits.rs1])
|
% static_cast<int32_t>(data->regs[u.bits.rs2]);
|
% static_cast<int32_t>(R[u.bits.rs2]);
|
data->regs[u.bits.rd] =
|
R[u.bits.rd] = static_cast<uint64_t>(static_cast<int64_t>(tmp));
|
static_cast<uint64_t>(static_cast<int64_t>(tmp));
|
return 4;
|
data->npc = data->pc + 4;
|
|
}
|
}
|
};
|
};
|
|
|
class REMUW : public IsaProcessor {
|
class REMUW : public RiscvInstruction {
|
public:
|
public:
|
REMUW() : IsaProcessor("REMUW", "0000001??????????111?????0111011") {}
|
REMUW(CpuRiver_Functional *icpu) :
|
|
RiscvInstruction(icpu, "REMUW", "0000001??????????111?????0111011") {}
|
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
virtual int exec(Reg64Type *payload) {
|
ISA_R_type u;
|
ISA_R_type u;
|
uint32_t tmp;
|
uint32_t tmp;
|
u.value = payload[0];
|
u.value = payload->buf32[0];
|
tmp = static_cast<uint32_t>(data->regs[u.bits.rs1])
|
tmp = static_cast<uint32_t>(R[u.bits.rs1])
|
% static_cast<uint32_t>(data->regs[u.bits.rs2]);
|
% static_cast<uint32_t>(R[u.bits.rs2]);
|
data->regs[u.bits.rd] =
|
R[u.bits.rd] = static_cast<uint64_t>(static_cast<int64_t>(tmp));
|
static_cast<uint64_t>(static_cast<int64_t>(tmp));
|
return 4;
|
data->npc = data->pc + 4;
|
|
}
|
}
|
};
|
};
|
|
|
void addIsaExtensionM(CpuContextType *data, AttributeType *out) {
|
void CpuRiver_Functional::addIsaExtensionM() {
|
addSupportedInstruction(new DIV, out);
|
addSupportedInstruction(new DIV(this));
|
addSupportedInstruction(new DIVU, out);
|
addSupportedInstruction(new DIVU(this));
|
addSupportedInstruction(new DIVUW, out);
|
addSupportedInstruction(new DIVUW(this));
|
addSupportedInstruction(new DIVW, out);
|
addSupportedInstruction(new DIVW(this));
|
addSupportedInstruction(new MUL, out);
|
addSupportedInstruction(new MUL(this));
|
addSupportedInstruction(new MULW, out);
|
addSupportedInstruction(new MULW(this));
|
addSupportedInstruction(new REM, out);
|
addSupportedInstruction(new REM(this));
|
addSupportedInstruction(new REMU, out);
|
addSupportedInstruction(new REMU(this));
|
addSupportedInstruction(new REMW, out);
|
addSupportedInstruction(new REMW(this));
|
addSupportedInstruction(new REMUW, out);
|
addSupportedInstruction(new REMUW(this));
|
|
|
// TODO
|
// TODO
|
/*
|
/*
|
addInstr("MULH", "0000001??????????001?????0110011", NULL, out);
|
addInstr("MULH", "0000001??????????001?????0110011", NULL, out);
|
addInstr("MULHSU", "0000001??????????010?????0110011", NULL, out);
|
addInstr("MULHSU", "0000001??????????010?????0110011", NULL, out);
|
addInstr("MULHU", "0000001??????????011?????0110011", NULL, out);
|
addInstr("MULHU", "0000001??????????011?????0110011", NULL, out);
|
*/
|
*/
|
data->csr[CSR_misa] |= (1LL << ('M' - 'A'));
|
|
|
uint64_t isa = portCSR_.read(CSR_misa).val;
|
|
portCSR_.write(CSR_misa, isa | (1LL << ('M' - 'A')));
|
}
|
}
|
|
|
} // namespace debugger
|
} // namespace debugger
|
|
|
No newline at end of file
|
No newline at end of file
|