qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support
@ 2019-09-12  6:06 Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 01/22] MAINTAINERS: Add RX Yoshinori Sato
                   ` (27 more replies)
  0 siblings, 28 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, richard.henderson, Yoshinori Sato, philmd

Hello.
This patch series is added Renesas RX target emulation.

Changes for v23.
Follow master changes.

Changes for v22.
Added some include.

Changes for v21.
rebase latest master.
Remove unneeded hmp_info_tlb.

Chanegs for v20.
Reorderd patches.
Squashed v19 changes.

Changes for v19.
Follow tcg changes.
Cleanup cpu.c.
simplify rx_cpu_class_by_name and rx_load_image move to rx-virt.

My git repository is bellow.
git://git.pf.osdn.net/gitroot/y/ys/ysato/qemu.git tags/rx-20190912

Testing binaries bellow.
u-boot
Download - https://osdn.net/users/ysato/pf/qemu/dl/u-boot.bin.gz

starting
$ gzip -d u-boot.bin.gz
$ qemu-system-rx -bios u-boot.bin

linux and pico-root (only sash)
Download - https://osdn.net/users/ysato/pf/qemu/dl/zImage (kernel)
           https://osdn.net/users/ysato/pf/qemu/dl/rx-qemu.dtb (DeviceTree)

starting
$ qemu-system-rx -kernel zImage -dtb rx-qemu.dtb -append "earlycon"

Philippe Mathieu-Daudé (3):
  hw/registerfields.h: Add 8bit and 16bit register macros
  hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
  BootLinuxConsoleTest: Test the RX-Virt machine

Richard Henderson (7):
  target/rx: Disassemble rx_index_addr into a string
  target/rx: Replace operand with prt_ldmi in disassembler
  target/rx: Use prt_ldmi for XCHG_mr disassembly
  target/rx: Emit all disassembly in one prt()
  target/rx: Collect all bytes during disassembly
  target/rx: Dump bytes for each insn during disassembly
  hw/rx: Honor -accel qtest

Yoshinori Sato (12):
  MAINTAINERS: Add RX
  qemu/bitops.h: Add extract8 and extract16
  target/rx: TCG translation
  target/rx: TCG helper
  target/rx: CPU definition
  target/rx: RX disassembler
  hw/intc: RX62N interrupt controller (ICUa)
  hw/timer: RX62N internal timer modules
  hw/char: RX62N serial communication interface (SCI)
  hw/rx: RX Target hardware definition
  Add rx-softmmu
  qapi/machine.json: Add RX cpu.

 configure                              |    8 +
 default-configs/rx-softmmu.mak         |    3 +
 qapi/machine.json                      |    2 +-
 include/disas/dis-asm.h                |    5 +
 include/exec/poison.h                  |    1 +
 include/hw/char/renesas_sci.h          |   45 +
 include/hw/intc/rx_icu.h               |   56 +
 include/hw/registerfields.h            |   32 +-
 include/hw/rx/rx.h                     |    7 +
 include/hw/rx/rx62n.h                  |   91 +
 include/hw/timer/renesas_cmt.h         |   38 +
 include/hw/timer/renesas_tmr.h         |   53 +
 include/qemu/bitops.h                  |   38 +
 include/sysemu/arch_init.h             |    1 +
 target/rx/cpu-param.h                  |   31 +
 target/rx/cpu-qom.h                    |   42 +
 target/rx/cpu.h                        |  181 ++
 target/rx/helper.h                     |   31 +
 arch_init.c                            |    2 +
 hw/char/renesas_sci.c                  |  343 ++++
 hw/intc/rx_icu.c                       |  379 ++++
 hw/rx/rx-virt.c                        |  135 ++
 hw/rx/rx62n.c                          |  247 +++
 hw/timer/renesas_cmt.c                 |  278 +++
 hw/timer/renesas_tmr.c                 |  458 +++++
 target/rx/cpu.c                        |  217 +++
 target/rx/disas.c                      | 1446 ++++++++++++++
 target/rx/gdbstub.c                    |  112 ++
 target/rx/helper.c                     |  149 ++
 target/rx/op_helper.c                  |  470 +++++
 target/rx/translate.c                  | 2432 ++++++++++++++++++++++++
 tests/machine-none-test.c              |    1 +
 MAINTAINERS                            |   19 +
 hw/Kconfig                             |    1 +
 hw/char/Kconfig                        |    3 +
 hw/char/Makefile.objs                  |    1 +
 hw/intc/Kconfig                        |    3 +
 hw/intc/Makefile.objs                  |    1 +
 hw/rx/Kconfig                          |   14 +
 hw/rx/Makefile.objs                    |    2 +
 hw/timer/Kconfig                       |    6 +
 hw/timer/Makefile.objs                 |    3 +
 target/rx/Makefile.objs                |   11 +
 target/rx/insns.decode                 |  621 ++++++
 tests/acceptance/boot_linux_console.py |   46 +
 45 files changed, 8063 insertions(+), 2 deletions(-)
 create mode 100644 default-configs/rx-softmmu.mak
 create mode 100644 include/hw/char/renesas_sci.h
 create mode 100644 include/hw/intc/rx_icu.h
 create mode 100644 include/hw/rx/rx.h
 create mode 100644 include/hw/rx/rx62n.h
 create mode 100644 include/hw/timer/renesas_cmt.h
 create mode 100644 include/hw/timer/renesas_tmr.h
 create mode 100644 target/rx/cpu-param.h
 create mode 100644 target/rx/cpu-qom.h
 create mode 100644 target/rx/cpu.h
 create mode 100644 target/rx/helper.h
 create mode 100644 hw/char/renesas_sci.c
 create mode 100644 hw/intc/rx_icu.c
 create mode 100644 hw/rx/rx-virt.c
 create mode 100644 hw/rx/rx62n.c
 create mode 100644 hw/timer/renesas_cmt.c
 create mode 100644 hw/timer/renesas_tmr.c
 create mode 100644 target/rx/cpu.c
 create mode 100644 target/rx/disas.c
 create mode 100644 target/rx/gdbstub.c
 create mode 100644 target/rx/helper.c
 create mode 100644 target/rx/op_helper.c
 create mode 100644 target/rx/translate.c
 create mode 100644 hw/rx/Kconfig
 create mode 100644 hw/rx/Makefile.objs
 create mode 100644 target/rx/Makefile.objs
 create mode 100644 target/rx/insns.decode

-- 
2.20.1



^ permalink raw reply	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 01/22] MAINTAINERS: Add RX
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 02/22] qemu/bitops.h: Add extract8 and extract16 Yoshinori Sato
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, richard.henderson, Yoshinori Sato, philmd

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20190607091116.49044-18-ysato@users.sourceforge.jp>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 MAINTAINERS | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 50eaf005f4..bfc99986cc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -271,6 +271,13 @@ F: include/hw/riscv/
 F: linux-user/host/riscv32/
 F: linux-user/host/riscv64/
 
+RENESAS RX CPUs
+M: Yoshinori Sato <ysato@users.sourceforge.jp>
+S: Maintained
+F: target/rx/
+F: hw/rx/
+F: include/hw/rx/
+
 S390 TCG CPUs
 M: Richard Henderson <rth@twiddle.net>
 M: David Hildenbrand <david@redhat.com>
@@ -1118,6 +1125,18 @@ F: pc-bios/canyonlands.dt[sb]
 F: pc-bios/u-boot-sam460ex-20100605.bin
 F: roms/u-boot-sam460ex
 
+RX Machines
+-----------
+rx-virt
+M: Yoshinori Sato <ysato@users.sourceforge.jp>
+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
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 02/22] qemu/bitops.h: Add extract8 and extract16
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 01/22] MAINTAINERS: Add RX Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 03/22] hw/registerfields.h: Add 8bit and 16bit register macros Yoshinori Sato
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, richard.henderson, Yoshinori Sato, philmd

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20190607091116.49044-10-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 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 start, int length)
     return (value >> start) & (~0U >> (32 - length));
 }
 
+/**
+ * extract8:
+ * @value: the value to extract the bit field from
+ * @start: the lowest bit in the bit field (numbered from 0)
+ * @length: the length of the bit field
+ *
+ * Extract from the 8 bit input @value the bit field specified by the
+ * @start and @length parameters, and return it. The bit field must
+ * lie entirely within the 8 bit word. It is valid to request that
+ * all 8 bits are returned (ie @length 8 and @start 0).
+ *
+ * Returns: the value of the bit field extracted from the input value.
+ */
+static inline uint8_t extract8(uint8_t value, int start, int length)
+{
+    assert(start >= 0 && length > 0 && length <= 8 - start);
+    return extract32(value, start, length);
+}
+
+/**
+ * extract16:
+ * @value: the value to extract the bit field from
+ * @start: the lowest bit in the bit field (numbered from 0)
+ * @length: the length of the bit field
+ *
+ * Extract from the 16 bit input @value the bit field specified by the
+ * @start and @length parameters, and return it. The bit field must
+ * lie entirely within the 16 bit word. It is valid to request that
+ * all 16 bits are returned (ie @length 16 and @start 0).
+ *
+ * Returns: the value of the bit field extracted from the input value.
+ */
+static inline uint16_t extract16(uint16_t value, int start, int length)
+{
+    assert(start >= 0 && length > 0 && length <= 16 - start);
+    return extract32(value, start, length);
+}
+
 /**
  * extract64:
  * @value: the value to extract the bit field from
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 03/22] hw/registerfields.h: Add 8bit and 16bit register macros
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 01/22] MAINTAINERS: Add RX Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 02/22] qemu/bitops.h: Add extract8 and extract16 Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 04/22] target/rx: TCG translation Yoshinori Sato
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Yoshinori Sato, richard.henderson,
	Alistair Francis, imammedo, Philippe Mathieu-Daudé

From: Philippe Mathieu-Daudé <philmd@redhat.com>

Some RX peripheral using 8bit and 16bit registers.
Added 8bit and 16bit APIs.

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20190607091116.49044-11-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/hw/registerfields.h | 32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/include/hw/registerfields.h b/include/hw/registerfields.h
index 2659a58737..a0bb0654d6 100644
--- a/include/hw/registerfields.h
+++ b/include/hw/registerfields.h
@@ -22,6 +22,14 @@
     enum { A_ ## reg = (addr) };                                          \
     enum { R_ ## reg = (addr) / 4 };
 
+#define REG8(reg, addr)                                                  \
+    enum { A_ ## reg = (addr) };                                          \
+    enum { R_ ## reg = (addr) };
+
+#define REG16(reg, addr)                                                  \
+    enum { A_ ## reg = (addr) };                                          \
+    enum { R_ ## reg = (addr) / 2 };
+
 /* Define SHIFT, LENGTH and MASK constants for a field within a register */
 
 /* This macro will define R_FOO_BAR_MASK, R_FOO_BAR_SHIFT and R_FOO_BAR_LENGTH
@@ -34,6 +42,12 @@
                                         MAKE_64BIT_MASK(shift, length)};
 
 /* Extract a field from a register */
+#define FIELD_EX8(storage, reg, field)                                    \
+    extract8((storage), R_ ## reg ## _ ## field ## _SHIFT,                \
+              R_ ## reg ## _ ## field ## _LENGTH)
+#define FIELD_EX16(storage, reg, field)                                   \
+    extract16((storage), R_ ## reg ## _ ## field ## _SHIFT,               \
+              R_ ## reg ## _ ## field ## _LENGTH)
 #define FIELD_EX32(storage, reg, field)                                   \
     extract32((storage), R_ ## reg ## _ ## field ## _SHIFT,               \
               R_ ## reg ## _ ## field ## _LENGTH)
@@ -49,6 +63,22 @@
  * Assigning values larger then the target field will result in
  * compilation warnings.
  */
+#define FIELD_DP8(storage, reg, field, val) ({                            \
+    struct {                                                              \
+        unsigned int v:R_ ## reg ## _ ## field ## _LENGTH;                \
+    } v = { .v = val };                                                   \
+    uint8_t d;                                                            \
+    d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT,           \
+                  R_ ## reg ## _ ## field ## _LENGTH, v.v);               \
+    d; })
+#define FIELD_DP16(storage, reg, field, val) ({                           \
+    struct {                                                              \
+        unsigned int v:R_ ## reg ## _ ## field ## _LENGTH;                \
+    } v = { .v = val };                                                   \
+    uint16_t d;                                                           \
+    d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT,           \
+                  R_ ## reg ## _ ## field ## _LENGTH, v.v);               \
+    d; })
 #define FIELD_DP32(storage, reg, field, val) ({                           \
     struct {                                                              \
         unsigned int v:R_ ## reg ## _ ## field ## _LENGTH;                \
@@ -57,7 +87,7 @@
     d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT,           \
                   R_ ## reg ## _ ## field ## _LENGTH, v.v);               \
     d; })
-#define FIELD_DP64(storage, reg, field, val) ({                           \
+#define FIELD_DP64(storage, reg, field, val) ({                         \
     struct {                                                              \
         unsigned int v:R_ ## reg ## _ ## field ## _LENGTH;                \
     } v = { .v = val };                                                   \
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 04/22] target/rx: TCG translation
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (2 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 03/22] hw/registerfields.h: Add 8bit and 16bit register macros Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 05/22] target/rx: TCG helper Yoshinori Sato
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, richard.henderson, Yoshinori Sato, philmd

This part only supported RXv1 instructions.
Instruction manual.
https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01us0032ej0120_rxsm.pdf

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20190607091116.49044-2-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 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..21a67db570
--- /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 for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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] = {
+    "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 <= n) {
+        uint8_t b = cpu_ldub_code(ctx->env, ctx->base.pc_next++);
+        insn |= b << (32 - i * 8);
+    }
+    return insn;
+}
+
+static uint32_t li(DisasContext *ctx, int sz)
+{
+    int32_t tmp, addr;
+    CPURXState *env = ctx->env;
+    addr = ctx->base.pc_next;
+
+    tcg_debug_assert(sz < 4);
+    switch (sz) {
+    case 1:
+        ctx->base.pc_next += 1;
+        return cpu_ldsb_code(env, addr);
+    case 2:
+        ctx->base.pc_next += 2;
+        return cpu_ldsw_code(env, addr);
+    case 3:
+        ctx->base.pc_next += 3;
+        tmp = cpu_ldsb_code(env, addr + 2) << 16;
+        tmp |= cpu_lduw_code(env, addr) & 0xffff;
+        return tmp;
+    case 0:
+        ctx->base.pc_next += 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 += 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 = RXCPU(cs);
+    CPURXState *env = &cpu->env;
+    int i;
+    uint32_t psw;
+
+    psw = rx_cpu_pack_psw(env);
+    qemu_fprintf(f, "pc=0x%08x psw=0x%08x\n",
+                 env->pc, psw);
+    for (i = 0; i < 16; i += 4) {
+        qemu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\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 = 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 = cpu_ldub_code(ctx->env, ctx->base.pc_next) << size;
+        tcg_gen_addi_i32(mem, cpu_regs[reg], dsp);
+        ctx->base.pc_next += 1;
+        return mem;
+    case 2:
+        dsp = cpu_lduw_code(ctx->env, ctx->base.pc_next) << size;
+        tcg_gen_addi_i32(mem, cpu_regs[reg], dsp);
+        ctx->base.pc_next += 2;
+        return mem;
+    }
+    return NULL;
+}
+
+static inline MemOp mi_to_mop(unsigned mi)
+{
+    static const MemOp mop[5] = { 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;
+    MemOp mop;
+    if (ld < 3) {
+        mop = mi_to_mop(mi);
+        addr = 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 = TCG_COND_EQ;
+        dc->value = cpu_psw_z;
+        break;
+    case 1: /* nz */
+        dc->cond = TCG_COND_NE;
+        dc->value = cpu_psw_z;
+        break;
+    case 2: /* c */
+        dc->cond = TCG_COND_NE;
+        dc->value = cpu_psw_c;
+        break;
+    case 3: /* nc */
+        dc->cond = TCG_COND_EQ;
+        dc->value = cpu_psw_c;
+        break;
+    case 4: /* gtu (C& ~Z) == 1 */
+    case 5: /* leu (C& ~Z) == 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 = (cond == 4) ? TCG_COND_NE : TCG_COND_EQ;
+        dc->value = dc->temp;
+        break;
+    case 6: /* pz (S == 0) */
+        dc->cond = TCG_COND_GE;
+        dc->value = cpu_psw_s;
+        break;
+    case 7: /* n (S == 1) */
+        dc->cond = TCG_COND_LT;
+        dc->value = cpu_psw_s;
+        break;
+    case 8: /* ge (S^O)==0 */
+    case 9: /* lt (S^O)==1 */
+        tcg_gen_xor_i32(dc->temp, cpu_psw_o, cpu_psw_s);
+        dc->cond = (cond == 8) ? TCG_COND_GE : TCG_COND_LT;
+        dc->value = dc->temp;
+        break;
+    case 10: /* gt ((S^O)|Z)==0 */
+    case 11: /* le ((S^O)|Z)==1 */
+        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 = (cond == 10) ? TCG_COND_NE : TCG_COND_EQ;
+        dc->value = dc->temp;
+        break;
+    case 12: /* o */
+        dc->cond = TCG_COND_LT;
+        dc->value = cpu_psw_o;
+        break;
+    case 13: /* no */
+        dc->cond = TCG_COND_GE;
+        dc->value = cpu_psw_o;
+        break;
+    case 14: /* always true */
+        dc->cond = TCG_COND_ALWAYS;
+        dc->value = dc->temp;
+        break;
+    case 15: /* always false */
+        dc->cond = TCG_COND_NEVER;
+        dc->value = dc->temp;
+        break;
+    }
+}
+
+static void move_from_cr(TCGv ret, int cr, uint32_t pc)
+{
+    TCGv z = 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 >= 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 = 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.<bwl> rs,dsp5[rd] */
+static bool trans_MOV_rm(DisasContext *ctx, arg_MOV_rm *a)
+{
+    TCGv mem;
+    mem = 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.<bwl> dsp5[rs],rd */
+static bool trans_MOV_mr(DisasContext *ctx, arg_MOV_mr *a)
+{
+    TCGv mem;
+    mem = 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.<bwl> #uimm8,dsp[rd] */
+/* mov.<bwl> #imm, dsp[rd] */
+static bool trans_MOV_im(DisasContext *ctx, arg_MOV_im *a)
+{
+    TCGv imm, mem;
+    imm = tcg_const_i32(a->imm);
+    mem = 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.<bwl> [ri,rb],rd */
+static bool trans_MOV_ar(DisasContext *ctx, arg_MOV_ar *a)
+{
+    TCGv mem;
+    mem = 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.<bwl> rd,[ri,rb] */
+static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a)
+{
+    TCGv mem;
+    mem = 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.<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)
+{
+    static void (* const mov[])(TCGv ret, TCGv arg) = {
+        tcg_gen_ext8s_i32, tcg_gen_ext16s_i32, tcg_gen_mov_i32,
+    };
+    TCGv tmp, mem, addr;
+    if (a->lds == 3 && a->ldd == 3) {
+        /* mov.<bwl> rs,rd */
+        mov[a->sz](cpu_regs[a->rd], cpu_regs[a->rs]);
+        return true;
+    }
+
+    mem = tcg_temp_new();
+    if (a->lds == 3) {
+        /* mov.<bwl> rs,dsp[rd] */
+        addr = 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 == 3) {
+        /* mov.<bwl> dsp[rs],rd */
+        addr = rx_index_addr(ctx, mem, a->lds, a->sz, a->rs);
+        rx_gen_ld(a->sz, cpu_regs[a->rd], addr);
+    } else {
+        /* mov.<bwl> dsp[rs],dsp[rd] */
+        tmp = tcg_temp_new();
+        addr = rx_index_addr(ctx, mem, a->lds, a->sz, a->rs);
+        rx_gen_ld(a->sz, tmp, addr);
+        addr = 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.<bwl> rs,[rd+] */
+/* mov.<bwl> rs,[-rd] */
+static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a)
+{
+    TCGv val;
+    val = tcg_temp_new();
+    tcg_gen_mov_i32(val, cpu_regs[a->rs]);
+    if (a->ad == 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 == 0) {
+        tcg_gen_addi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz);
+    }
+    tcg_temp_free(val);
+    return true;
+}
+
+/* mov.<bwl> [rd+],rs */
+/* mov.<bwl> [-rd],rs */
+static bool trans_MOV_pr(DisasContext *ctx, arg_MOV_pr *a)
+{
+    TCGv val;
+    val = tcg_temp_new();
+    if (a->ad == 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 == 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.<bw> dsp5[rs],rd */
+/* movu.<bw> dsp[rs],rd */
+static bool trans_MOVU_mr(DisasContext *ctx, arg_MOVU_mr *a)
+{
+    TCGv mem;
+    mem = 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.<bw> rs,rd */
+static bool trans_MOVU_rr(DisasContext *ctx, arg_MOVU_rr *a)
+{
+    static void (* const ext[])(TCGv ret, TCGv arg) = {
+        tcg_gen_ext8u_i32, tcg_gen_ext16u_i32,
+    };
+    ext[a->sz](cpu_regs[a->rd], cpu_regs[a->rs]);
+    return true;
+}
+
+/* movu.<bw> [ri,rb],rd */
+static bool trans_MOVU_ar(DisasContext *ctx, arg_MOVU_ar *a)
+{
+    TCGv mem;
+    mem = 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.<bw> [rd+],rs */
+/* mov.<bw> [-rd],rs */
+static bool trans_MOVU_pr(DisasContext *ctx, arg_MOVU_pr *a)
+{
+    TCGv val;
+    val = tcg_temp_new();
+    if (a->ad == 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 == 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 = 0;
+    mov_a.rs = a->rd;
+    mov_a.ad = 0;
+    mov_a.sz = MO_32;
+    trans_MOV_pr(ctx, &mov_a);
+    return true;
+}
+
+/* popc cr */
+static bool trans_POPC(DisasContext *ctx, arg_POPC *a)
+{
+    TCGv val;
+    val = tcg_temp_new();
+    pop(val);
+    move_to_cr(ctx, val, a->cr);
+    if (a->cr == 0 && is_privileged(ctx, 0)) {
+        /* PSW.I may be updated here. exit TB. */
+        ctx->base.is_jmp = 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 == 0 || a->rd >= a->rd2) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "Invalid  register ranges r%d-r%d", a->rd, a->rd2);
+    }
+    r = a->rd;
+    while (r <= a->rd2 && r < 16) {
+        pop(cpu_regs[r++]);
+    }
+    return true;
+}
+
+
+/* push.<bwl> rs */
+static bool trans_PUSH_r(DisasContext *ctx, arg_PUSH_r *a)
+{
+    TCGv val;
+    val = 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.<bwl> dsp[rs] */
+static bool trans_PUSH_m(DisasContext *ctx, arg_PUSH_m *a)
+{
+    TCGv mem, val, addr;
+    mem = tcg_temp_new();
+    val = tcg_temp_new();
+    addr = 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 = 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 == 0 || a->rs >= a->rs2) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "Invalid  register ranges r%d-r%d", a->rs, a->rs2);
+    }
+    r = a->rs2;
+    while (r >= a->rs && r >= 0) {
+        push(cpu_regs[r--]);
+    }
+    return true;
+}
+
+/* xchg rs,rd */
+static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr *a)
+{
+    TCGv tmp;
+    tmp = 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].<mi>,rd */
+static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a)
+{
+    TCGv mem, addr;
+    mem = tcg_temp_new();
+    switch (a->mi) {
+    case 0: /* dsp[rs].b */
+    case 1: /* dsp[rs].w */
+    case 2: /* dsp[rs].l */
+        addr = rx_index_addr(ctx, mem, a->ld, a->mi, a->rs);
+        break;
+    case 3: /* dsp[rs].uw */
+    case 4: /* dsp[rs].ub */
+        addr = 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 = tcg_const_i32(0);
+    _imm = 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.<bwl> rd */
+/* sccnd.<bwl> dsp:[rd] */
+static bool trans_SCCnd(DisasContext *ctx, arg_SCCnd *a)
+{
+    DisasCompare dc;
+    TCGv val, mem, addr;
+    dc.temp = tcg_temp_new();
+    psw_cond(&dc, a->cd);
+    if (a->ld < 3) {
+        val = tcg_temp_new();
+        mem = tcg_temp_new();
+        tcg_gen_setcondi_i32(dc.cond, val, dc.value, 0);
+        addr = 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 = 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 >= a->rd) {
+        adj = a->imm - (a->rd2 - a->rd + 1);
+    } else {
+        adj = a->imm - (15 - a->rd + 1);
+    }
+
+    tcg_gen_addi_i32(cpu_sp, cpu_sp, adj << 2);
+    dst = a->rd;
+    while (dst <= a->rd2 && dst < 16) {
+        pop(cpu_regs[dst++]);
+    }
+    pop(cpu_pc);
+    ctx->base.is_jmp = 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 src2)
+{
+    TCGv imm = 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 = tcg_temp_new();
+    val = 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 = arg1 + arg2 + psw_c */
+static void rx_adc(TCGv ret, TCGv arg1, TCGv arg2)
+{
+    TCGv z;
+    z = 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 != 2) {
+        return false;
+    }
+    rx_gen_op_mr(rx_adc, ctx, a->rd, a->rs, a->ld, a->mi);
+    return true;
+}
+
+/* ret = arg1 + arg2 */
+static void rx_add(TCGv ret, TCGv arg1, TCGv arg2)
+{
+    TCGv z;
+    z = 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 = 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 = 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 = arg1 - arg2 - !psw_c */
+/* -> ret = arg1 + ~arg2 + psw_c */
+static void rx_sbb(TCGv ret, TCGv arg1, TCGv arg2)
+{
+    TCGv temp;
+    temp = 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 != 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 = tcg_temp_new();
+    zero = 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 = 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 = tcg_temp_new();
+    val = 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 = 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 = tcg_temp_new();
+    val = 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 = 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 = gen_new_label();
+    done = gen_new_label();
+    /* if (cpu_regs[a->rs]) { */
+    tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_regs[a->rs], 0, noshift);
+    count = tcg_const_i32(32);
+    tmp = 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) = {
+        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) = {
+        tcg_gen_shri_i32, tcg_gen_sari_i32,
+    };
+    static void (* const gen_sXr[])(TCGv ret, TCGv arg1, TCGv arg2) = {
+        tcg_gen_shr_i32, tcg_gen_sar_i32,
+    };
+    tcg_debug_assert(alith < 2);
+    noshift = gen_new_label();
+    done = gen_new_label();
+    count = 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 = 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 = 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 = 0, ROTL = 1};
+enum {ROT_IMM = 0, ROT_REG = 1};
+static inline void rx_rot(int ir, int dir, int rd, int src)
+{
+    switch (dir) {
+    case ROTL:
+        if (ir == 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 == 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 = 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 = tcg_temp_new();
+        psw_cond(&dc, cd);
+        t = gen_new_label();
+        done = 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 = DISAS_JUMP;
+    return true;
+}
+
+static inline void rx_save_pc(DisasContext *ctx)
+{
+    TCGv pc = 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 = 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 = 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 = DISAS_JUMP;
+    return true;
+}
+
+/* rts */
+static bool trans_RTS(DisasContext *ctx, arg_RTS *a)
+{
+    pop(cpu_pc);
+    ctx->base.is_jmp = 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 = tcg_const_i32(a->sz);       \
+        gen_helper_##op(cpu_env, size);         \
+        tcg_temp_free(size);                    \
+    } while (0)
+
+/* suntile.<bwl> */
+static bool trans_SUNTIL(DisasContext *ctx, arg_SUNTIL *a)
+{
+    STRING(suntil);
+    return true;
+}
+
+/* swhile.<bwl> */
+static bool trans_SWHILE(DisasContext *ctx, arg_SWHILE *a)
+{
+    STRING(swhile);
+    return true;
+}
+/* sstr.<bwl> */
+static bool trans_SSTR(DisasContext *ctx, arg_SSTR *a)
+{
+    STRING(sstr);
+    return true;
+}
+
+/* rmpa.<bwl> */
+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 = tcg_temp_new_i64();
+    tmp1 = 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 = tcg_temp_new_i64();
+    tmp1 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = tcg_temp_new();
+    z = tcg_const_i32(0);
+    /* S == 1 -> 0xffffffff / S == 0 -> 0x00000000 */
+    tcg_gen_sari_i32(tmp, cpu_psw_s, 31);
+    /* S == 1 -> 0x7fffffff / S == 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 = 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 = tcg_temp_new();                                           \
+        val = 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 = tcg_temp_new();                                   \
+        val = 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 = 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 = tcg_temp_new();
+    val = 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 = tcg_temp_new();
+    val = 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 = 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 = 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 = 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 = 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 = 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 = tcg_temp_new();                                           \
+        mask = tcg_const_i32(1 << a->imm);                              \
+        addr = 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 = 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 = tcg_const_i32(1);                                        \
+        b = 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 = tcg_const_i32(1);                                        \
+        b = tcg_temp_new();                                             \
+        tcg_gen_andi_i32(b, cpu_regs[a->rd], 7);                        \
+        tcg_gen_shl_i32(mask, mask, b);                                 \
+        mem = tcg_temp_new();                                           \
+        addr = 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 = tcg_temp_new();
+    bit = 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 = tcg_temp_new();
+    mem = tcg_temp_new();
+    addr = 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 = 0,
+    PSW_Z = 1,
+    PSW_S = 2,
+    PSW_O = 3,
+    PSW_I = 8,
+    PSW_U = 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 == 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 = 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 = DISAS_UPDATE;
+    }
+    return true;
+}
+
+/* mvtc #imm, rd */
+static bool trans_MVTC_i(DisasContext *ctx, arg_MVTC_i *a)
+{
+    TCGv imm;
+
+    imm = tcg_const_i32(a->imm);
+    move_to_cr(ctx, imm, a->cr);
+    if (a->cr == 0 && is_privileged(ctx, 0)) {
+        ctx->base.is_jmp = 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 == 0 && is_privileged(ctx, 0)) {
+        ctx->base.is_jmp = 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 = 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 = 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 = tcg_temp_new();
+        pop(cpu_pc);
+        pop(psw);
+        gen_helper_set_psw_rte(cpu_env, psw);
+        ctx->base.is_jmp = 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 = DISAS_NORETURN;
+    return true;
+}
+
+/* int #imm */
+static bool trans_INT(DisasContext *ctx, arg_INT *a)
+{
+    TCGv vec;
+
+    tcg_debug_assert(a->imm < 0x100);
+    vec = 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 = 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 *cs)
+{
+    CPURXState *env = cs->env_ptr;
+    DisasContext *ctx = container_of(dcbase, DisasContext, base);
+    ctx->env = env;
+}
+
+static void rx_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
+{
+}
+
+static void rx_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
+{
+    DisasContext *ctx = 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 = 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 = DISAS_NORETURN;
+    ctx->base.pc_next += 1;
+    return true;
+}
+
+static void rx_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
+{
+    DisasContext *ctx = container_of(dcbase, DisasContext, base);
+    uint32_t insn;
+
+    ctx->pc = ctx->base.pc_next;
+    insn = 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 = 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 = {
+    .init_disas_context = rx_tr_init_disas_context,
+    .tb_start           = rx_tr_tb_start,
+    .insn_start         = rx_tr_insn_start,
+    .breakpoint_check   = rx_tr_breakpoint_check,
+    .translate_insn     = rx_tr_translate_insn,
+    .tb_stop            = rx_tr_tb_stop,
+    .disas_log          = rx_tr_disas_log,
+};
+
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
+{
+    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 = data[0];
+}
+
+#define ALLOC_REGISTER(sym, name) \
+    cpu_##sym = tcg_global_mem_new_i32(cpu_env, \
+                                       offsetof(CPURXState, sym), name)
+
+void rx_translate_init(void)
+{
+    static const char * const regnames[NUM_REGS] = {
+        "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
+        "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"
+    };
+    int i;
+
+    for (i = 0; i < NUM_REGS; i++) {
+        cpu_regs[i] = 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 = 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 += translate.o op_helper.o helper.o cpu.o gdbstub.o disas.o
+obj-$(CONFIG_SOFTMMU) += monitor.o
+
+DECODETREE = $(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 <richard.henderson@linaro.org>
+# Copyright (c) 2019 Yoshinori Sato <ysato@users.sourceforge.jp>
+#
+# 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 <http://www.gnu.org/licenses/>.
+#
+
+&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=bdsp_s
+
+@b1_bcnd_s	.... cd:1 ...			&bcnd dsp=%b1_bdsp sz=1
+@b1_bra_s	.... ....			&jdsp dsp=%b1_bdsp sz=1
+
+%b2_r_0		16:4
+%b2_li_2	18:2 !function=li
+%b2_li_8	24:2 !function=li
+%b2_dsp5_3	23:4 19:1
+
+@b2_rds		.... .... .... rd:4		&rr rs=%b2_r_0
+@b2_rds_li	.... .... .... rd:4		&rri rs2=%b2_r_0 imm=%b2_li_8
+@b2_rds_uimm4	.... .... imm:4 rd:4		&rri rs2=%b2_r_0
+@b2_rs2_uimm4	.... .... imm:4 rs2:4		&rri rd=0
+@b2_rds_imm5	.... ... imm:5 rd:4		&rri rs2=%b2_r_0
+@b2_rd_rs_li	.... .... rs2:4 rd:4		&rri imm=%b2_li_8
+@b2_rd_ld_ub	.... .. ld:2 rs:4 rd:4		&rm mi=4
+@b2_ld_imm3	.... .. ld:2 rs:4 . imm:3	&mi mi=4
+@b2_bcnd_b	.... cd:4 dsp:s8		&bcnd sz=2
+@b2_bra_b	.... .... dsp:s8		&jdsp sz=2
+
+########
+
+%b3_r_0		8:4
+%b3_li_10	18:2 !function=li
+%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=%b3_r_0 imm=%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=4
+@b3_rd_ld_ul	.... .... .... .. ld:2 rs:4 rd:4	&rm mi=2
+@b3_rd_rs_rs2	.... .... .... rd:4 rs:4 rs2:4		&rrr
+@b3_rds_imm5	.... .... ....... imm:5 rd:4		&rri rs2=%b3_r_0
+@b3_rd_rs_imm5	.... .... ... imm:5 rs2:4 rd:4		&rri
+@b3_bcnd_w	.... ... cd:1 .... .... .... ....	&bcnd dsp=%b3_bdsp sz=3
+@b3_bra_w	.... .... .... .... .... ....		&jdsp dsp=%b3_bdsp sz=3
+@b3_ld_rd_rs	.... .... .... .. ld:2 rs:4 rd:4	&rm mi=0
+@b3_sz_ld_rd_cd	.... .... .... sz:2 ld:2 rd:4 cd:4	&mcnd
+
+########
+
+%b4_li_18	18:2 !function=li
+%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=%b4_bdsp sz=4
+########
+# 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==2 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=0
+# CMP #imm, rs2
+CMP_ir		0111 01.. 0000 rs2:4			&rri imm=%b2_li_8 rd=0
+# 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=%b2_dsp5_3 sz=0
+# MOV.w rs, dsp5[rd]
+MOV_rm		1001 0 .... rd:3 . rs:3			dsp=%b2_dsp5_3 sz=1
+# MOV.l rs, dsp5[rd]
+MOV_rm		1010 0 .... rd:3 . rs:3			dsp=%b2_dsp5_3 sz=2
+# MOV.b dsp5[rs], rd
+MOV_mr		1000 1 .... rs:3 . rd:3			dsp=%b2_dsp5_3 sz=0
+# MOV.w dsp5[rs], rd
+MOV_mr		1001 1 .... rs:3 . rd:3			dsp=%b2_dsp5_3 sz=1
+# MOV.l dsp5[rs], rd
+MOV_mr		1010 1 .... rs:3 . rd:3			dsp=%b2_dsp5_3 sz=2
+# 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=0 dsp=%b3_dsp5_8
+# MOV.w #imm8, dsp5[rd]
+MOV_im		0011 1101 . rd:3 .... imm:8		sz=1 dsp=%b3_dsp5_8
+# MOV.l #imm8, dsp5[rd]
+MOV_im		0011 1110 . rd:3 .... imm:8		sz=2 dsp=%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=%b2_li_2
+# MOV.<bwl> #imm, [rd]
+MOV_im		1111 1000 rd:4 .. sz:2			dsp=0 imm=%b2_li_2
+# MOV.<bwl> #imm, dsp8[rd]
+MOV_im		1111 1001 rd:4 .. sz:2 dsp:8		imm=%b3_li_10
+# MOV.<bwl> #imm, dsp16[rd]
+MOV_im		1111 1010 rd:4 .. sz:2 .... .... .... .... \
+		imm=%b4_li_18 dsp=%b4_dsp_16
+# MOV.<bwl> [ri,rb], rd
+MOV_ar		1111 1110 01 sz:2 ri:4 rb:4 rd:4
+# MOV.<bwl> rs, [ri,rb]
+MOV_ra		1111 1110 00 sz:2 ri:4 rb:4 rs:4
+# Note ldd=3 and lds=3 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=0
+# 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=1
+# 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=2
+# 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.<bw> dsp5[rs], rd
+MOVU_mr		1011 sz:1 ... . rs:3 . rd:3		dsp=%b2_dsp5_3
+# MOVU.<bw> [rs], rd
+MOVU_mr		0101 1 sz:1 00 rs:4 rd:4		dsp=0
+# MOVU.<bw> dsp8[rs], rd
+MOVU_mr		0101 1 sz:1 01 rs:4 rd:4 dsp:8
+# MOVU.<bw> dsp16[rs], rd
+MOVU_mr		0101 1 sz:1 10 rs:4 rd:4 .... .... .... .... dsp=%b4_dsp_16
+# MOVU.<bw> rs, rd
+MOVU_rr		0101 1 sz:1 11 rs:4 rd:4
+# MOVU.<bw> [ri, rb], rd
+MOVU_ar		1111 1110 110 sz:1 ri:4 rb:4 rd:4
+# MOVU.<bw> [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=%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.<bwl> rs
+{
+  POP		0111 1110 1011 rd:4
+  PUSH_r	0111 1110 10 sz:2 rs:4
+}
+# PUSH.<bwl> 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.<bwl>
+{
+  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==2 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.<bwl>
+{
+  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.<bwl>
+{
+  SCMPU		0111 1111 1000 0011
+  SUNTIL	0111 1111 1000 00 sz:2
+}
+
+# SMOVU
+# SWHILE.<bwl>
+{
+  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
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 05/22] target/rx: TCG helper
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (3 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 04/22] target/rx: TCG translation Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 06/22] target/rx: CPU definition Yoshinori Sato
                   ` (22 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, richard.henderson, Yoshinori Sato, philmd

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>

Message-Id: <20190616142836.10614-3-ysato@users.sourceforge.jp>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20190607091116.49044-3-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
[PMD: Removed tlb_fill, extracted from patch of Yoshinori Sato
 'Convert to CPUClass::tlb_fill']
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
---
 target/rx/helper.h    |  31 +++
 target/rx/helper.c    | 149 +++++++++++++
 target/rx/op_helper.c | 470 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 650 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..a34a40af83
--- /dev/null
+++ b/target/rx/helper.c
@@ -0,0 +1,149 @@
+/*
+ *  RX emulation
+ *
+ *  Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/bitops.h"
+#include "cpu.h"
+#include "exec/log.h"
+#include "exec/cpu_ldst.h"
+#include "sysemu/sysemu.h"
+#include "hw/irq.h"
+
+void rx_cpu_unpack_psw(CPURXState *env, uint32_t psw, int rte)
+{
+    if (env->psw_pm == 0) {
+        env->psw_ipl = FIELD_EX32(psw, PSW, IPL);
+        if (rte) {
+            /* PSW.PM can write RTE and RTFI */
+            env->psw_pm = FIELD_EX32(psw, PSW, PM);
+        }
+        env->psw_u = FIELD_EX32(psw, PSW, U);
+        env->psw_i = FIELD_EX32(psw, PSW, I);
+    }
+    env->psw_o = FIELD_EX32(psw, PSW, O) << 31;
+    env->psw_s = FIELD_EX32(psw, PSW, S) << 31;
+    env->psw_z = 1 - FIELD_EX32(psw, PSW, Z);
+    env->psw_c = FIELD_EX32(psw, PSW, C);
+}
+
+#define INT_FLAGS (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIR)
+void rx_cpu_do_interrupt(CPUState *cs)
+{
+    RXCPU *cpu = RXCPU(cs);
+    CPURXState *env = &cpu->env;
+    int do_irq = cs->interrupt_request & INT_FLAGS;
+    uint32_t save_psw;
+
+    env->in_sleep = 0;
+
+    if (env->psw_u) {
+        env->usp = env->regs[0];
+    } else {
+        env->isp = env->regs[0];
+    }
+    save_psw = rx_cpu_pack_psw(env);
+    env->psw_pm = env->psw_i = env->psw_u = 0;
+
+    if (do_irq) {
+        if (do_irq & CPU_INTERRUPT_FIR) {
+            env->bpc = env->pc;
+            env->bpsw = save_psw;
+            env->pc = env->fintv;
+            env->psw_ipl = 15;
+            cs->interrupt_request &= ~CPU_INTERRUPT_FIR;
+            qemu_set_irq(env->ack, env->ack_irq);
+            qemu_log_mask(CPU_LOG_INT, "fast interrupt raised\n");
+        } else if (do_irq & CPU_INTERRUPT_HARD) {
+            env->isp -= 4;
+            cpu_stl_all(env, env->isp, save_psw);
+            env->isp -= 4;
+            cpu_stl_all(env, env->isp, env->pc);
+            env->pc = cpu_ldl_all(env, env->intb + env->ack_irq * 4);
+            env->psw_ipl = env->ack_ipl;
+            cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
+            qemu_set_irq(env->ack, env->ack_irq);
+            qemu_log_mask(CPU_LOG_INT,
+                          "interrupt 0x%02x raised\n", env->ack_irq);
+        }
+    } else {
+        uint32_t vec = cs->exception_index;
+        const char *expname = "unknown exception";
+
+        env->isp -= 4;
+        cpu_stl_all(env, env->isp, save_psw);
+        env->isp -= 4;
+        cpu_stl_all(env, env->isp, env->pc);
+
+        if (vec < 0x100) {
+            env->pc = cpu_ldl_all(env, 0xffffffc0 + vec * 4);
+        } else {
+            env->pc = cpu_ldl_all(env, env->intb + (vec & 0xff) * 4);
+        }
+        switch (vec) {
+        case 20:
+            expname = "privilege violation";
+            break;
+        case 21:
+            expname = "access exception";
+            break;
+        case 23:
+            expname = "illegal instruction";
+            break;
+        case 25:
+            expname = "fpu exception";
+            break;
+        case 30:
+            expname = "non-maskable interrupt";
+            break;
+        case 0x100 ... 0x1ff:
+            expname = "unconditional trap";
+        }
+        qemu_log_mask(CPU_LOG_INT, "exception 0x%02x [%s] raised\n",
+                      (vec & 0xff), expname);
+    }
+    env->regs[0] = env->isp;
+}
+
+bool rx_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+    RXCPU *cpu = RXCPU(cs);
+    CPURXState *env = &cpu->env;
+    int accept = 0;
+    /* hardware interrupt (Normal) */
+    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
+        env->psw_i && (env->psw_ipl < env->req_ipl)) {
+        env->ack_irq = env->req_irq;
+        env->ack_ipl = env->req_ipl;
+        accept = 1;
+    }
+    /* hardware interrupt (FIR) */
+    if ((interrupt_request & CPU_INTERRUPT_FIR) &&
+        env->psw_i && (env->psw_ipl < 15)) {
+        accept = 1;
+    }
+    if (accept) {
+        rx_cpu_do_interrupt(cs);
+        return true;
+    }
+    return false;
+}
+
+hwaddr rx_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
+{
+    return addr;
+}
diff --git a/target/rx/op_helper.c b/target/rx/op_helper.c
new file mode 100644
index 0000000000..f89d294f2b
--- /dev/null
+++ b/target/rx/op_helper.c
@@ -0,0 +1,470 @@
+/*
+ *  RX helper functions
+ *
+ *  Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/bitops.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "exec/helper-proto.h"
+#include "exec/cpu_ldst.h"
+#include "fpu/softfloat.h"
+
+static inline void QEMU_NORETURN raise_exception(CPURXState *env, int index,
+                                                 uintptr_t retaddr);
+
+static void _set_psw(CPURXState *env, uint32_t psw, uint32_t rte)
+{
+    uint32_t prev_u;
+    prev_u = env->psw_u;
+    rx_cpu_unpack_psw(env, psw, rte);
+    if (prev_u != env->psw_u) {
+        /* switch r0  */
+        if (env->psw_u) {
+            env->isp = env->regs[0];
+            env->regs[0] = env->usp;
+        } else {
+            env->usp = env->regs[0];
+            env->regs[0] = env->isp;
+        }
+    }
+}
+
+void helper_set_psw(CPURXState *env, uint32_t psw)
+{
+    _set_psw(env, psw, 0);
+}
+
+void helper_set_psw_rte(CPURXState *env, uint32_t psw)
+{
+    _set_psw(env, psw, 1);
+}
+
+uint32_t helper_pack_psw(CPURXState *env)
+{
+    return rx_cpu_pack_psw(env);
+}
+
+#define SET_FPSW(b)                                             \
+    do {                                                        \
+        env->fpsw = FIELD_DP32(env->fpsw, FPSW, C ## b, 1);     \
+        if (!FIELD_EX32(env->fpsw, FPSW, E ## b)) {             \
+            env->fpsw = FIELD_DP32(env->fpsw, FPSW, F ## b, 1); \
+        }                                                       \
+    } while (0)
+
+/* fp operations */
+static void update_fpsw(CPURXState *env, float32 ret, uintptr_t retaddr)
+{
+    int xcpt, cause, enable;
+
+    env->psw_z = ret & ~(1 << 31); /* mask sign bit */
+    env->psw_s = ret;
+
+    xcpt = get_float_exception_flags(&env->fp_status);
+
+    /* Clear the cause entries */
+    env->fpsw = FIELD_DP32(env->fpsw, FPSW, CAUSE, 0);
+
+    /* set FPSW */
+    if (unlikely(xcpt)) {
+        if (xcpt & float_flag_invalid) {
+            SET_FPSW(V);
+        }
+        if (xcpt & float_flag_divbyzero) {
+            SET_FPSW(Z);
+        }
+        if (xcpt & float_flag_overflow) {
+            SET_FPSW(O);
+        }
+        if (xcpt & float_flag_underflow) {
+            SET_FPSW(U);
+        }
+        if (xcpt & float_flag_inexact) {
+            SET_FPSW(X);
+        }
+        if ((xcpt & (float_flag_input_denormal
+                     | float_flag_output_denormal))
+            && !FIELD_EX32(env->fpsw, FPSW, DN)) {
+            env->fpsw = FIELD_DP32(env->fpsw, FPSW, CE, 1);
+        }
+
+        /* update FPSW_FLAG_S */
+        if (FIELD_EX32(env->fpsw, FPSW, FLAGS) != 0) {
+            env->fpsw = FIELD_DP32(env->fpsw, FPSW, FS, 1);
+        }
+
+        /* Generate an exception if enabled */
+        cause = FIELD_EX32(env->fpsw, FPSW, CAUSE);
+        enable = FIELD_EX32(env->fpsw, FPSW, ENABLE);
+        enable |= 1 << 5; /* CE always enabled */
+        if (cause & enable) {
+            raise_exception(env, 21, retaddr);
+        }
+    }
+}
+
+void helper_set_fpsw(CPURXState *env, uint32_t val)
+{
+    static const int roundmode[] = {
+        float_round_nearest_even,
+        float_round_to_zero,
+        float_round_up,
+        float_round_down,
+    };
+    uint32_t fpsw = env->fpsw;
+    fpsw |= 0x7fffff03;
+    val &= ~0x80000000;
+    fpsw &= val;
+    FIELD_DP32(fpsw, FPSW, FS, FIELD_EX32(fpsw, FPSW, FLAGS) != 0);
+    env->fpsw = fpsw;
+    set_float_rounding_mode(roundmode[FIELD_EX32(env->fpsw, FPSW, RM)],
+                            &env->fp_status);
+}
+
+#define FLOATOP(op, func)                                           \
+    float32 helper_##op(CPURXState *env, float32 t0, float32 t1)    \
+    {                                                               \
+        float32 ret;                                                \
+        ret = func(t0, t1, &env->fp_status);                        \
+        update_fpsw(env, *(uint32_t *)&ret, GETPC());               \
+        return ret;                                                 \
+    }
+
+FLOATOP(fadd, float32_add)
+FLOATOP(fsub, float32_sub)
+FLOATOP(fmul, float32_mul)
+FLOATOP(fdiv, float32_div)
+
+void helper_fcmp(CPURXState *env, float32 t0, float32 t1)
+{
+    int st;
+    st = float32_compare(t0, t1, &env->fp_status);
+    update_fpsw(env, 0, GETPC());
+    env->psw_z = 1;
+    env->psw_s = env->psw_o = 0;
+    switch (st) {
+    case float_relation_equal:
+        env->psw_z = 0;
+        break;
+    case float_relation_less:
+        env->psw_s = -1;
+        break;
+    case float_relation_unordered:
+        env->psw_o = -1;
+        break;
+    }
+}
+
+uint32_t helper_ftoi(CPURXState *env, float32 t0)
+{
+    uint32_t ret;
+    ret = float32_to_int32_round_to_zero(t0, &env->fp_status);
+    update_fpsw(env, ret, GETPC());
+    return ret;
+}
+
+uint32_t helper_round(CPURXState *env, float32 t0)
+{
+    uint32_t ret;
+    ret = float32_to_int32(t0, &env->fp_status);
+    update_fpsw(env, ret, GETPC());
+    return ret;
+}
+
+float32 helper_itof(CPURXState *env, uint32_t t0)
+{
+    float32 ret;
+    ret = int32_to_float32(t0, &env->fp_status);
+    update_fpsw(env, ret, GETPC());
+    return ret;
+}
+
+/* string operations */
+void helper_scmpu(CPURXState *env)
+{
+    uint8_t tmp0, tmp1;
+    if (env->regs[3] == 0) {
+        return;
+    }
+    while (env->regs[3] != 0) {
+        tmp0 = cpu_ldub_data_ra(env, env->regs[1]++, GETPC());
+        tmp1 = cpu_ldub_data_ra(env, env->regs[2]++, GETPC());
+        env->regs[3]--;
+        if (tmp0 != tmp1 || tmp0 == '\0') {
+            break;
+        }
+    }
+    env->psw_z = tmp0 - tmp1;
+    env->psw_c = (tmp0 >= tmp1);
+}
+
+static uint32_t (* const cpu_ldufn[])(CPUArchState *env,
+                                     target_ulong ptr,
+                                     uintptr_t retaddr) = {
+    cpu_ldub_data_ra, cpu_lduw_data_ra, cpu_ldl_data_ra,
+};
+
+static uint32_t (* const cpu_ldfn[])(CPUArchState *env,
+                                     target_ulong ptr,
+                                     uintptr_t retaddr) = {
+    cpu_ldub_data_ra, cpu_lduw_data_ra, cpu_ldl_data_ra,
+};
+
+static void (* const cpu_stfn[])(CPUArchState *env,
+                                 target_ulong ptr,
+                                 uint32_t val,
+                                 uintptr_t retaddr) = {
+    cpu_stb_data_ra, cpu_stw_data_ra, cpu_stl_data_ra,
+};
+
+void helper_sstr(CPURXState *env, uint32_t sz)
+{
+    tcg_debug_assert(sz < 3);
+    while (env->regs[3] != 0) {
+        cpu_stfn[sz](env, env->regs[1], env->regs[2], GETPC());
+        env->regs[1] += 1 << sz;
+        env->regs[3]--;
+    }
+}
+
+#define OP_SMOVU 1
+#define OP_SMOVF 0
+#define OP_SMOVB 2
+
+static void smov(uint32_t mode, CPURXState *env)
+{
+    uint8_t tmp;
+    int dir;
+
+    dir = (mode & OP_SMOVB) ? -1 : 1;
+    while (env->regs[3] != 0) {
+        tmp = cpu_ldub_data_ra(env, env->regs[2], GETPC());
+        cpu_stb_data_ra(env, env->regs[1], tmp, GETPC());
+        env->regs[1] += dir;
+        env->regs[2] += dir;
+        env->regs[3]--;
+        if ((mode & OP_SMOVU) && tmp == 0) {
+            break;
+        }
+    }
+}
+
+void helper_smovu(CPURXState *env)
+{
+    smov(OP_SMOVU, env);
+}
+
+void helper_smovf(CPURXState *env)
+{
+    smov(OP_SMOVF, env);
+}
+
+void helper_smovb(CPURXState *env)
+{
+    smov(OP_SMOVB, env);
+}
+
+
+void helper_suntil(CPURXState *env, uint32_t sz)
+{
+    uint32_t tmp;
+    tcg_debug_assert(sz < 3);
+    if (env->regs[3] == 0) {
+        return ;
+    }
+    while (env->regs[3] != 0) {
+        tmp = cpu_ldufn[sz](env, env->regs[1], GETPC());
+        env->regs[1] += 1 << sz;
+        env->regs[3]--;
+        if (tmp == env->regs[2]) {
+            break;
+        }
+    }
+    env->psw_z = tmp - env->regs[2];
+    env->psw_c = (tmp <= env->regs[2]);
+}
+
+void helper_swhile(CPURXState *env, uint32_t sz)
+{
+    uint32_t tmp;
+    tcg_debug_assert(sz < 3);
+    if (env->regs[3] == 0) {
+        return ;
+    }
+    while (env->regs[3] != 0) {
+        tmp = cpu_ldufn[sz](env, env->regs[1], GETPC());
+        env->regs[1] += 1 << sz;
+        env->regs[3]--;
+        if (tmp != env->regs[2]) {
+            break;
+        }
+    }
+    env->psw_z = env->regs[3];
+    env->psw_c = (tmp <= env->regs[2]);
+}
+
+/* accumlator operations */
+void helper_rmpa(CPURXState *env, uint32_t sz)
+{
+    uint64_t result_l, prev;
+    int32_t result_h;
+    int64_t tmp0, tmp1;
+
+    if (env->regs[3] == 0) {
+        return;
+    }
+    result_l = env->regs[5];
+    result_l <<= 32;
+    result_l |= env->regs[4];
+    result_h = env->regs[6];
+    env->psw_o = 0;
+
+    while (env->regs[3] != 0) {
+        tmp0 = cpu_ldfn[sz](env, env->regs[1], GETPC());
+        tmp1 = cpu_ldfn[sz](env, env->regs[2], GETPC());
+        tmp0 *= tmp1;
+        prev = result_l;
+        result_l += tmp0;
+        /* carry / bollow */
+        if (tmp0 < 0) {
+            if (prev > result_l) {
+                result_h--;
+            }
+        } else {
+            if (prev < result_l) {
+                result_h++;
+            }
+        }
+
+        env->regs[1] += 1 << sz;
+        env->regs[2] += 1 << sz;
+    }
+    env->psw_s = result_h;
+    env->psw_o = (result_h != 0 && result_h != -1) << 31;
+    env->regs[6] = result_h;
+    env->regs[5] = result_l >> 32;
+    env->regs[4] = result_l & 0xffffffff;
+}
+
+void helper_racw(CPURXState *env, uint32_t imm)
+{
+    int64_t acc;
+    acc = env->acc;
+    acc <<= (imm + 1);
+    acc += 0x0000000080000000LL;
+    if (acc > 0x00007fff00000000LL) {
+        acc = 0x00007fff00000000LL;
+    } else if (acc < -0x800000000000LL) {
+        acc = -0x800000000000LL;
+    } else {
+        acc &= 0xffffffff00000000LL;
+    }
+    env->acc = acc;
+}
+
+void helper_satr(CPURXState *env)
+{
+    if (env->psw_o >> 31) {
+        if ((int)env->psw_s < 0) {
+            env->regs[6] = 0x00000000;
+            env->regs[5] = 0x7fffffff;
+            env->regs[4] = 0xffffffff;
+        } else {
+            env->regs[6] = 0xffffffff;
+            env->regs[5] = 0x80000000;
+            env->regs[4] = 0x00000000;
+        }
+    }
+}
+
+/* div */
+uint32_t helper_div(CPURXState *env, uint32_t num, uint32_t den)
+{
+    uint32_t ret = num;
+    if (!((num == INT_MIN && den == -1) || den == 0)) {
+        ret = (int32_t)num / (int32_t)den;
+        env->psw_o = 0;
+    } else {
+        env->psw_o = -1;
+    }
+    return ret;
+}
+
+uint32_t helper_divu(CPURXState *env, uint32_t num, uint32_t den)
+{
+    uint32_t ret = num;
+    if (den != 0) {
+        ret = num / den;
+        env->psw_o = 0;
+    } else {
+        env->psw_o = -1;
+    }
+    return ret;
+}
+
+/* exception */
+static inline void QEMU_NORETURN raise_exception(CPURXState *env, int index,
+                                                 uintptr_t retaddr)
+{
+    CPUState *cs = env_cpu(env);
+
+    cs->exception_index = index;
+    cpu_loop_exit_restore(cs, retaddr);
+}
+
+void QEMU_NORETURN helper_raise_privilege_violation(CPURXState *env)
+{
+    raise_exception(env, 20, GETPC());
+}
+
+void QEMU_NORETURN helper_raise_access_fault(CPURXState *env)
+{
+    raise_exception(env, 21, GETPC());
+}
+
+void QEMU_NORETURN helper_raise_illegal_instruction(CPURXState *env)
+{
+    raise_exception(env, 23, GETPC());
+}
+
+void QEMU_NORETURN helper_wait(CPURXState *env)
+{
+    CPUState *cs = env_cpu(env);
+
+    cs->halted = 1;
+    env->in_sleep = 1;
+    raise_exception(env, EXCP_HLT, 0);
+}
+
+void QEMU_NORETURN helper_debug(CPURXState *env)
+{
+    CPUState *cs = env_cpu(env);
+
+    cs->exception_index = EXCP_DEBUG;
+    cpu_loop_exit(cs);
+}
+
+void QEMU_NORETURN helper_rxint(CPURXState *env, uint32_t vec)
+{
+    raise_exception(env, 0x100 + vec, 0);
+}
+
+void QEMU_NORETURN helper_rxbrk(CPURXState *env)
+{
+    raise_exception(env, 0x100, 0);
+}
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 06/22] target/rx: CPU definition
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (4 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 05/22] target/rx: TCG helper Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-23 15:49   ` Philippe Mathieu-Daudé
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 07/22] target/rx: RX disassembler Yoshinori Sato
                   ` (21 subsequent siblings)
  27 siblings, 1 reply; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, richard.henderson, Yoshinori Sato, philmd

v21 changes
Add cpu-param.h
Remove CPU_COMMON
rx_load_image move to rx-virt.

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>

Message-Id: <20190616142836.10614-4-ysato@users.sourceforge.jp>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20190607091116.49044-4-ysato@users.sourceforge.jp>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
[PMD: Use newer QOM style, split cpu-qom.h, restrict access to
 extable array, use rx_cpu_tlb_fill() extracted from patch of
 Yoshinori Sato 'Convert to CPUClass::tlb_fill']
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>

cpu.c: remove rx_load_image

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
---
 target/rx/cpu-param.h   |  31 ++++++
 target/rx/cpu-qom.h     |  42 ++++++++
 target/rx/cpu.h         | 181 +++++++++++++++++++++++++++++++++
 target/rx/cpu.c         | 217 ++++++++++++++++++++++++++++++++++++++++
 target/rx/gdbstub.c     | 112 +++++++++++++++++++++
 target/rx/Makefile.objs |   1 -
 6 files changed, 583 insertions(+), 1 deletion(-)
 create mode 100644 target/rx/cpu-param.h
 create mode 100644 target/rx/cpu-qom.h
 create mode 100644 target/rx/cpu.h
 create mode 100644 target/rx/cpu.c
 create mode 100644 target/rx/gdbstub.c

diff --git a/target/rx/cpu-param.h b/target/rx/cpu-param.h
new file mode 100644
index 0000000000..5da87fbebe
--- /dev/null
+++ b/target/rx/cpu-param.h
@@ -0,0 +1,31 @@
+/*
+ *  RX cpu parameters
+ *
+ *  Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef RX_CPU_PARAM_H
+#define RX_CPU_PARAM_H
+
+#define TARGET_LONG_BITS 32
+#define TARGET_PAGE_BITS 12
+
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+
+#define NB_MMU_MODES 1
+#define MMU_MODE0_SUFFIX _all
+
+#endif
diff --git a/target/rx/cpu-qom.h b/target/rx/cpu-qom.h
new file mode 100644
index 0000000000..8328900f3f
--- /dev/null
+++ b/target/rx/cpu-qom.h
@@ -0,0 +1,42 @@
+#ifndef QEMU_RX_CPU_QOM_H
+#define QEMU_RX_CPU_QOM_H
+
+#include "hw/core/cpu.h"
+/*
+ * RX CPU
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ * SPDX-License-Identifier: LGPL-2.0+
+ */
+
+#define TYPE_RX_CPU "rx-cpu"
+
+#define TYPE_RX62N_CPU RX_CPU_TYPE_NAME("rx62n")
+
+#define RXCPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(RXCPUClass, (klass), TYPE_RX_CPU)
+#define RXCPU(obj) \
+    OBJECT_CHECK(RXCPU, (obj), TYPE_RX_CPU)
+#define RXCPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(RXCPUClass, (obj), TYPE_RX_CPU)
+
+/*
+ * RXCPUClass:
+ * @parent_realize: The parent class' realize handler.
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A RX CPU model.
+ */
+typedef struct RXCPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    DeviceRealize parent_realize;
+    void (*parent_reset)(CPUState *cpu);
+
+} RXCPUClass;
+
+#define CPUArchState struct CPURXState
+
+#endif
diff --git a/target/rx/cpu.h b/target/rx/cpu.h
new file mode 100644
index 0000000000..2d1eb7665c
--- /dev/null
+++ b/target/rx/cpu.h
@@ -0,0 +1,181 @@
+/*
+ *  RX emulation definition
+ *
+ *  Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef RX_CPU_H
+#define RX_CPU_H
+
+#include "qemu/bitops.h"
+#include "qemu-common.h"
+#include "hw/registerfields.h"
+#include "cpu-qom.h"
+
+#include "exec/cpu-defs.h"
+
+/* PSW define */
+REG32(PSW, 0)
+FIELD(PSW, C, 0, 1)
+FIELD(PSW, Z, 1, 1)
+FIELD(PSW, S, 2, 1)
+FIELD(PSW, O, 3, 1)
+FIELD(PSW, I, 16, 1)
+FIELD(PSW, U, 17, 1)
+FIELD(PSW, PM, 20, 1)
+FIELD(PSW, IPL, 24, 4)
+
+/* FPSW define */
+REG32(FPSW, 0)
+FIELD(FPSW, RM, 0, 2)
+FIELD(FPSW, CV, 2, 1)
+FIELD(FPSW, CO, 3, 1)
+FIELD(FPSW, CZ, 4, 1)
+FIELD(FPSW, CU, 5, 1)
+FIELD(FPSW, CX, 6, 1)
+FIELD(FPSW, CE, 7, 1)
+FIELD(FPSW, CAUSE, 2, 6)
+FIELD(FPSW, DN, 8, 1)
+FIELD(FPSW, EV, 10, 1)
+FIELD(FPSW, EO, 11, 1)
+FIELD(FPSW, EZ, 12, 1)
+FIELD(FPSW, EU, 13, 1)
+FIELD(FPSW, EX, 14, 1)
+FIELD(FPSW, ENABLE, 10, 5)
+FIELD(FPSW, FV, 26, 1)
+FIELD(FPSW, FO, 27, 1)
+FIELD(FPSW, FZ, 28, 1)
+FIELD(FPSW, FU, 29, 1)
+FIELD(FPSW, FX, 30, 1)
+FIELD(FPSW, FLAGS, 26, 4)
+FIELD(FPSW, FS, 31, 1)
+
+enum {
+    NUM_REGS = 16,
+};
+
+typedef struct CPURXState {
+    /* CPU registers */
+    uint32_t regs[NUM_REGS];    /* general registers */
+    uint32_t psw_o;             /* O bit of status register */
+    uint32_t psw_s;             /* S bit of status register */
+    uint32_t psw_z;             /* Z bit of status register */
+    uint32_t psw_c;             /* C bit of status register */
+    uint32_t psw_u;
+    uint32_t psw_i;
+    uint32_t psw_pm;
+    uint32_t psw_ipl;
+    uint32_t bpsw;              /* backup status */
+    uint32_t bpc;               /* backup pc */
+    uint32_t isp;               /* global base register */
+    uint32_t usp;               /* vector base register */
+    uint32_t pc;                /* program counter */
+    uint32_t intb;              /* interrupt vector */
+    uint32_t fintv;
+    uint32_t fpsw;
+    uint64_t acc;
+
+    /* Fields up to this point are cleared by a CPU reset */
+    struct {} end_reset_fields;
+
+    /* Internal use */
+    uint32_t in_sleep;
+    uint32_t req_irq;           /* Requested interrupt no (hard) */
+    uint32_t req_ipl;           /* Requested interrupt level */
+    uint32_t ack_irq;           /* execute irq */
+    uint32_t ack_ipl;           /* execute ipl */
+    float_status fp_status;
+    qemu_irq ack;               /* Interrupt acknowledge */
+} CPURXState;
+
+/*
+ * RXCPU:
+ * @env: #CPURXState
+ *
+ * A RX CPU
+ */
+struct RXCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUNegativeOffsetState neg;
+    CPURXState env;
+};
+
+typedef struct RXCPU RXCPU;
+typedef RXCPU ArchCPU;
+
+#define ENV_OFFSET offsetof(RXCPU, env)
+
+#define RX_CPU_TYPE_SUFFIX "-" TYPE_RX_CPU
+#define RX_CPU_TYPE_NAME(model) model RX_CPU_TYPE_SUFFIX
+#define CPU_RESOLVING_TYPE TYPE_RX_CPU
+
+extern const char rx_crname[][6];
+
+void rx_cpu_do_interrupt(CPUState *cpu);
+bool rx_cpu_exec_interrupt(CPUState *cpu, int int_req);
+void rx_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
+int rx_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int rx_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+hwaddr rx_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+
+void rx_translate_init(void);
+int cpu_rx_signal_handler(int host_signum, void *pinfo,
+                           void *puc);
+
+void rx_cpu_list(void);
+void rx_cpu_unpack_psw(CPURXState *env, uint32_t psw, int rte);
+
+#define cpu_signal_handler cpu_rx_signal_handler
+#define cpu_list rx_cpu_list
+
+#include "exec/cpu-all.h"
+
+#define CPU_INTERRUPT_SOFT CPU_INTERRUPT_TGT_INT_0
+#define CPU_INTERRUPT_FIR  CPU_INTERRUPT_TGT_INT_1
+
+#define RX_CPU_IRQ 0
+#define RX_CPU_FIR 1
+
+static inline void cpu_get_tb_cpu_state(CPURXState *env, target_ulong *pc,
+                                        target_ulong *cs_base, uint32_t *flags)
+{
+    *pc = env->pc;
+    *cs_base = 0;
+    *flags = FIELD_DP32(0, PSW, PM, env->psw_pm);
+}
+
+static inline int cpu_mmu_index(CPURXState *env, bool ifetch)
+{
+    return 0;
+}
+
+static inline uint32_t rx_cpu_pack_psw(CPURXState *env)
+{
+    uint32_t psw = 0;
+    psw = FIELD_DP32(psw, PSW, IPL, env->psw_ipl);
+    psw = FIELD_DP32(psw, PSW, PM,  env->psw_pm);
+    psw = FIELD_DP32(psw, PSW, U,   env->psw_u);
+    psw = FIELD_DP32(psw, PSW, I,   env->psw_i);
+    psw = FIELD_DP32(psw, PSW, O,   env->psw_o >> 31);
+    psw = FIELD_DP32(psw, PSW, S,   env->psw_s >> 31);
+    psw = FIELD_DP32(psw, PSW, Z,   env->psw_z == 0);
+    psw = FIELD_DP32(psw, PSW, C,   env->psw_c);
+    return psw;
+}
+
+#endif /* RX_CPU_H */
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
new file mode 100644
index 0000000000..ea38639f47
--- /dev/null
+++ b/target/rx/cpu.c
@@ -0,0 +1,217 @@
+/*
+ * QEMU RX CPU
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/qemu-print.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "qemu-common.h"
+#include "migration/vmstate.h"
+#include "exec/exec-all.h"
+#include "hw/loader.h"
+#include "fpu/softfloat.h"
+
+static void rx_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    RXCPU *cpu = RXCPU(cs);
+
+    cpu->env.pc = value;
+}
+
+static void rx_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
+{
+    RXCPU *cpu = RXCPU(cs);
+
+    cpu->env.pc = tb->pc;
+}
+
+static bool rx_cpu_has_work(CPUState *cs)
+{
+    return cs->interrupt_request &
+        (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIR);
+}
+
+static void rx_cpu_reset(CPUState *s)
+{
+    RXCPU *cpu = RXCPU(s);
+    RXCPUClass *rcc = RXCPU_GET_CLASS(cpu);
+    CPURXState *env = &cpu->env;
+    uint32_t *resetvec;
+
+    rcc->parent_reset(s);
+
+    memset(env, 0, offsetof(CPURXState, end_reset_fields));
+
+    resetvec = rom_ptr(0xfffffffc, 4);
+    if (resetvec) {
+        /* In the case of kernel, it is ignored because it is not set. */
+        env->pc = ldl_p(resetvec);
+    }
+    rx_cpu_unpack_psw(env, 0, 1);
+    env->regs[0] = env->isp = env->usp = 0;
+    env->fpsw = 0;
+    set_flush_to_zero(1, &env->fp_status);
+    set_flush_inputs_to_zero(1, &env->fp_status);
+}
+
+static void rx_cpu_list_entry(gpointer data, gpointer user_data)
+{
+    const char *typename = object_class_get_name(OBJECT_CLASS(data));
+
+    qemu_printf("%s\n", typename);
+}
+
+void rx_cpu_list(void)
+{
+    GSList *list;
+    list = object_class_get_list_sorted(TYPE_RX_CPU, false);
+    g_slist_foreach(list, rx_cpu_list_entry, NULL);
+    g_slist_free(list);
+}
+
+static ObjectClass *rx_cpu_class_by_name(const char *cpu_model)
+{
+    ObjectClass *oc;
+
+    oc = object_class_by_name(cpu_model);
+    if (object_class_dynamic_cast(oc, TYPE_RX_CPU) == NULL ||
+        object_class_is_abstract(oc)) {
+        oc = NULL;
+    }
+
+    return oc;
+}
+
+static void rx_cpu_realize(DeviceState *dev, Error **errp)
+{
+    CPUState *cs = CPU(dev);
+    RXCPUClass *rcc = RXCPU_GET_CLASS(dev);
+    Error *local_err = NULL;
+
+    cpu_exec_realizefn(cs, &local_err);
+    if (local_err != NULL) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    cpu_reset(cs);
+    qemu_init_vcpu(cs);
+
+    rcc->parent_realize(dev, errp);
+}
+
+static void rx_cpu_set_irq(void *opaque, int no, int request)
+{
+    RXCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
+    int irq = request & 0xff;
+
+    static const int mask[] = {
+        [RX_CPU_IRQ] = CPU_INTERRUPT_HARD,
+        [RX_CPU_FIR] = CPU_INTERRUPT_FIR,
+    };
+    if (irq) {
+        cpu->env.req_irq = irq;
+        cpu->env.req_ipl = (request >> 8) & 0x0f;
+        cpu_interrupt(cs, mask[no]);
+    } else {
+        cpu_reset_interrupt(cs, mask[no]);
+    }
+}
+
+static void rx_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
+{
+    info->mach = bfd_mach_rx;
+    info->print_insn = print_insn_rx;
+}
+
+static bool rx_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
+                            MMUAccessType access_type, int mmu_idx,
+                            bool probe, uintptr_t retaddr)
+{
+    uint32_t address, physical, prot;
+
+    /* Linear mapping */
+    address = physical = addr & TARGET_PAGE_MASK;
+    prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+    tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE);
+    return true;
+}
+
+static void rx_cpu_init(Object *obj)
+{
+    CPUState *cs = CPU(obj);
+    RXCPU *cpu = RXCPU(obj);
+    CPURXState *env = &cpu->env;
+
+    cpu_set_cpustate_pointers(cpu);
+    cs->env_ptr = env;
+    qdev_init_gpio_in(DEVICE(cpu), rx_cpu_set_irq, 2);
+}
+
+static void rx_cpu_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    CPUClass *cc = CPU_CLASS(klass);
+    RXCPUClass *rcc = RXCPU_CLASS(klass);
+
+    device_class_set_parent_realize(dc, rx_cpu_realize,
+                                    &rcc->parent_realize);
+
+    rcc->parent_reset = cc->reset;
+    cc->reset = rx_cpu_reset;
+
+    cc->class_by_name = rx_cpu_class_by_name;
+    cc->has_work = rx_cpu_has_work;
+    cc->do_interrupt = rx_cpu_do_interrupt;
+    cc->cpu_exec_interrupt = rx_cpu_exec_interrupt;
+    cc->dump_state = rx_cpu_dump_state;
+    cc->set_pc = rx_cpu_set_pc;
+    cc->synchronize_from_tb = rx_cpu_synchronize_from_tb;
+    cc->gdb_read_register = rx_cpu_gdb_read_register;
+    cc->gdb_write_register = rx_cpu_gdb_write_register;
+    cc->get_phys_page_debug = rx_cpu_get_phys_page_debug;
+    cc->disas_set_info = rx_cpu_disas_set_info;
+    cc->tcg_initialize = rx_translate_init;
+    cc->tlb_fill = rx_cpu_tlb_fill;
+
+    cc->gdb_num_core_regs = 26;
+}
+
+static const TypeInfo rx_cpu_info = {
+    .name = TYPE_RX_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(RXCPU),
+    .instance_init = rx_cpu_init,
+    .abstract = true,
+    .class_size = sizeof(RXCPUClass),
+    .class_init = rx_cpu_class_init,
+};
+
+static const TypeInfo rx62n_rx_cpu_info = {
+    .name = TYPE_RX62N_CPU,
+    .parent = TYPE_RX_CPU,
+};
+
+static void rx_cpu_register_types(void)
+{
+    type_register_static(&rx_cpu_info);
+    type_register_static(&rx62n_rx_cpu_info);
+}
+
+type_init(rx_cpu_register_types)
diff --git a/target/rx/gdbstub.c b/target/rx/gdbstub.c
new file mode 100644
index 0000000000..d76ca52e82
--- /dev/null
+++ b/target/rx/gdbstub.c
@@ -0,0 +1,112 @@
+/*
+ * RX gdb server stub
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "exec/gdbstub.h"
+
+int rx_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+    RXCPU *cpu = RXCPU(cs);
+    CPURXState *env = &cpu->env;
+
+    switch (n) {
+    case 0 ... 15:
+        return gdb_get_regl(mem_buf, env->regs[n]);
+    case 16:
+        return gdb_get_regl(mem_buf, (env->psw_u) ? env->regs[0] : env->usp);
+    case 17:
+        return gdb_get_regl(mem_buf, (!env->psw_u) ? env->regs[0] : env->isp);
+    case 18:
+        return gdb_get_regl(mem_buf, rx_cpu_pack_psw(env));
+    case 19:
+        return gdb_get_regl(mem_buf, env->pc);
+    case 20:
+        return gdb_get_regl(mem_buf, env->intb);
+    case 21:
+        return gdb_get_regl(mem_buf, env->bpsw);
+    case 22:
+        return gdb_get_regl(mem_buf, env->bpc);
+    case 23:
+        return gdb_get_regl(mem_buf, env->fintv);
+    case 24:
+        return gdb_get_regl(mem_buf, env->fpsw);
+    case 25:
+        return 0;
+    }
+    return 0;
+}
+
+int rx_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+    RXCPU *cpu = RXCPU(cs);
+    CPURXState *env = &cpu->env;
+    uint32_t psw;
+    switch (n) {
+    case 0 ... 15:
+        env->regs[n] = ldl_p(mem_buf);
+        if (n == 0) {
+            if (env->psw_u) {
+                env->usp = env->regs[0];
+            } else {
+                env->isp = env->regs[0];
+            }
+        }
+        break;
+    case 16:
+        env->usp = ldl_p(mem_buf);
+        if (env->psw_u) {
+            env->regs[0] = ldl_p(mem_buf);
+        }
+        break;
+    case 17:
+        env->isp = ldl_p(mem_buf);
+        if (!env->psw_u) {
+            env->regs[0] = ldl_p(mem_buf);
+        }
+        break;
+    case 18:
+        psw = ldl_p(mem_buf);
+        rx_cpu_unpack_psw(env, psw, 1);
+        break;
+    case 19:
+        env->pc = ldl_p(mem_buf);
+        break;
+    case 20:
+        env->intb = ldl_p(mem_buf);
+        break;
+    case 21:
+        env->bpsw = ldl_p(mem_buf);
+        break;
+    case 22:
+        env->bpc = ldl_p(mem_buf);
+        break;
+    case 23:
+        env->fintv = ldl_p(mem_buf);
+        break;
+    case 24:
+        env->fpsw = ldl_p(mem_buf);
+        break;
+    case 25:
+        return 8;
+    default:
+        return 0;
+    }
+
+    return 4;
+}
diff --git a/target/rx/Makefile.objs b/target/rx/Makefile.objs
index aa6f2d2d6c..a0018d5bc5 100644
--- a/target/rx/Makefile.objs
+++ b/target/rx/Makefile.objs
@@ -1,5 +1,4 @@
 obj-y += translate.o op_helper.o helper.o cpu.o gdbstub.o disas.o
-obj-$(CONFIG_SOFTMMU) += monitor.o
 
 DECODETREE = $(SRC_PATH)/scripts/decodetree.py
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 07/22] target/rx: RX disassembler
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (5 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 06/22] target/rx: CPU definition Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 08/22] target/rx: Disassemble rx_index_addr into a string Yoshinori Sato
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, richard.henderson, Yoshinori Sato, philmd

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20190607091116.49044-5-ysato@users.sourceforge.jp>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/disas/dis-asm.h |    5 +
 target/rx/disas.c       | 1480 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 1485 insertions(+)
 create mode 100644 target/rx/disas.c

diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index e9c7dd8eb4..a900bd0a27 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -226,6 +226,10 @@ enum bfd_architecture
 #define bfd_mach_nios2r2        2
   bfd_arch_lm32,       /* Lattice Mico32 */
 #define bfd_mach_lm32 1
+  bfd_arch_rx,       /* Renesas RX */
+#define bfd_mach_rx            0x75
+#define bfd_mach_rx_v2         0x76
+#define bfd_mach_rx_v3         0x77
   bfd_arch_last
   };
 #define bfd_mach_s390_31 31
@@ -433,6 +437,7 @@ int print_insn_little_nios2     (bfd_vma, disassemble_info*);
 int print_insn_xtensa           (bfd_vma, disassemble_info*);
 int print_insn_riscv32          (bfd_vma, disassemble_info*);
 int print_insn_riscv64          (bfd_vma, disassemble_info*);
+int print_insn_rx(bfd_vma, disassemble_info *);
 
 #if 0
 /* Fetch the disassembler for a given BFD, if that support is available.  */
diff --git a/target/rx/disas.c b/target/rx/disas.c
new file mode 100644
index 0000000000..8cada4825d
--- /dev/null
+++ b/target/rx/disas.c
@@ -0,0 +1,1480 @@
+/*
+ * Renesas RX Disassembler
+ *
+ * Copyright (c) 2019 Yoshinori Sato <ysato@users.sourceforge.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "disas/dis-asm.h"
+#include "qemu/bitops.h"
+#include "cpu.h"
+
+typedef struct DisasContext {
+    disassemble_info *dis;
+    uint32_t addr;
+    uint32_t pc;
+} DisasContext;
+
+
+static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn,
+                           int i, int n)
+{
+    bfd_byte buf;
+    while (++i <= n) {
+        ctx->dis->read_memory_func(ctx->addr++, &buf, 1, ctx->dis);
+        insn |= buf << (32 - i * 8);
+    }
+    return insn;
+}
+
+static int32_t li(DisasContext *ctx, int sz)
+{
+    int32_t addr;
+    bfd_byte buf[4];
+    addr = ctx->addr;
+
+    switch (sz) {
+    case 1:
+        ctx->addr += 1;
+        ctx->dis->read_memory_func(addr, buf, 1, ctx->dis);
+        return (int8_t)buf[0];
+    case 2:
+        ctx->addr += 2;
+        ctx->dis->read_memory_func(addr, buf, 2, ctx->dis);
+        return ldsw_le_p(buf);
+    case 3:
+        ctx->addr += 3;
+        ctx->dis->read_memory_func(addr, buf, 3, ctx->dis);
+        return (int8_t)buf[2] << 16 | lduw_le_p(buf);
+    case 0:
+        ctx->addr += 4;
+        ctx->dis->read_memory_func(addr, buf, 4, ctx->dis);
+        return ldl_le_p(buf);
+    default:
+        g_assert_not_reached();
+    }
+}
+
+static int bdsp_s(DisasContext *ctx, int d)
+{
+    /*
+     * 0 -> 8
+     * 1 -> 9
+     * 2 -> 10
+     * 3 -> 3
+     * :
+     * 7 -> 7
+     */
+    if (d < 3) {
+        d += 8;
+    }
+    return d;
+}
+
+/* Include the auto-generated decoder.  */
+#include "decode.inc.c"
+
+#define prt(...) (ctx->dis->fprintf_func)((ctx->dis->stream), __VA_ARGS__)
+
+#define RX_MEMORY_BYTE 0
+#define RX_MEMORY_WORD 1
+#define RX_MEMORY_LONG 2
+
+#define RX_IM_BYTE 0
+#define RX_IM_WORD 1
+#define RX_IM_LONG 2
+#define RX_IM_UWORD 3
+
+static const char size[] = {'b', 'w', 'l'};
+static const char cond[][4] = {
+    "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n",
+    "ge", "lt", "gt", "le", "o", "no", "ra", "f"
+};
+static const char psw[] = {
+    'c', 'z', 's', 'o', 0, 0, 0, 0,
+    'i', 'u', 0, 0, 0, 0, 0, 0,
+};
+
+static uint32_t rx_index_addr(int ld, int size, DisasContext *ctx)
+{
+    bfd_byte buf[2];
+    switch (ld) {
+    case 0:
+        return 0;
+    case 1:
+        ctx->dis->read_memory_func(ctx->addr, buf, 1, ctx->dis);
+        ctx->addr += 1;
+        return ((uint8_t)buf[0]) << size;
+    case 2:
+        ctx->dis->read_memory_func(ctx->addr, buf, 2, ctx->dis);
+        ctx->addr += 2;
+        return lduw_le_p(buf) << size;
+    }
+    g_assert_not_reached();
+}
+
+static void operand(DisasContext *ctx, int ld, int mi, int rs, int rd)
+{
+    int dsp;
+    static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"};
+    if (ld < 3) {
+        switch (mi) {
+        case 4:
+            /* dsp[rs].ub */
+            dsp = rx_index_addr(ld, RX_MEMORY_BYTE, ctx);
+            break;
+        case 3:
+            /* dsp[rs].uw */
+            dsp = rx_index_addr(ld, RX_MEMORY_WORD, ctx);
+            break;
+        default:
+            /* dsp[rs].b */
+            /* dsp[rs].w */
+            /* dsp[rs].l */
+            dsp = rx_index_addr(ld, mi, ctx);
+            break;
+        }
+        if (dsp > 0) {
+            prt("%d", dsp);
+        }
+        prt("[r%d]%s", rs, sizes[mi]);
+    } else {
+        prt("r%d", rs);
+    }
+    prt(", r%d", rd);
+}
+
+static void prt_ir(DisasContext *ctx, const char *insn, int imm, int rd)
+{
+    if (imm < 0x100) {
+        prt("%s\t#%d, r%d", insn, imm, rd);
+    } else {
+        prt("%s\t#0x%08x, r%d", insn, imm, rd);
+    }
+}
+
+/* mov.[bwl] rs,dsp:[rd] */
+static bool trans_MOV_rm(DisasContext *ctx, arg_MOV_rm *a)
+{
+    if (a->dsp > 0) {
+        prt("mov.%c\tr%d,%d[r%d]",
+            size[a->sz], a->rs, a->dsp << a->sz, a->rd);
+    } else {
+        prt("mov.%c\tr%d,[r%d]",
+            size[a->sz], a->rs, a->rd);
+    }
+    return true;
+}
+
+/* mov.[bwl] dsp:[rs],rd */
+static bool trans_MOV_mr(DisasContext *ctx, arg_MOV_mr *a)
+{
+    if (a->dsp > 0) {
+        prt("mov.%c\t%d[r%d], r%d",
+            size[a->sz], a->dsp << a->sz, a->rs, a->rd);
+    } else {
+        prt("mov.%c\t[r%d], r%d",
+            size[a->sz], a->rs, a->rd);
+    }
+    return true;
+}
+
+/* mov.l #uimm4,rd */
+/* mov.l #uimm8,rd */
+/* mov.l #imm,rd */
+static bool trans_MOV_ir(DisasContext *ctx, arg_MOV_ir *a)
+{
+    prt_ir(ctx, "mov.l", a->imm, a->rd);
+    return true;
+}
+
+/* mov.[bwl] #uimm8,dsp:[rd] */
+/* mov #imm, dsp:[rd] */
+static bool trans_MOV_im(DisasContext *ctx, arg_MOV_im *a)
+{
+    if (a->dsp > 0) {
+        prt("mov.%c\t#%d,%d[r%d]",
+            size[a->sz], a->imm, a->dsp << a->sz, a->rd);
+    } else {
+        prt("mov.%c\t#%d,[r%d]",
+            size[a->sz], a->imm, a->rd);
+    }
+    return true;
+}
+
+/* mov.[bwl] [ri,rb],rd */
+static bool trans_MOV_ar(DisasContext *ctx, arg_MOV_ar *a)
+{
+    prt("mov.%c\t[r%d,r%d], r%d", size[a->sz], a->ri, a->rb, a->rd);
+    return true;
+}
+
+/* mov.[bwl] rd,[ri,rb] */
+static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a)
+{
+    prt("mov.%c\tr%d, [r%d, r%d]", size[a->sz], a->rs, a->ri, a->rb);
+    return true;
+}
+
+
+/* mov.[bwl] dsp:[rs],dsp:[rd] */
+/* mov.[bwl] rs,dsp:[rd] */
+/* mov.[bwl] dsp:[rs],rd */
+/* mov.[bwl] rs,rd */
+static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a)
+{
+    int dsp;
+
+    prt("mov.%c\t", size[a->sz]);
+    if (a->lds == 3 && a->ldd == 3) {
+        /* mov.[bwl] rs,rd */
+        prt("r%d, r%d", a->rs, a->rd);
+        return true;
+    }
+    if (a->lds == 3) {
+        prt("r%d, ", a->rd);
+        dsp = rx_index_addr(a->ldd, a->sz, ctx);
+        if (dsp > 0) {
+            prt("%d", dsp);
+        }
+        prt("[r%d]", a->rs);
+    } else if (a->ldd == 3) {
+        dsp = rx_index_addr(a->lds, a->sz, ctx);
+        if (dsp > 0) {
+            prt("%d", dsp);
+        }
+        prt("[r%d], r%d", a->rs, a->rd);
+    } else {
+        dsp = rx_index_addr(a->lds, a->sz, ctx);
+        if (dsp > 0) {
+            prt("%d", dsp);
+        }
+        prt("[r%d], ", a->rs);
+        dsp = rx_index_addr(a->ldd, a->sz, ctx);
+        if (dsp > 0) {
+            prt("%d", dsp);
+        }
+        prt("[r%d]", a->rd);
+    }
+    return true;
+}
+
+/* mov.[bwl] rs,[rd+] */
+/* mov.[bwl] rs,[-rd] */
+static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a)
+{
+    prt("mov.%c\tr%d, ", size[a->sz], a->rs);
+    prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd);
+    return true;
+}
+
+/* mov.[bwl] [rd+],rs */
+/* mov.[bwl] [-rd],rs */
+static bool trans_MOV_pr(DisasContext *ctx, arg_MOV_pr *a)
+{
+    prt("mov.%c\t", size[a->sz]);
+    prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd);
+    prt(", r%d", a->rs);
+    return true;
+}
+
+/* movu.[bw] dsp5:[rs],rd */
+static bool trans_MOVU_mr(DisasContext *ctx, arg_MOVU_mr *a)
+{
+    if (a->dsp > 0) {
+        prt("movu.%c\t%d[r%d], r%d", size[a->sz],
+            a->dsp << a->sz, a->rs, a->rd);
+    } else {
+        prt("movu.%c\t[r%d], r%d", size[a->sz], a->rs, a->rd);
+    }
+    return true;
+}
+
+/* movu.[bw] rs,rd */
+static bool trans_MOVU_rr(DisasContext *ctx, arg_MOVU_rr *a)
+{
+    prt("movu.%c\tr%d, r%d", size[a->sz], a->rs, a->rd);
+    return true;
+}
+
+/* movu.[bw] [ri,rb],rd */
+static bool trans_MOVU_ar(DisasContext *ctx, arg_MOVU_ar *a)
+{
+    prt("mov.%c\t[r%d,r%d], r%d", size[a->sz], a->ri, a->rb, a->rd);
+    return true;
+}
+
+/* movu.[bw] [rs+],rd */
+/* movu.[bw] [-rs],rd */
+static bool trans_MOVU_pr(DisasContext *ctx, arg_MOVU_pr *a)
+{
+    prt("movu.%c\t", size[a->sz]);
+    prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd);
+    prt(", r%d", a->rs);
+    return true;
+}
+
+/* pop rd */
+static bool trans_POP(DisasContext *ctx, arg_POP *a)
+{
+    prt("pop\tr%d", a->rd);
+    return true;
+}
+
+/* popc rx */
+static bool trans_POPC(DisasContext *ctx, arg_POPC *a)
+{
+    prt("pop\tr%s", rx_crname[a->cr]);
+    return true;
+}
+
+/* popm rd-rd2 */
+static bool trans_POPM(DisasContext *ctx, arg_POPM *a)
+{
+    prt("popm\tr%d-r%d", a->rd, a->rd2);
+    return true;
+}
+
+/* push rs */
+static bool trans_PUSH_r(DisasContext *ctx, arg_PUSH_r *a)
+{
+    prt("push\tr%d", a->rs);
+    return true;
+}
+
+/* push dsp[rs] */
+static bool trans_PUSH_m(DisasContext *ctx, arg_PUSH_m *a)
+{
+    prt("push\t");
+    int dsp = rx_index_addr(a->ld, a->sz, ctx);
+    if (dsp > 0) {
+        prt("%d", dsp);
+    }
+    prt("[r%d]", a->rs);
+    return true;
+}
+
+/* pushc rx */
+static bool trans_PUSHC(DisasContext *ctx, arg_PUSHC *a)
+{
+    prt("push\t%s", rx_crname[a->cr]);
+    return true;
+}
+
+/* pushm rs-rs2*/
+static bool trans_PUSHM(DisasContext *ctx, arg_PUSHM *a)
+{
+    prt("pushm\tr%d-r%d", a->rs, a->rs2);
+    return true;
+}
+
+/* xchg rs,rd */
+static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr *a)
+{
+    prt("xchg\tr%d, r%d", a->rs, a->rd);
+    return true;
+}
+/* xchg dsp[rs].<mi>,rd */
+static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a)
+{
+    int dsp;
+    static const char msize[][4] = {
+        "b", "w", "l", "ub", "uw",
+    };
+
+    prt("xchg\t");
+    dsp = rx_index_addr(a->ld, a->mi, ctx);
+    if (dsp > 0) {
+        prt("%d", dsp);
+    }
+    prt("[r%d].%s, r%d", a->rs, msize[a->mi], a->rd);
+    return true;
+}
+
+/* stz #imm,rd */
+static bool trans_STZ(DisasContext *ctx, arg_STZ *a)
+{
+    prt_ir(ctx, "stz", a->imm, a->rd);
+    return true;
+}
+
+/* stnz #imm,rd */
+static bool trans_STNZ(DisasContext *ctx, arg_STNZ *a)
+{
+    prt_ir(ctx, "stnz", a->imm, a->rd);
+    return true;
+}
+
+/* rtsd #imm */
+static bool trans_RTSD_i(DisasContext *ctx, arg_RTSD_i *a)
+{
+    prt("rtsd\t#%d", a->imm << 2);
+    return true;
+}
+
+/* rtsd #imm, rd-rd2 */
+static bool trans_RTSD_irr(DisasContext *ctx, arg_RTSD_irr *a)
+{
+    prt("rtsd\t#%d, r%d - r%d", a->imm << 2, a->rd, a->rd2);
+    return true;
+}
+
+/* and #uimm:4, rd */
+/* and #imm, rd */
+static bool trans_AND_ir(DisasContext *ctx, arg_AND_ir *a)
+{
+    prt_ir(ctx, "and", a->imm, a->rd);
+    return true;
+}
+
+/* and dsp[rs], rd */
+/* and rs,rd */
+static bool trans_AND_mr(DisasContext *ctx, arg_AND_mr *a)
+{
+    prt("and\t");
+    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    return true;
+}
+
+/* and rs,rs2,rd */
+static bool trans_AND_rrr(DisasContext *ctx, arg_AND_rrr *a)
+{
+    prt("and\tr%d,r%d, r%d", a->rs, a->rs2, a->rd);
+    return true;
+}
+
+/* or #uimm:4, rd */
+/* or #imm, rd */
+static bool trans_OR_ir(DisasContext *ctx, arg_OR_ir *a)
+{
+    prt_ir(ctx, "or", a->imm, a->rd);
+    return true;
+}
+
+/* or dsp[rs], rd */
+/* or rs,rd */
+static bool trans_OR_mr(DisasContext *ctx, arg_OR_mr *a)
+{
+    prt("or\t");
+    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    return true;
+}
+
+/* or rs,rs2,rd */
+static bool trans_OR_rrr(DisasContext *ctx, arg_OR_rrr *a)
+{
+    prt("or\tr%d, r%d, r%d", a->rs, a->rs2, a->rd);
+    return true;
+}
+
+/* xor #imm, rd */
+static bool trans_XOR_ir(DisasContext *ctx, arg_XOR_ir *a)
+{
+    prt_ir(ctx, "xor", a->imm, a->rd);
+    return true;
+}
+
+/* xor dsp[rs], rd */
+/* xor rs,rd */
+static bool trans_XOR_mr(DisasContext *ctx, arg_XOR_mr *a)
+{
+    prt("xor\t");
+    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    return true;
+}
+
+/* tst #imm, rd */
+static bool trans_TST_ir(DisasContext *ctx, arg_TST_ir *a)
+{
+    prt_ir(ctx, "tst", a->imm, a->rd);
+    return true;
+}
+
+/* tst dsp[rs], rd */
+/* tst rs, rd */
+static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *a)
+{
+    prt("tst\t");
+    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    return true;
+}
+
+/* not rd */
+/* not rs, rd */
+static bool trans_NOT_rr(DisasContext *ctx, arg_NOT_rr *a)
+{
+    prt("not\t");
+    if (a->rs != a->rd) {
+        prt("r%d, ", a->rs);
+    }
+    prt("r%d", a->rd);
+    return true;
+}
+
+/* neg rd */
+/* neg rs, rd */
+static bool trans_NEG_rr(DisasContext *ctx, arg_NEG_rr *a)
+{
+    prt("neg\t");
+    if (a->rs != a->rd) {
+        prt("r%d, ", a->rs);
+    }
+    prt("r%d", a->rd);
+    return true;
+}
+
+/* adc #imm, rd */
+static bool trans_ADC_ir(DisasContext *ctx, arg_ADC_ir *a)
+{
+    prt_ir(ctx, "adc", a->imm, a->rd);
+    return true;
+}
+
+/* adc rs, rd */
+static bool trans_ADC_rr(DisasContext *ctx, arg_ADC_rr *a)
+{
+    prt("adc\tr%d, r%d", a->rs, a->rd);
+    return true;
+}
+
+/* adc dsp[rs], rd */
+static bool trans_ADC_mr(DisasContext *ctx, arg_ADC_mr *a)
+{
+    int dsp;
+    prt("adc\t");
+    dsp = rx_index_addr(a->ld, 2, ctx);
+    if (dsp > 0) {
+        prt("%d", dsp);
+    }
+    prt("[r%d], r%d", a->rs, a->rd);
+    return true;
+}
+
+/* add #uimm4, rd */
+/* add #imm, rs, rd */
+static bool trans_ADD_irr(DisasContext *ctx, arg_ADD_irr *a)
+{
+    if (a->imm < 0x10 && a->rs2 == a->rd) {
+        prt("add\t#%d, r%d", a->imm, a->rd);
+    } else {
+        prt("add\t#0x%08x, r%d, r%d", a->imm, a->rs2, a->rd);
+    }
+    return true;
+}
+
+/* add rs, rd */
+/* add dsp[rs], rd */
+static bool trans_ADD_mr(DisasContext *ctx, arg_ADD_mr *a)
+{
+    prt("add\t");
+    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    return true;
+}
+
+/* add rs, rs2, rd */
+static bool trans_ADD_rrr(DisasContext *ctx, arg_ADD_rrr *a)
+{
+    prt("add\tr%d, r%d, r%d", a->rs, a->rs2, a->rd);
+    return true;
+}
+
+/* cmp #imm4, rd */
+/* cmp #imm8, rd */
+/* cmp #imm, rs2 */
+static bool trans_CMP_ir(DisasContext *ctx, arg_CMP_ir *a)
+{
+    prt_ir(ctx, "cmp", a->imm, a->rs2);
+    return true;
+}
+
+/* cmp rs, rs2 */
+/* cmp dsp[rs], rs2 */
+static bool trans_CMP_mr(DisasContext *ctx, arg_CMP_mr *a)
+{
+    prt("cmp\t");
+    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    return true;
+}
+
+/* sub #imm4, rd */
+static bool trans_SUB_ir(DisasContext *ctx, arg_SUB_ir *a)
+{
+    prt("sub\t#%d, r%d", a->imm, a->rd);
+    return true;
+}
+
+/* sub rs, rd */
+/* sub dsp[rs], rd */
+static bool trans_SUB_mr(DisasContext *ctx, arg_SUB_mr *a)
+{
+    prt("sub\t");
+    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    return true;
+}
+
+/* sub rs, rs2, rd */
+static bool trans_SUB_rrr(DisasContext *ctx, arg_SUB_rrr *a)
+{
+    prt("sub\tr%d, r%d, r%d", a->rs, a->rs2, a->rd);
+    return true;
+}
+
+/* sbb rs, rd */
+static bool trans_SBB_rr(DisasContext *ctx, arg_SBB_rr *a)
+{
+    prt("sbb\tr%d, r%d", a->rs, a->rd);
+    return true;
+}
+
+/* sbb dsp[rs], rd */
+static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a)
+{
+    prt("sbb\t");
+    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    return true;
+}
+
+/* abs rd */
+/* abs rs, rd */
+static bool trans_ABS_rr(DisasContext *ctx, arg_ABS_rr *a)
+{
+    prt("abs\t");
+    if (a->rs == a->rd) {
+        prt("r%d", a->rd);
+    } else {
+        prt("r%d, r%d", a->rs, a->rd);
+    }
+    return true;
+}
+
+/* max #imm, rd */
+static bool trans_MAX_ir(DisasContext *ctx, arg_MAX_ir *a)
+{
+    prt_ir(ctx, "max", a->imm, a->rd);
+    return true;
+}
+
+/* max rs, rd */
+/* max dsp[rs], rd */
+static bool trans_MAX_mr(DisasContext *ctx, arg_MAX_mr *a)
+{
+    prt("max\t");
+    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    return true;
+}
+
+/* min #imm, rd */
+static bool trans_MIN_ir(DisasContext *ctx, arg_MIN_ir *a)
+{
+    prt_ir(ctx, "min", a->imm, a->rd);
+    return true;
+}
+
+/* min rs, rd */
+/* min dsp[rs], rd */
+static bool trans_MIN_mr(DisasContext *ctx, arg_MIN_mr *a)
+{
+    prt("max\t");
+    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    return true;
+}
+
+/* mul #uimm4, rd */
+/* mul #imm, rd */
+static bool trans_MUL_ir(DisasContext *ctx, arg_MUL_ir *a)
+{
+    prt_ir(ctx, "mul", a->imm, a->rd);
+    return true;
+}
+
+/* mul rs, rd */
+/* mul dsp[rs], rd */
+static bool trans_MUL_mr(DisasContext *ctx, arg_MUL_mr *a)
+{
+    prt("mul\t");
+    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    return true;
+}
+
+/* mul rs, rs2, rd */
+static bool trans_MUL_rrr(DisasContext *ctx, arg_MUL_rrr *a)
+{
+    prt("mul\tr%d,r%d,r%d", a->rs, a->rs2, a->rd);
+    return true;
+}
+
+/* emul #imm, rd */
+static bool trans_EMUL_ir(DisasContext *ctx, arg_EMUL_ir *a)
+{
+    prt_ir(ctx, "emul", a->imm, a->rd);
+    return true;
+}
+
+/* emul rs, rd */
+/* emul dsp[rs], rd */
+static bool trans_EMUL_mr(DisasContext *ctx, arg_EMUL_mr *a)
+{
+    prt("emul\t");
+    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    return true;
+}
+
+/* emulu #imm, rd */
+static bool trans_EMULU_ir(DisasContext *ctx, arg_EMULU_ir *a)
+{
+    prt_ir(ctx, "emulu", a->imm, a->rd);
+    return true;
+}
+
+/* emulu rs, rd */
+/* emulu dsp[rs], rd */
+static bool trans_EMULU_mr(DisasContext *ctx, arg_EMULU_mr *a)
+{
+    prt("emulu\t");
+    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    return true;
+}
+
+/* div #imm, rd */
+static bool trans_DIV_ir(DisasContext *ctx, arg_DIV_ir *a)
+{
+    prt_ir(ctx, "div", a->imm, a->rd);
+    return true;
+}
+
+/* div rs, rd */
+/* div dsp[rs], rd */
+static bool trans_DIV_mr(DisasContext *ctx, arg_DIV_mr *a)
+{
+    prt("div\t");
+    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    return true;
+}
+
+/* divu #imm, rd */
+static bool trans_DIVU_ir(DisasContext *ctx, arg_DIVU_ir *a)
+{
+    prt_ir(ctx, "divu", a->imm, a->rd);
+    return true;
+}
+
+/* divu rs, rd */
+/* divu dsp[rs], rd */
+static bool trans_DIVU_mr(DisasContext *ctx, arg_DIVU_mr *a)
+{
+    prt("divu\t");
+    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    return true;
+}
+
+
+/* shll #imm:5, rd */
+/* shll #imm:5, rs, rd */
+static bool trans_SHLL_irr(DisasContext *ctx, arg_SHLL_irr *a)
+{
+    prt("shll\t#%d, ", a->imm);
+    if (a->rs2 != a->rd) {
+        prt("r%d, ", a->rs2);
+    }
+    prt("r%d", a->rd);
+    return true;
+}
+
+/* shll rs, rd */
+static bool trans_SHLL_rr(DisasContext *ctx, arg_SHLL_rr *a)
+{
+    prt("shll\tr%d, r%d", a->rs, a->rd);
+    return true;
+}
+
+/* shar #imm:5, rd */
+/* shar #imm:5, rs, rd */
+static bool trans_SHAR_irr(DisasContext *ctx, arg_SHAR_irr *a)
+{
+    prt("shar\t#%d,", a->imm);
+    if (a->rs2 != a->rd) {
+        prt("r%d, ", a->rs2);
+    }
+    prt("r%d", a->rd);
+    return true;
+}
+
+/* shar rs, rd */
+static bool trans_SHAR_rr(DisasContext *ctx, arg_SHAR_rr *a)
+{
+    prt("shar\tr%d, r%d", a->rs, a->rd);
+    return true;
+}
+
+/* shlr #imm:5, rd */
+/* shlr #imm:5, rs, rd */
+static bool trans_SHLR_irr(DisasContext *ctx, arg_SHLR_irr *a)
+{
+    prt("shlr\t#%d, ", a->imm);
+    if (a->rs2 != a->rd) {
+        prt("r%d, ", a->rs2);
+    }
+    prt("r%d", a->rd);
+    return true;
+}
+
+/* shlr rs, rd */
+static bool trans_SHLR_rr(DisasContext *ctx, arg_SHLR_rr *a)
+{
+    prt("shlr\tr%d, r%d", a->rs, a->rd);
+    return true;
+}
+
+/* rolc rd */
+static bool trans_ROLC(DisasContext *ctx, arg_ROLC *a)
+{
+    prt("rorc\tr%d", a->rd);
+    return true;
+}
+
+/* rorc rd */
+static bool trans_RORC(DisasContext *ctx, arg_RORC *a)
+{
+    prt("rorc\tr%d", a->rd);
+    return true;
+}
+
+/* rotl #imm, rd */
+static bool trans_ROTL_ir(DisasContext *ctx, arg_ROTL_ir *a)
+{
+    prt("rotl\t#%d, r%d", a->imm, a->rd);
+    return true;
+}
+
+/* rotl rs, rd */
+static bool trans_ROTL_rr(DisasContext *ctx, arg_ROTL_rr *a)
+{
+    prt("rotl\tr%d, r%d", a->rs, a->rd);
+    return true;
+}
+
+/* rotr #imm, rd */
+static bool trans_ROTR_ir(DisasContext *ctx, arg_ROTR_ir *a)
+{
+    prt("rotr\t#%d, r%d", a->imm, a->rd);
+    return true;
+}
+
+/* rotr rs, rd */
+static bool trans_ROTR_rr(DisasContext *ctx, arg_ROTR_rr *a)
+{
+    prt("rotr\tr%d, r%d", a->rs, a->rd);
+    return true;
+}
+
+/* revl rs, rd */
+static bool trans_REVL(DisasContext *ctx, arg_REVL *a)
+{
+    prt("revl\tr%d, r%d", a->rs, a->rd);
+    return true;
+}
+
+/* revw rs, rd */
+static bool trans_REVW(DisasContext *ctx, arg_REVW *a)
+{
+    prt("revw\tr%d, r%d", a->rs, a->rd);
+    return true;
+}
+
+/* conditional branch helper */
+static void rx_bcnd_main(DisasContext *ctx, int cd, int len, int dst)
+{
+    static const char sz[] = {'s', 'b', 'w', 'a'};
+    prt("b%s.%c\t%08x", cond[cd], sz[len - 1], ctx->pc + dst);
+}
+
+/* beq dsp:3 / bne dsp:3 */
+/* beq dsp:8 / bne dsp:8 */
+/* bc dsp:8 / bnc dsp:8 */
+/* bgtu dsp:8 / bleu dsp:8 */
+/* bpz dsp:8 / bn dsp:8 */
+/* bge dsp:8 / blt dsp:8 */
+/* bgt dsp:8 / ble dsp:8 */
+/* bo dsp:8 / bno dsp:8 */
+/* beq dsp:16 / bne dsp:16 */
+static bool trans_BCnd(DisasContext *ctx, arg_BCnd *a)
+{
+    rx_bcnd_main(ctx, a->cd, a->sz, a->dsp);
+    return true;
+}
+
+/* bra dsp:3 */
+/* bra dsp:8 */
+/* bra dsp:16 */
+/* bra dsp:24 */
+static bool trans_BRA(DisasContext *ctx, arg_BRA *a)
+{
+    rx_bcnd_main(ctx, 14, a->sz, a->dsp);
+    return true;
+}
+
+/* bra rs */
+static bool trans_BRA_l(DisasContext *ctx, arg_BRA_l *a)
+{
+    prt("bra.l\tr%d", a->rd);
+    return true;
+}
+
+/* jmp rs */
+static bool trans_JMP(DisasContext *ctx, arg_JMP *a)
+{
+    prt("jmp\tr%d", a->rs);
+    return true;
+}
+
+/* jsr rs */
+static bool trans_JSR(DisasContext *ctx, arg_JSR *a)
+{
+    prt("jsr\tr%d", a->rs);
+    return true;
+}
+
+/* bsr dsp:16 */
+/* bsr dsp:24 */
+static bool trans_BSR(DisasContext *ctx, arg_BSR *a)
+{
+    static const char sz[] = {'w', 'a'};
+    prt("bsr.%c\t%08x", sz[a->sz - 3], ctx->pc + a->dsp);
+    return true;
+}
+
+/* bsr rs */
+static bool trans_BSR_l(DisasContext *ctx, arg_BSR_l *a)
+{
+    prt("bsr.l\tr%d", a->rd);
+    return true;
+}
+
+/* rts */
+static bool trans_RTS(DisasContext *ctx, arg_RTS *a)
+{
+    prt("rts");
+    return true;
+}
+
+/* nop */
+static bool trans_NOP(DisasContext *ctx, arg_NOP *a)
+{
+    prt("nop");
+    return true;
+}
+
+/* scmpu */
+static bool trans_SCMPU(DisasContext *ctx, arg_SCMPU *a)
+{
+    prt("scmpu");
+    return true;
+}
+
+/* smovu */
+static bool trans_SMOVU(DisasContext *ctx, arg_SMOVU *a)
+{
+    prt("smovu");
+    return true;
+}
+
+/* smovf */
+static bool trans_SMOVF(DisasContext *ctx, arg_SMOVF *a)
+{
+    prt("smovf");
+    return true;
+}
+
+/* smovb */
+static bool trans_SMOVB(DisasContext *ctx, arg_SMOVB *a)
+{
+    prt("smovb");
+    return true;
+}
+
+/* suntile */
+static bool trans_SUNTIL(DisasContext *ctx, arg_SUNTIL *a)
+{
+    prt("suntil.%c", size[a->sz]);
+    return true;
+}
+
+/* swhile */
+static bool trans_SWHILE(DisasContext *ctx, arg_SWHILE *a)
+{
+    prt("swhile.%c", size[a->sz]);
+    return true;
+}
+/* sstr */
+static bool trans_SSTR(DisasContext *ctx, arg_SSTR *a)
+{
+    prt("sstr.%c", size[a->sz]);
+    return true;
+}
+
+/* rmpa */
+static bool trans_RMPA(DisasContext *ctx, arg_RMPA *a)
+{
+    prt("rmpa.%c", size[a->sz]);
+    return true;
+}
+
+/* mulhi rs,rs2 */
+static bool trans_MULHI(DisasContext *ctx, arg_MULHI *a)
+{
+    prt("mulhi\tr%d,r%d", a->rs, a->rs2);
+    return true;
+}
+
+/* mullo rs,rs2 */
+static bool trans_MULLO(DisasContext *ctx, arg_MULLO *a)
+{
+    prt("mullo\tr%d, r%d", a->rs, a->rs2);
+    return true;
+}
+
+/* machi rs,rs2 */
+static bool trans_MACHI(DisasContext *ctx, arg_MACHI *a)
+{
+    prt("machi\tr%d, r%d", a->rs, a->rs2);
+    return true;
+}
+
+/* maclo rs,rs2 */
+static bool trans_MACLO(DisasContext *ctx, arg_MACLO *a)
+{
+    prt("maclo\tr%d, r%d", a->rs, a->rs2);
+    return true;
+}
+
+/* mvfachi rd */
+static bool trans_MVFACHI(DisasContext *ctx, arg_MVFACHI *a)
+{
+    prt("mvfachi\tr%d", a->rd);
+    return true;
+}
+
+/* mvfacmi rd */
+static bool trans_MVFACMI(DisasContext *ctx, arg_MVFACMI *a)
+{
+    prt("mvfacmi\tr%d", a->rd);
+    return true;
+}
+
+/* mvtachi rs */
+static bool trans_MVTACHI(DisasContext *ctx, arg_MVTACHI *a)
+{
+    prt("mvtachi\tr%d", a->rs);
+    return true;
+}
+
+/* mvtaclo rs */
+static bool trans_MVTACLO(DisasContext *ctx, arg_MVTACLO *a)
+{
+    prt("mvtaclo\tr%d", a->rs);
+    return true;
+}
+
+/* racw #imm */
+static bool trans_RACW(DisasContext *ctx, arg_RACW *a)
+{
+    prt("racw\t#%d", a->imm + 1);
+    return true;
+}
+
+/* sat rd */
+static bool trans_SAT(DisasContext *ctx, arg_SAT *a)
+{
+    prt("sat\tr%d", a->rd);
+    return true;
+}
+
+/* satr */
+static bool trans_SATR(DisasContext *ctx, arg_SATR *a)
+{
+    prt("satr");
+    return true;
+}
+
+/* fadd #imm, rd */
+static bool trans_FADD_ir(DisasContext *ctx, arg_FADD_ir *a)
+{
+    prt("fadd\t#%d,r%d", li(ctx, 0), a->rd);
+    return true;
+}
+
+/* fadd dsp[rs], rd */
+/* fadd rs, rd */
+static bool trans_FADD_mr(DisasContext *ctx, arg_FADD_mr *a)
+{
+    prt("fadd\t");
+    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    return true;
+}
+
+/* fcmp #imm, rd */
+static bool trans_FCMP_ir(DisasContext *ctx, arg_FCMP_ir *a)
+{
+    prt("fadd\t#%d,r%d", li(ctx, 0), a->rd);
+    return true;
+}
+
+/* fcmp dsp[rs], rd */
+/* fcmp rs, rd */
+static bool trans_FCMP_mr(DisasContext *ctx, arg_FCMP_mr *a)
+{
+    prt("fcmp\t");
+    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    return true;
+}
+
+/* fsub #imm, rd */
+static bool trans_FSUB_ir(DisasContext *ctx, arg_FSUB_ir *a)
+{
+    prt("fsub\t#%d,r%d", li(ctx, 0), a->rd);
+    return true;
+}
+
+/* fsub dsp[rs], rd */
+/* fsub rs, rd */
+static bool trans_FSUB_mr(DisasContext *ctx, arg_FSUB_mr *a)
+{
+    prt("fsub\t");
+    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    return true;
+}
+
+/* ftoi dsp[rs], rd */
+/* ftoi rs, rd */
+static bool trans_FTOI(DisasContext *ctx, arg_FTOI *a)
+{
+    prt("ftoi\t");
+    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    return true;
+}
+
+/* fmul #imm, rd */
+static bool trans_FMUL_ir(DisasContext *ctx, arg_FMUL_ir *a)
+{
+    prt("fmul\t#%d,r%d", li(ctx, 0), a->rd);
+    return true;
+}
+
+/* fmul dsp[rs], rd */
+/* fmul rs, rd */
+static bool trans_FMUL_mr(DisasContext *ctx, arg_FMUL_mr *a)
+{
+    prt("fmul\t");
+    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    return true;
+}
+
+/* fdiv #imm, rd */
+static bool trans_FDIV_ir(DisasContext *ctx, arg_FDIV_ir *a)
+{
+    prt("fdiv\t#%d,r%d", li(ctx, 0), a->rd);
+    return true;
+}
+
+/* fdiv dsp[rs], rd */
+/* fdiv rs, rd */
+static bool trans_FDIV_mr(DisasContext *ctx, arg_FDIV_mr *a)
+{
+    prt("fdiv\t");
+    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    return true;
+}
+
+/* round dsp[rs], rd */
+/* round rs, rd */
+static bool trans_ROUND(DisasContext *ctx, arg_ROUND *a)
+{
+    prt("round\t");
+    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    return true;
+}
+
+/* itof rs, rd */
+/* itof dsp[rs], rd */
+static bool trans_ITOF(DisasContext *ctx, arg_ITOF *a)
+{
+    prt("itof\t");
+    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    return true;
+}
+
+#define BOP_IM(name, reg)                                       \
+    do {                                                        \
+        int dsp;                                                \
+        prt("b%s\t#%d, ", #name, a->imm);                       \
+        dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx);        \
+        if (dsp > 0) {                                          \
+            prt("%d", dsp);                                     \
+        }                                                       \
+        prt("[r%d]", reg);                                      \
+        return true;                                            \
+    } while (0)
+
+#define BOP_RM(name)                                            \
+    do {                                                        \
+        int dsp;                                                \
+        prt("b%s\tr%d, ", #name, a->rd);                        \
+        dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx);        \
+        if (dsp > 0) {                                          \
+            prt("%d", dsp);                                     \
+        }                                                       \
+        prt("[r%d]", a->rs);                                    \
+        return true;                                            \
+    } while (0)
+
+/* bset #imm, dsp[rd] */
+static bool trans_BSET_im(DisasContext *ctx, arg_BSET_im *a)
+{
+    BOP_IM(bset, a->rs);
+}
+
+/* bset rs, dsp[rd] */
+static bool trans_BSET_rm(DisasContext *ctx, arg_BSET_rm *a)
+{
+    BOP_RM(set);
+}
+
+/* bset rs, rd */
+static bool trans_BSET_rr(DisasContext *ctx, arg_BSET_rr *a)
+{
+    prt("bset\tr%d,r%d", a->rs, a->rd);
+    return true;
+}
+
+/* bset #imm, rd */
+static bool trans_BSET_ir(DisasContext *ctx, arg_BSET_ir *a)
+{
+    prt("bset\t#%d, r%d", a->imm, a->rd);
+    return true;
+}
+
+/* bclr #imm, dsp[rd] */
+static bool trans_BCLR_im(DisasContext *ctx, arg_BCLR_im *a)
+{
+    BOP_IM(clr, a->rs);
+}
+
+/* bclr rs, dsp[rd] */
+static bool trans_BCLR_rm(DisasContext *ctx, arg_BCLR_rm *a)
+{
+    BOP_RM(clr);
+}
+
+/* bclr rs, rd */
+static bool trans_BCLR_rr(DisasContext *ctx, arg_BCLR_rr *a)
+{
+    prt("bclr\tr%d, r%d", a->rs, a->rd);
+    return true;
+}
+
+/* bclr #imm, rd */
+static bool trans_BCLR_ir(DisasContext *ctx, arg_BCLR_ir *a)
+{
+    prt("bclr\t#%d,r%d", a->imm, a->rd);
+    return true;
+}
+
+/* btst #imm, dsp[rd] */
+static bool trans_BTST_im(DisasContext *ctx, arg_BTST_im *a)
+{
+    BOP_IM(tst, a->rs);
+}
+
+/* btst rs, dsp[rd] */
+static bool trans_BTST_rm(DisasContext *ctx, arg_BTST_rm *a)
+{
+    BOP_RM(tst);
+}
+
+/* btst rs, rd */
+static bool trans_BTST_rr(DisasContext *ctx, arg_BTST_rr *a)
+{
+    prt("btst\tr%d, r%d", a->rs, a->rd);
+    return true;
+}
+
+/* btst #imm, rd */
+static bool trans_BTST_ir(DisasContext *ctx, arg_BTST_ir *a)
+{
+    prt("btst\t#%d, r%d", a->imm, a->rd);
+    return true;
+}
+
+/* bnot rs, dsp[rd] */
+static bool trans_BNOT_rm(DisasContext *ctx, arg_BNOT_rm *a)
+{
+    BOP_RM(not);
+}
+
+/* bnot rs, rd */
+static bool trans_BNOT_rr(DisasContext *ctx, arg_BNOT_rr *a)
+{
+    prt("bnot\tr%d, r%d", a->rs, a->rd);
+    return true;
+}
+
+/* bnot #imm, dsp[rd] */
+static bool trans_BNOT_im(DisasContext *ctx, arg_BNOT_im *a)
+{
+    BOP_IM(not, a->rs);
+}
+
+/* bnot #imm, rd */
+static bool trans_BNOT_ir(DisasContext *ctx, arg_BNOT_ir *a)
+{
+    prt("bnot\t#%d, r%d", a->imm, a->rd);
+    return true;
+}
+
+/* bmcond #imm, dsp[rd] */
+static bool trans_BMCnd_im(DisasContext *ctx, arg_BMCnd_im *a)
+{
+    int dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx);
+    prt("bm%s\t#%d, ", cond[a->cd], a->imm);
+    if (dsp > 0) {
+        prt("%d", dsp);
+    }
+    prt("[%d]", a->rd);
+    return true;
+}
+
+/* bmcond #imm, rd */
+static bool trans_BMCnd_ir(DisasContext *ctx, arg_BMCnd_ir *a)
+{
+    prt("bm%s\t#%d, r%d", cond[a->cd], a->imm, a->rd);
+    return true;
+}
+
+/* clrpsw psw */
+static bool trans_CLRPSW(DisasContext *ctx, arg_CLRPSW *a)
+{
+    prt("clrpsw\t%c", psw[a->cb]);
+    return true;
+}
+
+/* setpsw psw */
+static bool trans_SETPSW(DisasContext *ctx, arg_SETPSW *a)
+{
+    prt("setpsw\t%c", psw[a->cb]);
+    return true;
+}
+
+/* mvtipl #imm */
+static bool trans_MVTIPL(DisasContext *ctx, arg_MVTIPL *a)
+{
+    prt("movtipl\t#%d", a->imm);
+    return true;
+}
+
+/* mvtc #imm, rd */
+static bool trans_MVTC_i(DisasContext *ctx, arg_MVTC_i *a)
+{
+    prt("mvtc\t#0x%08x, %s", a->imm, rx_crname[a->cr]);
+    return true;
+}
+
+/* mvtc rs, rd */
+static bool trans_MVTC_r(DisasContext *ctx, arg_MVTC_r *a)
+{
+    prt("mvtc\tr%d, %s", a->rs, rx_crname[a->cr]);
+    return true;
+}
+
+/* mvfc rs, rd */
+static bool trans_MVFC(DisasContext *ctx, arg_MVFC *a)
+{
+    prt("mvfc\t%s, r%d", rx_crname[a->cr], a->rd);
+    return true;
+}
+
+/* rtfi */
+static bool trans_RTFI(DisasContext *ctx, arg_RTFI *a)
+{
+    prt("rtfi");
+    return true;
+}
+
+/* rte */
+static bool trans_RTE(DisasContext *ctx, arg_RTE *a)
+{
+    prt("rte");
+    return true;
+}
+
+/* brk */
+static bool trans_BRK(DisasContext *ctx, arg_BRK *a)
+{
+    prt("brk");
+    return true;
+}
+
+/* int #imm */
+static bool trans_INT(DisasContext *ctx, arg_INT *a)
+{
+    prt("int\t#%d", a->imm);
+    return true;
+}
+
+/* wait */
+static bool trans_WAIT(DisasContext *ctx, arg_WAIT *a)
+{
+    prt("wait");
+    return true;
+}
+
+/* sccnd.[bwl] rd */
+/* sccnd.[bwl] dsp:[rd] */
+static bool trans_SCCnd(DisasContext *ctx, arg_SCCnd *a)
+{
+    int dsp;
+    prt("sc%s.%c\t", cond[a->cd], size[a->sz]);
+    if (a->ld < 3) {
+        dsp = rx_index_addr(a->sz, a->ld, ctx);
+        if (dsp > 0) {
+            prt("%d", dsp);
+        }
+        prt("[r%d]", a->rd);
+    } else {
+        prt("r%d", a->rd);
+    }
+    return true;
+}
+
+int print_insn_rx(bfd_vma addr, disassemble_info *dis)
+{
+    DisasContext ctx;
+    uint32_t insn;
+    int i;
+    ctx.dis = dis;
+    ctx.pc = ctx.addr = addr;
+
+    insn = decode_load(&ctx);
+    if (!decode(&ctx, insn)) {
+        ctx.dis->fprintf_func(ctx.dis->stream, ".byte\t");
+        for (i = 0; i < ctx.addr - addr; i++) {
+            if (i > 0) {
+                ctx.dis->fprintf_func(ctx.dis->stream, ",");
+            }
+            ctx.dis->fprintf_func(ctx.dis->stream, "0x%02x", insn >> 24);
+            insn <<= 8;
+        }
+    }
+    return ctx.addr - addr;
+}
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 08/22] target/rx: Disassemble rx_index_addr into a string
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (6 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 07/22] target/rx: RX disassembler Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 09/22] target/rx: Replace operand with prt_ldmi in disassembler Yoshinori Sato
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, Richard Henderson, Yoshinori Sato, philmd

From: Richard Henderson <richard.henderson@linaro.org>

We were eliding all zero indexes.  It is only ld==0 that does
not have an index in the instruction.  This also allows us to
avoid breaking the final print into multiple pieces.

Reviewed-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Message-Id: <20190607091116.49044-19-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/rx/disas.c | 154 +++++++++++++++++-----------------------------
 1 file changed, 55 insertions(+), 99 deletions(-)

diff --git a/target/rx/disas.c b/target/rx/disas.c
index 8cada4825d..64342537ee 100644
--- a/target/rx/disas.c
+++ b/target/rx/disas.c
@@ -107,49 +107,42 @@ static const char psw[] = {
     'i', 'u', 0, 0, 0, 0, 0, 0,
 };
 
-static uint32_t rx_index_addr(int ld, int size, DisasContext *ctx)
+static void rx_index_addr(DisasContext *ctx, char out[8], int ld, int mi)
 {
-    bfd_byte buf[2];
+    uint32_t addr = ctx->addr;
+    uint8_t buf[2];
+    uint16_t dsp;
+
     switch (ld) {
     case 0:
-        return 0;
+        /* No index; return empty string.  */
+        out[0] = '\0';
+        return;
     case 1:
-        ctx->dis->read_memory_func(ctx->addr, buf, 1, ctx->dis);
         ctx->addr += 1;
-        return ((uint8_t)buf[0]) << size;
+        ctx->dis->read_memory_func(addr, buf, 1, ctx->dis);
+        dsp = buf[0];
+        break;
     case 2:
-        ctx->dis->read_memory_func(ctx->addr, buf, 2, ctx->dis);
         ctx->addr += 2;
-        return lduw_le_p(buf) << size;
+        ctx->dis->read_memory_func(addr, buf, 2, ctx->dis);
+        dsp = lduw_le_p(buf);
+        break;
+    default:
+        g_assert_not_reached();
     }
-    g_assert_not_reached();
+
+    sprintf(out, "%u", dsp << (mi < 3 ? mi : 4 - mi));
 }
 
 static void operand(DisasContext *ctx, int ld, int mi, int rs, int rd)
 {
-    int dsp;
     static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"};
+    char dsp[8];
+
     if (ld < 3) {
-        switch (mi) {
-        case 4:
-            /* dsp[rs].ub */
-            dsp = rx_index_addr(ld, RX_MEMORY_BYTE, ctx);
-            break;
-        case 3:
-            /* dsp[rs].uw */
-            dsp = rx_index_addr(ld, RX_MEMORY_WORD, ctx);
-            break;
-        default:
-            /* dsp[rs].b */
-            /* dsp[rs].w */
-            /* dsp[rs].l */
-            dsp = rx_index_addr(ld, mi, ctx);
-            break;
-        }
-        if (dsp > 0) {
-            prt("%d", dsp);
-        }
-        prt("[r%d]%s", rs, sizes[mi]);
+        rx_index_addr(ctx, dsp, ld, mi);
+        prt("%s[r%d]%s", dsp, rs, sizes[mi]);
     } else {
         prt("r%d", rs);
     }
@@ -235,7 +228,7 @@ static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a)
 /* mov.[bwl] rs,rd */
 static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a)
 {
-    int dsp;
+    char dspd[8], dsps[8];
 
     prt("mov.%c\t", size[a->sz]);
     if (a->lds == 3 && a->ldd == 3) {
@@ -244,29 +237,15 @@ static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a)
         return true;
     }
     if (a->lds == 3) {
-        prt("r%d, ", a->rd);
-        dsp = rx_index_addr(a->ldd, a->sz, ctx);
-        if (dsp > 0) {
-            prt("%d", dsp);
-        }
-        prt("[r%d]", a->rs);
+        rx_index_addr(ctx, dspd, a->ldd, a->sz);
+        prt("r%d, %s[r%d]", a->rs, dspd, a->rd);
     } else if (a->ldd == 3) {
-        dsp = rx_index_addr(a->lds, a->sz, ctx);
-        if (dsp > 0) {
-            prt("%d", dsp);
-        }
-        prt("[r%d], r%d", a->rs, a->rd);
+        rx_index_addr(ctx, dsps, a->lds, a->sz);
+        prt("%s[r%d], r%d", dsps, a->rs, a->rd);
     } else {
-        dsp = rx_index_addr(a->lds, a->sz, ctx);
-        if (dsp > 0) {
-            prt("%d", dsp);
-        }
-        prt("[r%d], ", a->rs);
-        dsp = rx_index_addr(a->ldd, a->sz, ctx);
-        if (dsp > 0) {
-            prt("%d", dsp);
-        }
-        prt("[r%d]", a->rd);
+        rx_index_addr(ctx, dsps, a->lds, a->sz);
+        rx_index_addr(ctx, dspd, a->ldd, a->sz);
+        prt("%s[r%d], %s[r%d]", dsps, a->rs, dspd, a->rd);
     }
     return true;
 }
@@ -357,12 +336,10 @@ static bool trans_PUSH_r(DisasContext *ctx, arg_PUSH_r *a)
 /* push dsp[rs] */
 static bool trans_PUSH_m(DisasContext *ctx, arg_PUSH_m *a)
 {
-    prt("push\t");
-    int dsp = rx_index_addr(a->ld, a->sz, ctx);
-    if (dsp > 0) {
-        prt("%d", dsp);
-    }
-    prt("[r%d]", a->rs);
+    char dsp[8];
+
+    rx_index_addr(ctx, dsp, a->ld, a->sz);
+    prt("push\t%s[r%d]", dsp, a->rs);
     return true;
 }
 
@@ -389,17 +366,13 @@ static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr *a)
 /* xchg dsp[rs].<mi>,rd */
 static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a)
 {
-    int dsp;
     static const char msize[][4] = {
         "b", "w", "l", "ub", "uw",
     };
+    char dsp[8];
 
-    prt("xchg\t");
-    dsp = rx_index_addr(a->ld, a->mi, ctx);
-    if (dsp > 0) {
-        prt("%d", dsp);
-    }
-    prt("[r%d].%s, r%d", a->rs, msize[a->mi], a->rd);
+    rx_index_addr(ctx, dsp, a->ld, a->mi);
+    prt("xchg\t%s[r%d].%s, r%d", dsp, a->rs, msize[a->mi], a->rd);
     return true;
 }
 
@@ -552,13 +525,10 @@ static bool trans_ADC_rr(DisasContext *ctx, arg_ADC_rr *a)
 /* adc dsp[rs], rd */
 static bool trans_ADC_mr(DisasContext *ctx, arg_ADC_mr *a)
 {
-    int dsp;
-    prt("adc\t");
-    dsp = rx_index_addr(a->ld, 2, ctx);
-    if (dsp > 0) {
-        prt("%d", dsp);
-    }
-    prt("[r%d], r%d", a->rs, a->rd);
+    char dsp[8];
+
+    rx_index_addr(ctx, dsp, a->ld, 2);
+    prt("adc\t%s[r%d], r%d", dsp, a->rs, a->rd);
     return true;
 }
 
@@ -1217,25 +1187,17 @@ static bool trans_ITOF(DisasContext *ctx, arg_ITOF *a)
 
 #define BOP_IM(name, reg)                                       \
     do {                                                        \
-        int dsp;                                                \
-        prt("b%s\t#%d, ", #name, a->imm);                       \
-        dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx);        \
-        if (dsp > 0) {                                          \
-            prt("%d", dsp);                                     \
-        }                                                       \
-        prt("[r%d]", reg);                                      \
+        char dsp[8];                                            \
+        rx_index_addr(ctx, dsp, a->ld, RX_MEMORY_BYTE);         \
+        prt("b%s\t#%d, %s[r%d]", #name, a->imm, dsp, reg);      \
         return true;                                            \
     } while (0)
 
 #define BOP_RM(name)                                            \
     do {                                                        \
-        int dsp;                                                \
-        prt("b%s\tr%d, ", #name, a->rd);                        \
-        dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx);        \
-        if (dsp > 0) {                                          \
-            prt("%d", dsp);                                     \
-        }                                                       \
-        prt("[r%d]", a->rs);                                    \
+        char dsp[8];                                            \
+        rx_index_addr(ctx, dsp, a->ld, RX_MEMORY_BYTE);         \
+        prt("b%s\tr%d, %s[r%d]", #name, a->rd, dsp, a->rs);     \
         return true;                                            \
     } while (0)
 
@@ -1346,12 +1308,10 @@ static bool trans_BNOT_ir(DisasContext *ctx, arg_BNOT_ir *a)
 /* bmcond #imm, dsp[rd] */
 static bool trans_BMCnd_im(DisasContext *ctx, arg_BMCnd_im *a)
 {
-    int dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx);
-    prt("bm%s\t#%d, ", cond[a->cd], a->imm);
-    if (dsp > 0) {
-        prt("%d", dsp);
-    }
-    prt("[%d]", a->rd);
+    char dsp[8];
+
+    rx_index_addr(ctx, dsp, a->ld, RX_MEMORY_BYTE);
+    prt("bm%s\t#%d, %s[r%d]", cond[a->cd], a->imm, dsp, a->rd);
     return true;
 }
 
@@ -1443,16 +1403,12 @@ static bool trans_WAIT(DisasContext *ctx, arg_WAIT *a)
 /* sccnd.[bwl] dsp:[rd] */
 static bool trans_SCCnd(DisasContext *ctx, arg_SCCnd *a)
 {
-    int dsp;
-    prt("sc%s.%c\t", cond[a->cd], size[a->sz]);
     if (a->ld < 3) {
-        dsp = rx_index_addr(a->sz, a->ld, ctx);
-        if (dsp > 0) {
-            prt("%d", dsp);
-        }
-        prt("[r%d]", a->rd);
+        char dsp[8];
+        rx_index_addr(ctx, dsp, a->sz, a->ld);
+        prt("sc%s.%c\t%s[r%d]", cond[a->cd], size[a->sz], dsp, a->rd);
     } else {
-        prt("r%d", a->rd);
+        prt("sc%s.%c\tr%d", cond[a->cd], size[a->sz], a->rd);
     }
     return true;
 }
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 09/22] target/rx: Replace operand with prt_ldmi in disassembler
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (7 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 08/22] target/rx: Disassemble rx_index_addr into a string Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 10/22] target/rx: Use prt_ldmi for XCHG_mr disassembly Yoshinori Sato
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, Richard Henderson, Yoshinori Sato, philmd

From: Richard Henderson <richard.henderson@linaro.org>

This has consistency with prt_ri().  It loads all data before
beginning output.  It uses exactly one call to prt() to emit
the full instruction.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Message-Id: <20190607091116.49044-20-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/rx/disas.c | 77 +++++++++++++++++------------------------------
 1 file changed, 27 insertions(+), 50 deletions(-)

diff --git a/target/rx/disas.c b/target/rx/disas.c
index 64342537ee..515b365528 100644
--- a/target/rx/disas.c
+++ b/target/rx/disas.c
@@ -135,18 +135,18 @@ static void rx_index_addr(DisasContext *ctx, char out[8], int ld, int mi)
     sprintf(out, "%u", dsp << (mi < 3 ? mi : 4 - mi));
 }
 
-static void operand(DisasContext *ctx, int ld, int mi, int rs, int rd)
+static void prt_ldmi(DisasContext *ctx, const char *insn,
+                     int ld, int mi, int rs, int rd)
 {
     static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"};
     char dsp[8];
 
     if (ld < 3) {
         rx_index_addr(ctx, dsp, ld, mi);
-        prt("%s[r%d]%s", dsp, rs, sizes[mi]);
+        prt("%s\t%s[r%d]%s, r%d", insn, dsp, rs, sizes[mi], rd);
     } else {
-        prt("r%d", rs);
+        prt("%s\tr%d, r%d", insn, rs, rd);
     }
-    prt(", r%d", rd);
 }
 
 static void prt_ir(DisasContext *ctx, const char *insn, int imm, int rd)
@@ -416,8 +416,7 @@ static bool trans_AND_ir(DisasContext *ctx, arg_AND_ir *a)
 /* and rs,rd */
 static bool trans_AND_mr(DisasContext *ctx, arg_AND_mr *a)
 {
-    prt("and\t");
-    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    prt_ldmi(ctx, "and", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
@@ -440,8 +439,7 @@ static bool trans_OR_ir(DisasContext *ctx, arg_OR_ir *a)
 /* or rs,rd */
 static bool trans_OR_mr(DisasContext *ctx, arg_OR_mr *a)
 {
-    prt("or\t");
-    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    prt_ldmi(ctx, "or", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
@@ -463,8 +461,7 @@ static bool trans_XOR_ir(DisasContext *ctx, arg_XOR_ir *a)
 /* xor rs,rd */
 static bool trans_XOR_mr(DisasContext *ctx, arg_XOR_mr *a)
 {
-    prt("xor\t");
-    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    prt_ldmi(ctx, "xor", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
@@ -479,8 +476,7 @@ static bool trans_TST_ir(DisasContext *ctx, arg_TST_ir *a)
 /* tst rs, rd */
 static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *a)
 {
-    prt("tst\t");
-    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    prt_ldmi(ctx, "tst", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
@@ -548,8 +544,7 @@ static bool trans_ADD_irr(DisasContext *ctx, arg_ADD_irr *a)
 /* add dsp[rs], rd */
 static bool trans_ADD_mr(DisasContext *ctx, arg_ADD_mr *a)
 {
-    prt("add\t");
-    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    prt_ldmi(ctx, "add", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
@@ -573,8 +568,7 @@ static bool trans_CMP_ir(DisasContext *ctx, arg_CMP_ir *a)
 /* cmp dsp[rs], rs2 */
 static bool trans_CMP_mr(DisasContext *ctx, arg_CMP_mr *a)
 {
-    prt("cmp\t");
-    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    prt_ldmi(ctx, "cmp", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
@@ -589,8 +583,7 @@ static bool trans_SUB_ir(DisasContext *ctx, arg_SUB_ir *a)
 /* sub dsp[rs], rd */
 static bool trans_SUB_mr(DisasContext *ctx, arg_SUB_mr *a)
 {
-    prt("sub\t");
-    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    prt_ldmi(ctx, "sub", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
@@ -611,8 +604,7 @@ static bool trans_SBB_rr(DisasContext *ctx, arg_SBB_rr *a)
 /* sbb dsp[rs], rd */
 static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a)
 {
-    prt("sbb\t");
-    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    prt_ldmi(ctx, "sbb", a->ld, RX_IM_LONG, a->rs, a->rd);
     return true;
 }
 
@@ -640,8 +632,7 @@ static bool trans_MAX_ir(DisasContext *ctx, arg_MAX_ir *a)
 /* max dsp[rs], rd */
 static bool trans_MAX_mr(DisasContext *ctx, arg_MAX_mr *a)
 {
-    prt("max\t");
-    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    prt_ldmi(ctx, "max", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
@@ -656,8 +647,7 @@ static bool trans_MIN_ir(DisasContext *ctx, arg_MIN_ir *a)
 /* min dsp[rs], rd */
 static bool trans_MIN_mr(DisasContext *ctx, arg_MIN_mr *a)
 {
-    prt("max\t");
-    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    prt_ldmi(ctx, "min", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
@@ -673,8 +663,7 @@ static bool trans_MUL_ir(DisasContext *ctx, arg_MUL_ir *a)
 /* mul dsp[rs], rd */
 static bool trans_MUL_mr(DisasContext *ctx, arg_MUL_mr *a)
 {
-    prt("mul\t");
-    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    prt_ldmi(ctx, "mul", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
@@ -696,8 +685,7 @@ static bool trans_EMUL_ir(DisasContext *ctx, arg_EMUL_ir *a)
 /* emul dsp[rs], rd */
 static bool trans_EMUL_mr(DisasContext *ctx, arg_EMUL_mr *a)
 {
-    prt("emul\t");
-    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    prt_ldmi(ctx, "emul", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
@@ -712,8 +700,7 @@ static bool trans_EMULU_ir(DisasContext *ctx, arg_EMULU_ir *a)
 /* emulu dsp[rs], rd */
 static bool trans_EMULU_mr(DisasContext *ctx, arg_EMULU_mr *a)
 {
-    prt("emulu\t");
-    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    prt_ldmi(ctx, "emulu", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
@@ -728,8 +715,7 @@ static bool trans_DIV_ir(DisasContext *ctx, arg_DIV_ir *a)
 /* div dsp[rs], rd */
 static bool trans_DIV_mr(DisasContext *ctx, arg_DIV_mr *a)
 {
-    prt("div\t");
-    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    prt_ldmi(ctx, "div", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
@@ -744,8 +730,7 @@ static bool trans_DIVU_ir(DisasContext *ctx, arg_DIVU_ir *a)
 /* divu dsp[rs], rd */
 static bool trans_DIVU_mr(DisasContext *ctx, arg_DIVU_mr *a)
 {
-    prt("divu\t");
-    operand(ctx, a->ld, a->mi, a->rs, a->rd);
+    prt_ldmi(ctx, "divu", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
@@ -1089,8 +1074,7 @@ static bool trans_FADD_ir(DisasContext *ctx, arg_FADD_ir *a)
 /* fadd rs, rd */
 static bool trans_FADD_mr(DisasContext *ctx, arg_FADD_mr *a)
 {
-    prt("fadd\t");
-    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    prt_ldmi(ctx, "fadd", a->ld, RX_IM_LONG, a->rs, a->rd);
     return true;
 }
 
@@ -1105,8 +1089,7 @@ static bool trans_FCMP_ir(DisasContext *ctx, arg_FCMP_ir *a)
 /* fcmp rs, rd */
 static bool trans_FCMP_mr(DisasContext *ctx, arg_FCMP_mr *a)
 {
-    prt("fcmp\t");
-    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    prt_ldmi(ctx, "fcmp", a->ld, RX_IM_LONG, a->rs, a->rd);
     return true;
 }
 
@@ -1121,8 +1104,7 @@ static bool trans_FSUB_ir(DisasContext *ctx, arg_FSUB_ir *a)
 /* fsub rs, rd */
 static bool trans_FSUB_mr(DisasContext *ctx, arg_FSUB_mr *a)
 {
-    prt("fsub\t");
-    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    prt_ldmi(ctx, "fsub", a->ld, RX_IM_LONG, a->rs, a->rd);
     return true;
 }
 
@@ -1130,8 +1112,7 @@ static bool trans_FSUB_mr(DisasContext *ctx, arg_FSUB_mr *a)
 /* ftoi rs, rd */
 static bool trans_FTOI(DisasContext *ctx, arg_FTOI *a)
 {
-    prt("ftoi\t");
-    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    prt_ldmi(ctx, "ftoi", a->ld, RX_IM_LONG, a->rs, a->rd);
     return true;
 }
 
@@ -1146,8 +1127,7 @@ static bool trans_FMUL_ir(DisasContext *ctx, arg_FMUL_ir *a)
 /* fmul rs, rd */
 static bool trans_FMUL_mr(DisasContext *ctx, arg_FMUL_mr *a)
 {
-    prt("fmul\t");
-    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    prt_ldmi(ctx, "fmul", a->ld, RX_IM_LONG, a->rs, a->rd);
     return true;
 }
 
@@ -1162,8 +1142,7 @@ static bool trans_FDIV_ir(DisasContext *ctx, arg_FDIV_ir *a)
 /* fdiv rs, rd */
 static bool trans_FDIV_mr(DisasContext *ctx, arg_FDIV_mr *a)
 {
-    prt("fdiv\t");
-    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    prt_ldmi(ctx, "fdiv", a->ld, RX_IM_LONG, a->rs, a->rd);
     return true;
 }
 
@@ -1171,8 +1150,7 @@ static bool trans_FDIV_mr(DisasContext *ctx, arg_FDIV_mr *a)
 /* round rs, rd */
 static bool trans_ROUND(DisasContext *ctx, arg_ROUND *a)
 {
-    prt("round\t");
-    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    prt_ldmi(ctx, "round", a->ld, RX_IM_LONG, a->rs, a->rd);
     return true;
 }
 
@@ -1180,8 +1158,7 @@ static bool trans_ROUND(DisasContext *ctx, arg_ROUND *a)
 /* itof dsp[rs], rd */
 static bool trans_ITOF(DisasContext *ctx, arg_ITOF *a)
 {
-    prt("itof\t");
-    operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+    prt_ldmi(ctx, "itof", a->ld, RX_IM_LONG, a->rs, a->rd);
     return true;
 }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 10/22] target/rx: Use prt_ldmi for XCHG_mr disassembly
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (8 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 09/22] target/rx: Replace operand with prt_ldmi in disassembler Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 11/22] target/rx: Emit all disassembly in one prt() Yoshinori Sato
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, Richard Henderson, Yoshinori Sato, philmd

From: Richard Henderson <richard.henderson@linaro.org>

Note that the ld == 3 case handled by prt_ldmi is decoded as
XCHG_rr and cannot appear here.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Message-Id: <20190607091116.49044-21-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/rx/disas.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/target/rx/disas.c b/target/rx/disas.c
index 515b365528..db10385fd0 100644
--- a/target/rx/disas.c
+++ b/target/rx/disas.c
@@ -366,13 +366,7 @@ static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr *a)
 /* xchg dsp[rs].<mi>,rd */
 static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a)
 {
-    static const char msize[][4] = {
-        "b", "w", "l", "ub", "uw",
-    };
-    char dsp[8];
-
-    rx_index_addr(ctx, dsp, a->ld, a->mi);
-    prt("xchg\t%s[r%d].%s, r%d", dsp, a->rs, msize[a->mi], a->rd);
+    prt_ldmi(ctx, "xchg", a->ld, a->mi, a->rs, a->rd);
     return true;
 }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 11/22] target/rx: Emit all disassembly in one prt()
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (9 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 10/22] target/rx: Use prt_ldmi for XCHG_mr disassembly Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 12/22] target/rx: Collect all bytes during disassembly Yoshinori Sato
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, Richard Henderson, Yoshinori Sato, philmd

From: Richard Henderson <richard.henderson@linaro.org>

Many of the multi-part prints have been eliminated by previous
patches.  Eliminate the rest of them.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Message-Id: <20190607091116.49044-22-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/rx/disas.c | 75 ++++++++++++++++++++++++-----------------------
 1 file changed, 39 insertions(+), 36 deletions(-)

diff --git a/target/rx/disas.c b/target/rx/disas.c
index db10385fd0..ebc1a44249 100644
--- a/target/rx/disas.c
+++ b/target/rx/disas.c
@@ -228,24 +228,21 @@ static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a)
 /* mov.[bwl] rs,rd */
 static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a)
 {
-    char dspd[8], dsps[8];
+    char dspd[8], dsps[8], szc = size[a->sz];
 
-    prt("mov.%c\t", size[a->sz]);
     if (a->lds == 3 && a->ldd == 3) {
         /* mov.[bwl] rs,rd */
-        prt("r%d, r%d", a->rs, a->rd);
-        return true;
-    }
-    if (a->lds == 3) {
+        prt("mov.%c\tr%d, r%d", szc, a->rs, a->rd);
+    } else if (a->lds == 3) {
         rx_index_addr(ctx, dspd, a->ldd, a->sz);
-        prt("r%d, %s[r%d]", a->rs, dspd, a->rd);
+        prt("mov.%c\tr%d, %s[r%d]", szc, a->rs, dspd, a->rd);
     } else if (a->ldd == 3) {
         rx_index_addr(ctx, dsps, a->lds, a->sz);
-        prt("%s[r%d], r%d", dsps, a->rs, a->rd);
+        prt("mov.%c\t%s[r%d], r%d", szc, dsps, a->rs, a->rd);
     } else {
         rx_index_addr(ctx, dsps, a->lds, a->sz);
         rx_index_addr(ctx, dspd, a->ldd, a->sz);
-        prt("%s[r%d], %s[r%d]", dsps, a->rs, dspd, a->rd);
+        prt("mov.%c\t%s[r%d], %s[r%d]", szc, dsps, a->rs, dspd, a->rd);
     }
     return true;
 }
@@ -254,8 +251,11 @@ static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a)
 /* mov.[bwl] rs,[-rd] */
 static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a)
 {
-    prt("mov.%c\tr%d, ", size[a->sz], a->rs);
-    prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd);
+    if (a->ad) {
+        prt("mov.%c\tr%d, [-r%d]", size[a->sz], a->rs, a->rd);
+    } else {
+        prt("mov.%c\tr%d, [r%d+]", size[a->sz], a->rs, a->rd);
+    }
     return true;
 }
 
@@ -263,9 +263,11 @@ static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a)
 /* mov.[bwl] [-rd],rs */
 static bool trans_MOV_pr(DisasContext *ctx, arg_MOV_pr *a)
 {
-    prt("mov.%c\t", size[a->sz]);
-    prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd);
-    prt(", r%d", a->rs);
+    if (a->ad) {
+        prt("mov.%c\t[-r%d], r%d", size[a->sz], a->rd, a->rs);
+    } else {
+        prt("mov.%c\t[r%d+], r%d", size[a->sz], a->rd, a->rs);
+    }
     return true;
 }
 
@@ -299,9 +301,11 @@ static bool trans_MOVU_ar(DisasContext *ctx, arg_MOVU_ar *a)
 /* movu.[bw] [-rs],rd */
 static bool trans_MOVU_pr(DisasContext *ctx, arg_MOVU_pr *a)
 {
-    prt("movu.%c\t", size[a->sz]);
-    prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd);
-    prt(", r%d", a->rs);
+    if (a->ad) {
+        prt("movu.%c\t[-r%d], r%d", size[a->sz], a->rd, a->rs);
+    } else {
+        prt("movu.%c\t[r%d+], r%d", size[a->sz], a->rd, a->rs);
+    }
     return true;
 }
 
@@ -478,11 +482,11 @@ static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *a)
 /* not rs, rd */
 static bool trans_NOT_rr(DisasContext *ctx, arg_NOT_rr *a)
 {
-    prt("not\t");
     if (a->rs != a->rd) {
-        prt("r%d, ", a->rs);
+        prt("not\tr%d, r%d", a->rs, a->rd);
+    } else {
+        prt("not\tr%d", a->rs);
     }
-    prt("r%d", a->rd);
     return true;
 }
 
@@ -490,11 +494,11 @@ static bool trans_NOT_rr(DisasContext *ctx, arg_NOT_rr *a)
 /* neg rs, rd */
 static bool trans_NEG_rr(DisasContext *ctx, arg_NEG_rr *a)
 {
-    prt("neg\t");
     if (a->rs != a->rd) {
-        prt("r%d, ", a->rs);
+        prt("neg\tr%d, r%d", a->rs, a->rd);
+    } else {
+        prt("neg\tr%d", a->rs);
     }
-    prt("r%d", a->rd);
     return true;
 }
 
@@ -606,11 +610,10 @@ static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a)
 /* abs rs, rd */
 static bool trans_ABS_rr(DisasContext *ctx, arg_ABS_rr *a)
 {
-    prt("abs\t");
-    if (a->rs == a->rd) {
-        prt("r%d", a->rd);
+    if (a->rs != a->rd) {
+        prt("abs\tr%d, r%d", a->rs, a->rd);
     } else {
-        prt("r%d, r%d", a->rs, a->rd);
+        prt("abs\tr%d", a->rs);
     }
     return true;
 }
@@ -733,11 +736,11 @@ static bool trans_DIVU_mr(DisasContext *ctx, arg_DIVU_mr *a)
 /* shll #imm:5, rs, rd */
 static bool trans_SHLL_irr(DisasContext *ctx, arg_SHLL_irr *a)
 {
-    prt("shll\t#%d, ", a->imm);
     if (a->rs2 != a->rd) {
-        prt("r%d, ", a->rs2);
+        prt("shll\t#%d, r%d, r%d", a->imm, a->rs2, a->rd);
+    } else {
+        prt("shll\t#%d, r%d", a->imm, a->rd);
     }
-    prt("r%d", a->rd);
     return true;
 }
 
@@ -752,11 +755,11 @@ static bool trans_SHLL_rr(DisasContext *ctx, arg_SHLL_rr *a)
 /* shar #imm:5, rs, rd */
 static bool trans_SHAR_irr(DisasContext *ctx, arg_SHAR_irr *a)
 {
-    prt("shar\t#%d,", a->imm);
     if (a->rs2 != a->rd) {
-        prt("r%d, ", a->rs2);
+        prt("shar\t#%d, r%d, r%d", a->imm, a->rs2, a->rd);
+    } else {
+        prt("shar\t#%d, r%d", a->imm, a->rd);
     }
-    prt("r%d", a->rd);
     return true;
 }
 
@@ -771,11 +774,11 @@ static bool trans_SHAR_rr(DisasContext *ctx, arg_SHAR_rr *a)
 /* shlr #imm:5, rs, rd */
 static bool trans_SHLR_irr(DisasContext *ctx, arg_SHLR_irr *a)
 {
-    prt("shlr\t#%d, ", a->imm);
     if (a->rs2 != a->rd) {
-        prt("r%d, ", a->rs2);
+        prt("shlr\t#%d, r%d, r%d", a->imm, a->rs2, a->rd);
+    } else {
+        prt("shlr\t#%d, r%d", a->imm, a->rd);
     }
-    prt("r%d", a->rd);
     return true;
 }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 12/22] target/rx: Collect all bytes during disassembly
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (10 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 11/22] target/rx: Emit all disassembly in one prt() Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 13/22] target/rx: Dump bytes for each insn " Yoshinori Sato
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, Richard Henderson, Yoshinori Sato, philmd

From: Richard Henderson <richard.henderson@linaro.org>

Collected, to be used in the next patch.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Message-Id: <20190607091116.49044-23-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/rx/disas.c | 62 ++++++++++++++++++++++++++++++++---------------
 1 file changed, 42 insertions(+), 20 deletions(-)

diff --git a/target/rx/disas.c b/target/rx/disas.c
index ebc1a44249..5a32a87534 100644
--- a/target/rx/disas.c
+++ b/target/rx/disas.c
@@ -25,43 +25,59 @@ typedef struct DisasContext {
     disassemble_info *dis;
     uint32_t addr;
     uint32_t pc;
+    uint8_t len;
+    uint8_t bytes[8];
 } DisasContext;
 
 
 static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn,
-                           int i, int n)
+                                  int i, int n)
 {
-    bfd_byte buf;
+    uint32_t addr = ctx->addr;
+
+    g_assert(ctx->len == i);
+    g_assert(n <= ARRAY_SIZE(ctx->bytes));
+
     while (++i <= n) {
-        ctx->dis->read_memory_func(ctx->addr++, &buf, 1, ctx->dis);
-        insn |= buf << (32 - i * 8);
+        ctx->dis->read_memory_func(addr++, &ctx->bytes[i - 1], 1, ctx->dis);
+        insn |= ctx->bytes[i - 1] << (32 - i * 8);
     }
+    ctx->addr = addr;
+    ctx->len = n;
+
     return insn;
 }
 
 static int32_t li(DisasContext *ctx, int sz)
 {
-    int32_t addr;
-    bfd_byte buf[4];
-    addr = ctx->addr;
+    uint32_t addr = ctx->addr;
+    uintptr_t len = ctx->len;
 
     switch (sz) {
     case 1:
+        g_assert(len + 1 <= ARRAY_SIZE(ctx->bytes));
         ctx->addr += 1;
-        ctx->dis->read_memory_func(addr, buf, 1, ctx->dis);
-        return (int8_t)buf[0];
+        ctx->len += 1;
+        ctx->dis->read_memory_func(addr, ctx->bytes + len, 1, ctx->dis);
+        return (int8_t)ctx->bytes[len];
     case 2:
+        g_assert(len + 2 <= ARRAY_SIZE(ctx->bytes));
         ctx->addr += 2;
-        ctx->dis->read_memory_func(addr, buf, 2, ctx->dis);
-        return ldsw_le_p(buf);
+        ctx->len += 2;
+        ctx->dis->read_memory_func(addr, ctx->bytes + len, 2, ctx->dis);
+        return ldsw_le_p(ctx->bytes + len);
     case 3:
+        g_assert(len + 3 <= ARRAY_SIZE(ctx->bytes));
         ctx->addr += 3;
-        ctx->dis->read_memory_func(addr, buf, 3, ctx->dis);
-        return (int8_t)buf[2] << 16 | lduw_le_p(buf);
+        ctx->len += 3;
+        ctx->dis->read_memory_func(addr, ctx->bytes + len, 3, ctx->dis);
+        return (int8_t)ctx->bytes[len + 2] << 16 | lduw_le_p(ctx->bytes + len);
     case 0:
+        g_assert(len + 4 <= ARRAY_SIZE(ctx->bytes));
         ctx->addr += 4;
-        ctx->dis->read_memory_func(addr, buf, 4, ctx->dis);
-        return ldl_le_p(buf);
+        ctx->len += 4;
+        ctx->dis->read_memory_func(addr, ctx->bytes + len, 4, ctx->dis);
+        return ldl_le_p(ctx->bytes + len);
     default:
         g_assert_not_reached();
     }
@@ -110,7 +126,7 @@ static const char psw[] = {
 static void rx_index_addr(DisasContext *ctx, char out[8], int ld, int mi)
 {
     uint32_t addr = ctx->addr;
-    uint8_t buf[2];
+    uintptr_t len = ctx->len;
     uint16_t dsp;
 
     switch (ld) {
@@ -119,14 +135,18 @@ static void rx_index_addr(DisasContext *ctx, char out[8], int ld, int mi)
         out[0] = '\0';
         return;
     case 1:
+        g_assert(len + 1 <= ARRAY_SIZE(ctx->bytes));
         ctx->addr += 1;
-        ctx->dis->read_memory_func(addr, buf, 1, ctx->dis);
-        dsp = buf[0];
+        ctx->len += 1;
+        ctx->dis->read_memory_func(addr, ctx->bytes + len, 1, ctx->dis);
+        dsp = ctx->bytes[len];
         break;
     case 2:
+        g_assert(len + 2 <= ARRAY_SIZE(ctx->bytes));
         ctx->addr += 2;
-        ctx->dis->read_memory_func(addr, buf, 2, ctx->dis);
-        dsp = lduw_le_p(buf);
+        ctx->len += 2;
+        ctx->dis->read_memory_func(addr, ctx->bytes + len, 2, ctx->dis);
+        dsp = lduw_le_p(ctx->bytes + len);
         break;
     default:
         g_assert_not_reached();
@@ -1392,8 +1412,10 @@ int print_insn_rx(bfd_vma addr, disassemble_info *dis)
     DisasContext ctx;
     uint32_t insn;
     int i;
+
     ctx.dis = dis;
     ctx.pc = ctx.addr = addr;
+    ctx.len = 0;
 
     insn = decode_load(&ctx);
     if (!decode(&ctx, insn)) {
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 13/22] target/rx: Dump bytes for each insn during disassembly
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (11 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 12/22] target/rx: Collect all bytes during disassembly Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 14/22] hw/intc: RX62N interrupt controller (ICUa) Yoshinori Sato
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, Richard Henderson, Yoshinori Sato, philmd

From: Richard Henderson <richard.henderson@linaro.org>

There are so many different forms of each RX instruction
that it will be very useful to be able to look at the bytes
to see on which path a bug may lie.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Message-Id: <20190607091116.49044-24-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/rx/disas.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/target/rx/disas.c b/target/rx/disas.c
index 5a32a87534..d73b53db44 100644
--- a/target/rx/disas.c
+++ b/target/rx/disas.c
@@ -102,7 +102,21 @@ static int bdsp_s(DisasContext *ctx, int d)
 /* Include the auto-generated decoder.  */
 #include "decode.inc.c"
 
-#define prt(...) (ctx->dis->fprintf_func)((ctx->dis->stream), __VA_ARGS__)
+static void dump_bytes(DisasContext *ctx)
+{
+    int i, len = ctx->len;
+
+    for (i = 0; i < len; ++i) {
+        ctx->dis->fprintf_func(ctx->dis->stream, "%02x ", ctx->bytes[i]);
+    }
+    ctx->dis->fprintf_func(ctx->dis->stream, "%*c", (8 - i) * 3, '\t');
+}
+
+#define prt(...) \
+    do {                                                        \
+        dump_bytes(ctx);                                        \
+        ctx->dis->fprintf_func(ctx->dis->stream, __VA_ARGS__);  \
+    } while (0)
 
 #define RX_MEMORY_BYTE 0
 #define RX_MEMORY_WORD 1
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 14/22] hw/intc: RX62N interrupt controller (ICUa)
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (12 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 13/22] target/rx: Dump bytes for each insn " Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 15/22] hw/timer: RX62N internal timer modules Yoshinori Sato
                   ` (13 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Yoshinori Sato, philmd, richard.henderson,
	imammedo, Alex Bennée

This implementation supported only ICUa.
Hardware manual.
https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej0140_rx62n.pdf

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20190607091116.49044-6-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/hw/intc/rx_icu.h |  56 ++++++
 hw/intc/rx_icu.c         | 379 +++++++++++++++++++++++++++++++++++++++
 hw/intc/Kconfig          |   3 +
 hw/intc/Makefile.objs    |   1 +
 4 files changed, 439 insertions(+)
 create mode 100644 include/hw/intc/rx_icu.h
 create mode 100644 hw/intc/rx_icu.c

diff --git a/include/hw/intc/rx_icu.h b/include/hw/intc/rx_icu.h
new file mode 100644
index 0000000000..acfcf06aef
--- /dev/null
+++ b/include/hw/intc/rx_icu.h
@@ -0,0 +1,56 @@
+#ifndef RX_ICU_H
+#define RX_ICU_H
+
+#include "qemu-common.h"
+#include "hw/irq.h"
+
+enum TRG_MODE {
+    TRG_LEVEL = 0,
+    TRG_NEDGE = 1,      /* Falling */
+    TRG_PEDGE = 2,      /* Raising */
+    TRG_BEDGE = 3,      /* Both */
+};
+
+struct IRQSource {
+    enum TRG_MODE sense;
+    int level;
+};
+
+enum {
+    /* Software interrupt request */
+    SWI = 27,
+    NR_IRQS = 256,
+};
+
+struct RXICUState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion memory;
+    struct IRQSource src[NR_IRQS];
+    char *icutype;
+    uint32_t nr_irqs;
+    uint32_t *map;
+    uint32_t nr_sense;
+    uint32_t *init_sense;
+
+    uint8_t ir[NR_IRQS];
+    uint8_t dtcer[NR_IRQS];
+    uint8_t ier[NR_IRQS / 8];
+    uint8_t ipr[142];
+    uint8_t dmasr[4];
+    uint16_t fir;
+    uint8_t nmisr;
+    uint8_t nmier;
+    uint8_t nmiclr;
+    uint8_t nmicr;
+    int req_irq;
+    qemu_irq _irq;
+    qemu_irq _fir;
+    qemu_irq _swi;
+};
+typedef struct RXICUState RXICUState;
+
+#define TYPE_RXICU "rx-icu"
+#define RXICU(obj) OBJECT_CHECK(RXICUState, (obj), TYPE_RXICU)
+
+#endif /* RX_ICU_H */
diff --git a/hw/intc/rx_icu.c b/hw/intc/rx_icu.c
new file mode 100644
index 0000000000..ac4dcbfe37
--- /dev/null
+++ b/hw/intc/rx_icu.c
@@ -0,0 +1,379 @@
+/*
+ * RX Interrupt Control Unit
+ *
+ * Warning: Only ICUa is supported.
+ *
+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
+ * (Rev.1.40 R01UH0033EJ0140)
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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/irq.h"
+#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "hw/qdev-properties.h"
+#include "hw/intc/rx_icu.h"
+#include "migration/vmstate.h"
+#include "qemu/error-report.h"
+
+REG8(IR, 0)
+  FIELD(IR, IR,  0, 1)
+REG8(DTCER, 0x100)
+  FIELD(DTCER, DTCE,  0, 1)
+REG8(IER, 0x200)
+REG8(SWINTR, 0x2e0)
+  FIELD(SWINTR, SWINT, 0, 1)
+REG16(FIR, 0x2f0)
+  FIELD(FIR, FVCT, 0, 8)
+  FIELD(FIR, FIEN, 15, 1)
+REG8(IPR, 0x300)
+  FIELD(IPR, IPR, 0, 4)
+REG8(DMRSR, 0x400)
+REG8(IRQCR, 0x500)
+  FIELD(IRQCR, IRQMD, 2, 2)
+REG8(NMISR, 0x580)
+  FIELD(NMISR, NMIST, 0, 1)
+  FIELD(NMISR, LVDST, 1, 1)
+  FIELD(NMISR, OSTST, 2, 1)
+REG8(NMIER, 0x581)
+  FIELD(NMIER, NMIEN, 0, 1)
+  FIELD(NMIER, LVDEN, 1, 1)
+  FIELD(NMIER, OSTEN, 2, 1)
+REG8(NMICLR, 0x582)
+  FIELD(NMICLR, NMICLR, 0, 1)
+  FIELD(NMICLR, OSTCLR, 2, 1)
+REG8(NMICR, 0x583)
+  FIELD(NMICR, NMIMD, 3, 1)
+
+#define request(icu, n) (icu->ipr[icu->map[n]] << 8 | n)
+
+static void set_irq(RXICUState *icu, int n_IRQ, int req)
+{
+    if ((icu->fir & R_FIR_FIEN_MASK) &&
+        (icu->fir & R_FIR_FVCT_MASK) == n_IRQ) {
+        qemu_set_irq(icu->_fir, req);
+    } else {
+        qemu_set_irq(icu->_irq, req);
+    }
+}
+
+static void rxicu_request(RXICUState *icu, int n_IRQ)
+{
+    int enable;
+
+    enable = icu->ier[n_IRQ / 8] & (1 << (n_IRQ & 7));
+    if (n_IRQ > 0 && enable != 0 && atomic_read(&icu->req_irq) < 0) {
+        atomic_set(&icu->req_irq, n_IRQ);
+        set_irq(icu, n_IRQ, request(icu, n_IRQ));
+    }
+}
+
+static void rxicu_set_irq(void *opaque, int n_IRQ, int level)
+{
+    RXICUState *icu = opaque;
+    struct IRQSource *src;
+    int issue;
+
+    if (n_IRQ >= NR_IRQS) {
+        error_report("%s: IRQ %d out of range", __func__, n_IRQ);
+        return;
+    }
+
+    src = &icu->src[n_IRQ];
+
+    level = (level != 0);
+    switch (src->sense) {
+    case TRG_LEVEL:
+        /* level-sensitive irq */
+        issue = level;
+        src->level = level;
+        break;
+    case TRG_NEDGE:
+        issue = (level == 0 && src->level == 1);
+        src->level = level;
+        break;
+    case TRG_PEDGE:
+        issue = (level == 1 && src->level == 0);
+        src->level = level;
+        break;
+    case TRG_BEDGE:
+        issue = ((level ^ src->level) & 1);
+        src->level = level;
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    if (issue == 0 && src->sense == TRG_LEVEL) {
+        icu->ir[n_IRQ] = 0;
+        if (atomic_read(&icu->req_irq) == n_IRQ) {
+            /* clear request */
+            set_irq(icu, n_IRQ, 0);
+            atomic_set(&icu->req_irq, -1);
+        }
+        return;
+    }
+    if (issue) {
+        icu->ir[n_IRQ] = 1;
+        rxicu_request(icu, n_IRQ);
+    }
+}
+
+static void rxicu_ack_irq(void *opaque, int no, int level)
+{
+    RXICUState *icu = opaque;
+    int i;
+    int n_IRQ;
+    int max_pri;
+
+    n_IRQ = atomic_read(&icu->req_irq);
+    if (n_IRQ < 0) {
+        return;
+    }
+    atomic_set(&icu->req_irq, -1);
+    if (icu->src[n_IRQ].sense != TRG_LEVEL) {
+        icu->ir[n_IRQ] = 0;
+    }
+
+    max_pri = 0;
+    n_IRQ = -1;
+    for (i = 0; i < NR_IRQS; i++) {
+        if (icu->ir[i]) {
+            if (max_pri < icu->ipr[icu->map[i]]) {
+                n_IRQ = i;
+                max_pri = icu->ipr[icu->map[i]];
+            }
+        }
+    }
+
+    if (n_IRQ >= 0) {
+        rxicu_request(icu, n_IRQ);
+    }
+}
+
+static uint64_t icu_read(void *opaque, hwaddr addr, unsigned size)
+{
+    RXICUState *icu = opaque;
+    int reg = addr & 0xff;
+
+    if ((addr != A_FIR && size != 1) ||
+        (addr == A_FIR && size != 2)) {
+        qemu_log_mask(LOG_GUEST_ERROR, "rx_icu: Invalid read size 0x%"
+                      HWADDR_PRIX "\n", addr);
+        return UINT64_MAX;
+    }
+    switch (addr) {
+    case A_IR ... A_IR + 0xff:
+        return icu->ir[reg] & R_IR_IR_MASK;
+    case A_DTCER ... A_DTCER + 0xff:
+        return icu->dtcer[reg] & R_DTCER_DTCE_MASK;
+    case A_IER ... A_IER + 0x1f:
+        return icu->ier[reg];
+    case A_SWINTR:
+        return 0;
+    case A_FIR:
+        return icu->fir & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK);
+    case A_IPR ... A_IPR + 0x8f:
+        return icu->ipr[reg] & R_IPR_IPR_MASK;
+    case A_DMRSR:
+    case A_DMRSR + 4:
+    case A_DMRSR + 8:
+    case A_DMRSR + 12:
+        return icu->dmasr[reg >> 2];
+    case A_IRQCR ... A_IRQCR + 0x1f:
+        return icu->src[64 + reg].sense << R_IRQCR_IRQMD_SHIFT;
+    case A_NMISR:
+    case A_NMICLR:
+        return 0;
+    case A_NMIER:
+        return icu->nmier;
+    case A_NMICR:
+        return icu->nmicr;
+    default:
+        qemu_log_mask(LOG_UNIMP, "rx_icu: Register 0x%" HWADDR_PRIX
+                      " not implemented.\n", addr);
+        break;
+    }
+    return UINT64_MAX;
+}
+
+static void icu_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+    RXICUState *icu = opaque;
+    int reg = addr & 0xff;
+
+    if ((addr != A_FIR && size != 1) ||
+        (addr == A_FIR && size != 2)) {
+        qemu_log_mask(LOG_GUEST_ERROR, "rx_icu: Invalid write size at 0x%"
+                      HWADDR_PRIX "\n", addr);
+        return;
+    }
+    switch (addr) {
+    case A_IR ... A_IR + 0xff:
+        if (icu->src[reg].sense != TRG_LEVEL && val == 0) {
+            icu->ir[reg] = 0;
+        }
+        break;
+    case A_DTCER ... A_DTCER + 0xff:
+        icu->dtcer[reg] = val & R_DTCER_DTCE_MASK;
+        qemu_log_mask(LOG_UNIMP,
+                      "rx_icu: DTC not implemented\n");
+        break;
+    case A_IER ... A_IER + 0x1f:
+        icu->ier[reg] = val;
+        break;
+    case A_SWINTR:
+        if (val & R_SWINTR_SWINT_MASK) {
+            qemu_irq_pulse(icu->_swi);
+        }
+        break;
+    case A_FIR:
+        icu->fir = val & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK);
+        break;
+    case A_IPR ... A_IPR + 0x8f:
+        icu->ipr[reg] = val & R_IPR_IPR_MASK;
+        break;
+    case A_DMRSR:
+    case A_DMRSR + 4:
+    case A_DMRSR + 8:
+    case A_DMRSR + 12:
+        icu->dmasr[reg >> 2] = val;
+        qemu_log_mask(LOG_UNIMP,
+                      "rx_icu: DMAC not implemented\n");
+        break;
+    case A_IRQCR ... A_IRQCR + 0x1f:
+        icu->src[64 + reg].sense = val >> R_IRQCR_IRQMD_SHIFT;
+        break;
+    case A_NMICLR:
+        break;
+    case A_NMIER:
+        icu->nmier |= val & (R_NMIER_NMIEN_MASK |
+                             R_NMIER_LVDEN_MASK |
+                             R_NMIER_OSTEN_MASK);
+            break;
+    case A_NMICR:
+        if ((icu->nmier & R_NMIER_NMIEN_MASK) == 0) {
+            icu->nmicr = val & R_NMICR_NMIMD_MASK;
+        }
+        break;
+    default:
+        qemu_log_mask(LOG_UNIMP, "rx_icu: Register 0x%" HWADDR_PRIX
+                      " not implemented\n", addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps icu_ops = {
+    .write = icu_write,
+    .read  = icu_read,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .max_access_size = 2,
+    },
+};
+
+static void rxicu_realize(DeviceState *dev, Error **errp)
+{
+    RXICUState *icu = RXICU(dev);
+    int i, j;
+
+    if (icu->init_sense == NULL) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "rx_icu: trigger-level property must be set.");
+        return;
+    }
+    for (i = j = 0; i < NR_IRQS; i++) {
+        if (icu->init_sense[j] == i) {
+            icu->src[i].sense = TRG_LEVEL;
+            if (j < icu->nr_sense) {
+                j++;
+            }
+        } else {
+            icu->src[i].sense = TRG_PEDGE;
+        }
+    }
+    icu->req_irq = -1;
+}
+
+static void rxicu_init(Object *obj)
+{
+    SysBusDevice *d = SYS_BUS_DEVICE(obj);
+    RXICUState *icu = RXICU(obj);
+
+    memory_region_init_io(&icu->memory, OBJECT(icu), &icu_ops,
+                          icu, "rx-icu", 0x600);
+    sysbus_init_mmio(d, &icu->memory);
+
+    qdev_init_gpio_in(DEVICE(d), rxicu_set_irq, NR_IRQS);
+    qdev_init_gpio_in_named(DEVICE(d), rxicu_ack_irq, "ack", 1);
+    sysbus_init_irq(d, &icu->_irq);
+    sysbus_init_irq(d, &icu->_fir);
+    sysbus_init_irq(d, &icu->_swi);
+}
+
+static void rxicu_fini(Object *obj)
+{
+    RXICUState *icu = RXICU(obj);
+    g_free(icu->map);
+    g_free(icu->init_sense);
+}
+
+static const VMStateDescription vmstate_rxicu = {
+    .name = "rx-icu",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property rxicu_properties[] = {
+    DEFINE_PROP_ARRAY("ipr-map", RXICUState, nr_irqs, map,
+                      qdev_prop_uint32, uint32_t),
+    DEFINE_PROP_ARRAY("trigger-level", RXICUState, nr_sense, init_sense,
+                      qdev_prop_uint32, uint32_t),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void rxicu_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = rxicu_realize;
+    dc->props = rxicu_properties;
+    dc->vmsd = &vmstate_rxicu;
+}
+
+static const TypeInfo rxicu_info = {
+    .name       = TYPE_RXICU,
+    .parent     = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(RXICUState),
+    .instance_init = rxicu_init,
+    .instance_finalize = rxicu_fini,
+    .class_init = rxicu_class_init,
+};
+
+static void rxicu_register_types(void)
+{
+    type_register_static(&rxicu_info);
+}
+
+type_init(rxicu_register_types)
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 5347f8412c..67e9d97464 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -58,3 +58,6 @@ config S390_FLIC_KVM
 
 config OMPIC
     bool
+
+config RX_ICU
+    bool
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index f726d87532..f17cbd1a9f 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -49,3 +49,4 @@ obj-$(CONFIG_ARM_GIC) += arm_gicv3_cpuif.o
 obj-$(CONFIG_MIPS_CPS) += mips_gic.o
 obj-$(CONFIG_NIOS2) += nios2_iic.o
 obj-$(CONFIG_OMPIC) += ompic.o
+obj-$(CONFIG_RX) += rx_icu.o
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 15/22] hw/timer: RX62N internal timer modules
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (13 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 14/22] hw/intc: RX62N interrupt controller (ICUa) Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 16/22] hw/char: RX62N serial communication interface (SCI) Yoshinori Sato
                   ` (12 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Yoshinori Sato, philmd, richard.henderson,
	imammedo, Alex Bennée

renesas_tmr: 8bit timer modules.
renesas_cmt: 16bit compare match timer modules.
This part use many renesas's CPU.
Hardware manual.
https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej0140_rx62n.pdf

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20190607091116.49044-7-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/hw/timer/renesas_cmt.h |  38 +++
 include/hw/timer/renesas_tmr.h |  53 ++++
 hw/timer/renesas_cmt.c         | 278 ++++++++++++++++++++
 hw/timer/renesas_tmr.c         | 458 +++++++++++++++++++++++++++++++++
 hw/timer/Kconfig               |   6 +
 hw/timer/Makefile.objs         |   3 +
 6 files changed, 836 insertions(+)
 create mode 100644 include/hw/timer/renesas_cmt.h
 create mode 100644 include/hw/timer/renesas_tmr.h
 create mode 100644 hw/timer/renesas_cmt.c
 create mode 100644 hw/timer/renesas_tmr.c

diff --git a/include/hw/timer/renesas_cmt.h b/include/hw/timer/renesas_cmt.h
new file mode 100644
index 0000000000..acd25c6e0b
--- /dev/null
+++ b/include/hw/timer/renesas_cmt.h
@@ -0,0 +1,38 @@
+/*
+ * Renesas Compare-match timer Object
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This code is licensed under the GPL version 2 or later.
+ *
+ */
+
+#ifndef HW_RENESAS_CMT_H
+#define HW_RENESAS_CMT_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_RENESAS_CMT "renesas-cmt"
+#define RCMT(obj) OBJECT_CHECK(RCMTState, (obj), TYPE_RENESAS_CMT)
+
+enum {
+    CMT_CH = 2,
+    CMT_NR_IRQ = 1 * CMT_CH,
+};
+
+typedef struct RCMTState {
+    SysBusDevice parent_obj;
+
+    uint64_t input_freq;
+    MemoryRegion memory;
+
+    uint16_t cmstr;
+    uint16_t cmcr[CMT_CH];
+    uint16_t cmcnt[CMT_CH];
+    uint16_t cmcor[CMT_CH];
+    int64_t tick[CMT_CH];
+    qemu_irq cmi[CMT_CH];
+    QEMUTimer *timer[CMT_CH];
+} RCMTState;
+
+#endif
diff --git a/include/hw/timer/renesas_tmr.h b/include/hw/timer/renesas_tmr.h
new file mode 100644
index 0000000000..5787004c74
--- /dev/null
+++ b/include/hw/timer/renesas_tmr.h
@@ -0,0 +1,53 @@
+/*
+ * Renesas 8bit timer Object
+ *
+ * Copyright (c) 2018 Yoshinori Sato
+ *
+ * This code is licensed under the GPL version 2 or later.
+ *
+ */
+
+#ifndef HW_RENESAS_TMR_H
+#define HW_RENESAS_TMR_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_RENESAS_TMR "renesas-tmr"
+#define RTMR(obj) OBJECT_CHECK(RTMRState, (obj), TYPE_RENESAS_TMR)
+
+enum timer_event {
+    cmia = 0,
+    cmib = 1,
+    ovi = 2,
+    none = 3,
+    TMR_NR_EVENTS = 4
+};
+
+enum {
+    TMR_CH = 2,
+    TMR_NR_IRQ = 3 * TMR_CH,
+};
+
+typedef struct RTMRState {
+    SysBusDevice parent_obj;
+
+    uint64_t input_freq;
+    MemoryRegion memory;
+
+    uint8_t tcnt[TMR_CH];
+    uint8_t tcora[TMR_CH];
+    uint8_t tcorb[TMR_CH];
+    uint8_t tcr[TMR_CH];
+    uint8_t tccr[TMR_CH];
+    uint8_t tcor[TMR_CH];
+    uint8_t tcsr[TMR_CH];
+    int64_t tick;
+    int64_t div_round[TMR_CH];
+    enum timer_event next[TMR_CH];
+    qemu_irq cmia[TMR_CH];
+    qemu_irq cmib[TMR_CH];
+    qemu_irq ovi[TMR_CH];
+    QEMUTimer *timer[TMR_CH];
+} RTMRState;
+
+#endif
diff --git a/hw/timer/renesas_cmt.c b/hw/timer/renesas_cmt.c
new file mode 100644
index 0000000000..5d57c447b8
--- /dev/null
+++ b/hw/timer/renesas_cmt.c
@@ -0,0 +1,278 @@
+/*
+ * Renesas 16bit Compare-match timer
+ *
+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
+ * (Rev.1.40 R01UH0033EJ0140)
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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/irq.h"
+#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "hw/qdev-properties.h"
+#include "hw/timer/renesas_cmt.h"
+#include "migration/vmstate.h"
+#include "qemu/error-report.h"
+
+/*
+ *  +0 CMSTR - common control
+ *  +2 CMCR  - ch0
+ *  +4 CMCNT - ch0
+ *  +6 CMCOR - ch0
+ *  +8 CMCR  - ch1
+ * +10 CMCNT - ch1
+ * +12 CMCOR - ch1
+ * If we think that the address of CH 0 has an offset of +2,
+ * we can treat it with the same address as CH 1, so define it like that.
+ */
+REG16(CMSTR, 0)
+  FIELD(CMSTR, STR0, 0, 1)
+  FIELD(CMSTR, STR1, 1, 1)
+  FIELD(CMSTR, STR,  0, 2)
+/* This addeess is channel offset */
+REG16(CMCR, 0)
+  FIELD(CMCR, CKS, 0, 2)
+  FIELD(CMCR, CMIE, 6, 1)
+REG16(CMCNT, 2)
+REG16(CMCOR, 4)
+
+static void update_events(RCMTState *cmt, int ch)
+{
+    int64_t next_time;
+
+    if ((cmt->cmstr & (1 << ch)) == 0) {
+        /* count disable, so not happened next event. */
+        return ;
+    }
+    next_time = cmt->cmcor[ch] - cmt->cmcnt[ch];
+    next_time *= NANOSECONDS_PER_SECOND;
+    next_time /= cmt->input_freq;
+    /*
+     * CKS -> div rate
+     *  0 -> 8 (1 << 3)
+     *  1 -> 32 (1 << 5)
+     *  2 -> 128 (1 << 7)
+     *  3 -> 512 (1 << 9)
+     */
+    next_time *= 1 << (3 + FIELD_EX16(cmt->cmcr[ch], CMCR, CKS) * 2);
+    next_time += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+    timer_mod(cmt->timer[ch], next_time);
+}
+
+static int64_t read_cmcnt(RCMTState *cmt, int ch)
+{
+    int64_t delta, now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+
+    if (cmt->cmstr & (1 << ch)) {
+        delta = (now - cmt->tick[ch]);
+        delta /= NANOSECONDS_PER_SECOND;
+        delta /= cmt->input_freq;
+        delta /= 1 << (3 + FIELD_EX16(cmt->cmcr[ch], CMCR, CKS) * 2);
+        cmt->tick[ch] = now;
+        return cmt->cmcnt[ch] + delta;
+    } else {
+        return cmt->cmcnt[ch];
+    }
+}
+
+static uint64_t cmt_read(void *opaque, hwaddr addr, unsigned size)
+{
+    hwaddr offset = addr & 0x0f;
+    RCMTState *cmt = opaque;
+    int ch = offset / 0x08;
+    uint64_t ret;
+
+    if (offset == A_CMSTR) {
+        ret = 0;
+        ret = FIELD_DP16(ret, CMSTR, STR,
+                         FIELD_EX16(cmt->cmstr, CMSTR, STR));
+        return ret;
+    } else {
+        offset &= 0x07;
+        if (ch == 0) {
+            offset -= 0x02;
+        }
+        switch (offset) {
+        case A_CMCR:
+            ret = 0;
+            ret = FIELD_DP16(ret, CMCR, CKS,
+                             FIELD_EX16(cmt->cmstr, CMCR, CKS));
+            ret = FIELD_DP16(ret, CMCR, CMIE,
+                             FIELD_EX16(cmt->cmstr, CMCR, CMIE));
+            return ret;
+        case A_CMCNT:
+            return read_cmcnt(cmt, ch);
+        case A_CMCOR:
+            return cmt->cmcor[ch];
+        }
+    }
+    qemu_log_mask(LOG_UNIMP, "renesas_cmt: Register 0x%"
+                  HWADDR_PRIX " not implemented\n", offset);
+    return UINT64_MAX;
+}
+
+static void start_stop(RCMTState *cmt, int ch, int st)
+{
+    if (st) {
+        update_events(cmt, ch);
+    } else {
+        timer_del(cmt->timer[ch]);
+    }
+}
+
+static void cmt_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+    hwaddr offset = addr & 0x0f;
+    RCMTState *cmt = opaque;
+    int ch = offset / 0x08;
+
+    if (offset == A_CMSTR) {
+        cmt->cmstr = FIELD_EX16(val, CMSTR, STR);
+        start_stop(cmt, 0, FIELD_EX16(cmt->cmstr, CMSTR, STR0));
+        start_stop(cmt, 1, FIELD_EX16(cmt->cmstr, CMSTR, STR1));
+    } else {
+        offset &= 0x07;
+        if (ch == 0) {
+            offset -= 0x02;
+        }
+        switch (offset) {
+        case A_CMCR:
+            cmt->cmcr[ch] = FIELD_DP16(cmt->cmcr[ch], CMCR, CKS,
+                                       FIELD_EX16(val, CMCR, CKS));
+            cmt->cmcr[ch] = FIELD_DP16(cmt->cmcr[ch], CMCR, CMIE,
+                                       FIELD_EX16(val, CMCR, CMIE));
+            break;
+        case 2:
+            cmt->cmcnt[ch] = val;
+            break;
+        case 4:
+            cmt->cmcor[ch] = val;
+            break;
+        default:
+            qemu_log_mask(LOG_UNIMP, "renesas_cmt: Register -0x%" HWADDR_PRIX
+                          " not implemented\n", offset);
+            return;
+        }
+        if (FIELD_EX16(cmt->cmstr, CMSTR, STR) & (1 << ch)) {
+            update_events(cmt, ch);
+        }
+    }
+}
+
+static const MemoryRegionOps cmt_ops = {
+    .write = cmt_write,
+    .read  = cmt_read,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 2,
+        .max_access_size = 2,
+    },
+};
+
+static void timer_events(RCMTState *cmt, int ch)
+{
+    cmt->cmcnt[ch] = 0;
+    cmt->tick[ch] = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+    update_events(cmt, ch);
+    if (FIELD_EX16(cmt->cmcr[ch], CMCR, CMIE)) {
+        qemu_irq_pulse(cmt->cmi[ch]);
+    }
+}
+
+static void timer_event0(void *opaque)
+{
+    RCMTState *cmt = opaque;
+
+    timer_events(cmt, 0);
+}
+
+static void timer_event1(void *opaque)
+{
+    RCMTState *cmt = opaque;
+
+    timer_events(cmt, 1);
+}
+
+static void rcmt_reset(DeviceState *dev)
+{
+    RCMTState *cmt = RCMT(dev);
+    cmt->cmstr = 0;
+    cmt->cmcr[0] = cmt->cmcr[1] = 0;
+    cmt->cmcnt[0] = cmt->cmcnt[1] = 0;
+    cmt->cmcor[0] = cmt->cmcor[1] = 0xffff;
+}
+
+static void rcmt_init(Object *obj)
+{
+    SysBusDevice *d = SYS_BUS_DEVICE(obj);
+    RCMTState *cmt = RCMT(obj);
+    int i;
+
+    memory_region_init_io(&cmt->memory, OBJECT(cmt), &cmt_ops,
+                          cmt, "renesas-cmt", 0x10);
+    sysbus_init_mmio(d, &cmt->memory);
+
+    for (i = 0; i < ARRAY_SIZE(cmt->cmi); i++) {
+        sysbus_init_irq(d, &cmt->cmi[i]);
+    }
+    cmt->timer[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event0, cmt);
+    cmt->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event1, cmt);
+}
+
+static const VMStateDescription vmstate_rcmt = {
+    .name = "rx-cmt",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property rcmt_properties[] = {
+    DEFINE_PROP_UINT64("input-freq", RCMTState, input_freq, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void rcmt_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props = rcmt_properties;
+    dc->vmsd = &vmstate_rcmt;
+    dc->reset = rcmt_reset;
+}
+
+static const TypeInfo rcmt_info = {
+    .name       = TYPE_RENESAS_CMT,
+    .parent     = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(RCMTState),
+    .instance_init = rcmt_init,
+    .class_init = rcmt_class_init,
+};
+
+static void rcmt_register_types(void)
+{
+    type_register_static(&rcmt_info);
+}
+
+type_init(rcmt_register_types)
diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c
new file mode 100644
index 0000000000..eebdd0cb1f
--- /dev/null
+++ b/hw/timer/renesas_tmr.c
@@ -0,0 +1,458 @@
+/*
+ * Renesas 8bit timer
+ *
+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
+ * (Rev.1.40 R01UH0033EJ0140)
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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/irq.h"
+#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "hw/qdev-properties.h"
+#include "hw/timer/renesas_tmr.h"
+#include "migration/vmstate.h"
+#include "qemu/error-report.h"
+
+REG8(TCR, 0)
+  FIELD(TCR, CCLR, 3, 2)
+  FIELD(TCR, OVIE, 5, 1)
+  FIELD(TCR, CMIEA, 6, 1)
+  FIELD(TCR, CMIEB, 7, 1)
+REG8(TCSR, 2)
+  FIELD(TCSR, OSA, 0, 2)
+  FIELD(TCSR, OSB, 2, 2)
+  FIELD(TCSR, ADTE, 4, 2)
+REG8(TCORA, 4)
+REG8(TCORB, 6)
+REG8(TCNT, 8)
+REG8(TCCR, 10)
+  FIELD(TCCR, CKS, 0, 3)
+  FIELD(TCCR, CSS, 3, 2)
+  FIELD(TCCR, TMRIS, 7, 1)
+
+#define INTERNAL  0x01
+#define CASCADING 0x03
+#define CCLR_A    0x01
+#define CCLR_B    0x02
+
+static const int clkdiv[] = {0, 1, 2, 8, 32, 64, 1024, 8192};
+
+#define concat_reg(reg) ((reg[0] << 8) | reg[1])
+static void update_events(RTMRState *tmr, int ch)
+{
+    uint16_t diff[TMR_NR_EVENTS], min;
+    int64_t next_time;
+    int i, event;
+
+    if (tmr->tccr[ch] == 0) {
+        return ;
+    }
+    if (FIELD_EX8(tmr->tccr[ch], TCCR, CSS) == 0) {
+        /* external clock mode */
+        /* event not happened */
+        return ;
+    }
+    if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) == CASCADING) {
+        /* cascading mode */
+        if (ch == 1) {
+            tmr->next[ch] = none;
+            return ;
+        }
+        diff[cmia] = concat_reg(tmr->tcora) - concat_reg(tmr->tcnt);
+        diff[cmib] = concat_reg(tmr->tcorb) - concat_reg(tmr->tcnt);
+        diff[ovi] = 0x10000 - concat_reg(tmr->tcnt);
+    } else {
+        /* separate mode */
+        diff[cmia] = tmr->tcora[ch] - tmr->tcnt[ch];
+        diff[cmib] = tmr->tcorb[ch] - tmr->tcnt[ch];
+        diff[ovi] = 0x100 - tmr->tcnt[ch];
+    }
+    /* Search for the most recently occurring event. */
+    for (event = 0, min = diff[0], i = 1; i < none; i++) {
+        if (min > diff[i]) {
+            event = i;
+            min = diff[i];
+        }
+    }
+    tmr->next[ch] = event;
+    next_time = diff[event];
+    next_time *= clkdiv[FIELD_EX8(tmr->tccr[ch], TCCR, CKS)];
+    next_time *= NANOSECONDS_PER_SECOND;
+    next_time /= tmr->input_freq;
+    next_time += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+    timer_mod(tmr->timer[ch], next_time);
+}
+
+
+static inline int elapsed_time(RTMRState *tmr, int ch, int64_t delta)
+{
+    int divrate = clkdiv[FIELD_EX8(tmr->tccr[ch], TCCR, CKS)];
+    int et;
+
+    tmr->div_round[ch] += delta;
+    if (divrate > 0) {
+        et = tmr->div_round[ch] / divrate;
+        tmr->div_round[ch] %= divrate;
+    } else {
+        /* disble clock. so no update */
+        et = 0;
+    }
+    return et;
+}
+static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
+{
+    int64_t delta, now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+    int elapsed, ovf = 0;
+    uint16_t tcnt[2];
+    uint32_t ret;
+
+    delta = (now - tmr->tick) * NANOSECONDS_PER_SECOND / tmr->input_freq;
+    if (delta > 0) {
+        tmr->tick = now;
+
+        if (FIELD_EX8(tmr->tccr[1], TCCR, CSS) == INTERNAL) {
+            /* timer1 count update */
+            elapsed = elapsed_time(tmr, 1, delta);
+            if (elapsed >= 0x100) {
+                ovf = elapsed >> 8;
+            }
+            tcnt[1] = tmr->tcnt[1] + (elapsed & 0xff);
+        }
+        switch (FIELD_EX8(tmr->tccr[0], TCCR, CSS)) {
+        case INTERNAL:
+            elapsed = elapsed_time(tmr, 0, delta);
+            tcnt[0] = tmr->tcnt[0] + elapsed;
+            break;
+        case CASCADING:
+            if (ovf > 0) {
+                tcnt[0] = tmr->tcnt[0] + ovf;
+            }
+            break;
+        }
+    } else {
+        tcnt[0] = tmr->tcnt[0];
+        tcnt[1] = tmr->tcnt[1];
+    }
+    if (size == 1) {
+        return tcnt[ch];
+    } else {
+        ret = 0;
+        ret = deposit32(ret, 0, 8, tcnt[1]);
+        ret = deposit32(ret, 8, 8, tcnt[0]);
+        return ret;
+    }
+}
+
+static inline uint8_t read_tccr(uint8_t r)
+{
+    uint8_t tccr = 0;
+    tccr = FIELD_DP8(tccr, TCCR, TMRIS,
+                     FIELD_EX8(r, TCCR, TMRIS));
+    tccr = FIELD_DP8(tccr, TCCR, CSS,
+                     FIELD_EX8(r, TCCR, CSS));
+    tccr = FIELD_DP8(tccr, TCCR, CKS,
+                     FIELD_EX8(r, TCCR, CKS));
+    return tccr;
+}
+
+static uint64_t tmr_read(void *opaque, hwaddr addr, unsigned size)
+{
+    RTMRState *tmr = opaque;
+    int ch = addr & 1;
+    uint64_t ret;
+
+    if (size == 2 && (ch != 0 || addr == A_TCR || addr == A_TCSR)) {
+        qemu_log_mask(LOG_GUEST_ERROR, "renesas_tmr: Invalid read size 0x%"
+                      HWADDR_PRIX "\n", addr);
+        return UINT64_MAX;
+    }
+    switch (addr & 0x0e) {
+    case A_TCR:
+        ret = 0;
+        ret = FIELD_DP8(ret, TCR, CCLR,
+                        FIELD_EX8(tmr->tcr[ch], TCR, CCLR));
+        ret = FIELD_DP8(ret, TCR, OVIE,
+                        FIELD_EX8(tmr->tcr[ch], TCR, OVIE));
+        ret = FIELD_DP8(ret, TCR, CMIEA,
+                        FIELD_EX8(tmr->tcr[ch], TCR, CMIEA));
+        ret = FIELD_DP8(ret, TCR, CMIEB,
+                        FIELD_EX8(tmr->tcr[ch], TCR, CMIEB));
+        return ret;
+    case A_TCSR:
+        ret = 0;
+        ret = FIELD_DP8(ret, TCSR, OSA,
+                        FIELD_EX8(tmr->tcsr[ch], TCSR, OSA));
+        ret = FIELD_DP8(ret, TCSR, OSB,
+                        FIELD_EX8(tmr->tcsr[ch], TCSR, OSB));
+        switch (ch) {
+        case 0:
+            ret = FIELD_DP8(ret, TCSR, ADTE,
+                            FIELD_EX8(tmr->tcsr[ch], TCSR, ADTE));
+            break;
+        case 1: /* CH1 ADTE unimplement always 1 */
+            ret = FIELD_DP8(ret, TCSR, ADTE, 1);
+            break;
+        }
+        return ret;
+    case A_TCORA:
+        if (size == 1) {
+            return tmr->tcora[ch];
+        } else if (ch == 0) {
+            return concat_reg(tmr->tcora);
+        }
+    case A_TCORB:
+        if (size == 1) {
+            return tmr->tcorb[ch];
+        } else {
+            return concat_reg(tmr->tcorb);
+        }
+    case A_TCNT:
+        return read_tcnt(tmr, size, ch);
+    case A_TCCR:
+        if (size == 1) {
+            return read_tccr(tmr->tccr[ch]);
+        } else {
+            return read_tccr(tmr->tccr[0]) << 8 | read_tccr(tmr->tccr[1]);
+        }
+    default:
+        qemu_log_mask(LOG_UNIMP, "renesas_tmr: Register 0x%" HWADDR_PRIX
+                      " not implemented\n", addr);
+        break;
+    }
+    return UINT64_MAX;
+}
+
+#define COUNT_WRITE(reg, val)                   \
+    do {                                        \
+        if (size == 1) {                        \
+            tmr->reg[ch] = val;                 \
+            update_events(tmr, ch);             \
+        } else {                                \
+            tmr->reg[0] = extract32(val, 8, 8); \
+            tmr->reg[1] = extract32(val, 0, 8); \
+            update_events(tmr, 0);              \
+            update_events(tmr, 1);              \
+        }                                       \
+    } while (0)
+
+static void tmr_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+    RTMRState *tmr = opaque;
+    int ch = addr & 1;
+
+    if (size == 2 && (ch != 0 || addr == A_TCR || addr == A_TCSR)) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "renesas_tmr: Invalid write size 0x%" HWADDR_PRIX
+                      "\n", addr);
+        return;
+    }
+    switch (addr & 0x0e) {
+    case A_TCR:
+        tmr->tcr[ch] = val;
+        break;
+    case A_TCSR:
+        tmr->tcsr[ch] = val;
+        break;
+    case A_TCORA:
+        COUNT_WRITE(tcora, val);
+        break;
+    case A_TCORB:
+        COUNT_WRITE(tcorb, val);
+        break;
+    case A_TCNT:
+        COUNT_WRITE(tcnt, val);
+        break;
+    case A_TCCR:
+        COUNT_WRITE(tccr, val);
+        break;
+    default:
+        qemu_log_mask(LOG_UNIMP, "renesas_tmr: Register 0x%" HWADDR_PRIX
+                      " not implemented\n", addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps tmr_ops = {
+    .write = tmr_write,
+    .read  = tmr_read,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 2,
+    },
+};
+
+static void timer_events(RTMRState *tmr, int ch);
+
+static uint16_t issue_event(RTMRState *tmr, int ch, int sz,
+                        uint16_t tcnt, uint16_t tcora, uint16_t tcorb)
+{
+    uint16_t ret = tcnt;
+
+    switch (tmr->next[ch]) {
+    case none:
+        break;
+    case cmia:
+        if (tcnt >= tcora) {
+            if (FIELD_EX8(tmr->tcr[ch], TCR, CCLR) == CCLR_A) {
+                ret = tcnt - tcora;
+            }
+            if (FIELD_EX8(tmr->tcr[ch], TCR, CMIEA)) {
+                qemu_irq_pulse(tmr->cmia[ch]);
+            }
+            if (sz == 8 && ch == 0 &&
+                FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CASCADING) {
+                tmr->tcnt[1]++;
+                timer_events(tmr, 1);
+            }
+        }
+        break;
+    case cmib:
+        if (tcnt >= tcorb) {
+            if (FIELD_EX8(tmr->tcr[ch], TCR, CCLR) == CCLR_B) {
+                ret = tcnt - tcorb;
+            }
+            if (FIELD_EX8(tmr->tcr[ch], TCR, CMIEB)) {
+                qemu_irq_pulse(tmr->cmib[ch]);
+            }
+        }
+        break;
+    case ovi:
+        if ((tcnt >= (1 << sz)) && FIELD_EX8(tmr->tcr[ch], TCR, OVIE)) {
+            qemu_irq_pulse(tmr->ovi[ch]);
+        }
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    return ret;
+}
+
+static void timer_events(RTMRState *tmr, int ch)
+{
+    uint16_t tcnt;
+    tmr->tcnt[ch] = read_tcnt(tmr, 1, ch);
+    if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) != CASCADING) {
+        tmr->tcnt[ch] = issue_event(tmr, ch, 8,
+                                    tmr->tcnt[ch],
+                                    tmr->tcora[ch], tmr->tcorb[ch]) & 0xff;
+    } else {
+        if (ch == 1) {
+            return ;
+        }
+        tcnt = issue_event(tmr, ch, 16,
+                           concat_reg(tmr->tcnt),
+                           concat_reg(tmr->tcora),
+                           concat_reg(tmr->tcorb));
+        tmr->tcnt[0] = (tcnt >> 8) & 0xff;
+        tmr->tcnt[1] = tcnt & 0xff;
+    }
+    update_events(tmr, ch);
+}
+
+static void timer_event0(void *opaque)
+{
+    RTMRState *tmr = opaque;
+
+    timer_events(tmr, 0);
+}
+
+static void timer_event1(void *opaque)
+{
+    RTMRState *tmr = opaque;
+
+    timer_events(tmr, 1);
+}
+
+static void rtmr_reset(DeviceState *dev)
+{
+    RTMRState *tmr = RTMR(dev);
+    tmr->tcr[0]   = tmr->tcr[1]   = 0x00;
+    tmr->tcsr[0]  = 0x00;
+    tmr->tcsr[1]  = 0x10;
+    tmr->tcnt[0]  = tmr->tcnt[1]  = 0x00;
+    tmr->tcora[0] = tmr->tcora[1] = 0xff;
+    tmr->tcorb[0] = tmr->tcorb[1] = 0xff;
+    tmr->tccr[0]  = tmr->tccr[1]  = 0x00;
+    tmr->next[0]  = tmr->next[1]  = none;
+    tmr->tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+}
+
+static void rtmr_init(Object *obj)
+{
+    SysBusDevice *d = SYS_BUS_DEVICE(obj);
+    RTMRState *tmr = RTMR(obj);
+    int i;
+
+    memory_region_init_io(&tmr->memory, OBJECT(tmr), &tmr_ops,
+                          tmr, "renesas-tmr", 0x10);
+    sysbus_init_mmio(d, &tmr->memory);
+
+    for (i = 0; i < ARRAY_SIZE(tmr->ovi); i++) {
+        sysbus_init_irq(d, &tmr->cmia[i]);
+        sysbus_init_irq(d, &tmr->cmib[i]);
+        sysbus_init_irq(d, &tmr->ovi[i]);
+    }
+    tmr->timer[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event0, tmr);
+    tmr->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event1, tmr);
+}
+
+static const VMStateDescription vmstate_rtmr = {
+    .name = "rx-tmr",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property rtmr_properties[] = {
+    DEFINE_PROP_UINT64("input-freq", RTMRState, input_freq, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void rtmr_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props = rtmr_properties;
+    dc->vmsd = &vmstate_rtmr;
+    dc->reset = rtmr_reset;
+}
+
+static const TypeInfo rtmr_info = {
+    .name       = TYPE_RENESAS_TMR,
+    .parent     = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(RTMRState),
+    .instance_init = rtmr_init,
+    .class_init = rtmr_class_init,
+};
+
+static void rtmr_register_types(void)
+{
+    type_register_static(&rtmr_info);
+}
+
+type_init(rtmr_register_types)
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
index eefc95f35e..4c93874159 100644
--- a/hw/timer/Kconfig
+++ b/hw/timer/Kconfig
@@ -58,3 +58,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 123d92c969..706bd1510c 100644
--- a/hw/timer/Makefile.objs
+++ b/hw/timer/Makefile.objs
@@ -40,6 +40,9 @@ obj-$(CONFIG_MC146818RTC) += mc146818rtc.o
 
 obj-$(CONFIG_ALLWINNER_A10_PIT) += allwinner-a10-pit.o
 
+obj-$(CONFIG_RENESAS_TMR8) += renesas_tmr.o
+obj-$(CONFIG_RENESAS_CMT) += renesas_cmt.o
+
 common-obj-$(CONFIG_STM32F2XX_TIMER) += stm32f2xx_timer.o
 common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o aspeed_rtc.o
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 16/22] hw/char: RX62N serial communication interface (SCI)
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (14 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 15/22] hw/timer: RX62N internal timer modules Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 17/22] hw/rx: RX Target hardware definition Yoshinori Sato
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Yoshinori Sato, philmd, richard.henderson,
	imammedo, Alex Bennée

This module supported only non FIFO type.
Hardware manual.
https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej0140_rx62n.pdf

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20190607091116.49044-8-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/hw/char/renesas_sci.h |  45 +++++
 hw/char/renesas_sci.c         | 343 ++++++++++++++++++++++++++++++++++
 hw/char/Kconfig               |   3 +
 hw/char/Makefile.objs         |   1 +
 4 files changed, 392 insertions(+)
 create mode 100644 include/hw/char/renesas_sci.h
 create mode 100644 hw/char/renesas_sci.c

diff --git a/include/hw/char/renesas_sci.h b/include/hw/char/renesas_sci.h
new file mode 100644
index 0000000000..50d1336944
--- /dev/null
+++ b/include/hw/char/renesas_sci.h
@@ -0,0 +1,45 @@
+/*
+ * Renesas Serial Communication Interface
+ *
+ * Copyright (c) 2018 Yoshinori Sato
+ *
+ * This code is licensed under the GPL version 2 or later.
+ *
+ */
+
+#include "chardev/char-fe.h"
+#include "qemu/timer.h"
+#include "hw/sysbus.h"
+
+#define TYPE_RENESAS_SCI "renesas-sci"
+#define RSCI(obj) OBJECT_CHECK(RSCIState, (obj), TYPE_RENESAS_SCI)
+
+enum {
+    ERI = 0,
+    RXI = 1,
+    TXI = 2,
+    TEI = 3,
+    SCI_NR_IRQ = 4,
+};
+
+typedef struct {
+    SysBusDevice parent_obj;
+    MemoryRegion memory;
+
+    uint8_t smr;
+    uint8_t brr;
+    uint8_t scr;
+    uint8_t tdr;
+    uint8_t ssr;
+    uint8_t rdr;
+    uint8_t scmr;
+    uint8_t semr;
+
+    uint8_t read_ssr;
+    int64_t trtime;
+    int64_t rx_next;
+    QEMUTimer *timer;
+    CharBackend chr;
+    uint64_t input_freq;
+    qemu_irq irq[SCI_NR_IRQ];
+} RSCIState;
diff --git a/hw/char/renesas_sci.c b/hw/char/renesas_sci.c
new file mode 100644
index 0000000000..df63c5292e
--- /dev/null
+++ b/hw/char/renesas_sci.c
@@ -0,0 +1,343 @@
+/*
+ * Renesas Serial Communication Interface
+ *
+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
+ * (Rev.1.40 R01UH0033EJ0140)
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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/irq.h"
+#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "hw/qdev-properties.h"
+#include "hw/char/renesas_sci.h"
+#include "migration/vmstate.h"
+#include "qemu/error-report.h"
+
+/* SCI register map */
+REG8(SMR, 0)
+  FIELD(SMR, CKS,  0, 2)
+  FIELD(SMR, MP,   2, 1)
+  FIELD(SMR, STOP, 3, 1)
+  FIELD(SMR, PM,   4, 1)
+  FIELD(SMR, PE,   5, 1)
+  FIELD(SMR, CHR,  6, 1)
+  FIELD(SMR, CM,   7, 1)
+REG8(BRR, 1)
+REG8(SCR, 2)
+  FIELD(SCR, CKE, 0, 2)
+  FIELD(SCR, TEIE, 2, 1)
+  FIELD(SCR, MPIE, 3, 1)
+  FIELD(SCR, RE,   4, 1)
+  FIELD(SCR, TE,   5, 1)
+  FIELD(SCR, RIE,  6, 1)
+  FIELD(SCR, TIE,  7, 1)
+REG8(TDR, 3)
+REG8(SSR, 4)
+  FIELD(SSR, MPBT, 0, 1)
+  FIELD(SSR, MPB,  1, 1)
+  FIELD(SSR, TEND, 2, 1)
+  FIELD(SSR, ERR, 3, 3)
+    FIELD(SSR, PER,  3, 1)
+    FIELD(SSR, FER,  4, 1)
+    FIELD(SSR, ORER, 5, 1)
+  FIELD(SSR, RDRF, 6, 1)
+  FIELD(SSR, TDRE, 7, 1)
+REG8(RDR, 5)
+REG8(SCMR, 6)
+  FIELD(SCMR, SMIF, 0, 1)
+  FIELD(SCMR, SINV, 2, 1)
+  FIELD(SCMR, SDIR, 3, 1)
+  FIELD(SCMR, BCP2, 7, 1)
+REG8(SEMR, 7)
+  FIELD(SEMR, ACS0, 0, 1)
+  FIELD(SEMR, ABCS, 4, 1)
+
+static int can_receive(void *opaque)
+{
+    RSCIState *sci = RSCI(opaque);
+    if (sci->rx_next > qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) {
+        return 0;
+    } else {
+        return FIELD_EX8(sci->scr, SCR, RE);
+    }
+}
+
+static void receive(void *opaque, const uint8_t *buf, int size)
+{
+    RSCIState *sci = RSCI(opaque);
+    sci->rx_next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + sci->trtime;
+    if (FIELD_EX8(sci->ssr, SSR, RDRF) || size > 1) {
+        sci->ssr = FIELD_DP8(sci->ssr, SSR, ORER, 1);
+        if (FIELD_EX8(sci->scr, SCR, RIE)) {
+            qemu_set_irq(sci->irq[ERI], 1);
+        }
+    } else {
+        sci->rdr = buf[0];
+        sci->ssr = FIELD_DP8(sci->ssr, SSR, RDRF, 1);
+        if (FIELD_EX8(sci->scr, SCR, RIE)) {
+            qemu_irq_pulse(sci->irq[RXI]);
+        }
+    }
+}
+
+static void send_byte(RSCIState *sci)
+{
+    if (qemu_chr_fe_backend_connected(&sci->chr)) {
+        qemu_chr_fe_write_all(&sci->chr, &sci->tdr, 1);
+    }
+    timer_mod(sci->timer,
+              qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + sci->trtime);
+    sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 0);
+    sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 1);
+    qemu_set_irq(sci->irq[TEI], 0);
+    if (FIELD_EX8(sci->scr, SCR, TIE)) {
+        qemu_irq_pulse(sci->irq[TXI]);
+    }
+}
+
+static void txend(void *opaque)
+{
+    RSCIState *sci = RSCI(opaque);
+    if (!FIELD_EX8(sci->ssr, SSR, TDRE)) {
+        send_byte(sci);
+    } else {
+        sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 1);
+        if (FIELD_EX8(sci->scr, SCR, TEIE)) {
+            qemu_set_irq(sci->irq[TEI], 1);
+        }
+    }
+}
+
+static void update_trtime(RSCIState *sci)
+{
+    /* char per bits */
+    sci->trtime = 8 - FIELD_EX8(sci->smr, SMR, CHR);
+    sci->trtime += FIELD_EX8(sci->smr, SMR, PE);
+    sci->trtime += FIELD_EX8(sci->smr, SMR, STOP) + 1;
+    /* x bit transmit time (32 * divrate * brr) / base freq */
+    sci->trtime *= 32 * sci->brr;
+    sci->trtime *= 1 << (2 * FIELD_EX8(sci->smr, SMR, CKS));
+    sci->trtime *= NANOSECONDS_PER_SECOND;
+    sci->trtime /= sci->input_freq;
+}
+
+#define IS_TR_ENABLED(scr) \
+    (FIELD_EX8(scr, SCR, TE) || FIELD_EX8(scr, SCR, RE))
+
+static void sci_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+    hwaddr offset = addr & 0x07;
+    RSCIState *sci = RSCI(opaque);
+
+    switch (offset) {
+    case A_SMR:
+        if (!IS_TR_ENABLED(sci->scr)) {
+            sci->smr = val;
+            update_trtime(sci);
+        }
+        break;
+    case A_BRR:
+        if (!IS_TR_ENABLED(sci->scr)) {
+            sci->brr = val;
+            update_trtime(sci);
+        }
+        break;
+    case A_SCR:
+        sci->scr = val;
+        if (FIELD_EX8(sci->scr, SCR, TE)) {
+            sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 1);
+            sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 1);
+            if (FIELD_EX8(sci->scr, SCR, TIE)) {
+                qemu_irq_pulse(sci->irq[TXI]);
+            }
+        }
+        if (!FIELD_EX8(sci->scr, SCR, TEIE)) {
+            qemu_set_irq(sci->irq[TEI], 0);
+        }
+        if (!FIELD_EX8(sci->scr, SCR, RIE)) {
+            qemu_set_irq(sci->irq[ERI], 0);
+        }
+        break;
+    case A_TDR:
+        sci->tdr = val;
+        if (FIELD_EX8(sci->ssr, SSR, TEND)) {
+            send_byte(sci);
+        } else {
+            sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 0);
+        }
+        break;
+    case A_SSR:
+        sci->ssr = FIELD_DP8(sci->ssr, SSR, MPBT,
+                             FIELD_EX8(val, SSR, MPBT));
+        sci->ssr = FIELD_DP8(sci->ssr, SSR, ERR,
+                             FIELD_EX8(val, SSR, ERR) & 0x07);
+        if (FIELD_EX8(sci->read_ssr, SSR, ERR) &&
+            FIELD_EX8(sci->ssr, SSR, ERR) == 0) {
+            qemu_set_irq(sci->irq[ERI], 0);
+        }
+        break;
+    case A_RDR:
+        qemu_log_mask(LOG_GUEST_ERROR, "reneas_sci: RDR is read only.\n");
+        break;
+    case A_SCMR:
+        sci->scmr = val; break;
+    case A_SEMR: /* SEMR */
+        sci->semr = val; break;
+    default:
+        qemu_log_mask(LOG_UNIMP, "renesas_sci: Register 0x%" HWADDR_PRIX
+                      " not implemented\n", offset);
+    }
+}
+
+static uint64_t sci_read(void *opaque, hwaddr addr, unsigned size)
+{
+    hwaddr offset = addr & 0x07;
+    RSCIState *sci = RSCI(opaque);
+
+    switch (offset) {
+    case A_SMR:
+        return sci->smr;
+    case A_BRR:
+        return sci->brr;
+    case A_SCR:
+        return sci->scr;
+    case A_TDR:
+        return sci->tdr;
+    case A_SSR:
+        sci->read_ssr = sci->ssr;
+        return sci->ssr;
+    case A_RDR:
+        sci->ssr = FIELD_DP8(sci->ssr, SSR, RDRF, 0);
+        return sci->rdr;
+    case A_SCMR:
+        return sci->scmr;
+    case A_SEMR:
+        return sci->semr;
+    default:
+        qemu_log_mask(LOG_UNIMP, "renesas_sci: Register 0x%" HWADDR_PRIX
+                      " not implemented.\n", offset);
+    }
+    return UINT64_MAX;
+}
+
+static const MemoryRegionOps sci_ops = {
+    .write = sci_write,
+    .read  = sci_read,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .max_access_size = 1,
+    },
+};
+
+static void rsci_reset(DeviceState *dev)
+{
+    RSCIState *sci = RSCI(dev);
+    sci->smr = sci->scr = 0x00;
+    sci->brr = 0xff;
+    sci->tdr = 0xff;
+    sci->rdr = 0x00;
+    sci->ssr = 0x84;
+    sci->scmr = 0x00;
+    sci->semr = 0x00;
+    sci->rx_next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+}
+
+static void sci_event(void *opaque, int event)
+{
+    RSCIState *sci = RSCI(opaque);
+    if (event == CHR_EVENT_BREAK) {
+        sci->ssr = FIELD_DP8(sci->ssr, SSR, FER, 1);
+        if (FIELD_EX8(sci->scr, SCR, RIE)) {
+            qemu_set_irq(sci->irq[ERI], 1);
+        }
+    }
+}
+
+static void rsci_realize(DeviceState *dev, Error **errp)
+{
+    RSCIState *sci = RSCI(dev);
+
+    if (sci->input_freq == 0) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "renesas_sci: input-freq property must be set.");
+        return;
+    }
+    qemu_chr_fe_set_handlers(&sci->chr, can_receive, receive,
+                             sci_event, NULL, sci, NULL, true);
+}
+
+static void rsci_init(Object *obj)
+{
+    SysBusDevice *d = SYS_BUS_DEVICE(obj);
+    RSCIState *sci = RSCI(obj);
+    int i;
+
+    memory_region_init_io(&sci->memory, OBJECT(sci), &sci_ops,
+                          sci, "renesas-sci", 0x8);
+    sysbus_init_mmio(d, &sci->memory);
+
+    for (i = 0; i < SCI_NR_IRQ; i++) {
+        sysbus_init_irq(d, &sci->irq[i]);
+    }
+    sci->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, txend, sci);
+}
+
+static const VMStateDescription vmstate_rsci = {
+    .name = "renesas-sci",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property rsci_properties[] = {
+    DEFINE_PROP_UINT64("input-freq", RSCIState, input_freq, 0),
+    DEFINE_PROP_CHR("chardev", RSCIState, chr),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void rsci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = rsci_realize;
+    dc->props = rsci_properties;
+    dc->vmsd = &vmstate_rsci;
+    dc->reset = rsci_reset;
+}
+
+static const TypeInfo rsci_info = {
+    .name       = TYPE_RENESAS_SCI,
+    .parent     = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(RSCIState),
+    .instance_init = rsci_init,
+    .class_init = rsci_class_init,
+};
+
+static void rsci_register_types(void)
+{
+    type_register_static(&rsci_info);
+}
+
+type_init(rsci_register_types)
diff --git a/hw/char/Kconfig b/hw/char/Kconfig
index 40e7a8b8bb..874627520c 100644
--- a/hw/char/Kconfig
+++ b/hw/char/Kconfig
@@ -46,3 +46,6 @@ config SCLPCONSOLE
 
 config TERMINAL3270
     bool
+
+config RENESAS_SCI
+    bool
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
index 02d8a66925..4472d563b5 100644
--- a/hw/char/Makefile.objs
+++ b/hw/char/Makefile.objs
@@ -21,6 +21,7 @@ obj-$(CONFIG_PSERIES) += spapr_vty.o
 obj-$(CONFIG_DIGIC) += digic-uart.o
 obj-$(CONFIG_STM32F2XX_USART) += stm32f2xx_usart.o
 obj-$(CONFIG_RASPI) += bcm2835_aux.o
+obj-$(CONFIG_RENESAS_SCI) += renesas_sci.o
 
 common-obj-$(CONFIG_CMSDK_APB_UART) += cmsdk-apb-uart.o
 common-obj-$(CONFIG_ETRAXFS) += etraxfs_ser.o
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 17/22] hw/rx: RX Target hardware definition
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (15 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 16/22] hw/char: RX62N serial communication interface (SCI) Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 18/22] hw/rx: Honor -accel qtest Yoshinori Sato
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, richard.henderson, Yoshinori Sato, philmd

rx62n - RX62N cpu.
rx-virt - RX QEMU virtual target.

v23 changes.
Add missing includes.

v21 changes.
rx_load_image move to rx-virt.c

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>

Message-Id: <20190616142836.10614-17-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20190607091116.49044-9-ysato@users.sourceforge.jp>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
[PMD: Use TYPE_RX62N_CPU, use #define for RX62N_NR_TMR/CMT/SCI,
 renamed CPU -> MCU, device -> microcontroller]
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
v19: Fixed typo (Peter Maydell)
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
---
 include/hw/rx/rx.h    |   7 ++
 include/hw/rx/rx62n.h |  91 ++++++++++++++++
 hw/rx/rx-virt.c       | 127 ++++++++++++++++++++++
 hw/rx/rx62n.c         | 239 ++++++++++++++++++++++++++++++++++++++++++
 hw/rx/Kconfig         |  14 +++
 hw/rx/Makefile.objs   |   2 +
 6 files changed, 480 insertions(+)
 create mode 100644 include/hw/rx/rx.h
 create mode 100644 include/hw/rx/rx62n.h
 create mode 100644 hw/rx/rx-virt.c
 create mode 100644 hw/rx/rx62n.c
 create mode 100644 hw/rx/Kconfig
 create mode 100644 hw/rx/Makefile.objs

diff --git a/include/hw/rx/rx.h b/include/hw/rx/rx.h
new file mode 100644
index 0000000000..ff5924b81f
--- /dev/null
+++ b/include/hw/rx/rx.h
@@ -0,0 +1,7 @@
+#ifndef QEMU_RX_H
+#define QEMU_RX_H
+/* Definitions for RX board emulation.  */
+
+#include "target/rx/cpu-qom.h"
+
+#endif
diff --git a/include/hw/rx/rx62n.h b/include/hw/rx/rx62n.h
new file mode 100644
index 0000000000..97ea8ddb8e
--- /dev/null
+++ b/include/hw/rx/rx62n.h
@@ -0,0 +1,91 @@
+/*
+ * RX62N MCU Object
+ *
+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
+ * (Rev.1.40 R01UH0033EJ0140)
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_RX_RX62N_H
+#define HW_RX_RX62N_H
+
+#include "hw/sysbus.h"
+#include "hw/intc/rx_icu.h"
+#include "hw/timer/renesas_tmr.h"
+#include "hw/timer/renesas_cmt.h"
+#include "hw/char/renesas_sci.h"
+#include "target/rx/cpu.h"
+#include "qemu/units.h"
+
+#define TYPE_RX62N "rx62n"
+#define RX62N(obj) OBJECT_CHECK(RX62NState, (obj), TYPE_RX62N)
+
+#define RX62N_NR_TMR    2
+#define RX62N_NR_CMT    2
+#define RX62N_NR_SCI    6
+
+typedef struct RX62NState {
+    SysBusDevice parent_obj;
+
+    RXCPU cpu;
+    RXICUState icu;
+    RTMRState tmr[RX62N_NR_TMR];
+    RCMTState cmt[RX62N_NR_CMT];
+    RSCIState sci[RX62N_NR_SCI];
+
+    MemoryRegion *sysmem;
+    bool kernel;
+
+    MemoryRegion iram;
+    MemoryRegion iomem1;
+    MemoryRegion d_flash;
+    MemoryRegion iomem2;
+    MemoryRegion iomem3;
+    MemoryRegion c_flash;
+    qemu_irq irq[NR_IRQS];
+} RX62NState;
+
+/*
+ * RX62N Peripheral Address
+ * See users manual section 5
+ */
+#define RX62N_ICUBASE 0x00087000
+#define RX62N_TMRBASE 0x00088200
+#define RX62N_CMTBASE 0x00088000
+#define RX62N_SCIBASE 0x00088240
+
+/*
+ * RX62N Peripheral IRQ
+ * See users manual section 11
+ */
+#define RX62N_TMR_IRQBASE 174
+#define RX62N_CMT_IRQBASE 28
+#define RX62N_SCI_IRQBASE 214
+
+/*
+ * RX62N Internal Memory
+ * It is the value of R5F562N8.
+ * Please change the size for R5F562N7.
+ */
+#define RX62N_IRAM_BASE 0x00000000
+#define RX62N_IRAM_SIZE (96 * KiB)
+#define RX62N_DFLASH_BASE 0x00100000
+#define RX62N_DFLASH_SIZE (32 * KiB)
+#define RX62N_CFLASH_BASE 0xfff80000
+#define RX62N_CFLASH_SIZE (512 * KiB)
+
+#define RX62N_PCLK (48 * 1000 * 1000)
+#endif
diff --git a/hw/rx/rx-virt.c b/hw/rx/rx-virt.c
new file mode 100644
index 0000000000..4cfe2e3123
--- /dev/null
+++ b/hw/rx/rx-virt.c
@@ -0,0 +1,127 @@
+/*
+ * RX QEMU virtual platform
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "hw/loader.h"
+#include "hw/rx/rx62n.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
+#include "sysemu/device_tree.h"
+#include "hw/boards.h"
+
+/* Same address of GDB integrated simulator */
+#define SDRAM_BASE 0x01000000
+
+static void rx_load_image(RXCPU *cpu, const char *filename,
+                          uint32_t start, uint32_t size)
+{
+    static uint32_t extable[32];
+    long kernel_size;
+    int i;
+
+    kernel_size = load_image_targphys(filename, start, size);
+    if (kernel_size < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n", filename);
+        exit(1);
+    }
+    cpu->env.pc = start;
+
+    /* setup exception trap trampoline */
+    /* linux kernel only works little-endian mode */
+    for (i = 0; i < ARRAY_SIZE(extable); i++) {
+        extable[i] = cpu_to_le32(0x10 + i * 4);
+    }
+    rom_add_blob_fixed("extable", extable, sizeof(extable), 0xffffff80);
+}
+
+static void rxvirt_init(MachineState *machine)
+{
+    RX62NState *s = g_new(RX62NState, 1);
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *sdram = g_new(MemoryRegion, 1);
+    const char *kernel_filename = machine->kernel_filename;
+    const char *dtb_filename = machine->dtb;
+    void *dtb = NULL;
+    int dtb_size;
+
+    /* Allocate memory space */
+    memory_region_init_ram(sdram, NULL, "sdram", 16 * MiB,
+                           &error_fatal);
+    memory_region_add_subregion(sysmem, SDRAM_BASE, sdram);
+
+    /* Initialize MCU */
+    object_initialize_child(OBJECT(machine), "mcu", s,
+                            sizeof(RX62NState), TYPE_RX62N,
+                            &error_fatal, NULL);
+    object_property_set_link(OBJECT(s), OBJECT(get_system_memory()),
+                             "memory", &error_abort);
+    object_property_set_bool(OBJECT(s), kernel_filename != NULL,
+                             "load-kernel", &error_abort);
+    object_property_set_bool(OBJECT(s), true, "realized", &error_abort);
+
+    /* Load kernel and dtb */
+    if (kernel_filename) {
+        rx_load_image(RXCPU(first_cpu), kernel_filename,
+                      SDRAM_BASE + 8 * MiB, 8 * MiB);
+        if (dtb_filename) {
+            dtb = load_device_tree(dtb_filename, &dtb_size);
+            if (dtb == NULL) {
+                fprintf(stderr, "Couldn't open dtb file %s\n", dtb_filename);
+                exit(1);
+            }
+            if (machine->kernel_cmdline &&
+                qemu_fdt_setprop_string(dtb, "/chosen", "bootargs",
+                                        machine->kernel_cmdline) < 0) {
+                fprintf(stderr, "couldn't set /chosen/bootargs\n");
+                exit(1);
+            }
+            rom_add_blob_fixed("dtb", dtb, dtb_size,
+                               SDRAM_BASE + 16 * MiB - dtb_size);
+            /* Set dtb address to R1 */
+            RXCPU(first_cpu)->env.regs[1] = 0x02000000 - dtb_size;
+        }
+    }
+}
+
+static void rxvirt_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+
+    mc->desc = "RX QEMU Virtual Target";
+    mc->init = rxvirt_init;
+    mc->is_default = 1;
+    mc->default_cpu_type = TYPE_RX62N_CPU;
+}
+
+static const TypeInfo rxvirt_type = {
+    .name = MACHINE_TYPE_NAME("rx-virt"),
+    .parent = TYPE_MACHINE,
+    .class_init = rxvirt_class_init,
+};
+
+static void rxvirt_machine_init(void)
+{
+    type_register_static(&rxvirt_type);
+}
+
+type_init(rxvirt_machine_init)
diff --git a/hw/rx/rx62n.c b/hw/rx/rx62n.c
new file mode 100644
index 0000000000..ac47f2a397
--- /dev/null
+++ b/hw/rx/rx62n.c
@@ -0,0 +1,239 @@
+/*
+ * RX62N Microcontroller
+ *
+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
+ * (Rev.1.40 R01UH0033EJ0140)
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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 "hw/qdev-properties.h"
+#include "sysemu/sysemu.h"
+#include "cpu.h"
+
+/*
+ * IRQ -> IPR mapping table
+ * 0x00 - 0x91: IPR no (IPR00 to IPR91)
+ * 0xff: IPR not assigned
+ * See "11.3.1 Interrupt Vector Table" in hardware manual.
+ */
+static const int ipr_table[NR_IRQS] = {
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 15 */
+    0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x02,
+    0xff, 0xff, 0xff, 0x03, 0x04, 0x05, 0x06, 0x07, /* 31 */
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x14, 0x14, 0x14, /* 47 */
+    0x15, 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff,
+    0x18, 0x18, 0x18, 0x18, 0x18, 0x1d, 0x1e, 0x1f, /* 63 */
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 79 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0x3a, 0x3b, 0x3c, 0xff, 0xff, 0xff, /* 95 */
+    0x40, 0xff, 0x44, 0x45, 0xff, 0xff, 0x48, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 111 */
+    0xff, 0xff, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52,
+    0x52, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, /* 127 */
+    0x56, 0x57, 0x57, 0x57, 0x57, 0x58, 0x59, 0x59,
+    0x59, 0x59, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, /* 143 */
+    0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f,
+    0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x62, /* 159 */
+    0x62, 0x63, 0x64, 0x64, 0x64, 0x64, 0x65, 0x66,
+    0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, /* 175 */
+    0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b,
+    0x6b, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 191 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x71,
+    0x72, 0x73, 0x74, 0x75, 0xff, 0xff, 0xff, 0xff, /* 207 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80,
+    0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, /* 223 */
+    0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0xff, 0xff,
+    0xff, 0xff, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, /* 239 */
+    0x86, 0x86, 0xff, 0xff, 0xff, 0xff, 0x88, 0x89,
+    0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, /* 255 */
+};
+
+/*
+ * Level triggerd IRQ list
+ * Not listed IRQ is Edge trigger.
+ * See "11.3.1 Interrupt Vector Table" in hardware manual.
+ */
+static const uint32_t levelirq[] = {
+     16,  21,  32,  44,  47,  48,  51,  64,  65,  66,
+     67,  68,  69,  70,  71,  72,  73,  74,  75,  76,
+     77,  78,  79,  90,  91, 170, 171, 172, 173, 214,
+    217, 218, 221, 222, 225, 226, 229, 234, 237, 238,
+    241, 246, 249, 250, 253,
+};
+
+static void register_icu(RX62NState *s)
+{
+    int i;
+    SysBusDevice *icu;
+
+    object_initialize_child(OBJECT(s), "icu", &s->icu, sizeof(RXICUState),
+                            TYPE_RXICU, &error_abort, NULL);
+
+    icu = SYS_BUS_DEVICE(&s->icu);
+    sysbus_mmio_map(SYS_BUS_DEVICE(icu), 0, RX62N_ICUBASE);
+    qdev_prop_set_uint32(DEVICE(icu), "len-ipr-map", NR_IRQS);
+    for (i = 0; i < NR_IRQS; i++) {
+        char propname[32];
+        snprintf(propname, sizeof(propname), "ipr-map[%d]", i);
+        qdev_prop_set_uint32(DEVICE(icu), propname, ipr_table[i]);
+    }
+    qdev_prop_set_uint32(DEVICE(icu), "len-trigger-level",
+                         ARRAY_SIZE(levelirq));
+    for (i = 0; i < ARRAY_SIZE(levelirq); i++) {
+        char propname[32];
+        snprintf(propname, sizeof(propname), "trigger-level[%d]", i);
+        qdev_prop_set_uint32(DEVICE(icu), propname, levelirq[i]);
+    }
+
+    for (i = 0; i < NR_IRQS; i++) {
+        s->irq[i] = qdev_get_gpio_in(DEVICE(icu), i);
+    }
+
+    qdev_init_nofail(DEVICE(icu));
+    sysbus_connect_irq(icu, 0, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_IRQ));
+    sysbus_connect_irq(icu, 1, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_FIR));
+    sysbus_connect_irq(icu, 2, s->irq[SWI]);
+
+}
+
+static void register_tmr(RX62NState *s, int unit)
+{
+    SysBusDevice *tmr;
+    int i, irqbase;
+
+    object_initialize_child(OBJECT(s), "tmr[*]", &s->tmr[unit],
+                            sizeof(RTMRState), TYPE_RENESAS_TMR,
+                            &error_abort, NULL);
+
+    tmr = SYS_BUS_DEVICE(&s->tmr[unit]);
+    sysbus_mmio_map(tmr, 0, RX62N_TMRBASE + unit * 0x10);
+    qdev_prop_set_uint64(DEVICE(tmr), "input-freq", RX62N_PCLK);
+
+    qdev_init_nofail(DEVICE(tmr));
+    irqbase = RX62N_TMR_IRQBASE + TMR_NR_IRQ * unit;
+    for (i = 0; i < TMR_NR_IRQ; i++) {
+        sysbus_connect_irq(tmr, i, s->irq[irqbase + i]);
+    }
+}
+
+static void register_cmt(RX62NState *s, int unit)
+{
+    SysBusDevice *cmt;
+    int i, irqbase;
+
+    object_initialize_child(OBJECT(s), "cmt[*]", &s->cmt[unit],
+                            sizeof(RCMTState), TYPE_RENESAS_CMT,
+                            &error_abort, NULL);
+
+    cmt = SYS_BUS_DEVICE(&s->cmt[unit]);
+    sysbus_mmio_map(cmt, 0, RX62N_CMTBASE + unit * 0x10);
+    qdev_prop_set_uint64(DEVICE(cmt), "input-freq", RX62N_PCLK);
+
+    qdev_init_nofail(DEVICE(cmt));
+    irqbase = RX62N_CMT_IRQBASE + CMT_NR_IRQ * unit;
+    for (i = 0; i < CMT_NR_IRQ; i++) {
+        sysbus_connect_irq(cmt, i, s->irq[irqbase + i]);
+    }
+}
+
+static void register_sci(RX62NState *s, int unit)
+{
+    SysBusDevice *sci;
+    int i, irqbase;
+
+    object_initialize_child(OBJECT(s), "sci[*]", &s->sci[unit],
+                            sizeof(RSCIState), TYPE_RENESAS_SCI,
+                            &error_abort, NULL);
+
+    sci = SYS_BUS_DEVICE(&s->sci[unit]);
+    sysbus_mmio_map(sci, 0, RX62N_SCIBASE + unit * 0x08);
+    qdev_prop_set_chr(DEVICE(sci), "chardev", serial_hd(unit));
+    qdev_prop_set_uint64(DEVICE(sci), "input-freq", RX62N_PCLK);
+
+    qdev_init_nofail(DEVICE(sci));
+    irqbase = RX62N_SCI_IRQBASE + SCI_NR_IRQ * unit;
+    for (i = 0; i < SCI_NR_IRQ; i++) {
+        sysbus_connect_irq(sci, i, s->irq[irqbase + i]);
+    }
+}
+
+static void rx62n_realize(DeviceState *dev, Error **errp)
+{
+    RX62NState *s = RX62N(dev);
+
+    memory_region_init_ram(&s->iram, NULL, "iram", RX62N_IRAM_SIZE, errp);
+    memory_region_add_subregion(s->sysmem, RX62N_IRAM_BASE, &s->iram);
+    memory_region_init_rom(&s->d_flash, NULL, "dataflash",
+                           RX62N_DFLASH_SIZE, errp);
+    memory_region_add_subregion(s->sysmem, RX62N_DFLASH_BASE, &s->d_flash);
+    memory_region_init_rom(&s->c_flash, NULL, "codeflash",
+                           RX62N_CFLASH_SIZE, errp);
+    memory_region_add_subregion(s->sysmem, RX62N_CFLASH_BASE, &s->c_flash);
+    if (!s->kernel) {
+        rom_add_file_fixed(bios_name, RX62N_CFLASH_BASE, 0);
+    }
+
+    /* Initialize CPU */
+    object_initialize_child(OBJECT(s), "cpu", &s->cpu, sizeof(RXCPU),
+                            TYPE_RX62N_CPU, errp, NULL);
+    object_property_set_bool(OBJECT(&s->cpu), true, "realized", errp);
+
+    register_icu(s);
+    s->cpu.env.ack = qdev_get_gpio_in_named(DEVICE(&s->icu), "ack", 0);
+    register_tmr(s, 0);
+    register_tmr(s, 1);
+    register_cmt(s, 0);
+    register_cmt(s, 1);
+    register_sci(s, 0);
+}
+
+static Property rx62n_properties[] = {
+    DEFINE_PROP_LINK("memory", RX62NState, sysmem, TYPE_MEMORY_REGION,
+                     MemoryRegion *),
+    DEFINE_PROP_BOOL("load-kernel", RX62NState, kernel, false),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void rx62n_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = rx62n_realize;
+    dc->props = rx62n_properties;
+}
+
+static const TypeInfo rx62n_info = {
+    .name = TYPE_RX62N,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(RX62NState),
+    .class_init = rx62n_class_init,
+};
+
+static void rx62n_register_types(void)
+{
+    type_register_static(&rx62n_info);
+}
+
+type_init(rx62n_register_types)
diff --git a/hw/rx/Kconfig b/hw/rx/Kconfig
new file mode 100644
index 0000000000..a07490a65e
--- /dev/null
+++ b/hw/rx/Kconfig
@@ -0,0 +1,14 @@
+config RX
+    bool
+
+config RX62N
+    bool
+    select RX
+    select RX_ICU
+    select RENESAS_TMR8
+    select RENESAS_CMT
+    select RENESAS_SCI
+
+config RX_VIRT
+    bool
+    select RX62N
diff --git a/hw/rx/Makefile.objs b/hw/rx/Makefile.objs
new file mode 100644
index 0000000000..63f8be0e82
--- /dev/null
+++ b/hw/rx/Makefile.objs
@@ -0,0 +1,2 @@
+obj-$(CONFIG_RX62N) += rx62n.o
+obj-$(CONFIG_RX_VIRT) += rx-virt.o
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 18/22] hw/rx: Honor -accel qtest
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (16 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 17/22] hw/rx: RX Target hardware definition Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 19/22] hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core Yoshinori Sato
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, Richard Henderson, Yoshinori Sato, philmd

From: Richard Henderson <richard.henderson@linaro.org>

Issue an error if no kernel, no bios, and not qtest'ing.
Fixes make check-qtest-rx: test/qom-test.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Message-Id: <20190607091116.49044-16-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
We could squash this with the previous patch
---
 hw/rx/rx62n.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/hw/rx/rx62n.c b/hw/rx/rx62n.c
index ac47f2a397..a0986fd15e 100644
--- a/hw/rx/rx62n.c
+++ b/hw/rx/rx62n.c
@@ -21,12 +21,14 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qemu/error-report.h"
 #include "hw/hw.h"
 #include "hw/rx/rx62n.h"
 #include "hw/loader.h"
 #include "hw/sysbus.h"
 #include "hw/qdev-properties.h"
 #include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
 #include "cpu.h"
 
 /*
@@ -191,8 +193,14 @@ static void rx62n_realize(DeviceState *dev, Error **errp)
     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);
+        if (bios_name) {
+            rom_add_file_fixed(bios_name, RX62N_CFLASH_BASE, 0);
+        }  else if (!qtest_enabled()) {
+            error_report("No bios or kernel specified");
+            exit(1);
+        }
     }
 
     /* Initialize CPU */
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 19/22] hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (17 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 18/22] hw/rx: Honor -accel qtest Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 20/22] Add rx-softmmu Yoshinori Sato
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, richard.henderson, Philippe Mathieu-Daudé,
	Yoshinori Sato, imammedo

From: Philippe Mathieu-Daudé <philmd@redhat.com>

While the VIRT machine can use different microcontrollers,
the RX62N microcontroller is tied to the RX62N CPU core.

Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
---
 hw/rx/rx-virt.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/hw/rx/rx-virt.c b/hw/rx/rx-virt.c
index 4cfe2e3123..9676a5e7bf 100644
--- a/hw/rx/rx-virt.c
+++ b/hw/rx/rx-virt.c
@@ -17,6 +17,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
 #include "cpu.h"
@@ -56,6 +57,7 @@ static void rx_load_image(RXCPU *cpu, const char *filename,
 
 static void rxvirt_init(MachineState *machine)
 {
+    MachineClass *mc = MACHINE_GET_CLASS(machine);
     RX62NState *s = g_new(RX62NState, 1);
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *sdram = g_new(MemoryRegion, 1);
@@ -64,6 +66,12 @@ static void rxvirt_init(MachineState *machine)
     void *dtb = NULL;
     int dtb_size;
 
+    if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
+        error_report("This board can only be used with CPU %s",
+                     mc->default_cpu_type);
+        exit(1);
+    }
+
     /* Allocate memory space */
     memory_region_init_ram(sdram, NULL, "sdram", 16 * MiB,
                            &error_fatal);
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 20/22] Add rx-softmmu
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (18 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 19/22] hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core Yoshinori Sato
@ 2019-09-12  6:06 ` Yoshinori Sato
  2019-09-12  6:07 ` [Qemu-devel] [PATCH v24 21/22] BootLinuxConsoleTest: Test the RX-Virt machine Yoshinori Sato
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, richard.henderson, Yoshinori Sato, philmd

Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Message-Id: <20190607091116.49044-17-ysato@users.sourceforge.jp>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
pick ed65c02993 target/rx: Add RX to SysEmuTarget
pick 01372568ae tests: Add rx to machine-none-test.c
[PMD: Squashed patches from Richard Henderson modifying
      qapi/common.json and tests/machine-none-test.c]
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 configure                      | 8 ++++++++
 default-configs/rx-softmmu.mak | 3 +++
 include/exec/poison.h          | 1 +
 include/sysemu/arch_init.h     | 1 +
 arch_init.c                    | 2 ++
 tests/machine-none-test.c      | 1 +
 hw/Kconfig                     | 1 +
 7 files changed, 17 insertions(+)
 create mode 100644 default-configs/rx-softmmu.mak

diff --git a/configure b/configure
index 95134c0180..30ffde1788 100755
--- a/configure
+++ b/configure
@@ -7607,6 +7607,11 @@ case "$target_name" in
     gdb_xml_files="riscv-64bit-cpu.xml riscv-64bit-fpu.xml riscv-64bit-csr.xml"
     target_compiler=$cross_cc_riscv64
   ;;
+  rx)
+    TARGET_ARCH=rx
+    bflt="yes"
+    target_compiler=$cross_cc_rx
+  ;;
   sh4|sh4eb)
     TARGET_ARCH=sh4
     bflt="yes"
@@ -7830,6 +7835,9 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
   riscv*)
     disas_config "RISCV"
   ;;
+  rx)
+    disas_config "RX"
+  ;;
   s390*)
     disas_config "S390"
   ;;
diff --git a/default-configs/rx-softmmu.mak b/default-configs/rx-softmmu.mak
new file mode 100644
index 0000000000..a3eecefb11
--- /dev/null
+++ b/default-configs/rx-softmmu.mak
@@ -0,0 +1,3 @@
+# Default configuration for rx-softmmu
+
+CONFIG_RX_VIRT=y
diff --git a/include/exec/poison.h b/include/exec/poison.h
index 955eb863ab..7b9ac361dc 100644
--- a/include/exec/poison.h
+++ b/include/exec/poison.h
@@ -26,6 +26,7 @@
 #pragma GCC poison TARGET_PPC
 #pragma GCC poison TARGET_PPC64
 #pragma GCC poison TARGET_ABI32
+#pragma GCC poison TARGET_RX
 #pragma GCC poison TARGET_S390X
 #pragma GCC poison TARGET_SH4
 #pragma GCC poison TARGET_SPARC
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 62c6fe4cf1..6c011acc52 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -24,6 +24,7 @@ enum {
     QEMU_ARCH_NIOS2 = (1 << 17),
     QEMU_ARCH_HPPA = (1 << 18),
     QEMU_ARCH_RISCV = (1 << 19),
+    QEMU_ARCH_RX = (1 << 20),
 };
 
 extern const uint32_t arch_type;
diff --git a/arch_init.c b/arch_init.c
index 0a1531124c..7a37fb2c34 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -73,6 +73,8 @@ int graphic_depth = 32;
 #define QEMU_ARCH QEMU_ARCH_PPC
 #elif defined(TARGET_RISCV)
 #define QEMU_ARCH QEMU_ARCH_RISCV
+#elif defined(TARGET_RX)
+#define QEMU_ARCH QEMU_ARCH_RX
 #elif defined(TARGET_S390X)
 #define QEMU_ARCH QEMU_ARCH_S390X
 #elif defined(TARGET_SH4)
diff --git a/tests/machine-none-test.c b/tests/machine-none-test.c
index 5953d31755..8bb54a6360 100644
--- a/tests/machine-none-test.c
+++ b/tests/machine-none-test.c
@@ -56,6 +56,7 @@ static struct arch2cpu cpus_map[] = {
     { "hppa", "hppa" },
     { "riscv64", "rv64gcsu-v1.10.0" },
     { "riscv32", "rv32gcsu-v1.9.1" },
+    { "rx", "rx62n" },
 };
 
 static const char *get_cpu_model_by_arch(const char *arch)
diff --git a/hw/Kconfig b/hw/Kconfig
index b45db3c813..77bbc59cc7 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -54,6 +54,7 @@ source nios2/Kconfig
 source openrisc/Kconfig
 source ppc/Kconfig
 source riscv/Kconfig
+source rx/Kconfig
 source s390x/Kconfig
 source sh4/Kconfig
 source sparc/Kconfig
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 21/22] BootLinuxConsoleTest: Test the RX-Virt machine
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (19 preceding siblings ...)
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 20/22] Add rx-softmmu Yoshinori Sato
@ 2019-09-12  6:07 ` Yoshinori Sato
  2019-09-12  6:07 ` [Qemu-devel] [PATCH v24 22/22] qapi/machine.json: Add RX cpu Yoshinori Sato
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, richard.henderson, Philippe Mathieu-Daudé,
	Yoshinori Sato, imammedo

From: Philippe Mathieu-Daudé <philmd@redhat.com>

Add two tests for the rx-virt machine, based on the recommended test
setup from Yoshinori Sato:
https://lists.gnu.org/archive/html/qemu-devel/2019-05/msg03586.html

- U-Boot prompt
- Linux kernel with Sash shell

These are very quick tests:

  $ avocado run -t arch:rx tests/acceptance/boot_linux_console.py
  JOB ID     : 84a6ef01c0b87975ecbfcb31a920afd735753ace
  JOB LOG    : /home/phil/avocado/job-results/job-2019-05-24T05.02-84a6ef0/job.log
   (1/2) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_rx_uboot: PASS (0.11 s)
   (2/2) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_rx_linux: PASS (0.45 s)
  RESULTS    : PASS 2 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0

Tests can also be run with:

  $ avocado --show=console run -t arch:rx tests/acceptance/boot_linux_console.py
  console: U-Boot 2016.05-rc3-23705-ga1ef3c71cb-dirty (Feb 05 2019 - 21:56:06 +0900)
  console: Linux version 4.19.0+ (yo-satoh@yo-satoh-debian) (gcc version 9.0.0 20181105 (experimental) (GCC)) #137 Wed Feb 20 23:20:02 JST 2019
  console: Built 1 zonelists, mobility grouping on.  Total pages: 8128
  ...
  console: SuperH (H)SCI(F) driver initialized
  console: 88240.serial: ttySC0 at MMIO 0x88240 (irq = 215, base_baud = 0) is a sci
  console: console [ttySC0] enabled
  console: 88248.serial: ttySC1 at MMIO 0x88248 (irq = 219, base_baud = 0) is a sci

Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
Based-on: 20190517045136.3509-1-richard.henderson@linaro.org
"RX architecture support"
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
---
 tests/acceptance/boot_linux_console.py | 46 ++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
index 2504ef0150..8309687778 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -373,3 +373,49 @@ class BootLinuxConsole(Test):
         self.vm.launch()
         console_pattern = 'Kernel command line: %s' % kernel_command_line
         self.wait_for_console_pattern(console_pattern)
+
+    def test_rx_uboot(self):
+        """
+        :avocado: tags=arch:rx
+        :avocado: tags=machine:rx-virt
+        :avocado: tags=endian:little
+        """
+        uboot_url = ('https://acc.dl.osdn.jp/users/23/23888/u-boot.bin.gz')
+        uboot_hash = '9b78dbd43b40b2526848c0b1ce9de02c24f4dcdb'
+        uboot_path = self.fetch_asset(uboot_url, asset_hash=uboot_hash)
+        uboot_path = archive.uncompress(uboot_path, self.workdir)
+
+        self.vm.set_machine('rx-virt')
+        self.vm.set_console()
+        self.vm.add_args('-bios', uboot_path,
+                         '-no-reboot')
+        self.vm.launch()
+        uboot_version = 'U-Boot 2016.05-rc3-23705-ga1ef3c71cb-dirty'
+        self.wait_for_console_pattern(uboot_version)
+        gcc_version = 'rx-unknown-linux-gcc (GCC) 9.0.0 20181105 (experimental)'
+        # FIXME limit baudrate on chardev, else we type too fast
+        #self.exec_command_and_wait_for_pattern('version', gcc_version)
+
+    def test_rx_linux(self):
+        """
+        :avocado: tags=arch:rx
+        :avocado: tags=machine:rx-virt
+        :avocado: tags=endian:little
+        """
+        dtb_url = ('https://acc.dl.osdn.jp/users/23/23887/rx-qemu.dtb')
+        dtb_hash = '7b4e4e2c71905da44e86ce47adee2210b026ac18'
+        dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash)
+        kernel_url = ('http://acc.dl.osdn.jp/users/23/23845/zImage')
+        kernel_hash = '39a81067f8d72faad90866ddfefa19165d68fc99'
+        kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
+
+        self.vm.set_machine('rx-virt')
+        self.vm.set_console()
+        kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'earlycon'
+        self.vm.add_args('-kernel', kernel_path,
+                         '-dtb', dtb_path,
+                         '-no-reboot')
+        self.vm.launch()
+        self.wait_for_console_pattern('Sash command shell (version 1.1.1)')
+        self.exec_command_and_wait_for_pattern('printenv',
+                                               'TERM=linux')
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH v24 22/22] qapi/machine.json: Add RX cpu.
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (20 preceding siblings ...)
  2019-09-12  6:07 ` [Qemu-devel] [PATCH v24 21/22] BootLinuxConsoleTest: Test the RX-Virt machine Yoshinori Sato
@ 2019-09-12  6:07 ` Yoshinori Sato
  2019-09-20 12:39   ` Eric Blake
  2019-09-12  6:39 ` [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support no-reply
                   ` (5 subsequent siblings)
  27 siblings, 1 reply; 31+ messages in thread
From: Yoshinori Sato @ 2019-09-12  6:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, imammedo, richard.henderson, Yoshinori Sato, philmd

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
---
 qapi/machine.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/qapi/machine.json b/qapi/machine.json
index ca26779f1a..70398c521f 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -28,7 +28,7 @@
   'data' : [ 'aarch64', 'alpha', 'arm', 'cris', 'hppa', 'i386', 'lm32',
              'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
              'mips64el', 'mipsel', 'moxie', 'nios2', 'or1k', 'ppc',
-             'ppc64', 'riscv32', 'riscv64', 's390x', 'sh4',
+             'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4',
              'sh4eb', 'sparc', 'sparc64', 'tricore', 'unicore32',
              'x86_64', 'xtensa', 'xtensaeb' ] }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (21 preceding siblings ...)
  2019-09-12  6:07 ` [Qemu-devel] [PATCH v24 22/22] qapi/machine.json: Add RX cpu Yoshinori Sato
@ 2019-09-12  6:39 ` no-reply
  2019-09-12  7:47 ` no-reply
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: no-reply @ 2019-09-12  6:39 UTC (permalink / raw)
  To: ysato
  Cc: peter.maydell, ysato, richard.henderson, qemu-devel, imammedo, philmd

Patchew URL: https://patchew.org/QEMU/20190912060701.4642-1-ysato@users.sourceforge.jp/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Subject: [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support
Message-id: 20190912060701.4642-1-ysato@users.sourceforge.jp
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

From https://github.com/patchew-project/qemu
 * [new tag]         patchew/20190912060701.4642-1-ysato@users.sourceforge.jp -> patchew/20190912060701.4642-1-ysato@users.sourceforge.jp
Switched to a new branch 'test'
c7211ec qapi/machine.json: Add RX cpu.
0a60bc1 BootLinuxConsoleTest: Test the RX-Virt machine
21ccd2b Add rx-softmmu
53b5a3e hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
100e307 hw/rx: Honor -accel qtest
4737268 hw/rx: RX Target hardware definition
6d1d3f2 hw/char: RX62N serial communication interface (SCI)
96aa2bf hw/timer: RX62N internal timer modules
54ced3e hw/intc: RX62N interrupt controller (ICUa)
3200a28 target/rx: Dump bytes for each insn during disassembly
a254a82 target/rx: Collect all bytes during disassembly
5f7675e target/rx: Emit all disassembly in one prt()
04b3639 target/rx: Use prt_ldmi for XCHG_mr disassembly
b58c020 target/rx: Replace operand with prt_ldmi in disassembler
9217628 target/rx: Disassemble rx_index_addr into a string
e4f57d2 target/rx: RX disassembler
702f27d target/rx: CPU definition
8abda61 target/rx: TCG helper
ba2df21 target/rx: TCG translation
9201c38 hw/registerfields.h: Add 8bit and 16bit register macros
a1dbe53 qemu/bitops.h: Add extract8 and extract16
7b0a56f MAINTAINERS: Add RX

=== OUTPUT BEGIN ===
1/22 Checking commit 7b0a56f73866 (MAINTAINERS: Add RX)
2/22 Checking commit a1dbe53d2434 (qemu/bitops.h: Add extract8 and extract16)
3/22 Checking commit 9201c38b0287 (hw/registerfields.h: Add 8bit and 16bit register macros)
Use of uninitialized value in concatenation (.) or string at ./scripts/checkpatch.pl line 2484.
ERROR: Macros with multiple statements should be enclosed in a do - while loop
#27: FILE: include/hw/registerfields.h:25:
+#define REG8(reg, addr)                                                  \
+    enum { A_ ## reg = (addr) };                                          \
+    enum { R_ ## reg = (addr) };

ERROR: Macros with multiple statements should be enclosed in a do - while loop
#31: FILE: include/hw/registerfields.h:29:
+#define REG16(reg, addr)                                                  \
+    enum { A_ ## reg = (addr) };                                          \
+    enum { R_ ## reg = (addr) / 2 };

total: 2 errors, 0 warnings, 56 lines checked

Patch 3/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

4/22 Checking commit ba2df2186230 (target/rx: TCG translation)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#20: 
new file mode 100644

total: 0 errors, 1 warnings, 3065 lines checked

Patch 4/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
5/22 Checking commit 8abda6115755 (target/rx: TCG helper)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#21: 
new file mode 100644

total: 0 errors, 1 warnings, 650 lines checked

Patch 5/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
6/22 Checking commit 702f27d78dde (target/rx: CPU definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#39: 
new file mode 100644

total: 0 errors, 1 warnings, 588 lines checked

Patch 6/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
7/22 Checking commit e4f57d2f27c6 (target/rx: RX disassembler)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#38: 
new file mode 100644

total: 0 errors, 1 warnings, 1497 lines checked

Patch 7/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
8/22 Checking commit 9217628e8446 (target/rx: Disassemble rx_index_addr into a string)
9/22 Checking commit b58c020a513e (target/rx: Replace operand with prt_ldmi in disassembler)
10/22 Checking commit 04b36390113a (target/rx: Use prt_ldmi for XCHG_mr disassembly)
11/22 Checking commit 5f7675ee892f (target/rx: Emit all disassembly in one prt())
12/22 Checking commit a254a827a9c5 (target/rx: Collect all bytes during disassembly)
13/22 Checking commit 3200a284e4a4 (target/rx: Dump bytes for each insn during disassembly)
14/22 Checking commit 54ced3e375a8 (hw/intc: RX62N interrupt controller (ICUa))
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#40: 
new file mode 100644

total: 0 errors, 1 warnings, 445 lines checked

Patch 14/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
15/22 Checking commit 96aa2bf733b4 (hw/timer: RX62N internal timer modules)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#50: 
new file mode 100644

total: 0 errors, 1 warnings, 845 lines checked

Patch 15/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
16/22 Checking commit 6d1d3f22147c (hw/char: RX62N serial communication interface (SCI))
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#43: 
new file mode 100644

total: 0 errors, 1 warnings, 401 lines checked

Patch 16/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
17/22 Checking commit 4737268c2023 (hw/rx: RX Target hardware definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#29: 
new file mode 100644

total: 0 errors, 1 warnings, 480 lines checked

Patch 17/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
18/22 Checking commit 100e307f42ee (hw/rx: Honor -accel qtest)
19/22 Checking commit 53b5a3ea7549 (hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core)
20/22 Checking commit 21ccd2b57887 (Add rx-softmmu)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#59: 
new file mode 100644

total: 0 errors, 1 warnings, 59 lines checked

Patch 20/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
21/22 Checking commit 0a60bc15b465 (BootLinuxConsoleTest: Test the RX-Virt machine)
22/22 Checking commit c7211ec79d66 (qapi/machine.json: Add RX cpu.)
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20190912060701.4642-1-ysato@users.sourceforge.jp/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (22 preceding siblings ...)
  2019-09-12  6:39 ` [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support no-reply
@ 2019-09-12  7:47 ` no-reply
  2019-09-12  9:18 ` no-reply
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: no-reply @ 2019-09-12  7:47 UTC (permalink / raw)
  To: ysato
  Cc: peter.maydell, ysato, richard.henderson, qemu-devel, imammedo, philmd

Patchew URL: https://patchew.org/QEMU/20190912060701.4642-1-ysato@users.sourceforge.jp/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Subject: [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support
Message-id: 20190912060701.4642-1-ysato@users.sourceforge.jp
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 - [tag update]      patchew/20190911155125.11932-1-eric.auger@redhat.com -> patchew/20190911155125.11932-1-eric.auger@redhat.com
 - [tag update]      patchew/20190912060701.4642-1-ysato@users.sourceforge.jp -> patchew/20190912060701.4642-1-ysato@users.sourceforge.jp
Switched to a new branch 'test'
8840cbe qapi/machine.json: Add RX cpu.
4771d28 BootLinuxConsoleTest: Test the RX-Virt machine
0ec329e Add rx-softmmu
bbc35e0 hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
1101341 hw/rx: Honor -accel qtest
a74f685 hw/rx: RX Target hardware definition
d8a6c3f hw/char: RX62N serial communication interface (SCI)
19db804 hw/timer: RX62N internal timer modules
d62c0fc hw/intc: RX62N interrupt controller (ICUa)
fb0a977 target/rx: Dump bytes for each insn during disassembly
5f7434e target/rx: Collect all bytes during disassembly
85a2cc5 target/rx: Emit all disassembly in one prt()
522142f target/rx: Use prt_ldmi for XCHG_mr disassembly
1def58b target/rx: Replace operand with prt_ldmi in disassembler
c655e3d target/rx: Disassemble rx_index_addr into a string
96bdcb6 target/rx: RX disassembler
64e57e5 target/rx: CPU definition
de36389 target/rx: TCG helper
0663825 target/rx: TCG translation
36d9ad4 hw/registerfields.h: Add 8bit and 16bit register macros
f1d9a7f qemu/bitops.h: Add extract8 and extract16
a4c45e2 MAINTAINERS: Add RX

=== OUTPUT BEGIN ===
1/22 Checking commit a4c45e218ea4 (MAINTAINERS: Add RX)
2/22 Checking commit f1d9a7fda4d6 (qemu/bitops.h: Add extract8 and extract16)
3/22 Checking commit 36d9ad4d18a6 (hw/registerfields.h: Add 8bit and 16bit register macros)
Use of uninitialized value in concatenation (.) or string at ./scripts/checkpatch.pl line 2484.
ERROR: Macros with multiple statements should be enclosed in a do - while loop
#27: FILE: include/hw/registerfields.h:25:
+#define REG8(reg, addr)                                                  \
+    enum { A_ ## reg = (addr) };                                          \
+    enum { R_ ## reg = (addr) };

ERROR: Macros with multiple statements should be enclosed in a do - while loop
#31: FILE: include/hw/registerfields.h:29:
+#define REG16(reg, addr)                                                  \
+    enum { A_ ## reg = (addr) };                                          \
+    enum { R_ ## reg = (addr) / 2 };

total: 2 errors, 0 warnings, 56 lines checked

Patch 3/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

4/22 Checking commit 066382540c53 (target/rx: TCG translation)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#20: 
new file mode 100644

total: 0 errors, 1 warnings, 3065 lines checked

Patch 4/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
5/22 Checking commit de3638959b10 (target/rx: TCG helper)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#21: 
new file mode 100644

total: 0 errors, 1 warnings, 650 lines checked

Patch 5/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
6/22 Checking commit 64e57e51cdfe (target/rx: CPU definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#39: 
new file mode 100644

total: 0 errors, 1 warnings, 588 lines checked

Patch 6/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
7/22 Checking commit 96bdcb65077f (target/rx: RX disassembler)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#38: 
new file mode 100644

total: 0 errors, 1 warnings, 1497 lines checked

Patch 7/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
8/22 Checking commit c655e3d74d62 (target/rx: Disassemble rx_index_addr into a string)
9/22 Checking commit 1def58b9354e (target/rx: Replace operand with prt_ldmi in disassembler)
10/22 Checking commit 522142f319b1 (target/rx: Use prt_ldmi for XCHG_mr disassembly)
11/22 Checking commit 85a2cc54ba82 (target/rx: Emit all disassembly in one prt())
12/22 Checking commit 5f7434eb5757 (target/rx: Collect all bytes during disassembly)
13/22 Checking commit fb0a97747b43 (target/rx: Dump bytes for each insn during disassembly)
14/22 Checking commit d62c0fcfec86 (hw/intc: RX62N interrupt controller (ICUa))
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#40: 
new file mode 100644

total: 0 errors, 1 warnings, 445 lines checked

Patch 14/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
15/22 Checking commit 19db80403fae (hw/timer: RX62N internal timer modules)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#50: 
new file mode 100644

total: 0 errors, 1 warnings, 845 lines checked

Patch 15/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
16/22 Checking commit d8a6c3f3d21b (hw/char: RX62N serial communication interface (SCI))
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#43: 
new file mode 100644

total: 0 errors, 1 warnings, 401 lines checked

Patch 16/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
17/22 Checking commit a74f68504808 (hw/rx: RX Target hardware definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#29: 
new file mode 100644

total: 0 errors, 1 warnings, 480 lines checked

Patch 17/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
18/22 Checking commit 110134180d8b (hw/rx: Honor -accel qtest)
19/22 Checking commit bbc35e031774 (hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core)
20/22 Checking commit 0ec329eeeee1 (Add rx-softmmu)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#59: 
new file mode 100644

total: 0 errors, 1 warnings, 59 lines checked

Patch 20/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
21/22 Checking commit 4771d283f8a5 (BootLinuxConsoleTest: Test the RX-Virt machine)
22/22 Checking commit 8840cbe6b3ab (qapi/machine.json: Add RX cpu.)
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20190912060701.4642-1-ysato@users.sourceforge.jp/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (23 preceding siblings ...)
  2019-09-12  7:47 ` no-reply
@ 2019-09-12  9:18 ` no-reply
  2019-09-12  9:40 ` no-reply
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: no-reply @ 2019-09-12  9:18 UTC (permalink / raw)
  To: ysato
  Cc: peter.maydell, ysato, richard.henderson, qemu-devel, imammedo, philmd

Patchew URL: https://patchew.org/QEMU/20190912060701.4642-1-ysato@users.sourceforge.jp/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Subject: [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support
Message-id: 20190912060701.4642-1-ysato@users.sourceforge.jp
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
672cebc qapi/machine.json: Add RX cpu.
5470489 BootLinuxConsoleTest: Test the RX-Virt machine
7c0507a Add rx-softmmu
2f5604b hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
35359c6 hw/rx: Honor -accel qtest
4e38d1e hw/rx: RX Target hardware definition
5eed65b hw/char: RX62N serial communication interface (SCI)
70855a7 hw/timer: RX62N internal timer modules
9fdcd72 hw/intc: RX62N interrupt controller (ICUa)
2e4ae69 target/rx: Dump bytes for each insn during disassembly
25ff366 target/rx: Collect all bytes during disassembly
8ec9dc5 target/rx: Emit all disassembly in one prt()
be71e73 target/rx: Use prt_ldmi for XCHG_mr disassembly
aa2175d target/rx: Replace operand with prt_ldmi in disassembler
48ed0fb target/rx: Disassemble rx_index_addr into a string
d4bbb21 target/rx: RX disassembler
cc17d1a target/rx: CPU definition
27b404b target/rx: TCG helper
4d35681 target/rx: TCG translation
6c2f3d2 hw/registerfields.h: Add 8bit and 16bit register macros
bd8a862 qemu/bitops.h: Add extract8 and extract16
2ab4d1d MAINTAINERS: Add RX

=== OUTPUT BEGIN ===
1/22 Checking commit 2ab4d1de3b6b (MAINTAINERS: Add RX)
2/22 Checking commit bd8a8623b650 (qemu/bitops.h: Add extract8 and extract16)
3/22 Checking commit 6c2f3d225fa5 (hw/registerfields.h: Add 8bit and 16bit register macros)
Use of uninitialized value in concatenation (.) or string at ./scripts/checkpatch.pl line 2484.
ERROR: Macros with multiple statements should be enclosed in a do - while loop
#27: FILE: include/hw/registerfields.h:25:
+#define REG8(reg, addr)                                                  \
+    enum { A_ ## reg = (addr) };                                          \
+    enum { R_ ## reg = (addr) };

ERROR: Macros with multiple statements should be enclosed in a do - while loop
#31: FILE: include/hw/registerfields.h:29:
+#define REG16(reg, addr)                                                  \
+    enum { A_ ## reg = (addr) };                                          \
+    enum { R_ ## reg = (addr) / 2 };

total: 2 errors, 0 warnings, 56 lines checked

Patch 3/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

4/22 Checking commit 4d356815dd13 (target/rx: TCG translation)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#20: 
new file mode 100644

total: 0 errors, 1 warnings, 3065 lines checked

Patch 4/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
5/22 Checking commit 27b404b9078d (target/rx: TCG helper)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#21: 
new file mode 100644

total: 0 errors, 1 warnings, 650 lines checked

Patch 5/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
6/22 Checking commit cc17d1accf57 (target/rx: CPU definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#39: 
new file mode 100644

total: 0 errors, 1 warnings, 588 lines checked

Patch 6/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
7/22 Checking commit d4bbb21de8d1 (target/rx: RX disassembler)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#38: 
new file mode 100644

total: 0 errors, 1 warnings, 1497 lines checked

Patch 7/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
8/22 Checking commit 48ed0fb6bc35 (target/rx: Disassemble rx_index_addr into a string)
9/22 Checking commit aa2175df5901 (target/rx: Replace operand with prt_ldmi in disassembler)
10/22 Checking commit be71e734f793 (target/rx: Use prt_ldmi for XCHG_mr disassembly)
11/22 Checking commit 8ec9dc58c13f (target/rx: Emit all disassembly in one prt())
12/22 Checking commit 25ff366929de (target/rx: Collect all bytes during disassembly)
13/22 Checking commit 2e4ae6986d66 (target/rx: Dump bytes for each insn during disassembly)
14/22 Checking commit 9fdcd721382e (hw/intc: RX62N interrupt controller (ICUa))
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#40: 
new file mode 100644

total: 0 errors, 1 warnings, 445 lines checked

Patch 14/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
15/22 Checking commit 70855a767490 (hw/timer: RX62N internal timer modules)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#50: 
new file mode 100644

total: 0 errors, 1 warnings, 845 lines checked

Patch 15/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
16/22 Checking commit 5eed65b22dee (hw/char: RX62N serial communication interface (SCI))
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#43: 
new file mode 100644

total: 0 errors, 1 warnings, 401 lines checked

Patch 16/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
17/22 Checking commit 4e38d1ec8a27 (hw/rx: RX Target hardware definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#29: 
new file mode 100644

total: 0 errors, 1 warnings, 480 lines checked

Patch 17/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
18/22 Checking commit 35359c66753f (hw/rx: Honor -accel qtest)
19/22 Checking commit 2f5604b4ac6c (hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core)
20/22 Checking commit 7c0507a16ffd (Add rx-softmmu)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#59: 
new file mode 100644

total: 0 errors, 1 warnings, 59 lines checked

Patch 20/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
21/22 Checking commit 5470489924c3 (BootLinuxConsoleTest: Test the RX-Virt machine)
22/22 Checking commit 672cebcb0d1f (qapi/machine.json: Add RX cpu.)
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20190912060701.4642-1-ysato@users.sourceforge.jp/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (24 preceding siblings ...)
  2019-09-12  9:18 ` no-reply
@ 2019-09-12  9:40 ` no-reply
  2019-09-12 10:30 ` no-reply
  2019-09-12 11:09 ` no-reply
  27 siblings, 0 replies; 31+ messages in thread
From: no-reply @ 2019-09-12  9:40 UTC (permalink / raw)
  To: ysato
  Cc: peter.maydell, ysato, richard.henderson, qemu-devel, imammedo, philmd

Patchew URL: https://patchew.org/QEMU/20190912060701.4642-1-ysato@users.sourceforge.jp/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Subject: [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support
Message-id: 20190912060701.4642-1-ysato@users.sourceforge.jp
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

From https://github.com/patchew-project/qemu
 - [tag update]      patchew/20190912060701.4642-1-ysato@users.sourceforge.jp -> patchew/20190912060701.4642-1-ysato@users.sourceforge.jp
Switched to a new branch 'test'
4839961 qapi/machine.json: Add RX cpu.
ee1a34c BootLinuxConsoleTest: Test the RX-Virt machine
4bce111 Add rx-softmmu
dd0ced9 hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
c96b527 hw/rx: Honor -accel qtest
edda463 hw/rx: RX Target hardware definition
c0a3cae hw/char: RX62N serial communication interface (SCI)
fc2fa4e hw/timer: RX62N internal timer modules
df2c149 hw/intc: RX62N interrupt controller (ICUa)
c3fa177 target/rx: Dump bytes for each insn during disassembly
9fee305 target/rx: Collect all bytes during disassembly
2ce3519 target/rx: Emit all disassembly in one prt()
60ad535 target/rx: Use prt_ldmi for XCHG_mr disassembly
4f15796 target/rx: Replace operand with prt_ldmi in disassembler
54f46ef target/rx: Disassemble rx_index_addr into a string
b0f939a target/rx: RX disassembler
3343ef5 target/rx: CPU definition
20e5daa target/rx: TCG helper
d345ff0 target/rx: TCG translation
a6c73ed hw/registerfields.h: Add 8bit and 16bit register macros
624d286 qemu/bitops.h: Add extract8 and extract16
7a7544c MAINTAINERS: Add RX

=== OUTPUT BEGIN ===
1/22 Checking commit 7a7544c80606 (MAINTAINERS: Add RX)
2/22 Checking commit 624d286dbc3b (qemu/bitops.h: Add extract8 and extract16)
3/22 Checking commit a6c73edab979 (hw/registerfields.h: Add 8bit and 16bit register macros)
Use of uninitialized value in concatenation (.) or string at ./scripts/checkpatch.pl line 2484.
ERROR: Macros with multiple statements should be enclosed in a do - while loop
#27: FILE: include/hw/registerfields.h:25:
+#define REG8(reg, addr)                                                  \
+    enum { A_ ## reg = (addr) };                                          \
+    enum { R_ ## reg = (addr) };

ERROR: Macros with multiple statements should be enclosed in a do - while loop
#31: FILE: include/hw/registerfields.h:29:
+#define REG16(reg, addr)                                                  \
+    enum { A_ ## reg = (addr) };                                          \
+    enum { R_ ## reg = (addr) / 2 };

total: 2 errors, 0 warnings, 56 lines checked

Patch 3/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

4/22 Checking commit d345ff0914d4 (target/rx: TCG translation)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#20: 
new file mode 100644

total: 0 errors, 1 warnings, 3065 lines checked

Patch 4/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
5/22 Checking commit 20e5daaba751 (target/rx: TCG helper)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#21: 
new file mode 100644

total: 0 errors, 1 warnings, 650 lines checked

Patch 5/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
6/22 Checking commit 3343ef5d08c6 (target/rx: CPU definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#39: 
new file mode 100644

total: 0 errors, 1 warnings, 588 lines checked

Patch 6/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
7/22 Checking commit b0f939a431d1 (target/rx: RX disassembler)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#38: 
new file mode 100644

total: 0 errors, 1 warnings, 1497 lines checked

Patch 7/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
8/22 Checking commit 54f46ef1d86a (target/rx: Disassemble rx_index_addr into a string)
9/22 Checking commit 4f157967ac8c (target/rx: Replace operand with prt_ldmi in disassembler)
10/22 Checking commit 60ad5358dfcf (target/rx: Use prt_ldmi for XCHG_mr disassembly)
11/22 Checking commit 2ce3519386d5 (target/rx: Emit all disassembly in one prt())
12/22 Checking commit 9fee3055f6b2 (target/rx: Collect all bytes during disassembly)
13/22 Checking commit c3fa177cd274 (target/rx: Dump bytes for each insn during disassembly)
14/22 Checking commit df2c14900c44 (hw/intc: RX62N interrupt controller (ICUa))
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#40: 
new file mode 100644

total: 0 errors, 1 warnings, 445 lines checked

Patch 14/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
15/22 Checking commit fc2fa4e6ee7a (hw/timer: RX62N internal timer modules)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#50: 
new file mode 100644

total: 0 errors, 1 warnings, 845 lines checked

Patch 15/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
16/22 Checking commit c0a3cae6bf5a (hw/char: RX62N serial communication interface (SCI))
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#43: 
new file mode 100644

total: 0 errors, 1 warnings, 401 lines checked

Patch 16/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
17/22 Checking commit edda463ad0aa (hw/rx: RX Target hardware definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#29: 
new file mode 100644

total: 0 errors, 1 warnings, 480 lines checked

Patch 17/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
18/22 Checking commit c96b527d5cc1 (hw/rx: Honor -accel qtest)
19/22 Checking commit dd0ced9a2709 (hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core)
20/22 Checking commit 4bce11113551 (Add rx-softmmu)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#59: 
new file mode 100644

total: 0 errors, 1 warnings, 59 lines checked

Patch 20/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
21/22 Checking commit ee1a34c691b4 (BootLinuxConsoleTest: Test the RX-Virt machine)
22/22 Checking commit 4839961c0c48 (qapi/machine.json: Add RX cpu.)
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20190912060701.4642-1-ysato@users.sourceforge.jp/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (25 preceding siblings ...)
  2019-09-12  9:40 ` no-reply
@ 2019-09-12 10:30 ` no-reply
  2019-09-12 11:09 ` no-reply
  27 siblings, 0 replies; 31+ messages in thread
From: no-reply @ 2019-09-12 10:30 UTC (permalink / raw)
  To: ysato
  Cc: peter.maydell, ysato, richard.henderson, qemu-devel, imammedo, philmd

Patchew URL: https://patchew.org/QEMU/20190912060701.4642-1-ysato@users.sourceforge.jp/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Subject: [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support
Message-id: 20190912060701.4642-1-ysato@users.sourceforge.jp
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
854b969 qapi/machine.json: Add RX cpu.
40265e4 BootLinuxConsoleTest: Test the RX-Virt machine
a426c56 Add rx-softmmu
bf7b8b6 hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
e33fc18 hw/rx: Honor -accel qtest
c1f8515 hw/rx: RX Target hardware definition
ff330e1 hw/char: RX62N serial communication interface (SCI)
d9b6ec7 hw/timer: RX62N internal timer modules
61b5881 hw/intc: RX62N interrupt controller (ICUa)
449d7d2 target/rx: Dump bytes for each insn during disassembly
2324075 target/rx: Collect all bytes during disassembly
9d9e64f target/rx: Emit all disassembly in one prt()
bd10603 target/rx: Use prt_ldmi for XCHG_mr disassembly
621d97e target/rx: Replace operand with prt_ldmi in disassembler
faf812b target/rx: Disassemble rx_index_addr into a string
8836e1a target/rx: RX disassembler
9484d60 target/rx: CPU definition
280801b target/rx: TCG helper
e60db75 target/rx: TCG translation
2c8d76b hw/registerfields.h: Add 8bit and 16bit register macros
18cb0d7 qemu/bitops.h: Add extract8 and extract16
4441ef6 MAINTAINERS: Add RX

=== OUTPUT BEGIN ===
1/22 Checking commit 4441ef69b003 (MAINTAINERS: Add RX)
2/22 Checking commit 18cb0d7779c4 (qemu/bitops.h: Add extract8 and extract16)
3/22 Checking commit 2c8d76b1623d (hw/registerfields.h: Add 8bit and 16bit register macros)
Use of uninitialized value in concatenation (.) or string at ./scripts/checkpatch.pl line 2484.
ERROR: Macros with multiple statements should be enclosed in a do - while loop
#27: FILE: include/hw/registerfields.h:25:
+#define REG8(reg, addr)                                                  \
+    enum { A_ ## reg = (addr) };                                          \
+    enum { R_ ## reg = (addr) };

ERROR: Macros with multiple statements should be enclosed in a do - while loop
#31: FILE: include/hw/registerfields.h:29:
+#define REG16(reg, addr)                                                  \
+    enum { A_ ## reg = (addr) };                                          \
+    enum { R_ ## reg = (addr) / 2 };

total: 2 errors, 0 warnings, 56 lines checked

Patch 3/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

4/22 Checking commit e60db75852e0 (target/rx: TCG translation)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#20: 
new file mode 100644

total: 0 errors, 1 warnings, 3065 lines checked

Patch 4/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
5/22 Checking commit 280801b8d545 (target/rx: TCG helper)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#21: 
new file mode 100644

total: 0 errors, 1 warnings, 650 lines checked

Patch 5/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
6/22 Checking commit 9484d60bcbeb (target/rx: CPU definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#39: 
new file mode 100644

total: 0 errors, 1 warnings, 588 lines checked

Patch 6/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
7/22 Checking commit 8836e1a85647 (target/rx: RX disassembler)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#38: 
new file mode 100644

total: 0 errors, 1 warnings, 1497 lines checked

Patch 7/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
8/22 Checking commit faf812b3f51b (target/rx: Disassemble rx_index_addr into a string)
9/22 Checking commit 621d97ea9533 (target/rx: Replace operand with prt_ldmi in disassembler)
10/22 Checking commit bd1060338c1b (target/rx: Use prt_ldmi for XCHG_mr disassembly)
11/22 Checking commit 9d9e64f6c956 (target/rx: Emit all disassembly in one prt())
12/22 Checking commit 23240751bf85 (target/rx: Collect all bytes during disassembly)
13/22 Checking commit 449d7d244352 (target/rx: Dump bytes for each insn during disassembly)
14/22 Checking commit 61b5881909fe (hw/intc: RX62N interrupt controller (ICUa))
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#40: 
new file mode 100644

total: 0 errors, 1 warnings, 445 lines checked

Patch 14/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
15/22 Checking commit d9b6ec7b8832 (hw/timer: RX62N internal timer modules)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#50: 
new file mode 100644

total: 0 errors, 1 warnings, 845 lines checked

Patch 15/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
16/22 Checking commit ff330e15b104 (hw/char: RX62N serial communication interface (SCI))
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#43: 
new file mode 100644

total: 0 errors, 1 warnings, 401 lines checked

Patch 16/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
17/22 Checking commit c1f851529a0f (hw/rx: RX Target hardware definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#29: 
new file mode 100644

total: 0 errors, 1 warnings, 480 lines checked

Patch 17/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
18/22 Checking commit e33fc1839e70 (hw/rx: Honor -accel qtest)
19/22 Checking commit bf7b8b6d98d1 (hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core)
20/22 Checking commit a426c56f9cfe (Add rx-softmmu)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#59: 
new file mode 100644

total: 0 errors, 1 warnings, 59 lines checked

Patch 20/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
21/22 Checking commit 40265e40369a (BootLinuxConsoleTest: Test the RX-Virt machine)
22/22 Checking commit 854b969dc208 (qapi/machine.json: Add RX cpu.)
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20190912060701.4642-1-ysato@users.sourceforge.jp/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support
  2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
                   ` (26 preceding siblings ...)
  2019-09-12 10:30 ` no-reply
@ 2019-09-12 11:09 ` no-reply
  27 siblings, 0 replies; 31+ messages in thread
From: no-reply @ 2019-09-12 11:09 UTC (permalink / raw)
  To: ysato
  Cc: peter.maydell, ysato, richard.henderson, qemu-devel, imammedo, philmd

Patchew URL: https://patchew.org/QEMU/20190912060701.4642-1-ysato@users.sourceforge.jp/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Subject: [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support
Message-id: 20190912060701.4642-1-ysato@users.sourceforge.jp
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

From https://github.com/patchew-project/qemu
 - [tag update]      patchew/20190912060701.4642-1-ysato@users.sourceforge.jp -> patchew/20190912060701.4642-1-ysato@users.sourceforge.jp
Switched to a new branch 'test'
b344509 qapi/machine.json: Add RX cpu.
dbc4316 BootLinuxConsoleTest: Test the RX-Virt machine
a73dba4 Add rx-softmmu
9e326f2 hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
0e20757 hw/rx: Honor -accel qtest
b8ef978 hw/rx: RX Target hardware definition
a6e9525 hw/char: RX62N serial communication interface (SCI)
523f6ae hw/timer: RX62N internal timer modules
dd7c03a hw/intc: RX62N interrupt controller (ICUa)
034ef9c target/rx: Dump bytes for each insn during disassembly
4a9f231 target/rx: Collect all bytes during disassembly
52ea55b target/rx: Emit all disassembly in one prt()
c6a6fa3 target/rx: Use prt_ldmi for XCHG_mr disassembly
9d2d4c2 target/rx: Replace operand with prt_ldmi in disassembler
9409eea target/rx: Disassemble rx_index_addr into a string
24a6ce3 target/rx: RX disassembler
4324951 target/rx: CPU definition
e013cf2 target/rx: TCG helper
2f5906e target/rx: TCG translation
bd2b801 hw/registerfields.h: Add 8bit and 16bit register macros
ffecfbc qemu/bitops.h: Add extract8 and extract16
08c4e97 MAINTAINERS: Add RX

=== OUTPUT BEGIN ===
1/22 Checking commit 08c4e975d29f (MAINTAINERS: Add RX)
2/22 Checking commit ffecfbc89a8c (qemu/bitops.h: Add extract8 and extract16)
3/22 Checking commit bd2b8012f2e5 (hw/registerfields.h: Add 8bit and 16bit register macros)
Use of uninitialized value in concatenation (.) or string at ./scripts/checkpatch.pl line 2484.
ERROR: Macros with multiple statements should be enclosed in a do - while loop
#27: FILE: include/hw/registerfields.h:25:
+#define REG8(reg, addr)                                                  \
+    enum { A_ ## reg = (addr) };                                          \
+    enum { R_ ## reg = (addr) };

ERROR: Macros with multiple statements should be enclosed in a do - while loop
#31: FILE: include/hw/registerfields.h:29:
+#define REG16(reg, addr)                                                  \
+    enum { A_ ## reg = (addr) };                                          \
+    enum { R_ ## reg = (addr) / 2 };

total: 2 errors, 0 warnings, 56 lines checked

Patch 3/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

4/22 Checking commit 2f5906ec35fa (target/rx: TCG translation)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#20: 
new file mode 100644

total: 0 errors, 1 warnings, 3065 lines checked

Patch 4/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
5/22 Checking commit e013cf2e29f7 (target/rx: TCG helper)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#21: 
new file mode 100644

total: 0 errors, 1 warnings, 650 lines checked

Patch 5/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
6/22 Checking commit 432495109747 (target/rx: CPU definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#39: 
new file mode 100644

total: 0 errors, 1 warnings, 588 lines checked

Patch 6/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
7/22 Checking commit 24a6ce386bc6 (target/rx: RX disassembler)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#38: 
new file mode 100644

total: 0 errors, 1 warnings, 1497 lines checked

Patch 7/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
8/22 Checking commit 9409eeafa61d (target/rx: Disassemble rx_index_addr into a string)
9/22 Checking commit 9d2d4c2a3f48 (target/rx: Replace operand with prt_ldmi in disassembler)
10/22 Checking commit c6a6fa3f837f (target/rx: Use prt_ldmi for XCHG_mr disassembly)
11/22 Checking commit 52ea55be5ba4 (target/rx: Emit all disassembly in one prt())
12/22 Checking commit 4a9f231d6170 (target/rx: Collect all bytes during disassembly)
13/22 Checking commit 034ef9cc868c (target/rx: Dump bytes for each insn during disassembly)
14/22 Checking commit dd7c03aa119a (hw/intc: RX62N interrupt controller (ICUa))
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#40: 
new file mode 100644

total: 0 errors, 1 warnings, 445 lines checked

Patch 14/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
15/22 Checking commit 523f6ae3c8eb (hw/timer: RX62N internal timer modules)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#50: 
new file mode 100644

total: 0 errors, 1 warnings, 845 lines checked

Patch 15/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
16/22 Checking commit a6e952569108 (hw/char: RX62N serial communication interface (SCI))
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#43: 
new file mode 100644

total: 0 errors, 1 warnings, 401 lines checked

Patch 16/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
17/22 Checking commit b8ef9788960c (hw/rx: RX Target hardware definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#29: 
new file mode 100644

total: 0 errors, 1 warnings, 480 lines checked

Patch 17/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
18/22 Checking commit 0e207577f922 (hw/rx: Honor -accel qtest)
19/22 Checking commit 9e326f205701 (hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core)
20/22 Checking commit a73dba432bb2 (Add rx-softmmu)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#59: 
new file mode 100644

total: 0 errors, 1 warnings, 59 lines checked

Patch 20/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
21/22 Checking commit dbc431623329 (BootLinuxConsoleTest: Test the RX-Virt machine)
22/22 Checking commit b344509cdbc8 (qapi/machine.json: Add RX cpu.)
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20190912060701.4642-1-ysato@users.sourceforge.jp/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PATCH v24 22/22] qapi/machine.json: Add RX cpu.
  2019-09-12  6:07 ` [Qemu-devel] [PATCH v24 22/22] qapi/machine.json: Add RX cpu Yoshinori Sato
@ 2019-09-20 12:39   ` Eric Blake
  0 siblings, 0 replies; 31+ messages in thread
From: Eric Blake @ 2019-09-20 12:39 UTC (permalink / raw)
  To: Yoshinori Sato, qemu-devel
  Cc: peter.maydell, philmd, richard.henderson, imammedo


[-- Attachment #1.1: Type: text/plain, Size: 978 bytes --]

On 9/12/19 1:07 AM, Yoshinori Sato wrote:
> Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
> ---
>  qapi/machine.json | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/qapi/machine.json b/qapi/machine.json
> index ca26779f1a..70398c521f 100644
> --- a/qapi/machine.json
> +++ b/qapi/machine.json
> @@ -28,7 +28,7 @@
>    'data' : [ 'aarch64', 'alpha', 'arm', 'cris', 'hppa', 'i386', 'lm32',
>               'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
>               'mips64el', 'mipsel', 'moxie', 'nios2', 'or1k', 'ppc',
> -             'ppc64', 'riscv32', 'riscv64', 's390x', 'sh4',
> +             'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4',
>               'sh4eb', 'sparc', 'sparc64', 'tricore', 'unicore32',

Missing documentation mentioning that rx is since 4.2.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v24 06/22] target/rx: CPU definition
  2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 06/22] target/rx: CPU definition Yoshinori Sato
@ 2019-09-23 15:49   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-09-23 15:49 UTC (permalink / raw)
  To: Yoshinori Sato, qemu-devel; +Cc: peter.maydell, richard.henderson, imammedo

On 9/12/19 8:06 AM, Yoshinori Sato wrote:
> v21 changes

FYI Please add changes bellow the '---' separator.

> Add cpu-param.h
> Remove CPU_COMMON
> rx_load_image move to rx-virt.
> 
> Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
> 
> Message-Id: <20190616142836.10614-4-ysato@users.sourceforge.jp>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Message-Id: <20190607091116.49044-4-ysato@users.sourceforge.jp>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> [PMD: Use newer QOM style, split cpu-qom.h, restrict access to
>  extable array, use rx_cpu_tlb_fill() extracted from patch of
>  Yoshinori Sato 'Convert to CPUClass::tlb_fill']
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> 
> cpu.c: remove rx_load_image
> 
> Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>

This one has:
Acked-by: Igor Mammedov <imammedo@redhat.com>
https://www.mail-archive.com/qemu-devel@nongnu.org/msg625231.html

> ---

Here:

Changes since v21:
  ...

>  target/rx/cpu-param.h   |  31 ++++++
>  target/rx/cpu-qom.h     |  42 ++++++++
>  target/rx/cpu.h         | 181 +++++++++++++++++++++++++++++++++
>  target/rx/cpu.c         | 217 ++++++++++++++++++++++++++++++++++++++++
>  target/rx/gdbstub.c     | 112 +++++++++++++++++++++
>  target/rx/Makefile.objs |   1 -
>  6 files changed, 583 insertions(+), 1 deletion(-)
>  create mode 100644 target/rx/cpu-param.h
>  create mode 100644 target/rx/cpu-qom.h
>  create mode 100644 target/rx/cpu.h
>  create mode 100644 target/rx/cpu.c
>  create mode 100644 target/rx/gdbstub.c
[...]


^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2019-09-23 15:50 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-12  6:06 [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 01/22] MAINTAINERS: Add RX Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 02/22] qemu/bitops.h: Add extract8 and extract16 Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 03/22] hw/registerfields.h: Add 8bit and 16bit register macros Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 04/22] target/rx: TCG translation Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 05/22] target/rx: TCG helper Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 06/22] target/rx: CPU definition Yoshinori Sato
2019-09-23 15:49   ` Philippe Mathieu-Daudé
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 07/22] target/rx: RX disassembler Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 08/22] target/rx: Disassemble rx_index_addr into a string Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 09/22] target/rx: Replace operand with prt_ldmi in disassembler Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 10/22] target/rx: Use prt_ldmi for XCHG_mr disassembly Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 11/22] target/rx: Emit all disassembly in one prt() Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 12/22] target/rx: Collect all bytes during disassembly Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 13/22] target/rx: Dump bytes for each insn " Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 14/22] hw/intc: RX62N interrupt controller (ICUa) Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 15/22] hw/timer: RX62N internal timer modules Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 16/22] hw/char: RX62N serial communication interface (SCI) Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 17/22] hw/rx: RX Target hardware definition Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 18/22] hw/rx: Honor -accel qtest Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 19/22] hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core Yoshinori Sato
2019-09-12  6:06 ` [Qemu-devel] [PATCH v24 20/22] Add rx-softmmu Yoshinori Sato
2019-09-12  6:07 ` [Qemu-devel] [PATCH v24 21/22] BootLinuxConsoleTest: Test the RX-Virt machine Yoshinori Sato
2019-09-12  6:07 ` [Qemu-devel] [PATCH v24 22/22] qapi/machine.json: Add RX cpu Yoshinori Sato
2019-09-20 12:39   ` Eric Blake
2019-09-12  6:39 ` [Qemu-devel] [PATCH v24 00/22] Add RX archtecture support no-reply
2019-09-12  7:47 ` no-reply
2019-09-12  9:18 ` no-reply
2019-09-12  9:40 ` no-reply
2019-09-12 10:30 ` no-reply
2019-09-12 11:09 ` no-reply

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).