* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "cpu.h"
-#include "gdbstub.h"
+#include "exec/gdbstub.h"
-#include "helpers.h"
+#include "exec/helper-proto.h"
#define SIGNBIT (1u << 31)
-enum m68k_cpuid {
- M68K_CPUID_M5206,
- M68K_CPUID_M5208,
- M68K_CPUID_CFV4E,
- M68K_CPUID_ANY,
-};
+/* Sort alphabetically, except for "any". */
+static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+ ObjectClass *class_a = (ObjectClass *)a;
+ ObjectClass *class_b = (ObjectClass *)b;
+ const char *name_a, *name_b;
-typedef struct m68k_def_t m68k_def_t;
+ name_a = object_class_get_name(class_a);
+ name_b = object_class_get_name(class_b);
+ if (strcmp(name_a, "any-" TYPE_M68K_CPU) == 0) {
+ return 1;
+ } else if (strcmp(name_b, "any-" TYPE_M68K_CPU) == 0) {
+ return -1;
+ } else {
+ return strcasecmp(name_a, name_b);
+ }
+}
-struct m68k_def_t {
- const char * name;
- enum m68k_cpuid id;
-};
+static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
+{
+ ObjectClass *c = data;
+ CPUListState *s = user_data;
+ const char *typename;
+ char *name;
-static m68k_def_t m68k_cpu_defs[] = {
- {"m5206", M68K_CPUID_M5206},
- {"m5208", M68K_CPUID_M5208},
- {"cfv4e", M68K_CPUID_CFV4E},
- {"any", M68K_CPUID_ANY},
- {NULL, 0},
-};
+ typename = object_class_get_name(c);
+ name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_M68K_CPU));
+ (*s->cpu_fprintf)(s->file, "%s\n",
+ name);
+ g_free(name);
+}
void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
{
- unsigned int i;
+ CPUListState s = {
+ .file = f,
+ .cpu_fprintf = cpu_fprintf,
+ };
+ GSList *list;
- for (i = 0; m68k_cpu_defs[i].name; i++) {
- (*cpu_fprintf)(f, "%s\n", m68k_cpu_defs[i].name);
- }
+ list = object_class_get_list(TYPE_M68K_CPU, false);
+ list = g_slist_sort(list, m68k_cpu_list_compare);
+ g_slist_foreach(list, m68k_cpu_list_entry, &s);
+ g_slist_free(list);
}
-static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
+static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
{
if (n < 8) {
stfq_p(mem_buf, env->fregs[n]);
return 0;
}
-static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
+static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
{
if (n < 8) {
env->fregs[n] = ldfq_p(mem_buf);
return 0;
}
-static void m68k_set_feature(CPUM68KState *env, int feature)
+M68kCPU *cpu_m68k_init(const char *cpu_model)
{
- env->features |= (1u << feature);
-}
-
-static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
-{
- m68k_def_t *def;
-
- for (def = m68k_cpu_defs; def->name; def++) {
- if (strcmp(def->name, name) == 0)
- break;
- }
- if (!def->name)
- return -1;
+ M68kCPU *cpu;
+ CPUM68KState *env;
+ ObjectClass *oc;
- 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_BRAL);
- m68k_set_feature(env, M68K_FEATURE_CF_FPU);
- 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_APLUSC);
- m68k_set_feature(env, M68K_FEATURE_BRAL);
- m68k_set_feature(env, M68K_FEATURE_CF_FPU);
- /* 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;
+ oc = cpu_class_by_name(TYPE_M68K_CPU, cpu_model);
+ if (oc == NULL) {
+ return NULL;
}
+ cpu = M68K_CPU(object_new(object_class_get_name(oc)));
+ env = &cpu->env;
register_m68k_insns(env);
- if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
- gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
- 11, "cf-fp.xml", 18);
- }
- /* TODO: Add [E]MAC registers. */
- return 0;
-}
-void cpu_reset(CPUM68KState *env)
-{
- if (qemu_loglevel_mask(CPU_LOG_RESET)) {
- qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
- log_cpu_state(env, 0);
- }
+ object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
- 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);
+ return cpu;
}
-CPUM68KState *cpu_m68k_init(const char *cpu_model)
+void m68k_cpu_init_gdb(M68kCPU *cpu)
{
- CPUM68KState *env;
- static int inited;
-
- env = g_malloc0(sizeof(CPUM68KState));
- cpu_exec_init(env);
- if (!inited) {
- inited = 1;
- m68k_tcg_init();
- }
+ CPUState *cs = CPU(cpu);
+ CPUM68KState *env = &cpu->env;
- env->cpu_model_str = cpu_model;
-
- if (cpu_m68k_set_model(env, cpu_model) < 0) {
- cpu_m68k_close(env);
- return NULL;
+ if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
+ gdb_register_coprocessor(cs, fpu_gdb_get_reg, fpu_gdb_set_reg,
+ 11, "cf-fp.xml", 18);
}
-
- cpu_reset(env);
- qemu_init_vcpu(env);
- return env;
-}
-
-void cpu_m68k_close(CPUM68KState *env)
-{
- g_free(env);
+ /* TODO: Add [E]MAC registers. */
}
void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
{
+ M68kCPU *cpu = m68k_env_get_cpu(env);
int flags;
uint32_t src;
uint32_t dest;
flags |= CCF_C;
break;
default:
- cpu_abort(env, "Bad CC_OP %d", cc_op);
+ cpu_abort(CPU(cpu), "Bad CC_OP %d", cc_op);
}
env->cc_op = CC_OP_FLAGS;
env->cc_dest = flags;
void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
{
+ M68kCPU *cpu = m68k_env_get_cpu(env);
+
switch (reg) {
case 0x02: /* CACR */
env->cacr = val;
break;
/* TODO: Implement control registers. */
default:
- cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
+ cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
reg, val);
}
}
#if defined(CONFIG_USER_ONLY)
-int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
- int mmu_idx)
+int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
+ int mmu_idx)
{
- env->exception_index = EXCP_ACCESS;
- env->mmu.ar = address;
+ M68kCPU *cpu = M68K_CPU(cs);
+
+ cs->exception_index = EXCP_ACCESS;
+ cpu->env.mmu.ar = address;
return 1;
}
/* MMU */
/* TODO: This will need fixing once the MMU is implemented. */
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
return addr;
}
-int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
- int mmu_idx)
+int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
+ int mmu_idx)
{
int prot;
address &= TARGET_PAGE_MASK;
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
+ tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
return 0;
}
be handled by the interrupt controller. Real hardware only requests
the vector when the interrupt is acknowledged by the CPU. For
simplicitly we calculate it when the interrupt is signalled. */
-void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
+void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
{
+ CPUState *cs = CPU(cpu);
+ CPUM68KState *env = &cpu->env;
+
env->pending_level = level;
env->pending_vector = vector;
- if (level)
- cpu_interrupt(env, CPU_INTERRUPT_HARD);
- else
- cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+ if (level) {
+ cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+ }
}
#endif
return val;
}
-uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
+uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
{
uint32_t res;
uint32_t old_flags;
return res;
}
-uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
+uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
{
uint32_t res;
uint32_t old_flags;
return a < b;
}
-void HELPER(set_sr)(CPUState *env, uint32_t val)
+void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
{
env->sr = val & 0xffff;
m68k_switch_sp(env);
}
-uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
+uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
{
uint32_t result;
uint32_t cf;
return result;
}
-uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
+uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
{
uint32_t result;
uint32_t cf;
return result;
}
-uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
+uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
{
uint32_t result;
uint32_t cf;
}
/* FPU helpers. */
-uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
+uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
{
return float64_to_int32(val, &env->fp_status);
}
-float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
+float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
{
return float64_to_float32(val, &env->fp_status);
}
-float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
+float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
{
return int32_to_float64(val, &env->fp_status);
}
-float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
+float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
{
return float32_to_float64(val, &env->fp_status);
}
-float64 HELPER(iround_f64)(CPUState *env, float64 val)
+float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
{
return float64_round_to_int(val, &env->fp_status);
}
-float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
+float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
{
return float64_trunc_to_int(val, &env->fp_status);
}
-float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
+float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val)
{
return float64_sqrt(val, &env->fp_status);
}
return float64_chs(val);
}
-float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
+float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b)
{
return float64_add(a, b, &env->fp_status);
}
-float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
+float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
{
return float64_sub(a, b, &env->fp_status);
}
-float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
+float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
{
return float64_mul(a, b, &env->fp_status);
}
-float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
+float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
{
return float64_div(a, b, &env->fp_status);
}
-float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
+float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b)
{
/* ??? This may incorrectly raise exceptions. */
/* ??? Should flush denormals to zero. */
return res;
}
-uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
+uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val)
{
return float64_compare_quiet(val, float64_zero, &env->fp_status);
}
/* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
take values, others take register numbers and manipulate the contents
in-place. */
-void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
+void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
{
uint32_t mask;
env->macc[dest] = env->macc[src];
env->macsr &= ~mask;
}
-uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
+uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
{
int64_t product;
int64_t res;
return res;
}
-uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
+uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
{
uint64_t product;
return product;
}
-uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
+uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
{
uint64_t product;
uint32_t remainder;
return product;
}
-void HELPER(macsats)(CPUState *env, uint32_t acc)
+void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
{
int64_t tmp;
int64_t result;
env->macc[acc] = result;
}
-void HELPER(macsatu)(CPUState *env, uint32_t acc)
+void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
{
uint64_t val;
env->macc[acc] = val;
}
-void HELPER(macsatf)(CPUState *env, uint32_t acc)
+void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
{
int64_t sum;
int64_t result;
env->macc[acc] = result;
}
-void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
+void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
{
uint64_t val;
val = env->macc[acc];
}
}
-void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
+void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
{
cpu_m68k_flush_flags(env, cc_op);
}
-uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
+uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
{
int rem;
uint32_t result;
}
}
-uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
+uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
{
uint32_t val;
val = env->macc[acc] & 0x00ff;
return val;
}
-uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
+uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
{
uint32_t val;
val = (env->macc[acc] >> 32) & 0xffff;
return val;
}
-void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
+void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
{
int64_t res;
int32_t tmp;
env->macc[acc + 1] = res;
}
-void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
+void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
{
int64_t res;
int32_t tmp;
env->macc[acc + 1] = res;
}
-void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
+void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
{
uint64_t res;
res = (uint32_t)env->macc[acc];
res |= (uint64_t)(val & 0xffff0000) << 16;
env->macc[acc + 1] = res;
}
+
+void m68k_cpu_exec_enter(CPUState *cs)
+{
+ M68kCPU *cpu = M68K_CPU(cs);
+ CPUM68KState *env = &cpu->env;
+
+ env->cc_op = CC_OP_FLAGS;
+ env->cc_dest = env->sr & 0xf;
+ env->cc_x = (env->sr >> 4) & 1;
+}
+
+void m68k_cpu_exec_exit(CPUState *cs)
+{
+ M68kCPU *cpu = M68K_CPU(cs);
+ CPUM68KState *env = &cpu->env;
+
+ cpu_m68k_flush_flags(env, env->cc_op);
+ env->cc_op = CC_OP_FLAGS;
+ env->sr = (env->sr & 0xffe0) | env->cc_dest | (env->cc_x << 4);
+}