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;
636 void dsp_check_if_i2s_interrupt_needed(void)
638 static uint32 count=8;
646 // already in an interrupt handler ?
650 // get the interrupt mask
651 mask = (dsp_flags >> 4) & 0x1f;
652 mask |= (dsp_flags >> 11) & 0x20;
656 dsp_set_irq_line(1,1);
660 void dsp_check_irqs(void)
662 int bits, mask, which = 0;
667 // get the active interrupt bits
668 bits = (dsp_control >> 6) & 0x1f;
669 bits |= (dsp_control >> 10) & 0x20;
671 // get the interrupt mask
672 mask = (dsp_flags >> 4) & 0x1f;
673 mask |= (dsp_flags >> 11) & 0x20;
675 // fprintf(log_get(),"dsp: bits=%.2x mask=%.2x\n",bits,mask);
676 // bail if nothing is available
682 // determine which interrupt
683 if (bits & 0x01) which = 0;
684 if (bits & 0x02) which = 1;
685 if (bits & 0x04) which = 2;
686 if (bits & 0x08) which = 3;
687 if (bits & 0x10) which = 4;
688 if (bits & 0x20) which = 5;
690 // fprintf(log_get(),"dsp: generating interrupt %i\n",which);
693 dsp_update_register_banks();
695 // subqt #4,r31 ; pre-decrement stack pointer
696 // move pc,r30 ; address of interrupted code
697 // store r30,(r31) ; store return address
700 dsp_long_write(dsp_reg[31], dsp_pc - 2);
702 // movei #service_address,r30 ; pointer to ISR entry
703 // jump (r30) ; jump to ISR
705 dsp_pc = DSP_WORK_RAM_BASE;
706 dsp_pc += which * 0x10;
710 void dsp_set_irq_line(int irqline, int state)
712 int mask = 0x40 << irqline;
713 dsp_control &= ~mask;
723 memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
724 memory_malloc_secure((void **)&dsp_reg, 32*sizeof(int32), "DSP bank 0 regs");
725 memory_malloc_secure((void **)&dsp_alternate_reg, 32*sizeof(int32), "DSP bank 1 regs");
727 dsp_build_branch_condition_table();
734 dsp_acc = 0x00000000;
735 dsp_remain = 0x00000000;
736 dsp_modulo = 0xFFFFFFFF;
737 dsp_flags = 0x00040000;
738 dsp_matrix_control = 0x00000000;
739 dsp_pointer_to_matrix = 0x00000000;
740 dsp_data_organization = 0xffffffff;
741 dsp_control = 0x00012800;
742 dsp_div_control = 0x00000000;
745 for(int i=0; i<32; i++)
747 dsp_reg[i] = 0x00000000;
748 dsp_alternate_reg[i] = 0x00000000;
751 dsp_reg_bank_0 = dsp_reg;
752 dsp_reg_bank_1 = dsp_alternate_reg;
753 // dsp_reg_bank_1 = dsp_reg;
754 // dsp_reg_bank_0 = dsp_alternate_reg;
760 dsp_alternate_flag_z = 0;
761 dsp_alternate_flag_n = 0;
762 dsp_alternate_flag_c = 0;
765 memset(dsp_ram_8, 0xFF, 0x2000);
771 fprintf(log_get(), "DSP: Stopped at PC=%08X dsp_modulo=%08X(dsp %s running)\n", dsp_pc, dsp_modulo, dsp_running ? "was" : "wasn't");
772 fprintf(log_get(), "DSP: %sin interrupt handler\n", (dsp_flags & 0x8) ? "" : "not ");
775 // get the active interrupt bits
776 bits = (dsp_control >> 6) & 0x1F;
777 bits |= (dsp_control >> 10) & 0x20;
779 // get the interrupt mask
780 mask = (dsp_flags >> 4) & 0x1F;
781 mask |= (dsp_flags >> 11) & 0x20;
783 fprintf(log_get(), "DSP: bits=%08X mask=%08X\n", bits, mask);
784 fprintf(log_get(), "\nRegisters bank 0\n");
785 for(int j=0; j<8; j++)
787 fprintf(log_get(), "\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
788 (j << 2) + 0, dsp_reg[(j << 2) + 0],
789 (j << 2) + 1, dsp_reg[(j << 2) + 1],
790 (j << 2) + 2, dsp_reg[(j << 2) + 2],
791 (j << 2) + 3, dsp_reg[(j << 2) + 3]);
793 // fprintf(log_get(),"registers bank 1\n");
796 // fprintf(log_get(),"\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
797 // (j<<2)+0,dsp_alternate_reg[(j<<2)+0],
798 // (j<<2)+1,dsp_alternate_reg[(j<<2)+1],
799 // (j<<2)+2,dsp_alternate_reg[(j<<2)+2],
800 // (j<<2)+3,dsp_alternate_reg[(j<<2)+3]);
803 static char buffer[512];
804 j = DSP_WORK_RAM_BASE;
805 // for(int i=0; i<4096; i++)
806 while (j <= 0xF1BFFF)
809 j += dasmjag(JAGUAR_DSP, buffer, j);
810 fprintf(log_get(), "\t%08X: %s\n", oldj, buffer);
813 fprintf(log_get(),"dsp opcodes use:\n");
816 if (dsp_opcode_use[i])
817 fprintf(log_get(),"\t%s %i\n",dsp_opcode_str[i],dsp_opcode_use[i]);
820 memory_free(dsp_ram_8);
823 void dsp_exec(int32 cycles)
825 if ((cycles!=1)&&(jaguar_mainRom_crc32==0xba74c3ed))
826 dsp_check_if_i2s_interrupt_needed();
828 #ifdef DSP_SINGLE_STEPPING
829 if (dsp_control&0x18)
836 dsp_releaseTimeSlice_flag=0;
838 while ((cycles>0)&&(dsp_running))
840 dsp_flag_c=(dsp_flag_c?1:0);
841 dsp_flag_z=(dsp_flag_z?1:0);
842 dsp_flag_n=(dsp_flag_n?1:0);
846 if (dsp_pc==0x00f1b02c)
855 if (dsp_pc==0x00f1b032)
857 dsp_fp=fopen("c:\\bad.log","wrt");
859 MessageBox(NULL,"Cannot open dsp log","",MB_OK);
863 fprintf(dsp_fp,"0x%.8x\n",dsp_pc);
866 // if (dsp_pc==0x00f1b130)
867 // dsp_load_bin_at("SCHRIFT.DAT",0x120000);
869 uint16 opcode=dsp_word_read(dsp_pc);
870 dsp_opcode_first_parameter=(opcode&0x3e0)>>5;
871 dsp_opcode_second_parameter=(opcode&0x1f);
873 dsp_opcode[opcode>>10]();
874 dsp_opcode_use[opcode>>10]++;
875 cycles-=dsp_opcode_cycles[opcode>>10];
880 static void dsp_opcode_jump(void)
882 uint32 delayed_pc = Rm;
886 dsp_flag_c=dsp_flag_c?1:0;
887 dsp_flag_z=dsp_flag_z?1:0;
888 dsp_flag_n=dsp_flag_n?1:0;
890 jaguar_flags=(dsp_flag_n<<2)|(dsp_flag_c<<1)|dsp_flag_z;
892 if (branch_condition(imm_2))
899 static void dsp_opcode_jr(void)
901 int32 offset=(imm_1&0x10) ? (0xFFFFFFF0|imm_1) : imm_1;
903 int32 delayed_pc = dsp_pc + (offset * 2);
907 dsp_flag_c=dsp_flag_c?1:0;
908 dsp_flag_z=dsp_flag_z?1:0;
909 dsp_flag_n=dsp_flag_n?1:0;
911 jaguar_flags=(dsp_flag_n<<2)|(dsp_flag_c<<1)|dsp_flag_z;
913 if (branch_condition(imm_2))
920 static void dsp_opcode_add(void)
928 GCC on WIN32 (more importantly mingw) doesn't know the declared
929 variables in asm until we put a _ before it.
931 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
942 : "d"(_Rm), "a"(_Rn));
953 : "d"(_Rm), "a"(_Rn));
971 static void dsp_opcode_addc(void)
979 GCC on WIN32 (more importantly mingw) doesn't know the declared
980 variables in asm until we put a _ before it.
982 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
983 We use __GCCWIN32__ for this "bug".
1002 : "d"(_Rm), "a"(_Rn));
1019 : "d"(_Rm), "a"(_Rn));
1030 jz dsp_opcode_addc_no_carry
1032 dsp_opcode_addc_no_carry:
1043 static void dsp_opcode_addq(void)
1046 uint32 _Rm=dsp_convert_zero[imm_1];
1052 GCC on WIN32 (more importantly mingw) doesn't know the declared
1053 variables in asm until we put a _ before it.
1055 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1068 : "d"(_Rm), "a"(_Rn));
1080 : "d"(_Rm), "a"(_Rn));
1099 static void dsp_opcode_sub(void)
1107 GCC on WIN32 (more importantly mingw) doesn't know the declared
1108 variables in asm until we put a _ before it.
1110 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1123 : "d"(_Rm), "a"(_Rn));
1135 : "d"(_Rm), "a"(_Rn));
1154 static void dsp_opcode_subc(void)
1162 GCC on WIN32 (more importantly mingw) doesn't know the declared
1163 variables in asm until we put a _ before it.
1165 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1184 : "d"(_Rm), "a"(_Rn));
1202 : "d"(_Rm), "a"(_Rn));
1213 jz dsp_opcode_subc_no_carry
1215 dsp_opcode_subc_no_carry:
1226 static void dsp_opcode_subq(void)
1228 uint32 _Rm=dsp_convert_zero[imm_1];
1234 GCC on WIN32 (more importantly mingw) doesn't know the declared
1235 variables in asm until we put a _ before it.
1237 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1250 : "d"(_Rm), "a"(_Rn));
1262 : "d"(_Rm), "a"(_Rn));
1280 static void dsp_opcode_cmp(void)
1287 GCC on WIN32 (more importantly mingw) doesn't know the declared
1288 variables in asm until we put a _ before it.
1290 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1302 : "d"(_Rm), "a"(_Rn));
1313 : "d"(_Rm), "a"(_Rn));
1330 static void dsp_opcode_cmpq(void)
1332 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};
1333 int32 _Rm=sqtable[imm_1&0x1f];
1338 GCC on WIN32 (more importantly mingw) doesn't know the declared
1339 variables in asm until we put a _ before it.
1341 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1353 : "d"(_Rm), "a"(_Rn));
1364 : "d"(_Rm), "a"(_Rn));
1381 static void dsp_opcode_and(void)
1389 GCC on WIN32 (more importantly mingw) doesn't know the declared
1390 variables in asm until we put a _ before it.
1392 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1404 : "d"(_Rm), "a"(_Rn));
1415 : "d"(_Rm), "a"(_Rn));
1433 static void dsp_opcode_or(void)
1441 GCC on WIN32 (more importantly mingw) doesn't know the declared
1442 variables in asm until we put a _ before it.
1444 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1456 : "d"(_Rm), "a"(_Rn));
1467 : "d"(_Rm), "a"(_Rn));
1485 static void dsp_opcode_xor(void)
1493 GCC on WIN32 (more importantly mingw) doesn't know the declared
1494 variables in asm until we put a _ before it.
1496 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1508 : "d"(_Rm), "a"(_Rn));
1519 : "d"(_Rm), "a"(_Rn));
1537 static void dsp_opcode_not(void)
1544 GCC on WIN32 (more importantly mingw) doesn't know the declared
1545 variables in asm until we put a _ before it.
1547 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1587 static void dsp_opcode_move_pc(void)
1592 static void dsp_opcode_sat8(void)
1594 int32 _Rn=(int32)Rn;
1596 uint32 res= Rn = (_Rn<0) ? 0 : (_Rn > 0xff ? 0xff : _Rn);
1601 static void dsp_opcode_sat16(void)
1604 uint32 res= Rn = (_Rn&0x80000000) ? 0 : (_Rn > 0xFFFF ? 0xFFFF : _Rn);
1609 static void dsp_opcode_sat24(void)
1613 uint32 res= Rn = (_Rn&0x80000000) ? 0 : (_Rn > 0xFFFFFF ? 0xFFFFFF : _Rn);
1618 static void dsp_opcode_store_r14_indexed(void)
1620 dsp_long_write( dsp_reg[14] + (dsp_convert_zero[imm_1] << 2),Rn);
1623 static void dsp_opcode_store_r15_indexed(void)
1625 dsp_long_write( dsp_reg[15] + (dsp_convert_zero[imm_1] << 2),Rn);
1628 static void dsp_opcode_load_r14_ri(void)
1630 Rn=dsp_long_read(dsp_reg[14] + Rm);
1633 static void dsp_opcode_load_r15_ri(void)
1635 Rn=dsp_long_read(dsp_reg[15] + Rm);
1638 static void dsp_opcode_store_r14_ri(void)
1640 dsp_long_write(dsp_reg[14] + Rm,Rn);
1643 static void dsp_opcode_store_r15_ri(void)
1645 dsp_long_write(dsp_reg[15] + Rm,Rn);
1648 static void dsp_opcode_nop(void)
1652 static void dsp_opcode_pack(void)
1658 Rn =((_Rn & 0x03C00000) >> 10) |
1659 ((_Rn & 0x0001E000) >> 5) |
1660 ((_Rn & 0x000000FF));
1664 Rn =((_Rn & 0x0000F000) << 10) |
1665 ((_Rn & 0x00000F00) << 5) |
1666 ((_Rn & 0x000000FF));
1674 static void dsp_opcode_storeb(void)
1676 if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1677 dsp_long_write(Rm,Rn&0xff);
1679 jaguar_byte_write(Rm,Rn);
1682 static void dsp_opcode_storew(void)
1684 if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1685 dsp_long_write(Rm,Rn&0xffff);
1687 jaguar_word_write(Rm,Rn);
1690 static void dsp_opcode_store(void)
1692 dsp_long_write(Rm,Rn);
1695 static void dsp_opcode_loadb(void)
1697 if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1698 Rn=dsp_long_read(Rm)&0xff;
1700 Rn=jaguar_byte_read(Rm);
1703 static void dsp_opcode_loadw(void)
1705 if ((Rm >= DSP_WORK_RAM_BASE) && (Rm < (DSP_WORK_RAM_BASE+0x2000)))
1706 Rn=dsp_long_read(Rm)&0xffff;
1708 Rn=jaguar_word_read(Rm);
1711 static void dsp_opcode_load(void)
1713 Rn = dsp_long_read(Rm);
1716 static void dsp_opcode_load_r14_indexed(void)
1718 Rn = dsp_long_read( dsp_reg[14] + (dsp_convert_zero[imm_1] << 2));
1721 static void dsp_opcode_load_r15_indexed(void)
1723 Rn = dsp_long_read( dsp_reg[15] + (dsp_convert_zero[imm_1] << 2));
1726 static void dsp_opcode_movei(void)
1728 Rn = ((uint32)dsp_word_read(dsp_pc)) + (((uint32)dsp_word_read(dsp_pc+2))<<16);
1732 static void dsp_opcode_moveta(void)
1737 static void dsp_opcode_movefa(void)
1742 static void dsp_opcode_move(void)
1747 static void dsp_opcode_moveq(void)
1752 static void dsp_opcode_resmac(void)
1757 static void dsp_opcode_imult(void)
1759 uint32 res=Rn=((int16)Rn)*((int16)Rm);
1764 static void dsp_opcode_mult(void)
1766 uint32 res=Rn = ((uint16)Rm) * ((uint16)Rn);
1771 static void dsp_opcode_bclr(void)
1779 GCC on WIN32 (more importantly mingw) doesn't know the declared
1780 variables in asm until we put a _ before it.
1782 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1795 : "c"(_Rm), "a"(_Rn));
1807 : "c"(_Rm), "a"(_Rn));
1827 static void dsp_opcode_btst(void)
1834 GCC on WIN32 (more importantly mingw) doesn't know the declared
1835 variables in asm until we put a _ before it.
1837 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1847 : "c"(_Rm), "a"(_Rn));
1856 : "c"(_Rm), "a"(_Rn));
1871 static void dsp_opcode_bset(void)
1879 GCC on WIN32 (more importantly mingw) doesn't know the declared
1880 variables in asm until we put a _ before it.
1882 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
1895 : "c"(_Rm), "a"(_Rn));
1907 : "c"(_Rm), "a"(_Rn));
1926 static void dsp_opcode_subqt(void)
1928 Rn -= dsp_convert_zero[imm_1];
1931 static void dsp_opcode_addqt(void)
1933 Rn += dsp_convert_zero[imm_1];
1936 static void dsp_opcode_imacn(void)
1938 uint32 res=((int16)Rm) * ((int16)(Rn));
1942 static void dsp_opcode_mtoi(void)
1945 uint32 res=Rn=(((INT32)_Rm >> 8) & 0xff800000) | (_Rm & 0x007fffff);
1950 static void dsp_opcode_normi(void)
1957 while ((_Rm & 0xffc00000) == 0)
1962 while ((_Rm & 0xff800000) != 0)
1973 static void dsp_opcode_mmult(void)
1975 int count = dsp_matrix_control&0x0f;
1976 uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
1980 if (!(dsp_matrix_control & 0x10))
1982 for (int i = 0; i < count; i++)
1986 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
1988 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
1989 int16 b=((int16)dsp_word_read(addr+2));
1996 for (int i = 0; i < count; i++)
2000 a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
2002 a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
2003 int16 b=((int16)dsp_word_read(addr+2));
2008 Rn = res = (int32)accum;
2014 static void dsp_opcode_abs(void)
2019 if (_Rn==0x80000000)
2025 dsp_flag_c = ((_Rn&0x80000000)>>31);
2026 res= Rn = (_Rn & 0x80000000) ? -_Rn : _Rn;
2032 static void dsp_opcode_div(void)
2039 if (dsp_div_control & 1)
2041 dsp_remain = (((uint64)_Rn) << 16) % _Rm;
2042 if (dsp_remain&0x80000000)
2044 Rn = (((uint64)_Rn) << 16) / _Rm;
2048 dsp_remain = _Rn % _Rm;
2049 if (dsp_remain&0x80000000)
2058 static void dsp_opcode_imultn(void)
2060 uint32 res=(int32)(((int16)Rn)*((int16)Rm));
2066 static void dsp_opcode_neg(void)
2073 GCC on WIN32 (more importantly mingw) doesn't know the declared
2074 variables in asm until we put a _ before it.
2076 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2090 : "d"(_Rn), "a"(0));
2103 : "d"(_Rn), "a"(0));
2122 static void dsp_opcode_shlq(void)
2124 uint32 shift=(32-dsp_convert_zero[imm_1]);
2130 GCC on WIN32 (more importantly mingw) doesn't know the declared
2131 variables in asm until we put a _ before it.
2133 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2139 "testl $0x80000000, %2
2148 : "c"(shift), "a"(_Rn));
2153 "testl $0x80000000, %2
2162 : "c"(shift), "a"(_Rn));
2183 static void dsp_opcode_shrq(void)
2185 uint32 shift=dsp_convert_zero[imm_1];
2192 GCC on WIN32 (more importantly mingw) doesn't know the declared
2193 variables in asm until we put a _ before it.
2195 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2201 "testl $0x00000001, %2
2210 : "c"(shift), "a"(_Rn));
2215 "testl $0x00000001, %2
2224 : "c"(shift), "a"(_Rn));
2245 static void dsp_opcode_ror(void)
2253 GCC on WIN32 (more importantly mingw) doesn't know the declared
2254 variables in asm until we put a _ before it.
2256 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2262 "testl $0x80000000, %2
2271 : "c"(shift), "a"(_Rn));
2276 "testl $0x80000000, %2
2285 : "c"(shift), "a"(_Rn));
2306 static void dsp_opcode_rorq(void)
2308 uint32 shift=dsp_convert_zero[imm_1&0x1f];
2314 GCC on WIN32 (more importantly mingw) doesn't know the declared
2315 variables in asm until we put a _ before it.
2317 So the declaration dsp_flag_c needs to be _dsp_flag_c on mingw.
2323 "testl $0x80000000, %2
2332 : "c"(shift), "a"(_Rn));
2337 "testl $0x80000000, %2
2346 : "c"(shift), "a"(_Rn));
2367 static void dsp_opcode_sha(void)
2369 int32 sRm=(int32)Rm;
2375 if (shift>=32) shift=32;
2376 dsp_flag_c=(_Rn&0x80000000)>>31;
2386 if (shift>=32) shift=32;
2390 _Rn=((int32)_Rn)>>1;
2399 static void dsp_opcode_sharq(void)
2401 uint32 shift=dsp_convert_zero[imm_1];
2404 dsp_flag_c = (_Rn & 0x1);
2407 _Rn=((int32)_Rn)>>1;
2415 static void dsp_opcode_sh(void)
2417 int32 sRm=(int32)Rm;
2422 uint32 shift=(-sRm);
2423 if (shift>=32) shift=32;
2424 dsp_flag_c=(_Rn&0x80000000)>>31;
2434 if (shift>=32) shift=32;
2447 #define CLR_ZN { dsp_flag_n=0; dsp_flag_z=0; };
2448 #define CLR_ZNC { dsp_flag_c=0; dsp_flag_n=0; dsp_flag_z=0; };
2449 #define SET_Z(r) (dsp_flag_z= ((r) == 0))
2450 #define SET_C_ADD(a,b) (dsp_flag_c= ((UINT32)(b) > (UINT32)(~(a))) << 1)
2451 #define SET_C_SUB(a,b) (dsp_flag_c= ((UINT32)(b) > (UINT32)(a)) << 1)
2452 #define SET_N(r) (dsp_flag_n= (((UINT32)(r) >> 29) & 4))
2453 #define SET_ZN(r) SET_N(r); SET_Z(r)
2454 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
2455 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
2457 void dsp_opcode_addqmod(void)
2459 UINT32 r1 = dsp_convert_zero[imm_1];
2461 UINT32 res = r2 + r1;
2462 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2464 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);
2466 void dsp_opcode_subqmod(void)
2468 UINT32 r1 = dsp_convert_zero[imm_1];
2470 UINT32 res = r2 - r1;
2471 res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
2474 SET_ZNC_SUB(r2,r1,res);
2476 void dsp_opcode_mirror(void)
2479 UINT32 res = (mirror_table[r1 & 0xffff] << 16) | mirror_table[r1 >> 16];
2481 CLR_ZN; SET_ZN(res);
2483 void dsp_opcode_sat32s(void)
2485 INT32 r2 = (UINT32)Rn;
2486 INT32 temp = dsp_acc >> 32;
2487 UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7fffffff : r2;
2489 CLR_ZN; SET_ZN(res);
2491 void dsp_opcode_sat16s(void)
2494 UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
2496 CLR_ZN; SET_ZN(res);