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

Subversion Repositories s80186

[/] [s80186/] [trunk/] [sim/] [common/] [CPU.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 <functional>
22
#include <stdexcept>
23
#include <string>
24
#include <vector>
25
 
26
#include <boost/serialization/list.hpp>
27
#include <boost/serialization/string.hpp>
28
#include <boost/serialization/version.hpp>
29
 
30
#include "Memory.h"
31
#include "RegisterFile.h"
32
 
33
#define __unused __attribute__((unused))
34
 
35
class Emulator;
36
class EmulatorPimpl;
37
 
38
enum InterruptVectorOffset {
39
    VEC_DIVIDE_ERROR = 0,
40
    VEC_SINGLE_STEP = 4,
41
    VEC_NMI = 8,
42
    VEC_INT = 12,
43
    VEC_OVERFLOW = 16,
44
    VEC_BOUND = 20,
45
    VEC_INVALID_OPCODE = 24,
46
    VEC_ESCAPE = 28
47
};
48
 
49
static inline phys_addr get_phys_addr(uint16_t segment, uint32_t displacement)
50
{
51
    return ((static_cast<uint32_t>(segment) << 4) + displacement) %
52
           (1 * 1024 * 1024);
53
}
54
 
55
class IOPorts
56
{
57
public:
58
    IOPorts(uint16_t base, size_t num_ports) : base(base), num_ports(num_ports)
59
    {
60
    }
61
 
62
    virtual ~IOPorts()
63
    {
64
    }
65
 
66
    virtual uint8_t read8(uint16_t port_num, unsigned offs) = 0;
67
    virtual uint16_t read16(uint16_t port_num)
68
    {
69
        return read8(port_num, 0) |
70
               (static_cast<uint16_t>(read8(port_num, 1)) << 8);
71
    }
72
    virtual void write8(uint16_t port_num, unsigned offs, uint8_t v) = 0;
73
    virtual void write16(uint16_t port_num, uint16_t v)
74
    {
75
        write8(port_num, 0, v);
76
        write8(port_num, 1, v >> 8);
77
    }
78
    uint16_t get_base() const
79
    {
80
        return base;
81
    }
82
    size_t get_num_ports() const
83
    {
84
        return num_ports;
85
    }
86
 
87
private:
88
    uint16_t base;
89
    size_t num_ports;
90
};
91
 
92
using NotImplemented = std::runtime_error;
93
 
94
class CPU
95
{
96
public:
97
    CPU() : CPU("default")
98
    {
99
    }
100
    explicit CPU(const std::string __unused &name)
101
    {
102
    }
103
    virtual ~CPU(){};
104
    virtual bool has_instruction_length() const = 0;
105
    virtual void write_coverage()
106
    {
107
    }
108
    virtual void write_reg(GPR regnum, uint16_t val) = 0;
109
    virtual uint16_t read_reg(GPR regnum) const = 0;
110
    virtual void cycle_cpu()
111
    {
112
        throw NotImplemented("cycle not implemented");
113
    }
114
    virtual void start_instruction()
115
    {
116
        throw NotImplemented("start_instruction not implemented");
117
    }
118
    virtual void complete_instruction()
119
    {
120
        throw NotImplemented("complete_instruction not implemented");
121
    }
122
    virtual bool int_yield_ready()
123
    {
124
        throw NotImplemented("int_yield_ready not implemented");
125
    }
126
    virtual void debug_detach()
127
    {
128
    }
129
    virtual size_t step() = 0;
130
    virtual void write_flags(uint16_t val) = 0;
131
    virtual uint16_t read_flags() const = 0;
132
    virtual bool has_trapped() = 0;
133
    virtual void reset() = 0;
134
    virtual bool instruction_had_side_effects() const = 0;
135
    virtual void clear_side_effects() = 0;
136
    virtual void write_mem8(uint16_t segment, uint16_t addr, uint8_t val) = 0;
137
    virtual void write_mem16(uint16_t segment, uint16_t addr, uint16_t val) = 0;
138
    virtual void write_mem32(uint16_t segment, uint16_t addr, uint32_t val) = 0;
139
    virtual uint8_t read_mem8(uint16_t segment, uint16_t addr) = 0;
140
    virtual uint16_t read_mem16(uint16_t segment, uint16_t addr) = 0;
141
    virtual uint32_t read_mem32(uint16_t segment, uint16_t addr) = 0;
142
    virtual void write_io8(uint32_t addr, uint8_t val) = 0;
143
    virtual void write_io16(uint32_t addr, uint16_t val) = 0;
144
    virtual uint8_t read_io8(uint32_t addr) = 0;
145
    virtual uint16_t read_io16(uint32_t addr) = 0;
146
    virtual void add_ioport(IOPorts *p) = 0;
147
 
148
    virtual std::vector<uint8_t> read_vector8(uint16_t segment,
149
                                              uint16_t addr,
150
                                              size_t count)
151
    {
152
        std::vector<uint8_t> v;
153
 
154
        for (size_t m = 0; m < count; ++m)
155
            v.push_back(read_mem8(segment, addr + m));
156
 
157
        return v;
158
    }
159
 
160
    virtual void write_vector8(uint16_t segment,
161
                               uint16_t addr,
162
                               const std::vector<uint8_t> &v)
163
    {
164
        uint16_t offs = 0;
165
        for (auto &b : v)
166
            write_mem8(segment, addr + offs++, b);
167
    }
168
 
169
    virtual std::vector<uint16_t> read_vector16(uint16_t segment,
170
                                                uint16_t addr,
171
                                                size_t count)
172
    {
173
        std::vector<uint16_t> v;
174
 
175
        for (size_t m = 0; m < count; ++m)
176
            v.push_back(read_mem16(segment, addr + m * sizeof(uint16_t)));
177
 
178
        return v;
179
    }
180
 
181
    virtual void write_vector16(uint16_t segment,
182
                                uint16_t addr,
183
                                const std::vector<uint16_t> &v)
184
    {
185
        uint16_t offs = 0;
186
        for (auto &w : v) {
187
            write_mem16(segment, addr + offs, w);
188
            offs += 2;
189
        }
190
    }
191
    virtual void raise_nmi() = 0;
192
    virtual void raise_irq(int irq_num) = 0;
193
    virtual void set_inta_handler(std::function<void(int)> __unused handler)
194
    {
195
        throw NotImplemented("set_inta_handler not implemented");
196
    }
197
    virtual unsigned long cycle_count() const = 0;
198
};
199
 
200
class SimCPU : public CPU
201
{
202
public:
203
    explicit SimCPU(const std::string &name)
204
        : CPU(name), inta_handler([](int __unused irq_num) {})
205
    {
206
    }
207
 
208
    Memory *get_memory()
209
    {
210
        return &mem;
211
    }
212
 
213
    virtual size_t step_with_io(std::function<void(unsigned long)> io_callback)
214
    {
215
        (void)io_callback;
216
 
217
        throw NotImplemented("step_with_io not implemented");
218
    }
219
 
220
    virtual void cycle_cpu_with_io(
221
        std::function<void(unsigned long)> io_callback)
222
    {
223
        (void)io_callback;
224
 
225
        throw NotImplemented("cycle_with_io not implemented");
226
    }
227
 
228
    virtual void set_inta_handler(std::function<void(int)> handler)
229
    {
230
        this->inta_handler = handler;
231
    }
232
 
233
protected:
234
    Memory mem;
235
 
236
    void ack_int(int irq_num)
237
    {
238
        this->inta_handler(irq_num);
239
    }
240
 
241
    friend class Emulator;
242
    friend class EmulatorPimpl;
243
 
244
private:
245
    std::function<void(int)> inta_handler;
246
 
247
    friend class boost::serialization::access;
248
    template <class Archive>
249
    void save(Archive &ar, const unsigned int __unused version) const
250
    {
251
        for (auto r = static_cast<int>(AX);
252
             r <= static_cast<int>(NUM_16BIT_REGS); ++r) {
253
            auto v = read_reg(static_cast<GPR>(r));
254
            // clang-format off
255
            ar & v;
256
            // clang-format on
257
        }
258
 
259
        // clang-format off
260
        auto flags = read_flags();
261
        ar & flags;
262
 
263
        ar & mem;
264
        // clang-format on
265
    }
266
 
267
    template <class Archive>
268
    void load(Archive &ar, const unsigned int __unused version)
269
    {
270
        for (auto r = static_cast<int>(AX);
271
             r <= static_cast<int>(NUM_16BIT_REGS); ++r) {
272
            uint16_t v = 0;
273
            // clang-format off
274
            ar & v;
275
            write_reg(static_cast<GPR>(r), v);
276
            // clang-format on
277
        }
278
 
279
        // clang-format off
280
        uint16_t flags = 0;
281
        ar & flags;
282
        write_flags(flags);
283
 
284
        ar & mem;
285
        // clang-format on
286
    }
287
    BOOST_SERIALIZATION_SPLIT_MEMBER()
288
};
289
BOOST_CLASS_VERSION(SimCPU, 1)

powered by: WebSVN 2.1.0

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