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 and Tratax (c) 2004
6
7 #include "Core/DSP/DSPMemoryMap.h"
8 #include "Core/DSP/Interpreter/DSPIntUtil.h"
9 #include "Core/DSP/Interpreter/DSPInterpreter.h"
10
11 namespace DSP::Interpreter
12 {
13 // SRS @M, $(0x18+S)
14 // 0010 1sss mmmm mmmm
15 // Move value from register $(0x18+S) to data memory pointed by address
16 // CR[0-7] | M. That is, the upper 8 bits of the address are the
17 // bottom 8 bits from CR, and the lower 8 bits are from the 8-bit immediate.
18 // Note: pc+=2 in duddie's doc seems wrong
srs(const UDSPInstruction opc)19 void srs(const UDSPInstruction opc)
20 {
21 u8 reg = ((opc >> 8) & 0x7) + 0x18;
22 u16 addr = (g_dsp.r.cr << 8) | (opc & 0xFF);
23
24 if (reg >= DSP_REG_ACM0)
25 dsp_dmem_write(addr, dsp_op_read_reg_and_saturate(reg - DSP_REG_ACM0));
26 else
27 dsp_dmem_write(addr, dsp_op_read_reg(reg));
28 }
29
30 // LRS $(0x18+D), @M
31 // 0010 0ddd mmmm mmmm
32 // Move value from data memory pointed by address CR[0-7] | M to register
33 // $(0x18+D). That is, the upper 8 bits of the address are the bottom 8 bits
34 // from CR, and the lower 8 bits are from the 8-bit immediate.
lrs(const UDSPInstruction opc)35 void lrs(const UDSPInstruction opc)
36 {
37 u8 reg = ((opc >> 8) & 0x7) + 0x18;
38 u16 addr = (g_dsp.r.cr << 8) | (opc & 0xFF);
39 dsp_op_write_reg(reg, dsp_dmem_read(addr));
40 dsp_conditional_extend_accum(reg);
41 }
42
43 // LR $D, @M
44 // 0000 0000 110d dddd
45 // mmmm mmmm mmmm mmmm
46 // Move value from data memory pointed by address M to register $D.
lr(const UDSPInstruction opc)47 void lr(const UDSPInstruction opc)
48 {
49 u8 reg = opc & 0x1F;
50 u16 addr = dsp_fetch_code();
51 u16 val = dsp_dmem_read(addr);
52 dsp_op_write_reg(reg, val);
53 dsp_conditional_extend_accum(reg);
54 }
55
56 // SR @M, $S
57 // 0000 0000 111s ssss
58 // mmmm mmmm mmmm mmmm
59 // Store value from register $S to a memory pointed by address M.
sr(const UDSPInstruction opc)60 void sr(const UDSPInstruction opc)
61 {
62 u8 reg = opc & 0x1F;
63 u16 addr = dsp_fetch_code();
64
65 if (reg >= DSP_REG_ACM0)
66 dsp_dmem_write(addr, dsp_op_read_reg_and_saturate(reg - DSP_REG_ACM0));
67 else
68 dsp_dmem_write(addr, dsp_op_read_reg(reg));
69 }
70
71 // SI @M, #I
72 // 0001 0110 mmmm mmmm
73 // iiii iiii iiii iiii
74 // Store 16-bit immediate value I to a memory location pointed by address
75 // M (M is 8-bit value sign extended).
si(const UDSPInstruction opc)76 void si(const UDSPInstruction opc)
77 {
78 u16 addr = (s8)opc;
79 u16 imm = dsp_fetch_code();
80 dsp_dmem_write(addr, imm);
81 }
82
83 // LRR $D, @$S
84 // 0001 1000 0ssd dddd
85 // Move value from data memory pointed by addressing register $S to register $D.
lrr(const UDSPInstruction opc)86 void lrr(const UDSPInstruction opc)
87 {
88 u8 sreg = (opc >> 5) & 0x3;
89 u8 dreg = opc & 0x1f;
90
91 u16 val = dsp_dmem_read(dsp_op_read_reg(sreg));
92 dsp_op_write_reg(dreg, val);
93 dsp_conditional_extend_accum(dreg);
94 }
95
96 // LRRD $D, @$S
97 // 0001 1000 1ssd dddd
98 // Move value from data memory pointed by addressing register $S to register $D.
99 // Decrement register $S.
lrrd(const UDSPInstruction opc)100 void lrrd(const UDSPInstruction opc)
101 {
102 u8 sreg = (opc >> 5) & 0x3;
103 u8 dreg = opc & 0x1f;
104
105 u16 val = dsp_dmem_read(dsp_op_read_reg(sreg));
106 dsp_op_write_reg(dreg, val);
107 dsp_conditional_extend_accum(dreg);
108 g_dsp.r.ar[sreg] = dsp_decrement_addr_reg(sreg);
109 }
110
111 // LRRI $D, @$S
112 // 0001 1001 0ssd dddd
113 // Move value from data memory pointed by addressing register $S to register $D.
114 // Increment register $S.
lrri(const UDSPInstruction opc)115 void lrri(const UDSPInstruction opc)
116 {
117 u8 sreg = (opc >> 5) & 0x3;
118 u8 dreg = opc & 0x1f;
119
120 u16 val = dsp_dmem_read(dsp_op_read_reg(sreg));
121 dsp_op_write_reg(dreg, val);
122 dsp_conditional_extend_accum(dreg);
123 g_dsp.r.ar[sreg] = dsp_increment_addr_reg(sreg);
124 }
125
126 // LRRN $D, @$S
127 // 0001 1001 1ssd dddd
128 // Move value from data memory pointed by addressing register $S to register $D.
129 // Add indexing register $(0x4+S) to register $S.
lrrn(const UDSPInstruction opc)130 void lrrn(const UDSPInstruction opc)
131 {
132 u8 sreg = (opc >> 5) & 0x3;
133 u8 dreg = opc & 0x1f;
134
135 u16 val = dsp_dmem_read(dsp_op_read_reg(sreg));
136 dsp_op_write_reg(dreg, val);
137 dsp_conditional_extend_accum(dreg);
138 g_dsp.r.ar[sreg] = dsp_increase_addr_reg(sreg, (s16)g_dsp.r.ix[sreg]);
139 }
140
141 // SRR @$D, $S
142 // 0001 1010 0dds ssss
143 // Store value from source register $S to a memory location pointed by
144 // addressing register $D.
srr(const UDSPInstruction opc)145 void srr(const UDSPInstruction opc)
146 {
147 u8 dreg = (opc >> 5) & 0x3;
148 u8 sreg = opc & 0x1f;
149
150 if (sreg >= DSP_REG_ACM0)
151 dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg - DSP_REG_ACM0));
152 else
153 dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg(sreg));
154 }
155
156 // SRRD @$D, $S
157 // 0001 1010 1dds ssss
158 // Store value from source register $S to a memory location pointed by
159 // addressing register $D. Decrement register $D.
srrd(const UDSPInstruction opc)160 void srrd(const UDSPInstruction opc)
161 {
162 u8 dreg = (opc >> 5) & 0x3;
163 u8 sreg = opc & 0x1f;
164
165 if (sreg >= DSP_REG_ACM0)
166 dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg - DSP_REG_ACM0));
167 else
168 dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg(sreg));
169
170 g_dsp.r.ar[dreg] = dsp_decrement_addr_reg(dreg);
171 }
172
173 // SRRI @$D, $S
174 // 0001 1011 0dds ssss
175 // Store value from source register $S to a memory location pointed by
176 // addressing register $D. Increment register $D.
srri(const UDSPInstruction opc)177 void srri(const UDSPInstruction opc)
178 {
179 u8 dreg = (opc >> 5) & 0x3;
180 u8 sreg = opc & 0x1f;
181
182 if (sreg >= DSP_REG_ACM0)
183 dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg - DSP_REG_ACM0));
184 else
185 dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg(sreg));
186
187 g_dsp.r.ar[dreg] = dsp_increment_addr_reg(dreg);
188 }
189
190 // SRRN @$D, $S
191 // 0001 1011 1dds ssss
192 // Store value from source register $S to a memory location pointed by
193 // addressing register $D. Add DSP_REG_IX0 register to register $D.
srrn(const UDSPInstruction opc)194 void srrn(const UDSPInstruction opc)
195 {
196 u8 dreg = (opc >> 5) & 0x3;
197 u8 sreg = opc & 0x1f;
198
199 if (sreg >= DSP_REG_ACM0)
200 dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg - DSP_REG_ACM0));
201 else
202 dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg(sreg));
203
204 g_dsp.r.ar[dreg] = dsp_increase_addr_reg(dreg, (s16)g_dsp.r.ix[dreg]);
205 }
206
207 // ILRR $acD.m, @$arS
208 // 0000 001d 0001 00ss
209 // Move value from instruction memory pointed by addressing register
210 // $arS to mid accumulator register $acD.m.
ilrr(const UDSPInstruction opc)211 void ilrr(const UDSPInstruction opc)
212 {
213 u16 reg = opc & 0x3;
214 u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
215
216 g_dsp.r.ac[dreg - DSP_REG_ACM0].m = dsp_imem_read(g_dsp.r.ar[reg]);
217 dsp_conditional_extend_accum(dreg);
218 }
219
220 // ILRRD $acD.m, @$arS
221 // 0000 001d 0001 01ss
222 // Move value from instruction memory pointed by addressing register
223 // $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
ilrrd(const UDSPInstruction opc)224 void ilrrd(const UDSPInstruction opc)
225 {
226 u16 reg = opc & 0x3;
227 u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
228
229 g_dsp.r.ac[dreg - DSP_REG_ACM0].m = dsp_imem_read(g_dsp.r.ar[reg]);
230 dsp_conditional_extend_accum(dreg);
231 g_dsp.r.ar[reg] = dsp_decrement_addr_reg(reg);
232 }
233
234 // ILRRI $acD.m, @$S
235 // 0000 001d 0001 10ss
236 // Move value from instruction memory pointed by addressing register
237 // $arS to mid accumulator register $acD.m. Increment addressing register $arS.
ilrri(const UDSPInstruction opc)238 void ilrri(const UDSPInstruction opc)
239 {
240 u16 reg = opc & 0x3;
241 u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
242
243 g_dsp.r.ac[dreg - DSP_REG_ACM0].m = dsp_imem_read(g_dsp.r.ar[reg]);
244 dsp_conditional_extend_accum(dreg);
245 g_dsp.r.ar[reg] = dsp_increment_addr_reg(reg);
246 }
247
248 // ILRRN $acD.m, @$arS
249 // 0000 001d 0001 11ss
250 // Move value from instruction memory pointed by addressing register
251 // $arS to mid accumulator register $acD.m. Add corresponding indexing
252 // register $ixS to addressing register $arS.
ilrrn(const UDSPInstruction opc)253 void ilrrn(const UDSPInstruction opc)
254 {
255 u16 reg = opc & 0x3;
256 u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
257
258 g_dsp.r.ac[dreg - DSP_REG_ACM0].m = dsp_imem_read(g_dsp.r.ar[reg]);
259 dsp_conditional_extend_accum(dreg);
260 g_dsp.r.ar[reg] = dsp_increase_addr_reg(reg, (s16)g_dsp.r.ix[reg]);
261 }
262 } // namespace DSP::Interpreter
263