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