1 //
2 // rsp/vfunctions.c: RSP vector execution functions.
3 //
4 // CEN64: Cycle-Accurate Nintendo 64 Emulator.
5 // Copyright (C) 2015, Tyler J. Stachecki.
6 //
7 // This file is subject to the terms and conditions defined in
8 // 'LICENSE', which is part of this source code package.
9 //
10 
11 #include "../state.hpp"
12 #include "../rsp_op.hpp"
13 #include "rsp_impl.h"
14 #include <stdio.h>
15 
16 #define LOAD_VS() rsp_vect_load_unshuffled_operand(rsp->cp2.regs[vs].e)
17 #define LOAD_VT() rsp_vect_load_and_shuffle_operand(rsp->cp2.regs[vt].e, e)
18 #define STORE_RESULT() rsp_vect_write_operand(rsp->cp2.regs[vd].e, result)
19 
20 #ifdef TRACE_COP2
21 #define TRACE_VU(op) printf(#op " v%u, v%u, v%u[%u]\n", vd, vs, vt, e)
22 #else
23 #define TRACE_VU(op) ((void)0)
24 #endif
25 
26 extern "C"
27 {
28 	//
29 	// VABS
30 	//
RSP_VABS(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)31 	void RSP_VABS(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
32 	{
33 		TRACE_VU(VABS);
34 		uint16_t *acc = rsp->cp2.acc.e;
35 		rsp_vect_t acc_lo;
36 		rsp_vect_t result = rsp_vabs(LOAD_VS(), LOAD_VT(), &acc_lo);
37 		write_acc_lo(acc, acc_lo);
38 		rsp_vect_write_operand(rsp->cp2.regs[vd].e, result);
39 	}
40 
41 	//
42 	// VADD
43 	//
RSP_VADD(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)44 	void RSP_VADD(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
45 	{
46 		TRACE_VU(VADD);
47 		uint16_t *acc = rsp->cp2.acc.e;
48 		rsp_vect_t carry, acc_lo;
49 
50 		carry = read_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e);
51 		rsp_vect_t result = rsp_vadd(LOAD_VS(), LOAD_VT(), carry, &acc_lo);
52 
53 		write_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
54 		write_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
55 		write_acc_lo(acc, acc_lo);
56 		STORE_RESULT();
57 	}
58 
59 	//
60 	// VADDC
61 	//
RSP_VADDC(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)62 	void RSP_VADDC(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
63 	{
64 		TRACE_VU(VADDC);
65 		uint16_t *acc = rsp->cp2.acc.e;
66 		rsp_vect_t sn;
67 
68 		rsp_vect_t result = rsp_vaddc(LOAD_VS(), LOAD_VT(), rsp_vzero(), &sn);
69 		write_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero()); // TODO: Confirm.
70 		write_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e, sn);
71 		write_acc_lo(acc, result);
72 		STORE_RESULT();
73 	}
74 
75 	//
76 	// VAND
77 	// VNAND
78 	//
RSP_VAND(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)79 	void RSP_VAND(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
80 	{
81 		TRACE_VU(VAND);
82 		uint16_t *acc = rsp->cp2.acc.e;
83 		rsp_vect_t result = rsp_vand(LOAD_VS(), LOAD_VT());
84 		write_acc_lo(acc, result);
85 		STORE_RESULT();
86 	}
87 
RSP_VNAND(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)88 	void RSP_VNAND(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
89 	{
90 		TRACE_VU(VNAND);
91 		uint16_t *acc = rsp->cp2.acc.e;
92 		rsp_vect_t result = rsp_vnand(LOAD_VS(), LOAD_VT());
93 		write_acc_lo(acc, result);
94 		STORE_RESULT();
95 	}
96 
97 	//
98 	// VCH
99 	//
RSP_VCH(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)100 	void RSP_VCH(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
101 	{
102 		TRACE_VU(VCH);
103 		uint16_t *acc = rsp->cp2.acc.e;
104 		rsp_vect_t ge, le, sign, eq, vce;
105 
106 		rsp_vect_t result = rsp_vch(LOAD_VS(), LOAD_VT(), rsp_vzero(), &ge, &le, &eq, &sign, &vce);
107 
108 		write_vcc_hi(rsp->cp2.flags[RSP::RSP_VCC].e, ge);
109 		write_vcc_lo(rsp->cp2.flags[RSP::RSP_VCC].e, le);
110 		write_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e, eq);
111 		write_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e, sign);
112 		write_vce(rsp->cp2.flags[RSP::RSP_VCE].e, vce);
113 		write_acc_lo(acc, result);
114 		STORE_RESULT();
115 	}
116 
117 	//
118 	// VCL
119 	//
RSP_VCL(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)120 	void RSP_VCL(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
121 	{
122 		TRACE_VU(VCL);
123 		uint16_t *acc = rsp->cp2.acc.e;
124 		rsp_vect_t ge, le, eq, sign, vce;
125 
126 		ge = read_vcc_hi(rsp->cp2.flags[RSP::RSP_VCC].e);
127 		le = read_vcc_lo(rsp->cp2.flags[RSP::RSP_VCC].e);
128 		eq = read_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e);
129 		sign = read_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e);
130 		vce = read_vce(rsp->cp2.flags[RSP::RSP_VCE].e);
131 
132 		rsp_vect_t result = rsp_vcl(LOAD_VS(), LOAD_VT(), rsp_vzero(), &ge, &le, eq, sign, vce);
133 
134 		write_vcc_hi(rsp->cp2.flags[RSP::RSP_VCC].e, ge);
135 		write_vcc_lo(rsp->cp2.flags[RSP::RSP_VCC].e, le);
136 		write_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
137 		write_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
138 		write_vce(rsp->cp2.flags[RSP::RSP_VCE].e, rsp_vzero());
139 		write_acc_lo(acc, result);
140 		STORE_RESULT();
141 	}
142 
143 	//
144 	// VCR
145 	//
RSP_VCR(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)146 	void RSP_VCR(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
147 	{
148 		TRACE_VU(VCR);
149 		uint16_t *acc = rsp->cp2.acc.e;
150 		rsp_vect_t ge, le;
151 
152 		rsp_vect_t result = rsp_vcr(LOAD_VS(), LOAD_VT(), rsp_vzero(), &ge, &le);
153 
154 #ifdef INTENSE_DEBUG
155 		for (unsigned i = 0; i < 8; i++)
156 			fprintf(stderr, "VD[%d] = %d\n", i, reinterpret_cast<int16_t *>(&result)[i]);
157 #endif
158 
159 		write_vcc_hi(rsp->cp2.flags[RSP::RSP_VCC].e, ge);
160 		write_vcc_lo(rsp->cp2.flags[RSP::RSP_VCC].e, le);
161 		write_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
162 		write_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
163 		write_vce(rsp->cp2.flags[RSP::RSP_VCE].e, rsp_vzero());
164 		write_acc_lo(acc, result);
165 		STORE_RESULT();
166 	}
167 
168 	//
169 	// VEQ
170 	// VGE
171 	// VLT
172 	// VNE
173 	//
RSP_VEQ(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)174 	void RSP_VEQ(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
175 	{
176 		TRACE_VU(VEQ);
177 		uint16_t *acc = rsp->cp2.acc.e;
178 		rsp_vect_t le, eq, sign;
179 
180 		eq = read_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e);
181 		sign = read_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e);
182 
183 		rsp_vect_t result = rsp_veq(LOAD_VS(), LOAD_VT(), rsp_vzero(), &le, eq, sign);
184 
185 		write_vcc_hi(rsp->cp2.flags[RSP::RSP_VCC].e, rsp_vzero());
186 		write_vcc_lo(rsp->cp2.flags[RSP::RSP_VCC].e, le);
187 		write_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
188 		write_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
189 		write_acc_lo(acc, result);
190 		STORE_RESULT();
191 	}
192 
RSP_VGE(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)193 	void RSP_VGE(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
194 	{
195 		TRACE_VU(VGE);
196 		uint16_t *acc = rsp->cp2.acc.e;
197 		rsp_vect_t le, eq, sign;
198 
199 		eq = read_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e);
200 		sign = read_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e);
201 
202 		rsp_vect_t result = rsp_vge(LOAD_VS(), LOAD_VT(), rsp_vzero(), &le, eq, sign);
203 
204 		write_vcc_hi(rsp->cp2.flags[RSP::RSP_VCC].e, rsp_vzero());
205 		write_vcc_lo(rsp->cp2.flags[RSP::RSP_VCC].e, le);
206 		write_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
207 		write_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
208 		write_acc_lo(acc, result);
209 		STORE_RESULT();
210 	}
211 
RSP_VLT(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)212 	void RSP_VLT(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
213 	{
214 		TRACE_VU(VLT);
215 		uint16_t *acc = rsp->cp2.acc.e;
216 		rsp_vect_t le, eq, sign;
217 
218 		eq = read_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e);
219 		sign = read_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e);
220 
221 		rsp_vect_t result = rsp_vlt(LOAD_VS(), LOAD_VT(), rsp_vzero(), &le, eq, sign);
222 
223 		write_vcc_hi(rsp->cp2.flags[RSP::RSP_VCC].e, rsp_vzero());
224 		write_vcc_lo(rsp->cp2.flags[RSP::RSP_VCC].e, le);
225 		write_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
226 		write_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
227 		write_acc_lo(acc, result);
228 		STORE_RESULT();
229 	}
230 
RSP_VNE(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)231 	void RSP_VNE(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
232 	{
233 		TRACE_VU(VNE);
234 		uint16_t *acc = rsp->cp2.acc.e;
235 		rsp_vect_t le, eq, sign;
236 
237 		eq = read_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e);
238 		sign = read_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e);
239 
240 		rsp_vect_t result = rsp_vne(LOAD_VS(), LOAD_VT(), rsp_vzero(), &le, eq, sign);
241 #ifdef INTENSE_DEBUG
242 		for (unsigned i = 0; i < 8; i++)
243 			fprintf(stderr, "VD[%d] = %d\n", i, reinterpret_cast<int16_t *>(&result)[i]);
244 #endif
245 
246 		write_vcc_hi(rsp->cp2.flags[RSP::RSP_VCC].e, rsp_vzero());
247 		write_vcc_lo(rsp->cp2.flags[RSP::RSP_VCC].e, le);
248 		write_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
249 		write_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
250 		write_acc_lo(acc, result);
251 		STORE_RESULT();
252 	}
253 
254 	//
255 	// VINVALID
256 	//
RSP_VINVALID(RSP::CPUState *,unsigned,unsigned,unsigned,unsigned)257 	void RSP_VINVALID(RSP::CPUState *, unsigned, unsigned, unsigned, unsigned)
258 	{
259 		fprintf(stderr, "Unimplemented ...\n");
260 	}
261 
262 	//
263 	// VMACF
264 	// VMACU
265 	//
RSP_VMACF(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)266 	void RSP_VMACF(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
267 	{
268 		TRACE_VU(VMACF);
269 		uint16_t *acc = rsp->cp2.acc.e;
270 		rsp_vect_t acc_lo, acc_md, acc_hi, result;
271 		acc_lo = read_acc_lo(acc);
272 		acc_md = read_acc_md(acc);
273 		acc_hi = read_acc_hi(acc);
274 
275 		result = rsp_vmacf_vmacu<false>(LOAD_VS(), LOAD_VT(), rsp_vzero(), &acc_lo, &acc_md, &acc_hi);
276 
277 		write_acc_lo(acc, acc_lo);
278 		write_acc_md(acc, acc_md);
279 		write_acc_hi(acc, acc_hi);
280 		STORE_RESULT();
281 	}
282 
RSP_VMACU(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)283 	void RSP_VMACU(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
284 	{
285 		TRACE_VU(VMACU);
286 		uint16_t *acc = rsp->cp2.acc.e;
287 		rsp_vect_t acc_lo, acc_md, acc_hi, result;
288 		acc_lo = read_acc_lo(acc);
289 		acc_md = read_acc_md(acc);
290 		acc_hi = read_acc_hi(acc);
291 
292 		result = rsp_vmacf_vmacu<true>(LOAD_VS(), LOAD_VT(), rsp_vzero(), &acc_lo, &acc_md, &acc_hi);
293 
294 		write_acc_lo(acc, acc_lo);
295 		write_acc_md(acc, acc_md);
296 		write_acc_hi(acc, acc_hi);
297 		STORE_RESULT();
298 	}
299 
300 	//
301 	// VMADH
302 	// VMUDH
303 	//
RSP_VMADH(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)304 	void RSP_VMADH(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
305 	{
306 		TRACE_VU(VMADH);
307 		uint16_t *acc = rsp->cp2.acc.e;
308 		rsp_vect_t acc_lo, acc_md, acc_hi, result;
309 
310 		acc_lo = read_acc_lo(acc);
311 		acc_md = read_acc_md(acc);
312 		acc_hi = read_acc_hi(acc);
313 
314 		result = rsp_vmadh_vmudh<true>(LOAD_VS(), LOAD_VT(), rsp_vzero(), &acc_lo, &acc_md, &acc_hi);
315 
316 		write_acc_lo(acc, acc_lo);
317 		write_acc_md(acc, acc_md);
318 		write_acc_hi(acc, acc_hi);
319 		STORE_RESULT();
320 	}
321 
RSP_VMUDH(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)322 	void RSP_VMUDH(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
323 	{
324 		TRACE_VU(VMUDH);
325 		uint16_t *acc = rsp->cp2.acc.e;
326 		rsp_vect_t acc_lo, acc_md, acc_hi, result;
327 
328 		acc_lo = read_acc_lo(acc);
329 		acc_md = read_acc_md(acc);
330 		acc_hi = read_acc_hi(acc);
331 
332 		result = rsp_vmadh_vmudh<false>(LOAD_VS(), LOAD_VT(), rsp_vzero(), &acc_lo, &acc_md, &acc_hi);
333 
334 		write_acc_lo(acc, acc_lo);
335 		write_acc_md(acc, acc_md);
336 		write_acc_hi(acc, acc_hi);
337 		STORE_RESULT();
338 	}
339 
340 	//
341 	// VMADL
342 	// VMUDL
343 	//
RSP_VMADL(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)344 	void RSP_VMADL(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
345 	{
346 		TRACE_VU(VMADL);
347 		uint16_t *acc = rsp->cp2.acc.e;
348 		rsp_vect_t acc_lo, acc_md, acc_hi, result;
349 
350 		acc_lo = read_acc_lo(acc);
351 		acc_md = read_acc_md(acc);
352 		acc_hi = read_acc_hi(acc);
353 
354 		result = rsp_vmadl_vmudl<true>(LOAD_VS(), LOAD_VT(), rsp_vzero(), &acc_lo, &acc_md, &acc_hi);
355 
356 		write_acc_lo(acc, acc_lo);
357 		write_acc_md(acc, acc_md);
358 		write_acc_hi(acc, acc_hi);
359 		STORE_RESULT();
360 	}
361 
RSP_VMUDL(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)362 	void RSP_VMUDL(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
363 	{
364 		TRACE_VU(VMUDL);
365 		uint16_t *acc = rsp->cp2.acc.e;
366 		rsp_vect_t acc_lo, acc_md, acc_hi, result;
367 
368 		acc_lo = read_acc_lo(acc);
369 		acc_md = read_acc_md(acc);
370 		acc_hi = read_acc_hi(acc);
371 
372 		result = rsp_vmadl_vmudl<false>(LOAD_VS(), LOAD_VT(), rsp_vzero(), &acc_lo, &acc_md, &acc_hi);
373 
374 		write_acc_lo(acc, acc_lo);
375 		write_acc_md(acc, acc_md);
376 		write_acc_hi(acc, acc_hi);
377 		STORE_RESULT();
378 	}
379 
380 	//
381 	// VMADM
382 	// VMUDM
383 	//
RSP_VMADM(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)384 	void RSP_VMADM(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
385 	{
386 		TRACE_VU(VMADM);
387 		uint16_t *acc = rsp->cp2.acc.e;
388 		rsp_vect_t acc_lo, acc_md, acc_hi, result;
389 
390 		acc_lo = read_acc_lo(acc);
391 		acc_md = read_acc_md(acc);
392 		acc_hi = read_acc_hi(acc);
393 
394 		result = rsp_vmadm_vmudm<true>(LOAD_VS(), LOAD_VT(), rsp_vzero(), &acc_lo, &acc_md, &acc_hi);
395 
396 		write_acc_lo(acc, acc_lo);
397 		write_acc_md(acc, acc_md);
398 		write_acc_hi(acc, acc_hi);
399 		STORE_RESULT();
400 	}
401 
RSP_VMUDM(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)402 	void RSP_VMUDM(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
403 	{
404 		TRACE_VU(VMUDM);
405 		uint16_t *acc = rsp->cp2.acc.e;
406 		rsp_vect_t acc_lo, acc_md, acc_hi, result;
407 
408 		acc_lo = read_acc_lo(acc);
409 		acc_md = read_acc_md(acc);
410 		acc_hi = read_acc_hi(acc);
411 
412 		result = rsp_vmadm_vmudm<false>(LOAD_VS(), LOAD_VT(), rsp_vzero(), &acc_lo, &acc_md, &acc_hi);
413 
414 		write_acc_lo(acc, acc_lo);
415 		write_acc_md(acc, acc_md);
416 		write_acc_hi(acc, acc_hi);
417 		STORE_RESULT();
418 	}
419 
420 	//
421 	// VMADN
422 	// VMUDN
423 	//
RSP_VMADN(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)424 	void RSP_VMADN(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
425 	{
426 		TRACE_VU(VMADN);
427 		uint16_t *acc = rsp->cp2.acc.e;
428 		rsp_vect_t acc_lo, acc_md, acc_hi, result;
429 
430 		acc_lo = read_acc_lo(acc);
431 		acc_md = read_acc_md(acc);
432 		acc_hi = read_acc_hi(acc);
433 
434 		result = rsp_vmadn_vmudn<true>(LOAD_VS(), LOAD_VT(), rsp_vzero(), &acc_lo, &acc_md, &acc_hi);
435 
436 		write_acc_lo(acc, acc_lo);
437 		write_acc_md(acc, acc_md);
438 		write_acc_hi(acc, acc_hi);
439 		STORE_RESULT();
440 	}
441 
RSP_VMUDN(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)442 	void RSP_VMUDN(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
443 	{
444 		TRACE_VU(VMUDN);
445 		uint16_t *acc = rsp->cp2.acc.e;
446 		rsp_vect_t acc_lo, acc_md, acc_hi, result;
447 
448 		acc_lo = read_acc_lo(acc);
449 		acc_md = read_acc_md(acc);
450 		acc_hi = read_acc_hi(acc);
451 
452 		result = rsp_vmadn_vmudn<false>(LOAD_VS(), LOAD_VT(), rsp_vzero(), &acc_lo, &acc_md, &acc_hi);
453 
454 		write_acc_lo(acc, acc_lo);
455 		write_acc_md(acc, acc_md);
456 		write_acc_hi(acc, acc_hi);
457 		STORE_RESULT();
458 	}
459 
460 	//
461 	// VMOV
462 	//
RSP_VMOV(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)463 	void RSP_VMOV(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
464 	{
465 		TRACE_VU(VMOV);
466 		uint16_t *acc = rsp->cp2.acc.e;
467 		unsigned de = vs & 0x7;
468 		write_acc_lo(acc, LOAD_VT());
469 		__m128i result = rsp_vmov(rsp, vt, e, vd, de);
470 		STORE_RESULT();
471 	}
472 
473 	//
474 	// VMRG
475 	//
RSP_VMRG(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)476 	void RSP_VMRG(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
477 	{
478 		TRACE_VU(VMRG);
479 		uint16_t *acc = rsp->cp2.acc.e;
480 		rsp_vect_t le;
481 
482 		le = read_vcc_lo(rsp->cp2.flags[RSP::RSP_VCC].e);
483 		rsp_vect_t result = rsp_vmrg(LOAD_VS(), LOAD_VT(), le);
484 		write_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
485 		write_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
486 		write_acc_lo(acc, result);
487 		STORE_RESULT();
488 	}
489 
490 	//
491 	// VMULF
492 	// VMULU
493 	//
RSP_VMULF(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)494 	void RSP_VMULF(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
495 	{
496 		TRACE_VU(VMULF);
497 		uint16_t *acc = rsp->cp2.acc.e;
498 		rsp_vect_t acc_lo, acc_md, acc_hi, result;
499 
500 		result = rsp_vmulf_vmulu<false>(LOAD_VS(), LOAD_VT(), rsp_vzero(), &acc_lo, &acc_md, &acc_hi);
501 
502 		write_acc_lo(acc, acc_lo);
503 		write_acc_md(acc, acc_md);
504 		write_acc_hi(acc, acc_hi);
505 		STORE_RESULT();
506 	}
507 
RSP_VMULU(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)508 	void RSP_VMULU(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
509 	{
510 		TRACE_VU(VMULU);
511 		uint16_t *acc = rsp->cp2.acc.e;
512 		rsp_vect_t acc_lo, acc_md, acc_hi, result;
513 
514 		result = rsp_vmulf_vmulu<true>(LOAD_VS(), LOAD_VT(), rsp_vzero(), &acc_lo, &acc_md, &acc_hi);
515 
516 		write_acc_lo(acc, acc_lo);
517 		write_acc_md(acc, acc_md);
518 		write_acc_hi(acc, acc_hi);
519 		STORE_RESULT();
520 	}
521 
522 	//
523 	// VNOP
524 	//
RSP_VNOP(RSP::CPUState *,unsigned,unsigned,unsigned,unsigned)525 	void RSP_VNOP(RSP::CPUState *, unsigned, unsigned, unsigned, unsigned)
526 	{
527 	}
528 
529 	//
530 	// VOR
531 	// VNOR
532 	//
RSP_VOR(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)533 	void RSP_VOR(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
534 	{
535 		TRACE_VU(VOR);
536 		uint16_t *acc = rsp->cp2.acc.e;
537 
538 		rsp_vect_t result = rsp_vor(LOAD_VS(), LOAD_VT());
539 
540 		write_acc_lo(acc, result);
541 		STORE_RESULT();
542 	}
543 
RSP_VNOR(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)544 	void RSP_VNOR(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
545 	{
546 		TRACE_VU(VNOR);
547 		uint16_t *acc = rsp->cp2.acc.e;
548 
549 		rsp_vect_t result = rsp_vnor(LOAD_VS(), LOAD_VT());
550 
551 		write_acc_lo(acc, result);
552 		STORE_RESULT();
553 	}
554 
555 	//
556 	// VRCP
557 	// VRCPL
558 	// VRSQ
559 	// VRSQL
560 	//
RSP_VRCP(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)561 	void RSP_VRCP(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
562 	{
563 		TRACE_VU(VRCP);
564 		uint16_t *acc = rsp->cp2.acc.e;
565 		unsigned de = vs & 0x7;
566 		e &= 0x7;
567 
568 		write_acc_lo(acc, LOAD_VT());
569 
570 		rsp->cp2.dp_flag = 0;
571 		rsp_vect_t result = rsp_vrcp_vrsq<false>(rsp, 0, vt, e, vd, de);
572 		STORE_RESULT();
573 	}
574 
RSP_VRCPL(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)575 	void RSP_VRCPL(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
576 	{
577 		TRACE_VU(VRCPL);
578 		uint16_t *acc = rsp->cp2.acc.e;
579 		unsigned de = vs & 0x7;
580 		e &= 0x7;
581 
582 		write_acc_lo(acc, LOAD_VT());
583 
584 		int dp = rsp->cp2.dp_flag & 1;
585 		rsp->cp2.dp_flag = 0;
586 
587 		rsp_vect_t result = rsp_vrcp_vrsq<false>(rsp, dp, vt, e, vd, de);
588 		STORE_RESULT();
589 	}
590 
RSP_VRSQ(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)591 	void RSP_VRSQ(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
592 	{
593 		TRACE_VU(VRSQ);
594 		uint16_t *acc = rsp->cp2.acc.e;
595 		unsigned de = vs & 0x7;
596 		e &= 0x7;
597 
598 		write_acc_lo(acc, LOAD_VT());
599 
600 		rsp->cp2.dp_flag = 0;
601 		rsp_vect_t result = rsp_vrcp_vrsq<true>(rsp, 0, vt, e, vd, de);
602 		STORE_RESULT();
603 	}
604 
RSP_VRSQL(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)605 	void RSP_VRSQL(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
606 	{
607 		TRACE_VU(VRSQL);
608 		uint16_t *acc = rsp->cp2.acc.e;
609 		unsigned de = vs & 0x7;
610 		e &= 0x7;
611 
612 		write_acc_lo(acc, LOAD_VT());
613 
614 		int dp = rsp->cp2.dp_flag & 1;
615 		rsp->cp2.dp_flag = 0;
616 
617 		rsp_vect_t result = rsp_vrcp_vrsq<true>(rsp, dp, vt, e, vd, de);
618 		STORE_RESULT();
619 	}
620 
621 	//
622 	// VRCPH
623 	// VRSQH
624 	//
RSP_VRCPH(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)625 	void RSP_VRCPH(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
626 	{
627 		TRACE_VU(VRCPH);
628 		uint16_t *acc = rsp->cp2.acc.e;
629 		unsigned de = vs & 0x7;
630 		e &= 0x7;
631 
632 		write_acc_lo(acc, LOAD_VT());
633 
634 		// Specify double-precision for VRCPL on the next pass.
635 		rsp->cp2.dp_flag = 1;
636 
637 		rsp_vect_t result = rsp_vdivh(rsp, vt, e, vd, de);
638 		STORE_RESULT();
639 	}
640 
RSP_VRSQH(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)641 	void RSP_VRSQH(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
642 	{
643 		TRACE_VU(VRSQH);
644 		uint16_t *acc = rsp->cp2.acc.e;
645 		unsigned de = vs & 0x7;
646 		e &= 0x7;
647 
648 		write_acc_lo(acc, LOAD_VT());
649 
650 		// Specify double-precision for VRCPL on the next pass.
651 		rsp->cp2.dp_flag = 1;
652 
653 		rsp_vect_t result = rsp_vdivh(rsp, vt, e, vd, de);
654 		STORE_RESULT();
655 	}
656 
657 	//
658 	// VSAR
659 	//
RSP_VSAR(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)660 	void RSP_VSAR(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
661 	{
662 		TRACE_VU(VSAR);
663 		uint16_t *acc = rsp->cp2.acc.e;
664 		rsp_vect_t result;
665 
666 		switch (e)
667 		{
668 		case 8:
669 			result = read_acc_hi(acc);
670 			break;
671 		case 9:
672 			result = read_acc_md(acc);
673 			break;
674 		case 10:
675 			result = read_acc_lo(acc);
676 			break;
677 		default:
678 			result = rsp_vzero();
679 			break;
680 		}
681 
682 		STORE_RESULT();
683 	}
684 
685 	//
686 	// VSUB
687 	//
RSP_VSUB(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)688 	void RSP_VSUB(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
689 	{
690 		TRACE_VU(VSUB);
691 		uint16_t *acc = rsp->cp2.acc.e;
692 		rsp_vect_t carry, acc_lo;
693 
694 		carry = read_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e);
695 
696 		rsp_vect_t result = rsp_vsub(LOAD_VS(), LOAD_VT(), carry, &acc_lo);
697 
698 		write_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
699 		write_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e, rsp_vzero());
700 		write_acc_lo(acc, acc_lo);
701 		STORE_RESULT();
702 	}
703 
704 	//
705 	// VSUBC
706 	//
RSP_VSUBC(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)707 	void RSP_VSUBC(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
708 	{
709 		TRACE_VU(VSUBC);
710 		uint16_t *acc = rsp->cp2.acc.e;
711 		rsp_vect_t eq, sn;
712 
713 		rsp_vect_t result = rsp_vsubc(LOAD_VS(), LOAD_VT(), rsp_vzero(), &eq, &sn);
714 
715 		write_vco_hi(rsp->cp2.flags[RSP::RSP_VCO].e, eq);
716 		write_vco_lo(rsp->cp2.flags[RSP::RSP_VCO].e, sn);
717 		write_acc_lo(acc, result);
718 		STORE_RESULT();
719 	}
720 
721 	//
722 	// VXOR
723 	// VNXOR
724 	//
RSP_VXOR(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)725 	void RSP_VXOR(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
726 	{
727 		TRACE_VU(VXOR);
728 		uint16_t *acc = rsp->cp2.acc.e;
729 
730 		rsp_vect_t result = rsp_vxor(LOAD_VS(), LOAD_VT());
731 
732 		write_acc_lo(acc, result);
733 		STORE_RESULT();
734 	}
735 
RSP_VNXOR(RSP::CPUState * rsp,unsigned vd,unsigned vs,unsigned vt,unsigned e)736 	void RSP_VNXOR(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
737 	{
738 		TRACE_VU(VXNOR);
739 		uint16_t *acc = rsp->cp2.acc.e;
740 
741 		rsp_vect_t result = rsp_vnxor(LOAD_VS(), LOAD_VT());
742 
743 		write_acc_lo(acc, result);
744 		STORE_RESULT();
745 	}
746 
747 	// RESERVED
RSP_RESERVED(RSP::CPUState * rsp,unsigned vd,unsigned,unsigned,unsigned)748 	void RSP_RESERVED(RSP::CPUState *rsp, unsigned vd, unsigned, unsigned, unsigned)
749 	{
750 		rsp_vect_t result = rsp_vzero();
751 		STORE_RESULT();
752 	}
753 }
754