1 /*###################################################################################################
2 **
3 **
4 ** jaguar.c
5 ** Core implementation for the portable Jaguar DSP emulator.
6 ** Written by Aaron Giles
7 **
8 **
9 **#################################################################################################*/
10
11 #include <stdio.h>
12 #include <stddef.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include "driver.h"
16 #include "mamedbg.h"
17 #include "state.h"
18 #include "jaguar.h"
19
20
21 /*###################################################################################################
22 ** CONSTANTS
23 **#################################################################################################*/
24
25 #define ZFLAG 0x00001
26 #define CFLAG 0x00002
27 #define NFLAG 0x00004
28 #define IFLAG 0x00008
29 #define EINT0FLAG 0x00010
30 #define EINT1FLAG 0x00020
31 #define EINT2FLAG 0x00040
32 #define EINT3FLAG 0x00080
33 #define EINT4FLAG 0x00100
34 #define EINT04FLAGS (EINT0FLAG | EINT1FLAG | EINT2FLAG | EINT3FLAG | EINT4FLAG)
35 #define CINT0FLAG 0x00200
36 #define CINT1FLAG 0x00400
37 #define CINT2FLAG 0x00800
38 #define CINT3FLAG 0x01000
39 #define CINT4FLAG 0x02000
40 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
41 #define RPAGEFLAG 0x04000
42 #define DMAFLAG 0x08000
43 #define EINT5FLAG 0x10000 /* DSP only */
44 #define CINT5FLAG 0x20000 /* DSP only */
45
46 #define CLR_Z (jaguar.FLAGS &= ~ZFLAG)
47 #define CLR_ZN (jaguar.FLAGS &= ~(ZFLAG | NFLAG))
48 #define CLR_ZNC (jaguar.FLAGS &= ~(CFLAG | ZFLAG | NFLAG))
49 #define SET_Z(r) (jaguar.FLAGS |= ((r) == 0))
50 #define SET_C_ADD(a,b) (jaguar.FLAGS |= ((UINT32)(b) > (UINT32)(~(a))) << 1)
51 #define SET_C_SUB(a,b) (jaguar.FLAGS |= ((UINT32)(b) > (UINT32)(a)) << 1)
52 #define SET_N(r) (jaguar.FLAGS |= (((UINT32)(r) >> 29) & 4))
53 #define SET_ZN(r) SET_N(r); SET_Z(r)
54 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
55 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
56
57
58
59 /*###################################################################################################
60 ** MACROS
61 **#################################################################################################*/
62
63 #define PC ctrl[G_PC]
64 #define FLAGS ctrl[G_FLAGS]
65
66 #define CONDITION(x) condition_table[(x) + ((jaguar.FLAGS & 7) << 5)]
67
68 #define READBYTE(a) cpu_readmem24bedw(a)
69 #define READWORD(a) cpu_readmem24bedw_word(a)
70 #define READLONG(a) cpu_readmem24bedw_dword(a)
71
72 #define WRITEBYTE(a,v) cpu_writemem24bedw(a,v)
73 #define WRITEWORD(a,v) cpu_writemem24bedw_word(a,v)
74 #define WRITELONG(a,v) cpu_writemem24bedw_dword(a,v)
75
76
77
78 /*###################################################################################################
79 ** STRUCTURES & TYPEDEFS
80 **#################################################################################################*/
81
82 /* Jaguar Registers */
83 typedef struct
84 {
85 /* core registers */
86 UINT32 r[32];
87 UINT32 a[32];
88 UINT32 * b0;
89 UINT32 * b1;
90
91 /* control registers */
92 UINT32 ctrl[G_CTRLMAX];
93 UINT32 ppc;
94 UINT64 accum;
95
96 /* internal stuff */
97 int isdsp;
98 int op;
99 int interrupt_cycles;
100 void (**table)(void);
101 int (*irq_callback)(int irqline);
102 void (*cpu_interrupt)(void);
103 } jaguar_regs;
104
105
106
107 /*###################################################################################################
108 ** PUBLIC GLOBAL VARIABLES
109 **#################################################################################################*/
110
111 int jaguar_icount;
112 static int bankswitch_icount;
113
114
115
116 /*###################################################################################################
117 ** PRIVATE GLOBAL VARIABLES
118 **#################################################################################################*/
119
120 static jaguar_regs jaguar;
121 static UINT16 * mirror_table;
122 static UINT8 * condition_table;
123 static int executing_cpu = -1;
124
125 static const UINT32 convert_zero[32] =
126 { 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 };
127
128
129
130 /*###################################################################################################
131 ** FUNCTION TABLES
132 **#################################################################################################*/
133
134 static void abs_rn(void);
135 static void add_rn_rn(void);
136 static void addc_rn_rn(void);
137 static void addq_n_rn(void);
138 static void addqmod_n_rn(void); /* DSP only */
139 static void addqt_n_rn(void);
140 static void and_rn_rn(void);
141 static void bclr_n_rn(void);
142 static void bset_n_rn(void);
143 static void btst_n_rn(void);
144 static void cmp_rn_rn(void);
145 static void cmpq_n_rn(void);
146 static void div_rn_rn(void);
147 static void illegal(void);
148 static void imacn_rn_rn(void);
149 static void imult_rn_rn(void);
150 static void imultn_rn_rn(void);
151 static void jr_cc_n(void);
152 static void jump_cc_rn(void);
153 static void load_rn_rn(void);
154 static void load_r14n_rn(void);
155 static void load_r15n_rn(void);
156 static void load_r14rn_rn(void);
157 static void load_r15rn_rn(void);
158 static void loadb_rn_rn(void);
159 static void loadw_rn_rn(void);
160 static void loadp_rn_rn(void); /* GPU only */
161 static void mirror_rn(void); /* DSP only */
162 static void mmult_rn_rn(void);
163 static void move_rn_rn(void);
164 static void move_pc_rn(void);
165 static void movefa_rn_rn(void);
166 static void movei_n_rn(void);
167 static void moveq_n_rn(void);
168 static void moveta_rn_rn(void);
169 static void mtoi_rn_rn(void);
170 static void mult_rn_rn(void);
171 static void neg_rn(void);
172 static void nop(void);
173 static void normi_rn_rn(void);
174 static void not_rn(void);
175 static void or_rn_rn(void);
176 static void pack_rn(void); /* GPU only */
177 static void resmac_rn(void);
178 static void ror_rn_rn(void);
179 static void rorq_n_rn(void);
180 static void sat8_rn(void); /* GPU only */
181 static void sat16_rn(void); /* GPU only */
182 static void sat16s_rn(void); /* DSP only */
183 static void sat24_rn(void); /* GPU only */
184 static void sat32s_rn(void); /* DSP only */
185 static void sh_rn_rn(void);
186 static void sha_rn_rn(void);
187 static void sharq_n_rn(void);
188 static void shlq_n_rn(void);
189 static void shrq_n_rn(void);
190 static void store_rn_rn(void);
191 static void store_rn_r14n(void);
192 static void store_rn_r15n(void);
193 static void store_rn_r14rn(void);
194 static void store_rn_r15rn(void);
195 static void storeb_rn_rn(void);
196 static void storew_rn_rn(void);
197 static void storep_rn_rn(void); /* GPU only */
198 static void sub_rn_rn(void);
199 static void subc_rn_rn(void);
200 static void subq_n_rn(void);
201 static void subqmod_n_rn(void); /* DSP only */
202 static void subqt_n_rn(void);
203 static void xor_rn_rn(void);
204
205 static void (*gpu_op_table[64])(void) =
206 {
207 /* 00-03 */ add_rn_rn, addc_rn_rn, addq_n_rn, addqt_n_rn,
208 /* 04-07 */ sub_rn_rn, subc_rn_rn, subq_n_rn, subqt_n_rn,
209 /* 08-11 */ neg_rn, and_rn_rn, or_rn_rn, xor_rn_rn,
210 /* 12-15 */ not_rn, btst_n_rn, bset_n_rn, bclr_n_rn,
211 /* 16-19 */ mult_rn_rn, imult_rn_rn, imultn_rn_rn, resmac_rn,
212 /* 20-23 */ imacn_rn_rn, div_rn_rn, abs_rn, sh_rn_rn,
213 /* 24-27 */ shlq_n_rn, shrq_n_rn, sha_rn_rn, sharq_n_rn,
214 /* 28-31 */ ror_rn_rn, rorq_n_rn, cmp_rn_rn, cmpq_n_rn,
215 /* 32-35 */ sat8_rn, sat16_rn, move_rn_rn, moveq_n_rn,
216 /* 36-39 */ moveta_rn_rn, movefa_rn_rn, movei_n_rn, loadb_rn_rn,
217 /* 40-43 */ loadw_rn_rn, load_rn_rn, loadp_rn_rn, load_r14n_rn,
218 /* 44-47 */ load_r15n_rn, storeb_rn_rn, storew_rn_rn, store_rn_rn,
219 /* 48-51 */ storep_rn_rn, store_rn_r14n, store_rn_r15n, move_pc_rn,
220 /* 52-55 */ jump_cc_rn, jr_cc_n, mmult_rn_rn, mtoi_rn_rn,
221 /* 56-59 */ normi_rn_rn, nop, load_r14rn_rn, load_r15rn_rn,
222 /* 60-63 */ store_rn_r14rn, store_rn_r15rn, sat24_rn, pack_rn
223 };
224
225 static void (*dsp_op_table[64])(void) =
226 {
227 /* 00-03 */ add_rn_rn, addc_rn_rn, addq_n_rn, addqt_n_rn,
228 /* 04-07 */ sub_rn_rn, subc_rn_rn, subq_n_rn, subqt_n_rn,
229 /* 08-11 */ neg_rn, and_rn_rn, or_rn_rn, xor_rn_rn,
230 /* 12-15 */ not_rn, btst_n_rn, bset_n_rn, bclr_n_rn,
231 /* 16-19 */ mult_rn_rn, imult_rn_rn, imultn_rn_rn, resmac_rn,
232 /* 20-23 */ imacn_rn_rn, div_rn_rn, abs_rn, sh_rn_rn,
233 /* 24-27 */ shlq_n_rn, shrq_n_rn, sha_rn_rn, sharq_n_rn,
234 /* 28-31 */ ror_rn_rn, rorq_n_rn, cmp_rn_rn, cmpq_n_rn,
235 /* 32-35 */ subqmod_n_rn, sat16s_rn, move_rn_rn, moveq_n_rn,
236 /* 36-39 */ moveta_rn_rn, movefa_rn_rn, movei_n_rn, loadb_rn_rn,
237 /* 40-43 */ loadw_rn_rn, load_rn_rn, sat32s_rn, load_r14n_rn,
238 /* 44-47 */ load_r15n_rn, storeb_rn_rn, storew_rn_rn, store_rn_rn,
239 /* 48-51 */ mirror_rn, store_rn_r14n, store_rn_r15n, move_pc_rn,
240 /* 52-55 */ jump_cc_rn, jr_cc_n, mmult_rn_rn, mtoi_rn_rn,
241 /* 56-59 */ normi_rn_rn, nop, load_r14rn_rn, load_r15rn_rn,
242 /* 60-63 */ store_rn_r14rn, store_rn_r15rn, illegal, addqmod_n_rn
243 };
244
245
246
247 /*###################################################################################################
248 ** MEMORY ACCESSORS
249 **#################################################################################################*/
250
251 #ifdef MSB_FIRST
252 #define ROPCODE(pc) (*(UINT16 *)&OP_ROM[(UINT32)(pc)])
253 #else
254 #define ROPCODE(pc) (*(UINT16 *)&OP_ROM[(UINT32)(pc) ^ 2])
255 #endif
256
257
258
259 /*###################################################################################################
260 ** INLINES
261 **#################################################################################################*/
262
update_register_banks(void)263 static INLINE void update_register_banks(void)
264 {
265 UINT32 temp;
266 int i, bank;
267
268 /* pick the bank */
269 bank = jaguar.FLAGS & RPAGEFLAG;
270 if (jaguar.FLAGS & IFLAG) bank = 0;
271
272 /* do we need to swap? */
273 if ((!bank && jaguar.b0 != jaguar.r) || (bank && jaguar.b1 != jaguar.r))
274 {
275 /* remember the icount of the instruction after we swap */
276 bankswitch_icount = jaguar_icount - 1;
277
278 /* exchange the contents */
279 for (i = 0; i < 32; i++)
280 temp = jaguar.r[i], jaguar.r[i] = jaguar.a[i], jaguar.a[i] = temp;
281
282 /* swap the bank pointers */
283 if (!bank)
284 {
285 jaguar.b0 = jaguar.r;
286 jaguar.b1 = jaguar.a;
287 }
288 else
289 {
290 jaguar.b0 = jaguar.a;
291 jaguar.b1 = jaguar.r;
292 }
293 }
294 }
295
296
297
298 /*###################################################################################################
299 ** IRQ HANDLING
300 **#################################################################################################*/
301
check_irqs(void)302 static void check_irqs(void)
303 {
304 int bits, mask, which = 0;
305
306 /* if the IMASK is set, bail */
307 if (jaguar.FLAGS & IFLAG)
308 return;
309
310 /* get the active interrupt bits */
311 bits = (jaguar.ctrl[G_CTRL] >> 6) & 0x1f;
312 bits |= (jaguar.ctrl[G_CTRL] >> 10) & 0x20;
313
314 /* get the interrupt mask */
315 mask = (jaguar.FLAGS >> 4) & 0x1f;
316 mask |= (jaguar.FLAGS >> 11) & 0x20;
317
318 /* bail if nothing is available */
319 bits &= mask;
320 if (!bits)
321 return;
322
323 /* determine which interrupt */
324 if (bits & 0x01) which = 0;
325 if (bits & 0x02) which = 1;
326 if (bits & 0x04) which = 2;
327 if (bits & 0x08) which = 3;
328 if (bits & 0x10) which = 4;
329 if (bits & 0x20) which = 5;
330
331 /* set the interrupt flag */
332 jaguar.FLAGS |= IFLAG;
333 update_register_banks();
334
335 /* push the PC-2 on the stack */
336 jaguar.r[31] -= 4;
337 WRITELONG(jaguar.r[31], jaguar.PC - 2);
338
339 /* dispatch */
340 jaguar.PC = (jaguar.isdsp) ? 0xf1b000 : 0xf03000;
341 jaguar.PC += which * 0x10;
342 change_pc24bedw(jaguar.PC);
343 }
344
345
jaguargpu_set_irq_line(int irqline,int state)346 void jaguargpu_set_irq_line(int irqline, int state)
347 {
348 int mask = 0x40 << irqline;
349 jaguar.ctrl[G_CTRL] &= ~mask;
350 if (state != CLEAR_LINE)
351 {
352 jaguar.ctrl[G_CTRL] |= mask;
353 check_irqs();
354 }
355 }
356
jaguardsp_set_irq_line(int irqline,int state)357 void jaguardsp_set_irq_line(int irqline, int state)
358 {
359 int mask = (irqline < 5) ? (0x40 << irqline) : 0x10000;
360 jaguar.ctrl[G_CTRL] &= ~mask;
361 if (state != CLEAR_LINE)
362 {
363 jaguar.ctrl[G_CTRL] |= mask;
364 check_irqs();
365 }
366 }
367
368
jaguargpu_set_irq_callback(int (* callback)(int irqline))369 void jaguargpu_set_irq_callback(int (*callback)(int irqline))
370 {
371 jaguar.irq_callback = callback;
372 }
373
jaguardsp_set_irq_callback(int (* callback)(int irqline))374 void jaguardsp_set_irq_callback(int (*callback)(int irqline))
375 {
376 jaguar.irq_callback = callback;
377 }
378
379
380
381 /*###################################################################################################
382 ** CONTEXT SWITCHING
383 **#################################################################################################*/
384
jaguargpu_get_context(void * dst)385 unsigned jaguargpu_get_context(void *dst)
386 {
387 /* copy the context */
388 if (dst)
389 *(jaguar_regs *)dst = jaguar;
390
391 /* return the context size */
392 return sizeof(jaguar_regs);
393 }
394
jaguardsp_get_context(void * dst)395 unsigned jaguardsp_get_context(void *dst)
396 {
397 /* copy the context */
398 if (dst)
399 *(jaguar_regs *)dst = jaguar;
400
401 /* return the context size */
402 return sizeof(jaguar_regs);
403 }
404
405
jaguargpu_set_context(void * src)406 void jaguargpu_set_context(void *src)
407 {
408 /* copy the context */
409 if (src)
410 jaguar = *(jaguar_regs *)src;
411
412 /* check for IRQs */
413 check_irqs();
414 }
415
jaguardsp_set_context(void * src)416 void jaguardsp_set_context(void *src)
417 {
418 /* copy the context */
419 if (src)
420 jaguar = *(jaguar_regs *)src;
421
422 /* check for IRQs */
423 check_irqs();
424 }
425
426
427 /*###################################################################################################
428 ** INITIALIZATION AND SHUTDOWN
429 **#################################################################################################*/
430
init_tables(void)431 static void init_tables(void)
432 {
433 int i, j;
434
435 /* allocate the mirror table */
436 if (!mirror_table)
437 mirror_table = malloc(65536 * sizeof(mirror_table[0]));
438
439 /* fill in the mirror table */
440 if (mirror_table)
441 for (i = 0; i < 65536; i++)
442 mirror_table[i] = ((i >> 15) & 0x0001) | ((i >> 13) & 0x0002) |
443 ((i >> 11) & 0x0004) | ((i >> 9) & 0x0008) |
444 ((i >> 7) & 0x0010) | ((i >> 5) & 0x0020) |
445 ((i >> 3) & 0x0040) | ((i >> 1) & 0x0080) |
446 ((i << 1) & 0x0100) | ((i << 3) & 0x0200) |
447 ((i << 5) & 0x0400) | ((i << 7) & 0x0800) |
448 ((i << 9) & 0x1000) | ((i << 11) & 0x2000) |
449 ((i << 13) & 0x4000) | ((i << 15) & 0x8000);
450
451 /* allocate the condition table */
452 if (!condition_table)
453 condition_table = malloc(32 * 8 * sizeof(condition_table[0]));
454
455 /* fill in the condition table */
456 if (condition_table)
457 for (i = 0; i < 8; i++)
458 for (j = 0; j < 32; j++)
459 {
460 int result = 1;
461 if (j & 1)
462 if (i & ZFLAG) result = 0;
463 if (j & 2)
464 if (!(i & ZFLAG)) result = 0;
465 if (j & 4)
466 if (i & (CFLAG << (j >> 4))) result = 0;
467 if (j & 8)
468 if (!(i & (CFLAG << (j >> 4)))) result = 0;
469 condition_table[i * 32 + j] = result;
470 }
471 }
472
jaguar_state_register(const char * type)473 static void jaguar_state_register(const char *type)
474 {
475 int cpu = cpu_getactivecpu();
476 state_save_register_UINT32(type, cpu, "R", jaguar.r, 32);
477 state_save_register_UINT32(type, cpu, "A", jaguar.a, 32);
478 state_save_register_UINT32(type, cpu, "CTRL", jaguar.ctrl, G_CTRLMAX);
479 state_save_register_UINT32(type, cpu, "PPC", &jaguar.ppc, 1);
480 state_save_register_func_postload(update_register_banks);
481 state_save_register_func_postload(check_irqs);
482 }
483
jaguargpu_init(void)484 void jaguargpu_init(void)
485 {
486 jaguar_state_register("jaguargpu");
487 }
488
jaguardsp_init(void)489 void jaguardsp_init(void)
490 {
491 jaguar_state_register("jaguardsp");
492 }
493
common_reset(struct jaguar_config * config)494 static INLINE void common_reset(struct jaguar_config *config)
495 {
496 init_tables();
497
498 if (config)
499 jaguar.cpu_interrupt = config->cpu_int_callback;
500
501 jaguar.b0 = jaguar.r;
502 jaguar.b1 = jaguar.a;
503
504 change_pc24bedw(jaguar.PC);
505 }
506
jaguargpu_reset(void * param)507 void jaguargpu_reset(void *param)
508 {
509 common_reset(param);
510 jaguar.table = gpu_op_table;
511 jaguar.isdsp = 0;
512 }
513
jaguardsp_reset(void * param)514 void jaguardsp_reset(void *param)
515 {
516 common_reset(param);
517 jaguar.table = dsp_op_table;
518 jaguar.isdsp = 1;
519 }
520
common_exit(void)521 static INLINE void common_exit(void)
522 {
523 if (mirror_table)
524 free(mirror_table);
525 mirror_table = NULL;
526
527 if (condition_table)
528 free(condition_table);
529 condition_table = NULL;
530 }
531
jaguargpu_exit(void)532 void jaguargpu_exit(void)
533 {
534 common_exit();
535 }
536
jaguardsp_exit(void)537 void jaguardsp_exit(void)
538 {
539 common_exit();
540 }
541
542
543
544 /*###################################################################################################
545 ** CORE EXECUTION LOOP
546 **#################################################################################################*/
547
jaguargpu_execute(int cycles)548 int jaguargpu_execute(int cycles)
549 {
550 /* if we're halted, we shouldn't be here */
551 if (!(jaguar.ctrl[G_CTRL] & 1))
552 {
553 cpu_set_halt_line(cpu_getactivecpu(), ASSERT_LINE);
554 return cycles;
555 }
556
557 /* count cycles and interrupt cycles */
558 bankswitch_icount = -1000;
559 jaguar_icount = cycles;
560 jaguar_icount -= jaguar.interrupt_cycles;
561 jaguar.interrupt_cycles = 0;
562 change_pc24bedw(jaguar.PC);
563
564 /* remember that we're executing */
565 executing_cpu = cpu_getactivecpu();
566
567 /* core execution loop */
568 do
569 {
570 /* debugging */
571 /*if (jaguar.PC < 0xf03000 || jaguar.PC > 0xf04000) { fprintf(stderr, "GPU: jaguar.PC = %06X (ppc = %06X)\n", jaguar.PC, jaguar.ppc); exit(1); }*/
572 jaguar.ppc = jaguar.PC;
573 CALL_MAME_DEBUG;
574
575 /* instruction fetch */
576 jaguar.op = ROPCODE(jaguar.PC);
577 jaguar.PC += 2;
578
579 /* parse the instruction */
580 (*gpu_op_table[jaguar.op >> 10])();
581 jaguar_icount--;
582
583 } while (jaguar_icount > 0 || jaguar_icount == bankswitch_icount);
584
585 /* no longer executing */
586 executing_cpu = -1;
587
588 /* adjust cycles for interrupts */
589 jaguar_icount -= jaguar.interrupt_cycles;
590 jaguar.interrupt_cycles = 0;
591 return cycles - jaguar_icount;
592 }
593
jaguardsp_execute(int cycles)594 int jaguardsp_execute(int cycles)
595 {
596 /* if we're halted, we shouldn't be here */
597 if (!(jaguar.ctrl[G_CTRL] & 1))
598 {
599 cpu_set_halt_line(cpu_getactivecpu(), ASSERT_LINE);
600 return cycles;
601 }
602
603 /* count cycles and interrupt cycles */
604 bankswitch_icount = -1000;
605 jaguar_icount = cycles;
606 jaguar_icount -= jaguar.interrupt_cycles;
607 jaguar.interrupt_cycles = 0;
608 change_pc24bedw(jaguar.PC);
609
610 /* remember that we're executing */
611 executing_cpu = cpu_getactivecpu();
612
613 /* core execution loop */
614 do
615 {
616 /* debugging */
617 /*if (jaguar.PC < 0xf1b000 || jaguar.PC > 0xf1d000) { fprintf(stderr, "DSP: jaguar.PC = %06X\n", jaguar.PC); exit(1); }*/
618 jaguar.ppc = jaguar.PC;
619 CALL_MAME_DEBUG;
620
621 /* instruction fetch */
622 jaguar.op = ROPCODE(jaguar.PC);
623 jaguar.PC += 2;
624
625 /* parse the instruction */
626 (*dsp_op_table[jaguar.op >> 10])();
627 jaguar_icount--;
628
629 } while (jaguar_icount > 0 || jaguar_icount == bankswitch_icount);
630
631 /* no longer executing */
632 executing_cpu = -1;
633
634 /* adjust cycles for interrupts */
635 jaguar_icount -= jaguar.interrupt_cycles;
636 jaguar.interrupt_cycles = 0;
637 return cycles - jaguar_icount;
638 }
639
640
641
642 /*###################################################################################################
643 ** REGISTER SNOOP
644 **#################################################################################################*/
645
common_get_reg(int regnum)646 static INLINE unsigned common_get_reg(int regnum)
647 {
648 switch (regnum)
649 {
650 case REG_PC:
651 case JAGUAR_PC: return jaguar.PC;
652 case JAGUAR_FLAGS: return jaguar.FLAGS;
653
654 case JAGUAR_R0: return jaguar.r[0];
655 case JAGUAR_R1: return jaguar.r[1];
656 case JAGUAR_R2: return jaguar.r[2];
657 case JAGUAR_R3: return jaguar.r[3];
658 case JAGUAR_R4: return jaguar.r[4];
659 case JAGUAR_R5: return jaguar.r[5];
660 case JAGUAR_R6: return jaguar.r[6];
661 case JAGUAR_R7: return jaguar.r[7];
662 case JAGUAR_R8: return jaguar.r[8];
663 case JAGUAR_R9: return jaguar.r[9];
664 case JAGUAR_R10: return jaguar.r[10];
665 case JAGUAR_R11: return jaguar.r[11];
666 case JAGUAR_R12: return jaguar.r[12];
667 case JAGUAR_R13: return jaguar.r[13];
668 case JAGUAR_R14: return jaguar.r[14];
669 case JAGUAR_R15: return jaguar.r[15];
670 case JAGUAR_R16: return jaguar.r[16];
671 case JAGUAR_R17: return jaguar.r[17];
672 case JAGUAR_R18: return jaguar.r[18];
673 case JAGUAR_R19: return jaguar.r[19];
674 case JAGUAR_R20: return jaguar.r[20];
675 case JAGUAR_R21: return jaguar.r[21];
676 case JAGUAR_R22: return jaguar.r[22];
677 case JAGUAR_R23: return jaguar.r[23];
678 case JAGUAR_R24: return jaguar.r[24];
679 case JAGUAR_R25: return jaguar.r[25];
680 case JAGUAR_R26: return jaguar.r[26];
681 case JAGUAR_R27: return jaguar.r[27];
682 case JAGUAR_R28: return jaguar.r[28];
683 case JAGUAR_R29: return jaguar.r[29];
684 case JAGUAR_R30: return jaguar.r[30];
685 case JAGUAR_R31: return jaguar.r[31];
686 case REG_SP: return jaguar.b0[31];
687
688 case REG_PREVIOUSPC: return jaguar.ppc;
689
690 default:
691 if (regnum <= REG_SP_CONTENTS)
692 {
693 /* unsigned offset = REG_SP_CONTENTS - regnum;*/
694 /* if (offset < PC_STACK_DEPTH)*/
695 /* return jaguar.pc_stack[offset];*/
696 }
697 }
698 return 0;
699 }
700
jaguargpu_get_reg(int regnum)701 unsigned jaguargpu_get_reg(int regnum)
702 {
703 return common_get_reg(regnum);
704 }
705
jaguardsp_get_reg(int regnum)706 unsigned jaguardsp_get_reg(int regnum)
707 {
708 return common_get_reg(regnum);
709 }
710
711
712
713 /*###################################################################################################
714 ** REGISTER MODIFY
715 **#################################################################################################*/
716
common_set_reg(int regnum,unsigned val)717 static INLINE void common_set_reg(int regnum, unsigned val)
718 {
719 switch (regnum)
720 {
721 case REG_PC:
722 case JAGUAR_PC: jaguar.PC = val; break;
723 case JAGUAR_FLAGS: jaguar.FLAGS = val; break;
724
725 case JAGUAR_R0: jaguar.r[0] = val; break;
726 case JAGUAR_R1: jaguar.r[1] = val; break;
727 case JAGUAR_R2: jaguar.r[2] = val; break;
728 case JAGUAR_R3: jaguar.r[3] = val; break;
729 case JAGUAR_R4: jaguar.r[4] = val; break;
730 case JAGUAR_R5: jaguar.r[5] = val; break;
731 case JAGUAR_R6: jaguar.r[6] = val; break;
732 case JAGUAR_R7: jaguar.r[7] = val; break;
733 case JAGUAR_R8: jaguar.r[8] = val; break;
734 case JAGUAR_R9: jaguar.r[9] = val; break;
735 case JAGUAR_R10: jaguar.r[10] = val; break;
736 case JAGUAR_R11: jaguar.r[11] = val; break;
737 case JAGUAR_R12: jaguar.r[12] = val; break;
738 case JAGUAR_R13: jaguar.r[13] = val; break;
739 case JAGUAR_R14: jaguar.r[14] = val; break;
740 case JAGUAR_R15: jaguar.r[15] = val; break;
741 case JAGUAR_R16: jaguar.r[16] = val; break;
742 case JAGUAR_R17: jaguar.r[17] = val; break;
743 case JAGUAR_R18: jaguar.r[18] = val; break;
744 case JAGUAR_R19: jaguar.r[19] = val; break;
745 case JAGUAR_R20: jaguar.r[20] = val; break;
746 case JAGUAR_R21: jaguar.r[21] = val; break;
747 case JAGUAR_R22: jaguar.r[22] = val; break;
748 case JAGUAR_R23: jaguar.r[23] = val; break;
749 case JAGUAR_R24: jaguar.r[24] = val; break;
750 case JAGUAR_R25: jaguar.r[25] = val; break;
751 case JAGUAR_R26: jaguar.r[26] = val; break;
752 case JAGUAR_R27: jaguar.r[27] = val; break;
753 case JAGUAR_R28: jaguar.r[28] = val; break;
754 case JAGUAR_R29: jaguar.r[29] = val; break;
755 case JAGUAR_R30: jaguar.r[30] = val; break;
756 case JAGUAR_R31: jaguar.r[31] = val; break;
757 case REG_SP: jaguar.b0[31] = val; break;
758
759 default:
760 if (regnum <= REG_SP_CONTENTS)
761 {
762 /* unsigned offset = REG_SP_CONTENTS - regnum;*/
763 /* if (offset < PC_STACK_DEPTH)*/
764 /* jaguar.pc_stack[offset] = val;*/
765 }
766 }
767 }
768
jaguargpu_set_reg(int regnum,unsigned val)769 void jaguargpu_set_reg(int regnum, unsigned val)
770 {
771 common_set_reg(regnum, val);
772 }
773
jaguardsp_set_reg(int regnum,unsigned val)774 void jaguardsp_set_reg(int regnum, unsigned val)
775 {
776 common_set_reg(regnum, val);
777 }
778
779
780
781 /*###################################################################################################
782 ** DEBUGGER DEFINITIONS
783 **#################################################################################################*/
784
785 static UINT8 jaguar_reg_layout[] =
786 {
787 JAGUAR_PC, JAGUAR_FLAGS, -1,
788 JAGUAR_R0, JAGUAR_R16, -1,
789 JAGUAR_R1, JAGUAR_R17, -1,
790 JAGUAR_R2, JAGUAR_R18, -1,
791 JAGUAR_R3, JAGUAR_R19, -1,
792 JAGUAR_R4, JAGUAR_R20, -1,
793 JAGUAR_R5, JAGUAR_R21, -1,
794 JAGUAR_R6, JAGUAR_R22, -1,
795 JAGUAR_R7, JAGUAR_R23, -1,
796 JAGUAR_R8, JAGUAR_R24, -1,
797 JAGUAR_R9, JAGUAR_R25, -1,
798 JAGUAR_R10, JAGUAR_R26, -1,
799 JAGUAR_R11, JAGUAR_R27, -1,
800 JAGUAR_R12, JAGUAR_R28, -1,
801 JAGUAR_R13, JAGUAR_R29, -1,
802 JAGUAR_R14, JAGUAR_R30, -1,
803 JAGUAR_R15, JAGUAR_R31, 0
804 };
805
806 static UINT8 jaguar_win_layout[] =
807 {
808 0, 0,30,20, /* register window (top rows) */
809 31, 0,48,14, /* disassembler window (left colums) */
810 0,21,30, 1, /* memory #1 window (right, upper middle) */
811 31,15,48, 7, /* memory #2 window (right, lower middle) */
812 0,23,80, 1, /* command line window (bottom rows) */
813 };
814
815
816
817 /*###################################################################################################
818 ** DEBUGGER STRINGS
819 **#################################################################################################*/
820
common_info(void * context,int regnum)821 static const char *common_info(void *context, int regnum)
822 {
823 static char buffer[16][47+1];
824 static int which = 0;
825 jaguar_regs *r = context;
826
827 which = (which+1) % 16;
828 buffer[which][0] = '\0';
829
830 if (!context)
831 r = &jaguar;
832
833 switch( regnum )
834 {
835 case CPU_INFO_REG+JAGUAR_PC: sprintf(buffer[which], "PC: %08X", r->PC); break;
836
837 case CPU_INFO_REG+JAGUAR_R0: sprintf(buffer[which], "R0: %08X", r->r[0]); break;
838 case CPU_INFO_REG+JAGUAR_R1: sprintf(buffer[which], "R1: %08X", r->r[1]); break;
839 case CPU_INFO_REG+JAGUAR_R2: sprintf(buffer[which], "R2: %08X", r->r[2]); break;
840 case CPU_INFO_REG+JAGUAR_R3: sprintf(buffer[which], "R3: %08X", r->r[3]); break;
841 case CPU_INFO_REG+JAGUAR_R4: sprintf(buffer[which], "R4: %08X", r->r[4]); break;
842 case CPU_INFO_REG+JAGUAR_R5: sprintf(buffer[which], "R5: %08X", r->r[5]); break;
843 case CPU_INFO_REG+JAGUAR_R6: sprintf(buffer[which], "R6: %08X", r->r[6]); break;
844 case CPU_INFO_REG+JAGUAR_R7: sprintf(buffer[which], "R7: %08X", r->r[7]); break;
845 case CPU_INFO_REG+JAGUAR_R8: sprintf(buffer[which], "R8: %08X", r->r[8]); break;
846 case CPU_INFO_REG+JAGUAR_R9: sprintf(buffer[which], "R9: %08X", r->r[9]); break;
847 case CPU_INFO_REG+JAGUAR_R10: sprintf(buffer[which], "R10:%08X", r->r[10]); break;
848 case CPU_INFO_REG+JAGUAR_R11: sprintf(buffer[which], "R11:%08X", r->r[11]); break;
849 case CPU_INFO_REG+JAGUAR_R12: sprintf(buffer[which], "R12:%08X", r->r[12]); break;
850 case CPU_INFO_REG+JAGUAR_R13: sprintf(buffer[which], "R13:%08X", r->r[13]); break;
851 case CPU_INFO_REG+JAGUAR_R14: sprintf(buffer[which], "R14:%08X", r->r[14]); break;
852 case CPU_INFO_REG+JAGUAR_R15: sprintf(buffer[which], "R15:%08X", r->r[15]); break;
853 case CPU_INFO_REG+JAGUAR_R16: sprintf(buffer[which], "R16:%08X", r->r[16]); break;
854 case CPU_INFO_REG+JAGUAR_R17: sprintf(buffer[which], "R17:%08X", r->r[17]); break;
855 case CPU_INFO_REG+JAGUAR_R18: sprintf(buffer[which], "R18:%08X", r->r[18]); break;
856 case CPU_INFO_REG+JAGUAR_R19: sprintf(buffer[which], "R19:%08X", r->r[19]); break;
857 case CPU_INFO_REG+JAGUAR_R20: sprintf(buffer[which], "R20:%08X", r->r[20]); break;
858 case CPU_INFO_REG+JAGUAR_R21: sprintf(buffer[which], "R21:%08X", r->r[21]); break;
859 case CPU_INFO_REG+JAGUAR_R22: sprintf(buffer[which], "R22:%08X", r->r[22]); break;
860 case CPU_INFO_REG+JAGUAR_R23: sprintf(buffer[which], "R23:%08X", r->r[23]); break;
861 case CPU_INFO_REG+JAGUAR_R24: sprintf(buffer[which], "R24:%08X", r->r[24]); break;
862 case CPU_INFO_REG+JAGUAR_R25: sprintf(buffer[which], "R25:%08X", r->r[25]); break;
863 case CPU_INFO_REG+JAGUAR_R26: sprintf(buffer[which], "R26:%08X", r->r[26]); break;
864 case CPU_INFO_REG+JAGUAR_R27: sprintf(buffer[which], "R27:%08X", r->r[27]); break;
865 case CPU_INFO_REG+JAGUAR_R28: sprintf(buffer[which], "R28:%08X", r->r[28]); break;
866 case CPU_INFO_REG+JAGUAR_R29: sprintf(buffer[which], "R29:%08X", r->r[29]); break;
867 case CPU_INFO_REG+JAGUAR_R30: sprintf(buffer[which], "R30:%08X", r->r[30]); break;
868 case CPU_INFO_REG+JAGUAR_R31: sprintf(buffer[which], "R31:%08X", r->r[31]); break;
869
870 case CPU_INFO_REG+JAGUAR_FLAGS: sprintf(buffer[which], "%c%c%c%c%c%c%c%c%c%c%c",
871 r->FLAGS & 0x8000 ? 'D':'.',
872 r->FLAGS & 0x4000 ? 'A':'.',
873 r->FLAGS & 0x0100 ? '4':'.',
874 r->FLAGS & 0x0080 ? '3':'.',
875 r->FLAGS & 0x0040 ? '2':'.',
876 r->FLAGS & 0x0020 ? '1':'.',
877 r->FLAGS & 0x0010 ? '0':'.',
878 r->FLAGS & 0x0008 ? 'I':'.',
879 r->FLAGS & 0x0004 ? 'N':'.',
880 r->FLAGS & 0x0002 ? 'C':'.',
881 r->FLAGS & 0x0001 ? 'Z':'.'); break;
882
883 case CPU_INFO_FAMILY: return "Jaguar";
884 case CPU_INFO_VERSION: return "1.0";
885 case CPU_INFO_FILE: return __FILE__;
886 case CPU_INFO_CREDITS: return "Copyright (C) Aaron Giles 2000-2002";
887 case CPU_INFO_REG_LAYOUT: return (const char *)jaguar_reg_layout;
888 case CPU_INFO_WIN_LAYOUT: return (const char *)jaguar_win_layout;
889 case CPU_INFO_REG+10000: return " ";
890 }
891 return buffer[which];
892 }
893
jaguargpu_info(void * context,int regnum)894 const char *jaguargpu_info(void *context, int regnum)
895 {
896 switch (regnum)
897 {
898 case CPU_INFO_NAME: return "Jaguar GPU";
899 default: return common_info(context, regnum);
900 }
901 }
902
jaguardsp_info(void * context,int regnum)903 const char *jaguardsp_info(void *context, int regnum)
904 {
905 switch (regnum)
906 {
907 case CPU_INFO_NAME: return "Jaguar DSP";
908 default: return common_info(context, regnum);
909 }
910 }
911
912
913
914 /*###################################################################################################
915 ** DISASSEMBLY HOOK
916 **#################################################################################################*/
917
jaguargpu_dasm(char * buffer,unsigned pc)918 unsigned jaguargpu_dasm(char *buffer, unsigned pc)
919 {
920 #ifdef MAME_DEBUG
921 extern unsigned dasmjag(int, char *, unsigned);
922 return dasmjag(JAGUAR_VARIANT_GPU, buffer, pc);
923 #else
924 sprintf(buffer, "$%04X", ROPCODE(pc));
925 return 2;
926 #endif
927 }
928
jaguardsp_dasm(char * buffer,unsigned pc)929 unsigned jaguardsp_dasm(char *buffer, unsigned pc)
930 {
931 #ifdef MAME_DEBUG
932 extern unsigned dasmjag(int, char *, unsigned);
933 return dasmjag(JAGUAR_VARIANT_DSP, buffer, pc);
934 #else
935 sprintf(buffer, "$%04X", ROPCODE(pc));
936 return 2;
937 #endif
938 }
939
940
941
942 /*###################################################################################################
943 ** OPCODES
944 **#################################################################################################*/
945
abs_rn(void)946 void abs_rn(void)
947 {
948 int dreg = jaguar.op & 31;
949 UINT32 res = jaguar.r[dreg];
950 CLR_ZNC;
951 if (res & 0x80000000)
952 {
953 jaguar.r[dreg] = res = -res;
954 jaguar.FLAGS |= CFLAG;
955 }
956 SET_Z(res);
957 }
958
add_rn_rn(void)959 void add_rn_rn(void)
960 {
961 int dreg = jaguar.op & 31;
962 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
963 UINT32 r2 = jaguar.r[dreg];
964 UINT32 res = r2 + r1;
965 jaguar.r[dreg] = res;
966 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);
967 }
968
addc_rn_rn(void)969 void addc_rn_rn(void)
970 {
971 int dreg = jaguar.op & 31;
972 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
973 UINT32 r2 = jaguar.r[dreg];
974 UINT32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
975 jaguar.r[dreg] = res;
976 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);
977 }
978
addq_n_rn(void)979 void addq_n_rn(void)
980 {
981 int dreg = jaguar.op & 31;
982 UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
983 UINT32 r2 = jaguar.r[dreg];
984 UINT32 res = r2 + r1;
985 jaguar.r[dreg] = res;
986 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);
987 }
988
addqmod_n_rn(void)989 void addqmod_n_rn(void) /* DSP only */
990 {
991 int dreg = jaguar.op & 31;
992 UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
993 UINT32 r2 = jaguar.r[dreg];
994 UINT32 res = r2 + r1;
995 res = (res & ~jaguar.ctrl[D_MOD]) | (r2 & ~jaguar.ctrl[D_MOD]);
996 jaguar.r[dreg] = res;
997 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);
998 }
999
addqt_n_rn(void)1000 void addqt_n_rn(void)
1001 {
1002 int dreg = jaguar.op & 31;
1003 UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1004 UINT32 r2 = jaguar.r[dreg];
1005 UINT32 res = r2 + r1;
1006 jaguar.r[dreg] = res;
1007 }
1008
and_rn_rn(void)1009 void and_rn_rn(void)
1010 {
1011 int dreg = jaguar.op & 31;
1012 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1013 UINT32 r2 = jaguar.r[dreg];
1014 UINT32 res = r2 & r1;
1015 jaguar.r[dreg] = res;
1016 CLR_ZN; SET_ZN(res);
1017 }
1018
bclr_n_rn(void)1019 void bclr_n_rn(void)
1020 {
1021 int dreg = jaguar.op & 31;
1022 UINT32 r1 = (jaguar.op >> 5) & 31;
1023 UINT32 r2 = jaguar.r[dreg];
1024 UINT32 res = r2 & ~(1 << r1);
1025 jaguar.r[dreg] = res;
1026 CLR_ZN; SET_ZN(res);
1027 }
1028
bset_n_rn(void)1029 void bset_n_rn(void)
1030 {
1031 int dreg = jaguar.op & 31;
1032 UINT32 r1 = (jaguar.op >> 5) & 31;
1033 UINT32 r2 = jaguar.r[dreg];
1034 UINT32 res = r2 | (1 << r1);
1035 jaguar.r[dreg] = res;
1036 CLR_ZN; SET_ZN(res);
1037 }
1038
btst_n_rn(void)1039 void btst_n_rn(void)
1040 {
1041 UINT32 r1 = (jaguar.op >> 5) & 31;
1042 UINT32 r2 = jaguar.r[jaguar.op & 31];
1043 CLR_Z; jaguar.FLAGS |= (~r2 >> r1) & 1;
1044 }
1045
cmp_rn_rn(void)1046 void cmp_rn_rn(void)
1047 {
1048 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1049 UINT32 r2 = jaguar.r[jaguar.op & 31];
1050 UINT32 res = r2 - r1;
1051 CLR_ZNC; SET_ZNC_SUB(r2,r1,res);
1052 }
1053
cmpq_n_rn(void)1054 void cmpq_n_rn(void)
1055 {
1056 UINT32 r1 = (INT8)(jaguar.op >> 2) >> 3;
1057 UINT32 r2 = jaguar.r[jaguar.op & 31];
1058 UINT32 res = r2 - r1;
1059 CLR_ZNC; SET_ZNC_SUB(r2,r1,res);
1060 }
1061
div_rn_rn(void)1062 void div_rn_rn(void)
1063 {
1064 int dreg = jaguar.op & 31;
1065 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1066 UINT32 r2 = jaguar.r[dreg];
1067 if (r1)
1068 {
1069 if (jaguar.ctrl[D_DIVCTRL] & 1)
1070 {
1071 jaguar.r[dreg] = ((UINT64)r2 << 16) / r1;
1072 jaguar.ctrl[D_REMAINDER] = ((UINT64)r2 << 16) % r1;
1073 }
1074 else
1075 {
1076 jaguar.r[dreg] = r2 / r1;
1077 jaguar.ctrl[D_REMAINDER] = r2 % r1;
1078 }
1079 }
1080 else
1081 jaguar.r[dreg] = 0xffffffff;
1082 }
1083
illegal(void)1084 void illegal(void)
1085 {
1086 }
1087
imacn_rn_rn(void)1088 void imacn_rn_rn(void)
1089 {
1090 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1091 UINT32 r2 = jaguar.r[jaguar.op & 31];
1092 jaguar.accum += (INT64)((INT16)r1 * (INT16)r2);
1093 log_cb(RETRO_LOG_DEBUG, LOGPRE "Unexpected IMACN instruction!\n");
1094 }
1095
imult_rn_rn(void)1096 void imult_rn_rn(void)
1097 {
1098 int dreg = jaguar.op & 31;
1099 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1100 UINT32 r2 = jaguar.r[dreg];
1101 UINT32 res = (INT16)r1 * (INT16)r2;
1102 jaguar.r[dreg] = res;
1103 CLR_ZN; SET_ZN(res);
1104 }
1105
imultn_rn_rn(void)1106 void imultn_rn_rn(void)
1107 {
1108 int dreg = jaguar.op & 31;
1109 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1110 UINT32 r2 = jaguar.r[dreg];
1111 UINT32 res = (INT16)r1 * (INT16)r2;
1112 jaguar.accum = (INT32)res;
1113 CLR_ZN; SET_ZN(res);
1114
1115 jaguar.op = ROPCODE(jaguar.PC);
1116 while ((jaguar.op >> 10) == 20)
1117 {
1118 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1119 r2 = jaguar.r[jaguar.op & 31];
1120 jaguar.accum += (INT64)((INT16)r1 * (INT16)r2);
1121 jaguar.PC += 2;
1122 jaguar.op = ROPCODE(jaguar.PC);
1123 }
1124 if ((jaguar.op >> 10) == 19)
1125 {
1126 jaguar.PC += 2;
1127 jaguar.r[jaguar.op & 31] = (UINT32)jaguar.accum;
1128 }
1129 }
1130
jr_cc_n(void)1131 void jr_cc_n(void)
1132 {
1133 if (CONDITION(jaguar.op & 31))
1134 {
1135 INT32 r1 = (INT8)((jaguar.op >> 2) & 0xf8) >> 2;
1136 UINT32 newpc = jaguar.PC + r1;
1137 CALL_MAME_DEBUG;
1138 jaguar.op = ROPCODE(jaguar.PC);
1139 jaguar.PC = newpc;
1140 (*jaguar.table[jaguar.op >> 10])();
1141
1142 jaguar_icount -= 3; /* 3 wait states guaranteed */
1143 }
1144 }
1145
jump_cc_rn(void)1146 void jump_cc_rn(void)
1147 {
1148 if (CONDITION(jaguar.op & 31))
1149 {
1150 UINT8 reg = (jaguar.op >> 5) & 31;
1151
1152 /* special kludge for risky code in the cojag DSP interrupt handlers */
1153 UINT32 newpc = (jaguar_icount == bankswitch_icount) ? jaguar.a[reg] : jaguar.r[reg];
1154 CALL_MAME_DEBUG;
1155 jaguar.op = ROPCODE(jaguar.PC);
1156 jaguar.PC = newpc;
1157 (*jaguar.table[jaguar.op >> 10])();
1158
1159 jaguar_icount -= 3; /* 3 wait states guaranteed */
1160 }
1161 }
1162
load_rn_rn(void)1163 void load_rn_rn(void)
1164 {
1165 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1166 jaguar.r[jaguar.op & 31] = READLONG(r1);
1167 }
1168
load_r14n_rn(void)1169 void load_r14n_rn(void)
1170 {
1171 UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1172 jaguar.r[jaguar.op & 31] = READLONG(jaguar.r[14] + 4 * r1);
1173 }
1174
load_r15n_rn(void)1175 void load_r15n_rn(void)
1176 {
1177 UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1178 jaguar.r[jaguar.op & 31] = READLONG(jaguar.r[15] + 4 * r1);
1179 }
1180
load_r14rn_rn(void)1181 void load_r14rn_rn(void)
1182 {
1183 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1184 jaguar.r[jaguar.op & 31] = READLONG(jaguar.r[14] + r1);
1185 }
1186
load_r15rn_rn(void)1187 void load_r15rn_rn(void)
1188 {
1189 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1190 jaguar.r[jaguar.op & 31] = READLONG(jaguar.r[15] + r1);
1191 }
1192
loadb_rn_rn(void)1193 void loadb_rn_rn(void)
1194 {
1195 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1196 jaguar.r[jaguar.op & 31] = READBYTE(r1);
1197 }
1198
loadw_rn_rn(void)1199 void loadw_rn_rn(void)
1200 {
1201 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1202 jaguar.r[jaguar.op & 31] = READWORD(r1);
1203 }
1204
loadp_rn_rn(void)1205 void loadp_rn_rn(void) /* GPU only */
1206 {
1207 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1208 jaguar.ctrl[G_HIDATA] = READWORD(r1);
1209 jaguar.r[jaguar.op & 31] = READWORD(r1+4);
1210 }
1211
mirror_rn(void)1212 void mirror_rn(void) /* DSP only */
1213 {
1214 int dreg = jaguar.op & 31;
1215 UINT32 r1 = jaguar.r[dreg];
1216 UINT32 res = (mirror_table[r1 & 0xffff] << 16) | mirror_table[r1 >> 16];
1217 jaguar.r[dreg] = res;
1218 CLR_ZN; SET_ZN(res);
1219 }
1220
mmult_rn_rn(void)1221 void mmult_rn_rn(void)
1222 {
1223 int count = jaguar.ctrl[G_MTXC] & 15, i;
1224 int sreg = (jaguar.op >> 5) & 31;
1225 int dreg = jaguar.op & 31;
1226 UINT32 addr = jaguar.ctrl[G_MTXA];
1227 INT64 accum = 0;
1228 UINT32 res;
1229
1230 if (!(jaguar.ctrl[G_MTXC] & 0x10))
1231 {
1232 for (i = 0; i < count; i++)
1233 {
1234 accum += (INT16)(jaguar.b1[sreg + i/2] >> (16 * ((i & 1) ^ 1))) * (INT16)READWORD(addr);
1235 addr += 2;
1236 }
1237 }
1238 else
1239 {
1240 for (i = 0; i < count; i++)
1241 {
1242 accum += (INT16)(jaguar.b1[sreg + i/2] >> (16 * ((i & 1) ^ 1))) * (INT16)READWORD(addr);
1243 addr += 2 * count;
1244 }
1245 }
1246 jaguar.r[dreg] = res = (UINT32)accum;
1247 CLR_ZN; SET_ZN(res);
1248 }
1249
move_rn_rn(void)1250 void move_rn_rn(void)
1251 {
1252 jaguar.r[jaguar.op & 31] = jaguar.r[(jaguar.op >> 5) & 31];
1253 }
1254
move_pc_rn(void)1255 void move_pc_rn(void)
1256 {
1257 jaguar.r[jaguar.op & 31] = jaguar.ppc;
1258 }
1259
movefa_rn_rn(void)1260 void movefa_rn_rn(void)
1261 {
1262 jaguar.r[jaguar.op & 31] = jaguar.a[(jaguar.op >> 5) & 31];
1263 }
1264
movei_n_rn(void)1265 void movei_n_rn(void)
1266 {
1267 UINT32 res = ROPCODE(jaguar.PC) | (ROPCODE(jaguar.PC + 2) << 16);
1268 jaguar.PC += 4;
1269 jaguar.r[jaguar.op & 31] = res;
1270 }
1271
moveq_n_rn(void)1272 void moveq_n_rn(void)
1273 {
1274 jaguar.r[jaguar.op & 31] = (jaguar.op >> 5) & 31;
1275 }
1276
moveta_rn_rn(void)1277 void moveta_rn_rn(void)
1278 {
1279 jaguar.a[jaguar.op & 31] = jaguar.r[(jaguar.op >> 5) & 31];
1280 }
1281
mtoi_rn_rn(void)1282 void mtoi_rn_rn(void)
1283 {
1284 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1285 jaguar.r[jaguar.op & 31] = (((INT32)r1 >> 8) & 0xff800000) | (r1 & 0x007fffff);
1286 }
1287
mult_rn_rn(void)1288 void mult_rn_rn(void)
1289 {
1290 int dreg = jaguar.op & 31;
1291 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1292 UINT32 r2 = jaguar.r[dreg];
1293 UINT32 res = (UINT16)r1 * (UINT16)r2;
1294 jaguar.r[dreg] = res;
1295 CLR_ZN; SET_ZN(res);
1296 }
1297
neg_rn(void)1298 void neg_rn(void)
1299 {
1300 int dreg = jaguar.op & 31;
1301 UINT32 r2 = jaguar.r[dreg];
1302 UINT32 res = -r2;
1303 jaguar.r[dreg] = res;
1304 CLR_ZNC; SET_ZNC_SUB(0,r2,res);
1305 }
1306
nop(void)1307 void nop(void)
1308 {
1309 }
1310
normi_rn_rn(void)1311 void normi_rn_rn(void)
1312 {
1313 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1314 UINT32 res = 0;
1315 if (r1 != 0)
1316 {
1317 while ((r1 & 0xffc00000) == 0)
1318 {
1319 r1 <<= 1;
1320 res--;
1321 }
1322 while ((r1 & 0xff800000) != 0)
1323 {
1324 r1 >>= 1;
1325 res++;
1326 }
1327 }
1328 jaguar.r[jaguar.op & 31] = res;
1329 CLR_ZN; SET_ZN(res);
1330 }
1331
not_rn(void)1332 void not_rn(void)
1333 {
1334 int dreg = jaguar.op & 31;
1335 UINT32 res = ~jaguar.r[dreg];
1336 jaguar.r[dreg] = res;
1337 CLR_ZN; SET_ZN(res);
1338 }
1339
or_rn_rn(void)1340 void or_rn_rn(void)
1341 {
1342 int dreg = jaguar.op & 31;
1343 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1344 UINT32 r2 = jaguar.r[dreg];
1345 UINT32 res = r1 | r2;
1346 jaguar.r[dreg] = res;
1347 CLR_ZN; SET_ZN(res);
1348 }
1349
pack_rn(void)1350 void pack_rn(void) /* GPU only */
1351 {
1352 int dreg = jaguar.op & 31;
1353 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1354 UINT32 r2 = jaguar.r[dreg];
1355 UINT32 res;
1356 if (r1 == 0) /* PACK */
1357 res = ((r2 >> 10) & 0xf000) | ((r2 >> 5) & 0x0f00) | (r2 & 0xff);
1358 else /* UNPACK */
1359 res = ((r2 & 0xf000) << 10) | ((r2 & 0x0f00) << 5) | (r2 & 0xff);
1360 jaguar.r[dreg] = res;
1361 CLR_ZN; SET_ZN(res);
1362 }
1363
resmac_rn(void)1364 void resmac_rn(void)
1365 {
1366 jaguar.r[jaguar.op & 31] = (UINT32)jaguar.accum;
1367 }
1368
ror_rn_rn(void)1369 void ror_rn_rn(void)
1370 {
1371 int dreg = jaguar.op & 31;
1372 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31] & 31;
1373 UINT32 r2 = jaguar.r[dreg];
1374 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
1375 jaguar.r[dreg] = res;
1376 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 >> 30) & 2;
1377 }
1378
rorq_n_rn(void)1379 void rorq_n_rn(void)
1380 {
1381 int dreg = jaguar.op & 31;
1382 UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1383 UINT32 r2 = jaguar.r[dreg];
1384 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
1385 jaguar.r[dreg] = res;
1386 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 >> 30) & 2;
1387 }
1388
sat8_rn(void)1389 void sat8_rn(void) /* GPU only */
1390 {
1391 int dreg = jaguar.op & 31;
1392 INT32 r2 = jaguar.r[dreg];
1393 UINT32 res = (r2 < 0) ? 0 : (r2 > 255) ? 255 : r2;
1394 jaguar.r[dreg] = res;
1395 CLR_ZN; SET_ZN(res);
1396 }
1397
sat16_rn(void)1398 void sat16_rn(void) /* GPU only */
1399 {
1400 int dreg = jaguar.op & 31;
1401 INT32 r2 = jaguar.r[dreg];
1402 UINT32 res = (r2 < 0) ? 0 : (r2 > 65535) ? 65535 : r2;
1403 jaguar.r[dreg] = res;
1404 CLR_ZN; SET_ZN(res);
1405 }
1406
sat16s_rn(void)1407 void sat16s_rn(void) /* DSP only */
1408 {
1409 UINT32 res;
1410 int dreg = jaguar.op & 31;
1411 INT32 r2 = jaguar.r[dreg];
1412 MAME_CLAMP_SAMPLE(r2);
1413 res = r2;
1414 jaguar.r[dreg] = res;
1415 CLR_ZN; SET_ZN(res);
1416 }
1417
sat24_rn(void)1418 void sat24_rn(void) /* GPU only */
1419 {
1420 int dreg = jaguar.op & 31;
1421 INT32 r2 = jaguar.r[dreg];
1422 UINT32 res = (r2 < 0) ? 0 : (r2 > 16777215) ? 16777215 : r2;
1423 jaguar.r[dreg] = res;
1424 CLR_ZN; SET_ZN(res);
1425 }
1426
sat32s_rn(void)1427 void sat32s_rn(void) /* DSP only */
1428 {
1429 int dreg = jaguar.op & 31;
1430 INT32 r2 = (UINT32)jaguar.r[dreg];
1431 INT32 temp = jaguar.accum >> 32;
1432 UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7fffffff : r2;
1433 jaguar.r[dreg] = res;
1434 CLR_ZN; SET_ZN(res);
1435 }
1436
sh_rn_rn(void)1437 void sh_rn_rn(void)
1438 {
1439 int dreg = jaguar.op & 31;
1440 INT32 r1 = (INT32)jaguar.r[(jaguar.op >> 5) & 31];
1441 UINT32 r2 = jaguar.r[dreg];
1442 UINT32 res;
1443
1444 CLR_ZNC;
1445 if (r1 < 0)
1446 {
1447 res = (r1 <= -32) ? 0 : (r2 << -r1);
1448 jaguar.FLAGS |= (r2 >> 30) & 2;
1449 }
1450 else
1451 {
1452 res = (r1 >= 32) ? 0 : (r2 >> r1);
1453 jaguar.FLAGS |= (r2 << 1) & 2;
1454 }
1455 jaguar.r[dreg] = res;
1456 SET_ZN(res);
1457 }
1458
sha_rn_rn(void)1459 void sha_rn_rn(void)
1460 {
1461 int dreg = jaguar.op & 31;
1462 INT32 r1 = (INT32)jaguar.r[(jaguar.op >> 5) & 31];
1463 UINT32 r2 = jaguar.r[dreg];
1464 UINT32 res;
1465
1466 CLR_ZNC;
1467 if (r1 < 0)
1468 {
1469 res = (r1 <= -32) ? 0 : (r2 << -r1);
1470 jaguar.FLAGS |= (r2 >> 30) & 2;
1471 }
1472 else
1473 {
1474 res = (r1 >= 32) ? ((INT32)r2 >> 31) : ((INT32)r2 >> r1);
1475 jaguar.FLAGS |= (r2 << 1) & 2;
1476 }
1477 jaguar.r[dreg] = res;
1478 SET_ZN(res);
1479 }
1480
sharq_n_rn(void)1481 void sharq_n_rn(void)
1482 {
1483 int dreg = jaguar.op & 31;
1484 INT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1485 UINT32 r2 = jaguar.r[dreg];
1486 UINT32 res = (INT32)r2 >> r1;
1487 jaguar.r[dreg] = res;
1488 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 << 1) & 2;
1489 }
1490
shlq_n_rn(void)1491 void shlq_n_rn(void)
1492 {
1493 int dreg = jaguar.op & 31;
1494 INT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1495 UINT32 r2 = jaguar.r[dreg];
1496 UINT32 res = r2 << (32 - r1);
1497 jaguar.r[dreg] = res;
1498 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 >> 30) & 2;
1499 }
1500
shrq_n_rn(void)1501 void shrq_n_rn(void)
1502 {
1503 int dreg = jaguar.op & 31;
1504 INT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1505 UINT32 r2 = jaguar.r[dreg];
1506 UINT32 res = r2 >> r1;
1507 jaguar.r[dreg] = res;
1508 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 << 1) & 2;
1509 }
1510
store_rn_rn(void)1511 void store_rn_rn(void)
1512 {
1513 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1514 WRITELONG(r1, jaguar.r[jaguar.op & 31]);
1515 }
1516
store_rn_r14n(void)1517 void store_rn_r14n(void)
1518 {
1519 UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1520 WRITELONG(jaguar.r[14] + r1 * 4, jaguar.r[jaguar.op & 31]);
1521 }
1522
store_rn_r15n(void)1523 void store_rn_r15n(void)
1524 {
1525 UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1526 WRITELONG(jaguar.r[15] + r1 * 4, jaguar.r[jaguar.op & 31]);
1527 }
1528
store_rn_r14rn(void)1529 void store_rn_r14rn(void)
1530 {
1531 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1532 WRITELONG(jaguar.r[14] + r1, jaguar.r[jaguar.op & 31]);
1533 }
1534
store_rn_r15rn(void)1535 void store_rn_r15rn(void)
1536 {
1537 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1538 WRITELONG(jaguar.r[15] + r1, jaguar.r[jaguar.op & 31]);
1539 }
1540
storeb_rn_rn(void)1541 void storeb_rn_rn(void)
1542 {
1543 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1544 WRITEBYTE(r1, jaguar.r[jaguar.op & 31]);
1545 }
1546
storew_rn_rn(void)1547 void storew_rn_rn(void)
1548 {
1549 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1550 WRITEWORD(r1, jaguar.r[jaguar.op & 31]);
1551 }
1552
storep_rn_rn(void)1553 void storep_rn_rn(void) /* GPU only */
1554 {
1555 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1556 WRITELONG(r1, jaguar.ctrl[G_HIDATA]);
1557 WRITELONG(r1+4, jaguar.r[jaguar.op & 31]);
1558 }
1559
sub_rn_rn(void)1560 void sub_rn_rn(void)
1561 {
1562 int dreg = jaguar.op & 31;
1563 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1564 UINT32 r2 = jaguar.r[dreg];
1565 UINT32 res = r2 - r1;
1566 jaguar.r[dreg] = res;
1567 CLR_ZNC; SET_ZNC_SUB(r2,r1,res);
1568 }
1569
subc_rn_rn(void)1570 void subc_rn_rn(void)
1571 {
1572 int dreg = jaguar.op & 31;
1573 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1574 UINT32 r2 = jaguar.r[dreg];
1575 UINT32 res = r2 - r1 - ((jaguar.FLAGS >> 1) & 1);
1576 jaguar.r[dreg] = res;
1577 CLR_ZNC; SET_ZNC_SUB(r2,r1,res);
1578 }
1579
subq_n_rn(void)1580 void subq_n_rn(void)
1581 {
1582 int dreg = jaguar.op & 31;
1583 UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1584 UINT32 r2 = jaguar.r[dreg];
1585 UINT32 res = r2 - r1;
1586 jaguar.r[dreg] = res;
1587 CLR_ZNC; SET_ZNC_SUB(r2,r1,res);
1588 }
1589
subqmod_n_rn(void)1590 void subqmod_n_rn(void) /* DSP only */
1591 {
1592 int dreg = jaguar.op & 31;
1593 UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1594 UINT32 r2 = jaguar.r[dreg];
1595 UINT32 res = r2 - r1;
1596 res = (res & ~jaguar.ctrl[D_MOD]) | (r2 & ~jaguar.ctrl[D_MOD]);
1597 jaguar.r[dreg] = res;
1598 CLR_ZNC; SET_ZNC_SUB(r2,r1,res);
1599 }
1600
subqt_n_rn(void)1601 void subqt_n_rn(void)
1602 {
1603 int dreg = jaguar.op & 31;
1604 UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
1605 UINT32 r2 = jaguar.r[dreg];
1606 UINT32 res = r2 - r1;
1607 jaguar.r[dreg] = res;
1608 }
1609
xor_rn_rn(void)1610 void xor_rn_rn(void)
1611 {
1612 int dreg = jaguar.op & 31;
1613 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1614 UINT32 r2 = jaguar.r[dreg];
1615 UINT32 res = r1 ^ r2;
1616 jaguar.r[dreg] = res;
1617 CLR_ZN; SET_ZN(res);
1618 }
1619
1620
1621
1622 /*###################################################################################################
1623 ** I/O HANDLING
1624 **#################################################################################################*/
1625
jaguargpu_ctrl_r(int cpunum,offs_t offset)1626 data32_t jaguargpu_ctrl_r(int cpunum, offs_t offset)
1627 {
1628 data32_t result;
1629
1630 log_cb(RETRO_LOG_DEBUG, LOGPRE "%08X/%d:GPU read register @ F021%02X\n", activecpu_get_previouspc(), cpu_getactivecpu(), offset * 4);
1631
1632 /* switch to the target context */
1633 cpuintrf_push_context(cpunum);
1634 result = jaguar.ctrl[offset];
1635 cpuintrf_pop_context();
1636
1637 return result;
1638 }
1639
1640
jaguargpu_ctrl_w(int cpunum,offs_t offset,data32_t data,data32_t mem_mask)1641 void jaguargpu_ctrl_w(int cpunum, offs_t offset, data32_t data, data32_t mem_mask)
1642 {
1643 UINT32 oldval, newval;
1644
1645 if (offset != G_HIDATA)
1646 log_cb(RETRO_LOG_DEBUG, LOGPRE "%08X/%d:GPU write register @ F021%02X = %08X\n", activecpu_get_previouspc(), cpu_getactivecpu(), offset * 4, data);
1647
1648 /* switch to the target context */
1649 cpuintrf_push_context(cpunum);
1650
1651 /* remember the old and set the new */
1652 oldval = jaguar.ctrl[offset];
1653 newval = oldval;
1654 COMBINE_DATA(&newval);
1655
1656 /* handle the various registers */
1657 switch (offset)
1658 {
1659 case G_FLAGS:
1660
1661 /* combine the data properly */
1662 jaguar.ctrl[offset] = newval & (ZFLAG | CFLAG | NFLAG | EINT04FLAGS | RPAGEFLAG);
1663 if (newval & IFLAG)
1664 jaguar.ctrl[offset] |= oldval & IFLAG;
1665
1666 /* clear interrupts */
1667 jaguar.ctrl[G_CTRL] &= ~((newval & CINT04FLAGS) >> 3);
1668
1669 /* determine which register bank should be active */
1670 update_register_banks();
1671
1672 /* update IRQs */
1673 check_irqs();
1674 break;
1675
1676 case G_MTXC:
1677 case G_MTXA:
1678 jaguar.ctrl[offset] = newval;
1679 break;
1680
1681 case G_END:
1682 jaguar.ctrl[offset] = newval;
1683 if ((newval & 7) != 7)
1684 log_cb(RETRO_LOG_DEBUG, LOGPRE "GPU to set to little-endian!\n");
1685 break;
1686
1687 case G_PC:
1688 jaguar.PC = newval & 0xffffff;
1689 if (executing_cpu == cpunum)
1690 change_pc24bedw(jaguar.PC);
1691 break;
1692
1693 case G_CTRL:
1694 jaguar.ctrl[offset] = newval;
1695 if ((oldval ^ newval) & 0x01)
1696 {
1697 cpu_set_halt_line(cpunum, (newval & 1) ? CLEAR_LINE : ASSERT_LINE);
1698 cpu_yield();
1699 }
1700 if (newval & 0x02)
1701 {
1702 if (jaguar.cpu_interrupt)
1703 (*jaguar.cpu_interrupt)();
1704 jaguar.ctrl[offset] &= ~0x02;
1705 }
1706 if (newval & 0x04)
1707 {
1708 jaguar.ctrl[G_CTRL] |= 1 << 6;
1709 jaguar.ctrl[offset] &= ~0x04;
1710 check_irqs();
1711 }
1712 if (newval & 0x18)
1713 {
1714 log_cb(RETRO_LOG_DEBUG, LOGPRE "GPU single stepping was enabled!\n");
1715 }
1716 break;
1717
1718 case G_HIDATA:
1719 case G_DIVCTRL:
1720 jaguar.ctrl[offset] = newval;
1721 break;
1722 }
1723
1724 /* restore old context */
1725 cpuintrf_pop_context();
1726 }
1727
1728
1729
1730 /*###################################################################################################
1731 ** I/O HANDLING
1732 **#################################################################################################*/
1733
jaguardsp_ctrl_r(int cpunum,offs_t offset)1734 data32_t jaguardsp_ctrl_r(int cpunum, offs_t offset)
1735 {
1736 data32_t result;
1737
1738 if (offset != D_FLAGS)
1739 log_cb(RETRO_LOG_DEBUG, LOGPRE "%08X/%d:DSP read register @ F1A1%02X\n", activecpu_get_previouspc(), cpu_getactivecpu(), offset * 4);
1740
1741 /* switch to the target context */
1742 cpuintrf_push_context(cpunum);
1743 result = jaguar.ctrl[offset];
1744 cpuintrf_pop_context();
1745
1746 return result;
1747 }
1748
1749
jaguardsp_ctrl_w(int cpunum,offs_t offset,data32_t data,data32_t mem_mask)1750 void jaguardsp_ctrl_w(int cpunum, offs_t offset, data32_t data, data32_t mem_mask)
1751 {
1752 UINT32 oldval, newval;
1753
1754 if (offset != D_FLAGS)
1755 log_cb(RETRO_LOG_DEBUG, LOGPRE "%08X/%d:DSP write register @ F1A1%02X = %08X\n", activecpu_get_previouspc(), cpu_getactivecpu(), offset * 4, data);
1756
1757 /* switch to the target context */
1758 cpuintrf_push_context(cpunum);
1759
1760 /* remember the old and set the new */
1761 oldval = jaguar.ctrl[offset];
1762 newval = oldval;
1763 COMBINE_DATA(&newval);
1764
1765 /* handle the various registers */
1766 switch (offset)
1767 {
1768 case D_FLAGS:
1769
1770 /* combine the data properly */
1771 jaguar.ctrl[offset] = newval & (ZFLAG | CFLAG | NFLAG | EINT04FLAGS | EINT5FLAG | RPAGEFLAG);
1772 if (newval & IFLAG)
1773 jaguar.ctrl[offset] |= oldval & IFLAG;
1774
1775 /* clear interrupts */
1776 jaguar.ctrl[D_CTRL] &= ~((newval & CINT04FLAGS) >> 3);
1777 jaguar.ctrl[D_CTRL] &= ~((newval & CINT5FLAG) >> 1);
1778
1779 /* determine which register bank should be active */
1780 update_register_banks();
1781
1782 /* update IRQs */
1783 check_irqs();
1784 break;
1785
1786 case D_MTXC:
1787 case D_MTXA:
1788 jaguar.ctrl[offset] = newval;
1789 break;
1790
1791 case D_END:
1792 jaguar.ctrl[offset] = newval;
1793 if ((newval & 7) != 7)
1794 log_cb(RETRO_LOG_DEBUG, LOGPRE "DSP to set to little-endian!\n");
1795 break;
1796
1797 case D_PC:
1798 jaguar.PC = newval & 0xffffff;
1799 if (executing_cpu == cpunum)
1800 change_pc24bedw(jaguar.PC);
1801 break;
1802
1803 case D_CTRL:
1804 jaguar.ctrl[offset] = newval;
1805 if ((oldval ^ newval) & 0x01)
1806 {
1807 cpu_set_halt_line(cpunum, (newval & 1) ? CLEAR_LINE : ASSERT_LINE);
1808 cpu_yield();
1809 }
1810 if (newval & 0x02)
1811 {
1812 if (jaguar.cpu_interrupt)
1813 (*jaguar.cpu_interrupt)();
1814 jaguar.ctrl[offset] &= ~0x02;
1815 }
1816 if (newval & 0x04)
1817 {
1818 jaguar.ctrl[D_CTRL] |= 1 << 6;
1819 jaguar.ctrl[offset] &= ~0x04;
1820 check_irqs();
1821 }
1822 if (newval & 0x18)
1823 {
1824 log_cb(RETRO_LOG_DEBUG, LOGPRE "DSP single stepping was enabled!\n");
1825 }
1826 break;
1827
1828 case D_MOD:
1829 case D_DIVCTRL:
1830 jaguar.ctrl[offset] = newval;
1831 break;
1832 }
1833
1834 /* restore old context */
1835 cpuintrf_pop_context();
1836 }
1837