4 // Original source by Cal2
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...
13 //#define DSP_DEBUG_IRQ
14 //#define DSP_DEBUG_PL2
15 //#define DSP_DEBUG_STALL
16 //#define DSP_DEBUG_CC
18 // Disassembly definitions
20 #define DSP_DIS_ABS // Pipelined only
24 #define DSP_DIS_ADDQMOD
34 #define DSP_DIS_IMULTN
35 #define DSP_DIS_ILLEGAL
39 #define DSP_DIS_LOAD14I
40 #define DSP_DIS_LOAD14R
41 #define DSP_DIS_LOAD15I
42 #define DSP_DIS_LOAD15R
48 #define DSP_DIS_MOVEFA
49 #define DSP_DIS_MOVETA
55 #define DSP_DIS_RESMAC
62 #define DSP_DIS_STORE14I
63 #define DSP_DIS_STORE15I
64 #define DSP_DIS_STOREB
65 #define DSP_DIS_STOREW
72 bool doDSPDis = false;
73 //bool doDSPDis = true;
108 + load_r15_indexed 284500
110 + store_r15_indexed 47416
114 + load_r14_ri 1229448
117 // Pipeline structures
119 const bool affectsScoreboard[64] =
121 true, true, true, true,
122 true, true, true, true,
123 true, true, true, true,
124 true, false, true, true,
126 true, true, false, true,
127 false, true, true, true,
128 true, true, true, true,
129 true, true, false, false,
131 true, true, true, true,
132 false, true, true, true,
133 true, true, true, true,
134 true, false, false, false,
136 true, false, false, true,
137 false, false, true, true,
138 true, false, true, true,
139 false, false, false, true
145 uint8 opcode, operand1, operand2;
146 uint32 reg1, reg2, areg1, areg2;
148 uint8 writebackRegister;
149 // General memory store...
158 #define PIPELINE_STALL 64 // Set to # of opcodes + 1
160 uint8 plPtrFetch, plPtrRead, plPtrExec, plPtrWrite;
161 PipelineStage pipeline[4];
162 bool IMASKCleared = false;
164 // DSP flags (old--have to get rid of this crap)
166 #define CINT0FLAG 0x00200
167 #define CINT1FLAG 0x00400
168 #define CINT2FLAG 0x00800
169 #define CINT3FLAG 0x01000
170 #define CINT4FLAG 0x02000
171 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
172 #define CINT5FLAG 0x20000 /* DSP only */
176 #define ZERO_FLAG 0x00001
177 #define CARRY_FLAG 0x00002
178 #define NEGA_FLAG 0x00004
179 #define IMASK 0x00008
180 #define INT_ENA0 0x00010
181 #define INT_ENA1 0x00020
182 #define INT_ENA2 0x00040
183 #define INT_ENA3 0x00080
184 #define INT_ENA4 0x00100
185 #define INT_CLR0 0x00200
186 #define INT_CLR1 0x00400
187 #define INT_CLR2 0x00800
188 #define INT_CLR3 0x01000
189 #define INT_CLR4 0x02000
190 #define REGPAGE 0x04000
191 #define DMAEN 0x08000
192 #define INT_ENA5 0x10000
193 #define INT_CLR5 0x20000
197 #define DSPGO 0x00001
198 #define CPUINT 0x00002
199 #define DSPINT0 0x00004
200 #define SINGLE_STEP 0x00008
201 #define SINGLE_GO 0x00010
203 #define INT_LAT0 0x00040
204 #define INT_LAT1 0x00080
205 #define INT_LAT2 0x00100
206 #define INT_LAT3 0x00200
207 #define INT_LAT4 0x00400
208 #define BUS_HOG 0x00800
209 #define VERSION 0x0F000
210 #define INT_LAT5 0x10000
212 extern uint32 jaguar_mainRom_crc32;
214 // Is opcode 62 *really* a NOP? Seems like it...
215 static void dsp_opcode_abs(void);
216 static void dsp_opcode_add(void);
217 static void dsp_opcode_addc(void);
218 static void dsp_opcode_addq(void);
219 static void dsp_opcode_addqmod(void);
220 static void dsp_opcode_addqt(void);
221 static void dsp_opcode_and(void);
222 static void dsp_opcode_bclr(void);
223 static void dsp_opcode_bset(void);
224 static void dsp_opcode_btst(void);
225 static void dsp_opcode_cmp(void);
226 static void dsp_opcode_cmpq(void);
227 static void dsp_opcode_div(void);
228 static void dsp_opcode_imacn(void);
229 static void dsp_opcode_imult(void);
230 static void dsp_opcode_imultn(void);
231 static void dsp_opcode_jr(void);
232 static void dsp_opcode_jump(void);
233 static void dsp_opcode_load(void);
234 static void dsp_opcode_loadb(void);
235 static void dsp_opcode_loadw(void);
236 static void dsp_opcode_load_r14_indexed(void);
237 static void dsp_opcode_load_r14_ri(void);
238 static void dsp_opcode_load_r15_indexed(void);
239 static void dsp_opcode_load_r15_ri(void);
240 static void dsp_opcode_mirror(void);
241 static void dsp_opcode_mmult(void);
242 static void dsp_opcode_move(void);
243 static void dsp_opcode_movei(void);
244 static void dsp_opcode_movefa(void);
245 static void dsp_opcode_move_pc(void);
246 static void dsp_opcode_moveq(void);
247 static void dsp_opcode_moveta(void);
248 static void dsp_opcode_mtoi(void);
249 static void dsp_opcode_mult(void);
250 static void dsp_opcode_neg(void);
251 static void dsp_opcode_nop(void);
252 static void dsp_opcode_normi(void);
253 static void dsp_opcode_not(void);
254 static void dsp_opcode_or(void);
255 static void dsp_opcode_resmac(void);
256 static void dsp_opcode_ror(void);
257 static void dsp_opcode_rorq(void);
258 static void dsp_opcode_xor(void);
259 static void dsp_opcode_sat16s(void);
260 static void dsp_opcode_sat32s(void);
261 static void dsp_opcode_sh(void);
262 static void dsp_opcode_sha(void);
263 static void dsp_opcode_sharq(void);
264 static void dsp_opcode_shlq(void);
265 static void dsp_opcode_shrq(void);
266 static void dsp_opcode_store(void);
267 static void dsp_opcode_storeb(void);
268 static void dsp_opcode_storew(void);
269 static void dsp_opcode_store_r14_indexed(void);
270 static void dsp_opcode_store_r14_ri(void);
271 static void dsp_opcode_store_r15_indexed(void);
272 static void dsp_opcode_store_r15_ri(void);
273 static void dsp_opcode_sub(void);
274 static void dsp_opcode_subc(void);
275 static void dsp_opcode_subq(void);
276 static void dsp_opcode_subqmod(void);
277 static void dsp_opcode_subqt(void);
279 uint8 dsp_opcode_cycles[64] =
299 void (* dsp_opcode[64])() =
301 dsp_opcode_add, dsp_opcode_addc, dsp_opcode_addq, dsp_opcode_addqt,
302 dsp_opcode_sub, dsp_opcode_subc, dsp_opcode_subq, dsp_opcode_subqt,
303 dsp_opcode_neg, dsp_opcode_and, dsp_opcode_or, dsp_opcode_xor,
304 dsp_opcode_not, dsp_opcode_btst, dsp_opcode_bset, dsp_opcode_bclr,
305 dsp_opcode_mult, dsp_opcode_imult, dsp_opcode_imultn, dsp_opcode_resmac,
306 dsp_opcode_imacn, dsp_opcode_div, dsp_opcode_abs, dsp_opcode_sh,
307 dsp_opcode_shlq, dsp_opcode_shrq, dsp_opcode_sha, dsp_opcode_sharq,
308 dsp_opcode_ror, dsp_opcode_rorq, dsp_opcode_cmp, dsp_opcode_cmpq,
309 dsp_opcode_subqmod, dsp_opcode_sat16s, dsp_opcode_move, dsp_opcode_moveq,
310 dsp_opcode_moveta, dsp_opcode_movefa, dsp_opcode_movei, dsp_opcode_loadb,
311 dsp_opcode_loadw, dsp_opcode_load, dsp_opcode_sat32s, dsp_opcode_load_r14_indexed,
312 dsp_opcode_load_r15_indexed, dsp_opcode_storeb, dsp_opcode_storew, dsp_opcode_store,
313 dsp_opcode_mirror, dsp_opcode_store_r14_indexed, dsp_opcode_store_r15_indexed, dsp_opcode_move_pc,
314 dsp_opcode_jump, dsp_opcode_jr, dsp_opcode_mmult, dsp_opcode_mtoi,
315 dsp_opcode_normi, dsp_opcode_nop, dsp_opcode_load_r14_ri, dsp_opcode_load_r15_ri,
316 dsp_opcode_store_r14_ri, dsp_opcode_store_r15_ri, dsp_opcode_nop, dsp_opcode_addqmod,
319 uint32 dsp_opcode_use[65];
321 char * dsp_opcode_str[65]=
323 "add", "addc", "addq", "addqt",
324 "sub", "subc", "subq", "subqt",
325 "neg", "and", "or", "xor",
326 "not", "btst", "bset", "bclr",
327 "mult", "imult", "imultn", "resmac",
328 "imacn", "div", "abs", "sh",
329 "shlq", "shrq", "sha", "sharq",
330 "ror", "rorq", "cmp", "cmpq",
331 "subqmod", "sat16s", "move", "moveq",
332 "moveta", "movefa", "movei", "loadb",
333 "loadw", "load", "sat32s", "load_r14_indexed",
334 "load_r15_indexed", "storeb", "storew", "store",
335 "mirror", "store_r14_indexed","store_r15_indexed","move_pc",
336 "jump", "jr", "mmult", "mtoi",
337 "normi", "nop", "load_r14_ri", "load_r15_ri",
338 "store_r14_ri", "store_r15_ri", "illegal", "addqmod",
343 static uint64 dsp_acc; // 40 bit register, NOT 32!
344 static uint32 dsp_remain;
345 static uint32 dsp_modulo;
346 static uint32 dsp_flags;
347 static uint32 dsp_matrix_control;
348 static uint32 dsp_pointer_to_matrix;
349 static uint32 dsp_data_organization;
351 static uint32 dsp_div_control;
352 static uint8 dsp_flag_z, dsp_flag_n, dsp_flag_c;
353 static uint32 * dsp_reg, * dsp_alternate_reg;
354 static uint32 * dsp_reg_bank_0, * dsp_reg_bank_1;
356 static uint32 dsp_opcode_first_parameter;
357 static uint32 dsp_opcode_second_parameter;
359 #define DSP_RUNNING (dsp_control & 0x01)
361 #define RM dsp_reg[dsp_opcode_first_parameter]
362 #define RN dsp_reg[dsp_opcode_second_parameter]
363 #define ALTERNATE_RM dsp_alternate_reg[dsp_opcode_first_parameter]
364 #define ALTERNATE_RN dsp_alternate_reg[dsp_opcode_second_parameter]
365 #define IMM_1 dsp_opcode_first_parameter
366 #define IMM_2 dsp_opcode_second_parameter
368 #define CLR_Z (dsp_flag_z = 0)
369 #define CLR_ZN (dsp_flag_z = dsp_flag_n = 0)
370 #define CLR_ZNC (dsp_flag_z = dsp_flag_n = dsp_flag_c = 0)
371 #define SET_Z(r) (dsp_flag_z = ((r) == 0))
372 #define SET_N(r) (dsp_flag_n = (((UINT32)(r) >> 31) & 0x01))
373 #define SET_C_ADD(a,b) (dsp_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
374 #define SET_C_SUB(a,b) (dsp_flag_c = ((UINT32)(b) > (UINT32)(a)))
375 #define SET_ZN(r) SET_N(r); SET_Z(r)
376 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
377 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
379 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 };
380 uint8 * dsp_branch_condition_table = NULL;
381 static uint16 * mirror_table = NULL;
382 static uint8 * dsp_ram_8 = NULL;
384 #define BRANCH_CONDITION(x) dsp_branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
386 static uint32 dsp_in_exec = 0;
387 static uint32 dsp_releaseTimeSlice_flag = 0;
392 // Comparison core vars (used only for core comparison! :-)
393 static uint64 count = 0;
394 static uint8 ram1[0x2000], ram2[0x2000];
395 static uint32 regs1[64], regs2[64];
396 static uint32 ctrl1[14], ctrl2[14];
399 // Private function prototypes
401 void DSPDumpRegisters(void);
402 void DSPDumpDisassembly(void);
403 void FlushDSPPipeline(void);
406 void dsp_reset_stats(void)
408 for(int i=0; i<65; i++)
409 dsp_opcode_use[i] = 0;
412 void dsp_releaseTimeslice(void)
414 //This does absolutely nothing!!! !!! FIX !!!
415 dsp_releaseTimeSlice_flag = 1;
418 void dsp_build_branch_condition_table(void)
420 // Allocate the mirror table
422 mirror_table = (uint16 *)malloc(65536 * sizeof(mirror_table[0]));
424 // Fill in the mirror table
426 for(int i=0; i<65536; i++)
427 mirror_table[i] = ((i >> 15) & 0x0001) | ((i >> 13) & 0x0002) |
428 ((i >> 11) & 0x0004) | ((i >> 9) & 0x0008) |
429 ((i >> 7) & 0x0010) | ((i >> 5) & 0x0020) |
430 ((i >> 3) & 0x0040) | ((i >> 1) & 0x0080) |
431 ((i << 1) & 0x0100) | ((i << 3) & 0x0200) |
432 ((i << 5) & 0x0400) | ((i << 7) & 0x0800) |
433 ((i << 9) & 0x1000) | ((i << 11) & 0x2000) |
434 ((i << 13) & 0x4000) | ((i << 15) & 0x8000);
436 if (!dsp_branch_condition_table)
438 dsp_branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(dsp_branch_condition_table[0]));
440 // Fill in the condition table
441 if (dsp_branch_condition_table)
443 for(int i=0; i<8; i++)
445 for(int j=0; j<32; j++)
452 if (!(i & ZERO_FLAG))
455 if (i & (CARRY_FLAG << (j >> 4)))
458 if (!(i & (CARRY_FLAG << (j >> 4))))
460 dsp_branch_condition_table[i * 32 + j] = result;
467 uint8 DSPReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
469 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
470 WriteLog("DSP: ReadByte--Attempt to read from DSP register file by %s!\n", whoName[who]);
472 // if ((offset==0xF1CFE0)||(offset==0xF1CFE2))
475 /* if ((jaguar_mainRom_crc32==0xbfd751a4)||(jaguar_mainRom_crc32==0x053efaf9))
477 if (offset==0xF1CFE0)
480 if (offset >= DSP_WORK_RAM_BASE && offset <= (DSP_WORK_RAM_BASE + 0x1FFF))
481 return dsp_ram_8[offset - DSP_WORK_RAM_BASE];
483 if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
485 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
487 if ((offset&0x03)==0)
490 if ((offset&0x03)==1)
491 return((data>>16)&0xff);
493 if ((offset&0x03)==2)
494 return((data>>8)&0xff);
496 if ((offset&0x03)==3)
500 return JaguarReadByte(offset, who);
503 uint16 DSPReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
505 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
506 WriteLog("DSP: ReadWord--Attempt to read from DSP register file by %s!\n", whoName[who]);
508 offset &= 0xFFFFFFFE;
510 /* if (jaguar_mainRom_crc32==0xa74a97cd)
512 if (offset==0xF1A114) return(0x0000);
513 if (offset==0xF1A116) return(0x0000);
514 if (offset==0xF1B000) return(0x1234);
515 if (offset==0xF1B002) return(0x5678);
518 if (jaguar_mainRom_crc32==0x7ae20823)
520 if (offset==0xF1B9D8) return(0x0000);
521 if (offset==0xF1B9Da) return(0x0000);
522 if (offset==0xF1B2C0) return(0x0000);
523 if (offset==0xF1B2C2) return(0x0000);
526 // pour permettre à wolfenstein 3d de tourner sans le dsp
527 /* if ((offset==0xF1B0D0)||(offset==0xF1B0D2))
531 // pour permettre à nba jam de tourner sans le dsp
532 /* if (jaguar_mainRom_crc32==0x4faddb18)
534 if (offset==0xf1b2c0) return(0);
535 if (offset==0xf1b2c2) return(0);
536 if (offset==0xf1b240) return(0);
537 if (offset==0xf1b242) return(0);
538 if (offset==0xF1B340) return(0);
539 if (offset==0xF1B342) return(0);
540 if (offset==0xF1BAD8) return(0);
541 if (offset==0xF1BADA) return(0);
542 if (offset==0xF1B040) return(0);
543 if (offset==0xF1B042) return(0);
544 if (offset==0xF1B0C0) return(0);
545 if (offset==0xF1B0C2) return(0);
546 if (offset==0xF1B140) return(0);
547 if (offset==0xF1B142) return(0);
548 if (offset==0xF1B1C0) return(0);
549 if (offset==0xF1B1C2) return(0);
552 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE+0x1FFF)
554 offset -= DSP_WORK_RAM_BASE;
555 /* uint16 data = (((uint16)dsp_ram_8[offset])<<8)|((uint16)dsp_ram_8[offset+1]);
557 return GET16(dsp_ram_8, offset);
559 else if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
561 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
564 return data & 0xFFFF;
569 return JaguarReadWord(offset, who);
572 uint32 DSPReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
574 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
575 WriteLog("DSP: ReadLong--Attempt to read from DSP register file by %s!\n", whoName[who]);
578 offset &= 0xFFFFFFFC;
579 /*if (offset == 0xF1BCF4)
581 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));
582 DSPDumpDisassembly();
584 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
586 offset -= DSP_WORK_RAM_BASE;
587 return GET32(dsp_ram_8, offset);
589 //NOTE: Didn't return DSP_ACCUM!!!
590 //Mebbe it's not 'spose to! Yes, it is!
591 if (offset >= DSP_CONTROL_RAM_BASE && offset <= DSP_CONTROL_RAM_BASE + 0x23)
596 case 0x00: /*dsp_flag_c?(dsp_flag_c=1):(dsp_flag_c=0);
597 dsp_flag_z?(dsp_flag_z=1):(dsp_flag_z=0);
598 dsp_flag_n?(dsp_flag_n=1):(dsp_flag_n=0);*/
600 dsp_flags = (dsp_flags & 0xFFFFFFF8) | (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
601 return dsp_flags & 0xFFFFC1FF;
602 case 0x04: return dsp_matrix_control;
603 case 0x08: return dsp_pointer_to_matrix;
604 case 0x0C: return dsp_data_organization;
605 case 0x10: return dsp_pc;
606 case 0x14: return dsp_control;
607 case 0x18: return dsp_modulo;
608 case 0x1C: return dsp_remain;
610 return (int32)((int8)(dsp_acc >> 32)); // Top 8 bits of 40-bit accumulator, sign extended
612 // unaligned long read-- !!! FIX !!!
616 return JaguarReadLong(offset, who);
619 void DSPWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
621 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
622 WriteLog("DSP: WriteByte--Attempt to write to DSP register file by %s!\n", whoName[who]);
624 if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
626 offset -= DSP_WORK_RAM_BASE;
627 dsp_ram_8[offset] = data;
628 //This is rather stupid! !!! FIX !!!
629 /* if (dsp_in_exec == 0)
631 m68k_end_timeslice();
632 gpu_releaseTimeslice();
636 if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
638 uint32 reg = offset & 0x1C;
639 int bytenum = offset & 0x03;
641 if ((reg >= 0x1C) && (reg <= 0x1F))
642 dsp_div_control = (dsp_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
645 //This looks funky. !!! FIX !!!
646 uint32 old_data = DSPReadLong(offset&0xFFFFFFC, who);
647 bytenum = 3 - bytenum; // convention motorola !!!
648 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
649 DSPWriteLong(offset & 0xFFFFFFC, old_data, who);
653 // WriteLog("dsp: writing %.2x at 0x%.8x\n",data,offset);
654 //Should this *ever* happen??? Shouldn't we be saying "unknown" here???
655 JaguarWriteByte(offset, data, who);
658 void DSPWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
660 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
661 WriteLog("DSP: WriteWord--Attempt to write to DSP register file by %s!\n", whoName[who]);
662 offset &= 0xFFFFFFFE;
663 /*if (offset == 0xF1BCF4)
665 WriteLog("DSPWriteWord: Writing to 0xF1BCF4... %04X -> %04X\n", GET16(dsp_ram_8, 0x0CF4), data);
667 // WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset);
668 if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
670 offset -= DSP_WORK_RAM_BASE;
671 dsp_ram_8[offset] = data >> 8;
672 dsp_ram_8[offset+1] = data & 0xFF;
673 //This is rather stupid! !!! FIX !!!
674 /* if (dsp_in_exec == 0)
676 // WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset+DSP_WORK_RAM_BASE);
677 m68k_end_timeslice();
678 gpu_releaseTimeslice();
682 SET16(ram1, offset, data),
683 SET16(ram2, offset, data);
688 else if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
690 if ((offset & 0x1C) == 0x1C)
693 dsp_div_control = (dsp_div_control&0xffff0000)|(data&0xffff);
695 dsp_div_control = (dsp_div_control&0xffff)|((data&0xffff)<<16);
699 uint32 old_data = DSPReadLong(offset & 0xffffffc, who);
701 old_data = (old_data&0xffff0000)|(data&0xffff);
703 old_data = (old_data&0xffff)|((data&0xffff)<<16);
704 DSPWriteLong(offset & 0xffffffc, old_data, who);
709 JaguarWriteWord(offset, data, who);
712 //bool badWrite = false;
713 void DSPWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
715 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
716 WriteLog("DSP: WriteLong--Attempt to write to DSP register file by %s!\n", whoName[who]);
718 offset &= 0xFFFFFFFC;
719 /*if (offset == 0xF1BCF4)
721 WriteLog("DSPWriteLong: Writing to 0xF1BCF4... %08X -> %08X\n", GET32(dsp_ram_8, 0x0CF4), data);
723 // WriteLog("dsp: writing %.8x at 0x%.8x\n",data,offset);
724 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
726 /*if (offset == 0xF1BE2C)
728 WriteLog("DSP: %s is writing %08X at location 0xF1BE2C (DSP_PC: %08X)...\n", whoName[who], data, dsp_pc - 2);
730 offset -= DSP_WORK_RAM_BASE;
731 SET32(dsp_ram_8, offset, data);
734 SET32(ram1, offset, data),
735 SET32(ram2, offset, data);
740 else if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
748 WriteLog("DSP: Writing %08X to DSP_FLAGS by %s (REGPAGE is %s)...\n", data, whoName[who], (dsp_flags & REGPAGE ? "set" : "not set"));
750 // bool IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
751 IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
753 dsp_flag_z = dsp_flags & 0x01;
754 dsp_flag_c = (dsp_flags >> 1) & 0x01;
755 dsp_flag_n = (dsp_flags >> 2) & 0x01;
756 DSPUpdateRegisterBanks();
757 dsp_control &= ~((dsp_flags & CINT04FLAGS) >> 3);
758 dsp_control &= ~((dsp_flags & CINT5FLAG) >> 1);
759 /* if (IMASKCleared) // If IMASK was cleared,
762 WriteLog("DSP: Finished interrupt.\n");
764 DSPHandleIRQs(); // see if any other interrupts need servicing!
771 dsp_matrix_control = data;
774 // According to JTRM, only lines 2-11 are addressable, the rest being
775 // hardwired to $F1Bxxx.
776 dsp_pointer_to_matrix = 0xF1B000 | (data & 0x000FFC);
779 dsp_data_organization = data;
784 WriteLog("DSP: Setting DSP PC to %08X by %s%s\n", dsp_pc, whoName[who], (DSP_RUNNING ? " (DSP is RUNNING!)" : ""));//*/
789 ctrl1[0] = ctrl2[0] = data;
796 WriteLog("Write to DSP CTRL by %s: %08X\n", whoName[who], data);
798 bool wasRunning = DSP_RUNNING;
799 // uint32 dsp_was_running = DSP_RUNNING;
800 // Check for DSP -> CPU interrupt
804 WriteLog("DSP: DSP -> CPU interrupt\n");
807 // Why do we check for a valid handler at 64? Isn't that the Jag programmer's responsibility?
808 if (JERRYIRQEnabled(IRQ2_DSP))// && jaguar_interrupt_handler_is_valid(64))
810 JERRYSetPendingIRQ(IRQ2_DSP);
811 dsp_releaseTimeslice();
812 m68k_set_irq(7); // Set 68000 NMI...
816 // Check for CPU -> DSP interrupt
820 WriteLog("DSP: CPU -> DSP interrupt\n");
822 m68k_end_timeslice();
823 gpu_releaseTimeslice();
824 DSPSetIRQLine(DSPIRQ_CPU, ASSERT_LINE);
828 if (data & SINGLE_STEP)
830 // WriteLog("DSP: Asked to perform a single step (single step is %senabled)\n", (data & 0x8 ? "" : "not "));
833 // Protect writes to VERSION and the interrupt latches...
834 uint32 mask = VERSION | INT_LAT0 | INT_LAT1 | INT_LAT2 | INT_LAT3 | INT_LAT4 | INT_LAT5;
835 dsp_control = (dsp_control & mask) | (data & ~mask);
839 ctrl1[8] = ctrl2[8] = dsp_control;
843 // if dsp wasn't running but is now running
844 // execute a few cycles
845 //This is just plain wrong, wrong, WRONG!
846 #ifndef DSP_SINGLE_STEPPING
847 /* if (!dsp_was_running && DSP_RUNNING)
852 //This is WRONG! !!! FIX !!!
853 if (dsp_control & 0x18)
858 WriteLog(" --> Starting to run at %08X by %s...", dsp_pc, whoName[who]);
860 WriteLog(" --> Stopped by %s! (DSP PC: %08X)", whoName[who], dsp_pc);
863 //This isn't exactly right either--we don't know if it was the M68K or the GPU writing here...
864 // !!! FIX !!! [DONE]
868 m68k_end_timeslice();
870 gpu_releaseTimeslice();
874 //DSPDumpDisassembly();
882 dsp_div_control = data;
884 // default: // unaligned long read
890 //We don't have to break this up like this! We CAN do 32 bit writes!
891 // JaguarWriteWord(offset, (data>>16) & 0xFFFF, DSP);
892 // JaguarWriteWord(offset+2, data & 0xFFFF, DSP);
893 //if (offset > 0xF1FFFF)
895 JaguarWriteLong(offset, data, who);
899 // Update the DSP register file pointers depending on REGPAGE bit
901 void DSPUpdateRegisterBanks(void)
903 int bank = (dsp_flags & REGPAGE);
905 if (dsp_flags & IMASK)
906 bank = 0; // IMASK forces main bank to be bank 0
909 dsp_reg = dsp_reg_bank_1, dsp_alternate_reg = dsp_reg_bank_0;
911 dsp_reg = dsp_reg_bank_0, dsp_alternate_reg = dsp_reg_bank_1;
915 // Check for and handle any asserted DSP IRQs
917 void DSPHandleIRQs(void)
919 if (dsp_flags & IMASK) // Bail if we're already inside an interrupt
922 // Get the active interrupt bits (latches) & interrupt mask (enables)
923 uint32 bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
924 mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
926 // WriteLog("dsp: bits=%.2x mask=%.2x\n",bits,mask);
929 if (!bits) // Bail if nothing is enabled
932 int which = 0; // Determine which interrupt
947 WriteLog("DSP: Generating interrupt #%i...", which);
950 //if (which == 0) doDSPDis = true;
952 // NOTE: Since the actual Jaguar hardware injects the code sequence below
953 // directly into the pipeline, it has the side effect of ensuring that the
954 // instruction interrupted also gets to do its writeback. We simulate that
956 /* if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
958 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
959 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
961 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
962 scoreboard[pipeline[plPtrWrite].operand2] = false;
964 //This should be execute (or should it?--not sure now!)
965 //Actually, the way this is called now, this should be correct (i.e., the plPtrs advance,
966 //and what just executed is now in the Write position...). So why didn't it do the
967 //writeback into register 0?
969 WriteLog("--> Pipeline dump [DSP_PC=%08X]...\n", dsp_pc);
970 WriteLog("\tR -> %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]);
971 WriteLog("\tE -> %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]);
972 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister, dsp_opcode_str[pipeline[plPtrWrite].opcode]);
974 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
976 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
978 if (pipeline[plPtrWrite].writebackRegister != 0xFE)
979 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
982 if (pipeline[plPtrWrite].type == TYPE_BYTE)
983 JaguarWriteByte(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
984 else if (pipeline[plPtrWrite].type == TYPE_WORD)
985 JaguarWriteWord(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
987 JaguarWriteLong(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
991 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
992 scoreboard[pipeline[plPtrWrite].operand2] = false;
998 ctrl2[4] = dsp_flags;
1001 DSPUpdateRegisterBanks();
1002 #ifdef DSP_DEBUG_IRQ
1003 // WriteLog(" [PC will return to %08X, R31 = %08X]\n", dsp_pc, dsp_reg[31]);
1004 WriteLog(" [PC will return to %08X, R31 = %08X]\n", dsp_pc - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2)), dsp_reg[31]);
1007 // subqt #4,r31 ; pre-decrement stack pointer
1008 // move pc,r30 ; address of interrupted code
1009 // store r30,(r31) ; store return address
1016 //This might not come back to the right place if the instruction was MOVEI #. !!! FIX !!!
1017 //But, then again, JTRM says that it adds two regardless of what the instruction was...
1018 //It missed the place that it was supposed to come back to, so this is WRONG!
1020 // Look at the pipeline when an interrupt occurs (instructions of foo, bar, baz):
1022 // R -> baz (<- PC points here)
1023 // E -> bar (when it should point here!)
1026 // 'Foo' just completed executing as per above. PC is pointing to the instruction 'baz'
1027 // which means (assuming they're all 2 bytes long) that the code below will come back on
1028 // instruction 'baz' instead of 'bar' which is the next instruction to execute in the
1029 // instruction stream...
1031 // DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
1032 DSPWriteLong(dsp_reg[31], dsp_pc - 2 - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2)), DSP);
1035 SET32(ram2, regs2[31] - 0xF1B000, dsp_pc - 2 - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2)));
1039 // movei #service_address,r30 ; pointer to ISR entry
1040 // jump (r30) ; jump to ISR
1042 dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
1045 ctrl2[0] = regs2[30] = dsp_pc;
1052 // Non-pipelined version...
1054 void DSPHandleIRQsNP(void)
1058 memcpy(dsp_ram_8, ram1, 0x2000);
1059 memcpy(dsp_reg_bank_0, regs1, 32 * 4);
1060 memcpy(dsp_reg_bank_1, ®s1[32], 32 * 4);
1063 dsp_remain = ctrl1[2];
1064 dsp_modulo = ctrl1[3];
1065 dsp_flags = ctrl1[4];
1066 dsp_matrix_control = ctrl1[5];
1067 dsp_pointer_to_matrix = ctrl1[6];
1068 dsp_data_organization = ctrl1[7];
1069 dsp_control = ctrl1[8];
1070 dsp_div_control = ctrl1[9];
1071 IMASKCleared = ctrl1[10];
1072 dsp_flag_z = ctrl1[11];
1073 dsp_flag_n = ctrl1[12];
1074 dsp_flag_c = ctrl1[13];
1075 DSPUpdateRegisterBanks();
1078 if (dsp_flags & IMASK) // Bail if we're already inside an interrupt
1081 // Get the active interrupt bits (latches) & interrupt mask (enables)
1082 uint32 bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
1083 mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
1085 // WriteLog("dsp: bits=%.2x mask=%.2x\n",bits,mask);
1088 if (!bits) // Bail if nothing is enabled
1091 int which = 0; // Determine which interrupt
1105 #ifdef DSP_DEBUG_IRQ
1106 WriteLog("DSP: Generating interrupt #%i...", which);
1112 ctrl1[4] = dsp_flags;
1115 DSPUpdateRegisterBanks();
1116 #ifdef DSP_DEBUG_IRQ
1117 WriteLog(" [PC will return to %08X, R31 = %08X]\n", dsp_pc, dsp_reg[31]);
1120 // subqt #4,r31 ; pre-decrement stack pointer
1121 // move pc,r30 ; address of interrupted code
1122 // store r30,(r31) ; store return address
1129 DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
1132 SET32(ram1, regs1[31] - 0xF1B000, dsp_pc - 2);
1136 // movei #service_address,r30 ; pointer to ISR entry
1137 // jump (r30) ; jump to ISR
1139 dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
1142 ctrl1[0] = regs1[30] = dsp_pc;
1148 // Set the specified DSP IRQ line to a given state
1150 void DSPSetIRQLine(int irqline, int state)
1152 //NOTE: This doesn't take INT_LAT5 into account. !!! FIX !!!
1153 uint32 mask = INT_LAT0 << irqline;
1154 dsp_control &= ~mask; // Clear the latch bit
1157 ctrl1[8] = ctrl2[8] = dsp_control;
1163 dsp_control |= mask; // Set the latch bit
1167 ctrl1[8] = ctrl2[8] = dsp_control;
1176 memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
1177 memory_malloc_secure((void **)&dsp_reg_bank_0, 32 * sizeof(int32), "DSP bank 0 regs");
1178 memory_malloc_secure((void **)&dsp_reg_bank_1, 32 * sizeof(int32), "DSP bank 1 regs");
1180 dsp_build_branch_condition_table();
1186 dsp_pc = 0x00F1B000;
1187 dsp_acc = 0x00000000;
1188 dsp_remain = 0x00000000;
1189 dsp_modulo = 0xFFFFFFFF;
1190 dsp_flags = 0x00040000;
1191 dsp_matrix_control = 0x00000000;
1192 dsp_pointer_to_matrix = 0x00000000;
1193 dsp_data_organization = 0xFFFFFFFF;
1194 dsp_control = 0x00002000; // Report DSP version 2
1195 dsp_div_control = 0x00000000;
1198 dsp_reg = dsp_reg_bank_0;
1199 dsp_alternate_reg = dsp_reg_bank_1;
1201 for(int i=0; i<32; i++)
1202 dsp_reg[i] = dsp_alternate_reg[i] = 0x00000000;
1205 IMASKCleared = false;
1208 memset(dsp_ram_8, 0xFF, 0x2000);
1211 void DSPDumpDisassembly(void)
1215 WriteLog("\n---[DSP code at 00F1B000]---------------------------\n");
1216 uint32 j = 0xF1B000;
1217 while (j <= 0xF1CFFF)
1220 j += dasmjag(JAGUAR_DSP, buffer, j);
1221 WriteLog("\t%08X: %s\n", oldj, buffer);
1225 void DSPDumpRegisters(void)
1227 //Shoud add modulus, etc to dump here...
1228 WriteLog("\n---[DSP flags: NCZ %d%d%d, DSP PC: %08X]------------\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_pc);
1229 WriteLog("\nRegisters bank 0\n");
1230 for(int j=0; j<8; j++)
1232 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1233 (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
1234 (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
1235 (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
1236 (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
1238 WriteLog("Registers bank 1\n");
1239 for(int j=0; j<8; j++)
1241 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1242 (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
1243 (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
1244 (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
1245 (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
1252 WriteLog("DSP: Stopped at PC=%08X dsp_modulo=%08X (dsp %s running)\n", dsp_pc, dsp_modulo, (DSP_RUNNING ? "was" : "wasn't"));
1253 WriteLog("DSP: %sin interrupt handler\n", (dsp_flags & IMASK ? "" : "not "));
1255 // get the active interrupt bits
1256 int bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F);
1257 // get the interrupt mask
1258 int mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
1260 WriteLog("DSP: pending=%08X enabled=%08X\n", bits, mask);
1261 WriteLog("\nRegisters bank 0\n");
1262 for(int j=0; j<8; j++)
1264 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
1265 (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
1266 (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
1267 (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
1268 (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
1270 WriteLog("\nRegisters bank 1\n");
1273 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
1274 (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
1275 (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
1276 (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
1277 (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
1281 static char buffer[512];
1282 j = DSP_WORK_RAM_BASE;
1283 while (j <= 0xF1BFFF)
1286 j += dasmjag(JAGUAR_DSP, buffer, j);
1287 WriteLog("\t%08X: %s\n", oldj, buffer);
1290 WriteLog("DSP opcodes use:\n");
1293 if (dsp_opcode_use[i])
1294 WriteLog("\t%s %i\n", dsp_opcode_str[i], dsp_opcode_use[i]);
1297 memory_free(dsp_ram_8);
1303 // DSP comparison core...
1306 static uint16 lastExec;
1307 void DSPExecComp(int32 cycles)
1309 while (cycles > 0 && DSP_RUNNING)
1311 // Load up vars for non-pipelined core
1312 memcpy(dsp_ram_8, ram1, 0x2000);
1313 memcpy(dsp_reg_bank_0, regs1, 32 * 4);
1314 memcpy(dsp_reg_bank_1, ®s1[32], 32 * 4);
1317 dsp_remain = ctrl1[2];
1318 dsp_modulo = ctrl1[3];
1319 dsp_flags = ctrl1[4];
1320 dsp_matrix_control = ctrl1[5];
1321 dsp_pointer_to_matrix = ctrl1[6];
1322 dsp_data_organization = ctrl1[7];
1323 dsp_control = ctrl1[8];
1324 dsp_div_control = ctrl1[9];
1325 IMASKCleared = ctrl1[10];
1326 dsp_flag_z = ctrl1[11];
1327 dsp_flag_n = ctrl1[12];
1328 dsp_flag_c = ctrl1[13];
1329 DSPUpdateRegisterBanks();
1331 // Decrement cycles based on non-pipelined core...
1332 uint16 instr1 = DSPReadWord(dsp_pc, DSP);
1333 cycles -= dsp_opcode_cycles[instr1 >> 10];
1335 //WriteLog("\tAbout to execute non-pipelined core on tick #%u (DSP_PC=%08X)...\n", (uint32)count, dsp_pc);
1336 DSPExec(1); // Do *one* instruction
1339 memcpy(ram1, dsp_ram_8, 0x2000);
1340 memcpy(regs1, dsp_reg_bank_0, 32 * 4);
1341 memcpy(®s1[32], dsp_reg_bank_1, 32 * 4);
1344 ctrl1[2] = dsp_remain;
1345 ctrl1[3] = dsp_modulo;
1346 ctrl1[4] = dsp_flags;
1347 ctrl1[5] = dsp_matrix_control;
1348 ctrl1[6] = dsp_pointer_to_matrix;
1349 ctrl1[7] = dsp_data_organization;
1350 ctrl1[8] = dsp_control;
1351 ctrl1[9] = dsp_div_control;
1352 ctrl1[10] = IMASKCleared;
1353 ctrl1[11] = dsp_flag_z;
1354 ctrl1[12] = dsp_flag_n;
1355 ctrl1[13] = dsp_flag_c;
1357 // Load up vars for pipelined core
1358 memcpy(dsp_ram_8, ram2, 0x2000);
1359 memcpy(dsp_reg_bank_0, regs2, 32 * 4);
1360 memcpy(dsp_reg_bank_1, ®s2[32], 32 * 4);
1363 dsp_remain = ctrl2[2];
1364 dsp_modulo = ctrl2[3];
1365 dsp_flags = ctrl2[4];
1366 dsp_matrix_control = ctrl2[5];
1367 dsp_pointer_to_matrix = ctrl2[6];
1368 dsp_data_organization = ctrl2[7];
1369 dsp_control = ctrl2[8];
1370 dsp_div_control = ctrl2[9];
1371 IMASKCleared = ctrl2[10];
1372 dsp_flag_z = ctrl2[11];
1373 dsp_flag_n = ctrl2[12];
1374 dsp_flag_c = ctrl2[13];
1375 DSPUpdateRegisterBanks();
1377 //WriteLog("\tAbout to execute pipelined core on tick #%u (DSP_PC=%08X)...\n", (uint32)count, dsp_pc);
1378 DSPExecP2(1); // Do *one* instruction
1381 memcpy(ram2, dsp_ram_8, 0x2000);
1382 memcpy(regs2, dsp_reg_bank_0, 32 * 4);
1383 memcpy(®s2[32], dsp_reg_bank_1, 32 * 4);
1386 ctrl2[2] = dsp_remain;
1387 ctrl2[3] = dsp_modulo;
1388 ctrl2[4] = dsp_flags;
1389 ctrl2[5] = dsp_matrix_control;
1390 ctrl2[6] = dsp_pointer_to_matrix;
1391 ctrl2[7] = dsp_data_organization;
1392 ctrl2[8] = dsp_control;
1393 ctrl2[9] = dsp_div_control;
1394 ctrl2[10] = IMASKCleared;
1395 ctrl2[11] = dsp_flag_z;
1396 ctrl2[12] = dsp_flag_n;
1397 ctrl2[13] = dsp_flag_c;
1399 if (instr1 != lastExec)
1401 // WriteLog("\nCores diverged at instruction tick #%u!\nAttemping to synchronize...\n\n", count);
1403 // uint32 ppc = ctrl2[0] - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2)) - (pipeline[plPtrWrite].opcode == 38 ? 6 : (pipeline[plPtrWrite].opcode == PIPELINE_STALL ? 0 : 2));
1404 //WriteLog("[DSP_PC1=%08X, DSP_PC2=%08X]\n", ctrl1[0], ppc);
1405 // if (ctrl1[0] < ppc) // P ran ahead of NP
1406 //How to test this crap???
1409 DSPExecP2(1); // Do one more instruction
1412 memcpy(ram2, dsp_ram_8, 0x2000);
1413 memcpy(regs2, dsp_reg_bank_0, 32 * 4);
1414 memcpy(®s2[32], dsp_reg_bank_1, 32 * 4);
1417 ctrl2[2] = dsp_remain;
1418 ctrl2[3] = dsp_modulo;
1419 ctrl2[4] = dsp_flags;
1420 ctrl2[5] = dsp_matrix_control;
1421 ctrl2[6] = dsp_pointer_to_matrix;
1422 ctrl2[7] = dsp_data_organization;
1423 ctrl2[8] = dsp_control;
1424 ctrl2[9] = dsp_div_control;
1425 ctrl2[10] = IMASKCleared;
1426 ctrl2[11] = dsp_flag_z;
1427 ctrl2[12] = dsp_flag_n;
1428 ctrl2[13] = dsp_flag_c;
1430 // else // NP ran ahead of P
1431 if (instr1 != lastExec) // Must be the other way...
1434 // Load up vars for non-pipelined core
1435 memcpy(dsp_ram_8, ram1, 0x2000);
1436 memcpy(dsp_reg_bank_0, regs1, 32 * 4);
1437 memcpy(dsp_reg_bank_1, ®s1[32], 32 * 4);
1440 dsp_remain = ctrl1[2];
1441 dsp_modulo = ctrl1[3];
1442 dsp_flags = ctrl1[4];
1443 dsp_matrix_control = ctrl1[5];
1444 dsp_pointer_to_matrix = ctrl1[6];
1445 dsp_data_organization = ctrl1[7];
1446 dsp_control = ctrl1[8];
1447 dsp_div_control = ctrl1[9];
1448 IMASKCleared = ctrl1[10];
1449 dsp_flag_z = ctrl1[11];
1450 dsp_flag_n = ctrl1[12];
1451 dsp_flag_c = ctrl1[13];
1452 DSPUpdateRegisterBanks();
1454 for(int k=0; k<2; k++)
1456 // Decrement cycles based on non-pipelined core...
1457 instr1 = DSPReadWord(dsp_pc, DSP);
1458 cycles -= dsp_opcode_cycles[instr1 >> 10];
1460 //WriteLog("\tAbout to execute non-pipelined core on tick #%u (DSP_PC=%08X)...\n", (uint32)count, dsp_pc);
1461 DSPExec(1); // Do *one* instruction
1465 memcpy(ram1, dsp_ram_8, 0x2000);
1466 memcpy(regs1, dsp_reg_bank_0, 32 * 4);
1467 memcpy(®s1[32], dsp_reg_bank_1, 32 * 4);
1470 ctrl1[2] = dsp_remain;
1471 ctrl1[3] = dsp_modulo;
1472 ctrl1[4] = dsp_flags;
1473 ctrl1[5] = dsp_matrix_control;
1474 ctrl1[6] = dsp_pointer_to_matrix;
1475 ctrl1[7] = dsp_data_organization;
1476 ctrl1[8] = dsp_control;
1477 ctrl1[9] = dsp_div_control;
1478 ctrl1[10] = IMASKCleared;
1479 ctrl1[11] = dsp_flag_z;
1480 ctrl1[12] = dsp_flag_n;
1481 ctrl1[13] = dsp_flag_c;
1485 if (instr1 != lastExec)
1487 WriteLog("\nCores diverged at instruction tick #%u!\nStopped!\n\n", count);
1489 WriteLog("Instruction for non-pipelined core: %04X\n", instr1);
1490 WriteLog("Instruction for pipelined core: %04X\n", lastExec);
1503 // DSP execution core
1505 //static bool R20Set = false, tripwire = false;
1506 //static uint32 pcQueue[32], ptrPCQ = 0;
1507 void DSPExec(int32 cycles)
1509 /*HACKS!!! -> if (cycles != 1 && jaguar_mainRom_crc32 == 0xba74c3ed)
1510 dsp_check_if_i2s_interrupt_needed();*/
1512 #ifdef DSP_SINGLE_STEPPING
1513 if (dsp_control & 0x18)
1516 dsp_control &= ~0x10;
1519 //There is *no* good reason to do this here!
1521 dsp_releaseTimeSlice_flag = 0;
1524 while (cycles > 0 && DSP_RUNNING)
1526 if (IMASKCleared) // If IMASK was cleared,
1528 #ifdef DSP_DEBUG_IRQ
1529 WriteLog("DSP: Finished interrupt.\n");
1531 DSPHandleIRQsNP(); // See if any other interrupts are pending!
1532 IMASKCleared = false;
1537 WriteLog("\nDSP: Encountered bad write in Atari Synth module. PC=%08X, R15=%08X\n", dsp_pc, dsp_reg[15]);
1538 for(int i=0; i<80; i+=4)
1539 WriteLog(" %08X: %08X\n", dsp_reg[15]+i, JaguarReadLong(dsp_reg[15]+i));
1542 /*if (dsp_pc == 0xF1B55E)
1544 WriteLog("DSP: At $F1B55E--R15 = %08X at %u ms%s...\n", dsp_reg[15], SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1546 /*if (dsp_pc == 0xF1B7D2) // Start here???
1548 pcQueue[ptrPCQ++] = dsp_pc;
1550 uint16 opcode = DSPReadWord(dsp_pc, DSP);
1551 uint32 index = opcode >> 10;
1552 dsp_opcode_first_parameter = (opcode >> 5) & 0x1F;
1553 dsp_opcode_second_parameter = opcode & 0x1F;
1555 dsp_opcode[index]();
1556 dsp_opcode_use[index]++;
1557 cycles -= dsp_opcode_cycles[index];
1558 /*if (dsp_reg_bank_0[20] == 0xF1A100 & !R20Set)
1560 WriteLog("DSP: R20 set to $F1A100 at %u ms%s...\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1563 if (dsp_reg_bank_0[20] != 0xF1A100 && R20Set)
1565 WriteLog("DSP: R20 corrupted at %u ms from starting%s!\nAborting!\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1567 DSPDumpDisassembly();
1570 if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFE) && !tripwire)
1573 WriteLog("DSP: Jumping outside of DSP RAM at %u ms. Register dump:\n", SDL_GetTicks());
1576 WriteLog("\nBacktrace:\n");
1577 for(int i=0; i<32; i++)
1579 dasmjag(JAGUAR_DSP, buffer, pcQueue[(ptrPCQ + i) % 32]);
1580 WriteLog("\t%08X: %s\n", pcQueue[(ptrPCQ + i) % 32], buffer);
1590 // DSP opcode handlers
1593 // There is a problem here with interrupt handlers the JUMP and JR instructions that
1594 // can cause trouble because an interrupt can occur *before* the instruction following the
1595 // jump can execute... !!! FIX !!!
1596 static void dsp_opcode_jump(void)
1599 char * condition[32] =
1600 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1601 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1602 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1603 "???", "???", "???", "F" };
1605 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);
1608 /* dsp_flag_c=dsp_flag_c?1:0;
1609 dsp_flag_z=dsp_flag_z?1:0;
1610 dsp_flag_n=dsp_flag_n?1:0;*/
1611 // KLUDGE: Used by BRANCH_CONDITION
1612 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1614 if (BRANCH_CONDITION(IMM_2))
1618 WriteLog("Branched!\n");
1620 uint32 delayed_pc = RM;
1622 dsp_pc = delayed_pc;
1627 WriteLog("Branch NOT taken.\n");
1631 static void dsp_opcode_jr(void)
1634 char * condition[32] =
1635 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1636 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1637 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1638 "???", "???", "???", "F" };
1640 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);
1643 /* dsp_flag_c=dsp_flag_c?1:0;
1644 dsp_flag_z=dsp_flag_z?1:0;
1645 dsp_flag_n=dsp_flag_n?1:0;*/
1646 // KLUDGE: Used by BRANCH_CONDITION
1647 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1649 if (BRANCH_CONDITION(IMM_2))
1653 WriteLog("Branched!\n");
1655 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1656 int32 delayed_pc = dsp_pc + (offset * 2);
1658 dsp_pc = delayed_pc;
1663 WriteLog("Branch NOT taken.\n");
1667 static void dsp_opcode_add(void)
1671 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);
1673 UINT32 res = RN + RM;
1674 SET_ZNC_ADD(RN, RM, res);
1678 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);
1682 static void dsp_opcode_addc(void)
1686 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);
1688 UINT32 res = RN + RM + dsp_flag_c;
1689 UINT32 carry = dsp_flag_c;
1690 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1691 SET_ZNC_ADD(RN + carry, RM, res);
1692 // SET_ZNC_ADD(RN, RM + carry, res);
1696 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);
1700 static void dsp_opcode_addq(void)
1704 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);
1706 UINT32 r1 = dsp_convert_zero[IMM_1];
1707 UINT32 res = RN + r1;
1708 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1712 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1716 static void dsp_opcode_sub(void)
1720 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);
1722 UINT32 res = RN - RM;
1723 SET_ZNC_SUB(RN, RM, res);
1727 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);
1731 static void dsp_opcode_subc(void)
1735 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);
1737 UINT32 res = RN - RM - dsp_flag_c;
1738 UINT32 borrow = dsp_flag_c;
1739 SET_ZNC_SUB(RN - borrow, RM, res);
1743 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);
1747 static void dsp_opcode_subq(void)
1751 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);
1753 UINT32 r1 = dsp_convert_zero[IMM_1];
1754 UINT32 res = RN - r1;
1755 SET_ZNC_SUB(RN, r1, res);
1759 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1763 static void dsp_opcode_cmp(void)
1767 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);
1769 UINT32 res = RN - RM;
1770 SET_ZNC_SUB(RN, RM, res);
1773 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1777 static void dsp_opcode_cmpq(void)
1779 static int32 sqtable[32] =
1780 { 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 };
1783 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);
1785 UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1786 UINT32 res = RN - r1;
1787 SET_ZNC_SUB(RN, r1, res);
1790 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1794 static void dsp_opcode_and(void)
1798 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);
1804 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);
1808 static void dsp_opcode_or(void)
1812 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);
1818 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);
1822 static void dsp_opcode_xor(void)
1826 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);
1832 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);
1836 static void dsp_opcode_not(void)
1840 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);
1846 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);
1850 static void dsp_opcode_move_pc(void)
1855 static void dsp_opcode_store_r14_indexed(void)
1857 #ifdef DSP_DIS_STORE14I
1859 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));
1861 DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1864 static void dsp_opcode_store_r15_indexed(void)
1866 #ifdef DSP_DIS_STORE15I
1868 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));
1870 DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1873 static void dsp_opcode_load_r14_ri(void)
1875 #ifdef DSP_DIS_LOAD14R
1877 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);
1879 RN = DSPReadLong(dsp_reg[14] + RM, DSP);
1880 #ifdef DSP_DIS_LOAD14R
1882 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1886 static void dsp_opcode_load_r15_ri(void)
1888 #ifdef DSP_DIS_LOAD15R
1890 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);
1892 RN = DSPReadLong(dsp_reg[15] + RM, DSP);
1893 #ifdef DSP_DIS_LOAD15R
1895 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1899 static void dsp_opcode_store_r14_ri(void)
1901 DSPWriteLong(dsp_reg[14] + RM, RN, DSP);
1904 static void dsp_opcode_store_r15_ri(void)
1906 DSPWriteLong(dsp_reg[15] + RM, RN, DSP);
1909 static void dsp_opcode_nop(void)
1913 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", dsp_pc-2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
1917 static void dsp_opcode_storeb(void)
1919 #ifdef DSP_DIS_STOREB
1921 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);
1923 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1924 DSPWriteLong(RM, RN & 0xFF, DSP);
1926 JaguarWriteByte(RM, RN, DSP);
1929 static void dsp_opcode_storew(void)
1931 #ifdef DSP_DIS_STOREW
1933 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);
1935 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1936 DSPWriteLong(RM, RN & 0xFFFF, DSP);
1938 JaguarWriteWord(RM, RN, DSP);
1941 static void dsp_opcode_store(void)
1943 #ifdef DSP_DIS_STORE
1945 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);
1947 DSPWriteLong(RM, RN, DSP);
1950 static void dsp_opcode_loadb(void)
1952 #ifdef DSP_DIS_LOADB
1954 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);
1956 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1957 RN = DSPReadLong(RM, DSP) & 0xFF;
1959 RN = JaguarReadByte(RM, DSP);
1960 #ifdef DSP_DIS_LOADB
1962 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1966 static void dsp_opcode_loadw(void)
1968 #ifdef DSP_DIS_LOADW
1970 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);
1972 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1973 RN = DSPReadLong(RM, DSP) & 0xFFFF;
1975 RN = JaguarReadWord(RM, DSP);
1976 #ifdef DSP_DIS_LOADW
1978 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1982 static void dsp_opcode_load(void)
1986 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);
1988 RN = DSPReadLong(RM, DSP);
1991 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1995 static void dsp_opcode_load_r14_indexed(void)
1997 #ifdef DSP_DIS_LOAD14I
1999 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);
2001 RN = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), DSP);
2002 #ifdef DSP_DIS_LOAD14I
2004 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2008 static void dsp_opcode_load_r15_indexed(void)
2010 #ifdef DSP_DIS_LOAD15I
2012 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);
2014 RN = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), DSP);
2015 #ifdef DSP_DIS_LOAD15I
2017 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2021 static void dsp_opcode_movei(void)
2023 #ifdef DSP_DIS_MOVEI
2025 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);
2027 // This instruction is followed by 32-bit value in LSW / MSW format...
2028 RN = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
2030 #ifdef DSP_DIS_MOVEI
2032 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2036 static void dsp_opcode_moveta(void)
2038 #ifdef DSP_DIS_MOVETA
2040 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);
2043 #ifdef DSP_DIS_MOVETA
2045 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);
2049 static void dsp_opcode_movefa(void)
2051 #ifdef DSP_DIS_MOVEFA
2053 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);
2056 #ifdef DSP_DIS_MOVEFA
2058 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);
2062 static void dsp_opcode_move(void)
2066 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);
2071 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);
2075 static void dsp_opcode_moveq(void)
2077 #ifdef DSP_DIS_MOVEQ
2079 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);
2082 #ifdef DSP_DIS_MOVEQ
2084 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2088 static void dsp_opcode_resmac(void)
2090 #ifdef DSP_DIS_RESMAC
2092 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));
2094 RN = (uint32)dsp_acc;
2095 #ifdef DSP_DIS_RESMAC
2097 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2101 static void dsp_opcode_imult(void)
2103 #ifdef DSP_DIS_IMULT
2105 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);
2107 RN = (int16)RN * (int16)RM;
2109 #ifdef DSP_DIS_IMULT
2111 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);
2115 static void dsp_opcode_mult(void)
2119 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);
2121 RN = (uint16)RM * (uint16)RN;
2125 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);
2129 static void dsp_opcode_bclr(void)
2133 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);
2135 UINT32 res = RN & ~(1 << IMM_1);
2140 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2144 static void dsp_opcode_btst(void)
2148 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);
2150 dsp_flag_z = (~RN >> IMM_1) & 1;
2153 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2157 static void dsp_opcode_bset(void)
2161 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);
2163 UINT32 res = RN | (1 << IMM_1);
2168 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2172 static void dsp_opcode_subqt(void)
2174 #ifdef DSP_DIS_SUBQT
2176 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);
2178 RN -= dsp_convert_zero[IMM_1];
2179 #ifdef DSP_DIS_SUBQT
2181 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2185 static void dsp_opcode_addqt(void)
2187 #ifdef DSP_DIS_ADDQT
2189 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);
2191 RN += dsp_convert_zero[IMM_1];
2192 #ifdef DSP_DIS_ADDQT
2194 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2198 static void dsp_opcode_imacn(void)
2200 #ifdef DSP_DIS_IMACN
2202 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);
2204 int32 res = (int16)RM * (int16)RN;
2205 dsp_acc += (int64)res;
2206 //Should we AND the result to fit into 40 bits here???
2207 #ifdef DSP_DIS_IMACN
2209 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));
2213 static void dsp_opcode_mtoi(void)
2215 RN = (((INT32)RM >> 8) & 0xFF800000) | (RM & 0x007FFFFF);
2219 static void dsp_opcode_normi(void)
2226 while ((_Rm & 0xffc00000) == 0)
2231 while ((_Rm & 0xff800000) != 0)
2241 static void dsp_opcode_mmult(void)
2243 int count = dsp_matrix_control&0x0f;
2244 uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
2248 if (!(dsp_matrix_control & 0x10))
2250 for (int i = 0; i < count; i++)
2254 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
2256 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
2257 int16 b=((int16)DSPReadWord(addr + 2, DSP));
2264 for (int i = 0; i < count; i++)
2268 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
2270 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
2271 int16 b=((int16)DSPReadWord(addr + 2, DSP));
2276 RN = res = (int32)accum;
2278 //NOTE: The flags are set based upon the last add/multiply done...
2282 static void dsp_opcode_abs(void)
2287 if (_Rn == 0x80000000)
2291 dsp_flag_c = ((_Rn & 0x80000000) >> 31);
2292 res = RN = (_Rn & 0x80000000 ? -_Rn : _Rn);
2297 static void dsp_opcode_div(void)
2304 if (dsp_div_control & 1)
2306 dsp_remain = (((uint64)_Rn) << 16) % _Rm;
2307 if (dsp_remain&0x80000000)
2309 RN = (((uint64)_Rn) << 16) / _Rm;
2313 dsp_remain = _Rn % _Rm;
2314 if (dsp_remain&0x80000000)
2323 static void dsp_opcode_imultn(void)
2325 #ifdef DSP_DIS_IMULTN
2327 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);
2329 // This is OK, since this multiply won't overflow 32 bits...
2330 int32 res = (int32)((int16)RN * (int16)RM);
2331 dsp_acc = (int64)res;
2333 #ifdef DSP_DIS_IMULTN
2335 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));
2339 static void dsp_opcode_neg(void)
2343 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);
2346 SET_ZNC_SUB(0, RN, res);
2350 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2354 static void dsp_opcode_shlq(void)
2358 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);
2360 INT32 r1 = 32 - IMM_1;
2361 UINT32 res = RN << r1;
2362 SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
2366 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2370 static void dsp_opcode_shrq(void)
2374 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);
2376 INT32 r1 = dsp_convert_zero[IMM_1];
2377 UINT32 res = RN >> r1;
2378 SET_ZN(res); dsp_flag_c = RN & 1;
2382 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2386 static void dsp_opcode_ror(void)
2390 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);
2392 UINT32 r1 = RM & 0x1F;
2393 UINT32 res = (RN >> r1) | (RN << (32 - r1));
2394 SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
2398 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);
2402 static void dsp_opcode_rorq(void)
2406 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);
2408 UINT32 r1 = dsp_convert_zero[IMM_1 & 0x1F];
2410 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
2412 SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
2415 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2419 static void dsp_opcode_sha(void)
2421 int32 sRm=(int32)RM;
2427 if (shift>=32) shift=32;
2428 dsp_flag_c=(_Rn&0x80000000)>>31;
2438 if (shift>=32) shift=32;
2442 _Rn=((int32)_Rn)>>1;
2450 static void dsp_opcode_sharq(void)
2452 #ifdef DSP_DIS_SHARQ
2454 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);
2456 UINT32 res = (INT32)RN >> dsp_convert_zero[IMM_1];
2457 SET_ZN(res); dsp_flag_c = RN & 0x01;
2459 #ifdef DSP_DIS_SHARQ
2461 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2465 static void dsp_opcode_sh(void)
2467 int32 sRm=(int32)RM;
2472 uint32 shift=(-sRm);
2473 if (shift>=32) shift=32;
2474 dsp_flag_c=(_Rn&0x80000000)>>31;
2484 if (shift>=32) shift=32;
2496 void dsp_opcode_addqmod(void)
2498 #ifdef DSP_DIS_ADDQMOD
2500 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);
2502 UINT32 r1 = dsp_convert_zero[IMM_1];
2504 UINT32 res = r2 + r1;
2505 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2507 SET_ZNC_ADD(r2, r1, res);
2508 #ifdef DSP_DIS_ADDQMOD
2510 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2514 void dsp_opcode_subqmod(void)
2516 UINT32 r1 = dsp_convert_zero[IMM_1];
2518 UINT32 res = r2 - r1;
2519 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2522 SET_ZNC_SUB(r2, r1, res);
2525 void dsp_opcode_mirror(void)
2528 RN = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
2532 void dsp_opcode_sat32s(void)
2534 INT32 r2 = (UINT32)RN;
2535 INT32 temp = dsp_acc >> 32;
2536 UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
2541 void dsp_opcode_sat16s(void)
2544 UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
2550 // New pipelined DSP core
2553 static void DSP_abs(void);
2554 static void DSP_add(void);
2555 static void DSP_addc(void);
2556 static void DSP_addq(void);
2557 static void DSP_addqmod(void);
2558 static void DSP_addqt(void);
2559 static void DSP_and(void);
2560 static void DSP_bclr(void);
2561 static void DSP_bset(void);
2562 static void DSP_btst(void);
2563 static void DSP_cmp(void);
2564 static void DSP_cmpq(void);
2565 static void DSP_div(void);
2566 static void DSP_imacn(void);
2567 static void DSP_imult(void);
2568 static void DSP_imultn(void);
2569 static void DSP_illegal(void);
2570 static void DSP_jr(void);
2571 static void DSP_jump(void);
2572 static void DSP_load(void);
2573 static void DSP_loadb(void);
2574 static void DSP_loadw(void);
2575 static void DSP_load_r14_i(void);
2576 static void DSP_load_r14_r(void);
2577 static void DSP_load_r15_i(void);
2578 static void DSP_load_r15_r(void);
2579 static void DSP_mirror(void);
2580 static void DSP_mmult(void);
2581 static void DSP_move(void);
2582 static void DSP_movefa(void);
2583 static void DSP_movei(void);
2584 static void DSP_movepc(void);
2585 static void DSP_moveq(void);
2586 static void DSP_moveta(void);
2587 static void DSP_mtoi(void);
2588 static void DSP_mult(void);
2589 static void DSP_neg(void);
2590 static void DSP_nop(void);
2591 static void DSP_normi(void);
2592 static void DSP_not(void);
2593 static void DSP_or(void);
2594 static void DSP_resmac(void);
2595 static void DSP_ror(void);
2596 static void DSP_rorq(void);
2597 static void DSP_sat16s(void);
2598 static void DSP_sat32s(void);
2599 static void DSP_sh(void);
2600 static void DSP_sha(void);
2601 static void DSP_sharq(void);
2602 static void DSP_shlq(void);
2603 static void DSP_shrq(void);
2604 static void DSP_store(void);
2605 static void DSP_storeb(void);
2606 static void DSP_storew(void);
2607 static void DSP_store_r14_i(void);
2608 static void DSP_store_r14_r(void);
2609 static void DSP_store_r15_i(void);
2610 static void DSP_store_r15_r(void);
2611 static void DSP_sub(void);
2612 static void DSP_subc(void);
2613 static void DSP_subq(void);
2614 static void DSP_subqmod(void);
2615 static void DSP_subqt(void);
2616 static void DSP_xor(void);
2618 void (* DSPOpcode[64])() =
2620 DSP_add, DSP_addc, DSP_addq, DSP_addqt,
2621 DSP_sub, DSP_subc, DSP_subq, DSP_subqt,
2622 DSP_neg, DSP_and, DSP_or, DSP_xor,
2623 DSP_not, DSP_btst, DSP_bset, DSP_bclr,
2625 DSP_mult, DSP_imult, DSP_imultn, DSP_resmac,
2626 DSP_imacn, DSP_div, DSP_abs, DSP_sh,
2627 DSP_shlq, DSP_shrq, DSP_sha, DSP_sharq,
2628 DSP_ror, DSP_rorq, DSP_cmp, DSP_cmpq,
2630 DSP_subqmod, DSP_sat16s, DSP_move, DSP_moveq,
2631 DSP_moveta, DSP_movefa, DSP_movei, DSP_loadb,
2632 DSP_loadw, DSP_load, DSP_sat32s, DSP_load_r14_i,
2633 DSP_load_r15_i, DSP_storeb, DSP_storew, DSP_store,
2635 DSP_mirror, DSP_store_r14_i, DSP_store_r15_i, DSP_movepc,
2636 DSP_jump, DSP_jr, DSP_mmult, DSP_mtoi,
2637 DSP_normi, DSP_nop, DSP_load_r14_r, DSP_load_r15_r,
2638 DSP_store_r14_r, DSP_store_r15_r, DSP_illegal, DSP_addqmod
2641 bool readAffected[64][2] =
2643 { true, true}, { true, true}, {false, true}, {false, true},
2644 { true, true}, { true, true}, {false, true}, {false, true},
2645 {false, true}, { true, true}, { true, true}, { true, true},
2646 {false, true}, {false, true}, {false, true}, {false, true},
2648 { true, true}, { true, true}, { true, true}, {false, true},
2649 { true, true}, { true, true}, {false, true}, { true, true},
2650 {false, true}, {false, true}, { true, true}, {false, true},
2651 { true, true}, {false, true}, { true, true}, {false, true},
2653 {false, true}, {false, true}, { true, false}, {false, false},
2654 { true, false}, {false, false}, {false, false}, { true, false},
2655 { true, false}, { true, false}, {false, true}, { true, false},
2656 { true, false}, { true, true}, { true, true}, { true, true},
2658 {false, true}, { true, true}, { true, true}, {false, true},
2659 { true, false}, { true, false}, { true, true}, { true, false},
2660 { true, false}, {false, false}, { true, false}, { true, false},
2661 { true, true}, { true, true}, {false, false}, {false, true}
2664 void FlushDSPPipeline(void)
2666 plPtrFetch = 3, plPtrRead = 2, plPtrExec = 1, plPtrWrite = 0;
2668 for(int i=0; i<4; i++)
2669 pipeline[i].opcode = PIPELINE_STALL;
2671 for(int i=0; i<32; i++)
2672 scoreboard[i] = false;
2676 // New pipelined DSP execution core
2678 /*void DSPExecP(int32 cycles)
2680 // bool inhibitFetch = false;
2682 dsp_releaseTimeSlice_flag = 0;
2685 while (cycles > 0 && DSP_RUNNING)
2687 WriteLog("DSPExecP: Pipeline status...\n");
2688 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);
2689 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);
2690 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);
2691 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);
2692 WriteLog(" --> Scoreboard: ");
2693 for(int i=0; i<32; i++)
2694 WriteLog("%s ", scoreboard[i] ? "T" : "F");
2696 // Stage 1: Instruction fetch
2697 // if (!inhibitFetch)
2699 pipeline[plPtrFetch].instruction = DSPReadWord(dsp_pc, DSP);
2700 pipeline[plPtrFetch].opcode = pipeline[plPtrFetch].instruction >> 10;
2701 pipeline[plPtrFetch].operand1 = (pipeline[plPtrFetch].instruction >> 5) & 0x1F;
2702 pipeline[plPtrFetch].operand2 = pipeline[plPtrFetch].instruction & 0x1F;
2703 if (pipeline[plPtrFetch].opcode == 38)
2704 pipeline[plPtrFetch].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
2705 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
2708 // inhibitFetch = false;
2709 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrFetch].instruction, dsp_pc);
2711 WriteLog("DSPExecP: Pipeline status (after stage 1)...\n");
2712 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);
2713 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);
2714 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);
2715 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);
2716 // Stage 2: Read registers
2717 //Ok, stalls here depend on whether or not the instruction reads two registers or not
2718 //and *which* register (1 or 2) is the one being read... !!! FIX !!!
2719 if (scoreboard[pipeline[plPtrRead].operand2])
2720 && pipeline[plPtrRead].opcode != PIPELINE_STALL)
2721 // We have a hit in the scoreboard, so we have to stall the pipeline...
2723 //This is crappy, crappy CRAPPY! And it doesn't work! !!! FIX !!!
2724 // dsp_pc -= (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2725 WriteLog(" --> Stalling pipeline: scoreboard = %s\n", scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
2726 pipeline[plPtrFetch] = pipeline[plPtrRead];
2727 pipeline[plPtrRead].opcode = PIPELINE_STALL;
2731 pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
2732 pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
2733 pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2; // Set it to RN
2735 if (pipeline[plPtrRead].opcode != PIPELINE_STALL)
2736 // Shouldn't we be more selective with the register scoreboarding?
2737 // Yes, we should. !!! FIX !!!
2738 scoreboard[pipeline[plPtrRead].operand2] = true;
2739 //Advance PC here??? Yes.
2740 // dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2741 //This is a mangling of the pipeline stages, but what else to do???
2742 dsp_pc += (pipeline[plPtrFetch].opcode == 38 ? 6 : 2);
2745 WriteLog("DSPExecP: Pipeline status (after stage 2)...\n");
2746 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);
2747 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);
2748 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);
2749 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);
2751 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
2753 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
2754 DSPOpcode[pipeline[plPtrExec].opcode]();
2755 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
2756 cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
2761 WriteLog("DSPExecP: Pipeline status (after stage 3)...\n");
2762 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);
2763 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);
2764 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);
2765 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);
2766 // Stage 4: Write back register
2767 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
2769 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
2770 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
2772 scoreboard[pipeline[plPtrWrite].operand1]
2773 = scoreboard[pipeline[plPtrWrite].operand2] = false;
2776 // Push instructions through the pipeline...
2777 plPtrFetch = (++plPtrFetch) & 0x03;
2778 plPtrRead = (++plPtrRead) & 0x03;
2779 plPtrExec = (++plPtrExec) & 0x03;
2780 plPtrWrite = (++plPtrWrite) & 0x03;
2787 //Problems: JR and any other instruction that relies on DSP_PC is getting WRONG values!
2789 // Should be fixed now. Another problem is figuring how to do the sequence following
2790 // a branch followed with the JR & JUMP instructions...
2792 // There are two conflicting problems:
2795 F1B236: LOAD (R31), R03 [NCZ:000, R31=00F1CFDC, R03=00F14000] -> [NCZ:000, R03=00F1B084]
2796 F1B238: BCLR #3, R00 [NCZ:000, R00=00004039] -> [NCZ:000, R00=00004031]
2797 F1B23A: ADDQ #2, R03 [NCZ:000, R03=00F1B084] -> [NCZ:000, R03=00F1B086]
2798 F1B23C: SUBQ #1, R17 [NCZ:000, R17=00000040] -> [NCZ:000, R17=0000003F]
2799 F1B23E: MOVEI #$00F1CFE0, R31 [NCZ:000, R31=00F1CFDC] -> [NCZ:000, R31=00F1CFE0]
2800 F1B244: JR z, F1B254 [NCZ:000] Branch NOT taken.
2801 F1B246: BSET #10, R00 [NCZ:000, R00=00004031] -> [NCZ:000, R00=00004431]
2802 F1B248: MOVEI #$00F1A100, R01 [NCZ:000, R01=00F1A148] -> [NCZ:000, R01=00F1A100]
2803 F1B24E: STORE R00, (R01) [NCZ:000, R00=00004431, R01=00F1A100]
2804 DSP: Writing 00004431 to DSP_FLAGS by DSP...
2805 DSP: Finished interrupt.
2806 ; Without pipeline effects, the value in R03 is erroneously read from bank 1 instead of
2807 ; bank 0 (where is was prepared)!
2808 F1B250: JUMP T, (R03) [NCZ:001, R03=00000000] Branched!
2809 F1B252: NOP [NCZ:001]
2812 // The other is when you see this at the end of an IRQ:
2815 JUMP T, (R29) ; R29 = Previous stack + 2
2816 STORE R28, (R30) ; R28 = Modified flags register, R30 = $F1A100
2818 ; Actually, this is OK if we do the atomic JUMP/JR operation correctly:
2819 ; 1) The STORE goes through the pipeline and is executed/written back
2820 ; 2) The pipeline is flushed
2821 ; 3) The DSP_PC is set to the new address
2822 ; 4) Execution resumes
2824 JUMP T, (R25) ; Oops! Because of pipeline effects R25 has the value from
2825 ; bank 0 instead of the current bank 1 and so goes astray!
2828 //One other thing: Since these stages are supposed to happen simulaneously, try executing
2829 //them in reverse order to see if that reduces pipeline stalls from late writebacks...
2833 Small problem here: The return address when INT0 comes up is $F1B088, but when INT1
2834 follows it, the JUMP out of the previous interrupt is bypassed immediately--this is
2835 because the STORE instruction writes back on stage #2 of the pipeline instead of stage #3...
2836 If it were done properly, the STORE write back would occur *after* (well, technically,
2837 during) the execution of the the JUMP that follows it.
2841 F1B08A: JR z, F1B082 [NCZ:001] Branched!
2842 F1B08A: NOP [NCZ:001]
2844 F1B080: MOVEI #$00F1B178, R00 [NCZ:001, R00=00F1B178] -> [NCZ:001, R00=00F1B178]
2847 F1B086: LOAD (R00), R01 [NCZ:001, R00=00F1B178, R01=00000000] -> [NCZ:001, R01=00000000]
2850 F1B088: OR R01, R01 [NCZ:001, R01=00000000, R01=00000000] -> [NCZ:001, R01=00000000, R01=00000000]
2851 F1B08A: JR z, F1B082 [NCZ:001] Branched!
2852 F1B08A: NOP [NCZ:001]
2854 F1B080: MOVEI #$00F1B178, R00 [NCZ:001, R00=00F1B178] -> [NCZ:001, R00=00F1B178]
2857 Write to DSP CTRL: 00002301 --> Starting to run at 00F1B088 by M68K...
2858 DSP: CPU -> DSP interrupt
2859 DSP: Generating interrupt #0... [PC will return to 00F1B088, R31 = 00F1CFE0]
2860 Write to DSP CTRL: 00000001 --> Starting to run at 00F1B000 by M68K...
2862 F1B000: MOVEI #$00F1B0D4, R30 [NCZ:001, R30=00F1B000] -> [NCZ:001, R30=00F1B0D4]
2865 F1B006: JUMP T, (R30) [NCZ:001, R30=00F1B0D4] Branched!
2866 F1B006: NOP [NCZ:001]
2868 F1B0D4: MOVEI #$00F1A100, R01 [NCZ:001, R01=00F1A100] -> [NCZ:001, R01=00F1A100]
2871 F1B0DA: LOAD (R01), R00 [NCZ:001, R01=00F1A100, R00=00004431] -> [NCZ:001, R00=00004039]
2872 F1B0DC: MOVEI #$00F1B0C8, R01 [NCZ:001, R01=00F1A100] -> [NCZ:001, R01=00F1B0C8]
2875 F1B0E2: LOAD (R01), R02 [NCZ:001, R01=00F1B0C8, R02=00000000] -> [NCZ:001, R02=00000001]
2876 F1B0E4: MOVEI #$00F1B0CC, R01 [NCZ:001, R01=00F1B0C8] -> [NCZ:001, R01=00F1B0CC]
2879 F1B0EA: LOAD (R01), R03 [NCZ:001, R01=00F1B0CC, R03=00F1B086] -> [NCZ:001, R03=00000064]
2880 F1B0EC: MOVEI #$00F1B0D0, R01 [NCZ:001, R01=00F1B0CC] -> [NCZ:001, R01=00F1B0D0]
2883 F1B0F2: LOAD (R01), R04 [NCZ:001, R01=00F1B0D0, R04=00000000] -> [NCZ:001, R04=00000008]
2884 F1B0F4: MOVEI #$00F1B0BC, R01 [NCZ:001, R01=00F1B0D0] -> [NCZ:001, R01=00F1B0BC]
2887 F1B0FA: ADD R04, R01 [NCZ:001, R04=00000008, R01=00F1B0BC] -> [NCZ:000, R04=00000008, R01=00F1B0C4]
2890 F1B0FC: LOAD (R01), R01 [NCZ:000, R01=00F1B0C4, R01=00F1B0C4] -> [NCZ:000, R01=00F1B12E]
2893 F1B0FE: JUMP T, (R01) [NCZ:000, R01=00F1B12E] Branched!
2894 F1B0FE: NOP [NCZ:000]
2896 F1B12E: MOVE R02, R08 [NCZ:000, R02=00000001, R08=00000000] -> [NCZ:000, R02=00000001, R08=00000001]
2899 F1B132: MOVEI #$00F1B102, R01 [NCZ:000, R01=00F1B12E] -> [NCZ:000, R01=00F1B102]
2902 F1B138: JUMP T, (R01) [NCZ:000, R01=00F1B102] Branched!
2903 F1B138: NOP [NCZ:000]
2905 F1B102: MOVEI #$00F1B0C8, R01 [NCZ:000, R01=00F1B102] -> [NCZ:000, R01=00F1B0C8]
2908 F1B108: STORE R08, (R01) [NCZ:000, R08=00000000, R01=00F1B0C8]
2909 F1B10A: MOVEI #$00F1B0D0, R01 [NCZ:000, R01=00F1B0C8] -> [NCZ:000, R01=00F1B0D0]
2910 F1B110: MOVEQ #0, R04 [NCZ:000, R04=00000008] -> [NCZ:000, R04=00000000]
2913 F1B112: STORE R04, (R01) [NCZ:000, R04=00000000, R01=00F1B0D0]
2914 F1B114: BCLR #3, R00 [NCZ:000, R00=00004039] -> [NCZ:000, R00=00004031]
2917 F1B116: BSET #9, R00 [NCZ:000, R00=00004031] -> [NCZ:000, R00=00004231]
2918 F1B118: LOAD (R31), R04 [NCZ:000, R31=00F1CFDC, R04=00000000] -> [NCZ:000, R04=00F1B086]
2919 F1B11A: MOVEI #$00F1CFE0, R31 [NCZ:000, R31=00F1CFDC] -> [NCZ:000, R31=00F1CFE0]
2921 F1B120: ADDQ #2, R04 [NCZ:000, R04=00F1B086] -> [NCZ:000, R04=00F1B088]
2922 F1B122: MOVEI #$00F1A100, R01 [NCZ:000, R01=00F1B0D0] -> [NCZ:000, R01=00F1A100]
2925 F1B128: STORE R00, (R01) [NCZ:000, R00=00004231, R01=00F1A100]
2926 DSP: Writing 00004231 to DSP_FLAGS by DSP (REGPAGE is set)...
2927 DSP: Finished interrupt.
2928 DSP: Generating interrupt #1... [PC will return to 00F1B12A, R31 = 00F1CFE0]
2930 F1B010: MOVEI #$00F1B1FC, R30 [NCZ:001, R30=00F1B010] -> [NCZ:001, R30=00F1B1FC]
2933 F1B016: JUMP T, (R30) [NCZ:001, R30=00F1B1FC] Branched!
2934 F1B016: NOP [NCZ:001]
2936 F1B1FC: MOVEI #$00F1A100, R01 [NCZ:001, R01=00F1A100] -> [NCZ:001, R01=00F1A100]
2939 uint32 pcQueue1[0x400];
2942 //Let's try a 3 stage pipeline....
2943 //Looks like 3 stage is correct, otherwise bad things happen...
2944 void DSPExecP2(int32 cycles)
2946 dsp_releaseTimeSlice_flag = 0;
2949 while (cycles > 0 && DSP_RUNNING)
2951 if (dsp_pc == 0xF1B0A0)
2954 pcQueue1[pcQPtr1++] = dsp_pc;
2957 if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFF) && !doDSPDis)
2959 WriteLog("DSP: PC has stepped out of bounds...\n\nBacktrace:\n\n");
2964 for(int i=0; i<0x400; i++)
2966 dasmjag(JAGUAR_DSP, buffer, pcQueue1[(i + pcQPtr1) & 0x3FF]);
2967 WriteLog("\t%08X: %s\n", pcQueue1[(i + pcQPtr1) & 0x3FF], buffer);
2971 if (IMASKCleared) // If IMASK was cleared,
2973 #ifdef DSP_DEBUG_IRQ
2974 WriteLog("DSP: Finished interrupt.\n");
2976 DSPHandleIRQs(); // See if any other interrupts are pending!
2977 IMASKCleared = false;
2980 //if (dsp_flags & REGPAGE)
2981 // WriteLog(" --> REGPAGE has just been set!\n");
2982 #ifdef DSP_DEBUG_PL2
2985 WriteLog("DSPExecP: Pipeline status [PC=%08X]...\n", dsp_pc);
2986 WriteLog("\tR -> %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]);
2987 WriteLog("\tE -> %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]);
2988 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister, dsp_opcode_str[pipeline[plPtrWrite].opcode]);
2989 WriteLog(" --> Scoreboard: ");
2990 for(int i=0; i<32; i++)
2991 WriteLog("%s ", scoreboard[i] ? "T" : "F");
2995 // Stage 1a: Instruction fetch
2996 pipeline[plPtrRead].instruction = DSPReadWord(dsp_pc, DSP);
2997 pipeline[plPtrRead].opcode = pipeline[plPtrRead].instruction >> 10;
2998 pipeline[plPtrRead].operand1 = (pipeline[plPtrRead].instruction >> 5) & 0x1F;
2999 pipeline[plPtrRead].operand2 = pipeline[plPtrRead].instruction & 0x1F;
3000 if (pipeline[plPtrRead].opcode == 38)
3001 pipeline[plPtrRead].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
3002 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
3003 #ifdef DSP_DEBUG_PL2
3006 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrRead].instruction, dsp_pc);
3007 WriteLog("DSPExecP: Pipeline status (after stage 1a) [PC=%08X]...\n", dsp_pc);
3008 WriteLog("\tR -> %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]);
3009 WriteLog("\tE -> %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]);
3010 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister, dsp_opcode_str[pipeline[plPtrWrite].opcode]);
3013 // Stage 1b: Read registers
3014 //Small problem--when say LOAD or STORE (R14/5+$nn) is executed AFTER an instruction that
3015 //modifies R14/5, we don't check the scoreboard for R14/5 (and we need to!)... !!! FIX !!!
3017 if ((scoreboard[pipeline[plPtrRead].operand1] && readAffected[pipeline[plPtrRead].opcode][0])
3018 || (scoreboard[pipeline[plPtrRead].operand2] && readAffected[pipeline[plPtrRead].opcode][1])
3019 || ((pipeline[plPtrRead].opcode == 43 || pipeline[plPtrRead].opcode == 58) && scoreboard[14])
3020 || ((pipeline[plPtrRead].opcode == 44 || pipeline[plPtrRead].opcode == 59) && scoreboard[15]))
3021 // We have a hit in the scoreboard, so we have to stall the pipeline...
3022 #ifdef DSP_DEBUG_PL2
3026 WriteLog(" --> Stalling pipeline: ");
3027 if (readAffected[pipeline[plPtrRead].opcode][0])
3028 WriteLog("scoreboard[%u] = %s (reg 1) ", pipeline[plPtrRead].operand1, scoreboard[pipeline[plPtrRead].operand1] ? "true" : "false");
3029 if (readAffected[pipeline[plPtrRead].opcode][1])
3030 WriteLog("scoreboard[%u] = %s (reg 2)", pipeline[plPtrRead].operand2, scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
3034 pipeline[plPtrRead].opcode = PIPELINE_STALL;
3035 #ifdef DSP_DEBUG_PL2
3040 pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
3041 pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
3042 pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2; // Set it to RN
3044 // Shouldn't we be more selective with the register scoreboarding?
3045 // Yes, we should. !!! FIX !!! Kinda [DONE]
3046 scoreboard[pipeline[plPtrRead].operand2] = affectsScoreboard[pipeline[plPtrRead].opcode];
3048 //Advance PC here??? Yes.
3049 dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
3052 #ifdef DSP_DEBUG_PL2
3055 WriteLog("DSPExecP: Pipeline status (after stage 1b) [PC=%08X]...\n", dsp_pc);
3056 WriteLog("\tR -> %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]);
3057 WriteLog("\tE -> %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]);
3058 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister, dsp_opcode_str[pipeline[plPtrWrite].opcode]);
3062 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
3064 #ifdef DSP_DEBUG_PL2
3067 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
3072 lastExec = pipeline[plPtrExec].instruction;
3073 //WriteLog("[lastExec = %04X]\n", lastExec);
3075 cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
3076 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
3077 DSPOpcode[pipeline[plPtrExec].opcode]();
3078 //WriteLog(" --> Returned from execute. DSP_PC: %08X\n", dsp_pc);
3082 //Let's not, until we do the stalling correctly...
3083 //But, we gotta while we're doing the comparison core...!
3084 //Or do we? cycles--;
3085 #ifdef DSP_DEBUG_STALL
3087 WriteLog("[STALL... DSP_PC = %08X]\n", dsp_pc);
3091 #ifdef DSP_DEBUG_PL2
3094 WriteLog("DSPExecP: Pipeline status (after stage 2) [PC=%08X]...\n", dsp_pc);
3095 WriteLog("\tR -> %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]);
3096 WriteLog("\tE -> %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]);
3097 WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", pipeline[plPtrWrite].opcode, pipeline[plPtrWrite].operand1, pipeline[plPtrWrite].operand2, pipeline[plPtrWrite].reg1, pipeline[plPtrWrite].reg2, pipeline[plPtrWrite].result, pipeline[plPtrWrite].writebackRegister, dsp_opcode_str[pipeline[plPtrWrite].opcode]);
3101 // Stage 3: Write back register/memory address
3102 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
3104 /*if (pipeline[plPtrWrite].writebackRegister == 3
3105 && (pipeline[plPtrWrite].result < 0xF14000 || pipeline[plPtrWrite].result > 0xF1CFFF)
3108 WriteLog("DSP: Register R03 has stepped out of bounds...\n\n");
3111 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
3113 if (pipeline[plPtrWrite].writebackRegister != 0xFE)
3114 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
3117 if (pipeline[plPtrWrite].type == TYPE_BYTE)
3118 JaguarWriteByte(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3119 else if (pipeline[plPtrWrite].type == TYPE_WORD)
3120 JaguarWriteWord(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3122 JaguarWriteLong(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3126 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
3127 scoreboard[pipeline[plPtrWrite].operand2] = false;
3130 // Push instructions through the pipeline...
3131 plPtrRead = (++plPtrRead) & 0x03;
3132 plPtrExec = (++plPtrExec) & 0x03;
3133 plPtrWrite = (++plPtrWrite) & 0x03;
3142 //#define DSP_DEBUG_PL3
3143 //Let's try a 2 stage pipeline....
3144 void DSPExecP3(int32 cycles)
3146 dsp_releaseTimeSlice_flag = 0;
3149 while (cycles > 0 && DSP_RUNNING)
3151 //if (dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFF)
3153 #ifdef DSP_DEBUG_PL3
3154 WriteLog("DSPExecP: Pipeline status...\n");
3155 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]);
3156 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]);
3157 WriteLog(" --> Scoreboard: ");
3158 for(int i=0; i<32; i++)
3159 WriteLog("%s ", scoreboard[i] ? "T" : "F");
3162 // Stage 1a: Instruction fetch
3163 pipeline[plPtrRead].instruction = DSPReadWord(dsp_pc, DSP);
3164 pipeline[plPtrRead].opcode = pipeline[plPtrRead].instruction >> 10;
3165 pipeline[plPtrRead].operand1 = (pipeline[plPtrRead].instruction >> 5) & 0x1F;
3166 pipeline[plPtrRead].operand2 = pipeline[plPtrRead].instruction & 0x1F;
3167 if (pipeline[plPtrRead].opcode == 38)
3168 pipeline[plPtrRead].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
3169 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
3170 #ifdef DSP_DEBUG_PL3
3171 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrRead].instruction, dsp_pc);
3172 WriteLog("DSPExecP: Pipeline status (after stage 1a)...\n");
3173 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]);
3174 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]);
3176 // Stage 1b: Read registers
3177 if ((scoreboard[pipeline[plPtrRead].operand1] && readAffected[pipeline[plPtrRead].opcode][0])
3178 || (scoreboard[pipeline[plPtrRead].operand2] && readAffected[pipeline[plPtrRead].opcode][1]))
3179 // We have a hit in the scoreboard, so we have to stall the pipeline...
3180 #ifdef DSP_DEBUG_PL3
3182 WriteLog(" --> Stalling pipeline: ");
3183 if (readAffected[pipeline[plPtrRead].opcode][0])
3184 WriteLog("scoreboard[%u] = %s (reg 1) ", pipeline[plPtrRead].operand1, scoreboard[pipeline[plPtrRead].operand1] ? "true" : "false");
3185 if (readAffected[pipeline[plPtrRead].opcode][1])
3186 WriteLog("scoreboard[%u] = %s (reg 2)", pipeline[plPtrRead].operand2, scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
3189 pipeline[plPtrRead].opcode = PIPELINE_STALL;
3190 #ifdef DSP_DEBUG_PL3
3195 pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
3196 pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
3197 pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2; // Set it to RN
3199 // Shouldn't we be more selective with the register scoreboarding?
3200 // Yes, we should. !!! FIX !!! [Kinda DONE]
3201 scoreboard[pipeline[plPtrRead].operand2] = affectsScoreboard[pipeline[plPtrRead].opcode];
3203 //Advance PC here??? Yes.
3204 dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
3207 #ifdef DSP_DEBUG_PL3
3208 WriteLog("DSPExecP: Pipeline status (after stage 1b)...\n");
3209 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]);
3210 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]);
3212 // Stage 2a: Execute
3213 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
3215 #ifdef DSP_DEBUG_PL3
3216 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
3218 DSPOpcode[pipeline[plPtrExec].opcode]();
3219 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
3220 cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
3225 #ifdef DSP_DEBUG_PL3
3226 WriteLog("DSPExecP: Pipeline status (after stage 2a)...\n");
3227 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]);
3228 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]);
3231 // Stage 2b: Write back register
3232 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
3234 if (pipeline[plPtrExec].writebackRegister != 0xFF)
3235 dsp_reg[pipeline[plPtrExec].writebackRegister] = pipeline[plPtrExec].result;
3237 if (affectsScoreboard[pipeline[plPtrExec].opcode])
3238 scoreboard[pipeline[plPtrExec].operand2] = false;
3241 // Push instructions through the pipeline...
3242 plPtrRead = (++plPtrRead) & 0x03;
3243 plPtrExec = (++plPtrExec) & 0x03;
3250 // DSP pipelined opcode handlers
3253 #define PRM pipeline[plPtrExec].reg1
3254 #define PRN pipeline[plPtrExec].reg2
3255 #define PIMM1 pipeline[plPtrExec].operand1
3256 #define PIMM2 pipeline[plPtrExec].operand2
3257 #define PRES pipeline[plPtrExec].result
3258 #define PWBR pipeline[plPtrExec].writebackRegister
3259 #define NO_WRITEBACK pipeline[plPtrExec].writebackRegister = 0xFF
3260 //#define DSP_PPC dsp_pc - (pipeline[plPtrRead].opcode == 38 ? 6 : 2) - (pipeline[plPtrExec].opcode == 38 ? 6 : 2)
3261 #define DSP_PPC dsp_pc - (pipeline[plPtrRead].opcode == 38 ? 6 : (pipeline[plPtrRead].opcode == PIPELINE_STALL ? 0 : 2)) - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2))
3262 #define WRITEBACK_ADDR pipeline[plPtrExec].writebackRegister = 0xFE
3264 static void DSP_abs(void)
3268 WriteLog("%06X: ABS R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3272 if (_Rn == 0x80000000)
3276 dsp_flag_c = ((_Rn & 0x80000000) >> 31);
3277 PRES = (_Rn & 0x80000000 ? -_Rn : _Rn);
3278 CLR_ZN; SET_Z(PRES);
3282 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3286 static void DSP_add(void)
3290 WriteLog("%06X: ADD R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3292 UINT32 res = PRN + PRM;
3293 SET_ZNC_ADD(PRN, PRM, res);
3297 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
3301 static void DSP_addc(void)
3305 WriteLog("%06X: ADDC R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3307 UINT32 res = PRN + PRM + dsp_flag_c;
3308 UINT32 carry = dsp_flag_c;
3309 // SET_ZNC_ADD(PRN, PRM, res); //???BUG??? Yes!
3310 SET_ZNC_ADD(PRN + carry, PRM, res);
3311 // SET_ZNC_ADD(PRN, PRM + carry, res);
3315 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
3319 static void DSP_addq(void)
3323 WriteLog("%06X: ADDQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3325 UINT32 r1 = dsp_convert_zero[PIMM1];
3326 UINT32 res = PRN + r1;
3327 CLR_ZNC; SET_ZNC_ADD(PRN, r1, res);
3331 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3335 static void DSP_addqmod(void)
3337 #ifdef DSP_DIS_ADDQMOD
3339 WriteLog("%06X: ADDQMOD #%u, R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_MOD=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, dsp_modulo);
3341 UINT32 r1 = dsp_convert_zero[PIMM1];
3343 UINT32 res = r2 + r1;
3344 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
3346 SET_ZNC_ADD(r2, r1, res);
3347 #ifdef DSP_DIS_ADDQMOD
3349 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3353 static void DSP_addqt(void)
3355 #ifdef DSP_DIS_ADDQT
3357 WriteLog("%06X: ADDQT #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3359 PRES = PRN + dsp_convert_zero[PIMM1];
3360 #ifdef DSP_DIS_ADDQT
3362 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3366 static void DSP_and(void)
3370 WriteLog("%06X: AND R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3376 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
3380 static void DSP_bclr(void)
3384 WriteLog("%06X: BCLR #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3386 PRES = PRN & ~(1 << PIMM1);
3390 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3394 static void DSP_bset(void)
3398 WriteLog("%06X: BSET #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3400 PRES = PRN | (1 << PIMM1);
3404 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3408 static void DSP_btst(void)
3412 WriteLog("%06X: BTST #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3414 dsp_flag_z = (~PRN >> PIMM1) & 1;
3418 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3422 static void DSP_cmp(void)
3426 WriteLog("%06X: CMP R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3428 UINT32 res = PRN - PRM;
3429 SET_ZNC_SUB(PRN, PRM, res);
3433 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
3437 static void DSP_cmpq(void)
3439 static int32 sqtable[32] =
3440 { 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 };
3443 WriteLog("%06X: CMPQ #%d, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, sqtable[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3445 UINT32 r1 = sqtable[PIMM1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
3446 UINT32 res = PRN - r1;
3447 SET_ZNC_SUB(PRN, r1, res);
3451 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
3455 static void DSP_div(void)
3457 uint32 _Rm = PRM, _Rn = PRN;
3461 if (dsp_div_control & 1)
3463 dsp_remain = (((uint64)_Rn) << 16) % _Rm;
3464 if (dsp_remain & 0x80000000)
3466 PRES = (((uint64)_Rn) << 16) / _Rm;
3470 dsp_remain = _Rn % _Rm;
3471 if (dsp_remain & 0x80000000)
3480 static void DSP_imacn(void)
3482 #ifdef DSP_DIS_IMACN
3484 WriteLog("%06X: IMACN R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3486 int32 res = (int16)PRM * (int16)PRN;
3487 dsp_acc += (int64)res;
3488 //Should we AND the result to fit into 40 bits here???
3490 #ifdef DSP_DIS_IMACN
3492 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));
3496 static void DSP_imult(void)
3498 #ifdef DSP_DIS_IMULT
3500 WriteLog("%06X: IMULT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3502 PRES = (int16)PRN * (int16)PRM;
3504 #ifdef DSP_DIS_IMULT
3506 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
3510 static void DSP_imultn(void)
3512 #ifdef DSP_DIS_IMULTN
3514 WriteLog("%06X: IMULTN R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3516 // This is OK, since this multiply won't overflow 32 bits...
3517 int32 res = (int32)((int16)PRN * (int16)PRM);
3518 dsp_acc = (int64)res;
3521 #ifdef DSP_DIS_IMULTN
3523 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));
3527 static void DSP_illegal(void)
3529 #ifdef DSP_DIS_ILLEGAL
3531 WriteLog("%06X: ILLEGAL [NCZ:%u%u%u]\n", DSP_PPC, dsp_flag_n, dsp_flag_c, dsp_flag_z);
3536 // There is a problem here with interrupt handlers the JUMP and JR instructions that
3537 // can cause trouble because an interrupt can occur *before* the instruction following the
3538 // jump can execute... !!! FIX !!!
3539 // This can probably be solved by judicious coding in the pipeline execution core...
3540 // And should be fixed now...
3541 static void DSP_jr(void)
3544 char * condition[32] =
3545 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
3546 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
3547 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
3548 "???", "???", "???", "F" };
3550 //How come this is always off by 2???
3551 WriteLog("%06X: JR %s, %06X [NCZ:%u%u%u] ", DSP_PPC, condition[PIMM2], DSP_PPC+((PIMM1 & 0x10 ? 0xFFFFFFF0 | PIMM1 : PIMM1) * 2), dsp_flag_n, dsp_flag_c, dsp_flag_z);
3553 // KLUDGE: Used by BRANCH_CONDITION macro
3554 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
3556 if (BRANCH_CONDITION(PIMM2))
3560 WriteLog("Branched!\n");
3562 int32 offset = (PIMM1 & 0x10 ? 0xFFFFFFF0 | PIMM1 : PIMM1); // Sign extend PIMM1
3563 //Account for pipeline effects...
3564 uint32 newPC = dsp_pc + (offset * 2) - (pipeline[plPtrRead].opcode == 38 ? 6 : (pipeline[plPtrRead].opcode == PIPELINE_STALL ? 0 : 2));
3565 //WriteLog(" --> Old PC: %08X, new PC: %08X\n", dsp_pc, newPC);
3567 // Now that we've branched, we have to make sure that the following instruction
3568 // is executed atomically with this one and then flush the pipeline before setting
3571 // Step 1: Handle writebacks at stage 3 of pipeline
3572 /* if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
3574 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
3575 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
3577 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
3578 scoreboard[pipeline[plPtrWrite].operand2] = false;
3580 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
3582 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
3584 if (pipeline[plPtrWrite].writebackRegister != 0xFE)
3585 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
3588 if (pipeline[plPtrWrite].type == TYPE_BYTE)
3589 JaguarWriteByte(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3590 else if (pipeline[plPtrWrite].type == TYPE_WORD)
3591 JaguarWriteWord(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3593 JaguarWriteLong(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3597 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
3598 scoreboard[pipeline[plPtrWrite].operand2] = false;
3601 // Step 2: Push instruction through pipeline & execute following instruction
3602 // NOTE: By putting our following instruction at stage 3 of the pipeline,
3603 // we effectively handle the final push of the instruction through the
3604 // pipeline when the new PC takes effect (since when we return, the
3605 // pipeline code will be executing the writeback stage. If we reverse
3606 // the execution order of the pipeline stages, this will no longer be
3608 pipeline[plPtrExec] = pipeline[plPtrRead];
3609 //This is BAD. We need to get that next opcode and execute it!
3610 //NOTE: The problem is here because of a bad stall. Once those are fixed, we can probably
3611 // remove this crap.
3612 if (pipeline[plPtrExec].opcode == PIPELINE_STALL)
3614 uint16 instruction = DSPReadWord(dsp_pc, DSP);
3615 pipeline[plPtrExec].opcode = instruction >> 10;
3616 pipeline[plPtrExec].operand1 = (instruction >> 5) & 0x1F;
3617 pipeline[plPtrExec].operand2 = instruction & 0x1F;
3618 pipeline[plPtrExec].reg1 = dsp_reg[pipeline[plPtrExec].operand1];
3619 pipeline[plPtrExec].reg2 = dsp_reg[pipeline[plPtrExec].operand2];
3620 pipeline[plPtrExec].writebackRegister = pipeline[plPtrExec].operand2; // Set it to RN
3622 DSPOpcode[pipeline[plPtrExec].opcode]();
3623 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
3624 pipeline[plPtrWrite] = pipeline[plPtrExec];
3626 // Step 3: Flush pipeline & set new PC
3627 pipeline[plPtrRead].opcode = pipeline[plPtrExec].opcode = PIPELINE_STALL;
3634 WriteLog("Branch NOT taken.\n");
3640 // WriteLog(" --> DSP_PC: %08X\n", dsp_pc);
3643 static void DSP_jump(void)
3646 char * condition[32] =
3647 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
3648 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
3649 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
3650 "???", "???", "???", "F" };
3652 WriteLog("%06X: JUMP %s, (R%02u) [NCZ:%u%u%u, R%02u=%08X] ", DSP_PPC, condition[PIMM2], PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM);
3654 // KLUDGE: Used by BRANCH_CONDITION macro
3655 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
3657 if (BRANCH_CONDITION(PIMM2))
3661 WriteLog("Branched!\n");
3663 uint32 PCSave = PRM;
3664 // Now that we've branched, we have to make sure that the following instruction
3665 // is executed atomically with this one and then flush the pipeline before setting
3668 // Step 1: Handle writebacks at stage 3 of pipeline
3669 /* if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
3671 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
3672 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
3674 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
3675 scoreboard[pipeline[plPtrWrite].operand2] = false;
3677 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
3679 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
3681 if (pipeline[plPtrWrite].writebackRegister != 0xFE)
3682 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
3685 if (pipeline[plPtrWrite].type == TYPE_BYTE)
3686 JaguarWriteByte(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3687 else if (pipeline[plPtrWrite].type == TYPE_WORD)
3688 JaguarWriteWord(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3690 JaguarWriteLong(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3694 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
3695 scoreboard[pipeline[plPtrWrite].operand2] = false;
3698 // Step 2: Push instruction through pipeline & execute following instruction
3699 // NOTE: By putting our following instruction at stage 3 of the pipeline,
3700 // we effectively handle the final push of the instruction through the
3701 // pipeline when the new PC takes effect (since when we return, the
3702 // pipeline code will be executing the writeback stage. If we reverse
3703 // the execution order of the pipeline stages, this will no longer be
3705 pipeline[plPtrExec] = pipeline[plPtrRead];
3706 //This is BAD. We need to get that next opcode and execute it!
3707 //Also, same problem in JR!
3708 //NOTE: The problem is here because of a bad stall. Once those are fixed, we can probably
3709 // remove this crap.
3710 if (pipeline[plPtrExec].opcode == PIPELINE_STALL)
3712 uint16 instruction = DSPReadWord(dsp_pc, DSP);
3713 pipeline[plPtrExec].opcode = instruction >> 10;
3714 pipeline[plPtrExec].operand1 = (instruction >> 5) & 0x1F;
3715 pipeline[plPtrExec].operand2 = instruction & 0x1F;
3716 pipeline[plPtrExec].reg1 = dsp_reg[pipeline[plPtrExec].operand1];
3717 pipeline[plPtrExec].reg2 = dsp_reg[pipeline[plPtrExec].operand2];
3718 pipeline[plPtrExec].writebackRegister = pipeline[plPtrExec].operand2; // Set it to RN
3720 DSPOpcode[pipeline[plPtrExec].opcode]();
3721 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
3722 pipeline[plPtrWrite] = pipeline[plPtrExec];
3724 // Step 3: Flush pipeline & set new PC
3725 pipeline[plPtrRead].opcode = pipeline[plPtrExec].opcode = PIPELINE_STALL;
3732 WriteLog("Branch NOT taken.\n");
3740 static void DSP_load(void)
3744 WriteLog("%06X: LOAD (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3746 PRES = DSPReadLong(PRM, DSP);
3749 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3753 static void DSP_loadb(void)
3755 #ifdef DSP_DIS_LOADB
3757 WriteLog("%06X: LOADB (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3759 if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
3760 PRES = DSPReadLong(PRM, DSP) & 0xFF;
3762 PRES = JaguarReadByte(PRM, DSP);
3763 #ifdef DSP_DIS_LOADB
3765 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3769 static void DSP_loadw(void)
3771 #ifdef DSP_DIS_LOADW
3773 WriteLog("%06X: LOADW (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3775 if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
3776 PRES = DSPReadLong(PRM, DSP) & 0xFFFF;
3778 PRES = JaguarReadWord(PRM, DSP);
3779 #ifdef DSP_DIS_LOADW
3781 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3785 static void DSP_load_r14_i(void)
3787 #ifdef DSP_DIS_LOAD14I
3789 WriteLog("%06X: LOAD (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", DSP_PPC, 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);
3791 PRES = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), DSP);
3792 #ifdef DSP_DIS_LOAD14I
3794 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3798 static void DSP_load_r14_r(void)
3800 #ifdef DSP_DIS_LOAD14R
3802 WriteLog("%06X: LOAD (R14+R%02u), R%02u [NCZ:%u%u%u, R14+R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM+dsp_reg[14], PIMM2, PRES);
3804 PRES = DSPReadLong(dsp_reg[14] + PRM, DSP);
3805 #ifdef DSP_DIS_LOAD14R
3807 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3811 static void DSP_load_r15_i(void)
3813 #ifdef DSP_DIS_LOAD15I
3815 WriteLog("%06X: LOAD (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", DSP_PPC, 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);
3817 PRES = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), DSP);
3818 #ifdef DSP_DIS_LOAD15I
3820 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3824 static void DSP_load_r15_r(void)
3826 #ifdef DSP_DIS_LOAD15R
3828 WriteLog("%06X: LOAD (R15+R%02u), R%02u [NCZ:%u%u%u, R15+R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM+dsp_reg[15], PIMM2, PRN);
3830 PRES = DSPReadLong(dsp_reg[15] + PRM, DSP);
3831 #ifdef DSP_DIS_LOAD15R
3833 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3837 static void DSP_mirror(void)
3840 PRES = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
3844 static void DSP_mmult(void)
3846 int count = dsp_matrix_control&0x0f;
3847 uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
3851 if (!(dsp_matrix_control & 0x10))
3853 for (int i = 0; i < count; i++)
3857 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
3859 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
3860 int16 b=((int16)DSPReadWord(addr + 2, DSP));
3867 for (int i = 0; i < count; i++)
3871 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
3873 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
3874 int16 b=((int16)DSPReadWord(addr + 2, DSP));
3880 PRES = res = (int32)accum;
3882 //NOTE: The flags are set based upon the last add/multiply done...
3886 static void DSP_move(void)
3890 WriteLog("%06X: MOVE R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3895 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
3899 static void DSP_movefa(void)
3901 #ifdef DSP_DIS_MOVEFA
3903 // WriteLog("%06X: MOVEFA R%02u, R%02u [NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, ALTERNATE_RM, PIMM2, PRN);
3904 WriteLog("%06X: MOVEFA R%02u, R%02u [NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, dsp_alternate_reg[PIMM1], PIMM2, PRN);
3906 // PRES = ALTERNATE_RM;
3907 PRES = dsp_alternate_reg[PIMM1];
3908 #ifdef DSP_DIS_MOVEFA
3910 // 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);
3911 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);
3915 static void DSP_movei(void)
3917 #ifdef DSP_DIS_MOVEI
3919 WriteLog("%06X: MOVEI #$%08X, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PRES, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3921 // // This instruction is followed by 32-bit value in LSW / MSW format...
3922 // PRES = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
3924 #ifdef DSP_DIS_MOVEI
3926 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3930 static void DSP_movepc(void)
3932 //Need to fix this to take into account pipelining effects... !!! FIX !!! [DONE]
3933 // PRES = dsp_pc - 2;
3934 //Account for pipeline effects...
3935 PRES = dsp_pc - (pipeline[plPtrRead].opcode == 38 ? 6 : (pipeline[plPtrRead].opcode == PIPELINE_STALL ? 0 : 2));
3938 static void DSP_moveq(void)
3940 #ifdef DSP_DIS_MOVEQ
3942 WriteLog("%06X: MOVEQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3945 #ifdef DSP_DIS_MOVEQ
3947 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3951 static void DSP_moveta(void)
3953 #ifdef DSP_DIS_MOVETA
3955 // WriteLog("%06X: MOVETA R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, ALTERNATE_RN);
3956 WriteLog("%06X: MOVETA R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, dsp_alternate_reg[PIMM2]);
3958 // ALTERNATE_RN = PRM;
3959 dsp_alternate_reg[PIMM2] = PRM;
3961 #ifdef DSP_DIS_MOVETA
3963 // 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);
3964 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]);
3968 static void DSP_mtoi(void)
3970 PRES = (((INT32)PRM >> 8) & 0xFF800000) | (PRM & 0x007FFFFF);
3974 static void DSP_mult(void)
3978 WriteLog("%06X: MULT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
3980 PRES = (uint16)PRM * (uint16)PRN;
3984 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
3988 static void DSP_neg(void)
3992 WriteLog("%06X: NEG R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3995 SET_ZNC_SUB(0, PRN, res);
3999 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
4003 static void DSP_nop(void)
4007 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", DSP_PPC, dsp_flag_n, dsp_flag_c, dsp_flag_z);
4012 static void DSP_normi(void)
4019 while ((_Rm & 0xffc00000) == 0)
4024 while ((_Rm & 0xff800000) != 0)
4034 static void DSP_not(void)
4038 WriteLog("%06X: NOT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
4044 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
4048 static void DSP_or(void)
4052 WriteLog("%06X: OR R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
4058 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
4062 static void DSP_resmac(void)
4064 #ifdef DSP_DIS_RESMAC
4066 WriteLog("%06X: RESMAC R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_ACC=%02X%08X] -> ", DSP_PPC, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
4068 PRES = (uint32)dsp_acc;
4069 #ifdef DSP_DIS_RESMAC
4071 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
4075 static void DSP_ror(void)
4079 WriteLog("%06X: ROR R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
4081 UINT32 r1 = PRM & 0x1F;
4082 UINT32 res = (PRN >> r1) | (PRN << (32 - r1));
4083 SET_ZN(res); dsp_flag_c = (PRN >> 31) & 1;
4087 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
4091 static void DSP_rorq(void)
4095 WriteLog("%06X: RORQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
4097 UINT32 r1 = dsp_convert_zero[PIMM1 & 0x1F];
4099 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
4101 SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
4104 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
4108 static void DSP_sat16s(void)
4111 UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
4116 static void DSP_sat32s(void)
4118 INT32 r2 = (UINT32)PRN;
4119 INT32 temp = dsp_acc >> 32;
4120 UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
4125 static void DSP_sh(void)
4127 int32 sRm = (int32)PRM;
4132 uint32 shift = -sRm;
4137 dsp_flag_c = (_Rn & 0x80000000) >> 31;
4152 dsp_flag_c = _Rn & 0x1;
4165 static void DSP_sha(void)
4167 int32 sRm = (int32)PRM;
4172 uint32 shift = -sRm;
4177 dsp_flag_c = (_Rn & 0x80000000) >> 31;
4192 dsp_flag_c = _Rn & 0x1;
4196 _Rn = ((int32)_Rn) >> 1;
4205 static void DSP_sharq(void)
4207 #ifdef DSP_DIS_SHARQ
4209 WriteLog("%06X: SHARQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
4211 UINT32 res = (INT32)PRN >> dsp_convert_zero[PIMM1];
4212 SET_ZN(res); dsp_flag_c = PRN & 0x01;
4214 #ifdef DSP_DIS_SHARQ
4216 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
4220 static void DSP_shlq(void)
4224 WriteLog("%06X: SHLQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, 32 - PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
4226 INT32 r1 = 32 - PIMM1;
4227 UINT32 res = PRN << r1;
4228 SET_ZN(res); dsp_flag_c = (PRN >> 31) & 1;
4232 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
4236 static void DSP_shrq(void)
4240 WriteLog("%06X: SHRQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
4242 INT32 r1 = dsp_convert_zero[PIMM1];
4243 UINT32 res = PRN >> r1;
4244 SET_ZN(res); dsp_flag_c = PRN & 1;
4248 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
4252 static void DSP_store(void)
4254 #ifdef DSP_DIS_STORE
4256 WriteLog("%06X: STORE R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", DSP_PPC, PIMM2, PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, PIMM1, PRM);
4258 // DSPWriteLong(PRM, PRN, DSP);
4260 pipeline[plPtrExec].address = PRM;
4261 pipeline[plPtrExec].value = PRN;
4262 pipeline[plPtrExec].type = TYPE_DWORD;
4266 static void DSP_storeb(void)
4268 #ifdef DSP_DIS_STOREB
4270 WriteLog("%06X: STOREB R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", DSP_PPC, PIMM2, PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, PIMM1, PRM);
4272 // if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
4273 // DSPWriteLong(PRM, PRN & 0xFF, DSP);
4275 // JaguarWriteByte(PRM, PRN, DSP);
4278 pipeline[plPtrExec].address = PRM;
4280 if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
4282 pipeline[plPtrExec].value = PRN & 0xFF;
4283 pipeline[plPtrExec].type = TYPE_DWORD;
4287 pipeline[plPtrExec].value = PRN;
4288 pipeline[plPtrExec].type = TYPE_BYTE;
4294 static void DSP_storew(void)
4296 #ifdef DSP_DIS_STOREW
4298 WriteLog("%06X: STOREW R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", DSP_PPC, PIMM2, PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, PIMM1, PRM);
4300 // if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
4301 // DSPWriteLong(PRM, PRN & 0xFFFF, DSP);
4303 // JaguarWriteWord(PRM, PRN, DSP);
4306 pipeline[plPtrExec].address = PRM;
4308 if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
4310 pipeline[plPtrExec].value = PRN & 0xFFFF;
4311 pipeline[plPtrExec].type = TYPE_DWORD;
4315 pipeline[plPtrExec].value = PRN;
4316 pipeline[plPtrExec].type = TYPE_WORD;
4321 static void DSP_store_r14_i(void)
4323 #ifdef DSP_DIS_STORE14I
4325 WriteLog("%06X: STORE R%02u, (R14+$%02X) [NCZ:%u%u%u, R%02u=%08X, R14+$%02X=%08X]\n", DSP_PPC, 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));
4327 // DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
4329 pipeline[plPtrExec].address = dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2);
4330 pipeline[plPtrExec].value = PRN;
4331 pipeline[plPtrExec].type = TYPE_DWORD;
4335 static void DSP_store_r14_r(void)
4337 // DSPWriteLong(dsp_reg[14] + PRM, PRN, DSP);
4339 pipeline[plPtrExec].address = dsp_reg[14] + PRM;
4340 pipeline[plPtrExec].value = PRN;
4341 pipeline[plPtrExec].type = TYPE_DWORD;
4345 static void DSP_store_r15_i(void)
4347 #ifdef DSP_DIS_STORE15I
4349 WriteLog("%06X: STORE R%02u, (R15+$%02X) [NCZ:%u%u%u, R%02u=%08X, R15+$%02X=%08X]\n", DSP_PPC, 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));
4351 // DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
4353 pipeline[plPtrExec].address = dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2);
4354 pipeline[plPtrExec].value = PRN;
4355 pipeline[plPtrExec].type = TYPE_DWORD;
4359 static void DSP_store_r15_r(void)
4361 // DSPWriteLong(dsp_reg[15] + PRM, PRN, DSP);
4363 pipeline[plPtrExec].address = dsp_reg[15] + PRM;
4364 pipeline[plPtrExec].value = PRN;
4365 pipeline[plPtrExec].type = TYPE_DWORD;
4369 static void DSP_sub(void)
4373 WriteLog("%06X: SUB R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
4375 UINT32 res = PRN - PRM;
4376 SET_ZNC_SUB(PRN, PRM, res);
4380 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
4384 static void DSP_subc(void)
4388 WriteLog("%06X: SUBC R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
4390 UINT32 res = PRN - PRM - dsp_flag_c;
4391 UINT32 borrow = dsp_flag_c;
4392 SET_ZNC_SUB(PRN - borrow, PRM, res);
4396 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
4400 static void DSP_subq(void)
4404 WriteLog("%06X: SUBQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
4406 UINT32 r1 = dsp_convert_zero[PIMM1];
4407 UINT32 res = PRN - r1;
4408 SET_ZNC_SUB(PRN, r1, res);
4412 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
4416 static void DSP_subqmod(void)
4418 UINT32 r1 = dsp_convert_zero[PIMM1];
4420 UINT32 res = r2 - r1;
4421 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
4423 SET_ZNC_SUB(r2, r1, res);
4426 static void DSP_subqt(void)
4428 #ifdef DSP_DIS_SUBQT
4430 WriteLog("%06X: SUBQT #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
4432 PRES = PRN - dsp_convert_zero[PIMM1];
4433 #ifdef DSP_DIS_SUBQT
4435 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
4439 static void DSP_xor(void)
4443 WriteLog("%06X: XOR R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
4449 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);