summaryrefslogtreecommitdiff
path: root/m68k_debugging.hpp
blob: 5bcdd735dab7d3e783a12342626e1caabf880370 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/* SPDX-License-Identifier: Unlicense
 */

#pragma once

#include "gdbremote_parser.hpp"

#include <cstdint>
#include <cstddef>

enum class M68KRegister: size_t {
    kD0 = 0,
    kD1 = 1,
    kD2 = 2,
    kD3 = 3,
    kD4 = 4,
    kD5 = 5,
    kD6 = 6,
    kD7 = 7,
    kA0 = 8,
    kA1 = 9,
    kA2 = 10,
    kA3 = 11,
    kA4 = 12,
    kA5 = 13,
    kA6 = 14,           /* Address of executing stack frame  */
    kFP = kA6,
    kA7 = 15,           /* Address of top of stack (Stack pointer)  */
    kSP = kA7,
    kPS = 16,           /* Processor status (Condition code register)  */
    kPC = 17,           /* Program counter  */
    kRegistersCount,
    kFP0 = 18,          /* Floating point register 0  */
    kFPC = 26,          /* 68881 control register  */
    kFPS = 27,          /* 68881 status register  */
    kFPI = 28,          /* Floating point register 1  */
};

struct M68KCPUState {
    size_t registers_count{};
    uint32_t registers[static_cast<size_t>(M68KRegister::kRegistersCount)]{};
};

class M68KDebuggingControl {
public:
    using BreakpointType = GDBRemote::BreakpointType;

    M68KDebuggingControl() = default;
    M68KDebuggingControl(M68KDebuggingControl&&) = delete;
    M68KDebuggingControl(const M68KDebuggingControl&) = delete;

    uint32_t GetRegister(M68KRegister) const;
    M68KCPUState GetCPUState() const;
    void SetRegister(M68KRegister, uint32_t value);
    bool IsRunning() const { return _is_running; }
    void SetRunning(bool running) { _is_running = running; }
    bool IsNoAckModeEnabled() const { return _no_ack_mode; }
    void SetNoAckMode(bool enabled = true) { _no_ack_mode = enabled; }
    void Reset();
    void Continue();
    void Pause();
    uint8_t Read8(uint32_t address) const;
    uint16_t Read16(uint32_t address) const;
    uint32_t Read32(uint32_t address) const;
    void Write8(uint32_t address, uint8_t value);
    void Write16(uint32_t address, uint16_t value);
    void Write32(uint32_t address, uint32_t value);
    void SetBreakpoint(BreakpointType type, uint32_t address, uint32_t length);
    void RemoveBreakpoint(BreakpointType type, uint32_t address, uint32_t length);
    void RaiseBreakpoint() { _have_break_risen = true; }
    bool HasBreakpoint() const { return _have_break_risen; }
    void ResetPendingBreakpoint() { _have_break_risen = false; }

private:
    bool _is_running{};
    bool _have_break_risen{};
    bool _no_ack_mode{};
};