#include "tst_machine.h" #include "alu.h" #include "qtmipsexception.h" using namespace machine; void MachineTests::alu_data() { QTest::addColumn("op"); QTest::addColumn("s"); QTest::addColumn("t"); QTest::addColumn("sa"); QTest::addColumn("regs_init"); QTest::addColumn("regs_res"); QTest::addColumn("res"); QTest::newRow("SLL") << ALU_OP_SLL \ << (std::uint32_t)0 \ << (std::uint32_t)0x80000001 \ << (std::uint8_t)3 \ << Registers() \ << Registers() \ << (std::uint32_t)0x8; QTest::newRow("SRL") << ALU_OP_SRL \ << (std::uint32_t)0 \ << (std::uint32_t)0x80000008 \ << (std::uint8_t)3 \ << Registers() \ << Registers() \ << (std::uint32_t)0x10000001; QTest::newRow("SRA") << ALU_OP_SRA \ << (std::uint32_t)0 \ << (std::uint32_t)0x80000008 \ << (std::uint8_t)3 \ << Registers() \ << Registers() \ << (std::uint32_t)0xF0000001; QTest::newRow("SLLV") << ALU_OP_SLLV \ << (std::uint32_t)3 \ << (std::uint32_t)0x80000001 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)0x8; QTest::newRow("SRLV") << ALU_OP_SRLV \ << (std::uint32_t)3 \ << (std::uint32_t)0x80000008 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)0x10000001; QTest::newRow("SRAV") << ALU_OP_SRAV \ << (std::uint32_t)3 \ << (std::uint32_t)0x80000008 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)0xF0000001; // JR and JALR should have no effect and we test that in core (it really doesn't make sense to test it here) QTest::newRow("MOVZ") << ALU_OP_MOVZ \ << (std::uint32_t)22 \ << (std::uint32_t)0 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)22; QTest::newRow("MOVN") << ALU_OP_MOVN \ << (std::uint32_t)22 \ << (std::uint32_t)1 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)22; { Registers init; init.write_hi_lo(true, 42); init.write_hi_lo(false, 24); Registers res(init); QTest::newRow("MFHI") << ALU_OP_MFHI \ << (std::uint32_t)0 \ << (std::uint32_t)0 \ << (std::uint8_t)0 \ << init \ << res \ << (std::uint32_t)42; QTest::newRow("MFLO") << ALU_OP_MFLO \ << (std::uint32_t)0 \ << (std::uint32_t)0 \ << (std::uint8_t)0 \ << init \ << res \ << (std::uint32_t)24; res.write_hi_lo(true, 43); QTest::newRow("MTHI") << ALU_OP_MTHI \ << (std::uint32_t)43 \ << (std::uint32_t)0 \ << (std::uint8_t)0 \ << init \ << res \ << (std::uint32_t)0; res.write_hi_lo(true, 42); res.write_hi_lo(false, 23); QTest::newRow("MTLO") << ALU_OP_MTLO \ << (std::uint32_t)23 \ << (std::uint32_t)0 \ << (std::uint8_t)0 \ << init \ << res \ << (std::uint32_t)0; } QTest::newRow("ADD") << ALU_OP_ADD \ << (std::uint32_t)24 \ << (std::uint32_t)66 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)90; QTest::newRow("ADDU") << ALU_OP_ADDU \ << (std::uint32_t)24 \ << (std::uint32_t)66 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)90; QTest::newRow("SUB") << ALU_OP_SUB \ << (std::uint32_t)66 \ << (std::uint32_t)24 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)42; QTest::newRow("SUBU") << ALU_OP_SUBU \ << (std::uint32_t)24 \ << (std::uint32_t)66 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)-42; QTest::newRow("AND") << ALU_OP_AND \ << (std::uint32_t)0xA81 \ << (std::uint32_t)0x603 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)0x201; QTest::newRow("OR") << ALU_OP_OR \ << (std::uint32_t)0xA81 \ << (std::uint32_t)0x603 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)0xE83; QTest::newRow("XOR") << ALU_OP_XOR \ << (std::uint32_t)0xA81 \ << (std::uint32_t)0x603 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)0xC82; QTest::newRow("NOR") << ALU_OP_NOR \ << (std::uint32_t)0xA81 \ << (std::uint32_t)0x603 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)0xFFFFF17C; QTest::newRow("SLT") << ALU_OP_SLT \ << (std::uint32_t)-31 \ << (std::uint32_t)24 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)1; QTest::newRow("SLTU") << ALU_OP_SLTU \ << (std::uint32_t)24 \ << (std::uint32_t)32 \ << (std::uint8_t)0 \ << Registers() \ << Registers() \ << (std::uint32_t)1; } void MachineTests::alu() { QFETCH(AluOp, op); QFETCH(std::uint32_t, s); QFETCH(std::uint32_t, t); QFETCH(std::uint8_t, sa); QFETCH(Registers, regs_init); QFETCH(Registers, regs_res); QFETCH(std::uint32_t, res); QCOMPARE(alu_operate(op, s , t, sa, ®s_init), res); QCOMPARE(regs_res, regs_init); } void MachineTests::alu_except_data() { QTest::addColumn("op"); QTest::addColumn("s"); QTest::addColumn("t"); // Note no sa as shift unstruction has no exceptions QTest::newRow("ADD") << (std::uint8_t)ALU_OP_ADD \ << (std::uint32_t)0x8fffffff \ << (std::uint32_t)0x90000000; QTest::newRow("SUB") << (std::uint8_t)ALU_OP_SUB \ << (std::uint32_t)3 \ << (std::uint32_t)4; // Just test that we can throw unsupported ALU operation QTest::newRow("?") << (std::uint8_t)ALU_OP_LAST \ << (std::uint32_t)0 \ << (std::uint32_t)0; } void MachineTests::alu_except() { QFETCH(std::uint8_t, op); QFETCH(std::uint32_t, s); QFETCH(std::uint32_t, t); Registers regs; // Only runtime exception is expected as any other exception is a bug QVERIFY_EXCEPTION_THROWN(alu_operate((enum AluOp)op, s , t, 0, ®s), QtMipsExceptionRuntime); }