5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Extensive cleanups/rewrites by James L. Hammons
9 #include <SDL.h> // Used only for SDL_GetTicks...
15 // Disassembly definitions
20 #define DSP_DIS_ADDQMOD
30 #define DSP_DIS_IMULTN
31 #define DSP_DIS_ILLEGAL
35 #define DSP_DIS_LOAD14I
36 #define DSP_DIS_LOAD14R
37 #define DSP_DIS_LOAD15I
38 #define DSP_DIS_LOAD15R
44 #define DSP_DIS_MOVEFA
45 #define DSP_DIS_MOVETA
51 #define DSP_DIS_RESMAC
58 #define DSP_DIS_STORE14I
59 #define DSP_DIS_STORE15I
60 #define DSP_DIS_STOREB
61 #define DSP_DIS_STOREW
68 //bool doDSPDis = false;
104 + load_r15_indexed 284500
106 + store_r15_indexed 47416
110 + load_r14_ri 1229448
113 // DSP flags (old--have to get rid of this crap)
115 #define CINT0FLAG 0x00200
116 #define CINT1FLAG 0x00400
117 #define CINT2FLAG 0x00800
118 #define CINT3FLAG 0x01000
119 #define CINT4FLAG 0x02000
120 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
121 #define CINT5FLAG 0x20000 /* DSP only */
125 #define ZERO_FLAG 0x00001
126 #define CARRY_FLAG 0x00002
127 #define NEGA_FLAG 0x00004
128 #define IMASK 0x00008
129 #define INT_ENA0 0x00010
130 #define INT_ENA1 0x00020
131 #define INT_ENA2 0x00040
132 #define INT_ENA3 0x00080
133 #define INT_ENA4 0x00100
134 #define INT_CLR0 0x00200
135 #define INT_CLR1 0x00400
136 #define INT_CLR2 0x00800
137 #define INT_CLR3 0x01000
138 #define INT_CLR4 0x02000
139 #define REGPAGE 0x04000
140 #define DMAEN 0x08000
141 #define INT_ENA5 0x10000
142 #define INT_CLR5 0x20000
146 #define DSPGO 0x00001
147 #define CPUINT 0x00002
148 #define DSPINT0 0x00004
149 #define SINGLE_STEP 0x00008
150 #define SINGLE_GO 0x00010
152 #define INT_LAT0 0x00040
153 #define INT_LAT1 0x00080
154 #define INT_LAT2 0x00100
155 #define INT_LAT3 0x00200
156 #define INT_LAT4 0x00400
157 #define BUS_HOG 0x00800
158 #define VERSION 0x0F000
159 #define INT_LAT5 0x10000
161 extern uint32 jaguar_mainRom_crc32;
163 // Is opcode 62 *really* a NOP? Seems like it...
164 static void dsp_opcode_abs(void);
165 static void dsp_opcode_add(void);
166 static void dsp_opcode_addc(void);
167 static void dsp_opcode_addq(void);
168 static void dsp_opcode_addqmod(void);
169 static void dsp_opcode_addqt(void);
170 static void dsp_opcode_and(void);
171 static void dsp_opcode_bclr(void);
172 static void dsp_opcode_bset(void);
173 static void dsp_opcode_btst(void);
174 static void dsp_opcode_cmp(void);
175 static void dsp_opcode_cmpq(void);
176 static void dsp_opcode_div(void);
177 static void dsp_opcode_imacn(void);
178 static void dsp_opcode_imult(void);
179 static void dsp_opcode_imultn(void);
180 static void dsp_opcode_jr(void);
181 static void dsp_opcode_jump(void);
182 static void dsp_opcode_load(void);
183 static void dsp_opcode_loadb(void);
184 static void dsp_opcode_loadw(void);
185 static void dsp_opcode_load_r14_indexed(void);
186 static void dsp_opcode_load_r14_ri(void);
187 static void dsp_opcode_load_r15_indexed(void);
188 static void dsp_opcode_load_r15_ri(void);
189 static void dsp_opcode_mirror(void);
190 static void dsp_opcode_mmult(void);
191 static void dsp_opcode_move(void);
192 static void dsp_opcode_movei(void);
193 static void dsp_opcode_movefa(void);
194 static void dsp_opcode_move_pc(void);
195 static void dsp_opcode_moveq(void);
196 static void dsp_opcode_moveta(void);
197 static void dsp_opcode_mtoi(void);
198 static void dsp_opcode_mult(void);
199 static void dsp_opcode_neg(void);
200 static void dsp_opcode_nop(void);
201 static void dsp_opcode_normi(void);
202 static void dsp_opcode_not(void);
203 static void dsp_opcode_or(void);
204 static void dsp_opcode_resmac(void);
205 static void dsp_opcode_ror(void);
206 static void dsp_opcode_rorq(void);
207 static void dsp_opcode_xor(void);
208 static void dsp_opcode_sat16s(void);
209 static void dsp_opcode_sat32s(void);
210 static void dsp_opcode_sh(void);
211 static void dsp_opcode_sha(void);
212 static void dsp_opcode_sharq(void);
213 static void dsp_opcode_shlq(void);
214 static void dsp_opcode_shrq(void);
215 static void dsp_opcode_store(void);
216 static void dsp_opcode_storeb(void);
217 static void dsp_opcode_storew(void);
218 static void dsp_opcode_store_r14_indexed(void);
219 static void dsp_opcode_store_r14_ri(void);
220 static void dsp_opcode_store_r15_indexed(void);
221 static void dsp_opcode_store_r15_ri(void);
222 static void dsp_opcode_sub(void);
223 static void dsp_opcode_subc(void);
224 static void dsp_opcode_subq(void);
225 static void dsp_opcode_subqmod(void);
226 static void dsp_opcode_subqt(void);
228 uint8 dsp_opcode_cycles[64] =
248 void (* dsp_opcode[64])() =
250 dsp_opcode_add, dsp_opcode_addc, dsp_opcode_addq, dsp_opcode_addqt,
251 dsp_opcode_sub, dsp_opcode_subc, dsp_opcode_subq, dsp_opcode_subqt,
252 dsp_opcode_neg, dsp_opcode_and, dsp_opcode_or, dsp_opcode_xor,
253 dsp_opcode_not, dsp_opcode_btst, dsp_opcode_bset, dsp_opcode_bclr,
254 dsp_opcode_mult, dsp_opcode_imult, dsp_opcode_imultn, dsp_opcode_resmac,
255 dsp_opcode_imacn, dsp_opcode_div, dsp_opcode_abs, dsp_opcode_sh,
256 dsp_opcode_shlq, dsp_opcode_shrq, dsp_opcode_sha, dsp_opcode_sharq,
257 dsp_opcode_ror, dsp_opcode_rorq, dsp_opcode_cmp, dsp_opcode_cmpq,
258 dsp_opcode_subqmod, dsp_opcode_sat16s, dsp_opcode_move, dsp_opcode_moveq,
259 dsp_opcode_moveta, dsp_opcode_movefa, dsp_opcode_movei, dsp_opcode_loadb,
260 dsp_opcode_loadw, dsp_opcode_load, dsp_opcode_sat32s, dsp_opcode_load_r14_indexed,
261 dsp_opcode_load_r15_indexed, dsp_opcode_storeb, dsp_opcode_storew, dsp_opcode_store,
262 dsp_opcode_mirror, dsp_opcode_store_r14_indexed, dsp_opcode_store_r15_indexed, dsp_opcode_move_pc,
263 dsp_opcode_jump, dsp_opcode_jr, dsp_opcode_mmult, dsp_opcode_mtoi,
264 dsp_opcode_normi, dsp_opcode_nop, dsp_opcode_load_r14_ri, dsp_opcode_load_r15_ri,
265 dsp_opcode_store_r14_ri, dsp_opcode_store_r15_ri, dsp_opcode_nop, dsp_opcode_addqmod,
268 uint32 dsp_opcode_use[64];
270 char * dsp_opcode_str[65]=
272 "add", "addc", "addq", "addqt",
273 "sub", "subc", "subq", "subqt",
274 "neg", "and", "or", "xor",
275 "not", "btst", "bset", "bclr",
276 "mult", "imult", "imultn", "resmac",
277 "imacn", "div", "abs", "sh",
278 "shlq", "shrq", "sha", "sharq",
279 "ror", "rorq", "cmp", "cmpq",
280 "subqmod", "sat16s", "move", "moveq",
281 "moveta", "movefa", "movei", "loadb",
282 "loadw", "load", "sat32s", "load_r14_indexed",
283 "load_r15_indexed", "storeb", "storew", "store",
284 "mirror", "store_r14_indexed","store_r15_indexed","move_pc",
285 "jump", "jr", "mmult", "mtoi",
286 "normi", "nop", "load_r14_ri", "load_r15_ri",
287 "store_r14_ri", "store_r15_ri", "illegal", "addqmod",
292 static uint64 dsp_acc; // 40 bit register, NOT 32!
293 static uint32 dsp_remain;
294 static uint32 dsp_modulo;
295 static uint32 dsp_flags;
296 static uint32 dsp_matrix_control;
297 static uint32 dsp_pointer_to_matrix;
298 static uint32 dsp_data_organization;
300 static uint32 dsp_div_control;
301 static uint8 dsp_flag_z, dsp_flag_n, dsp_flag_c;
302 static uint32 * dsp_reg, * dsp_alternate_reg;
303 static uint32 * dsp_reg_bank_0, * dsp_reg_bank_1;
305 static uint32 dsp_opcode_first_parameter;
306 static uint32 dsp_opcode_second_parameter;
308 #define DSP_RUNNING (dsp_control & 0x01)
310 #define RM dsp_reg[dsp_opcode_first_parameter]
311 #define RN dsp_reg[dsp_opcode_second_parameter]
312 #define ALTERNATE_RM dsp_alternate_reg[dsp_opcode_first_parameter]
313 #define ALTERNATE_RN dsp_alternate_reg[dsp_opcode_second_parameter]
314 #define IMM_1 dsp_opcode_first_parameter
315 #define IMM_2 dsp_opcode_second_parameter
317 #define CLR_Z (dsp_flag_z = 0)
318 #define CLR_ZN (dsp_flag_z = dsp_flag_n = 0)
319 #define CLR_ZNC (dsp_flag_z = dsp_flag_n = dsp_flag_c = 0)
320 #define SET_Z(r) (dsp_flag_z = ((r) == 0))
321 #define SET_N(r) (dsp_flag_n = (((UINT32)(r) >> 31) & 0x01))
322 #define SET_C_ADD(a,b) (dsp_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
323 #define SET_C_SUB(a,b) (dsp_flag_c = ((UINT32)(b) > (UINT32)(a)))
324 #define SET_ZN(r) SET_N(r); SET_Z(r)
325 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
326 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
328 uint32 dsp_convert_zero[32] = { 32,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 };
329 uint8 * dsp_branch_condition_table = NULL;
330 static uint16 * mirror_table = NULL;
331 static uint8 * dsp_ram_8 = NULL;
333 #define BRANCH_CONDITION(x) dsp_branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
335 static uint32 dsp_in_exec = 0;
336 static uint32 dsp_releaseTimeSlice_flag = 0;
340 // Private function prototypes
342 void DSPDumpRegisters(void);
343 void DSPDumpDisassembly(void);
344 void FlushDSPPipeline(void);
347 void dsp_reset_stats(void)
349 for(int i=0; i<64; i++)
350 dsp_opcode_use[i] = 0;
353 void dsp_releaseTimeslice(void)
355 //This does absolutely nothing!!! !!! FIX !!!
356 dsp_releaseTimeSlice_flag = 1;
359 void dsp_build_branch_condition_table(void)
361 // Allocate the mirror table
363 mirror_table = (uint16 *)malloc(65536 * sizeof(mirror_table[0]));
365 // Fill in the mirror table
367 for(int i=0; i<65536; i++)
368 mirror_table[i] = ((i >> 15) & 0x0001) | ((i >> 13) & 0x0002) |
369 ((i >> 11) & 0x0004) | ((i >> 9) & 0x0008) |
370 ((i >> 7) & 0x0010) | ((i >> 5) & 0x0020) |
371 ((i >> 3) & 0x0040) | ((i >> 1) & 0x0080) |
372 ((i << 1) & 0x0100) | ((i << 3) & 0x0200) |
373 ((i << 5) & 0x0400) | ((i << 7) & 0x0800) |
374 ((i << 9) & 0x1000) | ((i << 11) & 0x2000) |
375 ((i << 13) & 0x4000) | ((i << 15) & 0x8000);
377 if (!dsp_branch_condition_table)
379 dsp_branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(dsp_branch_condition_table[0]));
381 // Fill in the condition table
382 if (dsp_branch_condition_table)
384 for(int i=0; i<8; i++)
386 for(int j=0; j<32; j++)
393 if (!(i & ZERO_FLAG))
396 if (i & (CARRY_FLAG << (j >> 4)))
399 if (!(i & (CARRY_FLAG << (j >> 4))))
401 dsp_branch_condition_table[i * 32 + j] = result;
408 uint8 DSPReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
410 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
411 WriteLog("DSP: ReadByte--Attempt to read from DSP register file by %s!\n", whoName[who]);
413 // if ((offset==0xF1CFE0)||(offset==0xF1CFE2))
416 /* if ((jaguar_mainRom_crc32==0xbfd751a4)||(jaguar_mainRom_crc32==0x053efaf9))
418 if (offset==0xF1CFE0)
421 if (offset >= DSP_WORK_RAM_BASE && offset <= (DSP_WORK_RAM_BASE + 0x1FFF))
422 return dsp_ram_8[offset - DSP_WORK_RAM_BASE];
424 if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
426 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
428 if ((offset&0x03)==0)
431 if ((offset&0x03)==1)
432 return((data>>16)&0xff);
434 if ((offset&0x03)==2)
435 return((data>>8)&0xff);
437 if ((offset&0x03)==3)
441 return JaguarReadByte(offset, who);
444 uint16 DSPReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
446 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
447 WriteLog("DSP: ReadWord--Attempt to read from DSP register file by %s!\n", whoName[who]);
449 offset &= 0xFFFFFFFE;
451 /* if (jaguar_mainRom_crc32==0xa74a97cd)
453 if (offset==0xF1A114) return(0x0000);
454 if (offset==0xF1A116) return(0x0000);
455 if (offset==0xF1B000) return(0x1234);
456 if (offset==0xF1B002) return(0x5678);
459 if (jaguar_mainRom_crc32==0x7ae20823)
461 if (offset==0xF1B9D8) return(0x0000);
462 if (offset==0xF1B9Da) return(0x0000);
463 if (offset==0xF1B2C0) return(0x0000);
464 if (offset==0xF1B2C2) return(0x0000);
467 // pour permettre à wolfenstein 3d de tourner sans le dsp
468 /* if ((offset==0xF1B0D0)||(offset==0xF1B0D2))
472 // pour permettre à nba jam de tourner sans le dsp
473 /* if (jaguar_mainRom_crc32==0x4faddb18)
475 if (offset==0xf1b2c0) return(0);
476 if (offset==0xf1b2c2) return(0);
477 if (offset==0xf1b240) return(0);
478 if (offset==0xf1b242) return(0);
479 if (offset==0xF1B340) return(0);
480 if (offset==0xF1B342) return(0);
481 if (offset==0xF1BAD8) return(0);
482 if (offset==0xF1BADA) return(0);
483 if (offset==0xF1B040) return(0);
484 if (offset==0xF1B042) return(0);
485 if (offset==0xF1B0C0) return(0);
486 if (offset==0xF1B0C2) return(0);
487 if (offset==0xF1B140) return(0);
488 if (offset==0xF1B142) return(0);
489 if (offset==0xF1B1C0) return(0);
490 if (offset==0xF1B1C2) return(0);
493 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE+0x1FFF)
495 offset -= DSP_WORK_RAM_BASE;
496 /* uint16 data = (((uint16)dsp_ram_8[offset])<<8)|((uint16)dsp_ram_8[offset+1]);
498 return GET16(dsp_ram_8, offset);
500 else if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
502 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
505 return data & 0xFFFF;
510 return JaguarReadWord(offset, who);
513 uint32 DSPReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
515 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
516 WriteLog("DSP: ReadLong--Attempt to read from DSP register file by %s!\n", whoName[who]);
519 offset &= 0xFFFFFFFC;
520 /*if (offset == 0xF1BCF4)
522 WriteLog("DSPReadLong: Reading from 0xF1BCF4... -> %08X [%02X %02X %02X %02X][%04X %04X]\n", GET32(dsp_ram_8, 0x0CF4), dsp_ram_8[0x0CF4], dsp_ram_8[0x0CF5], dsp_ram_8[0x0CF6], dsp_ram_8[0x0CF7], JaguarReadWord(0xF1BCF4, DSP), JaguarReadWord(0xF1BCF6, DSP));
523 DSPDumpDisassembly();
525 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
527 offset -= DSP_WORK_RAM_BASE;
528 return GET32(dsp_ram_8, offset);
530 //NOTE: Didn't return DSP_ACCUM!!!
531 //Mebbe it's not 'spose to! Yes, it is!
532 if (offset >= DSP_CONTROL_RAM_BASE && offset <= DSP_CONTROL_RAM_BASE + 0x23)
537 case 0x00: /*dsp_flag_c?(dsp_flag_c=1):(dsp_flag_c=0);
538 dsp_flag_z?(dsp_flag_z=1):(dsp_flag_z=0);
539 dsp_flag_n?(dsp_flag_n=1):(dsp_flag_n=0);*/
541 dsp_flags = (dsp_flags & 0xFFFFFFF8) | (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
542 return dsp_flags & 0xFFFFC1FF;
543 case 0x04: return dsp_matrix_control;
544 case 0x08: return dsp_pointer_to_matrix;
545 case 0x0C: return dsp_data_organization;
546 case 0x10: return dsp_pc;
547 case 0x14: return dsp_control;
548 case 0x18: return dsp_modulo;
549 case 0x1C: return dsp_remain;
551 return (int32)((int8)(dsp_acc >> 32)); // Top 8 bits of 40-bit accumulator, sign extended
553 // unaligned long read-- !!! FIX !!!
557 return JaguarReadLong(offset, who);
560 void DSPWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
562 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
563 WriteLog("DSP: WriteByte--Attempt to write to DSP register file by %s!\n", whoName[who]);
565 if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
567 offset -= DSP_WORK_RAM_BASE;
568 dsp_ram_8[offset] = data;
569 //This is rather stupid! !!! FIX !!!
570 /* if (dsp_in_exec == 0)
572 m68k_end_timeslice();
573 gpu_releaseTimeslice();
577 if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
579 uint32 reg = offset & 0x1C;
580 int bytenum = offset & 0x03;
582 if ((reg >= 0x1C) && (reg <= 0x1F))
583 dsp_div_control = (dsp_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
586 //This looks funky. !!! FIX !!!
587 uint32 old_data = DSPReadLong(offset&0xFFFFFFC, who);
588 bytenum = 3 - bytenum; // convention motorola !!!
589 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
590 DSPWriteLong(offset & 0xFFFFFFC, old_data, who);
594 // WriteLog("dsp: writing %.2x at 0x%.8x\n",data,offset);
595 //Should this *ever* happen??? Shouldn't we be saying "unknown" here???
596 JaguarWriteByte(offset, data, who);
599 void DSPWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
601 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
602 WriteLog("DSP: WriteWord--Attempt to write to DSP register file by %s!\n", whoName[who]);
603 offset &= 0xFFFFFFFE;
604 /*if (offset == 0xF1BCF4)
606 WriteLog("DSPWriteWord: Writing to 0xF1BCF4... %04X -> %04X\n", GET16(dsp_ram_8, 0x0CF4), data);
608 // WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset);
609 if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
611 offset -= DSP_WORK_RAM_BASE;
612 dsp_ram_8[offset] = data >> 8;
613 dsp_ram_8[offset+1] = data & 0xFF;
614 //This is rather stupid! !!! FIX !!!
615 /* if (dsp_in_exec == 0)
617 // WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset+DSP_WORK_RAM_BASE);
618 m68k_end_timeslice();
619 gpu_releaseTimeslice();
623 else if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
625 if ((offset & 0x1C) == 0x1C)
628 dsp_div_control = (dsp_div_control&0xffff0000)|(data&0xffff);
630 dsp_div_control = (dsp_div_control&0xffff)|((data&0xffff)<<16);
634 uint32 old_data = DSPReadLong(offset & 0xffffffc, who);
636 old_data = (old_data&0xffff0000)|(data&0xffff);
638 old_data = (old_data&0xffff)|((data&0xffff)<<16);
639 DSPWriteLong(offset & 0xffffffc, old_data, who);
644 JaguarWriteWord(offset, data, who);
647 //bool badWrite = false;
648 void DSPWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
650 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
651 WriteLog("DSP: WriteLong--Attempt to write to DSP register file by %s!\n", whoName[who]);
653 offset &= 0xFFFFFFFC;
654 /*if (offset == 0xF1BCF4)
656 WriteLog("DSPWriteLong: Writing to 0xF1BCF4... %08X -> %08X\n", GET32(dsp_ram_8, 0x0CF4), data);
658 // WriteLog("dsp: writing %.8x at 0x%.8x\n",data,offset);
659 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
661 /*if (offset == 0xF1BE2C)
663 WriteLog("DSP: %s is writing %08X at location 0xF1BE2C (DSP_PC: %08X)...\n", whoName[who], data, dsp_pc - 2);
665 offset -= DSP_WORK_RAM_BASE;
666 SET32(dsp_ram_8, offset, data);
669 else if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
677 WriteLog("DSP: Writing %08X to DSP_FLAGS by %s...\n", data, whoName[who]);
679 bool IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
681 dsp_flag_z = dsp_flags & 0x01;
682 dsp_flag_c = (dsp_flags >> 1) & 0x01;
683 dsp_flag_n = (dsp_flags >> 2) & 0x01;
684 DSPUpdateRegisterBanks();
685 dsp_control &= ~((dsp_flags & CINT04FLAGS) >> 3);
686 dsp_control &= ~((dsp_flags & CINT5FLAG) >> 1);
687 if (IMASKCleared) // If IMASK was cleared,
690 WriteLog("DSP: Finished interrupt.\n");
692 DSPHandleIRQs(); // see if any other interrupts need servicing!
699 dsp_matrix_control = data;
702 // According to JTRM, only lines 2-11 are adressable, the rest being
703 // hardwired to $F1Bxxx.
704 dsp_pointer_to_matrix = 0xF1B000 | (data & 0x000FFC);
707 dsp_data_organization = data;
712 WriteLog("DSP: Setting DSP PC to %08X by %s%s\n", dsp_pc, whoName[who], (DSP_RUNNING ? " (DSP is RUNNING!)" : ""));//*/
717 // uint32 dsp_was_running = DSP_RUNNING;
718 // Check for DSP -> CPU interrupt
721 // WriteLog("DSP: DSP -> CPU interrupt\n");
723 // Why do we check for a valid handler at 64? Isn't that the Jag programmer's responsibility?
724 if (JERRYIRQEnabled(IRQ2_DSP) && jaguar_interrupt_handler_is_valid(64))
726 JERRYSetPendingIRQ(IRQ2_DSP);
727 dsp_releaseTimeslice();
728 m68k_set_irq(7); // Set 68000 NMI...
732 // Check for CPU -> DSP interrupt
736 WriteLog("DSP: CPU -> DSP interrupt\n");
738 m68k_end_timeslice();
739 gpu_releaseTimeslice();
740 DSPSetIRQLine(DSPIRQ_CPU, ASSERT_LINE);
744 if (data & SINGLE_STEP)
746 // WriteLog("DSP: Asked to perform a single step (single step is %senabled)\n", (data & 0x8 ? "" : "not "));
749 // Protect writes to VERSION and the interrupt latches...
750 uint32 mask = VERSION | INT_LAT0 | INT_LAT1 | INT_LAT2 | INT_LAT3 | INT_LAT4 | INT_LAT5;
751 dsp_control = (dsp_control & mask) | (data & ~mask);
753 // if dsp wasn't running but is now running
754 // execute a few cycles
755 //This is just plain wrong, wrong, WRONG!
756 #ifndef DSP_SINGLE_STEPPING
757 /* if (!dsp_was_running && DSP_RUNNING)
762 //This is WRONG! !!! FIX !!!
763 if (dsp_control & 0x18)
767 WriteLog("Write to DSP CTRL: %08X ", data);
769 WriteLog(" --> Starting to run at %08X by %s...", dsp_pc, whoName[who]);
771 WriteLog(" --> Stopped by %s! (DSP PC: %08X)", whoName[who], dsp_pc);
774 //This isn't exactly right either--we don't know if it was the M68K or the GPU writing here...
775 // !!! FIX !!! [DONE]
779 m68k_end_timeslice();
781 gpu_releaseTimeslice();
784 //DSPDumpDisassembly();
792 dsp_div_control = data;
794 // default: // unaligned long read
800 //We don't have to break this up like this! We CAN do 32 bit writes!
801 // JaguarWriteWord(offset, (data>>16) & 0xFFFF, DSP);
802 // JaguarWriteWord(offset+2, data & 0xFFFF, DSP);
803 //if (offset > 0xF1FFFF)
805 JaguarWriteLong(offset, data, who);
809 // Update the DSP register file pointers depending on REGPAGE bit
811 void DSPUpdateRegisterBanks(void)
813 int bank = (dsp_flags & REGPAGE);
815 if (dsp_flags & IMASK)
816 bank = 0; // IMASK forces main bank to be bank 0
819 dsp_reg = dsp_reg_bank_1, dsp_alternate_reg = dsp_reg_bank_0;
821 dsp_reg = dsp_reg_bank_0, dsp_alternate_reg = dsp_reg_bank_1;
825 // Check for an handle any asserted DSP IRQs
827 void DSPHandleIRQs(void)
829 if (dsp_flags & IMASK) // Bail if we're already inside an interrupt
832 // Get the active interrupt bits (latches) & interrupt mask (enables)
833 uint32 bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
834 mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
836 // WriteLog("dsp: bits=%.2x mask=%.2x\n",bits,mask);
839 if (!bits) // Bail if nothing is enabled
842 int which = 0; // Determine which interrupt
857 WriteLog("DSP: Generating interrupt #%i...\n", which);
860 DSPUpdateRegisterBanks();
862 // subqt #4,r31 ; pre-decrement stack pointer
863 // move pc,r30 ; address of interrupted code
864 // store r30,(r31) ; store return address
866 DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
868 // movei #service_address,r30 ; pointer to ISR entry
869 // jump (r30) ; jump to ISR
871 dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
876 // Set the specified DSP IRQ line to a given state
878 void DSPSetIRQLine(int irqline, int state)
880 //NOTE: This doesn't take INT_LAT5 into account. !!! FIX !!!
881 uint32 mask = INT_LAT0 << irqline;
882 dsp_control &= ~mask; // Clear the latch bit
886 dsp_control |= mask; // Set the latch bit
893 memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
894 memory_malloc_secure((void **)&dsp_reg_bank_0, 32 * sizeof(int32), "DSP bank 0 regs");
895 memory_malloc_secure((void **)&dsp_reg_bank_1, 32 * sizeof(int32), "DSP bank 1 regs");
897 dsp_build_branch_condition_table();
904 dsp_acc = 0x00000000;
905 dsp_remain = 0x00000000;
906 dsp_modulo = 0xFFFFFFFF;
907 dsp_flags = 0x00040000;
908 dsp_matrix_control = 0x00000000;
909 dsp_pointer_to_matrix = 0x00000000;
910 dsp_data_organization = 0xFFFFFFFF;
911 dsp_control = 0x00002000; // Report DSP version 2
912 dsp_div_control = 0x00000000;
915 dsp_reg = dsp_reg_bank_0;
916 dsp_alternate_reg = dsp_reg_bank_1;
918 for(int i=0; i<32; i++)
919 dsp_reg[i] = dsp_alternate_reg[i] = 0x00000000;
924 memset(dsp_ram_8, 0xFF, 0x2000);
927 void DSPDumpDisassembly(void)
931 WriteLog("\n---[DSP code at 00F1B000]---------------------------\n");
933 while (j <= 0xF1CFFF)
936 j += dasmjag(JAGUAR_DSP, buffer, j);
937 WriteLog("\t%08X: %s\n", oldj, buffer);
941 void DSPDumpRegisters(void)
943 //Shoud add modulus, etc to dump here...
944 WriteLog("\n---[DSP flags: NCZ %d%d%d, DSP PC: %08X]------------\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_pc);
945 WriteLog("\nRegisters bank 0\n");
946 for(int j=0; j<8; j++)
948 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
949 (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
950 (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
951 (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
952 (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
954 WriteLog("Registers bank 1\n");
955 for(int j=0; j<8; j++)
957 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
958 (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
959 (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
960 (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
961 (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
968 WriteLog("DSP: Stopped at PC=%08X dsp_modulo=%08X (dsp %s running)\n", dsp_pc, dsp_modulo, (DSP_RUNNING ? "was" : "wasn't"));
969 WriteLog("DSP: %sin interrupt handler\n", (dsp_flags & IMASK ? "" : "not "));
971 // get the active interrupt bits
972 int bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F);
973 // get the interrupt mask
974 int mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
976 WriteLog("DSP: pending=%08X enabled=%08X\n", bits, mask);
977 WriteLog("\nRegisters bank 0\n");
978 for(int j=0; j<8; j++)
980 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
981 (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
982 (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
983 (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
984 (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
986 WriteLog("\nRegisters bank 1\n");
989 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
990 (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
991 (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
992 (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
993 (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
997 static char buffer[512];
998 j = DSP_WORK_RAM_BASE;
999 while (j <= 0xF1BFFF)
1002 j += dasmjag(JAGUAR_DSP, buffer, j);
1003 WriteLog("\t%08X: %s\n", oldj, buffer);
1006 WriteLog("DSP opcodes use:\n");
1009 if (dsp_opcode_use[i])
1010 WriteLog("\t%s %i\n", dsp_opcode_str[i], dsp_opcode_use[i]);
1013 memory_free(dsp_ram_8);
1017 // DSP execution core
1019 static bool R20Set = false, tripwire = false;
1020 static uint32 pcQueue[32], ptrPCQ = 0;
1021 void DSPExec(int32 cycles)
1023 /*HACKS!!! -> if (cycles != 1 && jaguar_mainRom_crc32 == 0xba74c3ed)
1024 dsp_check_if_i2s_interrupt_needed();*/
1026 #ifdef DSP_SINGLE_STEPPING
1027 if (dsp_control & 0x18)
1030 dsp_control &= ~0x10;
1033 //There is *no* good reason to do this here!
1035 dsp_releaseTimeSlice_flag = 0;
1038 while (cycles > 0 && DSP_RUNNING)
1042 WriteLog("\nDSP: Encountered bad write in Atari Synth module. PC=%08X, R15=%08X\n", dsp_pc, dsp_reg[15]);
1043 for(int i=0; i<80; i+=4)
1044 WriteLog(" %08X: %08X\n", dsp_reg[15]+i, JaguarReadLong(dsp_reg[15]+i));
1047 /*if (dsp_pc == 0xF1B55E)
1049 WriteLog("DSP: At $F1B55E--R15 = %08X at %u ms%s...\n", dsp_reg[15], SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1051 /*if (dsp_pc == 0xF1B7D2) // Start here???
1053 pcQueue[ptrPCQ++] = dsp_pc;
1055 uint16 opcode = DSPReadWord(dsp_pc, DSP);
1056 uint32 index = opcode >> 10;
1057 dsp_opcode_first_parameter = (opcode >> 5) & 0x1F;
1058 dsp_opcode_second_parameter = opcode & 0x1F;
1060 dsp_opcode[index]();
1061 dsp_opcode_use[index]++;
1062 cycles -= dsp_opcode_cycles[index];
1063 /*if (dsp_reg_bank_0[20] == 0xF1A100 & !R20Set)
1065 WriteLog("DSP: R20 set to $F1A100 at %u ms%s...\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1068 if (dsp_reg_bank_0[20] != 0xF1A100 && R20Set)
1070 WriteLog("DSP: R20 corrupted at %u ms from starting%s!\nAborting!\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1072 DSPDumpDisassembly();
1075 if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFE) && !tripwire)
1078 WriteLog("DSP: Jumping outside of DSP RAM at %u ms. Register dump:\n", SDL_GetTicks());
1081 WriteLog("\nBacktrace:\n");
1082 for(int i=0; i<32; i++)
1084 dasmjag(JAGUAR_DSP, buffer, pcQueue[(ptrPCQ + i) % 32]);
1085 WriteLog("\t%08X: %s\n", pcQueue[(ptrPCQ + i) % 32], buffer);
1095 // DSP opcode handlers
1098 // There is a problem here with interrupt handlers the JUMP and JR instructions that
1099 // can cause trouble because an interrupt can occur *before* the instruction following the
1100 // jump can execute... !!! FIX !!!
1101 static void dsp_opcode_jump(void)
1104 char * condition[32] =
1105 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1106 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1107 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1108 "???", "???", "???", "F" };
1110 WriteLog("%06X: JUMP %s, (R%02u) [NCZ:%u%u%u, R%02u=%08X] ", dsp_pc-2, condition[IMM_2], IMM_1, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM);
1113 /* dsp_flag_c=dsp_flag_c?1:0;
1114 dsp_flag_z=dsp_flag_z?1:0;
1115 dsp_flag_n=dsp_flag_n?1:0;*/
1116 // KLUDGE: Used by BRANCH_CONDITION
1117 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1119 if (BRANCH_CONDITION(IMM_2))
1123 WriteLog("Branched!\n");
1125 uint32 delayed_pc = RM;
1127 dsp_pc = delayed_pc;
1132 WriteLog("Branch NOT taken.\n");
1136 static void dsp_opcode_jr(void)
1139 char * condition[32] =
1140 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1141 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1142 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1143 "???", "???", "???", "F" };
1145 WriteLog("%06X: JR %s, %06X [NCZ:%u%u%u] ", dsp_pc-2, condition[IMM_2], dsp_pc+((IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1) * 2), dsp_flag_n, dsp_flag_c, dsp_flag_z);
1148 /* dsp_flag_c=dsp_flag_c?1:0;
1149 dsp_flag_z=dsp_flag_z?1:0;
1150 dsp_flag_n=dsp_flag_n?1:0;*/
1151 // KLUDGE: Used by BRANCH_CONDITION
1152 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1154 if (BRANCH_CONDITION(IMM_2))
1158 WriteLog("Branched!\n");
1160 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1161 int32 delayed_pc = dsp_pc + (offset * 2);
1163 dsp_pc = delayed_pc;
1168 WriteLog("Branch NOT taken.\n");
1172 static void dsp_opcode_add(void)
1176 WriteLog("%06X: ADD R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1178 UINT32 res = RN + RM;
1179 SET_ZNC_ADD(RN, RM, res);
1183 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1187 static void dsp_opcode_addc(void)
1191 WriteLog("%06X: ADDC R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1193 UINT32 res = RN + RM + dsp_flag_c;
1194 UINT32 carry = dsp_flag_c;
1195 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1196 SET_ZNC_ADD(RN + carry, RM, res);
1197 // SET_ZNC_ADD(RN, RM + carry, res);
1201 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1205 static void dsp_opcode_addq(void)
1209 WriteLog("%06X: ADDQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1211 UINT32 r1 = dsp_convert_zero[IMM_1];
1212 UINT32 res = RN + r1;
1213 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1217 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1221 static void dsp_opcode_sub(void)
1225 WriteLog("%06X: SUB R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1227 UINT32 res = RN - RM;
1228 SET_ZNC_SUB(RN, RM, res);
1232 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1236 static void dsp_opcode_subc(void)
1240 WriteLog("%06X: SUBC R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1242 UINT32 res = RN - RM - dsp_flag_c;
1243 UINT32 borrow = dsp_flag_c;
1244 SET_ZNC_SUB(RN - borrow, RM, res);
1248 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1252 static void dsp_opcode_subq(void)
1256 WriteLog("%06X: SUBQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1258 UINT32 r1 = dsp_convert_zero[IMM_1];
1259 UINT32 res = RN - r1;
1260 SET_ZNC_SUB(RN, r1, res);
1264 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1268 static void dsp_opcode_cmp(void)
1272 WriteLog("%06X: CMP R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1274 UINT32 res = RN - RM;
1275 SET_ZNC_SUB(RN, RM, res);
1278 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1282 static void dsp_opcode_cmpq(void)
1284 static int32 sqtable[32] =
1285 { 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 };
1288 WriteLog("%06X: CMPQ #%d, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, sqtable[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1290 UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1291 UINT32 res = RN - r1;
1292 SET_ZNC_SUB(RN, r1, res);
1295 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1299 static void dsp_opcode_and(void)
1303 WriteLog("%06X: AND R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1309 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1313 static void dsp_opcode_or(void)
1317 WriteLog("%06X: OR R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1323 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1327 static void dsp_opcode_xor(void)
1331 WriteLog("%06X: XOR R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1337 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1341 static void dsp_opcode_not(void)
1345 WriteLog("%06X: NOT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1351 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1355 static void dsp_opcode_move_pc(void)
1360 static void dsp_opcode_store_r14_indexed(void)
1362 #ifdef DSP_DIS_STORE14I
1364 WriteLog("%06X: STORE R%02u, (R14+$%02X) [NCZ:%u%u%u, R%02u=%08X, R14+$%02X=%08X]\n", dsp_pc-2, IMM_2, dsp_convert_zero[IMM_1] << 2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, dsp_convert_zero[IMM_1] << 2, dsp_reg[14]+(dsp_convert_zero[IMM_1] << 2));
1366 DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1369 static void dsp_opcode_store_r15_indexed(void)
1371 #ifdef DSP_DIS_STORE15I
1373 WriteLog("%06X: STORE R%02u, (R15+$%02X) [NCZ:%u%u%u, R%02u=%08X, R15+$%02X=%08X]\n", dsp_pc-2, IMM_2, dsp_convert_zero[IMM_1] << 2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, dsp_convert_zero[IMM_1] << 2, dsp_reg[15]+(dsp_convert_zero[IMM_1] << 2));
1375 DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1378 static void dsp_opcode_load_r14_ri(void)
1380 #ifdef DSP_DIS_LOAD14R
1382 WriteLog("%06X: LOAD (R14+R%02u), R%02u [NCZ:%u%u%u, R14+R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM+dsp_reg[14], IMM_2, RN);
1384 RN = DSPReadLong(dsp_reg[14] + RM, DSP);
1385 #ifdef DSP_DIS_LOAD14R
1387 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1391 static void dsp_opcode_load_r15_ri(void)
1393 #ifdef DSP_DIS_LOAD15R
1395 WriteLog("%06X: LOAD (R15+R%02u), R%02u [NCZ:%u%u%u, R15+R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM+dsp_reg[15], IMM_2, RN);
1397 RN = DSPReadLong(dsp_reg[15] + RM, DSP);
1398 #ifdef DSP_DIS_LOAD15R
1400 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1404 static void dsp_opcode_store_r14_ri(void)
1406 DSPWriteLong(dsp_reg[14] + RM, RN, DSP);
1409 static void dsp_opcode_store_r15_ri(void)
1411 DSPWriteLong(dsp_reg[15] + RM, RN, DSP);
1414 static void dsp_opcode_nop(void)
1418 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", dsp_pc-2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
1422 static void dsp_opcode_storeb(void)
1424 #ifdef DSP_DIS_STOREB
1426 WriteLog("%06X: STOREB R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, IMM_2, IMM_1, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, IMM_1, RM);
1428 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1429 DSPWriteLong(RM, RN & 0xFF, DSP);
1431 JaguarWriteByte(RM, RN, DSP);
1434 static void dsp_opcode_storew(void)
1436 #ifdef DSP_DIS_STOREW
1438 WriteLog("%06X: STOREW R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, IMM_2, IMM_1, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, IMM_1, RM);
1440 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1441 DSPWriteLong(RM, RN & 0xFFFF, DSP);
1443 JaguarWriteWord(RM, RN, DSP);
1446 static void dsp_opcode_store(void)
1448 #ifdef DSP_DIS_STORE
1450 WriteLog("%06X: STORE R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, IMM_2, IMM_1, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, IMM_1, RM);
1452 DSPWriteLong(RM, RN, DSP);
1455 static void dsp_opcode_loadb(void)
1457 #ifdef DSP_DIS_LOADB
1459 WriteLog("%06X: LOADB (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1461 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1462 RN = DSPReadLong(RM, DSP) & 0xFF;
1464 RN = JaguarReadByte(RM, DSP);
1465 #ifdef DSP_DIS_LOADB
1467 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1471 static void dsp_opcode_loadw(void)
1473 #ifdef DSP_DIS_LOADW
1475 WriteLog("%06X: LOADW (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1477 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1478 RN = DSPReadLong(RM, DSP) & 0xFFFF;
1480 RN = JaguarReadWord(RM, DSP);
1481 #ifdef DSP_DIS_LOADW
1483 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1487 static void dsp_opcode_load(void)
1491 WriteLog("%06X: LOAD (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1493 RN = DSPReadLong(RM, DSP);
1496 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1500 static void dsp_opcode_load_r14_indexed(void)
1502 #ifdef DSP_DIS_LOAD14I
1504 WriteLog("%06X: LOAD (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1] << 2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[IMM_1] << 2, dsp_reg[14]+(dsp_convert_zero[IMM_1] << 2), IMM_2, RN);
1506 RN = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), DSP);
1507 #ifdef DSP_DIS_LOAD14I
1509 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1513 static void dsp_opcode_load_r15_indexed(void)
1515 #ifdef DSP_DIS_LOAD15I
1517 WriteLog("%06X: LOAD (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1] << 2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[IMM_1] << 2, dsp_reg[15]+(dsp_convert_zero[IMM_1] << 2), IMM_2, RN);
1519 RN = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), DSP);
1520 #ifdef DSP_DIS_LOAD15I
1522 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1526 static void dsp_opcode_movei(void)
1528 #ifdef DSP_DIS_MOVEI
1530 WriteLog("%06X: MOVEI #$%08X, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, (uint32)DSPReadWord(dsp_pc) | ((uint32)DSPReadWord(dsp_pc + 2) << 16), IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1532 // This instruction is followed by 32-bit value in LSW / MSW format...
1533 RN = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
1535 #ifdef DSP_DIS_MOVEI
1537 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1541 static void dsp_opcode_moveta(void)
1543 #ifdef DSP_DIS_MOVETA
1545 WriteLog("%06X: MOVETA R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, ALTERNATE_RN);
1548 #ifdef DSP_DIS_MOVETA
1550 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, ALTERNATE_RN);
1554 static void dsp_opcode_movefa(void)
1556 #ifdef DSP_DIS_MOVEFA
1558 WriteLog("%06X: MOVEFA R%02u, R%02u [NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, ALTERNATE_RM, IMM_2, RN);
1561 #ifdef DSP_DIS_MOVEFA
1563 WriteLog("[NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, ALTERNATE_RM, IMM_2, RN);
1567 static void dsp_opcode_move(void)
1571 WriteLog("%06X: MOVE R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1576 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1580 static void dsp_opcode_moveq(void)
1582 #ifdef DSP_DIS_MOVEQ
1584 WriteLog("%06X: MOVEQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1587 #ifdef DSP_DIS_MOVEQ
1589 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1593 static void dsp_opcode_resmac(void)
1595 #ifdef DSP_DIS_RESMAC
1597 WriteLog("%06X: RESMAC R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_ACC=%02X%08X] -> ", dsp_pc-2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
1599 RN = (uint32)dsp_acc;
1600 #ifdef DSP_DIS_RESMAC
1602 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1606 static void dsp_opcode_imult(void)
1608 #ifdef DSP_DIS_IMULT
1610 WriteLog("%06X: IMULT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1612 RN = (int16)RN * (int16)RM;
1614 #ifdef DSP_DIS_IMULT
1616 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1620 static void dsp_opcode_mult(void)
1624 WriteLog("%06X: MULT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1626 RN = (uint16)RM * (uint16)RN;
1630 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1634 static void dsp_opcode_bclr(void)
1638 WriteLog("%06X: BCLR #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1640 UINT32 res = RN & ~(1 << IMM_1);
1645 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1649 static void dsp_opcode_btst(void)
1653 WriteLog("%06X: BTST #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1655 dsp_flag_z = (~RN >> IMM_1) & 1;
1658 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1662 static void dsp_opcode_bset(void)
1666 WriteLog("%06X: BSET #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1668 UINT32 res = RN | (1 << IMM_1);
1673 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1677 static void dsp_opcode_subqt(void)
1679 #ifdef DSP_DIS_SUBQT
1681 WriteLog("%06X: SUBQT #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1683 RN -= dsp_convert_zero[IMM_1];
1684 #ifdef DSP_DIS_SUBQT
1686 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1690 static void dsp_opcode_addqt(void)
1692 #ifdef DSP_DIS_ADDQT
1694 WriteLog("%06X: ADDQT #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1696 RN += dsp_convert_zero[IMM_1];
1697 #ifdef DSP_DIS_ADDQT
1699 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1703 static void dsp_opcode_imacn(void)
1705 #ifdef DSP_DIS_IMACN
1707 WriteLog("%06X: IMACN R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1709 int32 res = (int16)RM * (int16)RN;
1710 dsp_acc += (int64)res;
1711 //Should we AND the result to fit into 40 bits here???
1712 #ifdef DSP_DIS_IMACN
1714 WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
1718 static void dsp_opcode_mtoi(void)
1720 RN = (((INT32)RM >> 8) & 0xFF800000) | (RM & 0x007FFFFF);
1724 static void dsp_opcode_normi(void)
1731 while ((_Rm & 0xffc00000) == 0)
1736 while ((_Rm & 0xff800000) != 0)
1746 static void dsp_opcode_mmult(void)
1748 int count = dsp_matrix_control&0x0f;
1749 uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
1753 if (!(dsp_matrix_control & 0x10))
1755 for (int i = 0; i < count; i++)
1759 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1761 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1762 int16 b=((int16)DSPReadWord(addr + 2, DSP));
1769 for (int i = 0; i < count; i++)
1773 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1775 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1776 int16 b=((int16)DSPReadWord(addr + 2, DSP));
1781 RN = res = (int32)accum;
1783 //NOTE: The flags are set based upon the last add/multiply done...
1787 static void dsp_opcode_abs(void)
1792 if (_Rn == 0x80000000)
1796 dsp_flag_c = ((_Rn & 0x80000000) >> 31);
1797 res = RN = (_Rn & 0x80000000 ? -_Rn : _Rn);
1802 static void dsp_opcode_div(void)
1809 if (dsp_div_control & 1)
1811 dsp_remain = (((uint64)_Rn) << 16) % _Rm;
1812 if (dsp_remain&0x80000000)
1814 RN = (((uint64)_Rn) << 16) / _Rm;
1818 dsp_remain = _Rn % _Rm;
1819 if (dsp_remain&0x80000000)
1828 static void dsp_opcode_imultn(void)
1830 #ifdef DSP_DIS_IMULTN
1832 WriteLog("%06X: IMULTN R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1834 // This is OK, since this multiply won't overflow 32 bits...
1835 int32 res = (int32)((int16)RN * (int16)RM);
1836 dsp_acc = (int64)res;
1838 #ifdef DSP_DIS_IMULTN
1840 WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
1844 static void dsp_opcode_neg(void)
1848 WriteLog("%06X: NEG R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1851 SET_ZNC_SUB(0, RN, res);
1855 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1859 static void dsp_opcode_shlq(void)
1863 WriteLog("%06X: SHLQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, 32 - IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1865 INT32 r1 = 32 - IMM_1;
1866 UINT32 res = RN << r1;
1867 SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
1871 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1875 static void dsp_opcode_shrq(void)
1879 WriteLog("%06X: SHRQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1881 INT32 r1 = dsp_convert_zero[IMM_1];
1882 UINT32 res = RN >> r1;
1883 SET_ZN(res); dsp_flag_c = RN & 1;
1887 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1891 static void dsp_opcode_ror(void)
1895 WriteLog("%06X: ROR R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1897 UINT32 r1 = RM & 0x1F;
1898 UINT32 res = (RN >> r1) | (RN << (32 - r1));
1899 SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
1903 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
1907 static void dsp_opcode_rorq(void)
1911 WriteLog("%06X: RORQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1913 UINT32 r1 = dsp_convert_zero[IMM_1 & 0x1F];
1915 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
1917 SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
1920 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1924 static void dsp_opcode_sha(void)
1926 int32 sRm=(int32)RM;
1932 if (shift>=32) shift=32;
1933 dsp_flag_c=(_Rn&0x80000000)>>31;
1943 if (shift>=32) shift=32;
1947 _Rn=((int32)_Rn)>>1;
1955 static void dsp_opcode_sharq(void)
1957 #ifdef DSP_DIS_SHARQ
1959 WriteLog("%06X: SHARQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1961 UINT32 res = (INT32)RN >> dsp_convert_zero[IMM_1];
1962 SET_ZN(res); dsp_flag_c = RN & 0x01;
1964 #ifdef DSP_DIS_SHARQ
1966 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1970 static void dsp_opcode_sh(void)
1972 int32 sRm=(int32)RM;
1977 uint32 shift=(-sRm);
1978 if (shift>=32) shift=32;
1979 dsp_flag_c=(_Rn&0x80000000)>>31;
1989 if (shift>=32) shift=32;
2001 void dsp_opcode_addqmod(void)
2003 #ifdef DSP_DIS_ADDQMOD
2005 WriteLog("%06X: ADDQMOD #%u, R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_MOD=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, dsp_modulo);
2007 UINT32 r1 = dsp_convert_zero[IMM_1];
2009 UINT32 res = r2 + r1;
2010 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2012 SET_ZNC_ADD(r2, r1, res);
2013 #ifdef DSP_DIS_ADDQMOD
2015 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2019 void dsp_opcode_subqmod(void)
2021 UINT32 r1 = dsp_convert_zero[IMM_1];
2023 UINT32 res = r2 - r1;
2024 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2027 SET_ZNC_SUB(r2, r1, res);
2030 void dsp_opcode_mirror(void)
2033 RN = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
2037 void dsp_opcode_sat32s(void)
2039 INT32 r2 = (UINT32)RN;
2040 INT32 temp = dsp_acc >> 32;
2041 UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
2046 void dsp_opcode_sat16s(void)
2049 UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
2055 // New pipelined DSP core
2058 static void DSP_abs(void);
2059 static void DSP_add(void);
2060 static void DSP_addc(void);
2061 static void DSP_addq(void);
2062 static void DSP_addqmod(void);
2063 static void DSP_addqt(void);
2064 static void DSP_and(void);
2065 static void DSP_bclr(void);
2066 static void DSP_bset(void);
2067 static void DSP_btst(void);
2068 static void DSP_cmp(void);
2069 static void DSP_cmpq(void);
2070 static void DSP_div(void);
2071 static void DSP_imacn(void);
2072 static void DSP_imult(void);
2073 static void DSP_imultn(void);
2074 static void DSP_illegal(void);
2075 static void DSP_jr(void);
2076 static void DSP_jump(void);
2077 static void DSP_load(void);
2078 static void DSP_loadb(void);
2079 static void DSP_loadw(void);
2080 static void DSP_load_r14_i(void);
2081 static void DSP_load_r14_r(void);
2082 static void DSP_load_r15_i(void);
2083 static void DSP_load_r15_r(void);
2084 static void DSP_mirror(void);
2085 static void DSP_mmult(void);
2086 static void DSP_move(void);
2087 static void DSP_movefa(void);
2088 static void DSP_movei(void);
2089 static void DSP_movepc(void);
2090 static void DSP_moveq(void);
2091 static void DSP_moveta(void);
2092 static void DSP_mtoi(void);
2093 static void DSP_mult(void);
2094 static void DSP_neg(void);
2095 static void DSP_nop(void);
2096 static void DSP_normi(void);
2097 static void DSP_not(void);
2098 static void DSP_or(void);
2099 static void DSP_resmac(void);
2100 static void DSP_ror(void);
2101 static void DSP_rorq(void);
2102 static void DSP_sat16s(void);
2103 static void DSP_sat32s(void);
2104 static void DSP_sh(void);
2105 static void DSP_sha(void);
2106 static void DSP_sharq(void);
2107 static void DSP_shlq(void);
2108 static void DSP_shrq(void);
2109 static void DSP_store(void);
2110 static void DSP_storeb(void);
2111 static void DSP_storew(void);
2112 static void DSP_store_r14_i(void);
2113 static void DSP_store_r14_r(void);
2114 static void DSP_store_r15_i(void);
2115 static void DSP_store_r15_r(void);
2116 static void DSP_sub(void);
2117 static void DSP_subc(void);
2118 static void DSP_subq(void);
2119 static void DSP_subqmod(void);
2120 static void DSP_subqt(void);
2121 static void DSP_xor(void);
2123 void (* DSPOpcode[64])() =
2125 DSP_add, DSP_addc, DSP_addq, DSP_addqt,
2126 DSP_sub, DSP_subc, DSP_subq, DSP_subqt,
2127 DSP_neg, DSP_and, DSP_or, DSP_xor,
2128 DSP_not, DSP_btst, DSP_bset, DSP_bclr,
2130 DSP_mult, DSP_imult, DSP_imultn, DSP_resmac,
2131 DSP_imacn, DSP_div, DSP_abs, DSP_sh,
2132 DSP_shlq, DSP_shrq, DSP_sha, DSP_sharq,
2133 DSP_ror, DSP_rorq, DSP_cmp, DSP_cmpq,
2135 DSP_subqmod, DSP_sat16s, DSP_move, DSP_moveq,
2136 DSP_moveta, DSP_movefa, DSP_movei, DSP_loadb,
2137 DSP_loadw, DSP_load, DSP_sat32s, DSP_load_r14_i,
2138 DSP_load_r15_i, DSP_storeb, DSP_storew, DSP_store,
2140 DSP_mirror, DSP_store_r14_i, DSP_store_r15_i, DSP_movepc,
2141 DSP_jump, DSP_jr, DSP_mmult, DSP_mtoi,
2142 DSP_normi, DSP_nop, DSP_load_r14_r, DSP_load_r15_r,
2143 DSP_store_r14_r, DSP_store_r15_r, DSP_illegal, DSP_addqmod
2146 bool readAffected[64][2] =
2148 { true, true}, { true, true}, {false, true}, {false, true},
2149 { true, true}, { true, true}, {false, true}, {false, true},
2150 {false, true}, { true, true}, { true, true}, { true, true},
2151 {false, true}, {false, true}, {false, true}, {false, true},
2153 { true, true}, { true, true}, { true, true}, {false, true},
2154 { true, true}, { true, true}, {false, true}, { true, true},
2155 {false, true}, {false, true}, { true, true}, {false, true},
2156 { true, true}, {false, true}, { true, true}, {false, true},
2158 {false, true}, {false, true}, { true, false}, {false, false},
2159 { true, false}, {false, false}, {false, false}, { true, false},
2160 { true, false}, { true, false}, {false, true}, { true, false},
2161 { true, false}, { true, true}, { true, true}, { true, true},
2163 {false, true}, { true, true}, { true, true}, {false, true},
2164 { true, false}, { true, false}, { true, true}, { true, false},
2165 { true, false}, {false, false}, { true, false}, { true, false},
2166 { true, true}, { true, true}, {false, false}, {false, true}
2169 bool affectsScoreboard[64] =
2171 true, true, true, true,
2172 true, true, true, true,
2173 true, true, true, true,
2174 true, false, true, true,
2176 true, true, false, true,
2177 false, true, true, true,
2178 true, true, true, true,
2179 true, true, false, false,
2181 true, true, true, true,
2182 false, true, true, true,
2183 true, true, true, true,
2184 true, false, false, false,
2186 true, false, false, true,
2187 false, false, true, true,
2188 true, false, true, true,
2189 false, false, false, true
2192 // Pipeline structures
2194 struct PipelineStage
2197 uint8 opcode, operand1, operand2;
2198 uint32 reg1, reg2, areg1, areg2;
2200 uint8 writebackRegister;
2203 bool scoreboard[32];
2205 uint8 plPtrFetch, plPtrRead, plPtrExec, plPtrWrite;
2207 #define PIPELINE_STALL 64 // Set to # of opcodes + 1
2209 PipelineStage pipeline[4];
2211 void FlushDSPPipeline(void)
2213 plPtrFetch = 3, plPtrRead = 2, plPtrExec = 1, plPtrWrite = 0;
2215 for(int i=0; i<4; i++)
2216 pipeline[i].opcode = PIPELINE_STALL;
2218 for(int i=0; i<32; i++)
2219 scoreboard[i] = false;
2223 // New pipelined DSP execution core
2225 void DSPExecP(int32 cycles)
2227 // bool inhibitFetch = false;
2229 dsp_releaseTimeSlice_flag = 0;
2232 while (cycles > 0 && DSP_RUNNING)
2234 WriteLog("DSPExecP: Pipeline status...\n");
2235 WriteLog("\tF -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrFetch].opcode, pipeline[plPtrFetch].operand1, pipeline[plPtrFetch].operand2, pipeline[plPtrFetch].reg1, pipeline[plPtrFetch].reg2, pipeline[plPtrFetch].result, pipeline[plPtrFetch].writebackRegister);
2236 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister);
2237 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister);
2238 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister);
2239 WriteLog(" --> Scoreboard: ");
2240 for(int i=0; i<32; i++)
2241 WriteLog("%s ", scoreboard[i] ? "T" : "F");
2243 // Stage 1: Instruction fetch
2244 // if (!inhibitFetch)
2246 pipeline[plPtrFetch].instruction = DSPReadWord(dsp_pc, DSP);
2247 pipeline[plPtrFetch].opcode = pipeline[plPtrFetch].instruction >> 10;
2248 pipeline[plPtrFetch].operand1 = (pipeline[plPtrFetch].instruction >> 5) & 0x1F;
2249 pipeline[plPtrFetch].operand2 = pipeline[plPtrFetch].instruction & 0x1F;
2250 if (pipeline[plPtrFetch].opcode == 38)
2251 pipeline[plPtrFetch].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
2252 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
2255 // inhibitFetch = false;
2256 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrFetch].instruction, dsp_pc);
2258 WriteLog("DSPExecP: Pipeline status (after stage 1)...\n");
2259 WriteLog("\tF -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrFetch].opcode, pipeline[plPtrFetch].operand1, pipeline[plPtrFetch].operand2, pipeline[plPtrFetch].reg1, pipeline[plPtrFetch].reg2, pipeline[plPtrFetch].result, pipeline[plPtrFetch].writebackRegister);
2260 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister);
2261 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister);
2262 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister);
2263 // Stage 2: Read registers
2264 //Ok, stalls here depend on whether or not the instruction reads two registers or not
2265 //and *which* register (1 or 2) is the one being read... !!! FIX !!!
2266 if ((/*scoreboard[pipeline[plPtrRead].operand1]
2267 ||*/ scoreboard[pipeline[plPtrRead].operand2])
2268 && pipeline[plPtrRead].opcode != PIPELINE_STALL)
2269 // We have a hit in the scoreboard, so we have to stall the pipeline...
2271 //This is crappy, crappy CRAPPY! And it doesn't work! !!! FIX !!!
2272 // dsp_pc -= (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2273 WriteLog(" --> Stalling pipeline: scoreboard = %s\n", scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
2274 pipeline[plPtrFetch] = pipeline[plPtrRead];
2275 pipeline[plPtrRead].opcode = PIPELINE_STALL;
2279 pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
2280 pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
2281 pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2; // Set it to RN
2283 if (pipeline[plPtrRead].opcode != PIPELINE_STALL)
2284 // Shouldn't we be more selective with the register scoreboarding?
2285 // Yes, we should. !!! FIX !!!
2286 // scoreboard[pipeline[plPtrRead].operand1]
2287 /*=*/ scoreboard[pipeline[plPtrRead].operand2] = true;
2288 //Advance PC here??? Yes.
2289 // dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2290 //This is a mangling of the pipeline stages, but what else to do???
2291 dsp_pc += (pipeline[plPtrFetch].opcode == 38 ? 6 : 2);
2294 DSPExecP: Pipeline status (after stage 1)...
2295 F -> 52, 00, 00; r1=00000000, r2= 00000000, res=00000000, wb=0
2296 R -> 38, 00, 00; r1=00000000, r2= 00000000, res=00F1B034, wb=0
2297 E -> 64, 00, 00; r1=00000000, r2= 00000000, res=00000000, wb=0
2298 W -> 64, 00, 00; r1=00000000, r2= 00000000, res=00000000, wb=0
2299 --> Stalling pipeline: scoreboard = true
2300 DSPExecP: Pipeline status (after stage 2)...
2301 F -> 52, 00, 00; r1=00000000, r2= 00000000, res=00000000, wb=0
2302 R -> 64, 00, 00; r1=00000000, r2= 00000000, res=00F1B034, wb=0
2303 E -> 64, 00, 00; r1=00000000, r2= 00000000, res=00000000, wb=0
2304 W -> 64, 00, 00; r1=00000000, r2= 00000000, res=00000000, wb=0 */
2307 WriteLog("DSPExecP: Pipeline status (after stage 2)...\n");
2308 WriteLog("\tF -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrFetch].opcode, pipeline[plPtrFetch].operand1, pipeline[plPtrFetch].operand2, pipeline[plPtrFetch].reg1, pipeline[plPtrFetch].reg2, pipeline[plPtrFetch].result, pipeline[plPtrFetch].writebackRegister);
2309 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister);
2310 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister);
2311 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister);
2313 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
2315 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
2316 DSPOpcode[pipeline[plPtrExec].opcode]();
2317 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
2318 cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
2323 WriteLog("DSPExecP: Pipeline status (after stage 3)...\n");
2324 WriteLog("\tF -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrFetch].opcode, pipeline[plPtrFetch].operand1, pipeline[plPtrFetch].operand2, pipeline[plPtrFetch].reg1, pipeline[plPtrFetch].reg2, pipeline[plPtrFetch].result, pipeline[plPtrFetch].writebackRegister);
2325 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister);
2326 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister);
2327 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister);
2328 // Stage 4: Write back register
2329 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
2331 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
2332 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
2334 scoreboard[pipeline[plPtrWrite].operand1]
2335 = scoreboard[pipeline[plPtrWrite].operand2] = false;
2338 // Push instructions through the pipeline...
2339 plPtrFetch = (++plPtrFetch) & 0x03;
2340 plPtrRead = (++plPtrRead) & 0x03;
2341 plPtrExec = (++plPtrExec) & 0x03;
2342 plPtrWrite = (++plPtrWrite) & 0x03;
2350 #define DSP_DEBUG_PL2
2351 //Let's try a 3 stage pipeline....
2352 void DSPExecP2(int32 cycles)
2354 dsp_releaseTimeSlice_flag = 0;
2357 while (cycles > 0 && DSP_RUNNING)
2359 #ifdef DSP_DEBUG_PL2
2360 WriteLog("DSPExecP: Pipeline status...\n");
2361 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister);
2362 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister);
2363 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister);
2364 WriteLog(" --> Scoreboard: ");
2365 for(int i=0; i<32; i++)
2366 WriteLog("%s ", scoreboard[i] ? "T" : "F");
2369 // Stage 1a: Instruction fetch
2370 pipeline[plPtrRead].instruction = DSPReadWord(dsp_pc, DSP);
2371 pipeline[plPtrRead].opcode = pipeline[plPtrRead].instruction >> 10;
2372 pipeline[plPtrRead].operand1 = (pipeline[plPtrRead].instruction >> 5) & 0x1F;
2373 pipeline[plPtrRead].operand2 = pipeline[plPtrRead].instruction & 0x1F;
2374 if (pipeline[plPtrRead].opcode == 38)
2375 pipeline[plPtrRead].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
2376 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
2377 #ifdef DSP_DEBUG_PL2
2378 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrRead].instruction, dsp_pc);
2379 WriteLog("DSPExecP: Pipeline status (after stage 1a)...\n");
2380 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister);
2381 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister);
2382 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister);
2384 // Stage 1b: Read registers
2385 if (scoreboard[pipeline[plPtrRead].operand2])
2386 // We have a hit in the scoreboard, so we have to stall the pipeline...
2387 #ifdef DSP_DEBUG_PL2
2389 WriteLog(" --> Stalling pipeline: scoreboard[%u] = %s\n", pipeline[plPtrRead].operand2, scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
2391 pipeline[plPtrRead].opcode = PIPELINE_STALL;
2392 #ifdef DSP_DEBUG_PL2
2397 pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
2398 pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
2399 pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2; // Set it to RN
2401 // Shouldn't we be more selective with the register scoreboarding?
2402 // Yes, we should. !!! FIX !!! [Kinda DONE]
2403 scoreboard[pipeline[plPtrRead].operand2] = affectsScoreboard[pipeline[plPtrRead].opcode];
2405 //Advance PC here??? Yes.
2406 dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2409 #ifdef DSP_DEBUG_PL2
2410 WriteLog("DSPExecP: Pipeline status (after stage 1b)...\n");
2411 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister);
2412 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister);
2413 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister);
2416 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
2418 #ifdef DSP_DEBUG_PL2
2419 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
2421 DSPOpcode[pipeline[plPtrExec].opcode]();
2422 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
2423 cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
2428 #ifdef DSP_DEBUG_PL2
2429 WriteLog("DSPExecP: Pipeline status (after stage 2)...\n");
2430 WriteLog("\tR -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister);
2431 WriteLog("\tE -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister);
2432 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u \n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister);
2435 // Stage 3: Write back register
2436 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
2438 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
2439 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
2441 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
2442 scoreboard[pipeline[plPtrWrite].operand2] = false;
2445 // Push instructions through the pipeline...
2446 plPtrRead = (++plPtrRead) & 0x03;
2447 plPtrExec = (++plPtrExec) & 0x03;
2448 plPtrWrite = (++plPtrWrite) & 0x03;
2455 //Problems: JR and any other instruction that relies on DSP_PC is getting WRONG values!
2458 #define DSP_DEBUG_PL3
2459 //Let's try a 2 stage pipeline....
2460 void DSPExecP3(int32 cycles)
2462 dsp_releaseTimeSlice_flag = 0;
2465 while (cycles > 0 && DSP_RUNNING)
2467 #ifdef DSP_DEBUG_PL3
2468 WriteLog("DSPExecP: Pipeline status...\n");
2469 WriteLog("\tF/R -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister, dsp_opcode_str[pipeline[plPtrRead].opcode]);
2470 WriteLog("\tE/W -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister, dsp_opcode_str[pipeline[plPtrExec].opcode]);
2471 WriteLog(" --> Scoreboard: ");
2472 for(int i=0; i<32; i++)
2473 WriteLog("%s ", scoreboard[i] ? "T" : "F");
2476 // Stage 1a: Instruction fetch
2477 pipeline[plPtrRead].instruction = DSPReadWord(dsp_pc, DSP);
2478 pipeline[plPtrRead].opcode = pipeline[plPtrRead].instruction >> 10;
2479 pipeline[plPtrRead].operand1 = (pipeline[plPtrRead].instruction >> 5) & 0x1F;
2480 pipeline[plPtrRead].operand2 = pipeline[plPtrRead].instruction & 0x1F;
2481 if (pipeline[plPtrRead].opcode == 38)
2482 pipeline[plPtrRead].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
2483 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
2484 #ifdef DSP_DEBUG_PL3
2485 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrRead].instruction, dsp_pc);
2486 WriteLog("DSPExecP: Pipeline status (after stage 1a)...\n");
2487 WriteLog("\tF/R -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister, dsp_opcode_str[pipeline[plPtrRead].opcode]);
2488 WriteLog("\tE/W -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister, dsp_opcode_str[pipeline[plPtrExec].opcode]);
2490 // Stage 1b: Read registers
2491 if ((scoreboard[pipeline[plPtrRead].operand1] && readAffected[pipeline[plPtrRead].opcode][0])
2492 || (scoreboard[pipeline[plPtrRead].operand2] && readAffected[pipeline[plPtrRead].opcode][1]))
2493 // We have a hit in the scoreboard, so we have to stall the pipeline...
2494 #if 1//def DSP_DEBUG_PL3
2496 WriteLog(" --> Stalling pipeline: ");
2497 if (readAffected[pipeline[plPtrRead].opcode][0])
2498 WriteLog("scoreboard[%u] = %s (reg 1) ", pipeline[plPtrRead].operand1, scoreboard[pipeline[plPtrRead].operand1] ? "true" : "false");
2499 if (readAffected[pipeline[plPtrRead].opcode][1])
2500 WriteLog("scoreboard[%u] = %s (reg 2)", pipeline[plPtrRead].operand2, scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
2503 pipeline[plPtrRead].opcode = PIPELINE_STALL;
2504 #if 1//def DSP_DEBUG_PL3
2509 pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
2510 pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
2511 pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2; // Set it to RN
2513 // Shouldn't we be more selective with the register scoreboarding?
2514 // Yes, we should. !!! FIX !!! [Kinda DONE]
2515 scoreboard[pipeline[plPtrRead].operand2] = affectsScoreboard[pipeline[plPtrRead].opcode];
2517 //Advance PC here??? Yes.
2518 dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2521 #ifdef DSP_DEBUG_PL3
2522 WriteLog("DSPExecP: Pipeline status (after stage 1b)...\n");
2523 WriteLog("\tF/R -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister, dsp_opcode_str[pipeline[plPtrRead].opcode]);
2524 WriteLog("\tE/W -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister, dsp_opcode_str[pipeline[plPtrExec].opcode]);
2526 // Stage 2a: Execute
2527 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
2529 #ifdef DSP_DEBUG_PL3
2530 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
2532 DSPOpcode[pipeline[plPtrExec].opcode]();
2533 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
2534 cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
2539 #ifdef DSP_DEBUG_PL3
2540 WriteLog("DSPExecP: Pipeline status (after stage 2a)...\n");
2541 WriteLog("\tF/R -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrRead].opcode, pipeline[plPtrRead].operand1, pipeline[plPtrRead].operand2, pipeline[plPtrRead].reg1, pipeline[plPtrRead].reg2, pipeline[plPtrRead].result, pipeline[plPtrRead].writebackRegister, dsp_opcode_str[pipeline[plPtrRead].opcode]);
2542 WriteLog("\tE/W -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrExec].opcode, pipeline[plPtrExec].operand1, pipeline[plPtrExec].operand2, pipeline[plPtrExec].reg1, pipeline[plPtrExec].reg2, pipeline[plPtrExec].result, pipeline[plPtrExec].writebackRegister, dsp_opcode_str[pipeline[plPtrExec].opcode]);
2545 // Stage 2b: Write back register
2546 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
2548 if (pipeline[plPtrExec].writebackRegister != 0xFF)
2549 dsp_reg[pipeline[plPtrExec].writebackRegister] = pipeline[plPtrExec].result;
2551 if (affectsScoreboard[pipeline[plPtrExec].opcode])
2552 scoreboard[pipeline[plPtrExec].operand2] = false;
2555 // Push instructions through the pipeline...
2556 plPtrRead = (++plPtrRead) & 0x03;
2557 plPtrExec = (++plPtrExec) & 0x03;
2558 // plPtrWrite = (++plPtrWrite) & 0x03;
2565 // DSP pipelined opcode handlers
2568 #define PRM pipeline[plPtrExec].reg1
2569 #define PRN pipeline[plPtrExec].reg2
2570 #define PIMM1 pipeline[plPtrExec].operand1
2571 #define PIMM2 pipeline[plPtrExec].operand2
2572 #define PRES pipeline[plPtrExec].result
2573 #define PWBR pipeline[plPtrExec].writebackRegister
2574 #define NO_WRITEBACK pipeline[plPtrExec].writebackRegister = 0xFF
2576 static void DSP_abs(void)
2580 if (_Rn == 0x80000000)
2584 dsp_flag_c = ((_Rn & 0x80000000) >> 31);
2585 PRES = (_Rn & 0x80000000 ? -_Rn : _Rn);
2586 CLR_ZN; SET_Z(PRES);
2590 static void DSP_add(void)
2594 WriteLog("%06X: ADD R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2596 UINT32 res = PRN + PRM;
2597 SET_ZNC_ADD(PRN, PRM, res);
2601 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2605 static void DSP_addc(void)
2609 WriteLog("%06X: ADDC R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2611 UINT32 res = PRN + PRM + dsp_flag_c;
2612 UINT32 carry = dsp_flag_c;
2613 // SET_ZNC_ADD(PRN, PRM, res); //???BUG??? Yes!
2614 SET_ZNC_ADD(PRN + carry, PRM, res);
2615 // SET_ZNC_ADD(PRN, PRM + carry, res);
2619 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2623 static void DSP_addq(void)
2627 WriteLog("%06X: ADDQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2629 UINT32 r1 = dsp_convert_zero[PIMM1];
2630 UINT32 res = PRN + r1;
2631 CLR_ZNC; SET_ZNC_ADD(PRN, r1, res);
2635 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2639 static void DSP_addqmod(void)
2641 #ifdef DSP_DIS_ADDQMOD
2643 WriteLog("%06X: ADDQMOD #%u, R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_MOD=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, dsp_modulo);
2645 UINT32 r1 = dsp_convert_zero[PIMM1];
2647 UINT32 res = r2 + r1;
2648 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2650 SET_ZNC_ADD(r2, r1, res);
2651 #ifdef DSP_DIS_ADDQMOD
2653 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2657 static void DSP_addqt(void)
2659 #ifdef DSP_DIS_ADDQT
2661 WriteLog("%06X: ADDQT #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2663 PRES = PRN + dsp_convert_zero[PIMM1];
2664 #ifdef DSP_DIS_ADDQT
2666 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2670 static void DSP_and(void)
2674 WriteLog("%06X: AND R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2680 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2684 static void DSP_bclr(void)
2688 WriteLog("%06X: BCLR #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2690 PRES = PRN & ~(1 << PIMM1);
2694 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2698 static void DSP_bset(void)
2702 WriteLog("%06X: BSET #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2704 PRES = PRN | (1 << PIMM1);
2708 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2712 static void DSP_btst(void)
2716 WriteLog("%06X: BTST #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2718 dsp_flag_z = (~PRN >> PIMM1) & 1;
2722 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2726 static void DSP_cmp(void)
2730 WriteLog("%06X: CMP R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2732 UINT32 res = PRN - PRM;
2733 SET_ZNC_SUB(PRN, PRM, res);
2737 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
2741 static void DSP_cmpq(void)
2743 static int32 sqtable[32] =
2744 { 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 };
2747 WriteLog("%06X: CMPQ #%d, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, sqtable[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2749 UINT32 r1 = sqtable[PIMM1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
2750 UINT32 res = PRN - r1;
2751 SET_ZNC_SUB(PRN, r1, res);
2755 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
2759 static void DSP_div(void)
2761 uint32 _Rm = PRM, _Rn = PRN;
2765 if (dsp_div_control & 1)
2767 dsp_remain = (((uint64)_Rn) << 16) % _Rm;
2768 if (dsp_remain & 0x80000000)
2770 PRES = (((uint64)_Rn) << 16) / _Rm;
2774 dsp_remain = _Rn % _Rm;
2775 if (dsp_remain & 0x80000000)
2784 static void DSP_imacn(void)
2786 #ifdef DSP_DIS_IMACN
2788 WriteLog("%06X: IMACN R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2790 int32 res = (int16)PRM * (int16)PRN;
2791 dsp_acc += (int64)res;
2792 //Should we AND the result to fit into 40 bits here???
2794 #ifdef DSP_DIS_IMACN
2796 WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
2800 static void DSP_imult(void)
2802 #ifdef DSP_DIS_IMULT
2804 WriteLog("%06X: IMULT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2806 PRES = (int16)PRN * (int16)PRM;
2808 #ifdef DSP_DIS_IMULT
2810 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2814 static void DSP_imultn(void)
2816 #ifdef DSP_DIS_IMULTN
2818 WriteLog("%06X: IMULTN R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2820 // This is OK, since this multiply won't overflow 32 bits...
2821 int32 res = (int32)((int16)PRN * (int16)PRM);
2822 dsp_acc = (int64)res;
2825 #ifdef DSP_DIS_IMULTN
2827 WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
2831 static void DSP_illegal(void)
2833 #ifdef DSP_DIS_ILLEGAL
2835 WriteLog("%06X: ILLEGAL [NCZ:%u%u%u]\n", dsp_pc-2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
2840 // There is a problem here with interrupt handlers the JUMP and JR instructions that
2841 // can cause trouble because an interrupt can occur *before* the instruction following the
2842 // jump can execute... !!! FIX !!!
2843 static void DSP_jr(void)
2846 char * condition[32] =
2847 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
2848 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
2849 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
2850 "???", "???", "???", "F" };
2852 WriteLog("%06X: JR %s, %06X [NCZ:%u%u%u] ", dsp_pc-2, condition[PIMM2], dsp_pc+((PIMM1 & 0x10 ? 0xFFFFFFF0 | PIMM1 : PIMM1) * 2), dsp_flag_n, dsp_flag_c, dsp_flag_z);
2854 // KLUDGE: Used by BRANCH_CONDITION macro
2855 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
2857 if (BRANCH_CONDITION(PIMM2))
2861 WriteLog("Branched!\n");
2863 int32 offset = (PIMM1 & 0x10 ? 0xFFFFFFF0 | PIMM1 : PIMM1); // Sign extend PIMM1
2864 int32 delayed_pc = dsp_pc + (offset * 2);
2866 dsp_pc = delayed_pc;
2871 WriteLog("Branch NOT taken.\n");
2876 static void DSP_jump(void)
2879 char * condition[32] =
2880 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
2881 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
2882 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
2883 "???", "???", "???", "F" };
2885 WriteLog("%06X: JUMP %s, (R%02u) [NCZ:%u%u%u, R%02u=%08X] ", dsp_pc-2, condition[PIMM2], PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM);
2887 // KLUDGE: Used by BRANCH_CONDITION macro
2888 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
2890 if (BRANCH_CONDITION(PIMM2))
2894 WriteLog("Branched!\n");
2896 // uint32 delayed_pc = PRM;
2898 // dsp_pc = delayed_pc;
2904 WriteLog("Branch NOT taken.\n");
2909 static void DSP_load(void)
2913 WriteLog("%06X: LOAD (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2915 PRES = DSPReadLong(PRM, DSP);
2918 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2922 static void DSP_loadb(void)
2924 #ifdef DSP_DIS_LOADB
2926 WriteLog("%06X: LOADB (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2928 if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
2929 PRES = DSPReadLong(PRM, DSP) & 0xFF;
2931 PRES = JaguarReadByte(PRM, DSP);
2932 #ifdef DSP_DIS_LOADB
2934 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2938 static void DSP_loadw(void)
2940 #ifdef DSP_DIS_LOADW
2942 WriteLog("%06X: LOADW (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
2944 if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
2945 PRES = DSPReadLong(PRM, DSP) & 0xFFFF;
2947 PRES = JaguarReadWord(PRM, DSP);
2948 #ifdef DSP_DIS_LOADW
2950 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2954 static void DSP_load_r14_i(void)
2956 #ifdef DSP_DIS_LOAD14I
2958 WriteLog("%06X: LOAD (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1] << 2, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[PIMM1] << 2, dsp_reg[14]+(dsp_convert_zero[PIMM1] << 2), PIMM2, PRN);
2960 PRES = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), DSP);
2961 #ifdef DSP_DIS_LOAD14I
2963 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2967 static void DSP_load_r14_r(void)
2969 #ifdef DSP_DIS_LOAD14R
2971 WriteLog("%06X: LOAD (R14+R%02u), R%02u [NCZ:%u%u%u, R14+R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM+dsp_reg[14], PIMM2, PRN);
2973 PRES = DSPReadLong(dsp_reg[14] + PRM, DSP);
2974 #ifdef DSP_DIS_LOAD14R
2976 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2980 static void DSP_load_r15_i(void)
2982 #ifdef DSP_DIS_LOAD15I
2984 WriteLog("%06X: LOAD (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1] << 2, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[PIMM1] << 2, dsp_reg[15]+(dsp_convert_zero[PIMM1] << 2), PIMM2, PRN);
2986 PRES = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), DSP);
2987 #ifdef DSP_DIS_LOAD15I
2989 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2993 static void DSP_load_r15_r(void)
2995 #ifdef DSP_DIS_LOAD15R
2997 WriteLog("%06X: LOAD (R15+R%02u), R%02u [NCZ:%u%u%u, R15+R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM+dsp_reg[15], PIMM2, PRN);
2999 PRES = DSPReadLong(dsp_reg[15] + PRM, DSP);
3000 #ifdef DSP_DIS_LOAD15R
3002 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3006 static void DSP_mirror(void)
3009 PRES = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
3013 static void DSP_mmult(void)
3015 int count = dsp_matrix_control&0x0f;
3016 uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
3020 if (!(dsp_matrix_control & 0x10))
3022 for (int i = 0; i < count; i++)
3026 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
3028 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
3029 int16 b=((int16)DSPReadWord(addr + 2, DSP));
3036 for (int i = 0; i < count; i++)
3040 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
3042 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
3043 int16 b=((int16)DSPReadWord(addr + 2, DSP));
3049 PRES = res = (int32)accum;
3051 //NOTE: The flags are set based upon the last add/multiply done...
3055 static void DSP_move(void)
3059 WriteLog("%06X: MOVE R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3064 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3068 static void DSP_movefa(void)
3070 #ifdef DSP_DIS_MOVEFA
3072 // WriteLog("%06X: MOVEFA R%02u, R%02u [NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, ALTERNATE_RM, PIMM2, PRN);
3073 WriteLog("%06X: MOVEFA R%02u, R%02u [NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, dsp_alternate_reg[PIMM1], PIMM2, PRN);
3075 // PRES = ALTERNATE_RM;
3076 PRES = dsp_alternate_reg[PIMM1];
3077 #ifdef DSP_DIS_MOVEFA
3079 // WriteLog("[NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, ALTERNATE_RM, PIMM2, PRN);
3080 WriteLog("[NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, dsp_alternate_reg[PIMM1], PIMM2, PRES);
3084 static void DSP_movei(void)
3086 #ifdef DSP_DIS_MOVEI
3088 WriteLog("%06X: MOVEI #$%08X, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, PRES, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3090 // // This instruction is followed by 32-bit value in LSW / MSW format...
3091 // PRES = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
3093 #ifdef DSP_DIS_MOVEI
3095 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3099 static void DSP_movepc(void)
3101 //Need to fix this to take into account pipelining effects... !!! FIX !!!
3105 static void DSP_moveq(void)
3107 #ifdef DSP_DIS_MOVEQ
3109 WriteLog("%06X: MOVEQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3112 #ifdef DSP_DIS_MOVEQ
3114 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3118 static void DSP_moveta(void)
3120 #ifdef DSP_DIS_MOVETA
3122 // WriteLog("%06X: MOVETA R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, ALTERNATE_RN);
3123 WriteLog("%06X: MOVETA R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, dsp_alternate_reg[PIMM2]);
3125 // ALTERNATE_RN = PRM;
3126 dsp_alternate_reg[PIMM2] = PRM;
3128 #ifdef DSP_DIS_MOVETA
3130 // WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, ALTERNATE_RN);
3131 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, dsp_alternate_reg[PIMM2]);
3135 static void DSP_mtoi(void)
3137 PRES = (((INT32)PRM >> 8) & 0xFF800000) | (PRM & 0x007FFFFF);
3141 static void DSP_mult(void)
3145 WriteLog("%06X: MULT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3147 PRES = (uint16)PRM * (uint16)PRN;
3151 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3155 static void DSP_neg(void)
3159 WriteLog("%06X: NEG R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3162 SET_ZNC_SUB(0, PRN, res);
3166 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3170 static void DSP_nop(void)
3174 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", dsp_pc-2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
3179 static void DSP_normi(void)
3186 while ((_Rm & 0xffc00000) == 0)
3191 while ((_Rm & 0xff800000) != 0)
3201 static void DSP_not(void)
3205 WriteLog("%06X: NOT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3211 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3215 static void DSP_or(void)
3219 WriteLog("%06X: OR R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3225 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3229 static void DSP_resmac(void)
3231 #ifdef DSP_DIS_RESMAC
3233 WriteLog("%06X: RESMAC R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_ACC=%02X%08X] -> ", dsp_pc-2, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
3235 PRES = (uint32)dsp_acc;
3236 #ifdef DSP_DIS_RESMAC
3238 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3242 static void DSP_ror(void)
3246 WriteLog("%06X: ROR R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3248 UINT32 r1 = PRM & 0x1F;
3249 UINT32 res = (PRN >> r1) | (PRN << (32 - r1));
3250 SET_ZN(res); dsp_flag_c = (PRN >> 31) & 1;
3254 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3258 static void DSP_rorq(void)
3262 WriteLog("%06X: RORQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3264 UINT32 r1 = dsp_convert_zero[PIMM1 & 0x1F];
3266 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
3268 SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
3271 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3275 static void DSP_sat16s(void)
3278 UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
3283 static void DSP_sat32s(void)
3285 INT32 r2 = (UINT32)PRN;
3286 INT32 temp = dsp_acc >> 32;
3287 UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
3292 static void DSP_sh(void)
3294 int32 sRm = (int32)PRM;
3299 uint32 shift = -sRm;
3304 dsp_flag_c = (_Rn & 0x80000000) >> 31;
3319 dsp_flag_c = _Rn & 0x1;
3332 static void DSP_sha(void)
3334 int32 sRm = (int32)PRM;
3339 uint32 shift = -sRm;
3344 dsp_flag_c = (_Rn & 0x80000000) >> 31;
3359 dsp_flag_c = _Rn & 0x1;
3363 _Rn = ((int32)_Rn) >> 1;
3372 static void DSP_sharq(void)
3374 #ifdef DSP_DIS_SHARQ
3376 WriteLog("%06X: SHARQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3378 UINT32 res = (INT32)PRN >> dsp_convert_zero[PIMM1];
3379 SET_ZN(res); dsp_flag_c = PRN & 0x01;
3381 #ifdef DSP_DIS_SHARQ
3383 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3387 static void DSP_shlq(void)
3391 WriteLog("%06X: SHLQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, 32 - PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3393 INT32 r1 = 32 - PIMM1;
3394 UINT32 res = PRN << r1;
3395 SET_ZN(res); dsp_flag_c = (PRN >> 31) & 1;
3399 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3403 static void DSP_shrq(void)
3407 WriteLog("%06X: SHRQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3409 INT32 r1 = dsp_convert_zero[PIMM1];
3410 UINT32 res = PRN >> r1;
3411 SET_ZN(res); dsp_flag_c = PRN & 1;
3415 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3419 static void DSP_store(void)
3421 #ifdef DSP_DIS_STORE
3423 WriteLog("%06X: STORE R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, PIMM2, PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, PIMM1, PRM);
3425 DSPWriteLong(PRM, PRN, DSP);
3429 static void DSP_storeb(void)
3431 #ifdef DSP_DIS_STOREB
3433 WriteLog("%06X: STOREB R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, PIMM2, PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, PIMM1, PRM);
3435 if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
3436 DSPWriteLong(PRM, PRN & 0xFF, DSP);
3438 JaguarWriteByte(PRM, PRN, DSP);
3443 static void DSP_storew(void)
3445 #ifdef DSP_DIS_STOREW
3447 WriteLog("%06X: STOREW R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, PIMM2, PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, PIMM1, PRM);
3449 if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
3450 DSPWriteLong(PRM, PRN & 0xFFFF, DSP);
3452 JaguarWriteWord(PRM, PRN, DSP);
3457 static void DSP_store_r14_i(void)
3459 #ifdef DSP_DIS_STORE14I
3461 WriteLog("%06X: STORE R%02u, (R14+$%02X) [NCZ:%u%u%u, R%02u=%08X, R14+$%02X=%08X]\n", dsp_pc-2, PIMM2, dsp_convert_zero[PIMM1] << 2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, dsp_convert_zero[PIMM1] << 2, dsp_reg[14]+(dsp_convert_zero[PIMM1] << 2));
3463 DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
3467 static void DSP_store_r14_r(void)
3469 DSPWriteLong(dsp_reg[14] + PRM, PRN, DSP);
3473 static void DSP_store_r15_i(void)
3475 #ifdef DSP_DIS_STORE15I
3477 WriteLog("%06X: STORE R%02u, (R15+$%02X) [NCZ:%u%u%u, R%02u=%08X, R15+$%02X=%08X]\n", dsp_pc-2, PIMM2, dsp_convert_zero[PIMM1] << 2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, dsp_convert_zero[PIMM1] << 2, dsp_reg[15]+(dsp_convert_zero[PIMM1] << 2));
3479 DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
3483 static void DSP_store_r15_r(void)
3485 DSPWriteLong(dsp_reg[15] + PRM, PRN, DSP);
3489 static void DSP_sub(void)
3493 WriteLog("%06X: SUB R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3495 UINT32 res = PRN - PRM;
3496 SET_ZNC_SUB(PRN, PRM, res);
3500 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3504 static void DSP_subc(void)
3508 WriteLog("%06X: SUBC R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3510 UINT32 res = PRN - PRM - dsp_flag_c;
3511 UINT32 borrow = dsp_flag_c;
3512 SET_ZNC_SUB(PRN - borrow, PRM, res);
3516 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3520 static void DSP_subq(void)
3524 WriteLog("%06X: SUBQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3526 UINT32 r1 = dsp_convert_zero[PIMM1];
3527 UINT32 res = PRN - r1;
3528 SET_ZNC_SUB(PRN, r1, res);
3532 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3536 static void DSP_subqmod(void)
3538 UINT32 r1 = dsp_convert_zero[PIMM1];
3540 UINT32 res = r2 - r1;
3541 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
3543 SET_ZNC_SUB(r2, r1, res);
3546 static void DSP_subqt(void)
3548 #ifdef DSP_DIS_SUBQT
3550 WriteLog("%06X: SUBQT #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3552 PRES = PRN - dsp_convert_zero[PIMM1];
3553 #ifdef DSP_DIS_SUBQT
3555 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3559 static void DSP_xor(void)
3563 WriteLog("%06X: XOR R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3569 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);