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