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
15 // Disassembly definitions
20 #define DSP_DIS_ADDQMOD
30 #define DSP_DIS_IMULTN
34 #define DSP_DIS_LOAD14I
35 #define DSP_DIS_LOAD14R
36 #define DSP_DIS_LOAD15I
37 #define DSP_DIS_LOAD15R
43 #define DSP_DIS_MOVEFA
44 #define DSP_DIS_MOVETA
50 #define DSP_DIS_RESMAC
57 #define DSP_DIS_STORE14I
58 #define DSP_DIS_STORE15I
59 #define DSP_DIS_STOREB
60 #define DSP_DIS_STOREW
67 bool doDSPDis = false;
102 + load_r15_indexed 284500
104 + store_r15_indexed 47416
108 + load_r14_ri 1229448
111 // DSP flags (old--have to get rid of this crap)
113 #define CINT0FLAG 0x00200
114 #define CINT1FLAG 0x00400
115 #define CINT2FLAG 0x00800
116 #define CINT3FLAG 0x01000
117 #define CINT4FLAG 0x02000
118 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
119 #define CINT5FLAG 0x20000 /* DSP only */
123 #define ZERO_FLAG 0x00001
124 #define CARRY_FLAG 0x00002
125 #define NEGA_FLAG 0x00004
126 #define IMASK 0x00008
127 #define INT_ENA0 0x00010
128 #define INT_ENA1 0x00020
129 #define INT_ENA2 0x00040
130 #define INT_ENA3 0x00080
131 #define INT_ENA4 0x00100
132 #define INT_CLR0 0x00200
133 #define INT_CLR1 0x00400
134 #define INT_CLR2 0x00800
135 #define INT_CLR3 0x01000
136 #define INT_CLR4 0x02000
137 #define REGPAGE 0x04000
138 #define DMAEN 0x08000
139 #define INT_ENA5 0x10000
140 #define INT_CLR5 0x20000
144 #define DSPGO 0x00001
145 #define CPUINT 0x00002
146 #define DSPINT0 0x00004
147 #define SINGLE_STEP 0x00008
148 #define SINGLE_GO 0x00010
150 #define INT_LAT0 0x00040
151 #define INT_LAT1 0x00080
152 #define INT_LAT2 0x00100
153 #define INT_LAT3 0x00200
154 #define INT_LAT4 0x00400
155 #define BUS_HOG 0x00800
156 #define VERSION 0x0F000
157 #define INT_LAT5 0x10000
159 extern uint32 jaguar_mainRom_crc32;
161 // Is opcode 62 *really* a NOP? Seems like it...
162 static void dsp_opcode_abs(void);
163 static void dsp_opcode_add(void);
164 static void dsp_opcode_addc(void);
165 static void dsp_opcode_addq(void);
166 static void dsp_opcode_addqmod(void);
167 static void dsp_opcode_addqt(void);
168 static void dsp_opcode_and(void);
169 static void dsp_opcode_bclr(void);
170 static void dsp_opcode_bset(void);
171 static void dsp_opcode_btst(void);
172 static void dsp_opcode_cmp(void);
173 static void dsp_opcode_cmpq(void);
174 static void dsp_opcode_div(void);
175 static void dsp_opcode_imacn(void);
176 static void dsp_opcode_imult(void);
177 static void dsp_opcode_imultn(void);
178 static void dsp_opcode_jr(void);
179 static void dsp_opcode_jump(void);
180 static void dsp_opcode_load(void);
181 static void dsp_opcode_loadb(void);
182 static void dsp_opcode_loadw(void);
183 static void dsp_opcode_load_r14_indexed(void);
184 static void dsp_opcode_load_r14_ri(void);
185 static void dsp_opcode_load_r15_indexed(void);
186 static void dsp_opcode_load_r15_ri(void);
187 static void dsp_opcode_mirror(void);
188 static void dsp_opcode_mmult(void);
189 static void dsp_opcode_move(void);
190 static void dsp_opcode_movei(void);
191 static void dsp_opcode_movefa(void);
192 static void dsp_opcode_move_pc(void);
193 static void dsp_opcode_moveq(void);
194 static void dsp_opcode_moveta(void);
195 static void dsp_opcode_mtoi(void);
196 static void dsp_opcode_mult(void);
197 static void dsp_opcode_neg(void);
198 static void dsp_opcode_nop(void);
199 static void dsp_opcode_normi(void);
200 static void dsp_opcode_not(void);
201 static void dsp_opcode_or(void);
202 static void dsp_opcode_resmac(void);
203 static void dsp_opcode_ror(void);
204 static void dsp_opcode_rorq(void);
205 static void dsp_opcode_xor(void);
206 static void dsp_opcode_sat16s(void);
207 static void dsp_opcode_sat32s(void);
208 static void dsp_opcode_sh(void);
209 static void dsp_opcode_sha(void);
210 static void dsp_opcode_sharq(void);
211 static void dsp_opcode_shlq(void);
212 static void dsp_opcode_shrq(void);
213 static void dsp_opcode_store(void);
214 static void dsp_opcode_storeb(void);
215 static void dsp_opcode_storew(void);
216 static void dsp_opcode_store_r14_indexed(void);
217 static void dsp_opcode_store_r14_ri(void);
218 static void dsp_opcode_store_r15_indexed(void);
219 static void dsp_opcode_store_r15_ri(void);
220 static void dsp_opcode_sub(void);
221 static void dsp_opcode_subc(void);
222 static void dsp_opcode_subq(void);
223 static void dsp_opcode_subqmod(void);
224 static void dsp_opcode_subqt(void);
226 uint8 dsp_opcode_cycles[64] =
246 void (* dsp_opcode[64])() =
248 dsp_opcode_add, dsp_opcode_addc, dsp_opcode_addq, dsp_opcode_addqt,
249 dsp_opcode_sub, dsp_opcode_subc, dsp_opcode_subq, dsp_opcode_subqt,
250 dsp_opcode_neg, dsp_opcode_and, dsp_opcode_or, dsp_opcode_xor,
251 dsp_opcode_not, dsp_opcode_btst, dsp_opcode_bset, dsp_opcode_bclr,
252 dsp_opcode_mult, dsp_opcode_imult, dsp_opcode_imultn, dsp_opcode_resmac,
253 dsp_opcode_imacn, dsp_opcode_div, dsp_opcode_abs, dsp_opcode_sh,
254 dsp_opcode_shlq, dsp_opcode_shrq, dsp_opcode_sha, dsp_opcode_sharq,
255 dsp_opcode_ror, dsp_opcode_rorq, dsp_opcode_cmp, dsp_opcode_cmpq,
256 dsp_opcode_subqmod, dsp_opcode_sat16s, dsp_opcode_move, dsp_opcode_moveq,
257 dsp_opcode_moveta, dsp_opcode_movefa, dsp_opcode_movei, dsp_opcode_loadb,
258 dsp_opcode_loadw, dsp_opcode_load, dsp_opcode_sat32s, dsp_opcode_load_r14_indexed,
259 dsp_opcode_load_r15_indexed, dsp_opcode_storeb, dsp_opcode_storew, dsp_opcode_store,
260 dsp_opcode_mirror, dsp_opcode_store_r14_indexed, dsp_opcode_store_r15_indexed, dsp_opcode_move_pc,
261 dsp_opcode_jump, dsp_opcode_jr, dsp_opcode_mmult, dsp_opcode_mtoi,
262 dsp_opcode_normi, dsp_opcode_nop, dsp_opcode_load_r14_ri, dsp_opcode_load_r15_ri,
263 dsp_opcode_store_r14_ri, dsp_opcode_store_r15_ri, dsp_opcode_nop, dsp_opcode_addqmod,
266 uint32 dsp_opcode_use[64];
268 char * dsp_opcode_str[64]=
270 "add", "addc", "addq", "addqt",
271 "sub", "subc", "subq", "subqt",
272 "neg", "and", "or", "xor",
273 "not", "btst", "bset", "bclr",
274 "mult", "imult", "imultn", "resmac",
275 "imacn", "div", "abs", "sh",
276 "shlq", "shrq", "sha", "sharq",
277 "ror", "rorq", "cmp", "cmpq",
278 "subqmod", "sat16s", "move", "moveq",
279 "moveta", "movefa", "movei", "loadb",
280 "loadw", "load", "sat32s", "load_r14_indexed",
281 "load_r15_indexed", "storeb", "storew", "store",
282 "mirror", "store_r14_indexed","store_r15_indexed","move_pc",
283 "jump", "jr", "mmult", "mtoi",
284 "normi", "nop", "load_r14_ri", "load_r15_ri",
285 "store_r14_ri", "store_r15_ri", "nop", "addqmod",
289 static uint64 dsp_acc; // 40 bit register, NOT 32!
290 static uint32 dsp_remain;
291 static uint32 dsp_modulo;
292 static uint32 dsp_flags;
293 static uint32 dsp_matrix_control;
294 static uint32 dsp_pointer_to_matrix;
295 static uint32 dsp_data_organization;
297 static uint32 dsp_div_control;
298 static uint8 dsp_flag_z, dsp_flag_n, dsp_flag_c;
299 static uint32 * dsp_reg, * dsp_alternate_reg;
300 static uint32 * dsp_reg_bank_0, * dsp_reg_bank_1;
302 static uint32 dsp_opcode_first_parameter;
303 static uint32 dsp_opcode_second_parameter;
305 #define DSP_RUNNING (dsp_control & 0x01)
307 #define RM dsp_reg[dsp_opcode_first_parameter]
308 #define RN dsp_reg[dsp_opcode_second_parameter]
309 #define ALTERNATE_RM dsp_alternate_reg[dsp_opcode_first_parameter]
310 #define ALTERNATE_RN dsp_alternate_reg[dsp_opcode_second_parameter]
311 #define IMM_1 dsp_opcode_first_parameter
312 #define IMM_2 dsp_opcode_second_parameter
314 #define CLR_Z (dsp_flag_z = 0)
315 #define CLR_ZN (dsp_flag_z = dsp_flag_n = 0)
316 #define CLR_ZNC (dsp_flag_z = dsp_flag_n = dsp_flag_c = 0)
317 #define SET_Z(r) (dsp_flag_z = ((r) == 0))
318 #define SET_N(r) (dsp_flag_n = (((UINT32)(r) >> 31) & 0x01))
319 #define SET_C_ADD(a,b) (dsp_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
320 #define SET_C_SUB(a,b) (dsp_flag_c = ((UINT32)(b) > (UINT32)(a)))
321 #define SET_ZN(r) SET_N(r); SET_Z(r)
322 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
323 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
325 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 };
326 uint8 * dsp_branch_condition_table = NULL;
327 static uint16 * mirror_table = NULL;
328 static uint8 * dsp_ram_8 = NULL;
330 #define BRANCH_CONDITION(x) dsp_branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
332 static uint32 dsp_in_exec = 0;
333 static uint32 dsp_releaseTimeSlice_flag = 0;
337 // Private function prototypes
339 void DSPDumpRegisters(void);
340 void DSPDumpDisassembly(void);
343 void dsp_reset_stats(void)
345 for(int i=0; i<64; i++)
346 dsp_opcode_use[i] = 0;
349 void dsp_releaseTimeslice(void)
351 //This does absolutely nothing!!! !!! FIX !!!
352 dsp_releaseTimeSlice_flag = 1;
355 void dsp_build_branch_condition_table(void)
357 // Allocate the mirror table
359 mirror_table = (uint16 *)malloc(65536 * sizeof(mirror_table[0]));
361 // Fill in the mirror table
363 for(int i=0; i<65536; i++)
364 mirror_table[i] = ((i >> 15) & 0x0001) | ((i >> 13) & 0x0002) |
365 ((i >> 11) & 0x0004) | ((i >> 9) & 0x0008) |
366 ((i >> 7) & 0x0010) | ((i >> 5) & 0x0020) |
367 ((i >> 3) & 0x0040) | ((i >> 1) & 0x0080) |
368 ((i << 1) & 0x0100) | ((i << 3) & 0x0200) |
369 ((i << 5) & 0x0400) | ((i << 7) & 0x0800) |
370 ((i << 9) & 0x1000) | ((i << 11) & 0x2000) |
371 ((i << 13) & 0x4000) | ((i << 15) & 0x8000);
373 if (!dsp_branch_condition_table)
375 dsp_branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(dsp_branch_condition_table[0]));
377 // Fill in the condition table
378 if (dsp_branch_condition_table)
380 for(int i=0; i<8; i++)
382 for(int j=0; j<32; j++)
389 if (!(i & ZERO_FLAG))
392 if (i & (CARRY_FLAG << (j >> 4)))
395 if (!(i & (CARRY_FLAG << (j >> 4))))
397 dsp_branch_condition_table[i * 32 + j] = result;
404 uint8 DSPReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
407 // if ((offset==0xF1CFE0)||(offset==0xF1CFE2))
410 /* if ((jaguar_mainRom_crc32==0xbfd751a4)||(jaguar_mainRom_crc32==0x053efaf9))
412 if (offset==0xF1CFE0)
415 if (offset >= DSP_WORK_RAM_BASE && offset <= (DSP_WORK_RAM_BASE + 0x1FFF))
416 return dsp_ram_8[offset - DSP_WORK_RAM_BASE];
418 if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
420 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
422 if ((offset&0x03)==0)
425 if ((offset&0x03)==1)
426 return((data>>16)&0xff);
428 if ((offset&0x03)==2)
429 return((data>>8)&0xff);
431 if ((offset&0x03)==3)
435 return JaguarReadByte(offset, who);
438 uint16 DSPReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
441 offset &= 0xFFFFFFFE;
443 /* if (jaguar_mainRom_crc32==0xa74a97cd)
445 if (offset==0xF1A114) return(0x0000);
446 if (offset==0xF1A116) return(0x0000);
447 if (offset==0xF1B000) return(0x1234);
448 if (offset==0xF1B002) return(0x5678);
451 if (jaguar_mainRom_crc32==0x7ae20823)
453 if (offset==0xF1B9D8) return(0x0000);
454 if (offset==0xF1B9Da) return(0x0000);
455 if (offset==0xF1B2C0) return(0x0000);
456 if (offset==0xF1B2C2) return(0x0000);
459 // pour permettre à wolfenstein 3d de tourner sans le dsp
460 /* if ((offset==0xF1B0D0)||(offset==0xF1B0D2))
464 // pour permettre à nba jam de tourner sans le dsp
465 /* if (jaguar_mainRom_crc32==0x4faddb18)
467 if (offset==0xf1b2c0) return(0);
468 if (offset==0xf1b2c2) return(0);
469 if (offset==0xf1b240) return(0);
470 if (offset==0xf1b242) return(0);
471 if (offset==0xF1B340) return(0);
472 if (offset==0xF1B342) return(0);
473 if (offset==0xF1BAD8) return(0);
474 if (offset==0xF1BADA) return(0);
475 if (offset==0xF1B040) return(0);
476 if (offset==0xF1B042) return(0);
477 if (offset==0xF1B0C0) return(0);
478 if (offset==0xF1B0C2) return(0);
479 if (offset==0xF1B140) return(0);
480 if (offset==0xF1B142) return(0);
481 if (offset==0xF1B1C0) return(0);
482 if (offset==0xF1B1C2) return(0);
485 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE+0x1FFF)
487 offset -= DSP_WORK_RAM_BASE;
488 /* uint16 data = (((uint16)dsp_ram_8[offset])<<8)|((uint16)dsp_ram_8[offset+1]);
490 return GET16(dsp_ram_8, offset);
492 else if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
494 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
497 return data & 0xFFFF;
502 return JaguarReadWord(offset, who);
505 uint32 DSPReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
508 offset &= 0xFFFFFFFC;
509 /*if (offset == 0xF1BCF4)
511 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));
512 DSPDumpDisassembly();
514 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
516 offset -= DSP_WORK_RAM_BASE;
517 return GET32(dsp_ram_8, offset);
519 //NOTE: Didn't return DSP_ACCUM!!!
520 //Mebbe it's not 'spose to! Yes, it is!
521 if (offset >= DSP_CONTROL_RAM_BASE && offset <= DSP_CONTROL_RAM_BASE + 0x23)
526 case 0x00: /*dsp_flag_c?(dsp_flag_c=1):(dsp_flag_c=0);
527 dsp_flag_z?(dsp_flag_z=1):(dsp_flag_z=0);
528 dsp_flag_n?(dsp_flag_n=1):(dsp_flag_n=0);*/
530 dsp_flags = (dsp_flags & 0xFFFFFFF8) | (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
531 return dsp_flags & 0xFFFFC1FF;
532 case 0x04: return dsp_matrix_control;
533 case 0x08: return dsp_pointer_to_matrix;
534 case 0x0C: return dsp_data_organization;
535 case 0x10: return dsp_pc;
536 case 0x14: return dsp_control;
537 case 0x18: return dsp_modulo;
538 case 0x1C: return dsp_remain;
540 return (int32)((int8)(dsp_acc >> 32)); // Top 8 bits of 40-bit accumulator, sign extended
542 // unaligned long read-- !!! FIX !!!
546 return JaguarReadLong(offset, who);
549 void DSPWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
551 if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
553 offset -= DSP_WORK_RAM_BASE;
554 dsp_ram_8[offset] = data;
555 //This is rather stupid! !!! FIX !!!
556 /* if (dsp_in_exec == 0)
558 m68k_end_timeslice();
559 gpu_releaseTimeslice();
563 if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
565 uint32 reg = offset & 0x1C;
566 int bytenum = offset & 0x03;
568 if ((reg >= 0x1C) && (reg <= 0x1F))
569 dsp_div_control = (dsp_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
572 //This looks funky. !!! FIX !!!
573 uint32 old_data = DSPReadLong(offset&0xFFFFFFC, who);
574 bytenum = 3 - bytenum; // convention motorola !!!
575 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
576 DSPWriteLong(offset & 0xFFFFFFC, old_data, who);
580 // WriteLog("dsp: writing %.2x at 0x%.8x\n",data,offset);
581 //Should this *ever* happen??? Shouldn't we be saying "unknown" here???
582 JaguarWriteByte(offset, data, who);
585 void DSPWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
587 offset &= 0xFFFFFFFE;
588 /*if (offset == 0xF1BCF4)
590 WriteLog("DSPWriteWord: Writing to 0xF1BCF4... %04X -> %04X\n", GET16(dsp_ram_8, 0x0CF4), data);
592 // WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset);
593 if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
595 offset -= DSP_WORK_RAM_BASE;
596 dsp_ram_8[offset] = data >> 8;
597 dsp_ram_8[offset+1] = data & 0xFF;
598 //This is rather stupid! !!! FIX !!!
599 /* if (dsp_in_exec == 0)
601 // WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset+DSP_WORK_RAM_BASE);
602 m68k_end_timeslice();
603 gpu_releaseTimeslice();
607 else if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
609 if ((offset & 0x1C) == 0x1C)
612 dsp_div_control = (dsp_div_control&0xffff0000)|(data&0xffff);
614 dsp_div_control = (dsp_div_control&0xffff)|((data&0xffff)<<16);
618 uint32 old_data = DSPReadLong(offset & 0xffffffc, who);
620 old_data = (old_data&0xffff0000)|(data&0xffff);
622 old_data = (old_data&0xffff)|((data&0xffff)<<16);
623 DSPWriteLong(offset & 0xffffffc, old_data, who);
628 JaguarWriteWord(offset, data, who);
631 void DSPWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
634 offset &= 0xFFFFFFFC;
635 /*if (offset == 0xF1BCF4)
637 WriteLog("DSPWriteLong: Writing to 0xF1BCF4... %08X -> %08X\n", GET32(dsp_ram_8, 0x0CF4), data);
639 // WriteLog("dsp: writing %.8x at 0x%.8x\n",data,offset);
640 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
642 /*if (offset == 0xF1BE2C)
644 WriteLog("DSP: %s is writing %08X at location 0xF1BE2C (DSP_PC: %08X)...\n", whoName[who], data, dsp_pc - 2);
646 offset -= DSP_WORK_RAM_BASE;
647 SET32(dsp_ram_8, offset, data);
650 else if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
657 bool IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
659 dsp_flag_z = dsp_flags & 0x01;
660 dsp_flag_c = (dsp_flags >> 1) & 0x01;
661 dsp_flag_n = (dsp_flags >> 2) & 0x01;
662 DSPUpdateRegisterBanks();
663 dsp_control &= ~((dsp_flags & CINT04FLAGS) >> 3);
664 dsp_control &= ~((dsp_flags & CINT5FLAG) >> 1);
665 if (IMASKCleared) // If IMASK was cleared,
668 WriteLog("DSP: Finished interrupt.\n");
670 DSPHandleIRQs(); // see if any other interrupts need servicing!
677 dsp_matrix_control = data;
680 dsp_pointer_to_matrix = data;
683 dsp_data_organization = data;
688 WriteLog("DSP: Setting DSP PC to %08X by %s%s\n", dsp_pc, whoName[who], (DSP_RUNNING ? " (DSP is RUNNING!)" : ""));//*/
693 // uint32 dsp_was_running = DSP_RUNNING;
694 // Check for DSP -> CPU interrupt
697 // WriteLog("DSP: DSP -> CPU interrupt\n");
699 // Why do we check for a valid handler at 64? Isn't that the Jag programmer's responsibility?
700 if (JERRYIRQEnabled(IRQ2_DSP) && jaguar_interrupt_handler_is_valid(64))
702 JERRYSetPendingIRQ(IRQ2_DSP);
703 dsp_releaseTimeslice();
704 m68k_set_irq(7); // Set 68000 NMI...
708 // Check for CPU -> DSP interrupt
711 // WriteLog("DSP: CPU -> DSP interrupt\n");
712 m68k_end_timeslice();
713 gpu_releaseTimeslice();
714 DSPSetIRQLine(DSPIRQ_CPU, ASSERT_LINE);
718 if (data & SINGLE_STEP)
720 // WriteLog("DSP: Asked to perform a single step (single step is %senabled)\n", (data & 0x8 ? "" : "not "));
723 // Protect writes to VERSION and the interrupt latches...
724 uint32 mask = VERSION | INT_LAT0 | INT_LAT1 | INT_LAT2 | INT_LAT3 | INT_LAT4 | INT_LAT5;
725 dsp_control = (dsp_control & mask) | (data & ~mask);
727 // if dsp wasn't running but is now running
728 // execute a few cycles
729 //This is just plain wrong, wrong, WRONG!
730 #ifndef DSP_SINGLE_STEPPING
731 /* if (!dsp_was_running && DSP_RUNNING)
736 //This is WRONG! !!! FIX !!!
737 if (dsp_control & 0x18)
741 WriteLog("Write to DSP CTRL: %08X ", data);
743 WriteLog(" --> Starting to run at %08X by %s...", dsp_pc, whoName[who]);
745 WriteLog(" --> Stopped by %s! (DSP PC: %08X)", whoName[who], dsp_pc);
748 //This isn't exactly right either--we don't know if it was the M68K or the GPU writing here...
751 m68k_end_timeslice();
758 dsp_div_control = data;
760 // default: // unaligned long read
766 //We don't have to break this up like this! We CAN do 32 bit writes!
767 // JaguarWriteWord(offset, (data>>16) & 0xFFFF, DSP);
768 // JaguarWriteWord(offset+2, data & 0xFFFF, DSP);
769 JaguarWriteLong(offset, data, who);
773 // Update the DSP register file pointers depending on REGPAGE bit
775 void DSPUpdateRegisterBanks(void)
777 int bank = (dsp_flags & REGPAGE);
779 if (dsp_flags & IMASK)
780 bank = 0; // IMASK forces main bank to be bank 0
783 dsp_reg = dsp_reg_bank_1, dsp_alternate_reg = dsp_reg_bank_0;
785 dsp_reg = dsp_reg_bank_0, dsp_alternate_reg = dsp_reg_bank_1;
789 // Check for an handle any asserted DSP IRQs
791 void DSPHandleIRQs(void)
793 if (dsp_flags & IMASK) // Bail if we're already inside an interrupt
796 // Get the active interrupt bits (latches) & interrupt mask (enables)
797 uint32 bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
798 mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
800 // WriteLog("dsp: bits=%.2x mask=%.2x\n",bits,mask);
803 if (!bits) // Bail if nothing is enabled
806 int which = 0; // Determine which interrupt
821 WriteLog("DSP: Generating interrupt #%i...\n", which);
825 DSPUpdateRegisterBanks();
827 // subqt #4,r31 ; pre-decrement stack pointer
828 // move pc,r30 ; address of interrupted code
829 // store r30,(r31) ; store return address
831 DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
833 // movei #service_address,r30 ; pointer to ISR entry
834 // jump (r30) ; jump to ISR
836 dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
840 // Set the specified DSP IRQ line to a given state
842 void DSPSetIRQLine(int irqline, int state)
844 //NOTE: This doesn't take INT_LAT5 into account. !!! FIX !!!
845 uint32 mask = INT_LAT0 << irqline;
846 dsp_control &= ~mask; // Clear the latch bit
850 dsp_control |= mask; // Set the latch bit
857 memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
858 memory_malloc_secure((void **)&dsp_reg_bank_0, 32 * sizeof(int32), "DSP bank 0 regs");
859 memory_malloc_secure((void **)&dsp_reg_bank_1, 32 * sizeof(int32), "DSP bank 1 regs");
861 dsp_build_branch_condition_table();
868 dsp_acc = 0x00000000;
869 dsp_remain = 0x00000000;
870 dsp_modulo = 0xFFFFFFFF;
871 dsp_flags = 0x00040000;
872 dsp_matrix_control = 0x00000000;
873 dsp_pointer_to_matrix = 0x00000000;
874 dsp_data_organization = 0xFFFFFFFF;
875 dsp_control = 0x00002000; // Report DSP version 2
876 dsp_div_control = 0x00000000;
879 dsp_reg = dsp_reg_bank_0;
880 dsp_alternate_reg = dsp_reg_bank_1;
882 for(int i=0; i<32; i++)
883 dsp_reg[i] = dsp_alternate_reg[i] = 0x00000000;
888 memset(dsp_ram_8, 0xFF, 0x2000);
891 void DSPDumpDisassembly(void)
895 WriteLog("\n---[DSP code at 00F1B000]---------------------------\n");
897 while (j <= 0xF1CFFF)
900 j += dasmjag(JAGUAR_DSP, buffer, j);
901 WriteLog("\t%08X: %s\n", oldj, buffer);
905 void DSPDumpRegisters(void)
907 //Shoud add modulus, etc to dump here...
908 WriteLog("\n---[DSP flags: NCZ %d%d%d, DSP PC: %08X]------------\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_pc);
909 WriteLog("\nRegisters bank 0\n");
910 for(int j=0; j<8; j++)
912 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
913 (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
914 (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
915 (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
916 (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
918 WriteLog("Registers bank 1\n");
919 for(int j=0; j<8; j++)
921 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
922 (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
923 (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
924 (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
925 (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
932 WriteLog("DSP: Stopped at PC=%08X dsp_modulo=%08X (dsp %s running)\n", dsp_pc, dsp_modulo, (DSP_RUNNING ? "was" : "wasn't"));
933 WriteLog("DSP: %sin interrupt handler\n", (dsp_flags & IMASK ? "" : "not "));
935 // get the active interrupt bits
936 int bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F);
937 // get the interrupt mask
938 int mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
940 WriteLog("DSP: pending=%08X enabled=%08X\n", bits, mask);
941 WriteLog("\nRegisters bank 0\n");
942 for(int j=0; j<8; j++)
944 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
945 (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
946 (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
947 (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
948 (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
950 WriteLog("\nRegisters bank 1\n");
953 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
954 (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
955 (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
956 (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
957 (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
961 static char buffer[512];
962 j = DSP_WORK_RAM_BASE;
963 while (j <= 0xF1BFFF)
966 j += dasmjag(JAGUAR_DSP, buffer, j);
967 WriteLog("\t%08X: %s\n", oldj, buffer);
970 WriteLog("DSP opcodes use:\n");
973 if (dsp_opcode_use[i])
974 WriteLog("\t%s %i\n", dsp_opcode_str[i], dsp_opcode_use[i]);
977 memory_free(dsp_ram_8);
981 // DSP execution core
983 static bool R20Set = false, tripwire = false;
984 static uint32 pcQueue[32], ptrPCQ = 0;
985 void DSPExec(int32 cycles)
987 /*HACKS!!! -> if (cycles != 1 && jaguar_mainRom_crc32 == 0xba74c3ed)
988 dsp_check_if_i2s_interrupt_needed();*/
990 #ifdef DSP_SINGLE_STEPPING
991 if (dsp_control & 0x18)
994 dsp_control &= ~0x10;
997 //There is *no* good reason to do this here!
999 dsp_releaseTimeSlice_flag = 0;
1002 while (cycles > 0 && DSP_RUNNING)
1004 if (dsp_pc == 0xF1B5D8)
1006 WriteLog("DSP: At $F1B4D8--R15 = %08X at %u ms%s...\n", dsp_reg[15], SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1008 /*if (dsp_pc == 0xF1B7D2) // Start here???
1010 pcQueue[ptrPCQ++] = dsp_pc;
1012 uint16 opcode = DSPReadWord(dsp_pc, DSP);
1013 uint32 index = opcode >> 10;
1014 dsp_opcode_first_parameter = (opcode >> 5) & 0x1F;
1015 dsp_opcode_second_parameter = opcode & 0x1F;
1017 dsp_opcode[index]();
1018 dsp_opcode_use[index]++;
1019 cycles -= dsp_opcode_cycles[index];
1020 /*if (dsp_reg_bank_0[20] == 0xF1A100 & !R20Set)
1022 WriteLog("DSP: R20 set to $F1A100 at %u ms%s...\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1025 if (dsp_reg_bank_0[20] != 0xF1A100 && R20Set)
1027 WriteLog("DSP: R20 corrupted at %u ms from starting%s!\nAborting!\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1029 DSPDumpDisassembly();
1032 if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFE) && !tripwire)
1035 WriteLog("DSP: Jumping outside of DSP RAM at %u ms. Register dump:\n", SDL_GetTicks());
1038 WriteLog("\nBacktrace:\n");
1039 for(int i=0; i<32; i++)
1041 dasmjag(JAGUAR_DSP, buffer, pcQueue[(ptrPCQ + i) % 32]);
1042 WriteLog("\t%08X: %s\n", pcQueue[(ptrPCQ + i) % 32], buffer);
1052 // DSP opcode handlers
1055 // There is a problem here with interrupt handlers the JUMP and JR instructions that
1056 // can cause trouble because an interrupt can occur *before* the instruction following the
1057 // jump can execute... !!! FIX !!!
1058 static void dsp_opcode_jump(void)
1061 char * condition[32] =
1062 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1063 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1064 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1065 "???", "???", "???", "F" };
1067 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);
1070 /* dsp_flag_c=dsp_flag_c?1:0;
1071 dsp_flag_z=dsp_flag_z?1:0;
1072 dsp_flag_n=dsp_flag_n?1:0;*/
1073 // KLUDGE: Used by BRANCH_CONDITION
1074 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1076 if (BRANCH_CONDITION(IMM_2))
1080 WriteLog("Branched!\n");
1082 uint32 delayed_pc = RM;
1084 dsp_pc = delayed_pc;
1089 WriteLog("Branch NOT taken.\n");
1093 static void dsp_opcode_jr(void)
1096 char * condition[32] =
1097 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1098 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1099 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1100 "???", "???", "???", "F" };
1102 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);
1105 /* dsp_flag_c=dsp_flag_c?1:0;
1106 dsp_flag_z=dsp_flag_z?1:0;
1107 dsp_flag_n=dsp_flag_n?1:0;*/
1108 // KLUDGE: Used by BRANCH_CONDITION
1109 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1111 if (BRANCH_CONDITION(IMM_2))
1115 WriteLog("Branched!\n");
1117 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1118 int32 delayed_pc = dsp_pc + (offset * 2);
1120 dsp_pc = delayed_pc;
1125 WriteLog("Branch NOT taken.\n");
1129 static void dsp_opcode_add(void)
1133 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);
1135 UINT32 res = RN + RM;
1136 SET_ZNC_ADD(RN, RM, res);
1140 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);
1144 static void dsp_opcode_addc(void)
1148 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);
1150 UINT32 res = RN + RM + dsp_flag_c;
1151 UINT32 carry = dsp_flag_c;
1152 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1153 SET_ZNC_ADD(RN + carry, RM, res);
1154 // SET_ZNC_ADD(RN, RM + carry, res);
1158 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);
1162 static void dsp_opcode_addq(void)
1166 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);
1168 UINT32 r1 = dsp_convert_zero[IMM_1];
1169 UINT32 res = RN + r1;
1170 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1174 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1178 static void dsp_opcode_sub(void)
1182 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);
1184 UINT32 res = RN - RM;
1185 SET_ZNC_SUB(RN, RM, res);
1189 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);
1193 static void dsp_opcode_subc(void)
1197 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);
1199 UINT32 res = RN - RM - dsp_flag_c;
1200 UINT32 borrow = dsp_flag_c;
1201 SET_ZNC_SUB(RN - borrow, RM, res);
1205 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);
1209 static void dsp_opcode_subq(void)
1213 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);
1215 UINT32 r1 = dsp_convert_zero[IMM_1];
1216 UINT32 res = RN - r1;
1217 SET_ZNC_SUB(RN, r1, res);
1221 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1225 static void dsp_opcode_cmp(void)
1229 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);
1231 UINT32 res = RN - RM;
1232 SET_ZNC_SUB(RN, RM, res);
1235 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1239 static void dsp_opcode_cmpq(void)
1241 static int32 sqtable[32] =
1242 { 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 };
1245 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);
1247 UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1248 UINT32 res = RN - r1;
1249 SET_ZNC_SUB(RN, r1, res);
1252 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1256 static void dsp_opcode_and(void)
1260 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);
1266 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);
1270 static void dsp_opcode_or(void)
1274 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);
1280 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);
1284 static void dsp_opcode_xor(void)
1288 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);
1294 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);
1298 static void dsp_opcode_not(void)
1302 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);
1308 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);
1312 static void dsp_opcode_move_pc(void)
1317 static void dsp_opcode_store_r14_indexed(void)
1319 #ifdef DSP_DIS_STORE14I
1321 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));
1323 DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1326 static void dsp_opcode_store_r15_indexed(void)
1328 #ifdef DSP_DIS_STORE15I
1330 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));
1332 DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1335 static void dsp_opcode_load_r14_ri(void)
1337 #ifdef DSP_DIS_LOAD14R
1339 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);
1341 RN = DSPReadLong(dsp_reg[14] + RM, DSP);
1342 #ifdef DSP_DIS_LOAD14R
1344 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1348 static void dsp_opcode_load_r15_ri(void)
1350 #ifdef DSP_DIS_LOAD15R
1352 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);
1354 RN = DSPReadLong(dsp_reg[15] + RM, DSP);
1355 #ifdef DSP_DIS_LOAD15R
1357 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1361 static void dsp_opcode_store_r14_ri(void)
1363 DSPWriteLong(dsp_reg[14] + RM, RN, DSP);
1366 static void dsp_opcode_store_r15_ri(void)
1368 DSPWriteLong(dsp_reg[15] + RM, RN, DSP);
1371 static void dsp_opcode_nop(void)
1375 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", dsp_pc-2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
1379 static void dsp_opcode_storeb(void)
1381 #ifdef DSP_DIS_STOREB
1383 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);
1385 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1386 DSPWriteLong(RM, RN & 0xFF, DSP);
1388 JaguarWriteByte(RM, RN, DSP);
1391 static void dsp_opcode_storew(void)
1393 #ifdef DSP_DIS_STOREW
1395 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);
1397 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1398 DSPWriteLong(RM, RN & 0xFFFF, DSP);
1400 JaguarWriteWord(RM, RN, DSP);
1403 static void dsp_opcode_store(void)
1405 #ifdef DSP_DIS_STORE
1407 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);
1409 DSPWriteLong(RM, RN, DSP);
1412 static void dsp_opcode_loadb(void)
1414 #ifdef DSP_DIS_LOADB
1416 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);
1418 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1419 RN = DSPReadLong(RM, DSP) & 0xFF;
1421 RN = JaguarReadByte(RM, DSP);
1422 #ifdef DSP_DIS_LOADB
1424 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1428 static void dsp_opcode_loadw(void)
1430 #ifdef DSP_DIS_LOADW
1432 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);
1434 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1435 RN = DSPReadLong(RM, DSP) & 0xFFFF;
1437 RN = JaguarReadWord(RM, DSP);
1438 #ifdef DSP_DIS_LOADW
1440 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1444 static void dsp_opcode_load(void)
1448 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);
1450 RN = DSPReadLong(RM, DSP);
1453 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1457 static void dsp_opcode_load_r14_indexed(void)
1459 #ifdef DSP_DIS_LOAD14I
1461 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);
1463 RN = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), DSP);
1464 #ifdef DSP_DIS_LOAD14I
1466 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1470 static void dsp_opcode_load_r15_indexed(void)
1472 #ifdef DSP_DIS_LOAD15I
1474 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);
1476 RN = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), DSP);
1477 #ifdef DSP_DIS_LOAD15I
1479 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1483 static void dsp_opcode_movei(void)
1485 #ifdef DSP_DIS_MOVEI
1487 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);
1489 // This instruction is followed by 32-bit value in LSW / MSW format...
1490 RN = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
1492 #ifdef DSP_DIS_MOVEI
1494 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1498 static void dsp_opcode_moveta(void)
1500 #ifdef DSP_DIS_MOVETA
1502 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);
1505 #ifdef DSP_DIS_MOVETA
1507 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);
1511 static void dsp_opcode_movefa(void)
1513 #ifdef DSP_DIS_MOVEFA
1515 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);
1518 #ifdef DSP_DIS_MOVEFA
1520 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);
1524 static void dsp_opcode_move(void)
1528 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);
1533 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);
1537 static void dsp_opcode_moveq(void)
1539 #ifdef DSP_DIS_MOVEQ
1541 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);
1544 #ifdef DSP_DIS_MOVEQ
1546 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1550 static void dsp_opcode_resmac(void)
1552 #ifdef DSP_DIS_RESMAC
1554 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));
1556 RN = (uint32)dsp_acc;
1557 #ifdef DSP_DIS_RESMAC
1559 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1563 static void dsp_opcode_imult(void)
1565 #ifdef DSP_DIS_IMULT
1567 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);
1569 RN = (int16)RN * (int16)RM;
1571 #ifdef DSP_DIS_IMULT
1573 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);
1577 static void dsp_opcode_mult(void)
1581 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);
1583 RN = (uint16)RM * (uint16)RN;
1587 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);
1591 static void dsp_opcode_bclr(void)
1595 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);
1597 UINT32 res = RN & ~(1 << IMM_1);
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_btst(void)
1610 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);
1612 dsp_flag_z = (~RN >> IMM_1) & 1;
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_bset(void)
1623 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);
1625 UINT32 res = RN | (1 << IMM_1);
1630 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1634 static void dsp_opcode_subqt(void)
1636 #ifdef DSP_DIS_SUBQT
1638 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);
1640 RN -= dsp_convert_zero[IMM_1];
1641 #ifdef DSP_DIS_SUBQT
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_addqt(void)
1649 #ifdef DSP_DIS_ADDQT
1651 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);
1653 RN += dsp_convert_zero[IMM_1];
1654 #ifdef DSP_DIS_ADDQT
1656 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1660 static void dsp_opcode_imacn(void)
1662 #ifdef DSP_DIS_IMACN
1664 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);
1666 int32 res = (int16)RM * (int16)RN;
1667 dsp_acc += (int64)res;
1668 //Should we AND the result to fit into 40 bits here???
1669 #ifdef DSP_DIS_IMACN
1671 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));
1675 static void dsp_opcode_mtoi(void)
1677 RN = (((INT32)RM >> 8) & 0xFF800000) | (RM & 0x007FFFFF);
1681 static void dsp_opcode_normi(void)
1688 while ((_Rm & 0xffc00000) == 0)
1693 while ((_Rm & 0xff800000) != 0)
1703 static void dsp_opcode_mmult(void)
1705 int count = dsp_matrix_control&0x0f;
1706 uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
1710 if (!(dsp_matrix_control & 0x10))
1712 for (int i = 0; i < count; i++)
1716 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1718 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1719 int16 b=((int16)DSPReadWord(addr + 2, DSP));
1726 for (int i = 0; i < count; i++)
1730 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1732 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1733 int16 b=((int16)DSPReadWord(addr + 2, DSP));
1738 RN = res = (int32)accum;
1740 //NOTE: The flags are set based upon the last add/multiply done...
1744 static void dsp_opcode_abs(void)
1749 if (_Rn == 0x80000000)
1753 dsp_flag_c = ((_Rn & 0x80000000) >> 31);
1754 res = RN = (_Rn & 0x80000000 ? -_Rn : _Rn);
1759 static void dsp_opcode_div(void)
1766 if (dsp_div_control & 1)
1768 dsp_remain = (((uint64)_Rn) << 16) % _Rm;
1769 if (dsp_remain&0x80000000)
1771 RN = (((uint64)_Rn) << 16) / _Rm;
1775 dsp_remain = _Rn % _Rm;
1776 if (dsp_remain&0x80000000)
1785 static void dsp_opcode_imultn(void)
1787 #ifdef DSP_DIS_IMULTN
1789 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);
1791 // This is OK, since this multiply won't overflow 32 bits...
1792 int32 res = (int32)((int16)RN * (int16)RM);
1793 dsp_acc = (int64)res;
1795 #ifdef DSP_DIS_IMULTN
1797 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));
1801 static void dsp_opcode_neg(void)
1805 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);
1808 SET_ZNC_SUB(0, RN, res);
1812 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1816 static void dsp_opcode_shlq(void)
1820 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);
1822 INT32 r1 = 32 - IMM_1;
1823 UINT32 res = RN << r1;
1824 SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
1828 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1832 static void dsp_opcode_shrq(void)
1836 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);
1838 INT32 r1 = dsp_convert_zero[IMM_1];
1839 UINT32 res = RN >> r1;
1840 SET_ZN(res); dsp_flag_c = RN & 1;
1844 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1848 static void dsp_opcode_ror(void)
1852 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);
1854 UINT32 r1 = RM & 0x1F;
1855 UINT32 res = (RN >> r1) | (RN << (32 - r1));
1856 SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
1860 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);
1864 static void dsp_opcode_rorq(void)
1868 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);
1870 UINT32 r1 = dsp_convert_zero[IMM_1 & 0x1F];
1872 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
1874 SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
1877 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1881 static void dsp_opcode_sha(void)
1883 int32 sRm=(int32)RM;
1889 if (shift>=32) shift=32;
1890 dsp_flag_c=(_Rn&0x80000000)>>31;
1900 if (shift>=32) shift=32;
1904 _Rn=((int32)_Rn)>>1;
1912 static void dsp_opcode_sharq(void)
1914 #ifdef DSP_DIS_SHARQ
1916 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);
1918 UINT32 res = (INT32)RN >> dsp_convert_zero[IMM_1];
1919 SET_ZN(res); dsp_flag_c = RN & 0x01;
1921 #ifdef DSP_DIS_SHARQ
1923 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1927 static void dsp_opcode_sh(void)
1929 int32 sRm=(int32)RM;
1934 uint32 shift=(-sRm);
1935 if (shift>=32) shift=32;
1936 dsp_flag_c=(_Rn&0x80000000)>>31;
1946 if (shift>=32) shift=32;
1958 void dsp_opcode_addqmod(void)
1960 #ifdef DSP_DIS_ADDQMOD
1962 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);
1964 UINT32 r1 = dsp_convert_zero[IMM_1];
1966 UINT32 res = r2 + r1;
1967 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
1969 SET_ZNC_ADD(r2, r1, res);
1970 #ifdef DSP_DIS_ADDQMOD
1972 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1976 void dsp_opcode_subqmod(void)
1978 UINT32 r1 = dsp_convert_zero[IMM_1];
1980 UINT32 res = r2 - r1;
1981 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
1984 SET_ZNC_SUB(r2, r1, res);
1987 void dsp_opcode_mirror(void)
1990 RN = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
1994 void dsp_opcode_sat32s(void)
1996 INT32 r2 = (UINT32)RN;
1997 INT32 temp = dsp_acc >> 32;
1998 UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
2003 void dsp_opcode_sat16s(void)
2006 UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;