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