From patchwork Thu Feb 11 16:01:56 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Bastian Koppelmann X-Patchwork-Id: 8281991 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 42B6B9F38B for ; Thu, 11 Feb 2016 16:02:29 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5401A20120 for ; Thu, 11 Feb 2016 16:02:28 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9A8E9201EF for ; Thu, 11 Feb 2016 16:02:24 +0000 (UTC) Received: from localhost ([::1]:51230 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTthG-0002Bt-Sp for patchwork-qemu-devel@patchwork.kernel.org; Thu, 11 Feb 2016 11:02:22 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35417) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTth8-0002BQ-Bh for qemu-devel@nongnu.org; Thu, 11 Feb 2016 11:02:15 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aTth6-00086R-4b for qemu-devel@nongnu.org; Thu, 11 Feb 2016 11:02:14 -0500 Received: from mail.uni-paderborn.de ([131.234.142.9]:33705) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTth5-00084O-RT for qemu-devel@nongnu.org; Thu, 11 Feb 2016 11:02:12 -0500 From: Bastian Koppelmann To: qemu-devel@nongnu.org Date: Thu, 11 Feb 2016 17:01:56 +0100 Message-Id: <1455206520-6465-2-git-send-email-kbastian@mail.uni-paderborn.de> X-Mailer: git-send-email 2.7.1 In-Reply-To: <1455206520-6465-1-git-send-email-kbastian@mail.uni-paderborn.de> References: <1455206520-6465-1-git-send-email-kbastian@mail.uni-paderborn.de> MIME-Version: 1.0 X-IMT-Spam-Score: 0.0 () X-PMX-Version: 6.2.1.2493963, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2016.2.11.155416 X-IMT-Authenticated-Sender: uid=kbastian,ou=People,o=upb,c=de X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 131.234.142.9 Cc: rth@twiddle.net Subject: [Qemu-devel] [PATCH 1/5] target-tricore: Add trap handling X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add the infrastructure needed to generate and handle traps. Signed-off-by: Bastian Koppelmann --- target-tricore/cpu-qom.h | 2 +- target-tricore/cpu.c | 2 +- target-tricore/cpu.h | 1 + target-tricore/helper.c | 52 +++++++++++++++++++++++++++++++ target-tricore/helper.h | 3 ++ target-tricore/op_helper.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++ target-tricore/translate.c | 21 +++++++++++++ 7 files changed, 155 insertions(+), 2 deletions(-) diff --git a/target-tricore/cpu-qom.h b/target-tricore/cpu-qom.h index 66c9664..0909c0c 100644 --- a/target-tricore/cpu-qom.h +++ b/target-tricore/cpu-qom.h @@ -65,6 +65,6 @@ static inline TriCoreCPU *tricore_env_get_cpu(CPUTriCoreState *env) hwaddr tricore_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); void tricore_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf, int flags); - +void tricore_cpu_do_interrupt(CPUState *cs); #endif /*QEMU_TRICORE_CPU_QOM_H */ diff --git a/target-tricore/cpu.c b/target-tricore/cpu.c index f8b8518..01e39dc 100644 --- a/target-tricore/cpu.c +++ b/target-tricore/cpu.c @@ -166,7 +166,7 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data) 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; diff --git a/target-tricore/cpu.h b/target-tricore/cpu.h index 20a12f3..b4cc2ef 100644 --- a/target-tricore/cpu.h +++ b/target-tricore/cpu.h @@ -271,6 +271,7 @@ enum { TRAPC_ASSERT = 5, TRAPC_SYSCALL = 6, TRAPC_NMI = 7, + TRAPC_IRQ = 8 }; /* Class 0 TIN */ diff --git a/target-tricore/helper.c b/target-tricore/helper.c index a8fd418..d781f21 100644 --- a/target-tricore/helper.c +++ b/target-tricore/helper.c @@ -133,3 +133,55 @@ void psw_write(CPUTriCoreState *env, uint32_t val) env->PSW_USB_SAV = ((val & MASK_USB_SAV) << 4); env->PSW = val; } + +void tricore_cpu_do_interrupt(CPUState *cs) +{ + TriCoreCPU *cpu = TRICORE_CPU(cs); + CPUTriCoreState *env = &cpu->env; + + /* The stack pointer in A[10] is set to the Interrupt Stack Pointer (ISP) + when the processor was not previously using the interrupt stack + (in case of PSW.IS = 0). The stack pointer bit is set for using the + interrupt stack: PSW.IS = 1. */ + if ((env->PSW & MASK_PSW_IS) == 0) { + env->gpr_a[10] = env->ISP; + } + env->PSW |= MASK_PSW_IS; + /* The I/O mode is set to Supervisor mode, which means all permissions + are enabled: PSW.IO = 10 B .*/ + env->PSW |= (2 << 10); + + /*The current Protection Register Set is set to 0: PSW.PRS = 00 B .*/ + env->PSW &= ~(MASK_PSW_PRS); + + /* The Call Depth Counter (CDC) is cleared, and the call depth limit is + set for 64: PSW.CDC = 0000000 B .*/ + env->PSW &= ~(MASK_PSW_CDC); + + /* Call Depth Counter is enabled, PSW.CDE = 1. */ + env->PSW |= MASK_PSW_CDE; + + /* Write permission to global registers A[0], A[1], A[8], A[9] is + disabled: PSW.GW = 0. */ + env->PSW &= ~MASK_PSW_GW; + + /*The interrupt system is globally disabled: ICR.IE = 0. The ‘old’ + ICR.IE and ICR.CCPN are saved */ + + /* PCXI.PIE = ICR.IE */ + env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + + ((env->ICR & MASK_ICR_IE) << 15)); + /* PCXI.PCPN = ICR.CCPN */ + env->PCXI = (env->PCXI & 0xffffff) + + ((env->ICR & MASK_ICR_CCPN) << 24); + + if (cs->exception_index <= TRAPC_NMI) { + /* The trap vector table is accessed to fetch the first instruction of + the trap handler. */ + env->PC = env->BTV | (cs->exception_index << 5); + } else if (cs->exception_index == TRAPC_IRQ) { + /* The interrupt vector table is accessed to fetch the first instruction + of the interrupt handler. */ + env->PC = env->BIV | ((env->ICR & MASK_ICR_PIPN) >> 10); + } +} diff --git a/target-tricore/helper.h b/target-tricore/helper.h index cc221f1..5ae1125 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -132,6 +132,7 @@ DEF_HELPER_2(lducx, void, env, i32) DEF_HELPER_2(stlcx, void, env, i32) DEF_HELPER_2(stucx, void, env, i32) DEF_HELPER_1(svlcx, void, env) +DEF_HELPER_1(svucx, void, env) DEF_HELPER_1(rslcx, void, env) /* Address mode helper */ DEF_HELPER_1(br_update, i32, i32) @@ -139,3 +140,5 @@ DEF_HELPER_2(circ_update, i32, i32, i32) /* PSW cache helper */ DEF_HELPER_2(psw_write, void, env, i32) DEF_HELPER_1(psw_read, i32, env) +/* Exceptions */ +DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index 3aa6326..fbe2be0 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -21,6 +21,41 @@ #include "exec/cpu_ldst.h" #include /* for crc32 */ + +/* Exception helpers */ +void helper_raise_exception_err(CPUTriCoreState *env, uint32_t class, + int error_code) +{ + CPUState *cs = CPU(tricore_env_get_cpu(env)); + cs->exception_index = class; + env->error_code = error_code; + cpu_loop_exit(cs); +} + +static inline void generate_trap(CPUTriCoreState *env, uint32_t class, + uint32_t tin) +{ + CPUState *cs = CPU(tricore_env_get_cpu(env)); + + if ((class == TRAPC_CTX_MNG) && (tin == TIN3_FCU)) { + /* upper context cannot be saved, if the context list is empty */ + } else { + helper_svucx(env); + } + /* in order to allow the trap handlers for async traps to recognize when + when they have interrupted FCD trap handler FCDSF flag is set */ + if (class == TRAPC_CTX_MNG && tin == TIN3_FCD) { + env->SYSCON |= MASK_SYSCON_FCD_SF; + /* when we fault here, the return address is the start of the faulting + trap handler */ + env->gpr_a[11] = env->BTV | cs->exception_index << 5; + } else { + env->gpr_a[11] = env->PC; + } + env->gpr_a[15] = tin; + helper_raise_exception_err(env, class, 0); +} + /* Addressing mode helper */ static uint16_t reverse16(uint16_t val) @@ -2625,6 +2660,47 @@ void helper_svlcx(CPUTriCoreState *env) } } +void helper_svucx(CPUTriCoreState *env) +{ + target_ulong tmp_FCX; + target_ulong ea; + target_ulong new_FCX; + + if (env->FCX == 0) { + /* FCU trap */ + } + /* tmp_FCX = FCX; */ + tmp_FCX = env->FCX; + /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */ + ea = ((env->FCX & MASK_FCX_FCXS) << 12) + + ((env->FCX & MASK_FCX_FCXO) << 6); + /* new_FCX = M(EA, word); */ + new_FCX = cpu_ldl_data(env, ea); + /* M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], + A[12], A[13], A[14], A[15], D[12], D[13], D[14], + D[15]}; */ + save_context_upper(env, ea); + + /* PCXI.PCPN = ICR.CCPN; */ + env->PCXI = (env->PCXI & 0xffffff) + + ((env->ICR & MASK_ICR_CCPN) << 24); + /* PCXI.PIE = ICR.IE; */ + env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + + ((env->ICR & MASK_ICR_IE) << 15)); + /* PCXI.UL = 1; */ + env->PCXI |= MASK_PCXI_UL; + + /* PCXI[19: 0] = FCX[19: 0]; */ + env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); + /* FCX[19: 0] = new_FCX[19: 0]; */ + env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); + + /* if (tmp_FCX == LCX) trap(FCD);*/ + if (tmp_FCX == env->LCX) { + /* FCD trap */ + } +} + void helper_rslcx(CPUTriCoreState *env) { target_ulong ea; diff --git a/target-tricore/translate.c b/target-tricore/translate.c index a70fdf7..721878d 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -3244,6 +3244,27 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) } } +static inline void +generate_trap(DisasContext *ctx, int class, int tin) +{ + TCGv_i32 classtemp = tcg_const_i32(class); + gen_save_pc(ctx->pc); + /* upper context cannot be saved, if the context list is empty */ + if (class != TRAPC_SYSCALL) { + gen_helper_svucx(cpu_env); + } + /* Tin is loaded into d[15] */ + tcg_gen_movi_tl(cpu_gpr_d[15], tin); + /* The return address in A[11] is updated. */ + if (class == TRAPC_SYSCALL) { + tcg_gen_movi_tl(cpu_gpr_a[11], ctx->next_pc); + } else { + tcg_gen_movi_tl(cpu_gpr_a[11], ctx->pc); + } + gen_helper_raise_exception_err(cpu_env, classtemp, 0); + tcg_temp_free(classtemp); +} + static inline void gen_branch_cond(DisasContext *ctx, TCGCond cond, TCGv r1, TCGv r2, int16_t address) {