2 * MIPS emulation micro-operations for qemu.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2007 Thiemo Seufer (64-bit FPU support)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "host-utils.h"
28 #define CALL_FROM_TB0(func) func()
31 #define CALL_FROM_TB1(func, arg0) func(arg0)
33 #ifndef CALL_FROM_TB1_CONST16
34 #define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
37 #define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
39 #ifndef CALL_FROM_TB2_CONST16
40 #define CALL_FROM_TB2_CONST16(func, arg0, arg1) \
41 CALL_FROM_TB2(func, arg0, arg1)
44 #define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
47 #define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
48 func(arg0, arg1, arg2, arg3)
52 #include "fop_template.c"
55 #include "fop_template.c"
58 #include "fop_template.c"
61 #include "fop_template.c"
64 #include "fop_template.c"
67 #include "fop_template.c"
70 #include "fop_template.c"
73 #include "fop_template.c"
76 #include "fop_template.c"
79 #include "fop_template.c"
82 #include "fop_template.c"
85 #include "fop_template.c"
88 #include "fop_template.c"
91 #include "fop_template.c"
94 #include "fop_template.c"
97 #include "fop_template.c"
100 #include "fop_template.c"
103 #include "fop_template.c"
106 #include "fop_template.c"
109 #include "fop_template.c"
112 #include "fop_template.c"
115 #include "fop_template.c"
118 #include "fop_template.c"
121 #include "fop_template.c"
124 #include "fop_template.c"
127 #include "fop_template.c"
130 #include "fop_template.c"
133 #include "fop_template.c"
136 #include "fop_template.c"
139 #include "fop_template.c"
142 #include "fop_template.c"
145 #include "fop_template.c"
149 #define MEMSUFFIX _raw
152 #if !defined(CONFIG_USER_ONLY)
153 #define MEMSUFFIX _user
157 #define MEMSUFFIX _super
161 #define MEMSUFFIX _kernel
166 /* 64 bits arithmetic */
167 #if TARGET_LONG_BITS > HOST_LONG_BITS
170 CALL_FROM_TB0(do_mult);
176 CALL_FROM_TB0(do_multu);
182 CALL_FROM_TB0(do_madd);
188 CALL_FROM_TB0(do_maddu);
194 CALL_FROM_TB0(do_msub);
200 CALL_FROM_TB0(do_msubu);
204 /* Multiplication variants of the vr54xx. */
207 CALL_FROM_TB0(do_muls);
213 CALL_FROM_TB0(do_mulsu);
219 CALL_FROM_TB0(do_macc);
223 void op_macchi (void)
225 CALL_FROM_TB0(do_macchi);
231 CALL_FROM_TB0(do_maccu);
234 void op_macchiu (void)
236 CALL_FROM_TB0(do_macchiu);
242 CALL_FROM_TB0(do_msac);
246 void op_msachi (void)
248 CALL_FROM_TB0(do_msachi);
254 CALL_FROM_TB0(do_msacu);
258 void op_msachiu (void)
260 CALL_FROM_TB0(do_msachiu);
266 CALL_FROM_TB0(do_mulhi);
270 void op_mulhiu (void)
272 CALL_FROM_TB0(do_mulhiu);
276 void op_mulshi (void)
278 CALL_FROM_TB0(do_mulshi);
282 void op_mulshiu (void)
284 CALL_FROM_TB0(do_mulshiu);
288 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
290 static always_inline uint64_t get_HILO (void)
292 return ((uint64_t)env->HI[env->current_tc][0] << 32) |
293 ((uint64_t)(uint32_t)env->LO[env->current_tc][0]);
296 static always_inline void set_HILO (uint64_t HILO)
298 env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
299 env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
302 static always_inline void set_HIT0_LO (uint64_t HILO)
304 env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
305 T0 = env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
308 static always_inline void set_HI_LOT0 (uint64_t HILO)
310 T0 = env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
311 env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
316 set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
322 set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
330 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
331 set_HILO((int64_t)get_HILO() + tmp);
339 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
340 set_HILO(get_HILO() + tmp);
348 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
349 set_HILO((int64_t)get_HILO() - tmp);
357 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
358 set_HILO(get_HILO() - tmp);
362 /* Multiplication variants of the vr54xx. */
365 set_HI_LOT0(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
371 set_HI_LOT0(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
377 set_HI_LOT0(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
381 void op_macchi (void)
383 set_HIT0_LO(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
389 set_HI_LOT0(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
393 void op_macchiu (void)
395 set_HIT0_LO(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
401 set_HI_LOT0(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
405 void op_msachi (void)
407 set_HIT0_LO(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
413 set_HI_LOT0(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
417 void op_msachiu (void)
419 set_HIT0_LO(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
425 set_HIT0_LO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
429 void op_mulhiu (void)
431 set_HIT0_LO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
435 void op_mulshi (void)
437 set_HIT0_LO(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
441 void op_mulshiu (void)
443 set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
447 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
449 #if defined(TARGET_MIPS64)
452 CALL_FROM_TB4(muls64, &(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1);
456 void op_dmultu (void)
458 CALL_FROM_TB4(mulu64, &(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1);
464 void op_mfc0_mvpcontrol (void)
466 T0 = env->mvp->CP0_MVPControl;
470 void op_mfc0_mvpconf0 (void)
472 T0 = env->mvp->CP0_MVPConf0;
476 void op_mfc0_mvpconf1 (void)
478 T0 = env->mvp->CP0_MVPConf1;
482 void op_mfc0_random (void)
484 CALL_FROM_TB0(do_mfc0_random);
488 void op_mfc0_tcstatus (void)
490 T0 = env->CP0_TCStatus[env->current_tc];
494 void op_mftc0_tcstatus(void)
496 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
498 T0 = env->CP0_TCStatus[other_tc];
502 void op_mfc0_tcbind (void)
504 T0 = env->CP0_TCBind[env->current_tc];
508 void op_mftc0_tcbind(void)
510 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
512 T0 = env->CP0_TCBind[other_tc];
516 void op_mfc0_tcrestart (void)
518 T0 = env->PC[env->current_tc];
522 void op_mftc0_tcrestart(void)
524 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
526 T0 = env->PC[other_tc];
530 void op_mfc0_tchalt (void)
532 T0 = env->CP0_TCHalt[env->current_tc];
536 void op_mftc0_tchalt(void)
538 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
540 T0 = env->CP0_TCHalt[other_tc];
544 void op_mfc0_tccontext (void)
546 T0 = env->CP0_TCContext[env->current_tc];
550 void op_mftc0_tccontext(void)
552 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
554 T0 = env->CP0_TCContext[other_tc];
558 void op_mfc0_tcschedule (void)
560 T0 = env->CP0_TCSchedule[env->current_tc];
564 void op_mftc0_tcschedule(void)
566 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
568 T0 = env->CP0_TCSchedule[other_tc];
572 void op_mfc0_tcschefback (void)
574 T0 = env->CP0_TCScheFBack[env->current_tc];
578 void op_mftc0_tcschefback(void)
580 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
582 T0 = env->CP0_TCScheFBack[other_tc];
586 void op_mfc0_count (void)
588 CALL_FROM_TB0(do_mfc0_count);
592 void op_mftc0_entryhi(void)
594 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
596 T0 = (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff);
600 void op_mftc0_status(void)
602 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
603 uint32_t tcstatus = env->CP0_TCStatus[other_tc];
605 T0 = env->CP0_Status & ~0xf1000018;
606 T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
607 T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
608 T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
612 void op_mfc0_lladdr (void)
614 T0 = (int32_t)env->CP0_LLAddr >> 4;
618 void op_mfc0_watchlo (void)
620 T0 = (int32_t)env->CP0_WatchLo[PARAM1];
624 void op_mfc0_watchhi (void)
626 T0 = env->CP0_WatchHi[PARAM1];
630 void op_mfc0_debug (void)
633 if (env->hflags & MIPS_HFLAG_DM)
638 void op_mftc0_debug(void)
640 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
642 /* XXX: Might be wrong, check with EJTAG spec. */
643 T0 = (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
644 (env->CP0_Debug_tcstatus[other_tc] &
645 ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
649 void op_mtc0_index (void)
652 unsigned int tmp = env->tlb->nb_tlb;
658 env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (num - 1));
662 void op_mtc0_mvpcontrol (void)
667 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
668 mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
670 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
671 mask |= (1 << CP0MVPCo_STLB);
672 newval = (env->mvp->CP0_MVPControl & ~mask) | (T0 & mask);
674 // TODO: Enable/disable shared TLB, enable/disable VPEs.
676 env->mvp->CP0_MVPControl = newval;
680 void op_mtc0_vpecontrol (void)
685 mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
686 (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
687 newval = (env->CP0_VPEControl & ~mask) | (T0 & mask);
689 /* Yield scheduler intercept not implemented. */
690 /* Gating storage scheduler intercept not implemented. */
692 // TODO: Enable/disable TCs.
694 env->CP0_VPEControl = newval;
698 void op_mtc0_vpeconf0 (void)
703 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
704 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
705 mask |= (0xff << CP0VPEC0_XTC);
706 mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
708 newval = (env->CP0_VPEConf0 & ~mask) | (T0 & mask);
710 // TODO: TC exclusive handling due to ERL/EXL.
712 env->CP0_VPEConf0 = newval;
716 void op_mtc0_vpeconf1 (void)
721 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
722 mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
723 (0xff << CP0VPEC1_NCP1);
724 newval = (env->CP0_VPEConf1 & ~mask) | (T0 & mask);
726 /* UDI not implemented. */
727 /* CP2 not implemented. */
729 // TODO: Handle FPU (CP1) binding.
731 env->CP0_VPEConf1 = newval;
735 void op_mtc0_yqmask (void)
737 /* Yield qualifier inputs not implemented. */
738 env->CP0_YQMask = 0x00000000;
742 void op_mtc0_vpeschedule (void)
744 env->CP0_VPESchedule = T0;
748 void op_mtc0_vpeschefback (void)
750 env->CP0_VPEScheFBack = T0;
754 void op_mtc0_vpeopt (void)
756 env->CP0_VPEOpt = T0 & 0x0000ffff;
760 void op_mtc0_entrylo0 (void)
762 /* Large physaddr (PABITS) not implemented */
763 /* 1k pages not implemented */
764 env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
768 void op_mtc0_tcstatus (void)
770 uint32_t mask = env->CP0_TCStatus_rw_bitmask;
773 newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (T0 & mask);
775 // TODO: Sync with CP0_Status.
777 env->CP0_TCStatus[env->current_tc] = newval;
781 void op_mttc0_tcstatus (void)
783 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
785 // TODO: Sync with CP0_Status.
787 env->CP0_TCStatus[other_tc] = T0;
791 void op_mtc0_tcbind (void)
793 uint32_t mask = (1 << CP0TCBd_TBE);
796 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
797 mask |= (1 << CP0TCBd_CurVPE);
798 newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (T0 & mask);
799 env->CP0_TCBind[env->current_tc] = newval;
803 void op_mttc0_tcbind (void)
805 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
806 uint32_t mask = (1 << CP0TCBd_TBE);
809 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
810 mask |= (1 << CP0TCBd_CurVPE);
811 newval = (env->CP0_TCBind[other_tc] & ~mask) | (T0 & mask);
812 env->CP0_TCBind[other_tc] = newval;
816 void op_mtc0_tcrestart (void)
818 env->PC[env->current_tc] = T0;
819 env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS);
820 env->CP0_LLAddr = 0ULL;
821 /* MIPS16 not implemented. */
825 void op_mttc0_tcrestart (void)
827 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
829 env->PC[other_tc] = T0;
830 env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS);
831 env->CP0_LLAddr = 0ULL;
832 /* MIPS16 not implemented. */
836 void op_mtc0_tchalt (void)
838 env->CP0_TCHalt[env->current_tc] = T0 & 0x1;
840 // TODO: Halt TC / Restart (if allocated+active) TC.
845 void op_mttc0_tchalt (void)
847 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
849 // TODO: Halt TC / Restart (if allocated+active) TC.
851 env->CP0_TCHalt[other_tc] = T0;
855 void op_mtc0_tccontext (void)
857 env->CP0_TCContext[env->current_tc] = T0;
861 void op_mttc0_tccontext (void)
863 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
865 env->CP0_TCContext[other_tc] = T0;
869 void op_mtc0_tcschedule (void)
871 env->CP0_TCSchedule[env->current_tc] = T0;
875 void op_mttc0_tcschedule (void)
877 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
879 env->CP0_TCSchedule[other_tc] = T0;
883 void op_mtc0_tcschefback (void)
885 env->CP0_TCScheFBack[env->current_tc] = T0;
889 void op_mttc0_tcschefback (void)
891 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
893 env->CP0_TCScheFBack[other_tc] = T0;
897 void op_mtc0_entrylo1 (void)
899 /* Large physaddr (PABITS) not implemented */
900 /* 1k pages not implemented */
901 env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
905 void op_mtc0_context (void)
907 env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
911 void op_mtc0_pagemask (void)
913 /* 1k pages not implemented */
914 env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
918 void op_mtc0_pagegrain (void)
920 /* SmartMIPS not implemented */
921 /* Large physaddr (PABITS) not implemented */
922 /* 1k pages not implemented */
923 env->CP0_PageGrain = 0;
927 void op_mtc0_wired (void)
929 env->CP0_Wired = T0 % env->tlb->nb_tlb;
933 void op_mtc0_srsconf0 (void)
935 env->CP0_SRSConf0 |= T0 & env->CP0_SRSConf0_rw_bitmask;
939 void op_mtc0_srsconf1 (void)
941 env->CP0_SRSConf1 |= T0 & env->CP0_SRSConf1_rw_bitmask;
945 void op_mtc0_srsconf2 (void)
947 env->CP0_SRSConf2 |= T0 & env->CP0_SRSConf2_rw_bitmask;
951 void op_mtc0_srsconf3 (void)
953 env->CP0_SRSConf3 |= T0 & env->CP0_SRSConf3_rw_bitmask;
957 void op_mtc0_srsconf4 (void)
959 env->CP0_SRSConf4 |= T0 & env->CP0_SRSConf4_rw_bitmask;
963 void op_mtc0_hwrena (void)
965 env->CP0_HWREna = T0 & 0x0000000F;
969 void op_mtc0_count (void)
971 CALL_FROM_TB2(cpu_mips_store_count, env, T0);
975 void op_mtc0_entryhi (void)
977 target_ulong old, val;
979 /* 1k pages not implemented */
980 val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
981 #if defined(TARGET_MIPS64)
984 old = env->CP0_EntryHi;
985 env->CP0_EntryHi = val;
986 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
987 uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff;
988 env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff);
990 /* If the ASID changes, flush qemu's TLB. */
991 if ((old & 0xFF) != (val & 0xFF))
992 CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
996 void op_mttc0_entryhi(void)
998 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1000 env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (T0 & ~0xff);
1001 env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (T0 & 0xff);
1005 void op_mtc0_compare (void)
1007 CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1011 void op_mtc0_status (void)
1014 uint32_t mask = env->CP0_Status_rw_bitmask;
1017 old = env->CP0_Status;
1018 env->CP0_Status = (env->CP0_Status & ~mask) | val;
1019 CALL_FROM_TB1(compute_hflags, env);
1020 if (loglevel & CPU_LOG_EXEC)
1021 CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1022 CALL_FROM_TB1(cpu_mips_update_irq, env);
1026 void op_mttc0_status(void)
1028 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1029 uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1031 env->CP0_Status = T0 & ~0xf1000018;
1032 tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
1033 tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
1034 tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
1035 env->CP0_TCStatus[other_tc] = tcstatus;
1039 void op_mtc0_intctl (void)
1041 /* vectored interrupts not implemented, no performance counters. */
1042 env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (T0 & 0x000002e0);
1046 void op_mtc0_srsctl (void)
1048 uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1049 env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (T0 & mask);
1053 void op_mtc0_srsmap (void)
1055 env->CP0_SRSMap = T0;
1059 void op_mtc0_cause (void)
1061 uint32_t mask = 0x00C00300;
1062 uint32_t old = env->CP0_Cause;
1064 if (env->insn_flags & ISA_MIPS32R2)
1065 mask |= 1 << CP0Ca_DC;
1067 env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
1069 if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
1070 if (env->CP0_Cause & (1 << CP0Ca_DC))
1071 CALL_FROM_TB1(cpu_mips_stop_count, env);
1073 CALL_FROM_TB1(cpu_mips_start_count, env);
1076 /* Handle the software interrupt as an hardware one, as they
1078 if (T0 & CP0Ca_IP_mask) {
1079 CALL_FROM_TB1(cpu_mips_update_irq, env);
1084 void op_mtc0_epc (void)
1090 void op_mtc0_ebase (void)
1092 /* vectored interrupts not implemented */
1093 /* Multi-CPU not implemented */
1094 env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
1098 void op_mtc0_config0 (void)
1100 env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (T0 & 0x00000007);
1104 void op_mtc0_config2 (void)
1106 /* tertiary/secondary caches not implemented */
1107 env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1111 void op_mtc0_watchlo (void)
1113 /* Watch exceptions for instructions, data loads, data stores
1115 env->CP0_WatchLo[PARAM1] = (T0 & ~0x7);
1119 void op_mtc0_watchhi (void)
1121 env->CP0_WatchHi[PARAM1] = (T0 & 0x40FF0FF8);
1122 env->CP0_WatchHi[PARAM1] &= ~(env->CP0_WatchHi[PARAM1] & T0 & 0x7);
1126 void op_mtc0_xcontext (void)
1128 target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1129 env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
1133 void op_mtc0_framemask (void)
1135 env->CP0_Framemask = T0; /* XXX */
1139 void op_mtc0_debug (void)
1141 env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1142 if (T0 & (1 << CP0DB_DM))
1143 env->hflags |= MIPS_HFLAG_DM;
1145 env->hflags &= ~MIPS_HFLAG_DM;
1149 void op_mttc0_debug(void)
1151 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1153 /* XXX: Might be wrong, check with EJTAG spec. */
1154 env->CP0_Debug_tcstatus[other_tc] = T0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1155 env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1156 (T0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1160 void op_mtc0_depc (void)
1166 void op_mtc0_performance0 (void)
1168 env->CP0_Performance0 = T0 & 0x000007ff;
1172 void op_mtc0_taglo (void)
1174 env->CP0_TagLo = T0 & 0xFFFFFCF6;
1178 void op_mtc0_datalo (void)
1180 env->CP0_DataLo = T0; /* XXX */
1184 void op_mtc0_taghi (void)
1186 env->CP0_TagHi = T0; /* XXX */
1190 void op_mtc0_datahi (void)
1192 env->CP0_DataHi = T0; /* XXX */
1196 void op_mtc0_errorepc (void)
1198 env->CP0_ErrorEPC = T0;
1202 void op_mtc0_desave (void)
1204 env->CP0_DESAVE = T0;
1208 #if defined(TARGET_MIPS64)
1209 void op_dmfc0_tcrestart (void)
1211 T0 = env->PC[env->current_tc];
1215 void op_dmfc0_tchalt (void)
1217 T0 = env->CP0_TCHalt[env->current_tc];
1221 void op_dmfc0_tccontext (void)
1223 T0 = env->CP0_TCContext[env->current_tc];
1227 void op_dmfc0_tcschedule (void)
1229 T0 = env->CP0_TCSchedule[env->current_tc];
1233 void op_dmfc0_tcschefback (void)
1235 T0 = env->CP0_TCScheFBack[env->current_tc];
1239 void op_dmfc0_lladdr (void)
1241 T0 = env->CP0_LLAddr >> 4;
1245 void op_dmfc0_watchlo (void)
1247 T0 = env->CP0_WatchLo[PARAM1];
1250 #endif /* TARGET_MIPS64 */
1252 /* MIPS MT functions */
1253 void op_mftgpr(void)
1255 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1257 T0 = env->gpr[other_tc][PARAM1];
1263 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1265 T0 = env->LO[other_tc][PARAM1];
1271 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1273 T0 = env->HI[other_tc][PARAM1];
1277 void op_mftacx(void)
1279 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1281 T0 = env->ACX[other_tc][PARAM1];
1285 void op_mftdsp(void)
1287 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1289 T0 = env->DSPControl[other_tc];
1293 void op_mttgpr(void)
1295 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1297 T0 = env->gpr[other_tc][PARAM1];
1303 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1305 T0 = env->LO[other_tc][PARAM1];
1311 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1313 T0 = env->HI[other_tc][PARAM1];
1317 void op_mttacx(void)
1319 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1321 T0 = env->ACX[other_tc][PARAM1];
1325 void op_mttdsp(void)
1327 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1329 T0 = env->DSPControl[other_tc];
1370 // TODO: store to TC register
1377 /* No scheduling policy implemented. */
1379 if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
1380 env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) {
1381 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1382 env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
1383 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
1386 } else if (T0 == 0) {
1387 if (0 /* TODO: TC underflow */) {
1388 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1389 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
1391 // TODO: Deallocate TC
1393 } else if (T0 > 0) {
1394 /* Yield qualifier inputs not implemented. */
1395 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1396 env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
1397 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
1399 T0 = env->CP0_YQMask;
1405 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
1407 # define DEBUG_FPU_STATE() do { } while(0)
1412 CALL_FROM_TB1(do_cfc1, PARAM1);
1419 CALL_FROM_TB1(do_ctc1, PARAM1);
1438 void op_dmfc1 (void)
1445 void op_dmtc1 (void)
1452 void op_mfhc1 (void)
1459 void op_mthc1 (void)
1467 Single precition routines have a "s" suffix, double precision a
1468 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
1469 paired single lowwer "pl", paired single upper "pu". */
1471 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1475 CALL_FROM_TB0(do_float_cvtd_s);
1481 CALL_FROM_TB0(do_float_cvtd_w);
1487 CALL_FROM_TB0(do_float_cvtd_l);
1493 CALL_FROM_TB0(do_float_cvtl_d);
1499 CALL_FROM_TB0(do_float_cvtl_s);
1512 CALL_FROM_TB0(do_float_cvtps_pw);
1518 CALL_FROM_TB0(do_float_cvtpw_ps);
1524 CALL_FROM_TB0(do_float_cvts_d);
1530 CALL_FROM_TB0(do_float_cvts_w);
1536 CALL_FROM_TB0(do_float_cvts_l);
1542 CALL_FROM_TB0(do_float_cvts_pl);
1548 CALL_FROM_TB0(do_float_cvts_pu);
1554 CALL_FROM_TB0(do_float_cvtw_s);
1560 CALL_FROM_TB0(do_float_cvtw_d);
1567 DT2 = ((uint64_t)WT0 << 32) | WT1;
1573 DT2 = ((uint64_t)WT0 << 32) | WTH1;
1579 DT2 = ((uint64_t)WTH0 << 32) | WT1;
1585 DT2 = ((uint64_t)WTH0 << 32) | WTH1;
1590 #define FLOAT_ROUNDOP(op, ttype, stype) \
1591 FLOAT_OP(op ## ttype, stype) \
1593 CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
1594 DEBUG_FPU_STATE(); \
1598 FLOAT_ROUNDOP(round, l, d)
1599 FLOAT_ROUNDOP(round, l, s)
1600 FLOAT_ROUNDOP(round, w, d)
1601 FLOAT_ROUNDOP(round, w, s)
1603 FLOAT_ROUNDOP(trunc, l, d)
1604 FLOAT_ROUNDOP(trunc, l, s)
1605 FLOAT_ROUNDOP(trunc, w, d)
1606 FLOAT_ROUNDOP(trunc, w, s)
1608 FLOAT_ROUNDOP(ceil, l, d)
1609 FLOAT_ROUNDOP(ceil, l, s)
1610 FLOAT_ROUNDOP(ceil, w, d)
1611 FLOAT_ROUNDOP(ceil, w, s)
1613 FLOAT_ROUNDOP(floor, l, d)
1614 FLOAT_ROUNDOP(floor, l, s)
1615 FLOAT_ROUNDOP(floor, w, d)
1616 FLOAT_ROUNDOP(floor, w, s)
1617 #undef FLOAR_ROUNDOP
1621 if (!(env->fpu->fcr31 & PARAM1))
1628 if (!(env->fpu->fcr31 & PARAM1))
1635 unsigned int mask = GET_FP_COND (env->fpu) >> PARAM1;
1645 if (env->fpu->fcr31 & PARAM1)
1652 if (env->fpu->fcr31 & PARAM1)
1659 unsigned int mask = GET_FP_COND (env->fpu) >> PARAM1;
1714 /* operations calling helpers, for s, d and ps */
1715 #define FLOAT_HOP(name) \
1718 CALL_FROM_TB0(do_float_ ## name ## _d); \
1719 DEBUG_FPU_STATE(); \
1724 CALL_FROM_TB0(do_float_ ## name ## _s); \
1725 DEBUG_FPU_STATE(); \
1728 FLOAT_OP(name, ps) \
1730 CALL_FROM_TB0(do_float_ ## name ## _ps); \
1731 DEBUG_FPU_STATE(); \
1744 /* operations calling helpers, for s and d */
1745 #define FLOAT_HOP(name) \
1748 CALL_FROM_TB0(do_float_ ## name ## _d); \
1749 DEBUG_FPU_STATE(); \
1754 CALL_FROM_TB0(do_float_ ## name ## _s); \
1755 DEBUG_FPU_STATE(); \
1762 /* operations calling helpers, for ps */
1763 #define FLOAT_HOP(name) \
1764 FLOAT_OP(name, ps) \
1766 CALL_FROM_TB0(do_float_ ## name ## _ps); \
1767 DEBUG_FPU_STATE(); \
1774 /* ternary operations */
1775 #define FLOAT_TERNOP(name1, name2) \
1776 FLOAT_OP(name1 ## name2, d) \
1778 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
1779 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
1780 DEBUG_FPU_STATE(); \
1783 FLOAT_OP(name1 ## name2, s) \
1785 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
1786 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
1787 DEBUG_FPU_STATE(); \
1790 FLOAT_OP(name1 ## name2, ps) \
1792 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
1793 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
1794 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
1795 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
1796 DEBUG_FPU_STATE(); \
1799 FLOAT_TERNOP(mul, add)
1800 FLOAT_TERNOP(mul, sub)
1803 /* negated ternary operations */
1804 #define FLOAT_NTERNOP(name1, name2) \
1805 FLOAT_OP(n ## name1 ## name2, d) \
1807 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
1808 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
1809 FDT2 = float64_chs(FDT2); \
1810 DEBUG_FPU_STATE(); \
1813 FLOAT_OP(n ## name1 ## name2, s) \
1815 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
1816 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
1817 FST2 = float32_chs(FST2); \
1818 DEBUG_FPU_STATE(); \
1821 FLOAT_OP(n ## name1 ## name2, ps) \
1823 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
1824 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
1825 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
1826 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
1827 FST2 = float32_chs(FST2); \
1828 FSTH2 = float32_chs(FSTH2); \
1829 DEBUG_FPU_STATE(); \
1832 FLOAT_NTERNOP(mul, add)
1833 FLOAT_NTERNOP(mul, sub)
1834 #undef FLOAT_NTERNOP
1836 /* unary operations, modifying fp status */
1837 #define FLOAT_UNOP(name) \
1840 FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
1841 DEBUG_FPU_STATE(); \
1846 FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
1847 DEBUG_FPU_STATE(); \
1853 /* unary operations, not modifying fp status */
1854 #define FLOAT_UNOP(name) \
1857 FDT2 = float64_ ## name(FDT0); \
1858 DEBUG_FPU_STATE(); \
1863 FST2 = float32_ ## name(FST0); \
1864 DEBUG_FPU_STATE(); \
1867 FLOAT_OP(name, ps) \
1869 FST2 = float32_ ## name(FST0); \
1870 FSTH2 = float32_ ## name(FSTH0); \
1871 DEBUG_FPU_STATE(); \
1905 #ifdef TARGET_WORDS_BIGENDIAN
1913 default: /* unpredictable */
1920 #ifdef CONFIG_SOFTFLOAT
1921 #define clear_invalid() do { \
1922 int flags = get_float_exception_flags(&env->fpu->fp_status); \
1923 flags &= ~float_flag_invalid; \
1924 set_float_exception_flags(flags, &env->fpu->fp_status); \
1927 #define clear_invalid() do { } while(0)
1930 extern void dump_fpu_s(CPUState *env);
1932 #define CMP_OP(fmt, op) \
1933 void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void) \
1935 CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
1936 DEBUG_FPU_STATE(); \
1939 void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void) \
1941 CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
1942 DEBUG_FPU_STATE(); \
1945 #define CMP_OPS(op) \
1971 T0 = !!(~GET_FP_COND(env->fpu) & (0x1 << PARAM1));
1975 void op_bc1any2f (void)
1977 T0 = !!(~GET_FP_COND(env->fpu) & (0x3 << PARAM1));
1981 void op_bc1any4f (void)
1983 T0 = !!(~GET_FP_COND(env->fpu) & (0xf << PARAM1));
1990 T0 = !!(GET_FP_COND(env->fpu) & (0x1 << PARAM1));
1994 void op_bc1any2t (void)
1996 T0 = !!(GET_FP_COND(env->fpu) & (0x3 << PARAM1));
2000 void op_bc1any4t (void)
2002 T0 = !!(GET_FP_COND(env->fpu) & (0xf << PARAM1));
2007 void op_tlbwi (void)
2009 CALL_FROM_TB0(env->tlb->do_tlbwi);
2013 void op_tlbwr (void)
2015 CALL_FROM_TB0(env->tlb->do_tlbwr);
2021 CALL_FROM_TB0(env->tlb->do_tlbp);
2027 CALL_FROM_TB0(env->tlb->do_tlbr);
2032 #if defined (CONFIG_USER_ONLY)
2033 void op_tls_value (void)
2035 T0 = env->tls_value;
2041 CALL_FROM_TB1(do_pmon, PARAM1);
2047 T0 = env->CP0_Status;
2048 env->CP0_Status = T0 & ~(1 << CP0St_IE);
2049 CALL_FROM_TB1(cpu_mips_update_irq, env);
2055 T0 = env->CP0_Status;
2056 env->CP0_Status = T0 | (1 << CP0St_IE);
2057 CALL_FROM_TB1(cpu_mips_update_irq, env);
2064 CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
2069 void op_debug (void)
2071 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
2075 void debug_pre_eret (void);
2076 void debug_post_eret (void);
2079 if (loglevel & CPU_LOG_EXEC)
2080 CALL_FROM_TB0(debug_pre_eret);
2081 if (env->CP0_Status & (1 << CP0St_ERL)) {
2082 env->PC[env->current_tc] = env->CP0_ErrorEPC;
2083 env->CP0_Status &= ~(1 << CP0St_ERL);
2085 env->PC[env->current_tc] = env->CP0_EPC;
2086 env->CP0_Status &= ~(1 << CP0St_EXL);
2088 CALL_FROM_TB1(compute_hflags, env);
2089 if (loglevel & CPU_LOG_EXEC)
2090 CALL_FROM_TB0(debug_post_eret);
2091 env->CP0_LLAddr = 1;
2095 void op_deret (void)
2097 if (loglevel & CPU_LOG_EXEC)
2098 CALL_FROM_TB0(debug_pre_eret);
2099 env->PC[env->current_tc] = env->CP0_DEPC;
2100 env->hflags &= MIPS_HFLAG_DM;
2101 CALL_FROM_TB1(compute_hflags, env);
2102 if (loglevel & CPU_LOG_EXEC)
2103 CALL_FROM_TB0(debug_post_eret);
2104 env->CP0_LLAddr = 1;
2108 void op_rdhwr_cpunum(void)
2110 if ((env->hflags & MIPS_HFLAG_CP0) ||
2111 (env->CP0_HWREna & (1 << 0)))
2112 T0 = env->CP0_EBase & 0x3ff;
2114 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2118 void op_rdhwr_synci_step(void)
2120 if ((env->hflags & MIPS_HFLAG_CP0) ||
2121 (env->CP0_HWREna & (1 << 1)))
2122 T0 = env->SYNCI_Step;
2124 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2128 void op_rdhwr_cc(void)
2130 if ((env->hflags & MIPS_HFLAG_CP0) ||
2131 (env->CP0_HWREna & (1 << 2)))
2132 T0 = env->CP0_Count;
2134 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2138 void op_rdhwr_ccres(void)
2140 if ((env->hflags & MIPS_HFLAG_CP0) ||
2141 (env->CP0_HWREna & (1 << 3)))
2144 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2148 void op_save_state (void)
2150 env->hflags = PARAM1;
2157 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
2161 /* Bitfield operations. */
2164 unsigned int pos = PARAM1;
2165 unsigned int size = PARAM2;
2167 T0 = (int32_t)((T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0));
2173 unsigned int pos = PARAM1;
2174 unsigned int size = PARAM2;
2175 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
2177 T0 = (int32_t)((T0 & ~mask) | ((T1 << pos) & mask));
2183 T0 = (int32_t)(((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF));
2187 #if defined(TARGET_MIPS64)
2190 unsigned int pos = PARAM1;
2191 unsigned int size = PARAM2;
2193 T0 = (T1 >> pos) & ((size < 64) ? ((1ULL << size) - 1) : ~0ULL);
2199 unsigned int pos = PARAM1;
2200 unsigned int size = PARAM2;
2201 target_ulong mask = ((size < 64) ? ((1ULL << size) - 1) : ~0ULL) << pos;
2203 T0 = (T0 & ~mask) | ((T1 << pos) & mask);
2209 T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
2215 T1 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
2216 T0 = (T1 << 32) | (T1 >> 32);