From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33922) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XOPHQ-0003KJ-FJ for qemu-devel@nongnu.org; Mon, 01 Sep 2014 06:56:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XOPHF-0008TY-C9 for qemu-devel@nongnu.org; Mon, 01 Sep 2014 06:56:12 -0400 Received: from mail.uni-paderborn.de ([131.234.142.9]:8277) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XOPHE-0008St-Uw for qemu-devel@nongnu.org; Mon, 01 Sep 2014 06:56:01 -0400 From: Bastian Koppelmann Date: Mon, 1 Sep 2014 12:59:46 +0100 Message-Id: <1409572800-4116-2-git-send-email-kbastian@mail.uni-paderborn.de> In-Reply-To: <1409572800-4116-1-git-send-email-kbastian@mail.uni-paderborn.de> References: <1409572800-4116-1-git-send-email-kbastian@mail.uni-paderborn.de> Subject: [Qemu-devel] [PATCH v7 01/15] target-tricore: Add target stubs and qom-cpu List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, rth@twiddle.net Add TriCore target stubs, and QOM cpu, and Maintainer Signed-off-by: Bastian Koppelmann --- v6 -> v7: - TRICORECPU -> TriCoreCPU. - TRICORECPUClass -> TriCoreCPUClass. - CPUTRICOREState -> CPUTriCoreState. - TRICORECPUInfo: Add terminator. - TRICORECPUInfo -> TriCoreCPUInfo. - Remove ARM-style IRQ and FIQ lines. - CPUTRICOREState: target_ulong -> uint32_t. - CPUTRICOREState: Move mask defines below the struct. MAINTAINERS | 6 + arch_init.c | 2 + cpu-exec.c | 11 +- cpus.c | 6 + include/elf.h | 2 + include/sysemu/arch_init.h | 1 + target-tricore/Makefile.objs | 1 + target-tricore/cpu-qom.h | 71 ++++++++ target-tricore/cpu.c | 192 ++++++++++++++++++++ target-tricore/cpu.h | 405 ++++++++++++++++++++++++++++++++++++++++++ target-tricore/helper.c | 92 ++++++++++ target-tricore/helper.h | 0 target-tricore/op_helper.c | 27 +++ target-tricore/translate.c | 100 +++++++++++ target-tricore/tricore-defs.h | 28 +++ 15 files changed, 943 insertions(+), 1 deletion(-) create mode 100644 target-tricore/Makefile.objs create mode 100644 target-tricore/cpu-qom.h create mode 100644 target-tricore/cpu.c create mode 100644 target-tricore/cpu.h create mode 100644 target-tricore/helper.c create mode 100644 target-tricore/helper.h create mode 100644 target-tricore/op_helper.c create mode 100644 target-tricore/translate.c create mode 100644 target-tricore/tricore-defs.h diff --git a/MAINTAINERS b/MAINTAINERS index a74c04c..142f68a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -161,6 +161,12 @@ S: Maintained F: target-xtensa/ F: hw/xtensa/ +TriCore +M: Bastian Koppelmann +S: Maintained +F: target-tricore/ +F: hw/tricore/ + Guest CPU Cores (KVM): ---------------------- diff --git a/arch_init.c b/arch_init.c index 28ece76..c974f3f 100644 --- a/arch_init.c +++ b/arch_init.c @@ -104,6 +104,8 @@ int graphic_depth = 32; #define QEMU_ARCH QEMU_ARCH_XTENSA #elif defined(TARGET_UNICORE32) #define QEMU_ARCH QEMU_ARCH_UNICORE32 +#elif defined(TARGET_TRICORE) +#define QEMU_ARCH QEMU_ARCH_TRICORE #endif const uint32_t arch_type = QEMU_ARCH; diff --git a/cpu-exec.c b/cpu-exec.c index c6aad74..7b5d2e2 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -387,6 +387,7 @@ int cpu_exec(CPUArchState *env) #elif defined(TARGET_CRIS) #elif defined(TARGET_S390X) #elif defined(TARGET_XTENSA) +#elif defined(TARGET_TRICORE) /* XXXXX */ #else #error unsupported target CPU @@ -444,7 +445,8 @@ int cpu_exec(CPUArchState *env) } #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \ defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \ - defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32) + defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || \ + defined(TARGET_UNICORE32) || defined(TARGET_TRICORE) if (interrupt_request & CPU_INTERRUPT_HALT) { cpu->interrupt_request &= ~CPU_INTERRUPT_HALT; cpu->halted = 1; @@ -560,6 +562,12 @@ int cpu_exec(CPUArchState *env) cc->do_interrupt(cpu); next_tb = 0; } +#elif defined(TARGET_TRICORE) + if ((interrupt_request & CPU_INTERRUPT_HARD)) { + cc->do_interrupt(cpu); + next_tb = 0; + } + #elif defined(TARGET_OPENRISC) { int idx = -1; @@ -846,6 +854,7 @@ int cpu_exec(CPUArchState *env) | env->cc_dest | (env->cc_x << 4); #elif defined(TARGET_MICROBLAZE) #elif defined(TARGET_MIPS) +#elif defined(TARGET_TRICORE) #elif defined(TARGET_MOXIE) #elif defined(TARGET_OPENRISC) #elif defined(TARGET_SH4) diff --git a/cpus.c b/cpus.c index eb1ac85..0f7d0ea 100644 --- a/cpus.c +++ b/cpus.c @@ -1410,6 +1410,9 @@ CpuInfoList *qmp_query_cpus(Error **errp) #elif defined(TARGET_MIPS) MIPSCPU *mips_cpu = MIPS_CPU(cpu); CPUMIPSState *env = &mips_cpu->env; +#elif defined(TARGET_TRICORE) + TriCoreCPU *tricore_cpu = TRICORE_CPU(cpu); + CPUTriCoreState *env = &tricore_cpu->env; #endif cpu_synchronize_state(cpu); @@ -1434,6 +1437,9 @@ CpuInfoList *qmp_query_cpus(Error **errp) #elif defined(TARGET_MIPS) info->value->has_PC = true; info->value->PC = env->active_tc.PC; +#elif defined(TARGET_TRICORE) + info->value->has_PC = true; + info->value->PC = env->PC; #endif /* XXX: waiting for the qapi to support GSList */ diff --git a/include/elf.h b/include/elf.h index e88d52f..70107f0 100644 --- a/include/elf.h +++ b/include/elf.h @@ -92,6 +92,8 @@ typedef int64_t Elf64_Sxword; #define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_TRICORE 44 /* Infineon TriCore */ + #define EM_IA_64 50 /* HP/Intel IA-64 */ #define EM_X86_64 62 /* AMD x86-64 */ diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h index 182d48d..8939233 100644 --- a/include/sysemu/arch_init.h +++ b/include/sysemu/arch_init.h @@ -22,6 +22,7 @@ enum { QEMU_ARCH_OPENRISC = 8192, QEMU_ARCH_UNICORE32 = 0x4000, QEMU_ARCH_MOXIE = 0x8000, + QEMU_ARCH_TRICORE = 0x10000, }; extern const uint32_t arch_type; diff --git a/target-tricore/Makefile.objs b/target-tricore/Makefile.objs new file mode 100644 index 0000000..21e820d --- /dev/null +++ b/target-tricore/Makefile.objs @@ -0,0 +1 @@ +obj-y += translate.o helper.o cpu.o op_helper.o diff --git a/target-tricore/cpu-qom.h b/target-tricore/cpu-qom.h new file mode 100644 index 0000000..470215a --- /dev/null +++ b/target-tricore/cpu-qom.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef QEMU_TRICORE_CPU_QOM_H +#define QEMU_TRICORE_CPU_QOM_H + +#include "qom/cpu.h" + + +#define TYPE_TRICORE_CPU "tricore-cpu" + +#define TRICORE_CPU_CLASS(klass) \ + OBJECT_CLASS_CHECK(TriCoreCPUClass, (klass), TYPE_TRICORE_CPU) +#define TRICORE_CPU(obj) \ + OBJECT_CHECK(TriCoreCPU, (obj), TYPE_TRICORE_CPU) +#define TRICORE_CPU_GET_CLASS(obj) \ + OBJECT_GET_CLASS(TriCoreCPUClass, (obj), TYPE_TRICORE_CPU) + +typedef struct TriCoreCPUClass { + /*< private >*/ + CPUClass parent_class; + /*< public >*/ + + DeviceRealize parent_realize; + void (*parent_reset)(CPUState *cpu); +} TriCoreCPUClass; + +/** + * TriCoreCPU: + * @env: #CPUTriCoreState + * + * A TriCore CPU. + */ +typedef struct TriCoreCPU { + /*< private >*/ + CPUState parent_obj; + /*< public >*/ + + CPUTriCoreState env; +} TriCoreCPU; + +static inline TriCoreCPU *tricore_env_get_cpu(CPUTriCoreState *env) +{ + return TRICORE_CPU(container_of(env, TriCoreCPU, env)); +} + +#define ENV_GET_CPU(e) CPU(tricore_env_get_cpu(e)) + +#define ENV_OFFSET offsetof(TriCoreCPU, env) + +hwaddr tricore_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); +void tricore_cpu_do_interrupt(CPUState *cpu); +void tricore_cpu_dump_state(CPUState *cpu, FILE *f, + fprintf_function cpu_fprintf, int flags); + + +#endif /*QEMU_TRICORE_CPU_QOM_H */ diff --git a/target-tricore/cpu.c b/target-tricore/cpu.c new file mode 100644 index 0000000..db9f404 --- /dev/null +++ b/target-tricore/cpu.c @@ -0,0 +1,192 @@ +/* + * TriCore emulation for qemu: main translation routines. + * + * Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "cpu.h" +#include "qemu-common.h" + +static inline void set_feature(CPUTriCoreState *env, int feature) +{ + env->features |= 1ULL << feature; +} + +static void tricore_cpu_set_pc(CPUState *cs, vaddr value) +{ + TriCoreCPU *cpu = TRICORE_CPU(cs); + CPUTriCoreState *env = &cpu->env; + + env->PC = value & ~(target_ulong)1; +} + +static void tricore_cpu_synchronize_from_tb(CPUState *cs, + TranslationBlock *tb) +{ + TriCoreCPU *cpu = TRICORE_CPU(cs); + CPUTriCoreState *env = &cpu->env; + + env->PC = tb->pc; +} + +static void tricore_cpu_reset(CPUState *s) +{ + TriCoreCPU *cpu = TRICORE_CPU(s); + TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(cpu); + CPUTriCoreState *env = &cpu->env; + + tcc->parent_reset(s); + + tlb_flush(s, 1); + + cpu_state_reset(env); +} + +static bool tricore_cpu_has_work(CPUState *cs) +{ + return true; +} + +static void tricore_cpu_realizefn(DeviceState *dev, Error **errp) +{ + CPUState *cs = CPU(dev); + TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(dev); + + cpu_reset(cs); + qemu_init_vcpu(cs); + + tcc->parent_realize(dev, errp); +} + + +static void tricore_cpu_initfn(Object *obj) +{ + CPUState *cs = CPU(obj); + TriCoreCPU *cpu = TRICORE_CPU(obj); + CPUTriCoreState *env = &cpu->env; + + cs->env_ptr = env; + cpu_exec_init(env); + + if (tcg_enabled()) { + tricore_tcg_init(); + } +} + +static ObjectClass *tricore_cpu_class_by_name(const char *cpu_model) +{ + ObjectClass *oc; + char *typename; + + if (!cpu_model) { + return NULL; + } + + typename = g_strdup_printf("%s-" TYPE_TRICORE_CPU, cpu_model); + oc = object_class_by_name(typename); + g_free(typename); + if (!oc || !object_class_dynamic_cast(oc, TYPE_TRICORE_CPU) || + object_class_is_abstract(oc)) { + return NULL; + } + return oc; +} + +static void tc1796_initfn(Object *obj) +{ + TriCoreCPU *cpu = TRICORE_CPU(obj); + + set_feature(&cpu->env, TRICORE_FEATURE_13); +} + +static void aurix_initfn(Object *obj) +{ + TriCoreCPU *cpu = TRICORE_CPU(obj); + + set_feature(&cpu->env, TRICORE_FEATURE_16); +} + +typedef struct TriCoreCPUInfo { + const char *name; + void (*initfn)(Object *obj); + void (*class_init)(ObjectClass *oc, void *data); +} TriCoreCPUInfo; + +static const TriCoreCPUInfo tricore_cpus[] = { + { .name = "tc1796", .initfn = tc1796_initfn }, + { .name = "aurix", .initfn = aurix_initfn }, + { .name = NULL } +}; + +static void tricore_cpu_class_init(ObjectClass *c, void *data) +{ + TriCoreCPUClass *mcc = TRICORE_CPU_CLASS(c); + CPUClass *cc = CPU_CLASS(c); + DeviceClass *dc = DEVICE_CLASS(c); + + mcc->parent_realize = dc->realize; + dc->realize = tricore_cpu_realizefn; + + mcc->parent_reset = cc->reset; + cc->reset = tricore_cpu_reset; + cc->class_by_name = tricore_cpu_class_by_name; + cc->has_work = tricore_cpu_has_work; + + cc->do_interrupt = tricore_cpu_do_interrupt; + cc->dump_state = tricore_cpu_dump_state; + cc->set_pc = tricore_cpu_set_pc; + cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb; + +} + +static void cpu_register(const TriCoreCPUInfo *info) +{ + TypeInfo type_info = { + .parent = TYPE_TRICORE_CPU, + .instance_size = sizeof(TriCoreCPU), + .instance_init = info->initfn, + .class_size = sizeof(TriCoreCPUClass), + .class_init = info->class_init, + }; + + type_info.name = g_strdup_printf("%s-" TYPE_TRICORE_CPU, info->name); + type_register(&type_info); + g_free((void *)type_info.name); +} + +static const TypeInfo tricore_cpu_type_info = { + .name = TYPE_TRICORE_CPU, + .parent = TYPE_CPU, + .instance_size = sizeof(TriCoreCPU), + .instance_init = tricore_cpu_initfn, + .abstract = true, + .class_size = sizeof(TriCoreCPUClass), + .class_init = tricore_cpu_class_init, +}; + +static void tricore_cpu_register_types(void) +{ + const TriCoreCPUInfo *info = tricore_cpus; + + type_register_static(&tricore_cpu_type_info); + + while (info->name) { + cpu_register(info); + info++; + } +} + +type_init(tricore_cpu_register_types) diff --git a/target-tricore/cpu.h b/target-tricore/cpu.h new file mode 100644 index 0000000..b036ff1 --- /dev/null +++ b/target-tricore/cpu.h @@ -0,0 +1,405 @@ +/* + * TriCore emulation for qemu: main CPU struct. + * + * Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#if !defined(__TRICORE_CPU_H__) +#define __TRICORE_CPU_H__ + +#include "tricore-defs.h" +#include "config.h" +#include "qemu-common.h" +#include "exec/cpu-defs.h" +#include "fpu/softfloat.h" + +#define ELF_MACHINE EM_TRICORE + +#define CPUArchState struct CPUTriCoreState + +struct CPUTriCoreState; + +struct tricore_boot_info; + +#define NB_MMU_MODES 3 + +typedef struct tricore_def_t tricore_def_t; + +typedef struct CPUTriCoreState CPUTriCoreState; +struct CPUTriCoreState { + /* GPR Register */ + uint32_t gpr_a[16]; + uint32_t gpr_d[16]; + /* CSFR Register */ + uint32_t PCXI; +/* Frequently accessed PSW_USB bits are stored separately for efficiency. + This contains all the other bits. Use psw_{read,write} to access + the whole PSW. */ + uint32_t PSW; + + /* PSW flag cache for faster execution + */ + uint32_t PSW_USB_C; + uint32_t PSW_USB_V; /* Only if bit 31 set, then flag is set */ + uint32_t PSW_USB_SV; /* Only if bit 31 set, then flag is set */ + uint32_t PSW_USB_AV; /* Only if bit 31 set, then flag is set. */ + uint32_t PSW_USB_SAV; /* Only if bit 31 set, then flag is set. */ + + uint32_t PC; + uint32_t SYSCON; + uint32_t CPU_ID; + uint32_t BIV; + uint32_t BTV; + uint32_t ISP; + uint32_t ICR; + uint32_t FCX; + uint32_t LCX; + uint32_t COMPAT; + + /* Mem Protection Register */ + uint32_t DPR0_0L; + uint32_t DPR0_0U; + uint32_t DPR0_1L; + uint32_t DPR0_1U; + uint32_t DPR0_2L; + uint32_t DPR0_2U; + uint32_t DPR0_3L; + uint32_t DPR0_3U; + + uint32_t DPR1_0L; + uint32_t DPR1_0U; + uint32_t DPR1_1L; + uint32_t DPR1_1U; + uint32_t DPR1_2L; + uint32_t DPR1_2U; + uint32_t DPR1_3L; + uint32_t DPR1_3U; + + uint32_t DPR2_0L; + uint32_t DPR2_0U; + uint32_t DPR2_1L; + uint32_t DPR2_1U; + uint32_t DPR2_2L; + uint32_t DPR2_2U; + uint32_t DPR2_3L; + uint32_t DPR2_3U; + + uint32_t DPR3_0L; + uint32_t DPR3_0U; + uint32_t DPR3_1L; + uint32_t DPR3_1U; + uint32_t DPR3_2L; + uint32_t DPR3_2U; + uint32_t DPR3_3L; + uint32_t DPR3_3U; + + uint32_t CPR0_0L; + uint32_t CPR0_0U; + uint32_t CPR0_1L; + uint32_t CPR0_1U; + uint32_t CPR0_2L; + uint32_t CPR0_2U; + uint32_t CPR0_3L; + uint32_t CPR0_3U; + + uint32_t CPR1_0L; + uint32_t CPR1_0U; + uint32_t CPR1_1L; + uint32_t CPR1_1U; + uint32_t CPR1_2L; + uint32_t CPR1_2U; + uint32_t CPR1_3L; + uint32_t CPR1_3U; + + uint32_t CPR2_0L; + uint32_t CPR2_0U; + uint32_t CPR2_1L; + uint32_t CPR2_1U; + uint32_t CPR2_2L; + uint32_t CPR2_2U; + uint32_t CPR2_3L; + uint32_t CPR2_3U; + + uint32_t CPR3_0L; + uint32_t CPR3_0U; + uint32_t CPR3_1L; + uint32_t CPR3_1U; + uint32_t CPR3_2L; + uint32_t CPR3_2U; + uint32_t CPR3_3L; + uint32_t CPR3_3U; + + uint32_t DPM0; + uint32_t DPM1; + uint32_t DPM2; + uint32_t DPM3; + + uint32_t CPM0; + uint32_t CPM1; + uint32_t CPM2; + uint32_t CPM3; + + /* Memory Management Registers */ + uint32_t MMU_CON; + uint32_t MMU_ASI; + uint32_t MMU_TVA; + uint32_t MMU_TPA; + uint32_t MMU_TPX; + uint32_t MMU_TFA; + /* {1.3.1 only */ + uint32_t BMACON; + uint32_t SMACON; + uint32_t DIEAR; + uint32_t DIETR; + uint32_t CCDIER; + uint32_t MIECON; + uint32_t PIEAR; + uint32_t PIETR; + uint32_t CCPIER; + /*} */ + /* Debug Registers */ + uint32_t DBGSR; + uint32_t EXEVT; + uint32_t CREVT; + uint32_t SWEVT; + uint32_t TR0EVT; + uint32_t TR1EVT; + uint32_t DMS; + uint32_t DCX; + uint32_t DBGTCR; + uint32_t CCTRL; + uint32_t CCNT; + uint32_t ICNT; + uint32_t M1CNT; + uint32_t M2CNT; + uint32_t M3CNT; + /* Floating Point Registers */ + /* XXX: */ + + /* QEMU */ + int error_code; + uint32_t hflags; /* CPU State */ + + CPU_COMMON + + /* Internal CPU feature flags. */ + uint64_t features; + + const tricore_def_t *cpu_model; + void *irq[8]; + struct QEMUTimer *timer; /* Internal timer */ +}; + +#define MASK_PCXI_PCPN 0xff000000 +#define MASK_PCXI_PIE 0x00800000 +#define MASK_PCXI_UL 0x00400000 +#define MASK_PCXI_PCXS 0x000f0000 +#define MASK_PCXI_PCXO 0x0000ffff + +#define MASK_PSW_USB 0xff000000 +#define MASK_USB_C 0x80000000 +#define MASK_USB_V 0x40000000 +#define MASK_USB_SV 0x20000000 +#define MASK_USB_AV 0x10000000 +#define MASK_USB_SAV 0x08000000 +#define MASK_PSW_PRS 0x00003000 +#define MASK_PSW_IO 0x00000c00 +#define MASK_PSW_IS 0x00000200 +#define MASK_PSW_GW 0x00000100 +#define MASK_PSW_CDE 0x00000080 +#define MASK_PSW_CDC 0x0000007f + +#define MASK_SYSCON_PRO_TEN 0x2 +#define MASK_SYSCON_FCD_SF 0x1 + +#define MASK_CPUID_MOD 0xffff0000 +#define MASK_CPUID_MOD_32B 0x0000ff00 +#define MASK_CPUID_REV 0x000000ff + +#define MASK_ICR_PIPN 0x00ff0000 +#define MASK_ICR_IE 0x00000100 +#define MASK_ICR_CCPN 0x000000ff + +#define MASK_FCX_FCXS 0x000f0000 +#define MASK_FCX_FCXO 0x0000ffff + +#define MASK_LCX_LCXS 0x000f0000 +#define MASK_LCX_LCX0 0x0000ffff + +#define TRICORE_HFLAG_UM0 0x00002 /* user mode-0 flag */ +#define TRICORE_HFLAG_UM1 0x00001 /* user mode-1 flag */ +#define TRICORE_HFLAG_SM 0x00000 /* kernel mode flag */ + +enum tricore_features { + TRICORE_FEATURE_13, + TRICORE_FEATURE_131, + TRICORE_FEATURE_16, +}; + +static inline int tricore_feature(CPUTriCoreState *env, int feature) +{ + return (env->features & (1ULL << feature)) != 0; +} + +/* TriCore Traps Classes*/ +enum { + TRAPC_NONE = -1, + TRAPC_MMU = 0, + TRAPC_PROT = 1, + TRAPC_INSN_ERR = 2, + TRAPC_CTX_MNG = 3, + TRAPC_SYSBUS = 4, + TRAPC_ASSERT = 5, + TRAPC_SYSCALL = 6, + TRAPC_NMI = 7, +}; + +/* Class 0 TIN */ +enum { + TIN0_VAF = 0, + TIN0_VAP = 1, +}; + +/* Class 1 TIN */ +enum { + TIN1_PRIV = 1, + TIN1_MPR = 2, + TIN1_MPW = 3, + TIN1_MPX = 4, + TIN1_MPP = 5, + TIN1_MPN = 6, + TIN1_GRWP = 7, +}; + +/* Class 2 TIN */ +enum { + TIN2_IOPC = 1, + TIN2_UOPC = 2, + TIN2_OPD = 3, + TIN2_ALN = 4, + TIN2_MEM = 5, +}; + +/* Class 3 TIN */ +enum { + TIN3_FCD = 1, + TIN3_CDO = 2, + TIN3_CDU = 3, + TIN3_FCU = 4, + TIN3_CSU = 5, + TIN3_CTYP = 6, + TIN3_NEST = 7, +}; + +/* Class 4 TIN */ +enum { + TIN4_PSE = 1, + TIN4_DSE = 2, + TIN4_DAE = 3, + TIN4_CAE = 4, + TIN4_PIE = 5, + TIN4_DIE = 6, +}; + +/* Class 5 TIN */ +enum { + TIN5_OVF = 1, + TIN5_SOVF = 1, +}; + +/* Class 6 TIN + * + * Is always TIN6_SYS + */ + +/* Class 7 TIN */ +enum { + TIN7_NMI = 0, +}; + +uint32_t psw_read(CPUTriCoreState *env); +void psw_write(CPUTriCoreState *env, uint32_t val); + +#include "cpu-qom.h" +#define MMU_USER_IDX 2 + +void tricore_cpu_list(FILE *f, fprintf_function cpu_fprintf); + +#define cpu_exec cpu_tricore_exec +#define cpu_signal_handler cpu_tricore_signal_handler +#define cpu_list tricore_cpu_list + +static inline int cpu_mmu_index(CPUTriCoreState *env) +{ + return 0; +} + + + +#include "exec/cpu-all.h" + +enum { + /* 1 bit to define user level / supervisor access */ + ACCESS_USER = 0x00, + ACCESS_SUPER = 0x01, + /* 1 bit to indicate direction */ + ACCESS_STORE = 0x02, + /* Type of instruction that generated the access */ + ACCESS_CODE = 0x10, /* Code fetch access */ + ACCESS_INT = 0x20, /* Integer load/store access */ + ACCESS_FLOAT = 0x30, /* floating point load/store access */ +}; + +void cpu_state_reset(CPUTriCoreState *s); +int cpu_tricore_exec(CPUTriCoreState *s); +void tricore_tcg_init(void); +int cpu_tricore_signal_handler(int host_signum, void *pinfo, void *puc); + +static inline void cpu_get_tb_cpu_state(CPUTriCoreState *env, target_ulong *pc, + target_ulong *cs_base, int *flags) +{ + *pc = env->PC; + *cs_base = 0; + *flags = 0; +} + +TriCoreCPU *cpu_tricore_init(const char *cpu_model); + +static inline CPUTriCoreState *cpu_init(const char *cpu_model) +{ + TriCoreCPU *cpu = cpu_tricore_init(cpu_model); + if (cpu == NULL) { + return NULL; + } + return &cpu->env; + +} + + +/* helpers.c */ +int cpu_tricore_handle_mmu_fault(CPUState *cpu, target_ulong address, + int rw, int mmu_idx); +#define cpu_handle_mmu_fault cpu_tricore_handle_mmu_fault + +#include "exec/exec-all.h" + +static inline void cpu_pc_from_tb(CPUTriCoreState *env, TranslationBlock *tb) +{ + env->PC = tb->pc; +} + +void do_interrupt(CPUTriCoreState *env); + +#endif /*__TRICORE_CPU_H__ */ diff --git a/target-tricore/helper.c b/target-tricore/helper.c new file mode 100644 index 0000000..ee7f007 --- /dev/null +++ b/target-tricore/helper.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include "cpu.h" + +int cpu_tricore_handle_mmu_fault(CPUState *cs, target_ulong address, + int rw, int mmu_idx) +{ + return 0; +} + +void tricore_cpu_do_interrupt(CPUState *cs) +{ +} + +TriCoreCPU *cpu_tricore_init(const char *cpu_model) +{ + return TRICORE_CPU(cpu_generic_init(TYPE_TRICORE_CPU, cpu_model)); +} + +static void tricore_cpu_list_entry(gpointer data, gpointer user_data) +{ + ObjectClass *oc = data; + CPUListState *s = user_data; + const char *typename; + char *name; + + typename = object_class_get_name(oc); + name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_TRICORE_CPU)); + (*s->cpu_fprintf)(s->file, " %s\n", + name); + g_free(name); +} + +void tricore_cpu_list(FILE *f, fprintf_function cpu_fprintf) +{ + CPUListState s = { + .file = f, + .cpu_fprintf = cpu_fprintf, + }; + GSList *list; + + list = object_class_get_list(TYPE_TRICORE_CPU, false); + (*cpu_fprintf)(f, "Available CPUs:\n"); + g_slist_foreach(list, tricore_cpu_list_entry, &s); + g_slist_free(list); +} + +uint32_t psw_read(CPUTriCoreState *env) +{ + /* clear all USB bits */ + env->PSW &= 0xffffff; + /* now set them from the cache */ + env->PSW |= ((env->PSW_USB_C != 0) << 31); + env->PSW |= ((env->PSW_USB_V & (1 << 31)) >> 1); + env->PSW |= ((env->PSW_USB_SV & (1 << 31)) >> 2); + env->PSW |= ((env->PSW_USB_AV & (1 << 31)) >> 3); + env->PSW |= ((env->PSW_USB_SAV & (1 << 31)) >> 4); + + return env->PSW; +} + +void psw_write(CPUTriCoreState *env, uint32_t val) +{ + env->PSW_USB_C = (val & MASK_USB_C); + env->PSW_USB_V = (val & MASK_USB_V << 1); + env->PSW_USB_SV = (val & MASK_USB_SV << 2); + env->PSW_USB_AV = ((val & MASK_USB_AV) << 3); + env->PSW_USB_SAV = ((val & MASK_USB_SAV) << 4); + env->PSW = val; +} diff --git a/target-tricore/helper.h b/target-tricore/helper.h new file mode 100644 index 0000000..e69de29 diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c new file mode 100644 index 0000000..275790b --- /dev/null +++ b/target-tricore/op_helper.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#include +#include "cpu.h" +#include "qemu/host-utils.h" +#include "exec/helper-proto.h" +#include "exec/cpu_ldst.h" + +void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx, + uintptr_t retaddr) +{ +} + diff --git a/target-tricore/translate.c b/target-tricore/translate.c new file mode 100644 index 0000000..fae1b1a --- /dev/null +++ b/target-tricore/translate.c @@ -0,0 +1,100 @@ +/* + * TriCore emulation for qemu: main translation routines. + * + * Copyright (c) 2013-2014 Bastian Koppelmann C-Lab/University Paderborn + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + + +#include "cpu.h" +#include "disas/disas.h" +#include "tcg-op.h" +#include "exec/cpu_ldst.h" + +#include "exec/helper-proto.h" +#include "exec/helper-gen.h" + + +static const char *regnames_a[] = { + "a0" , "a1" , "a2" , "a3" , "a4" , "a5" , + "a6" , "a7" , "a8" , "a9" , "sp" , "a11" , + "a12" , "a13" , "a14" , "a15", + }; + +static const char *regnames_d[] = { + "d0" , "d1" , "d2" , "d3" , "d4" , "d5" , + "d6" , "d7" , "d8" , "d9" , "d10" , "d11" , + "d12" , "d13" , "d14" , "d15", + }; + +void tricore_cpu_dump_state(CPUState *cs, FILE *f, + fprintf_function cpu_fprintf, int flags) +{ + TriCoreCPU *cpu = TRICORE_CPU(cs); + CPUTriCoreState *env = &cpu->env; + int i; + + cpu_fprintf(f, "PC=%08x\n", env->PC); + for (i = 0; i < 16; ++i) { + if ((i & 3) == 0) { + cpu_fprintf(f, "GPR A%02d:", i); + } + cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_a[i], env->gpr_a[i]); + } + for (i = 0; i < 16; ++i) { + if ((i & 3) == 0) { + cpu_fprintf(f, "GPR D%02d:", i); + } + cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_d[i], env->gpr_d[i]); + } + +} + +static inline void +gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb, + int search_pc) +{ +} + +void +gen_intermediate_code(CPUTriCoreState *env, struct TranslationBlock *tb) +{ + gen_intermediate_code_internal(tricore_env_get_cpu(env), tb, false); +} + +void +gen_intermediate_code_pc(CPUTriCoreState *env, struct TranslationBlock *tb) +{ + gen_intermediate_code_internal(tricore_env_get_cpu(env), tb, true); +} + +void +restore_state_to_opc(CPUTriCoreState *env, TranslationBlock *tb, int pc_pos) +{ + env->PC = tcg_ctx.gen_opc_pc[pc_pos]; +} +/* + * + * Initialization + * + */ + +void cpu_state_reset(CPUTriCoreState *env) +{ +} + +void tricore_tcg_init(void) +{ +} diff --git a/target-tricore/tricore-defs.h b/target-tricore/tricore-defs.h new file mode 100644 index 0000000..4350b03 --- /dev/null +++ b/target-tricore/tricore-defs.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#if !defined(__QEMU_TRICORE_DEFS_H__) +#define __QEMU_TRICORE_DEFS_H__ + +#define TARGET_PAGE_BITS 14 +#define TARGET_LONG_BITS 32 +#define TARGET_PHYS_ADDR_SPACE_BITS 32 +#define TARGET_VIRT_ADDR_SPACE_BITS 32 + +#define TRICORE_TLB_MAX 128 + +#endif /* __QEMU_TRICORE_DEFS_H__ */ -- 2.1.0