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