22 // Opcode Function Prototypes
24 void G_ADD( void ); void G_ADDC( void );
25 void G_ADDQ( void ); void G_ADDQT( void );
26 void G_SUB( void ); void G_SUBC( void );
27 void G_SUBQ( void ); void G_SUBQT( void );
28 void G_NEG( void ); void G_AND( void );
29 void G_OR( void ); void G_XOR( void );
30 void G_NOT( void ); void G_BTST( void );
31 void G_BSET( void ); void G_BCLR( void );
32 void G_MULT( void ); void G_IMULT( void );
33 void G_IMULTN( void ); void G_RESMAC( void );
34 void G_IMACN( void ); void G_DIV( void );
35 void G_ABS( void ); void G_SH( void );
36 void G_SHLQ( void ); void G_SHRQ( void );
37 void G_SHA( void ); void G_SHARQ( void );
38 void G_ROR( void ); void G_RORQ( void );
39 void G_CMP( void ); void G_CMPQ( void );
40 void G_SAT8( void ); void G_SAT16( void );
41 void G_MOVE( void ); void G_MOVEQ( void );
42 void G_MOVETA( void ); void G_MOVEFA( void );
43 void G_MOVEI( void ); void G_LOADB( void );
44 void G_LOADW( void ); void G_LOAD( void );
45 void G_LOADP( void ); void G_STORE_14I( void );
46 void G_LOAD_14I( void ); void G_LOAD_15I( void );
47 void G_STOREB( void ); void G_STOREW( void );
48 void G_STORE( void ); void G_STOREP( void );
49 void G_STORE_15I( void ); void G_MOVE_PC( void );
50 void G_JUMP( void ); void G_JR( void );
51 void G_MMULT( void ); void G_MTOI( void );
52 void G_NORMI( void ); void G_NOP( void );
53 void G_LOAD_14R( void ); void G_LOAD_15R( void );
54 void G_STORE_14R( void ); void G_STORE_15R( void );
55 void G_SAT24( void ); void G_PACK_UNPACK( void );
59 unsigned mem_readword( unsigned );
60 unsigned mem_readbyte( unsigned );
61 void mem_writeword( unsigned, unsigned );
62 void mem_writebyte( unsigned, unsigned );
64 // CPU Cycles for Each GPU Opcode
66 byte gpuCycles[64] = {
67 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
68 3, 3, 1, 3, 1, 18, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
69 3, 3, 2, 2, 2, 2, 3, 4, 5, 4, 5, 6, 6, 1, 1, 1,
70 1, 2, 2, 2, 1, 1, 9, 3, 3, 0, 6, 6, 2, 2, 3, 3
74 // GPU Opcode Function Table
76 void (*gpuOp[64])()= {
77 G_ADD, G_ADDC, G_ADDQ, G_ADDQT,
78 G_SUB, G_SUBC, G_SUBQ, G_SUBQT,
79 G_NEG, G_AND, G_OR, G_XOR,
80 G_NOT, G_BTST, G_BSET, G_BCLR,
81 G_MULT, G_IMULT, G_IMULTN, G_RESMAC,
82 G_IMACN, G_DIV, G_ABS, G_SH,
83 G_SHLQ, G_SHRQ, G_SHA, G_SHARQ,
84 G_ROR, G_RORQ, G_CMP, G_CMPQ,
85 G_SAT8, G_SAT16, G_MOVE, G_MOVEQ,
86 G_MOVETA, G_MOVEFA, G_MOVEI, G_LOADB,
87 G_LOADW, G_LOAD, G_LOADP, G_LOAD_14I,
88 G_LOAD_15I, G_STOREB, G_STOREW, G_STORE,
89 G_STOREP, G_STORE_14I, G_STORE_15I, G_MOVE_PC,
90 G_JUMP, G_JR, G_MMULT, G_MTOI,
91 G_NORMI, G_NOP, G_LOAD_14R, G_LOAD_15R,
92 G_STORE_14R, G_STORE_15R, G_SAT24, G_PACK_UNPACK
95 GPUSTATE gst; // GPU State Information
96 dword GincPC; // PC Increment Flag
97 dword GjmpPC; // PC Jump gdstination
98 dword Gbranch; // Branch Flag
104 sdword arb[32]; // GPU Active Register Bank
105 sdword srb[32]; // GPU Secondary Register Bank
106 dword acc; // Accumulator
107 dword pc; // Program Counter
108 dword src; // Source Register
109 dword dst; // Destination Register
111 BOOL n; // Negative Flag
112 BOOL c; // Carry Flag
113 dword ctrl; // GPU Control Word (0xF02114 RW)
114 BOOL div16; // 16.16 Division Flag (0xF0211C WO)
115 dword divrem; // Division Remainder (0xF0211C RO)
118 dword gpc; // Program Counter
119 dword gsrc; // Instruction Word Source
120 dword gdst; // Instruction Word Destination
121 BOOL gz; // Zero Flag
122 BOOL gn; // Negative Flag
123 BOOL gc; // Carry Flag
126 // GPU Processor Emulation
128 DWORD gpu_exec( LPVOID lpParam )
130 dword iw; // Instruction Word
133 oo = fopen( "gpudbg.out", "w" );
139 f = fopen( "gpudump.bin", "wb" );
140 for( i = 0x3000; i < 0x4000; i += 2 ) // Dump GPU RAM
142 fwrite( &st.tom[i+1], 1, 1, f );
143 fwrite( &st.tom[i], 1, 1, f );
149 // Counter = InterruptPeriod;
151 while( gst.gpuActive )
153 if( gst.step ) // While Single Step Enabled
155 while( !gst.stepgo ) ; // Wait Until StepGo Issued
156 printf( " GPU Released for One Instruction (SINGLE STEP)\n" );
159 iw = mem_readword( gpc ); // Get Instruction Word
160 gsrc = (iw & 0x03E0) >> 5; // Get Source
161 gdst = (iw & 0x001F); // Get Destination
163 gpuOp[iw >> 10](); // Jump to and Execute Opcode Routine
169 // Counter -= Cycles[Opcode];
171 // if( Counter <= 0 )
173 // /* Check for Interrupts and do Other Cyclic tasks here
174 // Counter += InterruptPeriod
177 switch( Gbranch ) // Increment Program Counter
179 case 2: // Next Instruction is the Branch Address
184 // A Branch Address was Stored in the Branch Program Counter.
185 // The Next Instruction is a PC + 4 (Case 0 is Executed).
186 // The Next Instruction is at the Branch Program Counter
190 case 0: // Normal Execution
193 case 1: // Opcode Used a 32-Bit Word
197 case 0: // Normal Execution
204 if( gst.step ) // If Single Step Mode Enabled
206 gst.stepgo = 0; // Reset StepGo Flag
207 printf( " GPU Paused Until New SINGLE_GO (SINGLE STEP)\n" );
220 if( gst.arb[gdst] == 0x80000000 )
223 if( gst.arb[gdst] < 0 )
227 mov eax,[ecx*4+gst.arb]
229 mov [ecx*4+gst.arb],eax
232 gz = (gst.arb[gdst] == 0) ? 1 : 0;
238 fprintf( oo, "0x%06X ABS R%i\t\t\tR%02i = 0x%08X Z:%i N:%i C:%i\n",
239 gpc, gdst, gdst, gst.arb[gdst],
248 mov edx,[ecx*4+gst.arb]
250 mov eax,[ecx*4+gst.arb]
252 mov [ecx*4+gst.arb],eax
260 gz = (gst.arb[gdst] == 0) ? 1 : 0;
261 gn = (gst.arb[gdst] < 0) ? 1 : 0;
264 fprintf( oo, "0x%06X ADD R%i,R%i\t\tR%02i = 0x%08X Z:%i N:%i C:%i\n",
265 gpc, gsrc, gdst, gdst, gst.arb[gdst],
279 mov edx,[ecx*4+gst.arb]
281 mov eax,[ecx*4+gst.arb]
283 mov [ecx*4+gst.arb],eax
291 gz = (gst.arb[gdst] == 0) ? 1 : 0;
292 gn = (gst.arb[gdst] < 0) ? 1 : 0;
295 fprintf( oo, "0x%06X ADDC R%i,R%i\t\tR%02i = 0x%08X "
296 "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst,
297 gst.arb[gdst], gz, gn, gc );
305 mov eax,[ecx*4+gst.arb]
308 mov [ecx*4+gst.arb],eax
316 gz = (gst.arb[gdst] == 0) ? 1 : 0;
317 gn = (gst.arb[gdst] < 0) ? 1 : 0;
320 fprintf( oo, "0x%06X ADDQ 0x%02X,R%i\t\tR%02i = 0x%08X "
321 "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst,
322 gst.arb[gdst], gz, gn, gc );
330 mov eax,[ecx*4+gst.arb]
333 mov [ecx*4+gst.arb],eax
337 fprintf( oo, "0x%06X ADDQT 0x%02X,R%i\t\tR%02i = 0x%08X\n",
338 gpc, gsrc, gdst, gdst, gst.arb[gdst] );
344 gst.arb[gdst] &= gst.arb[gsrc];
345 gz = (gst.arb[gdst] == 0) ? 1 : 0;
346 gn = (gst.arb[gdst] < 0) ? 1 : 0;
349 fprintf( oo, "0x%06X AND R%i,R%i\t\tR%02i = 0x%08X Z:%i N:%i C:%i\n",
350 gpc, gsrc, gdst, gdst, gst.arb[gdst],
359 mov eax,[ecx*4+gst.arb]
362 mov [ecx*4+gst.arb],eax
365 gz = (gst.arb[gdst] == 0) ? 1 : 0;
366 gn = (gst.arb[gdst] < 0) ? 1 : 0;
369 fprintf( oo, "0x%06X BCLR 0x%04X,R%i\t\t\t "
371 gpc, gsrc, gdst, gz, gn, gc );
379 mov eax,[ecx*4+gst.arb]
382 mov [ecx*4+gst.arb],eax
385 gz = (gst.arb[gdst] == 0) ? 1 : 0;
386 gn = (gst.arb[gdst] < 0) ? 1 : 0;
389 fprintf( oo, "0x%06X BSET 0x%04X,R%i\t\t\t "
391 gpc, gsrc, gdst, gz, gn, gc );
399 mov eax,[ecx*4+gst.arb]
410 fprintf( oo, "0x%06X BTST 0x%04X,R%i\t\t\t "
412 gpc, gsrc, gdst, gz, gn, gc );
422 mov edx,[ecx*4+gst.arb]
424 mov eax,[ecx*4+gst.arb]
430 gc = (tmpW & 0x0100) ? 1 : 0;
431 gz = (tmpW & 0x4000) ? 1 : 0;
432 gn = (tmpW & 0x8000) ? 1 : 0;
435 fprintf( oo, "0x%06X CMP R%i,R%i\t\t "
437 gpc, gsrc, gdst, gz, gn, gc );
452 mov eax,[ecx*4+gst.arb]
458 gc = (tmpW & 0x0100) ? 1 : 0;
459 gz = (tmpW & 0x4000) ? 1 : 0;
460 gn = (tmpW & 0x8000) ? 1 : 0;
463 fprintf( oo, "0x%06X CMPQ 0x%02X,R%i\t\t "
465 gpc, gsrc, gdst, gz, gn, gc );
472 printf( "GPU DIVIDE 16.16 REQUIRED !!!!\n" );
475 (dword)gst.arb[gdst] = (dword)gst.arb[gdst] /
476 (dword)gst.arb[gsrc];
478 gst.divrem = (dword)gst.arb[gdst] % (dword)gst.arb[gsrc];
482 fprintf( oo, "0x%06X DIV R%i,R%i\t\tR%02i = 0x%08X ",
483 gpc, gsrc, gdst, gdst, gst.arb[gdst] );
489 // Like IMULT but product is added to the previous arithmetic operation.
490 // Intended to be used after IMULTN.
492 gst.acc += (sdword)((sword)gst.arb[gsrc] *
493 (sword)gst.arb[gdst] );
496 fprintf( oo, "0x%06X IMACN R%i,R%i\t\tACC = 0x%08X\n",
497 gpc, gsrc, gdst, gst.acc );
503 gst.arb[gdst] = (sdword)((sword)gst.arb[gsrc] *
504 (sword)gst.arb[gdst] );
506 gz = (gst.arb[gdst] == 0) ? 1 : 0;
507 gn = (gst.arb[gdst] < 0) ? 1 : 0;
510 fprintf( oo, "0x%06X IMULT R%i,R%i\t\tR%02i = 0x%08X "
511 "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst,
512 gst.arb[gdst], gz, gn, gc );
516 void G_IMULTN( void )
518 // Like IMULT but result not written back to gst.arb[gdst]
519 // but to an accumulator. Used as first part of multiply/accumulate group.
521 gst.acc = (sdword)((sword)gst.arb[gsrc] *
522 (sword)gst.arb[gdst] );
524 gz = (gst.arb[gdst] == 0) ? 1 : 0;
525 gn = (gst.arb[gdst] < 0) ? 1 : 0;
528 fprintf( oo, "0x%06X IMULTN R%i,R%i\t\tACC = 0x%08X "
529 "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gst.acc,
536 if( gsrc >= 16 ) // Set Jump Direction
539 GjmpPC = (gpc + 2) + (gsrc * 2);
543 case 0x00: // No Conditions
546 fprintf( oo, "0x%06X JR 0x%08X\n", gpc, GjmpPC );
550 case 0x01: // NE - Not Equal
551 if( !gz ) // Zero Flag Unset
554 fprintf( oo, "0x%06X JR NE,0x%08X\n",gpc, GjmpPC );
558 case 0x02: // EQ - Equal
559 if( gz) // Zero Flag Set
562 fprintf( oo, "0x%06X JR EQ,0x%08X\n", gpc, GjmpPC );
566 case 0x04: // Flag Selected Cleared to Jump
567 if( !gc ) Gbranch = 1; else Gbranch = 0;
569 fprintf( oo, "0x%06X JR CC,0x%08X\n", gpc, GjmpPC );
573 case 0x08: // Flag Selected Set to Jump
574 if( gc ) Gbranch = 1; else Gbranch = 0;
576 fprintf( oo, "0x%06X JR CS,0x%08X\n", gpc, GjmpPC );
581 if( !gn ) Gbranch = 1; else Gbranch = 0;
583 fprintf( oo, "0x%06X JR NN,0x%08X\n", gpc, GjmpPC );
588 if( gn ) Gbranch = 1; else Gbranch = 0;
590 fprintf( oo, "0x%06X JR N,0x%08X\n", gpc, GjmpPC );
596 fprintf( oo, "Unknown JR Condition at 0x%08X\n", gpc );
605 GjmpPC = gst.arb[gsrc];
612 fprintf( oo, "0x%06X JUMP (R%02i) DEST = 0x%08X\n",
618 if( !gz ) Gbranch = 1;
621 fprintf( oo, "0x%06X JUMP NZ,(R%02i) DEST = 0x%08X\n",
630 fprintf( oo, "0x%06X JUMP Z,(R%02i) DEST = 0x%08X\n",
636 if( !gc ) Gbranch = 1;
639 fprintf( oo, "0x%06X JUMP NC,(R%02i) DEST = 0x%08X\n",
645 if( !gc && !gz ) Gbranch = 1;
648 fprintf( oo, "0x%06X JUMP NC_NZ,(R%02i) DEST = 0x%08X\n",
654 if( !gc && gz ) Gbranch = 1;
657 fprintf( oo, "0x%06X JUMP NC_Z,(R%02i) DEST = 0x%08X\n",
663 if( gc ) Gbranch = 1;
666 fprintf( oo, "0x%06X JUMP C,(R%02i) DEST = 0x%08X\n",
672 if( gc && !gz ) Gbranch = 1;
675 fprintf( oo, "0x%06X JUMP C_NZ,(R%02i) DEST = 0x%08X\n",
681 if( gc && gz ) Gbranch = 1;
684 fprintf( oo, "0x%06X JUMP C_Z,(R%02i) DEST = 0x%08X\n",
690 if( !gn ) Gbranch = 1;
693 fprintf( oo, "0x%06X JUMP NN,(R%02i) DEST = 0x%08X\n",
699 if( !gn && !gz ) Gbranch = 1;
702 fprintf( oo, "0x%06X JUMP NN_NZ,(R%02i) DEST = 0x%08X\n",
708 if( !gn && gz ) Gbranch = 1;
711 fprintf( oo, "0x%06X JUMP NN_Z,(R%02i) DEST = 0x%08X\n",
717 if( gn ) Gbranch = 1;
720 fprintf( oo, "0x%06X JUMP N,(R%02i) DEST = 0x%08X\n",
726 if( gn && !gz ) Gbranch = 1;
729 fprintf( oo, "0x%06X JUMP N_NZ,(R%02i) DEST = 0x%08X\n",
735 if( gn && gz ) Gbranch = 1;
738 fprintf( oo, "0x%06X JUMP N_Z,(R%02i) DEST = 0x%08X\n",
746 fprintf( oo, "0x%06X JUMP NEVER (R%02i) DEST = 0x%08X\n",
753 fprintf( oo, "Unknown JUMP Condition\n" );
761 gst.arb[gdst] = mem_readword( gst.arb[gsrc] ) << 16;
762 gst.arb[gdst] |= mem_readword( gst.arb[gsrc] + 2 );
765 fprintf( oo, "0x%06X LOAD (R%i),R%i\t\tR%02i = 0x%08X\n",
766 gpc, gsrc, gdst, gdst, gst.arb[gdst] );
770 void G_LOAD_14I( void )
774 tmpW = gst.arb[0x0E] + (gsrc * 4);
775 gst.arb[gdst] = mem_readword( tmpW ) << 16;
776 gst.arb[gdst] |= mem_readword( tmpW + 2 );
779 fprintf( oo, "0x%06X LOAD (R14+%02i),R%i\t\tR%02i = 0x%08X\n",
780 gpc, gsrc, gdst, gdst, gst.arb[gdst] );
784 void G_LOAD_15I( void )
788 tmpW = gst.arb[0x0F] + (gsrc * 4);
789 gst.arb[gdst] = mem_readword( tmpW ) << 16;
790 gst.arb[gdst] |= mem_readword( tmpW + 2 );
793 fprintf( oo, "0x%06X LOAD (R15+%02i),R%i\t\tR%02i = 0x%08X\n",
794 gpc, gsrc, gdst, gdst, gst.arb[gdst] );
798 void G_LOAD_14R( void )
802 tmpW = gst.arb[0x0E] + gst.arb[gsrc];
803 gst.arb[gdst] = mem_readword( tmpW ) << 16;
804 gst.arb[gdst] |= mem_readword( tmpW + 2 );
807 fprintf( oo, "0x%06X LOAD (R14+R%i),R%i\tR%02i = 0x%08X\n",
808 gpc, gsrc, gdst, gdst, gst.arb[gdst] );
812 void G_LOAD_15R( void )
816 // NOTE: Manual seems to indicate that this opcode
817 // uses Register 14 as the base offset address.
819 tmpW = gst.arb[0x0E] + gst.arb[gsrc];
820 gst.arb[gdst] = mem_readword( tmpW ) << 16;
821 gst.arb[gdst] |= mem_readword( tmpW + 2 );
824 fprintf( oo, "0x%06X LOAD (R15+R%i),R%i\tR%02i = 0x%08X\n",
825 gpc, gsrc, gdst, gdst, gst.arb[gdst] );
831 if( gst.arb[gsrc] >= 0xF03000 && gst.arb[gsrc] < 0xF04000 )
833 gst.arb[gdst] = mem_readword( gst.arb[gsrc] ) << 16;
834 gst.arb[gdst] |= mem_readword( gst.arb[gsrc] + 2 );
837 gst.arb[gdst] = mem_readbyte( gst.arb[gsrc] );
840 fprintf( oo, "0x%06X LOADB (R%i),R%i\t\tR%02i = 0x%08X\n",
841 gpc, gsrc, gdst, gdst, gst.arb[gdst] );
847 if( gst.arb[gsrc] >= 0xF03000 && gst.arb[gsrc] < 0xF04000 )
849 gst.arb[gdst] = mem_readword( gst.arb[gsrc] ) << 16;
850 gst.arb[gdst] |= mem_readword( gst.arb[gsrc] + 2 );
853 gst.arb[gdst] = mem_readword( gst.arb[gsrc] );
856 fprintf( oo, "0x%06X LOADW (R%i),R%i\t\tR%02i = 0x%08X\n",
857 gpc, gsrc, gdst, gdst, gst.arb[gdst] );
863 phr.hi = mem_readword( tolp ) << 16;
864 phr.hi |= mem_readword( tolp + 0x02 );
865 phr.lo = mem_readword( tolp + 0x04 ) << 16;
866 phr.lo |= mem_readword( tolp + 0x06 );
869 fprintf( oo, "GPU - Unimplemented Opcode (LOADP)\n" );
872 gst.gpuActive = FALSE;
878 fprintf( oo, "GPU - Unimplemented Opcode (MMULT)\n" );
880 gst.gpuActive = FALSE;
885 gst.arb[gdst] = gst.arb[gsrc];
888 fprintf( oo, "0x%06X MOVE R%i,R%i\t\tR%02i = 0x%08X\n",
889 gpc, gsrc, gdst, gdst, gst.arb[gdst] );
893 void G_MOVE_PC( void )
898 fprintf( oo, "0x%06X MOVE PC,R%i\t\tR%02i = 0x%08X\n",
899 gpc, gdst, gdst, gst.arb[gdst] );
903 void G_MOVEFA( void )
905 gst.arb[gdst] = gst.srb[gsrc];
908 fprintf( oo, "0x%06X MOVEFA R%i,R%i\t\tR%02i = 0x%08X\n",
909 gpc, gsrc, gdst, gdst, gst.arb[gdst] );
915 gst.arb[gdst] = mem_readword(gpc + 2);
916 gst.arb[gdst] |= mem_readword(gpc + 4) << 16;
921 fprintf( oo, "0x%06X MOVEI 0x%08X,R%i\tR%02i = 0x%08X\n",
922 gpc, gst.arb[gdst], gdst, gdst, gst.arb[gdst] );
928 gst.arb[gdst] = gsrc;
931 fprintf( oo, "0x%06X MOVEQ 0x%02X,R%i\t\tR%02i = 0x%08X\n",
932 gpc, gsrc, gdst, gdst, gst.arb[gdst] );
936 void G_MOVETA( void )
938 gst.srb[gdst] = gst.arb[gsrc];
941 fprintf( oo, "0x%06X MOVETA R%i,R%i\t\tR%02i = 0x%08X(0)\n",
942 gpc, gsrc, gdst, gdst, gst.srb[gdst] );
949 fprintf( oo, "GPU - Unimplemented Opcode (MTOI)\n" );
951 gst.gpuActive = FALSE;
956 gst.arb[gdst] = (sdword)((word)gst.arb[gsrc] *
957 (word)gst.arb[gdst] );
959 gz = (gst.arb[gdst] == 0) ? 1 : 0;
960 gn = (gst.arb[gdst] < 0) ? 1 : 0;
963 fprintf( oo, "0x%06X MULT R%i,R%i\t\tR%02i = 0x%08X "
964 "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst,
965 gst.arb[gdst], gz, gn, gc );
973 mov eax,[ecx*4+gst.arb]
975 mov [ecx*4+gst.arb],eax
983 gz = (gst.arb[gdst] == 0) ? 1 : 0;
984 gn = (gst.arb[gdst] < 0) ? 1 : 0;
987 fprintf( oo, "0x%06X NEG R%i\t\t\tR%02i = 0x%08X Z:%i N:%i C:%i\n",
988 gpc, gdst, gdst, gst.arb[gdst],
996 fprintf( oo, "0x%06X NOP\n", gpc );
1000 void G_NORMI( void )
1003 fprintf( oo, "GPU - Unimplemented Opcode (NORMI)\n" );
1005 gst.gpuActive = FALSE;
1008 void G_NOT( void ) // Fix donated by YaK
1010 gst.arb[gdst] = gst.arb[gdst] ^ 0xFFFFFFFF;
1011 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1012 gn = (gst.arb[gdst] < 0) ? 1 : 0;
1015 fprintf( oo, "0x%06X NOT R%i\t\t\tR%02i = 0x%08X Z:%i N:%i C:%i\n",
1016 gpc, gdst, gdst, gst.arb[gdst],
1023 gst.arb[gdst] |= gst.arb[gsrc];
1024 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1025 gn = (gst.arb[gdst] < 0) ? 1 : 0;
1028 fprintf( oo, "0x%06X OR R%i,R%i\t\tR%02i = 0x%08X Z:%i N:%i C:%i\n",
1029 gpc, gsrc, gdst, gdst, gst.arb[gdst],
1034 void G_PACK_UNPACK( void )
1038 tmpW = gst.arb[gdst];
1040 if( gsrc ) // UNPACK
1042 gst.arb[gdst] = (tmpW & 0x000000FF);
1043 gst.arb[gdst] |= (tmpW & 0x00000F00) << 5;
1044 gst.arb[gdst] |= (tmpW & 0x0000F000) << 10;
1047 fprintf( oo, "0x%06X UNPACK R%i\t\t\tR%02i = 0x%08X\n",
1048 gpc, gdst, gdst, gst.arb[gdst] );
1053 gst.arb[gdst] = (tmpW & 0x000000FF);
1054 gst.arb[gdst] |= (tmpW & 0x0001E000) >> 5;
1055 gst.arb[gdst] |= (tmpW & 0x03C00000) >> 10;
1058 fprintf( oo, "0x%06X PACK R%i\t\t\tR%02i = 0x%08X\n",
1059 gpc, gdst, gdst, gst.arb[gdst] );
1064 void G_RESMAC( void )
1066 // Write result register to Register Rn
1067 // Used as last part of multiply/accumulate group.
1069 gst.arb[gdst] = gst.acc;
1072 fprintf( oo, "0x%06X RESMAC R%i\t\tR%02X = 0x%08X\n",
1073 gpc, gdst, gdst, gst.arb[gdst] );
1079 gc = (gst.arb[gdst] >> 31) & 0x01;
1083 mov eax,[ecx*4+gst.arb]
1085 mov ecx,[edx*4+gst.arb]
1089 mov [ecx*4+gst.arb],eax
1092 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1093 gn = (gst.arb[gdst] < 0) ? 1 : 0;
1096 fprintf( oo, "0x%06X ROR R%i,R%i\t\tR%02i = 0x%08X Z:%i N:%i C:%i\n",
1097 gpc, gsrc, gdst, gdst, gst.arb[gdst],
1106 gc = (gst.arb[gdst] >> 31) & 0x01;
1107 tmpW = gst.arb[gdst];
1116 gst.arb[gdst] = tmpW;
1118 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1119 gn = (gst.arb[gdst] < 0) ? 1 : 0;
1122 fprintf( oo, "0x%06X RORQ 0x%02X,R%i\t\tR%02i = 0x%08X "
1124 gpc, gsrc, gdst, gdst, gst.arb[gdst],
1131 if( gst.arb[gdst] < 0 ) gst.arb[gdst] =0x00000000;
1132 if( gst.arb[gdst] > 255 ) gst.arb[gdst] =0x000000FF;
1135 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1138 fprintf( oo, "0x%06X SAT8 R%02i\t\t\tR%02i = 0x%08X "
1140 gpc, gdst, gdst, gst.arb[gdst],
1145 void G_SAT16( void )
1147 if( gst.arb[gdst] < 0 ) gst.arb[gdst] =0x00000000;
1148 if( gst.arb[gdst] > 65535 ) gst.arb[gdst] =0x0000FFFF;
1151 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1154 fprintf( oo, "0x%06X SAT16 R%02i\t\t\tR%02i = 0x%08X "
1156 gpc, gdst, gdst, gst.arb[gdst],
1161 void G_SAT24( void )
1163 if( gst.arb[gdst] < 0 ) gst.arb[gdst] =0x00000000;
1164 if( gst.arb[gdst] > 16777215 ) gst.arb[gdst] =0x00FFFFFF;
1167 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1170 fprintf( oo, "0x%06X SAT24 R%02i\t\t\tR%02i = 0x%08X "
1172 gpc, gdst, gdst, gst.arb[gdst],
1181 // NOTE: Watch the values here carefully
1183 if( gst.arb[gsrc] >= 0 ) // Shift Right
1185 gc = gst.arb[gdst] & 0x01;
1186 tmpW = gst.arb[gsrc];
1189 mov eax,[edx*4+gst.arb]
1192 mov [edx*4+gst.arb],eax
1197 gc = (gst.arb[gdst] >> 31) & 0x01;
1198 // Fix donated by YaK
1199 tmpW = (0xFFFFFFFF - gst.arb[gsrc]) + 1;
1202 mov eax,[edx*4+gst.arb]
1205 mov [edx*4+gst.arb],eax
1209 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1210 gn = (gst.arb[gdst] < 0) ? 1 : 0;
1213 fprintf( oo, "0x%06X SH R%i,R%i\t\tR%02i = 0x%08X "
1215 gpc, gsrc, gdst, gdst, gst.arb[gdst],
1224 // NOTE: Watch the values here carefully
1226 if( gst.arb[gsrc] >= 0 ) // Shift Right
1228 gc = gst.arb[gdst] & 0x01;
1229 tmpW = gst.arb[gsrc];
1232 mov eax,[edx*4+gst.arb]
1235 mov [edx*4+gst.arb],eax
1240 gc = (gst.arb[gdst] >> 31) & 0x01;
1241 // Fix donated by YaK
1242 tmpW = (0xFFFFFFFF - gst.arb[gsrc]) + 1;
1245 mov eax,[edx*4+gst.arb]
1248 mov [edx*4+gst.arb],eax
1252 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1253 gn = (gst.arb[gdst] < 0) ? 1 : 0;
1256 fprintf( oo, "0x%06X SHA R%i,R%i\t\tR%02i = 0x%08X "
1258 gpc, gsrc, gdst, gdst, gst.arb[gdst],
1263 void G_SHARQ( void )
1267 gc = (gst.arb[gdst] & 0x01);
1268 tmpW = gst.arb[gdst];
1277 gst.arb[gdst] = tmpW;
1279 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1280 gn = (gst.arb[gdst] < 0) ? 1 : 0;
1283 fprintf( oo, "0x%06X SHARQ 0x%02X,R%i\t\tR%02i = 0x%08X "
1284 "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst,
1285 gst.arb[gdst], gz, gn, gc );
1291 gc = (gst.arb[gdst] >> 31) & 0x01;
1292 gst.arb[gdst] <<= (32 - gsrc);
1294 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1295 gn = (gst.arb[gdst] < 0) ? 1 : 0;
1298 fprintf( oo, "0x%06X SHLQ 0x%02X,R%i\t\tR%02i = 0x%08X "
1299 "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst,
1300 gst.arb[gdst], gz, gn, gc );
1306 gc = gst.arb[gdst] & 0x01;
1307 gst.arb[gdst] >>= (32 - gsrc);
1309 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1310 gn = (gst.arb[gdst] < 0) ? 1 : 0;
1313 fprintf( oo, "0x%06X SHRQ 0x%02X,R%i\t\tR%02i = 0x%08X "
1314 "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst,
1315 gst.arb[gdst], gz, gn, gc );
1319 void G_STORE( void )
1321 mem_writeword( gst.arb[gsrc], (gst.arb[gdst] >> 16) );
1322 mem_writeword( gst.arb[gsrc] + 2, (gst.arb[gdst] & 0xFFFF) );
1325 fprintf( oo, "0x%06X STORE R%i,(R%i)\t\tgdst = 0x%08X\n",
1326 gpc, gdst, gsrc, gst.arb[gsrc] );
1330 void G_STORE_14I( void )
1334 tmpW = gst.arb[0x0E] + (gsrc * 4);
1336 mem_writeword( tmpW, (gst.arb[gdst] >> 16) );
1337 mem_writeword( tmpW + 2, (gst.arb[gdst] & 0xFFFF) );
1340 fprintf( oo, "0x%06X STORE R%i,(R14+%02i)\t\tgdst = 0x%08X\n",
1341 gpc, gsrc, gdst, tmpW );
1345 void G_STORE_15I( void )
1349 tmpW = gst.arb[0x0F] + (gsrc * 4);
1351 mem_writeword( tmpW, (gst.arb[gdst] >> 16) );
1352 mem_writeword( tmpW + 2, (gst.arb[gdst] & 0xFFFF) );
1355 fprintf( oo, "0x%06X STORE R%i,(R15+%02i)\t\tgdst = 0x%08X\n",
1356 gpc, gsrc, gdst, tmpW );
1360 void G_STORE_14R( void )
1364 tmpW = gst.arb[0x0E] + gst.arb[gsrc];
1365 mem_writeword( tmpW, (gst.arb[gdst] >> 16) );
1366 mem_writeword( tmpW + 2, (gst.arb[gdst] & 0xFFFF) );
1369 fprintf( oo, "0x%06X STORE R%i,(R14+R%i)\tgdst = 0x%08X\n",
1370 gpc, gdst, gsrc, tmpW );
1374 void G_STORE_15R( void )
1378 // NOTE: Manual seems to indicate that this opcode
1379 // uses Register 14 as the base offset address.
1381 tmpW = gst.arb[0x0E] + gst.arb[gsrc];
1382 mem_writeword( tmpW, (gst.arb[gdst] >> 16) );
1383 mem_writeword( tmpW + 2, (gst.arb[gdst] & 0xFFFF) );
1386 fprintf( oo, "0x%06X STORE R%i,(R14+R%i)\tgdst = 0x%08X\n",
1387 gpc, gdst, gsrc, tmpW );
1391 void G_STOREB( void )
1393 if( gst.arb[gsrc] >= 0xF03000 && gst.arb[gsrc] < 0xF04000 )
1395 mem_writeword( gst.arb[gsrc], (gst.arb[gdst] >> 16) );
1396 mem_writeword( gst.arb[gsrc] + 2, (gst.arb[gdst] & 0xFFFF) );
1399 mem_writebyte( gst.arb[gsrc], (gst.arb[gdst] & 0xFF) );
1402 fprintf( oo, "0x%06X STOREB R%i,(R%i)\tgdst = 0x%08X\n",
1403 gpc, gdst, gsrc, gsrc );
1407 void G_STOREW( void )
1409 if( gst.arb[gsrc] >= 0xF03000 && gst.arb[gsrc] < 0xF04000 )
1411 mem_writeword( gst.arb[gsrc], (gst.arb[gdst] >> 16) );
1412 mem_writeword( gst.arb[gsrc] + 2, (gst.arb[gdst] & 0xFFFF) );
1415 mem_writeword( gst.arb[gsrc], (gst.arb[gdst] & 0xFFFF) );
1418 fprintf( oo, "0x%06X STOREW R%i,(R%i)\tgdst = 0x%08X\n",
1419 gpc, gdst, gsrc, gsrc );
1423 void G_STOREP( void )
1426 fprintf( oo, "GPU - Unimplemented Opcode (STOREP)\n" );
1428 gst.gpuActive = FALSE;
1435 mov edx,[ecx*4+gst.arb]
1437 mov eax,[ecx*4+gst.arb]
1439 mov [ecx*4+gst.arb],eax
1447 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1448 gn = (gst.arb[gdst] < 0) ? 1 : 0;
1451 fprintf( oo, "0x%06X SUB R%i,R%i\t\tR%02i = 0x%08X Z:%i N:%i C:%i\n",
1452 gpc, gsrc, gdst, gdst, gst.arb[gdst],
1466 mov edx,[ecx*4+gst.arb]
1468 mov eax,[ecx*4+gst.arb]
1470 mov [ecx*4+gst.arb],eax
1478 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1479 gn = (gst.arb[gdst] < 0) ? 1 : 0;
1482 fprintf( oo, "0x%06X SUBC R%i,R%i\t\tR%02i = 0x%08X "
1483 "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst,
1484 gst.arb[gdst], gz, gn, gc );
1492 mov eax,[ecx*4+gst.arb]
1495 mov [ecx*4+gst.arb],eax
1503 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1504 gn = (gst.arb[gdst] < 0) ? 1 : 0;
1507 fprintf( oo, "0x%06X SUBQ 0x%02X,R%i\t\tR%02i = 0x%08X "
1508 "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst,
1509 gst.arb[gdst], gz, gn, gc );
1513 void G_SUBQT( void )
1517 mov eax,[ecx*4+gst.arb]
1520 mov [ecx*4+gst.arb],eax
1524 fprintf( oo, "0x%06X SUBQT 0x%02X,R%i\t\tR%02i = 0x%08X\n",
1525 gpc, gsrc, gdst, gdst, gst.arb[gdst] );
1531 gst.arb[gdst] ^= gst.arb[gsrc];
1532 gz = (gst.arb[gdst] == 0) ? 1 : 0;
1533 gn = (gst.arb[gdst] < 0) ? 1 : 0;
1536 fprintf( oo, "0x%06X XOR R%i,R%i\t\tR%02i = 0x%08X Z:%i N:%i C:%i\n",
1537 gpc, gsrc, gdst, gdst, gst.arb[gdst],