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