RSP LLE plugin. Compile and run (slowly, eat 50% CPU) on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-rsp-z64 / src / rsp_opinfo.cpp
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
24 static 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
44 void 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 }