Previous 199869 Revisions Next

r28740 Wednesday 19th March, 2014 at 20:38:42 UTC by Oliver Stöneberg
ppc *.c -> *.inc renaming
[src/emu/cpu/powerpc]ppc.c ppc403.c ppc403.inc* ppc602.c ppc602.inc* ppc603.c ppc603.inc* ppc_mem.c ppc_mem.inc* ppc_ops.c ppc_ops.inc*

trunk/src/emu/cpu/powerpc/ppc_ops.c
r28739r28740
1/* PowerPC common opcodes */
2
3// it really seems like this should be elsewhere - like maybe the floating point checks can hang out someplace else
4#include <math.h>
5
6#ifndef PPC_DRC
7static void ppc_unimplemented(UINT32 op)
8{
9   fatalerror("ppc: Unimplemented opcode %08X at %08X\n", op, ppc.pc);
10}
11
12static void ppc_addx(UINT32 op)
13{
14   UINT32 ra = REG(RA);
15   UINT32 rb = REG(RB);
16
17   REG(RT) = ra + rb;
18
19   if( OEBIT ) {
20      SET_ADD_OV(REG(RT), ra, rb);
21   }
22   if( RCBIT ) {
23      SET_CR0(REG(RT));
24   }
25}
26
27static void ppc_addcx(UINT32 op)
28{
29   UINT32 ra = REG(RA);
30   UINT32 rb = REG(RB);
31
32   REG(RT) = ra + rb;
33
34   SET_ADD_CA(REG(RT), ra, rb);
35
36   if( OEBIT ) {
37      SET_ADD_OV(REG(RT), ra, rb);
38   }
39   if( RCBIT ) {
40      SET_CR0(REG(RT));
41   }
42}
43#endif
44
45static void ppc_addex(UINT32 op)
46{
47   UINT32 ra = REG(RA);
48   UINT32 rb = REG(RB);
49   UINT32 carry = (XER >> 29) & 0x1;
50   UINT32 tmp;
51
52   tmp = rb + carry;
53   REG(RT) = ra + tmp;
54
55   if( ADD_CA(tmp, rb, carry) || ADD_CA(REG(RT), ra, tmp) )
56      XER |= XER_CA;
57   else
58      XER &= ~XER_CA;
59
60   if( OEBIT ) {
61      SET_ADD_OV(REG(RT), ra, rb);
62   }
63   if( RCBIT ) {
64      SET_CR0(REG(RT));
65   }
66}
67
68#ifndef PPC_DRC
69static void ppc_addi(UINT32 op)
70{
71   UINT32 i = SIMM16;
72   UINT32 a = RA;
73
74   if( a )
75      i += REG(a);
76
77   REG(RT) = i;
78}
79
80static void ppc_addic(UINT32 op)
81{
82   UINT32 i = SIMM16;
83   UINT32 ra = REG(RA);
84
85   REG(RT) = ra + i;
86
87   if( ADD_CA(REG(RT), ra, i) )
88      XER |= XER_CA;
89   else
90      XER &= ~XER_CA;
91}
92
93static void ppc_addic_rc(UINT32 op)
94{
95   UINT32 i = SIMM16;
96   UINT32 ra = REG(RA);
97
98   REG(RT) = ra + i;
99
100   if( ADD_CA(REG(RT), ra, i) )
101      XER |= XER_CA;
102   else
103      XER &= ~XER_CA;
104
105   SET_CR0(REG(RT));
106}
107
108static void ppc_addis(UINT32 op)
109{
110   UINT32 i = UIMM16 << 16;
111   UINT32 a = RA;
112
113   if( a )
114      i += REG(a);
115
116   REG(RT) = i;
117}
118#endif
119
120static void ppc_addmex(UINT32 op)
121{
122   UINT32 ra = REG(RA);
123   UINT32 carry = (XER >> 29) & 0x1;
124   UINT32 tmp;
125
126   tmp = ra + carry;
127   REG(RT) = tmp + -1;
128
129   if( ADD_CA(tmp, ra, carry) || ADD_CA(REG(RT), tmp, -1) )
130      XER |= XER_CA;
131   else
132      XER &= ~XER_CA;
133
134   if( OEBIT ) {
135      SET_ADD_OV(REG(RT), ra, carry - 1);
136   }
137   if( RCBIT ) {
138      SET_CR0(REG(RT));
139   }
140}
141
142static void ppc_addzex(UINT32 op)
143{
144   UINT32 ra = REG(RA);
145   UINT32 carry = (XER >> 29) & 0x1;
146
147   REG(RT) = ra + carry;
148
149   if( ADD_CA(REG(RT), ra, carry) )
150      XER |= XER_CA;
151   else
152      XER &= ~XER_CA;
153
154   if( OEBIT ) {
155      SET_ADD_OV(REG(RT), ra, carry);
156   }
157   if( RCBIT ) {
158      SET_CR0(REG(RT));
159   }
160}
161
162#ifndef PPC_DRC
163static void ppc_andx(UINT32 op)
164{
165   REG(RA) = REG(RS) & REG(RB);
166
167   if( RCBIT ) {
168      SET_CR0(REG(RA));
169   }
170}
171
172static void ppc_andcx(UINT32 op)
173{
174   REG(RA) = REG(RS) & ~REG(RB);
175
176   if( RCBIT ) {
177      SET_CR0(REG(RA));
178   }
179}
180
181static void ppc_andi_rc(UINT32 op)
182{
183   UINT32 i = UIMM16;
184
185   REG(RA) = REG(RS) & i;
186
187   SET_CR0(REG(RA));
188}
189
190static void ppc_andis_rc(UINT32 op)
191{
192   UINT32 i = UIMM16 << 16;
193
194   REG(RA) = REG(RS) & i;
195
196   SET_CR0(REG(RA));
197}
198
199static void ppc_bx(UINT32 op)
200{
201   INT32 li = op & 0x3fffffc;
202   if( li & 0x2000000 )
203      li |= 0xfc000000;
204
205   if( AABIT ) {
206      ppc.npc = li;
207   } else {
208      ppc.npc = ppc.pc + li;
209   }
210
211   if( LKBIT ) {
212      LR = ppc.pc + 4;
213   }
214}
215
216static void ppc_bcx(UINT32 op)
217{
218   int condition = check_condition_code(BO, BI);
219
220   if( condition ) {
221      if( AABIT ) {
222         ppc.npc = SIMM16 & ~0x3;
223      } else {
224         ppc.npc = ppc.pc + (SIMM16 & ~0x3);
225      }
226   }
227
228   if( LKBIT ) {
229      LR = ppc.pc + 4;
230   }
231}
232
233static void ppc_bcctrx(UINT32 op)
234{
235   int condition = check_condition_code(BO, BI);
236
237   if( condition ) {
238      ppc.npc = CTR & ~0x3;
239   }
240
241   if( LKBIT ) {
242      LR = ppc.pc + 4;
243   }
244}
245
246static void ppc_bclrx(UINT32 op)
247{
248   int condition = check_condition_code(BO, BI);
249
250   if( condition ) {
251      ppc.npc = LR & ~0x3;
252   }
253
254   if( LKBIT ) {
255      LR = ppc.pc + 4;
256   }
257}
258
259static void ppc_cmp(UINT32 op)
260{
261   INT32 ra = REG(RA);
262   INT32 rb = REG(RB);
263   int d = CRFD;
264
265   if( ra < rb )
266      CR(d) = 0x8;
267   else if( ra > rb )
268      CR(d) = 0x4;
269   else
270      CR(d) = 0x2;
271
272   if( XER & XER_SO )
273      CR(d) |= 0x1;
274}
275
276static void ppc_cmpi(UINT32 op)
277{
278   INT32 ra = REG(RA);
279   INT32 i = SIMM16;
280   int d = CRFD;
281
282   if( ra < i )
283      CR(d) = 0x8;
284   else if( ra > i )
285      CR(d) = 0x4;
286   else
287      CR(d) = 0x2;
288
289   if( XER & XER_SO )
290      CR(d) |= 0x1;
291}
292
293static void ppc_cmpl(UINT32 op)
294{
295   UINT32 ra = REG(RA);
296   UINT32 rb = REG(RB);
297   int d = CRFD;
298
299   if( ra < rb )
300      CR(d) = 0x8;
301   else if( ra > rb )
302      CR(d) = 0x4;
303   else
304      CR(d) = 0x2;
305
306   if( XER & XER_SO )
307      CR(d) |= 0x1;
308}
309
310static void ppc_cmpli(UINT32 op)
311{
312   UINT32 ra = REG(RA);
313   UINT32 i = UIMM16;
314   int d = CRFD;
315
316   if( ra < i )
317      CR(d) = 0x8;
318   else if( ra > i )
319      CR(d) = 0x4;
320   else
321      CR(d) = 0x2;
322
323   if( XER & XER_SO )
324      CR(d) |= 0x1;
325}
326
327static void ppc_cntlzw(UINT32 op)
328{
329   int n = 0;
330   int t = RT;
331   UINT32 m = 0x80000000;
332
333   while(n < 32)
334   {
335      if( REG(t) & m )
336         break;
337      m >>= 1;
338      n++;
339   }
340
341   REG(RA) = n;
342
343   if( RCBIT ) {
344      SET_CR0(REG(RA));
345   }
346}
347#endif
348
349static void ppc_crand(UINT32 op)
350{
351   int bit = RT;
352   int b = CRBIT(RA) & CRBIT(RB);
353   if( b & 0x1 )
354      CR(bit / 4) |= _BIT(3-(bit % 4));
355   else
356      CR(bit / 4) &= ~_BIT(3-(bit % 4));
357}
358
359static void ppc_crandc(UINT32 op)
360{
361   int bit = RT;
362   int b = CRBIT(RA) & ~CRBIT(RB);
363   if( b & 0x1 )
364      CR(bit / 4) |= _BIT(3-(bit % 4));
365   else
366      CR(bit / 4) &= ~_BIT(3-(bit % 4));
367}
368
369static void ppc_creqv(UINT32 op)
370{
371   int bit = RT;
372   int b = ~(CRBIT(RA) ^ CRBIT(RB));
373   if( b & 0x1 )
374      CR(bit / 4) |= _BIT(3-(bit % 4));
375   else
376      CR(bit / 4) &= ~_BIT(3-(bit % 4));
377}
378
379static void ppc_crnand(UINT32 op)
380{
381   int bit = RT;
382   int b = ~(CRBIT(RA) & CRBIT(RB));
383   if( b & 0x1 )
384      CR(bit / 4) |= _BIT(3-(bit % 4));
385   else
386      CR(bit / 4) &= ~_BIT(3-(bit % 4));
387}
388
389static void ppc_crnor(UINT32 op)
390{
391   int bit = RT;
392   int b = ~(CRBIT(RA) | CRBIT(RB));
393   if( b & 0x1 )
394      CR(bit / 4) |= _BIT(3-(bit % 4));
395   else
396      CR(bit / 4) &= ~_BIT(3-(bit % 4));
397}
398
399static void ppc_cror(UINT32 op)
400{
401   int bit = RT;
402   int b = CRBIT(RA) | CRBIT(RB);
403   if( b & 0x1 )
404      CR(bit / 4) |= _BIT(3-(bit % 4));
405   else
406      CR(bit / 4) &= ~_BIT(3-(bit % 4));
407}
408
409static void ppc_crorc(UINT32 op)
410{
411   int bit = RT;
412   int b = CRBIT(RA) | ~CRBIT(RB);
413   if( b & 0x1 )
414      CR(bit / 4) |= _BIT(3-(bit % 4));
415   else
416      CR(bit / 4) &= ~_BIT(3-(bit % 4));
417}
418
419static void ppc_crxor(UINT32 op)
420{
421   int bit = RT;
422   int b = CRBIT(RA) ^ CRBIT(RB);
423   if( b & 0x1 )
424      CR(bit / 4) |= _BIT(3-(bit % 4));
425   else
426      CR(bit / 4) &= ~_BIT(3-(bit % 4));
427}
428
429#ifndef PPC_DRC
430static void ppc_dcbf(UINT32 op)
431{
432}
433
434static void ppc_dcbi(UINT32 op)
435{
436}
437
438static void ppc_dcbst(UINT32 op)
439{
440}
441
442static void ppc_dcbt(UINT32 op)
443{
444}
445
446static void ppc_dcbtst(UINT32 op)
447{
448}
449
450static void ppc_dcbz(UINT32 op)
451{
452}
453#endif
454
455static void ppc_divwx(UINT32 op)
456{
457   if( REG(RB) == 0 && REG(RA) < 0x80000000 )
458   {
459      REG(RT) = 0;
460      if( OEBIT ) {
461         XER |= XER_SO | XER_OV;
462      }
463   }
464   else if( REG(RB) == 0 || (REG(RB) == 0xffffffff && REG(RA) == 0x80000000) )
465   {
466      REG(RT) = 0xffffffff;
467      if( OEBIT ) {
468         XER |= XER_SO | XER_OV;
469      }
470   }
471   else
472   {
473      REG(RT) = (INT32)REG(RA) / (INT32)REG(RB);
474      if( OEBIT ) {
475         XER &= ~XER_OV;
476      }
477   }
478
479   if( RCBIT ) {
480      SET_CR0(REG(RT));
481   }
482}
483
484static void ppc_divwux(UINT32 op)
485{
486   if( REG(RB) == 0 )
487   {
488      REG(RT) = 0;
489      if( OEBIT ) {
490         XER |= XER_SO | XER_OV;
491      }
492   }
493   else
494   {
495      REG(RT) = (UINT32)REG(RA) / (UINT32)REG(RB);
496      if( OEBIT ) {
497         XER &= ~XER_OV;
498      }
499   }
500
501   if( RCBIT ) {
502      SET_CR0(REG(RT));
503   }
504}
505
506#ifndef PPC_DRC
507static void ppc_eieio(UINT32 op)
508{
509}
510
511static void ppc_eqvx(UINT32 op)
512{
513   REG(RA) = ~(REG(RS) ^ REG(RB));
514
515   if( RCBIT ) {
516      SET_CR0(REG(RA));
517   }
518}
519
520static void ppc_extsbx(UINT32 op)
521{
522   REG(RA) = (INT32)(INT8)REG(RS);
523
524   if( RCBIT ) {
525      SET_CR0(REG(RA));
526   }
527}
528
529static void ppc_extshx(UINT32 op)
530{
531   REG(RA) = (INT32)(INT16)REG(RS);
532
533   if( RCBIT ) {
534      SET_CR0(REG(RA));
535   }
536}
537
538static void ppc_icbi(UINT32 op)
539{
540}
541
542static void ppc_isync(UINT32 op)
543{
544}
545
546static void ppc_lbz(UINT32 op)
547{
548   UINT32 ea;
549
550   if( RA == 0 )
551      ea = SIMM16;
552   else
553      ea = REG(RA) + SIMM16;
554
555   REG(RT) = (UINT32)READ8(ea);
556}
557
558static void ppc_lbzu(UINT32 op)
559{
560   UINT32 ea = REG(RA) + SIMM16;
561
562   REG(RT) = (UINT32)READ8(ea);
563   REG(RA) = ea;
564}
565
566static void ppc_lbzux(UINT32 op)
567{
568   UINT32 ea = REG(RA) + REG(RB);
569
570   REG(RT) = (UINT32)READ8(ea);
571   REG(RA) = ea;
572}
573
574static void ppc_lbzx(UINT32 op)
575{
576   UINT32 ea;
577
578   if( RA == 0 )
579      ea = REG(RB);
580   else
581      ea = REG(RA) + REG(RB);
582
583   REG(RT) = (UINT32)READ8(ea);
584}
585
586static void ppc_lha(UINT32 op)
587{
588   UINT32 ea;
589
590   if( RA == 0 )
591      ea = SIMM16;
592   else
593      ea = REG(RA) + SIMM16;
594
595   REG(RT) = (INT32)(INT16)READ16(ea);
596}
597
598static void ppc_lhau(UINT32 op)
599{
600   UINT32 ea = REG(RA) + SIMM16;
601
602   REG(RT) = (INT32)(INT16)READ16(ea);
603   REG(RA) = ea;
604}
605
606static void ppc_lhaux(UINT32 op)
607{
608   UINT32 ea = REG(RA) + REG(RB);
609
610   REG(RT) = (INT32)(INT16)READ16(ea);
611   REG(RA) = ea;
612}
613
614static void ppc_lhax(UINT32 op)
615{
616   UINT32 ea;
617
618   if( RA == 0 )
619      ea = REG(RB);
620   else
621      ea = REG(RA) + REG(RB);
622
623   REG(RT) = (INT32)(INT16)READ16(ea);
624}
625
626static void ppc_lhbrx(UINT32 op)
627{
628   UINT32 ea;
629   UINT16 w;
630
631   if( RA == 0 )
632      ea = REG(RB);
633   else
634      ea = REG(RA) + REG(RB);
635
636   w = READ16(ea);
637   REG(RT) = (UINT32)BYTE_REVERSE16(w);
638}
639
640static void ppc_lhz(UINT32 op)
641{
642   UINT32 ea;
643
644   if( RA == 0 )
645      ea = SIMM16;
646   else
647      ea = REG(RA) + SIMM16;
648
649   REG(RT) = (UINT32)READ16(ea);
650}
651
652static void ppc_lhzu(UINT32 op)
653{
654   UINT32 ea = REG(RA) + SIMM16;
655
656   REG(RT) = (UINT32)READ16(ea);
657   REG(RA) = ea;
658}
659
660static void ppc_lhzux(UINT32 op)
661{
662   UINT32 ea = REG(RA) + REG(RB);
663
664   REG(RT) = (UINT32)READ16(ea);
665   REG(RA) = ea;
666}
667
668static void ppc_lhzx(UINT32 op)
669{
670   UINT32 ea;
671
672   if( RA == 0 )
673      ea = REG(RB);
674   else
675      ea = REG(RA) + REG(RB);
676
677   REG(RT) = (UINT32)READ16(ea);
678}
679#endif
680
681static void ppc_lmw(UINT32 op)
682{
683   int r = RT;
684   UINT32 ea;
685
686   if( RA == 0 )
687      ea = SIMM16;
688   else
689      ea = REG(RA) + SIMM16;
690
691   while( r <= 31 )
692   {
693      REG(r) = READ32(ea);
694      ea += 4;
695      r++;
696   }
697}
698
699static void ppc_lswi(UINT32 op)
700{
701   int n, r, i;
702   UINT32 ea = 0;
703   if( RA != 0 )
704      ea = REG(RA);
705
706   if( RB == 0 )
707      n = 32;
708   else
709      n = RB;
710
711   r = RT - 1;
712   i = 0;
713
714   while(n > 0)
715   {
716      if (i == 0) {
717         r = (r + 1) % 32;
718         REG(r) = 0;
719      }
720      REG(r) |= ((READ8(ea) & 0xff) << (24 - i));
721      i += 8;
722      if (i == 32) {
723         i = 0;
724      }
725      ea++;
726      n--;
727   }
728}
729
730static void ppc_lswx(UINT32 op)
731{
732   int n, r, i;
733   UINT32 ea = 0;
734   if( RA != 0 )
735      ea = REG(RA);
736
737   ea += REG(RB);
738
739   n = ppc.xer & 0x7f;
740
741   r = RT - 1;
742   i = 0;
743
744   while(n > 0)
745   {
746      if (i == 0) {
747         r = (r + 1) % 32;
748         REG(r) = 0;
749      }
750      REG(r) |= ((READ8(ea) & 0xff) << (24 - i));
751      i += 8;
752      if (i == 32) {
753         i = 0;
754      }
755      ea++;
756      n--;
757   }
758}
759
760static void ppc_lwarx(UINT32 op)
761{
762   UINT32 ea;
763
764   if( RA == 0 )
765      ea = REG(RB);
766   else
767      ea = REG(RA) + REG(RB);
768
769   ppc.reserved_address = ea;
770   ppc.reserved = 1;
771
772   REG(RT) = READ32(ea);
773}
774
775#ifndef PPC_DRC
776static void ppc_lwbrx(UINT32 op)
777{
778   UINT32 ea;
779   UINT32 w;
780
781   if( RA == 0 )
782      ea = REG(RB);
783   else
784      ea = REG(RA) + REG(RB);
785
786   w = READ32(ea);
787   REG(RT) = BYTE_REVERSE32(w);
788}
789
790static void ppc_lwz(UINT32 op)
791{
792   UINT32 ea;
793
794   if( RA == 0 )
795      ea = SIMM16;
796   else
797      ea = REG(RA) + SIMM16;
798
799   REG(RT) = READ32(ea);
800}
801
802static void ppc_lwzu(UINT32 op)
803{
804   UINT32 ea = REG(RA) + SIMM16;
805
806   REG(RT) = READ32(ea);
807   REG(RA) = ea;
808}
809
810static void ppc_lwzux(UINT32 op)
811{
812   UINT32 ea = REG(RA) + REG(RB);
813
814   REG(RT) = READ32(ea);
815   REG(RA) = ea;
816}
817
818static void ppc_lwzx(UINT32 op)
819{
820   UINT32 ea;
821
822   if( RA == 0 )
823      ea = REG(RB);
824   else
825      ea = REG(RA) + REG(RB);
826
827   REG(RT) = READ32(ea);
828}
829
830static void ppc_mcrf(UINT32 op)
831{
832   CR(RT >> 2) = CR(RA >> 2);
833}
834
835static void ppc_mcrxr(UINT32 op)
836{
837   CR(RT >> 2) = (XER >> 28) & 0x0F;
838   XER &= ~0xf0000000;
839}
840
841static void ppc_mfcr(UINT32 op)
842{
843   REG(RT) = ppc_get_cr();
844}
845
846static void ppc_mfmsr(UINT32 op)
847{
848   REG(RT) = ppc_get_msr();
849}
850
851static void ppc_mfspr(UINT32 op)
852{
853   REG(RT) = ppc_get_spr(SPR);
854}
855#endif
856
857static void ppc_mtcrf(UINT32 op)
858{
859   int fxm = FXM;
860   int t = RT;
861
862   if( fxm & 0x80 )    CR(0) = (REG(t) >> 28) & 0xf;
863   if( fxm & 0x40 )    CR(1) = (REG(t) >> 24) & 0xf;
864   if( fxm & 0x20 )    CR(2) = (REG(t) >> 20) & 0xf;
865   if( fxm & 0x10 )    CR(3) = (REG(t) >> 16) & 0xf;
866   if( fxm & 0x08 )    CR(4) = (REG(t) >> 12) & 0xf;
867   if( fxm & 0x04 )    CR(5) = (REG(t) >> 8) & 0xf;
868   if( fxm & 0x02 )    CR(6) = (REG(t) >> 4) & 0xf;
869   if( fxm & 0x01 )    CR(7) = (REG(t) >> 0) & 0xf;
870}
871
872#ifndef PPC_DRC
873static void ppc_mtmsr(UINT32 op)
874{
875   ppc_set_msr(REG(RS));
876}
877
878static void ppc_mtspr(UINT32 op)
879{
880   ppc_set_spr(SPR, REG(RS));
881}
882
883static void ppc_mulhwx(UINT32 op)
884{
885   INT64 ra = (INT64)(INT32)REG(RA);
886   INT64 rb = (INT64)(INT32)REG(RB);
887
888   REG(RT) = (UINT32)((ra * rb) >> 32);
889
890   if( RCBIT ) {
891      SET_CR0(REG(RT));
892   }
893}
894
895static void ppc_mulhwux(UINT32 op)
896{
897   UINT64 ra = (UINT64)REG(RA);
898   UINT64 rb = (UINT64)REG(RB);
899
900   REG(RT) = (UINT32)((ra * rb) >> 32);
901
902   if( RCBIT ) {
903      SET_CR0(REG(RT));
904   }
905}
906
907static void ppc_mulli(UINT32 op)
908{
909   INT32 ra = (INT32)REG(RA);
910   INT32 i = SIMM16;
911
912   REG(RT) = ra * i;
913}
914
915static void ppc_mullwx(UINT32 op)
916{
917   INT64 ra = (INT64)(INT32)REG(RA);
918   INT64 rb = (INT64)(INT32)REG(RB);
919   INT64 r;
920
921   r = ra * rb;
922   REG(RT) = (UINT32)r;
923
924   if( OEBIT ) {
925      XER &= ~XER_OV;
926
927      if( r != (INT64)(INT32)r )
928         XER |= XER_OV | XER_SO;
929   }
930
931   if( RCBIT ) {
932      SET_CR0(REG(RT));
933   }
934}
935
936static void ppc_nandx(UINT32 op)
937{
938   REG(RA) = ~(REG(RS) & REG(RB));
939
940   if( RCBIT ) {
941      SET_CR0(REG(RA));
942   }
943}
944
945static void ppc_negx(UINT32 op)
946{
947   REG(RT) = -REG(RA);
948
949   if( OEBIT ) {
950      if( REG(RT) == 0x80000000 )
951         XER |= XER_OV | XER_SO;
952      else
953         XER &= ~XER_OV;
954   }
955
956   if( RCBIT ) {
957      SET_CR0(REG(RT));
958   }
959}
960
961static void ppc_norx(UINT32 op)
962{
963   REG(RA) = ~(REG(RS) | REG(RB));
964
965   if( RCBIT ) {
966      SET_CR0(REG(RA));
967   }
968}
969
970static void ppc_orx(UINT32 op)
971{
972   REG(RA) = REG(RS) | REG(RB);
973
974   if( RCBIT ) {
975      SET_CR0(REG(RA));
976   }
977}
978
979static void ppc_orcx(UINT32 op)
980{
981   REG(RA) = REG(RS) | ~REG(RB);
982
983   if( RCBIT ) {
984      SET_CR0(REG(RA));
985   }
986}
987
988static void ppc_ori(UINT32 op)
989{
990   REG(RA) = REG(RS) | UIMM16;
991}
992
993static void ppc_oris(UINT32 op)
994{
995   REG(RA) = REG(RS) | (UIMM16 << 16);
996}
997
998static void ppc_rfi(UINT32 op)
999{
1000   UINT32 msr;
1001   ppc.npc = ppc_get_spr(SPR_SRR0);
1002   msr = ppc_get_spr(SPR_SRR1);
1003   ppc_set_msr( msr );
1004}
1005
1006static void ppc_rlwimix(UINT32 op)
1007{
1008   UINT32 r;
1009   UINT32 mask = GET_ROTATE_MASK(MB, ME);
1010   UINT32 rs = REG(RS);
1011   int sh = SH;
1012
1013   r = (rs << sh) | (rs >> (32-sh));
1014   REG(RA) = (REG(RA) & ~mask) | (r & mask);
1015
1016   if( RCBIT ) {
1017      SET_CR0(REG(RA));
1018   }
1019}
1020
1021static void ppc_rlwinmx(UINT32 op)
1022{
1023   UINT32 r;
1024   UINT32 mask = GET_ROTATE_MASK(MB, ME);
1025   UINT32 rs = REG(RS);
1026   int sh = SH;
1027
1028   r = (rs << sh) | (rs >> (32-sh));
1029   REG(RA) = r & mask;
1030
1031   if( RCBIT ) {
1032      SET_CR0(REG(RA));
1033   }
1034}
1035
1036static void ppc_rlwnmx(UINT32 op)
1037{
1038   UINT32 r;
1039   UINT32 mask = GET_ROTATE_MASK(MB, ME);
1040   UINT32 rs = REG(RS);
1041   int sh = REG(RB) & 0x1f;
1042
1043   r = (rs << sh) | (rs >> (32-sh));
1044   REG(RA) = r & mask;
1045
1046   if( RCBIT ) {
1047      SET_CR0(REG(RA));
1048   }
1049}
1050#endif
1051
1052#ifndef PPC_DRC
1053static void ppc_sc(UINT32 op)
1054{
1055   if (ppc.is603) {
1056      ppc603_exception(EXCEPTION_SYSTEM_CALL);
1057   }
1058   if (ppc.is602) {
1059      ppc602_exception(EXCEPTION_SYSTEM_CALL);
1060   }
1061   if (IS_PPC403()) {
1062      ppc403_exception(EXCEPTION_SYSTEM_CALL);
1063   }
1064}
1065#endif
1066
1067static void ppc_slwx(UINT32 op)
1068{
1069   int sh = REG(RB) & 0x3f;
1070
1071   if( sh > 31 ) {
1072      REG(RA) = 0;
1073   }
1074   else {
1075      REG(RA) = REG(RS) << sh;
1076   }
1077
1078   if( RCBIT ) {
1079      SET_CR0(REG(RA));
1080   }
1081}
1082
1083static void ppc_srawx(UINT32 op)
1084{
1085   int sh = REG(RB) & 0x3f;
1086
1087   XER &= ~XER_CA;
1088
1089   if( sh > 31 ) {
1090      if (REG(RS) & 0x80000000)
1091         REG(RA) = 0xffffffff;
1092      else
1093         REG(RA) = 0;
1094      if( REG(RA) )
1095         XER |= XER_CA;
1096   }
1097   else {
1098      REG(RA) = (INT32)(REG(RS)) >> sh;
1099      if( ((INT32)(REG(RS)) < 0) && (REG(RS) & BITMASK_0(sh)) )
1100         XER |= XER_CA;
1101   }
1102
1103   if( RCBIT ) {
1104      SET_CR0(REG(RA));
1105   }
1106}
1107
1108static void ppc_srawix(UINT32 op)
1109{
1110   int sh = SH;
1111
1112   XER &= ~XER_CA;
1113   if( ((INT32)(REG(RS)) < 0) && (REG(RS) & BITMASK_0(sh)) )
1114      XER |= XER_CA;
1115
1116   REG(RA) = (INT32)(REG(RS)) >> sh;
1117
1118   if( RCBIT ) {
1119      SET_CR0(REG(RA));
1120   }
1121}
1122
1123static void ppc_srwx(UINT32 op)
1124{
1125   int sh = REG(RB) & 0x3f;
1126
1127   if( sh > 31 ) {
1128      REG(RA) = 0;
1129   }
1130   else {
1131      REG(RA) = REG(RS) >> sh;
1132   }
1133
1134   if( RCBIT ) {
1135      SET_CR0(REG(RA));
1136   }
1137}
1138
1139#ifndef PPC_DRC
1140static void ppc_stb(UINT32 op)
1141{
1142   UINT32 ea;
1143
1144   if( RA == 0 )
1145      ea = SIMM16;
1146   else
1147      ea = REG(RA) + SIMM16;
1148
1149   WRITE8(ea, (UINT8)REG(RS));
1150}
1151
1152static void ppc_stbu(UINT32 op)
1153{
1154   UINT32 ea = REG(RA) + SIMM16;
1155
1156   WRITE8(ea, (UINT8)REG(RS));
1157   REG(RA) = ea;
1158}
1159
1160static void ppc_stbux(UINT32 op)
1161{
1162   UINT32 ea = REG(RA) + REG(RB);
1163
1164   WRITE8(ea, (UINT8)REG(RS));
1165   REG(RA) = ea;
1166}
1167
1168static void ppc_stbx(UINT32 op)
1169{
1170   UINT32 ea;
1171
1172   if( RA == 0 )
1173      ea = REG(RB);
1174   else
1175      ea = REG(RA) + REG(RB);
1176
1177   WRITE8(ea, (UINT8)REG(RS));
1178}
1179
1180static void ppc_sth(UINT32 op)
1181{
1182   UINT32 ea;
1183
1184   if( RA == 0 )
1185      ea = SIMM16;
1186   else
1187      ea = REG(RA) + SIMM16;
1188
1189   WRITE16(ea, (UINT16)REG(RS));
1190}
1191
1192static void ppc_sthbrx(UINT32 op)
1193{
1194   UINT32 ea;
1195   UINT16 w;
1196
1197   if( RA == 0 )
1198      ea = REG(RB);
1199   else
1200      ea = REG(RA) + REG(RB);
1201
1202   w = REG(RS);
1203   WRITE16(ea, (UINT16)BYTE_REVERSE16(w));
1204}
1205
1206static void ppc_sthu(UINT32 op)
1207{
1208   UINT32 ea = REG(RA) + SIMM16;
1209
1210   WRITE16(ea, (UINT16)REG(RS));
1211   REG(RA) = ea;
1212}
1213
1214static void ppc_sthux(UINT32 op)
1215{
1216   UINT32 ea = REG(RA) + REG(RB);
1217
1218   WRITE16(ea, (UINT16)REG(RS));
1219   REG(RA) = ea;
1220}
1221
1222static void ppc_sthx(UINT32 op)
1223{
1224   UINT32 ea;
1225
1226   if( RA == 0 )
1227      ea = REG(RB);
1228   else
1229      ea = REG(RA) + REG(RB);
1230
1231   WRITE16(ea, (UINT16)REG(RS));
1232}
1233#endif
1234
1235static void ppc_stmw(UINT32 op)
1236{
1237   UINT32 ea;
1238   int r = RS;
1239
1240   if( RA == 0 )
1241      ea = SIMM16;
1242   else
1243      ea = REG(RA) + SIMM16;
1244
1245   while( r <= 31 )
1246   {
1247      WRITE32(ea, REG(r));
1248      ea += 4;
1249      r++;
1250   }
1251}
1252
1253static void ppc_stswi(UINT32 op)
1254{
1255   int n, r, i;
1256   UINT32 ea = 0;
1257   if( RA != 0 )
1258      ea = REG(RA);
1259
1260   if( RB == 0 )
1261      n = 32;
1262   else
1263      n = RB;
1264
1265   r = RT - 1;
1266   i = 0;
1267
1268   while(n > 0)
1269   {
1270      if (i == 0) {
1271         r = (r + 1) % 32;
1272      }
1273      WRITE8(ea, (REG(r) >> (24-i)) & 0xff);
1274      i += 8;
1275      if (i == 32) {
1276         i = 0;
1277      }
1278      ea++;
1279      n--;
1280   }
1281}
1282
1283static void ppc_stswx(UINT32 op)
1284{
1285   int n, r, i;
1286   UINT32 ea = 0;
1287   if( RA != 0 )
1288      ea = REG(RA);
1289
1290   ea += REG(RB);
1291
1292   n = ppc.xer & 0x7f;
1293
1294   r = RT - 1;
1295   i = 0;
1296
1297   while(n > 0)
1298   {
1299      if (i == 0) {
1300         r = (r + 1) % 32;
1301      }
1302      WRITE8(ea, (REG(r) >> (24-i)) & 0xff);
1303      i += 8;
1304      if (i == 32) {
1305         i = 0;
1306      }
1307      ea++;
1308      n--;
1309   }
1310}
1311
1312#ifndef PPC_DRC
1313static void ppc_stw(UINT32 op)
1314{
1315   UINT32 ea;
1316
1317   if( RA == 0 )
1318      ea = SIMM16;
1319   else
1320      ea = REG(RA) + SIMM16;
1321
1322   WRITE32(ea, REG(RS));
1323}
1324
1325static void ppc_stwbrx(UINT32 op)
1326{
1327   UINT32 ea;
1328   UINT32 w;
1329
1330   if( RA == 0 )
1331      ea = REG(RB);
1332   else
1333      ea = REG(RA) + REG(RB);
1334
1335   w = REG(RS);
1336   WRITE32(ea, BYTE_REVERSE32(w));
1337}
1338#endif
1339
1340static void ppc_stwcx_rc(UINT32 op)
1341{
1342   UINT32 ea;
1343
1344   if( RA == 0 )
1345      ea = REG(RB);
1346   else
1347      ea = REG(RA) + REG(RB);
1348
1349   if( ppc.reserved ) {
1350      WRITE32(ea, REG(RS));
1351
1352      ppc.reserved = 0;
1353      ppc.reserved_address = 0;
1354
1355      CR(0) = 0x2;
1356      if( XER & XER_SO )
1357         CR(0) |= 0x1;
1358   } else {
1359      CR(0) = 0;
1360      if( XER & XER_SO )
1361         CR(0) |= 0x1;
1362   }
1363}
1364
1365#ifndef PPC_DRC
1366static void ppc_stwu(UINT32 op)
1367{
1368   UINT32 ea = REG(RA) + SIMM16;
1369
1370   WRITE32(ea, REG(RS));
1371   REG(RA) = ea;
1372}
1373
1374static void ppc_stwux(UINT32 op)
1375{
1376   UINT32 ea = REG(RA) + REG(RB);
1377
1378   WRITE32(ea, REG(RS));
1379   REG(RA) = ea;
1380}
1381
1382static void ppc_stwx(UINT32 op)
1383{
1384   UINT32 ea;
1385
1386   if( RA == 0 )
1387      ea = REG(RB);
1388   else
1389      ea = REG(RA) + REG(RB);
1390
1391   WRITE32(ea, REG(RS));
1392}
1393
1394static void ppc_subfx(UINT32 op)
1395{
1396   UINT32 ra = REG(RA);
1397   UINT32 rb = REG(RB);
1398   REG(RT) = rb - ra;
1399
1400   if( OEBIT ) {
1401      SET_SUB_OV(REG(RT), rb, ra);
1402   }
1403   if( RCBIT ) {
1404      SET_CR0(REG(RT));
1405   }
1406}
1407#endif
1408
1409static void ppc_subfcx(UINT32 op)
1410{
1411   UINT32 ra = REG(RA);
1412   UINT32 rb = REG(RB);
1413   REG(RT) = rb - ra;
1414
1415   SET_SUB_CA(REG(RT), rb, ra);
1416
1417   if( OEBIT ) {
1418      SET_SUB_OV(REG(RT), rb, ra);
1419   }
1420   if( RCBIT ) {
1421      SET_CR0(REG(RT));
1422   }
1423}
1424
1425#ifndef PPC_DRC
1426static void ppc_subfex(UINT32 op)
1427{
1428   UINT32 ra = REG(RA);
1429   UINT32 rb = REG(RB);
1430   UINT32 carry = (XER >> 29) & 0x1;
1431   UINT32 r;
1432
1433   r = ~ra + carry;
1434   REG(RT) = rb + r;
1435
1436   SET_ADD_CA(r, ~ra, carry);      /* step 1 carry */
1437   if( REG(RT) < r )               /* step 2 carry */
1438      XER |= XER_CA;
1439
1440   if( OEBIT ) {
1441      SET_SUB_OV(REG(RT), rb, ra);
1442   }
1443   if( RCBIT ) {
1444      SET_CR0(REG(RT));
1445   }
1446}
1447
1448static void ppc_subfic(UINT32 op)
1449{
1450   UINT32 i = SIMM16;
1451   UINT32 ra = REG(RA);
1452
1453   REG(RT) = i - ra;
1454
1455   SET_SUB_CA(REG(RT), i, ra);
1456}
1457#endif
1458
1459static void ppc_subfmex(UINT32 op)
1460{
1461   UINT32 ra = REG(RA);
1462   UINT32 carry = (XER >> 29) & 0x1;
1463   UINT32 r;
1464
1465   r = ~ra + carry;
1466   REG(RT) = r - 1;
1467
1468   SET_SUB_CA(r, ~ra, carry);      /* step 1 carry */
1469   if( REG(RT) < r )
1470      XER |= XER_CA;              /* step 2 carry */
1471
1472   if( OEBIT ) {
1473      SET_SUB_OV(REG(RT), -1, ra);
1474   }
1475   if( RCBIT ) {
1476      SET_CR0(REG(RT));
1477   }
1478}
1479
1480static void ppc_subfzex(UINT32 op)
1481{
1482   UINT32 ra = REG(RA);
1483   UINT32 carry = (XER >> 29) & 0x1;
1484
1485   REG(RT) = ~ra + carry;
1486
1487   SET_ADD_CA(REG(RT), ~ra, carry);
1488
1489   if( OEBIT ) {
1490      SET_SUB_OV(REG(RT), 0, REG(RA));
1491   }
1492   if( RCBIT ) {
1493      SET_CR0(REG(RT));
1494   }
1495}
1496
1497#ifndef PPC_DRC
1498static void ppc_sync(UINT32 op)
1499{
1500}
1501#endif
1502
1503#ifndef PPC_DRC
1504static void ppc_tw(UINT32 op)
1505{
1506   int exception = 0;
1507   INT32 a = REG(RA);
1508   INT32 b = REG(RB);
1509   int to = RT;
1510
1511   if( (a < b) && (to & 0x10) ) {
1512      exception = 1;
1513   }
1514   if( (a > b) && (to & 0x08) ) {
1515      exception = 1;
1516   }
1517   if( (a == b) && (to & 0x04) ) {
1518      exception = 1;
1519   }
1520   if( ((UINT32)a < (UINT32)b) && (to & 0x02) ) {
1521      exception = 1;
1522   }
1523   if( ((UINT32)a > (UINT32)b) && (to & 0x01) ) {
1524      exception = 1;
1525   }
1526
1527   if (exception) {
1528      if (ppc.is603) {
1529         ppc603_exception(EXCEPTION_TRAP);
1530      }
1531      if (ppc.is602) {
1532         ppc602_exception(EXCEPTION_TRAP);
1533      }
1534      if (IS_PPC403()) {
1535         ppc403_exception(EXCEPTION_TRAP);
1536      }
1537   }
1538}
1539#endif
1540
1541#ifndef PPC_DRC
1542static void ppc_twi(UINT32 op)
1543{
1544   int exception = 0;
1545   INT32 a = REG(RA);
1546   INT32 i = SIMM16;
1547   int to = RT;
1548
1549   if( (a < i) && (to & 0x10) ) {
1550      exception = 1;
1551   }
1552   if( (a > i) && (to & 0x08) ) {
1553      exception = 1;
1554   }
1555   if( (a == i) && (to & 0x04) ) {
1556      exception = 1;
1557   }
1558   if( ((UINT32)a < (UINT32)i) && (to & 0x02) ) {
1559      exception = 1;
1560   }
1561   if( ((UINT32)a > (UINT32)i) && (to & 0x01) ) {
1562      exception = 1;
1563   }
1564
1565   if (exception) {
1566      if (ppc.is603) {
1567         ppc603_exception(EXCEPTION_TRAP);
1568      }
1569      if (ppc.is602) {
1570         ppc602_exception(EXCEPTION_TRAP);
1571      }
1572      if (IS_PPC403()) {
1573         ppc403_exception(EXCEPTION_TRAP);
1574      }
1575   }
1576}
1577#endif
1578
1579#ifndef PPC_DRC
1580static void ppc_xorx(UINT32 op)
1581{
1582   REG(RA) = REG(RS) ^ REG(RB);
1583
1584   if( RCBIT ) {
1585      SET_CR0(REG(RA));
1586   }
1587}
1588
1589static void ppc_xori(UINT32 op)
1590{
1591   REG(RA) = REG(RS) ^ UIMM16;
1592}
1593
1594static void ppc_xoris(UINT32 op)
1595{
1596   REG(RA) = REG(RS) ^ (UIMM16 << 16);
1597}
1598
1599
1600
1601static void ppc_invalid(UINT32 op)
1602{
1603   fatalerror("ppc: Invalid opcode %08X PC : %X\n", op, ppc.pc);
1604}
1605#endif
1606
1607
1608// Everything below is new from AJG
1609
1610////////////////////////////
1611// !here are the 6xx ops! //
1612////////////////////////////
1613
1614#define DOUBLE_SIGN     (U64(0x8000000000000000))
1615#define DOUBLE_EXP      (U64(0x7ff0000000000000))
1616#define DOUBLE_FRAC     (U64(0x000fffffffffffff))
1617#define DOUBLE_ZERO     (0)
1618
1619/*
1620  Floating point operations.
1621*/
1622
1623INLINE int is_nan_double(FPR x)
1624{
1625   return( ((x.id & DOUBLE_EXP) == DOUBLE_EXP) &&
1626         ((x.id & DOUBLE_FRAC) != DOUBLE_ZERO) );
1627}
1628
1629INLINE int is_qnan_double(FPR x)
1630{
1631   return( ((x.id & DOUBLE_EXP) == DOUBLE_EXP) &&
1632         ((x.id & U64(0x0007fffffffffff)) == U64(0x000000000000000)) &&
1633         ((x.id & U64(0x000800000000000)) == U64(0x000800000000000)) );
1634}
1635
1636INLINE int is_snan_double(FPR x)
1637{
1638   return( ((x.id & DOUBLE_EXP) == DOUBLE_EXP) &&
1639         ((x.id & DOUBLE_FRAC) != DOUBLE_ZERO) &&
1640         ((x.id & U64(0x0008000000000000)) == DOUBLE_ZERO) );
1641}
1642
1643INLINE int is_infinity_double(FPR x)
1644{
1645   return( ((x.id & DOUBLE_EXP) == DOUBLE_EXP) &&
1646         ((x.id & DOUBLE_FRAC) == DOUBLE_ZERO) );
1647}
1648
1649INLINE int is_normalized_double(FPR x)
1650{
1651   UINT64 exp;
1652
1653   exp = (x.id & DOUBLE_EXP) >> 52;
1654
1655   return (exp >= 1) && (exp <= 2046);
1656}
1657
1658INLINE int is_denormalized_double(FPR x)
1659{
1660   return( ((x.id & DOUBLE_EXP) == 0) &&
1661         ((x.id & DOUBLE_FRAC) != DOUBLE_ZERO) );
1662}
1663
1664INLINE int sign_double(FPR x)
1665{
1666   return ((x.id & DOUBLE_SIGN) != 0);
1667}
1668
1669INLINE INT64 round_to_nearest(FPR f)
1670{
1671   if (f.fd >= 0)
1672   {
1673      return (INT64)(f.fd + 0.5);
1674   }
1675   else
1676   {
1677      return -(INT64)(-f.fd + 0.5);
1678   }
1679}
1680
1681INLINE INT64 round_toward_zero(FPR f)
1682{
1683   return (INT64)(f.fd);
1684}
1685
1686INLINE INT64 round_toward_positive_infinity(FPR f)
1687{
1688   double r = ceil(f.fd);
1689   return (INT64)(r);
1690}
1691
1692INLINE INT64 round_toward_negative_infinity(FPR f)
1693{
1694   double r = floor(f.fd);
1695   return (INT64)(r);
1696}
1697
1698
1699INLINE void set_fprf(FPR f)
1700{
1701   UINT32 fprf;
1702
1703   // see page 3-30, 3-31
1704
1705   if (is_qnan_double(f))
1706   {
1707      fprf = 0x11;
1708   }
1709   else if (is_infinity_double(f))
1710   {
1711      if (sign_double(f))     // -INF
1712         fprf = 0x09;
1713      else                    // +INF
1714         fprf = 0x05;
1715   }
1716   else if (is_normalized_double(f))
1717   {
1718      if (sign_double(f))     // -Normalized
1719         fprf = 0x08;
1720      else                    // +Normalized
1721         fprf = 0x04;
1722   }
1723   else if (is_denormalized_double(f))
1724   {
1725      if (sign_double(f))     // -Denormalized
1726         fprf = 0x18;
1727      else                    // +Denormalized
1728         fprf = 0x14;
1729   }
1730   else    // Zero
1731   {
1732      if (sign_double(f))     // -Zero
1733         fprf = 0x12;
1734      else                    // +Zero
1735         fprf = 0x02;
1736   }
1737
1738   ppc.fpscr &= ~0x0001f000;
1739   ppc.fpscr |= (fprf << 12);
1740}
1741
1742
1743
1744#define SET_VXSNAN(a, b)    if (is_snan_double(a) || is_snan_double(b)) ppc.fpscr |= 0x80000000
1745#define SET_VXSNAN_1(c)     if (is_snan_double(c)) ppc.fpscr |= 0x80000000
1746
1747
1748
1749
1750static void ppc_lfs(UINT32 op)
1751{
1752   UINT32 ea = SIMM16;
1753   UINT32 a = RA;
1754   UINT32 t = RT;
1755   FPR32 f;
1756
1757   if(a)
1758      ea += REG(a);
1759
1760   f.i = READ32(ea);
1761   FPR(t).fd = (double)(f.f);
1762}
1763
1764static void ppc_lfsu(UINT32 op)
1765{
1766   UINT32 ea = SIMM16;
1767   UINT32 a = RA;
1768   UINT32 t = RT;
1769   FPR32 f;
1770
1771   ea += REG(a);
1772
1773   f.i = READ32(ea);
1774   FPR(t).fd = (double)(f.f);
1775
1776   REG(a) = ea;
1777}
1778
1779#ifndef PPC_DRC
1780static void ppc_lfd(UINT32 op)
1781{
1782   UINT32 ea = SIMM16;
1783   UINT32 a = RA;
1784   UINT32 t = RT;
1785
1786   if(a)
1787      ea += REG(a);
1788
1789   FPR(t).id = READ64(ea);
1790}
1791
1792static void ppc_lfdu(UINT32 op)
1793{
1794   UINT32 ea = SIMM16;
1795   UINT32 a = RA;
1796   UINT32 d = RD;
1797
1798   ea += REG(a);
1799
1800   FPR(d).id = READ64(ea);
1801
1802   REG(a) = ea;
1803}
1804#endif
1805
1806static void ppc_stfs(UINT32 op)
1807{
1808   UINT32 ea = SIMM16;
1809   UINT32 a = RA;
1810   UINT32 t = RT;
1811   FPR32 f;
1812
1813   if(a)
1814      ea += REG(a);
1815
1816   f.f = (float)(FPR(t).fd);
1817   WRITE32(ea, f.i);
1818}
1819
1820static void ppc_stfsu(UINT32 op)
1821{
1822   UINT32 ea = SIMM16;
1823   UINT32 a = RA;
1824   UINT32 t = RT;
1825   FPR32 f;
1826
1827   ea += REG(a);
1828
1829   f.f = (float)(FPR(t).fd);
1830   WRITE32(ea, f.i);
1831
1832   REG(a) = ea;
1833}
1834
1835#ifndef PPC_DRC
1836static void ppc_stfd(UINT32 op)
1837{
1838   UINT32 ea = SIMM16;
1839   UINT32 a = RA;
1840   UINT32 t = RT;
1841
1842   if(a)
1843      ea += REG(a);
1844
1845   WRITE64(ea, FPR(t).id);
1846}
1847
1848static void ppc_stfdu(UINT32 op)
1849{
1850   UINT32 ea = SIMM16;
1851   UINT32 a = RA;
1852   UINT32 t = RT;
1853
1854   ea += REG(a);
1855
1856   WRITE64(ea, FPR(t).id);
1857
1858   REG(a) = ea;
1859}
1860
1861static void ppc_lfdux(UINT32 op)
1862{
1863   UINT32 ea = REG(RB);
1864   UINT32 a = RA;
1865   UINT32 d = RD;
1866
1867   ea += REG(a);
1868
1869   FPR(d).id = READ64(ea);
1870
1871   REG(a) = ea;
1872}
1873
1874static void ppc_lfdx(UINT32 op)
1875{
1876   UINT32 ea = REG(RB);
1877   UINT32 a = RA;
1878   UINT32 d = RD;
1879
1880   if(a)
1881      ea += REG(a);
1882
1883   FPR(d).id = READ64(ea);
1884}
1885#endif
1886
1887static void ppc_lfsux(UINT32 op)
1888{
1889   UINT32 ea = REG(RB);
1890   UINT32 a = RA;
1891   UINT32 t = RT;
1892   FPR32 f;
1893
1894   ea += REG(a);
1895
1896   f.i = READ32(ea);
1897   FPR(t).fd = (double)(f.f);
1898
1899   REG(a) = ea;
1900}
1901
1902static void ppc_lfsx(UINT32 op)
1903{
1904   UINT32 ea = REG(RB);
1905   UINT32 a = RA;
1906   UINT32 t = RT;
1907   FPR32 f;
1908
1909   if(a)
1910      ea += REG(a);
1911
1912   f.i = READ32(ea);
1913   FPR(t).fd = (double)(f.f);
1914}
1915
1916static void ppc_mfsr(UINT32 op)
1917{
1918   UINT32 sr = (op >> 16) & 15;
1919   UINT32 t = RT;
1920
1921   CHECK_SUPERVISOR();
1922
1923   REG(t) = ppc.sr[sr];
1924}
1925
1926static void ppc_mfsrin(UINT32 op)
1927{
1928   UINT32 b = RB;
1929   UINT32 t = RT;
1930
1931   CHECK_SUPERVISOR();
1932
1933   REG(t) = ppc.sr[REG(b) >> 28];
1934}
1935
1936static void ppc_mftb(UINT32 op)
1937{
1938   UINT32 x = SPRF;
1939
1940   switch(x)
1941   {
1942      case 268:   REG(RT) = (UINT32)(ppc_read_timebase()); break;
1943      case 269:   REG(RT) = (UINT32)(ppc_read_timebase() >> 32); break;
1944      default:    fatalerror("ppc: Invalid timebase register %d at %08X\n", x, ppc.pc); break;
1945   }
1946}
1947
1948static void ppc_mtsr(UINT32 op)
1949{
1950   UINT32 sr = (op >> 16) & 15;
1951   UINT32 t = RT;
1952
1953   CHECK_SUPERVISOR();
1954
1955   ppc.sr[sr] = REG(t);
1956}
1957
1958static void ppc_mtsrin(UINT32 op)
1959{
1960   UINT32 b = RB;
1961   UINT32 t = RT;
1962
1963   CHECK_SUPERVISOR();
1964
1965   ppc.sr[REG(b) >> 28] = REG(t);
1966}
1967
1968#ifndef PPC_DRC
1969static void ppc_dcba(UINT32 op)
1970{
1971   /* TODO: Cache not emulated so this opcode doesn't need to be implemented */
1972}
1973
1974static void ppc_stfdux(UINT32 op)
1975{
1976   UINT32 ea = REG(RB);
1977   UINT32 a = RA;
1978   UINT32 t = RT;
1979
1980   ea += REG(a);
1981
1982   WRITE64(ea, FPR(t).id);
1983
1984   REG(a) = ea;
1985}
1986#endif
1987
1988static void ppc_stfdx(UINT32 op)
1989{
1990   UINT32 ea = REG(RB);
1991   UINT32 a = RA;
1992   UINT32 t = RT;
1993
1994   if(a)
1995      ea += REG(a);
1996
1997   WRITE64(ea, FPR(t).id);
1998}
1999
2000static void ppc_stfiwx(UINT32 op)
2001{
2002   UINT32 ea = REG(RB);
2003   UINT32 a = RA;
2004   UINT32 t = RT;
2005
2006   if(a)
2007      ea += REG(a);
2008
2009   WRITE32(ea, (UINT32)FPR(t).id);
2010}
2011
2012static void ppc_stfsux(UINT32 op)
2013{
2014   UINT32 ea = REG(RB);
2015   UINT32 a = RA;
2016   UINT32 t = RT;
2017   FPR32 f;
2018
2019   ea += REG(a);
2020
2021   f.f = (float)(FPR(t).fd);
2022   WRITE32(ea, f.i);
2023
2024   REG(a) = ea;
2025}
2026
2027static void ppc_stfsx(UINT32 op)
2028{
2029   UINT32 ea = REG(RB);
2030   UINT32 a = RA;
2031   UINT32 t = RT;
2032   FPR32 f;
2033
2034   if(a)
2035      ea += REG(a);
2036
2037   f.f = (float)(FPR(t).fd);
2038
2039   WRITE32(ea, f.i);
2040}
2041
2042#ifndef PPC_DRC
2043static void ppc_tlbia(UINT32 op)
2044{
2045   /* TODO: TLB not emulated so this opcode doesn't need to implemented */
2046}
2047
2048static void ppc_tlbie(UINT32 op)
2049{
2050   /* TODO: TLB not emulated so this opcode doesn't need to implemented */
2051}
2052
2053static void ppc_tlbsync(UINT32 op)
2054{
2055   /* TODO: TLB not emulated so this opcode doesn't need to implemented */
2056}
2057
2058static void ppc_eciwx(UINT32 op)
2059{
2060   ppc_unimplemented(op);
2061}
2062
2063static void ppc_ecowx(UINT32 op)
2064{
2065   ppc_unimplemented(op);
2066}
2067#endif
2068
2069static void ppc_fabsx(UINT32 op)
2070{
2071   UINT32 b = RB;
2072   UINT32 t = RT;
2073
2074   CHECK_FPU_AVAILABLE();
2075
2076   FPR(t).id = FPR(b).id & ~DOUBLE_SIGN;
2077
2078   if( RCBIT ) {
2079      SET_CR1();
2080   }
2081}
2082
2083static void ppc_faddx(UINT32 op)
2084{
2085   UINT32 b = RB;
2086   UINT32 a = RA;
2087   UINT32 t = RT;
2088
2089   CHECK_FPU_AVAILABLE();
2090
2091   SET_VXSNAN(FPR(a), FPR(b));
2092
2093   FPR(t).fd = FPR(a).fd + FPR(b).fd;
2094
2095   set_fprf(FPR(t));
2096   if( RCBIT ) {
2097      SET_CR1();
2098   }
2099}
2100
2101static void ppc_fcmpo(UINT32 op)
2102{
2103   UINT32 b = RB;
2104   UINT32 a = RA;
2105   UINT32 t = (RT >> 2);
2106   UINT32 c;
2107
2108   CHECK_FPU_AVAILABLE();
2109
2110   SET_VXSNAN(FPR(a), FPR(b));
2111
2112   if(is_nan_double(FPR(a)) || is_nan_double(FPR(b)))
2113   {
2114      c = 1; /* OX */
2115      if(is_snan_double(FPR(a)) || is_snan_double(FPR(b))) {
2116         ppc.fpscr |= 0x01000000; /* VXSNAN */
2117
2118         if(!(ppc.fpscr & 0x40000000) || is_qnan_double(FPR(a)) || is_qnan_double(FPR(b)))
2119            ppc.fpscr |= 0x00080000; /* VXVC */
2120      }
2121   }
2122   else if(FPR(a).fd < FPR(b).fd){
2123      c = 8; /* FX */
2124   }
2125   else if(FPR(a).fd > FPR(b).fd){
2126      c = 4; /* FEX */
2127   }
2128   else {
2129      c = 2; /* VX */
2130   }
2131
2132   CR(t) = c;
2133
2134   ppc.fpscr &= ~0x0001F000;
2135   ppc.fpscr |= (c << 12);
2136}
2137
2138static void ppc_fcmpu(UINT32 op)
2139{
2140   UINT32 b = RB;
2141   UINT32 a = RA;
2142   UINT32 t = (RT >> 2);
2143   UINT32 c;
2144
2145   CHECK_FPU_AVAILABLE();
2146
2147   SET_VXSNAN(FPR(a), FPR(b));
2148
2149   if(is_nan_double(FPR(a)) || is_nan_double(FPR(b)))
2150   {
2151      c = 1; /* OX */
2152      if(is_snan_double(FPR(a)) || is_snan_double(FPR(b))) {
2153         ppc.fpscr |= 0x01000000; /* VXSNAN */
2154      }
2155   }
2156   else if(FPR(a).fd < FPR(b).fd){
2157      c = 8; /* FX */
2158   }
2159   else if(FPR(a).fd > FPR(b).fd){
2160      c = 4; /* FEX */
2161   }
2162   else {
2163      c = 2; /* VX */
2164   }
2165
2166   CR(t) = c;
2167
2168   ppc.fpscr &= ~0x0001F000;
2169   ppc.fpscr |= (c << 12);
2170}
2171
2172static void ppc_fctiwx(UINT32 op)
2173{
2174   UINT32 b = RB;
2175   UINT32 t = RT;
2176   INT64 r = 0;
2177
2178   // TODO: fix FPSCR flags FX,VXSNAN,VXCVI
2179
2180   CHECK_FPU_AVAILABLE();
2181
2182   SET_VXSNAN_1(FPR(b));
2183
2184   switch(ppc.fpscr & 3)
2185   {
2186      case 0: r = (INT64)round_to_nearest(FPR(b)); break;
2187      case 1: r = (INT64)round_toward_zero(FPR(b)); break;
2188      case 2: r = (INT64)round_toward_positive_infinity(FPR(b)); break;
2189      case 3: r = (INT64)round_toward_negative_infinity(FPR(b)); break;
2190   }
2191
2192   if(r > (INT64)((INT32)0x7FFFFFFF))
2193   {
2194      FPR(t).id = 0x7FFFFFFF;
2195      // FPSCR[FR] = 0
2196      // FPSCR[FI] = 1
2197      // FPSCR[XX] = 1
2198   }
2199   else if(FPR(b).fd < (INT64)((INT32)0x80000000))
2200   {
2201      FPR(t).id = 0x80000000;
2202      // FPSCR[FR] = 1
2203      // FPSCR[FI] = 1
2204      // FPSCR[XX] = 1
2205   }
2206   else
2207   {
2208      FPR(t).id = (UINT32)r;
2209      // FPSCR[FR] = t.iw > t.fd
2210      // FPSCR[FI] = t.iw == t.fd
2211      // FPSCR[XX] = ?
2212   }
2213
2214   // FPSCR[FPRF] = undefined (leave it as is)
2215   if( RCBIT ) {
2216      SET_CR1();
2217   }
2218}
2219
2220static void ppc_fctiwzx(UINT32 op)
2221{
2222   UINT32 b = RB;
2223   UINT32 t = RT;
2224   INT64 r;
2225
2226   // TODO: fix FPSCR flags FX,VXSNAN,VXCVI
2227
2228   CHECK_FPU_AVAILABLE();
2229
2230   SET_VXSNAN_1(FPR(b));
2231   r = round_toward_zero(FPR(b));
2232
2233   if(r > (INT64)((INT32)0x7fffffff))
2234   {
2235      FPR(t).id = 0x7fffffff;
2236      // FPSCR[FR] = 0
2237      // FPSCR[FI] = 1
2238      // FPSCR[XX] = 1
2239
2240   }
2241   else if(r < (INT64)((INT32)0x80000000))
2242   {
2243      FPR(t).id = 0x80000000;
2244      // FPSCR[FR] = 1
2245      // FPSCR[FI] = 1
2246      // FPSCR[XX] = 1
2247   }
2248   else
2249   {
2250      FPR(t).id = (UINT32)r;
2251      // FPSCR[FR] = t.iw > t.fd
2252      // FPSCR[FI] = t.iw == t.fd
2253      // FPSCR[XX] = ?
2254   }
2255
2256   // FPSCR[FPRF] = undefined (leave it as is)
2257   if( RCBIT ) {
2258      SET_CR1();
2259   }
2260}
2261
2262static void ppc_fdivx(UINT32 op)
2263{
2264   UINT32 b = RB;
2265   UINT32 a = RA;
2266   UINT32 t = RT;
2267
2268   CHECK_FPU_AVAILABLE();
2269
2270   SET_VXSNAN(FPR(a), FPR(b));
2271
2272   FPR(t).fd = FPR(a).fd / FPR(b).fd;
2273
2274   set_fprf(FPR(t));
2275   if( RCBIT ) {
2276      SET_CR1();
2277   }
2278}
2279
2280static void ppc_fmrx(UINT32 op)
2281{
2282   UINT32 b = RB;
2283   UINT32 t = RT;
2284
2285   CHECK_FPU_AVAILABLE();
2286
2287   FPR(t).fd = FPR(b).fd;
2288
2289   if( RCBIT ) {
2290      SET_CR1();
2291   }
2292}
2293
2294static void ppc_fnabsx(UINT32 op)
2295{
2296   UINT32 b = RB;
2297   UINT32 t = RT;
2298
2299   CHECK_FPU_AVAILABLE();
2300
2301   FPR(t).id = FPR(b).id | DOUBLE_SIGN;
2302
2303   if( RCBIT ) {
2304      SET_CR1();
2305   }
2306}
2307
2308static void ppc_fnegx(UINT32 op)
2309{
2310   UINT32 b = RB;
2311   UINT32 t = RT;
2312
2313   CHECK_FPU_AVAILABLE();
2314
2315   FPR(t).id = FPR(b).id ^ DOUBLE_SIGN;
2316
2317   if( RCBIT ) {
2318      SET_CR1();
2319   }
2320}
2321
2322static void ppc_frspx(UINT32 op)
2323{
2324   UINT32 b = RB;
2325   UINT32 t = RT;
2326
2327   CHECK_FPU_AVAILABLE();
2328
2329   SET_VXSNAN_1(FPR(b));
2330
2331   FPR(t).fd = (float)FPR(b).fd;
2332
2333   set_fprf(FPR(t));
2334   if( RCBIT ) {
2335      SET_CR1();
2336   }
2337}
2338
2339static void ppc_frsqrtex(UINT32 op)
2340{
2341   UINT32 b = RB;
2342   UINT32 t = RT;
2343
2344   CHECK_FPU_AVAILABLE();
2345
2346   SET_VXSNAN_1(FPR(b));
2347
2348   FPR(t).fd = 1.0 / sqrt(FPR(b).fd);  /* verify this */
2349
2350   set_fprf(FPR(t));
2351   if( RCBIT ) {
2352      SET_CR1();
2353   }
2354}
2355
2356static void ppc_fsqrtx(UINT32 op)
2357{
2358   /* NOTE: PPC603e doesn't support this opcode */
2359   UINT32 b = RB;
2360   UINT32 t = RT;
2361
2362   CHECK_FPU_AVAILABLE();
2363
2364   SET_VXSNAN_1(FPR(b));
2365
2366   FPR(t).fd = (double)(sqrt(FPR(b).fd));
2367
2368   set_fprf(FPR(t));
2369   if( RCBIT ) {
2370      SET_CR1();
2371   }
2372}
2373
2374static void ppc_fsubx(UINT32 op)
2375{
2376   UINT32 b = RB;
2377   UINT32 a = RA;
2378   UINT32 t = RT;
2379
2380   CHECK_FPU_AVAILABLE();
2381
2382   SET_VXSNAN(FPR(a), FPR(b));
2383
2384   FPR(t).fd = FPR(a).fd - FPR(b).fd;
2385
2386   set_fprf(FPR(t));
2387   if( RCBIT ) {
2388      SET_CR1();
2389   }
2390}
2391
2392static void ppc_mffsx(UINT32 op)
2393{
2394   FPR(RT).id = (UINT32)ppc.fpscr;
2395
2396   if( RCBIT ) {
2397      SET_CR1();
2398   }
2399}
2400
2401static void ppc_mtfsb0x(UINT32 op)
2402{
2403   UINT32 crbD;
2404
2405   crbD = (op >> 21) & 0x1F;
2406
2407   if (crbD != 1 && crbD != 2) // these bits cannot be explicitly cleared
2408      ppc.fpscr &= ~(1 << (31 - crbD));
2409
2410   if( RCBIT ) {
2411      SET_CR1();
2412   }
2413}
2414
2415static void ppc_mtfsb1x(UINT32 op)
2416{
2417   UINT32 crbD;
2418
2419   crbD = (op >> 21) & 0x1F;
2420
2421   if (crbD != 1 && crbD != 2) // these bits cannot be explicitly cleared
2422      ppc.fpscr |= (1 << (31 - crbD));
2423
2424   if( RCBIT ) {
2425      SET_CR1();
2426   }
2427}
2428
2429static void ppc_mtfsfx(UINT32 op)
2430{
2431   UINT32 b = RB;
2432   UINT32 f = FM;
2433
2434   f = ppc_field_xlat[FM];
2435
2436   ppc.fpscr &= (~f) | ~(FPSCR_FEX | FPSCR_VX);
2437   ppc.fpscr |= (UINT32)(FPR(b).id) & ~(FPSCR_FEX | FPSCR_VX);
2438
2439   // FEX, VX
2440
2441   if( RCBIT ) {
2442      SET_CR1();
2443   }
2444}
2445
2446static void ppc_mtfsfix(UINT32 op)
2447{
2448   UINT32 crfd = CRFD;
2449   UINT32 imm = (op >> 12) & 0xF;
2450
2451   /*
2452    * According to the manual:
2453    *
2454    * If bits 0 and 3 of FPSCR are to be modified, they take the immediate
2455    * value specified. Bits 1 and 2 (FEX and VX) are set according to the
2456    * "usual rule" and not from IMM[1-2].
2457    *
2458    * The "usual rule" is not emulated, so these bits simply aren't modified
2459    * at all here.
2460    */
2461
2462   crfd = (7 - crfd) * 4;  // calculate LSB position of field
2463
2464   if (crfd == 28)         // field containing FEX and VX is special...
2465   {                       // bits 1 and 2 of FPSCR must not be altered
2466      ppc.fpscr &= 0x9fffffff;
2467      ppc.fpscr |= (imm & 0x9fffffff);
2468   }
2469
2470   ppc.fpscr &= ~(0xf << crfd);    // clear field
2471   ppc.fpscr |= (imm << crfd);     // insert new data
2472
2473   if( RCBIT ) {
2474      SET_CR1();
2475   }
2476}
2477
2478static void ppc_mcrfs(UINT32 op)
2479{
2480   UINT32 crfs, f;
2481   crfs = CRFA;
2482
2483   f = ppc.fpscr >> ((7 - crfs) * 4);  // get crfS field from FPSCR
2484   f &= 0xf;
2485
2486   switch(crfs)    // determine which exception bits to clear in FPSCR
2487   {
2488      case 0:     // FX, OX
2489         ppc.fpscr &= ~0x90000000;
2490         break;
2491      case 1:     // UX, ZX, XX, VXSNAN
2492         ppc.fpscr &= ~0x0f000000;
2493         break;
2494      case 2:     // VXISI, VXIDI, VXZDZ, VXIMZ
2495         ppc.fpscr &= ~0x00F00000;
2496         break;
2497      case 3:     // VXVC
2498         ppc.fpscr &= ~0x00080000;
2499         break;
2500      case 5:     // VXSOFT, VXSQRT, VXCVI
2501         ppc.fpscr &= ~0x00000e00;
2502         break;
2503      default:
2504         break;
2505   }
2506
2507   CR(CRFD) = f;
2508}
2509
2510static void ppc_faddsx(UINT32 op)
2511{
2512   UINT32 b = RB;
2513   UINT32 a = RA;
2514   UINT32 t = RT;
2515
2516   CHECK_FPU_AVAILABLE();
2517
2518   SET_VXSNAN(FPR(a), FPR(b));
2519
2520   FPR(t).fd = (float)(FPR(a).fd + FPR(b).fd);
2521
2522   set_fprf(FPR(t));
2523   if( RCBIT ) {
2524      SET_CR1();
2525   }
2526}
2527
2528static void ppc_fdivsx(UINT32 op)
2529{
2530   UINT32 b = RB;
2531   UINT32 a = RA;
2532   UINT32 t = RT;
2533
2534   CHECK_FPU_AVAILABLE();
2535
2536   SET_VXSNAN(FPR(a), FPR(b));
2537
2538   FPR(t).fd = (float)(FPR(a).fd / FPR(b).fd);
2539
2540   set_fprf(FPR(t));
2541   if( RCBIT ) {
2542      SET_CR1();
2543   }
2544}
2545
2546static void ppc_fresx(UINT32 op)
2547{
2548   UINT32 b = RB;
2549   UINT32 t = RT;
2550
2551   CHECK_FPU_AVAILABLE();
2552
2553   SET_VXSNAN_1(FPR(b));
2554
2555   FPR(t).fd = 1.0 / FPR(b).fd; /* ??? */
2556
2557   set_fprf(FPR(t));
2558   if( RCBIT ) {
2559      SET_CR1();
2560   }
2561}
2562
2563static void ppc_fsqrtsx(UINT32 op)
2564{
2565   /* NOTE: This opcode is not supported in PPC603e */
2566   UINT32 b = RB;
2567   UINT32 t = RT;
2568
2569   CHECK_FPU_AVAILABLE();
2570
2571   SET_VXSNAN_1(FPR(b));
2572
2573   FPR(t).fd = (float)(sqrt(FPR(b).fd));
2574
2575   set_fprf(FPR(t));
2576   if( RCBIT ) {
2577      SET_CR1();
2578   }
2579}
2580
2581static void ppc_fsubsx(UINT32 op)
2582{
2583   UINT32 b = RB;
2584   UINT32 a = RA;
2585   UINT32 t = RT;
2586
2587   CHECK_FPU_AVAILABLE();
2588
2589   SET_VXSNAN(FPR(a), FPR(b));
2590
2591   FPR(t).fd = (float)(FPR(a).fd - FPR(b).fd);
2592
2593   set_fprf(FPR(t));
2594   if( RCBIT ) {
2595      SET_CR1();
2596   }
2597}
2598
2599static void ppc_fmaddx(UINT32 op)
2600{
2601   UINT32 c = RC;
2602   UINT32 b = RB;
2603   UINT32 a = RA;
2604   UINT32 t = RT;
2605
2606   CHECK_FPU_AVAILABLE();
2607
2608   SET_VXSNAN(FPR(a), FPR(b));
2609   SET_VXSNAN_1(FPR(c));
2610
2611   FPR(t).fd = ((FPR(a).fd * FPR(c).fd) + FPR(b).fd);
2612
2613   set_fprf(FPR(t));
2614   if( RCBIT ) {
2615      SET_CR1();
2616   }
2617}
2618
2619static void ppc_fmsubx(UINT32 op)
2620{
2621   UINT32 c = RC;
2622   UINT32 b = RB;
2623   UINT32 a = RA;
2624   UINT32 t = RT;
2625
2626   CHECK_FPU_AVAILABLE();
2627
2628   SET_VXSNAN(FPR(a), FPR(b));
2629   SET_VXSNAN_1(FPR(c));
2630
2631   FPR(t).fd = ((FPR(a).fd * FPR(c).fd) - FPR(b).fd);
2632
2633   set_fprf(FPR(t));
2634   if( RCBIT ) {
2635      SET_CR1();
2636   }
2637}
2638
2639static void ppc_fmulx(UINT32 op)
2640{
2641   UINT32 c = RC;
2642   UINT32 a = RA;
2643   UINT32 t = RT;
2644
2645   CHECK_FPU_AVAILABLE();
2646
2647   SET_VXSNAN(FPR(a), FPR(c));
2648
2649   FPR(t).fd = (FPR(a).fd * FPR(c).fd);
2650
2651   set_fprf(FPR(t));
2652   if( RCBIT ) {
2653      SET_CR1();
2654   }
2655}
2656
2657static void ppc_fnmaddx(UINT32 op)
2658{
2659   UINT32 c = RC;
2660   UINT32 b = RB;
2661   UINT32 a = RA;
2662   UINT32 t = RT;
2663
2664   CHECK_FPU_AVAILABLE();
2665
2666   SET_VXSNAN(FPR(a), FPR(b));
2667   SET_VXSNAN_1(FPR(c));
2668
2669   FPR(t).fd = (-((FPR(a).fd * FPR(c).fd) + FPR(b).fd));
2670
2671   set_fprf(FPR(t));
2672   if( RCBIT ) {
2673      SET_CR1();
2674   }
2675}
2676
2677static void ppc_fnmsubx(UINT32 op)
2678{
2679   UINT32 c = RC;
2680   UINT32 b = RB;
2681   UINT32 a = RA;
2682   UINT32 t = RT;
2683
2684   CHECK_FPU_AVAILABLE();
2685
2686   SET_VXSNAN(FPR(a), FPR(b));
2687   SET_VXSNAN_1(FPR(c));
2688
2689   FPR(t).fd = (-((FPR(a).fd * FPR(c).fd) - FPR(b).fd));
2690
2691   set_fprf(FPR(t));
2692   if( RCBIT ) {
2693      SET_CR1();
2694   }
2695}
2696
2697static void ppc_fselx(UINT32 op)
2698{
2699   UINT32 c = RC;
2700   UINT32 b = RB;
2701   UINT32 a = RA;
2702   UINT32 t = RT;
2703
2704   CHECK_FPU_AVAILABLE();
2705
2706   FPR(t).fd = (FPR(a).fd >= 0.0) ? FPR(c).fd : FPR(b).fd;
2707
2708   if( RCBIT ) {
2709      SET_CR1();
2710   }
2711}
2712
2713static void ppc_fmaddsx(UINT32 op)
2714{
2715   UINT32 c = RC;
2716   UINT32 b = RB;
2717   UINT32 a = RA;
2718   UINT32 t = RT;
2719
2720   CHECK_FPU_AVAILABLE();
2721
2722   SET_VXSNAN(FPR(a), FPR(b));
2723   SET_VXSNAN_1(FPR(c));
2724
2725   FPR(t).fd = (float)((FPR(a).fd * FPR(c).fd) + FPR(b).fd);
2726
2727   set_fprf(FPR(t));
2728   if( RCBIT ) {
2729      SET_CR1();
2730   }
2731}
2732
2733static void ppc_fmsubsx(UINT32 op)
2734{
2735   UINT32 c = RC;
2736   UINT32 b = RB;
2737   UINT32 a = RA;
2738   UINT32 t = RT;
2739
2740   CHECK_FPU_AVAILABLE();
2741
2742   SET_VXSNAN(FPR(a), FPR(b));
2743   SET_VXSNAN_1(FPR(c));
2744
2745   FPR(t).fd = (float)((FPR(a).fd * FPR(c).fd) - FPR(b).fd);
2746
2747   set_fprf(FPR(t));
2748   if( RCBIT ) {
2749      SET_CR1();
2750   }
2751}
2752
2753static void ppc_fmulsx(UINT32 op)
2754{
2755   UINT32 c = RC;
2756   UINT32 a = RA;
2757   UINT32 t = RT;
2758
2759   CHECK_FPU_AVAILABLE();
2760   SET_VXSNAN(FPR(a), FPR(c));
2761
2762   FPR(t).fd = (float)(FPR(a).fd * FPR(c).fd);
2763
2764   set_fprf(FPR(t));
2765   if( RCBIT ) {
2766      SET_CR1();
2767   }
2768}
2769
2770static void ppc_fnmaddsx(UINT32 op)
2771{
2772   UINT32 c = RC;
2773   UINT32 b = RB;
2774   UINT32 a = RA;
2775   UINT32 t = RT;
2776
2777   CHECK_FPU_AVAILABLE();
2778
2779   SET_VXSNAN(FPR(a), FPR(b));
2780   SET_VXSNAN_1(FPR(c));
2781
2782   FPR(t).fd = (float)(-((FPR(a).fd * FPR(c).fd) + FPR(b).fd));
2783
2784   set_fprf(FPR(t));
2785   if( RCBIT ) {
2786      SET_CR1();
2787   }
2788}
2789
2790static void ppc_fnmsubsx(UINT32 op)
2791{
2792   UINT32 c = RC;
2793   UINT32 b = RB;
2794   UINT32 a = RA;
2795   UINT32 t = RT;
2796
2797   CHECK_FPU_AVAILABLE();
2798
2799   SET_VXSNAN(FPR(a), FPR(b));
2800   SET_VXSNAN_1(FPR(c));
2801
2802   FPR(t).fd = (float)(-((FPR(a).fd * FPR(c).fd) - FPR(b).fd));
2803
2804   set_fprf(FPR(t));
2805   if( RCBIT ) {
2806      SET_CR1();
2807   }
2808}
trunk/src/emu/cpu/powerpc/ppc403.c
r28739r28740
1/* PowerPC 403 specific functions */
2
3static void ppc403_dma_exec(int ch);
4
5#define DMA_CE      0x80000000
6#define DMA_CIE     0x40000000
7#define DMA_TD      0x20000000
8#define DMA_PL      0x10000000
9#define DMA_DAI     0x02000000
10#define DMA_SAI     0x01000000
11#define DMA_CP      0x00800000
12#define DMA_ETD     0x00000200
13#define DMA_TCE     0x00000100
14#define DMA_CH      0x00000080
15#define DMA_BME     0x00000040
16#define DMA_ECE     0x00000020
17#define DMA_TCD     0x00000010
18#define DMA_PCE     0x00000008
19
20static SPU_RX_HANDLER spu_rx_handler;
21static SPU_TX_HANDLER spu_tx_handler;
22static TIMER_CALLBACK( ppc403_spu_rx_callback );
23static TIMER_CALLBACK( ppc403_spu_tx_callback );
24
25static PPC_DMA_HANDLER spu_rx_dma_handler;
26static PPC_DMA_HANDLER spu_tx_dma_handler;
27static UINT8 *spu_rx_dma_ptr;
28static UINT8 *spu_tx_dma_ptr;
29
30static PPC_DMA_HANDLER dma_read_handler[4];
31static PPC_DMA_HANDLER dma_write_handler[4];
32static UINT8 *dma_read_ptr[4];
33static UINT8 *dma_write_ptr[4];
34
35INLINE void ppc_set_dcr(int dcr, UINT32 value)
36{
37   switch(dcr)
38   {
39      case DCR_BEAR:      ppc.bear = value; break;
40      case DCR_BESR:      ppc.besr = value; break;
41      case DCR_BR0:       ppc.br[0] = value; break;
42      case DCR_BR1:       ppc.br[1] = value; break;
43      case DCR_BR2:       ppc.br[2] = value; break;
44      case DCR_BR3:       ppc.br[3] = value; break;
45      case DCR_BR4:       ppc.br[4] = value; break;
46      case DCR_BR5:       ppc.br[5] = value; break;
47      case DCR_BR6:       ppc.br[6] = value; break;
48      case DCR_BR7:       ppc.br[7] = value; break;
49
50      case DCR_EXISR:     ppc.exisr &= ~value; break;
51      case DCR_EXIER:     EXIER = value; ppc.exisr &= EXIER; break;
52      case DCR_IOCR:      ppc.iocr = value; break;
53      case DCR_DMASR:     break;      /* TODO */
54      case DCR_DMADA0:    ppc.dma[0].da = value; break;
55      case DCR_DMADA1:    ppc.dma[1].da = value; break;
56      case DCR_DMADA2:    ppc.dma[2].da = value; break;
57      case DCR_DMADA3:    ppc.dma[3].da = value; break;
58      case DCR_DMASA0:    ppc.dma[0].sa = value; break;
59      case DCR_DMASA1:    ppc.dma[1].sa = value; break;
60      case DCR_DMASA2:    ppc.dma[2].sa = value; break;
61      case DCR_DMASA3:    ppc.dma[3].sa = value; break;
62      case DCR_DMACT0:    ppc.dma[0].ct = value; break;
63      case DCR_DMACT1:    ppc.dma[1].ct = value; break;
64      case DCR_DMACT2:    ppc.dma[2].ct = value; break;
65      case DCR_DMACT3:    ppc.dma[3].ct = value; break;
66      case DCR_DMACR0:    ppc.dma[0].cr = value; ppc403_dma_exec(0); break;
67      case DCR_DMACR1:    ppc.dma[1].cr = value; ppc403_dma_exec(1); break;
68      case DCR_DMACR2:    ppc.dma[2].cr = value; ppc403_dma_exec(2); break;
69      case DCR_DMACR3:    ppc.dma[3].cr = value; ppc403_dma_exec(3); break;
70
71      default:
72         fatalerror("ppc: set_dcr: Unimplemented DCR %X\n", dcr);
73         break;
74   }
75}
76
77INLINE UINT32 ppc_get_dcr(int dcr)
78{
79   switch(dcr)
80   {
81      case DCR_BEAR:      return ppc.bear;
82      case DCR_BESR:      return ppc.besr;
83      case DCR_BR0:       return ppc.br[0];
84      case DCR_BR1:       return ppc.br[1];
85      case DCR_BR2:       return ppc.br[2];
86      case DCR_BR3:       return ppc.br[3];
87      case DCR_BR4:       return ppc.br[4];
88      case DCR_BR5:       return ppc.br[5];
89      case DCR_BR6:       return ppc.br[6];
90      case DCR_BR7:       return ppc.br[7];
91      case DCR_EXISR:     return EXISR;
92      case DCR_EXIER:     return EXIER;
93      case DCR_IOCR:      return ppc.iocr;
94      case DCR_DMASR:     return ppc.dmasr;
95      case DCR_DMADA0:    return ppc.dma[0].da;
96      case DCR_DMADA1:    return ppc.dma[1].da;
97      case DCR_DMADA2:    return ppc.dma[2].da;
98      case DCR_DMADA3:    return ppc.dma[3].da;
99      case DCR_DMASA0:    return ppc.dma[0].sa;
100      case DCR_DMASA1:    return ppc.dma[1].sa;
101      case DCR_DMASA2:    return ppc.dma[2].sa;
102      case DCR_DMASA3:    return ppc.dma[3].sa;
103      case DCR_DMACT0:    return ppc.dma[0].ct;
104      case DCR_DMACT1:    return ppc.dma[1].ct;
105      case DCR_DMACT2:    return ppc.dma[2].ct;
106      case DCR_DMACT3:    return ppc.dma[3].ct;
107      case DCR_DMACR0:    return ppc.dma[0].cr;
108      case DCR_DMACR1:    return ppc.dma[1].cr;
109      case DCR_DMACR2:    return ppc.dma[2].cr;
110      case DCR_DMACR3:    return ppc.dma[3].cr;
111
112      default:
113         fatalerror("ppc: get_dcr: Unimplemented DCR %X\n", dcr);
114         break;
115   }
116}
117
118
119
120#ifndef PPC_DRC
121INLINE void ppc403_check_interrupts(void)
122{
123   if (MSR & MSR_EE)
124   {
125      if (ppc.interrupt_pending != 0)
126      {
127         if (ppc.interrupt_pending & 0x1)
128         {
129            ppc403_exception(EXCEPTION_IRQ);
130         }
131         else if (ppc.interrupt_pending & 0x2)
132         {
133            ppc403_exception(EXCEPTION_PROGRAMMABLE_INTERVAL_TIMER);
134         }
135         else if (ppc.interrupt_pending & 0x4)
136         {
137            ppc403_exception(EXCEPTION_FIXED_INTERVAL_TIMER);
138         }
139      }
140   }
141}
142
143static CPU_RESET( ppc403 )
144{
145   ppc.pc = ppc.npc = 0xfffffffc;
146
147   ppc_set_msr(0);
148}
149
150static CPU_EXECUTE( ppc403 )
151{
152   UINT32 fit_trigger_cycle;
153   ppc_tb_base_icount = cycles;
154
155   fit_trigger_cycle = 0x7fffffff;
156
157   if (ppc.fit_int_enable)
158   {
159      UINT32 tb = (UINT32)ppc.tb;
160      UINT32 fit_cycles = 0;
161
162      if (ppc.tb & ppc.fit_bit)
163      {
164         fit_cycles += ppc.fit_bit;
165         tb += fit_cycles;
166      }
167
168      fit_cycles += ppc.fit_bit - (tb & (ppc.fit_bit-1));
169
170      fit_trigger_cycle = ppc_icount - fit_cycles;
171   }
172
173   while( ppc_icount > 0 )
174   {
175      UINT32 opcode;
176
177      debugger_instruction_hook(device, ppc.pc);
178      ppc.pc = ppc.npc;
179      ppc.npc += 4;
180      opcode = ROPCODE(ppc.pc);
181
182      switch(opcode >> 26)
183      {
184         case 19:    ppc.optable19[(opcode >> 1) & 0x3ff](opcode); break;
185         case 31:    ppc.optable31[(opcode >> 1) & 0x3ff](opcode); break;
186         case 59:    ppc.optable59[(opcode >> 1) & 0x3ff](opcode); break;
187         case 63:    ppc.optable63[(opcode >> 1) & 0x3ff](opcode); break;
188         default:    ppc.optable[opcode >> 26](opcode); break;
189      }
190
191      ppc_icount--;
192
193      /* Programmable Interval Timer (PIT) */
194      if (ppc.pit_counter > 0)
195      {
196         ppc.pit_counter--;
197         if (ppc.pit_counter == 0)
198         {
199            if (ppc.pit_int_enable) {
200               ppc.interrupt_pending |= 0x2;
201            }
202            if (ppc.tcr & 0x00400000)   // Automatic reload
203            {
204               ppc.pit_counter = ppc.pit;
205            }
206         }
207      }
208
209      /* Fixed Interval Timer */
210      if (fit_trigger_cycle != 0x7fffffff)
211      {
212         if (ppc_icount == fit_trigger_cycle)
213         {
214            if (ppc.fit_int_enable)
215            {
216               fit_trigger_cycle -= ppc.fit_bit;
217               ppc.interrupt_pending |= 0x4;
218            }
219         }
220      }
221
222#if 0
223      /* Watchdog Timer */
224      if (((UINT32)(ppc.tb) & ppc.wdt_bit) && (tblo & ppc.wdt_bit) == 0) {
225         switch((ppc.tsr >> 28) & 0x3)
226         {
227            case 0: ppc.tsr |= TSR_ENW; break;
228            case 1: ppc.tsr |= TSR_ENW; break;
229            case 2:
230               if (ppc.wdt_int_enable && (ppc.msr & MSR_CE)) {
231                  ppc403_exception(EXCEPTION_WATCHDOG_TIMER);
232               }
233               break;
234            case 3:
235               fatalerror("PPC: Watchdog Timer caused reset\n");
236               break;
237         }
238      }
239#endif
240
241      ppc403_check_interrupts();
242   }
243
244   // update timebase
245   ppc.tb += (ppc_tb_base_icount - ppc_icount);
246}
247
248void ppc403_exception(int exception)
249{
250   switch( exception )
251   {
252      case EXCEPTION_IRQ:     /* External Interrupt */
253      {
254         if( ppc_get_msr() & MSR_EE ) {
255            UINT32 msr = ppc_get_msr();
256
257            SRR0 = ppc.npc;
258            SRR1 = msr;
259
260            msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE);    // Clear WE, PR, EE, PR
261            if( msr & MSR_LE )
262               msr |= MSR_ILE;
263            else
264               msr &= ~MSR_ILE;
265            ppc_set_msr(msr);
266
267            ppc.npc = EVPR | 0x0500;
268
269            ppc.interrupt_pending &= ~0x1;
270         }
271         break;
272      }
273
274      case EXCEPTION_TRAP:            /* Program exception / Trap */
275      {
276            UINT32 msr = ppc_get_msr();
277
278            SRR0 = ppc.pc;
279            SRR1 = msr;
280
281            msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE);    // Clear WE, PR, EE, PR
282            if( msr & MSR_ILE )
283               msr |= MSR_LE;
284            else
285               msr &= ~MSR_LE;
286            ppc_set_msr(msr);
287
288            if( msr & MSR_IP )
289               ppc.npc = 0xfff00000 | 0x0700;
290            else
291               ppc.npc = EVPR | 0x0700;
292         break;
293      }
294
295      case EXCEPTION_SYSTEM_CALL:     /* System call */
296      {
297            UINT32 msr = ppc_get_msr();
298
299            SRR0 = ppc.npc;
300            SRR1 = msr;
301
302            msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE);    // Clear WE, PR, EE, PR
303            if( msr & MSR_ILE )
304               msr |= MSR_LE;
305            else
306               msr &= ~MSR_LE;
307            ppc_set_msr(msr);
308
309            if( msr & MSR_IP )
310               ppc.npc = 0xfff00000 | 0x0c00;
311            else
312               ppc.npc = EVPR | 0x0c00;
313         break;
314      }
315
316      case EXCEPTION_PROGRAMMABLE_INTERVAL_TIMER:
317      {
318         if( ppc_get_msr() & MSR_EE ) {
319            UINT32 msr = ppc_get_msr();
320
321            SRR0 = ppc.npc;
322            SRR1 = msr;
323
324            msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE);    // Clear WE, PR, EE, PR
325            if( msr & MSR_LE )
326               msr |= MSR_ILE;
327            else
328               msr &= ~MSR_ILE;
329            ppc_set_msr(msr);
330
331            ppc.npc = EVPR | 0x1000;
332
333            ppc.tsr |= 0x08000000;      // PIT interrupt
334            ppc.interrupt_pending &= ~0x2;
335         }
336         break;
337      }
338
339      case EXCEPTION_FIXED_INTERVAL_TIMER:        /* Fixed Interval Timer */
340      {
341         if( ppc_get_msr() & MSR_EE ) {
342            UINT32 msr = ppc_get_msr();
343
344            SRR0 = ppc.npc;
345            SRR1 = msr;
346
347            msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE);    // Clear WE, PR, EE, PR
348            if( msr & MSR_LE )
349               msr |= MSR_ILE;
350            else
351               msr &= ~MSR_ILE;
352            ppc_set_msr(msr);
353
354            ppc.npc = EVPR | 0x1010;
355         ppc.interrupt_pending &= ~0x4;
356         }
357         break;
358      }
359
360      case EXCEPTION_WATCHDOG_TIMER:              /* Watchdog Timer */
361      {
362         UINT32 msr = ppc_get_msr();
363
364         SRR2 = ppc.npc;
365         SRR3 = msr;
366
367         msr &= ~(MSR_WE | MSR_PR | MSR_CE | MSR_EE | MSR_DE | MSR_PE | MSR_DR | MSR_IR);
368         if (msr & MSR_LE)
369            msr |= MSR_ILE;
370         else
371            msr &= ~MSR_ILE;
372         ppc_set_msr(msr);
373
374         ppc.npc = EVPR | 0x1020;
375         break;
376      }
377
378      case EXCEPTION_CRITICAL_INTERRUPT:
379      {
380         UINT32 msr = ppc_get_msr();
381
382         SRR2 = ppc.npc;
383         SRR3 = msr;
384
385         msr &= ~(MSR_WE | MSR_PR | MSR_CE | MSR_EE | MSR_DE | MSR_PE | MSR_DR | MSR_IR);
386         if (msr & MSR_LE)
387            msr |= MSR_ILE;
388         else
389            msr &= ~MSR_ILE;
390         ppc_set_msr(msr);
391
392         EXISR |= 0x80000000;
393         ppc.npc = EVPR | 0x100;
394         break;
395      }
396
397      default:
398         fatalerror("ppc: Unhandled exception %d\n", exception);
399         break;
400   }
401}
402
403static void ppc403_set_irq_line(int irqline, int state)
404{
405   if (irqline >= INPUT_LINE_IRQ0 && irqline <= INPUT_LINE_IRQ4)
406   {
407      UINT32 mask = (1 << (4 - irqline));
408      if( state == ASSERT_LINE) {
409         if( EXIER & mask ) {
410            ppc.exisr |= mask;
411            ppc.interrupt_pending |= 0x1;
412
413            if (ppc.irq_callback)
414            {
415               ppc.irq_callback(ppc.device, irqline);
416            }
417         }
418      }
419      // clear line is used to clear the interrupt when the interrupts are level-sensitive
420      else if (state == CLEAR_LINE)
421      {
422         ppc.exisr &= ~mask;
423      }
424   }
425   else if (irqline == PPC_IRQ_SPU_RX)
426   {
427      UINT32 mask = 0x08000000;
428      if (state) {
429         if( EXIER & mask ) {
430            ppc.exisr |= mask;
431            ppc.interrupt_pending |= 0x1;
432         }
433      }
434   }
435   else if (irqline == PPC_IRQ_SPU_TX)
436   {
437      UINT32 mask = 0x04000000;
438      if (state) {
439         if( EXIER & mask ) {
440            ppc.exisr |= mask;
441            ppc.interrupt_pending |= 0x1;
442         }
443      }
444   }
445   else if (irqline == PPC_IRQ_CRITICAL)
446   {
447      if (state) {
448         if (EXIER & 0x80000000) {
449            ppc403_exception(EXCEPTION_CRITICAL_INTERRUPT);
450         }
451      }
452   }
453   else
454   {
455      fatalerror("PPC: Unknown IRQ line %d\n", irqline);
456   }
457}
458
459static void ppc403_dma_set_irq_line(int dma, int state)
460{
461   UINT32 mask = (1 << (3 - dma)) << 20;
462   if( state ) {
463      if( EXIER & mask ) {
464         ppc.exisr |= mask;
465         ppc.interrupt_pending |= 0x1;
466      }
467   }
468}
469#endif
470
471#ifdef PPC_DRC
472static void ppc403_dma_set_irq_line(int dma, int state)
473{
474   UINT32 mask = (1 << (3 - dma)) << 20;
475   if( state ) {
476      if( EXIER & mask ) {
477         ppc.exisr |= mask;
478         ppc.exception_pending |= 0x1;
479      }
480   }
481}
482#endif
483
484
485
486
487
488
489#ifndef PPC_DRC
490static void ppc_dccci(UINT32 op)
491{
492}
493
494static void ppc_dcread(UINT32 op)
495{
496}
497
498static void ppc_icbt(UINT32 op)
499{
500}
501
502static void ppc_iccci(UINT32 op)
503{
504}
505
506static void ppc_icread(UINT32 op)
507{
508}
509
510static void ppc_rfci(UINT32 op)
511{
512   UINT32 msr;
513   ppc.npc = ppc.srr2;
514   msr = ppc.srr3;
515   ppc_set_msr( msr );
516
517}
518#endif
519
520static void ppc_mfdcr(UINT32 op)
521{
522   REG(RT) = ppc_get_dcr(SPR);
523}
524
525static void ppc_mtdcr(UINT32 op)
526{
527   ppc_set_dcr(SPR, REG(RS));
528}
529
530static void ppc_wrtee(UINT32 op)
531{
532   if( REG(RS) & 0x8000 )
533      ppc_set_msr( ppc_get_msr() | MSR_EE);
534   else
535      ppc_set_msr( ppc_get_msr() & ~MSR_EE);
536}
537
538static void ppc_wrteei(UINT32 op)
539{
540   if( op & 0x8000 )
541      ppc_set_msr( ppc_get_msr() | MSR_EE);
542   else
543      ppc_set_msr( ppc_get_msr() & ~MSR_EE);
544}
545
546
547
548/**************************************************************************/
549/* PPC403 Serial Port */
550
551static UINT8 ppc403_spu_r(UINT32 a)
552{
553   switch(a & 0xf)
554   {
555      case 0x0:       return ppc.spu.spls | 0x6;      /* transmit buffer is always empty */
556      case 0x2:       return ppc.spu.sphs;
557      case 0x4:       return (ppc.spu.brd >> 8) & 0xf;
558      case 0x5:       return (ppc.spu.brd & 0xff);
559      case 0x6:       return ppc.spu.spctl;
560      case 0x7:       return ppc.spu.sprc;
561      case 0x8:       return ppc.spu.sptc;
562      case 0x9:       return ppc.spu.sprb;
563      default:        fatalerror("ppc: spu_r: %02X\n", a & 0xf);
564   }
565}
566
567static void ppc403_spu_w(UINT32 a, UINT8 d)
568{
569   switch(a & 0xf)
570   {
571      case 0x0:
572         if( d & 0x80 )  ppc.spu.spls &= ~0x80;
573         if( d & 0x40 )  ppc.spu.spls &= ~0x40;
574         if( d & 0x20 )  ppc.spu.spls &= ~0x20;
575         if( d & 0x10 )  ppc.spu.spls &= ~0x10;
576         if( d & 0x08 )  ppc.spu.spls &= ~0x08;
577         break;
578
579      case 0x2:
580         ppc.spu.sphs = d;
581         break;
582
583      case 0x4:
584         ppc.spu.brd &= 0xff;
585         ppc.spu.brd |= (d << 8);
586         break;
587
588      case 0x5:
589         ppc.spu.brd &= 0xff00;
590         ppc.spu.brd |= d;
591         if (ppc.iocr & 0x2) {
592            mame_printf_debug("ppc: SPU Baud rate: %d\n", (3686400 / (ppc.spu.brd + 1)) / 16);
593         } else {
594            mame_printf_debug("ppc: SPU Baud rate: %d\n", (33333333 / (ppc.spu.brd + 1)) / 16);
595         }
596         break;
597
598      case 0x6:
599         ppc.spu.spctl = d;
600         break;
601
602      case 0x7:
603         ppc.spu.sprc = d;
604         if (ppc.spu.sprc & 0x80)    /* enable RX */
605         {
606            /*
607            int baud_rate;
608            if (ppc.iocr & 0x2) {
609                baud_rate = (3686400 / (ppc.spu.brd + 1)) / 16;
610            } else {
611                baud_rate = (33333333 / (ppc.spu.brd + 1)) / 16;
612            }
613            */
614
615            /* check if serial port is hooked to a DMA channel */
616            /* if so, do a DMA operation */
617            if( ((((ppc.spu.sprc >> 5) & 0x3) == 2) && (ppc.dma[2].cr & DMA_CE)) ||
618               ((((ppc.spu.sprc >> 5) & 0x3) == 3) && (ppc.dma[3].cr & DMA_CE)) )
619            {
620               int i;
621               int ch = (ppc.spu.sprc >> 5) & 0x3;
622            //  mame_printf_debug("ppc: DMA from serial port on channel %d (DA: %08X)\n", ch, ppc.dma[ch].da);
623
624               if (spu_rx_dma_handler)
625               {
626                  int length = ppc.dma[ch].ct;
627
628                  spu_rx_dma_handler(length);
629
630                  for (i=0; i < length; i++)
631                  {
632                     ppc.program->write_byte(ppc.dma[ch].da++, spu_rx_dma_ptr[i]);
633                  }
634               }
635
636               ppc.dmasr |= (1 << (27 - ch));
637
638               /* generate interrupts */
639               if( ppc.dma[ch].cr & DMA_CIE )
640               {
641                  ppc403_dma_set_irq_line( ch, PULSE_LINE );
642               }
643
644               /* set receive buffer full */
645               ppc.spu.spls = 0x80;
646
647#ifndef PPC_DRC
648               ppc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
649#else
650               ppcdrc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
651#endif
652            }
653         }
654         else                        /* disable RX */
655         {
656         }
657         break;
658
659      case 0x8:
660         ppc.spu.sptc = d;
661         break;
662
663      case 0x9:
664         ppc.spu.sptb = d;
665         ppc403_spu_tx_callback(NULL/* Machine */, NULL, cpunum_get_active());
666         break;
667
668      default:
669         fatalerror("ppc: spu_w: %02X, %02X\n", a & 0xf, d);
670         break;
671   }
672   //mame_printf_debug("spu_w: %02X, %02X at %08X\n", a & 0xf, d, ppc.pc);
673}
674
675void ppc403_spu_rx(UINT8 data)
676{
677   ppc.spu.sprb = data;
678
679   /* set receive buffer full */
680   ppc.spu.spls = 0x80;
681
682   /* generate interrupt if DMA is disabled and RBR interrupt is enabled */
683   if (((ppc.spu.sprc >> 5) & 0x3) == 0x01) {
684#ifndef PPC_DRC
685      ppc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
686#else
687      ppcdrc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
688#endif
689   }
690}
691
692static TIMER_CALLBACK( ppc403_spu_rx_callback )
693{
694   if (spu_rx_handler != NULL)
695   {
696      ppc403_spu_rx(spu_rx_handler());
697   }
698}
699
700static TIMER_CALLBACK( ppc403_spu_tx_callback )
701{
702   if (spu_tx_handler != NULL)
703   {
704      spu_tx_handler(ppc.spu.sptb);
705
706      /* generate interrupt if DMA is disabled and TBR interrupt is enabled */
707      if (((ppc.spu.sptc >> 5) & 0x3) == 0x01) {
708#ifndef PPC_DRC
709         ppc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
710#else
711         ppcdrc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
712#endif
713      }
714   }
715}
716
717void ppc403_install_spu_rx_handler(SPU_RX_HANDLER rx_handler)
718{
719   spu_rx_handler = rx_handler;
720}
721
722void ppc403_install_spu_tx_handler(SPU_TX_HANDLER tx_handler)
723{
724   spu_tx_handler = tx_handler;
725}
726
727
728void ppc403_spu_rx_dma(UINT8 *data, int length)
729{
730}
731
732void ppc403_install_spu_rx_dma_handler(PPC_DMA_HANDLER rx_dma_handler, UINT8 *buffer)
733{
734   spu_rx_dma_handler = rx_dma_handler;
735   spu_rx_dma_ptr = buffer;
736}
737
738void ppc403_install_spu_tx_dma_handler(PPC_DMA_HANDLER tx_dma_handler, UINT8 *buffer)
739{
740   spu_tx_dma_handler = tx_dma_handler;
741   spu_tx_dma_ptr = buffer;
742}
743
744/*********************************************************************************/
745
746/* PPC 403 DMA */
747
748static const int dma_transfer_width[4] = { 1, 2, 4, 16 };
749
750void ppc403_install_dma_read_handler(int ch, PPC_DMA_HANDLER dma_handler, UINT8 *buffer)
751{
752   dma_read_handler[ch] = dma_handler;
753   dma_read_ptr[ch] = buffer;
754}
755
756void ppc403_install_dma_write_handler(int ch, PPC_DMA_HANDLER dma_handler, UINT8 *buffer)
757{
758   dma_write_handler[ch] = dma_handler;
759   dma_write_ptr[ch] = buffer;
760}
761
762static void ppc403_dma_exec(int ch)
763{
764   int i;
765   int dai, sai, width;
766
767   /* Is the DMA channel enabled ? */
768   if( ppc.dma[ch].cr & DMA_CE )
769   {
770      /* transfer width */
771      width = dma_transfer_width[(ppc.dma[ch].cr >> 26) & 0x3];
772
773      if( ppc.dma[ch].cr & DMA_DAI )
774         dai = width;
775      else
776         dai = 0;        /* DA not incremented */
777
778      if( ppc.dma[ch].cr & DMA_SAI )
779         sai = width;
780      else
781         sai = 0;        /* SA not incremented */
782
783
784      /* transfer mode */
785      switch( (ppc.dma[ch].cr >> 21) & 0x3 )
786      {
787         case 0:     /* buffered DMA */
788            if( ppc.dma[ch].cr & DMA_TD )   /* peripheral to mem */
789            {
790               // nothing to do for now */
791            }
792            else                            /* mem to peripheral */
793            {
794               /* check if the serial port is hooked to channel 2 or 3 */
795               if( (ch == 2 && ((ppc.spu.sptc >> 5) & 0x3) == 2) ||
796                  (ch == 3 && ((ppc.spu.sptc >> 5) & 0x3) == 3) )
797               {
798                  mame_printf_debug("ppc: dma_exec: DMA to serial port on channel %d (DA: %08X)\n", ch, ppc.dma[ch].da);
799
800                  if (spu_tx_dma_handler)
801                  {
802                     int length = ppc.dma[ch].ct;
803
804                     for( i=0; i < length; i++ ) {
805                        spu_tx_dma_ptr[i] = ppc.program->read_byte(ppc.dma[ch].da++);
806                     }
807                     spu_tx_dma_handler(length);
808                  }
809
810#ifndef PPC_DRC
811                  ppc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
812#else
813                  ppcdrc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
814#endif
815               }
816               else {
817                  fatalerror("ppc: dma_exec: buffered DMA to unknown peripheral ! (channel %d)\n", ch);
818               }
819
820            }
821            break;
822
823         case 1:     /* fly-by DMA */
824            fatalerror("ppc: dma_exec: fly-by DMA not implemented\n");
825            break;
826
827         case 2:     /* software initiated mem-to-mem DMA */
828            //mame_printf_debug("ppc: DMA (%d, SW mem-to-mem): SA = %08X, DA = %08X, CT = %08X\n", ch, ppc.dma[ch].sa, ppc.dma[ch].da, ppc.dma[ch].ct);
829
830            switch(width)
831            {
832               case 1:     /* Byte transfer */
833                  for (i=0; i < ppc.dma[ch].ct; i++)
834                  {
835                     UINT8 b = READ8(ppc.dma[ch].sa);
836                     WRITE8(ppc.dma[ch].da, b);
837                     ppc.dma[ch].sa += sai;
838                     ppc.dma[ch].da += dai;
839                  }
840                  break;
841               case 2:     /* Word transfer */
842                  for (i=0; i < ppc.dma[ch].ct; i++)
843                  {
844                     UINT16 w = READ16(ppc.dma[ch].sa);
845                     WRITE16(ppc.dma[ch].da, w);
846                     ppc.dma[ch].sa += sai;
847                     ppc.dma[ch].da += dai;
848                  }
849                  break;
850               case 4:     /* Double word transfer */
851                  for (i=0; i < ppc.dma[ch].ct; i++)
852                  {
853                     UINT32 d = READ32(ppc.dma[ch].sa);
854                     WRITE32(ppc.dma[ch].da, d);
855                     ppc.dma[ch].sa += sai;
856                     ppc.dma[ch].da += dai;
857                  }
858                  break;
859               case 16:    /* 16-byte transfer */
860                  for (i=0; i < ppc.dma[ch].ct; i++)
861                  {
862                     UINT32 d1 = READ32(ppc.dma[ch].sa+0);
863                     UINT32 d2 = READ32(ppc.dma[ch].sa+4);
864                     UINT32 d3 = READ32(ppc.dma[ch].sa+8);
865                     UINT32 d4 = READ32(ppc.dma[ch].sa+12);
866                     WRITE32(ppc.dma[ch].da+0, d1);
867                     WRITE32(ppc.dma[ch].da+4, d2);
868                     WRITE32(ppc.dma[ch].da+8, d3);
869                     WRITE32(ppc.dma[ch].da+12, d4);
870                     ppc.dma[ch].sa += 16;
871                     ppc.dma[ch].da += 16;
872                  }
873                  break;
874               default:
875                  fatalerror("dma: dma_exec: SW mem-to-mem DMA, width = %d\n", width);
876            }
877            break;
878
879         case 3:     /* hardware initiated mem-to-mem DMA */
880            fatalerror("ppc: dma_exec: HW mem-to-mem DMA not implemented\n");
881            break;
882      }
883
884      ppc.dmasr |= (1 << (27 - ch));
885
886      /* DEBUG: check for not yet supported features */
887      if( (ppc.dma[ch].cr & DMA_TCE) == 0 )
888         fatalerror("ppc: dma_exec: DMA_TCE == 0\n");
889
890      if( ppc.dma[ch].cr & DMA_CH )
891         fatalerror("ppc: dma_exec: DMA chaining not implemented\n");
892
893      /* generate interrupts */
894      if( ppc.dma[ch].cr & DMA_CIE )
895         ppc403_dma_set_irq_line( ch, PULSE_LINE );
896
897   }
898}
899
900/*********************************************************************************/
901
902static UINT8 ppc403_read8(address_space &space, UINT32 a)
903{
904   if(a >= 0x40000000 && a <= 0x4000000f)      /* Serial Port */
905      return ppc403_spu_r(a);
906   return space.read_byte(a);
907}
908
909#define ppc403_read16   memory_read_word_32be
910#define ppc403_read32   memory_read_dword_32be
911
912static void ppc403_write8(address_space &space, UINT32 a, UINT8 d)
913{
914   if( a >= 0x40000000 && a <= 0x4000000f )        /* Serial Port */
915   {
916      ppc403_spu_w(a, d);
917      return;
918   }
919   space.write_byte(a, d);
920}
921
922#define ppc403_write16  memory_write_word_32be
923#define ppc403_write32  memory_write_dword_32be
924
925static UINT16 ppc403_read16_unaligned(address_space &space, UINT32 a)
926{
927   fatalerror("ppc: Unaligned read16 %08X at %08X\n", a, ppc.pc);
928   return 0;
929}
930
931static UINT32 ppc403_read32_unaligned(address_space &space, UINT32 a)
932{
933   fatalerror("ppc: Unaligned read32 %08X at %08X\n", a, ppc.pc);
934   return 0;
935}
936
937static void ppc403_write16_unaligned(address_space &space, UINT32 a, UINT16 d)
938{
939   fatalerror("ppc: Unaligned write16 %08X, %04X at %08X\n", a, d, ppc.pc);
940}
941
942static void ppc403_write32_unaligned(address_space &space, UINT32 a, UINT32 d)
943{
944   fatalerror("ppc: Unaligned write32 %08X, %08X at %08X\n", a, d, ppc.pc);
945}
trunk/src/emu/cpu/powerpc/ppc602.c
r28739r28740
1static void ppc_dsa(UINT32 op)
2{
3   UINT32 msr = ppc_get_msr();
4
5   msr &= ~(MSR_SA | MSR_EE | MSR_PR | MSR_AP);
6   if (ppc.esasrr & 0x8)   msr |= MSR_PR;
7   if (ppc.esasrr & 0x4)   msr |= MSR_AP;
8   if (ppc.esasrr & 0x2)   msr |= MSR_SA;
9   if (ppc.esasrr & 0x1)   msr |= MSR_EE;
10
11   ppc_set_msr(msr);
12}
13
14static void ppc_esa(UINT32 op)
15{
16   int sa, ee, pr, ap;
17   UINT32 msr = ppc_get_msr();
18
19   sa = (msr & MSR_SA) ? 1 : 0;
20   ee = (msr & MSR_EE) ? 1 : 0;
21   pr = (msr & MSR_PR) ? 1 : 0;
22   ap = (msr & MSR_AP) ? 1 : 0;
23
24   ppc.esasrr = (pr << 3) | (ap << 2) | (sa << 1) | (ee);
25
26   msr &= ~(MSR_EE | MSR_PR | MSR_AP);
27   msr |= MSR_SA;
28
29   ppc_set_msr(msr);
30}
31
32#ifndef PPC_DRC
33static void ppc_tlbli(UINT32 op)
34{
35}
36
37static void ppc_tlbld(UINT32 op)
38{
39}
40#endif
41
42#ifndef PPC_DRC
43void ppc602_exception(int exception)
44{
45   switch( exception )
46   {
47      case EXCEPTION_IRQ:     /* External Interrupt */
48         if( ppc_get_msr() & MSR_EE ) {
49            UINT32 msr = ppc_get_msr();
50
51            SRR0 = ppc.npc;
52            SRR1 = msr & 0xff73;
53
54            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
55            if( msr & MSR_ILE )
56               msr |= MSR_LE;
57            else
58               msr &= ~MSR_LE;
59            ppc_set_msr(msr);
60
61            if( msr & MSR_IP )
62               ppc.npc = 0xfff00000 | 0x0500;
63            else
64               ppc.npc = ppc.ibr | 0x0500;
65
66            ppc.interrupt_pending &= ~0x1;
67         }
68         break;
69
70      case EXCEPTION_DECREMENTER:     /* Decrementer overflow exception */
71         if( ppc_get_msr() & MSR_EE ) {
72            UINT32 msr = ppc_get_msr();
73
74            SRR0 = ppc.npc;
75            SRR1 = msr & 0xff73;
76
77            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
78            if( msr & MSR_ILE )
79               msr |= MSR_LE;
80            else
81               msr &= ~MSR_LE;
82            ppc_set_msr(msr);
83
84            if( msr & MSR_IP )
85               ppc.npc = 0xfff00000 | 0x0900;
86            else
87               ppc.npc = ppc.ibr | 0x0900;
88
89            ppc.interrupt_pending &= ~0x2;
90         }
91         break;
92
93      case EXCEPTION_TRAP:            /* Program exception / Trap */
94         {
95            UINT32 msr = ppc_get_msr();
96
97            SRR0 = ppc.pc;
98            SRR1 = (msr & 0xff73) | 0x20000;    /* 0x20000 = TRAP bit */
99
100            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
101            if( msr & MSR_ILE )
102               msr |= MSR_LE;
103            else
104               msr &= ~MSR_LE;
105
106            if( msr & MSR_IP )
107               ppc.npc = 0xfff00000 | 0x0700;
108            else
109               ppc.npc = ppc.ibr | 0x0700;
110         }
111         break;
112
113      case EXCEPTION_SYSTEM_CALL:     /* System call */
114         {
115            UINT32 msr = ppc_get_msr();
116
117            SRR0 = ppc.npc;
118            SRR1 = (msr & 0xff73);
119
120            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
121            if( msr & MSR_ILE )
122               msr |= MSR_LE;
123            else
124               msr &= ~MSR_LE;
125
126            if( msr & MSR_IP )
127               ppc.npc = 0xfff00000 | 0x0c00;
128            else
129               ppc.npc = ppc.ibr | 0x0c00;
130         }
131         break;
132
133      case EXCEPTION_SMI:
134         if( ppc_get_msr() & MSR_EE ) {
135            UINT32 msr = ppc_get_msr();
136
137            SRR0 = ppc.npc;
138            SRR1 = msr & 0xff73;
139
140            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
141            if( msr & MSR_ILE )
142               msr |= MSR_LE;
143            else
144               msr &= ~MSR_LE;
145            ppc_set_msr(msr);
146
147            if( msr & MSR_IP )
148               ppc.npc = 0xfff00000 | 0x1400;
149            else
150               ppc.npc = ppc.ibr | 0x1400;
151
152            ppc.interrupt_pending &= ~0x4;
153         }
154         break;
155
156
157      default:
158         fatalerror("ppc: Unhandled exception %d\n", exception);
159         break;
160   }
161}
162
163static void ppc602_set_irq_line(int irqline, int state)
164{
165   if( state ) {
166      ppc.interrupt_pending |= 0x1;
167      if (ppc.irq_callback)
168      {
169         ppc.irq_callback(ppc.device, irqline);
170      }
171   }
172}
173
174static void ppc602_set_smi_line(int state)
175{
176   if( state ) {
177      ppc.interrupt_pending |= 0x4;
178   }
179}
180
181INLINE void ppc602_check_interrupts(void)
182{
183   if (MSR & MSR_EE)
184   {
185      if (ppc.interrupt_pending != 0)
186      {
187         if (ppc.interrupt_pending & 0x1)
188         {
189            ppc602_exception(EXCEPTION_IRQ);
190         }
191         else if (ppc.interrupt_pending & 0x2)
192         {
193            ppc602_exception(EXCEPTION_DECREMENTER);
194         }
195         else if (ppc.interrupt_pending & 0x4)
196         {
197            ppc602_exception(EXCEPTION_SMI);
198         }
199      }
200   }
201}
202
203static CPU_RESET( ppc602 )
204{
205   ppc.pc = ppc.npc = 0xfff00100;
206
207   ppc_set_msr(0x40);
208
209   ppc.hid0 = 1;
210
211   ppc.interrupt_pending = 0;
212}
213
214static CPU_EXECUTE( ppc602 )
215{
216   int exception_type;
217   UINT32 opcode;
218   ppc_tb_base_icount = ppc_icount;
219   ppc_dec_base_icount = ppc_icount;
220
221   // check if decrementer exception occurs during execution
222   if ((UINT32)(DEC - ppc_icount) > (UINT32)(DEC))
223   {
224      ppc_dec_trigger_cycle = ppc_icount - DEC;
225   }
226   else
227   {
228      ppc_dec_trigger_cycle = 0x7fffffff;
229   }
230
231   // MinGW's optimizer kills setjmp()/longjmp()
232   SETJMP_GNUC_PROTECT();
233
234   exception_type = setjmp(ppc.exception_jmpbuf);
235   if (exception_type)
236   {
237      ppc.npc = ppc.pc;
238      ppc602_exception(exception_type);
239   }
240
241   while( ppc_icount > 0 )
242   {
243      ppc.pc = ppc.npc;
244      debugger_instruction_hook(device, ppc.pc);
245
246      if (MSR & MSR_IR)
247         opcode = ppc_readop_translated(ppc.program, ppc.pc);
248      else
249      opcode = ROPCODE64(ppc.pc);
250
251      ppc.npc = ppc.pc + 4;
252      switch(opcode >> 26)
253      {
254         case 19:    ppc.optable19[(opcode >> 1) & 0x3ff](opcode); break;
255         case 31:    ppc.optable31[(opcode >> 1) & 0x3ff](opcode); break;
256         case 59:    ppc.optable59[(opcode >> 1) & 0x3ff](opcode); break;
257         case 63:    ppc.optable63[(opcode >> 1) & 0x3ff](opcode); break;
258         default:    ppc.optable[opcode >> 26](opcode); break;
259      }
260
261      ppc_icount--;
262
263      if(ppc_icount == ppc_dec_trigger_cycle) {
264         ppc.interrupt_pending |= 0x2;
265      }
266
267      ppc602_check_interrupts();
268   }
269
270   // update timebase
271   // timebase is incremented once every four core clock cycles, so adjust the cycles accordingly
272   ppc.tb += ((ppc_tb_base_icount - ppc_icount) / 4);
273
274   // update decrementer
275   DEC -= ((ppc_dec_base_icount - ppc_icount) / (bus_freq_multiplier * 2));
276}
277#endif  // PPC_DRC
trunk/src/emu/cpu/powerpc/ppc603.c
r28739r28740
1void ppc603_exception(int exception)
2{
3   switch( exception )
4   {
5      case EXCEPTION_IRQ:     /* External Interrupt */
6         if( ppc_get_msr() & MSR_EE ) {
7            UINT32 msr = ppc_get_msr();
8
9            SRR0 = ppc.npc;
10            SRR1 = msr & 0xff73;
11
12            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
13            if( msr & MSR_ILE )
14               msr |= MSR_LE;
15            else
16               msr &= ~MSR_LE;
17            ppc_set_msr(msr);
18
19            if( msr & MSR_IP )
20               ppc.npc = 0xfff00000 | 0x0500;
21            else
22               ppc.npc = 0x00000000 | 0x0500;
23
24            ppc.interrupt_pending &= ~0x1;
25         }
26         break;
27
28      case EXCEPTION_DECREMENTER:     /* Decrementer overflow exception */
29         if( ppc_get_msr() & MSR_EE ) {
30            UINT32 msr = ppc_get_msr();
31
32            SRR0 = ppc.npc;
33            SRR1 = msr & 0xff73;
34
35            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
36            if( msr & MSR_ILE )
37               msr |= MSR_LE;
38            else
39               msr &= ~MSR_LE;
40            ppc_set_msr(msr);
41
42            if( msr & MSR_IP )
43               ppc.npc = 0xfff00000 | 0x0900;
44            else
45               ppc.npc = 0x00000000 | 0x0900;
46
47            ppc.interrupt_pending &= ~0x2;
48         }
49         break;
50
51      case EXCEPTION_TRAP:            /* Program exception / Trap */
52         {
53            UINT32 msr = ppc_get_msr();
54
55            SRR0 = ppc.pc;
56            SRR1 = (msr & 0xff73) | 0x20000;    /* 0x20000 = TRAP bit */
57
58            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
59            if( msr & MSR_ILE )
60               msr |= MSR_LE;
61            else
62               msr &= ~MSR_LE;
63            ppc_set_msr(msr);
64
65            if( msr & MSR_IP )
66               ppc.npc = 0xfff00000 | 0x0700;
67            else
68               ppc.npc = 0x00000000 | 0x0700;
69         }
70         break;
71
72      case EXCEPTION_SYSTEM_CALL:     /* System call */
73         {
74            UINT32 msr = ppc_get_msr();
75
76            SRR0 = ppc.npc;
77            SRR1 = (msr & 0xff73);
78
79            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
80            if( msr & MSR_ILE )
81               msr |= MSR_LE;
82            else
83               msr &= ~MSR_LE;
84            ppc_set_msr(msr);
85
86            if( msr & MSR_IP )
87               ppc.npc = 0xfff00000 | 0x0c00;
88            else
89               ppc.npc = 0x00000000 | 0x0c00;
90         }
91         break;
92
93      case EXCEPTION_SMI:
94         if( ppc_get_msr() & MSR_EE ) {
95            UINT32 msr = ppc_get_msr();
96
97            SRR0 = ppc.npc;
98            SRR1 = msr & 0xff73;
99
100            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
101            if( msr & MSR_ILE )
102               msr |= MSR_LE;
103            else
104               msr &= ~MSR_LE;
105            ppc_set_msr(msr);
106
107            if( msr & MSR_IP )
108               ppc.npc = 0xfff00000 | 0x1400;
109            else
110               ppc.npc = 0x00000000 | 0x1400;
111
112            ppc.interrupt_pending &= ~0x4;
113         }
114         break;
115
116      case EXCEPTION_DSI:
117         {
118            UINT32 msr = ppc_get_msr();
119
120            SRR0 = ppc.npc;
121            SRR1 = msr & 0xff73;
122
123            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
124            if( msr & MSR_ILE )
125               msr |= MSR_LE;
126            else
127               msr &= ~MSR_LE;
128            ppc_set_msr(msr);
129
130            if( msr & MSR_IP )
131               ppc.npc = 0xfff00000 | 0x0300;
132            else
133               ppc.npc = 0x00000000 | 0x0300;
134
135            ppc.interrupt_pending &= ~0x4;
136         }
137         break;
138
139      case EXCEPTION_ISI:
140         {
141            UINT32 msr = ppc_get_msr();
142
143            SRR0 = ppc.npc;
144            SRR1 = msr & 0xff73;
145
146            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
147            if( msr & MSR_ILE )
148               msr |= MSR_LE;
149            else
150               msr &= ~MSR_LE;
151            ppc_set_msr(msr);
152
153            if( msr & MSR_IP )
154               ppc.npc = 0xfff00000 | 0x0400;
155            else
156               ppc.npc = 0x00000000 | 0x0400;
157
158            ppc.interrupt_pending &= ~0x4;
159         }
160         break;
161
162      default:
163         fatalerror("ppc: Unhandled exception %d\n", exception);
164         break;
165   }
166}
167
168static void ppc603_set_irq_line(int irqline, int state)
169{
170   if( state ) {
171      ppc.interrupt_pending |= 0x1;
172      if (ppc.irq_callback)
173      {
174         ppc.irq_callback(ppc.device, irqline);
175      }
176   }
177}
178
179static void ppc603_set_smi_line(int state)
180{
181   if( state ) {
182      ppc.interrupt_pending |= 0x4;
183   }
184}
185
186INLINE void ppc603_check_interrupts(void)
187{
188   if (MSR & MSR_EE)
189   {
190      if (ppc.interrupt_pending != 0)
191      {
192         if (ppc.interrupt_pending & 0x1)
193         {
194            ppc603_exception(EXCEPTION_IRQ);
195         }
196         else if (ppc.interrupt_pending & 0x2)
197         {
198            ppc603_exception(EXCEPTION_DECREMENTER);
199         }
200         else if (ppc.interrupt_pending & 0x4)
201         {
202            ppc603_exception(EXCEPTION_SMI);
203         }
204      }
205   }
206}
207
208static CPU_RESET( ppc603 )
209{
210   ppc.pc = ppc.npc = 0xfff00100;
211
212   ppc_set_msr(0x40);
213
214   ppc.hid0 = 1;
215
216   ppc.interrupt_pending = 0;
217}
218
219
220static CPU_EXECUTE( ppc603 )
221{
222   int exception_type;
223   UINT32 opcode;
224   ppc_tb_base_icount = ppc_icount;
225   ppc_dec_base_icount = ppc_icount + ppc.dec_frac;
226
227   // check if decrementer exception occurs during execution
228   if ((UINT32)(DEC - ppc_icount) > (UINT32)(DEC))
229   {
230      ppc_dec_trigger_cycle = ppc_icount - DEC;
231   }
232   else
233   {
234      ppc_dec_trigger_cycle = 0x7fffffff;
235   }
236
237   // MinGW's optimizer kills setjmp()/longjmp()
238   SETJMP_GNUC_PROTECT();
239
240   exception_type = setjmp(ppc.exception_jmpbuf);
241   if (exception_type)
242   {
243      ppc.npc = ppc.pc;
244      ppc603_exception(exception_type);
245   }
246
247   while( ppc_icount > 0 )
248   {
249      ppc.pc = ppc.npc;
250      debugger_instruction_hook(device, ppc.pc);
251
252      if (MSR & MSR_IR)
253         opcode = ppc_readop_translated(ppc.program, ppc.pc);
254      else
255      opcode = ROPCODE64(ppc.pc);
256
257      ppc.npc = ppc.pc + 4;
258      switch(opcode >> 26)
259      {
260         case 19:    ppc.optable19[(opcode >> 1) & 0x3ff](opcode); break;
261         case 31:    ppc.optable31[(opcode >> 1) & 0x3ff](opcode); break;
262         case 59:    ppc.optable59[(opcode >> 1) & 0x3ff](opcode); break;
263         case 63:    ppc.optable63[(opcode >> 1) & 0x3ff](opcode); break;
264         default:    ppc.optable[opcode >> 26](opcode); break;
265      }
266
267      ppc_icount--;
268
269      if(ppc_icount == ppc_dec_trigger_cycle) {
270         ppc.interrupt_pending |= 0x2;
271      }
272
273      ppc603_check_interrupts();
274   }
275
276   // update timebase
277   // timebase is incremented once every four core clock cycles, so adjust the cycles accordingly
278   ppc.tb += ((ppc_tb_base_icount - ppc_icount) / 4);
279
280   // update decrementer
281   ppc.dec_frac = ((ppc_dec_base_icount - ppc_icount) % (bus_freq_multiplier * 2));
282   DEC -= ((ppc_dec_base_icount - ppc_icount) / (bus_freq_multiplier * 2));
283}
trunk/src/emu/cpu/powerpc/ppc_mem.c
r28739r28740
1#define DUMP_PAGEFAULTS 0
2
3INLINE UINT8 READ8(UINT32 a)
4{
5   return ppc.read8(ppc.program, a);
6}
7
8INLINE UINT16 READ16(UINT32 a)
9{
10   if( a & 0x1 )
11      return ppc.read16_unaligned(ppc.program, a);
12   else
13      return ppc.read16(ppc.program, a);
14}
15
16INLINE UINT32 READ32(UINT32 a)
17{
18   if( a & 0x3 )
19      return ppc.read32_unaligned(ppc.program, a);
20   else
21      return ppc.read32(ppc.program, a);
22}
23
24INLINE UINT64 READ64(UINT32 a)
25{
26   if( a & 0x7 )
27      return ppc.read64_unaligned(ppc.program, a);
28   else
29      return ppc.read64(ppc.program, a);
30}
31
32INLINE void WRITE8(UINT32 a, UINT8 d)
33{
34   ppc.write8(ppc.program, a, d);
35}
36
37INLINE void WRITE16(UINT32 a, UINT16 d)
38{
39   if( a & 0x1 )
40      ppc.write16_unaligned(ppc.program, a, d);
41   else
42      ppc.write16(ppc.program, a, d);
43}
44
45INLINE void WRITE32(UINT32 a, UINT32 d)
46{
47   if( ppc.reserved ) {
48      if( a == ppc.reserved_address ) {
49         ppc.reserved = 0;
50      }
51   }
52
53   if( a & 0x3 )
54      ppc.write32_unaligned(ppc.program, a, d);
55   else
56      ppc.write32(ppc.program, a, d);
57}
58
59INLINE void WRITE64(UINT32 a, UINT64 d)
60{
61   if( a & 0x7 )
62      ppc.write64_unaligned(ppc.program, a, d);
63   else
64      ppc.write64(ppc.program, a, d);
65}
66
67/***********************************************************************/
68
69static UINT16 ppc_read16_unaligned(address_space &space, UINT32 a)
70{
71   return ((UINT16)ppc.read8(space, a+0) << 8) | ((UINT16)ppc.read8(space, a+1) << 0);
72}
73
74static UINT32 ppc_read32_unaligned(address_space &space, UINT32 a)
75{
76   return ((UINT32)ppc.read8(space, a+0) << 24) | ((UINT32)ppc.read8(space, a+1) << 16) |
77               ((UINT32)ppc.read8(space, a+2) << 8) | ((UINT32)ppc.read8(space, a+3) << 0);
78}
79
80static UINT64 ppc_read64_unaligned(address_space &space, UINT32 a)
81{
82   return ((UINT64)READ32(space, a+0) << 32) | (UINT64)(READ32(space, a+4));
83}
84
85static void ppc_write16_unaligned(address_space &space, UINT32 a, UINT16 d)
86{
87   ppc.write8(space, a+0, (UINT8)(d >> 8));
88   ppc.write8(space, a+1, (UINT8)(d));
89}
90
91static void ppc_write32_unaligned(address_space &space, UINT32 a, UINT32 d)
92{
93   ppc.write8(space, a+0, (UINT8)(d >> 24));
94   ppc.write8(space, a+1, (UINT8)(d >> 16));
95   ppc.write8(space, a+2, (UINT8)(d >> 8));
96   ppc.write8(space, a+3, (UINT8)(d >> 0));
97}
98
99static void ppc_write64_unaligned(address_space &space, UINT32 a, UINT64 d)
100{
101   ppc.write32(space, a+0, (UINT32)(d >> 32));
102   ppc.write32(space, a+4, (UINT32)(d));
103}
104
105/***********************************************************************/
106
107#define DSISR_PAGE      0x40000000
108#define DSISR_PROT      0x08000000
109#define DSISR_STORE     0x02000000
110
111enum
112{
113   PPC_TRANSLATE_DATA  = 0x0000,
114   PPC_TRANSLATE_CODE  = 0x0001,
115
116   PPC_TRANSLATE_READ  = 0x0000,
117   PPC_TRANSLATE_WRITE = 0x0002,
118
119   PPC_TRANSLATE_NOEXCEPTION = 0x0004
120};
121
122static int ppc_is_protected(UINT32 pp, int flags)
123{
124   if (flags & PPC_TRANSLATE_WRITE)
125   {
126      if ((pp & 0x00000003) != 0x00000002)
127         return TRUE;
128   }
129   else
130   {
131      if ((pp & 0x00000003) == 0x00000000)
132         return TRUE;
133   }
134   return FALSE;
135}
136
137static int ppc_translate_address(offs_t *addr_ptr, int flags)
138{
139   const BATENT *bat;
140   UINT32 address;
141   UINT32 sr, vsid, hash;
142   UINT32 pteg_address;
143   UINT32 target_pte, bl, mask;
144   UINT64 pte;
145   UINT64 *pteg_ptr[2];
146   int i, hash_type;
147   UINT32 dsisr = DSISR_PROT;
148
149   bat = (flags & PPC_TRANSLATE_CODE) ? ppc.ibat : ppc.dbat;
150
151   address = *addr_ptr;
152
153   /* first check the block address translation table */
154   for (i = 0; i < 4; i++)
155   {
156      if (bat[i].u & ((MSR & MSR_PR) ? 0x00000001 : 0x00000002))
157      {
158         bl = bat[i].u & 0x00001FFC;
159         mask = (~bl << 15) & 0xFFFE0000;
160
161         if ((address & mask) == (bat[i].u & 0xFFFE0000))
162         {
163            if (ppc_is_protected(bat[i].l, flags))
164               goto exception;
165
166            *addr_ptr = (bat[i].l & 0xFFFE0000)
167               | (address & ((bl << 15) | 0x0001FFFF));
168            return 1;
169         }
170      }
171   }
172
173   /* now try page address translation */
174   sr = ppc.sr[(address >> 28) & 0x0F];
175   if (sr & 0x80000000)
176   {
177      /* direct store translation */
178      if ((flags & PPC_TRANSLATE_NOEXCEPTION) == 0)
179         fatalerror("ppc: direct store translation not yet implemented\n");
180      return 0;
181   }
182   else
183   {
184      /* is no execute is set? */
185      if ((flags & PPC_TRANSLATE_CODE) && (sr & 0x10000000))
186         goto exception;
187
188      vsid = sr & 0x00FFFFFF;
189      hash = (vsid & 0x0007FFFF) ^ ((address >> 12) & 0xFFFF);
190      target_pte = (vsid << 7) | ((address >> 22) & 0x3F) | 0x80000000;
191
192      /* we have to try both types of hashes */
193      for (hash_type = 0; hash_type <= 1; hash_type++)
194      {
195         pteg_address = (ppc.sdr1 & 0xFFFF0000)
196            | (((ppc.sdr1 & 0x01FF) & (hash >> 10)) << 16)
197            | ((hash & 0x03FF) << 6);
198
199         pteg_ptr[hash_type] = ppc->program->get_read_ptr(pteg_address);
200         if (pteg_ptr[hash_type])
201         {
202            for (i = 0; i < 8; i++)
203            {
204               pte = pteg_ptr[hash_type][i];
205
206               /* is valid? */
207               if (((pte >> 32) & 0xFFFFFFFF) == target_pte)
208               {
209                  if (ppc_is_protected((UINT32) pte, flags))
210                     goto exception;
211
212                  *addr_ptr = ((UINT32) (pte & 0xFFFFF000))
213                     | (address & 0x0FFF);
214                  return 1;
215               }
216            }
217         }
218
219         hash ^= 0x7FFFF;
220         target_pte ^= 0x40;
221      }
222
223      if (DUMP_PAGEFAULTS)
224      {
225         mame_printf_debug("PAGE FAULT: address=%08X PC=%08X SDR1=%08X MSR=%08X\n", address, ppc.pc, ppc.sdr1, ppc.msr);
226         mame_printf_debug("\n");
227
228         for (i = 0; i < 4; i++)
229         {
230            bl = bat[i].u & 0x00001FFC;
231            mask = (~bl << 15) & 0xFFFE0000;
232            mame_printf_debug("    BAT[%d]=%08X%08X    (A & %08X = %08X)\n", i, bat[i].u, bat[i].l,
233               mask, bat[i].u & 0xFFFE0000);
234         }
235         mame_printf_debug("\n");
236         mame_printf_debug("    VSID=%06X HASH=%05X HASH\'=%05X\n", vsid, hash, hash ^ 0x7FFFF);
237
238         for (hash_type = 0; hash_type <= 1; hash_type++)
239         {
240            if (pteg_ptr[hash_type])
241            {
242               for (i = 0; i < 8; i++)
243               {
244                  pte = pteg_ptr[hash_type][i];
245                  mame_printf_debug("    PTE[%i%c]=%08X%08X\n",
246                     i,
247                     hash_type ? '\'' : ' ',
248                     (unsigned) (pte >> 32),
249                     (unsigned) (pte >> 0));
250               }
251            }
252         }
253      }
254   }
255
256   dsisr = DSISR_PAGE;
257
258exception:
259   /* lookup failure - exception */
260   if ((flags & PPC_TRANSLATE_NOEXCEPTION) == 0)
261   {
262      if (flags & PPC_TRANSLATE_CODE)
263      {
264         ppc_exception(EXCEPTION_ISI);
265      }
266      else
267      {
268         ppc.dar = address;
269         if (flags & PPC_TRANSLATE_WRITE)
270            ppc.dsisr = dsisr | DSISR_STORE;
271         else
272            ppc.dsisr = dsisr;
273
274         ppc_exception(EXCEPTION_DSI);
275      }
276   }
277   return 0;
278}
279
280static int ppc_translate_address_cb(address_spacenum space, offs_t *addr)
281{
282   int success = 1;
283
284   if (space == AS_PROGRAM)
285   {
286      if (MSR & MSR_DR)
287         success = ppc_translate_address(addr, PPC_TRANSLATE_CODE | PPC_TRANSLATE_READ | PPC_TRANSLATE_NOEXCEPTION);
288   }
289   return success;
290}
291
292static UINT8 ppc_read8_translated(address_space &space, offs_t address)
293{
294   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ);
295   return space.read_byte(address);
296}
297
298static UINT16 ppc_read16_translated(address_space &space, offs_t address)
299{
300   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ);
301   return space.read_word(address);
302}
303
304static UINT32 ppc_read32_translated(address_space &space, offs_t address)
305{
306   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ);
307   return space.read_dword(address);
308}
309
310static UINT64 ppc_read64_translated(address_space &space, offs_t address)
311{
312   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ);
313   return space.read_qword(address);
314}
315
316static void ppc_write8_translated(address_space &space, offs_t address, UINT8 data)
317{
318   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE);
319   space.write_byte(address, data);
320}
321
322static void ppc_write16_translated(address_space &space, offs_t address, UINT16 data)
323{
324   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE);
325   space.write_word(address, data);
326}
327
328static void ppc_write32_translated(address_space &space, offs_t address, UINT32 data)
329{
330   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE);
331   space.write_dword(address, data);
332}
333
334static void ppc_write64_translated(address_space &space, offs_t address, UINT64 data)
335{
336   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE);
337   space.write_qword(address, data);
338}
339
340#ifndef PPC_DRC
341static UINT32 ppc_readop_translated(address_space &space, offs_t address)
342{
343   ppc_translate_address(&address, PPC_TRANSLATE_CODE | PPC_TRANSLATE_READ);
344   return space.read_dword(address);
345}
346#endif
347
348/***********************************************************************/
349
350
351static CPU_DISASSEMBLE( ppc )
352{
353   UINT32 op;
354   op = BIG_ENDIANIZE_INT32(*((UINT32 *) oprom));
355   return ppc_dasm_one(buffer, pc, op);
356}
357
358/***********************************************************************/
359
360static CPU_READOP( ppc )
361{
362   if (!(ppc.msr & MSR_IR))
363      return 0;
364
365   *value = 0;
366
367   if (ppc_translate_address(&offset, PPC_TRANSLATE_CODE | PPC_TRANSLATE_READ | PPC_TRANSLATE_NOEXCEPTION))
368   {
369      switch(size)
370      {
371         case 1: *value = ppc.program->read_byte(offset);    break;
372         case 2: *value = ppc.program->read_word(offset);    break;
373         case 4: *value = ppc.program->read_dword(offset);   break;
374         case 8: *value = ppc.program->read_qword(offset);   break;
375      }
376   }
377
378   return 1;
379}
380
381static CPU_READ( ppc )
382{
383   if (!(ppc.msr & MSR_DR))
384      return 0;
385
386   *value = 0;
387
388   if (ppc_translate_address(&offset, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ | PPC_TRANSLATE_NOEXCEPTION))
389   {
390      switch(size)
391      {
392         case 1: *value = ppc.program->read_byte(offset);    break;
393         case 2: *value = ppc.program->read_word(offset);    break;
394         case 4: *value = ppc.program->read_dword(offset);   break;
395         case 8: *value = ppc.program->read_qword(offset);   break;
396      }
397   }
398
399   return 1;
400}
401
402static CPU_WRITE( ppc )
403{
404   if (!(ppc.msr & MSR_DR))
405      return 0;
406
407   if (ppc_translate_address(&offset, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE | PPC_TRANSLATE_NOEXCEPTION))
408   {
409      switch(size)
410      {
411         case 1: ppc.program->write_byte(offset, value); break;
412         case 2: ppc.program->write_word(offset, value); break;
413         case 4: ppc.program->write_dword(offset, value);    break;
414         case 8: ppc.program->write_qword(offset, value);    break;
415      }
416   }
417
418   return 1;
419}
trunk/src/emu/cpu/powerpc/ppc403.inc
r0r28740
1/* PowerPC 403 specific functions */
2
3static void ppc403_dma_exec(int ch);
4
5#define DMA_CE      0x80000000
6#define DMA_CIE     0x40000000
7#define DMA_TD      0x20000000
8#define DMA_PL      0x10000000
9#define DMA_DAI     0x02000000
10#define DMA_SAI     0x01000000
11#define DMA_CP      0x00800000
12#define DMA_ETD     0x00000200
13#define DMA_TCE     0x00000100
14#define DMA_CH      0x00000080
15#define DMA_BME     0x00000040
16#define DMA_ECE     0x00000020
17#define DMA_TCD     0x00000010
18#define DMA_PCE     0x00000008
19
20static SPU_RX_HANDLER spu_rx_handler;
21static SPU_TX_HANDLER spu_tx_handler;
22static TIMER_CALLBACK( ppc403_spu_rx_callback );
23static TIMER_CALLBACK( ppc403_spu_tx_callback );
24
25static PPC_DMA_HANDLER spu_rx_dma_handler;
26static PPC_DMA_HANDLER spu_tx_dma_handler;
27static UINT8 *spu_rx_dma_ptr;
28static UINT8 *spu_tx_dma_ptr;
29
30static PPC_DMA_HANDLER dma_read_handler[4];
31static PPC_DMA_HANDLER dma_write_handler[4];
32static UINT8 *dma_read_ptr[4];
33static UINT8 *dma_write_ptr[4];
34
35INLINE void ppc_set_dcr(int dcr, UINT32 value)
36{
37   switch(dcr)
38   {
39      case DCR_BEAR:      ppc.bear = value; break;
40      case DCR_BESR:      ppc.besr = value; break;
41      case DCR_BR0:       ppc.br[0] = value; break;
42      case DCR_BR1:       ppc.br[1] = value; break;
43      case DCR_BR2:       ppc.br[2] = value; break;
44      case DCR_BR3:       ppc.br[3] = value; break;
45      case DCR_BR4:       ppc.br[4] = value; break;
46      case DCR_BR5:       ppc.br[5] = value; break;
47      case DCR_BR6:       ppc.br[6] = value; break;
48      case DCR_BR7:       ppc.br[7] = value; break;
49
50      case DCR_EXISR:     ppc.exisr &= ~value; break;
51      case DCR_EXIER:     EXIER = value; ppc.exisr &= EXIER; break;
52      case DCR_IOCR:      ppc.iocr = value; break;
53      case DCR_DMASR:     break;      /* TODO */
54      case DCR_DMADA0:    ppc.dma[0].da = value; break;
55      case DCR_DMADA1:    ppc.dma[1].da = value; break;
56      case DCR_DMADA2:    ppc.dma[2].da = value; break;
57      case DCR_DMADA3:    ppc.dma[3].da = value; break;
58      case DCR_DMASA0:    ppc.dma[0].sa = value; break;
59      case DCR_DMASA1:    ppc.dma[1].sa = value; break;
60      case DCR_DMASA2:    ppc.dma[2].sa = value; break;
61      case DCR_DMASA3:    ppc.dma[3].sa = value; break;
62      case DCR_DMACT0:    ppc.dma[0].ct = value; break;
63      case DCR_DMACT1:    ppc.dma[1].ct = value; break;
64      case DCR_DMACT2:    ppc.dma[2].ct = value; break;
65      case DCR_DMACT3:    ppc.dma[3].ct = value; break;
66      case DCR_DMACR0:    ppc.dma[0].cr = value; ppc403_dma_exec(0); break;
67      case DCR_DMACR1:    ppc.dma[1].cr = value; ppc403_dma_exec(1); break;
68      case DCR_DMACR2:    ppc.dma[2].cr = value; ppc403_dma_exec(2); break;
69      case DCR_DMACR3:    ppc.dma[3].cr = value; ppc403_dma_exec(3); break;
70
71      default:
72         fatalerror("ppc: set_dcr: Unimplemented DCR %X\n", dcr);
73         break;
74   }
75}
76
77INLINE UINT32 ppc_get_dcr(int dcr)
78{
79   switch(dcr)
80   {
81      case DCR_BEAR:      return ppc.bear;
82      case DCR_BESR:      return ppc.besr;
83      case DCR_BR0:       return ppc.br[0];
84      case DCR_BR1:       return ppc.br[1];
85      case DCR_BR2:       return ppc.br[2];
86      case DCR_BR3:       return ppc.br[3];
87      case DCR_BR4:       return ppc.br[4];
88      case DCR_BR5:       return ppc.br[5];
89      case DCR_BR6:       return ppc.br[6];
90      case DCR_BR7:       return ppc.br[7];
91      case DCR_EXISR:     return EXISR;
92      case DCR_EXIER:     return EXIER;
93      case DCR_IOCR:      return ppc.iocr;
94      case DCR_DMASR:     return ppc.dmasr;
95      case DCR_DMADA0:    return ppc.dma[0].da;
96      case DCR_DMADA1:    return ppc.dma[1].da;
97      case DCR_DMADA2:    return ppc.dma[2].da;
98      case DCR_DMADA3:    return ppc.dma[3].da;
99      case DCR_DMASA0:    return ppc.dma[0].sa;
100      case DCR_DMASA1:    return ppc.dma[1].sa;
101      case DCR_DMASA2:    return ppc.dma[2].sa;
102      case DCR_DMASA3:    return ppc.dma[3].sa;
103      case DCR_DMACT0:    return ppc.dma[0].ct;
104      case DCR_DMACT1:    return ppc.dma[1].ct;
105      case DCR_DMACT2:    return ppc.dma[2].ct;
106      case DCR_DMACT3:    return ppc.dma[3].ct;
107      case DCR_DMACR0:    return ppc.dma[0].cr;
108      case DCR_DMACR1:    return ppc.dma[1].cr;
109      case DCR_DMACR2:    return ppc.dma[2].cr;
110      case DCR_DMACR3:    return ppc.dma[3].cr;
111
112      default:
113         fatalerror("ppc: get_dcr: Unimplemented DCR %X\n", dcr);
114         break;
115   }
116}
117
118
119
120#ifndef PPC_DRC
121INLINE void ppc403_check_interrupts(void)
122{
123   if (MSR & MSR_EE)
124   {
125      if (ppc.interrupt_pending != 0)
126      {
127         if (ppc.interrupt_pending & 0x1)
128         {
129            ppc403_exception(EXCEPTION_IRQ);
130         }
131         else if (ppc.interrupt_pending & 0x2)
132         {
133            ppc403_exception(EXCEPTION_PROGRAMMABLE_INTERVAL_TIMER);
134         }
135         else if (ppc.interrupt_pending & 0x4)
136         {
137            ppc403_exception(EXCEPTION_FIXED_INTERVAL_TIMER);
138         }
139      }
140   }
141}
142
143static CPU_RESET( ppc403 )
144{
145   ppc.pc = ppc.npc = 0xfffffffc;
146
147   ppc_set_msr(0);
148}
149
150static CPU_EXECUTE( ppc403 )
151{
152   UINT32 fit_trigger_cycle;
153   ppc_tb_base_icount = cycles;
154
155   fit_trigger_cycle = 0x7fffffff;
156
157   if (ppc.fit_int_enable)
158   {
159      UINT32 tb = (UINT32)ppc.tb;
160      UINT32 fit_cycles = 0;
161
162      if (ppc.tb & ppc.fit_bit)
163      {
164         fit_cycles += ppc.fit_bit;
165         tb += fit_cycles;
166      }
167
168      fit_cycles += ppc.fit_bit - (tb & (ppc.fit_bit-1));
169
170      fit_trigger_cycle = ppc_icount - fit_cycles;
171   }
172
173   while( ppc_icount > 0 )
174   {
175      UINT32 opcode;
176
177      debugger_instruction_hook(device, ppc.pc);
178      ppc.pc = ppc.npc;
179      ppc.npc += 4;
180      opcode = ROPCODE(ppc.pc);
181
182      switch(opcode >> 26)
183      {
184         case 19:    ppc.optable19[(opcode >> 1) & 0x3ff](opcode); break;
185         case 31:    ppc.optable31[(opcode >> 1) & 0x3ff](opcode); break;
186         case 59:    ppc.optable59[(opcode >> 1) & 0x3ff](opcode); break;
187         case 63:    ppc.optable63[(opcode >> 1) & 0x3ff](opcode); break;
188         default:    ppc.optable[opcode >> 26](opcode); break;
189      }
190
191      ppc_icount--;
192
193      /* Programmable Interval Timer (PIT) */
194      if (ppc.pit_counter > 0)
195      {
196         ppc.pit_counter--;
197         if (ppc.pit_counter == 0)
198         {
199            if (ppc.pit_int_enable) {
200               ppc.interrupt_pending |= 0x2;
201            }
202            if (ppc.tcr & 0x00400000)   // Automatic reload
203            {
204               ppc.pit_counter = ppc.pit;
205            }
206         }
207      }
208
209      /* Fixed Interval Timer */
210      if (fit_trigger_cycle != 0x7fffffff)
211      {
212         if (ppc_icount == fit_trigger_cycle)
213         {
214            if (ppc.fit_int_enable)
215            {
216               fit_trigger_cycle -= ppc.fit_bit;
217               ppc.interrupt_pending |= 0x4;
218            }
219         }
220      }
221
222#if 0
223      /* Watchdog Timer */
224      if (((UINT32)(ppc.tb) & ppc.wdt_bit) && (tblo & ppc.wdt_bit) == 0) {
225         switch((ppc.tsr >> 28) & 0x3)
226         {
227            case 0: ppc.tsr |= TSR_ENW; break;
228            case 1: ppc.tsr |= TSR_ENW; break;
229            case 2:
230               if (ppc.wdt_int_enable && (ppc.msr & MSR_CE)) {
231                  ppc403_exception(EXCEPTION_WATCHDOG_TIMER);
232               }
233               break;
234            case 3:
235               fatalerror("PPC: Watchdog Timer caused reset\n");
236               break;
237         }
238      }
239#endif
240
241      ppc403_check_interrupts();
242   }
243
244   // update timebase
245   ppc.tb += (ppc_tb_base_icount - ppc_icount);
246}
247
248void ppc403_exception(int exception)
249{
250   switch( exception )
251   {
252      case EXCEPTION_IRQ:     /* External Interrupt */
253      {
254         if( ppc_get_msr() & MSR_EE ) {
255            UINT32 msr = ppc_get_msr();
256
257            SRR0 = ppc.npc;
258            SRR1 = msr;
259
260            msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE);    // Clear WE, PR, EE, PR
261            if( msr & MSR_LE )
262               msr |= MSR_ILE;
263            else
264               msr &= ~MSR_ILE;
265            ppc_set_msr(msr);
266
267            ppc.npc = EVPR | 0x0500;
268
269            ppc.interrupt_pending &= ~0x1;
270         }
271         break;
272      }
273
274      case EXCEPTION_TRAP:            /* Program exception / Trap */
275      {
276            UINT32 msr = ppc_get_msr();
277
278            SRR0 = ppc.pc;
279            SRR1 = msr;
280
281            msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE);    // Clear WE, PR, EE, PR
282            if( msr & MSR_ILE )
283               msr |= MSR_LE;
284            else
285               msr &= ~MSR_LE;
286            ppc_set_msr(msr);
287
288            if( msr & MSR_IP )
289               ppc.npc = 0xfff00000 | 0x0700;
290            else
291               ppc.npc = EVPR | 0x0700;
292         break;
293      }
294
295      case EXCEPTION_SYSTEM_CALL:     /* System call */
296      {
297            UINT32 msr = ppc_get_msr();
298
299            SRR0 = ppc.npc;
300            SRR1 = msr;
301
302            msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE);    // Clear WE, PR, EE, PR
303            if( msr & MSR_ILE )
304               msr |= MSR_LE;
305            else
306               msr &= ~MSR_LE;
307            ppc_set_msr(msr);
308
309            if( msr & MSR_IP )
310               ppc.npc = 0xfff00000 | 0x0c00;
311            else
312               ppc.npc = EVPR | 0x0c00;
313         break;
314      }
315
316      case EXCEPTION_PROGRAMMABLE_INTERVAL_TIMER:
317      {
318         if( ppc_get_msr() & MSR_EE ) {
319            UINT32 msr = ppc_get_msr();
320
321            SRR0 = ppc.npc;
322            SRR1 = msr;
323
324            msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE);    // Clear WE, PR, EE, PR
325            if( msr & MSR_LE )
326               msr |= MSR_ILE;
327            else
328               msr &= ~MSR_ILE;
329            ppc_set_msr(msr);
330
331            ppc.npc = EVPR | 0x1000;
332
333            ppc.tsr |= 0x08000000;      // PIT interrupt
334            ppc.interrupt_pending &= ~0x2;
335         }
336         break;
337      }
338
339      case EXCEPTION_FIXED_INTERVAL_TIMER:        /* Fixed Interval Timer */
340      {
341         if( ppc_get_msr() & MSR_EE ) {
342            UINT32 msr = ppc_get_msr();
343
344            SRR0 = ppc.npc;
345            SRR1 = msr;
346
347            msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE);    // Clear WE, PR, EE, PR
348            if( msr & MSR_LE )
349               msr |= MSR_ILE;
350            else
351               msr &= ~MSR_ILE;
352            ppc_set_msr(msr);
353
354            ppc.npc = EVPR | 0x1010;
355         ppc.interrupt_pending &= ~0x4;
356         }
357         break;
358      }
359
360      case EXCEPTION_WATCHDOG_TIMER:              /* Watchdog Timer */
361      {
362         UINT32 msr = ppc_get_msr();
363
364         SRR2 = ppc.npc;
365         SRR3 = msr;
366
367         msr &= ~(MSR_WE | MSR_PR | MSR_CE | MSR_EE | MSR_DE | MSR_PE | MSR_DR | MSR_IR);
368         if (msr & MSR_LE)
369            msr |= MSR_ILE;
370         else
371            msr &= ~MSR_ILE;
372         ppc_set_msr(msr);
373
374         ppc.npc = EVPR | 0x1020;
375         break;
376      }
377
378      case EXCEPTION_CRITICAL_INTERRUPT:
379      {
380         UINT32 msr = ppc_get_msr();
381
382         SRR2 = ppc.npc;
383         SRR3 = msr;
384
385         msr &= ~(MSR_WE | MSR_PR | MSR_CE | MSR_EE | MSR_DE | MSR_PE | MSR_DR | MSR_IR);
386         if (msr & MSR_LE)
387            msr |= MSR_ILE;
388         else
389            msr &= ~MSR_ILE;
390         ppc_set_msr(msr);
391
392         EXISR |= 0x80000000;
393         ppc.npc = EVPR | 0x100;
394         break;
395      }
396
397      default:
398         fatalerror("ppc: Unhandled exception %d\n", exception);
399         break;
400   }
401}
402
403static void ppc403_set_irq_line(int irqline, int state)
404{
405   if (irqline >= INPUT_LINE_IRQ0 && irqline <= INPUT_LINE_IRQ4)
406   {
407      UINT32 mask = (1 << (4 - irqline));
408      if( state == ASSERT_LINE) {
409         if( EXIER & mask ) {
410            ppc.exisr |= mask;
411            ppc.interrupt_pending |= 0x1;
412
413            if (ppc.irq_callback)
414            {
415               ppc.irq_callback(ppc.device, irqline);
416            }
417         }
418      }
419      // clear line is used to clear the interrupt when the interrupts are level-sensitive
420      else if (state == CLEAR_LINE)
421      {
422         ppc.exisr &= ~mask;
423      }
424   }
425   else if (irqline == PPC_IRQ_SPU_RX)
426   {
427      UINT32 mask = 0x08000000;
428      if (state) {
429         if( EXIER & mask ) {
430            ppc.exisr |= mask;
431            ppc.interrupt_pending |= 0x1;
432         }
433      }
434   }
435   else if (irqline == PPC_IRQ_SPU_TX)
436   {
437      UINT32 mask = 0x04000000;
438      if (state) {
439         if( EXIER & mask ) {
440            ppc.exisr |= mask;
441            ppc.interrupt_pending |= 0x1;
442         }
443      }
444   }
445   else if (irqline == PPC_IRQ_CRITICAL)
446   {
447      if (state) {
448         if (EXIER & 0x80000000) {
449            ppc403_exception(EXCEPTION_CRITICAL_INTERRUPT);
450         }
451      }
452   }
453   else
454   {
455      fatalerror("PPC: Unknown IRQ line %d\n", irqline);
456   }
457}
458
459static void ppc403_dma_set_irq_line(int dma, int state)
460{
461   UINT32 mask = (1 << (3 - dma)) << 20;
462   if( state ) {
463      if( EXIER & mask ) {
464         ppc.exisr |= mask;
465         ppc.interrupt_pending |= 0x1;
466      }
467   }
468}
469#endif
470
471#ifdef PPC_DRC
472static void ppc403_dma_set_irq_line(int dma, int state)
473{
474   UINT32 mask = (1 << (3 - dma)) << 20;
475   if( state ) {
476      if( EXIER & mask ) {
477         ppc.exisr |= mask;
478         ppc.exception_pending |= 0x1;
479      }
480   }
481}
482#endif
483
484
485
486
487
488
489#ifndef PPC_DRC
490static void ppc_dccci(UINT32 op)
491{
492}
493
494static void ppc_dcread(UINT32 op)
495{
496}
497
498static void ppc_icbt(UINT32 op)
499{
500}
501
502static void ppc_iccci(UINT32 op)
503{
504}
505
506static void ppc_icread(UINT32 op)
507{
508}
509
510static void ppc_rfci(UINT32 op)
511{
512   UINT32 msr;
513   ppc.npc = ppc.srr2;
514   msr = ppc.srr3;
515   ppc_set_msr( msr );
516
517}
518#endif
519
520static void ppc_mfdcr(UINT32 op)
521{
522   REG(RT) = ppc_get_dcr(SPR);
523}
524
525static void ppc_mtdcr(UINT32 op)
526{
527   ppc_set_dcr(SPR, REG(RS));
528}
529
530static void ppc_wrtee(UINT32 op)
531{
532   if( REG(RS) & 0x8000 )
533      ppc_set_msr( ppc_get_msr() | MSR_EE);
534   else
535      ppc_set_msr( ppc_get_msr() & ~MSR_EE);
536}
537
538static void ppc_wrteei(UINT32 op)
539{
540   if( op & 0x8000 )
541      ppc_set_msr( ppc_get_msr() | MSR_EE);
542   else
543      ppc_set_msr( ppc_get_msr() & ~MSR_EE);
544}
545
546
547
548/**************************************************************************/
549/* PPC403 Serial Port */
550
551static UINT8 ppc403_spu_r(UINT32 a)
552{
553   switch(a & 0xf)
554   {
555      case 0x0:       return ppc.spu.spls | 0x6;      /* transmit buffer is always empty */
556      case 0x2:       return ppc.spu.sphs;
557      case 0x4:       return (ppc.spu.brd >> 8) & 0xf;
558      case 0x5:       return (ppc.spu.brd & 0xff);
559      case 0x6:       return ppc.spu.spctl;
560      case 0x7:       return ppc.spu.sprc;
561      case 0x8:       return ppc.spu.sptc;
562      case 0x9:       return ppc.spu.sprb;
563      default:        fatalerror("ppc: spu_r: %02X\n", a & 0xf);
564   }
565}
566
567static void ppc403_spu_w(UINT32 a, UINT8 d)
568{
569   switch(a & 0xf)
570   {
571      case 0x0:
572         if( d & 0x80 )  ppc.spu.spls &= ~0x80;
573         if( d & 0x40 )  ppc.spu.spls &= ~0x40;
574         if( d & 0x20 )  ppc.spu.spls &= ~0x20;
575         if( d & 0x10 )  ppc.spu.spls &= ~0x10;
576         if( d & 0x08 )  ppc.spu.spls &= ~0x08;
577         break;
578
579      case 0x2:
580         ppc.spu.sphs = d;
581         break;
582
583      case 0x4:
584         ppc.spu.brd &= 0xff;
585         ppc.spu.brd |= (d << 8);
586         break;
587
588      case 0x5:
589         ppc.spu.brd &= 0xff00;
590         ppc.spu.brd |= d;
591         if (ppc.iocr & 0x2) {
592            mame_printf_debug("ppc: SPU Baud rate: %d\n", (3686400 / (ppc.spu.brd + 1)) / 16);
593         } else {
594            mame_printf_debug("ppc: SPU Baud rate: %d\n", (33333333 / (ppc.spu.brd + 1)) / 16);
595         }
596         break;
597
598      case 0x6:
599         ppc.spu.spctl = d;
600         break;
601
602      case 0x7:
603         ppc.spu.sprc = d;
604         if (ppc.spu.sprc & 0x80)    /* enable RX */
605         {
606            /*
607            int baud_rate;
608            if (ppc.iocr & 0x2) {
609                baud_rate = (3686400 / (ppc.spu.brd + 1)) / 16;
610            } else {
611                baud_rate = (33333333 / (ppc.spu.brd + 1)) / 16;
612            }
613            */
614
615            /* check if serial port is hooked to a DMA channel */
616            /* if so, do a DMA operation */
617            if( ((((ppc.spu.sprc >> 5) & 0x3) == 2) && (ppc.dma[2].cr & DMA_CE)) ||
618               ((((ppc.spu.sprc >> 5) & 0x3) == 3) && (ppc.dma[3].cr & DMA_CE)) )
619            {
620               int i;
621               int ch = (ppc.spu.sprc >> 5) & 0x3;
622            //  mame_printf_debug("ppc: DMA from serial port on channel %d (DA: %08X)\n", ch, ppc.dma[ch].da);
623
624               if (spu_rx_dma_handler)
625               {
626                  int length = ppc.dma[ch].ct;
627
628                  spu_rx_dma_handler(length);
629
630                  for (i=0; i < length; i++)
631                  {
632                     ppc.program->write_byte(ppc.dma[ch].da++, spu_rx_dma_ptr[i]);
633                  }
634               }
635
636               ppc.dmasr |= (1 << (27 - ch));
637
638               /* generate interrupts */
639               if( ppc.dma[ch].cr & DMA_CIE )
640               {
641                  ppc403_dma_set_irq_line( ch, PULSE_LINE );
642               }
643
644               /* set receive buffer full */
645               ppc.spu.spls = 0x80;
646
647#ifndef PPC_DRC
648               ppc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
649#else
650               ppcdrc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
651#endif
652            }
653         }
654         else                        /* disable RX */
655         {
656         }
657         break;
658
659      case 0x8:
660         ppc.spu.sptc = d;
661         break;
662
663      case 0x9:
664         ppc.spu.sptb = d;
665         ppc403_spu_tx_callback(NULL/* Machine */, NULL, cpunum_get_active());
666         break;
667
668      default:
669         fatalerror("ppc: spu_w: %02X, %02X\n", a & 0xf, d);
670         break;
671   }
672   //mame_printf_debug("spu_w: %02X, %02X at %08X\n", a & 0xf, d, ppc.pc);
673}
674
675void ppc403_spu_rx(UINT8 data)
676{
677   ppc.spu.sprb = data;
678
679   /* set receive buffer full */
680   ppc.spu.spls = 0x80;
681
682   /* generate interrupt if DMA is disabled and RBR interrupt is enabled */
683   if (((ppc.spu.sprc >> 5) & 0x3) == 0x01) {
684#ifndef PPC_DRC
685      ppc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
686#else
687      ppcdrc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
688#endif
689   }
690}
691
692static TIMER_CALLBACK( ppc403_spu_rx_callback )
693{
694   if (spu_rx_handler != NULL)
695   {
696      ppc403_spu_rx(spu_rx_handler());
697   }
698}
699
700static TIMER_CALLBACK( ppc403_spu_tx_callback )
701{
702   if (spu_tx_handler != NULL)
703   {
704      spu_tx_handler(ppc.spu.sptb);
705
706      /* generate interrupt if DMA is disabled and TBR interrupt is enabled */
707      if (((ppc.spu.sptc >> 5) & 0x3) == 0x01) {
708#ifndef PPC_DRC
709         ppc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
710#else
711         ppcdrc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
712#endif
713      }
714   }
715}
716
717void ppc403_install_spu_rx_handler(SPU_RX_HANDLER rx_handler)
718{
719   spu_rx_handler = rx_handler;
720}
721
722void ppc403_install_spu_tx_handler(SPU_TX_HANDLER tx_handler)
723{
724   spu_tx_handler = tx_handler;
725}
726
727
728void ppc403_spu_rx_dma(UINT8 *data, int length)
729{
730}
731
732void ppc403_install_spu_rx_dma_handler(PPC_DMA_HANDLER rx_dma_handler, UINT8 *buffer)
733{
734   spu_rx_dma_handler = rx_dma_handler;
735   spu_rx_dma_ptr = buffer;
736}
737
738void ppc403_install_spu_tx_dma_handler(PPC_DMA_HANDLER tx_dma_handler, UINT8 *buffer)
739{
740   spu_tx_dma_handler = tx_dma_handler;
741   spu_tx_dma_ptr = buffer;
742}
743
744/*********************************************************************************/
745
746/* PPC 403 DMA */
747
748static const int dma_transfer_width[4] = { 1, 2, 4, 16 };
749
750void ppc403_install_dma_read_handler(int ch, PPC_DMA_HANDLER dma_handler, UINT8 *buffer)
751{
752   dma_read_handler[ch] = dma_handler;
753   dma_read_ptr[ch] = buffer;
754}
755
756void ppc403_install_dma_write_handler(int ch, PPC_DMA_HANDLER dma_handler, UINT8 *buffer)
757{
758   dma_write_handler[ch] = dma_handler;
759   dma_write_ptr[ch] = buffer;
760}
761
762static void ppc403_dma_exec(int ch)
763{
764   int i;
765   int dai, sai, width;
766
767   /* Is the DMA channel enabled ? */
768   if( ppc.dma[ch].cr & DMA_CE )
769   {
770      /* transfer width */
771      width = dma_transfer_width[(ppc.dma[ch].cr >> 26) & 0x3];
772
773      if( ppc.dma[ch].cr & DMA_DAI )
774         dai = width;
775      else
776         dai = 0;        /* DA not incremented */
777
778      if( ppc.dma[ch].cr & DMA_SAI )
779         sai = width;
780      else
781         sai = 0;        /* SA not incremented */
782
783
784      /* transfer mode */
785      switch( (ppc.dma[ch].cr >> 21) & 0x3 )
786      {
787         case 0:     /* buffered DMA */
788            if( ppc.dma[ch].cr & DMA_TD )   /* peripheral to mem */
789            {
790               // nothing to do for now */
791            }
792            else                            /* mem to peripheral */
793            {
794               /* check if the serial port is hooked to channel 2 or 3 */
795               if( (ch == 2 && ((ppc.spu.sptc >> 5) & 0x3) == 2) ||
796                  (ch == 3 && ((ppc.spu.sptc >> 5) & 0x3) == 3) )
797               {
798                  mame_printf_debug("ppc: dma_exec: DMA to serial port on channel %d (DA: %08X)\n", ch, ppc.dma[ch].da);
799
800                  if (spu_tx_dma_handler)
801                  {
802                     int length = ppc.dma[ch].ct;
803
804                     for( i=0; i < length; i++ ) {
805                        spu_tx_dma_ptr[i] = ppc.program->read_byte(ppc.dma[ch].da++);
806                     }
807                     spu_tx_dma_handler(length);
808                  }
809
810#ifndef PPC_DRC
811                  ppc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
812#else
813                  ppcdrc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
814#endif
815               }
816               else {
817                  fatalerror("ppc: dma_exec: buffered DMA to unknown peripheral ! (channel %d)\n", ch);
818               }
819
820            }
821            break;
822
823         case 1:     /* fly-by DMA */
824            fatalerror("ppc: dma_exec: fly-by DMA not implemented\n");
825            break;
826
827         case 2:     /* software initiated mem-to-mem DMA */
828            //mame_printf_debug("ppc: DMA (%d, SW mem-to-mem): SA = %08X, DA = %08X, CT = %08X\n", ch, ppc.dma[ch].sa, ppc.dma[ch].da, ppc.dma[ch].ct);
829
830            switch(width)
831            {
832               case 1:     /* Byte transfer */
833                  for (i=0; i < ppc.dma[ch].ct; i++)
834                  {
835                     UINT8 b = READ8(ppc.dma[ch].sa);
836                     WRITE8(ppc.dma[ch].da, b);
837                     ppc.dma[ch].sa += sai;
838                     ppc.dma[ch].da += dai;
839                  }
840                  break;
841               case 2:     /* Word transfer */
842                  for (i=0; i < ppc.dma[ch].ct; i++)
843                  {
844                     UINT16 w = READ16(ppc.dma[ch].sa);
845                     WRITE16(ppc.dma[ch].da, w);
846                     ppc.dma[ch].sa += sai;
847                     ppc.dma[ch].da += dai;
848                  }
849                  break;
850               case 4:     /* Double word transfer */
851                  for (i=0; i < ppc.dma[ch].ct; i++)
852                  {
853                     UINT32 d = READ32(ppc.dma[ch].sa);
854                     WRITE32(ppc.dma[ch].da, d);
855                     ppc.dma[ch].sa += sai;
856                     ppc.dma[ch].da += dai;
857                  }
858                  break;
859               case 16:    /* 16-byte transfer */
860                  for (i=0; i < ppc.dma[ch].ct; i++)
861                  {
862                     UINT32 d1 = READ32(ppc.dma[ch].sa+0);
863                     UINT32 d2 = READ32(ppc.dma[ch].sa+4);
864                     UINT32 d3 = READ32(ppc.dma[ch].sa+8);
865                     UINT32 d4 = READ32(ppc.dma[ch].sa+12);
866                     WRITE32(ppc.dma[ch].da+0, d1);
867                     WRITE32(ppc.dma[ch].da+4, d2);
868                     WRITE32(ppc.dma[ch].da+8, d3);
869                     WRITE32(ppc.dma[ch].da+12, d4);
870                     ppc.dma[ch].sa += 16;
871                     ppc.dma[ch].da += 16;
872                  }
873                  break;
874               default:
875                  fatalerror("dma: dma_exec: SW mem-to-mem DMA, width = %d\n", width);
876            }
877            break;
878
879         case 3:     /* hardware initiated mem-to-mem DMA */
880            fatalerror("ppc: dma_exec: HW mem-to-mem DMA not implemented\n");
881            break;
882      }
883
884      ppc.dmasr |= (1 << (27 - ch));
885
886      /* DEBUG: check for not yet supported features */
887      if( (ppc.dma[ch].cr & DMA_TCE) == 0 )
888         fatalerror("ppc: dma_exec: DMA_TCE == 0\n");
889
890      if( ppc.dma[ch].cr & DMA_CH )
891         fatalerror("ppc: dma_exec: DMA chaining not implemented\n");
892
893      /* generate interrupts */
894      if( ppc.dma[ch].cr & DMA_CIE )
895         ppc403_dma_set_irq_line( ch, PULSE_LINE );
896
897   }
898}
899
900/*********************************************************************************/
901
902static UINT8 ppc403_read8(address_space &space, UINT32 a)
903{
904   if(a >= 0x40000000 && a <= 0x4000000f)      /* Serial Port */
905      return ppc403_spu_r(a);
906   return space.read_byte(a);
907}
908
909#define ppc403_read16   memory_read_word_32be
910#define ppc403_read32   memory_read_dword_32be
911
912static void ppc403_write8(address_space &space, UINT32 a, UINT8 d)
913{
914   if( a >= 0x40000000 && a <= 0x4000000f )        /* Serial Port */
915   {
916      ppc403_spu_w(a, d);
917      return;
918   }
919   space.write_byte(a, d);
920}
921
922#define ppc403_write16  memory_write_word_32be
923#define ppc403_write32  memory_write_dword_32be
924
925static UINT16 ppc403_read16_unaligned(address_space &space, UINT32 a)
926{
927   fatalerror("ppc: Unaligned read16 %08X at %08X\n", a, ppc.pc);
928   return 0;
929}
930
931static UINT32 ppc403_read32_unaligned(address_space &space, UINT32 a)
932{
933   fatalerror("ppc: Unaligned read32 %08X at %08X\n", a, ppc.pc);
934   return 0;
935}
936
937static void ppc403_write16_unaligned(address_space &space, UINT32 a, UINT16 d)
938{
939   fatalerror("ppc: Unaligned write16 %08X, %04X at %08X\n", a, d, ppc.pc);
940}
941
942static void ppc403_write32_unaligned(address_space &space, UINT32 a, UINT32 d)
943{
944   fatalerror("ppc: Unaligned write32 %08X, %08X at %08X\n", a, d, ppc.pc);
945}
Property changes on: trunk/src/emu/cpu/powerpc/ppc403.inc
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/cpu/powerpc/ppc602.inc
r0r28740
1static void ppc_dsa(UINT32 op)
2{
3   UINT32 msr = ppc_get_msr();
4
5   msr &= ~(MSR_SA | MSR_EE | MSR_PR | MSR_AP);
6   if (ppc.esasrr & 0x8)   msr |= MSR_PR;
7   if (ppc.esasrr & 0x4)   msr |= MSR_AP;
8   if (ppc.esasrr & 0x2)   msr |= MSR_SA;
9   if (ppc.esasrr & 0x1)   msr |= MSR_EE;
10
11   ppc_set_msr(msr);
12}
13
14static void ppc_esa(UINT32 op)
15{
16   int sa, ee, pr, ap;
17   UINT32 msr = ppc_get_msr();
18
19   sa = (msr & MSR_SA) ? 1 : 0;
20   ee = (msr & MSR_EE) ? 1 : 0;
21   pr = (msr & MSR_PR) ? 1 : 0;
22   ap = (msr & MSR_AP) ? 1 : 0;
23
24   ppc.esasrr = (pr << 3) | (ap << 2) | (sa << 1) | (ee);
25
26   msr &= ~(MSR_EE | MSR_PR | MSR_AP);
27   msr |= MSR_SA;
28
29   ppc_set_msr(msr);
30}
31
32#ifndef PPC_DRC
33static void ppc_tlbli(UINT32 op)
34{
35}
36
37static void ppc_tlbld(UINT32 op)
38{
39}
40#endif
41
42#ifndef PPC_DRC
43void ppc602_exception(int exception)
44{
45   switch( exception )
46   {
47      case EXCEPTION_IRQ:     /* External Interrupt */
48         if( ppc_get_msr() & MSR_EE ) {
49            UINT32 msr = ppc_get_msr();
50
51            SRR0 = ppc.npc;
52            SRR1 = msr & 0xff73;
53
54            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
55            if( msr & MSR_ILE )
56               msr |= MSR_LE;
57            else
58               msr &= ~MSR_LE;
59            ppc_set_msr(msr);
60
61            if( msr & MSR_IP )
62               ppc.npc = 0xfff00000 | 0x0500;
63            else
64               ppc.npc = ppc.ibr | 0x0500;
65
66            ppc.interrupt_pending &= ~0x1;
67         }
68         break;
69
70      case EXCEPTION_DECREMENTER:     /* Decrementer overflow exception */
71         if( ppc_get_msr() & MSR_EE ) {
72            UINT32 msr = ppc_get_msr();
73
74            SRR0 = ppc.npc;
75            SRR1 = msr & 0xff73;
76
77            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
78            if( msr & MSR_ILE )
79               msr |= MSR_LE;
80            else
81               msr &= ~MSR_LE;
82            ppc_set_msr(msr);
83
84            if( msr & MSR_IP )
85               ppc.npc = 0xfff00000 | 0x0900;
86            else
87               ppc.npc = ppc.ibr | 0x0900;
88
89            ppc.interrupt_pending &= ~0x2;
90         }
91         break;
92
93      case EXCEPTION_TRAP:            /* Program exception / Trap */
94         {
95            UINT32 msr = ppc_get_msr();
96
97            SRR0 = ppc.pc;
98            SRR1 = (msr & 0xff73) | 0x20000;    /* 0x20000 = TRAP bit */
99
100            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
101            if( msr & MSR_ILE )
102               msr |= MSR_LE;
103            else
104               msr &= ~MSR_LE;
105
106            if( msr & MSR_IP )
107               ppc.npc = 0xfff00000 | 0x0700;
108            else
109               ppc.npc = ppc.ibr | 0x0700;
110         }
111         break;
112
113      case EXCEPTION_SYSTEM_CALL:     /* System call */
114         {
115            UINT32 msr = ppc_get_msr();
116
117            SRR0 = ppc.npc;
118            SRR1 = (msr & 0xff73);
119
120            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
121            if( msr & MSR_ILE )
122               msr |= MSR_LE;
123            else
124               msr &= ~MSR_LE;
125
126            if( msr & MSR_IP )
127               ppc.npc = 0xfff00000 | 0x0c00;
128            else
129               ppc.npc = ppc.ibr | 0x0c00;
130         }
131         break;
132
133      case EXCEPTION_SMI:
134         if( ppc_get_msr() & MSR_EE ) {
135            UINT32 msr = ppc_get_msr();
136
137            SRR0 = ppc.npc;
138            SRR1 = msr & 0xff73;
139
140            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
141            if( msr & MSR_ILE )
142               msr |= MSR_LE;
143            else
144               msr &= ~MSR_LE;
145            ppc_set_msr(msr);
146
147            if( msr & MSR_IP )
148               ppc.npc = 0xfff00000 | 0x1400;
149            else
150               ppc.npc = ppc.ibr | 0x1400;
151
152            ppc.interrupt_pending &= ~0x4;
153         }
154         break;
155
156
157      default:
158         fatalerror("ppc: Unhandled exception %d\n", exception);
159         break;
160   }
161}
162
163static void ppc602_set_irq_line(int irqline, int state)
164{
165   if( state ) {
166      ppc.interrupt_pending |= 0x1;
167      if (ppc.irq_callback)
168      {
169         ppc.irq_callback(ppc.device, irqline);
170      }
171   }
172}
173
174static void ppc602_set_smi_line(int state)
175{
176   if( state ) {
177      ppc.interrupt_pending |= 0x4;
178   }
179}
180
181INLINE void ppc602_check_interrupts(void)
182{
183   if (MSR & MSR_EE)
184   {
185      if (ppc.interrupt_pending != 0)
186      {
187         if (ppc.interrupt_pending & 0x1)
188         {
189            ppc602_exception(EXCEPTION_IRQ);
190         }
191         else if (ppc.interrupt_pending & 0x2)
192         {
193            ppc602_exception(EXCEPTION_DECREMENTER);
194         }
195         else if (ppc.interrupt_pending & 0x4)
196         {
197            ppc602_exception(EXCEPTION_SMI);
198         }
199      }
200   }
201}
202
203static CPU_RESET( ppc602 )
204{
205   ppc.pc = ppc.npc = 0xfff00100;
206
207   ppc_set_msr(0x40);
208
209   ppc.hid0 = 1;
210
211   ppc.interrupt_pending = 0;
212}
213
214static CPU_EXECUTE( ppc602 )
215{
216   int exception_type;
217   UINT32 opcode;
218   ppc_tb_base_icount = ppc_icount;
219   ppc_dec_base_icount = ppc_icount;
220
221   // check if decrementer exception occurs during execution
222   if ((UINT32)(DEC - ppc_icount) > (UINT32)(DEC))
223   {
224      ppc_dec_trigger_cycle = ppc_icount - DEC;
225   }
226   else
227   {
228      ppc_dec_trigger_cycle = 0x7fffffff;
229   }
230
231   // MinGW's optimizer kills setjmp()/longjmp()
232   SETJMP_GNUC_PROTECT();
233
234   exception_type = setjmp(ppc.exception_jmpbuf);
235   if (exception_type)
236   {
237      ppc.npc = ppc.pc;
238      ppc602_exception(exception_type);
239   }
240
241   while( ppc_icount > 0 )
242   {
243      ppc.pc = ppc.npc;
244      debugger_instruction_hook(device, ppc.pc);
245
246      if (MSR & MSR_IR)
247         opcode = ppc_readop_translated(ppc.program, ppc.pc);
248      else
249      opcode = ROPCODE64(ppc.pc);
250
251      ppc.npc = ppc.pc + 4;
252      switch(opcode >> 26)
253      {
254         case 19:    ppc.optable19[(opcode >> 1) & 0x3ff](opcode); break;
255         case 31:    ppc.optable31[(opcode >> 1) & 0x3ff](opcode); break;
256         case 59:    ppc.optable59[(opcode >> 1) & 0x3ff](opcode); break;
257         case 63:    ppc.optable63[(opcode >> 1) & 0x3ff](opcode); break;
258         default:    ppc.optable[opcode >> 26](opcode); break;
259      }
260
261      ppc_icount--;
262
263      if(ppc_icount == ppc_dec_trigger_cycle) {
264         ppc.interrupt_pending |= 0x2;
265      }
266
267      ppc602_check_interrupts();
268   }
269
270   // update timebase
271   // timebase is incremented once every four core clock cycles, so adjust the cycles accordingly
272   ppc.tb += ((ppc_tb_base_icount - ppc_icount) / 4);
273
274   // update decrementer
275   DEC -= ((ppc_dec_base_icount - ppc_icount) / (bus_freq_multiplier * 2));
276}
277#endif  // PPC_DRC
Property changes on: trunk/src/emu/cpu/powerpc/ppc602.inc
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/cpu/powerpc/ppc603.inc
r0r28740
1void ppc603_exception(int exception)
2{
3   switch( exception )
4   {
5      case EXCEPTION_IRQ:     /* External Interrupt */
6         if( ppc_get_msr() & MSR_EE ) {
7            UINT32 msr = ppc_get_msr();
8
9            SRR0 = ppc.npc;
10            SRR1 = msr & 0xff73;
11
12            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
13            if( msr & MSR_ILE )
14               msr |= MSR_LE;
15            else
16               msr &= ~MSR_LE;
17            ppc_set_msr(msr);
18
19            if( msr & MSR_IP )
20               ppc.npc = 0xfff00000 | 0x0500;
21            else
22               ppc.npc = 0x00000000 | 0x0500;
23
24            ppc.interrupt_pending &= ~0x1;
25         }
26         break;
27
28      case EXCEPTION_DECREMENTER:     /* Decrementer overflow exception */
29         if( ppc_get_msr() & MSR_EE ) {
30            UINT32 msr = ppc_get_msr();
31
32            SRR0 = ppc.npc;
33            SRR1 = msr & 0xff73;
34
35            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
36            if( msr & MSR_ILE )
37               msr |= MSR_LE;
38            else
39               msr &= ~MSR_LE;
40            ppc_set_msr(msr);
41
42            if( msr & MSR_IP )
43               ppc.npc = 0xfff00000 | 0x0900;
44            else
45               ppc.npc = 0x00000000 | 0x0900;
46
47            ppc.interrupt_pending &= ~0x2;
48         }
49         break;
50
51      case EXCEPTION_TRAP:            /* Program exception / Trap */
52         {
53            UINT32 msr = ppc_get_msr();
54
55            SRR0 = ppc.pc;
56            SRR1 = (msr & 0xff73) | 0x20000;    /* 0x20000 = TRAP bit */
57
58            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
59            if( msr & MSR_ILE )
60               msr |= MSR_LE;
61            else
62               msr &= ~MSR_LE;
63            ppc_set_msr(msr);
64
65            if( msr & MSR_IP )
66               ppc.npc = 0xfff00000 | 0x0700;
67            else
68               ppc.npc = 0x00000000 | 0x0700;
69         }
70         break;
71
72      case EXCEPTION_SYSTEM_CALL:     /* System call */
73         {
74            UINT32 msr = ppc_get_msr();
75
76            SRR0 = ppc.npc;
77            SRR1 = (msr & 0xff73);
78
79            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
80            if( msr & MSR_ILE )
81               msr |= MSR_LE;
82            else
83               msr &= ~MSR_LE;
84            ppc_set_msr(msr);
85
86            if( msr & MSR_IP )
87               ppc.npc = 0xfff00000 | 0x0c00;
88            else
89               ppc.npc = 0x00000000 | 0x0c00;
90         }
91         break;
92
93      case EXCEPTION_SMI:
94         if( ppc_get_msr() & MSR_EE ) {
95            UINT32 msr = ppc_get_msr();
96
97            SRR0 = ppc.npc;
98            SRR1 = msr & 0xff73;
99
100            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
101            if( msr & MSR_ILE )
102               msr |= MSR_LE;
103            else
104               msr &= ~MSR_LE;
105            ppc_set_msr(msr);
106
107            if( msr & MSR_IP )
108               ppc.npc = 0xfff00000 | 0x1400;
109            else
110               ppc.npc = 0x00000000 | 0x1400;
111
112            ppc.interrupt_pending &= ~0x4;
113         }
114         break;
115
116      case EXCEPTION_DSI:
117         {
118            UINT32 msr = ppc_get_msr();
119
120            SRR0 = ppc.npc;
121            SRR1 = msr & 0xff73;
122
123            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
124            if( msr & MSR_ILE )
125               msr |= MSR_LE;
126            else
127               msr &= ~MSR_LE;
128            ppc_set_msr(msr);
129
130            if( msr & MSR_IP )
131               ppc.npc = 0xfff00000 | 0x0300;
132            else
133               ppc.npc = 0x00000000 | 0x0300;
134
135            ppc.interrupt_pending &= ~0x4;
136         }
137         break;
138
139      case EXCEPTION_ISI:
140         {
141            UINT32 msr = ppc_get_msr();
142
143            SRR0 = ppc.npc;
144            SRR1 = msr & 0xff73;
145
146            msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
147            if( msr & MSR_ILE )
148               msr |= MSR_LE;
149            else
150               msr &= ~MSR_LE;
151            ppc_set_msr(msr);
152
153            if( msr & MSR_IP )
154               ppc.npc = 0xfff00000 | 0x0400;
155            else
156               ppc.npc = 0x00000000 | 0x0400;
157
158            ppc.interrupt_pending &= ~0x4;
159         }
160         break;
161
162      default:
163         fatalerror("ppc: Unhandled exception %d\n", exception);
164         break;
165   }
166}
167
168static void ppc603_set_irq_line(int irqline, int state)
169{
170   if( state ) {
171      ppc.interrupt_pending |= 0x1;
172      if (ppc.irq_callback)
173      {
174         ppc.irq_callback(ppc.device, irqline);
175      }
176   }
177}
178
179static void ppc603_set_smi_line(int state)
180{
181   if( state ) {
182      ppc.interrupt_pending |= 0x4;
183   }
184}
185
186INLINE void ppc603_check_interrupts(void)
187{
188   if (MSR & MSR_EE)
189   {
190      if (ppc.interrupt_pending != 0)
191      {
192         if (ppc.interrupt_pending & 0x1)
193         {
194            ppc603_exception(EXCEPTION_IRQ);
195         }
196         else if (ppc.interrupt_pending & 0x2)
197         {
198            ppc603_exception(EXCEPTION_DECREMENTER);
199         }
200         else if (ppc.interrupt_pending & 0x4)
201         {
202            ppc603_exception(EXCEPTION_SMI);
203         }
204      }
205   }
206}
207
208static CPU_RESET( ppc603 )
209{
210   ppc.pc = ppc.npc = 0xfff00100;
211
212   ppc_set_msr(0x40);
213
214   ppc.hid0 = 1;
215
216   ppc.interrupt_pending = 0;
217}
218
219
220static CPU_EXECUTE( ppc603 )
221{
222   int exception_type;
223   UINT32 opcode;
224   ppc_tb_base_icount = ppc_icount;
225   ppc_dec_base_icount = ppc_icount + ppc.dec_frac;
226
227   // check if decrementer exception occurs during execution
228   if ((UINT32)(DEC - ppc_icount) > (UINT32)(DEC))
229   {
230      ppc_dec_trigger_cycle = ppc_icount - DEC;
231   }
232   else
233   {
234      ppc_dec_trigger_cycle = 0x7fffffff;
235   }
236
237   // MinGW's optimizer kills setjmp()/longjmp()
238   SETJMP_GNUC_PROTECT();
239
240   exception_type = setjmp(ppc.exception_jmpbuf);
241   if (exception_type)
242   {
243      ppc.npc = ppc.pc;
244      ppc603_exception(exception_type);
245   }
246
247   while( ppc_icount > 0 )
248   {
249      ppc.pc = ppc.npc;
250      debugger_instruction_hook(device, ppc.pc);
251
252      if (MSR & MSR_IR)
253         opcode = ppc_readop_translated(ppc.program, ppc.pc);
254      else
255      opcode = ROPCODE64(ppc.pc);
256
257      ppc.npc = ppc.pc + 4;
258      switch(opcode >> 26)
259      {
260         case 19:    ppc.optable19[(opcode >> 1) & 0x3ff](opcode); break;
261         case 31:    ppc.optable31[(opcode >> 1) & 0x3ff](opcode); break;
262         case 59:    ppc.optable59[(opcode >> 1) & 0x3ff](opcode); break;
263         case 63:    ppc.optable63[(opcode >> 1) & 0x3ff](opcode); break;
264         default:    ppc.optable[opcode >> 26](opcode); break;
265      }
266
267      ppc_icount--;
268
269      if(ppc_icount == ppc_dec_trigger_cycle) {
270         ppc.interrupt_pending |= 0x2;
271      }
272
273      ppc603_check_interrupts();
274   }
275
276   // update timebase
277   // timebase is incremented once every four core clock cycles, so adjust the cycles accordingly
278   ppc.tb += ((ppc_tb_base_icount - ppc_icount) / 4);
279
280   // update decrementer
281   ppc.dec_frac = ((ppc_dec_base_icount - ppc_icount) % (bus_freq_multiplier * 2));
282   DEC -= ((ppc_dec_base_icount - ppc_icount) / (bus_freq_multiplier * 2));
283}
Property changes on: trunk/src/emu/cpu/powerpc/ppc603.inc
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/cpu/powerpc/ppc_mem.inc
r0r28740
1#define DUMP_PAGEFAULTS 0
2
3INLINE UINT8 READ8(UINT32 a)
4{
5   return ppc.read8(ppc.program, a);
6}
7
8INLINE UINT16 READ16(UINT32 a)
9{
10   if( a & 0x1 )
11      return ppc.read16_unaligned(ppc.program, a);
12   else
13      return ppc.read16(ppc.program, a);
14}
15
16INLINE UINT32 READ32(UINT32 a)
17{
18   if( a & 0x3 )
19      return ppc.read32_unaligned(ppc.program, a);
20   else
21      return ppc.read32(ppc.program, a);
22}
23
24INLINE UINT64 READ64(UINT32 a)
25{
26   if( a & 0x7 )
27      return ppc.read64_unaligned(ppc.program, a);
28   else
29      return ppc.read64(ppc.program, a);
30}
31
32INLINE void WRITE8(UINT32 a, UINT8 d)
33{
34   ppc.write8(ppc.program, a, d);
35}
36
37INLINE void WRITE16(UINT32 a, UINT16 d)
38{
39   if( a & 0x1 )
40      ppc.write16_unaligned(ppc.program, a, d);
41   else
42      ppc.write16(ppc.program, a, d);
43}
44
45INLINE void WRITE32(UINT32 a, UINT32 d)
46{
47   if( ppc.reserved ) {
48      if( a == ppc.reserved_address ) {
49         ppc.reserved = 0;
50      }
51   }
52
53   if( a & 0x3 )
54      ppc.write32_unaligned(ppc.program, a, d);
55   else
56      ppc.write32(ppc.program, a, d);
57}
58
59INLINE void WRITE64(UINT32 a, UINT64 d)
60{
61   if( a & 0x7 )
62      ppc.write64_unaligned(ppc.program, a, d);
63   else
64      ppc.write64(ppc.program, a, d);
65}
66
67/***********************************************************************/
68
69static UINT16 ppc_read16_unaligned(address_space &space, UINT32 a)
70{
71   return ((UINT16)ppc.read8(space, a+0) << 8) | ((UINT16)ppc.read8(space, a+1) << 0);
72}
73
74static UINT32 ppc_read32_unaligned(address_space &space, UINT32 a)
75{
76   return ((UINT32)ppc.read8(space, a+0) << 24) | ((UINT32)ppc.read8(space, a+1) << 16) |
77               ((UINT32)ppc.read8(space, a+2) << 8) | ((UINT32)ppc.read8(space, a+3) << 0);
78}
79
80static UINT64 ppc_read64_unaligned(address_space &space, UINT32 a)
81{
82   return ((UINT64)READ32(space, a+0) << 32) | (UINT64)(READ32(space, a+4));
83}
84
85static void ppc_write16_unaligned(address_space &space, UINT32 a, UINT16 d)
86{
87   ppc.write8(space, a+0, (UINT8)(d >> 8));
88   ppc.write8(space, a+1, (UINT8)(d));
89}
90
91static void ppc_write32_unaligned(address_space &space, UINT32 a, UINT32 d)
92{
93   ppc.write8(space, a+0, (UINT8)(d >> 24));
94   ppc.write8(space, a+1, (UINT8)(d >> 16));
95   ppc.write8(space, a+2, (UINT8)(d >> 8));
96   ppc.write8(space, a+3, (UINT8)(d >> 0));
97}
98
99static void ppc_write64_unaligned(address_space &space, UINT32 a, UINT64 d)
100{
101   ppc.write32(space, a+0, (UINT32)(d >> 32));
102   ppc.write32(space, a+4, (UINT32)(d));
103}
104
105/***********************************************************************/
106
107#define DSISR_PAGE      0x40000000
108#define DSISR_PROT      0x08000000
109#define DSISR_STORE     0x02000000
110
111enum
112{
113   PPC_TRANSLATE_DATA  = 0x0000,
114   PPC_TRANSLATE_CODE  = 0x0001,
115
116   PPC_TRANSLATE_READ  = 0x0000,
117   PPC_TRANSLATE_WRITE = 0x0002,
118
119   PPC_TRANSLATE_NOEXCEPTION = 0x0004
120};
121
122static int ppc_is_protected(UINT32 pp, int flags)
123{
124   if (flags & PPC_TRANSLATE_WRITE)
125   {
126      if ((pp & 0x00000003) != 0x00000002)
127         return TRUE;
128   }
129   else
130   {
131      if ((pp & 0x00000003) == 0x00000000)
132         return TRUE;
133   }
134   return FALSE;
135}
136
137static int ppc_translate_address(offs_t *addr_ptr, int flags)
138{
139   const BATENT *bat;
140   UINT32 address;
141   UINT32 sr, vsid, hash;
142   UINT32 pteg_address;
143   UINT32 target_pte, bl, mask;
144   UINT64 pte;
145   UINT64 *pteg_ptr[2];
146   int i, hash_type;
147   UINT32 dsisr = DSISR_PROT;
148
149   bat = (flags & PPC_TRANSLATE_CODE) ? ppc.ibat : ppc.dbat;
150
151   address = *addr_ptr;
152
153   /* first check the block address translation table */
154   for (i = 0; i < 4; i++)
155   {
156      if (bat[i].u & ((MSR & MSR_PR) ? 0x00000001 : 0x00000002))
157      {
158         bl = bat[i].u & 0x00001FFC;
159         mask = (~bl << 15) & 0xFFFE0000;
160
161         if ((address & mask) == (bat[i].u & 0xFFFE0000))
162         {
163            if (ppc_is_protected(bat[i].l, flags))
164               goto exception;
165
166            *addr_ptr = (bat[i].l & 0xFFFE0000)
167               | (address & ((bl << 15) | 0x0001FFFF));
168            return 1;
169         }
170      }
171   }
172
173   /* now try page address translation */
174   sr = ppc.sr[(address >> 28) & 0x0F];
175   if (sr & 0x80000000)
176   {
177      /* direct store translation */
178      if ((flags & PPC_TRANSLATE_NOEXCEPTION) == 0)
179         fatalerror("ppc: direct store translation not yet implemented\n");
180      return 0;
181   }
182   else
183   {
184      /* is no execute is set? */
185      if ((flags & PPC_TRANSLATE_CODE) && (sr & 0x10000000))
186         goto exception;
187
188      vsid = sr & 0x00FFFFFF;
189      hash = (vsid & 0x0007FFFF) ^ ((address >> 12) & 0xFFFF);
190      target_pte = (vsid << 7) | ((address >> 22) & 0x3F) | 0x80000000;
191
192      /* we have to try both types of hashes */
193      for (hash_type = 0; hash_type <= 1; hash_type++)
194      {
195         pteg_address = (ppc.sdr1 & 0xFFFF0000)
196            | (((ppc.sdr1 & 0x01FF) & (hash >> 10)) << 16)
197            | ((hash & 0x03FF) << 6);
198
199         pteg_ptr[hash_type] = ppc->program->get_read_ptr(pteg_address);
200         if (pteg_ptr[hash_type])
201         {
202            for (i = 0; i < 8; i++)
203            {
204               pte = pteg_ptr[hash_type][i];
205
206               /* is valid? */
207               if (((pte >> 32) & 0xFFFFFFFF) == target_pte)
208               {
209                  if (ppc_is_protected((UINT32) pte, flags))
210                     goto exception;
211
212                  *addr_ptr = ((UINT32) (pte & 0xFFFFF000))
213                     | (address & 0x0FFF);
214                  return 1;
215               }
216            }
217         }
218
219         hash ^= 0x7FFFF;
220         target_pte ^= 0x40;
221      }
222
223      if (DUMP_PAGEFAULTS)
224      {
225         mame_printf_debug("PAGE FAULT: address=%08X PC=%08X SDR1=%08X MSR=%08X\n", address, ppc.pc, ppc.sdr1, ppc.msr);
226         mame_printf_debug("\n");
227
228         for (i = 0; i < 4; i++)
229         {
230            bl = bat[i].u & 0x00001FFC;
231            mask = (~bl << 15) & 0xFFFE0000;
232            mame_printf_debug("    BAT[%d]=%08X%08X    (A & %08X = %08X)\n", i, bat[i].u, bat[i].l,
233               mask, bat[i].u & 0xFFFE0000);
234         }
235         mame_printf_debug("\n");
236         mame_printf_debug("    VSID=%06X HASH=%05X HASH\'=%05X\n", vsid, hash, hash ^ 0x7FFFF);
237
238         for (hash_type = 0; hash_type <= 1; hash_type++)
239         {
240            if (pteg_ptr[hash_type])
241            {
242               for (i = 0; i < 8; i++)
243               {
244                  pte = pteg_ptr[hash_type][i];
245                  mame_printf_debug("    PTE[%i%c]=%08X%08X\n",
246                     i,
247                     hash_type ? '\'' : ' ',
248                     (unsigned) (pte >> 32),
249                     (unsigned) (pte >> 0));
250               }
251            }
252         }
253      }
254   }
255
256   dsisr = DSISR_PAGE;
257
258exception:
259   /* lookup failure - exception */
260   if ((flags & PPC_TRANSLATE_NOEXCEPTION) == 0)
261   {
262      if (flags & PPC_TRANSLATE_CODE)
263      {
264         ppc_exception(EXCEPTION_ISI);
265      }
266      else
267      {
268         ppc.dar = address;
269         if (flags & PPC_TRANSLATE_WRITE)
270            ppc.dsisr = dsisr | DSISR_STORE;
271         else
272            ppc.dsisr = dsisr;
273
274         ppc_exception(EXCEPTION_DSI);
275      }
276   }
277   return 0;
278}
279
280static int ppc_translate_address_cb(address_spacenum space, offs_t *addr)
281{
282   int success = 1;
283
284   if (space == AS_PROGRAM)
285   {
286      if (MSR & MSR_DR)
287         success = ppc_translate_address(addr, PPC_TRANSLATE_CODE | PPC_TRANSLATE_READ | PPC_TRANSLATE_NOEXCEPTION);
288   }
289   return success;
290}
291
292static UINT8 ppc_read8_translated(address_space &space, offs_t address)
293{
294   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ);
295   return space.read_byte(address);
296}
297
298static UINT16 ppc_read16_translated(address_space &space, offs_t address)
299{
300   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ);
301   return space.read_word(address);
302}
303
304static UINT32 ppc_read32_translated(address_space &space, offs_t address)
305{
306   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ);
307   return space.read_dword(address);
308}
309
310static UINT64 ppc_read64_translated(address_space &space, offs_t address)
311{
312   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ);
313   return space.read_qword(address);
314}
315
316static void ppc_write8_translated(address_space &space, offs_t address, UINT8 data)
317{
318   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE);
319   space.write_byte(address, data);
320}
321
322static void ppc_write16_translated(address_space &space, offs_t address, UINT16 data)
323{
324   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE);
325   space.write_word(address, data);
326}
327
328static void ppc_write32_translated(address_space &space, offs_t address, UINT32 data)
329{
330   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE);
331   space.write_dword(address, data);
332}
333
334static void ppc_write64_translated(address_space &space, offs_t address, UINT64 data)
335{
336   ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE);
337   space.write_qword(address, data);
338}
339
340#ifndef PPC_DRC
341static UINT32 ppc_readop_translated(address_space &space, offs_t address)
342{
343   ppc_translate_address(&address, PPC_TRANSLATE_CODE | PPC_TRANSLATE_READ);
344   return space.read_dword(address);
345}
346#endif
347
348/***********************************************************************/
349
350
351static CPU_DISASSEMBLE( ppc )
352{
353   UINT32 op;
354   op = BIG_ENDIANIZE_INT32(*((UINT32 *) oprom));
355   return ppc_dasm_one(buffer, pc, op);
356}
357
358/***********************************************************************/
359
360static CPU_READOP( ppc )
361{
362   if (!(ppc.msr & MSR_IR))
363      return 0;
364
365   *value = 0;
366
367   if (ppc_translate_address(&offset, PPC_TRANSLATE_CODE | PPC_TRANSLATE_READ | PPC_TRANSLATE_NOEXCEPTION))
368   {
369      switch(size)
370      {
371         case 1: *value = ppc.program->read_byte(offset);    break;
372         case 2: *value = ppc.program->read_word(offset);    break;
373         case 4: *value = ppc.program->read_dword(offset);   break;
374         case 8: *value = ppc.program->read_qword(offset);   break;
375      }
376   }
377
378   return 1;
379}
380
381static CPU_READ( ppc )
382{
383   if (!(ppc.msr & MSR_DR))
384      return 0;
385
386   *value = 0;
387
388   if (ppc_translate_address(&offset, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ | PPC_TRANSLATE_NOEXCEPTION))
389   {
390      switch(size)
391      {
392         case 1: *value = ppc.program->read_byte(offset);    break;
393         case 2: *value = ppc.program->read_word(offset);    break;
394         case 4: *value = ppc.program->read_dword(offset);   break;
395         case 8: *value = ppc.program->read_qword(offset);   break;
396      }
397   }
398
399   return 1;
400}
401
402static CPU_WRITE( ppc )
403{
404   if (!(ppc.msr & MSR_DR))
405      return 0;
406
407   if (ppc_translate_address(&offset, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE | PPC_TRANSLATE_NOEXCEPTION))
408   {
409      switch(size)
410      {
411         case 1: ppc.program->write_byte(offset, value); break;
412         case 2: ppc.program->write_word(offset, value); break;
413         case 4: ppc.program->write_dword(offset, value);    break;
414         case 8: ppc.program->write_qword(offset, value);    break;
415      }
416   }
417
418   return 1;
419}
Property changes on: trunk/src/emu/cpu/powerpc/ppc_mem.inc
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/cpu/powerpc/ppc.c
r28739r28740
858858
859859/***********************************************************************/
860860
861#include "ppc_mem.c"
861#include "ppc_mem.inc"
862862
863#include "ppc403.c"
864#include "ppc602.c"
865#include "ppc603.c"
863#include "ppc403.inc"
864#include "ppc602.inc"
865#include "ppc603.inc"
866866
867867/********************************************************************/
868868
869#include "ppc_ops.c"
869#include "ppc_ops.inc"
870870#include "ppc_ops.h"
871871
872872/* Initialization and shutdown */
trunk/src/emu/cpu/powerpc/ppc_ops.inc
r0r28740
1/* PowerPC common opcodes */
2
3// it really seems like this should be elsewhere - like maybe the floating point checks can hang out someplace else
4#include <math.h>
5
6#ifndef PPC_DRC
7static void ppc_unimplemented(UINT32 op)
8{
9   fatalerror("ppc: Unimplemented opcode %08X at %08X\n", op, ppc.pc);
10}
11
12static void ppc_addx(UINT32 op)
13{
14   UINT32 ra = REG(RA);
15   UINT32 rb = REG(RB);
16
17   REG(RT) = ra + rb;
18
19   if( OEBIT ) {
20      SET_ADD_OV(REG(RT), ra, rb);
21   }
22   if( RCBIT ) {
23      SET_CR0(REG(RT));
24   }
25}
26
27static void ppc_addcx(UINT32 op)
28{
29   UINT32 ra = REG(RA);
30   UINT32 rb = REG(RB);
31
32   REG(RT) = ra + rb;
33
34   SET_ADD_CA(REG(RT), ra, rb);
35
36   if( OEBIT ) {
37      SET_ADD_OV(REG(RT), ra, rb);
38   }
39   if( RCBIT ) {
40      SET_CR0(REG(RT));
41   }
42}
43#endif
44
45static void ppc_addex(UINT32 op)
46{
47   UINT32 ra = REG(RA);
48   UINT32 rb = REG(RB);
49   UINT32 carry = (XER >> 29) & 0x1;
50   UINT32 tmp;
51
52   tmp = rb + carry;
53   REG(RT) = ra + tmp;
54
55   if( ADD_CA(tmp, rb, carry) || ADD_CA(REG(RT), ra, tmp) )
56      XER |= XER_CA;
57   else
58      XER &= ~XER_CA;
59
60   if( OEBIT ) {
61      SET_ADD_OV(REG(RT), ra, rb);
62   }
63   if( RCBIT ) {
64      SET_CR0(REG(RT));
65   }
66}
67
68#ifndef PPC_DRC
69static void ppc_addi(UINT32 op)
70{
71   UINT32 i = SIMM16;
72   UINT32 a = RA;
73
74   if( a )
75      i += REG(a);
76
77   REG(RT) = i;
78}
79
80static void ppc_addic(UINT32 op)
81{
82   UINT32 i = SIMM16;
83   UINT32 ra = REG(RA);
84
85   REG(RT) = ra + i;
86
87   if( ADD_CA(REG(RT), ra, i) )
88      XER |= XER_CA;
89   else
90      XER &= ~XER_CA;
91}
92
93static void ppc_addic_rc(UINT32 op)
94{
95   UINT32 i = SIMM16;
96   UINT32 ra = REG(RA);
97
98   REG(RT) = ra + i;
99
100   if( ADD_CA(REG(RT), ra, i) )
101      XER |= XER_CA;
102   else
103      XER &= ~XER_CA;
104
105   SET_CR0(REG(RT));
106}
107
108static void ppc_addis(UINT32 op)
109{
110   UINT32 i = UIMM16 << 16;
111   UINT32 a = RA;
112
113   if( a )
114      i += REG(a);
115
116   REG(RT) = i;
117}
118#endif
119
120static void ppc_addmex(UINT32 op)
121{
122   UINT32 ra = REG(RA);
123   UINT32 carry = (XER >> 29) & 0x1;
124   UINT32 tmp;
125
126   tmp = ra + carry;
127   REG(RT) = tmp + -1;
128
129   if( ADD_CA(tmp, ra, carry) || ADD_CA(REG(RT), tmp, -1) )
130      XER |= XER_CA;
131   else
132      XER &= ~XER_CA;
133
134   if( OEBIT ) {
135      SET_ADD_OV(REG(RT), ra, carry - 1);
136   }
137   if( RCBIT ) {
138      SET_CR0(REG(RT));
139   }
140}
141
142static void ppc_addzex(UINT32 op)
143{
144   UINT32 ra = REG(RA);
145   UINT32 carry = (XER >> 29) & 0x1;
146
147   REG(RT) = ra + carry;
148
149   if( ADD_CA(REG(RT), ra, carry) )
150      XER |= XER_CA;
151   else
152      XER &= ~XER_CA;
153
154   if( OEBIT ) {
155      SET_ADD_OV(REG(RT), ra, carry);
156   }
157   if( RCBIT ) {
158      SET_CR0(REG(RT));
159   }
160}
161
162#ifndef PPC_DRC
163static void ppc_andx(UINT32 op)
164{
165   REG(RA) = REG(RS) & REG(RB);
166
167   if( RCBIT ) {
168      SET_CR0(REG(RA));
169   }
170}
171
172static void ppc_andcx(UINT32 op)
173{
174   REG(RA) = REG(RS) & ~REG(RB);
175
176   if( RCBIT ) {
177      SET_CR0(REG(RA));
178   }
179}
180
181static void ppc_andi_rc(UINT32 op)
182{
183   UINT32 i = UIMM16;
184
185   REG(RA) = REG(RS) & i;
186
187   SET_CR0(REG(RA));
188}
189
190static void ppc_andis_rc(UINT32 op)
191{
192   UINT32 i = UIMM16 << 16;
193
194   REG(RA) = REG(RS) & i;
195
196   SET_CR0(REG(RA));
197}
198
199static void ppc_bx(UINT32 op)
200{
201   INT32 li = op & 0x3fffffc;
202   if( li & 0x2000000 )
203      li |= 0xfc000000;
204
205   if( AABIT ) {
206      ppc.npc = li;
207   } else {
208      ppc.npc = ppc.pc + li;
209   }
210
211   if( LKBIT ) {
212      LR = ppc.pc + 4;
213   }
214}
215
216static void ppc_bcx(UINT32 op)
217{
218   int condition = check_condition_code(BO, BI);
219
220   if( condition ) {
221      if( AABIT ) {
222         ppc.npc = SIMM16 & ~0x3;
223      } else {
224         ppc.npc = ppc.pc + (SIMM16 & ~0x3);
225      }
226   }
227
228   if( LKBIT ) {
229      LR = ppc.pc + 4;
230   }
231}
232
233static void ppc_bcctrx(UINT32 op)
234{
235   int condition = check_condition_code(BO, BI);
236
237   if( condition ) {
238      ppc.npc = CTR & ~0x3;
239   }
240
241   if( LKBIT ) {
242      LR = ppc.pc + 4;
243   }
244}
245
246static void ppc_bclrx(UINT32 op)
247{
248   int condition = check_condition_code(BO, BI);
249
250   if( condition ) {
251      ppc.npc = LR & ~0x3;
252   }
253
254   if( LKBIT ) {
255      LR = ppc.pc + 4;
256   }
257}
258
259static void ppc_cmp(UINT32 op)
260{
261   INT32 ra = REG(RA);
262   INT32 rb = REG(RB);
263   int d = CRFD;
264
265   if( ra < rb )
266      CR(d) = 0x8;
267   else if( ra > rb )
268      CR(d) = 0x4;
269   else
270      CR(d) = 0x2;
271
272   if( XER & XER_SO )
273      CR(d) |= 0x1;
274}
275
276static void ppc_cmpi(UINT32 op)
277{
278   INT32 ra = REG(RA);
279   INT32 i = SIMM16;
280   int d = CRFD;
281
282   if( ra < i )
283      CR(d) = 0x8;
284   else if( ra > i )
285      CR(d) = 0x4;
286   else
287      CR(d) = 0x2;
288
289   if( XER & XER_SO )
290      CR(d) |= 0x1;
291}
292
293static void ppc_cmpl(UINT32 op)
294{
295   UINT32 ra = REG(RA);
296   UINT32 rb = REG(RB);
297   int d = CRFD;
298
299   if( ra < rb )
300      CR(d) = 0x8;
301   else if( ra > rb )
302      CR(d) = 0x4;
303   else
304      CR(d) = 0x2;
305
306   if( XER & XER_SO )
307      CR(d) |= 0x1;
308}
309
310static void ppc_cmpli(UINT32 op)
311{
312   UINT32 ra = REG(RA);
313   UINT32 i = UIMM16;
314   int d = CRFD;
315
316   if( ra < i )
317      CR(d) = 0x8;
318   else if( ra > i )
319      CR(d) = 0x4;
320   else
321      CR(d) = 0x2;
322
323   if( XER & XER_SO )
324      CR(d) |= 0x1;
325}
326
327static void ppc_cntlzw(UINT32 op)
328{
329   int n = 0;
330   int t = RT;
331   UINT32 m = 0x80000000;
332
333   while(n < 32)
334   {
335      if( REG(t) & m )
336         break;
337      m >>= 1;
338      n++;
339   }
340
341   REG(RA) = n;
342
343   if( RCBIT ) {
344      SET_CR0(REG(RA));
345   }
346}
347#endif
348
349static void ppc_crand(UINT32 op)
350{
351   int bit = RT;
352   int b = CRBIT(RA) & CRBIT(RB);
353   if( b & 0x1 )
354      CR(bit / 4) |= _BIT(3-(bit % 4));
355   else
356      CR(bit / 4) &= ~_BIT(3-(bit % 4));
357}
358
359static void ppc_crandc(UINT32 op)
360{
361   int bit = RT;
362   int b = CRBIT(RA) & ~CRBIT(RB);
363   if( b & 0x1 )
364      CR(bit / 4) |= _BIT(3-(bit % 4));
365   else
366      CR(bit / 4) &= ~_BIT(3-(bit % 4));
367}
368
369static void ppc_creqv(UINT32 op)
370{
371   int bit = RT;
372   int b = ~(CRBIT(RA) ^ CRBIT(RB));
373   if( b & 0x1 )
374      CR(bit / 4) |= _BIT(3-(bit % 4));
375   else
376      CR(bit / 4) &= ~_BIT(3-(bit % 4));
377}
378
379static void ppc_crnand(UINT32 op)
380{
381   int bit = RT;
382   int b = ~(CRBIT(RA) & CRBIT(RB));
383   if( b & 0x1 )
384      CR(bit / 4) |= _BIT(3-(bit % 4));
385   else
386      CR(bit / 4) &= ~_BIT(3-(bit % 4));
387}
388
389static void ppc_crnor(UINT32 op)
390{
391   int bit = RT;
392   int b = ~(CRBIT(RA) | CRBIT(RB));
393   if( b & 0x1 )
394      CR(bit / 4) |= _BIT(3-(bit % 4));
395   else
396      CR(bit / 4) &= ~_BIT(3-(bit % 4));
397}
398
399static void ppc_cror(UINT32 op)
400{
401   int bit = RT;
402   int b = CRBIT(RA) | CRBIT(RB);
403   if( b & 0x1 )
404      CR(bit / 4) |= _BIT(3-(bit % 4));
405   else
406      CR(bit / 4) &= ~_BIT(3-(bit % 4));
407}
408
409static void ppc_crorc(UINT32 op)
410{
411   int bit = RT;
412   int b = CRBIT(RA) | ~CRBIT(RB);
413   if( b & 0x1 )
414      CR(bit / 4) |= _BIT(3-(bit % 4));
415   else
416      CR(bit / 4) &= ~_BIT(3-(bit % 4));
417}
418
419static void ppc_crxor(UINT32 op)
420{
421   int bit = RT;
422   int b = CRBIT(RA) ^ CRBIT(RB);
423   if( b & 0x1 )
424      CR(bit / 4) |= _BIT(3-(bit % 4));
425   else
426      CR(bit / 4) &= ~_BIT(3-(bit % 4));
427}
428
429#ifndef PPC_DRC
430static void ppc_dcbf(UINT32 op)
431{
432}
433
434static void ppc_dcbi(UINT32 op)
435{
436}
437
438static void ppc_dcbst(UINT32 op)
439{
440}
441
442static void ppc_dcbt(UINT32 op)
443{
444}
445
446static void ppc_dcbtst(UINT32 op)
447{
448}
449
450static void ppc_dcbz(UINT32 op)
451{
452}
453#endif
454
455static void ppc_divwx(UINT32 op)
456{
457   if( REG(RB) == 0 && REG(RA) < 0x80000000 )
458   {
459      REG(RT) = 0;
460      if( OEBIT ) {
461         XER |= XER_SO | XER_OV;
462      }
463   }
464   else if( REG(RB) == 0 || (REG(RB) == 0xffffffff && REG(RA) == 0x80000000) )
465   {
466      REG(RT) = 0xffffffff;
467      if( OEBIT ) {
468         XER |= XER_SO | XER_OV;
469      }
470   }
471   else
472   {
473      REG(RT) = (INT32)REG(RA) / (INT32)REG(RB);
474      if( OEBIT ) {
475         XER &= ~XER_OV;
476      }
477   }
478
479   if( RCBIT ) {
480      SET_CR0(REG(RT));
481   }
482}
483
484static void ppc_divwux(UINT32 op)
485{
486   if( REG(RB) == 0 )
487   {
488      REG(RT) = 0;
489      if( OEBIT ) {
490         XER |= XER_SO | XER_OV;
491      }
492   }
493   else
494   {
495      REG(RT) = (UINT32)REG(RA) / (UINT32)REG(RB);
496      if( OEBIT ) {
497         XER &= ~XER_OV;
498      }
499   }
500
501   if( RCBIT ) {
502      SET_CR0(REG(RT));
503   }
504}
505
506#ifndef PPC_DRC
507static void ppc_eieio(UINT32 op)
508{
509}
510
511static void ppc_eqvx(UINT32 op)
512{
513   REG(RA) = ~(REG(RS) ^ REG(RB));
514
515   if( RCBIT ) {
516      SET_CR0(REG(RA));
517   }
518}
519
520static void ppc_extsbx(UINT32 op)
521{
522   REG(RA) = (INT32)(INT8)REG(RS);
523
524   if( RCBIT ) {
525      SET_CR0(REG(RA));
526   }
527}
528
529static void ppc_extshx(UINT32 op)
530{
531   REG(RA) = (INT32)(INT16)REG(RS);
532
533   if( RCBIT ) {
534      SET_CR0(REG(RA));
535   }
536}
537
538static void ppc_icbi(UINT32 op)
539{
540}
541
542static void ppc_isync(UINT32 op)
543{
544}
545
546static void ppc_lbz(UINT32 op)
547{
548   UINT32 ea;
549
550   if( RA == 0 )
551      ea = SIMM16;
552   else
553      ea = REG(RA) + SIMM16;
554
555   REG(RT) = (UINT32)READ8(ea);
556}
557
558static void ppc_lbzu(UINT32 op)
559{
560   UINT32 ea = REG(RA) + SIMM16;
561
562   REG(RT) = (UINT32)READ8(ea);
563   REG(RA) = ea;
564}
565
566static void ppc_lbzux(UINT32 op)
567{
568   UINT32 ea = REG(RA) + REG(RB);
569
570   REG(RT) = (UINT32)READ8(ea);
571   REG(RA) = ea;
572}
573
574static void ppc_lbzx(UINT32 op)
575{
576   UINT32 ea;
577
578   if( RA == 0 )
579      ea = REG(RB);
580   else
581      ea = REG(RA) + REG(RB);
582
583   REG(RT) = (UINT32)READ8(ea);
584}
585
586static void ppc_lha(UINT32 op)
587{
588   UINT32 ea;
589
590   if( RA == 0 )
591      ea = SIMM16;
592   else
593      ea = REG(RA) + SIMM16;
594
595   REG(RT) = (INT32)(INT16)READ16(ea);
596}
597
598static void ppc_lhau(UINT32 op)
599{
600   UINT32 ea = REG(RA) + SIMM16;
601
602   REG(RT) = (INT32)(INT16)READ16(ea);
603   REG(RA) = ea;
604}
605
606static void ppc_lhaux(UINT32 op)
607{
608   UINT32 ea = REG(RA) + REG(RB);
609
610   REG(RT) = (INT32)(INT16)READ16(ea);
611   REG(RA) = ea;
612}
613
614static void ppc_lhax(UINT32 op)
615{
616   UINT32 ea;
617
618   if( RA == 0 )
619      ea = REG(RB);
620   else
621      ea = REG(RA) + REG(RB);
622
623   REG(RT) = (INT32)(INT16)READ16(ea);
624}
625
626static void ppc_lhbrx(UINT32 op)
627{
628   UINT32 ea;
629   UINT16 w;
630
631   if( RA == 0 )
632      ea = REG(RB);
633   else
634      ea = REG(RA) + REG(RB);
635
636   w = READ16(ea);
637   REG(RT) = (UINT32)BYTE_REVERSE16(w);
638}
639
640static void ppc_lhz(UINT32 op)
641{
642   UINT32 ea;
643
644   if( RA == 0 )
645      ea = SIMM16;
646   else
647      ea = REG(RA) + SIMM16;
648
649   REG(RT) = (UINT32)READ16(ea);
650}
651
652static void ppc_lhzu(UINT32 op)
653{
654   UINT32 ea = REG(RA) + SIMM16;
655
656   REG(RT) = (UINT32)READ16(ea);
657   REG(RA) = ea;
658}
659
660static void ppc_lhzux(UINT32 op)
661{
662   UINT32 ea = REG(RA) + REG(RB);
663
664   REG(RT) = (UINT32)READ16(ea);
665   REG(RA) = ea;
666}
667
668static void ppc_lhzx(UINT32 op)
669{
670   UINT32 ea;
671
672   if( RA == 0 )
673      ea = REG(RB);
674   else
675      ea = REG(RA) + REG(RB);
676
677   REG(RT) = (UINT32)READ16(ea);
678}
679#endif
680
681static void ppc_lmw(UINT32 op)
682{
683   int r = RT;
684   UINT32 ea;
685
686   if( RA == 0 )
687      ea = SIMM16;
688   else
689      ea = REG(RA) + SIMM16;
690
691   while( r <= 31 )
692   {
693      REG(r) = READ32(ea);
694      ea += 4;
695      r++;
696   }
697}
698
699static void ppc_lswi(UINT32 op)
700{
701   int n, r, i;
702   UINT32 ea = 0;
703   if( RA != 0 )
704      ea = REG(RA);
705
706   if( RB == 0 )
707      n = 32;
708   else
709      n = RB;
710
711   r = RT - 1;
712   i = 0;
713
714   while(n > 0)
715   {
716      if (i == 0) {
717         r = (r + 1) % 32;
718         REG(r) = 0;
719      }
720      REG(r) |= ((READ8(ea) & 0xff) << (24 - i));
721      i += 8;
722      if (i == 32) {
723         i = 0;
724      }
725      ea++;
726      n--;
727   }
728}
729
730static void ppc_lswx(UINT32 op)
731{
732   int n, r, i;
733   UINT32 ea = 0;
734   if( RA != 0 )
735      ea = REG(RA);
736
737   ea += REG(RB);
738
739   n = ppc.xer & 0x7f;
740
741   r = RT - 1;
742   i = 0;
743
744   while(n > 0)
745   {
746      if (i == 0) {
747         r = (r + 1) % 32;
748         REG(r) = 0;
749      }
750      REG(r) |= ((READ8(ea) & 0xff) << (24 - i));
751      i += 8;
752      if (i == 32) {
753         i = 0;
754      }
755      ea++;
756      n--;
757   }
758}
759
760static void ppc_lwarx(UINT32 op)
761{
762   UINT32 ea;
763
764   if( RA == 0 )
765      ea = REG(RB);
766   else
767      ea = REG(RA) + REG(RB);
768
769   ppc.reserved_address = ea;
770   ppc.reserved = 1;
771
772   REG(RT) = READ32(ea);
773}
774
775#ifndef PPC_DRC
776static void ppc_lwbrx(UINT32 op)
777{
778   UINT32 ea;
779   UINT32 w;
780
781   if( RA == 0 )
782      ea = REG(RB);
783   else
784      ea = REG(RA) + REG(RB);
785
786   w = READ32(ea);
787   REG(RT) = BYTE_REVERSE32(w);
788}
789
790static void ppc_lwz(UINT32 op)
791{
792   UINT32 ea;
793
794   if( RA == 0 )
795      ea = SIMM16;
796   else
797      ea = REG(RA) + SIMM16;
798
799   REG(RT) = READ32(ea);
800}
801
802static void ppc_lwzu(UINT32 op)
803{
804   UINT32 ea = REG(RA) + SIMM16;
805
806   REG(RT) = READ32(ea);
807   REG(RA) = ea;
808}
809
810static void ppc_lwzux(UINT32 op)
811{
812   UINT32 ea = REG(RA) + REG(RB);
813
814   REG(RT) = READ32(ea);
815   REG(RA) = ea;
816}
817
818static void ppc_lwzx(UINT32 op)
819{
820   UINT32 ea;
821
822   if( RA == 0 )
823      ea = REG(RB);
824   else
825      ea = REG(RA) + REG(RB);
826
827   REG(RT) = READ32(ea);
828}
829
830static void ppc_mcrf(UINT32 op)
831{
832   CR(RT >> 2) = CR(RA >> 2);
833}
834
835static void ppc_mcrxr(UINT32 op)
836{
837   CR(RT >> 2) = (XER >> 28) & 0x0F;
838   XER &= ~0xf0000000;
839}
840
841static void ppc_mfcr(UINT32 op)
842{
843   REG(RT) = ppc_get_cr();
844}
845
846static void ppc_mfmsr(UINT32 op)
847{
848   REG(RT) = ppc_get_msr();
849}
850
851static void ppc_mfspr(UINT32 op)
852{
853   REG(RT) = ppc_get_spr(SPR);
854}
855#endif
856
857static void ppc_mtcrf(UINT32 op)
858{
859   int fxm = FXM;
860   int t = RT;
861
862   if( fxm & 0x80 )    CR(0) = (REG(t) >> 28) & 0xf;
863   if( fxm & 0x40 )    CR(1) = (REG(t) >> 24) & 0xf;
864   if( fxm & 0x20 )    CR(2) = (REG(t) >> 20) & 0xf;
865   if( fxm & 0x10 )    CR(3) = (REG(t) >> 16) & 0xf;
866   if( fxm & 0x08 )    CR(4) = (REG(t) >> 12) & 0xf;
867   if( fxm & 0x04 )    CR(5) = (REG(t) >> 8) & 0xf;
868   if( fxm & 0x02 )    CR(6) = (REG(t) >> 4) & 0xf;
869   if( fxm & 0x01 )    CR(7) = (REG(t) >> 0) & 0xf;
870}
871
872#ifndef PPC_DRC
873static void ppc_mtmsr(UINT32 op)
874{
875   ppc_set_msr(REG(RS));
876}
877
878static void ppc_mtspr(UINT32 op)
879{
880   ppc_set_spr(SPR, REG(RS));
881}
882
883static void ppc_mulhwx(UINT32 op)
884{
885   INT64 ra = (INT64)(INT32)REG(RA);
886   INT64 rb = (INT64)(INT32)REG(RB);
887
888   REG(RT) = (UINT32)((ra * rb) >> 32);
889
890   if( RCBIT ) {
891      SET_CR0(REG(RT));
892   }
893}
894
895static void ppc_mulhwux(UINT32 op)
896{
897   UINT64 ra = (UINT64)REG(RA);
898   UINT64 rb = (UINT64)REG(RB);
899
900   REG(RT) = (UINT32)((ra * rb) >> 32);
901
902   if( RCBIT ) {
903      SET_CR0(REG(RT));
904   }
905}
906
907static void ppc_mulli(UINT32 op)
908{
909   INT32 ra = (INT32)REG(RA);
910   INT32 i = SIMM16;
911
912   REG(RT) = ra * i;
913}
914
915static void ppc_mullwx(UINT32 op)
916{
917   INT64 ra = (INT64)(INT32)REG(RA);
918   INT64 rb = (INT64)(INT32)REG(RB);
919   INT64 r;
920
921   r = ra * rb;
922   REG(RT) = (UINT32)r;
923
924   if( OEBIT ) {
925      XER &= ~XER_OV;
926
927      if( r != (INT64)(INT32)r )
928         XER |= XER_OV | XER_SO;
929   }
930
931   if( RCBIT ) {
932      SET_CR0(REG(RT));
933   }
934}
935
936static void ppc_nandx(UINT32 op)
937{
938   REG(RA) = ~(REG(RS) & REG(RB));
939
940   if( RCBIT ) {
941      SET_CR0(REG(RA));
942   }
943}
944
945static void ppc_negx(UINT32 op)
946{
947   REG(RT) = -REG(RA);
948
949   if( OEBIT ) {
950      if( REG(RT) == 0x80000000 )
951         XER |= XER_OV | XER_SO;
952      else
953         XER &= ~XER_OV;
954   }
955
956   if( RCBIT ) {
957      SET_CR0(REG(RT));
958   }
959}
960
961static void ppc_norx(UINT32 op)
962{
963   REG(RA) = ~(REG(RS) | REG(RB));
964
965   if( RCBIT ) {
966      SET_CR0(REG(RA));
967   }
968}
969
970static void ppc_orx(UINT32 op)
971{
972   REG(RA) = REG(RS) | REG(RB);
973
974   if( RCBIT ) {
975      SET_CR0(REG(RA));
976   }
977}
978
979static void ppc_orcx(UINT32 op)
980{
981   REG(RA) = REG(RS) | ~REG(RB);
982
983   if( RCBIT ) {
984      SET_CR0(REG(RA));
985   }
986}
987
988static void ppc_ori(UINT32 op)
989{
990   REG(RA) = REG(RS) | UIMM16;
991}
992
993static void ppc_oris(UINT32 op)
994{
995   REG(RA) = REG(RS) | (UIMM16 << 16);
996}
997
998static void ppc_rfi(UINT32 op)
999{
1000   UINT32 msr;
1001   ppc.npc = ppc_get_spr(SPR_SRR0);
1002   msr = ppc_get_spr(SPR_SRR1);
1003   ppc_set_msr( msr );
1004}
1005
1006static void ppc_rlwimix(UINT32 op)
1007{
1008   UINT32 r;
1009   UINT32 mask = GET_ROTATE_MASK(MB, ME);
1010   UINT32 rs = REG(RS);
1011   int sh = SH;
1012
1013   r = (rs << sh) | (rs >> (32-sh));
1014   REG(RA) = (REG(RA) & ~mask) | (r & mask);
1015
1016   if( RCBIT ) {
1017      SET_CR0(REG(RA));
1018   }
1019}
1020
1021static void ppc_rlwinmx(UINT32 op)
1022{
1023   UINT32 r;
1024   UINT32 mask = GET_ROTATE_MASK(MB, ME);
1025   UINT32 rs = REG(RS);
1026   int sh = SH;
1027
1028   r = (rs << sh) | (rs >> (32-sh));
1029   REG(RA) = r & mask;
1030
1031   if( RCBIT ) {
1032      SET_CR0(REG(RA));
1033   }
1034}
1035
1036static void ppc_rlwnmx(UINT32 op)
1037{
1038   UINT32 r;
1039   UINT32 mask = GET_ROTATE_MASK(MB, ME);
1040   UINT32 rs = REG(RS);
1041   int sh = REG(RB) & 0x1f;
1042
1043   r = (rs << sh) | (rs >> (32-sh));
1044   REG(RA) = r & mask;
1045
1046   if( RCBIT ) {
1047      SET_CR0(REG(RA));
1048   }
1049}
1050#endif
1051
1052#ifndef PPC_DRC
1053static void ppc_sc(UINT32 op)
1054{
1055   if (ppc.is603) {
1056      ppc603_exception(EXCEPTION_SYSTEM_CALL);
1057   }
1058   if (ppc.is602) {
1059      ppc602_exception(EXCEPTION_SYSTEM_CALL);
1060   }
1061   if (IS_PPC403()) {
1062      ppc403_exception(EXCEPTION_SYSTEM_CALL);
1063   }
1064}
1065#endif
1066
1067static void ppc_slwx(UINT32 op)
1068{
1069   int sh = REG(RB) & 0x3f;
1070
1071   if( sh > 31 ) {
1072      REG(RA) = 0;
1073   }
1074   else {
1075      REG(RA) = REG(RS) << sh;
1076   }
1077
1078   if( RCBIT ) {
1079      SET_CR0(REG(RA));
1080   }
1081}
1082
1083static void ppc_srawx(UINT32 op)
1084{
1085   int sh = REG(RB) & 0x3f;
1086
1087   XER &= ~XER_CA;
1088
1089   if( sh > 31 ) {
1090      if (REG(RS) & 0x80000000)
1091         REG(RA) = 0xffffffff;
1092      else
1093         REG(RA) = 0;
1094      if( REG(RA) )
1095         XER |= XER_CA;
1096   }
1097   else {
1098      REG(RA) = (INT32)(REG(RS)) >> sh;
1099      if( ((INT32)(REG(RS)) < 0) && (REG(RS) & BITMASK_0(sh)) )
1100         XER |= XER_CA;
1101   }
1102
1103   if( RCBIT ) {
1104      SET_CR0(REG(RA));
1105   }
1106}
1107
1108static void ppc_srawix(UINT32 op)
1109{
1110   int sh = SH;
1111
1112   XER &= ~XER_CA;
1113   if( ((INT32)(REG(RS)) < 0) && (REG(RS) & BITMASK_0(sh)) )
1114      XER |= XER_CA;
1115
1116   REG(RA) = (INT32)(REG(RS)) >> sh;
1117
1118   if( RCBIT ) {
1119      SET_CR0(REG(RA));
1120   }
1121}
1122
1123static void ppc_srwx(UINT32 op)
1124{
1125   int sh = REG(RB) & 0x3f;
1126
1127   if( sh > 31 ) {
1128      REG(RA) = 0;
1129   }
1130   else {
1131      REG(RA) = REG(RS) >> sh;
1132   }
1133
1134   if( RCBIT ) {
1135      SET_CR0(REG(RA));
1136   }
1137}
1138
1139#ifndef PPC_DRC
1140static void ppc_stb(UINT32 op)
1141{
1142   UINT32 ea;
1143
1144   if( RA == 0 )
1145      ea = SIMM16;
1146   else
1147      ea = REG(RA) + SIMM16;
1148
1149   WRITE8(ea, (UINT8)REG(RS));
1150}
1151
1152static void ppc_stbu(UINT32 op)
1153{
1154   UINT32 ea = REG(RA) + SIMM16;
1155
1156   WRITE8(ea, (UINT8)REG(RS));
1157   REG(RA) = ea;
1158}
1159
1160static void ppc_stbux(UINT32 op)
1161{
1162   UINT32 ea = REG(RA) + REG(RB);
1163
1164   WRITE8(ea, (UINT8)REG(RS));
1165   REG(RA) = ea;
1166}
1167
1168static void ppc_stbx(UINT32 op)
1169{
1170   UINT32 ea;
1171
1172   if( RA == 0 )
1173      ea = REG(RB);
1174   else
1175      ea = REG(RA) + REG(RB);
1176
1177   WRITE8(ea, (UINT8)REG(RS));
1178}
1179
1180static void ppc_sth(UINT32 op)
1181{
1182   UINT32 ea;
1183
1184   if( RA == 0 )
1185      ea = SIMM16;
1186   else
1187      ea = REG(RA) + SIMM16;
1188
1189   WRITE16(ea, (UINT16)REG(RS));
1190}
1191
1192static void ppc_sthbrx(UINT32 op)
1193{
1194   UINT32 ea;
1195   UINT16 w;
1196
1197   if( RA == 0 )
1198      ea = REG(RB);
1199   else
1200      ea = REG(RA) + REG(RB);
1201
1202   w = REG(RS);
1203   WRITE16(ea, (UINT16)BYTE_REVERSE16(w));
1204}
1205
1206static void ppc_sthu(UINT32 op)
1207{
1208   UINT32 ea = REG(RA) + SIMM16;
1209
1210   WRITE16(ea, (UINT16)REG(RS));
1211   REG(RA) = ea;
1212}
1213
1214static void ppc_sthux(UINT32 op)
1215{
1216   UINT32 ea = REG(RA) + REG(RB);
1217
1218   WRITE16(ea, (UINT16)REG(RS));
1219   REG(RA) = ea;
1220}
1221
1222static void ppc_sthx(UINT32 op)
1223{
1224   UINT32 ea;
1225
1226   if( RA == 0 )
1227      ea = REG(RB);
1228   else
1229      ea = REG(RA) + REG(RB);
1230
1231   WRITE16(ea, (UINT16)REG(RS));
1232}
1233#endif
1234
1235static void ppc_stmw(UINT32 op)
1236{
1237   UINT32 ea;
1238   int r = RS;
1239
1240   if( RA == 0 )
1241      ea = SIMM16;
1242   else
1243      ea = REG(RA) + SIMM16;
1244
1245   while( r <= 31 )
1246   {
1247      WRITE32(ea, REG(r));
1248      ea += 4;
1249      r++;
1250   }
1251}
1252
1253static void ppc_stswi(UINT32 op)
1254{
1255   int n, r, i;
1256   UINT32 ea = 0;
1257   if( RA != 0 )
1258      ea = REG(RA);
1259
1260   if( RB == 0 )
1261      n = 32;
1262   else
1263      n = RB;
1264
1265   r = RT - 1;
1266   i = 0;
1267
1268   while(n > 0)
1269   {
1270      if (i == 0) {
1271         r = (r + 1) % 32;
1272      }
1273      WRITE8(ea, (REG(r) >> (24-i)) & 0xff);
1274      i += 8;
1275      if (i == 32) {
1276         i = 0;
1277      }
1278      ea++;
1279      n--;
1280   }
1281}
1282
1283static void ppc_stswx(UINT32 op)
1284{
1285   int n, r, i;
1286   UINT32 ea = 0;
1287   if( RA != 0 )
1288      ea = REG(RA);
1289
1290   ea += REG(RB);
1291
1292   n = ppc.xer & 0x7f;
1293
1294   r = RT - 1;
1295   i = 0;
1296
1297   while(n > 0)
1298   {
1299      if (i == 0) {
1300         r = (r + 1) % 32;
1301      }
1302      WRITE8(ea, (REG(r) >> (24-i)) & 0xff);
1303      i += 8;
1304      if (i == 32) {
1305         i = 0;
1306      }
1307      ea++;
1308      n--;
1309   }
1310}
1311
1312#ifndef PPC_DRC
1313static void ppc_stw(UINT32 op)
1314{
1315   UINT32 ea;
1316
1317   if( RA == 0 )
1318      ea = SIMM16;
1319   else
1320      ea = REG(RA) + SIMM16;
1321
1322   WRITE32(ea, REG(RS));
1323}
1324
1325static void ppc_stwbrx(UINT32 op)
1326{
1327   UINT32 ea;
1328   UINT32 w;
1329
1330   if( RA == 0 )
1331      ea = REG(RB);
1332   else
1333      ea = REG(RA) + REG(RB);
1334
1335   w = REG(RS);
1336   WRITE32(ea, BYTE_REVERSE32(w));
1337}
1338#endif
1339
1340static void ppc_stwcx_rc(UINT32 op)
1341{
1342   UINT32 ea;
1343
1344   if( RA == 0 )
1345      ea = REG(RB);
1346   else
1347      ea = REG(RA) + REG(RB);
1348
1349   if( ppc.reserved ) {
1350      WRITE32(ea, REG(RS));
1351
1352      ppc.reserved = 0;
1353      ppc.reserved_address = 0;
1354
1355      CR(0) = 0x2;
1356      if( XER & XER_SO )
1357         CR(0) |= 0x1;
1358   } else {
1359      CR(0) = 0;
1360      if( XER & XER_SO )
1361         CR(0) |= 0x1;
1362   }
1363}
1364
1365#ifndef PPC_DRC
1366static void ppc_stwu(UINT32 op)
1367{
1368   UINT32 ea = REG(RA) + SIMM16;
1369
1370   WRITE32(ea, REG(RS));
1371   REG(RA) = ea;
1372}
1373
1374static void ppc_stwux(UINT32 op)
1375{
1376   UINT32 ea = REG(RA) + REG(RB);
1377
1378   WRITE32(ea, REG(RS));
1379   REG(RA) = ea;
1380}
1381
1382static void ppc_stwx(UINT32 op)
1383{
1384   UINT32 ea;
1385
1386   if( RA == 0 )
1387      ea = REG(RB);
1388   else
1389      ea = REG(RA) + REG(RB);
1390
1391   WRITE32(ea, REG(RS));
1392}
1393
1394static void ppc_subfx(UINT32 op)
1395{
1396   UINT32 ra = REG(RA);
1397   UINT32 rb = REG(RB);
1398   REG(RT) = rb - ra;
1399
1400   if( OEBIT ) {
1401      SET_SUB_OV(REG(RT), rb, ra);
1402   }
1403   if( RCBIT ) {
1404      SET_CR0(REG(RT));
1405   }
1406}
1407#endif
1408
1409static void ppc_subfcx(UINT32 op)
1410{
1411   UINT32 ra = REG(RA);
1412   UINT32 rb = REG(RB);
1413   REG(RT) = rb - ra;
1414
1415   SET_SUB_CA(REG(RT), rb, ra);
1416
1417   if( OEBIT ) {
1418      SET_SUB_OV(REG(RT), rb, ra);
1419   }
1420   if( RCBIT ) {
1421      SET_CR0(REG(RT));
1422   }
1423}
1424
1425#ifndef PPC_DRC
1426static void ppc_subfex(UINT32 op)
1427{
1428   UINT32 ra = REG(RA);
1429   UINT32 rb = REG(RB);
1430   UINT32 carry = (XER >> 29) & 0x1;
1431   UINT32 r;
1432
1433   r = ~ra + carry;
1434   REG(RT) = rb + r;
1435
1436   SET_ADD_CA(r, ~ra, carry);      /* step 1 carry */
1437   if( REG(RT) < r )               /* step 2 carry */
1438      XER |= XER_CA;
1439
1440   if( OEBIT ) {
1441      SET_SUB_OV(REG(RT), rb, ra);
1442   }
1443   if( RCBIT ) {
1444      SET_CR0(REG(RT));
1445   }
1446}
1447
1448static void ppc_subfic(UINT32 op)
1449{
1450   UINT32 i = SIMM16;
1451   UINT32 ra = REG(RA);
1452
1453   REG(RT) = i - ra;
1454
1455   SET_SUB_CA(REG(RT), i, ra);
1456}
1457#endif
1458
1459static void ppc_subfmex(UINT32 op)
1460{
1461   UINT32 ra = REG(RA);
1462   UINT32 carry = (XER >> 29) & 0x1;
1463   UINT32 r;
1464
1465   r = ~ra + carry;
1466   REG(RT) = r - 1;
1467
1468   SET_SUB_CA(r, ~ra, carry);      /* step 1 carry */
1469   if( REG(RT) < r )
1470      XER |= XER_CA;              /* step 2 carry */
1471
1472   if( OEBIT ) {
1473      SET_SUB_OV(REG(RT), -1, ra);
1474   }
1475   if( RCBIT ) {
1476      SET_CR0(REG(RT));
1477   }
1478}
1479
1480static void ppc_subfzex(UINT32 op)
1481{
1482   UINT32 ra = REG(RA);
1483   UINT32 carry = (XER >> 29) & 0x1;
1484
1485   REG(RT) = ~ra + carry;
1486
1487   SET_ADD_CA(REG(RT), ~ra, carry);
1488
1489   if( OEBIT ) {
1490      SET_SUB_OV(REG(RT), 0, REG(RA));
1491   }
1492   if( RCBIT ) {
1493      SET_CR0(REG(RT));
1494   }
1495}
1496
1497#ifndef PPC_DRC
1498static void ppc_sync(UINT32 op)
1499{
1500}
1501#endif
1502
1503#ifndef PPC_DRC
1504static void ppc_tw(UINT32 op)
1505{
1506   int exception = 0;
1507   INT32 a = REG(RA);
1508   INT32 b = REG(RB);
1509   int to = RT;
1510
1511   if( (a < b) && (to & 0x10) ) {
1512      exception = 1;
1513   }
1514   if( (a > b) && (to & 0x08) ) {
1515      exception = 1;
1516   }
1517   if( (a == b) && (to & 0x04) ) {
1518      exception = 1;
1519   }
1520   if( ((UINT32)a < (UINT32)b) && (to & 0x02) ) {
1521      exception = 1;
1522   }
1523   if( ((UINT32)a > (UINT32)b) && (to & 0x01) ) {
1524      exception = 1;
1525   }
1526
1527   if (exception) {
1528      if (ppc.is603) {
1529         ppc603_exception(EXCEPTION_TRAP);
1530      }
1531      if (ppc.is602) {
1532         ppc602_exception(EXCEPTION_TRAP);
1533      }
1534      if (IS_PPC403()) {
1535         ppc403_exception(EXCEPTION_TRAP);
1536      }
1537   }
1538}
1539#endif
1540
1541#ifndef PPC_DRC
1542static void ppc_twi(UINT32 op)
1543{
1544   int exception = 0;
1545   INT32 a = REG(RA);
1546   INT32 i = SIMM16;
1547   int to = RT;
1548
1549   if( (a < i) && (to & 0x10) ) {
1550      exception = 1;
1551   }
1552   if( (a > i) && (to & 0x08) ) {
1553      exception = 1;
1554   }
1555   if( (a == i) && (to & 0x04) ) {
1556      exception = 1;
1557   }
1558   if( ((UINT32)a < (UINT32)i) && (to & 0x02) ) {
1559      exception = 1;
1560   }
1561   if( ((UINT32)a > (UINT32)i) && (to & 0x01) ) {
1562      exception = 1;
1563   }
1564
1565   if (exception) {
1566      if (ppc.is603) {
1567         ppc603_exception(EXCEPTION_TRAP);
1568      }
1569      if (ppc.is602) {
1570         ppc602_exception(EXCEPTION_TRAP);
1571      }
1572      if (IS_PPC403()) {
1573         ppc403_exception(EXCEPTION_TRAP);
1574      }
1575   }
1576}
1577#endif
1578
1579#ifndef PPC_DRC
1580static void ppc_xorx(UINT32 op)
1581{
1582   REG(RA) = REG(RS) ^ REG(RB);
1583
1584   if( RCBIT ) {
1585      SET_CR0(REG(RA));
1586   }
1587}
1588
1589static void ppc_xori(UINT32 op)
1590{
1591   REG(RA) = REG(RS) ^ UIMM16;
1592}
1593
1594static void ppc_xoris(UINT32 op)
1595{
1596   REG(RA) = REG(RS) ^ (UIMM16 << 16);
1597}
1598
1599
1600
1601static void ppc_invalid(UINT32 op)
1602{
1603   fatalerror("ppc: Invalid opcode %08X PC : %X\n", op, ppc.pc);
1604}
1605#endif
1606
1607
1608// Everything below is new from AJG
1609
1610////////////////////////////
1611// !here are the 6xx ops! //
1612////////////////////////////
1613
1614#define DOUBLE_SIGN     (U64(0x8000000000000000))
1615#define DOUBLE_EXP      (U64(0x7ff0000000000000))
1616#define DOUBLE_FRAC     (U64(0x000fffffffffffff))
1617#define DOUBLE_ZERO     (0)
1618
1619/*
1620  Floating point operations.
1621*/
1622
1623INLINE int is_nan_double(FPR x)
1624{
1625   return( ((x.id & DOUBLE_EXP) == DOUBLE_EXP) &&
1626         ((x.id & DOUBLE_FRAC) != DOUBLE_ZERO) );
1627}
1628
1629INLINE int is_qnan_double(FPR x)
1630{
1631   return( ((x.id & DOUBLE_EXP) == DOUBLE_EXP) &&
1632         ((x.id & U64(0x0007fffffffffff)) == U64(0x000000000000000)) &&
1633         ((x.id & U64(0x000800000000000)) == U64(0x000800000000000)) );
1634}
1635
1636INLINE int is_snan_double(FPR x)
1637{
1638   return( ((x.id & DOUBLE_EXP) == DOUBLE_EXP) &&
1639         ((x.id & DOUBLE_FRAC) != DOUBLE_ZERO) &&
1640         ((x.id & U64(0x0008000000000000)) == DOUBLE_ZERO) );
1641}
1642
1643INLINE int is_infinity_double(FPR x)
1644{
1645   return( ((x.id & DOUBLE_EXP) == DOUBLE_EXP) &&
1646         ((x.id & DOUBLE_FRAC) == DOUBLE_ZERO) );
1647}
1648
1649INLINE int is_normalized_double(FPR x)
1650{
1651   UINT64 exp;
1652
1653   exp = (x.id & DOUBLE_EXP) >> 52;
1654
1655   return (exp >= 1) && (exp <= 2046);
1656}
1657
1658INLINE int is_denormalized_double(FPR x)
1659{
1660   return( ((x.id & DOUBLE_EXP) == 0) &&
1661         ((x.id & DOUBLE_FRAC) != DOUBLE_ZERO) );
1662}
1663
1664INLINE int sign_double(FPR x)
1665{
1666   return ((x.id & DOUBLE_SIGN) != 0);
1667}
1668
1669INLINE INT64 round_to_nearest(FPR f)
1670{
1671   if (f.fd >= 0)
1672   {
1673      return (INT64)(f.fd + 0.5);
1674   }
1675   else
1676   {
1677      return -(INT64)(-f.fd + 0.5);
1678   }
1679}
1680
1681INLINE INT64 round_toward_zero(FPR f)
1682{
1683   return (INT64)(f.fd);
1684}
1685
1686INLINE INT64 round_toward_positive_infinity(FPR f)
1687{
1688   double r = ceil(f.fd);
1689   return (INT64)(r);
1690}
1691
1692INLINE INT64 round_toward_negative_infinity(FPR f)
1693{
1694   double r = floor(f.fd);
1695   return (INT64)(r);
1696}
1697
1698
1699INLINE void set_fprf(FPR f)
1700{
1701   UINT32 fprf;
1702
1703   // see page 3-30, 3-31
1704
1705   if (is_qnan_double(f))
1706   {
1707      fprf = 0x11;
1708   }
1709   else if (is_infinity_double(f))
1710   {
1711      if (sign_double(f))     // -INF
1712         fprf = 0x09;
1713      else                    // +INF
1714         fprf = 0x05;
1715   }
1716   else if (is_normalized_double(f))
1717   {
1718      if (sign_double(f))     // -Normalized
1719         fprf = 0x08;
1720      else                    // +Normalized
1721         fprf = 0x04;
1722   }
1723   else if (is_denormalized_double(f))
1724   {
1725      if (sign_double(f))     // -Denormalized
1726         fprf = 0x18;
1727      else                    // +Denormalized
1728         fprf = 0x14;
1729   }
1730   else    // Zero
1731   {
1732      if (sign_double(f))     // -Zero
1733         fprf = 0x12;
1734      else                    // +Zero
1735         fprf = 0x02;
1736   }
1737
1738   ppc.fpscr &= ~0x0001f000;
1739   ppc.fpscr |= (fprf << 12);
1740}
1741
1742
1743
1744#define SET_VXSNAN(a, b)    if (is_snan_double(a) || is_snan_double(b)) ppc.fpscr |= 0x80000000
1745#define SET_VXSNAN_1(c)     if (is_snan_double(c)) ppc.fpscr |= 0x80000000
1746
1747
1748
1749
1750static void ppc_lfs(UINT32 op)
1751{
1752   UINT32 ea = SIMM16;
1753   UINT32 a = RA;
1754   UINT32 t = RT;
1755   FPR32 f;
1756
1757   if(a)
1758      ea += REG(a);
1759
1760   f.i = READ32(ea);
1761   FPR(t).fd = (double)(f.f);
1762}
1763
1764static void ppc_lfsu(UINT32 op)
1765{
1766   UINT32 ea = SIMM16;
1767   UINT32 a = RA;
1768   UINT32 t = RT;
1769   FPR32 f;
1770
1771   ea += REG(a);
1772
1773   f.i = READ32(ea);
1774   FPR(t).fd = (double)(f.f);
1775
1776   REG(a) = ea;
1777}
1778
1779#ifndef PPC_DRC
1780static void ppc_lfd(UINT32 op)
1781{
1782   UINT32 ea = SIMM16;
1783   UINT32 a = RA;
1784   UINT32 t = RT;
1785
1786   if(a)
1787      ea += REG(a);
1788
1789   FPR(t).id = READ64(ea);
1790}
1791
1792static void ppc_lfdu(UINT32 op)
1793{
1794   UINT32 ea = SIMM16;
1795   UINT32 a = RA;
1796   UINT32 d = RD;
1797
1798   ea += REG(a);
1799
1800   FPR(d).id = READ64(ea);
1801
1802   REG(a) = ea;
1803}
1804#endif
1805
1806static void ppc_stfs(UINT32 op)
1807{
1808   UINT32 ea = SIMM16;
1809   UINT32 a = RA;
1810   UINT32 t = RT;
1811   FPR32 f;
1812
1813   if(a)
1814      ea += REG(a);
1815
1816   f.f = (float)(FPR(t).fd);
1817   WRITE32(ea, f.i);
1818}
1819
1820static void ppc_stfsu(UINT32 op)
1821{
1822   UINT32 ea = SIMM16;
1823   UINT32 a = RA;
1824   UINT32 t = RT;
1825   FPR32 f;
1826
1827   ea += REG(a);
1828
1829   f.f = (float)(FPR(t).fd);
1830   WRITE32(ea, f.i);
1831
1832   REG(a) = ea;
1833}
1834
1835#ifndef PPC_DRC
1836static void ppc_stfd(UINT32 op)
1837{
1838   UINT32 ea = SIMM16;
1839   UINT32 a = RA;
1840   UINT32 t = RT;
1841
1842   if(a)
1843      ea += REG(a);
1844
1845   WRITE64(ea, FPR(t).id);
1846}
1847
1848static void ppc_stfdu(UINT32 op)
1849{
1850   UINT32 ea = SIMM16;
1851   UINT32 a = RA;
1852   UINT32 t = RT;
1853
1854   ea += REG(a);
1855
1856   WRITE64(ea, FPR(t).id);
1857
1858   REG(a) = ea;
1859}
1860
1861static void ppc_lfdux(UINT32 op)
1862{
1863   UINT32 ea = REG(RB);
1864   UINT32 a = RA;
1865   UINT32 d = RD;
1866
1867   ea += REG(a);
1868
1869   FPR(d).id = READ64(ea);
1870
1871   REG(a) = ea;
1872}
1873
1874static void ppc_lfdx(UINT32 op)
1875{
1876   UINT32 ea = REG(RB);
1877   UINT32 a = RA;
1878   UINT32 d = RD;
1879
1880   if(a)
1881      ea += REG(a);
1882
1883   FPR(d).id = READ64(ea);
1884}
1885#endif
1886
1887static void ppc_lfsux(UINT32 op)
1888{
1889   UINT32 ea = REG(RB);
1890   UINT32 a = RA;
1891   UINT32 t = RT;
1892   FPR32 f;
1893
1894   ea += REG(a);
1895
1896   f.i = READ32(ea);
1897   FPR(t).fd = (double)(f.f);
1898
1899   REG(a) = ea;
1900}
1901
1902static void ppc_lfsx(UINT32 op)
1903{
1904   UINT32 ea = REG(RB);
1905   UINT32 a = RA;
1906   UINT32 t = RT;
1907   FPR32 f;
1908
1909   if(a)
1910      ea += REG(a);
1911
1912   f.i = READ32(ea);
1913   FPR(t).fd = (double)(f.f);
1914}
1915
1916static void ppc_mfsr(UINT32 op)
1917{
1918   UINT32 sr = (op >> 16) & 15;
1919   UINT32 t = RT;
1920
1921   CHECK_SUPERVISOR();
1922
1923   REG(t) = ppc.sr[sr];
1924}
1925
1926static void ppc_mfsrin(UINT32 op)
1927{
1928   UINT32 b = RB;
1929   UINT32 t = RT;
1930
1931   CHECK_SUPERVISOR();
1932
1933   REG(t) = ppc.sr[REG(b) >> 28];
1934}
1935
1936static void ppc_mftb(UINT32 op)
1937{
1938   UINT32 x = SPRF;
1939
1940   switch(x)
1941   {
1942      case 268:   REG(RT) = (UINT32)(ppc_read_timebase()); break;
1943      case 269:   REG(RT) = (UINT32)(ppc_read_timebase() >> 32); break;
1944      default:    fatalerror("ppc: Invalid timebase register %d at %08X\n", x, ppc.pc); break;
1945   }
1946}
1947
1948static void ppc_mtsr(UINT32 op)
1949{
1950   UINT32 sr = (op >> 16) & 15;
1951   UINT32 t = RT;
1952
1953   CHECK_SUPERVISOR();
1954
1955   ppc.sr[sr] = REG(t);
1956}
1957
1958static void ppc_mtsrin(UINT32 op)
1959{
1960   UINT32 b = RB;
1961   UINT32 t = RT;
1962
1963   CHECK_SUPERVISOR();
1964
1965   ppc.sr[REG(b) >> 28] = REG(t);
1966}
1967
1968#ifndef PPC_DRC
1969static void ppc_dcba(UINT32 op)
1970{
1971   /* TODO: Cache not emulated so this opcode doesn't need to be implemented */
1972}
1973
1974static void ppc_stfdux(UINT32 op)
1975{
1976   UINT32 ea = REG(RB);
1977   UINT32 a = RA;
1978   UINT32 t = RT;
1979
1980   ea += REG(a);
1981
1982   WRITE64(ea, FPR(t).id);
1983
1984   REG(a) = ea;
1985}
1986#endif
1987
1988static void ppc_stfdx(UINT32 op)
1989{
1990   UINT32 ea = REG(RB);
1991   UINT32 a = RA;
1992   UINT32 t = RT;
1993
1994   if(a)
1995      ea += REG(a);
1996
1997   WRITE64(ea, FPR(t).id);
1998}
1999
2000static void ppc_stfiwx(UINT32 op)
2001{
2002   UINT32 ea = REG(RB);
2003   UINT32 a = RA;
2004   UINT32 t = RT;
2005
2006   if(a)
2007      ea += REG(a);
2008
2009   WRITE32(ea, (UINT32)FPR(t).id);
2010}
2011
2012static void ppc_stfsux(UINT32 op)
2013{
2014   UINT32 ea = REG(RB);
2015   UINT32 a = RA;
2016   UINT32 t = RT;
2017   FPR32 f;
2018
2019   ea += REG(a);
2020
2021   f.f = (float)(FPR(t).fd);
2022   WRITE32(ea, f.i);
2023
2024   REG(a) = ea;
2025}
2026
2027static void ppc_stfsx(UINT32 op)
2028{
2029   UINT32 ea = REG(RB);
2030   UINT32 a = RA;
2031   UINT32 t = RT;
2032   FPR32 f;
2033
2034   if(a)
2035      ea += REG(a);
2036
2037   f.f = (float)(FPR(t).fd);
2038
2039   WRITE32(ea, f.i);
2040}
2041
2042#ifndef PPC_DRC
2043static void ppc_tlbia(UINT32 op)
2044{
2045   /* TODO: TLB not emulated so this opcode doesn't need to implemented */
2046}
2047
2048static void ppc_tlbie(UINT32 op)
2049{
2050   /* TODO: TLB not emulated so this opcode doesn't need to implemented */
2051}
2052
2053static void ppc_tlbsync(UINT32 op)
2054{
2055   /* TODO: TLB not emulated so this opcode doesn't need to implemented */
2056}
2057
2058static void ppc_eciwx(UINT32 op)
2059{
2060   ppc_unimplemented(op);
2061}
2062
2063static void ppc_ecowx(UINT32 op)
2064{
2065   ppc_unimplemented(op);
2066}
2067#endif
2068
2069static void ppc_fabsx(UINT32 op)
2070{
2071   UINT32 b = RB;
2072   UINT32 t = RT;
2073
2074   CHECK_FPU_AVAILABLE();
2075
2076   FPR(t).id = FPR(b).id & ~DOUBLE_SIGN;
2077
2078   if( RCBIT ) {
2079      SET_CR1();
2080   }
2081}
2082
2083static void ppc_faddx(UINT32 op)
2084{
2085   UINT32 b = RB;
2086   UINT32 a = RA;
2087   UINT32 t = RT;
2088
2089   CHECK_FPU_AVAILABLE();
2090
2091   SET_VXSNAN(FPR(a), FPR(b));
2092
2093   FPR(t).fd = FPR(a).fd + FPR(b).fd;
2094
2095   set_fprf(FPR(t));
2096   if( RCBIT ) {
2097      SET_CR1();
2098   }
2099}
2100
2101static void ppc_fcmpo(UINT32 op)
2102{
2103   UINT32 b = RB;
2104   UINT32 a = RA;
2105   UINT32 t = (RT >> 2);
2106   UINT32 c;
2107
2108   CHECK_FPU_AVAILABLE();
2109
2110   SET_VXSNAN(FPR(a), FPR(b));
2111
2112   if(is_nan_double(FPR(a)) || is_nan_double(FPR(b)))
2113   {
2114      c = 1; /* OX */
2115      if(is_snan_double(FPR(a)) || is_snan_double(FPR(b))) {
2116         ppc.fpscr |= 0x01000000; /* VXSNAN */
2117
2118         if(!(ppc.fpscr & 0x40000000) || is_qnan_double(FPR(a)) || is_qnan_double(FPR(b)))
2119            ppc.fpscr |= 0x00080000; /* VXVC */
2120      }
2121   }
2122   else if(FPR(a).fd < FPR(b).fd){
2123      c = 8; /* FX */
2124   }
2125   else if(FPR(a).fd > FPR(b).fd){
2126      c = 4; /* FEX */
2127   }
2128   else {
2129      c = 2; /* VX */
2130   }
2131
2132   CR(t) = c;
2133
2134   ppc.fpscr &= ~0x0001F000;
2135   ppc.fpscr |= (c << 12);
2136}
2137
2138static void ppc_fcmpu(UINT32 op)
2139{
2140   UINT32 b = RB;
2141   UINT32 a = RA;
2142   UINT32 t = (RT >> 2);
2143   UINT32 c;
2144
2145   CHECK_FPU_AVAILABLE();
2146
2147   SET_VXSNAN(FPR(a), FPR(b));
2148
2149   if(is_nan_double(FPR(a)) || is_nan_double(FPR(b)))
2150   {
2151      c = 1; /* OX */
2152      if(is_snan_double(FPR(a)) || is_snan_double(FPR(b))) {
2153         ppc.fpscr |= 0x01000000; /* VXSNAN */
2154      }
2155   }
2156   else if(FPR(a).fd < FPR(b).fd){
2157      c = 8; /* FX */
2158   }
2159   else if(FPR(a).fd > FPR(b).fd){
2160      c = 4; /* FEX */
2161   }
2162   else {
2163      c = 2; /* VX */
2164   }
2165
2166   CR(t) = c;
2167
2168   ppc.fpscr &= ~0x0001F000;
2169   ppc.fpscr |= (c << 12);
2170}
2171
2172static void ppc_fctiwx(UINT32 op)
2173{
2174   UINT32 b = RB;
2175   UINT32 t = RT;
2176   INT64 r = 0;
2177
2178   // TODO: fix FPSCR flags FX,VXSNAN,VXCVI
2179
2180   CHECK_FPU_AVAILABLE();
2181
2182   SET_VXSNAN_1(FPR(b));
2183
2184   switch(ppc.fpscr & 3)
2185   {
2186      case 0: r = (INT64)round_to_nearest(FPR(b)); break;
2187      case 1: r = (INT64)round_toward_zero(FPR(b)); break;
2188      case 2: r = (INT64)round_toward_positive_infinity(FPR(b)); break;
2189      case 3: r = (INT64)round_toward_negative_infinity(FPR(b)); break;
2190   }
2191
2192   if(r > (INT64)((INT32)0x7FFFFFFF))
2193   {
2194      FPR(t).id = 0x7FFFFFFF;
2195      // FPSCR[FR] = 0
2196      // FPSCR[FI] = 1
2197      // FPSCR[XX] = 1
2198   }
2199   else if(FPR(b).fd < (INT64)((INT32)0x80000000))
2200   {
2201      FPR(t).id = 0x80000000;
2202      // FPSCR[FR] = 1
2203      // FPSCR[FI] = 1
2204      // FPSCR[XX] = 1
2205   }
2206   else
2207   {
2208      FPR(t).id = (UINT32)r;
2209      // FPSCR[FR] = t.iw > t.fd
2210      // FPSCR[FI] = t.iw == t.fd
2211      // FPSCR[XX] = ?
2212   }
2213
2214   // FPSCR[FPRF] = undefined (leave it as is)
2215   if( RCBIT ) {
2216      SET_CR1();
2217   }
2218}
2219
2220static void ppc_fctiwzx(UINT32 op)
2221{
2222   UINT32 b = RB;
2223   UINT32 t = RT;
2224   INT64 r;
2225
2226   // TODO: fix FPSCR flags FX,VXSNAN,VXCVI
2227
2228   CHECK_FPU_AVAILABLE();
2229
2230   SET_VXSNAN_1(FPR(b));
2231   r = round_toward_zero(FPR(b));
2232
2233   if(r > (INT64)((INT32)0x7fffffff))
2234   {
2235      FPR(t).id = 0x7fffffff;
2236      // FPSCR[FR] = 0
2237      // FPSCR[FI] = 1
2238      // FPSCR[XX] = 1
2239
2240   }
2241   else if(r < (INT64)((INT32)0x80000000))
2242   {
2243      FPR(t).id = 0x80000000;
2244      // FPSCR[FR] = 1
2245      // FPSCR[FI] = 1
2246      // FPSCR[XX] = 1
2247   }
2248   else
2249   {
2250      FPR(t).id = (UINT32)r;
2251      // FPSCR[FR] = t.iw > t.fd
2252      // FPSCR[FI] = t.iw == t.fd
2253      // FPSCR[XX] = ?
2254   }
2255
2256   // FPSCR[FPRF] = undefined (leave it as is)
2257   if( RCBIT ) {
2258      SET_CR1();
2259   }
2260}
2261
2262static void ppc_fdivx(UINT32 op)
2263{
2264   UINT32 b = RB;
2265   UINT32 a = RA;
2266   UINT32 t = RT;
2267
2268   CHECK_FPU_AVAILABLE();
2269
2270   SET_VXSNAN(FPR(a), FPR(b));
2271
2272   FPR(t).fd = FPR(a).fd / FPR(b).fd;
2273
2274   set_fprf(FPR(t));
2275   if( RCBIT ) {
2276      SET_CR1();
2277   }
2278}
2279
2280static void ppc_fmrx(UINT32 op)
2281{
2282   UINT32 b = RB;
2283   UINT32 t = RT;
2284
2285   CHECK_FPU_AVAILABLE();
2286
2287   FPR(t).fd = FPR(b).fd;
2288
2289   if( RCBIT ) {
2290      SET_CR1();
2291   }
2292}
2293
2294static void ppc_fnabsx(UINT32 op)
2295{
2296   UINT32 b = RB;
2297   UINT32 t = RT;
2298
2299   CHECK_FPU_AVAILABLE();
2300
2301   FPR(t).id = FPR(b).id | DOUBLE_SIGN;
2302
2303   if( RCBIT ) {
2304      SET_CR1();
2305   }
2306}
2307
2308static void ppc_fnegx(UINT32 op)
2309{
2310   UINT32 b = RB;
2311   UINT32 t = RT;
2312
2313   CHECK_FPU_AVAILABLE();
2314
2315   FPR(t).id = FPR(b).id ^ DOUBLE_SIGN;
2316
2317   if( RCBIT ) {
2318      SET_CR1();
2319   }
2320}
2321
2322static void ppc_frspx(UINT32 op)
2323{
2324   UINT32 b = RB;
2325   UINT32 t = RT;
2326
2327   CHECK_FPU_AVAILABLE();
2328
2329   SET_VXSNAN_1(FPR(b));
2330
2331   FPR(t).fd = (float)FPR(b).fd;
2332
2333   set_fprf(FPR(t));
2334   if( RCBIT ) {
2335      SET_CR1();
2336   }
2337}
2338
2339static void ppc_frsqrtex(UINT32 op)
2340{
2341   UINT32 b = RB;
2342   UINT32 t = RT;
2343
2344   CHECK_FPU_AVAILABLE();
2345
2346   SET_VXSNAN_1(FPR(b));
2347
2348   FPR(t).fd = 1.0 / sqrt(FPR(b).fd);  /* verify this */
2349
2350   set_fprf(FPR(t));
2351   if( RCBIT ) {
2352      SET_CR1();
2353   }
2354}
2355
2356static void ppc_fsqrtx(UINT32 op)
2357{
2358   /* NOTE: PPC603e doesn't support this opcode */
2359   UINT32 b = RB;
2360   UINT32 t = RT;
2361
2362   CHECK_FPU_AVAILABLE();
2363
2364   SET_VXSNAN_1(FPR(b));
2365
2366   FPR(t).fd = (double)(sqrt(FPR(b).fd));
2367
2368   set_fprf(FPR(t));
2369   if( RCBIT ) {
2370      SET_CR1();
2371   }
2372}
2373
2374static void ppc_fsubx(UINT32 op)
2375{
2376   UINT32 b = RB;
2377   UINT32 a = RA;
2378   UINT32 t = RT;
2379
2380   CHECK_FPU_AVAILABLE();
2381
2382   SET_VXSNAN(FPR(a), FPR(b));
2383
2384   FPR(t).fd = FPR(a).fd - FPR(b).fd;
2385
2386   set_fprf(FPR(t));
2387   if( RCBIT ) {
2388      SET_CR1();
2389   }
2390}
2391
2392static void ppc_mffsx(UINT32 op)
2393{
2394   FPR(RT).id = (UINT32)ppc.fpscr;
2395
2396   if( RCBIT ) {
2397      SET_CR1();
2398   }
2399}
2400
2401static void ppc_mtfsb0x(UINT32 op)
2402{
2403   UINT32 crbD;
2404
2405   crbD = (op >> 21) & 0x1F;
2406
2407   if (crbD != 1 && crbD != 2) // these bits cannot be explicitly cleared
2408      ppc.fpscr &= ~(1 << (31 - crbD));
2409
2410   if( RCBIT ) {
2411      SET_CR1();
2412   }
2413}
2414
2415static void ppc_mtfsb1x(UINT32 op)
2416{
2417   UINT32 crbD;
2418
2419   crbD = (op >> 21) & 0x1F;
2420
2421   if (crbD != 1 && crbD != 2) // these bits cannot be explicitly cleared
2422      ppc.fpscr |= (1 << (31 - crbD));
2423
2424   if( RCBIT ) {
2425      SET_CR1();
2426   }
2427}
2428
2429static void ppc_mtfsfx(UINT32 op)
2430{
2431   UINT32 b = RB;
2432   UINT32 f = FM;
2433
2434   f = ppc_field_xlat[FM];
2435
2436   ppc.fpscr &= (~f) | ~(FPSCR_FEX | FPSCR_VX);
2437   ppc.fpscr |= (UINT32)(FPR(b).id) & ~(FPSCR_FEX | FPSCR_VX);
2438
2439   // FEX, VX
2440
2441   if( RCBIT ) {
2442      SET_CR1();
2443   }
2444}
2445
2446static void ppc_mtfsfix(UINT32 op)
2447{
2448   UINT32 crfd = CRFD;
2449   UINT32 imm = (op >> 12) & 0xF;
2450
2451   /*
2452    * According to the manual:
2453    *
2454    * If bits 0 and 3 of FPSCR are to be modified, they take the immediate
2455    * value specified. Bits 1 and 2 (FEX and VX) are set according to the
2456    * "usual rule" and not from IMM[1-2].
2457    *
2458    * The "usual rule" is not emulated, so these bits simply aren't modified
2459    * at all here.
2460    */
2461
2462   crfd = (7 - crfd) * 4;  // calculate LSB position of field
2463
2464   if (crfd == 28)         // field containing FEX and VX is special...
2465   {                       // bits 1 and 2 of FPSCR must not be altered
2466      ppc.fpscr &= 0x9fffffff;
2467      ppc.fpscr |= (imm & 0x9fffffff);
2468   }
2469
2470   ppc.fpscr &= ~(0xf << crfd);    // clear field
2471   ppc.fpscr |= (imm << crfd);     // insert new data
2472
2473   if( RCBIT ) {
2474      SET_CR1();
2475   }
2476}
2477
2478static void ppc_mcrfs(UINT32 op)
2479{
2480   UINT32 crfs, f;
2481   crfs = CRFA;
2482
2483   f = ppc.fpscr >> ((7 - crfs) * 4);  // get crfS field from FPSCR
2484   f &= 0xf;
2485
2486   switch(crfs)    // determine which exception bits to clear in FPSCR
2487   {
2488      case 0:     // FX, OX
2489         ppc.fpscr &= ~0x90000000;
2490         break;
2491      case 1:     // UX, ZX, XX, VXSNAN
2492         ppc.fpscr &= ~0x0f000000;
2493         break;
2494      case 2:     // VXISI, VXIDI, VXZDZ, VXIMZ
2495         ppc.fpscr &= ~0x00F00000;
2496         break;
2497      case 3:     // VXVC
2498         ppc.fpscr &= ~0x00080000;
2499         break;
2500      case 5:     // VXSOFT, VXSQRT, VXCVI
2501         ppc.fpscr &= ~0x00000e00;
2502         break;
2503      default:
2504         break;
2505   }
2506
2507   CR(CRFD) = f;
2508}
2509
2510static void ppc_faddsx(UINT32 op)
2511{
2512   UINT32 b = RB;
2513   UINT32 a = RA;
2514   UINT32 t = RT;
2515
2516   CHECK_FPU_AVAILABLE();
2517
2518   SET_VXSNAN(FPR(a), FPR(b));
2519
2520   FPR(t).fd = (float)(FPR(a).fd + FPR(b).fd);
2521
2522   set_fprf(FPR(t));
2523   if( RCBIT ) {
2524      SET_CR1();
2525   }
2526}
2527
2528static void ppc_fdivsx(UINT32 op)
2529{
2530   UINT32 b = RB;
2531   UINT32 a = RA;
2532   UINT32 t = RT;
2533
2534   CHECK_FPU_AVAILABLE();
2535
2536   SET_VXSNAN(FPR(a), FPR(b));
2537
2538   FPR(t).fd = (float)(FPR(a).fd / FPR(b).fd);
2539
2540   set_fprf(FPR(t));
2541   if( RCBIT ) {
2542      SET_CR1();
2543   }
2544}
2545
2546static void ppc_fresx(UINT32 op)
2547{
2548   UINT32 b = RB;
2549   UINT32 t = RT;
2550
2551   CHECK_FPU_AVAILABLE();
2552
2553   SET_VXSNAN_1(FPR(b));
2554
2555   FPR(t).fd = 1.0 / FPR(b).fd; /* ??? */
2556
2557   set_fprf(FPR(t));
2558   if( RCBIT ) {
2559      SET_CR1();
2560   }
2561}
2562
2563static void ppc_fsqrtsx(UINT32 op)
2564{
2565   /* NOTE: This opcode is not supported in PPC603e */
2566   UINT32 b = RB;
2567   UINT32 t = RT;
2568
2569   CHECK_FPU_AVAILABLE();
2570
2571   SET_VXSNAN_1(FPR(b));
2572
2573   FPR(t).fd = (float)(sqrt(FPR(b).fd));
2574
2575   set_fprf(FPR(t));
2576   if( RCBIT ) {
2577      SET_CR1();
2578   }
2579}
2580
2581static void ppc_fsubsx(UINT32 op)
2582{
2583   UINT32 b = RB;
2584   UINT32 a = RA;
2585   UINT32 t = RT;
2586
2587   CHECK_FPU_AVAILABLE();
2588
2589   SET_VXSNAN(FPR(a), FPR(b));
2590
2591   FPR(t).fd = (float)(FPR(a).fd - FPR(b).fd);
2592
2593   set_fprf(FPR(t));
2594   if( RCBIT ) {
2595      SET_CR1();
2596   }
2597}
2598
2599static void ppc_fmaddx(UINT32 op)
2600{
2601   UINT32 c = RC;
2602   UINT32 b = RB;
2603   UINT32 a = RA;
2604   UINT32 t = RT;
2605
2606   CHECK_FPU_AVAILABLE();
2607
2608   SET_VXSNAN(FPR(a), FPR(b));
2609   SET_VXSNAN_1(FPR(c));
2610
2611   FPR(t).fd = ((FPR(a).fd * FPR(c).fd) + FPR(b).fd);
2612
2613   set_fprf(FPR(t));
2614   if( RCBIT ) {
2615      SET_CR1();
2616   }
2617}
2618
2619static void ppc_fmsubx(UINT32 op)
2620{
2621   UINT32 c = RC;
2622   UINT32 b = RB;
2623   UINT32 a = RA;
2624   UINT32 t = RT;
2625
2626   CHECK_FPU_AVAILABLE();
2627
2628   SET_VXSNAN(FPR(a), FPR(b));
2629   SET_VXSNAN_1(FPR(c));
2630
2631   FPR(t).fd = ((FPR(a).fd * FPR(c).fd) - FPR(b).fd);
2632
2633   set_fprf(FPR(t));
2634   if( RCBIT ) {
2635      SET_CR1();
2636   }
2637}
2638
2639static void ppc_fmulx(UINT32 op)
2640{
2641   UINT32 c = RC;
2642   UINT32 a = RA;
2643   UINT32 t = RT;
2644
2645   CHECK_FPU_AVAILABLE();
2646
2647   SET_VXSNAN(FPR(a), FPR(c));
2648
2649   FPR(t).fd = (FPR(a).fd * FPR(c).fd);
2650
2651   set_fprf(FPR(t));
2652   if( RCBIT ) {
2653      SET_CR1();
2654   }
2655}
2656
2657static void ppc_fnmaddx(UINT32 op)
2658{
2659   UINT32 c = RC;
2660   UINT32 b = RB;
2661   UINT32 a = RA;
2662   UINT32 t = RT;
2663
2664   CHECK_FPU_AVAILABLE();
2665
2666   SET_VXSNAN(FPR(a), FPR(b));
2667   SET_VXSNAN_1(FPR(c));
2668
2669   FPR(t).fd = (-((FPR(a).fd * FPR(c).fd) + FPR(b).fd));
2670
2671   set_fprf(FPR(t));
2672   if( RCBIT ) {
2673      SET_CR1();
2674   }
2675}
2676
2677static void ppc_fnmsubx(UINT32 op)
2678{
2679   UINT32 c = RC;
2680   UINT32 b = RB;
2681   UINT32 a = RA;
2682   UINT32 t = RT;
2683
2684   CHECK_FPU_AVAILABLE();
2685
2686   SET_VXSNAN(FPR(a), FPR(b));
2687   SET_VXSNAN_1(FPR(c));
2688
2689   FPR(t).fd = (-((FPR(a).fd * FPR(c).fd) - FPR(b).fd));
2690
2691   set_fprf(FPR(t));
2692   if( RCBIT ) {
2693      SET_CR1();
2694   }
2695}
2696
2697static void ppc_fselx(UINT32 op)
2698{
2699   UINT32 c = RC;
2700   UINT32 b = RB;
2701   UINT32 a = RA;
2702   UINT32 t = RT;
2703
2704   CHECK_FPU_AVAILABLE();
2705
2706   FPR(t).fd = (FPR(a).fd >= 0.0) ? FPR(c).fd : FPR(b).fd;
2707
2708   if( RCBIT ) {
2709      SET_CR1();
2710   }
2711}
2712
2713static void ppc_fmaddsx(UINT32 op)
2714{
2715   UINT32 c = RC;
2716   UINT32 b = RB;
2717   UINT32 a = RA;
2718   UINT32 t = RT;
2719
2720   CHECK_FPU_AVAILABLE();
2721
2722   SET_VXSNAN(FPR(a), FPR(b));
2723   SET_VXSNAN_1(FPR(c));
2724
2725   FPR(t).fd = (float)((FPR(a).fd * FPR(c).fd) + FPR(b).fd);
2726
2727   set_fprf(FPR(t));
2728   if( RCBIT ) {
2729      SET_CR1();
2730   }
2731}
2732
2733static void ppc_fmsubsx(UINT32 op)
2734{
2735   UINT32 c = RC;
2736   UINT32 b = RB;
2737   UINT32 a = RA;
2738   UINT32 t = RT;
2739
2740   CHECK_FPU_AVAILABLE();
2741
2742   SET_VXSNAN(FPR(a), FPR(b));
2743   SET_VXSNAN_1(FPR(c));
2744
2745   FPR(t).fd = (float)((FPR(a).fd * FPR(c).fd) - FPR(b).fd);
2746
2747   set_fprf(FPR(t));
2748   if( RCBIT ) {
2749      SET_CR1();
2750   }
2751}
2752
2753static void ppc_fmulsx(UINT32 op)
2754{
2755   UINT32 c = RC;
2756   UINT32 a = RA;
2757   UINT32 t = RT;
2758
2759   CHECK_FPU_AVAILABLE();
2760   SET_VXSNAN(FPR(a), FPR(c));
2761
2762   FPR(t).fd = (float)(FPR(a).fd * FPR(c).fd);
2763
2764   set_fprf(FPR(t));
2765   if( RCBIT ) {
2766      SET_CR1();
2767   }
2768}
2769
2770static void ppc_fnmaddsx(UINT32 op)
2771{
2772   UINT32 c = RC;
2773   UINT32 b = RB;
2774   UINT32 a = RA;
2775   UINT32 t = RT;
2776
2777   CHECK_FPU_AVAILABLE();
2778
2779   SET_VXSNAN(FPR(a), FPR(b));
2780   SET_VXSNAN_1(FPR(c));
2781
2782   FPR(t).fd = (float)(-((FPR(a).fd * FPR(c).fd) + FPR(b).fd));
2783
2784   set_fprf(FPR(t));
2785   if( RCBIT ) {
2786      SET_CR1();
2787   }
2788}
2789
2790static void ppc_fnmsubsx(UINT32 op)
2791{
2792   UINT32 c = RC;
2793   UINT32 b = RB;
2794   UINT32 a = RA;
2795   UINT32 t = RT;
2796
2797   CHECK_FPU_AVAILABLE();
2798
2799   SET_VXSNAN(FPR(a), FPR(b));
2800   SET_VXSNAN_1(FPR(c));
2801
2802   FPR(t).fd = (float)(-((FPR(a).fd * FPR(c).fd) - FPR(b).fd));
2803
2804   set_fprf(FPR(t));
2805   if( RCBIT ) {
2806      SET_CR1();
2807   }
2808}
Property changes on: trunk/src/emu/cpu/powerpc/ppc_ops.inc
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Previous 199869 Revisions Next


© 1997-2024 The MAME Team