URL
https://opencores.org/ocsvn/s80186/s80186/trunk
Subversion Repositories s80186
[/] [s80186/] [trunk/] [tests/] [instructions/] [TestStringInterrupt.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" class StringIntTest : public EmulateFixture { public: void setup_nmi_handler(); void assert_nmi_taken(int return_offset); void inject_nmi(); }; void StringIntTest::setup_nmi_handler() { write_mem16(VEC_NMI + 2, 0x8000, CS); // CS write_mem16(VEC_NMI + 0, 0x0100, CS); // IP write_reg(SP, 0x100); } void StringIntTest::inject_nmi() { cpu->start_instruction(); // yield point inside the string instruction wait_for_int_yield(); cpu->raise_nmi(); cpu->complete_instruction(); } void StringIntTest::assert_nmi_taken(int return_offset) { EXPECT_PRED_FORMAT2(AssertFlagsEqual, read_flags() & (TF | IF), 0); EXPECT_EQ(read_reg(CS), 0x8000); EXPECT_EQ(read_reg(IP), 0x0100); EXPECT_EQ(read_reg(SP), 0x0100 - 6); EXPECT_EQ(read_mem16(0x100 - 4, SS), 0x0000); EXPECT_EQ(read_mem16(0x100 - 6, SS), 0x1000 + return_offset); } // These tests only run on the RTL CPU where we know that we can start single // stepping and then go through cycle by cycle and then inject an NMI. TEST_F(StringIntTest, ScasbInt) { setup_nmi_handler(); write_reg(AL, 0); write_reg(DI, 0x800); write_reg(CX, 0xff); write_cstring(0x800, "8086", ES); // repne scasb set_instruction({0xf2, 0xae}); inject_nmi(); ASSERT_EQ(read_reg(DI), 0x801); assert_nmi_taken(0); } TEST_F(StringIntTest, ScaswInt) { setup_nmi_handler(); 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}); inject_nmi(); ASSERT_EQ(read_reg(DI), 0x802); assert_nmi_taken(0); } TEST_F(StringIntTest, MovsbInt) { setup_nmi_handler(); 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({0x26, 0xf3, 0xa4}); inject_nmi(); ASSERT_EQ(read_reg(DI), 0x401); ASSERT_EQ(read_reg(SI), 0x801); ASSERT_EQ(read_reg(CX), 0x3); assert_nmi_taken(0); } TEST_F(StringIntTest, MovswInt) { setup_nmi_handler(); 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}); inject_nmi(); ASSERT_EQ(read_reg(DI), 0x402); ASSERT_EQ(read_reg(SI), 0x802); assert_nmi_taken(0); } TEST_F(StringIntTest, CmpsbInt) { setup_nmi_handler(); write_flags(0); write_reg(SI, 0x800); write_reg(DI, 0x400); write_reg(CX, 8); for (auto i = 0; i < 8; ++i) { write_mem8(0x400 + i, 0, ES); write_mem8(0x800 + i, 0); } write_vector8(0x800, {0, 1, 2, 4, 5, 6, 7}); write_vector8(0x400, {0, 1, 2, 4, 5, 6, 7}, ES); set_instruction({0xf3, 0xa6}); inject_nmi(); ASSERT_EQ(1, read_reg(SI) - 0x800); assert_nmi_taken(0); } TEST_F(StringIntTest, CmpswInt) { setup_nmi_handler(); write_flags(0); write_reg(SI, 0x800); write_reg(DI, 0x400); write_reg(CX, 4); for (auto i = 0; i < 8; ++i) { write_mem8(0x400 + i, 0, ES); write_mem8(0x800 + i, 0); } write_vector8(0x800, {0, 1, 2, 4, 5, 6, 7}); write_vector8(0x400, {0, 1, 2, 4, 5, 6, 7}, ES); set_instruction({0xf3, 0xa7}); inject_nmi(); ASSERT_EQ(2, read_reg(SI) - 0x800); assert_nmi_taken(0); } TEST_F(StringIntTest, LodsbInt) { setup_nmi_handler(); write_flags(0); write_reg(SI, 0x800); write_cstring(0x800, "foo"); write_reg(CX, 3); set_instruction({0xf2, 0xac}); inject_nmi(); ASSERT_EQ(read_reg(SI), 0x801); assert_nmi_taken(0); } TEST_F(StringIntTest, LodswInt) { setup_nmi_handler(); write_flags(0); write_reg(SI, 0x800); write_vector16(0x800, {0x1234, 0x5678}); write_reg(CX, 2); set_instruction({0xf2, 0xad}); inject_nmi(); ASSERT_EQ(read_reg(SI), 0x802); assert_nmi_taken(0); } TEST_F(StringIntTest, StosbInt) { setup_nmi_handler(); 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}); inject_nmi(); ASSERT_EQ(read_reg(DI), 0x801); assert_nmi_taken(0); } TEST_F(StringIntTest, StoswInt) { setup_nmi_handler(); 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}); inject_nmi(); ASSERT_EQ(read_reg(DI), 0x802); assert_nmi_taken(0); } TEST_F(StringIntTest, HltBlocks) { setup_nmi_handler(); write_flags(0); set_instruction({0xf4}); cpu->start_instruction(); // Skip over the opcode_fetch yield point wait_for_int_yield(); for (auto i = 0; i < 256; ++i) cpu->cycle_cpu(); cpu->raise_nmi(); cpu->complete_instruction(); assert_nmi_taken(1); }