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