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