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