qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [4399] CPU feature selection support


From: Blue Swirl
Subject: [Qemu-devel] [4399] CPU feature selection support
Date: Fri, 09 May 2008 20:13:43 +0000

Revision: 4399
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4399
Author:   blueswir1
Date:     2008-05-09 20:13:43 +0000 (Fri, 09 May 2008)

Log Message:
-----------
CPU feature selection support

Modified Paths:
--------------
    trunk/target-sparc/cpu.h
    trunk/target-sparc/exec.h
    trunk/target-sparc/helper.c
    trunk/target-sparc/helper.h
    trunk/target-sparc/op_helper.c
    trunk/target-sparc/translate.c

Modified: trunk/target-sparc/cpu.h
===================================================================
--- trunk/target-sparc/cpu.h    2008-05-09 20:12:09 UTC (rev 4398)
+++ trunk/target-sparc/cpu.h    2008-05-09 20:13:43 UTC (rev 4399)
@@ -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 @@
     /* 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 @@
     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 @@
 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);

Modified: trunk/target-sparc/exec.h
===================================================================
--- trunk/target-sparc/exec.h   2008-05-09 20:12:09 UTC (rev 4398)
+++ trunk/target-sparc/exec.h   2008-05-09 20:13:43 UTC (rev 4399)
@@ -39,10 +39,8 @@
 #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"

Modified: trunk/target-sparc/helper.c
===================================================================
--- trunk/target-sparc/helper.c 2008-05-09 20:12:09 UTC (rev 4398)
+++ trunk/target-sparc/helper.c 2008-05-09 20:13:43 UTC (rev 4399)
@@ -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 @@
     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 @@
 #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 @@
     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 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "Fujitsu Sparc64 III",
@@ -739,6 +757,7 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "Fujitsu Sparc64 IV",
@@ -746,6 +765,7 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "Fujitsu Sparc64 V",
@@ -753,6 +773,7 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "TI UltraSparc I",
@@ -760,6 +781,7 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "TI UltraSparc II",
@@ -767,6 +789,7 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "TI UltraSparc IIi",
@@ -774,6 +797,7 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "TI UltraSparc IIe",
@@ -781,6 +805,7 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "Sun UltraSparc III",
@@ -788,6 +813,7 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "Sun UltraSparc III Cu",
@@ -795,6 +821,7 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "Sun UltraSparc IIIi",
@@ -802,6 +829,7 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "Sun UltraSparc IV",
@@ -809,6 +837,7 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "Sun UltraSparc IV+",
@@ -816,6 +845,7 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "Sun UltraSparc IIIi+",
@@ -823,6 +853,7 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "NEC UltraSparc I",
@@ -830,6 +861,7 @@
                        | (MAXTL << 8) | (NWINDOWS - 1)),
         .fpu_version = 0x00000000,
         .mmu_version = 0,
+        .features = CPU_DEFAULT_FEATURES,
     },
 #else
     {
@@ -842,6 +874,7 @@
         .mmu_cxr_mask = 0x0000003f,
         .mmu_sfsr_mask = 0xffffffff,
         .mmu_trcr_mask = 0xffffffff,
+        .features = CPU_FEATURE_FLOAT,
     },
     {
         .name = "Fujitsu MB86904",
@@ -853,6 +886,7 @@
         .mmu_cxr_mask = 0x000000ff,
         .mmu_sfsr_mask = 0x00016fff,
         .mmu_trcr_mask = 0x00ffffff,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "Fujitsu MB86907",
@@ -864,6 +898,7 @@
         .mmu_cxr_mask = 0x000000ff,
         .mmu_sfsr_mask = 0x00016fff,
         .mmu_trcr_mask = 0xffffffff,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "LSI L64811",
@@ -875,6 +910,7 @@
         .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 @@
         .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 @@
         .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 @@
         .mmu_cxr_mask = 0x0000ffff,
         .mmu_sfsr_mask = 0xffffffff,
         .mmu_trcr_mask = 0xffffffff,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "TI MicroSparc I",
@@ -919,6 +958,7 @@
         .mmu_cxr_mask = 0x0000003f,
         .mmu_sfsr_mask = 0x00016fff,
         .mmu_trcr_mask = 0x0000003f,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "TI MicroSparc II",
@@ -930,6 +970,7 @@
         .mmu_cxr_mask = 0x000000ff,
         .mmu_sfsr_mask = 0x00016fff,
         .mmu_trcr_mask = 0x00ffffff,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "TI MicroSparc IIep",
@@ -941,6 +982,7 @@
         .mmu_cxr_mask = 0x000000ff,
         .mmu_sfsr_mask = 0x00016bff,
         .mmu_trcr_mask = 0x00ffffff,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "TI SuperSparc 51",
@@ -952,6 +994,7 @@
         .mmu_cxr_mask = 0x0000ffff,
         .mmu_sfsr_mask = 0xffffffff,
         .mmu_trcr_mask = 0xffffffff,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "TI SuperSparc 61",
@@ -963,6 +1006,7 @@
         .mmu_cxr_mask = 0x0000ffff,
         .mmu_sfsr_mask = 0xffffffff,
         .mmu_trcr_mask = 0xffffffff,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "Ross RT625",
@@ -974,6 +1018,7 @@
         .mmu_cxr_mask = 0x0000003f,
         .mmu_sfsr_mask = 0xffffffff,
         .mmu_trcr_mask = 0xffffffff,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "Ross RT620",
@@ -985,6 +1030,7 @@
         .mmu_cxr_mask = 0x0000003f,
         .mmu_sfsr_mask = 0xffffffff,
         .mmu_trcr_mask = 0xffffffff,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "BIT B5010",
@@ -996,6 +1042,7 @@
         .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 @@
         .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 @@
         .mmu_cxr_mask = 0x0000003f,
         .mmu_sfsr_mask = 0xffffffff,
         .mmu_trcr_mask = 0xffffffff,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "LEON2",
@@ -1029,6 +1078,7 @@
         .mmu_cxr_mask = 0x0000003f,
         .mmu_sfsr_mask = 0xffffffff,
         .mmu_trcr_mask = 0xffffffff,
+        .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "LEON3",
@@ -1040,20 +1090,137 @@
         .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 @@
     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:'-')

Modified: trunk/target-sparc/helper.h
===================================================================
--- trunk/target-sparc/helper.h 2008-05-09 20:12:09 UTC (rev 4398)
+++ trunk/target-sparc/helper.h 2008-05-09 20:13:43 UTC (rev 4399)
@@ -48,10 +48,8 @@
 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_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_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_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 @@
 #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);

Modified: trunk/target-sparc/op_helper.c
===================================================================
--- trunk/target-sparc/op_helper.c      2008-05-09 20:12:09 UTC (rev 4398)
+++ trunk/target-sparc/op_helper.c      2008-05-09 20:13:43 UTC (rev 4399)
@@ -61,7 +61,6 @@
 
 #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 @@
     {                                                           \
         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 @@
                       &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 @@
     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 @@
     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 @@
 {
     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 @@
     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 @@
 {
     QT0 = float64_to_float128(DT1, &env->fp_status);
 }
-#endif
 
 /* Float to integer conversion.  */
 void helper_fstoi(void)
@@ -209,12 +188,10 @@
     *((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 @@
     *((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 @@
     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 @@
     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(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 @@
     case 8:
         *((int64_t *)&DT0) = val;
         break;
-#if defined(CONFIG_USER_ONLY)
     case 16:
         // XXX
         break;
-#endif
     }
 }
 
@@ -2119,11 +2084,9 @@
     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 @@
 #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
 }
-#endif
 
 #undef ADDR
 

Modified: trunk/target-sparc/translate.c
===================================================================
--- trunk/target-sparc/translate.c      2008-05-09 20:12:09 UTC (rev 4398)
+++ trunk/target-sparc/translate.c      2008-05-09 20:13:43 UTC (rev 4399)
@@ -63,6 +63,7 @@
     int mem_idx;
     int fpu_enabled;
     struct TranslationBlock *tb;
+    uint32_t features;
 } DisasContext;
 
 extern FILE *logfile;
@@ -140,7 +141,6 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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,17 +2540,14 @@
                         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 @@
                     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 @@
                     gen_op_store_QT0_fpr(QFPREG(rd));
                     gen_set_label(l1);
                     break;
-#else
-                    goto nfpu_insn;
-#endif
                 }
 #endif
                 switch (xop) {
@@ -2681,12 +2625,9 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                     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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                         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 @@
                     // 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 @@
                     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 @@
                     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 @@
                     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 @@
                     // 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 @@
                     // 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 @@
                     // 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 @@
                     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 @@
                     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 @@
                     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,14 +4153,11 @@
                 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 @@
                     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 @@
                     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 @@
                     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 @@
     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 @@
     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);






reply via email to

[Prev in Thread] Current Thread [Next in Thread]