diff --git a/simulator/mips/mips_instr.cpp b/simulator/mips/mips_instr.cpp index db80e9c6f..6eab2ead3 100644 --- a/simulator/mips/mips_instr.cpp +++ b/simulator/mips/mips_instr.cpp @@ -294,6 +294,50 @@ BaseMIPSInstr::BaseMIPSInstr( MIPSVersion version, uint32 bytes, A } } +template +BaseMIPSInstr::BaseMIPSInstr( MIPSVersion version, std::string_view str_opcode, Addr PC) : + new_PC( PC + 4), + PC( PC) +{ + auto it = find_entry( isaMapR, str_opcode); + if ( it == isaMapR.end()) + it = find_entry( isaMapRI, str_opcode); + if ( it == isaMapRI.end()) + it = find_entry( isaMapMIPS32, str_opcode); + if ( it == isaMapMIPS32.end()) + it = find_entry( isaMapIJ, str_opcode); + + if ( str_opcode == "nop") + { + init (isaMapR.find( 0)->second, version); + disasm = "nop "; + } + else if ( it == isaMapIJ.end()) + { + std::ostringstream oss; + if ( PC != 0) + oss << std::hex << "0x" << PC << ": "; + oss << str_opcode << '\t' << "Unknown"; + disasm = oss.str(); + } + else { + init( it->second, version); + } +} + +template +typename BaseMIPSInstr::MapType::const_iterator +BaseMIPSInstr::find_entry( const BaseMIPSInstr::MapType& map, std::string_view name) const +{ + auto it = map.begin(); + for ( ; it != map.end(); it++) + { + if ( it->second.name == name) + return it; + } + return map.end(); +} + template MIPSRegister BaseMIPSInstr::get_register( RegType type) const { diff --git a/simulator/mips/mips_instr.h b/simulator/mips/mips_instr.h index d4e2e2cf6..61f7b3101 100644 --- a/simulator/mips/mips_instr.h +++ b/simulator/mips/mips_instr.h @@ -161,6 +161,7 @@ class BaseMIPSInstr static const MapType isaMapRI; static const MapType isaMapIJ; static const MapType isaMapMIPS32; + typename MapType::const_iterator find_entry( const MapType& isaMap, std::string_view name) const; MIPSRegister src1 = MIPSRegister::zero; MIPSRegister src2 = MIPSRegister::zero; @@ -402,6 +403,7 @@ class BaseMIPSInstr Execute function = &BaseMIPSInstr::execute_unknown; protected: BaseMIPSInstr( MIPSVersion version, uint32 bytes, Addr PC); + BaseMIPSInstr( MIPSVersion version, std::string_view str_opcode, Addr PC); public: static const constexpr Endian endian = Endian::little; @@ -467,6 +469,9 @@ class BaseMIPSInstr Trap trap_type() const { return trap; } bool is_bubble() const { return is_nop() && PC == 0; } + + void set_v_imm( uint32 value) { v_imm = value; } + auto get_v_imm() { return v_imm; } void set_v_src( RegisterUInt value, uint8 index) { @@ -511,6 +516,8 @@ class MIPSInstr : public BaseMIPSInstr> public: explicit MIPSInstr( uint32 bytes, Addr PC = 0) : Base( V, bytes, PC) { } + explicit MIPSInstr( std::string_view str_opcode, Addr PC = 0) + : Base( V, str_opcode, PC) { } }; diff --git a/simulator/mips/t/unit_test.cpp b/simulator/mips/t/unit_test.cpp index 039746b8f..733f0925b 100644 --- a/simulator/mips/t/unit_test.cpp +++ b/simulator/mips/t/unit_test.cpp @@ -9,6 +9,49 @@ TEST_CASE( "MIPS32_instr_init: Process_Wrong_Args_Of_Constr") CHECK_NOTHROW( MIPS32Instr(0x0).execute()); } +TEST_CASE( "MIPS32_instr: invalid instruction in ctor from string") +{ + MIPS32Instr instr( "invalid_instruction"); + CHECK_THROWS_AS( instr.execute(), UnknownMIPSInstruction); +} + +TEST_CASE( "MIPS32_instr: sllv") +{ + MIPS32Instr instr( "sllv"); + instr.set_v_src( 1, 0); + instr.set_v_src( 0, 1); + instr.execute(); + CHECK( instr.get_v_dst() == 1); +} + +TEST_CASE( "MIPS32_instr: mul") +{ + MIPS32Instr instr( "mul"); + instr.set_v_src( 10, 0); + instr.set_v_src( 20, 1); + instr.execute(); + CHECK( instr.get_v_dst() == 200); +} + +TEST_CASE( "MIPS32_instr: addi") +{ + MIPS32Instr instr( "addi"); + instr.set_v_src( 10, 0); + instr.set_v_src( 0, 1); + instr.set_v_imm( 20); + instr.execute(); + CHECK( instr.get_v_dst() == 30); +} + +TEST_CASE( "MIPS32_instr: teqi") +{ + MIPS32Instr instr( "teqi"); + instr.set_v_src( 0, 0); + instr.set_v_imm( 0); + instr.execute(); + CHECK( instr.has_trap()); +} + TEST_CASE( "MIPS32_instr: Divmult") { CHECK(MIPS32Instr(0x02290018).is_divmult()); @@ -19,6 +62,14 @@ TEST_CASE( "MIPS32_instr: Divmult") CHECK(MIPS32Instr(0x72290001).is_divmult()); CHECK(MIPS32Instr(0x72290004).is_divmult()); CHECK(MIPS32Instr(0x72290005).is_divmult()); + CHECK(MIPS32Instr("mult").is_divmult()); + CHECK(MIPS32Instr("multu").is_divmult()); + CHECK(MIPS32Instr("div").is_divmult()); + CHECK(MIPS32Instr("divu").is_divmult()); + CHECK(MIPS32Instr("dmult").is_divmult()); + CHECK(MIPS32Instr("dmultu").is_divmult()); + CHECK(MIPS32Instr("ddiv").is_divmult()); + CHECK(MIPS32Instr("ddivu").is_divmult()); } TEST_CASE( "MIPS32_instr_disasm: Process_Disasm_R") @@ -79,6 +130,7 @@ TEST_CASE( "MIPS32_instr_disasm: Process_Disasm_R") CHECK(MIPS32Instr(0x02290036).get_disasm() == "tne $s1, $t1"); CHECK(MIPS32Instr(0x01208809).get_disasm() == "jalr $s1, $t1"); CHECK(MIPS32Instr(0x00000000).get_disasm() == "nop "); + CHECK(MIPS32Instr ("nop").get_disasm() == "nop "); } TEST_CASE( "MIPS32_instr_disasm: Process_Disasm_IJ")