1 /******************************************************************************/
2 /* Mednafen Sony PS1 Emulation Module */
3 /******************************************************************************/
4 /* gte.cpp:
5 ** Copyright (C) 2011-2016 Mednafen Team
6 **
7 ** This program is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU General Public License
9 ** as published by the Free Software Foundation; either version 2
10 ** of the License, or (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software Foundation, Inc.,
19 ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 #pragma GCC optimize ("no-unroll-loops,no-peel-loops")
23
24 #ifndef PSXDEV_GTE_TESTING
25 #include "psx.h"
26 #include "gte.h"
27 #endif
28
29 /* Notes:
30
31 AVSZ3/AVSZ4:
32 OTZ is MAC0 >> 12
33 OTZ overflow/underflow flag is set in an overflow condition even if MAC0 == 0.
34 sf field bit has no effect?
35
36 FLAG register:
37 Bits present mask: 0xfffff000
38
39 Checksum bit can't be directly set, it's apparently calculated like (bool)(FLAGS & 0x7f87e000)
40
41 Instructions effectively clear it 0 at start. (todo: test "invalid" instructions)
42
43 X/Y FIFO [3] register write pushes a copy down to [2]
44
45 */
46
47 #ifndef PSXDEV_GTE_TESTING
48 namespace MDFN_IEN_PSX
49 {
50 #endif
51
52 typedef struct
53 {
54 int16 MX[3][3];
55 int16 dummy;
56 } gtematrix;
57 #ifndef PSXDEV_GTE_TESTING
58 static_assert(sizeof(gtematrix) == 20, "gtematrix wrong size!");
59 #endif
60
61 typedef struct
62 {
63 union
64 {
65 struct
66 {
67 uint8 R;
68 uint8 G;
69 uint8 B;
70 uint8 CD;
71 };
72 uint8 Raw8[4];
73 };
74 } gtergb;
75
76 typedef struct
77 {
78 int16 X;
79 int16 Y;
80 } gtexy;
81
82 static uint32 CR[32];
83 static uint32 FLAGS; // Temporary for instruction execution, copied into CR[31] at end of instruction execution.
84
85 typedef union
86 {
87 gtematrix All[4];
88 int32 Raw[4][5]; // Don't read from this(Raw[][]), only write(and when writing, if running on a big-endian platform, swap the upper 16-bits with the lower 16-bits)
89 int16 Raw16[4][10];
90
91 struct
92 {
93 gtematrix Rot;
94 gtematrix Light;
95 gtematrix Color;
96 gtematrix AbbyNormal;
97 };
98 } Matrices_t;
99
100 static Matrices_t Matrices;
101
102 static union
103 {
104 int32 All[4][4]; // Really only [4][3], but [4] to ease address calculation.
105
106 struct
107 {
108 int32 T[4];
109 int32 B[4];
110 int32 FC[4];
111 int32 Null[4];
112 };
113 } CRVectors;
114
115 static int32 OFX;
116 static int32 OFY;
117 static uint16 H;
118 static int16 DQA;
119 static int32 DQB;
120
121 static int16 ZSF3;
122 static int16 ZSF4;
123
124
125 // Begin DR
126 static int16 Vectors[3][4];
127 static gtergb RGB;
128 static uint16 OTZ;
129
130 static int16 IR[4];
131
132 #define IR0 IR[0]
133 #define IR1 IR[1]
134 #define IR2 IR[2]
135 #define IR3 IR[3]
136
137 static gtexy XY_FIFO[4];
138 static uint16 Z_FIFO[4];
139 static gtergb RGB_FIFO[3];
140 static int32 MAC[4];
141 static uint32 LZCS;
142 static uint32 LZCR;
143
144 static uint32 Reg23;
145 // end DR
146
Sat5(int16 cc)147 static INLINE uint8 Sat5(int16 cc)
148 {
149 if(cc < 0)
150 cc = 0;
151 if(cc > 0x1F)
152 cc = 0x1F;
153 return(cc);
154 }
155
156 //
157 // Newton-Raphson division table. (Initialized at startup; do NOT save in save states!)
158 //
159 static uint8 DivTable[0x100 + 1];
CalcRecip(uint16 divisor)160 static INLINE uint32 CalcRecip(uint16 divisor)
161 {
162 int32 x = (0x101 + DivTable[(((divisor & 0x7FFF) + 0x40) >> 7)]);
163 int32 tmp = (((int32)divisor * -x) + 0x80) >> 8;
164 int32 tmp2 = ((x * (131072 + tmp)) + 0x80) >> 8;
165
166 return(tmp2);
167 }
168
GTE_Init(void)169 void GTE_Init(void)
170 {
171 for(uint32_t divisor = 0x8000; divisor < 0x10000; divisor += 0x80)
172 {
173 uint32_t xa = 512;
174
175 for(unsigned i = 1; i < 5; i++)
176 {
177 xa = (xa * (1024 * 512 - ((divisor >> 7) * xa))) >> 18;
178 }
179
180 DivTable[(divisor >> 7) & 0xFF] = ((xa + 1) >> 1) - 0x101;
181 //printf("%04x, %02x\n", divisor, ((xa + 1) >> 1) - 0x101);
182 }
183
184 //
185 // To avoid a bounds limiting if statement in the emulation code:
186 DivTable[0x100] = DivTable[0xFF];
187 }
188
GTE_Power(void)189 void GTE_Power(void)
190 {
191 memset(CR, 0, sizeof(CR));
192 //memset(DR, 0, sizeof(DR));
193
194 memset(Matrices.All, 0, sizeof(Matrices.All));
195 memset(CRVectors.All, 0, sizeof(CRVectors.All));
196 OFX = 0;
197 OFY = 0;
198 H = 0;
199 DQA = 0;
200 DQB = 0;
201 ZSF3 = 0;
202 ZSF4 = 0;
203
204
205 memset(Vectors, 0, sizeof(Vectors));
206 memset(&RGB, 0, sizeof(RGB));
207 OTZ = 0;
208 IR0 = 0;
209 IR1 = 0;
210 IR2 = 0;
211 IR3 = 0;
212
213 memset(XY_FIFO, 0, sizeof(XY_FIFO));
214 memset(Z_FIFO, 0, sizeof(Z_FIFO));
215 memset(RGB_FIFO, 0, sizeof(RGB_FIFO));
216 memset(MAC, 0, sizeof(MAC));
217 LZCS = 0;
218 LZCR = 0;
219
220 Reg23 = 0;
221 }
222
223 // TODO: Don't save redundant state, regarding CR cache variables
GTE_StateAction(StateMem * sm,const unsigned load,const bool data_only)224 void GTE_StateAction(StateMem *sm, const unsigned load, const bool data_only)
225 {
226 SFORMAT StateRegs[] =
227 {
228 SFVAR(CR),
229 SFVAR(FLAGS),
230
231 SFVARN(Matrices.Raw16, "&Matrices.Raw16[0][0]"),
232
233 SFVARN(CRVectors.All, "&CRVectors.All[0][0]"),
234
235 SFVAR(OFX),
236 SFVAR(OFY),
237 SFVAR(H),
238 SFVAR(DQA),
239 SFVAR(DQB),
240
241 SFVAR(ZSF3),
242 SFVAR(ZSF4),
243 SFVARN(Vectors, "&Vectors[0][0]"),
244
245 SFVAR(RGB.Raw8),
246 SFVAR(OTZ),
247 SFVAR(IR),
248
249 SFVAR(XY_FIFO[0].X),
250 SFVAR(XY_FIFO[0].Y),
251 SFVAR(XY_FIFO[1].X),
252 SFVAR(XY_FIFO[1].Y),
253 SFVAR(XY_FIFO[2].X),
254 SFVAR(XY_FIFO[2].Y),
255 SFVAR(XY_FIFO[3].X),
256 SFVAR(XY_FIFO[3].Y),
257
258 SFVAR(Z_FIFO),
259
260 SFVAR(RGB_FIFO[0].Raw8),
261 SFVAR(RGB_FIFO[1].Raw8),
262 SFVAR(RGB_FIFO[2].Raw8),
263
264 SFVAR(MAC),
265
266 SFVAR(LZCS),
267 SFVAR(LZCR),
268 SFVAR(Reg23),
269
270 SFEND
271 };
272
273 MDFNSS_StateAction(sm, load, data_only, StateRegs, "GTE");
274
275 if(load)
276 {
277
278 }
279 }
280
281
GTE_WriteCR(unsigned int which,uint32 value)282 void GTE_WriteCR(unsigned int which, uint32 value)
283 {
284 static const uint32 mask_table[32] = {
285 /* 0x00 */
286 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
287
288 /* 0x08 */
289 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
290
291 /* 0x10 */
292 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
293
294 /* 0x18 */
295 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0x0000FFFF, 0xFFFFFFFF, 0x0000FFFF, 0x0000FFFF, 0xFFFFFFFF
296 };
297
298 //PSX_WARNING("[GTE] Write CR %d, 0x%08x", which, value);
299
300 value &= mask_table[which];
301
302 CR[which] = value | (CR[which] & ~mask_table[which]);
303
304 if(which < 24)
305 {
306 int we = which >> 3;
307 which &= 0x7;
308
309 if(which >= 5)
310 CRVectors.All[we][which - 5] = value;
311 else
312 {
313 #ifdef MSB_FIRST
314 Matrices.Raw[we][which] = (value << 16) | (value >> 16);
315 #else
316 Matrices.Raw[we][which] = value;
317 #endif
318 }
319 return;
320 }
321
322 switch(which)
323 {
324 case 24:
325 OFX = value;
326 break;
327
328 case 25:
329 OFY = value;
330 break;
331
332 case 26:
333 H = value;
334 break;
335
336 case 27:
337 DQA = value;
338 break;
339
340 case 28:
341 DQB = value;
342 break;
343
344 case 29:
345 ZSF3 = value;
346 break;
347
348 case 30:
349 ZSF4 = value;
350 break;
351
352 case 31:
353 CR[31] = (value & 0x7ffff000) | ((value & 0x7f87e000) ? (1 << 31) : 0);
354 break;
355 }
356 }
357
GTE_ReadCR(unsigned int which)358 uint32 GTE_ReadCR(unsigned int which)
359 {
360 uint32 ret = 0;
361
362 switch(which)
363 {
364 default:
365 ret = CR[which];
366 if(which == 4 || which == 12 || which == 20)
367 ret = (int16)ret;
368 break;
369
370 case 24:
371 ret = OFX;
372 break;
373
374 case 25:
375 ret = OFY;
376 break;
377
378 case 26:
379 ret = (int16)H;
380 break;
381
382 case 27:
383 ret = (int16)DQA;
384 break;
385
386 case 28:
387 ret = DQB;
388 break;
389
390 case 29:
391 ret = (int16)ZSF3;
392 break;
393
394 case 30:
395 ret = (int16)ZSF4;
396 break;
397
398 case 31:
399 ret = CR[31];
400 break;
401 }
402
403 return(ret);
404 }
405
GTE_WriteDR(unsigned int which,uint32 value)406 void GTE_WriteDR(unsigned int which, uint32 value)
407 {
408 switch(which & 0x1F)
409 {
410 case 0:
411 Vectors[0][0] = value;
412 Vectors[0][1] = value >> 16;
413 break;
414
415 case 1:
416 Vectors[0][2] = value;
417 break;
418
419 case 2:
420 Vectors[1][0] = value;
421 Vectors[1][1] = value >> 16;
422 break;
423
424 case 3:
425 Vectors[1][2] = value;
426 break;
427
428 case 4:
429 Vectors[2][0] = value;
430 Vectors[2][1] = value >> 16;
431 break;
432
433 case 5:
434 Vectors[2][2] = value;
435 break;
436
437 case 6:
438 RGB.R = value >> 0;
439 RGB.G = value >> 8;
440 RGB.B = value >> 16;
441 RGB.CD = value >> 24;
442 break;
443
444 case 7:
445 OTZ = value;
446 break;
447
448 case 8:
449 IR0 = value;
450 break;
451
452 case 9:
453 IR1 = value;
454 break;
455
456 case 10:
457 IR2 = value;
458 break;
459
460 case 11:
461 IR3 = value;
462 break;
463
464 case 12:
465 XY_FIFO[0].X = value;
466 XY_FIFO[0].Y = value >> 16;
467 break;
468
469 case 13:
470 XY_FIFO[1].X = value;
471 XY_FIFO[1].Y = value >> 16;
472 break;
473
474 case 14:
475 XY_FIFO[2].X = value;
476 XY_FIFO[2].Y = value >> 16;
477 XY_FIFO[3].X = value;
478 XY_FIFO[3].Y = value >> 16;
479 break;
480
481 case 15:
482 XY_FIFO[3].X = value;
483 XY_FIFO[3].Y = value >> 16;
484
485 XY_FIFO[0] = XY_FIFO[1];
486 XY_FIFO[1] = XY_FIFO[2];
487 XY_FIFO[2] = XY_FIFO[3];
488 break;
489
490 case 16:
491 Z_FIFO[0] = value;
492 break;
493
494 case 17:
495 Z_FIFO[1] = value;
496 break;
497
498 case 18:
499 Z_FIFO[2] = value;
500 break;
501
502 case 19:
503 Z_FIFO[3] = value;
504 break;
505
506 case 20:
507 RGB_FIFO[0].R = value;
508 RGB_FIFO[0].G = value >> 8;
509 RGB_FIFO[0].B = value >> 16;
510 RGB_FIFO[0].CD = value >> 24;
511 break;
512
513 case 21:
514 RGB_FIFO[1].R = value;
515 RGB_FIFO[1].G = value >> 8;
516 RGB_FIFO[1].B = value >> 16;
517 RGB_FIFO[1].CD = value >> 24;
518 break;
519
520 case 22:
521 RGB_FIFO[2].R = value;
522 RGB_FIFO[2].G = value >> 8;
523 RGB_FIFO[2].B = value >> 16;
524 RGB_FIFO[2].CD = value >> 24;
525 break;
526
527 case 23:
528 Reg23 = value;
529 break;
530
531 case 24:
532 MAC[0] = value;
533 break;
534
535 case 25:
536 MAC[1] = value;
537 break;
538
539 case 26:
540 MAC[2] = value;
541 break;
542
543 case 27:
544 MAC[3] = value;
545 break;
546
547 case 28:
548 IR1 = ((value >> 0) & 0x1F) << 7;
549 IR2 = ((value >> 5) & 0x1F) << 7;
550 IR3 = ((value >> 10) & 0x1F) << 7;
551 break;
552
553 case 29: // Read-only
554 break;
555
556 case 30:
557 LZCS = value;
558 LZCR = MDFN_lzcount32(value ^ ((int32)value >> 31));
559 break;
560
561 case 31: // Read-only
562 break;
563 }
564 }
565
GTE_ReadDR(unsigned int which)566 uint32 GTE_ReadDR(unsigned int which)
567 {
568 uint32 ret = 0;
569
570 switch(which & 0x1F)
571 {
572 case 0:
573 ret = (uint16)Vectors[0][0] | ((uint16)Vectors[0][1] << 16);
574 break;
575
576 case 1:
577 ret = (int16)Vectors[0][2];
578 break;
579
580 case 2:
581 ret = (uint16)Vectors[1][0] | ((uint16)Vectors[1][1] << 16);
582 break;
583
584 case 3:
585 ret = (int16)Vectors[1][2];
586 break;
587
588 case 4:
589 ret = (uint16)Vectors[2][0] | ((uint16)Vectors[2][1] << 16);
590 break;
591
592 case 5:
593 ret = (int16)Vectors[2][2];
594 break;
595
596 case 6:
597 ret = RGB.R | (RGB.G << 8) | (RGB.B << 16) | (RGB.CD << 24);
598 break;
599
600 case 7:
601 ret = (uint16)OTZ;
602 break;
603
604 case 8:
605 ret = (int16)IR0;
606 break;
607
608 case 9:
609 ret = (int16)IR1;
610 break;
611
612 case 10:
613 ret = (int16)IR2;
614 break;
615
616 case 11:
617 ret = (int16)IR3;
618 break;
619
620 case 12:
621 ret = (uint16)XY_FIFO[0].X | ((uint16)XY_FIFO[0].Y << 16);
622 break;
623
624 case 13:
625 ret = (uint16)XY_FIFO[1].X | ((uint16)XY_FIFO[1].Y << 16);
626 break;
627
628 case 14:
629 ret = (uint16)XY_FIFO[2].X | ((uint16)XY_FIFO[2].Y << 16);
630 break;
631
632 case 15:
633 ret = (uint16)XY_FIFO[3].X | ((uint16)XY_FIFO[3].Y << 16);
634 break;
635
636 case 16:
637 ret = (uint16)Z_FIFO[0];
638 break;
639
640 case 17:
641 ret = (uint16)Z_FIFO[1];
642 break;
643
644 case 18:
645 ret = (uint16)Z_FIFO[2];
646 break;
647
648 case 19:
649 ret = (uint16)Z_FIFO[3];
650 break;
651
652 case 20:
653 ret = RGB_FIFO[0].R | (RGB_FIFO[0].G << 8) | (RGB_FIFO[0].B << 16) | (RGB_FIFO[0].CD << 24);
654 break;
655
656 case 21:
657 ret = RGB_FIFO[1].R | (RGB_FIFO[1].G << 8) | (RGB_FIFO[1].B << 16) | (RGB_FIFO[1].CD << 24);
658 break;
659
660 case 22:
661 ret = RGB_FIFO[2].R | (RGB_FIFO[2].G << 8) | (RGB_FIFO[2].B << 16) | (RGB_FIFO[2].CD << 24);
662 break;
663
664 case 23:
665 ret = Reg23;
666 break;
667
668 case 24:
669 ret = MAC[0];
670 break;
671
672 case 25:
673 ret = MAC[1];
674 break;
675
676 case 26:
677 ret = MAC[2];
678 break;
679
680 case 27:
681 ret = MAC[3];
682 break;
683
684 case 28:
685 case 29:
686 ret = Sat5(IR1 >> 7) | (Sat5(IR2 >> 7) << 5) | (Sat5(IR3 >> 7) << 10);
687 break;
688
689 case 30:
690 ret = LZCS;
691 break;
692
693 case 31:
694 ret = LZCR;
695 break;
696 }
697 return(ret);
698 }
699
700 #define sign_x_to_s64(_bits, _value) (((int64)((uint64)(_value) << (64 - _bits))) >> (64 - _bits))
A_MV(unsigned which,int64 value)701 static INLINE int64 A_MV(unsigned which, int64 value)
702 {
703 if(value >= (1LL << 43))
704 FLAGS |= 1 << (30 - which);
705
706 if(value < -(1LL << 43))
707 FLAGS |= 1 << (27 - which);
708
709 return sign_x_to_s64(44, value);
710 }
711
F(int64 value)712 static INLINE int64 F(int64 value)
713 {
714 if(value < -2147483648LL)
715 {
716 // flag set here
717 FLAGS |= 1 << 15;
718 }
719
720 if(value > 2147483647LL)
721 {
722 // flag set here
723 FLAGS |= 1 << 16;
724 }
725 return(value);
726 }
727
728
Lm_B(unsigned int which,int32 value,int lm)729 static INLINE int16 Lm_B(unsigned int which, int32 value, int lm)
730 {
731 int32 tmp = lm << 15;
732
733 if(value < (-32768 + tmp))
734 {
735 // set flag here
736 FLAGS |= 1 << (24 - which);
737 value = -32768 + tmp;
738 }
739
740 if(value > 32767)
741 {
742 // Set flag here
743 FLAGS |= 1 << (24 - which);
744 value = 32767;
745 }
746
747 return(value);
748 }
749
750
Lm_B_PTZ(unsigned int which,int32 value,int32 ftv_value,int lm)751 static INLINE int16 Lm_B_PTZ(unsigned int which, int32 value, int32 ftv_value, int lm)
752 {
753 int32 tmp = lm << 15;
754
755 if(ftv_value < -32768)
756 {
757 FLAGS |= 1 << (24 - which);
758 }
759
760 if(ftv_value > 32767)
761 {
762 FLAGS |= 1 << (24 - which);
763 }
764
765 if(value < (-32768 + tmp))
766 {
767 value = -32768 + tmp;
768 }
769
770 if(value > 32767)
771 {
772 value = 32767;
773 }
774
775 return(value);
776 }
777
Lm_C(unsigned int which,int32 value)778 static INLINE uint8 Lm_C(unsigned int which, int32 value)
779 {
780 if(value & ~0xFF)
781 {
782 // Set flag here
783 FLAGS |= 1 << (21 - which); // Tested with GPF
784
785 if(value < 0)
786 value = 0;
787
788 if(value > 255)
789 value = 255;
790 }
791
792 return(value);
793 }
794
Lm_D(int32 value,int unchained)795 static INLINE int32 Lm_D(int32 value, int unchained)
796 {
797 // Not sure if we should have it as int64, or just chain on to and special case when the F flags are set.
798 if(!unchained)
799 {
800 if(FLAGS & (1 << 15))
801 {
802 FLAGS |= 1 << 18;
803 return(0);
804 }
805
806 if(FLAGS & (1 << 16))
807 {
808 FLAGS |= 1 << 18;
809 return(0xFFFF);
810 }
811 }
812
813 if(value < 0)
814 {
815 // Set flag here
816 value = 0;
817 FLAGS |= 1 << 18; // Tested with AVSZ3
818 }
819 else if(value > 65535)
820 {
821 // Set flag here.
822 value = 65535;
823 FLAGS |= 1 << 18; // Tested with AVSZ3
824 }
825
826 return(value);
827 }
828
Lm_G(unsigned int which,int32 value)829 static INLINE int32 Lm_G(unsigned int which, int32 value)
830 {
831 if(value < -1024)
832 {
833 // Set flag here
834 value = -1024;
835 FLAGS |= 1 << (14 - which);
836 }
837
838 if(value > 1023)
839 {
840 // Set flag here.
841 value = 1023;
842 FLAGS |= 1 << (14 - which);
843 }
844
845 return(value);
846 }
847
848 // limit to 4096, not 4095
Lm_H(int32 value)849 static INLINE int32 Lm_H(int32 value)
850 {
851 if(value < 0)
852 {
853 value = 0;
854 FLAGS |= 1 << 12;
855 }
856
857 if(value > 4096)
858 {
859 value = 4096;
860 FLAGS |= 1 << 12;
861 }
862
863 return(value);
864 }
865
MAC_to_RGB_FIFO(void)866 static INLINE void MAC_to_RGB_FIFO(void)
867 {
868 RGB_FIFO[0] = RGB_FIFO[1];
869 RGB_FIFO[1] = RGB_FIFO[2];
870 RGB_FIFO[2].R = Lm_C(0, MAC[1] >> 4);
871 RGB_FIFO[2].G = Lm_C(1, MAC[2] >> 4);
872 RGB_FIFO[2].B = Lm_C(2, MAC[3] >> 4);
873 RGB_FIFO[2].CD = RGB.CD;
874 }
875
876
MAC_to_IR(int lm)877 static INLINE void MAC_to_IR(int lm)
878 {
879 IR1 = Lm_B(0, MAC[1], lm);
880 IR2 = Lm_B(1, MAC[2], lm);
881 IR3 = Lm_B(2, MAC[3], lm);
882 }
883
MultiplyMatrixByVector(const gtematrix * matrix,const int16 * v,const int32 * crv,uint32 sf,int lm)884 static INLINE void MultiplyMatrixByVector(const gtematrix *matrix, const int16 *v, const int32 *crv, uint32 sf, int lm)
885 {
886 unsigned i;
887
888 for(i = 0; i < 3; i++)
889 {
890 int64 tmp;
891 int32 mulr[3];
892
893 tmp = (uint64)(int64)crv[i] << 12;
894
895 if(matrix == &Matrices.AbbyNormal)
896 {
897 if(i == 0)
898 {
899 mulr[0] = -((RGB.R << 4) * v[0]);
900 mulr[1] = (RGB.R << 4) * v[1];
901 mulr[2] = IR0 * v[2];
902 }
903 else
904 {
905 mulr[0] = (int16)CR[i] * v[0];
906 mulr[1] = (int16)CR[i] * v[1];
907 mulr[2] = (int16)CR[i] * v[2];
908 }
909 }
910 else
911 {
912 mulr[0] = matrix->MX[i][0] * v[0];
913 mulr[1] = matrix->MX[i][1] * v[1];
914 mulr[2] = matrix->MX[i][2] * v[2];
915 }
916
917 tmp = A_MV(i, tmp + mulr[0]);
918 if(crv == CRVectors.FC)
919 {
920 Lm_B(i, tmp >> sf, false);
921 tmp = 0;
922 }
923
924 tmp = A_MV(i, tmp + mulr[1]);
925 tmp = A_MV(i, tmp + mulr[2]);
926
927 MAC[1 + i] = tmp >> sf;
928 }
929
930
931 MAC_to_IR(lm);
932 }
933
934
MultiplyMatrixByVector_PT(const gtematrix * matrix,const int16 * v,const int32 * crv,uint32 sf,int lm)935 static INLINE void MultiplyMatrixByVector_PT(const gtematrix *matrix, const int16 *v, const int32 *crv, uint32 sf, int lm)
936 {
937 int64 tmp[3];
938 unsigned i;
939
940 for(i = 0; i < 3; i++)
941 {
942 int32 mulr[3];
943
944 tmp[i] = (uint64)(int64)crv[i] << 12;
945
946 mulr[0] = matrix->MX[i][0] * v[0];
947 mulr[1] = matrix->MX[i][1] * v[1];
948 mulr[2] = matrix->MX[i][2] * v[2];
949
950 tmp[i] = A_MV(i, tmp[i] + mulr[0]);
951 tmp[i] = A_MV(i, tmp[i] + mulr[1]);
952 tmp[i] = A_MV(i, tmp[i] + mulr[2]);
953
954 MAC[1 + i] = tmp[i] >> sf;
955 }
956
957 IR1 = Lm_B(0, MAC[1], lm);
958 IR2 = Lm_B(1, MAC[2], lm);
959 //printf("FTV: %08x %08x\n", crv[2], (uint32)(tmp[2] >> 12));
960 IR3 = Lm_B_PTZ(2, MAC[3], tmp[2] >> 12, lm);
961
962 Z_FIFO[0] = Z_FIFO[1];
963 Z_FIFO[1] = Z_FIFO[2];
964 Z_FIFO[2] = Z_FIFO[3];
965 Z_FIFO[3] = Lm_D(tmp[2] >> 12, true);
966 }
967
968
969 #define DECODE_FIELDS \
970 const uint32 sf MDFN_NOWARN_UNUSED = (instr & (1 << 19)) ? 12 : 0; \
971 const uint32 mx MDFN_NOWARN_UNUSED = (instr >> 17) & 0x3; \
972 const uint32 v_i = (instr >> 15) & 0x3; \
973 const int32* cv MDFN_NOWARN_UNUSED = CRVectors.All[(instr >> 13) & 0x3]; \
974 const int lm MDFN_NOWARN_UNUSED = (instr >> 10) & 1; \
975 int16 v[3] MDFN_NOWARN_UNUSED; \
976 if(v_i == 3) \
977 { \
978 v[0] = IR1; \
979 v[1] = IR2; \
980 v[2] = IR3; \
981 } \
982 else \
983 { \
984 v[0] = Vectors[v_i][0]; \
985 v[1] = Vectors[v_i][1]; \
986 v[2] = Vectors[v_i][2]; \
987 }
988
989
SQR(uint32 instr)990 static INLINE int32 SQR(uint32 instr)
991 {
992 DECODE_FIELDS;
993
994 MAC[1] = ((IR1 * IR1) >> sf);
995 MAC[2] = ((IR2 * IR2) >> sf);
996 MAC[3] = ((IR3 * IR3) >> sf);
997
998 MAC_to_IR(lm);
999
1000 return(5);
1001 }
1002
MVMVA(uint32 instr)1003 static INLINE int32 MVMVA(uint32 instr)
1004 {
1005 DECODE_FIELDS;
1006
1007 MultiplyMatrixByVector(&Matrices.All[mx], v, cv, sf, lm);
1008
1009 return(8);
1010 }
1011
CountLeadingZeroU16(uint16 val)1012 static INLINE unsigned CountLeadingZeroU16(uint16 val)
1013 {
1014 unsigned ret = 0;
1015
1016 while(!(val & 0x8000) && ret < 16)
1017 {
1018 val <<= 1;
1019 ret++;
1020 }
1021
1022 return ret;
1023 }
1024
Divide(uint32 dividend,uint32 divisor)1025 static INLINE uint32 Divide(uint32 dividend, uint32 divisor)
1026 {
1027 //if((Z_FIFO[3] * 2) > H)
1028 if((divisor * 2) > dividend)
1029 {
1030 unsigned shift_bias = CountLeadingZeroU16(divisor);
1031
1032 dividend <<= shift_bias;
1033 divisor <<= shift_bias;
1034
1035 return std::min<uint32>(0x1FFFF, ((uint64)dividend * CalcRecip(divisor | 0x8000) + 32768) >> 16);
1036 }
1037 else
1038 {
1039 FLAGS |= 1 << 17;
1040 return 0x1FFFF;
1041 }
1042 }
1043
TransformXY(int64 h_div_sz)1044 static INLINE void TransformXY(int64 h_div_sz)
1045 {
1046 MAC[0] = F((int64)OFX + IR1 * h_div_sz) >> 16;
1047 XY_FIFO[3].X = Lm_G(0, MAC[0]);
1048
1049 MAC[0] = F((int64)OFY + IR2 * h_div_sz) >> 16;
1050 XY_FIFO[3].Y = Lm_G(1, MAC[0]);
1051
1052 XY_FIFO[0] = XY_FIFO[1];
1053 XY_FIFO[1] = XY_FIFO[2];
1054 XY_FIFO[2] = XY_FIFO[3];
1055 }
1056
TransformDQ(int64 h_div_sz)1057 static INLINE void TransformDQ(int64 h_div_sz)
1058 {
1059 MAC[0] = F((int64)DQB + DQA * h_div_sz);
1060 IR0 = Lm_H(((int64)DQB + DQA * h_div_sz) >> 12);
1061 }
1062
RTPS(uint32 instr)1063 static INLINE int32 RTPS(uint32 instr)
1064 {
1065 DECODE_FIELDS;
1066 int64 h_div_sz;
1067
1068 MultiplyMatrixByVector_PT(&Matrices.Rot, Vectors[0], CRVectors.T, sf, lm);
1069 h_div_sz = Divide(H, Z_FIFO[3]);
1070
1071 TransformXY(h_div_sz);
1072 TransformDQ(h_div_sz);
1073
1074 return(15);
1075 }
1076
RTPT(uint32 instr)1077 static INLINE int32 RTPT(uint32 instr)
1078 {
1079 DECODE_FIELDS;
1080 int i;
1081
1082 for(i = 0; i < 3; i++)
1083 {
1084 int64 h_div_sz;
1085
1086 MultiplyMatrixByVector_PT(&Matrices.Rot, Vectors[i], CRVectors.T, sf, lm);
1087 h_div_sz = Divide(H, Z_FIFO[3]);
1088
1089 TransformXY(h_div_sz);
1090
1091 if(i == 2)
1092 TransformDQ(h_div_sz);
1093 }
1094
1095 return(23);
1096 }
1097
NormColor(uint32 sf,int lm,uint32 v)1098 static INLINE void NormColor(uint32 sf, int lm, uint32 v)
1099 {
1100 int16 tmp_vector[3];
1101
1102 MultiplyMatrixByVector(&Matrices.Light, Vectors[v], CRVectors.Null, sf, lm);
1103
1104 tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3;
1105 MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm);
1106
1107 MAC_to_RGB_FIFO();
1108 }
1109
NCS(uint32 instr)1110 static INLINE int32 NCS(uint32 instr)
1111 {
1112 DECODE_FIELDS;
1113
1114 NormColor(sf, lm, 0);
1115
1116 return(14);
1117 }
1118
NCT(uint32 instr)1119 static int32 NCT(uint32 instr)
1120 {
1121 DECODE_FIELDS;
1122 int i;
1123
1124 for(i = 0; i < 3; i++)
1125 NormColor(sf, lm, i);
1126
1127 return(30);
1128 }
1129
NormColorColor(uint32 v,uint32 sf,int lm)1130 static INLINE void NormColorColor(uint32 v, uint32 sf, int lm)
1131 {
1132 int16 tmp_vector[3];
1133
1134 MultiplyMatrixByVector(&Matrices.Light, Vectors[v], CRVectors.Null, sf, lm);
1135
1136 tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3;
1137 MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm);
1138
1139 MAC[1] = ((RGB.R << 4) * IR1) >> sf;
1140 MAC[2] = ((RGB.G << 4) * IR2) >> sf;
1141 MAC[3] = ((RGB.B << 4) * IR3) >> sf;
1142
1143 MAC_to_IR(lm);
1144
1145 MAC_to_RGB_FIFO();
1146 }
1147
NCCS(uint32 instr)1148 static INLINE int32 NCCS(uint32 instr)
1149 {
1150 DECODE_FIELDS;
1151
1152 NormColorColor(0, sf, lm);
1153 return(17);
1154 }
1155
1156
NCCT(uint32 instr)1157 static INLINE int32 NCCT(uint32 instr)
1158 {
1159 int i;
1160 DECODE_FIELDS;
1161
1162 for(i = 0; i < 3; i++)
1163 NormColorColor(i, sf, lm);
1164
1165 return(39);
1166 }
1167
DepthCue(int mult_IR123,int RGB_from_FIFO,uint32 sf,int lm)1168 static INLINE void DepthCue(int mult_IR123, int RGB_from_FIFO, uint32 sf, int lm)
1169 {
1170 int32 RGB_temp[3];
1171 int32 IR_temp[3] = { IR1, IR2, IR3 };
1172 int i;
1173
1174 //assert(sf);
1175
1176 if(RGB_from_FIFO)
1177 {
1178 RGB_temp[0] = RGB_FIFO[0].R << 4;
1179 RGB_temp[1] = RGB_FIFO[0].G << 4;
1180 RGB_temp[2] = RGB_FIFO[0].B << 4;
1181 }
1182 else
1183 {
1184 RGB_temp[0] = RGB.R << 4;
1185 RGB_temp[1] = RGB.G << 4;
1186 RGB_temp[2] = RGB.B << 4;
1187 }
1188
1189 if(mult_IR123)
1190 {
1191 for(i = 0; i < 3; i++)
1192 {
1193 MAC[1 + i] = A_MV(i, ((int64)((uint64)(int64)CRVectors.FC[i] << 12) - RGB_temp[i] * IR_temp[i])) >> sf;
1194 MAC[1 + i] = A_MV(i, (RGB_temp[i] * IR_temp[i] + IR0 * Lm_B(i, MAC[1 + i], false))) >> sf;
1195 }
1196 }
1197 else
1198 {
1199 for(i = 0; i < 3; i++)
1200 {
1201 MAC[1 + i] = A_MV(i, ((int64)((uint64)(int64)CRVectors.FC[i] << 12) - (int32)((uint32)RGB_temp[i] << 12))) >> sf;
1202 MAC[1 + i] = A_MV(i, ((int64)((uint64)(int64)RGB_temp[i] << 12) + IR0 * Lm_B(i, MAC[1 + i], false))) >> sf;
1203 }
1204 }
1205
1206 MAC_to_IR(lm);
1207
1208 MAC_to_RGB_FIFO();
1209 }
1210
1211
DCPL(uint32 instr)1212 static INLINE int32 DCPL(uint32 instr)
1213 {
1214 DECODE_FIELDS;
1215
1216 DepthCue(true, false, sf, lm);
1217
1218 return(8);
1219 }
1220
1221
DPCS(uint32 instr)1222 static INLINE int32 DPCS(uint32 instr)
1223 {
1224 DECODE_FIELDS;
1225
1226 DepthCue(false, false, sf, lm);
1227
1228 return(8);
1229 }
1230
DPCT(uint32 instr)1231 static INLINE int32 DPCT(uint32 instr)
1232 {
1233 int i;
1234 DECODE_FIELDS;
1235
1236 for(i = 0; i < 3; i++)
1237 {
1238 DepthCue(false, true, sf, lm);
1239 }
1240
1241 return(17);
1242 }
1243
INTPL(uint32 instr)1244 static INLINE int32 INTPL(uint32 instr)
1245 {
1246 DECODE_FIELDS;
1247
1248 MAC[1] = A_MV(0, ((int64)((uint64)(int64)CRVectors.FC[0] << 12) - (int32)((uint32)(int32)IR1 << 12))) >> sf;
1249 MAC[2] = A_MV(1, ((int64)((uint64)(int64)CRVectors.FC[1] << 12) - (int32)((uint32)(int32)IR2 << 12))) >> sf;
1250 MAC[3] = A_MV(2, ((int64)((uint64)(int64)CRVectors.FC[2] << 12) - (int32)((uint32)(int32)IR3 << 12))) >> sf;
1251
1252 MAC[1] = A_MV(0, ((int64)((uint64)(int64)IR1 << 12) + IR0 * Lm_B(0, MAC[1], false)) >> sf);
1253 MAC[2] = A_MV(1, ((int64)((uint64)(int64)IR2 << 12) + IR0 * Lm_B(1, MAC[2], false)) >> sf);
1254 MAC[3] = A_MV(2, ((int64)((uint64)(int64)IR3 << 12) + IR0 * Lm_B(2, MAC[3], false)) >> sf);
1255
1256 MAC_to_IR(lm);
1257
1258 MAC_to_RGB_FIFO();
1259
1260 return(8);
1261 }
1262
1263
NormColorDepthCue(uint32 v,uint32 sf,int lm)1264 static INLINE void NormColorDepthCue(uint32 v, uint32 sf, int lm)
1265 {
1266 int16 tmp_vector[3];
1267
1268 MultiplyMatrixByVector(&Matrices.Light, Vectors[v], CRVectors.Null, sf, lm);
1269
1270 tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3;
1271 MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm);
1272
1273 DepthCue(true, false, sf, lm);
1274 }
1275
NCDS(uint32 instr)1276 static INLINE int32 NCDS(uint32 instr)
1277 {
1278 DECODE_FIELDS;
1279
1280 NormColorDepthCue(0, sf, lm);
1281
1282 return(19);
1283 }
1284
NCDT(uint32 instr)1285 static INLINE int32 NCDT(uint32 instr)
1286 {
1287 int i;
1288 DECODE_FIELDS;
1289
1290 for(i = 0; i < 3; i++)
1291 {
1292 NormColorDepthCue(i, sf, lm);
1293 }
1294
1295 return(44);
1296 }
1297
CC(uint32 instr)1298 static INLINE int32 CC(uint32 instr)
1299 {
1300 DECODE_FIELDS;
1301 int16 tmp_vector[3];
1302
1303 tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3;
1304 MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm);
1305
1306 MAC[1] = ((RGB.R << 4) * IR1) >> sf;
1307 MAC[2] = ((RGB.G << 4) * IR2) >> sf;
1308 MAC[3] = ((RGB.B << 4) * IR3) >> sf;
1309
1310 MAC_to_IR(lm);
1311
1312 MAC_to_RGB_FIFO();
1313
1314 return(11);
1315 }
1316
CDP(uint32 instr)1317 static INLINE int32 CDP(uint32 instr)
1318 {
1319 DECODE_FIELDS;
1320 int16 tmp_vector[3];
1321
1322 tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3;
1323 MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm);
1324
1325 DepthCue(true, false, sf, lm);
1326
1327 return(13);
1328 }
1329
NCLIP(uint32 instr)1330 static INLINE int32 NCLIP(uint32 instr)
1331 {
1332 DECODE_FIELDS;
1333
1334 MAC[0] = F( (int64)(XY_FIFO[0].X * (XY_FIFO[1].Y - XY_FIFO[2].Y)) + (XY_FIFO[1].X * (XY_FIFO[2].Y - XY_FIFO[0].Y)) + (XY_FIFO[2].X * (XY_FIFO[0].Y - XY_FIFO[1].Y))
1335 );
1336
1337 return(8);
1338 }
1339
AVSZ3(uint32 instr)1340 static INLINE int32 AVSZ3(uint32 instr)
1341 {
1342 DECODE_FIELDS;
1343
1344 MAC[0] = F(((int64)ZSF3 * (Z_FIFO[1] + Z_FIFO[2] + Z_FIFO[3])));
1345
1346 OTZ = Lm_D(MAC[0] >> 12, false);
1347
1348 return(5);
1349 }
1350
AVSZ4(uint32 instr)1351 static INLINE int32 AVSZ4(uint32 instr)
1352 {
1353 DECODE_FIELDS;
1354
1355 MAC[0] = F(((int64)ZSF4 * (Z_FIFO[0] + Z_FIFO[1] + Z_FIFO[2] + Z_FIFO[3])));
1356
1357 OTZ = Lm_D(MAC[0] >> 12, false);
1358
1359 return(5);
1360 }
1361
1362
1363 // -32768 * -32768 - 32767 * -32768 = 2147450880
1364 // (2 ^ 31) - 1 = 2147483647
OP(uint32 instr)1365 static INLINE int32 OP(uint32 instr)
1366 {
1367 DECODE_FIELDS;
1368
1369 MAC[1] = ((Matrices.Rot.MX[1][1] * IR3) - (Matrices.Rot.MX[2][2] * IR2)) >> sf;
1370 MAC[2] = ((Matrices.Rot.MX[2][2] * IR1) - (Matrices.Rot.MX[0][0] * IR3)) >> sf;
1371 MAC[3] = ((Matrices.Rot.MX[0][0] * IR2) - (Matrices.Rot.MX[1][1] * IR1)) >> sf;
1372
1373 MAC_to_IR(lm);
1374
1375 return(6);
1376 }
1377
GPF(uint32 instr)1378 static INLINE int32 GPF(uint32 instr)
1379 {
1380 DECODE_FIELDS;
1381
1382 MAC[1] = (IR0 * IR1) >> sf;
1383 MAC[2] = (IR0 * IR2) >> sf;
1384 MAC[3] = (IR0 * IR3) >> sf;
1385
1386 MAC_to_IR(lm);
1387
1388 MAC_to_RGB_FIFO();
1389
1390 return(5);
1391 }
1392
GPL(uint32 instr)1393 static INLINE int32 GPL(uint32 instr)
1394 {
1395 DECODE_FIELDS;
1396
1397 MAC[1] = A_MV(0, (int64)((uint64)(int64)MAC[1] << sf) + (IR0 * IR1)) >> sf;
1398 MAC[2] = A_MV(1, (int64)((uint64)(int64)MAC[2] << sf) + (IR0 * IR2)) >> sf;
1399 MAC[3] = A_MV(2, (int64)((uint64)(int64)MAC[3] << sf) + (IR0 * IR3)) >> sf;
1400
1401 MAC_to_IR(lm);
1402
1403 MAC_to_RGB_FIFO();
1404
1405 return(5);
1406 }
1407
1408 /*
1409
1410 ---------------------------------------------------------------------------------------------
1411 | 24 23 22 21 20 | 19 | 18 17 | 16 15 | 14 13 | 12 11 | 10 | 9 8 7 6 | 5 4 3 2 1 0 |
1412 |-------------------------------------------------------------------------------------------|
1413 | (unused) | sf | mx | v | cv |(unused)| lm | (unused) | opcode |
1414 ---------------------------------------------------------------------------------------------
1415 (unused) = unused, ignored
1416
1417 sf = shift 12
1418
1419 mx = matrix selection
1420
1421 v = source vector
1422
1423 cv = add vector(translation/back/far color(bugged)/none)
1424
1425 (unused) = unused, ignored
1426
1427 lm = limit negative results to 0
1428
1429 (unused) = unused, ignored
1430
1431 opcode = operation code
1432 */
1433
GTE_Instruction(uint32 instr)1434 int32 GTE_Instruction(uint32 instr)
1435 {
1436 const unsigned code = instr & 0x3F;
1437 int32 ret = 1;
1438
1439 FLAGS = 0;
1440
1441 switch(code)
1442 {
1443 default:
1444 #ifndef PSXDEV_GTE_TESTING
1445 PSX_WARNING("[GTE] Unknown instruction code: 0x%02x", code);
1446 #endif
1447 break;
1448
1449 case 0x00: // alternate?
1450 case 0x01:
1451 ret = RTPS(instr);
1452 break;
1453
1454 /*
1455 case 0x02: // UNSTABLE?
1456 break;
1457
1458 case 0x03: // UNSTABLE?
1459 break;
1460
1461 case 0x04: // Probably simple with v,cv,sf,mx,lm ignored. Same calculation as 0x3B?
1462 break;
1463
1464 case 0x05: // UNSTABLE?
1465 break;
1466 */
1467
1468 case 0x06:
1469 ret = NCLIP(instr);
1470 break;
1471
1472 /*
1473 case 0x07: // UNSTABLE?
1474 break;
1475
1476 case 0x08: // UNSTABLE?
1477 break;
1478
1479 case 0x09: // UNSTABLE?
1480 break;
1481
1482 case 0x0A: // UNSTABLE?
1483 break;
1484
1485 case 0x0B: // UNSTABLE?
1486 break;
1487
1488 */
1489
1490 case 0x0C:
1491 ret = OP(instr);
1492 break;
1493
1494 /*
1495 case 0x0D: // UNSTABLE?
1496 break;
1497
1498 case 0x0E: // UNSTABLE?
1499 break;
1500
1501 case 0x0F: // UNSTABLE?
1502 break;
1503 */
1504
1505 case 0x10:
1506 ret = DPCS(instr);
1507 break;
1508
1509 case 0x11:
1510 ret = INTPL(instr);
1511 break;
1512
1513 case 0x12:
1514 ret = MVMVA(instr);
1515 break;
1516
1517 case 0x13:
1518 ret = NCDS(instr);
1519 break;
1520
1521 case 0x14:
1522 ret = CDP(instr);
1523 break;
1524
1525
1526 /*
1527 case 0x15: // does one push on RGB FIFO, what else...
1528 break;
1529 */
1530
1531 case 0x16:
1532 ret = NCDT(instr);
1533 break;
1534
1535 /*
1536 case 0x17: // PARTIALLY UNSTABLE(depending on sf or v or cv or mx or lm???), similar behavior under some conditions to 0x16?
1537 break;
1538
1539 case 0x18:
1540 break;
1541
1542 case 0x19:
1543 break;
1544 */
1545
1546 // case 0x1A handled next to case 0x29
1547
1548 case 0x1B:
1549 ret = NCCS(instr);
1550 break;
1551
1552 case 0x1C:
1553 ret = CC(instr);
1554 break;
1555
1556 /*
1557 case 0x1D:
1558 break;
1559 */
1560
1561 case 0x1E:
1562 ret = NCS(instr);
1563 break;
1564
1565 /*
1566 case 0x1F:
1567 break;
1568 */
1569
1570 case 0x20:
1571 ret = NCT(instr);
1572 break;
1573 /*
1574 case 0x21:
1575 break;
1576
1577 case 0x22: // UNSTABLE?
1578 break;
1579
1580 case 0x23:
1581 break;
1582
1583 case 0x24:
1584 break;
1585
1586 case 0x25:
1587 break;
1588
1589 case 0x26:
1590 break;
1591
1592 case 0x27:
1593 break;
1594 */
1595
1596 case 0x28:
1597 ret = SQR(instr);
1598 break;
1599
1600 case 0x1A: // Alternate for 0x29?
1601 case 0x29:
1602 ret = DCPL(instr);
1603 break;
1604
1605 case 0x2A:
1606 ret = DPCT(instr);
1607 break;
1608
1609 /*
1610 case 0x2B:
1611 break;
1612
1613 case 0x2C:
1614 break;
1615 */
1616
1617 case 0x2D:
1618 ret = AVSZ3(instr);
1619 break;
1620
1621 case 0x2E:
1622 ret = AVSZ4(instr);
1623 break;
1624
1625 /*
1626 case 0x2F: // UNSTABLE?
1627 break;
1628 */
1629
1630 case 0x30:
1631 ret = RTPT(instr);
1632 break;
1633
1634 /*
1635 case 0x31: // UNSTABLE?
1636 break;
1637
1638 case 0x32: // UNSTABLE?
1639 break;
1640
1641 case 0x33: // UNSTABLE?
1642 break;
1643
1644 case 0x34: // UNSTABLE?
1645 break;
1646
1647 case 0x35: // UNSTABLE?
1648 break;
1649
1650 case 0x36: // UNSTABLE?
1651 break;
1652
1653 case 0x37: // UNSTABLE?
1654 break;
1655
1656 case 0x38:
1657 break;
1658
1659 case 0x39: // Probably simple with v,cv,sf,mx,lm ignored.
1660 break;
1661
1662 case 0x3A: // Probably simple with v,cv,sf,mx,lm ignored.
1663 break;
1664
1665 case 0x3B: // Probably simple with v,cv,sf,mx,lm ignored. Same calculation as 0x04?
1666 break;
1667
1668 case 0x3C: // UNSTABLE?
1669 break;
1670 */
1671
1672 case 0x3D:
1673 ret = GPF(instr);
1674 break;
1675
1676 case 0x3E:
1677 ret = GPL(instr);
1678 break;
1679
1680 case 0x3F:
1681 ret = NCCT(instr);
1682 break;
1683 }
1684
1685 if(FLAGS & 0x7f87e000)
1686 FLAGS |= 1 << 31;
1687
1688 CR[31] = FLAGS;
1689
1690 return(ret - 1);
1691 }
1692
1693 #ifndef PSXDEV_GTE_TESTING
1694 }
1695 #endif
1696