Commit 1a14026e11b9baaf5050b0bed947e1b57f10ca08

Authored by blueswir1
1 parent 96d19126

Allow NWINDOWS selection (CPU feature with model specific defaults)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4690 c046a42c-6fe2-441c-8c8c-71466251a162
hw/sun4m.c
... ... @@ -404,7 +404,7 @@ static void sun4m_hw_init(const struct hwdef *hwdef, ram_addr_t RAM_size,
404 404 qemu_register_reset(secondary_cpu_reset, env);
405 405 env->halted = 1;
406 406 }
407   - register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
  407 + register_savevm("cpu", i, 4, cpu_save, cpu_load, env);
408 408 cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS);
409 409 env->prom_addr = hwdef->slavio_base;
410 410 }
... ... @@ -579,7 +579,7 @@ static void sun4c_hw_init(const struct hwdef *hwdef, ram_addr_t RAM_size,
579 579 cpu_sparc_set_id(env, 0);
580 580  
581 581 qemu_register_reset(main_cpu_reset, env);
582   - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
  582 + register_savevm("cpu", 0, 4, cpu_save, cpu_load, env);
583 583 cpu_irqs = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
584 584 env->prom_addr = hwdef->slavio_base;
585 585  
... ... @@ -1391,7 +1391,7 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size,
1391 1391 qemu_register_reset(secondary_cpu_reset, env);
1392 1392 env->halted = 1;
1393 1393 }
1394   - register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
  1394 + register_savevm("cpu", i, 4, cpu_save, cpu_load, env);
1395 1395 cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS);
1396 1396 env->prom_addr = hwdef->slavio_base;
1397 1397 }
... ...
hw/sun4u.c
... ... @@ -260,7 +260,7 @@ static void sun4u_init(ram_addr_t RAM_size, int vga_ram_size,
260 260 bh = qemu_bh_new(hstick_irq, env);
261 261 env->hstick = ptimer_init(bh);
262 262 ptimer_set_period(env->hstick, 1ULL);
263   - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
  263 + register_savevm("cpu", 0, 4, cpu_save, cpu_load, env);
264 264 qemu_register_reset(main_cpu_reset, env);
265 265 main_cpu_reset(env);
266 266  
... ...
linux-user/main.c
... ... @@ -626,11 +626,11 @@ void cpu_loop(CPUARMState *env)
626 626 can be found at http://www.sics.se/~psm/sparcstack.html */
627 627 static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
628 628 {
629   - index = (index + cwp * 16) & (16 * NWINDOWS - 1);
  629 + index = (index + cwp * 16) % (16 * env->nwindows);
630 630 /* wrap handling : if cwp is on the last window, then we use the
631 631 registers 'after' the end */
632   - if (index < 8 && env->cwp == (NWINDOWS - 1))
633   - index += (16 * NWINDOWS);
  632 + if (index < 8 && env->cwp == env->nwindows - 1)
  633 + index += 16 * env->nwindows;
634 634 return index;
635 635 }
636 636  
... ... @@ -656,12 +656,12 @@ static void save_window(CPUSPARCState *env)
656 656 {
657 657 #ifndef TARGET_SPARC64
658 658 unsigned int new_wim;
659   - new_wim = ((env->wim >> 1) | (env->wim << (NWINDOWS - 1))) &
660   - ((1LL << NWINDOWS) - 1);
661   - save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1));
  659 + new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
  660 + ((1LL << env->nwindows) - 1);
  661 + save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
662 662 env->wim = new_wim;
663 663 #else
664   - save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1));
  664 + save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
665 665 env->cansave++;
666 666 env->canrestore--;
667 667 #endif
... ... @@ -672,11 +672,11 @@ static void restore_window(CPUSPARCState *env)
672 672 unsigned int new_wim, i, cwp1;
673 673 abi_ulong sp_ptr;
674 674  
675   - new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) &
676   - ((1LL << NWINDOWS) - 1);
  675 + new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
  676 + ((1LL << env->nwindows) - 1);
677 677  
678 678 /* restore the invalid window */
679   - cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
  679 + cwp1 = cpu_cwp_inc(env, env->cwp + 1);
680 680 sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
681 681 #if defined(DEBUG_WIN)
682 682 printf("win_underflow: sp_ptr=0x%x load_cwp=%d\n",
... ... @@ -690,8 +690,8 @@ static void restore_window(CPUSPARCState *env)
690 690 env->wim = new_wim;
691 691 #ifdef TARGET_SPARC64
692 692 env->canrestore++;
693   - if (env->cleanwin < NWINDOWS - 1)
694   - env->cleanwin++;
  693 + if (env->cleanwin < env->nwindows - 1)
  694 + env->cleanwin++;
695 695 env->cansave--;
696 696 #endif
697 697 }
... ... @@ -703,14 +703,14 @@ static void flush_windows(CPUSPARCState *env)
703 703 offset = 1;
704 704 for(;;) {
705 705 /* if restore would invoke restore_window(), then we can stop */
706   - cwp1 = (env->cwp + offset) & (NWINDOWS - 1);
  706 + cwp1 = cpu_cwp_inc(env, env->cwp + offset);
707 707 if (env->wim & (1 << cwp1))
708 708 break;
709 709 save_window_offset(env, cwp1);
710 710 offset++;
711 711 }
712 712 /* set wim so that restore will reload the registers */
713   - cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
  713 + cwp1 = cpu_cwp_inc(env, env->cwp + 1);
714 714 env->wim = 1 << cwp1;
715 715 #if defined(DEBUG_WIN)
716 716 printf("flush_windows: nb=%d\n", offset - 1);
... ...
target-sparc/TODO
... ... @@ -6,7 +6,6 @@ CPU common:
6 6 slot next page)
7 7 - Atomical instructions
8 8 - CPU features should match real CPUs (also ASI selection)
9   - - Allow choosing of NWINDOWS (CPU model specific and as a CPU feature)
10 9 - Optimizations/improvements:
11 10 - Condition code/branch handling like x86, also for FPU?
12 11 - Remove remaining explicit alignment checks
... ...
target-sparc/cpu.h
... ... @@ -170,8 +170,9 @@
170 170 #define PG_MODIFIED_MASK (1 << PG_MODIFIED_BIT)
171 171 #define PG_CACHE_MASK (1 << PG_CACHE_BIT)
172 172  
173   -/* 2 <= NWINDOWS <= 32. In QEMU it must also be a power of two. */
174   -#define NWINDOWS 8
  173 +/* 3 <= NWINDOWS <= 32. */
  174 +#define MIN_NWINDOWS 3
  175 +#define MAX_NWINDOWS 32
175 176  
176 177 #if !defined(TARGET_SPARC64)
177 178 #define NB_MMU_MODES 2
... ... @@ -222,8 +223,9 @@ typedef struct CPUSPARCState {
222 223 uint32_t mmu_cxr_mask;
223 224 uint32_t mmu_sfsr_mask;
224 225 uint32_t mmu_trcr_mask;
  226 + uint32_t nwindows;
225 227 /* NOTE: we allow 8 more registers to handle wrapping */
226   - target_ulong regbase[NWINDOWS * 16 + 8];
  228 + target_ulong regbase[MAX_NWINDOWS * 16 + 8];
227 229  
228 230 CPU_COMMON
229 231  
... ... @@ -330,6 +332,20 @@ void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
330 332  
331 333 #ifndef NO_CPU_IO_DEFS
332 334 void cpu_set_cwp(CPUSPARCState *env1, int new_cwp);
  335 +
  336 +static inline int cpu_cwp_inc(CPUSPARCState *env1, int cwp)
  337 +{
  338 + if (unlikely(cwp >= env1->nwindows))
  339 + cwp -= env1->nwindows;
  340 + return cwp;
  341 +}
  342 +
  343 +static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp)
  344 +{
  345 + if (unlikely(cwp < 0))
  346 + cwp += env1->nwindows;
  347 + return cwp;
  348 +}
333 349 #endif
334 350  
335 351 #define PUT_PSR(env, val) do { int _tmp = val; \
... ... @@ -348,9 +364,14 @@ void cpu_set_cwp(CPUSPARCState *env1, int new_cwp);
348 364 env->xcc = (_tmp >> 4) << 20; \
349 365 env->psr = (_tmp & 0xf) << 20; \
350 366 } while (0)
351   -#define GET_CWP64(env) (NWINDOWS - 1 - (env)->cwp)
352   -#define PUT_CWP64(env, val) \
353   - cpu_set_cwp(env, NWINDOWS - 1 - ((val) & (NWINDOWS - 1)))
  367 +#define GET_CWP64(env) (env->nwindows - 1 - (env)->cwp)
  368 +
  369 +static inline void PUT_CWP64(CPUSPARCState *env1, int cwp)
  370 +{
  371 + if (unlikely(cwp >= env1->nwindows || cwp < 0))
  372 + cwp = 0;
  373 + cpu_set_cwp(env1, env1->nwindows - 1 - cwp);
  374 +}
354 375  
355 376 #endif
356 377  
... ...
target-sparc/helper.c
... ... @@ -47,6 +47,7 @@ struct sparc_def_t {
47 47 uint32_t mmu_sfsr_mask;
48 48 uint32_t mmu_trcr_mask;
49 49 uint32_t features;
  50 + uint32_t nwindows;
50 51 };
51 52  
52 53 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
... ... @@ -750,11 +751,11 @@ void do_interrupt(CPUState *env)
750 751 change_pstate(PS_PEF | PS_PRIV | PS_AG);
751 752  
752 753 if (intno == TT_CLRWIN)
753   - cpu_set_cwp(env, (env->cwp - 1) & (NWINDOWS - 1));
  754 + cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
754 755 else if ((intno & 0x1c0) == TT_SPILL)
755   - cpu_set_cwp(env, (env->cwp - env->cansave - 2) & (NWINDOWS - 1));
  756 + cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
756 757 else if ((intno & 0x1c0) == TT_FILL)
757   - cpu_set_cwp(env, (env->cwp + 1) & (NWINDOWS - 1));
  758 + cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
758 759 env->tbr &= ~0x7fffULL;
759 760 env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
760 761 if (env->tl < MAXTL - 1) {
... ... @@ -853,7 +854,7 @@ void do_interrupt(CPUState *env)
853 854 }
854 855 #endif
855 856 env->psret = 0;
856   - cwp = (env->cwp - 1) & (NWINDOWS - 1);
  857 + cwp = cpu_cwp_dec(env, env->cwp - 1);
857 858 cpu_set_cwp(env, cwp);
858 859 env->regwptr[9] = env->pc;
859 860 env->regwptr[10] = env->npc;
... ... @@ -887,8 +888,8 @@ void cpu_reset(CPUSPARCState *env)
887 888 #if defined(CONFIG_USER_ONLY)
888 889 env->user_mode_only = 1;
889 890 #ifdef TARGET_SPARC64
890   - env->cleanwin = NWINDOWS - 2;
891   - env->cansave = NWINDOWS - 2;
  891 + env->cleanwin = env->nwindows - 2;
  892 + env->cansave = env->nwindows - 2;
892 893 env->pstate = PS_RMO | PS_PEF | PS_IE;
893 894 env->asi = 0x82; // Primary no-fault
894 895 #endif
... ... @@ -921,6 +922,7 @@ static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
921 922 env->cpu_model_str = cpu_model;
922 923 env->version = def->iu_version;
923 924 env->fsr = def->fpu_version;
  925 + env->nwindows = def->nwindows;
924 926 #if !defined(TARGET_SPARC64)
925 927 env->mmu_bm = def->mmu_bm;
926 928 env->mmu_ctpr_mask = def->mmu_ctpr_mask;
... ... @@ -929,6 +931,8 @@ static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
929 931 env->mmu_trcr_mask = def->mmu_trcr_mask;
930 932 env->mmuregs[0] |= def->mmu_version;
931 933 cpu_sparc_set_id(env, 0);
  934 +#else
  935 + env->version |= def->nwindows - 1;
932 936 #endif
933 937 return 0;
934 938 }
... ... @@ -970,121 +974,136 @@ static const sparc_def_t sparc_defs[] = {
970 974 {
971 975 .name = "Fujitsu Sparc64",
972 976 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)
973   - | (MAXTL << 8) | (NWINDOWS - 1)),
  977 + | (MAXTL << 8)),
974 978 .fpu_version = 0x00000000,
975 979 .mmu_version = 0,
  980 + .nwindows = 4,
976 981 .features = CPU_DEFAULT_FEATURES,
977 982 },
978 983 {
979 984 .name = "Fujitsu Sparc64 III",
980 985 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)
981   - | (MAXTL << 8) | (NWINDOWS - 1)),
  986 + | (MAXTL << 8)),
982 987 .fpu_version = 0x00000000,
983 988 .mmu_version = 0,
  989 + .nwindows = 5,
984 990 .features = CPU_DEFAULT_FEATURES,
985 991 },
986 992 {
987 993 .name = "Fujitsu Sparc64 IV",
988 994 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)
989   - | (MAXTL << 8) | (NWINDOWS - 1)),
  995 + | (MAXTL << 8)),
990 996 .fpu_version = 0x00000000,
991 997 .mmu_version = 0,
  998 + .nwindows = 8,
992 999 .features = CPU_DEFAULT_FEATURES,
993 1000 },
994 1001 {
995 1002 .name = "Fujitsu Sparc64 V",
996 1003 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)
997   - | (MAXTL << 8) | (NWINDOWS - 1)),
  1004 + | (MAXTL << 8)),
998 1005 .fpu_version = 0x00000000,
999 1006 .mmu_version = 0,
  1007 + .nwindows = 8,
1000 1008 .features = CPU_DEFAULT_FEATURES,
1001 1009 },
1002 1010 {
1003 1011 .name = "TI UltraSparc I",
1004 1012 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)
1005   - | (MAXTL << 8) | (NWINDOWS - 1)),
  1013 + | (MAXTL << 8)),
1006 1014 .fpu_version = 0x00000000,
1007 1015 .mmu_version = 0,
  1016 + .nwindows = 8,
1008 1017 .features = CPU_DEFAULT_FEATURES,
1009 1018 },
1010 1019 {
1011 1020 .name = "TI UltraSparc II",
1012 1021 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)
1013   - | (MAXTL << 8) | (NWINDOWS - 1)),
  1022 + | (MAXTL << 8)),
1014 1023 .fpu_version = 0x00000000,
1015 1024 .mmu_version = 0,
  1025 + .nwindows = 8,
1016 1026 .features = CPU_DEFAULT_FEATURES,
1017 1027 },
1018 1028 {
1019 1029 .name = "TI UltraSparc IIi",
1020 1030 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)
1021   - | (MAXTL << 8) | (NWINDOWS - 1)),
  1031 + | (MAXTL << 8)),
1022 1032 .fpu_version = 0x00000000,
1023 1033 .mmu_version = 0,
  1034 + .nwindows = 8,
1024 1035 .features = CPU_DEFAULT_FEATURES,
1025 1036 },
1026 1037 {
1027 1038 .name = "TI UltraSparc IIe",
1028 1039 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)
1029   - | (MAXTL << 8) | (NWINDOWS - 1)),
  1040 + | (MAXTL << 8)),
1030 1041 .fpu_version = 0x00000000,
1031 1042 .mmu_version = 0,
  1043 + .nwindows = 8,
1032 1044 .features = CPU_DEFAULT_FEATURES,
1033 1045 },
1034 1046 {
1035 1047 .name = "Sun UltraSparc III",
1036 1048 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)
1037   - | (MAXTL << 8) | (NWINDOWS - 1)),
  1049 + | (MAXTL << 8)),
1038 1050 .fpu_version = 0x00000000,
1039 1051 .mmu_version = 0,
  1052 + .nwindows = 8,
1040 1053 .features = CPU_DEFAULT_FEATURES,
1041 1054 },
1042 1055 {
1043 1056 .name = "Sun UltraSparc III Cu",
1044 1057 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)
1045   - | (MAXTL << 8) | (NWINDOWS - 1)),
  1058 + | (MAXTL << 8)),
1046 1059 .fpu_version = 0x00000000,
1047 1060 .mmu_version = 0,
  1061 + .nwindows = 8,
1048 1062 .features = CPU_DEFAULT_FEATURES,
1049 1063 },
1050 1064 {
1051 1065 .name = "Sun UltraSparc IIIi",
1052 1066 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)
1053   - | (MAXTL << 8) | (NWINDOWS - 1)),
  1067 + | (MAXTL << 8)),
1054 1068 .fpu_version = 0x00000000,
1055 1069 .mmu_version = 0,
  1070 + .nwindows = 8,
1056 1071 .features = CPU_DEFAULT_FEATURES,
1057 1072 },
1058 1073 {
1059 1074 .name = "Sun UltraSparc IV",
1060 1075 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)
1061   - | (MAXTL << 8) | (NWINDOWS - 1)),
  1076 + | (MAXTL << 8)),
1062 1077 .fpu_version = 0x00000000,
1063 1078 .mmu_version = 0,
  1079 + .nwindows = 8,
1064 1080 .features = CPU_DEFAULT_FEATURES,
1065 1081 },
1066 1082 {
1067 1083 .name = "Sun UltraSparc IV+",
1068 1084 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)
1069   - | (MAXTL << 8) | (NWINDOWS - 1)),
  1085 + | (MAXTL << 8)),
1070 1086 .fpu_version = 0x00000000,
1071 1087 .mmu_version = 0,
  1088 + .nwindows = 8,
1072 1089 .features = CPU_DEFAULT_FEATURES,
1073 1090 },
1074 1091 {
1075 1092 .name = "Sun UltraSparc IIIi+",
1076 1093 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)
1077   - | (MAXTL << 8) | (NWINDOWS - 1)),
  1094 + | (MAXTL << 8)),
1078 1095 .fpu_version = 0x00000000,
1079 1096 .mmu_version = 0,
  1097 + .nwindows = 8,
1080 1098 .features = CPU_DEFAULT_FEATURES,
1081 1099 },
1082 1100 {
1083 1101 .name = "NEC UltraSparc I",
1084 1102 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)
1085   - | (MAXTL << 8) | (NWINDOWS - 1)),
  1103 + | (MAXTL << 8)),
1086 1104 .fpu_version = 0x00000000,
1087 1105 .mmu_version = 0,
  1106 + .nwindows = 8,
1088 1107 .features = CPU_DEFAULT_FEATURES,
1089 1108 },
1090 1109 #else
... ... @@ -1098,6 +1117,7 @@ static const sparc_def_t sparc_defs[] = {
1098 1117 .mmu_cxr_mask = 0x0000003f,
1099 1118 .mmu_sfsr_mask = 0xffffffff,
1100 1119 .mmu_trcr_mask = 0xffffffff,
  1120 + .nwindows = 7,
1101 1121 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
1102 1122 },
1103 1123 {
... ... @@ -1110,6 +1130,7 @@ static const sparc_def_t sparc_defs[] = {
1110 1130 .mmu_cxr_mask = 0x000000ff,
1111 1131 .mmu_sfsr_mask = 0x00016fff,
1112 1132 .mmu_trcr_mask = 0x00ffffff,
  1133 + .nwindows = 8,
1113 1134 .features = CPU_DEFAULT_FEATURES,
1114 1135 },
1115 1136 {
... ... @@ -1122,6 +1143,7 @@ static const sparc_def_t sparc_defs[] = {
1122 1143 .mmu_cxr_mask = 0x000000ff,
1123 1144 .mmu_sfsr_mask = 0x00016fff,
1124 1145 .mmu_trcr_mask = 0xffffffff,
  1146 + .nwindows = 8,
1125 1147 .features = CPU_DEFAULT_FEATURES,
1126 1148 },
1127 1149 {
... ... @@ -1134,6 +1156,7 @@ static const sparc_def_t sparc_defs[] = {
1134 1156 .mmu_cxr_mask = 0x0000003f,
1135 1157 .mmu_sfsr_mask = 0xffffffff,
1136 1158 .mmu_trcr_mask = 0xffffffff,
  1159 + .nwindows = 8,
1137 1160 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1138 1161 CPU_FEATURE_FSMULD,
1139 1162 },
... ... @@ -1147,6 +1170,7 @@ static const sparc_def_t sparc_defs[] = {
1147 1170 .mmu_cxr_mask = 0x0000003f,
1148 1171 .mmu_sfsr_mask = 0xffffffff,
1149 1172 .mmu_trcr_mask = 0xffffffff,
  1173 + .nwindows = 8,
1150 1174 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1151 1175 CPU_FEATURE_FSMULD,
1152 1176 },
... ... @@ -1160,6 +1184,7 @@ static const sparc_def_t sparc_defs[] = {
1160 1184 .mmu_cxr_mask = 0x0000003f,
1161 1185 .mmu_sfsr_mask = 0xffffffff,
1162 1186 .mmu_trcr_mask = 0xffffffff,
  1187 + .nwindows = 8,
1163 1188 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1164 1189 CPU_FEATURE_FSMULD,
1165 1190 },
... ... @@ -1173,6 +1198,7 @@ static const sparc_def_t sparc_defs[] = {
1173 1198 .mmu_cxr_mask = 0x0000ffff,
1174 1199 .mmu_sfsr_mask = 0xffffffff,
1175 1200 .mmu_trcr_mask = 0xffffffff,
  1201 + .nwindows = 8,
1176 1202 .features = CPU_DEFAULT_FEATURES,
1177 1203 },
1178 1204 {
... ... @@ -1185,6 +1211,7 @@ static const sparc_def_t sparc_defs[] = {
1185 1211 .mmu_cxr_mask = 0x0000003f,
1186 1212 .mmu_sfsr_mask = 0x00016fff,
1187 1213 .mmu_trcr_mask = 0x0000003f,
  1214 + .nwindows = 7,
1188 1215 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1189 1216 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1190 1217 CPU_FEATURE_FMUL,
... ... @@ -1199,6 +1226,7 @@ static const sparc_def_t sparc_defs[] = {
1199 1226 .mmu_cxr_mask = 0x000000ff,
1200 1227 .mmu_sfsr_mask = 0x00016fff,
1201 1228 .mmu_trcr_mask = 0x00ffffff,
  1229 + .nwindows = 8,
1202 1230 .features = CPU_DEFAULT_FEATURES,
1203 1231 },
1204 1232 {
... ... @@ -1211,6 +1239,7 @@ static const sparc_def_t sparc_defs[] = {
1211 1239 .mmu_cxr_mask = 0x000000ff,
1212 1240 .mmu_sfsr_mask = 0x00016bff,
1213 1241 .mmu_trcr_mask = 0x00ffffff,
  1242 + .nwindows = 8,
1214 1243 .features = CPU_DEFAULT_FEATURES,
1215 1244 },
1216 1245 {
... ... @@ -1223,6 +1252,7 @@ static const sparc_def_t sparc_defs[] = {
1223 1252 .mmu_cxr_mask = 0x0000ffff,
1224 1253 .mmu_sfsr_mask = 0xffffffff,
1225 1254 .mmu_trcr_mask = 0xffffffff,
  1255 + .nwindows = 8,
1226 1256 .features = CPU_DEFAULT_FEATURES,
1227 1257 },
1228 1258 {
... ... @@ -1235,6 +1265,7 @@ static const sparc_def_t sparc_defs[] = {
1235 1265 .mmu_cxr_mask = 0x0000ffff,
1236 1266 .mmu_sfsr_mask = 0xffffffff,
1237 1267 .mmu_trcr_mask = 0xffffffff,
  1268 + .nwindows = 8,
1238 1269 .features = CPU_DEFAULT_FEATURES,
1239 1270 },
1240 1271 {
... ... @@ -1247,6 +1278,7 @@ static const sparc_def_t sparc_defs[] = {
1247 1278 .mmu_cxr_mask = 0x0000ffff,
1248 1279 .mmu_sfsr_mask = 0xffffffff,
1249 1280 .mmu_trcr_mask = 0xffffffff,
  1281 + .nwindows = 8,
1250 1282 .features = CPU_DEFAULT_FEATURES,
1251 1283 },
1252 1284 {
... ... @@ -1259,6 +1291,7 @@ static const sparc_def_t sparc_defs[] = {
1259 1291 .mmu_cxr_mask = 0x0000ffff,
1260 1292 .mmu_sfsr_mask = 0xffffffff,
1261 1293 .mmu_trcr_mask = 0xffffffff,
  1294 + .nwindows = 8,
1262 1295 .features = CPU_DEFAULT_FEATURES,
1263 1296 },
1264 1297 {
... ... @@ -1271,6 +1304,7 @@ static const sparc_def_t sparc_defs[] = {
1271 1304 .mmu_cxr_mask = 0x0000ffff,
1272 1305 .mmu_sfsr_mask = 0xffffffff,
1273 1306 .mmu_trcr_mask = 0xffffffff,
  1307 + .nwindows = 8,
1274 1308 .features = CPU_DEFAULT_FEATURES,
1275 1309 },
1276 1310 {
... ... @@ -1283,6 +1317,7 @@ static const sparc_def_t sparc_defs[] = {
1283 1317 .mmu_cxr_mask = 0x0000003f,
1284 1318 .mmu_sfsr_mask = 0xffffffff,
1285 1319 .mmu_trcr_mask = 0xffffffff,
  1320 + .nwindows = 8,
1286 1321 .features = CPU_DEFAULT_FEATURES,
1287 1322 },
1288 1323 {
... ... @@ -1295,6 +1330,7 @@ static const sparc_def_t sparc_defs[] = {
1295 1330 .mmu_cxr_mask = 0x0000003f,
1296 1331 .mmu_sfsr_mask = 0xffffffff,
1297 1332 .mmu_trcr_mask = 0xffffffff,
  1333 + .nwindows = 8,
1298 1334 .features = CPU_DEFAULT_FEATURES,
1299 1335 },
1300 1336 {
... ... @@ -1307,6 +1343,7 @@ static const sparc_def_t sparc_defs[] = {
1307 1343 .mmu_cxr_mask = 0x0000003f,
1308 1344 .mmu_sfsr_mask = 0xffffffff,
1309 1345 .mmu_trcr_mask = 0xffffffff,
  1346 + .nwindows = 8,
1310 1347 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1311 1348 CPU_FEATURE_FSMULD,
1312 1349 },
... ... @@ -1320,6 +1357,7 @@ static const sparc_def_t sparc_defs[] = {
1320 1357 .mmu_cxr_mask = 0x0000003f,
1321 1358 .mmu_sfsr_mask = 0xffffffff,
1322 1359 .mmu_trcr_mask = 0xffffffff,
  1360 + .nwindows = 8,
1323 1361 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1324 1362 CPU_FEATURE_FSMULD,
1325 1363 },
... ... @@ -1333,6 +1371,7 @@ static const sparc_def_t sparc_defs[] = {
1333 1371 .mmu_cxr_mask = 0x0000003f,
1334 1372 .mmu_sfsr_mask = 0xffffffff,
1335 1373 .mmu_trcr_mask = 0xffffffff,
  1374 + .nwindows = 8,
1336 1375 .features = CPU_DEFAULT_FEATURES,
1337 1376 },
1338 1377 {
... ... @@ -1345,6 +1384,7 @@ static const sparc_def_t sparc_defs[] = {
1345 1384 .mmu_cxr_mask = 0x0000003f,
1346 1385 .mmu_sfsr_mask = 0xffffffff,
1347 1386 .mmu_trcr_mask = 0xffffffff,
  1387 + .nwindows = 8,
1348 1388 .features = CPU_DEFAULT_FEATURES,
1349 1389 },
1350 1390 {
... ... @@ -1357,6 +1397,7 @@ static const sparc_def_t sparc_defs[] = {
1357 1397 .mmu_cxr_mask = 0x0000003f,
1358 1398 .mmu_sfsr_mask = 0xffffffff,
1359 1399 .mmu_trcr_mask = 0xffffffff,
  1400 + .nwindows = 8,
1360 1401 .features = CPU_DEFAULT_FEATURES,
1361 1402 },
1362 1403 #endif
... ... @@ -1411,7 +1452,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1411 1452 uint32_t plus_features = 0;
1412 1453 uint32_t minus_features = 0;
1413 1454 long long iu_version;
1414   - uint32_t fpu_version, mmu_version;
  1455 + uint32_t fpu_version, mmu_version, nwindows;
1415 1456  
1416 1457 for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1417 1458 if (strcasecmp(name, sparc_defs[i].name) == 0) {
... ... @@ -1468,6 +1509,19 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1468 1509 #ifdef DEBUG_FEATURES
1469 1510 fprintf(stderr, "mmu_version %llx\n", mmu_version);
1470 1511 #endif
  1512 + } else if (!strcmp(featurestr, "nwindows")) {
  1513 + char *err;
  1514 +
  1515 + nwindows = strtol(val, &err, 0);
  1516 + if (!*val || *err || nwindows > MAX_NWINDOWS ||
  1517 + nwindows < MIN_NWINDOWS) {
  1518 + fprintf(stderr, "bad numerical value %s\n", val);
  1519 + goto error;
  1520 + }
  1521 + cpu_def->nwindows = nwindows;
  1522 +#ifdef DEBUG_FEATURES
  1523 + fprintf(stderr, "nwindows %d\n", nwindows);
  1524 +#endif
1471 1525 } else {
1472 1526 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1473 1527 goto error;
... ... @@ -1497,11 +1551,12 @@ void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1497 1551 unsigned int i;
1498 1552  
1499 1553 for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1500   - (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x ",
  1554 + (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1501 1555 sparc_defs[i].name,
1502 1556 sparc_defs[i].iu_version,
1503 1557 sparc_defs[i].fpu_version,
1504   - sparc_defs[i].mmu_version);
  1558 + sparc_defs[i].mmu_version,
  1559 + sparc_defs[i].nwindows);
1505 1560 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1506 1561 ~sparc_defs[i].features, "-");
1507 1562 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
... ... @@ -1512,7 +1567,7 @@ void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1512 1567 print_features(f, cpu_fprintf, -1, NULL);
1513 1568 (*cpu_fprintf)(f, "\n");
1514 1569 (*cpu_fprintf)(f, "Numerical features (=): iu_version fpu_version "
1515   - "mmu_version\n");
  1570 + "mmu_version nwindows\n");
1516 1571 }
1517 1572  
1518 1573 #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
... ... @@ -1558,7 +1613,7 @@ void cpu_dump_state(CPUState *env, FILE *f,
1558 1613 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
1559 1614 "cleanwin %d cwp %d\n",
1560 1615 env->cansave, env->canrestore, env->otherwin, env->wstate,
1561   - env->cleanwin, NWINDOWS - 1 - env->cwp);
  1616 + env->cleanwin, env->nwindows - 1 - env->cwp);
1562 1617 #else
1563 1618 cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
1564 1619 GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
... ...
target-sparc/machine.c
... ... @@ -31,7 +31,8 @@ void cpu_save(QEMUFile *f, void *opaque)
31 31  
32 32 for(i = 0; i < 8; i++)
33 33 qemu_put_betls(f, &env->gregs[i]);
34   - for(i = 0; i < NWINDOWS * 16; i++)
  34 + qemu_put_be32s(f, &env->nwindows);
  35 + for(i = 0; i < env->nwindows * 16; i++)
35 36 qemu_put_betls(f, &env->regbase[i]);
36 37  
37 38 /* FPU */
... ... @@ -65,9 +66,12 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
65 66 int i;
66 67 uint32_t tmp;
67 68  
  69 + if (version_id != 4)
  70 + return -EINVAL;
68 71 for(i = 0; i < 8; i++)
69 72 qemu_get_betls(f, &env->gregs[i]);
70   - for(i = 0; i < NWINDOWS * 16; i++)
  73 + qemu_get_be32s(f, &env->nwindows);
  74 + for(i = 0; i < env->nwindows * 16; i++)
71 75 qemu_get_betls(f, &env->regbase[i]);
72 76  
73 77 /* FPU */
... ...
target-sparc/op_helper.c
... ... @@ -2178,7 +2178,7 @@ void helper_rett(void)
2178 2178 raise_exception(TT_ILL_INSN);
2179 2179  
2180 2180 env->psret = 1;
2181   - cwp = (env->cwp + 1) & (NWINDOWS - 1);
  2181 + cwp = cpu_cwp_inc(env, env->cwp + 1) ;
2182 2182 if (env->wim & (1 << cwp)) {
2183 2183 raise_exception(TT_WIN_UNF);
2184 2184 }
... ... @@ -2399,7 +2399,7 @@ void helper_save(void)
2399 2399 {
2400 2400 uint32_t cwp;
2401 2401  
2402   - cwp = (env->cwp - 1) & (NWINDOWS - 1);
  2402 + cwp = cpu_cwp_dec(env, env->cwp - 1);
2403 2403 if (env->wim & (1 << cwp)) {
2404 2404 raise_exception(TT_WIN_OVF);
2405 2405 }
... ... @@ -2410,7 +2410,7 @@ void helper_restore(void)
2410 2410 {
2411 2411 uint32_t cwp;
2412 2412  
2413   - cwp = (env->cwp + 1) & (NWINDOWS - 1);
  2413 + cwp = cpu_cwp_inc(env, env->cwp + 1);
2414 2414 if (env->wim & (1 << cwp)) {
2415 2415 raise_exception(TT_WIN_UNF);
2416 2416 }
... ... @@ -2419,7 +2419,7 @@ void helper_restore(void)
2419 2419  
2420 2420 void helper_wrpsr(target_ulong new_psr)
2421 2421 {
2422   - if ((new_psr & PSR_CWP) >= NWINDOWS)
  2422 + if ((new_psr & PSR_CWP) >= env->nwindows)
2423 2423 raise_exception(TT_ILL_INSN);
2424 2424 else
2425 2425 PUT_PSR(env, new_psr);
... ... @@ -2437,7 +2437,7 @@ void helper_save(void)
2437 2437 {
2438 2438 uint32_t cwp;
2439 2439  
2440   - cwp = (env->cwp - 1) & (NWINDOWS - 1);
  2440 + cwp = cpu_cwp_dec(env, env->cwp - 1);
2441 2441 if (env->cansave == 0) {
2442 2442 raise_exception(TT_SPILL | (env->otherwin != 0 ?
2443 2443 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
... ... @@ -2458,7 +2458,7 @@ void helper_restore(void)
2458 2458 {
2459 2459 uint32_t cwp;
2460 2460  
2461   - cwp = (env->cwp + 1) & (NWINDOWS - 1);
  2461 + cwp = cpu_cwp_inc(env, env->cwp + 1);
2462 2462 if (env->canrestore == 0) {
2463 2463 raise_exception(TT_FILL | (env->otherwin != 0 ?
2464 2464 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
... ... @@ -2472,7 +2472,7 @@ void helper_restore(void)
2472 2472  
2473 2473 void helper_flushw(void)
2474 2474 {
2475   - if (env->cansave != NWINDOWS - 2) {
  2475 + if (env->cansave != env->nwindows - 2) {
2476 2476 raise_exception(TT_SPILL | (env->otherwin != 0 ?
2477 2477 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2478 2478 ((env->wstate & 0x7) << 2)));
... ... @@ -2491,7 +2491,7 @@ void helper_saved(void)
2491 2491 void helper_restored(void)
2492 2492 {
2493 2493 env->canrestore++;
2494   - if (env->cleanwin < NWINDOWS - 1)
  2494 + if (env->cleanwin < env->nwindows - 1)
2495 2495 env->cleanwin++;
2496 2496 if (env->otherwin == 0)
2497 2497 env->cansave--;
... ... @@ -2622,12 +2622,12 @@ void helper_retry(void)
2622 2622 void cpu_set_cwp(CPUState *env1, int new_cwp)
2623 2623 {
2624 2624 /* put the modified wrap registers at their proper location */
2625   - if (env1->cwp == (NWINDOWS - 1))
2626   - memcpy32(env1->regbase, env1->regbase + NWINDOWS * 16);
  2625 + if (env1->cwp == env->nwindows - 1)
  2626 + memcpy32(env1->regbase, env1->regbase + env->nwindows * 16);
2627 2627 env1->cwp = new_cwp;
2628 2628 /* put the wrap registers at their temporary location */
2629   - if (new_cwp == (NWINDOWS - 1))
2630   - memcpy32(env1->regbase + NWINDOWS * 16, env1->regbase);
  2629 + if (new_cwp == env->nwindows - 1)
  2630 + memcpy32(env1->regbase + env->nwindows * 16, env1->regbase);
2631 2631 env1->regwptr = env1->regbase + (new_cwp * 16);
2632 2632 }
2633 2633  
... ...
target-sparc/translate.c
... ... @@ -3442,8 +3442,6 @@ static void disas_sparc_insn(DisasContext * dc)
3442 3442 goto illegal_insn;
3443 3443 }
3444 3444 #else
3445   - tcg_gen_andi_tl(cpu_dst, cpu_dst,
3446   - ((1 << NWINDOWS) - 1));
3447 3445 tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
3448 3446 tcg_gen_st_i32(cpu_tmp32, cpu_env,
3449 3447 offsetof(CPUSPARCState, wim));
... ...