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