1ab3b491fSBlue Swirl /* 2ab3b491fSBlue Swirl * Sparc CPU init helpers 3ab3b491fSBlue Swirl * 4ab3b491fSBlue Swirl * Copyright (c) 2003-2005 Fabrice Bellard 5ab3b491fSBlue Swirl * 6ab3b491fSBlue Swirl * This library is free software; you can redistribute it and/or 7ab3b491fSBlue Swirl * modify it under the terms of the GNU Lesser General Public 8ab3b491fSBlue Swirl * License as published by the Free Software Foundation; either 9ab3b491fSBlue Swirl * version 2 of the License, or (at your option) any later version. 10ab3b491fSBlue Swirl * 11ab3b491fSBlue Swirl * This library is distributed in the hope that it will be useful, 12ab3b491fSBlue Swirl * but WITHOUT ANY WARRANTY; without even the implied warranty of 13ab3b491fSBlue Swirl * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14ab3b491fSBlue Swirl * Lesser General Public License for more details. 15ab3b491fSBlue Swirl * 16ab3b491fSBlue Swirl * You should have received a copy of the GNU Lesser General Public 17ab3b491fSBlue Swirl * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18ab3b491fSBlue Swirl */ 19ab3b491fSBlue Swirl 20db5ebe5fSPeter Maydell #include "qemu/osdep.h" 21da34e65cSMarkus Armbruster #include "qapi/error.h" 22ab3b491fSBlue Swirl #include "cpu.h" 23db5d39f7SAndreas Färber #include "qemu/error-report.h" 2463c91552SPaolo Bonzini #include "exec/exec-all.h" 25*de05005bSIgor Mammedov #include "hw/qdev-properties.h" 26*de05005bSIgor Mammedov #include "qapi/visitor.h" 27ab3b491fSBlue Swirl 28ab3b491fSBlue Swirl //#define DEBUG_FEATURES 29ab3b491fSBlue Swirl 30ab7ab3d7SAndreas Färber /* CPUClass::reset() */ 31ab7ab3d7SAndreas Färber static void sparc_cpu_reset(CPUState *s) 32ab7ab3d7SAndreas Färber { 33ab7ab3d7SAndreas Färber SPARCCPU *cpu = SPARC_CPU(s); 34ab7ab3d7SAndreas Färber SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu); 35ab7ab3d7SAndreas Färber CPUSPARCState *env = &cpu->env; 36ab7ab3d7SAndreas Färber 37ab7ab3d7SAndreas Färber scc->parent_reset(s); 38ab7ab3d7SAndreas Färber 391f5c00cfSAlex Bennée memset(env, 0, offsetof(CPUSPARCState, end_reset_fields)); 40ab3b491fSBlue Swirl env->cwp = 0; 41ab3b491fSBlue Swirl #ifndef TARGET_SPARC64 42ab3b491fSBlue Swirl env->wim = 1; 43ab3b491fSBlue Swirl #endif 44ab3b491fSBlue Swirl env->regwptr = env->regbase + (env->cwp * 16); 45ab3b491fSBlue Swirl CC_OP = CC_OP_FLAGS; 46ab3b491fSBlue Swirl #if defined(CONFIG_USER_ONLY) 47ab3b491fSBlue Swirl #ifdef TARGET_SPARC64 48ab3b491fSBlue Swirl env->cleanwin = env->nwindows - 2; 49ab3b491fSBlue Swirl env->cansave = env->nwindows - 2; 50ab3b491fSBlue Swirl env->pstate = PS_RMO | PS_PEF | PS_IE; 51ab3b491fSBlue Swirl env->asi = 0x82; /* Primary no-fault */ 52ab3b491fSBlue Swirl #endif 53ab3b491fSBlue Swirl #else 54ab3b491fSBlue Swirl #if !defined(TARGET_SPARC64) 55ab3b491fSBlue Swirl env->psret = 0; 56ab3b491fSBlue Swirl env->psrs = 1; 57ab3b491fSBlue Swirl env->psrps = 1; 58ab3b491fSBlue Swirl #endif 59ab3b491fSBlue Swirl #ifdef TARGET_SPARC64 60cbc3a6a4SArtyom Tarasenko env->pstate = PS_PRIV | PS_RED | PS_PEF; 61cbc3a6a4SArtyom Tarasenko if (!cpu_has_hypervisor(env)) { 62cbc3a6a4SArtyom Tarasenko env->pstate |= PS_AG; 63cbc3a6a4SArtyom Tarasenko } 64ab3b491fSBlue Swirl env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0; 65ab3b491fSBlue Swirl env->tl = env->maxtl; 66cbc3a6a4SArtyom Tarasenko env->gl = 2; 67ab3b491fSBlue Swirl cpu_tsptr(env)->tt = TT_POWER_ON_RESET; 68ab3b491fSBlue Swirl env->lsu = 0; 69ab3b491fSBlue Swirl #else 70ab3b491fSBlue Swirl env->mmuregs[0] &= ~(MMU_E | MMU_NF); 71576e1c4cSIgor Mammedov env->mmuregs[0] |= env->def.mmu_bm; 72ab3b491fSBlue Swirl #endif 73ab3b491fSBlue Swirl env->pc = 0; 74ab3b491fSBlue Swirl env->npc = env->pc + 4; 75ab3b491fSBlue Swirl #endif 76ab3b491fSBlue Swirl env->cache_control = 0; 77ab3b491fSBlue Swirl } 78ab3b491fSBlue Swirl 7987afe467SRichard Henderson static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request) 8087afe467SRichard Henderson { 8187afe467SRichard Henderson if (interrupt_request & CPU_INTERRUPT_HARD) { 8287afe467SRichard Henderson SPARCCPU *cpu = SPARC_CPU(cs); 8387afe467SRichard Henderson CPUSPARCState *env = &cpu->env; 8487afe467SRichard Henderson 8587afe467SRichard Henderson if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) { 8687afe467SRichard Henderson int pil = env->interrupt_index & 0xf; 8787afe467SRichard Henderson int type = env->interrupt_index & 0xf0; 8887afe467SRichard Henderson 8987afe467SRichard Henderson if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) { 9087afe467SRichard Henderson cs->exception_index = env->interrupt_index; 9187afe467SRichard Henderson sparc_cpu_do_interrupt(cs); 9287afe467SRichard Henderson return true; 9387afe467SRichard Henderson } 9487afe467SRichard Henderson } 9587afe467SRichard Henderson } 9687afe467SRichard Henderson return false; 9787afe467SRichard Henderson } 9887afe467SRichard Henderson 99df0900ebSPeter Crosthwaite static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info) 100df0900ebSPeter Crosthwaite { 101df0900ebSPeter Crosthwaite info->print_insn = print_insn_sparc; 102df0900ebSPeter Crosthwaite #ifdef TARGET_SPARC64 103df0900ebSPeter Crosthwaite info->mach = bfd_mach_sparc_v9b; 104df0900ebSPeter Crosthwaite #endif 105df0900ebSPeter Crosthwaite } 106df0900ebSPeter Crosthwaite 107fb02d56eSIgor Mammedov static void sparc_cpu_parse_features(CPUState *cs, char *features, 108fb02d56eSIgor Mammedov Error **errp); 109fb02d56eSIgor Mammedov 110433ac7a9SAndreas Färber static int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model) 111ab3b491fSBlue Swirl { 112433ac7a9SAndreas Färber CPUSPARCState *env = &cpu->env; 113433ac7a9SAndreas Färber char *s = g_strdup(cpu_model); 11412a6c15eSIgor Mammedov char *featurestr = strtok(s, ","); 115433ac7a9SAndreas Färber Error *err = NULL; 116ab3b491fSBlue Swirl 117433ac7a9SAndreas Färber featurestr = strtok(NULL, ","); 118fb02d56eSIgor Mammedov sparc_cpu_parse_features(CPU(cpu), featurestr, &err); 119433ac7a9SAndreas Färber g_free(s); 120433ac7a9SAndreas Färber if (err) { 121565f65d2SMarkus Armbruster error_report_err(err); 122433ac7a9SAndreas Färber return -1; 123433ac7a9SAndreas Färber } 124433ac7a9SAndreas Färber 125576e1c4cSIgor Mammedov env->version = env->def.iu_version; 126576e1c4cSIgor Mammedov env->fsr = env->def.fpu_version; 127576e1c4cSIgor Mammedov env->nwindows = env->def.nwindows; 128ab3b491fSBlue Swirl #if !defined(TARGET_SPARC64) 129576e1c4cSIgor Mammedov env->mmuregs[0] |= env->def.mmu_version; 130ab3b491fSBlue Swirl cpu_sparc_set_id(env, 0); 131576e1c4cSIgor Mammedov env->mxccregs[7] |= env->def.mxcc_version; 132ab3b491fSBlue Swirl #else 133576e1c4cSIgor Mammedov env->mmu_version = env->def.mmu_version; 134576e1c4cSIgor Mammedov env->maxtl = env->def.maxtl; 135576e1c4cSIgor Mammedov env->version |= env->def.maxtl << 8; 136576e1c4cSIgor Mammedov env->version |= env->def.nwindows - 1; 137ab3b491fSBlue Swirl #endif 138ab3b491fSBlue Swirl return 0; 139ab3b491fSBlue Swirl } 140ab3b491fSBlue Swirl 141e59be77aSAndreas Färber SPARCCPU *cpu_sparc_init(const char *cpu_model) 142ab3b491fSBlue Swirl { 143ab7ab3d7SAndreas Färber SPARCCPU *cpu; 14412a6c15eSIgor Mammedov ObjectClass *oc; 14512a6c15eSIgor Mammedov char *str, *name; 146ab3b491fSBlue Swirl 14712a6c15eSIgor Mammedov str = g_strdup(cpu_model); 14812a6c15eSIgor Mammedov name = strtok(str, ","); 14912a6c15eSIgor Mammedov oc = cpu_class_by_name(TYPE_SPARC_CPU, name); 15012a6c15eSIgor Mammedov g_free(str); 15112a6c15eSIgor Mammedov if (oc == NULL) { 15212a6c15eSIgor Mammedov return NULL; 15312a6c15eSIgor Mammedov } 15412a6c15eSIgor Mammedov 15512a6c15eSIgor Mammedov cpu = SPARC_CPU(object_new(object_class_get_name(oc))); 156ab3b491fSBlue Swirl 157433ac7a9SAndreas Färber if (cpu_sparc_register(cpu, cpu_model) < 0) { 1585c099537SPaolo Bonzini object_unref(OBJECT(cpu)); 159ab3b491fSBlue Swirl return NULL; 160ab3b491fSBlue Swirl } 161b6e91ebfSAndreas Färber 162b6e91ebfSAndreas Färber object_property_set_bool(OBJECT(cpu), true, "realized", NULL); 163ab3b491fSBlue Swirl 164e59be77aSAndreas Färber return cpu; 165ab3b491fSBlue Swirl } 166ab3b491fSBlue Swirl 167ab3b491fSBlue Swirl void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu) 168ab3b491fSBlue Swirl { 169ab3b491fSBlue Swirl #if !defined(TARGET_SPARC64) 170ab3b491fSBlue Swirl env->mxccregs[7] = ((cpu + 8) & 0xf) << 24; 171ab3b491fSBlue Swirl #endif 172ab3b491fSBlue Swirl } 173ab3b491fSBlue Swirl 174ab3b491fSBlue Swirl static const sparc_def_t sparc_defs[] = { 175ab3b491fSBlue Swirl #ifdef TARGET_SPARC64 176ab3b491fSBlue Swirl { 177ab3b491fSBlue Swirl .name = "Fujitsu Sparc64", 178ab3b491fSBlue Swirl .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)), 179ab3b491fSBlue Swirl .fpu_version = 0x00000000, 180ab3b491fSBlue Swirl .mmu_version = mmu_us_12, 181ab3b491fSBlue Swirl .nwindows = 4, 182ab3b491fSBlue Swirl .maxtl = 4, 183ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 184ab3b491fSBlue Swirl }, 185ab3b491fSBlue Swirl { 186ab3b491fSBlue Swirl .name = "Fujitsu Sparc64 III", 187ab3b491fSBlue Swirl .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)), 188ab3b491fSBlue Swirl .fpu_version = 0x00000000, 189ab3b491fSBlue Swirl .mmu_version = mmu_us_12, 190ab3b491fSBlue Swirl .nwindows = 5, 191ab3b491fSBlue Swirl .maxtl = 4, 192ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 193ab3b491fSBlue Swirl }, 194ab3b491fSBlue Swirl { 195ab3b491fSBlue Swirl .name = "Fujitsu Sparc64 IV", 196ab3b491fSBlue Swirl .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)), 197ab3b491fSBlue Swirl .fpu_version = 0x00000000, 198ab3b491fSBlue Swirl .mmu_version = mmu_us_12, 199ab3b491fSBlue Swirl .nwindows = 8, 200ab3b491fSBlue Swirl .maxtl = 5, 201ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 202ab3b491fSBlue Swirl }, 203ab3b491fSBlue Swirl { 204ab3b491fSBlue Swirl .name = "Fujitsu Sparc64 V", 205ab3b491fSBlue Swirl .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)), 206ab3b491fSBlue Swirl .fpu_version = 0x00000000, 207ab3b491fSBlue Swirl .mmu_version = mmu_us_12, 208ab3b491fSBlue Swirl .nwindows = 8, 209ab3b491fSBlue Swirl .maxtl = 5, 210ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 211ab3b491fSBlue Swirl }, 212ab3b491fSBlue Swirl { 213ab3b491fSBlue Swirl .name = "TI UltraSparc I", 214ab3b491fSBlue Swirl .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)), 215ab3b491fSBlue Swirl .fpu_version = 0x00000000, 216ab3b491fSBlue Swirl .mmu_version = mmu_us_12, 217ab3b491fSBlue Swirl .nwindows = 8, 218ab3b491fSBlue Swirl .maxtl = 5, 219ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 220ab3b491fSBlue Swirl }, 221ab3b491fSBlue Swirl { 222ab3b491fSBlue Swirl .name = "TI UltraSparc II", 223ab3b491fSBlue Swirl .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)), 224ab3b491fSBlue Swirl .fpu_version = 0x00000000, 225ab3b491fSBlue Swirl .mmu_version = mmu_us_12, 226ab3b491fSBlue Swirl .nwindows = 8, 227ab3b491fSBlue Swirl .maxtl = 5, 228ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 229ab3b491fSBlue Swirl }, 230ab3b491fSBlue Swirl { 231ab3b491fSBlue Swirl .name = "TI UltraSparc IIi", 232ab3b491fSBlue Swirl .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)), 233ab3b491fSBlue Swirl .fpu_version = 0x00000000, 234ab3b491fSBlue Swirl .mmu_version = mmu_us_12, 235ab3b491fSBlue Swirl .nwindows = 8, 236ab3b491fSBlue Swirl .maxtl = 5, 237ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 238ab3b491fSBlue Swirl }, 239ab3b491fSBlue Swirl { 240ab3b491fSBlue Swirl .name = "TI UltraSparc IIe", 241ab3b491fSBlue Swirl .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)), 242ab3b491fSBlue Swirl .fpu_version = 0x00000000, 243ab3b491fSBlue Swirl .mmu_version = mmu_us_12, 244ab3b491fSBlue Swirl .nwindows = 8, 245ab3b491fSBlue Swirl .maxtl = 5, 246ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 247ab3b491fSBlue Swirl }, 248ab3b491fSBlue Swirl { 249ab3b491fSBlue Swirl .name = "Sun UltraSparc III", 250ab3b491fSBlue Swirl .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)), 251ab3b491fSBlue Swirl .fpu_version = 0x00000000, 252ab3b491fSBlue Swirl .mmu_version = mmu_us_12, 253ab3b491fSBlue Swirl .nwindows = 8, 254ab3b491fSBlue Swirl .maxtl = 5, 255ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 256ab3b491fSBlue Swirl }, 257ab3b491fSBlue Swirl { 258ab3b491fSBlue Swirl .name = "Sun UltraSparc III Cu", 259ab3b491fSBlue Swirl .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)), 260ab3b491fSBlue Swirl .fpu_version = 0x00000000, 261ab3b491fSBlue Swirl .mmu_version = mmu_us_3, 262ab3b491fSBlue Swirl .nwindows = 8, 263ab3b491fSBlue Swirl .maxtl = 5, 264ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 265ab3b491fSBlue Swirl }, 266ab3b491fSBlue Swirl { 267ab3b491fSBlue Swirl .name = "Sun UltraSparc IIIi", 268ab3b491fSBlue Swirl .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)), 269ab3b491fSBlue Swirl .fpu_version = 0x00000000, 270ab3b491fSBlue Swirl .mmu_version = mmu_us_12, 271ab3b491fSBlue Swirl .nwindows = 8, 272ab3b491fSBlue Swirl .maxtl = 5, 273ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 274ab3b491fSBlue Swirl }, 275ab3b491fSBlue Swirl { 276ab3b491fSBlue Swirl .name = "Sun UltraSparc IV", 277ab3b491fSBlue Swirl .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)), 278ab3b491fSBlue Swirl .fpu_version = 0x00000000, 279ab3b491fSBlue Swirl .mmu_version = mmu_us_4, 280ab3b491fSBlue Swirl .nwindows = 8, 281ab3b491fSBlue Swirl .maxtl = 5, 282ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 283ab3b491fSBlue Swirl }, 284ab3b491fSBlue Swirl { 285ab3b491fSBlue Swirl .name = "Sun UltraSparc IV+", 286ab3b491fSBlue Swirl .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)), 287ab3b491fSBlue Swirl .fpu_version = 0x00000000, 288ab3b491fSBlue Swirl .mmu_version = mmu_us_12, 289ab3b491fSBlue Swirl .nwindows = 8, 290ab3b491fSBlue Swirl .maxtl = 5, 291ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT, 292ab3b491fSBlue Swirl }, 293ab3b491fSBlue Swirl { 294ab3b491fSBlue Swirl .name = "Sun UltraSparc IIIi+", 295ab3b491fSBlue Swirl .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)), 296ab3b491fSBlue Swirl .fpu_version = 0x00000000, 297ab3b491fSBlue Swirl .mmu_version = mmu_us_3, 298ab3b491fSBlue Swirl .nwindows = 8, 299ab3b491fSBlue Swirl .maxtl = 5, 300ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 301ab3b491fSBlue Swirl }, 302ab3b491fSBlue Swirl { 303ab3b491fSBlue Swirl .name = "Sun UltraSparc T1", 304ab3b491fSBlue Swirl /* defined in sparc_ifu_fdp.v and ctu.h */ 305ab3b491fSBlue Swirl .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)), 306ab3b491fSBlue Swirl .fpu_version = 0x00000000, 307ab3b491fSBlue Swirl .mmu_version = mmu_sun4v, 308ab3b491fSBlue Swirl .nwindows = 8, 309ab3b491fSBlue Swirl .maxtl = 6, 310ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT 311ab3b491fSBlue Swirl | CPU_FEATURE_GL, 312ab3b491fSBlue Swirl }, 313ab3b491fSBlue Swirl { 314ab3b491fSBlue Swirl .name = "Sun UltraSparc T2", 315ab3b491fSBlue Swirl /* defined in tlu_asi_ctl.v and n2_revid_cust.v */ 316ab3b491fSBlue Swirl .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)), 317ab3b491fSBlue Swirl .fpu_version = 0x00000000, 318ab3b491fSBlue Swirl .mmu_version = mmu_sun4v, 319ab3b491fSBlue Swirl .nwindows = 8, 320ab3b491fSBlue Swirl .maxtl = 6, 321ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT 322ab3b491fSBlue Swirl | CPU_FEATURE_GL, 323ab3b491fSBlue Swirl }, 324ab3b491fSBlue Swirl { 325ab3b491fSBlue Swirl .name = "NEC UltraSparc I", 326ab3b491fSBlue Swirl .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)), 327ab3b491fSBlue Swirl .fpu_version = 0x00000000, 328ab3b491fSBlue Swirl .mmu_version = mmu_us_12, 329ab3b491fSBlue Swirl .nwindows = 8, 330ab3b491fSBlue Swirl .maxtl = 5, 331ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 332ab3b491fSBlue Swirl }, 333ab3b491fSBlue Swirl #else 334ab3b491fSBlue Swirl { 335ab3b491fSBlue Swirl .name = "Fujitsu MB86904", 336ab3b491fSBlue Swirl .iu_version = 0x04 << 24, /* Impl 0, ver 4 */ 337ab3b491fSBlue Swirl .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ 338ab3b491fSBlue Swirl .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */ 339ab3b491fSBlue Swirl .mmu_bm = 0x00004000, 340ab3b491fSBlue Swirl .mmu_ctpr_mask = 0x00ffffc0, 341ab3b491fSBlue Swirl .mmu_cxr_mask = 0x000000ff, 342ab3b491fSBlue Swirl .mmu_sfsr_mask = 0x00016fff, 343ab3b491fSBlue Swirl .mmu_trcr_mask = 0x00ffffff, 344ab3b491fSBlue Swirl .nwindows = 8, 345ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 346ab3b491fSBlue Swirl }, 347ab3b491fSBlue Swirl { 348ab3b491fSBlue Swirl .name = "Fujitsu MB86907", 349ab3b491fSBlue Swirl .iu_version = 0x05 << 24, /* Impl 0, ver 5 */ 350ab3b491fSBlue Swirl .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ 351ab3b491fSBlue Swirl .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */ 352ab3b491fSBlue Swirl .mmu_bm = 0x00004000, 353ab3b491fSBlue Swirl .mmu_ctpr_mask = 0xffffffc0, 354ab3b491fSBlue Swirl .mmu_cxr_mask = 0x000000ff, 355ab3b491fSBlue Swirl .mmu_sfsr_mask = 0x00016fff, 356ab3b491fSBlue Swirl .mmu_trcr_mask = 0xffffffff, 357ab3b491fSBlue Swirl .nwindows = 8, 358ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 359ab3b491fSBlue Swirl }, 360ab3b491fSBlue Swirl { 361ab3b491fSBlue Swirl .name = "TI MicroSparc I", 362ab3b491fSBlue Swirl .iu_version = 0x41000000, 363ab3b491fSBlue Swirl .fpu_version = 4 << 17, 364ab3b491fSBlue Swirl .mmu_version = 0x41000000, 365ab3b491fSBlue Swirl .mmu_bm = 0x00004000, 366ab3b491fSBlue Swirl .mmu_ctpr_mask = 0x007ffff0, 367ab3b491fSBlue Swirl .mmu_cxr_mask = 0x0000003f, 368ab3b491fSBlue Swirl .mmu_sfsr_mask = 0x00016fff, 369ab3b491fSBlue Swirl .mmu_trcr_mask = 0x0000003f, 370ab3b491fSBlue Swirl .nwindows = 7, 371ab3b491fSBlue Swirl .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL | 372ab3b491fSBlue Swirl CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT | 373ab3b491fSBlue Swirl CPU_FEATURE_FMUL, 374ab3b491fSBlue Swirl }, 375ab3b491fSBlue Swirl { 376ab3b491fSBlue Swirl .name = "TI MicroSparc II", 377ab3b491fSBlue Swirl .iu_version = 0x42000000, 378ab3b491fSBlue Swirl .fpu_version = 4 << 17, 379ab3b491fSBlue Swirl .mmu_version = 0x02000000, 380ab3b491fSBlue Swirl .mmu_bm = 0x00004000, 381ab3b491fSBlue Swirl .mmu_ctpr_mask = 0x00ffffc0, 382ab3b491fSBlue Swirl .mmu_cxr_mask = 0x000000ff, 383ab3b491fSBlue Swirl .mmu_sfsr_mask = 0x00016fff, 384ab3b491fSBlue Swirl .mmu_trcr_mask = 0x00ffffff, 385ab3b491fSBlue Swirl .nwindows = 8, 386ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 387ab3b491fSBlue Swirl }, 388ab3b491fSBlue Swirl { 389ab3b491fSBlue Swirl .name = "TI MicroSparc IIep", 390ab3b491fSBlue Swirl .iu_version = 0x42000000, 391ab3b491fSBlue Swirl .fpu_version = 4 << 17, 392ab3b491fSBlue Swirl .mmu_version = 0x04000000, 393ab3b491fSBlue Swirl .mmu_bm = 0x00004000, 394ab3b491fSBlue Swirl .mmu_ctpr_mask = 0x00ffffc0, 395ab3b491fSBlue Swirl .mmu_cxr_mask = 0x000000ff, 396ab3b491fSBlue Swirl .mmu_sfsr_mask = 0x00016bff, 397ab3b491fSBlue Swirl .mmu_trcr_mask = 0x00ffffff, 398ab3b491fSBlue Swirl .nwindows = 8, 399ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 400ab3b491fSBlue Swirl }, 401ab3b491fSBlue Swirl { 402ab3b491fSBlue Swirl .name = "TI SuperSparc 40", /* STP1020NPGA */ 403ab3b491fSBlue Swirl .iu_version = 0x41000000, /* SuperSPARC 2.x */ 404ab3b491fSBlue Swirl .fpu_version = 0 << 17, 405ab3b491fSBlue Swirl .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */ 406ab3b491fSBlue Swirl .mmu_bm = 0x00002000, 407ab3b491fSBlue Swirl .mmu_ctpr_mask = 0xffffffc0, 408ab3b491fSBlue Swirl .mmu_cxr_mask = 0x0000ffff, 409ab3b491fSBlue Swirl .mmu_sfsr_mask = 0xffffffff, 410ab3b491fSBlue Swirl .mmu_trcr_mask = 0xffffffff, 411ab3b491fSBlue Swirl .nwindows = 8, 412ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 413ab3b491fSBlue Swirl }, 414ab3b491fSBlue Swirl { 415ab3b491fSBlue Swirl .name = "TI SuperSparc 50", /* STP1020PGA */ 416ab3b491fSBlue Swirl .iu_version = 0x40000000, /* SuperSPARC 3.x */ 417ab3b491fSBlue Swirl .fpu_version = 0 << 17, 418ab3b491fSBlue Swirl .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */ 419ab3b491fSBlue Swirl .mmu_bm = 0x00002000, 420ab3b491fSBlue Swirl .mmu_ctpr_mask = 0xffffffc0, 421ab3b491fSBlue Swirl .mmu_cxr_mask = 0x0000ffff, 422ab3b491fSBlue Swirl .mmu_sfsr_mask = 0xffffffff, 423ab3b491fSBlue Swirl .mmu_trcr_mask = 0xffffffff, 424ab3b491fSBlue Swirl .nwindows = 8, 425ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 426ab3b491fSBlue Swirl }, 427ab3b491fSBlue Swirl { 428ab3b491fSBlue Swirl .name = "TI SuperSparc 51", 429ab3b491fSBlue Swirl .iu_version = 0x40000000, /* SuperSPARC 3.x */ 430ab3b491fSBlue Swirl .fpu_version = 0 << 17, 431ab3b491fSBlue Swirl .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */ 432ab3b491fSBlue Swirl .mmu_bm = 0x00002000, 433ab3b491fSBlue Swirl .mmu_ctpr_mask = 0xffffffc0, 434ab3b491fSBlue Swirl .mmu_cxr_mask = 0x0000ffff, 435ab3b491fSBlue Swirl .mmu_sfsr_mask = 0xffffffff, 436ab3b491fSBlue Swirl .mmu_trcr_mask = 0xffffffff, 437ab3b491fSBlue Swirl .mxcc_version = 0x00000104, 438ab3b491fSBlue Swirl .nwindows = 8, 439ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 440ab3b491fSBlue Swirl }, 441ab3b491fSBlue Swirl { 442ab3b491fSBlue Swirl .name = "TI SuperSparc 60", /* STP1020APGA */ 443ab3b491fSBlue Swirl .iu_version = 0x40000000, /* SuperSPARC 3.x */ 444ab3b491fSBlue Swirl .fpu_version = 0 << 17, 445ab3b491fSBlue Swirl .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */ 446ab3b491fSBlue Swirl .mmu_bm = 0x00002000, 447ab3b491fSBlue Swirl .mmu_ctpr_mask = 0xffffffc0, 448ab3b491fSBlue Swirl .mmu_cxr_mask = 0x0000ffff, 449ab3b491fSBlue Swirl .mmu_sfsr_mask = 0xffffffff, 450ab3b491fSBlue Swirl .mmu_trcr_mask = 0xffffffff, 451ab3b491fSBlue Swirl .nwindows = 8, 452ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 453ab3b491fSBlue Swirl }, 454ab3b491fSBlue Swirl { 455ab3b491fSBlue Swirl .name = "TI SuperSparc 61", 456ab3b491fSBlue Swirl .iu_version = 0x44000000, /* SuperSPARC 3.x */ 457ab3b491fSBlue Swirl .fpu_version = 0 << 17, 458ab3b491fSBlue Swirl .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */ 459ab3b491fSBlue Swirl .mmu_bm = 0x00002000, 460ab3b491fSBlue Swirl .mmu_ctpr_mask = 0xffffffc0, 461ab3b491fSBlue Swirl .mmu_cxr_mask = 0x0000ffff, 462ab3b491fSBlue Swirl .mmu_sfsr_mask = 0xffffffff, 463ab3b491fSBlue Swirl .mmu_trcr_mask = 0xffffffff, 464ab3b491fSBlue Swirl .mxcc_version = 0x00000104, 465ab3b491fSBlue Swirl .nwindows = 8, 466ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 467ab3b491fSBlue Swirl }, 468ab3b491fSBlue Swirl { 469ab3b491fSBlue Swirl .name = "TI SuperSparc II", 470ab3b491fSBlue Swirl .iu_version = 0x40000000, /* SuperSPARC II 1.x */ 471ab3b491fSBlue Swirl .fpu_version = 0 << 17, 472ab3b491fSBlue Swirl .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */ 473ab3b491fSBlue Swirl .mmu_bm = 0x00002000, 474ab3b491fSBlue Swirl .mmu_ctpr_mask = 0xffffffc0, 475ab3b491fSBlue Swirl .mmu_cxr_mask = 0x0000ffff, 476ab3b491fSBlue Swirl .mmu_sfsr_mask = 0xffffffff, 477ab3b491fSBlue Swirl .mmu_trcr_mask = 0xffffffff, 478ab3b491fSBlue Swirl .mxcc_version = 0x00000104, 479ab3b491fSBlue Swirl .nwindows = 8, 480ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES, 481ab3b491fSBlue Swirl }, 482ab3b491fSBlue Swirl { 483ab3b491fSBlue Swirl .name = "LEON2", 484ab3b491fSBlue Swirl .iu_version = 0xf2000000, 485ab3b491fSBlue Swirl .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ 486ab3b491fSBlue Swirl .mmu_version = 0xf2000000, 487ab3b491fSBlue Swirl .mmu_bm = 0x00004000, 488ab3b491fSBlue Swirl .mmu_ctpr_mask = 0x007ffff0, 489ab3b491fSBlue Swirl .mmu_cxr_mask = 0x0000003f, 490ab3b491fSBlue Swirl .mmu_sfsr_mask = 0xffffffff, 491ab3b491fSBlue Swirl .mmu_trcr_mask = 0xffffffff, 492ab3b491fSBlue Swirl .nwindows = 8, 493ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN, 494ab3b491fSBlue Swirl }, 495ab3b491fSBlue Swirl { 496ab3b491fSBlue Swirl .name = "LEON3", 497ab3b491fSBlue Swirl .iu_version = 0xf3000000, 498ab3b491fSBlue Swirl .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ 499ab3b491fSBlue Swirl .mmu_version = 0xf3000000, 500ab3b491fSBlue Swirl .mmu_bm = 0x00000000, 5017a0a9c2cSRonald Hecht .mmu_ctpr_mask = 0xfffffffc, 5027a0a9c2cSRonald Hecht .mmu_cxr_mask = 0x000000ff, 503ab3b491fSBlue Swirl .mmu_sfsr_mask = 0xffffffff, 504ab3b491fSBlue Swirl .mmu_trcr_mask = 0xffffffff, 505ab3b491fSBlue Swirl .nwindows = 8, 506ab3b491fSBlue Swirl .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN | 50716c358e9SSebastian Huber CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN | 50816c358e9SSebastian Huber CPU_FEATURE_CASA, 509ab3b491fSBlue Swirl }, 510ab3b491fSBlue Swirl #endif 511ab3b491fSBlue Swirl }; 512ab3b491fSBlue Swirl 513ab3b491fSBlue Swirl static const char * const feature_name[] = { 514ab3b491fSBlue Swirl "float", 515ab3b491fSBlue Swirl "float128", 516ab3b491fSBlue Swirl "swap", 517ab3b491fSBlue Swirl "mul", 518ab3b491fSBlue Swirl "div", 519ab3b491fSBlue Swirl "flush", 520ab3b491fSBlue Swirl "fsqrt", 521ab3b491fSBlue Swirl "fmul", 522ab3b491fSBlue Swirl "vis1", 523ab3b491fSBlue Swirl "vis2", 524ab3b491fSBlue Swirl "fsmuld", 525ab3b491fSBlue Swirl "hypv", 526ab3b491fSBlue Swirl "cmt", 527ab3b491fSBlue Swirl "gl", 528ab3b491fSBlue Swirl }; 529ab3b491fSBlue Swirl 530ab3b491fSBlue Swirl static void print_features(FILE *f, fprintf_function cpu_fprintf, 531ab3b491fSBlue Swirl uint32_t features, const char *prefix) 532ab3b491fSBlue Swirl { 533ab3b491fSBlue Swirl unsigned int i; 534ab3b491fSBlue Swirl 535ab3b491fSBlue Swirl for (i = 0; i < ARRAY_SIZE(feature_name); i++) { 536ab3b491fSBlue Swirl if (feature_name[i] && (features & (1 << i))) { 537ab3b491fSBlue Swirl if (prefix) { 538ab3b491fSBlue Swirl (*cpu_fprintf)(f, "%s", prefix); 539ab3b491fSBlue Swirl } 540ab3b491fSBlue Swirl (*cpu_fprintf)(f, "%s ", feature_name[i]); 541ab3b491fSBlue Swirl } 542ab3b491fSBlue Swirl } 543ab3b491fSBlue Swirl } 544ab3b491fSBlue Swirl 545ab3b491fSBlue Swirl static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features) 546ab3b491fSBlue Swirl { 547ab3b491fSBlue Swirl unsigned int i; 548ab3b491fSBlue Swirl 549ab3b491fSBlue Swirl for (i = 0; i < ARRAY_SIZE(feature_name); i++) { 550ab3b491fSBlue Swirl if (feature_name[i] && !strcmp(flagname, feature_name[i])) { 551ab3b491fSBlue Swirl *features |= 1 << i; 552ab3b491fSBlue Swirl return; 553ab3b491fSBlue Swirl } 554ab3b491fSBlue Swirl } 555db5d39f7SAndreas Färber error_report("CPU feature %s not found", flagname); 556ab3b491fSBlue Swirl } 557ab3b491fSBlue Swirl 558433ac7a9SAndreas Färber static void sparc_cpu_parse_features(CPUState *cs, char *features, 559433ac7a9SAndreas Färber Error **errp) 560433ac7a9SAndreas Färber { 561433ac7a9SAndreas Färber SPARCCPU *cpu = SPARC_CPU(cs); 562576e1c4cSIgor Mammedov sparc_def_t *cpu_def = &cpu->env.def; 563433ac7a9SAndreas Färber char *featurestr; 564433ac7a9SAndreas Färber uint32_t plus_features = 0; 565433ac7a9SAndreas Färber uint32_t minus_features = 0; 566433ac7a9SAndreas Färber uint64_t iu_version; 567433ac7a9SAndreas Färber uint32_t fpu_version, mmu_version, nwindows; 568433ac7a9SAndreas Färber 569433ac7a9SAndreas Färber featurestr = features ? strtok(features, ",") : NULL; 570ab3b491fSBlue Swirl while (featurestr) { 571ab3b491fSBlue Swirl char *val; 572ab3b491fSBlue Swirl 573ab3b491fSBlue Swirl if (featurestr[0] == '+') { 574ab3b491fSBlue Swirl add_flagname_to_bitmaps(featurestr + 1, &plus_features); 575ab3b491fSBlue Swirl } else if (featurestr[0] == '-') { 576ab3b491fSBlue Swirl add_flagname_to_bitmaps(featurestr + 1, &minus_features); 577ab3b491fSBlue Swirl } else if ((val = strchr(featurestr, '='))) { 578ab3b491fSBlue Swirl *val = 0; val++; 579ab3b491fSBlue Swirl if (!strcmp(featurestr, "iu_version")) { 580ab3b491fSBlue Swirl char *err; 581ab3b491fSBlue Swirl 582ab3b491fSBlue Swirl iu_version = strtoll(val, &err, 0); 583ab3b491fSBlue Swirl if (!*val || *err) { 584433ac7a9SAndreas Färber error_setg(errp, "bad numerical value %s", val); 585433ac7a9SAndreas Färber return; 586ab3b491fSBlue Swirl } 587ab3b491fSBlue Swirl cpu_def->iu_version = iu_version; 588ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES 589ab3b491fSBlue Swirl fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version); 590ab3b491fSBlue Swirl #endif 591ab3b491fSBlue Swirl } else if (!strcmp(featurestr, "fpu_version")) { 592ab3b491fSBlue Swirl char *err; 593ab3b491fSBlue Swirl 594ab3b491fSBlue Swirl fpu_version = strtol(val, &err, 0); 595ab3b491fSBlue Swirl if (!*val || *err) { 596433ac7a9SAndreas Färber error_setg(errp, "bad numerical value %s", val); 597433ac7a9SAndreas Färber return; 598ab3b491fSBlue Swirl } 599ab3b491fSBlue Swirl cpu_def->fpu_version = fpu_version; 600ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES 601ab3b491fSBlue Swirl fprintf(stderr, "fpu_version %x\n", fpu_version); 602ab3b491fSBlue Swirl #endif 603ab3b491fSBlue Swirl } else if (!strcmp(featurestr, "mmu_version")) { 604ab3b491fSBlue Swirl char *err; 605ab3b491fSBlue Swirl 606ab3b491fSBlue Swirl mmu_version = strtol(val, &err, 0); 607ab3b491fSBlue Swirl if (!*val || *err) { 608433ac7a9SAndreas Färber error_setg(errp, "bad numerical value %s", val); 609433ac7a9SAndreas Färber return; 610ab3b491fSBlue Swirl } 611ab3b491fSBlue Swirl cpu_def->mmu_version = mmu_version; 612ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES 613ab3b491fSBlue Swirl fprintf(stderr, "mmu_version %x\n", mmu_version); 614ab3b491fSBlue Swirl #endif 615ab3b491fSBlue Swirl } else if (!strcmp(featurestr, "nwindows")) { 616ab3b491fSBlue Swirl char *err; 617ab3b491fSBlue Swirl 618ab3b491fSBlue Swirl nwindows = strtol(val, &err, 0); 619ab3b491fSBlue Swirl if (!*val || *err || nwindows > MAX_NWINDOWS || 620ab3b491fSBlue Swirl nwindows < MIN_NWINDOWS) { 621433ac7a9SAndreas Färber error_setg(errp, "bad numerical value %s", val); 622433ac7a9SAndreas Färber return; 623ab3b491fSBlue Swirl } 624ab3b491fSBlue Swirl cpu_def->nwindows = nwindows; 625ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES 626ab3b491fSBlue Swirl fprintf(stderr, "nwindows %d\n", nwindows); 627ab3b491fSBlue Swirl #endif 628ab3b491fSBlue Swirl } else { 629433ac7a9SAndreas Färber error_setg(errp, "unrecognized feature %s", featurestr); 630433ac7a9SAndreas Färber return; 631ab3b491fSBlue Swirl } 632ab3b491fSBlue Swirl } else { 633433ac7a9SAndreas Färber error_setg(errp, "feature string `%s' not in format " 634db5d39f7SAndreas Färber "(+feature|-feature|feature=xyz)", featurestr); 635433ac7a9SAndreas Färber return; 636ab3b491fSBlue Swirl } 637ab3b491fSBlue Swirl featurestr = strtok(NULL, ","); 638ab3b491fSBlue Swirl } 639ab3b491fSBlue Swirl cpu_def->features |= plus_features; 640ab3b491fSBlue Swirl cpu_def->features &= ~minus_features; 641ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES 642ab3b491fSBlue Swirl print_features(stderr, fprintf, cpu_def->features, NULL); 643ab3b491fSBlue Swirl #endif 644ab3b491fSBlue Swirl } 645ab3b491fSBlue Swirl 646ab3b491fSBlue Swirl void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf) 647ab3b491fSBlue Swirl { 648ab3b491fSBlue Swirl unsigned int i; 649ab3b491fSBlue Swirl 650ab3b491fSBlue Swirl for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) { 651ab3b491fSBlue Swirl (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx 652ab3b491fSBlue Swirl " FPU %08x MMU %08x NWINS %d ", 653ab3b491fSBlue Swirl sparc_defs[i].name, 654ab3b491fSBlue Swirl sparc_defs[i].iu_version, 655ab3b491fSBlue Swirl sparc_defs[i].fpu_version, 656ab3b491fSBlue Swirl sparc_defs[i].mmu_version, 657ab3b491fSBlue Swirl sparc_defs[i].nwindows); 658ab3b491fSBlue Swirl print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES & 659ab3b491fSBlue Swirl ~sparc_defs[i].features, "-"); 660ab3b491fSBlue Swirl print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES & 661ab3b491fSBlue Swirl sparc_defs[i].features, "+"); 662ab3b491fSBlue Swirl (*cpu_fprintf)(f, "\n"); 663ab3b491fSBlue Swirl } 664ab3b491fSBlue Swirl (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): "); 665ab3b491fSBlue Swirl print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL); 666ab3b491fSBlue Swirl (*cpu_fprintf)(f, "\n"); 667ab3b491fSBlue Swirl (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): "); 668ab3b491fSBlue Swirl print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL); 669ab3b491fSBlue Swirl (*cpu_fprintf)(f, "\n"); 670ab3b491fSBlue Swirl (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version " 671ab3b491fSBlue Swirl "fpu_version mmu_version nwindows\n"); 672ab3b491fSBlue Swirl } 673ab3b491fSBlue Swirl 674ab3b491fSBlue Swirl static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf, 675ab3b491fSBlue Swirl uint32_t cc) 676ab3b491fSBlue Swirl { 677ab3b491fSBlue Swirl cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-', 678ab3b491fSBlue Swirl cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-', 679ab3b491fSBlue Swirl cc & PSR_CARRY ? 'C' : '-'); 680ab3b491fSBlue Swirl } 681ab3b491fSBlue Swirl 682ab3b491fSBlue Swirl #ifdef TARGET_SPARC64 683ab3b491fSBlue Swirl #define REGS_PER_LINE 4 684ab3b491fSBlue Swirl #else 685ab3b491fSBlue Swirl #define REGS_PER_LINE 8 686ab3b491fSBlue Swirl #endif 687ab3b491fSBlue Swirl 688878096eeSAndreas Färber void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, 689ab3b491fSBlue Swirl int flags) 690ab3b491fSBlue Swirl { 691878096eeSAndreas Färber SPARCCPU *cpu = SPARC_CPU(cs); 692878096eeSAndreas Färber CPUSPARCState *env = &cpu->env; 693ab3b491fSBlue Swirl int i, x; 694ab3b491fSBlue Swirl 695ab3b491fSBlue Swirl cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc, 696ab3b491fSBlue Swirl env->npc); 697ab3b491fSBlue Swirl 698ab3b491fSBlue Swirl for (i = 0; i < 8; i++) { 699ab3b491fSBlue Swirl if (i % REGS_PER_LINE == 0) { 700ab3b491fSBlue Swirl cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1); 701ab3b491fSBlue Swirl } 702ab3b491fSBlue Swirl cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]); 703ab3b491fSBlue Swirl if (i % REGS_PER_LINE == REGS_PER_LINE - 1) { 704ab3b491fSBlue Swirl cpu_fprintf(f, "\n"); 705ab3b491fSBlue Swirl } 706ab3b491fSBlue Swirl } 707ab3b491fSBlue Swirl for (x = 0; x < 3; x++) { 708ab3b491fSBlue Swirl for (i = 0; i < 8; i++) { 709ab3b491fSBlue Swirl if (i % REGS_PER_LINE == 0) { 710ab3b491fSBlue Swirl cpu_fprintf(f, "%%%c%d-%d: ", 711ab3b491fSBlue Swirl x == 0 ? 'o' : (x == 1 ? 'l' : 'i'), 712ab3b491fSBlue Swirl i, i + REGS_PER_LINE - 1); 713ab3b491fSBlue Swirl } 714ab3b491fSBlue Swirl cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]); 715ab3b491fSBlue Swirl if (i % REGS_PER_LINE == REGS_PER_LINE - 1) { 716ab3b491fSBlue Swirl cpu_fprintf(f, "\n"); 717ab3b491fSBlue Swirl } 718ab3b491fSBlue Swirl } 719ab3b491fSBlue Swirl } 72076a23ca0SRichard Henderson 72130038fd8SRichard Henderson for (i = 0; i < TARGET_DPREGS; i++) { 722ab3b491fSBlue Swirl if ((i & 3) == 0) { 72330038fd8SRichard Henderson cpu_fprintf(f, "%%f%02d: ", i * 2); 724ab3b491fSBlue Swirl } 72530038fd8SRichard Henderson cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll); 726ab3b491fSBlue Swirl if ((i & 3) == 3) { 727ab3b491fSBlue Swirl cpu_fprintf(f, "\n"); 728ab3b491fSBlue Swirl } 729ab3b491fSBlue Swirl } 730ab3b491fSBlue Swirl #ifdef TARGET_SPARC64 731ab3b491fSBlue Swirl cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate, 732ab3b491fSBlue Swirl (unsigned)cpu_get_ccr(env)); 733ab3b491fSBlue Swirl cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT); 734ab3b491fSBlue Swirl cpu_fprintf(f, " xcc: "); 735ab3b491fSBlue Swirl cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4)); 736cbc3a6a4SArtyom Tarasenko cpu_fprintf(f, ") asi: %02x tl: %d pil: %x gl: %d\n", env->asi, env->tl, 737cbc3a6a4SArtyom Tarasenko env->psrpil, env->gl); 738cbc3a6a4SArtyom Tarasenko cpu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: " 739cbc3a6a4SArtyom Tarasenko TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba); 740ab3b491fSBlue Swirl cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d " 741ab3b491fSBlue Swirl "cleanwin: %d cwp: %d\n", 742ab3b491fSBlue Swirl env->cansave, env->canrestore, env->otherwin, env->wstate, 743ab3b491fSBlue Swirl env->cleanwin, env->nwindows - 1 - env->cwp); 744ab3b491fSBlue Swirl cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: " 745ab3b491fSBlue Swirl TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs); 746cbc3a6a4SArtyom Tarasenko 747ab3b491fSBlue Swirl #else 748ab3b491fSBlue Swirl cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env)); 749ab3b491fSBlue Swirl cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env)); 750ab3b491fSBlue Swirl cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-', 751ab3b491fSBlue Swirl env->psrps ? 'P' : '-', env->psret ? 'E' : '-', 752ab3b491fSBlue Swirl env->wim); 753ab3b491fSBlue Swirl cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n", 754ab3b491fSBlue Swirl env->fsr, env->y); 755ab3b491fSBlue Swirl #endif 75676a23ca0SRichard Henderson cpu_fprintf(f, "\n"); 757ab3b491fSBlue Swirl } 758ab7ab3d7SAndreas Färber 759f45748f1SAndreas Färber static void sparc_cpu_set_pc(CPUState *cs, vaddr value) 760f45748f1SAndreas Färber { 761f45748f1SAndreas Färber SPARCCPU *cpu = SPARC_CPU(cs); 762f45748f1SAndreas Färber 763f45748f1SAndreas Färber cpu->env.pc = value; 764f45748f1SAndreas Färber cpu->env.npc = value + 4; 765f45748f1SAndreas Färber } 766f45748f1SAndreas Färber 767bdf7ae5bSAndreas Färber static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) 768bdf7ae5bSAndreas Färber { 769bdf7ae5bSAndreas Färber SPARCCPU *cpu = SPARC_CPU(cs); 770bdf7ae5bSAndreas Färber 771bdf7ae5bSAndreas Färber cpu->env.pc = tb->pc; 772bdf7ae5bSAndreas Färber cpu->env.npc = tb->cs_base; 773bdf7ae5bSAndreas Färber } 774bdf7ae5bSAndreas Färber 7758c2e1b00SAndreas Färber static bool sparc_cpu_has_work(CPUState *cs) 7768c2e1b00SAndreas Färber { 7778c2e1b00SAndreas Färber SPARCCPU *cpu = SPARC_CPU(cs); 7788c2e1b00SAndreas Färber CPUSPARCState *env = &cpu->env; 7798c2e1b00SAndreas Färber 7808c2e1b00SAndreas Färber return (cs->interrupt_request & CPU_INTERRUPT_HARD) && 7818c2e1b00SAndreas Färber cpu_interrupts_enabled(env); 7828c2e1b00SAndreas Färber } 7838c2e1b00SAndreas Färber 78412a6c15eSIgor Mammedov static char *sparc_cpu_type_name(const char *cpu_model) 78512a6c15eSIgor Mammedov { 78612a6c15eSIgor Mammedov char *name = g_strdup_printf("%s-" TYPE_SPARC_CPU, cpu_model); 78712a6c15eSIgor Mammedov char *s = name; 78812a6c15eSIgor Mammedov 78912a6c15eSIgor Mammedov /* SPARC cpu model names happen to have whitespaces, 79012a6c15eSIgor Mammedov * as type names shouldn't have spaces replace them with '-' 79112a6c15eSIgor Mammedov */ 79212a6c15eSIgor Mammedov while ((s = strchr(s, ' '))) { 79312a6c15eSIgor Mammedov *s = '-'; 79412a6c15eSIgor Mammedov } 79512a6c15eSIgor Mammedov 79612a6c15eSIgor Mammedov return name; 79712a6c15eSIgor Mammedov } 79812a6c15eSIgor Mammedov 79912a6c15eSIgor Mammedov static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model) 80012a6c15eSIgor Mammedov { 80112a6c15eSIgor Mammedov ObjectClass *oc; 80212a6c15eSIgor Mammedov char *typename; 80312a6c15eSIgor Mammedov 80412a6c15eSIgor Mammedov if (cpu_model == NULL) { 80512a6c15eSIgor Mammedov return NULL; 80612a6c15eSIgor Mammedov } 80712a6c15eSIgor Mammedov 80812a6c15eSIgor Mammedov typename = sparc_cpu_type_name(cpu_model); 80912a6c15eSIgor Mammedov oc = object_class_by_name(typename); 81012a6c15eSIgor Mammedov g_free(typename); 81112a6c15eSIgor Mammedov return oc; 81212a6c15eSIgor Mammedov } 81312a6c15eSIgor Mammedov 814b6e91ebfSAndreas Färber static void sparc_cpu_realizefn(DeviceState *dev, Error **errp) 815b6e91ebfSAndreas Färber { 816ce5b1bbfSLaurent Vivier CPUState *cs = CPU(dev); 817b6e91ebfSAndreas Färber SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev); 818ce5b1bbfSLaurent Vivier Error *local_err = NULL; 819247bf011SAndreas Färber #if defined(CONFIG_USER_ONLY) 820247bf011SAndreas Färber SPARCCPU *cpu = SPARC_CPU(dev); 821247bf011SAndreas Färber CPUSPARCState *env = &cpu->env; 822247bf011SAndreas Färber 823576e1c4cSIgor Mammedov if ((env->def.features & CPU_FEATURE_FLOAT)) { 824576e1c4cSIgor Mammedov env->def.features |= CPU_FEATURE_FLOAT128; 825247bf011SAndreas Färber } 826247bf011SAndreas Färber #endif 827b6e91ebfSAndreas Färber 828ce5b1bbfSLaurent Vivier cpu_exec_realizefn(cs, &local_err); 829ce5b1bbfSLaurent Vivier if (local_err != NULL) { 830ce5b1bbfSLaurent Vivier error_propagate(errp, local_err); 831ce5b1bbfSLaurent Vivier return; 832ce5b1bbfSLaurent Vivier } 833ce5b1bbfSLaurent Vivier 834ce5b1bbfSLaurent Vivier qemu_init_vcpu(cs); 83514a10fc3SAndreas Färber 836b6e91ebfSAndreas Färber scc->parent_realize(dev, errp); 837b6e91ebfSAndreas Färber } 838b6e91ebfSAndreas Färber 839ab7ab3d7SAndreas Färber static void sparc_cpu_initfn(Object *obj) 840ab7ab3d7SAndreas Färber { 841c05efcb1SAndreas Färber CPUState *cs = CPU(obj); 842ab7ab3d7SAndreas Färber SPARCCPU *cpu = SPARC_CPU(obj); 84312a6c15eSIgor Mammedov SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj); 844ab7ab3d7SAndreas Färber CPUSPARCState *env = &cpu->env; 845ab7ab3d7SAndreas Färber 846c05efcb1SAndreas Färber cs->env_ptr = env; 8475266d20aSAndreas Färber 8485266d20aSAndreas Färber if (tcg_enabled()) { 8495266d20aSAndreas Färber gen_intermediate_code_init(env); 8505266d20aSAndreas Färber } 85112a6c15eSIgor Mammedov 852576e1c4cSIgor Mammedov if (scc->cpu_def) { 853576e1c4cSIgor Mammedov env->def = *scc->cpu_def; 854ab7ab3d7SAndreas Färber } 855ab7ab3d7SAndreas Färber } 856ab7ab3d7SAndreas Färber 857*de05005bSIgor Mammedov static void sparc_get_nwindows(Object *obj, Visitor *v, const char *name, 858*de05005bSIgor Mammedov void *opaque, Error **errp) 859*de05005bSIgor Mammedov { 860*de05005bSIgor Mammedov SPARCCPU *cpu = SPARC_CPU(obj); 861*de05005bSIgor Mammedov int64_t value = cpu->env.def.nwindows; 862*de05005bSIgor Mammedov 863*de05005bSIgor Mammedov visit_type_int(v, name, &value, errp); 864*de05005bSIgor Mammedov } 865*de05005bSIgor Mammedov 866*de05005bSIgor Mammedov static void sparc_set_nwindows(Object *obj, Visitor *v, const char *name, 867*de05005bSIgor Mammedov void *opaque, Error **errp) 868*de05005bSIgor Mammedov { 869*de05005bSIgor Mammedov const int64_t min = MIN_NWINDOWS; 870*de05005bSIgor Mammedov const int64_t max = MAX_NWINDOWS; 871*de05005bSIgor Mammedov SPARCCPU *cpu = SPARC_CPU(obj); 872*de05005bSIgor Mammedov Error *err = NULL; 873*de05005bSIgor Mammedov int64_t value; 874*de05005bSIgor Mammedov 875*de05005bSIgor Mammedov visit_type_int(v, name, &value, &err); 876*de05005bSIgor Mammedov if (err) { 877*de05005bSIgor Mammedov error_propagate(errp, err); 878*de05005bSIgor Mammedov return; 879*de05005bSIgor Mammedov } 880*de05005bSIgor Mammedov 881*de05005bSIgor Mammedov if (value < min || value > max) { 882*de05005bSIgor Mammedov error_setg(errp, "Property %s.%s doesn't take value %" PRId64 883*de05005bSIgor Mammedov " (minimum: %" PRId64 ", maximum: %" PRId64 ")", 884*de05005bSIgor Mammedov object_get_typename(obj), name ? name : "null", 885*de05005bSIgor Mammedov value, min, max); 886*de05005bSIgor Mammedov return; 887*de05005bSIgor Mammedov } 888*de05005bSIgor Mammedov cpu->env.def.nwindows = value; 889*de05005bSIgor Mammedov } 890*de05005bSIgor Mammedov 891*de05005bSIgor Mammedov static PropertyInfo qdev_prop_nwindows = { 892*de05005bSIgor Mammedov .name = "int", 893*de05005bSIgor Mammedov .get = sparc_get_nwindows, 894*de05005bSIgor Mammedov .set = sparc_set_nwindows, 895*de05005bSIgor Mammedov }; 896*de05005bSIgor Mammedov 897*de05005bSIgor Mammedov static Property sparc_cpu_properties[] = { 898*de05005bSIgor Mammedov DEFINE_PROP_BIT("float", SPARCCPU, env.def.features, 0, false), 899*de05005bSIgor Mammedov DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, 1, false), 900*de05005bSIgor Mammedov DEFINE_PROP_BIT("swap", SPARCCPU, env.def.features, 2, false), 901*de05005bSIgor Mammedov DEFINE_PROP_BIT("mul", SPARCCPU, env.def.features, 3, false), 902*de05005bSIgor Mammedov DEFINE_PROP_BIT("div", SPARCCPU, env.def.features, 4, false), 903*de05005bSIgor Mammedov DEFINE_PROP_BIT("flush", SPARCCPU, env.def.features, 5, false), 904*de05005bSIgor Mammedov DEFINE_PROP_BIT("fsqrt", SPARCCPU, env.def.features, 6, false), 905*de05005bSIgor Mammedov DEFINE_PROP_BIT("fmul", SPARCCPU, env.def.features, 7, false), 906*de05005bSIgor Mammedov DEFINE_PROP_BIT("vis1", SPARCCPU, env.def.features, 8, false), 907*de05005bSIgor Mammedov DEFINE_PROP_BIT("vis2", SPARCCPU, env.def.features, 9, false), 908*de05005bSIgor Mammedov DEFINE_PROP_BIT("fsmuld", SPARCCPU, env.def.features, 10, false), 909*de05005bSIgor Mammedov DEFINE_PROP_BIT("hypv", SPARCCPU, env.def.features, 11, false), 910*de05005bSIgor Mammedov DEFINE_PROP_BIT("cmt", SPARCCPU, env.def.features, 12, false), 911*de05005bSIgor Mammedov DEFINE_PROP_BIT("gl", SPARCCPU, env.def.features, 13, false), 912*de05005bSIgor Mammedov DEFINE_PROP_UNSIGNED("iu-version", SPARCCPU, env.def.iu_version, 0, 913*de05005bSIgor Mammedov qdev_prop_uint64, target_ulong), 914*de05005bSIgor Mammedov DEFINE_PROP_UINT32("fpu-version", SPARCCPU, env.def.fpu_version, 0), 915*de05005bSIgor Mammedov DEFINE_PROP_UINT32("mmu-version", SPARCCPU, env.def.mmu_version, 0), 916*de05005bSIgor Mammedov { .name = "nwindows", .info = &qdev_prop_nwindows }, 917*de05005bSIgor Mammedov DEFINE_PROP_END_OF_LIST() 918*de05005bSIgor Mammedov }; 919*de05005bSIgor Mammedov 920ab7ab3d7SAndreas Färber static void sparc_cpu_class_init(ObjectClass *oc, void *data) 921ab7ab3d7SAndreas Färber { 922ab7ab3d7SAndreas Färber SPARCCPUClass *scc = SPARC_CPU_CLASS(oc); 923ab7ab3d7SAndreas Färber CPUClass *cc = CPU_CLASS(oc); 924b6e91ebfSAndreas Färber DeviceClass *dc = DEVICE_CLASS(oc); 925b6e91ebfSAndreas Färber 926b6e91ebfSAndreas Färber scc->parent_realize = dc->realize; 927b6e91ebfSAndreas Färber dc->realize = sparc_cpu_realizefn; 928*de05005bSIgor Mammedov dc->props = sparc_cpu_properties; 929ab7ab3d7SAndreas Färber 930ab7ab3d7SAndreas Färber scc->parent_reset = cc->reset; 931ab7ab3d7SAndreas Färber cc->reset = sparc_cpu_reset; 93297a8ea5aSAndreas Färber 93312a6c15eSIgor Mammedov cc->class_by_name = sparc_cpu_class_by_name; 9348c2e1b00SAndreas Färber cc->has_work = sparc_cpu_has_work; 93597a8ea5aSAndreas Färber cc->do_interrupt = sparc_cpu_do_interrupt; 93687afe467SRichard Henderson cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt; 937878096eeSAndreas Färber cc->dump_state = sparc_cpu_dump_state; 938f3659eeeSAndreas Färber #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) 939f3659eeeSAndreas Färber cc->memory_rw_debug = sparc_cpu_memory_rw_debug; 940f3659eeeSAndreas Färber #endif 941f45748f1SAndreas Färber cc->set_pc = sparc_cpu_set_pc; 942bdf7ae5bSAndreas Färber cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb; 9435b50e790SAndreas Färber cc->gdb_read_register = sparc_cpu_gdb_read_register; 9445b50e790SAndreas Färber cc->gdb_write_register = sparc_cpu_gdb_write_register; 9457510454eSAndreas Färber #ifdef CONFIG_USER_ONLY 9467510454eSAndreas Färber cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault; 9477510454eSAndreas Färber #else 94800b941e5SAndreas Färber cc->do_unassigned_access = sparc_cpu_unassigned_access; 94993e22326SPaolo Bonzini cc->do_unaligned_access = sparc_cpu_do_unaligned_access; 95000b941e5SAndreas Färber cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug; 951df32c8d4SJuan Quintela cc->vmsd = &vmstate_sparc_cpu; 95200b941e5SAndreas Färber #endif 953df0900ebSPeter Crosthwaite cc->disas_set_info = cpu_sparc_disas_set_info; 954a0e372f0SAndreas Färber 955a0e372f0SAndreas Färber #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 956a0e372f0SAndreas Färber cc->gdb_num_core_regs = 86; 957a0e372f0SAndreas Färber #else 958a0e372f0SAndreas Färber cc->gdb_num_core_regs = 72; 959a0e372f0SAndreas Färber #endif 960ab7ab3d7SAndreas Färber } 961ab7ab3d7SAndreas Färber 962ab7ab3d7SAndreas Färber static const TypeInfo sparc_cpu_type_info = { 963ab7ab3d7SAndreas Färber .name = TYPE_SPARC_CPU, 964ab7ab3d7SAndreas Färber .parent = TYPE_CPU, 965ab7ab3d7SAndreas Färber .instance_size = sizeof(SPARCCPU), 966ab7ab3d7SAndreas Färber .instance_init = sparc_cpu_initfn, 96712a6c15eSIgor Mammedov .abstract = true, 968ab7ab3d7SAndreas Färber .class_size = sizeof(SPARCCPUClass), 969ab7ab3d7SAndreas Färber .class_init = sparc_cpu_class_init, 970ab7ab3d7SAndreas Färber }; 971ab7ab3d7SAndreas Färber 97212a6c15eSIgor Mammedov static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data) 97312a6c15eSIgor Mammedov { 97412a6c15eSIgor Mammedov SPARCCPUClass *scc = SPARC_CPU_CLASS(oc); 97512a6c15eSIgor Mammedov scc->cpu_def = data; 97612a6c15eSIgor Mammedov } 97712a6c15eSIgor Mammedov 97812a6c15eSIgor Mammedov static void sparc_register_cpudef_type(const struct sparc_def_t *def) 97912a6c15eSIgor Mammedov { 98012a6c15eSIgor Mammedov char *typename = sparc_cpu_type_name(def->name); 98112a6c15eSIgor Mammedov TypeInfo ti = { 98212a6c15eSIgor Mammedov .name = typename, 98312a6c15eSIgor Mammedov .parent = TYPE_SPARC_CPU, 98412a6c15eSIgor Mammedov .class_init = sparc_cpu_cpudef_class_init, 98512a6c15eSIgor Mammedov .class_data = (void *)def, 98612a6c15eSIgor Mammedov }; 98712a6c15eSIgor Mammedov 98812a6c15eSIgor Mammedov type_register(&ti); 98912a6c15eSIgor Mammedov g_free(typename); 99012a6c15eSIgor Mammedov } 99112a6c15eSIgor Mammedov 992ab7ab3d7SAndreas Färber static void sparc_cpu_register_types(void) 993ab7ab3d7SAndreas Färber { 99412a6c15eSIgor Mammedov int i; 99512a6c15eSIgor Mammedov 996ab7ab3d7SAndreas Färber type_register_static(&sparc_cpu_type_info); 99712a6c15eSIgor Mammedov for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) { 99812a6c15eSIgor Mammedov sparc_register_cpudef_type(&sparc_defs[i]); 99912a6c15eSIgor Mammedov } 1000ab7ab3d7SAndreas Färber } 1001ab7ab3d7SAndreas Färber 1002ab7ab3d7SAndreas Färber type_init(sparc_cpu_register_types) 1003