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