From patchwork Tue Jun 18 14:10:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117948 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45Sqrf1QYWz9sBr for ; Wed, 19 Jun 2019 00:16:34 +1000 (AEST) Received: from localhost ([::1]:58438 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEuW-0007Ei-59 for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:16:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60039) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEpl-0002sJ-HR for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpi-0007sG-SQ for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:36 -0400 Received: from mail01.asahi-net.or.jp ([202.224.55.13]:60231) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEpi-0007mA-6x for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:34 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail01.asahi-net.or.jp (Postfix) with ESMTPA id 6B497126D3E; Tue, 18 Jun 2019 23:11:28 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id BC98D240086; Tue, 18 Jun 2019 23:11:25 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:10:40 +0900 Message-Id: <20190618141118.52955-2-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.13 Subject: [Qemu-devel] [PATCH v21 01/21] MAINTAINERS: Add RX X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, richard.henderson@linaro.org, Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Yoshinori Sato Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20190607091116.49044-18-ysato@users.sourceforge.jp> Signed-off-by: Richard Henderson --- MAINTAINERS | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index d32c5c2313..cfe57ef11e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -273,6 +273,13 @@ F: include/hw/riscv/ F: linux-user/host/riscv32/ F: linux-user/host/riscv64/ +RENESAS RX CPUs +M: Yoshinori Sato +S: Maintained +F: target/rx/ +F: hw/rx/ +F: include/hw/rx/ + S390 TCG CPUs M: Richard Henderson M: David Hildenbrand @@ -1102,6 +1109,18 @@ F: pc-bios/canyonlands.dt[sb] F: pc-bios/u-boot-sam460ex-20100605.bin F: roms/u-boot-sam460ex +RX Machines +----------- +rx-virt +M: Yoshinori Sato +S: Maintained +F: hw/rx/rxqemu.c +F: hw/intc/rx_icu.c +F: hw/timer/renesas_*.c +F: hw/char/renesas_sci.c +F: include/hw/timer/renesas_*.h +F: include/hw/char/renesas_sci.h + SH4 Machines ------------ R2D From patchwork Tue Jun 18 14:10:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117949 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45Sqsz0PxHz9sBr for ; Wed, 19 Jun 2019 00:17:43 +1000 (AEST) Received: from localhost ([::1]:58446 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEvd-00087Z-4H for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:17:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60044) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEpl-0002sO-Ip for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpj-0007tB-Fa for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:37 -0400 Received: from mail01.asahi-net.or.jp ([202.224.55.13]:60241) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEpi-0007ma-TP for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:35 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail01.asahi-net.or.jp (Postfix) with ESMTPA id 4DA3D126D25; Tue, 18 Jun 2019 23:11:28 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 1B9C1240087; Tue, 18 Jun 2019 23:11:26 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:10:41 +0900 Message-Id: <20190618141118.52955-3-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.13 Subject: [Qemu-devel] [PATCH v21 02/21] qemu/bitops.h: Add extract8 and extract16 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, richard.henderson@linaro.org, Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Yoshinori Sato Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20190607091116.49044-10-ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- include/qemu/bitops.h | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h index 3f0926cf40..764f9d1ea0 100644 --- a/include/qemu/bitops.h +++ b/include/qemu/bitops.h @@ -301,6 +301,44 @@ static inline uint32_t extract32(uint32_t value, int start, int length) } /** + * extract8: + * @value: the value to extract the bit field from + * @start: the lowest bit in the bit field (numbered from 0) + * @length: the length of the bit field + * + * Extract from the 8 bit input @value the bit field specified by the + * @start and @length parameters, and return it. The bit field must + * lie entirely within the 8 bit word. It is valid to request that + * all 8 bits are returned (ie @length 8 and @start 0). + * + * Returns: the value of the bit field extracted from the input value. + */ +static inline uint8_t extract8(uint8_t value, int start, int length) +{ + assert(start >= 0 && length > 0 && length <= 8 - start); + return extract32(value, start, length); +} + +/** + * extract16: + * @value: the value to extract the bit field from + * @start: the lowest bit in the bit field (numbered from 0) + * @length: the length of the bit field + * + * Extract from the 16 bit input @value the bit field specified by the + * @start and @length parameters, and return it. The bit field must + * lie entirely within the 16 bit word. It is valid to request that + * all 16 bits are returned (ie @length 16 and @start 0). + * + * Returns: the value of the bit field extracted from the input value. + */ +static inline uint16_t extract16(uint16_t value, int start, int length) +{ + assert(start >= 0 && length > 0 && length <= 16 - start); + return extract32(value, start, length); +} + +/** * extract64: * @value: the value to extract the bit field from * @start: the lowest bit in the bit field (numbered from 0) From patchwork Tue Jun 18 14:10:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117981 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45SrNt5wbJz9sBp for ; Wed, 19 Jun 2019 00:41:02 +1000 (AEST) Received: from localhost ([::1]:58596 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdFIC-0002xl-TT for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:41:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60236) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEq1-0002zJ-G1 for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpk-0007v0-Nt for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:47 -0400 Received: from mail01.asahi-net.or.jp ([202.224.55.13]:60227) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEpi-0007m1-T6 for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:35 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail01.asahi-net.or.jp (Postfix) with ESMTPA id 1DBE2126D55; Tue, 18 Jun 2019 23:11:29 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 239C824008A; Tue, 18 Jun 2019 23:11:27 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:10:44 +0900 Message-Id: <20190618141118.52955-6-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.13 Subject: [Qemu-devel] [PATCH v21 03/21] target/rx: TCG helper X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, richard.henderson@linaro.org, Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" v21 changes Use cpu_env Signed-off-by: Yoshinori Sato Message-Id: <20190616142836.10614-3-ysato@users.sourceforge.jp> Reviewed-by: Richard Henderson Message-Id: <20190607091116.49044-3-ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson [PMD: Removed tlb_fill, extracted from patch of Yoshinori Sato 'Convert to CPUClass::tlb_fill'] Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Yoshinori Sato --- target/rx/helper.h | 31 ++++ target/rx/helper.c | 148 ++++++++++++++++ target/rx/op_helper.c | 470 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 649 insertions(+) create mode 100644 target/rx/helper.h create mode 100644 target/rx/helper.c create mode 100644 target/rx/op_helper.c diff --git a/target/rx/helper.h b/target/rx/helper.h new file mode 100644 index 0000000000..f0b7ebbbf7 --- /dev/null +++ b/target/rx/helper.h @@ -0,0 +1,31 @@ +DEF_HELPER_1(raise_illegal_instruction, noreturn, env) +DEF_HELPER_1(raise_access_fault, noreturn, env) +DEF_HELPER_1(raise_privilege_violation, noreturn, env) +DEF_HELPER_1(wait, noreturn, env) +DEF_HELPER_1(debug, noreturn, env) +DEF_HELPER_2(rxint, noreturn, env, i32) +DEF_HELPER_1(rxbrk, noreturn, env) +DEF_HELPER_FLAGS_3(fadd, TCG_CALL_NO_WG, f32, env, f32, f32) +DEF_HELPER_FLAGS_3(fsub, TCG_CALL_NO_WG, f32, env, f32, f32) +DEF_HELPER_FLAGS_3(fmul, TCG_CALL_NO_WG, f32, env, f32, f32) +DEF_HELPER_FLAGS_3(fdiv, TCG_CALL_NO_WG, f32, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_WG, void, env, f32, f32) +DEF_HELPER_FLAGS_2(ftoi, TCG_CALL_NO_WG, i32, env, f32) +DEF_HELPER_FLAGS_2(round, TCG_CALL_NO_WG, i32, env, f32) +DEF_HELPER_FLAGS_2(itof, TCG_CALL_NO_WG, f32, env, i32) +DEF_HELPER_2(set_fpsw, void, env, i32) +DEF_HELPER_FLAGS_2(racw, TCG_CALL_NO_WG, void, env, i32) +DEF_HELPER_FLAGS_2(set_psw_rte, TCG_CALL_NO_WG, void, env, i32) +DEF_HELPER_FLAGS_2(set_psw, TCG_CALL_NO_WG, void, env, i32) +DEF_HELPER_1(pack_psw, i32, env) +DEF_HELPER_FLAGS_3(div, TCG_CALL_NO_WG, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(divu, TCG_CALL_NO_WG, i32, env, i32, i32) +DEF_HELPER_FLAGS_1(scmpu, TCG_CALL_NO_WG, void, env) +DEF_HELPER_1(smovu, void, env) +DEF_HELPER_1(smovf, void, env) +DEF_HELPER_1(smovb, void, env) +DEF_HELPER_2(sstr, void, env, i32) +DEF_HELPER_FLAGS_2(swhile, TCG_CALL_NO_WG, void, env, i32) +DEF_HELPER_FLAGS_2(suntil, TCG_CALL_NO_WG, void, env, i32) +DEF_HELPER_FLAGS_2(rmpa, TCG_CALL_NO_WG, void, env, i32) +DEF_HELPER_1(satr, void, env) diff --git a/target/rx/helper.c b/target/rx/helper.c new file mode 100644 index 0000000000..1dae74eae7 --- /dev/null +++ b/target/rx/helper.c @@ -0,0 +1,148 @@ +/* + * RX emulation + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/bitops.h" +#include "cpu.h" +#include "exec/log.h" +#include "exec/cpu_ldst.h" +#include "sysemu/sysemu.h" + +void rx_cpu_unpack_psw(CPURXState *env, uint32_t psw, int rte) +{ + if (env->psw_pm == 0) { + env->psw_ipl = FIELD_EX32(psw, PSW, IPL); + if (rte) { + /* PSW.PM can write RTE and RTFI */ + env->psw_pm = FIELD_EX32(psw, PSW, PM); + } + env->psw_u = FIELD_EX32(psw, PSW, U); + env->psw_i = FIELD_EX32(psw, PSW, I); + } + env->psw_o = FIELD_EX32(psw, PSW, O) << 31; + env->psw_s = FIELD_EX32(psw, PSW, S) << 31; + env->psw_z = 1 - FIELD_EX32(psw, PSW, Z); + env->psw_c = FIELD_EX32(psw, PSW, C); +} + +#define INT_FLAGS (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIR) +void rx_cpu_do_interrupt(CPUState *cs) +{ + RXCPU *cpu = RXCPU(cs); + CPURXState *env = &cpu->env; + int do_irq = cs->interrupt_request & INT_FLAGS; + uint32_t save_psw; + + env->in_sleep = 0; + + if (env->psw_u) { + env->usp = env->regs[0]; + } else { + env->isp = env->regs[0]; + } + save_psw = rx_cpu_pack_psw(env); + env->psw_pm = env->psw_i = env->psw_u = 0; + + if (do_irq) { + if (do_irq & CPU_INTERRUPT_FIR) { + env->bpc = env->pc; + env->bpsw = save_psw; + env->pc = env->fintv; + env->psw_ipl = 15; + cs->interrupt_request &= ~CPU_INTERRUPT_FIR; + qemu_set_irq(env->ack, env->ack_irq); + qemu_log_mask(CPU_LOG_INT, "fast interrupt raised\n"); + } else if (do_irq & CPU_INTERRUPT_HARD) { + env->isp -= 4; + cpu_stl_all(env, env->isp, save_psw); + env->isp -= 4; + cpu_stl_all(env, env->isp, env->pc); + env->pc = cpu_ldl_all(env, env->intb + env->ack_irq * 4); + env->psw_ipl = env->ack_ipl; + cs->interrupt_request &= ~CPU_INTERRUPT_HARD; + qemu_set_irq(env->ack, env->ack_irq); + qemu_log_mask(CPU_LOG_INT, + "interrupt 0x%02x raised\n", env->ack_irq); + } + } else { + uint32_t vec = cs->exception_index; + const char *expname = "unknown exception"; + + env->isp -= 4; + cpu_stl_all(env, env->isp, save_psw); + env->isp -= 4; + cpu_stl_all(env, env->isp, env->pc); + + if (vec < 0x100) { + env->pc = cpu_ldl_all(env, 0xffffffc0 + vec * 4); + } else { + env->pc = cpu_ldl_all(env, env->intb + (vec & 0xff) * 4); + } + switch (vec) { + case 20: + expname = "privilege violation"; + break; + case 21: + expname = "access exception"; + break; + case 23: + expname = "illegal instruction"; + break; + case 25: + expname = "fpu exception"; + break; + case 30: + expname = "non-maskable interrupt"; + break; + case 0x100 ... 0x1ff: + expname = "unconditional trap"; + } + qemu_log_mask(CPU_LOG_INT, "exception 0x%02x [%s] raised\n", + (vec & 0xff), expname); + } + env->regs[0] = env->isp; +} + +bool rx_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +{ + RXCPU *cpu = RXCPU(cs); + CPURXState *env = &cpu->env; + int accept = 0; + /* hardware interrupt (Normal) */ + if ((interrupt_request & CPU_INTERRUPT_HARD) && + env->psw_i && (env->psw_ipl < env->req_ipl)) { + env->ack_irq = env->req_irq; + env->ack_ipl = env->req_ipl; + accept = 1; + } + /* hardware interrupt (FIR) */ + if ((interrupt_request & CPU_INTERRUPT_FIR) && + env->psw_i && (env->psw_ipl < 15)) { + accept = 1; + } + if (accept) { + rx_cpu_do_interrupt(cs); + return true; + } + return false; +} + +hwaddr rx_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) +{ + return addr; +} diff --git a/target/rx/op_helper.c b/target/rx/op_helper.c new file mode 100644 index 0000000000..f89d294f2b --- /dev/null +++ b/target/rx/op_helper.c @@ -0,0 +1,470 @@ +/* + * RX helper functions + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/bitops.h" +#include "cpu.h" +#include "exec/exec-all.h" +#include "exec/helper-proto.h" +#include "exec/cpu_ldst.h" +#include "fpu/softfloat.h" + +static inline void QEMU_NORETURN raise_exception(CPURXState *env, int index, + uintptr_t retaddr); + +static void _set_psw(CPURXState *env, uint32_t psw, uint32_t rte) +{ + uint32_t prev_u; + prev_u = env->psw_u; + rx_cpu_unpack_psw(env, psw, rte); + if (prev_u != env->psw_u) { + /* switch r0 */ + if (env->psw_u) { + env->isp = env->regs[0]; + env->regs[0] = env->usp; + } else { + env->usp = env->regs[0]; + env->regs[0] = env->isp; + } + } +} + +void helper_set_psw(CPURXState *env, uint32_t psw) +{ + _set_psw(env, psw, 0); +} + +void helper_set_psw_rte(CPURXState *env, uint32_t psw) +{ + _set_psw(env, psw, 1); +} + +uint32_t helper_pack_psw(CPURXState *env) +{ + return rx_cpu_pack_psw(env); +} + +#define SET_FPSW(b) \ + do { \ + env->fpsw = FIELD_DP32(env->fpsw, FPSW, C ## b, 1); \ + if (!FIELD_EX32(env->fpsw, FPSW, E ## b)) { \ + env->fpsw = FIELD_DP32(env->fpsw, FPSW, F ## b, 1); \ + } \ + } while (0) + +/* fp operations */ +static void update_fpsw(CPURXState *env, float32 ret, uintptr_t retaddr) +{ + int xcpt, cause, enable; + + env->psw_z = ret & ~(1 << 31); /* mask sign bit */ + env->psw_s = ret; + + xcpt = get_float_exception_flags(&env->fp_status); + + /* Clear the cause entries */ + env->fpsw = FIELD_DP32(env->fpsw, FPSW, CAUSE, 0); + + /* set FPSW */ + if (unlikely(xcpt)) { + if (xcpt & float_flag_invalid) { + SET_FPSW(V); + } + if (xcpt & float_flag_divbyzero) { + SET_FPSW(Z); + } + if (xcpt & float_flag_overflow) { + SET_FPSW(O); + } + if (xcpt & float_flag_underflow) { + SET_FPSW(U); + } + if (xcpt & float_flag_inexact) { + SET_FPSW(X); + } + if ((xcpt & (float_flag_input_denormal + | float_flag_output_denormal)) + && !FIELD_EX32(env->fpsw, FPSW, DN)) { + env->fpsw = FIELD_DP32(env->fpsw, FPSW, CE, 1); + } + + /* update FPSW_FLAG_S */ + if (FIELD_EX32(env->fpsw, FPSW, FLAGS) != 0) { + env->fpsw = FIELD_DP32(env->fpsw, FPSW, FS, 1); + } + + /* Generate an exception if enabled */ + cause = FIELD_EX32(env->fpsw, FPSW, CAUSE); + enable = FIELD_EX32(env->fpsw, FPSW, ENABLE); + enable |= 1 << 5; /* CE always enabled */ + if (cause & enable) { + raise_exception(env, 21, retaddr); + } + } +} + +void helper_set_fpsw(CPURXState *env, uint32_t val) +{ + static const int roundmode[] = { + float_round_nearest_even, + float_round_to_zero, + float_round_up, + float_round_down, + }; + uint32_t fpsw = env->fpsw; + fpsw |= 0x7fffff03; + val &= ~0x80000000; + fpsw &= val; + FIELD_DP32(fpsw, FPSW, FS, FIELD_EX32(fpsw, FPSW, FLAGS) != 0); + env->fpsw = fpsw; + set_float_rounding_mode(roundmode[FIELD_EX32(env->fpsw, FPSW, RM)], + &env->fp_status); +} + +#define FLOATOP(op, func) \ + float32 helper_##op(CPURXState *env, float32 t0, float32 t1) \ + { \ + float32 ret; \ + ret = func(t0, t1, &env->fp_status); \ + update_fpsw(env, *(uint32_t *)&ret, GETPC()); \ + return ret; \ + } + +FLOATOP(fadd, float32_add) +FLOATOP(fsub, float32_sub) +FLOATOP(fmul, float32_mul) +FLOATOP(fdiv, float32_div) + +void helper_fcmp(CPURXState *env, float32 t0, float32 t1) +{ + int st; + st = float32_compare(t0, t1, &env->fp_status); + update_fpsw(env, 0, GETPC()); + env->psw_z = 1; + env->psw_s = env->psw_o = 0; + switch (st) { + case float_relation_equal: + env->psw_z = 0; + break; + case float_relation_less: + env->psw_s = -1; + break; + case float_relation_unordered: + env->psw_o = -1; + break; + } +} + +uint32_t helper_ftoi(CPURXState *env, float32 t0) +{ + uint32_t ret; + ret = float32_to_int32_round_to_zero(t0, &env->fp_status); + update_fpsw(env, ret, GETPC()); + return ret; +} + +uint32_t helper_round(CPURXState *env, float32 t0) +{ + uint32_t ret; + ret = float32_to_int32(t0, &env->fp_status); + update_fpsw(env, ret, GETPC()); + return ret; +} + +float32 helper_itof(CPURXState *env, uint32_t t0) +{ + float32 ret; + ret = int32_to_float32(t0, &env->fp_status); + update_fpsw(env, ret, GETPC()); + return ret; +} + +/* string operations */ +void helper_scmpu(CPURXState *env) +{ + uint8_t tmp0, tmp1; + if (env->regs[3] == 0) { + return; + } + while (env->regs[3] != 0) { + tmp0 = cpu_ldub_data_ra(env, env->regs[1]++, GETPC()); + tmp1 = cpu_ldub_data_ra(env, env->regs[2]++, GETPC()); + env->regs[3]--; + if (tmp0 != tmp1 || tmp0 == '\0') { + break; + } + } + env->psw_z = tmp0 - tmp1; + env->psw_c = (tmp0 >= tmp1); +} + +static uint32_t (* const cpu_ldufn[])(CPUArchState *env, + target_ulong ptr, + uintptr_t retaddr) = { + cpu_ldub_data_ra, cpu_lduw_data_ra, cpu_ldl_data_ra, +}; + +static uint32_t (* const cpu_ldfn[])(CPUArchState *env, + target_ulong ptr, + uintptr_t retaddr) = { + cpu_ldub_data_ra, cpu_lduw_data_ra, cpu_ldl_data_ra, +}; + +static void (* const cpu_stfn[])(CPUArchState *env, + target_ulong ptr, + uint32_t val, + uintptr_t retaddr) = { + cpu_stb_data_ra, cpu_stw_data_ra, cpu_stl_data_ra, +}; + +void helper_sstr(CPURXState *env, uint32_t sz) +{ + tcg_debug_assert(sz < 3); + while (env->regs[3] != 0) { + cpu_stfn[sz](env, env->regs[1], env->regs[2], GETPC()); + env->regs[1] += 1 << sz; + env->regs[3]--; + } +} + +#define OP_SMOVU 1 +#define OP_SMOVF 0 +#define OP_SMOVB 2 + +static void smov(uint32_t mode, CPURXState *env) +{ + uint8_t tmp; + int dir; + + dir = (mode & OP_SMOVB) ? -1 : 1; + while (env->regs[3] != 0) { + tmp = cpu_ldub_data_ra(env, env->regs[2], GETPC()); + cpu_stb_data_ra(env, env->regs[1], tmp, GETPC()); + env->regs[1] += dir; + env->regs[2] += dir; + env->regs[3]--; + if ((mode & OP_SMOVU) && tmp == 0) { + break; + } + } +} + +void helper_smovu(CPURXState *env) +{ + smov(OP_SMOVU, env); +} + +void helper_smovf(CPURXState *env) +{ + smov(OP_SMOVF, env); +} + +void helper_smovb(CPURXState *env) +{ + smov(OP_SMOVB, env); +} + + +void helper_suntil(CPURXState *env, uint32_t sz) +{ + uint32_t tmp; + tcg_debug_assert(sz < 3); + if (env->regs[3] == 0) { + return ; + } + while (env->regs[3] != 0) { + tmp = cpu_ldufn[sz](env, env->regs[1], GETPC()); + env->regs[1] += 1 << sz; + env->regs[3]--; + if (tmp == env->regs[2]) { + break; + } + } + env->psw_z = tmp - env->regs[2]; + env->psw_c = (tmp <= env->regs[2]); +} + +void helper_swhile(CPURXState *env, uint32_t sz) +{ + uint32_t tmp; + tcg_debug_assert(sz < 3); + if (env->regs[3] == 0) { + return ; + } + while (env->regs[3] != 0) { + tmp = cpu_ldufn[sz](env, env->regs[1], GETPC()); + env->regs[1] += 1 << sz; + env->regs[3]--; + if (tmp != env->regs[2]) { + break; + } + } + env->psw_z = env->regs[3]; + env->psw_c = (tmp <= env->regs[2]); +} + +/* accumlator operations */ +void helper_rmpa(CPURXState *env, uint32_t sz) +{ + uint64_t result_l, prev; + int32_t result_h; + int64_t tmp0, tmp1; + + if (env->regs[3] == 0) { + return; + } + result_l = env->regs[5]; + result_l <<= 32; + result_l |= env->regs[4]; + result_h = env->regs[6]; + env->psw_o = 0; + + while (env->regs[3] != 0) { + tmp0 = cpu_ldfn[sz](env, env->regs[1], GETPC()); + tmp1 = cpu_ldfn[sz](env, env->regs[2], GETPC()); + tmp0 *= tmp1; + prev = result_l; + result_l += tmp0; + /* carry / bollow */ + if (tmp0 < 0) { + if (prev > result_l) { + result_h--; + } + } else { + if (prev < result_l) { + result_h++; + } + } + + env->regs[1] += 1 << sz; + env->regs[2] += 1 << sz; + } + env->psw_s = result_h; + env->psw_o = (result_h != 0 && result_h != -1) << 31; + env->regs[6] = result_h; + env->regs[5] = result_l >> 32; + env->regs[4] = result_l & 0xffffffff; +} + +void helper_racw(CPURXState *env, uint32_t imm) +{ + int64_t acc; + acc = env->acc; + acc <<= (imm + 1); + acc += 0x0000000080000000LL; + if (acc > 0x00007fff00000000LL) { + acc = 0x00007fff00000000LL; + } else if (acc < -0x800000000000LL) { + acc = -0x800000000000LL; + } else { + acc &= 0xffffffff00000000LL; + } + env->acc = acc; +} + +void helper_satr(CPURXState *env) +{ + if (env->psw_o >> 31) { + if ((int)env->psw_s < 0) { + env->regs[6] = 0x00000000; + env->regs[5] = 0x7fffffff; + env->regs[4] = 0xffffffff; + } else { + env->regs[6] = 0xffffffff; + env->regs[5] = 0x80000000; + env->regs[4] = 0x00000000; + } + } +} + +/* div */ +uint32_t helper_div(CPURXState *env, uint32_t num, uint32_t den) +{ + uint32_t ret = num; + if (!((num == INT_MIN && den == -1) || den == 0)) { + ret = (int32_t)num / (int32_t)den; + env->psw_o = 0; + } else { + env->psw_o = -1; + } + return ret; +} + +uint32_t helper_divu(CPURXState *env, uint32_t num, uint32_t den) +{ + uint32_t ret = num; + if (den != 0) { + ret = num / den; + env->psw_o = 0; + } else { + env->psw_o = -1; + } + return ret; +} + +/* exception */ +static inline void QEMU_NORETURN raise_exception(CPURXState *env, int index, + uintptr_t retaddr) +{ + CPUState *cs = env_cpu(env); + + cs->exception_index = index; + cpu_loop_exit_restore(cs, retaddr); +} + +void QEMU_NORETURN helper_raise_privilege_violation(CPURXState *env) +{ + raise_exception(env, 20, GETPC()); +} + +void QEMU_NORETURN helper_raise_access_fault(CPURXState *env) +{ + raise_exception(env, 21, GETPC()); +} + +void QEMU_NORETURN helper_raise_illegal_instruction(CPURXState *env) +{ + raise_exception(env, 23, GETPC()); +} + +void QEMU_NORETURN helper_wait(CPURXState *env) +{ + CPUState *cs = env_cpu(env); + + cs->halted = 1; + env->in_sleep = 1; + raise_exception(env, EXCP_HLT, 0); +} + +void QEMU_NORETURN helper_debug(CPURXState *env) +{ + CPUState *cs = env_cpu(env); + + cs->exception_index = EXCP_DEBUG; + cpu_loop_exit(cs); +} + +void QEMU_NORETURN helper_rxint(CPURXState *env, uint32_t vec) +{ + raise_exception(env, 0x100 + vec, 0); +} + +void QEMU_NORETURN helper_rxbrk(CPURXState *env) +{ + raise_exception(env, 0x100, 0); +} From patchwork Tue Jun 18 14:10:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117947 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45Sqph5PfTz9s3l for ; Wed, 19 Jun 2019 00:14:52 +1000 (AEST) Received: from localhost ([::1]:58422 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEss-00052i-QR for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:14:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60173) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEpu-0002wF-1Z for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpi-0007rP-B0 for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:42 -0400 Received: from mail02.asahi-net.or.jp ([202.224.55.14]:34994) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEph-0007mD-Hu for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:34 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail02.asahi-net.or.jp (Postfix) with ESMTPA id 1BE8943D7A; Tue, 18 Jun 2019 23:11:29 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 74D6324008B; Tue, 18 Jun 2019 23:11:27 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:10:45 +0900 Message-Id: <20190618141118.52955-7-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.14 Subject: [Qemu-devel] [PATCH v21 04/21] target/rx: CPU definition X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, richard.henderson@linaro.org, Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" v21 changes Add cpu-param.h Remove CPU_COMMON rx_load_image move to rx-virt. Signed-off-by: Yoshinori Sato Message-Id: <20190616142836.10614-4-ysato@users.sourceforge.jp> Reviewed-by: Richard Henderson Message-Id: <20190607091116.49044-4-ysato@users.sourceforge.jp> Signed-off-by: Richard Henderson [PMD: Use newer QOM style, split cpu-qom.h, restrict access to extable array, use rx_cpu_tlb_fill() extracted from patch of Yoshinori Sato 'Convert to CPUClass::tlb_fill'] Signed-off-by: Philippe Mathieu-Daudé cpu.c: remove rx_load_image Signed-off-by: Yoshinori Sato --- target/rx/cpu-param.h | 31 ++++++++ target/rx/cpu-qom.h | 42 ++++++++++ target/rx/cpu.h | 182 ++++++++++++++++++++++++++++++++++++++++++ target/rx/cpu.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++ target/rx/gdbstub.c | 112 ++++++++++++++++++++++++++ target/rx/monitor.c | 38 +++++++++ 6 files changed, 622 insertions(+) create mode 100644 target/rx/cpu-param.h create mode 100644 target/rx/cpu-qom.h create mode 100644 target/rx/cpu.h create mode 100644 target/rx/cpu.c create mode 100644 target/rx/gdbstub.c create mode 100644 target/rx/monitor.c diff --git a/target/rx/cpu-param.h b/target/rx/cpu-param.h new file mode 100644 index 0000000000..5da87fbebe --- /dev/null +++ b/target/rx/cpu-param.h @@ -0,0 +1,31 @@ +/* + * RX cpu parameters + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef RX_CPU_PARAM_H +#define RX_CPU_PARAM_H + +#define TARGET_LONG_BITS 32 +#define TARGET_PAGE_BITS 12 + +#define TARGET_PHYS_ADDR_SPACE_BITS 32 +#define TARGET_VIRT_ADDR_SPACE_BITS 32 + +#define NB_MMU_MODES 1 +#define MMU_MODE0_SUFFIX _all + +#endif diff --git a/target/rx/cpu-qom.h b/target/rx/cpu-qom.h new file mode 100644 index 0000000000..4ae3b38b3e --- /dev/null +++ b/target/rx/cpu-qom.h @@ -0,0 +1,42 @@ +#ifndef QEMU_SUPERH_CPU_QOM_H +#define QEMU_SUPERH_CPU_QOM_H + +#include "qom/cpu.h" +/* + * RX CPU + * + * Copyright (c) 2019 Yoshinori Sato + * SPDX-License-Identifier: LGPL-2.0+ + */ + +#define TYPE_RX_CPU "rx-cpu" + +#define TYPE_RX62N_CPU RX_CPU_TYPE_NAME("rx62n") + +#define RXCPU_CLASS(klass) \ + OBJECT_CLASS_CHECK(RXCPUClass, (klass), TYPE_RX_CPU) +#define RXCPU(obj) \ + OBJECT_CHECK(RXCPU, (obj), TYPE_RX_CPU) +#define RXCPU_GET_CLASS(obj) \ + OBJECT_GET_CLASS(RXCPUClass, (obj), TYPE_RX_CPU) + +/* + * RXCPUClass: + * @parent_realize: The parent class' realize handler. + * @parent_reset: The parent class' reset handler. + * + * A RX CPU model. + */ +typedef struct RXCPUClass { + /*< private >*/ + CPUClass parent_class; + /*< public >*/ + + DeviceRealize parent_realize; + void (*parent_reset)(CPUState *cpu); + +} RXCPUClass; + +#define CPUArchState struct CPURXState + +#endif diff --git a/target/rx/cpu.h b/target/rx/cpu.h new file mode 100644 index 0000000000..3f9c4fdd25 --- /dev/null +++ b/target/rx/cpu.h @@ -0,0 +1,182 @@ +/* + * RX emulation definition + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef RX_CPU_H +#define RX_CPU_H + +#include "qemu/bitops.h" +#include "qemu-common.h" +#include "hw/registerfields.h" +#include "cpu-qom.h" +#include "qom/cpu.h" + +#include "exec/cpu-defs.h" + +/* PSW define */ +REG32(PSW, 0) +FIELD(PSW, C, 0, 1) +FIELD(PSW, Z, 1, 1) +FIELD(PSW, S, 2, 1) +FIELD(PSW, O, 3, 1) +FIELD(PSW, I, 16, 1) +FIELD(PSW, U, 17, 1) +FIELD(PSW, PM, 20, 1) +FIELD(PSW, IPL, 24, 4) + +/* FPSW define */ +REG32(FPSW, 0) +FIELD(FPSW, RM, 0, 2) +FIELD(FPSW, CV, 2, 1) +FIELD(FPSW, CO, 3, 1) +FIELD(FPSW, CZ, 4, 1) +FIELD(FPSW, CU, 5, 1) +FIELD(FPSW, CX, 6, 1) +FIELD(FPSW, CE, 7, 1) +FIELD(FPSW, CAUSE, 2, 6) +FIELD(FPSW, DN, 8, 1) +FIELD(FPSW, EV, 10, 1) +FIELD(FPSW, EO, 11, 1) +FIELD(FPSW, EZ, 12, 1) +FIELD(FPSW, EU, 13, 1) +FIELD(FPSW, EX, 14, 1) +FIELD(FPSW, ENABLE, 10, 5) +FIELD(FPSW, FV, 26, 1) +FIELD(FPSW, FO, 27, 1) +FIELD(FPSW, FZ, 28, 1) +FIELD(FPSW, FU, 29, 1) +FIELD(FPSW, FX, 30, 1) +FIELD(FPSW, FLAGS, 26, 4) +FIELD(FPSW, FS, 31, 1) + +enum { + NUM_REGS = 16, +}; + +typedef struct CPURXState { + /* CPU registers */ + uint32_t regs[NUM_REGS]; /* general registers */ + uint32_t psw_o; /* O bit of status register */ + uint32_t psw_s; /* S bit of status register */ + uint32_t psw_z; /* Z bit of status register */ + uint32_t psw_c; /* C bit of status register */ + uint32_t psw_u; + uint32_t psw_i; + uint32_t psw_pm; + uint32_t psw_ipl; + uint32_t bpsw; /* backup status */ + uint32_t bpc; /* backup pc */ + uint32_t isp; /* global base register */ + uint32_t usp; /* vector base register */ + uint32_t pc; /* program counter */ + uint32_t intb; /* interrupt vector */ + uint32_t fintv; + uint32_t fpsw; + uint64_t acc; + + /* Fields up to this point are cleared by a CPU reset */ + struct {} end_reset_fields; + + /* Internal use */ + uint32_t in_sleep; + uint32_t req_irq; /* Requested interrupt no (hard) */ + uint32_t req_ipl; /* Requested interrupt level */ + uint32_t ack_irq; /* execute irq */ + uint32_t ack_ipl; /* execute ipl */ + float_status fp_status; + qemu_irq ack; /* Interrupt acknowledge */ +} CPURXState; + +/* + * RXCPU: + * @env: #CPURXState + * + * A RX CPU + */ +struct RXCPU { + /*< private >*/ + CPUState parent_obj; + /*< public >*/ + + CPUNegativeOffsetState neg; + CPURXState env; +}; + +typedef struct RXCPU RXCPU; +typedef RXCPU ArchCPU; + +#define ENV_OFFSET offsetof(RXCPU, env) + +#define RX_CPU_TYPE_SUFFIX "-" TYPE_RX_CPU +#define RX_CPU_TYPE_NAME(model) model RX_CPU_TYPE_SUFFIX +#define CPU_RESOLVING_TYPE TYPE_RX_CPU + +extern const char rx_crname[][6]; + +void rx_cpu_do_interrupt(CPUState *cpu); +bool rx_cpu_exec_interrupt(CPUState *cpu, int int_req); +void rx_cpu_dump_state(CPUState *cpu, FILE *f, int flags); +int rx_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); +int rx_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); +hwaddr rx_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); + +void rx_translate_init(void); +int cpu_rx_signal_handler(int host_signum, void *pinfo, + void *puc); + +void rx_cpu_list(void); +void rx_cpu_unpack_psw(CPURXState *env, uint32_t psw, int rte); + +#define cpu_signal_handler cpu_rx_signal_handler +#define cpu_list rx_cpu_list + +#include "exec/cpu-all.h" + +#define CPU_INTERRUPT_SOFT CPU_INTERRUPT_TGT_INT_0 +#define CPU_INTERRUPT_FIR CPU_INTERRUPT_TGT_INT_1 + +#define RX_CPU_IRQ 0 +#define RX_CPU_FIR 1 + +static inline void cpu_get_tb_cpu_state(CPURXState *env, target_ulong *pc, + target_ulong *cs_base, uint32_t *flags) +{ + *pc = env->pc; + *cs_base = 0; + *flags = FIELD_DP32(0, PSW, PM, env->psw_pm); +} + +static inline int cpu_mmu_index(CPURXState *env, bool ifetch) +{ + return 0; +} + +static inline uint32_t rx_cpu_pack_psw(CPURXState *env) +{ + uint32_t psw = 0; + psw = FIELD_DP32(psw, PSW, IPL, env->psw_ipl); + psw = FIELD_DP32(psw, PSW, PM, env->psw_pm); + psw = FIELD_DP32(psw, PSW, U, env->psw_u); + psw = FIELD_DP32(psw, PSW, I, env->psw_i); + psw = FIELD_DP32(psw, PSW, O, env->psw_o >> 31); + psw = FIELD_DP32(psw, PSW, S, env->psw_s >> 31); + psw = FIELD_DP32(psw, PSW, Z, env->psw_z == 0); + psw = FIELD_DP32(psw, PSW, C, env->psw_c); + return psw; +} + +#endif /* RX_CPU_H */ diff --git a/target/rx/cpu.c b/target/rx/cpu.c new file mode 100644 index 0000000000..ea38639f47 --- /dev/null +++ b/target/rx/cpu.c @@ -0,0 +1,217 @@ +/* + * QEMU RX CPU + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/qemu-print.h" +#include "qapi/error.h" +#include "cpu.h" +#include "qemu-common.h" +#include "migration/vmstate.h" +#include "exec/exec-all.h" +#include "hw/loader.h" +#include "fpu/softfloat.h" + +static void rx_cpu_set_pc(CPUState *cs, vaddr value) +{ + RXCPU *cpu = RXCPU(cs); + + cpu->env.pc = value; +} + +static void rx_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) +{ + RXCPU *cpu = RXCPU(cs); + + cpu->env.pc = tb->pc; +} + +static bool rx_cpu_has_work(CPUState *cs) +{ + return cs->interrupt_request & + (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIR); +} + +static void rx_cpu_reset(CPUState *s) +{ + RXCPU *cpu = RXCPU(s); + RXCPUClass *rcc = RXCPU_GET_CLASS(cpu); + CPURXState *env = &cpu->env; + uint32_t *resetvec; + + rcc->parent_reset(s); + + memset(env, 0, offsetof(CPURXState, end_reset_fields)); + + resetvec = rom_ptr(0xfffffffc, 4); + if (resetvec) { + /* In the case of kernel, it is ignored because it is not set. */ + env->pc = ldl_p(resetvec); + } + rx_cpu_unpack_psw(env, 0, 1); + env->regs[0] = env->isp = env->usp = 0; + env->fpsw = 0; + set_flush_to_zero(1, &env->fp_status); + set_flush_inputs_to_zero(1, &env->fp_status); +} + +static void rx_cpu_list_entry(gpointer data, gpointer user_data) +{ + const char *typename = object_class_get_name(OBJECT_CLASS(data)); + + qemu_printf("%s\n", typename); +} + +void rx_cpu_list(void) +{ + GSList *list; + list = object_class_get_list_sorted(TYPE_RX_CPU, false); + g_slist_foreach(list, rx_cpu_list_entry, NULL); + g_slist_free(list); +} + +static ObjectClass *rx_cpu_class_by_name(const char *cpu_model) +{ + ObjectClass *oc; + + oc = object_class_by_name(cpu_model); + if (object_class_dynamic_cast(oc, TYPE_RX_CPU) == NULL || + object_class_is_abstract(oc)) { + oc = NULL; + } + + return oc; +} + +static void rx_cpu_realize(DeviceState *dev, Error **errp) +{ + CPUState *cs = CPU(dev); + RXCPUClass *rcc = RXCPU_GET_CLASS(dev); + Error *local_err = NULL; + + cpu_exec_realizefn(cs, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } + + cpu_reset(cs); + qemu_init_vcpu(cs); + + rcc->parent_realize(dev, errp); +} + +static void rx_cpu_set_irq(void *opaque, int no, int request) +{ + RXCPU *cpu = opaque; + CPUState *cs = CPU(cpu); + int irq = request & 0xff; + + static const int mask[] = { + [RX_CPU_IRQ] = CPU_INTERRUPT_HARD, + [RX_CPU_FIR] = CPU_INTERRUPT_FIR, + }; + if (irq) { + cpu->env.req_irq = irq; + cpu->env.req_ipl = (request >> 8) & 0x0f; + cpu_interrupt(cs, mask[no]); + } else { + cpu_reset_interrupt(cs, mask[no]); + } +} + +static void rx_cpu_disas_set_info(CPUState *cpu, disassemble_info *info) +{ + info->mach = bfd_mach_rx; + info->print_insn = print_insn_rx; +} + +static bool rx_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) +{ + uint32_t address, physical, prot; + + /* Linear mapping */ + address = physical = addr & TARGET_PAGE_MASK; + prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE); + return true; +} + +static void rx_cpu_init(Object *obj) +{ + CPUState *cs = CPU(obj); + RXCPU *cpu = RXCPU(obj); + CPURXState *env = &cpu->env; + + cpu_set_cpustate_pointers(cpu); + cs->env_ptr = env; + qdev_init_gpio_in(DEVICE(cpu), rx_cpu_set_irq, 2); +} + +static void rx_cpu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + CPUClass *cc = CPU_CLASS(klass); + RXCPUClass *rcc = RXCPU_CLASS(klass); + + device_class_set_parent_realize(dc, rx_cpu_realize, + &rcc->parent_realize); + + rcc->parent_reset = cc->reset; + cc->reset = rx_cpu_reset; + + cc->class_by_name = rx_cpu_class_by_name; + cc->has_work = rx_cpu_has_work; + cc->do_interrupt = rx_cpu_do_interrupt; + cc->cpu_exec_interrupt = rx_cpu_exec_interrupt; + cc->dump_state = rx_cpu_dump_state; + cc->set_pc = rx_cpu_set_pc; + cc->synchronize_from_tb = rx_cpu_synchronize_from_tb; + cc->gdb_read_register = rx_cpu_gdb_read_register; + cc->gdb_write_register = rx_cpu_gdb_write_register; + cc->get_phys_page_debug = rx_cpu_get_phys_page_debug; + cc->disas_set_info = rx_cpu_disas_set_info; + cc->tcg_initialize = rx_translate_init; + cc->tlb_fill = rx_cpu_tlb_fill; + + cc->gdb_num_core_regs = 26; +} + +static const TypeInfo rx_cpu_info = { + .name = TYPE_RX_CPU, + .parent = TYPE_CPU, + .instance_size = sizeof(RXCPU), + .instance_init = rx_cpu_init, + .abstract = true, + .class_size = sizeof(RXCPUClass), + .class_init = rx_cpu_class_init, +}; + +static const TypeInfo rx62n_rx_cpu_info = { + .name = TYPE_RX62N_CPU, + .parent = TYPE_RX_CPU, +}; + +static void rx_cpu_register_types(void) +{ + type_register_static(&rx_cpu_info); + type_register_static(&rx62n_rx_cpu_info); +} + +type_init(rx_cpu_register_types) diff --git a/target/rx/gdbstub.c b/target/rx/gdbstub.c new file mode 100644 index 0000000000..d76ca52e82 --- /dev/null +++ b/target/rx/gdbstub.c @@ -0,0 +1,112 @@ +/* + * RX gdb server stub + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" +#include "exec/gdbstub.h" + +int rx_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) +{ + RXCPU *cpu = RXCPU(cs); + CPURXState *env = &cpu->env; + + switch (n) { + case 0 ... 15: + return gdb_get_regl(mem_buf, env->regs[n]); + case 16: + return gdb_get_regl(mem_buf, (env->psw_u) ? env->regs[0] : env->usp); + case 17: + return gdb_get_regl(mem_buf, (!env->psw_u) ? env->regs[0] : env->isp); + case 18: + return gdb_get_regl(mem_buf, rx_cpu_pack_psw(env)); + case 19: + return gdb_get_regl(mem_buf, env->pc); + case 20: + return gdb_get_regl(mem_buf, env->intb); + case 21: + return gdb_get_regl(mem_buf, env->bpsw); + case 22: + return gdb_get_regl(mem_buf, env->bpc); + case 23: + return gdb_get_regl(mem_buf, env->fintv); + case 24: + return gdb_get_regl(mem_buf, env->fpsw); + case 25: + return 0; + } + return 0; +} + +int rx_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) +{ + RXCPU *cpu = RXCPU(cs); + CPURXState *env = &cpu->env; + uint32_t psw; + switch (n) { + case 0 ... 15: + env->regs[n] = ldl_p(mem_buf); + if (n == 0) { + if (env->psw_u) { + env->usp = env->regs[0]; + } else { + env->isp = env->regs[0]; + } + } + break; + case 16: + env->usp = ldl_p(mem_buf); + if (env->psw_u) { + env->regs[0] = ldl_p(mem_buf); + } + break; + case 17: + env->isp = ldl_p(mem_buf); + if (!env->psw_u) { + env->regs[0] = ldl_p(mem_buf); + } + break; + case 18: + psw = ldl_p(mem_buf); + rx_cpu_unpack_psw(env, psw, 1); + break; + case 19: + env->pc = ldl_p(mem_buf); + break; + case 20: + env->intb = ldl_p(mem_buf); + break; + case 21: + env->bpsw = ldl_p(mem_buf); + break; + case 22: + env->bpc = ldl_p(mem_buf); + break; + case 23: + env->fintv = ldl_p(mem_buf); + break; + case 24: + env->fpsw = ldl_p(mem_buf); + break; + case 25: + return 8; + default: + return 0; + } + + return 4; +} diff --git a/target/rx/monitor.c b/target/rx/monitor.c new file mode 100644 index 0000000000..5d7a1e58b5 --- /dev/null +++ b/target/rx/monitor.c @@ -0,0 +1,38 @@ +/* + * QEMU monitor + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "cpu.h" +#include "monitor/monitor.h" +#include "monitor/hmp-target.h" +#include "hmp.h" + +void hmp_info_tlb(Monitor *mon, const QDict *qdict) +{ + CPUArchState *env = mon_get_cpu_env(); + + if (!env) { + monitor_printf(mon, "No CPU available\n"); + return; + } +} From patchwork Tue Jun 18 14:10:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117955 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45SqyV5fH1z9sBp for ; Wed, 19 Jun 2019 00:21:38 +1000 (AEST) Received: from localhost ([::1]:58478 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEzQ-0003aT-R0 for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:21:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60171) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEpu-0002wE-0v for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpk-0007uH-5j for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:42 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:57036) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEpi-0007mn-PT for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:35 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id 550DA4A1A2; Tue, 18 Jun 2019 23:11:29 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 42A8D24008F; Tue, 18 Jun 2019 23:11:28 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:10:47 +0900 Message-Id: <20190618141118.52955-9-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.15 Subject: [Qemu-devel] [PATCH v21 05/21] target/rx: RX disassembler X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, richard.henderson@linaro.org, Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Yoshinori Sato Reviewed-by: Richard Henderson Tested-by: Philippe Mathieu-Daudé Message-Id: <20190607091116.49044-5-ysato@users.sourceforge.jp> Signed-off-by: Richard Henderson --- include/disas/dis-asm.h | 5 + target/rx/disas.c | 1480 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1485 insertions(+) create mode 100644 target/rx/disas.c diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h index e9c7dd8eb4..a900bd0a27 100644 --- a/include/disas/dis-asm.h +++ b/include/disas/dis-asm.h @@ -226,6 +226,10 @@ enum bfd_architecture #define bfd_mach_nios2r2 2 bfd_arch_lm32, /* Lattice Mico32 */ #define bfd_mach_lm32 1 + bfd_arch_rx, /* Renesas RX */ +#define bfd_mach_rx 0x75 +#define bfd_mach_rx_v2 0x76 +#define bfd_mach_rx_v3 0x77 bfd_arch_last }; #define bfd_mach_s390_31 31 @@ -433,6 +437,7 @@ int print_insn_little_nios2 (bfd_vma, disassemble_info*); int print_insn_xtensa (bfd_vma, disassemble_info*); int print_insn_riscv32 (bfd_vma, disassemble_info*); int print_insn_riscv64 (bfd_vma, disassemble_info*); +int print_insn_rx(bfd_vma, disassemble_info *); #if 0 /* Fetch the disassembler for a given BFD, if that support is available. */ diff --git a/target/rx/disas.c b/target/rx/disas.c new file mode 100644 index 0000000000..8cada4825d --- /dev/null +++ b/target/rx/disas.c @@ -0,0 +1,1480 @@ +/* + * Renesas RX Disassembler + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "disas/dis-asm.h" +#include "qemu/bitops.h" +#include "cpu.h" + +typedef struct DisasContext { + disassemble_info *dis; + uint32_t addr; + uint32_t pc; +} DisasContext; + + +static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn, + int i, int n) +{ + bfd_byte buf; + while (++i <= n) { + ctx->dis->read_memory_func(ctx->addr++, &buf, 1, ctx->dis); + insn |= buf << (32 - i * 8); + } + return insn; +} + +static int32_t li(DisasContext *ctx, int sz) +{ + int32_t addr; + bfd_byte buf[4]; + addr = ctx->addr; + + switch (sz) { + case 1: + ctx->addr += 1; + ctx->dis->read_memory_func(addr, buf, 1, ctx->dis); + return (int8_t)buf[0]; + case 2: + ctx->addr += 2; + ctx->dis->read_memory_func(addr, buf, 2, ctx->dis); + return ldsw_le_p(buf); + case 3: + ctx->addr += 3; + ctx->dis->read_memory_func(addr, buf, 3, ctx->dis); + return (int8_t)buf[2] << 16 | lduw_le_p(buf); + case 0: + ctx->addr += 4; + ctx->dis->read_memory_func(addr, buf, 4, ctx->dis); + return ldl_le_p(buf); + default: + g_assert_not_reached(); + } +} + +static int bdsp_s(DisasContext *ctx, int d) +{ + /* + * 0 -> 8 + * 1 -> 9 + * 2 -> 10 + * 3 -> 3 + * : + * 7 -> 7 + */ + if (d < 3) { + d += 8; + } + return d; +} + +/* Include the auto-generated decoder. */ +#include "decode.inc.c" + +#define prt(...) (ctx->dis->fprintf_func)((ctx->dis->stream), __VA_ARGS__) + +#define RX_MEMORY_BYTE 0 +#define RX_MEMORY_WORD 1 +#define RX_MEMORY_LONG 2 + +#define RX_IM_BYTE 0 +#define RX_IM_WORD 1 +#define RX_IM_LONG 2 +#define RX_IM_UWORD 3 + +static const char size[] = {'b', 'w', 'l'}; +static const char cond[][4] = { + "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n", + "ge", "lt", "gt", "le", "o", "no", "ra", "f" +}; +static const char psw[] = { + 'c', 'z', 's', 'o', 0, 0, 0, 0, + 'i', 'u', 0, 0, 0, 0, 0, 0, +}; + +static uint32_t rx_index_addr(int ld, int size, DisasContext *ctx) +{ + bfd_byte buf[2]; + switch (ld) { + case 0: + return 0; + case 1: + ctx->dis->read_memory_func(ctx->addr, buf, 1, ctx->dis); + ctx->addr += 1; + return ((uint8_t)buf[0]) << size; + case 2: + ctx->dis->read_memory_func(ctx->addr, buf, 2, ctx->dis); + ctx->addr += 2; + return lduw_le_p(buf) << size; + } + g_assert_not_reached(); +} + +static void operand(DisasContext *ctx, int ld, int mi, int rs, int rd) +{ + int dsp; + static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"}; + if (ld < 3) { + switch (mi) { + case 4: + /* dsp[rs].ub */ + dsp = rx_index_addr(ld, RX_MEMORY_BYTE, ctx); + break; + case 3: + /* dsp[rs].uw */ + dsp = rx_index_addr(ld, RX_MEMORY_WORD, ctx); + break; + default: + /* dsp[rs].b */ + /* dsp[rs].w */ + /* dsp[rs].l */ + dsp = rx_index_addr(ld, mi, ctx); + break; + } + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d]%s", rs, sizes[mi]); + } else { + prt("r%d", rs); + } + prt(", r%d", rd); +} + +static void prt_ir(DisasContext *ctx, const char *insn, int imm, int rd) +{ + if (imm < 0x100) { + prt("%s\t#%d, r%d", insn, imm, rd); + } else { + prt("%s\t#0x%08x, r%d", insn, imm, rd); + } +} + +/* mov.[bwl] rs,dsp:[rd] */ +static bool trans_MOV_rm(DisasContext *ctx, arg_MOV_rm *a) +{ + if (a->dsp > 0) { + prt("mov.%c\tr%d,%d[r%d]", + size[a->sz], a->rs, a->dsp << a->sz, a->rd); + } else { + prt("mov.%c\tr%d,[r%d]", + size[a->sz], a->rs, a->rd); + } + return true; +} + +/* mov.[bwl] dsp:[rs],rd */ +static bool trans_MOV_mr(DisasContext *ctx, arg_MOV_mr *a) +{ + if (a->dsp > 0) { + prt("mov.%c\t%d[r%d], r%d", + size[a->sz], a->dsp << a->sz, a->rs, a->rd); + } else { + prt("mov.%c\t[r%d], r%d", + size[a->sz], a->rs, a->rd); + } + return true; +} + +/* mov.l #uimm4,rd */ +/* mov.l #uimm8,rd */ +/* mov.l #imm,rd */ +static bool trans_MOV_ir(DisasContext *ctx, arg_MOV_ir *a) +{ + prt_ir(ctx, "mov.l", a->imm, a->rd); + return true; +} + +/* mov.[bwl] #uimm8,dsp:[rd] */ +/* mov #imm, dsp:[rd] */ +static bool trans_MOV_im(DisasContext *ctx, arg_MOV_im *a) +{ + if (a->dsp > 0) { + prt("mov.%c\t#%d,%d[r%d]", + size[a->sz], a->imm, a->dsp << a->sz, a->rd); + } else { + prt("mov.%c\t#%d,[r%d]", + size[a->sz], a->imm, a->rd); + } + return true; +} + +/* mov.[bwl] [ri,rb],rd */ +static bool trans_MOV_ar(DisasContext *ctx, arg_MOV_ar *a) +{ + prt("mov.%c\t[r%d,r%d], r%d", size[a->sz], a->ri, a->rb, a->rd); + return true; +} + +/* mov.[bwl] rd,[ri,rb] */ +static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a) +{ + prt("mov.%c\tr%d, [r%d, r%d]", size[a->sz], a->rs, a->ri, a->rb); + return true; +} + + +/* mov.[bwl] dsp:[rs],dsp:[rd] */ +/* mov.[bwl] rs,dsp:[rd] */ +/* mov.[bwl] dsp:[rs],rd */ +/* mov.[bwl] rs,rd */ +static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a) +{ + int dsp; + + prt("mov.%c\t", size[a->sz]); + if (a->lds == 3 && a->ldd == 3) { + /* mov.[bwl] rs,rd */ + prt("r%d, r%d", a->rs, a->rd); + return true; + } + if (a->lds == 3) { + prt("r%d, ", a->rd); + dsp = rx_index_addr(a->ldd, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d]", a->rs); + } else if (a->ldd == 3) { + dsp = rx_index_addr(a->lds, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d], r%d", a->rs, a->rd); + } else { + dsp = rx_index_addr(a->lds, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d], ", a->rs); + dsp = rx_index_addr(a->ldd, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d]", a->rd); + } + return true; +} + +/* mov.[bwl] rs,[rd+] */ +/* mov.[bwl] rs,[-rd] */ +static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a) +{ + prt("mov.%c\tr%d, ", size[a->sz], a->rs); + prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd); + return true; +} + +/* mov.[bwl] [rd+],rs */ +/* mov.[bwl] [-rd],rs */ +static bool trans_MOV_pr(DisasContext *ctx, arg_MOV_pr *a) +{ + prt("mov.%c\t", size[a->sz]); + prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd); + prt(", r%d", a->rs); + return true; +} + +/* movu.[bw] dsp5:[rs],rd */ +static bool trans_MOVU_mr(DisasContext *ctx, arg_MOVU_mr *a) +{ + if (a->dsp > 0) { + prt("movu.%c\t%d[r%d], r%d", size[a->sz], + a->dsp << a->sz, a->rs, a->rd); + } else { + prt("movu.%c\t[r%d], r%d", size[a->sz], a->rs, a->rd); + } + return true; +} + +/* movu.[bw] rs,rd */ +static bool trans_MOVU_rr(DisasContext *ctx, arg_MOVU_rr *a) +{ + prt("movu.%c\tr%d, r%d", size[a->sz], a->rs, a->rd); + return true; +} + +/* movu.[bw] [ri,rb],rd */ +static bool trans_MOVU_ar(DisasContext *ctx, arg_MOVU_ar *a) +{ + prt("mov.%c\t[r%d,r%d], r%d", size[a->sz], a->ri, a->rb, a->rd); + return true; +} + +/* movu.[bw] [rs+],rd */ +/* movu.[bw] [-rs],rd */ +static bool trans_MOVU_pr(DisasContext *ctx, arg_MOVU_pr *a) +{ + prt("movu.%c\t", size[a->sz]); + prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd); + prt(", r%d", a->rs); + return true; +} + +/* pop rd */ +static bool trans_POP(DisasContext *ctx, arg_POP *a) +{ + prt("pop\tr%d", a->rd); + return true; +} + +/* popc rx */ +static bool trans_POPC(DisasContext *ctx, arg_POPC *a) +{ + prt("pop\tr%s", rx_crname[a->cr]); + return true; +} + +/* popm rd-rd2 */ +static bool trans_POPM(DisasContext *ctx, arg_POPM *a) +{ + prt("popm\tr%d-r%d", a->rd, a->rd2); + return true; +} + +/* push rs */ +static bool trans_PUSH_r(DisasContext *ctx, arg_PUSH_r *a) +{ + prt("push\tr%d", a->rs); + return true; +} + +/* push dsp[rs] */ +static bool trans_PUSH_m(DisasContext *ctx, arg_PUSH_m *a) +{ + prt("push\t"); + int dsp = rx_index_addr(a->ld, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d]", a->rs); + return true; +} + +/* pushc rx */ +static bool trans_PUSHC(DisasContext *ctx, arg_PUSHC *a) +{ + prt("push\t%s", rx_crname[a->cr]); + return true; +} + +/* pushm rs-rs2*/ +static bool trans_PUSHM(DisasContext *ctx, arg_PUSHM *a) +{ + prt("pushm\tr%d-r%d", a->rs, a->rs2); + return true; +} + +/* xchg rs,rd */ +static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr *a) +{ + prt("xchg\tr%d, r%d", a->rs, a->rd); + return true; +} +/* xchg dsp[rs].,rd */ +static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a) +{ + int dsp; + static const char msize[][4] = { + "b", "w", "l", "ub", "uw", + }; + + prt("xchg\t"); + dsp = rx_index_addr(a->ld, a->mi, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d].%s, r%d", a->rs, msize[a->mi], a->rd); + return true; +} + +/* stz #imm,rd */ +static bool trans_STZ(DisasContext *ctx, arg_STZ *a) +{ + prt_ir(ctx, "stz", a->imm, a->rd); + return true; +} + +/* stnz #imm,rd */ +static bool trans_STNZ(DisasContext *ctx, arg_STNZ *a) +{ + prt_ir(ctx, "stnz", a->imm, a->rd); + return true; +} + +/* rtsd #imm */ +static bool trans_RTSD_i(DisasContext *ctx, arg_RTSD_i *a) +{ + prt("rtsd\t#%d", a->imm << 2); + return true; +} + +/* rtsd #imm, rd-rd2 */ +static bool trans_RTSD_irr(DisasContext *ctx, arg_RTSD_irr *a) +{ + prt("rtsd\t#%d, r%d - r%d", a->imm << 2, a->rd, a->rd2); + return true; +} + +/* and #uimm:4, rd */ +/* and #imm, rd */ +static bool trans_AND_ir(DisasContext *ctx, arg_AND_ir *a) +{ + prt_ir(ctx, "and", a->imm, a->rd); + return true; +} + +/* and dsp[rs], rd */ +/* and rs,rd */ +static bool trans_AND_mr(DisasContext *ctx, arg_AND_mr *a) +{ + prt("and\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* and rs,rs2,rd */ +static bool trans_AND_rrr(DisasContext *ctx, arg_AND_rrr *a) +{ + prt("and\tr%d,r%d, r%d", a->rs, a->rs2, a->rd); + return true; +} + +/* or #uimm:4, rd */ +/* or #imm, rd */ +static bool trans_OR_ir(DisasContext *ctx, arg_OR_ir *a) +{ + prt_ir(ctx, "or", a->imm, a->rd); + return true; +} + +/* or dsp[rs], rd */ +/* or rs,rd */ +static bool trans_OR_mr(DisasContext *ctx, arg_OR_mr *a) +{ + prt("or\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* or rs,rs2,rd */ +static bool trans_OR_rrr(DisasContext *ctx, arg_OR_rrr *a) +{ + prt("or\tr%d, r%d, r%d", a->rs, a->rs2, a->rd); + return true; +} + +/* xor #imm, rd */ +static bool trans_XOR_ir(DisasContext *ctx, arg_XOR_ir *a) +{ + prt_ir(ctx, "xor", a->imm, a->rd); + return true; +} + +/* xor dsp[rs], rd */ +/* xor rs,rd */ +static bool trans_XOR_mr(DisasContext *ctx, arg_XOR_mr *a) +{ + prt("xor\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* tst #imm, rd */ +static bool trans_TST_ir(DisasContext *ctx, arg_TST_ir *a) +{ + prt_ir(ctx, "tst", a->imm, a->rd); + return true; +} + +/* tst dsp[rs], rd */ +/* tst rs, rd */ +static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *a) +{ + prt("tst\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* not rd */ +/* not rs, rd */ +static bool trans_NOT_rr(DisasContext *ctx, arg_NOT_rr *a) +{ + prt("not\t"); + if (a->rs != a->rd) { + prt("r%d, ", a->rs); + } + prt("r%d", a->rd); + return true; +} + +/* neg rd */ +/* neg rs, rd */ +static bool trans_NEG_rr(DisasContext *ctx, arg_NEG_rr *a) +{ + prt("neg\t"); + if (a->rs != a->rd) { + prt("r%d, ", a->rs); + } + prt("r%d", a->rd); + return true; +} + +/* adc #imm, rd */ +static bool trans_ADC_ir(DisasContext *ctx, arg_ADC_ir *a) +{ + prt_ir(ctx, "adc", a->imm, a->rd); + return true; +} + +/* adc rs, rd */ +static bool trans_ADC_rr(DisasContext *ctx, arg_ADC_rr *a) +{ + prt("adc\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* adc dsp[rs], rd */ +static bool trans_ADC_mr(DisasContext *ctx, arg_ADC_mr *a) +{ + int dsp; + prt("adc\t"); + dsp = rx_index_addr(a->ld, 2, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d], r%d", a->rs, a->rd); + return true; +} + +/* add #uimm4, rd */ +/* add #imm, rs, rd */ +static bool trans_ADD_irr(DisasContext *ctx, arg_ADD_irr *a) +{ + if (a->imm < 0x10 && a->rs2 == a->rd) { + prt("add\t#%d, r%d", a->imm, a->rd); + } else { + prt("add\t#0x%08x, r%d, r%d", a->imm, a->rs2, a->rd); + } + return true; +} + +/* add rs, rd */ +/* add dsp[rs], rd */ +static bool trans_ADD_mr(DisasContext *ctx, arg_ADD_mr *a) +{ + prt("add\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* add rs, rs2, rd */ +static bool trans_ADD_rrr(DisasContext *ctx, arg_ADD_rrr *a) +{ + prt("add\tr%d, r%d, r%d", a->rs, a->rs2, a->rd); + return true; +} + +/* cmp #imm4, rd */ +/* cmp #imm8, rd */ +/* cmp #imm, rs2 */ +static bool trans_CMP_ir(DisasContext *ctx, arg_CMP_ir *a) +{ + prt_ir(ctx, "cmp", a->imm, a->rs2); + return true; +} + +/* cmp rs, rs2 */ +/* cmp dsp[rs], rs2 */ +static bool trans_CMP_mr(DisasContext *ctx, arg_CMP_mr *a) +{ + prt("cmp\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* sub #imm4, rd */ +static bool trans_SUB_ir(DisasContext *ctx, arg_SUB_ir *a) +{ + prt("sub\t#%d, r%d", a->imm, a->rd); + return true; +} + +/* sub rs, rd */ +/* sub dsp[rs], rd */ +static bool trans_SUB_mr(DisasContext *ctx, arg_SUB_mr *a) +{ + prt("sub\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* sub rs, rs2, rd */ +static bool trans_SUB_rrr(DisasContext *ctx, arg_SUB_rrr *a) +{ + prt("sub\tr%d, r%d, r%d", a->rs, a->rs2, a->rd); + return true; +} + +/* sbb rs, rd */ +static bool trans_SBB_rr(DisasContext *ctx, arg_SBB_rr *a) +{ + prt("sbb\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* sbb dsp[rs], rd */ +static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a) +{ + prt("sbb\t"); + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + return true; +} + +/* abs rd */ +/* abs rs, rd */ +static bool trans_ABS_rr(DisasContext *ctx, arg_ABS_rr *a) +{ + prt("abs\t"); + if (a->rs == a->rd) { + prt("r%d", a->rd); + } else { + prt("r%d, r%d", a->rs, a->rd); + } + return true; +} + +/* max #imm, rd */ +static bool trans_MAX_ir(DisasContext *ctx, arg_MAX_ir *a) +{ + prt_ir(ctx, "max", a->imm, a->rd); + return true; +} + +/* max rs, rd */ +/* max dsp[rs], rd */ +static bool trans_MAX_mr(DisasContext *ctx, arg_MAX_mr *a) +{ + prt("max\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* min #imm, rd */ +static bool trans_MIN_ir(DisasContext *ctx, arg_MIN_ir *a) +{ + prt_ir(ctx, "min", a->imm, a->rd); + return true; +} + +/* min rs, rd */ +/* min dsp[rs], rd */ +static bool trans_MIN_mr(DisasContext *ctx, arg_MIN_mr *a) +{ + prt("max\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* mul #uimm4, rd */ +/* mul #imm, rd */ +static bool trans_MUL_ir(DisasContext *ctx, arg_MUL_ir *a) +{ + prt_ir(ctx, "mul", a->imm, a->rd); + return true; +} + +/* mul rs, rd */ +/* mul dsp[rs], rd */ +static bool trans_MUL_mr(DisasContext *ctx, arg_MUL_mr *a) +{ + prt("mul\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* mul rs, rs2, rd */ +static bool trans_MUL_rrr(DisasContext *ctx, arg_MUL_rrr *a) +{ + prt("mul\tr%d,r%d,r%d", a->rs, a->rs2, a->rd); + return true; +} + +/* emul #imm, rd */ +static bool trans_EMUL_ir(DisasContext *ctx, arg_EMUL_ir *a) +{ + prt_ir(ctx, "emul", a->imm, a->rd); + return true; +} + +/* emul rs, rd */ +/* emul dsp[rs], rd */ +static bool trans_EMUL_mr(DisasContext *ctx, arg_EMUL_mr *a) +{ + prt("emul\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* emulu #imm, rd */ +static bool trans_EMULU_ir(DisasContext *ctx, arg_EMULU_ir *a) +{ + prt_ir(ctx, "emulu", a->imm, a->rd); + return true; +} + +/* emulu rs, rd */ +/* emulu dsp[rs], rd */ +static bool trans_EMULU_mr(DisasContext *ctx, arg_EMULU_mr *a) +{ + prt("emulu\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* div #imm, rd */ +static bool trans_DIV_ir(DisasContext *ctx, arg_DIV_ir *a) +{ + prt_ir(ctx, "div", a->imm, a->rd); + return true; +} + +/* div rs, rd */ +/* div dsp[rs], rd */ +static bool trans_DIV_mr(DisasContext *ctx, arg_DIV_mr *a) +{ + prt("div\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* divu #imm, rd */ +static bool trans_DIVU_ir(DisasContext *ctx, arg_DIVU_ir *a) +{ + prt_ir(ctx, "divu", a->imm, a->rd); + return true; +} + +/* divu rs, rd */ +/* divu dsp[rs], rd */ +static bool trans_DIVU_mr(DisasContext *ctx, arg_DIVU_mr *a) +{ + prt("divu\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + + +/* shll #imm:5, rd */ +/* shll #imm:5, rs, rd */ +static bool trans_SHLL_irr(DisasContext *ctx, arg_SHLL_irr *a) +{ + prt("shll\t#%d, ", a->imm); + if (a->rs2 != a->rd) { + prt("r%d, ", a->rs2); + } + prt("r%d", a->rd); + return true; +} + +/* shll rs, rd */ +static bool trans_SHLL_rr(DisasContext *ctx, arg_SHLL_rr *a) +{ + prt("shll\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* shar #imm:5, rd */ +/* shar #imm:5, rs, rd */ +static bool trans_SHAR_irr(DisasContext *ctx, arg_SHAR_irr *a) +{ + prt("shar\t#%d,", a->imm); + if (a->rs2 != a->rd) { + prt("r%d, ", a->rs2); + } + prt("r%d", a->rd); + return true; +} + +/* shar rs, rd */ +static bool trans_SHAR_rr(DisasContext *ctx, arg_SHAR_rr *a) +{ + prt("shar\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* shlr #imm:5, rd */ +/* shlr #imm:5, rs, rd */ +static bool trans_SHLR_irr(DisasContext *ctx, arg_SHLR_irr *a) +{ + prt("shlr\t#%d, ", a->imm); + if (a->rs2 != a->rd) { + prt("r%d, ", a->rs2); + } + prt("r%d", a->rd); + return true; +} + +/* shlr rs, rd */ +static bool trans_SHLR_rr(DisasContext *ctx, arg_SHLR_rr *a) +{ + prt("shlr\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* rolc rd */ +static bool trans_ROLC(DisasContext *ctx, arg_ROLC *a) +{ + prt("rorc\tr%d", a->rd); + return true; +} + +/* rorc rd */ +static bool trans_RORC(DisasContext *ctx, arg_RORC *a) +{ + prt("rorc\tr%d", a->rd); + return true; +} + +/* rotl #imm, rd */ +static bool trans_ROTL_ir(DisasContext *ctx, arg_ROTL_ir *a) +{ + prt("rotl\t#%d, r%d", a->imm, a->rd); + return true; +} + +/* rotl rs, rd */ +static bool trans_ROTL_rr(DisasContext *ctx, arg_ROTL_rr *a) +{ + prt("rotl\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* rotr #imm, rd */ +static bool trans_ROTR_ir(DisasContext *ctx, arg_ROTR_ir *a) +{ + prt("rotr\t#%d, r%d", a->imm, a->rd); + return true; +} + +/* rotr rs, rd */ +static bool trans_ROTR_rr(DisasContext *ctx, arg_ROTR_rr *a) +{ + prt("rotr\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* revl rs, rd */ +static bool trans_REVL(DisasContext *ctx, arg_REVL *a) +{ + prt("revl\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* revw rs, rd */ +static bool trans_REVW(DisasContext *ctx, arg_REVW *a) +{ + prt("revw\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* conditional branch helper */ +static void rx_bcnd_main(DisasContext *ctx, int cd, int len, int dst) +{ + static const char sz[] = {'s', 'b', 'w', 'a'}; + prt("b%s.%c\t%08x", cond[cd], sz[len - 1], ctx->pc + dst); +} + +/* beq dsp:3 / bne dsp:3 */ +/* beq dsp:8 / bne dsp:8 */ +/* bc dsp:8 / bnc dsp:8 */ +/* bgtu dsp:8 / bleu dsp:8 */ +/* bpz dsp:8 / bn dsp:8 */ +/* bge dsp:8 / blt dsp:8 */ +/* bgt dsp:8 / ble dsp:8 */ +/* bo dsp:8 / bno dsp:8 */ +/* beq dsp:16 / bne dsp:16 */ +static bool trans_BCnd(DisasContext *ctx, arg_BCnd *a) +{ + rx_bcnd_main(ctx, a->cd, a->sz, a->dsp); + return true; +} + +/* bra dsp:3 */ +/* bra dsp:8 */ +/* bra dsp:16 */ +/* bra dsp:24 */ +static bool trans_BRA(DisasContext *ctx, arg_BRA *a) +{ + rx_bcnd_main(ctx, 14, a->sz, a->dsp); + return true; +} + +/* bra rs */ +static bool trans_BRA_l(DisasContext *ctx, arg_BRA_l *a) +{ + prt("bra.l\tr%d", a->rd); + return true; +} + +/* jmp rs */ +static bool trans_JMP(DisasContext *ctx, arg_JMP *a) +{ + prt("jmp\tr%d", a->rs); + return true; +} + +/* jsr rs */ +static bool trans_JSR(DisasContext *ctx, arg_JSR *a) +{ + prt("jsr\tr%d", a->rs); + return true; +} + +/* bsr dsp:16 */ +/* bsr dsp:24 */ +static bool trans_BSR(DisasContext *ctx, arg_BSR *a) +{ + static const char sz[] = {'w', 'a'}; + prt("bsr.%c\t%08x", sz[a->sz - 3], ctx->pc + a->dsp); + return true; +} + +/* bsr rs */ +static bool trans_BSR_l(DisasContext *ctx, arg_BSR_l *a) +{ + prt("bsr.l\tr%d", a->rd); + return true; +} + +/* rts */ +static bool trans_RTS(DisasContext *ctx, arg_RTS *a) +{ + prt("rts"); + return true; +} + +/* nop */ +static bool trans_NOP(DisasContext *ctx, arg_NOP *a) +{ + prt("nop"); + return true; +} + +/* scmpu */ +static bool trans_SCMPU(DisasContext *ctx, arg_SCMPU *a) +{ + prt("scmpu"); + return true; +} + +/* smovu */ +static bool trans_SMOVU(DisasContext *ctx, arg_SMOVU *a) +{ + prt("smovu"); + return true; +} + +/* smovf */ +static bool trans_SMOVF(DisasContext *ctx, arg_SMOVF *a) +{ + prt("smovf"); + return true; +} + +/* smovb */ +static bool trans_SMOVB(DisasContext *ctx, arg_SMOVB *a) +{ + prt("smovb"); + return true; +} + +/* suntile */ +static bool trans_SUNTIL(DisasContext *ctx, arg_SUNTIL *a) +{ + prt("suntil.%c", size[a->sz]); + return true; +} + +/* swhile */ +static bool trans_SWHILE(DisasContext *ctx, arg_SWHILE *a) +{ + prt("swhile.%c", size[a->sz]); + return true; +} +/* sstr */ +static bool trans_SSTR(DisasContext *ctx, arg_SSTR *a) +{ + prt("sstr.%c", size[a->sz]); + return true; +} + +/* rmpa */ +static bool trans_RMPA(DisasContext *ctx, arg_RMPA *a) +{ + prt("rmpa.%c", size[a->sz]); + return true; +} + +/* mulhi rs,rs2 */ +static bool trans_MULHI(DisasContext *ctx, arg_MULHI *a) +{ + prt("mulhi\tr%d,r%d", a->rs, a->rs2); + return true; +} + +/* mullo rs,rs2 */ +static bool trans_MULLO(DisasContext *ctx, arg_MULLO *a) +{ + prt("mullo\tr%d, r%d", a->rs, a->rs2); + return true; +} + +/* machi rs,rs2 */ +static bool trans_MACHI(DisasContext *ctx, arg_MACHI *a) +{ + prt("machi\tr%d, r%d", a->rs, a->rs2); + return true; +} + +/* maclo rs,rs2 */ +static bool trans_MACLO(DisasContext *ctx, arg_MACLO *a) +{ + prt("maclo\tr%d, r%d", a->rs, a->rs2); + return true; +} + +/* mvfachi rd */ +static bool trans_MVFACHI(DisasContext *ctx, arg_MVFACHI *a) +{ + prt("mvfachi\tr%d", a->rd); + return true; +} + +/* mvfacmi rd */ +static bool trans_MVFACMI(DisasContext *ctx, arg_MVFACMI *a) +{ + prt("mvfacmi\tr%d", a->rd); + return true; +} + +/* mvtachi rs */ +static bool trans_MVTACHI(DisasContext *ctx, arg_MVTACHI *a) +{ + prt("mvtachi\tr%d", a->rs); + return true; +} + +/* mvtaclo rs */ +static bool trans_MVTACLO(DisasContext *ctx, arg_MVTACLO *a) +{ + prt("mvtaclo\tr%d", a->rs); + return true; +} + +/* racw #imm */ +static bool trans_RACW(DisasContext *ctx, arg_RACW *a) +{ + prt("racw\t#%d", a->imm + 1); + return true; +} + +/* sat rd */ +static bool trans_SAT(DisasContext *ctx, arg_SAT *a) +{ + prt("sat\tr%d", a->rd); + return true; +} + +/* satr */ +static bool trans_SATR(DisasContext *ctx, arg_SATR *a) +{ + prt("satr"); + return true; +} + +/* fadd #imm, rd */ +static bool trans_FADD_ir(DisasContext *ctx, arg_FADD_ir *a) +{ + prt("fadd\t#%d,r%d", li(ctx, 0), a->rd); + return true; +} + +/* fadd dsp[rs], rd */ +/* fadd rs, rd */ +static bool trans_FADD_mr(DisasContext *ctx, arg_FADD_mr *a) +{ + prt("fadd\t"); + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + return true; +} + +/* fcmp #imm, rd */ +static bool trans_FCMP_ir(DisasContext *ctx, arg_FCMP_ir *a) +{ + prt("fadd\t#%d,r%d", li(ctx, 0), a->rd); + return true; +} + +/* fcmp dsp[rs], rd */ +/* fcmp rs, rd */ +static bool trans_FCMP_mr(DisasContext *ctx, arg_FCMP_mr *a) +{ + prt("fcmp\t"); + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + return true; +} + +/* fsub #imm, rd */ +static bool trans_FSUB_ir(DisasContext *ctx, arg_FSUB_ir *a) +{ + prt("fsub\t#%d,r%d", li(ctx, 0), a->rd); + return true; +} + +/* fsub dsp[rs], rd */ +/* fsub rs, rd */ +static bool trans_FSUB_mr(DisasContext *ctx, arg_FSUB_mr *a) +{ + prt("fsub\t"); + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + return true; +} + +/* ftoi dsp[rs], rd */ +/* ftoi rs, rd */ +static bool trans_FTOI(DisasContext *ctx, arg_FTOI *a) +{ + prt("ftoi\t"); + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + return true; +} + +/* fmul #imm, rd */ +static bool trans_FMUL_ir(DisasContext *ctx, arg_FMUL_ir *a) +{ + prt("fmul\t#%d,r%d", li(ctx, 0), a->rd); + return true; +} + +/* fmul dsp[rs], rd */ +/* fmul rs, rd */ +static bool trans_FMUL_mr(DisasContext *ctx, arg_FMUL_mr *a) +{ + prt("fmul\t"); + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + return true; +} + +/* fdiv #imm, rd */ +static bool trans_FDIV_ir(DisasContext *ctx, arg_FDIV_ir *a) +{ + prt("fdiv\t#%d,r%d", li(ctx, 0), a->rd); + return true; +} + +/* fdiv dsp[rs], rd */ +/* fdiv rs, rd */ +static bool trans_FDIV_mr(DisasContext *ctx, arg_FDIV_mr *a) +{ + prt("fdiv\t"); + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + return true; +} + +/* round dsp[rs], rd */ +/* round rs, rd */ +static bool trans_ROUND(DisasContext *ctx, arg_ROUND *a) +{ + prt("round\t"); + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + return true; +} + +/* itof rs, rd */ +/* itof dsp[rs], rd */ +static bool trans_ITOF(DisasContext *ctx, arg_ITOF *a) +{ + prt("itof\t"); + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + return true; +} + +#define BOP_IM(name, reg) \ + do { \ + int dsp; \ + prt("b%s\t#%d, ", #name, a->imm); \ + dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx); \ + if (dsp > 0) { \ + prt("%d", dsp); \ + } \ + prt("[r%d]", reg); \ + return true; \ + } while (0) + +#define BOP_RM(name) \ + do { \ + int dsp; \ + prt("b%s\tr%d, ", #name, a->rd); \ + dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx); \ + if (dsp > 0) { \ + prt("%d", dsp); \ + } \ + prt("[r%d]", a->rs); \ + return true; \ + } while (0) + +/* bset #imm, dsp[rd] */ +static bool trans_BSET_im(DisasContext *ctx, arg_BSET_im *a) +{ + BOP_IM(bset, a->rs); +} + +/* bset rs, dsp[rd] */ +static bool trans_BSET_rm(DisasContext *ctx, arg_BSET_rm *a) +{ + BOP_RM(set); +} + +/* bset rs, rd */ +static bool trans_BSET_rr(DisasContext *ctx, arg_BSET_rr *a) +{ + prt("bset\tr%d,r%d", a->rs, a->rd); + return true; +} + +/* bset #imm, rd */ +static bool trans_BSET_ir(DisasContext *ctx, arg_BSET_ir *a) +{ + prt("bset\t#%d, r%d", a->imm, a->rd); + return true; +} + +/* bclr #imm, dsp[rd] */ +static bool trans_BCLR_im(DisasContext *ctx, arg_BCLR_im *a) +{ + BOP_IM(clr, a->rs); +} + +/* bclr rs, dsp[rd] */ +static bool trans_BCLR_rm(DisasContext *ctx, arg_BCLR_rm *a) +{ + BOP_RM(clr); +} + +/* bclr rs, rd */ +static bool trans_BCLR_rr(DisasContext *ctx, arg_BCLR_rr *a) +{ + prt("bclr\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* bclr #imm, rd */ +static bool trans_BCLR_ir(DisasContext *ctx, arg_BCLR_ir *a) +{ + prt("bclr\t#%d,r%d", a->imm, a->rd); + return true; +} + +/* btst #imm, dsp[rd] */ +static bool trans_BTST_im(DisasContext *ctx, arg_BTST_im *a) +{ + BOP_IM(tst, a->rs); +} + +/* btst rs, dsp[rd] */ +static bool trans_BTST_rm(DisasContext *ctx, arg_BTST_rm *a) +{ + BOP_RM(tst); +} + +/* btst rs, rd */ +static bool trans_BTST_rr(DisasContext *ctx, arg_BTST_rr *a) +{ + prt("btst\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* btst #imm, rd */ +static bool trans_BTST_ir(DisasContext *ctx, arg_BTST_ir *a) +{ + prt("btst\t#%d, r%d", a->imm, a->rd); + return true; +} + +/* bnot rs, dsp[rd] */ +static bool trans_BNOT_rm(DisasContext *ctx, arg_BNOT_rm *a) +{ + BOP_RM(not); +} + +/* bnot rs, rd */ +static bool trans_BNOT_rr(DisasContext *ctx, arg_BNOT_rr *a) +{ + prt("bnot\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* bnot #imm, dsp[rd] */ +static bool trans_BNOT_im(DisasContext *ctx, arg_BNOT_im *a) +{ + BOP_IM(not, a->rs); +} + +/* bnot #imm, rd */ +static bool trans_BNOT_ir(DisasContext *ctx, arg_BNOT_ir *a) +{ + prt("bnot\t#%d, r%d", a->imm, a->rd); + return true; +} + +/* bmcond #imm, dsp[rd] */ +static bool trans_BMCnd_im(DisasContext *ctx, arg_BMCnd_im *a) +{ + int dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx); + prt("bm%s\t#%d, ", cond[a->cd], a->imm); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[%d]", a->rd); + return true; +} + +/* bmcond #imm, rd */ +static bool trans_BMCnd_ir(DisasContext *ctx, arg_BMCnd_ir *a) +{ + prt("bm%s\t#%d, r%d", cond[a->cd], a->imm, a->rd); + return true; +} + +/* clrpsw psw */ +static bool trans_CLRPSW(DisasContext *ctx, arg_CLRPSW *a) +{ + prt("clrpsw\t%c", psw[a->cb]); + return true; +} + +/* setpsw psw */ +static bool trans_SETPSW(DisasContext *ctx, arg_SETPSW *a) +{ + prt("setpsw\t%c", psw[a->cb]); + return true; +} + +/* mvtipl #imm */ +static bool trans_MVTIPL(DisasContext *ctx, arg_MVTIPL *a) +{ + prt("movtipl\t#%d", a->imm); + return true; +} + +/* mvtc #imm, rd */ +static bool trans_MVTC_i(DisasContext *ctx, arg_MVTC_i *a) +{ + prt("mvtc\t#0x%08x, %s", a->imm, rx_crname[a->cr]); + return true; +} + +/* mvtc rs, rd */ +static bool trans_MVTC_r(DisasContext *ctx, arg_MVTC_r *a) +{ + prt("mvtc\tr%d, %s", a->rs, rx_crname[a->cr]); + return true; +} + +/* mvfc rs, rd */ +static bool trans_MVFC(DisasContext *ctx, arg_MVFC *a) +{ + prt("mvfc\t%s, r%d", rx_crname[a->cr], a->rd); + return true; +} + +/* rtfi */ +static bool trans_RTFI(DisasContext *ctx, arg_RTFI *a) +{ + prt("rtfi"); + return true; +} + +/* rte */ +static bool trans_RTE(DisasContext *ctx, arg_RTE *a) +{ + prt("rte"); + return true; +} + +/* brk */ +static bool trans_BRK(DisasContext *ctx, arg_BRK *a) +{ + prt("brk"); + return true; +} + +/* int #imm */ +static bool trans_INT(DisasContext *ctx, arg_INT *a) +{ + prt("int\t#%d", a->imm); + return true; +} + +/* wait */ +static bool trans_WAIT(DisasContext *ctx, arg_WAIT *a) +{ + prt("wait"); + return true; +} + +/* sccnd.[bwl] rd */ +/* sccnd.[bwl] dsp:[rd] */ +static bool trans_SCCnd(DisasContext *ctx, arg_SCCnd *a) +{ + int dsp; + prt("sc%s.%c\t", cond[a->cd], size[a->sz]); + if (a->ld < 3) { + dsp = rx_index_addr(a->sz, a->ld, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d]", a->rd); + } else { + prt("r%d", a->rd); + } + return true; +} + +int print_insn_rx(bfd_vma addr, disassemble_info *dis) +{ + DisasContext ctx; + uint32_t insn; + int i; + ctx.dis = dis; + ctx.pc = ctx.addr = addr; + + insn = decode_load(&ctx); + if (!decode(&ctx, insn)) { + ctx.dis->fprintf_func(ctx.dis->stream, ".byte\t"); + for (i = 0; i < ctx.addr - addr; i++) { + if (i > 0) { + ctx.dis->fprintf_func(ctx.dis->stream, ","); + } + ctx.dis->fprintf_func(ctx.dis->stream, "0x%02x", insn >> 24); + insn <<= 8; + } + } + return ctx.addr - addr; +} From patchwork Tue Jun 18 14:10:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117959 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45Sr1c5F2Gz9s3l for ; Wed, 19 Jun 2019 00:24:20 +1000 (AEST) Received: from localhost ([::1]:58498 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdF22-000657-Qy for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:24:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60140) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEps-0002w3-Ba for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpk-0007uY-Em for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:42 -0400 Received: from mail02.asahi-net.or.jp ([202.224.55.14]:35000) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEpi-0007mo-St for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:35 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail02.asahi-net.or.jp (Postfix) with ESMTPA id B398243F18; Tue, 18 Jun 2019 23:11:29 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 5EA79240086; Tue, 18 Jun 2019 23:11:29 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:10:49 +0900 Message-Id: <20190618141118.52955-11-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.14 Subject: [Qemu-devel] [PATCH v21 06/21] target/rx: CPU definition X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, richard.henderson@linaro.org, Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" v21 changes Add cpu-param.h Remove CPU_COMMON rx_load_image move to rx-virt. Signed-off-by: Yoshinori Sato Message-Id: <20190616142836.10614-4-ysato@users.sourceforge.jp> Reviewed-by: Richard Henderson Message-Id: <20190607091116.49044-4-ysato@users.sourceforge.jp> Signed-off-by: Richard Henderson [PMD: Use newer QOM style, split cpu-qom.h, restrict access to extable array, use rx_cpu_tlb_fill() extracted from patch of Yoshinori Sato 'Convert to CPUClass::tlb_fill'] Signed-off-by: Philippe Mathieu-Daudé cpu.c: remove rx_load_image Signed-off-by: Yoshinori Sato --- target/rx/cpu-param.h | 31 ++++++++ target/rx/cpu-qom.h | 42 ++++++++++ target/rx/cpu.h | 182 ++++++++++++++++++++++++++++++++++++++++++ target/rx/cpu.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++ target/rx/gdbstub.c | 112 ++++++++++++++++++++++++++ target/rx/monitor.c | 38 +++++++++ 6 files changed, 622 insertions(+) create mode 100644 target/rx/cpu-param.h create mode 100644 target/rx/cpu-qom.h create mode 100644 target/rx/cpu.h create mode 100644 target/rx/cpu.c create mode 100644 target/rx/gdbstub.c create mode 100644 target/rx/monitor.c diff --git a/target/rx/cpu-param.h b/target/rx/cpu-param.h new file mode 100644 index 0000000000..5da87fbebe --- /dev/null +++ b/target/rx/cpu-param.h @@ -0,0 +1,31 @@ +/* + * RX cpu parameters + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef RX_CPU_PARAM_H +#define RX_CPU_PARAM_H + +#define TARGET_LONG_BITS 32 +#define TARGET_PAGE_BITS 12 + +#define TARGET_PHYS_ADDR_SPACE_BITS 32 +#define TARGET_VIRT_ADDR_SPACE_BITS 32 + +#define NB_MMU_MODES 1 +#define MMU_MODE0_SUFFIX _all + +#endif diff --git a/target/rx/cpu-qom.h b/target/rx/cpu-qom.h new file mode 100644 index 0000000000..4ae3b38b3e --- /dev/null +++ b/target/rx/cpu-qom.h @@ -0,0 +1,42 @@ +#ifndef QEMU_SUPERH_CPU_QOM_H +#define QEMU_SUPERH_CPU_QOM_H + +#include "qom/cpu.h" +/* + * RX CPU + * + * Copyright (c) 2019 Yoshinori Sato + * SPDX-License-Identifier: LGPL-2.0+ + */ + +#define TYPE_RX_CPU "rx-cpu" + +#define TYPE_RX62N_CPU RX_CPU_TYPE_NAME("rx62n") + +#define RXCPU_CLASS(klass) \ + OBJECT_CLASS_CHECK(RXCPUClass, (klass), TYPE_RX_CPU) +#define RXCPU(obj) \ + OBJECT_CHECK(RXCPU, (obj), TYPE_RX_CPU) +#define RXCPU_GET_CLASS(obj) \ + OBJECT_GET_CLASS(RXCPUClass, (obj), TYPE_RX_CPU) + +/* + * RXCPUClass: + * @parent_realize: The parent class' realize handler. + * @parent_reset: The parent class' reset handler. + * + * A RX CPU model. + */ +typedef struct RXCPUClass { + /*< private >*/ + CPUClass parent_class; + /*< public >*/ + + DeviceRealize parent_realize; + void (*parent_reset)(CPUState *cpu); + +} RXCPUClass; + +#define CPUArchState struct CPURXState + +#endif diff --git a/target/rx/cpu.h b/target/rx/cpu.h new file mode 100644 index 0000000000..3f9c4fdd25 --- /dev/null +++ b/target/rx/cpu.h @@ -0,0 +1,182 @@ +/* + * RX emulation definition + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef RX_CPU_H +#define RX_CPU_H + +#include "qemu/bitops.h" +#include "qemu-common.h" +#include "hw/registerfields.h" +#include "cpu-qom.h" +#include "qom/cpu.h" + +#include "exec/cpu-defs.h" + +/* PSW define */ +REG32(PSW, 0) +FIELD(PSW, C, 0, 1) +FIELD(PSW, Z, 1, 1) +FIELD(PSW, S, 2, 1) +FIELD(PSW, O, 3, 1) +FIELD(PSW, I, 16, 1) +FIELD(PSW, U, 17, 1) +FIELD(PSW, PM, 20, 1) +FIELD(PSW, IPL, 24, 4) + +/* FPSW define */ +REG32(FPSW, 0) +FIELD(FPSW, RM, 0, 2) +FIELD(FPSW, CV, 2, 1) +FIELD(FPSW, CO, 3, 1) +FIELD(FPSW, CZ, 4, 1) +FIELD(FPSW, CU, 5, 1) +FIELD(FPSW, CX, 6, 1) +FIELD(FPSW, CE, 7, 1) +FIELD(FPSW, CAUSE, 2, 6) +FIELD(FPSW, DN, 8, 1) +FIELD(FPSW, EV, 10, 1) +FIELD(FPSW, EO, 11, 1) +FIELD(FPSW, EZ, 12, 1) +FIELD(FPSW, EU, 13, 1) +FIELD(FPSW, EX, 14, 1) +FIELD(FPSW, ENABLE, 10, 5) +FIELD(FPSW, FV, 26, 1) +FIELD(FPSW, FO, 27, 1) +FIELD(FPSW, FZ, 28, 1) +FIELD(FPSW, FU, 29, 1) +FIELD(FPSW, FX, 30, 1) +FIELD(FPSW, FLAGS, 26, 4) +FIELD(FPSW, FS, 31, 1) + +enum { + NUM_REGS = 16, +}; + +typedef struct CPURXState { + /* CPU registers */ + uint32_t regs[NUM_REGS]; /* general registers */ + uint32_t psw_o; /* O bit of status register */ + uint32_t psw_s; /* S bit of status register */ + uint32_t psw_z; /* Z bit of status register */ + uint32_t psw_c; /* C bit of status register */ + uint32_t psw_u; + uint32_t psw_i; + uint32_t psw_pm; + uint32_t psw_ipl; + uint32_t bpsw; /* backup status */ + uint32_t bpc; /* backup pc */ + uint32_t isp; /* global base register */ + uint32_t usp; /* vector base register */ + uint32_t pc; /* program counter */ + uint32_t intb; /* interrupt vector */ + uint32_t fintv; + uint32_t fpsw; + uint64_t acc; + + /* Fields up to this point are cleared by a CPU reset */ + struct {} end_reset_fields; + + /* Internal use */ + uint32_t in_sleep; + uint32_t req_irq; /* Requested interrupt no (hard) */ + uint32_t req_ipl; /* Requested interrupt level */ + uint32_t ack_irq; /* execute irq */ + uint32_t ack_ipl; /* execute ipl */ + float_status fp_status; + qemu_irq ack; /* Interrupt acknowledge */ +} CPURXState; + +/* + * RXCPU: + * @env: #CPURXState + * + * A RX CPU + */ +struct RXCPU { + /*< private >*/ + CPUState parent_obj; + /*< public >*/ + + CPUNegativeOffsetState neg; + CPURXState env; +}; + +typedef struct RXCPU RXCPU; +typedef RXCPU ArchCPU; + +#define ENV_OFFSET offsetof(RXCPU, env) + +#define RX_CPU_TYPE_SUFFIX "-" TYPE_RX_CPU +#define RX_CPU_TYPE_NAME(model) model RX_CPU_TYPE_SUFFIX +#define CPU_RESOLVING_TYPE TYPE_RX_CPU + +extern const char rx_crname[][6]; + +void rx_cpu_do_interrupt(CPUState *cpu); +bool rx_cpu_exec_interrupt(CPUState *cpu, int int_req); +void rx_cpu_dump_state(CPUState *cpu, FILE *f, int flags); +int rx_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); +int rx_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); +hwaddr rx_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); + +void rx_translate_init(void); +int cpu_rx_signal_handler(int host_signum, void *pinfo, + void *puc); + +void rx_cpu_list(void); +void rx_cpu_unpack_psw(CPURXState *env, uint32_t psw, int rte); + +#define cpu_signal_handler cpu_rx_signal_handler +#define cpu_list rx_cpu_list + +#include "exec/cpu-all.h" + +#define CPU_INTERRUPT_SOFT CPU_INTERRUPT_TGT_INT_0 +#define CPU_INTERRUPT_FIR CPU_INTERRUPT_TGT_INT_1 + +#define RX_CPU_IRQ 0 +#define RX_CPU_FIR 1 + +static inline void cpu_get_tb_cpu_state(CPURXState *env, target_ulong *pc, + target_ulong *cs_base, uint32_t *flags) +{ + *pc = env->pc; + *cs_base = 0; + *flags = FIELD_DP32(0, PSW, PM, env->psw_pm); +} + +static inline int cpu_mmu_index(CPURXState *env, bool ifetch) +{ + return 0; +} + +static inline uint32_t rx_cpu_pack_psw(CPURXState *env) +{ + uint32_t psw = 0; + psw = FIELD_DP32(psw, PSW, IPL, env->psw_ipl); + psw = FIELD_DP32(psw, PSW, PM, env->psw_pm); + psw = FIELD_DP32(psw, PSW, U, env->psw_u); + psw = FIELD_DP32(psw, PSW, I, env->psw_i); + psw = FIELD_DP32(psw, PSW, O, env->psw_o >> 31); + psw = FIELD_DP32(psw, PSW, S, env->psw_s >> 31); + psw = FIELD_DP32(psw, PSW, Z, env->psw_z == 0); + psw = FIELD_DP32(psw, PSW, C, env->psw_c); + return psw; +} + +#endif /* RX_CPU_H */ diff --git a/target/rx/cpu.c b/target/rx/cpu.c new file mode 100644 index 0000000000..ea38639f47 --- /dev/null +++ b/target/rx/cpu.c @@ -0,0 +1,217 @@ +/* + * QEMU RX CPU + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/qemu-print.h" +#include "qapi/error.h" +#include "cpu.h" +#include "qemu-common.h" +#include "migration/vmstate.h" +#include "exec/exec-all.h" +#include "hw/loader.h" +#include "fpu/softfloat.h" + +static void rx_cpu_set_pc(CPUState *cs, vaddr value) +{ + RXCPU *cpu = RXCPU(cs); + + cpu->env.pc = value; +} + +static void rx_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) +{ + RXCPU *cpu = RXCPU(cs); + + cpu->env.pc = tb->pc; +} + +static bool rx_cpu_has_work(CPUState *cs) +{ + return cs->interrupt_request & + (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIR); +} + +static void rx_cpu_reset(CPUState *s) +{ + RXCPU *cpu = RXCPU(s); + RXCPUClass *rcc = RXCPU_GET_CLASS(cpu); + CPURXState *env = &cpu->env; + uint32_t *resetvec; + + rcc->parent_reset(s); + + memset(env, 0, offsetof(CPURXState, end_reset_fields)); + + resetvec = rom_ptr(0xfffffffc, 4); + if (resetvec) { + /* In the case of kernel, it is ignored because it is not set. */ + env->pc = ldl_p(resetvec); + } + rx_cpu_unpack_psw(env, 0, 1); + env->regs[0] = env->isp = env->usp = 0; + env->fpsw = 0; + set_flush_to_zero(1, &env->fp_status); + set_flush_inputs_to_zero(1, &env->fp_status); +} + +static void rx_cpu_list_entry(gpointer data, gpointer user_data) +{ + const char *typename = object_class_get_name(OBJECT_CLASS(data)); + + qemu_printf("%s\n", typename); +} + +void rx_cpu_list(void) +{ + GSList *list; + list = object_class_get_list_sorted(TYPE_RX_CPU, false); + g_slist_foreach(list, rx_cpu_list_entry, NULL); + g_slist_free(list); +} + +static ObjectClass *rx_cpu_class_by_name(const char *cpu_model) +{ + ObjectClass *oc; + + oc = object_class_by_name(cpu_model); + if (object_class_dynamic_cast(oc, TYPE_RX_CPU) == NULL || + object_class_is_abstract(oc)) { + oc = NULL; + } + + return oc; +} + +static void rx_cpu_realize(DeviceState *dev, Error **errp) +{ + CPUState *cs = CPU(dev); + RXCPUClass *rcc = RXCPU_GET_CLASS(dev); + Error *local_err = NULL; + + cpu_exec_realizefn(cs, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } + + cpu_reset(cs); + qemu_init_vcpu(cs); + + rcc->parent_realize(dev, errp); +} + +static void rx_cpu_set_irq(void *opaque, int no, int request) +{ + RXCPU *cpu = opaque; + CPUState *cs = CPU(cpu); + int irq = request & 0xff; + + static const int mask[] = { + [RX_CPU_IRQ] = CPU_INTERRUPT_HARD, + [RX_CPU_FIR] = CPU_INTERRUPT_FIR, + }; + if (irq) { + cpu->env.req_irq = irq; + cpu->env.req_ipl = (request >> 8) & 0x0f; + cpu_interrupt(cs, mask[no]); + } else { + cpu_reset_interrupt(cs, mask[no]); + } +} + +static void rx_cpu_disas_set_info(CPUState *cpu, disassemble_info *info) +{ + info->mach = bfd_mach_rx; + info->print_insn = print_insn_rx; +} + +static bool rx_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) +{ + uint32_t address, physical, prot; + + /* Linear mapping */ + address = physical = addr & TARGET_PAGE_MASK; + prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE); + return true; +} + +static void rx_cpu_init(Object *obj) +{ + CPUState *cs = CPU(obj); + RXCPU *cpu = RXCPU(obj); + CPURXState *env = &cpu->env; + + cpu_set_cpustate_pointers(cpu); + cs->env_ptr = env; + qdev_init_gpio_in(DEVICE(cpu), rx_cpu_set_irq, 2); +} + +static void rx_cpu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + CPUClass *cc = CPU_CLASS(klass); + RXCPUClass *rcc = RXCPU_CLASS(klass); + + device_class_set_parent_realize(dc, rx_cpu_realize, + &rcc->parent_realize); + + rcc->parent_reset = cc->reset; + cc->reset = rx_cpu_reset; + + cc->class_by_name = rx_cpu_class_by_name; + cc->has_work = rx_cpu_has_work; + cc->do_interrupt = rx_cpu_do_interrupt; + cc->cpu_exec_interrupt = rx_cpu_exec_interrupt; + cc->dump_state = rx_cpu_dump_state; + cc->set_pc = rx_cpu_set_pc; + cc->synchronize_from_tb = rx_cpu_synchronize_from_tb; + cc->gdb_read_register = rx_cpu_gdb_read_register; + cc->gdb_write_register = rx_cpu_gdb_write_register; + cc->get_phys_page_debug = rx_cpu_get_phys_page_debug; + cc->disas_set_info = rx_cpu_disas_set_info; + cc->tcg_initialize = rx_translate_init; + cc->tlb_fill = rx_cpu_tlb_fill; + + cc->gdb_num_core_regs = 26; +} + +static const TypeInfo rx_cpu_info = { + .name = TYPE_RX_CPU, + .parent = TYPE_CPU, + .instance_size = sizeof(RXCPU), + .instance_init = rx_cpu_init, + .abstract = true, + .class_size = sizeof(RXCPUClass), + .class_init = rx_cpu_class_init, +}; + +static const TypeInfo rx62n_rx_cpu_info = { + .name = TYPE_RX62N_CPU, + .parent = TYPE_RX_CPU, +}; + +static void rx_cpu_register_types(void) +{ + type_register_static(&rx_cpu_info); + type_register_static(&rx62n_rx_cpu_info); +} + +type_init(rx_cpu_register_types) diff --git a/target/rx/gdbstub.c b/target/rx/gdbstub.c new file mode 100644 index 0000000000..d76ca52e82 --- /dev/null +++ b/target/rx/gdbstub.c @@ -0,0 +1,112 @@ +/* + * RX gdb server stub + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" +#include "exec/gdbstub.h" + +int rx_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) +{ + RXCPU *cpu = RXCPU(cs); + CPURXState *env = &cpu->env; + + switch (n) { + case 0 ... 15: + return gdb_get_regl(mem_buf, env->regs[n]); + case 16: + return gdb_get_regl(mem_buf, (env->psw_u) ? env->regs[0] : env->usp); + case 17: + return gdb_get_regl(mem_buf, (!env->psw_u) ? env->regs[0] : env->isp); + case 18: + return gdb_get_regl(mem_buf, rx_cpu_pack_psw(env)); + case 19: + return gdb_get_regl(mem_buf, env->pc); + case 20: + return gdb_get_regl(mem_buf, env->intb); + case 21: + return gdb_get_regl(mem_buf, env->bpsw); + case 22: + return gdb_get_regl(mem_buf, env->bpc); + case 23: + return gdb_get_regl(mem_buf, env->fintv); + case 24: + return gdb_get_regl(mem_buf, env->fpsw); + case 25: + return 0; + } + return 0; +} + +int rx_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) +{ + RXCPU *cpu = RXCPU(cs); + CPURXState *env = &cpu->env; + uint32_t psw; + switch (n) { + case 0 ... 15: + env->regs[n] = ldl_p(mem_buf); + if (n == 0) { + if (env->psw_u) { + env->usp = env->regs[0]; + } else { + env->isp = env->regs[0]; + } + } + break; + case 16: + env->usp = ldl_p(mem_buf); + if (env->psw_u) { + env->regs[0] = ldl_p(mem_buf); + } + break; + case 17: + env->isp = ldl_p(mem_buf); + if (!env->psw_u) { + env->regs[0] = ldl_p(mem_buf); + } + break; + case 18: + psw = ldl_p(mem_buf); + rx_cpu_unpack_psw(env, psw, 1); + break; + case 19: + env->pc = ldl_p(mem_buf); + break; + case 20: + env->intb = ldl_p(mem_buf); + break; + case 21: + env->bpsw = ldl_p(mem_buf); + break; + case 22: + env->bpc = ldl_p(mem_buf); + break; + case 23: + env->fintv = ldl_p(mem_buf); + break; + case 24: + env->fpsw = ldl_p(mem_buf); + break; + case 25: + return 8; + default: + return 0; + } + + return 4; +} diff --git a/target/rx/monitor.c b/target/rx/monitor.c new file mode 100644 index 0000000000..5d7a1e58b5 --- /dev/null +++ b/target/rx/monitor.c @@ -0,0 +1,38 @@ +/* + * QEMU monitor + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "cpu.h" +#include "monitor/monitor.h" +#include "monitor/hmp-target.h" +#include "hmp.h" + +void hmp_info_tlb(Monitor *mon, const QDict *qdict) +{ + CPUArchState *env = mon_get_cpu_env(); + + if (!env) { + monitor_printf(mon, "No CPU available\n"); + return; + } +} From patchwork Tue Jun 18 14:10:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117964 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45Sr2w12Myz9s3l for ; Wed, 19 Jun 2019 00:25:28 +1000 (AEST) Received: from localhost ([::1]:58504 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdF38-0006z7-7W for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:25:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60208) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEpz-0002yl-8b for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpk-0007uC-64 for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:44 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:57039) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEpi-0007o5-SP for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:35 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id EC44A4A10F; Tue, 18 Jun 2019 23:11:30 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id A0953240085; Tue, 18 Jun 2019 23:11:30 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:10:52 +0900 Message-Id: <20190618141118.52955-14-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.15 Subject: [Qemu-devel] [PATCH v21 07/21] target/rx: Replace operand with prt_ldmi in disassembler X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, Richard Henderson , Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson This has consistency with prt_ri(). It loads all data before beginning output. It uses exactly one call to prt() to emit the full instruction. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Yoshinori Sato Signed-off-by: Yoshinori Sato Message-Id: <20190607091116.49044-20-ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/rx/disas.c | 77 +++++++++++++++++++------------------------------------ 1 file changed, 27 insertions(+), 50 deletions(-) diff --git a/target/rx/disas.c b/target/rx/disas.c index 64342537ee..515b365528 100644 --- a/target/rx/disas.c +++ b/target/rx/disas.c @@ -135,18 +135,18 @@ static void rx_index_addr(DisasContext *ctx, char out[8], int ld, int mi) sprintf(out, "%u", dsp << (mi < 3 ? mi : 4 - mi)); } -static void operand(DisasContext *ctx, int ld, int mi, int rs, int rd) +static void prt_ldmi(DisasContext *ctx, const char *insn, + int ld, int mi, int rs, int rd) { static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"}; char dsp[8]; if (ld < 3) { rx_index_addr(ctx, dsp, ld, mi); - prt("%s[r%d]%s", dsp, rs, sizes[mi]); + prt("%s\t%s[r%d]%s, r%d", insn, dsp, rs, sizes[mi], rd); } else { - prt("r%d", rs); + prt("%s\tr%d, r%d", insn, rs, rd); } - prt(", r%d", rd); } static void prt_ir(DisasContext *ctx, const char *insn, int imm, int rd) @@ -416,8 +416,7 @@ static bool trans_AND_ir(DisasContext *ctx, arg_AND_ir *a) /* and rs,rd */ static bool trans_AND_mr(DisasContext *ctx, arg_AND_mr *a) { - prt("and\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "and", a->ld, a->mi, a->rs, a->rd); return true; } @@ -440,8 +439,7 @@ static bool trans_OR_ir(DisasContext *ctx, arg_OR_ir *a) /* or rs,rd */ static bool trans_OR_mr(DisasContext *ctx, arg_OR_mr *a) { - prt("or\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "or", a->ld, a->mi, a->rs, a->rd); return true; } @@ -463,8 +461,7 @@ static bool trans_XOR_ir(DisasContext *ctx, arg_XOR_ir *a) /* xor rs,rd */ static bool trans_XOR_mr(DisasContext *ctx, arg_XOR_mr *a) { - prt("xor\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "xor", a->ld, a->mi, a->rs, a->rd); return true; } @@ -479,8 +476,7 @@ static bool trans_TST_ir(DisasContext *ctx, arg_TST_ir *a) /* tst rs, rd */ static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *a) { - prt("tst\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "tst", a->ld, a->mi, a->rs, a->rd); return true; } @@ -548,8 +544,7 @@ static bool trans_ADD_irr(DisasContext *ctx, arg_ADD_irr *a) /* add dsp[rs], rd */ static bool trans_ADD_mr(DisasContext *ctx, arg_ADD_mr *a) { - prt("add\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "add", a->ld, a->mi, a->rs, a->rd); return true; } @@ -573,8 +568,7 @@ static bool trans_CMP_ir(DisasContext *ctx, arg_CMP_ir *a) /* cmp dsp[rs], rs2 */ static bool trans_CMP_mr(DisasContext *ctx, arg_CMP_mr *a) { - prt("cmp\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "cmp", a->ld, a->mi, a->rs, a->rd); return true; } @@ -589,8 +583,7 @@ static bool trans_SUB_ir(DisasContext *ctx, arg_SUB_ir *a) /* sub dsp[rs], rd */ static bool trans_SUB_mr(DisasContext *ctx, arg_SUB_mr *a) { - prt("sub\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "sub", a->ld, a->mi, a->rs, a->rd); return true; } @@ -611,8 +604,7 @@ static bool trans_SBB_rr(DisasContext *ctx, arg_SBB_rr *a) /* sbb dsp[rs], rd */ static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a) { - prt("sbb\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "sbb", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -640,8 +632,7 @@ static bool trans_MAX_ir(DisasContext *ctx, arg_MAX_ir *a) /* max dsp[rs], rd */ static bool trans_MAX_mr(DisasContext *ctx, arg_MAX_mr *a) { - prt("max\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "max", a->ld, a->mi, a->rs, a->rd); return true; } @@ -656,8 +647,7 @@ static bool trans_MIN_ir(DisasContext *ctx, arg_MIN_ir *a) /* min dsp[rs], rd */ static bool trans_MIN_mr(DisasContext *ctx, arg_MIN_mr *a) { - prt("max\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "min", a->ld, a->mi, a->rs, a->rd); return true; } @@ -673,8 +663,7 @@ static bool trans_MUL_ir(DisasContext *ctx, arg_MUL_ir *a) /* mul dsp[rs], rd */ static bool trans_MUL_mr(DisasContext *ctx, arg_MUL_mr *a) { - prt("mul\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "mul", a->ld, a->mi, a->rs, a->rd); return true; } @@ -696,8 +685,7 @@ static bool trans_EMUL_ir(DisasContext *ctx, arg_EMUL_ir *a) /* emul dsp[rs], rd */ static bool trans_EMUL_mr(DisasContext *ctx, arg_EMUL_mr *a) { - prt("emul\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "emul", a->ld, a->mi, a->rs, a->rd); return true; } @@ -712,8 +700,7 @@ static bool trans_EMULU_ir(DisasContext *ctx, arg_EMULU_ir *a) /* emulu dsp[rs], rd */ static bool trans_EMULU_mr(DisasContext *ctx, arg_EMULU_mr *a) { - prt("emulu\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "emulu", a->ld, a->mi, a->rs, a->rd); return true; } @@ -728,8 +715,7 @@ static bool trans_DIV_ir(DisasContext *ctx, arg_DIV_ir *a) /* div dsp[rs], rd */ static bool trans_DIV_mr(DisasContext *ctx, arg_DIV_mr *a) { - prt("div\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "div", a->ld, a->mi, a->rs, a->rd); return true; } @@ -744,8 +730,7 @@ static bool trans_DIVU_ir(DisasContext *ctx, arg_DIVU_ir *a) /* divu dsp[rs], rd */ static bool trans_DIVU_mr(DisasContext *ctx, arg_DIVU_mr *a) { - prt("divu\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "divu", a->ld, a->mi, a->rs, a->rd); return true; } @@ -1089,8 +1074,7 @@ static bool trans_FADD_ir(DisasContext *ctx, arg_FADD_ir *a) /* fadd rs, rd */ static bool trans_FADD_mr(DisasContext *ctx, arg_FADD_mr *a) { - prt("fadd\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "fadd", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -1105,8 +1089,7 @@ static bool trans_FCMP_ir(DisasContext *ctx, arg_FCMP_ir *a) /* fcmp rs, rd */ static bool trans_FCMP_mr(DisasContext *ctx, arg_FCMP_mr *a) { - prt("fcmp\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "fcmp", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -1121,8 +1104,7 @@ static bool trans_FSUB_ir(DisasContext *ctx, arg_FSUB_ir *a) /* fsub rs, rd */ static bool trans_FSUB_mr(DisasContext *ctx, arg_FSUB_mr *a) { - prt("fsub\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "fsub", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -1130,8 +1112,7 @@ static bool trans_FSUB_mr(DisasContext *ctx, arg_FSUB_mr *a) /* ftoi rs, rd */ static bool trans_FTOI(DisasContext *ctx, arg_FTOI *a) { - prt("ftoi\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "ftoi", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -1146,8 +1127,7 @@ static bool trans_FMUL_ir(DisasContext *ctx, arg_FMUL_ir *a) /* fmul rs, rd */ static bool trans_FMUL_mr(DisasContext *ctx, arg_FMUL_mr *a) { - prt("fmul\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "fmul", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -1162,8 +1142,7 @@ static bool trans_FDIV_ir(DisasContext *ctx, arg_FDIV_ir *a) /* fdiv rs, rd */ static bool trans_FDIV_mr(DisasContext *ctx, arg_FDIV_mr *a) { - prt("fdiv\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "fdiv", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -1171,8 +1150,7 @@ static bool trans_FDIV_mr(DisasContext *ctx, arg_FDIV_mr *a) /* round rs, rd */ static bool trans_ROUND(DisasContext *ctx, arg_ROUND *a) { - prt("round\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "round", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -1180,8 +1158,7 @@ static bool trans_ROUND(DisasContext *ctx, arg_ROUND *a) /* itof dsp[rs], rd */ static bool trans_ITOF(DisasContext *ctx, arg_ITOF *a) { - prt("itof\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "itof", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } From patchwork Tue Jun 18 14:10:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117943 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45Sqmk6lR3z9s3l for ; Wed, 19 Jun 2019 00:13:09 +1000 (AEST) Received: from localhost ([::1]:58398 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdErD-0002vO-9c for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:13:07 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60045) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEpl-0002sQ-Iz for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpi-0007rJ-A0 for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:36 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:57044) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEph-0007oH-JK for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:34 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id 409FE4A25C; Tue, 18 Jun 2019 23:11:31 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id E7566240086; Tue, 18 Jun 2019 23:11:30 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:10:53 +0900 Message-Id: <20190618141118.52955-15-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.15 Subject: [Qemu-devel] [PATCH v21 08/21] target/rx: Disassemble rx_index_addr into a string X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, Richard Henderson , Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson We were eliding all zero indexes. It is only ld==0 that does not have an index in the instruction. This also allows us to avoid breaking the final print into multiple pieces. Reviewed-by: Yoshinori Sato Signed-off-by: Yoshinori Sato Message-Id: <20190607091116.49044-19-ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/rx/disas.c | 154 +++++++++++++++++++----------------------------------- 1 file changed, 55 insertions(+), 99 deletions(-) diff --git a/target/rx/disas.c b/target/rx/disas.c index 8cada4825d..64342537ee 100644 --- a/target/rx/disas.c +++ b/target/rx/disas.c @@ -107,49 +107,42 @@ static const char psw[] = { 'i', 'u', 0, 0, 0, 0, 0, 0, }; -static uint32_t rx_index_addr(int ld, int size, DisasContext *ctx) +static void rx_index_addr(DisasContext *ctx, char out[8], int ld, int mi) { - bfd_byte buf[2]; + uint32_t addr = ctx->addr; + uint8_t buf[2]; + uint16_t dsp; + switch (ld) { case 0: - return 0; + /* No index; return empty string. */ + out[0] = '\0'; + return; case 1: - ctx->dis->read_memory_func(ctx->addr, buf, 1, ctx->dis); ctx->addr += 1; - return ((uint8_t)buf[0]) << size; + ctx->dis->read_memory_func(addr, buf, 1, ctx->dis); + dsp = buf[0]; + break; case 2: - ctx->dis->read_memory_func(ctx->addr, buf, 2, ctx->dis); ctx->addr += 2; - return lduw_le_p(buf) << size; + ctx->dis->read_memory_func(addr, buf, 2, ctx->dis); + dsp = lduw_le_p(buf); + break; + default: + g_assert_not_reached(); } - g_assert_not_reached(); + + sprintf(out, "%u", dsp << (mi < 3 ? mi : 4 - mi)); } static void operand(DisasContext *ctx, int ld, int mi, int rs, int rd) { - int dsp; static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"}; + char dsp[8]; + if (ld < 3) { - switch (mi) { - case 4: - /* dsp[rs].ub */ - dsp = rx_index_addr(ld, RX_MEMORY_BYTE, ctx); - break; - case 3: - /* dsp[rs].uw */ - dsp = rx_index_addr(ld, RX_MEMORY_WORD, ctx); - break; - default: - /* dsp[rs].b */ - /* dsp[rs].w */ - /* dsp[rs].l */ - dsp = rx_index_addr(ld, mi, ctx); - break; - } - if (dsp > 0) { - prt("%d", dsp); - } - prt("[r%d]%s", rs, sizes[mi]); + rx_index_addr(ctx, dsp, ld, mi); + prt("%s[r%d]%s", dsp, rs, sizes[mi]); } else { prt("r%d", rs); } @@ -235,7 +228,7 @@ static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a) /* mov.[bwl] rs,rd */ static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a) { - int dsp; + char dspd[8], dsps[8]; prt("mov.%c\t", size[a->sz]); if (a->lds == 3 && a->ldd == 3) { @@ -244,29 +237,15 @@ static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a) return true; } if (a->lds == 3) { - prt("r%d, ", a->rd); - dsp = rx_index_addr(a->ldd, a->sz, ctx); - if (dsp > 0) { - prt("%d", dsp); - } - prt("[r%d]", a->rs); + rx_index_addr(ctx, dspd, a->ldd, a->sz); + prt("r%d, %s[r%d]", a->rs, dspd, a->rd); } else if (a->ldd == 3) { - dsp = rx_index_addr(a->lds, a->sz, ctx); - if (dsp > 0) { - prt("%d", dsp); - } - prt("[r%d], r%d", a->rs, a->rd); + rx_index_addr(ctx, dsps, a->lds, a->sz); + prt("%s[r%d], r%d", dsps, a->rs, a->rd); } else { - dsp = rx_index_addr(a->lds, a->sz, ctx); - if (dsp > 0) { - prt("%d", dsp); - } - prt("[r%d], ", a->rs); - dsp = rx_index_addr(a->ldd, a->sz, ctx); - if (dsp > 0) { - prt("%d", dsp); - } - prt("[r%d]", a->rd); + rx_index_addr(ctx, dsps, a->lds, a->sz); + rx_index_addr(ctx, dspd, a->ldd, a->sz); + prt("%s[r%d], %s[r%d]", dsps, a->rs, dspd, a->rd); } return true; } @@ -357,12 +336,10 @@ static bool trans_PUSH_r(DisasContext *ctx, arg_PUSH_r *a) /* push dsp[rs] */ static bool trans_PUSH_m(DisasContext *ctx, arg_PUSH_m *a) { - prt("push\t"); - int dsp = rx_index_addr(a->ld, a->sz, ctx); - if (dsp > 0) { - prt("%d", dsp); - } - prt("[r%d]", a->rs); + char dsp[8]; + + rx_index_addr(ctx, dsp, a->ld, a->sz); + prt("push\t%s[r%d]", dsp, a->rs); return true; } @@ -389,17 +366,13 @@ static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr *a) /* xchg dsp[rs].,rd */ static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a) { - int dsp; static const char msize[][4] = { "b", "w", "l", "ub", "uw", }; + char dsp[8]; - prt("xchg\t"); - dsp = rx_index_addr(a->ld, a->mi, ctx); - if (dsp > 0) { - prt("%d", dsp); - } - prt("[r%d].%s, r%d", a->rs, msize[a->mi], a->rd); + rx_index_addr(ctx, dsp, a->ld, a->mi); + prt("xchg\t%s[r%d].%s, r%d", dsp, a->rs, msize[a->mi], a->rd); return true; } @@ -552,13 +525,10 @@ static bool trans_ADC_rr(DisasContext *ctx, arg_ADC_rr *a) /* adc dsp[rs], rd */ static bool trans_ADC_mr(DisasContext *ctx, arg_ADC_mr *a) { - int dsp; - prt("adc\t"); - dsp = rx_index_addr(a->ld, 2, ctx); - if (dsp > 0) { - prt("%d", dsp); - } - prt("[r%d], r%d", a->rs, a->rd); + char dsp[8]; + + rx_index_addr(ctx, dsp, a->ld, 2); + prt("adc\t%s[r%d], r%d", dsp, a->rs, a->rd); return true; } @@ -1217,25 +1187,17 @@ static bool trans_ITOF(DisasContext *ctx, arg_ITOF *a) #define BOP_IM(name, reg) \ do { \ - int dsp; \ - prt("b%s\t#%d, ", #name, a->imm); \ - dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx); \ - if (dsp > 0) { \ - prt("%d", dsp); \ - } \ - prt("[r%d]", reg); \ + char dsp[8]; \ + rx_index_addr(ctx, dsp, a->ld, RX_MEMORY_BYTE); \ + prt("b%s\t#%d, %s[r%d]", #name, a->imm, dsp, reg); \ return true; \ } while (0) #define BOP_RM(name) \ do { \ - int dsp; \ - prt("b%s\tr%d, ", #name, a->rd); \ - dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx); \ - if (dsp > 0) { \ - prt("%d", dsp); \ - } \ - prt("[r%d]", a->rs); \ + char dsp[8]; \ + rx_index_addr(ctx, dsp, a->ld, RX_MEMORY_BYTE); \ + prt("b%s\tr%d, %s[r%d]", #name, a->rd, dsp, a->rs); \ return true; \ } while (0) @@ -1346,12 +1308,10 @@ static bool trans_BNOT_ir(DisasContext *ctx, arg_BNOT_ir *a) /* bmcond #imm, dsp[rd] */ static bool trans_BMCnd_im(DisasContext *ctx, arg_BMCnd_im *a) { - int dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx); - prt("bm%s\t#%d, ", cond[a->cd], a->imm); - if (dsp > 0) { - prt("%d", dsp); - } - prt("[%d]", a->rd); + char dsp[8]; + + rx_index_addr(ctx, dsp, a->ld, RX_MEMORY_BYTE); + prt("bm%s\t#%d, %s[r%d]", cond[a->cd], a->imm, dsp, a->rd); return true; } @@ -1443,16 +1403,12 @@ static bool trans_WAIT(DisasContext *ctx, arg_WAIT *a) /* sccnd.[bwl] dsp:[rd] */ static bool trans_SCCnd(DisasContext *ctx, arg_SCCnd *a) { - int dsp; - prt("sc%s.%c\t", cond[a->cd], size[a->sz]); if (a->ld < 3) { - dsp = rx_index_addr(a->sz, a->ld, ctx); - if (dsp > 0) { - prt("%d", dsp); - } - prt("[r%d]", a->rd); + char dsp[8]; + rx_index_addr(ctx, dsp, a->sz, a->ld); + prt("sc%s.%c\t%s[r%d]", cond[a->cd], size[a->sz], dsp, a->rd); } else { - prt("r%d", a->rd); + prt("sc%s.%c\tr%d", cond[a->cd], size[a->sz], a->rd); } return true; } From patchwork Tue Jun 18 14:10:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117950 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45SqtQ2WWVz9s3l for ; Wed, 19 Jun 2019 00:18:06 +1000 (AEST) Received: from localhost ([::1]:58448 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEw0-0008Go-Du for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:18:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60139) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEps-0002w2-BR for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpl-0007wI-IU for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:42 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:57053) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEpj-0007rp-Cm for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:36 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id 1A7954A2B4; Tue, 18 Jun 2019 23:11:32 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id B8871240085; Tue, 18 Jun 2019 23:11:31 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:10:56 +0900 Message-Id: <20190618141118.52955-18-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.15 Subject: [Qemu-devel] [PATCH v21 09/21] target/rx: Replace operand with prt_ldmi in disassembler X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, Richard Henderson , Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson This has consistency with prt_ri(). It loads all data before beginning output. It uses exactly one call to prt() to emit the full instruction. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Yoshinori Sato Signed-off-by: Yoshinori Sato Message-Id: <20190607091116.49044-20-ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/rx/disas.c | 77 +++++++++++++++++++------------------------------------ 1 file changed, 27 insertions(+), 50 deletions(-) diff --git a/target/rx/disas.c b/target/rx/disas.c index 64342537ee..515b365528 100644 --- a/target/rx/disas.c +++ b/target/rx/disas.c @@ -135,18 +135,18 @@ static void rx_index_addr(DisasContext *ctx, char out[8], int ld, int mi) sprintf(out, "%u", dsp << (mi < 3 ? mi : 4 - mi)); } -static void operand(DisasContext *ctx, int ld, int mi, int rs, int rd) +static void prt_ldmi(DisasContext *ctx, const char *insn, + int ld, int mi, int rs, int rd) { static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"}; char dsp[8]; if (ld < 3) { rx_index_addr(ctx, dsp, ld, mi); - prt("%s[r%d]%s", dsp, rs, sizes[mi]); + prt("%s\t%s[r%d]%s, r%d", insn, dsp, rs, sizes[mi], rd); } else { - prt("r%d", rs); + prt("%s\tr%d, r%d", insn, rs, rd); } - prt(", r%d", rd); } static void prt_ir(DisasContext *ctx, const char *insn, int imm, int rd) @@ -416,8 +416,7 @@ static bool trans_AND_ir(DisasContext *ctx, arg_AND_ir *a) /* and rs,rd */ static bool trans_AND_mr(DisasContext *ctx, arg_AND_mr *a) { - prt("and\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "and", a->ld, a->mi, a->rs, a->rd); return true; } @@ -440,8 +439,7 @@ static bool trans_OR_ir(DisasContext *ctx, arg_OR_ir *a) /* or rs,rd */ static bool trans_OR_mr(DisasContext *ctx, arg_OR_mr *a) { - prt("or\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "or", a->ld, a->mi, a->rs, a->rd); return true; } @@ -463,8 +461,7 @@ static bool trans_XOR_ir(DisasContext *ctx, arg_XOR_ir *a) /* xor rs,rd */ static bool trans_XOR_mr(DisasContext *ctx, arg_XOR_mr *a) { - prt("xor\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "xor", a->ld, a->mi, a->rs, a->rd); return true; } @@ -479,8 +476,7 @@ static bool trans_TST_ir(DisasContext *ctx, arg_TST_ir *a) /* tst rs, rd */ static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *a) { - prt("tst\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "tst", a->ld, a->mi, a->rs, a->rd); return true; } @@ -548,8 +544,7 @@ static bool trans_ADD_irr(DisasContext *ctx, arg_ADD_irr *a) /* add dsp[rs], rd */ static bool trans_ADD_mr(DisasContext *ctx, arg_ADD_mr *a) { - prt("add\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "add", a->ld, a->mi, a->rs, a->rd); return true; } @@ -573,8 +568,7 @@ static bool trans_CMP_ir(DisasContext *ctx, arg_CMP_ir *a) /* cmp dsp[rs], rs2 */ static bool trans_CMP_mr(DisasContext *ctx, arg_CMP_mr *a) { - prt("cmp\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "cmp", a->ld, a->mi, a->rs, a->rd); return true; } @@ -589,8 +583,7 @@ static bool trans_SUB_ir(DisasContext *ctx, arg_SUB_ir *a) /* sub dsp[rs], rd */ static bool trans_SUB_mr(DisasContext *ctx, arg_SUB_mr *a) { - prt("sub\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "sub", a->ld, a->mi, a->rs, a->rd); return true; } @@ -611,8 +604,7 @@ static bool trans_SBB_rr(DisasContext *ctx, arg_SBB_rr *a) /* sbb dsp[rs], rd */ static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a) { - prt("sbb\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "sbb", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -640,8 +632,7 @@ static bool trans_MAX_ir(DisasContext *ctx, arg_MAX_ir *a) /* max dsp[rs], rd */ static bool trans_MAX_mr(DisasContext *ctx, arg_MAX_mr *a) { - prt("max\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "max", a->ld, a->mi, a->rs, a->rd); return true; } @@ -656,8 +647,7 @@ static bool trans_MIN_ir(DisasContext *ctx, arg_MIN_ir *a) /* min dsp[rs], rd */ static bool trans_MIN_mr(DisasContext *ctx, arg_MIN_mr *a) { - prt("max\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "min", a->ld, a->mi, a->rs, a->rd); return true; } @@ -673,8 +663,7 @@ static bool trans_MUL_ir(DisasContext *ctx, arg_MUL_ir *a) /* mul dsp[rs], rd */ static bool trans_MUL_mr(DisasContext *ctx, arg_MUL_mr *a) { - prt("mul\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "mul", a->ld, a->mi, a->rs, a->rd); return true; } @@ -696,8 +685,7 @@ static bool trans_EMUL_ir(DisasContext *ctx, arg_EMUL_ir *a) /* emul dsp[rs], rd */ static bool trans_EMUL_mr(DisasContext *ctx, arg_EMUL_mr *a) { - prt("emul\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "emul", a->ld, a->mi, a->rs, a->rd); return true; } @@ -712,8 +700,7 @@ static bool trans_EMULU_ir(DisasContext *ctx, arg_EMULU_ir *a) /* emulu dsp[rs], rd */ static bool trans_EMULU_mr(DisasContext *ctx, arg_EMULU_mr *a) { - prt("emulu\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "emulu", a->ld, a->mi, a->rs, a->rd); return true; } @@ -728,8 +715,7 @@ static bool trans_DIV_ir(DisasContext *ctx, arg_DIV_ir *a) /* div dsp[rs], rd */ static bool trans_DIV_mr(DisasContext *ctx, arg_DIV_mr *a) { - prt("div\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "div", a->ld, a->mi, a->rs, a->rd); return true; } @@ -744,8 +730,7 @@ static bool trans_DIVU_ir(DisasContext *ctx, arg_DIVU_ir *a) /* divu dsp[rs], rd */ static bool trans_DIVU_mr(DisasContext *ctx, arg_DIVU_mr *a) { - prt("divu\t"); - operand(ctx, a->ld, a->mi, a->rs, a->rd); + prt_ldmi(ctx, "divu", a->ld, a->mi, a->rs, a->rd); return true; } @@ -1089,8 +1074,7 @@ static bool trans_FADD_ir(DisasContext *ctx, arg_FADD_ir *a) /* fadd rs, rd */ static bool trans_FADD_mr(DisasContext *ctx, arg_FADD_mr *a) { - prt("fadd\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "fadd", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -1105,8 +1089,7 @@ static bool trans_FCMP_ir(DisasContext *ctx, arg_FCMP_ir *a) /* fcmp rs, rd */ static bool trans_FCMP_mr(DisasContext *ctx, arg_FCMP_mr *a) { - prt("fcmp\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "fcmp", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -1121,8 +1104,7 @@ static bool trans_FSUB_ir(DisasContext *ctx, arg_FSUB_ir *a) /* fsub rs, rd */ static bool trans_FSUB_mr(DisasContext *ctx, arg_FSUB_mr *a) { - prt("fsub\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "fsub", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -1130,8 +1112,7 @@ static bool trans_FSUB_mr(DisasContext *ctx, arg_FSUB_mr *a) /* ftoi rs, rd */ static bool trans_FTOI(DisasContext *ctx, arg_FTOI *a) { - prt("ftoi\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "ftoi", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -1146,8 +1127,7 @@ static bool trans_FMUL_ir(DisasContext *ctx, arg_FMUL_ir *a) /* fmul rs, rd */ static bool trans_FMUL_mr(DisasContext *ctx, arg_FMUL_mr *a) { - prt("fmul\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "fmul", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -1162,8 +1142,7 @@ static bool trans_FDIV_ir(DisasContext *ctx, arg_FDIV_ir *a) /* fdiv rs, rd */ static bool trans_FDIV_mr(DisasContext *ctx, arg_FDIV_mr *a) { - prt("fdiv\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "fdiv", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -1171,8 +1150,7 @@ static bool trans_FDIV_mr(DisasContext *ctx, arg_FDIV_mr *a) /* round rs, rd */ static bool trans_ROUND(DisasContext *ctx, arg_ROUND *a) { - prt("round\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "round", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } @@ -1180,8 +1158,7 @@ static bool trans_ROUND(DisasContext *ctx, arg_ROUND *a) /* itof dsp[rs], rd */ static bool trans_ITOF(DisasContext *ctx, arg_ITOF *a) { - prt("itof\t"); - operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + prt_ldmi(ctx, "itof", a->ld, RX_IM_LONG, a->rs, a->rd); return true; } From patchwork Tue Jun 18 14:10:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117968 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45Sr7Z6CjPz9sNl for ; Wed, 19 Jun 2019 00:29:30 +1000 (AEST) Received: from localhost ([::1]:58526 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdF72-0001dm-Uv for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:29:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60206) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEpz-0002yj-8S for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpq-00081e-3c for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:44 -0400 Received: from mail01.asahi-net.or.jp ([202.224.55.13]:60256) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEpl-0007vK-L5 for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:39 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail01.asahi-net.or.jp (Postfix) with ESMTPA id ACA02126D27; Tue, 18 Jun 2019 23:11:33 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 5910A240085; Tue, 18 Jun 2019 23:11:32 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:10:58 +0900 Message-Id: <20190618141118.52955-20-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.13 Subject: [Qemu-devel] [PATCH v21 10/21] target/rx: Use prt_ldmi for XCHG_mr disassembly X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, Richard Henderson , Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson Note that the ld == 3 case handled by prt_ldmi is decoded as XCHG_rr and cannot appear here. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Yoshinori Sato Signed-off-by: Yoshinori Sato Message-Id: <20190607091116.49044-21-ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/rx/disas.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/target/rx/disas.c b/target/rx/disas.c index 515b365528..db10385fd0 100644 --- a/target/rx/disas.c +++ b/target/rx/disas.c @@ -366,13 +366,7 @@ static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr *a) /* xchg dsp[rs].,rd */ static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a) { - static const char msize[][4] = { - "b", "w", "l", "ub", "uw", - }; - char dsp[8]; - - rx_index_addr(ctx, dsp, a->ld, a->mi); - prt("xchg\t%s[r%d].%s, r%d", dsp, a->rs, msize[a->mi], a->rd); + prt_ldmi(ctx, "xchg", a->ld, a->mi, a->rs, a->rd); return true; } From patchwork Tue Jun 18 14:10:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117946 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45Sqn83tcrz9s5c for ; Wed, 19 Jun 2019 00:13:32 +1000 (AEST) Received: from localhost ([::1]:58414 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEra-0004AW-DZ for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:13:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60048) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEpl-0002sc-KT for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpi-0007sM-T2 for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:36 -0400 Received: from mail02.asahi-net.or.jp ([202.224.55.14]:35006) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEpi-0007qL-9o for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:34 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail02.asahi-net.or.jp (Postfix) with ESMTPA id 2EE7843F58; Tue, 18 Jun 2019 23:11:33 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 9BBBF240086; Tue, 18 Jun 2019 23:11:32 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:10:59 +0900 Message-Id: <20190618141118.52955-21-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.14 Subject: [Qemu-devel] [PATCH v21 11/21] target/rx: Dump bytes for each insn during disassembly X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, Richard Henderson , Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson There are so many different forms of each RX instruction that it will be very useful to be able to look at the bytes to see on which path a bug may lie. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Yoshinori Sato Signed-off-by: Yoshinori Sato Message-Id: <20190607091116.49044-24-ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/rx/disas.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/target/rx/disas.c b/target/rx/disas.c index 5a32a87534..d73b53db44 100644 --- a/target/rx/disas.c +++ b/target/rx/disas.c @@ -102,7 +102,21 @@ static int bdsp_s(DisasContext *ctx, int d) /* Include the auto-generated decoder. */ #include "decode.inc.c" -#define prt(...) (ctx->dis->fprintf_func)((ctx->dis->stream), __VA_ARGS__) +static void dump_bytes(DisasContext *ctx) +{ + int i, len = ctx->len; + + for (i = 0; i < len; ++i) { + ctx->dis->fprintf_func(ctx->dis->stream, "%02x ", ctx->bytes[i]); + } + ctx->dis->fprintf_func(ctx->dis->stream, "%*c", (8 - i) * 3, '\t'); +} + +#define prt(...) \ + do { \ + dump_bytes(ctx); \ + ctx->dis->fprintf_func(ctx->dis->stream, __VA_ARGS__); \ + } while (0) #define RX_MEMORY_BYTE 0 #define RX_MEMORY_WORD 1 From patchwork Tue Jun 18 14:11:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117965 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45Sr400194z9s3l for ; Wed, 19 Jun 2019 00:26:23 +1000 (AEST) Received: from localhost ([::1]:58508 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdF40-0007JD-UK for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:26:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60207) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEpz-0002yk-8O for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpq-00081v-4O for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:44 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:57055) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEpl-0007ru-IJ for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:39 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id 113524A2B5; Tue, 18 Jun 2019 23:11:34 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id BB964240085; Tue, 18 Jun 2019 23:11:33 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:11:02 +0900 Message-Id: <20190618141118.52955-24-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.15 Subject: [Qemu-devel] [PATCH v21 12/21] target/rx: Collect all bytes during disassembly X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, Richard Henderson , Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson Collected, to be used in the next patch. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Yoshinori Sato Signed-off-by: Yoshinori Sato Message-Id: <20190607091116.49044-23-ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/rx/disas.c | 62 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/target/rx/disas.c b/target/rx/disas.c index ebc1a44249..5a32a87534 100644 --- a/target/rx/disas.c +++ b/target/rx/disas.c @@ -25,43 +25,59 @@ typedef struct DisasContext { disassemble_info *dis; uint32_t addr; uint32_t pc; + uint8_t len; + uint8_t bytes[8]; } DisasContext; static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn, - int i, int n) + int i, int n) { - bfd_byte buf; + uint32_t addr = ctx->addr; + + g_assert(ctx->len == i); + g_assert(n <= ARRAY_SIZE(ctx->bytes)); + while (++i <= n) { - ctx->dis->read_memory_func(ctx->addr++, &buf, 1, ctx->dis); - insn |= buf << (32 - i * 8); + ctx->dis->read_memory_func(addr++, &ctx->bytes[i - 1], 1, ctx->dis); + insn |= ctx->bytes[i - 1] << (32 - i * 8); } + ctx->addr = addr; + ctx->len = n; + return insn; } static int32_t li(DisasContext *ctx, int sz) { - int32_t addr; - bfd_byte buf[4]; - addr = ctx->addr; + uint32_t addr = ctx->addr; + uintptr_t len = ctx->len; switch (sz) { case 1: + g_assert(len + 1 <= ARRAY_SIZE(ctx->bytes)); ctx->addr += 1; - ctx->dis->read_memory_func(addr, buf, 1, ctx->dis); - return (int8_t)buf[0]; + ctx->len += 1; + ctx->dis->read_memory_func(addr, ctx->bytes + len, 1, ctx->dis); + return (int8_t)ctx->bytes[len]; case 2: + g_assert(len + 2 <= ARRAY_SIZE(ctx->bytes)); ctx->addr += 2; - ctx->dis->read_memory_func(addr, buf, 2, ctx->dis); - return ldsw_le_p(buf); + ctx->len += 2; + ctx->dis->read_memory_func(addr, ctx->bytes + len, 2, ctx->dis); + return ldsw_le_p(ctx->bytes + len); case 3: + g_assert(len + 3 <= ARRAY_SIZE(ctx->bytes)); ctx->addr += 3; - ctx->dis->read_memory_func(addr, buf, 3, ctx->dis); - return (int8_t)buf[2] << 16 | lduw_le_p(buf); + ctx->len += 3; + ctx->dis->read_memory_func(addr, ctx->bytes + len, 3, ctx->dis); + return (int8_t)ctx->bytes[len + 2] << 16 | lduw_le_p(ctx->bytes + len); case 0: + g_assert(len + 4 <= ARRAY_SIZE(ctx->bytes)); ctx->addr += 4; - ctx->dis->read_memory_func(addr, buf, 4, ctx->dis); - return ldl_le_p(buf); + ctx->len += 4; + ctx->dis->read_memory_func(addr, ctx->bytes + len, 4, ctx->dis); + return ldl_le_p(ctx->bytes + len); default: g_assert_not_reached(); } @@ -110,7 +126,7 @@ static const char psw[] = { static void rx_index_addr(DisasContext *ctx, char out[8], int ld, int mi) { uint32_t addr = ctx->addr; - uint8_t buf[2]; + uintptr_t len = ctx->len; uint16_t dsp; switch (ld) { @@ -119,14 +135,18 @@ static void rx_index_addr(DisasContext *ctx, char out[8], int ld, int mi) out[0] = '\0'; return; case 1: + g_assert(len + 1 <= ARRAY_SIZE(ctx->bytes)); ctx->addr += 1; - ctx->dis->read_memory_func(addr, buf, 1, ctx->dis); - dsp = buf[0]; + ctx->len += 1; + ctx->dis->read_memory_func(addr, ctx->bytes + len, 1, ctx->dis); + dsp = ctx->bytes[len]; break; case 2: + g_assert(len + 2 <= ARRAY_SIZE(ctx->bytes)); ctx->addr += 2; - ctx->dis->read_memory_func(addr, buf, 2, ctx->dis); - dsp = lduw_le_p(buf); + ctx->len += 2; + ctx->dis->read_memory_func(addr, ctx->bytes + len, 2, ctx->dis); + dsp = lduw_le_p(ctx->bytes + len); break; default: g_assert_not_reached(); @@ -1392,8 +1412,10 @@ int print_insn_rx(bfd_vma addr, disassemble_info *dis) DisasContext ctx; uint32_t insn; int i; + ctx.dis = dis; ctx.pc = ctx.addr = addr; + ctx.len = 0; insn = decode_load(&ctx); if (!decode(&ctx, insn)) { From patchwork Tue Jun 18 14:11:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117951 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45Sqtt4mf0z9s3l for ; Wed, 19 Jun 2019 00:18:30 +1000 (AEST) Received: from localhost ([::1]:58456 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEwO-0000iJ-Ll for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:18:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60238) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEq1-0002zL-G4 for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpq-00081l-4U for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:47 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:57063) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEpl-0007uc-HM for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:39 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id 5C6284A2AF; Tue, 18 Jun 2019 23:11:34 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 0964C240086; Tue, 18 Jun 2019 23:11:34 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:11:03 +0900 Message-Id: <20190618141118.52955-25-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.15 Subject: [Qemu-devel] [PATCH v21 13/21] hw/timer: RX62N internal timer modules X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, richard.henderson@linaro.org, Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" renesas_tmr: 8bit timer modules. renesas_cmt: 16bit compare match timer modules. This part use many renesas's CPU. Hardware manual. https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej0140_rx62n.pdf Signed-off-by: Yoshinori Sato Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20190607091116.49044-7-ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- include/hw/timer/renesas_cmt.h | 38 ++++ include/hw/timer/renesas_tmr.h | 53 +++++ hw/timer/renesas_cmt.c | 275 +++++++++++++++++++++++++ hw/timer/renesas_tmr.c | 455 +++++++++++++++++++++++++++++++++++++++++ hw/timer/Kconfig | 6 + hw/timer/Makefile.objs | 3 + 6 files changed, 830 insertions(+) create mode 100644 include/hw/timer/renesas_cmt.h create mode 100644 include/hw/timer/renesas_tmr.h create mode 100644 hw/timer/renesas_cmt.c create mode 100644 hw/timer/renesas_tmr.c diff --git a/include/hw/timer/renesas_cmt.h b/include/hw/timer/renesas_cmt.h new file mode 100644 index 0000000000..acd25c6e0b --- /dev/null +++ b/include/hw/timer/renesas_cmt.h @@ -0,0 +1,38 @@ +/* + * Renesas Compare-match timer Object + * + * Copyright (c) 2019 Yoshinori Sato + * + * This code is licensed under the GPL version 2 or later. + * + */ + +#ifndef HW_RENESAS_CMT_H +#define HW_RENESAS_CMT_H + +#include "hw/sysbus.h" + +#define TYPE_RENESAS_CMT "renesas-cmt" +#define RCMT(obj) OBJECT_CHECK(RCMTState, (obj), TYPE_RENESAS_CMT) + +enum { + CMT_CH = 2, + CMT_NR_IRQ = 1 * CMT_CH, +}; + +typedef struct RCMTState { + SysBusDevice parent_obj; + + uint64_t input_freq; + MemoryRegion memory; + + uint16_t cmstr; + uint16_t cmcr[CMT_CH]; + uint16_t cmcnt[CMT_CH]; + uint16_t cmcor[CMT_CH]; + int64_t tick[CMT_CH]; + qemu_irq cmi[CMT_CH]; + QEMUTimer *timer[CMT_CH]; +} RCMTState; + +#endif diff --git a/include/hw/timer/renesas_tmr.h b/include/hw/timer/renesas_tmr.h new file mode 100644 index 0000000000..5787004c74 --- /dev/null +++ b/include/hw/timer/renesas_tmr.h @@ -0,0 +1,53 @@ +/* + * Renesas 8bit timer Object + * + * Copyright (c) 2018 Yoshinori Sato + * + * This code is licensed under the GPL version 2 or later. + * + */ + +#ifndef HW_RENESAS_TMR_H +#define HW_RENESAS_TMR_H + +#include "hw/sysbus.h" + +#define TYPE_RENESAS_TMR "renesas-tmr" +#define RTMR(obj) OBJECT_CHECK(RTMRState, (obj), TYPE_RENESAS_TMR) + +enum timer_event { + cmia = 0, + cmib = 1, + ovi = 2, + none = 3, + TMR_NR_EVENTS = 4 +}; + +enum { + TMR_CH = 2, + TMR_NR_IRQ = 3 * TMR_CH, +}; + +typedef struct RTMRState { + SysBusDevice parent_obj; + + uint64_t input_freq; + MemoryRegion memory; + + uint8_t tcnt[TMR_CH]; + uint8_t tcora[TMR_CH]; + uint8_t tcorb[TMR_CH]; + uint8_t tcr[TMR_CH]; + uint8_t tccr[TMR_CH]; + uint8_t tcor[TMR_CH]; + uint8_t tcsr[TMR_CH]; + int64_t tick; + int64_t div_round[TMR_CH]; + enum timer_event next[TMR_CH]; + qemu_irq cmia[TMR_CH]; + qemu_irq cmib[TMR_CH]; + qemu_irq ovi[TMR_CH]; + QEMUTimer *timer[TMR_CH]; +} RTMRState; + +#endif diff --git a/hw/timer/renesas_cmt.c b/hw/timer/renesas_cmt.c new file mode 100644 index 0000000000..a2a2b92055 --- /dev/null +++ b/hw/timer/renesas_cmt.c @@ -0,0 +1,275 @@ +/* + * Renesas 16bit Compare-match timer + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "qemu/timer.h" +#include "cpu.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/timer/renesas_cmt.h" +#include "qemu/error-report.h" + +/* + * +0 CMSTR - common control + * +2 CMCR - ch0 + * +4 CMCNT - ch0 + * +6 CMCOR - ch0 + * +8 CMCR - ch1 + * +10 CMCNT - ch1 + * +12 CMCOR - ch1 + * If we think that the address of CH 0 has an offset of +2, + * we can treat it with the same address as CH 1, so define it like that. + */ +REG16(CMSTR, 0) + FIELD(CMSTR, STR0, 0, 1) + FIELD(CMSTR, STR1, 1, 1) + FIELD(CMSTR, STR, 0, 2) +/* This addeess is channel offset */ +REG16(CMCR, 0) + FIELD(CMCR, CKS, 0, 2) + FIELD(CMCR, CMIE, 6, 1) +REG16(CMCNT, 2) +REG16(CMCOR, 4) + +static void update_events(RCMTState *cmt, int ch) +{ + int64_t next_time; + + if ((cmt->cmstr & (1 << ch)) == 0) { + /* count disable, so not happened next event. */ + return ; + } + next_time = cmt->cmcor[ch] - cmt->cmcnt[ch]; + next_time *= NANOSECONDS_PER_SECOND; + next_time /= cmt->input_freq; + /* + * CKS -> div rate + * 0 -> 8 (1 << 3) + * 1 -> 32 (1 << 5) + * 2 -> 128 (1 << 7) + * 3 -> 512 (1 << 9) + */ + next_time *= 1 << (3 + FIELD_EX16(cmt->cmcr[ch], CMCR, CKS) * 2); + next_time += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + timer_mod(cmt->timer[ch], next_time); +} + +static int64_t read_cmcnt(RCMTState *cmt, int ch) +{ + int64_t delta, now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + + if (cmt->cmstr & (1 << ch)) { + delta = (now - cmt->tick[ch]); + delta /= NANOSECONDS_PER_SECOND; + delta /= cmt->input_freq; + delta /= 1 << (3 + FIELD_EX16(cmt->cmcr[ch], CMCR, CKS) * 2); + cmt->tick[ch] = now; + return cmt->cmcnt[ch] + delta; + } else { + return cmt->cmcnt[ch]; + } +} + +static uint64_t cmt_read(void *opaque, hwaddr addr, unsigned size) +{ + hwaddr offset = addr & 0x0f; + RCMTState *cmt = opaque; + int ch = offset / 0x08; + uint64_t ret; + + if (offset == A_CMSTR) { + ret = 0; + ret = FIELD_DP16(ret, CMSTR, STR, + FIELD_EX16(cmt->cmstr, CMSTR, STR)); + return ret; + } else { + offset &= 0x07; + if (ch == 0) { + offset -= 0x02; + } + switch (offset) { + case A_CMCR: + ret = 0; + ret = FIELD_DP16(ret, CMCR, CKS, + FIELD_EX16(cmt->cmstr, CMCR, CKS)); + ret = FIELD_DP16(ret, CMCR, CMIE, + FIELD_EX16(cmt->cmstr, CMCR, CMIE)); + return ret; + case A_CMCNT: + return read_cmcnt(cmt, ch); + case A_CMCOR: + return cmt->cmcor[ch]; + } + } + qemu_log_mask(LOG_UNIMP, "renesas_cmt: Register 0x%" + HWADDR_PRIX " not implemented\n", offset); + return UINT64_MAX; +} + +static void start_stop(RCMTState *cmt, int ch, int st) +{ + if (st) { + update_events(cmt, ch); + } else { + timer_del(cmt->timer[ch]); + } +} + +static void cmt_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) +{ + hwaddr offset = addr & 0x0f; + RCMTState *cmt = opaque; + int ch = offset / 0x08; + + if (offset == A_CMSTR) { + cmt->cmstr = FIELD_EX16(val, CMSTR, STR); + start_stop(cmt, 0, FIELD_EX16(cmt->cmstr, CMSTR, STR0)); + start_stop(cmt, 1, FIELD_EX16(cmt->cmstr, CMSTR, STR1)); + } else { + offset &= 0x07; + if (ch == 0) { + offset -= 0x02; + } + switch (offset) { + case A_CMCR: + cmt->cmcr[ch] = FIELD_DP16(cmt->cmcr[ch], CMCR, CKS, + FIELD_EX16(val, CMCR, CKS)); + cmt->cmcr[ch] = FIELD_DP16(cmt->cmcr[ch], CMCR, CMIE, + FIELD_EX16(val, CMCR, CMIE)); + break; + case 2: + cmt->cmcnt[ch] = val; + break; + case 4: + cmt->cmcor[ch] = val; + break; + default: + qemu_log_mask(LOG_UNIMP, "renesas_cmt: Register -0x%" HWADDR_PRIX + " not implemented\n", offset); + return; + } + if (FIELD_EX16(cmt->cmstr, CMSTR, STR) & (1 << ch)) { + update_events(cmt, ch); + } + } +} + +static const MemoryRegionOps cmt_ops = { + .write = cmt_write, + .read = cmt_read, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 2, + .max_access_size = 2, + }, +}; + +static void timer_events(RCMTState *cmt, int ch) +{ + cmt->cmcnt[ch] = 0; + cmt->tick[ch] = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + update_events(cmt, ch); + if (FIELD_EX16(cmt->cmcr[ch], CMCR, CMIE)) { + qemu_irq_pulse(cmt->cmi[ch]); + } +} + +static void timer_event0(void *opaque) +{ + RCMTState *cmt = opaque; + + timer_events(cmt, 0); +} + +static void timer_event1(void *opaque) +{ + RCMTState *cmt = opaque; + + timer_events(cmt, 1); +} + +static void rcmt_reset(DeviceState *dev) +{ + RCMTState *cmt = RCMT(dev); + cmt->cmstr = 0; + cmt->cmcr[0] = cmt->cmcr[1] = 0; + cmt->cmcnt[0] = cmt->cmcnt[1] = 0; + cmt->cmcor[0] = cmt->cmcor[1] = 0xffff; +} + +static void rcmt_init(Object *obj) +{ + SysBusDevice *d = SYS_BUS_DEVICE(obj); + RCMTState *cmt = RCMT(obj); + int i; + + memory_region_init_io(&cmt->memory, OBJECT(cmt), &cmt_ops, + cmt, "renesas-cmt", 0x10); + sysbus_init_mmio(d, &cmt->memory); + + for (i = 0; i < ARRAY_SIZE(cmt->cmi); i++) { + sysbus_init_irq(d, &cmt->cmi[i]); + } + cmt->timer[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event0, cmt); + cmt->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event1, cmt); +} + +static const VMStateDescription vmstate_rcmt = { + .name = "rx-cmt", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static Property rcmt_properties[] = { + DEFINE_PROP_UINT64("input-freq", RCMTState, input_freq, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rcmt_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->props = rcmt_properties; + dc->vmsd = &vmstate_rcmt; + dc->reset = rcmt_reset; +} + +static const TypeInfo rcmt_info = { + .name = TYPE_RENESAS_CMT, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(RCMTState), + .instance_init = rcmt_init, + .class_init = rcmt_class_init, +}; + +static void rcmt_register_types(void) +{ + type_register_static(&rcmt_info); +} + +type_init(rcmt_register_types) diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c new file mode 100644 index 0000000000..aa12ca7726 --- /dev/null +++ b/hw/timer/renesas_tmr.c @@ -0,0 +1,455 @@ +/* + * Renesas 8bit timer + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "qemu/timer.h" +#include "qemu/bitops.h" +#include "cpu.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/timer/renesas_tmr.h" +#include "qemu/error-report.h" + +REG8(TCR, 0) + FIELD(TCR, CCLR, 3, 2) + FIELD(TCR, OVIE, 5, 1) + FIELD(TCR, CMIEA, 6, 1) + FIELD(TCR, CMIEB, 7, 1) +REG8(TCSR, 2) + FIELD(TCSR, OSA, 0, 2) + FIELD(TCSR, OSB, 2, 2) + FIELD(TCSR, ADTE, 4, 2) +REG8(TCORA, 4) +REG8(TCORB, 6) +REG8(TCNT, 8) +REG8(TCCR, 10) + FIELD(TCCR, CKS, 0, 3) + FIELD(TCCR, CSS, 3, 2) + FIELD(TCCR, TMRIS, 7, 1) + +#define INTERNAL 0x01 +#define CASCADING 0x03 +#define CCLR_A 0x01 +#define CCLR_B 0x02 + +static const int clkdiv[] = {0, 1, 2, 8, 32, 64, 1024, 8192}; + +#define concat_reg(reg) ((reg[0] << 8) | reg[1]) +static void update_events(RTMRState *tmr, int ch) +{ + uint16_t diff[TMR_NR_EVENTS], min; + int64_t next_time; + int i, event; + + if (tmr->tccr[ch] == 0) { + return ; + } + if (FIELD_EX8(tmr->tccr[ch], TCCR, CSS) == 0) { + /* external clock mode */ + /* event not happened */ + return ; + } + if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) == CASCADING) { + /* cascading mode */ + if (ch == 1) { + tmr->next[ch] = none; + return ; + } + diff[cmia] = concat_reg(tmr->tcora) - concat_reg(tmr->tcnt); + diff[cmib] = concat_reg(tmr->tcorb) - concat_reg(tmr->tcnt); + diff[ovi] = 0x10000 - concat_reg(tmr->tcnt); + } else { + /* separate mode */ + diff[cmia] = tmr->tcora[ch] - tmr->tcnt[ch]; + diff[cmib] = tmr->tcorb[ch] - tmr->tcnt[ch]; + diff[ovi] = 0x100 - tmr->tcnt[ch]; + } + /* Search for the most recently occurring event. */ + for (event = 0, min = diff[0], i = 1; i < none; i++) { + if (min > diff[i]) { + event = i; + min = diff[i]; + } + } + tmr->next[ch] = event; + next_time = diff[event]; + next_time *= clkdiv[FIELD_EX8(tmr->tccr[ch], TCCR, CKS)]; + next_time *= NANOSECONDS_PER_SECOND; + next_time /= tmr->input_freq; + next_time += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + timer_mod(tmr->timer[ch], next_time); +} + + +static inline int elapsed_time(RTMRState *tmr, int ch, int64_t delta) +{ + int divrate = clkdiv[FIELD_EX8(tmr->tccr[ch], TCCR, CKS)]; + int et; + + tmr->div_round[ch] += delta; + if (divrate > 0) { + et = tmr->div_round[ch] / divrate; + tmr->div_round[ch] %= divrate; + } else { + /* disble clock. so no update */ + et = 0; + } + return et; +} +static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch) +{ + int64_t delta, now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + int elapsed, ovf = 0; + uint16_t tcnt[2]; + uint32_t ret; + + delta = (now - tmr->tick) * NANOSECONDS_PER_SECOND / tmr->input_freq; + if (delta > 0) { + tmr->tick = now; + + if (FIELD_EX8(tmr->tccr[1], TCCR, CSS) == INTERNAL) { + /* timer1 count update */ + elapsed = elapsed_time(tmr, 1, delta); + if (elapsed >= 0x100) { + ovf = elapsed >> 8; + } + tcnt[1] = tmr->tcnt[1] + (elapsed & 0xff); + } + switch (FIELD_EX8(tmr->tccr[0], TCCR, CSS)) { + case INTERNAL: + elapsed = elapsed_time(tmr, 0, delta); + tcnt[0] = tmr->tcnt[0] + elapsed; + break; + case CASCADING: + if (ovf > 0) { + tcnt[0] = tmr->tcnt[0] + ovf; + } + break; + } + } else { + tcnt[0] = tmr->tcnt[0]; + tcnt[1] = tmr->tcnt[1]; + } + if (size == 1) { + return tcnt[ch]; + } else { + ret = 0; + ret = deposit32(ret, 0, 8, tcnt[1]); + ret = deposit32(ret, 8, 8, tcnt[0]); + return ret; + } +} + +static inline uint8_t read_tccr(uint8_t r) +{ + uint8_t tccr = 0; + tccr = FIELD_DP8(tccr, TCCR, TMRIS, + FIELD_EX8(r, TCCR, TMRIS)); + tccr = FIELD_DP8(tccr, TCCR, CSS, + FIELD_EX8(r, TCCR, CSS)); + tccr = FIELD_DP8(tccr, TCCR, CKS, + FIELD_EX8(r, TCCR, CKS)); + return tccr; +} + +static uint64_t tmr_read(void *opaque, hwaddr addr, unsigned size) +{ + RTMRState *tmr = opaque; + int ch = addr & 1; + uint64_t ret; + + if (size == 2 && (ch != 0 || addr == A_TCR || addr == A_TCSR)) { + qemu_log_mask(LOG_GUEST_ERROR, "renesas_tmr: Invalid read size 0x%" + HWADDR_PRIX "\n", addr); + return UINT64_MAX; + } + switch (addr & 0x0e) { + case A_TCR: + ret = 0; + ret = FIELD_DP8(ret, TCR, CCLR, + FIELD_EX8(tmr->tcr[ch], TCR, CCLR)); + ret = FIELD_DP8(ret, TCR, OVIE, + FIELD_EX8(tmr->tcr[ch], TCR, OVIE)); + ret = FIELD_DP8(ret, TCR, CMIEA, + FIELD_EX8(tmr->tcr[ch], TCR, CMIEA)); + ret = FIELD_DP8(ret, TCR, CMIEB, + FIELD_EX8(tmr->tcr[ch], TCR, CMIEB)); + return ret; + case A_TCSR: + ret = 0; + ret = FIELD_DP8(ret, TCSR, OSA, + FIELD_EX8(tmr->tcsr[ch], TCSR, OSA)); + ret = FIELD_DP8(ret, TCSR, OSB, + FIELD_EX8(tmr->tcsr[ch], TCSR, OSB)); + switch (ch) { + case 0: + ret = FIELD_DP8(ret, TCSR, ADTE, + FIELD_EX8(tmr->tcsr[ch], TCSR, ADTE)); + break; + case 1: /* CH1 ADTE unimplement always 1 */ + ret = FIELD_DP8(ret, TCSR, ADTE, 1); + break; + } + return ret; + case A_TCORA: + if (size == 1) { + return tmr->tcora[ch]; + } else if (ch == 0) { + return concat_reg(tmr->tcora); + } + case A_TCORB: + if (size == 1) { + return tmr->tcorb[ch]; + } else { + return concat_reg(tmr->tcorb); + } + case A_TCNT: + return read_tcnt(tmr, size, ch); + case A_TCCR: + if (size == 1) { + return read_tccr(tmr->tccr[ch]); + } else { + return read_tccr(tmr->tccr[0]) << 8 | read_tccr(tmr->tccr[1]); + } + default: + qemu_log_mask(LOG_UNIMP, "renesas_tmr: Register 0x%" HWADDR_PRIX + " not implemented\n", addr); + break; + } + return UINT64_MAX; +} + +#define COUNT_WRITE(reg, val) \ + do { \ + if (size == 1) { \ + tmr->reg[ch] = val; \ + update_events(tmr, ch); \ + } else { \ + tmr->reg[0] = extract32(val, 8, 8); \ + tmr->reg[1] = extract32(val, 0, 8); \ + update_events(tmr, 0); \ + update_events(tmr, 1); \ + } \ + } while (0) + +static void tmr_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) +{ + RTMRState *tmr = opaque; + int ch = addr & 1; + + if (size == 2 && (ch != 0 || addr == A_TCR || addr == A_TCSR)) { + qemu_log_mask(LOG_GUEST_ERROR, + "renesas_tmr: Invalid write size 0x%" HWADDR_PRIX + "\n", addr); + return; + } + switch (addr & 0x0e) { + case A_TCR: + tmr->tcr[ch] = val; + break; + case A_TCSR: + tmr->tcsr[ch] = val; + break; + case A_TCORA: + COUNT_WRITE(tcora, val); + break; + case A_TCORB: + COUNT_WRITE(tcorb, val); + break; + case A_TCNT: + COUNT_WRITE(tcnt, val); + break; + case A_TCCR: + COUNT_WRITE(tccr, val); + break; + default: + qemu_log_mask(LOG_UNIMP, "renesas_tmr: Register 0x%" HWADDR_PRIX + " not implemented\n", addr); + break; + } +} + +static const MemoryRegionOps tmr_ops = { + .write = tmr_write, + .read = tmr_read, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 1, + .max_access_size = 2, + }, +}; + +static void timer_events(RTMRState *tmr, int ch); + +static uint16_t issue_event(RTMRState *tmr, int ch, int sz, + uint16_t tcnt, uint16_t tcora, uint16_t tcorb) +{ + uint16_t ret = tcnt; + + switch (tmr->next[ch]) { + case none: + break; + case cmia: + if (tcnt >= tcora) { + if (FIELD_EX8(tmr->tcr[ch], TCR, CCLR) == CCLR_A) { + ret = tcnt - tcora; + } + if (FIELD_EX8(tmr->tcr[ch], TCR, CMIEA)) { + qemu_irq_pulse(tmr->cmia[ch]); + } + if (sz == 8 && ch == 0 && + FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CASCADING) { + tmr->tcnt[1]++; + timer_events(tmr, 1); + } + } + break; + case cmib: + if (tcnt >= tcorb) { + if (FIELD_EX8(tmr->tcr[ch], TCR, CCLR) == CCLR_B) { + ret = tcnt - tcorb; + } + if (FIELD_EX8(tmr->tcr[ch], TCR, CMIEB)) { + qemu_irq_pulse(tmr->cmib[ch]); + } + } + break; + case ovi: + if ((tcnt >= (1 << sz)) && FIELD_EX8(tmr->tcr[ch], TCR, OVIE)) { + qemu_irq_pulse(tmr->ovi[ch]); + } + break; + default: + g_assert_not_reached(); + } + return ret; +} + +static void timer_events(RTMRState *tmr, int ch) +{ + uint16_t tcnt; + tmr->tcnt[ch] = read_tcnt(tmr, 1, ch); + if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) != CASCADING) { + tmr->tcnt[ch] = issue_event(tmr, ch, 8, + tmr->tcnt[ch], + tmr->tcora[ch], tmr->tcorb[ch]) & 0xff; + } else { + if (ch == 1) { + return ; + } + tcnt = issue_event(tmr, ch, 16, + concat_reg(tmr->tcnt), + concat_reg(tmr->tcora), + concat_reg(tmr->tcorb)); + tmr->tcnt[0] = (tcnt >> 8) & 0xff; + tmr->tcnt[1] = tcnt & 0xff; + } + update_events(tmr, ch); +} + +static void timer_event0(void *opaque) +{ + RTMRState *tmr = opaque; + + timer_events(tmr, 0); +} + +static void timer_event1(void *opaque) +{ + RTMRState *tmr = opaque; + + timer_events(tmr, 1); +} + +static void rtmr_reset(DeviceState *dev) +{ + RTMRState *tmr = RTMR(dev); + tmr->tcr[0] = tmr->tcr[1] = 0x00; + tmr->tcsr[0] = 0x00; + tmr->tcsr[1] = 0x10; + tmr->tcnt[0] = tmr->tcnt[1] = 0x00; + tmr->tcora[0] = tmr->tcora[1] = 0xff; + tmr->tcorb[0] = tmr->tcorb[1] = 0xff; + tmr->tccr[0] = tmr->tccr[1] = 0x00; + tmr->next[0] = tmr->next[1] = none; + tmr->tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +} + +static void rtmr_init(Object *obj) +{ + SysBusDevice *d = SYS_BUS_DEVICE(obj); + RTMRState *tmr = RTMR(obj); + int i; + + memory_region_init_io(&tmr->memory, OBJECT(tmr), &tmr_ops, + tmr, "renesas-tmr", 0x10); + sysbus_init_mmio(d, &tmr->memory); + + for (i = 0; i < ARRAY_SIZE(tmr->ovi); i++) { + sysbus_init_irq(d, &tmr->cmia[i]); + sysbus_init_irq(d, &tmr->cmib[i]); + sysbus_init_irq(d, &tmr->ovi[i]); + } + tmr->timer[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event0, tmr); + tmr->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event1, tmr); +} + +static const VMStateDescription vmstate_rtmr = { + .name = "rx-tmr", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static Property rtmr_properties[] = { + DEFINE_PROP_UINT64("input-freq", RTMRState, input_freq, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rtmr_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->props = rtmr_properties; + dc->vmsd = &vmstate_rtmr; + dc->reset = rtmr_reset; +} + +static const TypeInfo rtmr_info = { + .name = TYPE_RENESAS_TMR, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(RTMRState), + .instance_init = rtmr_init, + .class_init = rtmr_class_init, +}; + +static void rtmr_register_types(void) +{ + type_register_static(&rtmr_info); +} + +type_init(rtmr_register_types) diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig index 51921eb63f..2249458f42 100644 --- a/hw/timer/Kconfig +++ b/hw/timer/Kconfig @@ -61,3 +61,9 @@ config CMSDK_APB_TIMER config CMSDK_APB_DUALTIMER bool select PTIMER + +config RENESAS_TMR8 + bool + +config RENESAS_CMT + bool diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs index 0e9a4530f8..86a75bc8d8 100644 --- a/hw/timer/Makefile.objs +++ b/hw/timer/Makefile.objs @@ -40,6 +40,9 @@ obj-$(CONFIG_MC146818RTC) += mc146818rtc.o obj-$(CONFIG_ALLWINNER_A10_PIT) += allwinner-a10-pit.o +obj-$(CONFIG_RENESAS_TMR8) += renesas_tmr.o +obj-$(CONFIG_RENESAS_CMT) += renesas_cmt.o + common-obj-$(CONFIG_STM32F2XX_TIMER) += stm32f2xx_timer.o common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o From patchwork Tue Jun 18 14:11:06 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117979 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45SrLR138fz9sBp for ; Wed, 19 Jun 2019 00:38:55 +1000 (AEST) Received: from localhost ([::1]:58586 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdFG9-0001OJ-5v for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:38:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60237) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEq1-0002zK-G3 for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpq-00081q-41 for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:47 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:57065) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEpl-0007uf-Ix for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:39 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id 4125D4A2E3; Tue, 18 Jun 2019 23:11:35 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id E8A65240085; Tue, 18 Jun 2019 23:11:34 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:11:06 +0900 Message-Id: <20190618141118.52955-28-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.15 Subject: [Qemu-devel] [PATCH v21 14/21] hw/intc: RX62N interrupt controller (ICUa) X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, richard.henderson@linaro.org, Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This implementation supported only ICUa. Hardware manual. https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej0140_rx62n.pdf Signed-off-by: Yoshinori Sato Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20190607091116.49044-6-ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- include/hw/intc/rx_icu.h | 56 +++++++ hw/intc/rx_icu.c | 376 +++++++++++++++++++++++++++++++++++++++++++++++ hw/intc/Kconfig | 3 + hw/intc/Makefile.objs | 1 + 4 files changed, 436 insertions(+) create mode 100644 include/hw/intc/rx_icu.h create mode 100644 hw/intc/rx_icu.c diff --git a/include/hw/intc/rx_icu.h b/include/hw/intc/rx_icu.h new file mode 100644 index 0000000000..acfcf06aef --- /dev/null +++ b/include/hw/intc/rx_icu.h @@ -0,0 +1,56 @@ +#ifndef RX_ICU_H +#define RX_ICU_H + +#include "qemu-common.h" +#include "hw/irq.h" + +enum TRG_MODE { + TRG_LEVEL = 0, + TRG_NEDGE = 1, /* Falling */ + TRG_PEDGE = 2, /* Raising */ + TRG_BEDGE = 3, /* Both */ +}; + +struct IRQSource { + enum TRG_MODE sense; + int level; +}; + +enum { + /* Software interrupt request */ + SWI = 27, + NR_IRQS = 256, +}; + +struct RXICUState { + SysBusDevice parent_obj; + + MemoryRegion memory; + struct IRQSource src[NR_IRQS]; + char *icutype; + uint32_t nr_irqs; + uint32_t *map; + uint32_t nr_sense; + uint32_t *init_sense; + + uint8_t ir[NR_IRQS]; + uint8_t dtcer[NR_IRQS]; + uint8_t ier[NR_IRQS / 8]; + uint8_t ipr[142]; + uint8_t dmasr[4]; + uint16_t fir; + uint8_t nmisr; + uint8_t nmier; + uint8_t nmiclr; + uint8_t nmicr; + int req_irq; + qemu_irq _irq; + qemu_irq _fir; + qemu_irq _swi; +}; +typedef struct RXICUState RXICUState; + +#define TYPE_RXICU "rx-icu" +#define RXICU(obj) OBJECT_CHECK(RXICUState, (obj), TYPE_RXICU) + +#endif /* RX_ICU_H */ diff --git a/hw/intc/rx_icu.c b/hw/intc/rx_icu.c new file mode 100644 index 0000000000..cb28c7a8d2 --- /dev/null +++ b/hw/intc/rx_icu.c @@ -0,0 +1,376 @@ +/* + * RX Interrupt Control Unit + * + * Warning: Only ICUa is supported. + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "cpu.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/intc/rx_icu.h" +#include "qemu/error-report.h" + +REG8(IR, 0) + FIELD(IR, IR, 0, 1) +REG8(DTCER, 0x100) + FIELD(DTCER, DTCE, 0, 1) +REG8(IER, 0x200) +REG8(SWINTR, 0x2e0) + FIELD(SWINTR, SWINT, 0, 1) +REG16(FIR, 0x2f0) + FIELD(FIR, FVCT, 0, 8) + FIELD(FIR, FIEN, 15, 1) +REG8(IPR, 0x300) + FIELD(IPR, IPR, 0, 4) +REG8(DMRSR, 0x400) +REG8(IRQCR, 0x500) + FIELD(IRQCR, IRQMD, 2, 2) +REG8(NMISR, 0x580) + FIELD(NMISR, NMIST, 0, 1) + FIELD(NMISR, LVDST, 1, 1) + FIELD(NMISR, OSTST, 2, 1) +REG8(NMIER, 0x581) + FIELD(NMIER, NMIEN, 0, 1) + FIELD(NMIER, LVDEN, 1, 1) + FIELD(NMIER, OSTEN, 2, 1) +REG8(NMICLR, 0x582) + FIELD(NMICLR, NMICLR, 0, 1) + FIELD(NMICLR, OSTCLR, 2, 1) +REG8(NMICR, 0x583) + FIELD(NMICR, NMIMD, 3, 1) + +#define request(icu, n) (icu->ipr[icu->map[n]] << 8 | n) + +static void set_irq(RXICUState *icu, int n_IRQ, int req) +{ + if ((icu->fir & R_FIR_FIEN_MASK) && + (icu->fir & R_FIR_FVCT_MASK) == n_IRQ) { + qemu_set_irq(icu->_fir, req); + } else { + qemu_set_irq(icu->_irq, req); + } +} + +static void rxicu_request(RXICUState *icu, int n_IRQ) +{ + int enable; + + enable = icu->ier[n_IRQ / 8] & (1 << (n_IRQ & 7)); + if (n_IRQ > 0 && enable != 0 && atomic_read(&icu->req_irq) < 0) { + atomic_set(&icu->req_irq, n_IRQ); + set_irq(icu, n_IRQ, request(icu, n_IRQ)); + } +} + +static void rxicu_set_irq(void *opaque, int n_IRQ, int level) +{ + RXICUState *icu = opaque; + struct IRQSource *src; + int issue; + + if (n_IRQ >= NR_IRQS) { + error_report("%s: IRQ %d out of range", __func__, n_IRQ); + return; + } + + src = &icu->src[n_IRQ]; + + level = (level != 0); + switch (src->sense) { + case TRG_LEVEL: + /* level-sensitive irq */ + issue = level; + src->level = level; + break; + case TRG_NEDGE: + issue = (level == 0 && src->level == 1); + src->level = level; + break; + case TRG_PEDGE: + issue = (level == 1 && src->level == 0); + src->level = level; + break; + case TRG_BEDGE: + issue = ((level ^ src->level) & 1); + src->level = level; + break; + default: + g_assert_not_reached(); + } + if (issue == 0 && src->sense == TRG_LEVEL) { + icu->ir[n_IRQ] = 0; + if (atomic_read(&icu->req_irq) == n_IRQ) { + /* clear request */ + set_irq(icu, n_IRQ, 0); + atomic_set(&icu->req_irq, -1); + } + return; + } + if (issue) { + icu->ir[n_IRQ] = 1; + rxicu_request(icu, n_IRQ); + } +} + +static void rxicu_ack_irq(void *opaque, int no, int level) +{ + RXICUState *icu = opaque; + int i; + int n_IRQ; + int max_pri; + + n_IRQ = atomic_read(&icu->req_irq); + if (n_IRQ < 0) { + return; + } + atomic_set(&icu->req_irq, -1); + if (icu->src[n_IRQ].sense != TRG_LEVEL) { + icu->ir[n_IRQ] = 0; + } + + max_pri = 0; + n_IRQ = -1; + for (i = 0; i < NR_IRQS; i++) { + if (icu->ir[i]) { + if (max_pri < icu->ipr[icu->map[i]]) { + n_IRQ = i; + max_pri = icu->ipr[icu->map[i]]; + } + } + } + + if (n_IRQ >= 0) { + rxicu_request(icu, n_IRQ); + } +} + +static uint64_t icu_read(void *opaque, hwaddr addr, unsigned size) +{ + RXICUState *icu = opaque; + int reg = addr & 0xff; + + if ((addr != A_FIR && size != 1) || + (addr == A_FIR && size != 2)) { + qemu_log_mask(LOG_GUEST_ERROR, "rx_icu: Invalid read size 0x%" + HWADDR_PRIX "\n", addr); + return UINT64_MAX; + } + switch (addr) { + case A_IR ... A_IR + 0xff: + return icu->ir[reg] & R_IR_IR_MASK; + case A_DTCER ... A_DTCER + 0xff: + return icu->dtcer[reg] & R_DTCER_DTCE_MASK; + case A_IER ... A_IER + 0x1f: + return icu->ier[reg]; + case A_SWINTR: + return 0; + case A_FIR: + return icu->fir & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK); + case A_IPR ... A_IPR + 0x8f: + return icu->ipr[reg] & R_IPR_IPR_MASK; + case A_DMRSR: + case A_DMRSR + 4: + case A_DMRSR + 8: + case A_DMRSR + 12: + return icu->dmasr[reg >> 2]; + case A_IRQCR ... A_IRQCR + 0x1f: + return icu->src[64 + reg].sense << R_IRQCR_IRQMD_SHIFT; + case A_NMISR: + case A_NMICLR: + return 0; + case A_NMIER: + return icu->nmier; + case A_NMICR: + return icu->nmicr; + default: + qemu_log_mask(LOG_UNIMP, "rx_icu: Register 0x%" HWADDR_PRIX + " not implemented.\n", addr); + break; + } + return UINT64_MAX; +} + +static void icu_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) +{ + RXICUState *icu = opaque; + int reg = addr & 0xff; + + if ((addr != A_FIR && size != 1) || + (addr == A_FIR && size != 2)) { + qemu_log_mask(LOG_GUEST_ERROR, "rx_icu: Invalid write size at 0x%" + HWADDR_PRIX "\n", addr); + return; + } + switch (addr) { + case A_IR ... A_IR + 0xff: + if (icu->src[reg].sense != TRG_LEVEL && val == 0) { + icu->ir[reg] = 0; + } + break; + case A_DTCER ... A_DTCER + 0xff: + icu->dtcer[reg] = val & R_DTCER_DTCE_MASK; + qemu_log_mask(LOG_UNIMP, + "rx_icu: DTC not implemented\n"); + break; + case A_IER ... A_IER + 0x1f: + icu->ier[reg] = val; + break; + case A_SWINTR: + if (val & R_SWINTR_SWINT_MASK) { + qemu_irq_pulse(icu->_swi); + } + break; + case A_FIR: + icu->fir = val & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK); + break; + case A_IPR ... A_IPR + 0x8f: + icu->ipr[reg] = val & R_IPR_IPR_MASK; + break; + case A_DMRSR: + case A_DMRSR + 4: + case A_DMRSR + 8: + case A_DMRSR + 12: + icu->dmasr[reg >> 2] = val; + qemu_log_mask(LOG_UNIMP, + "rx_icu: DMAC not implemented\n"); + break; + case A_IRQCR ... A_IRQCR + 0x1f: + icu->src[64 + reg].sense = val >> R_IRQCR_IRQMD_SHIFT; + break; + case A_NMICLR: + break; + case A_NMIER: + icu->nmier |= val & (R_NMIER_NMIEN_MASK | + R_NMIER_LVDEN_MASK | + R_NMIER_OSTEN_MASK); + break; + case A_NMICR: + if ((icu->nmier & R_NMIER_NMIEN_MASK) == 0) { + icu->nmicr = val & R_NMICR_NMIMD_MASK; + } + break; + default: + qemu_log_mask(LOG_UNIMP, "rx_icu: Register 0x%" HWADDR_PRIX + " not implemented\n", addr); + break; + } +} + +static const MemoryRegionOps icu_ops = { + .write = icu_write, + .read = icu_read, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .max_access_size = 2, + }, +}; + +static void rxicu_realize(DeviceState *dev, Error **errp) +{ + RXICUState *icu = RXICU(dev); + int i, j; + + if (icu->init_sense == NULL) { + qemu_log_mask(LOG_GUEST_ERROR, + "rx_icu: trigger-level property must be set."); + return; + } + for (i = j = 0; i < NR_IRQS; i++) { + if (icu->init_sense[j] == i) { + icu->src[i].sense = TRG_LEVEL; + if (j < icu->nr_sense) { + j++; + } + } else { + icu->src[i].sense = TRG_PEDGE; + } + } + icu->req_irq = -1; +} + +static void rxicu_init(Object *obj) +{ + SysBusDevice *d = SYS_BUS_DEVICE(obj); + RXICUState *icu = RXICU(obj); + + memory_region_init_io(&icu->memory, OBJECT(icu), &icu_ops, + icu, "rx-icu", 0x600); + sysbus_init_mmio(d, &icu->memory); + + qdev_init_gpio_in(DEVICE(d), rxicu_set_irq, NR_IRQS); + qdev_init_gpio_in_named(DEVICE(d), rxicu_ack_irq, "ack", 1); + sysbus_init_irq(d, &icu->_irq); + sysbus_init_irq(d, &icu->_fir); + sysbus_init_irq(d, &icu->_swi); +} + +static void rxicu_fini(Object *obj) +{ + RXICUState *icu = RXICU(obj); + g_free(icu->map); + g_free(icu->init_sense); +} + +static const VMStateDescription vmstate_rxicu = { + .name = "rx-icu", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static Property rxicu_properties[] = { + DEFINE_PROP_ARRAY("ipr-map", RXICUState, nr_irqs, map, + qdev_prop_uint32, uint32_t), + DEFINE_PROP_ARRAY("trigger-level", RXICUState, nr_sense, init_sense, + qdev_prop_uint32, uint32_t), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rxicu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = rxicu_realize; + dc->props = rxicu_properties; + dc->vmsd = &vmstate_rxicu; +} + +static const TypeInfo rxicu_info = { + .name = TYPE_RXICU, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(RXICUState), + .instance_init = rxicu_init, + .instance_finalize = rxicu_fini, + .class_init = rxicu_class_init, +}; + +static void rxicu_register_types(void) +{ + type_register_static(&rxicu_info); +} + +type_init(rxicu_register_types) diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig index 5347f8412c..67e9d97464 100644 --- a/hw/intc/Kconfig +++ b/hw/intc/Kconfig @@ -58,3 +58,6 @@ config S390_FLIC_KVM config OMPIC bool + +config RX_ICU + bool diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs index 03019b9a03..16bdc7e427 100644 --- a/hw/intc/Makefile.objs +++ b/hw/intc/Makefile.objs @@ -49,3 +49,4 @@ obj-$(CONFIG_ARM_GIC) += arm_gicv3_cpuif.o obj-$(CONFIG_MIPS_CPS) += mips_gic.o obj-$(CONFIG_NIOS2) += nios2_iic.o obj-$(CONFIG_OMPIC) += ompic.o +obj-$(CONFIG_RX) += rx_icu.o From patchwork Tue Jun 18 14:11:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117956 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45SqzR6cqqz9s3l for ; Wed, 19 Jun 2019 00:22:27 +1000 (AEST) Received: from localhost ([::1]:58486 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdF0D-0004VO-Vz for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:22:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60239) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEq1-0002zM-G9 for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEpq-00081X-3w for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:47 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:57067) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEpl-0007uh-IC for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:39 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id 8C0994A2E6; Tue, 18 Jun 2019 23:11:35 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 3BA9D240086; Tue, 18 Jun 2019 23:11:35 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:11:07 +0900 Message-Id: <20190618141118.52955-29-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.15 Subject: [Qemu-devel] [PATCH v21 15/21] hw/rx: RX Target hardware definition X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, richard.henderson@linaro.org, Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" rx62n - RX62N cpu. rx-virt - RX QEMU virtual target. v21 changes. rx_load_image move to rx-virt.c Signed-off-by: Yoshinori Sato Message-Id: <20190616142836.10614-17-ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20190607091116.49044-9-ysato@users.sourceforge.jp> Signed-off-by: Richard Henderson [PMD: Use TYPE_RX62N_CPU, use #define for RX62N_NR_TMR/CMT/SCI, renamed CPU -> MCU, device -> microcontroller] Signed-off-by: Philippe Mathieu-Daudé --- v19: Fixed typo (Peter Maydell) Signed-off-by: Yoshinori Sato --- include/hw/rx/rx.h | 7 ++ include/hw/rx/rx62n.h | 91 +++++++++++++++++++ hw/rx/rx-virt.c | 127 +++++++++++++++++++++++++++ hw/rx/rx62n.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++ hw/rx/Kconfig | 14 +++ hw/rx/Makefile.objs | 2 + 6 files changed, 479 insertions(+) create mode 100644 include/hw/rx/rx.h create mode 100644 include/hw/rx/rx62n.h create mode 100644 hw/rx/rx-virt.c create mode 100644 hw/rx/rx62n.c create mode 100644 hw/rx/Kconfig create mode 100644 hw/rx/Makefile.objs diff --git a/include/hw/rx/rx.h b/include/hw/rx/rx.h new file mode 100644 index 0000000000..ff5924b81f --- /dev/null +++ b/include/hw/rx/rx.h @@ -0,0 +1,7 @@ +#ifndef QEMU_RX_H +#define QEMU_RX_H +/* Definitions for RX board emulation. */ + +#include "target/rx/cpu-qom.h" + +#endif diff --git a/include/hw/rx/rx62n.h b/include/hw/rx/rx62n.h new file mode 100644 index 0000000000..97ea8ddb8e --- /dev/null +++ b/include/hw/rx/rx62n.h @@ -0,0 +1,91 @@ +/* + * RX62N MCU Object + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef HW_RX_RX62N_H +#define HW_RX_RX62N_H + +#include "hw/sysbus.h" +#include "hw/intc/rx_icu.h" +#include "hw/timer/renesas_tmr.h" +#include "hw/timer/renesas_cmt.h" +#include "hw/char/renesas_sci.h" +#include "target/rx/cpu.h" +#include "qemu/units.h" + +#define TYPE_RX62N "rx62n" +#define RX62N(obj) OBJECT_CHECK(RX62NState, (obj), TYPE_RX62N) + +#define RX62N_NR_TMR 2 +#define RX62N_NR_CMT 2 +#define RX62N_NR_SCI 6 + +typedef struct RX62NState { + SysBusDevice parent_obj; + + RXCPU cpu; + RXICUState icu; + RTMRState tmr[RX62N_NR_TMR]; + RCMTState cmt[RX62N_NR_CMT]; + RSCIState sci[RX62N_NR_SCI]; + + MemoryRegion *sysmem; + bool kernel; + + MemoryRegion iram; + MemoryRegion iomem1; + MemoryRegion d_flash; + MemoryRegion iomem2; + MemoryRegion iomem3; + MemoryRegion c_flash; + qemu_irq irq[NR_IRQS]; +} RX62NState; + +/* + * RX62N Peripheral Address + * See users manual section 5 + */ +#define RX62N_ICUBASE 0x00087000 +#define RX62N_TMRBASE 0x00088200 +#define RX62N_CMTBASE 0x00088000 +#define RX62N_SCIBASE 0x00088240 + +/* + * RX62N Peripheral IRQ + * See users manual section 11 + */ +#define RX62N_TMR_IRQBASE 174 +#define RX62N_CMT_IRQBASE 28 +#define RX62N_SCI_IRQBASE 214 + +/* + * RX62N Internal Memory + * It is the value of R5F562N8. + * Please change the size for R5F562N7. + */ +#define RX62N_IRAM_BASE 0x00000000 +#define RX62N_IRAM_SIZE (96 * KiB) +#define RX62N_DFLASH_BASE 0x00100000 +#define RX62N_DFLASH_SIZE (32 * KiB) +#define RX62N_CFLASH_BASE 0xfff80000 +#define RX62N_CFLASH_SIZE (512 * KiB) + +#define RX62N_PCLK (48 * 1000 * 1000) +#endif diff --git a/hw/rx/rx-virt.c b/hw/rx/rx-virt.c new file mode 100644 index 0000000000..4cfe2e3123 --- /dev/null +++ b/hw/rx/rx-virt.c @@ -0,0 +1,127 @@ +/* + * RX QEMU virtual platform + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "cpu.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/loader.h" +#include "hw/rx/rx62n.h" +#include "sysemu/sysemu.h" +#include "sysemu/qtest.h" +#include "sysemu/device_tree.h" +#include "hw/boards.h" + +/* Same address of GDB integrated simulator */ +#define SDRAM_BASE 0x01000000 + +static void rx_load_image(RXCPU *cpu, const char *filename, + uint32_t start, uint32_t size) +{ + static uint32_t extable[32]; + long kernel_size; + int i; + + kernel_size = load_image_targphys(filename, start, size); + if (kernel_size < 0) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", filename); + exit(1); + } + cpu->env.pc = start; + + /* setup exception trap trampoline */ + /* linux kernel only works little-endian mode */ + for (i = 0; i < ARRAY_SIZE(extable); i++) { + extable[i] = cpu_to_le32(0x10 + i * 4); + } + rom_add_blob_fixed("extable", extable, sizeof(extable), 0xffffff80); +} + +static void rxvirt_init(MachineState *machine) +{ + RX62NState *s = g_new(RX62NState, 1); + MemoryRegion *sysmem = get_system_memory(); + MemoryRegion *sdram = g_new(MemoryRegion, 1); + const char *kernel_filename = machine->kernel_filename; + const char *dtb_filename = machine->dtb; + void *dtb = NULL; + int dtb_size; + + /* Allocate memory space */ + memory_region_init_ram(sdram, NULL, "sdram", 16 * MiB, + &error_fatal); + memory_region_add_subregion(sysmem, SDRAM_BASE, sdram); + + /* Initialize MCU */ + object_initialize_child(OBJECT(machine), "mcu", s, + sizeof(RX62NState), TYPE_RX62N, + &error_fatal, NULL); + object_property_set_link(OBJECT(s), OBJECT(get_system_memory()), + "memory", &error_abort); + object_property_set_bool(OBJECT(s), kernel_filename != NULL, + "load-kernel", &error_abort); + object_property_set_bool(OBJECT(s), true, "realized", &error_abort); + + /* Load kernel and dtb */ + if (kernel_filename) { + rx_load_image(RXCPU(first_cpu), kernel_filename, + SDRAM_BASE + 8 * MiB, 8 * MiB); + if (dtb_filename) { + dtb = load_device_tree(dtb_filename, &dtb_size); + if (dtb == NULL) { + fprintf(stderr, "Couldn't open dtb file %s\n", dtb_filename); + exit(1); + } + if (machine->kernel_cmdline && + qemu_fdt_setprop_string(dtb, "/chosen", "bootargs", + machine->kernel_cmdline) < 0) { + fprintf(stderr, "couldn't set /chosen/bootargs\n"); + exit(1); + } + rom_add_blob_fixed("dtb", dtb, dtb_size, + SDRAM_BASE + 16 * MiB - dtb_size); + /* Set dtb address to R1 */ + RXCPU(first_cpu)->env.regs[1] = 0x02000000 - dtb_size; + } + } +} + +static void rxvirt_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "RX QEMU Virtual Target"; + mc->init = rxvirt_init; + mc->is_default = 1; + mc->default_cpu_type = TYPE_RX62N_CPU; +} + +static const TypeInfo rxvirt_type = { + .name = MACHINE_TYPE_NAME("rx-virt"), + .parent = TYPE_MACHINE, + .class_init = rxvirt_class_init, +}; + +static void rxvirt_machine_init(void) +{ + type_register_static(&rxvirt_type); +} + +type_init(rxvirt_machine_init) diff --git a/hw/rx/rx62n.c b/hw/rx/rx62n.c new file mode 100644 index 0000000000..74d2fd0ee3 --- /dev/null +++ b/hw/rx/rx62n.c @@ -0,0 +1,238 @@ +/* + * RX62N Microcontroller + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/rx/rx62n.h" +#include "hw/loader.h" +#include "hw/sysbus.h" +#include "sysemu/sysemu.h" +#include "cpu.h" + +/* + * IRQ -> IPR mapping table + * 0x00 - 0x91: IPR no (IPR00 to IPR91) + * 0xff: IPR not assigned + * See "11.3.1 Interrupt Vector Table" in hardware manual. + */ +static const int ipr_table[NR_IRQS] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 15 */ + 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x02, + 0xff, 0xff, 0xff, 0x03, 0x04, 0x05, 0x06, 0x07, /* 31 */ + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x14, 0x14, 0x14, /* 47 */ + 0x15, 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1d, 0x1e, 0x1f, /* 63 */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 79 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x3a, 0x3b, 0x3c, 0xff, 0xff, 0xff, /* 95 */ + 0x40, 0xff, 0x44, 0x45, 0xff, 0xff, 0x48, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 111 */ + 0xff, 0xff, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52, + 0x52, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, /* 127 */ + 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, 0x59, 0x59, + 0x59, 0x59, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, /* 143 */ + 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, + 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x62, /* 159 */ + 0x62, 0x63, 0x64, 0x64, 0x64, 0x64, 0x65, 0x66, + 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, /* 175 */ + 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, + 0x6b, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 191 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x71, + 0x72, 0x73, 0x74, 0x75, 0xff, 0xff, 0xff, 0xff, /* 207 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, + 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, /* 223 */ + 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0xff, 0xff, + 0xff, 0xff, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, /* 239 */ + 0x86, 0x86, 0xff, 0xff, 0xff, 0xff, 0x88, 0x89, + 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, /* 255 */ +}; + +/* + * Level triggerd IRQ list + * Not listed IRQ is Edge trigger. + * See "11.3.1 Interrupt Vector Table" in hardware manual. + */ +static const uint32_t levelirq[] = { + 16, 21, 32, 44, 47, 48, 51, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 90, 91, 170, 171, 172, 173, 214, + 217, 218, 221, 222, 225, 226, 229, 234, 237, 238, + 241, 246, 249, 250, 253, +}; + +static void register_icu(RX62NState *s) +{ + int i; + SysBusDevice *icu; + + object_initialize_child(OBJECT(s), "icu", &s->icu, sizeof(RXICUState), + TYPE_RXICU, &error_abort, NULL); + + icu = SYS_BUS_DEVICE(&s->icu); + sysbus_mmio_map(SYS_BUS_DEVICE(icu), 0, RX62N_ICUBASE); + qdev_prop_set_uint32(DEVICE(icu), "len-ipr-map", NR_IRQS); + for (i = 0; i < NR_IRQS; i++) { + char propname[32]; + snprintf(propname, sizeof(propname), "ipr-map[%d]", i); + qdev_prop_set_uint32(DEVICE(icu), propname, ipr_table[i]); + } + qdev_prop_set_uint32(DEVICE(icu), "len-trigger-level", + ARRAY_SIZE(levelirq)); + for (i = 0; i < ARRAY_SIZE(levelirq); i++) { + char propname[32]; + snprintf(propname, sizeof(propname), "trigger-level[%d]", i); + qdev_prop_set_uint32(DEVICE(icu), propname, levelirq[i]); + } + + for (i = 0; i < NR_IRQS; i++) { + s->irq[i] = qdev_get_gpio_in(DEVICE(icu), i); + } + + qdev_init_nofail(DEVICE(icu)); + sysbus_connect_irq(icu, 0, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_IRQ)); + sysbus_connect_irq(icu, 1, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_FIR)); + sysbus_connect_irq(icu, 2, s->irq[SWI]); + +} + +static void register_tmr(RX62NState *s, int unit) +{ + SysBusDevice *tmr; + int i, irqbase; + + object_initialize_child(OBJECT(s), "tmr[*]", &s->tmr[unit], + sizeof(RTMRState), TYPE_RENESAS_TMR, + &error_abort, NULL); + + tmr = SYS_BUS_DEVICE(&s->tmr[unit]); + sysbus_mmio_map(tmr, 0, RX62N_TMRBASE + unit * 0x10); + qdev_prop_set_uint64(DEVICE(tmr), "input-freq", RX62N_PCLK); + + qdev_init_nofail(DEVICE(tmr)); + irqbase = RX62N_TMR_IRQBASE + TMR_NR_IRQ * unit; + for (i = 0; i < TMR_NR_IRQ; i++) { + sysbus_connect_irq(tmr, i, s->irq[irqbase + i]); + } +} + +static void register_cmt(RX62NState *s, int unit) +{ + SysBusDevice *cmt; + int i, irqbase; + + object_initialize_child(OBJECT(s), "cmt[*]", &s->cmt[unit], + sizeof(RCMTState), TYPE_RENESAS_CMT, + &error_abort, NULL); + + cmt = SYS_BUS_DEVICE(&s->cmt[unit]); + sysbus_mmio_map(cmt, 0, RX62N_CMTBASE + unit * 0x10); + qdev_prop_set_uint64(DEVICE(cmt), "input-freq", RX62N_PCLK); + + qdev_init_nofail(DEVICE(cmt)); + irqbase = RX62N_CMT_IRQBASE + CMT_NR_IRQ * unit; + for (i = 0; i < CMT_NR_IRQ; i++) { + sysbus_connect_irq(cmt, i, s->irq[irqbase + i]); + } +} + +static void register_sci(RX62NState *s, int unit) +{ + SysBusDevice *sci; + int i, irqbase; + + object_initialize_child(OBJECT(s), "sci[*]", &s->sci[unit], + sizeof(RSCIState), TYPE_RENESAS_SCI, + &error_abort, NULL); + + sci = SYS_BUS_DEVICE(&s->sci[unit]); + sysbus_mmio_map(sci, 0, RX62N_SCIBASE + unit * 0x08); + qdev_prop_set_chr(DEVICE(sci), "chardev", serial_hd(unit)); + qdev_prop_set_uint64(DEVICE(sci), "input-freq", RX62N_PCLK); + + qdev_init_nofail(DEVICE(sci)); + irqbase = RX62N_SCI_IRQBASE + SCI_NR_IRQ * unit; + for (i = 0; i < SCI_NR_IRQ; i++) { + sysbus_connect_irq(sci, i, s->irq[irqbase + i]); + } +} + +static void rx62n_realize(DeviceState *dev, Error **errp) +{ + RX62NState *s = RX62N(dev); + + memory_region_init_ram(&s->iram, NULL, "iram", RX62N_IRAM_SIZE, errp); + memory_region_add_subregion(s->sysmem, RX62N_IRAM_BASE, &s->iram); + memory_region_init_rom(&s->d_flash, NULL, "dataflash", + RX62N_DFLASH_SIZE, errp); + memory_region_add_subregion(s->sysmem, RX62N_DFLASH_BASE, &s->d_flash); + memory_region_init_rom(&s->c_flash, NULL, "codeflash", + RX62N_CFLASH_SIZE, errp); + memory_region_add_subregion(s->sysmem, RX62N_CFLASH_BASE, &s->c_flash); + if (!s->kernel) { + rom_add_file_fixed(bios_name, RX62N_CFLASH_BASE, 0); + } + + /* Initialize CPU */ + object_initialize_child(OBJECT(s), "cpu", &s->cpu, sizeof(RXCPU), + TYPE_RX62N_CPU, errp, NULL); + object_property_set_bool(OBJECT(&s->cpu), true, "realized", errp); + + register_icu(s); + s->cpu.env.ack = qdev_get_gpio_in_named(DEVICE(&s->icu), "ack", 0); + register_tmr(s, 0); + register_tmr(s, 1); + register_cmt(s, 0); + register_cmt(s, 1); + register_sci(s, 0); +} + +static Property rx62n_properties[] = { + DEFINE_PROP_LINK("memory", RX62NState, sysmem, TYPE_MEMORY_REGION, + MemoryRegion *), + DEFINE_PROP_BOOL("load-kernel", RX62NState, kernel, false), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rx62n_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = rx62n_realize; + dc->props = rx62n_properties; +} + +static const TypeInfo rx62n_info = { + .name = TYPE_RX62N, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(RX62NState), + .class_init = rx62n_class_init, +}; + +static void rx62n_register_types(void) +{ + type_register_static(&rx62n_info); +} + +type_init(rx62n_register_types) diff --git a/hw/rx/Kconfig b/hw/rx/Kconfig new file mode 100644 index 0000000000..a07490a65e --- /dev/null +++ b/hw/rx/Kconfig @@ -0,0 +1,14 @@ +config RX + bool + +config RX62N + bool + select RX + select RX_ICU + select RENESAS_TMR8 + select RENESAS_CMT + select RENESAS_SCI + +config RX_VIRT + bool + select RX62N diff --git a/hw/rx/Makefile.objs b/hw/rx/Makefile.objs new file mode 100644 index 0000000000..63f8be0e82 --- /dev/null +++ b/hw/rx/Makefile.objs @@ -0,0 +1,2 @@ +obj-$(CONFIG_RX62N) += rx62n.o +obj-$(CONFIG_RX_VIRT) += rx-virt.o From patchwork Tue Jun 18 14:11:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1118001 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45Srf66phrz9sBr for ; Wed, 19 Jun 2019 00:52:27 +1000 (AEST) Received: from localhost ([::1]:58656 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdFTE-0003bk-KE for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:52:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60498) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEqL-00035G-Fq for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEqE-0008Uz-9g for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:13 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:57071) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEqA-0007vP-SA for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:05 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id 31C014A2EA; Tue, 18 Jun 2019 23:11:36 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id D918D240086; Tue, 18 Jun 2019 23:11:35 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:11:09 +0900 Message-Id: <20190618141118.52955-31-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.15 Subject: [Qemu-devel] [PATCH v21 16/21] hw/char: RX62N serial communication interface (SCI) X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, richard.henderson@linaro.org, Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This module supported only non FIFO type. Hardware manual. https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej0140_rx62n.pdf Signed-off-by: Yoshinori Sato Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20190607091116.49044-8-ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- include/hw/char/renesas_sci.h | 45 ++++++ hw/char/renesas_sci.c | 340 ++++++++++++++++++++++++++++++++++++++++++ hw/char/Kconfig | 3 + hw/char/Makefile.objs | 1 + 4 files changed, 389 insertions(+) create mode 100644 include/hw/char/renesas_sci.h create mode 100644 hw/char/renesas_sci.c diff --git a/include/hw/char/renesas_sci.h b/include/hw/char/renesas_sci.h new file mode 100644 index 0000000000..50d1336944 --- /dev/null +++ b/include/hw/char/renesas_sci.h @@ -0,0 +1,45 @@ +/* + * Renesas Serial Communication Interface + * + * Copyright (c) 2018 Yoshinori Sato + * + * This code is licensed under the GPL version 2 or later. + * + */ + +#include "chardev/char-fe.h" +#include "qemu/timer.h" +#include "hw/sysbus.h" + +#define TYPE_RENESAS_SCI "renesas-sci" +#define RSCI(obj) OBJECT_CHECK(RSCIState, (obj), TYPE_RENESAS_SCI) + +enum { + ERI = 0, + RXI = 1, + TXI = 2, + TEI = 3, + SCI_NR_IRQ = 4, +}; + +typedef struct { + SysBusDevice parent_obj; + MemoryRegion memory; + + uint8_t smr; + uint8_t brr; + uint8_t scr; + uint8_t tdr; + uint8_t ssr; + uint8_t rdr; + uint8_t scmr; + uint8_t semr; + + uint8_t read_ssr; + int64_t trtime; + int64_t rx_next; + QEMUTimer *timer; + CharBackend chr; + uint64_t input_freq; + qemu_irq irq[SCI_NR_IRQ]; +} RSCIState; diff --git a/hw/char/renesas_sci.c b/hw/char/renesas_sci.c new file mode 100644 index 0000000000..6298cbf43a --- /dev/null +++ b/hw/char/renesas_sci.c @@ -0,0 +1,340 @@ +/* + * Renesas Serial Communication Interface + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "cpu.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/char/renesas_sci.h" +#include "qemu/error-report.h" + +/* SCI register map */ +REG8(SMR, 0) + FIELD(SMR, CKS, 0, 2) + FIELD(SMR, MP, 2, 1) + FIELD(SMR, STOP, 3, 1) + FIELD(SMR, PM, 4, 1) + FIELD(SMR, PE, 5, 1) + FIELD(SMR, CHR, 6, 1) + FIELD(SMR, CM, 7, 1) +REG8(BRR, 1) +REG8(SCR, 2) + FIELD(SCR, CKE, 0, 2) + FIELD(SCR, TEIE, 2, 1) + FIELD(SCR, MPIE, 3, 1) + FIELD(SCR, RE, 4, 1) + FIELD(SCR, TE, 5, 1) + FIELD(SCR, RIE, 6, 1) + FIELD(SCR, TIE, 7, 1) +REG8(TDR, 3) +REG8(SSR, 4) + FIELD(SSR, MPBT, 0, 1) + FIELD(SSR, MPB, 1, 1) + FIELD(SSR, TEND, 2, 1) + FIELD(SSR, ERR, 3, 3) + FIELD(SSR, PER, 3, 1) + FIELD(SSR, FER, 4, 1) + FIELD(SSR, ORER, 5, 1) + FIELD(SSR, RDRF, 6, 1) + FIELD(SSR, TDRE, 7, 1) +REG8(RDR, 5) +REG8(SCMR, 6) + FIELD(SCMR, SMIF, 0, 1) + FIELD(SCMR, SINV, 2, 1) + FIELD(SCMR, SDIR, 3, 1) + FIELD(SCMR, BCP2, 7, 1) +REG8(SEMR, 7) + FIELD(SEMR, ACS0, 0, 1) + FIELD(SEMR, ABCS, 4, 1) + +static int can_receive(void *opaque) +{ + RSCIState *sci = RSCI(opaque); + if (sci->rx_next > qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) { + return 0; + } else { + return FIELD_EX8(sci->scr, SCR, RE); + } +} + +static void receive(void *opaque, const uint8_t *buf, int size) +{ + RSCIState *sci = RSCI(opaque); + sci->rx_next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + sci->trtime; + if (FIELD_EX8(sci->ssr, SSR, RDRF) || size > 1) { + sci->ssr = FIELD_DP8(sci->ssr, SSR, ORER, 1); + if (FIELD_EX8(sci->scr, SCR, RIE)) { + qemu_set_irq(sci->irq[ERI], 1); + } + } else { + sci->rdr = buf[0]; + sci->ssr = FIELD_DP8(sci->ssr, SSR, RDRF, 1); + if (FIELD_EX8(sci->scr, SCR, RIE)) { + qemu_irq_pulse(sci->irq[RXI]); + } + } +} + +static void send_byte(RSCIState *sci) +{ + if (qemu_chr_fe_backend_connected(&sci->chr)) { + qemu_chr_fe_write_all(&sci->chr, &sci->tdr, 1); + } + timer_mod(sci->timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + sci->trtime); + sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 0); + sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 1); + qemu_set_irq(sci->irq[TEI], 0); + if (FIELD_EX8(sci->scr, SCR, TIE)) { + qemu_irq_pulse(sci->irq[TXI]); + } +} + +static void txend(void *opaque) +{ + RSCIState *sci = RSCI(opaque); + if (!FIELD_EX8(sci->ssr, SSR, TDRE)) { + send_byte(sci); + } else { + sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 1); + if (FIELD_EX8(sci->scr, SCR, TEIE)) { + qemu_set_irq(sci->irq[TEI], 1); + } + } +} + +static void update_trtime(RSCIState *sci) +{ + /* char per bits */ + sci->trtime = 8 - FIELD_EX8(sci->smr, SMR, CHR); + sci->trtime += FIELD_EX8(sci->smr, SMR, PE); + sci->trtime += FIELD_EX8(sci->smr, SMR, STOP) + 1; + /* x bit transmit time (32 * divrate * brr) / base freq */ + sci->trtime *= 32 * sci->brr; + sci->trtime *= 1 << (2 * FIELD_EX8(sci->smr, SMR, CKS)); + sci->trtime *= NANOSECONDS_PER_SECOND; + sci->trtime /= sci->input_freq; +} + +#define IS_TR_ENABLED(scr) \ + (FIELD_EX8(scr, SCR, TE) || FIELD_EX8(scr, SCR, RE)) + +static void sci_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) +{ + hwaddr offset = addr & 0x07; + RSCIState *sci = RSCI(opaque); + + switch (offset) { + case A_SMR: + if (!IS_TR_ENABLED(sci->scr)) { + sci->smr = val; + update_trtime(sci); + } + break; + case A_BRR: + if (!IS_TR_ENABLED(sci->scr)) { + sci->brr = val; + update_trtime(sci); + } + break; + case A_SCR: + sci->scr = val; + if (FIELD_EX8(sci->scr, SCR, TE)) { + sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 1); + sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 1); + if (FIELD_EX8(sci->scr, SCR, TIE)) { + qemu_irq_pulse(sci->irq[TXI]); + } + } + if (!FIELD_EX8(sci->scr, SCR, TEIE)) { + qemu_set_irq(sci->irq[TEI], 0); + } + if (!FIELD_EX8(sci->scr, SCR, RIE)) { + qemu_set_irq(sci->irq[ERI], 0); + } + break; + case A_TDR: + sci->tdr = val; + if (FIELD_EX8(sci->ssr, SSR, TEND)) { + send_byte(sci); + } else { + sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 0); + } + break; + case A_SSR: + sci->ssr = FIELD_DP8(sci->ssr, SSR, MPBT, + FIELD_EX8(val, SSR, MPBT)); + sci->ssr = FIELD_DP8(sci->ssr, SSR, ERR, + FIELD_EX8(val, SSR, ERR) & 0x07); + if (FIELD_EX8(sci->read_ssr, SSR, ERR) && + FIELD_EX8(sci->ssr, SSR, ERR) == 0) { + qemu_set_irq(sci->irq[ERI], 0); + } + break; + case A_RDR: + qemu_log_mask(LOG_GUEST_ERROR, "reneas_sci: RDR is read only.\n"); + break; + case A_SCMR: + sci->scmr = val; break; + case A_SEMR: /* SEMR */ + sci->semr = val; break; + default: + qemu_log_mask(LOG_UNIMP, "renesas_sci: Register 0x%" HWADDR_PRIX + " not implemented\n", offset); + } +} + +static uint64_t sci_read(void *opaque, hwaddr addr, unsigned size) +{ + hwaddr offset = addr & 0x07; + RSCIState *sci = RSCI(opaque); + + switch (offset) { + case A_SMR: + return sci->smr; + case A_BRR: + return sci->brr; + case A_SCR: + return sci->scr; + case A_TDR: + return sci->tdr; + case A_SSR: + sci->read_ssr = sci->ssr; + return sci->ssr; + case A_RDR: + sci->ssr = FIELD_DP8(sci->ssr, SSR, RDRF, 0); + return sci->rdr; + case A_SCMR: + return sci->scmr; + case A_SEMR: + return sci->semr; + default: + qemu_log_mask(LOG_UNIMP, "renesas_sci: Register 0x%" HWADDR_PRIX + " not implemented.\n", offset); + } + return UINT64_MAX; +} + +static const MemoryRegionOps sci_ops = { + .write = sci_write, + .read = sci_read, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .max_access_size = 1, + }, +}; + +static void rsci_reset(DeviceState *dev) +{ + RSCIState *sci = RSCI(dev); + sci->smr = sci->scr = 0x00; + sci->brr = 0xff; + sci->tdr = 0xff; + sci->rdr = 0x00; + sci->ssr = 0x84; + sci->scmr = 0x00; + sci->semr = 0x00; + sci->rx_next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +} + +static void sci_event(void *opaque, int event) +{ + RSCIState *sci = RSCI(opaque); + if (event == CHR_EVENT_BREAK) { + sci->ssr = FIELD_DP8(sci->ssr, SSR, FER, 1); + if (FIELD_EX8(sci->scr, SCR, RIE)) { + qemu_set_irq(sci->irq[ERI], 1); + } + } +} + +static void rsci_realize(DeviceState *dev, Error **errp) +{ + RSCIState *sci = RSCI(dev); + + if (sci->input_freq == 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "renesas_sci: input-freq property must be set."); + return; + } + qemu_chr_fe_set_handlers(&sci->chr, can_receive, receive, + sci_event, NULL, sci, NULL, true); +} + +static void rsci_init(Object *obj) +{ + SysBusDevice *d = SYS_BUS_DEVICE(obj); + RSCIState *sci = RSCI(obj); + int i; + + memory_region_init_io(&sci->memory, OBJECT(sci), &sci_ops, + sci, "renesas-sci", 0x8); + sysbus_init_mmio(d, &sci->memory); + + for (i = 0; i < SCI_NR_IRQ; i++) { + sysbus_init_irq(d, &sci->irq[i]); + } + sci->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, txend, sci); +} + +static const VMStateDescription vmstate_rcmt = { + .name = "renesas-sci", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static Property rsci_properties[] = { + DEFINE_PROP_UINT64("input-freq", RSCIState, input_freq, 0), + DEFINE_PROP_CHR("chardev", RSCIState, chr), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rsci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = rsci_realize; + dc->props = rsci_properties; + dc->vmsd = &vmstate_rcmt; + dc->reset = rsci_reset; +} + +static const TypeInfo rsci_info = { + .name = TYPE_RENESAS_SCI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(RSCIState), + .instance_init = rsci_init, + .class_init = rsci_class_init, +}; + +static void rsci_register_types(void) +{ + type_register_static(&rsci_info); +} + +type_init(rsci_register_types) diff --git a/hw/char/Kconfig b/hw/char/Kconfig index 40e7a8b8bb..874627520c 100644 --- a/hw/char/Kconfig +++ b/hw/char/Kconfig @@ -46,3 +46,6 @@ config SCLPCONSOLE config TERMINAL3270 bool + +config RENESAS_SCI + bool diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs index 02d8a66925..4472d563b5 100644 --- a/hw/char/Makefile.objs +++ b/hw/char/Makefile.objs @@ -21,6 +21,7 @@ obj-$(CONFIG_PSERIES) += spapr_vty.o obj-$(CONFIG_DIGIC) += digic-uart.o obj-$(CONFIG_STM32F2XX_USART) += stm32f2xx_usart.o obj-$(CONFIG_RASPI) += bcm2835_aux.o +obj-$(CONFIG_RENESAS_SCI) += renesas_sci.o common-obj-$(CONFIG_CMSDK_APB_UART) += cmsdk-apb-uart.o common-obj-$(CONFIG_ETRAXFS) += etraxfs_ser.o From patchwork Tue Jun 18 14:11:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117989 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45SrWm6Qz0z9sBp for ; Wed, 19 Jun 2019 00:47:00 +1000 (AEST) Received: from localhost ([::1]:58634 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdFNy-0008CN-Gu for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:46:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60375) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEqF-00032N-NC for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEqA-0008O5-75 for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:07 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:57079) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEq6-0007xc-Q4 for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:11:59 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id 085334A2ED; Tue, 18 Jun 2019 23:11:38 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 84732240086; Tue, 18 Jun 2019 23:11:37 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:11:12 +0900 Message-Id: <20190618141118.52955-34-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.15 Subject: [Qemu-devel] [PATCH v21 17/21] hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, richard.henderson@linaro.org, =?utf-8?q?Phil?= =?utf-8?q?ippe_Mathieu-Daud=C3=A9?= , Yoshinori Sato , imammedo@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Philippe Mathieu-Daudé While the VIRT machine can use different microcontrollers, the RX62N microcontroller is tied to the RX62N CPU core. Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Yoshinori Sato --- hw/rx/rx-virt.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/rx/rx-virt.c b/hw/rx/rx-virt.c index 4cfe2e3123..9676a5e7bf 100644 --- a/hw/rx/rx-virt.c +++ b/hw/rx/rx-virt.c @@ -17,6 +17,7 @@ */ #include "qemu/osdep.h" +#include "qemu/error-report.h" #include "qapi/error.h" #include "qemu-common.h" #include "cpu.h" @@ -56,6 +57,7 @@ static void rx_load_image(RXCPU *cpu, const char *filename, static void rxvirt_init(MachineState *machine) { + MachineClass *mc = MACHINE_GET_CLASS(machine); RX62NState *s = g_new(RX62NState, 1); MemoryRegion *sysmem = get_system_memory(); MemoryRegion *sdram = g_new(MemoryRegion, 1); @@ -64,6 +66,12 @@ static void rxvirt_init(MachineState *machine) void *dtb = NULL; int dtb_size; + if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) { + error_report("This board can only be used with CPU %s", + mc->default_cpu_type); + exit(1); + } + /* Allocate memory space */ memory_region_init_ram(sdram, NULL, "sdram", 16 * MiB, &error_fatal); From patchwork Tue Jun 18 14:11:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117970 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45Sr800J4Cz9sNC for ; Wed, 19 Jun 2019 00:29:52 +1000 (AEST) Received: from localhost ([::1]:58534 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdF7O-0002WZ-3d for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:29:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60454) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEqJ-00033x-IP for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEqI-00009k-D1 for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:11 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:57067) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEqF-0007uh-Ri for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:09 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id A98A54A2EF; Tue, 18 Jun 2019 23:11:38 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 1D130240086; Tue, 18 Jun 2019 23:11:38 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:11:14 +0900 Message-Id: <20190618141118.52955-36-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.15 Subject: [Qemu-devel] [PATCH v21 18/21] qemu/bitops.h: Add extract8 and extract16 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, richard.henderson@linaro.org, Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Yoshinori Sato Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20190607091116.49044-10-ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- include/qemu/bitops.h | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h index 3f0926cf40..764f9d1ea0 100644 --- a/include/qemu/bitops.h +++ b/include/qemu/bitops.h @@ -301,6 +301,44 @@ static inline uint32_t extract32(uint32_t value, int start, int length) } /** + * extract8: + * @value: the value to extract the bit field from + * @start: the lowest bit in the bit field (numbered from 0) + * @length: the length of the bit field + * + * Extract from the 8 bit input @value the bit field specified by the + * @start and @length parameters, and return it. The bit field must + * lie entirely within the 8 bit word. It is valid to request that + * all 8 bits are returned (ie @length 8 and @start 0). + * + * Returns: the value of the bit field extracted from the input value. + */ +static inline uint8_t extract8(uint8_t value, int start, int length) +{ + assert(start >= 0 && length > 0 && length <= 8 - start); + return extract32(value, start, length); +} + +/** + * extract16: + * @value: the value to extract the bit field from + * @start: the lowest bit in the bit field (numbered from 0) + * @length: the length of the bit field + * + * Extract from the 16 bit input @value the bit field specified by the + * @start and @length parameters, and return it. The bit field must + * lie entirely within the 16 bit word. It is valid to request that + * all 16 bits are returned (ie @length 16 and @start 0). + * + * Returns: the value of the bit field extracted from the input value. + */ +static inline uint16_t extract16(uint16_t value, int start, int length) +{ + assert(start >= 0 && length > 0 && length <= 16 - start); + return extract32(value, start, length); +} + +/** * extract64: * @value: the value to extract the bit field from * @start: the lowest bit in the bit field (numbered from 0) From patchwork Tue Jun 18 14:11:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117999 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45SrdW5YN3z9sBr for ; Wed, 19 Jun 2019 00:51:59 +1000 (AEST) Received: from localhost ([::1]:58654 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdFSn-0002ek-RB for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:51:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60497) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEqL-00035F-Fq for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEqI-0000Ac-Tb for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:13 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:57065) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEqH-0007uf-JD for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:10 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id E60F74A2F2; Tue, 18 Jun 2019 23:11:38 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 9F044240085; Tue, 18 Jun 2019 23:11:38 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:11:15 +0900 Message-Id: <20190618141118.52955-37-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.15 Subject: [Qemu-devel] [PATCH v21 19/21] hw/registerfields.h: Add 8bit and 16bit register macros X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, richard.henderson@linaro.org, =?utf-8?q?Phil?= =?utf-8?q?ippe_Mathieu-Daud=C3=A9?= , Yoshinori Sato , imammedo@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Philippe Mathieu-Daudé Some RX peripheral using 8bit and 16bit registers. Added 8bit and 16bit APIs. Signed-off-by: Yoshinori Sato Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20190607091116.49044-11-ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson --- include/hw/registerfields.h | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/include/hw/registerfields.h b/include/hw/registerfields.h index 2659a58737..a0bb0654d6 100644 --- a/include/hw/registerfields.h +++ b/include/hw/registerfields.h @@ -22,6 +22,14 @@ enum { A_ ## reg = (addr) }; \ enum { R_ ## reg = (addr) / 4 }; +#define REG8(reg, addr) \ + enum { A_ ## reg = (addr) }; \ + enum { R_ ## reg = (addr) }; + +#define REG16(reg, addr) \ + enum { A_ ## reg = (addr) }; \ + enum { R_ ## reg = (addr) / 2 }; + /* Define SHIFT, LENGTH and MASK constants for a field within a register */ /* This macro will define R_FOO_BAR_MASK, R_FOO_BAR_SHIFT and R_FOO_BAR_LENGTH @@ -34,6 +42,12 @@ MAKE_64BIT_MASK(shift, length)}; /* Extract a field from a register */ +#define FIELD_EX8(storage, reg, field) \ + extract8((storage), R_ ## reg ## _ ## field ## _SHIFT, \ + R_ ## reg ## _ ## field ## _LENGTH) +#define FIELD_EX16(storage, reg, field) \ + extract16((storage), R_ ## reg ## _ ## field ## _SHIFT, \ + R_ ## reg ## _ ## field ## _LENGTH) #define FIELD_EX32(storage, reg, field) \ extract32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ R_ ## reg ## _ ## field ## _LENGTH) @@ -49,6 +63,22 @@ * Assigning values larger then the target field will result in * compilation warnings. */ +#define FIELD_DP8(storage, reg, field, val) ({ \ + struct { \ + unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \ + } v = { .v = val }; \ + uint8_t d; \ + d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ + R_ ## reg ## _ ## field ## _LENGTH, v.v); \ + d; }) +#define FIELD_DP16(storage, reg, field, val) ({ \ + struct { \ + unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \ + } v = { .v = val }; \ + uint16_t d; \ + d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ + R_ ## reg ## _ ## field ## _LENGTH, v.v); \ + d; }) #define FIELD_DP32(storage, reg, field, val) ({ \ struct { \ unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \ @@ -57,7 +87,7 @@ d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ R_ ## reg ## _ ## field ## _LENGTH, v.v); \ d; }) -#define FIELD_DP64(storage, reg, field, val) ({ \ +#define FIELD_DP64(storage, reg, field, val) ({ \ struct { \ unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \ } v = { .v = val }; \ From patchwork Tue Jun 18 14:11:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1118006 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45Srjj2FD4z9sNT for ; Wed, 19 Jun 2019 00:55:36 +1000 (AEST) Received: from localhost ([::1]:58672 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdFWI-0006sJ-VN for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:55:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60380) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEqF-00032P-Nq for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEqE-0008UZ-8c for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:07 -0400 Received: from mail01.asahi-net.or.jp ([202.224.55.13]:60272) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEqA-0007zA-Rp for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:04 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail01.asahi-net.or.jp (Postfix) with ESMTPA id 7F2A7126D9A; Tue, 18 Jun 2019 23:11:39 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 326CA240085; Tue, 18 Jun 2019 23:11:39 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:11:17 +0900 Message-Id: <20190618141118.52955-39-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.13 Subject: [Qemu-devel] [PATCH v21 20/21] Add rx-softmmu X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, imammedo@redhat.com, richard.henderson@linaro.org, Yoshinori Sato , philmd@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Tested-by: Philippe Mathieu-Daudé Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Yoshinori Sato Message-Id: <20190607091116.49044-17-ysato@users.sourceforge.jp> Signed-off-by: Richard Henderson pick ed65c02993 target/rx: Add RX to SysEmuTarget pick 01372568ae tests: Add rx to machine-none-test.c [PMD: Squashed patches from Richard Henderson modifying qapi/common.json and tests/machine-none-test.c] Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Yoshinori Sato --- configure | 8 ++++++++ default-configs/rx-softmmu.mak | 3 +++ qapi/common.json | 3 ++- include/exec/poison.h | 1 + include/sysemu/arch_init.h | 1 + arch_init.c | 2 ++ tests/machine-none-test.c | 1 + hw/Kconfig | 1 + 8 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 default-configs/rx-softmmu.mak diff --git a/configure b/configure index b091b82cb3..d6e16c58c3 100755 --- a/configure +++ b/configure @@ -7595,6 +7595,11 @@ case "$target_name" in gdb_xml_files="riscv-64bit-cpu.xml riscv-64bit-fpu.xml riscv-64bit-csr.xml" target_compiler=$cross_cc_riscv64 ;; + rx) + TARGET_ARCH=rx + bflt="yes" + target_compiler=$cross_cc_rx + ;; sh4|sh4eb) TARGET_ARCH=sh4 bflt="yes" @@ -7815,6 +7820,9 @@ for i in $ARCH $TARGET_BASE_ARCH ; do riscv*) disas_config "RISCV" ;; + rx) + disas_config "RX" + ;; s390*) disas_config "S390" ;; diff --git a/default-configs/rx-softmmu.mak b/default-configs/rx-softmmu.mak new file mode 100644 index 0000000000..a3eecefb11 --- /dev/null +++ b/default-configs/rx-softmmu.mak @@ -0,0 +1,3 @@ +# Default configuration for rx-softmmu + +CONFIG_RX_VIRT=y diff --git a/qapi/common.json b/qapi/common.json index 99d313ef3b..d0fc931159 100644 --- a/qapi/common.json +++ b/qapi/common.json @@ -183,6 +183,7 @@ # is true even for "qemu-system-x86_64". # # ppcemb: dropped in 3.1 +# rx: added in 4.1 # # Since: 3.0 ## @@ -190,6 +191,6 @@ 'data' : [ 'aarch64', 'alpha', 'arm', 'cris', 'hppa', 'i386', 'lm32', 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64', 'mips64el', 'mipsel', 'moxie', 'nios2', 'or1k', 'ppc', - 'ppc64', 'riscv32', 'riscv64', 's390x', 'sh4', + 'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4', 'sh4eb', 'sparc', 'sparc64', 'tricore', 'unicore32', 'x86_64', 'xtensa', 'xtensaeb' ] } diff --git a/include/exec/poison.h b/include/exec/poison.h index b862320fa6..c17911d859 100644 --- a/include/exec/poison.h +++ b/include/exec/poison.h @@ -26,6 +26,7 @@ #pragma GCC poison TARGET_PPC #pragma GCC poison TARGET_PPC64 #pragma GCC poison TARGET_ABI32 +#pragma GCC poison TARGET_RX #pragma GCC poison TARGET_S390X #pragma GCC poison TARGET_SH4 #pragma GCC poison TARGET_SPARC diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h index 10cbafe970..3f4f844f7b 100644 --- a/include/sysemu/arch_init.h +++ b/include/sysemu/arch_init.h @@ -25,6 +25,7 @@ enum { QEMU_ARCH_NIOS2 = (1 << 17), QEMU_ARCH_HPPA = (1 << 18), QEMU_ARCH_RISCV = (1 << 19), + QEMU_ARCH_RX = (1 << 20), }; extern const uint32_t arch_type; diff --git a/arch_init.c b/arch_init.c index 74b0708634..48d9b4c86f 100644 --- a/arch_init.c +++ b/arch_init.c @@ -73,6 +73,8 @@ int graphic_depth = 32; #define QEMU_ARCH QEMU_ARCH_PPC #elif defined(TARGET_RISCV) #define QEMU_ARCH QEMU_ARCH_RISCV +#elif defined(TARGET_RX) +#define QEMU_ARCH QEMU_ARCH_RX #elif defined(TARGET_S390X) #define QEMU_ARCH QEMU_ARCH_S390X #elif defined(TARGET_SH4) diff --git a/tests/machine-none-test.c b/tests/machine-none-test.c index 4c6d470798..80df277357 100644 --- a/tests/machine-none-test.c +++ b/tests/machine-none-test.c @@ -56,6 +56,7 @@ static struct arch2cpu cpus_map[] = { { "hppa", "hppa" }, { "riscv64", "rv64gcsu-v1.10.0" }, { "riscv32", "rv32gcsu-v1.9.1" }, + { "rx", "rx62n" }, }; static const char *get_cpu_model_by_arch(const char *arch) diff --git a/hw/Kconfig b/hw/Kconfig index 195f541e50..b0c7221240 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -54,6 +54,7 @@ source nios2/Kconfig source openrisc/Kconfig source ppc/Kconfig source riscv/Kconfig +source rx/Kconfig source s390x/Kconfig source sh4/Kconfig source sparc/Kconfig From patchwork Tue Jun 18 14:11:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 1117978 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45SrKZ6cQhz9s3C for ; Wed, 19 Jun 2019 00:38:10 +1000 (AEST) Received: from localhost ([::1]:58580 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdFFR-0000Nf-0l for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2019 10:38:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60378) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdEqF-00032O-NZ for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hdEqE-0008Up-9b for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:07 -0400 Received: from mail01.asahi-net.or.jp ([202.224.55.13]:60274) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hdEqA-0007zU-Sb for qemu-devel@nongnu.org; Tue, 18 Jun 2019 10:12:05 -0400 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.ablenetvps.ne.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail01.asahi-net.or.jp (Postfix) with ESMTPA id C1B3A126DA3; Tue, 18 Jun 2019 23:11:39 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 7814C240086; Tue, 18 Jun 2019 23:11:39 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2019 23:11:18 +0900 Message-Id: <20190618141118.52955-40-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190618141118.52955-1-ysato@users.sourceforge.jp> References: <20190618141118.52955-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.13 Subject: [Qemu-devel] [PATCH v21 21/21] BootLinuxConsoleTest: Test the RX-Virt machine X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, richard.henderson@linaro.org, =?utf-8?q?Phil?= =?utf-8?q?ippe_Mathieu-Daud=C3=A9?= , Yoshinori Sato , imammedo@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Philippe Mathieu-Daudé Add two tests for the rx-virt machine, based on the recommended test setup from Yoshinori Sato: https://lists.gnu.org/archive/html/qemu-devel/2019-05/msg03586.html - U-Boot prompt - Linux kernel with Sash shell These are very quick tests: $ avocado run -t arch:rx tests/acceptance/boot_linux_console.py JOB ID : 84a6ef01c0b87975ecbfcb31a920afd735753ace JOB LOG : /home/phil/avocado/job-results/job-2019-05-24T05.02-84a6ef0/job.log (1/2) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_rx_uboot: PASS (0.11 s) (2/2) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_rx_linux: PASS (0.45 s) RESULTS : PASS 2 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0 Tests can also be run with: $ avocado --show=console run -t arch:rx tests/acceptance/boot_linux_console.py console: U-Boot 2016.05-rc3-23705-ga1ef3c71cb-dirty (Feb 05 2019 - 21:56:06 +0900) console: Linux version 4.19.0+ (yo-satoh@yo-satoh-debian) (gcc version 9.0.0 20181105 (experimental) (GCC)) #137 Wed Feb 20 23:20:02 JST 2019 console: Built 1 zonelists, mobility grouping on. Total pages: 8128 ... console: SuperH (H)SCI(F) driver initialized console: 88240.serial: ttySC0 at MMIO 0x88240 (irq = 215, base_baud = 0) is a sci console: console [ttySC0] enabled console: 88248.serial: ttySC1 at MMIO 0x88248 (irq = 219, base_baud = 0) is a sci Signed-off-by: Philippe Mathieu-Daudé --- Based-on: 20190517045136.3509-1-richard.henderson@linaro.org "RX architecture support" Signed-off-by: Yoshinori Sato --- tests/acceptance/boot_linux_console.py | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py index 32159503e9..19aab894d1 100644 --- a/tests/acceptance/boot_linux_console.py +++ b/tests/acceptance/boot_linux_console.py @@ -354,3 +354,49 @@ class BootLinuxConsole(Test): self.vm.launch() console_pattern = 'Kernel command line: %s' % kernel_command_line self.wait_for_console_pattern(console_pattern) + + def test_rx_uboot(self): + """ + :avocado: tags=arch:rx + :avocado: tags=machine:rx-virt + :avocado: tags=endian:little + """ + uboot_url = ('https://acc.dl.osdn.jp/users/23/23888/u-boot.bin.gz') + uboot_hash = '9b78dbd43b40b2526848c0b1ce9de02c24f4dcdb' + uboot_path = self.fetch_asset(uboot_url, asset_hash=uboot_hash) + uboot_path = archive.uncompress(uboot_path, self.workdir) + + self.vm.set_machine('rx-virt') + self.vm.set_console() + self.vm.add_args('-bios', uboot_path, + '-no-reboot') + self.vm.launch() + uboot_version = 'U-Boot 2016.05-rc3-23705-ga1ef3c71cb-dirty' + self.wait_for_console_pattern(uboot_version) + gcc_version = 'rx-unknown-linux-gcc (GCC) 9.0.0 20181105 (experimental)' + # FIXME limit baudrate on chardev, else we type too fast + #self.exec_command_and_wait_for_pattern('version', gcc_version) + + def test_rx_linux(self): + """ + :avocado: tags=arch:rx + :avocado: tags=machine:rx-virt + :avocado: tags=endian:little + """ + dtb_url = ('https://acc.dl.osdn.jp/users/23/23887/rx-qemu.dtb') + dtb_hash = '7b4e4e2c71905da44e86ce47adee2210b026ac18' + dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash) + kernel_url = ('http://acc.dl.osdn.jp/users/23/23845/zImage') + kernel_hash = '39a81067f8d72faad90866ddfefa19165d68fc99' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.vm.set_machine('rx-virt') + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'earlycon' + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Sash command shell (version 1.1.1)') + self.exec_command_and_wait_for_pattern('printenv', + 'TERM=linux')