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