5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups, endian wrongness, and bad ASM amelioration by James L. Hammons
7 // Note: Endian wrongness probably stems from the MAME origins of this emu and
8 // the braindead way in which MAME handles memory. :-)
10 // Problem with not booting the BIOS was the incorrect way that the
11 // SUBC instruction set the carry when the carry was set going in...
12 // Same problem with ADDC...
17 // For GPU dissasembly...
20 //#define GPU_DIS_ADDC
22 //#define GPU_DIS_CMPQ
24 //#define GPU_DIS_JUMP
27 //#define GPU_DIS_RORQ
30 //#define GPU_DIS_SHARQ
31 //#define GPU_DIS_SHLQ
32 //#define GPU_DIS_SHRQ
33 //#define GPU_DIS_STORE14R
34 //#define GPU_DIS_STORE15R
35 //#define GPU_DIS_SUBC
37 GPU opcodes use (BIOS flying ATARI logo):
77 // Private function prototypes
79 void gpu_dump_disassembly(void);
80 void gpu_dump_registers(void);
81 void gpu_dump_memory(void);
83 #define CINT0FLAG 0x00200
84 #define CINT1FLAG 0x00400
85 #define CINT2FLAG 0x00800
86 #define CINT3FLAG 0x01000
87 #define CINT4FLAG 0x02000
88 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
90 extern int start_logging;
91 extern int gpu_start_log;
93 static void gpu_opcode_add(void);
94 static void gpu_opcode_addc(void);
95 static void gpu_opcode_addq(void);
96 static void gpu_opcode_addqt(void);
97 static void gpu_opcode_sub(void);
98 static void gpu_opcode_subc(void);
99 static void gpu_opcode_subq(void);
100 static void gpu_opcode_subqt(void);
101 static void gpu_opcode_neg(void);
102 static void gpu_opcode_and(void);
103 static void gpu_opcode_or(void);
104 static void gpu_opcode_xor(void);
105 static void gpu_opcode_not(void);
106 static void gpu_opcode_btst(void);
107 static void gpu_opcode_bset(void);
108 static void gpu_opcode_bclr(void);
109 static void gpu_opcode_mult(void);
110 static void gpu_opcode_imult(void);
111 static void gpu_opcode_imultn(void);
112 static void gpu_opcode_resmac(void);
113 static void gpu_opcode_imacn(void);
114 static void gpu_opcode_div(void);
115 static void gpu_opcode_abs(void);
116 static void gpu_opcode_sh(void);
117 static void gpu_opcode_shlq(void);
118 static void gpu_opcode_shrq(void);
119 static void gpu_opcode_sha(void);
120 static void gpu_opcode_sharq(void);
121 static void gpu_opcode_ror(void);
122 static void gpu_opcode_rorq(void);
123 static void gpu_opcode_cmp(void);
124 static void gpu_opcode_cmpq(void);
125 static void gpu_opcode_sat8(void);
126 static void gpu_opcode_sat16(void);
127 static void gpu_opcode_move(void);
128 static void gpu_opcode_moveq(void);
129 static void gpu_opcode_moveta(void);
130 static void gpu_opcode_movefa(void);
131 static void gpu_opcode_movei(void);
132 static void gpu_opcode_loadb(void);
133 static void gpu_opcode_loadw(void);
134 static void gpu_opcode_load(void);
135 static void gpu_opcode_loadp(void);
136 static void gpu_opcode_load_r14_indexed(void);
137 static void gpu_opcode_load_r15_indexed(void);
138 static void gpu_opcode_storeb(void);
139 static void gpu_opcode_storew(void);
140 static void gpu_opcode_store(void);
141 static void gpu_opcode_storep(void);
142 static void gpu_opcode_store_r14_indexed(void);
143 static void gpu_opcode_store_r15_indexed(void);
144 static void gpu_opcode_move_pc(void);
145 static void gpu_opcode_jump(void);
146 static void gpu_opcode_jr(void);
147 static void gpu_opcode_mmult(void);
148 static void gpu_opcode_mtoi(void);
149 static void gpu_opcode_normi(void);
150 static void gpu_opcode_nop(void);
151 static void gpu_opcode_load_r14_ri(void);
152 static void gpu_opcode_load_r15_ri(void);
153 static void gpu_opcode_store_r14_ri(void);
154 static void gpu_opcode_store_r15_ri(void);
155 static void gpu_opcode_sat24(void);
156 static void gpu_opcode_pack(void);
158 uint8 gpu_opcode_cycles[64] =
160 3, 3, 3, 3, 3, 3, 3, 3,
161 3, 3, 3, 3, 3, 3, 3, 3,
162 3, 3, 1, 3, 1, 18, 3, 3,
163 3, 3, 3, 3, 3, 3, 3, 3,
164 3, 3, 2, 2, 2, 2, 3, 4,
165 5, 4, 5, 6, 6, 1, 1, 1,
166 1, 2, 2, 2, 1, 1, 9, 3,
167 3, 1, 6, 6, 2, 2, 3, 3
170 void (*gpu_opcode[64])()=
172 gpu_opcode_add, gpu_opcode_addc, gpu_opcode_addq, gpu_opcode_addqt,
173 gpu_opcode_sub, gpu_opcode_subc, gpu_opcode_subq, gpu_opcode_subqt,
174 gpu_opcode_neg, gpu_opcode_and, gpu_opcode_or, gpu_opcode_xor,
175 gpu_opcode_not, gpu_opcode_btst, gpu_opcode_bset, gpu_opcode_bclr,
176 gpu_opcode_mult, gpu_opcode_imult, gpu_opcode_imultn, gpu_opcode_resmac,
177 gpu_opcode_imacn, gpu_opcode_div, gpu_opcode_abs, gpu_opcode_sh,
178 gpu_opcode_shlq, gpu_opcode_shrq, gpu_opcode_sha, gpu_opcode_sharq,
179 gpu_opcode_ror, gpu_opcode_rorq, gpu_opcode_cmp, gpu_opcode_cmpq,
180 gpu_opcode_sat8, gpu_opcode_sat16, gpu_opcode_move, gpu_opcode_moveq,
181 gpu_opcode_moveta, gpu_opcode_movefa, gpu_opcode_movei, gpu_opcode_loadb,
182 gpu_opcode_loadw, gpu_opcode_load, gpu_opcode_loadp, gpu_opcode_load_r14_indexed,
183 gpu_opcode_load_r15_indexed, gpu_opcode_storeb, gpu_opcode_storew, gpu_opcode_store,
184 gpu_opcode_storep, gpu_opcode_store_r14_indexed, gpu_opcode_store_r15_indexed, gpu_opcode_move_pc,
185 gpu_opcode_jump, gpu_opcode_jr, gpu_opcode_mmult, gpu_opcode_mtoi,
186 gpu_opcode_normi, gpu_opcode_nop, gpu_opcode_load_r14_ri, gpu_opcode_load_r15_ri,
187 gpu_opcode_store_r14_ri, gpu_opcode_store_r15_ri, gpu_opcode_sat24, gpu_opcode_pack,
190 static uint8 * gpu_ram_8;
191 static uint32 gpu_pc;
192 static uint32 gpu_acc;
193 static uint32 gpu_remain;
194 static uint32 gpu_hidata;
195 static uint32 gpu_flags;
196 static uint32 gpu_matrix_control;
197 static uint32 gpu_pointer_to_matrix;
198 static uint32 gpu_data_organization;
199 static uint32 gpu_control;
200 static uint32 gpu_div_control;
201 static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
202 static uint8 gpu_alternate_flag_z, gpu_alternate_flag_n, gpu_alternate_flag_c;
203 static uint32 * gpu_reg;
204 static uint32 * gpu_alternate_reg;
205 static uint32 * gpu_reg_bank_0;
206 static uint32 * gpu_reg_bank_1;
208 static uint32 gpu_instruction;
209 static uint32 gpu_opcode_first_parameter;
210 static uint32 gpu_opcode_second_parameter;
212 #define GPU_RUNNING (gpu_control & 0x01)
214 #define RM gpu_reg[gpu_opcode_first_parameter]
215 #define RN gpu_reg[gpu_opcode_second_parameter]
216 #define ALTERNATE_RM gpu_alternate_reg[gpu_opcode_first_parameter]
217 #define ALTERNATE_RN gpu_alternate_reg[gpu_opcode_second_parameter]
218 #define IMM_1 gpu_opcode_first_parameter
219 #define IMM_2 gpu_opcode_second_parameter
221 #define SET_FLAG_Z(r) (gpu_flag_z = ((r) == 0));
222 #define SET_FLAG_N(r) (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01));
224 #define RESET_FLAG_Z() gpu_flag_z = 0;
225 #define RESET_FLAG_N() gpu_flag_n = 0;
226 #define RESET_FLAG_C() gpu_flag_c = 0;
228 #define CLR_Z (gpu_flag_z = 0)
229 #define CLR_ZN (gpu_flag_z = gpu_flag_n = 0)
230 #define CLR_ZNC (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
231 #define SET_Z(r) (gpu_flag_z = ((r) == 0))
232 #define SET_N(r) (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01))
233 #define SET_C_ADD(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
234 #define SET_C_SUB(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(a)))
235 #define SET_ZN(r) SET_N(r); SET_Z(r)
236 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
237 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
239 uint32 gpu_convert_zero[32] =
240 { 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 };
242 uint8 * branch_condition_table = 0;
243 #define BRANCH_CONDITION(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
245 uint32 gpu_opcode_use[64];
247 void gpu_update_register_banks(void);
249 char * gpu_opcode_str[64]=
251 "add", "addc", "addq", "addqt",
252 "sub", "subc", "subq", "subqt",
253 "neg", "and", "or", "xor",
254 "not", "btst", "bset", "bclr",
255 "mult", "imult", "imultn", "resmac",
256 "imacn", "div", "abs", "sh",
257 "shlq", "shrq", "sha", "sharq",
258 "ror", "rorq", "cmp", "cmpq",
259 "sat8", "sat16", "move", "moveq",
260 "moveta", "movefa", "movei", "loadb",
261 "loadw", "load", "loadp", "load_r14_indexed",
262 "load_r15_indexed", "storeb", "storew", "store",
263 "storep", "store_r14_indexed","store_r15_indexed","move_pc",
264 "jump", "jr", "mmult", "mtoi",
265 "normi", "nop", "load_r14_ri", "load_r15_ri",
266 "store_r14_ri", "store_r15_ri", "sat24", "pack",
269 static uint32 gpu_in_exec = 0;
270 static uint32 gpu_releaseTimeSlice_flag = 0;
273 void gpu_releaseTimeslice(void)
275 gpu_releaseTimeSlice_flag = 1;
278 uint32 gpu_get_pc(void)
283 #define ZFLAG 0x00001
284 #define CFLAG 0x00002
285 #define NFLAG 0x00004
287 void build_branch_condition_table(void)
289 if (!branch_condition_table)
291 branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(branch_condition_table[0]));
293 if (branch_condition_table)
295 for(int i=0; i<8; i++)
297 for(int j=0; j<32; j++)
307 if (i & (CFLAG << (j >> 4)))
310 if (!(i & (CFLAG << (j >> 4))))
312 branch_condition_table[i * 32 + j] = result;
320 // GPU byte access (read)
323 unsigned gpu_byte_read(unsigned int offset)
325 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
326 return gpu_ram_8[offset & 0xFFF];
327 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
329 uint32 data = gpu_long_read(offset & 0xFFFFFFFC);
331 if ((offset & 0x03) == 0)
333 else if ((offset & 0x03) == 1)
334 return (data >> 16) & 0xFF;
335 else if ((offset & 0x03) == 2)
336 return (data >> 8) & 0xFF;
337 else if ((offset & 0x03) == 3)
341 return jaguar_byte_read(offset);
345 // GPU word access (read)
348 unsigned gpu_word_read(unsigned int offset)
350 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
353 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
356 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
358 // This looks and smells wrong...
359 // But it *might* be OK...
360 if (offset & 0x01) // Catch cases 1 & 3... (unaligned read)
361 return (gpu_byte_read(offset) << 8) | gpu_byte_read(offset+1);
363 uint32 data = gpu_long_read(offset & 0xFFFFFFFC);
365 if (offset & 0x02) // Cases 0 & 2...
366 return data & 0xFFFF;
371 //TEMP--Mirror of F03000?
372 if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
373 WriteLog("[GPUR16] --> Possible GPU RAM mirror access!");
375 return jaguar_word_read(offset);
379 // GPU dword access (read)
382 unsigned gpu_long_read(unsigned int offset)
385 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
388 return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
389 | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];
391 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
397 gpu_flag_c = (gpu_flag_c ? 1 : 0);
398 gpu_flag_z = (gpu_flag_z ? 1 : 0);
399 gpu_flag_n = (gpu_flag_n ? 1 : 0);
401 gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
403 return gpu_flags & 0xFFFFC1FF;
405 return gpu_matrix_control;
407 return gpu_pointer_to_matrix;
409 return gpu_data_organization;
418 default: // unaligned long read
424 // to prevent any lock-ups
426 //TEMP--Mirror of F03000?
427 if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
428 WriteLog("[GPUR32] --> Possible GPU RAM mirror access!\n");
429 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
430 WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
432 return (jaguar_word_read(offset) << 16) | jaguar_word_read(offset+2);
436 // GPU byte access (write)
439 void gpu_byte_write(unsigned offset, unsigned data)
441 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
443 gpu_ram_8[offset & 0xFFF] = data;
444 if (gpu_in_exec == 0)
446 // s68000releaseTimeslice();
447 m68k_end_timeslice();
448 dsp_releaseTimeslice();
452 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
454 uint32 reg = offset & 0x1C;
455 int bytenum = offset & 0x03;
457 //This is definitely wrong!
458 if ((reg >= 0x1C) && (reg <= 0x1F))
459 gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
462 uint32 old_data = gpu_long_read(offset & 0xFFFFFFC);
463 bytenum = 3 - bytenum; // convention motorola !!!
464 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
465 gpu_long_write(offset & 0xFFFFFFC, old_data);
469 // WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
470 jaguar_byte_write(offset, data);
474 // GPU word access (write)
477 void gpu_word_write(unsigned offset, unsigned data)
480 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
482 //if (offset >= 0xF03000 && offset <= 0xF03003)
483 // WriteLog("--> GPU(16): Writing %04X at %08X ***\n", data, offset);
485 gpu_ram_8[offset & 0xFFF] = (data>>8) & 0xFF;
486 gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;
487 if (gpu_in_exec == 0)
489 // s68000releaseTimeslice();
490 m68k_end_timeslice();
491 dsp_releaseTimeslice();
495 if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
497 if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
502 if ((offset & 0x1C) == 0x1C)
504 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
506 gpu_div_control = (gpu_div_control&0xFFFF0000) | (data&0xFFFF);
508 gpu_div_control = (gpu_div_control&0xFFFF) | ((data&0xFFFF)<<16);
512 uint32 old_data = gpu_long_read(offset & 0xFFFFFFC);
514 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
516 old_data = (old_data & 0xFFFF) | ((data & 0xFFFF) << 16);
517 gpu_long_write(offset & 0xFFFFFFC, old_data);
522 // WriteLog("gpu: writing %.4x at 0x%.8x\n",data,offset);
523 //This is done by the blitter...
524 //if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
525 // WriteLog("GPU(16): Writing %08X at %08X\n", data, offset);
526 //if ((offset >= 0x1FE020 && offset <= 0x1FE03F) || (offset >= 0x1FE820 && offset <= 0x1FE83F))
527 // WriteLog("GPU(16): Writing %08X at %08X\n", data, offset);
528 //if (offset >= 0xF02200 && offset <= 0xF0229F)
529 // WriteLog("GPU(16): Writing to blitter --> %08X at %08X\n", data, offset);
531 jaguar_word_write(offset, data);
535 // GPU dword access (write)
538 void gpu_long_write(unsigned offset, unsigned data)
541 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
546 WriteLog("GPU: Someone is trying an unaligned write @ %08X [%08X]\n", offset, data)
547 gpu_dump_registers();
549 #endif // #ifdef GPU_DEBUG
550 /*if (offset == 0xF03000)
552 WriteLog("GPU Write [F03000]: %08X\n", data);
553 // data = 0x03D0DEAD; // Why isn't this there???
554 // data = 0xABCDEFFF; // Why isn't this there???
556 gpu_ram_8[offset & 0xFFF] = (data >> 24) & 0xFF,
557 gpu_ram_8[(offset+1) & 0xFFF] = (data >> 16) & 0xFF,
558 gpu_ram_8[(offset+2) & 0xFFF] = (data >> 8) & 0xFF,
559 gpu_ram_8[(offset+3) & 0xFFF] = data & 0xFF;
562 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
569 gpu_flags=(data&(~0x08))|(gpu_flags&0x08); // update dsp_flags, but keep imask unchanged
572 gpu_flag_z = gpu_flags & 0x01;
573 gpu_flag_c = (gpu_flags>>1) & 0x01;
574 gpu_flag_n = (gpu_flags>>2) & 0x01;
575 gpu_update_register_banks();
576 gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3);
580 gpu_matrix_control = data;
583 // Can only point to long aligned addresses
584 gpu_pointer_to_matrix = data & 0xFFFFFFFC;
587 gpu_data_organization = data;
590 gpu_pc = data; /*WriteLog("setting gpu pc to 0x%.8x\n",gpu_pc);*/
594 uint32 gpu_was_running = GPU_RUNNING;
596 // data &= (~0x07C0); // disable writes to irq pending
597 data &= (~0xF7C0); // Disable writes to INT_LAT0-4 & TOM version number
600 WriteLog("gpu pc is 0x%.8x\n",gpu_pc);
604 // check for GPU->CPU interrupt
607 // WriteLog("GPU->CPU interrupt\n");
608 if (tom_irq_enabled(IRQ_GPU))
610 if ((tom_irq_enabled(IRQ_GPU)) && (jaguar_interrupt_handler_is_valid(64)))
612 tom_set_pending_gpu_int();
613 // s68000interrupt(7,64);
614 // s68000flushInterrupts();
615 m68k_set_irq(7); // Set 68000 NMI
616 gpu_releaseTimeslice();
619 uint32 addr=jaguar_word_read(((IRQ_GPU+64)<<2)+0);
621 addr|=jaguar_word_read(((IRQ_GPU+64)<<2)+2);
622 if ((addr)&&(jaguar_interrupt_handler_is_valid(IRQ_GPU+64)))
624 s68000interrupt(7,IRQ_GPU+64);
625 s68000flushInterrupts();
631 // check for CPU->GPU interrupt
634 //WriteLog("CPU->GPU interrupt\n");
635 gpu_set_irq_line(0, 1);
636 // s68000releaseTimeslice();
637 m68k_end_timeslice();
638 dsp_releaseTimeslice();
644 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
646 // gpu_control = (gpu_control & 0x107C0) | (data & (~0x107C0));
647 gpu_control = (gpu_control & 0x1F7C0) | (data & (~0x1F7C0));
649 // if gpu wasn't running but is now running, execute a few cycles
650 #ifndef GPU_SINGLE_STEPPING
651 if ((!gpu_was_running) && (GPU_RUNNING))
654 if (gpu_control & 0x18)
656 #endif // #ifndef GPU_SINGLE_STEPPING
658 WriteLog("Write to GPU CTRL: %08X ", data);
660 WriteLog("-- Starting to run at %08X...", gpu_pc);
662 #endif // #ifdef GPU_DEBUG
664 // gpu_dump_disassembly();
671 gpu_div_control = data;
673 // default: // unaligned long write
680 //This is done by the blitter...
681 //if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
682 // WriteLog("GPU(32): Writing %08X at %08X\n", data, offset);
683 //if ((offset >= 0x1FE020 && offset <= 0x1FE03F) || (offset >= 0x1FE820 && offset <= 0x1FE83F))
684 // WriteLog("GPU(32): Writing %08X at %08X\n", data, offset);
685 //if (offset >= 0xF02200 && offset <= 0xF0229F)
686 // WriteLog("GPU(32): Writing to blitter --> %08X at %08X\n", data, offset);
688 jaguar_word_write(offset, (data >> 16) & 0xFFFF);
689 jaguar_word_write(offset+2, data & 0xFFFF);
692 void gpu_update_register_banks(void)
695 int bank = (gpu_flags & 0x4000);
697 // WriteLog("gpu_update_register_banks at gpu pc 0x%.8x bank=%i iflag=%i\n",gpu_pc,bank?1:0,(gpu_flags&0x8)?1:0);
702 if ((!bank && (gpu_reg_bank_0 != gpu_reg)) || (bank && (gpu_reg_bank_1 != gpu_reg)))
704 // WriteLog("\tswitching to bank %i\n",bank?1:0);
705 for(int i=0; i<32; i++)
708 gpu_reg[i] = gpu_alternate_reg[i];
709 gpu_alternate_reg[i] = temp;
714 gpu_flag_z = gpu_alternate_flag_z;
715 gpu_alternate_flag_z = temp;
718 gpu_flag_n = gpu_alternate_flag_n;
719 gpu_alternate_flag_n = temp;
722 gpu_flag_c = gpu_alternate_flag_c;
723 gpu_alternate_flag_c = temp;
727 gpu_reg_bank_0 = gpu_reg;
728 gpu_reg_bank_1 = gpu_alternate_reg;
732 gpu_reg_bank_0 = gpu_alternate_reg;
733 gpu_reg_bank_1 = gpu_reg;
738 // WriteLog("\tnot switching banks\n");
742 void gpu_check_irqs(void)
744 int bits, mask, which = 0;
746 // get the active interrupt bits
747 bits = (gpu_control >> 6) & 0x1F;
748 bits |= (gpu_control >> 10) & 0x20;
750 // get the interrupt mask
751 mask = (gpu_flags >> 4) & 0x1F;
752 mask |= (gpu_flags >> 11) & 0x20;
754 // bail if nothing is available
759 // determine which interrupt
760 if (bits & 0x01) which = 0;
761 if (bits & 0x02) which = 1;
762 if (bits & 0x04) which = 2;
763 if (bits & 0x08) which = 3;
764 if (bits & 0x10) which = 4;
765 if (bits & 0x20) which = 5;
767 if (gpu_flags & 0x08)
771 WriteLog("GPU: generating irq %i\n", which);
773 // set the interrupt flag
775 gpu_update_register_banks();
777 // subqt #4,r31 ; pre-decrement stack pointer
778 // move pc,r30 ; address of interrupted code
779 // store r30,(r31) ; store return address
781 gpu_reg[30] = gpu_pc - 2;
782 gpu_long_write(gpu_reg[31], gpu_pc - 2);
784 // movei #service_address,r30 ; pointer to ISR entry
785 // jump (r30) ; jump to ISR
787 gpu_pc = GPU_WORK_RAM_BASE + (which * 0x10);
788 gpu_reg[30] = gpu_pc;
791 void gpu_set_irq_line(int irqline, int state)
794 WriteLog("GPU: setting irg line %i\n", irqline);
795 int mask = 0x40 << irqline;
796 gpu_control &= ~mask;
805 //TEMPORARY: Testing only!
811 memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work ram");
812 // gpu_ram_16=(uint16*)gpu_ram_8;
813 // gpu_ram_32=(uint32*)gpu_ram_8;
815 memory_malloc_secure((void **)&gpu_reg, 32*sizeof(int32), "GPU bank 0 regs");
816 memory_malloc_secure((void **)&gpu_alternate_reg, 32*sizeof(int32), "GPU bank 1 regs");
818 build_branch_condition_table();
822 //TEMPORARY: Testing only!
830 gpu_acc = 0x00000000;
831 gpu_remain = 0x00000000;
832 gpu_hidata = 0x00000000;
833 gpu_flags = 0x00040000;
834 gpu_matrix_control = 0x00000000;
835 gpu_pointer_to_matrix = 0x00000000;
836 gpu_data_organization = 0xFFFFFFFF;
837 gpu_control = 0x00012800; // Correctly sets this a TOM Rev. 2
838 gpu_div_control = 0x00000000;
841 for(int i=0; i<32; i++)
843 gpu_reg[i] = 0x00000000;
844 gpu_alternate_reg[i] = 0x00000000;
847 gpu_reg_bank_0 = gpu_reg;
848 gpu_reg_bank_1 = gpu_alternate_reg;
849 // gpu_reg_bank_1 = gpu_reg;
850 // gpu_reg_bank_0 = gpu_alternate_reg;
854 gpu_alternate_flag_z = 0;
855 gpu_alternate_flag_n = 0;
856 gpu_alternate_flag_c = 0;
858 memset(gpu_ram_8, 0xFF, 0x1000);
863 uint32 gpu_read_pc(void)
868 void gpu_reset_stats(void)
870 for(uint32 i=0; i<64; i++)
871 gpu_opcode_use[i] = 0;
872 WriteLog("--> GPU stats were reset!\n");
875 void gpu_dump_disassembly(void)
879 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
881 while (j <= 0xF03FFF)
884 j += dasmjag(JAGUAR_GPU, buffer, j);
885 WriteLog("\t%08X: %s\n", oldj, buffer);
889 void gpu_dump_registers(void)
891 WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
892 WriteLog("\nRegisters bank 0\n");
893 for(int j=0; j<8; j++)
895 WriteLog("\tr%2i = %08X r%2i = %08X r%2i = %08X r%2i = %08X\n",
896 (j << 2) + 0, gpu_reg[(j << 2) + 0],
897 (j << 2) + 1, gpu_reg[(j << 2) + 1],
898 (j << 2) + 2, gpu_reg[(j << 2) + 2],
899 (j << 2) + 3, gpu_reg[(j << 2) + 3]);
901 WriteLog("Registers bank 1\n");
902 for(int j=0; j<8; j++)
904 WriteLog("\tr%2i = %08X r%2i = %08X r%2i = %08X r%2i = %08X\n",
905 (j << 2) + 0, gpu_alternate_reg[(j << 2) + 0],
906 (j << 2) + 1, gpu_alternate_reg[(j << 2) + 1],
907 (j << 2) + 2, gpu_alternate_reg[(j << 2) + 2],
908 (j << 2) + 3, gpu_alternate_reg[(j << 2) + 3]);
912 void gpu_dump_memory(void)
914 WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
915 for(int i=0; i<0xFFF; i+=4)
916 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i, gpu_ram_8[i],
917 gpu_ram_8[i+1], gpu_ram_8[i+2], gpu_ram_8[i+3]);
922 WriteLog("GPU: stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
924 // get the active interrupt bits
925 int bits = (gpu_control >> 6) & 0x1F;
926 bits |= (gpu_control >> 10) & 0x20;
928 // get the interrupt mask
929 int mask = (gpu_flags >> 4) & 0x1F;
930 mask |= (gpu_flags >> 11) & 0x20;
933 WriteLog("GPU: ibits=0x%.8x imask=0x%.8x\n", bits, mask);
934 // WriteLog("\nregisters bank 0\n");
935 // for (int j=0;j<8;j++)
937 // WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
938 // (j<<2)+0,gpu_reg[(j<<2)+0],
939 // (j<<2)+1,gpu_reg[(j<<2)+1],
940 // (j<<2)+2,gpu_reg[(j<<2)+2],
941 // (j<<2)+3,gpu_reg[(j<<2)+3]);
944 // WriteLog("registers bank 1\n");
947 // WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
948 // (j<<2)+0,gpu_alternate_reg[(j<<2)+0],
949 // (j<<2)+1,gpu_alternate_reg[(j<<2)+1],
950 // (j<<2)+2,gpu_alternate_reg[(j<<2)+2],
951 // (j<<2)+3,gpu_alternate_reg[(j<<2)+3]);
954 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
955 static char buffer[512];
957 // for(int i=0; i<4096; i++)
958 while (j <= 0xF03FFF)
961 j += dasmjag(JAGUAR_GPU, buffer, j);
962 WriteLog("\t%08X: %s\n", oldj, buffer);
965 /* WriteLog("---[GPU code at %08X]---------------------------\n", gpu_pc);
967 for(int i=0; i<4096; i++)
970 j += dasmjag(JAGUAR_GPU, buffer, j);
971 WriteLog("\t%08X: %s\n", oldj, buffer);
974 WriteLog("\nGPU opcodes use:\n");
975 for(int i=0; i<64; i++)
977 if (gpu_opcode_use[i])
978 WriteLog("\t%17s %lu\n", gpu_opcode_str[i], gpu_opcode_use[i]);
982 memory_free(gpu_ram_8);
986 // Main GPU execution core
989 static int testCount = 1;
991 void gpu_exec(int32 cycles)
996 #ifdef GPU_SINGLE_STEPPING
997 if (gpu_control & 0x18)
1000 gpu_control &= ~0x10;
1004 gpu_releaseTimeSlice_flag = 0;
1007 while ((cycles > 0) && GPU_RUNNING)
1009 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1010 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1011 gpu_flag_n = (gpu_flag_n ? 1 : 0);
1013 uint16 opcode = gpu_word_read(gpu_pc);
1015 uint32 index = opcode >> 10;
1016 gpu_instruction = opcode; // Added for GPU #3...
1017 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1018 gpu_opcode_second_parameter = opcode & 0x1F;
1019 /*if (gpu_pc == 0xF03BE8)
1020 WriteLog("Start of OP frame write...\n");
1021 if (gpu_pc == 0xF03EEE)
1022 WriteLog("--> Writing BRANCH object ---\n");
1023 if (gpu_pc == 0xF03F62)
1024 WriteLog("--> Writing BITMAP object ***\n");//*/
1025 /*if (gpu_pc == 0xF03546)
1027 WriteLog("\n--> GPU PC: F03546\n");
1028 gpu_dump_registers();
1029 gpu_dump_disassembly();
1031 /*if (gpu_pc == 0xF033F6)
1033 WriteLog("\n--> GPU PC: F033F6\n");
1034 gpu_dump_registers();
1035 gpu_dump_disassembly();
1037 /*if (gpu_pc == 0xF033CC)
1039 WriteLog("\n--> GPU PC: F033CC\n");
1040 gpu_dump_registers();
1041 gpu_dump_disassembly();
1043 /*if (gpu_pc == 0xF033D6)
1045 WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1046 gpu_dump_registers();
1049 /*if (gpu_pc == 0xF033D8)
1051 WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1052 gpu_dump_registers();
1055 /*if (gpu_pc == 0xF0358E)
1057 WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1058 gpu_dump_registers();
1061 /*if (gpu_pc == 0xF034CA)
1063 WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1064 gpu_dump_registers();
1066 /*if (gpu_pc == 0xF034CA)
1068 len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1069 WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
1070 for(int i=0; i<len; i+=4)
1071 WriteLog(" %08X", gpu_long_read(gpu_reg[15]+i));
1073 for(int i=0; i<len; i+=4)
1074 WriteLog(" %08X", gpu_long_read(gpu_reg[14]+i));
1077 if (gpu_pc == 0xF034DE)
1079 WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n ", gpu_reg[14], gpu_reg[15]);
1080 for(int i=0; i<len; i+=4)
1081 WriteLog(" %08X", gpu_long_read(gpu_reg[15]+i));
1083 for(int i=0; i<len; i+=4)
1084 WriteLog(" %08X", gpu_long_read(gpu_reg[14]+i));
1086 for(int i=0; i<len; i+=4)
1087 WriteLog(" --------");
1089 for(int i=0; i<len; i+=4)
1090 WriteLog(" %08X", gpu_long_read(gpu_reg[9]+4+i));
1093 /*if (gpu_pc == 0xF035C8)
1095 WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1096 gpu_dump_registers();
1097 gpu_dump_disassembly();
1103 static char buffer[512];
1104 dasmjag(JAGUAR_GPU, buffer, gpu_pc);
1105 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
1107 //$E400 -> 1110 01 -> $39 -> 57
1110 gpu_opcode[index]();
1112 // gpu2_opcode[index]();
1114 //GPU #3 (Doesn't show ATARI logo! #1 & #2 do...)
1116 // gpu3_opcode[index]();
1119 //GPU: [00F03548] jr nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) -> --> JR: Branch taken.
1120 /*static bool firstTime = true;
1121 if (gpu_pc == 0xF03548 && firstTime)
1124 // firstTime = false;
1126 //static char buffer[512];
1128 //while (k<0xF0356C)
1131 //k += dasmjag(JAGUAR_GPU, buffer, k);
1132 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1134 // gpu_start_log = 1;
1136 //GPU: [00F0354C] jump nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1137 /*if (gpu_pc == 0xF0354C)
1138 gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1140 cycles -= gpu_opcode_cycles[index];
1141 gpu_opcode_use[index]++;
1143 WriteLog("(RM=%08X, RN=%08X)\n", RM, RN);//*/
1154 GPU opcodes use (offset punch--vertically below bad guy):
1176 load_r14_indexed 1183
1177 load_r15_indexed 1125
1180 store_r14_indexed 320
1188 static void gpu_opcode_jump(void)
1191 char * condition[32] =
1192 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1193 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1194 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1195 "???", "???", "???", "F" };
1196 WriteLog("%06X: JUMP %s, (R%02u) [NCZ:%u%u%u, R%02u=%08X] ", gpu_pc-2, condition[IMM_2], IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM);
1199 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1200 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1201 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1202 // KLUDGE: Used by BRANCH_CONDITION
1203 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1205 if (BRANCH_CONDITION(IMM_2))
1208 WriteLog("Branched!\n");
1211 WriteLog(" --> JUMP: Branch taken.\n");
1212 uint32 delayed_pc = RM;
1215 gpu_pc = delayed_pc;
1216 /* uint16 opcode = gpu_word_read(gpu_pc);
1217 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1218 gpu_opcode_second_parameter = opcode & 0x1F;
1220 gpu_pc = delayed_pc;
1221 gpu_opcode[opcode>>10]();//*/
1225 WriteLog("Branch NOT taken.\n");
1229 static void gpu_opcode_jr(void)
1232 char * condition[32] =
1233 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1234 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1235 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1236 "???", "???", "???", "F" };
1237 WriteLog("%06X: JR %s, %06X [NCZ:%u%u%u] ", gpu_pc-2, condition[IMM_2], gpu_pc+((IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1) * 2), gpu_flag_n, gpu_flag_c, gpu_flag_z);
1239 /* if (CONDITION(jaguar.op & 31))
1241 INT32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1242 UINT32 newpc = jaguar.PC + r1;
1244 jaguar.op = ROPCODE(jaguar.PC);
1246 (*jaguar.table[jaguar.op >> 10])();
1248 jaguar_icount -= 3; // 3 wait states guaranteed
1251 /* gpu_flag_n = (gpu_flag_n ? 1 : 0);
1252 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1253 gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1254 // KLUDGE: Used by BRANCH_CONDITION
1255 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1257 if (BRANCH_CONDITION(IMM_2))
1260 WriteLog("Branched!\n");
1263 WriteLog(" --> JR: Branch taken.\n");
1264 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1265 int32 delayed_pc = gpu_pc + (offset * 2);
1268 gpu_pc = delayed_pc;
1269 /* uint16 opcode = gpu_word_read(gpu_pc);
1270 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1271 gpu_opcode_second_parameter = opcode & 0x1F;
1273 gpu_pc = delayed_pc;
1274 gpu_opcode[opcode>>10]();//*/
1278 WriteLog("Branch NOT taken.\n");
1282 static void gpu_opcode_add(void)
1284 /* int dreg = jaguar.op & 31;
1285 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1286 UINT32 r2 = jaguar.r[dreg];
1287 UINT32 res = r2 + r1;
1288 jaguar.r[dreg] = res;
1289 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1291 UINT32 res = RN + RM;
1292 CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
1296 static void gpu_opcode_addc(void)
1299 WriteLog("%06X: ADDC R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
1301 /* int dreg = jaguar.op & 31;
1302 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1303 UINT32 r2 = jaguar.r[dreg];
1304 UINT32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1305 jaguar.r[dreg] = res;
1306 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1308 UINT32 res = RN + RM + gpu_flag_c;
1309 UINT32 carry = gpu_flag_c;
1310 // SET_ZNC_ADD(RN, RM, res); //???BUG???
1311 SET_ZNC_ADD(RN + carry, RM, res);
1312 // SET_ZNC_ADD(RN, RM + carry, res);
1315 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
1319 static void gpu_opcode_addq(void)
1321 /* int dreg = jaguar.op & 31;
1322 UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1323 UINT32 r2 = jaguar.r[dreg];
1324 UINT32 res = r2 + r1;
1325 jaguar.r[dreg] = res;
1326 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1328 UINT32 r1 = gpu_convert_zero[IMM_1];
1329 UINT32 res = RN + r1;
1330 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1334 static void gpu_opcode_addqt(void)
1336 RN += gpu_convert_zero[IMM_1];
1339 static void gpu_opcode_sub(void)
1341 /* int dreg = jaguar.op & 31;
1342 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1343 UINT32 r2 = jaguar.r[dreg];
1344 UINT32 res = r2 - r1;
1345 jaguar.r[dreg] = res;
1346 CLR_ZNC; SET_ZNC_SUB(r2,r1,res);*/
1348 UINT32 res = RN - RM;
1349 SET_ZNC_SUB(RN, RM, res);
1353 static void gpu_opcode_subc(void)
1356 WriteLog("%06X: SUBC R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
1358 UINT32 res = RN - RM - gpu_flag_c;
1359 UINT32 borrow = gpu_flag_c;
1360 // SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
1361 SET_ZNC_SUB(RN - borrow, RM, res);
1364 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
1368 static void gpu_opcode_subq(void)
1370 UINT32 r1 = gpu_convert_zero[IMM_1];
1371 UINT32 res = RN - r1;
1372 SET_ZNC_SUB(RN, r1, res);
1376 static void gpu_opcode_subqt(void)
1378 RN -= gpu_convert_zero[IMM_1];
1381 static void gpu_opcode_cmp(void)
1384 WriteLog("%06X: CMP R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
1386 UINT32 res = RN - RM;
1387 SET_ZNC_SUB(RN, RM, res);
1389 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1393 static void gpu_opcode_cmpq(void)
1396 WriteLog("%06X: CMPQ #%d, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, sqtable[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1398 static int32 sqtable[32] =
1399 { 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 };
1401 UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1402 UINT32 res = RN - r1;
1403 SET_ZNC_SUB(RN, r1, res);
1405 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1409 static void gpu_opcode_and(void)
1415 static void gpu_opcode_or(void)
1421 static void gpu_opcode_xor(void)
1427 static void gpu_opcode_not(void)
1433 static void gpu_opcode_move_pc(void)
1435 // Should be previous PC--this might not always be previous instruction!
1436 // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1440 static void gpu_opcode_sat8(void)
1442 RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
1446 static void gpu_opcode_sat16(void)
1448 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
1452 static void gpu_opcode_sat24(void)
1454 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
1458 static void gpu_opcode_store_r14_indexed(void)
1460 gpu_long_write(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN);
1463 static void gpu_opcode_store_r15_indexed(void)
1465 gpu_long_write(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN);
1468 static void gpu_opcode_load_r14_ri(void)
1470 RN = gpu_long_read(gpu_reg[14] + RM);
1473 static void gpu_opcode_load_r15_ri(void)
1475 RN = gpu_long_read(gpu_reg[15] + RM);
1478 static void gpu_opcode_store_r14_ri(void)
1480 #ifdef GPU_DIS_STORE14R
1481 WriteLog("%06X: STORE R%02u, (R14+R%02u) [NCZ:%u%u%u, R%02u=%08X, R14+R%02u=%08X]\n", gpu_pc-2, IMM_2, IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, IMM_1, RM+gpu_reg[14]);
1483 gpu_long_write(gpu_reg[14] + RM, RN);
1486 static void gpu_opcode_store_r15_ri(void)
1488 #ifdef GPU_DIS_STORE15R
1489 WriteLog("%06X: STORE R%02u, (R15+R%02u) [NCZ:%u%u%u, R%02u=%08X, R15+R%02u=%08X]\n", gpu_pc-2, IMM_2, IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, IMM_1, RM+gpu_reg[15]);
1491 gpu_long_write(gpu_reg[15] + RM, RN);
1494 static void gpu_opcode_nop(void)
1497 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", gpu_pc-2, gpu_flag_n, gpu_flag_c, gpu_flag_z);
1501 static void gpu_opcode_pack(void)
1505 if (RM == 0) // Pack
1506 RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
1508 RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
1511 static void gpu_opcode_storeb(void)
1514 // Would appear to be so...!
1515 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1516 gpu_long_write(RM, RN & 0xFF);
1518 jaguar_byte_write(RM, RN);
1521 static void gpu_opcode_storew(void)
1523 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1524 gpu_long_write(RM, RN & 0xFFFF);
1526 jaguar_word_write(RM, RN);
1529 static void gpu_opcode_store(void)
1531 gpu_long_write(RM, RN);
1534 static void gpu_opcode_storep(void)
1536 gpu_long_write(RM + 0, gpu_hidata);
1537 gpu_long_write(RM + 4, RN);
1540 static void gpu_opcode_loadb(void)
1542 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1543 RN = gpu_long_read(RM) & 0xFF;
1545 RN = jaguar_byte_read(RM);
1548 static void gpu_opcode_loadw(void)
1550 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1551 RN = gpu_long_read(RM) & 0xFFFF;
1553 RN = jaguar_word_read(RM);
1556 static void gpu_opcode_load(void)
1558 RN = gpu_long_read(RM);
1561 static void gpu_opcode_loadp(void)
1563 gpu_hidata = gpu_long_read(RM + 0);
1564 RN = gpu_long_read(RM + 4);
1567 static void gpu_opcode_load_r14_indexed(void)
1569 RN = gpu_long_read(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2));
1572 static void gpu_opcode_load_r15_indexed(void)
1574 RN = gpu_long_read(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2));
1577 static void gpu_opcode_movei(void)
1579 // This instruction is followed by 32-bit value in LSW / MSW format...
1580 RN = (uint32)gpu_word_read(gpu_pc) | ((uint32)gpu_word_read(gpu_pc + 2) << 16);
1584 static void gpu_opcode_moveta(void)
1589 static void gpu_opcode_movefa(void)
1594 static void gpu_opcode_move(void)
1599 static void gpu_opcode_moveq(void)
1604 static void gpu_opcode_resmac(void)
1609 static void gpu_opcode_imult(void)
1611 RN = (int16)RN * (int16)RM;
1615 static void gpu_opcode_mult(void)
1617 RN = (uint16)RM * (uint16)RN;
1621 static void gpu_opcode_bclr(void)
1623 UINT32 res = RN & ~(1 << IMM_1);
1628 static void gpu_opcode_btst(void)
1630 gpu_flag_z = (~RN >> IMM_1) & 1;
1633 static void gpu_opcode_bset(void)
1635 UINT32 res = RN | (1 << IMM_1);
1640 static void gpu_opcode_imacn(void)
1642 uint32 res = (int16)RM * (int16)(RN);
1646 static void gpu_opcode_mtoi(void)
1649 uint32 res = RN = (((INT32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
1653 static void gpu_opcode_normi(void)
1660 while ((_RM & 0xFFC00000) == 0)
1665 while ((_RM & 0xFF800000) != 0)
1675 static void gpu_opcode_mmult(void)
1677 int count = gpu_matrix_control & 0x0F; // Matrix width
1678 uint32 addr = gpu_pointer_to_matrix; // In the GPU's RAM
1682 if (gpu_matrix_control & 0x10) // Column stepping
1684 for(int i=0; i<count; i++)
1688 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
1690 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
1692 int16 b = ((int16)gpu_word_read(addr + 2));
1697 else // Row stepping
1699 for(int i=0; i<count; i++)
1703 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
1705 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
1707 int16 b = ((int16)gpu_word_read(addr + 2));
1712 RN = res = (int32)accum;
1713 // carry flag to do (out of the last add)
1717 static void gpu_opcode_abs(void)
1720 WriteLog("%06X: ABS R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1722 gpu_flag_c = RN >> 31;
1723 if (RN == 0x80000000)
1724 //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
1725 gpu_flag_n = 1, gpu_flag_z = 0;
1730 gpu_flag_n = 0; SET_FLAG_Z(RN);
1733 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1737 static void gpu_opcode_div(void) // RN / RM
1740 WriteLog("%06X: DIV R%02u, R%02u (%s) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, (gpu_div_control & 0x01 ? "16.16" : "32"), gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
1742 // NOTE: remainder is NOT calculated correctly here!
1743 // The original tried to get it right by checking to see if the
1744 // remainder was negative, but that's too late...
1745 // The code there should do it now, but I'm not 100% sure...
1749 if (gpu_div_control & 0x01) // 16.16 division
1751 RN = ((UINT64)RN << 16) / RM;
1752 gpu_remain = ((UINT64)RN << 16) % RM;
1757 gpu_remain = RN % RM;
1760 if ((gpu_remain - RM) & 0x80000000) // If the result would have been negative...
1761 gpu_remain -= RM; // Then make it negative!
1771 if (gpu_div_control & 1)
1773 gpu_remain = (((uint64)_RN) << 16) % _RM;
1774 if (gpu_remain&0x80000000)
1776 RN = (((uint64)_RN) << 16) / _RM;
1780 gpu_remain = _RN % _RM;
1781 if (gpu_remain&0x80000000)
1789 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] Remainder: %08X\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN, gpu_remain);
1793 static void gpu_opcode_imultn(void)
1795 uint32 res = (int32)((int16)RN * (int16)RM);
1796 gpu_acc = (int32)res;
1801 static void gpu_opcode_neg(void)
1804 SET_ZNC_SUB(0, RN, res);
1808 static void gpu_opcode_shlq(void)
1810 /* int dreg = jaguar.op & 31;
1811 INT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1812 UINT32 r2 = jaguar.r[dreg];
1813 UINT32 res = r2 << (32 - r1);
1814 jaguar.r[dreg] = res;
1815 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 >> 30) & 2;*/
1818 WriteLog("%06X: SHLQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, 32 - IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1820 // Was a bug here...
1821 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
1822 INT32 r1 = 32 - IMM_1;
1823 UINT32 res = RN << r1;
1824 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
1827 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1831 static void gpu_opcode_shrq(void)
1833 /* int dreg = jaguar.op & 31;
1834 INT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1835 UINT32 r2 = jaguar.r[dreg];
1836 UINT32 res = r2 >> r1;
1837 jaguar.r[dreg] = res;
1838 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 << 1) & 2;*/
1841 WriteLog("%06X: SHRQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1843 INT32 r1 = gpu_convert_zero[IMM_1];
1844 UINT32 res = RN >> r1;
1845 SET_ZN(res); gpu_flag_c = RN & 1;
1848 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1852 static void gpu_opcode_ror(void)
1854 /* int dreg = jaguar.op & 31;
1855 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31] & 31;
1856 UINT32 r2 = jaguar.r[dreg];
1857 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
1858 jaguar.r[dreg] = res;
1859 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 >> 30) & 2;*/
1862 WriteLog("%06X: ROR R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
1864 UINT32 r1 = RM & 0x1F;
1865 UINT32 res = (RN >> r1) | (RN << (32 - r1));
1866 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
1869 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
1873 static void gpu_opcode_rorq(void)
1875 /* int dreg = jaguar.op & 31;
1876 UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1877 UINT32 r2 = jaguar.r[dreg];
1878 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
1879 jaguar.r[dreg] = res;
1880 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 >> 30) & 2;*/
1883 WriteLog("%06X: RORQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1885 UINT32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
1887 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
1889 SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
1891 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1895 static void gpu_opcode_sha(void)
1897 /* int dreg = jaguar.op & 31;
1898 INT32 r1 = (INT32)jaguar.r[(jaguar.op >> 5) & 31];
1899 UINT32 r2 = jaguar.r[dreg];
1905 res = (r1 <= -32) ? 0 : (r2 << -r1);
1906 jaguar.FLAGS |= (r2 >> 30) & 2;
1910 res = (r1 >= 32) ? ((INT32)r2 >> 31) : ((INT32)r2 >> r1);
1911 jaguar.FLAGS |= (r2 << 1) & 2;
1913 jaguar.r[dreg] = res;
1917 WriteLog("%06X: SHA R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
1923 res = ((INT32)RM <= -32) ? 0 : (RN << -(INT32)RM);
1924 gpu_flag_c = RN >> 31;
1928 res = ((INT32)RM >= 32) ? ((INT32)RN >> 31) : ((INT32)RN >> (INT32)RM);
1929 gpu_flag_c = RN & 0x01;
1934 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
1937 /* int32 sRM=(int32)RM;
1943 if (shift>=32) shift=32;
1944 gpu_flag_c=(_RN&0x80000000)>>31;
1954 if (shift>=32) shift=32;
1958 _RN=((int32)_RN)>>1;
1967 static void gpu_opcode_sharq(void)
1969 /* int dreg = jaguar.op & 31;
1970 INT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1971 UINT32 r2 = jaguar.r[dreg];
1972 UINT32 res = (INT32)r2 >> r1;
1973 jaguar.r[dreg] = res;
1974 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 << 1) & 2;*/
1976 #ifdef GPU_DIS_SHARQ
1977 WriteLog("%06X: SHARQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1979 UINT32 res = (INT32)RN >> gpu_convert_zero[IMM_1];
1980 SET_ZN(res); gpu_flag_c = RN & 0x01;
1982 #ifdef GPU_DIS_SHARQ
1983 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1987 /* uint32 shift = gpu_convert_zero[IMM_1];
1990 gpu_flag_c = (_RN & 0x01);
1993 _RN = ((int32)_RN) >> 1;
2001 static void gpu_opcode_sh(void)
2004 WriteLog("%06X: SH R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
2006 if (RM & 0x80000000) // Shift left
2008 gpu_flag_c = RN >> 31;
2009 RN = ((int32)RM <= -32 ? 0 : RN << -(int32)RM);
2013 gpu_flag_c = RN & 0x01;
2014 RN = (RM >= 32 ? 0 : RN >> RM);
2018 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
2022 //Temporary: Testing only!