URL
https://opencores.org/ocsvn/s80186/s80186/trunk
Subversion Repositories s80186
[/] [s80186/] [trunk/] [tests/] [instructions/] [TestDiv.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 <sstream> #include <vector> #include <gtest/gtest.h> #include "EmulateFixture.h" template <typename T1, typename T2> struct DivTest { T1 v1; T2 v2; T2 quotient; T2 remainder; }; using Div8Params = std::pair<const std::vector<uint8_t>, const std::vector<struct DivTest<uint16_t, uint8_t>>>; using Div16Params = std::pair<const std::vector<uint8_t>, const std::vector<struct DivTest<uint32_t, uint16_t>>>; using IDiv8Params = std::pair<const std::vector<uint8_t>, const std::vector<struct DivTest<int16_t, int8_t>>>; using IDiv16Params = std::pair<const std::vector<uint8_t>, const std::vector<struct DivTest<int32_t, int16_t>>>; static const std::vector<struct DivTest<uint16_t, uint8_t>> div8_tests = { {100, 20, 5, 0}, {500, 250, 2, 0}, {10, 3, 3, 1}, }; class DivReg8Test : public EmulateFixture, public ::testing::WithParamInterface<Div8Params> { }; TEST_P(DivReg8Test, Result) { auto params = GetParam(); for (auto &t : params.second) { reset(); SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " / " + std::to_string(static_cast<int>(t.v2))); write_reg(AX, t.v1); write_reg(BL, t.v2); // xDIV bl set_instruction(params.first); emulate(); ASSERT_EQ(read_reg(AL), t.quotient); ASSERT_EQ(read_reg(AH), t.remainder); } } INSTANTIATE_TEST_CASE_P(Div, DivReg8Test, ::testing::Values(Div8Params({0xf6, 0xf3}, div8_tests))); class DivMem8Test : public EmulateFixture, public ::testing::WithParamInterface<Div8Params> { }; TEST_P(DivMem8Test, Result) { auto params = GetParam(); for (auto &t : params.second) { reset(); SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " / " + std::to_string(static_cast<int>(t.v2))); write_reg(AX, t.v1); write_reg(BX, 0x100); write_mem8(0x100, t.v2); // xDIV byte [bx] set_instruction(params.first); emulate(); ASSERT_EQ(read_reg(AL), t.quotient); ASSERT_EQ(read_reg(AH), t.remainder); } } INSTANTIATE_TEST_CASE_P(Div, DivMem8Test, ::testing::Values(Div8Params({0xf6, 0x37}, div8_tests))); static const std::vector<struct DivTest<uint32_t, uint16_t>> div16_tests = { {1000, 200, 5, 0}, {500, 250, 2, 0}, {1000, 3, 333, 1}, {0x109, 0xe90b, 0, 265}, }; class DivReg16Test : public EmulateFixture, public ::testing::WithParamInterface<Div16Params> { }; TEST_P(DivReg16Test, Result) { auto params = GetParam(); for (auto &t : params.second) { reset(); SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " / " + std::to_string(static_cast<int>(t.v2))); write_reg(DX, (t.v1 >> 16) & 0xffff); write_reg(AX, t.v1); write_reg(BX, t.v2); // xDIV bx set_instruction(params.first); emulate(); ASSERT_EQ(read_reg(AX), t.quotient); ASSERT_EQ(read_reg(DX), t.remainder); } } INSTANTIATE_TEST_CASE_P(Div, DivReg16Test, ::testing::Values(Div16Params({0xf7, 0xf3}, div16_tests))); class DivMem16Test : public EmulateFixture, public ::testing::WithParamInterface<Div16Params> { }; TEST_P(DivMem16Test, Result) { auto params = GetParam(); for (auto &t : params.second) { reset(); SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " / " + std::to_string(static_cast<int>(t.v2))); write_reg(DX, (t.v1 >> 16) & 0xffff); write_reg(AX, t.v1); write_reg(BX, 0x100); write_mem16(0x100, t.v2); // xDIV word [bx] set_instruction(params.first); emulate(); ASSERT_EQ(read_reg(AX), t.quotient); ASSERT_EQ(read_reg(DX), t.remainder); } } INSTANTIATE_TEST_CASE_P(Div, DivMem16Test, ::testing::Values(Div16Params({0xf7, 0x37}, div16_tests))); static const std::vector<struct DivTest<int16_t, int8_t>> idiv8_tests = { { 250, 10, 25, 0, }, { 10, 3, 3, 1, }, { 10, -3, -3, 1, }, { -10, -3, 3, -1, }, { -10, 3, -3, -1, }, { 254, 2, 127, 0, }, }; class IDivReg8Test : public EmulateFixture, public ::testing::WithParamInterface<IDiv8Params> { }; TEST_P(IDivReg8Test, Result) { auto params = GetParam(); for (auto &t : params.second) { reset(); SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " / " + std::to_string(static_cast<int>(t.v2))); write_reg(AX, t.v1); write_reg(BL, t.v2); // xDIV bl set_instruction(params.first); emulate(); EXPECT_EQ(static_cast<int8_t>(read_reg(AL)), t.quotient); EXPECT_EQ(static_cast<int8_t>(read_reg(AH)), t.remainder); } } INSTANTIATE_TEST_CASE_P(IDiv, IDivReg8Test, ::testing::Values(IDiv8Params({0xf6, 0xfb}, idiv8_tests))); class IDivMem8Test : public EmulateFixture, public ::testing::WithParamInterface<IDiv8Params> { }; TEST_P(IDivMem8Test, Result) { auto params = GetParam(); for (auto &t : params.second) { reset(); SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " / " + std::to_string(static_cast<int>(t.v2))); write_reg(AX, t.v1); write_reg(BX, 0x100); write_mem8(0x100, t.v2); // xDIV byte [bx] set_instruction(params.first); emulate(); ASSERT_EQ(static_cast<int8_t>(read_reg(AL)), t.quotient); ASSERT_EQ(static_cast<int8_t>(read_reg(AH)), t.remainder); } } INSTANTIATE_TEST_CASE_P(IDiv, IDivMem8Test, ::testing::Values(IDiv8Params({0xf6, 0x3f}, idiv8_tests))); static const std::vector<struct DivTest<int32_t, int16_t>> idiv16_tests = { {10, 3, 3, 1}, {10, -3, -3, 1}, {-10, -3, 3, -1}, {-10, 3, -3, -1}, {65534, 2, 32767, 0}, }; class IDivReg16Test : public EmulateFixture, public ::testing::WithParamInterface<IDiv16Params> { }; TEST_P(IDivReg16Test, Result) { auto params = GetParam(); for (auto &t : params.second) { reset(); SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " / " + std::to_string(static_cast<int>(t.v2))); write_reg(DX, (t.v1 >> 16) & 0xffff); write_reg(AX, t.v1); write_reg(BX, t.v2); // xDIV bx set_instruction(params.first); emulate(); EXPECT_EQ(static_cast<int16_t>(read_reg(AX)), t.quotient); EXPECT_EQ(static_cast<int16_t>(read_reg(DX)), t.remainder); } } INSTANTIATE_TEST_CASE_P(IDiv, IDivReg16Test, ::testing::Values(IDiv16Params({0xf7, 0xfb}, idiv16_tests))); class IDivMem16Test : public EmulateFixture, public ::testing::WithParamInterface<IDiv16Params> { }; TEST_P(IDivMem16Test, Result) { auto params = GetParam(); for (auto &t : params.second) { reset(); SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " / " + std::to_string(static_cast<int>(t.v2))); write_reg(DX, (t.v1 >> 16) & 0xffff); write_reg(AX, t.v1); write_reg(BX, 0x100); write_mem16(0x100, t.v2); // xDIV word [bx] set_instruction(params.first); emulate(); ASSERT_EQ(static_cast<int16_t>(read_reg(AX)), t.quotient); ASSERT_EQ(static_cast<int16_t>(read_reg(DX)), t.remainder); } } INSTANTIATE_TEST_CASE_P(IDiv, IDivMem16Test, ::testing::Values(IDiv16Params({0xf7, 0x3f}, idiv16_tests)));