forked from libretro/parallel-rsp
-
Notifications
You must be signed in to change notification settings - Fork 3
/
state.hpp
146 lines (129 loc) · 3.1 KB
/
state.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
#ifndef STATE_HPP__
#define STATE_HPP__
#include "rsp_common.h"
#define DMEM_SIZE (4 * 1024)
#define IMEM_SIZE (4 * 1024)
#define DMEM_WORDS (DMEM_SIZE / 4)
#define IMEM_WORDS (IMEM_SIZE / 4)
#define CODE_BLOCK_SIZE (256)
#define CODE_BLOCK_WORDS (CODE_BLOCK_SIZE / 4)
#define CODE_BLOCK_SIZE_LOG2 (8)
#define CODE_BLOCKS (IMEM_SIZE / CODE_BLOCK_SIZE)
namespace RSP
{
enum RSPFlags
{
RSP_VCO = 0,
RSP_VCC = 1,
RSP_VCE = 2
};
enum RSPAccumulator
{
RSP_ACC_LO = 16,
RSP_ACC_MD = 8,
RSP_ACC_HI = 0
};
enum CP0Registers
{
CP0_REGISTER_DMA_CACHE = 0,
CP0_REGISTER_DMA_DRAM = 1,
CP0_REGISTER_DMA_READ_LENGTH = 2,
CP0_REGISTER_DMA_WRITE_LENGTH = 3,
CP0_REGISTER_SP_STATUS = 4,
CP0_REGISTER_DMA_FULL = 5,
CP0_REGISTER_DMA_BUSY = 6,
CP0_REGISTER_SP_SEMAPHORE = 7,
CP0_REGISTER_CMD_START = 8,
CP0_REGISTER_CMD_END = 9,
CP0_REGISTER_CMD_CURRENT = 10,
CP0_REGISTER_CMD_STATUS = 11,
CP0_REGISTER_CMD_CLOCK = 12,
CP0_REGISTER_CMD_BUSY = 13,
CP0_REGISTER_CMD_PIPE_BUSY = 14,
CP0_REGISTER_CMD_TMEM_BUSY = 15,
};
// SP_STATUS read bits.
#define SP_STATUS_HALT 0x0001
#define SP_STATUS_BROKE 0x0002
#define SP_STATUS_DMA_BUSY 0x0004
#define SP_STATUS_DMA_FULL 0x0008
#define SP_STATUS_IO_FULL 0x0010
#define SP_STATUS_SSTEP 0x0020
#define SP_STATUS_INTR_BREAK 0x0040
#define SP_STATUS_SIG0 0x0080
#define SP_STATUS_SIG1 0x0100
#define SP_STATUS_SIG2 0x0200
#define SP_STATUS_SIG3 0x0400
#define SP_STATUS_SIG4 0x0800
#define SP_STATUS_SIG5 0x1000
#define SP_STATUS_SIG6 0x2000
#define SP_STATUS_SIG7 0x4000
// SP_STATUS write bits.
#define SP_CLR_HALT 0x00000001
#define SP_SET_HALT 0x00000002
#define SP_CLR_BROKE 0x00000004
#define SP_CLR_INTR 0x00000008
#define SP_SET_INTR 0x00000010
#define SP_CLR_SSTEP 0x00000020
#define SP_SET_SSTEP 0x00000040
#define SP_CLR_INTR_BREAK 0x00000080
#define SP_SET_INTR_BREAK 0x00000100
#define SP_CLR_SIG0 0x00000200
#define SP_SET_SIG0 0x00000400
#define SP_CLR_SIG1 0x00000800
#define SP_SET_SIG1 0x00001000
#define SP_CLR_SIG2 0x00002000
#define SP_SET_SIG2 0x00004000
#define SP_CLR_SIG3 0x00008000
#define SP_SET_SIG3 0x00010000
#define SP_CLR_SIG4 0x00020000
#define SP_SET_SIG4 0x00040000
#define SP_CLR_SIG5 0x00080000
#define SP_SET_SIG5 0x00100000
#define SP_CLR_SIG6 0x00200000
#define SP_SET_SIG6 0x00400000
#define SP_CLR_SIG7 0x00800000
#define SP_SET_SIG7 0x01000000
template <int N>
struct alignas(rsp_vect_t) AlignedRSPVector
{
uint16_t e[8 * N];
};
struct CP0
{
uint32_t *cr[16] = {};
uint32_t *irq = nullptr;
};
struct alignas(64) CP2
{
AlignedRSPVector<1> regs[32];
AlignedRSPVector<2> flags[3];
AlignedRSPVector<3> acc;
int16_t div_out;
int16_t div_in;
int8_t dp_flag;
};
struct CPUState
{
uint32_t pc = 0;
uint32_t dirty_blocks = 0;
static_assert(CODE_BLOCKS <= 32, "Code blocks must fit in 32-bit register.");
uint32_t has_delay_slot = 0;
uint32_t branch_target = 0;
uint32_t sr[33] = {}; // r32 is used as a scratch register.
uint32_t *dmem = nullptr;
uint32_t *imem = nullptr;
uint32_t *rdram = nullptr;
CP2 cp2 = {};
CP0 cp0;
};
enum ReturnMode
{
MODE_ENTER = 0,
MODE_CONTINUE = 1,
MODE_BREAK = 2,
MODE_DMA_READ = 3,
MODE_CHECK_FLAGS = 4
};
} // namespace RSP
#endif