File: CommandProcessor.h

package info (click to toggle)
dolphin-emu 2512%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 76,328 kB
  • sloc: cpp: 499,023; ansic: 119,674; python: 6,547; sh: 2,338; makefile: 1,093; asm: 726; pascal: 257; javascript: 183; perl: 97; objc: 75; xml: 30
file content (211 lines) | stat: -rw-r--r-- 4,595 bytes parent folder | download
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <atomic>

#include "Common/CommonTypes.h"
#include "Common/Flag.h"

class PointerWrap;
namespace MMIO
{
class Mapping;
}
namespace Core
{
class System;
}
namespace CoreTiming
{
struct EventType;
}

namespace CommandProcessor
{
struct SCPFifoStruct
{
  // fifo registers
  std::atomic<u32> CPBase = 0;
  std::atomic<u32> CPEnd = 0;
  u32 CPHiWatermark = 0;
  u32 CPLoWatermark = 0;
  std::atomic<u32> CPReadWriteDistance = 0;
  std::atomic<u32> CPWritePointer = 0;
  std::atomic<u32> CPReadPointer = 0;
  std::atomic<u32> CPBreakpoint = 0;
  std::atomic<u32> SafeCPReadPointer = 0;

  std::atomic<u32> bFF_GPLinkEnable = 0;
  std::atomic<u32> bFF_GPReadEnable = 0;
  std::atomic<u32> bFF_BPEnable = 0;
  std::atomic<u32> bFF_BPInt = 0;
  std::atomic<u32> bFF_Breakpoint = 0;

  std::atomic<u32> bFF_LoWatermarkInt = 0;
  std::atomic<u32> bFF_HiWatermarkInt = 0;

  std::atomic<u32> bFF_LoWatermark = 0;
  std::atomic<u32> bFF_HiWatermark = 0;

  void Init();
  void DoState(PointerWrap& p);
};

// internal hardware addresses
enum
{
  STATUS_REGISTER = 0x00,
  CTRL_REGISTER = 0x02,
  CLEAR_REGISTER = 0x04,
  PERF_SELECT = 0x06,
  UNK_0A_REGISTER = 0x0A,
  FIFO_BASE_LO = 0x20,
  FIFO_BASE_HI = 0x22,
  FIFO_END_LO = 0x24,
  FIFO_END_HI = 0x26,
  FIFO_HI_WATERMARK_LO = 0x28,
  FIFO_HI_WATERMARK_HI = 0x2a,
  FIFO_LO_WATERMARK_LO = 0x2c,
  FIFO_LO_WATERMARK_HI = 0x2e,
  FIFO_RW_DISTANCE_LO = 0x30,
  FIFO_RW_DISTANCE_HI = 0x32,
  FIFO_WRITE_POINTER_LO = 0x34,
  FIFO_WRITE_POINTER_HI = 0x36,
  FIFO_READ_POINTER_LO = 0x38,
  FIFO_READ_POINTER_HI = 0x3A,
  FIFO_BP_LO = 0x3C,
  FIFO_BP_HI = 0x3E,
  XF_RASBUSY_L = 0x40,
  XF_RASBUSY_H = 0x42,
  XF_CLKS_L = 0x44,
  XF_CLKS_H = 0x46,
  XF_WAIT_IN_L = 0x48,
  XF_WAIT_IN_H = 0x4a,
  XF_WAIT_OUT_L = 0x4c,
  XF_WAIT_OUT_H = 0x4e,
  VCACHE_METRIC_CHECK_L = 0x50,
  VCACHE_METRIC_CHECK_H = 0x52,
  VCACHE_METRIC_MISS_L = 0x54,
  VCACHE_METRIC_MISS_H = 0x56,
  VCACHE_METRIC_STALL_L = 0x58,
  VCACHE_METRIC_STALL_H = 0x5A,
  CLKS_PER_VTX_IN_L = 0x60,
  CLKS_PER_VTX_IN_H = 0x62,
  CLKS_PER_VTX_OUT = 0x64,
};

enum
{
  INT_CAUSE_CP = 0x800
};

// Fifo Status Register
union UCPStatusReg
{
  struct
  {
    u16 OverflowHiWatermark : 1;
    u16 UnderflowLoWatermark : 1;
    u16 ReadIdle : 1;
    u16 CommandIdle : 1;
    u16 Breakpoint : 1;
    u16 : 11;
  };
  u16 Hex;
  UCPStatusReg() { Hex = 0; }
  UCPStatusReg(u16 _hex) { Hex = _hex; }
};

// Fifo Control Register
union UCPCtrlReg
{
  struct
  {
    u16 GPReadEnable : 1;
    u16 BPEnable : 1;
    u16 FifoOverflowIntEnable : 1;
    u16 FifoUnderflowIntEnable : 1;
    u16 GPLinkEnable : 1;
    u16 BPInt : 1;
    u16 : 10;
  };
  u16 Hex;
  UCPCtrlReg() { Hex = 0; }
  UCPCtrlReg(u16 _hex) { Hex = _hex; }
};

// Fifo Clear Register
union UCPClearReg
{
  struct
  {
    u16 ClearFifoOverflow : 1;
    u16 ClearFifoUnderflow : 1;
    // set by GXClearGPMetric
    u16 ClearMetrics : 1;
    u16 : 13;
  };
  u16 Hex;
  UCPClearReg() { Hex = 0; }
  UCPClearReg(u16 _hex) { Hex = _hex; }
};

constexpr u32 GetPhysicalAddressMask(bool is_wii)
{
  // Physical addresses in CP seem to ignore some of the upper bits (depending on platform)
  // This can be observed in CP MMIO registers by setting to 0xffffffff and then reading back.
  return is_wii ? 0x1fffffff : 0x03ffffff;
}

class CommandProcessorManager
{
public:
  explicit CommandProcessorManager(Core::System& system);

  void Init();
  void DoState(PointerWrap& p);

  void RegisterMMIO(MMIO::Mapping* mmio, u32 base);

  void SetCPStatusFromGPU();
  void SetCPStatusFromCPU();
  void GatherPipeBursted();
  void UpdateInterrupts(u64 userdata);
  void UpdateInterruptsFromVideoBackend(u64 userdata);

  bool IsInterruptWaiting() const;

  void SetCpClearRegister();
  void SetCpControlRegister();
  void SetCpStatusRegister();
  void ResetFifo();

  void HandleUnknownOpcode(u8 cmd_byte, const u8* buffer, bool preprocess);

  // This one is shared between gfx thread and emulator thread.
  // It is only used by the Fifo and by the CommandProcessor.
  SCPFifoStruct& GetFifo() { return m_fifo; }

private:
  SCPFifoStruct m_fifo;

  CoreTiming::EventType* m_event_type_update_interrupts = nullptr;

  // STATE_TO_SAVE
  UCPStatusReg m_cp_status_reg;
  UCPCtrlReg m_cp_ctrl_reg;
  UCPClearReg m_cp_clear_reg;
  u16 m_perf_select = 0;
  u16 m_unk_0a_reg = 0;

  Common::Flag m_interrupt_set;
  Common::Flag m_interrupt_waiting;

  bool m_is_fifo_error_seen = false;

  Core::System& m_system;
};

}  // namespace CommandProcessor