all tests passed!

This commit is contained in:
mariusmonton 2018-11-14 19:14:57 +01:00
parent d449ea5502
commit a8bdc37c12
4 changed files with 160 additions and 6 deletions

View File

@ -77,7 +77,7 @@ public:
* @return rs1 field
*/
inline int32_t get_rs1() {
return m_instr.range(19, 5);
return m_instr.range(19, 15);
}
inline void set_rs1(int32_t value) {

View File

@ -105,7 +105,7 @@ bool CPU::process_m_instruction(Instruction &inst) {
exec->M_DIV(inst);
break;
case OP_M_DIVU:
exec->M_DIV(inst);
exec->M_DIVU(inst);
break;
case OP_M_REM:
exec->M_REM(inst);

View File

@ -1130,38 +1130,191 @@ void Execute::M_MUL(Instruction &inst) {
multiplicand = regs->getValue(rs2);
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
<< " -> x" << rd << "(" << result << ")" << endl;
}
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) {
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) {
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) {
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) {
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) {
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) {
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) {

View File

@ -157,7 +157,9 @@ opCodes Instruction::decode() {
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;
} else if (m_instr.range(1,0) == 0b00) {
return C_EXTENSION;
@ -165,9 +167,8 @@ extension_t Instruction::check_extension() {
return C_EXTENSION;
} else if (m_instr.range(1,0) == 0b10) {
return C_EXTENSION;
} else if (m_instr.range(6,0) == 0b0110011) {
return M_EXTENSION;
} else if (m_instr.range(6,0) == 0b0101111) {
cout << "check_extension A not yet implemented" << endl;
return A_EXTENSION;
} else {
return UNKNOWN_EXTENSION;