implementation of all remaining C extension
This commit is contained in:
parent
e67e8b2c08
commit
ed7be704f9
|
@ -71,6 +71,14 @@ typedef enum {
|
||||||
C_LI = 0b010,
|
C_LI = 0b010,
|
||||||
C_ADDI16SP = 0b011,
|
C_ADDI16SP = 0b011,
|
||||||
C_SRLI = 0b100,
|
C_SRLI = 0b100,
|
||||||
|
C_2_SRLI = 0b00,
|
||||||
|
C_2_SRAI = 0b01,
|
||||||
|
C_2_ANDI = 0b10,
|
||||||
|
C_2_SUB = 0b11,
|
||||||
|
C_3_SUB = 0b00,
|
||||||
|
C_3_XOR = 0b01,
|
||||||
|
C_3_OR = 0b10,
|
||||||
|
C_3_AND = 0b11,
|
||||||
C_J = 0b101,
|
C_J = 0b101,
|
||||||
C_BEQZ = 0b110,
|
C_BEQZ = 0b110,
|
||||||
C_BNEZ = 0b111,
|
C_BNEZ = 0b111,
|
||||||
|
@ -118,7 +126,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int32_t get_rdp() {
|
inline int32_t get_rdp() {
|
||||||
return m_instr.range(4, 2);
|
return m_instr.range(4, 2) + 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -135,7 +143,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
inline int32_t get_rs1p() {
|
inline int32_t get_rs1p() {
|
||||||
return m_instr.range(9, 7);
|
return m_instr.range(9, 7) + 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,6 +158,9 @@ public:
|
||||||
m_instr.range(6,2) = value;
|
m_instr.range(6,2) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int32_t get_rs2p() {
|
||||||
|
return m_instr.range(4, 2) + 8;
|
||||||
|
}
|
||||||
|
|
||||||
inline int32_t get_funct3() {
|
inline int32_t get_funct3() {
|
||||||
return m_instr.range(15, 13);
|
return m_instr.range(15, 13);
|
||||||
|
@ -259,7 +270,7 @@ public:
|
||||||
aux |= m_instr[6] << 7;
|
aux |= m_instr[6] << 7;
|
||||||
aux |= m_instr.range(5,3) << 1;
|
aux |= m_instr.range(5,3) << 1;
|
||||||
aux |= m_instr[2] << 5;
|
aux |= m_instr[2] << 5;
|
||||||
|
|
||||||
if (m_instr[12] == 1) {
|
if (m_instr[12] == 1) {
|
||||||
aux |= 0b1111 << 12;
|
aux |= 0b1111 << 12;
|
||||||
}
|
}
|
||||||
|
@ -362,6 +373,19 @@ public:
|
||||||
return aux;
|
return aux;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int32_t get_imm_LUI() {
|
||||||
|
int32_t aux = 0;
|
||||||
|
|
||||||
|
aux = m_instr[12] << 17;
|
||||||
|
aux |= m_instr.range(6,2) << 12;
|
||||||
|
|
||||||
|
if (m_instr[12] == 1) {
|
||||||
|
aux |= 0b111111111111111 << 17;
|
||||||
|
}
|
||||||
|
|
||||||
|
return aux;
|
||||||
|
}
|
||||||
|
|
||||||
inline int32_t get_csr() {
|
inline int32_t get_csr() {
|
||||||
return get_imm_I();
|
return get_imm_I();
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ public:
|
||||||
void AUIPC(Instruction &inst);
|
void AUIPC(Instruction &inst);
|
||||||
|
|
||||||
void JAL(Instruction &inst, bool c_extension = false, int m_rd = 1);
|
void JAL(Instruction &inst, bool c_extension = false, int m_rd = 1);
|
||||||
void JALR(Instruction &inst);
|
void JALR(Instruction &inst, bool c_extension = false);
|
||||||
|
|
||||||
void BEQ(Instruction &inst);
|
void BEQ(Instruction &inst);
|
||||||
void BNE(Instruction &inst);
|
void BNE(Instruction &inst);
|
||||||
|
@ -63,7 +63,7 @@ public:
|
||||||
|
|
||||||
void SB(Instruction &inst);
|
void SB(Instruction &inst);
|
||||||
void SH(Instruction &inst);
|
void SH(Instruction &inst);
|
||||||
void SW(Instruction &inst);
|
void SW(Instruction &inst, bool c_extension = false);
|
||||||
void SBU(Instruction &inst);
|
void SBU(Instruction &inst);
|
||||||
void SHU(Instruction &inst);
|
void SHU(Instruction &inst);
|
||||||
|
|
||||||
|
@ -99,18 +99,29 @@ public:
|
||||||
void CSRRSI(Instruction &inst);
|
void CSRRSI(Instruction &inst);
|
||||||
void CSRRCI(Instruction &inst);
|
void CSRRCI(Instruction &inst);
|
||||||
|
|
||||||
|
/*********************** Privileged Instructions ******************************/
|
||||||
void MRET(Instruction &inst);
|
void MRET(Instruction &inst);
|
||||||
|
void WFI(Instruction &inst);
|
||||||
|
|
||||||
/* C Extensions */
|
/* C Extensions */
|
||||||
void C_JR(Instruction &inst);
|
void C_JR(Instruction &inst);
|
||||||
void C_MV(Instruction &inst);
|
void C_MV(Instruction &inst);
|
||||||
void C_LWSP(Instruction &inst);
|
void C_LWSP(Instruction &inst);
|
||||||
void C_ADDI4SPN(Instruction &inst);
|
void C_ADDI4SPN(Instruction &inst);
|
||||||
|
void C_SLLI(Instruction &inst);
|
||||||
void C_ADDI16SP(Instruction &inst);
|
void C_ADDI16SP(Instruction &inst);
|
||||||
void C_SWSP(Instruction &inst);
|
void C_SWSP(Instruction &inst);
|
||||||
void C_BEQZ(Instruction &inst);
|
void C_BEQZ(Instruction &inst);
|
||||||
void C_BNEZ(Instruction &inst);
|
void C_BNEZ(Instruction &inst);
|
||||||
void C_LI(Instruction &inst);
|
void C_LI(Instruction &inst);
|
||||||
|
void C_SRLI(Instruction &inst);
|
||||||
|
void C_SRAI(Instruction &inst);
|
||||||
|
void C_ANDI(Instruction &inst);
|
||||||
|
void C_ADD(Instruction &inst);
|
||||||
|
void C_SUB(Instruction &inst);
|
||||||
|
void C_XOR(Instruction &inst);
|
||||||
|
void C_OR(Instruction &inst);
|
||||||
|
void C_AND(Instruction &inst);
|
||||||
|
|
||||||
/* M Extensinos */
|
/* M Extensinos */
|
||||||
void M_MUL(Instruction &inst);
|
void M_MUL(Instruction &inst);
|
||||||
|
|
|
@ -89,6 +89,7 @@ OP_CSRRCI,
|
||||||
OP_URET,
|
OP_URET,
|
||||||
OP_SRET,
|
OP_SRET,
|
||||||
OP_MRET,
|
OP_MRET,
|
||||||
|
OP_WFI,
|
||||||
|
|
||||||
OP_ERROR
|
OP_ERROR
|
||||||
} opCodes;
|
} opCodes;
|
||||||
|
@ -156,6 +157,7 @@ typedef enum {
|
||||||
URET_F = 0b000000000010,
|
URET_F = 0b000000000010,
|
||||||
SRET_F = 0b000100000010,
|
SRET_F = 0b000100000010,
|
||||||
MRET_F = 0b001100000010,
|
MRET_F = 0b001100000010,
|
||||||
|
WFI_F = 0b000100000101,
|
||||||
ECALL_F3= 0b000,
|
ECALL_F3= 0b000,
|
||||||
CSRRW = 0b001,
|
CSRRW = 0b001,
|
||||||
CSRRS = 0b010,
|
CSRRS = 0b010,
|
||||||
|
@ -182,7 +184,6 @@ public:
|
||||||
* @return return opcode field
|
* @return return opcode field
|
||||||
*/
|
*/
|
||||||
inline int32_t opcode() {
|
inline int32_t opcode() {
|
||||||
// cout << "OP: " << m_instr << endl;
|
|
||||||
return m_instr.range(6,0);
|
return m_instr.range(6,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
39
src/CPU.cpp
39
src/CPU.cpp
|
@ -33,6 +33,9 @@ bool CPU::process_c_instruction(Instruction &inst) {
|
||||||
case OP_C_LW:
|
case OP_C_LW:
|
||||||
exec->LW(inst, true);
|
exec->LW(inst, true);
|
||||||
break;
|
break;
|
||||||
|
case OP_C_SW:
|
||||||
|
exec->SW(inst, true);
|
||||||
|
break;
|
||||||
case OP_C_ADDI:
|
case OP_C_ADDI:
|
||||||
exec->ADDI(inst, true);
|
exec->ADDI(inst, true);
|
||||||
break;
|
break;
|
||||||
|
@ -47,6 +50,9 @@ bool CPU::process_c_instruction(Instruction &inst) {
|
||||||
case OP_C_LI:
|
case OP_C_LI:
|
||||||
exec->C_LI(inst);
|
exec->C_LI(inst);
|
||||||
break;
|
break;
|
||||||
|
case OP_C_SLLI:
|
||||||
|
exec->C_SLLI(inst);
|
||||||
|
break;
|
||||||
case OP_C_LWSP:
|
case OP_C_LWSP:
|
||||||
exec->C_LWSP(inst);
|
exec->C_LWSP(inst);
|
||||||
break;
|
break;
|
||||||
|
@ -57,6 +63,13 @@ bool CPU::process_c_instruction(Instruction &inst) {
|
||||||
case OP_C_MV:
|
case OP_C_MV:
|
||||||
exec->C_MV(inst);
|
exec->C_MV(inst);
|
||||||
break;
|
break;
|
||||||
|
case OP_C_JALR:
|
||||||
|
exec->JALR(inst, true);
|
||||||
|
PC_not_affected = false;
|
||||||
|
break;
|
||||||
|
case OP_C_ADD:
|
||||||
|
exec->C_ADD(inst);
|
||||||
|
break;
|
||||||
case OP_C_SWSP:
|
case OP_C_SWSP:
|
||||||
exec->C_SWSP(inst);
|
exec->C_SWSP(inst);
|
||||||
break;
|
break;
|
||||||
|
@ -71,6 +84,27 @@ bool CPU::process_c_instruction(Instruction &inst) {
|
||||||
exec->C_BNEZ(inst);
|
exec->C_BNEZ(inst);
|
||||||
PC_not_affected = false;
|
PC_not_affected = false;
|
||||||
break;
|
break;
|
||||||
|
case OP_C_SRLI:
|
||||||
|
exec->C_SRLI(inst);
|
||||||
|
break;
|
||||||
|
case OP_C_SRAI:
|
||||||
|
exec->C_SRAI(inst);
|
||||||
|
break;
|
||||||
|
case OP_C_ANDI:
|
||||||
|
exec->C_ANDI(inst);
|
||||||
|
break;
|
||||||
|
case OP_C_SUB:
|
||||||
|
exec->C_SUB(inst);
|
||||||
|
break;
|
||||||
|
case OP_C_XOR:
|
||||||
|
exec->C_XOR(inst);
|
||||||
|
break;
|
||||||
|
case OP_C_OR:
|
||||||
|
exec->C_OR(inst);
|
||||||
|
break;
|
||||||
|
case OP_C_AND:
|
||||||
|
exec->C_AND(inst);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
std::cout << "C instruction not implemented yet" << endl;
|
std::cout << "C instruction not implemented yet" << endl;
|
||||||
inst.dump();
|
inst.dump();
|
||||||
|
@ -286,6 +320,9 @@ bool CPU::process_base_instruction(Instruction &inst) {
|
||||||
exec->MRET(inst);
|
exec->MRET(inst);
|
||||||
PC_not_affected = false;
|
PC_not_affected = false;
|
||||||
break;
|
break;
|
||||||
|
case OP_WFI:
|
||||||
|
exec->WFI(inst);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
std::cout << "Wrong instruction" << endl;
|
std::cout << "Wrong instruction" << endl;
|
||||||
inst.dump();
|
inst.dump();
|
||||||
|
@ -317,7 +354,7 @@ void CPU::CPU_thread(void) {
|
||||||
trans->set_dmi_allowed( false ); // Mandatory initial value
|
trans->set_dmi_allowed( false ); // Mandatory initial value
|
||||||
trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE );
|
trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE );
|
||||||
|
|
||||||
register_bank->dump();
|
//register_bank->dump();
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
/* Get new PC value */
|
/* Get new PC value */
|
||||||
|
|
|
@ -53,7 +53,32 @@ op_C_Codes C_Instruction::decode() {
|
||||||
return OP_C_ADDI16SP;
|
return OP_C_ADDI16SP;
|
||||||
break;
|
break;
|
||||||
case C_SRLI:
|
case C_SRLI:
|
||||||
return OP_C_SRLI;
|
switch(m_instr.range(11,10)) {
|
||||||
|
case C_2_SRLI:
|
||||||
|
return OP_C_SRLI;
|
||||||
|
break;
|
||||||
|
case C_2_SRAI:
|
||||||
|
return OP_C_SRAI;
|
||||||
|
break;
|
||||||
|
case C_2_ANDI:
|
||||||
|
return OP_C_ANDI;
|
||||||
|
break;
|
||||||
|
case C_2_SUB:
|
||||||
|
switch(m_instr.range(6,5)) {
|
||||||
|
case C_3_SUB:
|
||||||
|
return OP_C_SUB;
|
||||||
|
break;
|
||||||
|
case C_3_XOR:
|
||||||
|
return OP_C_XOR;
|
||||||
|
break;
|
||||||
|
case C_3_OR:
|
||||||
|
return OP_C_OR;
|
||||||
|
break;
|
||||||
|
case C_3_AND:
|
||||||
|
return OP_C_AND;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case C_J:
|
case C_J:
|
||||||
return OP_C_J;
|
return OP_C_J;
|
||||||
|
@ -73,6 +98,8 @@ op_C_Codes C_Instruction::decode() {
|
||||||
case 0b10:
|
case 0b10:
|
||||||
switch(get_funct3()) {
|
switch(get_funct3()) {
|
||||||
case C_SLLI:
|
case C_SLLI:
|
||||||
|
return OP_C_SLLI;
|
||||||
|
break;
|
||||||
case C_FLDSP:
|
case C_FLDSP:
|
||||||
case C_LWSP:
|
case C_LWSP:
|
||||||
return OP_C_LWSP;
|
return OP_C_LWSP;
|
||||||
|
@ -81,10 +108,20 @@ op_C_Codes C_Instruction::decode() {
|
||||||
return OP_C_FLWSP;
|
return OP_C_FLWSP;
|
||||||
break;
|
break;
|
||||||
case C_JR:
|
case C_JR:
|
||||||
if (m_instr.range(6,2) == 0) {
|
if (m_instr[12] == 0) {
|
||||||
return OP_C_JR;
|
if (m_instr.range(6,2) == 0) {
|
||||||
|
return OP_C_JR;
|
||||||
|
} else {
|
||||||
|
return OP_C_MV;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return OP_C_MV;
|
if (m_instr.range(11,2) == 0) {
|
||||||
|
return OP_C_EBREAK;
|
||||||
|
} else if (m_instr.range(6,2) == 0) {
|
||||||
|
return OP_C_JALR;
|
||||||
|
} else {
|
||||||
|
return OP_C_ADD;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case C_FDSP:
|
case C_FDSP:
|
||||||
|
|
293
src/Execute.cpp
293
src/Execute.cpp
|
@ -73,24 +73,42 @@ void Execute::JAL(Instruction &inst, bool c_extension, int m_rd) {
|
||||||
<< hex << new_pc << ")" << endl;
|
<< hex << new_pc << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::JALR(Instruction &inst) {
|
void Execute::JALR(Instruction &inst, bool c_extension) {
|
||||||
uint32_t mem_addr = 0;
|
uint32_t mem_addr = 0;
|
||||||
int rd, rs1;
|
int rd, rs1;
|
||||||
int new_pc, old_pc;
|
int new_pc, old_pc;
|
||||||
|
|
||||||
rd = inst.get_rd();
|
if (c_extension == false) {
|
||||||
rs1 = inst.get_rs1();
|
rd = inst.get_rd();
|
||||||
mem_addr = inst.get_imm_I();
|
rs1 = inst.get_rs1();
|
||||||
|
mem_addr = inst.get_imm_I();
|
||||||
|
|
||||||
old_pc = regs->getPC();
|
old_pc = regs->getPC();
|
||||||
regs->setValue(rd, old_pc + 4);
|
regs->setValue(rd, old_pc + 4);
|
||||||
|
|
||||||
new_pc = (regs->getValue(rs1) + mem_addr) & 0xFFFFFFFE;
|
new_pc = (regs->getValue(rs1) + mem_addr) & 0xFFFFFFFE;
|
||||||
regs->setPC(new_pc);
|
regs->setPC(new_pc);
|
||||||
|
|
||||||
log->SC_log(Log::INFO) << dec << "JALR: x"
|
log->SC_log(Log::INFO) << dec << "JALR: x"
|
||||||
<< rd << " <- 0x" << hex << old_pc + 4
|
<< rd << " <- 0x" << hex << old_pc + 4
|
||||||
<< " PC <- 0x" << hex << new_pc << endl;
|
<< " PC <- 0x" << hex << new_pc << endl;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
C_Instruction c_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = 1;
|
||||||
|
rs1 = c_inst.get_rs1();
|
||||||
|
|
||||||
|
old_pc = regs->getPC();
|
||||||
|
regs->setValue(rd, old_pc + 2);
|
||||||
|
|
||||||
|
new_pc = (regs->getValue(rs1) + mem_addr) & 0xFFFFFFFE;
|
||||||
|
regs->setPC(new_pc);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << dec << "C.JALR: x"
|
||||||
|
<< rd << " <- 0x" << hex << old_pc + 4
|
||||||
|
<< " PC <- 0x" << hex << new_pc << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::BEQ(Instruction &inst) {
|
void Execute::BEQ(Instruction &inst) {
|
||||||
|
@ -364,15 +382,22 @@ void Execute::SH(Instruction &inst) {
|
||||||
<< mem_addr << dec << ")" << endl;
|
<< mem_addr << dec << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::SW(Instruction &inst) {
|
void Execute::SW(Instruction &inst, bool c_extension) {
|
||||||
uint32_t mem_addr = 0;
|
uint32_t mem_addr = 0;
|
||||||
int rs1, rs2;
|
int rs1, rs2;
|
||||||
int32_t imm = 0;
|
int32_t imm = 0;
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
|
|
||||||
rs1 = inst.get_rs1();
|
if (c_extension == false) {
|
||||||
rs2 = inst.get_rs2();
|
rs1 = inst.get_rs1();
|
||||||
imm = inst.get_imm_S();
|
rs2 = inst.get_rs2();
|
||||||
|
imm = inst.get_imm_S();
|
||||||
|
} else {
|
||||||
|
C_Instruction c_inst(inst.getInstr());
|
||||||
|
rs1 = c_inst.get_rs1p();
|
||||||
|
rs2 = c_inst.get_rs2p();
|
||||||
|
imm = c_inst.get_imm_L();
|
||||||
|
}
|
||||||
|
|
||||||
mem_addr = imm + regs->getValue(rs1);
|
mem_addr = imm + regs->getValue(rs1);
|
||||||
data = regs->getValue(rs2);
|
data = regs->getValue(rs2);
|
||||||
|
@ -519,6 +544,10 @@ void Execute::SLLI(Instruction &inst) {
|
||||||
rs1 = inst.get_rs1();
|
rs1 = inst.get_rs1();
|
||||||
rs2 = inst.get_rs2();
|
rs2 = inst.get_rs2();
|
||||||
|
|
||||||
|
if (rs2 >= 0x20) {
|
||||||
|
// raise an exception, but how?
|
||||||
|
}
|
||||||
|
|
||||||
shift = rs2 & 0x1F;
|
shift = rs2 & 0x1F;
|
||||||
|
|
||||||
calc = ((uint32_t)regs->getValue(rs1)) << shift;
|
calc = ((uint32_t)regs->getValue(rs1)) << shift;
|
||||||
|
@ -599,7 +628,7 @@ void Execute::SUB(Instruction &inst) {
|
||||||
log->SC_log(Log::INFO) << "SUB: x"
|
log->SC_log(Log::INFO) << "SUB: x"
|
||||||
<< rs1 << " - x"
|
<< rs1 << " - x"
|
||||||
<< rs2 << " -> x"
|
<< rs2 << " -> x"
|
||||||
<< rd << endl;
|
<< rd << "("<< calc << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::SLL(Instruction &inst) {
|
void Execute::SLL(Instruction &inst) {
|
||||||
|
@ -788,7 +817,7 @@ void Execute::CSRRW(Instruction &inst) {
|
||||||
void Execute::CSRRS(Instruction &inst) {
|
void Execute::CSRRS(Instruction &inst) {
|
||||||
int rd, rs1;
|
int rd, rs1;
|
||||||
int csr;
|
int csr;
|
||||||
uint32_t bitmask, aux;
|
uint32_t bitmask, aux, aux2;
|
||||||
|
|
||||||
rd = inst.get_rd();
|
rd = inst.get_rd();
|
||||||
rs1 = inst.get_rs1();
|
rs1 = inst.get_rs1();
|
||||||
|
@ -803,11 +832,11 @@ void Execute::CSRRS(Instruction &inst) {
|
||||||
regs->setValue(rd, aux);
|
regs->setValue(rd, aux);
|
||||||
|
|
||||||
bitmask = regs->getValue(rs1);
|
bitmask = regs->getValue(rs1);
|
||||||
aux = aux | bitmask;
|
aux2 = aux | bitmask;
|
||||||
regs->setCSR(csr, aux);
|
regs->setCSR(csr, aux2);
|
||||||
|
|
||||||
log->SC_log(Log::INFO) << "CSRRS: CSR #"
|
log->SC_log(Log::INFO) << "CSRRS: CSR #"
|
||||||
<< csr << " -> x" << rd
|
<< csr << "(" << aux << ") -> x" << dec << rd
|
||||||
<< ". x" << rs1 << " & CSR #" << csr << endl;
|
<< ". x" << rs1 << " & CSR #" << csr << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,6 +941,8 @@ void Execute::CSRRCI(Instruction &inst) {
|
||||||
<< ". x" << rs1 << " & CSR #" << csr << endl;
|
<< ". x" << rs1 << " & CSR #" << csr << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************** Privileged Instructions ******************************/
|
||||||
|
|
||||||
void Execute::MRET(Instruction &inst) {
|
void Execute::MRET(Instruction &inst) {
|
||||||
uint32_t new_pc = 0;
|
uint32_t new_pc = 0;
|
||||||
|
|
||||||
|
@ -921,6 +952,13 @@ void Execute::MRET(Instruction &inst) {
|
||||||
log->SC_log(Log::INFO) << "MRET: PC <- 0x" << hex << new_pc << endl;
|
log->SC_log(Log::INFO) << "MRET: PC <- 0x" << hex << new_pc << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Execute::WFI(Instruction &inst) {
|
||||||
|
log->SC_log(Log::INFO) << "WFI" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************** C Instructions **********************************/
|
||||||
|
|
||||||
void Execute::C_JR(Instruction &inst) {
|
void Execute::C_JR(Instruction &inst) {
|
||||||
uint32_t mem_addr = 0;
|
uint32_t mem_addr = 0;
|
||||||
int rs1;
|
int rs1;
|
||||||
|
@ -952,12 +990,31 @@ void Execute::C_MV(Instruction &inst) {
|
||||||
calc = regs->getValue(rs1) + regs->getValue(rs2);
|
calc = regs->getValue(rs1) + regs->getValue(rs2);
|
||||||
regs->setValue(rd, calc);
|
regs->setValue(rd, calc);
|
||||||
|
|
||||||
log->SC_log(Log::INFO) << "MV: x" << dec
|
log->SC_log(Log::INFO) << "C.MV: x" << dec
|
||||||
<< rs1 << "(" << regs->getValue(rs1) << ") + x"
|
<< rs1 << "(" << regs->getValue(rs1) << ") + x"
|
||||||
<< rs2 << "(" << regs->getValue(rs2) << ") -> x"
|
<< rs2 << "(" << regs->getValue(rs2) << ") -> x"
|
||||||
<< rd << "(" << calc << ")" << endl;
|
<< rd << "(" << calc << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Execute::C_ADD(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
uint32_t calc;
|
||||||
|
|
||||||
|
C_Instruction c_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = c_inst.get_rs1();
|
||||||
|
rs1 = c_inst.get_rs1();
|
||||||
|
rs2 = c_inst.get_rs2();
|
||||||
|
|
||||||
|
calc = regs->getValue(rs1) + regs->getValue(rs2);
|
||||||
|
regs->setValue(rd, calc);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << "C.ADD: x"
|
||||||
|
<< dec << rs1 << " + x"
|
||||||
|
<< rs2 << " -> x"
|
||||||
|
<< rd << endl;
|
||||||
|
}
|
||||||
|
|
||||||
void Execute::C_LWSP(Instruction &inst) {
|
void Execute::C_LWSP(Instruction &inst) {
|
||||||
uint32_t mem_addr = 0;
|
uint32_t mem_addr = 0;
|
||||||
int rd, rs1;
|
int rd, rs1;
|
||||||
|
@ -1010,17 +1067,27 @@ void Execute::C_ADDI16SP(Instruction &inst) {
|
||||||
|
|
||||||
C_Instruction c_inst(inst.getInstr());
|
C_Instruction c_inst(inst.getInstr());
|
||||||
|
|
||||||
rd = 2;
|
if (c_inst.get_rd() == 2) {
|
||||||
rs1 = 2;
|
rd = 2;
|
||||||
imm = c_inst.get_imm_ADDI16SP();
|
rs1 = 2;
|
||||||
|
imm = c_inst.get_imm_ADDI16SP();
|
||||||
|
|
||||||
calc = regs->getValue(rs1) + imm;
|
calc = regs->getValue(rs1) + imm;
|
||||||
regs->setValue(rd, calc);
|
regs->setValue(rd, calc);
|
||||||
|
|
||||||
log->SC_log(Log::INFO) << dec << "ADDI16SP: x"
|
log->SC_log(Log::INFO) << dec << "ADDI16SP: x"
|
||||||
<< rs1 << " + "
|
<< rs1 << " + "
|
||||||
<< dec << imm << " -> x"
|
<< dec << imm << " -> x"
|
||||||
<< rd << "(0x" << hex << calc << ")" << endl;
|
<< rd << "(0x" << hex << calc << ")" << endl;
|
||||||
|
} else {
|
||||||
|
/* C.LUI OPCODE */
|
||||||
|
rd = c_inst.get_rd();
|
||||||
|
imm = c_inst.get_imm_LUI();
|
||||||
|
regs->setValue(rd, imm);
|
||||||
|
log->SC_log(Log::INFO) << dec << "C.LUI x"
|
||||||
|
<< rd << " <- 0x" << hex << imm << endl;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::C_SWSP(Instruction &inst) {
|
void Execute::C_SWSP(Instruction &inst) {
|
||||||
|
@ -1092,7 +1159,6 @@ void Execute::C_BNEZ(Instruction &inst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::C_LI(Instruction &inst) {
|
void Execute::C_LI(Instruction &inst) {
|
||||||
|
|
||||||
int rd, rs1;
|
int rd, rs1;
|
||||||
int32_t imm = 0;
|
int32_t imm = 0;
|
||||||
int32_t calc;
|
int32_t calc;
|
||||||
|
@ -1111,6 +1177,171 @@ void Execute::C_LI(Instruction &inst) {
|
||||||
<< imm << " -> x" << rd << "(" << calc << ")" << endl;
|
<< imm << " -> x" << rd << "(" << calc << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Execute::C_SRLI(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
uint32_t shift;
|
||||||
|
uint32_t calc;
|
||||||
|
|
||||||
|
C_Instruction c_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = c_inst.get_rs1p();
|
||||||
|
rs1 = c_inst.get_rs1p();
|
||||||
|
rs2 = c_inst.get_rs2();
|
||||||
|
|
||||||
|
shift = rs2 & 0x1F;
|
||||||
|
|
||||||
|
calc = ((uint32_t)regs->getValue(rs1)) >> shift;
|
||||||
|
regs->setValue(rd, calc);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << "C.SRLI: x"
|
||||||
|
<< rs1 << " >> " << shift << " -> x"
|
||||||
|
<< rd << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Execute::C_SRAI(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
uint32_t shift;
|
||||||
|
int32_t calc;
|
||||||
|
|
||||||
|
C_Instruction c_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = c_inst.get_rs1p();
|
||||||
|
rs1 = c_inst.get_rs1p();
|
||||||
|
rs2 = c_inst.get_rs2();
|
||||||
|
|
||||||
|
shift = rs2 & 0x1F;
|
||||||
|
|
||||||
|
calc = (int32_t)regs->getValue(rs1) >> shift;
|
||||||
|
regs->setValue(rd, calc);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << "C.SRAI: x"
|
||||||
|
<< rs1 << " >> " << dec << shift << " -> x"
|
||||||
|
<< rd << "("<< calc << ")" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Execute::C_SLLI(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
uint32_t shift;
|
||||||
|
uint32_t calc;
|
||||||
|
|
||||||
|
C_Instruction c_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = c_inst.get_rs1p();
|
||||||
|
rs1 = c_inst.get_rs1p();
|
||||||
|
rs2 = c_inst.get_imm_ADDI();
|
||||||
|
|
||||||
|
shift = rs2 & 0x1F;
|
||||||
|
|
||||||
|
calc = ((uint32_t)regs->getValue(rs1)) << shift;
|
||||||
|
regs->setValue(rd, calc);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << "C.SLLI: x"
|
||||||
|
<< dec << rs1 << " << "
|
||||||
|
<< shift << " -> x"
|
||||||
|
<< rd << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Execute::C_ANDI(Instruction &inst) {
|
||||||
|
int rd, rs1;
|
||||||
|
int32_t imm;
|
||||||
|
uint32_t calc;
|
||||||
|
|
||||||
|
C_Instruction c_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = c_inst.get_rs1p();
|
||||||
|
rs1 = c_inst.get_rs1p();
|
||||||
|
imm = c_inst.get_imm_ADDI();
|
||||||
|
|
||||||
|
calc = regs->getValue(rs1) & imm;
|
||||||
|
regs->setValue(rd, calc);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << "C.ANDI: x"
|
||||||
|
<< rs1 << " AND "
|
||||||
|
<< imm << " -> x"
|
||||||
|
<< rd << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Execute::C_SUB(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
uint32_t calc;
|
||||||
|
|
||||||
|
C_Instruction c_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = c_inst.get_rs1p();
|
||||||
|
rs1 = c_inst.get_rs1p();
|
||||||
|
rs2 = c_inst.get_rs2p();
|
||||||
|
|
||||||
|
calc = regs->getValue(rs1) - regs->getValue(rs2);
|
||||||
|
regs->setValue(rd, calc);
|
||||||
|
|
||||||
|
/* Can insert some arbitrary execution time */
|
||||||
|
//wait(sc_time(10, SC_NS));
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << "C.SUB: x"
|
||||||
|
<< dec << rs1 << " - x"
|
||||||
|
<< rs2 << " -> x"
|
||||||
|
<< rd << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Execute::C_XOR(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
uint32_t calc;
|
||||||
|
|
||||||
|
C_Instruction c_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = c_inst.get_rs1p();
|
||||||
|
rs1 = c_inst.get_rs1p();
|
||||||
|
rs2 = c_inst.get_rs2p();
|
||||||
|
|
||||||
|
calc = regs->getValue(rs1) ^ regs->getValue(rs2);
|
||||||
|
regs->setValue(rd, calc);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << "C.XOR: x"
|
||||||
|
<< dec << rs1 << " XOR x"
|
||||||
|
<< rs2 << "-> x"
|
||||||
|
<< rd << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Execute::C_OR(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
uint32_t calc;
|
||||||
|
|
||||||
|
C_Instruction c_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = c_inst.get_rs1p();
|
||||||
|
rs1 = c_inst.get_rs1p();
|
||||||
|
rs2 = c_inst.get_rs2p();
|
||||||
|
|
||||||
|
calc = regs->getValue(rs1) | regs->getValue(rs2);
|
||||||
|
regs->setValue(rd, calc);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << "C_OR: x"
|
||||||
|
<< dec << rs1 << " OR x"
|
||||||
|
<< rs2 << "-> x"
|
||||||
|
<< rd << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Execute::C_AND(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
uint32_t calc;
|
||||||
|
|
||||||
|
C_Instruction c_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = c_inst.get_rs1p();
|
||||||
|
rs1 = c_inst.get_rs1p();
|
||||||
|
rs2 = c_inst.get_rs2p();
|
||||||
|
|
||||||
|
calc = regs->getValue(rs1) & regs->getValue(rs2);
|
||||||
|
regs->setValue(rd, calc);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << "C.AND: x"
|
||||||
|
<< dec << rs1 << " AND x"
|
||||||
|
<< rs2 << "-> x"
|
||||||
|
<< rd << endl;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* M Extensions */
|
/* M Extensions */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
|
@ -128,6 +128,8 @@ opCodes Instruction::decode() {
|
||||||
return OP_SRET;
|
return OP_SRET;
|
||||||
case MRET_F:
|
case MRET_F:
|
||||||
return OP_MRET;
|
return OP_MRET;
|
||||||
|
case WFI_F:
|
||||||
|
return OP_WFI;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CSRRW:
|
case CSRRW:
|
||||||
|
|
Loading…
Reference in New Issue