]> Shamusworld >> Repos - virtualjaguar/blob - dsp.cpp
710b90a169ad33fa05c478a84b2362e9543aacef
[virtualjaguar] / dsp.cpp
1 //
2 // DSP core
3 //
4 // by cal2
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Extensive cleanups/rewrites by James L. Hammons
7 //
8
9 #include <SDL.h>        // Used only for SDL_GetTicks...
10 #include "dsp.h"
11
12 #define DSP_DEBUG
13 //#define DSP_DEBUG_IRQ
14
15 // Disassembly definitions
16
17 #define DSP_DIS_ADD
18 #define DSP_DIS_ADDC
19 #define DSP_DIS_ADDQ
20 #define DSP_DIS_ADDQMOD
21 #define DSP_DIS_ADDQT
22 #define DSP_DIS_AND
23 #define DSP_DIS_BCLR
24 #define DSP_DIS_BSET
25 #define DSP_DIS_BTST
26 #define DSP_DIS_CMP
27 #define DSP_DIS_CMPQ
28 #define DSP_DIS_IMACN
29 #define DSP_DIS_IMULT
30 #define DSP_DIS_IMULTN
31 #define DSP_DIS_JR
32 #define DSP_DIS_JUMP
33 #define DSP_DIS_LOAD
34 #define DSP_DIS_LOAD14I
35 #define DSP_DIS_LOAD14R
36 #define DSP_DIS_LOAD15I
37 #define DSP_DIS_LOAD15R
38 #define DSP_DIS_LOADB
39 #define DSP_DIS_LOADW
40 #define DSP_DIS_MOVE
41 #define DSP_DIS_MOVEI
42 #define DSP_DIS_MOVEQ
43 #define DSP_DIS_MOVEFA
44 #define DSP_DIS_MOVETA
45 #define DSP_DIS_MULT
46 #define DSP_DIS_NEG
47 #define DSP_DIS_NOP
48 #define DSP_DIS_NOT
49 #define DSP_DIS_OR
50 #define DSP_DIS_RESMAC
51 #define DSP_DIS_ROR
52 #define DSP_DIS_RORQ
53 #define DSP_DIS_SHARQ
54 #define DSP_DIS_SHLQ
55 #define DSP_DIS_SHRQ
56 #define DSP_DIS_STORE
57 #define DSP_DIS_STORE14I
58 #define DSP_DIS_STORE15I
59 #define DSP_DIS_STOREB
60 #define DSP_DIS_STOREW
61 #define DSP_DIS_SUB
62 #define DSP_DIS_SUBC
63 #define DSP_DIS_SUBQ
64 #define DSP_DIS_SUBQT
65 #define DSP_DIS_XOR
66
67 bool doDSPDis = false;
68 //*/
69
70 /*
71 No dis yet:
72 +       subqt 4560
73 +       mult 1472
74 +       imultn 395024
75 +       resmac 395024
76 +       imacn 395024
77 +       addqmod 93328
78
79 dsp opcodes use:
80 +       add 1672497
81 +       addq 4366576
82 +       addqt 44405640
83 +       sub 94833
84 +       subq 111769
85 +       and 47416
86 +       btst 94521
87 +       bset 2277826
88 +       bclr 3223372
89 +       mult 47104
90 +       imult 237080
91 +       shlq 365464
92 +       shrq 141624
93 +       sharq 318368
94 +       cmp 45175078
95 +       move 2238994
96 +       moveq 335305
97 +       moveta 19
98 +       movefa 47406440
99 +       movei 1920664
100 +       loadb 94832
101 +       load 4031281
102 +       load_r15_indexed 284500
103 +       store 2161732
104 +       store_r15_indexed 47416
105 +       jump 3872424
106 +       jr 46386967
107 +       nop 3300029
108 +       load_r14_ri 1229448
109 */
110
111 // DSP flags (old--have to get rid of this crap)
112
113 #define CINT0FLAG                       0x00200
114 #define CINT1FLAG                       0x00400
115 #define CINT2FLAG                       0x00800
116 #define CINT3FLAG                       0x01000
117 #define CINT4FLAG                       0x02000
118 #define CINT04FLAGS                     (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
119 #define CINT5FLAG                       0x20000         /* DSP only */
120
121 // DSP_FLAGS bits
122
123 #define ZERO_FLAG               0x00001
124 #define CARRY_FLAG              0x00002
125 #define NEGA_FLAG               0x00004
126 #define IMASK                   0x00008
127 #define INT_ENA0                0x00010
128 #define INT_ENA1                0x00020
129 #define INT_ENA2                0x00040
130 #define INT_ENA3                0x00080
131 #define INT_ENA4                0x00100
132 #define INT_CLR0                0x00200
133 #define INT_CLR1                0x00400
134 #define INT_CLR2                0x00800
135 #define INT_CLR3                0x01000
136 #define INT_CLR4                0x02000
137 #define REGPAGE                 0x04000
138 #define DMAEN                   0x08000
139 #define INT_ENA5                0x10000
140 #define INT_CLR5                0x20000
141
142 // DSP_CTRL bits
143
144 #define DSPGO                   0x00001
145 #define CPUINT                  0x00002
146 #define DSPINT0                 0x00004
147 #define SINGLE_STEP             0x00008
148 #define SINGLE_GO               0x00010
149 // Bit 5 is unused!
150 #define INT_LAT0                0x00040
151 #define INT_LAT1                0x00080
152 #define INT_LAT2                0x00100
153 #define INT_LAT3                0x00200
154 #define INT_LAT4                0x00400
155 #define BUS_HOG                 0x00800
156 #define VERSION                 0x0F000
157 #define INT_LAT5                0x10000
158
159 extern uint32 jaguar_mainRom_crc32;
160
161 // Is opcode 62 *really* a NOP? Seems like it...
162 static void dsp_opcode_abs(void);
163 static void dsp_opcode_add(void);
164 static void dsp_opcode_addc(void);
165 static void dsp_opcode_addq(void);
166 static void dsp_opcode_addqmod(void);   
167 static void dsp_opcode_addqt(void);
168 static void dsp_opcode_and(void);
169 static void dsp_opcode_bclr(void);
170 static void dsp_opcode_bset(void);
171 static void dsp_opcode_btst(void);
172 static void dsp_opcode_cmp(void);
173 static void dsp_opcode_cmpq(void);
174 static void dsp_opcode_div(void);
175 static void dsp_opcode_imacn(void);
176 static void dsp_opcode_imult(void);
177 static void dsp_opcode_imultn(void);
178 static void dsp_opcode_jr(void);
179 static void dsp_opcode_jump(void);
180 static void dsp_opcode_load(void);
181 static void dsp_opcode_loadb(void);
182 static void dsp_opcode_loadw(void);
183 static void dsp_opcode_load_r14_indexed(void);
184 static void dsp_opcode_load_r14_ri(void);
185 static void dsp_opcode_load_r15_indexed(void);
186 static void dsp_opcode_load_r15_ri(void);
187 static void dsp_opcode_mirror(void);    
188 static void dsp_opcode_mmult(void);
189 static void dsp_opcode_move(void);
190 static void dsp_opcode_movei(void);
191 static void dsp_opcode_movefa(void);
192 static void dsp_opcode_move_pc(void);
193 static void dsp_opcode_moveq(void);
194 static void dsp_opcode_moveta(void);
195 static void dsp_opcode_mtoi(void);
196 static void dsp_opcode_mult(void);
197 static void dsp_opcode_neg(void);
198 static void dsp_opcode_nop(void);
199 static void dsp_opcode_normi(void);
200 static void dsp_opcode_not(void);
201 static void dsp_opcode_or(void);
202 static void dsp_opcode_resmac(void);
203 static void dsp_opcode_ror(void);
204 static void dsp_opcode_rorq(void);
205 static void dsp_opcode_xor(void);
206 static void dsp_opcode_sat16s(void);    
207 static void dsp_opcode_sat32s(void);    
208 static void dsp_opcode_sh(void);
209 static void dsp_opcode_sha(void);
210 static void dsp_opcode_sharq(void);
211 static void dsp_opcode_shlq(void);
212 static void dsp_opcode_shrq(void);
213 static void dsp_opcode_store(void);
214 static void dsp_opcode_storeb(void);
215 static void dsp_opcode_storew(void);
216 static void dsp_opcode_store_r14_indexed(void);
217 static void dsp_opcode_store_r14_ri(void);
218 static void dsp_opcode_store_r15_indexed(void);
219 static void dsp_opcode_store_r15_ri(void);
220 static void dsp_opcode_sub(void);
221 static void dsp_opcode_subc(void);
222 static void dsp_opcode_subq(void);
223 static void dsp_opcode_subqmod(void);   
224 static void dsp_opcode_subqt(void);
225
226 uint8 dsp_opcode_cycles[64] =
227 {
228         3,  3,  3,  3,  
229         3,  3,  3,  3,  
230         3,  3,  3,  3,  
231         3,  3,  3,  3,
232         3,  3,  1,  3,  
233         1, 18,  3,  3,  
234         3,  3,  3,  3,  
235         3,  3,  3,  3,
236         3,  3,  2,  2,  
237         2,  2,  3,  4,  
238         5,  4,  5,  6,  
239         6,  1,  1,  1,
240         1,  2,  2,  2,  
241         1,  1,  9,  3,  
242         3,  1,  6,  6,  
243         2,  2,  3,  3
244 };
245
246 void (* dsp_opcode[64])() =
247 {       
248         dsp_opcode_add,                                 dsp_opcode_addc,                                dsp_opcode_addq,                                dsp_opcode_addqt,
249         dsp_opcode_sub,                                 dsp_opcode_subc,                                dsp_opcode_subq,                                dsp_opcode_subqt,
250         dsp_opcode_neg,                                 dsp_opcode_and,                                 dsp_opcode_or,                                  dsp_opcode_xor,
251         dsp_opcode_not,                                 dsp_opcode_btst,                                dsp_opcode_bset,                                dsp_opcode_bclr,
252         dsp_opcode_mult,                                dsp_opcode_imult,                               dsp_opcode_imultn,                              dsp_opcode_resmac,
253         dsp_opcode_imacn,                               dsp_opcode_div,                                 dsp_opcode_abs,                                 dsp_opcode_sh,
254         dsp_opcode_shlq,                                dsp_opcode_shrq,                                dsp_opcode_sha,                                 dsp_opcode_sharq,
255         dsp_opcode_ror,                                 dsp_opcode_rorq,                                dsp_opcode_cmp,                                 dsp_opcode_cmpq,
256         dsp_opcode_subqmod,                             dsp_opcode_sat16s,                              dsp_opcode_move,                                dsp_opcode_moveq,
257         dsp_opcode_moveta,                              dsp_opcode_movefa,                              dsp_opcode_movei,                               dsp_opcode_loadb,
258         dsp_opcode_loadw,                               dsp_opcode_load,                                dsp_opcode_sat32s,                              dsp_opcode_load_r14_indexed,
259         dsp_opcode_load_r15_indexed,    dsp_opcode_storeb,                              dsp_opcode_storew,                              dsp_opcode_store,
260         dsp_opcode_mirror,                              dsp_opcode_store_r14_indexed,   dsp_opcode_store_r15_indexed,   dsp_opcode_move_pc,
261         dsp_opcode_jump,                                dsp_opcode_jr,                                  dsp_opcode_mmult,                               dsp_opcode_mtoi,
262         dsp_opcode_normi,                               dsp_opcode_nop,                                 dsp_opcode_load_r14_ri,                 dsp_opcode_load_r15_ri,
263         dsp_opcode_store_r14_ri,                dsp_opcode_store_r15_ri,                dsp_opcode_nop,                                 dsp_opcode_addqmod,
264 };
265
266 uint32 dsp_opcode_use[64];
267
268 char * dsp_opcode_str[64]=
269 {       
270         "add",                          "addc",                         "addq",                         "addqt",
271         "sub",                          "subc",                         "subq",                         "subqt",
272         "neg",                          "and",                          "or",                           "xor",
273         "not",                          "btst",                         "bset",                         "bclr",
274         "mult",                         "imult",                        "imultn",                       "resmac",
275         "imacn",                        "div",                          "abs",                          "sh",
276         "shlq",                         "shrq",                         "sha",                          "sharq",
277         "ror",                          "rorq",                         "cmp",                          "cmpq",
278         "subqmod",                      "sat16s",                       "move",                         "moveq",
279         "moveta",                       "movefa",                       "movei",                        "loadb",
280         "loadw",                        "load",                         "sat32s",                       "load_r14_indexed",
281         "load_r15_indexed",     "storeb",                       "storew",                       "store",
282         "mirror",                       "store_r14_indexed","store_r15_indexed","move_pc",
283         "jump",                         "jr",                           "mmult",                        "mtoi",
284         "normi",                        "nop",                          "load_r14_ri",          "load_r15_ri",
285         "store_r14_ri",         "store_r15_ri",         "nop",                          "addqmod",
286 };
287
288 uint32 dsp_pc;
289 static uint64 dsp_acc;                                                          // 40 bit register, NOT 32!
290 static uint32 dsp_remain;
291 static uint32 dsp_modulo;
292 static uint32 dsp_flags;
293 static uint32 dsp_matrix_control;
294 static uint32 dsp_pointer_to_matrix;
295 static uint32 dsp_data_organization;
296 uint32 dsp_control;
297 static uint32 dsp_div_control;
298 static uint8 dsp_flag_z, dsp_flag_n, dsp_flag_c;    
299 static uint32 * dsp_reg, * dsp_alternate_reg;
300 static uint32 * dsp_reg_bank_0, * dsp_reg_bank_1;
301
302 static uint32 dsp_opcode_first_parameter;
303 static uint32 dsp_opcode_second_parameter;
304
305 #define DSP_RUNNING                     (dsp_control & 0x01)
306
307 #define RM                                      dsp_reg[dsp_opcode_first_parameter]
308 #define RN                                      dsp_reg[dsp_opcode_second_parameter]
309 #define ALTERNATE_RM            dsp_alternate_reg[dsp_opcode_first_parameter]
310 #define ALTERNATE_RN            dsp_alternate_reg[dsp_opcode_second_parameter]
311 #define IMM_1                           dsp_opcode_first_parameter
312 #define IMM_2                           dsp_opcode_second_parameter
313
314 #define CLR_Z                           (dsp_flag_z = 0)
315 #define CLR_ZN                          (dsp_flag_z = dsp_flag_n = 0)
316 #define CLR_ZNC                         (dsp_flag_z = dsp_flag_n = dsp_flag_c = 0)
317 #define SET_Z(r)                        (dsp_flag_z = ((r) == 0))
318 #define SET_N(r)                        (dsp_flag_n = (((UINT32)(r) >> 31) & 0x01))
319 #define SET_C_ADD(a,b)          (dsp_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
320 #define SET_C_SUB(a,b)          (dsp_flag_c = ((UINT32)(b) > (UINT32)(a)))
321 #define SET_ZN(r)                       SET_N(r); SET_Z(r)
322 #define SET_ZNC_ADD(a,b,r)      SET_N(r); SET_Z(r); SET_C_ADD(a,b)
323 #define SET_ZNC_SUB(a,b,r)      SET_N(r); SET_Z(r); SET_C_SUB(a,b)
324
325 uint32 dsp_convert_zero[32] = { 32,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 };
326 uint8 * dsp_branch_condition_table = NULL;
327 static uint16 * mirror_table = NULL;
328 static uint8 * dsp_ram_8 = NULL;
329
330 #define BRANCH_CONDITION(x)             dsp_branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
331
332 static uint32 dsp_in_exec = 0;
333 static uint32 dsp_releaseTimeSlice_flag = 0;
334
335 FILE * dsp_fp;
336
337 // Private function prototypes
338
339 void DSPDumpRegisters(void);
340 void DSPDumpDisassembly(void);
341
342
343 void dsp_reset_stats(void)
344 {
345         for(int i=0; i<64; i++)
346                 dsp_opcode_use[i] = 0;
347 }
348
349 void dsp_releaseTimeslice(void)
350 {
351 //This does absolutely nothing!!! !!! FIX !!!
352         dsp_releaseTimeSlice_flag = 1;
353 }
354
355 void dsp_build_branch_condition_table(void)
356 {
357         // Allocate the mirror table
358         if (!mirror_table)
359                 mirror_table = (uint16 *)malloc(65536 * sizeof(mirror_table[0]));
360
361         // Fill in the mirror table
362         if (mirror_table)
363                 for(int i=0; i<65536; i++)
364                         mirror_table[i] = ((i >> 15) & 0x0001) | ((i >> 13) & 0x0002) |
365                                           ((i >> 11) & 0x0004) | ((i >> 9)  & 0x0008) |
366                                           ((i >> 7)  & 0x0010) | ((i >> 5)  & 0x0020) |
367                                           ((i >> 3)  & 0x0040) | ((i >> 1)  & 0x0080) |
368                                           ((i << 1)  & 0x0100) | ((i << 3)  & 0x0200) |
369                                           ((i << 5)  & 0x0400) | ((i << 7)  & 0x0800) |
370                                           ((i << 9)  & 0x1000) | ((i << 11) & 0x2000) |
371                                           ((i << 13) & 0x4000) | ((i << 15) & 0x8000);
372
373         if (!dsp_branch_condition_table)
374         {
375                 dsp_branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(dsp_branch_condition_table[0]));
376
377                 // Fill in the condition table
378                 if (dsp_branch_condition_table)
379                 {
380                         for(int i=0; i<8; i++)
381                         {
382                                 for(int j=0; j<32; j++)
383                                 {
384                                         int result = 1;
385                                         if (j & 1)
386                                                 if (i & ZERO_FLAG)
387                                                         result = 0;
388                                         if (j & 2)
389                                                 if (!(i & ZERO_FLAG))
390                                                         result = 0;
391                                         if (j & 4)
392                                                 if (i & (CARRY_FLAG << (j >> 4)))
393                                                         result = 0;
394                                         if (j & 8)
395                                                 if (!(i & (CARRY_FLAG << (j >> 4))))
396                                                         result = 0;
397                                         dsp_branch_condition_table[i * 32 + j] = result;
398                                 }
399                         }
400                 }
401         }
402 }
403
404 uint8 DSPReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
405 {
406 // battlemorph
407 //      if ((offset==0xF1CFE0)||(offset==0xF1CFE2))
408 //              return(0xffff);
409         // mutant penguin
410 /*      if ((jaguar_mainRom_crc32==0xbfd751a4)||(jaguar_mainRom_crc32==0x053efaf9))
411         {
412                 if (offset==0xF1CFE0)
413                         return(0xff);
414         }*/
415         if (offset >= DSP_WORK_RAM_BASE && offset <= (DSP_WORK_RAM_BASE + 0x1FFF))
416                 return dsp_ram_8[offset - DSP_WORK_RAM_BASE];
417
418         if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
419         {
420                 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
421
422                 if ((offset&0x03)==0)
423                         return(data>>24);
424                 else
425                 if ((offset&0x03)==1)
426                         return((data>>16)&0xff);
427                 else
428                 if ((offset&0x03)==2)
429                         return((data>>8)&0xff);
430                 else
431                 if ((offset&0x03)==3)
432                         return(data&0xff);
433         }
434
435         return JaguarReadByte(offset, who);
436
437
438 uint16 DSPReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
439 {
440         //???
441         offset &= 0xFFFFFFFE;
442         // jaguar cd bios
443 /*      if (jaguar_mainRom_crc32==0xa74a97cd)
444         {
445                 if (offset==0xF1A114) return(0x0000);
446                 if (offset==0xF1A116) return(0x0000);
447                 if (offset==0xF1B000) return(0x1234);
448                 if (offset==0xF1B002) return(0x5678);
449         }*/
450 /*
451         if (jaguar_mainRom_crc32==0x7ae20823)
452         {
453                 if (offset==0xF1B9D8) return(0x0000);
454                 if (offset==0xF1B9Da) return(0x0000);
455                 if (offset==0xF1B2C0) return(0x0000);
456                 if (offset==0xF1B2C2) return(0x0000);
457         }
458 */
459         // pour permettre Ã  wolfenstein 3d de tourner sans le dsp
460 /*      if ((offset==0xF1B0D0)||(offset==0xF1B0D2))
461                 return(0);
462 */
463
464                 // pour permettre Ã  nba jam de tourner sans le dsp
465 /*      if (jaguar_mainRom_crc32==0x4faddb18)
466         {
467                 if (offset==0xf1b2c0) return(0);
468                 if (offset==0xf1b2c2) return(0);
469                 if (offset==0xf1b240) return(0);
470                 if (offset==0xf1b242) return(0);
471                 if (offset==0xF1B340) return(0);
472                 if (offset==0xF1B342) return(0);
473                 if (offset==0xF1BAD8) return(0);
474                 if (offset==0xF1BADA) return(0);
475                 if (offset==0xF1B040) return(0);
476                 if (offset==0xF1B042) return(0);
477                 if (offset==0xF1B0C0) return(0);
478                 if (offset==0xF1B0C2) return(0);
479                 if (offset==0xF1B140) return(0);
480                 if (offset==0xF1B142) return(0);
481                 if (offset==0xF1B1C0) return(0);
482                 if (offset==0xF1B1C2) return(0);
483         }*/
484
485         if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE+0x1FFF)
486         {
487                 offset -= DSP_WORK_RAM_BASE;
488 /*              uint16 data = (((uint16)dsp_ram_8[offset])<<8)|((uint16)dsp_ram_8[offset+1]);
489                 return data;*/
490                 return GET16(dsp_ram_8, offset);
491         }
492         else if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
493         {
494                 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
495
496                 if (offset & 0x03)
497                         return data & 0xFFFF;
498                 else
499                         return data >> 16;
500         }
501
502         return JaguarReadWord(offset, who);
503 }
504
505 uint32 DSPReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
506 {
507         // ??? WHY ???
508         offset &= 0xFFFFFFFC;
509 /*if (offset == 0xF1BCF4)
510 {
511         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));
512         DSPDumpDisassembly();
513 }*/
514         if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
515         {
516                 offset -= DSP_WORK_RAM_BASE;
517                 return GET32(dsp_ram_8, offset);
518         }
519 //NOTE: Didn't return DSP_ACCUM!!!
520 //Mebbe it's not 'spose to! Yes, it is!
521         if (offset >= DSP_CONTROL_RAM_BASE && offset <= DSP_CONTROL_RAM_BASE + 0x23)
522         {
523                 offset &= 0x3F;
524                 switch (offset)
525                 {
526                 case 0x00:      /*dsp_flag_c?(dsp_flag_c=1):(dsp_flag_c=0);
527                                         dsp_flag_z?(dsp_flag_z=1):(dsp_flag_z=0);
528                                         dsp_flag_n?(dsp_flag_n=1):(dsp_flag_n=0);*/
529
530                                         dsp_flags = (dsp_flags & 0xFFFFFFF8) | (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
531                                         return dsp_flags & 0xFFFFC1FF;
532                 case 0x04: return dsp_matrix_control;
533                 case 0x08: return dsp_pointer_to_matrix;
534                 case 0x0C: return dsp_data_organization;
535                 case 0x10: return dsp_pc;
536                 case 0x14: return dsp_control;
537                 case 0x18: return dsp_modulo;
538                 case 0x1C: return dsp_remain;
539                 case 0x20:
540                         return (int32)((int8)(dsp_acc >> 32));  // Top 8 bits of 40-bit accumulator, sign extended
541                 }
542                 // unaligned long read-- !!! FIX !!!
543                 return 0xFFFFFFFF;
544         }
545
546         return JaguarReadLong(offset, who);
547 }
548
549 void DSPWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
550 {
551         if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
552         {
553                 offset -= DSP_WORK_RAM_BASE;
554                 dsp_ram_8[offset] = data;
555 //This is rather stupid! !!! FIX !!!
556 /*              if (dsp_in_exec == 0)
557                 {
558                         m68k_end_timeslice();
559                         gpu_releaseTimeslice();
560                 }*/
561                 return;
562         }
563         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
564         {
565                 uint32 reg = offset & 0x1C;
566                 int bytenum = offset & 0x03;
567                 
568                 if ((reg >= 0x1C) && (reg <= 0x1F))
569                         dsp_div_control = (dsp_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
570                 else
571                 {
572 //This looks funky. !!! FIX !!!
573                         uint32 old_data = DSPReadLong(offset&0xFFFFFFC, who);
574                         bytenum = 3 - bytenum; // convention motorola !!!
575                         old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3)); 
576                         DSPWriteLong(offset & 0xFFFFFFC, old_data, who);
577                 }
578                 return;
579         }
580 //      WriteLog("dsp: writing %.2x at 0x%.8x\n",data,offset);
581 //Should this *ever* happen??? Shouldn't we be saying "unknown" here???
582         JaguarWriteByte(offset, data, who);
583 }
584
585 void DSPWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
586 {
587         offset &= 0xFFFFFFFE;
588 /*if (offset == 0xF1BCF4)
589 {
590         WriteLog("DSPWriteWord: Writing to 0xF1BCF4... %04X -> %04X\n", GET16(dsp_ram_8, 0x0CF4), data);
591 }*/
592 //      WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset);
593         if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
594         {
595                 offset -= DSP_WORK_RAM_BASE;
596                 dsp_ram_8[offset] = data >> 8;
597                 dsp_ram_8[offset+1] = data & 0xFF;
598 //This is rather stupid! !!! FIX !!!
599 /*              if (dsp_in_exec == 0)
600                 {
601 //                      WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset+DSP_WORK_RAM_BASE);
602                         m68k_end_timeslice();
603                         gpu_releaseTimeslice();
604                 }*/
605                 return;
606         }
607         else if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
608         {
609                 if ((offset & 0x1C) == 0x1C)
610                 {
611                         if (offset & 0x03)
612                                 dsp_div_control = (dsp_div_control&0xffff0000)|(data&0xffff);
613                         else
614                                 dsp_div_control = (dsp_div_control&0xffff)|((data&0xffff)<<16);
615                 }
616                 else
617                 {
618                         uint32 old_data = DSPReadLong(offset & 0xffffffc, who);
619                         if (offset & 0x03)
620                                 old_data = (old_data&0xffff0000)|(data&0xffff);
621                         else
622                                 old_data = (old_data&0xffff)|((data&0xffff)<<16);
623                         DSPWriteLong(offset & 0xffffffc, old_data, who);
624                 }
625                 return;
626         }
627
628         JaguarWriteWord(offset, data, who);
629 }
630
631 void DSPWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
632 {
633         // ??? WHY ???
634         offset &= 0xFFFFFFFC;
635 /*if (offset == 0xF1BCF4)
636 {
637         WriteLog("DSPWriteLong: Writing to 0xF1BCF4... %08X -> %08X\n", GET32(dsp_ram_8, 0x0CF4), data);
638 }*/
639 //      WriteLog("dsp: writing %.8x at 0x%.8x\n",data,offset);
640         if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
641         {
642 /*if (offset == 0xF1BE2C)
643 {
644         WriteLog("DSP: %s is writing %08X at location 0xF1BE2C (DSP_PC: %08X)...\n", whoName[who], data, dsp_pc - 2);
645 }//*/
646                 offset -= DSP_WORK_RAM_BASE;
647                 SET32(dsp_ram_8, offset, data);
648                 return;
649         }
650         else if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
651         {
652                 offset &= 0x1F;
653                 switch (offset)
654                 {
655                 case 0x00:
656                 {
657                         bool IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
658                         dsp_flags = data;
659                         dsp_flag_z = dsp_flags & 0x01;
660                         dsp_flag_c = (dsp_flags >> 1) & 0x01;
661                         dsp_flag_n = (dsp_flags >> 2) & 0x01;
662                         DSPUpdateRegisterBanks();
663                         dsp_control &= ~((dsp_flags & CINT04FLAGS) >> 3);
664                         dsp_control &= ~((dsp_flags & CINT5FLAG) >> 1);
665                         if (IMASKCleared)                                               // If IMASK was cleared,
666 #ifdef DSP_DEBUG_IRQ
667                         {
668                                 WriteLog("DSP: Finished interrupt.\n");
669 #endif
670                                 DSPHandleIRQs();                                        // see if any other interrupts need servicing!
671 #ifdef DSP_DEBUG_IRQ
672                         }
673 #endif
674                         break;
675                 }
676                 case 0x04:
677                         dsp_matrix_control = data;
678                         break;
679                 case 0x08:
680                         dsp_pointer_to_matrix = data;
681                         break;
682                 case 0x0C:
683                         dsp_data_organization = data;
684                         break;
685                 case 0x10:
686                         dsp_pc = data;
687 #ifdef DSP_DEBUG
688                         WriteLog("DSP: Setting DSP PC to %08X by %s%s\n", dsp_pc, whoName[who], (DSP_RUNNING ? " (DSP is RUNNING!)" : ""));//*/
689 #endif
690                         break;
691                 case 0x14:
692                 {       
693 //                      uint32 dsp_was_running = DSP_RUNNING;
694                         // Check for DSP -> CPU interrupt
695                         if (data & CPUINT)
696                         {
697 //                              WriteLog("DSP: DSP -> CPU interrupt\n");
698 // This was WRONG
699 // Why do we check for a valid handler at 64? Isn't that the Jag programmer's responsibility?
700                                 if (JERRYIRQEnabled(IRQ2_DSP) && jaguar_interrupt_handler_is_valid(64))
701                                 {
702                                         JERRYSetPendingIRQ(IRQ2_DSP);
703                                         dsp_releaseTimeslice();
704                                         m68k_set_irq(7);                        // Set 68000 NMI...
705                                 }
706                                 data &= ~CPUINT;
707                         }
708                         // Check for CPU -> DSP interrupt
709                         if (data & DSPINT0)
710                         {
711 //                              WriteLog("DSP: CPU -> DSP interrupt\n");
712                                 m68k_end_timeslice();
713                                 gpu_releaseTimeslice();
714                                 DSPSetIRQLine(DSPIRQ_CPU, ASSERT_LINE);
715                                 data &= ~DSPINT0;
716                         }
717                         // single stepping
718                         if (data & SINGLE_STEP)
719                         {
720 //                              WriteLog("DSP: Asked to perform a single step (single step is %senabled)\n", (data & 0x8 ? "" : "not "));
721                         }
722
723                         // Protect writes to VERSION and the interrupt latches...
724                         uint32 mask = VERSION | INT_LAT0 | INT_LAT1 | INT_LAT2 | INT_LAT3 | INT_LAT4 | INT_LAT5;
725                         dsp_control = (dsp_control & mask) | (data & ~mask);
726
727                         // if dsp wasn't running but is now running
728                         // execute a few cycles
729 //This is just plain wrong, wrong, WRONG!
730 #ifndef DSP_SINGLE_STEPPING
731 /*                      if (!dsp_was_running && DSP_RUNNING)
732                         {
733                                 DSPExec(200);
734                         }*/
735 #else
736 //This is WRONG! !!! FIX !!!
737                         if (dsp_control & 0x18)
738                                 DSPExec(1);
739 #endif
740 #ifdef DSP_DEBUG
741 WriteLog("Write to DSP CTRL: %08X ", data);
742 if (DSP_RUNNING)
743         WriteLog(" --> Starting to run at %08X by %s...", dsp_pc, whoName[who]);
744 else
745         WriteLog(" --> Stopped by %s! (DSP PC: %08X)", whoName[who], dsp_pc);
746 WriteLog("\n");
747 #endif  // DSP_DEBUG
748 //This isn't exactly right either--we don't know if it was the M68K or the GPU writing here...
749 // !!! FIX !!!
750                         if (DSP_RUNNING)
751                                 m68k_end_timeslice();
752                         break;
753                 }
754                 case 0x18:
755                         dsp_modulo = data;
756                         break;
757                 case 0x1C:
758                         dsp_div_control = data;
759                         break;
760 //              default:   // unaligned long read
761                                    //__asm int 3
762                 }
763                 return;
764         }
765
766 //We don't have to break this up like this! We CAN do 32 bit writes!
767 //      JaguarWriteWord(offset, (data>>16) & 0xFFFF, DSP);
768 //      JaguarWriteWord(offset+2, data & 0xFFFF, DSP);
769         JaguarWriteLong(offset, data, who);
770 }
771
772 //
773 // Update the DSP register file pointers depending on REGPAGE bit
774 //
775 void DSPUpdateRegisterBanks(void)
776 {
777         int bank = (dsp_flags & REGPAGE);
778
779         if (dsp_flags & IMASK)
780                 bank = 0;                                                       // IMASK forces main bank to be bank 0
781
782         if (bank)
783                 dsp_reg = dsp_reg_bank_1, dsp_alternate_reg = dsp_reg_bank_0;
784         else
785                 dsp_reg = dsp_reg_bank_0, dsp_alternate_reg = dsp_reg_bank_1;
786 }
787
788 //
789 // Check for an handle any asserted DSP IRQs
790 //
791 void DSPHandleIRQs(void)
792 {
793         if (dsp_flags & IMASK)                                                  // Bail if we're already inside an interrupt
794                 return;
795
796         // Get the active interrupt bits (latches) & interrupt mask (enables)
797         uint32 bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
798                 mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
799
800 //      WriteLog("dsp: bits=%.2x mask=%.2x\n",bits,mask);
801         bits &= mask;
802
803         if (!bits)                                                                              // Bail if nothing is enabled
804                 return;
805
806         int which = 0;                                                                  // Determine which interrupt 
807         if (bits & 0x01)
808                 which = 0;
809         if (bits & 0x02)
810                 which = 1;
811         if (bits & 0x04)
812                 which = 2;
813         if (bits & 0x08)
814                 which = 3;
815         if (bits & 0x10)
816                 which = 4;
817         if (bits & 0x20)
818                 which = 5;
819
820 #ifdef DSP_DEBUG_IRQ
821         WriteLog("DSP: Generating interrupt #%i...\n", which);
822 #endif
823
824         dsp_flags |= IMASK;
825         DSPUpdateRegisterBanks();
826
827         // subqt  #4,r31                ; pre-decrement stack pointer 
828         // move  pc,r30                 ; address of interrupted code 
829         // store  r30,(r31)     ; store return address
830         dsp_reg[31] -= 4;
831         DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
832
833         // movei  #service_address,r30  ; pointer to ISR entry 
834         // jump  (r30)                                  ; jump to ISR 
835         // nop
836         dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
837 }
838
839 //
840 // Set the specified DSP IRQ line to a given state
841 //
842 void DSPSetIRQLine(int irqline, int state)
843 {
844 //NOTE: This doesn't take INT_LAT5 into account. !!! FIX !!!
845         uint32 mask = INT_LAT0 << irqline;
846         dsp_control &= ~mask;                                                   // Clear the latch bit
847
848         if (state)
849         {
850                 dsp_control |= mask;                                            // Set the latch bit
851                 DSPHandleIRQs();
852         }
853 }
854
855 void DSPInit(void)
856 {
857         memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
858         memory_malloc_secure((void **)&dsp_reg_bank_0, 32 * sizeof(int32), "DSP bank 0 regs");
859         memory_malloc_secure((void **)&dsp_reg_bank_1, 32 * sizeof(int32), "DSP bank 1 regs");
860
861         dsp_build_branch_condition_table();
862         DSPReset();
863 }
864
865 void DSPReset(void)
866 {
867         dsp_pc                            = 0x00F1B000;
868         dsp_acc                           = 0x00000000;
869         dsp_remain                        = 0x00000000;
870         dsp_modulo                        = 0xFFFFFFFF;
871         dsp_flags                         = 0x00040000;
872         dsp_matrix_control    = 0x00000000;
873         dsp_pointer_to_matrix = 0x00000000;
874         dsp_data_organization = 0xFFFFFFFF;
875         dsp_control                       = 0x00002000;                         // Report DSP version 2
876         dsp_div_control           = 0x00000000;
877         dsp_in_exec                       = 0;
878
879         dsp_reg = dsp_reg_bank_0;
880         dsp_alternate_reg = dsp_reg_bank_1;
881
882         for(int i=0; i<32; i++)
883                 dsp_reg[i] = dsp_alternate_reg[i] = 0x00000000;
884
885         CLR_ZNC;
886
887         dsp_reset_stats();
888         memset(dsp_ram_8, 0xFF, 0x2000);
889 }
890
891 void DSPDumpDisassembly(void)
892 {
893         char buffer[512];
894
895         WriteLog("\n---[DSP code at 00F1B000]---------------------------\n");
896         uint32 j = 0xF1B000;
897         while (j <= 0xF1CFFF)
898         {
899                 uint32 oldj = j;
900                 j += dasmjag(JAGUAR_DSP, buffer, j);
901                 WriteLog("\t%08X: %s\n", oldj, buffer);
902         }
903 }
904
905 void DSPDumpRegisters(void)
906 {
907 //Shoud add modulus, etc to dump here...
908         WriteLog("\n---[DSP flags: NCZ %d%d%d, DSP PC: %08X]------------\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_pc);
909         WriteLog("\nRegisters bank 0\n");
910         for(int j=0; j<8; j++)
911         {
912                 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
913                                                   (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
914                                                   (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
915                                                   (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
916                                                   (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
917         }
918         WriteLog("Registers bank 1\n");
919         for(int j=0; j<8; j++)
920         {
921                 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
922                                                   (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
923                                                   (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
924                                                   (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
925                                                   (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
926         }
927 }
928
929 void DSPDone(void)
930 {
931         int i, j;
932         WriteLog("DSP: Stopped at PC=%08X dsp_modulo=%08X (dsp %s running)\n", dsp_pc, dsp_modulo, (DSP_RUNNING ? "was" : "wasn't"));
933         WriteLog("DSP: %sin interrupt handler\n", (dsp_flags & IMASK ? "" : "not "));
934
935         // get the active interrupt bits 
936         int bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F);
937         // get the interrupt mask 
938         int mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
939
940         WriteLog("DSP: pending=%08X enabled=%08X\n", bits, mask);
941         WriteLog("\nRegisters bank 0\n");
942         for(int j=0; j<8; j++)
943         {
944                 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
945                                                   (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
946                                                   (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
947                                                   (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
948                                                   (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
949         }
950         WriteLog("\nRegisters bank 1\n");
951         for (j=0; j<8; j++)
952         {
953                 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
954                                                   (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
955                                                   (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
956                                                   (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
957                                                   (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
958
959         }
960
961         static char buffer[512];
962         j = DSP_WORK_RAM_BASE;
963         while (j <= 0xF1BFFF)
964         {
965                 uint32 oldj = j;
966                 j += dasmjag(JAGUAR_DSP, buffer, j);
967                 WriteLog("\t%08X: %s\n", oldj, buffer);
968         }//*/
969
970         WriteLog("DSP opcodes use:\n");
971         for (i=0;i<64;i++)
972         {
973                 if (dsp_opcode_use[i])
974                         WriteLog("\t%s %i\n", dsp_opcode_str[i], dsp_opcode_use[i]);
975         }//*/
976
977         memory_free(dsp_ram_8);
978 }
979
980 //
981 // DSP execution core
982 //
983 static bool R20Set = false, tripwire = false;
984 static uint32 pcQueue[32], ptrPCQ = 0;
985 void DSPExec(int32 cycles)
986 {
987 /*HACKS!!! ->   if (cycles != 1 && jaguar_mainRom_crc32 == 0xba74c3ed)
988                 dsp_check_if_i2s_interrupt_needed();*/
989
990 #ifdef DSP_SINGLE_STEPPING
991         if (dsp_control & 0x18)
992         {
993                 cycles = 1;
994                 dsp_control &= ~0x10;
995         }
996 #endif
997 //There is *no* good reason to do this here!
998 //      DSPHandleIRQs();
999         dsp_releaseTimeSlice_flag = 0;
1000         dsp_in_exec++;
1001
1002         while (cycles > 0 && DSP_RUNNING)
1003         {
1004 if (dsp_pc == 0xF1B5D8)
1005 {
1006         WriteLog("DSP: At $F1B4D8--R15 = %08X at %u ms%s...\n", dsp_reg[15], SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1007 }
1008 /*if (dsp_pc == 0xF1B7D2)       // Start here???
1009         doDSPDis = true;
1010 pcQueue[ptrPCQ++] = dsp_pc;
1011 ptrPCQ %= 32;*/
1012                 uint16 opcode = DSPReadWord(dsp_pc, DSP);
1013                 uint32 index = opcode >> 10;
1014                 dsp_opcode_first_parameter = (opcode >> 5) & 0x1F;
1015                 dsp_opcode_second_parameter = opcode & 0x1F;
1016                 dsp_pc += 2;
1017                 dsp_opcode[index]();
1018                 dsp_opcode_use[index]++;
1019                 cycles -= dsp_opcode_cycles[index];
1020 /*if (dsp_reg_bank_0[20] == 0xF1A100 & !R20Set)
1021 {
1022         WriteLog("DSP: R20 set to $F1A100 at %u ms%s...\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1023         R20Set = true;
1024 }
1025 if (dsp_reg_bank_0[20] != 0xF1A100 && R20Set)
1026 {
1027         WriteLog("DSP: R20 corrupted at %u ms from starting%s!\nAborting!\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1028         DSPDumpRegisters();
1029         DSPDumpDisassembly();
1030         exit(1);
1031 }
1032 if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFE) && !tripwire)
1033 {
1034         char buffer[512];
1035         WriteLog("DSP: Jumping outside of DSP RAM at %u ms. Register dump:\n", SDL_GetTicks());
1036         DSPDumpRegisters();
1037         tripwire = true;
1038         WriteLog("\nBacktrace:\n");
1039         for(int i=0; i<32; i++)
1040         {
1041                 dasmjag(JAGUAR_DSP, buffer, pcQueue[(ptrPCQ + i) % 32]);
1042                 WriteLog("\t%08X: %s\n", pcQueue[(ptrPCQ + i) % 32], buffer);
1043         }
1044         WriteLog("\n");
1045 }*/
1046         }
1047
1048         dsp_in_exec--;
1049 }
1050
1051 //
1052 // DSP opcode handlers
1053 //
1054
1055 // There is a problem here with interrupt handlers the JUMP and JR instructions that
1056 // can cause trouble because an interrupt can occur *before* the instruction following the
1057 // jump can execute... !!! FIX !!!
1058 static void dsp_opcode_jump(void)
1059 {
1060 #ifdef DSP_DIS_JUMP
1061 char * condition[32] =
1062 {       "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1063         "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1064         "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1065         "???", "???", "???", "F" };
1066         if (doDSPDis)
1067                 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);
1068 #endif
1069         // normalize flags
1070 /*      dsp_flag_c=dsp_flag_c?1:0;
1071         dsp_flag_z=dsp_flag_z?1:0;
1072         dsp_flag_n=dsp_flag_n?1:0;*/
1073         // KLUDGE: Used by BRANCH_CONDITION
1074         uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1075
1076         if (BRANCH_CONDITION(IMM_2))
1077         {
1078 #ifdef DSP_DIS_JUMP
1079         if (doDSPDis)
1080                 WriteLog("Branched!\n");
1081 #endif
1082                 uint32 delayed_pc = RM;
1083                 DSPExec(1);
1084                 dsp_pc = delayed_pc;
1085         }
1086 #ifdef DSP_DIS_JUMP
1087         else
1088                 if (doDSPDis)
1089                         WriteLog("Branch NOT taken.\n");
1090 #endif
1091 }
1092
1093 static void dsp_opcode_jr(void)
1094 {
1095 #ifdef DSP_DIS_JR
1096 char * condition[32] =
1097 {       "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1098         "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1099         "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1100         "???", "???", "???", "F" };
1101         if (doDSPDis)
1102                 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);
1103 #endif
1104         // normalize flags
1105 /*      dsp_flag_c=dsp_flag_c?1:0;
1106         dsp_flag_z=dsp_flag_z?1:0;
1107         dsp_flag_n=dsp_flag_n?1:0;*/
1108         // KLUDGE: Used by BRANCH_CONDITION
1109         uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1110
1111         if (BRANCH_CONDITION(IMM_2))
1112         {
1113 #ifdef DSP_DIS_JR
1114         if (doDSPDis)
1115                 WriteLog("Branched!\n");
1116 #endif
1117                 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1);             // Sign extend IMM_1
1118                 int32 delayed_pc = dsp_pc + (offset * 2);
1119                 DSPExec(1);
1120                 dsp_pc = delayed_pc;
1121         }
1122 #ifdef DSP_DIS_JR
1123         else
1124                 if (doDSPDis)
1125                         WriteLog("Branch NOT taken.\n");
1126 #endif
1127 }
1128
1129 static void dsp_opcode_add(void)
1130 {
1131 #ifdef DSP_DIS_ADD
1132         if (doDSPDis)
1133                 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);
1134 #endif
1135         UINT32 res = RN + RM;
1136         SET_ZNC_ADD(RN, RM, res);
1137         RN = res;
1138 #ifdef DSP_DIS_ADD
1139         if (doDSPDis)
1140                 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);
1141 #endif
1142 }
1143
1144 static void dsp_opcode_addc(void)
1145 {
1146 #ifdef DSP_DIS_ADDC
1147         if (doDSPDis)
1148                 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);
1149 #endif
1150         UINT32 res = RN + RM + dsp_flag_c;
1151         UINT32 carry = dsp_flag_c;
1152 //      SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1153         SET_ZNC_ADD(RN + carry, RM, res);
1154 //      SET_ZNC_ADD(RN, RM + carry, res);
1155         RN = res;
1156 #ifdef DSP_DIS_ADDC
1157         if (doDSPDis)
1158                 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);
1159 #endif
1160 }
1161
1162 static void dsp_opcode_addq(void)
1163 {
1164 #ifdef DSP_DIS_ADDQ
1165         if (doDSPDis)
1166                 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);
1167 #endif
1168         UINT32 r1 = dsp_convert_zero[IMM_1];
1169         UINT32 res = RN + r1;
1170         CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1171         RN = res;
1172 #ifdef DSP_DIS_ADDQ
1173         if (doDSPDis)
1174                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1175 #endif
1176 }
1177
1178 static void dsp_opcode_sub(void)
1179 {
1180 #ifdef DSP_DIS_SUB
1181         if (doDSPDis)
1182                 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);
1183 #endif
1184         UINT32 res = RN - RM;
1185         SET_ZNC_SUB(RN, RM, res);
1186         RN = res;
1187 #ifdef DSP_DIS_SUB
1188         if (doDSPDis)
1189                 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);
1190 #endif
1191 }
1192
1193 static void dsp_opcode_subc(void)
1194 {
1195 #ifdef DSP_DIS_SUBC
1196         if (doDSPDis)
1197                 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);
1198 #endif
1199         UINT32 res = RN - RM - dsp_flag_c;
1200         UINT32 borrow = dsp_flag_c;
1201         SET_ZNC_SUB(RN - borrow, RM, res);
1202         RN = res;
1203 #ifdef DSP_DIS_SUBC
1204         if (doDSPDis)
1205                 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);
1206 #endif
1207 }
1208
1209 static void dsp_opcode_subq(void)
1210 {
1211 #ifdef DSP_DIS_SUBQ
1212         if (doDSPDis)
1213                 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);
1214 #endif
1215         UINT32 r1 = dsp_convert_zero[IMM_1];
1216         UINT32 res = RN - r1;
1217         SET_ZNC_SUB(RN, r1, res);
1218         RN = res;
1219 #ifdef DSP_DIS_SUBQ
1220         if (doDSPDis)
1221                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1222 #endif
1223 }
1224
1225 static void dsp_opcode_cmp(void)
1226 {
1227 #ifdef DSP_DIS_CMP
1228         if (doDSPDis)
1229                 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);
1230 #endif
1231         UINT32 res = RN - RM;
1232         SET_ZNC_SUB(RN, RM, res);
1233 #ifdef DSP_DIS_CMP
1234         if (doDSPDis)
1235                 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1236 #endif
1237 }
1238
1239 static void dsp_opcode_cmpq(void)
1240 {
1241         static int32 sqtable[32] =
1242                 { 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 };
1243 #ifdef DSP_DIS_CMPQ
1244         if (doDSPDis)
1245                 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);
1246 #endif
1247         UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1248         UINT32 res = RN - r1;
1249         SET_ZNC_SUB(RN, r1, res);
1250 #ifdef DSP_DIS_CMPQ
1251         if (doDSPDis)
1252                 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1253 #endif
1254 }
1255
1256 static void dsp_opcode_and(void)
1257 {
1258 #ifdef DSP_DIS_AND
1259         if (doDSPDis)
1260                 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);
1261 #endif
1262         RN = RN & RM;
1263         SET_ZN(RN);
1264 #ifdef DSP_DIS_AND
1265         if (doDSPDis)
1266                 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);
1267 #endif
1268 }
1269
1270 static void dsp_opcode_or(void)
1271 {
1272 #ifdef DSP_DIS_OR
1273         if (doDSPDis)
1274                 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);
1275 #endif
1276         RN = RN | RM;
1277         SET_ZN(RN);
1278 #ifdef DSP_DIS_OR
1279         if (doDSPDis)
1280                 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);
1281 #endif
1282 }
1283
1284 static void dsp_opcode_xor(void)
1285 {
1286 #ifdef DSP_DIS_XOR
1287         if (doDSPDis)
1288                 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);
1289 #endif
1290         RN = RN ^ RM;
1291         SET_ZN(RN);
1292 #ifdef DSP_DIS_XOR
1293         if (doDSPDis)
1294                 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);
1295 #endif
1296 }
1297
1298 static void dsp_opcode_not(void)
1299 {
1300 #ifdef DSP_DIS_NOT
1301         if (doDSPDis)
1302                 WriteLog("%06X: NOT    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);
1303 #endif
1304         RN = ~RN;
1305         SET_ZN(RN);
1306 #ifdef DSP_DIS_NOT
1307         if (doDSPDis)
1308                 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);
1309 #endif
1310 }
1311
1312 static void dsp_opcode_move_pc(void)
1313 {
1314         RN = dsp_pc - 2;
1315 }
1316
1317 static void dsp_opcode_store_r14_indexed(void)
1318 {
1319 #ifdef DSP_DIS_STORE14I
1320         if (doDSPDis)
1321                 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));
1322 #endif
1323         DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1324 }
1325
1326 static void dsp_opcode_store_r15_indexed(void)
1327 {
1328 #ifdef DSP_DIS_STORE15I
1329         if (doDSPDis)
1330                 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));
1331 #endif
1332         DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1333 }
1334
1335 static void dsp_opcode_load_r14_ri(void)
1336 {
1337 #ifdef DSP_DIS_LOAD14R
1338         if (doDSPDis)
1339                 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);
1340 #endif
1341         RN = DSPReadLong(dsp_reg[14] + RM, DSP);
1342 #ifdef DSP_DIS_LOAD14R
1343         if (doDSPDis)
1344                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1345 #endif
1346 }
1347
1348 static void dsp_opcode_load_r15_ri(void)
1349 {
1350 #ifdef DSP_DIS_LOAD15R
1351         if (doDSPDis)
1352                 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);
1353 #endif
1354         RN = DSPReadLong(dsp_reg[15] + RM, DSP);
1355 #ifdef DSP_DIS_LOAD15R
1356         if (doDSPDis)
1357                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1358 #endif
1359 }
1360
1361 static void dsp_opcode_store_r14_ri(void)
1362 {
1363         DSPWriteLong(dsp_reg[14] + RM, RN, DSP);
1364 }
1365
1366 static void dsp_opcode_store_r15_ri(void)
1367 {
1368         DSPWriteLong(dsp_reg[15] + RM, RN, DSP);
1369 }
1370
1371 static void dsp_opcode_nop(void)
1372 {
1373 #ifdef DSP_DIS_NOP
1374         if (doDSPDis)
1375                 WriteLog("%06X: NOP    [NCZ:%u%u%u]\n", dsp_pc-2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
1376 #endif
1377 }
1378
1379 static void dsp_opcode_storeb(void)
1380 {
1381 #ifdef DSP_DIS_STOREB
1382         if (doDSPDis)
1383                 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);
1384 #endif
1385         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1386                 DSPWriteLong(RM, RN & 0xFF, DSP);
1387         else
1388                 JaguarWriteByte(RM, RN, DSP);
1389 }
1390
1391 static void dsp_opcode_storew(void)
1392 {
1393 #ifdef DSP_DIS_STOREW
1394         if (doDSPDis)
1395                 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);
1396 #endif
1397         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1398                 DSPWriteLong(RM, RN & 0xFFFF, DSP);
1399         else
1400                 JaguarWriteWord(RM, RN, DSP);
1401 }
1402
1403 static void dsp_opcode_store(void)
1404 {
1405 #ifdef DSP_DIS_STORE
1406         if (doDSPDis)
1407                 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);
1408 #endif
1409         DSPWriteLong(RM, RN, DSP);
1410 }
1411
1412 static void dsp_opcode_loadb(void)
1413 {
1414 #ifdef DSP_DIS_LOADB
1415         if (doDSPDis)
1416                 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);
1417 #endif
1418         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1419                 RN = DSPReadLong(RM, DSP) & 0xFF;
1420         else
1421                 RN = JaguarReadByte(RM, DSP);
1422 #ifdef DSP_DIS_LOADB
1423         if (doDSPDis)
1424                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1425 #endif
1426 }
1427
1428 static void dsp_opcode_loadw(void)
1429 {
1430 #ifdef DSP_DIS_LOADW
1431         if (doDSPDis)
1432                 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);
1433 #endif
1434         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1435                 RN = DSPReadLong(RM, DSP) & 0xFFFF;
1436         else
1437                 RN = JaguarReadWord(RM, DSP);
1438 #ifdef DSP_DIS_LOADW
1439         if (doDSPDis)
1440                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1441 #endif
1442 }
1443
1444 static void dsp_opcode_load(void)
1445 {
1446 #ifdef DSP_DIS_LOAD
1447         if (doDSPDis)
1448                 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);
1449 #endif
1450         RN = DSPReadLong(RM, DSP);
1451 #ifdef DSP_DIS_LOAD
1452         if (doDSPDis)
1453                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1454 #endif
1455 }
1456
1457 static void dsp_opcode_load_r14_indexed(void)
1458 {
1459 #ifdef DSP_DIS_LOAD14I
1460         if (doDSPDis)
1461                 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);
1462 #endif
1463         RN = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), DSP);
1464 #ifdef DSP_DIS_LOAD14I
1465         if (doDSPDis)
1466                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1467 #endif
1468 }
1469
1470 static void dsp_opcode_load_r15_indexed(void)
1471 {
1472 #ifdef DSP_DIS_LOAD15I
1473         if (doDSPDis)
1474                 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);
1475 #endif
1476         RN = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), DSP);
1477 #ifdef DSP_DIS_LOAD15I
1478         if (doDSPDis)
1479                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1480 #endif
1481 }
1482
1483 static void dsp_opcode_movei(void)
1484 {
1485 #ifdef DSP_DIS_MOVEI
1486         if (doDSPDis)
1487                 WriteLog("%06X: MOVEI  #$%08X, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, (uint32)DSPReadWord(dsp_pc) | ((uint32)DSPReadWord(dsp_pc + 2) << 16), IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1488 #endif
1489         // This instruction is followed by 32-bit value in LSW / MSW format...
1490         RN = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
1491         dsp_pc += 4;
1492 #ifdef DSP_DIS_MOVEI
1493         if (doDSPDis)
1494                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1495 #endif
1496 }
1497
1498 static void dsp_opcode_moveta(void)
1499 {
1500 #ifdef DSP_DIS_MOVETA
1501         if (doDSPDis)
1502                 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);
1503 #endif
1504         ALTERNATE_RN = RM;
1505 #ifdef DSP_DIS_MOVETA
1506         if (doDSPDis)
1507                 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);
1508 #endif
1509 }
1510
1511 static void dsp_opcode_movefa(void)
1512 {
1513 #ifdef DSP_DIS_MOVEFA
1514         if (doDSPDis)
1515                 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);
1516 #endif
1517         RN = ALTERNATE_RM;
1518 #ifdef DSP_DIS_MOVEFA
1519         if (doDSPDis)
1520                 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);
1521 #endif
1522 }
1523
1524 static void dsp_opcode_move(void)
1525 {
1526 #ifdef DSP_DIS_MOVE
1527         if (doDSPDis)
1528                 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);
1529 #endif
1530         RN = RM;
1531 #ifdef DSP_DIS_MOVE
1532         if (doDSPDis)
1533                 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);
1534 #endif
1535 }
1536
1537 static void dsp_opcode_moveq(void)
1538 {
1539 #ifdef DSP_DIS_MOVEQ
1540         if (doDSPDis)
1541                 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);
1542 #endif
1543         RN = IMM_1;
1544 #ifdef DSP_DIS_MOVEQ
1545         if (doDSPDis)
1546                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1547 #endif
1548 }
1549
1550 static void dsp_opcode_resmac(void)
1551 {
1552 #ifdef DSP_DIS_RESMAC
1553         if (doDSPDis)
1554                 WriteLog("%06X: RESMAC R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_ACC=%02X%08X] -> ", dsp_pc-2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
1555 #endif
1556         RN = (uint32)dsp_acc;
1557 #ifdef DSP_DIS_RESMAC
1558         if (doDSPDis)
1559                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1560 #endif
1561 }
1562
1563 static void dsp_opcode_imult(void)
1564 {
1565 #ifdef DSP_DIS_IMULT
1566         if (doDSPDis)
1567                 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);
1568 #endif
1569         RN = (int16)RN * (int16)RM;
1570         SET_ZN(RN);
1571 #ifdef DSP_DIS_IMULT
1572         if (doDSPDis)
1573                 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);
1574 #endif
1575 }
1576
1577 static void dsp_opcode_mult(void)
1578 {
1579 #ifdef DSP_DIS_MULT
1580         if (doDSPDis)
1581                 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);
1582 #endif
1583         RN = (uint16)RM * (uint16)RN;
1584         SET_ZN(RN);
1585 #ifdef DSP_DIS_MULT
1586         if (doDSPDis)
1587                 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);
1588 #endif
1589 }
1590
1591 static void dsp_opcode_bclr(void)
1592 {
1593 #ifdef DSP_DIS_BCLR
1594         if (doDSPDis)
1595                 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);
1596 #endif
1597         UINT32 res = RN & ~(1 << IMM_1);
1598         RN = res;
1599         SET_ZN(res);
1600 #ifdef DSP_DIS_BCLR
1601         if (doDSPDis)
1602                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1603 #endif
1604 }
1605
1606 static void dsp_opcode_btst(void)
1607 {
1608 #ifdef DSP_DIS_BTST
1609         if (doDSPDis)
1610                 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);
1611 #endif
1612         dsp_flag_z = (~RN >> IMM_1) & 1;
1613 #ifdef DSP_DIS_BTST
1614         if (doDSPDis)
1615                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1616 #endif
1617 }
1618
1619 static void dsp_opcode_bset(void)
1620 {
1621 #ifdef DSP_DIS_BSET
1622         if (doDSPDis)
1623                 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);
1624 #endif
1625         UINT32 res = RN | (1 << IMM_1);
1626         RN = res;
1627         SET_ZN(res);
1628 #ifdef DSP_DIS_BSET
1629         if (doDSPDis)
1630                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1631 #endif
1632 }
1633
1634 static void dsp_opcode_subqt(void)
1635 {
1636 #ifdef DSP_DIS_SUBQT
1637         if (doDSPDis)
1638                 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);
1639 #endif
1640         RN -= dsp_convert_zero[IMM_1];
1641 #ifdef DSP_DIS_SUBQT
1642         if (doDSPDis)
1643                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1644 #endif
1645 }
1646
1647 static void dsp_opcode_addqt(void)
1648 {
1649 #ifdef DSP_DIS_ADDQT
1650         if (doDSPDis)
1651                 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);
1652 #endif
1653         RN += dsp_convert_zero[IMM_1];
1654 #ifdef DSP_DIS_ADDQT
1655         if (doDSPDis)
1656                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1657 #endif
1658 }
1659
1660 static void dsp_opcode_imacn(void)
1661 {
1662 #ifdef DSP_DIS_IMACN
1663         if (doDSPDis)
1664                 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);
1665 #endif
1666         int32 res = (int16)RM * (int16)RN;
1667         dsp_acc += (int64)res;
1668 //Should we AND the result to fit into 40 bits here???
1669 #ifdef DSP_DIS_IMACN
1670         if (doDSPDis)
1671                 WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
1672 #endif
1673
1674
1675 static void dsp_opcode_mtoi(void)
1676 {
1677         RN = (((INT32)RM >> 8) & 0xFF800000) | (RM & 0x007FFFFF);
1678         SET_ZN(RN);
1679 }
1680
1681 static void dsp_opcode_normi(void)
1682 {
1683         uint32 _Rm = RM;
1684         uint32 res = 0;
1685
1686         if (_Rm)
1687         {
1688                 while ((_Rm & 0xffc00000) == 0)
1689                 {
1690                         _Rm <<= 1;
1691                         res--;
1692                 }
1693                 while ((_Rm & 0xff800000) != 0)
1694                 {
1695                         _Rm >>= 1;
1696                         res++;
1697                 }
1698         }
1699         RN = res;
1700         SET_ZN(RN);
1701 }
1702
1703 static void dsp_opcode_mmult(void)
1704 {
1705         int count       = dsp_matrix_control&0x0f;
1706         uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
1707         int64 accum = 0;
1708         uint32 res;
1709
1710         if (!(dsp_matrix_control & 0x10))
1711         {
1712                 for (int i = 0; i < count; i++)
1713                 { 
1714                         int16 a;
1715                         if (i&0x01)
1716                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1717                         else
1718                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1719                         int16 b=((int16)DSPReadWord(addr + 2, DSP));
1720                         accum += a*b;
1721                         addr += 4;
1722                 }
1723         }
1724         else
1725         {
1726                 for (int i = 0; i < count; i++)
1727                 {
1728                         int16 a;
1729                         if (i&0x01)
1730                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1731                         else
1732                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1733                         int16 b=((int16)DSPReadWord(addr + 2, DSP));
1734                         accum += a*b;
1735                         addr += 4 * count;
1736                 }
1737         }
1738         RN = res = (int32)accum;
1739         // carry flag to do
1740 //NOTE: The flags are set based upon the last add/multiply done...
1741         SET_ZN(RN);
1742 }
1743
1744 static void dsp_opcode_abs(void)
1745 {
1746         uint32 _Rn = RN;
1747         uint32 res;
1748         
1749         if (_Rn == 0x80000000)
1750                 dsp_flag_n = 1;
1751         else
1752         {
1753                 dsp_flag_c = ((_Rn & 0x80000000) >> 31);
1754                 res = RN = (_Rn & 0x80000000 ? -_Rn : _Rn);
1755                 CLR_ZN; SET_Z(res);
1756         }
1757 }
1758
1759 static void dsp_opcode_div(void)
1760 {
1761         uint32 _Rm=RM;
1762         uint32 _Rn=RN;
1763
1764         if (_Rm)
1765         {
1766                 if (dsp_div_control & 1)
1767                 {
1768                         dsp_remain = (((uint64)_Rn) << 16) % _Rm;
1769                         if (dsp_remain&0x80000000)
1770                                 dsp_remain-=_Rm;
1771                         RN = (((uint64)_Rn) << 16) / _Rm;
1772                 }
1773                 else
1774                 {
1775                         dsp_remain = _Rn % _Rm;
1776                         if (dsp_remain&0x80000000)
1777                                 dsp_remain-=_Rm;
1778                         RN/=_Rm;
1779                 }
1780         }
1781         else
1782                 RN=0xffffffff;
1783 }
1784
1785 static void dsp_opcode_imultn(void)
1786 {
1787 #ifdef DSP_DIS_IMULTN
1788         if (doDSPDis)
1789                 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);
1790 #endif
1791         // This is OK, since this multiply won't overflow 32 bits...
1792         int32 res = (int32)((int16)RN * (int16)RM);
1793         dsp_acc = (int64)res;
1794         SET_ZN(res);
1795 #ifdef DSP_DIS_IMULTN
1796         if (doDSPDis)
1797                 WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
1798 #endif
1799 }
1800
1801 static void dsp_opcode_neg(void)
1802 {
1803 #ifdef DSP_DIS_NEG
1804         if (doDSPDis)
1805                 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);
1806 #endif
1807         UINT32 res = -RN;
1808         SET_ZNC_SUB(0, RN, res);
1809         RN = res;
1810 #ifdef DSP_DIS_NEG
1811         if (doDSPDis)
1812                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1813 #endif
1814 }
1815
1816 static void dsp_opcode_shlq(void)
1817 {
1818 #ifdef DSP_DIS_SHLQ
1819         if (doDSPDis)
1820                 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);
1821 #endif
1822         INT32 r1 = 32 - IMM_1;
1823         UINT32 res = RN << r1;
1824         SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
1825         RN = res;
1826 #ifdef DSP_DIS_SHLQ
1827         if (doDSPDis)
1828                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1829 #endif
1830 }
1831
1832 static void dsp_opcode_shrq(void)
1833 {
1834 #ifdef DSP_DIS_SHRQ
1835         if (doDSPDis)
1836                 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);
1837 #endif
1838         INT32 r1 = dsp_convert_zero[IMM_1];
1839         UINT32 res = RN >> r1;
1840         SET_ZN(res); dsp_flag_c = RN & 1;
1841         RN = res;
1842 #ifdef DSP_DIS_SHRQ
1843         if (doDSPDis)
1844                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1845 #endif
1846 }
1847
1848 static void dsp_opcode_ror(void)
1849 {
1850 #ifdef DSP_DIS_ROR
1851         if (doDSPDis)
1852                 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);
1853 #endif
1854         UINT32 r1 = RM & 0x1F;
1855         UINT32 res = (RN >> r1) | (RN << (32 - r1));
1856         SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
1857         RN = res;
1858 #ifdef DSP_DIS_ROR
1859         if (doDSPDis)
1860                 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);
1861 #endif
1862 }
1863
1864 static void dsp_opcode_rorq(void)
1865 {
1866 #ifdef DSP_DIS_RORQ
1867         if (doDSPDis)
1868                 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);
1869 #endif
1870         UINT32 r1 = dsp_convert_zero[IMM_1 & 0x1F];
1871         UINT32 r2 = RN;
1872         UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
1873         RN = res;
1874         SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
1875 #ifdef DSP_DIS_RORQ
1876         if (doDSPDis)
1877                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1878 #endif
1879 }
1880
1881 static void dsp_opcode_sha(void)
1882 {
1883         int32 sRm=(int32)RM;
1884         uint32 _Rn=RN;
1885
1886         if (sRm<0)
1887         {
1888                 uint32 shift=-sRm;
1889                 if (shift>=32) shift=32;
1890                 dsp_flag_c=(_Rn&0x80000000)>>31;
1891                 while (shift)
1892                 {
1893                         _Rn<<=1;
1894                         shift--;
1895                 }
1896         }
1897         else
1898         {
1899                 uint32 shift=sRm;
1900                 if (shift>=32) shift=32;
1901                 dsp_flag_c=_Rn&0x1;
1902                 while (shift)
1903                 {
1904                         _Rn=((int32)_Rn)>>1;
1905                         shift--;
1906                 }
1907         }
1908         RN = _Rn;
1909         SET_ZN(RN);
1910 }
1911
1912 static void dsp_opcode_sharq(void)
1913 {
1914 #ifdef DSP_DIS_SHARQ
1915         if (doDSPDis)
1916                 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);
1917 #endif
1918         UINT32 res = (INT32)RN >> dsp_convert_zero[IMM_1];
1919         SET_ZN(res); dsp_flag_c = RN & 0x01;
1920         RN = res;
1921 #ifdef DSP_DIS_SHARQ
1922         if (doDSPDis)
1923                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1924 #endif
1925 }
1926
1927 static void dsp_opcode_sh(void)
1928 {
1929         int32 sRm=(int32)RM;
1930         uint32 _Rn=RN;
1931
1932         if (sRm<0)
1933         {
1934                 uint32 shift=(-sRm);
1935                 if (shift>=32) shift=32;
1936                 dsp_flag_c=(_Rn&0x80000000)>>31;
1937                 while (shift)
1938                 {
1939                         _Rn<<=1;
1940                         shift--;
1941                 }
1942         }
1943         else
1944         {
1945                 uint32 shift=sRm;
1946                 if (shift>=32) shift=32;
1947                 dsp_flag_c=_Rn&0x1;
1948                 while (shift)
1949                 {
1950                         _Rn>>=1;
1951                         shift--;
1952                 }
1953         }
1954         RN = _Rn;
1955         SET_ZN(RN);
1956 }
1957
1958 void dsp_opcode_addqmod(void)
1959 {
1960 #ifdef DSP_DIS_ADDQMOD
1961         if (doDSPDis)
1962                 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);
1963 #endif
1964         UINT32 r1 = dsp_convert_zero[IMM_1];
1965         UINT32 r2 = RN;
1966         UINT32 res = r2 + r1;
1967         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
1968         RN = res;
1969         SET_ZNC_ADD(r2, r1, res);
1970 #ifdef DSP_DIS_ADDQMOD
1971         if (doDSPDis)
1972                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1973 #endif
1974 }
1975
1976 void dsp_opcode_subqmod(void)   
1977 {
1978         UINT32 r1 = dsp_convert_zero[IMM_1];
1979         UINT32 r2 = RN;
1980         UINT32 res = r2 - r1;
1981         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
1982         RN = res;
1983         
1984         SET_ZNC_SUB(r2, r1, res);
1985 }
1986
1987 void dsp_opcode_mirror(void)    
1988 {
1989         UINT32 r1 = RN;
1990         RN = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
1991         SET_ZN(RN);
1992 }
1993
1994 void dsp_opcode_sat32s(void)            
1995 {
1996         INT32 r2 = (UINT32)RN;
1997         INT32 temp = dsp_acc >> 32;
1998         UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
1999         RN = res;
2000         SET_ZN(res);
2001 }
2002
2003 void dsp_opcode_sat16s(void)            
2004 {
2005         INT32 r2 = RN;
2006         UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
2007         RN = res;
2008         SET_ZN(res);
2009 }