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_STALL
16 // Disassembly definitions
18 #define DSP_DIS_ABS // Pipelined only
22 #define DSP_DIS_ADDQMOD
32 #define DSP_DIS_IMULTN
33 #define DSP_DIS_ILLEGAL
37 #define DSP_DIS_LOAD14I
38 #define DSP_DIS_LOAD14R
39 #define DSP_DIS_LOAD15I
40 #define DSP_DIS_LOAD15R
46 #define DSP_DIS_MOVEFA
47 #define DSP_DIS_MOVETA
53 #define DSP_DIS_RESMAC
60 #define DSP_DIS_STORE14I
61 #define DSP_DIS_STORE15I
62 #define DSP_DIS_STOREB
63 #define DSP_DIS_STOREW
70 bool doDSPDis = false;
71 //bool doDSPDis = true;
106 + load_r15_indexed 284500
108 + store_r15_indexed 47416
112 + load_r14_ri 1229448
115 // Pipeline structures
117 const bool affectsScoreboard[64] =
119 true, true, true, true,
120 true, true, true, true,
121 true, true, true, true,
122 true, false, true, true,
124 true, true, false, true,
125 false, true, true, true,
126 true, true, true, true,
127 true, true, false, false,
129 true, true, true, true,
130 false, true, true, true,
131 true, true, true, true,
132 true, false, false, false,
134 true, false, false, true,
135 false, false, true, true,
136 true, false, true, true,
137 false, false, false, true
143 uint8 opcode, operand1, operand2;
144 uint32 reg1, reg2, areg1, areg2;
146 uint8 writebackRegister;
147 // General memory store...
156 #define PIPELINE_STALL 64 // Set to # of opcodes + 1
158 uint8 plPtrFetch, plPtrRead, plPtrExec, plPtrWrite;
159 PipelineStage pipeline[4];
160 bool IMASKCleared = false;
162 // DSP flags (old--have to get rid of this crap)
164 #define CINT0FLAG 0x00200
165 #define CINT1FLAG 0x00400
166 #define CINT2FLAG 0x00800
167 #define CINT3FLAG 0x01000
168 #define CINT4FLAG 0x02000
169 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
170 #define CINT5FLAG 0x20000 /* DSP only */
174 #define ZERO_FLAG 0x00001
175 #define CARRY_FLAG 0x00002
176 #define NEGA_FLAG 0x00004
177 #define IMASK 0x00008
178 #define INT_ENA0 0x00010
179 #define INT_ENA1 0x00020
180 #define INT_ENA2 0x00040
181 #define INT_ENA3 0x00080
182 #define INT_ENA4 0x00100
183 #define INT_CLR0 0x00200
184 #define INT_CLR1 0x00400
185 #define INT_CLR2 0x00800
186 #define INT_CLR3 0x01000
187 #define INT_CLR4 0x02000
188 #define REGPAGE 0x04000
189 #define DMAEN 0x08000
190 #define INT_ENA5 0x10000
191 #define INT_CLR5 0x20000
195 #define DSPGO 0x00001
196 #define CPUINT 0x00002
197 #define DSPINT0 0x00004
198 #define SINGLE_STEP 0x00008
199 #define SINGLE_GO 0x00010
201 #define INT_LAT0 0x00040
202 #define INT_LAT1 0x00080
203 #define INT_LAT2 0x00100
204 #define INT_LAT3 0x00200
205 #define INT_LAT4 0x00400
206 #define BUS_HOG 0x00800
207 #define VERSION 0x0F000
208 #define INT_LAT5 0x10000
210 extern uint32 jaguar_mainRom_crc32;
212 // Is opcode 62 *really* a NOP? Seems like it...
213 static void dsp_opcode_abs(void);
214 static void dsp_opcode_add(void);
215 static void dsp_opcode_addc(void);
216 static void dsp_opcode_addq(void);
217 static void dsp_opcode_addqmod(void);
218 static void dsp_opcode_addqt(void);
219 static void dsp_opcode_and(void);
220 static void dsp_opcode_bclr(void);
221 static void dsp_opcode_bset(void);
222 static void dsp_opcode_btst(void);
223 static void dsp_opcode_cmp(void);
224 static void dsp_opcode_cmpq(void);
225 static void dsp_opcode_div(void);
226 static void dsp_opcode_imacn(void);
227 static void dsp_opcode_imult(void);
228 static void dsp_opcode_imultn(void);
229 static void dsp_opcode_jr(void);
230 static void dsp_opcode_jump(void);
231 static void dsp_opcode_load(void);
232 static void dsp_opcode_loadb(void);
233 static void dsp_opcode_loadw(void);
234 static void dsp_opcode_load_r14_indexed(void);
235 static void dsp_opcode_load_r14_ri(void);
236 static void dsp_opcode_load_r15_indexed(void);
237 static void dsp_opcode_load_r15_ri(void);
238 static void dsp_opcode_mirror(void);
239 static void dsp_opcode_mmult(void);
240 static void dsp_opcode_move(void);
241 static void dsp_opcode_movei(void);
242 static void dsp_opcode_movefa(void);
243 static void dsp_opcode_move_pc(void);
244 static void dsp_opcode_moveq(void);
245 static void dsp_opcode_moveta(void);
246 static void dsp_opcode_mtoi(void);
247 static void dsp_opcode_mult(void);
248 static void dsp_opcode_neg(void);
249 static void dsp_opcode_nop(void);
250 static void dsp_opcode_normi(void);
251 static void dsp_opcode_not(void);
252 static void dsp_opcode_or(void);
253 static void dsp_opcode_resmac(void);
254 static void dsp_opcode_ror(void);
255 static void dsp_opcode_rorq(void);
256 static void dsp_opcode_xor(void);
257 static void dsp_opcode_sat16s(void);
258 static void dsp_opcode_sat32s(void);
259 static void dsp_opcode_sh(void);
260 static void dsp_opcode_sha(void);
261 static void dsp_opcode_sharq(void);
262 static void dsp_opcode_shlq(void);
263 static void dsp_opcode_shrq(void);
264 static void dsp_opcode_store(void);
265 static void dsp_opcode_storeb(void);
266 static void dsp_opcode_storew(void);
267 static void dsp_opcode_store_r14_indexed(void);
268 static void dsp_opcode_store_r14_ri(void);
269 static void dsp_opcode_store_r15_indexed(void);
270 static void dsp_opcode_store_r15_ri(void);
271 static void dsp_opcode_sub(void);
272 static void dsp_opcode_subc(void);
273 static void dsp_opcode_subq(void);
274 static void dsp_opcode_subqmod(void);
275 static void dsp_opcode_subqt(void);
277 uint8 dsp_opcode_cycles[64] =
297 void (* dsp_opcode[64])() =
299 dsp_opcode_add, dsp_opcode_addc, dsp_opcode_addq, dsp_opcode_addqt,
300 dsp_opcode_sub, dsp_opcode_subc, dsp_opcode_subq, dsp_opcode_subqt,
301 dsp_opcode_neg, dsp_opcode_and, dsp_opcode_or, dsp_opcode_xor,
302 dsp_opcode_not, dsp_opcode_btst, dsp_opcode_bset, dsp_opcode_bclr,
303 dsp_opcode_mult, dsp_opcode_imult, dsp_opcode_imultn, dsp_opcode_resmac,
304 dsp_opcode_imacn, dsp_opcode_div, dsp_opcode_abs, dsp_opcode_sh,
305 dsp_opcode_shlq, dsp_opcode_shrq, dsp_opcode_sha, dsp_opcode_sharq,
306 dsp_opcode_ror, dsp_opcode_rorq, dsp_opcode_cmp, dsp_opcode_cmpq,
307 dsp_opcode_subqmod, dsp_opcode_sat16s, dsp_opcode_move, dsp_opcode_moveq,
308 dsp_opcode_moveta, dsp_opcode_movefa, dsp_opcode_movei, dsp_opcode_loadb,
309 dsp_opcode_loadw, dsp_opcode_load, dsp_opcode_sat32s, dsp_opcode_load_r14_indexed,
310 dsp_opcode_load_r15_indexed, dsp_opcode_storeb, dsp_opcode_storew, dsp_opcode_store,
311 dsp_opcode_mirror, dsp_opcode_store_r14_indexed, dsp_opcode_store_r15_indexed, dsp_opcode_move_pc,
312 dsp_opcode_jump, dsp_opcode_jr, dsp_opcode_mmult, dsp_opcode_mtoi,
313 dsp_opcode_normi, dsp_opcode_nop, dsp_opcode_load_r14_ri, dsp_opcode_load_r15_ri,
314 dsp_opcode_store_r14_ri, dsp_opcode_store_r15_ri, dsp_opcode_nop, dsp_opcode_addqmod,
317 uint32 dsp_opcode_use[65];
319 char * dsp_opcode_str[65]=
321 "add", "addc", "addq", "addqt",
322 "sub", "subc", "subq", "subqt",
323 "neg", "and", "or", "xor",
324 "not", "btst", "bset", "bclr",
325 "mult", "imult", "imultn", "resmac",
326 "imacn", "div", "abs", "sh",
327 "shlq", "shrq", "sha", "sharq",
328 "ror", "rorq", "cmp", "cmpq",
329 "subqmod", "sat16s", "move", "moveq",
330 "moveta", "movefa", "movei", "loadb",
331 "loadw", "load", "sat32s", "load_r14_indexed",
332 "load_r15_indexed", "storeb", "storew", "store",
333 "mirror", "store_r14_indexed","store_r15_indexed","move_pc",
334 "jump", "jr", "mmult", "mtoi",
335 "normi", "nop", "load_r14_ri", "load_r15_ri",
336 "store_r14_ri", "store_r15_ri", "illegal", "addqmod",
341 static uint64 dsp_acc; // 40 bit register, NOT 32!
342 static uint32 dsp_remain;
343 static uint32 dsp_modulo;
344 static uint32 dsp_flags;
345 static uint32 dsp_matrix_control;
346 static uint32 dsp_pointer_to_matrix;
347 static uint32 dsp_data_organization;
349 static uint32 dsp_div_control;
350 static uint8 dsp_flag_z, dsp_flag_n, dsp_flag_c;
351 static uint32 * dsp_reg, * dsp_alternate_reg;
352 static uint32 * dsp_reg_bank_0, * dsp_reg_bank_1;
354 static uint32 dsp_opcode_first_parameter;
355 static uint32 dsp_opcode_second_parameter;
357 #define DSP_RUNNING (dsp_control & 0x01)
359 #define RM dsp_reg[dsp_opcode_first_parameter]
360 #define RN dsp_reg[dsp_opcode_second_parameter]
361 #define ALTERNATE_RM dsp_alternate_reg[dsp_opcode_first_parameter]
362 #define ALTERNATE_RN dsp_alternate_reg[dsp_opcode_second_parameter]
363 #define IMM_1 dsp_opcode_first_parameter
364 #define IMM_2 dsp_opcode_second_parameter
366 #define CLR_Z (dsp_flag_z = 0)
367 #define CLR_ZN (dsp_flag_z = dsp_flag_n = 0)
368 #define CLR_ZNC (dsp_flag_z = dsp_flag_n = dsp_flag_c = 0)
369 #define SET_Z(r) (dsp_flag_z = ((r) == 0))
370 #define SET_N(r) (dsp_flag_n = (((UINT32)(r) >> 31) & 0x01))
371 #define SET_C_ADD(a,b) (dsp_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
372 #define SET_C_SUB(a,b) (dsp_flag_c = ((UINT32)(b) > (UINT32)(a)))
373 #define SET_ZN(r) SET_N(r); SET_Z(r)
374 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
375 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
377 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 };
378 uint8 * dsp_branch_condition_table = NULL;
379 static uint16 * mirror_table = NULL;
380 static uint8 * dsp_ram_8 = NULL;
382 #define BRANCH_CONDITION(x) dsp_branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
384 static uint32 dsp_in_exec = 0;
385 static uint32 dsp_releaseTimeSlice_flag = 0;
389 // Private function prototypes
391 void DSPDumpRegisters(void);
392 void DSPDumpDisassembly(void);
393 void FlushDSPPipeline(void);
396 void dsp_reset_stats(void)
398 for(int i=0; i<65; i++)
399 dsp_opcode_use[i] = 0;
402 void dsp_releaseTimeslice(void)
404 //This does absolutely nothing!!! !!! FIX !!!
405 dsp_releaseTimeSlice_flag = 1;
408 void dsp_build_branch_condition_table(void)
410 // Allocate the mirror table
412 mirror_table = (uint16 *)malloc(65536 * sizeof(mirror_table[0]));
414 // Fill in the mirror table
416 for(int i=0; i<65536; i++)
417 mirror_table[i] = ((i >> 15) & 0x0001) | ((i >> 13) & 0x0002) |
418 ((i >> 11) & 0x0004) | ((i >> 9) & 0x0008) |
419 ((i >> 7) & 0x0010) | ((i >> 5) & 0x0020) |
420 ((i >> 3) & 0x0040) | ((i >> 1) & 0x0080) |
421 ((i << 1) & 0x0100) | ((i << 3) & 0x0200) |
422 ((i << 5) & 0x0400) | ((i << 7) & 0x0800) |
423 ((i << 9) & 0x1000) | ((i << 11) & 0x2000) |
424 ((i << 13) & 0x4000) | ((i << 15) & 0x8000);
426 if (!dsp_branch_condition_table)
428 dsp_branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(dsp_branch_condition_table[0]));
430 // Fill in the condition table
431 if (dsp_branch_condition_table)
433 for(int i=0; i<8; i++)
435 for(int j=0; j<32; j++)
442 if (!(i & ZERO_FLAG))
445 if (i & (CARRY_FLAG << (j >> 4)))
448 if (!(i & (CARRY_FLAG << (j >> 4))))
450 dsp_branch_condition_table[i * 32 + j] = result;
457 uint8 DSPReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
459 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
460 WriteLog("DSP: ReadByte--Attempt to read from DSP register file by %s!\n", whoName[who]);
462 // if ((offset==0xF1CFE0)||(offset==0xF1CFE2))
465 /* if ((jaguar_mainRom_crc32==0xbfd751a4)||(jaguar_mainRom_crc32==0x053efaf9))
467 if (offset==0xF1CFE0)
470 if (offset >= DSP_WORK_RAM_BASE && offset <= (DSP_WORK_RAM_BASE + 0x1FFF))
471 return dsp_ram_8[offset - DSP_WORK_RAM_BASE];
473 if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
475 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
477 if ((offset&0x03)==0)
480 if ((offset&0x03)==1)
481 return((data>>16)&0xff);
483 if ((offset&0x03)==2)
484 return((data>>8)&0xff);
486 if ((offset&0x03)==3)
490 return JaguarReadByte(offset, who);
493 uint16 DSPReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
495 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
496 WriteLog("DSP: ReadWord--Attempt to read from DSP register file by %s!\n", whoName[who]);
498 offset &= 0xFFFFFFFE;
500 /* if (jaguar_mainRom_crc32==0xa74a97cd)
502 if (offset==0xF1A114) return(0x0000);
503 if (offset==0xF1A116) return(0x0000);
504 if (offset==0xF1B000) return(0x1234);
505 if (offset==0xF1B002) return(0x5678);
508 if (jaguar_mainRom_crc32==0x7ae20823)
510 if (offset==0xF1B9D8) return(0x0000);
511 if (offset==0xF1B9Da) return(0x0000);
512 if (offset==0xF1B2C0) return(0x0000);
513 if (offset==0xF1B2C2) return(0x0000);
516 // pour permettre à wolfenstein 3d de tourner sans le dsp
517 /* if ((offset==0xF1B0D0)||(offset==0xF1B0D2))
521 // pour permettre à nba jam de tourner sans le dsp
522 /* if (jaguar_mainRom_crc32==0x4faddb18)
524 if (offset==0xf1b2c0) return(0);
525 if (offset==0xf1b2c2) return(0);
526 if (offset==0xf1b240) return(0);
527 if (offset==0xf1b242) return(0);
528 if (offset==0xF1B340) return(0);
529 if (offset==0xF1B342) return(0);
530 if (offset==0xF1BAD8) return(0);
531 if (offset==0xF1BADA) return(0);
532 if (offset==0xF1B040) return(0);
533 if (offset==0xF1B042) return(0);
534 if (offset==0xF1B0C0) return(0);
535 if (offset==0xF1B0C2) return(0);
536 if (offset==0xF1B140) return(0);
537 if (offset==0xF1B142) return(0);
538 if (offset==0xF1B1C0) return(0);
539 if (offset==0xF1B1C2) return(0);
542 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE+0x1FFF)
544 offset -= DSP_WORK_RAM_BASE;
545 /* uint16 data = (((uint16)dsp_ram_8[offset])<<8)|((uint16)dsp_ram_8[offset+1]);
547 return GET16(dsp_ram_8, offset);
549 else if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
551 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
554 return data & 0xFFFF;
559 return JaguarReadWord(offset, who);
562 uint32 DSPReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
564 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
565 WriteLog("DSP: ReadLong--Attempt to read from DSP register file by %s!\n", whoName[who]);
568 offset &= 0xFFFFFFFC;
569 /*if (offset == 0xF1BCF4)
571 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));
572 DSPDumpDisassembly();
574 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
576 offset -= DSP_WORK_RAM_BASE;
577 return GET32(dsp_ram_8, offset);
579 //NOTE: Didn't return DSP_ACCUM!!!
580 //Mebbe it's not 'spose to! Yes, it is!
581 if (offset >= DSP_CONTROL_RAM_BASE && offset <= DSP_CONTROL_RAM_BASE + 0x23)
586 case 0x00: /*dsp_flag_c?(dsp_flag_c=1):(dsp_flag_c=0);
587 dsp_flag_z?(dsp_flag_z=1):(dsp_flag_z=0);
588 dsp_flag_n?(dsp_flag_n=1):(dsp_flag_n=0);*/
590 dsp_flags = (dsp_flags & 0xFFFFFFF8) | (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
591 return dsp_flags & 0xFFFFC1FF;
592 case 0x04: return dsp_matrix_control;
593 case 0x08: return dsp_pointer_to_matrix;
594 case 0x0C: return dsp_data_organization;
595 case 0x10: return dsp_pc;
596 case 0x14: return dsp_control;
597 case 0x18: return dsp_modulo;
598 case 0x1C: return dsp_remain;
600 return (int32)((int8)(dsp_acc >> 32)); // Top 8 bits of 40-bit accumulator, sign extended
602 // unaligned long read-- !!! FIX !!!
606 return JaguarReadLong(offset, who);
609 void DSPWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
611 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
612 WriteLog("DSP: WriteByte--Attempt to write to DSP register file by %s!\n", whoName[who]);
614 if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
616 offset -= DSP_WORK_RAM_BASE;
617 dsp_ram_8[offset] = data;
618 //This is rather stupid! !!! FIX !!!
619 /* if (dsp_in_exec == 0)
621 m68k_end_timeslice();
622 gpu_releaseTimeslice();
626 if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
628 uint32 reg = offset & 0x1C;
629 int bytenum = offset & 0x03;
631 if ((reg >= 0x1C) && (reg <= 0x1F))
632 dsp_div_control = (dsp_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
635 //This looks funky. !!! FIX !!!
636 uint32 old_data = DSPReadLong(offset&0xFFFFFFC, who);
637 bytenum = 3 - bytenum; // convention motorola !!!
638 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
639 DSPWriteLong(offset & 0xFFFFFFC, old_data, who);
643 // WriteLog("dsp: writing %.2x at 0x%.8x\n",data,offset);
644 //Should this *ever* happen??? Shouldn't we be saying "unknown" here???
645 JaguarWriteByte(offset, data, who);
648 void DSPWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
650 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
651 WriteLog("DSP: WriteWord--Attempt to write to DSP register file by %s!\n", whoName[who]);
652 offset &= 0xFFFFFFFE;
653 /*if (offset == 0xF1BCF4)
655 WriteLog("DSPWriteWord: Writing to 0xF1BCF4... %04X -> %04X\n", GET16(dsp_ram_8, 0x0CF4), data);
657 // WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset);
658 if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
660 offset -= DSP_WORK_RAM_BASE;
661 dsp_ram_8[offset] = data >> 8;
662 dsp_ram_8[offset+1] = data & 0xFF;
663 //This is rather stupid! !!! FIX !!!
664 /* if (dsp_in_exec == 0)
666 // WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset+DSP_WORK_RAM_BASE);
667 m68k_end_timeslice();
668 gpu_releaseTimeslice();
672 else if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
674 if ((offset & 0x1C) == 0x1C)
677 dsp_div_control = (dsp_div_control&0xffff0000)|(data&0xffff);
679 dsp_div_control = (dsp_div_control&0xffff)|((data&0xffff)<<16);
683 uint32 old_data = DSPReadLong(offset & 0xffffffc, who);
685 old_data = (old_data&0xffff0000)|(data&0xffff);
687 old_data = (old_data&0xffff)|((data&0xffff)<<16);
688 DSPWriteLong(offset & 0xffffffc, old_data, who);
693 JaguarWriteWord(offset, data, who);
696 //bool badWrite = false;
697 void DSPWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
699 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
700 WriteLog("DSP: WriteLong--Attempt to write to DSP register file by %s!\n", whoName[who]);
702 offset &= 0xFFFFFFFC;
703 /*if (offset == 0xF1BCF4)
705 WriteLog("DSPWriteLong: Writing to 0xF1BCF4... %08X -> %08X\n", GET32(dsp_ram_8, 0x0CF4), data);
707 // WriteLog("dsp: writing %.8x at 0x%.8x\n",data,offset);
708 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
710 /*if (offset == 0xF1BE2C)
712 WriteLog("DSP: %s is writing %08X at location 0xF1BE2C (DSP_PC: %08X)...\n", whoName[who], data, dsp_pc - 2);
714 offset -= DSP_WORK_RAM_BASE;
715 SET32(dsp_ram_8, offset, data);
718 else if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
726 WriteLog("DSP: Writing %08X to DSP_FLAGS by %s (REGPAGE is %s)...\n", data, whoName[who], (dsp_flags & REGPAGE ? "set" : "not set"));
728 // bool IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
729 IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
731 dsp_flag_z = dsp_flags & 0x01;
732 dsp_flag_c = (dsp_flags >> 1) & 0x01;
733 dsp_flag_n = (dsp_flags >> 2) & 0x01;
734 DSPUpdateRegisterBanks();
735 dsp_control &= ~((dsp_flags & CINT04FLAGS) >> 3);
736 dsp_control &= ~((dsp_flags & CINT5FLAG) >> 1);
737 /* if (IMASKCleared) // If IMASK was cleared,
740 WriteLog("DSP: Finished interrupt.\n");
742 DSPHandleIRQs(); // see if any other interrupts need servicing!
749 dsp_matrix_control = data;
752 // According to JTRM, only lines 2-11 are adressable, the rest being
753 // hardwired to $F1Bxxx.
754 dsp_pointer_to_matrix = 0xF1B000 | (data & 0x000FFC);
757 dsp_data_organization = data;
762 WriteLog("DSP: Setting DSP PC to %08X by %s%s\n", dsp_pc, whoName[who], (DSP_RUNNING ? " (DSP is RUNNING!)" : ""));//*/
767 // uint32 dsp_was_running = DSP_RUNNING;
768 // Check for DSP -> CPU interrupt
771 // WriteLog("DSP: DSP -> CPU interrupt\n");
773 // Why do we check for a valid handler at 64? Isn't that the Jag programmer's responsibility?
774 if (JERRYIRQEnabled(IRQ2_DSP))// && jaguar_interrupt_handler_is_valid(64))
776 JERRYSetPendingIRQ(IRQ2_DSP);
777 dsp_releaseTimeslice();
778 m68k_set_irq(7); // Set 68000 NMI...
782 // Check for CPU -> DSP interrupt
786 WriteLog("DSP: CPU -> DSP interrupt\n");
788 m68k_end_timeslice();
789 gpu_releaseTimeslice();
790 DSPSetIRQLine(DSPIRQ_CPU, ASSERT_LINE);
794 if (data & SINGLE_STEP)
796 // WriteLog("DSP: Asked to perform a single step (single step is %senabled)\n", (data & 0x8 ? "" : "not "));
799 // Protect writes to VERSION and the interrupt latches...
800 uint32 mask = VERSION | INT_LAT0 | INT_LAT1 | INT_LAT2 | INT_LAT3 | INT_LAT4 | INT_LAT5;
801 dsp_control = (dsp_control & mask) | (data & ~mask);
803 // if dsp wasn't running but is now running
804 // execute a few cycles
805 //This is just plain wrong, wrong, WRONG!
806 #ifndef DSP_SINGLE_STEPPING
807 /* if (!dsp_was_running && DSP_RUNNING)
812 //This is WRONG! !!! FIX !!!
813 if (dsp_control & 0x18)
817 WriteLog("Write to DSP CTRL: %08X ", data);
819 WriteLog(" --> Starting to run at %08X by %s...", dsp_pc, whoName[who]);
821 WriteLog(" --> Stopped by %s! (DSP PC: %08X)", whoName[who], dsp_pc);
824 //This isn't exactly right either--we don't know if it was the M68K or the GPU writing here...
825 // !!! FIX !!! [DONE]
829 m68k_end_timeslice();
831 gpu_releaseTimeslice();
834 //DSPDumpDisassembly();
842 dsp_div_control = data;
844 // default: // unaligned long read
850 //We don't have to break this up like this! We CAN do 32 bit writes!
851 // JaguarWriteWord(offset, (data>>16) & 0xFFFF, DSP);
852 // JaguarWriteWord(offset+2, data & 0xFFFF, DSP);
853 //if (offset > 0xF1FFFF)
855 JaguarWriteLong(offset, data, who);
859 // Update the DSP register file pointers depending on REGPAGE bit
861 void DSPUpdateRegisterBanks(void)
863 int bank = (dsp_flags & REGPAGE);
865 if (dsp_flags & IMASK)
866 bank = 0; // IMASK forces main bank to be bank 0
869 dsp_reg = dsp_reg_bank_1, dsp_alternate_reg = dsp_reg_bank_0;
871 dsp_reg = dsp_reg_bank_0, dsp_alternate_reg = dsp_reg_bank_1;
875 // Check for an handle any asserted DSP IRQs
877 void DSPHandleIRQs(void)
879 if (dsp_flags & IMASK) // Bail if we're already inside an interrupt
882 // Get the active interrupt bits (latches) & interrupt mask (enables)
883 uint32 bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
884 mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
886 // WriteLog("dsp: bits=%.2x mask=%.2x\n",bits,mask);
889 if (!bits) // Bail if nothing is enabled
892 int which = 0; // Determine which interrupt
907 WriteLog("DSP: Generating interrupt #%i...", which);
910 //if (which == 0) doDSPDis = true;
912 // NOTE: Since the actual Jaguar hardware injects the code sequence below
913 // directly into the pipeline, it has the side effect of ensuring that the
914 // instruction interrupted also gets to do its writeback. We simulate that
916 /* if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
918 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
919 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
921 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
922 scoreboard[pipeline[plPtrWrite].operand2] = false;
924 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
926 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
928 if (pipeline[plPtrWrite].writebackRegister != 0xFE)
929 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
932 if (pipeline[plPtrWrite].type == TYPE_BYTE)
933 JaguarWriteByte(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
934 else if (pipeline[plPtrWrite].type == TYPE_WORD)
935 JaguarWriteWord(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
937 JaguarWriteLong(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
941 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
942 scoreboard[pipeline[plPtrWrite].operand2] = false;
946 DSPUpdateRegisterBanks();
948 // WriteLog(" [PC will return to %08X, R31 = %08X]\n", dsp_pc, dsp_reg[31]);
949 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]);
952 // subqt #4,r31 ; pre-decrement stack pointer
953 // move pc,r30 ; address of interrupted code
954 // store r30,(r31) ; store return address
956 //This might not come back to the right place if the instruction was MOVEI #. !!! FIX !!!
957 //But, then again, JTRM says that it adds two regardless of what the instruction was...
958 //It missed the place that it was supposed to come back to, so this is WRONG!
960 // Look at the pipeline when an interrupt occurs (instructions of foo, bar, baz):
962 // R -> baz (<- PC points here)
963 // E -> bar (when it should point here!)
966 // 'Foo' just completed executing as per above. PC is pointing to the instruction 'baz'
967 // which means (assuming they're all 2 bytes long) that the code below will come back on
968 // instruction 'baz' instead of 'bar' which is the next instruction to execute in the
969 // instruction stream...
971 // DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
972 DSPWriteLong(dsp_reg[31], dsp_pc - 2 - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2)), DSP);
974 // movei #service_address,r30 ; pointer to ISR entry
975 // jump (r30) ; jump to ISR
977 dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
982 // Set the specified DSP IRQ line to a given state
984 void DSPSetIRQLine(int irqline, int state)
986 //NOTE: This doesn't take INT_LAT5 into account. !!! FIX !!!
987 uint32 mask = INT_LAT0 << irqline;
988 dsp_control &= ~mask; // Clear the latch bit
992 dsp_control |= mask; // Set the latch bit
999 memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
1000 memory_malloc_secure((void **)&dsp_reg_bank_0, 32 * sizeof(int32), "DSP bank 0 regs");
1001 memory_malloc_secure((void **)&dsp_reg_bank_1, 32 * sizeof(int32), "DSP bank 1 regs");
1003 dsp_build_branch_condition_table();
1009 dsp_pc = 0x00F1B000;
1010 dsp_acc = 0x00000000;
1011 dsp_remain = 0x00000000;
1012 dsp_modulo = 0xFFFFFFFF;
1013 dsp_flags = 0x00040000;
1014 dsp_matrix_control = 0x00000000;
1015 dsp_pointer_to_matrix = 0x00000000;
1016 dsp_data_organization = 0xFFFFFFFF;
1017 dsp_control = 0x00002000; // Report DSP version 2
1018 dsp_div_control = 0x00000000;
1021 dsp_reg = dsp_reg_bank_0;
1022 dsp_alternate_reg = dsp_reg_bank_1;
1024 for(int i=0; i<32; i++)
1025 dsp_reg[i] = dsp_alternate_reg[i] = 0x00000000;
1028 IMASKCleared = false;
1030 memset(dsp_ram_8, 0xFF, 0x2000);
1033 void DSPDumpDisassembly(void)
1037 WriteLog("\n---[DSP code at 00F1B000]---------------------------\n");
1038 uint32 j = 0xF1B000;
1039 while (j <= 0xF1CFFF)
1042 j += dasmjag(JAGUAR_DSP, buffer, j);
1043 WriteLog("\t%08X: %s\n", oldj, buffer);
1047 void DSPDumpRegisters(void)
1049 //Shoud add modulus, etc to dump here...
1050 WriteLog("\n---[DSP flags: NCZ %d%d%d, DSP PC: %08X]------------\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_pc);
1051 WriteLog("\nRegisters bank 0\n");
1052 for(int j=0; j<8; j++)
1054 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1055 (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
1056 (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
1057 (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
1058 (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
1060 WriteLog("Registers bank 1\n");
1061 for(int j=0; j<8; j++)
1063 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1064 (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
1065 (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
1066 (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
1067 (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
1074 WriteLog("DSP: Stopped at PC=%08X dsp_modulo=%08X (dsp %s running)\n", dsp_pc, dsp_modulo, (DSP_RUNNING ? "was" : "wasn't"));
1075 WriteLog("DSP: %sin interrupt handler\n", (dsp_flags & IMASK ? "" : "not "));
1077 // get the active interrupt bits
1078 int bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F);
1079 // get the interrupt mask
1080 int mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
1082 WriteLog("DSP: pending=%08X enabled=%08X\n", bits, mask);
1083 WriteLog("\nRegisters bank 0\n");
1084 for(int j=0; j<8; j++)
1086 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
1087 (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
1088 (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
1089 (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
1090 (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
1092 WriteLog("\nRegisters bank 1\n");
1095 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
1096 (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
1097 (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
1098 (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
1099 (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
1103 static char buffer[512];
1104 j = DSP_WORK_RAM_BASE;
1105 while (j <= 0xF1BFFF)
1108 j += dasmjag(JAGUAR_DSP, buffer, j);
1109 WriteLog("\t%08X: %s\n", oldj, buffer);
1112 WriteLog("DSP opcodes use:\n");
1115 if (dsp_opcode_use[i])
1116 WriteLog("\t%s %i\n", dsp_opcode_str[i], dsp_opcode_use[i]);
1119 memory_free(dsp_ram_8);
1123 // DSP execution core
1125 //static bool R20Set = false, tripwire = false;
1126 //static uint32 pcQueue[32], ptrPCQ = 0;
1127 void DSPExec(int32 cycles)
1129 /*HACKS!!! -> if (cycles != 1 && jaguar_mainRom_crc32 == 0xba74c3ed)
1130 dsp_check_if_i2s_interrupt_needed();*/
1132 #ifdef DSP_SINGLE_STEPPING
1133 if (dsp_control & 0x18)
1136 dsp_control &= ~0x10;
1139 //There is *no* good reason to do this here!
1141 dsp_releaseTimeSlice_flag = 0;
1144 while (cycles > 0 && DSP_RUNNING)
1148 WriteLog("\nDSP: Encountered bad write in Atari Synth module. PC=%08X, R15=%08X\n", dsp_pc, dsp_reg[15]);
1149 for(int i=0; i<80; i+=4)
1150 WriteLog(" %08X: %08X\n", dsp_reg[15]+i, JaguarReadLong(dsp_reg[15]+i));
1153 /*if (dsp_pc == 0xF1B55E)
1155 WriteLog("DSP: At $F1B55E--R15 = %08X at %u ms%s...\n", dsp_reg[15], SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1157 /*if (dsp_pc == 0xF1B7D2) // Start here???
1159 pcQueue[ptrPCQ++] = dsp_pc;
1161 uint16 opcode = DSPReadWord(dsp_pc, DSP);
1162 uint32 index = opcode >> 10;
1163 dsp_opcode_first_parameter = (opcode >> 5) & 0x1F;
1164 dsp_opcode_second_parameter = opcode & 0x1F;
1166 dsp_opcode[index]();
1167 dsp_opcode_use[index]++;
1168 cycles -= dsp_opcode_cycles[index];
1169 /*if (dsp_reg_bank_0[20] == 0xF1A100 & !R20Set)
1171 WriteLog("DSP: R20 set to $F1A100 at %u ms%s...\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1174 if (dsp_reg_bank_0[20] != 0xF1A100 && R20Set)
1176 WriteLog("DSP: R20 corrupted at %u ms from starting%s!\nAborting!\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1178 DSPDumpDisassembly();
1181 if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFE) && !tripwire)
1184 WriteLog("DSP: Jumping outside of DSP RAM at %u ms. Register dump:\n", SDL_GetTicks());
1187 WriteLog("\nBacktrace:\n");
1188 for(int i=0; i<32; i++)
1190 dasmjag(JAGUAR_DSP, buffer, pcQueue[(ptrPCQ + i) % 32]);
1191 WriteLog("\t%08X: %s\n", pcQueue[(ptrPCQ + i) % 32], buffer);
1201 // DSP opcode handlers
1204 // There is a problem here with interrupt handlers the JUMP and JR instructions that
1205 // can cause trouble because an interrupt can occur *before* the instruction following the
1206 // jump can execute... !!! FIX !!!
1207 static void dsp_opcode_jump(void)
1210 char * condition[32] =
1211 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1212 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1213 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1214 "???", "???", "???", "F" };
1216 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);
1219 /* dsp_flag_c=dsp_flag_c?1:0;
1220 dsp_flag_z=dsp_flag_z?1:0;
1221 dsp_flag_n=dsp_flag_n?1:0;*/
1222 // KLUDGE: Used by BRANCH_CONDITION
1223 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1225 if (BRANCH_CONDITION(IMM_2))
1229 WriteLog("Branched!\n");
1231 uint32 delayed_pc = RM;
1233 dsp_pc = delayed_pc;
1238 WriteLog("Branch NOT taken.\n");
1242 static void dsp_opcode_jr(void)
1245 char * condition[32] =
1246 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1247 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1248 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1249 "???", "???", "???", "F" };
1251 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);
1254 /* dsp_flag_c=dsp_flag_c?1:0;
1255 dsp_flag_z=dsp_flag_z?1:0;
1256 dsp_flag_n=dsp_flag_n?1:0;*/
1257 // KLUDGE: Used by BRANCH_CONDITION
1258 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1260 if (BRANCH_CONDITION(IMM_2))
1264 WriteLog("Branched!\n");
1266 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1267 int32 delayed_pc = dsp_pc + (offset * 2);
1269 dsp_pc = delayed_pc;
1274 WriteLog("Branch NOT taken.\n");
1278 static void dsp_opcode_add(void)
1282 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);
1284 UINT32 res = RN + RM;
1285 SET_ZNC_ADD(RN, RM, res);
1289 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);
1293 static void dsp_opcode_addc(void)
1297 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);
1299 UINT32 res = RN + RM + dsp_flag_c;
1300 UINT32 carry = dsp_flag_c;
1301 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1302 SET_ZNC_ADD(RN + carry, RM, res);
1303 // SET_ZNC_ADD(RN, RM + carry, res);
1307 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);
1311 static void dsp_opcode_addq(void)
1315 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);
1317 UINT32 r1 = dsp_convert_zero[IMM_1];
1318 UINT32 res = RN + r1;
1319 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1323 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1327 static void dsp_opcode_sub(void)
1331 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);
1333 UINT32 res = RN - RM;
1334 SET_ZNC_SUB(RN, RM, res);
1338 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);
1342 static void dsp_opcode_subc(void)
1346 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);
1348 UINT32 res = RN - RM - dsp_flag_c;
1349 UINT32 borrow = dsp_flag_c;
1350 SET_ZNC_SUB(RN - borrow, RM, res);
1354 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);
1358 static void dsp_opcode_subq(void)
1362 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);
1364 UINT32 r1 = dsp_convert_zero[IMM_1];
1365 UINT32 res = RN - r1;
1366 SET_ZNC_SUB(RN, r1, res);
1370 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1374 static void dsp_opcode_cmp(void)
1378 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);
1380 UINT32 res = RN - RM;
1381 SET_ZNC_SUB(RN, RM, res);
1384 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1388 static void dsp_opcode_cmpq(void)
1390 static int32 sqtable[32] =
1391 { 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 };
1394 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);
1396 UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1397 UINT32 res = RN - r1;
1398 SET_ZNC_SUB(RN, r1, res);
1401 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1405 static void dsp_opcode_and(void)
1409 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);
1415 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);
1419 static void dsp_opcode_or(void)
1423 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);
1429 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);
1433 static void dsp_opcode_xor(void)
1437 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);
1443 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);
1447 static void dsp_opcode_not(void)
1451 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);
1457 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);
1461 static void dsp_opcode_move_pc(void)
1466 static void dsp_opcode_store_r14_indexed(void)
1468 #ifdef DSP_DIS_STORE14I
1470 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));
1472 DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1475 static void dsp_opcode_store_r15_indexed(void)
1477 #ifdef DSP_DIS_STORE15I
1479 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));
1481 DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1484 static void dsp_opcode_load_r14_ri(void)
1486 #ifdef DSP_DIS_LOAD14R
1488 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);
1490 RN = DSPReadLong(dsp_reg[14] + RM, DSP);
1491 #ifdef DSP_DIS_LOAD14R
1493 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1497 static void dsp_opcode_load_r15_ri(void)
1499 #ifdef DSP_DIS_LOAD15R
1501 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);
1503 RN = DSPReadLong(dsp_reg[15] + RM, DSP);
1504 #ifdef DSP_DIS_LOAD15R
1506 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1510 static void dsp_opcode_store_r14_ri(void)
1512 DSPWriteLong(dsp_reg[14] + RM, RN, DSP);
1515 static void dsp_opcode_store_r15_ri(void)
1517 DSPWriteLong(dsp_reg[15] + RM, RN, DSP);
1520 static void dsp_opcode_nop(void)
1524 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", dsp_pc-2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
1528 static void dsp_opcode_storeb(void)
1530 #ifdef DSP_DIS_STOREB
1532 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);
1534 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1535 DSPWriteLong(RM, RN & 0xFF, DSP);
1537 JaguarWriteByte(RM, RN, DSP);
1540 static void dsp_opcode_storew(void)
1542 #ifdef DSP_DIS_STOREW
1544 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);
1546 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1547 DSPWriteLong(RM, RN & 0xFFFF, DSP);
1549 JaguarWriteWord(RM, RN, DSP);
1552 static void dsp_opcode_store(void)
1554 #ifdef DSP_DIS_STORE
1556 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);
1558 DSPWriteLong(RM, RN, DSP);
1561 static void dsp_opcode_loadb(void)
1563 #ifdef DSP_DIS_LOADB
1565 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);
1567 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1568 RN = DSPReadLong(RM, DSP) & 0xFF;
1570 RN = JaguarReadByte(RM, DSP);
1571 #ifdef DSP_DIS_LOADB
1573 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1577 static void dsp_opcode_loadw(void)
1579 #ifdef DSP_DIS_LOADW
1581 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);
1583 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1584 RN = DSPReadLong(RM, DSP) & 0xFFFF;
1586 RN = JaguarReadWord(RM, DSP);
1587 #ifdef DSP_DIS_LOADW
1589 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1593 static void dsp_opcode_load(void)
1597 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);
1599 RN = DSPReadLong(RM, DSP);
1602 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1606 static void dsp_opcode_load_r14_indexed(void)
1608 #ifdef DSP_DIS_LOAD14I
1610 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);
1612 RN = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), DSP);
1613 #ifdef DSP_DIS_LOAD14I
1615 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1619 static void dsp_opcode_load_r15_indexed(void)
1621 #ifdef DSP_DIS_LOAD15I
1623 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);
1625 RN = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), DSP);
1626 #ifdef DSP_DIS_LOAD15I
1628 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1632 static void dsp_opcode_movei(void)
1634 #ifdef DSP_DIS_MOVEI
1636 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);
1638 // This instruction is followed by 32-bit value in LSW / MSW format...
1639 RN = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
1641 #ifdef DSP_DIS_MOVEI
1643 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1647 static void dsp_opcode_moveta(void)
1649 #ifdef DSP_DIS_MOVETA
1651 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);
1654 #ifdef DSP_DIS_MOVETA
1656 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);
1660 static void dsp_opcode_movefa(void)
1662 #ifdef DSP_DIS_MOVEFA
1664 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);
1667 #ifdef DSP_DIS_MOVEFA
1669 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);
1673 static void dsp_opcode_move(void)
1677 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);
1682 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);
1686 static void dsp_opcode_moveq(void)
1688 #ifdef DSP_DIS_MOVEQ
1690 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);
1693 #ifdef DSP_DIS_MOVEQ
1695 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1699 static void dsp_opcode_resmac(void)
1701 #ifdef DSP_DIS_RESMAC
1703 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));
1705 RN = (uint32)dsp_acc;
1706 #ifdef DSP_DIS_RESMAC
1708 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1712 static void dsp_opcode_imult(void)
1714 #ifdef DSP_DIS_IMULT
1716 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);
1718 RN = (int16)RN * (int16)RM;
1720 #ifdef DSP_DIS_IMULT
1722 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);
1726 static void dsp_opcode_mult(void)
1730 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);
1732 RN = (uint16)RM * (uint16)RN;
1736 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);
1740 static void dsp_opcode_bclr(void)
1744 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);
1746 UINT32 res = RN & ~(1 << IMM_1);
1751 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1755 static void dsp_opcode_btst(void)
1759 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);
1761 dsp_flag_z = (~RN >> IMM_1) & 1;
1764 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1768 static void dsp_opcode_bset(void)
1772 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);
1774 UINT32 res = RN | (1 << IMM_1);
1779 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1783 static void dsp_opcode_subqt(void)
1785 #ifdef DSP_DIS_SUBQT
1787 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);
1789 RN -= dsp_convert_zero[IMM_1];
1790 #ifdef DSP_DIS_SUBQT
1792 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1796 static void dsp_opcode_addqt(void)
1798 #ifdef DSP_DIS_ADDQT
1800 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);
1802 RN += dsp_convert_zero[IMM_1];
1803 #ifdef DSP_DIS_ADDQT
1805 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1809 static void dsp_opcode_imacn(void)
1811 #ifdef DSP_DIS_IMACN
1813 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);
1815 int32 res = (int16)RM * (int16)RN;
1816 dsp_acc += (int64)res;
1817 //Should we AND the result to fit into 40 bits here???
1818 #ifdef DSP_DIS_IMACN
1820 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));
1824 static void dsp_opcode_mtoi(void)
1826 RN = (((INT32)RM >> 8) & 0xFF800000) | (RM & 0x007FFFFF);
1830 static void dsp_opcode_normi(void)
1837 while ((_Rm & 0xffc00000) == 0)
1842 while ((_Rm & 0xff800000) != 0)
1852 static void dsp_opcode_mmult(void)
1854 int count = dsp_matrix_control&0x0f;
1855 uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
1859 if (!(dsp_matrix_control & 0x10))
1861 for (int i = 0; i < count; i++)
1865 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1867 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1868 int16 b=((int16)DSPReadWord(addr + 2, DSP));
1875 for (int i = 0; i < count; i++)
1879 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1881 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1882 int16 b=((int16)DSPReadWord(addr + 2, DSP));
1887 RN = res = (int32)accum;
1889 //NOTE: The flags are set based upon the last add/multiply done...
1893 static void dsp_opcode_abs(void)
1898 if (_Rn == 0x80000000)
1902 dsp_flag_c = ((_Rn & 0x80000000) >> 31);
1903 res = RN = (_Rn & 0x80000000 ? -_Rn : _Rn);
1908 static void dsp_opcode_div(void)
1915 if (dsp_div_control & 1)
1917 dsp_remain = (((uint64)_Rn) << 16) % _Rm;
1918 if (dsp_remain&0x80000000)
1920 RN = (((uint64)_Rn) << 16) / _Rm;
1924 dsp_remain = _Rn % _Rm;
1925 if (dsp_remain&0x80000000)
1934 static void dsp_opcode_imultn(void)
1936 #ifdef DSP_DIS_IMULTN
1938 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);
1940 // This is OK, since this multiply won't overflow 32 bits...
1941 int32 res = (int32)((int16)RN * (int16)RM);
1942 dsp_acc = (int64)res;
1944 #ifdef DSP_DIS_IMULTN
1946 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));
1950 static void dsp_opcode_neg(void)
1954 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);
1957 SET_ZNC_SUB(0, RN, res);
1961 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1965 static void dsp_opcode_shlq(void)
1969 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);
1971 INT32 r1 = 32 - IMM_1;
1972 UINT32 res = RN << r1;
1973 SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
1977 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1981 static void dsp_opcode_shrq(void)
1985 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);
1987 INT32 r1 = dsp_convert_zero[IMM_1];
1988 UINT32 res = RN >> r1;
1989 SET_ZN(res); dsp_flag_c = RN & 1;
1993 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1997 static void dsp_opcode_ror(void)
2001 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);
2003 UINT32 r1 = RM & 0x1F;
2004 UINT32 res = (RN >> r1) | (RN << (32 - r1));
2005 SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
2009 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);
2013 static void dsp_opcode_rorq(void)
2017 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);
2019 UINT32 r1 = dsp_convert_zero[IMM_1 & 0x1F];
2021 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
2023 SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
2026 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2030 static void dsp_opcode_sha(void)
2032 int32 sRm=(int32)RM;
2038 if (shift>=32) shift=32;
2039 dsp_flag_c=(_Rn&0x80000000)>>31;
2049 if (shift>=32) shift=32;
2053 _Rn=((int32)_Rn)>>1;
2061 static void dsp_opcode_sharq(void)
2063 #ifdef DSP_DIS_SHARQ
2065 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);
2067 UINT32 res = (INT32)RN >> dsp_convert_zero[IMM_1];
2068 SET_ZN(res); dsp_flag_c = RN & 0x01;
2070 #ifdef DSP_DIS_SHARQ
2072 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2076 static void dsp_opcode_sh(void)
2078 int32 sRm=(int32)RM;
2083 uint32 shift=(-sRm);
2084 if (shift>=32) shift=32;
2085 dsp_flag_c=(_Rn&0x80000000)>>31;
2095 if (shift>=32) shift=32;
2107 void dsp_opcode_addqmod(void)
2109 #ifdef DSP_DIS_ADDQMOD
2111 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);
2113 UINT32 r1 = dsp_convert_zero[IMM_1];
2115 UINT32 res = r2 + r1;
2116 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2118 SET_ZNC_ADD(r2, r1, res);
2119 #ifdef DSP_DIS_ADDQMOD
2121 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2125 void dsp_opcode_subqmod(void)
2127 UINT32 r1 = dsp_convert_zero[IMM_1];
2129 UINT32 res = r2 - r1;
2130 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2133 SET_ZNC_SUB(r2, r1, res);
2136 void dsp_opcode_mirror(void)
2139 RN = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
2143 void dsp_opcode_sat32s(void)
2145 INT32 r2 = (UINT32)RN;
2146 INT32 temp = dsp_acc >> 32;
2147 UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
2152 void dsp_opcode_sat16s(void)
2155 UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
2161 // New pipelined DSP core
2164 static void DSP_abs(void);
2165 static void DSP_add(void);
2166 static void DSP_addc(void);
2167 static void DSP_addq(void);
2168 static void DSP_addqmod(void);
2169 static void DSP_addqt(void);
2170 static void DSP_and(void);
2171 static void DSP_bclr(void);
2172 static void DSP_bset(void);
2173 static void DSP_btst(void);
2174 static void DSP_cmp(void);
2175 static void DSP_cmpq(void);
2176 static void DSP_div(void);
2177 static void DSP_imacn(void);
2178 static void DSP_imult(void);
2179 static void DSP_imultn(void);
2180 static void DSP_illegal(void);
2181 static void DSP_jr(void);
2182 static void DSP_jump(void);
2183 static void DSP_load(void);
2184 static void DSP_loadb(void);
2185 static void DSP_loadw(void);
2186 static void DSP_load_r14_i(void);
2187 static void DSP_load_r14_r(void);
2188 static void DSP_load_r15_i(void);
2189 static void DSP_load_r15_r(void);
2190 static void DSP_mirror(void);
2191 static void DSP_mmult(void);
2192 static void DSP_move(void);
2193 static void DSP_movefa(void);
2194 static void DSP_movei(void);
2195 static void DSP_movepc(void);
2196 static void DSP_moveq(void);
2197 static void DSP_moveta(void);
2198 static void DSP_mtoi(void);
2199 static void DSP_mult(void);
2200 static void DSP_neg(void);
2201 static void DSP_nop(void);
2202 static void DSP_normi(void);
2203 static void DSP_not(void);
2204 static void DSP_or(void);
2205 static void DSP_resmac(void);
2206 static void DSP_ror(void);
2207 static void DSP_rorq(void);
2208 static void DSP_sat16s(void);
2209 static void DSP_sat32s(void);
2210 static void DSP_sh(void);
2211 static void DSP_sha(void);
2212 static void DSP_sharq(void);
2213 static void DSP_shlq(void);
2214 static void DSP_shrq(void);
2215 static void DSP_store(void);
2216 static void DSP_storeb(void);
2217 static void DSP_storew(void);
2218 static void DSP_store_r14_i(void);
2219 static void DSP_store_r14_r(void);
2220 static void DSP_store_r15_i(void);
2221 static void DSP_store_r15_r(void);
2222 static void DSP_sub(void);
2223 static void DSP_subc(void);
2224 static void DSP_subq(void);
2225 static void DSP_subqmod(void);
2226 static void DSP_subqt(void);
2227 static void DSP_xor(void);
2229 void (* DSPOpcode[64])() =
2231 DSP_add, DSP_addc, DSP_addq, DSP_addqt,
2232 DSP_sub, DSP_subc, DSP_subq, DSP_subqt,
2233 DSP_neg, DSP_and, DSP_or, DSP_xor,
2234 DSP_not, DSP_btst, DSP_bset, DSP_bclr,
2236 DSP_mult, DSP_imult, DSP_imultn, DSP_resmac,
2237 DSP_imacn, DSP_div, DSP_abs, DSP_sh,
2238 DSP_shlq, DSP_shrq, DSP_sha, DSP_sharq,
2239 DSP_ror, DSP_rorq, DSP_cmp, DSP_cmpq,
2241 DSP_subqmod, DSP_sat16s, DSP_move, DSP_moveq,
2242 DSP_moveta, DSP_movefa, DSP_movei, DSP_loadb,
2243 DSP_loadw, DSP_load, DSP_sat32s, DSP_load_r14_i,
2244 DSP_load_r15_i, DSP_storeb, DSP_storew, DSP_store,
2246 DSP_mirror, DSP_store_r14_i, DSP_store_r15_i, DSP_movepc,
2247 DSP_jump, DSP_jr, DSP_mmult, DSP_mtoi,
2248 DSP_normi, DSP_nop, DSP_load_r14_r, DSP_load_r15_r,
2249 DSP_store_r14_r, DSP_store_r15_r, DSP_illegal, DSP_addqmod
2252 bool readAffected[64][2] =
2254 { true, true}, { true, true}, {false, true}, {false, true},
2255 { true, true}, { true, true}, {false, true}, {false, true},
2256 {false, true}, { true, true}, { true, true}, { true, true},
2257 {false, true}, {false, true}, {false, true}, {false, true},
2259 { true, true}, { true, true}, { true, true}, {false, true},
2260 { true, true}, { true, true}, {false, true}, { true, true},
2261 {false, true}, {false, true}, { true, true}, {false, true},
2262 { true, true}, {false, true}, { true, true}, {false, true},
2264 {false, true}, {false, true}, { true, false}, {false, false},
2265 { true, false}, {false, false}, {false, false}, { true, false},
2266 { true, false}, { true, false}, {false, true}, { true, false},
2267 { true, false}, { true, true}, { true, true}, { true, true},
2269 {false, true}, { true, true}, { true, true}, {false, true},
2270 { true, false}, { true, false}, { true, true}, { true, false},
2271 { true, false}, {false, false}, { true, false}, { true, false},
2272 { true, true}, { true, true}, {false, false}, {false, true}
2275 void FlushDSPPipeline(void)
2277 plPtrFetch = 3, plPtrRead = 2, plPtrExec = 1, plPtrWrite = 0;
2279 for(int i=0; i<4; i++)
2280 pipeline[i].opcode = PIPELINE_STALL;
2282 for(int i=0; i<32; i++)
2283 scoreboard[i] = false;
2287 // New pipelined DSP execution core
2289 /*void DSPExecP(int32 cycles)
2291 // bool inhibitFetch = false;
2293 dsp_releaseTimeSlice_flag = 0;
2296 while (cycles > 0 && DSP_RUNNING)
2298 WriteLog("DSPExecP: Pipeline status...\n");
2299 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);
2300 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);
2301 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);
2302 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);
2303 WriteLog(" --> Scoreboard: ");
2304 for(int i=0; i<32; i++)
2305 WriteLog("%s ", scoreboard[i] ? "T" : "F");
2307 // Stage 1: Instruction fetch
2308 // if (!inhibitFetch)
2310 pipeline[plPtrFetch].instruction = DSPReadWord(dsp_pc, DSP);
2311 pipeline[plPtrFetch].opcode = pipeline[plPtrFetch].instruction >> 10;
2312 pipeline[plPtrFetch].operand1 = (pipeline[plPtrFetch].instruction >> 5) & 0x1F;
2313 pipeline[plPtrFetch].operand2 = pipeline[plPtrFetch].instruction & 0x1F;
2314 if (pipeline[plPtrFetch].opcode == 38)
2315 pipeline[plPtrFetch].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
2316 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
2319 // inhibitFetch = false;
2320 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrFetch].instruction, dsp_pc);
2322 WriteLog("DSPExecP: Pipeline status (after stage 1)...\n");
2323 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);
2324 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);
2325 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);
2326 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);
2327 // Stage 2: Read registers
2328 //Ok, stalls here depend on whether or not the instruction reads two registers or not
2329 //and *which* register (1 or 2) is the one being read... !!! FIX !!!
2330 if (scoreboard[pipeline[plPtrRead].operand2])
2331 && pipeline[plPtrRead].opcode != PIPELINE_STALL)
2332 // We have a hit in the scoreboard, so we have to stall the pipeline...
2334 //This is crappy, crappy CRAPPY! And it doesn't work! !!! FIX !!!
2335 // dsp_pc -= (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2336 WriteLog(" --> Stalling pipeline: scoreboard = %s\n", scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
2337 pipeline[plPtrFetch] = pipeline[plPtrRead];
2338 pipeline[plPtrRead].opcode = PIPELINE_STALL;
2342 pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
2343 pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
2344 pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2; // Set it to RN
2346 if (pipeline[plPtrRead].opcode != PIPELINE_STALL)
2347 // Shouldn't we be more selective with the register scoreboarding?
2348 // Yes, we should. !!! FIX !!!
2349 scoreboard[pipeline[plPtrRead].operand2] = true;
2350 //Advance PC here??? Yes.
2351 // dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2352 //This is a mangling of the pipeline stages, but what else to do???
2353 dsp_pc += (pipeline[plPtrFetch].opcode == 38 ? 6 : 2);
2356 WriteLog("DSPExecP: Pipeline status (after stage 2)...\n");
2357 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);
2358 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);
2359 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);
2360 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);
2362 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
2364 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
2365 DSPOpcode[pipeline[plPtrExec].opcode]();
2366 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
2367 cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
2372 WriteLog("DSPExecP: Pipeline status (after stage 3)...\n");
2373 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);
2374 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);
2375 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);
2376 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);
2377 // Stage 4: Write back register
2378 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
2380 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
2381 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
2383 scoreboard[pipeline[plPtrWrite].operand1]
2384 = scoreboard[pipeline[plPtrWrite].operand2] = false;
2387 // Push instructions through the pipeline...
2388 plPtrFetch = (++plPtrFetch) & 0x03;
2389 plPtrRead = (++plPtrRead) & 0x03;
2390 plPtrExec = (++plPtrExec) & 0x03;
2391 plPtrWrite = (++plPtrWrite) & 0x03;
2398 //Problems: JR and any other instruction that relies on DSP_PC is getting WRONG values!
2400 // Should be fixed now. Another problem is figuring how to do the sequence following
2401 // a branch followed with the JR & JUMP instructions...
2403 // There are two conflicting problems:
2406 F1B236: LOAD (R31), R03 [NCZ:000, R31=00F1CFDC, R03=00F14000] -> [NCZ:000, R03=00F1B084]
2407 F1B238: BCLR #3, R00 [NCZ:000, R00=00004039] -> [NCZ:000, R00=00004031]
2408 F1B23A: ADDQ #2, R03 [NCZ:000, R03=00F1B084] -> [NCZ:000, R03=00F1B086]
2409 F1B23C: SUBQ #1, R17 [NCZ:000, R17=00000040] -> [NCZ:000, R17=0000003F]
2410 F1B23E: MOVEI #$00F1CFE0, R31 [NCZ:000, R31=00F1CFDC] -> [NCZ:000, R31=00F1CFE0]
2411 F1B244: JR z, F1B254 [NCZ:000] Branch NOT taken.
2412 F1B246: BSET #10, R00 [NCZ:000, R00=00004031] -> [NCZ:000, R00=00004431]
2413 F1B248: MOVEI #$00F1A100, R01 [NCZ:000, R01=00F1A148] -> [NCZ:000, R01=00F1A100]
2414 F1B24E: STORE R00, (R01) [NCZ:000, R00=00004431, R01=00F1A100]
2415 DSP: Writing 00004431 to DSP_FLAGS by DSP...
2416 DSP: Finished interrupt.
2417 ; Without pipeline effects, the value in R03 is erroneously read from bank 1 instead of
2418 ; bank 0 (where is was prepared)!
2419 F1B250: JUMP T, (R03) [NCZ:001, R03=00000000] Branched!
2420 F1B252: NOP [NCZ:001]
2423 // The other is when you see this at the end of an IRQ:
2426 JUMP T, (R29) ; R29 = Previous stack + 2
2427 STORE R28, (R30) ; R28 = Modified flags register, R30 = $F1A100
2429 ; Actually, this is OK if we do the atomic JUMP/JR operation correctly:
2430 ; 1) The STORE goes through the pipeline and is executed/written back
2431 ; 2) The pipeline is flushed
2432 ; 3) The DSP_PC is set to the new address
2433 ; 4) Execution resumes
2435 JUMP T, (R25) ; Oops! Because of pipeline effects R25 has the value from
2436 ; bank 0 instead of the current bank 1 and so goes astray!
2439 //One other thing: Since these stages are supposed to happen simulaneously, try executing
2440 //them in reverse order to see if that reduces pipeline stalls from late writebacks...
2444 Small problem here: The return address when INT0 comes up is $F1B088, but when INT1
2445 follows it, the JUMP out of the previous interrupt is bypassed immediately--this is
2446 because the STORE instruction writes back on stage #2 of the pipeline instead of stage #3...
2447 If it were done properly, the STORE write back would occur *after* (well, technically,
2448 during) the execution of the the JUMP that follows it.
2452 F1B08A: JR z, F1B082 [NCZ:001] Branched!
2453 F1B08A: NOP [NCZ:001]
2455 F1B080: MOVEI #$00F1B178, R00 [NCZ:001, R00=00F1B178] -> [NCZ:001, R00=00F1B178]
2458 F1B086: LOAD (R00), R01 [NCZ:001, R00=00F1B178, R01=00000000] -> [NCZ:001, R01=00000000]
2461 F1B088: OR R01, R01 [NCZ:001, R01=00000000, R01=00000000] -> [NCZ:001, R01=00000000, R01=00000000]
2462 F1B08A: JR z, F1B082 [NCZ:001] Branched!
2463 F1B08A: NOP [NCZ:001]
2465 F1B080: MOVEI #$00F1B178, R00 [NCZ:001, R00=00F1B178] -> [NCZ:001, R00=00F1B178]
2468 Write to DSP CTRL: 00002301 --> Starting to run at 00F1B088 by M68K...
2469 DSP: CPU -> DSP interrupt
2470 DSP: Generating interrupt #0... [PC will return to 00F1B088, R31 = 00F1CFE0]
2471 Write to DSP CTRL: 00000001 --> Starting to run at 00F1B000 by M68K...
2473 F1B000: MOVEI #$00F1B0D4, R30 [NCZ:001, R30=00F1B000] -> [NCZ:001, R30=00F1B0D4]
2476 F1B006: JUMP T, (R30) [NCZ:001, R30=00F1B0D4] Branched!
2477 F1B006: NOP [NCZ:001]
2479 F1B0D4: MOVEI #$00F1A100, R01 [NCZ:001, R01=00F1A100] -> [NCZ:001, R01=00F1A100]
2482 F1B0DA: LOAD (R01), R00 [NCZ:001, R01=00F1A100, R00=00004431] -> [NCZ:001, R00=00004039]
2483 F1B0DC: MOVEI #$00F1B0C8, R01 [NCZ:001, R01=00F1A100] -> [NCZ:001, R01=00F1B0C8]
2486 F1B0E2: LOAD (R01), R02 [NCZ:001, R01=00F1B0C8, R02=00000000] -> [NCZ:001, R02=00000001]
2487 F1B0E4: MOVEI #$00F1B0CC, R01 [NCZ:001, R01=00F1B0C8] -> [NCZ:001, R01=00F1B0CC]
2490 F1B0EA: LOAD (R01), R03 [NCZ:001, R01=00F1B0CC, R03=00F1B086] -> [NCZ:001, R03=00000064]
2491 F1B0EC: MOVEI #$00F1B0D0, R01 [NCZ:001, R01=00F1B0CC] -> [NCZ:001, R01=00F1B0D0]
2494 F1B0F2: LOAD (R01), R04 [NCZ:001, R01=00F1B0D0, R04=00000000] -> [NCZ:001, R04=00000008]
2495 F1B0F4: MOVEI #$00F1B0BC, R01 [NCZ:001, R01=00F1B0D0] -> [NCZ:001, R01=00F1B0BC]
2498 F1B0FA: ADD R04, R01 [NCZ:001, R04=00000008, R01=00F1B0BC] -> [NCZ:000, R04=00000008, R01=00F1B0C4]
2501 F1B0FC: LOAD (R01), R01 [NCZ:000, R01=00F1B0C4, R01=00F1B0C4] -> [NCZ:000, R01=00F1B12E]
2504 F1B0FE: JUMP T, (R01) [NCZ:000, R01=00F1B12E] Branched!
2505 F1B0FE: NOP [NCZ:000]
2507 F1B12E: MOVE R02, R08 [NCZ:000, R02=00000001, R08=00000000] -> [NCZ:000, R02=00000001, R08=00000001]
2510 F1B132: MOVEI #$00F1B102, R01 [NCZ:000, R01=00F1B12E] -> [NCZ:000, R01=00F1B102]
2513 F1B138: JUMP T, (R01) [NCZ:000, R01=00F1B102] Branched!
2514 F1B138: NOP [NCZ:000]
2516 F1B102: MOVEI #$00F1B0C8, R01 [NCZ:000, R01=00F1B102] -> [NCZ:000, R01=00F1B0C8]
2519 F1B108: STORE R08, (R01) [NCZ:000, R08=00000000, R01=00F1B0C8]
2520 F1B10A: MOVEI #$00F1B0D0, R01 [NCZ:000, R01=00F1B0C8] -> [NCZ:000, R01=00F1B0D0]
2521 F1B110: MOVEQ #0, R04 [NCZ:000, R04=00000008] -> [NCZ:000, R04=00000000]
2524 F1B112: STORE R04, (R01) [NCZ:000, R04=00000000, R01=00F1B0D0]
2525 F1B114: BCLR #3, R00 [NCZ:000, R00=00004039] -> [NCZ:000, R00=00004031]
2528 F1B116: BSET #9, R00 [NCZ:000, R00=00004031] -> [NCZ:000, R00=00004231]
2529 F1B118: LOAD (R31), R04 [NCZ:000, R31=00F1CFDC, R04=00000000] -> [NCZ:000, R04=00F1B086]
2530 F1B11A: MOVEI #$00F1CFE0, R31 [NCZ:000, R31=00F1CFDC] -> [NCZ:000, R31=00F1CFE0]
2532 F1B120: ADDQ #2, R04 [NCZ:000, R04=00F1B086] -> [NCZ:000, R04=00F1B088]
2533 F1B122: MOVEI #$00F1A100, R01 [NCZ:000, R01=00F1B0D0] -> [NCZ:000, R01=00F1A100]
2536 F1B128: STORE R00, (R01) [NCZ:000, R00=00004231, R01=00F1A100]
2537 DSP: Writing 00004231 to DSP_FLAGS by DSP (REGPAGE is set)...
2538 DSP: Finished interrupt.
2539 DSP: Generating interrupt #1... [PC will return to 00F1B12A, R31 = 00F1CFE0]
2541 F1B010: MOVEI #$00F1B1FC, R30 [NCZ:001, R30=00F1B010] -> [NCZ:001, R30=00F1B1FC]
2544 F1B016: JUMP T, (R30) [NCZ:001, R30=00F1B1FC] Branched!
2545 F1B016: NOP [NCZ:001]
2547 F1B1FC: MOVEI #$00F1A100, R01 [NCZ:001, R01=00F1A100] -> [NCZ:001, R01=00F1A100]
2551 //#define DSP_DEBUG_PL2
2552 //Let's try a 3 stage pipeline....
2553 //Looks like 3 stage is correct, otherwise bad things happen...
2554 void DSPExecP2(int32 cycles)
2556 dsp_releaseTimeSlice_flag = 0;
2559 while (cycles > 0 && DSP_RUNNING)
2561 if (IMASKCleared) // If IMASK was cleared,
2563 #ifdef DSP_DEBUG_IRQ
2564 WriteLog("DSP: Finished interrupt.\n");
2566 DSPHandleIRQs(); // See if any other interrupts are pending!
2567 IMASKCleared = false;
2570 //if (dsp_flags & REGPAGE)
2571 // WriteLog(" --> REGPAGE has just been set!\n");
2572 #ifdef DSP_DEBUG_PL2
2573 WriteLog("DSPExecP: Pipeline status [PC=%08X]...\n", dsp_pc);
2574 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]);
2575 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]);
2576 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]);
2577 WriteLog(" --> Scoreboard: ");
2578 for(int i=0; i<32; i++)
2579 WriteLog("%s ", scoreboard[i] ? "T" : "F");
2582 // Stage 1a: Instruction fetch
2583 pipeline[plPtrRead].instruction = DSPReadWord(dsp_pc, DSP);
2584 pipeline[plPtrRead].opcode = pipeline[plPtrRead].instruction >> 10;
2585 pipeline[plPtrRead].operand1 = (pipeline[plPtrRead].instruction >> 5) & 0x1F;
2586 pipeline[plPtrRead].operand2 = pipeline[plPtrRead].instruction & 0x1F;
2587 if (pipeline[plPtrRead].opcode == 38)
2588 pipeline[plPtrRead].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
2589 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
2590 #ifdef DSP_DEBUG_PL2
2591 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrRead].instruction, dsp_pc);
2592 WriteLog("DSPExecP: Pipeline status (after stage 1a) [PC=%08X]...\n", dsp_pc);
2593 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]);
2594 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]);
2595 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]);
2597 // Stage 1b: Read registers
2598 //Small problem--when say LOAD or STORE (R14/5+$nn) is executed AFTER an instruction that
2599 //modifies R14/5, we don't check the scoreboard for R14/5 (and we need to!)... !!! FIX !!!
2601 if ((scoreboard[pipeline[plPtrRead].operand1] && readAffected[pipeline[plPtrRead].opcode][0])
2602 || (scoreboard[pipeline[plPtrRead].operand2] && readAffected[pipeline[plPtrRead].opcode][1])
2603 || ((pipeline[plPtrRead].opcode == 43 || pipeline[plPtrRead].opcode == 58) && scoreboard[14])
2604 || ((pipeline[plPtrRead].opcode == 44 || pipeline[plPtrRead].opcode == 59) && scoreboard[15]))
2605 // We have a hit in the scoreboard, so we have to stall the pipeline...
2606 #ifdef DSP_DEBUG_PL2
2608 WriteLog(" --> Stalling pipeline: ");
2609 if (readAffected[pipeline[plPtrRead].opcode][0])
2610 WriteLog("scoreboard[%u] = %s (reg 1) ", pipeline[plPtrRead].operand1, scoreboard[pipeline[plPtrRead].operand1] ? "true" : "false");
2611 if (readAffected[pipeline[plPtrRead].opcode][1])
2612 WriteLog("scoreboard[%u] = %s (reg 2)", pipeline[plPtrRead].operand2, scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
2615 pipeline[plPtrRead].opcode = PIPELINE_STALL;
2616 #ifdef DSP_DEBUG_PL2
2621 pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
2622 pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
2623 pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2; // Set it to RN
2625 // Shouldn't we be more selective with the register scoreboarding?
2626 // Yes, we should. !!! FIX !!! Kinda [DONE]
2627 scoreboard[pipeline[plPtrRead].operand2] = affectsScoreboard[pipeline[plPtrRead].opcode];
2629 //Advance PC here??? Yes.
2630 dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2633 #ifdef DSP_DEBUG_PL2
2634 WriteLog("DSPExecP: Pipeline status (after stage 1b) [PC=%08X]...\n", dsp_pc);
2635 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]);
2636 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]);
2637 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]);
2640 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
2642 #ifdef DSP_DEBUG_PL2
2643 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
2645 DSPOpcode[pipeline[plPtrExec].opcode]();
2646 //WriteLog(" --> Returned from execute. DSP_PC: %08X\n", dsp_pc);
2647 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
2648 cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
2653 #ifdef DSP_DEBUG_STALL
2654 WriteLog("[STALL...]\n");
2658 #ifdef DSP_DEBUG_PL2
2659 WriteLog("DSPExecP: Pipeline status (after stage 2) [PC=%08X]...\n", dsp_pc);
2660 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]);
2661 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]);
2662 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]);
2665 // Stage 3: Write back register/memory address
2666 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
2668 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
2670 if (pipeline[plPtrWrite].writebackRegister != 0xFE)
2671 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
2674 if (pipeline[plPtrWrite].type == TYPE_BYTE)
2675 JaguarWriteByte(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
2676 else if (pipeline[plPtrWrite].type == TYPE_WORD)
2677 JaguarWriteWord(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
2679 JaguarWriteLong(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
2683 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
2684 scoreboard[pipeline[plPtrWrite].operand2] = false;
2687 // Push instructions through the pipeline...
2688 plPtrRead = (++plPtrRead) & 0x03;
2689 plPtrExec = (++plPtrExec) & 0x03;
2690 plPtrWrite = (++plPtrWrite) & 0x03;
2699 //#define DSP_DEBUG_PL3
2700 //Let's try a 2 stage pipeline....
2701 void DSPExecP3(int32 cycles)
2703 dsp_releaseTimeSlice_flag = 0;
2706 while (cycles > 0 && DSP_RUNNING)
2708 //if (dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFF)
2710 #ifdef DSP_DEBUG_PL3
2711 WriteLog("DSPExecP: Pipeline status...\n");
2712 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]);
2713 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]);
2714 WriteLog(" --> Scoreboard: ");
2715 for(int i=0; i<32; i++)
2716 WriteLog("%s ", scoreboard[i] ? "T" : "F");
2719 // Stage 1a: Instruction fetch
2720 pipeline[plPtrRead].instruction = DSPReadWord(dsp_pc, DSP);
2721 pipeline[plPtrRead].opcode = pipeline[plPtrRead].instruction >> 10;
2722 pipeline[plPtrRead].operand1 = (pipeline[plPtrRead].instruction >> 5) & 0x1F;
2723 pipeline[plPtrRead].operand2 = pipeline[plPtrRead].instruction & 0x1F;
2724 if (pipeline[plPtrRead].opcode == 38)
2725 pipeline[plPtrRead].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
2726 | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
2727 #ifdef DSP_DEBUG_PL3
2728 WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrRead].instruction, dsp_pc);
2729 WriteLog("DSPExecP: Pipeline status (after stage 1a)...\n");
2730 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]);
2731 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]);
2733 // Stage 1b: Read registers
2734 if ((scoreboard[pipeline[plPtrRead].operand1] && readAffected[pipeline[plPtrRead].opcode][0])
2735 || (scoreboard[pipeline[plPtrRead].operand2] && readAffected[pipeline[plPtrRead].opcode][1]))
2736 // We have a hit in the scoreboard, so we have to stall the pipeline...
2737 #ifdef DSP_DEBUG_PL3
2739 WriteLog(" --> Stalling pipeline: ");
2740 if (readAffected[pipeline[plPtrRead].opcode][0])
2741 WriteLog("scoreboard[%u] = %s (reg 1) ", pipeline[plPtrRead].operand1, scoreboard[pipeline[plPtrRead].operand1] ? "true" : "false");
2742 if (readAffected[pipeline[plPtrRead].opcode][1])
2743 WriteLog("scoreboard[%u] = %s (reg 2)", pipeline[plPtrRead].operand2, scoreboard[pipeline[plPtrRead].operand2] ? "true" : "false");
2746 pipeline[plPtrRead].opcode = PIPELINE_STALL;
2747 #ifdef DSP_DEBUG_PL3
2752 pipeline[plPtrRead].reg1 = dsp_reg[pipeline[plPtrRead].operand1];
2753 pipeline[plPtrRead].reg2 = dsp_reg[pipeline[plPtrRead].operand2];
2754 pipeline[plPtrRead].writebackRegister = pipeline[plPtrRead].operand2; // Set it to RN
2756 // Shouldn't we be more selective with the register scoreboarding?
2757 // Yes, we should. !!! FIX !!! [Kinda DONE]
2758 scoreboard[pipeline[plPtrRead].operand2] = affectsScoreboard[pipeline[plPtrRead].opcode];
2760 //Advance PC here??? Yes.
2761 dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
2764 #ifdef DSP_DEBUG_PL3
2765 WriteLog("DSPExecP: Pipeline status (after stage 1b)...\n");
2766 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]);
2767 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]);
2769 // Stage 2a: Execute
2770 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
2772 #ifdef DSP_DEBUG_PL3
2773 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
2775 DSPOpcode[pipeline[plPtrExec].opcode]();
2776 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
2777 cycles -= dsp_opcode_cycles[pipeline[plPtrExec].opcode];
2782 #ifdef DSP_DEBUG_PL3
2783 WriteLog("DSPExecP: Pipeline status (after stage 2a)...\n");
2784 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]);
2785 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]);
2788 // Stage 2b: Write back register
2789 if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
2791 if (pipeline[plPtrExec].writebackRegister != 0xFF)
2792 dsp_reg[pipeline[plPtrExec].writebackRegister] = pipeline[plPtrExec].result;
2794 if (affectsScoreboard[pipeline[plPtrExec].opcode])
2795 scoreboard[pipeline[plPtrExec].operand2] = false;
2798 // Push instructions through the pipeline...
2799 plPtrRead = (++plPtrRead) & 0x03;
2800 plPtrExec = (++plPtrExec) & 0x03;
2807 // DSP pipelined opcode handlers
2810 #define PRM pipeline[plPtrExec].reg1
2811 #define PRN pipeline[plPtrExec].reg2
2812 #define PIMM1 pipeline[plPtrExec].operand1
2813 #define PIMM2 pipeline[plPtrExec].operand2
2814 #define PRES pipeline[plPtrExec].result
2815 #define PWBR pipeline[plPtrExec].writebackRegister
2816 #define NO_WRITEBACK pipeline[plPtrExec].writebackRegister = 0xFF
2817 //#define DSP_PPC dsp_pc - (pipeline[plPtrRead].opcode == 38 ? 6 : 2) - (pipeline[plPtrExec].opcode == 38 ? 6 : 2)
2818 #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))
2819 #define WRITEBACK_ADDR pipeline[plPtrExec].writebackRegister = 0xFE
2821 static void DSP_abs(void)
2825 WriteLog("%06X: ABS R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
2829 if (_Rn == 0x80000000)
2833 dsp_flag_c = ((_Rn & 0x80000000) >> 31);
2834 PRES = (_Rn & 0x80000000 ? -_Rn : _Rn);
2835 CLR_ZN; SET_Z(PRES);
2839 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
2843 static void DSP_add(void)
2847 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);
2849 UINT32 res = PRN + PRM;
2850 SET_ZNC_ADD(PRN, PRM, res);
2854 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);
2858 static void DSP_addc(void)
2862 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);
2864 UINT32 res = PRN + PRM + dsp_flag_c;
2865 UINT32 carry = dsp_flag_c;
2866 // SET_ZNC_ADD(PRN, PRM, res); //???BUG??? Yes!
2867 SET_ZNC_ADD(PRN + carry, PRM, res);
2868 // SET_ZNC_ADD(PRN, PRM + carry, res);
2872 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);
2876 static void DSP_addq(void)
2880 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);
2882 UINT32 r1 = dsp_convert_zero[PIMM1];
2883 UINT32 res = PRN + r1;
2884 CLR_ZNC; SET_ZNC_ADD(PRN, r1, res);
2888 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
2892 static void DSP_addqmod(void)
2894 #ifdef DSP_DIS_ADDQMOD
2896 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);
2898 UINT32 r1 = dsp_convert_zero[PIMM1];
2900 UINT32 res = r2 + r1;
2901 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2903 SET_ZNC_ADD(r2, r1, res);
2904 #ifdef DSP_DIS_ADDQMOD
2906 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
2910 static void DSP_addqt(void)
2912 #ifdef DSP_DIS_ADDQT
2914 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);
2916 PRES = PRN + dsp_convert_zero[PIMM1];
2917 #ifdef DSP_DIS_ADDQT
2919 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
2923 static void DSP_and(void)
2927 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);
2933 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);
2937 static void DSP_bclr(void)
2941 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);
2943 PRES = PRN & ~(1 << PIMM1);
2947 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
2951 static void DSP_bset(void)
2955 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);
2957 PRES = PRN | (1 << PIMM1);
2961 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
2965 static void DSP_btst(void)
2969 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);
2971 dsp_flag_z = (~PRN >> PIMM1) & 1;
2975 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
2979 static void DSP_cmp(void)
2983 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);
2985 UINT32 res = PRN - PRM;
2986 SET_ZNC_SUB(PRN, PRM, res);
2990 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
2994 static void DSP_cmpq(void)
2996 static int32 sqtable[32] =
2997 { 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 };
3000 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);
3002 UINT32 r1 = sqtable[PIMM1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
3003 UINT32 res = PRN - r1;
3004 SET_ZNC_SUB(PRN, r1, res);
3008 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
3012 static void DSP_div(void)
3014 uint32 _Rm = PRM, _Rn = PRN;
3018 if (dsp_div_control & 1)
3020 dsp_remain = (((uint64)_Rn) << 16) % _Rm;
3021 if (dsp_remain & 0x80000000)
3023 PRES = (((uint64)_Rn) << 16) / _Rm;
3027 dsp_remain = _Rn % _Rm;
3028 if (dsp_remain & 0x80000000)
3037 static void DSP_imacn(void)
3039 #ifdef DSP_DIS_IMACN
3041 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);
3043 int32 res = (int16)PRM * (int16)PRN;
3044 dsp_acc += (int64)res;
3045 //Should we AND the result to fit into 40 bits here???
3047 #ifdef DSP_DIS_IMACN
3049 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));
3053 static void DSP_imult(void)
3055 #ifdef DSP_DIS_IMULT
3057 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);
3059 PRES = (int16)PRN * (int16)PRM;
3061 #ifdef DSP_DIS_IMULT
3063 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);
3067 static void DSP_imultn(void)
3069 #ifdef DSP_DIS_IMULTN
3071 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);
3073 // This is OK, since this multiply won't overflow 32 bits...
3074 int32 res = (int32)((int16)PRN * (int16)PRM);
3075 dsp_acc = (int64)res;
3078 #ifdef DSP_DIS_IMULTN
3080 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));
3084 static void DSP_illegal(void)
3086 #ifdef DSP_DIS_ILLEGAL
3088 WriteLog("%06X: ILLEGAL [NCZ:%u%u%u]\n", DSP_PPC, dsp_flag_n, dsp_flag_c, dsp_flag_z);
3093 // There is a problem here with interrupt handlers the JUMP and JR instructions that
3094 // can cause trouble because an interrupt can occur *before* the instruction following the
3095 // jump can execute... !!! FIX !!!
3096 // This can probably be solved by judicious coding in the pipeline execution core...
3097 // And should be fixed now...
3098 static void DSP_jr(void)
3101 char * condition[32] =
3102 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
3103 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
3104 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
3105 "???", "???", "???", "F" };
3107 WriteLog("%06X: JR %s, %06X [NCZ:%u%u%u] ", DSP_PPC, condition[PIMM2], dsp_pc+((PIMM1 & 0x10 ? 0xFFFFFFF0 | PIMM1 : PIMM1) * 2), dsp_flag_n, dsp_flag_c, dsp_flag_z);
3109 // KLUDGE: Used by BRANCH_CONDITION macro
3110 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
3112 if (BRANCH_CONDITION(PIMM2))
3116 WriteLog("Branched!\n");
3118 int32 offset = (PIMM1 & 0x10 ? 0xFFFFFFF0 | PIMM1 : PIMM1); // Sign extend PIMM1
3119 //Account for pipeline effects...
3120 uint32 newPC = dsp_pc + (offset * 2) - (pipeline[plPtrRead].opcode == 38 ? 6 : (pipeline[plPtrRead].opcode == PIPELINE_STALL ? 0 : 2));
3121 //WriteLog(" --> Old PC: %08X, new PC: %08X\n", dsp_pc, newPC);
3123 // Now that we've branched, we have to make sure that the following instruction
3124 // is executed atomically with this one and then flush the pipeline before setting
3127 // Step 1: Handle writebacks at stage 3 of pipeline
3128 /* if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
3130 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
3131 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
3133 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
3134 scoreboard[pipeline[plPtrWrite].operand2] = false;
3136 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
3138 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
3140 if (pipeline[plPtrWrite].writebackRegister != 0xFE)
3141 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
3144 if (pipeline[plPtrWrite].type == TYPE_BYTE)
3145 JaguarWriteByte(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3146 else if (pipeline[plPtrWrite].type == TYPE_WORD)
3147 JaguarWriteWord(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3149 JaguarWriteLong(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3153 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
3154 scoreboard[pipeline[plPtrWrite].operand2] = false;
3157 // Step 2: Push instruction through pipeline & execute following instruction
3158 // NOTE: By putting our following instruction at stage 3 of the pipeline,
3159 // we effectively handle the final push of the instruction through the
3160 // pipeline when the new PC takes effect (since when we return, the
3161 // pipeline code will be executing the writeback stage. If we reverse
3162 // the execution order of the pipeline stages, this will no longer be
3164 pipeline[plPtrExec] = pipeline[plPtrRead];
3165 //This is BAD. We need to get that next opcode and execute it!
3166 //NOTE: The problem is here because of a bad stall. Once those are fixed, we can probably
3167 // remove this crap.
3168 if (pipeline[plPtrExec].opcode == PIPELINE_STALL)
3170 uint16 instruction = DSPReadWord(dsp_pc, DSP);
3171 pipeline[plPtrExec].opcode = instruction >> 10;
3172 pipeline[plPtrExec].operand1 = (instruction >> 5) & 0x1F;
3173 pipeline[plPtrExec].operand2 = instruction & 0x1F;
3174 pipeline[plPtrExec].reg1 = dsp_reg[pipeline[plPtrExec].operand1];
3175 pipeline[plPtrExec].reg2 = dsp_reg[pipeline[plPtrExec].operand2];
3176 pipeline[plPtrExec].writebackRegister = pipeline[plPtrExec].operand2; // Set it to RN
3178 DSPOpcode[pipeline[plPtrExec].opcode]();
3179 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
3180 pipeline[plPtrWrite] = pipeline[plPtrExec];
3182 // Step 3: Flush pipeline & set new PC
3183 pipeline[plPtrRead].opcode = pipeline[plPtrExec].opcode = PIPELINE_STALL;
3190 WriteLog("Branch NOT taken.\n");
3196 // WriteLog(" --> DSP_PC: %08X\n", dsp_pc);
3199 static void DSP_jump(void)
3202 char * condition[32] =
3203 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
3204 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
3205 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
3206 "???", "???", "???", "F" };
3208 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);
3210 // KLUDGE: Used by BRANCH_CONDITION macro
3211 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
3213 if (BRANCH_CONDITION(PIMM2))
3217 WriteLog("Branched!\n");
3219 uint32 PCSave = PRM;
3220 // Now that we've branched, we have to make sure that the following instruction
3221 // is executed atomically with this one and then flush the pipeline before setting
3224 // Step 1: Handle writebacks at stage 3 of pipeline
3225 /* if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
3227 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
3228 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
3230 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
3231 scoreboard[pipeline[plPtrWrite].operand2] = false;
3233 if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
3235 if (pipeline[plPtrWrite].writebackRegister != 0xFF)
3237 if (pipeline[plPtrWrite].writebackRegister != 0xFE)
3238 dsp_reg[pipeline[plPtrWrite].writebackRegister] = pipeline[plPtrWrite].result;
3241 if (pipeline[plPtrWrite].type == TYPE_BYTE)
3242 JaguarWriteByte(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3243 else if (pipeline[plPtrWrite].type == TYPE_WORD)
3244 JaguarWriteWord(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3246 JaguarWriteLong(pipeline[plPtrWrite].address, pipeline[plPtrWrite].value);
3250 if (affectsScoreboard[pipeline[plPtrWrite].opcode])
3251 scoreboard[pipeline[plPtrWrite].operand2] = false;
3254 // Step 2: Push instruction through pipeline & execute following instruction
3255 // NOTE: By putting our following instruction at stage 3 of the pipeline,
3256 // we effectively handle the final push of the instruction through the
3257 // pipeline when the new PC takes effect (since when we return, the
3258 // pipeline code will be executing the writeback stage. If we reverse
3259 // the execution order of the pipeline stages, this will no longer be
3261 pipeline[plPtrExec] = pipeline[plPtrRead];
3262 //This is BAD. We need to get that next opcode and execute it!
3263 //Also, same problem in JR!
3264 //NOTE: The problem is here because of a bad stall. Once those are fixed, we can probably
3265 // remove this crap.
3266 if (pipeline[plPtrExec].opcode == PIPELINE_STALL)
3268 uint16 instruction = DSPReadWord(dsp_pc, DSP);
3269 pipeline[plPtrExec].opcode = instruction >> 10;
3270 pipeline[plPtrExec].operand1 = (instruction >> 5) & 0x1F;
3271 pipeline[plPtrExec].operand2 = instruction & 0x1F;
3272 pipeline[plPtrExec].reg1 = dsp_reg[pipeline[plPtrExec].operand1];
3273 pipeline[plPtrExec].reg2 = dsp_reg[pipeline[plPtrExec].operand2];
3274 pipeline[plPtrExec].writebackRegister = pipeline[plPtrExec].operand2; // Set it to RN
3276 DSPOpcode[pipeline[plPtrExec].opcode]();
3277 dsp_opcode_use[pipeline[plPtrExec].opcode]++;
3278 pipeline[plPtrWrite] = pipeline[plPtrExec];
3280 // Step 3: Flush pipeline & set new PC
3281 pipeline[plPtrRead].opcode = pipeline[plPtrExec].opcode = PIPELINE_STALL;
3288 WriteLog("Branch NOT taken.\n");
3296 static void DSP_load(void)
3300 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);
3302 PRES = DSPReadLong(PRM, DSP);
3305 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3309 static void DSP_loadb(void)
3311 #ifdef DSP_DIS_LOADB
3313 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);
3315 if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
3316 PRES = DSPReadLong(PRM, DSP) & 0xFF;
3318 PRES = JaguarReadByte(PRM, DSP);
3319 #ifdef DSP_DIS_LOADB
3321 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3325 static void DSP_loadw(void)
3327 #ifdef DSP_DIS_LOADW
3329 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);
3331 if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
3332 PRES = DSPReadLong(PRM, DSP) & 0xFFFF;
3334 PRES = JaguarReadWord(PRM, DSP);
3335 #ifdef DSP_DIS_LOADW
3337 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3341 static void DSP_load_r14_i(void)
3343 #ifdef DSP_DIS_LOAD14I
3345 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);
3347 PRES = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), DSP);
3348 #ifdef DSP_DIS_LOAD14I
3350 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3354 static void DSP_load_r14_r(void)
3356 #ifdef DSP_DIS_LOAD14R
3358 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);
3360 PRES = DSPReadLong(dsp_reg[14] + PRM, DSP);
3361 #ifdef DSP_DIS_LOAD14R
3363 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3367 static void DSP_load_r15_i(void)
3369 #ifdef DSP_DIS_LOAD15I
3371 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);
3373 PRES = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), DSP);
3374 #ifdef DSP_DIS_LOAD15I
3376 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3380 static void DSP_load_r15_r(void)
3382 #ifdef DSP_DIS_LOAD15R
3384 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);
3386 PRES = DSPReadLong(dsp_reg[15] + PRM, DSP);
3387 #ifdef DSP_DIS_LOAD15R
3389 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3393 static void DSP_mirror(void)
3396 PRES = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
3400 static void DSP_mmult(void)
3402 int count = dsp_matrix_control&0x0f;
3403 uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
3407 if (!(dsp_matrix_control & 0x10))
3409 for (int i = 0; i < count; i++)
3413 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
3415 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
3416 int16 b=((int16)DSPReadWord(addr + 2, DSP));
3423 for (int i = 0; i < count; i++)
3427 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
3429 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
3430 int16 b=((int16)DSPReadWord(addr + 2, DSP));
3436 PRES = res = (int32)accum;
3438 //NOTE: The flags are set based upon the last add/multiply done...
3442 static void DSP_move(void)
3446 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);
3451 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);
3455 static void DSP_movefa(void)
3457 #ifdef DSP_DIS_MOVEFA
3459 // 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);
3460 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);
3462 // PRES = ALTERNATE_RM;
3463 PRES = dsp_alternate_reg[PIMM1];
3464 #ifdef DSP_DIS_MOVEFA
3466 // 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);
3467 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);
3471 static void DSP_movei(void)
3473 #ifdef DSP_DIS_MOVEI
3475 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);
3477 // // This instruction is followed by 32-bit value in LSW / MSW format...
3478 // PRES = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
3480 #ifdef DSP_DIS_MOVEI
3482 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3486 static void DSP_movepc(void)
3488 //Need to fix this to take into account pipelining effects... !!! FIX !!!
3492 static void DSP_moveq(void)
3494 #ifdef DSP_DIS_MOVEQ
3496 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);
3499 #ifdef DSP_DIS_MOVEQ
3501 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3505 static void DSP_moveta(void)
3507 #ifdef DSP_DIS_MOVETA
3509 // 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);
3510 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]);
3512 // ALTERNATE_RN = PRM;
3513 dsp_alternate_reg[PIMM2] = PRM;
3515 #ifdef DSP_DIS_MOVETA
3517 // 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);
3518 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]);
3522 static void DSP_mtoi(void)
3524 PRES = (((INT32)PRM >> 8) & 0xFF800000) | (PRM & 0x007FFFFF);
3528 static void DSP_mult(void)
3532 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);
3534 PRES = (uint16)PRM * (uint16)PRN;
3538 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);
3542 static void DSP_neg(void)
3546 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);
3549 SET_ZNC_SUB(0, PRN, res);
3553 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3557 static void DSP_nop(void)
3561 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", DSP_PPC, dsp_flag_n, dsp_flag_c, dsp_flag_z);
3566 static void DSP_normi(void)
3573 while ((_Rm & 0xffc00000) == 0)
3578 while ((_Rm & 0xff800000) != 0)
3588 static void DSP_not(void)
3592 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);
3598 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);
3602 static void DSP_or(void)
3606 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);
3612 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);
3616 static void DSP_resmac(void)
3618 #ifdef DSP_DIS_RESMAC
3620 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));
3622 PRES = (uint32)dsp_acc;
3623 #ifdef DSP_DIS_RESMAC
3625 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
3629 static void DSP_ror(void)
3633 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);
3635 UINT32 r1 = PRM & 0x1F;
3636 UINT32 res = (PRN >> r1) | (PRN << (32 - r1));
3637 SET_ZN(res); dsp_flag_c = (PRN >> 31) & 1;
3641 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);
3645 static void DSP_rorq(void)
3649 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);
3651 UINT32 r1 = dsp_convert_zero[PIMM1 & 0x1F];
3653 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
3655 SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
3658 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3662 static void DSP_sat16s(void)
3665 UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
3670 static void DSP_sat32s(void)
3672 INT32 r2 = (UINT32)PRN;
3673 INT32 temp = dsp_acc >> 32;
3674 UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
3679 static void DSP_sh(void)
3681 int32 sRm = (int32)PRM;
3686 uint32 shift = -sRm;
3691 dsp_flag_c = (_Rn & 0x80000000) >> 31;
3706 dsp_flag_c = _Rn & 0x1;
3719 static void DSP_sha(void)
3721 int32 sRm = (int32)PRM;
3726 uint32 shift = -sRm;
3731 dsp_flag_c = (_Rn & 0x80000000) >> 31;
3746 dsp_flag_c = _Rn & 0x1;
3750 _Rn = ((int32)_Rn) >> 1;
3759 static void DSP_sharq(void)
3761 #ifdef DSP_DIS_SHARQ
3763 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);
3765 UINT32 res = (INT32)PRN >> dsp_convert_zero[PIMM1];
3766 SET_ZN(res); dsp_flag_c = PRN & 0x01;
3768 #ifdef DSP_DIS_SHARQ
3770 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3774 static void DSP_shlq(void)
3778 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);
3780 INT32 r1 = 32 - PIMM1;
3781 UINT32 res = PRN << r1;
3782 SET_ZN(res); dsp_flag_c = (PRN >> 31) & 1;
3786 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3790 static void DSP_shrq(void)
3794 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);
3796 INT32 r1 = dsp_convert_zero[PIMM1];
3797 UINT32 res = PRN >> r1;
3798 SET_ZN(res); dsp_flag_c = PRN & 1;
3802 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3806 static void DSP_store(void)
3808 #ifdef DSP_DIS_STORE
3810 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);
3812 // DSPWriteLong(PRM, PRN, DSP);
3814 pipeline[plPtrExec].address = PRM;
3815 pipeline[plPtrExec].value = PRN;
3816 pipeline[plPtrExec].type = TYPE_DWORD;
3820 static void DSP_storeb(void)
3822 #ifdef DSP_DIS_STOREB
3824 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);
3826 // if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
3827 // DSPWriteLong(PRM, PRN & 0xFF, DSP);
3829 // JaguarWriteByte(PRM, PRN, DSP);
3832 pipeline[plPtrExec].address = PRM;
3834 if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
3836 pipeline[plPtrExec].value = PRN & 0xFF;
3837 pipeline[plPtrExec].type = TYPE_DWORD;
3841 pipeline[plPtrExec].value = PRN;
3842 pipeline[plPtrExec].type = TYPE_BYTE;
3848 static void DSP_storew(void)
3850 #ifdef DSP_DIS_STOREW
3852 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);
3854 // if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
3855 // DSPWriteLong(PRM, PRN & 0xFFFF, DSP);
3857 // JaguarWriteWord(PRM, PRN, DSP);
3860 pipeline[plPtrExec].address = PRM;
3862 if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
3864 pipeline[plPtrExec].value = PRN & 0xFFFF;
3865 pipeline[plPtrExec].type = TYPE_DWORD;
3869 pipeline[plPtrExec].value = PRN;
3870 pipeline[plPtrExec].type = TYPE_WORD;
3875 static void DSP_store_r14_i(void)
3877 #ifdef DSP_DIS_STORE14I
3879 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));
3881 // DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
3883 pipeline[plPtrExec].address = dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2);
3884 pipeline[plPtrExec].value = PRN;
3885 pipeline[plPtrExec].type = TYPE_DWORD;
3889 static void DSP_store_r14_r(void)
3891 // DSPWriteLong(dsp_reg[14] + PRM, PRN, DSP);
3893 pipeline[plPtrExec].address = dsp_reg[14] + PRM;
3894 pipeline[plPtrExec].value = PRN;
3895 pipeline[plPtrExec].type = TYPE_DWORD;
3899 static void DSP_store_r15_i(void)
3901 #ifdef DSP_DIS_STORE15I
3903 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));
3905 // DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
3907 pipeline[plPtrExec].address = dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2);
3908 pipeline[plPtrExec].value = PRN;
3909 pipeline[plPtrExec].type = TYPE_DWORD;
3913 static void DSP_store_r15_r(void)
3915 // DSPWriteLong(dsp_reg[15] + PRM, PRN, DSP);
3917 pipeline[plPtrExec].address = dsp_reg[15] + PRM;
3918 pipeline[plPtrExec].value = PRN;
3919 pipeline[plPtrExec].type = TYPE_DWORD;
3923 static void DSP_sub(void)
3927 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);
3929 UINT32 res = PRN - PRM;
3930 SET_ZNC_SUB(PRN, PRM, res);
3934 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);
3938 static void DSP_subc(void)
3942 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);
3944 UINT32 res = PRN - PRM - dsp_flag_c;
3945 UINT32 borrow = dsp_flag_c;
3946 SET_ZNC_SUB(PRN - borrow, PRM, res);
3950 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);
3954 static void DSP_subq(void)
3958 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);
3960 UINT32 r1 = dsp_convert_zero[PIMM1];
3961 UINT32 res = PRN - r1;
3962 SET_ZNC_SUB(PRN, r1, res);
3966 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3970 static void DSP_subqmod(void)
3972 UINT32 r1 = dsp_convert_zero[PIMM1];
3974 UINT32 res = r2 - r1;
3975 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
3977 SET_ZNC_SUB(r2, r1, res);
3980 static void DSP_subqt(void)
3982 #ifdef DSP_DIS_SUBQT
3984 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);
3986 PRES = PRN - dsp_convert_zero[PIMM1];
3987 #ifdef DSP_DIS_SUBQT
3989 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
3993 static void DSP_xor(void)
3997 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);
4003 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);