This repository has been archived by the owner on Feb 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
dmac.hpp
149 lines (133 loc) · 2.54 KB
/
dmac.hpp
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#pragma once
#include <int128.h>
class Bus;
class EmotionEngine;
constexpr uint32_t DMATAG_END = 0x7;
union TagAddr
{
uint32_t value;
struct
{
uint32_t address : 30;
uint32_t mem_select : 1;
};
};
union DMATag
{
uint128_t value;
struct
{
uint128_t qwords : 16;
uint128_t : 10;
uint128_t priority : 2;
uint128_t id : 3;
uint128_t irq : 1;
uint128_t address : 31;
uint128_t mem_select : 1;
uint128_t data : 64;
};
};
union DCHCR
{
uint32_t value;
struct
{
uint32_t direction : 1;
uint32_t : 1;
uint32_t mode : 2;
uint32_t stack_ptr : 2;
uint32_t transfer_tag : 1;
uint32_t enable_irq_bit : 1;
uint32_t running : 1;
uint32_t : 7;
uint32_t tag : 16;
};
};
struct DMACChannel
{
DCHCR control;
uint32_t address;
uint32_t qword_count;
TagAddr tag_address;
TagAddr saved_tag_address[2];
uint32_t padding[2];
uint32_t scratchpad_address;
bool end_transfer = false;
};
union DSTAT
{
uint32_t value;
struct
{
uint32_t channel_irq : 10;
uint32_t : 3;
uint32_t dma_stall : 1;
uint32_t mfifo_empty : 1;
uint32_t bus_error : 1;
uint32_t channel_irq_mask : 10;
uint32_t : 3;
uint32_t stall_irq_mask : 1;
uint32_t mfifo_irq_mask : 1;
uint32_t : 1;
};
struct
{
uint32_t clear : 16;
uint32_t reverse : 16;
};
};
struct DMACGlobals
{
uint32_t d_ctrl;
DSTAT d_stat;
uint32_t d_pcr;
uint32_t d_sqwc;
uint32_t d_rbsr;
uint32_t d_rbor;
uint32_t d_stadr;
uint32_t d_enable = 0x1201;
};
enum DMAChannels : uint32_t
{
VIF0,
VIF1,
GIFC,
IPU_FROM,
IPU_TO,
SIF0,
SIF1,
SIF2,
SPR_FROM,
SPR_TO
};
enum DMASourceID : uint32_t
{
REFE,
CNT,
NEXT,
REF,
REFS,
CALL,
RET,
END
};
class DMAController
{
public:
DMAController(Bus* parent, EmotionEngine* _cpu);
~DMAController() = default;
uint32_t read_channel(uint32_t addr);
uint32_t read_global(uint32_t addr);
uint32_t read_enabler(uint32_t addr);
void write_channel(uint32_t addr, uint32_t data);
void write_global(uint32_t addr, uint32_t data);
void write_enabler(uint32_t addr, uint32_t data);
void tick(uint32_t cycles);
private:
void fetch_tag(uint32_t id);
private:
Bus* bus;
EmotionEngine* cpu;
DMACChannel channels[10] = {};
DMACGlobals globals = {};
};