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