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