|
|
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:
1.1.1.2 ! root 454: PPC_OP(goto_tb0)
1.1 root 455: {
1.1.1.2 ! root 456: GOTO_TB(op_goto_tb0, PARAM1, 0);
! 457: }
! 458:
! 459: PPC_OP(goto_tb1)
! 460: {
! 461: GOTO_TB(op_goto_tb1, PARAM1, 1);
1.1 root 462: }
463:
464: PPC_OP(b_T1)
465: {
466: regs->nip = T1 & ~3;
467: }
468:
1.1.1.2 ! root 469: PPC_OP(jz_T0)
1.1 root 470: {
1.1.1.2 ! root 471: if (!T0)
! 472: GOTO_LABEL_PARAM(1);
1.1 root 473: RETURN();
474: }
475:
476: PPC_OP(btest_T1)
477: {
478: if (T0) {
479: regs->nip = T1 & ~3;
480: } else {
481: regs->nip = PARAM1;
482: }
483: RETURN();
484: }
485:
486: PPC_OP(movl_T1_ctr)
487: {
488: T1 = regs->ctr;
489: }
490:
491: PPC_OP(movl_T1_lr)
492: {
493: T1 = regs->lr;
494: }
495:
496: /* tests with result in T0 */
497:
498: PPC_OP(test_ctr)
499: {
500: T0 = regs->ctr;
501: }
502:
503: PPC_OP(test_ctr_true)
504: {
505: T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0);
506: }
507:
508: PPC_OP(test_ctr_false)
509: {
510: T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0);
511: }
512:
513: PPC_OP(test_ctrz)
514: {
515: T0 = (regs->ctr == 0);
516: }
517:
518: PPC_OP(test_ctrz_true)
519: {
520: T0 = (regs->ctr == 0 && (T0 & PARAM(1)) != 0);
521: }
522:
523: PPC_OP(test_ctrz_false)
524: {
525: T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
526: }
527:
528: PPC_OP(test_true)
529: {
530: T0 = (T0 & PARAM(1));
531: }
532:
533: PPC_OP(test_false)
534: {
535: T0 = ((T0 & PARAM(1)) == 0);
536: }
537:
538: /* CTR maintenance */
539: PPC_OP(dec_ctr)
540: {
541: regs->ctr--;
542: RETURN();
543: }
544:
545: /*** Integer arithmetic ***/
546: /* add */
547: PPC_OP(add)
548: {
549: T0 += T1;
550: RETURN();
551: }
552:
553: void do_addo (void);
554: void op_addo (void)
555: {
556: do_addo();
557: RETURN();
558: }
559:
560: /* add carrying */
561: PPC_OP(addc)
562: {
563: T2 = T0;
564: T0 += T1;
565: if (T0 < T2) {
566: xer_ca = 1;
567: } else {
568: xer_ca = 0;
569: }
570: RETURN();
571: }
572:
573: void do_addco (void);
574: void op_addco (void)
575: {
576: do_addco();
577: RETURN();
578: }
579:
580: /* add extended */
581: void do_adde (void);
582: void op_adde (void)
583: {
584: do_adde();
585: }
586:
587: void do_addeo (void);
588: PPC_OP(addeo)
589: {
590: do_addeo();
591: RETURN();
592: }
593:
594: /* add immediate */
595: PPC_OP(addi)
596: {
597: T0 += PARAM(1);
598: RETURN();
599: }
600:
601: /* add immediate carrying */
602: PPC_OP(addic)
603: {
604: T1 = T0;
605: T0 += PARAM(1);
606: if (T0 < T1) {
607: xer_ca = 1;
608: } else {
609: xer_ca = 0;
610: }
611: RETURN();
612: }
613:
614: /* add to minus one extended */
615: PPC_OP(addme)
616: {
617: T1 = T0;
618: T0 += xer_ca + (-1);
619: if (T1 != 0)
620: xer_ca = 1;
621: RETURN();
622: }
623:
624: void do_addmeo (void);
625: void op_addmeo (void)
626: {
627: do_addmeo();
628: RETURN();
629: }
630:
631: /* add to zero extended */
632: PPC_OP(addze)
633: {
634: T1 = T0;
635: T0 += xer_ca;
636: if (T0 < T1) {
637: xer_ca = 1;
638: } else {
639: xer_ca = 0;
640: }
641: RETURN();
642: }
643:
644: void do_addzeo (void);
645: void op_addzeo (void)
646: {
647: do_addzeo();
648: RETURN();
649: }
650:
651: /* divide word */
652: PPC_OP(divw)
653: {
654: if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
655: T0 = (int32_t)((-1) * (T0 >> 31));
656: } else {
657: T0 = (Ts0 / Ts1);
658: }
659: RETURN();
660: }
661:
662: void do_divwo (void);
663: void op_divwo (void)
664: {
665: do_divwo();
666: RETURN();
667: }
668:
669: /* divide word unsigned */
670: PPC_OP(divwu)
671: {
672: if (T1 == 0) {
673: T0 = 0;
674: } else {
675: T0 /= T1;
676: }
677: RETURN();
678: }
679:
680: void do_divwuo (void);
681: void op_divwuo (void)
682: {
683: do_divwuo();
684: RETURN();
685: }
686:
687: /* multiply high word */
688: PPC_OP(mulhw)
689: {
690: T0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
691: RETURN();
692: }
693:
694: /* multiply high word unsigned */
695: PPC_OP(mulhwu)
696: {
697: T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
698: RETURN();
699: }
700:
701: /* multiply low immediate */
702: PPC_OP(mulli)
703: {
704: T0 = (Ts0 * SPARAM(1));
705: RETURN();
706: }
707:
708: /* multiply low word */
709: PPC_OP(mullw)
710: {
711: T0 *= T1;
712: RETURN();
713: }
714:
715: void do_mullwo (void);
716: void op_mullwo (void)
717: {
718: do_mullwo();
719: RETURN();
720: }
721:
722: /* negate */
723: PPC_OP(neg)
724: {
725: if (T0 != 0x80000000) {
726: T0 = -Ts0;
727: }
728: RETURN();
729: }
730:
731: void do_nego (void);
732: void op_nego (void)
733: {
734: do_nego();
735: RETURN();
736: }
737:
738: /* substract from */
739: PPC_OP(subf)
740: {
741: T0 = T1 - T0;
742: RETURN();
743: }
744:
745: void do_subfo (void);
746: void op_subfo (void)
747: {
748: do_subfo();
749: RETURN();
750: }
751:
752: /* substract from carrying */
753: PPC_OP(subfc)
754: {
755: T0 = T1 - T0;
756: if (T0 <= T1) {
757: xer_ca = 1;
758: } else {
759: xer_ca = 0;
760: }
761: RETURN();
762: }
763:
764: void do_subfco (void);
765: void op_subfco (void)
766: {
767: do_subfco();
768: RETURN();
769: }
770:
771: /* substract from extended */
772: void do_subfe (void);
773: void op_subfe (void)
774: {
775: do_subfe();
776: RETURN();
777: }
778:
779: void do_subfeo (void);
780: PPC_OP(subfeo)
781: {
782: do_subfeo();
783: RETURN();
784: }
785:
786: /* substract from immediate carrying */
787: PPC_OP(subfic)
788: {
789: T0 = PARAM(1) + ~T0 + 1;
790: if (T0 <= PARAM(1)) {
791: xer_ca = 1;
792: } else {
793: xer_ca = 0;
794: }
795: RETURN();
796: }
797:
798: /* substract from minus one extended */
799: PPC_OP(subfme)
800: {
801: T0 = ~T0 + xer_ca - 1;
802:
803: if (T0 != -1)
804: xer_ca = 1;
805: RETURN();
806: }
807:
808: void do_subfmeo (void);
809: void op_subfmeo (void)
810: {
811: do_subfmeo();
812: RETURN();
813: }
814:
815: /* substract from zero extended */
816: PPC_OP(subfze)
817: {
818: T1 = ~T0;
819: T0 = T1 + xer_ca;
820: if (T0 < T1) {
821: xer_ca = 1;
822: } else {
823: xer_ca = 0;
824: }
825: RETURN();
826: }
827:
828: void do_subfzeo (void);
829: void op_subfzeo (void)
830: {
831: do_subfzeo();
832: RETURN();
833: }
834:
835: /*** Integer comparison ***/
836: /* compare */
837: PPC_OP(cmp)
838: {
839: if (Ts0 < Ts1) {
840: T0 = 0x08;
841: } else if (Ts0 > Ts1) {
842: T0 = 0x04;
843: } else {
844: T0 = 0x02;
845: }
846: RETURN();
847: }
848:
849: /* compare immediate */
850: PPC_OP(cmpi)
851: {
852: if (Ts0 < SPARAM(1)) {
853: T0 = 0x08;
854: } else if (Ts0 > SPARAM(1)) {
855: T0 = 0x04;
856: } else {
857: T0 = 0x02;
858: }
859: RETURN();
860: }
861:
862: /* compare logical */
863: PPC_OP(cmpl)
864: {
865: if (T0 < T1) {
866: T0 = 0x08;
867: } else if (T0 > T1) {
868: T0 = 0x04;
869: } else {
870: T0 = 0x02;
871: }
872: RETURN();
873: }
874:
875: /* compare logical immediate */
876: PPC_OP(cmpli)
877: {
878: if (T0 < PARAM(1)) {
879: T0 = 0x08;
880: } else if (T0 > PARAM(1)) {
881: T0 = 0x04;
882: } else {
883: T0 = 0x02;
884: }
885: RETURN();
886: }
887:
888: /*** Integer logical ***/
889: /* and */
890: PPC_OP(and)
891: {
892: T0 &= T1;
893: RETURN();
894: }
895:
896: /* andc */
897: PPC_OP(andc)
898: {
899: T0 &= ~T1;
900: RETURN();
901: }
902:
903: /* andi. */
904: PPC_OP(andi_)
905: {
906: T0 &= PARAM(1);
907: RETURN();
908: }
909:
910: /* count leading zero */
911: PPC_OP(cntlzw)
912: {
913: T1 = T0;
914: for (T0 = 32; T1 > 0; T0--)
915: T1 = T1 >> 1;
916: RETURN();
917: }
918:
919: /* eqv */
920: PPC_OP(eqv)
921: {
922: T0 = ~(T0 ^ T1);
923: RETURN();
924: }
925:
926: /* extend sign byte */
927: PPC_OP(extsb)
928: {
929: T0 = (int32_t)((int8_t)(Ts0));
930: RETURN();
931: }
932:
933: /* extend sign half word */
934: PPC_OP(extsh)
935: {
936: T0 = (int32_t)((int16_t)(Ts0));
937: RETURN();
938: }
939:
940: /* nand */
941: PPC_OP(nand)
942: {
943: T0 = ~(T0 & T1);
944: RETURN();
945: }
946:
947: /* nor */
948: PPC_OP(nor)
949: {
950: T0 = ~(T0 | T1);
951: RETURN();
952: }
953:
954: /* or */
955: PPC_OP(or)
956: {
957: T0 |= T1;
958: RETURN();
959: }
960:
961: /* orc */
962: PPC_OP(orc)
963: {
964: T0 |= ~T1;
965: RETURN();
966: }
967:
968: /* ori */
969: PPC_OP(ori)
970: {
971: T0 |= PARAM(1);
972: RETURN();
973: }
974:
975: /* xor */
976: PPC_OP(xor)
977: {
978: T0 ^= T1;
979: RETURN();
980: }
981:
982: /* xori */
983: PPC_OP(xori)
984: {
985: T0 ^= PARAM(1);
986: RETURN();
987: }
988:
989: /*** Integer rotate ***/
990: /* rotate left word immediate then mask insert */
991: PPC_OP(rlwimi)
992: {
993: T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
994: RETURN();
995: }
996:
997: /* rotate left immediate then and with mask insert */
998: PPC_OP(rotlwi)
999: {
1000: T0 = rotl(T0, PARAM(1));
1001: RETURN();
1002: }
1003:
1004: PPC_OP(slwi)
1005: {
1006: T0 = T0 << PARAM(1);
1007: RETURN();
1008: }
1009:
1010: PPC_OP(srwi)
1011: {
1012: T0 = T0 >> PARAM(1);
1013: RETURN();
1014: }
1015:
1016: /* rotate left word then and with mask insert */
1017: PPC_OP(rlwinm)
1018: {
1019: T0 = rotl(T0, PARAM(1)) & PARAM(2);
1020: RETURN();
1021: }
1022:
1023: PPC_OP(rotl)
1024: {
1025: T0 = rotl(T0, T1);
1026: RETURN();
1027: }
1028:
1029: PPC_OP(rlwnm)
1030: {
1031: T0 = rotl(T0, T1) & PARAM(1);
1032: RETURN();
1033: }
1034:
1035: /*** Integer shift ***/
1036: /* shift left word */
1037: PPC_OP(slw)
1038: {
1039: if (T1 & 0x20) {
1040: T0 = 0;
1041: } else {
1042: T0 = T0 << T1;
1043: }
1044: RETURN();
1045: }
1046:
1047: /* shift right algebraic word */
1048: void op_sraw (void)
1049: {
1050: do_sraw();
1051: RETURN();
1052: }
1053:
1054: /* shift right algebraic word immediate */
1055: PPC_OP(srawi)
1056: {
1057: T1 = T0;
1058: T0 = (Ts0 >> PARAM(1));
1059: if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1060: xer_ca = 1;
1061: } else {
1062: xer_ca = 0;
1063: }
1064: RETURN();
1065: }
1066:
1067: /* shift right word */
1068: PPC_OP(srw)
1069: {
1070: if (T1 & 0x20) {
1071: T0 = 0;
1072: } else {
1073: T0 = T0 >> T1;
1074: }
1075: RETURN();
1076: }
1077:
1078: /*** Floating-Point arithmetic ***/
1079: /* fadd - fadd. */
1080: PPC_OP(fadd)
1081: {
1082: FT0 += FT1;
1083: RETURN();
1084: }
1085:
1086: /* fsub - fsub. */
1087: PPC_OP(fsub)
1088: {
1089: FT0 -= FT1;
1090: RETURN();
1091: }
1092:
1093: /* fmul - fmul. */
1094: PPC_OP(fmul)
1095: {
1096: FT0 *= FT1;
1097: RETURN();
1098: }
1099:
1100: /* fdiv - fdiv. */
1101: PPC_OP(fdiv)
1102: {
1103: FT0 = float64_div(FT0, FT1, &env->fp_status);
1104: RETURN();
1105: }
1106:
1107: /* fsqrt - fsqrt. */
1108: PPC_OP(fsqrt)
1109: {
1110: do_fsqrt();
1111: RETURN();
1112: }
1113:
1114: /* fres - fres. */
1115: PPC_OP(fres)
1116: {
1117: do_fres();
1118: RETURN();
1119: }
1120:
1121: /* frsqrte - frsqrte. */
1122: PPC_OP(frsqrte)
1123: {
1124: do_frsqrte();
1125: RETURN();
1126: }
1127:
1128: /* fsel - fsel. */
1129: PPC_OP(fsel)
1130: {
1131: do_fsel();
1132: RETURN();
1133: }
1134:
1135: /*** Floating-Point multiply-and-add ***/
1136: /* fmadd - fmadd. */
1137: PPC_OP(fmadd)
1138: {
1139: FT0 = (FT0 * FT1) + FT2;
1140: RETURN();
1141: }
1142:
1143: /* fmsub - fmsub. */
1144: PPC_OP(fmsub)
1145: {
1146: FT0 = (FT0 * FT1) - FT2;
1147: RETURN();
1148: }
1149:
1150: /* fnmadd - fnmadd. - fnmadds - fnmadds. */
1151: PPC_OP(fnmadd)
1152: {
1153: do_fnmadd();
1154: RETURN();
1155: }
1156:
1157: /* fnmsub - fnmsub. */
1158: PPC_OP(fnmsub)
1159: {
1160: do_fnmsub();
1161: RETURN();
1162: }
1163:
1164: /*** Floating-Point round & convert ***/
1165: /* frsp - frsp. */
1166: PPC_OP(frsp)
1167: {
1168: FT0 = (float)FT0;
1169: RETURN();
1170: }
1171:
1172: /* fctiw - fctiw. */
1173: PPC_OP(fctiw)
1174: {
1175: do_fctiw();
1176: RETURN();
1177: }
1178:
1179: /* fctiwz - fctiwz. */
1180: PPC_OP(fctiwz)
1181: {
1182: do_fctiwz();
1183: RETURN();
1184: }
1185:
1186:
1187: /*** Floating-Point compare ***/
1188: /* fcmpu */
1189: PPC_OP(fcmpu)
1190: {
1191: do_fcmpu();
1192: RETURN();
1193: }
1194:
1195: /* fcmpo */
1196: PPC_OP(fcmpo)
1197: {
1198: do_fcmpo();
1199: RETURN();
1200: }
1201:
1202: /*** Floating-point move ***/
1203: /* fabs */
1204: PPC_OP(fabs)
1205: {
1206: FT0 = float64_abs(FT0);
1207: RETURN();
1208: }
1209:
1210: /* fnabs */
1211: PPC_OP(fnabs)
1212: {
1213: FT0 = float64_abs(FT0);
1214: FT0 = float64_chs(FT0);
1215: RETURN();
1216: }
1217:
1218: /* fneg */
1219: PPC_OP(fneg)
1220: {
1221: FT0 = float64_chs(FT0);
1222: RETURN();
1223: }
1224:
1225: /* Load and store */
1226: #define MEMSUFFIX _raw
1227: #include "op_mem.h"
1228: #if !defined(CONFIG_USER_ONLY)
1229: #define MEMSUFFIX _user
1230: #include "op_mem.h"
1231:
1232: #define MEMSUFFIX _kernel
1233: #include "op_mem.h"
1234: #endif
1235:
1236: /* Special op to check and maybe clear reservation */
1237: PPC_OP(check_reservation)
1238: {
1239: if ((uint32_t)env->reserve == (uint32_t)(T0 & ~0x00000003))
1240: env->reserve = -1;
1241: RETURN();
1242: }
1243:
1244: /* Return from interrupt */
1245: void do_rfi (void);
1246: void op_rfi (void)
1247: {
1248: do_rfi();
1249: RETURN();
1250: }
1251:
1252: /* Trap word */
1253: void do_tw (uint32_t cmp, int flags);
1254: void op_tw (void)
1255: {
1256: do_tw(T1, PARAM(1));
1257: RETURN();
1258: }
1259:
1260: void op_twi (void)
1261: {
1262: do_tw(PARAM(1), PARAM(2));
1263: RETURN();
1264: }
1265:
1266: /* Instruction cache block invalidate */
1267: PPC_OP(icbi)
1268: {
1269: do_icbi();
1270: RETURN();
1271: }
1272:
1273: /* tlbia */
1274: PPC_OP(tlbia)
1275: {
1276: do_tlbia();
1277: RETURN();
1278: }
1279:
1280: /* tlbie */
1281: PPC_OP(tlbie)
1282: {
1283: do_tlbie();
1284: RETURN();
1285: }
1286:
1287: void op_store_pir (void)
1288: {
1289: env->spr[SPR_PIR] = T0 & 0x0000000FUL;
1290: RETURN();
1291: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.