all tests passed!
This commit is contained in:
parent
d449ea5502
commit
a8bdc37c12
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
155
src/Execute.cpp
155
src/Execute.cpp
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue