1 /*
2 www.freedo.org
3 The first working 3DO multiplayer emulator.
4
5 The FreeDO licensed under modified GNU LGPL, with following notes:
6
7 * The owners and original authors of the FreeDO have full right to
8 * develop closed source derivative work.
9
10 * Any non-commercial uses of the FreeDO sources or any knowledge
11 * obtained by studying or reverse engineering of the sources, or
12 * any other material published by FreeDO have to be accompanied
13 * with full credits.
14
15 * Any commercial uses of FreeDO sources or any knowledge obtained
16 * by studying or reverse engineering of the sources, or any other
17 * material published by FreeDO is strictly forbidden without
18 * owners approval.
19
20 The above notes are taking precedence over GNU LGPL in conflicting
21 situations.
22
23 Project authors:
24 * Alexander Troosh
25 * Maxim Grishin
26 * Allen Wright
27 * John Sammons
28 * Felix Lazarev
29 */
30
31 #include "bool.h"
32 #include "inline.h"
33 #include "opera_clio.h"
34 #include "opera_core.h"
35 #include "opera_dsp.h"
36
37 #include <string.h>
38
39 #if 0 //20 bit ALU
40 #define ALUSIZEMASK 0xFFFFF000
41 #else //32 bit ALU
42 #define ALUSIZEMASK 0xFFFFFFFF
43 #endif
44
45 #define TOPBIT 0x80000000
46 #define SYSTEM_TICKS 568 /* ceil(((25000000 / 44100) + 1)) */
47
48 #pragma pack(push,1)
49
50 struct CIFTAG_s
51 {
52 uint32_t BCH_ADDR:10;
53 uint32_t FLAG_MASK:2;
54 uint32_t FLGSEL:1;
55 uint32_t MODE:2;
56 uint32_t PAD:1;
57 };
58
59 typedef struct CIFTAG_s CIFTAG_t;
60
61 struct BRNTAG_s
62 {
63 uint32_t BCH_ADDR:10;
64 uint32_t FLAGM0:1;
65 uint32_t FLAGM1:1;
66 uint32_t FLAGSEL:1;
67 uint32_t MODE0:1;
68 uint32_t MODE1:1;
69 uint32_t AC:1;
70 };
71
72 typedef struct BRNTAG_s BRNTAG_t;
73
74 struct BRNBITS_s
75 {
76 uint32_t BCH_ADDR:10;
77 uint32_t bits:5;
78 uint32_t AC:1;
79 };
80
81 typedef struct BRNBITS_s BRNBITS_t;
82
83 struct AIFTAG_s
84 {
85 uint32_t BS:4;
86 uint32_t ALU:4;
87 uint32_t MUXB:2;
88 uint32_t MUXA:2;
89 int32_t M2SEL:1;
90 uint32_t NUMOPS:2;
91 int32_t PAD:1;
92 };
93
94 typedef struct AIFTAG_s AIFTAG_t;
95
96 struct IOFTAG_s
97 {
98 int32_t IMMEDIATE:13;
99 int32_t JUSTIFY:1;
100 uint32_t TYPE:2;
101 };
102
103 typedef struct IOFTAG_s IOFTAG_t;
104
105 struct NROFTAG_s
106 {
107 uint32_t OP_ADDR:10;
108 int32_t DI:1;
109 uint32_t WB1:1;
110 uint32_t PAD:1;
111 uint32_t TYPE:3;
112 };
113
114 typedef struct NROFTAG_s NROFTAG_t;
115
116 struct R2OFTAG_s
117 {
118 uint32_t R1:4;
119 int32_t R1_DI:1;
120 uint32_t R2:4;
121 int32_t R2_DI:1;
122 uint32_t NUMREGS:1;
123 uint32_t WB1:1;
124 uint32_t WB2:1;
125 uint32_t TYPE:3;
126 };
127
128 typedef struct R2OFTAG_s R2OFTAG_t;
129
130 struct R3OFTAG_s
131 {
132 uint32_t R1:4;
133 int32_t R1_DI:1;
134 uint32_t R2:4;
135 int32_t R2_DI:1;
136 uint32_t R3:4;
137 int32_t R3_DI:1;
138 uint32_t TYPE:1;
139 };
140
141 typedef struct R3OFTAG_s R3OFTAG_t;
142
143 union ITAG_u
144 {
145 uint32_t raw;
146 AIFTAG_t aif;
147 CIFTAG_t cif;
148 IOFTAG_t iof;
149 NROFTAG_t nrof;
150 R2OFTAG_t r2of;
151 R3OFTAG_t r3of;
152 BRNTAG_t branch;
153 BRNBITS_t br;
154 };
155
156 typedef union ITAG_u ITAG_t;
157
158 struct RQFTAG_s
159 {
160 uint32_t BS:1;
161 uint32_t ALU2:1;
162 uint32_t ALU1:1;
163 uint32_t MULT2:1;
164 uint32_t MULT1:1;
165 };
166
167 typedef struct RQFTAG_s RQFTAG_t;
168
169 union REQ_u
170 {
171 uint8_t raw;
172 RQFTAG_t rq;
173 };
174
175 typedef union REQ_u REQ_t;
176
177 /* only for ALU command */
178 struct INSTTRAS_s
179 {
180 REQ_t req;
181 char BS; // 4+1 bits
182 };
183
184 typedef struct INSTTRAS_s INSTTRAS_t;
185
186 struct REGSTAG_s
187 {
188 uint32_t PC; // 0x0ee
189 uint16_t NOISE; // 0x0ea
190 uint16_t AudioOutStatus; // audlock,lftfull,rgtfull -- 0x0eb//0x3eb
191 uint16_t Sema4Status; // 0x0ec // 0x3ec
192 uint16_t Sema4Data; // 0x0ed // 0x3ed
193 int16_t DSPPCNT; // 0x0ef
194 int16_t DSPPRLD; // 0x3ef
195 int16_t AUDCNT;
196 uint16_t INT; // 0x3ee
197 };
198
199 typedef struct REGSTAG_s REGSTAG_t;
200
201 struct INTAG_s
202 {
203 int16_t MULT1;
204 int16_t MULT2;
205 int16_t ALU1;
206 int16_t ALU2;
207 int32_t BS;
208 uint16_t RMAP;
209 uint16_t nOP_MASK;
210 uint16_t WRITEBACK;
211 REQ_t req;
212 bool_t Running;
213 bool_t GenFIQ;
214 };
215
216 typedef struct INTAG_s INTAG_t;
217
218 struct dsp_s
219 {
220 uint32_t RBASEx4;
221 INSTTRAS_t INSTTRAS[0x8000];
222 uint16_t REGCONV[8][16];
223 int BRCONDTAB[32][32];
224 uint16_t NMem[2048];
225 uint16_t IMem[1024];
226 int REGi;
227 REGSTAG_t dregs;
228 INTAG_t flags;
229 uint32_t g_seed;
230 int CPUSupply[16];
231 };
232
233 typedef struct dsp_s dsp_t;
234
235 union dsp_alu_flags_u
236 {
237 uint32_t raw;
238
239 struct
240 {
241 uint8_t zero;
242 uint8_t negative;
243 uint8_t carry;
244 uint8_t overflow;
245 };
246 };
247
248 typedef union dsp_alu_flags_u dsp_alu_flags_t;
249
250 #pragma pack(pop)
251
252 static dsp_t DSP;
253
254 int
fastrand(void)255 fastrand(void)
256 {
257 DSP.g_seed = 69069 * DSP.g_seed + 1;
258 return (DSP.g_seed & 0xFFFF);
259 }
260
261 static
262 FORCEINLINE
263 int
ADD_CFLAG(const uint32_t a_,const uint32_t b_,const uint32_t y_)264 ADD_CFLAG(const uint32_t a_,
265 const uint32_t b_,
266 const uint32_t y_)
267 {
268 return ((a_ & b_ & TOPBIT) ||
269 (a_ & ~y_ & TOPBIT) ||
270 (b_ & ~y_ & TOPBIT));
271 }
272
273 static
274 FORCEINLINE
275 int
SUB_CFLAG(const uint32_t a_,const uint32_t b_,const uint32_t y_)276 SUB_CFLAG(const uint32_t a_,
277 const uint32_t b_,
278 const uint32_t y_)
279 {
280 return (( a_ & ~b_ & TOPBIT) ||
281 ( a_ & ~y_ & TOPBIT) ||
282 (~b_ & ~y_ & TOPBIT));
283 }
284
285 static
286 FORCEINLINE
287 int
ADD_VFLAG(const uint32_t a_,const uint32_t b_,const uint32_t y_)288 ADD_VFLAG(const uint32_t a_,
289 const uint32_t b_,
290 const uint32_t y_)
291 {
292 return (( a_ & b_ & ~y_ & TOPBIT) ||
293 (~a_ & ~b_ & y_ & TOPBIT));
294 }
295
296 static
297 FORCEINLINE
298 int
SUB_VFLAG(const uint32_t a_,const uint32_t b_,const uint32_t y_)299 SUB_VFLAG(const uint32_t a_,
300 const uint32_t b_,
301 const uint32_t y_)
302 {
303 return (( a_ & ~b_ & ~y_ & TOPBIT) ||
304 (~a_ & b_ & y_ & TOPBIT));
305 }
306
307 /* DSP IREAD (includes EI, I) */
308 static
309 uint16_t
dsp_read(uint32_t addr_)310 dsp_read(uint32_t addr_)
311 {
312 uint16_t val;
313
314 /* addr &= 0x3FF; */
315 switch(addr_)
316 {
317 case 0xEA:
318 DSP.dregs.NOISE = fastrand();
319 return DSP.dregs.NOISE;
320 case 0xEB:
321 return DSP.dregs.AudioOutStatus;
322 case 0xEC:
323 return DSP.dregs.Sema4Status;
324 case 0xED:
325 return DSP.dregs.Sema4Data;
326 case 0xEE:
327 return DSP.dregs.PC;
328 case 0xEF:
329 return DSP.dregs.DSPPCNT;
330 case 0xF0:
331 case 0xF1:
332 case 0xF2:
333 case 0xF3:
334 case 0xF4:
335 case 0xF5:
336 case 0xF6:
337 case 0xF7:
338 case 0xF8:
339 case 0xF9:
340 case 0xFA:
341 case 0xFB:
342 case 0xFC:
343 /*
344 printf("#DSP read from CPU!!! chan=0x%x\n",addr&0x0f);
345 val=IMem[addr-0x80];
346 */
347 if(DSP.CPUSupply[addr_ - 0xF0])
348 return (DSP.CPUSupply[addr_ - 0xF0] = 0, fastrand());
349 return opera_clio_fifo_ei(addr_ & 0x0F);
350 case 0x70:
351 case 0x71:
352 case 0x72:
353 case 0x73:
354 case 0x74:
355 case 0x75:
356 case 0x76:
357 case 0x77:
358 case 0x78:
359 case 0x79:
360 case 0x7A:
361 case 0x7B:
362 case 0x7C:
363 //printf("#DSP read from CPU!!! chan=0x%x\n",addr&0x0f);
364 if(DSP.CPUSupply[addr_ - 0x70])
365 return (DSP.CPUSupply[addr_ - 0x70] = 0, DSP.IMem[addr_]);
366 return opera_clio_fifo_ei_read(addr_ & 0x0F);
367 case 0xD0:
368 case 0xD1:
369 case 0xD2:
370 case 0xD3:
371 case 0xD4:
372 case 0xD5:
373 case 0xD6:
374 case 0xD7:
375 case 0xD8:
376 case 0xD9:
377 case 0xDA:
378 case 0xDB:
379 case 0xDC:
380 case 0xDD:
381 case 0xDE:
382 /*
383 what is last two case's?
384 if(CPUSupply[addr&0x0f])
385 {
386 CPUSupply[addr&0x0f]=0;
387 printf("#DSP read from CPU!!! chan=0x%x\n",addr&0x0f);
388 return IMem[0x70+addr&0x0f];
389 }
390 else
391 printf("#DSP read EIFifo status 0x%4.4X\n",addr&0x0f);
392 */
393 if(DSP.CPUSupply[addr_ & 0x0F])
394 return 2;
395 return opera_clio_fifo_ei_status(addr_ & 0x0F);
396 case 0xE0:
397 case 0xE1:
398 case 0xE2:
399 case 0xE3:
400 return opera_clio_fifo_eo_status(addr_ & 0x0F);
401 default:
402 //printf("#EIRead 0x%3.3X>=0x%4.4X\n",addr, IMem[addr_ & 0x7F]);
403 addr_ -= 0x100;
404 if(addr_ < 0x200)
405 return DSP.IMem[addr_ | 0x100];
406 }
407
408 return DSP.IMem[addr_ & 0x7F];
409 }
410
411 /* DSP IWRITE (includes EO,I) */
412 static
413 void
dsp_write(uint32_t addr_,uint16_t val_)414 dsp_write(uint32_t addr_,
415 uint16_t val_)
416 {
417 addr_ &= 0x3FF;
418 switch(addr_)
419 {
420 case 0x3EB:
421 DSP.dregs.AudioOutStatus = val_;
422 break;
423 case 0x3EC:
424 /* DSP write to Sema4ACK */
425 DSP.dregs.Sema4Status |= 0x01;
426 break;
427 case 0x3ED:
428 DSP.dregs.Sema4Data = val_;
429 DSP.dregs.Sema4Status = 0x4; /* DSP write to Sema4Data */
430 break;
431 case 0x3EE:
432 DSP.dregs.INT = val_;
433 DSP.flags.GenFIQ = TRUE;
434 break;
435 case 0x3EF:
436 DSP.dregs.DSPPRLD = val_;
437 break;
438 case 0x3F0:
439 case 0x3F1:
440 case 0x3F2:
441 case 0x3F3:
442 opera_clio_fifo_eo(addr_ & 0x0F,val_);
443 break;
444 case 0x3FD:
445 /* FLUSH EOFIFO */
446 break;
447 case 0x3FE: /* DAC Left channel */
448 case 0x3FF: /* DAC Right channel */
449 DSP.IMem[addr_] = val_;
450 break;
451 default:
452 if(addr_ < 0x100)
453 return;
454
455 addr_ -= 0x100;
456 if(addr_ < 0x200)
457 DSP.IMem[addr_ | 0x100] = val_;
458 else
459 DSP.IMem[addr_ + 0x100] = val_;
460 break;
461 }
462 }
463
464 uint32_t
opera_dsp_state_size(void)465 opera_dsp_state_size(void)
466 {
467 return sizeof(dsp_t);
468 }
469
470 void
opera_dsp_state_save(void * buf_)471 opera_dsp_state_save(void *buf_)
472 {
473 memcpy(buf_,&DSP,sizeof(dsp_t));
474 }
475
476 void
opera_dsp_state_load(const void * buf_)477 opera_dsp_state_load(const void *buf_)
478 {
479 memcpy(&DSP,buf_,sizeof(dsp_t));
480 }
481
482 static
483 uint16_t
dsp_operand_load1(void)484 dsp_operand_load1(void)
485 {
486 uint16_t op;
487 ITAG_t operand;
488
489 operand.raw = DSP.NMem[DSP.dregs.PC++];
490 switch(operand.nrof.TYPE)
491 {
492 case 0:
493 case 1:
494 case 2:
495 case 3:
496 op = dsp_read(DSP.REGCONV[DSP.REGi][operand.r3of.R3] ^ DSP.RBASEx4);
497 if(operand.r3of.R3_DI) /* ??? */
498 return dsp_read(op);
499 return op;
500 case 4:
501 // non reg format
502 // IT'S an address!!!
503 op = dsp_read(operand.nrof.OP_ADDR);
504 if(operand.nrof.DI)
505 return dsp_read(op);
506 return op;
507 case 5:
508 // if(operand.r2of.NUMREGS) ignore... It's right?
509 op = dsp_read(DSP.REGCONV[DSP.REGi][operand.r2of.R1] ^ DSP.RBASEx4);
510 if(operand.r2of.R1_DI)
511 return dsp_read(op);
512 return op;
513 case 6:
514 case 7:
515 return (operand.iof.IMMEDIATE << (operand.iof.JUSTIFY & 3));
516 default:
517 break;
518 }
519
520 return 0;
521 }
522
523 static
524 void
dsp_operand_load(int requests_)525 dsp_operand_load(int requests_)
526 {
527 int idx;
528 int op_cnt;
529 uint16_t ops[6];
530 uint16_t GWRITEBACK;
531 ITAG_t operand;
532
533 DSP.flags.WRITEBACK = 0;
534
535 if(requests_ == 0)
536 {
537 if(DSP.flags.req.raw)
538 requests_ = 4;
539 else
540 return;
541 }
542
543 op_cnt = 0;
544 GWRITEBACK = 0;
545
546 do
547 {
548 operand.raw = DSP.NMem[DSP.dregs.PC++];
549 switch(operand.nrof.TYPE)
550 {
551 case 0:
552 case 1:
553 case 2:
554 case 3:
555 ops[op_cnt] = dsp_read(DSP.REGCONV[DSP.REGi][operand.r3of.R3] ^ DSP.RBASEx4);
556 if(operand.r3of.R3_DI)
557 ops[op_cnt] = dsp_read(ops[op_cnt]);
558 op_cnt++;
559
560 ops[op_cnt] = dsp_read(DSP.REGCONV[DSP.REGi][operand.r3of.R2] ^ DSP.RBASEx4);
561 if(operand.r3of.R2_DI)
562 ops[op_cnt] = dsp_read(ops[op_cnt]);
563 op_cnt++;
564
565 /* only R1 can be WRITEBACK */
566 DSP.flags.WRITEBACK = (DSP.REGCONV[DSP.REGi][operand.r3of.R1] ^ DSP.RBASEx4);
567 ops[op_cnt] = dsp_read(DSP.flags.WRITEBACK);
568 if(operand.r3of.R1_DI)
569 ops[op_cnt] = dsp_read(ops[op_cnt]);
570 op_cnt++;
571 break;
572 case 4:
573 //non reg format ///IT'S an address!!!
574 DSP.flags.WRITEBACK = operand.nrof.OP_ADDR;
575 ops[op_cnt] = dsp_read(DSP.flags.WRITEBACK);
576 if(operand.nrof.DI)
577 ops[op_cnt] = dsp_read(ops[op_cnt]);
578 op_cnt++;
579
580 if(operand.nrof.WB1)
581 GWRITEBACK = DSP.flags.WRITEBACK;
582 break;
583 case 5:
584 //regged 1/2 format
585 if(operand.r2of.NUMREGS)
586 {
587 DSP.flags.WRITEBACK = DSP.REGCONV[DSP.REGi][operand.r2of.R2] ^ DSP.RBASEx4;
588 if(operand.r2of.R2_DI)
589 DSP.flags.WRITEBACK = dsp_read(DSP.flags.WRITEBACK);
590 ops[op_cnt] = dsp_read(DSP.flags.WRITEBACK);
591 op_cnt++;
592
593 if(operand.r2of.WB2)
594 GWRITEBACK = DSP.flags.WRITEBACK;
595 }
596
597 DSP.flags.WRITEBACK = DSP.REGCONV[DSP.REGi][operand.r2of.R1] ^ DSP.RBASEx4;
598 if(operand.r2of.R1_DI)
599 DSP.flags.WRITEBACK = dsp_read(DSP.flags.WRITEBACK);
600 ops[op_cnt] = dsp_read(DSP.flags.WRITEBACK);
601 op_cnt++;
602
603 if(operand.r2of.WB1)
604 GWRITEBACK = DSP.flags.WRITEBACK;
605 break;
606 case 6:
607 case 7:
608 ops[op_cnt] = (operand.iof.IMMEDIATE << (operand.iof.JUSTIFY & 3));
609 DSP.flags.WRITEBACK = ops[op_cnt++];
610 break;
611 default:
612 break;
613 }
614 } while(op_cnt < requests_);
615
616
617 /* ok let's clean out requests_ (using op_mask) */
618 DSP.flags.req.raw &= DSP.flags.nOP_MASK;
619
620 idx = 0;
621 if(DSP.flags.req.rq.MULT1)
622 DSP.flags.MULT1 = ops[idx++];
623 if(DSP.flags.req.rq.MULT2)
624 DSP.flags.MULT2 = ops[idx++];
625
626 if(DSP.flags.req.rq.ALU1)
627 DSP.flags.ALU1 = ops[idx++];
628 if(DSP.flags.req.rq.ALU2)
629 DSP.flags.ALU2 = ops[idx++];
630
631 if(DSP.flags.req.rq.BS)
632 DSP.flags.BS = ops[idx++];
633
634 if(op_cnt != idx)
635 {
636 if(GWRITEBACK)
637 DSP.flags.WRITEBACK = GWRITEBACK;
638 /* else
639 DSP.flags.WRITEBACK = 0; */
640 }
641 else
642 {
643 DSP.flags.WRITEBACK = GWRITEBACK;
644 }
645 }
646
647 static
648 INLINE
649 uint16_t
dsp_register_base(uint32_t reg_)650 dsp_register_base(uint32_t reg_)
651 {
652 uint8_t x;
653 uint8_t y;
654 uint8_t twi;
655
656 reg_ &= 0x0000000F;
657 x = ((reg_ >> 2) & 1);
658 y = ((reg_ >> 3) & 1);
659
660 switch(DSP.flags.RMAP)
661 {
662 case 0:
663 case 1:
664 case 2:
665 case 3:
666 twi = x;
667 break;
668 case 4:
669 twi = y;
670 break;
671 case 5:
672 twi = !y;
673 break;
674 case 6:
675 twi = x & y;
676 break;
677 case 7:
678 twi = x | y;
679 break;
680 }
681
682 return ((reg_ & 7) | (twi << 8) | (reg_ >> 3) << 9);
683 }
684
685 void
opera_dsp_init(void)686 opera_dsp_init(void)
687 {
688 uint32_t i;
689 int32_t a,c;
690 ITAG_t inst;
691
692 DSP.g_seed = 0xa5a5a5a5;
693 for(a = 0; a < 16; a++)
694 {
695 for(c = 0; c < 8; c++)
696 {
697 DSP.flags.RMAP = c;
698 DSP.REGCONV[c][a] = dsp_register_base(a);
699 }
700 }
701
702 for(inst.raw = 0; inst.raw < 0x8000; inst.raw++)
703 {
704 DSP.flags.req.raw = 0;
705
706 if(inst.aif.BS == 0x8)
707 DSP.flags.req.rq.BS = 1;
708
709 switch(inst.aif.MUXA)
710 {
711 case 3:
712 DSP.flags.req.rq.MULT1 = 1;
713 DSP.flags.req.rq.MULT2 = inst.aif.M2SEL;
714 break;
715 case 1:
716 DSP.flags.req.rq.ALU1 = 1;
717 break;
718 case 2:
719 DSP.flags.req.rq.ALU2 = 1;
720 break;
721 }
722
723 switch(inst.aif.MUXB)
724 {
725 case 1:
726 DSP.flags.req.rq.ALU1 = 1;
727 break;
728 case 2:
729 DSP.flags.req.rq.ALU2 = 1;
730 break;
731 case 3:
732 DSP.flags.req.rq.MULT1 = 1;
733 DSP.flags.req.rq.MULT2 = inst.aif.M2SEL;
734 break;
735 }
736
737 DSP.INSTTRAS[inst.raw].req.raw = DSP.flags.req.raw;
738 DSP.INSTTRAS[inst.raw].BS = (inst.aif.BS | ((inst.aif.ALU & 8) << (4 - 3)));
739 }
740
741 {
742 int MD1, MD2, MD3;
743 int STAT0, STAT1;
744 int NSTAT0, NSTAT1;
745 int TDCARE0, TDCARE1;
746 int RDCARE;
747 int MD12S;
748 int SUPER0, SUPER1;
749 int ALLZERO, NALLZERO;
750 int SDS;
751 int NVTest;
752 int TMPCS;
753 int CZTest, XactTest;
754 int MD3S;
755 int fExact;
756
757 dsp_alu_flags_t flags;
758
759 for(inst.raw = 0xA000; inst.raw <= 0xFFFF; inst.raw += 1024)
760 for(flags.zero = 0; flags.zero < 2; flags.zero++)
761 for(flags.negative = 0; flags.negative < 2; flags.negative++)
762 for(flags.carry = 0; flags.carry < 2; flags.carry++)
763 for(flags.overflow = 0; flags.overflow < 2; flags.overflow++)
764 for(fExact = 0; fExact < 2; fExact++)
765 {
766 MD1 = !inst.branch.MODE1 && inst.branch.MODE0;
767 MD2 = inst.branch.MODE1 && !inst.branch.MODE0;
768 MD3 = inst.branch.MODE1 && inst.branch.MODE0;
769
770 STAT0 = (inst.branch.FLAGSEL && flags.carry) || (!inst.branch.FLAGSEL && flags.negative);
771 STAT1 = (inst.branch.FLAGSEL && flags.zero) || (!inst.branch.FLAGSEL && flags.overflow);
772 NSTAT0 = STAT0 != MD2;
773 NSTAT1 = STAT1 != MD2;
774
775 TDCARE1 = !inst.branch.FLAGM1 || (inst.branch.FLAGM1 && NSTAT0);
776 TDCARE0 = !inst.branch.FLAGM0 || (inst.branch.FLAGM0 && NSTAT1);
777
778 RDCARE = !inst.branch.FLAGM1 && !inst.branch.FLAGM0;
779
780 MD12S = TDCARE1 && TDCARE0 && (inst.branch.MODE1!=inst.branch.MODE0) && !RDCARE;
781
782 SUPER0 = MD1 && !inst.branch.FLAGSEL && RDCARE;
783 SUPER1 = MD1 && inst.branch.FLAGSEL && RDCARE;
784
785 ALLZERO = SUPER0 && flags.zero && fExact;
786 NALLZERO = SUPER1 && !(flags.zero && fExact);
787
788 SDS = ALLZERO || NALLZERO;
789
790 NVTest = ((((flags.negative != flags.overflow) ||
791 (flags.zero && inst.branch.FLAGM0)) != inst.branch.FLAGM1) &&
792 !inst.branch.FLAGSEL);
793 TMPCS = flags.carry && !flags.zero;
794 CZTest = (TMPCS != inst.branch.FLAGM0) && inst.branch.FLAGSEL && !inst.branch.FLAGM1;
795 XactTest = (fExact != inst.branch.FLAGM0) && inst.branch.FLAGSEL && inst.branch.FLAGM1;
796
797 MD3S = ((NVTest || CZTest || XactTest) && MD3);
798
799 DSP.BRCONDTAB[inst.br.bits][fExact+((flags.raw*0x10080402)>>24)] = (MD12S || MD3S || SDS);
800 }
801 }
802
803 DSP.flags.Running = FALSE;
804 DSP.flags.GenFIQ = FALSE;
805 DSP.dregs.DSPPRLD = SYSTEM_TICKS;
806 DSP.dregs.AUDCNT = SYSTEM_TICKS;
807
808 opera_dsp_reset();
809
810 /* ?? 8-CPU last, 4-DSP last, 2-CPU ACK, 1 DSP ACK ?? */
811 DSP.dregs.Sema4Status = 0;
812
813 for(i = 0; i < sizeof(DSP.NMem)/sizeof(DSP.NMem[0]); i++)
814 DSP.NMem[i] = 0x8380; /* sleep */
815
816 for(i = 0; i < 16; i++)
817 DSP.CPUSupply[i] = 0;
818 }
819
820 void
opera_dsp_reset(void)821 opera_dsp_reset(void)
822 {
823 DSP.dregs.DSPPCNT = DSP.dregs.DSPPRLD;
824 DSP.dregs.PC = 0;
825 DSP.RBASEx4 = 0;
826 DSP.REGi = 0;
827 DSP.flags.nOP_MASK = ~0;
828 }
829
830 uint32_t
opera_dsp_loop(void)831 opera_dsp_loop(void)
832 {
833 uint32_t Y; /* accumulator */
834 uint32_t BOP; /* 1st & 2nd operand */
835 dsp_alu_flags_t flags;
836
837 if(DSP.flags.Running)
838 {
839 uint32_t AOP = 0; /* 1st operand */
840 uint32_t RBSR = 0; /* return address */
841 int fExact = 0;
842 bool_t work = TRUE;
843
844 opera_dsp_reset();
845
846 Y = 0;
847 BOP = 0;
848 flags.raw = 0;
849
850 do
851 {
852 ITAG_t inst;
853
854 inst.raw = DSP.NMem[DSP.dregs.PC++];
855 if(inst.aif.PAD)
856 { // Control instruction
857 switch((inst.raw >> 7) & 0xFF)
858 {
859 case 0: /* NOP TODO */
860 break;
861 case 1: /* branch accum */
862 DSP.dregs.PC = ((Y >> 16) & 0x3FF);
863 break;
864 case 2: /* set rbase */
865 DSP.RBASEx4 = ((inst.cif.BCH_ADDR & 0x3F) << 2);
866 break;
867 case 3: /* set rmap */
868 DSP.REGi = (inst.cif.BCH_ADDR & 7);
869 break;
870 case 4: /* RTS */
871 DSP.dregs.PC = RBSR;
872 break;
873 case 5: /* set op_mask */
874 DSP.flags.nOP_MASK = ~(inst.cif.BCH_ADDR & 0x1F);
875 break;
876 case 6: /* -not used2- ins */
877 break;
878 case 7: /* sleep */
879 work = FALSE;
880 break;
881 case 8:
882 case 9:
883 case 10:
884 case 11:
885 case 12:
886 case 13:
887 case 14:
888 case 15:
889 /* jump */
890 DSP.dregs.PC = inst.cif.BCH_ADDR;
891 break;
892 case 16:
893 case 17:
894 case 18:
895 case 19:
896 case 20:
897 case 21:
898 case 22:
899 case 23:
900 /* jsr */
901 RBSR = DSP.dregs.PC;
902 DSP.dregs.PC = inst.cif.BCH_ADDR;
903 break;
904 case 24:
905 case 25:
906 case 26:
907 case 27:
908 case 28:
909 case 29:
910 case 30:
911 case 31:
912 /* branch only if was branched */
913 DSP.dregs.PC = inst.cif.BCH_ADDR;
914 break;
915 case 32:
916 case 33:
917 case 34:
918 case 35:
919 case 36:
920 case 37:
921 case 38:
922 case 39:
923 case 40:
924 case 41:
925 case 42:
926 case 43:
927 case 44:
928 case 45:
929 case 46:
930 case 47: /* MOVEREG */
931 {
932 uint16_t op;
933 uint16_t addr;
934
935 op = dsp_operand_load1();
936 addr = DSP.REGCONV[DSP.REGi][inst.r2of.R1] ^ DSP.RBASEx4;
937 if(inst.r2of.R1_DI)
938 addr = dsp_read(addr);
939 dsp_write(addr,op);
940 }
941 break;
942 case 48:
943 case 49:
944 case 50:
945 case 51:
946 case 52:
947 case 53:
948 case 54:
949 case 55:
950 case 56:
951 case 57:
952 case 58:
953 case 59:
954 case 60:
955 case 61:
956 case 62:
957 case 63: /* move */
958 {
959 uint16_t op;
960 uint16_t addr;
961
962 op = dsp_operand_load1();
963 addr = inst.cif.BCH_ADDR;
964 if(inst.nrof.DI)
965 addr = dsp_read(addr);
966 dsp_write(addr,op);
967 }
968 break;
969 default: /* condition branch */
970 if(1 & DSP.BRCONDTAB[inst.br.bits][fExact+((flags.raw*0x10080402)>>24)])
971 DSP.dregs.PC = inst.cif.BCH_ADDR;
972 break;
973 }
974 }
975 else
976 {
977 /* ALU instruction */
978 DSP.flags.req.raw = DSP.INSTTRAS[inst.raw].req.raw;
979 DSP.flags.BS = DSP.INSTTRAS[inst.raw].BS;
980
981 dsp_operand_load(inst.aif.NUMOPS);
982
983 switch(inst.aif.MUXA)
984 {
985 case 3:
986 if(inst.aif.M2SEL == 0)
987 {
988 if((inst.aif.ALU == 3) || (inst.aif.ALU == 5)) // ACSBU signal
989 AOP = (flags.carry ? ((int)DSP.flags.MULT1<<16) & ALUSIZEMASK : 0);
990 else
991 AOP = (((int)DSP.flags.MULT1 * (((int32_t)Y >> 15) & ~1)) & ALUSIZEMASK);
992 }
993 else
994 {
995 AOP = (((int)DSP.flags.MULT1 * (int)DSP.flags.MULT2 * 2) & ALUSIZEMASK);
996 }
997 break;
998 case 1:
999 AOP = (DSP.flags.ALU1 << 16);
1000 break;
1001 case 0:
1002 AOP = Y;
1003 break;
1004 case 2:
1005 AOP = (DSP.flags.ALU2 << 16);
1006 break;
1007 }
1008
1009 /* ACSBU signal */
1010 if((inst.aif.ALU == 3) || (inst.aif.ALU == 5))
1011 {
1012 BOP = (flags.carry << 16);
1013 }
1014 else
1015 {
1016 switch(inst.aif.MUXB)
1017 {
1018 case 0:
1019 BOP = Y;
1020 break;
1021 case 1:
1022 BOP = (DSP.flags.ALU1 << 16);
1023 break;
1024 case 2:
1025 BOP = (DSP.flags.ALU2 << 16);
1026 break;
1027 case 3:
1028 if(inst.aif.M2SEL == 0) // ACSBU == 0 here always
1029 BOP = (((int)DSP.flags.MULT1 * (((int32_t)Y >> 15)) & ~1) & ALUSIZEMASK);
1030 else
1031 BOP = (((int)DSP.flags.MULT1 * (int)DSP.flags.MULT2 * 2) & ALUSIZEMASK);
1032 break;
1033 }
1034 }
1035
1036 /* Any ALU op. change overflow and possible carry */
1037 flags.carry = 0;
1038 flags.overflow = 0;
1039 switch(inst.aif.ALU)
1040 {
1041 case 0:
1042 Y = AOP;
1043 break;
1044 //*
1045 case 1:
1046 Y = (0 - BOP);
1047 flags.carry = SUB_CFLAG(0,BOP,Y);
1048 flags.overflow = SUB_VFLAG(0,BOP,Y);
1049 break;
1050 case 2:
1051 case 3:
1052 Y = (AOP + BOP);
1053 flags.carry = ADD_CFLAG(AOP,BOP,Y);
1054 flags.overflow = ADD_VFLAG(AOP,BOP,Y);
1055 break;
1056 case 4:
1057 case 5:
1058 Y = (AOP - BOP);
1059 flags.carry = SUB_CFLAG(AOP,BOP,Y);
1060 flags.overflow = SUB_VFLAG(AOP,BOP,Y);
1061 break;
1062 case 6:
1063 Y = (AOP + 0x1000);
1064 flags.carry = ADD_CFLAG(AOP,0x1000,Y);
1065 flags.overflow = ADD_VFLAG(AOP,0x1000,Y);
1066 break;
1067 case 7:
1068 Y = (AOP - 0x1000);
1069 flags.carry = SUB_CFLAG(AOP,0x1000,Y);
1070 flags.overflow = SUB_VFLAG(AOP,0x1000,Y);
1071 break;
1072 case 8: // A
1073 Y = AOP;
1074 break;
1075 case 9: // NOT A
1076 Y = (AOP ^ ALUSIZEMASK);
1077 break;
1078 case 10: // A AND B
1079 Y = (AOP & BOP);
1080 break;
1081 case 11: // A NAND B
1082 Y = ((AOP & BOP) ^ ALUSIZEMASK);
1083 break;
1084 case 12: // A OR B
1085 Y= (AOP | BOP);
1086 break;
1087 case 13: // A NOR B
1088 Y = ((AOP | BOP) ^ ALUSIZEMASK);
1089 break;
1090 case 14: // A XOR B
1091 Y = (AOP ^ BOP);
1092 break;
1093 case 15: // A XNOR B
1094 Y = (AOP ^ BOP ^ ALUSIZEMASK);
1095 break;
1096 }
1097
1098 flags.zero = ((Y & 0xFFFF0000) ? 0 : 1);
1099 flags.negative = ((Y >> 31) ? 1 : 0);
1100 fExact = ((Y & 0x0000F000) ? 0 : 1);
1101
1102 //and BarrelShifter
1103 switch(DSP.flags.BS)
1104 {
1105 case 1:
1106 case 17:
1107 Y = Y << 1;
1108 break;
1109 case 2:
1110 case 18:
1111 Y = Y << 2;
1112 break;
1113 case 3:
1114 case 19:
1115 Y = Y << 3;
1116 break;
1117 case 4:
1118 case 20:
1119 Y = Y << 4;
1120 break;
1121 case 5:
1122 case 21:
1123 Y = Y << 5;
1124 break;
1125 case 6:
1126 case 22:
1127 Y = Y << 8;
1128 break;
1129
1130 //arithmetic shifts
1131 case 9:
1132 Y = ((int32_t)Y >> 16);
1133 Y &= ALUSIZEMASK;
1134 break;
1135 case 10:
1136 Y = ((int32_t)Y >> 8);
1137 Y &= ALUSIZEMASK;
1138 break;
1139 case 11:
1140 Y = ((int32_t)Y >> 5);
1141 Y &= ALUSIZEMASK;
1142 break;
1143 case 12:
1144 Y = ((int32_t)Y >> 4);
1145 Y &= ALUSIZEMASK;
1146 break;
1147 case 13:
1148 Y = ((int32_t)Y >> 3);
1149 Y &= ALUSIZEMASK;
1150 break;
1151 case 14:
1152 Y = ((int32_t)Y >> 2);
1153 Y &= ALUSIZEMASK;
1154 break;
1155 case 15:
1156 Y = ((int32_t)Y >> 1);
1157 Y &= ALUSIZEMASK;
1158 break;
1159
1160 // logocal shift
1161 case 7: // CLIP ari
1162 case 23: // CLIP log
1163 if(1 & flags.overflow)
1164 {
1165 if(1 & flags.negative)
1166 Y = 0x7FFFF000;
1167 else
1168 Y = 0x80000000;
1169 }
1170 break;
1171 case 8: // Load operand load sameself again (ari)
1172 case 24: // same, but logicalshift
1173 {
1174 //int temp=flags.carry;
1175 flags.carry = ((signed)Y < 0); // shift out bit to Carry
1176 //Y=Y<<1;
1177 //Y|=temp<<16;
1178 Y = (((Y << 1) & 0xFFFE0000) |
1179 (flags.carry ? 1<<16 : 0) |
1180 (Y & 0xF000));
1181 }
1182 break;
1183 case 25:
1184 Y = ((uint32_t)Y >> 16);
1185 Y &= ALUSIZEMASK;
1186 break;
1187 case 26:
1188 Y = ((uint32_t)Y >> 8);
1189 Y &= ALUSIZEMASK;
1190 break;
1191 case 27:
1192 Y = ((uint32_t)Y >> 5);
1193 Y &= ALUSIZEMASK;
1194 break;
1195 case 28:
1196 Y = ((uint32_t)Y >> 4);
1197 Y &= ALUSIZEMASK;
1198 break;
1199 case 29:
1200 Y = ((uint32_t)Y >> 3);
1201 Y &= ALUSIZEMASK;
1202 break;
1203 case 30:
1204 Y = ((uint32_t)Y >> 2);
1205 Y &= ALUSIZEMASK;
1206 break;
1207 case 31:
1208 Y = ((uint32_t)Y >> 1);
1209 Y &= ALUSIZEMASK;
1210 break;
1211 }
1212
1213 if(DSP.flags.WRITEBACK)
1214 dsp_write(DSP.flags.WRITEBACK,((int32_t)Y) >> 16);
1215 }
1216
1217 } while(work);
1218
1219
1220 if(1 & DSP.flags.GenFIQ)
1221 {
1222 DSP.flags.GenFIQ = FALSE;
1223 opera_clio_fiq_generate(0x800,0); /* AudioFIQ */
1224 }
1225
1226 DSP.dregs.DSPPCNT -= SYSTEM_TICKS;
1227 if(DSP.dregs.DSPPCNT <= 0)
1228 DSP.dregs.DSPPCNT += DSP.dregs.DSPPRLD;
1229 }
1230
1231 return ((DSP.IMem[0x3FF] << 16) | DSP.IMem[0x3FE]);
1232 }
1233
1234 /* CPU writes NMEM of DSP */
1235 void
opera_dsp_mem_write(uint16_t addr_,uint16_t val_)1236 opera_dsp_mem_write(uint16_t addr_,
1237 uint16_t val_)
1238 {
1239 //mwriteh(addr,val);
1240 DSP.NMem[addr_ & 0x3FF] = val_;
1241 }
1242
1243 void
opera_dsp_set_running(int val_)1244 opera_dsp_set_running(int val_)
1245 {
1246 DSP.flags.Running = (val_ & 1);
1247 }
1248
1249 /* CPU writes to EI,I of DSP */
1250 void
opera_dsp_imem_write(uint16_t addr_,uint16_t val_)1251 opera_dsp_imem_write(uint16_t addr_,
1252 uint16_t val_)
1253 {
1254 if((addr_ >= 0x70) && (addr_ <= 0x7C))
1255 {
1256 DSP.CPUSupply[addr_ - 0x70] = 1;
1257 DSP.IMem[addr_ & 0x7F] = val_;
1258 }
1259 else if(!(addr_ & 0x80))
1260 {
1261 DSP.IMem[addr_ & 0x7F] = val_;
1262 }
1263 }
1264
1265 void
opera_dsp_arm_semaphore_write(uint32_t val_)1266 opera_dsp_arm_semaphore_write(uint32_t val_)
1267 {
1268 // How about Sema4ACK? Now don't think about it
1269 // ARM write to Sema4Data low 16 bits
1270 // ARM be last
1271 DSP.dregs.Sema4Data = (val_ & 0xFFFF);
1272 DSP.dregs.Sema4Status = 0x8;
1273 }
1274
1275 /* CPU reads from EO,I of DSP */
1276 uint16_t
opera_dsp_imem_read(uint16_t addr_)1277 opera_dsp_imem_read(uint16_t addr_)
1278 {
1279 switch(addr_)
1280 {
1281 case 0x3EB:
1282 return DSP.dregs.AudioOutStatus;
1283 case 0x3EC:
1284 return DSP.dregs.Sema4Status;
1285 case 0x3ED:
1286 return DSP.dregs.Sema4Data;
1287 case 0x3EE:
1288 return DSP.dregs.INT;
1289 case 0x3EF:
1290 return DSP.dregs.DSPPRLD;
1291 default:
1292 break;
1293 }
1294
1295 return DSP.IMem[addr_];
1296 }
1297
1298 uint32_t
opera_dsp_arm_semaphore_read(void)1299 opera_dsp_arm_semaphore_read(void)
1300 {
1301 return ((DSP.dregs.Sema4Status << 16) | DSP.dregs.Sema4Data);
1302 }
1303