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