RSP LLE plugin. Compile and run (slowly, eat 50% CPU) on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-rsp-z64 / src / rsp_opinfo.cpp
CommitLineData
fc5d46b4 1/*
2 * z64
3 *
4 * Copyright (C) 2007 ziggy
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20**/
21
22#include "rsp_opinfo.h"
23
24static const int vector_elements_2[16][8] =
25{
26 { 0, 1, 2, 3, 4, 5, 6, 7 }, // none
27 { 0, 1, 2, 3, 4, 5, 6, 7 }, // ???
28 { 0, 0, 2, 2, 4, 4, 6, 6 }, // 0q
29 { 1, 1, 3, 3, 5, 5, 7, 7 }, // 1q
30 { 0, 0, 0, 0, 4, 4, 4, 4 }, // 0h
31 { 1, 1, 1, 1, 5, 5, 5, 5 }, // 1h
32 { 2, 2, 2, 2, 6, 6, 6, 6 }, // 2h
33 { 3, 3, 3, 3, 7, 7, 7, 7 }, // 3h
34 { 0, 0, 0, 0, 0, 0, 0, 0 }, // 0
35 { 1, 1, 1, 1, 1, 1, 1, 1 }, // 1
36 { 2, 2, 2, 2, 2, 2, 2, 2 }, // 2
37 { 3, 3, 3, 3, 3, 3, 3, 3 }, // 3
38 { 4, 4, 4, 4, 4, 4, 4, 4 }, // 4
39 { 5, 5, 5, 5, 5, 5, 5, 5 }, // 5
40 { 6, 6, 6, 6, 6, 6, 6, 6 }, // 6
41 { 7, 7, 7, 7, 7, 7, 7, 7 }, // 7
42};
43
44void rsp_get_opinfo(UINT32 op, rsp_opinfo_t * info)
45{
46 int op2;
47 int i;
48 info->op = op;
49 switch (op>>26) {
50 case 0: /* SPECIAL */
51 op2 = RSP_SPECIAL_OFFS + (op&0x3f);
52 break;
53 case 0x12: /* COP2 */
54 if (((op>>21)&0x1f) >= 0x10)
55 op2 = RSP_COP2_2_OFFS + (op & 0x3f);
56 else
57 op2 = RSP_COP2_1_OFFS + ((op >> 21) & 0x1f);
58 break;
59 case 0x32: /* LWC2 */
60 op2 = RSP_LWC2_OFFS + ((op>>11)&0x1f);
61 break;
62 case 0x3a: /* SWC2 */
63 op2 = RSP_SWC2_OFFS + ((op>>11)&0x1f);
64 break;
65 default:
66 op2 = RSP_BASIC_OFFS + (op>>26);
67 if (op2 == RSP_REGIMM) {
68 switch (RTREG)
69 {
70 case 0x00: /* BLTZ */
71 op2 = RSP_BLTZ;
72 break;
73 case 0x01: /* BGEZ */
74 op2 = RSP_BGEZ;
75 break;
76 case 0x11: /* BGEZAL */
77 op2 = RSP_BGEZAL;
78 break;
79 }
80 }
81 }
82 info->op2 = op2;
83
84 memset(&info->used, 0, sizeof(info->used));
85 memset(&info->set, 0, sizeof(info->set));
86 info->used.accu = info->used.flag = 0;
87 info->set.accu = info->set.flag = 0;
88 info->flags = 0;
89
90 int dest = (op >> 16) & 0x1f;
91 int index = (op >> 7) & 0xf;
92 int offset = (op & 0x7f);
93 if (offset & 0x40)
94 offset |= 0xffffffc0;
95
96 switch(op2) {
97 case RSP_SPECIAL:
98 case RSP_BLTZ:
99 info->flags = RSP_OPINFO_JUMP | RSP_OPINFO_COND | RSP_OPINFO_USEPC;
100 break;
101 case RSP_BGEZ:
102 info->flags = RSP_OPINFO_JUMP | RSP_OPINFO_COND | RSP_OPINFO_USEPC;
103 break;
104 case RSP_BGEZAL:
105 info->flags = RSP_OPINFO_JUMP | RSP_OPINFO_COND | RSP_OPINFO_LINK | RSP_OPINFO_USEPC;
106 break;
107 case RSP_J:
108 info->flags = RSP_OPINFO_JUMP;
109 break;
110 case RSP_JAL:
111 info->flags = RSP_OPINFO_JUMP | RSP_OPINFO_LINK | RSP_OPINFO_USEPC;
112 break;
113 case RSP_BEQ:
114 case RSP_BNE:
115 case RSP_BLEZ:
116 case RSP_BGTZ:
117 info->flags = RSP_OPINFO_JUMP | RSP_OPINFO_COND | RSP_OPINFO_USEPC;
118 break;
119 case RSP_ADDI:
120 case RSP_ADDIU:
121 case RSP_SLTI:
122 case RSP_SLTIU:
123 case RSP_ANDI:
124 case RSP_ORI:
125 case RSP_XORI:
126 case RSP_LUI:
127 case RSP_COP0:
128 case RSP_LB:
129 case RSP_LH:
130 case RSP_LW:
131 case RSP_LBU:
132 case RSP_LHU:
133 case RSP_SB:
134 case RSP_SH:
135 case RSP_SW:
136 break;
137
138 case RSP_SLL:
139 case RSP_SRL:
140 case RSP_SRA:
141 case RSP_SLLV:
142 case RSP_SRLV:
143 case RSP_SRAV:
144 break;
145
146 case RSP_JR:
147 info->flags = RSP_OPINFO_JUMP;
148 break;
149 case RSP_JALR:
150 info->flags = RSP_OPINFO_JUMP | RSP_OPINFO_LINK | RSP_OPINFO_USEPC;
151 break;
152 case RSP_BREAK:
153 info->flags = RSP_OPINFO_BREAK;
154 break;
155
156 case RSP_ADD:
157 case RSP_ADDU:
158 case RSP_SUB:
159 case RSP_SUBU:
160 case RSP_AND:
161 case RSP_OR:
162 case RSP_XOR:
163 case RSP_NOR:
164 case RSP_SLT:
165 case RSP_SLTU:
166 break;
167
168 case RSP_MFC2:
169 {
170 int el = op >> 7;
171 RSP_SET_VEC_I(info->used, VS1REG, ((el+0)&0xf)>>1);
172 RSP_SET_VEC_I(info->used, VS1REG, ((el+1)&0xf)>>1);
173 break;
174 }
175 case RSP_CFC2:
176 RSP_SET_FLAG_I(info->used, RDREG & 3);
177 break;
178 case RSP_MTC2:
179 {
180 int el = op >> 7;
181 RSP_SET_VEC_I(info->set, VS1REG, ((el+0)&0xf)>>1);
182 RSP_SET_VEC_I(info->set, VS1REG, ((el+1)&0xf)>>1);
183 break;
184 }
185 case RSP_CTC2:
186 RSP_SET_FLAG_I(info->set, RDREG & 3);
187 break;
188
189
190 case RSP_LBV:
191 RSP_SET_VEC_I(info->set, dest, index>>1);
192 break;
193 case RSP_LSV:
194 for (i=index; i<index+2; i++)
195 RSP_SET_VEC_I(info->set, dest, (i>>1)&7);
196 break;
197 case RSP_LLV:
198 for (i=index; i<index+4; i++)
199 RSP_SET_VEC_I(info->set, dest, (i>>1)&7);
200 break;
201 case RSP_LDV:
202 for (i=index; i<index+8; i++)
203 RSP_SET_VEC_I(info->set, dest, (i>>1)&7);
204 break;
205 case RSP_LQV:
206 case RSP_LRV:
207 // WARNING WARNING WARNING
208 // we assume this instruction always used to load the full vector
209 // i.e. the address is always 16 bytes aligned
210 // for (i=0; i<8; i++)
211 // RSP_SET_VEC_I(info->set, dest, i);
212 break;
213 case RSP_LPV:
214 case RSP_LUV:
215 case RSP_LHV:
216 case RSP_LWV:
217 for (i=0; i<8; i++)
218 RSP_SET_VEC_I(info->set, dest, i);
219 break;
220 case RSP_LFV:
221 for (i=(index>>1); i<(index>>1)+4; i++)
222 RSP_SET_VEC_I(info->set, dest, i);
223 break;
224 case RSP_LTV:
225 {
226 // 31 25 20 15 10 6 0
227 // --------------------------------------------------
228 // | 110010 | BBBBB | TTTTT | 01011 | IIII | Offset |
229 // --------------------------------------------------
230 //
231 // Loads one element to maximum of 8 vectors, while incrementing element index
232
233 // FIXME: has a small problem with odd indices
234
235 int element;
236 int vs = dest;
237 int ve = dest + 8;
238 if (ve > 32)
239 ve = 32;
240
241 element = 7 - (index >> 1);
242
243 if (index & 1)
244 log(M64MSG_ERROR, "RSP: LTV: index = %d\n", index);
245
246 for (i=vs; i < ve; i++)
247 {
248 element = ((8 - (index >> 1) + (i-vs)) << 1);
249 RSP_SET_VEC_I(info->set, i, (element & 0xf)>>1);
250 RSP_SET_VEC_I(info->set, i, ((element+1) & 0xf)>>1);
251 }
252 break;
253 }
254
255 case RSP_SBV:
256 RSP_SET_VEC_I(info->used, dest, index>>1);
257 break;
258 case RSP_SSV:
259 for (i=index; i<index+2; i++)
260 RSP_SET_VEC_I(info->used, dest, (i>>1)&7);
261 break;
262 case RSP_SLV:
263 for (i=index; i<index+4; i++)
264 RSP_SET_VEC_I(info->used, dest, (i>>1)&7);
265 break;
266 case RSP_SDV:
267 for (i=index; i<index+8; i++)
268 RSP_SET_VEC_I(info->used, dest, (i>>1)&7);
269 break;
270 case RSP_SQV:
271 case RSP_SRV:
272 // WARNING WARNING WARNING
273 // we assume this instruction always used to store the full vector
274 // i.e. the address is always 16 bytes aligned
275 for (i=0; i<8; i++)
276 RSP_SET_VEC_I(info->used, dest, i);
277 break;
278 case RSP_SPV:
279 case RSP_SUV:
280 case RSP_SHV:
281 case RSP_SWV:
282 for (i=0; i<8; i++)
283 RSP_SET_VEC_I(info->used, dest, i);
284 break;
285 case RSP_SFV:
286 for (i=(index>>1); i<(index>>1)+4; i++)
287 RSP_SET_VEC_I(info->used, dest, i);
288 break;
289 case RSP_STV:
290 {
291 // 31 25 20 15 10 6 0
292 // --------------------------------------------------
293 // | 111010 | BBBBB | TTTTT | 01011 | IIII | Offset |
294 // --------------------------------------------------
295 //
296 // Stores one element from maximum of 8 vectors, while incrementing element index
297
298 int element;
299 int vs = dest;
300 int ve = dest + 8;
301 if (ve > 32)
302 ve = 32;
303
304 element = 8 - (index >> 1);
305 if (index & 0x1)
306 log(M64MSG_ERROR, "RSP: STV: index = %d at %08X\n", index, rsp.ppc);
307
308 for (i=vs; i < ve; i++)
309 {
310 RSP_SET_VEC_I(info->used, i, element & 0x7);
311 element++;
312 }
313 break;
314 }
315
316 case RSP_VMULF:
317 case RSP_VMULU:
318 case RSP_VMUDL:
319 case RSP_VMUDM:
320 case RSP_VMUDN:
321 case RSP_VMUDH:
322 {
323 for (i=0; i < 8; i++)
324 {
325 int sel = VEC_EL_2(EL, i);
326 RSP_SET_VEC_I(info->used, VS1REG, i);
327 RSP_SET_VEC_I(info->used, VS2REG, sel);
328 RSP_SET_VEC_I(info->set, VDREG, i);
329 RSP_SET_ACCU_I(info->set, i, 14);
330 }
331 break;
332 }
333 case RSP_VMACF:
334 case RSP_VMACU:
335 case RSP_VMADL:
336 case RSP_VMADM:
337 case RSP_VMADN:
338 case RSP_VMADH:
339 {
340 for (i=0; i < 8; i++)
341 {
342 int sel = VEC_EL_2(EL, i);
343 RSP_SET_VEC_I(info->used, VS1REG, i);
344 RSP_SET_VEC_I(info->used, VS2REG, sel);
345 RSP_SET_VEC_I(info->set, VDREG, i);
346 RSP_SET_ACCU_I(info->used, i, 14);
347 RSP_SET_ACCU_I(info->set, i, 14);
348 }
349 break;
350 }
351 case RSP_VADD:
352 case RSP_VSUB:
353 {
354 for (i=0; i < 8; i++)
355 {
356 int sel = VEC_EL_2(EL, i);
357 RSP_SET_VEC_I(info->used, VS1REG, i);
358 RSP_SET_VEC_I(info->used, VS2REG, sel);
359 RSP_SET_VEC_I(info->set, VDREG, i);
360 RSP_SET_ACCU_I(info->set, i, 2);
361 }
362 RSP_SET_FLAG_I(info->used, 0);
363 RSP_SET_FLAG_I(info->set, 0);
364 break;
365 }
366 case RSP_VABS:
367 {
368 for (i=0; i < 8; i++)
369 {
370 int sel = VEC_EL_2(EL, i);
371 RSP_SET_VEC_I(info->used, VS1REG, i);
372 RSP_SET_VEC_I(info->used, VS2REG, sel);
373 RSP_SET_VEC_I(info->set, VDREG, i);
374 RSP_SET_ACCU_I(info->set, i, 2);
375 }
376 break;
377 }
378 case RSP_VADDC:
379 case RSP_VSUBC:
380 {
381 for (i=0; i < 8; i++)
382 {
383 int sel = VEC_EL_2(EL, i);
384 RSP_SET_VEC_I(info->used, VS1REG, i);
385 RSP_SET_VEC_I(info->used, VS2REG, sel);
386 RSP_SET_VEC_I(info->set, VDREG, i);
387 RSP_SET_ACCU_I(info->set, i, 2);
388 }
389 RSP_SET_FLAG_I(info->set, 0);
390 break;
391 }
392 case RSP_VSAW:
393 switch (EL)
394 {
395 case 0x08: // VSAWH
396 {
397 for (i=0; i < 8; i++)
398 {
399 RSP_SET_VEC_I(info->set, VDREG, i);
400 RSP_SET_ACCU_I(info->used, i, 8);
401 }
402 break;
403 }
404 case 0x09: // VSAWM
405 {
406 for (i=0; i < 8; i++)
407 {
408 RSP_SET_VEC_I(info->set, VDREG, i);
409 RSP_SET_ACCU_I(info->used, i, 4);
410 }
411 break;
412 }
413 case 0x0a: // VSAWL
414 {
415 for (i=0; i < 8; i++)
416 {
417 RSP_SET_VEC_I(info->set, VDREG, i);
418 RSP_SET_ACCU_I(info->used, i, 2);
419 }
420 break;
421 }
422 default:
423 log(M64MSG_ERROR, "RSP: VSAW: el = %d\n", EL);
424 }
425 break;
426 case RSP_VLT:
427 {
428 for (i=0; i < 8; i++)
429 {
430 int sel = VEC_EL_2(EL, i);
431 RSP_SET_VEC_I(info->used, VS1REG, i);
432 RSP_SET_VEC_I(info->used, VS2REG, sel);
433 RSP_SET_VEC_I(info->set, VDREG, i);
434 RSP_SET_ACCU_I(info->set, i, 2);
435 }
436 RSP_SET_FLAG_I(info->set, 0);
437 RSP_SET_FLAG_I(info->set, 1);
438 break;
439 }
440 case RSP_VEQ:
441 case RSP_VNE:
442 case RSP_VGE:
443 {
444 for (i=0; i < 8; i++)
445 {
446 int sel = VEC_EL_2(EL, i);
447 RSP_SET_VEC_I(info->used, VS1REG, i);
448 RSP_SET_VEC_I(info->used, VS2REG, sel);
449 RSP_SET_VEC_I(info->set, VDREG, i);
450 RSP_SET_ACCU_I(info->set, i, 2);
451 }
452 RSP_SET_FLAG_I(info->used, 0);
453 RSP_SET_FLAG_I(info->set, 0);
454 RSP_SET_FLAG_I(info->set, 1);
455 break;
456 }
457 case RSP_VCL:
458 {
459 for (i=0; i < 8; i++)
460 {
461 int sel = VEC_EL_2(EL, i);
462 RSP_SET_VEC_I(info->used, VS1REG, i);
463 RSP_SET_VEC_I(info->used, VS2REG, sel);
464 RSP_SET_VEC_I(info->set, VDREG, i);
465 RSP_SET_ACCU_I(info->set, i, 2);
466 }
467 RSP_SET_FLAG_I(info->used, 0);
468 RSP_SET_FLAG_I(info->used, 1);
469 RSP_SET_FLAG_I(info->set, 0);
470 RSP_SET_FLAG_I(info->set, 1);
471 RSP_SET_FLAG_I(info->set, 2);
472 break;
473 }
474 case RSP_VCH:
475 case RSP_VCR:
476 {
477 for (i=0; i < 8; i++)
478 {
479 int sel = VEC_EL_2(EL, i);
480 RSP_SET_VEC_I(info->used, VS1REG, i);
481 RSP_SET_VEC_I(info->used, VS2REG, sel);
482 RSP_SET_VEC_I(info->set, VDREG, i);
483 RSP_SET_ACCU_I(info->set, i, 2);
484 }
485 RSP_SET_FLAG_I(info->set, 0);
486 RSP_SET_FLAG_I(info->set, 1);
487 RSP_SET_FLAG_I(info->set, 2);
488 break;
489 }
490 case RSP_VMRG:
491 {
492 for (i=0; i < 8; i++)
493 {
494 int sel = VEC_EL_2(EL, i);
495 RSP_SET_VEC_I(info->used, VS1REG, i);
496 RSP_SET_VEC_I(info->used, VS2REG, sel);
497 RSP_SET_VEC_I(info->set, VDREG, i);
498 RSP_SET_ACCU_I(info->set, i, 2);
499 }
500 RSP_SET_FLAG_I(info->used, 1);
501 break;
502 }
503 case RSP_VAND:
504 case RSP_VNAND:
505 case RSP_VOR:
506 case RSP_VNOR:
507 case RSP_VXOR:
508 case RSP_VNXOR:
509 {
510 for (i=0; i < 8; i++)
511 {
512 int sel = VEC_EL_2(EL, i);
513 RSP_SET_VEC_I(info->used, VS1REG, i);
514 RSP_SET_VEC_I(info->used, VS2REG, sel);
515 RSP_SET_VEC_I(info->set, VDREG, i);
516 RSP_SET_ACCU_I(info->set, i, 2);
517 }
518 break;
519 }
520 case RSP_VRCP:
521 case RSP_VRCPL:
522 case RSP_VRCPH:
523 case RSP_VRSQL:
524 case RSP_VRSQH:
525 {
526 int del = (VS1REG & 7);
527 int sel = VEC_EL_2(EL, del);
528
529 RSP_SET_VEC_I(info->used, VS2REG, sel);
530
531 for (i=0; i < 8; i++)
532 {
533 int element = VEC_EL_2(EL, i);
534 RSP_SET_VEC_I(info->used, VS2REG, element);
535 RSP_SET_ACCU_I(info->set, i, 2);
536 }
537
538 RSP_SET_VEC_I(info->set, VDREG, del);
539 break;
540 }
541 case RSP_VMOV:
542 {
543 int element = VS1REG & 7;
544 RSP_SET_VEC_I(info->used, VS2REG, VEC_EL_2(EL, 7-element));
545 RSP_SET_VEC_I(info->set, VDREG, element);
546 break;
547 }
548
549 default:
550 {
551 // char string[200];
552 // rsp_dasm_one(string, 0x800, op);
553 // if (strcmp(string, "???")) {
554 // printf("%s\n", string);
555 // printf("unimplemented opcode\n");
556 // }
557 break;
558 }
559 }
560}