Skip to content

Commit

Permalink
Add ctor of MIPS instruction from string
Browse files Browse the repository at this point in the history
Fixes #589 
Additionally:
New utility method in class BaseMIPSInstr:
    MapType::iterator find_entry(MapType isaMap, std::string_view name);
New unit tests:
    TEST_CASE( "sllv") (#530)
    TEST_CASE( "MIPS32_instr: Divmult") ( using new ctor)

Fix types of supporting function.
Add get_v_imm and set_v_imm for unit tests.
Add sllv, mul, addi, teqi tests.
Fix nop bug for ctor, add nop test for new ctor.
  • Loading branch information
pukhovv authored and pavelkryukov committed Oct 28, 2018
1 parent 1b59024 commit 2a5e093
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 0 deletions.
44 changes: 44 additions & 0 deletions simulator/mips/mips_instr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,50 @@ BaseMIPSInstr<RegisterUInt>::BaseMIPSInstr( MIPSVersion version, uint32 bytes, A
}
}

template<typename RegisterUInt>
BaseMIPSInstr<RegisterUInt>::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 RegisterUInt>
typename BaseMIPSInstr<RegisterUInt>::MapType::const_iterator
BaseMIPSInstr<RegisterUInt>::find_entry( const BaseMIPSInstr<RegisterUInt>::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<typename RegisterUInt>
MIPSRegister BaseMIPSInstr<RegisterUInt>::get_register( RegType type) const
{
Expand Down
7 changes: 7 additions & 0 deletions simulator/mips/mips_instr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -511,6 +516,8 @@ class MIPSInstr : public BaseMIPSInstr<MIPSRegisterUInt<V>>
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) { }
};


Expand Down
52 changes: 52 additions & 0 deletions simulator/mips/t/unit_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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")
Expand Down Expand Up @@ -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")
Expand Down

0 comments on commit 2a5e093

Please sign in to comment.