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