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