From nobody Sun May 5 10:44:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1558621394; cv=none; d=zoho.com; s=zohoarc; b=l47oCZH9Q4a71jVUYp2WaEHcI4n+Y0xBVvQGylsw/Ab+FmU5IFACqcswtRVIG8onGt7D8L5PhSvdZokBOkLvvRiVBZS69VGvDBsmdpy7ljCB/nZJIsJ8OAWgnduPPVcvZ+GcU2oz4xC0vCqncl8uJr6BK9CrBIp3bTOVodSNFOU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558621394; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=FI28Hqw//HjRHINjRmZtjboy1cNBGXKFtxi0q/FTEqs=; b=FUaEL2eSLakjNIaQIfEXNbMF8iHWU8NyXjglQuR35dIvEvijsAzQHPacYtI0pI/XdMlYDG01JeVJcGv3Sw1EKFtVbW2lPbXxwztxej1ctBe6lDAHxwN/5KOMTGlDxAiHqOCnCy0PkCmHTxeGwLSAMmp3Lrm2HujqCCxijbOAVbs= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1558621394587203.3416235292708; Thu, 23 May 2019 07:23:14 -0700 (PDT) Received: from localhost ([127.0.0.1]:37373 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hTocd-0001bL-Bq for importer@patchew.org; Thu, 23 May 2019 10:23:07 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46597) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToHd-0006Ir-9S for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hToHR-0004Of-E4 for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:25 -0400 Received: from mail-ua1-x92b.google.com ([2607:f8b0:4864:20::92b]:41227) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hToHP-0004Lq-8M for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:13 -0400 Received: by mail-ua1-x92b.google.com with SMTP id l14so2207709uah.8 for ; Thu, 23 May 2019 07:01:08 -0700 (PDT) Received: from localhost.localdomain (ip-173-130-215-183.orldfl.spcsdns.net. [173.130.215.183]) by smtp.gmail.com with ESMTPSA id v133sm1984166vkv.5.2019.05.23.07.01.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 May 2019 07:01:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FI28Hqw//HjRHINjRmZtjboy1cNBGXKFtxi0q/FTEqs=; b=Jym2emxrgKB4mDilzyDF58/YDDmF8MXBgnrgA+7NIxSkEuvv2vpUrDIJfr64RTlK7n PUfpjzUhILJGo+T2rrON8bwAx+7m2k6ZCzQzPWTdGCX6E+6CLEuGMsh64dlPRe3snj93 Y9PTWjF8aC7CEXolt+iKJfEXm7hdFmoS2fVvG2mAxqHOxprSqBVuwRMrqmJm0ELnXcnd MNU2Th2MdJTC+a0PrJHXFZpVd1138PQVphHQQzuNFghnYbOFKDapXe1pkU96u/Rvz0zo 7QBLITuxYPL9rGUBHXKWDDAYa92Z6o6tDQ1HGWmfc/BvuhZhVOVL8cLqGa/oWLHx6r/C 1iVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FI28Hqw//HjRHINjRmZtjboy1cNBGXKFtxi0q/FTEqs=; b=FRipWbwR5kp0YdXpodbYsM+FllsqBWkAs1kUutvBuct6sjCLu4igQ4caTRM9TnnQE3 OQ9qhVty3uDmWq0rsqq6TjO/mPRp4ssvSUMgxS5dXFGegrzNe7sEITTRB8QKMoZeGzX7 fvPUkz0RhlecsXkW5AM7MNICzs59JyOOfJAZjnTMi9EG6GERbx94CygOdt9CknEbkcm4 o2srvnW6YwKfj0USPAzh8TXH+V+PbIZh27jtk8IIVF/KUK2jn1QyNaGcrI7v7VWjVHGB 5fIJfi0bOdZDkrQRyNLi8MWB6zJeRKcxLW8cMkyruw7c+fXy9QHdVAC9kK19mB1QnE7f yd8Q== X-Gm-Message-State: APjAAAUaGxSjBMOAcckxy5l5pRa22xWSdFL3WtXzRDk4TGP9Opc9vhnR +jSBCBLNEc5wxIqHjtLukDZbkDXsO74= X-Google-Smtp-Source: APXvYqx7F3T27E+FPzc0TVME5j1/BPyDFhcfzXNEz+F9iipkID6/CIYV2uSC+FbrNfigv2YIZ/InBA== X-Received: by 2002:ab0:2407:: with SMTP id f7mr2250348uan.18.1558620065102; Thu, 23 May 2019 07:01:05 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 23 May 2019 10:00:47 -0400 Message-Id: <20190523140059.18548-2-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190523140059.18548-1-richard.henderson@linaro.org> References: <20190523140059.18548-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::92b Subject: [Qemu-devel] [PULL 01/13] target/rx: TCG translation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) From: Yoshinori Sato This part only supported RXv1 instructions. Instruction manual. https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01us0032ej= 0120_rxsm.pdf Signed-off-by: Yoshinori Sato Reviewed-by: Richard Henderson Tested-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20190516055244.95559-2-ysato@users.sourceforge.jp> Signed-off-by: Richard Henderson --- target/rx/translate.c | 2432 +++++++++++++++++++++++++++++++++++++++ target/rx/Makefile.objs | 12 + target/rx/insns.decode | 621 ++++++++++ 3 files changed, 3065 insertions(+) create mode 100644 target/rx/translate.c create mode 100644 target/rx/Makefile.objs create mode 100644 target/rx/insns.decode diff --git a/target/rx/translate.c b/target/rx/translate.c new file mode 100644 index 0000000000..3765ea0895 --- /dev/null +++ b/target/rx/translate.c @@ -0,0 +1,2432 @@ +/* + * RX translation + * + * 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 f= or + * 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/bswap.h" +#include "qemu/qemu-print.h" +#include "cpu.h" +#include "exec/exec-all.h" +#include "tcg-op.h" +#include "exec/cpu_ldst.h" +#include "exec/helper-proto.h" +#include "exec/helper-gen.h" +#include "exec/translator.h" +#include "trace-tcg.h" +#include "exec/log.h" + +typedef struct DisasContext { + DisasContextBase base; + CPURXState *env; + uint32_t pc; +} DisasContext; + +typedef struct DisasCompare { + TCGv value; + TCGv temp; + TCGCond cond; +} DisasCompare; + +const char rx_crname[][6] =3D { + "psw", "pc", "usp", "fpsw", "", "", "", "", + "bpsw", "bpc", "isp", "fintv", "intb", "", "", "", +}; + +/* Target-specific values for dc->base.is_jmp. */ +#define DISAS_JUMP DISAS_TARGET_0 +#define DISAS_UPDATE DISAS_TARGET_1 +#define DISAS_EXIT DISAS_TARGET_2 + +/* global register indexes */ +static TCGv cpu_regs[16]; +static TCGv cpu_psw_o, cpu_psw_s, cpu_psw_z, cpu_psw_c; +static TCGv cpu_psw_i, cpu_psw_pm, cpu_psw_u, cpu_psw_ipl; +static TCGv cpu_usp, cpu_fpsw, cpu_bpsw, cpu_bpc, cpu_isp; +static TCGv cpu_fintv, cpu_intb, cpu_pc; +static TCGv_i64 cpu_acc; + +#define cpu_sp cpu_regs[0] + +#include "exec/gen-icount.h" + +/* decoder helper */ +static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn, + int i, int n) +{ + while (++i <=3D n) { + uint8_t b =3D cpu_ldub_code(ctx->env, ctx->base.pc_next++); + insn |=3D b << (32 - i * 8); + } + return insn; +} + +static uint32_t li(DisasContext *ctx, int sz) +{ + int32_t tmp, addr; + CPURXState *env =3D ctx->env; + addr =3D ctx->base.pc_next; + + tcg_debug_assert(sz < 4); + switch (sz) { + case 1: + ctx->base.pc_next +=3D 1; + return cpu_ldsb_code(env, addr); + case 2: + ctx->base.pc_next +=3D 2; + return cpu_ldsw_code(env, addr); + case 3: + ctx->base.pc_next +=3D 3; + tmp =3D cpu_ldsb_code(env, addr + 2) << 16; + tmp |=3D cpu_lduw_code(env, addr) & 0xffff; + return tmp; + case 0: + ctx->base.pc_next +=3D 4; + return cpu_ldl_code(env, addr); + } + return 0; +} + +static int bdsp_s(DisasContext *ctx, int d) +{ + /* + * 0 -> 8 + * 1 -> 9 + * 2 -> 10 + * 3 -> 3 + * : + * 7 -> 7 + */ + if (d < 3) { + d +=3D 8; + } + return d; +} + +/* Include the auto-generated decoder. */ +#include "decode.inc.c" + +void rx_cpu_dump_state(CPUState *cs, FILE *f, int flags) +{ + RXCPU *cpu =3D RXCPU(cs); + CPURXState *env =3D &cpu->env; + int i; + uint32_t psw; + + psw =3D rx_cpu_pack_psw(env); + qemu_fprintf(f, "pc=3D0x%08x psw=3D0x%08x\n", + env->pc, psw); + for (i =3D 0; i < 16; i +=3D 4) { + qemu_fprintf(f, "r%d=3D0x%08x r%d=3D0x%08x r%d=3D0x%08x r%d=3D0x%0= 8x\n", + i, env->regs[i], i + 1, env->regs[i + 1], + i + 2, env->regs[i + 2], i + 3, env->regs[i + 3]); + } +} + +static bool use_goto_tb(DisasContext *dc, target_ulong dest) +{ + if (unlikely(dc->base.singlestep_enabled)) { + return false; + } else { + return true; + } +} + +static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) +{ + if (use_goto_tb(dc, dest)) { + tcg_gen_goto_tb(n); + tcg_gen_movi_i32(cpu_pc, dest); + tcg_gen_exit_tb(dc->base.tb, n); + } else { + tcg_gen_movi_i32(cpu_pc, dest); + if (dc->base.singlestep_enabled) { + gen_helper_debug(cpu_env); + } else { + tcg_gen_lookup_and_goto_ptr(); + } + } + dc->base.is_jmp =3D DISAS_NORETURN; +} + +/* generic load wrapper */ +static inline void rx_gen_ld(unsigned int size, TCGv reg, TCGv mem) +{ + tcg_gen_qemu_ld_i32(reg, mem, 0, size | MO_SIGN | MO_TE); +} + +/* unsigned load wrapper */ +static inline void rx_gen_ldu(unsigned int size, TCGv reg, TCGv mem) +{ + tcg_gen_qemu_ld_i32(reg, mem, 0, size | MO_TE); +} + +/* generic store wrapper */ +static inline void rx_gen_st(unsigned int size, TCGv reg, TCGv mem) +{ + tcg_gen_qemu_st_i32(reg, mem, 0, size | MO_TE); +} + +/* [ri, rb] */ +static inline void rx_gen_regindex(DisasContext *ctx, TCGv mem, + int size, int ri, int rb) +{ + tcg_gen_shli_i32(mem, cpu_regs[ri], size); + tcg_gen_add_i32(mem, mem, cpu_regs[rb]); +} + +/* dsp[reg] */ +static inline TCGv rx_index_addr(DisasContext *ctx, TCGv mem, + int ld, int size, int reg) +{ + uint32_t dsp; + + tcg_debug_assert(ld < 3); + switch (ld) { + case 0: + return cpu_regs[reg]; + case 1: + dsp =3D cpu_ldub_code(ctx->env, ctx->base.pc_next) << size; + tcg_gen_addi_i32(mem, cpu_regs[reg], dsp); + ctx->base.pc_next +=3D 1; + return mem; + case 2: + dsp =3D cpu_lduw_code(ctx->env, ctx->base.pc_next) << size; + tcg_gen_addi_i32(mem, cpu_regs[reg], dsp); + ctx->base.pc_next +=3D 2; + return mem; + } + return NULL; +} + +static inline TCGMemOp mi_to_mop(unsigned mi) +{ + static const TCGMemOp mop[5] =3D { MO_SB, MO_SW, MO_UL, MO_UW, MO_UB }; + tcg_debug_assert(mi < 5); + return mop[mi]; +} + +/* load source operand */ +static inline TCGv rx_load_source(DisasContext *ctx, TCGv mem, + int ld, int mi, int rs) +{ + TCGv addr; + TCGMemOp mop; + if (ld < 3) { + mop =3D mi_to_mop(mi); + addr =3D rx_index_addr(ctx, mem, ld, mop & MO_SIZE, rs); + tcg_gen_qemu_ld_i32(mem, addr, 0, mop | MO_TE); + return mem; + } else { + return cpu_regs[rs]; + } +} + +/* Processor mode check */ +static int is_privileged(DisasContext *ctx, int is_exception) +{ + if (FIELD_EX32(ctx->base.tb->flags, PSW, PM)) { + if (is_exception) { + gen_helper_raise_privilege_violation(cpu_env); + } + return 0; + } else { + return 1; + } +} + +/* generate QEMU condition */ +static void psw_cond(DisasCompare *dc, uint32_t cond) +{ + tcg_debug_assert(cond < 16); + switch (cond) { + case 0: /* z */ + dc->cond =3D TCG_COND_EQ; + dc->value =3D cpu_psw_z; + break; + case 1: /* nz */ + dc->cond =3D TCG_COND_NE; + dc->value =3D cpu_psw_z; + break; + case 2: /* c */ + dc->cond =3D TCG_COND_NE; + dc->value =3D cpu_psw_c; + break; + case 3: /* nc */ + dc->cond =3D TCG_COND_EQ; + dc->value =3D cpu_psw_c; + break; + case 4: /* gtu (C& ~Z) =3D=3D 1 */ + case 5: /* leu (C& ~Z) =3D=3D 0 */ + tcg_gen_setcondi_i32(TCG_COND_NE, dc->temp, cpu_psw_z, 0); + tcg_gen_and_i32(dc->temp, dc->temp, cpu_psw_c); + dc->cond =3D (cond =3D=3D 4) ? TCG_COND_NE : TCG_COND_EQ; + dc->value =3D dc->temp; + break; + case 6: /* pz (S =3D=3D 0) */ + dc->cond =3D TCG_COND_GE; + dc->value =3D cpu_psw_s; + break; + case 7: /* n (S =3D=3D 1) */ + dc->cond =3D TCG_COND_LT; + dc->value =3D cpu_psw_s; + break; + case 8: /* ge (S^O)=3D=3D0 */ + case 9: /* lt (S^O)=3D=3D1 */ + tcg_gen_xor_i32(dc->temp, cpu_psw_o, cpu_psw_s); + dc->cond =3D (cond =3D=3D 8) ? TCG_COND_GE : TCG_COND_LT; + dc->value =3D dc->temp; + break; + case 10: /* gt ((S^O)|Z)=3D=3D0 */ + case 11: /* le ((S^O)|Z)=3D=3D1 */ + tcg_gen_xor_i32(dc->temp, cpu_psw_o, cpu_psw_s); + tcg_gen_sari_i32(dc->temp, dc->temp, 31); + tcg_gen_andc_i32(dc->temp, cpu_psw_z, dc->temp); + dc->cond =3D (cond =3D=3D 10) ? TCG_COND_NE : TCG_COND_EQ; + dc->value =3D dc->temp; + break; + case 12: /* o */ + dc->cond =3D TCG_COND_LT; + dc->value =3D cpu_psw_o; + break; + case 13: /* no */ + dc->cond =3D TCG_COND_GE; + dc->value =3D cpu_psw_o; + break; + case 14: /* always true */ + dc->cond =3D TCG_COND_ALWAYS; + dc->value =3D dc->temp; + break; + case 15: /* always false */ + dc->cond =3D TCG_COND_NEVER; + dc->value =3D dc->temp; + break; + } +} + +static void move_from_cr(TCGv ret, int cr, uint32_t pc) +{ + TCGv z =3D tcg_const_i32(0); + switch (cr) { + case 0: /* PSW */ + gen_helper_pack_psw(ret, cpu_env); + break; + case 1: /* PC */ + tcg_gen_movi_i32(ret, pc); + break; + case 2: /* USP */ + tcg_gen_movcond_i32(TCG_COND_NE, ret, + cpu_psw_u, z, cpu_sp, cpu_usp); + break; + case 3: /* FPSW */ + tcg_gen_mov_i32(ret, cpu_fpsw); + break; + case 8: /* BPSW */ + tcg_gen_mov_i32(ret, cpu_bpsw); + break; + case 9: /* BPC */ + tcg_gen_mov_i32(ret, cpu_bpc); + break; + case 10: /* ISP */ + tcg_gen_movcond_i32(TCG_COND_EQ, ret, + cpu_psw_u, z, cpu_sp, cpu_isp); + break; + case 11: /* FINTV */ + tcg_gen_mov_i32(ret, cpu_fintv); + break; + case 12: /* INTB */ + tcg_gen_mov_i32(ret, cpu_intb); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "Unimplement control register %d", = cr); + /* Unimplement registers return 0 */ + tcg_gen_movi_i32(ret, 0); + break; + } + tcg_temp_free(z); +} + +static void move_to_cr(DisasContext *ctx, TCGv val, int cr) +{ + TCGv z; + if (cr >=3D 8 && !is_privileged(ctx, 0)) { + /* Some control registers can only be written in privileged mode. = */ + qemu_log_mask(LOG_GUEST_ERROR, + "disallow control register write %s", rx_crname[cr]); + return; + } + z =3D tcg_const_i32(0); + switch (cr) { + case 0: /* PSW */ + gen_helper_set_psw(cpu_env, val); + break; + /* case 1: to PC not supported */ + case 2: /* USP */ + tcg_gen_mov_i32(cpu_usp, val); + tcg_gen_movcond_i32(TCG_COND_NE, cpu_sp, + cpu_psw_u, z, cpu_usp, cpu_sp); + break; + case 3: /* FPSW */ + gen_helper_set_fpsw(cpu_env, val); + break; + case 8: /* BPSW */ + tcg_gen_mov_i32(cpu_bpsw, val); + break; + case 9: /* BPC */ + tcg_gen_mov_i32(cpu_bpc, val); + break; + case 10: /* ISP */ + tcg_gen_mov_i32(cpu_isp, val); + /* if PSW.U is 0, copy isp to r0 */ + tcg_gen_movcond_i32(TCG_COND_EQ, cpu_sp, + cpu_psw_u, z, cpu_isp, cpu_sp); + break; + case 11: /* FINTV */ + tcg_gen_mov_i32(cpu_fintv, val); + break; + case 12: /* INTB */ + tcg_gen_mov_i32(cpu_intb, val); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "Unimplement control register %d", cr); + break; + } + tcg_temp_free(z); +} + +static void push(TCGv val) +{ + tcg_gen_subi_i32(cpu_sp, cpu_sp, 4); + rx_gen_st(MO_32, val, cpu_sp); +} + +static void pop(TCGv ret) +{ + rx_gen_ld(MO_32, ret, cpu_sp); + tcg_gen_addi_i32(cpu_sp, cpu_sp, 4); +} + +/* mov. rs,dsp5[rd] */ +static bool trans_MOV_rm(DisasContext *ctx, arg_MOV_rm *a) +{ + TCGv mem; + mem =3D tcg_temp_new(); + tcg_gen_addi_i32(mem, cpu_regs[a->rd], a->dsp << a->sz); + rx_gen_st(a->sz, cpu_regs[a->rs], mem); + tcg_temp_free(mem); + return true; +} + +/* mov. dsp5[rs],rd */ +static bool trans_MOV_mr(DisasContext *ctx, arg_MOV_mr *a) +{ + TCGv mem; + mem =3D tcg_temp_new(); + tcg_gen_addi_i32(mem, cpu_regs[a->rs], a->dsp << a->sz); + rx_gen_ld(a->sz, cpu_regs[a->rd], mem); + tcg_temp_free(mem); + 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) +{ + tcg_gen_movi_i32(cpu_regs[a->rd], a->imm); + return true; +} + +/* mov. #uimm8,dsp[rd] */ +/* mov. #imm, dsp[rd] */ +static bool trans_MOV_im(DisasContext *ctx, arg_MOV_im *a) +{ + TCGv imm, mem; + imm =3D tcg_const_i32(a->imm); + mem =3D tcg_temp_new(); + tcg_gen_addi_i32(mem, cpu_regs[a->rd], a->dsp << a->sz); + rx_gen_st(a->sz, imm, mem); + tcg_temp_free(imm); + tcg_temp_free(mem); + return true; +} + +/* mov. [ri,rb],rd */ +static bool trans_MOV_ar(DisasContext *ctx, arg_MOV_ar *a) +{ + TCGv mem; + mem =3D tcg_temp_new(); + rx_gen_regindex(ctx, mem, a->sz, a->ri, a->rb); + rx_gen_ld(a->sz, cpu_regs[a->rd], mem); + tcg_temp_free(mem); + return true; +} + +/* mov. rd,[ri,rb] */ +static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a) +{ + TCGv mem; + mem =3D tcg_temp_new(); + rx_gen_regindex(ctx, mem, a->sz, a->ri, a->rb); + rx_gen_st(a->sz, cpu_regs[a->rs], mem); + tcg_temp_free(mem); + return true; +} + +/* mov. dsp[rs],dsp[rd] */ +/* mov. rs,dsp[rd] */ +/* mov. dsp[rs],rd */ +/* mov. rs,rd */ +static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a) +{ + static void (* const mov[])(TCGv ret, TCGv arg) =3D { + tcg_gen_ext8s_i32, tcg_gen_ext16s_i32, tcg_gen_mov_i32, + }; + TCGv tmp, mem, addr; + if (a->lds =3D=3D 3 && a->ldd =3D=3D 3) { + /* mov. rs,rd */ + mov[a->sz](cpu_regs[a->rd], cpu_regs[a->rs]); + return true; + } + + mem =3D tcg_temp_new(); + if (a->lds =3D=3D 3) { + /* mov. rs,dsp[rd] */ + addr =3D rx_index_addr(ctx, mem, a->ldd, a->sz, a->rs); + rx_gen_st(a->sz, cpu_regs[a->rd], addr); + } else if (a->ldd =3D=3D 3) { + /* mov. dsp[rs],rd */ + addr =3D rx_index_addr(ctx, mem, a->lds, a->sz, a->rs); + rx_gen_ld(a->sz, cpu_regs[a->rd], addr); + } else { + /* mov. dsp[rs],dsp[rd] */ + tmp =3D tcg_temp_new(); + addr =3D rx_index_addr(ctx, mem, a->lds, a->sz, a->rs); + rx_gen_ld(a->sz, tmp, addr); + addr =3D rx_index_addr(ctx, mem, a->ldd, a->sz, a->rd); + rx_gen_st(a->sz, tmp, addr); + tcg_temp_free(tmp); + } + tcg_temp_free(mem); + return true; +} + +/* mov. rs,[rd+] */ +/* mov. rs,[-rd] */ +static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a) +{ + TCGv val; + val =3D tcg_temp_new(); + tcg_gen_mov_i32(val, cpu_regs[a->rs]); + if (a->ad =3D=3D 1) { + tcg_gen_subi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz); + } + rx_gen_st(a->sz, val, cpu_regs[a->rd]); + if (a->ad =3D=3D 0) { + tcg_gen_addi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz); + } + tcg_temp_free(val); + return true; +} + +/* mov. [rd+],rs */ +/* mov. [-rd],rs */ +static bool trans_MOV_pr(DisasContext *ctx, arg_MOV_pr *a) +{ + TCGv val; + val =3D tcg_temp_new(); + if (a->ad =3D=3D 1) { + tcg_gen_subi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz); + } + rx_gen_ld(a->sz, val, cpu_regs[a->rd]); + if (a->ad =3D=3D 0) { + tcg_gen_addi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz); + } + tcg_gen_mov_i32(cpu_regs[a->rs], val); + tcg_temp_free(val); + return true; +} + +/* movu. dsp5[rs],rd */ +/* movu. dsp[rs],rd */ +static bool trans_MOVU_mr(DisasContext *ctx, arg_MOVU_mr *a) +{ + TCGv mem; + mem =3D tcg_temp_new(); + tcg_gen_addi_i32(mem, cpu_regs[a->rs], a->dsp << a->sz); + rx_gen_ldu(a->sz, cpu_regs[a->rd], mem); + tcg_temp_free(mem); + return true; +} + +/* movu. rs,rd */ +static bool trans_MOVU_rr(DisasContext *ctx, arg_MOVU_rr *a) +{ + static void (* const ext[])(TCGv ret, TCGv arg) =3D { + tcg_gen_ext8u_i32, tcg_gen_ext16u_i32, + }; + ext[a->sz](cpu_regs[a->rd], cpu_regs[a->rs]); + return true; +} + +/* movu. [ri,rb],rd */ +static bool trans_MOVU_ar(DisasContext *ctx, arg_MOVU_ar *a) +{ + TCGv mem; + mem =3D tcg_temp_new(); + rx_gen_regindex(ctx, mem, a->sz, a->ri, a->rb); + rx_gen_ldu(a->sz, cpu_regs[a->rd], mem); + tcg_temp_free(mem); + return true; +} + +/* movu. [rd+],rs */ +/* mov. [-rd],rs */ +static bool trans_MOVU_pr(DisasContext *ctx, arg_MOVU_pr *a) +{ + TCGv val; + val =3D tcg_temp_new(); + if (a->ad =3D=3D 1) { + tcg_gen_subi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz); + } + rx_gen_ldu(a->sz, val, cpu_regs[a->rd]); + if (a->ad =3D=3D 0) { + tcg_gen_addi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz); + } + tcg_gen_mov_i32(cpu_regs[a->rs], val); + tcg_temp_free(val); + return true; +} + + +/* pop rd */ +static bool trans_POP(DisasContext *ctx, arg_POP *a) +{ + /* mov.l [r0+], rd */ + arg_MOV_rp mov_a; + mov_a.rd =3D 0; + mov_a.rs =3D a->rd; + mov_a.ad =3D 0; + mov_a.sz =3D MO_32; + trans_MOV_pr(ctx, &mov_a); + return true; +} + +/* popc cr */ +static bool trans_POPC(DisasContext *ctx, arg_POPC *a) +{ + TCGv val; + val =3D tcg_temp_new(); + pop(val); + move_to_cr(ctx, val, a->cr); + if (a->cr =3D=3D 0 && is_privileged(ctx, 0)) { + /* PSW.I may be updated here. exit TB. */ + ctx->base.is_jmp =3D DISAS_UPDATE; + } + tcg_temp_free(val); + return true; +} + +/* popm rd-rd2 */ +static bool trans_POPM(DisasContext *ctx, arg_POPM *a) +{ + int r; + if (a->rd =3D=3D 0 || a->rd >=3D a->rd2) { + qemu_log_mask(LOG_GUEST_ERROR, + "Invalid register ranges r%d-r%d", a->rd, a->rd2); + } + r =3D a->rd; + while (r <=3D a->rd2 && r < 16) { + pop(cpu_regs[r++]); + } + return true; +} + + +/* push. rs */ +static bool trans_PUSH_r(DisasContext *ctx, arg_PUSH_r *a) +{ + TCGv val; + val =3D tcg_temp_new(); + tcg_gen_mov_i32(val, cpu_regs[a->rs]); + tcg_gen_subi_i32(cpu_sp, cpu_sp, 4); + rx_gen_st(a->sz, val, cpu_sp); + tcg_temp_free(val); + return true; +} + +/* push. dsp[rs] */ +static bool trans_PUSH_m(DisasContext *ctx, arg_PUSH_m *a) +{ + TCGv mem, val, addr; + mem =3D tcg_temp_new(); + val =3D tcg_temp_new(); + addr =3D rx_index_addr(ctx, mem, a->ld, a->sz, a->rs); + rx_gen_ld(a->sz, val, addr); + tcg_gen_subi_i32(cpu_sp, cpu_sp, 4); + rx_gen_st(a->sz, val, cpu_sp); + tcg_temp_free(mem); + tcg_temp_free(val); + return true; +} + +/* pushc rx */ +static bool trans_PUSHC(DisasContext *ctx, arg_PUSHC *a) +{ + TCGv val; + val =3D tcg_temp_new(); + move_from_cr(val, a->cr, ctx->pc); + push(val); + tcg_temp_free(val); + return true; +} + +/* pushm rs-rs2 */ +static bool trans_PUSHM(DisasContext *ctx, arg_PUSHM *a) +{ + int r; + + if (a->rs =3D=3D 0 || a->rs >=3D a->rs2) { + qemu_log_mask(LOG_GUEST_ERROR, + "Invalid register ranges r%d-r%d", a->rs, a->rs2); + } + r =3D a->rs2; + while (r >=3D a->rs && r >=3D 0) { + push(cpu_regs[r--]); + } + return true; +} + +/* xchg rs,rd */ +static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr *a) +{ + TCGv tmp; + tmp =3D tcg_temp_new(); + tcg_gen_mov_i32(tmp, cpu_regs[a->rs]); + tcg_gen_mov_i32(cpu_regs[a->rs], cpu_regs[a->rd]); + tcg_gen_mov_i32(cpu_regs[a->rd], tmp); + tcg_temp_free(tmp); + return true; +} + +/* xchg dsp[rs].,rd */ +static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a) +{ + TCGv mem, addr; + mem =3D tcg_temp_new(); + switch (a->mi) { + case 0: /* dsp[rs].b */ + case 1: /* dsp[rs].w */ + case 2: /* dsp[rs].l */ + addr =3D rx_index_addr(ctx, mem, a->ld, a->mi, a->rs); + break; + case 3: /* dsp[rs].uw */ + case 4: /* dsp[rs].ub */ + addr =3D rx_index_addr(ctx, mem, a->ld, 4 - a->mi, a->rs); + break; + default: + g_assert_not_reached(); + } + tcg_gen_atomic_xchg_i32(cpu_regs[a->rd], addr, cpu_regs[a->rd], + 0, mi_to_mop(a->mi)); + tcg_temp_free(mem); + return true; +} + +static inline void stcond(TCGCond cond, int rd, int imm) +{ + TCGv z; + TCGv _imm; + z =3D tcg_const_i32(0); + _imm =3D tcg_const_i32(imm); + tcg_gen_movcond_i32(cond, cpu_regs[rd], cpu_psw_z, z, + _imm, cpu_regs[rd]); + tcg_temp_free(z); + tcg_temp_free(_imm); +} + +/* stz #imm,rd */ +static bool trans_STZ(DisasContext *ctx, arg_STZ *a) +{ + stcond(TCG_COND_EQ, a->rd, a->imm); + return true; +} + +/* stnz #imm,rd */ +static bool trans_STNZ(DisasContext *ctx, arg_STNZ *a) +{ + stcond(TCG_COND_NE, a->rd, a->imm); + return true; +} + +/* sccnd. rd */ +/* sccnd. dsp:[rd] */ +static bool trans_SCCnd(DisasContext *ctx, arg_SCCnd *a) +{ + DisasCompare dc; + TCGv val, mem, addr; + dc.temp =3D tcg_temp_new(); + psw_cond(&dc, a->cd); + if (a->ld < 3) { + val =3D tcg_temp_new(); + mem =3D tcg_temp_new(); + tcg_gen_setcondi_i32(dc.cond, val, dc.value, 0); + addr =3D rx_index_addr(ctx, mem, a->sz, a->ld, a->rd); + rx_gen_st(a->sz, val, addr); + tcg_temp_free(val); + tcg_temp_free(mem); + } else { + tcg_gen_setcondi_i32(dc.cond, cpu_regs[a->rd], dc.value, 0); + } + tcg_temp_free(dc.temp); + return true; +} + +/* rtsd #imm */ +static bool trans_RTSD_i(DisasContext *ctx, arg_RTSD_i *a) +{ + tcg_gen_addi_i32(cpu_sp, cpu_sp, a->imm << 2); + pop(cpu_pc); + ctx->base.is_jmp =3D DISAS_JUMP; + return true; +} + +/* rtsd #imm, rd-rd2 */ +static bool trans_RTSD_irr(DisasContext *ctx, arg_RTSD_irr *a) +{ + int dst; + int adj; + + if (a->rd2 >=3D a->rd) { + adj =3D a->imm - (a->rd2 - a->rd + 1); + } else { + adj =3D a->imm - (15 - a->rd + 1); + } + + tcg_gen_addi_i32(cpu_sp, cpu_sp, adj << 2); + dst =3D a->rd; + while (dst <=3D a->rd2 && dst < 16) { + pop(cpu_regs[dst++]); + } + pop(cpu_pc); + ctx->base.is_jmp =3D DISAS_JUMP; + return true; +} + +typedef void (*op2fn)(TCGv ret, TCGv arg1); +typedef void (*op3fn)(TCGv ret, TCGv arg1, TCGv arg2); + +static inline void rx_gen_op_rr(op2fn opr, int dst, int src) +{ + opr(cpu_regs[dst], cpu_regs[src]); +} + +static inline void rx_gen_op_rrr(op3fn opr, int dst, int src, int src2) +{ + opr(cpu_regs[dst], cpu_regs[src], cpu_regs[src2]); +} + +static inline void rx_gen_op_irr(op3fn opr, int dst, int src, uint32_t src= 2) +{ + TCGv imm =3D tcg_const_i32(src2); + opr(cpu_regs[dst], cpu_regs[src], imm); + tcg_temp_free(imm); +} + +static inline void rx_gen_op_mr(op3fn opr, DisasContext *ctx, + int dst, int src, int ld, int mi) +{ + TCGv val, mem; + mem =3D tcg_temp_new(); + val =3D rx_load_source(ctx, mem, ld, mi, src); + opr(cpu_regs[dst], cpu_regs[dst], val); + tcg_temp_free(mem); +} + +static void rx_and(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_and_i32(cpu_psw_s, arg1, arg2); + tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s); + tcg_gen_mov_i32(ret, cpu_psw_s); +} + +/* and #uimm:4, rd */ +/* and #imm, rd */ +static bool trans_AND_ir(DisasContext *ctx, arg_AND_ir *a) +{ + rx_gen_op_irr(rx_and, a->rd, a->rd, a->imm); + return true; +} + +/* and dsp[rs], rd */ +/* and rs,rd */ +static bool trans_AND_mr(DisasContext *ctx, arg_AND_mr *a) +{ + rx_gen_op_mr(rx_and, ctx, a->rd, a->rs, a->ld, a->mi); + return true; +} + +/* and rs,rs2,rd */ +static bool trans_AND_rrr(DisasContext *ctx, arg_AND_rrr *a) +{ + rx_gen_op_rrr(rx_and, a->rd, a->rs, a->rs2); + return true; +} + +static void rx_or(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_or_i32(cpu_psw_s, arg1, arg2); + tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s); + tcg_gen_mov_i32(ret, cpu_psw_s); +} + +/* or #uimm:4, rd */ +/* or #imm, rd */ +static bool trans_OR_ir(DisasContext *ctx, arg_OR_ir *a) +{ + rx_gen_op_irr(rx_or, a->rd, a->rd, a->imm); + return true; +} + +/* or dsp[rs], rd */ +/* or rs,rd */ +static bool trans_OR_mr(DisasContext *ctx, arg_OR_mr *a) +{ + rx_gen_op_mr(rx_or, ctx, a->rd, a->rs, a->ld, a->mi); + return true; +} + +/* or rs,rs2,rd */ +static bool trans_OR_rrr(DisasContext *ctx, arg_OR_rrr *a) +{ + rx_gen_op_rrr(rx_or, a->rd, a->rs, a->rs2); + return true; +} + +static void rx_xor(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_xor_i32(cpu_psw_s, arg1, arg2); + tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s); + tcg_gen_mov_i32(ret, cpu_psw_s); +} + +/* xor #imm, rd */ +static bool trans_XOR_ir(DisasContext *ctx, arg_XOR_ir *a) +{ + rx_gen_op_irr(rx_xor, a->rd, a->rd, a->imm); + return true; +} + +/* xor dsp[rs], rd */ +/* xor rs,rd */ +static bool trans_XOR_mr(DisasContext *ctx, arg_XOR_mr *a) +{ + rx_gen_op_mr(rx_xor, ctx, a->rd, a->rs, a->ld, a->mi); + return true; +} + +static void rx_tst(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_and_i32(cpu_psw_s, arg1, arg2); + tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s); +} + +/* tst #imm, rd */ +static bool trans_TST_ir(DisasContext *ctx, arg_TST_ir *a) +{ + rx_gen_op_irr(rx_tst, a->rd, a->rd, a->imm); + return true; +} + +/* tst dsp[rs], rd */ +/* tst rs, rd */ +static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *a) +{ + rx_gen_op_mr(rx_tst, ctx, a->rd, a->rs, a->ld, a->mi); + return true; +} + +static void rx_not(TCGv ret, TCGv arg1) +{ + tcg_gen_not_i32(ret, arg1); + tcg_gen_mov_i32(cpu_psw_z, ret); + tcg_gen_mov_i32(cpu_psw_s, ret); +} + +/* not rd */ +/* not rs, rd */ +static bool trans_NOT_rr(DisasContext *ctx, arg_NOT_rr *a) +{ + rx_gen_op_rr(rx_not, a->rd, a->rs); + return true; +} + +static void rx_neg(TCGv ret, TCGv arg1) +{ + tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_psw_o, arg1, 0x80000000); + tcg_gen_neg_i32(ret, arg1); + tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_psw_c, ret, 0); + tcg_gen_mov_i32(cpu_psw_z, ret); + tcg_gen_mov_i32(cpu_psw_s, ret); +} + + +/* neg rd */ +/* neg rs, rd */ +static bool trans_NEG_rr(DisasContext *ctx, arg_NEG_rr *a) +{ + rx_gen_op_rr(rx_neg, a->rd, a->rs); + return true; +} + +/* ret =3D arg1 + arg2 + psw_c */ +static void rx_adc(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv z; + z =3D tcg_const_i32(0); + tcg_gen_add2_i32(cpu_psw_s, cpu_psw_c, arg1, z, cpu_psw_c, z); + tcg_gen_add2_i32(cpu_psw_s, cpu_psw_c, cpu_psw_s, cpu_psw_c, arg2, z); + tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s); + tcg_gen_xor_i32(cpu_psw_o, cpu_psw_s, arg1); + tcg_gen_xor_i32(z, arg1, arg2); + tcg_gen_andc_i32(cpu_psw_o, cpu_psw_o, z); + tcg_gen_mov_i32(ret, cpu_psw_s); + tcg_temp_free(z); +} + +/* adc #imm, rd */ +static bool trans_ADC_ir(DisasContext *ctx, arg_ADC_ir *a) +{ + rx_gen_op_irr(rx_adc, a->rd, a->rd, a->imm); + return true; +} + +/* adc rs, rd */ +static bool trans_ADC_rr(DisasContext *ctx, arg_ADC_rr *a) +{ + rx_gen_op_rrr(rx_adc, a->rd, a->rd, a->rs); + return true; +} + +/* adc dsp[rs], rd */ +static bool trans_ADC_mr(DisasContext *ctx, arg_ADC_mr *a) +{ + /* mi only 2 */ + if (a->mi !=3D 2) { + return false; + } + rx_gen_op_mr(rx_adc, ctx, a->rd, a->rs, a->ld, a->mi); + return true; +} + +/* ret =3D arg1 + arg2 */ +static void rx_add(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv z; + z =3D tcg_const_i32(0); + tcg_gen_add2_i32(cpu_psw_s, cpu_psw_c, arg1, z, arg2, z); + tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s); + tcg_gen_xor_i32(cpu_psw_o, cpu_psw_s, arg1); + tcg_gen_xor_i32(z, arg1, arg2); + tcg_gen_andc_i32(cpu_psw_o, cpu_psw_o, z); + tcg_gen_mov_i32(ret, cpu_psw_s); + tcg_temp_free(z); +} + +/* add #uimm4, rd */ +/* add #imm, rs, rd */ +static bool trans_ADD_irr(DisasContext *ctx, arg_ADD_irr *a) +{ + rx_gen_op_irr(rx_add, a->rd, a->rs2, a->imm); + return true; +} + +/* add rs, rd */ +/* add dsp[rs], rd */ +static bool trans_ADD_mr(DisasContext *ctx, arg_ADD_mr *a) +{ + rx_gen_op_mr(rx_add, ctx, a->rd, a->rs, a->ld, a->mi); + return true; +} + +/* add rs, rs2, rd */ +static bool trans_ADD_rrr(DisasContext *ctx, arg_ADD_rrr *a) +{ + rx_gen_op_rrr(rx_add, a->rd, a->rs, a->rs2); + return true; +} + +/* ret =3D arg1 - arg2 */ +static void rx_sub(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv temp; + tcg_gen_sub_i32(cpu_psw_s, arg1, arg2); + tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s); + tcg_gen_setcond_i32(TCG_COND_GEU, cpu_psw_c, arg1, arg2); + tcg_gen_xor_i32(cpu_psw_o, cpu_psw_s, arg1); + temp =3D tcg_temp_new_i32(); + tcg_gen_xor_i32(temp, arg1, arg2); + tcg_gen_and_i32(cpu_psw_o, cpu_psw_o, temp); + tcg_temp_free_i32(temp); + /* CMP not requred return */ + if (ret) { + tcg_gen_mov_i32(ret, cpu_psw_s); + } +} +static void rx_cmp(TCGv dummy, TCGv arg1, TCGv arg2) +{ + rx_sub(NULL, arg1, arg2); +} +/* ret =3D arg1 - arg2 - !psw_c */ +/* -> ret =3D arg1 + ~arg2 + psw_c */ +static void rx_sbb(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv temp; + temp =3D tcg_temp_new(); + tcg_gen_not_i32(temp, arg2); + rx_adc(ret, arg1, temp); + tcg_temp_free(temp); +} + +/* cmp #imm4, rs2 */ +/* cmp #imm8, rs2 */ +/* cmp #imm, rs2 */ +static bool trans_CMP_ir(DisasContext *ctx, arg_CMP_ir *a) +{ + rx_gen_op_irr(rx_cmp, 0, a->rs2, a->imm); + return true; +} + +/* cmp rs, rs2 */ +/* cmp dsp[rs], rs2 */ +static bool trans_CMP_mr(DisasContext *ctx, arg_CMP_mr *a) +{ + rx_gen_op_mr(rx_cmp, ctx, a->rd, a->rs, a->ld, a->mi); + return true; +} + +/* sub #imm4, rd */ +static bool trans_SUB_ir(DisasContext *ctx, arg_SUB_ir *a) +{ + rx_gen_op_irr(rx_sub, a->rd, a->rd, a->imm); + return true; +} + +/* sub rs, rd */ +/* sub dsp[rs], rd */ +static bool trans_SUB_mr(DisasContext *ctx, arg_SUB_mr *a) +{ + rx_gen_op_mr(rx_sub, ctx, a->rd, a->rs, a->ld, a->mi); + return true; +} + +/* sub rs2, rs, rd */ +static bool trans_SUB_rrr(DisasContext *ctx, arg_SUB_rrr *a) +{ + rx_gen_op_rrr(rx_sub, a->rd, a->rs2, a->rs); + return true; +} + +/* sbb rs, rd */ +static bool trans_SBB_rr(DisasContext *ctx, arg_SBB_rr *a) +{ + rx_gen_op_rrr(rx_sbb, a->rd, a->rd, a->rs); + return true; +} + +/* sbb dsp[rs], rd */ +static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a) +{ + /* mi only 2 */ + if (a->mi !=3D 2) { + return false; + } + rx_gen_op_mr(rx_sbb, ctx, a->rd, a->rs, a->ld, a->mi); + return true; +} + +static void rx_abs(TCGv ret, TCGv arg1) +{ + TCGv neg; + TCGv zero; + neg =3D tcg_temp_new(); + zero =3D tcg_const_i32(0); + tcg_gen_neg_i32(neg, arg1); + tcg_gen_movcond_i32(TCG_COND_LT, ret, arg1, zero, neg, arg1); + tcg_temp_free(neg); + tcg_temp_free(zero); +} + +/* abs rd */ +/* abs rs, rd */ +static bool trans_ABS_rr(DisasContext *ctx, arg_ABS_rr *a) +{ + rx_gen_op_rr(rx_abs, a->rd, a->rs); + return true; +} + +/* max #imm, rd */ +static bool trans_MAX_ir(DisasContext *ctx, arg_MAX_ir *a) +{ + rx_gen_op_irr(tcg_gen_smax_i32, a->rd, a->rd, a->imm); + return true; +} + +/* max rs, rd */ +/* max dsp[rs], rd */ +static bool trans_MAX_mr(DisasContext *ctx, arg_MAX_mr *a) +{ + rx_gen_op_mr(tcg_gen_smax_i32, ctx, a->rd, a->rs, a->ld, a->mi); + return true; +} + +/* min #imm, rd */ +static bool trans_MIN_ir(DisasContext *ctx, arg_MIN_ir *a) +{ + rx_gen_op_irr(tcg_gen_smin_i32, a->rd, a->rd, a->imm); + return true; +} + +/* min rs, rd */ +/* min dsp[rs], rd */ +static bool trans_MIN_mr(DisasContext *ctx, arg_MIN_mr *a) +{ + rx_gen_op_mr(tcg_gen_smin_i32, ctx, a->rd, a->rs, a->ld, a->mi); + return true; +} + +/* mul #uimm4, rd */ +/* mul #imm, rd */ +static bool trans_MUL_ir(DisasContext *ctx, arg_MUL_ir *a) +{ + rx_gen_op_irr(tcg_gen_mul_i32, a->rd, a->rd, a->imm); + return true; +} + +/* mul rs, rd */ +/* mul dsp[rs], rd */ +static bool trans_MUL_mr(DisasContext *ctx, arg_MUL_mr *a) +{ + rx_gen_op_mr(tcg_gen_mul_i32, ctx, a->rd, a->rs, a->ld, a->mi); + return true; +} + +/* mul rs, rs2, rd */ +static bool trans_MUL_rrr(DisasContext *ctx, arg_MUL_rrr *a) +{ + rx_gen_op_rrr(tcg_gen_mul_i32, a->rd, a->rs, a->rs2); + return true; +} + +/* emul #imm, rd */ +static bool trans_EMUL_ir(DisasContext *ctx, arg_EMUL_ir *a) +{ + TCGv imm =3D tcg_const_i32(a->imm); + if (a->rd > 14) { + qemu_log_mask(LOG_GUEST_ERROR, "rd too large %d", a->rd); + } + tcg_gen_muls2_i32(cpu_regs[a->rd], cpu_regs[(a->rd + 1) & 15], + cpu_regs[a->rd], imm); + tcg_temp_free(imm); + return true; +} + +/* emul rs, rd */ +/* emul dsp[rs], rd */ +static bool trans_EMUL_mr(DisasContext *ctx, arg_EMUL_mr *a) +{ + TCGv val, mem; + if (a->rd > 14) { + qemu_log_mask(LOG_GUEST_ERROR, "rd too large %d", a->rd); + } + mem =3D tcg_temp_new(); + val =3D rx_load_source(ctx, mem, a->ld, a->mi, a->rs); + tcg_gen_muls2_i32(cpu_regs[a->rd], cpu_regs[(a->rd + 1) & 15], + cpu_regs[a->rd], val); + tcg_temp_free(mem); + return true; +} + +/* emulu #imm, rd */ +static bool trans_EMULU_ir(DisasContext *ctx, arg_EMULU_ir *a) +{ + TCGv imm =3D tcg_const_i32(a->imm); + if (a->rd > 14) { + qemu_log_mask(LOG_GUEST_ERROR, "rd too large %d", a->rd); + } + tcg_gen_mulu2_i32(cpu_regs[a->rd], cpu_regs[(a->rd + 1) & 15], + cpu_regs[a->rd], imm); + tcg_temp_free(imm); + return true; +} + +/* emulu rs, rd */ +/* emulu dsp[rs], rd */ +static bool trans_EMULU_mr(DisasContext *ctx, arg_EMULU_mr *a) +{ + TCGv val, mem; + if (a->rd > 14) { + qemu_log_mask(LOG_GUEST_ERROR, "rd too large %d", a->rd); + } + mem =3D tcg_temp_new(); + val =3D rx_load_source(ctx, mem, a->ld, a->mi, a->rs); + tcg_gen_mulu2_i32(cpu_regs[a->rd], cpu_regs[(a->rd + 1) & 15], + cpu_regs[a->rd], val); + tcg_temp_free(mem); + return true; +} + +static void rx_div(TCGv ret, TCGv arg1, TCGv arg2) +{ + gen_helper_div(ret, cpu_env, arg1, arg2); +} + +static void rx_divu(TCGv ret, TCGv arg1, TCGv arg2) +{ + gen_helper_divu(ret, cpu_env, arg1, arg2); +} + +/* div #imm, rd */ +static bool trans_DIV_ir(DisasContext *ctx, arg_DIV_ir *a) +{ + rx_gen_op_irr(rx_div, a->rd, a->rd, a->imm); + return true; +} + +/* div rs, rd */ +/* div dsp[rs], rd */ +static bool trans_DIV_mr(DisasContext *ctx, arg_DIV_mr *a) +{ + rx_gen_op_mr(rx_div, ctx, a->rd, a->rs, a->ld, a->mi); + return true; +} + +/* divu #imm, rd */ +static bool trans_DIVU_ir(DisasContext *ctx, arg_DIVU_ir *a) +{ + rx_gen_op_irr(rx_divu, a->rd, a->rd, a->imm); + return true; +} + +/* divu rs, rd */ +/* divu dsp[rs], rd */ +static bool trans_DIVU_mr(DisasContext *ctx, arg_DIVU_mr *a) +{ + rx_gen_op_mr(rx_divu, ctx, a->rd, a->rs, a->ld, a->mi); + return true; +} + + +/* shll #imm:5, rd */ +/* shll #imm:5, rs2, rd */ +static bool trans_SHLL_irr(DisasContext *ctx, arg_SHLL_irr *a) +{ + TCGv tmp; + tmp =3D tcg_temp_new(); + if (a->imm) { + tcg_gen_sari_i32(cpu_psw_c, cpu_regs[a->rs2], 32 - a->imm); + tcg_gen_shli_i32(cpu_regs[a->rd], cpu_regs[a->rs2], a->imm); + tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_psw_o, cpu_psw_c, 0); + tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_psw_c, 0xffffffff); + tcg_gen_or_i32(cpu_psw_o, cpu_psw_o, tmp); + tcg_gen_setcondi_i32(TCG_COND_NE, cpu_psw_c, cpu_psw_c, 0); + } else { + tcg_gen_mov_i32(cpu_regs[a->rd], cpu_regs[a->rs2]); + tcg_gen_movi_i32(cpu_psw_c, 0); + tcg_gen_movi_i32(cpu_psw_o, 0); + } + tcg_gen_mov_i32(cpu_psw_z, cpu_regs[a->rd]); + tcg_gen_mov_i32(cpu_psw_s, cpu_regs[a->rd]); + return true; +} + +/* shll rs, rd */ +static bool trans_SHLL_rr(DisasContext *ctx, arg_SHLL_rr *a) +{ + TCGLabel *noshift, *done; + TCGv count, tmp; + + noshift =3D gen_new_label(); + done =3D gen_new_label(); + /* if (cpu_regs[a->rs]) { */ + tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_regs[a->rs], 0, noshift); + count =3D tcg_const_i32(32); + tmp =3D tcg_temp_new(); + tcg_gen_andi_i32(tmp, cpu_regs[a->rs], 31); + tcg_gen_sub_i32(count, count, tmp); + tcg_gen_sar_i32(cpu_psw_c, cpu_regs[a->rd], count); + tcg_gen_shl_i32(cpu_regs[a->rd], cpu_regs[a->rd], tmp); + tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_psw_o, cpu_psw_c, 0); + tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_psw_c, 0xffffffff); + tcg_gen_or_i32(cpu_psw_o, cpu_psw_o, tmp); + tcg_gen_setcondi_i32(TCG_COND_NE, cpu_psw_c, cpu_psw_c, 0); + tcg_gen_br(done); + /* } else { */ + gen_set_label(noshift); + tcg_gen_movi_i32(cpu_psw_c, 0); + tcg_gen_movi_i32(cpu_psw_o, 0); + /* } */ + gen_set_label(done); + tcg_gen_mov_i32(cpu_psw_z, cpu_regs[a->rd]); + tcg_gen_mov_i32(cpu_psw_s, cpu_regs[a->rd]); + tcg_temp_free(count); + tcg_temp_free(tmp); + return true; +} + +static inline void shiftr_imm(uint32_t rd, uint32_t rs, uint32_t imm, + unsigned int alith) +{ + static void (* const gen_sXri[])(TCGv ret, TCGv arg1, int arg2) =3D { + tcg_gen_shri_i32, tcg_gen_sari_i32, + }; + tcg_debug_assert(alith < 2); + if (imm) { + gen_sXri[alith](cpu_regs[rd], cpu_regs[rs], imm - 1); + tcg_gen_andi_i32(cpu_psw_c, cpu_regs[rd], 0x00000001); + gen_sXri[alith](cpu_regs[rd], cpu_regs[rd], 1); + } else { + tcg_gen_mov_i32(cpu_regs[rd], cpu_regs[rs]); + tcg_gen_movi_i32(cpu_psw_c, 0); + } + tcg_gen_movi_i32(cpu_psw_o, 0); + tcg_gen_mov_i32(cpu_psw_z, cpu_regs[rd]); + tcg_gen_mov_i32(cpu_psw_s, cpu_regs[rd]); +} + +static inline void shiftr_reg(uint32_t rd, uint32_t rs, unsigned int alith) +{ + TCGLabel *noshift, *done; + TCGv count; + static void (* const gen_sXri[])(TCGv ret, TCGv arg1, int arg2) =3D { + tcg_gen_shri_i32, tcg_gen_sari_i32, + }; + static void (* const gen_sXr[])(TCGv ret, TCGv arg1, TCGv arg2) =3D { + tcg_gen_shr_i32, tcg_gen_sar_i32, + }; + tcg_debug_assert(alith < 2); + noshift =3D gen_new_label(); + done =3D gen_new_label(); + count =3D tcg_temp_new(); + /* if (cpu_regs[rs]) { */ + tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_regs[rs], 0, noshift); + tcg_gen_andi_i32(count, cpu_regs[rs], 31); + tcg_gen_subi_i32(count, count, 1); + gen_sXr[alith](cpu_regs[rd], cpu_regs[rd], count); + tcg_gen_andi_i32(cpu_psw_c, cpu_regs[rd], 0x00000001); + gen_sXri[alith](cpu_regs[rd], cpu_regs[rd], 1); + tcg_gen_br(done); + /* } else { */ + gen_set_label(noshift); + tcg_gen_movi_i32(cpu_psw_c, 0); + /* } */ + gen_set_label(done); + tcg_gen_movi_i32(cpu_psw_o, 0); + tcg_gen_mov_i32(cpu_psw_z, cpu_regs[rd]); + tcg_gen_mov_i32(cpu_psw_s, cpu_regs[rd]); + tcg_temp_free(count); +} + +/* shar #imm:5, rd */ +/* shar #imm:5, rs2, rd */ +static bool trans_SHAR_irr(DisasContext *ctx, arg_SHAR_irr *a) +{ + shiftr_imm(a->rd, a->rs2, a->imm, 1); + return true; +} + +/* shar rs, rd */ +static bool trans_SHAR_rr(DisasContext *ctx, arg_SHAR_rr *a) +{ + shiftr_reg(a->rd, a->rs, 1); + return true; +} + +/* shlr #imm:5, rd */ +/* shlr #imm:5, rs2, rd */ +static bool trans_SHLR_irr(DisasContext *ctx, arg_SHLR_irr *a) +{ + shiftr_imm(a->rd, a->rs2, a->imm, 0); + return true; +} + +/* shlr rs, rd */ +static bool trans_SHLR_rr(DisasContext *ctx, arg_SHLR_rr *a) +{ + shiftr_reg(a->rd, a->rs, 0); + return true; +} + +/* rolc rd */ +static bool trans_ROLC(DisasContext *ctx, arg_ROLC *a) +{ + TCGv tmp; + tmp =3D tcg_temp_new(); + tcg_gen_shri_i32(tmp, cpu_regs[a->rd], 31); + tcg_gen_shli_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1); + tcg_gen_or_i32(cpu_regs[a->rd], cpu_regs[a->rd], cpu_psw_c); + tcg_gen_mov_i32(cpu_psw_c, tmp); + tcg_gen_mov_i32(cpu_psw_z, cpu_regs[a->rd]); + tcg_gen_mov_i32(cpu_psw_s, cpu_regs[a->rd]); + tcg_temp_free(tmp); + return true; +} + +/* rorc rd */ +static bool trans_RORC(DisasContext *ctx, arg_RORC *a) +{ + TCGv tmp; + tmp =3D tcg_temp_new(); + tcg_gen_andi_i32(tmp, cpu_regs[a->rd], 0x00000001); + tcg_gen_shri_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1); + tcg_gen_shli_i32(cpu_psw_c, cpu_psw_c, 31); + tcg_gen_or_i32(cpu_regs[a->rd], cpu_regs[a->rd], cpu_psw_c); + tcg_gen_mov_i32(cpu_psw_c, tmp); + tcg_gen_mov_i32(cpu_psw_z, cpu_regs[a->rd]); + tcg_gen_mov_i32(cpu_psw_s, cpu_regs[a->rd]); + return true; +} + +enum {ROTR =3D 0, ROTL =3D 1}; +enum {ROT_IMM =3D 0, ROT_REG =3D 1}; +static inline void rx_rot(int ir, int dir, int rd, int src) +{ + switch (dir) { + case ROTL: + if (ir =3D=3D ROT_IMM) { + tcg_gen_rotli_i32(cpu_regs[rd], cpu_regs[rd], src); + } else { + tcg_gen_rotl_i32(cpu_regs[rd], cpu_regs[rd], cpu_regs[src]); + } + tcg_gen_andi_i32(cpu_psw_c, cpu_regs[rd], 0x00000001); + break; + case ROTR: + if (ir =3D=3D ROT_IMM) { + tcg_gen_rotri_i32(cpu_regs[rd], cpu_regs[rd], src); + } else { + tcg_gen_rotr_i32(cpu_regs[rd], cpu_regs[rd], cpu_regs[src]); + } + tcg_gen_shri_i32(cpu_psw_c, cpu_regs[rd], 31); + break; + } + tcg_gen_mov_i32(cpu_psw_z, cpu_regs[rd]); + tcg_gen_mov_i32(cpu_psw_s, cpu_regs[rd]); +} + +/* rotl #imm, rd */ +static bool trans_ROTL_ir(DisasContext *ctx, arg_ROTL_ir *a) +{ + rx_rot(ROT_IMM, ROTL, a->rd, a->imm); + return true; +} + +/* rotl rs, rd */ +static bool trans_ROTL_rr(DisasContext *ctx, arg_ROTL_rr *a) +{ + rx_rot(ROT_REG, ROTL, a->rd, a->rs); + return true; +} + +/* rotr #imm, rd */ +static bool trans_ROTR_ir(DisasContext *ctx, arg_ROTR_ir *a) +{ + rx_rot(ROT_IMM, ROTR, a->rd, a->imm); + return true; +} + +/* rotr rs, rd */ +static bool trans_ROTR_rr(DisasContext *ctx, arg_ROTR_rr *a) +{ + rx_rot(ROT_REG, ROTR, a->rd, a->rs); + return true; +} + +/* revl rs, rd */ +static bool trans_REVL(DisasContext *ctx, arg_REVL *a) +{ + tcg_gen_bswap32_i32(cpu_regs[a->rd], cpu_regs[a->rs]); + return true; +} + +/* revw rs, rd */ +static bool trans_REVW(DisasContext *ctx, arg_REVW *a) +{ + TCGv tmp; + tmp =3D tcg_temp_new(); + tcg_gen_andi_i32(tmp, cpu_regs[a->rs], 0x00ff00ff); + tcg_gen_shli_i32(tmp, tmp, 8); + tcg_gen_shri_i32(cpu_regs[a->rd], cpu_regs[a->rs], 8); + tcg_gen_andi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 0x00ff00ff); + tcg_gen_or_i32(cpu_regs[a->rd], cpu_regs[a->rd], tmp); + tcg_temp_free(tmp); + return true; +} + +/* conditional branch helper */ +static void rx_bcnd_main(DisasContext *ctx, int cd, int dst) +{ + DisasCompare dc; + TCGLabel *t, *done; + + switch (cd) { + case 0 ... 13: + dc.temp =3D tcg_temp_new(); + psw_cond(&dc, cd); + t =3D gen_new_label(); + done =3D gen_new_label(); + tcg_gen_brcondi_i32(dc.cond, dc.value, 0, t); + gen_goto_tb(ctx, 0, ctx->base.pc_next); + tcg_gen_br(done); + gen_set_label(t); + gen_goto_tb(ctx, 1, ctx->pc + dst); + gen_set_label(done); + tcg_temp_free(dc.temp); + break; + case 14: + /* always true case */ + gen_goto_tb(ctx, 0, ctx->pc + dst); + break; + case 15: + /* always false case */ + /* Nothing do */ + break; + } +} + +/* 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->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->dsp); + return true; +} + +/* bra rs */ +static bool trans_BRA_l(DisasContext *ctx, arg_BRA_l *a) +{ + tcg_gen_addi_i32(cpu_pc, cpu_regs[a->rd], ctx->pc); + ctx->base.is_jmp =3D DISAS_JUMP; + return true; +} + +static inline void rx_save_pc(DisasContext *ctx) +{ + TCGv pc =3D tcg_const_i32(ctx->base.pc_next); + push(pc); + tcg_temp_free(pc); +} + +/* jmp rs */ +static bool trans_JMP(DisasContext *ctx, arg_JMP *a) +{ + tcg_gen_mov_i32(cpu_pc, cpu_regs[a->rs]); + ctx->base.is_jmp =3D DISAS_JUMP; + return true; +} + +/* jsr rs */ +static bool trans_JSR(DisasContext *ctx, arg_JSR *a) +{ + rx_save_pc(ctx); + tcg_gen_mov_i32(cpu_pc, cpu_regs[a->rs]); + ctx->base.is_jmp =3D DISAS_JUMP; + return true; +} + +/* bsr dsp:16 */ +/* bsr dsp:24 */ +static bool trans_BSR(DisasContext *ctx, arg_BSR *a) +{ + rx_save_pc(ctx); + rx_bcnd_main(ctx, 14, a->dsp); + return true; +} + +/* bsr rs */ +static bool trans_BSR_l(DisasContext *ctx, arg_BSR_l *a) +{ + rx_save_pc(ctx); + tcg_gen_addi_i32(cpu_pc, cpu_regs[a->rd], ctx->pc); + ctx->base.is_jmp =3D DISAS_JUMP; + return true; +} + +/* rts */ +static bool trans_RTS(DisasContext *ctx, arg_RTS *a) +{ + pop(cpu_pc); + ctx->base.is_jmp =3D DISAS_JUMP; + return true; +} + +/* nop */ +static bool trans_NOP(DisasContext *ctx, arg_NOP *a) +{ + return true; +} + +/* scmpu */ +static bool trans_SCMPU(DisasContext *ctx, arg_SCMPU *a) +{ + gen_helper_scmpu(cpu_env); + return true; +} + +/* smovu */ +static bool trans_SMOVU(DisasContext *ctx, arg_SMOVU *a) +{ + gen_helper_smovu(cpu_env); + return true; +} + +/* smovf */ +static bool trans_SMOVF(DisasContext *ctx, arg_SMOVF *a) +{ + gen_helper_smovf(cpu_env); + return true; +} + +/* smovb */ +static bool trans_SMOVB(DisasContext *ctx, arg_SMOVB *a) +{ + gen_helper_smovb(cpu_env); + return true; +} + +#define STRING(op) \ + do { \ + TCGv size =3D tcg_const_i32(a->sz); \ + gen_helper_##op(cpu_env, size); \ + tcg_temp_free(size); \ + } while (0) + +/* suntile. */ +static bool trans_SUNTIL(DisasContext *ctx, arg_SUNTIL *a) +{ + STRING(suntil); + return true; +} + +/* swhile. */ +static bool trans_SWHILE(DisasContext *ctx, arg_SWHILE *a) +{ + STRING(swhile); + return true; +} +/* sstr. */ +static bool trans_SSTR(DisasContext *ctx, arg_SSTR *a) +{ + STRING(sstr); + return true; +} + +/* rmpa. */ +static bool trans_RMPA(DisasContext *ctx, arg_RMPA *a) +{ + STRING(rmpa); + return true; +} + +static void rx_mul64hi(TCGv_i64 ret, int rs, int rs2) +{ + TCGv_i64 tmp0, tmp1; + tmp0 =3D tcg_temp_new_i64(); + tmp1 =3D tcg_temp_new_i64(); + tcg_gen_ext_i32_i64(tmp0, cpu_regs[rs]); + tcg_gen_sari_i64(tmp0, tmp0, 16); + tcg_gen_ext_i32_i64(tmp1, cpu_regs[rs2]); + tcg_gen_sari_i64(tmp1, tmp1, 16); + tcg_gen_mul_i64(ret, tmp0, tmp1); + tcg_gen_shli_i64(ret, ret, 16); + tcg_temp_free_i64(tmp0); + tcg_temp_free_i64(tmp1); +} + +static void rx_mul64lo(TCGv_i64 ret, int rs, int rs2) +{ + TCGv_i64 tmp0, tmp1; + tmp0 =3D tcg_temp_new_i64(); + tmp1 =3D tcg_temp_new_i64(); + tcg_gen_ext_i32_i64(tmp0, cpu_regs[rs]); + tcg_gen_ext16s_i64(tmp0, tmp0); + tcg_gen_ext_i32_i64(tmp1, cpu_regs[rs2]); + tcg_gen_ext16s_i64(tmp1, tmp1); + tcg_gen_mul_i64(ret, tmp0, tmp1); + tcg_gen_shli_i64(ret, ret, 16); + tcg_temp_free_i64(tmp0); + tcg_temp_free_i64(tmp1); +} + +/* mulhi rs,rs2 */ +static bool trans_MULHI(DisasContext *ctx, arg_MULHI *a) +{ + rx_mul64hi(cpu_acc, a->rs, a->rs2); + return true; +} + +/* mullo rs,rs2 */ +static bool trans_MULLO(DisasContext *ctx, arg_MULLO *a) +{ + rx_mul64lo(cpu_acc, a->rs, a->rs2); + return true; +} + +/* machi rs,rs2 */ +static bool trans_MACHI(DisasContext *ctx, arg_MACHI *a) +{ + TCGv_i64 tmp; + tmp =3D tcg_temp_new_i64(); + rx_mul64hi(tmp, a->rs, a->rs2); + tcg_gen_add_i64(cpu_acc, cpu_acc, tmp); + tcg_temp_free_i64(tmp); + return true; +} + +/* maclo rs,rs2 */ +static bool trans_MACLO(DisasContext *ctx, arg_MACLO *a) +{ + TCGv_i64 tmp; + tmp =3D tcg_temp_new_i64(); + rx_mul64lo(tmp, a->rs, a->rs2); + tcg_gen_add_i64(cpu_acc, cpu_acc, tmp); + tcg_temp_free_i64(tmp); + return true; +} + +/* mvfachi rd */ +static bool trans_MVFACHI(DisasContext *ctx, arg_MVFACHI *a) +{ + tcg_gen_extrh_i64_i32(cpu_regs[a->rd], cpu_acc); + return true; +} + +/* mvfacmi rd */ +static bool trans_MVFACMI(DisasContext *ctx, arg_MVFACMI *a) +{ + TCGv_i64 rd64; + rd64 =3D tcg_temp_new_i64(); + tcg_gen_extract_i64(rd64, cpu_acc, 16, 32); + tcg_gen_extrl_i64_i32(cpu_regs[a->rd], rd64); + tcg_temp_free_i64(rd64); + return true; +} + +/* mvtachi rs */ +static bool trans_MVTACHI(DisasContext *ctx, arg_MVTACHI *a) +{ + TCGv_i64 rs64; + rs64 =3D tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(rs64, cpu_regs[a->rs]); + tcg_gen_deposit_i64(cpu_acc, cpu_acc, rs64, 32, 32); + tcg_temp_free_i64(rs64); + return true; +} + +/* mvtaclo rs */ +static bool trans_MVTACLO(DisasContext *ctx, arg_MVTACLO *a) +{ + TCGv_i64 rs64; + rs64 =3D tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(rs64, cpu_regs[a->rs]); + tcg_gen_deposit_i64(cpu_acc, cpu_acc, rs64, 0, 32); + tcg_temp_free_i64(rs64); + return true; +} + +/* racw #imm */ +static bool trans_RACW(DisasContext *ctx, arg_RACW *a) +{ + TCGv imm =3D tcg_const_i32(a->imm + 1); + gen_helper_racw(cpu_env, imm); + tcg_temp_free(imm); + return true; +} + +/* sat rd */ +static bool trans_SAT(DisasContext *ctx, arg_SAT *a) +{ + TCGv tmp, z; + tmp =3D tcg_temp_new(); + z =3D tcg_const_i32(0); + /* S =3D=3D 1 -> 0xffffffff / S =3D=3D 0 -> 0x00000000 */ + tcg_gen_sari_i32(tmp, cpu_psw_s, 31); + /* S =3D=3D 1 -> 0x7fffffff / S =3D=3D 0 -> 0x80000000 */ + tcg_gen_xori_i32(tmp, tmp, 0x80000000); + tcg_gen_movcond_i32(TCG_COND_LT, cpu_regs[a->rd], + cpu_psw_o, z, tmp, cpu_regs[a->rd]); + tcg_temp_free(tmp); + tcg_temp_free(z); + return true; +} + +/* satr */ +static bool trans_SATR(DisasContext *ctx, arg_SATR *a) +{ + gen_helper_satr(cpu_env); + return true; +} + +#define cat3(a, b, c) a##b##c +#define FOP(name, op) \ + static bool cat3(trans_, name, _ir)(DisasContext *ctx, \ + cat3(arg_, name, _ir) * a) \ + { \ + TCGv imm =3D tcg_const_i32(li(ctx, 0)); \ + gen_helper_##op(cpu_regs[a->rd], cpu_env, \ + cpu_regs[a->rd], imm); \ + tcg_temp_free(imm); \ + return true; \ + } \ + static bool cat3(trans_, name, _mr)(DisasContext *ctx, \ + cat3(arg_, name, _mr) * a) \ + { \ + TCGv val, mem; \ + mem =3D tcg_temp_new(); \ + val =3D rx_load_source(ctx, mem, a->ld, MO_32, a->rs); \ + gen_helper_##op(cpu_regs[a->rd], cpu_env, \ + cpu_regs[a->rd], val); \ + tcg_temp_free(mem); \ + return true; \ + } + +#define FCONVOP(name, op) \ + static bool trans_##name(DisasContext *ctx, arg_##name * a) \ + { \ + TCGv val, mem; \ + mem =3D tcg_temp_new(); \ + val =3D rx_load_source(ctx, mem, a->ld, MO_32, a->rs); \ + gen_helper_##op(cpu_regs[a->rd], cpu_env, val); \ + tcg_temp_free(mem); \ + return true; \ + } + +FOP(FADD, fadd) +FOP(FSUB, fsub) +FOP(FMUL, fmul) +FOP(FDIV, fdiv) + +/* fcmp #imm, rd */ +static bool trans_FCMP_ir(DisasContext *ctx, arg_FCMP_ir * a) +{ + TCGv imm =3D tcg_const_i32(li(ctx, 0)); + gen_helper_fcmp(cpu_env, cpu_regs[a->rd], imm); + tcg_temp_free(imm); + return true; +} + +/* fcmp dsp[rs], rd */ +/* fcmp rs, rd */ +static bool trans_FCMP_mr(DisasContext *ctx, arg_FCMP_mr *a) +{ + TCGv val, mem; + mem =3D tcg_temp_new(); + val =3D rx_load_source(ctx, mem, a->ld, MO_32, a->rs); + gen_helper_fcmp(cpu_env, cpu_regs[a->rd], val); + tcg_temp_free(mem); + return true; +} + +FCONVOP(FTOI, ftoi) +FCONVOP(ROUND, round) + +/* itof rs, rd */ +/* itof dsp[rs], rd */ +static bool trans_ITOF(DisasContext *ctx, arg_ITOF * a) +{ + TCGv val, mem; + mem =3D tcg_temp_new(); + val =3D rx_load_source(ctx, mem, a->ld, a->mi, a->rs); + gen_helper_itof(cpu_regs[a->rd], cpu_env, val); + tcg_temp_free(mem); + return true; +} + +static void rx_bsetm(TCGv mem, TCGv mask) +{ + TCGv val; + val =3D tcg_temp_new(); + rx_gen_ld(MO_8, val, mem); + tcg_gen_or_i32(val, val, mask); + rx_gen_st(MO_8, val, mem); + tcg_temp_free(val); +} + +static void rx_bclrm(TCGv mem, TCGv mask) +{ + TCGv val; + val =3D tcg_temp_new(); + rx_gen_ld(MO_8, val, mem); + tcg_gen_andc_i32(val, val, mask); + rx_gen_st(MO_8, val, mem); + tcg_temp_free(val); +} + +static void rx_btstm(TCGv mem, TCGv mask) +{ + TCGv val; + val =3D tcg_temp_new(); + rx_gen_ld(MO_8, val, mem); + tcg_gen_and_i32(val, val, mask); + tcg_gen_setcondi_i32(TCG_COND_NE, cpu_psw_c, val, 0); + tcg_gen_mov_i32(cpu_psw_z, cpu_psw_c); + tcg_temp_free(val); +} + +static void rx_bnotm(TCGv mem, TCGv mask) +{ + TCGv val; + val =3D tcg_temp_new(); + rx_gen_ld(MO_8, val, mem); + tcg_gen_xor_i32(val, val, mask); + rx_gen_st(MO_8, val, mem); + tcg_temp_free(val); +} + +static void rx_bsetr(TCGv reg, TCGv mask) +{ + tcg_gen_or_i32(reg, reg, mask); +} + +static void rx_bclrr(TCGv reg, TCGv mask) +{ + tcg_gen_andc_i32(reg, reg, mask); +} + +static inline void rx_btstr(TCGv reg, TCGv mask) +{ + TCGv t0; + t0 =3D tcg_temp_new(); + tcg_gen_and_i32(t0, reg, mask); + tcg_gen_setcondi_i32(TCG_COND_NE, cpu_psw_c, t0, 0); + tcg_gen_mov_i32(cpu_psw_z, cpu_psw_c); + tcg_temp_free(t0); +} + +static inline void rx_bnotr(TCGv reg, TCGv mask) +{ + tcg_gen_xor_i32(reg, reg, mask); +} + +#define BITOP(name, op) \ + static bool cat3(trans_, name, _im)(DisasContext *ctx, \ + cat3(arg_, name, _im) * a) \ + { \ + TCGv mask, mem, addr; \ + mem =3D tcg_temp_new(); \ + mask =3D tcg_const_i32(1 << a->imm); \ + addr =3D rx_index_addr(ctx, mem, a->ld, MO_8, a->rs); \ + cat3(rx_, op, m)(addr, mask); \ + tcg_temp_free(mask); \ + tcg_temp_free(mem); \ + return true; \ + } \ + static bool cat3(trans_, name, _ir)(DisasContext *ctx, \ + cat3(arg_, name, _ir) * a) \ + { \ + TCGv mask; \ + mask =3D tcg_const_i32(1 << a->imm); \ + cat3(rx_, op, r)(cpu_regs[a->rd], mask); \ + tcg_temp_free(mask); \ + return true; \ + } \ + static bool cat3(trans_, name, _rr)(DisasContext *ctx, \ + cat3(arg_, name, _rr) * a) \ + { \ + TCGv mask, b; \ + mask =3D tcg_const_i32(1); \ + b =3D tcg_temp_new(); \ + tcg_gen_andi_i32(b, cpu_regs[a->rs], 31); \ + tcg_gen_shl_i32(mask, mask, b); \ + cat3(rx_, op, r)(cpu_regs[a->rd], mask); \ + tcg_temp_free(mask); \ + tcg_temp_free(b); \ + return true; \ + } \ + static bool cat3(trans_, name, _rm)(DisasContext *ctx, \ + cat3(arg_, name, _rm) * a) \ + { \ + TCGv mask, mem, addr, b; \ + mask =3D tcg_const_i32(1); \ + b =3D tcg_temp_new(); \ + tcg_gen_andi_i32(b, cpu_regs[a->rd], 7); \ + tcg_gen_shl_i32(mask, mask, b); \ + mem =3D tcg_temp_new(); \ + addr =3D rx_index_addr(ctx, mem, a->ld, MO_8, a->rs); \ + cat3(rx_, op, m)(addr, mask); \ + tcg_temp_free(mem); \ + tcg_temp_free(mask); \ + tcg_temp_free(b); \ + return true; \ + } + +BITOP(BSET, bset) +BITOP(BCLR, bclr) +BITOP(BTST, btst) +BITOP(BNOT, bnot) + +static inline void bmcnd_op(TCGv val, TCGCond cond, int pos) +{ + TCGv bit; + DisasCompare dc; + dc.temp =3D tcg_temp_new(); + bit =3D tcg_temp_new(); + psw_cond(&dc, cond); + tcg_gen_andi_i32(val, val, ~(1 << pos)); + tcg_gen_setcondi_i32(dc.cond, bit, dc.value, 0); + tcg_gen_deposit_i32(val, val, bit, pos, 1); + tcg_temp_free(bit); + tcg_temp_free(dc.temp); + } + +/* bmcnd #imm, dsp[rd] */ +static bool trans_BMCnd_im(DisasContext *ctx, arg_BMCnd_im *a) +{ + TCGv val, mem, addr; + val =3D tcg_temp_new(); + mem =3D tcg_temp_new(); + addr =3D rx_index_addr(ctx, mem, a->ld, MO_8, a->rd); + rx_gen_ld(MO_8, val, addr); + bmcnd_op(val, a->cd, a->imm); + rx_gen_st(MO_8, val, addr); + tcg_temp_free(val); + tcg_temp_free(mem); + return true; +} + +/* bmcond #imm, rd */ +static bool trans_BMCnd_ir(DisasContext *ctx, arg_BMCnd_ir *a) +{ + bmcnd_op(cpu_regs[a->rd], a->cd, a->imm); + return true; +} + +enum { + PSW_C =3D 0, + PSW_Z =3D 1, + PSW_S =3D 2, + PSW_O =3D 3, + PSW_I =3D 8, + PSW_U =3D 9, +}; + +static inline void clrsetpsw(DisasContext *ctx, int cb, int val) +{ + if (cb < 8) { + switch (cb) { + case PSW_C: + tcg_gen_movi_i32(cpu_psw_c, val); + break; + case PSW_Z: + tcg_gen_movi_i32(cpu_psw_z, val =3D=3D 0); + break; + case PSW_S: + tcg_gen_movi_i32(cpu_psw_s, val ? -1 : 0); + break; + case PSW_O: + tcg_gen_movi_i32(cpu_psw_o, val << 31); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "Invalid distination %d", cb); + break; + } + } else if (is_privileged(ctx, 0)) { + switch (cb) { + case PSW_I: + tcg_gen_movi_i32(cpu_psw_i, val); + ctx->base.is_jmp =3D DISAS_UPDATE; + break; + case PSW_U: + tcg_gen_movi_i32(cpu_psw_u, val); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "Invalid distination %d", cb); + break; + } + } +} + +/* clrpsw psw */ +static bool trans_CLRPSW(DisasContext *ctx, arg_CLRPSW *a) +{ + clrsetpsw(ctx, a->cb, 0); + return true; +} + +/* setpsw psw */ +static bool trans_SETPSW(DisasContext *ctx, arg_SETPSW *a) +{ + clrsetpsw(ctx, a->cb, 1); + return true; +} + +/* mvtipl #imm */ +static bool trans_MVTIPL(DisasContext *ctx, arg_MVTIPL *a) +{ + if (is_privileged(ctx, 1)) { + tcg_gen_movi_i32(cpu_psw_ipl, a->imm); + ctx->base.is_jmp =3D DISAS_UPDATE; + } + return true; +} + +/* mvtc #imm, rd */ +static bool trans_MVTC_i(DisasContext *ctx, arg_MVTC_i *a) +{ + TCGv imm; + + imm =3D tcg_const_i32(a->imm); + move_to_cr(ctx, imm, a->cr); + if (a->cr =3D=3D 0 && is_privileged(ctx, 0)) { + ctx->base.is_jmp =3D DISAS_UPDATE; + } + tcg_temp_free(imm); + return true; +} + +/* mvtc rs, rd */ +static bool trans_MVTC_r(DisasContext *ctx, arg_MVTC_r *a) +{ + move_to_cr(ctx, cpu_regs[a->rs], a->cr); + if (a->cr =3D=3D 0 && is_privileged(ctx, 0)) { + ctx->base.is_jmp =3D DISAS_UPDATE; + } + return true; +} + +/* mvfc rs, rd */ +static bool trans_MVFC(DisasContext *ctx, arg_MVFC *a) +{ + move_from_cr(cpu_regs[a->rd], a->cr, ctx->pc); + return true; +} + +/* rtfi */ +static bool trans_RTFI(DisasContext *ctx, arg_RTFI *a) +{ + TCGv psw; + if (is_privileged(ctx, 1)) { + psw =3D tcg_temp_new(); + tcg_gen_mov_i32(cpu_pc, cpu_bpc); + tcg_gen_mov_i32(psw, cpu_bpsw); + gen_helper_set_psw_rte(cpu_env, psw); + ctx->base.is_jmp =3D DISAS_EXIT; + tcg_temp_free(psw); + } + return true; +} + +/* rte */ +static bool trans_RTE(DisasContext *ctx, arg_RTE *a) +{ + TCGv psw; + if (is_privileged(ctx, 1)) { + psw =3D tcg_temp_new(); + pop(cpu_pc); + pop(psw); + gen_helper_set_psw_rte(cpu_env, psw); + ctx->base.is_jmp =3D DISAS_EXIT; + tcg_temp_free(psw); + } + return true; +} + +/* brk */ +static bool trans_BRK(DisasContext *ctx, arg_BRK *a) +{ + tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next); + gen_helper_rxbrk(cpu_env); + ctx->base.is_jmp =3D DISAS_NORETURN; + return true; +} + +/* int #imm */ +static bool trans_INT(DisasContext *ctx, arg_INT *a) +{ + TCGv vec; + + tcg_debug_assert(a->imm < 0x100); + vec =3D tcg_const_i32(a->imm); + tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next); + gen_helper_rxint(cpu_env, vec); + tcg_temp_free(vec); + ctx->base.is_jmp =3D DISAS_NORETURN; + return true; +} + +/* wait */ +static bool trans_WAIT(DisasContext *ctx, arg_WAIT *a) +{ + if (is_privileged(ctx, 1)) { + tcg_gen_addi_i32(cpu_pc, cpu_pc, 2); + gen_helper_wait(cpu_env); + } + return true; +} + +static void rx_tr_init_disas_context(DisasContextBase *dcbase, CPUState *c= s) +{ + CPURXState *env =3D cs->env_ptr; + DisasContext *ctx =3D container_of(dcbase, DisasContext, base); + ctx->env =3D env; +} + +static void rx_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) +{ +} + +static void rx_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *ctx =3D container_of(dcbase, DisasContext, base); + + tcg_gen_insn_start(ctx->base.pc_next); +} + +static bool rx_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, + const CPUBreakpoint *bp) +{ + DisasContext *ctx =3D container_of(dcbase, DisasContext, base); + + /* We have hit a breakpoint - make sure PC is up-to-date */ + tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next); + gen_helper_debug(cpu_env); + ctx->base.is_jmp =3D DISAS_NORETURN; + ctx->base.pc_next +=3D 1; + return true; +} + +static void rx_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *ctx =3D container_of(dcbase, DisasContext, base); + uint32_t insn; + + ctx->pc =3D ctx->base.pc_next; + insn =3D decode_load(ctx); + if (!decode(ctx, insn)) { + gen_helper_raise_illegal_instruction(cpu_env); + } +} + +static void rx_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *ctx =3D container_of(dcbase, DisasContext, base); + + switch (ctx->base.is_jmp) { + case DISAS_NEXT: + case DISAS_TOO_MANY: + gen_goto_tb(ctx, 0, dcbase->pc_next); + break; + case DISAS_JUMP: + if (ctx->base.singlestep_enabled) { + gen_helper_debug(cpu_env); + } else { + tcg_gen_lookup_and_goto_ptr(); + } + break; + case DISAS_UPDATE: + tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next); + case DISAS_EXIT: + tcg_gen_exit_tb(NULL, 0); + break; + case DISAS_NORETURN: + break; + default: + g_assert_not_reached(); + } +} + +static void rx_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) +{ + qemu_log("IN:\n"); /* , lookup_symbol(dcbase->pc_first)); */ + log_target_disas(cs, dcbase->pc_first, dcbase->tb->size); +} + +static const TranslatorOps rx_tr_ops =3D { + .init_disas_context =3D rx_tr_init_disas_context, + .tb_start =3D rx_tr_tb_start, + .insn_start =3D rx_tr_insn_start, + .breakpoint_check =3D rx_tr_breakpoint_check, + .translate_insn =3D rx_tr_translate_insn, + .tb_stop =3D rx_tr_tb_stop, + .disas_log =3D rx_tr_disas_log, +}; + +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_ins= ns) +{ + DisasContext dc; + + translator_loop(&rx_tr_ops, &dc.base, cs, tb, max_insns); +} + +void restore_state_to_opc(CPURXState *env, TranslationBlock *tb, + target_ulong *data) +{ + env->pc =3D data[0]; +} + +#define ALLOC_REGISTER(sym, name) \ + cpu_##sym =3D tcg_global_mem_new_i32(cpu_env, \ + offsetof(CPURXState, sym), name) + +void rx_translate_init(void) +{ + static const char * const regnames[NUM_REGS] =3D { + "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", + "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15" + }; + int i; + + for (i =3D 0; i < NUM_REGS; i++) { + cpu_regs[i] =3D tcg_global_mem_new_i32(cpu_env, + offsetof(CPURXState, regs[i]= ), + regnames[i]); + } + ALLOC_REGISTER(pc, "PC"); + ALLOC_REGISTER(psw_o, "PSW(O)"); + ALLOC_REGISTER(psw_s, "PSW(S)"); + ALLOC_REGISTER(psw_z, "PSW(Z)"); + ALLOC_REGISTER(psw_c, "PSW(C)"); + ALLOC_REGISTER(psw_u, "PSW(U)"); + ALLOC_REGISTER(psw_i, "PSW(I)"); + ALLOC_REGISTER(psw_pm, "PSW(PM)"); + ALLOC_REGISTER(psw_ipl, "PSW(IPL)"); + ALLOC_REGISTER(usp, "USP"); + ALLOC_REGISTER(fpsw, "FPSW"); + ALLOC_REGISTER(bpsw, "BPSW"); + ALLOC_REGISTER(bpc, "BPC"); + ALLOC_REGISTER(isp, "ISP"); + ALLOC_REGISTER(fintv, "FINTV"); + ALLOC_REGISTER(intb, "INTB"); + cpu_acc =3D tcg_global_mem_new_i64(cpu_env, + offsetof(CPURXState, acc), "ACC"); +} diff --git a/target/rx/Makefile.objs b/target/rx/Makefile.objs new file mode 100644 index 0000000000..aa6f2d2d6c --- /dev/null +++ b/target/rx/Makefile.objs @@ -0,0 +1,12 @@ +obj-y +=3D translate.o op_helper.o helper.o cpu.o gdbstub.o disas.o +obj-$(CONFIG_SOFTMMU) +=3D monitor.o + +DECODETREE =3D $(SRC_PATH)/scripts/decodetree.py + +target/rx/decode.inc.c: \ + $(SRC_PATH)/target/rx/insns.decode $(DECODETREE) + $(call quiet-command,\ + $(PYTHON) $(DECODETREE) --varinsnwidth 32 -o $@ $<, "GEN", $(TARGET_DIR= )$@) + +target/rx/translate.o: target/rx/decode.inc.c +target/rx/disas.o: target/rx/decode.inc.c diff --git a/target/rx/insns.decode b/target/rx/insns.decode new file mode 100644 index 0000000000..232a61fc8e --- /dev/null +++ b/target/rx/insns.decode @@ -0,0 +1,621 @@ +# +# Renesas RX instruction decode definitions. +# +# Copyright (c) 2019 Richard Henderson +# Copyright (c) 2019 Yoshinori Sato +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . +# + +&bcnd cd dsp sz +&jdsp dsp sz +&jreg rs +&rr rd rs +&ri rd imm +&rrr rd rs rs2 +&rri rd imm rs2 +&rm rd rs ld mi +&mi rs ld mi imm +&mr rs ld mi rs2 +&mcnd ld sz rd cd +######## +%b1_bdsp 24:3 !function=3Dbdsp_s + +@b1_bcnd_s .... cd:1 ... &bcnd dsp=3D%b1_bdsp sz=3D1 +@b1_bra_s .... .... &jdsp dsp=3D%b1_bdsp sz=3D1 + +%b2_r_0 16:4 +%b2_li_2 18:2 !function=3Dli +%b2_li_8 24:2 !function=3Dli +%b2_dsp5_3 23:4 19:1 + +@b2_rds .... .... .... rd:4 &rr rs=3D%b2_r_0 +@b2_rds_li .... .... .... rd:4 &rri rs2=3D%b2_r_0 imm=3D%b2_li_8 +@b2_rds_uimm4 .... .... imm:4 rd:4 &rri rs2=3D%b2_r_0 +@b2_rs2_uimm4 .... .... imm:4 rs2:4 &rri rd=3D0 +@b2_rds_imm5 .... ... imm:5 rd:4 &rri rs2=3D%b2_r_0 +@b2_rd_rs_li .... .... rs2:4 rd:4 &rri imm=3D%b2_li_8 +@b2_rd_ld_ub .... .. ld:2 rs:4 rd:4 &rm mi=3D4 +@b2_ld_imm3 .... .. ld:2 rs:4 . imm:3 &mi mi=3D4 +@b2_bcnd_b .... cd:4 dsp:s8 &bcnd sz=3D2 +@b2_bra_b .... .... dsp:s8 &jdsp sz=3D2 + +######## + +%b3_r_0 8:4 +%b3_li_10 18:2 !function=3Dli +%b3_dsp5_8 23:1 16:4 +%b3_bdsp 8:s8 16:8 + +@b3_rd_rs .... .... .... .... rs:4 rd:4 &rr +@b3_rs_rd .... .... .... .... rd:4 rs:4 &rr +@b3_rd_li .... .... .... .... .... rd:4 \ + &rri rs2=3D%b3_r_0 imm=3D%b3_li_10 +@b3_rd_ld .... .... mi:2 .... ld:2 rs:4 rd:4 &rm +@b3_rd_ld_ub .... .... .... .. ld:2 rs:4 rd:4 &rm mi=3D4 +@b3_rd_ld_ul .... .... .... .. ld:2 rs:4 rd:4 &rm mi=3D2 +@b3_rd_rs_rs2 .... .... .... rd:4 rs:4 rs2:4 &rrr +@b3_rds_imm5 .... .... ....... imm:5 rd:4 &rri rs2=3D%b3_r_0 +@b3_rd_rs_imm5 .... .... ... imm:5 rs2:4 rd:4 &rri +@b3_bcnd_w .... ... cd:1 .... .... .... .... &bcnd dsp=3D%b3_bdsp sz=3D3 +@b3_bra_w .... .... .... .... .... .... &jdsp dsp=3D%b3_bdsp sz=3D3 +@b3_ld_rd_rs .... .... .... .. ld:2 rs:4 rd:4 &rm mi=3D0 +@b3_sz_ld_rd_cd .... .... .... sz:2 ld:2 rd:4 cd:4 &mcnd + +######## + +%b4_li_18 18:2 !function=3Dli +%b4_dsp_16 0:s8 8:8 +%b4_bdsp 0:s8 8:8 16:8 + +@b4_rd_ldmi .... .... mi:2 .... ld:2 .... .... rs:4 rd:4 &rm +@b4_bra_a .... .... .... .... .... .... .... .... \ + &jdsp dsp=3D%b4_bdsp sz=3D4 +######## +# ABS rd +ABS_rr 0111 1110 0010 .... @b2_rds +# ABS rs, rd +ABS_rr 1111 1100 0000 1111 .... .... @b3_rd_rs + +# ADC #imm, rd +ADC_ir 1111 1101 0111 ..00 0010 .... @b3_rd_li +# ADC rs, rd +ADC_rr 1111 1100 0000 1011 .... .... @b3_rd_rs +# ADC dsp[rs].l, rd +# Note only mi=3D=3D2 allowed. +ADC_mr 0000 0110 ..10 00.. 0000 0010 .... .... @b4_rd_ldmi + +# ADD #uimm4, rd +ADD_irr 0110 0010 .... .... @b2_rds_uimm4 +# ADD #imm, rs, rd +ADD_irr 0111 00.. .... .... @b2_rd_rs_li +# ADD dsp[rs].ub, rd +# ADD rs, rd +ADD_mr 0100 10.. .... .... @b2_rd_ld_ub +# ADD dsp[rs], rd +ADD_mr 0000 0110 ..00 10.. .... .... @b3_rd_ld +# ADD rs, rs2, rd +ADD_rrr 1111 1111 0010 .... .... .... @b3_rd_rs_rs2 + +# AND #uimm4, rd +AND_ir 0110 0100 .... .... @b2_rds_uimm4 +# AND #imm, rd +AND_ir 0111 01.. 0010 .... @b2_rds_li +# AND dsp[rs].ub, rd +# AND rs, rd +AND_mr 0101 00.. .... .... @b2_rd_ld_ub +# AND dsp[rs], rd +AND_mr 0000 0110 ..01 00.. .... .... @b3_rd_ld +# AND rs, rs2, rd +AND_rrr 1111 1111 0100 .... .... .... @b3_rd_rs_rs2 + +# BCLR #imm, dsp[rd] +BCLR_im 1111 00.. .... 1... @b2_ld_imm3 +# BCLR #imm, rs +BCLR_ir 0111 101. .... .... @b2_rds_imm5 +# BCLR rs, rd +# BCLR rs, dsp[rd] +{ + BCLR_rr 1111 1100 0110 0111 .... .... @b3_rs_rd + BCLR_rm 1111 1100 0110 01.. .... .... @b3_rd_ld_ub +} + +# BCnd.s dsp +BCnd 0001 .... @b1_bcnd_s +# BRA.b dsp +# BCnd.b dsp +{ + BRA 0010 1110 .... .... @b2_bra_b + BCnd 0010 .... .... .... @b2_bcnd_b +} + +# BCnd.w dsp +BCnd 0011 101 . .... .... .... .... @b3_bcnd_w + +# BNOT #imm, dsp[rd] +# BMCnd #imm, dsp[rd] +{ + BNOT_im 1111 1100 111 imm:3 ld:2 rs:4 1111 + BMCnd_im 1111 1100 111 imm:3 ld:2 rd:4 cd:4 +} + +# BNOT #imm, rd +# BMCnd #imm, rd +{ + BNOT_ir 1111 1101 111 imm:5 1111 rd:4 + BMCnd_ir 1111 1101 111 imm:5 cd:4 rd:4 +} + +# BNOT rs, rd +# BNOT rs, dsp[rd] +{ + BNOT_rr 1111 1100 0110 1111 .... .... @b3_rs_rd + BNOT_rm 1111 1100 0110 11.. .... .... @b3_rd_ld_ub +} + +# BRA.s dsp +BRA 0000 1 ... @b1_bra_s +# BRA.w dsp +BRA 0011 1000 .... .... .... .... @b3_bra_w +# BRA.a dsp +BRA 0000 0100 .... .... .... .... .... .... @b4_bra_a +# BRA.l rs +BRA_l 0111 1111 0100 rd:4 + +BRK 0000 0000 + +# BSET #imm, dsp[rd] +BSET_im 1111 00.. .... 0... @b2_ld_imm3 +# BSET #imm, rd +BSET_ir 0111 100. .... .... @b2_rds_imm5 +# BSET rs, rd +# BSET rs, dsp[rd] +{ + BSET_rr 1111 1100 0110 0011 .... .... @b3_rs_rd + BSET_rm 1111 1100 0110 00.. .... .... @b3_rd_ld_ub +} + +# BSR.w dsp +BSR 0011 1001 .... .... .... .... @b3_bra_w +# BSR.a dsp +BSR 0000 0101 .... .... .... .... .... .... @b4_bra_a +# BSR.l rs +BSR_l 0111 1111 0101 rd:4 + +# BSET #imm, dsp[rd] +BTST_im 1111 01.. .... 0... @b2_ld_imm3 +# BSET #imm, rd +BTST_ir 0111 110. .... .... @b2_rds_imm5 +# BSET rs, rd +# BSET rs, dsp[rd] +{ + BTST_rr 1111 1100 0110 1011 .... .... @b3_rs_rd + BTST_rm 1111 1100 0110 10.. .... .... @b3_rd_ld_ub +} + +# CLRSPW psw +CLRPSW 0111 1111 1011 cb:4 + +# CMP #uimm4, rs2 +CMP_ir 0110 0001 .... .... @b2_rs2_uimm4 +# CMP #uimm8, rs2 +CMP_ir 0111 0101 0101 rs2:4 imm:8 &rri rd=3D0 +# CMP #imm, rs2 +CMP_ir 0111 01.. 0000 rs2:4 &rri imm=3D%b2_li_8 rd=3D0 +# CMP dsp[rs].ub, rs2 +# CMP rs, rs2 +CMP_mr 0100 01.. .... .... @b2_rd_ld_ub +# CMP dsp[rs], rs2 +CMP_mr 0000 0110 ..00 01.. .... .... @b3_rd_ld + +# DIV #imm, rd +DIV_ir 1111 1101 0111 ..00 1000 .... @b3_rd_li +# DIV dsp[rs].ub, rd +# DIV rs, rd +DIV_mr 1111 1100 0010 00.. .... .... @b3_rd_ld_ub +# DIV dsp[rs], rd +DIV_mr 0000 0110 ..10 00.. 0000 1000 .... .... @b4_rd_ldmi + +# DIVU #imm, rd +DIVU_ir 1111 1101 0111 ..00 1001 .... @b3_rd_li +# DIVU dsp[rs].ub, rd +# DIVU rs, rd +DIVU_mr 1111 1100 0010 01.. .... .... @b3_rd_ld_ub +# DIVU dsp[rs], rd +DIVU_mr 0000 0110 ..10 00.. 0000 1001 .... .... @b4_rd_ldmi + +# EMUL #imm, rd +EMUL_ir 1111 1101 0111 ..00 0110 .... @b3_rd_li +# EMUL dsp[rs].ub, rd +# EMUL rs, rd +EMUL_mr 1111 1100 0001 10.. .... .... @b3_rd_ld_ub +# EMUL dsp[rs], rd +EMUL_mr 0000 0110 ..10 00.. 0000 0110 .... .... @b4_rd_ldmi + +# EMULU #imm, rd +EMULU_ir 1111 1101 0111 ..00 0111 .... @b3_rd_li +# EMULU dsp[rs].ub, rd +# EMULU rs, rd +EMULU_mr 1111 1100 0001 11.. .... .... @b3_rd_ld_ub +# EMULU dsp[rs], rd +EMULU_mr 0000 0110 ..10 00.. 0000 0111 .... .... @b4_rd_ldmi + +# FADD #imm, rd +FADD_ir 1111 1101 0111 0010 0010 rd:4 +# FADD rs, rd +# FADD dsp[rs], rd +FADD_mr 1111 1100 1000 10.. .... .... @b3_rd_ld_ul + +# FCMP #imm, rd +FCMP_ir 1111 1101 0111 0010 0001 rd:4 +# FCMP rs, rd +# FCMP dsp[rs], rd +FCMP_mr 1111 1100 1000 01.. .... .... @b3_rd_ld_ul + +# FDIV #imm, rd +FDIV_ir 1111 1101 0111 0010 0100 rd:4 +# FDIV rs, rd +# FDIV dsp[rs], rd +FDIV_mr 1111 1100 1001 00.. .... .... @b3_rd_ld_ul + +# FMUL #imm, rd +FMUL_ir 1111 1101 0111 0010 0011 rd:4 +# FMUL rs, rd +# FMUL dsp[rs], rd +FMUL_mr 1111 1100 1000 11.. .... .... @b3_rd_ld_ul + +# FSUB #imm, rd +FSUB_ir 1111 1101 0111 0010 0000 rd:4 +# FSUB rs, rd +# FSUB dsp[rs], rd +FSUB_mr 1111 1100 1000 00.. .... .... @b3_rd_ld_ul + +# FTOI rs, rd +# FTOI dsp[rs], rd +FTOI 1111 1100 1001 01.. .... .... @b3_rd_ld_ul + +# INT #uimm8 +INT 0111 0101 0110 0000 imm:8 + +# ITOF dsp[rs].ub, rd +# ITOF rs, rd +ITOF 1111 1100 0100 01.. .... .... @b3_rd_ld_ub +# ITOF dsp[rs], rd +ITOF 0000 0110 ..10 00.. 0001 0001 .... .... @b4_rd_ldmi + +# JMP rs +JMP 0111 1111 0000 rs:4 &jreg +# JSR rs +JSR 0111 1111 0001 rs:4 &jreg + +# MACHI rs, rs2 +MACHI 1111 1101 0000 0100 rs:4 rs2:4 +# MACLO rs, rs2 +MACLO 1111 1101 0000 0101 rs:4 rs2:4 + +# MAX #imm, rd +MAX_ir 1111 1101 0111 ..00 0100 .... @b3_rd_li +# MAX dsp[rs].ub, rd +# MAX rs, rd +MAX_mr 1111 1100 0001 00.. .... .... @b3_rd_ld_ub +# MAX dsp[rs], rd +MAX_mr 0000 0110 ..10 00.. 0000 0100 .... .... @b4_rd_ldmi + +# MIN #imm, rd +MIN_ir 1111 1101 0111 ..00 0101 .... @b3_rd_li +# MIN dsp[rs].ub, rd +# MIN rs, rd +MIN_mr 1111 1100 0001 01.. .... .... @b3_rd_ld_ub +# MIN dsp[rs], rd +MIN_mr 0000 0110 ..10 00.. 0000 0101 .... .... @b4_rd_ldmi + +# MOV.b rs, dsp5[rd] +MOV_rm 1000 0 .... rd:3 . rs:3 dsp=3D%b2_dsp5_3 sz=3D0 +# MOV.w rs, dsp5[rd] +MOV_rm 1001 0 .... rd:3 . rs:3 dsp=3D%b2_dsp5_3 sz=3D1 +# MOV.l rs, dsp5[rd] +MOV_rm 1010 0 .... rd:3 . rs:3 dsp=3D%b2_dsp5_3 sz=3D2 +# MOV.b dsp5[rs], rd +MOV_mr 1000 1 .... rs:3 . rd:3 dsp=3D%b2_dsp5_3 sz=3D0 +# MOV.w dsp5[rs], rd +MOV_mr 1001 1 .... rs:3 . rd:3 dsp=3D%b2_dsp5_3 sz=3D1 +# MOV.l dsp5[rs], rd +MOV_mr 1010 1 .... rs:3 . rd:3 dsp=3D%b2_dsp5_3 sz=3D2 +# MOV.l #uimm4, rd +MOV_ir 0110 0110 imm:4 rd:4 +# MOV.b #imm8, dsp5[rd] +MOV_im 0011 1100 . rd:3 .... imm:8 sz=3D0 dsp=3D%b3_dsp5_8 +# MOV.w #imm8, dsp5[rd] +MOV_im 0011 1101 . rd:3 .... imm:8 sz=3D1 dsp=3D%b3_dsp5_8 +# MOV.l #imm8, dsp5[rd] +MOV_im 0011 1110 . rd:3 .... imm:8 sz=3D2 dsp=3D%b3_dsp5_8 +# MOV.l #imm8, rd +MOV_ir 0111 0101 0100 rd:4 imm:8 +# MOV.l #mm8, rd +MOV_ir 1111 1011 rd:4 .. 10 imm=3D%b2_li_2 +# MOV. #imm, [rd] +MOV_im 1111 1000 rd:4 .. sz:2 dsp=3D0 imm=3D%b2_li_2 +# MOV. #imm, dsp8[rd] +MOV_im 1111 1001 rd:4 .. sz:2 dsp:8 imm=3D%b3_li_10 +# MOV. #imm, dsp16[rd] +MOV_im 1111 1010 rd:4 .. sz:2 .... .... .... .... \ + imm=3D%b4_li_18 dsp=3D%b4_dsp_16 +# MOV. [ri,rb], rd +MOV_ar 1111 1110 01 sz:2 ri:4 rb:4 rd:4 +# MOV. rs, [ri,rb] +MOV_ra 1111 1110 00 sz:2 ri:4 rb:4 rs:4 +# Note ldd=3D3 and lds=3D3 indicate register src or dst +# MOV.b rs, rd +# MOV.b rs, dsp[rd] +# MOV.b dsp[rs], rd +# MOV.b dsp[rs], dsp[rd] +MOV_mm 1100 ldd:2 lds:2 rs:4 rd:4 sz=3D0 +# MOV.w rs, rd +# MOV.w rs, dsp[rd] +# MOV.w dsp[rs], rd +# MOV.w dsp[rs], dsp[rd] +MOV_mm 1101 ldd:2 lds:2 rs:4 rd:4 sz=3D1 +# MOV.l rs, rd +# MOV.l rs, dsp[rd] +# MOV.l dsp[rs], rd +# MOV.l dsp[rs], dsp[rd] +MOV_mm 1110 ldd:2 lds:2 rs:4 rd:4 sz=3D2 +# MOV.l rs, [rd+] +# MOV.l rs, [-rd] +MOV_rp 1111 1101 0010 0 ad:1 sz:2 rd:4 rs:4 +# MOV.l [rs+], rd +# MOV.l [-rs], rd +MOV_pr 1111 1101 0010 1 ad:1 sz:2 rd:4 rs:4 + +# MOVU. dsp5[rs], rd +MOVU_mr 1011 sz:1 ... . rs:3 . rd:3 dsp=3D%b2_dsp5_3 +# MOVU. [rs], rd +MOVU_mr 0101 1 sz:1 00 rs:4 rd:4 dsp=3D0 +# MOVU. dsp8[rs], rd +MOVU_mr 0101 1 sz:1 01 rs:4 rd:4 dsp:8 +# MOVU. dsp16[rs], rd +MOVU_mr 0101 1 sz:1 10 rs:4 rd:4 .... .... .... .... dsp=3D%b4_dsp_16 +# MOVU. rs, rd +MOVU_rr 0101 1 sz:1 11 rs:4 rd:4 +# MOVU. [ri, rb], rd +MOVU_ar 1111 1110 110 sz:1 ri:4 rb:4 rd:4 +# MOVU. [rs+], rd +MOVU_pr 1111 1101 0011 1 ad:1 0 sz:1 rd:4 rs:4 + +# MUL #uimm4, rd +MUL_ir 0110 0011 .... .... @b2_rds_uimm4 +# MUL #imm4, rd +MUL_ir 0111 01.. 0001 .... @b2_rds_li +# MUL dsp[rs].ub, rd +# MUL rs, rd +MUL_mr 0100 11.. .... .... @b2_rd_ld_ub +# MUL dsp[rs], rd +MUL_mr 0000 0110 ..00 11.. .... .... @b3_rd_ld +# MOV rs, rs2, rd +MUL_rrr 1111 1111 0011 .... .... .... @b3_rd_rs_rs2 + +# MULHI rs, rs2 +MULHI 1111 1101 0000 0000 rs:4 rs2:4 +# MULLO rs, rs2 +MULLO 1111 1101 0000 0001 rs:4 rs2:4 + +# MVFACHI rd +MVFACHI 1111 1101 0001 1111 0000 rd:4 +# MVFACMI rd +MVFACMI 1111 1101 0001 1111 0010 rd:4 + +# MVFC cr, rd +MVFC 1111 1101 0110 1010 cr:4 rd:4 + +# MVTACHI rs +MVTACHI 1111 1101 0001 0111 0000 rs:4 +# MVTACLO rs +MVTACLO 1111 1101 0001 0111 0001 rs:4 + +# MVTC #imm, cr +MVTC_i 1111 1101 0111 ..11 0000 cr:4 imm=3D%b3_li_10 +# MVTC rs, cr +MVTC_r 1111 1101 0110 1000 rs:4 cr:4 + +# MVTIPL #imm +MVTIPL 0111 0101 0111 0000 0000 imm:4 + +# NEG rd +NEG_rr 0111 1110 0001 .... @b2_rds +# NEG rs, rd +NEG_rr 1111 1100 0000 0111 .... .... @b3_rd_rs + +NOP 0000 0011 + +# NOT rd +NOT_rr 0111 1110 0000 .... @b2_rds +# NOT rs, rd +NOT_rr 1111 1100 0011 1011 .... .... @b3_rd_rs + +# OR #uimm4, rd +OR_ir 0110 0101 .... .... @b2_rds_uimm4 +# OR #imm, rd +OR_ir 0111 01.. 0011 .... @b2_rds_li +# OR dsp[rs].ub, rd +# OR rs, rd +OR_mr 0101 01.. .... .... @b2_rd_ld_ub +# OR dsp[rs], rd +OR_mr 0000 0110 .. 0101 .. .... .... @b3_rd_ld +# OR rs, rs2, rd +OR_rrr 1111 1111 0101 .... .... .... @b3_rd_rs_rs2 + +# POP cr +POPC 0111 1110 1110 cr:4 +# POP rd-rd2 +POPM 0110 1111 rd:4 rd2:4 + +# POP rd +# PUSH. rs +{ + POP 0111 1110 1011 rd:4 + PUSH_r 0111 1110 10 sz:2 rs:4 +} +# PUSH. dsp[rs] +PUSH_m 1111 01 ld:2 rs:4 10 sz:2 +# PUSH cr +PUSHC 0111 1110 1100 cr:4 +# PUSHM rs-rs2 +PUSHM 0110 1110 rs:4 rs2:4 + +# RACW #imm +RACW 1111 1101 0001 1000 000 imm:1 0000 + +# REVL rs,rd +REVL 1111 1101 0110 0111 .... .... @b3_rd_rs +# REVW rs,rd +REVW 1111 1101 0110 0101 .... .... @b3_rd_rs + +# SMOVF +# RPMA. +{ + SMOVF 0111 1111 1000 1111 + RMPA 0111 1111 1000 11 sz:2 +} + +# ROLC rd +ROLC 0111 1110 0101 .... @b2_rds +# RORC rd +RORC 0111 1110 0100 .... @b2_rds + +# ROTL #imm, rd +ROTL_ir 1111 1101 0110 111. .... .... @b3_rds_imm5 +# ROTL rs, rd +ROTL_rr 1111 1101 0110 0110 .... .... @b3_rd_rs + +# ROTR #imm, rd +ROTR_ir 1111 1101 0110 110. .... .... @b3_rds_imm5 +# ROTR #imm, rd +ROTR_rr 1111 1101 0110 0100 .... .... @b3_rd_rs + +# ROUND rs,rd +# ROUND dsp[rs],rd +ROUND 1111 1100 1001 10 .. .... .... @b3_ld_rd_rs + +RTE 0111 1111 1001 0101 + +RTFI 0111 1111 1001 0100 + +RTS 0000 0010 + +# RTSD #imm +RTSD_i 0110 0111 imm:8 +# RTSD #imm, rd-rd2 +RTSD_irr 0011 1111 rd:4 rd2:4 imm:8 + +# SAT rd +SAT 0111 1110 0011 .... @b2_rds +# SATR +SATR 0111 1111 1001 0011 + +# SBB rs, rd +SBB_rr 1111 1100 0000 0011 .... .... @b3_rd_rs +# SBB dsp[rs].l, rd +# Note only mi=3D=3D2 allowed. +SBB_mr 0000 0110 ..10 00.. 0000 0000 .... .... @b4_rd_ldmi + +# SCCnd dsp[rd] +# SCCnd rd +SCCnd 1111 1100 1101 .... .... .... @b3_sz_ld_rd_cd + +# SETPSW psw +SETPSW 0111 1111 1010 cb:4 + +# SHAR #imm, rd +SHAR_irr 0110 101. .... .... @b2_rds_imm5 +# SHAR #imm, rs, rd +SHAR_irr 1111 1101 101. .... .... .... @b3_rd_rs_imm5 +# SHAR rs, rd +SHAR_rr 1111 1101 0110 0001 .... .... @b3_rd_rs + +# SHLL #imm, rd +SHLL_irr 0110 110. .... .... @b2_rds_imm5 +# SHLL #imm, rs, rd +SHLL_irr 1111 1101 110. .... .... .... @b3_rd_rs_imm5 +# SHLL rs, rd +SHLL_rr 1111 1101 0110 0010 .... .... @b3_rd_rs + +# SHLR #imm, rd +SHLR_irr 0110 100. .... .... @b2_rds_imm5 +# SHLR #imm, rs, rd +SHLR_irr 1111 1101 100. .... .... .... @b3_rd_rs_imm5 +# SHLR rs, rd +SHLR_rr 1111 1101 0110 0000 .... .... @b3_rd_rs + +# SMOVB +# SSTR. +{ + SMOVB 0111 1111 1000 1011 + SSTR 0111 1111 1000 10 sz:2 +} + +# STNZ #imm, rd +STNZ 1111 1101 0111 ..00 1111 .... @b3_rd_li +# STZ #imm, rd +STZ 1111 1101 0111 ..00 1110 .... @b3_rd_li + +# SUB #uimm4, rd +SUB_ir 0110 0000 .... .... @b2_rds_uimm4 +# SUB dsp[rs].ub, rd +# SUB rs, rd +SUB_mr 0100 00.. .... .... @b2_rd_ld_ub +# SUB dsp[rs], rd +SUB_mr 0000 0110 ..00 00.. .... .... @b3_rd_ld +# SUB rs, rs2, rd +SUB_rrr 1111 1111 0000 .... .... .... @b3_rd_rs_rs2 + +# SCMPU +# SUNTIL. +{ + SCMPU 0111 1111 1000 0011 + SUNTIL 0111 1111 1000 00 sz:2 +} + +# SMOVU +# SWHILE. +{ + SMOVU 0111 1111 1000 0111 + SWHILE 0111 1111 1000 01 sz:2 +} + +# TST #imm, rd +TST_ir 1111 1101 0111 ..00 1100 .... @b3_rd_li +# TST dsp[rs].ub, rd +# TST rs, rd +TST_mr 1111 1100 0011 00.. .... .... @b3_rd_ld_ub +# TST dsp[rs], rd +TST_mr 0000 0110 ..10 00.. 0000 1100 .... .... @b4_rd_ldmi + +WAIT 0111 1111 1001 0110 + +# XCHG rs, rd +# XCHG dsp[rs].ub, rd +{ + XCHG_rr 1111 1100 0100 0011 .... .... @b3_rd_rs + XCHG_mr 1111 1100 0100 00.. .... .... @b3_rd_ld_ub +} +# XCHG dsp[rs], rd +XCHG_mr 0000 0110 ..10 00.. 0001 0000 .... .... @b4_rd_ldmi + +# XOR #imm, rd +XOR_ir 1111 1101 0111 ..00 1101 .... @b3_rd_li +# XOR dsp[rs].ub, rd +# XOR rs, rd +XOR_mr 1111 1100 0011 01.. .... .... @b3_rd_ld_ub +# XOR dsp[rs], rd +XOR_mr 0000 0110 ..10 00.. 0000 1101 .... .... @b4_rd_ldmi --=20 2.17.1 From nobody Sun May 5 10:44:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1558621025; cv=none; d=zoho.com; s=zohoarc; b=V2lERqa1qfcS8cR8BqXKI5/JsNEN8dG0MDsM+wtVlFawEMhAWwrhplr2qt+U7EWWf8jW4h+BMGym/3YJdqwwtRpLN/cHNMvEHNo9ZqP1YQz7GicXOdjX4MkfvsFwuxjo32P5p7H4o5sDLsMfqFwNMRWzoZSoOquluimLaOeyYCY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558621025; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=pYId7u6ge3wwL5u8IcKUKWAJjekbKt1Pj1loyfXf2e0=; b=RYXkIrpwFTrRCnzLkLef68n+8L1b6a+Zr3Qaeg55UmpwX674mf/xH0VBb/+FZxBa/Tdd5qlF3VNi98EubCKlDRskS2XKd5vU+J++0dfsNmr4MooLUgOK741Skkw5yVPlJabyqxTemwOVgRLIjCnRnIKRjv05W7NYW6K8pDMAi+8= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1558621025046908.5759235994698; Thu, 23 May 2019 07:17:05 -0700 (PDT) Received: from localhost ([127.0.0.1]:37228 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToWg-0004V2-6l for importer@patchew.org; Thu, 23 May 2019 10:16:58 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46432) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToHV-0006Cr-Ak for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hToHR-0004OX-97 for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:17 -0400 Received: from mail-ua1-x92e.google.com ([2607:f8b0:4864:20::92e]:46835) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hToHP-0004Lf-6m for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:13 -0400 Received: by mail-ua1-x92e.google.com with SMTP id a95so2189403uaa.13 for ; Thu, 23 May 2019 07:01:08 -0700 (PDT) Received: from localhost.localdomain (ip-173-130-215-183.orldfl.spcsdns.net. [173.130.215.183]) by smtp.gmail.com with ESMTPSA id v133sm1984166vkv.5.2019.05.23.07.01.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 May 2019 07:01:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=pYId7u6ge3wwL5u8IcKUKWAJjekbKt1Pj1loyfXf2e0=; b=D22bFz1x8YFpvukdVqRixsakoy49deUWLAdfqR3FizhqaRC3flf2MaxrzdEkNI2qnU rltga7nSp82Yk5BEA2I5hLksO7b87P6FtK3CDHKoMe1PCzWQ5ROMEwoeCqmhgpCI0BMP TE7oCj2g5JlrrRYIFdDfF1FPY/jQCIwrm4sJc4uklfRI5J8ko3Tu/MOhXYebQmdYeyzK 5rPx3WAv9ivmPRagZyfp9fdB0qE0JzpTkZUHiQTa/8HxdR+pqUxPYw3GyVvgGjKhKsT+ YiJ1cPuJyr82wnPFjeZvS680GxJhtSpzNnAvWgDE520cU/39PyTSBrqomdIqFKTlfWr3 YOZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=pYId7u6ge3wwL5u8IcKUKWAJjekbKt1Pj1loyfXf2e0=; b=NourT408sPKRfgDvkgBBvth0EiZPULW2q8s9ldKAdt23zZZXfXzDEFNVwkGiQNt0ET xK+BW9Uh2HvzW9UIXxPVpitWz6xN+06WB20WkMD7V9hTY8R00ssPLNwGgqc8QI4RIVI+ P7bZLa/+tlHJWskw1Y0dJPw/KNz0CGe/W7Wvw7tR9gMNpCSmBaVsGDiA0f/koFZl1ups 4xYDhFMvTVUqGuPT815AK4oICNGDCHQaJq2Uukvqqff3wn/WpwIVpUBOHLuUI0JCmFNU 6Z7XFzxnxsVUTE2x9xPTtHEnlRIU9F2DlTGtiwGNAenhrqmExTICfluVoj7Jcstv53GY XTqQ== X-Gm-Message-State: APjAAAWAwp0HTcQBSJfhwvZSeMMtApWqS0rbUURJ9FXchDsr20Bpyl5O R91z8RlhNj98tDUy7vuNTJE0GGrD9lQ= X-Google-Smtp-Source: APXvYqwxAjQj9Cln3k8VwgknCD85VHeC0TCJv8YJi9wFMEKkWhAAr0+j2mkgk6TWzYHoXjxRXHowZg== X-Received: by 2002:ab0:5a07:: with SMTP id l7mr4909941uad.78.1558620066734; Thu, 23 May 2019 07:01:06 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 23 May 2019 10:00:48 -0400 Message-Id: <20190523140059.18548-3-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190523140059.18548-1-richard.henderson@linaro.org> References: <20190523140059.18548-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::92e Subject: [Qemu-devel] [PULL 02/13] target/rx: TCG helper X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Yoshinori Sato Signed-off-by: Yoshinori Sato Reviewed-by: Richard Henderson Message-Id: <20190516055244.95559-3-ysato@users.sourceforge.jp> Signed-off-by: Richard Henderson --- target/rx/helper.h | 31 +++ target/rx/helper.c | 148 +++++++++++++ target/rx/op_helper.c | 481 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 660 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 f= or + * 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 =3D=3D 0) { + env->psw_ipl =3D FIELD_EX32(psw, PSW, IPL); + if (rte) { + /* PSW.PM can write RTE and RTFI */ + env->psw_pm =3D FIELD_EX32(psw, PSW, PM); + } + env->psw_u =3D FIELD_EX32(psw, PSW, U); + env->psw_i =3D FIELD_EX32(psw, PSW, I); + } + env->psw_o =3D FIELD_EX32(psw, PSW, O) << 31; + env->psw_s =3D FIELD_EX32(psw, PSW, S) << 31; + env->psw_z =3D 1 - FIELD_EX32(psw, PSW, Z); + env->psw_c =3D FIELD_EX32(psw, PSW, C); +} + +#define INT_FLAGS (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIR) +void rx_cpu_do_interrupt(CPUState *cs) +{ + RXCPU *cpu =3D RXCPU(cs); + CPURXState *env =3D &cpu->env; + int do_irq =3D cs->interrupt_request & INT_FLAGS; + uint32_t save_psw; + + env->in_sleep =3D 0; + + if (env->psw_u) { + env->usp =3D env->regs[0]; + } else { + env->isp =3D env->regs[0]; + } + save_psw =3D rx_cpu_pack_psw(env); + env->psw_pm =3D env->psw_i =3D env->psw_u =3D 0; + + if (do_irq) { + if (do_irq & CPU_INTERRUPT_FIR) { + env->bpc =3D env->pc; + env->bpsw =3D save_psw; + env->pc =3D env->fintv; + env->psw_ipl =3D 15; + cs->interrupt_request &=3D ~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 -=3D 4; + cpu_stl_all(env, env->isp, save_psw); + env->isp -=3D 4; + cpu_stl_all(env, env->isp, env->pc); + env->pc =3D cpu_ldl_all(env, env->intb + env->ack_irq * 4); + env->psw_ipl =3D env->ack_ipl; + cs->interrupt_request &=3D ~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 =3D cs->exception_index; + const char *expname =3D "unknown exception"; + + env->isp -=3D 4; + cpu_stl_all(env, env->isp, save_psw); + env->isp -=3D 4; + cpu_stl_all(env, env->isp, env->pc); + + if (vec < 0x100) { + env->pc =3D cpu_ldl_all(env, 0xffffffc0 + vec * 4); + } else { + env->pc =3D cpu_ldl_all(env, env->intb + (vec & 0xff) * 4); + } + switch (vec) { + case 20: + expname =3D "privilege violation"; + break; + case 21: + expname =3D "access exception"; + break; + case 23: + expname =3D "illegal instruction"; + break; + case 25: + expname =3D "fpu exception"; + break; + case 30: + expname =3D "non-maskable interrupt"; + break; + case 0x100 ... 0x1ff: + expname =3D "unconditional trap"; + } + qemu_log_mask(CPU_LOG_INT, "exception 0x%02x [%s] raised\n", + (vec & 0xff), expname); + } + env->regs[0] =3D env->isp; +} + +bool rx_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +{ + RXCPU *cpu =3D RXCPU(cs); + CPURXState *env =3D &cpu->env; + int accept =3D 0; + /* hardware interrupt (Normal) */ + if ((interrupt_request & CPU_INTERRUPT_HARD) && + env->psw_i && (env->psw_ipl < env->req_ipl)) { + env->ack_irq =3D env->req_irq; + env->ack_ipl =3D env->req_ipl; + accept =3D 1; + } + /* hardware interrupt (FIR) */ + if ((interrupt_request & CPU_INTERRUPT_FIR) && + env->psw_i && (env->psw_ipl < 15)) { + accept =3D 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..9a460070e9 --- /dev/null +++ b/target/rx/op_helper.c @@ -0,0 +1,481 @@ +/* + * 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 f= or + * 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 inde= x, + uintptr_t retaddr); + +static void _set_psw(CPURXState *env, uint32_t psw, uint32_t rte) +{ + uint32_t prev_u; + prev_u =3D env->psw_u; + rx_cpu_unpack_psw(env, psw, rte); + if (prev_u !=3D env->psw_u) { + /* switch r0 */ + if (env->psw_u) { + env->isp =3D env->regs[0]; + env->regs[0] =3D env->usp; + } else { + env->usp =3D env->regs[0]; + env->regs[0] =3D 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 =3D FIELD_DP32(env->fpsw, FPSW, C ## b, 1); \ + if (!FIELD_EX32(env->fpsw, FPSW, E ## b)) { \ + env->fpsw =3D 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 =3D ret & ~(1 << 31); /* mask sign bit */ + env->psw_s =3D ret; + + xcpt =3D get_float_exception_flags(&env->fp_status); + + /* Clear the cause entries */ + env->fpsw =3D 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 =3D FIELD_DP32(env->fpsw, FPSW, CE, 1); + } + + /* update FPSW_FLAG_S */ + if (FIELD_EX32(env->fpsw, FPSW, FLAGS) !=3D 0) { + env->fpsw =3D FIELD_DP32(env->fpsw, FPSW, FS, 1); + } + + /* Generate an exception if enabled */ + cause =3D FIELD_EX32(env->fpsw, FPSW, CAUSE); + enable =3D FIELD_EX32(env->fpsw, FPSW, ENABLE); + enable |=3D 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[] =3D { + float_round_nearest_even, + float_round_to_zero, + float_round_up, + float_round_down, + }; + uint32_t fpsw =3D env->fpsw; + fpsw |=3D 0x7fffff03; + val &=3D ~0x80000000; + fpsw &=3D val; + FIELD_DP32(fpsw, FPSW, FS, FIELD_EX32(fpsw, FPSW, FLAGS) !=3D 0); + env->fpsw =3D 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 =3D 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 =3D float32_compare(t0, t1, &env->fp_status); + update_fpsw(env, 0, GETPC()); + env->psw_z =3D 1; + env->psw_s =3D env->psw_o =3D 0; + switch (st) { + case float_relation_equal: + env->psw_z =3D 0; + break; + case float_relation_less: + env->psw_s =3D -1; + break; + case float_relation_unordered: + env->psw_o =3D -1; + break; + } +} + +uint32_t helper_ftoi(CPURXState *env, float32 t0) +{ + uint32_t ret; + ret =3D 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 =3D 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 =3D 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] =3D=3D 0) { + return; + } + while (env->regs[3] !=3D 0) { + tmp0 =3D cpu_ldub_data_ra(env, env->regs[1]++, GETPC()); + tmp1 =3D cpu_ldub_data_ra(env, env->regs[2]++, GETPC()); + env->regs[3]--; + if (tmp0 !=3D tmp1 || tmp0 =3D=3D '\0') { + break; + } + } + env->psw_z =3D tmp0 - tmp1; + env->psw_c =3D (tmp0 >=3D tmp1); +} + +static uint32_t (* const cpu_ldufn[])(CPUArchState *env, + target_ulong ptr, + uintptr_t retaddr) =3D { + 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) =3D { + 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) =3D { + 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] !=3D 0) { + cpu_stfn[sz](env, env->regs[1], env->regs[2], GETPC()); + env->regs[1] +=3D 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 =3D (mode & OP_SMOVB) ? -1 : 1; + while (env->regs[3] !=3D 0) { + tmp =3D cpu_ldub_data_ra(env, env->regs[2], GETPC()); + cpu_stb_data_ra(env, env->regs[1], tmp, GETPC()); + env->regs[1] +=3D dir; + env->regs[2] +=3D dir; + env->regs[3]--; + if ((mode & OP_SMOVU) && tmp =3D=3D 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] =3D=3D 0) { + return ; + } + while (env->regs[3] !=3D 0) { + tmp =3D cpu_ldufn[sz](env, env->regs[1], GETPC()); + env->regs[1] +=3D 1 << sz; + env->regs[3]--; + if (tmp =3D=3D env->regs[2]) { + break; + } + } + env->psw_z =3D tmp - env->regs[2]; + env->psw_c =3D (tmp <=3D env->regs[2]); +} + +void helper_swhile(CPURXState *env, uint32_t sz) +{ + uint32_t tmp; + tcg_debug_assert(sz < 3); + if (env->regs[3] =3D=3D 0) { + return ; + } + while (env->regs[3] !=3D 0) { + tmp =3D cpu_ldufn[sz](env, env->regs[1], GETPC()); + env->regs[1] +=3D 1 << sz; + env->regs[3]--; + if (tmp !=3D env->regs[2]) { + break; + } + } + env->psw_z =3D env->regs[3]; + env->psw_c =3D (tmp <=3D 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] =3D=3D 0) { + return; + } + result_l =3D env->regs[5]; + result_l <<=3D 32; + result_l |=3D env->regs[4]; + result_h =3D env->regs[6]; + env->psw_o =3D 0; + + while (env->regs[3] !=3D 0) { + tmp0 =3D cpu_ldfn[sz](env, env->regs[1], GETPC()); + tmp1 =3D cpu_ldfn[sz](env, env->regs[2], GETPC()); + tmp0 *=3D tmp1; + prev =3D result_l; + result_l +=3D tmp0; + /* carry / bollow */ + if (tmp0 < 0) { + if (prev > result_l) { + result_h--; + } + } else { + if (prev < result_l) { + result_h++; + } + } + + env->regs[1] +=3D 1 << sz; + env->regs[2] +=3D 1 << sz; + } + env->psw_s =3D result_h; + env->psw_o =3D (result_h !=3D 0 && result_h !=3D -1) << 31; + env->regs[6] =3D result_h; + env->regs[5] =3D result_l >> 32; + env->regs[4] =3D result_l & 0xffffffff; +} + +void helper_racw(CPURXState *env, uint32_t imm) +{ + int64_t acc; + acc =3D env->acc; + acc <<=3D (imm + 1); + acc +=3D 0x0000000080000000LL; + if (acc > 0x00007fff00000000LL) { + acc =3D 0x00007fff00000000LL; + } else if (acc < -0x800000000000LL) { + acc =3D -0x800000000000LL; + } else { + acc &=3D 0xffffffff00000000LL; + } + env->acc =3D acc; +} + +void helper_satr(CPURXState *env) +{ + if (env->psw_o >> 31) { + if ((int)env->psw_s < 0) { + env->regs[6] =3D 0x00000000; + env->regs[5] =3D 0x7fffffff; + env->regs[4] =3D 0xffffffff; + } else { + env->regs[6] =3D 0xffffffff; + env->regs[5] =3D 0x80000000; + env->regs[4] =3D 0x00000000; + } + } +} + +/* div */ +uint32_t helper_div(CPURXState *env, uint32_t num, uint32_t den) +{ + uint32_t ret =3D num; + if (!((num =3D=3D INT_MIN && den =3D=3D -1) || den =3D=3D 0)) { + ret =3D (int32_t)num / (int32_t)den; + env->psw_o =3D 0; + } else { + env->psw_o =3D -1; + } + return ret; +} + +uint32_t helper_divu(CPURXState *env, uint32_t num, uint32_t den) +{ + uint32_t ret =3D num; + if (den !=3D 0) { + ret =3D num / den; + env->psw_o =3D 0; + } else { + env->psw_o =3D -1; + } + return ret; +} + +/* exception */ +static inline void QEMU_NORETURN raise_exception(CPURXState *env, int inde= x, + uintptr_t retaddr) +{ + CPUState *cs =3D CPU(rx_env_get_cpu(env)); + + cs->exception_index =3D 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 =3D CPU(rx_env_get_cpu(env)); + + cs->halted =3D 1; + env->in_sleep =3D 1; + raise_exception(env, EXCP_HLT, 0); +} + +void QEMU_NORETURN helper_debug(CPURXState *env) +{ + CPUState *cs =3D CPU(rx_env_get_cpu(env)); + + cs->exception_index =3D 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); +} + +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + uint32_t address, physical, prot; + + /* Linear mapping */ + address =3D physical =3D addr & TARGET_PAGE_MASK; + prot =3D PAGE_READ | PAGE_WRITE | PAGE_EXEC; + tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE); +} --=20 2.17.1 From nobody Sun May 5 10:44:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1558620747; cv=none; d=zoho.com; s=zohoarc; b=Ufo9NVqq3dm2CqeNDUjoZ3EEHcRL6pWO7iE2iWxhOgAOQ7IudgeGkwCjHtwfSXCXBFiVWfdOvyfNRFy80WHOFO5353u7i2Ad11US6h3aySZjrIlhLZmjTyz1SNO3dyH+zSR988Ogt/exQYezDBJWPf469bvE8sS50Oma0id7wzs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558620747; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=DLSTlL6ipwSUa07Ie1q+0ewVzHyis1A8deJmyXS8hdA=; b=WZ75NYQTuGifNxm+uB5OWscpGjG9ycZIoD7E/mjDSuFT9ND50MNh/aPdV0POH9d5yPwhc33+Zsk6F5pQdEtgAsdyOV+WZlTsOe4GEjyL4vMKK07+IMVXIC6/laxu8ztZopH/hn/sSGtCsbCpQfAnDrfcaxG/b/uuPpMvOJKcAg4= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 15586207470801011.9368952107615; Thu, 23 May 2019 07:12:27 -0700 (PDT) Received: from localhost ([127.0.0.1]:37119 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToSE-00080H-U1 for importer@patchew.org; Thu, 23 May 2019 10:12:22 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46431) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToHV-0006Cq-Ah for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hToHR-0004OS-8f for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:17 -0400 Received: from mail-ua1-x930.google.com ([2607:f8b0:4864:20::930]:43662) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hToHP-0004Mr-73 for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:13 -0400 Received: by mail-ua1-x930.google.com with SMTP id u4so2195086uau.10 for ; Thu, 23 May 2019 07:01:09 -0700 (PDT) Received: from localhost.localdomain (ip-173-130-215-183.orldfl.spcsdns.net. [173.130.215.183]) by smtp.gmail.com with ESMTPSA id v133sm1984166vkv.5.2019.05.23.07.01.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 May 2019 07:01:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=DLSTlL6ipwSUa07Ie1q+0ewVzHyis1A8deJmyXS8hdA=; b=ezVMS3I5bLR/qce4buWgfqUf89nLCqVaENkwhmpYeAatmZFRjzbv2jxMJ0zKIo78YE Wp7oZIioRlWFn49Ac2H4NNKlmXavpcZaTCeranzWD9v8EOOTrr2bgGWaLBt1a74X/AB1 HRCndOwp8zH5lDZQEIJXyEL4X9XQvT6DNmmrKie462hbCGBjc4pbKUkeon5PDO2XMHtr uQzMFdM/o3fKukzqGxtoPYBF9oY8ZYruRB5HK1PsSTgAVIC1wsKiQyj263KTdsrVgUEM J97z8qCNx898Yrz+vIGzLguqPKaNaA+PpIJv67BZWMwgC4qaTyl1zCge1hLusdnE5KfX 6gzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=DLSTlL6ipwSUa07Ie1q+0ewVzHyis1A8deJmyXS8hdA=; b=NcIFZkWYs/1vkVFruoWBOOfteuK8JPkYdBptpf3SBJF3q6MnFcyzhjozRGjo9Bfx9D Z5WSPjxT0UCBkszwsdd6+opyWH6NLbIJAK40hkCjEckTHB7yeXsekyjFFwgSg3NbpHnR myG7K+8PbVA2r1dMAGW5TKcjNi7KcCW73XhEDw137sh9d1ROdE8KwkdNWziRFVAHLCfq 30E+TGNUh3lNLb/tsDtL9+PWYCCpApMQOcCkFkK6wD+ZK+6TAcHX/XPXymC73wnw+LK7 B5Vlz6jDoCGkzkZPZE0a5DP50asXrP16qwn1ojIeDfPeMPoMORC+lTigK338fsNCLEH8 2jtA== X-Gm-Message-State: APjAAAX6f2NVJiecYKVNMBz0KLITsl7SlGrlEiuTESMHCwTruVzK/mL2 w1sHRrqtFbmAEVXMbRY0t8Yc59R86F0= X-Google-Smtp-Source: APXvYqxzFnJe5tx1AoEQy6kZ3eyTGx0BrEYUdDRCTtFnjBryTmIp8rWYGfhNbyWHwXVTyXMTcSoJng== X-Received: by 2002:ab0:138e:: with SMTP id m14mr4211989uae.71.1558620068346; Thu, 23 May 2019 07:01:08 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 23 May 2019 10:00:49 -0400 Message-Id: <20190523140059.18548-4-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190523140059.18548-1-richard.henderson@linaro.org> References: <20190523140059.18548-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::930 Subject: [Qemu-devel] [PULL 03/13] target/rx: CPU definition X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Yoshinori Sato Signed-off-by: Yoshinori Sato Reviewed-by: Richard Henderson Message-Id: <20190516055244.95559-4-ysato@users.sourceforge.jp> Signed-off-by: Richard Henderson --- target/rx/cpu.h | 227 ++++++++++++++++++++++++++++++++++++++++++++ target/rx/cpu.c | 222 +++++++++++++++++++++++++++++++++++++++++++ target/rx/gdbstub.c | 112 ++++++++++++++++++++++ target/rx/monitor.c | 38 ++++++++ 4 files changed, 599 insertions(+) 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.h b/target/rx/cpu.h new file mode 100644 index 0000000000..fa07c25af4 --- /dev/null +++ b/target/rx/cpu.h @@ -0,0 +1,227 @@ +/* + * 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 f= or + * 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 "qom/cpu.h" + +#define TYPE_RXCPU "rxcpu" + +#define RXCPU_CLASS(klass) \ + OBJECT_CLASS_CHECK(RXCPUClass, (klass), TYPE_RXCPU) +#define RXCPU(obj) \ + OBJECT_CHECK(RXCPU, (obj), TYPE_RXCPU) +#define RXCPU_GET_CLASS(obj) \ + OBJECT_GET_CLASS(RXCPUClass, (obj), TYPE_RXCPU) + +/* + * 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 TARGET_LONG_BITS 32 +#define TARGET_PAGE_BITS 12 + +#define CPUArchState struct CPURXState + +#include "exec/cpu-defs.h" + +#define TARGET_PHYS_ADDR_SPACE_BITS 32 +#define TARGET_VIRT_ADDR_SPACE_BITS 32 + +/* 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) + +#define NB_MMU_MODES 1 +#define MMU_MODE0_SUFFIX _all + +enum { + NUM_REGS =3D 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 */ + + CPU_COMMON +} CPURXState; + +/* + * RXCPU: + * @env: #CPURXState + * + * A RX CPU + */ +struct RXCPU { + /*< private >*/ + CPUState parent_obj; + /*< public >*/ + + CPURXState env; +}; + +typedef struct RXCPU RXCPU; + +static inline RXCPU *rx_env_get_cpu(CPURXState *env) +{ + return container_of(env, RXCPU, env); +} + +#define ENV_GET_CPU(e) CPU(rx_env_get_cpu(e)) + +#define ENV_OFFSET offsetof(RXCPU, env) + +#define RX_CPU_TYPE_SUFFIX "-" TYPE_RXCPU +#define RX_CPU_TYPE_NAME(model) model RX_CPU_TYPE_SUFFIX +#define CPU_RESOLVING_TYPE TYPE_RXCPU + +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_load_image(RXCPU *cpu, const char *filename, + uint32_t start, uint32_t size); +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 *f= lags) +{ + *pc =3D env->pc; + *cs_base =3D 0; + *flags =3D 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 =3D 0; + psw =3D FIELD_DP32(psw, PSW, IPL, env->psw_ipl); + psw =3D FIELD_DP32(psw, PSW, PM, env->psw_pm); + psw =3D FIELD_DP32(psw, PSW, U, env->psw_u); + psw =3D FIELD_DP32(psw, PSW, I, env->psw_i); + psw =3D FIELD_DP32(psw, PSW, O, env->psw_o >> 31); + psw =3D FIELD_DP32(psw, PSW, S, env->psw_s >> 31); + psw =3D FIELD_DP32(psw, PSW, Z, env->psw_z =3D=3D 0); + psw =3D 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..4b96f2e463 --- /dev/null +++ b/target/rx/cpu.c @@ -0,0 +1,222 @@ +/* + * 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 f= or + * 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 =3D RXCPU(cs); + + cpu->env.pc =3D value; +} + +static void rx_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) +{ + RXCPU *cpu =3D RXCPU(cs); + + cpu->env.pc =3D 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 =3D RXCPU(s); + RXCPUClass *rcc =3D RXCPU_GET_CLASS(cpu); + CPURXState *env =3D &cpu->env; + uint32_t *resetvec; + + rcc->parent_reset(s); + + memset(env, 0, offsetof(CPURXState, end_reset_fields)); + + resetvec =3D rom_ptr(0xfffffffc, 4); + if (resetvec) { + /* In the case of kernel, it is ignored because it is not set. */ + env->pc =3D ldl_p(resetvec); + } + rx_cpu_unpack_psw(env, 0, 1); + env->regs[0] =3D env->isp =3D env->usp =3D 0; + env->fpsw =3D 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 =3D object_class_get_name(OBJECT_CLASS(data)); + int len =3D strlen(typename) - strlen(RX_CPU_TYPE_SUFFIX); + + qemu_printf("%.*s\n", len, typename); +} + +void rx_cpu_list(void) +{ + GSList *list; + list =3D object_class_get_list_sorted(TYPE_RXCPU, 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; + char *typename =3D NULL; + + typename =3D g_strdup_printf(RX_CPU_TYPE_NAME("")); + oc =3D object_class_by_name(typename); + if (oc !=3D NULL && object_class_is_abstract(oc)) { + oc =3D NULL; + } + + g_free(typename); + return oc; +} + +static void rx_cpu_realize(DeviceState *dev, Error **errp) +{ + CPUState *cs =3D CPU(dev); + RXCPUClass *rcc =3D RXCPU_GET_CLASS(dev); + Error *local_err =3D NULL; + + cpu_exec_realizefn(cs, &local_err); + if (local_err !=3D 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 =3D opaque; + CPUState *cs =3D CPU(cpu); + int irq =3D request & 0xff; + + static const int mask[] =3D { + [RX_CPU_IRQ] =3D CPU_INTERRUPT_HARD, + [RX_CPU_FIR] =3D CPU_INTERRUPT_FIR, + }; + if (irq) { + cpu->env.req_irq =3D irq; + cpu->env.req_ipl =3D (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 =3D bfd_mach_rx; + info->print_insn =3D print_insn_rx; +} + +static void rx_cpu_init(Object *obj) +{ + CPUState *cs =3D CPU(obj); + RXCPU *cpu =3D RXCPU(obj); + CPURXState *env =3D &cpu->env; + + cs->env_ptr =3D env; + qdev_init_gpio_in(DEVICE(cpu), rx_cpu_set_irq, 2); +} + +static void rxcpu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + CPUClass *cc =3D CPU_CLASS(klass); + RXCPUClass *rcc =3D RXCPU_CLASS(klass); + + device_class_set_parent_realize(dc, rx_cpu_realize, + &rcc->parent_realize); + + rcc->parent_reset =3D cc->reset; + cc->reset =3D rx_cpu_reset; + + cc->class_by_name =3D rx_cpu_class_by_name; + cc->has_work =3D rx_cpu_has_work; + cc->do_interrupt =3D rx_cpu_do_interrupt; + cc->cpu_exec_interrupt =3D rx_cpu_exec_interrupt; + cc->dump_state =3D rx_cpu_dump_state; + cc->set_pc =3D rx_cpu_set_pc; + cc->synchronize_from_tb =3D rx_cpu_synchronize_from_tb; + cc->gdb_read_register =3D rx_cpu_gdb_read_register; + cc->gdb_write_register =3D rx_cpu_gdb_write_register; + cc->get_phys_page_debug =3D rx_cpu_get_phys_page_debug; + cc->disas_set_info =3D rx_cpu_disas_set_info; + cc->tcg_initialize =3D rx_translate_init; + + cc->gdb_num_core_regs =3D 26; +} + +static const TypeInfo rxcpu_info =3D { + .name =3D TYPE_RXCPU, + .parent =3D TYPE_CPU, + .instance_size =3D sizeof(RXCPU), + .instance_init =3D rx_cpu_init, + .abstract =3D false, + .class_size =3D sizeof(RXCPUClass), + .class_init =3D rxcpu_class_init, +}; + +static void rxcpu_register_types(void) +{ + type_register_static(&rxcpu_info); +} + +type_init(rxcpu_register_types) + +static uint32_t extable[32]; + +void rx_load_image(RXCPU *cpu, const char *filename, + uint32_t start, uint32_t size) +{ + long kernel_size; + int i; + + kernel_size =3D 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 =3D start; + + /* setup exception trap trampoline */ + /* linux kernel only works little-endian mode */ + for (i =3D 0; i < 32; i++) { + extable[i] =3D cpu_to_le32(0x10 + i * 4); + } + rom_add_blob_fixed("extable", extable, sizeof(extable), 0xffffff80); +} 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 f= or + * 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 =3D RXCPU(cs); + CPURXState *env =3D &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->us= p); + case 17: + return gdb_get_regl(mem_buf, (!env->psw_u) ? env->regs[0] : env->i= sp); + 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 =3D RXCPU(cs); + CPURXState *env =3D &cpu->env; + uint32_t psw; + switch (n) { + case 0 ... 15: + env->regs[n] =3D ldl_p(mem_buf); + if (n =3D=3D 0) { + if (env->psw_u) { + env->usp =3D env->regs[0]; + } else { + env->isp =3D env->regs[0]; + } + } + break; + case 16: + env->usp =3D ldl_p(mem_buf); + if (env->psw_u) { + env->regs[0] =3D ldl_p(mem_buf); + } + break; + case 17: + env->isp =3D ldl_p(mem_buf); + if (!env->psw_u) { + env->regs[0] =3D ldl_p(mem_buf); + } + break; + case 18: + psw =3D ldl_p(mem_buf); + rx_cpu_unpack_psw(env, psw, 1); + break; + case 19: + env->pc =3D ldl_p(mem_buf); + break; + case 20: + env->intb =3D ldl_p(mem_buf); + break; + case 21: + env->bpsw =3D ldl_p(mem_buf); + break; + case 22: + env->bpc =3D ldl_p(mem_buf); + break; + case 23: + env->fintv =3D ldl_p(mem_buf); + break; + case 24: + env->fpsw =3D 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"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * 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 OT= HER + * 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 =3D mon_get_cpu_env(); + + if (!env) { + monitor_printf(mon, "No CPU available\n"); + return; + } +} --=20 2.17.1 From nobody Sun May 5 10:44:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1558620630; cv=none; d=zoho.com; s=zohoarc; b=LtesU8kJQs9fqaXwF84qw/18Jx7kaAKcZIHq0v+g862G5FGj84WyIq3ju6K1bsOPpC02IL+afguvLN47iaktzONtWj/AsAEkQFS66adFjjfnfNTH2KPOMdLR1RmOSlDxPYZCqA0AnigdY2iiCOxhHe131crZRnGRFLwtVL2MXPI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558620630; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=666Lr4obOo+DDJ7gg2S1+ap30abGvfUrXEvn4CaVhSk=; b=TjfBeDRDQR4eRLSZLcxH9ulq6V7zplHM6ti6M17IqFsaC/zHq6Yey3MSdvz7OQfck6FoHQFiN0nu3PatApCp7z2gADJAipPdkKZ9tnsewBZwhWeN5r7miXAcEyptaVPcwqiBDkTU8GlNWflN31cLg2pgbU37YLarnoA5JzIMWt8= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1558620630203483.564408954407; Thu, 23 May 2019 07:10:30 -0700 (PDT) Received: from localhost ([127.0.0.1]:37049 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToQL-00054w-Vc for importer@patchew.org; Thu, 23 May 2019 10:10:26 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46459) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToHX-0006Du-6e for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hToHT-0004Pd-4H for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:19 -0400 Received: from mail-vs1-xe2f.google.com ([2607:f8b0:4864:20::e2f]:42146) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hToHR-0004Nr-Cu for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:13 -0400 Received: by mail-vs1-xe2f.google.com with SMTP id z11so3634542vsq.9 for ; Thu, 23 May 2019 07:01:13 -0700 (PDT) Received: from localhost.localdomain (ip-173-130-215-183.orldfl.spcsdns.net. [173.130.215.183]) by smtp.gmail.com with ESMTPSA id v133sm1984166vkv.5.2019.05.23.07.01.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 May 2019 07:01:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=666Lr4obOo+DDJ7gg2S1+ap30abGvfUrXEvn4CaVhSk=; b=f2Ee4HJ8HKjGul5NB6Kg7ReIg9dMrwKeK2ufZYM/JTpnV772j+VNqitXVXRx3xV1Io qqs3vOq6ufDSWQ6B104xZ52CK3U31LYRJzzSC9CN40SC+/OCaDiAy4zk4VJ4Xzq+dgQN kuAlPNbo3p1G8FIA5fWa+3gKz+s74eqreb63/5TCJUUvWwgLyXe22BEA3gUsIpJpTYfy EiZK4w+E86PigRVbQjDxCUGNHxqZCvI3Wz6JGBupV3Wg7kW6i1xxRMFckOlS8ff7mnXy oP19kVh98iE4RKqjVw939oCz2LZWSl2OvZdGEayI8hsMN4jnOjsaWeiUY9ZQcVQ/bCrL xugg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=666Lr4obOo+DDJ7gg2S1+ap30abGvfUrXEvn4CaVhSk=; b=t0xHU2XEFLjuR7tMJXZUHeua5hmdddfuNGXB31sYjB5BU9ikUH3nATI7mRsPuhaN1X Nlkx7jUTfEJ5R859sFoNXTunxfaXiHqxvb91yerr7SVGYgOOO3e2Y36ibhUY2/r6o/Oh FLcJ24M4ffASjnvkqnr2SydKr6Siry74uy5uhhwWHtzbPEfY2wYm/r3EKoD4KUyz0uCV sCrF8wbj16C8/i8t/aMRSkTgE1/gkFWYrhYDzxnB2jMQ4olrKVGQbRgtobSMde15g8sc v5/5Bicf2LNvHdhqQLpZJoR9DeBHN4ZWa+KQ+erfOyMksfI6exBVbHoG0DFShJqfZQao 8+5A== X-Gm-Message-State: APjAAAUtnBmBlWDbjoJ9U+i8vI7sj4Mry/J72jVKE0U15NMc90JVEBgd qLSm7gDD1K/brxvKoHuDVOvFf6viBa0= X-Google-Smtp-Source: APXvYqyGaOAlLsVmoUzOJKwkj4HEQ7uJ42axMDo+uGiTej7LXyPhuyAuiT2PjQVyP/eHG878+vqNEg== X-Received: by 2002:a67:ebc1:: with SMTP id y1mr11914023vso.16.1558620070113; Thu, 23 May 2019 07:01:10 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 23 May 2019 10:00:50 -0400 Message-Id: <20190523140059.18548-5-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190523140059.18548-1-richard.henderson@linaro.org> References: <20190523140059.18548-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::e2f Subject: [Qemu-devel] [PULL 04/13] target/rx: RX disassembler X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) From: Yoshinori Sato Signed-off-by: Yoshinori Sato Reviewed-by: Richard Henderson Tested-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20190516055244.95559-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 9240ec32c2..de17792e88 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_i= nfo*); 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 *); =20 #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 f= or + * 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 <=3D n) { + ctx->dis->read_memory_func(ctx->addr++, &buf, 1, ctx->dis); + insn |=3D buf << (32 - i * 8); + } + return insn; +} + +static int32_t li(DisasContext *ctx, int sz) +{ + int32_t addr; + bfd_byte buf[4]; + addr =3D ctx->addr; + + switch (sz) { + case 1: + ctx->addr +=3D 1; + ctx->dis->read_memory_func(addr, buf, 1, ctx->dis); + return (int8_t)buf[0]; + case 2: + ctx->addr +=3D 2; + ctx->dis->read_memory_func(addr, buf, 2, ctx->dis); + return ldsw_le_p(buf); + case 3: + ctx->addr +=3D 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 +=3D 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 +=3D 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[] =3D {'b', 'w', 'l'}; +static const char cond[][4] =3D { + "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n", + "ge", "lt", "gt", "le", "o", "no", "ra", "f" +}; +static const char psw[] =3D { + '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 +=3D 1; + return ((uint8_t)buf[0]) << size; + case 2: + ctx->dis->read_memory_func(ctx->addr, buf, 2, ctx->dis); + ctx->addr +=3D 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] =3D {".b", ".w", ".l", ".uw", ".ub"}; + if (ld < 3) { + switch (mi) { + case 4: + /* dsp[rs].ub */ + dsp =3D rx_index_addr(ld, RX_MEMORY_BYTE, ctx); + break; + case 3: + /* dsp[rs].uw */ + dsp =3D rx_index_addr(ld, RX_MEMORY_WORD, ctx); + break; + default: + /* dsp[rs].b */ + /* dsp[rs].w */ + /* dsp[rs].l */ + dsp =3D 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 =3D=3D 3 && a->ldd =3D=3D 3) { + /* mov.[bwl] rs,rd */ + prt("r%d, r%d", a->rs, a->rd); + return true; + } + if (a->lds =3D=3D 3) { + prt("r%d, ", a->rd); + dsp =3D rx_index_addr(a->ldd, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d]", a->rs); + } else if (a->ldd =3D=3D 3) { + dsp =3D 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 =3D rx_index_addr(a->lds, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d], ", a->rs); + dsp =3D 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 =3D=3D 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 =3D=3D 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 =3D=3D 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 =3D 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] =3D { + "b", "w", "l", "ub", "uw", + }; + + prt("xchg\t"); + dsp =3D 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 !=3D 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 !=3D 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 =3D 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 =3D=3D 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 =3D=3D 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 !=3D 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 !=3D 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 !=3D 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[] =3D {'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[] =3D {'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 =3D 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 =3D 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 =3D 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 =3D 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 =3D dis; + ctx.pc =3D ctx.addr =3D addr; + + insn =3D decode_load(&ctx); + if (!decode(&ctx, insn)) { + ctx.dis->fprintf_func(ctx.dis->stream, ".byte\t"); + for (i =3D 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 <<=3D 8; + } + } + return ctx.addr - addr; +} --=20 2.17.1 From nobody Sun May 5 10:44:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1558620245; cv=none; d=zoho.com; s=zohoarc; b=T9TTkDjtpZ7ly+7xkJxNQGW6tmTsjV4yHv58difOrDUNeLtdiYQCEYn8lmlIE5IYFd5uiI7P5zOq9iNQYD+N1OKKQUw2u+Yj3z5BBXsTOaKMCX/14iQQN/GrTbZeGJLHE3dhfVPxiY+AWyviRs+9ghSaEY4nEZRgqgTxd/Kowus= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558620245; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=Z0ZdLoMy0d/4TPYPawKcpAMNbM31FQPLybJs+GMojo4=; b=Q7go8jR4I+JA14etUPxR+g0J7jVdijXGwH/j2HjfPS8aSFFnbwNBdH7fTFryyfKWCzkWxcLINI65eoxkRIG6AAKGpps34aHAvOG4yXiz/rZmGvTvg60Rkuhu3FSrLwL0jsYjSLWx/aJ/73p8t6A2pPr7m97ltmcb6WzWn4KcSiE= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1558620245688100.9315032527644; Thu, 23 May 2019 07:04:05 -0700 (PDT) Received: from localhost ([127.0.0.1]:36967 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToK2-0007fz-Er for importer@patchew.org; Thu, 23 May 2019 10:03:54 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46562) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToHb-0006Gk-7J for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hToHV-0004S9-3C for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:23 -0400 Received: from mail-ua1-x944.google.com ([2607:f8b0:4864:20::944]:39585) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hToHT-0004Oy-Cg for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:15 -0400 Received: by mail-ua1-x944.google.com with SMTP id 79so2208882uav.6 for ; Thu, 23 May 2019 07:01:14 -0700 (PDT) Received: from localhost.localdomain (ip-173-130-215-183.orldfl.spcsdns.net. [173.130.215.183]) by smtp.gmail.com with ESMTPSA id v133sm1984166vkv.5.2019.05.23.07.01.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 May 2019 07:01:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Z0ZdLoMy0d/4TPYPawKcpAMNbM31FQPLybJs+GMojo4=; b=ef70NiQifBlcz0P+GfY6XFabKe8AGn9sVf8wkySHK69qDk7PYug+smfo2x9MukNAvA PPRv+FigQUkfvZd9xlZ5P72IOznanWGGVZKZL5HJbm/00Hx/433AWLf9Mm+acw4Y7xRn +oeblyBEe9zDr2OcxxqkCX92vy9gGTx4wPOG0M64UEvSSjjdTKh1FY6Bz9hST6gAYPai 4OzK/zdLWNjbtXP3Kq9UinRDglLxK4rqVpY7uW/h5pK3177D8hPoOV5F8vTkHJfDJFSo g1BEx29xR8PFhYjl4a/+NOugyeLhGIeuHupD27cnflKstKTDO5tV1jm+r6B5yYOwHf/p OG2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Z0ZdLoMy0d/4TPYPawKcpAMNbM31FQPLybJs+GMojo4=; b=kJvTFozY46P0hHYF01qPAv2XdLg+vXaFEsawIy1HXQ8Zx2n/Dh/bE1samZp1Tx87YE wpnAFg85MSncBQ5jd7yKG6GuLzWhD229Sx7zxS7Y+7P3Cdl9lssrIb9HVrKwcUPXVXq+ USa/5joEOex321hq5Ht8JGO0k1sHuD8C2XZngoS3HtR0roZuOs+v5oG2rSmyEWIpSnSE KfnusS4uvCZBe9yjFKc02haqIe3mJ3dxn2csqJlDh64y0tx4Bumofa3+HpXHHxXzRcva zUDMV5nROtQcR9Mbz51/5LX9nc8gCx7LhlrbCfieWAtQFkKUsfGwspS4uBSsrjdIR+DQ AiSQ== X-Gm-Message-State: APjAAAVYSdKD6Rki6YBmbNGMBBTrwzGv732RcccILzMYIW8Dx/Dk+QNG tbj8GDS4MhZ6Lr0UZoeDPSEe0Lvm8+I7Rg== X-Google-Smtp-Source: APXvYqwTfCzPWGAMOyt4KlkN96v7atGKgSddIXjArRD42E0FNu+MBBRniJTh87p1nuRbXtKNzntOcA== X-Received: by 2002:ab0:18a5:: with SMTP id t37mr28786298uag.134.1558620071464; Thu, 23 May 2019 07:01:11 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 23 May 2019 10:00:51 -0400 Message-Id: <20190523140059.18548-6-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190523140059.18548-1-richard.henderson@linaro.org> References: <20190523140059.18548-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::944 Subject: [Qemu-devel] [PULL 05/13] hw/intc: RX62N interrupt controller (ICUa) X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) From: Yoshinori Sato This implementation supported only ICUa. Hardware manual. https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej= 0140_rx62n.pdf Signed-off-by: Yoshinori Sato Reviewed-by: Alex Benn=C3=A9e Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20190516055244.95559-6-ysato@users.sourceforge.jp> 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..aab88f2ea7 --- /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 =3D 0, + TRG_NEDGE =3D 1, /* Falling */ + TRG_PEDGE =3D 2, /* Raising */ + TRG_BEDGE =3D 3, /* Both */ +}; + +struct IRQSource { + enum TRG_MODE sense; + int level; +}; + +enum { + /* Software interrupt request */ + SWI =3D 27, + NR_IRQS =3D 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 f= or + * 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) =3D=3D 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 =3D icu->ier[n_IRQ / 8] & (1 << (n_IRQ & 7)); + if (n_IRQ > 0 && enable !=3D 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 =3D opaque; + struct IRQSource *src; + int issue; + + if (n_IRQ >=3D NR_IRQS) { + error_report("%s: IRQ %d out of range", __func__, n_IRQ); + return; + } + + src =3D &icu->src[n_IRQ]; + + level =3D (level !=3D 0); + switch (src->sense) { + case TRG_LEVEL: + /* level-sensitive irq */ + issue =3D level; + src->level =3D level; + break; + case TRG_NEDGE: + issue =3D (level =3D=3D 0 && src->level =3D=3D 1); + src->level =3D level; + break; + case TRG_PEDGE: + issue =3D (level =3D=3D 1 && src->level =3D=3D 0); + src->level =3D level; + break; + case TRG_BEDGE: + issue =3D ((level ^ src->level) & 1); + src->level =3D level; + break; + default: + g_assert_not_reached(); + } + if (issue =3D=3D 0 && src->sense =3D=3D TRG_LEVEL) { + icu->ir[n_IRQ] =3D 0; + if (atomic_read(&icu->req_irq) =3D=3D n_IRQ) { + /* clear request */ + set_irq(icu, n_IRQ, 0); + atomic_set(&icu->req_irq, -1); + } + return; + } + if (issue) { + icu->ir[n_IRQ] =3D 1; + rxicu_request(icu, n_IRQ); + } +} + +static void rxicu_ack_irq(void *opaque, int no, int level) +{ + RXICUState *icu =3D opaque; + int i; + int n_IRQ; + int max_pri; + + n_IRQ =3D atomic_read(&icu->req_irq); + if (n_IRQ < 0) { + return; + } + atomic_set(&icu->req_irq, -1); + if (icu->src[n_IRQ].sense !=3D TRG_LEVEL) { + icu->ir[n_IRQ] =3D 0; + } + + max_pri =3D 0; + n_IRQ =3D -1; + for (i =3D 0; i < NR_IRQS; i++) { + if (icu->ir[i]) { + if (max_pri < icu->ipr[icu->map[i]]) { + n_IRQ =3D i; + max_pri =3D icu->ipr[icu->map[i]]; + } + } + } + + if (n_IRQ >=3D 0) { + rxicu_request(icu, n_IRQ); + } +} + +static uint64_t icu_read(void *opaque, hwaddr addr, unsigned size) +{ + RXICUState *icu =3D opaque; + int reg =3D addr & 0xff; + + if ((addr !=3D A_FIR && size !=3D 1) || + (addr =3D=3D A_FIR && size !=3D 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 si= ze) +{ + RXICUState *icu =3D opaque; + int reg =3D addr & 0xff; + + if ((addr !=3D A_FIR && size !=3D 1) || + (addr =3D=3D A_FIR && size !=3D 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 !=3D TRG_LEVEL && val =3D=3D 0) { + icu->ir[reg] =3D 0; + } + break; + case A_DTCER ... A_DTCER + 0xff: + icu->dtcer[reg] =3D 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] =3D val; + break; + case A_SWINTR: + if (val & R_SWINTR_SWINT_MASK) { + qemu_irq_pulse(icu->_swi); + } + break; + case A_FIR: + icu->fir =3D val & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK); + break; + case A_IPR ... A_IPR + 0x8f: + icu->ipr[reg] =3D 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] =3D val; + qemu_log_mask(LOG_UNIMP, + "rx_icu: DMAC not implemented\n"); + break; + case A_IRQCR ... A_IRQCR + 0x1f: + icu->src[64 + reg].sense =3D val >> R_IRQCR_IRQMD_SHIFT; + break; + case A_NMICLR: + break; + case A_NMIER: + icu->nmier |=3D val & (R_NMIER_NMIEN_MASK | + R_NMIER_LVDEN_MASK | + R_NMIER_OSTEN_MASK); + break; + case A_NMICR: + if ((icu->nmier & R_NMIER_NMIEN_MASK) =3D=3D 0) { + icu->nmicr =3D 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 =3D { + .write =3D icu_write, + .read =3D icu_read, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl =3D { + .max_access_size =3D 2, + }, +}; + +static void rxicu_realize(DeviceState *dev, Error **errp) +{ + RXICUState *icu =3D RXICU(dev); + int i, j; + + if (icu->init_sense =3D=3D NULL) { + qemu_log_mask(LOG_GUEST_ERROR, + "rx_icu: trigger-level property must be set."); + return; + } + for (i =3D j =3D 0; i < NR_IRQS; i++) { + if (icu->init_sense[j] =3D=3D i) { + icu->src[i].sense =3D TRG_LEVEL; + if (j < icu->nr_sense) { + j++; + } + } else { + icu->src[i].sense =3D TRG_PEDGE; + } + } + icu->req_irq =3D -1; +} + +static void rxicu_init(Object *obj) +{ + SysBusDevice *d =3D SYS_BUS_DEVICE(obj); + RXICUState *icu =3D 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 =3D RXICU(obj); + g_free(icu->map); + g_free(icu->init_sense); +} + +static const VMStateDescription vmstate_rxicu =3D { + .name =3D "rx-icu", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static Property rxicu_properties[] =3D { + 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 =3D DEVICE_CLASS(klass); + + dc->realize =3D rxicu_realize; + dc->props =3D rxicu_properties; + dc->vmsd =3D &vmstate_rxicu; +} + +static const TypeInfo rxicu_info =3D { + .name =3D TYPE_RXICU, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RXICUState), + .instance_init =3D rxicu_init, + .instance_finalize =3D rxicu_fini, + .class_init =3D 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 =20 config OMPIC bool + +config RX_ICU + bool diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs index df712c3e6c..b54b09b12e 100644 --- a/hw/intc/Makefile.objs +++ b/hw/intc/Makefile.objs @@ -48,3 +48,4 @@ obj-$(CONFIG_ARM_GIC) +=3D arm_gicv3_cpuif.o obj-$(CONFIG_MIPS_CPS) +=3D mips_gic.o obj-$(CONFIG_NIOS2) +=3D nios2_iic.o obj-$(CONFIG_OMPIC) +=3D ompic.o +obj-$(CONFIG_RX) +=3D rx_icu.o --=20 2.17.1 From nobody Sun May 5 10:44:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1558620438; cv=none; d=zoho.com; s=zohoarc; b=Db7p+m+TZW22w8yO6pr59RfUklf2yDZDbqekCjhhakMw9+1+AYmso+evxRZDs/9HPg4NIvHFvAxMPzNG2YYwZkvxLK3p6tr7nxoqIsW4U4u+Xd/m3nnS1LOuS6RBkpWwPwCIBoYtx8KZJ3sl4LGuvo6xqrkkHvvX6mFhEB1SEkA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558620438; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=zu2gXSrtXKRrObLRv9mb9RBagq1JlULvxov939E+29U=; b=aPruDr8lFJCO1Vi0FZWFiuoAZAcs3aFaCITI6mhxwCbKovbFJuWpgqS8h2+HQoA+uEaHj4j3ATXchM62WPzB38+gOchl3UF4BsNj9GyxNjg8BBKx0xdjVuZjOH7m/IuF3GFQL6ecg3A6pBHc0Px/wiSaUUvSgvcuYHS2KQsZn7s= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1558620438165342.3326232633734; Thu, 23 May 2019 07:07:18 -0700 (PDT) Received: from localhost ([127.0.0.1]:37025 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToND-0001xe-S4 for importer@patchew.org; Thu, 23 May 2019 10:07:11 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46486) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToHY-0006Ef-D8 for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hToHV-0004SE-3r for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:20 -0400 Received: from mail-vs1-xe2d.google.com ([2607:f8b0:4864:20::e2d]:44150) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hToHT-0004PO-DD for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:15 -0400 Received: by mail-vs1-xe2d.google.com with SMTP id w124so3614314vsb.11 for ; Thu, 23 May 2019 07:01:14 -0700 (PDT) Received: from localhost.localdomain (ip-173-130-215-183.orldfl.spcsdns.net. [173.130.215.183]) by smtp.gmail.com with ESMTPSA id v133sm1984166vkv.5.2019.05.23.07.01.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 May 2019 07:01:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=zu2gXSrtXKRrObLRv9mb9RBagq1JlULvxov939E+29U=; b=WkZBjBbz7ekxLXn7uxWihDnfu9dVl/wk3TT+AsR7p6lP6Pbx1O4797my6NJMEEkmyg 5gYSuOiNHxoYZ6knKCz4G0Ds9Kuzd3N8A7uPdo+KpJeV4/Qqc6e7lawXof/hBLMkR2pv mz/Iexf0i441rUgJ4thiqKMppfiVUF7h7z4UWmLucciPZeN4GvjyJHRaNA7nCT/nhy7F PCifrrA8bMCHAGhGRlYihsrDaqkkhY4uhpJ5T761rMQ7lDsxOdVFqde6a1ScETe8SsjS 2wF2+moTqIDHhDsTYUyC6a3MpqBs9Tq5OBa8gY8zFm7Mbsnze9AOo1mvdl0hldtKevC3 E0jQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=zu2gXSrtXKRrObLRv9mb9RBagq1JlULvxov939E+29U=; b=X3PH+kHClgAlEL+xN34y7YNaLMHHS7a8ef50U/a5AimnfvLKmmhYlSwEGIUj/qrSrn o/t/iKEGiQwjhjnXTrbHJmCKVN4z/AZg3dPWwNGpui8dpMkkehlG30uBnL0OAOUWXZd7 6TJpiQpWmhF+eU2KZrIGIsF5QPD7DxCS8+kMOgqceTCbtj8R17o7XXRHBUVbWJ8/QwCr FXt4npmW/EIT8wxW6dB6FFNzDXrZJZrR7nTqgKGirisNAVZgv2F6s0KhlkD/l6nObdk4 jtETrAb1thoKHjtPxmxQbbRnrqufv97+xyBTduSvolQ5UGelG6lcHDtAkh+BG/wexQi+ wvfA== X-Gm-Message-State: APjAAAX3t+EZqbs++pSKNvZBXq45FkF+bvZzw/8xW6GrlrY2eK+LNAbb xTa1Q1+TNW7LL4ZVN3fxORHjolXaekrG0w== X-Google-Smtp-Source: APXvYqzJJaez5aw3d27uWOAHkz6pPpXaxVjEuJ+TJbh8yRidqGUqhRE27z1rxbhW+bpS7MEeWD97SQ== X-Received: by 2002:a67:f24d:: with SMTP id y13mr7837316vsm.82.1558620073099; Thu, 23 May 2019 07:01:13 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 23 May 2019 10:00:52 -0400 Message-Id: <20190523140059.18548-7-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190523140059.18548-1-richard.henderson@linaro.org> References: <20190523140059.18548-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::e2d Subject: [Qemu-devel] [PULL 06/13] hw/timer: RX62N internal timer modules X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) From: Yoshinori Sato 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/r01uh0033ej= 0140_rx62n.pdf Signed-off-by: Yoshinori Sato Reviewed-by: Alex Benn=C3=A9e Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20190516055244.95559-7-ysato@users.sourceforge.jp> 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 =3D 2, + CMT_NR_IRQ =3D 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 =3D 0, + cmib =3D 1, + ovi =3D 2, + none =3D 3, + TMR_NR_EVENTS =3D 4 +}; + +enum { + TMR_CH =3D 2, + TMR_NR_IRQ =3D 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 f= or + * 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)) =3D=3D 0) { + /* count disable, so not happened next event. */ + return ; + } + next_time =3D cmt->cmcor[ch] - cmt->cmcnt[ch]; + next_time *=3D NANOSECONDS_PER_SECOND; + next_time /=3D cmt->input_freq; + /* + * CKS -> div rate + * 0 -> 8 (1 << 3) + * 1 -> 32 (1 << 5) + * 2 -> 128 (1 << 7) + * 3 -> 512 (1 << 9) + */ + next_time *=3D 1 << (3 + FIELD_EX16(cmt->cmcr[ch], CMCR, CKS) * 2); + next_time +=3D 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 =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + + if (cmt->cmstr & (1 << ch)) { + delta =3D (now - cmt->tick[ch]); + delta /=3D NANOSECONDS_PER_SECOND; + delta /=3D cmt->input_freq; + delta /=3D 1 << (3 + FIELD_EX16(cmt->cmcr[ch], CMCR, CKS) * 2); + cmt->tick[ch] =3D now; + return cmt->cmcnt[ch] + delta; + } else { + return cmt->cmcnt[ch]; + } +} + +static uint64_t cmt_read(void *opaque, hwaddr addr, unsigned size) +{ + hwaddr offset =3D addr & 0x0f; + RCMTState *cmt =3D opaque; + int ch =3D offset / 0x08; + uint64_t ret; + + if (offset =3D=3D A_CMSTR) { + ret =3D 0; + ret =3D FIELD_DP16(ret, CMSTR, STR, + FIELD_EX16(cmt->cmstr, CMSTR, STR)); + return ret; + } else { + offset &=3D 0x07; + if (ch =3D=3D 0) { + offset -=3D 0x02; + } + switch (offset) { + case A_CMCR: + ret =3D 0; + ret =3D FIELD_DP16(ret, CMCR, CKS, + FIELD_EX16(cmt->cmstr, CMCR, CKS)); + ret =3D 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 si= ze) +{ + hwaddr offset =3D addr & 0x0f; + RCMTState *cmt =3D opaque; + int ch =3D offset / 0x08; + + if (offset =3D=3D A_CMSTR) { + cmt->cmstr =3D 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 &=3D 0x07; + if (ch =3D=3D 0) { + offset -=3D 0x02; + } + switch (offset) { + case A_CMCR: + cmt->cmcr[ch] =3D FIELD_DP16(cmt->cmcr[ch], CMCR, CKS, + FIELD_EX16(val, CMCR, CKS)); + cmt->cmcr[ch] =3D FIELD_DP16(cmt->cmcr[ch], CMCR, CMIE, + FIELD_EX16(val, CMCR, CMIE)); + break; + case 2: + cmt->cmcnt[ch] =3D val; + break; + case 4: + cmt->cmcor[ch] =3D val; + break; + default: + qemu_log_mask(LOG_UNIMP, "renesas_cmt: Register -0x%" HWADDR_P= RIX + " not implemented\n", offset); + return; + } + if (FIELD_EX16(cmt->cmstr, CMSTR, STR) & (1 << ch)) { + update_events(cmt, ch); + } + } +} + +static const MemoryRegionOps cmt_ops =3D { + .write =3D cmt_write, + .read =3D cmt_read, + .endianness =3D DEVICE_NATIVE_ENDIAN, + .impl =3D { + .min_access_size =3D 2, + .max_access_size =3D 2, + }, +}; + +static void timer_events(RCMTState *cmt, int ch) +{ + cmt->cmcnt[ch] =3D 0; + cmt->tick[ch] =3D 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 =3D opaque; + + timer_events(cmt, 0); +} + +static void timer_event1(void *opaque) +{ + RCMTState *cmt =3D opaque; + + timer_events(cmt, 1); +} + +static void rcmt_reset(DeviceState *dev) +{ + RCMTState *cmt =3D RCMT(dev); + cmt->cmstr =3D 0; + cmt->cmcr[0] =3D cmt->cmcr[1] =3D 0; + cmt->cmcnt[0] =3D cmt->cmcnt[1] =3D 0; + cmt->cmcor[0] =3D cmt->cmcor[1] =3D 0xffff; +} + +static void rcmt_init(Object *obj) +{ + SysBusDevice *d =3D SYS_BUS_DEVICE(obj); + RCMTState *cmt =3D 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 =3D 0; i < ARRAY_SIZE(cmt->cmi); i++) { + sysbus_init_irq(d, &cmt->cmi[i]); + } + cmt->timer[0] =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event0, cmt); + cmt->timer[1] =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event1, cmt); +} + +static const VMStateDescription vmstate_rcmt =3D { + .name =3D "rx-cmt", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static Property rcmt_properties[] =3D { + 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 =3D DEVICE_CLASS(klass); + + dc->props =3D rcmt_properties; + dc->vmsd =3D &vmstate_rcmt; + dc->reset =3D rcmt_reset; +} + +static const TypeInfo rcmt_info =3D { + .name =3D TYPE_RENESAS_CMT, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RCMTState), + .instance_init =3D rcmt_init, + .class_init =3D 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 f= or + * 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[] =3D {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] =3D=3D 0) { + return ; + } + if (FIELD_EX8(tmr->tccr[ch], TCCR, CSS) =3D=3D 0) { + /* external clock mode */ + /* event not happened */ + return ; + } + if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) =3D=3D CASCADING) { + /* cascading mode */ + if (ch =3D=3D 1) { + tmr->next[ch] =3D none; + return ; + } + diff[cmia] =3D concat_reg(tmr->tcora) - concat_reg(tmr->tcnt); + diff[cmib] =3D concat_reg(tmr->tcorb) - concat_reg(tmr->tcnt); + diff[ovi] =3D 0x10000 - concat_reg(tmr->tcnt); + } else { + /* separate mode */ + diff[cmia] =3D tmr->tcora[ch] - tmr->tcnt[ch]; + diff[cmib] =3D tmr->tcorb[ch] - tmr->tcnt[ch]; + diff[ovi] =3D 0x100 - tmr->tcnt[ch]; + } + /* Search for the most recently occurring event. */ + for (event =3D 0, min =3D diff[0], i =3D 1; i < none; i++) { + if (min > diff[i]) { + event =3D i; + min =3D diff[i]; + } + } + tmr->next[ch] =3D event; + next_time =3D diff[event]; + next_time *=3D clkdiv[FIELD_EX8(tmr->tccr[ch], TCCR, CKS)]; + next_time *=3D NANOSECONDS_PER_SECOND; + next_time /=3D tmr->input_freq; + next_time +=3D 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 =3D clkdiv[FIELD_EX8(tmr->tccr[ch], TCCR, CKS)]; + int et; + + tmr->div_round[ch] +=3D delta; + if (divrate > 0) { + et =3D tmr->div_round[ch] / divrate; + tmr->div_round[ch] %=3D divrate; + } else { + /* disble clock. so no update */ + et =3D 0; + } + return et; +} +static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch) +{ + int64_t delta, now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + int elapsed, ovf =3D 0; + uint16_t tcnt[2]; + uint32_t ret; + + delta =3D (now - tmr->tick) * NANOSECONDS_PER_SECOND / tmr->input_freq; + if (delta > 0) { + tmr->tick =3D now; + + if (FIELD_EX8(tmr->tccr[1], TCCR, CSS) =3D=3D INTERNAL) { + /* timer1 count update */ + elapsed =3D elapsed_time(tmr, 1, delta); + if (elapsed >=3D 0x100) { + ovf =3D elapsed >> 8; + } + tcnt[1] =3D tmr->tcnt[1] + (elapsed & 0xff); + } + switch (FIELD_EX8(tmr->tccr[0], TCCR, CSS)) { + case INTERNAL: + elapsed =3D elapsed_time(tmr, 0, delta); + tcnt[0] =3D tmr->tcnt[0] + elapsed; + break; + case CASCADING: + if (ovf > 0) { + tcnt[0] =3D tmr->tcnt[0] + ovf; + } + break; + } + } else { + tcnt[0] =3D tmr->tcnt[0]; + tcnt[1] =3D tmr->tcnt[1]; + } + if (size =3D=3D 1) { + return tcnt[ch]; + } else { + ret =3D 0; + ret =3D deposit32(ret, 0, 8, tcnt[1]); + ret =3D deposit32(ret, 8, 8, tcnt[0]); + return ret; + } +} + +static inline uint8_t read_tccr(uint8_t r) +{ + uint8_t tccr =3D 0; + tccr =3D FIELD_DP8(tccr, TCCR, TMRIS, + FIELD_EX8(r, TCCR, TMRIS)); + tccr =3D FIELD_DP8(tccr, TCCR, CSS, + FIELD_EX8(r, TCCR, CSS)); + tccr =3D 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 =3D opaque; + int ch =3D addr & 1; + uint64_t ret; + + if (size =3D=3D 2 && (ch !=3D 0 || addr =3D=3D A_TCR || addr =3D=3D 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 =3D 0; + ret =3D FIELD_DP8(ret, TCR, CCLR, + FIELD_EX8(tmr->tcr[ch], TCR, CCLR)); + ret =3D FIELD_DP8(ret, TCR, OVIE, + FIELD_EX8(tmr->tcr[ch], TCR, OVIE)); + ret =3D FIELD_DP8(ret, TCR, CMIEA, + FIELD_EX8(tmr->tcr[ch], TCR, CMIEA)); + ret =3D FIELD_DP8(ret, TCR, CMIEB, + FIELD_EX8(tmr->tcr[ch], TCR, CMIEB)); + return ret; + case A_TCSR: + ret =3D 0; + ret =3D FIELD_DP8(ret, TCSR, OSA, + FIELD_EX8(tmr->tcsr[ch], TCSR, OSA)); + ret =3D FIELD_DP8(ret, TCSR, OSB, + FIELD_EX8(tmr->tcsr[ch], TCSR, OSB)); + switch (ch) { + case 0: + ret =3D FIELD_DP8(ret, TCSR, ADTE, + FIELD_EX8(tmr->tcsr[ch], TCSR, ADTE)); + break; + case 1: /* CH1 ADTE unimplement always 1 */ + ret =3D FIELD_DP8(ret, TCSR, ADTE, 1); + break; + } + return ret; + case A_TCORA: + if (size =3D=3D 1) { + return tmr->tcora[ch]; + } else if (ch =3D=3D 0) { + return concat_reg(tmr->tcora); + } + case A_TCORB: + if (size =3D=3D 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 =3D=3D 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 =3D=3D 1) { \ + tmr->reg[ch] =3D val; \ + update_events(tmr, ch); \ + } else { \ + tmr->reg[0] =3D extract32(val, 8, 8); \ + tmr->reg[1] =3D 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 si= ze) +{ + RTMRState *tmr =3D opaque; + int ch =3D addr & 1; + + if (size =3D=3D 2 && (ch !=3D 0 || addr =3D=3D A_TCR || addr =3D=3D 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] =3D val; + break; + case A_TCSR: + tmr->tcsr[ch] =3D 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 =3D { + .write =3D tmr_write, + .read =3D tmr_read, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl =3D { + .min_access_size =3D 1, + .max_access_size =3D 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 =3D tcnt; + + switch (tmr->next[ch]) { + case none: + break; + case cmia: + if (tcnt >=3D tcora) { + if (FIELD_EX8(tmr->tcr[ch], TCR, CCLR) =3D=3D CCLR_A) { + ret =3D tcnt - tcora; + } + if (FIELD_EX8(tmr->tcr[ch], TCR, CMIEA)) { + qemu_irq_pulse(tmr->cmia[ch]); + } + if (sz =3D=3D 8 && ch =3D=3D 0 && + FIELD_EX8(tmr->tccr[1], TCCR, CSS) =3D=3D CASCADING) { + tmr->tcnt[1]++; + timer_events(tmr, 1); + } + } + break; + case cmib: + if (tcnt >=3D tcorb) { + if (FIELD_EX8(tmr->tcr[ch], TCR, CCLR) =3D=3D CCLR_B) { + ret =3D tcnt - tcorb; + } + if (FIELD_EX8(tmr->tcr[ch], TCR, CMIEB)) { + qemu_irq_pulse(tmr->cmib[ch]); + } + } + break; + case ovi: + if ((tcnt >=3D (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] =3D read_tcnt(tmr, 1, ch); + if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) !=3D CASCADING) { + tmr->tcnt[ch] =3D issue_event(tmr, ch, 8, + tmr->tcnt[ch], + tmr->tcora[ch], tmr->tcorb[ch]) & 0xff; + } else { + if (ch =3D=3D 1) { + return ; + } + tcnt =3D issue_event(tmr, ch, 16, + concat_reg(tmr->tcnt), + concat_reg(tmr->tcora), + concat_reg(tmr->tcorb)); + tmr->tcnt[0] =3D (tcnt >> 8) & 0xff; + tmr->tcnt[1] =3D tcnt & 0xff; + } + update_events(tmr, ch); +} + +static void timer_event0(void *opaque) +{ + RTMRState *tmr =3D opaque; + + timer_events(tmr, 0); +} + +static void timer_event1(void *opaque) +{ + RTMRState *tmr =3D opaque; + + timer_events(tmr, 1); +} + +static void rtmr_reset(DeviceState *dev) +{ + RTMRState *tmr =3D RTMR(dev); + tmr->tcr[0] =3D tmr->tcr[1] =3D 0x00; + tmr->tcsr[0] =3D 0x00; + tmr->tcsr[1] =3D 0x10; + tmr->tcnt[0] =3D tmr->tcnt[1] =3D 0x00; + tmr->tcora[0] =3D tmr->tcora[1] =3D 0xff; + tmr->tcorb[0] =3D tmr->tcorb[1] =3D 0xff; + tmr->tccr[0] =3D tmr->tccr[1] =3D 0x00; + tmr->next[0] =3D tmr->next[1] =3D none; + tmr->tick =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +} + +static void rtmr_init(Object *obj) +{ + SysBusDevice *d =3D SYS_BUS_DEVICE(obj); + RTMRState *tmr =3D 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 =3D 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] =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event0, tmr); + tmr->timer[1] =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event1, tmr); +} + +static const VMStateDescription vmstate_rtmr =3D { + .name =3D "rx-tmr", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static Property rtmr_properties[] =3D { + 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 =3D DEVICE_CLASS(klass); + + dc->props =3D rtmr_properties; + dc->vmsd =3D &vmstate_rtmr; + dc->reset =3D rtmr_reset; +} + +static const TypeInfo rtmr_info =3D { + .name =3D TYPE_RENESAS_TMR, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RTMRState), + .instance_init =3D rtmr_init, + .class_init =3D 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) +=3D mc146818rtc.o =20 obj-$(CONFIG_ALLWINNER_A10_PIT) +=3D allwinner-a10-pit.o =20 +obj-$(CONFIG_RENESAS_TMR8) +=3D renesas_tmr.o +obj-$(CONFIG_RENESAS_CMT) +=3D renesas_cmt.o + common-obj-$(CONFIG_STM32F2XX_TIMER) +=3D stm32f2xx_timer.o common-obj-$(CONFIG_ASPEED_SOC) +=3D aspeed_timer.o =20 --=20 2.17.1 From nobody Sun May 5 10:44:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1558620406; cv=none; d=zoho.com; s=zohoarc; b=iBCVI4U0ag4J17WH/ch2XCcSOPoBbW1ZizQGSwQ4uwSjdxLbWXnPrbOvNagF1wUrLjrzllC5mYySqqW0uASqQ3xMOgxTti2A0jbjAGkd80+ZmAZ9fmqTGJz3/Xq8S2BH/M+IipcIhNwosrIHRq9zFyU86xI4L0upUDm3nAdOMtQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558620406; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=sElpgHoXbluM0Ji15y3dKG3rpq0Od+3SdqorgA46AMU=; b=LvryCS/7HTst95RExdSL8B/Fo/Bh9aKj9PoIobAwgHT/w7WuMbNvZnfTWSkHQ8xJVVjujOVBHacHbsX7OuMTmXLxpYtkyFjas4VpX9ROjwY1Tdc0ws8Wh7Lo+PVIjMwA5+9ikpgPs1GRKlSeOtwEVEy8DSIzTWMgpMXpfW0QfEA= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1558620406141311.6731952375054; Thu, 23 May 2019 07:06:46 -0700 (PDT) Received: from localhost ([127.0.0.1]:37023 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToMk-0001WZ-Vx for importer@patchew.org; Thu, 23 May 2019 10:06:43 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46537) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToHa-0006GG-Gn for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hToHY-0004UK-0O for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:22 -0400 Received: from mail-vk1-xa2b.google.com ([2607:f8b0:4864:20::a2b]:41733) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hToHX-0004Tk-PO for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:19 -0400 Received: by mail-vk1-xa2b.google.com with SMTP id l73so1376685vkl.8 for ; Thu, 23 May 2019 07:01:19 -0700 (PDT) Received: from localhost.localdomain (ip-173-130-215-183.orldfl.spcsdns.net. [173.130.215.183]) by smtp.gmail.com with ESMTPSA id v133sm1984166vkv.5.2019.05.23.07.01.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 May 2019 07:01:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=sElpgHoXbluM0Ji15y3dKG3rpq0Od+3SdqorgA46AMU=; b=beshHk5zZ81fDQ8k3dqBfwx0loKGXQQkzirRN9Z3p6cyEZBO3KZ0O6DzNQ2/eYnz/S MpXwHV/+M73d0UJscVeegIvZbkzf37FcnSTLUIuDZ21F2FAD/C7ds1aWEY0KiLgSp19Z ZrXI5HhHyi7Q3OWoNz0Cd52v4wz8ZTZDPxotK6u7MoY5PBWwdzx5+erokT5mpz0VqXDk zJvLwIQagXoiiNDQ8wZtYguk4WwSBvXavW1QEVsJuOyX275ubzqI2+TPvvWXmLSzIpiv aOB0nU/b8OPaGsUDg7o837R1SxOiOsxGuwLz0eKIo2qoDf5ynTF+NMuWZSx1r9RUByfW GNsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=sElpgHoXbluM0Ji15y3dKG3rpq0Od+3SdqorgA46AMU=; b=cEfOHZdCNrYbE8g3pGh1KHekWGSO7n3gQyPhkbwTAz5ZFC6qV1MPeknV8Dcfls/+QF BIV6TJjRcoqzPj+rzveMEXQCjXawN0/J+BJIYrtLHQPbiwk3vtqWHGfi/k+F3doO/ygu kdA+98v1SilZxoSnYUdNnPAHlD0hRBumO3C+zPzyHBGzJn3hQl0LCersIWCVYWKOhN8Y re2mNqFejon2WCP5F9mgs/QQEd7Q76Fr3+v+fxz055A23X/GzEnk0MBn0oc4v+CoBYh7 q27UvpLC6NR7+/wdR47JSGiaA64REC7uV7EgMNTvZomPCpdp2uQwtLDvnhtu52tp+spD bnsg== X-Gm-Message-State: APjAAAVVX26f+MRKJarmDBc0wOOcBAQdSx7Kxs2+jfF9XMnJJu9LN+T6 ArCUdeHddTulRTR/0VXavzipN1tGt/DGmA== X-Google-Smtp-Source: APXvYqzCqBvDTA2wuDMuwcRPok0a9mtSv6wx/CShyGZu+0GkG+d8QT8dGbV/S/w208lkXmM+FX7t7A== X-Received: by 2002:a1f:551:: with SMTP id 78mr1684572vkf.45.1558620074485; Thu, 23 May 2019 07:01:14 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 23 May 2019 10:00:53 -0400 Message-Id: <20190523140059.18548-8-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190523140059.18548-1-richard.henderson@linaro.org> References: <20190523140059.18548-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::a2b Subject: [Qemu-devel] [PULL 07/13] hw/char: RX62N serial communication interface (SCI) X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) From: Yoshinori Sato This module supported only non FIFO type. Hardware manual. https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej= 0140_rx62n.pdf Signed-off-by: Yoshinori Sato Reviewed-by: Alex Benn=C3=A9e Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20190516055244.95559-8-ysato@users.sourceforge.jp> 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 =3D 0, + RXI =3D 1, + TXI =3D 2, + TEI =3D 3, + SCI_NR_IRQ =3D 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 f= or + * 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 =3D 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 =3D RSCI(opaque); + sci->rx_next =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + sci->trtime; + if (FIELD_EX8(sci->ssr, SSR, RDRF) || size > 1) { + sci->ssr =3D FIELD_DP8(sci->ssr, SSR, ORER, 1); + if (FIELD_EX8(sci->scr, SCR, RIE)) { + qemu_set_irq(sci->irq[ERI], 1); + } + } else { + sci->rdr =3D buf[0]; + sci->ssr =3D 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 =3D FIELD_DP8(sci->ssr, SSR, TEND, 0); + sci->ssr =3D 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 =3D RSCI(opaque); + if (!FIELD_EX8(sci->ssr, SSR, TDRE)) { + send_byte(sci); + } else { + sci->ssr =3D 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 =3D 8 - FIELD_EX8(sci->smr, SMR, CHR); + sci->trtime +=3D FIELD_EX8(sci->smr, SMR, PE); + sci->trtime +=3D FIELD_EX8(sci->smr, SMR, STOP) + 1; + /* x bit transmit time (32 * divrate * brr) / base freq */ + sci->trtime *=3D 32 * sci->brr; + sci->trtime *=3D 1 << (2 * FIELD_EX8(sci->smr, SMR, CKS)); + sci->trtime *=3D NANOSECONDS_PER_SECOND; + sci->trtime /=3D 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 si= ze) +{ + hwaddr offset =3D addr & 0x07; + RSCIState *sci =3D RSCI(opaque); + + switch (offset) { + case A_SMR: + if (!IS_TR_ENABLED(sci->scr)) { + sci->smr =3D val; + update_trtime(sci); + } + break; + case A_BRR: + if (!IS_TR_ENABLED(sci->scr)) { + sci->brr =3D val; + update_trtime(sci); + } + break; + case A_SCR: + sci->scr =3D val; + if (FIELD_EX8(sci->scr, SCR, TE)) { + sci->ssr =3D FIELD_DP8(sci->ssr, SSR, TDRE, 1); + sci->ssr =3D 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 =3D val; + if (FIELD_EX8(sci->ssr, SSR, TEND)) { + send_byte(sci); + } else { + sci->ssr =3D FIELD_DP8(sci->ssr, SSR, TDRE, 0); + } + break; + case A_SSR: + sci->ssr =3D FIELD_DP8(sci->ssr, SSR, MPBT, + FIELD_EX8(val, SSR, MPBT)); + sci->ssr =3D 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) =3D=3D 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 =3D val; break; + case A_SEMR: /* SEMR */ + sci->semr =3D 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 =3D addr & 0x07; + RSCIState *sci =3D 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 =3D sci->ssr; + return sci->ssr; + case A_RDR: + sci->ssr =3D 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 =3D { + .write =3D sci_write, + .read =3D sci_read, + .endianness =3D DEVICE_NATIVE_ENDIAN, + .impl =3D { + .max_access_size =3D 1, + }, +}; + +static void rsci_reset(DeviceState *dev) +{ + RSCIState *sci =3D RSCI(dev); + sci->smr =3D sci->scr =3D 0x00; + sci->brr =3D 0xff; + sci->tdr =3D 0xff; + sci->rdr =3D 0x00; + sci->ssr =3D 0x84; + sci->scmr =3D 0x00; + sci->semr =3D 0x00; + sci->rx_next =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +} + +static void sci_event(void *opaque, int event) +{ + RSCIState *sci =3D RSCI(opaque); + if (event =3D=3D CHR_EVENT_BREAK) { + sci->ssr =3D 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 =3D RSCI(dev); + + if (sci->input_freq =3D=3D 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 =3D SYS_BUS_DEVICE(obj); + RSCIState *sci =3D 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 =3D 0; i < SCI_NR_IRQ; i++) { + sysbus_init_irq(d, &sci->irq[i]); + } + sci->timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, txend, sci); +} + +static const VMStateDescription vmstate_rcmt =3D { + .name =3D "renesas-sci", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static Property rsci_properties[] =3D { + 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 =3D DEVICE_CLASS(klass); + + dc->realize =3D rsci_realize; + dc->props =3D rsci_properties; + dc->vmsd =3D &vmstate_rcmt; + dc->reset =3D rsci_reset; +} + +static const TypeInfo rsci_info =3D { + .name =3D TYPE_RENESAS_SCI, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RSCIState), + .instance_init =3D rsci_init, + .class_init =3D 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 =20 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) +=3D spapr_vty.o obj-$(CONFIG_DIGIC) +=3D digic-uart.o obj-$(CONFIG_STM32F2XX_USART) +=3D stm32f2xx_usart.o obj-$(CONFIG_RASPI) +=3D bcm2835_aux.o +obj-$(CONFIG_RENESAS_SCI) +=3D renesas_sci.o =20 common-obj-$(CONFIG_CMSDK_APB_UART) +=3D cmsdk-apb-uart.o common-obj-$(CONFIG_ETRAXFS) +=3D etraxfs_ser.o --=20 2.17.1 From nobody Sun May 5 10:44:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1558620498; cv=none; d=zoho.com; s=zohoarc; b=UYi1jCa5Nkl64MLiFnLFsT7a99BNVblZ/IJJhy+DioDM1Gd6cnrOGX8EfGVLKd23JX5rYddBIWAz5ijQEOWezERDbBZaL/3KY1FmCi43Js25f3IogWgJH1ppRN22vTQFxgrLUxzKmZX1pQ27wVlLn6uhWq+NPUG+iZAcre8QCmU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558620498; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=2zUMv5xZP71KfmT0VCVXRmrjPE0MSztMOR2PXArEx1s=; b=LYxKGa1lHRmn/CMZjVEs0MY1zgasH6FZcd44RyQtsph1geTw6vBMmFiuDe9636CLf4yY+uZwo56zGPVteclqVdV0badYu5ADsmMnDGfan5t2fnAqVEKXacJfbcuDuQ1ueDyCLdxYcFmNmDJaIjI+4CzpwnRHsr07aH9NQ4n//tw= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1558620498918396.6196864840973; Thu, 23 May 2019 07:08:18 -0700 (PDT) Received: from localhost ([127.0.0.1]:37031 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToOB-0002s5-Lv for importer@patchew.org; Thu, 23 May 2019 10:08:11 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46560) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToHb-0006Gi-5k for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hToHY-0004Uz-JA for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:23 -0400 Received: from mail-ua1-x942.google.com ([2607:f8b0:4864:20::942]:45544) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hToHY-0004UP-CM for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:20 -0400 Received: by mail-ua1-x942.google.com with SMTP id n7so2198697uap.12 for ; Thu, 23 May 2019 07:01:20 -0700 (PDT) Received: from localhost.localdomain (ip-173-130-215-183.orldfl.spcsdns.net. [173.130.215.183]) by smtp.gmail.com with ESMTPSA id v133sm1984166vkv.5.2019.05.23.07.01.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 May 2019 07:01:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=2zUMv5xZP71KfmT0VCVXRmrjPE0MSztMOR2PXArEx1s=; b=VaNoCHTDjoFta03v2PX3OYuoPVjNZGLnuyKgJL3rvf9fOMzpLu3SogK9Wo4n9brYq1 QAvW7tj1bGXr1PO10vEGI3zuLoIdrCzlyrXCp/jsXvAqDKwH7Vuuy7fn/H/dlYIV4E2V ex97fUIPopHYaSVPDuICjp/zfrL4Bepsmp2Ne1apFvDgs2WdKAODXWjLm0BhTQPjMeBk 8SlTi1pWdcW7P8LZFztSnpdTSxN33n9qKNZWPuYDrMyNA06lmR8UZo9uhgWTRWgaVCmO OAeoZglUZwV9THdUjcFwk41QD/7k/ej6u0CLk63HM66nnAC0q4IuMmyLOaG6NN4aul4U 9nDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=2zUMv5xZP71KfmT0VCVXRmrjPE0MSztMOR2PXArEx1s=; b=O6cc+gUS5aQb8A80GB30qB1o52dtKEa3ayIxFlFAxoc/pqFtc2HXLfKuU2QxiqcSPy S+eq6sN6G3/Mzgt5RU9DHOuXeZ5R9ZsSUlncSNW5AIlWcuoBZ30KHr0JYv7gaBVanmv8 EEkTXFKGo8xWmX3q2MR5rKokCCPFGrj5XSwKauEG+wePfmDoPDuf0/1G+vWIwpOstUqT ISMQ6HVQYZoSSIfJtMJPAytwBVowuz15thaqB1/VWCMMljGaPmia15FPnJkK1m4W+DCu 6nEK495Ev4a0fnO4C4kAuK3EVAkRBkrTsrdUNiU7yg4FW0C5xX71+ooq/QrfEx7LLWLT HZ4w== X-Gm-Message-State: APjAAAWM70jLj832dT4MbfrAfgdrMwZBI3Ie5PpFMaQ+1W1ATpHw4gBu +89HBqzyFhELdw4b26pMt2pQeeJOTcwTUw== X-Google-Smtp-Source: APXvYqxC1waogUwkf6bdNT7Ahu6Cbb7VlqGW9182yODVe/PYwwVu4exuw1lywkXzdjuXPC3S1+1c9Q== X-Received: by 2002:ab0:1051:: with SMTP id g17mr13421139uab.41.1558620075875; Thu, 23 May 2019 07:01:15 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 23 May 2019 10:00:54 -0400 Message-Id: <20190523140059.18548-9-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190523140059.18548-1-richard.henderson@linaro.org> References: <20190523140059.18548-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::942 Subject: [Qemu-devel] [PULL 08/13] hw/rx: RX Target hardware definition X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) From: Yoshinori Sato rx62n - RX62N cpu. rx-virt - RX QEMU virtual target. Signed-off-by: Yoshinori Sato Tested-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20190516055244.95559-9-ysato@users.sourceforge.jp> Signed-off-by: Richard Henderson --- include/hw/rx/rx.h | 7 ++ include/hw/rx/rx62n.h | 94 +++++++++++++++++ hw/rx/rx-virt.c | 105 +++++++++++++++++++ hw/rx/rx62n.c | 238 ++++++++++++++++++++++++++++++++++++++++++ hw/rx/Kconfig | 14 +++ hw/rx/Makefile.objs | 2 + 6 files changed, 460 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..5f6912fe46 --- /dev/null +++ b/include/hw/rx/rx62n.h @@ -0,0 +1,94 @@ +/* + * 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 f= or + * 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 TYPE_RX62N_CPU RX_CPU_TYPE_NAME(TYPE_RX62N) +#define RX62N(obj) OBJECT_CHECK(RX62NState, (obj), TYPE_RX62N) + +enum { + RX62N_NR_TMR =3D 2, + RX62N_NR_CMT =3D 2, + RX62N_NR_SCI =3D 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..3deb7cb335 --- /dev/null +++ b/hw/rx/rx-virt.c @@ -0,0 +1,105 @@ +/* + * 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 f= or + * 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 rxvirt_init(MachineState *machine) +{ + RX62NState *s =3D g_new(RX62NState, 1); + MemoryRegion *sysmem =3D get_system_memory(); + MemoryRegion *sdram =3D g_new(MemoryRegion, 1); + const char *kernel_filename =3D machine->kernel_filename; + const char *dtb_filename =3D machine->dtb; + void *dtb =3D 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); + + /* Initalize CPU */ + 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 !=3D 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 =3D load_device_tree(dtb_filename, &dtb_size); + if (dtb =3D=3D NULL) { + fprintf(stderr, "Couldn't open dtb file %s\n", dtb_filenam= e); + 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] =3D 0x02000000 - dtb_size; + } + } +} + +static void rxvirt_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc =3D MACHINE_CLASS(oc); + + mc->desc =3D "RX QEMU Virtual Target"; + mc->init =3D rxvirt_init; + mc->is_default =3D 1; + mc->default_cpu_type =3D TYPE_RXCPU; +} + +static const TypeInfo rxvirt_type =3D { + .name =3D MACHINE_TYPE_NAME("rx-virt"), + .parent =3D TYPE_MACHINE, + .class_init =3D 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..c6660b75b4 --- /dev/null +++ b/hw/rx/rx62n.c @@ -0,0 +1,238 @@ +/* + * RX62N device + * + * 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 f= or + * 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] =3D { + 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[] =3D { + 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 =3D 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 =3D 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 =3D 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 =3D 0; i < NR_IRQS; i++) { + s->irq[i] =3D 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_IR= Q)); + sysbus_connect_irq(icu, 1, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_FI= R)); + 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 =3D 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 =3D RX62N_TMR_IRQBASE + TMR_NR_IRQ * unit; + for (i =3D 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 =3D 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 =3D RX62N_CMT_IRQBASE + CMT_NR_IRQ * unit; + for (i =3D 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 =3D 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 =3D RX62N_SCI_IRQBASE + SCI_NR_IRQ * unit; + for (i =3D 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 =3D 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); + } + + object_initialize_child(OBJECT(s), "cpu", &s->cpu, + sizeof(RXCPU), TYPE_RXCPU, + errp, NULL); + object_property_set_bool(OBJECT(&s->cpu), true, "realized", errp); + + register_icu(s); + s->cpu.env.ack =3D 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[] =3D { + 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 =3D DEVICE_CLASS(klass); + + dc->realize =3D rx62n_realize; + dc->props =3D rx62n_properties; +} + +static const TypeInfo rx62n_info =3D { + .name =3D TYPE_RX62N, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RX62NState), + .class_init =3D 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) +=3D rx62n.o +obj-$(CONFIG_RX_VIRT) +=3D rx-virt.o --=20 2.17.1 From nobody Sun May 5 10:44:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1558620673; cv=none; d=zoho.com; s=zohoarc; b=Q0yDCflvIgc8DsxjgijVzhDaZw+alQrw5Yh4Nzxs39vcZN4q8471+P+XuF4QMVljk35pFQ0E1mmLrfZ9+Qa+piKmulMzTkjHKjcOpkVMFl2iZr4q3+xG1crmd+q7Ifh3tiqNvMgvTRfEVIHJAQd7p3Ke8tUXxRyhJUA0mHX+P1E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558620673; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=cN7HSsTir9LPfFs0tqL8Rk/5kniGhoqrSHsDQ6DZZvw=; b=S8FgvSD9vdiWGinxEpTdP8nF3okdNun8MJAZ4Qfe/8RCPWLgLwMM4QXqmZBsDGWuMri5PGLx62xT0KA287Sw/9DpyWHngcS7SxKDyxgSlwrmOlGN/k4rCILckGRszic6UJjiGzUiGD9JhLL+x3x3TLvteXlafLai3mAcvdsDRvU= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1558620673723155.61499537875284; Thu, 23 May 2019 07:11:13 -0700 (PDT) Received: from localhost ([127.0.0.1]:37091 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToR3-0006HF-Nr for importer@patchew.org; Thu, 23 May 2019 10:11:09 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46568) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToHb-0006H3-JG for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hToHa-0004X7-Fu for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:23 -0400 Received: from mail-ua1-x931.google.com ([2607:f8b0:4864:20::931]:45267) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hToHa-0004Wf-AO for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:22 -0400 Received: by mail-ua1-x931.google.com with SMTP id n7so2198743uap.12 for ; Thu, 23 May 2019 07:01:22 -0700 (PDT) Received: from localhost.localdomain (ip-173-130-215-183.orldfl.spcsdns.net. [173.130.215.183]) by smtp.gmail.com with ESMTPSA id v133sm1984166vkv.5.2019.05.23.07.01.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 May 2019 07:01:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cN7HSsTir9LPfFs0tqL8Rk/5kniGhoqrSHsDQ6DZZvw=; b=dE4y100dtpMKczXTvrJJVBXBif3jy1bvx73wTA/KPdkJHm7lolCvVrPRnkntqADBOf j6OV5t0TgQ1rQrkJ5P1yApNGDdhBB8U3P4p4DjADMHsTSgNVXHL9As8qEQKK4i9MqhX+ HAtAxyMGxNkxvrZeRl8aIS+54b5jAvHbE+Fzo+lOGpLNs5Z289M7qVVXCniw/oAV8KQZ cys482X7KLqLGg9nahgIpsT9oyDegfBs3fBDAio5VpfUcERraafdQu74SQz5R3Zj/s17 dHuS6k2KPGYDYq2fej7PskmF0mxXZ+0TYG5BY1MJEVkDOeHtKsXBuoS1ar0sdYxWRm+d Q0fw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cN7HSsTir9LPfFs0tqL8Rk/5kniGhoqrSHsDQ6DZZvw=; b=spfAlwzWnYdKwT1ZhdjqcjNxkfVRyxv/p8oenrgz1skDIgNC4FdRLkje3sDB/hIiJC c0byyoEmvezk3sGnG8ak2UT0OvMmQWZLatmMvvoCtspwjOgNtT/OmdnKZuu8RX5HgW2h hwUydVYv/znSpZEzPWNk3zqDj+deruGHcI7FMcvQRSOK+cOsxCQ9qKmTw+1ZyVsGCW5r KVrLVek34ELKJ14vsAUSj/HTh7UWkJqUiLjtovO2UhNtwxtTQr/lB4HLIGTWdNyMwOP1 gTc9w3rQZ7DoMYM1UyUdTpdNgkiJChtuEBvaWm6laG2n0W5bNzpIyU34o1RuWcNCMcVG ildg== X-Gm-Message-State: APjAAAUlhADRm3Bq5TvMJMx3mMc0m6LGDK6BWuhqF3DojtGI/MX+fPl0 kClr8uQLNPOENXD3h81leZm6C92zR9nl0A== X-Google-Smtp-Source: APXvYqwuJ4d2erw479zJzSob5ukdnobdg/AxSgbxuKZt/O8g5Z7rblgFFyxnDQPeLp9/Hz7Y9zcbrw== X-Received: by 2002:ab0:7802:: with SMTP id x2mr4428653uaq.8.1558620077120; Thu, 23 May 2019 07:01:17 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 23 May 2019 10:00:55 -0400 Message-Id: <20190523140059.18548-10-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190523140059.18548-1-richard.henderson@linaro.org> References: <20190523140059.18548-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::931 Subject: [Qemu-devel] [PULL 09/13] qemu/bitops.h: Add extract8 and extract16 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) From: Yoshinori Sato Signed-off-by: Yoshinori Sato Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20190516055244.95559-12-ysato@users.sourceforge.jp> 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 @@ -300,6 +300,44 @@ static inline uint32_t extract32(uint32_t value, int s= tart, int length) return (value >> start) & (~0U >> (32 - length)); } =20 +/** + * 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 >=3D 0 && length > 0 && length <=3D 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 >=3D 0 && length > 0 && length <=3D 16 - start); + return extract32(value, start, length); +} + /** * extract64: * @value: the value to extract the bit field from --=20 2.17.1 From nobody Sun May 5 10:44:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1558620230; cv=none; d=zoho.com; s=zohoarc; b=B4i1JmBNW6di3D5kFaIDZ2L2ib8jNPOHPLW2LQFE3GW+d6UzTvmfHo+AGafedS3YzYUkWBTE2nSVM+L+Jn4u+ilbaiHjeUl8DhSgA0tyJCCy1ys0sbMy5rV/Fl2hUifT+qVH6r/eymT8h7CdfGHpwM0VBaW8LfCUGTx57YK7Ajw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558620230; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=1XbDcSxPxIwShmL7ibaMkqeCI/KNLPvufrTgWj8SAo0=; b=dGgF+9MP86dOjVBZ6noH5flbox4UoVuQ60Kuae7CRxdm60OczfCB/bRO0n4/g/AkgDxISU6l8x5fFHFrAV/0nIRIiLVkFKaDK2c+997zNym6ZW9I0mmSlTOSCDUH3R/kqC0Ho8WpxWoGp5ZO8Cij3K47F+2NaSQ4XILpQ56ZNNw= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1558620230454456.7541969220057; Thu, 23 May 2019 07:03:50 -0700 (PDT) Received: from localhost ([127.0.0.1]:36965 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToJt-0007Z4-GN for importer@patchew.org; Thu, 23 May 2019 10:03:45 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46503) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToHY-0006F5-UO for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hToHX-0004U3-O2 for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:20 -0400 Received: from mail-vs1-xe41.google.com ([2607:f8b0:4864:20::e41]:37945) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hToHX-0004Td-J5 for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:19 -0400 Received: by mail-vs1-xe41.google.com with SMTP id x184so3644978vsb.5 for ; Thu, 23 May 2019 07:01:19 -0700 (PDT) Received: from localhost.localdomain (ip-173-130-215-183.orldfl.spcsdns.net. [173.130.215.183]) by smtp.gmail.com with ESMTPSA id v133sm1984166vkv.5.2019.05.23.07.01.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 May 2019 07:01:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1XbDcSxPxIwShmL7ibaMkqeCI/KNLPvufrTgWj8SAo0=; b=Rb6LZ3/InjNx0VUBhtU+aR5muID1Z76HVg+NbdhXgvskYPIoA+uVZsXH/GtDnx0c7R YqVWRvE3Yvv4S4YoHKMZzvfyGfHGpWdAQAb+w0RQIaH7M/1G+z6pCGzFYu0XgbwSawAj QwTr2/IcCLCWSMniu3Z6dPXvJYqAN+kilgo5RrouMGJugTfdxiF9P5MNmxOnn48wbDW4 tgMf7hgdNT3rrmfOOQ3STkPWoTK7fKPVZJG06s1TMhPnQBqIRyCO+fWhcnjBBpNW5JoD X5Xvu2hjptqY+0rGQqyMJXWA8vicTRkIqQZRPyRw0pi44TMyW37CpyQRNtKe015piVw0 CX+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1XbDcSxPxIwShmL7ibaMkqeCI/KNLPvufrTgWj8SAo0=; b=BuxZkPI83oole06xLz/Jd3g0hDA5hEksmHngbW8vyIXFeNddXm6qDY9euwqVMOIZra aaPwIM1xWe8AEbcBrmAXprC+8c/3ufzDs1iAGB5IizfLExsVQujnx97oYwZ2Y8e8TOfp bpnubV5rRqKwSvyYpArreITk/GTWW4w14Pug2RrtTwSFXVBaD/IPBqLbxmVNBn0ZRhUx lWNGpNHYlFh4E8IhJvklWLOmmnLkSyUT+NBs37S3YT3r+nnZxQjYuNsRreiXmRXtL/xR jdArso2xphbq/qly8FRa/B/5QYLNQfgCRZySEVhs6IVo9CQzpcZB2x+ZTTCGi0J5urfI NGMw== X-Gm-Message-State: APjAAAULbvpIlgKt89ROI/zW04BXTetKNtnteViGsOz7kYU1gE+5Rw1m C4eXaxSTmnCC14DMDxG/rrWYlU/NM/drvw== X-Google-Smtp-Source: APXvYqy3SlbtmIwNT657LTANzCRacnbSC93jFYbL1KIZWLfHJr3huFwW5fB6D3KmS8Ahd4FLWcBqKA== X-Received: by 2002:a67:f610:: with SMTP id k16mr40647114vso.85.1558620078507; Thu, 23 May 2019 07:01:18 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 23 May 2019 10:00:56 -0400 Message-Id: <20190523140059.18548-11-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190523140059.18548-1-richard.henderson@linaro.org> References: <20190523140059.18548-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::e41 Subject: [Qemu-devel] [PULL 10/13] hw/registerfields.h: Add 8bit and 16bit register macros X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) From: Yoshinori Sato 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=C3=A9 Message-Id: <20190516055244.95559-11-ysato@users.sourceforge.jp> 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 =3D (addr) }; = \ enum { R_ ## reg =3D (addr) / 4 }; =20 +#define REG8(reg, addr) \ + enum { A_ ## reg =3D (addr) }; = \ + enum { R_ ## reg =3D (addr) }; + +#define REG16(reg, addr) \ + enum { A_ ## reg =3D (addr) }; = \ + enum { R_ ## reg =3D (addr) / 2 }; + /* Define SHIFT, LENGTH and MASK constants for a field within a register */ =20 /* This macro will define R_FOO_BAR_MASK, R_FOO_BAR_SHIFT and R_FOO_BAR_LE= NGTH @@ -34,6 +42,12 @@ MAKE_64BIT_MASK(shift, length)}; =20 /* 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 =3D { .v =3D val }; = \ + uint8_t d; \ + d =3D 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 =3D { .v =3D val }; = \ + uint16_t d; \ + d =3D 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 =3D 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 =3D { .v =3D val }; = \ --=20 2.17.1 From nobody Sun May 5 10:44:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1558620922; cv=none; d=zoho.com; s=zohoarc; b=E1ZN9dL/Pep4VxpgmXQ8LnrxRcIjsex8687jRSC/so8qnLrKD+vU5OluoYpo0ZQSdy7cM69YwRnbd7QLhPeTVF8nxbJ4IrTkGaqgu63W9DvhMSbBybk8tK60SRRjEoIPYdvwU8ZJjJ557+Cbg/0DxbDSdWIXfNU+ttdGDeqpxEE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558620922; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=YB1fZJoA1Y1wxrdEJayHVTCzPLNtdm/r4TsjTEPf7eE=; b=O5XshvG/bX7i8HMJB+YUHh/rX2uaopYhqHuSJgD5JENww5mZ/PN/edRwj2CFhLM4xBefFUlz9td38KFBaSTeQD/m8777ezBIGArf+eaLsUPSFlIeLGDG5HJPVl1SnGRI6TvceO0PmuvKjr2kmQM4/1cPnfcMQaO62STLVTiAXSE= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1558620922245666.9066424514245; Thu, 23 May 2019 07:15:22 -0700 (PDT) Received: from localhost ([127.0.0.1]:37149 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToUR-0001a2-Nn for importer@patchew.org; Thu, 23 May 2019 10:14:39 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46532) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToHa-0006G8-9y for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hToHZ-0004W9-3X for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:22 -0400 Received: from mail-vs1-xe42.google.com ([2607:f8b0:4864:20::e42]:45553) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hToHY-0004V3-VW for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:21 -0400 Received: by mail-vs1-xe42.google.com with SMTP id k187so3619909vsk.12 for ; Thu, 23 May 2019 07:01:20 -0700 (PDT) Received: from localhost.localdomain (ip-173-130-215-183.orldfl.spcsdns.net. [173.130.215.183]) by smtp.gmail.com with ESMTPSA id v133sm1984166vkv.5.2019.05.23.07.01.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 May 2019 07:01:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=YB1fZJoA1Y1wxrdEJayHVTCzPLNtdm/r4TsjTEPf7eE=; b=B/UmNJcUfwurBTD6GtX5T1UFo3oDrI9OrwB33nF75S8mgqcvqfX3UiVKP44FXt5k26 HM0h9BNes+T/SMLulrdNgGcj0Bi/KkMfqLXoEoM6YH1oQPQDw5r22DjMP+MxpvKbGVZV wcr7bfoNvGxihu4BD0af04Gy0SZMOuRZEAsoyo71jKy02ikihniIfWrd1oAWpyUfUXtF J6yJfZfwWHnbaN129rNak1qpNIFrtxCswSEC5J+qgmgrrzomIK18lDsWb0HpmUX3cJl0 dWA5nzeremXvnhcWkFmiOYV9uDmLomV4iFM/01ihwKdt/xCDP2vDjoe2XLb0D60PGFk5 yRjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=YB1fZJoA1Y1wxrdEJayHVTCzPLNtdm/r4TsjTEPf7eE=; b=q3cgk/lYWYUDvm7+i5E4nzf9gBqoXcfkZfM1Uby3H9bVG9RsMIo8FMmSWfh5AAo9i2 Dr0lj7MmlBzc0dS6D5JynFdY7zfMWPMzgtTyrpMhtDrt2kAW2SR0Zi82iXGcPeIQH/eG h/y3xp8prpZR3KUJQMrqbpvsn896hzpiACQwjgD14fwrn1sRtdXZCcW+oUYFXySAoVvy u4F67i31kEvtGiy0rO45LptbCp8mXcWPcm62fvS10cIldDOlLZrGLHZR9lAQvoEwf6KQ zBeOEAlFAu7eXJJfTfp8LkwEQ63Qe84U5hYJC4SA2cBctjHTkYhWQzlQ1wh4vBkz/l9x IiXg== X-Gm-Message-State: APjAAAUX38+6+i29URhkt24URvD6gj26K1kjBVWQzaqyzvE7G+Nch4nK WWTPaw7e8FjjCEStNMrIop59PX+oOB1W/Q== X-Google-Smtp-Source: APXvYqxhULkviZp694FyBkD2NCrAQL/q/tTKWrcvcGgDtX3+iS59p6ZrLWszLRLF7B30vbv+caIy6A== X-Received: by 2002:a67:eb82:: with SMTP id e2mr45758309vso.13.1558620079920; Thu, 23 May 2019 07:01:19 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 23 May 2019 10:00:57 -0400 Message-Id: <20190523140059.18548-12-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190523140059.18548-1-richard.henderson@linaro.org> References: <20190523140059.18548-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::e42 Subject: [Qemu-devel] [PULL 11/13] target/rx: Convert to CPUClass::tlb_fill X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) The interface for tlb_fill has changed very recently. Move the function into cpu.c so that it may be static while assigning to the CPUClass methods. Reviewed-by: Philippe Mathieu-Daud=C3=A9 Signed-off-by: Richard Henderson --- target/rx/cpu.c | 14 ++++++++++++++ target/rx/op_helper.c | 11 ----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/target/rx/cpu.c b/target/rx/cpu.c index 4b96f2e463..3268077d08 100644 --- a/target/rx/cpu.c +++ b/target/rx/cpu.c @@ -143,6 +143,19 @@ static void rx_cpu_disas_set_info(CPUState *cpu, disas= semble_info *info) info->print_insn =3D print_insn_rx; } =20 +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 =3D physical =3D addr & TARGET_PAGE_MASK; + prot =3D 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 =3D CPU(obj); @@ -177,6 +190,7 @@ static void rxcpu_class_init(ObjectClass *klass, void *= data) cc->get_phys_page_debug =3D rx_cpu_get_phys_page_debug; cc->disas_set_info =3D rx_cpu_disas_set_info; cc->tcg_initialize =3D rx_translate_init; + cc->tlb_fill =3D rx_cpu_tlb_fill; =20 cc->gdb_num_core_regs =3D 26; } diff --git a/target/rx/op_helper.c b/target/rx/op_helper.c index 9a460070e9..fb7ae3c3ec 100644 --- a/target/rx/op_helper.c +++ b/target/rx/op_helper.c @@ -468,14 +468,3 @@ void QEMU_NORETURN helper_rxbrk(CPURXState *env) { raise_exception(env, 0x100, 0); } - -void tlb_fill(CPUState *cs, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) -{ - uint32_t address, physical, prot; - - /* Linear mapping */ - address =3D physical =3D addr & TARGET_PAGE_MASK; - prot =3D PAGE_READ | PAGE_WRITE | PAGE_EXEC; - tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE); -} --=20 2.17.1 From nobody Sun May 5 10:44:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1558621280; cv=none; d=zoho.com; s=zohoarc; b=R9gHKb625Jbyk6b2rbaqzR7Z18lMmGXAoFHZO46RQVzzi7xVVPt1his1YBcpG1tzUI5TjRbSJjlGr+oWRny2trJruE+cF3pgQOJA0t3HrBp7og2nAKkJhFg7kkF4AB0QoQBeds6dTjmKQaJNt1EBqxFcM5/EoHWlmvxTKD5sbBU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558621280; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=Zp/XppcdDbx7mB8QWYDppSxf4juiYNTe8E7a8rf4oVA=; b=RWxNB70UsfPqV8kJc6czA+O69jMENh/RdhB5UUn/y4uQO91Olz6B+MRD9f2xiadlZWUV3li9oTPp7ydoOSdBnxUvnjijxZ1FHYgsminA+HSnxeLFeA52ECZP/BeswH+LPP/AKL6enai6RLZjjR/WmiDawe2pPlsB9ekeDWfgmgE= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1558621280962625.6194861199241; Thu, 23 May 2019 07:21:20 -0700 (PDT) Received: from localhost ([127.0.0.1]:37346 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToap-00085q-50 for importer@patchew.org; Thu, 23 May 2019 10:21:15 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46605) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToHf-0006Jy-Gt for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hToHa-0004XJ-LE for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:27 -0400 Received: from mail-vs1-xe43.google.com ([2607:f8b0:4864:20::e43]:43641) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hToHa-0004Wr-GB for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:22 -0400 Received: by mail-vs1-xe43.google.com with SMTP id d128so3624723vsc.10 for ; Thu, 23 May 2019 07:01:22 -0700 (PDT) Received: from localhost.localdomain (ip-173-130-215-183.orldfl.spcsdns.net. [173.130.215.183]) by smtp.gmail.com with ESMTPSA id v133sm1984166vkv.5.2019.05.23.07.01.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 May 2019 07:01:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Zp/XppcdDbx7mB8QWYDppSxf4juiYNTe8E7a8rf4oVA=; b=MklDAxKv9JKngGPfJmB5DzbxL+4KSprzwb5aIGaklxAMOgptWu0oA51mDPu8V+PXdv 17SV3UJQIQ3hzThVzxnERiuzCg2j33tXNCuDFbpnezK1yXRB4A2OsEyXba7QpbOPaR1y d0a8XVhxR5Q0RrD9CYihP8KiWUVB2VyYQAVxg19GjHQUE/8B+aGSp8A2WiAmTYBuaK44 bGPKAZ/YRYxKRP5o0xcqYYPxADztxyoSVQD8WovoAVz45VqffRikgbW0E4zKGLi3H/9G Rs4xRqG/iYd9qFLkUETbAGtZwwadE4oFXJppmC1hINh2p7SKqn1dQ1NEFuqTA6gpqdAs +PCQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Zp/XppcdDbx7mB8QWYDppSxf4juiYNTe8E7a8rf4oVA=; b=RAkc+q8GGkfdGnhlH10I8/WT+857wz1HXZpMPsOqSa4i/geChxtVjHfCcDDlJN8Gfq J58VfDzfcJOUUyMCXysaUBsBFkG60VYmUAwMdQAjjKodTdP5hVtT70V8VeehieJl2cBh wrpHbi1RfEsA8f9KgNRvfn4YiEGDOGywRVvzlq7sGJ5NJoH88IW+8wLQF9C88ylpij0i yfkvWZch+zIAm7nXcvdyDmky1EBx9eGjAytEXwGFN9eD8ZDMwxORKoUEp3ZEw5jToTGQ 4RE2xzLziHB4RuSnSaO1B6UpiaxsK14zPUyHRuNGI2bpsBf2AJMjh/eonXmjsh4qT+fM bi2A== X-Gm-Message-State: APjAAAUj5n8Bpo428YyemtWlvyX8wQMSkksdMVZCPipqRlHbXpnqo9pK uIdhwGfZKZDCF5twxiPOe88BG+wmDHEvag== X-Google-Smtp-Source: APXvYqxh6B7OiCZIg8ERnRNfNyQGl/jJbQK3gM2sc5wmMle4lyxOvK4zM8roE+Hv2Atr8iasgcTVdA== X-Received: by 2002:a67:b348:: with SMTP id b8mr39678030vsm.144.1558620081333; Thu, 23 May 2019 07:01:21 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 23 May 2019 10:00:58 -0400 Message-Id: <20190523140059.18548-13-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190523140059.18548-1-richard.henderson@linaro.org> References: <20190523140059.18548-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::e43 Subject: [Qemu-devel] [PULL 12/13] Add rx-softmmu X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) From: Yoshinori Sato Tested-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Philippe Mathieu-Daud=C3=A9 Signed-off-by: Yoshinori Sato Message-Id: <20190516055244.95559-10-ysato@users.sourceforge.jp> Signed-off-by: Richard Henderson --- include/sysemu/arch_init.h | 1 + arch_init.c | 2 ++ configure | 8 ++++++++ default-configs/rx-softmmu.mak | 3 +++ hw/Kconfig | 1 + 5 files changed, 15 insertions(+) create mode 100644 default-configs/rx-softmmu.mak 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 =3D (1 << 17), QEMU_ARCH_HPPA =3D (1 << 18), QEMU_ARCH_RISCV =3D (1 << 19), + QEMU_ARCH_RX =3D (1 << 20), }; =20 extern const uint32_t arch_type; diff --git a/arch_init.c b/arch_init.c index f4f3f610c8..cc25ddd7ca 100644 --- a/arch_init.c +++ b/arch_init.c @@ -74,6 +74,8 @@ int graphic_depth =3D 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/configure b/configure index 528b9ff705..dc04d6d13f 100755 --- a/configure +++ b/configure @@ -7578,6 +7578,11 @@ case "$target_name" in gdb_xml_files=3D"riscv-64bit-cpu.xml riscv-64bit-fpu.xml riscv-64bit-c= sr.xml" target_compiler=3D$cross_cc_riscv64 ;; + rx) + TARGET_ARCH=3Drx + bflt=3D"yes" + target_compiler=3D$cross_cc_rx + ;; sh4|sh4eb) TARGET_ARCH=3Dsh4 bflt=3D"yes" @@ -7798,6 +7803,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=3Dy diff --git a/hw/Kconfig b/hw/Kconfig index 88b9f15007..63a071092e 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -53,6 +53,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 --=20 2.17.1 From nobody Sun May 5 10:44:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1558620592; cv=none; d=zoho.com; s=zohoarc; b=QJEHox/y1XhJKrCSjlkvufg61OJU8kOf4vTbxxFfp0kJYThTRAEGighbpneM1/Ak59nNKcklBEnGoLgLvtV93TCPq55Y7UTud9bNKmHObnDGzs68bNR2FRLMQbz07/cNNisvsn0fryQ2GKIBsiBLFzmfQ1MTi1U3NigPPdQSt9M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558620592; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=W84fD2UDw9a9LmU00h2mTYcGOrNskf3otw0HP+RWaOg=; b=A32aQYrhJjmkZ1pf4CAm4aJiSqEWhlwlsFwgscaca8AihBXbna67RIrNA09EStvo4nYkBxOh3suZGjHuM8Pj0dZzf31/InsIKE1+5CdoIiXeyuXb6s0Dy1Rf6V0DuysUhnwV3cRwHU54ABKuEeQ6Mtw0QYhHEfL0RhTxO/Wi2Pc= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1558620592901362.9603505233573; Thu, 23 May 2019 07:09:52 -0700 (PDT) Received: from localhost ([127.0.0.1]:37045 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToPh-0004UB-T4 for importer@patchew.org; Thu, 23 May 2019 10:09:45 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46588) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hToHc-0006IE-Rc for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hToHb-0004YD-UF for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:24 -0400 Received: from mail-vs1-xe42.google.com ([2607:f8b0:4864:20::e42]:39960) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hToHb-0004Xz-Pf for qemu-devel@nongnu.org; Thu, 23 May 2019 10:01:23 -0400 Received: by mail-vs1-xe42.google.com with SMTP id c24so3638813vsp.7 for ; Thu, 23 May 2019 07:01:23 -0700 (PDT) Received: from localhost.localdomain (ip-173-130-215-183.orldfl.spcsdns.net. [173.130.215.183]) by smtp.gmail.com with ESMTPSA id v133sm1984166vkv.5.2019.05.23.07.01.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 May 2019 07:01:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=W84fD2UDw9a9LmU00h2mTYcGOrNskf3otw0HP+RWaOg=; b=WxiuXh9CygRREcnOMOKzYlC6/bqNX7dtYcyM1XfFm+Kg6b2VKcHyci3YwJglXLywZm MdOMxRx6St4K4O84vOFhvgzjkNbWihngqXWSQi577AQuhi5I8QNr6ckLrCZOI+BAQcpC QanG1YGiy/GifZQ+sbA+Lgv/uAYuH2xPHjzp1yHUBjXjn4qjV3e2VtbZToGHtiyFRiTd HAjDfNuqMq0k+n8V1aGRiJ9kgyS2La0HN1gLN/ZOvLvmp7UNh9iXYoy9SY4d21YK+8By eGKaPuEfyZHBBOCN/gQhNzfXzCT64px2NVDhmbiM1x7BKHkynEsPIP298T7QLxxBl7L7 0A4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=W84fD2UDw9a9LmU00h2mTYcGOrNskf3otw0HP+RWaOg=; b=YWG60uhYloH0VSx384XTRD8rUR7KnrxT9iYYoFqVtCz22KL8B8HxmBhuyO0nejQDXP rnHUuBPjg6BXggmJSaeH30loYQYBZPbns0DIxYUFEZRTObQxkXLfqVNelroKcb8Ee88y aLno3jass4cllsTwb6dHSYHp733dV4P4BgUgCQOhsRTtf2bK7gMptzCsKPg0lHV8ogeZ 1mis8YsRicfITCgcvE2ncNXs6StJpkLAhIrwhlthW9WYw6Q7iHhPcR0u/Q2jQ6SU/on5 4Ne5ZXK8U3RCNDAVqCjbADvgHeyaYRi24JD/Qmf+b5B8NmXkRi4EEHtUbD/KV75V17/O lQgA== X-Gm-Message-State: APjAAAUV9wXTN2HT6yZuW3nQVSbP5pCvkI0wHzzYFfCEQ9M78fuV0Fkq +tT48HRgU4Y1IQY3AaQSqhxIukBPthqgog== X-Google-Smtp-Source: APXvYqxlh6WnbqzM0zeW/4+JhZapnDdGHB4+ztuZA+FM0XY6eAvDIHX5cS2z+2Hs0uFlZ4AONykxGA== X-Received: by 2002:a67:c885:: with SMTP id v5mr48602285vsk.49.1558620082847; Thu, 23 May 2019 07:01:22 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 23 May 2019 10:00:59 -0400 Message-Id: <20190523140059.18548-14-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190523140059.18548-1-richard.henderson@linaro.org> References: <20190523140059.18548-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::e42 Subject: [Qemu-devel] [PULL 13/13] MAINTAINERS: Add RX X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) From: Yoshinori Sato Signed-off-by: Yoshinori Sato Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20190516055244.95559-13-ysato@users.sourceforge.jp> Signed-off-by: Richard Henderson --- MAINTAINERS | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 73a0105082..5286970936 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -272,6 +272,13 @@ F: include/hw/riscv/ F: linux-user/host/riscv32/ F: linux-user/host/riscv64/ =20 +RENESAS RX +M: Yoshinori Sato +S: Maintained +F: target/rx/ +F: hw/rx/ +F: include/hw/rx/ + S390 M: Richard Henderson M: David Hildenbrand @@ -1106,6 +1113,18 @@ F: pc-bios/canyonlands.dt[sb] F: pc-bios/u-boot-sam460ex-20100605.bin F: roms/u-boot-sam460ex =20 +RX Machines +----------- +RX-QEMU +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 --=20 2.17.1