]> Shamusworld >> Repos - virtualjaguar/blob - src/dsp.cpp
More updates to pipelined core
[virtualjaguar] / src / dsp.cpp
1 //
2 // DSP core
3 //
4 // Original source by Cal2
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Extensive cleanups/rewrites by James L. Hammons
7 //
8
9 #include <SDL.h>        // Used only for SDL_GetTicks...
10 #include "dsp.h"
11
12 //#define DSP_DEBUG
13 //#define DSP_DEBUG_IRQ
14 //#define DSP_DEBUG_PL2
15 //#define DSP_DEBUG_STALL
16 //#define DSP_DEBUG_CC
17
18 // Disassembly definitions
19
20 #define DSP_DIS_ABS                                                                     // Pipelined only
21 #define DSP_DIS_ADD
22 #define DSP_DIS_ADDC
23 #define DSP_DIS_ADDQ
24 #define DSP_DIS_ADDQMOD
25 #define DSP_DIS_ADDQT
26 #define DSP_DIS_AND
27 #define DSP_DIS_BCLR
28 #define DSP_DIS_BSET
29 #define DSP_DIS_BTST
30 #define DSP_DIS_CMP
31 #define DSP_DIS_CMPQ
32 #define DSP_DIS_IMACN
33 #define DSP_DIS_IMULT
34 #define DSP_DIS_IMULTN
35 #define DSP_DIS_ILLEGAL
36 #define DSP_DIS_JR
37 #define DSP_DIS_JUMP
38 #define DSP_DIS_LOAD
39 #define DSP_DIS_LOAD14I
40 #define DSP_DIS_LOAD14R
41 #define DSP_DIS_LOAD15I
42 #define DSP_DIS_LOAD15R
43 #define DSP_DIS_LOADB
44 #define DSP_DIS_LOADW
45 #define DSP_DIS_MOVE
46 #define DSP_DIS_MOVEI
47 #define DSP_DIS_MOVEQ
48 #define DSP_DIS_MOVEFA
49 #define DSP_DIS_MOVETA
50 #define DSP_DIS_MULT
51 #define DSP_DIS_NEG
52 #define DSP_DIS_NOP
53 #define DSP_DIS_NOT
54 #define DSP_DIS_OR
55 #define DSP_DIS_RESMAC
56 #define DSP_DIS_ROR
57 #define DSP_DIS_RORQ
58 #define DSP_DIS_SHARQ
59 #define DSP_DIS_SHLQ
60 #define DSP_DIS_SHRQ
61 #define DSP_DIS_STORE
62 #define DSP_DIS_STORE14I
63 #define DSP_DIS_STORE15I
64 #define DSP_DIS_STOREB
65 #define DSP_DIS_STOREW
66 #define DSP_DIS_SUB
67 #define DSP_DIS_SUBC
68 #define DSP_DIS_SUBQ
69 #define DSP_DIS_SUBQT
70 #define DSP_DIS_XOR
71 //*/
72 bool doDSPDis = false;
73 //bool doDSPDis = true;
74
75
76 /*
77 No dis yet:
78 +       subqt 4560
79 +       mult 1472
80 +       imultn 395024
81 +       resmac 395024
82 +       imacn 395024
83 +       addqmod 93328
84
85 dsp opcodes use:
86 +       add 1672497
87 +       addq 4366576
88 +       addqt 44405640
89 +       sub 94833
90 +       subq 111769
91 +       and 47416
92 +       btst 94521
93 +       bset 2277826
94 +       bclr 3223372
95 +       mult 47104
96 +       imult 237080
97 +       shlq 365464
98 +       shrq 141624
99 +       sharq 318368
100 +       cmp 45175078
101 +       move 2238994
102 +       moveq 335305
103 +       moveta 19
104 +       movefa 47406440
105 +       movei 1920664
106 +       loadb 94832
107 +       load 4031281
108 +       load_r15_indexed 284500
109 +       store 2161732
110 +       store_r15_indexed 47416
111 +       jump 3872424
112 +       jr 46386967
113 +       nop 3300029
114 +       load_r14_ri 1229448
115 */
116
117 // Pipeline structures
118
119 const bool affectsScoreboard[64] =
120 {
121          true,  true,  true,  true,
122          true,  true,  true,  true,
123          true,  true,  true,  true,
124          true, false,  true,  true,
125
126          true,  true, false,  true,
127         false,  true,  true,  true,
128          true,  true,  true,  true,
129          true,  true, false, false,
130
131          true,  true,  true,  true,
132         false,  true,  true,  true,
133          true,  true,  true,  true,
134          true, false, false, false,
135
136          true, false, false,  true,
137         false, false,  true,  true,
138          true, false,  true,  true,
139         false, false, false,  true
140 };
141
142 struct PipelineStage
143 {
144         uint16 instruction;
145         uint8 opcode, operand1, operand2;
146         uint32 reg1, reg2, areg1, areg2;
147         uint32 result;
148         uint8 writebackRegister;
149         // General memory store...
150         uint32 address;
151         uint32 value;
152         uint8 type;
153 };
154
155 #define TYPE_BYTE                       0
156 #define TYPE_WORD                       1
157 #define TYPE_DWORD                      2
158 #define PIPELINE_STALL          64                                              // Set to # of opcodes + 1
159 bool scoreboard[32];
160 uint8 plPtrFetch, plPtrRead, plPtrExec, plPtrWrite;
161 PipelineStage pipeline[4];
162 bool IMASKCleared = false;
163
164 // DSP flags (old--have to get rid of this crap)
165
166 #define CINT0FLAG                       0x00200
167 #define CINT1FLAG                       0x00400
168 #define CINT2FLAG                       0x00800
169 #define CINT3FLAG                       0x01000
170 #define CINT4FLAG                       0x02000
171 #define CINT04FLAGS                     (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
172 #define CINT5FLAG                       0x20000         /* DSP only */
173
174 // DSP_FLAGS bits
175
176 #define ZERO_FLAG               0x00001
177 #define CARRY_FLAG              0x00002
178 #define NEGA_FLAG               0x00004
179 #define IMASK                   0x00008
180 #define INT_ENA0                0x00010
181 #define INT_ENA1                0x00020
182 #define INT_ENA2                0x00040
183 #define INT_ENA3                0x00080
184 #define INT_ENA4                0x00100
185 #define INT_CLR0                0x00200
186 #define INT_CLR1                0x00400
187 #define INT_CLR2                0x00800
188 #define INT_CLR3                0x01000
189 #define INT_CLR4                0x02000
190 #define REGPAGE                 0x04000
191 #define DMAEN                   0x08000
192 #define INT_ENA5                0x10000
193 #define INT_CLR5                0x20000
194
195 // DSP_CTRL bits
196
197 #define DSPGO                   0x00001
198 #define CPUINT                  0x00002
199 #define DSPINT0                 0x00004
200 #define SINGLE_STEP             0x00008
201 #define SINGLE_GO               0x00010
202 // Bit 5 is unused!
203 #define INT_LAT0                0x00040
204 #define INT_LAT1                0x00080
205 #define INT_LAT2                0x00100
206 #define INT_LAT3                0x00200
207 #define INT_LAT4                0x00400
208 #define BUS_HOG                 0x00800
209 #define VERSION                 0x0F000
210 #define INT_LAT5                0x10000
211
212 extern uint32 jaguar_mainRom_crc32;
213
214 // Is opcode 62 *really* a NOP? Seems like it...
215 static void dsp_opcode_abs(void);
216 static void dsp_opcode_add(void);
217 static void dsp_opcode_addc(void);
218 static void dsp_opcode_addq(void);
219 static void dsp_opcode_addqmod(void);   
220 static void dsp_opcode_addqt(void);
221 static void dsp_opcode_and(void);
222 static void dsp_opcode_bclr(void);
223 static void dsp_opcode_bset(void);
224 static void dsp_opcode_btst(void);
225 static void dsp_opcode_cmp(void);
226 static void dsp_opcode_cmpq(void);
227 static void dsp_opcode_div(void);
228 static void dsp_opcode_imacn(void);
229 static void dsp_opcode_imult(void);
230 static void dsp_opcode_imultn(void);
231 static void dsp_opcode_jr(void);
232 static void dsp_opcode_jump(void);
233 static void dsp_opcode_load(void);
234 static void dsp_opcode_loadb(void);
235 static void dsp_opcode_loadw(void);
236 static void dsp_opcode_load_r14_indexed(void);
237 static void dsp_opcode_load_r14_ri(void);
238 static void dsp_opcode_load_r15_indexed(void);
239 static void dsp_opcode_load_r15_ri(void);
240 static void dsp_opcode_mirror(void);    
241 static void dsp_opcode_mmult(void);
242 static void dsp_opcode_move(void);
243 static void dsp_opcode_movei(void);
244 static void dsp_opcode_movefa(void);
245 static void dsp_opcode_move_pc(void);
246 static void dsp_opcode_moveq(void);
247 static void dsp_opcode_moveta(void);
248 static void dsp_opcode_mtoi(void);
249 static void dsp_opcode_mult(void);
250 static void dsp_opcode_neg(void);
251 static void dsp_opcode_nop(void);
252 static void dsp_opcode_normi(void);
253 static void dsp_opcode_not(void);
254 static void dsp_opcode_or(void);
255 static void dsp_opcode_resmac(void);
256 static void dsp_opcode_ror(void);
257 static void dsp_opcode_rorq(void);
258 static void dsp_opcode_xor(void);
259 static void dsp_opcode_sat16s(void);    
260 static void dsp_opcode_sat32s(void);    
261 static void dsp_opcode_sh(void);
262 static void dsp_opcode_sha(void);
263 static void dsp_opcode_sharq(void);
264 static void dsp_opcode_shlq(void);
265 static void dsp_opcode_shrq(void);
266 static void dsp_opcode_store(void);
267 static void dsp_opcode_storeb(void);
268 static void dsp_opcode_storew(void);
269 static void dsp_opcode_store_r14_indexed(void);
270 static void dsp_opcode_store_r14_ri(void);
271 static void dsp_opcode_store_r15_indexed(void);
272 static void dsp_opcode_store_r15_ri(void);
273 static void dsp_opcode_sub(void);
274 static void dsp_opcode_subc(void);
275 static void dsp_opcode_subq(void);
276 static void dsp_opcode_subqmod(void);   
277 static void dsp_opcode_subqt(void);
278
279 uint8 dsp_opcode_cycles[64] =
280 {
281         3,  3,  3,  3,  
282         3,  3,  3,  3,  
283         3,  3,  3,  3,  
284         3,  3,  3,  3,
285         3,  3,  1,  3,  
286         1, 18,  3,  3,  
287         3,  3,  3,  3,  
288         3,  3,  3,  3,
289         3,  3,  2,  2,  
290         2,  2,  3,  4,  
291         5,  4,  5,  6,  
292         6,  1,  1,  1,
293         1,  2,  2,  2,  
294         1,  1,  9,  3,  
295         3,  1,  6,  6,  
296         2,  2,  3,  3
297 };
298
299 void (* dsp_opcode[64])() =
300 {       
301         dsp_opcode_add,                                 dsp_opcode_addc,                                dsp_opcode_addq,                                dsp_opcode_addqt,
302         dsp_opcode_sub,                                 dsp_opcode_subc,                                dsp_opcode_subq,                                dsp_opcode_subqt,
303         dsp_opcode_neg,                                 dsp_opcode_and,                                 dsp_opcode_or,                                  dsp_opcode_xor,
304         dsp_opcode_not,                                 dsp_opcode_btst,                                dsp_opcode_bset,                                dsp_opcode_bclr,
305         dsp_opcode_mult,                                dsp_opcode_imult,                               dsp_opcode_imultn,                              dsp_opcode_resmac,
306         dsp_opcode_imacn,                               dsp_opcode_div,                                 dsp_opcode_abs,                                 dsp_opcode_sh,
307         dsp_opcode_shlq,                                dsp_opcode_shrq,                                dsp_opcode_sha,                                 dsp_opcode_sharq,
308         dsp_opcode_ror,                                 dsp_opcode_rorq,                                dsp_opcode_cmp,                                 dsp_opcode_cmpq,
309         dsp_opcode_subqmod,                             dsp_opcode_sat16s,                              dsp_opcode_move,                                dsp_opcode_moveq,
310         dsp_opcode_moveta,                              dsp_opcode_movefa,                              dsp_opcode_movei,                               dsp_opcode_loadb,
311         dsp_opcode_loadw,                               dsp_opcode_load,                                dsp_opcode_sat32s,                              dsp_opcode_load_r14_indexed,
312         dsp_opcode_load_r15_indexed,    dsp_opcode_storeb,                              dsp_opcode_storew,                              dsp_opcode_store,
313         dsp_opcode_mirror,                              dsp_opcode_store_r14_indexed,   dsp_opcode_store_r15_indexed,   dsp_opcode_move_pc,
314         dsp_opcode_jump,                                dsp_opcode_jr,                                  dsp_opcode_mmult,                               dsp_opcode_mtoi,
315         dsp_opcode_normi,                               dsp_opcode_nop,                                 dsp_opcode_load_r14_ri,                 dsp_opcode_load_r15_ri,
316         dsp_opcode_store_r14_ri,                dsp_opcode_store_r15_ri,                dsp_opcode_nop,                                 dsp_opcode_addqmod,
317 };
318
319 uint32 dsp_opcode_use[65];
320
321 char * dsp_opcode_str[65]=
322 {       
323         "add",                          "addc",                         "addq",                         "addqt",
324         "sub",                          "subc",                         "subq",                         "subqt",
325         "neg",                          "and",                          "or",                           "xor",
326         "not",                          "btst",                         "bset",                         "bclr",
327         "mult",                         "imult",                        "imultn",                       "resmac",
328         "imacn",                        "div",                          "abs",                          "sh",
329         "shlq",                         "shrq",                         "sha",                          "sharq",
330         "ror",                          "rorq",                         "cmp",                          "cmpq",
331         "subqmod",                      "sat16s",                       "move",                         "moveq",
332         "moveta",                       "movefa",                       "movei",                        "loadb",
333         "loadw",                        "load",                         "sat32s",                       "load_r14_indexed",
334         "load_r15_indexed",     "storeb",                       "storew",                       "store",
335         "mirror",                       "store_r14_indexed","store_r15_indexed","move_pc",
336         "jump",                         "jr",                           "mmult",                        "mtoi",
337         "normi",                        "nop",                          "load_r14_ri",          "load_r15_ri",
338         "store_r14_ri",         "store_r15_ri",         "illegal",                      "addqmod",
339         "STALL"
340 };
341
342 uint32 dsp_pc;
343 static uint64 dsp_acc;                                                          // 40 bit register, NOT 32!
344 static uint32 dsp_remain;
345 static uint32 dsp_modulo;
346 static uint32 dsp_flags;
347 static uint32 dsp_matrix_control;
348 static uint32 dsp_pointer_to_matrix;
349 static uint32 dsp_data_organization;
350 uint32 dsp_control;
351 static uint32 dsp_div_control;
352 static uint8 dsp_flag_z, dsp_flag_n, dsp_flag_c;    
353 static uint32 * dsp_reg, * dsp_alternate_reg;
354 static uint32 * dsp_reg_bank_0, * dsp_reg_bank_1;
355
356 static uint32 dsp_opcode_first_parameter;
357 static uint32 dsp_opcode_second_parameter;
358
359 #define DSP_RUNNING                     (dsp_control & 0x01)
360
361 #define RM                                      dsp_reg[dsp_opcode_first_parameter]
362 #define RN                                      dsp_reg[dsp_opcode_second_parameter]
363 #define ALTERNATE_RM            dsp_alternate_reg[dsp_opcode_first_parameter]
364 #define ALTERNATE_RN            dsp_alternate_reg[dsp_opcode_second_parameter]
365 #define IMM_1                           dsp_opcode_first_parameter
366 #define IMM_2                           dsp_opcode_second_parameter
367
368 #define CLR_Z                           (dsp_flag_z = 0)
369 #define CLR_ZN                          (dsp_flag_z = dsp_flag_n = 0)
370 #define CLR_ZNC                         (dsp_flag_z = dsp_flag_n = dsp_flag_c = 0)
371 #define SET_Z(r)                        (dsp_flag_z = ((r) == 0))
372 #define SET_N(r)                        (dsp_flag_n = (((UINT32)(r) >> 31) & 0x01))
373 #define SET_C_ADD(a,b)          (dsp_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
374 #define SET_C_SUB(a,b)          (dsp_flag_c = ((UINT32)(b) > (UINT32)(a)))
375 #define SET_ZN(r)                       SET_N(r); SET_Z(r)
376 #define SET_ZNC_ADD(a,b,r)      SET_N(r); SET_Z(r); SET_C_ADD(a,b)
377 #define SET_ZNC_SUB(a,b,r)      SET_N(r); SET_Z(r); SET_C_SUB(a,b)
378
379 uint32 dsp_convert_zero[32] = { 32,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 };
380 uint8 * dsp_branch_condition_table = NULL;
381 static uint16 * mirror_table = NULL;
382 static uint8 * dsp_ram_8 = NULL;
383
384 #define BRANCH_CONDITION(x)             dsp_branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
385
386 static uint32 dsp_in_exec = 0;
387 static uint32 dsp_releaseTimeSlice_flag = 0;
388
389 FILE * dsp_fp;
390
391 #ifdef DSP_DEBUG_CC
392 // Comparison core vars (used only for core comparison! :-)
393 static uint64 count = 0;
394 static uint8 ram1[0x2000], ram2[0x2000];
395 static uint32 regs1[64], regs2[64];
396 static uint32 ctrl1[14], ctrl2[14];
397 #endif
398
399 // Private function prototypes
400
401 void DSPDumpRegisters(void);
402 void DSPDumpDisassembly(void);
403 void FlushDSPPipeline(void);
404
405
406 void dsp_reset_stats(void)
407 {
408         for(int i=0; i<65; i++)
409                 dsp_opcode_use[i] = 0;
410 }
411
412 void dsp_releaseTimeslice(void)
413 {
414 //This does absolutely nothing!!! !!! FIX !!!
415         dsp_releaseTimeSlice_flag = 1;
416 }
417
418 void dsp_build_branch_condition_table(void)
419 {
420         // Allocate the mirror table
421         if (!mirror_table)
422                 mirror_table = (uint16 *)malloc(65536 * sizeof(mirror_table[0]));
423
424         // Fill in the mirror table
425         if (mirror_table)
426                 for(int i=0; i<65536; i++)
427                         mirror_table[i] = ((i >> 15) & 0x0001) | ((i >> 13) & 0x0002) |
428                                           ((i >> 11) & 0x0004) | ((i >> 9)  & 0x0008) |
429                                           ((i >> 7)  & 0x0010) | ((i >> 5)  & 0x0020) |
430                                           ((i >> 3)  & 0x0040) | ((i >> 1)  & 0x0080) |
431                                           ((i << 1)  & 0x0100) | ((i << 3)  & 0x0200) |
432                                           ((i << 5)  & 0x0400) | ((i << 7)  & 0x0800) |
433                                           ((i << 9)  & 0x1000) | ((i << 11) & 0x2000) |
434                                           ((i << 13) & 0x4000) | ((i << 15) & 0x8000);
435
436         if (!dsp_branch_condition_table)
437         {
438                 dsp_branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(dsp_branch_condition_table[0]));
439
440                 // Fill in the condition table
441                 if (dsp_branch_condition_table)
442                 {
443                         for(int i=0; i<8; i++)
444                         {
445                                 for(int j=0; j<32; j++)
446                                 {
447                                         int result = 1;
448                                         if (j & 1)
449                                                 if (i & ZERO_FLAG)
450                                                         result = 0;
451                                         if (j & 2)
452                                                 if (!(i & ZERO_FLAG))
453                                                         result = 0;
454                                         if (j & 4)
455                                                 if (i & (CARRY_FLAG << (j >> 4)))
456                                                         result = 0;
457                                         if (j & 8)
458                                                 if (!(i & (CARRY_FLAG << (j >> 4))))
459                                                         result = 0;
460                                         dsp_branch_condition_table[i * 32 + j] = result;
461                                 }
462                         }
463                 }
464         }
465 }
466
467 uint8 DSPReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
468 {
469         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
470                 WriteLog("DSP: ReadByte--Attempt to read from DSP register file by %s!\n", whoName[who]);
471 // battlemorph
472 //      if ((offset==0xF1CFE0)||(offset==0xF1CFE2))
473 //              return(0xffff);
474         // mutant penguin
475 /*      if ((jaguar_mainRom_crc32==0xbfd751a4)||(jaguar_mainRom_crc32==0x053efaf9))
476         {
477                 if (offset==0xF1CFE0)
478                         return(0xff);
479         }*/
480         if (offset >= DSP_WORK_RAM_BASE && offset <= (DSP_WORK_RAM_BASE + 0x1FFF))
481                 return dsp_ram_8[offset - DSP_WORK_RAM_BASE];
482
483         if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
484         {
485                 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
486
487                 if ((offset&0x03)==0)
488                         return(data>>24);
489                 else
490                 if ((offset&0x03)==1)
491                         return((data>>16)&0xff);
492                 else
493                 if ((offset&0x03)==2)
494                         return((data>>8)&0xff);
495                 else
496                 if ((offset&0x03)==3)
497                         return(data&0xff);
498         }
499
500         return JaguarReadByte(offset, who);
501
502
503 uint16 DSPReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
504 {
505         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
506                 WriteLog("DSP: ReadWord--Attempt to read from DSP register file by %s!\n", whoName[who]);
507         //???
508         offset &= 0xFFFFFFFE;
509         // jaguar cd bios
510 /*      if (jaguar_mainRom_crc32==0xa74a97cd)
511         {
512                 if (offset==0xF1A114) return(0x0000);
513                 if (offset==0xF1A116) return(0x0000);
514                 if (offset==0xF1B000) return(0x1234);
515                 if (offset==0xF1B002) return(0x5678);
516         }*/
517 /*
518         if (jaguar_mainRom_crc32==0x7ae20823)
519         {
520                 if (offset==0xF1B9D8) return(0x0000);
521                 if (offset==0xF1B9Da) return(0x0000);
522                 if (offset==0xF1B2C0) return(0x0000);
523                 if (offset==0xF1B2C2) return(0x0000);
524         }
525 */
526         // pour permettre Ã  wolfenstein 3d de tourner sans le dsp
527 /*      if ((offset==0xF1B0D0)||(offset==0xF1B0D2))
528                 return(0);
529 */
530
531                 // pour permettre Ã  nba jam de tourner sans le dsp
532 /*      if (jaguar_mainRom_crc32==0x4faddb18)
533         {
534                 if (offset==0xf1b2c0) return(0);
535                 if (offset==0xf1b2c2) return(0);
536                 if (offset==0xf1b240) return(0);
537                 if (offset==0xf1b242) return(0);
538                 if (offset==0xF1B340) return(0);
539                 if (offset==0xF1B342) return(0);
540                 if (offset==0xF1BAD8) return(0);
541                 if (offset==0xF1BADA) return(0);
542                 if (offset==0xF1B040) return(0);
543                 if (offset==0xF1B042) return(0);
544                 if (offset==0xF1B0C0) return(0);
545                 if (offset==0xF1B0C2) return(0);
546                 if (offset==0xF1B140) return(0);
547                 if (offset==0xF1B142) return(0);
548                 if (offset==0xF1B1C0) return(0);
549                 if (offset==0xF1B1C2) return(0);
550         }*/
551
552         if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE+0x1FFF)
553         {
554                 offset -= DSP_WORK_RAM_BASE;
555 /*              uint16 data = (((uint16)dsp_ram_8[offset])<<8)|((uint16)dsp_ram_8[offset+1]);
556                 return data;*/
557                 return GET16(dsp_ram_8, offset);
558         }
559         else if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
560         {
561                 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
562
563                 if (offset & 0x03)
564                         return data & 0xFFFF;
565                 else
566                         return data >> 16;
567         }
568
569         return JaguarReadWord(offset, who);
570 }
571
572 uint32 DSPReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
573 {
574         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
575                 WriteLog("DSP: ReadLong--Attempt to read from DSP register file by %s!\n", whoName[who]);
576
577         // ??? WHY ???
578         offset &= 0xFFFFFFFC;
579 /*if (offset == 0xF1BCF4)
580 {
581         WriteLog("DSPReadLong: Reading from 0xF1BCF4... -> %08X [%02X %02X %02X %02X][%04X %04X]\n", GET32(dsp_ram_8, 0x0CF4), dsp_ram_8[0x0CF4], dsp_ram_8[0x0CF5], dsp_ram_8[0x0CF6], dsp_ram_8[0x0CF7], JaguarReadWord(0xF1BCF4, DSP), JaguarReadWord(0xF1BCF6, DSP));
582         DSPDumpDisassembly();
583 }*/
584         if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
585         {
586                 offset -= DSP_WORK_RAM_BASE;
587                 return GET32(dsp_ram_8, offset);
588         }
589 //NOTE: Didn't return DSP_ACCUM!!!
590 //Mebbe it's not 'spose to! Yes, it is!
591         if (offset >= DSP_CONTROL_RAM_BASE && offset <= DSP_CONTROL_RAM_BASE + 0x23)
592         {
593                 offset &= 0x3F;
594                 switch (offset)
595                 {
596                 case 0x00:      /*dsp_flag_c?(dsp_flag_c=1):(dsp_flag_c=0);
597                                         dsp_flag_z?(dsp_flag_z=1):(dsp_flag_z=0);
598                                         dsp_flag_n?(dsp_flag_n=1):(dsp_flag_n=0);*/
599
600                                         dsp_flags = (dsp_flags & 0xFFFFFFF8) | (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
601                                         return dsp_flags & 0xFFFFC1FF;
602                 case 0x04: return dsp_matrix_control;
603                 case 0x08: return dsp_pointer_to_matrix;
604                 case 0x0C: return dsp_data_organization;
605                 case 0x10: return dsp_pc;
606                 case 0x14: return dsp_control;
607                 case 0x18: return dsp_modulo;
608                 case 0x1C: return dsp_remain;
609                 case 0x20:
610                         return (int32)((int8)(dsp_acc >> 32));  // Top 8 bits of 40-bit accumulator, sign extended
611                 }
612                 // unaligned long read-- !!! FIX !!!
613                 return 0xFFFFFFFF;
614         }
615
616         return JaguarReadLong(offset, who);
617 }
618
619 void DSPWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
620 {
621         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
622                 WriteLog("DSP: WriteByte--Attempt to write to DSP register file by %s!\n", whoName[who]);
623
624         if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
625         {
626                 offset -= DSP_WORK_RAM_BASE;
627                 dsp_ram_8[offset] = data;
628 //This is rather stupid! !!! FIX !!!
629 /*              if (dsp_in_exec == 0)
630                 {
631                         m68k_end_timeslice();
632                         gpu_releaseTimeslice();
633                 }*/
634                 return;
635         }
636         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
637         {
638                 uint32 reg = offset & 0x1C;
639                 int bytenum = offset & 0x03;
640                 
641                 if ((reg >= 0x1C) && (reg <= 0x1F))
642                         dsp_div_control = (dsp_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
643                 else
644                 {
645 //This looks funky. !!! FIX !!!
646                         uint32 old_data = DSPReadLong(offset&0xFFFFFFC, who);
647                         bytenum = 3 - bytenum; // convention motorola !!!
648                         old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3)); 
649                         DSPWriteLong(offset & 0xFFFFFFC, old_data, who);
650                 }
651                 return;
652         }
653 //      WriteLog("dsp: writing %.2x at 0x%.8x\n",data,offset);
654 //Should this *ever* happen??? Shouldn't we be saying "unknown" here???
655         JaguarWriteByte(offset, data, who);
656 }
657
658 void DSPWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
659 {
660         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
661                 WriteLog("DSP: WriteWord--Attempt to write to DSP register file by %s!\n", whoName[who]);
662         offset &= 0xFFFFFFFE;
663 /*if (offset == 0xF1BCF4)
664 {
665         WriteLog("DSPWriteWord: Writing to 0xF1BCF4... %04X -> %04X\n", GET16(dsp_ram_8, 0x0CF4), data);
666 }*/
667 //      WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset);
668         if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
669         {
670                 offset -= DSP_WORK_RAM_BASE;
671                 dsp_ram_8[offset] = data >> 8;
672                 dsp_ram_8[offset+1] = data & 0xFF;
673 //This is rather stupid! !!! FIX !!!
674 /*              if (dsp_in_exec == 0)
675                 {
676 //                      WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset+DSP_WORK_RAM_BASE);
677                         m68k_end_timeslice();
678                         gpu_releaseTimeslice();
679                 }*/
680 //CC only!
681 #ifdef DSP_DEBUG_CC
682 SET16(ram1, offset, data),
683 SET16(ram2, offset, data);
684 #endif
685 //!!!!!!!!
686                 return;
687         }
688         else if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
689         {
690                 if ((offset & 0x1C) == 0x1C)
691                 {
692                         if (offset & 0x03)
693                                 dsp_div_control = (dsp_div_control&0xffff0000)|(data&0xffff);
694                         else
695                                 dsp_div_control = (dsp_div_control&0xffff)|((data&0xffff)<<16);
696                 }
697                 else
698                 {
699                         uint32 old_data = DSPReadLong(offset & 0xffffffc, who);
700                         if (offset & 0x03)
701                                 old_data = (old_data&0xffff0000)|(data&0xffff);
702                         else
703                                 old_data = (old_data&0xffff)|((data&0xffff)<<16);
704                         DSPWriteLong(offset & 0xffffffc, old_data, who);
705                 }
706                 return;
707         }
708
709         JaguarWriteWord(offset, data, who);
710 }
711
712 //bool badWrite = false;
713 void DSPWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
714 {
715         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
716                 WriteLog("DSP: WriteLong--Attempt to write to DSP register file by %s!\n", whoName[who]);
717         // ??? WHY ???
718         offset &= 0xFFFFFFFC;
719 /*if (offset == 0xF1BCF4)
720 {
721         WriteLog("DSPWriteLong: Writing to 0xF1BCF4... %08X -> %08X\n", GET32(dsp_ram_8, 0x0CF4), data);
722 }*/
723 //      WriteLog("dsp: writing %.8x at 0x%.8x\n",data,offset);
724         if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
725         {
726 /*if (offset == 0xF1BE2C)
727 {
728         WriteLog("DSP: %s is writing %08X at location 0xF1BE2C (DSP_PC: %08X)...\n", whoName[who], data, dsp_pc - 2);
729 }//*/
730                 offset -= DSP_WORK_RAM_BASE;
731                 SET32(dsp_ram_8, offset, data);
732 //CC only!
733 #ifdef DSP_DEBUG_CC
734 SET32(ram1, offset, data),
735 SET32(ram2, offset, data);
736 #endif
737 //!!!!!!!!
738                 return;
739         }
740         else if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
741         {
742                 offset &= 0x1F;
743                 switch (offset)
744                 {
745                 case 0x00:
746                 {
747 #ifdef DSP_DEBUG
748                         WriteLog("DSP: Writing %08X to DSP_FLAGS by %s (REGPAGE is %s)...\n", data, whoName[who], (dsp_flags & REGPAGE ? "set" : "not set"));
749 #endif
750 //                      bool IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
751                         IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
752                         dsp_flags = data;
753                         dsp_flag_z = dsp_flags & 0x01;
754                         dsp_flag_c = (dsp_flags >> 1) & 0x01;
755                         dsp_flag_n = (dsp_flags >> 2) & 0x01;
756                         DSPUpdateRegisterBanks();
757                         dsp_control &= ~((dsp_flags & CINT04FLAGS) >> 3);
758                         dsp_control &= ~((dsp_flags & CINT5FLAG) >> 1);
759 /*                      if (IMASKCleared)                                               // If IMASK was cleared,
760 #ifdef DSP_DEBUG_IRQ
761                         {
762                                 WriteLog("DSP: Finished interrupt.\n");
763 #endif
764                                 DSPHandleIRQs();                                        // see if any other interrupts need servicing!
765 #ifdef DSP_DEBUG_IRQ
766                         }
767 #endif//*/
768                         break;
769                 }
770                 case 0x04:
771                         dsp_matrix_control = data;
772                         break;
773                 case 0x08:
774                         // According to JTRM, only lines 2-11 are addressable, the rest being
775                         // hardwired to $F1Bxxx.
776                         dsp_pointer_to_matrix = 0xF1B000 | (data & 0x000FFC);
777                         break;
778                 case 0x0C:
779                         dsp_data_organization = data;
780                         break;
781                 case 0x10:
782                         dsp_pc = data;
783 #ifdef DSP_DEBUG
784                         WriteLog("DSP: Setting DSP PC to %08X by %s%s\n", dsp_pc, whoName[who], (DSP_RUNNING ? " (DSP is RUNNING!)" : ""));//*/
785 #endif
786 //CC only!
787 #ifdef DSP_DEBUG_CC
788 if (who != DSP)
789         ctrl1[0] = ctrl2[0] = data;
790 #endif
791 //!!!!!!!!
792                         break;
793                 case 0x14:
794                 {       
795 #ifdef DSP_DEBUG
796 WriteLog("Write to DSP CTRL by %s: %08X\n", whoName[who], data);
797 #endif
798                         bool wasRunning = DSP_RUNNING;
799 //                      uint32 dsp_was_running = DSP_RUNNING;
800                         // Check for DSP -> CPU interrupt
801                         if (data & CPUINT)
802                         {
803 #ifdef DSP_DEBUG
804                                 WriteLog("DSP: DSP -> CPU interrupt\n");
805 #endif
806 // This was WRONG
807 // Why do we check for a valid handler at 64? Isn't that the Jag programmer's responsibility?
808                                 if (JERRYIRQEnabled(IRQ2_DSP))// && jaguar_interrupt_handler_is_valid(64))
809                                 {
810                                         JERRYSetPendingIRQ(IRQ2_DSP);
811                                         dsp_releaseTimeslice();
812                                         m68k_set_irq(7);                        // Set 68000 NMI...
813                                 }
814                                 data &= ~CPUINT;
815                         }
816                         // Check for CPU -> DSP interrupt
817                         if (data & DSPINT0)
818                         {
819 #ifdef DSP_DEBUG
820                                 WriteLog("DSP: CPU -> DSP interrupt\n");
821 #endif
822                                 m68k_end_timeslice();
823                                 gpu_releaseTimeslice();
824                                 DSPSetIRQLine(DSPIRQ_CPU, ASSERT_LINE);
825                                 data &= ~DSPINT0;
826                         }
827                         // single stepping
828                         if (data & SINGLE_STEP)
829                         {
830 //                              WriteLog("DSP: Asked to perform a single step (single step is %senabled)\n", (data & 0x8 ? "" : "not "));
831                         }
832
833                         // Protect writes to VERSION and the interrupt latches...
834                         uint32 mask = VERSION | INT_LAT0 | INT_LAT1 | INT_LAT2 | INT_LAT3 | INT_LAT4 | INT_LAT5;
835                         dsp_control = (dsp_control & mask) | (data & ~mask);
836 //CC only!
837 #ifdef DSP_DEBUG_CC
838 if (who != DSP)
839         ctrl1[8] = ctrl2[8] = dsp_control;
840 #endif
841 //!!!!!!!!
842
843                         // if dsp wasn't running but is now running
844                         // execute a few cycles
845 //This is just plain wrong, wrong, WRONG!
846 #ifndef DSP_SINGLE_STEPPING
847 /*                      if (!dsp_was_running && DSP_RUNNING)
848                         {
849                                 DSPExec(200);
850                         }*/
851 #else
852 //This is WRONG! !!! FIX !!!
853                         if (dsp_control & 0x18)
854                                 DSPExec(1);
855 #endif
856 #ifdef DSP_DEBUG
857 if (DSP_RUNNING)
858         WriteLog(" --> Starting to run at %08X by %s...", dsp_pc, whoName[who]);
859 else
860         WriteLog(" --> Stopped by %s! (DSP PC: %08X)", whoName[who], dsp_pc);
861 WriteLog("\n");
862 #endif  // DSP_DEBUG
863 //This isn't exactly right either--we don't know if it was the M68K or the GPU writing here...
864 // !!! FIX !!! [DONE]
865                         if (DSP_RUNNING)
866                         {
867                                 if (who == M68K)
868                                         m68k_end_timeslice();
869                                 else if (who == GPU)
870                                         gpu_releaseTimeslice();
871
872                                 if (!wasRunning)
873                                         FlushDSPPipeline();
874 //DSPDumpDisassembly();
875                         }
876                         break;
877                 }
878                 case 0x18:
879                         dsp_modulo = data;
880                         break;
881                 case 0x1C:
882                         dsp_div_control = data;
883                         break;
884 //              default:   // unaligned long read
885                                    //__asm int 3
886                 }
887                 return;
888         }
889
890 //We don't have to break this up like this! We CAN do 32 bit writes!
891 //      JaguarWriteWord(offset, (data>>16) & 0xFFFF, DSP);
892 //      JaguarWriteWord(offset+2, data & 0xFFFF, DSP);
893 //if (offset > 0xF1FFFF)
894 //      badWrite = true;
895         JaguarWriteLong(offset, data, who);
896 }
897
898 //
899 // Update the DSP register file pointers depending on REGPAGE bit
900 //
901 void DSPUpdateRegisterBanks(void)
902 {
903         int bank = (dsp_flags & REGPAGE);
904
905         if (dsp_flags & IMASK)
906                 bank = 0;                                                       // IMASK forces main bank to be bank 0
907
908         if (bank)
909                 dsp_reg = dsp_reg_bank_1, dsp_alternate_reg = dsp_reg_bank_0;
910         else
911                 dsp_reg = dsp_reg_bank_0, dsp_alternate_reg = dsp_reg_bank_1;
912 }
913
914 //
915 // Check for and handle any asserted DSP IRQs
916 //
917 void DSPHandleIRQs(void)
918 {
919         if (dsp_flags & IMASK)                                                  // Bail if we're already inside an interrupt
920                 return;
921
922         // Get the active interrupt bits (latches) & interrupt mask (enables)
923         uint32 bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
924                 mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
925
926 //      WriteLog("dsp: bits=%.2x mask=%.2x\n",bits,mask);
927         bits &= mask;
928
929         if (!bits)                                                                              // Bail if nothing is enabled
930                 return;
931
932         int which = 0;                                                                  // Determine which interrupt 
933         if (bits & 0x01)
934                 which = 0;
935         if (bits & 0x02)
936                 which = 1;
937         if (bits & 0x04)
938                 which = 2;
939         if (bits & 0x08)
940                 which = 3;
941         if (bits & 0x10)
942                 which = 4;
943         if (bits & 0x20)
944                 which = 5;
945
946 #ifdef DSP_DEBUG_IRQ
947         WriteLog("DSP: Generating interrupt #%i...", which);
948 #endif
949 //temp... !!!!!
950 //if (which == 0)       doDSPDis = true;
951
952         // NOTE: Since the actual Jaguar hardware injects the code sequence below
953         //       directly into the pipeline, it has the side effect of ensuring that the
954         //       instruction interrupted also gets to do its writeback. We simulate that
955         //       behavior here.
956 /*      if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
957         {
958                 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
959                         dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
960
961                 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
962                         scoreboard[pipeline[plPtrWrite].operand2] = false;
963         }//*/
964 //This should be execute (or should it?--not sure now!)
965 //Actually, the way this is called now, this should be correct (i.e., the plPtrs advance,
966 //and what just executed is now in the Write position...). So why didn't it do the
967 //writeback into register 0?
968 #ifdef DSP_DEBUG_IRQ
969 WriteLog("--> Pipeline dump [DSP_PC=%08X]...\n", dsp_pc);
970 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister, dsp_opcode_str[pipeline[plPtrRead].opcode]);
971 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister, dsp_opcode_str[pipeline[plPtrExec].opcode]);
972 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister, dsp_opcode_str[pipeline[plPtrWrite].opcode]);
973 #endif
974         if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
975         {
976                 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
977                 {
978                         if (pipeline[plPtrWrite].writebackRegister != 0xFE)
979                                 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
980                         else
981                         {
982                                 if (pipeline[plPtrWrite].type == TYPE_BYTE)
983                                         JaguarWriteByte(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
984                                 else if (pipeline[plPtrWrite].type == TYPE_WORD)
985                                         JaguarWriteWord(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
986                                 else
987                                         JaguarWriteLong(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
988                         }
989                 }
990
991                 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
992                         scoreboard[pipeline[plPtrWrite].operand2] = false;
993         }
994
995         dsp_flags |= IMASK;
996 //CC only!
997 #ifdef DSP_DEBUG_CC
998 ctrl2[4] = dsp_flags;
999 #endif
1000 //!!!!!!!!
1001         DSPUpdateRegisterBanks();
1002 #ifdef DSP_DEBUG_IRQ
1003 //      WriteLog(" [PC will return to %08X, R31 = %08X]\n", dsp_pc, dsp_reg[31]);
1004         WriteLog(" [PC will return to %08X, R31 = %08X]\n", dsp_pc - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2)), dsp_reg[31]);
1005 #endif
1006
1007         // subqt  #4,r31                ; pre-decrement stack pointer 
1008         // move   pc,r30                ; address of interrupted code 
1009         // store  r30,(r31)     ; store return address
1010         dsp_reg[31] -= 4;
1011 //CC only!
1012 #ifdef DSP_DEBUG_CC
1013 regs2[31] -= 4;
1014 #endif
1015 //!!!!!!!!
1016 //This might not come back to the right place if the instruction was MOVEI #. !!! FIX !!!
1017 //But, then again, JTRM says that it adds two regardless of what the instruction was...
1018 //It missed the place that it was supposed to come back to, so this is WRONG!
1019 //
1020 // Look at the pipeline when an interrupt occurs (instructions of foo, bar, baz):
1021 //
1022 // R -> baz             (<- PC points here)
1023 // E -> bar             (when it should point here!)
1024 // W -> foo
1025 //
1026 // 'Foo' just completed executing as per above. PC is pointing to the instruction 'baz'
1027 // which means (assuming they're all 2 bytes long) that the code below will come back on
1028 // instruction 'baz' instead of 'bar' which is the next instruction to execute in the
1029 // instruction stream...
1030
1031 //      DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
1032         DSPWriteLong(dsp_reg[31], dsp_pc - 2 - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2)), DSP);
1033 //CC only!
1034 #ifdef DSP_DEBUG_CC
1035 SET32(ram2, regs2[31] - 0xF1B000, dsp_pc - 2 - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2)));
1036 #endif
1037 //!!!!!!!!
1038
1039         // movei  #service_address,r30  ; pointer to ISR entry 
1040         // jump  (r30)                                  ; jump to ISR 
1041         // nop
1042         dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
1043 //CC only!
1044 #ifdef DSP_DEBUG_CC
1045 ctrl2[0] = regs2[30] = dsp_pc;
1046 #endif
1047 //!!!!!!!!
1048         FlushDSPPipeline();
1049 }
1050
1051 //
1052 // Non-pipelined version...
1053 //
1054 void DSPHandleIRQsNP(void)
1055 {
1056 //CC only!
1057 #ifdef DSP_DEBUG_CC
1058                 memcpy(dsp_ram_8, ram1, 0x2000);
1059                 memcpy(dsp_reg_bank_0, regs1, 32 * 4);
1060                 memcpy(dsp_reg_bank_1, &regs1[32], 32 * 4);
1061                 dsp_pc                                  = ctrl1[0];
1062                 dsp_acc                                 = ctrl1[1];
1063                 dsp_remain                              = ctrl1[2];
1064                 dsp_modulo                              = ctrl1[3];
1065                 dsp_flags                               = ctrl1[4];
1066                 dsp_matrix_control              = ctrl1[5];
1067                 dsp_pointer_to_matrix   = ctrl1[6];
1068                 dsp_data_organization   = ctrl1[7];
1069                 dsp_control                             = ctrl1[8];
1070                 dsp_div_control                 = ctrl1[9];
1071                 IMASKCleared                    = ctrl1[10];
1072                 dsp_flag_z                              = ctrl1[11];
1073                 dsp_flag_n                              = ctrl1[12];
1074                 dsp_flag_c                              = ctrl1[13];
1075 DSPUpdateRegisterBanks();
1076 #endif
1077 //!!!!!!!!
1078         if (dsp_flags & IMASK)                                                  // Bail if we're already inside an interrupt
1079                 return;
1080
1081         // Get the active interrupt bits (latches) & interrupt mask (enables)
1082         uint32 bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
1083                 mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
1084
1085 //      WriteLog("dsp: bits=%.2x mask=%.2x\n",bits,mask);
1086         bits &= mask;
1087
1088         if (!bits)                                                                              // Bail if nothing is enabled
1089                 return;
1090
1091         int which = 0;                                                                  // Determine which interrupt 
1092         if (bits & 0x01)
1093                 which = 0;
1094         if (bits & 0x02)
1095                 which = 1;
1096         if (bits & 0x04)
1097                 which = 2;
1098         if (bits & 0x08)
1099                 which = 3;
1100         if (bits & 0x10)
1101                 which = 4;
1102         if (bits & 0x20)
1103                 which = 5;
1104
1105 #ifdef DSP_DEBUG_IRQ
1106         WriteLog("DSP: Generating interrupt #%i...", which);
1107 #endif
1108
1109         dsp_flags |= IMASK;
1110 //CC only!
1111 #ifdef DSP_DEBUG_CC
1112 ctrl1[4] = dsp_flags;
1113 #endif
1114 //!!!!!!!!
1115         DSPUpdateRegisterBanks();
1116 #ifdef DSP_DEBUG_IRQ
1117         WriteLog(" [PC will return to %08X, R31 = %08X]\n", dsp_pc, dsp_reg[31]);
1118 #endif
1119
1120         // subqt  #4,r31                ; pre-decrement stack pointer 
1121         // move   pc,r30                ; address of interrupted code 
1122         // store  r30,(r31)     ; store return address
1123         dsp_reg[31] -= 4;
1124 //CC only!
1125 #ifdef DSP_DEBUG_CC
1126 regs1[31] -= 4;
1127 #endif
1128 //!!!!!!!!
1129         DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
1130 //CC only!
1131 #ifdef DSP_DEBUG_CC
1132 SET32(ram1, regs1[31] - 0xF1B000, dsp_pc - 2);
1133 #endif
1134 //!!!!!!!!
1135
1136         // movei  #service_address,r30  ; pointer to ISR entry 
1137         // jump  (r30)                                  ; jump to ISR 
1138         // nop
1139         dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
1140 //CC only!
1141 #ifdef DSP_DEBUG_CC
1142 ctrl1[0] = regs1[30] = dsp_pc;
1143 #endif
1144 //!!!!!!!!
1145 }
1146
1147 //
1148 // Set the specified DSP IRQ line to a given state
1149 //
1150 void DSPSetIRQLine(int irqline, int state)
1151 {
1152 //NOTE: This doesn't take INT_LAT5 into account. !!! FIX !!!
1153         uint32 mask = INT_LAT0 << irqline;
1154         dsp_control &= ~mask;                                                   // Clear the latch bit
1155 //CC only!
1156 #ifdef DSP_DEBUG_CC
1157 ctrl1[8] = ctrl2[8] = dsp_control;
1158 #endif
1159 //!!!!!!!!
1160
1161         if (state)
1162         {
1163                 dsp_control |= mask;                                            // Set the latch bit
1164                 DSPHandleIRQs();
1165 //CC only!
1166 #ifdef DSP_DEBUG_CC
1167 ctrl1[8] = ctrl2[8] = dsp_control;
1168 DSPHandleIRQsNP();
1169 #endif
1170 //!!!!!!!!
1171         }
1172 }
1173
1174 void DSPInit(void)
1175 {
1176         memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
1177         memory_malloc_secure((void **)&dsp_reg_bank_0, 32 * sizeof(int32), "DSP bank 0 regs");
1178         memory_malloc_secure((void **)&dsp_reg_bank_1, 32 * sizeof(int32), "DSP bank 1 regs");
1179
1180         dsp_build_branch_condition_table();
1181         DSPReset();
1182 }
1183
1184 void DSPReset(void)
1185 {
1186         dsp_pc                            = 0x00F1B000;
1187         dsp_acc                           = 0x00000000;
1188         dsp_remain                        = 0x00000000;
1189         dsp_modulo                        = 0xFFFFFFFF;
1190         dsp_flags                         = 0x00040000;
1191         dsp_matrix_control    = 0x00000000;
1192         dsp_pointer_to_matrix = 0x00000000;
1193         dsp_data_organization = 0xFFFFFFFF;
1194         dsp_control                       = 0x00002000;                         // Report DSP version 2
1195         dsp_div_control           = 0x00000000;
1196         dsp_in_exec                       = 0;
1197
1198         dsp_reg = dsp_reg_bank_0;
1199         dsp_alternate_reg = dsp_reg_bank_1;
1200
1201         for(int i=0; i<32; i++)
1202                 dsp_reg[i] = dsp_alternate_reg[i] = 0x00000000;
1203
1204         CLR_ZNC;
1205         IMASKCleared = false;
1206         FlushDSPPipeline();
1207         dsp_reset_stats();
1208         memset(dsp_ram_8, 0xFF, 0x2000);
1209 }
1210
1211 void DSPDumpDisassembly(void)
1212 {
1213         char buffer[512];
1214
1215         WriteLog("\n---[DSP code at 00F1B000]---------------------------\n");
1216         uint32 j = 0xF1B000;
1217         while (j <= 0xF1CFFF)
1218         {
1219                 uint32 oldj = j;
1220                 j += dasmjag(JAGUAR_DSP, buffer, j);
1221                 WriteLog("\t%08X: %s\n", oldj, buffer);
1222         }
1223 }
1224
1225 void DSPDumpRegisters(void)
1226 {
1227 //Shoud add modulus, etc to dump here...
1228         WriteLog("\n---[DSP flags: NCZ %d%d%d, DSP PC: %08X]------------\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_pc);
1229         WriteLog("\nRegisters bank 0\n");
1230         for(int j=0; j<8; j++)
1231         {
1232                 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1233                                                   (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
1234                                                   (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
1235                                                   (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
1236                                                   (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
1237         }
1238         WriteLog("Registers bank 1\n");
1239         for(int j=0; j<8; j++)
1240         {
1241                 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1242                                                   (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
1243                                                   (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
1244                                                   (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
1245                                                   (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
1246         }
1247 }
1248
1249 void DSPDone(void)
1250 {
1251         int i, j;
1252         WriteLog("DSP: Stopped at PC=%08X dsp_modulo=%08X (dsp %s running)\n", dsp_pc, dsp_modulo, (DSP_RUNNING ? "was" : "wasn't"));
1253         WriteLog("DSP: %sin interrupt handler\n", (dsp_flags & IMASK ? "" : "not "));
1254
1255         // get the active interrupt bits 
1256         int bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F);
1257         // get the interrupt mask 
1258         int mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
1259
1260         WriteLog("DSP: pending=%08X enabled=%08X\n", bits, mask);
1261         WriteLog("\nRegisters bank 0\n");
1262         for(int j=0; j<8; j++)
1263         {
1264                 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
1265                                                   (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
1266                                                   (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
1267                                                   (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
1268                                                   (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
1269         }
1270         WriteLog("\nRegisters bank 1\n");
1271         for (j=0; j<8; j++)
1272         {
1273                 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
1274                                                   (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
1275                                                   (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
1276                                                   (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
1277                                                   (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
1278
1279         }
1280
1281         static char buffer[512];
1282         j = DSP_WORK_RAM_BASE;
1283         while (j <= 0xF1BFFF)
1284         {
1285                 uint32 oldj = j;
1286                 j += dasmjag(JAGUAR_DSP, buffer, j);
1287                 WriteLog("\t%08X: %s\n", oldj, buffer);
1288         }//*/
1289
1290         WriteLog("DSP opcodes use:\n");
1291         for (i=0;i<64;i++)
1292         {
1293                 if (dsp_opcode_use[i])
1294                         WriteLog("\t%s %i\n", dsp_opcode_str[i], dsp_opcode_use[i]);
1295         }//*/
1296
1297         memory_free(dsp_ram_8);
1298 }
1299
1300
1301
1302 //
1303 // DSP comparison core...
1304 //
1305 #ifdef DSP_DEBUG_CC
1306 static uint16 lastExec;
1307 void DSPExecComp(int32 cycles)
1308 {
1309         while (cycles > 0 && DSP_RUNNING)
1310         {
1311                 // Load up vars for non-pipelined core
1312                 memcpy(dsp_ram_8, ram1, 0x2000);
1313                 memcpy(dsp_reg_bank_0, regs1, 32 * 4);
1314                 memcpy(dsp_reg_bank_1, &regs1[32], 32 * 4);
1315                 dsp_pc                                  = ctrl1[0];
1316                 dsp_acc                                 = ctrl1[1];
1317                 dsp_remain                              = ctrl1[2];
1318                 dsp_modulo                              = ctrl1[3];
1319                 dsp_flags                               = ctrl1[4];
1320                 dsp_matrix_control              = ctrl1[5];
1321                 dsp_pointer_to_matrix   = ctrl1[6];
1322                 dsp_data_organization   = ctrl1[7];
1323                 dsp_control                             = ctrl1[8];
1324                 dsp_div_control                 = ctrl1[9];
1325                 IMASKCleared                    = ctrl1[10];
1326                 dsp_flag_z                              = ctrl1[11];
1327                 dsp_flag_n                              = ctrl1[12];
1328                 dsp_flag_c                              = ctrl1[13];
1329 DSPUpdateRegisterBanks();
1330
1331                 // Decrement cycles based on non-pipelined core...
1332                 uint16 instr1 = DSPReadWord(dsp_pc, DSP);
1333                 cycles -= dsp_opcode_cycles[instr1 >> 10];
1334
1335 //WriteLog("\tAbout to execute non-pipelined core on tick #%u (DSP_PC=%08X)...\n", (uint32)count, dsp_pc);
1336                 DSPExec(1);                                                                     // Do *one* instruction
1337
1338                 // Save vars
1339                 memcpy(ram1, dsp_ram_8, 0x2000);
1340                 memcpy(regs1, dsp_reg_bank_0, 32 * 4);
1341                 memcpy(&regs1[32], dsp_reg_bank_1, 32 * 4);
1342                 ctrl1[0]  = dsp_pc;
1343                 ctrl1[1]  = dsp_acc;
1344                 ctrl1[2]  = dsp_remain;
1345                 ctrl1[3]  = dsp_modulo;
1346                 ctrl1[4]  = dsp_flags;
1347                 ctrl1[5]  = dsp_matrix_control;
1348                 ctrl1[6]  = dsp_pointer_to_matrix;
1349                 ctrl1[7]  = dsp_data_organization;
1350                 ctrl1[8]  = dsp_control;
1351                 ctrl1[9]  = dsp_div_control;
1352                 ctrl1[10] = IMASKCleared;
1353                 ctrl1[11] = dsp_flag_z;
1354                 ctrl1[12] = dsp_flag_n;
1355                 ctrl1[13] = dsp_flag_c;
1356
1357                 // Load up vars for pipelined core
1358                 memcpy(dsp_ram_8, ram2, 0x2000);
1359                 memcpy(dsp_reg_bank_0, regs2, 32 * 4);
1360                 memcpy(dsp_reg_bank_1, &regs2[32], 32 * 4);
1361                 dsp_pc                                  = ctrl2[0];
1362                 dsp_acc                                 = ctrl2[1];
1363                 dsp_remain                              = ctrl2[2];
1364                 dsp_modulo                              = ctrl2[3];
1365                 dsp_flags                               = ctrl2[4];
1366                 dsp_matrix_control              = ctrl2[5];
1367                 dsp_pointer_to_matrix   = ctrl2[6];
1368                 dsp_data_organization   = ctrl2[7];
1369                 dsp_control                             = ctrl2[8];
1370                 dsp_div_control                 = ctrl2[9];
1371                 IMASKCleared                    = ctrl2[10];
1372                 dsp_flag_z                              = ctrl2[11];
1373                 dsp_flag_n                              = ctrl2[12];
1374                 dsp_flag_c                              = ctrl2[13];
1375 DSPUpdateRegisterBanks();
1376
1377 //WriteLog("\tAbout to execute pipelined core on tick #%u (DSP_PC=%08X)...\n", (uint32)count, dsp_pc);
1378                 DSPExecP2(1);                                                           // Do *one* instruction
1379
1380                 // Save vars
1381                 memcpy(ram2, dsp_ram_8, 0x2000);
1382                 memcpy(regs2, dsp_reg_bank_0, 32 * 4);
1383                 memcpy(&regs2[32], dsp_reg_bank_1, 32 * 4);
1384                 ctrl2[0]  = dsp_pc;
1385                 ctrl2[1]  = dsp_acc;
1386                 ctrl2[2]  = dsp_remain;
1387                 ctrl2[3]  = dsp_modulo;
1388                 ctrl2[4]  = dsp_flags;
1389                 ctrl2[5]  = dsp_matrix_control;
1390                 ctrl2[6]  = dsp_pointer_to_matrix;
1391                 ctrl2[7]  = dsp_data_organization;
1392                 ctrl2[8]  = dsp_control;
1393                 ctrl2[9]  = dsp_div_control;
1394                 ctrl2[10] = IMASKCleared;
1395                 ctrl2[11] = dsp_flag_z;
1396                 ctrl2[12] = dsp_flag_n;
1397                 ctrl2[13] = dsp_flag_c;
1398
1399                 if (instr1 != lastExec)
1400                 {
1401 //                      WriteLog("\nCores diverged at instruction tick #%u!\nAttemping to synchronize...\n\n", count);
1402
1403 //                      uint32 ppc = ctrl2[0] - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2)) - (pipeline[plPtrWrite].opcode == 38 ? 6 : (pipeline[plPtrWrite].opcode == PIPELINE_STALL ? 0 : 2));
1404 //WriteLog("[DSP_PC1=%08X, DSP_PC2=%08X]\n", ctrl1[0], ppc);
1405 //                      if (ctrl1[0] < ppc)                                             // P ran ahead of NP
1406 //How to test this crap???
1407 //                      if (1)
1408                         {
1409                 DSPExecP2(1);                                                           // Do one more instruction
1410
1411                 // Save vars
1412                 memcpy(ram2, dsp_ram_8, 0x2000);
1413                 memcpy(regs2, dsp_reg_bank_0, 32 * 4);
1414                 memcpy(&regs2[32], dsp_reg_bank_1, 32 * 4);
1415                 ctrl2[0]  = dsp_pc;
1416                 ctrl2[1]  = dsp_acc;
1417                 ctrl2[2]  = dsp_remain;
1418                 ctrl2[3]  = dsp_modulo;
1419                 ctrl2[4]  = dsp_flags;
1420                 ctrl2[5]  = dsp_matrix_control;
1421                 ctrl2[6]  = dsp_pointer_to_matrix;
1422                 ctrl2[7]  = dsp_data_organization;
1423                 ctrl2[8]  = dsp_control;
1424                 ctrl2[9]  = dsp_div_control;
1425                 ctrl2[10] = IMASKCleared;
1426                 ctrl2[11] = dsp_flag_z;
1427                 ctrl2[12] = dsp_flag_n;
1428                 ctrl2[13] = dsp_flag_c;
1429                         }
1430 //                      else                                                                    // NP ran ahead of P
1431                 if (instr1 != lastExec)                                         // Must be the other way...
1432
1433                         {
1434                 // Load up vars for non-pipelined core
1435                 memcpy(dsp_ram_8, ram1, 0x2000);
1436                 memcpy(dsp_reg_bank_0, regs1, 32 * 4);
1437                 memcpy(dsp_reg_bank_1, &regs1[32], 32 * 4);
1438                 dsp_pc                                  = ctrl1[0];
1439                 dsp_acc                                 = ctrl1[1];
1440                 dsp_remain                              = ctrl1[2];
1441                 dsp_modulo                              = ctrl1[3];
1442                 dsp_flags                               = ctrl1[4];
1443                 dsp_matrix_control              = ctrl1[5];
1444                 dsp_pointer_to_matrix   = ctrl1[6];
1445                 dsp_data_organization   = ctrl1[7];
1446                 dsp_control                             = ctrl1[8];
1447                 dsp_div_control                 = ctrl1[9];
1448                 IMASKCleared                    = ctrl1[10];
1449                 dsp_flag_z                              = ctrl1[11];
1450                 dsp_flag_n                              = ctrl1[12];
1451                 dsp_flag_c                              = ctrl1[13];
1452 DSPUpdateRegisterBanks();
1453
1454 for(int k=0; k<2; k++)
1455 {
1456                 // Decrement cycles based on non-pipelined core...
1457                 instr1 = DSPReadWord(dsp_pc, DSP);
1458                 cycles -= dsp_opcode_cycles[instr1 >> 10];
1459
1460 //WriteLog("\tAbout to execute non-pipelined core on tick #%u (DSP_PC=%08X)...\n", (uint32)count, dsp_pc);
1461                 DSPExec(1);                                                                     // Do *one* instruction
1462 }
1463
1464                 // Save vars
1465                 memcpy(ram1, dsp_ram_8, 0x2000);
1466                 memcpy(regs1, dsp_reg_bank_0, 32 * 4);
1467                 memcpy(&regs1[32], dsp_reg_bank_1, 32 * 4);
1468                 ctrl1[0]  = dsp_pc;
1469                 ctrl1[1]  = dsp_acc;
1470                 ctrl1[2]  = dsp_remain;
1471                 ctrl1[3]  = dsp_modulo;
1472                 ctrl1[4]  = dsp_flags;
1473                 ctrl1[5]  = dsp_matrix_control;
1474                 ctrl1[6]  = dsp_pointer_to_matrix;
1475                 ctrl1[7]  = dsp_data_organization;
1476                 ctrl1[8]  = dsp_control;
1477                 ctrl1[9]  = dsp_div_control;
1478                 ctrl1[10] = IMASKCleared;
1479                 ctrl1[11] = dsp_flag_z;
1480                 ctrl1[12] = dsp_flag_n;
1481                 ctrl1[13] = dsp_flag_c;
1482                         }
1483                 }
1484
1485                 if (instr1 != lastExec)
1486                 {
1487                         WriteLog("\nCores diverged at instruction tick #%u!\nStopped!\n\n", count);
1488
1489                         WriteLog("Instruction for non-pipelined core: %04X\n", instr1);
1490                         WriteLog("Instruction for pipelined core: %04X\n", lastExec);
1491
1492                         log_done();
1493                         exit(1);
1494                 }
1495
1496                 count++;
1497         }
1498 }
1499 #endif
1500
1501
1502 //
1503 // DSP execution core
1504 //
1505 //static bool R20Set = false, tripwire = false;
1506 //static uint32 pcQueue[32], ptrPCQ = 0;
1507 void DSPExec(int32 cycles)
1508 {
1509 /*HACKS!!! ->   if (cycles != 1 && jaguar_mainRom_crc32 == 0xba74c3ed)
1510                 dsp_check_if_i2s_interrupt_needed();*/
1511
1512 #ifdef DSP_SINGLE_STEPPING
1513         if (dsp_control & 0x18)
1514         {
1515                 cycles = 1;
1516                 dsp_control &= ~0x10;
1517         }
1518 #endif
1519 //There is *no* good reason to do this here!
1520 //      DSPHandleIRQs();
1521         dsp_releaseTimeSlice_flag = 0;
1522         dsp_in_exec++;
1523
1524         while (cycles > 0 && DSP_RUNNING)
1525         {
1526                 if (IMASKCleared)                                               // If IMASK was cleared,
1527                 {
1528 #ifdef DSP_DEBUG_IRQ
1529                         WriteLog("DSP: Finished interrupt.\n");
1530 #endif
1531                         DSPHandleIRQsNP();                                      // See if any other interrupts are pending!
1532                         IMASKCleared = false;
1533                 }
1534
1535 /*if (badWrite)
1536 {
1537         WriteLog("\nDSP: Encountered bad write in Atari Synth module. PC=%08X, R15=%08X\n", dsp_pc, dsp_reg[15]);
1538         for(int i=0; i<80; i+=4)
1539                 WriteLog("     %08X: %08X\n", dsp_reg[15]+i, JaguarReadLong(dsp_reg[15]+i));
1540         WriteLog("\n");
1541 }//*/
1542 /*if (dsp_pc == 0xF1B55E)
1543 {
1544         WriteLog("DSP: At $F1B55E--R15 = %08X at %u ms%s...\n", dsp_reg[15], SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1545 }//*/
1546 /*if (dsp_pc == 0xF1B7D2)       // Start here???
1547         doDSPDis = true;
1548 pcQueue[ptrPCQ++] = dsp_pc;
1549 ptrPCQ %= 32;*/
1550                 uint16 opcode = DSPReadWord(dsp_pc, DSP);
1551                 uint32 index = opcode >> 10;
1552                 dsp_opcode_first_parameter = (opcode >> 5) & 0x1F;
1553                 dsp_opcode_second_parameter = opcode & 0x1F;
1554                 dsp_pc += 2;
1555                 dsp_opcode[index]();
1556                 dsp_opcode_use[index]++;
1557                 cycles -= dsp_opcode_cycles[index];
1558 /*if (dsp_reg_bank_0[20] == 0xF1A100 & !R20Set)
1559 {
1560         WriteLog("DSP: R20 set to $F1A100 at %u ms%s...\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1561         R20Set = true;
1562 }
1563 if (dsp_reg_bank_0[20] != 0xF1A100 && R20Set)
1564 {
1565         WriteLog("DSP: R20 corrupted at %u ms from starting%s!\nAborting!\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1566         DSPDumpRegisters();
1567         DSPDumpDisassembly();
1568         exit(1);
1569 }
1570 if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFE) && !tripwire)
1571 {
1572         char buffer[512];
1573         WriteLog("DSP: Jumping outside of DSP RAM at %u ms. Register dump:\n", SDL_GetTicks());
1574         DSPDumpRegisters();
1575         tripwire = true;
1576         WriteLog("\nBacktrace:\n");
1577         for(int i=0; i<32; i++)
1578         {
1579                 dasmjag(JAGUAR_DSP, buffer, pcQueue[(ptrPCQ + i) % 32]);
1580                 WriteLog("\t%08X: %s\n", pcQueue[(ptrPCQ + i) % 32], buffer);
1581         }
1582         WriteLog("\n");
1583 }*/
1584         }
1585
1586         dsp_in_exec--;
1587 }
1588
1589 //
1590 // DSP opcode handlers
1591 //
1592
1593 // There is a problem here with interrupt handlers the JUMP and JR instructions that
1594 // can cause trouble because an interrupt can occur *before* the instruction following the
1595 // jump can execute... !!! FIX !!!
1596 static void dsp_opcode_jump(void)
1597 {
1598 #ifdef DSP_DIS_JUMP
1599 char * condition[32] =
1600 {       "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1601         "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1602         "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1603         "???", "???", "???", "F" };
1604         if (doDSPDis)
1605                 WriteLog("%06X: JUMP   %s, (R%02u) [NCZ:%u%u%u, R%02u=%08X] ", dsp_pc-2, condition[IMM_2], IMM_1, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM);
1606 #endif
1607         // normalize flags
1608 /*      dsp_flag_c=dsp_flag_c?1:0;
1609         dsp_flag_z=dsp_flag_z?1:0;
1610         dsp_flag_n=dsp_flag_n?1:0;*/
1611         // KLUDGE: Used by BRANCH_CONDITION
1612         uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1613
1614         if (BRANCH_CONDITION(IMM_2))
1615         {
1616 #ifdef DSP_DIS_JUMP
1617         if (doDSPDis)
1618                 WriteLog("Branched!\n");
1619 #endif
1620                 uint32 delayed_pc = RM;
1621                 DSPExec(1);
1622                 dsp_pc = delayed_pc;
1623         }
1624 #ifdef DSP_DIS_JUMP
1625         else
1626                 if (doDSPDis)
1627                         WriteLog("Branch NOT taken.\n");
1628 #endif
1629 }
1630
1631 static void dsp_opcode_jr(void)
1632 {
1633 #ifdef DSP_DIS_JR
1634 char * condition[32] =
1635 {       "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1636         "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1637         "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1638         "???", "???", "???", "F" };
1639         if (doDSPDis)
1640                 WriteLog("%06X: JR     %s, %06X [NCZ:%u%u%u] ", dsp_pc-2, condition[IMM_2], dsp_pc+((IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1) * 2), dsp_flag_n, dsp_flag_c, dsp_flag_z);
1641 #endif
1642         // normalize flags
1643 /*      dsp_flag_c=dsp_flag_c?1:0;
1644         dsp_flag_z=dsp_flag_z?1:0;
1645         dsp_flag_n=dsp_flag_n?1:0;*/
1646         // KLUDGE: Used by BRANCH_CONDITION
1647         uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1648
1649         if (BRANCH_CONDITION(IMM_2))
1650         {
1651 #ifdef DSP_DIS_JR
1652         if (doDSPDis)
1653                 WriteLog("Branched!\n");
1654 #endif
1655                 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1);             // Sign extend IMM_1
1656                 int32 delayed_pc = dsp_pc + (offset * 2);
1657                 DSPExec(1);
1658                 dsp_pc = delayed_pc;
1659         }
1660 #ifdef DSP_DIS_JR
1661         else
1662                 if (doDSPDis)
1663                         WriteLog("Branch NOT taken.\n");
1664 #endif
1665 }
1666
1667 static void dsp_opcode_add(void)
1668 {
1669 #ifdef DSP_DIS_ADD
1670         if (doDSPDis)
1671                 WriteLog("%06X: ADD    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1672 #endif
1673         UINT32 res = RN + RM;
1674         SET_ZNC_ADD(RN, RM, res);
1675         RN = res;
1676 #ifdef DSP_DIS_ADD
1677         if (doDSPDis)
1678                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1679 #endif
1680 }
1681
1682 static void dsp_opcode_addc(void)
1683 {
1684 #ifdef DSP_DIS_ADDC
1685         if (doDSPDis)
1686                 WriteLog("%06X: ADDC   R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1687 #endif
1688         UINT32 res = RN + RM + dsp_flag_c;
1689         UINT32 carry = dsp_flag_c;
1690 //      SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1691         SET_ZNC_ADD(RN + carry, RM, res);
1692 //      SET_ZNC_ADD(RN, RM + carry, res);
1693         RN = res;
1694 #ifdef DSP_DIS_ADDC
1695         if (doDSPDis)
1696                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1697 #endif
1698 }
1699
1700 static void dsp_opcode_addq(void)
1701 {
1702 #ifdef DSP_DIS_ADDQ
1703         if (doDSPDis)
1704                 WriteLog("%06X: ADDQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1705 #endif
1706         UINT32 r1 = dsp_convert_zero[IMM_1];
1707         UINT32 res = RN + r1;
1708         CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1709         RN = res;
1710 #ifdef DSP_DIS_ADDQ
1711         if (doDSPDis)
1712                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1713 #endif
1714 }
1715
1716 static void dsp_opcode_sub(void)
1717 {
1718 #ifdef DSP_DIS_SUB
1719         if (doDSPDis)
1720                 WriteLog("%06X: SUB    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1721 #endif
1722         UINT32 res = RN - RM;
1723         SET_ZNC_SUB(RN, RM, res);
1724         RN = res;
1725 #ifdef DSP_DIS_SUB
1726         if (doDSPDis)
1727                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1728 #endif
1729 }
1730
1731 static void dsp_opcode_subc(void)
1732 {
1733 #ifdef DSP_DIS_SUBC
1734         if (doDSPDis)
1735                 WriteLog("%06X: SUBC   R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1736 #endif
1737         UINT32 res = RN - RM - dsp_flag_c;
1738         UINT32 borrow = dsp_flag_c;
1739         SET_ZNC_SUB(RN - borrow, RM, res);
1740         RN = res;
1741 #ifdef DSP_DIS_SUBC
1742         if (doDSPDis)
1743                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1744 #endif
1745 }
1746
1747 static void dsp_opcode_subq(void)
1748 {
1749 #ifdef DSP_DIS_SUBQ
1750         if (doDSPDis)
1751                 WriteLog("%06X: SUBQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1752 #endif
1753         UINT32 r1 = dsp_convert_zero[IMM_1];
1754         UINT32 res = RN - r1;
1755         SET_ZNC_SUB(RN, r1, res);
1756         RN = res;
1757 #ifdef DSP_DIS_SUBQ
1758         if (doDSPDis)
1759                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1760 #endif
1761 }
1762
1763 static void dsp_opcode_cmp(void)
1764 {
1765 #ifdef DSP_DIS_CMP
1766         if (doDSPDis)
1767                 WriteLog("%06X: CMP    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1768 #endif
1769         UINT32 res = RN - RM;
1770         SET_ZNC_SUB(RN, RM, res);
1771 #ifdef DSP_DIS_CMP
1772         if (doDSPDis)
1773                 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1774 #endif
1775 }
1776
1777 static void dsp_opcode_cmpq(void)
1778 {
1779         static int32 sqtable[32] =
1780                 { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1 };
1781 #ifdef DSP_DIS_CMPQ
1782         if (doDSPDis)
1783                 WriteLog("%06X: CMPQ   #%d, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, sqtable[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1784 #endif
1785         UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1786         UINT32 res = RN - r1;
1787         SET_ZNC_SUB(RN, r1, res);
1788 #ifdef DSP_DIS_CMPQ
1789         if (doDSPDis)
1790                 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1791 #endif
1792 }
1793
1794 static void dsp_opcode_and(void)
1795 {
1796 #ifdef DSP_DIS_AND
1797         if (doDSPDis)
1798                 WriteLog("%06X: AND    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1799 #endif
1800         RN = RN & RM;
1801         SET_ZN(RN);
1802 #ifdef DSP_DIS_AND
1803         if (doDSPDis)
1804                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1805 #endif
1806 }
1807
1808 static void dsp_opcode_or(void)
1809 {
1810 #ifdef DSP_DIS_OR
1811         if (doDSPDis)
1812                 WriteLog("%06X: OR     R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1813 #endif
1814         RN = RN | RM;
1815         SET_ZN(RN);
1816 #ifdef DSP_DIS_OR
1817         if (doDSPDis)
1818                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1819 #endif
1820 }
1821
1822 static void dsp_opcode_xor(void)
1823 {
1824 #ifdef DSP_DIS_XOR
1825         if (doDSPDis)
1826                 WriteLog("%06X: XOR    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1827 #endif
1828         RN = RN ^ RM;
1829         SET_ZN(RN);
1830 #ifdef DSP_DIS_XOR
1831         if (doDSPDis)
1832                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1833 #endif
1834 }
1835
1836 static void dsp_opcode_not(void)
1837 {
1838 #ifdef DSP_DIS_NOT
1839         if (doDSPDis)
1840                 WriteLog("%06X: NOT    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1841 #endif
1842         RN = ~RN;
1843         SET_ZN(RN);
1844 #ifdef DSP_DIS_NOT
1845         if (doDSPDis)
1846                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1847 #endif
1848 }
1849
1850 static void dsp_opcode_move_pc(void)
1851 {
1852         RN = dsp_pc - 2;
1853 }
1854
1855 static void dsp_opcode_store_r14_indexed(void)
1856 {
1857 #ifdef DSP_DIS_STORE14I
1858         if (doDSPDis)
1859                 WriteLog("%06X: STORE  R%02u, (R14+$%02X) [NCZ:%u%u%u, R%02u=%08X, R14+$%02X=%08X]\n", dsp_pc-2, IMM_2, dsp_convert_zero[IMM_1] << 2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, dsp_convert_zero[IMM_1] << 2, dsp_reg[14]+(dsp_convert_zero[IMM_1] << 2));
1860 #endif
1861         DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1862 }
1863
1864 static void dsp_opcode_store_r15_indexed(void)
1865 {
1866 #ifdef DSP_DIS_STORE15I
1867         if (doDSPDis)
1868                 WriteLog("%06X: STORE  R%02u, (R15+$%02X) [NCZ:%u%u%u, R%02u=%08X, R15+$%02X=%08X]\n", dsp_pc-2, IMM_2, dsp_convert_zero[IMM_1] << 2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, dsp_convert_zero[IMM_1] << 2, dsp_reg[15]+(dsp_convert_zero[IMM_1] << 2));
1869 #endif
1870         DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1871 }
1872
1873 static void dsp_opcode_load_r14_ri(void)
1874 {
1875 #ifdef DSP_DIS_LOAD14R
1876         if (doDSPDis)
1877                 WriteLog("%06X: LOAD   (R14+R%02u), R%02u [NCZ:%u%u%u, R14+R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM+dsp_reg[14], IMM_2, RN);
1878 #endif
1879         RN = DSPReadLong(dsp_reg[14] + RM, DSP);
1880 #ifdef DSP_DIS_LOAD14R
1881         if (doDSPDis)
1882                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1883 #endif
1884 }
1885
1886 static void dsp_opcode_load_r15_ri(void)
1887 {
1888 #ifdef DSP_DIS_LOAD15R
1889         if (doDSPDis)
1890                 WriteLog("%06X: LOAD   (R15+R%02u), R%02u [NCZ:%u%u%u, R15+R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM+dsp_reg[15], IMM_2, RN);
1891 #endif
1892         RN = DSPReadLong(dsp_reg[15] + RM, DSP);
1893 #ifdef DSP_DIS_LOAD15R
1894         if (doDSPDis)
1895                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1896 #endif
1897 }
1898
1899 static void dsp_opcode_store_r14_ri(void)
1900 {
1901         DSPWriteLong(dsp_reg[14] + RM, RN, DSP);
1902 }
1903
1904 static void dsp_opcode_store_r15_ri(void)
1905 {
1906         DSPWriteLong(dsp_reg[15] + RM, RN, DSP);
1907 }
1908
1909 static void dsp_opcode_nop(void)
1910 {
1911 #ifdef DSP_DIS_NOP
1912         if (doDSPDis)
1913                 WriteLog("%06X: NOP    [NCZ:%u%u%u]\n", dsp_pc-2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
1914 #endif
1915 }
1916
1917 static void dsp_opcode_storeb(void)
1918 {
1919 #ifdef DSP_DIS_STOREB
1920         if (doDSPDis)
1921                 WriteLog("%06X: STOREB R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, IMM_2, IMM_1, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, IMM_1, RM);
1922 #endif
1923         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1924                 DSPWriteLong(RM, RN & 0xFF, DSP);
1925         else
1926                 JaguarWriteByte(RM, RN, DSP);
1927 }
1928
1929 static void dsp_opcode_storew(void)
1930 {
1931 #ifdef DSP_DIS_STOREW
1932         if (doDSPDis)
1933                 WriteLog("%06X: STOREW R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, IMM_2, IMM_1, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, IMM_1, RM);
1934 #endif
1935         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1936                 DSPWriteLong(RM, RN & 0xFFFF, DSP);
1937         else
1938                 JaguarWriteWord(RM, RN, DSP);
1939 }
1940
1941 static void dsp_opcode_store(void)
1942 {
1943 #ifdef DSP_DIS_STORE
1944         if (doDSPDis)
1945                 WriteLog("%06X: STORE  R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, IMM_2, IMM_1, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, IMM_1, RM);
1946 #endif
1947         DSPWriteLong(RM, RN, DSP);
1948 }
1949
1950 static void dsp_opcode_loadb(void)
1951 {
1952 #ifdef DSP_DIS_LOADB
1953         if (doDSPDis)
1954                 WriteLog("%06X: LOADB  (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1955 #endif
1956         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1957                 RN = DSPReadLong(RM, DSP) & 0xFF;
1958         else
1959                 RN = JaguarReadByte(RM, DSP);
1960 #ifdef DSP_DIS_LOADB
1961         if (doDSPDis)
1962                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1963 #endif
1964 }
1965
1966 static void dsp_opcode_loadw(void)
1967 {
1968 #ifdef DSP_DIS_LOADW
1969         if (doDSPDis)
1970                 WriteLog("%06X: LOADW  (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1971 #endif
1972         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1973                 RN = DSPReadLong(RM, DSP) & 0xFFFF;
1974         else
1975                 RN = JaguarReadWord(RM, DSP);
1976 #ifdef DSP_DIS_LOADW
1977         if (doDSPDis)
1978                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1979 #endif
1980 }
1981
1982 static void dsp_opcode_load(void)
1983 {
1984 #ifdef DSP_DIS_LOAD
1985         if (doDSPDis)
1986                 WriteLog("%06X: LOAD   (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1987 #endif
1988         RN = DSPReadLong(RM, DSP);
1989 #ifdef DSP_DIS_LOAD
1990         if (doDSPDis)
1991                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1992 #endif
1993 }
1994
1995 static void dsp_opcode_load_r14_indexed(void)
1996 {
1997 #ifdef DSP_DIS_LOAD14I
1998         if (doDSPDis)
1999                 WriteLog("%06X: LOAD   (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1] << 2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[IMM_1] << 2, dsp_reg[14]+(dsp_convert_zero[IMM_1] << 2), IMM_2, RN);
2000 #endif
2001         RN = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), DSP);
2002 #ifdef DSP_DIS_LOAD14I
2003         if (doDSPDis)
2004                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2005 #endif
2006 }
2007
2008 static void dsp_opcode_load_r15_indexed(void)
2009 {
2010 #ifdef DSP_DIS_LOAD15I
2011         if (doDSPDis)
2012                 WriteLog("%06X: LOAD   (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1] << 2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[IMM_1] << 2, dsp_reg[15]+(dsp_convert_zero[IMM_1] << 2), IMM_2, RN);
2013 #endif
2014         RN = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), DSP);
2015 #ifdef DSP_DIS_LOAD15I
2016         if (doDSPDis)
2017                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2018 #endif
2019 }
2020
2021 static void dsp_opcode_movei(void)
2022 {
2023 #ifdef DSP_DIS_MOVEI
2024         if (doDSPDis)
2025                 WriteLog("%06X: MOVEI  #$%08X, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, (uint32)DSPReadWord(dsp_pc) | ((uint32)DSPReadWord(dsp_pc + 2) << 16), IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2026 #endif
2027         // This instruction is followed by 32-bit value in LSW / MSW format...
2028         RN = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
2029         dsp_pc += 4;
2030 #ifdef DSP_DIS_MOVEI
2031         if (doDSPDis)
2032                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2033 #endif
2034 }
2035
2036 static void dsp_opcode_moveta(void)
2037 {
2038 #ifdef DSP_DIS_MOVETA
2039         if (doDSPDis)
2040                 WriteLog("%06X: MOVETA R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, ALTERNATE_RN);
2041 #endif
2042         ALTERNATE_RN = RM;
2043 #ifdef DSP_DIS_MOVETA
2044         if (doDSPDis)
2045                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, ALTERNATE_RN);
2046 #endif
2047 }
2048
2049 static void dsp_opcode_movefa(void)
2050 {
2051 #ifdef DSP_DIS_MOVEFA
2052         if (doDSPDis)
2053                 WriteLog("%06X: MOVEFA R%02u, R%02u [NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, ALTERNATE_RM, IMM_2, RN);
2054 #endif
2055         RN = ALTERNATE_RM;
2056 #ifdef DSP_DIS_MOVEFA
2057         if (doDSPDis)
2058                 WriteLog("[NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, ALTERNATE_RM, IMM_2, RN);
2059 #endif
2060 }
2061
2062 static void dsp_opcode_move(void)
2063 {
2064 #ifdef DSP_DIS_MOVE
2065         if (doDSPDis)
2066                 WriteLog("%06X: MOVE   R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
2067 #endif
2068         RN = RM;
2069 #ifdef DSP_DIS_MOVE
2070         if (doDSPDis)
2071                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
2072 #endif
2073 }
2074
2075 static void dsp_opcode_moveq(void)
2076 {
2077 #ifdef DSP_DIS_MOVEQ
2078         if (doDSPDis)
2079                 WriteLog("%06X: MOVEQ  #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2080 #endif
2081         RN = IMM_1;
2082 #ifdef DSP_DIS_MOVEQ
2083         if (doDSPDis)
2084                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2085 #endif
2086 }
2087
2088 static void dsp_opcode_resmac(void)
2089 {
2090 #ifdef DSP_DIS_RESMAC
2091         if (doDSPDis)
2092                 WriteLog("%06X: RESMAC R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_ACC=%02X%08X] -> ", dsp_pc-2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
2093 #endif
2094         RN = (uint32)dsp_acc;
2095 #ifdef DSP_DIS_RESMAC
2096         if (doDSPDis)
2097                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2098 #endif
2099 }
2100
2101 static void dsp_opcode_imult(void)
2102 {
2103 #ifdef DSP_DIS_IMULT
2104         if (doDSPDis)
2105                 WriteLog("%06X: IMULT  R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
2106 #endif
2107         RN = (int16)RN * (int16)RM;
2108         SET_ZN(RN);
2109 #ifdef DSP_DIS_IMULT
2110         if (doDSPDis)
2111                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
2112 #endif
2113 }
2114
2115 static void dsp_opcode_mult(void)
2116 {
2117 #ifdef DSP_DIS_MULT
2118         if (doDSPDis)
2119                 WriteLog("%06X: MULT   R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
2120 #endif
2121         RN = (uint16)RM * (uint16)RN;
2122         SET_ZN(RN);
2123 #ifdef DSP_DIS_MULT
2124         if (doDSPDis)
2125                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
2126 #endif
2127 }
2128
2129 static void dsp_opcode_bclr(void)
2130 {
2131 #ifdef DSP_DIS_BCLR
2132         if (doDSPDis)
2133                 WriteLog("%06X: BCLR   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2134 #endif
2135         UINT32 res = RN & ~(1 << IMM_1);
2136         RN = res;
2137         SET_ZN(res);
2138 #ifdef DSP_DIS_BCLR
2139         if (doDSPDis)
2140                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2141 #endif
2142 }
2143
2144 static void dsp_opcode_btst(void)
2145 {
2146 #ifdef DSP_DIS_BTST
2147         if (doDSPDis)
2148                 WriteLog("%06X: BTST   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2149 #endif
2150         dsp_flag_z = (~RN >> IMM_1) & 1;
2151 #ifdef DSP_DIS_BTST
2152         if (doDSPDis)
2153                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2154 #endif
2155 }
2156
2157 static void dsp_opcode_bset(void)
2158 {
2159 #ifdef DSP_DIS_BSET
2160         if (doDSPDis)
2161                 WriteLog("%06X: BSET   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2162 #endif
2163         UINT32 res = RN | (1 << IMM_1);
2164         RN = res;
2165         SET_ZN(res);
2166 #ifdef DSP_DIS_BSET
2167         if (doDSPDis)
2168                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2169 #endif
2170 }
2171
2172 static void dsp_opcode_subqt(void)
2173 {
2174 #ifdef DSP_DIS_SUBQT
2175         if (doDSPDis)
2176                 WriteLog("%06X: SUBQT  #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2177 #endif
2178         RN -= dsp_convert_zero[IMM_1];
2179 #ifdef DSP_DIS_SUBQT
2180         if (doDSPDis)
2181                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2182 #endif
2183 }
2184
2185 static void dsp_opcode_addqt(void)
2186 {
2187 #ifdef DSP_DIS_ADDQT
2188         if (doDSPDis)
2189                 WriteLog("%06X: ADDQT  #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2190 #endif
2191         RN += dsp_convert_zero[IMM_1];
2192 #ifdef DSP_DIS_ADDQT
2193         if (doDSPDis)
2194                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2195 #endif
2196 }
2197
2198 static void dsp_opcode_imacn(void)
2199 {
2200 #ifdef DSP_DIS_IMACN
2201         if (doDSPDis)
2202                 WriteLog("%06X: IMACN  R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
2203 #endif
2204         int32 res = (int16)RM * (int16)RN;
2205         dsp_acc += (int64)res;
2206 //Should we AND the result to fit into 40 bits here???
2207 #ifdef DSP_DIS_IMACN
2208         if (doDSPDis)
2209                 WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
2210 #endif
2211
2212
2213 static void dsp_opcode_mtoi(void)
2214 {
2215         RN = (((INT32)RM >> 8) & 0xFF800000) | (RM & 0x007FFFFF);
2216         SET_ZN(RN);
2217 }
2218
2219 static void dsp_opcode_normi(void)
2220 {
2221         uint32 _Rm = RM;
2222         uint32 res = 0;
2223
2224         if (_Rm)
2225         {
2226                 while ((_Rm & 0xffc00000) == 0)
2227                 {
2228                         _Rm <<= 1;
2229                         res--;
2230                 }
2231                 while ((_Rm & 0xff800000) != 0)
2232                 {
2233                         _Rm >>= 1;
2234                         res++;
2235                 }
2236         }
2237         RN = res;
2238         SET_ZN(RN);
2239 }
2240
2241 static void dsp_opcode_mmult(void)
2242 {
2243         int count       = dsp_matrix_control&0x0f;
2244         uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
2245         int64 accum = 0;
2246         uint32 res;
2247
2248         if (!(dsp_matrix_control & 0x10))
2249         {
2250                 for (int i = 0; i < count; i++)
2251                 { 
2252                         int16 a;
2253                         if (i&0x01)
2254                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
2255                         else
2256                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
2257                         int16 b=((int16)DSPReadWord(addr + 2, DSP));
2258                         accum += a*b;
2259                         addr += 4;
2260                 }
2261         }
2262         else
2263         {
2264                 for (int i = 0; i < count; i++)
2265                 {
2266                         int16 a;
2267                         if (i&0x01)
2268                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
2269                         else
2270                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
2271                         int16 b=((int16)DSPReadWord(addr + 2, DSP));
2272                         accum += a*b;
2273                         addr += 4 * count;
2274                 }
2275         }
2276         RN = res = (int32)accum;
2277         // carry flag to do
2278 //NOTE: The flags are set based upon the last add/multiply done...
2279         SET_ZN(RN);
2280 }
2281
2282 static void dsp_opcode_abs(void)
2283 {
2284         uint32 _Rn = RN;
2285         uint32 res;
2286         
2287         if (_Rn == 0x80000000)
2288                 dsp_flag_n = 1;
2289         else
2290         {
2291                 dsp_flag_c = ((_Rn & 0x80000000) >> 31);
2292                 res = RN = (_Rn & 0x80000000 ? -_Rn : _Rn);
2293                 CLR_ZN; SET_Z(res);
2294         }
2295 }
2296
2297 static void dsp_opcode_div(void)
2298 {
2299         uint32 _Rm=RM;
2300         uint32 _Rn=RN;
2301
2302         if (_Rm)
2303         {
2304                 if (dsp_div_control & 1)
2305                 {
2306                         dsp_remain = (((uint64)_Rn) << 16) % _Rm;
2307                         if (dsp_remain&0x80000000)
2308                                 dsp_remain-=_Rm;
2309                         RN = (((uint64)_Rn) << 16) / _Rm;
2310                 }
2311                 else
2312                 {
2313                         dsp_remain = _Rn % _Rm;
2314                         if (dsp_remain&0x80000000)
2315                                 dsp_remain-=_Rm;
2316                         RN/=_Rm;
2317                 }
2318         }
2319         else
2320                 RN=0xffffffff;
2321 }
2322
2323 static void dsp_opcode_imultn(void)
2324 {
2325 #ifdef DSP_DIS_IMULTN
2326         if (doDSPDis)
2327                 WriteLog("%06X: IMULTN R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
2328 #endif
2329         // This is OK, since this multiply won't overflow 32 bits...
2330         int32 res = (int32)((int16)RN * (int16)RM);
2331         dsp_acc = (int64)res;
2332         SET_ZN(res);
2333 #ifdef DSP_DIS_IMULTN
2334         if (doDSPDis)
2335                 WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
2336 #endif
2337 }
2338
2339 static void dsp_opcode_neg(void)
2340 {
2341 #ifdef DSP_DIS_NEG
2342         if (doDSPDis)
2343                 WriteLog("%06X: NEG    R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2344 #endif
2345         UINT32 res = -RN;
2346         SET_ZNC_SUB(0, RN, res);
2347         RN = res;
2348 #ifdef DSP_DIS_NEG
2349         if (doDSPDis)
2350                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2351 #endif
2352 }
2353
2354 static void dsp_opcode_shlq(void)
2355 {
2356 #ifdef DSP_DIS_SHLQ
2357         if (doDSPDis)
2358                 WriteLog("%06X: SHLQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, 32 - IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2359 #endif
2360         INT32 r1 = 32 - IMM_1;
2361         UINT32 res = RN << r1;
2362         SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
2363         RN = res;
2364 #ifdef DSP_DIS_SHLQ
2365         if (doDSPDis)
2366                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2367 #endif
2368 }
2369
2370 static void dsp_opcode_shrq(void)
2371 {
2372 #ifdef DSP_DIS_SHRQ
2373         if (doDSPDis)
2374                 WriteLog("%06X: SHRQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2375 #endif
2376         INT32 r1 = dsp_convert_zero[IMM_1];
2377         UINT32 res = RN >> r1;
2378         SET_ZN(res); dsp_flag_c = RN & 1;
2379         RN = res;
2380 #ifdef DSP_DIS_SHRQ
2381         if (doDSPDis)
2382                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2383 #endif
2384 }
2385
2386 static void dsp_opcode_ror(void)
2387 {
2388 #ifdef DSP_DIS_ROR
2389         if (doDSPDis)
2390                 WriteLog("%06X: ROR    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
2391 #endif
2392         UINT32 r1 = RM & 0x1F;
2393         UINT32 res = (RN >> r1) | (RN << (32 - r1));
2394         SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
2395         RN = res;
2396 #ifdef DSP_DIS_ROR
2397         if (doDSPDis)
2398                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
2399 #endif
2400 }
2401
2402 static void dsp_opcode_rorq(void)
2403 {
2404 #ifdef DSP_DIS_RORQ
2405         if (doDSPDis)
2406                 WriteLog("%06X: RORQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2407 #endif
2408         UINT32 r1 = dsp_convert_zero[IMM_1 & 0x1F];
2409         UINT32 r2 = RN;
2410         UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
2411         RN = res;
2412         SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
2413 #ifdef DSP_DIS_RORQ
2414         if (doDSPDis)
2415                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2416 #endif
2417 }
2418
2419 static void dsp_opcode_sha(void)
2420 {
2421         int32 sRm=(int32)RM;
2422         uint32 _Rn=RN;
2423
2424         if (sRm<0)
2425         {
2426                 uint32 shift=-sRm;
2427                 if (shift>=32) shift=32;
2428                 dsp_flag_c=(_Rn&0x80000000)>>31;
2429                 while (shift)
2430                 {
2431                         _Rn<<=1;
2432                         shift--;
2433                 }
2434         }
2435         else
2436         {
2437                 uint32 shift=sRm;
2438                 if (shift>=32) shift=32;
2439                 dsp_flag_c=_Rn&0x1;
2440                 while (shift)
2441                 {
2442                         _Rn=((int32)_Rn)>>1;
2443                         shift--;
2444                 }
2445         }
2446         RN = _Rn;
2447         SET_ZN(RN);
2448 }
2449
2450 static void dsp_opcode_sharq(void)
2451 {
2452 #ifdef DSP_DIS_SHARQ
2453         if (doDSPDis)
2454                 WriteLog("%06X: SHARQ  #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2455 #endif
2456         UINT32 res = (INT32)RN >> dsp_convert_zero[IMM_1];
2457         SET_ZN(res); dsp_flag_c = RN & 0x01;
2458         RN = res;
2459 #ifdef DSP_DIS_SHARQ
2460         if (doDSPDis)
2461                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2462 #endif
2463 }
2464
2465 static void dsp_opcode_sh(void)
2466 {
2467         int32 sRm=(int32)RM;
2468         uint32 _Rn=RN;
2469
2470         if (sRm<0)
2471         {
2472                 uint32 shift=(-sRm);
2473                 if (shift>=32) shift=32;
2474                 dsp_flag_c=(_Rn&0x80000000)>>31;
2475                 while (shift)
2476                 {
2477                         _Rn<<=1;
2478                         shift--;
2479                 }
2480         }
2481         else
2482         {
2483                 uint32 shift=sRm;
2484                 if (shift>=32) shift=32;
2485                 dsp_flag_c=_Rn&0x1;
2486                 while (shift)
2487                 {
2488                         _Rn>>=1;
2489                         shift--;
2490                 }
2491         }
2492         RN = _Rn;
2493         SET_ZN(RN);
2494 }
2495
2496 void dsp_opcode_addqmod(void)
2497 {
2498 #ifdef DSP_DIS_ADDQMOD
2499         if (doDSPDis)
2500                 WriteLog("%06X: ADDQMOD #%u, R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_MOD=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, dsp_modulo);
2501 #endif
2502         UINT32 r1 = dsp_convert_zero[IMM_1];
2503         UINT32 r2 = RN;
2504         UINT32 res = r2 + r1;
2505         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2506         RN = res;
2507         SET_ZNC_ADD(r2, r1, res);
2508 #ifdef DSP_DIS_ADDQMOD
2509         if (doDSPDis)
2510                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2511 #endif
2512 }
2513
2514 void dsp_opcode_subqmod(void)   
2515 {
2516         UINT32 r1 = dsp_convert_zero[IMM_1];
2517         UINT32 r2 = RN;
2518         UINT32 res = r2 - r1;
2519         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2520         RN = res;
2521         
2522         SET_ZNC_SUB(r2, r1, res);
2523 }
2524
2525 void dsp_opcode_mirror(void)    
2526 {
2527         UINT32 r1 = RN;
2528         RN = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
2529         SET_ZN(RN);
2530 }
2531
2532 void dsp_opcode_sat32s(void)            
2533 {
2534         INT32 r2 = (UINT32)RN;
2535         INT32 temp = dsp_acc >> 32;
2536         UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
2537         RN = res;
2538         SET_ZN(res);
2539 }
2540
2541 void dsp_opcode_sat16s(void)            
2542 {
2543         INT32 r2 = RN;
2544         UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
2545         RN = res;
2546         SET_ZN(res);
2547 }
2548
2549 //
2550 // New pipelined DSP core
2551 //
2552
2553 static void DSP_abs(void);
2554 static void DSP_add(void);
2555 static void DSP_addc(void);
2556 static void DSP_addq(void);
2557 static void DSP_addqmod(void);  
2558 static void DSP_addqt(void);
2559 static void DSP_and(void);
2560 static void DSP_bclr(void);
2561 static void DSP_bset(void);
2562 static void DSP_btst(void);
2563 static void DSP_cmp(void);
2564 static void DSP_cmpq(void);
2565 static void DSP_div(void);
2566 static void DSP_imacn(void);
2567 static void DSP_imult(void);
2568 static void DSP_imultn(void);
2569 static void DSP_illegal(void);
2570 static void DSP_jr(void);
2571 static void DSP_jump(void);
2572 static void DSP_load(void);
2573 static void DSP_loadb(void);
2574 static void DSP_loadw(void);
2575 static void DSP_load_r14_i(void);
2576 static void DSP_load_r14_r(void);
2577 static void DSP_load_r15_i(void);
2578 static void DSP_load_r15_r(void);
2579 static void DSP_mirror(void);   
2580 static void DSP_mmult(void);
2581 static void DSP_move(void);
2582 static void DSP_movefa(void);
2583 static void DSP_movei(void);
2584 static void DSP_movepc(void);
2585 static void DSP_moveq(void);
2586 static void DSP_moveta(void);
2587 static void DSP_mtoi(void);
2588 static void DSP_mult(void);
2589 static void DSP_neg(void);
2590 static void DSP_nop(void);
2591 static void DSP_normi(void);
2592 static void DSP_not(void);
2593 static void DSP_or(void);
2594 static void DSP_resmac(void);
2595 static void DSP_ror(void);
2596 static void DSP_rorq(void);
2597 static void DSP_sat16s(void);   
2598 static void DSP_sat32s(void);   
2599 static void DSP_sh(void);
2600 static void DSP_sha(void);
2601 static void DSP_sharq(void);
2602 static void DSP_shlq(void);
2603 static void DSP_shrq(void);
2604 static void DSP_store(void);
2605 static void DSP_storeb(void);
2606 static void DSP_storew(void);
2607 static void DSP_store_r14_i(void);
2608 static void DSP_store_r14_r(void);
2609 static void DSP_store_r15_i(void);
2610 static void DSP_store_r15_r(void);
2611 static void DSP_sub(void);
2612 static void DSP_subc(void);
2613 static void DSP_subq(void);
2614 static void DSP_subqmod(void);  
2615 static void DSP_subqt(void);
2616 static void DSP_xor(void);
2617
2618 void (* DSPOpcode[64])() =
2619 {
2620         DSP_add,                        DSP_addc,                       DSP_addq,                       DSP_addqt,
2621         DSP_sub,                        DSP_subc,                       DSP_subq,                       DSP_subqt,
2622         DSP_neg,                        DSP_and,                        DSP_or,                         DSP_xor,
2623         DSP_not,                        DSP_btst,                       DSP_bset,                       DSP_bclr,
2624
2625         DSP_mult,                       DSP_imult,                      DSP_imultn,                     DSP_resmac,
2626         DSP_imacn,                      DSP_div,                        DSP_abs,                        DSP_sh,
2627         DSP_shlq,                       DSP_shrq,                       DSP_sha,                        DSP_sharq,
2628         DSP_ror,                        DSP_rorq,                       DSP_cmp,                        DSP_cmpq,
2629
2630         DSP_subqmod,            DSP_sat16s,                     DSP_move,                       DSP_moveq,
2631         DSP_moveta,                     DSP_movefa,                     DSP_movei,                      DSP_loadb,
2632         DSP_loadw,                      DSP_load,                       DSP_sat32s,                     DSP_load_r14_i,
2633         DSP_load_r15_i,         DSP_storeb,                     DSP_storew,                     DSP_store,
2634
2635         DSP_mirror,                     DSP_store_r14_i,        DSP_store_r15_i,        DSP_movepc,
2636         DSP_jump,                       DSP_jr,                         DSP_mmult,                      DSP_mtoi,
2637         DSP_normi,                      DSP_nop,                        DSP_load_r14_r,         DSP_load_r15_r,
2638         DSP_store_r14_r,        DSP_store_r15_r,        DSP_illegal,            DSP_addqmod
2639 };
2640
2641 bool readAffected[64][2] =
2642 {
2643         { true,  true}, { true,  true}, {false,  true}, {false,  true},
2644         { true,  true}, { true,  true}, {false,  true}, {false,  true},
2645         {false,  true}, { true,  true}, { true,  true}, { true,  true},
2646         {false,  true}, {false,  true}, {false,  true}, {false,  true},
2647
2648         { true,  true}, { true,  true}, { true,  true}, {false,  true},
2649         { true,  true}, { true,  true}, {false,  true}, { true,  true},
2650         {false,  true}, {false,  true}, { true,  true}, {false,  true},
2651         { true,  true}, {false,  true}, { true,  true}, {false,  true},
2652
2653         {false,  true}, {false,  true}, { true, false}, {false, false},
2654         { true, false}, {false, false}, {false, false}, { true, false},
2655         { true, false}, { true, false}, {false,  true}, { true, false},
2656         { true, false}, { true,  true}, { true,  true}, { true,  true},
2657
2658         {false,  true}, { true,  true}, { true,  true}, {false,  true},
2659         { true, false}, { true, false}, { true,  true}, { true, false},
2660         { true, false}, {false, false}, { true, false}, { true, false},
2661         { true,  true}, { true,  true}, {false, false}, {false,  true}
2662 };
2663
2664 void FlushDSPPipeline(void)
2665 {
2666         plPtrFetch = 3, plPtrRead = 2, plPtrExec = 1, plPtrWrite = 0;
2667
2668         for(int i=0; i<4; i++)
2669                 pipeline[i].opcode = PIPELINE_STALL;
2670
2671         for(int i=0; i<32; i++)
2672                 scoreboard[i] = false;
2673 }
2674
2675 //
2676 // New pipelined DSP execution core
2677 //
2678 /*void DSPExecP(int32 cycles)
2679 {
2680 //      bool inhibitFetch = false;
2681
2682         dsp_releaseTimeSlice_flag = 0;
2683         dsp_in_exec++;
2684
2685         while (cycles > 0 && DSP_RUNNING)
2686         {
2687 WriteLog("DSPExecP: Pipeline status...\n");
2688 WriteLog("\tF -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrFetch].opcode, pipeline[plPtrFetch].operand1, pipeline[plPtrFetch].operand2, pipeline[plPtrFetch].reg1, pipeline[plPtrFetch].reg2, pipeline[plPtrFetch].result, pipeline[plPtrFetch].writebackRegister);
2689 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister);
2690 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister);
2691 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister);
2692 WriteLog("  --> Scoreboard: ");
2693 for(int i=0; i<32; i++)
2694         WriteLog("%s ", scoreboard[i] ? "T" : "F");
2695 WriteLog("\n");
2696                 // Stage 1: Instruction fetch
2697 //              if (!inhibitFetch)
2698 //              {
2699                 pipeline[plPtrFetch].instruction = DSPReadWord(dsp_pc, DSP);
2700                 pipeline[plPtrFetch].opcode = pipeline[plPtrFetch].instruction >> 10;
2701                 pipeline[plPtrFetch].operand1 = (pipeline[plPtrFetch].instruction >> 5) & 0x1F;
2702                 pipeline[plPtrFetch].operand2 = pipeline[plPtrFetch].instruction & 0x1F;
2703                 if (pipeline[plPtrFetch].opcode == 38)
2704                         pipeline[plPtrFetch].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
2705                                 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
2706 //              }
2707 //              else
2708 //                      inhibitFetch = false;
2709 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrFetch].instruction, dsp_pc);
2710
2711 WriteLog("DSPExecP: Pipeline status (after stage 1)...\n");
2712 WriteLog("\tF -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrFetch].opcode, pipeline[plPtrFetch].operand1, pipeline[plPtrFetch].operand2, pipeline[plPtrFetch].reg1, pipeline[plPtrFetch].reg2, pipeline[plPtrFetch].result, pipeline[plPtrFetch].writebackRegister);
2713 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister);
2714 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister);
2715 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister);
2716                 // Stage 2: Read registers
2717 //Ok, stalls here depend on whether or not the instruction reads two registers or not
2718 //and *which* register (1 or 2) is the one being read... !!! FIX !!!
2719                 if (scoreboard[pipeline[plPtrRead].operand2])
2720                         && pipeline[plPtrRead].opcode != PIPELINE_STALL)
2721                         // We have a hit in the scoreboard, so we have to stall the pipeline...
2722 {
2723 //This is crappy, crappy CRAPPY! And it doesn't work! !!! FIX !!!
2724 //                      dsp_pc -= (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2725 WriteLog("  --> Stalling pipeline: scoreboard = %s\n", scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
2726                         pipeline[plPtrFetch] = pipeline[plPtrRead];
2727                         pipeline[plPtrRead].opcode = PIPELINE_STALL;
2728 }
2729                 else
2730                 {
2731                         pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
2732                         pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
2733                         pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2;   // Set it to RN
2734
2735                         if (pipeline[plPtrRead].opcode != PIPELINE_STALL)
2736                         // Shouldn't we be more selective with the register scoreboarding?
2737                         // Yes, we should. !!! FIX !!!
2738                         scoreboard[pipeline[plPtrRead].operand2] = true;
2739 //Advance PC here??? Yes.
2740 //                      dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2741 //This is a mangling of the pipeline stages, but what else to do???
2742                         dsp_pc += (pipeline[plPtrFetch].opcode == 38 ? 6 : 2);
2743                 }
2744
2745 WriteLog("DSPExecP: Pipeline status (after stage 2)...\n");
2746 WriteLog("\tF -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrFetch].opcode, pipeline[plPtrFetch].operand1, pipeline[plPtrFetch].operand2, pipeline[plPtrFetch].reg1, pipeline[plPtrFetch].reg2, pipeline[plPtrFetch].result, pipeline[plPtrFetch].writebackRegister);
2747 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister);
2748 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister);
2749 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister);
2750                 // Stage 3: Execute
2751                 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
2752                 {
2753 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
2754                         DSPOpcode[pipeline[plPtrExec].opcode]();
2755                         dsp_opcode_use[pipeline[plPtrExec].opcode]++;
2756                         cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
2757                 }
2758                 else
2759                         cycles--;
2760
2761 WriteLog("DSPExecP: Pipeline status (after stage 3)...\n");
2762 WriteLog("\tF -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrFetch].opcode, pipeline[plPtrFetch].operand1, pipeline[plPtrFetch].operand2, pipeline[plPtrFetch].reg1, pipeline[plPtrFetch].reg2, pipeline[plPtrFetch].result, pipeline[plPtrFetch].writebackRegister);
2763 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister);
2764 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister);
2765 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister);
2766                 // Stage 4: Write back register
2767                 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
2768                 {
2769                         if (pipeline[plPtrWrite].writebackRegister != 0xFF)
2770                                 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
2771
2772                         scoreboard[pipeline[plPtrWrite].operand1]
2773                                 = scoreboard[pipeline[plPtrWrite].operand2] = false;
2774                 }
2775
2776                 // Push instructions through the pipeline...
2777                 plPtrFetch = (++plPtrFetch) & 0x03;
2778                 plPtrRead = (++plPtrRead) & 0x03;
2779                 plPtrExec = (++plPtrExec) & 0x03;
2780                 plPtrWrite = (++plPtrWrite) & 0x03;
2781         }
2782
2783         dsp_in_exec--;
2784 }*/
2785
2786
2787 //Problems: JR and any other instruction that relies on DSP_PC is getting WRONG values!
2788 //!!! FIX !!!
2789 // Should be fixed now. Another problem is figuring how to do the sequence following
2790 // a branch followed with the JR & JUMP instructions...
2791 //
2792 // There are two conflicting problems:
2793
2794 /*
2795 F1B236: LOAD   (R31), R03 [NCZ:000, R31=00F1CFDC, R03=00F14000] -> [NCZ:000, R03=00F1B084]
2796 F1B238: BCLR   #3, R00 [NCZ:000, R00=00004039] -> [NCZ:000, R00=00004031]
2797 F1B23A: ADDQ   #2, R03 [NCZ:000, R03=00F1B084] -> [NCZ:000, R03=00F1B086]
2798 F1B23C: SUBQ   #1, R17 [NCZ:000, R17=00000040] -> [NCZ:000, R17=0000003F]
2799 F1B23E: MOVEI  #$00F1CFE0, R31 [NCZ:000, R31=00F1CFDC] -> [NCZ:000, R31=00F1CFE0]
2800 F1B244: JR     z, F1B254 [NCZ:000] Branch NOT taken.
2801 F1B246: BSET   #10, R00 [NCZ:000, R00=00004031] -> [NCZ:000, R00=00004431]
2802 F1B248: MOVEI  #$00F1A100, R01 [NCZ:000, R01=00F1A148] -> [NCZ:000, R01=00F1A100]
2803 F1B24E: STORE  R00, (R01) [NCZ:000, R00=00004431, R01=00F1A100]
2804 DSP: Writing 00004431 to DSP_FLAGS by DSP...
2805 DSP: Finished interrupt.
2806 ; Without pipeline effects, the value in R03 is erroneously read from bank 1 instead of
2807 ; bank 0 (where is was prepared)!
2808 F1B250: JUMP   T, (R03) [NCZ:001, R03=00000000] Branched!
2809 F1B252: NOP    [NCZ:001]
2810 */
2811
2812 // The other is when you see this at the end of an IRQ:
2813
2814 /*
2815 JUMP   T, (R29)         ; R29 = Previous stack + 2
2816 STORE  R28, (R30)       ; R28 = Modified flags register, R30 = $F1A100
2817
2818 ; Actually, this is OK if we do the atomic JUMP/JR operation correctly:
2819 ; 1) The STORE goes through the pipeline and is executed/written back
2820 ; 2) The pipeline is flushed
2821 ; 3) The DSP_PC is set to the new address
2822 ; 4) Execution resumes
2823
2824 JUMP   T, (R25)         ; Oops! Because of pipeline effects R25 has the value from
2825                                         ; bank 0 instead of the current bank 1 and so goes astray!
2826 */
2827
2828 //One other thing: Since these stages are supposed to happen simulaneously, try executing
2829 //them in reverse order to see if that reduces pipeline stalls from late writebacks...
2830
2831
2832 /*
2833 Small problem here: The return address when INT0 comes up is $F1B088, but when INT1
2834 follows it, the JUMP out of the previous interrupt is bypassed immediately--this is
2835 because the STORE instruction writes back on stage #2 of the pipeline instead of stage #3...
2836 If it were done properly, the STORE write back would occur *after* (well, technically,
2837 during) the execution of the the JUMP that follows it.
2838
2839 !!! FIX !!!
2840
2841 F1B08A: JR     z, F1B082 [NCZ:001] Branched!
2842 F1B08A: NOP    [NCZ:001]
2843 [STALL...]
2844 F1B080: MOVEI  #$00F1B178, R00 [NCZ:001, R00=00F1B178] -> [NCZ:001, R00=00F1B178]
2845 [STALL...]
2846 [STALL...]
2847 F1B086: LOAD   (R00), R01 [NCZ:001, R00=00F1B178, R01=00000000] -> [NCZ:001, R01=00000000]
2848 [STALL...]
2849 [STALL...]
2850 F1B088: OR     R01, R01 [NCZ:001, R01=00000000, R01=00000000] -> [NCZ:001, R01=00000000, R01=00000000]
2851 F1B08A: JR     z, F1B082 [NCZ:001] Branched!
2852 F1B08A: NOP    [NCZ:001]
2853 [STALL...]
2854 F1B080: MOVEI  #$00F1B178, R00 [NCZ:001, R00=00F1B178] -> [NCZ:001, R00=00F1B178]
2855 [STALL...]
2856 [STALL...]
2857 Write to DSP CTRL: 00002301  --> Starting to run at 00F1B088 by M68K...
2858 DSP: CPU -> DSP interrupt
2859 DSP: Generating interrupt #0... [PC will return to 00F1B088, R31 = 00F1CFE0]
2860 Write to DSP CTRL: 00000001  --> Starting to run at 00F1B000 by M68K...
2861 [STALL...]
2862 F1B000: MOVEI  #$00F1B0D4, R30 [NCZ:001, R30=00F1B000] -> [NCZ:001, R30=00F1B0D4]
2863 [STALL...]
2864 [STALL...]
2865 F1B006: JUMP   T, (R30) [NCZ:001, R30=00F1B0D4] Branched!
2866 F1B006: NOP    [NCZ:001]
2867 [STALL...]
2868 F1B0D4: MOVEI  #$00F1A100, R01 [NCZ:001, R01=00F1A100] -> [NCZ:001, R01=00F1A100]
2869 [STALL...]
2870 [STALL...]
2871 F1B0DA: LOAD   (R01), R00 [NCZ:001, R01=00F1A100, R00=00004431] -> [NCZ:001, R00=00004039]
2872 F1B0DC: MOVEI  #$00F1B0C8, R01 [NCZ:001, R01=00F1A100] -> [NCZ:001, R01=00F1B0C8]
2873 [STALL...]
2874 [STALL...]
2875 F1B0E2: LOAD   (R01), R02 [NCZ:001, R01=00F1B0C8, R02=00000000] -> [NCZ:001, R02=00000001]
2876 F1B0E4: MOVEI  #$00F1B0CC, R01 [NCZ:001, R01=00F1B0C8] -> [NCZ:001, R01=00F1B0CC]
2877 [STALL...]
2878 [STALL...]
2879 F1B0EA: LOAD   (R01), R03 [NCZ:001, R01=00F1B0CC, R03=00F1B086] -> [NCZ:001, R03=00000064]
2880 F1B0EC: MOVEI  #$00F1B0D0, R01 [NCZ:001, R01=00F1B0CC] -> [NCZ:001, R01=00F1B0D0]
2881 [STALL...]
2882 [STALL...]
2883 F1B0F2: LOAD   (R01), R04 [NCZ:001, R01=00F1B0D0, R04=00000000] -> [NCZ:001, R04=00000008]
2884 F1B0F4: MOVEI  #$00F1B0BC, R01 [NCZ:001, R01=00F1B0D0] -> [NCZ:001, R01=00F1B0BC]
2885 [STALL...]
2886 [STALL...]
2887 F1B0FA: ADD    R04, R01 [NCZ:001, R04=00000008, R01=00F1B0BC] -> [NCZ:000, R04=00000008, R01=00F1B0C4]
2888 [STALL...]
2889 [STALL...]
2890 F1B0FC: LOAD   (R01), R01 [NCZ:000, R01=00F1B0C4, R01=00F1B0C4] -> [NCZ:000, R01=00F1B12E]
2891 [STALL...]
2892 [STALL...]
2893 F1B0FE: JUMP   T, (R01) [NCZ:000, R01=00F1B12E] Branched!
2894 F1B0FE: NOP    [NCZ:000]
2895 [STALL...]
2896 F1B12E: MOVE   R02, R08 [NCZ:000, R02=00000001, R08=00000000] -> [NCZ:000, R02=00000001, R08=00000001]
2897 [STALL...]
2898 [STALL...]
2899 F1B132: MOVEI  #$00F1B102, R01 [NCZ:000, R01=00F1B12E] -> [NCZ:000, R01=00F1B102]
2900 [STALL...]
2901 [STALL...]
2902 F1B138: JUMP   T, (R01) [NCZ:000, R01=00F1B102] Branched!
2903 F1B138: NOP    [NCZ:000]
2904 [STALL...]
2905 F1B102: MOVEI  #$00F1B0C8, R01 [NCZ:000, R01=00F1B102] -> [NCZ:000, R01=00F1B0C8]
2906 [STALL...]
2907 [STALL...]
2908 F1B108: STORE  R08, (R01) [NCZ:000, R08=00000000, R01=00F1B0C8]
2909 F1B10A: MOVEI  #$00F1B0D0, R01 [NCZ:000, R01=00F1B0C8] -> [NCZ:000, R01=00F1B0D0]
2910 F1B110: MOVEQ  #0, R04 [NCZ:000, R04=00000008] -> [NCZ:000, R04=00000000]
2911 [STALL...]
2912 [STALL...]
2913 F1B112: STORE  R04, (R01) [NCZ:000, R04=00000000, R01=00F1B0D0]
2914 F1B114: BCLR   #3, R00 [NCZ:000, R00=00004039] -> [NCZ:000, R00=00004031]
2915 [STALL...]
2916 [STALL...]
2917 F1B116: BSET   #9, R00 [NCZ:000, R00=00004031] -> [NCZ:000, R00=00004231]
2918 F1B118: LOAD   (R31), R04 [NCZ:000, R31=00F1CFDC, R04=00000000] -> [NCZ:000, R04=00F1B086]
2919 F1B11A: MOVEI  #$00F1CFE0, R31 [NCZ:000, R31=00F1CFDC] -> [NCZ:000, R31=00F1CFE0]
2920 [STALL...]
2921 F1B120: ADDQ   #2, R04 [NCZ:000, R04=00F1B086] -> [NCZ:000, R04=00F1B088]
2922 F1B122: MOVEI  #$00F1A100, R01 [NCZ:000, R01=00F1B0D0] -> [NCZ:000, R01=00F1A100]
2923 [STALL...]
2924 [STALL...]
2925 F1B128: STORE  R00, (R01) [NCZ:000, R00=00004231, R01=00F1A100]
2926 DSP: Writing 00004231 to DSP_FLAGS by DSP (REGPAGE is set)...
2927 DSP: Finished interrupt.
2928 DSP: Generating interrupt #1... [PC will return to 00F1B12A, R31 = 00F1CFE0]
2929 [STALL...]
2930 F1B010: MOVEI  #$00F1B1FC, R30 [NCZ:001, R30=00F1B010] -> [NCZ:001, R30=00F1B1FC]
2931 [STALL...]
2932 [STALL...]
2933 F1B016: JUMP   T, (R30) [NCZ:001, R30=00F1B1FC] Branched!
2934 F1B016: NOP    [NCZ:001]
2935 [STALL...]
2936 F1B1FC: MOVEI  #$00F1A100, R01 [NCZ:001, R01=00F1A100] -> [NCZ:001, R01=00F1A100]
2937 */
2938
2939 uint32 pcQueue1[0x400];
2940 uint32 pcQPtr1 = 0;
2941
2942 //Let's try a 3 stage pipeline....
2943 //Looks like 3 stage is correct, otherwise bad things happen...
2944 void DSPExecP2(int32 cycles)
2945 {
2946         dsp_releaseTimeSlice_flag = 0;
2947         dsp_in_exec++;
2948
2949         while (cycles > 0 && DSP_RUNNING)
2950         {
2951 if (dsp_pc == 0xF1B0A0)
2952         doDSPDis = true;
2953
2954 pcQueue1[pcQPtr1++] = dsp_pc;
2955 pcQPtr1 &= 0x3FF;
2956
2957 if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFF) && !doDSPDis)
2958 {
2959         WriteLog("DSP: PC has stepped out of bounds...\n\nBacktrace:\n\n");
2960         doDSPDis = true;
2961
2962         char buffer[512];
2963
2964         for(int i=0; i<0x400; i++)
2965         {
2966                 dasmjag(JAGUAR_DSP, buffer, pcQueue1[(i + pcQPtr1) & 0x3FF]);
2967                 WriteLog("\t%08X: %s\n", pcQueue1[(i + pcQPtr1) & 0x3FF], buffer);
2968         }
2969         WriteLog("\n");
2970 }//*/
2971                 if (IMASKCleared)                                               // If IMASK was cleared,
2972                 {
2973 #ifdef DSP_DEBUG_IRQ
2974                         WriteLog("DSP: Finished interrupt.\n");
2975 #endif
2976                         DSPHandleIRQs();                                        // See if any other interrupts are pending!
2977                         IMASKCleared = false;
2978                 }
2979
2980 //if (dsp_flags & REGPAGE)
2981 //      WriteLog("  --> REGPAGE has just been set!\n");
2982 #ifdef DSP_DEBUG_PL2
2983 if (doDSPDis)
2984 {
2985 WriteLog("DSPExecP: Pipeline status [PC=%08X]...\n", dsp_pc);
2986 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister, dsp_opcode_str[pipeline[plPtrRead].opcode]);
2987 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister, dsp_opcode_str[pipeline[plPtrExec].opcode]);
2988 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister, dsp_opcode_str[pipeline[plPtrWrite].opcode]);
2989 WriteLog("  --> Scoreboard: ");
2990 for(int i=0; i<32; i++)
2991         WriteLog("%s ", scoreboard[i] ? "T" : "F");
2992 WriteLog("\n");
2993 }
2994 #endif
2995                 // Stage 1a: Instruction fetch
2996                 pipeline[plPtrRead].instruction = DSPReadWord(dsp_pc, DSP);
2997                 pipeline[plPtrRead].opcode = pipeline[plPtrRead].instruction >> 10;
2998                 pipeline[plPtrRead].operand1 = (pipeline[plPtrRead].instruction >> 5) & 0x1F;
2999                 pipeline[plPtrRead].operand2 = pipeline[plPtrRead].instruction & 0x1F;
3000                 if (pipeline[plPtrRead].opcode == 38)
3001                         pipeline[plPtrRead].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
3002                                 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
3003 #ifdef DSP_DEBUG_PL2
3004 if (doDSPDis)
3005 {
3006 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrRead].instruction, dsp_pc);
3007 WriteLog("DSPExecP: Pipeline status (after stage 1a) [PC=%08X]...\n", dsp_pc);
3008 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister, dsp_opcode_str[pipeline[plPtrRead].opcode]);
3009 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister, dsp_opcode_str[pipeline[plPtrExec].opcode]);
3010 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister, dsp_opcode_str[pipeline[plPtrWrite].opcode]);
3011 }
3012 #endif
3013                 // Stage 1b: Read registers
3014 //Small problem--when say LOAD or STORE (R14/5+$nn) is executed AFTER an instruction that
3015 //modifies R14/5, we don't check the scoreboard for R14/5 (and we need to!)... !!! FIX !!!
3016 //Ugly, but [DONE]
3017                 if ((scoreboard[pipeline[plPtrRead].operand1] && readAffected[pipeline[plPtrRead].opcode][0])
3018                         || (scoreboard[pipeline[plPtrRead].operand2] && readAffected[pipeline[plPtrRead].opcode][1])
3019                         || ((pipeline[plPtrRead].opcode == 43 || pipeline[plPtrRead].opcode == 58) && scoreboard[14])
3020                         || ((pipeline[plPtrRead].opcode == 44 || pipeline[plPtrRead].opcode == 59) && scoreboard[15]))
3021                         // We have a hit in the scoreboard, so we have to stall the pipeline...
3022 #ifdef DSP_DEBUG_PL2
3023 {
3024 if (doDSPDis)
3025 {
3026 WriteLog("  --> Stalling pipeline: ");
3027 if (readAffected[pipeline[plPtrRead].opcode][0])
3028         WriteLog("scoreboard[%u] = %s (reg 1) ", pipeline[plPtrRead].operand1, scoreboard[pipeline[plPtrRead].operand1] ? "true" : "false");
3029 if (readAffected[pipeline[plPtrRead].opcode][1])
3030         WriteLog("scoreboard[%u] = %s (reg 2)", pipeline[plPtrRead].operand2, scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
3031 WriteLog("\n");
3032 }
3033 #endif
3034                         pipeline[plPtrRead].opcode = PIPELINE_STALL;
3035 #ifdef DSP_DEBUG_PL2
3036 }
3037 #endif
3038                 else
3039                 {
3040                         pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
3041                         pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
3042                         pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2;   // Set it to RN
3043
3044                         // Shouldn't we be more selective with the register scoreboarding?
3045                         // Yes, we should. !!! FIX !!! Kinda [DONE]
3046                         scoreboard[pipeline[plPtrRead].operand2] = affectsScoreboard[pipeline[plPtrRead].opcode];
3047
3048 //Advance PC here??? Yes.
3049                         dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
3050                 }
3051
3052 #ifdef DSP_DEBUG_PL2
3053 if (doDSPDis)
3054 {
3055 WriteLog("DSPExecP: Pipeline status (after stage 1b) [PC=%08X]...\n", dsp_pc);
3056 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister, dsp_opcode_str[pipeline[plPtrRead].opcode]);
3057 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister, dsp_opcode_str[pipeline[plPtrExec].opcode]);
3058 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister, dsp_opcode_str[pipeline[plPtrWrite].opcode]);
3059 }
3060 #endif
3061                 // Stage 2: Execute
3062                 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
3063                 {
3064 #ifdef DSP_DEBUG_PL2
3065 if (doDSPDis)
3066 {
3067 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
3068 }
3069 #endif
3070 //CC only!
3071 #ifdef DSP_DEBUG_CC
3072 lastExec = pipeline[plPtrExec].instruction;
3073 //WriteLog("[lastExec = %04X]\n", lastExec);
3074 #endif
3075                         cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
3076                         dsp_opcode_use[pipeline[plPtrExec].opcode]++;
3077                         DSPOpcode[pipeline[plPtrExec].opcode]();
3078 //WriteLog("    --> Returned from execute. DSP_PC: %08X\n", dsp_pc);
3079                 }
3080                 else
3081 {
3082 //Let's not, until we do the stalling correctly...
3083 //But, we gotta while we're doing the comparison core...!
3084 //Or do we?                     cycles--;
3085 #ifdef DSP_DEBUG_STALL
3086 if (doDSPDis)
3087         WriteLog("[STALL... DSP_PC = %08X]\n", dsp_pc);
3088 #endif
3089 }
3090
3091 #ifdef DSP_DEBUG_PL2
3092 if (doDSPDis)
3093 {
3094 WriteLog("DSPExecP: Pipeline status (after stage 2) [PC=%08X]...\n", dsp_pc);
3095 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister, dsp_opcode_str[pipeline[plPtrRead].opcode]);
3096 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister, dsp_opcode_str[pipeline[plPtrExec].opcode]);
3097 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister, dsp_opcode_str[pipeline[plPtrWrite].opcode]);
3098 WriteLog("\n");
3099 }
3100 #endif
3101                 // Stage 3: Write back register/memory address
3102                 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
3103                 {
3104 /*if (pipeline[plPtrWrite].writebackRegister == 3
3105         && (pipeline[plPtrWrite].result < 0xF14000 || pipeline[plPtrWrite].result > 0xF1CFFF)
3106         && !doDSPDis)
3107 {
3108         WriteLog("DSP: Register R03 has stepped out of bounds...\n\n");
3109         doDSPDis = true;
3110 }//*/
3111                         if (pipeline[plPtrWrite].writebackRegister != 0xFF)
3112                         {
3113                                 if (pipeline[plPtrWrite].writebackRegister != 0xFE)
3114                                         dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
3115                                 else
3116                                 {
3117                                         if (pipeline[plPtrWrite].type == TYPE_BYTE)
3118                                                 JaguarWriteByte(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3119                                         else if (pipeline[plPtrWrite].type == TYPE_WORD)
3120                                                 JaguarWriteWord(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3121                                         else
3122                                                 JaguarWriteLong(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3123                                 }
3124                         }
3125
3126                         if (affectsScoreboard[pipeline[plPtrWrite].opcode])
3127                                 scoreboard[pipeline[plPtrWrite].operand2] = false;
3128                 }
3129
3130                 // Push instructions through the pipeline...
3131                 plPtrRead = (++plPtrRead) & 0x03;
3132                 plPtrExec = (++plPtrExec) & 0x03;
3133                 plPtrWrite = (++plPtrWrite) & 0x03;
3134         }
3135
3136         dsp_in_exec--;
3137 }
3138
3139
3140
3141 /*
3142 //#define DSP_DEBUG_PL3
3143 //Let's try a 2 stage pipeline....
3144 void DSPExecP3(int32 cycles)
3145 {
3146         dsp_releaseTimeSlice_flag = 0;
3147         dsp_in_exec++;
3148
3149         while (cycles > 0 && DSP_RUNNING)
3150         {
3151 //if (dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFF)
3152 //      doDSPDis = true;
3153 #ifdef DSP_DEBUG_PL3
3154 WriteLog("DSPExecP: Pipeline status...\n");
3155 WriteLog("\tF/R -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister, dsp_opcode_str[pipeline[plPtrRead].opcode]);
3156 WriteLog("\tE/W -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister, dsp_opcode_str[pipeline[plPtrExec].opcode]);
3157 WriteLog("  --> Scoreboard: ");
3158 for(int i=0; i<32; i++)
3159         WriteLog("%s ", scoreboard[i] ? "T" : "F");
3160 WriteLog("\n");
3161 #endif
3162                 // Stage 1a: Instruction fetch
3163                 pipeline[plPtrRead].instruction = DSPReadWord(dsp_pc, DSP);
3164                 pipeline[plPtrRead].opcode = pipeline[plPtrRead].instruction >> 10;
3165                 pipeline[plPtrRead].operand1 = (pipeline[plPtrRead].instruction >> 5) & 0x1F;
3166                 pipeline[plPtrRead].operand2 = pipeline[plPtrRead].instruction & 0x1F;
3167                 if (pipeline[plPtrRead].opcode == 38)
3168                         pipeline[plPtrRead].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
3169                                 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
3170 #ifdef DSP_DEBUG_PL3
3171 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrRead].instruction, dsp_pc);
3172 WriteLog("DSPExecP: Pipeline status (after stage 1a)...\n");
3173 WriteLog("\tF/R -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister, dsp_opcode_str[pipeline[plPtrRead].opcode]);
3174 WriteLog("\tE/W -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister, dsp_opcode_str[pipeline[plPtrExec].opcode]);
3175 #endif
3176                 // Stage 1b: Read registers
3177                 if ((scoreboard[pipeline[plPtrRead].operand1] && readAffected[pipeline[plPtrRead].opcode][0])
3178                         || (scoreboard[pipeline[plPtrRead].operand2] && readAffected[pipeline[plPtrRead].opcode][1]))
3179                         // We have a hit in the scoreboard, so we have to stall the pipeline...
3180 #ifdef DSP_DEBUG_PL3
3181 {
3182 WriteLog("  --> Stalling pipeline: ");
3183 if (readAffected[pipeline[plPtrRead].opcode][0])
3184         WriteLog("scoreboard[%u] = %s (reg 1) ", pipeline[plPtrRead].operand1, scoreboard[pipeline[plPtrRead].operand1] ? "true" : "false");
3185 if (readAffected[pipeline[plPtrRead].opcode][1])
3186         WriteLog("scoreboard[%u] = %s (reg 2)", pipeline[plPtrRead].operand2, scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
3187 WriteLog("\n");
3188 #endif
3189                         pipeline[plPtrRead].opcode = PIPELINE_STALL;
3190 #ifdef DSP_DEBUG_PL3
3191 }
3192 #endif
3193                 else
3194                 {
3195                         pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
3196                         pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
3197                         pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2;   // Set it to RN
3198
3199                         // Shouldn't we be more selective with the register scoreboarding?
3200                         // Yes, we should. !!! FIX !!! [Kinda DONE]
3201                         scoreboard[pipeline[plPtrRead].operand2] = affectsScoreboard[pipeline[plPtrRead].opcode];
3202
3203 //Advance PC here??? Yes.
3204                         dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
3205                 }
3206
3207 #ifdef DSP_DEBUG_PL3
3208 WriteLog("DSPExecP: Pipeline status (after stage 1b)...\n");
3209 WriteLog("\tF/R -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister, dsp_opcode_str[pipeline[plPtrRead].opcode]);
3210 WriteLog("\tE/W -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister, dsp_opcode_str[pipeline[plPtrExec].opcode]);
3211 #endif
3212                 // Stage 2a: Execute
3213                 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
3214                 {
3215 #ifdef DSP_DEBUG_PL3
3216 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
3217 #endif
3218                         DSPOpcode[pipeline[plPtrExec].opcode]();
3219                         dsp_opcode_use[pipeline[plPtrExec].opcode]++;
3220                         cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
3221                 }
3222                 else
3223                         cycles--;
3224
3225 #ifdef DSP_DEBUG_PL3
3226 WriteLog("DSPExecP: Pipeline status (after stage 2a)...\n");
3227 WriteLog("\tF/R -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister, dsp_opcode_str[pipeline[plPtrRead].opcode]);
3228 WriteLog("\tE/W -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister, dsp_opcode_str[pipeline[plPtrExec].opcode]);
3229 WriteLog("\n");
3230 #endif
3231                 // Stage 2b: Write back register
3232                 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
3233                 {
3234                         if (pipeline[plPtrExec].writebackRegister != 0xFF)
3235                                 dsp_reg[pipeline[plPtrExec].writebackRegister] = pipeline[plPtrExec].result;
3236
3237                         if (affectsScoreboard[pipeline[plPtrExec].opcode])
3238                                 scoreboard[pipeline[plPtrExec].operand2] = false;
3239                 }
3240
3241                 // Push instructions through the pipeline...
3242                 plPtrRead = (++plPtrRead) & 0x03;
3243                 plPtrExec = (++plPtrExec) & 0x03;
3244         }
3245
3246         dsp_in_exec--;
3247 }*/
3248
3249 //
3250 // DSP pipelined opcode handlers
3251 //
3252
3253 #define PRM                             pipeline[plPtrExec].reg1
3254 #define PRN                             pipeline[plPtrExec].reg2
3255 #define PIMM1                   pipeline[plPtrExec].operand1
3256 #define PIMM2                   pipeline[plPtrExec].operand2
3257 #define PRES                    pipeline[plPtrExec].result
3258 #define PWBR                    pipeline[plPtrExec].writebackRegister
3259 #define NO_WRITEBACK    pipeline[plPtrExec].writebackRegister = 0xFF
3260 //#define DSP_PPC                       dsp_pc - (pipeline[plPtrRead].opcode == 38 ? 6 : 2) - (pipeline[plPtrExec].opcode == 38 ? 6 : 2)
3261 #define DSP_PPC                 dsp_pc - (pipeline[plPtrRead].opcode == 38 ? 6 : (pipeline[plPtrRead].opcode == PIPELINE_STALL ? 0 : 2)) - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2))
3262 #define WRITEBACK_ADDR  pipeline[plPtrExec].writebackRegister = 0xFE
3263
3264 static void DSP_abs(void)
3265 {
3266 #ifdef DSP_DIS_ABS
3267         if (doDSPDis)
3268                 WriteLog("%06X: ABS    R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3269 #endif
3270         uint32 _Rn = PRN;
3271         
3272         if (_Rn == 0x80000000)
3273                 dsp_flag_n = 1;
3274         else
3275         {
3276                 dsp_flag_c = ((_Rn & 0x80000000) >> 31);
3277                 PRES = (_Rn & 0x80000000 ? -_Rn : _Rn);
3278                 CLR_ZN; SET_Z(PRES);
3279         }
3280 #ifdef DSP_DIS_ABS
3281         if (doDSPDis)
3282                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3283 #endif
3284 }
3285
3286 static void DSP_add(void)
3287 {
3288 #ifdef DSP_DIS_ADD
3289         if (doDSPDis)
3290                 WriteLog("%06X: ADD    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3291 #endif
3292         UINT32 res = PRN + PRM;
3293         SET_ZNC_ADD(PRN, PRM, res);
3294         PRES = res;
3295 #ifdef DSP_DIS_ADD
3296         if (doDSPDis)
3297                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
3298 #endif
3299 }
3300
3301 static void DSP_addc(void)
3302 {
3303 #ifdef DSP_DIS_ADDC
3304         if (doDSPDis)
3305                 WriteLog("%06X: ADDC   R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3306 #endif
3307         UINT32 res = PRN + PRM + dsp_flag_c;
3308         UINT32 carry = dsp_flag_c;
3309 //      SET_ZNC_ADD(PRN, PRM, res); //???BUG??? Yes!
3310         SET_ZNC_ADD(PRN + carry, PRM, res);
3311 //      SET_ZNC_ADD(PRN, PRM + carry, res);
3312         PRES = res;
3313 #ifdef DSP_DIS_ADDC
3314         if (doDSPDis)
3315                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
3316 #endif
3317 }
3318
3319 static void DSP_addq(void)
3320 {
3321 #ifdef DSP_DIS_ADDQ
3322         if (doDSPDis)
3323                 WriteLog("%06X: ADDQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3324 #endif
3325         UINT32 r1 = dsp_convert_zero[PIMM1];
3326         UINT32 res = PRN + r1;
3327         CLR_ZNC; SET_ZNC_ADD(PRN, r1, res);
3328         PRES = res;
3329 #ifdef DSP_DIS_ADDQ
3330         if (doDSPDis)
3331                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3332 #endif
3333 }
3334
3335 static void DSP_addqmod(void)
3336 {
3337 #ifdef DSP_DIS_ADDQMOD
3338         if (doDSPDis)
3339                 WriteLog("%06X: ADDQMOD #%u, R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_MOD=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, dsp_modulo);
3340 #endif
3341         UINT32 r1 = dsp_convert_zero[PIMM1];
3342         UINT32 r2 = PRN;
3343         UINT32 res = r2 + r1;
3344         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
3345         PRES = res;
3346         SET_ZNC_ADD(r2, r1, res);
3347 #ifdef DSP_DIS_ADDQMOD
3348         if (doDSPDis)
3349                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3350 #endif
3351 }
3352
3353 static void DSP_addqt(void)
3354 {
3355 #ifdef DSP_DIS_ADDQT
3356         if (doDSPDis)
3357                 WriteLog("%06X: ADDQT  #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3358 #endif
3359         PRES = PRN + dsp_convert_zero[PIMM1];
3360 #ifdef DSP_DIS_ADDQT
3361         if (doDSPDis)
3362                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3363 #endif
3364 }
3365
3366 static void DSP_and(void)
3367 {
3368 #ifdef DSP_DIS_AND
3369         if (doDSPDis)
3370                 WriteLog("%06X: AND    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3371 #endif
3372         PRES = PRN & PRM;
3373         SET_ZN(PRES);
3374 #ifdef DSP_DIS_AND
3375         if (doDSPDis)
3376                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
3377 #endif
3378 }
3379
3380 static void DSP_bclr(void)
3381 {
3382 #ifdef DSP_DIS_BCLR
3383         if (doDSPDis)
3384                 WriteLog("%06X: BCLR   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3385 #endif
3386         PRES = PRN & ~(1 << PIMM1);
3387         SET_ZN(PRES);
3388 #ifdef DSP_DIS_BCLR
3389         if (doDSPDis)
3390                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3391 #endif
3392 }
3393
3394 static void DSP_bset(void)
3395 {
3396 #ifdef DSP_DIS_BSET
3397         if (doDSPDis)
3398                 WriteLog("%06X: BSET   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3399 #endif
3400         PRES = PRN | (1 << PIMM1);
3401         SET_ZN(PRES);
3402 #ifdef DSP_DIS_BSET
3403         if (doDSPDis)
3404                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3405 #endif
3406 }
3407
3408 static void DSP_btst(void)
3409 {
3410 #ifdef DSP_DIS_BTST
3411         if (doDSPDis)
3412                 WriteLog("%06X: BTST   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3413 #endif
3414         dsp_flag_z = (~PRN >> PIMM1) & 1;
3415         NO_WRITEBACK;
3416 #ifdef DSP_DIS_BTST
3417         if (doDSPDis)
3418                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3419 #endif
3420 }
3421
3422 static void DSP_cmp(void)
3423 {
3424 #ifdef DSP_DIS_CMP
3425         if (doDSPDis)
3426                 WriteLog("%06X: CMP    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3427 #endif
3428         UINT32 res = PRN - PRM;
3429         SET_ZNC_SUB(PRN, PRM, res);
3430         NO_WRITEBACK;
3431 #ifdef DSP_DIS_CMP
3432         if (doDSPDis)
3433                 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
3434 #endif
3435 }
3436
3437 static void DSP_cmpq(void)
3438 {
3439         static int32 sqtable[32] =
3440                 { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1 };
3441 #ifdef DSP_DIS_CMPQ
3442         if (doDSPDis)
3443                 WriteLog("%06X: CMPQ   #%d, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, sqtable[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3444 #endif
3445         UINT32 r1 = sqtable[PIMM1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
3446         UINT32 res = PRN - r1;
3447         SET_ZNC_SUB(PRN, r1, res);
3448         NO_WRITEBACK;
3449 #ifdef DSP_DIS_CMPQ
3450         if (doDSPDis)
3451                 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
3452 #endif
3453 }
3454
3455 static void DSP_div(void)
3456 {
3457         uint32 _Rm = PRM, _Rn = PRN;
3458
3459         if (_Rm)
3460         {
3461                 if (dsp_div_control & 1)
3462                 {
3463                         dsp_remain = (((uint64)_Rn) << 16) % _Rm;
3464                         if (dsp_remain & 0x80000000)
3465                                 dsp_remain -= _Rm;
3466                         PRES = (((uint64)_Rn) << 16) / _Rm;
3467                 }
3468                 else
3469                 {
3470                         dsp_remain = _Rn % _Rm;
3471                         if (dsp_remain & 0x80000000)
3472                                 dsp_remain -= _Rm;
3473                         PRES = PRN / _Rm;
3474                 }
3475         }
3476         else
3477                 PRES = 0xFFFFFFFF;
3478 }
3479
3480 static void DSP_imacn(void)
3481 {
3482 #ifdef DSP_DIS_IMACN
3483         if (doDSPDis)
3484                 WriteLog("%06X: IMACN  R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3485 #endif
3486         int32 res = (int16)PRM * (int16)PRN;
3487         dsp_acc += (int64)res;
3488 //Should we AND the result to fit into 40 bits here???
3489         NO_WRITEBACK;
3490 #ifdef DSP_DIS_IMACN
3491         if (doDSPDis)
3492                 WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
3493 #endif
3494
3495
3496 static void DSP_imult(void)
3497 {
3498 #ifdef DSP_DIS_IMULT
3499         if (doDSPDis)
3500                 WriteLog("%06X: IMULT  R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3501 #endif
3502         PRES = (int16)PRN * (int16)PRM;
3503         SET_ZN(PRES);
3504 #ifdef DSP_DIS_IMULT
3505         if (doDSPDis)
3506                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
3507 #endif
3508 }
3509
3510 static void DSP_imultn(void)
3511 {
3512 #ifdef DSP_DIS_IMULTN
3513         if (doDSPDis)
3514                 WriteLog("%06X: IMULTN R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3515 #endif
3516         // This is OK, since this multiply won't overflow 32 bits...
3517         int32 res = (int32)((int16)PRN * (int16)PRM);
3518         dsp_acc = (int64)res;
3519         SET_ZN(res);
3520         NO_WRITEBACK;
3521 #ifdef DSP_DIS_IMULTN
3522         if (doDSPDis)
3523                 WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
3524 #endif
3525 }
3526
3527 static void DSP_illegal(void)
3528 {
3529 #ifdef DSP_DIS_ILLEGAL
3530         if (doDSPDis)
3531                 WriteLog("%06X: ILLEGAL [NCZ:%u%u%u]\n", DSP_PPC, dsp_flag_n, dsp_flag_c, dsp_flag_z);
3532 #endif
3533         NO_WRITEBACK;
3534 }
3535
3536 // There is a problem here with interrupt handlers the JUMP and JR instructions that
3537 // can cause trouble because an interrupt can occur *before* the instruction following the
3538 // jump can execute... !!! FIX !!!
3539 // This can probably be solved by judicious coding in the pipeline execution core...
3540 // And should be fixed now...
3541 static void DSP_jr(void)
3542 {
3543 #ifdef DSP_DIS_JR
3544 char * condition[32] =
3545 {       "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
3546         "c z", "???", "???", "???", "???", "???", "???", "???", "???",
3547         "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
3548         "???", "???", "???", "F" };
3549         if (doDSPDis)
3550 //How come this is always off by 2???
3551                 WriteLog("%06X: JR     %s, %06X [NCZ:%u%u%u] ", DSP_PPC, condition[PIMM2], DSP_PPC+((PIMM1 & 0x10 ? 0xFFFFFFF0 | PIMM1 : PIMM1) * 2), dsp_flag_n, dsp_flag_c, dsp_flag_z);
3552 #endif
3553         // KLUDGE: Used by BRANCH_CONDITION macro
3554         uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
3555
3556         if (BRANCH_CONDITION(PIMM2))
3557         {
3558 #ifdef DSP_DIS_JR
3559         if (doDSPDis)
3560                 WriteLog("Branched!\n");
3561 #endif
3562                 int32 offset = (PIMM1 & 0x10 ? 0xFFFFFFF0 | PIMM1 : PIMM1);             // Sign extend PIMM1
3563 //Account for pipeline effects...
3564                 uint32 newPC = dsp_pc + (offset * 2) - (pipeline[plPtrRead].opcode == 38 ? 6 : (pipeline[plPtrRead].opcode == PIPELINE_STALL ? 0 : 2));
3565 //WriteLog("  --> Old PC: %08X, new PC: %08X\n", dsp_pc, newPC);
3566
3567                 // Now that we've branched, we have to make sure that the following instruction
3568                 // is executed atomically with this one and then flush the pipeline before setting
3569                 // the new PC.
3570                 
3571                 // Step 1: Handle writebacks at stage 3 of pipeline
3572 /*              if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
3573                 {
3574                         if (pipeline[plPtrWrite].writebackRegister != 0xFF)
3575                                 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
3576
3577                         if (affectsScoreboard[pipeline[plPtrWrite].opcode])
3578                                 scoreboard[pipeline[plPtrWrite].operand2] = false;
3579                 }//*/
3580                 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
3581                 {
3582                         if (pipeline[plPtrWrite].writebackRegister != 0xFF)
3583                         {
3584                                 if (pipeline[plPtrWrite].writebackRegister != 0xFE)
3585                                         dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
3586                                 else
3587                                 {
3588                                         if (pipeline[plPtrWrite].type == TYPE_BYTE)
3589                                                 JaguarWriteByte(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3590                                         else if (pipeline[plPtrWrite].type == TYPE_WORD)
3591                                                 JaguarWriteWord(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3592                                         else
3593                                                 JaguarWriteLong(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3594                                 }
3595                         }
3596
3597                         if (affectsScoreboard[pipeline[plPtrWrite].opcode])
3598                                 scoreboard[pipeline[plPtrWrite].operand2] = false;
3599                 }
3600
3601                 // Step 2: Push instruction through pipeline & execute following instruction
3602                 // NOTE: By putting our following instruction at stage 3 of the pipeline,
3603                 //       we effectively handle the final push of the instruction through the
3604                 //       pipeline when the new PC takes effect (since when we return, the
3605                 //       pipeline code will be executing the writeback stage. If we reverse
3606                 //       the execution order of the pipeline stages, this will no longer be
3607                 //       the case!)...
3608                 pipeline[plPtrExec] = pipeline[plPtrRead];
3609 //This is BAD. We need to get that next opcode and execute it!
3610 //NOTE: The problem is here because of a bad stall. Once those are fixed, we can probably
3611 //      remove this crap.
3612                 if (pipeline[plPtrExec].opcode == PIPELINE_STALL)
3613                 {
3614                 uint16 instruction = DSPReadWord(dsp_pc, DSP);
3615                 pipeline[plPtrExec].opcode = instruction >> 10;
3616                 pipeline[plPtrExec].operand1 = (instruction >> 5) & 0x1F;
3617                 pipeline[plPtrExec].operand2 = instruction & 0x1F;
3618                         pipeline[plPtrExec].reg1 = dsp_reg[pipeline[plPtrExec].operand1];
3619                         pipeline[plPtrExec].reg2 = dsp_reg[pipeline[plPtrExec].operand2];
3620                         pipeline[plPtrExec].writebackRegister = pipeline[plPtrExec].operand2;   // Set it to RN
3621                 }//*/
3622                 DSPOpcode[pipeline[plPtrExec].opcode]();
3623                 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
3624                 pipeline[plPtrWrite] = pipeline[plPtrExec];
3625
3626                 // Step 3: Flush pipeline & set new PC
3627                 pipeline[plPtrRead].opcode = pipeline[plPtrExec].opcode = PIPELINE_STALL;
3628                 dsp_pc = newPC;
3629         }
3630         else
3631 #ifdef DSP_DIS_JR
3632         {
3633                 if (doDSPDis)
3634                         WriteLog("Branch NOT taken.\n");
3635 #endif
3636                 NO_WRITEBACK;
3637 #ifdef DSP_DIS_JR
3638         }
3639 #endif
3640 //      WriteLog("  --> DSP_PC: %08X\n", dsp_pc);
3641 }
3642
3643 static void DSP_jump(void)
3644 {
3645 #ifdef DSP_DIS_JUMP
3646 char * condition[32] =
3647 {       "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
3648         "c z", "???", "???", "???", "???", "???", "???", "???", "???",
3649         "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
3650         "???", "???", "???", "F" };
3651         if (doDSPDis)
3652                 WriteLog("%06X: JUMP   %s, (R%02u) [NCZ:%u%u%u, R%02u=%08X] ", DSP_PPC, condition[PIMM2], PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM);
3653 #endif
3654         // KLUDGE: Used by BRANCH_CONDITION macro
3655         uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
3656
3657         if (BRANCH_CONDITION(PIMM2))
3658         {
3659 #ifdef DSP_DIS_JUMP
3660         if (doDSPDis)
3661                 WriteLog("Branched!\n");
3662 #endif
3663                 uint32 PCSave = PRM;
3664                 // Now that we've branched, we have to make sure that the following instruction
3665                 // is executed atomically with this one and then flush the pipeline before setting
3666                 // the new PC.
3667                 
3668                 // Step 1: Handle writebacks at stage 3 of pipeline
3669 /*              if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
3670                 {
3671                         if (pipeline[plPtrWrite].writebackRegister != 0xFF)
3672                                 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
3673
3674                         if (affectsScoreboard[pipeline[plPtrWrite].opcode])
3675                                 scoreboard[pipeline[plPtrWrite].operand2] = false;
3676                 }//*/
3677                 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
3678                 {
3679                         if (pipeline[plPtrWrite].writebackRegister != 0xFF)
3680                         {
3681                                 if (pipeline[plPtrWrite].writebackRegister != 0xFE)
3682                                         dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
3683                                 else
3684                                 {
3685                                         if (pipeline[plPtrWrite].type == TYPE_BYTE)
3686                                                 JaguarWriteByte(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3687                                         else if (pipeline[plPtrWrite].type == TYPE_WORD)
3688                                                 JaguarWriteWord(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3689                                         else
3690                                                 JaguarWriteLong(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3691                                 }
3692                         }
3693
3694                         if (affectsScoreboard[pipeline[plPtrWrite].opcode])
3695                                 scoreboard[pipeline[plPtrWrite].operand2] = false;
3696                 }
3697
3698                 // Step 2: Push instruction through pipeline & execute following instruction
3699                 // NOTE: By putting our following instruction at stage 3 of the pipeline,
3700                 //       we effectively handle the final push of the instruction through the
3701                 //       pipeline when the new PC takes effect (since when we return, the
3702                 //       pipeline code will be executing the writeback stage. If we reverse
3703                 //       the execution order of the pipeline stages, this will no longer be
3704                 //       the case!)...
3705                 pipeline[plPtrExec] = pipeline[plPtrRead];
3706 //This is BAD. We need to get that next opcode and execute it!
3707 //Also, same problem in JR!
3708 //NOTE: The problem is here because of a bad stall. Once those are fixed, we can probably
3709 //      remove this crap.
3710                 if (pipeline[plPtrExec].opcode == PIPELINE_STALL)
3711                 {
3712                 uint16 instruction = DSPReadWord(dsp_pc, DSP);
3713                 pipeline[plPtrExec].opcode = instruction >> 10;
3714                 pipeline[plPtrExec].operand1 = (instruction >> 5) & 0x1F;
3715                 pipeline[plPtrExec].operand2 = instruction & 0x1F;
3716                         pipeline[plPtrExec].reg1 = dsp_reg[pipeline[plPtrExec].operand1];
3717                         pipeline[plPtrExec].reg2 = dsp_reg[pipeline[plPtrExec].operand2];
3718                         pipeline[plPtrExec].writebackRegister = pipeline[plPtrExec].operand2;   // Set it to RN
3719                 }//*/
3720                 DSPOpcode[pipeline[plPtrExec].opcode]();
3721                 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
3722                 pipeline[plPtrWrite] = pipeline[plPtrExec];
3723
3724                 // Step 3: Flush pipeline & set new PC
3725                 pipeline[plPtrRead].opcode = pipeline[plPtrExec].opcode = PIPELINE_STALL;
3726                 dsp_pc = PCSave;
3727         }
3728         else
3729 #ifdef DSP_DIS_JUMP
3730         {
3731                 if (doDSPDis)
3732                         WriteLog("Branch NOT taken.\n");
3733 #endif
3734                 NO_WRITEBACK;
3735 #ifdef DSP_DIS_JUMP
3736         }
3737 #endif
3738 }
3739
3740 static void DSP_load(void)
3741 {
3742 #ifdef DSP_DIS_LOAD
3743         if (doDSPDis)
3744                 WriteLog("%06X: LOAD   (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3745 #endif
3746         PRES = DSPReadLong(PRM, DSP);
3747 #ifdef DSP_DIS_LOAD
3748         if (doDSPDis)
3749                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3750 #endif
3751 }
3752
3753 static void DSP_loadb(void)
3754 {
3755 #ifdef DSP_DIS_LOADB
3756         if (doDSPDis)
3757                 WriteLog("%06X: LOADB  (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3758 #endif
3759         if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
3760                 PRES = DSPReadLong(PRM, DSP) & 0xFF;
3761         else
3762                 PRES = JaguarReadByte(PRM, DSP);
3763 #ifdef DSP_DIS_LOADB
3764         if (doDSPDis)
3765                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3766 #endif
3767 }
3768
3769 static void DSP_loadw(void)
3770 {
3771 #ifdef DSP_DIS_LOADW
3772         if (doDSPDis)
3773                 WriteLog("%06X: LOADW  (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3774 #endif
3775         if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
3776                 PRES = DSPReadLong(PRM, DSP) & 0xFFFF;
3777         else
3778                 PRES = JaguarReadWord(PRM, DSP);
3779 #ifdef DSP_DIS_LOADW
3780         if (doDSPDis)
3781                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3782 #endif
3783 }
3784
3785 static void DSP_load_r14_i(void)
3786 {
3787 #ifdef DSP_DIS_LOAD14I
3788         if (doDSPDis)
3789                 WriteLog("%06X: LOAD   (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1] << 2, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[PIMM1] << 2, dsp_reg[14]+(dsp_convert_zero[PIMM1] << 2), PIMM2, PRN);
3790 #endif
3791         PRES = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), DSP);
3792 #ifdef DSP_DIS_LOAD14I
3793         if (doDSPDis)
3794                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3795 #endif
3796 }
3797
3798 static void DSP_load_r14_r(void)
3799 {
3800 #ifdef DSP_DIS_LOAD14R
3801         if (doDSPDis)
3802                 WriteLog("%06X: LOAD   (R14+R%02u), R%02u [NCZ:%u%u%u, R14+R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM+dsp_reg[14], PIMM2, PRES);
3803 #endif
3804         PRES = DSPReadLong(dsp_reg[14] + PRM, DSP);
3805 #ifdef DSP_DIS_LOAD14R
3806         if (doDSPDis)
3807                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3808 #endif
3809 }
3810
3811 static void DSP_load_r15_i(void)
3812 {
3813 #ifdef DSP_DIS_LOAD15I
3814         if (doDSPDis)
3815                 WriteLog("%06X: LOAD   (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1] << 2, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[PIMM1] << 2, dsp_reg[15]+(dsp_convert_zero[PIMM1] << 2), PIMM2, PRN);
3816 #endif
3817         PRES = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), DSP);
3818 #ifdef DSP_DIS_LOAD15I
3819         if (doDSPDis)
3820                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3821 #endif
3822 }
3823
3824 static void DSP_load_r15_r(void)
3825 {
3826 #ifdef DSP_DIS_LOAD15R
3827         if (doDSPDis)
3828                 WriteLog("%06X: LOAD   (R15+R%02u), R%02u [NCZ:%u%u%u, R15+R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM+dsp_reg[15], PIMM2, PRN);
3829 #endif
3830         PRES = DSPReadLong(dsp_reg[15] + PRM, DSP);
3831 #ifdef DSP_DIS_LOAD15R
3832         if (doDSPDis)
3833                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3834 #endif
3835 }
3836
3837 static void DSP_mirror(void)    
3838 {
3839         UINT32 r1 = PRN;
3840         PRES = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
3841         SET_ZN(PRES);
3842 }
3843
3844 static void DSP_mmult(void)
3845 {
3846         int count       = dsp_matrix_control&0x0f;
3847         uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
3848         int64 accum = 0;
3849         uint32 res;
3850
3851         if (!(dsp_matrix_control & 0x10))
3852         {
3853                 for (int i = 0; i < count; i++)
3854                 { 
3855                         int16 a;
3856                         if (i&0x01)
3857                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
3858                         else
3859                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
3860                         int16 b=((int16)DSPReadWord(addr + 2, DSP));
3861                         accum += a*b;
3862                         addr += 4;
3863                 }
3864         }
3865         else
3866         {
3867                 for (int i = 0; i < count; i++)
3868                 {
3869                         int16 a;
3870                         if (i&0x01)
3871                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
3872                         else
3873                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
3874                         int16 b=((int16)DSPReadWord(addr + 2, DSP));
3875                         accum += a*b;
3876                         addr += 4 * count;
3877                 }
3878         }
3879
3880         PRES = res = (int32)accum;
3881         // carry flag to do
3882 //NOTE: The flags are set based upon the last add/multiply done...
3883         SET_ZN(PRES);
3884 }
3885
3886 static void DSP_move(void)
3887 {
3888 #ifdef DSP_DIS_MOVE
3889         if (doDSPDis)
3890                 WriteLog("%06X: MOVE   R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3891 #endif
3892         PRES = PRM;
3893 #ifdef DSP_DIS_MOVE
3894         if (doDSPDis)
3895                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
3896 #endif
3897 }
3898
3899 static void DSP_movefa(void)
3900 {
3901 #ifdef DSP_DIS_MOVEFA
3902         if (doDSPDis)
3903 //              WriteLog("%06X: MOVEFA R%02u, R%02u [NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, ALTERNATE_RM, PIMM2, PRN);
3904                 WriteLog("%06X: MOVEFA R%02u, R%02u [NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, dsp_alternate_reg[PIMM1], PIMM2, PRN);
3905 #endif
3906 //      PRES = ALTERNATE_RM;
3907         PRES = dsp_alternate_reg[PIMM1];
3908 #ifdef DSP_DIS_MOVEFA
3909         if (doDSPDis)
3910 //              WriteLog("[NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, ALTERNATE_RM, PIMM2, PRN);
3911                 WriteLog("[NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, dsp_alternate_reg[PIMM1], PIMM2, PRES);
3912 #endif
3913 }
3914
3915 static void DSP_movei(void)
3916 {
3917 #ifdef DSP_DIS_MOVEI
3918         if (doDSPDis)
3919                 WriteLog("%06X: MOVEI  #$%08X, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PRES, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3920 #endif
3921 //      // This instruction is followed by 32-bit value in LSW / MSW format...
3922 //      PRES = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
3923 //      dsp_pc += 4;
3924 #ifdef DSP_DIS_MOVEI
3925         if (doDSPDis)
3926                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3927 #endif
3928 }
3929
3930 static void DSP_movepc(void)
3931 {
3932 //Need to fix this to take into account pipelining effects... !!! FIX !!! [DONE]
3933 //      PRES = dsp_pc - 2;
3934 //Account for pipeline effects...
3935         PRES = dsp_pc - (pipeline[plPtrRead].opcode == 38 ? 6 : (pipeline[plPtrRead].opcode == PIPELINE_STALL ? 0 : 2));
3936 }
3937
3938 static void DSP_moveq(void)
3939 {
3940 #ifdef DSP_DIS_MOVEQ
3941         if (doDSPDis)
3942                 WriteLog("%06X: MOVEQ  #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3943 #endif
3944         PRES = PIMM1;
3945 #ifdef DSP_DIS_MOVEQ
3946         if (doDSPDis)
3947                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3948 #endif
3949 }
3950
3951 static void DSP_moveta(void)
3952 {
3953 #ifdef DSP_DIS_MOVETA
3954         if (doDSPDis)
3955 //              WriteLog("%06X: MOVETA R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, ALTERNATE_RN);
3956                 WriteLog("%06X: MOVETA R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, dsp_alternate_reg[PIMM2]);
3957 #endif
3958 //      ALTERNATE_RN = PRM;
3959         dsp_alternate_reg[PIMM2] = PRM;
3960         NO_WRITEBACK;
3961 #ifdef DSP_DIS_MOVETA
3962         if (doDSPDis)
3963 //              WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, ALTERNATE_RN);
3964                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, dsp_alternate_reg[PIMM2]);
3965 #endif
3966 }
3967
3968 static void DSP_mtoi(void)
3969 {
3970         PRES = (((INT32)PRM >> 8) & 0xFF800000) | (PRM & 0x007FFFFF);
3971         SET_ZN(PRES);
3972 }
3973
3974 static void DSP_mult(void)
3975 {
3976 #ifdef DSP_DIS_MULT
3977         if (doDSPDis)
3978                 WriteLog("%06X: MULT   R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3979 #endif
3980         PRES = (uint16)PRM * (uint16)PRN;
3981         SET_ZN(PRES);
3982 #ifdef DSP_DIS_MULT
3983         if (doDSPDis)
3984                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
3985 #endif
3986 }
3987
3988 static void DSP_neg(void)
3989 {
3990 #ifdef DSP_DIS_NEG
3991         if (doDSPDis)
3992                 WriteLog("%06X: NEG    R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3993 #endif
3994         UINT32 res = -PRN;
3995         SET_ZNC_SUB(0, PRN, res);
3996         PRES = res;
3997 #ifdef DSP_DIS_NEG
3998         if (doDSPDis)
3999                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
4000 #endif
4001 }
4002
4003 static void DSP_nop(void)
4004 {
4005 #ifdef DSP_DIS_NOP
4006         if (doDSPDis)
4007                 WriteLog("%06X: NOP    [NCZ:%u%u%u]\n", DSP_PPC, dsp_flag_n, dsp_flag_c, dsp_flag_z);
4008 #endif
4009         NO_WRITEBACK;
4010 }
4011
4012 static void DSP_normi(void)
4013 {
4014         uint32 _Rm = PRM;
4015         uint32 res = 0;
4016
4017         if (_Rm)
4018         {
4019                 while ((_Rm & 0xffc00000) == 0)
4020                 {
4021                         _Rm <<= 1;
4022                         res--;
4023                 }
4024                 while ((_Rm & 0xff800000) != 0)
4025                 {
4026                         _Rm >>= 1;
4027                         res++;
4028                 }
4029         }
4030         PRES = res;
4031         SET_ZN(PRES);
4032 }
4033
4034 static void DSP_not(void)
4035 {
4036 #ifdef DSP_DIS_NOT
4037         if (doDSPDis)
4038                 WriteLog("%06X: NOT    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
4039 #endif
4040         PRES = ~PRN;
4041         SET_ZN(PRES);
4042 #ifdef DSP_DIS_NOT
4043         if (doDSPDis)
4044                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
4045 #endif
4046 }
4047
4048 static void DSP_or(void)
4049 {
4050 #ifdef DSP_DIS_OR
4051         if (doDSPDis)
4052                 WriteLog("%06X: OR     R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
4053 #endif
4054         PRES = PRN | PRM;
4055         SET_ZN(PRES);
4056 #ifdef DSP_DIS_OR
4057         if (doDSPDis)
4058                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
4059 #endif
4060 }
4061
4062 static void DSP_resmac(void)
4063 {
4064 #ifdef DSP_DIS_RESMAC
4065         if (doDSPDis)
4066                 WriteLog("%06X: RESMAC R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_ACC=%02X%08X] -> ", DSP_PPC, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
4067 #endif
4068         PRES = (uint32)dsp_acc;
4069 #ifdef DSP_DIS_RESMAC
4070         if (doDSPDis)
4071                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
4072 #endif
4073 }
4074
4075 static void DSP_ror(void)
4076 {
4077 #ifdef DSP_DIS_ROR
4078         if (doDSPDis)
4079                 WriteLog("%06X: ROR    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
4080 #endif
4081         UINT32 r1 = PRM & 0x1F;
4082         UINT32 res = (PRN >> r1) | (PRN << (32 - r1));
4083         SET_ZN(res); dsp_flag_c = (PRN >> 31) & 1;
4084         PRES = res;
4085 #ifdef DSP_DIS_ROR
4086         if (doDSPDis)
4087                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
4088 #endif
4089 }
4090
4091 static void DSP_rorq(void)
4092 {
4093 #ifdef DSP_DIS_RORQ
4094         if (doDSPDis)
4095                 WriteLog("%06X: RORQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
4096 #endif
4097         UINT32 r1 = dsp_convert_zero[PIMM1 & 0x1F];
4098         UINT32 r2 = PRN;
4099         UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
4100         PRES = res;
4101         SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
4102 #ifdef DSP_DIS_RORQ
4103         if (doDSPDis)
4104                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
4105 #endif
4106 }
4107
4108 static void DSP_sat16s(void)            
4109 {
4110         INT32 r2 = PRN;
4111         UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
4112         PRES = res;
4113         SET_ZN(res);
4114 }
4115
4116 static void DSP_sat32s(void)            
4117 {
4118         INT32 r2 = (UINT32)PRN;
4119         INT32 temp = dsp_acc >> 32;
4120         UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
4121         PRES = res;
4122         SET_ZN(res);
4123 }
4124
4125 static void DSP_sh(void)
4126 {
4127         int32 sRm = (int32)PRM;
4128         uint32 _Rn = PRN;
4129
4130         if (sRm < 0)
4131         {
4132                 uint32 shift = -sRm;
4133
4134                 if (shift >= 32)
4135                         shift = 32;
4136
4137                 dsp_flag_c = (_Rn & 0x80000000) >> 31;
4138
4139                 while (shift)
4140                 {
4141                         _Rn <<= 1;
4142                         shift--;
4143                 }
4144         }
4145         else
4146         {
4147                 uint32 shift = sRm;
4148
4149                 if (shift >= 32)
4150                         shift = 32;
4151
4152                 dsp_flag_c = _Rn & 0x1;
4153
4154                 while (shift)
4155                 {
4156                         _Rn >>= 1;
4157                         shift--;
4158                 }
4159         }
4160
4161         PRES = _Rn;
4162         SET_ZN(PRES);
4163 }
4164
4165 static void DSP_sha(void)
4166 {
4167         int32 sRm = (int32)PRM;
4168         uint32 _Rn = PRN;
4169
4170         if (sRm < 0)
4171         {
4172                 uint32 shift = -sRm;
4173
4174                 if (shift >= 32)
4175                         shift = 32;
4176
4177                 dsp_flag_c = (_Rn & 0x80000000) >> 31;
4178
4179                 while (shift)
4180                 {
4181                         _Rn <<= 1;
4182                         shift--;
4183                 }
4184         }
4185         else
4186         {
4187                 uint32 shift = sRm;
4188
4189                 if (shift >= 32)
4190                         shift = 32;
4191
4192                 dsp_flag_c = _Rn & 0x1;
4193
4194                 while (shift)
4195                 {
4196                         _Rn = ((int32)_Rn) >> 1;
4197                         shift--;
4198                 }
4199         }
4200
4201         PRES = _Rn;
4202         SET_ZN(PRES);
4203 }
4204
4205 static void DSP_sharq(void)
4206 {
4207 #ifdef DSP_DIS_SHARQ
4208         if (doDSPDis)
4209                 WriteLog("%06X: SHARQ  #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
4210 #endif
4211         UINT32 res = (INT32)PRN >> dsp_convert_zero[PIMM1];
4212         SET_ZN(res); dsp_flag_c = PRN & 0x01;
4213         PRES = res;
4214 #ifdef DSP_DIS_SHARQ
4215         if (doDSPDis)
4216                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
4217 #endif
4218 }
4219
4220 static void DSP_shlq(void)
4221 {
4222 #ifdef DSP_DIS_SHLQ
4223         if (doDSPDis)
4224                 WriteLog("%06X: SHLQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, 32 - PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
4225 #endif
4226         INT32 r1 = 32 - PIMM1;
4227         UINT32 res = PRN << r1;
4228         SET_ZN(res); dsp_flag_c = (PRN >> 31) & 1;
4229         PRES = res;
4230 #ifdef DSP_DIS_SHLQ
4231         if (doDSPDis)
4232                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
4233 #endif
4234 }
4235
4236 static void DSP_shrq(void)
4237 {
4238 #ifdef DSP_DIS_SHRQ
4239         if (doDSPDis)
4240                 WriteLog("%06X: SHRQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
4241 #endif
4242         INT32 r1 = dsp_convert_zero[PIMM1];
4243         UINT32 res = PRN >> r1;
4244         SET_ZN(res); dsp_flag_c = PRN & 1;
4245         PRES = res;
4246 #ifdef DSP_DIS_SHRQ
4247         if (doDSPDis)
4248                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
4249 #endif
4250 }
4251
4252 static void DSP_store(void)
4253 {
4254 #ifdef DSP_DIS_STORE
4255         if (doDSPDis)
4256                 WriteLog("%06X: STORE  R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", DSP_PPC, PIMM2, PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, PIMM1, PRM);
4257 #endif
4258 //      DSPWriteLong(PRM, PRN, DSP);
4259 //      NO_WRITEBACK;
4260         pipeline[plPtrExec].address = PRM;
4261         pipeline[plPtrExec].value = PRN;
4262         pipeline[plPtrExec].type = TYPE_DWORD;
4263         WRITEBACK_ADDR;
4264 }
4265
4266 static void DSP_storeb(void)
4267 {
4268 #ifdef DSP_DIS_STOREB
4269         if (doDSPDis)
4270                 WriteLog("%06X: STOREB R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", DSP_PPC, PIMM2, PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, PIMM1, PRM);
4271 #endif
4272 //      if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
4273 //              DSPWriteLong(PRM, PRN & 0xFF, DSP);
4274 //      else
4275 //              JaguarWriteByte(PRM, PRN, DSP);
4276 //
4277 //      NO_WRITEBACK;
4278         pipeline[plPtrExec].address = PRM;
4279
4280         if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
4281         {
4282                 pipeline[plPtrExec].value = PRN & 0xFF;
4283                 pipeline[plPtrExec].type = TYPE_DWORD;
4284         }
4285         else
4286         {
4287                 pipeline[plPtrExec].value = PRN;
4288                 pipeline[plPtrExec].type = TYPE_BYTE;
4289         }
4290
4291         WRITEBACK_ADDR;
4292 }
4293
4294 static void DSP_storew(void)
4295 {
4296 #ifdef DSP_DIS_STOREW
4297         if (doDSPDis)
4298                 WriteLog("%06X: STOREW R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", DSP_PPC, PIMM2, PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, PIMM1, PRM);
4299 #endif
4300 //      if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
4301 //              DSPWriteLong(PRM, PRN & 0xFFFF, DSP);
4302 //      else
4303 //              JaguarWriteWord(PRM, PRN, DSP);
4304 //
4305 //      NO_WRITEBACK;
4306         pipeline[plPtrExec].address = PRM;
4307
4308         if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
4309         {
4310                 pipeline[plPtrExec].value = PRN & 0xFFFF;
4311                 pipeline[plPtrExec].type = TYPE_DWORD;
4312         }
4313         else
4314         {
4315                 pipeline[plPtrExec].value = PRN;
4316                 pipeline[plPtrExec].type = TYPE_WORD;
4317         }
4318         WRITEBACK_ADDR;
4319 }
4320
4321 static void DSP_store_r14_i(void)
4322 {
4323 #ifdef DSP_DIS_STORE14I
4324         if (doDSPDis)
4325                 WriteLog("%06X: STORE  R%02u, (R14+$%02X) [NCZ:%u%u%u, R%02u=%08X, R14+$%02X=%08X]\n", DSP_PPC, PIMM2, dsp_convert_zero[PIMM1] << 2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, dsp_convert_zero[PIMM1] << 2, dsp_reg[14]+(dsp_convert_zero[PIMM1] << 2));
4326 #endif
4327 //      DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
4328 //      NO_WRITEBACK;
4329         pipeline[plPtrExec].address = dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2);
4330         pipeline[plPtrExec].value = PRN;
4331         pipeline[plPtrExec].type = TYPE_DWORD;
4332         WRITEBACK_ADDR;
4333 }
4334
4335 static void DSP_store_r14_r(void)
4336 {
4337 //      DSPWriteLong(dsp_reg[14] + PRM, PRN, DSP);
4338 //      NO_WRITEBACK;
4339         pipeline[plPtrExec].address = dsp_reg[14] + PRM;
4340         pipeline[plPtrExec].value = PRN;
4341         pipeline[plPtrExec].type = TYPE_DWORD;
4342         WRITEBACK_ADDR;
4343 }
4344
4345 static void DSP_store_r15_i(void)
4346 {
4347 #ifdef DSP_DIS_STORE15I
4348         if (doDSPDis)
4349                 WriteLog("%06X: STORE  R%02u, (R15+$%02X) [NCZ:%u%u%u, R%02u=%08X, R15+$%02X=%08X]\n", DSP_PPC, PIMM2, dsp_convert_zero[PIMM1] << 2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, dsp_convert_zero[PIMM1] << 2, dsp_reg[15]+(dsp_convert_zero[PIMM1] << 2));
4350 #endif
4351 //      DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
4352 //      NO_WRITEBACK;
4353         pipeline[plPtrExec].address = dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2);
4354         pipeline[plPtrExec].value = PRN;
4355         pipeline[plPtrExec].type = TYPE_DWORD;
4356         WRITEBACK_ADDR;
4357 }
4358
4359 static void DSP_store_r15_r(void)
4360 {
4361 //      DSPWriteLong(dsp_reg[15] + PRM, PRN, DSP);
4362 //      NO_WRITEBACK;
4363         pipeline[plPtrExec].address = dsp_reg[15] + PRM;
4364         pipeline[plPtrExec].value = PRN;
4365         pipeline[plPtrExec].type = TYPE_DWORD;
4366         WRITEBACK_ADDR;
4367 }
4368
4369 static void DSP_sub(void)
4370 {
4371 #ifdef DSP_DIS_SUB
4372         if (doDSPDis)
4373                 WriteLog("%06X: SUB    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
4374 #endif
4375         UINT32 res = PRN - PRM;
4376         SET_ZNC_SUB(PRN, PRM, res);
4377         PRES = res;
4378 #ifdef DSP_DIS_SUB
4379         if (doDSPDis)
4380                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
4381 #endif
4382 }
4383
4384 static void DSP_subc(void)
4385 {
4386 #ifdef DSP_DIS_SUBC
4387         if (doDSPDis)
4388                 WriteLog("%06X: SUBC   R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
4389 #endif
4390         UINT32 res = PRN - PRM - dsp_flag_c;
4391         UINT32 borrow = dsp_flag_c;
4392         SET_ZNC_SUB(PRN - borrow, PRM, res);
4393         PRES = res;
4394 #ifdef DSP_DIS_SUBC
4395         if (doDSPDis)
4396                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
4397 #endif
4398 }
4399
4400 static void DSP_subq(void)
4401 {
4402 #ifdef DSP_DIS_SUBQ
4403         if (doDSPDis)
4404                 WriteLog("%06X: SUBQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
4405 #endif
4406         UINT32 r1 = dsp_convert_zero[PIMM1];
4407         UINT32 res = PRN - r1;
4408         SET_ZNC_SUB(PRN, r1, res);
4409         PRES = res;
4410 #ifdef DSP_DIS_SUBQ
4411         if (doDSPDis)
4412                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
4413 #endif
4414 }
4415
4416 static void DSP_subqmod(void)   
4417 {
4418         UINT32 r1 = dsp_convert_zero[PIMM1];
4419         UINT32 r2 = PRN;
4420         UINT32 res = r2 - r1;
4421         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
4422         PRES = res;
4423         SET_ZNC_SUB(r2, r1, res);
4424 }
4425
4426 static void DSP_subqt(void)
4427 {
4428 #ifdef DSP_DIS_SUBQT
4429         if (doDSPDis)
4430                 WriteLog("%06X: SUBQT  #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
4431 #endif
4432         PRES = PRN - dsp_convert_zero[PIMM1];
4433 #ifdef DSP_DIS_SUBQT
4434         if (doDSPDis)
4435                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
4436 #endif
4437 }
4438
4439 static void DSP_xor(void)
4440 {
4441 #ifdef DSP_DIS_XOR
4442         if (doDSPDis)
4443                 WriteLog("%06X: XOR    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
4444 #endif
4445         PRES = PRN ^ PRM;
4446         SET_ZN(PRES);
4447 #ifdef DSP_DIS_XOR
4448         if (doDSPDis)
4449                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
4450 #endif
4451 }