qemu_put signedness fixes, by Andre Przywara.
[qemu] / target-m68k / helper.c
index 12e3f78..c639648 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  m68k op helpers
- * 
+ *
  *  Copyright (c) 2006-2007 CodeSourcery
  *  Written by Paul Brook
  *
 
 enum m68k_cpuid {
     M68K_CPUID_M5206,
+    M68K_CPUID_M5208,
     M68K_CPUID_CFV4E,
     M68K_CPUID_ANY,
 };
 
+typedef struct m68k_def_t m68k_def_t;
+
 struct m68k_def_t {
     const char * name;
     enum m68k_cpuid id;
 };
 
 static m68k_def_t m68k_cpu_defs[] = {
-    {"m5206", M68K_CPUID_M5206}, 
+    {"m5206", M68K_CPUID_M5206},
+    {"m5208", M68K_CPUID_M5208},
     {"cfv4e", M68K_CPUID_CFV4E},
     {"any", M68K_CPUID_ANY},
-    {NULL, 0}, 
+    {NULL, 0},
 };
 
 static void m68k_set_feature(CPUM68KState *env, int feature)
@@ -49,7 +53,7 @@ static void m68k_set_feature(CPUM68KState *env, int feature)
     env->features |= (1u << feature);
 }
 
-int cpu_m68k_set_model(CPUM68KState *env, const char * name)
+static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
 {
     m68k_def_t *def;
 
@@ -58,36 +62,86 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name)
             break;
     }
     if (!def->name)
-        return 1;
+        return -1;
 
     switch (def->id) {
     case M68K_CPUID_M5206:
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
         break;
+    case M68K_CPUID_M5208:
+        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
+        m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
+        m68k_set_feature(env, M68K_FEATURE_BRAL);
+        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
+        m68k_set_feature(env, M68K_FEATURE_USP);
+        break;
     case M68K_CPUID_CFV4E:
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
-        m68k_set_feature(env, M68K_FEATURE_CF_ISA_C);
+        m68k_set_feature(env, M68K_FEATURE_BRAL);
         m68k_set_feature(env, M68K_FEATURE_CF_FPU);
-        m68k_set_feature(env, M68K_FEATURE_CF_MAC);
         m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
+        m68k_set_feature(env, M68K_FEATURE_USP);
         break;
     case M68K_CPUID_ANY:
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
-        m68k_set_feature(env, M68K_FEATURE_CF_ISA_C);
+        m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
+        m68k_set_feature(env, M68K_FEATURE_BRAL);
         m68k_set_feature(env, M68K_FEATURE_CF_FPU);
-        m68k_set_feature(env, M68K_FEATURE_CF_MAC);
+        /* MAC and EMAC are mututally exclusive, so pick EMAC.
+           It's mostly backwards compatible.  */
         m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
+        m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
+        m68k_set_feature(env, M68K_FEATURE_USP);
         m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
+        m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
         break;
     }
 
     register_m68k_insns(env);
-
     return 0;
 }
 
+void cpu_reset(CPUM68KState *env)
+{
+    memset(env, 0, offsetof(CPUM68KState, breakpoints));
+#if !defined (CONFIG_USER_ONLY)
+    env->sr = 0x2700;
+#endif
+    m68k_switch_sp(env);
+    /* ??? FP regs should be initialized to NaN.  */
+    env->cc_op = CC_OP_FLAGS;
+    /* TODO: We should set PC from the interrupt vector.  */
+    env->pc = 0;
+    tlb_flush(env, 1);
+}
+
+CPUM68KState *cpu_m68k_init(const char *cpu_model)
+{
+    CPUM68KState *env;
+
+    env = malloc(sizeof(CPUM68KState));
+    if (!env)
+        return NULL;
+    cpu_exec_init(env);
+
+    env->cpu_model_str = cpu_model;
+
+    if (cpu_m68k_set_model(env, cpu_model) < 0) {
+        cpu_m68k_close(env);
+        return NULL;
+    }
+
+    cpu_reset(env);
+    return env;
+}
+
+void cpu_m68k_close(CPUM68KState *env)
+{
+    qemu_free(env);
+}
+
 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
 {
     int flags;
@@ -203,7 +257,7 @@ float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1)
         /* +/-inf compares equal against itself, but sub returns nan.  */
         if (!float64_is_nan(src0)
             && !float64_is_nan(src1)) {
-            res = 0;
+            res = float64_zero;
             if (float64_lt_quiet(src0, res, &env->fp_status))
                 res = float64_chs(res);
         }
@@ -215,7 +269,11 @@ void helper_movec(CPUM68KState *env, int reg, uint32_t val)
 {
     switch (reg) {
     case 0x02: /* CACR */
-        /* Ignored.  */
+        env->cacr = val;
+        m68k_switch_sp(env);
+        break;
+    case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
+        /* TODO: Implement Access Control Registers.  */
         break;
     case 0x801: /* VBR */
         env->vbr = val;
@@ -227,6 +285,51 @@ void helper_movec(CPUM68KState *env, int reg, uint32_t val)
     }
 }
 
+void m68k_set_macsr(CPUM68KState *env, uint32_t val)
+{
+    uint32_t acc;
+    int8_t exthigh;
+    uint8_t extlow;
+    uint64_t regval;
+    int i;
+    if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
+        for (i = 0; i < 4; i++) {
+            regval = env->macc[i];
+            exthigh = regval >> 40;
+            if (env->macsr & MACSR_FI) {
+                acc = regval >> 8;
+                extlow = regval;
+            } else {
+                acc = regval;
+                extlow = regval >> 32;
+            }
+            if (env->macsr & MACSR_FI) {
+                regval = (((uint64_t)acc) << 8) | extlow;
+                regval |= ((int64_t)exthigh) << 40;
+            } else if (env->macsr & MACSR_SU) {
+                regval = acc | (((int64_t)extlow) << 32);
+                regval |= ((int64_t)exthigh) << 40;
+            } else {
+                regval = acc | (((uint64_t)extlow) << 32);
+                regval |= ((uint64_t)(uint8_t)exthigh) << 40;
+            }
+            env->macc[i] = regval;
+        }
+    }
+    env->macsr = val;
+}
+
+void m68k_switch_sp(CPUM68KState *env)
+{
+    int new_sp;
+
+    env->sp[env->current_sp] = env->aregs[7];
+    new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
+             ? M68K_SSP : M68K_USP;
+    env->aregs[7] = env->sp[new_sp];
+    env->current_sp = new_sp;
+}
+
 /* MMU */
 
 /* TODO: This will need fixing once the MMU is implemented.  */
@@ -235,10 +338,10 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
     return addr;
 }
 
-#if defined(CONFIG_USER_ONLY) 
+#if defined(CONFIG_USER_ONLY)
 
 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                               int is_user, int is_softmmu)
+                               int mmu_idx, int is_softmmu)
 {
     env->exception_index = EXCP_ACCESS;
     env->mmu.ar = address;
@@ -248,13 +351,13 @@ int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 #else
 
 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                               int is_user, int is_softmmu)
+                               int mmu_idx, int is_softmmu)
 {
     int prot;
 
     address &= TARGET_PAGE_MASK;
     prot = PAGE_READ | PAGE_WRITE;
-    return tlb_set_page(env, address, address, prot, is_user, is_softmmu);
+    return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
 }
 
 /* Notify CPU of a pending interrupt.  Prioritization and vectoring should