URL
https://opencores.org/ocsvn/s80186/s80186/trunk
Subversion Repositories s80186
[/] [s80186/] [trunk/] [tests/] [instructions/] [TestString.cpp] - Rev 2
Compare with Previous | Blame | View Log
// Copyright Jamie Iles, 2017 // // This file is part of s80x86. // // s80x86 is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // s80x86 is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with s80x86. If not, see <http://www.gnu.org/licenses/>. #include <gtest/gtest.h> #include "EmulateFixture.h" #include "Flags.h" TEST_F(EmulateFixture, ScasbNoRep) { write_reg(AL, 0); write_reg(DI, 0x800); write_reg(CX, 0xff); write_cstring(0x800, "8086", ES); // repne scasb set_instruction({0xae}); emulate(); ASSERT_EQ(read_reg(DI), 0x801); ASSERT_PRED_FORMAT2(AssertFlagsEqual, read_flags(), FLAGS_STUCK_BITS | CF | AF | SF); } TEST_F(EmulateFixture, ScasbInc) { write_reg(AL, 0); write_reg(DI, 0x800); write_reg(CX, 0xff); write_cstring(0x800, "8086", ES); // repne scasb set_instruction({0xf2, 0xae}); emulate(); ASSERT_EQ(read_reg(DI), 0x805); } TEST_F(EmulateFixture, ScasbDec) { write_flags(DF); write_reg(AL, '1'); write_reg(DI, 0x803); write_reg(CX, 0xff); write_cstring(0x800, "1234", ES); // repne scasb set_instruction({0xf2, 0xae}); emulate(); ASSERT_EQ(read_reg(DI), 0x7ff); } TEST_F(EmulateFixture, ScasbIncRepe) { write_reg(AL, 'a'); write_reg(DI, 0x800); write_reg(CX, 0xff); write_cstring(0x800, "aaab", ES); // repe scasb set_instruction({0xf3, 0xae}); emulate(); ASSERT_EQ(read_reg(DI), 0x804); } TEST_F(EmulateFixture, ScasbDecRepe) { write_flags(DF); write_reg(AL, 'b'); write_reg(DI, 0x803); write_reg(CX, 0xff); write_cstring(0x800, "abbb", ES); // repe scasb set_instruction({0xf3, 0xae}); emulate(); ASSERT_EQ(read_reg(DI), 0x7ff); } TEST_F(EmulateFixture, ScaswNoRep) { write_reg(AX, 0); write_reg(DI, 0x800); write_reg(CX, 0xff); for (int i = 0; i < 2; ++i) write_mem16(0x800 + i * 2, 0xaa55, ES); write_mem16(0x800 + 2 * 2, 0x0000, ES); // scasw set_instruction({0xaf}); emulate(); ASSERT_EQ(read_reg(DI), 0x802); ASSERT_PRED_FORMAT2(AssertFlagsEqual, read_flags(), FLAGS_STUCK_BITS | CF | AF); } TEST_F(EmulateFixture, ScaswInc) { write_reg(AX, 0); write_reg(DI, 0x800); write_reg(CX, 0xff); for (int i = 0; i < 2; ++i) write_mem16(0x800 + i * 2, 0xaa55, ES); write_mem16(0x800 + 2 * 2, 0x0000, ES); // repne scasw set_instruction({0xf2, 0xaf}); emulate(); ASSERT_EQ(read_reg(DI), 0x806); } TEST_F(EmulateFixture, ScaswDec) { write_flags(DF); write_reg(AX, 0); write_reg(DI, 0x806); write_reg(CX, 0xff); for (int i = 0; i < 4; ++i) write_mem16(0x800 + i * 2, 0xaa55, ES); write_mem16(0x800 + 4 * 2, 0x0000, ES); write_mem16(0x7fe, 0x0000, ES); // repne scasw set_instruction({0xf2, 0xaf}); emulate(); ASSERT_EQ(read_reg(DI), 0x7fc); } TEST_F(EmulateFixture, ScaswIncRepe) { write_reg(AX, 0xaa55); write_reg(DI, 0x800); write_reg(CX, 0xff); for (int i = 0; i < 4; ++i) write_mem16(0x800 + i * 2, 0xaa55, ES); // repe scasw set_instruction({0xf3, 0xaf}); emulate(); ASSERT_EQ(read_reg(DI), 0x80a); } TEST_F(EmulateFixture, ScaswDecRepe) { write_flags(DF); write_reg(AX, 0xaa55); write_reg(DI, 0x806); write_reg(CX, 0xff); for (int i = 0; i < 4; ++i) write_mem16(0x800 + i * 2, 0xaa55, ES); // repe scasw set_instruction({0xf3, 0xaf}); emulate(); ASSERT_EQ(read_reg(DI), 0x7fc); } TEST_F(EmulateFixture, MovsbInc) { write_reg(AL, 0); write_reg(SI, 0x800); write_reg(DI, 0x400); write_reg(CX, 0x4); write_cstring(0x800, "8086"); write_mem8(0x404, 0, ES); // repne movsb set_instruction({0xf3, 0xa4}); emulate(); ASSERT_EQ(read_reg(DI), 0x404); ASSERT_EQ(read_reg(SI), 0x804); ASSERT_EQ(read_cstring(0x400, ES), "8086"); } TEST_F(EmulateFixture, MovsbDec) { write_flags(DF); write_reg(AL, 0); write_reg(SI, 0x803); write_reg(DI, 0x403); write_reg(CX, 0x4); write_cstring(0x800, "8086"); write_mem8(0x404, 0, ES); // repne movsb set_instruction({0xf3, 0xa4}); emulate(); ASSERT_EQ(read_reg(DI), 0x3ff); ASSERT_EQ(read_reg(SI), 0x7ff); ASSERT_EQ(read_cstring(0x400, ES), "8086"); } TEST_F(EmulateFixture, MovswInc) { write_reg(AL, 0); write_reg(SI, 0x800); write_reg(DI, 0x400); write_reg(CX, 0x2); write_mem16(0x800, 0xaa55); write_mem16(0x802, 0x55aa); // repne movsw set_instruction({0xf3, 0xa5}); emulate(); ASSERT_EQ(read_reg(DI), 0x404); ASSERT_EQ(read_reg(SI), 0x804); ASSERT_EQ(read_mem16(0x400, ES), 0xaa55); ASSERT_EQ(read_mem16(0x402, ES), 0x55aa); } TEST_F(EmulateFixture, MovswDec) { write_flags(DF); write_reg(AL, 0); write_reg(SI, 0x802); write_reg(DI, 0x402); write_reg(CX, 0x2); write_mem16(0x800, 0xaa55); write_mem16(0x802, 0x55aa); // repne movsw set_instruction({0xf3, 0xa5}); emulate(); ASSERT_EQ(read_reg(DI), 0x3fe); ASSERT_EQ(read_reg(SI), 0x7fe); ASSERT_EQ(read_mem16(0x400, ES), 0xaa55); ASSERT_EQ(read_mem16(0x402, ES), 0x55aa); } template <typename T> struct CmpsTest { std::vector<T> src; std::vector<T> dst; uint16_t expected_flags; uint8_t prefix; uint8_t expected_length; }; using Cmps8Test = struct CmpsTest<uint8_t>; using Cmps16Test = struct CmpsTest<uint16_t>; class Cmps8Fixture : public EmulateFixture, public ::testing::WithParamInterface<Cmps8Test> { }; TEST_P(Cmps8Fixture, Flags) { auto p = GetParam(); write_flags(0); write_reg(SI, 0x800); write_reg(DI, 0x400); write_reg(CX, std::max(p.src.size() + 1, p.dst.size() + 1)); for (auto i = 0; i < 32; ++i) { write_mem8(0x400 + i, 0, ES); write_mem8(0x800 + i, 0); } write_vector8(0x800, p.src); write_vector8(0x400, p.dst, ES); set_instruction({p.prefix, 0xa6}); emulate(); ASSERT_PRED_FORMAT2(AssertFlagsEqual, read_flags(), FLAGS_STUCK_BITS | p.expected_flags); ASSERT_EQ(p.expected_length, read_reg(SI) - 0x800); } INSTANTIATE_TEST_CASE_P( CmpsRepe, Cmps8Fixture, ::testing::Values(Cmps8Test{std::vector<uint8_t>{'f', 'o', 'o'}, std::vector<uint8_t>{'f', 'o', 'o'}, ZF | PF, 0xf3, 4}, Cmps8Test{std::vector<uint8_t>{'a'}, std::vector<uint8_t>{'b'}, SF | PF | CF | AF, 0xf3, 1}, Cmps8Test{std::vector<uint8_t>{'b'}, std::vector<uint8_t>{'a'}, 0, 0xf3, 1}, Cmps8Test{std::vector<uint8_t>{'b'}, std::vector<uint8_t>{}, 0, 0xf3, 1})); INSTANTIATE_TEST_CASE_P( CmpsRepne, Cmps8Fixture, ::testing::Values( Cmps8Test{std::vector<uint8_t>{'b', 'a', 'r'}, std::vector<uint8_t>{'b', 'a', 'r'}, ZF | PF, 0xf2, 1}, Cmps8Test{std::vector<uint8_t>{'b', 'a', 'r'}, std::vector<uint8_t>{'f', 'o', 'o'}, ZF | PF, 0xf2, 4}, Cmps8Test{std::vector<uint8_t>{'b', 'a', 'r'}, std::vector<uint8_t>{'f', 'o', 'r'}, ZF | PF, 0xf2, 3}, Cmps8Test{std::vector<uint8_t>{'b', 'a', 'r'}, std::vector<uint8_t>{'c'}, ZF | PF, 0xf2, 4})); TEST_F(EmulateFixture, CmpsbDec) { write_flags(DF); write_reg(SI, 0x800); write_reg(DI, 0x400); write_mem8(0x800, 'f'); write_mem8(0x400, 'g', ES); set_instruction({0xa6}); emulate(); ASSERT_PRED_FORMAT2(AssertFlagsEqual, read_flags(), FLAGS_STUCK_BITS | SF | PF | CF | DF | AF); ASSERT_EQ(read_reg(SI), 0x7ff); ASSERT_EQ(read_reg(DI), 0x3ff); } class Cmps16Fixture : public EmulateFixture, public ::testing::WithParamInterface<Cmps16Test> { }; TEST_P(Cmps16Fixture, Flags) { auto p = GetParam(); write_flags(0); write_reg(SI, 0x800); write_reg(DI, 0x400); write_reg(CX, std::max(p.src.size() + 1, p.dst.size() + 1)); for (auto i = 0; i < 32; ++i) { write_mem16(0x400 + i, 0, ES); write_mem16(0x800 + i, 0); } write_vector16(0x800, p.src); write_vector16(0x400, p.dst, ES); set_instruction({p.prefix, 0xa7}); emulate(); ASSERT_PRED_FORMAT2(AssertFlagsEqual, read_flags(), FLAGS_STUCK_BITS | p.expected_flags); ASSERT_EQ(p.expected_length, read_reg(SI) - 0x800); } INSTANTIATE_TEST_CASE_P( CmpsRepe, Cmps16Fixture, ::testing::Values(Cmps16Test{std::vector<uint16_t>{0xaa55, 0xaa56, 0xaa57}, std::vector<uint16_t>{0xaa55, 0xaa56, 0xaa57}, ZF | PF, 0xf3, 8}, Cmps16Test{std::vector<uint16_t>{0x1000}, std::vector<uint16_t>{0x2000}, SF | PF | CF, 0xf3, 2}, Cmps16Test{std::vector<uint16_t>{0x2000}, std::vector<uint16_t>{0x1000}, PF, 0xf3, 2}, Cmps16Test{std::vector<uint16_t>{0x2000}, std::vector<uint16_t>{}, PF, 0xf3, 2})); INSTANTIATE_TEST_CASE_P( CmpsRepne, Cmps16Fixture, ::testing::Values(Cmps16Test{std::vector<uint16_t>{0xaa55, 0xaa56, 0xaa57}, std::vector<uint16_t>{0xaa55, 0xaa56, 0xaa57}, ZF | PF, 0xf2, 2}, Cmps16Test{std::vector<uint16_t>{0xaa55, 0xaa56, 0xaa57}, std::vector<uint16_t>{0x55aa, 0x55ab, 0x55ac}, ZF | PF, 0xf2, 8}, Cmps16Test{std::vector<uint16_t>{0xaa55, 0xaa56, 0xaa57}, std::vector<uint16_t>{0x55aa, 0x55aa, 0xaa57}, ZF | PF, 0xf2, 6}, Cmps16Test{std::vector<uint16_t>{0xaa55, 0xaa56, 0xaa57}, std::vector<uint16_t>{0x1234}, ZF | PF, 0xf2, 8})); TEST_F(EmulateFixture, CmpswDec) { write_flags(DF); write_reg(SI, 0x800); write_reg(DI, 0x400); write_mem16(0x800, 0xaa55); write_mem16(0x400, 0xaa56, ES); set_instruction({0xa7}); emulate(); ASSERT_PRED_FORMAT2(AssertFlagsEqual, read_flags(), FLAGS_STUCK_BITS | SF | PF | CF | DF | AF); ASSERT_EQ(read_reg(SI), 0x7fe); ASSERT_EQ(read_reg(DI), 0x3fe); } TEST_F(EmulateFixture, Lodsb) { write_flags(0); write_reg(SI, 0x800); write_cstring(0x800, "foo"); write_reg(CX, 3); set_instruction({0xf2, 0xac}); emulate(); ASSERT_EQ(read_reg(AL), 'o'); ASSERT_EQ(read_reg(SI), 0x803); } TEST_F(EmulateFixture, Lodsw) { write_flags(0); write_reg(SI, 0x800); write_vector16(0x800, {0x1234, 0x5678}); write_reg(CX, 2); set_instruction({0xf2, 0xad}); emulate(); ASSERT_EQ(read_reg(AX), 0x5678); ASSERT_EQ(read_reg(SI), 0x804); } TEST_F(EmulateFixture, LodsbDec) { write_flags(DF); write_reg(SI, 0x802); write_cstring(0x800, "foo"); write_reg(CX, 3); set_instruction({0xf2, 0xac}); emulate(); ASSERT_EQ(read_reg(AL), 'f'); ASSERT_EQ(read_reg(SI), 0x7ff); } TEST_F(EmulateFixture, LodswDec) { write_flags(DF); write_reg(SI, 0x802); write_vector16(0x800, {0x1234, 0x5678}); write_reg(CX, 2); set_instruction({0xf2, 0xad}); emulate(); ASSERT_EQ(read_reg(AX), 0x1234); ASSERT_EQ(read_reg(SI), 0x7fe); } TEST_F(EmulateFixture, Stosb) { write_flags(0); write_reg(DI, 0x800); write_mem8(0x803, 0); write_reg(AL, 'a'); write_reg(CX, 3); write_vector8(0x800, {0, 0, 0, 0, 0, 0, 0, 0}, ES); set_instruction({0xf2, 0xaa}); emulate(); ASSERT_EQ(read_reg(DI), 0x803); ASSERT_EQ(read_cstring(0x800, ES), "aaa"); } TEST_F(EmulateFixture, StosbDec) { write_flags(DF); write_reg(DI, 0x802); write_mem8(0x803, 0); write_reg(AL, 'a'); write_reg(CX, 3); set_instruction({0xf2, 0xaa}); write_vector8(0x800, {0, 0, 0, 0, 0, 0, 0, 0}, ES); emulate(); ASSERT_EQ(read_reg(DI), 0x7ff); ASSERT_EQ(read_cstring(0x800, ES), "aaa"); } TEST_F(EmulateFixture, Stosw) { write_flags(0); write_reg(DI, 0x800); write_reg(AX, 0x6261); write_mem16(0x806, 0x0000); write_reg(CX, 3); write_vector16(0x800, {0, 0, 0, 0, 0, 0, 0, 0}, ES); set_instruction({0xf2, 0xab}); emulate(); ASSERT_EQ(read_reg(DI), 0x806); ASSERT_EQ(read_cstring(0x800, ES), "ababab"); } TEST_F(EmulateFixture, StoswDec) { write_flags(DF); write_reg(DI, 0x804); write_mem16(0x806, 0x0000); write_reg(AX, 0x6261); write_reg(CX, 3); write_vector16(0x800, {0, 0, 0, 0, 0, 0, 0, 0}, ES); set_instruction({0xf2, 0xab}); emulate(); ASSERT_EQ(read_reg(DI), 0x7fe); ASSERT_EQ(read_cstring(0x800, ES), "ababab"); }