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