1 // Copyright 2009 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4
5 // Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
6
7 #pragma once
8
9 #include <algorithm>
10 #include <array>
11 #include <cstddef>
12 #include <string_view>
13
14 #include "Core/DSP/DSPCommon.h"
15
16 namespace DSP
17 {
18 // The non-ADDR ones that end with _D are the opposite one - if the bit specify
19 // ACC0, then ACC_D will be ACC1.
20
21 // The values of these are very important.
22 // For the reg ones, the value >> 8 is the base register.
23 // & 0x80 means it's a "D".
24
25 enum partype_t
26 {
27 P_NONE = 0x0000,
28 P_VAL = 0x0001,
29 P_IMM = 0x0002,
30 P_MEM = 0x0003,
31 P_STR = 0x0004,
32 P_ADDR_I = 0x0005,
33 P_ADDR_D = 0x0006,
34 P_REG = 0x8000,
35 P_REG04 = P_REG | 0x0400, // IX
36 P_REG08 = P_REG | 0x0800,
37 P_REG18 = P_REG | 0x1800,
38 P_REGM18 = P_REG | 0x1810, // used in multiply instructions
39 P_REG19 = P_REG | 0x1900,
40 P_REGM19 = P_REG | 0x1910, // used in multiply instructions
41 P_REG1A = P_REG | 0x1a80,
42 // P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value)
43 P_ACCL = P_REG | 0x1c00, // used for low part of accum
44 P_REG1C = P_REG | 0x1c10, // gcdsptool calls this P_ACCLM
45 P_ACCM = P_REG | 0x1e00, // used for mid part of accum
46 // The following are not in gcdsptool
47 P_ACCM_D = P_REG | 0x1e80,
48 P_ACC = P_REG | 0x2000, // used for full accum.
49 P_ACC_D = P_REG | 0x2080,
50 P_AX = P_REG | 0x2200,
51 P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80
52 P_REF = P_REG | 0x4000,
53 P_PRG = P_REF | P_REG,
54
55 // The following seem like junk:
56 // P_REG10 = P_REG | 0x1000,
57 // P_AX_D = P_REG | 0x2280,
58 };
59
60 struct param2_t
61 {
62 partype_t type;
63 u8 size;
64 u8 loc;
65 s8 lshift;
66 u16 mask;
67 };
68
69 struct DSPOPCTemplate
70 {
71 const char* name;
72 u16 opcode;
73 u16 opcode_mask;
74
75 u8 size;
76 u8 param_count;
77 param2_t params[8];
78 bool extended;
79 bool branch;
80 bool uncond_branch;
81 bool reads_pc;
82 bool updates_sr;
83 };
84
85 // Opcodes
86 extern const DSPOPCTemplate cw;
87
88 constexpr size_t WRITEBACK_LOG_SIZE = 5;
89 extern std::array<u16, WRITEBACK_LOG_SIZE> writeBackLog;
90 extern std::array<int, WRITEBACK_LOG_SIZE> writeBackLogIdx;
91
92 // Predefined labels
93 struct pdlabel_t
94 {
95 u16 addr;
96 const char* name;
97 const char* description;
98 };
99
100 extern const std::array<pdlabel_t, 36> regnames;
101 extern const std::array<pdlabel_t, 96> pdlabels;
102
103 const char* pdname(u16 val);
104 const char* pdregname(int val);
105 const char* pdregnamelong(int val);
106
107 void InitInstructionTable();
108 void ApplyWriteBackLog();
109 void ZeroWriteBackLog();
110 void ZeroWriteBackLogPreserveAcc(u8 acc);
111
112 // Used by the assembler and disassembler for info retrieval.
113 const DSPOPCTemplate* FindOpInfoByOpcode(UDSPInstruction opcode);
114 const DSPOPCTemplate* FindOpInfoByName(std::string_view name);
115
116 const DSPOPCTemplate* FindExtOpInfoByOpcode(UDSPInstruction opcode);
117 const DSPOPCTemplate* FindExtOpInfoByName(std::string_view name);
118
119 // Used by the interpreter and JIT for instruction emulation
120 const DSPOPCTemplate* GetOpTemplate(UDSPInstruction inst);
121 const DSPOPCTemplate* GetExtOpTemplate(UDSPInstruction inst);
122
123 template <typename T, size_t N>
FindByOpcode(UDSPInstruction opcode,const std::array<T,N> & data)124 auto FindByOpcode(UDSPInstruction opcode, const std::array<T, N>& data)
125 {
126 return std::find_if(data.cbegin(), data.cend(), [opcode](const auto& info) {
127 return (opcode & info.opcode_mask) == info.opcode;
128 });
129 }
130 } // namespace DSP
131