OpenCores
URL https://opencores.org/ocsvn/s80186/s80186/trunk

Subversion Repositories s80186

[/] [s80186/] [trunk/] [tests/] [instructions/] [TestMul.cpp] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jamieiles
// Copyright Jamie Iles, 2017
2
//
3
// This file is part of s80x86.
4
//
5
// s80x86 is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
//
10
// s80x86 is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
//
15
// You should have received a copy of the GNU General Public License
16
// along with s80x86.  If not, see <http://www.gnu.org/licenses/>.
17
 
18
#include <sstream>
19
#include <vector>
20
#include <gtest/gtest.h>
21
 
22
#include "EmulateFixture.h"
23
#include "Flags.h"
24
 
25
template <typename T>
26
struct MulTest {
27
    T v1;
28
    T v2;
29
    T expected;
30
    T expected_hi;
31
    uint16_t expected_flags;
32
};
33
 
34
using Mul8Params = std::pair<const std::vector<uint8_t>,
35
                             const std::vector<struct MulTest<uint8_t>>>;
36
using Mul16Params = std::pair<const std::vector<uint8_t>,
37
                              const std::vector<struct MulTest<uint16_t>>>;
38
 
39
static const std::vector<struct MulTest<uint8_t>> mul8_tests = {
40
    {0, 0, 0, 0x00, 0}, {0xff, 0, 0, 0x00, 0}, {0, 0xff, 0, 0x00, 0},
41
        {2, 8, 16, 0x00, 0}, {0x80, 2, 0x00, 0x01, CF | OF},
42
        {0xff, 0xff, 0x01, 0xfe, CF | OF},
43
};
44
 
45
static const std::vector<struct MulTest<uint8_t>> imul8_tests = {
46
    {0, 0, 0, 0x00, 0}, {0xff, 0, 0, 0x00, 0}, {0, 0xff, 0, 0x00, 0},
47
        {2, 8, 16, 0x00, 0}, {0x80, 2, 0x00, 0xff, CF | OF},
48
        {0xff, 0xff, 0x01, 0x00, 0}, {0xff, 1, 0xff, 0xff, CF | OF},
49
        {32, 8, 0x00, 0x01, CF | OF},
50
};
51
 
52
class MulReg8Test : public EmulateFixture,
53
                    public ::testing::WithParamInterface<Mul8Params>
54
{
55
};
56
TEST_P(MulReg8Test, ResultAndFlags)
57
{
58
    auto params = GetParam();
59
    for (auto &t : params.second) {
60
        reset();
61
 
62
        SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " * " +
63
                     std::to_string(static_cast<int>(t.v2)));
64
        write_flags(0);
65
        write_reg(AL, t.v1);
66
        write_reg(BL, t.v2);
67
        // xMUL bl
68
        set_instruction(params.first);
69
 
70
        emulate();
71
 
72
        ASSERT_EQ(read_reg(AL), t.expected);
73
        ASSERT_EQ(read_reg(AH), t.expected_hi);
74
        ASSERT_PRED_FORMAT2(AssertFlagsEqual, read_flags(),
75
                            FLAGS_STUCK_BITS | t.expected_flags);
76
    }
77
}
78
INSTANTIATE_TEST_CASE_P(Mul,
79
                        MulReg8Test,
80
                        ::testing::Values(Mul8Params({0xf6, 0xe3},
81
                                                     mul8_tests)));
82
INSTANTIATE_TEST_CASE_P(IMul,
83
                        MulReg8Test,
84
                        ::testing::Values(Mul8Params({0xf6, 0xeb},
85
                                                     imul8_tests)));
86
 
87
class MulMem8Test : public EmulateFixture,
88
                    public ::testing::WithParamInterface<Mul8Params>
89
{
90
};
91
TEST_P(MulMem8Test, ResultAndFlags)
92
{
93
    auto params = GetParam();
94
    for (auto &t : params.second) {
95
        reset();
96
 
97
        SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " * " +
98
                     std::to_string(static_cast<int>(t.v2)));
99
        write_flags(0);
100
        write_reg(AL, t.v2);
101
        write_reg(BX, 0x100);
102
        write_mem8(0x100, t.v1);
103
 
104
        // xMUL byte [bx]
105
        set_instruction(params.first);
106
 
107
        emulate();
108
 
109
        ASSERT_EQ(read_reg(AL), t.expected);
110
        ASSERT_EQ(read_reg(AH), t.expected_hi);
111
        ASSERT_PRED_FORMAT2(AssertFlagsEqual, read_flags(),
112
                            FLAGS_STUCK_BITS | t.expected_flags);
113
    }
114
}
115
INSTANTIATE_TEST_CASE_P(Mul,
116
                        MulMem8Test,
117
                        ::testing::Values(Mul8Params({0xf6, 0x27},
118
                                                     mul8_tests)));
119
INSTANTIATE_TEST_CASE_P(IMul,
120
                        MulMem8Test,
121
                        ::testing::Values(Mul8Params({0xf6, 0x2f},
122
                                                     imul8_tests)));
123
 
124
static const std::vector<struct MulTest<uint16_t>> mul16_tests = {
125
    {0, 0, 0, 0x00, 0}, {0xff, 0, 0, 0x00, 0}, {0, 0xff, 0, 0x00, 0},
126
        {2, 8, 16, 0x00, 0}, {0x80, 2, 0x100, 0x00, 0},
127
        {0x8000, 2, 0x0000, 0x0001, CF | OF},
128
        {0xffff, 0xffff, 0x0001, 0xfffe, CF | OF},
129
};
130
 
131
static const std::vector<struct MulTest<uint16_t>> imul16_tests = {
132
    {0, 0, 0, 0x00, 0}, {0xff, 0, 0, 0x00, 0}, {0, 0xff, 0, 0x00, 0},
133
        {2, 8, 16, 0x00, 0}, {0x8000, 2, 0x0000, 0xffff, CF | OF},
134
        {0xffff, 0xffff, 0x0001, 0x0000, 0},
135
        {0xffff, 1, 0xffff, 0xffff, CF | OF},
136
        {8192, 8, 0x0000, 0x0001, CF | OF},
137
};
138
 
139
class MulReg16Test : public EmulateFixture,
140
                     public ::testing::WithParamInterface<Mul16Params>
141
{
142
};
143
TEST_P(MulReg16Test, ResultAndFlags)
144
{
145
    auto params = GetParam();
146
    for (auto &t : params.second) {
147
        reset();
148
 
149
        SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " * " +
150
                     std::to_string(static_cast<int>(t.v2)));
151
        write_flags(0);
152
        write_reg(AX, t.v1);
153
        write_reg(BX, t.v2);
154
        // xMUL bx
155
        set_instruction(params.first);
156
 
157
        emulate();
158
 
159
        ASSERT_EQ(read_reg(AX), t.expected);
160
        ASSERT_EQ(read_reg(DX), t.expected_hi);
161
        ASSERT_PRED_FORMAT2(AssertFlagsEqual, read_flags(),
162
                            FLAGS_STUCK_BITS | t.expected_flags);
163
    }
164
}
165
INSTANTIATE_TEST_CASE_P(Mul,
166
                        MulReg16Test,
167
                        ::testing::Values(Mul16Params({0xf7, 0xe3},
168
                                                      mul16_tests)));
169
INSTANTIATE_TEST_CASE_P(IMul,
170
                        MulReg16Test,
171
                        ::testing::Values(Mul16Params({0xf7, 0xeb},
172
                                                      imul16_tests)));
173
 
174
class MulMem16Test : public EmulateFixture,
175
                     public ::testing::WithParamInterface<Mul16Params>
176
{
177
};
178
TEST_P(MulMem16Test, ResultAndFlags)
179
{
180
    auto params = GetParam();
181
    for (auto &t : params.second) {
182
        reset();
183
 
184
        SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " * " +
185
                     std::to_string(static_cast<int>(t.v2)));
186
        write_flags(0);
187
        write_reg(AX, t.v2);
188
        write_reg(BX, 0x100);
189
        write_mem16(0x100, t.v1);
190
 
191
        // xMUL word [bx]
192
        set_instruction(params.first);
193
 
194
        emulate();
195
 
196
        ASSERT_EQ(read_reg(AX), t.expected);
197
        ASSERT_EQ(read_reg(DX), t.expected_hi);
198
        ASSERT_PRED_FORMAT2(AssertFlagsEqual, read_flags(),
199
                            FLAGS_STUCK_BITS | t.expected_flags);
200
    }
201
}
202
INSTANTIATE_TEST_CASE_P(Mul,
203
                        MulMem16Test,
204
                        ::testing::Values(Mul16Params({0xf7, 0x27},
205
                                                      mul16_tests)));
206
INSTANTIATE_TEST_CASE_P(IMul,
207
                        MulMem16Test,
208
                        ::testing::Values(Mul16Params({0xf7, 0x2f},
209
                                                      imul16_tests)));
210
 
211
template <typename T>
212
struct MulImmTest {
213
    uint16_t v1;
214
    T v2;
215
    uint16_t expected;
216
    uint16_t expected_flags;
217
};
218
 
219
using MulImm8Params = struct MulImmTest<uint8_t>;
220
using MulImm16Params = struct MulImmTest<uint16_t>;
221
 
222
class MulImmReg8Test : public EmulateFixture,
223
                       public ::testing::WithParamInterface<MulImm8Params>
224
{
225
};
226
TEST_P(MulImmReg8Test, ResultAndFlags)
227
{
228
    auto t = GetParam();
229
 
230
    SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " * " +
231
                 std::to_string(static_cast<int>(t.v2)));
232
    write_flags(0);
233
    write_reg(BX, t.v1);
234
    // IMUL ax, bx, IMM8
235
    auto instr = std::vector<uint8_t>{0x6b, 0xc3};
236
    instr.push_back(t.v2);
237
    set_instruction(instr);
238
 
239
    emulate();
240
 
241
    EXPECT_EQ(read_reg(AX), t.expected);
242
    EXPECT_PRED_FORMAT2(AssertFlagsEqual, read_flags(),
243
                        FLAGS_STUCK_BITS | t.expected_flags);
244
}
245
INSTANTIATE_TEST_CASE_P(
246
    IMul,
247
    MulImmReg8Test,
248
    ::testing::Values(MulImm8Params{0, 0, 0, 0},
249
                      MulImm8Params{0xff, 0, 0, 0},
250
                      MulImm8Params{0, 0xff, 0, 0},
251
                      MulImm8Params{2, 8, 16, 0},
252
                      MulImm8Params{0x8000, 2, 0x0000, CF | OF},
253
                      MulImm8Params{0xffff, 0xff, 0x0001, 0},
254
                      MulImm8Params{0xffff, 1, 0xffff, CF | OF},
255
                      MulImm8Params{8192, 8, 0x0000, CF | OF}));
256
 
257
class MulImmMem8Test : public EmulateFixture,
258
                       public ::testing::WithParamInterface<MulImm8Params>
259
{
260
};
261
TEST_P(MulImmMem8Test, ResultAndFlags)
262
{
263
    auto t = GetParam();
264
 
265
    SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " * " +
266
                 std::to_string(static_cast<int>(t.v2)));
267
    write_flags(0);
268
    write_reg(BX, 0x100);
269
    write_mem16(0x100, t.v1);
270
    // IMUL ax, [bx], IMM8
271
    auto instr = std::vector<uint8_t>{0x6b, 0x07};
272
    instr.push_back(t.v2);
273
    set_instruction(instr);
274
 
275
    emulate();
276
 
277
    EXPECT_EQ(read_reg(AX), t.expected);
278
    EXPECT_PRED_FORMAT2(AssertFlagsEqual, read_flags(),
279
                        FLAGS_STUCK_BITS | t.expected_flags);
280
}
281
INSTANTIATE_TEST_CASE_P(
282
    IMul,
283
    MulImmMem8Test,
284
    ::testing::Values(MulImm8Params{0, 0, 0, 0},
285
                      MulImm8Params{0xff, 0, 0, 0},
286
                      MulImm8Params{0, 0xff, 0, 0},
287
                      MulImm8Params{2, 8, 16, 0},
288
                      MulImm8Params{0x8000, 2, 0x0000, CF | OF},
289
                      MulImm8Params{0xffff, 0xff, 0x0001, 0},
290
                      MulImm8Params{0xffff, 1, 0xffff, CF | OF},
291
                      MulImm8Params{8192, 8, 0x0000, CF | OF}));
292
 
293
class MulImmReg16Test : public EmulateFixture,
294
                        public ::testing::WithParamInterface<MulImm16Params>
295
{
296
};
297
TEST_P(MulImmReg16Test, ResultAndFlags)
298
{
299
    auto t = GetParam();
300
 
301
    SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " * " +
302
                 std::to_string(static_cast<int>(t.v2)));
303
    write_flags(0);
304
    write_reg(BX, t.v1);
305
    // IMUL ax, bx, IMM16
306
    auto instr = std::vector<uint8_t>{0x69, 0xc3};
307
    instr.push_back(t.v2 & 0xff);
308
    instr.push_back(t.v2 >> 8);
309
    set_instruction(instr);
310
 
311
    emulate();
312
 
313
    EXPECT_EQ(read_reg(AX), t.expected);
314
    EXPECT_PRED_FORMAT2(AssertFlagsEqual, read_flags(),
315
                        FLAGS_STUCK_BITS | t.expected_flags);
316
}
317
INSTANTIATE_TEST_CASE_P(
318
    IMul,
319
    MulImmReg16Test,
320
    ::testing::Values(MulImm16Params{0, 0, 0, 0},
321
                      MulImm16Params{0xff, 0, 0, 0},
322
                      MulImm16Params{0, 0xff, 0, 0},
323
                      MulImm16Params{2, 8, 16, 0},
324
                      MulImm16Params{0x8000, 2, 0x0000, CF | OF},
325
                      MulImm16Params{0xffff, 0xffff, 0x0001, 0},
326
                      MulImm16Params{0xffff, 1, 0xffff, CF | OF},
327
                      MulImm16Params{8192, 8, 0x0000, CF | OF}));
328
 
329
class MulImmMem16Test : public EmulateFixture,
330
                        public ::testing::WithParamInterface<MulImm16Params>
331
{
332
};
333
TEST_P(MulImmMem16Test, ResultAndFlags)
334
{
335
    auto t = GetParam();
336
 
337
    SCOPED_TRACE(std::to_string(static_cast<int>(t.v1)) + " * " +
338
                 std::to_string(static_cast<int>(t.v2)));
339
    write_flags(0);
340
    write_reg(BX, 0x100);
341
    write_mem16(0x100, t.v1);
342
    // IMUL ax, [bx], IMM16
343
    auto instr = std::vector<uint8_t>{0x69, 0x07};
344
    instr.push_back(t.v2 & 0xff);
345
    instr.push_back(t.v2 >> 8);
346
    set_instruction(instr);
347
 
348
    emulate();
349
 
350
    EXPECT_EQ(read_reg(AX), t.expected);
351
    EXPECT_PRED_FORMAT2(AssertFlagsEqual, read_flags(),
352
                        FLAGS_STUCK_BITS | t.expected_flags);
353
}
354
INSTANTIATE_TEST_CASE_P(
355
    IMul,
356
    MulImmMem16Test,
357
    ::testing::Values(MulImm16Params{0, 0, 0, 0},
358
                      MulImm16Params{0xff, 0, 0, 0},
359
                      MulImm16Params{0, 0xff, 0, 0},
360
                      MulImm16Params{2, 8, 16, 0},
361
                      MulImm16Params{0x8000, 2, 0x0000, CF | OF},
362
                      MulImm16Params{0xffff, 0xffff, 0x0001, 0},
363
                      MulImm16Params{0xffff, 1, 0xffff, CF | OF},
364
                      MulImm16Params{8192, 8, 0x0000, CF | OF}));

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.