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