5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups by James L. Hammons
11 #define CINT0FLAG 0x00200
12 #define CINT1FLAG 0x00400
13 #define CINT2FLAG 0x00800
14 #define CINT3FLAG 0x01000
15 #define CINT4FLAG 0x02000
16 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
17 #define CINT5FLAG 0x20000 /* DSP only */
19 extern uint32 jaguar_mainRom_crc32;
21 static void dsp_opcode_addqmod(void);
22 static void dsp_opcode_subqmod(void);
23 static void dsp_opcode_mirror(void);
24 static void dsp_opcode_sat32s(void);
25 static void dsp_opcode_sat16s(void);
26 static void dsp_opcode_add(void);
27 static void dsp_opcode_addc(void);
28 static void dsp_opcode_addq(void);
29 static void dsp_opcode_addqt(void);
30 static void dsp_opcode_sub(void);
31 static void dsp_opcode_subc(void);
32 static void dsp_opcode_subq(void);
33 static void dsp_opcode_subqt(void);
34 static void dsp_opcode_neg(void);
35 static void dsp_opcode_and(void);
36 static void dsp_opcode_or(void);
37 static void dsp_opcode_xor(void);
38 static void dsp_opcode_not(void);
39 static void dsp_opcode_btst(void);
40 static void dsp_opcode_bset(void);
41 static void dsp_opcode_bclr(void);
42 static void dsp_opcode_mult(void);
43 static void dsp_opcode_imult(void);
44 static void dsp_opcode_imultn(void);
45 static void dsp_opcode_resmac(void);
46 static void dsp_opcode_imacn(void);
47 static void dsp_opcode_div(void);
48 static void dsp_opcode_abs(void);
49 static void dsp_opcode_sh(void);
50 static void dsp_opcode_shlq(void);
51 static void dsp_opcode_shrq(void);
52 static void dsp_opcode_sha(void);
53 static void dsp_opcode_sharq(void);
54 static void dsp_opcode_ror(void);
55 static void dsp_opcode_rorq(void);
56 static void dsp_opcode_cmp(void);
57 static void dsp_opcode_cmpq(void);
58 static void dsp_opcode_sat8(void);
59 static void dsp_opcode_sat16(void);
60 static void dsp_opcode_move(void);
61 static void dsp_opcode_moveq(void);
62 static void dsp_opcode_moveta(void);
63 static void dsp_opcode_movefa(void);
64 static void dsp_opcode_movei(void);
65 static void dsp_opcode_loadb(void);
66 static void dsp_opcode_loadw(void);
67 static void dsp_opcode_load(void);
68 static void dsp_opcode_loadp(void);
69 static void dsp_opcode_load_r14_indexed(void);
70 static void dsp_opcode_load_r15_indexed(void);
71 static void dsp_opcode_storeb(void);
72 static void dsp_opcode_storew(void);
73 static void dsp_opcode_store(void);
74 static void dsp_opcode_storep(void);
75 static void dsp_opcode_store_r14_indexed(void);
76 static void dsp_opcode_store_r15_indexed(void);
77 static void dsp_opcode_move_pc(void);
78 static void dsp_opcode_jump(void);
79 static void dsp_opcode_jr(void);
80 static void dsp_opcode_mmult(void);
81 static void dsp_opcode_mtoi(void);
82 static void dsp_opcode_normi(void);
83 static void dsp_opcode_nop(void);
84 static void dsp_opcode_load_r14_ri(void);
85 static void dsp_opcode_load_r15_ri(void);
86 static void dsp_opcode_store_r14_ri(void);
87 static void dsp_opcode_store_r15_ri(void);
88 static void dsp_opcode_sat24(void);
90 uint8 dsp_opcode_cycles[64] =
110 void (*dsp_opcode[64])()=
112 dsp_opcode_add, dsp_opcode_addc, dsp_opcode_addq, dsp_opcode_addqt,
113 dsp_opcode_sub, dsp_opcode_subc, dsp_opcode_subq, dsp_opcode_subqt,
114 dsp_opcode_neg, dsp_opcode_and, dsp_opcode_or, dsp_opcode_xor,
115 dsp_opcode_not, dsp_opcode_btst, dsp_opcode_bset, dsp_opcode_bclr,
116 dsp_opcode_mult, dsp_opcode_imult, dsp_opcode_imultn, dsp_opcode_resmac,
117 dsp_opcode_imacn, dsp_opcode_div, dsp_opcode_abs, dsp_opcode_sh,
118 dsp_opcode_shlq, dsp_opcode_shrq, dsp_opcode_sha, dsp_opcode_sharq,
119 dsp_opcode_ror, dsp_opcode_rorq, dsp_opcode_cmp, dsp_opcode_cmpq,
120 dsp_opcode_subqmod, dsp_opcode_sat16s, dsp_opcode_move, dsp_opcode_moveq,
121 dsp_opcode_moveta, dsp_opcode_movefa, dsp_opcode_movei, dsp_opcode_loadb,
122 dsp_opcode_loadw, dsp_opcode_load, dsp_opcode_sat32s, dsp_opcode_load_r14_indexed,
123 dsp_opcode_load_r15_indexed, dsp_opcode_storeb, dsp_opcode_storew, dsp_opcode_store,
124 dsp_opcode_mirror, dsp_opcode_store_r14_indexed, dsp_opcode_store_r15_indexed, dsp_opcode_move_pc,
125 dsp_opcode_jump, dsp_opcode_jr, dsp_opcode_mmult, dsp_opcode_mtoi,
126 dsp_opcode_normi, dsp_opcode_nop, dsp_opcode_load_r14_ri, dsp_opcode_load_r15_ri,
127 dsp_opcode_store_r14_ri, dsp_opcode_store_r15_ri, dsp_opcode_nop, dsp_opcode_addqmod,
130 uint32 dsp_opcode_use[64];
132 char *dsp_opcode_str[64]=
134 "add", "addc", "addq", "addqt",
135 "sub", "subc", "subq", "subqt",
136 "neg", "and", "or", "xor",
137 "not", "btst", "bset", "bclr",
138 "mult", "imult", "imultn", "resmac",
139 "imacn", "div", "abs", "sh",
140 "shlq", "shrq", "sha", "sharq",
141 "ror", "rorq", "cmp", "cmpq",
142 "subqmod", "sat16s", "move", "moveq",
143 "moveta", "movefa", "movei", "loadb",
144 "loadw", "load", "sat32s", "load_r14_indexed",
145 "load_r15_indexed", "storeb", "storew", "store",
146 "mirror", "store_r14_indexed","store_r15_indexed","move_pc",
147 "jump", "jr", "mmult", "mtoi",
148 "normi", "nop", "load_r14_ri", "load_r15_ri",
149 "store_r14_ri", "store_r15_ri", "nop", "addqmod",
152 static uint16 *mirror_table;
153 static uint8 *dsp_ram_8;
156 static uint32 dsp_acc;
157 static uint32 dsp_remain;
158 static uint32 dsp_modulo;
159 static uint32 dsp_flags;
160 static uint32 dsp_matrix_control;
161 static uint32 dsp_pointer_to_matrix;
162 static uint32 dsp_data_organization;
164 static uint32 dsp_div_control;
165 static uint8 dsp_flag_z;
166 static uint8 dsp_flag_n;
167 static uint8 dsp_flag_c;
168 static uint8 dsp_alternate_flag_z;
169 static uint8 dsp_alternate_flag_n;
170 static uint8 dsp_alternate_flag_c;
171 static uint32 *dsp_reg;
172 static uint32 *dsp_alternate_reg;
173 static uint32 *dsp_reg_bank_0;
174 static uint32 *dsp_reg_bank_1;
176 static uint32 dsp_opcode_first_parameter;
177 static uint32 dsp_opcode_second_parameter;
179 #define dsp_running (dsp_control&0x01)
181 #define Rm dsp_reg[dsp_opcode_first_parameter]
182 #define Rn dsp_reg[dsp_opcode_second_parameter]
183 #define alternate_Rm dsp_alternate_reg[dsp_opcode_first_parameter]
184 #define alternate_Rn dsp_alternate_reg[dsp_opcode_second_parameter]
185 #define imm_1 dsp_opcode_first_parameter
186 #define imm_2 dsp_opcode_second_parameter
188 #define set_flag_z(r) dsp_flag_z=(r==0);
189 #define set_flag_n(r) dsp_flag_n=(r&0x80000000);
191 #define reset_flag_z() dsp_flag_z=0;
192 #define reset_flag_n() dsp_flag_n=0;
193 #define reset_flag_c() dsp_flag_c=0;
195 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 };
196 uint8 *dsp_branch_condition_table=0;
197 #define branch_condition(x) dsp_branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
199 static uint32 dsp_in_exec = 0;
200 static uint32 dsp_releaseTimeSlice_flag = 0;
205 void dsp_reset_stats(void)
207 for (uint32 i=0; i<64; i++)
208 dsp_opcode_use[i] = 0;
211 void dsp_releaseTimeslice(void)
213 dsp_releaseTimeSlice_flag = 1;
216 void dsp_build_branch_condition_table(void)
219 #define ZFLAG 0x00001
220 #define CFLAG 0x00002
221 #define NFLAG 0x00004
223 /* allocate the mirror table */
225 mirror_table = (uint16*)malloc(65536 * sizeof(mirror_table[0]));
227 /* fill in the mirror table */
229 for (int i = 0; i < 65536; i++)
230 mirror_table[i] = ((i >> 15) & 0x0001) | ((i >> 13) & 0x0002) |
231 ((i >> 11) & 0x0004) | ((i >> 9) & 0x0008) |
232 ((i >> 7) & 0x0010) | ((i >> 5) & 0x0020) |
233 ((i >> 3) & 0x0040) | ((i >> 1) & 0x0080) |
234 ((i << 1) & 0x0100) | ((i << 3) & 0x0200) |
235 ((i << 5) & 0x0400) | ((i << 7) & 0x0800) |
236 ((i << 9) & 0x1000) | ((i << 11) & 0x2000) |
237 ((i << 13) & 0x4000) | ((i << 15) & 0x8000);
239 if (!dsp_branch_condition_table)
241 dsp_branch_condition_table = (uint8*)malloc(32 * 8 * sizeof(dsp_branch_condition_table[0]));
243 /* fill in the condition table */
244 if (dsp_branch_condition_table)
245 for (i = 0; i < 8; i++)
246 for (j = 0; j < 32; j++)
250 if (i & ZFLAG) result = 0;
252 if (!(i & ZFLAG)) result = 0;
254 if (i & (CFLAG << (j >> 4))) result = 0;
256 if (!(i & (CFLAG << (j >> 4)))) result = 0;
257 dsp_branch_condition_table[i * 32 + j] = result;
262 unsigned dsp_byte_read(unsigned int offset)
265 // if ((offset==0xF1CFE0)||(offset==0xF1CFE2))
268 if ((jaguar_mainRom_crc32==0xbfd751a4)||(jaguar_mainRom_crc32==0x053efaf9))
270 if (offset==0xF1CFE0)
273 if ((offset>=DSP_WORK_RAM_BASE)&&(offset<DSP_WORK_RAM_BASE+0x2000))
274 return(dsp_ram_8[offset-DSP_WORK_RAM_BASE]);
276 if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
278 uint32 data=dsp_long_read(offset&0xfffffffc);
280 if ((offset&0x03)==0)
283 if ((offset&0x03)==1)
284 return((data>>16)&0xff);
286 if ((offset&0x03)==2)
287 return((data>>8)&0xff);
289 if ((offset&0x03)==3)
292 return(jaguar_byte_read(offset));
295 unsigned dsp_word_read(unsigned int offset)
299 if (jaguar_mainRom_crc32==0xa74a97cd)
301 if (offset==0xF1A114) return(0x0000);
302 if (offset==0xF1A116) return(0x0000);
303 if (offset==0xF1B000) return(0x1234);
304 if (offset==0xF1B002) return(0x5678);
307 if (jaguar_mainRom_crc32==0x7ae20823)
309 if (offset==0xF1B9D8) return(0x0000);
310 if (offset==0xF1B9Da) return(0x0000);
311 if (offset==0xF1B2C0) return(0x0000);
312 if (offset==0xF1B2C2) return(0x0000);
315 // pour permettre à wolfenstein 3d de tourner sans le dsp
316 /* if ((offset==0xF1B0D0)||(offset==0xF1B0D2))
320 // pour permettre à nba jam de tourner sans le dsp
321 if (jaguar_mainRom_crc32==0x4faddb18)
323 if (offset==0xf1b2c0) return(0);
324 if (offset==0xf1b2c2) return(0);
325 if (offset==0xf1b240) return(0);
326 if (offset==0xf1b242) return(0);
327 if (offset==0xF1B340) return(0);
328 if (offset==0xF1B342) return(0);
329 if (offset==0xF1BAD8) return(0);
330 if (offset==0xF1BADA) return(0);
331 if (offset==0xF1B040) return(0);
332 if (offset==0xF1B042) return(0);
333 if (offset==0xF1B0C0) return(0);
334 if (offset==0xF1B0C2) return(0);
335 if (offset==0xF1B140) return(0);
336 if (offset==0xF1B142) return(0);
337 if (offset==0xF1B1C0) return(0);
338 if (offset==0xF1B1C2) return(0);
341 if ((offset>=DSP_WORK_RAM_BASE)&&(offset<DSP_WORK_RAM_BASE+0x2000))
343 offset-=DSP_WORK_RAM_BASE;
344 uint16 data=(((uint16)dsp_ram_8[offset])<<8)|((uint16)dsp_ram_8[offset+1]);
347 if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
351 data=dsp_long_read(offset&0xfffffffc);
358 return(jaguar_word_read(offset));
361 unsigned dsp_long_read(unsigned int offset)
365 if ((offset>=DSP_WORK_RAM_BASE)&&(offset<DSP_WORK_RAM_BASE+0x2000))
367 offset-=DSP_WORK_RAM_BASE;
368 uint32 data= (((uint32)dsp_ram_8[offset] )<<24)|
369 (((uint32)dsp_ram_8[offset+1])<<16)|
370 (((uint32)dsp_ram_8[offset+2])<<8 )|
371 ( (uint32)dsp_ram_8[offset+3]);
374 if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
379 case 0x00: dsp_flag_c?(dsp_flag_c=1):(dsp_flag_c=0);
380 dsp_flag_z?(dsp_flag_z=1):(dsp_flag_z=0);
381 dsp_flag_n?(dsp_flag_n=1):(dsp_flag_n=0);
383 dsp_flags=(dsp_flags&0xFFFFFFF8)|(dsp_flag_n<<2)|(dsp_flag_c<<1)|dsp_flag_z;
385 return(dsp_flags&0xFFFFC1FF);
386 case 0x04: return(dsp_matrix_control);
387 case 0x08: return(dsp_pointer_to_matrix);
388 case 0x0C: return(dsp_data_organization);
389 case 0x10: return(dsp_pc);
390 case 0x14: return(dsp_control);
391 case 0x18: return(dsp_modulo);
392 case 0x1C: return(dsp_remain);
393 // default: // unaligned long read //__asm int 3
397 uint32 data=jaguar_word_read(offset);
399 data|=jaguar_word_read(offset+2);
403 void dsp_byte_write(unsigned offset, unsigned data)
405 if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
407 offset -= DSP_WORK_RAM_BASE;
408 dsp_ram_8[offset] = data;
409 if (dsp_in_exec == 0)
411 // s68000releaseTimeslice();
412 m68k_end_timeslice();
413 gpu_releaseTimeslice();
417 if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
419 uint32 reg = offset & 0x1C;
420 int bytenum = offset & 0x03;
422 if ((reg >= 0x1C) && (reg <= 0x1F))
423 dsp_div_control = (dsp_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
426 uint32 old_data = dsp_long_read(offset&0xFFFFFFC);
427 bytenum = 3 - bytenum; // convention motorola !!!
428 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
429 dsp_long_write(offset & 0xFFFFFFC, old_data);
433 // fprintf(log_get(),"dsp: writing %.2x at 0x%.8x\n",data,offset);
434 jaguar_byte_write(offset, data);
437 void dsp_word_write(unsigned offset, unsigned data)
439 offset &= 0xFFFFFFFE;
440 // fprintf(log_get(),"dsp: writing %.4x at 0x%.8x\n",data,offset);
441 if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
443 offset -= DSP_WORK_RAM_BASE;
444 dsp_ram_8[offset] = data >> 8;
445 dsp_ram_8[offset+1] = data & 0xFF;
446 if (dsp_in_exec == 0)
448 // fprintf(log_get(),"dsp: writing %.4x at 0x%.8x\n",data,offset+DSP_WORK_RAM_BASE);
449 // s68000releaseTimeslice();
450 m68k_end_timeslice();
451 gpu_releaseTimeslice();
455 else if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
457 if ((offset & 0x1C) == 0x1C)
460 dsp_div_control = (dsp_div_control&0xffff0000)|(data&0xffff);
462 dsp_div_control = (dsp_div_control&0xffff)|((data&0xffff)<<16);
466 uint32 old_data = dsp_long_read(offset & 0xffffffc);
468 old_data = (old_data&0xffff0000)|(data&0xffff);
470 old_data = (old_data&0xffff)|((data&0xffff)<<16);
471 dsp_long_write(offset & 0xffffffc, old_data);
475 jaguar_word_write(offset, data);
478 void dsp_long_write(unsigned offset, unsigned data)
480 offset &= 0xFFFFFFFC;
481 // fprintf(log_get(),"dsp: writing %.8x at 0x%.8x\n",data,offset);
482 if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
484 offset -= DSP_WORK_RAM_BASE;
485 dsp_ram_8[offset] = data >> 24;
486 dsp_ram_8[offset+1] = (data>>16) & 0xFF;
487 dsp_ram_8[offset+2] = (data>>8) & 0xFF;
488 dsp_ram_8[offset+3] = data & 0xFF;
491 else if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
498 dsp_flag_z = dsp_flags & 0x01;
499 dsp_flag_c = (dsp_flags>>1) & 0x01;
500 dsp_flag_n = (dsp_flags>>2) & 0x01;
501 dsp_update_register_banks();
502 dsp_control &= ~((dsp_flags & CINT04FLAGS) >> 3);
503 dsp_control &= ~((dsp_flags & CINT5FLAG) >> 1);
507 dsp_matrix_control = data;
510 dsp_pointer_to_matrix = data;
513 dsp_data_organization = data;
520 uint32 dsp_was_running = dsp_running;
521 // check for DSP->CPU interrupt
524 // fprintf(log_get(),"DSP->CPU interrupt\n");
525 if (tom_irq_enabled(IRQ_GPU) && jaguar_interrupt_handler_is_valid(64))
527 tom_set_pending_gpu_int();
528 // s68000interrupt(7,64);
529 // s68000flushInterrupts();
530 m68k_set_irq(7); // Set 68000 NMI...
531 dsp_releaseTimeslice();
535 // check for CPU->DSP interrupt
538 // fprintf(log_get(),"CPU->DSP interrupt\n");
539 dsp_set_irq_line(0, 1);
540 // s68000releaseTimeslice();
541 m68k_end_timeslice();
542 gpu_releaseTimeslice();
548 //fprintf(log_get(),"asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
552 // if dsp wasn't running but is now running
553 // execute a few cycles
554 #ifndef DSP_SINGLE_STEPPING
555 if (!dsp_was_running && dsp_running)
560 if (dsp_control & 0x18)
569 dsp_div_control=data;
571 // default: // unaligned long read
576 jaguar_word_write(offset, (data>>16) & 0xFFFF);
577 jaguar_word_write(offset+2, data & 0xFFFF);
580 /*uint8 * jaguar_rom_load(char * path, uint32 * romSize);
581 void dsp_load_bin_at(char * path, uint32 offset)
586 rom = jaguar_rom_load(path, &romSize);
587 for(uint32 i=0; i<romSize; i++)
588 jaguar_byte_write(offset+i, rom[i]);
592 void dsp_update_register_banks(void)
597 bank = dsp_flags&0x4000;
602 if ((!bank && (dsp_reg_bank_0 != dsp_reg)) || (bank && (dsp_reg_bank_1 != dsp_reg)))
604 for (i = 0; i < 32; i++)
607 dsp_reg[i] = dsp_alternate_reg[i];
608 dsp_alternate_reg[i]= temp;
612 dsp_flag_z=dsp_alternate_flag_z;
613 dsp_alternate_flag_z=temp;
616 dsp_flag_n=dsp_alternate_flag_n;
617 dsp_alternate_flag_n=temp;
620 dsp_flag_c=dsp_alternate_flag_c;
621 dsp_alternate_flag_c=temp;
625 dsp_reg_bank_0 = dsp_reg;
626 dsp_reg_bank_1 = dsp_alternate_reg;
630 dsp_reg_bank_0 = dsp_alternate_reg;
631 dsp_reg_bank_1 = dsp_reg;
637 void dsp_check_if_i2s_interrupt_needed(void)
639 // Commenting this shit out helped a little bit... This is probably the reason
640 // why the sound isn't working right!
641 /* static uint32 count=8;
649 // already in an interrupt handler ?
653 // get the interrupt mask
654 int mask = (dsp_flags >> 4) & 0x1f;
655 mask |= (dsp_flags >> 11) & 0x20;
658 dsp_set_irq_line(1, 1);
661 void dsp_check_irqs(void)
663 int bits, mask, which = 0;
668 // get the active interrupt bits
669 bits = (dsp_control >> 6) & 0x1f;
670 bits |= (dsp_control >> 10) & 0x20;
672 // get the interrupt mask
673 mask = (dsp_flags >> 4) & 0x1f;
674 mask |= (dsp_flags >> 11) & 0x20;
676 // fprintf(log_get(),"dsp: bits=%.2x mask=%.2x\n",bits,mask);
677 // bail if nothing is available
683 // determine which interrupt
684 if (bits & 0x01) which = 0;
685 if (bits & 0x02) which = 1;
686 if (bits & 0x04) which = 2;
687 if (bits & 0x08) which = 3;
688 if (bits & 0x10) which = 4;
689 if (bits & 0x20) which = 5;
691 // fprintf(log_get(),"dsp: generating interrupt %i\n",which);
694 dsp_update_register_banks();
696 // subqt #4,r31 ; pre-decrement stack pointer
697 // move pc,r30 ; address of interrupted code
698 // store r30,(r31) ; store return address
701 dsp_long_write(dsp_reg[31], dsp_pc - 2);
703 // movei #service_address,r30 ; pointer to ISR entry
704 // jump (r30) ; jump to ISR
706 dsp_pc = DSP_WORK_RAM_BASE;
707 dsp_pc += which * 0x10;
711 void dsp_set_irq_line(int irqline, int state)
713 int mask = 0x40 << irqline;
714 dsp_control &= ~mask;
724 memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
725 memory_malloc_secure((void **)&dsp_reg, 32*sizeof(int32), "DSP bank 0 regs");
726 memory_malloc_secure((void **)&dsp_alternate_reg, 32*sizeof(int32), "DSP bank 1 regs");
728 dsp_build_branch_condition_table();
735 dsp_acc = 0x00000000;
736 dsp_remain = 0x00000000;
737 dsp_modulo = 0xFFFFFFFF;
738 dsp_flags = 0x00040000;
739 dsp_matrix_control = 0x00000000;
740 dsp_pointer_to_matrix = 0x00000000;
741 dsp_data_organization = 0xffffffff;
742 dsp_control = 0x00012800;
743 dsp_div_control = 0x00000000;
746 for(int i=0; i<32; i++)
748 dsp_reg[i] = 0x00000000;
749 dsp_alternate_reg[i] = 0x00000000;
752 dsp_reg_bank_0 = dsp_reg;
753 dsp_reg_bank_1 = dsp_alternate_reg;
754 // dsp_reg_bank_1 = dsp_reg;
755 // dsp_reg_bank_0 = dsp_alternate_reg;
761 dsp_alternate_flag_z = 0;
762 dsp_alternate_flag_n = 0;
763 dsp_alternate_flag_c = 0;
766 memset(dsp_ram_8, 0xFF, 0x2000);
772 fprintf(log_get(), "DSP: Stopped at PC=%08X dsp_modulo=%08X(dsp %s running)\n", dsp_pc, dsp_modulo, dsp_running ? "was" : "wasn't");
773 fprintf(log_get(), "DSP: %sin interrupt handler\n", (dsp_flags & 0x8) ? "" : "not ");
776 // get the active interrupt bits
777 bits = (dsp_control >> 6) & 0x1F;
778 bits |= (dsp_control >> 10) & 0x20;
780 // get the interrupt mask
781 mask = (dsp_flags >> 4) & 0x1F;
782 mask |= (dsp_flags >> 11) & 0x20;
784 fprintf(log_get(), "DSP: bits=%08X mask=%08X\n", bits, mask);
785 fprintf(log_get(), "\nRegisters bank 0\n");
786 for(int j=0; j<8; j++)
788 fprintf(log_get(), "\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
789 (j << 2) + 0, dsp_reg[(j << 2) + 0],
790 (j << 2) + 1, dsp_reg[(j << 2) + 1],
791 (j << 2) + 2, dsp_reg[(j << 2) + 2],
792 (j << 2) + 3, dsp_reg[(j << 2) + 3]);
794 // fprintf(log_get(),"registers bank 1\n");
797 // fprintf(log_get(),"\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
798 // (j<<2)+0,dsp_alternate_reg[(j<<2)+0],
799 // (j<<2)+1,dsp_alternate_reg[(j<<2)+1],
800 // (j<<2)+2,dsp_alternate_reg[(j<<2)+2],
801 // (j<<2)+3,dsp_alternate_reg[(j<<2)+3]);
804 static char buffer[512];
805 j = DSP_WORK_RAM_BASE;
806 // for(int i=0; i<4096; i++)
807 while (j <= 0xF1BFFF)
810 j += dasmjag(JAGUAR_DSP, buffer, j);
811 fprintf(log_get(), "\t%08X: %s\n", oldj, buffer);
814 fprintf(log_get(),"dsp opcodes use:\n");
817 if (dsp_opcode_use[i])
818 fprintf(log_get(),"\t%s %i\n",dsp_opcode_str[i],dsp_opcode_use[i]);
821 memory_free(dsp_ram_8);
824 void dsp_exec(int32 cycles)
826 if ((cycles!=1)&&(jaguar_mainRom_crc32==0xba74c3ed))
827 dsp_check_if_i2s_interrupt_needed();
829 #ifdef DSP_SINGLE_STEPPING
830 if (dsp_control&0x18)
837 dsp_releaseTimeSlice_flag=0;
839 while ((cycles>0)&&(dsp_running))
841 dsp_flag_c=(dsp_flag_c?1:0);
842 dsp_flag_z=(dsp_flag_z?1:0);
843 dsp_flag_n=(dsp_flag_n?1:0);
847 if (dsp_pc==0x00f1b02c)
856 if (dsp_pc==0x00f1b032)
858 dsp_fp=fopen("c:\\bad.log","wrt");
860 MessageBox(NULL,"Cannot open dsp log","",MB_OK);
864 fprintf(dsp_fp,"0x%.8x\n",dsp_pc);
867 // if (dsp_pc==0x00f1b130)
868 // dsp_load_bin_at("SCHRIFT.DAT",0x120000);
870 uint16 opcode=dsp_word_read(dsp_pc);
871 dsp_opcode_first_parameter=(opcode&0x3e0)>>5;
872 dsp_opcode_second_parameter=(opcode&0x1f);
874 dsp_opcode[opcode>>10]();
875 dsp_opcode_use[opcode>>10]++;
876 cycles-=dsp_opcode_cycles[opcode>>10];
881 static void dsp_opcode_jump(void)
883 uint32 delayed_pc = Rm;
887 dsp_flag_c=dsp_flag_c?1:0;
888 dsp_flag_z=dsp_flag_z?1:0;
889 dsp_flag_n=dsp_flag_n?1:0;
891 jaguar_flags=(dsp_flag_n<<2)|(dsp_flag_c<<1)|dsp_flag_z;
893 if (branch_condition(imm_2))
900 static void dsp_opcode_jr(void)
902 int32 offset=(imm_1&0x10) ? (0xFFFFFFF0|imm_1) : imm_1;
904 int32 delayed_pc = dsp_pc + (offset * 2);
908 dsp_flag_c=dsp_flag_c?1:0;
909 dsp_flag_z=dsp_flag_z?1:0;
910 dsp_flag_n=dsp_flag_n?1:0;
912 jaguar_flags=(dsp_flag_n<<2)|(dsp_flag_c<<1)|dsp_flag_z;
914 if (branch_condition(imm_2))
921 static void dsp_opcode_add(void)
929 GCC on WIN32 (more importantly mingw) doesn't know the declared
930 variables in asm until we put a _ before it.
932 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
943 : "d"(_Rm), "a"(_Rn));
954 : "d"(_Rm), "a"(_Rn));
972 static void dsp_opcode_addc(void)
980 GCC on WIN32 (more importantly mingw) doesn't know the declared
981 variables in asm until we put a _ before it.
983 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
984 We use __GCCWIN32__ for this "bug".
1003 : "d"(_Rm), "a"(_Rn));
1020 : "d"(_Rm), "a"(_Rn));
1031 jz dsp_opcode_addc_no_carry
1033 dsp_opcode_addc_no_carry:
1044 static void dsp_opcode_addq(void)
1047 uint32 _Rm=dsp_convert_zero[imm_1];
1053 GCC on WIN32 (more importantly mingw) doesn't know the declared
1054 variables in asm until we put a _ before it.
1056 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1069 : "d"(_Rm), "a"(_Rn));
1081 : "d"(_Rm), "a"(_Rn));
1100 static void dsp_opcode_sub(void)
1108 GCC on WIN32 (more importantly mingw) doesn't know the declared
1109 variables in asm until we put a _ before it.
1111 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1124 : "d"(_Rm), "a"(_Rn));
1136 : "d"(_Rm), "a"(_Rn));
1155 static void dsp_opcode_subc(void)
1163 GCC on WIN32 (more importantly mingw) doesn't know the declared
1164 variables in asm until we put a _ before it.
1166 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1185 : "d"(_Rm), "a"(_Rn));
1203 : "d"(_Rm), "a"(_Rn));
1214 jz dsp_opcode_subc_no_carry
1216 dsp_opcode_subc_no_carry:
1227 static void dsp_opcode_subq(void)
1229 uint32 _Rm=dsp_convert_zero[imm_1];
1235 GCC on WIN32 (more importantly mingw) doesn't know the declared
1236 variables in asm until we put a _ before it.
1238 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1251 : "d"(_Rm), "a"(_Rn));
1263 : "d"(_Rm), "a"(_Rn));
1281 static void dsp_opcode_cmp(void)
1288 GCC on WIN32 (more importantly mingw) doesn't know the declared
1289 variables in asm until we put a _ before it.
1291 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1303 : "d"(_Rm), "a"(_Rn));
1314 : "d"(_Rm), "a"(_Rn));
1331 static void dsp_opcode_cmpq(void)
1333 static int32 sqtable[32] = { 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};
1334 int32 _Rm=sqtable[imm_1&0x1f];
1339 GCC on WIN32 (more importantly mingw) doesn't know the declared
1340 variables in asm until we put a _ before it.
1342 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1354 : "d"(_Rm), "a"(_Rn));
1365 : "d"(_Rm), "a"(_Rn));
1382 static void dsp_opcode_and(void)
1390 GCC on WIN32 (more importantly mingw) doesn't know the declared
1391 variables in asm until we put a _ before it.
1393 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1405 : "d"(_Rm), "a"(_Rn));
1416 : "d"(_Rm), "a"(_Rn));
1434 static void dsp_opcode_or(void)
1442 GCC on WIN32 (more importantly mingw) doesn't know the declared
1443 variables in asm until we put a _ before it.
1445 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1457 : "d"(_Rm), "a"(_Rn));
1468 : "d"(_Rm), "a"(_Rn));
1486 static void dsp_opcode_xor(void)
1494 GCC on WIN32 (more importantly mingw) doesn't know the declared
1495 variables in asm until we put a _ before it.
1497 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1509 : "d"(_Rm), "a"(_Rn));
1520 : "d"(_Rm), "a"(_Rn));
1538 static void dsp_opcode_not(void)
1545 GCC on WIN32 (more importantly mingw) doesn't know the declared
1546 variables in asm until we put a _ before it.
1548 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1588 static void dsp_opcode_move_pc(void)
1593 static void dsp_opcode_sat8(void)
1595 int32 _Rn=(int32)Rn;
1597 uint32 res= Rn = (_Rn<0) ? 0 : (_Rn > 0xff ? 0xff : _Rn);
1602 static void dsp_opcode_sat16(void)
1605 uint32 res= Rn = (_Rn&0x80000000) ? 0 : (_Rn > 0xFFFF ? 0xFFFF : _Rn);
1610 static void dsp_opcode_sat24(void)
1614 uint32 res= Rn = (_Rn&0x80000000) ? 0 : (_Rn > 0xFFFFFF ? 0xFFFFFF : _Rn);
1619 static void dsp_opcode_store_r14_indexed(void)
1621 dsp_long_write( dsp_reg[14] + (dsp_convert_zero[imm_1] << 2),Rn);
1624 static void dsp_opcode_store_r15_indexed(void)
1626 dsp_long_write( dsp_reg[15] + (dsp_convert_zero[imm_1] << 2),Rn);
1629 static void dsp_opcode_load_r14_ri(void)
1631 Rn=dsp_long_read(dsp_reg[14] + Rm);
1634 static void dsp_opcode_load_r15_ri(void)
1636 Rn=dsp_long_read(dsp_reg[15] + Rm);
1639 static void dsp_opcode_store_r14_ri(void)
1641 dsp_long_write(dsp_reg[14] + Rm,Rn);
1644 static void dsp_opcode_store_r15_ri(void)
1646 dsp_long_write(dsp_reg[15] + Rm,Rn);
1649 static void dsp_opcode_nop(void)
1653 static void dsp_opcode_pack(void)
1659 Rn =((_Rn & 0x03C00000) >> 10) |
1660 ((_Rn & 0x0001E000) >> 5) |
1661 ((_Rn & 0x000000FF));
1665 Rn =((_Rn & 0x0000F000) << 10) |
1666 ((_Rn & 0x00000F00) << 5) |
1667 ((_Rn & 0x000000FF));
1675 static void dsp_opcode_storeb(void)
1677 if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1678 dsp_long_write(Rm,Rn&0xff);
1680 jaguar_byte_write(Rm,Rn);
1683 static void dsp_opcode_storew(void)
1685 if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1686 dsp_long_write(Rm,Rn&0xffff);
1688 jaguar_word_write(Rm,Rn);
1691 static void dsp_opcode_store(void)
1693 dsp_long_write(Rm,Rn);
1696 static void dsp_opcode_loadb(void)
1698 if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1699 Rn=dsp_long_read(Rm)&0xff;
1701 Rn=jaguar_byte_read(Rm);
1704 static void dsp_opcode_loadw(void)
1706 if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1707 Rn=dsp_long_read(Rm)&0xffff;
1709 Rn=jaguar_word_read(Rm);
1712 static void dsp_opcode_load(void)
1714 Rn = dsp_long_read(Rm);
1717 static void dsp_opcode_load_r14_indexed(void)
1719 Rn = dsp_long_read( dsp_reg[14] + (dsp_convert_zero[imm_1] << 2));
1722 static void dsp_opcode_load_r15_indexed(void)
1724 Rn = dsp_long_read( dsp_reg[15] + (dsp_convert_zero[imm_1] << 2));
1727 static void dsp_opcode_movei(void)
1729 Rn = ((uint32)dsp_word_read(dsp_pc)) + (((uint32)dsp_word_read(dsp_pc+2))<<16);
1733 static void dsp_opcode_moveta(void)
1738 static void dsp_opcode_movefa(void)
1743 static void dsp_opcode_move(void)
1748 static void dsp_opcode_moveq(void)
1753 static void dsp_opcode_resmac(void)
1758 static void dsp_opcode_imult(void)
1760 uint32 res=Rn=((int16)Rn)*((int16)Rm);
1765 static void dsp_opcode_mult(void)
1767 uint32 res=Rn = ((uint16)Rm) * ((uint16)Rn);
1772 static void dsp_opcode_bclr(void)
1780 GCC on WIN32 (more importantly mingw) doesn't know the declared
1781 variables in asm until we put a _ before it.
1783 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1796 : "c"(_Rm), "a"(_Rn));
1808 : "c"(_Rm), "a"(_Rn));
1828 static void dsp_opcode_btst(void)
1835 GCC on WIN32 (more importantly mingw) doesn't know the declared
1836 variables in asm until we put a _ before it.
1838 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1848 : "c"(_Rm), "a"(_Rn));
1857 : "c"(_Rm), "a"(_Rn));
1872 static void dsp_opcode_bset(void)
1880 GCC on WIN32 (more importantly mingw) doesn't know the declared
1881 variables in asm until we put a _ before it.
1883 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1896 : "c"(_Rm), "a"(_Rn));
1908 : "c"(_Rm), "a"(_Rn));
1927 static void dsp_opcode_subqt(void)
1929 Rn -= dsp_convert_zero[imm_1];
1932 static void dsp_opcode_addqt(void)
1934 Rn += dsp_convert_zero[imm_1];
1937 static void dsp_opcode_imacn(void)
1939 uint32 res=((int16)Rm) * ((int16)(Rn));
1943 static void dsp_opcode_mtoi(void)
1946 uint32 res=Rn=(((INT32)_Rm >> 8) & 0xff800000) | (_Rm & 0x007fffff);
1951 static void dsp_opcode_normi(void)
1958 while ((_Rm & 0xffc00000) == 0)
1963 while ((_Rm & 0xff800000) != 0)
1974 static void dsp_opcode_mmult(void)
1976 int count = dsp_matrix_control&0x0f;
1977 uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
1981 if (!(dsp_matrix_control & 0x10))
1983 for (int i = 0; i < count; i++)
1987 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1989 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1990 int16 b=((int16)dsp_word_read(addr+2));
1997 for (int i = 0; i < count; i++)
2001 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
2003 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
2004 int16 b=((int16)dsp_word_read(addr+2));
2009 Rn = res = (int32)accum;
2015 static void dsp_opcode_abs(void)
2020 if (_Rn==0x80000000)
2026 dsp_flag_c = ((_Rn&0x80000000)>>31);
2027 res= Rn = (_Rn & 0x80000000) ? -_Rn : _Rn;
2033 static void dsp_opcode_div(void)
2040 if (dsp_div_control & 1)
2042 dsp_remain = (((uint64)_Rn) << 16) % _Rm;
2043 if (dsp_remain&0x80000000)
2045 Rn = (((uint64)_Rn) << 16) / _Rm;
2049 dsp_remain = _Rn % _Rm;
2050 if (dsp_remain&0x80000000)
2059 static void dsp_opcode_imultn(void)
2061 uint32 res=(int32)(((int16)Rn)*((int16)Rm));
2067 static void dsp_opcode_neg(void)
2074 GCC on WIN32 (more importantly mingw) doesn't know the declared
2075 variables in asm until we put a _ before it.
2077 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2091 : "d"(_Rn), "a"(0));
2104 : "d"(_Rn), "a"(0));
2123 static void dsp_opcode_shlq(void)
2125 uint32 shift=(32-dsp_convert_zero[imm_1]);
2131 GCC on WIN32 (more importantly mingw) doesn't know the declared
2132 variables in asm until we put a _ before it.
2134 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2140 "testl $0x80000000, %2
2149 : "c"(shift), "a"(_Rn));
2154 "testl $0x80000000, %2
2163 : "c"(shift), "a"(_Rn));
2184 static void dsp_opcode_shrq(void)
2186 uint32 shift=dsp_convert_zero[imm_1];
2193 GCC on WIN32 (more importantly mingw) doesn't know the declared
2194 variables in asm until we put a _ before it.
2196 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2202 "testl $0x00000001, %2
2211 : "c"(shift), "a"(_Rn));
2216 "testl $0x00000001, %2
2225 : "c"(shift), "a"(_Rn));
2246 static void dsp_opcode_ror(void)
2254 GCC on WIN32 (more importantly mingw) doesn't know the declared
2255 variables in asm until we put a _ before it.
2257 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2263 "testl $0x80000000, %2
2272 : "c"(shift), "a"(_Rn));
2277 "testl $0x80000000, %2
2286 : "c"(shift), "a"(_Rn));
2307 static void dsp_opcode_rorq(void)
2309 uint32 shift=dsp_convert_zero[imm_1&0x1f];
2315 GCC on WIN32 (more importantly mingw) doesn't know the declared
2316 variables in asm until we put a _ before it.
2318 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2324 "testl $0x80000000, %2
2333 : "c"(shift), "a"(_Rn));
2338 "testl $0x80000000, %2
2347 : "c"(shift), "a"(_Rn));
2368 static void dsp_opcode_sha(void)
2370 int32 sRm=(int32)Rm;
2376 if (shift>=32) shift=32;
2377 dsp_flag_c=(_Rn&0x80000000)>>31;
2387 if (shift>=32) shift=32;
2391 _Rn=((int32)_Rn)>>1;
2400 static void dsp_opcode_sharq(void)
2402 uint32 shift=dsp_convert_zero[imm_1];
2405 dsp_flag_c = (_Rn & 0x1);
2408 _Rn=((int32)_Rn)>>1;
2416 static void dsp_opcode_sh(void)
2418 int32 sRm=(int32)Rm;
2423 uint32 shift=(-sRm);
2424 if (shift>=32) shift=32;
2425 dsp_flag_c=(_Rn&0x80000000)>>31;
2435 if (shift>=32) shift=32;
2448 #define CLR_ZN { dsp_flag_n=0; dsp_flag_z=0; };
2449 #define CLR_ZNC { dsp_flag_c=0; dsp_flag_n=0; dsp_flag_z=0; };
2450 #define SET_Z(r) (dsp_flag_z= ((r) == 0))
2451 #define SET_C_ADD(a,b) (dsp_flag_c= ((UINT32)(b) > (UINT32)(~(a))) << 1)
2452 #define SET_C_SUB(a,b) (dsp_flag_c= ((UINT32)(b) > (UINT32)(a)) << 1)
2453 #define SET_N(r) (dsp_flag_n= (((UINT32)(r) >> 29) & 4))
2454 #define SET_ZN(r) SET_N(r); SET_Z(r)
2455 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
2456 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
2458 void dsp_opcode_addqmod(void)
2460 UINT32 r1 = dsp_convert_zero[imm_1];
2462 UINT32 res = r2 + r1;
2463 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2465 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);
2467 void dsp_opcode_subqmod(void)
2469 UINT32 r1 = dsp_convert_zero[imm_1];
2471 UINT32 res = r2 - r1;
2472 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2475 SET_ZNC_SUB(r2,r1,res);
2477 void dsp_opcode_mirror(void)
2480 UINT32 res = (mirror_table[r1 & 0xffff] << 16) | mirror_table[r1 >> 16];
2482 CLR_ZN; SET_ZN(res);
2484 void dsp_opcode_sat32s(void)
2486 INT32 r2 = (UINT32)Rn;
2487 INT32 temp = dsp_acc >> 32;
2488 UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7fffffff : r2;
2490 CLR_ZN; SET_ZN(res);
2492 void dsp_opcode_sat16s(void)
2495 UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
2497 CLR_ZN; SET_ZN(res);