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
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
20 extern int start_logging;
\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
87 uint8 gpu_opcode_cycles[64] =
\r
107 void (*gpu_opcode[64])()=
\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
127 static uint8 * gpu_ram_8;
\r
128 //static uint16 *gpu_ram_16;
\r
129 //static uint32 *gpu_ram_32;
\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
153 static uint32 gpu_opcode_first_parameter;
\r
154 static uint32 gpu_opcode_second_parameter;
\r
156 #define GPU_RUNNING (gpu_control & 0x01)
\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
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
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
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
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
183 uint8 * branch_condition_table = 0;
\r
184 #define branch_condition(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
\r
186 uint32 gpu_opcode_use[64];
\r
188 void gpu_update_register_banks(void);
\r
190 char *gpu_opcode_str[64]=
\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
210 static uint32 gpu_in_exec = 0;
\r
211 static uint32 gpu_releaseTimeSlice_flag = 0;
\r
214 void gpu_releaseTimeslice(void)
\r
216 gpu_releaseTimeSlice_flag = 1;
\r
219 uint32 gpu_get_pc(void)
\r
224 void build_branch_condition_table(void)
\r
226 #define ZFLAG 0x00001
\r
227 #define CFLAG 0x00002
\r
228 #define NFLAG 0x00004
\r
230 if (!branch_condition_table)
\r
232 branch_condition_table = (uint8*)malloc(32 * 8 * sizeof(branch_condition_table[0]));
\r
234 if (branch_condition_table)
\r
236 for(int i=0; i<8; i++)
\r
238 for(int j=0; j<32; j++)
\r
248 if (i & (CFLAG << (j >> 4)))
\r
251 if (!(i & (CFLAG << (j >> 4))))
\r
253 branch_condition_table[i * 32 + j] = result;
\r
261 // GPU byte access (read)
\r
264 unsigned gpu_byte_read(unsigned int offset)
\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
270 uint32 data = gpu_long_read(offset & 0xFFFFFFFC);
\r
272 if ((offset & 0x03) == 0)
\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
282 return jaguar_byte_read(offset);
\r
286 // GPU word access (read)
\r
289 unsigned gpu_word_read(unsigned int offset)
\r
291 if ((offset >= gpu_work_ram_base) && (offset < gpu_work_ram_base+0x1000))
\r
294 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
\r
297 else if ((offset >= gpu_control_ram_base) && (offset < gpu_control_ram_base+0x20))
\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
304 uint32 data = gpu_long_read(offset & 0xFFFFFFFC);
\r
306 if (offset & 0x02) // Cases 0 & 2...
\r
307 return data & 0xFFFF;
\r
312 return jaguar_word_read(offset);
\r
316 // GPU dword access (read)
\r
319 unsigned gpu_long_read(unsigned int offset)
\r
322 if ((offset >= gpu_work_ram_base) && (offset < gpu_work_ram_base+0x1000))
\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
328 else if ((offset >= gpu_control_ram_base) && (offset < gpu_control_ram_base+0x20))
\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
338 gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
\r
340 return gpu_flags & 0xFFFFC1FF;
\r
342 return gpu_matrix_control;
\r
344 return gpu_pointer_to_matrix;
\r
346 return gpu_data_organization;
\r
350 return gpu_control;
\r
355 default: // unaligned long read
\r
361 // to prevent any lock-ups
\r
364 return (jaguar_word_read(offset) << 16) | jaguar_word_read(offset+2);
\r
368 // GPU byte access (write)
\r
371 void gpu_byte_write(unsigned offset, unsigned data)
\r
373 if ((offset >= gpu_work_ram_base) && (offset < gpu_work_ram_base+0x1000))
\r
375 gpu_ram_8[offset & 0xFFF] = data;
\r
376 if (gpu_in_exec == 0)
\r
378 // s68000releaseTimeslice();
\r
379 m68k_end_timeslice();
\r
380 dsp_releaseTimeslice();
\r
384 else if ((offset >= gpu_control_ram_base) && (offset < gpu_control_ram_base+0x20))
\r
386 uint32 reg = offset & 0x1C;
\r
387 int bytenum = offset & 0x03;
\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
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
401 // fprintf(log_get(),"gpu: writing %.2x at 0x%.8x\n",data,offset);
\r
402 jaguar_byte_write(offset, data);
\r
406 // GPU word access (write)
\r
409 void gpu_word_write(unsigned offset, unsigned data)
\r
412 if ((offset >= gpu_work_ram_base) && (offset < gpu_work_ram_base+0x1000))
\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
419 // s68000releaseTimeslice();
\r
420 m68k_end_timeslice();
\r
421 dsp_releaseTimeslice();
\r
425 if ((offset >= gpu_control_ram_base) && (offset < gpu_control_ram_base+0x20))
\r
427 if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
\r
432 if ((offset & 0x1C) == 0x1C)
\r
434 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
\r
436 gpu_div_control = (gpu_div_control&0xFFFF0000) | (data&0xFFFF);
\r
438 gpu_div_control = (gpu_div_control&0xFFFF) | ((data&0xFFFF)<<16);
\r
442 uint32 old_data = gpu_long_read(offset & 0xFFFFFFC);
\r
444 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
\r
446 old_data = (old_data & 0xFFFF) | ((data & 0xFFFF) << 16);
\r
447 gpu_long_write(offset & 0xFFFFFFC, old_data);
\r
451 // fprintf(log_get(),"gpu: writing %.4x at 0x%.8x\n",data,offset);
\r
452 jaguar_word_write(offset, data);
\r
456 // GPU dword access (write)
\r
459 void gpu_long_write(unsigned offset, unsigned data)
\r
462 if ((offset >= gpu_work_ram_base) && (offset < gpu_work_ram_base+0x1000))
\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
470 else if ((offset >= gpu_control_ram_base) && (offset < gpu_control_ram_base+0x20))
\r
477 gpu_flags=(data&(~0x08))|(gpu_flags&0x08); // update dsp_flags, but keep imask unchanged
\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
488 gpu_matrix_control = data;
\r
491 gpu_pointer_to_matrix=data;
\r
494 gpu_data_organization=data;
\r
497 gpu_pc = data; /*fprintf(log_get(),"setting gpu pc to 0x%.8x\n",gpu_pc);*/
\r
501 uint32 gpu_was_running = GPU_RUNNING;
\r
503 data &= (~0x7C0); // disable writes to irq pending
\r
506 fprintf(log_get(),"gpu pc is 0x%.8x\n",gpu_pc);
\r
510 // check for GPU->CPU interrupt
\r
513 // fprintf(log_get(),"GPU->CPU interrupt\n");
\r
514 if (tom_irq_enabled(IRQ_GPU))
\r
516 if ((tom_irq_enabled(IRQ_GPU)) && (jaguar_interrupt_handler_is_valid(64)))
\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
525 uint32 addr=jaguar_word_read(((IRQ_GPU+64)<<2)+0);
\r
527 addr|=jaguar_word_read(((IRQ_GPU+64)<<2)+2);
\r
528 if ((addr)&&(jaguar_interrupt_handler_is_valid(IRQ_GPU+64)))
\r
530 s68000interrupt(7,IRQ_GPU+64);
\r
531 s68000flushInterrupts();
\r
537 // check for CPU->GPU interrupt
\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
550 //fprintf(log_get(),"asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
\r
552 gpu_control = (gpu_control & 0x107C0) | (data & (~0x107C0));
\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
559 if (gpu_control & 0x18)
\r
562 fprintf(log_get(), "Write to GPU CTRL: %08X ", data);
\r
564 fprintf(log_get(), "-- Starting to run at %08X...", gpu_pc);
\r
565 fprintf(log_get(), "\n");
\r
573 gpu_div_control = data;
\r
575 // default: // unaligned long write
\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
586 void gpu_update_register_banks(void)
\r
589 int bank = (gpu_flags & 0x4000);
\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
593 if (gpu_flags & 0x8)
\r
596 if ((!bank && (gpu_reg_bank_0 != gpu_reg)) || (bank && (gpu_reg_bank_1 != gpu_reg)))
\r
598 // fprintf(log_get(),"\tswitching to bank %i\n",bank?1:0);
\r
599 for(int i=0; i<32; i++)
\r
602 gpu_reg[i] = gpu_alternate_reg[i];
\r
603 gpu_alternate_reg[i] = temp;
\r
608 gpu_flag_z = gpu_alternate_flag_z;
\r
609 gpu_alternate_flag_z = temp;
\r
612 gpu_flag_n = gpu_alternate_flag_n;
\r
613 gpu_alternate_flag_n = temp;
\r
616 gpu_flag_c = gpu_alternate_flag_c;
\r
617 gpu_alternate_flag_c = temp;
\r
621 gpu_reg_bank_0 = gpu_reg;
\r
622 gpu_reg_bank_1 = gpu_alternate_reg;
\r
626 gpu_reg_bank_0 = gpu_alternate_reg;
\r
627 gpu_reg_bank_1 = gpu_reg;
\r
632 // fprintf(log_get(),"\tnot switching banks\n");
\r
636 void gpu_check_irqs(void)
\r
638 int bits, mask, which = 0;
\r
640 // get the active interrupt bits
\r
641 bits = (gpu_control >> 6) & 0x1F;
\r
642 bits |= (gpu_control >> 10) & 0x20;
\r
644 // get the interrupt mask
\r
645 mask = (gpu_flags >> 4) & 0x1F;
\r
646 mask |= (gpu_flags >> 11) & 0x20;
\r
648 // bail if nothing is available
\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
661 if (gpu_flags & 0x8)
\r
665 fprintf(log_get(),"gpu: generating irg %i\n",which);
\r
667 // set the interrupt flag
\r
669 gpu_update_register_banks();
\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
675 gpu_reg[30] = gpu_pc - 2;
\r
676 gpu_long_write(gpu_reg[31], gpu_pc - 2);
\r
678 // movei #service_address,r30 ; pointer to ISR entry
\r
679 // jump (r30) ; jump to ISR
\r
681 gpu_pc = gpu_work_ram_base;
\r
682 gpu_pc += which * 0x10;
\r
683 gpu_reg[30] = gpu_pc;
\r
686 void gpu_set_irq_line(int irqline, int state)
\r
689 fprintf(log_get(),"gpu: setting irg line %i\n",irqline);
\r
690 int mask = 0x40 << irqline;
\r
691 gpu_control &= ~mask;
\r
695 gpu_control |= mask;
\r
700 void gpu_init(void)
\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
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
709 build_branch_condition_table();
\r
714 void gpu_reset(void)
\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
728 for(int i=0; i<32; i++)
\r
730 gpu_reg[i] = 0x00000000;
\r
731 gpu_alternate_reg[i] = 0x00000000;
\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
743 gpu_alternate_flag_z = 0;
\r
744 gpu_alternate_flag_n = 0;
\r
745 gpu_alternate_flag_c = 0;
\r
747 memset(gpu_ram_8, 0xFF, 0x1000);
\r
752 uint32 gpu_read_pc(void)
\r
757 void gpu_reset_stats(void)
\r
759 for(uint32 i=0; i<64; i++)
\r
760 gpu_opcode_use[i] = 0;
\r
763 void gpu_done(void)
\r
765 fprintf(log_get(), "GPU: stopped at PC=%08X (GPU %s running)\n", gpu_pc, GPU_RUNNING ? "was" : "wasn't");
\r
767 // get the active interrupt bits
\r
768 int bits = (gpu_control >> 6) & 0x1F;
\r
769 bits |= (gpu_control >> 10) & 0x20;
\r
771 // get the interrupt mask
\r
772 int mask = (gpu_flags >> 4) & 0x1F;
\r
773 mask |= (gpu_flags >> 11) & 0x20;
\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
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
787 // fprintf(log_get(),"registers bank 1\n");
\r
788 // for (j=0;j<8;j++)
\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
797 fprintf(log_get(),"---[GPU code at 00F03000]---------------------------\n");
\r
798 static char buffer[512];
\r
800 for(int i=0; i<4096; i++)
\r
803 j += dasmjag(JAGUAR_GPU, buffer, j);
\r
804 fprintf(log_get(),"\t%08X: %s\n", oldj, buffer);
\r
807 fprintf(log_get(), "---[GPU code at %08X]---------------------------\n", gpu_pc);
\r
809 for(int i=0; i<4096; i++)
\r
812 j += dasmjag(JAGUAR_GPU, buffer, j);
\r
813 fprintf(log_get(), "\t%08X: %s\n", oldj, buffer);
\r
816 fprintf(log_get(), "gpu opcodes use:\n");
\r
817 for(int i=0; i<64; i++)
\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
822 memory_free(gpu_ram_8);
\r
826 // Main GPU execution core
\r
829 void gpu_exec(int32 cycles)
\r
834 #ifdef GPU_SINGLE_STEPPING
\r
835 if (gpu_control & 0x18)
\r
838 gpu_control &= ~0x10;
\r
842 gpu_releaseTimeSlice_flag = 0;
\r
845 while ((cycles > 0) && GPU_RUNNING)
\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
851 uint16 opcode = gpu_word_read(gpu_pc);
\r
853 uint32 index = opcode >> 10;
\r
854 gpu_opcode_first_parameter = (opcode & 0x3E0) >> 5;
\r
855 gpu_opcode_second_parameter = (opcode & 0x1F);
\r
857 gpu_opcode[index]();
\r
858 cycles -= gpu_opcode_cycles[index];
\r
859 gpu_opcode_use[index]++;
\r
869 static void gpu_opcode_jump(void)
\r
871 uint32 delayed_pc = Rm;
\r
872 uint32 jaguar_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
879 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
\r
881 if (branch_condition(imm_2))
\r
884 gpu_pc = delayed_pc;
\r
888 static void gpu_opcode_jr(void)
\r
890 int32 offset=(imm_1&0x10) ? (0xFFFFFFF0|imm_1) : imm_1;
\r
892 int32 delayed_pc = gpu_pc + (offset * 2);
\r
893 uint32 jaguar_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
900 jaguar_flags=(gpu_flag_n<<2)|(gpu_flag_c<<1)|gpu_flag_z;
\r
902 if (branch_condition(imm_2))
\r
909 static void gpu_opcode_add(void)
\r
915 #ifndef USE_ASSEMBLY
\r
917 /* uint32 index = opcode >> 10;
\r
918 gpu_opcode_first_parameter = (opcode & 0x3E0) >> 5;
\r
919 gpu_opcode_second_parameter = (opcode & 0x1F);
\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
931 UINT32 res = Rn + Rm;
\r
932 CLR_ZNC; SET_ZNC_ADD(Rn, Rm, res);
\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
940 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
944 #ifdef __GCCWIN32__
\r
948 setc _gpu_flag_c \n\
\r
949 setz _gpu_flag_z \n\
\r
950 sets _gpu_flag_n \n\
\r
954 : "d"(_Rm), "a"(_Rn));
\r
960 setc gpu_flag_c \n\
\r
961 setz gpu_flag_z \n\
\r
962 sets gpu_flag_n \n\
\r
966 : "d"(_Rm), "a"(_Rn));
\r
968 #endif // #ifdef __GCCWIN32__
\r
969 #endif // #ifndef USE_ASSEMBLY
\r
982 #endif // #ifdef __PORT__
\r
986 static void gpu_opcode_addc(void)
\r
992 #ifndef USE_ASSEMBLY
\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
1001 UINT32 res = Rn + Rm + gpu_flag_c;
\r
1002 CLR_ZNC; SET_ZNC_ADD(Rn, Rm, res);
\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
1011 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
1014 #ifdef __GCCWIN32__
\r
1018 cmp $0, _gpu_flag_c \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
1030 : "d"(_Rm), "a"(_Rn));
\r
1036 cmp $0, gpu_flag_c \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
1048 : "d"(_Rm), "a"(_Rn));
\r
1050 #endif // #ifdef __GCCWIN32__
\r
1051 #endif // #ifndef USE_ASSEMBLY
\r
1058 cmp [gpu_flag_c],0
\r
1060 jz gpu_opcode_addc_no_carry
\r
1062 gpu_opcode_addc_no_carry:
\r
1073 static void gpu_opcode_addq(void)
\r
1076 uint32 _Rm=gpu_convert_zero[imm_1];
\r
1079 #ifndef USE_ASSEMBLY
\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
1095 GCC on WIN32 (more importantly mingw) doesn't know the declared
\r
1096 variables in asm until we put a _ before it.
\r
1098 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
1101 #ifdef __GCCWIN32__
\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
1111 : "d"(_Rm), "a"(_Rn));
\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
1123 : "d"(_Rm), "a"(_Rn));
\r
1125 #endif // #ifdef __GCCWIN32__
\r
1126 #endif // #ifndef USE_ASSEMBLY
\r
1143 static void gpu_opcode_addqt(void)
\r
1145 Rn += gpu_convert_zero[imm_1];
\r
1148 static void gpu_opcode_sub(void)
\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
1159 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
1162 #ifdef __GCCWIN32__
\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
1172 : "d"(_Rm), "a"(_Rn));
\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
1184 : "d"(_Rm), "a"(_Rn));
\r
1203 static void gpu_opcode_subc(void)
\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
1214 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
1217 #ifdef __GCCWIN32__
\r
1221 cmp $0, _gpu_flag_c \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
1233 : "d"(_Rm), "a"(_Rn));
\r
1239 cmp $0, gpu_flag_c \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
1251 : "d"(_Rm), "a"(_Rn));
\r
1258 cmp [gpu_flag_c],0
\r
1260 jz gpu_opcode_subc_no_carry
\r
1262 gpu_opcode_subc_no_carry:
\r
1275 static void gpu_opcode_subq(void)
\r
1277 uint32 _Rm=gpu_convert_zero[imm_1];
\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
1286 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
1289 #ifdef __GCCWIN32__
\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
1299 : "d"(_Rm), "a"(_Rn));
\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
1311 : "d"(_Rm), "a"(_Rn));
\r
1330 static void gpu_opcode_subqt(void)
\r
1332 Rn -= gpu_convert_zero[imm_1];
\r
1335 static void gpu_opcode_cmp(void)
\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
1345 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
1348 #ifdef __GCCWIN32__
\r
1352 setc _gpu_flag_c \n\
\r
1353 setz _gpu_flag_z \n\
\r
1354 sets _gpu_flag_n \n\
\r
1357 : "d"(_Rm), "a"(_Rn));
\r
1363 setc gpu_flag_c \n\
\r
1364 setz gpu_flag_z \n\
\r
1365 sets gpu_flag_n \n\
\r
1368 : "d"(_Rm), "a"(_Rn));
\r
1385 static void gpu_opcode_cmpq(void)
\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
1393 GCC on WIN32 (more importantly mingw) doesn't know the declared
\r
1394 variables in asm until we put a _ before it.
\r
1396 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
1399 #ifdef __GCCWIN32__
\r
1403 setc _gpu_flag_c \n\
\r
1404 setz _gpu_flag_z \n\
\r
1405 sets _gpu_flag_n \n\
\r
1408 : "d"(_Rm), "a"(_Rn));
\r
1414 setc gpu_flag_c \n\
\r
1415 setz gpu_flag_z \n\
\r
1416 sets gpu_flag_n \n\
\r
1419 : "d"(_Rm), "a"(_Rn));
\r
1435 static void gpu_opcode_and(void)
\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
1446 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
1449 #ifdef __GCCWIN32__
\r
1453 setz _gpu_flag_z \n\
\r
1454 sets _gpu_flag_n \n\
\r
1455 movl %%eax, %0 \n\
\r
1458 : "d"(_Rm), "a"(_Rn));
\r
1464 setz gpu_flag_z \n\
\r
1465 sets gpu_flag_n \n\
\r
1466 movl %%eax, %0 \n\
\r
1469 : "d"(_Rm), "a"(_Rn));
\r
1486 static void gpu_opcode_or(void)
\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
1497 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
1500 #ifdef __GCCWIN32__
\r
1504 setz _gpu_flag_z \n\
\r
1505 sets _gpu_flag_n \n\
\r
1506 movl %%eax, %0 \n\
\r
1509 : "d"(_Rm), "a"(_Rn));
\r
1515 setz gpu_flag_z \n\
\r
1516 sets gpu_flag_n \n\
\r
1517 movl %%eax, %0 \n\
\r
1520 : "d"(_Rm), "a"(_Rn));
\r
1537 static void gpu_opcode_xor(void)
\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
1548 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
1551 #ifdef __GCCWIN32__
\r
1555 setz _gpu_flag_z \n\
\r
1556 sets _gpu_flag_n \n\
\r
1557 movl %%eax, %0 \n\
\r
1560 : "d"(_Rm), "a"(_Rn));
\r
1566 setz gpu_flag_z \n\
\r
1567 sets gpu_flag_n \n\
\r
1568 movl %%eax, %0 \n\
\r
1571 : "d"(_Rm), "a"(_Rn));
\r
1588 static void gpu_opcode_not(void)
\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
1598 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
1601 #ifdef __GCCWIN32__
\r
1605 setz _gpu_flag_z \n\
\r
1606 sets _gpu_flag_n \n\
\r
1607 movl %%eax, %0 \n\
\r
1616 setz gpu_flag_z \n\
\r
1617 sets gpu_flag_n \n\
\r
1618 movl %%eax, %0 \n\
\r
1637 static void gpu_opcode_move_pc(void)
\r
1642 static void gpu_opcode_sat8(void)
\r
1644 int32 _Rn=(int32)Rn;
\r
1646 uint32 res= Rn = (_Rn<0) ? 0 : (_Rn > 0xff ? 0xff : _Rn);
\r
1651 static void gpu_opcode_sat16(void)
\r
1653 int32 _Rn=(int32)Rn;
\r
1654 uint32 res= Rn = (_Rn<0) ? 0 : (_Rn > 0xFFFF ? 0xFFFF : _Rn);
\r
1659 static void gpu_opcode_sat24(void)
\r
1661 int32 _Rn=(int32)Rn;
\r
1663 uint32 res= Rn = (_Rn<0) ? 0 : (_Rn > 0xFFFFFF ? 0xFFFFFF : _Rn);
\r
1668 static void gpu_opcode_store_r14_indexed(void)
\r
1670 gpu_long_write( gpu_reg[14] + (gpu_convert_zero[imm_1] << 2),Rn);
\r
1673 static void gpu_opcode_store_r15_indexed(void)
\r
1675 gpu_long_write( gpu_reg[15] + (gpu_convert_zero[imm_1] << 2),Rn);
\r
1678 static void gpu_opcode_load_r14_ri(void)
\r
1680 Rn=gpu_long_read(gpu_reg[14] + Rm);
\r
1683 static void gpu_opcode_load_r15_ri(void)
\r
1685 Rn=gpu_long_read(gpu_reg[15] + Rm);
\r
1688 static void gpu_opcode_store_r14_ri(void)
\r
1690 gpu_long_write(gpu_reg[14] + Rm,Rn);
\r
1693 static void gpu_opcode_store_r15_ri(void)
\r
1695 gpu_long_write(gpu_reg[15] + Rm,Rn);
\r
1698 static void gpu_opcode_nop(void)
\r
1702 static void gpu_opcode_pack(void)
\r
1708 Rn =((_Rn & 0x03C00000) >> 10) |
\r
1709 ((_Rn & 0x0001E000) >> 5) |
\r
1710 ((_Rn & 0x000000FF));
\r
1714 Rn =((_Rn & 0x0000F000) << 10) |
\r
1715 ((_Rn & 0x00000F00) << 5) |
\r
1716 ((_Rn & 0x000000FF));
\r
1724 static void gpu_opcode_storeb(void)
\r
1726 if ((Rm >= 0xF03000) && (Rm < 0xF04000))
\r
1727 gpu_long_write(Rm,Rn&0xff);
\r
1729 jaguar_byte_write(Rm,Rn);
\r
1732 static void gpu_opcode_storew(void)
\r
1734 if ((Rm >= 0xF03000) && (Rm < 0xF04000))
\r
1735 gpu_long_write(Rm,Rn&0xffff);
\r
1737 jaguar_word_write(Rm,Rn);
\r
1740 static void gpu_opcode_store(void)
\r
1742 gpu_long_write(Rm,Rn);
\r
1745 static void gpu_opcode_storep(void)
\r
1748 gpu_long_write(_Rm, gpu_hidata);
\r
1749 gpu_long_write(_Rm+4, Rn);
\r
1752 static void gpu_opcode_loadb(void)
\r
1754 if ((Rm >= 0xF03000) && (Rm < 0xF04000))
\r
1755 Rn=gpu_long_read(Rm)&0xff;
\r
1757 Rn=jaguar_byte_read(Rm);
\r
1760 static void gpu_opcode_loadw(void)
\r
1762 if ((Rm >= 0xF03000) && (Rm < 0xF04000))
\r
1763 Rn=gpu_long_read(Rm)&0xffff;
\r
1765 Rn=jaguar_word_read(Rm);
\r
1768 static void gpu_opcode_load(void)
\r
1770 Rn = gpu_long_read(Rm);
\r
1773 static void gpu_opcode_loadp(void)
\r
1777 gpu_hidata = gpu_long_read(_Rm);
\r
1778 Rn = gpu_long_read(_Rm+4);
\r
1781 static void gpu_opcode_load_r14_indexed(void)
\r
1783 Rn = gpu_long_read( gpu_reg[14] + (gpu_convert_zero[imm_1] << 2));
\r
1786 static void gpu_opcode_load_r15_indexed(void)
\r
1788 Rn = gpu_long_read( gpu_reg[15] + (gpu_convert_zero[imm_1] << 2));
\r
1791 static void gpu_opcode_movei(void)
\r
1793 Rn = (uint32)gpu_word_read(gpu_pc) | ((uint32)gpu_word_read(gpu_pc + 2) << 16);
\r
1797 static void gpu_opcode_moveta(void)
\r
1799 alternate_Rn = Rm;
\r
1802 static void gpu_opcode_movefa(void)
\r
1804 Rn = alternate_Rm;
\r
1807 static void gpu_opcode_move(void)
\r
1812 static void gpu_opcode_moveq(void)
\r
1817 static void gpu_opcode_resmac(void)
\r
1822 static void gpu_opcode_imult(void)
\r
1824 uint32 res=Rn=((int16)Rn)*((int16)Rm);
\r
1829 static void gpu_opcode_mult(void)
\r
1831 uint32 res=Rn = ((uint16)Rm) * ((uint16)Rn);
\r
1836 static void gpu_opcode_bclr(void)
\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
1847 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
1850 #ifdef __GCCWIN32__
\r
1855 setz _gpu_flag_z \n\
\r
1856 sets _gpu_flag_n \n\
\r
1857 movl %%eax, %0 \n\
\r
1860 : "c"(_Rm), "a"(_Rn));
\r
1867 setz gpu_flag_z \n\
\r
1868 sets gpu_flag_n \n\
\r
1869 movl %%eax, %0 \n\
\r
1872 : "c"(_Rm), "a"(_Rn));
\r
1891 static void gpu_opcode_btst(void)
\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
1901 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
1904 #ifdef __GCCWIN32__
\r
1908 setnc _gpu_flag_z \n\
\r
1911 : "c"(_Rm), "a"(_Rn));
\r
1917 setnc gpu_flag_z \n\
\r
1920 : "c"(_Rm), "a"(_Rn));
\r
1929 setnc [gpu_flag_z]
\r
1934 static void gpu_opcode_bset(void)
\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
1945 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
1948 #ifdef __GCCWIN32__
\r
1953 setz _gpu_flag_z \n\
\r
1954 sets _gpu_flag_n \n\
\r
1955 movl %%eax, %0 \n\
\r
1958 : "c"(_Rm), "a"(_Rn));
\r
1965 setz gpu_flag_z \n\
\r
1966 sets gpu_flag_n \n\
\r
1967 movl %%eax, %0 \n\
\r
1970 : "c"(_Rm), "a"(_Rn));
\r
1989 static void gpu_opcode_imacn(void)
\r
1991 uint32 res = ((int16)Rm) * ((int16)(Rn));
\r
1995 static void gpu_opcode_mtoi(void)
\r
1998 uint32 res=Rn=(((INT32)_Rm >> 8) & 0xff800000) | (_Rm & 0x007fffff);
\r
2003 static void gpu_opcode_normi(void)
\r
2010 while ((_Rm & 0xffc00000) == 0)
\r
2015 while ((_Rm & 0xff800000) != 0)
\r
2026 static void gpu_opcode_mmult(void)
\r
2028 int count = gpu_matrix_control&0x0f;
\r
2029 uint32 addr = gpu_pointer_to_matrix; // in the gpu ram
\r
2033 if (!(gpu_matrix_control & 0x10))
\r
2035 for (int i = 0; i < count; i++)
\r
2039 a=(int16)((gpu_alternate_reg[gpu_opcode_first_parameter + (i>>1)]>>16)&0xffff);
\r
2041 a=(int16)(gpu_alternate_reg[gpu_opcode_first_parameter + (i>>1)]&0xffff);
\r
2043 int16 b=((int16)gpu_word_read(addr+2));
\r
2050 for (int i = 0; i < count; i++)
\r
2054 a=(int16)((gpu_alternate_reg[gpu_opcode_first_parameter + (i>>1)]>>16)&0xffff);
\r
2056 a=(int16)(gpu_alternate_reg[gpu_opcode_first_parameter + (i>>1)]&0xffff);
\r
2058 int16 b=((int16)gpu_word_read(addr+2));
\r
2060 addr += 4 * count;
\r
2063 Rn = res = (int32)accum;
\r
2064 // carry flag to do
\r
2069 static void gpu_opcode_abs(void)
\r
2074 if (_Rn==0x80000000)
\r
2080 gpu_flag_c = ((_Rn&0x80000000)>>31);
\r
2081 res= Rn = (((int32)_Rn)<0) ? -_Rn : _Rn;
\r
2087 static void gpu_opcode_div(void)
\r
2094 if (gpu_div_control & 1)
\r
2096 gpu_remain = (((uint64)_Rn) << 16) % _Rm;
\r
2097 if (gpu_remain&0x80000000)
\r
2099 Rn = (((uint64)_Rn) << 16) / _Rm;
\r
2103 gpu_remain = _Rn % _Rm;
\r
2104 if (gpu_remain&0x80000000)
\r
2113 static void gpu_opcode_imultn(void)
\r
2115 uint32 res = (int32)((int16)Rn * (int16)Rm);
\r
2116 gpu_acc = (int32)res;
\r
2121 static void gpu_opcode_neg(void)
\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
2131 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
2134 #ifdef __GCCWIN32__
\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
2144 : "d"(_Rn), "a"(0));
\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
2156 : "d"(_Rn), "a"(0));
\r
2174 static void gpu_opcode_shlq(void)
\r
2176 uint32 shift=(32-gpu_convert_zero[imm_1]);
\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
2185 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
2188 #ifdef __GCCWIN32__
\r
2191 "testl $0x80000000, %2 \n\
\r
2192 setnz _gpu_flag_c \n\
\r
2195 setz _gpu_flag_z \n\
\r
2196 sets _gpu_flag_n \n\
\r
2197 movl %%eax, %0 \n\
\r
2200 : "c"(shift), "a"(_Rn));
\r
2205 "testl $0x80000000, %2 \n\
\r
2206 setnz gpu_flag_c \n\
\r
2209 setz gpu_flag_z \n\
\r
2210 sets gpu_flag_n \n\
\r
2211 movl %%eax, %0 \n\
\r
2214 : "c"(shift), "a"(_Rn));
\r
2223 test eax,0x80000000
\r
2224 setnz [gpu_flag_c]
\r
2235 static void gpu_opcode_shrq(void)
\r
2237 uint32 shift=gpu_convert_zero[imm_1];
\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
2247 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
2250 #ifdef __GCCWIN32__
\r
2253 "testl $0x00000001, %2 \n\
\r
2254 setnz _gpu_flag_c \n\
\r
2257 setz _gpu_flag_z \n\
\r
2258 sets _gpu_flag_n \n\
\r
2259 movl %%eax, %0 \n\
\r
2262 : "c"(shift), "a"(_Rn));
\r
2267 "testl $0x00000001, %2 \n\
\r
2268 setnz gpu_flag_c \n\
\r
2271 setz gpu_flag_z \n\
\r
2272 sets gpu_flag_n \n\
\r
2273 movl %%eax, %0 \n\
\r
2276 : "c"(shift), "a"(_Rn));
\r
2284 test eax,0x00000001
\r
2285 setnz [gpu_flag_c]
\r
2296 static void gpu_opcode_ror(void)
\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
2307 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
2310 #ifdef __GCCWIN32__
\r
2313 "testl $0x80000000, %2 \n\
\r
2314 setnz _gpu_flag_c \n\
\r
2317 setz _gpu_flag_z \n\
\r
2318 sets _gpu_flag_n \n\
\r
2319 movl %%eax, %0 \n\
\r
2322 : "c"(shift), "a"(_Rn));
\r
2327 "testl $0x80000000, %2 \n\
\r
2328 setnz gpu_flag_c \n\
\r
2331 setz gpu_flag_z \n\
\r
2332 sets gpu_flag_n \n\
\r
2333 movl %%eax, %0 \n\
\r
2336 : "c"(shift), "a"(_Rn));
\r
2345 test eax,0x80000000
\r
2346 setnz [gpu_flag_c]
\r
2357 static void gpu_opcode_rorq(void)
\r
2359 uint32 shift = gpu_convert_zero[imm_1 & 0x1F];
\r
2363 #ifndef USE_ASSEMBLY
\r
2365 /* uint32 index = opcode >> 10;
\r
2366 gpu_opcode_first_parameter = (opcode & 0x3E0) >> 5;
\r
2367 gpu_opcode_second_parameter = (opcode & 0x1F);
\r
2369 gpu_opcode[index]();
\r
2370 cycles -= gpu_opcode_cycles[index];
\r
2371 gpu_opcode_use[index]++;*/
\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
2380 UINT32 r1 = gpu_convert_zero[imm_1 & 0x1F];
\r
2382 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
\r
2384 CLR_ZNC; SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
\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
2393 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
\r
2396 #ifdef __GCCWIN32__
\r
2399 "testl $0x80000000, %2 \n\
\r
2400 setnz _gpu_flag_c \n\
\r
2403 setz _gpu_flag_z \n\
\r
2404 sets _gpu_flag_n \n\
\r
2405 movl %%eax, %0 \n\
\r
2408 : "c"(shift), "a"(_Rn));
\r
2413 "testl $0x80000000, %2 \n\
\r
2414 setnz gpu_flag_c \n\
\r
2417 setz gpu_flag_z \n\
\r
2418 sets gpu_flag_n \n\
\r
2419 movl %%eax, %0 \n\
\r
2422 : "c"(shift), "a"(_Rn));
\r
2424 #endif // #ifdef __GCCWIN32__
\r
2425 #endif // #ifndef USE_ASSEMBLY
\r
2432 test eax,0x80000000
\r
2433 setnz [gpu_flag_c]
\r
2440 #endif // #ifdef __PORT__
\r
2444 static void gpu_opcode_sha(void)
\r
2446 int32 sRm=(int32)Rm;
\r
2451 uint32 shift=-sRm;
\r
2452 if (shift>=32) shift=32;
\r
2453 gpu_flag_c=(_Rn&0x80000000)>>31;
\r
2463 if (shift>=32) shift=32;
\r
2464 gpu_flag_c=_Rn&0x1;
\r
2467 _Rn=((int32)_Rn)>>1;
\r
2476 static void gpu_opcode_sharq(void)
\r
2478 uint32 shift=gpu_convert_zero[imm_1];
\r
2481 gpu_flag_c = (_Rn & 0x1);
\r
2484 _Rn=((int32)_Rn)>>1;
\r
2492 static void gpu_opcode_sh(void)
\r
2494 int32 sRm=(int32)Rm;
\r
2499 uint32 shift=(-sRm);
\r
2500 if (shift>=32) shift=32;
\r
2501 gpu_flag_c=(_Rn&0x80000000)>>31;
\r
2511 if (shift>=32) shift=32;
\r
2512 gpu_flag_c=_Rn&0x1;
\r