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