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