From a8bdc37c128f3e3d90c48bd8fd11629a1ecb9a23 Mon Sep 17 00:00:00 2001 From: mariusmonton Date: Wed, 14 Nov 2018 19:14:57 +0100 Subject: [PATCH] all tests passed! --- inc/M_Instruction.h | 2 +- src/CPU.cpp | 2 +- src/Execute.cpp | 155 +++++++++++++++++++++++++++++++++++++++++++- src/Instruction.cpp | 7 +- 4 files changed, 160 insertions(+), 6 deletions(-) diff --git a/inc/M_Instruction.h b/inc/M_Instruction.h index 8beebd4..6c7cbac 100644 --- a/inc/M_Instruction.h +++ b/inc/M_Instruction.h @@ -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) { diff --git a/src/CPU.cpp b/src/CPU.cpp index 8141b1b..341673c 100644 --- a/src/CPU.cpp +++ b/src/CPU.cpp @@ -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); diff --git a/src/Execute.cpp b/src/Execute.cpp index f9505e9..998f94b 100644 --- a/src/Execute.cpp +++ b/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) { diff --git a/src/Instruction.cpp b/src/Instruction.cpp index 503eec8..d9eb9f5 100644 --- a/src/Instruction.cpp +++ b/src/Instruction.cpp @@ -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;