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