diff options
Diffstat (limited to 'target-alpha')
-rw-r--r-- | target-alpha/cpu-qom.h | 5 | ||||
-rw-r--r-- | target-alpha/cpu.c | 224 | ||||
-rw-r--r-- | target-alpha/cpu.h | 33 | ||||
-rw-r--r-- | target-alpha/fpu_helper.c | 2 | ||||
-rw-r--r-- | target-alpha/helper.c | 16 | ||||
-rw-r--r-- | target-alpha/helper.h | 4 | ||||
-rw-r--r-- | target-alpha/int_helper.c | 2 | ||||
-rw-r--r-- | target-alpha/mem_helper.c | 18 | ||||
-rw-r--r-- | target-alpha/sys_helper.c | 10 | ||||
-rw-r--r-- | target-alpha/translate.c | 80 |
10 files changed, 283 insertions, 111 deletions
diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h index 6b4ca6d..16367d2 100644 --- a/target-alpha/cpu-qom.h +++ b/target-alpha/cpu-qom.h @@ -20,7 +20,7 @@ #ifndef QEMU_ALPHA_CPU_QOM_H #define QEMU_ALPHA_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #include "cpu.h" #define TYPE_ALPHA_CPU "alpha-cpu" @@ -58,6 +58,9 @@ typedef struct AlphaCPU { /*< public >*/ CPUAlphaState env; + + /* This alarm doesn't exist in real hardware; we wish it did. */ + struct QEMUTimer *alarm_timer; } AlphaCPU; static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env) diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c index 11a19eb..0ad69f0 100644 --- a/target-alpha/cpu.c +++ b/target-alpha/cpu.c @@ -21,8 +21,213 @@ #include "cpu.h" #include "qemu-common.h" +#include "qapi/error.h" +static void alpha_cpu_realize(Object *obj, Error **errp) +{ + AlphaCPU *cpu = ALPHA_CPU(obj); + + qemu_init_vcpu(&cpu->env); +} + +/* Sort alphabetically by type name. */ +static gint alpha_cpu_list_compare(gconstpointer a, gconstpointer b) +{ + ObjectClass *class_a = (ObjectClass *)a; + ObjectClass *class_b = (ObjectClass *)b; + const char *name_a, *name_b; + + name_a = object_class_get_name(class_a); + name_b = object_class_get_name(class_b); + return strcmp(name_a, name_b); +} + +static void alpha_cpu_list_entry(gpointer data, gpointer user_data) +{ + ObjectClass *oc = data; + CPUListState *s = user_data; + + (*s->cpu_fprintf)(s->file, " %s\n", + object_class_get_name(oc)); +} + +void alpha_cpu_list(FILE *f, fprintf_function cpu_fprintf) +{ + CPUListState s = { + .file = f, + .cpu_fprintf = cpu_fprintf, + }; + GSList *list; + + list = object_class_get_list(TYPE_ALPHA_CPU, false); + list = g_slist_sort(list, alpha_cpu_list_compare); + (*cpu_fprintf)(f, "Available CPUs:\n"); + g_slist_foreach(list, alpha_cpu_list_entry, &s); + g_slist_free(list); +} + +/* Models */ + +#define TYPE(model) model "-" TYPE_ALPHA_CPU + +typedef struct AlphaCPUAlias { + const char *alias; + const char *typename; +} AlphaCPUAlias; + +static const AlphaCPUAlias alpha_cpu_aliases[] = { + { "21064", TYPE("ev4") }, + { "21164", TYPE("ev5") }, + { "21164a", TYPE("ev56") }, + { "21164pc", TYPE("pca56") }, + { "21264", TYPE("ev6") }, + { "21264a", TYPE("ev67") }, +}; + +static ObjectClass *alpha_cpu_class_by_name(const char *cpu_model) +{ + ObjectClass *oc = NULL; + char *typename; + int i; + + if (cpu_model == NULL) { + return NULL; + } + + oc = object_class_by_name(cpu_model); + if (oc != NULL && object_class_dynamic_cast(oc, TYPE_ALPHA_CPU) != NULL && + !object_class_is_abstract(oc)) { + return oc; + } + + for (i = 0; i < ARRAY_SIZE(alpha_cpu_aliases); i++) { + if (strcmp(cpu_model, alpha_cpu_aliases[i].alias) == 0) { + oc = object_class_by_name(alpha_cpu_aliases[i].typename); + assert(oc != NULL && !object_class_is_abstract(oc)); + return oc; + } + } + + typename = g_strdup_printf("%s-" TYPE_ALPHA_CPU, cpu_model); + oc = object_class_by_name(typename); + g_free(typename); + if (oc != NULL && object_class_is_abstract(oc)) { + oc = NULL; + } + return oc; +} + +AlphaCPU *cpu_alpha_init(const char *cpu_model) +{ + AlphaCPU *cpu; + CPUAlphaState *env; + ObjectClass *cpu_class; + + cpu_class = alpha_cpu_class_by_name(cpu_model); + if (cpu_class == NULL) { + /* Default to ev67; no reason not to emulate insns by default. */ + cpu_class = object_class_by_name(TYPE("ev67")); + } + cpu = ALPHA_CPU(object_new(object_class_get_name(cpu_class))); + env = &cpu->env; + + env->cpu_model_str = cpu_model; + + alpha_cpu_realize(OBJECT(cpu), NULL); + return cpu; +} + +static void ev4_cpu_initfn(Object *obj) +{ + AlphaCPU *cpu = ALPHA_CPU(obj); + CPUAlphaState *env = &cpu->env; + + env->implver = IMPLVER_2106x; +} + +static const TypeInfo ev4_cpu_type_info = { + .name = TYPE("ev4"), + .parent = TYPE_ALPHA_CPU, + .instance_init = ev4_cpu_initfn, +}; + +static void ev5_cpu_initfn(Object *obj) +{ + AlphaCPU *cpu = ALPHA_CPU(obj); + CPUAlphaState *env = &cpu->env; + + env->implver = IMPLVER_21164; +} + +static const TypeInfo ev5_cpu_type_info = { + .name = TYPE("ev5"), + .parent = TYPE_ALPHA_CPU, + .instance_init = ev5_cpu_initfn, +}; + +static void ev56_cpu_initfn(Object *obj) +{ + AlphaCPU *cpu = ALPHA_CPU(obj); + CPUAlphaState *env = &cpu->env; + + env->amask |= AMASK_BWX; +} + +static const TypeInfo ev56_cpu_type_info = { + .name = TYPE("ev56"), + .parent = TYPE("ev5"), + .instance_init = ev56_cpu_initfn, +}; + +static void pca56_cpu_initfn(Object *obj) +{ + AlphaCPU *cpu = ALPHA_CPU(obj); + CPUAlphaState *env = &cpu->env; + + env->amask |= AMASK_MVI; +} + +static const TypeInfo pca56_cpu_type_info = { + .name = TYPE("pca56"), + .parent = TYPE("ev56"), + .instance_init = pca56_cpu_initfn, +}; + +static void ev6_cpu_initfn(Object *obj) +{ + AlphaCPU *cpu = ALPHA_CPU(obj); + CPUAlphaState *env = &cpu->env; + + env->implver = IMPLVER_21264; + env->amask = AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP; +} + +static const TypeInfo ev6_cpu_type_info = { + .name = TYPE("ev6"), + .parent = TYPE_ALPHA_CPU, + .instance_init = ev6_cpu_initfn, +}; + +static void ev67_cpu_initfn(Object *obj) +{ + AlphaCPU *cpu = ALPHA_CPU(obj); + CPUAlphaState *env = &cpu->env; + + env->amask |= AMASK_CIX | AMASK_PREFETCH; +} + +static const TypeInfo ev67_cpu_type_info = { + .name = TYPE("ev67"), + .parent = TYPE("ev6"), + .instance_init = ev67_cpu_initfn, +}; + +static const TypeInfo ev68_cpu_type_info = { + .name = TYPE("ev68"), + .parent = TYPE("ev67"), +}; + static void alpha_cpu_initfn(Object *obj) { AlphaCPU *cpu = ALPHA_CPU(obj); @@ -31,6 +236,8 @@ static void alpha_cpu_initfn(Object *obj) cpu_exec_init(env); tlb_flush(env, 1); + alpha_translate_init(); + #if defined(CONFIG_USER_ONLY) env->ps = PS_USER_MODE; cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD @@ -41,18 +248,33 @@ static void alpha_cpu_initfn(Object *obj) env->fen = 1; } +static void alpha_cpu_class_init(ObjectClass *oc, void *data) +{ + CPUClass *cc = CPU_CLASS(oc); + + cc->class_by_name = alpha_cpu_class_by_name; +} + static const TypeInfo alpha_cpu_type_info = { .name = TYPE_ALPHA_CPU, .parent = TYPE_CPU, .instance_size = sizeof(AlphaCPU), .instance_init = alpha_cpu_initfn, - .abstract = false, + .abstract = true, .class_size = sizeof(AlphaCPUClass), + .class_init = alpha_cpu_class_init, }; static void alpha_cpu_register_types(void) { type_register_static(&alpha_cpu_type_info); + type_register_static(&ev4_cpu_type_info); + type_register_static(&ev5_cpu_type_info); + type_register_static(&ev56_cpu_type_info); + type_register_static(&pca56_cpu_type_info); + type_register_static(&ev6_cpu_type_info); + type_register_static(&ev67_cpu_type_info); + type_register_static(&ev68_cpu_type_info); } type_init(alpha_cpu_register_types) diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 34221fb..f1db651 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -27,9 +27,9 @@ #define CPUArchState struct CPUAlphaState -#include "cpu-defs.h" +#include "exec/cpu-defs.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #define TARGET_HAS_ICE 1 @@ -277,16 +277,8 @@ struct CPUAlphaState { #endif /* This alarm doesn't exist in real hardware; we wish it did. */ - struct QEMUTimer *alarm_timer; uint64_t alarm_expire; -#if TARGET_LONG_BITS > HOST_LONG_BITS - /* temporary fixed-point registers - * used to emulate 64 bits target on 32 bits hosts - */ - target_ulong t0, t1; -#endif - /* Those resources are used only in QEMU core */ CPU_COMMON @@ -297,12 +289,12 @@ struct CPUAlphaState { int implver; }; -#define cpu_init cpu_alpha_init +#define cpu_list alpha_cpu_list #define cpu_exec cpu_alpha_exec #define cpu_gen_code cpu_alpha_gen_code #define cpu_signal_handler cpu_alpha_signal_handler -#include "cpu-all.h" +#include "exec/cpu-all.h" #include "cpu-qom.h" enum { @@ -434,7 +426,20 @@ enum { IR_ZERO = 31, }; -CPUAlphaState * cpu_alpha_init (const char *cpu_model); +void alpha_translate_init(void); + +AlphaCPU *cpu_alpha_init(const char *cpu_model); + +static inline CPUAlphaState *cpu_init(const char *cpu_model) +{ + AlphaCPU *cpu = cpu_alpha_init(cpu_model); + if (cpu == NULL) { + return NULL; + } + return &cpu->env; +} + +void alpha_cpu_list(FILE *f, fprintf_function cpu_fprintf); int cpu_alpha_exec(CPUAlphaState *s); /* you can call this signal handler from your SIGBUS and SIGSEGV signal handlers to inform the virtual CPU of exceptions. non zero @@ -527,7 +532,7 @@ static inline bool cpu_has_work(CPUState *cpu) | CPU_INTERRUPT_MCHK); } -#include "exec-all.h" +#include "exec/exec-all.h" static inline void cpu_pc_from_tb(CPUAlphaState *env, TranslationBlock *tb) { diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c index fe988ec..fad3575 100644 --- a/target-alpha/fpu_helper.c +++ b/target-alpha/fpu_helper.c @@ -19,7 +19,7 @@ #include "cpu.h" #include "helper.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #define FP_STATUS (env->fp_status) diff --git a/target-alpha/helper.c b/target-alpha/helper.c index d9d7f75..22c9c6e 100644 --- a/target-alpha/helper.c +++ b/target-alpha/helper.c @@ -22,7 +22,7 @@ #include <stdio.h> #include "cpu.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #include "helper.h" uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env) @@ -494,16 +494,6 @@ void cpu_dump_state (CPUAlphaState *env, FILE *f, fprintf_function cpu_fprintf, cpu_fprintf(f, "\n"); } -void do_restore_state(CPUAlphaState *env, uintptr_t retaddr) -{ - if (retaddr) { - TranslationBlock *tb = tb_find_pc(retaddr); - if (tb) { - cpu_restore_state(tb, env, retaddr); - } - } -} - /* This should only be called from translate, via gen_excp. We expect that ENV->PC has already been updated. */ void QEMU_NORETURN helper_excp(CPUAlphaState *env, int excp, int error) @@ -519,7 +509,9 @@ void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, uintptr_t retaddr, { env->exception_index = excp; env->error_code = error; - do_restore_state(env, retaddr); + if (retaddr) { + cpu_restore_state(env, retaddr); + } cpu_loop_exit(env); } diff --git a/target-alpha/helper.h b/target-alpha/helper.h index dd55f89..eac3041 100644 --- a/target-alpha/helper.h +++ b/target-alpha/helper.h @@ -1,4 +1,4 @@ -#include "def-helper.h" +#include "exec/def-helper.h" DEF_HELPER_3(excp, noreturn, env, int, int) DEF_HELPER_FLAGS_1(load_pcc, TCG_CALL_NO_RWG_SE, i64, env) @@ -119,4 +119,4 @@ DEF_HELPER_FLAGS_0(get_time, TCG_CALL_NO_RWG, i64) DEF_HELPER_FLAGS_2(set_alarm, TCG_CALL_NO_RWG, void, env, i64) #endif -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-alpha/int_helper.c b/target-alpha/int_helper.c index 1d832f0..c9b42b6 100644 --- a/target-alpha/int_helper.c +++ b/target-alpha/int_helper.c @@ -19,7 +19,7 @@ #include "cpu.h" #include "helper.h" -#include "host-utils.h" +#include "qemu/host-utils.h" uint64_t helper_umulh(uint64_t op1, uint64_t op2) diff --git a/target-alpha/mem_helper.c b/target-alpha/mem_helper.c index 617836c..3d2cd61 100644 --- a/target-alpha/mem_helper.c +++ b/target-alpha/mem_helper.c @@ -94,7 +94,9 @@ static void do_unaligned_access(CPUAlphaState *env, target_ulong addr, uint64_t pc; uint32_t insn; - do_restore_state(env, retaddr); + if (retaddr) { + cpu_restore_state(env, retaddr); + } pc = env->pc; insn = cpu_ldl_code(env, pc); @@ -115,22 +117,22 @@ void cpu_unassigned_access(CPUAlphaState *env, hwaddr addr, dynamic_excp(env, 0, EXCP_MCHK, 0); } -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #define MMUSUFFIX _mmu #define ALIGNED_ONLY #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" /* try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not @@ -143,7 +145,9 @@ void tlb_fill(CPUAlphaState *env, target_ulong addr, int is_write, ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret != 0)) { - do_restore_state(env, retaddr); + if (retaddr) { + cpu_restore_state(env, retaddr); + } /* Exception index and error code are already set */ cpu_loop_exit(env); } diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c index 40ca49c..339501a 100644 --- a/target-alpha/sys_helper.c +++ b/target-alpha/sys_helper.c @@ -19,8 +19,8 @@ #include "cpu.h" #include "helper.h" -#include "sysemu.h" -#include "qemu-timer.h" +#include "sysemu/sysemu.h" +#include "qemu/timer.h" uint64_t helper_load_pcc(CPUAlphaState *env) @@ -77,11 +77,13 @@ uint64_t helper_get_time(void) void helper_set_alarm(CPUAlphaState *env, uint64_t expire) { + AlphaCPU *cpu = alpha_env_get_cpu(env); + if (expire) { env->alarm_expire = expire; - qemu_mod_timer(env->alarm_timer, expire); + qemu_mod_timer(cpu->alarm_timer, expire); } else { - qemu_del_timer(env->alarm_timer); + qemu_del_timer(cpu->alarm_timer); } } #endif /* CONFIG_USER_ONLY */ diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 4045f78..f687b95 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -18,8 +18,8 @@ */ #include "cpu.h" -#include "disas.h" -#include "host-utils.h" +#include "disas/disas.h" +#include "qemu/host-utils.h" #include "tcg-op.h" #include "helper.h" @@ -88,9 +88,9 @@ static TCGv cpu_usp; /* register names */ static char cpu_reg_names[10*4+21*5 + 10*5+21*6]; -#include "gen-icount.h" +#include "exec/gen-icount.h" -static void alpha_translate_init(void) +void alpha_translate_init(void) { int i; char *p; @@ -611,7 +611,7 @@ static void gen_qual_roundmode(DisasContext *ctx, int fn11) } #if defined(CONFIG_SOFTFLOAT_INLINE) - /* ??? The "softfloat.h" interface is to call set_float_rounding_mode. + /* ??? The "fpu/softfloat.h" interface is to call set_float_rounding_mode. With CONFIG_SOFTFLOAT that expands to an out-of-line call that just sets the one field. */ tcg_gen_st8_i32(tmp, cpu_env, @@ -1579,7 +1579,7 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode) case 0x3C: /* WHAMI */ tcg_gen_ld32s_i64(cpu_ir[IR_V0], cpu_env, - offsetof(CPUAlphaState, cpu_index)); + -offsetof(AlphaCPU, env) + offsetof(CPUState, cpu_index)); break; default: @@ -3410,11 +3410,11 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env, if (lj < j) { lj++; while (lj < j) - gen_opc_instr_start[lj++] = 0; + tcg_ctx.gen_opc_instr_start[lj++] = 0; } - gen_opc_pc[lj] = ctx.pc; - gen_opc_instr_start[lj] = 1; - gen_opc_icount[lj] = num_insns; + tcg_ctx.gen_opc_pc[lj] = ctx.pc; + tcg_ctx.gen_opc_instr_start[lj] = 1; + tcg_ctx.gen_opc_icount[lj] = num_insns; } if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) gen_io_start(); @@ -3468,7 +3468,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env, j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; lj++; while (lj <= j) - gen_opc_instr_start[lj++] = 0; + tcg_ctx.gen_opc_instr_start[lj++] = 0; } else { tb->size = ctx.pc - pc_start; tb->icount = num_insns; @@ -3493,63 +3493,7 @@ void gen_intermediate_code_pc (CPUAlphaState *env, struct TranslationBlock *tb) gen_intermediate_code_internal(env, tb, 1); } -struct cpu_def_t { - const char *name; - int implver, amask; -}; - -static const struct cpu_def_t cpu_defs[] = { - { "ev4", IMPLVER_2106x, 0 }, - { "ev5", IMPLVER_21164, 0 }, - { "ev56", IMPLVER_21164, AMASK_BWX }, - { "pca56", IMPLVER_21164, AMASK_BWX | AMASK_MVI }, - { "ev6", IMPLVER_21264, AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP }, - { "ev67", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX - | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), }, - { "ev68", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX - | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), }, - { "21064", IMPLVER_2106x, 0 }, - { "21164", IMPLVER_21164, 0 }, - { "21164a", IMPLVER_21164, AMASK_BWX }, - { "21164pc", IMPLVER_21164, AMASK_BWX | AMASK_MVI }, - { "21264", IMPLVER_21264, AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP }, - { "21264a", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX - | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), } -}; - -CPUAlphaState * cpu_alpha_init (const char *cpu_model) -{ - AlphaCPU *cpu; - CPUAlphaState *env; - int implver, amask, i, max; - - cpu = ALPHA_CPU(object_new(TYPE_ALPHA_CPU)); - env = &cpu->env; - - alpha_translate_init(); - - /* Default to ev67; no reason not to emulate insns by default. */ - implver = IMPLVER_21264; - amask = (AMASK_BWX | AMASK_FIX | AMASK_CIX | AMASK_MVI - | AMASK_TRAP | AMASK_PREFETCH); - - max = ARRAY_SIZE(cpu_defs); - for (i = 0; i < max; i++) { - if (strcmp (cpu_model, cpu_defs[i].name) == 0) { - implver = cpu_defs[i].implver; - amask = cpu_defs[i].amask; - break; - } - } - env->implver = implver; - env->amask = amask; - env->cpu_model_str = cpu_model; - - qemu_init_vcpu(env); - return env; -} - void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos) { - env->pc = gen_opc_pc[pc_pos]; + env->pc = tcg_ctx.gen_opc_pc[pc_pos]; } |