|
|
1.1 root 1: /*
2: * PowerPC emulation micro-operations for qemu.
3: *
4: * Copyright (c) 2003-2005 Jocelyn Mayer
5: *
6: * This library is free software; you can redistribute it and/or
7: * modify it under the terms of the GNU Lesser General Public
8: * License as published by the Free Software Foundation; either
9: * version 2 of the License, or (at your option) any later version.
10: *
11: * This library is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * Lesser General Public License for more details.
15: *
16: * You should have received a copy of the GNU Lesser General Public
17: * License along with this library; if not, write to the Free Software
18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19: */
20:
21: //#define DEBUG_OP
22:
23: #include "config.h"
24: #include "exec.h"
25:
26: #define regs (env)
27: #define Ts0 (int32_t)T0
28: #define Ts1 (int32_t)T1
29: #define Ts2 (int32_t)T2
30:
31: #define FT0 (env->ft0)
32: #define FT1 (env->ft1)
33: #define FT2 (env->ft2)
34:
35: #define PPC_OP(name) void glue(op_, name)(void)
36:
37: #define REG 0
38: #include "op_template.h"
39:
40: #define REG 1
41: #include "op_template.h"
42:
43: #define REG 2
44: #include "op_template.h"
45:
46: #define REG 3
47: #include "op_template.h"
48:
49: #define REG 4
50: #include "op_template.h"
51:
52: #define REG 5
53: #include "op_template.h"
54:
55: #define REG 6
56: #include "op_template.h"
57:
58: #define REG 7
59: #include "op_template.h"
60:
61: #define REG 8
62: #include "op_template.h"
63:
64: #define REG 9
65: #include "op_template.h"
66:
67: #define REG 10
68: #include "op_template.h"
69:
70: #define REG 11
71: #include "op_template.h"
72:
73: #define REG 12
74: #include "op_template.h"
75:
76: #define REG 13
77: #include "op_template.h"
78:
79: #define REG 14
80: #include "op_template.h"
81:
82: #define REG 15
83: #include "op_template.h"
84:
85: #define REG 16
86: #include "op_template.h"
87:
88: #define REG 17
89: #include "op_template.h"
90:
91: #define REG 18
92: #include "op_template.h"
93:
94: #define REG 19
95: #include "op_template.h"
96:
97: #define REG 20
98: #include "op_template.h"
99:
100: #define REG 21
101: #include "op_template.h"
102:
103: #define REG 22
104: #include "op_template.h"
105:
106: #define REG 23
107: #include "op_template.h"
108:
109: #define REG 24
110: #include "op_template.h"
111:
112: #define REG 25
113: #include "op_template.h"
114:
115: #define REG 26
116: #include "op_template.h"
117:
118: #define REG 27
119: #include "op_template.h"
120:
121: #define REG 28
122: #include "op_template.h"
123:
124: #define REG 29
125: #include "op_template.h"
126:
127: #define REG 30
128: #include "op_template.h"
129:
130: #define REG 31
131: #include "op_template.h"
132:
133: /* PowerPC state maintenance operations */
134: /* set_Rc0 */
135: PPC_OP(set_Rc0)
136: {
137: uint32_t tmp;
138:
139: if (Ts0 < 0) {
140: tmp = 0x08;
141: } else if (Ts0 > 0) {
142: tmp = 0x04;
143: } else {
144: tmp = 0x02;
145: }
146: tmp |= xer_ov;
147: env->crf[0] = tmp;
148: RETURN();
149: }
150:
151: /* reset_Rc0 */
152: PPC_OP(reset_Rc0)
153: {
154: env->crf[0] = 0x02 | xer_ov;
155: RETURN();
156: }
157:
158: /* set_Rc0_1 */
159: PPC_OP(set_Rc0_1)
160: {
161: env->crf[0] = 0x04 | xer_ov;
162: RETURN();
163: }
164:
165: /* Set Rc1 (for floating point arithmetic) */
166: PPC_OP(set_Rc1)
167: {
168: env->crf[1] = regs->fpscr[7];
169: RETURN();
170: }
171:
172: /* Constants load */
173: PPC_OP(set_T0)
174: {
175: T0 = PARAM(1);
176: RETURN();
177: }
178:
179: PPC_OP(set_T1)
180: {
181: T1 = PARAM(1);
182: RETURN();
183: }
184:
185: PPC_OP(set_T2)
186: {
187: T2 = PARAM(1);
188: RETURN();
189: }
190:
191: /* Generate exceptions */
192: PPC_OP(raise_exception_err)
193: {
194: do_raise_exception_err(PARAM(1), PARAM(2));
195: }
196:
197: PPC_OP(raise_exception)
198: {
199: do_raise_exception(PARAM(1));
200: }
201:
202: PPC_OP(update_nip)
203: {
204: env->nip = PARAM(1);
205: }
206:
1.1.1.3 ! root 207: PPC_OP(debug)
! 208: {
! 209: do_raise_exception(EXCP_DEBUG);
! 210: }
! 211:
1.1 root 212: /* Segment registers load and store with immediate index */
213: PPC_OP(load_srin)
214: {
215: T0 = regs->sr[T1 >> 28];
216: RETURN();
217: }
218:
219: PPC_OP(store_srin)
220: {
221: do_store_sr(env, ((uint32_t)T1 >> 28), T0);
222: RETURN();
223: }
224:
225: PPC_OP(load_sdr1)
226: {
227: T0 = regs->sdr1;
228: RETURN();
229: }
230:
231: PPC_OP(store_sdr1)
232: {
233: do_store_sdr1(env, T0);
234: RETURN();
235: }
236:
237: PPC_OP(exit_tb)
238: {
239: EXIT_TB();
240: }
241:
242: /* Load/store special registers */
243: PPC_OP(load_cr)
244: {
245: T0 = do_load_cr(env);
246: RETURN();
247: }
248:
249: PPC_OP(store_cr)
250: {
251: do_store_cr(env, T0, PARAM(1));
252: RETURN();
253: }
254:
255: PPC_OP(load_xer_cr)
256: {
257: T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
258: RETURN();
259: }
260:
261: PPC_OP(clear_xer_cr)
262: {
263: xer_so = 0;
264: xer_ov = 0;
265: xer_ca = 0;
266: RETURN();
267: }
268:
269: PPC_OP(load_xer_bc)
270: {
271: T1 = xer_bc;
272: RETURN();
273: }
274:
275: PPC_OP(load_xer)
276: {
277: T0 = do_load_xer(env);
278: RETURN();
279: }
280:
281: PPC_OP(store_xer)
282: {
283: do_store_xer(env, T0);
284: RETURN();
285: }
286:
287: PPC_OP(load_msr)
288: {
289: T0 = do_load_msr(env);
290: RETURN();
291: }
292:
293: PPC_OP(store_msr)
294: {
295: do_store_msr(env, T0);
296: RETURN();
297: }
298:
299: /* SPR */
300: PPC_OP(load_spr)
301: {
302: T0 = regs->spr[PARAM(1)];
303: RETURN();
304: }
305:
306: PPC_OP(store_spr)
307: {
308: regs->spr[PARAM(1)] = T0;
309: RETURN();
310: }
311:
312: PPC_OP(load_lr)
313: {
314: T0 = regs->lr;
315: RETURN();
316: }
317:
318: PPC_OP(store_lr)
319: {
320: regs->lr = T0;
321: RETURN();
322: }
323:
324: PPC_OP(load_ctr)
325: {
326: T0 = regs->ctr;
327: RETURN();
328: }
329:
330: PPC_OP(store_ctr)
331: {
332: regs->ctr = T0;
333: RETURN();
334: }
335:
336: PPC_OP(load_tbl)
337: {
338: T0 = cpu_ppc_load_tbl(regs);
339: RETURN();
340: }
341:
342: PPC_OP(load_tbu)
343: {
344: T0 = cpu_ppc_load_tbu(regs);
345: RETURN();
346: }
347:
348: PPC_OP(store_tbl)
349: {
350: cpu_ppc_store_tbl(regs, T0);
351: RETURN();
352: }
353:
354: PPC_OP(store_tbu)
355: {
356: cpu_ppc_store_tbu(regs, T0);
357: RETURN();
358: }
359:
360: PPC_OP(load_decr)
361: {
362: T0 = cpu_ppc_load_decr(regs);
363: }
364:
365: PPC_OP(store_decr)
366: {
367: cpu_ppc_store_decr(regs, T0);
368: RETURN();
369: }
370:
371: PPC_OP(load_ibat)
372: {
373: T0 = regs->IBAT[PARAM(1)][PARAM(2)];
374: }
375:
376: void op_store_ibatu (void)
377: {
378: do_store_ibatu(env, PARAM1, T0);
379: RETURN();
380: }
381:
382: void op_store_ibatl (void)
383: {
384: #if 1
385: env->IBAT[1][PARAM1] = T0;
386: #else
387: do_store_ibatl(env, PARAM1, T0);
388: #endif
389: RETURN();
390: }
391:
392: PPC_OP(load_dbat)
393: {
394: T0 = regs->DBAT[PARAM(1)][PARAM(2)];
395: }
396:
397: void op_store_dbatu (void)
398: {
399: do_store_dbatu(env, PARAM1, T0);
400: RETURN();
401: }
402:
403: void op_store_dbatl (void)
404: {
405: #if 1
406: env->DBAT[1][PARAM1] = T0;
407: #else
408: do_store_dbatl(env, PARAM1, T0);
409: #endif
410: RETURN();
411: }
412:
413: /* FPSCR */
414: PPC_OP(load_fpscr)
415: {
416: FT0 = do_load_fpscr(env);
417: RETURN();
418: }
419:
420: PPC_OP(store_fpscr)
421: {
422: do_store_fpscr(env, FT0, PARAM1);
423: RETURN();
424: }
425:
426: PPC_OP(reset_scrfx)
427: {
428: regs->fpscr[7] &= ~0x8;
429: RETURN();
430: }
431:
432: /* crf operations */
433: PPC_OP(getbit_T0)
434: {
435: T0 = (T0 >> PARAM(1)) & 1;
436: RETURN();
437: }
438:
439: PPC_OP(getbit_T1)
440: {
441: T1 = (T1 >> PARAM(1)) & 1;
442: RETURN();
443: }
444:
445: PPC_OP(setcrfbit)
446: {
447: T1 = (T1 & PARAM(1)) | (T0 << PARAM(2));
448: RETURN();
449: }
450:
451: /* Branch */
452: #define EIP regs->nip
453:
454: PPC_OP(setlr)
455: {
456: regs->lr = PARAM1;
457: }
458:
1.1.1.2 root 459: PPC_OP(goto_tb0)
1.1 root 460: {
1.1.1.2 root 461: GOTO_TB(op_goto_tb0, PARAM1, 0);
462: }
463:
464: PPC_OP(goto_tb1)
465: {
466: GOTO_TB(op_goto_tb1, PARAM1, 1);
1.1 root 467: }
468:
469: PPC_OP(b_T1)
470: {
471: regs->nip = T1 & ~3;
472: }
473:
1.1.1.2 root 474: PPC_OP(jz_T0)
1.1 root 475: {
1.1.1.2 root 476: if (!T0)
477: GOTO_LABEL_PARAM(1);
1.1 root 478: RETURN();
479: }
480:
481: PPC_OP(btest_T1)
482: {
483: if (T0) {
484: regs->nip = T1 & ~3;
485: } else {
486: regs->nip = PARAM1;
487: }
488: RETURN();
489: }
490:
491: PPC_OP(movl_T1_ctr)
492: {
493: T1 = regs->ctr;
494: }
495:
496: PPC_OP(movl_T1_lr)
497: {
498: T1 = regs->lr;
499: }
500:
501: /* tests with result in T0 */
502:
503: PPC_OP(test_ctr)
504: {
505: T0 = regs->ctr;
506: }
507:
508: PPC_OP(test_ctr_true)
509: {
510: T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0);
511: }
512:
513: PPC_OP(test_ctr_false)
514: {
515: T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0);
516: }
517:
518: PPC_OP(test_ctrz)
519: {
520: T0 = (regs->ctr == 0);
521: }
522:
523: PPC_OP(test_ctrz_true)
524: {
525: T0 = (regs->ctr == 0 && (T0 & PARAM(1)) != 0);
526: }
527:
528: PPC_OP(test_ctrz_false)
529: {
530: T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
531: }
532:
533: PPC_OP(test_true)
534: {
535: T0 = (T0 & PARAM(1));
536: }
537:
538: PPC_OP(test_false)
539: {
540: T0 = ((T0 & PARAM(1)) == 0);
541: }
542:
543: /* CTR maintenance */
544: PPC_OP(dec_ctr)
545: {
546: regs->ctr--;
547: RETURN();
548: }
549:
550: /*** Integer arithmetic ***/
551: /* add */
552: PPC_OP(add)
553: {
554: T0 += T1;
555: RETURN();
556: }
557:
558: void do_addo (void);
559: void op_addo (void)
560: {
561: do_addo();
562: RETURN();
563: }
564:
565: /* add carrying */
566: PPC_OP(addc)
567: {
568: T2 = T0;
569: T0 += T1;
570: if (T0 < T2) {
571: xer_ca = 1;
572: } else {
573: xer_ca = 0;
574: }
575: RETURN();
576: }
577:
578: void do_addco (void);
579: void op_addco (void)
580: {
581: do_addco();
582: RETURN();
583: }
584:
585: /* add extended */
586: void do_adde (void);
587: void op_adde (void)
588: {
589: do_adde();
590: }
591:
592: void do_addeo (void);
593: PPC_OP(addeo)
594: {
595: do_addeo();
596: RETURN();
597: }
598:
599: /* add immediate */
600: PPC_OP(addi)
601: {
602: T0 += PARAM(1);
603: RETURN();
604: }
605:
606: /* add immediate carrying */
607: PPC_OP(addic)
608: {
609: T1 = T0;
610: T0 += PARAM(1);
611: if (T0 < T1) {
612: xer_ca = 1;
613: } else {
614: xer_ca = 0;
615: }
616: RETURN();
617: }
618:
619: /* add to minus one extended */
620: PPC_OP(addme)
621: {
622: T1 = T0;
623: T0 += xer_ca + (-1);
624: if (T1 != 0)
625: xer_ca = 1;
626: RETURN();
627: }
628:
629: void do_addmeo (void);
630: void op_addmeo (void)
631: {
632: do_addmeo();
633: RETURN();
634: }
635:
636: /* add to zero extended */
637: PPC_OP(addze)
638: {
639: T1 = T0;
640: T0 += xer_ca;
641: if (T0 < T1) {
642: xer_ca = 1;
643: } else {
644: xer_ca = 0;
645: }
646: RETURN();
647: }
648:
649: void do_addzeo (void);
650: void op_addzeo (void)
651: {
652: do_addzeo();
653: RETURN();
654: }
655:
656: /* divide word */
657: PPC_OP(divw)
658: {
659: if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
660: T0 = (int32_t)((-1) * (T0 >> 31));
661: } else {
662: T0 = (Ts0 / Ts1);
663: }
664: RETURN();
665: }
666:
667: void do_divwo (void);
668: void op_divwo (void)
669: {
670: do_divwo();
671: RETURN();
672: }
673:
674: /* divide word unsigned */
675: PPC_OP(divwu)
676: {
677: if (T1 == 0) {
678: T0 = 0;
679: } else {
680: T0 /= T1;
681: }
682: RETURN();
683: }
684:
685: void do_divwuo (void);
686: void op_divwuo (void)
687: {
688: do_divwuo();
689: RETURN();
690: }
691:
692: /* multiply high word */
693: PPC_OP(mulhw)
694: {
695: T0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
696: RETURN();
697: }
698:
699: /* multiply high word unsigned */
700: PPC_OP(mulhwu)
701: {
702: T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
703: RETURN();
704: }
705:
706: /* multiply low immediate */
707: PPC_OP(mulli)
708: {
709: T0 = (Ts0 * SPARAM(1));
710: RETURN();
711: }
712:
713: /* multiply low word */
714: PPC_OP(mullw)
715: {
716: T0 *= T1;
717: RETURN();
718: }
719:
720: void do_mullwo (void);
721: void op_mullwo (void)
722: {
723: do_mullwo();
724: RETURN();
725: }
726:
727: /* negate */
728: PPC_OP(neg)
729: {
730: if (T0 != 0x80000000) {
731: T0 = -Ts0;
732: }
733: RETURN();
734: }
735:
736: void do_nego (void);
737: void op_nego (void)
738: {
739: do_nego();
740: RETURN();
741: }
742:
743: /* substract from */
744: PPC_OP(subf)
745: {
746: T0 = T1 - T0;
747: RETURN();
748: }
749:
750: void do_subfo (void);
751: void op_subfo (void)
752: {
753: do_subfo();
754: RETURN();
755: }
756:
757: /* substract from carrying */
758: PPC_OP(subfc)
759: {
760: T0 = T1 - T0;
761: if (T0 <= T1) {
762: xer_ca = 1;
763: } else {
764: xer_ca = 0;
765: }
766: RETURN();
767: }
768:
769: void do_subfco (void);
770: void op_subfco (void)
771: {
772: do_subfco();
773: RETURN();
774: }
775:
776: /* substract from extended */
777: void do_subfe (void);
778: void op_subfe (void)
779: {
780: do_subfe();
781: RETURN();
782: }
783:
784: void do_subfeo (void);
785: PPC_OP(subfeo)
786: {
787: do_subfeo();
788: RETURN();
789: }
790:
791: /* substract from immediate carrying */
792: PPC_OP(subfic)
793: {
794: T0 = PARAM(1) + ~T0 + 1;
795: if (T0 <= PARAM(1)) {
796: xer_ca = 1;
797: } else {
798: xer_ca = 0;
799: }
800: RETURN();
801: }
802:
803: /* substract from minus one extended */
804: PPC_OP(subfme)
805: {
806: T0 = ~T0 + xer_ca - 1;
807:
808: if (T0 != -1)
809: xer_ca = 1;
810: RETURN();
811: }
812:
813: void do_subfmeo (void);
814: void op_subfmeo (void)
815: {
816: do_subfmeo();
817: RETURN();
818: }
819:
820: /* substract from zero extended */
821: PPC_OP(subfze)
822: {
823: T1 = ~T0;
824: T0 = T1 + xer_ca;
825: if (T0 < T1) {
826: xer_ca = 1;
827: } else {
828: xer_ca = 0;
829: }
830: RETURN();
831: }
832:
833: void do_subfzeo (void);
834: void op_subfzeo (void)
835: {
836: do_subfzeo();
837: RETURN();
838: }
839:
840: /*** Integer comparison ***/
841: /* compare */
842: PPC_OP(cmp)
843: {
844: if (Ts0 < Ts1) {
845: T0 = 0x08;
846: } else if (Ts0 > Ts1) {
847: T0 = 0x04;
848: } else {
849: T0 = 0x02;
850: }
851: RETURN();
852: }
853:
854: /* compare immediate */
855: PPC_OP(cmpi)
856: {
857: if (Ts0 < SPARAM(1)) {
858: T0 = 0x08;
859: } else if (Ts0 > SPARAM(1)) {
860: T0 = 0x04;
861: } else {
862: T0 = 0x02;
863: }
864: RETURN();
865: }
866:
867: /* compare logical */
868: PPC_OP(cmpl)
869: {
870: if (T0 < T1) {
871: T0 = 0x08;
872: } else if (T0 > T1) {
873: T0 = 0x04;
874: } else {
875: T0 = 0x02;
876: }
877: RETURN();
878: }
879:
880: /* compare logical immediate */
881: PPC_OP(cmpli)
882: {
883: if (T0 < PARAM(1)) {
884: T0 = 0x08;
885: } else if (T0 > PARAM(1)) {
886: T0 = 0x04;
887: } else {
888: T0 = 0x02;
889: }
890: RETURN();
891: }
892:
893: /*** Integer logical ***/
894: /* and */
895: PPC_OP(and)
896: {
897: T0 &= T1;
898: RETURN();
899: }
900:
901: /* andc */
902: PPC_OP(andc)
903: {
904: T0 &= ~T1;
905: RETURN();
906: }
907:
908: /* andi. */
909: PPC_OP(andi_)
910: {
911: T0 &= PARAM(1);
912: RETURN();
913: }
914:
915: /* count leading zero */
916: PPC_OP(cntlzw)
917: {
918: T1 = T0;
919: for (T0 = 32; T1 > 0; T0--)
920: T1 = T1 >> 1;
921: RETURN();
922: }
923:
924: /* eqv */
925: PPC_OP(eqv)
926: {
927: T0 = ~(T0 ^ T1);
928: RETURN();
929: }
930:
931: /* extend sign byte */
932: PPC_OP(extsb)
933: {
934: T0 = (int32_t)((int8_t)(Ts0));
935: RETURN();
936: }
937:
938: /* extend sign half word */
939: PPC_OP(extsh)
940: {
941: T0 = (int32_t)((int16_t)(Ts0));
942: RETURN();
943: }
944:
945: /* nand */
946: PPC_OP(nand)
947: {
948: T0 = ~(T0 & T1);
949: RETURN();
950: }
951:
952: /* nor */
953: PPC_OP(nor)
954: {
955: T0 = ~(T0 | T1);
956: RETURN();
957: }
958:
959: /* or */
960: PPC_OP(or)
961: {
962: T0 |= T1;
963: RETURN();
964: }
965:
966: /* orc */
967: PPC_OP(orc)
968: {
969: T0 |= ~T1;
970: RETURN();
971: }
972:
973: /* ori */
974: PPC_OP(ori)
975: {
976: T0 |= PARAM(1);
977: RETURN();
978: }
979:
980: /* xor */
981: PPC_OP(xor)
982: {
983: T0 ^= T1;
984: RETURN();
985: }
986:
987: /* xori */
988: PPC_OP(xori)
989: {
990: T0 ^= PARAM(1);
991: RETURN();
992: }
993:
994: /*** Integer rotate ***/
995: /* rotate left word immediate then mask insert */
996: PPC_OP(rlwimi)
997: {
998: T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
999: RETURN();
1000: }
1001:
1002: /* rotate left immediate then and with mask insert */
1003: PPC_OP(rotlwi)
1004: {
1005: T0 = rotl(T0, PARAM(1));
1006: RETURN();
1007: }
1008:
1009: PPC_OP(slwi)
1010: {
1011: T0 = T0 << PARAM(1);
1012: RETURN();
1013: }
1014:
1015: PPC_OP(srwi)
1016: {
1017: T0 = T0 >> PARAM(1);
1018: RETURN();
1019: }
1020:
1021: /* rotate left word then and with mask insert */
1022: PPC_OP(rlwinm)
1023: {
1024: T0 = rotl(T0, PARAM(1)) & PARAM(2);
1025: RETURN();
1026: }
1027:
1028: PPC_OP(rotl)
1029: {
1030: T0 = rotl(T0, T1);
1031: RETURN();
1032: }
1033:
1034: PPC_OP(rlwnm)
1035: {
1036: T0 = rotl(T0, T1) & PARAM(1);
1037: RETURN();
1038: }
1039:
1040: /*** Integer shift ***/
1041: /* shift left word */
1042: PPC_OP(slw)
1043: {
1044: if (T1 & 0x20) {
1045: T0 = 0;
1046: } else {
1047: T0 = T0 << T1;
1048: }
1049: RETURN();
1050: }
1051:
1052: /* shift right algebraic word */
1053: void op_sraw (void)
1054: {
1055: do_sraw();
1056: RETURN();
1057: }
1058:
1059: /* shift right algebraic word immediate */
1060: PPC_OP(srawi)
1061: {
1062: T1 = T0;
1063: T0 = (Ts0 >> PARAM(1));
1064: if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1065: xer_ca = 1;
1066: } else {
1067: xer_ca = 0;
1068: }
1069: RETURN();
1070: }
1071:
1072: /* shift right word */
1073: PPC_OP(srw)
1074: {
1075: if (T1 & 0x20) {
1076: T0 = 0;
1077: } else {
1078: T0 = T0 >> T1;
1079: }
1080: RETURN();
1081: }
1082:
1083: /*** Floating-Point arithmetic ***/
1084: /* fadd - fadd. */
1085: PPC_OP(fadd)
1086: {
1087: FT0 += FT1;
1088: RETURN();
1089: }
1090:
1091: /* fsub - fsub. */
1092: PPC_OP(fsub)
1093: {
1094: FT0 -= FT1;
1095: RETURN();
1096: }
1097:
1098: /* fmul - fmul. */
1099: PPC_OP(fmul)
1100: {
1101: FT0 *= FT1;
1102: RETURN();
1103: }
1104:
1105: /* fdiv - fdiv. */
1106: PPC_OP(fdiv)
1107: {
1108: FT0 = float64_div(FT0, FT1, &env->fp_status);
1109: RETURN();
1110: }
1111:
1112: /* fsqrt - fsqrt. */
1113: PPC_OP(fsqrt)
1114: {
1115: do_fsqrt();
1116: RETURN();
1117: }
1118:
1119: /* fres - fres. */
1120: PPC_OP(fres)
1121: {
1122: do_fres();
1123: RETURN();
1124: }
1125:
1126: /* frsqrte - frsqrte. */
1127: PPC_OP(frsqrte)
1128: {
1129: do_frsqrte();
1130: RETURN();
1131: }
1132:
1133: /* fsel - fsel. */
1134: PPC_OP(fsel)
1135: {
1136: do_fsel();
1137: RETURN();
1138: }
1139:
1140: /*** Floating-Point multiply-and-add ***/
1141: /* fmadd - fmadd. */
1142: PPC_OP(fmadd)
1143: {
1144: FT0 = (FT0 * FT1) + FT2;
1145: RETURN();
1146: }
1147:
1148: /* fmsub - fmsub. */
1149: PPC_OP(fmsub)
1150: {
1151: FT0 = (FT0 * FT1) - FT2;
1152: RETURN();
1153: }
1154:
1155: /* fnmadd - fnmadd. - fnmadds - fnmadds. */
1156: PPC_OP(fnmadd)
1157: {
1158: do_fnmadd();
1159: RETURN();
1160: }
1161:
1162: /* fnmsub - fnmsub. */
1163: PPC_OP(fnmsub)
1164: {
1165: do_fnmsub();
1166: RETURN();
1167: }
1168:
1169: /*** Floating-Point round & convert ***/
1170: /* frsp - frsp. */
1171: PPC_OP(frsp)
1172: {
1173: FT0 = (float)FT0;
1174: RETURN();
1175: }
1176:
1177: /* fctiw - fctiw. */
1178: PPC_OP(fctiw)
1179: {
1180: do_fctiw();
1181: RETURN();
1182: }
1183:
1184: /* fctiwz - fctiwz. */
1185: PPC_OP(fctiwz)
1186: {
1187: do_fctiwz();
1188: RETURN();
1189: }
1190:
1191:
1192: /*** Floating-Point compare ***/
1193: /* fcmpu */
1194: PPC_OP(fcmpu)
1195: {
1196: do_fcmpu();
1197: RETURN();
1198: }
1199:
1200: /* fcmpo */
1201: PPC_OP(fcmpo)
1202: {
1203: do_fcmpo();
1204: RETURN();
1205: }
1206:
1207: /*** Floating-point move ***/
1208: /* fabs */
1209: PPC_OP(fabs)
1210: {
1211: FT0 = float64_abs(FT0);
1212: RETURN();
1213: }
1214:
1215: /* fnabs */
1216: PPC_OP(fnabs)
1217: {
1218: FT0 = float64_abs(FT0);
1219: FT0 = float64_chs(FT0);
1220: RETURN();
1221: }
1222:
1223: /* fneg */
1224: PPC_OP(fneg)
1225: {
1226: FT0 = float64_chs(FT0);
1227: RETURN();
1228: }
1229:
1230: /* Load and store */
1231: #define MEMSUFFIX _raw
1232: #include "op_mem.h"
1233: #if !defined(CONFIG_USER_ONLY)
1234: #define MEMSUFFIX _user
1235: #include "op_mem.h"
1236:
1237: #define MEMSUFFIX _kernel
1238: #include "op_mem.h"
1239: #endif
1240:
1241: /* Special op to check and maybe clear reservation */
1242: PPC_OP(check_reservation)
1243: {
1244: if ((uint32_t)env->reserve == (uint32_t)(T0 & ~0x00000003))
1245: env->reserve = -1;
1246: RETURN();
1247: }
1248:
1249: /* Return from interrupt */
1250: void do_rfi (void);
1251: void op_rfi (void)
1252: {
1253: do_rfi();
1254: RETURN();
1255: }
1256:
1257: /* Trap word */
1258: void do_tw (uint32_t cmp, int flags);
1259: void op_tw (void)
1260: {
1261: do_tw(T1, PARAM(1));
1262: RETURN();
1263: }
1264:
1265: void op_twi (void)
1266: {
1267: do_tw(PARAM(1), PARAM(2));
1268: RETURN();
1269: }
1270:
1271: /* Instruction cache block invalidate */
1272: PPC_OP(icbi)
1273: {
1274: do_icbi();
1275: RETURN();
1276: }
1277:
1278: /* tlbia */
1279: PPC_OP(tlbia)
1280: {
1281: do_tlbia();
1282: RETURN();
1283: }
1284:
1285: /* tlbie */
1286: PPC_OP(tlbie)
1287: {
1288: do_tlbie();
1289: RETURN();
1290: }
1291:
1292: void op_store_pir (void)
1293: {
1294: env->spr[SPR_PIR] = T0 & 0x0000000FUL;
1295: RETURN();
1296: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.