all tests passed!
This commit is contained in:
parent
d449ea5502
commit
a8bdc37c12
|
@ -77,7 +77,7 @@ public:
|
||||||
* @return rs1 field
|
* @return rs1 field
|
||||||
*/
|
*/
|
||||||
inline int32_t get_rs1() {
|
inline int32_t get_rs1() {
|
||||||
return m_instr.range(19, 5);
|
return m_instr.range(19, 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_rs1(int32_t value) {
|
inline void set_rs1(int32_t value) {
|
||||||
|
|
|
@ -105,7 +105,7 @@ bool CPU::process_m_instruction(Instruction &inst) {
|
||||||
exec->M_DIV(inst);
|
exec->M_DIV(inst);
|
||||||
break;
|
break;
|
||||||
case OP_M_DIVU:
|
case OP_M_DIVU:
|
||||||
exec->M_DIV(inst);
|
exec->M_DIVU(inst);
|
||||||
break;
|
break;
|
||||||
case OP_M_REM:
|
case OP_M_REM:
|
||||||
exec->M_REM(inst);
|
exec->M_REM(inst);
|
||||||
|
|
155
src/Execute.cpp
155
src/Execute.cpp
|
@ -1130,38 +1130,191 @@ void Execute::M_MUL(Instruction &inst) {
|
||||||
multiplicand = regs->getValue(rs2);
|
multiplicand = regs->getValue(rs2);
|
||||||
|
|
||||||
result = multiplier * multiplicand;
|
result = multiplier * multiplicand;
|
||||||
regs->setValue(rd, result & 0x00000000FFFFFFFF);
|
result = result & 0x00000000FFFFFFFF;
|
||||||
|
regs->setValue(rd, result);
|
||||||
|
|
||||||
log->SC_log(Log::INFO) << dec << "MUL: x" << rs1 << " * x" << rs2
|
log->SC_log(Log::INFO) << dec << "MUL: x" << rs1 << " * x" << rs2
|
||||||
<< " -> x" << rd << "(" << result << ")" << endl;
|
<< " -> x" << rd << "(" << result << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::M_MULH(Instruction &inst) {
|
void Execute::M_MULH(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
int32_t multiplier, multiplicand;
|
||||||
|
int64_t result;
|
||||||
|
int32_t ret_value;
|
||||||
|
|
||||||
|
M_Instruction m_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = m_inst.get_rd();
|
||||||
|
rs1 = m_inst.get_rs1();
|
||||||
|
rs2 = m_inst.get_rs2();
|
||||||
|
|
||||||
|
multiplier = regs->getValue(rs1);
|
||||||
|
multiplicand = regs->getValue(rs2);
|
||||||
|
|
||||||
|
result = (int64_t) multiplier * (int64_t) multiplicand;
|
||||||
|
|
||||||
|
ret_value = (int32_t)((result >> 32) & 0x00000000FFFFFFFF);
|
||||||
|
regs->setValue(rd, ret_value);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << dec << "MULH: x" << rs1 << " * x" << rs2
|
||||||
|
<< " -> x" << rd << "(" << result << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::M_MULHSU(Instruction &inst) {
|
void Execute::M_MULHSU(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
int32_t multiplier;
|
||||||
|
uint32_t multiplicand;
|
||||||
|
int64_t result;
|
||||||
|
|
||||||
|
M_Instruction m_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = m_inst.get_rd();
|
||||||
|
rs1 = m_inst.get_rs1();
|
||||||
|
rs2 = m_inst.get_rs2();
|
||||||
|
|
||||||
|
multiplier = regs->getValue(rs1);
|
||||||
|
multiplicand = regs->getValue(rs2);
|
||||||
|
|
||||||
|
result = (int64_t) multiplier * (uint64_t) multiplicand;
|
||||||
|
result = (result >> 32) & 0x00000000FFFFFFFF;
|
||||||
|
regs->setValue(rd, result);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << dec << "MULHSU: x" << rs1 << " * x" << rs2
|
||||||
|
<< " -> x" << rd << "(" << result << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::M_MULHU(Instruction &inst) {
|
void Execute::M_MULHU(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
uint32_t multiplier, multiplicand;
|
||||||
|
uint64_t result;
|
||||||
|
int32_t ret_value;
|
||||||
|
|
||||||
|
M_Instruction m_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = m_inst.get_rd();
|
||||||
|
rs1 = m_inst.get_rs1();
|
||||||
|
rs2 = m_inst.get_rs2();
|
||||||
|
|
||||||
|
multiplier = (uint32_t) regs->getValue(rs1);
|
||||||
|
multiplicand = (uint32_t) regs->getValue(rs2);
|
||||||
|
|
||||||
|
result = (uint64_t) multiplier * (uint64_t) multiplicand;
|
||||||
|
ret_value = (uint32_t)(result >> 32) & 0x00000000FFFFFFFF;
|
||||||
|
regs->setValue(rd, ret_value);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << dec << "MULHU: x" << rs1 << " * x" << rs2
|
||||||
|
<< " -> x" << rd << "(" << ret_value << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::M_DIV(Instruction &inst) {
|
void Execute::M_DIV(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
int32_t divisor, dividend;
|
||||||
|
int64_t result;
|
||||||
|
|
||||||
|
M_Instruction m_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = m_inst.get_rd();
|
||||||
|
rs1 = m_inst.get_rs1();
|
||||||
|
rs2 = m_inst.get_rs2();
|
||||||
|
|
||||||
|
dividend = regs->getValue(rs1);
|
||||||
|
divisor = regs->getValue(rs2);
|
||||||
|
|
||||||
|
if (divisor == 0) {
|
||||||
|
result = - 1;
|
||||||
|
} else if ( (divisor == -1) && (dividend == (int32_t)0x80000000) ) {
|
||||||
|
result = 0x0000000080000000;
|
||||||
|
} else {
|
||||||
|
result = dividend / divisor;
|
||||||
|
result = result & 0x00000000FFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs->setValue(rd, result);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << dec << "DIV: x" << rs1 << " / x" << rs2
|
||||||
|
<< " -> x" << rd << "(" << result << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::M_DIVU(Instruction &inst) {
|
void Execute::M_DIVU(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
uint32_t divisor, dividend;
|
||||||
|
uint64_t result;
|
||||||
|
|
||||||
|
M_Instruction m_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = m_inst.get_rd();
|
||||||
|
rs1 = m_inst.get_rs1();
|
||||||
|
rs2 = m_inst.get_rs2();
|
||||||
|
|
||||||
|
dividend = regs->getValue(rs1);
|
||||||
|
divisor = regs->getValue(rs2);
|
||||||
|
|
||||||
|
if (divisor == 0) {
|
||||||
|
result = -1;
|
||||||
|
} else {
|
||||||
|
result = dividend / divisor;
|
||||||
|
result = result & 0x00000000FFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs->setValue(rd, result);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << dec << "DIVU: x" << rs1 << " / x" << rs2
|
||||||
|
<< " -> x" << rd << "(" << result << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::M_REM(Instruction &inst) {
|
void Execute::M_REM(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
int32_t divisor, dividend;
|
||||||
|
int32_t result;
|
||||||
|
|
||||||
|
M_Instruction m_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = m_inst.get_rd();
|
||||||
|
rs1 = m_inst.get_rs1();
|
||||||
|
rs2 = m_inst.get_rs2();
|
||||||
|
|
||||||
|
dividend = regs->getValue(rs1);
|
||||||
|
divisor = regs->getValue(rs2);
|
||||||
|
|
||||||
|
if (divisor == 0) {
|
||||||
|
result = dividend;
|
||||||
|
} else if ( (divisor == -1) && (dividend == (int32_t)0x80000000) ) {
|
||||||
|
result = 0;
|
||||||
|
} else {
|
||||||
|
result = dividend % divisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs->setValue(rd, result);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << dec << "REM: x" << rs1 << " / x" << rs2
|
||||||
|
<< " -> x" << rd << "(" << result << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::M_REMU(Instruction &inst) {
|
void Execute::M_REMU(Instruction &inst) {
|
||||||
|
int rd, rs1, rs2;
|
||||||
|
uint32_t divisor, dividend;
|
||||||
|
uint32_t result;
|
||||||
|
|
||||||
|
M_Instruction m_inst(inst.getInstr());
|
||||||
|
|
||||||
|
rd = m_inst.get_rd();
|
||||||
|
rs1 = m_inst.get_rs1();
|
||||||
|
rs2 = m_inst.get_rs2();
|
||||||
|
|
||||||
|
dividend = regs->getValue(rs1);
|
||||||
|
divisor = regs->getValue(rs2);
|
||||||
|
|
||||||
|
if (divisor == 0) {
|
||||||
|
result = dividend;
|
||||||
|
} else {
|
||||||
|
result = dividend % divisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs->setValue(rd, result);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << dec << "REMU: x" << rs1 << " / x" << rs2
|
||||||
|
<< " -> x" << rd << "(" << result << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::NOP(Instruction &inst) {
|
void Execute::NOP(Instruction &inst) {
|
||||||
|
|
|
@ -157,7 +157,9 @@ opCodes Instruction::decode() {
|
||||||
|
|
||||||
|
|
||||||
extension_t Instruction::check_extension() {
|
extension_t Instruction::check_extension() {
|
||||||
if (m_instr.range(1,0) == 0b11) {
|
if (m_instr.range(6,0) == 0b0110011) {
|
||||||
|
return M_EXTENSION;
|
||||||
|
} else if (m_instr.range(1,0) == 0b11) {
|
||||||
return BASE_EXTENSION;
|
return BASE_EXTENSION;
|
||||||
} else if (m_instr.range(1,0) == 0b00) {
|
} else if (m_instr.range(1,0) == 0b00) {
|
||||||
return C_EXTENSION;
|
return C_EXTENSION;
|
||||||
|
@ -165,9 +167,8 @@ extension_t Instruction::check_extension() {
|
||||||
return C_EXTENSION;
|
return C_EXTENSION;
|
||||||
} else if (m_instr.range(1,0) == 0b10) {
|
} else if (m_instr.range(1,0) == 0b10) {
|
||||||
return C_EXTENSION;
|
return C_EXTENSION;
|
||||||
} else if (m_instr.range(6,0) == 0b0110011) {
|
|
||||||
return M_EXTENSION;
|
|
||||||
} else if (m_instr.range(6,0) == 0b0101111) {
|
} else if (m_instr.range(6,0) == 0b0101111) {
|
||||||
|
cout << "check_extension A not yet implemented" << endl;
|
||||||
return A_EXTENSION;
|
return A_EXTENSION;
|
||||||
} else {
|
} else {
|
||||||
return UNKNOWN_EXTENSION;
|
return UNKNOWN_EXTENSION;
|
||||||
|
|
Loading…
Reference in New Issue