Introduce the architectural part of the Renesas RX
architecture emulation, developed by Yoshinori Sato. CI jobs results: https://gitlab.com/philmd/qemu/pipelines/127886344 https://travis-ci.org/github/philmd/qemu/builds/664579420 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAl50mpQACgkQ4+MsLN6t wN62zw//Y3ZRo9wYFIeILtDJzIzLRuZwmF1lN7j6o15gdwyjWjn08N4wsM/kyPPH hdF6faWYIoiAaxe5IHzI4dxhH+Mv6zyae1gpOVOAO4TzF1HNpdILrCBvQbJQu2lF jpqXBDeaa/4ugniANzSTVhCcelIdIoI56rV+E3hzgdoDxOrveA1m0NUGMGzSayEh xT+y/oaTfmgJHI9GBwSJFVTrI1+jMp6VnrOv5I0pZrE55g1IiZ0TTK12JheQMFvS 98MHFZ1PiKIJEVzEQTBra0T8hbTsZLETn35mOgt9Kf3YRN4Cgqel6gFGlgtXUs5z 8u+pVDb8cK4+hcyFs0FLtUqWO+SXMF215zT23ra/ebhcC2pQRVHlqOjlI85aaJnf 7VfLJFMd3U4tl/yqbkcmkkjc1zl0IQjaa2mLaS+xstWAXGEqeP8EGdhIIzxtHBgQ 1RgHzjbTYMenCisUwzvH9+I7Wc9LB8Vik1UrebbCju99zwt/cIG3FSlleSiuKbtX U5prRyBw4xyIe1IwcBUcuEBtibD473eBP/m2nF6TorHE0rH1X0n644aHSlTZhGoM G/GvMZ45zHGlOouqYHX81vzR/WfRBYNiFcXHkJ0Im4zkvpXEnsvoTei9wt2QQ1Wi YyHKxQUQo8OvBHR4QMUXbS2XVR0tv43NtDiR4mz+vhjC7eDCVc8= =mNmV -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/philmd-gitlab/tags/target_renesas_rx-20200320' into staging Introduce the architectural part of the Renesas RX architecture emulation, developed by Yoshinori Sato. CI jobs results: https://gitlab.com/philmd/qemu/pipelines/127886344 https://travis-ci.org/github/philmd/qemu/builds/664579420 # gpg: Signature made Fri 20 Mar 2020 10:27:32 GMT # gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE # gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full] # Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE * remotes/philmd-gitlab/tags/target_renesas_rx-20200320: Add rx-softmmu target/rx: Dump bytes for each insn during disassembly target/rx: Collect all bytes during disassembly target/rx: Emit all disassembly in one prt() target/rx: Use prt_ldmi for XCHG_mr disassembly target/rx: Replace operand with prt_ldmi in disassembler target/rx: Disassemble rx_index_addr into a string target/rx: RX disassembler target/rx: CPU definitions target/rx: TCG helpers target/rx: TCG translation MAINTAINERS: Add entry for the Renesas RX architecture hw/registerfields.h: Add 8bit and 16bit register macros Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
226cd20706
|
@ -277,6 +277,11 @@ F: include/hw/riscv/
|
||||||
F: linux-user/host/riscv32/
|
F: linux-user/host/riscv32/
|
||||||
F: linux-user/host/riscv64/
|
F: linux-user/host/riscv64/
|
||||||
|
|
||||||
|
RENESAS RX CPUs
|
||||||
|
M: Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||||
|
S: Maintained
|
||||||
|
F: target/rx/
|
||||||
|
|
||||||
S390 TCG CPUs
|
S390 TCG CPUs
|
||||||
M: Richard Henderson <rth@twiddle.net>
|
M: Richard Henderson <rth@twiddle.net>
|
||||||
M: David Hildenbrand <david@redhat.com>
|
M: David Hildenbrand <david@redhat.com>
|
||||||
|
|
|
@ -77,6 +77,8 @@ int graphic_depth = 32;
|
||||||
#define QEMU_ARCH QEMU_ARCH_PPC
|
#define QEMU_ARCH QEMU_ARCH_PPC
|
||||||
#elif defined(TARGET_RISCV)
|
#elif defined(TARGET_RISCV)
|
||||||
#define QEMU_ARCH QEMU_ARCH_RISCV
|
#define QEMU_ARCH QEMU_ARCH_RISCV
|
||||||
|
#elif defined(TARGET_RX)
|
||||||
|
#define QEMU_ARCH QEMU_ARCH_RX
|
||||||
#elif defined(TARGET_S390X)
|
#elif defined(TARGET_S390X)
|
||||||
#define QEMU_ARCH QEMU_ARCH_S390X
|
#define QEMU_ARCH QEMU_ARCH_S390X
|
||||||
#elif defined(TARGET_SH4)
|
#elif defined(TARGET_SH4)
|
||||||
|
|
11
configure
vendored
11
configure
vendored
|
@ -4227,7 +4227,7 @@ fi
|
||||||
fdt_required=no
|
fdt_required=no
|
||||||
for target in $target_list; do
|
for target in $target_list; do
|
||||||
case $target in
|
case $target in
|
||||||
aarch64*-softmmu|arm*-softmmu|ppc*-softmmu|microblaze*-softmmu|mips64el-softmmu|riscv*-softmmu)
|
aarch64*-softmmu|arm*-softmmu|ppc*-softmmu|microblaze*-softmmu|mips64el-softmmu|riscv*-softmmu|rx-softmmu)
|
||||||
fdt_required=yes
|
fdt_required=yes
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
@ -7912,6 +7912,12 @@ case "$target_name" in
|
||||||
mttcg=yes
|
mttcg=yes
|
||||||
gdb_xml_files="riscv-64bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-64bit-csr.xml riscv-64bit-virtual.xml"
|
gdb_xml_files="riscv-64bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-64bit-csr.xml riscv-64bit-virtual.xml"
|
||||||
;;
|
;;
|
||||||
|
rx)
|
||||||
|
TARGET_ARCH=rx
|
||||||
|
bflt="yes"
|
||||||
|
target_compiler=$cross_cc_rx
|
||||||
|
gdb_xml_files="rx-core.xml"
|
||||||
|
;;
|
||||||
sh4|sh4eb)
|
sh4|sh4eb)
|
||||||
TARGET_ARCH=sh4
|
TARGET_ARCH=sh4
|
||||||
bflt="yes"
|
bflt="yes"
|
||||||
|
@ -8093,6 +8099,9 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
|
||||||
riscv*)
|
riscv*)
|
||||||
disas_config "RISCV"
|
disas_config "RISCV"
|
||||||
;;
|
;;
|
||||||
|
rx)
|
||||||
|
disas_config "RX"
|
||||||
|
;;
|
||||||
s390*)
|
s390*)
|
||||||
disas_config "S390"
|
disas_config "S390"
|
||||||
;;
|
;;
|
||||||
|
|
2
default-configs/rx-softmmu.mak
Normal file
2
default-configs/rx-softmmu.mak
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# Default configuration for rx-softmmu
|
||||||
|
|
70
gdb-xml/rx-core.xml
Normal file
70
gdb-xml/rx-core.xml
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!-- Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved. -->
|
||||||
|
|
||||||
|
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
|
||||||
|
<feature name="org.gnu.gdb.rx.core">
|
||||||
|
<reg name="r0" bitsize="32" type="data_ptr"/>
|
||||||
|
<reg name="r1" bitsize="32" type="uint32"/>
|
||||||
|
<reg name="r2" bitsize="32" type="uint32"/>
|
||||||
|
<reg name="r3" bitsize="32" type="uint32"/>
|
||||||
|
<reg name="r4" bitsize="32" type="uint32"/>
|
||||||
|
<reg name="r5" bitsize="32" type="uint32"/>
|
||||||
|
<reg name="r6" bitsize="32" type="uint32"/>
|
||||||
|
<reg name="r7" bitsize="32" type="uint32"/>
|
||||||
|
<reg name="r8" bitsize="32" type="uint32"/>
|
||||||
|
<reg name="r9" bitsize="32" type="uint32"/>
|
||||||
|
<reg name="r10" bitsize="32" type="uint32"/>
|
||||||
|
<reg name="r11" bitsize="32" type="uint32"/>
|
||||||
|
<reg name="r12" bitsize="32" type="uint32"/>
|
||||||
|
<reg name="r13" bitsize="32" type="uint32"/>
|
||||||
|
<reg name="r14" bitsize="32" type="uint32"/>
|
||||||
|
<reg name="r15" bitsize="32" type="uint32"/>
|
||||||
|
|
||||||
|
<flags id="psw_flags" size="4">
|
||||||
|
<field name="C" start="0" end="0"/>
|
||||||
|
<field name="Z" start="1" end="1"/>
|
||||||
|
<field name="S" start="2" end="2"/>
|
||||||
|
<field name="O" start="3" end="3"/>
|
||||||
|
<field name="I" start="16" end="16"/>
|
||||||
|
<field name="U" start="17" end="17"/>
|
||||||
|
<field name="PM" start="20" end="20"/>
|
||||||
|
<field name="IPL" start="24" end="27"/>
|
||||||
|
</flags>
|
||||||
|
|
||||||
|
<flags id="fpsw_flags" size="4">
|
||||||
|
<field name="RM" start="0" end="1"/>
|
||||||
|
<field name="CV" start="2" end="2"/>
|
||||||
|
<field name="CO" start="3" end="3"/>
|
||||||
|
<field name="CZ" start="4" end="4"/>
|
||||||
|
<field name="CU" start="5" end="5"/>
|
||||||
|
<field name="CX" start="6" end="6"/>
|
||||||
|
<field name="CE" start="7" end="7"/>
|
||||||
|
<field name="DN" start="8" end="8"/>
|
||||||
|
<field name="EV" start="10" end="10"/>
|
||||||
|
<field name="EO" start="11" end="11"/>
|
||||||
|
<field name="EZ" start="12" end="12"/>
|
||||||
|
<field name="EU" start="13" end="13"/>
|
||||||
|
<field name="EX" start="14" end="14"/>
|
||||||
|
<field name="FV" start="26" end="26"/>
|
||||||
|
<field name="FO" start="27" end="27"/>
|
||||||
|
<field name="FZ" start="28" end="28"/>
|
||||||
|
<field name="FU" start="29" end="29"/>
|
||||||
|
<field name="FX" start="30" end="30"/>
|
||||||
|
<field name="FS" start="31" end="31"/>
|
||||||
|
</flags>
|
||||||
|
|
||||||
|
<reg name="usp" bitsize="32" type="data_ptr"/>
|
||||||
|
<reg name="isp" bitsize="32" type="data_ptr"/>
|
||||||
|
<reg name="psw" bitsize="32" type="psw_flags"/>
|
||||||
|
<reg name="pc" bitsize="32" type="code_ptr"/>
|
||||||
|
<reg name="intb" bitsize="32" type="data_ptr"/>
|
||||||
|
<reg name="bpsw" bitsize="32" type="psw_flags"/>
|
||||||
|
<reg name="bpc" bitsize="32" type="code_ptr"/>
|
||||||
|
<reg name="fintv" bitsize="32" type="code_ptr"/>
|
||||||
|
<reg name="fpsw" bitsize="32" type="fpsw_flags"/>
|
||||||
|
<reg name="acc" bitsize="64" type="uint64"/>
|
||||||
|
</feature>
|
|
@ -226,6 +226,10 @@ enum bfd_architecture
|
||||||
#define bfd_mach_nios2r2 2
|
#define bfd_mach_nios2r2 2
|
||||||
bfd_arch_lm32, /* Lattice Mico32 */
|
bfd_arch_lm32, /* Lattice Mico32 */
|
||||||
#define bfd_mach_lm32 1
|
#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
|
bfd_arch_last
|
||||||
};
|
};
|
||||||
#define bfd_mach_s390_31 31
|
#define bfd_mach_s390_31 31
|
||||||
|
@ -436,6 +440,7 @@ int print_insn_little_nios2 (bfd_vma, disassemble_info*);
|
||||||
int print_insn_xtensa (bfd_vma, disassemble_info*);
|
int print_insn_xtensa (bfd_vma, disassemble_info*);
|
||||||
int print_insn_riscv32 (bfd_vma, disassemble_info*);
|
int print_insn_riscv32 (bfd_vma, disassemble_info*);
|
||||||
int print_insn_riscv64 (bfd_vma, disassemble_info*);
|
int print_insn_riscv64 (bfd_vma, disassemble_info*);
|
||||||
|
int print_insn_rx(bfd_vma, disassemble_info *);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Fetch the disassembler for a given BFD, if that support is available. */
|
/* Fetch the disassembler for a given BFD, if that support is available. */
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#pragma GCC poison TARGET_PPC
|
#pragma GCC poison TARGET_PPC
|
||||||
#pragma GCC poison TARGET_PPC64
|
#pragma GCC poison TARGET_PPC64
|
||||||
#pragma GCC poison TARGET_ABI32
|
#pragma GCC poison TARGET_ABI32
|
||||||
|
#pragma GCC poison TARGET_RX
|
||||||
#pragma GCC poison TARGET_S390X
|
#pragma GCC poison TARGET_S390X
|
||||||
#pragma GCC poison TARGET_SH4
|
#pragma GCC poison TARGET_SH4
|
||||||
#pragma GCC poison TARGET_SPARC
|
#pragma GCC poison TARGET_SPARC
|
||||||
|
|
|
@ -22,6 +22,14 @@
|
||||||
enum { A_ ## reg = (addr) }; \
|
enum { A_ ## reg = (addr) }; \
|
||||||
enum { R_ ## reg = (addr) / 4 };
|
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 */
|
/* 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
|
/* 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)};
|
MAKE_64BIT_MASK(shift, length)};
|
||||||
|
|
||||||
/* Extract a field from a register */
|
/* 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) \
|
#define FIELD_EX32(storage, reg, field) \
|
||||||
extract32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
|
extract32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
|
||||||
R_ ## reg ## _ ## field ## _LENGTH)
|
R_ ## reg ## _ ## field ## _LENGTH)
|
||||||
|
@ -49,6 +63,22 @@
|
||||||
* Assigning values larger then the target field will result in
|
* Assigning values larger then the target field will result in
|
||||||
* compilation warnings.
|
* 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) ({ \
|
#define FIELD_DP32(storage, reg, field, val) ({ \
|
||||||
struct { \
|
struct { \
|
||||||
unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \
|
unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \
|
||||||
|
|
|
@ -24,6 +24,7 @@ enum {
|
||||||
QEMU_ARCH_NIOS2 = (1 << 17),
|
QEMU_ARCH_NIOS2 = (1 << 17),
|
||||||
QEMU_ARCH_HPPA = (1 << 18),
|
QEMU_ARCH_HPPA = (1 << 18),
|
||||||
QEMU_ARCH_RISCV = (1 << 19),
|
QEMU_ARCH_RISCV = (1 << 19),
|
||||||
|
QEMU_ARCH_RX = (1 << 20),
|
||||||
|
|
||||||
QEMU_ARCH_NONE = (1 << 31),
|
QEMU_ARCH_NONE = (1 << 31),
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
# individual target constants are not documented here, for the time
|
# individual target constants are not documented here, for the time
|
||||||
# being.
|
# being.
|
||||||
#
|
#
|
||||||
|
# @rx: since 5.0
|
||||||
|
#
|
||||||
# Notes: The resulting QMP strings can be appended to the "qemu-system-"
|
# Notes: The resulting QMP strings can be appended to the "qemu-system-"
|
||||||
# prefix to produce the corresponding QEMU executable name. This
|
# prefix to produce the corresponding QEMU executable name. This
|
||||||
# is true even for "qemu-system-x86_64".
|
# is true even for "qemu-system-x86_64".
|
||||||
|
@ -26,7 +28,7 @@
|
||||||
'data' : [ 'aarch64', 'alpha', 'arm', 'cris', 'hppa', 'i386', 'lm32',
|
'data' : [ 'aarch64', 'alpha', 'arm', 'cris', 'hppa', 'i386', 'lm32',
|
||||||
'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
|
'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
|
||||||
'mips64el', 'mipsel', 'moxie', 'nios2', 'or1k', 'ppc',
|
'mips64el', 'mipsel', 'moxie', 'nios2', 'or1k', 'ppc',
|
||||||
'ppc64', 'riscv32', 'riscv64', 's390x', 'sh4',
|
'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4',
|
||||||
'sh4eb', 'sparc', 'sparc64', 'tricore', 'unicore32',
|
'sh4eb', 'sparc', 'sparc64', 'tricore', 'unicore32',
|
||||||
'x86_64', 'xtensa', 'xtensaeb' ] }
|
'x86_64', 'xtensa', 'xtensaeb' ] }
|
||||||
|
|
||||||
|
|
11
target/rx/Makefile.objs
Normal file
11
target/rx/Makefile.objs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
obj-y += translate.o op_helper.o helper.o cpu.o gdbstub.o disas.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
|
30
target/rx/cpu-param.h
Normal file
30
target/rx/cpu-param.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
#endif
|
53
target/rx/cpu-qom.h
Normal file
53
target/rx/cpu-qom.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RX_CPU_QOM_H
|
||||||
|
#define RX_CPU_QOM_H
|
||||||
|
|
||||||
|
#include "hw/core/cpu.h"
|
||||||
|
|
||||||
|
#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;
|
||||||
|
DeviceReset parent_reset;
|
||||||
|
} RXCPUClass;
|
||||||
|
|
||||||
|
#define CPUArchState struct CPURXState
|
||||||
|
|
||||||
|
#endif
|
225
target/rx/cpu.c
Normal file
225
target/rx/cpu.c
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
/*
|
||||||
|
* 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(DeviceState *dev)
|
||||||
|
{
|
||||||
|
RXCPU *cpu = RXCPU(dev);
|
||||||
|
RXCPUClass *rcc = RXCPU_GET_CLASS(cpu);
|
||||||
|
CPURXState *env = &cpu->env;
|
||||||
|
uint32_t *resetvec;
|
||||||
|
|
||||||
|
rcc->parent_reset(dev);
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
ObjectClass *oc = data;
|
||||||
|
|
||||||
|
qemu_printf(" %s\n", object_class_get_name(oc));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rx_cpu_list(void)
|
||||||
|
{
|
||||||
|
GSList *list;
|
||||||
|
list = object_class_get_list_sorted(TYPE_RX_CPU, false);
|
||||||
|
qemu_printf("Available CPUs:\n");
|
||||||
|
g_slist_foreach(list, rx_cpu_list_entry, NULL);
|
||||||
|
g_slist_free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ObjectClass *rx_cpu_class_by_name(const char *cpu_model)
|
||||||
|
{
|
||||||
|
ObjectClass *oc;
|
||||||
|
char *typename;
|
||||||
|
|
||||||
|
oc = object_class_by_name(cpu_model);
|
||||||
|
if (oc != NULL && object_class_dynamic_cast(oc, TYPE_RX_CPU) != NULL &&
|
||||||
|
!object_class_is_abstract(oc)) {
|
||||||
|
return oc;
|
||||||
|
}
|
||||||
|
typename = g_strdup_printf(RX_CPU_TYPE_NAME("%s"), cpu_model);
|
||||||
|
oc = object_class_by_name(typename);
|
||||||
|
g_free(typename);
|
||||||
|
if (oc != 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_init_vcpu(cs);
|
||||||
|
cpu_reset(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);
|
||||||
|
device_class_set_parent_reset(dc, rx_cpu_reset,
|
||||||
|
&rcc->parent_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;
|
||||||
|
cc->gdb_core_xml_file = "rx-core.xml";
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
180
target/rx/cpu.h
Normal file
180
target/rx/cpu.h
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
const char *rx_crname(uint8_t cr);
|
||||||
|
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, GByteArray *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 */
|
1446
target/rx/disas.c
Normal file
1446
target/rx/disas.c
Normal file
File diff suppressed because it is too large
Load diff
112
target/rx/gdbstub.c
Normal file
112
target/rx/gdbstub.c
Normal file
|
@ -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, GByteArray *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;
|
||||||
|
}
|
149
target/rx/helper.c
Normal file
149
target/rx/helper.c
Normal file
|
@ -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_data(env, env->isp, save_psw);
|
||||||
|
env->isp -= 4;
|
||||||
|
cpu_stl_data(env, env->isp, env->pc);
|
||||||
|
env->pc = cpu_ldl_data(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_data(env, env->isp, save_psw);
|
||||||
|
env->isp -= 4;
|
||||||
|
cpu_stl_data(env, env->isp, env->pc);
|
||||||
|
|
||||||
|
if (vec < 0x100) {
|
||||||
|
env->pc = cpu_ldl_data(env, 0xffffffc0 + vec * 4);
|
||||||
|
} else {
|
||||||
|
env->pc = cpu_ldl_data(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;
|
||||||
|
}
|
31
target/rx/helper.h
Normal file
31
target/rx/helper.h
Normal file
|
@ -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)
|
621
target/rx/insns.decode
Normal file
621
target/rx/insns.decode
Normal file
|
@ -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
|
470
target/rx/op_helper.c
Normal file
470
target/rx/op_helper.c
Normal file
|
@ -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);
|
||||||
|
}
|
2439
target/rx/translate.c
Normal file
2439
target/rx/translate.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -56,6 +56,7 @@ static struct arch2cpu cpus_map[] = {
|
||||||
{ "hppa", "hppa" },
|
{ "hppa", "hppa" },
|
||||||
{ "riscv64", "rv64gcsu-v1.10.0" },
|
{ "riscv64", "rv64gcsu-v1.10.0" },
|
||||||
{ "riscv32", "rv32gcsu-v1.9.1" },
|
{ "riscv32", "rv32gcsu-v1.9.1" },
|
||||||
|
{ "rx", "rx62n" },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *get_cpu_model_by_arch(const char *arch)
|
static const char *get_cpu_model_by_arch(const char *arch)
|
||||||
|
|
Loading…
Reference in a new issue