]> Shamusworld >> Repos - virtualjaguar/blob - src/dsp.cpp
Virtual Jaguar 1.0.4 update (Shamus)
[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 void dsp_check_if_i2s_interrupt_needed(void)
637 {
638         static uint32 count=8;
639
640         int mask;
641         count--;
642         if (count>0)
643                 return;
644
645         count=4;
646         // already in an interrupt handler ?
647         if (dsp_flags & 0x8) 
648                 return;
649
650         // get the interrupt mask 
651         mask = (dsp_flags >> 4) & 0x1f;
652         mask |= (dsp_flags >> 11) & 0x20;
653
654         if (mask & 0x02)
655         {
656                 dsp_set_irq_line(1,1);
657         }
658 }
659
660 void dsp_check_irqs(void)
661 {
662         int bits, mask, which = 0;
663
664         if (dsp_flags & 0x8) 
665                 return;
666
667         // get the active interrupt bits 
668         bits = (dsp_control >> 6) & 0x1f;
669         bits |= (dsp_control >> 10) & 0x20;
670
671         // get the interrupt mask 
672         mask = (dsp_flags >> 4) & 0x1f;
673         mask |= (dsp_flags >> 11) & 0x20;
674
675 //      fprintf(log_get(),"dsp: bits=%.2x mask=%.2x\n",bits,mask);
676         // bail if nothing is available
677         bits &= mask;
678
679         if (!bits)
680                 return;
681
682         // determine which interrupt 
683         if (bits & 0x01) which = 0;
684         if (bits & 0x02) which = 1;
685         if (bits & 0x04) which = 2;
686         if (bits & 0x08) which = 3;
687         if (bits & 0x10) which = 4;
688         if (bits & 0x20) which = 5;
689
690 //      fprintf(log_get(),"dsp: generating interrupt %i\n",which);
691
692         dsp_flags |= 0x08;
693         dsp_update_register_banks();
694
695         // subqt  #4,r31                ; pre-decrement stack pointer 
696         // move  pc,r30                 ; address of interrupted code 
697         // store  r30,(r31)     ; store return address
698         dsp_reg[31] -= 4;
699         dsp_reg[30]=dsp_pc;
700         dsp_long_write(dsp_reg[31], dsp_pc - 2);
701
702         // movei  #service_address,r30  ; pointer to ISR entry 
703         // jump  (r30)                                  ; jump to ISR 
704         // nop
705         dsp_pc = DSP_WORK_RAM_BASE;
706         dsp_pc += which * 0x10;
707         dsp_reg[30]=dsp_pc;
708 }
709
710 void dsp_set_irq_line(int irqline, int state)
711 {
712         int mask = 0x40 << irqline;
713         dsp_control &= ~mask;
714         if (state)
715         {
716                 dsp_control |= mask;
717                 dsp_check_irqs();
718         }
719 }
720
721 void dsp_init(void)
722 {
723         memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
724         memory_malloc_secure((void **)&dsp_reg, 32*sizeof(int32), "DSP bank 0 regs");
725         memory_malloc_secure((void **)&dsp_alternate_reg, 32*sizeof(int32), "DSP bank 1 regs");
726
727         dsp_build_branch_condition_table();
728         dsp_reset();
729 }
730
731 void dsp_reset(void)
732 {
733         dsp_pc                            = 0x00f1b000;
734         dsp_acc                           = 0x00000000;
735         dsp_remain                        = 0x00000000;
736         dsp_modulo                        = 0xFFFFFFFF;
737         dsp_flags                         = 0x00040000;
738         dsp_matrix_control    = 0x00000000;
739         dsp_pointer_to_matrix = 0x00000000;
740         dsp_data_organization = 0xffffffff;
741         dsp_control                       = 0x00012800;
742         dsp_div_control           = 0x00000000;
743         dsp_in_exec                       = 0;
744
745         for(int i=0; i<32; i++)
746         {
747                 dsp_reg[i]           = 0x00000000;
748                 dsp_alternate_reg[i] = 0x00000000;
749         }
750         
751         dsp_reg_bank_0 = dsp_reg;
752         dsp_reg_bank_1 = dsp_alternate_reg;
753 //      dsp_reg_bank_1 = dsp_reg;
754 //      dsp_reg_bank_0 = dsp_alternate_reg;
755
756         reset_flag_z();
757         reset_flag_n();
758         reset_flag_c();
759
760         dsp_alternate_flag_z = 0;
761         dsp_alternate_flag_n = 0;
762         dsp_alternate_flag_c = 0;
763
764         dsp_reset_stats();
765         memset(dsp_ram_8, 0xFF, 0x2000);
766 }
767
768 void dsp_done(void)
769 {
770         int i, j;
771         fprintf(log_get(), "DSP: Stopped at PC=%08X dsp_modulo=%08X(dsp %s running)\n", dsp_pc, dsp_modulo, dsp_running ? "was" : "wasn't");
772         fprintf(log_get(), "DSP: %sin interrupt handler\n", (dsp_flags & 0x8) ? "" : "not ");
773         int bits, mask;
774
775         // get the active interrupt bits 
776         bits = (dsp_control >> 6) & 0x1F;
777         bits |= (dsp_control >> 10) & 0x20;
778
779         // get the interrupt mask 
780         mask = (dsp_flags >> 4) & 0x1F;
781         mask |= (dsp_flags >> 11) & 0x20;
782
783         fprintf(log_get(), "DSP: bits=%08X mask=%08X\n", bits, mask);
784         fprintf(log_get(), "\nRegisters bank 0\n");
785         for(int j=0; j<8; j++)
786         {
787                 fprintf(log_get(), "\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
788                                                   (j << 2) + 0, dsp_reg[(j << 2) + 0],
789                                                   (j << 2) + 1, dsp_reg[(j << 2) + 1],
790                                                   (j << 2) + 2, dsp_reg[(j << 2) + 2],
791                                                   (j << 2) + 3, dsp_reg[(j << 2) + 3]);
792         }
793 //      fprintf(log_get(),"registers bank 1\n");
794 //      for (j=0;j<8;j++)
795 //      {
796 //              fprintf(log_get(),"\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
797 //                                                (j<<2)+0,dsp_alternate_reg[(j<<2)+0],
798 //                                                (j<<2)+1,dsp_alternate_reg[(j<<2)+1],
799 //                                                (j<<2)+2,dsp_alternate_reg[(j<<2)+2],
800 //                                                (j<<2)+3,dsp_alternate_reg[(j<<2)+3]);
801 //
802 //      }
803         static char buffer[512];
804         j = DSP_WORK_RAM_BASE;
805 //      for(int i=0; i<4096; i++)
806         while (j <= 0xF1BFFF)
807         {
808                 uint32 oldj = j;
809                 j += dasmjag(JAGUAR_DSP, buffer, j);
810                 fprintf(log_get(), "\t%08X: %s\n", oldj, buffer);
811         }//*/
812
813         fprintf(log_get(),"dsp opcodes use:\n");
814         for (i=0;i<64;i++)
815         {
816                 if (dsp_opcode_use[i])
817                         fprintf(log_get(),"\t%s %i\n",dsp_opcode_str[i],dsp_opcode_use[i]);
818         }//*/
819
820         memory_free(dsp_ram_8);
821 }
822
823 void dsp_exec(int32 cycles)
824 {
825         if ((cycles!=1)&&(jaguar_mainRom_crc32==0xba74c3ed))
826                 dsp_check_if_i2s_interrupt_needed();
827
828 #ifdef DSP_SINGLE_STEPPING
829         if (dsp_control&0x18)
830         {
831                 cycles=1;
832                 dsp_control&=~0x10;
833         }
834 #endif
835         dsp_check_irqs();
836         dsp_releaseTimeSlice_flag=0;
837         dsp_in_exec++;
838         while ((cycles>0)&&(dsp_running))
839         {
840                 dsp_flag_c=(dsp_flag_c?1:0);
841                 dsp_flag_z=(dsp_flag_z?1:0);
842                 dsp_flag_n=(dsp_flag_n?1:0);
843
844
845 /*
846                 if (dsp_pc==0x00f1b02c)
847                 {
848                         if (dsp_fp)
849                         {
850                                 fclose(dsp_fp);
851                                 exit(0);
852                         }
853                 }
854                 else 
855                 if (dsp_pc==0x00f1b032)
856                 {
857                         dsp_fp=fopen("c:\\bad.log","wrt");
858                         if (dsp_fp==NULL)
859                                 MessageBox(NULL,"Cannot open dsp log","",MB_OK);
860                 }
861                 if (dsp_fp)
862                 {
863                         fprintf(dsp_fp,"0x%.8x\n",dsp_pc);
864                 }
865                 
866 //              if (dsp_pc==0x00f1b130)
867 //                      dsp_load_bin_at("SCHRIFT.DAT",0x120000);
868 */              
869                 uint16 opcode=dsp_word_read(dsp_pc);
870                 dsp_opcode_first_parameter=(opcode&0x3e0)>>5;
871                 dsp_opcode_second_parameter=(opcode&0x1f);
872                 dsp_pc+=2;
873                 dsp_opcode[opcode>>10]();
874                 dsp_opcode_use[opcode>>10]++;
875                 cycles-=dsp_opcode_cycles[opcode>>10];
876         }
877         dsp_in_exec--;
878 }
879
880 static void dsp_opcode_jump(void)
881 {
882         uint32 delayed_pc = Rm;
883         uint32 jaguar_flags;
884
885         // normalize flags
886         dsp_flag_c=dsp_flag_c?1:0;
887         dsp_flag_z=dsp_flag_z?1:0;
888         dsp_flag_n=dsp_flag_n?1:0;
889
890         jaguar_flags=(dsp_flag_n<<2)|(dsp_flag_c<<1)|dsp_flag_z;
891
892         if (branch_condition(imm_2))
893         {
894                 dsp_exec(1);
895                 dsp_pc=delayed_pc;
896         }
897 }
898
899 static void dsp_opcode_jr(void)
900 {
901         int32 offset=(imm_1&0x10) ? (0xFFFFFFF0|imm_1) : imm_1;
902
903         int32 delayed_pc = dsp_pc + (offset * 2);
904         uint32 jaguar_flags;
905
906         // normalize flags
907         dsp_flag_c=dsp_flag_c?1:0;
908         dsp_flag_z=dsp_flag_z?1:0;
909         dsp_flag_n=dsp_flag_n?1:0;
910         
911         jaguar_flags=(dsp_flag_n<<2)|(dsp_flag_c<<1)|dsp_flag_z;
912
913         if (branch_condition(imm_2))
914         {
915                 dsp_exec(1);
916                 dsp_pc=delayed_pc;
917         }
918 }
919
920 static void dsp_opcode_add(void)
921 {
922         uint32 _Rm=Rm;
923         uint32 _Rn=Rn;
924         uint32 res;
925 #ifdef __PORT__
926
927     /*
928        GCC on WIN32 (more importantly mingw) doesn't know the declared
929        variables in asm until we put a _ before it.
930        
931        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
932     */
933     #ifdef __GCCWIN32__
934         asm(
935         "addl %1, %2
936     setc  _dsp_flag_c
937         setz  _dsp_flag_z
938         sets  _dsp_flag_n
939         movl %%eax, %0
940         "
941         : "=m"(res)
942         : "d"(_Rm), "a"(_Rn));
943         
944         #else
945         asm(
946         "addl %1, %2
947         setc  dsp_flag_c
948         setz  dsp_flag_z
949         sets  dsp_flag_n
950         movl %%eax, %0
951         "
952         : "=m"(res)
953         : "d"(_Rm), "a"(_Rn));
954         #endif
955         
956 #else
957         __asm 
958         {
959                 mov   edx,_Rm
960                 mov   eax,_Rn
961                 add   eax,edx
962                 setc  [dsp_flag_c]
963                 setz  [dsp_flag_z]
964                 sets  [dsp_flag_n]
965                 mov       res,eax
966         };
967 #endif
968         Rn=res;
969 }
970
971 static void dsp_opcode_addc(void)
972 {
973         uint32 _Rm=Rm;
974         uint32 _Rn=Rn;
975         uint32 res;
976 #ifdef __PORT__
977
978     /*
979        GCC on WIN32 (more importantly mingw) doesn't know the declared
980        variables in asm until we put a _ before it.
981        
982        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
983        We use __GCCWIN32__ for this "bug".
984     */
985
986     #ifdef __GCCWIN32__ 
987         
988     asm(
989         "addl %1, %2
990         cmp       $0, _dsp_flag_c
991         clc
992         jz 1f
993         stc
994         1:
995         adc %1, %2
996         setc  _dsp_flag_c
997         setz  _dsp_flag_z
998         sets  _dsp_flag_n
999         movl %%eax, %0
1000         "
1001         : "=m"(res)
1002         : "d"(_Rm), "a"(_Rn));
1003         #else
1004
1005     asm(
1006         "addl %1, %2
1007         cmp       $0, dsp_flag_c
1008         clc
1009         jz 1f
1010         stc
1011         1:
1012         adc %1, %2
1013         setc  dsp_flag_c
1014         setz  dsp_flag_z
1015         sets  dsp_flag_n
1016         movl %%eax, %0
1017         "
1018         : "=m"(res)
1019         : "d"(_Rm), "a"(_Rn));
1020
1021     #endif      
1022         
1023 #else
1024         __asm 
1025         {
1026                 mov   edx,_Rm
1027                 mov   eax,_Rn
1028                 cmp       [dsp_flag_c],0
1029                 clc
1030                 jz        dsp_opcode_addc_no_carry
1031                 stc
1032 dsp_opcode_addc_no_carry:
1033                 adc   eax,edx
1034                 setc  [dsp_flag_c]
1035                 setz  [dsp_flag_z]
1036                 sets  [dsp_flag_n]
1037                 mov       res,eax
1038         };
1039 #endif
1040         Rn=res;
1041 }
1042
1043 static void dsp_opcode_addq(void)
1044 {
1045         uint32 _Rn=Rn;
1046         uint32 _Rm=dsp_convert_zero[imm_1];
1047         uint32 res;
1048         
1049 #ifdef __PORT__
1050
1051     /*
1052        GCC on WIN32 (more importantly mingw) doesn't know the declared
1053        variables in asm until we put a _ before it.
1054        
1055        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1056     */
1057
1058     #ifdef __GCCWIN32__
1059     
1060         asm(
1061         "addl %1, %2
1062         setc  _dsp_flag_c
1063         setz  _dsp_flag_z
1064         sets  _dsp_flag_n
1065         movl %%eax, %0
1066         "
1067         : "=m"(res)
1068         : "d"(_Rm), "a"(_Rn));
1069         
1070         #else
1071         
1072         asm(
1073         "addl %1, %2
1074         setc  dsp_flag_c
1075         setz  dsp_flag_z
1076         sets  dsp_flag_n
1077         movl %%eax, %0
1078         "
1079         : "=m"(res)
1080         : "d"(_Rm), "a"(_Rn));
1081
1082         #endif
1083         
1084 #else
1085         __asm 
1086         {
1087                 mov   edx,_Rm
1088                 mov   eax,_Rn
1089                 add   eax,edx
1090                 setc  [dsp_flag_c]
1091                 setz  [dsp_flag_z]
1092                 sets  [dsp_flag_n]
1093                 mov       res,eax
1094         };
1095 #endif
1096         Rn=res;
1097 }
1098
1099 static void dsp_opcode_sub(void)
1100 {
1101         uint32 _Rm=Rm;
1102         uint32 _Rn=Rn;
1103         uint32 res;
1104 #ifdef __PORT__
1105
1106     /*
1107        GCC on WIN32 (more importantly mingw) doesn't know the declared
1108        variables in asm until we put a _ before it.
1109        
1110        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1111     */
1112
1113     #ifdef __GCCWIN32__
1114     
1115         asm(
1116         "subl %1, %2
1117         setc  _dsp_flag_c
1118         setz  _dsp_flag_z
1119         sets  _dsp_flag_n
1120         movl %%eax, %0
1121         "
1122         : "=m"(res)
1123         : "d"(_Rm), "a"(_Rn));
1124         
1125         #else
1126
1127         asm(
1128         "subl %1, %2
1129         setc  dsp_flag_c
1130         setz  dsp_flag_z
1131         sets  dsp_flag_n
1132         movl %%eax, %0
1133         "
1134         : "=m"(res)
1135         : "d"(_Rm), "a"(_Rn));
1136
1137         #endif  
1138         
1139 #else
1140         __asm 
1141         {
1142                 mov   eax,_Rn
1143                 mov   edx,_Rm
1144                 sub   eax,edx
1145                 setc  [dsp_flag_c]
1146                 setz  [dsp_flag_z]
1147                 sets  [dsp_flag_n]
1148                 mov       res,eax
1149         };
1150 #endif
1151         Rn=res;
1152 }
1153
1154 static void dsp_opcode_subc(void)
1155 {
1156         uint32 _Rm=Rm;
1157         uint32 _Rn=Rn;
1158         uint32 res;
1159 #ifdef __PORT__
1160
1161     /*
1162        GCC on WIN32 (more importantly mingw) doesn't know the declared
1163        variables in asm until we put a _ before it.
1164        
1165        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1166     */
1167
1168     #ifdef __GCCWIN32__
1169
1170         asm(
1171         "addl %1, %2
1172         cmp       $0, _dsp_flag_c
1173         clc
1174         jz 1f
1175         stc
1176         1:
1177         sbb %1, %2
1178         setc  _dsp_flag_c
1179         setz  _dsp_flag_z
1180         sets  _dsp_flag_n
1181         movl %%eax, %0
1182         "
1183         : "=m"(res)
1184         : "d"(_Rm), "a"(_Rn));
1185         
1186         #else
1187
1188         asm(
1189         "addl %1, %2
1190         cmp       $0, dsp_flag_c
1191         clc
1192         jz 1f
1193         stc
1194         1:
1195         sbb %1, %2
1196         setc  dsp_flag_c
1197         setz  dsp_flag_z
1198         sets  dsp_flag_n
1199         movl %%eax, %0
1200         "
1201         : "=m"(res)
1202         : "d"(_Rm), "a"(_Rn));
1203
1204         #endif
1205         
1206 #else
1207         __asm 
1208         {
1209                 mov   edx,_Rm
1210                 mov   eax,_Rn
1211                 cmp       [dsp_flag_c],0
1212                 clc
1213                 jz        dsp_opcode_subc_no_carry
1214                 stc
1215 dsp_opcode_subc_no_carry:
1216                 sbb   eax,edx
1217                 setc  [dsp_flag_c]
1218                 setz  [dsp_flag_z]
1219                 sets  [dsp_flag_n]
1220                 mov       res,eax
1221         };
1222 #endif
1223         Rn=res;
1224 }
1225
1226 static void dsp_opcode_subq(void)
1227 {
1228         uint32 _Rm=dsp_convert_zero[imm_1];
1229         uint32 _Rn=Rn;
1230         uint32 res;
1231 #ifdef __PORT__
1232
1233     /*
1234        GCC on WIN32 (more importantly mingw) doesn't know the declared
1235        variables in asm until we put a _ before it.
1236        
1237        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1238     */
1239
1240     #ifdef __GCCWIN32__
1241
1242         asm(
1243         "subl %1, %2
1244         setc  _dsp_flag_c
1245         setz  _dsp_flag_z
1246         sets  _dsp_flag_n
1247         movl %%eax, %0
1248         "
1249         : "=m"(res)
1250         : "d"(_Rm), "a"(_Rn));
1251         
1252         #else
1253
1254         asm(
1255         "subl %1, %2
1256         setc  dsp_flag_c
1257         setz  dsp_flag_z
1258         sets  dsp_flag_n
1259         movl %%eax, %0
1260         "
1261         : "=m"(res)
1262         : "d"(_Rm), "a"(_Rn));
1263         
1264         #endif
1265 #else
1266         __asm 
1267         {
1268                 mov   eax,_Rn
1269                 mov   edx,_Rm
1270                 sub   eax,edx
1271                 setc  [dsp_flag_c]
1272                 setz  [dsp_flag_z]
1273                 sets  [dsp_flag_n]
1274                 mov       res,eax
1275         };
1276 #endif
1277         Rn=res;
1278 }
1279
1280 static void dsp_opcode_cmp(void)
1281 {
1282         uint32 _Rm=Rm;
1283         uint32 _Rn=Rn;
1284 #ifdef __PORT__
1285
1286     /*
1287        GCC on WIN32 (more importantly mingw) doesn't know the declared
1288        variables in asm until we put a _ before it.
1289        
1290        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1291     */
1292
1293     #ifdef __GCCWIN32__
1294
1295         asm(
1296         "cmpl %0, %1
1297         setc  _dsp_flag_c
1298         setz  _dsp_flag_z
1299         sets  _dsp_flag_n
1300         "
1301         :
1302         : "d"(_Rm), "a"(_Rn));
1303         
1304         #else
1305         
1306         asm(
1307         "cmpl %0, %1
1308         setc  dsp_flag_c
1309         setz  dsp_flag_z
1310         sets  dsp_flag_n
1311         "
1312         :
1313         : "d"(_Rm), "a"(_Rn));
1314         
1315         #endif
1316         
1317 #else
1318         __asm 
1319         {
1320                 mov   eax,_Rn
1321                 mov   edx,_Rm
1322                 cmp   eax,edx
1323                 setc  [dsp_flag_c]
1324                 setz  [dsp_flag_z]
1325                 sets  [dsp_flag_n]
1326         };
1327 #endif
1328 }
1329
1330 static void dsp_opcode_cmpq(void)
1331 {
1332         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};
1333         int32 _Rm=sqtable[imm_1&0x1f];
1334         uint32 _Rn=Rn;
1335 #ifdef __PORT__
1336
1337     /*
1338        GCC on WIN32 (more importantly mingw) doesn't know the declared
1339        variables in asm until we put a _ before it.
1340        
1341        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1342     */
1343
1344     #ifdef __GCCWIN32__
1345
1346         asm(
1347         "cmpl %0, %1
1348         setc  _dsp_flag_c
1349         setz  _dsp_flag_z
1350         sets  _dsp_flag_n
1351         "
1352         :
1353         : "d"(_Rm), "a"(_Rn));
1354         
1355         #else
1356
1357         asm(
1358         "cmpl %0, %1
1359         setc  dsp_flag_c
1360         setz  dsp_flag_z
1361         sets  dsp_flag_n
1362         "
1363         :
1364         : "d"(_Rm), "a"(_Rn));
1365         
1366         #endif
1367         
1368 #else
1369         __asm 
1370         {
1371                 mov   eax,_Rn
1372                 mov   edx,_Rm
1373                 cmp   eax,edx
1374                 setc  [dsp_flag_c]
1375                 setz  [dsp_flag_z]
1376                 sets  [dsp_flag_n]
1377         };
1378 #endif
1379 }
1380
1381 static void dsp_opcode_and(void)
1382 {
1383         uint32 _Rm=Rm;
1384         uint32 _Rn=Rn;
1385         uint32 res;
1386 #ifdef __PORT__
1387
1388     /*
1389        GCC on WIN32 (more importantly mingw) doesn't know the declared
1390        variables in asm until we put a _ before it.
1391        
1392        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1393     */
1394
1395     #ifdef __GCCWIN32__
1396
1397         asm(
1398         "andl %1, %2
1399         setz  _dsp_flag_z
1400         sets  _dsp_flag_n
1401         movl %%eax, %0
1402         "
1403         : "=m"(res)
1404         : "d"(_Rm), "a"(_Rn));
1405         
1406         #else
1407
1408         asm(
1409         "andl %1, %2
1410         setz  dsp_flag_z
1411         sets  dsp_flag_n
1412         movl %%eax, %0
1413         "
1414         : "=m"(res)
1415         : "d"(_Rm), "a"(_Rn));
1416         
1417         #endif
1418         
1419 #else
1420         __asm 
1421         {
1422                 mov   eax,_Rn
1423                 mov   edx,_Rm
1424                 and   eax,edx
1425                 setz  [dsp_flag_z]
1426                 sets  [dsp_flag_n]
1427                 mov   res,eax
1428         };
1429 #endif
1430         Rn=res;
1431 }
1432
1433 static void dsp_opcode_or(void)
1434 {
1435         uint32 _Rm=Rm;
1436         uint32 _Rn=Rn;
1437         uint32 res;
1438 #ifdef __PORT__
1439
1440     /*
1441        GCC on WIN32 (more importantly mingw) doesn't know the declared
1442        variables in asm until we put a _ before it.
1443        
1444        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1445     */
1446
1447     #ifdef __GCCWIN32__
1448
1449         asm(
1450         "orl %1, %2
1451         setz  _dsp_flag_z
1452         sets  _dsp_flag_n
1453         movl %%eax, %0
1454         "
1455         : "=m"(res)
1456         : "d"(_Rm), "a"(_Rn));
1457         
1458         #else
1459         
1460         asm(
1461         "orl %1, %2
1462         setz  dsp_flag_z
1463         sets  dsp_flag_n
1464         movl %%eax, %0
1465         "
1466         : "=m"(res)
1467         : "d"(_Rm), "a"(_Rn));
1468         
1469         #endif
1470
1471 #else
1472         __asm 
1473         {
1474                 mov   eax,_Rn
1475                 mov   edx,_Rm
1476                 or    eax,edx
1477                 setz  [dsp_flag_z]
1478                 sets  [dsp_flag_n]
1479                 mov   res,eax
1480         };
1481 #endif
1482         Rn=res;
1483 }
1484
1485 static void dsp_opcode_xor(void)
1486 {
1487         uint32 _Rm=Rm;
1488         uint32 _Rn=Rn;
1489         uint32 res;
1490 #ifdef __PORT__
1491
1492     /*
1493        GCC on WIN32 (more importantly mingw) doesn't know the declared
1494        variables in asm until we put a _ before it.
1495        
1496        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1497     */
1498
1499     #ifdef __GCCWIN32__
1500
1501         asm(
1502         "xorl %1, %2
1503         setz  _dsp_flag_z
1504         sets  _dsp_flag_n
1505         movl %%eax, %0
1506         "
1507         : "=m"(res)
1508         : "d"(_Rm), "a"(_Rn));
1509         
1510         #else
1511         
1512         asm(
1513         "xorl %1, %2
1514         setz  dsp_flag_z
1515         sets  dsp_flag_n
1516         movl %%eax, %0
1517         "
1518         : "=m"(res)
1519         : "d"(_Rm), "a"(_Rn));
1520         
1521         #endif
1522         
1523 #else
1524         __asm 
1525         {
1526                 mov   eax,_Rn
1527                 mov   edx,_Rm
1528                 xor   eax,edx
1529                 setz  [dsp_flag_z]
1530                 sets  [dsp_flag_n]
1531                 mov   res,eax
1532         };
1533 #endif
1534         Rn=res;
1535 }
1536
1537 static void dsp_opcode_not(void)
1538 {
1539         uint32 _Rn=Rn;
1540         uint32 res;
1541 #ifdef __PORT__
1542
1543     /*
1544        GCC on WIN32 (more importantly mingw) doesn't know the declared
1545        variables in asm until we put a _ before it.
1546        
1547        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1548     */
1549
1550     #ifdef __GCCWIN32__
1551
1552         asm(
1553         "notl %1
1554         setz  _dsp_flag_z
1555         sets  _dsp_flag_n
1556         movl %%eax, %0
1557         "
1558         : "=m"(res)
1559         : "a"(_Rn));
1560         
1561         #else
1562         
1563         asm(
1564         "notl %1
1565         setz  dsp_flag_z
1566         sets  dsp_flag_n
1567         movl %%eax, %0
1568         "
1569         : "=m"(res)
1570         : "a"(_Rn));
1571         
1572         #endif
1573         
1574 #else
1575         __asm 
1576         {
1577                 mov   eax,_Rn
1578                 not   eax
1579                 setz  [dsp_flag_z]
1580                 sets  [dsp_flag_n]
1581                 mov   res,eax
1582         };
1583 #endif
1584         Rn=res;
1585 }
1586
1587 static void dsp_opcode_move_pc(void)
1588 {
1589         Rn = dsp_pc-2; 
1590 }
1591
1592 static void dsp_opcode_sat8(void)
1593 {
1594         int32 _Rn=(int32)Rn;
1595
1596         uint32 res= Rn = (_Rn<0) ? 0 : (_Rn > 0xff ? 0xff : _Rn);
1597         set_flag_z(res);
1598         reset_flag_n();
1599 }
1600
1601 static void dsp_opcode_sat16(void)
1602 {
1603         uint32 _Rn=Rn;
1604         uint32 res= Rn = (_Rn&0x80000000) ? 0 : (_Rn > 0xFFFF ? 0xFFFF : _Rn);
1605         set_flag_z(res);
1606         reset_flag_n();
1607 }
1608
1609 static void dsp_opcode_sat24(void)
1610 {
1611         uint32 _Rn=Rn;
1612
1613         uint32 res= Rn = (_Rn&0x80000000) ? 0 : (_Rn > 0xFFFFFF ? 0xFFFFFF : _Rn);
1614         set_flag_z(res);
1615         reset_flag_n();
1616 }
1617
1618 static void dsp_opcode_store_r14_indexed(void)
1619 {
1620         dsp_long_write( dsp_reg[14] + (dsp_convert_zero[imm_1] << 2),Rn);
1621 }
1622
1623 static void dsp_opcode_store_r15_indexed(void)
1624 {
1625         dsp_long_write( dsp_reg[15] + (dsp_convert_zero[imm_1] << 2),Rn);
1626 }
1627
1628 static void dsp_opcode_load_r14_ri(void)
1629 {
1630         Rn=dsp_long_read(dsp_reg[14] + Rm);
1631 }
1632
1633 static void dsp_opcode_load_r15_ri(void)
1634 {
1635         Rn=dsp_long_read(dsp_reg[15] + Rm);
1636 }
1637
1638 static void dsp_opcode_store_r14_ri(void)
1639 {
1640         dsp_long_write(dsp_reg[14] + Rm,Rn);
1641 }
1642
1643 static void dsp_opcode_store_r15_ri(void)
1644 {
1645         dsp_long_write(dsp_reg[15] + Rm,Rn);
1646 }
1647
1648 static void dsp_opcode_nop(void)
1649 {
1650 }
1651
1652 static void dsp_opcode_pack(void)
1653 {
1654         uint32 _Rn=Rn;
1655
1656         if (Rm==0)
1657         {
1658                 Rn =((_Rn & 0x03C00000) >> 10) |
1659                         ((_Rn & 0x0001E000) >> 5)  |
1660                         ((_Rn & 0x000000FF));
1661         }
1662         else
1663         {
1664                 Rn =((_Rn & 0x0000F000) << 10) |
1665                         ((_Rn & 0x00000F00) << 5)  |
1666                         ((_Rn & 0x000000FF));
1667         }
1668         reset_flag_z();
1669         reset_flag_n();
1670         set_flag_z(Rn);
1671         set_flag_n(Rn);
1672 }
1673
1674 static void dsp_opcode_storeb(void)
1675 {
1676         if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1677                 dsp_long_write(Rm,Rn&0xff);
1678         else
1679                 jaguar_byte_write(Rm,Rn);
1680 }
1681
1682 static void dsp_opcode_storew(void)
1683 {
1684         if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1685                 dsp_long_write(Rm,Rn&0xffff);
1686         else
1687                 jaguar_word_write(Rm,Rn);
1688 }
1689
1690 static void dsp_opcode_store(void)
1691 {
1692         dsp_long_write(Rm,Rn);
1693 }
1694
1695 static void dsp_opcode_loadb(void)
1696 {
1697         if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1698                 Rn=dsp_long_read(Rm)&0xff;
1699         else
1700                 Rn=jaguar_byte_read(Rm);
1701 }
1702
1703 static void dsp_opcode_loadw(void)
1704 {
1705         if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1706                 Rn=dsp_long_read(Rm)&0xffff;
1707         else
1708                 Rn=jaguar_word_read(Rm);
1709 }
1710
1711 static void dsp_opcode_load(void)
1712 {
1713         Rn = dsp_long_read(Rm);
1714 }
1715
1716 static void dsp_opcode_load_r14_indexed(void)
1717 {
1718         Rn = dsp_long_read( dsp_reg[14] + (dsp_convert_zero[imm_1] << 2));
1719 }
1720
1721 static void dsp_opcode_load_r15_indexed(void)
1722 {
1723         Rn = dsp_long_read( dsp_reg[15] + (dsp_convert_zero[imm_1] << 2));
1724 }
1725
1726 static void dsp_opcode_movei(void)
1727 {
1728         Rn = ((uint32)dsp_word_read(dsp_pc)) + (((uint32)dsp_word_read(dsp_pc+2))<<16);
1729         dsp_pc+=4;
1730 }
1731
1732 static void dsp_opcode_moveta(void)
1733 {
1734         alternate_Rn = Rm;
1735 }
1736
1737 static void dsp_opcode_movefa(void)
1738 {
1739         Rn = alternate_Rm;
1740 }
1741
1742 static void dsp_opcode_move(void)
1743 {
1744         Rn = Rm;
1745 }
1746
1747 static void dsp_opcode_moveq(void)
1748 {
1749         Rn = imm_1;    
1750 }
1751
1752 static void dsp_opcode_resmac(void)
1753 {
1754         Rn = dsp_acc;
1755 }
1756
1757 static void dsp_opcode_imult(void)
1758 {
1759         uint32 res=Rn=((int16)Rn)*((int16)Rm);
1760         set_flag_z(res);
1761         set_flag_n(res);
1762 }
1763
1764 static void dsp_opcode_mult(void)
1765 {
1766         uint32 res=Rn =  ((uint16)Rm) * ((uint16)Rn);
1767         set_flag_z(res);
1768         set_flag_n(res);
1769 }
1770
1771 static void dsp_opcode_bclr(void)
1772 {
1773         uint32 _Rm=imm_1;
1774         uint32 _Rn=Rn;
1775         uint32 res;
1776 #ifdef __PORT__
1777
1778     /*
1779        GCC on WIN32 (more importantly mingw) doesn't know the declared
1780        variables in asm until we put a _ before it.
1781        
1782        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1783     */
1784
1785     #ifdef __GCCWIN32__
1786
1787         asm(
1788         "btrl %1, %2
1789         cmpl $0, %2
1790         setz  _dsp_flag_z
1791         sets  _dsp_flag_n
1792         movl %%eax, %0
1793         "
1794         : "=m"(res)
1795         : "c"(_Rm), "a"(_Rn));
1796         
1797         #else
1798
1799         asm(
1800         "btrl %1, %2
1801         cmpl $0, %2
1802         setz  dsp_flag_z
1803         sets  dsp_flag_n
1804         movl %%eax, %0
1805         "
1806         : "=m"(res)
1807         : "c"(_Rm), "a"(_Rn));
1808         
1809         #endif
1810         
1811         
1812 #else
1813         __asm 
1814         {
1815                 mov   eax,_Rn
1816                 mov   ecx,_Rm
1817                 btr       eax,ecx
1818                 cmp   eax,0
1819                 setz  [dsp_flag_z]
1820                 sets  [dsp_flag_n]
1821                 mov   res,eax
1822         };
1823 #endif
1824         Rn=res;
1825 }
1826
1827 static void dsp_opcode_btst(void)
1828 {
1829         uint32 _Rm=imm_1;
1830         uint32 _Rn=Rn;
1831 #ifdef __PORT__
1832
1833     /*
1834        GCC on WIN32 (more importantly mingw) doesn't know the declared
1835        variables in asm until we put a _ before it.
1836        
1837        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1838     */
1839
1840     #ifdef __GCCWIN32__
1841
1842         asm(
1843         "bt %0, %1
1844         setnc _dsp_flag_z
1845         "
1846         :
1847         : "c"(_Rm), "a"(_Rn));
1848         
1849         #else
1850         
1851         asm(
1852         "bt %0, %1
1853         setnc dsp_flag_z
1854         "
1855         :
1856         : "c"(_Rm), "a"(_Rn));
1857         
1858         #endif
1859         
1860 #else
1861         __asm 
1862         {
1863                 mov   eax,_Rn
1864                 mov   ecx,_Rm
1865                 bt        eax,ecx
1866                 setnc [dsp_flag_z]
1867         };
1868 #endif
1869 }
1870
1871 static void dsp_opcode_bset(void)
1872 {
1873         uint32 _Rm=imm_1;
1874         uint32 _Rn=Rn;
1875         uint32 res;
1876 #ifdef __PORT__
1877
1878     /*
1879        GCC on WIN32 (more importantly mingw) doesn't know the declared
1880        variables in asm until we put a _ before it.
1881        
1882        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1883     */
1884
1885     #ifdef __GCCWIN32__
1886
1887         asm(
1888         "btsl %1, %2
1889         cmpl $0, %2
1890         setz  _dsp_flag_z
1891         sets  _dsp_flag_n
1892         movl %%eax, %0
1893         "
1894         : "=m"(res)
1895         : "c"(_Rm), "a"(_Rn));
1896         
1897         #else
1898         
1899         asm(
1900         "btsl %1, %2
1901         cmpl $0, %2
1902         setz  dsp_flag_z
1903         sets  dsp_flag_n
1904         movl %%eax, %0
1905         "
1906         : "=m"(res)
1907         : "c"(_Rm), "a"(_Rn));
1908         
1909         #endif
1910         
1911 #else
1912         __asm 
1913         {
1914                 mov   eax,_Rn
1915                 mov   ecx,_Rm
1916                 bts       eax,ecx
1917                 cmp   eax,0
1918                 setz  [dsp_flag_z]
1919                 sets  [dsp_flag_n]
1920                 mov   res,eax
1921         };
1922 #endif
1923         Rn=res;
1924 }
1925
1926 static void dsp_opcode_subqt(void)
1927 {
1928         Rn -= dsp_convert_zero[imm_1];
1929 }
1930
1931 static void dsp_opcode_addqt(void)
1932 {
1933         Rn += dsp_convert_zero[imm_1];
1934 }
1935
1936 static void dsp_opcode_imacn(void)
1937 {
1938         uint32 res=((int16)Rm) * ((int16)(Rn));
1939         dsp_acc += res;
1940
1941
1942 static void dsp_opcode_mtoi(void)
1943 {
1944         uint32 _Rm=Rm;
1945         uint32 res=Rn=(((INT32)_Rm >> 8) & 0xff800000) | (_Rm & 0x007fffff);
1946         set_flag_z(res);
1947         set_flag_n(res);
1948 }
1949
1950 static void dsp_opcode_normi(void)
1951 {
1952         uint32 _Rm = Rm;
1953         uint32 res = 0;
1954
1955         if (_Rm)
1956         {
1957                 while ((_Rm & 0xffc00000) == 0)
1958                 {
1959                         _Rm <<= 1;
1960                         res--;
1961                 }
1962                 while ((_Rm & 0xff800000) != 0)
1963                 {
1964                         _Rm >>= 1;
1965                         res++;
1966                 }
1967         }
1968         Rn = res;
1969         set_flag_z(res);
1970         set_flag_n(res);
1971 }
1972
1973 static void dsp_opcode_mmult(void)
1974 {
1975         int count       = dsp_matrix_control&0x0f;
1976         uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
1977         int64 accum = 0;
1978         uint32 res;
1979
1980         if (!(dsp_matrix_control & 0x10))
1981         {
1982                 for (int i = 0; i < count; i++)
1983                 { 
1984                         int16 a;
1985                         if (i&0x01)
1986                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1987                         else
1988                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1989                         int16 b=((int16)dsp_word_read(addr+2));
1990                         accum += a*b;
1991                         addr += 4;
1992                 }
1993         }
1994         else
1995         {
1996                 for (int i = 0; i < count; i++)
1997                 {
1998                         int16 a;
1999                         if (i&0x01)
2000                                 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
2001                         else
2002                                 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
2003                         int16 b=((int16)dsp_word_read(addr+2));
2004                         accum += a*b;
2005                         addr += 4 * count;
2006                 }
2007         }
2008         Rn = res = (int32)accum;
2009         // carry flag to do
2010         set_flag_z(res);
2011         set_flag_n(res);
2012 }
2013
2014 static void dsp_opcode_abs(void)
2015 {
2016         uint32 _Rn=Rn;
2017         uint32 res;
2018         
2019         if (_Rn==0x80000000)
2020         {
2021                 set_flag_n(1);
2022         }
2023         else
2024         {
2025                 dsp_flag_c  = ((_Rn&0x80000000)>>31);
2026                 res= Rn =  (_Rn & 0x80000000) ? -_Rn : _Rn;
2027                 reset_flag_n();
2028                 set_flag_z(res);
2029         }
2030 }
2031
2032 static void dsp_opcode_div(void)
2033 {
2034         uint32 _Rm=Rm;
2035         uint32 _Rn=Rn;
2036
2037         if (_Rm)
2038         {
2039                 if (dsp_div_control & 1)
2040                 {
2041                         dsp_remain = (((uint64)_Rn) << 16) % _Rm;
2042                         if (dsp_remain&0x80000000)
2043                                 dsp_remain-=_Rm;
2044                         Rn = (((uint64)_Rn) << 16) / _Rm;
2045                 }
2046                 else
2047                 {
2048                         dsp_remain = _Rn % _Rm;
2049                         if (dsp_remain&0x80000000)
2050                                 dsp_remain-=_Rm;
2051                         Rn/=_Rm;
2052                 }
2053         }
2054         else
2055                 Rn=0xffffffff;
2056 }
2057
2058 static void dsp_opcode_imultn(void)
2059 {
2060         uint32 res=(int32)(((int16)Rn)*((int16)Rm));
2061         dsp_acc=(int32)res;
2062         set_flag_z(res);
2063         set_flag_n(res);
2064 }
2065
2066 static void dsp_opcode_neg(void)
2067 {
2068         uint32 _Rn=Rn;
2069         uint32 res;
2070 #ifdef __PORT__
2071
2072     /*
2073        GCC on WIN32 (more importantly mingw) doesn't know the declared
2074        variables in asm until we put a _ before it.
2075        
2076        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2077     */
2078
2079     #ifdef __GCCWIN32__
2080
2081         asm(
2082         "
2083         subl %1, %2
2084         setc  _dsp_flag_c
2085         setz  _dsp_flag_z
2086         sets  _dsp_flag_n
2087         movl %%eax, %0
2088         "
2089         : "=m"(res)
2090         : "d"(_Rn), "a"(0));
2091         
2092         #else
2093
2094         asm(
2095         "
2096         subl %1, %2
2097         setc  dsp_flag_c
2098         setz  dsp_flag_z
2099         sets  dsp_flag_n
2100         movl %%eax, %0
2101         "
2102         : "=m"(res)
2103         : "d"(_Rn), "a"(0));
2104         
2105         #endif
2106         
2107 #else
2108         __asm 
2109         {
2110                 xor       eax,eax
2111                 mov   edx,_Rn
2112                 sub   eax,edx
2113                 setc  [dsp_flag_c]
2114                 setz  [dsp_flag_z]
2115                 sets  [dsp_flag_n]
2116                 mov       res,eax
2117         };
2118 #endif
2119         Rn=res;
2120 }
2121
2122 static void dsp_opcode_shlq(void)
2123 {
2124         uint32 shift=(32-dsp_convert_zero[imm_1]);
2125         uint32 _Rn=Rn;
2126         uint32 res;
2127 #ifdef __PORT__
2128
2129     /*
2130        GCC on WIN32 (more importantly mingw) doesn't know the declared
2131        variables in asm until we put a _ before it.
2132        
2133        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2134     */
2135
2136     #ifdef __GCCWIN32__
2137
2138         asm(
2139         "testl $0x80000000, %2
2140         setnz _dsp_flag_c
2141         shl %%cl, %2
2142         cmpl $0, %2
2143         setz  _dsp_flag_z
2144         sets  _dsp_flag_n
2145         movl %%eax, %0
2146         "
2147         : "=m"(res)
2148         : "c"(shift), "a"(_Rn));
2149         
2150         #else
2151         
2152         asm(
2153         "testl $0x80000000, %2
2154         setnz dsp_flag_c
2155         shl %%cl, %2
2156         cmpl $0, %2
2157         setz  dsp_flag_z
2158         sets  dsp_flag_n
2159         movl %%eax, %0
2160         "
2161         : "=m"(res)
2162         : "c"(shift), "a"(_Rn));
2163
2164         #endif  
2165         
2166 #else
2167         __asm 
2168         {
2169                 mov ecx,shift
2170                 mov eax,_Rn
2171                 test eax,0x80000000
2172                 setnz [dsp_flag_c]
2173                 shl eax,cl
2174                 cmp eax,0
2175                 setz [dsp_flag_z]
2176                 sets [dsp_flag_n]
2177                 mov res,eax
2178         }
2179 #endif
2180         Rn=res;
2181 }
2182
2183 static void dsp_opcode_shrq(void)
2184 {
2185         uint32 shift=dsp_convert_zero[imm_1];
2186         uint32 _Rn=Rn;
2187         
2188         uint32 res;
2189 #ifdef __PORT__
2190
2191     /*
2192        GCC on WIN32 (more importantly mingw) doesn't know the declared
2193        variables in asm until we put a _ before it.
2194        
2195        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2196     */
2197
2198     #ifdef __GCCWIN32__
2199
2200         asm(
2201         "testl $0x00000001, %2
2202         setnz _dsp_flag_c
2203         shr %%cl, %2
2204         cmpl $0, %2
2205         setz  _dsp_flag_z
2206         sets  _dsp_flag_n
2207         movl %%eax, %0
2208         "
2209         : "=m"(res)
2210         : "c"(shift), "a"(_Rn));
2211         
2212         #else
2213         
2214         asm(
2215         "testl $0x00000001, %2
2216         setnz dsp_flag_c
2217         shr %%cl, %2
2218         cmpl $0, %2
2219         setz  dsp_flag_z
2220         sets  dsp_flag_n
2221         movl %%eax, %0
2222         "
2223         : "=m"(res)
2224         : "c"(shift), "a"(_Rn));
2225
2226         #endif  
2227
2228 #else
2229         __asm 
2230         {
2231                 mov ecx,shift
2232                 mov eax,_Rn
2233                 test eax,0x00000001
2234                 setnz [dsp_flag_c]
2235                 shr eax,cl
2236                 cmp eax,0
2237                 setz [dsp_flag_z]
2238                 sets [dsp_flag_n]
2239                 mov res,eax
2240         }
2241 #endif
2242         Rn=res;
2243 }
2244
2245 static void dsp_opcode_ror(void)
2246 {
2247         uint32 shift=Rm;
2248         uint32 _Rn=Rn;
2249         uint32 res;
2250 #ifdef __PORT__
2251
2252     /*
2253        GCC on WIN32 (more importantly mingw) doesn't know the declared
2254        variables in asm until we put a _ before it.
2255        
2256        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2257     */
2258
2259     #ifdef __GCCWIN32__
2260
2261         asm(
2262         "testl $0x80000000, %2
2263         setnz _dsp_flag_c
2264         ror %%cl, %2
2265         cmpl $0, %2
2266         setz  _dsp_flag_z
2267         sets  _dsp_flag_n
2268         movl %%eax, %0
2269         "
2270         : "=m"(res)
2271         : "c"(shift), "a"(_Rn));
2272         
2273         #else
2274
2275         asm(
2276         "testl $0x80000000, %2
2277         setnz dsp_flag_c
2278         ror %%cl, %2
2279         cmpl $0, %2
2280         setz  dsp_flag_z
2281         sets  dsp_flag_n
2282         movl %%eax, %0
2283         "
2284         : "=m"(res)
2285         : "c"(shift), "a"(_Rn));
2286         
2287         #endif
2288         
2289 #else
2290         __asm 
2291         {
2292                 mov ecx,shift
2293                 mov eax,_Rn
2294                 test eax,0x80000000
2295                 setnz [dsp_flag_c]
2296                 ror eax,cl
2297                 cmp eax,0
2298                 setz [dsp_flag_z]
2299                 sets [dsp_flag_n]
2300                 mov res,eax
2301         }
2302 #endif
2303         Rn=res;
2304 }
2305
2306 static void dsp_opcode_rorq(void)
2307 {
2308         uint32 shift=dsp_convert_zero[imm_1&0x1f];
2309         uint32 _Rn=Rn;
2310         uint32 res;
2311 #ifdef __PORT__
2312
2313     /*
2314        GCC on WIN32 (more importantly mingw) doesn't know the declared
2315        variables in asm until we put a _ before it.
2316        
2317        So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2318     */
2319
2320     #ifdef __GCCWIN32__
2321
2322         asm(
2323         "testl $0x80000000, %2
2324         setnz _dsp_flag_c
2325         ror %%cl, %2
2326         cmpl $0, %2
2327         setz  _dsp_flag_z
2328         sets  _dsp_flag_n
2329         movl %%eax, %0
2330         "
2331         : "=m"(res)
2332         : "c"(shift), "a"(_Rn));
2333         
2334         #else
2335         
2336         asm(
2337         "testl $0x80000000, %2
2338         setnz dsp_flag_c
2339         ror %%cl, %2
2340         cmpl $0, %2
2341         setz  dsp_flag_z
2342         sets  dsp_flag_n
2343         movl %%eax, %0
2344         "
2345         : "=m"(res)
2346         : "c"(shift), "a"(_Rn));
2347
2348         #endif
2349         
2350 #else
2351         __asm 
2352         {
2353                 mov ecx,shift
2354                 mov eax,_Rn
2355                 test eax,0x80000000
2356                 setnz [dsp_flag_c]
2357                 ror eax,cl
2358                 cmp eax,0
2359                 setz [dsp_flag_z]
2360                 sets [dsp_flag_n]
2361                 mov res,eax
2362         }
2363 #endif
2364         Rn=res;
2365 }
2366
2367 static void dsp_opcode_sha(void)
2368 {
2369         int32 sRm=(int32)Rm;
2370         uint32 _Rn=Rn;
2371
2372         if (sRm<0)
2373         {
2374                 uint32 shift=-sRm;
2375                 if (shift>=32) shift=32;
2376                 dsp_flag_c=(_Rn&0x80000000)>>31;
2377                 while (shift)
2378                 {
2379                         _Rn<<=1;
2380                         shift--;
2381                 }
2382         }
2383         else
2384         {
2385                 uint32 shift=sRm;
2386                 if (shift>=32) shift=32;
2387                 dsp_flag_c=_Rn&0x1;
2388                 while (shift)
2389                 {
2390                         _Rn=((int32)_Rn)>>1;
2391                         shift--;
2392                 }
2393         }
2394         Rn=_Rn;
2395         set_flag_z(_Rn);
2396         set_flag_n(_Rn);
2397 }
2398
2399 static void dsp_opcode_sharq(void)
2400 {
2401         uint32 shift=dsp_convert_zero[imm_1];
2402         uint32 _Rn=Rn;
2403
2404         dsp_flag_c  = (_Rn & 0x1);
2405         while (shift)
2406         {
2407                 _Rn=((int32)_Rn)>>1;
2408                 shift--;
2409         }
2410         Rn=_Rn;
2411         set_flag_z(_Rn);
2412         set_flag_n(_Rn);
2413 }
2414
2415 static void dsp_opcode_sh(void)
2416 {
2417         int32 sRm=(int32)Rm;
2418         uint32 _Rn=Rn;
2419
2420         if (sRm<0)
2421         {
2422                 uint32 shift=(-sRm);
2423                 if (shift>=32) shift=32;
2424                 dsp_flag_c=(_Rn&0x80000000)>>31;
2425                 while (shift)
2426                 {
2427                         _Rn<<=1;
2428                         shift--;
2429                 }
2430         }
2431         else
2432         {
2433                 uint32 shift=sRm;
2434                 if (shift>=32) shift=32;
2435                 dsp_flag_c=_Rn&0x1;
2436                 while (shift)
2437                 {
2438                         _Rn>>=1;
2439                         shift--;
2440                 }
2441         }
2442         Rn=_Rn;
2443         set_flag_z(_Rn);
2444         set_flag_n(_Rn);
2445 }
2446
2447 #define CLR_ZN  { dsp_flag_n=0; dsp_flag_z=0; };
2448 #define CLR_ZNC { dsp_flag_c=0; dsp_flag_n=0; dsp_flag_z=0; };
2449 #define SET_Z(r)                        (dsp_flag_z= ((r) == 0))
2450 #define SET_C_ADD(a,b)          (dsp_flag_c= ((UINT32)(b) > (UINT32)(~(a))) << 1)
2451 #define SET_C_SUB(a,b)          (dsp_flag_c= ((UINT32)(b) > (UINT32)(a)) << 1)
2452 #define SET_N(r)                        (dsp_flag_n= (((UINT32)(r) >> 29) & 4))
2453 #define SET_ZN(r)                       SET_N(r); SET_Z(r)
2454 #define SET_ZNC_ADD(a,b,r)      SET_N(r); SET_Z(r); SET_C_ADD(a,b)
2455 #define SET_ZNC_SUB(a,b,r)      SET_N(r); SET_Z(r); SET_C_SUB(a,b)
2456
2457 void dsp_opcode_addqmod(void)   
2458 {
2459         UINT32 r1 = dsp_convert_zero[imm_1];
2460         UINT32 r2 = Rn;
2461         UINT32 res = r2 + r1;
2462         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2463         Rn = res;
2464         CLR_ZNC; SET_ZNC_ADD(r2,r1,res);
2465 }
2466 void dsp_opcode_subqmod(void)   
2467 {
2468         UINT32 r1 = dsp_convert_zero[imm_1];
2469         UINT32 r2 = Rn;
2470         UINT32 res = r2 - r1;
2471         res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2472         Rn = res;
2473         
2474         SET_ZNC_SUB(r2,r1,res);
2475 }
2476 void dsp_opcode_mirror(void)    
2477 {
2478         UINT32 r1 = Rn;
2479         UINT32 res = (mirror_table[r1 & 0xffff] << 16) | mirror_table[r1 >> 16];
2480         Rn = res;
2481         CLR_ZN; SET_ZN(res);
2482 }
2483 void dsp_opcode_sat32s(void)            
2484 {
2485         INT32 r2 = (UINT32)Rn;
2486         INT32 temp = dsp_acc >> 32;
2487         UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7fffffff : r2;
2488         Rn = res;
2489         CLR_ZN; SET_ZN(res);
2490 }
2491 void dsp_opcode_sat16s(void)            
2492 {
2493         INT32 r2 = Rn;
2494         UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
2495         Rn = res;
2496         CLR_ZN; SET_ZN(res);
2497 }