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*/)
406 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
407 WriteLog("DSP: ReadByte--Attempt to read from DSP register file by %s!\n", whoName[who]);
409 // if ((offset==0xF1CFE0)||(offset==0xF1CFE2))
412 /* if ((jaguar_mainRom_crc32==0xbfd751a4)||(jaguar_mainRom_crc32==0x053efaf9))
414 if (offset==0xF1CFE0)
417 if (offset >= DSP_WORK_RAM_BASE && offset <= (DSP_WORK_RAM_BASE + 0x1FFF))
418 return dsp_ram_8[offset - DSP_WORK_RAM_BASE];
420 if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
422 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
424 if ((offset&0x03)==0)
427 if ((offset&0x03)==1)
428 return((data>>16)&0xff);
430 if ((offset&0x03)==2)
431 return((data>>8)&0xff);
433 if ((offset&0x03)==3)
437 return JaguarReadByte(offset, who);
440 uint16 DSPReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
442 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
443 WriteLog("DSP: ReadWord--Attempt to read from DSP register file by %s!\n", whoName[who]);
445 offset &= 0xFFFFFFFE;
447 /* if (jaguar_mainRom_crc32==0xa74a97cd)
449 if (offset==0xF1A114) return(0x0000);
450 if (offset==0xF1A116) return(0x0000);
451 if (offset==0xF1B000) return(0x1234);
452 if (offset==0xF1B002) return(0x5678);
455 if (jaguar_mainRom_crc32==0x7ae20823)
457 if (offset==0xF1B9D8) return(0x0000);
458 if (offset==0xF1B9Da) return(0x0000);
459 if (offset==0xF1B2C0) return(0x0000);
460 if (offset==0xF1B2C2) return(0x0000);
463 // pour permettre à wolfenstein 3d de tourner sans le dsp
464 /* if ((offset==0xF1B0D0)||(offset==0xF1B0D2))
468 // pour permettre à nba jam de tourner sans le dsp
469 /* if (jaguar_mainRom_crc32==0x4faddb18)
471 if (offset==0xf1b2c0) return(0);
472 if (offset==0xf1b2c2) return(0);
473 if (offset==0xf1b240) return(0);
474 if (offset==0xf1b242) return(0);
475 if (offset==0xF1B340) return(0);
476 if (offset==0xF1B342) return(0);
477 if (offset==0xF1BAD8) return(0);
478 if (offset==0xF1BADA) return(0);
479 if (offset==0xF1B040) return(0);
480 if (offset==0xF1B042) return(0);
481 if (offset==0xF1B0C0) return(0);
482 if (offset==0xF1B0C2) return(0);
483 if (offset==0xF1B140) return(0);
484 if (offset==0xF1B142) return(0);
485 if (offset==0xF1B1C0) return(0);
486 if (offset==0xF1B1C2) return(0);
489 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE+0x1FFF)
491 offset -= DSP_WORK_RAM_BASE;
492 /* uint16 data = (((uint16)dsp_ram_8[offset])<<8)|((uint16)dsp_ram_8[offset+1]);
494 return GET16(dsp_ram_8, offset);
496 else if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
498 uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
501 return data & 0xFFFF;
506 return JaguarReadWord(offset, who);
509 uint32 DSPReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
511 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
512 WriteLog("DSP: ReadLong--Attempt to read from DSP register file by %s!\n", whoName[who]);
515 offset &= 0xFFFFFFFC;
516 /*if (offset == 0xF1BCF4)
518 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));
519 DSPDumpDisassembly();
521 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
523 offset -= DSP_WORK_RAM_BASE;
524 return GET32(dsp_ram_8, offset);
526 //NOTE: Didn't return DSP_ACCUM!!!
527 //Mebbe it's not 'spose to! Yes, it is!
528 if (offset >= DSP_CONTROL_RAM_BASE && offset <= DSP_CONTROL_RAM_BASE + 0x23)
533 case 0x00: /*dsp_flag_c?(dsp_flag_c=1):(dsp_flag_c=0);
534 dsp_flag_z?(dsp_flag_z=1):(dsp_flag_z=0);
535 dsp_flag_n?(dsp_flag_n=1):(dsp_flag_n=0);*/
537 dsp_flags = (dsp_flags & 0xFFFFFFF8) | (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
538 return dsp_flags & 0xFFFFC1FF;
539 case 0x04: return dsp_matrix_control;
540 case 0x08: return dsp_pointer_to_matrix;
541 case 0x0C: return dsp_data_organization;
542 case 0x10: return dsp_pc;
543 case 0x14: return dsp_control;
544 case 0x18: return dsp_modulo;
545 case 0x1C: return dsp_remain;
547 return (int32)((int8)(dsp_acc >> 32)); // Top 8 bits of 40-bit accumulator, sign extended
549 // unaligned long read-- !!! FIX !!!
553 return JaguarReadLong(offset, who);
556 void DSPWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
558 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
559 WriteLog("DSP: WriteByte--Attempt to write to DSP register file by %s!\n", whoName[who]);
561 if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
563 offset -= DSP_WORK_RAM_BASE;
564 dsp_ram_8[offset] = data;
565 //This is rather stupid! !!! FIX !!!
566 /* if (dsp_in_exec == 0)
568 m68k_end_timeslice();
569 gpu_releaseTimeslice();
573 if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
575 uint32 reg = offset & 0x1C;
576 int bytenum = offset & 0x03;
578 if ((reg >= 0x1C) && (reg <= 0x1F))
579 dsp_div_control = (dsp_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
582 //This looks funky. !!! FIX !!!
583 uint32 old_data = DSPReadLong(offset&0xFFFFFFC, who);
584 bytenum = 3 - bytenum; // convention motorola !!!
585 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
586 DSPWriteLong(offset & 0xFFFFFFC, old_data, who);
590 // WriteLog("dsp: writing %.2x at 0x%.8x\n",data,offset);
591 //Should this *ever* happen??? Shouldn't we be saying "unknown" here???
592 JaguarWriteByte(offset, data, who);
595 void DSPWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
597 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
598 WriteLog("DSP: WriteWord--Attempt to write to DSP register file by %s!\n", whoName[who]);
599 offset &= 0xFFFFFFFE;
600 /*if (offset == 0xF1BCF4)
602 WriteLog("DSPWriteWord: Writing to 0xF1BCF4... %04X -> %04X\n", GET16(dsp_ram_8, 0x0CF4), data);
604 // WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset);
605 if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
607 offset -= DSP_WORK_RAM_BASE;
608 dsp_ram_8[offset] = data >> 8;
609 dsp_ram_8[offset+1] = data & 0xFF;
610 //This is rather stupid! !!! FIX !!!
611 /* if (dsp_in_exec == 0)
613 // WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset+DSP_WORK_RAM_BASE);
614 m68k_end_timeslice();
615 gpu_releaseTimeslice();
619 else if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
621 if ((offset & 0x1C) == 0x1C)
624 dsp_div_control = (dsp_div_control&0xffff0000)|(data&0xffff);
626 dsp_div_control = (dsp_div_control&0xffff)|((data&0xffff)<<16);
630 uint32 old_data = DSPReadLong(offset & 0xffffffc, who);
632 old_data = (old_data&0xffff0000)|(data&0xffff);
634 old_data = (old_data&0xffff)|((data&0xffff)<<16);
635 DSPWriteLong(offset & 0xffffffc, old_data, who);
640 JaguarWriteWord(offset, data, who);
643 //bool badWrite = false;
644 void DSPWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
646 if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
647 WriteLog("DSP: WriteLong--Attempt to write to DSP register file by %s!\n", whoName[who]);
649 offset &= 0xFFFFFFFC;
650 /*if (offset == 0xF1BCF4)
652 WriteLog("DSPWriteLong: Writing to 0xF1BCF4... %08X -> %08X\n", GET32(dsp_ram_8, 0x0CF4), data);
654 // WriteLog("dsp: writing %.8x at 0x%.8x\n",data,offset);
655 if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
657 /*if (offset == 0xF1BE2C)
659 WriteLog("DSP: %s is writing %08X at location 0xF1BE2C (DSP_PC: %08X)...\n", whoName[who], data, dsp_pc - 2);
661 offset -= DSP_WORK_RAM_BASE;
662 SET32(dsp_ram_8, offset, data);
665 else if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
672 bool IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
674 dsp_flag_z = dsp_flags & 0x01;
675 dsp_flag_c = (dsp_flags >> 1) & 0x01;
676 dsp_flag_n = (dsp_flags >> 2) & 0x01;
677 DSPUpdateRegisterBanks();
678 dsp_control &= ~((dsp_flags & CINT04FLAGS) >> 3);
679 dsp_control &= ~((dsp_flags & CINT5FLAG) >> 1);
680 if (IMASKCleared) // If IMASK was cleared,
683 WriteLog("DSP: Finished interrupt.\n");
685 DSPHandleIRQs(); // see if any other interrupts need servicing!
692 dsp_matrix_control = data;
695 // According to JTRM, only lines 2-11 are adressable, the rest being
696 // hardwired to $F1Bxxx.
697 dsp_pointer_to_matrix = 0xF1B000 | (data & 0x000FFC);
700 dsp_data_organization = data;
705 WriteLog("DSP: Setting DSP PC to %08X by %s%s\n", dsp_pc, whoName[who], (DSP_RUNNING ? " (DSP is RUNNING!)" : ""));//*/
710 // uint32 dsp_was_running = DSP_RUNNING;
711 // Check for DSP -> CPU interrupt
714 // WriteLog("DSP: DSP -> CPU interrupt\n");
716 // Why do we check for a valid handler at 64? Isn't that the Jag programmer's responsibility?
717 if (JERRYIRQEnabled(IRQ2_DSP) && jaguar_interrupt_handler_is_valid(64))
719 JERRYSetPendingIRQ(IRQ2_DSP);
720 dsp_releaseTimeslice();
721 m68k_set_irq(7); // Set 68000 NMI...
725 // Check for CPU -> DSP interrupt
728 WriteLog("DSP: CPU -> DSP interrupt\n");
729 m68k_end_timeslice();
730 gpu_releaseTimeslice();
731 DSPSetIRQLine(DSPIRQ_CPU, ASSERT_LINE);
735 if (data & SINGLE_STEP)
737 // WriteLog("DSP: Asked to perform a single step (single step is %senabled)\n", (data & 0x8 ? "" : "not "));
740 // Protect writes to VERSION and the interrupt latches...
741 uint32 mask = VERSION | INT_LAT0 | INT_LAT1 | INT_LAT2 | INT_LAT3 | INT_LAT4 | INT_LAT5;
742 dsp_control = (dsp_control & mask) | (data & ~mask);
744 // if dsp wasn't running but is now running
745 // execute a few cycles
746 //This is just plain wrong, wrong, WRONG!
747 #ifndef DSP_SINGLE_STEPPING
748 /* if (!dsp_was_running && DSP_RUNNING)
753 //This is WRONG! !!! FIX !!!
754 if (dsp_control & 0x18)
758 WriteLog("Write to DSP CTRL: %08X ", data);
760 WriteLog(" --> Starting to run at %08X by %s...", dsp_pc, whoName[who]);
762 WriteLog(" --> Stopped by %s! (DSP PC: %08X)", whoName[who], dsp_pc);
765 //This isn't exactly right either--we don't know if it was the M68K or the GPU writing here...
768 m68k_end_timeslice();
775 dsp_div_control = data;
777 // default: // unaligned long read
783 //We don't have to break this up like this! We CAN do 32 bit writes!
784 // JaguarWriteWord(offset, (data>>16) & 0xFFFF, DSP);
785 // JaguarWriteWord(offset+2, data & 0xFFFF, DSP);
786 //if (offset > 0xF1FFFF)
788 JaguarWriteLong(offset, data, who);
792 // Update the DSP register file pointers depending on REGPAGE bit
794 void DSPUpdateRegisterBanks(void)
796 int bank = (dsp_flags & REGPAGE);
798 if (dsp_flags & IMASK)
799 bank = 0; // IMASK forces main bank to be bank 0
802 dsp_reg = dsp_reg_bank_1, dsp_alternate_reg = dsp_reg_bank_0;
804 dsp_reg = dsp_reg_bank_0, dsp_alternate_reg = dsp_reg_bank_1;
808 // Check for an handle any asserted DSP IRQs
810 void DSPHandleIRQs(void)
812 if (dsp_flags & IMASK) // Bail if we're already inside an interrupt
815 // Get the active interrupt bits (latches) & interrupt mask (enables)
816 uint32 bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
817 mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
819 // WriteLog("dsp: bits=%.2x mask=%.2x\n",bits,mask);
822 if (!bits) // Bail if nothing is enabled
825 int which = 0; // Determine which interrupt
840 WriteLog("DSP: Generating interrupt #%i...\n", which);
844 DSPUpdateRegisterBanks();
846 // subqt #4,r31 ; pre-decrement stack pointer
847 // move pc,r30 ; address of interrupted code
848 // store r30,(r31) ; store return address
850 DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
852 // movei #service_address,r30 ; pointer to ISR entry
853 // jump (r30) ; jump to ISR
855 dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
859 // Set the specified DSP IRQ line to a given state
861 void DSPSetIRQLine(int irqline, int state)
863 //NOTE: This doesn't take INT_LAT5 into account. !!! FIX !!!
864 uint32 mask = INT_LAT0 << irqline;
865 dsp_control &= ~mask; // Clear the latch bit
869 dsp_control |= mask; // Set the latch bit
876 memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
877 memory_malloc_secure((void **)&dsp_reg_bank_0, 32 * sizeof(int32), "DSP bank 0 regs");
878 memory_malloc_secure((void **)&dsp_reg_bank_1, 32 * sizeof(int32), "DSP bank 1 regs");
880 dsp_build_branch_condition_table();
887 dsp_acc = 0x00000000;
888 dsp_remain = 0x00000000;
889 dsp_modulo = 0xFFFFFFFF;
890 dsp_flags = 0x00040000;
891 dsp_matrix_control = 0x00000000;
892 dsp_pointer_to_matrix = 0x00000000;
893 dsp_data_organization = 0xFFFFFFFF;
894 dsp_control = 0x00002000; // Report DSP version 2
895 dsp_div_control = 0x00000000;
898 dsp_reg = dsp_reg_bank_0;
899 dsp_alternate_reg = dsp_reg_bank_1;
901 for(int i=0; i<32; i++)
902 dsp_reg[i] = dsp_alternate_reg[i] = 0x00000000;
907 memset(dsp_ram_8, 0xFF, 0x2000);
910 void DSPDumpDisassembly(void)
914 WriteLog("\n---[DSP code at 00F1B000]---------------------------\n");
916 while (j <= 0xF1CFFF)
919 j += dasmjag(JAGUAR_DSP, buffer, j);
920 WriteLog("\t%08X: %s\n", oldj, buffer);
924 void DSPDumpRegisters(void)
926 //Shoud add modulus, etc to dump here...
927 WriteLog("\n---[DSP flags: NCZ %d%d%d, DSP PC: %08X]------------\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_pc);
928 WriteLog("\nRegisters bank 0\n");
929 for(int j=0; j<8; j++)
931 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
932 (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
933 (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
934 (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
935 (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
937 WriteLog("Registers bank 1\n");
938 for(int j=0; j<8; j++)
940 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
941 (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
942 (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
943 (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
944 (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
951 WriteLog("DSP: Stopped at PC=%08X dsp_modulo=%08X (dsp %s running)\n", dsp_pc, dsp_modulo, (DSP_RUNNING ? "was" : "wasn't"));
952 WriteLog("DSP: %sin interrupt handler\n", (dsp_flags & IMASK ? "" : "not "));
954 // get the active interrupt bits
955 int bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F);
956 // get the interrupt mask
957 int mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
959 WriteLog("DSP: pending=%08X enabled=%08X\n", bits, mask);
960 WriteLog("\nRegisters bank 0\n");
961 for(int j=0; j<8; j++)
963 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
964 (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
965 (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
966 (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
967 (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
969 WriteLog("\nRegisters bank 1\n");
972 WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
973 (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
974 (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
975 (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
976 (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
980 static char buffer[512];
981 j = DSP_WORK_RAM_BASE;
982 while (j <= 0xF1BFFF)
985 j += dasmjag(JAGUAR_DSP, buffer, j);
986 WriteLog("\t%08X: %s\n", oldj, buffer);
989 WriteLog("DSP opcodes use:\n");
992 if (dsp_opcode_use[i])
993 WriteLog("\t%s %i\n", dsp_opcode_str[i], dsp_opcode_use[i]);
996 memory_free(dsp_ram_8);
1000 // DSP execution core
1002 static bool R20Set = false, tripwire = false;
1003 static uint32 pcQueue[32], ptrPCQ = 0;
1004 void DSPExec(int32 cycles)
1006 /*HACKS!!! -> if (cycles != 1 && jaguar_mainRom_crc32 == 0xba74c3ed)
1007 dsp_check_if_i2s_interrupt_needed();*/
1009 #ifdef DSP_SINGLE_STEPPING
1010 if (dsp_control & 0x18)
1013 dsp_control &= ~0x10;
1016 //There is *no* good reason to do this here!
1018 dsp_releaseTimeSlice_flag = 0;
1021 while (cycles > 0 && DSP_RUNNING)
1025 WriteLog("\nDSP: Encountered bad write in Atari Synth module. PC=%08X, R15=%08X\n", dsp_pc, dsp_reg[15]);
1026 for(int i=0; i<80; i+=4)
1027 WriteLog(" %08X: %08X\n", dsp_reg[15]+i, JaguarReadLong(dsp_reg[15]+i));
1030 /*if (dsp_pc == 0xF1B55E)
1032 WriteLog("DSP: At $F1B55E--R15 = %08X at %u ms%s...\n", dsp_reg[15], SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1034 /*if (dsp_pc == 0xF1B7D2) // Start here???
1036 pcQueue[ptrPCQ++] = dsp_pc;
1038 uint16 opcode = DSPReadWord(dsp_pc, DSP);
1039 uint32 index = opcode >> 10;
1040 dsp_opcode_first_parameter = (opcode >> 5) & 0x1F;
1041 dsp_opcode_second_parameter = opcode & 0x1F;
1043 dsp_opcode[index]();
1044 dsp_opcode_use[index]++;
1045 cycles -= dsp_opcode_cycles[index];
1046 /*if (dsp_reg_bank_0[20] == 0xF1A100 & !R20Set)
1048 WriteLog("DSP: R20 set to $F1A100 at %u ms%s...\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1051 if (dsp_reg_bank_0[20] != 0xF1A100 && R20Set)
1053 WriteLog("DSP: R20 corrupted at %u ms from starting%s!\nAborting!\n", SDL_GetTicks(), (dsp_flags & IMASK ? " (inside interrupt)" : ""));
1055 DSPDumpDisassembly();
1058 if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFE) && !tripwire)
1061 WriteLog("DSP: Jumping outside of DSP RAM at %u ms. Register dump:\n", SDL_GetTicks());
1064 WriteLog("\nBacktrace:\n");
1065 for(int i=0; i<32; i++)
1067 dasmjag(JAGUAR_DSP, buffer, pcQueue[(ptrPCQ + i) % 32]);
1068 WriteLog("\t%08X: %s\n", pcQueue[(ptrPCQ + i) % 32], buffer);
1078 // DSP opcode handlers
1081 // There is a problem here with interrupt handlers the JUMP and JR instructions that
1082 // can cause trouble because an interrupt can occur *before* the instruction following the
1083 // jump can execute... !!! FIX !!!
1084 static void dsp_opcode_jump(void)
1087 char * condition[32] =
1088 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1089 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1090 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1091 "???", "???", "???", "F" };
1093 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);
1096 /* dsp_flag_c=dsp_flag_c?1:0;
1097 dsp_flag_z=dsp_flag_z?1:0;
1098 dsp_flag_n=dsp_flag_n?1:0;*/
1099 // KLUDGE: Used by BRANCH_CONDITION
1100 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1102 if (BRANCH_CONDITION(IMM_2))
1106 WriteLog("Branched!\n");
1108 uint32 delayed_pc = RM;
1110 dsp_pc = delayed_pc;
1115 WriteLog("Branch NOT taken.\n");
1119 static void dsp_opcode_jr(void)
1122 char * condition[32] =
1123 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1124 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1125 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1126 "???", "???", "???", "F" };
1128 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);
1131 /* dsp_flag_c=dsp_flag_c?1:0;
1132 dsp_flag_z=dsp_flag_z?1:0;
1133 dsp_flag_n=dsp_flag_n?1:0;*/
1134 // KLUDGE: Used by BRANCH_CONDITION
1135 uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
1137 if (BRANCH_CONDITION(IMM_2))
1141 WriteLog("Branched!\n");
1143 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1144 int32 delayed_pc = dsp_pc + (offset * 2);
1146 dsp_pc = delayed_pc;
1151 WriteLog("Branch NOT taken.\n");
1155 static void dsp_opcode_add(void)
1159 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);
1161 UINT32 res = RN + RM;
1162 SET_ZNC_ADD(RN, RM, res);
1166 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);
1170 static void dsp_opcode_addc(void)
1174 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);
1176 UINT32 res = RN + RM + dsp_flag_c;
1177 UINT32 carry = dsp_flag_c;
1178 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1179 SET_ZNC_ADD(RN + carry, RM, res);
1180 // SET_ZNC_ADD(RN, RM + carry, res);
1184 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);
1188 static void dsp_opcode_addq(void)
1192 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);
1194 UINT32 r1 = dsp_convert_zero[IMM_1];
1195 UINT32 res = RN + r1;
1196 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1200 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1204 static void dsp_opcode_sub(void)
1208 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);
1210 UINT32 res = RN - RM;
1211 SET_ZNC_SUB(RN, RM, res);
1215 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);
1219 static void dsp_opcode_subc(void)
1223 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);
1225 UINT32 res = RN - RM - dsp_flag_c;
1226 UINT32 borrow = dsp_flag_c;
1227 SET_ZNC_SUB(RN - borrow, RM, res);
1231 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);
1235 static void dsp_opcode_subq(void)
1239 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);
1241 UINT32 r1 = dsp_convert_zero[IMM_1];
1242 UINT32 res = RN - r1;
1243 SET_ZNC_SUB(RN, r1, res);
1247 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1251 static void dsp_opcode_cmp(void)
1255 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);
1257 UINT32 res = RN - RM;
1258 SET_ZNC_SUB(RN, RM, res);
1261 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1265 static void dsp_opcode_cmpq(void)
1267 static int32 sqtable[32] =
1268 { 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 };
1271 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);
1273 UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1274 UINT32 res = RN - r1;
1275 SET_ZNC_SUB(RN, r1, res);
1278 WriteLog("[NCZ:%u%u%u]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z);
1282 static void dsp_opcode_and(void)
1286 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);
1292 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);
1296 static void dsp_opcode_or(void)
1300 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);
1306 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);
1310 static void dsp_opcode_xor(void)
1314 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);
1320 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);
1324 static void dsp_opcode_not(void)
1328 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);
1334 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);
1338 static void dsp_opcode_move_pc(void)
1343 static void dsp_opcode_store_r14_indexed(void)
1345 #ifdef DSP_DIS_STORE14I
1347 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));
1349 DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1352 static void dsp_opcode_store_r15_indexed(void)
1354 #ifdef DSP_DIS_STORE15I
1356 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));
1358 DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
1361 static void dsp_opcode_load_r14_ri(void)
1363 #ifdef DSP_DIS_LOAD14R
1365 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);
1367 RN = DSPReadLong(dsp_reg[14] + RM, DSP);
1368 #ifdef DSP_DIS_LOAD14R
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_load_r15_ri(void)
1376 #ifdef DSP_DIS_LOAD15R
1378 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);
1380 RN = DSPReadLong(dsp_reg[15] + RM, DSP);
1381 #ifdef DSP_DIS_LOAD15R
1383 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1387 static void dsp_opcode_store_r14_ri(void)
1389 DSPWriteLong(dsp_reg[14] + RM, RN, DSP);
1392 static void dsp_opcode_store_r15_ri(void)
1394 DSPWriteLong(dsp_reg[15] + RM, RN, DSP);
1397 static void dsp_opcode_nop(void)
1401 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", dsp_pc-2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
1405 static void dsp_opcode_storeb(void)
1407 #ifdef DSP_DIS_STOREB
1409 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);
1411 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1412 DSPWriteLong(RM, RN & 0xFF, DSP);
1414 JaguarWriteByte(RM, RN, DSP);
1417 static void dsp_opcode_storew(void)
1419 #ifdef DSP_DIS_STOREW
1421 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);
1423 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1424 DSPWriteLong(RM, RN & 0xFFFF, DSP);
1426 JaguarWriteWord(RM, RN, DSP);
1429 static void dsp_opcode_store(void)
1431 #ifdef DSP_DIS_STORE
1433 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);
1435 DSPWriteLong(RM, RN, DSP);
1438 static void dsp_opcode_loadb(void)
1440 #ifdef DSP_DIS_LOADB
1442 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);
1444 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1445 RN = DSPReadLong(RM, DSP) & 0xFF;
1447 RN = JaguarReadByte(RM, DSP);
1448 #ifdef DSP_DIS_LOADB
1450 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1454 static void dsp_opcode_loadw(void)
1456 #ifdef DSP_DIS_LOADW
1458 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);
1460 if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
1461 RN = DSPReadLong(RM, DSP) & 0xFFFF;
1463 RN = JaguarReadWord(RM, DSP);
1464 #ifdef DSP_DIS_LOADW
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(void)
1474 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);
1476 RN = DSPReadLong(RM, DSP);
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_load_r14_indexed(void)
1485 #ifdef DSP_DIS_LOAD14I
1487 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);
1489 RN = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), DSP);
1490 #ifdef DSP_DIS_LOAD14I
1492 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1496 static void dsp_opcode_load_r15_indexed(void)
1498 #ifdef DSP_DIS_LOAD15I
1500 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);
1502 RN = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), DSP);
1503 #ifdef DSP_DIS_LOAD15I
1505 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1509 static void dsp_opcode_movei(void)
1511 #ifdef DSP_DIS_MOVEI
1513 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);
1515 // This instruction is followed by 32-bit value in LSW / MSW format...
1516 RN = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
1518 #ifdef DSP_DIS_MOVEI
1520 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1524 static void dsp_opcode_moveta(void)
1526 #ifdef DSP_DIS_MOVETA
1528 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);
1531 #ifdef DSP_DIS_MOVETA
1533 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);
1537 static void dsp_opcode_movefa(void)
1539 #ifdef DSP_DIS_MOVEFA
1541 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);
1544 #ifdef DSP_DIS_MOVEFA
1546 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);
1550 static void dsp_opcode_move(void)
1554 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);
1559 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);
1563 static void dsp_opcode_moveq(void)
1565 #ifdef DSP_DIS_MOVEQ
1567 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);
1570 #ifdef DSP_DIS_MOVEQ
1572 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1576 static void dsp_opcode_resmac(void)
1578 #ifdef DSP_DIS_RESMAC
1580 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));
1582 RN = (uint32)dsp_acc;
1583 #ifdef DSP_DIS_RESMAC
1585 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1589 static void dsp_opcode_imult(void)
1591 #ifdef DSP_DIS_IMULT
1593 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);
1595 RN = (int16)RN * (int16)RM;
1597 #ifdef DSP_DIS_IMULT
1599 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);
1603 static void dsp_opcode_mult(void)
1607 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);
1609 RN = (uint16)RM * (uint16)RN;
1613 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);
1617 static void dsp_opcode_bclr(void)
1621 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);
1623 UINT32 res = RN & ~(1 << IMM_1);
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_btst(void)
1636 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);
1638 dsp_flag_z = (~RN >> IMM_1) & 1;
1641 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1645 static void dsp_opcode_bset(void)
1649 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);
1651 UINT32 res = RN | (1 << IMM_1);
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_subqt(void)
1662 #ifdef DSP_DIS_SUBQT
1664 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);
1666 RN -= dsp_convert_zero[IMM_1];
1667 #ifdef DSP_DIS_SUBQT
1669 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1673 static void dsp_opcode_addqt(void)
1675 #ifdef DSP_DIS_ADDQT
1677 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);
1679 RN += dsp_convert_zero[IMM_1];
1680 #ifdef DSP_DIS_ADDQT
1682 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1686 static void dsp_opcode_imacn(void)
1688 #ifdef DSP_DIS_IMACN
1690 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);
1692 int32 res = (int16)RM * (int16)RN;
1693 dsp_acc += (int64)res;
1694 //Should we AND the result to fit into 40 bits here???
1695 #ifdef DSP_DIS_IMACN
1697 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));
1701 static void dsp_opcode_mtoi(void)
1703 RN = (((INT32)RM >> 8) & 0xFF800000) | (RM & 0x007FFFFF);
1707 static void dsp_opcode_normi(void)
1714 while ((_Rm & 0xffc00000) == 0)
1719 while ((_Rm & 0xff800000) != 0)
1729 static void dsp_opcode_mmult(void)
1731 int count = dsp_matrix_control&0x0f;
1732 uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
1736 if (!(dsp_matrix_control & 0x10))
1738 for (int i = 0; i < count; i++)
1742 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1744 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1745 int16 b=((int16)DSPReadWord(addr + 2, DSP));
1752 for (int i = 0; i < count; i++)
1756 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1758 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1759 int16 b=((int16)DSPReadWord(addr + 2, DSP));
1764 RN = res = (int32)accum;
1766 //NOTE: The flags are set based upon the last add/multiply done...
1770 static void dsp_opcode_abs(void)
1775 if (_Rn == 0x80000000)
1779 dsp_flag_c = ((_Rn & 0x80000000) >> 31);
1780 res = RN = (_Rn & 0x80000000 ? -_Rn : _Rn);
1785 static void dsp_opcode_div(void)
1792 if (dsp_div_control & 1)
1794 dsp_remain = (((uint64)_Rn) << 16) % _Rm;
1795 if (dsp_remain&0x80000000)
1797 RN = (((uint64)_Rn) << 16) / _Rm;
1801 dsp_remain = _Rn % _Rm;
1802 if (dsp_remain&0x80000000)
1811 static void dsp_opcode_imultn(void)
1813 #ifdef DSP_DIS_IMULTN
1815 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);
1817 // This is OK, since this multiply won't overflow 32 bits...
1818 int32 res = (int32)((int16)RN * (int16)RM);
1819 dsp_acc = (int64)res;
1821 #ifdef DSP_DIS_IMULTN
1823 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));
1827 static void dsp_opcode_neg(void)
1831 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);
1834 SET_ZNC_SUB(0, RN, res);
1838 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1842 static void dsp_opcode_shlq(void)
1846 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);
1848 INT32 r1 = 32 - IMM_1;
1849 UINT32 res = RN << r1;
1850 SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
1854 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1858 static void dsp_opcode_shrq(void)
1862 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);
1864 INT32 r1 = dsp_convert_zero[IMM_1];
1865 UINT32 res = RN >> r1;
1866 SET_ZN(res); dsp_flag_c = RN & 1;
1870 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1874 static void dsp_opcode_ror(void)
1878 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);
1880 UINT32 r1 = RM & 0x1F;
1881 UINT32 res = (RN >> r1) | (RN << (32 - r1));
1882 SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
1886 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);
1890 static void dsp_opcode_rorq(void)
1894 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);
1896 UINT32 r1 = dsp_convert_zero[IMM_1 & 0x1F];
1898 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
1900 SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
1903 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1907 static void dsp_opcode_sha(void)
1909 int32 sRm=(int32)RM;
1915 if (shift>=32) shift=32;
1916 dsp_flag_c=(_Rn&0x80000000)>>31;
1926 if (shift>=32) shift=32;
1930 _Rn=((int32)_Rn)>>1;
1938 static void dsp_opcode_sharq(void)
1940 #ifdef DSP_DIS_SHARQ
1942 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);
1944 UINT32 res = (INT32)RN >> dsp_convert_zero[IMM_1];
1945 SET_ZN(res); dsp_flag_c = RN & 0x01;
1947 #ifdef DSP_DIS_SHARQ
1949 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
1953 static void dsp_opcode_sh(void)
1955 int32 sRm=(int32)RM;
1960 uint32 shift=(-sRm);
1961 if (shift>=32) shift=32;
1962 dsp_flag_c=(_Rn&0x80000000)>>31;
1972 if (shift>=32) shift=32;
1984 void dsp_opcode_addqmod(void)
1986 #ifdef DSP_DIS_ADDQMOD
1988 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);
1990 UINT32 r1 = dsp_convert_zero[IMM_1];
1992 UINT32 res = r2 + r1;
1993 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
1995 SET_ZNC_ADD(r2, r1, res);
1996 #ifdef DSP_DIS_ADDQMOD
1998 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
2002 void dsp_opcode_subqmod(void)
2004 UINT32 r1 = dsp_convert_zero[IMM_1];
2006 UINT32 res = r2 - r1;
2007 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2010 SET_ZNC_SUB(r2, r1, res);
2013 void dsp_opcode_mirror(void)
2016 RN = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
2020 void dsp_opcode_sat32s(void)
2022 INT32 r2 = (UINT32)RN;
2023 INT32 temp = dsp_acc >> 32;
2024 UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
2029 void dsp_opcode_sat16s(void)
2032 UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;