[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 2/5] Blackfin: initial port
From: |
Andreas Färber |
Subject: |
Re: [Qemu-devel] [PATCH 2/5] Blackfin: initial port |
Date: |
Fri, 28 Jun 2013 16:24:13 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130510 Thunderbird/17.0.6 |
Hi,
Am 17.06.2013 09:16, schrieb Mike Frysinger:
> diff --git a/target-bfin/cpu-qom.h b/target-bfin/cpu-qom.h
> new file mode 100644
> index 0000000..697797b
> --- /dev/null
> +++ b/target-bfin/cpu-qom.h
For a new target, a separate cpu-qom.h should be unnecessary - it has
become impossible to include it without cpu.h. Just inline it into cpu.h
and group CPUState vs. CPUBfinState stuff together there.
> @@ -0,0 +1,61 @@
> +/*
> + * QEMU Blackfin CPU
> + *
> + * Copyright 2007-2013 Mike Frysinger
> + * Copyright 2007-2011 Analog Devices, Inc.
> + *
> + * Licensed under the Lesser GPL 2 or later.
> + */
> +
> +#ifndef QEMU_BFIN_CPU_QOM_H
> +#define QEMU_BFIN_CPU_QOM_H
> +
> +#include "qom/cpu.h"
> +
> +#define TYPE_BFIN_CPU "bfin-cpu"
> +
> +#define BFIN_CPU_CLASS(klass) \
> + OBJECT_CLASS_CHECK(BfinCPUClass, (klass), TYPE_BFIN_CPU)
> +#define BFIN_CPU(obj) \
> + OBJECT_CHECK(BfinCPU, (obj), TYPE_BFIN_CPU)
> +#define BFIN_CPU_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(BfinCPUClass, (obj), TYPE_BFIN_CPU)
> +
> +/**
> + * BfinCPUClass:
> + * @parent_reset: The parent class' reset handler.
> + *
> + * An Bfin CPU model.
> + */
> +typedef struct BfinCPUClass {
> + /*< private >*/
> + CPUClass parent_class;
> + /*< public >*/
> +
> + void (*parent_reset)(CPUState *cpu);
> +} BfinCPUClass;
> +
> +/**
> + * BfinCPU:
QOM types should have verbose, readable names. Please use BlackfinCPU,
BlackfinCPUClass, TYPE_BLACKFIN_CPU.
By contrast, CPUBfinState, bfin_cpu_... and bfin-cpu are totally fine, I
guess.
> + * @env: #CPUArchState
Please don't use CPUArchState anywhere in bfin code except for the
#define CPUArchState CPUBfinState.
> + *
> + * An Bfin CPU.
> + */
> +typedef struct BfinCPU {
> + /*< private >*/
> + CPUState parent_obj;
> + /*< public >*/
> +
> + CPUArchState env;
> +} BfinCPU;
> +
> +static inline BfinCPU *bfin_env_get_cpu(CPUArchState *env)
CPUbfinState *env
> +{
> + return BFIN_CPU(container_of(env, BfinCPU, env));
I've just posted a patch to drop these FOO_CPU() casts from all targets.
While there's no ACK yet, there was agreement on v1, so please just
return the container_of() here.
> +}
> +
> +#define ENV_GET_CPU(e) CPU(bfin_env_get_cpu(e))
> +
> +#define ENV_OFFSET offsetof(BfinCPU, env)
> +
> +#endif
> diff --git a/target-bfin/cpu.c b/target-bfin/cpu.c
> new file mode 100644
> index 0000000..871a1a1
> --- /dev/null
> +++ b/target-bfin/cpu.c
> @@ -0,0 +1,55 @@
> +/*
> + * QEMU Blackfin CPU
> + *
> + * Copyright 2007-2013 Mike Frysinger
> + * Copyright 2007-2011 Analog Devices, Inc.
> + *
> + * Licensed under the Lesser GPL 2 or later.
> + */
> +
> +#include "cpu.h"
> +#include "qemu-common.h"
> +
> +
> +/* CPUClass::reset() */
> +static void bfin_cpu_reset(CPUState *s)
> +{
> + BfinCPU *cpu = BFIN_CPU(s);
> + CPUArchState *env = &cpu->env;
CPUBfinState *
Missing memset(env, 0, offsetof(CPUBfinState, breakpoints)).
> +
> + env->pc = 0xEF000000;
> +}
> +
> +static void bfin_cpu_initfn(Object *obj)
> +{
> + CPUState *cs = CPU(obj);
> + BfinCPU *cpu = BFIN_CPU(obj);
> + CPUArchState *env = &cpu->env;
> +
> + cs->env_ptr = env;
> + cpu_exec_init(env);
> +}
> +
> +static void bfin_cpu_class_init(ObjectClass *oc, void *data)
> +{
> + CPUClass *cc = CPU_CLASS(oc);
> +
> + cc->reset = bfin_cpu_reset;
> +}
> +
> +static const TypeInfo bfin_cpu_type_info = {
> + .name = TYPE_BFIN_CPU,
> + .parent = TYPE_CPU,
> + .instance_size = sizeof(BfinCPU),
> + .instance_init = bfin_cpu_initfn,
> + .abstract = false,
> + .class_size = sizeof(BfinCPUClass),
> + .class_init = bfin_cpu_class_init,
> +};
> +
> +static void bfin_cpu_register_types(void)
> +{
> + type_register_static(&bfin_cpu_type_info);
> +}
> +
> +type_init(bfin_cpu_register_types)
> diff --git a/target-bfin/cpu.h b/target-bfin/cpu.h
> new file mode 100644
> index 0000000..d288197
> --- /dev/null
> +++ b/target-bfin/cpu.h
> @@ -0,0 +1,236 @@
> +/*
> + * Blackfin emulation
> + *
> + * Copyright 2007-2013 Mike Frysinger
> + * Copyright 2007-2011 Analog Devices, Inc.
> + *
> + * Licensed under the Lesser GPL 2 or later.
> + */
> +
> +#ifndef CPU_BFIN_H
> +#define CPU_BFIN_H
> +
> +struct DisasContext;
> +
> +#define TARGET_LONG_BITS 32
> +
> +#define ELF_MACHINE EM_BLACKFIN
> +
> +#define CPUArchState struct CPUBfinState
> +
> +#include "config.h"
> +#include "qemu-common.h"
> +#include "exec/cpu-defs.h"
> +
> +#define TARGET_HAS_ICE 1
> +
> +#define EXCP_SYSCALL 0
> +#define EXCP_SOFT_BP 1
> +#define EXCP_STACK_OVERFLOW 3
> +#define EXCP_SINGLE_STEP 0x10
> +#define EXCP_TRACE_FULL 0x11
> +#define EXCP_UNDEF_INST 0x21
> +#define EXCP_ILL_INST 0x22
> +#define EXCP_DCPLB_VIOLATE 0x23
> +#define EXCP_DATA_MISALGIN 0x24
> +#define EXCP_UNRECOVERABLE 0x25
> +#define EXCP_DCPLB_MISS 0x26
> +#define EXCP_DCPLB_MULT 0x27
> +#define EXCP_EMU_WATCH 0x28
> +#define EXCP_MISALIG_INST 0x2a
> +#define EXCP_ICPLB_PROT 0x2b
> +#define EXCP_ICPLB_MISS 0x2c
> +#define EXCP_ICPLB_MULT 0x2d
> +#define EXCP_ILL_SUPV 0x2e
> +#define EXCP_ABORT 0x100
> +#define EXCP_DBGA 0x101
> +#define EXCP_OUTC 0x102
> +
> +#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_1
> +
> +#define BFIN_L1_CACHE_BYTES 32
> +
> +/* Blackfin does 1K/4K/1M/4M, but for now only support 4k */
> +#define TARGET_PAGE_BITS 12
> +#define NB_MMU_MODES 2
> +
> +#define TARGET_PHYS_ADDR_SPACE_BITS 32
> +#define TARGET_VIRT_ADDR_SPACE_BITS 32
> +
> +#define cpu_init cpu_bfin_init
> +#define cpu_exec cpu_bfin_exec
> +#define cpu_gen_code cpu_bfin_gen_code
> +#define cpu_signal_handler cpu_bfin_signal_handler
> +
> +/* Indexes into astat array; matches bitpos in hardware too */
> +enum {
> + ASTAT_AZ = 0,
> + ASTAT_AN,
> + ASTAT_AC0_COPY,
> + ASTAT_V_COPY,
> + ASTAT_CC = 5,
> + ASTAT_AQ,
> + ASTAT_RND_MOD = 8,
> + ASTAT_AC0 = 12,
> + ASTAT_AC1,
> + ASTAT_AV0 = 16,
> + ASTAT_AV0S,
> + ASTAT_AV1,
> + ASTAT_AV1S,
> + ASTAT_V = 24,
> + ASTAT_VS
> +};
> +
> +typedef struct CPUBfinState {
> + CPU_COMMON
> + int personality;
> +
> + uint32_t dreg[8];
> + uint32_t preg[8];
> + uint32_t ireg[4];
> + uint32_t mreg[4];
> + uint32_t breg[4];
> + uint32_t lreg[4];
> + uint64_t areg[2];
> + uint32_t rets;
> + uint32_t lcreg[2], ltreg[2], lbreg[2];
> + uint32_t cycles[2];
> + uint32_t uspreg;
> + uint32_t seqstat;
> + uint32_t syscfg;
> + uint32_t reti;
> + uint32_t retx;
> + uint32_t retn;
> + uint32_t rete;
> + uint32_t emudat;
> + uint32_t pc;
> +
> + /* ASTAT bits; broken up for speeeeeeeed */
> + uint32_t astat[32];
> + /* ASTAT delayed helpers */
> + uint32_t astat_op, astat_arg[3];
Are you sure this field placement is what you want? Usually reset
memset()s all fields up to breakpoints (inside CPU_COMMON) so registers
are usually placed before CPU_COMMON.
Any field that is not a register accessed by TCG should rather be in
BlackfinCPU or BlackfinCPUClass - personality sounds like a candidate?
> +} CPUBfinState;
> +#define spreg preg[6]
> +#define fpreg preg[7]
> +
> +static inline uint32_t bfin_astat_read(CPUArchState *env)
> +{
> + unsigned int i, ret;
> +
> + ret = 0;
> + for (i = 0; i < 32; ++i)
> + ret |= (env->astat[i] << i);
> +
> + return ret;
> +}
> +
> +static inline void bfin_astat_write(CPUArchState *env, uint32_t astat)
> +{
> + unsigned int i;
> + for (i = 0; i < 32; ++i)
> + env->astat[i] = !!(astat & (1 << i));
> +}
> +
> +enum astat_ops {
> + ASTAT_OP_NONE,
> + ASTAT_OP_DYNAMIC,
> + ASTAT_OP_ABS,
> + ASTAT_OP_ABS_VECTOR,
> + ASTAT_OP_ADD16,
> + ASTAT_OP_ADD32,
> + ASTAT_OP_ASHIFT16,
> + ASTAT_OP_ASHIFT32,
> + ASTAT_OP_COMPARE_SIGNED,
> + ASTAT_OP_COMPARE_UNSIGNED,
> + ASTAT_OP_LOGICAL,
> + ASTAT_OP_LSHIFT16,
> + ASTAT_OP_LSHIFT32,
> + ASTAT_OP_LSHIFT_RT16,
> + ASTAT_OP_LSHIFT_RT32,
> + ASTAT_OP_MIN_MAX,
> + ASTAT_OP_MIN_MAX_VECTOR,
> + ASTAT_OP_NEGATE,
> + ASTAT_OP_SUB16,
> + ASTAT_OP_SUB32,
> + ASTAT_OP_VECTOR_ADD_ADD, /* +|+ */
> + ASTAT_OP_VECTOR_ADD_SUB, /* +|- */
> + ASTAT_OP_VECTOR_SUB_SUB, /* -|- */
> + ASTAT_OP_VECTOR_SUB_ADD, /* -|+ */
> +};
> +
> +typedef void (*hwloop_callback)(struct DisasContext *dc, int loop);
> +
> +typedef struct DisasContext {
> + CPUArchState *env;
> + struct TranslationBlock *tb;
> + /* The current PC we're decoding (could be middle of parallel insn) */
> + target_ulong pc;
> + /* Length of current insn (2/4/8) */
> + target_ulong insn_len;
> +
> + /* For delayed ASTAT handling */
> + enum astat_ops astat_op;
> +
> + /* For hardware loop processing */
> + hwloop_callback hwloop_callback;
> + void *hwloop_data;
> +
> + /* Was a DISALGNEXCPT used in this parallel insn ? */
> + int disalgnexcpt;
> +
> + int is_jmp;
> + int mem_idx;
> +} DisasContext;
> +
> +void do_interrupt(CPUArchState *env);
do_interrupt() has recently been converted to a CPUClass hook.
> +CPUArchState *cpu_init(const char *cpu_model);
> +int cpu_exec(CPUArchState *s);
> +int cpu_bfin_signal_handler(int host_signum, void *pinfo, void *puc);
> +
> +extern const char * const greg_names[];
> +extern const char *get_allreg_name(int grp, int reg);
> +
> +#define MMU_KERNEL_IDX 0
> +#define MMU_USER_IDX 1
> +
> +int cpu_bfin_handle_mmu_fault(CPUArchState *env, target_ulong address, int
> rw,
> + int mmu_idx);
> +#define cpu_handle_mmu_fault cpu_bfin_handle_mmu_fault
> +
> +#if defined(CONFIG_USER_ONLY)
> +static inline void cpu_clone_regs(CPUArchState *env, target_ulong newsp)
> +{
> + if (newsp)
> + env->spreg = newsp;
> +}
> +#endif
Note there's a pending patch moving cpu_clone_regs() to
linux-user/*/target_cpu.h.
> +
> +#include "exec/cpu-all.h"
> +#include "cpu-qom.h"
> +
> +static inline bool cpu_has_work(CPUState *cpu)
> +{
> + return (cpu->interrupt_request & (CPU_INTERRUPT_HARD |
> CPU_INTERRUPT_NMI));
> +}
> +
> +#include "exec/exec-all.h"
> +
> +static inline void cpu_pc_from_tb(CPUArchState *env, TranslationBlock *tb)
> +{
> + env->pc = tb->pc;
> +}
> +
> +static inline target_ulong cpu_get_pc(CPUArchState *env)
> +{
> + return env->pc;
> +}
Unused?
> +
> +static inline void cpu_get_tb_cpu_state(CPUArchState *env, target_ulong *pc,
> + target_ulong *cs_base, int *flags)
> +{
> + *pc = cpu_get_pc(env);
> + *cs_base = 0;
> + *flags = env->astat[ASTAT_RND_MOD];
> +}
> +
> +#endif
[...]
> diff --git a/target-bfin/translate.c b/target-bfin/translate.c
> new file mode 100644
> index 0000000..a619f66
> --- /dev/null
> +++ b/target-bfin/translate.c
[...]
> +
> +CPUArchState *cpu_init(const char *cpu_model)
> +{
> + BfinCPU *cpu;
> + CPUArchState *env;
> + static int tcg_initialized = 0;
> +
> + cpu = BFIN_CPU(object_new(TYPE_BFIN_CPU));
> + env = &cpu->env;
> +
> + cpu_reset(CPU(cpu));
> + qemu_init_vcpu(env);
> +
> + if (tcg_initialized)
> + return env;
> +
> + tcg_initialized = 1;
Please place this into the CPU realizefn. Note that qemu_init_vcpu() is
being moved to generic code with my next pull.
In light of possible bfin-softmmu support, please turn this function
into BlackfinCPU *cpu_bfin_init(const char *cpu_model) and place
cpu_init() as a static inline compatibility wrapper into cpu.h.
> +
> +#define GEN_HELPER 2
> +#include "helper.h"
> +
> + cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
> +
> + cpu_pc = tcg_global_mem_new(TCG_AREG0,
> + offsetof(CPUArchState, pc), "PC");
> + cpu_cc = tcg_global_mem_new(TCG_AREG0,
> + offsetof(CPUArchState, astat[ASTAT_CC]), "CC");
> +
> + /*cpu_astat_op = tcg_global_mem_new(TCG_AREG0,
> + offsetof(CPUArchState, astat_op), "astat_op");*/
> + cpu_astat_arg[0] = tcg_global_mem_new(TCG_AREG0,
> + offsetof(CPUArchState, astat_arg[0]), "astat_arg[0]");
> + cpu_astat_arg[1] = tcg_global_mem_new(TCG_AREG0,
> + offsetof(CPUArchState, astat_arg[1]), "astat_arg[1]");
> + cpu_astat_arg[2] = tcg_global_mem_new(TCG_AREG0,
> + offsetof(CPUArchState, astat_arg[2]), "astat_arg[2]");
> +
> + cpu_areg[0] = tcg_global_mem_new_i64(TCG_AREG0,
> + offsetof(CPUArchState, areg[0]), "A0");
> + cpu_areg[1] = tcg_global_mem_new_i64(TCG_AREG0,
> + offsetof(CPUArchState, areg[1]), "A1");
> +
> + bfin_tcg_new_set(dreg, 0);
> + bfin_tcg_new_set(preg, 8);
> + bfin_tcg_new_set(ireg, 16);
> + bfin_tcg_new_set(mreg, 20);
> + bfin_tcg_new_set(breg, 24);
> + bfin_tcg_new_set(lreg, 28);
> + bfin_tcg_new(rets, 39);
> + bfin_tcg_new(lcreg[0], 48);
> + bfin_tcg_new(ltreg[0], 49);
> + bfin_tcg_new(lbreg[0], 50);
> + bfin_tcg_new(lcreg[1], 51);
> + bfin_tcg_new(ltreg[1], 52);
> + bfin_tcg_new(lbreg[1], 53);
> + bfin_tcg_new_set(cycles, 54);
> + bfin_tcg_new(uspreg, 56);
> + bfin_tcg_new(seqstat, 57);
> + bfin_tcg_new(syscfg, 58);
> + bfin_tcg_new(reti, 59);
> + bfin_tcg_new(retx, 60);
> + bfin_tcg_new(retn, 61);
> + bfin_tcg_new(rete, 62);
> + bfin_tcg_new(emudat, 63);
> +
> + return env;
> +}
> +
> +#define _astat_printf(bit) cpu_fprintf(f, "%s" #bit " ",
> (env->astat[ASTAT_##bit] ? "" : "~"))
> +void cpu_dump_state(CPUArchState *env, FILE *f,
> + int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
> + int flags)
> +{
This will be converted to a CPUClass hook in my next pull.
[...]
> +static void
> +gen_intermediate_code_internal(CPUArchState *env, TranslationBlock *tb,
> + int search_pc)
> +{
Please use BlackfinCPU and bool arguments here, I am about to convert
all other targets (github.com/afaerber/qemu-cpu.git qom-cpu-11).
[...]
> +
> +void gen_intermediate_code(CPUArchState *env, struct TranslationBlock *tb)
> +{
> + gen_intermediate_code_internal(env, tb, 0);
> +}
> +
> +void gen_intermediate_code_pc(CPUArchState *env, struct TranslationBlock *tb)
> +{
> + gen_intermediate_code_internal(env, tb, 1);
> +}
> +
> +void restore_state_to_opc(CPUArchState *env, TranslationBlock *tb, int
> pc_pos)
> +{
> + env->pc = tcg_ctx.gen_opc_pc[pc_pos];
> +}
> +
> +#include "bfin-sim.c"
Regards,
Andreas
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
- [Qemu-devel] [PATCH 0/5] Initial Blackfin support (linux-user only), Mike Frysinger, 2013/06/17
- [Qemu-devel] [PATCH 1/5] Blackfin: add disassembler support, Mike Frysinger, 2013/06/17
- [Qemu-devel] [PATCH 2/5] Blackfin: initial port, Mike Frysinger, 2013/06/17
- [Qemu-devel] [PATCH 5/5] linux-user: add support for Blackfin syscalls, Mike Frysinger, 2013/06/17
- [Qemu-devel] [PATCH 3/5] Blackfin: add linux-user support, Mike Frysinger, 2013/06/17
- [Qemu-devel] [PATCH 4/5] Blackfin: add test suite, Mike Frysinger, 2013/06/17
- Re: [Qemu-devel] [PATCH 2/5] Blackfin: initial port, Richard Henderson, 2013/06/25
- Re: [Qemu-devel] [PATCH 2/5] Blackfin: initial port, Eric Blake, 2013/06/28
- Re: [Qemu-devel] [PATCH 2/5] Blackfin: initial port,
Andreas Färber <=