]> Shamusworld >> Repos - virtualjaguar/blob - src/dsp.cpp
More changes for upcoming 1.0.5 release
[virtualjaguar] / src / 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         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
407                 WriteLog("DSP: ReadByte--Attempt to read from DSP register file by %s!\n", whoName[who]);
408 // battlemorph
409 //      if ((offset==0xF1CFE0)||(offset==0xF1CFE2))
410 //              return(0xffff);
411         // mutant penguin
412 /*      if ((jaguar_mainRom_crc32==0xbfd751a4)||(jaguar_mainRom_crc32==0x053efaf9))
413         {
414                 if (offset==0xF1CFE0)
415                         return(0xff);
416         }*/
417         if (offset >= DSP_WORK_RAM_BASE && offset <= (DSP_WORK_RAM_BASE + 0x1FFF))
418                 return dsp_ram_8[offset - DSP_WORK_RAM_BASE];
419
420         if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
421         {
422                 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
423
424                 if ((offset&0x03)==0)
425                         return(data>>24);
426                 else
427                 if ((offset&0x03)==1)
428                         return((data>>16)&0xff);
429                 else
430                 if ((offset&0x03)==2)
431                         return((data>>8)&0xff);
432                 else
433                 if ((offset&0x03)==3)
434                         return(data&0xff);
435         }
436
437         return JaguarReadByte(offset, who);
438
439
440 uint16 DSPReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
441 {
442         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
443                 WriteLog("DSP: ReadWord--Attempt to read from DSP register file by %s!\n", whoName[who]);
444         //???
445         offset &= 0xFFFFFFFE;
446         // jaguar cd bios
447 /*      if (jaguar_mainRom_crc32==0xa74a97cd)
448         {
449                 if (offset==0xF1A114) return(0x0000);
450                 if (offset==0xF1A116) return(0x0000);
451                 if (offset==0xF1B000) return(0x1234);
452                 if (offset==0xF1B002) return(0x5678);
453         }*/
454 /*
455         if (jaguar_mainRom_crc32==0x7ae20823)
456         {
457                 if (offset==0xF1B9D8) return(0x0000);
458                 if (offset==0xF1B9Da) return(0x0000);
459                 if (offset==0xF1B2C0) return(0x0000);
460                 if (offset==0xF1B2C2) return(0x0000);
461         }
462 */
463         // pour permettre Ã  wolfenstein 3d de tourner sans le dsp
464 /*      if ((offset==0xF1B0D0)||(offset==0xF1B0D2))
465                 return(0);
466 */
467
468                 // pour permettre Ã  nba jam de tourner sans le dsp
469 /*      if (jaguar_mainRom_crc32==0x4faddb18)
470         {
471                 if (offset==0xf1b2c0) return(0);
472                 if (offset==0xf1b2c2) return(0);
473                 if (offset==0xf1b240) return(0);
474                 if (offset==0xf1b242) return(0);
475                 if (offset==0xF1B340) return(0);
476                 if (offset==0xF1B342) return(0);
477                 if (offset==0xF1BAD8) return(0);
478                 if (offset==0xF1BADA) return(0);
479                 if (offset==0xF1B040) return(0);
480                 if (offset==0xF1B042) return(0);
481                 if (offset==0xF1B0C0) return(0);
482                 if (offset==0xF1B0C2) return(0);
483                 if (offset==0xF1B140) return(0);
484                 if (offset==0xF1B142) return(0);
485                 if (offset==0xF1B1C0) return(0);
486                 if (offset==0xF1B1C2) return(0);
487         }*/
488
489         if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE+0x1FFF)
490         {
491                 offset -= DSP_WORK_RAM_BASE;
492 /*              uint16 data = (((uint16)dsp_ram_8[offset])<<8)|((uint16)dsp_ram_8[offset+1]);
493                 return data;*/
494                 return GET16(dsp_ram_8, offset);
495         }
496         else if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
497         {
498                 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
499
500                 if (offset & 0x03)
501                         return data & 0xFFFF;
502                 else
503                         return data >> 16;
504         }
505
506         return JaguarReadWord(offset, who);
507 }
508
509 uint32 DSPReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
510 {
511         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
512                 WriteLog("DSP: ReadLong--Attempt to read from DSP register file by %s!\n", whoName[who]);
513
514         // ??? WHY ???
515         offset &= 0xFFFFFFFC;
516 /*if (offset == 0xF1BCF4)
517 {
518         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));
519         DSPDumpDisassembly();
520 }*/
521         if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
522         {
523                 offset -= DSP_WORK_RAM_BASE;
524                 return GET32(dsp_ram_8, offset);
525         }
526 //NOTE: Didn't return DSP_ACCUM!!!
527 //Mebbe it's not 'spose to! Yes, it is!
528         if (offset >= DSP_CONTROL_RAM_BASE && offset <= DSP_CONTROL_RAM_BASE + 0x23)
529         {
530                 offset &= 0x3F;
531                 switch (offset)
532                 {
533                 case 0x00:      /*dsp_flag_c?(dsp_flag_c=1):(dsp_flag_c=0);
534                                         dsp_flag_z?(dsp_flag_z=1):(dsp_flag_z=0);
535                                         dsp_flag_n?(dsp_flag_n=1):(dsp_flag_n=0);*/
536
537                                         dsp_flags = (dsp_flags & 0xFFFFFFF8) | (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
538                                         return dsp_flags & 0xFFFFC1FF;
539                 case 0x04: return dsp_matrix_control;
540                 case 0x08: return dsp_pointer_to_matrix;
541                 case 0x0C: return dsp_data_organization;
542                 case 0x10: return dsp_pc;
543                 case 0x14: return dsp_control;
544                 case 0x18: return dsp_modulo;
545                 case 0x1C: return dsp_remain;
546                 case 0x20:
547                         return (int32)((int8)(dsp_acc >> 32));  // Top 8 bits of 40-bit accumulator, sign extended
548                 }
549                 // unaligned long read-- !!! FIX !!!
550                 return 0xFFFFFFFF;
551         }
552
553         return JaguarReadLong(offset, who);
554 }
555
556 void DSPWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
557 {
558         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
559                 WriteLog("DSP: WriteByte--Attempt to write to DSP register file by %s!\n", whoName[who]);
560
561         if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
562         {
563                 offset -= DSP_WORK_RAM_BASE;
564                 dsp_ram_8[offset] = data;
565 //This is rather stupid! !!! FIX !!!
566 /*              if (dsp_in_exec == 0)
567                 {
568                         m68k_end_timeslice();
569                         gpu_releaseTimeslice();
570                 }*/
571                 return;
572         }
573         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
574         {
575                 uint32 reg = offset & 0x1C;
576                 int bytenum = offset & 0x03;
577                 
578                 if ((reg >= 0x1C) && (reg <= 0x1F))
579                         dsp_div_control = (dsp_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
580                 else
581                 {
582 //This looks funky. !!! FIX !!!
583                         uint32 old_data = DSPReadLong(offset&0xFFFFFFC, who);
584                         bytenum = 3 - bytenum; // convention motorola !!!
585                         old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3)); 
586                         DSPWriteLong(offset & 0xFFFFFFC, old_data, who);
587                 }
588                 return;
589         }
590 //      WriteLog("dsp: writing %.2x at 0x%.8x\n",data,offset);
591 //Should this *ever* happen??? Shouldn't we be saying "unknown" here???
592         JaguarWriteByte(offset, data, who);
593 }
594
595 void DSPWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
596 {
597         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
598                 WriteLog("DSP: WriteWord--Attempt to write to DSP register file by %s!\n", whoName[who]);
599         offset &= 0xFFFFFFFE;
600 /*if (offset == 0xF1BCF4)
601 {
602         WriteLog("DSPWriteWord: Writing to 0xF1BCF4... %04X -> %04X\n", GET16(dsp_ram_8, 0x0CF4), data);
603 }*/
604 //      WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset);
605         if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
606         {
607                 offset -= DSP_WORK_RAM_BASE;
608                 dsp_ram_8[offset] = data >> 8;
609                 dsp_ram_8[offset+1] = data & 0xFF;
610 //This is rather stupid! !!! FIX !!!
611 /*              if (dsp_in_exec == 0)
612                 {
613 //                      WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset+DSP_WORK_RAM_BASE);
614                         m68k_end_timeslice();
615                         gpu_releaseTimeslice();
616                 }*/
617                 return;
618         }
619         else if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
620         {
621                 if ((offset & 0x1C) == 0x1C)
622                 {
623                         if (offset & 0x03)
624                                 dsp_div_control = (dsp_div_control&0xffff0000)|(data&0xffff);
625                         else
626                                 dsp_div_control = (dsp_div_control&0xffff)|((data&0xffff)<<16);
627                 }
628                 else
629                 {
630                         uint32 old_data = DSPReadLong(offset & 0xffffffc, who);
631                         if (offset & 0x03)
632                                 old_data = (old_data&0xffff0000)|(data&0xffff);
633                         else
634                                 old_data = (old_data&0xffff)|((data&0xffff)<<16);
635                         DSPWriteLong(offset & 0xffffffc, old_data, who);
636                 }
637                 return;
638         }
639
640         JaguarWriteWord(offset, data, who);
641 }
642
643 //bool badWrite = false;
644 void DSPWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
645 {
646         if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
647                 WriteLog("DSP: WriteLong--Attempt to write to DSP register file by %s!\n", whoName[who]);
648         // ??? WHY ???
649         offset &= 0xFFFFFFFC;
650 /*if (offset == 0xF1BCF4)
651 {
652         WriteLog("DSPWriteLong: Writing to 0xF1BCF4... %08X -> %08X\n", GET32(dsp_ram_8, 0x0CF4), data);
653 }*/
654 //      WriteLog("dsp: writing %.8x at 0x%.8x\n",data,offset);
655         if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
656         {
657 /*if (offset == 0xF1BE2C)
658 {
659         WriteLog("DSP: %s is writing %08X at location 0xF1BE2C (DSP_PC: %08X)...\n", whoName[who], data, dsp_pc - 2);
660 }//*/
661                 offset -= DSP_WORK_RAM_BASE;
662                 SET32(dsp_ram_8, offset, data);
663                 return;
664         }
665         else if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
666         {
667                 offset &= 0x1F;
668                 switch (offset)
669                 {
670                 case 0x00:
671                 {
672                         bool IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
673                         dsp_flags = data;
674                         dsp_flag_z = dsp_flags & 0x01;
675                         dsp_flag_c = (dsp_flags >> 1) & 0x01;
676                         dsp_flag_n = (dsp_flags >> 2) & 0x01;
677                         DSPUpdateRegisterBanks();
678                         dsp_control &= ~((dsp_flags & CINT04FLAGS) >> 3);
679                         dsp_control &= ~((dsp_flags & CINT5FLAG) >> 1);
680                         if (IMASKCleared)                                               // If IMASK was cleared,
681 #ifdef DSP_DEBUG_IRQ
682                         {
683                                 WriteLog("DSP: Finished interrupt.\n");
684 #endif
685                                 DSPHandleIRQs();                                        // see if any other interrupts need servicing!
686 #ifdef DSP_DEBUG_IRQ
687                         }
688 #endif
689                         break;
690                 }
691                 case 0x04:
692                         dsp_matrix_control = data;
693                         break;
694                 case 0x08:
695                         // According to JTRM, only lines 2-11 are adressable, the rest being
696                         // hardwired to $F1Bxxx.
697                         dsp_pointer_to_matrix = 0xF1B000 | (data & 0x000FFC);
698                         break;
699                 case 0x0C:
700                         dsp_data_organization = data;
701                         break;
702                 case 0x10:
703                         dsp_pc = data;
704 #ifdef DSP_DEBUG
705                         WriteLog("DSP: Setting DSP PC to %08X by %s%s\n", dsp_pc, whoName[who], (DSP_RUNNING ? " (DSP is RUNNING!)" : ""));//*/
706 #endif
707                         break;
708                 case 0x14:
709                 {       
710 //                      uint32 dsp_was_running = DSP_RUNNING;
711                         // Check for DSP -> CPU interrupt
712                         if (data & CPUINT)
713                         {
714 //                              WriteLog("DSP: DSP -> CPU interrupt\n");
715 // This was WRONG
716 // Why do we check for a valid handler at 64? Isn't that the Jag programmer's responsibility?
717                                 if (JERRYIRQEnabled(IRQ2_DSP) && jaguar_interrupt_handler_is_valid(64))
718                                 {
719                                         JERRYSetPendingIRQ(IRQ2_DSP);
720                                         dsp_releaseTimeslice();
721                                         m68k_set_irq(7);                        // Set 68000 NMI...
722                                 }
723                                 data &= ~CPUINT;
724                         }
725                         // Check for CPU -> DSP interrupt
726                         if (data & DSPINT0)
727                         {
728                                 WriteLog("DSP: CPU -> DSP interrupt\n");
729                                 m68k_end_timeslice();
730                                 gpu_releaseTimeslice();
731                                 DSPSetIRQLine(DSPIRQ_CPU, ASSERT_LINE);
732                                 data &= ~DSPINT0;
733                         }
734                         // single stepping
735                         if (data & SINGLE_STEP)
736                         {
737 //                              WriteLog("DSP: Asked to perform a single step (single step is %senabled)\n", (data & 0x8 ? "" : "not "));
738                         }
739
740                         // Protect writes to VERSION and the interrupt latches...
741                         uint32 mask = VERSION | INT_LAT0 | INT_LAT1 | INT_LAT2 | INT_LAT3 | INT_LAT4 | INT_LAT5;
742                         dsp_control = (dsp_control & mask) | (data & ~mask);
743
744                         // if dsp wasn't running but is now running
745                         // execute a few cycles
746 //This is just plain wrong, wrong, WRONG!
747 #ifndef DSP_SINGLE_STEPPING
748 /*                      if (!dsp_was_running && DSP_RUNNING)
749                         {
750                                 DSPExec(200);
751                         }*/
752 #else
753 //This is WRONG! !!! FIX !!!
754                         if (dsp_control & 0x18)
755                                 DSPExec(1);
756 #endif
757 #ifdef DSP_DEBUG
758 WriteLog("Write to DSP CTRL: %08X ", data);
759 if (DSP_RUNNING)
760         WriteLog(" --> Starting to run at %08X by %s...", dsp_pc, whoName[who]);
761 else
762         WriteLog(" --> Stopped by %s! (DSP PC: %08X)", whoName[who], dsp_pc);
763 WriteLog("\n");
764 #endif  // DSP_DEBUG
765 //This isn't exactly right either--we don't know if it was the M68K or the GPU writing here...
766 // !!! FIX !!!
767                         if (DSP_RUNNING)
768                                 m68k_end_timeslice();
769                         break;
770                 }
771                 case 0x18:
772                         dsp_modulo = data;
773                         break;
774                 case 0x1C:
775                         dsp_div_control = data;
776                         break;
777 //              default:   // unaligned long read
778                                    //__asm int 3
779                 }
780                 return;
781         }
782
783 //We don't have to break this up like this! We CAN do 32 bit writes!
784 //      JaguarWriteWord(offset, (data>>16) & 0xFFFF, DSP);
785 //      JaguarWriteWord(offset+2, data & 0xFFFF, DSP);
786 //if (offset > 0xF1FFFF)
787 //      badWrite = true;
788         JaguarWriteLong(offset, data, who);
789 }
790
791 //
792 // Update the DSP register file pointers depending on REGPAGE bit
793 //
794 void DSPUpdateRegisterBanks(void)
795 {
796         int bank = (dsp_flags & REGPAGE);
797
798         if (dsp_flags & IMASK)
799                 bank = 0;                                                       // IMASK forces main bank to be bank 0
800
801         if (bank)
802                 dsp_reg = dsp_reg_bank_1, dsp_alternate_reg = dsp_reg_bank_0;
803         else
804                 dsp_reg = dsp_reg_bank_0, dsp_alternate_reg = dsp_reg_bank_1;
805 }
806
807 //
808 // Check for an handle any asserted DSP IRQs
809 //
810 void DSPHandleIRQs(void)
811 {
812         if (dsp_flags & IMASK)                                                  // Bail if we're already inside an interrupt
813                 return;
814
815         // Get the active interrupt bits (latches) & interrupt mask (enables)
816         uint32 bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
817                 mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
818
819 //      WriteLog("dsp: bits=%.2x mask=%.2x\n",bits,mask);
820         bits &= mask;
821
822         if (!bits)                                                                              // Bail if nothing is enabled
823                 return;
824
825         int which = 0;                                                                  // Determine which interrupt 
826         if (bits & 0x01)
827                 which = 0;
828         if (bits & 0x02)
829                 which = 1;
830         if (bits & 0x04)
831                 which = 2;
832         if (bits & 0x08)
833                 which = 3;
834         if (bits & 0x10)
835                 which = 4;
836         if (bits & 0x20)
837                 which = 5;
838
839 #ifdef DSP_DEBUG_IRQ
840         WriteLog("DSP: Generating interrupt #%i...\n", which);
841 #endif
842
843         dsp_flags |= IMASK;
844         DSPUpdateRegisterBanks();
845
846         // subqt  #4,r31                ; pre-decrement stack pointer 
847         // move  pc,r30                 ; address of interrupted code 
848         // store  r30,(r31)     ; store return address
849         dsp_reg[31] -= 4;
850         DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
851
852         // movei  #service_address,r30  ; pointer to ISR entry 
853         // jump  (r30)                                  ; jump to ISR 
854         // nop
855         dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
856 }
857
858 //
859 // Set the specified DSP IRQ line to a given state
860 //
861 void DSPSetIRQLine(int irqline, int state)
862 {
863 //NOTE: This doesn't take INT_LAT5 into account. !!! FIX !!!
864         uint32 mask = INT_LAT0 << irqline;
865         dsp_control &= ~mask;                                                   // Clear the latch bit
866
867         if (state)
868         {
869                 dsp_control |= mask;                                            // Set the latch bit
870                 DSPHandleIRQs();
871         }
872 }
873
874 void DSPInit(void)
875 {
876         memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
877         memory_malloc_secure((void **)&dsp_reg_bank_0, 32 * sizeof(int32), "DSP bank 0 regs");
878         memory_malloc_secure((void **)&dsp_reg_bank_1, 32 * sizeof(int32), "DSP bank 1 regs");
879
880         dsp_build_branch_condition_table();
881         DSPReset();
882 }
883
884 void DSPReset(void)
885 {
886         dsp_pc                            = 0x00F1B000;
887         dsp_acc                           = 0x00000000;
888         dsp_remain                        = 0x00000000;
889         dsp_modulo                        = 0xFFFFFFFF;
890         dsp_flags                         = 0x00040000;
891         dsp_matrix_control    = 0x00000000;
892         dsp_pointer_to_matrix = 0x00000000;
893         dsp_data_organization = 0xFFFFFFFF;
894         dsp_control                       = 0x00002000;                         // Report DSP version 2
895         dsp_div_control           = 0x00000000;
896         dsp_in_exec                       = 0;
897
898         dsp_reg = dsp_reg_bank_0;
899         dsp_alternate_reg = dsp_reg_bank_1;
900
901         for(int i=0; i<32; i++)
902                 dsp_reg[i] = dsp_alternate_reg[i] = 0x00000000;
903
904         CLR_ZNC;
905
906         dsp_reset_stats();
907         memset(dsp_ram_8, 0xFF, 0x2000);
908 }
909
910 void DSPDumpDisassembly(void)
911 {
912         char buffer[512];
913
914         WriteLog("\n---[DSP code at 00F1B000]---------------------------\n");
915         uint32 j = 0xF1B000;
916         while (j <= 0xF1CFFF)
917         {
918                 uint32 oldj = j;
919                 j += dasmjag(JAGUAR_DSP, buffer, j);
920                 WriteLog("\t%08X: %s\n", oldj, buffer);
921         }
922 }
923
924 void DSPDumpRegisters(void)
925 {
926 //Shoud add modulus, etc to dump here...
927         WriteLog("\n---[DSP flags: NCZ %d%d%d, DSP PC: %08X]------------\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_pc);
928         WriteLog("\nRegisters bank 0\n");
929         for(int j=0; j<8; j++)
930         {
931                 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
932                                                   (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
933                                                   (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
934                                                   (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
935                                                   (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
936         }
937         WriteLog("Registers bank 1\n");
938         for(int j=0; j<8; j++)
939         {
940                 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
941                                                   (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
942                                                   (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
943                                                   (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
944                                                   (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
945         }
946 }
947
948 void DSPDone(void)
949 {
950         int i, j;
951         WriteLog("DSP: Stopped at PC=%08X dsp_modulo=%08X (dsp %s running)\n", dsp_pc, dsp_modulo, (DSP_RUNNING ? "was" : "wasn't"));
952         WriteLog("DSP: %sin interrupt handler\n", (dsp_flags & IMASK ? "" : "not "));
953
954         // get the active interrupt bits 
955         int bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F);
956         // get the interrupt mask 
957         int mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
958
959         WriteLog("DSP: pending=%08X enabled=%08X\n", bits, mask);
960         WriteLog("\nRegisters bank 0\n");
961         for(int j=0; j<8; j++)
962         {
963                 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
964                                                   (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
965                                                   (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
966                                                   (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
967                                                   (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
968         }
969         WriteLog("\nRegisters bank 1\n");
970         for (j=0; j<8; j++)
971         {
972                 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
973                                                   (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
974                                                   (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
975                                                   (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
976                                                   (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
977
978         }
979
980         static char buffer[512];
981         j = DSP_WORK_RAM_BASE;
982         while (j <= 0xF1BFFF)
983         {
984                 uint32 oldj = j;
985                 j += dasmjag(JAGUAR_DSP, buffer, j);
986                 WriteLog("\t%08X: %s\n", oldj, buffer);
987         }//*/
988
989         WriteLog("DSP opcodes use:\n");
990         for (i=0;i<64;i++)
991         {
992                 if (dsp_opcode_use[i])
993                         WriteLog("\t%s %i\n", dsp_opcode_str[i], dsp_opcode_use[i]);
994         }//*/
995
996         memory_free(dsp_ram_8);
997 }
998
999 //
1000 // DSP execution core
1001 //
1002 static bool R20Set = false, tripwire = false;
1003 static uint32 pcQueue[32], ptrPCQ = 0;
1004 void DSPExec(int32 cycles)
1005 {
1006 /*HACKS!!! ->   if (cycles != 1 && jaguar_mainRom_crc32 == 0xba74c3ed)
1007                 dsp_check_if_i2s_interrupt_needed();*/
1008
1009 #ifdef DSP_SINGLE_STEPPING
1010         if (dsp_control & 0x18)
1011         {
1012                 cycles = 1;
1013                 dsp_control &= ~0x10;
1014         }
1015 #endif
1016 //There is *no* good reason to do this here!
1017 //      DSPHandleIRQs();
1018         dsp_releaseTimeSlice_flag = 0;
1019         dsp_in_exec++;
1020
1021         while (cycles > 0 && DSP_RUNNING)
1022         {
1023 /*if (badWrite)
1024 {
1025         WriteLog("\nDSP: Encountered bad write in Atari Synth module. PC=%08X, R15=%08X\n", dsp_pc, dsp_reg[15]);
1026         for(int i=0; i<80; i+=4)
1027                 WriteLog("     %08X: %08X\n", dsp_reg[15]+i, JaguarReadLong(dsp_reg[15]+i));
1028         WriteLog("\n");
1029 }//*/
1030 /*if (dsp_pc == 0xF1B55E)
1031 {
1032         WriteLog("DSP: At $F1B55E--R15 = %08X at %u ms%s...\n", dsp_reg[15], SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1033 }//*/
1034 /*if (dsp_pc == 0xF1B7D2)       // Start here???
1035         doDSPDis = true;
1036 pcQueue[ptrPCQ++] = dsp_pc;
1037 ptrPCQ %= 32;*/
1038                 uint16 opcode = DSPReadWord(dsp_pc, DSP);
1039                 uint32 index = opcode >> 10;
1040                 dsp_opcode_first_parameter = (opcode >> 5) & 0x1F;
1041                 dsp_opcode_second_parameter = opcode & 0x1F;
1042                 dsp_pc += 2;
1043                 dsp_opcode[index]();
1044                 dsp_opcode_use[index]++;
1045                 cycles -= dsp_opcode_cycles[index];
1046 /*if (dsp_reg_bank_0[20] == 0xF1A100 & !R20Set)
1047 {
1048         WriteLog("DSP: R20 set to $F1A100 at %u ms%s...\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1049         R20Set = true;
1050 }
1051 if (dsp_reg_bank_0[20] != 0xF1A100 && R20Set)
1052 {
1053         WriteLog("DSP: R20 corrupted at %u ms from starting%s!\nAborting!\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1054         DSPDumpRegisters();
1055         DSPDumpDisassembly();
1056         exit(1);
1057 }
1058 if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFE) && !tripwire)
1059 {
1060         char buffer[512];
1061         WriteLog("DSP: Jumping outside of DSP RAM at %u ms. Register dump:\n", SDL_GetTicks());
1062         DSPDumpRegisters();
1063         tripwire = true;
1064         WriteLog("\nBacktrace:\n");
1065         for(int i=0; i<32; i++)
1066         {
1067                 dasmjag(JAGUAR_DSP, buffer, pcQueue[(ptrPCQ + i) % 32]);
1068                 WriteLog("\t%08X: %s\n", pcQueue[(ptrPCQ + i) % 32], buffer);
1069         }
1070         WriteLog("\n");
1071 }*/
1072         }
1073
1074         dsp_in_exec--;
1075 }
1076
1077 //
1078 // DSP opcode handlers
1079 //
1080
1081 // There is a problem here with interrupt handlers the JUMP and JR instructions that
1082 // can cause trouble because an interrupt can occur *before* the instruction following the
1083 // jump can execute... !!! FIX !!!
1084 static void dsp_opcode_jump(void)
1085 {
1086 #ifdef DSP_DIS_JUMP
1087 char * condition[32] =
1088 {       "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1089         "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1090         "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1091         "???", "???", "???", "F" };
1092         if (doDSPDis)
1093                 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);
1094 #endif
1095         // normalize flags
1096 /*      dsp_flag_c=dsp_flag_c?1:0;
1097         dsp_flag_z=dsp_flag_z?1:0;
1098         dsp_flag_n=dsp_flag_n?1:0;*/
1099         // KLUDGE: Used by BRANCH_CONDITION
1100         uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1101
1102         if (BRANCH_CONDITION(IMM_2))
1103         {
1104 #ifdef DSP_DIS_JUMP
1105         if (doDSPDis)
1106                 WriteLog("Branched!\n");
1107 #endif
1108                 uint32 delayed_pc = RM;
1109                 DSPExec(1);
1110                 dsp_pc = delayed_pc;
1111         }
1112 #ifdef DSP_DIS_JUMP
1113         else
1114                 if (doDSPDis)
1115                         WriteLog("Branch NOT taken.\n");
1116 #endif
1117 }
1118
1119 static void dsp_opcode_jr(void)
1120 {
1121 #ifdef DSP_DIS_JR
1122 char * condition[32] =
1123 {       "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1124         "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1125         "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1126         "???", "???", "???", "F" };
1127         if (doDSPDis)
1128                 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);
1129 #endif
1130         // normalize flags
1131 /*      dsp_flag_c=dsp_flag_c?1:0;
1132         dsp_flag_z=dsp_flag_z?1:0;
1133         dsp_flag_n=dsp_flag_n?1:0;*/
1134         // KLUDGE: Used by BRANCH_CONDITION
1135         uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1136
1137         if (BRANCH_CONDITION(IMM_2))
1138         {
1139 #ifdef DSP_DIS_JR
1140         if (doDSPDis)
1141                 WriteLog("Branched!\n");
1142 #endif
1143                 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1);             // Sign extend IMM_1
1144                 int32 delayed_pc = dsp_pc + (offset * 2);
1145                 DSPExec(1);
1146                 dsp_pc = delayed_pc;
1147         }
1148 #ifdef DSP_DIS_JR
1149         else
1150                 if (doDSPDis)
1151                         WriteLog("Branch NOT taken.\n");
1152 #endif
1153 }
1154
1155 static void dsp_opcode_add(void)
1156 {
1157 #ifdef DSP_DIS_ADD
1158         if (doDSPDis)
1159                 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);
1160 #endif
1161         UINT32 res = RN + RM;
1162         SET_ZNC_ADD(RN, RM, res);
1163         RN = res;
1164 #ifdef DSP_DIS_ADD
1165         if (doDSPDis)
1166                 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);
1167 #endif
1168 }
1169
1170 static void dsp_opcode_addc(void)
1171 {
1172 #ifdef DSP_DIS_ADDC
1173         if (doDSPDis)
1174                 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);
1175 #endif
1176         UINT32 res = RN + RM + dsp_flag_c;
1177         UINT32 carry = dsp_flag_c;
1178 //      SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1179         SET_ZNC_ADD(RN + carry, RM, res);
1180 //      SET_ZNC_ADD(RN, RM + carry, res);
1181         RN = res;
1182 #ifdef DSP_DIS_ADDC
1183         if (doDSPDis)
1184                 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);
1185 #endif
1186 }
1187
1188 static void dsp_opcode_addq(void)
1189 {
1190 #ifdef DSP_DIS_ADDQ
1191         if (doDSPDis)
1192                 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);
1193 #endif
1194         UINT32 r1 = dsp_convert_zero[IMM_1];
1195         UINT32 res = RN + r1;
1196         CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1197         RN = res;
1198 #ifdef DSP_DIS_ADDQ
1199         if (doDSPDis)
1200                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1201 #endif
1202 }
1203
1204 static void dsp_opcode_sub(void)
1205 {
1206 #ifdef DSP_DIS_SUB
1207         if (doDSPDis)
1208                 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);
1209 #endif
1210         UINT32 res = RN - RM;
1211         SET_ZNC_SUB(RN, RM, res);
1212         RN = res;
1213 #ifdef DSP_DIS_SUB
1214         if (doDSPDis)
1215                 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);
1216 #endif
1217 }
1218
1219 static void dsp_opcode_subc(void)
1220 {
1221 #ifdef DSP_DIS_SUBC
1222         if (doDSPDis)
1223                 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);
1224 #endif
1225         UINT32 res = RN - RM - dsp_flag_c;
1226         UINT32 borrow = dsp_flag_c;
1227         SET_ZNC_SUB(RN - borrow, RM, res);
1228         RN = res;
1229 #ifdef DSP_DIS_SUBC
1230         if (doDSPDis)
1231                 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);
1232 #endif
1233 }
1234
1235 static void dsp_opcode_subq(void)
1236 {
1237 #ifdef DSP_DIS_SUBQ
1238         if (doDSPDis)
1239                 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);
1240 #endif
1241         UINT32 r1 = dsp_convert_zero[IMM_1];
1242         UINT32 res = RN - r1;
1243         SET_ZNC_SUB(RN, r1, res);
1244         RN = res;
1245 #ifdef DSP_DIS_SUBQ
1246         if (doDSPDis)
1247                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1248 #endif
1249 }
1250
1251 static void dsp_opcode_cmp(void)
1252 {
1253 #ifdef DSP_DIS_CMP
1254         if (doDSPDis)
1255                 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);
1256 #endif
1257         UINT32 res = RN - RM;
1258         SET_ZNC_SUB(RN, RM, res);
1259 #ifdef DSP_DIS_CMP
1260         if (doDSPDis)
1261                 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1262 #endif
1263 }
1264
1265 static void dsp_opcode_cmpq(void)
1266 {
1267         static int32 sqtable[32] =
1268                 { 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 };
1269 #ifdef DSP_DIS_CMPQ
1270         if (doDSPDis)
1271                 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);
1272 #endif
1273         UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1274         UINT32 res = RN - r1;
1275         SET_ZNC_SUB(RN, r1, res);
1276 #ifdef DSP_DIS_CMPQ
1277         if (doDSPDis)
1278                 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1279 #endif
1280 }
1281
1282 static void dsp_opcode_and(void)
1283 {
1284 #ifdef DSP_DIS_AND
1285         if (doDSPDis)
1286                 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);
1287 #endif
1288         RN = RN & RM;
1289         SET_ZN(RN);
1290 #ifdef DSP_DIS_AND
1291         if (doDSPDis)
1292                 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);
1293 #endif
1294 }
1295
1296 static void dsp_opcode_or(void)
1297 {
1298 #ifdef DSP_DIS_OR
1299         if (doDSPDis)
1300                 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);
1301 #endif
1302         RN = RN | RM;
1303         SET_ZN(RN);
1304 #ifdef DSP_DIS_OR
1305         if (doDSPDis)
1306                 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);
1307 #endif
1308 }
1309
1310 static void dsp_opcode_xor(void)
1311 {
1312 #ifdef DSP_DIS_XOR
1313         if (doDSPDis)
1314                 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);
1315 #endif
1316         RN = RN ^ RM;
1317         SET_ZN(RN);
1318 #ifdef DSP_DIS_XOR
1319         if (doDSPDis)
1320                 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);
1321 #endif
1322 }
1323
1324 static void dsp_opcode_not(void)
1325 {
1326 #ifdef DSP_DIS_NOT
1327         if (doDSPDis)
1328                 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);
1329 #endif
1330         RN = ~RN;
1331         SET_ZN(RN);
1332 #ifdef DSP_DIS_NOT
1333         if (doDSPDis)
1334                 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);
1335 #endif
1336 }
1337
1338 static void dsp_opcode_move_pc(void)
1339 {
1340         RN = dsp_pc - 2;
1341 }
1342
1343 static void dsp_opcode_store_r14_indexed(void)
1344 {
1345 #ifdef DSP_DIS_STORE14I
1346         if (doDSPDis)
1347                 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));
1348 #endif
1349         DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1350 }
1351
1352 static void dsp_opcode_store_r15_indexed(void)
1353 {
1354 #ifdef DSP_DIS_STORE15I
1355         if (doDSPDis)
1356                 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));
1357 #endif
1358         DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1359 }
1360
1361 static void dsp_opcode_load_r14_ri(void)
1362 {
1363 #ifdef DSP_DIS_LOAD14R
1364         if (doDSPDis)
1365                 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);
1366 #endif
1367         RN = DSPReadLong(dsp_reg[14] + RM, DSP);
1368 #ifdef DSP_DIS_LOAD14R
1369         if (doDSPDis)
1370                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1371 #endif
1372 }
1373
1374 static void dsp_opcode_load_r15_ri(void)
1375 {
1376 #ifdef DSP_DIS_LOAD15R
1377         if (doDSPDis)
1378                 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);
1379 #endif
1380         RN = DSPReadLong(dsp_reg[15] + RM, DSP);
1381 #ifdef DSP_DIS_LOAD15R
1382         if (doDSPDis)
1383                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1384 #endif
1385 }
1386
1387 static void dsp_opcode_store_r14_ri(void)
1388 {
1389         DSPWriteLong(dsp_reg[14] + RM, RN, DSP);
1390 }
1391
1392 static void dsp_opcode_store_r15_ri(void)
1393 {
1394         DSPWriteLong(dsp_reg[15] + RM, RN, DSP);
1395 }
1396
1397 static void dsp_opcode_nop(void)
1398 {
1399 #ifdef DSP_DIS_NOP
1400         if (doDSPDis)
1401                 WriteLog("%06X: NOP    [NCZ:%u%u%u]\n", dsp_pc-2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
1402 #endif
1403 }
1404
1405 static void dsp_opcode_storeb(void)
1406 {
1407 #ifdef DSP_DIS_STOREB
1408         if (doDSPDis)
1409                 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);
1410 #endif
1411         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1412                 DSPWriteLong(RM, RN & 0xFF, DSP);
1413         else
1414                 JaguarWriteByte(RM, RN, DSP);
1415 }
1416
1417 static void dsp_opcode_storew(void)
1418 {
1419 #ifdef DSP_DIS_STOREW
1420         if (doDSPDis)
1421                 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);
1422 #endif
1423         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1424                 DSPWriteLong(RM, RN & 0xFFFF, DSP);
1425         else
1426                 JaguarWriteWord(RM, RN, DSP);
1427 }
1428
1429 static void dsp_opcode_store(void)
1430 {
1431 #ifdef DSP_DIS_STORE
1432         if (doDSPDis)
1433                 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);
1434 #endif
1435         DSPWriteLong(RM, RN, DSP);
1436 }
1437
1438 static void dsp_opcode_loadb(void)
1439 {
1440 #ifdef DSP_DIS_LOADB
1441         if (doDSPDis)
1442                 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);
1443 #endif
1444         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1445                 RN = DSPReadLong(RM, DSP) & 0xFF;
1446         else
1447                 RN = JaguarReadByte(RM, DSP);
1448 #ifdef DSP_DIS_LOADB
1449         if (doDSPDis)
1450                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1451 #endif
1452 }
1453
1454 static void dsp_opcode_loadw(void)
1455 {
1456 #ifdef DSP_DIS_LOADW
1457         if (doDSPDis)
1458                 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);
1459 #endif
1460         if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1461                 RN = DSPReadLong(RM, DSP) & 0xFFFF;
1462         else
1463                 RN = JaguarReadWord(RM, DSP);
1464 #ifdef DSP_DIS_LOADW
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(void)
1471 {
1472 #ifdef DSP_DIS_LOAD
1473         if (doDSPDis)
1474                 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);
1475 #endif
1476         RN = DSPReadLong(RM, DSP);
1477 #ifdef DSP_DIS_LOAD
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_load_r14_indexed(void)
1484 {
1485 #ifdef DSP_DIS_LOAD14I
1486         if (doDSPDis)
1487                 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);
1488 #endif
1489         RN = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), DSP);
1490 #ifdef DSP_DIS_LOAD14I
1491         if (doDSPDis)
1492                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1493 #endif
1494 }
1495
1496 static void dsp_opcode_load_r15_indexed(void)
1497 {
1498 #ifdef DSP_DIS_LOAD15I
1499         if (doDSPDis)
1500                 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);
1501 #endif
1502         RN = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), DSP);
1503 #ifdef DSP_DIS_LOAD15I
1504         if (doDSPDis)
1505                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1506 #endif
1507 }
1508
1509 static void dsp_opcode_movei(void)
1510 {
1511 #ifdef DSP_DIS_MOVEI
1512         if (doDSPDis)
1513                 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);
1514 #endif
1515         // This instruction is followed by 32-bit value in LSW / MSW format...
1516         RN = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
1517         dsp_pc += 4;
1518 #ifdef DSP_DIS_MOVEI
1519         if (doDSPDis)
1520                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1521 #endif
1522 }
1523
1524 static void dsp_opcode_moveta(void)
1525 {
1526 #ifdef DSP_DIS_MOVETA
1527         if (doDSPDis)
1528                 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);
1529 #endif
1530         ALTERNATE_RN = RM;
1531 #ifdef DSP_DIS_MOVETA
1532         if (doDSPDis)
1533                 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);
1534 #endif
1535 }
1536
1537 static void dsp_opcode_movefa(void)
1538 {
1539 #ifdef DSP_DIS_MOVEFA
1540         if (doDSPDis)
1541                 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);
1542 #endif
1543         RN = ALTERNATE_RM;
1544 #ifdef DSP_DIS_MOVEFA
1545         if (doDSPDis)
1546                 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);
1547 #endif
1548 }
1549
1550 static void dsp_opcode_move(void)
1551 {
1552 #ifdef DSP_DIS_MOVE
1553         if (doDSPDis)
1554                 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);
1555 #endif
1556         RN = RM;
1557 #ifdef DSP_DIS_MOVE
1558         if (doDSPDis)
1559                 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);
1560 #endif
1561 }
1562
1563 static void dsp_opcode_moveq(void)
1564 {
1565 #ifdef DSP_DIS_MOVEQ
1566         if (doDSPDis)
1567                 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);
1568 #endif
1569         RN = IMM_1;
1570 #ifdef DSP_DIS_MOVEQ
1571         if (doDSPDis)
1572                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1573 #endif
1574 }
1575
1576 static void dsp_opcode_resmac(void)
1577 {
1578 #ifdef DSP_DIS_RESMAC
1579         if (doDSPDis)
1580                 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));
1581 #endif
1582         RN = (uint32)dsp_acc;
1583 #ifdef DSP_DIS_RESMAC
1584         if (doDSPDis)
1585                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1586 #endif
1587 }
1588
1589 static void dsp_opcode_imult(void)
1590 {
1591 #ifdef DSP_DIS_IMULT
1592         if (doDSPDis)
1593                 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);
1594 #endif
1595         RN = (int16)RN * (int16)RM;
1596         SET_ZN(RN);
1597 #ifdef DSP_DIS_IMULT
1598         if (doDSPDis)
1599                 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);
1600 #endif
1601 }
1602
1603 static void dsp_opcode_mult(void)
1604 {
1605 #ifdef DSP_DIS_MULT
1606         if (doDSPDis)
1607                 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);
1608 #endif
1609         RN = (uint16)RM * (uint16)RN;
1610         SET_ZN(RN);
1611 #ifdef DSP_DIS_MULT
1612         if (doDSPDis)
1613                 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);
1614 #endif
1615 }
1616
1617 static void dsp_opcode_bclr(void)
1618 {
1619 #ifdef DSP_DIS_BCLR
1620         if (doDSPDis)
1621                 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);
1622 #endif
1623         UINT32 res = RN & ~(1 << IMM_1);
1624         RN = res;
1625         SET_ZN(res);
1626 #ifdef DSP_DIS_BCLR
1627         if (doDSPDis)
1628                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1629 #endif
1630 }
1631
1632 static void dsp_opcode_btst(void)
1633 {
1634 #ifdef DSP_DIS_BTST
1635         if (doDSPDis)
1636                 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);
1637 #endif
1638         dsp_flag_z = (~RN >> IMM_1) & 1;
1639 #ifdef DSP_DIS_BTST
1640         if (doDSPDis)
1641                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1642 #endif
1643 }
1644
1645 static void dsp_opcode_bset(void)
1646 {
1647 #ifdef DSP_DIS_BSET
1648         if (doDSPDis)
1649                 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);
1650 #endif
1651         UINT32 res = RN | (1 << IMM_1);
1652         RN = res;
1653         SET_ZN(res);
1654 #ifdef DSP_DIS_BSET
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_subqt(void)
1661 {
1662 #ifdef DSP_DIS_SUBQT
1663         if (doDSPDis)
1664                 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);
1665 #endif
1666         RN -= dsp_convert_zero[IMM_1];
1667 #ifdef DSP_DIS_SUBQT
1668         if (doDSPDis)
1669                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1670 #endif
1671 }
1672
1673 static void dsp_opcode_addqt(void)
1674 {
1675 #ifdef DSP_DIS_ADDQT
1676         if (doDSPDis)
1677                 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);
1678 #endif
1679         RN += dsp_convert_zero[IMM_1];
1680 #ifdef DSP_DIS_ADDQT
1681         if (doDSPDis)
1682                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1683 #endif
1684 }
1685
1686 static void dsp_opcode_imacn(void)
1687 {
1688 #ifdef DSP_DIS_IMACN
1689         if (doDSPDis)
1690                 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);
1691 #endif
1692         int32 res = (int16)RM * (int16)RN;
1693         dsp_acc += (int64)res;
1694 //Should we AND the result to fit into 40 bits here???
1695 #ifdef DSP_DIS_IMACN
1696         if (doDSPDis)
1697                 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));
1698 #endif
1699
1700
1701 static void dsp_opcode_mtoi(void)
1702 {
1703         RN = (((INT32)RM >> 8) & 0xFF800000) | (RM & 0x007FFFFF);
1704         SET_ZN(RN);
1705 }
1706
1707 static void dsp_opcode_normi(void)
1708 {
1709         uint32 _Rm = RM;
1710         uint32 res = 0;
1711
1712         if (_Rm)
1713         {
1714                 while ((_Rm & 0xffc00000) == 0)
1715                 {
1716                         _Rm <<= 1;
1717                         res--;
1718                 }
1719                 while ((_Rm & 0xff800000) != 0)
1720                 {
1721                         _Rm >>= 1;
1722                         res++;
1723                 }
1724         }
1725         RN = res;
1726         SET_ZN(RN);
1727 }
1728
1729 static void dsp_opcode_mmult(void)
1730 {
1731         int count       = dsp_matrix_control&0x0f;
1732         uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
1733         int64 accum = 0;
1734         uint32 res;
1735
1736         if (!(dsp_matrix_control & 0x10))
1737         {
1738                 for (int i = 0; i < count; i++)
1739                 { 
1740                         int16 a;
1741                         if (i&0x01)
1742                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1743                         else
1744                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1745                         int16 b=((int16)DSPReadWord(addr + 2, DSP));
1746                         accum += a*b;
1747                         addr += 4;
1748                 }
1749         }
1750         else
1751         {
1752                 for (int i = 0; i < count; i++)
1753                 {
1754                         int16 a;
1755                         if (i&0x01)
1756                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1757                         else
1758                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1759                         int16 b=((int16)DSPReadWord(addr + 2, DSP));
1760                         accum += a*b;
1761                         addr += 4 * count;
1762                 }
1763         }
1764         RN = res = (int32)accum;
1765         // carry flag to do
1766 //NOTE: The flags are set based upon the last add/multiply done...
1767         SET_ZN(RN);
1768 }
1769
1770 static void dsp_opcode_abs(void)
1771 {
1772         uint32 _Rn = RN;
1773         uint32 res;
1774         
1775         if (_Rn == 0x80000000)
1776                 dsp_flag_n = 1;
1777         else
1778         {
1779                 dsp_flag_c = ((_Rn & 0x80000000) >> 31);
1780                 res = RN = (_Rn & 0x80000000 ? -_Rn : _Rn);
1781                 CLR_ZN; SET_Z(res);
1782         }
1783 }
1784
1785 static void dsp_opcode_div(void)
1786 {
1787         uint32 _Rm=RM;
1788         uint32 _Rn=RN;
1789
1790         if (_Rm)
1791         {
1792                 if (dsp_div_control & 1)
1793                 {
1794                         dsp_remain = (((uint64)_Rn) << 16) % _Rm;
1795                         if (dsp_remain&0x80000000)
1796                                 dsp_remain-=_Rm;
1797                         RN = (((uint64)_Rn) << 16) / _Rm;
1798                 }
1799                 else
1800                 {
1801                         dsp_remain = _Rn % _Rm;
1802                         if (dsp_remain&0x80000000)
1803                                 dsp_remain-=_Rm;
1804                         RN/=_Rm;
1805                 }
1806         }
1807         else
1808                 RN=0xffffffff;
1809 }
1810
1811 static void dsp_opcode_imultn(void)
1812 {
1813 #ifdef DSP_DIS_IMULTN
1814         if (doDSPDis)
1815                 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);
1816 #endif
1817         // This is OK, since this multiply won't overflow 32 bits...
1818         int32 res = (int32)((int16)RN * (int16)RM);
1819         dsp_acc = (int64)res;
1820         SET_ZN(res);
1821 #ifdef DSP_DIS_IMULTN
1822         if (doDSPDis)
1823                 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));
1824 #endif
1825 }
1826
1827 static void dsp_opcode_neg(void)
1828 {
1829 #ifdef DSP_DIS_NEG
1830         if (doDSPDis)
1831                 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);
1832 #endif
1833         UINT32 res = -RN;
1834         SET_ZNC_SUB(0, RN, res);
1835         RN = res;
1836 #ifdef DSP_DIS_NEG
1837         if (doDSPDis)
1838                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1839 #endif
1840 }
1841
1842 static void dsp_opcode_shlq(void)
1843 {
1844 #ifdef DSP_DIS_SHLQ
1845         if (doDSPDis)
1846                 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);
1847 #endif
1848         INT32 r1 = 32 - IMM_1;
1849         UINT32 res = RN << r1;
1850         SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
1851         RN = res;
1852 #ifdef DSP_DIS_SHLQ
1853         if (doDSPDis)
1854                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1855 #endif
1856 }
1857
1858 static void dsp_opcode_shrq(void)
1859 {
1860 #ifdef DSP_DIS_SHRQ
1861         if (doDSPDis)
1862                 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);
1863 #endif
1864         INT32 r1 = dsp_convert_zero[IMM_1];
1865         UINT32 res = RN >> r1;
1866         SET_ZN(res); dsp_flag_c = RN & 1;
1867         RN = res;
1868 #ifdef DSP_DIS_SHRQ
1869         if (doDSPDis)
1870                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1871 #endif
1872 }
1873
1874 static void dsp_opcode_ror(void)
1875 {
1876 #ifdef DSP_DIS_ROR
1877         if (doDSPDis)
1878                 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);
1879 #endif
1880         UINT32 r1 = RM & 0x1F;
1881         UINT32 res = (RN >> r1) | (RN << (32 - r1));
1882         SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
1883         RN = res;
1884 #ifdef DSP_DIS_ROR
1885         if (doDSPDis)
1886                 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);
1887 #endif
1888 }
1889
1890 static void dsp_opcode_rorq(void)
1891 {
1892 #ifdef DSP_DIS_RORQ
1893         if (doDSPDis)
1894                 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);
1895 #endif
1896         UINT32 r1 = dsp_convert_zero[IMM_1 & 0x1F];
1897         UINT32 r2 = RN;
1898         UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
1899         RN = res;
1900         SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
1901 #ifdef DSP_DIS_RORQ
1902         if (doDSPDis)
1903                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1904 #endif
1905 }
1906
1907 static void dsp_opcode_sha(void)
1908 {
1909         int32 sRm=(int32)RM;
1910         uint32 _Rn=RN;
1911
1912         if (sRm<0)
1913         {
1914                 uint32 shift=-sRm;
1915                 if (shift>=32) shift=32;
1916                 dsp_flag_c=(_Rn&0x80000000)>>31;
1917                 while (shift)
1918                 {
1919                         _Rn<<=1;
1920                         shift--;
1921                 }
1922         }
1923         else
1924         {
1925                 uint32 shift=sRm;
1926                 if (shift>=32) shift=32;
1927                 dsp_flag_c=_Rn&0x1;
1928                 while (shift)
1929                 {
1930                         _Rn=((int32)_Rn)>>1;
1931                         shift--;
1932                 }
1933         }
1934         RN = _Rn;
1935         SET_ZN(RN);
1936 }
1937
1938 static void dsp_opcode_sharq(void)
1939 {
1940 #ifdef DSP_DIS_SHARQ
1941         if (doDSPDis)
1942                 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);
1943 #endif
1944         UINT32 res = (INT32)RN >> dsp_convert_zero[IMM_1];
1945         SET_ZN(res); dsp_flag_c = RN & 0x01;
1946         RN = res;
1947 #ifdef DSP_DIS_SHARQ
1948         if (doDSPDis)
1949                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1950 #endif
1951 }
1952
1953 static void dsp_opcode_sh(void)
1954 {
1955         int32 sRm=(int32)RM;
1956         uint32 _Rn=RN;
1957
1958         if (sRm<0)
1959         {
1960                 uint32 shift=(-sRm);
1961                 if (shift>=32) shift=32;
1962                 dsp_flag_c=(_Rn&0x80000000)>>31;
1963                 while (shift)
1964                 {
1965                         _Rn<<=1;
1966                         shift--;
1967                 }
1968         }
1969         else
1970         {
1971                 uint32 shift=sRm;
1972                 if (shift>=32) shift=32;
1973                 dsp_flag_c=_Rn&0x1;
1974                 while (shift)
1975                 {
1976                         _Rn>>=1;
1977                         shift--;
1978                 }
1979         }
1980         RN = _Rn;
1981         SET_ZN(RN);
1982 }
1983
1984 void dsp_opcode_addqmod(void)
1985 {
1986 #ifdef DSP_DIS_ADDQMOD
1987         if (doDSPDis)
1988                 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);
1989 #endif
1990         UINT32 r1 = dsp_convert_zero[IMM_1];
1991         UINT32 r2 = RN;
1992         UINT32 res = r2 + r1;
1993         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
1994         RN = res;
1995         SET_ZNC_ADD(r2, r1, res);
1996 #ifdef DSP_DIS_ADDQMOD
1997         if (doDSPDis)
1998                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1999 #endif
2000 }
2001
2002 void dsp_opcode_subqmod(void)   
2003 {
2004         UINT32 r1 = dsp_convert_zero[IMM_1];
2005         UINT32 r2 = RN;
2006         UINT32 res = r2 - r1;
2007         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2008         RN = res;
2009         
2010         SET_ZNC_SUB(r2, r1, res);
2011 }
2012
2013 void dsp_opcode_mirror(void)    
2014 {
2015         UINT32 r1 = RN;
2016         RN = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
2017         SET_ZN(RN);
2018 }
2019
2020 void dsp_opcode_sat32s(void)            
2021 {
2022         INT32 r2 = (UINT32)RN;
2023         INT32 temp = dsp_acc >> 32;
2024         UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
2025         RN = res;
2026         SET_ZN(res);
2027 }
2028
2029 void dsp_opcode_sat16s(void)            
2030 {
2031         INT32 r2 = RN;
2032         UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
2033         RN = res;
2034         SET_ZN(res);
2035 }