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