diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index ee30bf54e2..6ad98edf5f 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -43,6 +43,7 @@ #define TT_TOVF 0x0a #define TT_EXTINT 0x10 #define TT_CODE_ACCESS 0x21 +#define TT_UNIMP_FLUSH 0x25 #define TT_DATA_ACCESS 0x29 #define TT_DIV_ZERO 0x2a #define TT_NCP_INSN 0x24 @@ -52,6 +53,7 @@ #define TT_TMISS 0x09 #define TT_CODE_ACCESS 0x0a #define TT_ILL_INSN 0x10 +#define TT_UNIMP_FLUSH TT_ILL_INSN #define TT_PRIV_INSN 0x11 #define TT_NFPU_INSN 0x20 #define TT_FP_EXCP 0x21 @@ -244,9 +246,7 @@ typedef struct CPUSPARCState { /* temporary float registers */ float32 ft0, ft1; float64 dt0, dt1; -#if defined(CONFIG_USER_ONLY) float128 qt0, qt1; -#endif float_status fp_status; #if defined(TARGET_SPARC64) #define MAXTL 4 @@ -272,7 +272,32 @@ typedef struct CPUSPARCState { void *hstick; // UA 2005 #endif target_ulong t1, t2; + uint32_t features; } CPUSPARCState; + +#define CPU_FEATURE_FLOAT (1 << 0) +#define CPU_FEATURE_FLOAT128 (1 << 1) +#define CPU_FEATURE_SWAP (1 << 2) +#define CPU_FEATURE_MUL (1 << 3) +#define CPU_FEATURE_DIV (1 << 4) +#define CPU_FEATURE_FLUSH (1 << 5) +#define CPU_FEATURE_FSQRT (1 << 6) +#define CPU_FEATURE_FMUL (1 << 7) +#define CPU_FEATURE_VIS1 (1 << 8) +#define CPU_FEATURE_VIS2 (1 << 9) +#ifndef TARGET_SPARC64 +#define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | \ + CPU_FEATURE_MUL | CPU_FEATURE_DIV | \ + CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT | \ + CPU_FEATURE_FMUL) +#else +#define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | \ + CPU_FEATURE_MUL | CPU_FEATURE_DIV | \ + CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT | \ + CPU_FEATURE_FMUL | CPU_FEATURE_VIS1 | \ + CPU_FEATURE_VIS2) +#endif + #if defined(TARGET_SPARC64) #define GET_FSR32(env) (env->fsr & 0xcfc1ffff) #define PUT_FSR32(env, val) do { uint32_t _tmp = val; \ @@ -292,7 +317,6 @@ typedef struct CPUSPARCState { CPUSPARCState *cpu_sparc_init(const char *cpu_model); void gen_intermediate_code_init(CPUSPARCState *env); int cpu_sparc_exec(CPUSPARCState *s); -int cpu_sparc_close(CPUSPARCState *s); void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu); diff --git a/target-sparc/exec.h b/target-sparc/exec.h index e56b2c64ad..504d602bc1 100644 --- a/target-sparc/exec.h +++ b/target-sparc/exec.h @@ -39,10 +39,8 @@ register uint32_t T2 asm(AREG3); #define FT1 (env->ft1) #define DT0 (env->dt0) #define DT1 (env->dt1) -#if defined(CONFIG_USER_ONLY) #define QT0 (env->qt0) #define QT1 (env->qt1) -#endif #include "cpu.h" #include "exec-all.h" diff --git a/target-sparc/helper.c b/target-sparc/helper.c index dd7a51f9c2..e378028e13 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -30,6 +30,7 @@ #include "qemu-common.h" //#define DEBUG_MMU +//#define DEBUG_FEATURES typedef struct sparc_def_t sparc_def_t; @@ -43,9 +44,10 @@ struct sparc_def_t { uint32_t mmu_cxr_mask; uint32_t mmu_sfsr_mask; uint32_t mmu_trcr_mask; + uint32_t features; }; -static const sparc_def_t *cpu_sparc_find_by_name(const unsigned char *name); +static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const unsigned char *cpu_model); /* Sparc MMU emulation */ @@ -684,19 +686,14 @@ void cpu_reset(CPUSPARCState *env) #endif } -CPUSPARCState *cpu_sparc_init(const char *cpu_model) +static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model) { - CPUSPARCState *env; - const sparc_def_t *def; + sparc_def_t def1, *def = &def1; - def = cpu_sparc_find_by_name(cpu_model); - if (!def) - return NULL; + if (cpu_sparc_find_by_name(def, cpu_model) < 0) + return -1; - env = qemu_mallocz(sizeof(CPUSPARCState)); - if (!env) - return NULL; - cpu_exec_init(env); + env->features = def->features; env->cpu_model_str = cpu_model; env->version = def->iu_version; env->fsr = def->fpu_version; @@ -709,9 +706,29 @@ CPUSPARCState *cpu_sparc_init(const char *cpu_model) env->mmuregs[0] |= def->mmu_version; cpu_sparc_set_id(env, 0); #endif + return 0; +} + +static void cpu_sparc_close(CPUSPARCState *env) +{ + free(env); +} + +CPUSPARCState *cpu_sparc_init(const char *cpu_model) +{ + CPUSPARCState *env; + + env = qemu_mallocz(sizeof(CPUSPARCState)); + if (!env) + return NULL; + cpu_exec_init(env); gen_intermediate_code_init(env); + if (cpu_sparc_register(env, cpu_model) < 0) { + cpu_sparc_close(env); + return NULL; + } cpu_reset(env); return env; @@ -732,6 +749,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, { .name = "Fujitsu Sparc64 III", @@ -739,6 +757,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, { .name = "Fujitsu Sparc64 IV", @@ -746,6 +765,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, { .name = "Fujitsu Sparc64 V", @@ -753,6 +773,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, { .name = "TI UltraSparc I", @@ -760,6 +781,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, { .name = "TI UltraSparc II", @@ -767,6 +789,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, { .name = "TI UltraSparc IIi", @@ -774,6 +797,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, { .name = "TI UltraSparc IIe", @@ -781,6 +805,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, { .name = "Sun UltraSparc III", @@ -788,6 +813,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, { .name = "Sun UltraSparc III Cu", @@ -795,6 +821,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, { .name = "Sun UltraSparc IIIi", @@ -802,6 +829,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, { .name = "Sun UltraSparc IV", @@ -809,6 +837,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, { .name = "Sun UltraSparc IV+", @@ -816,6 +845,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, { .name = "Sun UltraSparc IIIi+", @@ -823,6 +853,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, { .name = "NEC UltraSparc I", @@ -830,6 +861,7 @@ static const sparc_def_t sparc_defs[] = { | (MAXTL << 8) | (NWINDOWS - 1)), .fpu_version = 0x00000000, .mmu_version = 0, + .features = CPU_DEFAULT_FEATURES, }, #else { @@ -842,6 +874,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_FEATURE_FLOAT, }, { .name = "Fujitsu MB86904", @@ -853,6 +886,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x000000ff, .mmu_sfsr_mask = 0x00016fff, .mmu_trcr_mask = 0x00ffffff, + .features = CPU_DEFAULT_FEATURES, }, { .name = "Fujitsu MB86907", @@ -864,6 +898,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x000000ff, .mmu_sfsr_mask = 0x00016fff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_DEFAULT_FEATURES, }, { .name = "LSI L64811", @@ -875,6 +910,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT, }, { .name = "Cypress CY7C601", @@ -886,6 +922,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT, }, { .name = "Cypress CY7C611", @@ -897,6 +934,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT, }, { .name = "TI SuperSparc II", @@ -908,6 +946,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000ffff, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_DEFAULT_FEATURES, }, { .name = "TI MicroSparc I", @@ -919,6 +958,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0x00016fff, .mmu_trcr_mask = 0x0000003f, + .features = CPU_DEFAULT_FEATURES, }, { .name = "TI MicroSparc II", @@ -930,6 +970,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x000000ff, .mmu_sfsr_mask = 0x00016fff, .mmu_trcr_mask = 0x00ffffff, + .features = CPU_DEFAULT_FEATURES, }, { .name = "TI MicroSparc IIep", @@ -941,6 +982,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x000000ff, .mmu_sfsr_mask = 0x00016bff, .mmu_trcr_mask = 0x00ffffff, + .features = CPU_DEFAULT_FEATURES, }, { .name = "TI SuperSparc 51", @@ -952,6 +994,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000ffff, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_DEFAULT_FEATURES, }, { .name = "TI SuperSparc 61", @@ -963,6 +1006,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000ffff, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_DEFAULT_FEATURES, }, { .name = "Ross RT625", @@ -974,6 +1018,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_DEFAULT_FEATURES, }, { .name = "Ross RT620", @@ -985,6 +1030,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_DEFAULT_FEATURES, }, { .name = "BIT B5010", @@ -996,6 +1042,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT, }, { .name = "Matsushita MN10501", @@ -1007,6 +1054,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT, }, { .name = "Weitek W8601", @@ -1018,6 +1066,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_DEFAULT_FEATURES, }, { .name = "LEON2", @@ -1029,6 +1078,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_DEFAULT_FEATURES, }, { .name = "LEON3", @@ -1040,20 +1090,137 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .features = CPU_DEFAULT_FEATURES, }, #endif }; -static const sparc_def_t *cpu_sparc_find_by_name(const unsigned char *name) +static const char * const feature_name[] = { + "float", + "float128", + "swap", + "mul", + "div", + "flush", + "fsqrt", + "fmul", + "vis1", + "vis2", +}; + +static void print_features(FILE *f, + int (*cpu_fprintf)(FILE *f, const char *fmt, ...), + uint32_t features, const char *prefix) { unsigned int i; + for (i = 0; i < ARRAY_SIZE(feature_name); i++) + if (feature_name[i] && (features & (1 << i))) { + if (prefix) + (*cpu_fprintf)(f, "%s", prefix); + (*cpu_fprintf)(f, "%s ", feature_name[i]); + } +} + +static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(feature_name); i++) + if (feature_name[i] && !strcmp(flagname, feature_name[i])) { + *features |= 1 << i; + return; + } + fprintf(stderr, "CPU feature %s not found\n", flagname); +} + +static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const unsigned char *cpu_model) +{ + unsigned int i; + const sparc_def_t *def = NULL; + char *s = strdup(cpu_model); + char *featurestr, *name = strtok(s, ","); + uint32_t plus_features = 0; + uint32_t minus_features = 0; + long long iu_version; + uint32_t fpu_version, mmu_version; + for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) { if (strcasecmp(name, sparc_defs[i].name) == 0) { - return &sparc_defs[i]; + def = &sparc_defs[i]; } } - return NULL; + if (!def) + goto error; + memcpy(cpu_def, def, sizeof(*def)); + + featurestr = strtok(NULL, ","); + while (featurestr) { + char *val; + + if (featurestr[0] == '+') { + add_flagname_to_bitmaps(featurestr + 1, &plus_features); + } else if (featurestr[0] == '-') { + add_flagname_to_bitmaps(featurestr + 1, &minus_features); + } else if ((val = strchr(featurestr, '='))) { + *val = 0; val++; + if (!strcmp(featurestr, "iu_version")) { + char *err; + + iu_version = strtoll(val, &err, 0); + if (!*val || *err) { + fprintf(stderr, "bad numerical value %s\n", val); + goto error; + } + cpu_def->iu_version = iu_version; +#ifdef DEBUG_FEATURES + fprintf(stderr, "iu_version %llx\n", iu_version); +#endif + } else if (!strcmp(featurestr, "fpu_version")) { + char *err; + + fpu_version = strtol(val, &err, 0); + if (!*val || *err) { + fprintf(stderr, "bad numerical value %s\n", val); + goto error; + } + cpu_def->fpu_version = fpu_version; +#ifdef DEBUG_FEATURES + fprintf(stderr, "fpu_version %llx\n", fpu_version); +#endif + } else if (!strcmp(featurestr, "mmu_version")) { + char *err; + + mmu_version = strtol(val, &err, 0); + if (!*val || *err) { + fprintf(stderr, "bad numerical value %s\n", val); + goto error; + } + cpu_def->mmu_version = mmu_version; +#ifdef DEBUG_FEATURES + fprintf(stderr, "mmu_version %llx\n", mmu_version); +#endif + } else { + fprintf(stderr, "unrecognized feature %s\n", featurestr); + goto error; + } + } else { + fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr); + goto error; + } + featurestr = strtok(NULL, ","); + } + cpu_def->features |= plus_features; + cpu_def->features &= ~minus_features; +#ifdef DEBUG_FEATURES + print_features(stderr, fprintf, cpu_def->features, NULL); +#endif + free(s); + return 0; + + error: + free(s); + return -1; } void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) @@ -1061,12 +1228,19 @@ void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) unsigned int i; for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) { - (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x\n", + (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x ", sparc_defs[i].name, sparc_defs[i].iu_version, sparc_defs[i].fpu_version, sparc_defs[i].mmu_version); + print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES & ~sparc_defs[i].features, "-"); + print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES & sparc_defs[i].features, "+"); + (*cpu_fprintf)(f, "\n"); } + (*cpu_fprintf)(f, "CPU feature flags (+/-): "); + print_features(f, cpu_fprintf, -1, NULL); + (*cpu_fprintf)(f, "\n"); + (*cpu_fprintf)(f, "Numerical features (=): iu_version fpu_version mmu_version\n"); } #define GET_FLAG(a,b) ((env->psr & a)?b:'-') diff --git a/target-sparc/helper.h b/target-sparc/helper.h index 4007ddfea0..8a6e660c23 100644 --- a/target-sparc/helper.h +++ b/target-sparc/helper.h @@ -48,10 +48,8 @@ uint64_t TCG_HELPER_PROTO helper_pack64(target_ulong high, target_ulong low); void TCG_HELPER_PROTO helper_std_i386(target_ulong addr, int mem_idx); void TCG_HELPER_PROTO helper_stdf(target_ulong addr, int mem_idx); void TCG_HELPER_PROTO helper_lddf(target_ulong addr, int mem_idx); -#if defined(CONFIG_USER_ONLY) -void TCG_HELPER_PROTO helper_ldqf(target_ulong addr); -void TCG_HELPER_PROTO helper_stqf(target_ulong addr); -#endif +void TCG_HELPER_PROTO helper_ldqf(target_ulong addr, int mem_idx); +void TCG_HELPER_PROTO helper_stqf(target_ulong addr, int mem_idx); uint64_t TCG_HELPER_PROTO helper_ld_asi(target_ulong addr, int asi, int size, int sign); void TCG_HELPER_PROTO helper_st_asi(target_ulong addr, uint64_t val, int asi, @@ -67,11 +65,9 @@ void TCG_HELPER_PROTO helper_fcmps(void); void TCG_HELPER_PROTO helper_fcmpd(void); void TCG_HELPER_PROTO helper_fcmpes(void); void TCG_HELPER_PROTO helper_fcmped(void); -#if defined(CONFIG_USER_ONLY) void TCG_HELPER_PROTO helper_fsqrtq(void); void TCG_HELPER_PROTO helper_fcmpq(void); void TCG_HELPER_PROTO helper_fcmpeq(void); -#endif #ifdef TARGET_SPARC64 void TCG_HELPER_PROTO helper_fabsd(void); void TCG_HELPER_PROTO helper_fcmps_fcc1(void); @@ -86,7 +82,6 @@ void TCG_HELPER_PROTO helper_fcmpes_fcc2(void); void TCG_HELPER_PROTO helper_fcmped_fcc2(void); void TCG_HELPER_PROTO helper_fcmpes_fcc3(void); void TCG_HELPER_PROTO helper_fcmped_fcc3(void); -#if defined(CONFIG_USER_ONLY) void TCG_HELPER_PROTO helper_fabsq(void); void TCG_HELPER_PROTO helper_fcmpq_fcc1(void); void TCG_HELPER_PROTO helper_fcmpq_fcc2(void); @@ -95,19 +90,12 @@ void TCG_HELPER_PROTO helper_fcmpeq_fcc1(void); void TCG_HELPER_PROTO helper_fcmpeq_fcc2(void); void TCG_HELPER_PROTO helper_fcmpeq_fcc3(void); #endif -#endif void TCG_HELPER_PROTO raise_exception(int tt); #define F_HELPER_0_0(name) void TCG_HELPER_PROTO helper_f ## name(void) -#if defined(CONFIG_USER_ONLY) #define F_HELPER_SDQ_0_0(name) \ F_HELPER_0_0(name ## s); \ F_HELPER_0_0(name ## d); \ F_HELPER_0_0(name ## q) -#else -#define F_HELPER_SDQ_0_0(name) \ - F_HELPER_0_0(name ## s); \ - F_HELPER_0_0(name ## d); -#endif F_HELPER_SDQ_0_0(add); F_HELPER_SDQ_0_0(sub); @@ -124,23 +112,17 @@ F_HELPER_SDQ_0_0(xto); #endif F_HELPER_0_0(dtos); F_HELPER_0_0(stod); -#if defined(CONFIG_USER_ONLY) F_HELPER_0_0(qtos); F_HELPER_0_0(stoq); F_HELPER_0_0(qtod); F_HELPER_0_0(dtoq); -#endif F_HELPER_0_0(stoi); F_HELPER_0_0(dtoi); -#if defined(CONFIG_USER_ONLY) F_HELPER_0_0(qtoi); -#endif #ifdef TARGET_SPARC64 F_HELPER_0_0(stox); F_HELPER_0_0(dtox); -#if defined(CONFIG_USER_ONLY) F_HELPER_0_0(qtox); -#endif F_HELPER_0_0(aligndata); void TCG_HELPER_PROTO helper_movl_FT0_0(void); void TCG_HELPER_PROTO helper_movl_DT0_0(void); diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index 13f6ac4c46..c53358e4c0 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -61,7 +61,6 @@ void helper_check_align(target_ulong addr, uint32_t align) #define F_HELPER(name, p) void helper_f##name##p(void) -#if defined(CONFIG_USER_ONLY) #define F_BINOP(name) \ F_HELPER(name, s) \ { \ @@ -75,17 +74,6 @@ void helper_check_align(target_ulong addr, uint32_t align) { \ QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \ } -#else -#define F_BINOP(name) \ - F_HELPER(name, s) \ - { \ - FT0 = float32_ ## name (FT0, FT1, &env->fp_status); \ - } \ - F_HELPER(name, d) \ - { \ - DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \ - } -#endif F_BINOP(add); F_BINOP(sub); @@ -100,14 +88,12 @@ void helper_fsmuld(void) &env->fp_status); } -#if defined(CONFIG_USER_ONLY) void helper_fdmulq(void) { QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status), float64_to_float128(DT1, &env->fp_status), &env->fp_status); } -#endif F_HELPER(neg, s) { @@ -120,13 +106,11 @@ F_HELPER(neg, d) DT0 = float64_chs(DT1); } -#if defined(CONFIG_USER_ONLY) F_HELPER(neg, q) { QT0 = float128_chs(QT1); } #endif -#endif /* Integer to float conversion. */ F_HELPER(ito, s) @@ -139,12 +123,10 @@ F_HELPER(ito, d) DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status); } -#if defined(CONFIG_USER_ONLY) F_HELPER(ito, q) { QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status); } -#endif #ifdef TARGET_SPARC64 F_HELPER(xto, s) @@ -156,13 +138,12 @@ F_HELPER(xto, d) { DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status); } -#if defined(CONFIG_USER_ONLY) + F_HELPER(xto, q) { QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status); } #endif -#endif #undef F_HELPER /* floating point conversion */ @@ -176,7 +157,6 @@ void helper_fstod(void) DT0 = float32_to_float64(FT1, &env->fp_status); } -#if defined(CONFIG_USER_ONLY) void helper_fqtos(void) { FT0 = float128_to_float32(QT1, &env->fp_status); @@ -196,7 +176,6 @@ void helper_fdtoq(void) { QT0 = float64_to_float128(DT1, &env->fp_status); } -#endif /* Float to integer conversion. */ void helper_fstoi(void) @@ -209,12 +188,10 @@ void helper_fdtoi(void) *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status); } -#if defined(CONFIG_USER_ONLY) void helper_fqtoi(void) { *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status); } -#endif #ifdef TARGET_SPARC64 void helper_fstox(void) @@ -227,12 +204,10 @@ void helper_fdtox(void) *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status); } -#if defined(CONFIG_USER_ONLY) void helper_fqtox(void) { *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status); } -#endif void helper_faligndata(void) { @@ -722,13 +697,11 @@ void helper_fabsd(void) DT0 = float64_abs(DT1); } -#if defined(CONFIG_USER_ONLY) void helper_fabsq(void) { QT0 = float128_abs(QT1); } #endif -#endif void helper_fsqrts(void) { @@ -740,12 +713,10 @@ void helper_fsqrtd(void) DT0 = float64_sqrt(DT1, &env->fp_status); } -#if defined(CONFIG_USER_ONLY) void helper_fsqrtq(void) { QT0 = float128_sqrt(QT1, &env->fp_status); } -#endif #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \ void glue(helper_, name) (void) \ @@ -784,38 +755,34 @@ GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0); GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1); GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1); -#ifdef CONFIG_USER_ONLY GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0); GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1); -#endif #ifdef TARGET_SPARC64 GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0); GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0); +GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0); GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0); GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0); +GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0); GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0); GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0); +GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0); GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1); GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1); +GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1); GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1); GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1); +GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1); GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1); GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1); -#ifdef CONFIG_USER_ONLY -GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0); -GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0); -GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0); -GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1); -GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1); GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1); #endif -#endif #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && defined(DEBUG_MXCC) static void dump_mxcc(CPUState *env) @@ -2074,11 +2041,9 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) case 8: *((int64_t *)&DT0) = val; break; -#if defined(CONFIG_USER_ONLY) case 16: // XXX break; -#endif } } @@ -2119,11 +2084,9 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd) case 8: val = *((int64_t *)&DT0); break; -#if defined(CONFIG_USER_ONLY) case 16: // XXX break; -#endif } helper_st_asi(addr, val, asi, size); } @@ -2299,27 +2262,73 @@ void helper_lddf(target_ulong addr, int mem_idx) #endif } -#if defined(CONFIG_USER_ONLY) -void helper_ldqf(target_ulong addr) +void helper_ldqf(target_ulong addr, int mem_idx) { // XXX add 128 bit load CPU_QuadU u; +#if !defined(CONFIG_USER_ONLY) + switch (mem_idx) { + case 0: + u.ll.upper = ldq_user(ADDR(addr)); + u.ll.lower = ldq_user(ADDR(addr + 8)); + QT0 = u.q; + break; + case 1: + u.ll.upper = ldq_kernel(ADDR(addr)); + u.ll.lower = ldq_kernel(ADDR(addr + 8)); + QT0 = u.q; + break; +#ifdef TARGET_SPARC64 + case 2: + u.ll.upper = ldq_hypv(ADDR(addr)); + u.ll.lower = ldq_hypv(ADDR(addr + 8)); + QT0 = u.q; + break; +#endif + default: + break; + } +#else u.ll.upper = ldq_raw(ADDR(addr)); u.ll.lower = ldq_raw(ADDR(addr + 8)); QT0 = u.q; +#endif } -void helper_stqf(target_ulong addr) +void helper_stqf(target_ulong addr, int mem_idx) { // XXX add 128 bit store CPU_QuadU u; +#if !defined(CONFIG_USER_ONLY) + switch (mem_idx) { + case 0: + u.q = QT0; + stq_user(ADDR(addr), u.ll.upper); + stq_user(ADDR(addr + 8), u.ll.lower); + break; + case 1: + u.q = QT0; + stq_kernel(ADDR(addr), u.ll.upper); + stq_kernel(ADDR(addr + 8), u.ll.lower); + break; +#ifdef TARGET_SPARC64 + case 2: + u.q = QT0; + stq_hypv(ADDR(addr), u.ll.upper); + stq_hypv(ADDR(addr + 8), u.ll.lower); + break; +#endif + default: + break; + } +#else u.q = QT0; stq_raw(ADDR(addr), u.ll.upper); stq_raw(ADDR(addr + 8), u.ll.lower); -} #endif +} #undef ADDR diff --git a/target-sparc/translate.c b/target-sparc/translate.c index c5f9c69901..b9bc2db217 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -63,6 +63,7 @@ typedef struct DisasContext { int mem_idx; int fpu_enabled; struct TranslationBlock *tb; + uint32_t features; } DisasContext; extern FILE *logfile; @@ -140,7 +141,6 @@ static void gen_op_store_DT0_fpr(unsigned int dst) tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[dst + 1])); } -#ifdef CONFIG_USER_ONLY static void gen_op_load_fpr_QT0(unsigned int src) { tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src])); @@ -176,7 +176,6 @@ static void gen_op_store_QT0_fpr(unsigned int dst) tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, qt0) + offsetof(CPU_QuadU, l.lowest)); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[dst + 3])); } -#endif /* moves */ #ifdef CONFIG_USER_ONLY @@ -1463,14 +1462,12 @@ static GenOpFunc * const gen_fcmpd[4] = { helper_fcmpd_fcc3, }; -#if defined(CONFIG_USER_ONLY) static GenOpFunc * const gen_fcmpq[4] = { helper_fcmpq, helper_fcmpq_fcc1, helper_fcmpq_fcc2, helper_fcmpq_fcc3, }; -#endif static GenOpFunc * const gen_fcmpes[4] = { helper_fcmpes, @@ -1486,14 +1483,12 @@ static GenOpFunc * const gen_fcmped[4] = { helper_fcmped_fcc3, }; -#if defined(CONFIG_USER_ONLY) static GenOpFunc * const gen_fcmpeq[4] = { helper_fcmpeq, helper_fcmpeq_fcc1, helper_fcmpeq_fcc2, helper_fcmpeq_fcc3, }; -#endif static inline void gen_op_fcmps(int fccno) { @@ -1505,12 +1500,10 @@ static inline void gen_op_fcmpd(int fccno) tcg_gen_helper_0_0(gen_fcmpd[fccno]); } -#if defined(CONFIG_USER_ONLY) static inline void gen_op_fcmpq(int fccno) { tcg_gen_helper_0_0(gen_fcmpq[fccno]); } -#endif static inline void gen_op_fcmpes(int fccno) { @@ -1522,12 +1515,10 @@ static inline void gen_op_fcmped(int fccno) tcg_gen_helper_0_0(gen_fcmped[fccno]); } -#if defined(CONFIG_USER_ONLY) static inline void gen_op_fcmpeq(int fccno) { tcg_gen_helper_0_0(gen_fcmpeq[fccno]); } -#endif #else @@ -1541,12 +1532,10 @@ static inline void gen_op_fcmpd(int fccno) tcg_gen_helper_0_0(helper_fcmpd); } -#if defined(CONFIG_USER_ONLY) static inline void gen_op_fcmpq(int fccno) { tcg_gen_helper_0_0(helper_fcmpq); } -#endif static inline void gen_op_fcmpes(int fccno) { @@ -1558,15 +1547,12 @@ static inline void gen_op_fcmped(int fccno) tcg_gen_helper_0_0(helper_fcmped); } -#if defined(CONFIG_USER_ONLY) static inline void gen_op_fcmpeq(int fccno) { tcg_gen_helper_0_0(helper_fcmpeq); } #endif -#endif - static inline void gen_op_fpexception_im(int fsr_flags) { tcg_gen_andi_tl(cpu_fsr, cpu_fsr, ~FSR_FTT_MASK); @@ -1820,6 +1806,13 @@ static inline TCGv get_src2(unsigned int insn, TCGv def) return r_rs2; } +#define CHECK_IU_FEATURE(dc, FEATURE) \ + if (!((dc)->features & CPU_FEATURE_ ## FEATURE)) \ + goto illegal_insn; +#define CHECK_FPU_FEATURE(dc, FEATURE) \ + if (!((dc)->features & CPU_FEATURE_ ## FEATURE)) \ + goto nfpu_insn; + /* before an instruction, dc->pc must be static */ static void disas_sparc_insn(DisasContext * dc) { @@ -2255,6 +2248,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_store_FT0_fpr(rd); break; case 0x29: /* fsqrts */ + CHECK_FPU_FEATURE(dc, FSQRT); gen_op_load_fpr_FT1(rs2); gen_clear_float_exceptions(); tcg_gen_helper_0_0(helper_fsqrts); @@ -2262,6 +2256,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_store_FT0_fpr(rd); break; case 0x2a: /* fsqrtd */ + CHECK_FPU_FEATURE(dc, FSQRT); gen_op_load_fpr_DT1(DFPREG(rs2)); gen_clear_float_exceptions(); tcg_gen_helper_0_0(helper_fsqrtd); @@ -2269,16 +2264,13 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x2b: /* fsqrtq */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_clear_float_exceptions(); tcg_gen_helper_0_0(helper_fsqrtq); tcg_gen_helper_0_0(helper_check_ieee_exceptions); gen_op_store_QT0_fpr(QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0x41: gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); @@ -2296,7 +2288,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x43: /* faddq */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT0(QFPREG(rs1)); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_clear_float_exceptions(); @@ -2304,9 +2296,6 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_helper_0_0(helper_check_ieee_exceptions); gen_op_store_QT0_fpr(QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0x45: gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); @@ -2324,7 +2313,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x47: /* fsubq */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT0(QFPREG(rs1)); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_clear_float_exceptions(); @@ -2332,10 +2321,8 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_helper_0_0(helper_check_ieee_exceptions); gen_op_store_QT0_fpr(QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif - case 0x49: + case 0x49: /* fmuls */ + CHECK_FPU_FEATURE(dc, FMUL); gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); gen_clear_float_exceptions(); @@ -2343,7 +2330,8 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_helper_0_0(helper_check_ieee_exceptions); gen_op_store_FT0_fpr(rd); break; - case 0x4a: + case 0x4a: /* fmuld */ + CHECK_FPU_FEATURE(dc, FMUL); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); gen_clear_float_exceptions(); @@ -2352,7 +2340,8 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x4b: /* fmulq */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); + CHECK_FPU_FEATURE(dc, FMUL); gen_op_load_fpr_QT0(QFPREG(rs1)); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_clear_float_exceptions(); @@ -2360,9 +2349,6 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_helper_0_0(helper_check_ieee_exceptions); gen_op_store_QT0_fpr(QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0x4d: gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); @@ -2380,7 +2366,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x4f: /* fdivq */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT0(QFPREG(rs1)); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_clear_float_exceptions(); @@ -2388,9 +2374,6 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_helper_0_0(helper_check_ieee_exceptions); gen_op_store_QT0_fpr(QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0x69: gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); @@ -2400,7 +2383,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x6e: /* fdmulq */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); gen_clear_float_exceptions(); @@ -2408,9 +2391,6 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_helper_0_0(helper_check_ieee_exceptions); gen_op_store_QT0_fpr(QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0xc4: gen_op_load_fpr_FT1(rs2); gen_clear_float_exceptions(); @@ -2426,16 +2406,13 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_store_FT0_fpr(rd); break; case 0xc7: /* fqtos */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_clear_float_exceptions(); tcg_gen_helper_0_0(helper_fqtos); tcg_gen_helper_0_0(helper_check_ieee_exceptions); gen_op_store_FT0_fpr(rd); break; -#else - goto nfpu_insn; -#endif case 0xc8: gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fitod); @@ -2447,43 +2424,31 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0xcb: /* fqtod */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_clear_float_exceptions(); tcg_gen_helper_0_0(helper_fqtod); tcg_gen_helper_0_0(helper_check_ieee_exceptions); gen_op_store_DT0_fpr(DFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0xcc: /* fitoq */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fitoq); gen_op_store_QT0_fpr(QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0xcd: /* fstoq */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fstoq); gen_op_store_QT0_fpr(QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0xce: /* fdtoq */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fdtoq); gen_op_store_QT0_fpr(QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0xd1: gen_op_load_fpr_FT1(rs2); gen_clear_float_exceptions(); @@ -2499,57 +2464,45 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_store_FT0_fpr(rd); break; case 0xd3: /* fqtoi */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_clear_float_exceptions(); tcg_gen_helper_0_0(helper_fqtoi); tcg_gen_helper_0_0(helper_check_ieee_exceptions); gen_op_store_FT0_fpr(rd); break; -#else - goto nfpu_insn; -#endif #ifdef TARGET_SPARC64 case 0x2: /* V9 fmovd */ gen_op_load_fpr_DT0(DFPREG(rs2)); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x3: /* V9 fmovq */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT0(QFPREG(rs2)); gen_op_store_QT0_fpr(QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0x6: /* V9 fnegd */ gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fnegd); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x7: /* V9 fnegq */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT1(QFPREG(rs2)); tcg_gen_helper_0_0(helper_fnegq); gen_op_store_QT0_fpr(QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0xa: /* V9 fabsd */ gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fabsd); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0xb: /* V9 fabsq */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT1(QFPREG(rs2)); tcg_gen_helper_0_0(helper_fabsq); gen_op_store_QT0_fpr(QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0x81: /* V9 fstox */ gen_op_load_fpr_FT1(rs2); gen_clear_float_exceptions(); @@ -2565,16 +2518,13 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x83: /* V9 fqtox */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_clear_float_exceptions(); tcg_gen_helper_0_0(helper_fqtox); tcg_gen_helper_0_0(helper_check_ieee_exceptions); gen_op_store_DT0_fpr(DFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0x84: /* V9 fxtos */ gen_op_load_fpr_DT1(DFPREG(rs2)); gen_clear_float_exceptions(); @@ -2590,16 +2540,13 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x8c: /* V9 fxtoq */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_DT1(DFPREG(rs2)); gen_clear_float_exceptions(); tcg_gen_helper_0_0(helper_fxtoq); tcg_gen_helper_0_0(helper_check_ieee_exceptions); gen_op_store_QT0_fpr(QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif #endif default: goto illegal_insn; @@ -2640,9 +2587,9 @@ static void disas_sparc_insn(DisasContext * dc) gen_set_label(l1); break; } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr -#if defined(CONFIG_USER_ONLY) int l1; + CHECK_FPU_FEATURE(dc, FLOAT128); l1 = gen_new_label(); cond = GET_FIELD_SP(insn, 14, 17); cpu_src1 = get_src1(insn, cpu_src1); @@ -2652,9 +2599,6 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_store_QT0_fpr(QFPREG(rd)); gen_set_label(l1); break; -#else - goto nfpu_insn; -#endif } #endif switch (xop) { @@ -2681,12 +2625,9 @@ static void disas_sparc_insn(DisasContext * dc) FMOVCC(D, 0); break; case 0x003: /* V9 fmovqcc %fcc0 */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); FMOVCC(Q, 0); break; -#else - goto nfpu_insn; -#endif case 0x041: /* V9 fmovscc %fcc1 */ FMOVCC(F, 1); break; @@ -2694,12 +2635,9 @@ static void disas_sparc_insn(DisasContext * dc) FMOVCC(D, 1); break; case 0x043: /* V9 fmovqcc %fcc1 */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); FMOVCC(Q, 1); break; -#else - goto nfpu_insn; -#endif case 0x081: /* V9 fmovscc %fcc2 */ FMOVCC(F, 2); break; @@ -2707,12 +2645,9 @@ static void disas_sparc_insn(DisasContext * dc) FMOVCC(D, 2); break; case 0x083: /* V9 fmovqcc %fcc2 */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); FMOVCC(Q, 2); break; -#else - goto nfpu_insn; -#endif case 0x0c1: /* V9 fmovscc %fcc3 */ FMOVCC(F, 3); break; @@ -2720,12 +2655,9 @@ static void disas_sparc_insn(DisasContext * dc) FMOVCC(D, 3); break; case 0x0c3: /* V9 fmovqcc %fcc3 */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); FMOVCC(Q, 3); break; -#else - goto nfpu_insn; -#endif #undef FMOVCC #define FMOVCC(size_FDQ, icc) \ { \ @@ -2749,12 +2681,9 @@ static void disas_sparc_insn(DisasContext * dc) case 0x102: /* V9 fmovdcc %icc */ FMOVCC(D, 0); case 0x103: /* V9 fmovqcc %icc */ -#if defined(CONFIG_USER_ONLY) - FMOVCC(D, 0); + CHECK_FPU_FEATURE(dc, FLOAT128); + FMOVCC(Q, 0); break; -#else - goto nfpu_insn; -#endif case 0x181: /* V9 fmovscc %xcc */ FMOVCC(F, 1); break; @@ -2762,12 +2691,9 @@ static void disas_sparc_insn(DisasContext * dc) FMOVCC(D, 1); break; case 0x183: /* V9 fmovqcc %xcc */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); FMOVCC(Q, 1); break; -#else - goto nfpu_insn; -#endif #undef FMOVCC #endif case 0x51: /* fcmps, V9 %fcc */ @@ -2781,14 +2707,11 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_fcmpd(rd & 3); break; case 0x53: /* fcmpq, V9 %fcc */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT0(QFPREG(rs1)); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_op_fcmpq(rd & 3); break; -#else /* !defined(CONFIG_USER_ONLY) */ - goto nfpu_insn; -#endif case 0x55: /* fcmpes, V9 %fcc */ gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); @@ -2800,14 +2723,11 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_fcmped(rd & 3); break; case 0x57: /* fcmpeq, V9 %fcc */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT0(QFPREG(rs1)); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_op_fcmpeq(rd & 3); break; -#else/* !defined(CONFIG_USER_ONLY) */ - goto nfpu_insn; -#endif default: goto illegal_insn; } @@ -2979,11 +2899,13 @@ static void disas_sparc_insn(DisasContext * dc) break; #endif case 0xa: + CHECK_IU_FEATURE(dc, MUL); gen_op_umul(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) gen_op_logic_cc(cpu_dst); break; case 0xb: + CHECK_IU_FEATURE(dc, MUL); gen_op_smul(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) gen_op_logic_cc(cpu_dst); @@ -3004,11 +2926,13 @@ static void disas_sparc_insn(DisasContext * dc) break; #endif case 0xe: + CHECK_IU_FEATURE(dc, DIV); tcg_gen_helper_1_2(helper_udiv, cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) gen_op_div_cc(cpu_dst); break; case 0xf: + CHECK_IU_FEATURE(dc, DIV); tcg_gen_helper_1_2(helper_sdiv, cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) gen_op_div_cc(cpu_dst); @@ -3476,6 +3400,7 @@ static void disas_sparc_insn(DisasContext * dc) // XXX goto illegal_insn; case 0x010: /* VIS I array8 */ + CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = get_src1(insn, cpu_src1); gen_movl_reg_TN(rs2, cpu_src2); tcg_gen_helper_1_2(helper_array8, cpu_dst, cpu_src1, @@ -3483,6 +3408,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_movl_TN_reg(rd, cpu_dst); break; case 0x012: /* VIS I array16 */ + CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = get_src1(insn, cpu_src1); gen_movl_reg_TN(rs2, cpu_src2); tcg_gen_helper_1_2(helper_array8, cpu_dst, cpu_src1, @@ -3491,6 +3417,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_movl_TN_reg(rd, cpu_dst); break; case 0x014: /* VIS I array32 */ + CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = get_src1(insn, cpu_src1); gen_movl_reg_TN(rs2, cpu_src2); tcg_gen_helper_1_2(helper_array8, cpu_dst, cpu_src1, @@ -3499,6 +3426,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_movl_TN_reg(rd, cpu_dst); break; case 0x018: /* VIS I alignaddr */ + CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = get_src1(insn, cpu_src1); gen_movl_reg_TN(rs2, cpu_src2); tcg_gen_helper_1_2(helper_alignaddr, cpu_dst, cpu_src1, @@ -3510,90 +3438,105 @@ static void disas_sparc_insn(DisasContext * dc) // XXX goto illegal_insn; case 0x020: /* VIS I fcmple16 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fcmple16); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x022: /* VIS I fcmpne16 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fcmpne16); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x024: /* VIS I fcmple32 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fcmple32); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x026: /* VIS I fcmpne32 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fcmpne32); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x028: /* VIS I fcmpgt16 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fcmpgt16); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x02a: /* VIS I fcmpeq16 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fcmpeq16); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x02c: /* VIS I fcmpgt32 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fcmpgt32); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x02e: /* VIS I fcmpeq32 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fcmpeq32); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x031: /* VIS I fmul8x16 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fmul8x16); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x033: /* VIS I fmul8x16au */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fmul8x16au); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x035: /* VIS I fmul8x16al */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fmul8x16al); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x036: /* VIS I fmul8sux16 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fmul8sux16); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x037: /* VIS I fmul8ulx16 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fmul8ulx16); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x038: /* VIS I fmuld8sux16 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fmuld8sux16); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x039: /* VIS I fmuld8ulx16 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fmuld8ulx16); @@ -3606,12 +3549,14 @@ static void disas_sparc_insn(DisasContext * dc) // XXX goto illegal_insn; case 0x048: /* VIS I faligndata */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_faligndata); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x04b: /* VIS I fpmerge */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fpmerge); @@ -3621,228 +3566,269 @@ static void disas_sparc_insn(DisasContext * dc) // XXX goto illegal_insn; case 0x04d: /* VIS I fexpand */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fexpand); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x050: /* VIS I fpadd16 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fpadd16); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x051: /* VIS I fpadd16s */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fpadd16s); gen_op_store_FT0_fpr(rd); break; case 0x052: /* VIS I fpadd32 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fpadd32); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x053: /* VIS I fpadd32s */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fpadd32s); gen_op_store_FT0_fpr(rd); break; case 0x054: /* VIS I fpsub16 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fpsub16); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x055: /* VIS I fpsub16s */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fpsub16s); gen_op_store_FT0_fpr(rd); break; case 0x056: /* VIS I fpsub32 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fpadd32); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x057: /* VIS I fpsub32s */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fpsub32s); gen_op_store_FT0_fpr(rd); break; case 0x060: /* VIS I fzero */ + CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_helper_0_0(helper_movl_DT0_0); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x061: /* VIS I fzeros */ + CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_helper_0_0(helper_movl_FT0_0); gen_op_store_FT0_fpr(rd); break; case 0x062: /* VIS I fnor */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fnor); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x063: /* VIS I fnors */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fnors); gen_op_store_FT0_fpr(rd); break; case 0x064: /* VIS I fandnot2 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT1(DFPREG(rs1)); gen_op_load_fpr_DT0(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fandnot); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x065: /* VIS I fandnot2s */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT1(rs1); gen_op_load_fpr_FT0(rs2); tcg_gen_helper_0_0(helper_fandnots); gen_op_store_FT0_fpr(rd); break; case 0x066: /* VIS I fnot2 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fnot); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x067: /* VIS I fnot2s */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fnot); gen_op_store_FT0_fpr(rd); break; case 0x068: /* VIS I fandnot1 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fandnot); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x069: /* VIS I fandnot1s */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fandnots); gen_op_store_FT0_fpr(rd); break; case 0x06a: /* VIS I fnot1 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT1(DFPREG(rs1)); tcg_gen_helper_0_0(helper_fnot); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x06b: /* VIS I fnot1s */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT1(rs1); tcg_gen_helper_0_0(helper_fnot); gen_op_store_FT0_fpr(rd); break; case 0x06c: /* VIS I fxor */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fxor); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x06d: /* VIS I fxors */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fxors); gen_op_store_FT0_fpr(rd); break; case 0x06e: /* VIS I fnand */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fnand); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x06f: /* VIS I fnands */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fnands); gen_op_store_FT0_fpr(rd); break; case 0x070: /* VIS I fand */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fand); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x071: /* VIS I fands */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fands); gen_op_store_FT0_fpr(rd); break; case 0x072: /* VIS I fxnor */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fxnor); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x073: /* VIS I fxnors */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fxnors); gen_op_store_FT0_fpr(rd); break; case 0x074: /* VIS I fsrc1 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x075: /* VIS I fsrc1s */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT0(rs1); gen_op_store_FT0_fpr(rd); break; case 0x076: /* VIS I fornot2 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT1(DFPREG(rs1)); gen_op_load_fpr_DT0(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fornot); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x077: /* VIS I fornot2s */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT1(rs1); gen_op_load_fpr_FT0(rs2); tcg_gen_helper_0_0(helper_fornots); gen_op_store_FT0_fpr(rd); break; case 0x078: /* VIS I fsrc2 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs2)); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x079: /* VIS I fsrc2s */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT0(rs2); gen_op_store_FT0_fpr(rd); break; case 0x07a: /* VIS I fornot1 */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_fornot); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x07b: /* VIS I fornot1s */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fornots); gen_op_store_FT0_fpr(rd); break; case 0x07c: /* VIS I for */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); tcg_gen_helper_0_0(helper_for); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x07d: /* VIS I fors */ + CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_FT0(rs1); gen_op_load_fpr_FT1(rs2); tcg_gen_helper_0_0(helper_fors); gen_op_store_FT0_fpr(rd); break; case 0x07e: /* VIS I fone */ + CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_helper_0_0(helper_movl_DT0_1); gen_op_store_DT0_fpr(DFPREG(rd)); break; case 0x07f: /* VIS I fones */ + CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_helper_0_0(helper_movl_FT0_1); gen_op_store_FT0_fpr(rd); break; @@ -3921,6 +3907,8 @@ static void disas_sparc_insn(DisasContext * dc) goto jmp_insn; #endif case 0x3b: /* flush */ + if (!((dc)->features & CPU_FEATURE_FLUSH)) + goto unimp_flush; tcg_gen_helper_0_1(helper_flush, cpu_dst); break; case 0x3c: /* save */ @@ -4034,6 +4022,7 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_qemu_st8(tcg_const_tl(0xff), cpu_addr, dc->mem_idx); break; case 0x0f: /* swap register with memory. Also atomically */ + CHECK_IU_FEATURE(dc, SWAP); tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); gen_movl_reg_TN(rd, cpu_val); ABI32_MASK(cpu_addr); @@ -4113,6 +4102,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_ldstub_asi(cpu_val, cpu_addr, insn); break; case 0x1f: /* swap reg with alt. memory. Also atomically */ + CHECK_IU_FEATURE(dc, SWAP); #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; @@ -4163,13 +4153,10 @@ static void disas_sparc_insn(DisasContext * dc) case 0x3d: /* V9 prefetcha, no effect */ goto skip_move; case 0x32: /* V9 ldqfa */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd)); goto skip_move; -#else - goto nfpu_insn; -#endif #endif default: goto illegal_insn; @@ -4196,15 +4183,12 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_helper_0_0(helper_ldfsr); break; case 0x22: /* load quad fpreg */ -#if defined(CONFIG_USER_ONLY) + CHECK_FPU_FEATURE(dc, FLOAT128); tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); - tcg_gen_helper_0_1(helper_ldqf, cpu_addr); + tcg_gen_helper_0_2(helper_ldqf, cpu_addr, dc->mem_idx); gen_op_store_QT0_fpr(QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0x23: /* load double fpreg */ tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); @@ -4334,16 +4318,13 @@ static void disas_sparc_insn(DisasContext * dc) break; case 0x26: #ifdef TARGET_SPARC64 -#if defined(CONFIG_USER_ONLY) /* V9 stqf, store quad fpreg */ + CHECK_FPU_FEATURE(dc, FLOAT128); tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); gen_op_load_fpr_QT0(QFPREG(rd)); - tcg_gen_helper_0_1(helper_stqf, cpu_addr); + tcg_gen_helper_0_2(helper_stqf, cpu_addr, dc->mem_idx); break; -#else - goto nfpu_insn; -#endif #else /* !TARGET_SPARC64 */ /* stdfq, store floating point queue */ #if defined(CONFIG_USER_ONLY) @@ -4375,14 +4356,12 @@ static void disas_sparc_insn(DisasContext * dc) gen_stf_asi(cpu_addr, insn, 4, rd); break; case 0x36: /* V9 stqfa */ -#if defined(CONFIG_USER_ONLY) - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); + CHECK_FPU_FEATURE(dc, FLOAT128); + tcg_gen_helper_0_2(helper_check_align, cpu_addr, + tcg_const_i32(7)); gen_op_load_fpr_QT0(QFPREG(rd)); gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd)); break; -#else - goto nfpu_insn; -#endif case 0x37: /* V9 stdfa */ tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); gen_op_load_fpr_DT0(DFPREG(rd)); @@ -4433,25 +4412,30 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_ILL_INSN)); dc->is_br = 1; return; + unimp_flush: + save_state(dc, cpu_cond); + tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_UNIMP_FLUSH)); + dc->is_br = 1; + return; #if !defined(CONFIG_USER_ONLY) priv_insn: save_state(dc, cpu_cond); tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_PRIV_INSN)); dc->is_br = 1; return; +#endif nfpu_insn: save_state(dc, cpu_cond); gen_op_fpexception_im(FSR_FTT_UNIMPFPOP); dc->is_br = 1; return; -#ifndef TARGET_SPARC64 +#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) nfq_insn: save_state(dc, cpu_cond); gen_op_fpexception_im(FSR_FTT_SEQ_ERROR); dc->is_br = 1; return; #endif -#endif #ifndef TARGET_SPARC64 ncp_insn: save_state(dc, cpu_cond); @@ -4480,7 +4464,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, last_pc = dc->pc; dc->npc = (target_ulong) tb->cs_base; dc->mem_idx = cpu_mmu_index(env); - dc->fpu_enabled = cpu_fpu_enabled(env); + dc->features = env->features; + if ((dc->features & CPU_FEATURE_FLOAT)) { + dc->fpu_enabled = cpu_fpu_enabled(env); +#if defined(CONFIG_USER_ONLY) + dc->features |= CPU_FEATURE_FLOAT128; +#endif + } else + dc->fpu_enabled = 0; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; cpu_tmp0 = tcg_temp_new(TCG_TYPE_TL);