]> Shamusworld >> Repos - virtualjaguar/blob - src/dsp.cpp
Mostly changes to support SDL sound system
[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 // Cleanups by James L. Hammons
7 //
8
9 #include "dsp.h"
10
11 #define CINT0FLAG                       0x00200
12 #define CINT1FLAG                       0x00400
13 #define CINT2FLAG                       0x00800
14 #define CINT3FLAG                       0x01000
15 #define CINT4FLAG                       0x02000
16 #define CINT04FLAGS                     (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
17 #define CINT5FLAG                       0x20000         /* DSP only */
18
19 extern uint32 jaguar_mainRom_crc32;
20
21 static void dsp_opcode_addqmod(void);   
22 static void dsp_opcode_subqmod(void);   
23 static void dsp_opcode_mirror(void);    
24 static void dsp_opcode_sat32s(void);    
25 static void dsp_opcode_sat16s(void);    
26 static void dsp_opcode_add(void);
27 static void dsp_opcode_addc(void);
28 static void dsp_opcode_addq(void);
29 static void dsp_opcode_addqt(void);
30 static void dsp_opcode_sub(void);
31 static void dsp_opcode_subc(void);
32 static void dsp_opcode_subq(void);
33 static void dsp_opcode_subqt(void);
34 static void dsp_opcode_neg(void);
35 static void dsp_opcode_and(void);
36 static void dsp_opcode_or(void);
37 static void dsp_opcode_xor(void);
38 static void dsp_opcode_not(void);
39 static void dsp_opcode_btst(void);
40 static void dsp_opcode_bset(void);
41 static void dsp_opcode_bclr(void);
42 static void dsp_opcode_mult(void);
43 static void dsp_opcode_imult(void);
44 static void dsp_opcode_imultn(void);
45 static void dsp_opcode_resmac(void);
46 static void dsp_opcode_imacn(void);
47 static void dsp_opcode_div(void);
48 static void dsp_opcode_abs(void);
49 static void dsp_opcode_sh(void);
50 static void dsp_opcode_shlq(void);
51 static void dsp_opcode_shrq(void);
52 static void dsp_opcode_sha(void);
53 static void dsp_opcode_sharq(void);
54 static void dsp_opcode_ror(void);
55 static void dsp_opcode_rorq(void);
56 static void dsp_opcode_cmp(void);
57 static void dsp_opcode_cmpq(void);
58 static void dsp_opcode_sat8(void);
59 static void dsp_opcode_sat16(void);
60 static void dsp_opcode_move(void);
61 static void dsp_opcode_moveq(void);
62 static void dsp_opcode_moveta(void);
63 static void dsp_opcode_movefa(void);
64 static void dsp_opcode_movei(void);
65 static void dsp_opcode_loadb(void);
66 static void dsp_opcode_loadw(void);
67 static void dsp_opcode_load(void);
68 static void dsp_opcode_loadp(void);
69 static void dsp_opcode_load_r14_indexed(void);
70 static void dsp_opcode_load_r15_indexed(void);
71 static void dsp_opcode_storeb(void);
72 static void dsp_opcode_storew(void);
73 static void dsp_opcode_store(void);
74 static void dsp_opcode_storep(void);
75 static void dsp_opcode_store_r14_indexed(void);
76 static void dsp_opcode_store_r15_indexed(void);
77 static void dsp_opcode_move_pc(void);
78 static void dsp_opcode_jump(void);
79 static void dsp_opcode_jr(void);
80 static void dsp_opcode_mmult(void);
81 static void dsp_opcode_mtoi(void);
82 static void dsp_opcode_normi(void);
83 static void dsp_opcode_nop(void);
84 static void dsp_opcode_load_r14_ri(void);
85 static void dsp_opcode_load_r15_ri(void);
86 static void dsp_opcode_store_r14_ri(void);
87 static void dsp_opcode_store_r15_ri(void);
88 static void dsp_opcode_sat24(void);
89
90 uint8 dsp_opcode_cycles[64] = 
91 {
92         3,  3,  3,  3,  
93         3,  3,  3,  3,  
94         3,  3,  3,  3,  
95         3,  3,  3,  3,
96         3,  3,  1,  3,  
97         1, 18,  3,  3,  
98         3,  3,  3,  3,  
99         3,  3,  3,  3,
100         3,  3,  2,  2,  
101         2,  2,  3,  4,  
102         5,  4,  5,  6,  
103         6,  1,  1,  1,
104         1,  2,  2,  2,  
105         1,  1,  9,  3,  
106         3,  1,  6,  6,  
107         2,  2,  3,  3
108 };
109
110 void (*dsp_opcode[64])()= 
111 {       
112         dsp_opcode_add,                                 dsp_opcode_addc,                                dsp_opcode_addq,                                dsp_opcode_addqt,
113         dsp_opcode_sub,                                 dsp_opcode_subc,                                dsp_opcode_subq,                                dsp_opcode_subqt,
114         dsp_opcode_neg,                                 dsp_opcode_and,                                 dsp_opcode_or,                                  dsp_opcode_xor,
115         dsp_opcode_not,                                 dsp_opcode_btst,                                dsp_opcode_bset,                                dsp_opcode_bclr,
116         dsp_opcode_mult,                                dsp_opcode_imult,                               dsp_opcode_imultn,                              dsp_opcode_resmac,
117         dsp_opcode_imacn,                               dsp_opcode_div,                                 dsp_opcode_abs,                                 dsp_opcode_sh,
118         dsp_opcode_shlq,                                dsp_opcode_shrq,                                dsp_opcode_sha,                                 dsp_opcode_sharq,
119         dsp_opcode_ror,                                 dsp_opcode_rorq,                                dsp_opcode_cmp,                                 dsp_opcode_cmpq,
120         dsp_opcode_subqmod,                             dsp_opcode_sat16s,                              dsp_opcode_move,                                dsp_opcode_moveq,
121         dsp_opcode_moveta,                              dsp_opcode_movefa,                              dsp_opcode_movei,                               dsp_opcode_loadb,
122         dsp_opcode_loadw,                               dsp_opcode_load,                                dsp_opcode_sat32s,                              dsp_opcode_load_r14_indexed,
123         dsp_opcode_load_r15_indexed,    dsp_opcode_storeb,                              dsp_opcode_storew,                              dsp_opcode_store,
124         dsp_opcode_mirror,                              dsp_opcode_store_r14_indexed,   dsp_opcode_store_r15_indexed,   dsp_opcode_move_pc,
125         dsp_opcode_jump,                                dsp_opcode_jr,                                  dsp_opcode_mmult,                               dsp_opcode_mtoi,
126         dsp_opcode_normi,                               dsp_opcode_nop,                                 dsp_opcode_load_r14_ri,                 dsp_opcode_load_r15_ri,
127         dsp_opcode_store_r14_ri,                dsp_opcode_store_r15_ri,                dsp_opcode_nop,                                 dsp_opcode_addqmod,
128 };
129
130 uint32 dsp_opcode_use[64];
131
132 char *dsp_opcode_str[64]= 
133 {       
134         "add",                          "addc",                         "addq",                         "addqt",
135         "sub",                          "subc",                         "subq",                         "subqt",
136         "neg",                          "and",                          "or",                           "xor",
137         "not",                          "btst",                         "bset",                         "bclr",
138         "mult",                         "imult",                        "imultn",                       "resmac",
139         "imacn",                        "div",                          "abs",                          "sh",
140         "shlq",                         "shrq",                         "sha",                          "sharq",
141         "ror",                          "rorq",                         "cmp",                          "cmpq",
142         "subqmod",                      "sat16s",                       "move",                         "moveq",
143         "moveta",                       "movefa",                       "movei",                        "loadb",
144         "loadw",                        "load",                         "sat32s",                       "load_r14_indexed",
145         "load_r15_indexed",     "storeb",                       "storew",                       "store",
146         "mirror",                       "store_r14_indexed","store_r15_indexed","move_pc",
147         "jump",                         "jr",                           "mmult",                        "mtoi",
148         "normi",                        "nop",                          "load_r14_ri",          "load_r15_ri",
149         "store_r14_ri",         "store_r15_ri",         "nop",                          "addqmod",
150 };
151
152 static uint16   *mirror_table;
153 static uint8    *dsp_ram_8;
154
155 uint32 dsp_pc;
156 static uint32   dsp_acc;
157 static uint32   dsp_remain;
158 static uint32   dsp_modulo;
159 static uint32   dsp_flags;
160 static uint32   dsp_matrix_control;
161 static uint32   dsp_pointer_to_matrix;
162 static uint32   dsp_data_organization;
163 uint32 dsp_control;
164 static uint32   dsp_div_control;
165 static uint8    dsp_flag_z;
166 static uint8    dsp_flag_n;
167 static uint8    dsp_flag_c;    
168 static uint8    dsp_alternate_flag_z;
169 static uint8    dsp_alternate_flag_n;
170 static uint8    dsp_alternate_flag_c;    
171 static uint32   *dsp_reg;
172 static uint32   *dsp_alternate_reg;
173 static uint32   *dsp_reg_bank_0;
174 static uint32   *dsp_reg_bank_1;
175
176 static uint32   dsp_opcode_first_parameter;
177 static uint32   dsp_opcode_second_parameter;
178
179 #define dsp_running (dsp_control&0x01)
180
181 #define Rm dsp_reg[dsp_opcode_first_parameter]
182 #define Rn dsp_reg[dsp_opcode_second_parameter]
183 #define alternate_Rm dsp_alternate_reg[dsp_opcode_first_parameter]
184 #define alternate_Rn dsp_alternate_reg[dsp_opcode_second_parameter]
185 #define imm_1 dsp_opcode_first_parameter
186 #define imm_2 dsp_opcode_second_parameter
187
188 #define set_flag_z(r) dsp_flag_z=(r==0); 
189 #define set_flag_n(r) dsp_flag_n=(r&0x80000000);
190
191 #define reset_flag_z()  dsp_flag_z=0;
192 #define reset_flag_n()  dsp_flag_n=0;
193 #define reset_flag_c()  dsp_flag_c=0;    
194
195 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 };
196 uint8 *dsp_branch_condition_table=0;
197 #define branch_condition(x)     dsp_branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
198
199 static uint32 dsp_in_exec = 0;
200 static uint32 dsp_releaseTimeSlice_flag = 0;
201
202 FILE * dsp_fp;
203
204
205 void dsp_reset_stats(void)
206 {
207         for (uint32 i=0; i<64; i++)
208                 dsp_opcode_use[i] = 0;
209 }
210
211 void dsp_releaseTimeslice(void)
212 {
213         dsp_releaseTimeSlice_flag = 1;
214 }
215
216 void dsp_build_branch_condition_table(void)
217 {
218         int i,j;
219         #define ZFLAG                           0x00001
220         #define CFLAG                           0x00002
221         #define NFLAG                           0x00004
222         
223         /* allocate the mirror table */
224         if (!mirror_table)
225                 mirror_table = (uint16*)malloc(65536 * sizeof(mirror_table[0]));
226
227         /* fill in the mirror table */
228         if (mirror_table)
229                 for (int i = 0; i < 65536; i++)
230                         mirror_table[i] = ((i >> 15) & 0x0001) | ((i >> 13) & 0x0002) |
231                                           ((i >> 11) & 0x0004) | ((i >> 9)  & 0x0008) |
232                                           ((i >> 7)  & 0x0010) | ((i >> 5)  & 0x0020) |
233                                           ((i >> 3)  & 0x0040) | ((i >> 1)  & 0x0080) |
234                                           ((i << 1)  & 0x0100) | ((i << 3)  & 0x0200) |
235                                           ((i << 5)  & 0x0400) | ((i << 7)  & 0x0800) |
236                                           ((i << 9)  & 0x1000) | ((i << 11) & 0x2000) |
237                                           ((i << 13) & 0x4000) | ((i << 15) & 0x8000);
238
239         if (!dsp_branch_condition_table)
240         {
241                 dsp_branch_condition_table = (uint8*)malloc(32 * 8 * sizeof(dsp_branch_condition_table[0]));
242
243                 /* fill in the condition table */
244                 if (dsp_branch_condition_table)
245                         for (i = 0; i < 8; i++)
246                                 for (j = 0; j < 32; j++)
247                                 {
248                                         int result = 1;
249                                         if (j & 1)
250                                                 if (i & ZFLAG) result = 0;
251                                         if (j & 2)
252                                                 if (!(i & ZFLAG)) result = 0;
253                                         if (j & 4)
254                                                 if (i & (CFLAG << (j >> 4))) result = 0;
255                                         if (j & 8)
256                                                 if (!(i & (CFLAG << (j >> 4)))) result = 0;
257                                         dsp_branch_condition_table[i * 32 + j] = result;
258                                 }
259         }
260 }
261
262 unsigned dsp_byte_read(unsigned int offset)
263 {
264 // battlemorph
265 //      if ((offset==0xF1CFE0)||(offset==0xF1CFE2))
266 //              return(0xffff);
267         // mutant penguin
268         if ((jaguar_mainRom_crc32==0xbfd751a4)||(jaguar_mainRom_crc32==0x053efaf9))
269         {
270                 if (offset==0xF1CFE0)
271                         return(0xff);
272         }
273         if ((offset>=DSP_WORK_RAM_BASE)&&(offset<DSP_WORK_RAM_BASE+0x2000))
274                 return(dsp_ram_8[offset-DSP_WORK_RAM_BASE]);
275
276         if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
277         {
278                 uint32 data=dsp_long_read(offset&0xfffffffc);
279
280                 if ((offset&0x03)==0)
281                         return(data>>24);
282                 else
283                 if ((offset&0x03)==1)
284                         return((data>>16)&0xff);
285                 else
286                 if ((offset&0x03)==2)
287                         return((data>>8)&0xff);
288                 else
289                 if ((offset&0x03)==3)
290                         return(data&0xff);
291         }
292         return(jaguar_byte_read(offset));
293
294
295 unsigned dsp_word_read(unsigned int offset)
296 {
297         offset&=0xFFFFFFFE;
298         // jaguar cd bios
299         if (jaguar_mainRom_crc32==0xa74a97cd)
300         {
301                 if (offset==0xF1A114) return(0x0000);
302                 if (offset==0xF1A116) return(0x0000);
303                 if (offset==0xF1B000) return(0x1234);
304                 if (offset==0xF1B002) return(0x5678);
305         }
306 /*
307         if (jaguar_mainRom_crc32==0x7ae20823)
308         {
309                 if (offset==0xF1B9D8) return(0x0000);
310                 if (offset==0xF1B9Da) return(0x0000);
311                 if (offset==0xF1B2C0) return(0x0000);
312                 if (offset==0xF1B2C2) return(0x0000);
313         }
314 */
315         // pour permettre Ã  wolfenstein 3d de tourner sans le dsp
316 /*      if ((offset==0xF1B0D0)||(offset==0xF1B0D2))
317                 return(0);
318 */
319
320                 // pour permettre Ã  nba jam de tourner sans le dsp
321         if (jaguar_mainRom_crc32==0x4faddb18)
322         {
323                 if (offset==0xf1b2c0) return(0);
324                 if (offset==0xf1b2c2) return(0);
325                 if (offset==0xf1b240) return(0);
326                 if (offset==0xf1b242) return(0);
327                 if (offset==0xF1B340) return(0);
328                 if (offset==0xF1B342) return(0);
329                 if (offset==0xF1BAD8) return(0);
330                 if (offset==0xF1BADA) return(0);
331                 if (offset==0xF1B040) return(0);
332                 if (offset==0xF1B042) return(0);
333                 if (offset==0xF1B0C0) return(0);
334                 if (offset==0xF1B0C2) return(0);
335                 if (offset==0xF1B140) return(0);
336                 if (offset==0xF1B142) return(0);
337                 if (offset==0xF1B1C0) return(0);
338                 if (offset==0xF1B1C2) return(0);
339         }
340
341         if ((offset>=DSP_WORK_RAM_BASE)&&(offset<DSP_WORK_RAM_BASE+0x2000))
342         {
343                 offset-=DSP_WORK_RAM_BASE;
344                 uint16 data=(((uint16)dsp_ram_8[offset])<<8)|((uint16)dsp_ram_8[offset+1]);
345                 return(data);
346         }
347         if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
348         {
349                 uint32 data;
350
351                 data=dsp_long_read(offset&0xfffffffc);
352
353                 if (offset&0x03)
354                         return(data&0xffff);
355                 else
356                         return(data>>16);
357         }
358         return(jaguar_word_read(offset));
359 }
360
361 unsigned dsp_long_read(unsigned int offset)
362 {
363         offset&=0xFFFFFFFC;
364
365         if ((offset>=DSP_WORK_RAM_BASE)&&(offset<DSP_WORK_RAM_BASE+0x2000))
366         {
367                 offset-=DSP_WORK_RAM_BASE;
368                 uint32 data= (((uint32)dsp_ram_8[offset]  )<<24)|
369                                  (((uint32)dsp_ram_8[offset+1])<<16)|
370                                          (((uint32)dsp_ram_8[offset+2])<<8 )|
371                                          ( (uint32)dsp_ram_8[offset+3]);
372                 return(data);
373         }
374         if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
375         {
376                 offset&=0x1f;
377                 switch (offset)
378                 {
379                 case 0x00:      dsp_flag_c?(dsp_flag_c=1):(dsp_flag_c=0);
380                                         dsp_flag_z?(dsp_flag_z=1):(dsp_flag_z=0);
381                                         dsp_flag_n?(dsp_flag_n=1):(dsp_flag_n=0);
382
383                                         dsp_flags=(dsp_flags&0xFFFFFFF8)|(dsp_flag_n<<2)|(dsp_flag_c<<1)|dsp_flag_z;
384                                         
385                                         return(dsp_flags&0xFFFFC1FF);
386                 case 0x04: return(dsp_matrix_control);
387                 case 0x08: return(dsp_pointer_to_matrix);
388                 case 0x0C: return(dsp_data_organization);
389                 case 0x10: return(dsp_pc);
390                 case 0x14: return(dsp_control);
391                 case 0x18: return(dsp_modulo);
392                 case 0x1C: return(dsp_remain);
393 //              default:   // unaligned long read //__asm int 3
394                 }
395                 return(0xfffffff);
396         }
397         uint32 data=jaguar_word_read(offset);
398         data<<=16;
399         data|=jaguar_word_read(offset+2);
400         return(data);
401 }
402
403 void dsp_byte_write(unsigned offset, unsigned data)
404 {
405         if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
406         {
407                 offset -= DSP_WORK_RAM_BASE;
408                 dsp_ram_8[offset] = data;
409                 if (dsp_in_exec == 0)
410                 {
411 //                      s68000releaseTimeslice();
412                         m68k_end_timeslice();
413                         gpu_releaseTimeslice();
414                 }
415                 return;
416         }
417         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
418         {
419                 uint32 reg = offset & 0x1C;
420                 int bytenum = offset & 0x03;
421                 
422                 if ((reg >= 0x1C) && (reg <= 0x1F))
423                         dsp_div_control = (dsp_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
424                 else
425                 {
426                         uint32 old_data = dsp_long_read(offset&0xFFFFFFC);
427                         bytenum = 3 - bytenum; // convention motorola !!!
428                         old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3)); 
429                         dsp_long_write(offset & 0xFFFFFFC, old_data);
430                 }
431                 return;
432         }
433 //      fprintf(log_get(),"dsp: writing %.2x at 0x%.8x\n",data,offset);
434         jaguar_byte_write(offset, data);
435 }
436
437 void dsp_word_write(unsigned offset, unsigned data)
438 {
439         offset &= 0xFFFFFFFE;
440 //      fprintf(log_get(),"dsp: writing %.4x at 0x%.8x\n",data,offset);
441         if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
442         {
443                 offset -= DSP_WORK_RAM_BASE;
444                 dsp_ram_8[offset] = data >> 8;
445                 dsp_ram_8[offset+1] = data & 0xFF;
446                 if (dsp_in_exec == 0)
447                 {
448 //                      fprintf(log_get(),"dsp: writing %.4x at 0x%.8x\n",data,offset+DSP_WORK_RAM_BASE);
449 //                      s68000releaseTimeslice();
450                         m68k_end_timeslice();
451                         gpu_releaseTimeslice();
452                 }
453                 return;
454         }
455         else if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
456         {
457                 if ((offset & 0x1C) == 0x1C)
458                 {
459                         if (offset & 0x03)
460                                 dsp_div_control = (dsp_div_control&0xffff0000)|(data&0xffff);
461                         else
462                                 dsp_div_control = (dsp_div_control&0xffff)|((data&0xffff)<<16);
463                 }
464                 else
465                 {
466                         uint32 old_data = dsp_long_read(offset & 0xffffffc);
467                         if (offset & 0x03)
468                                 old_data = (old_data&0xffff0000)|(data&0xffff);
469                         else
470                                 old_data = (old_data&0xffff)|((data&0xffff)<<16);
471                         dsp_long_write(offset & 0xffffffc, old_data);
472                 }
473                 return;
474         }
475         jaguar_word_write(offset, data);
476 }
477
478 void dsp_long_write(unsigned offset, unsigned data)
479 {
480         offset &= 0xFFFFFFFC;
481 //      fprintf(log_get(),"dsp: writing %.8x at 0x%.8x\n",data,offset);
482         if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
483         {
484                 offset -= DSP_WORK_RAM_BASE;
485                 dsp_ram_8[offset]  = data >> 24;
486                 dsp_ram_8[offset+1] = (data>>16) & 0xFF;
487                 dsp_ram_8[offset+2] = (data>>8) & 0xFF;
488                 dsp_ram_8[offset+3] = data & 0xFF;
489                 return;
490         }
491         else if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
492         {
493                 offset&=0x1f;
494                 switch (offset)
495                 {
496                 case 0x00:
497                         dsp_flags = data;
498                         dsp_flag_z = dsp_flags & 0x01;
499                         dsp_flag_c = (dsp_flags>>1) & 0x01;
500                         dsp_flag_n = (dsp_flags>>2) & 0x01;
501                         dsp_update_register_banks();
502                         dsp_control &= ~((dsp_flags & CINT04FLAGS) >> 3);
503                         dsp_control &= ~((dsp_flags & CINT5FLAG) >> 1);
504                         dsp_check_irqs();
505                         break;
506                 case 0x04:
507                         dsp_matrix_control = data;
508                         break;
509                 case 0x08:
510                         dsp_pointer_to_matrix = data;
511                         break;
512                 case 0x0C:
513                         dsp_data_organization = data;
514                         break;
515                 case 0x10:
516                         dsp_pc = data;
517                         break;
518                 case 0x14:
519                 {       
520                         uint32 dsp_was_running = dsp_running;
521                         // check for DSP->CPU interrupt
522                         if (data & 0x02)
523                         {
524 //                                                      fprintf(log_get(),"DSP->CPU interrupt\n");
525                                 if (tom_irq_enabled(IRQ_GPU) && jaguar_interrupt_handler_is_valid(64))
526                                 {
527                                         tom_set_pending_gpu_int();
528 //                                      s68000interrupt(7,64);
529 //                                      s68000flushInterrupts();
530                                         m68k_set_irq(7);                        // Set 68000 NMI...
531                                         dsp_releaseTimeslice();
532                                 }
533                                 data &= ~(0x02);
534                         }
535                         // check for CPU->DSP interrupt
536                         if (data & 0x04)
537                         {
538 //                                                      fprintf(log_get(),"CPU->DSP interrupt\n");
539                                 dsp_set_irq_line(0, 1);
540 //                              s68000releaseTimeslice();
541                                 m68k_end_timeslice();
542                                 gpu_releaseTimeslice();
543                                 data &= ~(0x04);
544                         }
545                         // single stepping
546                         if (data & 0x10)
547                         {
548                                                         //fprintf(log_get(),"asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
549                         }
550                         dsp_control = data;
551
552                         // if dsp wasn't running but is now running
553                         // execute a few cycles
554 #ifndef DSP_SINGLE_STEPPING
555                         if (!dsp_was_running && dsp_running)
556                         {
557                                 dsp_exec(200);
558                         }
559 #else
560                         if (dsp_control & 0x18)
561                                 dsp_exec(1);
562 #endif
563                         break;
564                 }
565                 case 0x18:
566                         dsp_modulo = data;
567                         break;
568                 case 0x1C:
569                         dsp_div_control=data;
570                         break;
571 //              default:   // unaligned long read
572                                    //__asm int 3
573                 }
574                 return;
575         }
576         jaguar_word_write(offset, (data>>16) & 0xFFFF);
577         jaguar_word_write(offset+2, data & 0xFFFF);
578 }
579
580 /*uint8 * jaguar_rom_load(char * path, uint32 * romSize);
581 void dsp_load_bin_at(char * path, uint32 offset)
582 {
583         uint32 romSize;
584         uint8 * rom;
585
586         rom = jaguar_rom_load(path, &romSize);
587         for(uint32 i=0; i<romSize; i++)
588                 jaguar_byte_write(offset+i, rom[i]);
589 }//*/
590
591 static int go = 0;
592 void dsp_update_register_banks(void)
593 {
594         uint32 temp;
595         int i, bank;
596
597         bank = dsp_flags&0x4000;
598
599         if (dsp_flags & 0x8) 
600                 bank = 0;
601         
602         if ((!bank && (dsp_reg_bank_0 != dsp_reg)) || (bank && (dsp_reg_bank_1 != dsp_reg)))
603         {
604                 for (i = 0; i < 32; i++)
605                 {
606                         temp = dsp_reg[i];
607                         dsp_reg[i] = dsp_alternate_reg[i];
608                         dsp_alternate_reg[i]= temp;
609                 }
610                 // switch flags
611                 temp=dsp_flag_z;
612                 dsp_flag_z=dsp_alternate_flag_z;
613                 dsp_alternate_flag_z=temp;
614
615                 temp=dsp_flag_n;
616                 dsp_flag_n=dsp_alternate_flag_n;
617                 dsp_alternate_flag_n=temp;
618
619                 temp=dsp_flag_c;
620                 dsp_flag_c=dsp_alternate_flag_c;
621                 dsp_alternate_flag_c=temp;
622         
623                 if (!bank)
624                 {
625                         dsp_reg_bank_0 = dsp_reg;
626                         dsp_reg_bank_1 = dsp_alternate_reg;
627                 }
628                 else
629                 {
630                         dsp_reg_bank_0 = dsp_alternate_reg;
631                         dsp_reg_bank_1 = dsp_reg;
632                 }
633         }
634 }
635
636
637 void dsp_check_if_i2s_interrupt_needed(void)
638 {
639 // Commenting this shit out helped a little bit... This is probably the reason
640 // why the sound isn't working right!
641 /*      static uint32 count=8;
642
643 //      int mask;
644         count--;
645         if (count>0)
646                 return;
647
648         count=4;*/
649         // already in an interrupt handler ?
650         if (dsp_flags & 0x8) 
651                 return;
652
653         // get the interrupt mask 
654         int mask = (dsp_flags >> 4) & 0x1f;
655         mask |= (dsp_flags >> 11) & 0x20;
656
657         if (mask & 0x02)
658                 dsp_set_irq_line(1, 1);
659 }
660
661 void dsp_check_irqs(void)
662 {
663         int bits, mask, which = 0;
664
665         if (dsp_flags & 0x8) 
666                 return;
667
668         // get the active interrupt bits 
669         bits = (dsp_control >> 6) & 0x1f;
670         bits |= (dsp_control >> 10) & 0x20;
671
672         // get the interrupt mask 
673         mask = (dsp_flags >> 4) & 0x1f;
674         mask |= (dsp_flags >> 11) & 0x20;
675
676 //      fprintf(log_get(),"dsp: bits=%.2x mask=%.2x\n",bits,mask);
677         // bail if nothing is available
678         bits &= mask;
679
680         if (!bits)
681                 return;
682
683         // determine which interrupt 
684         if (bits & 0x01) which = 0;
685         if (bits & 0x02) which = 1;
686         if (bits & 0x04) which = 2;
687         if (bits & 0x08) which = 3;
688         if (bits & 0x10) which = 4;
689         if (bits & 0x20) which = 5;
690
691 //      fprintf(log_get(),"dsp: generating interrupt %i\n",which);
692
693         dsp_flags |= 0x08;
694         dsp_update_register_banks();
695
696         // subqt  #4,r31                ; pre-decrement stack pointer 
697         // move  pc,r30                 ; address of interrupted code 
698         // store  r30,(r31)     ; store return address
699         dsp_reg[31] -= 4;
700         dsp_reg[30]=dsp_pc;
701         dsp_long_write(dsp_reg[31], dsp_pc - 2);
702
703         // movei  #service_address,r30  ; pointer to ISR entry 
704         // jump  (r30)                                  ; jump to ISR 
705         // nop
706         dsp_pc = DSP_WORK_RAM_BASE;
707         dsp_pc += which * 0x10;
708         dsp_reg[30]=dsp_pc;
709 }
710
711 void dsp_set_irq_line(int irqline, int state)
712 {
713         int mask = 0x40 << irqline;
714         dsp_control &= ~mask;
715         if (state)
716         {
717                 dsp_control |= mask;
718                 dsp_check_irqs();
719         }
720 }
721
722 void dsp_init(void)
723 {
724         memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
725         memory_malloc_secure((void **)&dsp_reg, 32*sizeof(int32), "DSP bank 0 regs");
726         memory_malloc_secure((void **)&dsp_alternate_reg, 32*sizeof(int32), "DSP bank 1 regs");
727
728         dsp_build_branch_condition_table();
729         dsp_reset();
730 }
731
732 void dsp_reset(void)
733 {
734         dsp_pc                            = 0x00f1b000;
735         dsp_acc                           = 0x00000000;
736         dsp_remain                        = 0x00000000;
737         dsp_modulo                        = 0xFFFFFFFF;
738         dsp_flags                         = 0x00040000;
739         dsp_matrix_control    = 0x00000000;
740         dsp_pointer_to_matrix = 0x00000000;
741         dsp_data_organization = 0xffffffff;
742         dsp_control                       = 0x00012800;
743         dsp_div_control           = 0x00000000;
744         dsp_in_exec                       = 0;
745
746         for(int i=0; i<32; i++)
747         {
748                 dsp_reg[i]           = 0x00000000;
749                 dsp_alternate_reg[i] = 0x00000000;
750         }
751         
752         dsp_reg_bank_0 = dsp_reg;
753         dsp_reg_bank_1 = dsp_alternate_reg;
754 //      dsp_reg_bank_1 = dsp_reg;
755 //      dsp_reg_bank_0 = dsp_alternate_reg;
756
757         reset_flag_z();
758         reset_flag_n();
759         reset_flag_c();
760
761         dsp_alternate_flag_z = 0;
762         dsp_alternate_flag_n = 0;
763         dsp_alternate_flag_c = 0;
764
765         dsp_reset_stats();
766         memset(dsp_ram_8, 0xFF, 0x2000);
767 }
768
769 void dsp_done(void)
770 {
771         int i, j;
772         fprintf(log_get(), "DSP: Stopped at PC=%08X dsp_modulo=%08X(dsp %s running)\n", dsp_pc, dsp_modulo, dsp_running ? "was" : "wasn't");
773         fprintf(log_get(), "DSP: %sin interrupt handler\n", (dsp_flags & 0x8) ? "" : "not ");
774         int bits, mask;
775
776         // get the active interrupt bits 
777         bits = (dsp_control >> 6) & 0x1F;
778         bits |= (dsp_control >> 10) & 0x20;
779
780         // get the interrupt mask 
781         mask = (dsp_flags >> 4) & 0x1F;
782         mask |= (dsp_flags >> 11) & 0x20;
783
784         fprintf(log_get(), "DSP: bits=%08X mask=%08X\n", bits, mask);
785         fprintf(log_get(), "\nRegisters bank 0\n");
786         for(int j=0; j<8; j++)
787         {
788                 fprintf(log_get(), "\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
789                                                   (j << 2) + 0, dsp_reg[(j << 2) + 0],
790                                                   (j << 2) + 1, dsp_reg[(j << 2) + 1],
791                                                   (j << 2) + 2, dsp_reg[(j << 2) + 2],
792                                                   (j << 2) + 3, dsp_reg[(j << 2) + 3]);
793         }
794 //      fprintf(log_get(),"registers bank 1\n");
795 //      for (j=0;j<8;j++)
796 //      {
797 //              fprintf(log_get(),"\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
798 //                                                (j<<2)+0,dsp_alternate_reg[(j<<2)+0],
799 //                                                (j<<2)+1,dsp_alternate_reg[(j<<2)+1],
800 //                                                (j<<2)+2,dsp_alternate_reg[(j<<2)+2],
801 //                                                (j<<2)+3,dsp_alternate_reg[(j<<2)+3]);
802 //
803 //      }
804         static char buffer[512];
805         j = DSP_WORK_RAM_BASE;
806 //      for(int i=0; i<4096; i++)
807         while (j <= 0xF1BFFF)
808         {
809                 uint32 oldj = j;
810                 j += dasmjag(JAGUAR_DSP, buffer, j);
811                 fprintf(log_get(), "\t%08X: %s\n", oldj, buffer);
812         }//*/
813
814         fprintf(log_get(),"dsp opcodes use:\n");
815         for (i=0;i<64;i++)
816         {
817                 if (dsp_opcode_use[i])
818                         fprintf(log_get(),"\t%s %i\n",dsp_opcode_str[i],dsp_opcode_use[i]);
819         }//*/
820
821         memory_free(dsp_ram_8);
822 }
823
824 void dsp_exec(int32 cycles)
825 {
826         if ((cycles!=1)&&(jaguar_mainRom_crc32==0xba74c3ed))
827                 dsp_check_if_i2s_interrupt_needed();
828
829 #ifdef DSP_SINGLE_STEPPING
830         if (dsp_control&0x18)
831         {
832                 cycles=1;
833                 dsp_control&=~0x10;
834         }
835 #endif
836         dsp_check_irqs();
837         dsp_releaseTimeSlice_flag=0;
838         dsp_in_exec++;
839         while ((cycles>0)&&(dsp_running))
840         {
841                 dsp_flag_c=(dsp_flag_c?1:0);
842                 dsp_flag_z=(dsp_flag_z?1:0);
843                 dsp_flag_n=(dsp_flag_n?1:0);
844
845
846 /*
847                 if (dsp_pc==0x00f1b02c)
848                 {
849                         if (dsp_fp)
850                         {
851                                 fclose(dsp_fp);
852                                 exit(0);
853                         }
854                 }
855                 else 
856                 if (dsp_pc==0x00f1b032)
857                 {
858                         dsp_fp=fopen("c:\\bad.log","wrt");
859                         if (dsp_fp==NULL)
860                                 MessageBox(NULL,"Cannot open dsp log","",MB_OK);
861                 }
862                 if (dsp_fp)
863                 {
864                         fprintf(dsp_fp,"0x%.8x\n",dsp_pc);
865                 }
866                 
867 //              if (dsp_pc==0x00f1b130)
868 //                      dsp_load_bin_at("SCHRIFT.DAT",0x120000);
869 */              
870                 uint16 opcode=dsp_word_read(dsp_pc);
871                 dsp_opcode_first_parameter=(opcode&0x3e0)>>5;
872                 dsp_opcode_second_parameter=(opcode&0x1f);
873                 dsp_pc+=2;
874                 dsp_opcode[opcode>>10]();
875                 dsp_opcode_use[opcode>>10]++;
876                 cycles-=dsp_opcode_cycles[opcode>>10];
877         }
878         dsp_in_exec--;
879 }
880
881 static void dsp_opcode_jump(void)
882 {
883         uint32 delayed_pc = Rm;
884         uint32 jaguar_flags;
885
886         // normalize flags
887         dsp_flag_c=dsp_flag_c?1:0;
888         dsp_flag_z=dsp_flag_z?1:0;
889         dsp_flag_n=dsp_flag_n?1:0;
890
891         jaguar_flags=(dsp_flag_n<<2)|(dsp_flag_c<<1)|dsp_flag_z;
892
893         if (branch_condition(imm_2))
894         {
895                 dsp_exec(1);
896                 dsp_pc=delayed_pc;
897         }
898 }
899
900 static void dsp_opcode_jr(void)
901 {
902         int32 offset=(imm_1&0x10) ? (0xFFFFFFF0|imm_1) : imm_1;
903
904         int32 delayed_pc = dsp_pc + (offset * 2);
905         uint32 jaguar_flags;
906
907         // normalize flags
908         dsp_flag_c=dsp_flag_c?1:0;
909         dsp_flag_z=dsp_flag_z?1:0;
910         dsp_flag_n=dsp_flag_n?1:0;
911         
912         jaguar_flags=(dsp_flag_n<<2)|(dsp_flag_c<<1)|dsp_flag_z;
913
914         if (branch_condition(imm_2))
915         {
916                 dsp_exec(1);
917                 dsp_pc=delayed_pc;
918         }
919 }
920
921 static void dsp_opcode_add(void)
922 {
923         uint32 _Rm=Rm;
924         uint32 _Rn=Rn;
925         uint32 res;
926 #ifdef __PORT__
927
928     /*
929        GCC on WIN32 (more importantly mingw) doesn't know the declared
930        variables in asm until we put a _ before it.
931        
932        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
933     */
934     #ifdef __GCCWIN32__
935         asm(
936         "addl %1, %2
937     setc  _dsp_flag_c
938         setz  _dsp_flag_z
939         sets  _dsp_flag_n
940         movl %%eax, %0
941         "
942         : "=m"(res)
943         : "d"(_Rm), "a"(_Rn));
944         
945         #else
946         asm(
947         "addl %1, %2
948         setc  dsp_flag_c
949         setz  dsp_flag_z
950         sets  dsp_flag_n
951         movl %%eax, %0
952         "
953         : "=m"(res)
954         : "d"(_Rm), "a"(_Rn));
955         #endif
956         
957 #else
958         __asm 
959         {
960                 mov   edx,_Rm
961                 mov   eax,_Rn
962                 add   eax,edx
963                 setc  [dsp_flag_c]
964                 setz  [dsp_flag_z]
965                 sets  [dsp_flag_n]
966                 mov       res,eax
967         };
968 #endif
969         Rn=res;
970 }
971
972 static void dsp_opcode_addc(void)
973 {
974         uint32 _Rm=Rm;
975         uint32 _Rn=Rn;
976         uint32 res;
977 #ifdef __PORT__
978
979     /*
980        GCC on WIN32 (more importantly mingw) doesn't know the declared
981        variables in asm until we put a _ before it.
982        
983        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
984        We use __GCCWIN32__ for this "bug".
985     */
986
987     #ifdef __GCCWIN32__ 
988         
989     asm(
990         "addl %1, %2
991         cmp       $0, _dsp_flag_c
992         clc
993         jz 1f
994         stc
995         1:
996         adc %1, %2
997         setc  _dsp_flag_c
998         setz  _dsp_flag_z
999         sets  _dsp_flag_n
1000         movl %%eax, %0
1001         "
1002         : "=m"(res)
1003         : "d"(_Rm), "a"(_Rn));
1004         #else
1005
1006     asm(
1007         "addl %1, %2
1008         cmp       $0, dsp_flag_c
1009         clc
1010         jz 1f
1011         stc
1012         1:
1013         adc %1, %2
1014         setc  dsp_flag_c
1015         setz  dsp_flag_z
1016         sets  dsp_flag_n
1017         movl %%eax, %0
1018         "
1019         : "=m"(res)
1020         : "d"(_Rm), "a"(_Rn));
1021
1022     #endif      
1023         
1024 #else
1025         __asm 
1026         {
1027                 mov   edx,_Rm
1028                 mov   eax,_Rn
1029                 cmp       [dsp_flag_c],0
1030                 clc
1031                 jz        dsp_opcode_addc_no_carry
1032                 stc
1033 dsp_opcode_addc_no_carry:
1034                 adc   eax,edx
1035                 setc  [dsp_flag_c]
1036                 setz  [dsp_flag_z]
1037                 sets  [dsp_flag_n]
1038                 mov       res,eax
1039         };
1040 #endif
1041         Rn=res;
1042 }
1043
1044 static void dsp_opcode_addq(void)
1045 {
1046         uint32 _Rn=Rn;
1047         uint32 _Rm=dsp_convert_zero[imm_1];
1048         uint32 res;
1049         
1050 #ifdef __PORT__
1051
1052     /*
1053        GCC on WIN32 (more importantly mingw) doesn't know the declared
1054        variables in asm until we put a _ before it.
1055        
1056        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1057     */
1058
1059     #ifdef __GCCWIN32__
1060     
1061         asm(
1062         "addl %1, %2
1063         setc  _dsp_flag_c
1064         setz  _dsp_flag_z
1065         sets  _dsp_flag_n
1066         movl %%eax, %0
1067         "
1068         : "=m"(res)
1069         : "d"(_Rm), "a"(_Rn));
1070         
1071         #else
1072         
1073         asm(
1074         "addl %1, %2
1075         setc  dsp_flag_c
1076         setz  dsp_flag_z
1077         sets  dsp_flag_n
1078         movl %%eax, %0
1079         "
1080         : "=m"(res)
1081         : "d"(_Rm), "a"(_Rn));
1082
1083         #endif
1084         
1085 #else
1086         __asm 
1087         {
1088                 mov   edx,_Rm
1089                 mov   eax,_Rn
1090                 add   eax,edx
1091                 setc  [dsp_flag_c]
1092                 setz  [dsp_flag_z]
1093                 sets  [dsp_flag_n]
1094                 mov       res,eax
1095         };
1096 #endif
1097         Rn=res;
1098 }
1099
1100 static void dsp_opcode_sub(void)
1101 {
1102         uint32 _Rm=Rm;
1103         uint32 _Rn=Rn;
1104         uint32 res;
1105 #ifdef __PORT__
1106
1107     /*
1108        GCC on WIN32 (more importantly mingw) doesn't know the declared
1109        variables in asm until we put a _ before it.
1110        
1111        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1112     */
1113
1114     #ifdef __GCCWIN32__
1115     
1116         asm(
1117         "subl %1, %2
1118         setc  _dsp_flag_c
1119         setz  _dsp_flag_z
1120         sets  _dsp_flag_n
1121         movl %%eax, %0
1122         "
1123         : "=m"(res)
1124         : "d"(_Rm), "a"(_Rn));
1125         
1126         #else
1127
1128         asm(
1129         "subl %1, %2
1130         setc  dsp_flag_c
1131         setz  dsp_flag_z
1132         sets  dsp_flag_n
1133         movl %%eax, %0
1134         "
1135         : "=m"(res)
1136         : "d"(_Rm), "a"(_Rn));
1137
1138         #endif  
1139         
1140 #else
1141         __asm 
1142         {
1143                 mov   eax,_Rn
1144                 mov   edx,_Rm
1145                 sub   eax,edx
1146                 setc  [dsp_flag_c]
1147                 setz  [dsp_flag_z]
1148                 sets  [dsp_flag_n]
1149                 mov       res,eax
1150         };
1151 #endif
1152         Rn=res;
1153 }
1154
1155 static void dsp_opcode_subc(void)
1156 {
1157         uint32 _Rm=Rm;
1158         uint32 _Rn=Rn;
1159         uint32 res;
1160 #ifdef __PORT__
1161
1162     /*
1163        GCC on WIN32 (more importantly mingw) doesn't know the declared
1164        variables in asm until we put a _ before it.
1165        
1166        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1167     */
1168
1169     #ifdef __GCCWIN32__
1170
1171         asm(
1172         "addl %1, %2
1173         cmp       $0, _dsp_flag_c
1174         clc
1175         jz 1f
1176         stc
1177         1:
1178         sbb %1, %2
1179         setc  _dsp_flag_c
1180         setz  _dsp_flag_z
1181         sets  _dsp_flag_n
1182         movl %%eax, %0
1183         "
1184         : "=m"(res)
1185         : "d"(_Rm), "a"(_Rn));
1186         
1187         #else
1188
1189         asm(
1190         "addl %1, %2
1191         cmp       $0, dsp_flag_c
1192         clc
1193         jz 1f
1194         stc
1195         1:
1196         sbb %1, %2
1197         setc  dsp_flag_c
1198         setz  dsp_flag_z
1199         sets  dsp_flag_n
1200         movl %%eax, %0
1201         "
1202         : "=m"(res)
1203         : "d"(_Rm), "a"(_Rn));
1204
1205         #endif
1206         
1207 #else
1208         __asm 
1209         {
1210                 mov   edx,_Rm
1211                 mov   eax,_Rn
1212                 cmp       [dsp_flag_c],0
1213                 clc
1214                 jz        dsp_opcode_subc_no_carry
1215                 stc
1216 dsp_opcode_subc_no_carry:
1217                 sbb   eax,edx
1218                 setc  [dsp_flag_c]
1219                 setz  [dsp_flag_z]
1220                 sets  [dsp_flag_n]
1221                 mov       res,eax
1222         };
1223 #endif
1224         Rn=res;
1225 }
1226
1227 static void dsp_opcode_subq(void)
1228 {
1229         uint32 _Rm=dsp_convert_zero[imm_1];
1230         uint32 _Rn=Rn;
1231         uint32 res;
1232 #ifdef __PORT__
1233
1234     /*
1235        GCC on WIN32 (more importantly mingw) doesn't know the declared
1236        variables in asm until we put a _ before it.
1237        
1238        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1239     */
1240
1241     #ifdef __GCCWIN32__
1242
1243         asm(
1244         "subl %1, %2
1245         setc  _dsp_flag_c
1246         setz  _dsp_flag_z
1247         sets  _dsp_flag_n
1248         movl %%eax, %0
1249         "
1250         : "=m"(res)
1251         : "d"(_Rm), "a"(_Rn));
1252         
1253         #else
1254
1255         asm(
1256         "subl %1, %2
1257         setc  dsp_flag_c
1258         setz  dsp_flag_z
1259         sets  dsp_flag_n
1260         movl %%eax, %0
1261         "
1262         : "=m"(res)
1263         : "d"(_Rm), "a"(_Rn));
1264         
1265         #endif
1266 #else
1267         __asm 
1268         {
1269                 mov   eax,_Rn
1270                 mov   edx,_Rm
1271                 sub   eax,edx
1272                 setc  [dsp_flag_c]
1273                 setz  [dsp_flag_z]
1274                 sets  [dsp_flag_n]
1275                 mov       res,eax
1276         };
1277 #endif
1278         Rn=res;
1279 }
1280
1281 static void dsp_opcode_cmp(void)
1282 {
1283         uint32 _Rm=Rm;
1284         uint32 _Rn=Rn;
1285 #ifdef __PORT__
1286
1287     /*
1288        GCC on WIN32 (more importantly mingw) doesn't know the declared
1289        variables in asm until we put a _ before it.
1290        
1291        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1292     */
1293
1294     #ifdef __GCCWIN32__
1295
1296         asm(
1297         "cmpl %0, %1
1298         setc  _dsp_flag_c
1299         setz  _dsp_flag_z
1300         sets  _dsp_flag_n
1301         "
1302         :
1303         : "d"(_Rm), "a"(_Rn));
1304         
1305         #else
1306         
1307         asm(
1308         "cmpl %0, %1
1309         setc  dsp_flag_c
1310         setz  dsp_flag_z
1311         sets  dsp_flag_n
1312         "
1313         :
1314         : "d"(_Rm), "a"(_Rn));
1315         
1316         #endif
1317         
1318 #else
1319         __asm 
1320         {
1321                 mov   eax,_Rn
1322                 mov   edx,_Rm
1323                 cmp   eax,edx
1324                 setc  [dsp_flag_c]
1325                 setz  [dsp_flag_z]
1326                 sets  [dsp_flag_n]
1327         };
1328 #endif
1329 }
1330
1331 static void dsp_opcode_cmpq(void)
1332 {
1333         static int32 sqtable[32] = { 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};
1334         int32 _Rm=sqtable[imm_1&0x1f];
1335         uint32 _Rn=Rn;
1336 #ifdef __PORT__
1337
1338     /*
1339        GCC on WIN32 (more importantly mingw) doesn't know the declared
1340        variables in asm until we put a _ before it.
1341        
1342        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1343     */
1344
1345     #ifdef __GCCWIN32__
1346
1347         asm(
1348         "cmpl %0, %1
1349         setc  _dsp_flag_c
1350         setz  _dsp_flag_z
1351         sets  _dsp_flag_n
1352         "
1353         :
1354         : "d"(_Rm), "a"(_Rn));
1355         
1356         #else
1357
1358         asm(
1359         "cmpl %0, %1
1360         setc  dsp_flag_c
1361         setz  dsp_flag_z
1362         sets  dsp_flag_n
1363         "
1364         :
1365         : "d"(_Rm), "a"(_Rn));
1366         
1367         #endif
1368         
1369 #else
1370         __asm 
1371         {
1372                 mov   eax,_Rn
1373                 mov   edx,_Rm
1374                 cmp   eax,edx
1375                 setc  [dsp_flag_c]
1376                 setz  [dsp_flag_z]
1377                 sets  [dsp_flag_n]
1378         };
1379 #endif
1380 }
1381
1382 static void dsp_opcode_and(void)
1383 {
1384         uint32 _Rm=Rm;
1385         uint32 _Rn=Rn;
1386         uint32 res;
1387 #ifdef __PORT__
1388
1389     /*
1390        GCC on WIN32 (more importantly mingw) doesn't know the declared
1391        variables in asm until we put a _ before it.
1392        
1393        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1394     */
1395
1396     #ifdef __GCCWIN32__
1397
1398         asm(
1399         "andl %1, %2
1400         setz  _dsp_flag_z
1401         sets  _dsp_flag_n
1402         movl %%eax, %0
1403         "
1404         : "=m"(res)
1405         : "d"(_Rm), "a"(_Rn));
1406         
1407         #else
1408
1409         asm(
1410         "andl %1, %2
1411         setz  dsp_flag_z
1412         sets  dsp_flag_n
1413         movl %%eax, %0
1414         "
1415         : "=m"(res)
1416         : "d"(_Rm), "a"(_Rn));
1417         
1418         #endif
1419         
1420 #else
1421         __asm 
1422         {
1423                 mov   eax,_Rn
1424                 mov   edx,_Rm
1425                 and   eax,edx
1426                 setz  [dsp_flag_z]
1427                 sets  [dsp_flag_n]
1428                 mov   res,eax
1429         };
1430 #endif
1431         Rn=res;
1432 }
1433
1434 static void dsp_opcode_or(void)
1435 {
1436         uint32 _Rm=Rm;
1437         uint32 _Rn=Rn;
1438         uint32 res;
1439 #ifdef __PORT__
1440
1441     /*
1442        GCC on WIN32 (more importantly mingw) doesn't know the declared
1443        variables in asm until we put a _ before it.
1444        
1445        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1446     */
1447
1448     #ifdef __GCCWIN32__
1449
1450         asm(
1451         "orl %1, %2
1452         setz  _dsp_flag_z
1453         sets  _dsp_flag_n
1454         movl %%eax, %0
1455         "
1456         : "=m"(res)
1457         : "d"(_Rm), "a"(_Rn));
1458         
1459         #else
1460         
1461         asm(
1462         "orl %1, %2
1463         setz  dsp_flag_z
1464         sets  dsp_flag_n
1465         movl %%eax, %0
1466         "
1467         : "=m"(res)
1468         : "d"(_Rm), "a"(_Rn));
1469         
1470         #endif
1471
1472 #else
1473         __asm 
1474         {
1475                 mov   eax,_Rn
1476                 mov   edx,_Rm
1477                 or    eax,edx
1478                 setz  [dsp_flag_z]
1479                 sets  [dsp_flag_n]
1480                 mov   res,eax
1481         };
1482 #endif
1483         Rn=res;
1484 }
1485
1486 static void dsp_opcode_xor(void)
1487 {
1488         uint32 _Rm=Rm;
1489         uint32 _Rn=Rn;
1490         uint32 res;
1491 #ifdef __PORT__
1492
1493     /*
1494        GCC on WIN32 (more importantly mingw) doesn't know the declared
1495        variables in asm until we put a _ before it.
1496        
1497        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1498     */
1499
1500     #ifdef __GCCWIN32__
1501
1502         asm(
1503         "xorl %1, %2
1504         setz  _dsp_flag_z
1505         sets  _dsp_flag_n
1506         movl %%eax, %0
1507         "
1508         : "=m"(res)
1509         : "d"(_Rm), "a"(_Rn));
1510         
1511         #else
1512         
1513         asm(
1514         "xorl %1, %2
1515         setz  dsp_flag_z
1516         sets  dsp_flag_n
1517         movl %%eax, %0
1518         "
1519         : "=m"(res)
1520         : "d"(_Rm), "a"(_Rn));
1521         
1522         #endif
1523         
1524 #else
1525         __asm 
1526         {
1527                 mov   eax,_Rn
1528                 mov   edx,_Rm
1529                 xor   eax,edx
1530                 setz  [dsp_flag_z]
1531                 sets  [dsp_flag_n]
1532                 mov   res,eax
1533         };
1534 #endif
1535         Rn=res;
1536 }
1537
1538 static void dsp_opcode_not(void)
1539 {
1540         uint32 _Rn=Rn;
1541         uint32 res;
1542 #ifdef __PORT__
1543
1544     /*
1545        GCC on WIN32 (more importantly mingw) doesn't know the declared
1546        variables in asm until we put a _ before it.
1547        
1548        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1549     */
1550
1551     #ifdef __GCCWIN32__
1552
1553         asm(
1554         "notl %1
1555         setz  _dsp_flag_z
1556         sets  _dsp_flag_n
1557         movl %%eax, %0
1558         "
1559         : "=m"(res)
1560         : "a"(_Rn));
1561         
1562         #else
1563         
1564         asm(
1565         "notl %1
1566         setz  dsp_flag_z
1567         sets  dsp_flag_n
1568         movl %%eax, %0
1569         "
1570         : "=m"(res)
1571         : "a"(_Rn));
1572         
1573         #endif
1574         
1575 #else
1576         __asm 
1577         {
1578                 mov   eax,_Rn
1579                 not   eax
1580                 setz  [dsp_flag_z]
1581                 sets  [dsp_flag_n]
1582                 mov   res,eax
1583         };
1584 #endif
1585         Rn=res;
1586 }
1587
1588 static void dsp_opcode_move_pc(void)
1589 {
1590         Rn = dsp_pc-2; 
1591 }
1592
1593 static void dsp_opcode_sat8(void)
1594 {
1595         int32 _Rn=(int32)Rn;
1596
1597         uint32 res= Rn = (_Rn<0) ? 0 : (_Rn > 0xff ? 0xff : _Rn);
1598         set_flag_z(res);
1599         reset_flag_n();
1600 }
1601
1602 static void dsp_opcode_sat16(void)
1603 {
1604         uint32 _Rn=Rn;
1605         uint32 res= Rn = (_Rn&0x80000000) ? 0 : (_Rn > 0xFFFF ? 0xFFFF : _Rn);
1606         set_flag_z(res);
1607         reset_flag_n();
1608 }
1609
1610 static void dsp_opcode_sat24(void)
1611 {
1612         uint32 _Rn=Rn;
1613
1614         uint32 res= Rn = (_Rn&0x80000000) ? 0 : (_Rn > 0xFFFFFF ? 0xFFFFFF : _Rn);
1615         set_flag_z(res);
1616         reset_flag_n();
1617 }
1618
1619 static void dsp_opcode_store_r14_indexed(void)
1620 {
1621         dsp_long_write( dsp_reg[14] + (dsp_convert_zero[imm_1] << 2),Rn);
1622 }
1623
1624 static void dsp_opcode_store_r15_indexed(void)
1625 {
1626         dsp_long_write( dsp_reg[15] + (dsp_convert_zero[imm_1] << 2),Rn);
1627 }
1628
1629 static void dsp_opcode_load_r14_ri(void)
1630 {
1631         Rn=dsp_long_read(dsp_reg[14] + Rm);
1632 }
1633
1634 static void dsp_opcode_load_r15_ri(void)
1635 {
1636         Rn=dsp_long_read(dsp_reg[15] + Rm);
1637 }
1638
1639 static void dsp_opcode_store_r14_ri(void)
1640 {
1641         dsp_long_write(dsp_reg[14] + Rm,Rn);
1642 }
1643
1644 static void dsp_opcode_store_r15_ri(void)
1645 {
1646         dsp_long_write(dsp_reg[15] + Rm,Rn);
1647 }
1648
1649 static void dsp_opcode_nop(void)
1650 {
1651 }
1652
1653 static void dsp_opcode_pack(void)
1654 {
1655         uint32 _Rn=Rn;
1656
1657         if (Rm==0)
1658         {
1659                 Rn =((_Rn & 0x03C00000) >> 10) |
1660                         ((_Rn & 0x0001E000) >> 5)  |
1661                         ((_Rn & 0x000000FF));
1662         }
1663         else
1664         {
1665                 Rn =((_Rn & 0x0000F000) << 10) |
1666                         ((_Rn & 0x00000F00) << 5)  |
1667                         ((_Rn & 0x000000FF));
1668         }
1669         reset_flag_z();
1670         reset_flag_n();
1671         set_flag_z(Rn);
1672         set_flag_n(Rn);
1673 }
1674
1675 static void dsp_opcode_storeb(void)
1676 {
1677         if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1678                 dsp_long_write(Rm,Rn&0xff);
1679         else
1680                 jaguar_byte_write(Rm,Rn);
1681 }
1682
1683 static void dsp_opcode_storew(void)
1684 {
1685         if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1686                 dsp_long_write(Rm,Rn&0xffff);
1687         else
1688                 jaguar_word_write(Rm,Rn);
1689 }
1690
1691 static void dsp_opcode_store(void)
1692 {
1693         dsp_long_write(Rm,Rn);
1694 }
1695
1696 static void dsp_opcode_loadb(void)
1697 {
1698         if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1699                 Rn=dsp_long_read(Rm)&0xff;
1700         else
1701                 Rn=jaguar_byte_read(Rm);
1702 }
1703
1704 static void dsp_opcode_loadw(void)
1705 {
1706         if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1707                 Rn=dsp_long_read(Rm)&0xffff;
1708         else
1709                 Rn=jaguar_word_read(Rm);
1710 }
1711
1712 static void dsp_opcode_load(void)
1713 {
1714         Rn = dsp_long_read(Rm);
1715 }
1716
1717 static void dsp_opcode_load_r14_indexed(void)
1718 {
1719         Rn = dsp_long_read( dsp_reg[14] + (dsp_convert_zero[imm_1] << 2));
1720 }
1721
1722 static void dsp_opcode_load_r15_indexed(void)
1723 {
1724         Rn = dsp_long_read( dsp_reg[15] + (dsp_convert_zero[imm_1] << 2));
1725 }
1726
1727 static void dsp_opcode_movei(void)
1728 {
1729         Rn = ((uint32)dsp_word_read(dsp_pc)) + (((uint32)dsp_word_read(dsp_pc+2))<<16);
1730         dsp_pc+=4;
1731 }
1732
1733 static void dsp_opcode_moveta(void)
1734 {
1735         alternate_Rn = Rm;
1736 }
1737
1738 static void dsp_opcode_movefa(void)
1739 {
1740         Rn = alternate_Rm;
1741 }
1742
1743 static void dsp_opcode_move(void)
1744 {
1745         Rn = Rm;
1746 }
1747
1748 static void dsp_opcode_moveq(void)
1749 {
1750         Rn = imm_1;    
1751 }
1752
1753 static void dsp_opcode_resmac(void)
1754 {
1755         Rn = dsp_acc;
1756 }
1757
1758 static void dsp_opcode_imult(void)
1759 {
1760         uint32 res=Rn=((int16)Rn)*((int16)Rm);
1761         set_flag_z(res);
1762         set_flag_n(res);
1763 }
1764
1765 static void dsp_opcode_mult(void)
1766 {
1767         uint32 res=Rn =  ((uint16)Rm) * ((uint16)Rn);
1768         set_flag_z(res);
1769         set_flag_n(res);
1770 }
1771
1772 static void dsp_opcode_bclr(void)
1773 {
1774         uint32 _Rm=imm_1;
1775         uint32 _Rn=Rn;
1776         uint32 res;
1777 #ifdef __PORT__
1778
1779     /*
1780        GCC on WIN32 (more importantly mingw) doesn't know the declared
1781        variables in asm until we put a _ before it.
1782        
1783        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1784     */
1785
1786     #ifdef __GCCWIN32__
1787
1788         asm(
1789         "btrl %1, %2
1790         cmpl $0, %2
1791         setz  _dsp_flag_z
1792         sets  _dsp_flag_n
1793         movl %%eax, %0
1794         "
1795         : "=m"(res)
1796         : "c"(_Rm), "a"(_Rn));
1797         
1798         #else
1799
1800         asm(
1801         "btrl %1, %2
1802         cmpl $0, %2
1803         setz  dsp_flag_z
1804         sets  dsp_flag_n
1805         movl %%eax, %0
1806         "
1807         : "=m"(res)
1808         : "c"(_Rm), "a"(_Rn));
1809         
1810         #endif
1811         
1812         
1813 #else
1814         __asm 
1815         {
1816                 mov   eax,_Rn
1817                 mov   ecx,_Rm
1818                 btr       eax,ecx
1819                 cmp   eax,0
1820                 setz  [dsp_flag_z]
1821                 sets  [dsp_flag_n]
1822                 mov   res,eax
1823         };
1824 #endif
1825         Rn=res;
1826 }
1827
1828 static void dsp_opcode_btst(void)
1829 {
1830         uint32 _Rm=imm_1;
1831         uint32 _Rn=Rn;
1832 #ifdef __PORT__
1833
1834     /*
1835        GCC on WIN32 (more importantly mingw) doesn't know the declared
1836        variables in asm until we put a _ before it.
1837        
1838        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1839     */
1840
1841     #ifdef __GCCWIN32__
1842
1843         asm(
1844         "bt %0, %1
1845         setnc _dsp_flag_z
1846         "
1847         :
1848         : "c"(_Rm), "a"(_Rn));
1849         
1850         #else
1851         
1852         asm(
1853         "bt %0, %1
1854         setnc dsp_flag_z
1855         "
1856         :
1857         : "c"(_Rm), "a"(_Rn));
1858         
1859         #endif
1860         
1861 #else
1862         __asm 
1863         {
1864                 mov   eax,_Rn
1865                 mov   ecx,_Rm
1866                 bt        eax,ecx
1867                 setnc [dsp_flag_z]
1868         };
1869 #endif
1870 }
1871
1872 static void dsp_opcode_bset(void)
1873 {
1874         uint32 _Rm=imm_1;
1875         uint32 _Rn=Rn;
1876         uint32 res;
1877 #ifdef __PORT__
1878
1879     /*
1880        GCC on WIN32 (more importantly mingw) doesn't know the declared
1881        variables in asm until we put a _ before it.
1882        
1883        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1884     */
1885
1886     #ifdef __GCCWIN32__
1887
1888         asm(
1889         "btsl %1, %2
1890         cmpl $0, %2
1891         setz  _dsp_flag_z
1892         sets  _dsp_flag_n
1893         movl %%eax, %0
1894         "
1895         : "=m"(res)
1896         : "c"(_Rm), "a"(_Rn));
1897         
1898         #else
1899         
1900         asm(
1901         "btsl %1, %2
1902         cmpl $0, %2
1903         setz  dsp_flag_z
1904         sets  dsp_flag_n
1905         movl %%eax, %0
1906         "
1907         : "=m"(res)
1908         : "c"(_Rm), "a"(_Rn));
1909         
1910         #endif
1911         
1912 #else
1913         __asm 
1914         {
1915                 mov   eax,_Rn
1916                 mov   ecx,_Rm
1917                 bts       eax,ecx
1918                 cmp   eax,0
1919                 setz  [dsp_flag_z]
1920                 sets  [dsp_flag_n]
1921                 mov   res,eax
1922         };
1923 #endif
1924         Rn=res;
1925 }
1926
1927 static void dsp_opcode_subqt(void)
1928 {
1929         Rn -= dsp_convert_zero[imm_1];
1930 }
1931
1932 static void dsp_opcode_addqt(void)
1933 {
1934         Rn += dsp_convert_zero[imm_1];
1935 }
1936
1937 static void dsp_opcode_imacn(void)
1938 {
1939         uint32 res=((int16)Rm) * ((int16)(Rn));
1940         dsp_acc += res;
1941
1942
1943 static void dsp_opcode_mtoi(void)
1944 {
1945         uint32 _Rm=Rm;
1946         uint32 res=Rn=(((INT32)_Rm >> 8) & 0xff800000) | (_Rm & 0x007fffff);
1947         set_flag_z(res);
1948         set_flag_n(res);
1949 }
1950
1951 static void dsp_opcode_normi(void)
1952 {
1953         uint32 _Rm = Rm;
1954         uint32 res = 0;
1955
1956         if (_Rm)
1957         {
1958                 while ((_Rm & 0xffc00000) == 0)
1959                 {
1960                         _Rm <<= 1;
1961                         res--;
1962                 }
1963                 while ((_Rm & 0xff800000) != 0)
1964                 {
1965                         _Rm >>= 1;
1966                         res++;
1967                 }
1968         }
1969         Rn = res;
1970         set_flag_z(res);
1971         set_flag_n(res);
1972 }
1973
1974 static void dsp_opcode_mmult(void)
1975 {
1976         int count       = dsp_matrix_control&0x0f;
1977         uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
1978         int64 accum = 0;
1979         uint32 res;
1980
1981         if (!(dsp_matrix_control & 0x10))
1982         {
1983                 for (int i = 0; i < count; i++)
1984                 { 
1985                         int16 a;
1986                         if (i&0x01)
1987                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1988                         else
1989                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1990                         int16 b=((int16)dsp_word_read(addr+2));
1991                         accum += a*b;
1992                         addr += 4;
1993                 }
1994         }
1995         else
1996         {
1997                 for (int i = 0; i < count; i++)
1998                 {
1999                         int16 a;
2000                         if (i&0x01)
2001                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
2002                         else
2003                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
2004                         int16 b=((int16)dsp_word_read(addr+2));
2005                         accum += a*b;
2006                         addr += 4 * count;
2007                 }
2008         }
2009         Rn = res = (int32)accum;
2010         // carry flag to do
2011         set_flag_z(res);
2012         set_flag_n(res);
2013 }
2014
2015 static void dsp_opcode_abs(void)
2016 {
2017         uint32 _Rn=Rn;
2018         uint32 res;
2019         
2020         if (_Rn==0x80000000)
2021         {
2022                 set_flag_n(1);
2023         }
2024         else
2025         {
2026                 dsp_flag_c  = ((_Rn&0x80000000)>>31);
2027                 res= Rn =  (_Rn & 0x80000000) ? -_Rn : _Rn;
2028                 reset_flag_n();
2029                 set_flag_z(res);
2030         }
2031 }
2032
2033 static void dsp_opcode_div(void)
2034 {
2035         uint32 _Rm=Rm;
2036         uint32 _Rn=Rn;
2037
2038         if (_Rm)
2039         {
2040                 if (dsp_div_control & 1)
2041                 {
2042                         dsp_remain = (((uint64)_Rn) << 16) % _Rm;
2043                         if (dsp_remain&0x80000000)
2044                                 dsp_remain-=_Rm;
2045                         Rn = (((uint64)_Rn) << 16) / _Rm;
2046                 }
2047                 else
2048                 {
2049                         dsp_remain = _Rn % _Rm;
2050                         if (dsp_remain&0x80000000)
2051                                 dsp_remain-=_Rm;
2052                         Rn/=_Rm;
2053                 }
2054         }
2055         else
2056                 Rn=0xffffffff;
2057 }
2058
2059 static void dsp_opcode_imultn(void)
2060 {
2061         uint32 res=(int32)(((int16)Rn)*((int16)Rm));
2062         dsp_acc=(int32)res;
2063         set_flag_z(res);
2064         set_flag_n(res);
2065 }
2066
2067 static void dsp_opcode_neg(void)
2068 {
2069         uint32 _Rn=Rn;
2070         uint32 res;
2071 #ifdef __PORT__
2072
2073     /*
2074        GCC on WIN32 (more importantly mingw) doesn't know the declared
2075        variables in asm until we put a _ before it.
2076        
2077        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2078     */
2079
2080     #ifdef __GCCWIN32__
2081
2082         asm(
2083         "
2084         subl %1, %2
2085         setc  _dsp_flag_c
2086         setz  _dsp_flag_z
2087         sets  _dsp_flag_n
2088         movl %%eax, %0
2089         "
2090         : "=m"(res)
2091         : "d"(_Rn), "a"(0));
2092         
2093         #else
2094
2095         asm(
2096         "
2097         subl %1, %2
2098         setc  dsp_flag_c
2099         setz  dsp_flag_z
2100         sets  dsp_flag_n
2101         movl %%eax, %0
2102         "
2103         : "=m"(res)
2104         : "d"(_Rn), "a"(0));
2105         
2106         #endif
2107         
2108 #else
2109         __asm 
2110         {
2111                 xor       eax,eax
2112                 mov   edx,_Rn
2113                 sub   eax,edx
2114                 setc  [dsp_flag_c]
2115                 setz  [dsp_flag_z]
2116                 sets  [dsp_flag_n]
2117                 mov       res,eax
2118         };
2119 #endif
2120         Rn=res;
2121 }
2122
2123 static void dsp_opcode_shlq(void)
2124 {
2125         uint32 shift=(32-dsp_convert_zero[imm_1]);
2126         uint32 _Rn=Rn;
2127         uint32 res;
2128 #ifdef __PORT__
2129
2130     /*
2131        GCC on WIN32 (more importantly mingw) doesn't know the declared
2132        variables in asm until we put a _ before it.
2133        
2134        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2135     */
2136
2137     #ifdef __GCCWIN32__
2138
2139         asm(
2140         "testl $0x80000000, %2
2141         setnz _dsp_flag_c
2142         shl %%cl, %2
2143         cmpl $0, %2
2144         setz  _dsp_flag_z
2145         sets  _dsp_flag_n
2146         movl %%eax, %0
2147         "
2148         : "=m"(res)
2149         : "c"(shift), "a"(_Rn));
2150         
2151         #else
2152         
2153         asm(
2154         "testl $0x80000000, %2
2155         setnz dsp_flag_c
2156         shl %%cl, %2
2157         cmpl $0, %2
2158         setz  dsp_flag_z
2159         sets  dsp_flag_n
2160         movl %%eax, %0
2161         "
2162         : "=m"(res)
2163         : "c"(shift), "a"(_Rn));
2164
2165         #endif  
2166         
2167 #else
2168         __asm 
2169         {
2170                 mov ecx,shift
2171                 mov eax,_Rn
2172                 test eax,0x80000000
2173                 setnz [dsp_flag_c]
2174                 shl eax,cl
2175                 cmp eax,0
2176                 setz [dsp_flag_z]
2177                 sets [dsp_flag_n]
2178                 mov res,eax
2179         }
2180 #endif
2181         Rn=res;
2182 }
2183
2184 static void dsp_opcode_shrq(void)
2185 {
2186         uint32 shift=dsp_convert_zero[imm_1];
2187         uint32 _Rn=Rn;
2188         
2189         uint32 res;
2190 #ifdef __PORT__
2191
2192     /*
2193        GCC on WIN32 (more importantly mingw) doesn't know the declared
2194        variables in asm until we put a _ before it.
2195        
2196        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2197     */
2198
2199     #ifdef __GCCWIN32__
2200
2201         asm(
2202         "testl $0x00000001, %2
2203         setnz _dsp_flag_c
2204         shr %%cl, %2
2205         cmpl $0, %2
2206         setz  _dsp_flag_z
2207         sets  _dsp_flag_n
2208         movl %%eax, %0
2209         "
2210         : "=m"(res)
2211         : "c"(shift), "a"(_Rn));
2212         
2213         #else
2214         
2215         asm(
2216         "testl $0x00000001, %2
2217         setnz dsp_flag_c
2218         shr %%cl, %2
2219         cmpl $0, %2
2220         setz  dsp_flag_z
2221         sets  dsp_flag_n
2222         movl %%eax, %0
2223         "
2224         : "=m"(res)
2225         : "c"(shift), "a"(_Rn));
2226
2227         #endif  
2228
2229 #else
2230         __asm 
2231         {
2232                 mov ecx,shift
2233                 mov eax,_Rn
2234                 test eax,0x00000001
2235                 setnz [dsp_flag_c]
2236                 shr eax,cl
2237                 cmp eax,0
2238                 setz [dsp_flag_z]
2239                 sets [dsp_flag_n]
2240                 mov res,eax
2241         }
2242 #endif
2243         Rn=res;
2244 }
2245
2246 static void dsp_opcode_ror(void)
2247 {
2248         uint32 shift=Rm;
2249         uint32 _Rn=Rn;
2250         uint32 res;
2251 #ifdef __PORT__
2252
2253     /*
2254        GCC on WIN32 (more importantly mingw) doesn't know the declared
2255        variables in asm until we put a _ before it.
2256        
2257        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2258     */
2259
2260     #ifdef __GCCWIN32__
2261
2262         asm(
2263         "testl $0x80000000, %2
2264         setnz _dsp_flag_c
2265         ror %%cl, %2
2266         cmpl $0, %2
2267         setz  _dsp_flag_z
2268         sets  _dsp_flag_n
2269         movl %%eax, %0
2270         "
2271         : "=m"(res)
2272         : "c"(shift), "a"(_Rn));
2273         
2274         #else
2275
2276         asm(
2277         "testl $0x80000000, %2
2278         setnz dsp_flag_c
2279         ror %%cl, %2
2280         cmpl $0, %2
2281         setz  dsp_flag_z
2282         sets  dsp_flag_n
2283         movl %%eax, %0
2284         "
2285         : "=m"(res)
2286         : "c"(shift), "a"(_Rn));
2287         
2288         #endif
2289         
2290 #else
2291         __asm 
2292         {
2293                 mov ecx,shift
2294                 mov eax,_Rn
2295                 test eax,0x80000000
2296                 setnz [dsp_flag_c]
2297                 ror eax,cl
2298                 cmp eax,0
2299                 setz [dsp_flag_z]
2300                 sets [dsp_flag_n]
2301                 mov res,eax
2302         }
2303 #endif
2304         Rn=res;
2305 }
2306
2307 static void dsp_opcode_rorq(void)
2308 {
2309         uint32 shift=dsp_convert_zero[imm_1&0x1f];
2310         uint32 _Rn=Rn;
2311         uint32 res;
2312 #ifdef __PORT__
2313
2314     /*
2315        GCC on WIN32 (more importantly mingw) doesn't know the declared
2316        variables in asm until we put a _ before it.
2317        
2318        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2319     */
2320
2321     #ifdef __GCCWIN32__
2322
2323         asm(
2324         "testl $0x80000000, %2
2325         setnz _dsp_flag_c
2326         ror %%cl, %2
2327         cmpl $0, %2
2328         setz  _dsp_flag_z
2329         sets  _dsp_flag_n
2330         movl %%eax, %0
2331         "
2332         : "=m"(res)
2333         : "c"(shift), "a"(_Rn));
2334         
2335         #else
2336         
2337         asm(
2338         "testl $0x80000000, %2
2339         setnz dsp_flag_c
2340         ror %%cl, %2
2341         cmpl $0, %2
2342         setz  dsp_flag_z
2343         sets  dsp_flag_n
2344         movl %%eax, %0
2345         "
2346         : "=m"(res)
2347         : "c"(shift), "a"(_Rn));
2348
2349         #endif
2350         
2351 #else
2352         __asm 
2353         {
2354                 mov ecx,shift
2355                 mov eax,_Rn
2356                 test eax,0x80000000
2357                 setnz [dsp_flag_c]
2358                 ror eax,cl
2359                 cmp eax,0
2360                 setz [dsp_flag_z]
2361                 sets [dsp_flag_n]
2362                 mov res,eax
2363         }
2364 #endif
2365         Rn=res;
2366 }
2367
2368 static void dsp_opcode_sha(void)
2369 {
2370         int32 sRm=(int32)Rm;
2371         uint32 _Rn=Rn;
2372
2373         if (sRm<0)
2374         {
2375                 uint32 shift=-sRm;
2376                 if (shift>=32) shift=32;
2377                 dsp_flag_c=(_Rn&0x80000000)>>31;
2378                 while (shift)
2379                 {
2380                         _Rn<<=1;
2381                         shift--;
2382                 }
2383         }
2384         else
2385         {
2386                 uint32 shift=sRm;
2387                 if (shift>=32) shift=32;
2388                 dsp_flag_c=_Rn&0x1;
2389                 while (shift)
2390                 {
2391                         _Rn=((int32)_Rn)>>1;
2392                         shift--;
2393                 }
2394         }
2395         Rn=_Rn;
2396         set_flag_z(_Rn);
2397         set_flag_n(_Rn);
2398 }
2399
2400 static void dsp_opcode_sharq(void)
2401 {
2402         uint32 shift=dsp_convert_zero[imm_1];
2403         uint32 _Rn=Rn;
2404
2405         dsp_flag_c  = (_Rn & 0x1);
2406         while (shift)
2407         {
2408                 _Rn=((int32)_Rn)>>1;
2409                 shift--;
2410         }
2411         Rn=_Rn;
2412         set_flag_z(_Rn);
2413         set_flag_n(_Rn);
2414 }
2415
2416 static void dsp_opcode_sh(void)
2417 {
2418         int32 sRm=(int32)Rm;
2419         uint32 _Rn=Rn;
2420
2421         if (sRm<0)
2422         {
2423                 uint32 shift=(-sRm);
2424                 if (shift>=32) shift=32;
2425                 dsp_flag_c=(_Rn&0x80000000)>>31;
2426                 while (shift)
2427                 {
2428                         _Rn<<=1;
2429                         shift--;
2430                 }
2431         }
2432         else
2433         {
2434                 uint32 shift=sRm;
2435                 if (shift>=32) shift=32;
2436                 dsp_flag_c=_Rn&0x1;
2437                 while (shift)
2438                 {
2439                         _Rn>>=1;
2440                         shift--;
2441                 }
2442         }
2443         Rn=_Rn;
2444         set_flag_z(_Rn);
2445         set_flag_n(_Rn);
2446 }
2447
2448 #define CLR_ZN  { dsp_flag_n=0; dsp_flag_z=0; };
2449 #define CLR_ZNC { dsp_flag_c=0; dsp_flag_n=0; dsp_flag_z=0; };
2450 #define SET_Z(r)                        (dsp_flag_z= ((r) == 0))
2451 #define SET_C_ADD(a,b)          (dsp_flag_c= ((UINT32)(b) > (UINT32)(~(a))) << 1)
2452 #define SET_C_SUB(a,b)          (dsp_flag_c= ((UINT32)(b) > (UINT32)(a)) << 1)
2453 #define SET_N(r)                        (dsp_flag_n= (((UINT32)(r) >> 29) & 4))
2454 #define SET_ZN(r)                       SET_N(r); SET_Z(r)
2455 #define SET_ZNC_ADD(a,b,r)      SET_N(r); SET_Z(r); SET_C_ADD(a,b)
2456 #define SET_ZNC_SUB(a,b,r)      SET_N(r); SET_Z(r); SET_C_SUB(a,b)
2457
2458 void dsp_opcode_addqmod(void)   
2459 {
2460         UINT32 r1 = dsp_convert_zero[imm_1];
2461         UINT32 r2 = Rn;
2462         UINT32 res = r2 + r1;
2463         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2464         Rn = res;
2465         CLR_ZNC; SET_ZNC_ADD(r2,r1,res);
2466 }
2467 void dsp_opcode_subqmod(void)   
2468 {
2469         UINT32 r1 = dsp_convert_zero[imm_1];
2470         UINT32 r2 = Rn;
2471         UINT32 res = r2 - r1;
2472         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2473         Rn = res;
2474         
2475         SET_ZNC_SUB(r2,r1,res);
2476 }
2477 void dsp_opcode_mirror(void)    
2478 {
2479         UINT32 r1 = Rn;
2480         UINT32 res = (mirror_table[r1 & 0xffff] << 16) | mirror_table[r1 >> 16];
2481         Rn = res;
2482         CLR_ZN; SET_ZN(res);
2483 }
2484 void dsp_opcode_sat32s(void)            
2485 {
2486         INT32 r2 = (UINT32)Rn;
2487         INT32 temp = dsp_acc >> 32;
2488         UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7fffffff : r2;
2489         Rn = res;
2490         CLR_ZN; SET_ZN(res);
2491 }
2492 void dsp_opcode_sat16s(void)            
2493 {
2494         INT32 r2 = Rn;
2495         UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
2496         Rn = res;
2497         CLR_ZN; SET_ZN(res);
2498 }