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