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

Subversion Repositories s80186

[/] [s80186/] [trunk/] [tests/] [include/] [EmulateFixture.h] - 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
#pragma once
19
 
20
#include <memory>
21
#include <vector>
22
#include <gtest/gtest.h>
23
 
24
#include <cassert>
25
#include "CPU.h"
26
#include "TestUtils.h"
27
 
28
extern std::unique_ptr<CPU> get_cpu(const std::string &test_name);
29
 
30
class DummyIO : public IOPorts
31
{
32
public:
33
    DummyIO(uint16_t addr, size_t num_ports) : IOPorts(addr, num_ports), val(0)
34
    {
35
    }
36
 
37
    uint8_t read8(uint16_t port_num, unsigned offs)
38
    {
39
        (void)port_num;
40
        return (val >> (offs * 8)) & 0xff;
41
    }
42
 
43
    uint16_t read16(uint16_t port_num)
44
    {
45
        (void)port_num;
46
        return val;
47
    }
48
 
49
    void write8(uint16_t port_num, unsigned offs, uint8_t v)
50
    {
51
        (void)port_num;
52
        uint16_t mask = 0xff << (8 * offs);
53
 
54
        val &= ~mask;
55
        val |= (static_cast<uint16_t>(v) << (8 * offs));
56
 
57
        write_vals.push_back(static_cast<uint16_t>(v) << (8 * offs));
58
    }
59
 
60
    void write16(uint16_t port_num, uint16_t v)
61
    {
62
        (void)port_num;
63
        val = v;
64
 
65
        write_vals.push_back(v);
66
    }
67
 
68
    std::vector<uint16_t> get_write_vals() const
69
    {
70
        return write_vals;
71
    }
72
 
73
private:
74
    uint16_t val;
75
    std::vector<uint16_t> write_vals;
76
};
77
 
78
class EmulateFixture : public ::testing::Test
79
{
80
public:
81
    EmulateFixture()
82
        : cpu(get_cpu(current_test_name())),
83
          io100(0x100, 1),
84
          io80(0x80, 1),
85
          io10(0x10, 1)
86
    {
87
        add_ioport(&io100);
88
        add_ioport(&io80);
89
        add_ioport(&io10);
90
        reset();
91
    }
92
 
93
    ~EmulateFixture()
94
    {
95
        cpu->write_coverage();
96
    }
97
 
98
    void add_ioport(IOPorts *p)
99
    {
100
        cpu->add_ioport(p);
101
    }
102
 
103
    void reset()
104
    {
105
        cpu->reset();
106
        // Doesn't need to model the reset vector of FFF0:0000 otherwise we
107
        // need to handle wrapping around to 0.  Just start off away from the
108
        // interrupt vector table so we can easily detect interrupts.
109
        cpu->write_reg(CS, 0x0000);
110
        cpu->write_reg(IP, 0x1000);
111
        cpu->write_reg(SS, 0x2000);
112
        cpu->write_reg(ES, 0x4000);
113
        cpu->write_reg(DS, 0x6000);
114
    }
115
 
116
    void set_instruction(const std::vector<uint8_t> &instr)
117
    {
118
        cpu->write_vector8(cpu->read_reg(CS), cpu->read_reg(IP), instr);
119
        instr_len = instr.size();
120
        // Force a prefetch fifo clear so we don't end up executing what was
121
        // there before we wrote this instruction.
122
        cpu->write_reg(IP, cpu->read_reg(IP));
123
    }
124
 
125
    void write_reg(GPR regnum, uint16_t val)
126
    {
127
        cpu->write_reg(regnum, val);
128
    }
129
 
130
    uint16_t read_reg(GPR regnum)
131
    {
132
        return cpu->read_reg(regnum);
133
    }
134
 
135
    void write_mem8(uint16_t addr, uint8_t val, GPR segment = DS)
136
    {
137
        cpu->write_mem8(cpu->read_reg(segment), addr, val);
138
    }
139
    void write_mem16(uint16_t addr, uint16_t val, GPR segment = DS)
140
    {
141
        cpu->write_mem16(cpu->read_reg(segment), addr, val);
142
    }
143
    void write_mem32(uint16_t addr, uint32_t val, GPR segment = DS)
144
    {
145
        cpu->write_mem32(cpu->read_reg(segment), addr, val);
146
    }
147
 
148
    void write_cstring(uint16_t addr, const char *str, GPR segment = DS)
149
    {
150
        do {
151
            write_mem8(addr++, *str++, segment);
152
        } while (*str);
153
        write_mem8(addr, 0, segment);
154
    }
155
 
156
    void write_vector8(uint16_t addr,
157
                       std::vector<uint8_t> vec,
158
                       GPR segment = DS)
159
    {
160
        for (auto v : vec) {
161
            write_mem8(addr, v, segment);
162
            ++addr;
163
        }
164
    }
165
    void write_vector16(uint16_t addr,
166
                        std::vector<uint16_t> vec,
167
                        GPR segment = DS)
168
    {
169
        for (auto v : vec) {
170
            write_mem16(addr, v, segment);
171
            addr += sizeof(uint16_t);
172
        }
173
    }
174
 
175
    std::string read_cstring(uint16_t addr, GPR segment = DS)
176
    {
177
        std::string str;
178
 
179
        char v;
180
        for (;;) {
181
            v = read_mem8(addr++, segment);
182
            if (!v)
183
                break;
184
            str += v;
185
        }
186
 
187
        return str;
188
    }
189
 
190
    uint8_t read_mem8(uint16_t addr, GPR segment = DS)
191
    {
192
        return cpu->read_mem8(cpu->read_reg(segment), addr);
193
    }
194
    uint16_t read_mem16(uint16_t addr, GPR segment = DS)
195
    {
196
        return cpu->read_mem16(cpu->read_reg(segment), addr);
197
    }
198
    uint32_t read_mem32(uint16_t addr, GPR segment = DS)
199
    {
200
        return cpu->read_mem32(cpu->read_reg(segment), addr);
201
    }
202
 
203
    void write_io8(uint32_t addr, uint8_t val)
204
    {
205
        cpu->write_io8(addr, val);
206
    }
207
    void write_io16(uint32_t addr, uint16_t val)
208
    {
209
        cpu->write_io16(addr, val);
210
    }
211
 
212
    uint8_t read_io8(uint32_t addr)
213
    {
214
        return cpu->read_io8(addr);
215
    }
216
    uint16_t read_io16(uint32_t addr)
217
    {
218
        return cpu->read_io16(addr);
219
    }
220
 
221
    void emulate(int count = 1)
222
    {
223
        cpu->clear_side_effects();
224
 
225
        assert(count > 0);
226
        size_t len = 0;
227
        for (auto i = 0; i < count; ++i)
228
            len += cpu->step();
229
        if (cpu->has_instruction_length())
230
            ASSERT_EQ(len, instr_len);
231
    }
232
 
233
    void wait_for_int_yield()
234
    {
235
        while (!cpu->int_yield_ready())
236
            cpu->cycle_cpu();
237
    }
238
 
239
    void write_flags(uint16_t val)
240
    {
241
        cpu->write_flags(val);
242
    }
243
 
244
    uint16_t read_flags()
245
    {
246
        return cpu->read_flags();
247
    }
248
 
249
    bool instruction_had_side_effects()
250
    {
251
        return cpu->instruction_had_side_effects();
252
    }
253
 
254
    void raise_nmi()
255
    {
256
        cpu->raise_nmi();
257
    }
258
 
259
    void raise_irq(int irq_num)
260
    {
261
        cpu->raise_irq(irq_num);
262
    }
263
 
264
protected:
265
    size_t instr_len;
266
    std::unique_ptr<CPU> cpu;
267
    DummyIO io100;
268
    DummyIO io80;
269
    DummyIO io10;
270
};

powered by: WebSVN 2.1.0

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