]> Shamusworld >> Repos - virtualjaguar/blob - src/dsp.cpp
New experimental pipelined core
[virtualjaguar] / src / dsp.cpp
1 //
2 // DSP core
3 //
4 // 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
15 // Disassembly definitions
16
17 #define DSP_DIS_ADD
18 #define DSP_DIS_ADDC
19 #define DSP_DIS_ADDQ
20 #define DSP_DIS_ADDQMOD
21 #define DSP_DIS_ADDQT
22 #define DSP_DIS_AND
23 #define DSP_DIS_BCLR
24 #define DSP_DIS_BSET
25 #define DSP_DIS_BTST
26 #define DSP_DIS_CMP
27 #define DSP_DIS_CMPQ
28 #define DSP_DIS_IMACN
29 #define DSP_DIS_IMULT
30 #define DSP_DIS_IMULTN
31 #define DSP_DIS_ILLEGAL
32 #define DSP_DIS_JR
33 #define DSP_DIS_JUMP
34 #define DSP_DIS_LOAD
35 #define DSP_DIS_LOAD14I
36 #define DSP_DIS_LOAD14R
37 #define DSP_DIS_LOAD15I
38 #define DSP_DIS_LOAD15R
39 #define DSP_DIS_LOADB
40 #define DSP_DIS_LOADW
41 #define DSP_DIS_MOVE
42 #define DSP_DIS_MOVEI
43 #define DSP_DIS_MOVEQ
44 #define DSP_DIS_MOVEFA
45 #define DSP_DIS_MOVETA
46 #define DSP_DIS_MULT
47 #define DSP_DIS_NEG
48 #define DSP_DIS_NOP
49 #define DSP_DIS_NOT
50 #define DSP_DIS_OR
51 #define DSP_DIS_RESMAC
52 #define DSP_DIS_ROR
53 #define DSP_DIS_RORQ
54 #define DSP_DIS_SHARQ
55 #define DSP_DIS_SHLQ
56 #define DSP_DIS_SHRQ
57 #define DSP_DIS_STORE
58 #define DSP_DIS_STORE14I
59 #define DSP_DIS_STORE15I
60 #define DSP_DIS_STOREB
61 #define DSP_DIS_STOREW
62 #define DSP_DIS_SUB
63 #define DSP_DIS_SUBC
64 #define DSP_DIS_SUBQ
65 #define DSP_DIS_SUBQT
66 #define DSP_DIS_XOR
67 //*/
68 //bool doDSPDis = false;
69 bool doDSPDis = true;
70
71
72 /*
73 No dis yet:
74 +       subqt 4560
75 +       mult 1472
76 +       imultn 395024
77 +       resmac 395024
78 +       imacn 395024
79 +       addqmod 93328
80
81 dsp opcodes use:
82 +       add 1672497
83 +       addq 4366576
84 +       addqt 44405640
85 +       sub 94833
86 +       subq 111769
87 +       and 47416
88 +       btst 94521
89 +       bset 2277826
90 +       bclr 3223372
91 +       mult 47104
92 +       imult 237080
93 +       shlq 365464
94 +       shrq 141624
95 +       sharq 318368
96 +       cmp 45175078
97 +       move 2238994
98 +       moveq 335305
99 +       moveta 19
100 +       movefa 47406440
101 +       movei 1920664
102 +       loadb 94832
103 +       load 4031281
104 +       load_r15_indexed 284500
105 +       store 2161732
106 +       store_r15_indexed 47416
107 +       jump 3872424
108 +       jr 46386967
109 +       nop 3300029
110 +       load_r14_ri 1229448
111 */
112
113 // DSP flags (old--have to get rid of this crap)
114
115 #define CINT0FLAG                       0x00200
116 #define CINT1FLAG                       0x00400
117 #define CINT2FLAG                       0x00800
118 #define CINT3FLAG                       0x01000
119 #define CINT4FLAG                       0x02000
120 #define CINT04FLAGS                     (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
121 #define CINT5FLAG                       0x20000         /* DSP only */
122
123 // DSP_FLAGS bits
124
125 #define ZERO_FLAG               0x00001
126 #define CARRY_FLAG              0x00002
127 #define NEGA_FLAG               0x00004
128 #define IMASK                   0x00008
129 #define INT_ENA0                0x00010
130 #define INT_ENA1                0x00020
131 #define INT_ENA2                0x00040
132 #define INT_ENA3                0x00080
133 #define INT_ENA4                0x00100
134 #define INT_CLR0                0x00200
135 #define INT_CLR1                0x00400
136 #define INT_CLR2                0x00800
137 #define INT_CLR3                0x01000
138 #define INT_CLR4                0x02000
139 #define REGPAGE                 0x04000
140 #define DMAEN                   0x08000
141 #define INT_ENA5                0x10000
142 #define INT_CLR5                0x20000
143
144 // DSP_CTRL bits
145
146 #define DSPGO                   0x00001
147 #define CPUINT                  0x00002
148 #define DSPINT0                 0x00004
149 #define SINGLE_STEP             0x00008
150 #define SINGLE_GO               0x00010
151 // Bit 5 is unused!
152 #define INT_LAT0                0x00040
153 #define INT_LAT1                0x00080
154 #define INT_LAT2                0x00100
155 #define INT_LAT3                0x00200
156 #define INT_LAT4                0x00400
157 #define BUS_HOG                 0x00800
158 #define VERSION                 0x0F000
159 #define INT_LAT5                0x10000
160
161 extern uint32 jaguar_mainRom_crc32;
162
163 // Is opcode 62 *really* a NOP? Seems like it...
164 static void dsp_opcode_abs(void);
165 static void dsp_opcode_add(void);
166 static void dsp_opcode_addc(void);
167 static void dsp_opcode_addq(void);
168 static void dsp_opcode_addqmod(void);   
169 static void dsp_opcode_addqt(void);
170 static void dsp_opcode_and(void);
171 static void dsp_opcode_bclr(void);
172 static void dsp_opcode_bset(void);
173 static void dsp_opcode_btst(void);
174 static void dsp_opcode_cmp(void);
175 static void dsp_opcode_cmpq(void);
176 static void dsp_opcode_div(void);
177 static void dsp_opcode_imacn(void);
178 static void dsp_opcode_imult(void);
179 static void dsp_opcode_imultn(void);
180 static void dsp_opcode_jr(void);
181 static void dsp_opcode_jump(void);
182 static void dsp_opcode_load(void);
183 static void dsp_opcode_loadb(void);
184 static void dsp_opcode_loadw(void);
185 static void dsp_opcode_load_r14_indexed(void);
186 static void dsp_opcode_load_r14_ri(void);
187 static void dsp_opcode_load_r15_indexed(void);
188 static void dsp_opcode_load_r15_ri(void);
189 static void dsp_opcode_mirror(void);    
190 static void dsp_opcode_mmult(void);
191 static void dsp_opcode_move(void);
192 static void dsp_opcode_movei(void);
193 static void dsp_opcode_movefa(void);
194 static void dsp_opcode_move_pc(void);
195 static void dsp_opcode_moveq(void);
196 static void dsp_opcode_moveta(void);
197 static void dsp_opcode_mtoi(void);
198 static void dsp_opcode_mult(void);
199 static void dsp_opcode_neg(void);
200 static void dsp_opcode_nop(void);
201 static void dsp_opcode_normi(void);
202 static void dsp_opcode_not(void);
203 static void dsp_opcode_or(void);
204 static void dsp_opcode_resmac(void);
205 static void dsp_opcode_ror(void);
206 static void dsp_opcode_rorq(void);
207 static void dsp_opcode_xor(void);
208 static void dsp_opcode_sat16s(void);    
209 static void dsp_opcode_sat32s(void);    
210 static void dsp_opcode_sh(void);
211 static void dsp_opcode_sha(void);
212 static void dsp_opcode_sharq(void);
213 static void dsp_opcode_shlq(void);
214 static void dsp_opcode_shrq(void);
215 static void dsp_opcode_store(void);
216 static void dsp_opcode_storeb(void);
217 static void dsp_opcode_storew(void);
218 static void dsp_opcode_store_r14_indexed(void);
219 static void dsp_opcode_store_r14_ri(void);
220 static void dsp_opcode_store_r15_indexed(void);
221 static void dsp_opcode_store_r15_ri(void);
222 static void dsp_opcode_sub(void);
223 static void dsp_opcode_subc(void);
224 static void dsp_opcode_subq(void);
225 static void dsp_opcode_subqmod(void);   
226 static void dsp_opcode_subqt(void);
227
228 uint8 dsp_opcode_cycles[64] =
229 {
230         3,  3,  3,  3,  
231         3,  3,  3,  3,  
232         3,  3,  3,  3,  
233         3,  3,  3,  3,
234         3,  3,  1,  3,  
235         1, 18,  3,  3,  
236         3,  3,  3,  3,  
237         3,  3,  3,  3,
238         3,  3,  2,  2,  
239         2,  2,  3,  4,  
240         5,  4,  5,  6,  
241         6,  1,  1,  1,
242         1,  2,  2,  2,  
243         1,  1,  9,  3,  
244         3,  1,  6,  6,  
245         2,  2,  3,  3
246 };
247
248 void (* dsp_opcode[64])() =
249 {       
250         dsp_opcode_add,                                 dsp_opcode_addc,                                dsp_opcode_addq,                                dsp_opcode_addqt,
251         dsp_opcode_sub,                                 dsp_opcode_subc,                                dsp_opcode_subq,                                dsp_opcode_subqt,
252         dsp_opcode_neg,                                 dsp_opcode_and,                                 dsp_opcode_or,                                  dsp_opcode_xor,
253         dsp_opcode_not,                                 dsp_opcode_btst,                                dsp_opcode_bset,                                dsp_opcode_bclr,
254         dsp_opcode_mult,                                dsp_opcode_imult,                               dsp_opcode_imultn,                              dsp_opcode_resmac,
255         dsp_opcode_imacn,                               dsp_opcode_div,                                 dsp_opcode_abs,                                 dsp_opcode_sh,
256         dsp_opcode_shlq,                                dsp_opcode_shrq,                                dsp_opcode_sha,                                 dsp_opcode_sharq,
257         dsp_opcode_ror,                                 dsp_opcode_rorq,                                dsp_opcode_cmp,                                 dsp_opcode_cmpq,
258         dsp_opcode_subqmod,                             dsp_opcode_sat16s,                              dsp_opcode_move,                                dsp_opcode_moveq,
259         dsp_opcode_moveta,                              dsp_opcode_movefa,                              dsp_opcode_movei,                               dsp_opcode_loadb,
260         dsp_opcode_loadw,                               dsp_opcode_load,                                dsp_opcode_sat32s,                              dsp_opcode_load_r14_indexed,
261         dsp_opcode_load_r15_indexed,    dsp_opcode_storeb,                              dsp_opcode_storew,                              dsp_opcode_store,
262         dsp_opcode_mirror,                              dsp_opcode_store_r14_indexed,   dsp_opcode_store_r15_indexed,   dsp_opcode_move_pc,
263         dsp_opcode_jump,                                dsp_opcode_jr,                                  dsp_opcode_mmult,                               dsp_opcode_mtoi,
264         dsp_opcode_normi,                               dsp_opcode_nop,                                 dsp_opcode_load_r14_ri,                 dsp_opcode_load_r15_ri,
265         dsp_opcode_store_r14_ri,                dsp_opcode_store_r15_ri,                dsp_opcode_nop,                                 dsp_opcode_addqmod,
266 };
267
268 uint32 dsp_opcode_use[64];
269
270 char * dsp_opcode_str[65]=
271 {       
272         "add",                          "addc",                         "addq",                         "addqt",
273         "sub",                          "subc",                         "subq",                         "subqt",
274         "neg",                          "and",                          "or",                           "xor",
275         "not",                          "btst",                         "bset",                         "bclr",
276         "mult",                         "imult",                        "imultn",                       "resmac",
277         "imacn",                        "div",                          "abs",                          "sh",
278         "shlq",                         "shrq",                         "sha",                          "sharq",
279         "ror",                          "rorq",                         "cmp",                          "cmpq",
280         "subqmod",                      "sat16s",                       "move",                         "moveq",
281         "moveta",                       "movefa",                       "movei",                        "loadb",
282         "loadw",                        "load",                         "sat32s",                       "load_r14_indexed",
283         "load_r15_indexed",     "storeb",                       "storew",                       "store",
284         "mirror",                       "store_r14_indexed","store_r15_indexed","move_pc",
285         "jump",                         "jr",                           "mmult",                        "mtoi",
286         "normi",                        "nop",                          "load_r14_ri",          "load_r15_ri",
287         "store_r14_ri",         "store_r15_ri",         "illegal",                      "addqmod",
288         "STALL"
289 };
290
291 uint32 dsp_pc;
292 static uint64 dsp_acc;                                                          // 40 bit register, NOT 32!
293 static uint32 dsp_remain;
294 static uint32 dsp_modulo;
295 static uint32 dsp_flags;
296 static uint32 dsp_matrix_control;
297 static uint32 dsp_pointer_to_matrix;
298 static uint32 dsp_data_organization;
299 uint32 dsp_control;
300 static uint32 dsp_div_control;
301 static uint8 dsp_flag_z, dsp_flag_n, dsp_flag_c;    
302 static uint32 * dsp_reg, * dsp_alternate_reg;
303 static uint32 * dsp_reg_bank_0, * dsp_reg_bank_1;
304
305 static uint32 dsp_opcode_first_parameter;
306 static uint32 dsp_opcode_second_parameter;
307
308 #define DSP_RUNNING                     (dsp_control & 0x01)
309
310 #define RM                                      dsp_reg[dsp_opcode_first_parameter]
311 #define RN                                      dsp_reg[dsp_opcode_second_parameter]
312 #define ALTERNATE_RM            dsp_alternate_reg[dsp_opcode_first_parameter]
313 #define ALTERNATE_RN            dsp_alternate_reg[dsp_opcode_second_parameter]
314 #define IMM_1                           dsp_opcode_first_parameter
315 #define IMM_2                           dsp_opcode_second_parameter
316
317 #define CLR_Z                           (dsp_flag_z = 0)
318 #define CLR_ZN                          (dsp_flag_z = dsp_flag_n = 0)
319 #define CLR_ZNC                         (dsp_flag_z = dsp_flag_n = dsp_flag_c = 0)
320 #define SET_Z(r)                        (dsp_flag_z = ((r) == 0))
321 #define SET_N(r)                        (dsp_flag_n = (((UINT32)(r) >> 31) & 0x01))
322 #define SET_C_ADD(a,b)          (dsp_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
323 #define SET_C_SUB(a,b)          (dsp_flag_c = ((UINT32)(b) > (UINT32)(a)))
324 #define SET_ZN(r)                       SET_N(r); SET_Z(r)
325 #define SET_ZNC_ADD(a,b,r)      SET_N(r); SET_Z(r); SET_C_ADD(a,b)
326 #define SET_ZNC_SUB(a,b,r)      SET_N(r); SET_Z(r); SET_C_SUB(a,b)
327
328 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 };
329 uint8 * dsp_branch_condition_table = NULL;
330 static uint16 * mirror_table = NULL;
331 static uint8 * dsp_ram_8 = NULL;
332
333 #define BRANCH_CONDITION(x)             dsp_branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
334
335 static uint32 dsp_in_exec = 0;
336 static uint32 dsp_releaseTimeSlice_flag = 0;
337
338 FILE * dsp_fp;
339
340 // Private function prototypes
341
342 void DSPDumpRegisters(void);
343 void DSPDumpDisassembly(void);
344 void FlushDSPPipeline(void);
345
346
347 void dsp_reset_stats(void)
348 {
349         for(int i=0; i<64; i++)
350                 dsp_opcode_use[i] = 0;
351 }
352
353 void dsp_releaseTimeslice(void)
354 {
355 //This does absolutely nothing!!! !!! FIX !!!
356         dsp_releaseTimeSlice_flag = 1;
357 }
358
359 void dsp_build_branch_condition_table(void)
360 {
361         // Allocate the mirror table
362         if (!mirror_table)
363                 mirror_table = (uint16 *)malloc(65536 * sizeof(mirror_table[0]));
364
365         // Fill in the mirror table
366         if (mirror_table)
367                 for(int i=0; i<65536; i++)
368                         mirror_table[i] = ((i >> 15) & 0x0001) | ((i >> 13) & 0x0002) |
369                                           ((i >> 11) & 0x0004) | ((i >> 9)  & 0x0008) |
370                                           ((i >> 7)  & 0x0010) | ((i >> 5)  & 0x0020) |
371                                           ((i >> 3)  & 0x0040) | ((i >> 1)  & 0x0080) |
372                                           ((i << 1)  & 0x0100) | ((i << 3)  & 0x0200) |
373                                           ((i << 5)  & 0x0400) | ((i << 7)  & 0x0800) |
374                                           ((i << 9)  & 0x1000) | ((i << 11) & 0x2000) |
375                                           ((i << 13) & 0x4000) | ((i << 15) & 0x8000);
376
377         if (!dsp_branch_condition_table)
378         {
379                 dsp_branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(dsp_branch_condition_table[0]));
380
381                 // Fill in the condition table
382                 if (dsp_branch_condition_table)
383                 {
384                         for(int i=0; i<8; i++)
385                         {
386                                 for(int j=0; j<32; j++)
387                                 {
388                                         int result = 1;
389                                         if (j & 1)
390                                                 if (i & ZERO_FLAG)
391                                                         result = 0;
392                                         if (j & 2)
393                                                 if (!(i & ZERO_FLAG))
394                                                         result = 0;
395                                         if (j & 4)
396                                                 if (i & (CARRY_FLAG << (j >> 4)))
397                                                         result = 0;
398                                         if (j & 8)
399                                                 if (!(i & (CARRY_FLAG << (j >> 4))))
400                                                         result = 0;
401                                         dsp_branch_condition_table[i * 32 + j] = result;
402                                 }
403                         }
404                 }
405         }
406 }
407
408 uint8 DSPReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
409 {
410         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
411                 WriteLog("DSP: ReadByte--Attempt to read from DSP register file by %s!\n", whoName[who]);
412 // battlemorph
413 //      if ((offset==0xF1CFE0)||(offset==0xF1CFE2))
414 //              return(0xffff);
415         // mutant penguin
416 /*      if ((jaguar_mainRom_crc32==0xbfd751a4)||(jaguar_mainRom_crc32==0x053efaf9))
417         {
418                 if (offset==0xF1CFE0)
419                         return(0xff);
420         }*/
421         if (offset >= DSP_WORK_RAM_BASE && offset <= (DSP_WORK_RAM_BASE + 0x1FFF))
422                 return dsp_ram_8[offset - DSP_WORK_RAM_BASE];
423
424         if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
425         {
426                 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
427
428                 if ((offset&0x03)==0)
429                         return(data>>24);
430                 else
431                 if ((offset&0x03)==1)
432                         return((data>>16)&0xff);
433                 else
434                 if ((offset&0x03)==2)
435                         return((data>>8)&0xff);
436                 else
437                 if ((offset&0x03)==3)
438                         return(data&0xff);
439         }
440
441         return JaguarReadByte(offset, who);
442
443
444 uint16 DSPReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
445 {
446         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
447                 WriteLog("DSP: ReadWord--Attempt to read from DSP register file by %s!\n", whoName[who]);
448         //???
449         offset &= 0xFFFFFFFE;
450         // jaguar cd bios
451 /*      if (jaguar_mainRom_crc32==0xa74a97cd)
452         {
453                 if (offset==0xF1A114) return(0x0000);
454                 if (offset==0xF1A116) return(0x0000);
455                 if (offset==0xF1B000) return(0x1234);
456                 if (offset==0xF1B002) return(0x5678);
457         }*/
458 /*
459         if (jaguar_mainRom_crc32==0x7ae20823)
460         {
461                 if (offset==0xF1B9D8) return(0x0000);
462                 if (offset==0xF1B9Da) return(0x0000);
463                 if (offset==0xF1B2C0) return(0x0000);
464                 if (offset==0xF1B2C2) return(0x0000);
465         }
466 */
467         // pour permettre Ã  wolfenstein 3d de tourner sans le dsp
468 /*      if ((offset==0xF1B0D0)||(offset==0xF1B0D2))
469                 return(0);
470 */
471
472                 // pour permettre Ã  nba jam de tourner sans le dsp
473 /*      if (jaguar_mainRom_crc32==0x4faddb18)
474         {
475                 if (offset==0xf1b2c0) return(0);
476                 if (offset==0xf1b2c2) return(0);
477                 if (offset==0xf1b240) return(0);
478                 if (offset==0xf1b242) return(0);
479                 if (offset==0xF1B340) return(0);
480                 if (offset==0xF1B342) return(0);
481                 if (offset==0xF1BAD8) return(0);
482                 if (offset==0xF1BADA) return(0);
483                 if (offset==0xF1B040) return(0);
484                 if (offset==0xF1B042) return(0);
485                 if (offset==0xF1B0C0) return(0);
486                 if (offset==0xF1B0C2) return(0);
487                 if (offset==0xF1B140) return(0);
488                 if (offset==0xF1B142) return(0);
489                 if (offset==0xF1B1C0) return(0);
490                 if (offset==0xF1B1C2) return(0);
491         }*/
492
493         if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE+0x1FFF)
494         {
495                 offset -= DSP_WORK_RAM_BASE;
496 /*              uint16 data = (((uint16)dsp_ram_8[offset])<<8)|((uint16)dsp_ram_8[offset+1]);
497                 return data;*/
498                 return GET16(dsp_ram_8, offset);
499         }
500         else if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
501         {
502                 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
503
504                 if (offset & 0x03)
505                         return data & 0xFFFF;
506                 else
507                         return data >> 16;
508         }
509
510         return JaguarReadWord(offset, who);
511 }
512
513 uint32 DSPReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
514 {
515         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
516                 WriteLog("DSP: ReadLong--Attempt to read from DSP register file by %s!\n", whoName[who]);
517
518         // ??? WHY ???
519         offset &= 0xFFFFFFFC;
520 /*if (offset == 0xF1BCF4)
521 {
522         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));
523         DSPDumpDisassembly();
524 }*/
525         if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
526         {
527                 offset -= DSP_WORK_RAM_BASE;
528                 return GET32(dsp_ram_8, offset);
529         }
530 //NOTE: Didn't return DSP_ACCUM!!!
531 //Mebbe it's not 'spose to! Yes, it is!
532         if (offset >= DSP_CONTROL_RAM_BASE && offset <= DSP_CONTROL_RAM_BASE + 0x23)
533         {
534                 offset &= 0x3F;
535                 switch (offset)
536                 {
537                 case 0x00:      /*dsp_flag_c?(dsp_flag_c=1):(dsp_flag_c=0);
538                                         dsp_flag_z?(dsp_flag_z=1):(dsp_flag_z=0);
539                                         dsp_flag_n?(dsp_flag_n=1):(dsp_flag_n=0);*/
540
541                                         dsp_flags = (dsp_flags & 0xFFFFFFF8) | (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
542                                         return dsp_flags & 0xFFFFC1FF;
543                 case 0x04: return dsp_matrix_control;
544                 case 0x08: return dsp_pointer_to_matrix;
545                 case 0x0C: return dsp_data_organization;
546                 case 0x10: return dsp_pc;
547                 case 0x14: return dsp_control;
548                 case 0x18: return dsp_modulo;
549                 case 0x1C: return dsp_remain;
550                 case 0x20:
551                         return (int32)((int8)(dsp_acc >> 32));  // Top 8 bits of 40-bit accumulator, sign extended
552                 }
553                 // unaligned long read-- !!! FIX !!!
554                 return 0xFFFFFFFF;
555         }
556
557         return JaguarReadLong(offset, who);
558 }
559
560 void DSPWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
561 {
562         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
563                 WriteLog("DSP: WriteByte--Attempt to write to DSP register file by %s!\n", whoName[who]);
564
565         if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
566         {
567                 offset -= DSP_WORK_RAM_BASE;
568                 dsp_ram_8[offset] = data;
569 //This is rather stupid! !!! FIX !!!
570 /*              if (dsp_in_exec == 0)
571                 {
572                         m68k_end_timeslice();
573                         gpu_releaseTimeslice();
574                 }*/
575                 return;
576         }
577         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
578         {
579                 uint32 reg = offset & 0x1C;
580                 int bytenum = offset & 0x03;
581                 
582                 if ((reg >= 0x1C) && (reg <= 0x1F))
583                         dsp_div_control = (dsp_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
584                 else
585                 {
586 //This looks funky. !!! FIX !!!
587                         uint32 old_data = DSPReadLong(offset&0xFFFFFFC, who);
588                         bytenum = 3 - bytenum; // convention motorola !!!
589                         old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3)); 
590                         DSPWriteLong(offset & 0xFFFFFFC, old_data, who);
591                 }
592                 return;
593         }
594 //      WriteLog("dsp: writing %.2x at 0x%.8x\n",data,offset);
595 //Should this *ever* happen??? Shouldn't we be saying "unknown" here???
596         JaguarWriteByte(offset, data, who);
597 }
598
599 void DSPWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
600 {
601         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
602                 WriteLog("DSP: WriteWord--Attempt to write to DSP register file by %s!\n", whoName[who]);
603         offset &= 0xFFFFFFFE;
604 /*if (offset == 0xF1BCF4)
605 {
606         WriteLog("DSPWriteWord: Writing to 0xF1BCF4... %04X -> %04X\n", GET16(dsp_ram_8, 0x0CF4), data);
607 }*/
608 //      WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset);
609         if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
610         {
611                 offset -= DSP_WORK_RAM_BASE;
612                 dsp_ram_8[offset] = data >> 8;
613                 dsp_ram_8[offset+1] = data & 0xFF;
614 //This is rather stupid! !!! FIX !!!
615 /*              if (dsp_in_exec == 0)
616                 {
617 //                      WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset+DSP_WORK_RAM_BASE);
618                         m68k_end_timeslice();
619                         gpu_releaseTimeslice();
620                 }*/
621                 return;
622         }
623         else if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
624         {
625                 if ((offset & 0x1C) == 0x1C)
626                 {
627                         if (offset & 0x03)
628                                 dsp_div_control = (dsp_div_control&0xffff0000)|(data&0xffff);
629                         else
630                                 dsp_div_control = (dsp_div_control&0xffff)|((data&0xffff)<<16);
631                 }
632                 else
633                 {
634                         uint32 old_data = DSPReadLong(offset & 0xffffffc, who);
635                         if (offset & 0x03)
636                                 old_data = (old_data&0xffff0000)|(data&0xffff);
637                         else
638                                 old_data = (old_data&0xffff)|((data&0xffff)<<16);
639                         DSPWriteLong(offset & 0xffffffc, old_data, who);
640                 }
641                 return;
642         }
643
644         JaguarWriteWord(offset, data, who);
645 }
646
647 //bool badWrite = false;
648 void DSPWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
649 {
650         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
651                 WriteLog("DSP: WriteLong--Attempt to write to DSP register file by %s!\n", whoName[who]);
652         // ??? WHY ???
653         offset &= 0xFFFFFFFC;
654 /*if (offset == 0xF1BCF4)
655 {
656         WriteLog("DSPWriteLong: Writing to 0xF1BCF4... %08X -> %08X\n", GET32(dsp_ram_8, 0x0CF4), data);
657 }*/
658 //      WriteLog("dsp: writing %.8x at 0x%.8x\n",data,offset);
659         if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
660         {
661 /*if (offset == 0xF1BE2C)
662 {
663         WriteLog("DSP: %s is writing %08X at location 0xF1BE2C (DSP_PC: %08X)...\n", whoName[who], data, dsp_pc - 2);
664 }//*/
665                 offset -= DSP_WORK_RAM_BASE;
666                 SET32(dsp_ram_8, offset, data);
667                 return;
668         }
669         else if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
670         {
671                 offset &= 0x1F;
672                 switch (offset)
673                 {
674                 case 0x00:
675                 {
676 #ifdef DSP_DEBUG
677                         WriteLog("DSP: Writing %08X to DSP_FLAGS by %s...\n", data, whoName[who]);
678 #endif
679                         bool IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
680                         dsp_flags = data;
681                         dsp_flag_z = dsp_flags & 0x01;
682                         dsp_flag_c = (dsp_flags >> 1) & 0x01;
683                         dsp_flag_n = (dsp_flags >> 2) & 0x01;
684                         DSPUpdateRegisterBanks();
685                         dsp_control &= ~((dsp_flags & CINT04FLAGS) >> 3);
686                         dsp_control &= ~((dsp_flags & CINT5FLAG) >> 1);
687                         if (IMASKCleared)                                               // If IMASK was cleared,
688 #ifdef DSP_DEBUG_IRQ
689                         {
690                                 WriteLog("DSP: Finished interrupt.\n");
691 #endif
692                                 DSPHandleIRQs();                                        // see if any other interrupts need servicing!
693 #ifdef DSP_DEBUG_IRQ
694                         }
695 #endif
696                         break;
697                 }
698                 case 0x04:
699                         dsp_matrix_control = data;
700                         break;
701                 case 0x08:
702                         // According to JTRM, only lines 2-11 are adressable, the rest being
703                         // hardwired to $F1Bxxx.
704                         dsp_pointer_to_matrix = 0xF1B000 | (data & 0x000FFC);
705                         break;
706                 case 0x0C:
707                         dsp_data_organization = data;
708                         break;
709                 case 0x10:
710                         dsp_pc = data;
711 #ifdef DSP_DEBUG
712                         WriteLog("DSP: Setting DSP PC to %08X by %s%s\n", dsp_pc, whoName[who], (DSP_RUNNING ? " (DSP is RUNNING!)" : ""));//*/
713 #endif
714                         break;
715                 case 0x14:
716                 {       
717 //                      uint32 dsp_was_running = DSP_RUNNING;
718                         // Check for DSP -> CPU interrupt
719                         if (data & CPUINT)
720                         {
721 //                              WriteLog("DSP: DSP -> CPU interrupt\n");
722 // This was WRONG
723 // Why do we check for a valid handler at 64? Isn't that the Jag programmer's responsibility?
724                                 if (JERRYIRQEnabled(IRQ2_DSP) && jaguar_interrupt_handler_is_valid(64))
725                                 {
726                                         JERRYSetPendingIRQ(IRQ2_DSP);
727                                         dsp_releaseTimeslice();
728                                         m68k_set_irq(7);                        // Set 68000 NMI...
729                                 }
730                                 data &= ~CPUINT;
731                         }
732                         // Check for CPU -> DSP interrupt
733                         if (data & DSPINT0)
734                         {
735 #ifdef DSP_DEBUG
736                                 WriteLog("DSP: CPU -> DSP interrupt\n");
737 #endif
738                                 m68k_end_timeslice();
739                                 gpu_releaseTimeslice();
740                                 DSPSetIRQLine(DSPIRQ_CPU, ASSERT_LINE);
741                                 data &= ~DSPINT0;
742                         }
743                         // single stepping
744                         if (data & SINGLE_STEP)
745                         {
746 //                              WriteLog("DSP: Asked to perform a single step (single step is %senabled)\n", (data & 0x8 ? "" : "not "));
747                         }
748
749                         // Protect writes to VERSION and the interrupt latches...
750                         uint32 mask = VERSION | INT_LAT0 | INT_LAT1 | INT_LAT2 | INT_LAT3 | INT_LAT4 | INT_LAT5;
751                         dsp_control = (dsp_control & mask) | (data & ~mask);
752
753                         // if dsp wasn't running but is now running
754                         // execute a few cycles
755 //This is just plain wrong, wrong, WRONG!
756 #ifndef DSP_SINGLE_STEPPING
757 /*                      if (!dsp_was_running && DSP_RUNNING)
758                         {
759                                 DSPExec(200);
760                         }*/
761 #else
762 //This is WRONG! !!! FIX !!!
763                         if (dsp_control & 0x18)
764                                 DSPExec(1);
765 #endif
766 #ifdef DSP_DEBUG
767 WriteLog("Write to DSP CTRL: %08X ", data);
768 if (DSP_RUNNING)
769         WriteLog(" --> Starting to run at %08X by %s...", dsp_pc, whoName[who]);
770 else
771         WriteLog(" --> Stopped by %s! (DSP PC: %08X)", whoName[who], dsp_pc);
772 WriteLog("\n");
773 #endif  // DSP_DEBUG
774 //This isn't exactly right either--we don't know if it was the M68K or the GPU writing here...
775 // !!! FIX !!! [DONE]
776                         if (DSP_RUNNING)
777                         {
778                                 if (who == M68K)
779                                         m68k_end_timeslice();
780                                 else if (who == GPU)
781                                         gpu_releaseTimeslice();
782
783                                 FlushDSPPipeline();
784 //DSPDumpDisassembly();
785                         }
786                         break;
787                 }
788                 case 0x18:
789                         dsp_modulo = data;
790                         break;
791                 case 0x1C:
792                         dsp_div_control = data;
793                         break;
794 //              default:   // unaligned long read
795                                    //__asm int 3
796                 }
797                 return;
798         }
799
800 //We don't have to break this up like this! We CAN do 32 bit writes!
801 //      JaguarWriteWord(offset, (data>>16) & 0xFFFF, DSP);
802 //      JaguarWriteWord(offset+2, data & 0xFFFF, DSP);
803 //if (offset > 0xF1FFFF)
804 //      badWrite = true;
805         JaguarWriteLong(offset, data, who);
806 }
807
808 //
809 // Update the DSP register file pointers depending on REGPAGE bit
810 //
811 void DSPUpdateRegisterBanks(void)
812 {
813         int bank = (dsp_flags & REGPAGE);
814
815         if (dsp_flags & IMASK)
816                 bank = 0;                                                       // IMASK forces main bank to be bank 0
817
818         if (bank)
819                 dsp_reg = dsp_reg_bank_1, dsp_alternate_reg = dsp_reg_bank_0;
820         else
821                 dsp_reg = dsp_reg_bank_0, dsp_alternate_reg = dsp_reg_bank_1;
822 }
823
824 //
825 // Check for an handle any asserted DSP IRQs
826 //
827 void DSPHandleIRQs(void)
828 {
829         if (dsp_flags & IMASK)                                                  // Bail if we're already inside an interrupt
830                 return;
831
832         // Get the active interrupt bits (latches) & interrupt mask (enables)
833         uint32 bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
834                 mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
835
836 //      WriteLog("dsp: bits=%.2x mask=%.2x\n",bits,mask);
837         bits &= mask;
838
839         if (!bits)                                                                              // Bail if nothing is enabled
840                 return;
841
842         int which = 0;                                                                  // Determine which interrupt 
843         if (bits & 0x01)
844                 which = 0;
845         if (bits & 0x02)
846                 which = 1;
847         if (bits & 0x04)
848                 which = 2;
849         if (bits & 0x08)
850                 which = 3;
851         if (bits & 0x10)
852                 which = 4;
853         if (bits & 0x20)
854                 which = 5;
855
856 #ifdef DSP_DEBUG_IRQ
857         WriteLog("DSP: Generating interrupt #%i...\n", which);
858 #endif
859         dsp_flags |= IMASK;
860         DSPUpdateRegisterBanks();
861
862         // subqt  #4,r31                ; pre-decrement stack pointer 
863         // move  pc,r30                 ; address of interrupted code 
864         // store  r30,(r31)     ; store return address
865         dsp_reg[31] -= 4;
866         DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
867
868         // movei  #service_address,r30  ; pointer to ISR entry 
869         // jump  (r30)                                  ; jump to ISR 
870         // nop
871         dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
872         FlushDSPPipeline();
873 }
874
875 //
876 // Set the specified DSP IRQ line to a given state
877 //
878 void DSPSetIRQLine(int irqline, int state)
879 {
880 //NOTE: This doesn't take INT_LAT5 into account. !!! FIX !!!
881         uint32 mask = INT_LAT0 << irqline;
882         dsp_control &= ~mask;                                                   // Clear the latch bit
883
884         if (state)
885         {
886                 dsp_control |= mask;                                            // Set the latch bit
887                 DSPHandleIRQs();
888         }
889 }
890
891 void DSPInit(void)
892 {
893         memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
894         memory_malloc_secure((void **)&dsp_reg_bank_0, 32 * sizeof(int32), "DSP bank 0 regs");
895         memory_malloc_secure((void **)&dsp_reg_bank_1, 32 * sizeof(int32), "DSP bank 1 regs");
896
897         dsp_build_branch_condition_table();
898         DSPReset();
899 }
900
901 void DSPReset(void)
902 {
903         dsp_pc                            = 0x00F1B000;
904         dsp_acc                           = 0x00000000;
905         dsp_remain                        = 0x00000000;
906         dsp_modulo                        = 0xFFFFFFFF;
907         dsp_flags                         = 0x00040000;
908         dsp_matrix_control    = 0x00000000;
909         dsp_pointer_to_matrix = 0x00000000;
910         dsp_data_organization = 0xFFFFFFFF;
911         dsp_control                       = 0x00002000;                         // Report DSP version 2
912         dsp_div_control           = 0x00000000;
913         dsp_in_exec                       = 0;
914
915         dsp_reg = dsp_reg_bank_0;
916         dsp_alternate_reg = dsp_reg_bank_1;
917
918         for(int i=0; i<32; i++)
919                 dsp_reg[i] = dsp_alternate_reg[i] = 0x00000000;
920
921         CLR_ZNC;
922
923         dsp_reset_stats();
924         memset(dsp_ram_8, 0xFF, 0x2000);
925 }
926
927 void DSPDumpDisassembly(void)
928 {
929         char buffer[512];
930
931         WriteLog("\n---[DSP code at 00F1B000]---------------------------\n");
932         uint32 j = 0xF1B000;
933         while (j <= 0xF1CFFF)
934         {
935                 uint32 oldj = j;
936                 j += dasmjag(JAGUAR_DSP, buffer, j);
937                 WriteLog("\t%08X: %s\n", oldj, buffer);
938         }
939 }
940
941 void DSPDumpRegisters(void)
942 {
943 //Shoud add modulus, etc to dump here...
944         WriteLog("\n---[DSP flags: NCZ %d%d%d, DSP PC: %08X]------------\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_pc);
945         WriteLog("\nRegisters bank 0\n");
946         for(int j=0; j<8; j++)
947         {
948                 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
949                                                   (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
950                                                   (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
951                                                   (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
952                                                   (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
953         }
954         WriteLog("Registers bank 1\n");
955         for(int j=0; j<8; j++)
956         {
957                 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
958                                                   (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
959                                                   (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
960                                                   (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
961                                                   (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
962         }
963 }
964
965 void DSPDone(void)
966 {
967         int i, j;
968         WriteLog("DSP: Stopped at PC=%08X dsp_modulo=%08X (dsp %s running)\n", dsp_pc, dsp_modulo, (DSP_RUNNING ? "was" : "wasn't"));
969         WriteLog("DSP: %sin interrupt handler\n", (dsp_flags & IMASK ? "" : "not "));
970
971         // get the active interrupt bits 
972         int bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F);
973         // get the interrupt mask 
974         int mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
975
976         WriteLog("DSP: pending=%08X enabled=%08X\n", bits, mask);
977         WriteLog("\nRegisters bank 0\n");
978         for(int j=0; j<8; j++)
979         {
980                 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
981                                                   (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
982                                                   (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
983                                                   (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
984                                                   (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
985         }
986         WriteLog("\nRegisters bank 1\n");
987         for (j=0; j<8; j++)
988         {
989                 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
990                                                   (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
991                                                   (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
992                                                   (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
993                                                   (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
994
995         }
996
997         static char buffer[512];
998         j = DSP_WORK_RAM_BASE;
999         while (j <= 0xF1BFFF)
1000         {
1001                 uint32 oldj = j;
1002                 j += dasmjag(JAGUAR_DSP, buffer, j);
1003                 WriteLog("\t%08X: %s\n", oldj, buffer);
1004         }//*/
1005
1006         WriteLog("DSP opcodes use:\n");
1007         for (i=0;i<64;i++)
1008         {
1009                 if (dsp_opcode_use[i])
1010                         WriteLog("\t%s %i\n", dsp_opcode_str[i], dsp_opcode_use[i]);
1011         }//*/
1012
1013         memory_free(dsp_ram_8);
1014 }
1015
1016 //
1017 // DSP execution core
1018 //
1019 static bool R20Set = false, tripwire = false;
1020 static uint32 pcQueue[32], ptrPCQ = 0;
1021 void DSPExec(int32 cycles)
1022 {
1023 /*HACKS!!! ->   if (cycles != 1 && jaguar_mainRom_crc32 == 0xba74c3ed)
1024                 dsp_check_if_i2s_interrupt_needed();*/
1025
1026 #ifdef DSP_SINGLE_STEPPING
1027         if (dsp_control & 0x18)
1028         {
1029                 cycles = 1;
1030                 dsp_control &= ~0x10;
1031         }
1032 #endif
1033 //There is *no* good reason to do this here!
1034 //      DSPHandleIRQs();
1035         dsp_releaseTimeSlice_flag = 0;
1036         dsp_in_exec++;
1037
1038         while (cycles > 0 && DSP_RUNNING)
1039         {
1040 /*if (badWrite)
1041 {
1042         WriteLog("\nDSP: Encountered bad write in Atari Synth module. PC=%08X, R15=%08X\n", dsp_pc, dsp_reg[15]);
1043         for(int i=0; i<80; i+=4)
1044                 WriteLog("     %08X: %08X\n", dsp_reg[15]+i, JaguarReadLong(dsp_reg[15]+i));
1045         WriteLog("\n");
1046 }//*/
1047 /*if (dsp_pc == 0xF1B55E)
1048 {
1049         WriteLog("DSP: At $F1B55E--R15 = %08X at %u ms%s...\n", dsp_reg[15], SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1050 }//*/
1051 /*if (dsp_pc == 0xF1B7D2)       // Start here???
1052         doDSPDis = true;
1053 pcQueue[ptrPCQ++] = dsp_pc;
1054 ptrPCQ %= 32;*/
1055                 uint16 opcode = DSPReadWord(dsp_pc, DSP);
1056                 uint32 index = opcode >> 10;
1057                 dsp_opcode_first_parameter = (opcode >> 5) & 0x1F;
1058                 dsp_opcode_second_parameter = opcode & 0x1F;
1059                 dsp_pc += 2;
1060                 dsp_opcode[index]();
1061                 dsp_opcode_use[index]++;
1062                 cycles -= dsp_opcode_cycles[index];
1063 /*if (dsp_reg_bank_0[20] == 0xF1A100 & !R20Set)
1064 {
1065         WriteLog("DSP: R20 set to $F1A100 at %u ms%s...\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1066         R20Set = true;
1067 }
1068 if (dsp_reg_bank_0[20] != 0xF1A100 && R20Set)
1069 {
1070         WriteLog("DSP: R20 corrupted at %u ms from starting%s!\nAborting!\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1071         DSPDumpRegisters();
1072         DSPDumpDisassembly();
1073         exit(1);
1074 }
1075 if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFE) && !tripwire)
1076 {
1077         char buffer[512];
1078         WriteLog("DSP: Jumping outside of DSP RAM at %u ms. Register dump:\n", SDL_GetTicks());
1079         DSPDumpRegisters();
1080         tripwire = true;
1081         WriteLog("\nBacktrace:\n");
1082         for(int i=0; i<32; i++)
1083         {
1084                 dasmjag(JAGUAR_DSP, buffer, pcQueue[(ptrPCQ + i) % 32]);
1085                 WriteLog("\t%08X: %s\n", pcQueue[(ptrPCQ + i) % 32], buffer);
1086         }
1087         WriteLog("\n");
1088 }*/
1089         }
1090
1091         dsp_in_exec--;
1092 }
1093
1094 //
1095 // DSP opcode handlers
1096 //
1097
1098 // There is a problem here with interrupt handlers the JUMP and JR instructions that
1099 // can cause trouble because an interrupt can occur *before* the instruction following the
1100 // jump can execute... !!! FIX !!!
1101 static void dsp_opcode_jump(void)
1102 {
1103 #ifdef DSP_DIS_JUMP
1104 char * condition[32] =
1105 {       "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1106         "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1107         "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1108         "???", "???", "???", "F" };
1109         if (doDSPDis)
1110                 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);
1111 #endif
1112         // normalize flags
1113 /*      dsp_flag_c=dsp_flag_c?1:0;
1114         dsp_flag_z=dsp_flag_z?1:0;
1115         dsp_flag_n=dsp_flag_n?1:0;*/
1116         // KLUDGE: Used by BRANCH_CONDITION
1117         uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1118
1119         if (BRANCH_CONDITION(IMM_2))
1120         {
1121 #ifdef DSP_DIS_JUMP
1122         if (doDSPDis)
1123                 WriteLog("Branched!\n");
1124 #endif
1125                 uint32 delayed_pc = RM;
1126                 DSPExec(1);
1127                 dsp_pc = delayed_pc;
1128         }
1129 #ifdef DSP_DIS_JUMP
1130         else
1131                 if (doDSPDis)
1132                         WriteLog("Branch NOT taken.\n");
1133 #endif
1134 }
1135
1136 static void dsp_opcode_jr(void)
1137 {
1138 #ifdef DSP_DIS_JR
1139 char * condition[32] =
1140 {       "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1141         "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1142         "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1143         "???", "???", "???", "F" };
1144         if (doDSPDis)
1145                 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);
1146 #endif
1147         // normalize flags
1148 /*      dsp_flag_c=dsp_flag_c?1:0;
1149         dsp_flag_z=dsp_flag_z?1:0;
1150         dsp_flag_n=dsp_flag_n?1:0;*/
1151         // KLUDGE: Used by BRANCH_CONDITION
1152         uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1153
1154         if (BRANCH_CONDITION(IMM_2))
1155         {
1156 #ifdef DSP_DIS_JR
1157         if (doDSPDis)
1158                 WriteLog("Branched!\n");
1159 #endif
1160                 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1);             // Sign extend IMM_1
1161                 int32 delayed_pc = dsp_pc + (offset * 2);
1162                 DSPExec(1);
1163                 dsp_pc = delayed_pc;
1164         }
1165 #ifdef DSP_DIS_JR
1166         else
1167                 if (doDSPDis)
1168                         WriteLog("Branch NOT taken.\n");
1169 #endif
1170 }
1171
1172 static void dsp_opcode_add(void)
1173 {
1174 #ifdef DSP_DIS_ADD
1175         if (doDSPDis)
1176                 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);
1177 #endif
1178         UINT32 res = RN + RM;
1179         SET_ZNC_ADD(RN, RM, res);
1180         RN = res;
1181 #ifdef DSP_DIS_ADD
1182         if (doDSPDis)
1183                 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);
1184 #endif
1185 }
1186
1187 static void dsp_opcode_addc(void)
1188 {
1189 #ifdef DSP_DIS_ADDC
1190         if (doDSPDis)
1191                 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);
1192 #endif
1193         UINT32 res = RN + RM + dsp_flag_c;
1194         UINT32 carry = dsp_flag_c;
1195 //      SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1196         SET_ZNC_ADD(RN + carry, RM, res);
1197 //      SET_ZNC_ADD(RN, RM + carry, res);
1198         RN = res;
1199 #ifdef DSP_DIS_ADDC
1200         if (doDSPDis)
1201                 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);
1202 #endif
1203 }
1204
1205 static void dsp_opcode_addq(void)
1206 {
1207 #ifdef DSP_DIS_ADDQ
1208         if (doDSPDis)
1209                 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);
1210 #endif
1211         UINT32 r1 = dsp_convert_zero[IMM_1];
1212         UINT32 res = RN + r1;
1213         CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1214         RN = res;
1215 #ifdef DSP_DIS_ADDQ
1216         if (doDSPDis)
1217                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1218 #endif
1219 }
1220
1221 static void dsp_opcode_sub(void)
1222 {
1223 #ifdef DSP_DIS_SUB
1224         if (doDSPDis)
1225                 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);
1226 #endif
1227         UINT32 res = RN - RM;
1228         SET_ZNC_SUB(RN, RM, res);
1229         RN = res;
1230 #ifdef DSP_DIS_SUB
1231         if (doDSPDis)
1232                 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);
1233 #endif
1234 }
1235
1236 static void dsp_opcode_subc(void)
1237 {
1238 #ifdef DSP_DIS_SUBC
1239         if (doDSPDis)
1240                 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);
1241 #endif
1242         UINT32 res = RN - RM - dsp_flag_c;
1243         UINT32 borrow = dsp_flag_c;
1244         SET_ZNC_SUB(RN - borrow, RM, res);
1245         RN = res;
1246 #ifdef DSP_DIS_SUBC
1247         if (doDSPDis)
1248                 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);
1249 #endif
1250 }
1251
1252 static void dsp_opcode_subq(void)
1253 {
1254 #ifdef DSP_DIS_SUBQ
1255         if (doDSPDis)
1256                 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);
1257 #endif
1258         UINT32 r1 = dsp_convert_zero[IMM_1];
1259         UINT32 res = RN - r1;
1260         SET_ZNC_SUB(RN, r1, res);
1261         RN = res;
1262 #ifdef DSP_DIS_SUBQ
1263         if (doDSPDis)
1264                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1265 #endif
1266 }
1267
1268 static void dsp_opcode_cmp(void)
1269 {
1270 #ifdef DSP_DIS_CMP
1271         if (doDSPDis)
1272                 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);
1273 #endif
1274         UINT32 res = RN - RM;
1275         SET_ZNC_SUB(RN, RM, res);
1276 #ifdef DSP_DIS_CMP
1277         if (doDSPDis)
1278                 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1279 #endif
1280 }
1281
1282 static void dsp_opcode_cmpq(void)
1283 {
1284         static int32 sqtable[32] =
1285                 { 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 };
1286 #ifdef DSP_DIS_CMPQ
1287         if (doDSPDis)
1288                 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);
1289 #endif
1290         UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1291         UINT32 res = RN - r1;
1292         SET_ZNC_SUB(RN, r1, res);
1293 #ifdef DSP_DIS_CMPQ
1294         if (doDSPDis)
1295                 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1296 #endif
1297 }
1298
1299 static void dsp_opcode_and(void)
1300 {
1301 #ifdef DSP_DIS_AND
1302         if (doDSPDis)
1303                 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);
1304 #endif
1305         RN = RN & RM;
1306         SET_ZN(RN);
1307 #ifdef DSP_DIS_AND
1308         if (doDSPDis)
1309                 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);
1310 #endif
1311 }
1312
1313 static void dsp_opcode_or(void)
1314 {
1315 #ifdef DSP_DIS_OR
1316         if (doDSPDis)
1317                 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);
1318 #endif
1319         RN = RN | RM;
1320         SET_ZN(RN);
1321 #ifdef DSP_DIS_OR
1322         if (doDSPDis)
1323                 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);
1324 #endif
1325 }
1326
1327 static void dsp_opcode_xor(void)
1328 {
1329 #ifdef DSP_DIS_XOR
1330         if (doDSPDis)
1331                 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);
1332 #endif
1333         RN = RN ^ RM;
1334         SET_ZN(RN);
1335 #ifdef DSP_DIS_XOR
1336         if (doDSPDis)
1337                 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);
1338 #endif
1339 }
1340
1341 static void dsp_opcode_not(void)
1342 {
1343 #ifdef DSP_DIS_NOT
1344         if (doDSPDis)
1345                 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);
1346 #endif
1347         RN = ~RN;
1348         SET_ZN(RN);
1349 #ifdef DSP_DIS_NOT
1350         if (doDSPDis)
1351                 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);
1352 #endif
1353 }
1354
1355 static void dsp_opcode_move_pc(void)
1356 {
1357         RN = dsp_pc - 2;
1358 }
1359
1360 static void dsp_opcode_store_r14_indexed(void)
1361 {
1362 #ifdef DSP_DIS_STORE14I
1363         if (doDSPDis)
1364                 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));
1365 #endif
1366         DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1367 }
1368
1369 static void dsp_opcode_store_r15_indexed(void)
1370 {
1371 #ifdef DSP_DIS_STORE15I
1372         if (doDSPDis)
1373                 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));
1374 #endif
1375         DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1376 }
1377
1378 static void dsp_opcode_load_r14_ri(void)
1379 {
1380 #ifdef DSP_DIS_LOAD14R
1381         if (doDSPDis)
1382                 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);
1383 #endif
1384         RN = DSPReadLong(dsp_reg[14] + RM, DSP);
1385 #ifdef DSP_DIS_LOAD14R
1386         if (doDSPDis)
1387                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1388 #endif
1389 }
1390
1391 static void dsp_opcode_load_r15_ri(void)
1392 {
1393 #ifdef DSP_DIS_LOAD15R
1394         if (doDSPDis)
1395                 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);
1396 #endif
1397         RN = DSPReadLong(dsp_reg[15] + RM, DSP);
1398 #ifdef DSP_DIS_LOAD15R
1399         if (doDSPDis)
1400                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1401 #endif
1402 }
1403
1404 static void dsp_opcode_store_r14_ri(void)
1405 {
1406         DSPWriteLong(dsp_reg[14] + RM, RN, DSP);
1407 }
1408
1409 static void dsp_opcode_store_r15_ri(void)
1410 {
1411         DSPWriteLong(dsp_reg[15] + RM, RN, DSP);
1412 }
1413
1414 static void dsp_opcode_nop(void)
1415 {
1416 #ifdef DSP_DIS_NOP
1417         if (doDSPDis)
1418                 WriteLog("%06X: NOP    [NCZ:%u%u%u]\n", dsp_pc-2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
1419 #endif
1420 }
1421
1422 static void dsp_opcode_storeb(void)
1423 {
1424 #ifdef DSP_DIS_STOREB
1425         if (doDSPDis)
1426                 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);
1427 #endif
1428         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1429                 DSPWriteLong(RM, RN & 0xFF, DSP);
1430         else
1431                 JaguarWriteByte(RM, RN, DSP);
1432 }
1433
1434 static void dsp_opcode_storew(void)
1435 {
1436 #ifdef DSP_DIS_STOREW
1437         if (doDSPDis)
1438                 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);
1439 #endif
1440         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1441                 DSPWriteLong(RM, RN & 0xFFFF, DSP);
1442         else
1443                 JaguarWriteWord(RM, RN, DSP);
1444 }
1445
1446 static void dsp_opcode_store(void)
1447 {
1448 #ifdef DSP_DIS_STORE
1449         if (doDSPDis)
1450                 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);
1451 #endif
1452         DSPWriteLong(RM, RN, DSP);
1453 }
1454
1455 static void dsp_opcode_loadb(void)
1456 {
1457 #ifdef DSP_DIS_LOADB
1458         if (doDSPDis)
1459                 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);
1460 #endif
1461         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1462                 RN = DSPReadLong(RM, DSP) & 0xFF;
1463         else
1464                 RN = JaguarReadByte(RM, DSP);
1465 #ifdef DSP_DIS_LOADB
1466         if (doDSPDis)
1467                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1468 #endif
1469 }
1470
1471 static void dsp_opcode_loadw(void)
1472 {
1473 #ifdef DSP_DIS_LOADW
1474         if (doDSPDis)
1475                 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);
1476 #endif
1477         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1478                 RN = DSPReadLong(RM, DSP) & 0xFFFF;
1479         else
1480                 RN = JaguarReadWord(RM, DSP);
1481 #ifdef DSP_DIS_LOADW
1482         if (doDSPDis)
1483                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1484 #endif
1485 }
1486
1487 static void dsp_opcode_load(void)
1488 {
1489 #ifdef DSP_DIS_LOAD
1490         if (doDSPDis)
1491                 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);
1492 #endif
1493         RN = DSPReadLong(RM, DSP);
1494 #ifdef DSP_DIS_LOAD
1495         if (doDSPDis)
1496                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1497 #endif
1498 }
1499
1500 static void dsp_opcode_load_r14_indexed(void)
1501 {
1502 #ifdef DSP_DIS_LOAD14I
1503         if (doDSPDis)
1504                 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);
1505 #endif
1506         RN = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), DSP);
1507 #ifdef DSP_DIS_LOAD14I
1508         if (doDSPDis)
1509                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1510 #endif
1511 }
1512
1513 static void dsp_opcode_load_r15_indexed(void)
1514 {
1515 #ifdef DSP_DIS_LOAD15I
1516         if (doDSPDis)
1517                 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);
1518 #endif
1519         RN = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), DSP);
1520 #ifdef DSP_DIS_LOAD15I
1521         if (doDSPDis)
1522                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1523 #endif
1524 }
1525
1526 static void dsp_opcode_movei(void)
1527 {
1528 #ifdef DSP_DIS_MOVEI
1529         if (doDSPDis)
1530                 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);
1531 #endif
1532         // This instruction is followed by 32-bit value in LSW / MSW format...
1533         RN = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
1534         dsp_pc += 4;
1535 #ifdef DSP_DIS_MOVEI
1536         if (doDSPDis)
1537                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1538 #endif
1539 }
1540
1541 static void dsp_opcode_moveta(void)
1542 {
1543 #ifdef DSP_DIS_MOVETA
1544         if (doDSPDis)
1545                 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);
1546 #endif
1547         ALTERNATE_RN = RM;
1548 #ifdef DSP_DIS_MOVETA
1549         if (doDSPDis)
1550                 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);
1551 #endif
1552 }
1553
1554 static void dsp_opcode_movefa(void)
1555 {
1556 #ifdef DSP_DIS_MOVEFA
1557         if (doDSPDis)
1558                 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);
1559 #endif
1560         RN = ALTERNATE_RM;
1561 #ifdef DSP_DIS_MOVEFA
1562         if (doDSPDis)
1563                 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);
1564 #endif
1565 }
1566
1567 static void dsp_opcode_move(void)
1568 {
1569 #ifdef DSP_DIS_MOVE
1570         if (doDSPDis)
1571                 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);
1572 #endif
1573         RN = RM;
1574 #ifdef DSP_DIS_MOVE
1575         if (doDSPDis)
1576                 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);
1577 #endif
1578 }
1579
1580 static void dsp_opcode_moveq(void)
1581 {
1582 #ifdef DSP_DIS_MOVEQ
1583         if (doDSPDis)
1584                 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);
1585 #endif
1586         RN = IMM_1;
1587 #ifdef DSP_DIS_MOVEQ
1588         if (doDSPDis)
1589                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1590 #endif
1591 }
1592
1593 static void dsp_opcode_resmac(void)
1594 {
1595 #ifdef DSP_DIS_RESMAC
1596         if (doDSPDis)
1597                 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));
1598 #endif
1599         RN = (uint32)dsp_acc;
1600 #ifdef DSP_DIS_RESMAC
1601         if (doDSPDis)
1602                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1603 #endif
1604 }
1605
1606 static void dsp_opcode_imult(void)
1607 {
1608 #ifdef DSP_DIS_IMULT
1609         if (doDSPDis)
1610                 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);
1611 #endif
1612         RN = (int16)RN * (int16)RM;
1613         SET_ZN(RN);
1614 #ifdef DSP_DIS_IMULT
1615         if (doDSPDis)
1616                 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);
1617 #endif
1618 }
1619
1620 static void dsp_opcode_mult(void)
1621 {
1622 #ifdef DSP_DIS_MULT
1623         if (doDSPDis)
1624                 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);
1625 #endif
1626         RN = (uint16)RM * (uint16)RN;
1627         SET_ZN(RN);
1628 #ifdef DSP_DIS_MULT
1629         if (doDSPDis)
1630                 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);
1631 #endif
1632 }
1633
1634 static void dsp_opcode_bclr(void)
1635 {
1636 #ifdef DSP_DIS_BCLR
1637         if (doDSPDis)
1638                 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);
1639 #endif
1640         UINT32 res = RN & ~(1 << IMM_1);
1641         RN = res;
1642         SET_ZN(res);
1643 #ifdef DSP_DIS_BCLR
1644         if (doDSPDis)
1645                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1646 #endif
1647 }
1648
1649 static void dsp_opcode_btst(void)
1650 {
1651 #ifdef DSP_DIS_BTST
1652         if (doDSPDis)
1653                 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);
1654 #endif
1655         dsp_flag_z = (~RN >> IMM_1) & 1;
1656 #ifdef DSP_DIS_BTST
1657         if (doDSPDis)
1658                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1659 #endif
1660 }
1661
1662 static void dsp_opcode_bset(void)
1663 {
1664 #ifdef DSP_DIS_BSET
1665         if (doDSPDis)
1666                 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);
1667 #endif
1668         UINT32 res = RN | (1 << IMM_1);
1669         RN = res;
1670         SET_ZN(res);
1671 #ifdef DSP_DIS_BSET
1672         if (doDSPDis)
1673                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1674 #endif
1675 }
1676
1677 static void dsp_opcode_subqt(void)
1678 {
1679 #ifdef DSP_DIS_SUBQT
1680         if (doDSPDis)
1681                 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);
1682 #endif
1683         RN -= dsp_convert_zero[IMM_1];
1684 #ifdef DSP_DIS_SUBQT
1685         if (doDSPDis)
1686                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1687 #endif
1688 }
1689
1690 static void dsp_opcode_addqt(void)
1691 {
1692 #ifdef DSP_DIS_ADDQT
1693         if (doDSPDis)
1694                 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);
1695 #endif
1696         RN += dsp_convert_zero[IMM_1];
1697 #ifdef DSP_DIS_ADDQT
1698         if (doDSPDis)
1699                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1700 #endif
1701 }
1702
1703 static void dsp_opcode_imacn(void)
1704 {
1705 #ifdef DSP_DIS_IMACN
1706         if (doDSPDis)
1707                 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);
1708 #endif
1709         int32 res = (int16)RM * (int16)RN;
1710         dsp_acc += (int64)res;
1711 //Should we AND the result to fit into 40 bits here???
1712 #ifdef DSP_DIS_IMACN
1713         if (doDSPDis)
1714                 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));
1715 #endif
1716
1717
1718 static void dsp_opcode_mtoi(void)
1719 {
1720         RN = (((INT32)RM >> 8) & 0xFF800000) | (RM & 0x007FFFFF);
1721         SET_ZN(RN);
1722 }
1723
1724 static void dsp_opcode_normi(void)
1725 {
1726         uint32 _Rm = RM;
1727         uint32 res = 0;
1728
1729         if (_Rm)
1730         {
1731                 while ((_Rm & 0xffc00000) == 0)
1732                 {
1733                         _Rm <<= 1;
1734                         res--;
1735                 }
1736                 while ((_Rm & 0xff800000) != 0)
1737                 {
1738                         _Rm >>= 1;
1739                         res++;
1740                 }
1741         }
1742         RN = res;
1743         SET_ZN(RN);
1744 }
1745
1746 static void dsp_opcode_mmult(void)
1747 {
1748         int count       = dsp_matrix_control&0x0f;
1749         uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
1750         int64 accum = 0;
1751         uint32 res;
1752
1753         if (!(dsp_matrix_control & 0x10))
1754         {
1755                 for (int i = 0; i < count; i++)
1756                 { 
1757                         int16 a;
1758                         if (i&0x01)
1759                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1760                         else
1761                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1762                         int16 b=((int16)DSPReadWord(addr + 2, DSP));
1763                         accum += a*b;
1764                         addr += 4;
1765                 }
1766         }
1767         else
1768         {
1769                 for (int i = 0; i < count; i++)
1770                 {
1771                         int16 a;
1772                         if (i&0x01)
1773                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1774                         else
1775                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1776                         int16 b=((int16)DSPReadWord(addr + 2, DSP));
1777                         accum += a*b;
1778                         addr += 4 * count;
1779                 }
1780         }
1781         RN = res = (int32)accum;
1782         // carry flag to do
1783 //NOTE: The flags are set based upon the last add/multiply done...
1784         SET_ZN(RN);
1785 }
1786
1787 static void dsp_opcode_abs(void)
1788 {
1789         uint32 _Rn = RN;
1790         uint32 res;
1791         
1792         if (_Rn == 0x80000000)
1793                 dsp_flag_n = 1;
1794         else
1795         {
1796                 dsp_flag_c = ((_Rn & 0x80000000) >> 31);
1797                 res = RN = (_Rn & 0x80000000 ? -_Rn : _Rn);
1798                 CLR_ZN; SET_Z(res);
1799         }
1800 }
1801
1802 static void dsp_opcode_div(void)
1803 {
1804         uint32 _Rm=RM;
1805         uint32 _Rn=RN;
1806
1807         if (_Rm)
1808         {
1809                 if (dsp_div_control & 1)
1810                 {
1811                         dsp_remain = (((uint64)_Rn) << 16) % _Rm;
1812                         if (dsp_remain&0x80000000)
1813                                 dsp_remain-=_Rm;
1814                         RN = (((uint64)_Rn) << 16) / _Rm;
1815                 }
1816                 else
1817                 {
1818                         dsp_remain = _Rn % _Rm;
1819                         if (dsp_remain&0x80000000)
1820                                 dsp_remain-=_Rm;
1821                         RN/=_Rm;
1822                 }
1823         }
1824         else
1825                 RN=0xffffffff;
1826 }
1827
1828 static void dsp_opcode_imultn(void)
1829 {
1830 #ifdef DSP_DIS_IMULTN
1831         if (doDSPDis)
1832                 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);
1833 #endif
1834         // This is OK, since this multiply won't overflow 32 bits...
1835         int32 res = (int32)((int16)RN * (int16)RM);
1836         dsp_acc = (int64)res;
1837         SET_ZN(res);
1838 #ifdef DSP_DIS_IMULTN
1839         if (doDSPDis)
1840                 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));
1841 #endif
1842 }
1843
1844 static void dsp_opcode_neg(void)
1845 {
1846 #ifdef DSP_DIS_NEG
1847         if (doDSPDis)
1848                 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);
1849 #endif
1850         UINT32 res = -RN;
1851         SET_ZNC_SUB(0, RN, res);
1852         RN = res;
1853 #ifdef DSP_DIS_NEG
1854         if (doDSPDis)
1855                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1856 #endif
1857 }
1858
1859 static void dsp_opcode_shlq(void)
1860 {
1861 #ifdef DSP_DIS_SHLQ
1862         if (doDSPDis)
1863                 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);
1864 #endif
1865         INT32 r1 = 32 - IMM_1;
1866         UINT32 res = RN << r1;
1867         SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
1868         RN = res;
1869 #ifdef DSP_DIS_SHLQ
1870         if (doDSPDis)
1871                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1872 #endif
1873 }
1874
1875 static void dsp_opcode_shrq(void)
1876 {
1877 #ifdef DSP_DIS_SHRQ
1878         if (doDSPDis)
1879                 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);
1880 #endif
1881         INT32 r1 = dsp_convert_zero[IMM_1];
1882         UINT32 res = RN >> r1;
1883         SET_ZN(res); dsp_flag_c = RN & 1;
1884         RN = res;
1885 #ifdef DSP_DIS_SHRQ
1886         if (doDSPDis)
1887                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1888 #endif
1889 }
1890
1891 static void dsp_opcode_ror(void)
1892 {
1893 #ifdef DSP_DIS_ROR
1894         if (doDSPDis)
1895                 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);
1896 #endif
1897         UINT32 r1 = RM & 0x1F;
1898         UINT32 res = (RN >> r1) | (RN << (32 - r1));
1899         SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
1900         RN = res;
1901 #ifdef DSP_DIS_ROR
1902         if (doDSPDis)
1903                 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);
1904 #endif
1905 }
1906
1907 static void dsp_opcode_rorq(void)
1908 {
1909 #ifdef DSP_DIS_RORQ
1910         if (doDSPDis)
1911                 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);
1912 #endif
1913         UINT32 r1 = dsp_convert_zero[IMM_1 & 0x1F];
1914         UINT32 r2 = RN;
1915         UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
1916         RN = res;
1917         SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
1918 #ifdef DSP_DIS_RORQ
1919         if (doDSPDis)
1920                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1921 #endif
1922 }
1923
1924 static void dsp_opcode_sha(void)
1925 {
1926         int32 sRm=(int32)RM;
1927         uint32 _Rn=RN;
1928
1929         if (sRm<0)
1930         {
1931                 uint32 shift=-sRm;
1932                 if (shift>=32) shift=32;
1933                 dsp_flag_c=(_Rn&0x80000000)>>31;
1934                 while (shift)
1935                 {
1936                         _Rn<<=1;
1937                         shift--;
1938                 }
1939         }
1940         else
1941         {
1942                 uint32 shift=sRm;
1943                 if (shift>=32) shift=32;
1944                 dsp_flag_c=_Rn&0x1;
1945                 while (shift)
1946                 {
1947                         _Rn=((int32)_Rn)>>1;
1948                         shift--;
1949                 }
1950         }
1951         RN = _Rn;
1952         SET_ZN(RN);
1953 }
1954
1955 static void dsp_opcode_sharq(void)
1956 {
1957 #ifdef DSP_DIS_SHARQ
1958         if (doDSPDis)
1959                 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);
1960 #endif
1961         UINT32 res = (INT32)RN >> dsp_convert_zero[IMM_1];
1962         SET_ZN(res); dsp_flag_c = RN & 0x01;
1963         RN = res;
1964 #ifdef DSP_DIS_SHARQ
1965         if (doDSPDis)
1966                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1967 #endif
1968 }
1969
1970 static void dsp_opcode_sh(void)
1971 {
1972         int32 sRm=(int32)RM;
1973         uint32 _Rn=RN;
1974
1975         if (sRm<0)
1976         {
1977                 uint32 shift=(-sRm);
1978                 if (shift>=32) shift=32;
1979                 dsp_flag_c=(_Rn&0x80000000)>>31;
1980                 while (shift)
1981                 {
1982                         _Rn<<=1;
1983                         shift--;
1984                 }
1985         }
1986         else
1987         {
1988                 uint32 shift=sRm;
1989                 if (shift>=32) shift=32;
1990                 dsp_flag_c=_Rn&0x1;
1991                 while (shift)
1992                 {
1993                         _Rn>>=1;
1994                         shift--;
1995                 }
1996         }
1997         RN = _Rn;
1998         SET_ZN(RN);
1999 }
2000
2001 void dsp_opcode_addqmod(void)
2002 {
2003 #ifdef DSP_DIS_ADDQMOD
2004         if (doDSPDis)
2005                 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);
2006 #endif
2007         UINT32 r1 = dsp_convert_zero[IMM_1];
2008         UINT32 r2 = RN;
2009         UINT32 res = r2 + r1;
2010         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2011         RN = res;
2012         SET_ZNC_ADD(r2, r1, res);
2013 #ifdef DSP_DIS_ADDQMOD
2014         if (doDSPDis)
2015                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2016 #endif
2017 }
2018
2019 void dsp_opcode_subqmod(void)   
2020 {
2021         UINT32 r1 = dsp_convert_zero[IMM_1];
2022         UINT32 r2 = RN;
2023         UINT32 res = r2 - r1;
2024         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2025         RN = res;
2026         
2027         SET_ZNC_SUB(r2, r1, res);
2028 }
2029
2030 void dsp_opcode_mirror(void)    
2031 {
2032         UINT32 r1 = RN;
2033         RN = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
2034         SET_ZN(RN);
2035 }
2036
2037 void dsp_opcode_sat32s(void)            
2038 {
2039         INT32 r2 = (UINT32)RN;
2040         INT32 temp = dsp_acc >> 32;
2041         UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
2042         RN = res;
2043         SET_ZN(res);
2044 }
2045
2046 void dsp_opcode_sat16s(void)            
2047 {
2048         INT32 r2 = RN;
2049         UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
2050         RN = res;
2051         SET_ZN(res);
2052 }
2053
2054 //
2055 // New pipelined DSP core
2056 //
2057
2058 static void DSP_abs(void);
2059 static void DSP_add(void);
2060 static void DSP_addc(void);
2061 static void DSP_addq(void);
2062 static void DSP_addqmod(void);  
2063 static void DSP_addqt(void);
2064 static void DSP_and(void);
2065 static void DSP_bclr(void);
2066 static void DSP_bset(void);
2067 static void DSP_btst(void);
2068 static void DSP_cmp(void);
2069 static void DSP_cmpq(void);
2070 static void DSP_div(void);
2071 static void DSP_imacn(void);
2072 static void DSP_imult(void);
2073 static void DSP_imultn(void);
2074 static void DSP_illegal(void);
2075 static void DSP_jr(void);
2076 static void DSP_jump(void);
2077 static void DSP_load(void);
2078 static void DSP_loadb(void);
2079 static void DSP_loadw(void);
2080 static void DSP_load_r14_i(void);
2081 static void DSP_load_r14_r(void);
2082 static void DSP_load_r15_i(void);
2083 static void DSP_load_r15_r(void);
2084 static void DSP_mirror(void);   
2085 static void DSP_mmult(void);
2086 static void DSP_move(void);
2087 static void DSP_movefa(void);
2088 static void DSP_movei(void);
2089 static void DSP_movepc(void);
2090 static void DSP_moveq(void);
2091 static void DSP_moveta(void);
2092 static void DSP_mtoi(void);
2093 static void DSP_mult(void);
2094 static void DSP_neg(void);
2095 static void DSP_nop(void);
2096 static void DSP_normi(void);
2097 static void DSP_not(void);
2098 static void DSP_or(void);
2099 static void DSP_resmac(void);
2100 static void DSP_ror(void);
2101 static void DSP_rorq(void);
2102 static void DSP_sat16s(void);   
2103 static void DSP_sat32s(void);   
2104 static void DSP_sh(void);
2105 static void DSP_sha(void);
2106 static void DSP_sharq(void);
2107 static void DSP_shlq(void);
2108 static void DSP_shrq(void);
2109 static void DSP_store(void);
2110 static void DSP_storeb(void);
2111 static void DSP_storew(void);
2112 static void DSP_store_r14_i(void);
2113 static void DSP_store_r14_r(void);
2114 static void DSP_store_r15_i(void);
2115 static void DSP_store_r15_r(void);
2116 static void DSP_sub(void);
2117 static void DSP_subc(void);
2118 static void DSP_subq(void);
2119 static void DSP_subqmod(void);  
2120 static void DSP_subqt(void);
2121 static void DSP_xor(void);
2122
2123 void (* DSPOpcode[64])() =
2124 {       
2125         DSP_add,                        DSP_addc,                       DSP_addq,                       DSP_addqt,
2126         DSP_sub,                        DSP_subc,                       DSP_subq,                       DSP_subqt,
2127         DSP_neg,                        DSP_and,                        DSP_or,                         DSP_xor,
2128         DSP_not,                        DSP_btst,                       DSP_bset,                       DSP_bclr,
2129
2130         DSP_mult,                       DSP_imult,                      DSP_imultn,                     DSP_resmac,
2131         DSP_imacn,                      DSP_div,                        DSP_abs,                        DSP_sh,
2132         DSP_shlq,                       DSP_shrq,                       DSP_sha,                        DSP_sharq,
2133         DSP_ror,                        DSP_rorq,                       DSP_cmp,                        DSP_cmpq,
2134
2135         DSP_subqmod,            DSP_sat16s,                     DSP_move,                       DSP_moveq,
2136         DSP_moveta,                     DSP_movefa,                     DSP_movei,                      DSP_loadb,
2137         DSP_loadw,                      DSP_load,                       DSP_sat32s,                     DSP_load_r14_i,
2138         DSP_load_r15_i,         DSP_storeb,                     DSP_storew,                     DSP_store,
2139
2140         DSP_mirror,                     DSP_store_r14_i,        DSP_store_r15_i,        DSP_movepc,
2141         DSP_jump,                       DSP_jr,                         DSP_mmult,                      DSP_mtoi,
2142         DSP_normi,                      DSP_nop,                        DSP_load_r14_r,         DSP_load_r15_r,
2143         DSP_store_r14_r,        DSP_store_r15_r,        DSP_illegal,            DSP_addqmod
2144 };
2145
2146 bool readAffected[64][2] =
2147 {
2148         { true,  true}, { true,  true}, {false,  true}, {false,  true},
2149         { true,  true}, { true,  true}, {false,  true}, {false,  true},
2150         {false,  true}, { true,  true}, { true,  true}, { true,  true},
2151         {false,  true}, {false,  true}, {false,  true}, {false,  true},
2152
2153         { true,  true}, { true,  true}, { true,  true}, {false,  true},
2154         { true,  true}, { true,  true}, {false,  true}, { true,  true},
2155         {false,  true}, {false,  true}, { true,  true}, {false,  true},
2156         { true,  true}, {false,  true}, { true,  true}, {false,  true},
2157
2158         {false,  true}, {false,  true}, { true, false}, {false, false},
2159         { true, false}, {false, false}, {false, false}, { true, false},
2160         { true, false}, { true, false}, {false,  true}, { true, false},
2161         { true, false}, { true,  true}, { true,  true}, { true,  true},
2162
2163         {false,  true}, { true,  true}, { true,  true}, {false,  true},
2164         { true, false}, { true, false}, { true,  true}, { true, false},
2165         { true, false}, {false, false}, { true, false}, { true, false},
2166         { true,  true}, { true,  true}, {false, false}, {false,  true}
2167 };
2168
2169 bool affectsScoreboard[64] =
2170 {
2171          true,  true,  true,  true,
2172          true,  true,  true,  true,
2173          true,  true,  true,  true,
2174          true, false,  true,  true,
2175
2176          true,  true, false,  true,
2177         false,  true,  true,  true,
2178          true,  true,  true,  true,
2179          true,  true, false, false,
2180
2181          true,  true,  true,  true,
2182         false,  true,  true,  true,
2183          true,  true,  true,  true,
2184          true, false, false, false,
2185
2186          true, false, false,  true,
2187         false, false,  true,  true,
2188          true, false,  true,  true,
2189         false, false, false,  true
2190 };
2191
2192 // Pipeline structures
2193
2194 struct PipelineStage
2195 {
2196         uint16 instruction;
2197         uint8 opcode, operand1, operand2;
2198         uint32 reg1, reg2, areg1, areg2;
2199         uint32 result;
2200         uint8 writebackRegister;
2201 };
2202
2203 bool scoreboard[32];
2204
2205 uint8 plPtrFetch, plPtrRead, plPtrExec, plPtrWrite;
2206
2207 #define PIPELINE_STALL          64                                              // Set to # of opcodes + 1
2208
2209 PipelineStage pipeline[4];
2210
2211 void FlushDSPPipeline(void)
2212 {
2213         plPtrFetch = 3, plPtrRead = 2, plPtrExec = 1, plPtrWrite = 0;
2214
2215         for(int i=0; i<4; i++)
2216                 pipeline[i].opcode = PIPELINE_STALL;
2217
2218         for(int i=0; i<32; i++)
2219                 scoreboard[i] = false;
2220 }
2221
2222 //
2223 // New pipelined DSP execution core
2224 //
2225 void DSPExecP(int32 cycles)
2226 {
2227 //      bool inhibitFetch = false;
2228
2229         dsp_releaseTimeSlice_flag = 0;
2230         dsp_in_exec++;
2231
2232         while (cycles > 0 && DSP_RUNNING)
2233         {
2234 WriteLog("DSPExecP: Pipeline status...\n");
2235 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);
2236 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);
2237 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);
2238 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);
2239 WriteLog("  --> Scoreboard: ");
2240 for(int i=0; i<32; i++)
2241         WriteLog("%s ", scoreboard[i] ? "T" : "F");
2242 WriteLog("\n");
2243                 // Stage 1: Instruction fetch
2244 //              if (!inhibitFetch)
2245 //              {
2246                 pipeline[plPtrFetch].instruction = DSPReadWord(dsp_pc, DSP);
2247                 pipeline[plPtrFetch].opcode = pipeline[plPtrFetch].instruction >> 10;
2248                 pipeline[plPtrFetch].operand1 = (pipeline[plPtrFetch].instruction >> 5) & 0x1F;
2249                 pipeline[plPtrFetch].operand2 = pipeline[plPtrFetch].instruction & 0x1F;
2250                 if (pipeline[plPtrFetch].opcode == 38)
2251                         pipeline[plPtrFetch].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
2252                                 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
2253 //              }
2254 //              else
2255 //                      inhibitFetch = false;
2256 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrFetch].instruction, dsp_pc);
2257
2258 WriteLog("DSPExecP: Pipeline status (after stage 1)...\n");
2259 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);
2260 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);
2261 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);
2262 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);
2263                 // Stage 2: Read registers
2264 //Ok, stalls here depend on whether or not the instruction reads two registers or not
2265 //and *which* register (1 or 2) is the one being read... !!! FIX !!!
2266                 if ((/*scoreboard[pipeline[plPtrRead].operand1]
2267                         ||*/ scoreboard[pipeline[plPtrRead].operand2])
2268                         && pipeline[plPtrRead].opcode != PIPELINE_STALL)
2269                         // We have a hit in the scoreboard, so we have to stall the pipeline...
2270 {
2271 //This is crappy, crappy CRAPPY! And it doesn't work! !!! FIX !!!
2272 //                      dsp_pc -= (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2273 WriteLog("  --> Stalling pipeline: scoreboard = %s\n", scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
2274                         pipeline[plPtrFetch] = pipeline[plPtrRead];
2275                         pipeline[plPtrRead].opcode = PIPELINE_STALL;
2276 }
2277                 else
2278                 {
2279                         pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
2280                         pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
2281                         pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2;   // Set it to RN
2282
2283                         if (pipeline[plPtrRead].opcode != PIPELINE_STALL)
2284                         // Shouldn't we be more selective with the register scoreboarding?
2285                         // Yes, we should. !!! FIX !!!
2286 //                      scoreboard[pipeline[plPtrRead].operand1]
2287                                 /*=*/ scoreboard[pipeline[plPtrRead].operand2] = true;
2288 //Advance PC here??? Yes.
2289 //                      dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2290 //This is a mangling of the pipeline stages, but what else to do???
2291                         dsp_pc += (pipeline[plPtrFetch].opcode == 38 ? 6 : 2);
2292                 }
2293 /*
2294 DSPExecP: Pipeline status (after stage 1)...
2295         F -> 52, 00, 00; r1=00000000, r2= 00000000, res=00000000, wb=0 
2296         R -> 38, 00, 00; r1=00000000, r2= 00000000, res=00F1B034, wb=0 
2297         E -> 64, 00, 00; r1=00000000, r2= 00000000, res=00000000, wb=0 
2298         W -> 64, 00, 00; r1=00000000, r2= 00000000, res=00000000, wb=0 
2299   --> Stalling pipeline: scoreboard = true
2300 DSPExecP: Pipeline status (after stage 2)...
2301         F -> 52, 00, 00; r1=00000000, r2= 00000000, res=00000000, wb=0 
2302         R -> 64, 00, 00; r1=00000000, r2= 00000000, res=00F1B034, wb=0 
2303         E -> 64, 00, 00; r1=00000000, r2= 00000000, res=00000000, wb=0 
2304         W -> 64, 00, 00; r1=00000000, r2= 00000000, res=00000000, wb=0 */
2305
2306
2307 WriteLog("DSPExecP: Pipeline status (after stage 2)...\n");
2308 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);
2309 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);
2310 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);
2311 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);
2312                 // Stage 3: Execute
2313                 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
2314                 {
2315 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
2316                         DSPOpcode[pipeline[plPtrExec].opcode]();
2317                         dsp_opcode_use[pipeline[plPtrExec].opcode]++;
2318                         cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
2319                 }
2320                 else
2321                         cycles--;
2322
2323 WriteLog("DSPExecP: Pipeline status (after stage 3)...\n");
2324 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);
2325 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);
2326 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);
2327 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);
2328                 // Stage 4: Write back register
2329                 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
2330                 {
2331                         if (pipeline[plPtrWrite].writebackRegister != 0xFF)
2332                                 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
2333
2334                         scoreboard[pipeline[plPtrWrite].operand1]
2335                                 = scoreboard[pipeline[plPtrWrite].operand2] = false;
2336                 }
2337
2338                 // Push instructions through the pipeline...
2339                 plPtrFetch = (++plPtrFetch) & 0x03;
2340                 plPtrRead = (++plPtrRead) & 0x03;
2341                 plPtrExec = (++plPtrExec) & 0x03;
2342                 plPtrWrite = (++plPtrWrite) & 0x03;
2343         }
2344
2345         dsp_in_exec--;
2346 }
2347
2348
2349
2350 #define DSP_DEBUG_PL2
2351 //Let's try a 3 stage pipeline....
2352 void DSPExecP2(int32 cycles)
2353 {
2354         dsp_releaseTimeSlice_flag = 0;
2355         dsp_in_exec++;
2356
2357         while (cycles > 0 && DSP_RUNNING)
2358         {
2359 #ifdef DSP_DEBUG_PL2
2360 WriteLog("DSPExecP: Pipeline status...\n");
2361 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);
2362 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);
2363 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);
2364 WriteLog("  --> Scoreboard: ");
2365 for(int i=0; i<32; i++)
2366         WriteLog("%s ", scoreboard[i] ? "T" : "F");
2367 WriteLog("\n");
2368 #endif
2369                 // Stage 1a: Instruction fetch
2370                 pipeline[plPtrRead].instruction = DSPReadWord(dsp_pc, DSP);
2371                 pipeline[plPtrRead].opcode = pipeline[plPtrRead].instruction >> 10;
2372                 pipeline[plPtrRead].operand1 = (pipeline[plPtrRead].instruction >> 5) & 0x1F;
2373                 pipeline[plPtrRead].operand2 = pipeline[plPtrRead].instruction & 0x1F;
2374                 if (pipeline[plPtrRead].opcode == 38)
2375                         pipeline[plPtrRead].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
2376                                 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
2377 #ifdef DSP_DEBUG_PL2
2378 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrRead].instruction, dsp_pc);
2379 WriteLog("DSPExecP: Pipeline status (after stage 1a)...\n");
2380 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);
2381 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);
2382 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);
2383 #endif
2384                 // Stage 1b: Read registers
2385                 if (scoreboard[pipeline[plPtrRead].operand2])
2386                         // We have a hit in the scoreboard, so we have to stall the pipeline...
2387 #ifdef DSP_DEBUG_PL2
2388 {
2389 WriteLog("  --> Stalling pipeline: scoreboard[%u] = %s\n", pipeline[plPtrRead].operand2, scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
2390 #endif
2391                         pipeline[plPtrRead].opcode = PIPELINE_STALL;
2392 #ifdef DSP_DEBUG_PL2
2393 }
2394 #endif
2395                 else
2396                 {
2397                         pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
2398                         pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
2399                         pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2;   // Set it to RN
2400
2401                         // Shouldn't we be more selective with the register scoreboarding?
2402                         // Yes, we should. !!! FIX !!! [Kinda DONE]
2403                         scoreboard[pipeline[plPtrRead].operand2] = affectsScoreboard[pipeline[plPtrRead].opcode];
2404
2405 //Advance PC here??? Yes.
2406                         dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2407                 }
2408
2409 #ifdef DSP_DEBUG_PL2
2410 WriteLog("DSPExecP: Pipeline status (after stage 1b)...\n");
2411 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);
2412 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);
2413 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);
2414 #endif
2415                 // Stage 2: Execute
2416                 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
2417                 {
2418 #ifdef DSP_DEBUG_PL2
2419 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
2420 #endif
2421                         DSPOpcode[pipeline[plPtrExec].opcode]();
2422                         dsp_opcode_use[pipeline[plPtrExec].opcode]++;
2423                         cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
2424                 }
2425                 else
2426                         cycles--;
2427
2428 #ifdef DSP_DEBUG_PL2
2429 WriteLog("DSPExecP: Pipeline status (after stage 2)...\n");
2430 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);
2431 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);
2432 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);
2433 WriteLog("\n");
2434 #endif
2435                 // Stage 3: Write back register
2436                 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
2437                 {
2438                         if (pipeline[plPtrWrite].writebackRegister != 0xFF)
2439                                 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
2440
2441                         if (affectsScoreboard[pipeline[plPtrWrite].opcode])
2442                                 scoreboard[pipeline[plPtrWrite].operand2] = false;
2443                 }
2444
2445                 // Push instructions through the pipeline...
2446                 plPtrRead = (++plPtrRead) & 0x03;
2447                 plPtrExec = (++plPtrExec) & 0x03;
2448                 plPtrWrite = (++plPtrWrite) & 0x03;
2449         }
2450
2451         dsp_in_exec--;
2452 }
2453
2454
2455 //Problems: JR and any other instruction that relies on DSP_PC is getting WRONG values!
2456 //!!! FIX !!!
2457
2458 #define DSP_DEBUG_PL3
2459 //Let's try a 2 stage pipeline....
2460 void DSPExecP3(int32 cycles)
2461 {
2462         dsp_releaseTimeSlice_flag = 0;
2463         dsp_in_exec++;
2464
2465         while (cycles > 0 && DSP_RUNNING)
2466         {
2467 #ifdef DSP_DEBUG_PL3
2468 WriteLog("DSPExecP: Pipeline status...\n");
2469 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]);
2470 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]);
2471 WriteLog("  --> Scoreboard: ");
2472 for(int i=0; i<32; i++)
2473         WriteLog("%s ", scoreboard[i] ? "T" : "F");
2474 WriteLog("\n");
2475 #endif
2476                 // Stage 1a: Instruction fetch
2477                 pipeline[plPtrRead].instruction = DSPReadWord(dsp_pc, DSP);
2478                 pipeline[plPtrRead].opcode = pipeline[plPtrRead].instruction >> 10;
2479                 pipeline[plPtrRead].operand1 = (pipeline[plPtrRead].instruction >> 5) & 0x1F;
2480                 pipeline[plPtrRead].operand2 = pipeline[plPtrRead].instruction & 0x1F;
2481                 if (pipeline[plPtrRead].opcode == 38)
2482                         pipeline[plPtrRead].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
2483                                 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
2484 #ifdef DSP_DEBUG_PL3
2485 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrRead].instruction, dsp_pc);
2486 WriteLog("DSPExecP: Pipeline status (after stage 1a)...\n");
2487 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]);
2488 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]);
2489 #endif
2490                 // Stage 1b: Read registers
2491                 if ((scoreboard[pipeline[plPtrRead].operand1] && readAffected[pipeline[plPtrRead].opcode][0])
2492                         || (scoreboard[pipeline[plPtrRead].operand2] && readAffected[pipeline[plPtrRead].opcode][1]))
2493                         // We have a hit in the scoreboard, so we have to stall the pipeline...
2494 #if 1//def DSP_DEBUG_PL3
2495 {
2496 WriteLog("  --> Stalling pipeline: ");
2497 if (readAffected[pipeline[plPtrRead].opcode][0])
2498         WriteLog("scoreboard[%u] = %s (reg 1) ", pipeline[plPtrRead].operand1, scoreboard[pipeline[plPtrRead].operand1] ? "true" : "false");
2499 if (readAffected[pipeline[plPtrRead].opcode][1])
2500         WriteLog("scoreboard[%u] = %s (reg 2)", pipeline[plPtrRead].operand2, scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
2501 WriteLog("\n");
2502 #endif
2503                         pipeline[plPtrRead].opcode = PIPELINE_STALL;
2504 #if 1//def DSP_DEBUG_PL3
2505 }
2506 #endif
2507                 else
2508                 {
2509                         pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
2510                         pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
2511                         pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2;   // Set it to RN
2512
2513                         // Shouldn't we be more selective with the register scoreboarding?
2514                         // Yes, we should. !!! FIX !!! [Kinda DONE]
2515                         scoreboard[pipeline[plPtrRead].operand2] = affectsScoreboard[pipeline[plPtrRead].opcode];
2516
2517 //Advance PC here??? Yes.
2518                         dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2519                 }
2520
2521 #ifdef DSP_DEBUG_PL3
2522 WriteLog("DSPExecP: Pipeline status (after stage 1b)...\n");
2523 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]);
2524 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]);
2525 #endif
2526                 // Stage 2a: Execute
2527                 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
2528                 {
2529 #ifdef DSP_DEBUG_PL3
2530 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
2531 #endif
2532                         DSPOpcode[pipeline[plPtrExec].opcode]();
2533                         dsp_opcode_use[pipeline[plPtrExec].opcode]++;
2534                         cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
2535                 }
2536                 else
2537                         cycles--;
2538
2539 #ifdef DSP_DEBUG_PL3
2540 WriteLog("DSPExecP: Pipeline status (after stage 2a)...\n");
2541 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]);
2542 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]);
2543 WriteLog("\n");
2544 #endif
2545                 // Stage 2b: Write back register
2546                 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
2547                 {
2548                         if (pipeline[plPtrExec].writebackRegister != 0xFF)
2549                                 dsp_reg[pipeline[plPtrExec].writebackRegister] = pipeline[plPtrExec].result;
2550
2551                         if (affectsScoreboard[pipeline[plPtrExec].opcode])
2552                                 scoreboard[pipeline[plPtrExec].operand2] = false;
2553                 }
2554
2555                 // Push instructions through the pipeline...
2556                 plPtrRead = (++plPtrRead) & 0x03;
2557                 plPtrExec = (++plPtrExec) & 0x03;
2558 //              plPtrWrite = (++plPtrWrite) & 0x03;
2559         }
2560
2561         dsp_in_exec--;
2562 }
2563
2564 //
2565 // DSP pipelined opcode handlers
2566 //
2567
2568 #define PRM                             pipeline[plPtrExec].reg1
2569 #define PRN                             pipeline[plPtrExec].reg2
2570 #define PIMM1                   pipeline[plPtrExec].operand1
2571 #define PIMM2                   pipeline[plPtrExec].operand2
2572 #define PRES                    pipeline[plPtrExec].result
2573 #define PWBR                    pipeline[plPtrExec].writebackRegister
2574 #define NO_WRITEBACK    pipeline[plPtrExec].writebackRegister = 0xFF
2575
2576 static void DSP_abs(void)
2577 {
2578         uint32 _Rn = PRN;
2579         
2580         if (_Rn == 0x80000000)
2581                 dsp_flag_n = 1;
2582         else
2583         {
2584                 dsp_flag_c = ((_Rn & 0x80000000) >> 31);
2585                 PRES = (_Rn & 0x80000000 ? -_Rn : _Rn);
2586                 CLR_ZN; SET_Z(PRES);
2587         }
2588 }
2589
2590 static void DSP_add(void)
2591 {
2592 #ifdef DSP_DIS_ADD
2593         if (doDSPDis)
2594                 WriteLog("%06X: ADD    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2595 #endif
2596         UINT32 res = PRN + PRM;
2597         SET_ZNC_ADD(PRN, PRM, res);
2598         PRES = res;
2599 #ifdef DSP_DIS_ADD
2600         if (doDSPDis)
2601                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2602 #endif
2603 }
2604
2605 static void DSP_addc(void)
2606 {
2607 #ifdef DSP_DIS_ADDC
2608         if (doDSPDis)
2609                 WriteLog("%06X: ADDC   R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2610 #endif
2611         UINT32 res = PRN + PRM + dsp_flag_c;
2612         UINT32 carry = dsp_flag_c;
2613 //      SET_ZNC_ADD(PRN, PRM, res); //???BUG??? Yes!
2614         SET_ZNC_ADD(PRN + carry, PRM, res);
2615 //      SET_ZNC_ADD(PRN, PRM + carry, res);
2616         PRES = res;
2617 #ifdef DSP_DIS_ADDC
2618         if (doDSPDis)
2619                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2620 #endif
2621 }
2622
2623 static void DSP_addq(void)
2624 {
2625 #ifdef DSP_DIS_ADDQ
2626         if (doDSPDis)
2627                 WriteLog("%06X: ADDQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2628 #endif
2629         UINT32 r1 = dsp_convert_zero[PIMM1];
2630         UINT32 res = PRN + r1;
2631         CLR_ZNC; SET_ZNC_ADD(PRN, r1, res);
2632         PRES = res;
2633 #ifdef DSP_DIS_ADDQ
2634         if (doDSPDis)
2635                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2636 #endif
2637 }
2638
2639 static void DSP_addqmod(void)
2640 {
2641 #ifdef DSP_DIS_ADDQMOD
2642         if (doDSPDis)
2643                 WriteLog("%06X: ADDQMOD #%u, R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_MOD=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, dsp_modulo);
2644 #endif
2645         UINT32 r1 = dsp_convert_zero[PIMM1];
2646         UINT32 r2 = PRN;
2647         UINT32 res = r2 + r1;
2648         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2649         PRES = res;
2650         SET_ZNC_ADD(r2, r1, res);
2651 #ifdef DSP_DIS_ADDQMOD
2652         if (doDSPDis)
2653                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2654 #endif
2655 }
2656
2657 static void DSP_addqt(void)
2658 {
2659 #ifdef DSP_DIS_ADDQT
2660         if (doDSPDis)
2661                 WriteLog("%06X: ADDQT  #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2662 #endif
2663         PRES = PRN + dsp_convert_zero[PIMM1];
2664 #ifdef DSP_DIS_ADDQT
2665         if (doDSPDis)
2666                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2667 #endif
2668 }
2669
2670 static void DSP_and(void)
2671 {
2672 #ifdef DSP_DIS_AND
2673         if (doDSPDis)
2674                 WriteLog("%06X: AND    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2675 #endif
2676         PRES = PRN & PRM;
2677         SET_ZN(PRES);
2678 #ifdef DSP_DIS_AND
2679         if (doDSPDis)
2680                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2681 #endif
2682 }
2683
2684 static void DSP_bclr(void)
2685 {
2686 #ifdef DSP_DIS_BCLR
2687         if (doDSPDis)
2688                 WriteLog("%06X: BCLR   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2689 #endif
2690         PRES = PRN & ~(1 << PIMM1);
2691         SET_ZN(PRES);
2692 #ifdef DSP_DIS_BCLR
2693         if (doDSPDis)
2694                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2695 #endif
2696 }
2697
2698 static void DSP_bset(void)
2699 {
2700 #ifdef DSP_DIS_BSET
2701         if (doDSPDis)
2702                 WriteLog("%06X: BSET   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2703 #endif
2704         PRES = PRN | (1 << PIMM1);
2705         SET_ZN(PRES);
2706 #ifdef DSP_DIS_BSET
2707         if (doDSPDis)
2708                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2709 #endif
2710 }
2711
2712 static void DSP_btst(void)
2713 {
2714 #ifdef DSP_DIS_BTST
2715         if (doDSPDis)
2716                 WriteLog("%06X: BTST   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2717 #endif
2718         dsp_flag_z = (~PRN >> PIMM1) & 1;
2719         NO_WRITEBACK;
2720 #ifdef DSP_DIS_BTST
2721         if (doDSPDis)
2722                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2723 #endif
2724 }
2725
2726 static void DSP_cmp(void)
2727 {
2728 #ifdef DSP_DIS_CMP
2729         if (doDSPDis)
2730                 WriteLog("%06X: CMP    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2731 #endif
2732         UINT32 res = PRN - PRM;
2733         SET_ZNC_SUB(PRN, PRM, res);
2734         NO_WRITEBACK;
2735 #ifdef DSP_DIS_CMP
2736         if (doDSPDis)
2737                 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
2738 #endif
2739 }
2740
2741 static void DSP_cmpq(void)
2742 {
2743         static int32 sqtable[32] =
2744                 { 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 };
2745 #ifdef DSP_DIS_CMPQ
2746         if (doDSPDis)
2747                 WriteLog("%06X: CMPQ   #%d, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, sqtable[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2748 #endif
2749         UINT32 r1 = sqtable[PIMM1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
2750         UINT32 res = PRN - r1;
2751         SET_ZNC_SUB(PRN, r1, res);
2752         NO_WRITEBACK;
2753 #ifdef DSP_DIS_CMPQ
2754         if (doDSPDis)
2755                 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
2756 #endif
2757 }
2758
2759 static void DSP_div(void)
2760 {
2761         uint32 _Rm = PRM, _Rn = PRN;
2762
2763         if (_Rm)
2764         {
2765                 if (dsp_div_control & 1)
2766                 {
2767                         dsp_remain = (((uint64)_Rn) << 16) % _Rm;
2768                         if (dsp_remain & 0x80000000)
2769                                 dsp_remain -= _Rm;
2770                         PRES = (((uint64)_Rn) << 16) / _Rm;
2771                 }
2772                 else
2773                 {
2774                         dsp_remain = _Rn % _Rm;
2775                         if (dsp_remain & 0x80000000)
2776                                 dsp_remain -= _Rm;
2777                         PRES = PRN / _Rm;
2778                 }
2779         }
2780         else
2781                 PRES = 0xFFFFFFFF;
2782 }
2783
2784 static void DSP_imacn(void)
2785 {
2786 #ifdef DSP_DIS_IMACN
2787         if (doDSPDis)
2788                 WriteLog("%06X: IMACN  R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2789 #endif
2790         int32 res = (int16)PRM * (int16)PRN;
2791         dsp_acc += (int64)res;
2792 //Should we AND the result to fit into 40 bits here???
2793         NO_WRITEBACK;
2794 #ifdef DSP_DIS_IMACN
2795         if (doDSPDis)
2796                 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));
2797 #endif
2798
2799
2800 static void DSP_imult(void)
2801 {
2802 #ifdef DSP_DIS_IMULT
2803         if (doDSPDis)
2804                 WriteLog("%06X: IMULT  R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2805 #endif
2806         PRES = (int16)PRN * (int16)PRM;
2807         SET_ZN(PRES);
2808 #ifdef DSP_DIS_IMULT
2809         if (doDSPDis)
2810                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2811 #endif
2812 }
2813
2814 static void DSP_imultn(void)
2815 {
2816 #ifdef DSP_DIS_IMULTN
2817         if (doDSPDis)
2818                 WriteLog("%06X: IMULTN R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2819 #endif
2820         // This is OK, since this multiply won't overflow 32 bits...
2821         int32 res = (int32)((int16)PRN * (int16)PRM);
2822         dsp_acc = (int64)res;
2823         SET_ZN(res);
2824         NO_WRITEBACK;
2825 #ifdef DSP_DIS_IMULTN
2826         if (doDSPDis)
2827                 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));
2828 #endif
2829 }
2830
2831 static void DSP_illegal(void)
2832 {
2833 #ifdef DSP_DIS_ILLEGAL
2834         if (doDSPDis)
2835                 WriteLog("%06X: ILLEGAL [NCZ:%u%u%u]\n", dsp_pc-2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
2836 #endif
2837         NO_WRITEBACK;
2838 }
2839
2840 // There is a problem here with interrupt handlers the JUMP and JR instructions that
2841 // can cause trouble because an interrupt can occur *before* the instruction following the
2842 // jump can execute... !!! FIX !!!
2843 static void DSP_jr(void)
2844 {
2845 #ifdef DSP_DIS_JR
2846 char * condition[32] =
2847 {       "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
2848         "c z", "???", "???", "???", "???", "???", "???", "???", "???",
2849         "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
2850         "???", "???", "???", "F" };
2851         if (doDSPDis)
2852                 WriteLog("%06X: JR     %s, %06X [NCZ:%u%u%u] ", dsp_pc-2, condition[PIMM2], dsp_pc+((PIMM1 & 0x10 ? 0xFFFFFFF0 | PIMM1 : PIMM1) * 2), dsp_flag_n, dsp_flag_c, dsp_flag_z);
2853 #endif
2854         // KLUDGE: Used by BRANCH_CONDITION macro
2855         uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
2856
2857         if (BRANCH_CONDITION(PIMM2))
2858         {
2859 #ifdef DSP_DIS_JR
2860         if (doDSPDis)
2861                 WriteLog("Branched!\n");
2862 #endif
2863                 int32 offset = (PIMM1 & 0x10 ? 0xFFFFFFF0 | PIMM1 : PIMM1);             // Sign extend PIMM1
2864                 int32 delayed_pc = dsp_pc + (offset * 2);
2865 //              DSPExec(1);
2866                 dsp_pc = delayed_pc;
2867         }
2868 #ifdef DSP_DIS_JR
2869         else
2870                 if (doDSPDis)
2871                         WriteLog("Branch NOT taken.\n");
2872 #endif
2873         NO_WRITEBACK;
2874 }
2875
2876 static void DSP_jump(void)
2877 {
2878 #ifdef DSP_DIS_JUMP
2879 char * condition[32] =
2880 {       "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
2881         "c z", "???", "???", "???", "???", "???", "???", "???", "???",
2882         "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
2883         "???", "???", "???", "F" };
2884         if (doDSPDis)
2885                 WriteLog("%06X: JUMP   %s, (R%02u) [NCZ:%u%u%u, R%02u=%08X] ", dsp_pc-2, condition[PIMM2], PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM);
2886 #endif
2887         // KLUDGE: Used by BRANCH_CONDITION macro
2888         uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
2889
2890         if (BRANCH_CONDITION(PIMM2))
2891         {
2892 #ifdef DSP_DIS_JUMP
2893         if (doDSPDis)
2894                 WriteLog("Branched!\n");
2895 #endif
2896 //              uint32 delayed_pc = PRM;
2897 //              DSPExec(1);
2898 //              dsp_pc = delayed_pc;
2899                 dsp_pc = PRM;
2900         }
2901 #ifdef DSP_DIS_JUMP
2902         else
2903                 if (doDSPDis)
2904                         WriteLog("Branch NOT taken.\n");
2905 #endif
2906         NO_WRITEBACK;
2907 }
2908
2909 static void DSP_load(void)
2910 {
2911 #ifdef DSP_DIS_LOAD
2912         if (doDSPDis)
2913                 WriteLog("%06X: LOAD   (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2914 #endif
2915         PRES = DSPReadLong(PRM, DSP);
2916 #ifdef DSP_DIS_LOAD
2917         if (doDSPDis)
2918                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2919 #endif
2920 }
2921
2922 static void DSP_loadb(void)
2923 {
2924 #ifdef DSP_DIS_LOADB
2925         if (doDSPDis)
2926                 WriteLog("%06X: LOADB  (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2927 #endif
2928         if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
2929                 PRES = DSPReadLong(PRM, DSP) & 0xFF;
2930         else
2931                 PRES = JaguarReadByte(PRM, DSP);
2932 #ifdef DSP_DIS_LOADB
2933         if (doDSPDis)
2934                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2935 #endif
2936 }
2937
2938 static void DSP_loadw(void)
2939 {
2940 #ifdef DSP_DIS_LOADW
2941         if (doDSPDis)
2942                 WriteLog("%06X: LOADW  (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2943 #endif
2944         if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
2945                 PRES = DSPReadLong(PRM, DSP) & 0xFFFF;
2946         else
2947                 PRES = JaguarReadWord(PRM, DSP);
2948 #ifdef DSP_DIS_LOADW
2949         if (doDSPDis)
2950                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2951 #endif
2952 }
2953
2954 static void DSP_load_r14_i(void)
2955 {
2956 #ifdef DSP_DIS_LOAD14I
2957         if (doDSPDis)
2958                 WriteLog("%06X: LOAD   (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", dsp_pc-2, 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);
2959 #endif
2960         PRES = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), DSP);
2961 #ifdef DSP_DIS_LOAD14I
2962         if (doDSPDis)
2963                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2964 #endif
2965 }
2966
2967 static void DSP_load_r14_r(void)
2968 {
2969 #ifdef DSP_DIS_LOAD14R
2970         if (doDSPDis)
2971                 WriteLog("%06X: LOAD   (R14+R%02u), R%02u [NCZ:%u%u%u, R14+R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM+dsp_reg[14], PIMM2, PRN);
2972 #endif
2973         PRES = DSPReadLong(dsp_reg[14] + PRM, DSP);
2974 #ifdef DSP_DIS_LOAD14R
2975         if (doDSPDis)
2976                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2977 #endif
2978 }
2979
2980 static void DSP_load_r15_i(void)
2981 {
2982 #ifdef DSP_DIS_LOAD15I
2983         if (doDSPDis)
2984                 WriteLog("%06X: LOAD   (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", dsp_pc-2, 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);
2985 #endif
2986         PRES = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), DSP);
2987 #ifdef DSP_DIS_LOAD15I
2988         if (doDSPDis)
2989                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2990 #endif
2991 }
2992
2993 static void DSP_load_r15_r(void)
2994 {
2995 #ifdef DSP_DIS_LOAD15R
2996         if (doDSPDis)
2997                 WriteLog("%06X: LOAD   (R15+R%02u), R%02u [NCZ:%u%u%u, R15+R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM+dsp_reg[15], PIMM2, PRN);
2998 #endif
2999         PRES = DSPReadLong(dsp_reg[15] + PRM, DSP);
3000 #ifdef DSP_DIS_LOAD15R
3001         if (doDSPDis)
3002                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3003 #endif
3004 }
3005
3006 static void DSP_mirror(void)    
3007 {
3008         UINT32 r1 = PRN;
3009         PRES = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
3010         SET_ZN(PRES);
3011 }
3012
3013 static void DSP_mmult(void)
3014 {
3015         int count       = dsp_matrix_control&0x0f;
3016         uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
3017         int64 accum = 0;
3018         uint32 res;
3019
3020         if (!(dsp_matrix_control & 0x10))
3021         {
3022                 for (int i = 0; i < count; i++)
3023                 { 
3024                         int16 a;
3025                         if (i&0x01)
3026                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
3027                         else
3028                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
3029                         int16 b=((int16)DSPReadWord(addr + 2, DSP));
3030                         accum += a*b;
3031                         addr += 4;
3032                 }
3033         }
3034         else
3035         {
3036                 for (int i = 0; i < count; i++)
3037                 {
3038                         int16 a;
3039                         if (i&0x01)
3040                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
3041                         else
3042                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
3043                         int16 b=((int16)DSPReadWord(addr + 2, DSP));
3044                         accum += a*b;
3045                         addr += 4 * count;
3046                 }
3047         }
3048
3049         PRES = res = (int32)accum;
3050         // carry flag to do
3051 //NOTE: The flags are set based upon the last add/multiply done...
3052         SET_ZN(PRES);
3053 }
3054
3055 static void DSP_move(void)
3056 {
3057 #ifdef DSP_DIS_MOVE
3058         if (doDSPDis)
3059                 WriteLog("%06X: MOVE   R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3060 #endif
3061         PRES = PRM;
3062 #ifdef DSP_DIS_MOVE
3063         if (doDSPDis)
3064                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3065 #endif
3066 }
3067
3068 static void DSP_movefa(void)
3069 {
3070 #ifdef DSP_DIS_MOVEFA
3071         if (doDSPDis)
3072 //              WriteLog("%06X: MOVEFA R%02u, R%02u [NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, ALTERNATE_RM, PIMM2, PRN);
3073                 WriteLog("%06X: MOVEFA R%02u, R%02u [NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, dsp_alternate_reg[PIMM1], PIMM2, PRN);
3074 #endif
3075 //      PRES = ALTERNATE_RM;
3076         PRES = dsp_alternate_reg[PIMM1];
3077 #ifdef DSP_DIS_MOVEFA
3078         if (doDSPDis)
3079 //              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);
3080                 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);
3081 #endif
3082 }
3083
3084 static void DSP_movei(void)
3085 {
3086 #ifdef DSP_DIS_MOVEI
3087         if (doDSPDis)
3088                 WriteLog("%06X: MOVEI  #$%08X, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, PRES, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3089 #endif
3090 //      // This instruction is followed by 32-bit value in LSW / MSW format...
3091 //      PRES = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
3092 //      dsp_pc += 4;
3093 #ifdef DSP_DIS_MOVEI
3094         if (doDSPDis)
3095                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3096 #endif
3097 }
3098
3099 static void DSP_movepc(void)
3100 {
3101 //Need to fix this to take into account pipelining effects... !!! FIX !!!
3102         PRES = dsp_pc - 2;
3103 }
3104
3105 static void DSP_moveq(void)
3106 {
3107 #ifdef DSP_DIS_MOVEQ
3108         if (doDSPDis)
3109                 WriteLog("%06X: MOVEQ  #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3110 #endif
3111         PRES = PIMM1;
3112 #ifdef DSP_DIS_MOVEQ
3113         if (doDSPDis)
3114                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3115 #endif
3116 }
3117
3118 static void DSP_moveta(void)
3119 {
3120 #ifdef DSP_DIS_MOVETA
3121         if (doDSPDis)
3122 //              WriteLog("%06X: MOVETA R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, ALTERNATE_RN);
3123                 WriteLog("%06X: MOVETA R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, dsp_alternate_reg[PIMM2]);
3124 #endif
3125 //      ALTERNATE_RN = PRM;
3126         dsp_alternate_reg[PIMM2] = PRM;
3127         NO_WRITEBACK;
3128 #ifdef DSP_DIS_MOVETA
3129         if (doDSPDis)
3130 //              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);
3131                 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]);
3132 #endif
3133 }
3134
3135 static void DSP_mtoi(void)
3136 {
3137         PRES = (((INT32)PRM >> 8) & 0xFF800000) | (PRM & 0x007FFFFF);
3138         SET_ZN(PRES);
3139 }
3140
3141 static void DSP_mult(void)
3142 {
3143 #ifdef DSP_DIS_MULT
3144         if (doDSPDis)
3145                 WriteLog("%06X: MULT   R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3146 #endif
3147         PRES = (uint16)PRM * (uint16)PRN;
3148         SET_ZN(PRES);
3149 #ifdef DSP_DIS_MULT
3150         if (doDSPDis)
3151                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3152 #endif
3153 }
3154
3155 static void DSP_neg(void)
3156 {
3157 #ifdef DSP_DIS_NEG
3158         if (doDSPDis)
3159                 WriteLog("%06X: NEG    R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3160 #endif
3161         UINT32 res = -PRN;
3162         SET_ZNC_SUB(0, PRN, res);
3163         PRES = res;
3164 #ifdef DSP_DIS_NEG
3165         if (doDSPDis)
3166                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3167 #endif
3168 }
3169
3170 static void DSP_nop(void)
3171 {
3172 #ifdef DSP_DIS_NOP
3173         if (doDSPDis)
3174                 WriteLog("%06X: NOP    [NCZ:%u%u%u]\n", dsp_pc-2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
3175 #endif
3176         NO_WRITEBACK;
3177 }
3178
3179 static void DSP_normi(void)
3180 {
3181         uint32 _Rm = PRM;
3182         uint32 res = 0;
3183
3184         if (_Rm)
3185         {
3186                 while ((_Rm & 0xffc00000) == 0)
3187                 {
3188                         _Rm <<= 1;
3189                         res--;
3190                 }
3191                 while ((_Rm & 0xff800000) != 0)
3192                 {
3193                         _Rm >>= 1;
3194                         res++;
3195                 }
3196         }
3197         PRES = res;
3198         SET_ZN(PRES);
3199 }
3200
3201 static void DSP_not(void)
3202 {
3203 #ifdef DSP_DIS_NOT
3204         if (doDSPDis)
3205                 WriteLog("%06X: NOT    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3206 #endif
3207         PRES = ~PRN;
3208         SET_ZN(PRES);
3209 #ifdef DSP_DIS_NOT
3210         if (doDSPDis)
3211                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3212 #endif
3213 }
3214
3215 static void DSP_or(void)
3216 {
3217 #ifdef DSP_DIS_OR
3218         if (doDSPDis)
3219                 WriteLog("%06X: OR     R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3220 #endif
3221         PRES = PRN | PRM;
3222         SET_ZN(PRES);
3223 #ifdef DSP_DIS_OR
3224         if (doDSPDis)
3225                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3226 #endif
3227 }
3228
3229 static void DSP_resmac(void)
3230 {
3231 #ifdef DSP_DIS_RESMAC
3232         if (doDSPDis)
3233                 WriteLog("%06X: RESMAC R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_ACC=%02X%08X] -> ", dsp_pc-2, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
3234 #endif
3235         PRES = (uint32)dsp_acc;
3236 #ifdef DSP_DIS_RESMAC
3237         if (doDSPDis)
3238                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3239 #endif
3240 }
3241
3242 static void DSP_ror(void)
3243 {
3244 #ifdef DSP_DIS_ROR
3245         if (doDSPDis)
3246                 WriteLog("%06X: ROR    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3247 #endif
3248         UINT32 r1 = PRM & 0x1F;
3249         UINT32 res = (PRN >> r1) | (PRN << (32 - r1));
3250         SET_ZN(res); dsp_flag_c = (PRN >> 31) & 1;
3251         PRES = res;
3252 #ifdef DSP_DIS_ROR
3253         if (doDSPDis)
3254                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3255 #endif
3256 }
3257
3258 static void DSP_rorq(void)
3259 {
3260 #ifdef DSP_DIS_RORQ
3261         if (doDSPDis)
3262                 WriteLog("%06X: RORQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3263 #endif
3264         UINT32 r1 = dsp_convert_zero[PIMM1 & 0x1F];
3265         UINT32 r2 = PRN;
3266         UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
3267         PRES = res;
3268         SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
3269 #ifdef DSP_DIS_RORQ
3270         if (doDSPDis)
3271                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3272 #endif
3273 }
3274
3275 static void DSP_sat16s(void)            
3276 {
3277         INT32 r2 = PRN;
3278         UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
3279         PRES = res;
3280         SET_ZN(res);
3281 }
3282
3283 static void DSP_sat32s(void)            
3284 {
3285         INT32 r2 = (UINT32)PRN;
3286         INT32 temp = dsp_acc >> 32;
3287         UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
3288         PRES = res;
3289         SET_ZN(res);
3290 }
3291
3292 static void DSP_sh(void)
3293 {
3294         int32 sRm = (int32)PRM;
3295         uint32 _Rn = PRN;
3296
3297         if (sRm < 0)
3298         {
3299                 uint32 shift = -sRm;
3300
3301                 if (shift >= 32)
3302                         shift = 32;
3303
3304                 dsp_flag_c = (_Rn & 0x80000000) >> 31;
3305
3306                 while (shift)
3307                 {
3308                         _Rn <<= 1;
3309                         shift--;
3310                 }
3311         }
3312         else
3313         {
3314                 uint32 shift = sRm;
3315
3316                 if (shift >= 32)
3317                         shift = 32;
3318
3319                 dsp_flag_c = _Rn & 0x1;
3320
3321                 while (shift)
3322                 {
3323                         _Rn >>= 1;
3324                         shift--;
3325                 }
3326         }
3327
3328         PRES = _Rn;
3329         SET_ZN(PRES);
3330 }
3331
3332 static void DSP_sha(void)
3333 {
3334         int32 sRm = (int32)PRM;
3335         uint32 _Rn = PRN;
3336
3337         if (sRm < 0)
3338         {
3339                 uint32 shift = -sRm;
3340
3341                 if (shift >= 32)
3342                         shift = 32;
3343
3344                 dsp_flag_c = (_Rn & 0x80000000) >> 31;
3345
3346                 while (shift)
3347                 {
3348                         _Rn <<= 1;
3349                         shift--;
3350                 }
3351         }
3352         else
3353         {
3354                 uint32 shift = sRm;
3355
3356                 if (shift >= 32)
3357                         shift = 32;
3358
3359                 dsp_flag_c = _Rn & 0x1;
3360
3361                 while (shift)
3362                 {
3363                         _Rn = ((int32)_Rn) >> 1;
3364                         shift--;
3365                 }
3366         }
3367
3368         PRES = _Rn;
3369         SET_ZN(PRES);
3370 }
3371
3372 static void DSP_sharq(void)
3373 {
3374 #ifdef DSP_DIS_SHARQ
3375         if (doDSPDis)
3376                 WriteLog("%06X: SHARQ  #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3377 #endif
3378         UINT32 res = (INT32)PRN >> dsp_convert_zero[PIMM1];
3379         SET_ZN(res); dsp_flag_c = PRN & 0x01;
3380         PRES = res;
3381 #ifdef DSP_DIS_SHARQ
3382         if (doDSPDis)
3383                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3384 #endif
3385 }
3386
3387 static void DSP_shlq(void)
3388 {
3389 #ifdef DSP_DIS_SHLQ
3390         if (doDSPDis)
3391                 WriteLog("%06X: SHLQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, 32 - PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3392 #endif
3393         INT32 r1 = 32 - PIMM1;
3394         UINT32 res = PRN << r1;
3395         SET_ZN(res); dsp_flag_c = (PRN >> 31) & 1;
3396         PRES = res;
3397 #ifdef DSP_DIS_SHLQ
3398         if (doDSPDis)
3399                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3400 #endif
3401 }
3402
3403 static void DSP_shrq(void)
3404 {
3405 #ifdef DSP_DIS_SHRQ
3406         if (doDSPDis)
3407                 WriteLog("%06X: SHRQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3408 #endif
3409         INT32 r1 = dsp_convert_zero[PIMM1];
3410         UINT32 res = PRN >> r1;
3411         SET_ZN(res); dsp_flag_c = PRN & 1;
3412         PRES = res;
3413 #ifdef DSP_DIS_SHRQ
3414         if (doDSPDis)
3415                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3416 #endif
3417 }
3418
3419 static void DSP_store(void)
3420 {
3421 #ifdef DSP_DIS_STORE
3422         if (doDSPDis)
3423                 WriteLog("%06X: STORE  R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, PIMM2, PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, PIMM1, PRM);
3424 #endif
3425         DSPWriteLong(PRM, PRN, DSP);
3426         NO_WRITEBACK;
3427 }
3428
3429 static void DSP_storeb(void)
3430 {
3431 #ifdef DSP_DIS_STOREB
3432         if (doDSPDis)
3433                 WriteLog("%06X: STOREB R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, PIMM2, PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, PIMM1, PRM);
3434 #endif
3435         if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
3436                 DSPWriteLong(PRM, PRN & 0xFF, DSP);
3437         else
3438                 JaguarWriteByte(PRM, PRN, DSP);
3439
3440         NO_WRITEBACK;
3441 }
3442
3443 static void DSP_storew(void)
3444 {
3445 #ifdef DSP_DIS_STOREW
3446         if (doDSPDis)
3447                 WriteLog("%06X: STOREW R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, PIMM2, PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, PIMM1, PRM);
3448 #endif
3449         if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
3450                 DSPWriteLong(PRM, PRN & 0xFFFF, DSP);
3451         else
3452                 JaguarWriteWord(PRM, PRN, DSP);
3453
3454         NO_WRITEBACK;
3455 }
3456
3457 static void DSP_store_r14_i(void)
3458 {
3459 #ifdef DSP_DIS_STORE14I
3460         if (doDSPDis)
3461                 WriteLog("%06X: STORE  R%02u, (R14+$%02X) [NCZ:%u%u%u, R%02u=%08X, R14+$%02X=%08X]\n", dsp_pc-2, 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));
3462 #endif
3463         DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
3464         NO_WRITEBACK;
3465 }
3466
3467 static void DSP_store_r14_r(void)
3468 {
3469         DSPWriteLong(dsp_reg[14] + PRM, PRN, DSP);
3470         NO_WRITEBACK;
3471 }
3472
3473 static void DSP_store_r15_i(void)
3474 {
3475 #ifdef DSP_DIS_STORE15I
3476         if (doDSPDis)
3477                 WriteLog("%06X: STORE  R%02u, (R15+$%02X) [NCZ:%u%u%u, R%02u=%08X, R15+$%02X=%08X]\n", dsp_pc-2, 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));
3478 #endif
3479         DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
3480         NO_WRITEBACK;
3481 }
3482
3483 static void DSP_store_r15_r(void)
3484 {
3485         DSPWriteLong(dsp_reg[15] + PRM, PRN, DSP);
3486         NO_WRITEBACK;
3487 }
3488
3489 static void DSP_sub(void)
3490 {
3491 #ifdef DSP_DIS_SUB
3492         if (doDSPDis)
3493                 WriteLog("%06X: SUB    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3494 #endif
3495         UINT32 res = PRN - PRM;
3496         SET_ZNC_SUB(PRN, PRM, res);
3497         PRES = res;
3498 #ifdef DSP_DIS_SUB
3499         if (doDSPDis)
3500                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3501 #endif
3502 }
3503
3504 static void DSP_subc(void)
3505 {
3506 #ifdef DSP_DIS_SUBC
3507         if (doDSPDis)
3508                 WriteLog("%06X: SUBC   R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3509 #endif
3510         UINT32 res = PRN - PRM - dsp_flag_c;
3511         UINT32 borrow = dsp_flag_c;
3512         SET_ZNC_SUB(PRN - borrow, PRM, res);
3513         PRES = res;
3514 #ifdef DSP_DIS_SUBC
3515         if (doDSPDis)
3516                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3517 #endif
3518 }
3519
3520 static void DSP_subq(void)
3521 {
3522 #ifdef DSP_DIS_SUBQ
3523         if (doDSPDis)
3524                 WriteLog("%06X: SUBQ   #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3525 #endif
3526         UINT32 r1 = dsp_convert_zero[PIMM1];
3527         UINT32 res = PRN - r1;
3528         SET_ZNC_SUB(PRN, r1, res);
3529         PRES = res;
3530 #ifdef DSP_DIS_SUBQ
3531         if (doDSPDis)
3532                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3533 #endif
3534 }
3535
3536 static void DSP_subqmod(void)   
3537 {
3538         UINT32 r1 = dsp_convert_zero[PIMM1];
3539         UINT32 r2 = PRN;
3540         UINT32 res = r2 - r1;
3541         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
3542         PRES = res;
3543         SET_ZNC_SUB(r2, r1, res);
3544 }
3545
3546 static void DSP_subqt(void)
3547 {
3548 #ifdef DSP_DIS_SUBQT
3549         if (doDSPDis)
3550                 WriteLog("%06X: SUBQT  #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3551 #endif
3552         PRES = PRN - dsp_convert_zero[PIMM1];
3553 #ifdef DSP_DIS_SUBQT
3554         if (doDSPDis)
3555                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3556 #endif
3557 }
3558
3559 static void DSP_xor(void)
3560 {
3561 #ifdef DSP_DIS_XOR
3562         if (doDSPDis)
3563                 WriteLog("%06X: XOR    R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3564 #endif
3565         PRES = PRN ^ PRM;
3566         SET_ZN(PRES);
3567 #ifdef DSP_DIS_XOR
3568         if (doDSPDis)
3569                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3570 #endif
3571 }