Discussion:
[PATCH v2 00/17] Qemu Openrisc support
Jia Liu
2012-05-27 05:32:42 UTC
Permalink
This is the Opencores Openrisc 1200 support for Qemu.
Full implementation of the system-model and linux-user-model support.

Openrisc 1200 is a Opencores Open Source CPU,
its Architecture Manual can be find at
http://opencores.org/svnget,or1k?file=/trunk/docs/openrisc_arch.pdf

---
Thank you all for your very helpful comments. If I missed something,
or made some wrong fix, please give me more comments,
I'm afraid I did not get all of your ideas, and made V2 not good enough.
---

Signed-off-by: Jia Liu <***@gmail.com>
---

Version History:

V2:
Addressed Malc, Weiren, Andreas and Blue's review comments:
- reimplement cpu QOM.

Addressed Andreas's review comments:
- reimplement machine.
- rewrite the Copyright Notice using better format.

Addressed Blue and Weiren's review comments:
- compiling with AREG0 and remove global env, no dyngen-exe longer.

Addressed Max, Blue and Weiren's review comments:
- handle div zero exception.
- handle illegal instruction.

Addressed Blue's review comments:
- separate do_interrupt into intrpt.c form intrpt_helper.c.
- add QEMU_NORETURN to raise_exception.
- reimplement float instrutions.
- fix type of linux syscall and termbits.
- reimplement sim board.
- use the LGPL web URL in Copyright Notice.
- reimplemt branch instructions.

- split taregt stubs, QOM and machine.

V1:
- add Qemu Openrisc support.
- well tested on x64 machine, and final tested x86 machine.

Jia Liu (17):
Openrisc: add target stubs
Openrisc: add cpu QOM implement
Openrisc: add basic machine
Openrisc: add MMU support
Openrisc: add interrupt support
Openrisc: add exception support
Openrisc: add int instruction helpers
Openrisc: add float instruction helpers
Openrisc: add instruction translation routines
Openrisc: add Programmable Interrupt Controller
Openrisc: add a timer
Openrisc: add a simulator board
Openrisc: add system instruction helpers
Openrisc: add gdb stub support
Openrisc: add linux syscall, signal and termbits
Openrisc: add linux user support
Openrisc: add testcases

Makefile.target | 8 +
arch_init.c | 2 +
arch_init.h | 1 +
configure | 11 +-
cpu-exec.c | 19 +
default-configs/or32-linux-user.mak | 2 +
default-configs/or32-softmmu.mak | 6 +
elf.h | 2 +
gdbstub.c | 64 ++
hw/openrisc_cpudev.h | 29 +
hw/openrisc_pic.c | 78 ++
hw/openrisc_sim.c | 145 ++++
hw/openrisc_timer.c | 153 ++++
linux-user/elfload.c | 41 +
linux-user/main.c | 100 +++
linux-user/openrisc/syscall.h | 24 +
linux-user/openrisc/syscall_nr.h | 506 ++++++++++++
linux-user/openrisc/target_signal.h | 26 +
linux-user/openrisc/termbits.h | 294 +++++++
linux-user/signal.c | 229 ++++++
linux-user/syscall.c | 2 +-
linux-user/syscall_defs.h | 40 +-
poison.h | 1 +
target-openrisc/cpu.c | 134 ++++
target-openrisc/cpu.h | 362 +++++++++
target-openrisc/excp.c | 27 +
target-openrisc/excp.h | 28 +
target-openrisc/excp_helper.c | 27 +
target-openrisc/fpu_helper.c | 275 +++++++
target-openrisc/helper.c | 101 +++
target-openrisc/helper.h | 73 ++
target-openrisc/int_helper.c | 155 ++++
target-openrisc/intrpt.c | 72 ++
target-openrisc/intrpt_helper.c | 52 ++
target-openrisc/machine.c | 51 ++
target-openrisc/mmu.c | 236 ++++++
target-openrisc/mmu_helper.c | 63 ++
target-openrisc/sys_helper.c | 226 ++++++
target-openrisc/translate.c | 1500 +++++++++++++++++++++++++++++++++++
tests/tcg/openrisc/Makefile | 73 ++
tests/tcg/openrisc/test_add.c | 34 +
tests/tcg/openrisc/test_addc.c | 37 +
tests/tcg/openrisc/test_addi.c | 31 +
tests/tcg/openrisc/test_addic.c | 32 +
tests/tcg/openrisc/test_and_or.c | 61 ++
tests/tcg/openrisc/test_bf.c | 46 ++
tests/tcg/openrisc/test_bnf.c | 50 ++
tests/tcg/openrisc/test_div.c | 32 +
tests/tcg/openrisc/test_extx.c | 71 ++
tests/tcg/openrisc/test_fx.c | 53 ++
tests/tcg/openrisc/test_j.c | 26 +
tests/tcg/openrisc/test_jal.c | 26 +
tests/tcg/openrisc/test_lf_add.c | 32 +
tests/tcg/openrisc/test_lf_div.c | 33 +
tests/tcg/openrisc/test_lf_eqd.c | 44 +
tests/tcg/openrisc/test_lf_eqs.c | 43 +
tests/tcg/openrisc/test_lf_ged.c | 45 ++
tests/tcg/openrisc/test_lf_ges.c | 45 ++
tests/tcg/openrisc/test_lf_gtd.c | 45 ++
tests/tcg/openrisc/test_lf_gts.c | 45 ++
tests/tcg/openrisc/test_lf_led.c | 43 +
tests/tcg/openrisc/test_lf_les.c | 45 ++
tests/tcg/openrisc/test_lf_ltd.c | 45 ++
tests/tcg/openrisc/test_lf_lts.c | 45 ++
tests/tcg/openrisc/test_lf_mul.c | 22 +
tests/tcg/openrisc/test_lf_ned.c | 46 ++
tests/tcg/openrisc/test_lf_nes.c | 46 ++
tests/tcg/openrisc/test_lf_rem.c | 31 +
tests/tcg/openrisc/test_lf_sub.c | 31 +
tests/tcg/openrisc/test_logic.c | 100 +++
tests/tcg/openrisc/test_lx.c | 78 ++
tests/tcg/openrisc/test_movhi.c | 30 +
tests/tcg/openrisc/test_mul.c | 47 ++
tests/tcg/openrisc/test_sfeq.c | 43 +
tests/tcg/openrisc/test_sfeqi.c | 39 +
tests/tcg/openrisc/test_sfges.c | 44 +
tests/tcg/openrisc/test_sfgesi.c | 40 +
tests/tcg/openrisc/test_sfgeu.c | 44 +
tests/tcg/openrisc/test_sfgeui.c | 41 +
tests/tcg/openrisc/test_sfgts.c | 45 ++
tests/tcg/openrisc/test_sfgtsi.c | 41 +
tests/tcg/openrisc/test_sfgtu.c | 43 +
tests/tcg/openrisc/test_sfgtui.c | 42 +
tests/tcg/openrisc/test_sfles.c | 26 +
tests/tcg/openrisc/test_sflesi.c | 39 +
tests/tcg/openrisc/test_sfleu.c | 43 +
tests/tcg/openrisc/test_sfleui.c | 39 +
tests/tcg/openrisc/test_sflts.c | 43 +
tests/tcg/openrisc/test_sfltsi.c | 38 +
tests/tcg/openrisc/test_sfltu.c | 41 +
tests/tcg/openrisc/test_sfltui.c | 39 +
tests/tcg/openrisc/test_sfne.c | 43 +
tests/tcg/openrisc/test_sfnei.c | 38 +
93 files changed, 7483 insertions(+), 6 deletions(-)
create mode 100644 default-configs/or32-linux-user.mak
create mode 100644 default-configs/or32-softmmu.mak
create mode 100644 hw/openrisc_cpudev.h
create mode 100644 hw/openrisc_pic.c
create mode 100644 hw/openrisc_sim.c
create mode 100644 hw/openrisc_timer.c
create mode 100644 linux-user/openrisc/syscall.h
create mode 100644 linux-user/openrisc/syscall_nr.h
create mode 100644 linux-user/openrisc/target_signal.h
create mode 100644 linux-user/openrisc/termbits.h
create mode 100644 target-openrisc/cpu.c
create mode 100644 target-openrisc/cpu.h
create mode 100644 target-openrisc/excp.c
create mode 100644 target-openrisc/excp.h
create mode 100644 target-openrisc/excp_helper.c
create mode 100644 target-openrisc/fpu_helper.c
create mode 100644 target-openrisc/helper.c
create mode 100644 target-openrisc/helper.h
create mode 100644 target-openrisc/int_helper.c
create mode 100644 target-openrisc/intrpt.c
create mode 100644 target-openrisc/intrpt_helper.c
create mode 100644 target-openrisc/machine.c
create mode 100644 target-openrisc/mmu.c
create mode 100644 target-openrisc/mmu_helper.c
create mode 100644 target-openrisc/sys_helper.c
create mode 100644 target-openrisc/translate.c
create mode 100644 tests/tcg/openrisc/Makefile
create mode 100644 tests/tcg/openrisc/test_add.c
create mode 100644 tests/tcg/openrisc/test_addc.c
create mode 100644 tests/tcg/openrisc/test_addi.c
create mode 100644 tests/tcg/openrisc/test_addic.c
create mode 100644 tests/tcg/openrisc/test_and_or.c
create mode 100644 tests/tcg/openrisc/test_bf.c
create mode 100644 tests/tcg/openrisc/test_bnf.c
create mode 100644 tests/tcg/openrisc/test_div.c
create mode 100644 tests/tcg/openrisc/test_extx.c
create mode 100644 tests/tcg/openrisc/test_fx.c
create mode 100644 tests/tcg/openrisc/test_j.c
create mode 100644 tests/tcg/openrisc/test_jal.c
create mode 100644 tests/tcg/openrisc/test_lf_add.c
create mode 100644 tests/tcg/openrisc/test_lf_div.c
create mode 100644 tests/tcg/openrisc/test_lf_eqd.c
create mode 100644 tests/tcg/openrisc/test_lf_eqs.c
create mode 100644 tests/tcg/openrisc/test_lf_ged.c
create mode 100644 tests/tcg/openrisc/test_lf_ges.c
create mode 100644 tests/tcg/openrisc/test_lf_gtd.c
create mode 100644 tests/tcg/openrisc/test_lf_gts.c
create mode 100644 tests/tcg/openrisc/test_lf_led.c
create mode 100644 tests/tcg/openrisc/test_lf_les.c
create mode 100644 tests/tcg/openrisc/test_lf_ltd.c
create mode 100644 tests/tcg/openrisc/test_lf_lts.c
create mode 100644 tests/tcg/openrisc/test_lf_mul.c
create mode 100644 tests/tcg/openrisc/test_lf_ned.c
create mode 100644 tests/tcg/openrisc/test_lf_nes.c
create mode 100644 tests/tcg/openrisc/test_lf_rem.c
create mode 100644 tests/tcg/openrisc/test_lf_sub.c
create mode 100644 tests/tcg/openrisc/test_logic.c
create mode 100644 tests/tcg/openrisc/test_lx.c
create mode 100644 tests/tcg/openrisc/test_movhi.c
create mode 100644 tests/tcg/openrisc/test_mul.c
create mode 100644 tests/tcg/openrisc/test_sfeq.c
create mode 100644 tests/tcg/openrisc/test_sfeqi.c
create mode 100644 tests/tcg/openrisc/test_sfges.c
create mode 100644 tests/tcg/openrisc/test_sfgesi.c
create mode 100644 tests/tcg/openrisc/test_sfgeu.c
create mode 100644 tests/tcg/openrisc/test_sfgeui.c
create mode 100644 tests/tcg/openrisc/test_sfgts.c
create mode 100644 tests/tcg/openrisc/test_sfgtsi.c
create mode 100644 tests/tcg/openrisc/test_sfgtu.c
create mode 100644 tests/tcg/openrisc/test_sfgtui.c
create mode 100644 tests/tcg/openrisc/test_sfles.c
create mode 100644 tests/tcg/openrisc/test_sflesi.c
create mode 100644 tests/tcg/openrisc/test_sfleu.c
create mode 100644 tests/tcg/openrisc/test_sfleui.c
create mode 100644 tests/tcg/openrisc/test_sflts.c
create mode 100644 tests/tcg/openrisc/test_sfltsi.c
create mode 100644 tests/tcg/openrisc/test_sfltu.c
create mode 100644 tests/tcg/openrisc/test_sfltui.c
create mode 100644 tests/tcg/openrisc/test_sfne.c
create mode 100644 tests/tcg/openrisc/test_sfnei.c
--
1.7.9.5
Jia Liu
2012-05-27 05:32:43 UTC
Permalink
add openrisc target stubs.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 3 +
arch_init.c | 2 +
arch_init.h | 1 +
configure | 10 ++-
cpu-exec.c | 2 +
default-configs/or32-softmmu.mak | 6 ++
elf.h | 2 +
poison.h | 1 +
target-openrisc/cpu.c | 24 +++++
target-openrisc/cpu.h | 184 ++++++++++++++++++++++++++++++++++++++
target-openrisc/helper.c | 60 +++++++++++++
target-openrisc/intrpt.c | 30 +++++++
target-openrisc/machine.c | 31 +++++++
target-openrisc/mmu.c | 35 ++++++++
target-openrisc/mmu_helper.c | 43 +++++++++
target-openrisc/translate.c | 61 +++++++++++++
16 files changed, 493 insertions(+), 2 deletions(-)
create mode 100644 default-configs/or32-softmmu.mak
create mode 100644 target-openrisc/cpu.c
create mode 100644 target-openrisc/cpu.h
create mode 100644 target-openrisc/helper.c
create mode 100644 target-openrisc/intrpt.c
create mode 100644 target-openrisc/machine.c
create mode 100644 target-openrisc/mmu.c
create mode 100644 target-openrisc/mmu_helper.c
create mode 100644 target-openrisc/translate.c

diff --git a/Makefile.target b/Makefile.target
index 1582904..0415db8 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -83,9 +83,11 @@ libobj-$(CONFIG_TCG_INTERPRETER) += tci.o
libobj-y += fpu/softfloat.o
ifneq ($(TARGET_BASE_ARCH), sparc)
ifneq ($(TARGET_BASE_ARCH), alpha)
+ifneq ($(TARGET_BASE_ARCH), openrisc)
libobj-y += op_helper.o
endif
endif
+endif
libobj-y += helper.o
ifneq ($(TARGET_BASE_ARCH), ppc)
libobj-y += cpu.o
@@ -99,6 +101,7 @@ endif
libobj-$(TARGET_SPARC) += int32_helper.o
libobj-$(TARGET_SPARC64) += int64_helper.o
libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
+libobj-$(TARGET_OPENRISC) += intrpt.o mmu.o mmu_helper.o

libobj-y += disas.o
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/arch_init.c b/arch_init.c
index 988adca..55b608d 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -71,6 +71,8 @@ int graphic_depth = 15;
#define QEMU_ARCH QEMU_ARCH_MICROBLAZE
#elif defined(TARGET_MIPS)
#define QEMU_ARCH QEMU_ARCH_MIPS
+#elif defined(TARGET_OPENRISC)
+#define QEMU_ARCH QEMU_ARCH_OPENRISC
#elif defined(TARGET_PPC)
#define QEMU_ARCH QEMU_ARCH_PPC
#elif defined(TARGET_S390X)
diff --git a/arch_init.h b/arch_init.h
index c7cb94a..3dfea3b 100644
--- a/arch_init.h
+++ b/arch_init.h
@@ -16,6 +16,7 @@ enum {
QEMU_ARCH_SH4 = 1024,
QEMU_ARCH_SPARC = 2048,
QEMU_ARCH_XTENSA = 4096,
+ QEMU_ARCH_OPENRISC = 8192,
};

extern const uint32_t arch_type;
diff --git a/configure b/configure
index b55a792..bcfe00f 100755
--- a/configure
+++ b/configure
@@ -924,6 +924,7 @@ mips-softmmu \
mipsel-softmmu \
mips64-softmmu \
mips64el-softmmu \
+or32-softmmu \
ppc-softmmu \
ppcemb-softmmu \
ppc64-softmmu \
@@ -3460,7 +3461,7 @@ target_arch2=`echo $target | cut -d '-' -f 1`
target_bigendian="no"

case "$target_arch2" in
- armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
+ armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|or32|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
target_bigendian=yes
;;
esac
@@ -3588,6 +3589,11 @@ case "$target_arch2" in
target_phys_bits=64
target_long_alignment=8
;;
+ or32)
+ TARGET_ARCH=openrisc
+ TARGET_BASE_ARCH=openrisc
+ target_phys_bits=32
+ ;;
ppc)
gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
target_phys_bits=64
@@ -3659,7 +3665,7 @@ case "$target_arch2" in
esac

case "$target_arch2" in
- alpha | sparc*)
+ alpha | or32 | sparc*)
echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
;;
esac
diff --git a/cpu-exec.c b/cpu-exec.c
index 0344cd5..ba10db1 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -222,6 +222,7 @@ int cpu_exec(CPUArchState *env)
#elif defined(TARGET_LM32)
#elif defined(TARGET_MICROBLAZE)
#elif defined(TARGET_MIPS)
+#elif defined(TARGET_OPENRISC)
#elif defined(TARGET_SH4)
#elif defined(TARGET_CRIS)
#elif defined(TARGET_S390X)
@@ -620,6 +621,7 @@ int cpu_exec(CPUArchState *env)
| env->cc_dest | (env->cc_x << 4);
#elif defined(TARGET_MICROBLAZE)
#elif defined(TARGET_MIPS)
+#elif defined(TARGET_OPENRISC)
#elif defined(TARGET_SH4)
#elif defined(TARGET_ALPHA)
#elif defined(TARGET_CRIS)
diff --git a/default-configs/or32-softmmu.mak b/default-configs/or32-softmmu.mak
new file mode 100644
index 0000000..7590eed
--- /dev/null
+++ b/default-configs/or32-softmmu.mak
@@ -0,0 +1,6 @@
+# Default configuration for or32-softmmu
+
+include pci.mak
+CONFIG_SERIAL=y
+CONFIG_NE2000_ISA=y
+CONFIG_I8259=y
diff --git a/elf.h b/elf.h
index e1422b8..e65f4b9 100644
--- a/elf.h
+++ b/elf.h
@@ -106,6 +106,8 @@ typedef int64_t Elf64_Sxword;
#define EM_H8S 48 /* Hitachi H8S */
#define EM_LATTICEMICO32 138 /* LatticeMico32 */

+#define EM_OPENRISC 92 /* Opencores Openrisc */
+
#define EM_UNICORE32 110 /* UniCore32 */

/*
diff --git a/poison.h b/poison.h
index d396f20..7d7b23b 100644
--- a/poison.h
+++ b/poison.h
@@ -14,6 +14,7 @@
#pragma GCC poison TARGET_M68K
#pragma GCC poison TARGET_MIPS
#pragma GCC poison TARGET_MIPS64
+#pragma GCC poison TARGET_OPENRISC
#pragma GCC poison TARGET_PPC
#pragma GCC poison TARGET_PPCEMB
#pragma GCC poison TARGET_PPC64
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
new file mode 100644
index 0000000..ef3ffb1
--- /dev/null
+++ b/target-openrisc/cpu.c
@@ -0,0 +1,24 @@
+/*
+ * QEMU Openrisc CPU
+ *
+ * Copyright (c) 2012 Jia Liu <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#if !defined(CONFIG_USER_ONLY)
+#include "hw/loader.h"
+#endif
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
new file mode 100644
index 0000000..80018df
--- /dev/null
+++ b/target-openrisc/cpu.h
@@ -0,0 +1,184 @@
+/*
+ * Openrisc virtual CPU header.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#ifndef CPU_OPENRISC_H
+#define CPU_OPENRISC_H
+
+#define TARGET_HAS_ICE 1
+
+#define ELF_MACHINE EM_OPENRISC
+
+#define CPUArchState struct CPUOpenriscState
+
+#define TARGET_LONG_BITS 32
+
+#include "config.h"
+#include "qemu-common.h"
+#include "cpu-defs.h"
+#include "softfloat.h"
+#include "qemu/cpu.h"
+
+struct CPUOpenriscState;
+
+#define NB_MMU_MODES 3
+#define MMU_NOMMU_IDX 0
+#define MMU_SUPERVISOR_IDX 1
+#define MMU_USER_IDX 2
+
+#define TARGET_PAGE_BITS 13
+
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+
+/* Verison Register */
+#define SPR_VR 0x12000001
+#define SPR_CPUCFGR 0x12000001
+
+/* Registers */
+enum {
+ R0 = 0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10,
+ R11, R12, R13, R14, R15, R16, R17, R18, R19, R20,
+ R21, R22, R23, R24, R25, R26, R27, R28, R29, R30,
+ R31
+};
+
+/* Register aliases */
+enum {
+ R_ZERO = R0,
+ R_SP = R1,
+ R_FP = R2,
+ R_LR = R9,
+ R_RV = R11,
+ R_RVH = R12
+};
+
+typedef struct CPUOpenriscState CPUOpenriscState;
+struct CPUOpenriscState {
+ target_ulong gpr[32]; /* General registers */
+
+ CPU_COMMON
+
+ target_ulong pc; /* Program counter */
+ target_ulong npc; /* Next PC */
+ target_ulong ppc; /* Prev PC */
+ target_ulong jmp_pc; /* Jump PC */
+ uint32_t flags;
+ /* Branch. */
+ uint32_t btaken; /* the SR_F bit */
+};
+
+#define TYPE_OPENRISC_CPU "or32-cpu"
+
+#define OPENRISC_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(OpenriscCPUClass, (klass), TYPE_OPENRISC_CPU)
+#define OPENRISC_CPU(obj) \
+ OBJECT_CHECK(OpenriscCPU, (obj), TYPE_OPENRISC_CPU)
+#define OPENRISC_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(OpenriscCPUClass, (obj), TYPE_OPENRISC_CPU)
+
+/**
+ * OpenriscCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A Openrisc CPU model.
+ */
+typedef struct OpenriscCPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ void (*parent_reset)(CPUState *cpu);
+} OpenriscCPUClass;
+
+/**
+ * OpenriscCPU:
+ * @env: #CPUOpenriscState
+ *
+ * A Openrisc CPU.
+ */
+typedef struct OpenriscCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUOpenriscState env;
+} OpenriscCPU;
+
+static inline OpenriscCPU *openrisc_env_get_cpu(CPUOpenriscState *env)
+{
+ return OPENRISC_CPU(container_of(env, OpenriscCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e))
+
+void openrisc_cpu_realize(OpenriscCPU *cpu);
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
+OpenriscCPU *cpu_openrisc_init(const char *cpu_model);
+int cpu_openrisc_exec(CPUOpenriscState *s);
+void do_interrupt(CPUOpenriscState *env);
+void openrisc_translate_init(void);
+
+#define cpu_list cpu_openrisc_list
+#define cpu_exec cpu_openrisc_exec
+#define cpu_gen_code cpu_openrisc_gen_code
+
+#define CPU_SAVE_VERSION 1
+
+void openrisc_reset(CPUOpenriscState *env);
+#if !defined(CONFIG_USER_ONLY)
+void openrisc_mmu_init(CPUOpenriscState *env);
+int get_phys_nommu(CPUOpenriscState *env, target_phys_addr_t *physical,
+ int *prot, target_ulong address, int rw);
+#endif
+
+static inline CPUOpenriscState *cpu_init(const char *cpu_model)
+{
+ return NULL;
+}
+
+#include "cpu-all.h"
+
+static inline void cpu_get_tb_cpu_state(CPUOpenriscState *env,
+ target_ulong *pc,
+ target_ulong *cs_base, int *flags)
+{
+ *pc = env->pc;
+ *cs_base = 0;
+ *flags = 0;
+}
+
+static inline int cpu_mmu_index(CPUOpenriscState *env)
+{
+ return 0;
+}
+
+static inline bool cpu_has_work(CPUOpenriscState *env)
+{
+ return 1;
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUOpenriscState *env, TranslationBlock *tb)
+{
+ env->pc = tb->pc;
+}
+
+#endif /* CPU_OPENRISC_H */
diff --git a/target-openrisc/helper.c b/target-openrisc/helper.c
new file mode 100644
index 0000000..934f73b
--- /dev/null
+++ b/target-openrisc/helper.c
@@ -0,0 +1,60 @@
+/*
+ * Openrisc helpers
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "host-utils.h"
+#include "sysemu.h"
+
+void cpu_state_reset(CPUOpenriscState *env)
+{
+ cpu_reset(ENV_GET_CPU(env));
+}
+
+OpenriscCPU *cpu_openrisc_init(const char *cpu_model)
+{
+ OpenriscCPU *cpu;
+ CPUOpenriscState *env;
+ static int inited;
+ inited = 0;
+
+ if (!object_class_by_name(cpu_model)) {
+ return NULL;
+ }
+ cpu = OPENRISC_CPU(object_new(cpu_model));
+ env = &cpu->env;
+ env->cpu_model_str = cpu_model;
+ /*realize openrisc cpu here*/
+
+ if (tcg_enabled() && !inited) {
+ inited = 1;
+ openrisc_translate_init();
+ }
+
+ cpu_state_reset(env);
+
+ return cpu;
+}
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
+{
+ (*cpu_fprintf)(f, "Available CPUs:\n"
+ "or1200\n");
+}
diff --git a/target-openrisc/intrpt.c b/target-openrisc/intrpt.c
new file mode 100644
index 0000000..a77116f
--- /dev/null
+++ b/target-openrisc/intrpt.c
@@ -0,0 +1,30 @@
+/*
+ * Openrisc interrupt.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "host-utils.h"
+#if !defined(CONFIG_USER_ONLY)
+#include "hw/loader.h"
+#endif
+
+void do_interrupt(CPUOpenriscState *env)
+{
+}
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
new file mode 100644
index 0000000..31165fc
--- /dev/null
+++ b/target-openrisc/machine.c
@@ -0,0 +1,31 @@
+/*
+ * Openrisc Machine
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "kvm.h"
+
+void cpu_save(QEMUFile *f, void *opaque)
+{
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+ return 0;
+}
diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c
new file mode 100644
index 0000000..bdd4bb4
--- /dev/null
+++ b/target-openrisc/mmu.c
@@ -0,0 +1,35 @@
+/*
+ * Openrisc MMU.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ * Zhizhou Zhang <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "host-utils.h"
+#if !defined(CONFIG_USER_ONLY)
+#include "hw/loader.h"
+#endif
+
+#if !defined(CONFIG_USER_ONLY)
+target_phys_addr_t cpu_get_phys_page_debug(CPUOpenriscState *env,
+ target_ulong addr)
+{
+ return 0;
+}
+#endif
diff --git a/target-openrisc/mmu_helper.c b/target-openrisc/mmu_helper.c
new file mode 100644
index 0000000..8c658ff
--- /dev/null
+++ b/target-openrisc/mmu_helper.c
@@ -0,0 +1,43 @@
+/*
+ * Openrisc mmu helper routines
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ * Zhizhou Zhang <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#define MMUSUFFIX _mmu
+
+#define SHIFT 0
+#include "softmmu_template.h"
+
+#define SHIFT 1
+#include "softmmu_template.h"
+
+#define SHIFT 2
+#include "softmmu_template.h"
+
+#define SHIFT 3
+#include "softmmu_template.h"
+
+void tlb_fill(CPUOpenriscState *env, target_ulong addr, int is_write,
+ int mmu_idx, uintptr_t retaddr)
+{
+}
+#endif
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
new file mode 100644
index 0000000..5bbad9e
--- /dev/null
+++ b/target-openrisc/translate.c
@@ -0,0 +1,61 @@
+/*
+ * Openrisc translation
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ * Feng Gao <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "disas.h"
+#include "tcg-op.h"
+#include "qemu-common.h"
+#include "qemu-log.h"
+#include "config.h"
+
+void openrisc_translate_init(void)
+{
+}
+
+static inline void gen_intermediate_code_internal(CPUOpenriscState *env,
+ TranslationBlock *tb,
+ int search_pc)
+{
+}
+
+void gen_intermediate_code(CPUOpenriscState *env, struct TranslationBlock *tb)
+{
+ gen_intermediate_code_internal(env, tb, 0);
+}
+
+void gen_intermediate_code_pc(CPUOpenriscState *env,
+ struct TranslationBlock *tb)
+{
+ gen_intermediate_code_internal(env, tb, 1);
+}
+
+void cpu_dump_state(CPUOpenriscState *env, FILE *f,
+ fprintf_function cpu_fprintf,
+ int flags)
+{
+ cpu_fprintf(f, "PC=%08x\n", env->pc);
+}
+
+void restore_state_to_opc(CPUOpenriscState *env, TranslationBlock *tb,
+ int pc_pos)
+{
+ env->pc = gen_opc_pc[pc_pos];
+}
--
1.7.9.5
Andreas Färber
2012-05-27 12:44:20 UTC
Permalink
Post by Jia Liu
add openrisc target stubs.
Minor nitpick: I'd recommend to stick to the typographic conventions
outlined here:
https://live.gnome.org/Git/CommitMessages

In particular please start the sentence with a capital A. GNOME
recommend a lowercase topic (we usually use the file/directory mainly
affected) and uppercase beginning of the actual description, e.g.

target-or32: Add target stubs

Add OpenRISC target stubs.

Signed-off-by: ...

Writing it that way is not mandatory but when you're reposting and
fixing the English grammar you can just as well make it perfect. ;)

As Stefan pointed out, www.opencores.org writes it as OpenRISC, not
Openrisc. I saw no prominent notice whether OpenRISC may be a trademark
but better to respect their naming, seeing all the misspellings of QEMU.

[...]
Post by Jia Liu
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
new file mode 100644
index 0000000..ef3ffb1
--- /dev/null
+++ b/target-openrisc/cpu.c
@@ -0,0 +1,24 @@
+/*
+ * QEMU Openrisc CPU
+ *
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#if !defined(CONFIG_USER_ONLY)
+#include "hw/loader.h"
+#endif
Missing TypeInfo, missing class_init, missing initfn (where you might
want to move the openrisc_translate_init() call btw, following Igor's
example), missing reset function. This cannot all be deferred to a later
patch.
Post by Jia Liu
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
new file mode 100644
index 0000000..80018df
--- /dev/null
+++ b/target-openrisc/cpu.h
@@ -0,0 +1,184 @@
+/*
+ * Openrisc virtual CPU header.
+ *
+ *
+ * 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/>.
+ */
+
+#ifndef CPU_OPENRISC_H
+#define CPU_OPENRISC_H
+
+#define TARGET_HAS_ICE 1
+
+#define ELF_MACHINE EM_OPENRISC
+
+#define CPUArchState struct CPUOpenriscState
+
+#define TARGET_LONG_BITS 32
+
+#include "config.h"
+#include "qemu-common.h"
+#include "cpu-defs.h"
+#include "softfloat.h"
+#include "qemu/cpu.h"
+
+struct CPUOpenriscState;
+
+#define NB_MMU_MODES 3
+#define MMU_NOMMU_IDX 0
+#define MMU_SUPERVISOR_IDX 1
+#define MMU_USER_IDX 2
Maybe make these three an enum?
Post by Jia Liu
+
+#define TARGET_PAGE_BITS 13
+
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+
+/* Verison Register */
+#define SPR_VR 0x12000001
+#define SPR_CPUCFGR 0x12000001
+
+/* Registers */
+enum {
+ R0 = 0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10,
+ R11, R12, R13, R14, R15, R16, R17, R18, R19, R20,
+ R21, R22, R23, R24, R25, R26, R27, R28, R29, R30,
+ R31
+};
+
+/* Register aliases */
+enum {
+ R_ZERO = R0,
+ R_SP = R1,
+ R_FP = R2,
+ R_LR = R9,
+ R_RV = R11,
+ R_RVH = R12
+};
+
+typedef struct CPUOpenriscState CPUOpenriscState;
+struct CPUOpenriscState {
+ target_ulong gpr[32]; /* General registers */
+
+ CPU_COMMON
+
+ target_ulong pc; /* Program counter */
+ target_ulong npc; /* Next PC */
+ target_ulong ppc; /* Prev PC */
+ target_ulong jmp_pc; /* Jump PC */
+ uint32_t flags;
+ /* Branch. */
+ uint32_t btaken; /* the SR_F bit */
+};
Why are pc, etc. placed after CPU_COMMON? Are they not supposed to be reset?
Post by Jia Liu
+
+#define TYPE_OPENRISC_CPU "or32-cpu"
+
+#define OPENRISC_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(OpenriscCPUClass, (klass), TYPE_OPENRISC_CPU)
+#define OPENRISC_CPU(obj) \
+ OBJECT_CHECK(OpenriscCPU, (obj), TYPE_OPENRISC_CPU)
+#define OPENRISC_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(OpenriscCPUClass, (obj), TYPE_OPENRISC_CPU)
+
+/**
+ *
+ * A Openrisc CPU model.
+ */
+typedef struct OpenriscCPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ void (*parent_reset)(CPUState *cpu);
+} OpenriscCPUClass;
+
+/**
+ *
+ * A Openrisc CPU.
+ */
+typedef struct OpenriscCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUOpenriscState env;
+} OpenriscCPU;
+
+static inline OpenriscCPU *openrisc_env_get_cpu(CPUOpenriscState *env)
+{
+ return OPENRISC_CPU(container_of(env, OpenriscCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e))
+
+void openrisc_cpu_realize(OpenriscCPU *cpu);
This should have a second Error **errp parameter, even if currently
unused. Please see target-i386 (target-arm is a bad example here).
Implementation is missing and it's not being used either.
Post by Jia Liu
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
+OpenriscCPU *cpu_openrisc_init(const char *cpu_model);
+int cpu_openrisc_exec(CPUOpenriscState *s);
+void do_interrupt(CPUOpenriscState *env);
+void openrisc_translate_init(void);
+
+#define cpu_list cpu_openrisc_list
+#define cpu_exec cpu_openrisc_exec
+#define cpu_gen_code cpu_openrisc_gen_code
+
+#define CPU_SAVE_VERSION 1
+
+void openrisc_reset(CPUOpenriscState *env);
Again, why the need? There's cpu_reset().
Post by Jia Liu
+#if !defined(CONFIG_USER_ONLY)
+void openrisc_mmu_init(CPUOpenriscState *env);
+int get_phys_nommu(CPUOpenriscState *env, target_phys_addr_t *physical,
+ int *prot, target_ulong address, int rw);
+#endif
+
+static inline CPUOpenriscState *cpu_init(const char *cpu_model)
+{
+ return NULL;
+}
Needs to be implemented properly by calling cpu_openrisc_init().
Post by Jia Liu
+
+#include "cpu-all.h"
+
+static inline void cpu_get_tb_cpu_state(CPUOpenriscState *env,
+ target_ulong *pc,
+ target_ulong *cs_base, int *flags)
+{
+ *pc = env->pc;
+ *cs_base = 0;
+ *flags = 0;
+}
+
+static inline int cpu_mmu_index(CPUOpenriscState *env)
+{
+ return 0;
+}
+
+static inline bool cpu_has_work(CPUOpenriscState *env)
+{
+ return 1;
The return type is bool, so please use true rather than 1.
Post by Jia Liu
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUOpenriscState *env, TranslationBlock *tb)
+{
+ env->pc = tb->pc;
+}
+
+#endif /* CPU_OPENRISC_H */
diff --git a/target-openrisc/helper.c b/target-openrisc/helper.c
new file mode 100644
index 0000000..934f73b
--- /dev/null
+++ b/target-openrisc/helper.c
@@ -0,0 +1,60 @@
+/*
+ * Openrisc helpers
+ *
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "host-utils.h"
+#include "sysemu.h"
+
+void cpu_state_reset(CPUOpenriscState *env)
+{
+ cpu_reset(ENV_GET_CPU(env));
+}
Had you rebased onto qom-next branch as requested, this would no longer
be necessary.
Post by Jia Liu
+
+OpenriscCPU *cpu_openrisc_init(const char *cpu_model)
+{
+ OpenriscCPU *cpu;
+ CPUOpenriscState *env;
+ static int inited;
+ inited = 0;
+
+ if (!object_class_by_name(cpu_model)) {
+ return NULL;
+ }
+ cpu = OPENRISC_CPU(object_new(cpu_model));
+ env = &cpu->env;
+ env->cpu_model_str = cpu_model;
+ /*realize openrisc cpu here*/
+
+ if (tcg_enabled() && !inited) {
+ inited = 1;
+ openrisc_translate_init();
+ }
+
+ cpu_state_reset(env);
cpu_reset().
Post by Jia Liu
+
+ return cpu;
+}
This function would best be placed into cpu.c.
Post by Jia Liu
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
+{
+ (*cpu_fprintf)(f, "Available CPUs:\n"
+ "or1200\n");
Nack. Do not hardcode CPU models. Register a class "or1200" in cpu.c and
call object_class_get_list() here, sort them and print the name of each.
Again, compare target-arm.
Post by Jia Liu
+}
This function should go into cpu.c, too. It's only in helper.c for many
existing targets because cpu.c is pretty new.
Post by Jia Liu
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
new file mode 100644
index 0000000..31165fc
--- /dev/null
+++ b/target-openrisc/machine.c
@@ -0,0 +1,31 @@
+/*
+ * Openrisc Machine
+ *
+ *
+ * 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/>.
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "kvm.h"
I doubt that there is KVM support for or32.
Post by Jia Liu
+
+void cpu_save(QEMUFile *f, void *opaque)
+{
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+ return 0;
+}
[snip]

Andreas
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
Jia Liu
2012-05-30 00:08:37 UTC
Permalink
Hi Andreas,
Post by Andreas Färber
Post by Jia Liu
add openrisc target stubs.
Minor nitpick: I'd recommend to stick to the typographic conventions
https://live.gnome.org/Git/CommitMessages
In particular please start the sentence with a capital A. GNOME
recommend a lowercase topic (we usually use the file/directory mainly
affected) and uppercase beginning of the actual description, e.g.
target-or32: Add target stubs
Add OpenRISC target stubs.
Thanks, I'll fix all of them.
Post by Andreas Färber
Signed-off-by: ...
Writing it that way is not mandatory but when you're reposting and
fixing the English grammar you can just as well make it perfect. ;)
I'm trying, all the time...
Post by Andreas Färber
As Stefan pointed out, www.opencores.org writes it as OpenRISC, not
Openrisc. I saw no prominent notice whether OpenRISC may be a trademark
but better to respect their naming, seeing all the misspellings of QEMU.
Thanks, I'll fix all of them.
Post by Andreas Färber
[...]
Post by Jia Liu
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
new file mode 100644
index 0000000..ef3ffb1
--- /dev/null
+++ b/target-openrisc/cpu.c
@@ -0,0 +1,24 @@
+/*
+ *  QEMU Openrisc CPU
+ *
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#if !defined(CONFIG_USER_ONLY)
+#include "hw/loader.h"
+#endif
Missing TypeInfo, missing class_init, missing initfn (where you might
want to move the openrisc_translate_init() call btw, following Igor's
example), missing reset function. This cannot all be deferred to a later
patch.
I'm trying fix this, is target-i386 a good example of QOM? If so, I'll
rewrite the code fellow target-i386.
Post by Andreas Färber
Post by Jia Liu
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
new file mode 100644
index 0000000..80018df
--- /dev/null
+++ b/target-openrisc/cpu.h
@@ -0,0 +1,184 @@
+/*
+ *  Openrisc virtual CPU header.
+ *
+ *
+ * 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/>.
+ */
+
+#ifndef CPU_OPENRISC_H
+#define CPU_OPENRISC_H
+
+#define TARGET_HAS_ICE 1
+
+#define ELF_MACHINE EM_OPENRISC
+
+#define CPUArchState struct CPUOpenriscState
+
+#define TARGET_LONG_BITS 32
+
+#include "config.h"
+#include "qemu-common.h"
+#include "cpu-defs.h"
+#include "softfloat.h"
+#include "qemu/cpu.h"
+
+struct CPUOpenriscState;
+
+#define NB_MMU_MODES 3
+#define MMU_NOMMU_IDX   0
+#define MMU_SUPERVISOR_IDX  1
+#define MMU_USER_IDX    2
Maybe make these three an enum?
Thanks, I'll make a enum for them.
Post by Andreas Färber
Post by Jia Liu
+
+#define TARGET_PAGE_BITS 13
+
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+
+/* Verison Register */
+#define SPR_VR       0x12000001
+#define SPR_CPUCFGR  0x12000001
+
+/* Registers */
+enum {
+    R0 = 0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10,
+    R11, R12, R13, R14, R15, R16, R17, R18, R19, R20,
+    R21, R22, R23, R24, R25, R26, R27, R28, R29, R30,
+    R31
+};
+
+/* Register aliases */
+enum {
+    R_ZERO = R0,
+    R_SP = R1,
+    R_FP = R2,
+    R_LR = R9,
+    R_RV = R11,
+    R_RVH = R12
+};
+
+typedef struct CPUOpenriscState CPUOpenriscState;
+struct CPUOpenriscState {
+    target_ulong gpr[32];   /* General registers */
+
+    CPU_COMMON
+
+    target_ulong pc;        /* Program counter */
+    target_ulong npc;       /* Next PC */
+    target_ulong ppc;       /* Prev PC */
+    target_ulong jmp_pc;    /* Jump PC */
+    uint32_t flags;
+    /* Branch. */
+    uint32_t btaken;        /* the SR_F bit */
+};
Why are pc, etc. placed after CPU_COMMON? Are they not supposed to be reset?
Aha, sorry, I'll place them before CPU_COMMON.
Post by Andreas Färber
Post by Jia Liu
+
+#define TYPE_OPENRISC_CPU "or32-cpu"
+
+#define OPENRISC_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(OpenriscCPUClass, (klass), TYPE_OPENRISC_CPU)
+#define OPENRISC_CPU(obj) \
+    OBJECT_CHECK(OpenriscCPU, (obj), TYPE_OPENRISC_CPU)
+#define OPENRISC_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(OpenriscCPUClass, (obj), TYPE_OPENRISC_CPU)
+
+/**
+ *
+ * A Openrisc CPU model.
+ */
+typedef struct OpenriscCPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    void (*parent_reset)(CPUState *cpu);
+} OpenriscCPUClass;
+
+/**
+ *
+ * A Openrisc CPU.
+ */
+typedef struct OpenriscCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUOpenriscState env;
+} OpenriscCPU;
+
+static inline OpenriscCPU *openrisc_env_get_cpu(CPUOpenriscState *env)
+{
+    return OPENRISC_CPU(container_of(env, OpenriscCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e))
+
+void openrisc_cpu_realize(OpenriscCPU *cpu);
This should have a second Error **errp parameter, even if currently
unused. Please see target-i386 (target-arm is a bad example here).
Implementation is missing and it's not being used either.
Thanks, I'll read target-i386 code.
Post by Andreas Färber
Post by Jia Liu
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
+OpenriscCPU *cpu_openrisc_init(const char *cpu_model);
+int cpu_openrisc_exec(CPUOpenriscState *s);
+void do_interrupt(CPUOpenriscState *env);
+void openrisc_translate_init(void);
+
+#define cpu_list cpu_openrisc_list
+#define cpu_exec cpu_openrisc_exec
+#define cpu_gen_code cpu_openrisc_gen_code
+
+#define CPU_SAVE_VERSION 1
+
+void openrisc_reset(CPUOpenriscState *env);
Again, why the need? There's cpu_reset().
Yes, I'll rename it.
Post by Andreas Färber
Post by Jia Liu
+#if !defined(CONFIG_USER_ONLY)
+void openrisc_mmu_init(CPUOpenriscState *env);
+int get_phys_nommu(CPUOpenriscState *env, target_phys_addr_t *physical,
+                   int *prot, target_ulong address, int rw);
+#endif
+
+static inline CPUOpenriscState *cpu_init(const char *cpu_model)
+{
+    return NULL;
+}
Needs to be implemented properly by calling cpu_openrisc_init().
Thanks, I'll fix this.
Post by Andreas Färber
Post by Jia Liu
+
+#include "cpu-all.h"
+
+static inline void cpu_get_tb_cpu_state(CPUOpenriscState *env,
+                                        target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->pc;
+    *cs_base = 0;
+    *flags = 0;
+}
+
+static inline int cpu_mmu_index(CPUOpenriscState *env)
+{
+    return 0;
+}
+
+static inline bool cpu_has_work(CPUOpenriscState *env)
+{
+    return 1;
The return type is bool, so please use true rather than 1.
Thanks, I'll fix this.
Post by Andreas Färber
Post by Jia Liu
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUOpenriscState *env, TranslationBlock *tb)
+{
+    env->pc = tb->pc;
+}
+
+#endif /* CPU_OPENRISC_H */
diff --git a/target-openrisc/helper.c b/target-openrisc/helper.c
new file mode 100644
index 0000000..934f73b
--- /dev/null
+++ b/target-openrisc/helper.c
@@ -0,0 +1,60 @@
+/*
+ *  Openrisc helpers
+ *
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "host-utils.h"
+#include "sysemu.h"
+
+void cpu_state_reset(CPUOpenriscState *env)
+{
+    cpu_reset(ENV_GET_CPU(env));
+}
Had you rebased onto qom-next branch as requested, this would no longer
be necessary.
Nope, I didn't find qom-next branch.
I'll clone qom-next git repo, and, which target should I fellow? i386?
Sorry, I need a good example.
Post by Andreas Färber
Post by Jia Liu
+
+OpenriscCPU *cpu_openrisc_init(const char *cpu_model)
+{
+    OpenriscCPU *cpu;
+    CPUOpenriscState *env;
+    static int inited;
+    inited = 0;
+
+    if (!object_class_by_name(cpu_model)) {
+        return NULL;
+    }
+    cpu = OPENRISC_CPU(object_new(cpu_model));
+    env = &cpu->env;
+    env->cpu_model_str = cpu_model;
+    /*realize openrisc cpu here*/
+
+    if (tcg_enabled() && !inited) {
+        inited = 1;
+        openrisc_translate_init();
+    }
+
+    cpu_state_reset(env);
cpu_reset().
Thanks, I'll fix it.
Post by Andreas Färber
Post by Jia Liu
+
+    return cpu;
+}
This function would best be placed into cpu.c.
Post by Jia Liu
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    (*cpu_fprintf)(f, "Available CPUs:\n"
+                      "or1200\n");
Nack. Do not hardcode CPU models. Register a class "or1200" in cpu.c and
call object_class_get_list() here, sort them and print the name of each.
Again, compare target-arm.
Thanks, I'll move the code form 02/17 and 03/17 to here.
Post by Andreas Färber
Post by Jia Liu
+}
This function should go into cpu.c, too. It's only in helper.c for many
existing targets because cpu.c is pretty new.
Post by Jia Liu
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
new file mode 100644
index 0000000..31165fc
--- /dev/null
+++ b/target-openrisc/machine.c
@@ -0,0 +1,31 @@
+/*
+ *  Openrisc Machine
+ *
+ *
+ * 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/>.
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "kvm.h"
I doubt that there is KVM support for or32.
Thanks, I'll delete it.
Post by Andreas Färber
Post by Jia Liu
+
+void cpu_save(QEMUFile *f, void *opaque)
+{
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    return 0;
+}
[snip]
Andreas
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
Regards,
Jia.
Jia Liu
2012-05-27 05:32:44 UTC
Permalink
add openrisc QOM cpu implement.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 2 +
hw/openrisc_cpudev.h | 29 ++++++++++++
hw/openrisc_pic.c | 28 ++++++++++++
target-openrisc/cpu.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++
target-openrisc/cpu.h | 29 ++++++++++++
target-openrisc/helper.c | 2 +-
target-openrisc/mmu.c | 4 ++
7 files changed, 203 insertions(+), 1 deletion(-)
create mode 100644 hw/openrisc_cpudev.h
create mode 100644 hw/openrisc_pic.c

diff --git a/Makefile.target b/Makefile.target
index 0415db8..0efabd2 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -390,6 +390,8 @@ obj-xtensa-y += core-dc232b.o
obj-xtensa-y += core-dc233c.o
obj-xtensa-y += core-fsf.o

+obj-openrisc-y += openrisc_pic.o
+
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)

monitor.o: hmp-commands.h qmp-commands-old.h
diff --git a/hw/openrisc_cpudev.h b/hw/openrisc_cpudev.h
new file mode 100644
index 0000000..f1c45e7
--- /dev/null
+++ b/hw/openrisc_cpudev.h
@@ -0,0 +1,29 @@
+/*
+ * Qemu Openrisc CPU device support.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#ifndef HW_OPENRISC_CPUDEV_H
+#define HW_OPENRISC_CPUDEV_H
+
+/* openrisc_pic.c */
+void cpu_openrisc_pic_init(CPUOpenriscState *env);
+
+/* openrisc_timer.c*/
+void cpu_openrisc_clock_init(CPUOpenriscState *env);
+
+#endif
diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
new file mode 100644
index 0000000..201c6bc
--- /dev/null
+++ b/hw/openrisc_pic.c
@@ -0,0 +1,28 @@
+/*
+ * Generic Openrisc Programmable Interrupt Controller support.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ * Feng Gao <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "hw.h"
+#include "openrisc_cpudev.h"
+#include "cpu.h"
+
+/* Reset PIC */
+void cpu_openrisc_pic_reset(CPUOpenriscState *env)
+{
+}
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index ef3ffb1..aec0e01 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -22,3 +22,113 @@
#if !defined(CONFIG_USER_ONLY)
#include "hw/loader.h"
#endif
+
+/* CPUClass::reset() */
+static void openrisc_cpu_reset(CPUState *s)
+{
+ OpenriscCPU *cpu = OPENRISC_CPU(s);
+ OpenriscCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu);
+ CPUOpenriscState *env = &cpu->env;
+
+ if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+ qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+ log_cpu_state(env, 0);
+ }
+
+ occ->parent_reset(s);
+
+ memset(env, 0, offsetof(CPUOpenriscState, breakpoints));
+ env->pc = 0x100;
+ env->sr = SR_FO | SR_SM;
+ env->exception_index = -1;
+#if !defined(CONFIG_USER_ONLY)
+ openrisc_mmu_init(env);
+ cpu_openrisc_pic_reset(env);
+#endif
+
+ tlb_flush(env, 1);
+ tb_flush(env);
+}
+
+static void openrisc_cpu_initfn(Object *obj)
+{
+ OpenriscCPU *cpu = OPENRISC_CPU(obj);
+
+ cpu_exec_init(&cpu->env);
+}
+
+void openrisc_cpu_realize(OpenriscCPU *cpu)
+{
+ CPUOpenriscState *env = &cpu->env;
+ cpu_state_reset(env);
+ qemu_init_vcpu(env);
+}
+
+/* CPU models */
+static void or1200_initfn(Object *obj)
+{
+ OpenriscCPU *cpu = OPENRISC_CPU(obj);
+ CPUOpenriscState *env = &cpu->env;
+ cpu_state_reset(env);
+}
+
+static void openrisc_any_initfn(Object *obj)
+{
+ OpenriscCPU *cpu = OPENRISC_CPU(obj);
+ CPUOpenriscState *env = &cpu->env;
+ cpu_state_reset(env);
+}
+
+typedef struct OpenriscCPUInfo {
+ const char *name;
+ void (*initfn)(Object *obj);
+} OpenriscCPUInfo;
+
+static const OpenriscCPUInfo openrisc_cpus[] = {
+ { .name = "or1200", .initfn = or1200_initfn },
+ { .name = "any", .initfn = openrisc_any_initfn },
+};
+
+static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
+{
+ OpenriscCPUClass *occ = OPENRISC_CPU_CLASS(oc);
+ CPUClass *cc = CPU_CLASS(oc);
+
+ occ->parent_reset = cc->reset;
+ cc->reset = openrisc_cpu_reset;
+}
+
+static void cpu_register(const OpenriscCPUInfo *info)
+{
+ TypeInfo type_info = {
+ .name = info->name,
+ .parent = TYPE_OPENRISC_CPU,
+ .instance_size = sizeof(OpenriscCPU),
+ .instance_init = info->initfn,
+ .class_size = sizeof(OpenriscCPUClass),
+ };
+
+ type_register_static(&type_info);
+}
+
+static const TypeInfo openrisc_cpu_type_info = {
+ .name = TYPE_OPENRISC_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(OpenriscCPU),
+ .instance_init = openrisc_cpu_initfn,
+ .abstract = false,
+ .class_size = sizeof(OpenriscCPUClass),
+ .class_init = openrisc_cpu_class_init,
+};
+
+static void openrisc_cpu_register_types(void)
+{
+ int i;
+
+ type_register_static(&openrisc_cpu_type_info);
+ for (i = 0; i < ARRAY_SIZE(openrisc_cpus); i++) {
+ cpu_register(&openrisc_cpus[i]);
+ }
+}
+
+type_init(openrisc_cpu_register_types)
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 80018df..dbc1380 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -68,9 +68,32 @@ enum {
R_RVH = R12
};

+/* Supervisor register */
+enum {
+ SR_SM = 1,
+ SR_TEE = (1<<1),
+ SR_IEE = (1<<2),
+ SR_DCE = (1<<3),
+ SR_ICE = (1<<4),
+ SR_DME = (1<<5),
+ SR_IME = (1<<6),
+ SR_LEE = (1<<7),
+ SR_CE = (1<<8),
+ SR_F = (1<<9),
+ SR_CY = (1<<10),
+ SR_OV = (1<<11),
+ SR_OVE = (1<<12),
+ SR_DSX = (1<<13),
+ SR_EPH = (1<<14),
+ SR_FO = (1<<15),
+ SR_SUMRA = (1<<16),
+ SR_SCE = (1<<17),
+};
+
typedef struct CPUOpenriscState CPUOpenriscState;
struct CPUOpenriscState {
target_ulong gpr[32]; /* General registers */
+ uint32_t sr; /* Supervisor register */

CPU_COMMON

@@ -143,6 +166,8 @@ void openrisc_translate_init(void);

void openrisc_reset(CPUOpenriscState *env);
#if !defined(CONFIG_USER_ONLY)
+void cpu_openrisc_pic_reset(CPUOpenriscState *env);
+
void openrisc_mmu_init(CPUOpenriscState *env);
int get_phys_nommu(CPUOpenriscState *env, target_phys_addr_t *physical,
int *prot, target_ulong address, int rw);
@@ -150,6 +175,10 @@ int get_phys_nommu(CPUOpenriscState *env, target_phys_addr_t *physical,

static inline CPUOpenriscState *cpu_init(const char *cpu_model)
{
+ OpenriscCPU *cpu = cpu_openrisc_init(cpu_model);
+ if (cpu) {
+ return &cpu->env;
+ }
return NULL;
}

diff --git a/target-openrisc/helper.c b/target-openrisc/helper.c
index 934f73b..13c68e2 100644
--- a/target-openrisc/helper.c
+++ b/target-openrisc/helper.c
@@ -41,7 +41,7 @@ OpenriscCPU *cpu_openrisc_init(const char *cpu_model)
cpu = OPENRISC_CPU(object_new(cpu_model));
env = &cpu->env;
env->cpu_model_str = cpu_model;
- /*realize openrisc cpu here*/
+ openrisc_cpu_realize(cpu);

if (tcg_enabled() && !inited) {
inited = 1;
diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c
index bdd4bb4..4f0312f 100644
--- a/target-openrisc/mmu.c
+++ b/target-openrisc/mmu.c
@@ -32,4 +32,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUOpenriscState *env,
{
return 0;
}
+
+void openrisc_mmu_init(CPUOpenriscState *env)
+{
+}
#endif
--
1.7.9.5
Jia Liu
2012-05-27 05:32:45 UTC
Permalink
add openrisc basic machine.

Signed-off-by: Jia Liu <***@gmail.com>
---
target-openrisc/cpu.h | 30 ++++++++++++++++++++++++++++++
target-openrisc/helper.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
target-openrisc/machine.c | 22 +++++++++++++++++++++-
3 files changed, 94 insertions(+), 3 deletions(-)

diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index dbc1380..24d82f8 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -46,6 +46,15 @@ struct CPUOpenriscState;
#define TARGET_PHYS_ADDR_SPACE_BITS 32
#define TARGET_VIRT_ADDR_SPACE_BITS 32

+#define SET_FP_CAUSE(reg, v) do {\
+ (reg) = ((reg) & ~(0x3f << 12)) | \
+ ((v & 0x3f) << 12);\
+ } while (0)
+#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f)
+#define UPDATE_FP_FLAGS(reg, v) do {\
+ (reg) |= ((v & 0x1f) << 2);\
+ } while (0)
+
/* Verison Register */
#define SPR_VR 0x12000001
#define SPR_CPUCFGR 0x12000001
@@ -68,6 +77,21 @@ enum {
R_RVH = R12
};

+/* FPCSR register */
+enum {
+ FPCSR_FPEE = 1,
+ FPCSR_RM = (3 << 1),
+ FPCSR_OVF = (1 << 3),
+ FPCSR_UNF = (1 << 4),
+ FPCSR_SNF = (1 << 5),
+ FPCSR_QNF = (1 << 6),
+ FPCSR_ZF = (1 << 7),
+ FPCSR_IXF = (1 << 8),
+ FPCSR_IVF = (1 << 9),
+ FPCSR_INF = (1 << 10),
+ FPCSR_DZF = (1 << 11),
+};
+
/* Supervisor register */
enum {
SR_SM = 1,
@@ -94,9 +118,15 @@ typedef struct CPUOpenriscState CPUOpenriscState;
struct CPUOpenriscState {
target_ulong gpr[32]; /* General registers */
uint32_t sr; /* Supervisor register */
+ target_ulong machi; /* Multiply register MACHI */
+ target_ulong maclo; /* Multiply register MACLO */
+ target_ulong epcr; /* Exception PC register */
+ target_ulong eear; /* Exception EA register */
+ uint32_t esr; /* Exception supervisor register */

CPU_COMMON

+ uint32_t fpcsr; /* Float register */
target_ulong pc; /* Program counter */
target_ulong npc; /* Next PC */
target_ulong ppc; /* Prev PC */
diff --git a/target-openrisc/helper.c b/target-openrisc/helper.c
index 13c68e2..96e837d 100644
--- a/target-openrisc/helper.c
+++ b/target-openrisc/helper.c
@@ -53,8 +53,49 @@ OpenriscCPU *cpu_openrisc_init(const char *cpu_model)
return cpu;
}

+typedef struct OpenriscCPUListState {
+ fprintf_function cpu_fprintf;
+ FILE *file;
+} OpenriscCPUListState;
+
+/* Sort alphabetically by type name, except for "any". */
+static gint openrisc_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+ ObjectClass *class_a = (ObjectClass *)a;
+ ObjectClass *class_b = (ObjectClass *)b;
+ const char *name_a, *name_b;
+
+ name_a = object_class_get_name(class_a);
+ name_b = object_class_get_name(class_b);
+ if (strcmp(name_a, "any") == 0) {
+ return 1;
+ } else if (strcmp(name_b, "any") == 0) {
+ return -1;
+ } else {
+ return strcmp(name_a, name_b);
+ }
+}
+
+static void openrisc_cpu_list_entry(gpointer data, gpointer user_data)
+{
+ ObjectClass *oc = data;
+ OpenriscCPUListState *s = user_data;
+
+ (*s->cpu_fprintf)(s->file, " %s\n",
+ object_class_get_name(oc));
+}
+
void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
{
- (*cpu_fprintf)(f, "Available CPUs:\n"
- "or1200\n");
+ OpenriscCPUListState s = {
+ .file = f,
+ .cpu_fprintf = cpu_fprintf,
+ };
+ GSList *list;
+
+ list = object_class_get_list(TYPE_OPENRISC_CPU, false);
+ list = g_slist_sort(list, openrisc_cpu_list_compare);
+ (*cpu_fprintf)(f, "Available CPUs:\n");
+ g_slist_foreach(list, openrisc_cpu_list_entry, &s);
+ g_slist_free(list);
}
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
index 31165fc..0da26fc 100644
--- a/target-openrisc/machine.c
+++ b/target-openrisc/machine.c
@@ -21,11 +21,31 @@
#include "hw/boards.h"
#include "kvm.h"

+static const VMStateDescription vmstate_cpu = {
+ .name = "cpu",
+ .version_id = CPU_SAVE_VERSION,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(gpr, CPUOpenriscState, 32),
+ VMSTATE_UINT32(sr, CPUOpenriscState),
+ VMSTATE_UINT32(epcr, CPUOpenriscState),
+ VMSTATE_UINT32(eear, CPUOpenriscState),
+ VMSTATE_UINT32(esr, CPUOpenriscState),
+ VMSTATE_UINT32(fpcsr, CPUOpenriscState),
+ VMSTATE_UINT32(pc, CPUOpenriscState),
+ VMSTATE_UINT32(npc, CPUOpenriscState),
+ VMSTATE_UINT32(ppc, CPUOpenriscState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
void cpu_save(QEMUFile *f, void *opaque)
{
+ vmstate_save_state(f, &vmstate_cpu, opaque);
}

int cpu_load(QEMUFile *f, void *opaque, int version_id)
{
- return 0;
+ return vmstate_load_state(f, &vmstate_cpu, opaque, version_id);
}
--
1.7.9.5
Jia Liu
2012-05-27 05:32:46 UTC
Permalink
add openrisc MMU support.

Signed-off-by: Jia Liu <***@gmail.com>
---
target-openrisc/cpu.h | 82 ++++++++++++++++-
target-openrisc/mmu.c | 199 +++++++++++++++++++++++++++++++++++++++++-
target-openrisc/mmu_helper.c | 20 +++++
3 files changed, 298 insertions(+), 3 deletions(-)

diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 24d82f8..779c889 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -55,6 +55,9 @@ struct CPUOpenriscState;
(reg) |= ((v & 0x1f) << 2);\
} while (0)

+/* Internel flags, delay slot flag */
+#define D_FLAG 1
+
/* Verison Register */
#define SPR_VR 0x12000001
#define SPR_CPUCFGR 0x12000001
@@ -92,6 +95,25 @@ enum {
FPCSR_DZF = (1 << 11),
};

+/* Exceptions indices */
+enum {
+ EXCP_RESET = 0x1,
+ EXCP_BUSERR = 0x2,
+ EXCP_DPF = 0x3,
+ EXCP_IPF = 0x4,
+ EXCP_TICK = 0x5,
+ EXCP_ALIGN = 0x6,
+ EXCP_ILLEGAL = 0x7,
+ EXCP_INT = 0x8,
+ EXCP_DTLBMISS = 0x9,
+ EXCP_ITLBMISS = 0xa,
+ EXCP_RANGE = 0xb,
+ EXCP_SYSCALL = 0xc,
+ EXCP_FPE = 0xd,
+ EXCP_TRAP = 0xe,
+ EXCP_NR,
+};
+
/* Supervisor register */
enum {
SR_SM = 1,
@@ -114,6 +136,39 @@ enum {
SR_SCE = (1<<17),
};

+enum {
+ DTLB_WAYS = 1,
+ DTLB_SIZE = 64,
+ DTLB_MASK = (DTLB_SIZE-1),
+ ITLB_WAYS = 1,
+ ITLB_SIZE = 64,
+ ITLB_MASK = (ITLB_SIZE-1),
+};
+
+/* TLB prot */
+enum {
+ URE = (1<<6),
+ UWE = (1<<7),
+ SRE = (1<<8),
+ SWE = (1<<9),
+
+ SXE = (1<<6),
+ UXE = (1<<7),
+};
+
+/* check if tlb available */
+enum {
+ TLBRET_INVALID = -3,
+ TLBRET_NOMATCH = -2,
+ TLBRET_BADADDR = -1,
+ TLBRET_MATCH = 0
+};
+
+typedef struct tlb_entry {
+ uint32_t mr;
+ uint32_t tr;
+} tlb_entry;
+
typedef struct CPUOpenriscState CPUOpenriscState;
struct CPUOpenriscState {
target_ulong gpr[32]; /* General registers */
@@ -123,9 +178,21 @@ struct CPUOpenriscState {
target_ulong epcr; /* Exception PC register */
target_ulong eear; /* Exception EA register */
uint32_t esr; /* Exception supervisor register */
+#if !defined(CONFIG_USER_ONLY)
+ tlb_entry itlb[ITLB_WAYS][ITLB_SIZE];
+ tlb_entry dtlb[DTLB_WAYS][DTLB_SIZE];
+#endif

CPU_COMMON

+#if !defined(CONFIG_USER_ONLY)
+ int (*map_address_code)(struct CPUOpenriscState *env,
+ target_phys_addr_t *physical, int *prot,
+ target_ulong address, int rw);
+ int (*map_address_data)(struct CPUOpenriscState *env,
+ target_phys_addr_t *physical, int *prot,
+ target_ulong address, int rw);
+#endif
uint32_t fpcsr; /* Float register */
target_ulong pc; /* Program counter */
target_ulong npc; /* Next PC */
@@ -187,10 +254,13 @@ OpenriscCPU *cpu_openrisc_init(const char *cpu_model);
int cpu_openrisc_exec(CPUOpenriscState *s);
void do_interrupt(CPUOpenriscState *env);
void openrisc_translate_init(void);
+int cpu_openrisc_handle_mmu_fault(CPUOpenriscState *env, target_ulong address,
+ int rw, int mmu_idx);

#define cpu_list cpu_openrisc_list
#define cpu_exec cpu_openrisc_exec
#define cpu_gen_code cpu_openrisc_gen_code
+#define cpu_handle_mmu_fault cpu_openrisc_handle_mmu_fault

#define CPU_SAVE_VERSION 1

@@ -201,6 +271,10 @@ void cpu_openrisc_pic_reset(CPUOpenriscState *env);
void openrisc_mmu_init(CPUOpenriscState *env);
int get_phys_nommu(CPUOpenriscState *env, target_phys_addr_t *physical,
int *prot, target_ulong address, int rw);
+int get_phys_code(CPUOpenriscState *env, target_phys_addr_t *physical,
+ int *prot, target_ulong address, int rw);
+int get_phys_data(CPUOpenriscState *env, target_phys_addr_t *physical,
+ int *prot, target_ulong address, int rw);
#endif

static inline CPUOpenriscState *cpu_init(const char *cpu_model)
@@ -220,12 +294,16 @@ static inline void cpu_get_tb_cpu_state(CPUOpenriscState *env,
{
*pc = env->pc;
*cs_base = 0;
- *flags = 0;
+ /* D_FLAG -- branch insrtuction exception */
+ *flags = (env->flags&D_FLAG);
}

static inline int cpu_mmu_index(CPUOpenriscState *env)
{
- return 0;
+ if (!(env->sr & SR_IME)) {
+ return MMU_NOMMU_IDX;
+ }
+ return (env->sr & SR_SM) == 0 ? MMU_USER_IDX : MMU_SUPERVISOR_IDX;
}

static inline bool cpu_has_work(CPUOpenriscState *env)
diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c
index 4f0312f..2403b77 100644
--- a/target-openrisc/mmu.c
+++ b/target-openrisc/mmu.c
@@ -27,13 +27,210 @@
#endif

#if !defined(CONFIG_USER_ONLY)
+/* no MMU emulation */
+int get_phys_nommu(CPUOpenriscState *env, target_phys_addr_t *physical,
+ int *prot, target_ulong address, int rw)
+{
+ *physical = address;
+ *prot = PAGE_READ | PAGE_WRITE;
+ return TLBRET_MATCH;
+}
+
+int get_phys_code(CPUOpenriscState *env, target_phys_addr_t *physical,
+ int *prot, target_ulong address, int rw)
+{
+ int vpn = address >> TARGET_PAGE_BITS;
+ int idx = vpn & ITLB_MASK;
+ int right = 0;
+
+ if ((env->itlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) {
+ return TLBRET_NOMATCH;
+ }
+ if (!(env->itlb[0][idx].mr & 1)) {
+ return TLBRET_INVALID;
+ }
+
+ if (env->sr & SR_SM) { /* supervisor mode */
+ if (env->itlb[0][idx].tr & SXE) {
+ right |= PAGE_EXEC;
+ }
+ } else {
+ if (env->itlb[0][idx].tr & UXE) {
+ right |= PAGE_EXEC;
+ }
+ }
+
+ if ((rw & 2) && ((right & PAGE_EXEC) == 0)) {
+ return TLBRET_BADADDR;
+ }
+
+ *physical = (env->itlb[0][idx].tr & TARGET_PAGE_MASK) |
+ (address & (TARGET_PAGE_SIZE-1));
+ *prot = right;
+ return TLBRET_MATCH;
+}
+
+int get_phys_data(CPUOpenriscState *env, target_phys_addr_t *physical,
+ int *prot, target_ulong address, int rw)
+{
+ int vpn = address >> TARGET_PAGE_BITS;
+ int idx = vpn & DTLB_MASK;
+ int right = 0;
+
+ if ((env->dtlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) {
+ return TLBRET_NOMATCH;
+ }
+ if (!(env->dtlb[0][idx].mr & 1)) {
+ return TLBRET_INVALID;
+ }
+
+ if (env->sr & SR_SM) { /* supervisor mode */
+ if (env->dtlb[0][idx].tr & SRE) {
+ right |= PAGE_READ;
+ }
+ if (env->dtlb[0][idx].tr & SWE) {
+ right |= PAGE_WRITE;
+ }
+ } else {
+ if (env->dtlb[0][idx].tr & URE) {
+ right |= PAGE_READ;
+ }
+ if (env->dtlb[0][idx].tr & UWE) {
+ right |= PAGE_WRITE;
+ }
+ }
+
+ if ((rw & 0) && ((right & PAGE_READ) == 0)) {
+ return TLBRET_BADADDR;
+ }
+ if ((rw & 1) && ((right & PAGE_WRITE) == 0)) {
+ return TLBRET_BADADDR;
+ }
+
+ *physical = (env->dtlb[0][idx].tr & TARGET_PAGE_MASK) |
+ (address & (TARGET_PAGE_SIZE-1));
+ *prot = right;
+ return TLBRET_MATCH;
+}
+
+static int get_physical_address(CPUOpenriscState *env,
+ target_phys_addr_t *physical,
+ int *prot, target_ulong address,
+ int rw)
+{
+ int ret = TLBRET_MATCH;
+
+ /* [0x0000--0x2000]: unmapped */
+ if (address < 0x2000 && (env->sr & SR_SM)) {
+ *physical = address;
+ *prot = PAGE_READ | PAGE_WRITE;
+ return ret;
+ }
+
+ if (rw == 2) { /* ITLB */
+ *physical = 0;
+ ret = env->map_address_code(env, physical,
+ prot, address, rw);
+ } else { /* DTLB */
+ ret = env->map_address_data(env, physical,
+ prot, address, rw);
+ }
+
+ return ret;
+}
+#endif
+
+static void raise_mmu_exception(CPUOpenriscState *env, target_ulong address,
+ int rw, int tlb_error)
+{
+ int exception = 0;
+
+ switch (tlb_error) {
+ default:
+ if (rw == 2) {
+ exception = EXCP_IPF;
+ } else {
+ exception = EXCP_DPF;
+ }
+ break;
+#if !defined(CONFIG_USER_ONLY)
+ case TLBRET_BADADDR:
+ if (rw == 2) {
+ exception = EXCP_IPF;
+ } else {
+ exception = EXCP_DPF;
+ }
+ break;
+ case TLBRET_INVALID:
+ case TLBRET_NOMATCH:
+ /* No TLB match for a mapped address */
+ if (rw == 2) {
+ exception = EXCP_ITLBMISS;
+ } else {
+ exception = EXCP_DTLBMISS;
+ }
+ break;
+#endif
+ }
+
+ env->exception_index = exception;
+ env->eear = address;
+}
+
+#if !defined(CONFIG_USER_ONLY)
+int cpu_openrisc_handle_mmu_fault(CPUOpenriscState *env,
+ target_ulong address, int rw, int mmu_idx)
+{
+ int ret = 0;
+ target_phys_addr_t physical = 0;
+ int prot = 0;
+
+ ret = get_physical_address(env, &physical, &prot,
+ address, rw);
+
+ if (ret == TLBRET_MATCH) {
+ tlb_set_page(env, address & TARGET_PAGE_MASK,
+ physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
+ mmu_idx, TARGET_PAGE_SIZE);
+ ret = 0;
+ } else if (ret < 0) {
+ raise_mmu_exception(env, address, rw, ret);
+ ret = 1;
+ }
+
+ return ret;
+}
+#else
+int cpu_openrisc_handle_mmu_fault(CPUOpenriscState *env,
+ target_ulong address, int rw, int mmu_idx)
+{
+ int ret = 0;
+
+ raise_mmu_exception(env, address, rw, ret);
+ ret = 1;
+
+ return ret;
+}
+#endif
+
+#if !defined(CONFIG_USER_ONLY)
target_phys_addr_t cpu_get_phys_page_debug(CPUOpenriscState *env,
target_ulong addr)
{
- return 0;
+ target_phys_addr_t phys_addr;
+ int prot;
+
+ if (get_physical_address(env, &phys_addr, &prot, addr, 0)) {
+ return -1;
+ }
+ return phys_addr;
}

void openrisc_mmu_init(CPUOpenriscState *env)
{
+ env->map_address_code = &get_phys_nommu;
+ env->map_address_data = &get_phys_nommu;
+ memset(env->dtlb, 0, sizeof(tlb_entry)*DTLB_SIZE*DTLB_WAYS);
+ memset(env->itlb, 0, sizeof(tlb_entry)*ITLB_SIZE*ITLB_WAYS);
}
#endif
diff --git a/target-openrisc/mmu_helper.c b/target-openrisc/mmu_helper.c
index 8c658ff..1fbd6a4 100644
--- a/target-openrisc/mmu_helper.c
+++ b/target-openrisc/mmu_helper.c
@@ -39,5 +39,25 @@
void tlb_fill(CPUOpenriscState *env, target_ulong addr, int is_write,
int mmu_idx, uintptr_t retaddr)
{
+ TranslationBlock *tb;
+ unsigned long pc;
+ int ret;
+
+ ret = cpu_openrisc_handle_mmu_fault(env, addr, is_write, mmu_idx);
+
+ if (ret) {
+ if (retaddr) {
+ /* now we have a real cpu fault */
+ pc = (unsigned long)retaddr;
+ tb = tb_find_pc(pc);
+ if (tb) {
+ /* the PC is inside the translated code. It means that we
+ have a virtual CPU fault */
+ cpu_restore_state(tb, env, pc);
+ }
+ }
+ /* Raise Exception... */
+ cpu_loop_exit(env);
+ }
}
#endif
--
1.7.9.5
Jia Liu
2012-05-27 05:32:48 UTC
Permalink
add openrisc exception support.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 3 ++-
target-openrisc/excp.c | 27 +++++++++++++++++++++++++++
target-openrisc/excp.h | 28 ++++++++++++++++++++++++++++
target-openrisc/excp_helper.c | 27 +++++++++++++++++++++++++++
target-openrisc/helper.h | 3 +++
5 files changed, 87 insertions(+), 1 deletion(-)
create mode 100644 target-openrisc/excp.c
create mode 100644 target-openrisc/excp.h
create mode 100644 target-openrisc/excp_helper.c

diff --git a/Makefile.target b/Makefile.target
index 47836c6..42574f6 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -101,7 +101,8 @@ endif
libobj-$(TARGET_SPARC) += int32_helper.o
libobj-$(TARGET_SPARC64) += int64_helper.o
libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
-libobj-$(TARGET_OPENRISC) += intrpt.o intrpt_helper.o mmu.o mmu_helper.o
+libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o \
+intrpt.o intrpt_helper.o mmu.o mmu_helper.o

libobj-y += disas.o
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-openrisc/excp.c b/target-openrisc/excp.c
new file mode 100644
index 0000000..0359c12
--- /dev/null
+++ b/target-openrisc/excp.c
@@ -0,0 +1,27 @@
+/*
+ * Openrisc exception.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "excp.h"
+
+void QEMU_NORETURN raise_exception(CPUOpenriscState *env, uint32_t excp)
+{
+ env->exception_index = excp;
+ cpu_loop_exit(env);
+}
diff --git a/target-openrisc/excp.h b/target-openrisc/excp.h
new file mode 100644
index 0000000..491ff81
--- /dev/null
+++ b/target-openrisc/excp.h
@@ -0,0 +1,28 @@
+/*
+ * Openrisc exception header.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#ifndef QEMU_OPENRISC_EXCP_H
+#define QEMU_OPENRISC_EXCP_H
+
+#include "cpu.h"
+#include "qemu-common.h"
+
+void QEMU_NORETURN raise_exception(CPUOpenriscState *env, uint32_t excp);
+
+#endif /* QEMU_OPENRISC_EXCP_H */
diff --git a/target-openrisc/excp_helper.c b/target-openrisc/excp_helper.c
new file mode 100644
index 0000000..59cbd55
--- /dev/null
+++ b/target-openrisc/excp_helper.c
@@ -0,0 +1,27 @@
+/*
+ * Openrisc exception helper routines
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "excp.h"
+
+void HELPER(exception)(CPUOpenriscState *env, uint32_t excp)
+{
+ raise_exception(env, excp);
+}
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index 66cd05c..fbcfd12 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -19,6 +19,9 @@

#include "def-helper.h"

+/* exception */
+DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)
+
/* interrupt */
DEF_HELPER_FLAGS_1(rfe, 0, void, env)
--
1.7.9.5
Jia Liu
2012-05-27 05:32:49 UTC
Permalink
add int piont instruction helpers for openrisc.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 2 +-
target-openrisc/helper.h | 8 +++
target-openrisc/int_helper.c | 155 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 164 insertions(+), 1 deletion(-)
create mode 100644 target-openrisc/int_helper.c

diff --git a/Makefile.target b/Makefile.target
index 42574f6..d68c168 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -101,7 +101,7 @@ endif
libobj-$(TARGET_SPARC) += int32_helper.o
libobj-$(TARGET_SPARC64) += int64_helper.o
libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
-libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o \
+libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o int_helper.o\
intrpt.o intrpt_helper.o mmu.o mmu_helper.o

libobj-y += disas.o
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index fbcfd12..3d82d24 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -22,6 +22,14 @@
/* exception */
DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)

+/* int */
+DEF_HELPER_FLAGS_1(ff1, 0, tl, tl)
+DEF_HELPER_FLAGS_1(fl1, 0, tl, tl)
+DEF_HELPER_FLAGS_3(add, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addc, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(sub, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(mul, 0, tl, env, tl, tl)
+
/* interrupt */
DEF_HELPER_FLAGS_1(rfe, 0, void, env)

diff --git a/target-openrisc/int_helper.c b/target-openrisc/int_helper.c
new file mode 100644
index 0000000..4e6b9ac
--- /dev/null
+++ b/target-openrisc/int_helper.c
@@ -0,0 +1,155 @@
+/*
+ * Openrisc int helper routines
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ * Feng Gao <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "excp.h"
+
+target_ulong HELPER(ff1)(target_ulong x)
+{
+ target_ulong n = 0;
+
+ if (x == 0) {
+ return 0;
+ }
+
+ for (n = 32; x; n--) {
+ x <<= 1;
+ }
+ return n+1;
+}
+
+target_ulong HELPER(fl1)(target_ulong x)
+{
+ target_ulong n = 0;
+
+ if (x == 0) {
+ return 0;
+ }
+
+ for (n = 0; x; n++) {
+ x >>= 1;
+ }
+ return n;
+}
+
+target_ulong HELPER(add)(CPUOpenriscState * env, target_ulong a, target_ulong b)
+{
+ target_ulong result;
+ result = a + b;
+
+ if (result < a) {
+ env->sr |= SR_CY;
+ } else {
+ env->sr &= ~SR_CY;
+ }
+
+ if ((a ^ b ^ -1) & (a ^ result)) {
+ env->sr |= SR_OV;
+ if (env->sr & SR_OVE) {
+ raise_exception(env, EXCP_RANGE);
+ }
+ } else {
+ env->sr &= ~SR_OV;
+ }
+ return result;
+}
+
+target_ulong HELPER(addc)(CPUOpenriscState * env,
+ target_ulong a, target_ulong b)
+{
+ target_ulong result;
+ int cf = env->sr & SR_CY;
+
+ if (!cf) {
+ result = a + b;
+ cf = result < a;
+ } else {
+ result = a + b + 1;
+ cf = result <= a;
+ }
+
+ if (cf) {
+ env->sr |= SR_CY;
+ } else {
+ env->sr &= ~SR_CY;
+ }
+
+ if ((a ^ b ^ -1) & (a ^ result)) {
+ env->sr |= SR_OV;
+ if (env->sr & SR_OVE) {
+ raise_exception(env, EXCP_RANGE);
+ }
+ } else {
+ env->sr &= ~SR_OV;
+ }
+ return result;
+}
+
+target_ulong HELPER(sub)(CPUOpenriscState * env, target_ulong a, target_ulong b)
+{
+ target_ulong result;
+ result = a - b;
+ if (a >= b) {
+ env->sr |= SR_CY;
+ } else {
+ env->sr &= ~SR_CY;
+ }
+
+ if ((a ^ b) & (a ^ result)) {
+ env->sr |= SR_OV;
+ if (env->sr & SR_OVE) {
+ raise_exception(env, EXCP_RANGE);
+ }
+ } else {
+ env->sr &= ~SR_OV;
+ }
+ return result;
+}
+
+target_ulong HELPER(mul)(CPUOpenriscState * env, target_ulong a, target_ulong b)
+{
+ uint64_t result;
+ result = a * b;
+ target_ulong high;
+
+ high = result >> (sizeof(target_ulong) * 8);
+
+ if (((result >> ((sizeof(target_ulong) * 8) - 1)) & 0x1) == 0) {
+ if (high == 0) {
+ return result;
+ }
+ }
+
+ if (((result >> ((sizeof(target_ulong) * 8) - 1)) & 0x1) == 1) {
+ if (high == 0xffffffff) {
+ return result;
+ }
+ }
+
+ env->sr |= SR_OV;
+ env->sr |= SR_CY;
+
+ if (env->sr & SR_OVE) {
+ raise_exception(env, EXCP_RANGE);
+ }
+
+ return result;
+}
--
1.7.9.5
Jia Liu
2012-05-27 05:32:53 UTC
Permalink
add a timer for openrisc.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 1 +
cpu-exec.c | 4 ++
hw/openrisc_timer.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++++
target-openrisc/cpu.h | 20 ++++++-
4 files changed, 177 insertions(+), 1 deletion(-)
create mode 100644 hw/openrisc_timer.c

diff --git a/Makefile.target b/Makefile.target
index f2dfa2a..ca03b03 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -392,6 +392,7 @@ obj-xtensa-y += core-dc233c.o
obj-xtensa-y += core-fsf.o

obj-openrisc-y += openrisc_pic.o
+obj-openrisc-y += openrisc_timer.o

main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)

diff --git a/cpu-exec.c b/cpu-exec.c
index ee9afd7..845b2ae 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -382,6 +382,10 @@ int cpu_exec(CPUArchState *env)
&& (env->sr & SR_IEE)) {
idx = EXCP_INT;
}
+ if ((interrupt_request & CPU_INTERRUPT_TIMER)
+ && (env->sr & SR_TEE)) {
+ idx = EXCP_TICK;
+ }
if (idx >= 0) {
env->exception_index = idx;
do_interrupt(env);
diff --git a/hw/openrisc_timer.c b/hw/openrisc_timer.c
new file mode 100644
index 0000000..9f7c094
--- /dev/null
+++ b/hw/openrisc_timer.c
@@ -0,0 +1,153 @@
+/*
+ * QEMU openrisc timer support
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ * Zhizhou Zhang <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "hw.h"
+#include "openrisc_cpudev.h"
+#include "qemu-timer.h"
+
+#define TIMER_FREQ (20 * 1000 * 1000) /* 20MHz */
+
+/* The time when ttcr changes */
+static uint64_t last_clk;
+static int is_counting;
+
+/* Timer Mode */
+enum {
+ TIMER_NONE = (0<<30),
+ TIMER_INTR = (1<<30),
+ TIMER_SHOT = (2<<30),
+ TIMER_CONT = (3<<30),
+};
+
+static void count_update(CPUOpenriscState *env)
+{
+ uint64_t now, next;
+ uint32_t wait;
+
+ now = qemu_get_clock_ns(vm_clock);
+ if (!is_counting) {
+ qemu_del_timer(env->timer);
+ last_clk = now;
+ return;
+ }
+
+ env->ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
+ get_ticks_per_sec());
+ last_clk = now;
+
+ if ((env->ttmr & TTMR_TP) <= (env->ttcr & TTMR_TP)) {
+ wait = TTMR_TP - (env->ttcr & TTMR_TP) + 1;
+ wait += env->ttmr & TTMR_TP;
+ } else {
+ wait = (env->ttmr & TTMR_TP) - (env->ttcr & TTMR_TP);
+ }
+
+ next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
+ qemu_mod_timer(env->timer, next);
+}
+
+static void count_start(CPUOpenriscState *env)
+{
+ is_counting = 1;
+ count_update(env);
+}
+
+static void count_stop(CPUOpenriscState *env)
+{
+ is_counting = 0;
+ count_update(env);
+}
+
+uint32_t cpu_openrisc_get_count(CPUOpenriscState *env)
+{
+ count_update(env);
+ return env->ttcr;
+}
+
+void cpu_openrisc_store_count(CPUOpenriscState *env, uint32_t count)
+{
+ /* Store new count register */
+ env->ttcr = count;
+ if (env->ttmr & TIMER_NONE) {
+ return;
+ }
+ count_start(env);
+}
+
+void cpu_openrisc_store_compare(CPUOpenriscState *env, uint32_t value)
+{
+ int ip = env->ttmr & TTMR_IP;
+
+ if (value & TTMR_IP) { /* Keep IP bit */
+ env->ttmr = (value & ~TTMR_IP) + ip;
+ } else { /* Clear IP bit */
+ env->ttmr = value & ~TTMR_IP;
+ env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
+ }
+ count_update(env);
+
+ switch (env->ttmr & TTMR_M) {
+ case TIMER_NONE:
+ count_stop(env);
+ break;
+ case TIMER_INTR:
+ count_start(env);
+ break;
+ case TIMER_SHOT:
+ count_start(env);
+ break;
+ case TIMER_CONT:
+ count_start(env);
+ break;
+ }
+}
+
+static void openrisc_timer_cb(void *opaque)
+{
+ CPUOpenriscState *env = opaque;
+
+ if ((env->ttmr & TTMR_IE) &&
+ qemu_timer_expired(env->timer, qemu_get_clock_ns(vm_clock))) {
+ env->ttmr |= TTMR_IP;
+ env->interrupt_request |= CPU_INTERRUPT_TIMER;
+ }
+
+ switch (env->ttmr & TTMR_M) {
+ case TIMER_NONE:
+ break;
+ case TIMER_INTR:
+ env->ttcr = 0;
+ count_start(env);
+ break;
+ case TIMER_SHOT:
+ count_stop(env);
+ break;
+ case TIMER_CONT:
+ count_start(env);
+ break;
+ }
+}
+
+void cpu_openrisc_clock_init(CPUOpenriscState *env)
+{
+ env->timer = qemu_new_timer_ns(vm_clock, &openrisc_timer_cb, env);
+ env->ttmr = 0;
+ env->ttcr = 0;
+}
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 7417dcc..c3212b0 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -139,6 +139,14 @@ enum {
SR_SCE = (1<<17),
};

+/* TTMR bit */
+enum {
+ TTMR_TP = (0xfffffff),
+ TTMR_IP = (1<<28),
+ TTMR_IE = (1<<29),
+ TTMR_M = (3<<30),
+};
+
enum {
DTLB_WAYS = 1,
DTLB_SIZE = 64,
@@ -199,6 +207,10 @@ struct CPUOpenriscState {
target_phys_addr_t *physical, int *prot,
target_ulong address, int rw);

+ struct QEMUTimer *timer;
+ uint32_t ttmr; /* Timer tick mode register */
+ uint32_t ttcr; /* Timer tick count register */
+
uint32_t picmr; /* Interrupt mask register */
uint32_t picsr; /* Interrupt contrl register*/
#endif
@@ -276,6 +288,10 @@ int cpu_openrisc_handle_mmu_fault(CPUOpenriscState *env, target_ulong address,

void openrisc_reset(CPUOpenriscState *env);
#if !defined(CONFIG_USER_ONLY)
+void cpu_openrisc_store_count(CPUOpenriscState *env, target_ulong count);
+void cpu_openrisc_store_compare(CPUOpenriscState *env, target_ulong value);
+uint32_t cpu_openrisc_get_count(CPUOpenriscState *env);
+
void cpu_openrisc_pic_reset(CPUOpenriscState *env);
void cpu_openrisc_store_picsr(CPUOpenriscState *env, uint32_t value);
void cpu_openrisc_store_picmr(CPUOpenriscState *env, uint32_t value);
@@ -318,9 +334,11 @@ static inline int cpu_mmu_index(CPUOpenriscState *env)
return (env->sr & SR_SM) == 0 ? MMU_USER_IDX : MMU_SUPERVISOR_IDX;
}

+#define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_INT_0
static inline bool cpu_has_work(CPUOpenriscState *env)
{
- return 1;
+ return env->interrupt_request & (CPU_INTERRUPT_HARD |
+ CPU_INTERRUPT_TIMER);
}

#include "exec-all.h"
--
1.7.9.5
Jia Liu
2012-05-27 05:32:54 UTC
Permalink
add a simulator board implement for openrisc.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 1 +
hw/openrisc_sim.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 146 insertions(+)
create mode 100644 hw/openrisc_sim.c

diff --git a/Makefile.target b/Makefile.target
index ca03b03..d6eca9b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -393,6 +393,7 @@ obj-xtensa-y += core-fsf.o

obj-openrisc-y += openrisc_pic.o
obj-openrisc-y += openrisc_timer.o
+obj-openrisc-y += openrisc_sim.o

main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)

diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c
new file mode 100644
index 0000000..2605ab9
--- /dev/null
+++ b/hw/openrisc_sim.c
@@ -0,0 +1,145 @@
+/*
+ * Openrisc simulator for use as an ISS.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ * Feng Gao <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "hw.h"
+#include "openrisc_cpudev.h"
+#include "boards.h"
+#include "elf.h"
+#include "pc.h"
+#include "loader.h"
+#include "exec-memory.h"
+#include "sysemu.h"
+#include "isa.h"
+#include "qtest.h"
+
+#define KERNEL_LOAD_ADDR 0x100
+
+static struct _loaderparams {
+ uint64_t ram_size;
+ const char *kernel_filename;
+ const char *kernel_cmdline;
+ const char *initrd_filename;
+} loaderparams;
+
+static void main_cpu_reset(void *opaque)
+{
+ CPUOpenriscState *env = opaque;
+ cpu_state_reset(env);
+}
+
+static uint64_t openrisc_load_kernel(void)
+{
+ long kernel_size;
+ uint64_t elf_entry;
+ target_phys_addr_t entry;
+
+ if (loaderparams.kernel_filename && !qtest_enabled()) {
+ kernel_size = load_elf(loaderparams.kernel_filename, NULL, NULL,
+ &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
+ entry = elf_entry;
+ if (kernel_size < 0) {
+ kernel_size = load_uimage(loaderparams.kernel_filename,
+ &entry, NULL, NULL);
+ }
+ if (kernel_size < 0) {
+ kernel_size = load_image_targphys(loaderparams.kernel_filename,
+ KERNEL_LOAD_ADDR,
+ ram_size - KERNEL_LOAD_ADDR);
+ entry = KERNEL_LOAD_ADDR;
+ }
+ if (kernel_size < 0) {
+ fprintf(stderr, "qemu: could not load kernel '%s'\n",
+ loaderparams.kernel_filename);
+ exit(1);
+ }
+
+ if (kernel_size > 0) {
+ return elf_entry;
+ }
+ } else {
+ entry = 0;
+ }
+
+ return entry;
+}
+
+static void openrisc_sim_init(ram_addr_t ram_size,
+ const char *boot_device,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename,
+ const char *cpu_model)
+{
+ CPUOpenriscState *env;
+ MemoryRegion *ram = g_new(MemoryRegion, 1);
+ qemu_irq *i8259;
+ ISABus *isa_bus;
+
+ if (!cpu_model) {
+ cpu_model = "or1200";
+ }
+ env = cpu_init(cpu_model);
+ if (!env) {
+ fprintf(stderr, "Unable to find CPU definition!\n");
+ exit(1);
+ }
+
+ qemu_register_reset(main_cpu_reset, env);
+ main_cpu_reset(env);
+
+ memory_region_init_ram(ram, "openrisc.ram", ram_size);
+ memory_region_add_subregion(get_system_memory(), 0, ram);
+
+ if (kernel_filename) {
+ loaderparams.ram_size = ram_size;
+ loaderparams.kernel_filename = kernel_filename;
+ loaderparams.kernel_cmdline = kernel_cmdline;
+ env->pc = openrisc_load_kernel();
+ }
+
+ cpu_openrisc_pic_init(env);
+ cpu_openrisc_clock_init(env);
+
+ isa_bus = isa_bus_new(NULL, get_system_io());
+ i8259 = i8259_init(isa_bus, env->irq[3]);
+ isa_bus_irqs(isa_bus, i8259);
+
+ serial_mm_init(get_system_memory(), 0x90000000, 0,
+ env->irq[2], 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
+
+ if (nd_table[0].vlan) {
+ isa_ne2000_init(isa_bus, 0x92000000, 4, &nd_table[0]);
+ }
+}
+
+static QEMUMachine openrisc_sim_machine = {
+ .name = "or32-sim",
+ .desc = "or32 simulation",
+ .init = openrisc_sim_init,
+ .max_cpus = 1,
+ .is_default = 1,
+};
+
+static void openrisc_sim_machine_init(void)
+{
+ qemu_register_machine(&openrisc_sim_machine);
+}
+
+machine_init(openrisc_sim_machine_init);
--
1.7.9.5
Jia Liu
2012-05-27 05:32:55 UTC
Permalink
add system instruction helpers for openrisc.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 2 +-
target-openrisc/helper.h | 4 +
target-openrisc/sys_helper.c | 226 ++++++++++++++++++++++++++++++++++++++++++
target-openrisc/translate.c | 18 ++++
4 files changed, 249 insertions(+), 1 deletion(-)
create mode 100644 target-openrisc/sys_helper.c

diff --git a/Makefile.target b/Makefile.target
index d6eca9b..eec3322 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -102,7 +102,7 @@ libobj-$(TARGET_SPARC) += int32_helper.o
libobj-$(TARGET_SPARC64) += int64_helper.o
libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o fpu_helper.o int_helper.o\
-intrpt.o intrpt_helper.o mmu.o mmu_helper.o
+intrpt.o intrpt_helper.o mmu.o mmu_helper.o sys_helper.o

libobj-y += disas.o
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index b26aad8..81ef900 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -66,4 +66,8 @@ DEF_HELPER_FLAGS_3(mul, 0, tl, env, tl, tl)
/* interrupt */
DEF_HELPER_FLAGS_1(rfe, 0, void, env)

+/* sys */
+DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl)
+DEF_HELPER_FLAGS_4(mfspr, 0, void, env, tl, tl, tl)
+
#include "def-helper.h"
diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
new file mode 100644
index 0000000..fb193ac
--- /dev/null
+++ b/target-openrisc/sys_helper.c
@@ -0,0 +1,226 @@
+/*
+ * Openrisc system-insns helper routines
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ * Zhizhou Zhang <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+
+#define TO_SPR(group, number) (((group)<<11)+(number))
+void HELPER(mtspr)(CPUOpenriscState * env,
+ target_ulong ra, target_ulong rb, uint32_t offset)
+{
+#if !defined(CONFIG_USER_ONLY)
+ int spr = env->gpr[ra] | offset;
+ int idx;
+
+ switch (spr) {
+ case TO_SPR(0, 16): /* NPC */
+ env->npc = env->gpr[rb];
+ break;
+
+ case TO_SPR(0, 17): /* SR */
+ if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
+ (env->gpr[rb] & (SR_IME | SR_DME | SR_SM))) {
+ tlb_flush(env, 1);
+ }
+ env->sr = env->gpr[rb];
+ env->sr |= SR_FO; /* FO is const equal to 1 */
+ if (env->sr & SR_DME) {
+ env->map_address_data = &get_phys_data;
+ } else {
+ env->map_address_data = &get_phys_nommu;
+ }
+
+ if (env->sr & SR_IME) {
+ env->map_address_code = &get_phys_code;
+ } else {
+ env->map_address_code = &get_phys_nommu;
+ }
+ break;
+
+ case TO_SPR(0, 18): /* PPC */
+ env->ppc = env->gpr[rb];
+ break;
+
+ case TO_SPR(0, 32): /* EPCR */
+ env->epcr = env->gpr[rb];
+ break;
+
+ case TO_SPR(0, 48): /* EEAR */
+ env->eear = env->gpr[rb];
+ break;
+
+ case TO_SPR(0, 64): /* ESR */
+ env->esr = env->gpr[rb];
+ break;
+ case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
+ idx = spr - TO_SPR(1, 512);
+ if (!(env->gpr[rb] & 1)) {
+ tlb_flush_page(env, env->dtlb[0][idx].mr & TARGET_PAGE_MASK);
+ }
+ env->dtlb[0][idx].mr = env->gpr[rb];
+ break;
+
+ case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
+ idx = spr - TO_SPR(1, 640);
+ env->dtlb[0][idx].tr = env->gpr[rb];
+ break;
+ case TO_SPR(1, 768) ... TO_SPR(1, 895): /* DTLBW1MR 0-127 */
+ case TO_SPR(1, 896) ... TO_SPR(1, 1023): /* DTLBW1TR 0-127 */
+ case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
+ case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
+ case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
+ case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
+ break;
+ case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */
+ idx = spr - TO_SPR(2, 512);
+ if (!(env->gpr[rb] & 1)) {
+ tlb_flush_page(env, env->itlb[0][idx].mr & TARGET_PAGE_MASK);
+ }
+ env->itlb[0][idx].mr = env->gpr[rb];
+ break;
+
+ case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
+ idx = spr - TO_SPR(2, 640);
+ env->itlb[0][idx].tr = env->gpr[rb];
+ case TO_SPR(2, 768) ... TO_SPR(2, 895): /* ITLBW1MR 0-127 */
+ case TO_SPR(2, 896) ... TO_SPR(2, 1023): /* ITLBW1TR 0-127 */
+ case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
+ case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 0-127 */
+ case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */
+ case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
+ break;
+ case TO_SPR(9, 0): /* PICMR */
+ cpu_openrisc_store_picmr(env, env->gpr[rb]);
+ break;
+ case TO_SPR(9, 2): /* PICSR */
+ cpu_openrisc_store_picsr(env, env->gpr[rb]);
+ break;
+ case TO_SPR(10, 0): /* TTMR */
+ cpu_openrisc_store_compare(env, env->gpr[rb]);
+ break;
+ case TO_SPR(10, 1): /* TTCR */
+ cpu_openrisc_store_count(env, env->gpr[rb]);
+ break;
+ default:
+ break;
+ }
+#endif
+}
+
+void HELPER(mfspr)(CPUOpenriscState * env,
+ target_ulong rd, target_ulong ra, uint32_t offset)
+{
+#if !defined(CONFIG_USER_ONLY)
+ int spr = env->gpr[ra] | offset;
+ int idx;
+
+ switch (spr) {
+ case TO_SPR(0, 0): /* VR */
+ env->gpr[rd] = SPR_VR;
+ break;
+
+ case TO_SPR(0, 1): /* UPR */
+ env->gpr[rd] = 0x619; /* TT, DM, IM, UP present */
+ break;
+
+ case TO_SPR(0, 2): /* CPUCFGR */
+ env->gpr[rd] = 0x000000a0;
+ break;
+
+ case TO_SPR(0, 3): /* DMMUCFGR */
+ env->gpr[rd] = 0x18; /* 1Way, 64 entries */
+ break;
+ case TO_SPR(0, 4): /* IMMUCFGR */
+ env->gpr[rd] = 0x18;
+ break;
+
+ case TO_SPR(0, 16): /* NPC */
+ env->gpr[rd] = env->npc;
+ break;
+
+ case TO_SPR(0, 17): /* SR */
+ env->gpr[rd] = env->sr;
+ break;
+
+ case TO_SPR(0, 18): /* PPC */
+ env->gpr[rd] = env->ppc;
+ break;
+
+ case TO_SPR(0, 32): /* EPCR */
+ env->gpr[rd] = env->epcr;
+ break;
+
+ case TO_SPR(0, 48): /* EEAR */
+ env->gpr[rd] = env->eear;
+ break;
+
+ case TO_SPR(0, 64): /* ESR */
+ env->gpr[rd] = env->esr;
+ break;
+ case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
+ idx = spr - TO_SPR(1, 512);
+ env->gpr[rd] = env->dtlb[0][idx].mr;
+ break;
+
+ case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
+ idx = spr - TO_SPR(1, 640);
+ env->gpr[rd] = env->dtlb[0][idx].tr;
+ break;
+ case TO_SPR(1, 768) ... TO_SPR(1, 895): /* DTLBW1MR 0-127 */
+ case TO_SPR(1, 896) ... TO_SPR(1, 1023): /* DTLBW1TR 0-127 */
+ case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
+ case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
+ case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
+ case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
+ break;
+
+ case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */
+ idx = spr - TO_SPR(2, 512);
+ env->gpr[rd] = env->itlb[0][idx].mr;
+ break;
+
+ case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
+ idx = spr - TO_SPR(2, 640);
+ env->gpr[rd] = env->itlb[0][idx].tr;
+ break;
+ case TO_SPR(2, 768) ... TO_SPR(2, 895): /* ITLBW1MR 0-127 */
+ case TO_SPR(2, 896) ... TO_SPR(2, 1023): /* ITLBW1TR 0-127 */
+ case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
+ case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 0-127 */
+ case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */
+ case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
+ break;
+ case TO_SPR(9, 0): /* PICMR */
+ env->gpr[rd] = env->picmr;
+ break;
+ case TO_SPR(9, 2): /* PICSR */
+ env->gpr[rd] = env->picsr;
+ break;
+ case TO_SPR(10, 0): /* TTMR */
+ env->gpr[rd] = env->ttmr;
+ break;
+ case TO_SPR(10, 1): /* TTCR */
+ env->gpr[rd] = cpu_openrisc_get_count(env);
+ break;
+ default:
+ break;
+ }
+#endif
+}
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 965fa0e..236f7af 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -748,10 +748,28 @@ static void dec_misc(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)

case 0x2d: /*l.mfspr*/
LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
+ {
+ TCGv_i32 ti = tcg_const_i32(I16);
+ TCGv td = tcg_const_tl(rd);
+ TCGv ta = tcg_const_tl(ra);
+ gen_helper_mfspr(cpu_env, td, ta, ti);
+ tcg_temp_free_i32(ti);
+ tcg_temp_free(td);
+ tcg_temp_free(ta);
+ }
break;

case 0x30: /*l.mtspr*/
LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+ {
+ TCGv_i32 ti = tcg_const_i32(tmp);
+ TCGv ta = tcg_const_tl(ra);
+ TCGv tb = tcg_const_tl(rb);
+ gen_helper_mtspr(cpu_env, ta, tb, ti);
+ tcg_temp_free_i32(ti);
+ tcg_temp_free(ta);
+ tcg_temp_free(tb);
+ }
break;

case 0x34: /*l.sd*/
--
1.7.9.5
Jia Liu
2012-05-27 05:32:58 UTC
Permalink
add linux user support for openrisc.

Signed-off-by: Jia Liu <***@gmail.com>
---
configure | 1 +
default-configs/or32-linux-user.mak | 2 +
linux-user/elfload.c | 41 +++++++
linux-user/main.c | 100 +++++++++++++++
linux-user/signal.c | 229 +++++++++++++++++++++++++++++++++++
linux-user/syscall.c | 2 +-
linux-user/syscall_defs.h | 40 +++++-
target-openrisc/cpu.h | 13 +-
8 files changed, 423 insertions(+), 5 deletions(-)
create mode 100644 default-configs/or32-linux-user.mak

diff --git a/configure b/configure
index bcfe00f..62b9519 100755
--- a/configure
+++ b/configure
@@ -951,6 +951,7 @@ microblaze-linux-user \
microblazeel-linux-user \
mips-linux-user \
mipsel-linux-user \
+or32-linux-user \
ppc-linux-user \
ppc64-linux-user \
ppc64abi32-linux-user \
diff --git a/default-configs/or32-linux-user.mak b/default-configs/or32-linux-user.mak
new file mode 100644
index 0000000..d2fdf22
--- /dev/null
+++ b/default-configs/or32-linux-user.mak
@@ -0,0 +1,2 @@
+# Default configuration for or32-linux-user
+
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index f3b1552..27c4a86 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -787,6 +787,47 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env

#endif /* TARGET_MICROBLAZE */

+#ifdef TARGET_OPENRISC
+
+#define ELF_START_MMAP 0x08000000
+
+#define elf_check_arch(x) ((x) == EM_OPENRISC)
+
+#define ELF_ARCH EM_OPENRISC
+#define ELF_CLASS ELFCLASS32
+#define ELF_DATA ELFDATA2MSB
+
+static inline void init_thread(struct target_pt_regs *regs,
+ struct image_info *infop)
+{
+ regs->pc = infop->entry;
+ regs->gpr[1] = infop->start_stack;
+}
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE 8192
+
+/* See linux kernel arch/openrisc/include/asm/elf.h. */
+#define ELF_NREG 34 /* gprs and pc, sr */
+typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
+
+static void elf_core_copy_regs(target_elf_gregset_t *regs,
+ const CPUOpenriscState *env)
+{
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ (*regs)[i] = tswapl(env->gpr[i]);
+ }
+
+ (*regs)[32] = tswapl(env->pc);
+ (*regs)[33] = tswapl(env->sr);
+}
+#define ELF_HWCAP 0
+#define ELF_PLATFORM NULL
+
+#endif /* TARGET_OPENRISC */
+
#ifdef TARGET_SH4

#define ELF_START_MMAP 0x80000000
diff --git a/linux-user/main.c b/linux-user/main.c
index 191b750..7352bc1 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2305,6 +2305,93 @@ done_syscall:
}
#endif

+#ifdef TARGET_OPENRISC
+
+void cpu_loop(CPUOpenriscState *env)
+{
+ int trapnr, gdbsig;
+
+ for (;;) {
+ trapnr = cpu_exec(env);
+ gdbsig = 0;
+
+ switch (trapnr) {
+ case EXCP_RESET:
+ fprintf(stderr, "\nReset request, exit, pc is %#x\n", env->pc);
+ exit(1);
+ break;
+ case EXCP_BUSERR:
+ fprintf(stderr, "\nBus error, exit, pc is %#x\n", env->pc);
+ gdbsig = SIGBUS;
+ break;
+ case EXCP_DPF:
+ case EXCP_IPF:
+ cpu_dump_state(env, stderr, fprintf, 0);
+ gdbsig = TARGET_SIGSEGV;
+ break;
+ case EXCP_TICK:
+ fprintf(stderr, "\nTick time interrupt pc is %#x\n", env->pc);
+ break;
+ case EXCP_ALIGN:
+ fprintf(stderr, "\nAlignment pc is %#x\n", env->pc);
+ gdbsig = SIGBUS;
+ break;
+ case EXCP_ILLEGAL:
+ fprintf(stderr, "\nIllegal instructionpc is %#x\n", env->pc);
+ gdbsig = SIGILL;
+ break;
+ case EXCP_INT:
+ fprintf(stderr, "\nExternal interruptpc is %#x\n", env->pc);
+ break;
+ case EXCP_DTLBMISS:
+ case EXCP_ITLBMISS:
+ printf("TLB miss\n");
+ break;
+ case EXCP_RANGE:
+ fprintf(stderr, "\nRange\n");
+ gdbsig = SIGSEGV;
+ break;
+ case EXCP_SYSCALL:
+ env->pc += 4; /* 0xc00; */
+ env->gpr[11] = do_syscall(env,
+ env->gpr[11], /* return value */
+ env->gpr[3], /* r3 - r7 are params */
+ env->gpr[4],
+ env->gpr[5],
+ env->gpr[6],
+ env->gpr[7],
+ env->gpr[8], 0, 0);
+ break;
+ case EXCP_FPE:
+ fprintf(stderr, "Floating point error\n");
+ break;
+ case EXCP_TRAP:
+ fprintf(stderr, "Trap\n");
+ gdbsig = SIGTRAP;
+ break;
+ case EXCP_NR:
+ fprintf(stderr, "NR\n");
+ break;
+ default:
+ fprintf(stderr, "qemu: unhandled CPU exception %#x - aborting\n", \
+ trapnr);
+ cpu_dump_state(env, stderr, fprintf, 0);
+ gdbsig = TARGET_SIGILL;
+ break;
+ }
+ if (gdbsig) {
+ gdb_handlesig(env, gdbsig);
+ if (gdbsig != TARGET_SIGTRAP) {
+ exit(1);
+ }
+ }
+
+ process_pending_signals(env);
+ }
+}
+
+#endif /* TARGET_OPENRISC */
+
#ifdef TARGET_SH4
void cpu_loop(CPUSH4State *env)
{
@@ -3385,6 +3472,8 @@ int main(int argc, char **argv, char **envp)
#else
cpu_model = "24Kf";
#endif
+#elif defined TARGET_OPENRISC
+ cpu_model = "or1200";
#elif defined(TARGET_PPC)
#ifdef TARGET_PPC64
cpu_model = "970fx";
@@ -3787,6 +3876,17 @@ int main(int argc, char **argv, char **envp)
env->hflags |= MIPS_HFLAG_M16;
}
}
+#elif defined(TARGET_OPENRISC)
+ {
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ env->gpr[i] = regs->gpr[i];
+ }
+
+ env->sr = regs->sr;
+ env->pc = regs->pc;
+ }
#elif defined(TARGET_SH4)
{
int i;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index b1e139d..5dda04c 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -3629,6 +3629,235 @@ long do_rt_sigreturn(CPUCRISState *env)
return -TARGET_ENOSYS;
}

+#elif defined(TARGET_OPENRISC)
+
+struct target_sigcontext {
+ struct target_pt_regs regs;
+ abi_ulong oldmask;
+ abi_ulong usp;
+};
+
+struct target_ucontext {
+ abi_ulong tuc_flags;
+ abi_ulong tuc_link;
+ target_stack_t tuc_stack;
+ struct target_sigcontext tuc_mcontext;
+ target_sigset_t tuc_sigmask; /* mask last for extensibility */
+};
+
+struct target_rt_sigframe {
+ abi_ulong pinfo;
+ uint64_t puc;
+ struct target_siginfo info;
+ struct target_sigcontext sc;
+ struct target_ucontext uc;
+ unsigned char retcode[16]; /* trampoline code */
+};
+
+/* This is the asm-generic/ucontext.h version */
+#if 0
+static int restore_sigcontext(CPUOpenriscState *regs,
+ struct target_sigcontext *sc)
+{
+ unsigned int err = 0;
+ unsigned long old_usp;
+
+ /* Alwys make any pending restarted system call return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+ /* restore the regs from &sc->regs (same as sc, since regs is first)
+ * (sc is already checked for VERIFY_READ since the sigframe was
+ * checked in sys_sigreturn previously)
+ */
+
+ if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
+ goto badframe;
+ }
+
+ /* make sure the U-flag is set so user-mode cannot fool us */
+
+ regs->sr &= ~SR_SM;
+
+ /* restore the old USP as it was before we stacked the sc etc.
+ * (we cannot just pop the sigcontext since we aligned the sp and
+ * stuff after pushing it)
+ */
+
+ err |= __get_user(old_usp, &sc->usp);
+ phx_signal("old_usp 0x%lx", old_usp);
+
+ __PHX__ REALLY /* ??? */
+ wrusp(old_usp);
+ regs->gpr[1] = old_usp;
+
+ /* TODO: the other ports use regs->orig_XX to disable syscall checks
+ * after this completes, but we don't use that mechanism. maybe we can
+ * use it now ?
+ */
+
+ return err;
+
+badframe:
+ return 1;
+}
+#endif
+
+/* Set up a signal frame. */
+
+static int setup_sigcontext(struct target_sigcontext *sc,
+ CPUOpenriscState *regs,
+ unsigned long mask)
+{
+ int err = 0;
+ unsigned long usp = regs->gpr[1];
+
+ /* copy the regs. they are first in sc so we can use sc directly */
+
+ /*err |= copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
+
+ /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
+ the signal handler. The frametype will be restored to its previous
+ value in restore_sigcontext. */
+ /*regs->frametype = CRIS_FRAME_NORMAL;*/
+
+ /* then some other stuff */
+ err |= __put_user(mask, &sc->oldmask);
+ err |= __put_user(usp, &sc->usp); return err;
+}
+
+static inline unsigned long align_sigframe(unsigned long sp)
+{
+ unsigned long i;
+ i = sp & ~3UL;
+ return i;
+}
+
+static inline abi_ulong get_sigframe(struct target_sigaction *ka,
+ CPUOpenriscState *regs,
+ size_t frame_size)
+{
+ unsigned long sp = regs->gpr[1];
+ int onsigstack = on_sig_stack(sp);
+
+ /* redzone */
+ /* This is the X/Open sanctioned signal stack switching. */
+ if ((ka->sa_flags & SA_ONSTACK) != 0 && !onsigstack) {
+ sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+ }
+
+ sp = align_sigframe(sp - frame_size);
+
+ /*
+ * If we are on the alternate signal stack and would overflow it, don't.
+ * Return an always-bogus address instead so we will die with SIGSEGV.
+ */
+
+ if (onsigstack && !likely(on_sig_stack(sp))) {
+ return -1L;
+ }
+
+ return sp;
+}
+
+static void setup_frame(int sig, struct target_sigaction *ka,
+ target_sigset_t *set, CPUOpenriscState *env)
+{
+ printf("Not implement.\n");
+}
+
+static void setup_rt_frame(int sig, struct target_sigaction *ka,
+ target_siginfo_t *info,
+ target_sigset_t *set, CPUOpenriscState *env)
+{
+ int err = 0;
+ abi_ulong frame_addr;
+ unsigned long return_ip;
+ struct target_rt_sigframe *frame;
+ abi_ulong info_addr, uc_addr;
+
+ frame_addr = get_sigframe(ka, env, sizeof *frame);
+
+ frame_addr = get_sigframe(ka, env, sizeof(*frame));
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+ goto give_sigsegv;
+ }
+
+ info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
+ err |= __put_user(info_addr, &frame->pinfo);
+ uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
+ err |= __put_user(uc_addr, &frame->puc);
+
+ if (ka->sa_flags & SA_SIGINFO) {
+ err |= copy_siginfo_to_user(&frame->info, info);
+ }
+ if (err) {
+ goto give_sigsegv;
+ }
+
+ /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/
+ err |= __put_user(0, &frame->uc.tuc_flags);
+ err |= __put_user(0, &frame->uc.tuc_link);
+ err |= __put_user(target_sigaltstack_used.ss_sp,
+ &frame->uc.tuc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
+ err |= __put_user(target_sigaltstack_used.ss_size,
+ &frame->uc.tuc_stack.ss_size);
+ err |= setup_sigcontext(&frame->sc, env, set->sig[0]);
+
+ /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
+
+ if (err) {
+ goto give_sigsegv;
+ }
+
+ /* trampoline - the desired return ip is the retcode itself */
+ return_ip = (unsigned long)&frame->retcode;
+ /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
+ err |= __put_user(0xa960, (short *)(frame->retcode + 0));
+ err |= __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
+ err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
+ err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
+
+ if (err) {
+ goto give_sigsegv;
+ }
+
+ /* TODO what is the current->exec_domain stuff and invmap ? */
+
+ /* Set up registers for signal handler */
+ env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
+ env->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
+ env->gpr[3] = (unsigned long)sig; /* arg 1: signo */
+ env->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
+ env->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
+
+ /* actually move the usp to reflect the stacked frame */
+ env->gpr[1] = (unsigned long)frame;
+
+ return;
+
+give_sigsegv:
+ unlock_user_struct(frame, frame_addr, 1);
+ if (sig == TARGET_SIGSEGV) {
+ ka->_sa_handler = TARGET_SIG_DFL;
+ }
+ force_sig(TARGET_SIGSEGV);
+}
+
+long do_sigreturn(CPUOpenriscState *env)
+{
+
+ fprintf(stderr, "do_sigreturn: not implemented\n");
+ return -TARGET_ENOSYS;
+}
+
+long do_rt_sigreturn(CPUOpenriscState *env)
+{
+ fprintf(stderr, "do_rt_sigreturn: not implemented\n");
+ return -TARGET_ENOSYS;
+}
+/* TARGET_OPENRISC */
+
#elif defined(TARGET_S390X)

#define __NUM_GPRS 16
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 20d2a74..cceb9bc 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7377,7 +7377,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_sigaltstack:
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) || \
- defined(TARGET_M68K) || defined(TARGET_S390X)
+ defined(TARGET_M68K) || defined(TARGET_S390X) || defined(TARGET_OPENRISC)
ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUArchState *)cpu_env));
break;
#else
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index a79b67d..4facfb4 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -59,7 +59,7 @@

#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
|| defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) \
- || defined(TARGET_S390X)
+ || defined(TARGET_S390X) || defined(TARGET_OPENRISC)

#define TARGET_IOC_SIZEBITS 14
#define TARGET_IOC_DIRBITS 2
@@ -323,7 +323,7 @@ int do_sigaction(int sig, const struct target_sigaction *act,
|| defined(TARGET_PPC) || defined(TARGET_MIPS) || defined(TARGET_SH4) \
|| defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) \
|| defined(TARGET_MICROBLAZE) || defined(TARGET_UNICORE32) \
- || defined(TARGET_S390X)
+ || defined(TARGET_S390X) || defined(TARGET_OPENRISC)

#if defined(TARGET_SPARC)
#define TARGET_SA_NOCLDSTOP 8u
@@ -344,6 +344,14 @@ int do_sigaction(int sig, const struct target_sigaction *act,
#if !defined(TARGET_ABI_MIPSN32) && !defined(TARGET_ABI_MIPSN64)
#define TARGET_SA_RESTORER 0x04000000 /* Only for O32 */
#endif
+#elif defined(TARGET_OPENRISC)
+#define TARGET_SA_NOCLDSTOP 0x00000001
+#define TARGET_SA_NOCLDWAIT 0x00000002
+#define TARGET_SA_SIGINFO 0x00000004
+#define TARGET_SA_ONSTACK 0x08000000
+#define TARGET_SA_RESTART 0x10000000
+#define TARGET_SA_NODEFER 0x40000000
+#define TARGET_SA_RESETHAND 0x80000000
#elif defined(TARGET_ALPHA)
#define TARGET_SA_ONSTACK 0x00000001
#define TARGET_SA_RESTART 0x00000002
@@ -448,6 +456,7 @@ int do_sigaction(int sig, const struct target_sigaction *act,

#else

+/* Openrisc Using the general signals */
#define TARGET_SIGHUP 1
#define TARGET_SIGINT 2
#define TARGET_SIGQUIT 3
@@ -1086,7 +1095,8 @@ struct target_winsize {
#endif

#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) \
- || defined(TARGET_CRIS) || defined(TARGET_UNICORE32)
+ || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) \
+ || defined(TARGET_OPENRISC)
struct target_stat {
unsigned short st_dev;
unsigned short __pad1;
@@ -1783,6 +1793,30 @@ struct target_stat {
abi_long st_blocks;
abi_ulong __unused[3];
};
+#elif defined(TARGET_OPENRISC)
+struct target_stat {
+ abi_ulong st_dev;
+ abi_ulong st_ino;
+ abi_ulong st_nlink;
+
+ unsigned int st_mode;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned int __pad0;
+ abi_ulong st_rdev;
+ abi_long st_size;
+ abi_long st_blksize;
+ abi_long st_blocks; /* Number 512-byte blocks allocated. */
+
+ abi_ulong target_st_atime;
+ abi_ulong target_st_atime_nsec;
+ abi_ulong target_st_mtime;
+ abi_ulong target_st_mtime_nsec;
+ abi_ulong target_st_ctime;
+ abi_ulong target_st_ctime_nsec;
+
+ abi_long __unused[3];
+};
#else
#error unsupported CPU
#endif
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index c3212b0..9b8ece8 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -275,13 +275,14 @@ void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
OpenriscCPU *cpu_openrisc_init(const char *cpu_model);
int cpu_openrisc_exec(CPUOpenriscState *s);
void do_interrupt(CPUOpenriscState *env);
+int cpu_openrisc_signal_handler(int host_signum, void *pinfo, void *puc);
void openrisc_translate_init(void);
int cpu_openrisc_handle_mmu_fault(CPUOpenriscState *env, target_ulong address,
int rw, int mmu_idx);
-
#define cpu_list cpu_openrisc_list
#define cpu_exec cpu_openrisc_exec
#define cpu_gen_code cpu_openrisc_gen_code
+#define cpu_signal_handler cpu_openrisc_signal_handler
#define cpu_handle_mmu_fault cpu_openrisc_handle_mmu_fault

#define CPU_SAVE_VERSION 1
@@ -314,6 +315,16 @@ static inline CPUOpenriscState *cpu_init(const char *cpu_model)
return NULL;
}

+#if defined(CONFIG_USER_ONLY)
+static inline void cpu_clone_regs(CPUOpenriscState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->gpr[1] = newsp;
+ }
+ env->gpr[2] = 0;
+}
+#endif
+
#include "cpu-all.h"

static inline void cpu_get_tb_cpu_state(CPUOpenriscState *env,
--
1.7.9.5
Jia Liu
2012-05-27 05:32:59 UTC
Permalink
add testcases for openrisc.

Signed-off-by: Jia Liu <***@gmail.com>
---
tests/tcg/openrisc/Makefile | 73 ++++++++++++++++++++++++++++
tests/tcg/openrisc/test_add.c | 34 +++++++++++++
tests/tcg/openrisc/test_addc.c | 37 ++++++++++++++
tests/tcg/openrisc/test_addi.c | 31 ++++++++++++
tests/tcg/openrisc/test_addic.c | 32 ++++++++++++
tests/tcg/openrisc/test_and_or.c | 61 +++++++++++++++++++++++
tests/tcg/openrisc/test_bf.c | 46 ++++++++++++++++++
tests/tcg/openrisc/test_bnf.c | 50 +++++++++++++++++++
tests/tcg/openrisc/test_div.c | 32 ++++++++++++
tests/tcg/openrisc/test_extx.c | 71 +++++++++++++++++++++++++++
tests/tcg/openrisc/test_fx.c | 53 ++++++++++++++++++++
tests/tcg/openrisc/test_j.c | 26 ++++++++++
tests/tcg/openrisc/test_jal.c | 26 ++++++++++
tests/tcg/openrisc/test_lf_add.c | 32 ++++++++++++
tests/tcg/openrisc/test_lf_div.c | 33 +++++++++++++
tests/tcg/openrisc/test_lf_eqd.c | 44 +++++++++++++++++
tests/tcg/openrisc/test_lf_eqs.c | 43 ++++++++++++++++
tests/tcg/openrisc/test_lf_ged.c | 45 +++++++++++++++++
tests/tcg/openrisc/test_lf_ges.c | 45 +++++++++++++++++
tests/tcg/openrisc/test_lf_gtd.c | 45 +++++++++++++++++
tests/tcg/openrisc/test_lf_gts.c | 45 +++++++++++++++++
tests/tcg/openrisc/test_lf_led.c | 43 ++++++++++++++++
tests/tcg/openrisc/test_lf_les.c | 45 +++++++++++++++++
tests/tcg/openrisc/test_lf_ltd.c | 45 +++++++++++++++++
tests/tcg/openrisc/test_lf_lts.c | 45 +++++++++++++++++
tests/tcg/openrisc/test_lf_mul.c | 22 +++++++++
tests/tcg/openrisc/test_lf_ned.c | 46 ++++++++++++++++++
tests/tcg/openrisc/test_lf_nes.c | 46 ++++++++++++++++++
tests/tcg/openrisc/test_lf_rem.c | 31 ++++++++++++
tests/tcg/openrisc/test_lf_sub.c | 31 ++++++++++++
tests/tcg/openrisc/test_logic.c | 100 ++++++++++++++++++++++++++++++++++++++
tests/tcg/openrisc/test_lx.c | 78 +++++++++++++++++++++++++++++
tests/tcg/openrisc/test_movhi.c | 30 ++++++++++++
tests/tcg/openrisc/test_mul.c | 47 ++++++++++++++++++
tests/tcg/openrisc/test_sfeq.c | 43 ++++++++++++++++
tests/tcg/openrisc/test_sfeqi.c | 39 +++++++++++++++
tests/tcg/openrisc/test_sfges.c | 44 +++++++++++++++++
tests/tcg/openrisc/test_sfgesi.c | 40 +++++++++++++++
tests/tcg/openrisc/test_sfgeu.c | 44 +++++++++++++++++
tests/tcg/openrisc/test_sfgeui.c | 41 ++++++++++++++++
tests/tcg/openrisc/test_sfgts.c | 45 +++++++++++++++++
tests/tcg/openrisc/test_sfgtsi.c | 41 ++++++++++++++++
tests/tcg/openrisc/test_sfgtu.c | 43 ++++++++++++++++
tests/tcg/openrisc/test_sfgtui.c | 42 ++++++++++++++++
tests/tcg/openrisc/test_sfles.c | 26 ++++++++++
tests/tcg/openrisc/test_sflesi.c | 39 +++++++++++++++
tests/tcg/openrisc/test_sfleu.c | 43 ++++++++++++++++
tests/tcg/openrisc/test_sfleui.c | 39 +++++++++++++++
tests/tcg/openrisc/test_sflts.c | 43 ++++++++++++++++
tests/tcg/openrisc/test_sfltsi.c | 38 +++++++++++++++
tests/tcg/openrisc/test_sfltu.c | 41 ++++++++++++++++
tests/tcg/openrisc/test_sfltui.c | 39 +++++++++++++++
tests/tcg/openrisc/test_sfne.c | 43 ++++++++++++++++
tests/tcg/openrisc/test_sfnei.c | 38 +++++++++++++++
54 files changed, 2324 insertions(+)
create mode 100644 tests/tcg/openrisc/Makefile
create mode 100644 tests/tcg/openrisc/test_add.c
create mode 100644 tests/tcg/openrisc/test_addc.c
create mode 100644 tests/tcg/openrisc/test_addi.c
create mode 100644 tests/tcg/openrisc/test_addic.c
create mode 100644 tests/tcg/openrisc/test_and_or.c
create mode 100644 tests/tcg/openrisc/test_bf.c
create mode 100644 tests/tcg/openrisc/test_bnf.c
create mode 100644 tests/tcg/openrisc/test_div.c
create mode 100644 tests/tcg/openrisc/test_extx.c
create mode 100644 tests/tcg/openrisc/test_fx.c
create mode 100644 tests/tcg/openrisc/test_j.c
create mode 100644 tests/tcg/openrisc/test_jal.c
create mode 100644 tests/tcg/openrisc/test_lf_add.c
create mode 100644 tests/tcg/openrisc/test_lf_div.c
create mode 100644 tests/tcg/openrisc/test_lf_eqd.c
create mode 100644 tests/tcg/openrisc/test_lf_eqs.c
create mode 100644 tests/tcg/openrisc/test_lf_ged.c
create mode 100644 tests/tcg/openrisc/test_lf_ges.c
create mode 100644 tests/tcg/openrisc/test_lf_gtd.c
create mode 100644 tests/tcg/openrisc/test_lf_gts.c
create mode 100644 tests/tcg/openrisc/test_lf_led.c
create mode 100644 tests/tcg/openrisc/test_lf_les.c
create mode 100644 tests/tcg/openrisc/test_lf_ltd.c
create mode 100644 tests/tcg/openrisc/test_lf_lts.c
create mode 100644 tests/tcg/openrisc/test_lf_mul.c
create mode 100644 tests/tcg/openrisc/test_lf_ned.c
create mode 100644 tests/tcg/openrisc/test_lf_nes.c
create mode 100644 tests/tcg/openrisc/test_lf_rem.c
create mode 100644 tests/tcg/openrisc/test_lf_sub.c
create mode 100644 tests/tcg/openrisc/test_logic.c
create mode 100644 tests/tcg/openrisc/test_lx.c
create mode 100644 tests/tcg/openrisc/test_movhi.c
create mode 100644 tests/tcg/openrisc/test_mul.c
create mode 100644 tests/tcg/openrisc/test_sfeq.c
create mode 100644 tests/tcg/openrisc/test_sfeqi.c
create mode 100644 tests/tcg/openrisc/test_sfges.c
create mode 100644 tests/tcg/openrisc/test_sfgesi.c
create mode 100644 tests/tcg/openrisc/test_sfgeu.c
create mode 100644 tests/tcg/openrisc/test_sfgeui.c
create mode 100644 tests/tcg/openrisc/test_sfgts.c
create mode 100644 tests/tcg/openrisc/test_sfgtsi.c
create mode 100644 tests/tcg/openrisc/test_sfgtu.c
create mode 100644 tests/tcg/openrisc/test_sfgtui.c
create mode 100644 tests/tcg/openrisc/test_sfles.c
create mode 100644 tests/tcg/openrisc/test_sflesi.c
create mode 100644 tests/tcg/openrisc/test_sfleu.c
create mode 100644 tests/tcg/openrisc/test_sfleui.c
create mode 100644 tests/tcg/openrisc/test_sflts.c
create mode 100644 tests/tcg/openrisc/test_sfltsi.c
create mode 100644 tests/tcg/openrisc/test_sfltu.c
create mode 100644 tests/tcg/openrisc/test_sfltui.c
create mode 100644 tests/tcg/openrisc/test_sfne.c
create mode 100644 tests/tcg/openrisc/test_sfnei.c

diff --git a/tests/tcg/openrisc/Makefile b/tests/tcg/openrisc/Makefile
new file mode 100644
index 0000000..e1b68c0
--- /dev/null
+++ b/tests/tcg/openrisc/Makefile
@@ -0,0 +1,73 @@
+-include ../../config-host.mak
+
+CROSS = or32-linux-
+
+SIM = qemu-or32
+
+CC = $(CROSS)gcc
+
+TESTCASES = test_add.tst
+TESTCASES += test_addc.tst
+TESTCASES += test_addi.tst
+TESTCASES += test_addic.tst
+TESTCASES += test_and_or.tst
+TESTCASES += test_bf.tst
+TESTCASES += test_bnf.tst
+TESTCASES += test_div.tst
+TESTCASES += test_extx.tst
+TESTCASES += test_fx.tst
+TESTCASES += test_jal.tst
+TESTCASES += test_j.tst
+TESTCASES += test_lf_add.tst
+TESTCASES += test_lf_div.tst
+TESTCASES += test_lf_eqd.tst
+TESTCASES += test_lf_eqs.tst
+TESTCASES += test_lf_ged.tst
+TESTCASES += test_lf_ges.tst
+TESTCASES += test_lf_gtd.tst
+TESTCASES += test_lf_gts.tst
+TESTCASES += test_lf_led.tst
+TESTCASES += test_lf_les.tst
+TESTCASES += test_lf_ltd.tst
+TESTCASES += test_lf_lts.tst
+TESTCASES += test_lf_mul.tst
+TESTCASES += test_lf_ned.tst
+TESTCASES += test_lf_nes.tst
+TESTCASES += test_lf_rem.tst
+TESTCASES += test_lf_sub.tst
+TESTCASES += test_logic.tst
+TESTCASES += test_lx.tst
+TESTCASES += test_movhi.tst
+TESTCASES += test_mul.tst
+TESTCASES += test_sfeq.tst
+TESTCASES += test_sfeqi.tst
+TESTCASES += test_sfges.tst
+TESTCASES += test_sfgesi.tst
+TESTCASES += test_sfgeu.tst
+TESTCASES += test_sfgeui.tst
+TESTCASES += test_sfgts.tst
+TESTCASES += test_sfgtsi.tst
+TESTCASES += test_sfgtu.tst
+TESTCASES += test_sfgtui.tst
+TESTCASES += test_sfles.tst
+TESTCASES += test_sflesi.tst
+TESTCASES += test_sfleu.tst
+TESTCASES += test_sfleui.tst
+TESTCASES += test_sflts.tst
+TESTCASES += test_sfltsi.tst
+TESTCASES += test_sfltu.tst
+TESTCASES += test_sfltui.tst
+TESTCASES += test_sfne.tst
+TESTCASES += test_sfnei.tst
+
+all: $(TESTCASES)
+
+%.tst: %.c
+ $(CC) -static $< -o $@
+
+
+check: $(TESTCASES)
+ @for case in $(TESTCASES); do $(SIM) $$case;echo $$case pass!; sleep 0.2; done
+
+clean:
+ $(RM) -fr $(TESTCASES)
diff --git a/tests/tcg/openrisc/test_add.c b/tests/tcg/openrisc/test_add.c
new file mode 100644
index 0000000..8845257
--- /dev/null
+++ b/tests/tcg/openrisc/test_add.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0x100;
+ b = 0x100;
+ result = 0x200;
+
+ __asm
+ ("l.add %0, %0, %1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("add error\n");
+ }
+
+ a = 0xffff;
+ b = 0x1;
+ result = 0x10000;
+ __asm
+ ("l.add %0, %0, %1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("add error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_addc.c b/tests/tcg/openrisc/test_addc.c
new file mode 100644
index 0000000..904ce3a
--- /dev/null
+++ b/tests/tcg/openrisc/test_addc.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x01;
+ c = 0xffffffff;
+ result = 0;
+
+ __asm
+ ("l.addc %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("addc error\n");
+ }
+
+ b = 0x01;
+ c = 0xffffffff;
+ result = 0x80000001;
+ __asm
+ ("l.addc %0, %1, %2\n\t"
+ "l.movhi %2, 0x7fff\n\t"
+ "l.ori %2, %2, 0xffff\n\t"
+ "l.addc %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("addc error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_addi.c b/tests/tcg/openrisc/test_addi.c
new file mode 100644
index 0000000..4ee71f1
--- /dev/null
+++ b/tests/tcg/openrisc/test_addi.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ b = 0x01;
+ result = 0x00;
+ __asm
+ ("l.addi %0, %1, 0xffff\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("addi error\n\t");
+ }
+
+ b = 0x010000;
+ result = 0xffff;
+ __asm
+ ("l.addi %0, %1, 0xffff\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("addi error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_addic.c b/tests/tcg/openrisc/test_addic.c
new file mode 100644
index 0000000..5dd629b
--- /dev/null
+++ b/tests/tcg/openrisc/test_addic.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 1;
+ result = 0;
+
+ __asm
+ ("l.addic %0, %0, 0xffff\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("addic error\n");
+ }
+
+ a = 0x1;
+ result = 0x201;
+ __asm
+ ("l.addic %0, %0, 0xffff\n\t"
+ "l.ori %0, r0, 0x100\n\t"
+ "l.addic %0, %0, 0x100\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("addic error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_and_or.c b/tests/tcg/openrisc/test_and_or.c
new file mode 100644
index 0000000..e6f8828
--- /dev/null
+++ b/tests/tcg/openrisc/test_and_or.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x2;
+ c = 0x1;
+ result = 0;
+
+ __asm
+ ("l.and %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("and error\n");
+ }
+
+ result = 0x2;
+ __asm
+ ("l.andi %0, %1, 0x3\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("andi error %x\n", a);
+ }
+
+ result = 0x3;
+ __asm
+ ("l.or %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("or error\n");
+ }
+
+ result = 0x3;
+ __asm
+ ("l.xor %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("xor error\n");
+ }
+
+ __asm
+ ("l.xori %0, %1, 0x1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("xori error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_bf.c b/tests/tcg/openrisc/test_bf.c
new file mode 100644
index 0000000..53ea96d
--- /dev/null
+++ b/tests/tcg/openrisc/test_bf.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 10;
+ c = 11;
+ result = 0x2;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %1, %1, 0x01\n\t"
+ "l.addi %0, %0, 0x01\n\t"
+ "l.sfeq %1, %2\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sfeq error\n");
+ }
+
+ a = 0x00;
+ b = 0x11;
+ c = 0x11;
+ result = 0x01;
+ __asm
+ ("1:\n\t"
+ "l.addi %1, %1, 0x01\n\t"
+ "l.addi %0, %0, 0x01\n\t"
+ "l.sfeq %1, %2\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sfeq error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_bnf.c b/tests/tcg/openrisc/test_bnf.c
new file mode 100644
index 0000000..bca94d9
--- /dev/null
+++ b/tests/tcg/openrisc/test_bnf.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ b = 0;
+ result = 0x3;
+
+ __asm
+ ("l.sfeqi %1, 0x0\n\t"
+ "l.bnf 1f\n\t"
+ "l.nop\n\t"
+ "\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "\n\t"
+ "1:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("l.bnf error\n");
+ }
+
+ a = 0;
+ b = 0;
+ result = 1;
+ __asm
+ ("l.sfeqi %1, 0x1\n\t"
+ "l.bnf 1f\n\t"
+ "l.nop\n\t"
+ "\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "\n\t"
+ "1:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("l.bnf error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_div.c b/tests/tcg/openrisc/test_div.c
new file mode 100644
index 0000000..27d71a5
--- /dev/null
+++ b/tests/tcg/openrisc/test_div.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x120;
+ c = 0x4;
+ result = 0x48;
+
+ __asm
+ ("l.div %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("div error\n");
+ }
+
+ result = 0x4;
+ __asm
+ ("l.divu %0, %1, %0\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("divu error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_extx.c b/tests/tcg/openrisc/test_extx.c
new file mode 100644
index 0000000..dbda5bf
--- /dev/null
+++ b/tests/tcg/openrisc/test_extx.c
@@ -0,0 +1,71 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ b = 0x83;
+ result = 0xffffff83;
+ __asm
+ ("l.extbs %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("extbs error\n");
+ }
+
+ result = 0x83;
+ __asm
+ ("l.extbz %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("extbz error\n");
+ }
+
+ b = 0x8083;
+ result = 0xffff8083;
+ __asm
+ ("l.exths %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("exths error\n");
+ }
+
+ result = 0x8083;
+ __asm
+ ("l.exthz %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("exthz error\n");
+ }
+
+ b = 0x80830080;
+ result = 0x80830080;
+ __asm
+ ("l.extws %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("extws error\n");
+ }
+
+ __asm
+ ("l.extwz %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("extwz error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_fx.c b/tests/tcg/openrisc/test_fx.c
new file mode 100644
index 0000000..238817e
--- /dev/null
+++ b/tests/tcg/openrisc/test_fx.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ b = 0x123;
+ result = 1;
+ __asm
+ ("l.ff1 %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("ff1 error\n");
+ }
+
+ b = 0x0;
+ result = 0;
+ __asm
+ ("l.ff1 %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("ff1 error\n");
+ }
+
+ b = 0x123;
+ result = 9;
+ __asm
+ ("l.fl1 %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("fl1 error\n");
+ }
+
+ b = 0x0;
+ result = 0;
+ __asm
+ ("l.fl1 %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("fl1 error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_j.c b/tests/tcg/openrisc/test_j.c
new file mode 100644
index 0000000..183d051
--- /dev/null
+++ b/tests/tcg/openrisc/test_j.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 0;
+ result = 2;
+
+ __asm
+ ("l.addi %0, %0, 1\n\t"
+ "l.j j\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.nop\n\t"
+ "j:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("j error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_jal.c b/tests/tcg/openrisc/test_jal.c
new file mode 100644
index 0000000..4c9af9a
--- /dev/null
+++ b/tests/tcg/openrisc/test_jal.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 0;
+ result = 2;
+
+ __asm
+ ("l.addi %0, %0, 1\n\t"
+ "l.jal jal\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.nop\n\t"
+ "jal:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("jal error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_add.c b/tests/tcg/openrisc/test_lf_add.c
new file mode 100644
index 0000000..ca9524f
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_add.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0x1001234;
+ b = 0x1101234;
+ result = 0x2102468;
+
+ __asm
+ ("lf.add.d %0, %0, %1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("lf.add.d error, %x\n", a);
+ }
+
+ result = 0x320369c;
+ __asm
+ ("lf.add.s %0, %0, %1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("lf.add.s error, %x\n", a);
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_div.c b/tests/tcg/openrisc/test_lf_div.c
new file mode 100644
index 0000000..4949ba5
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_div.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x80000000;
+ c = 0x40;
+ result = 0x2000000;
+ __asm
+ ("lf.div.d %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.div.d error\n");
+ }
+
+ b = 0x8000;
+ c = 0x40;
+ result = 0x200;
+ __asm
+ ("lf.div.s %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.div.s error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_eqd.c b/tests/tcg/openrisc/test_lf_eqd.c
new file mode 100644
index 0000000..d4abeb0
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_eqd.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0x1;
+ b = 0x122;
+ c = 0x123;
+ result = 0x3;
+
+ __asm
+ ("lfeqd:\n\t"
+ "l.addi%0, %0, 0x1\n\t"
+ "lf.sfeq.d %1, %2\n\t"
+ "l.bf lfeqd\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfeq.d error\n");
+ }
+
+ b = 0x13;
+ c = 0x13;
+ result = 0x3;
+ __asm
+ ("lf.sfeq.d %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfeq.d error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_eqs.c b/tests/tcg/openrisc/test_lf_eqs.c
new file mode 100644
index 0000000..e786cf8
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_eqs.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0x1;
+ b = 0x122;
+ c = 0x123;
+ result = 0x3;
+ __asm
+ ("lfeqd:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfeq.s %1, %2\n\t"
+ "l.bf lfeqd\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfeq.s error\n");
+ }
+
+ b = 0x13;
+ c = 0x13;
+ result = 0x3;
+ __asm
+ ("lf.sfeq.s %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi r4, r4, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfeq.s error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_ged.c b/tests/tcg/openrisc/test_lf_ged.c
new file mode 100644
index 0000000..5ecb93a
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_ged.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0x1;
+ b = 0x122;
+ c = 0x123;
+ result = 0x2;
+ __asm
+ ("lfged:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfge.d %1, %2\n\t"
+ "l.bf lfged\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfge.d error\n");
+ }
+
+ b = 0x133;
+ c = 0x13;
+ result = 0x4;
+ __asm
+ ("lf.sfge.d %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfge.d error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_ges.c b/tests/tcg/openrisc/test_lf_ges.c
new file mode 100644
index 0000000..d60f9df
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_ges.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 0x122;
+ c = 0x123;
+ result = 0x1;
+ __asm
+ ("lfges:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfge.s %1, %2\n\t"
+ "l.bf lfges\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfge.s error\n");
+ }
+
+ b = 0x133;
+ c = 0x13;
+ result = 0x3;
+ __asm
+ ("l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfge.s %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfge.s error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_gtd.c b/tests/tcg/openrisc/test_lf_gtd.c
new file mode 100644
index 0000000..33ac149
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_gtd.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 0x122;
+ c = 0x123;
+ result = 0x1;
+ __asm
+ ("lfgtd:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfgt.d %1, %2\n\t"
+ "l.bf lfgtd\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfgt.d error\n");
+ }
+
+ b = 0x133;
+ c = 0x13;
+ result = 0x3;
+ __asm
+ ("l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfgt.d %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfgt.d error, %x\n", a);
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_gts.c b/tests/tcg/openrisc/test_lf_gts.c
new file mode 100644
index 0000000..d757761
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_gts.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 0x122;
+ c = 0x123;
+ result = 0x1;
+
+ __asm
+ ("lfgts:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfgt.s %1, %2\n\t"
+ "l.bf lfgts\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfgt.s error\n");
+ }
+
+ b = 0x133;
+ c = 0x13;
+ result = 0x1;
+
+ __asm
+ ("lf.sfgt.s %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfgt.s error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_led.c b/tests/tcg/openrisc/test_lf_led.c
new file mode 100644
index 0000000..c4fa193
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_led.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 0x1212;
+ c = 0x123;
+ result = 0x1;
+ __asm
+ ("lfled:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfle.d %1, %2\n\t"
+ "l.bf lfled\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfle.d error\n");
+ }
+
+ b = 0x13;
+ c = 0x113;
+ result = 0x2;
+ __asm
+ ("l.addi %0, %0, 0x1\n\t"
+ "lf.sfle.d %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfle.d error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_les.c b/tests/tcg/openrisc/test_lf_les.c
new file mode 100644
index 0000000..705e98f
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_les.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 0x1022;
+ c = 0x123;
+ result = 0x1;
+ __asm
+ ("lfles:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfle.s %1, %2\n\t"
+ "l.bf lfles\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfle.s error\n");
+ }
+
+ b = 0x1;
+ c = 0x13;
+ result = 0x3;
+ __asm
+ ("l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfle.s %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfle.s error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_ltd.c b/tests/tcg/openrisc/test_lf_ltd.c
new file mode 100644
index 0000000..d0d1e7d
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_ltd.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 0x122;
+ c = 0x23;
+ result = 0x1;
+
+ __asm
+ ("lfltd:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sflt.d %1, %2\n\t"
+ "l.bf lfltd\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sflt.d error\n");
+ }
+
+ a = 0;
+ b = 0x13;
+ c = 0x123;
+ result = 0x110;
+ __asm
+ ("1:\n\t"
+ "l.addi %1, %1, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sflt.d %1, %2\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a), "+r"(b)
+ : "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sflt.d error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_lts.c b/tests/tcg/openrisc/test_lf_lts.c
new file mode 100644
index 0000000..b487365
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_lts.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 0x122;
+ c = 0x23;
+ result = 0x1;
+
+ __asm
+ ("lfltd:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sflt.s %1, %2\n\t"
+ "l.bf lfltd\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sflt.s error\n");
+ }
+
+ a = 0;
+ b = 0x13;
+ c = 0x123;
+ result = 0x110;
+ __asm
+ ("1:\n\t"
+ "l.addi %1, %1, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sflt.s %1, %2\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sflt.s error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_mul.c b/tests/tcg/openrisc/test_lf_mul.c
new file mode 100644
index 0000000..1355c2b
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_mul.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x420;
+ c = 0x3000;
+ result = 0xc60000;
+
+ __asm
+ ("lf.mul.d %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.mul.d error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_ned.c b/tests/tcg/openrisc/test_lf_ned.c
new file mode 100644
index 0000000..cb86f36
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_ned.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 0x122;
+ c = 0x122;
+ result = 0x1;
+ __asm
+ ("lfned:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfne.d %1, %2\n\t"
+ "l.bf lfned\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfne.d error\n");
+ }
+
+ b = 0x13;
+ c = 0x133;
+ result = 0x3;
+
+ __asm
+ ("l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfne.d %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi r4, r4, 0x1\n\t"
+ "l.addi r4, r4, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfne.d error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_nes.c b/tests/tcg/openrisc/test_lf_nes.c
new file mode 100644
index 0000000..6b9f5ea
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_nes.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 0x122;
+ c = 0x122;
+ result = 0x1;
+
+ __asm
+ ("lfnes:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfne.s %1, %2\n\t"
+ "l.bf lfnes\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfne.s error");
+ }
+
+ b = 0x173;
+ c = 0x13;
+ result = 0x3;
+ __asm
+ ("l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfne.s %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfne.s error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_rem.c b/tests/tcg/openrisc/test_lf_rem.c
new file mode 100644
index 0000000..dbb2b83
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_rem.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x1234;
+ c = 0x1233;
+ result = 0x1;
+
+ __asm
+ ("lf.rem.d %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.rem.d error\n");
+ }
+
+ __asm
+ ("lf.rem.s %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.rem.s error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_sub.c b/tests/tcg/openrisc/test_lf_sub.c
new file mode 100644
index 0000000..4b1edb5
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_sub.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x999;
+ c = 0x654;
+ result = 0x345;
+
+ __asm
+ ("lf.sub.d %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sub.d error\n");
+ }
+
+ __asm
+ ("lf.sub.s %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sub.s error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_logic.c b/tests/tcg/openrisc/test_logic.c
new file mode 100644
index 0000000..a01461b
--- /dev/null
+++ b/tests/tcg/openrisc/test_logic.c
@@ -0,0 +1,100 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x9743;
+ c = 0x2;
+ result = 0x25d0c;
+
+ __asm
+ ("l.sll %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sll error\n");
+ }
+
+ b = 0x9743;
+ result = 0x25d0c;
+ __asm
+ ("l.slli %0, %1, 0x2\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("slli error\n");
+ }
+
+ b = 0x7654;
+ c = 0x03;
+ result = 0xeca;
+ __asm
+ ("l.srl %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+
+ b = 0x7654;
+ result = 0xeca;
+ __asm
+ ("l.srli %0, %1, 0x3\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("srli error\n");
+ }
+
+ b = 0x80000001;
+ c = 0x4;
+ result = 0x18000000;
+ __asm
+ ("l.ror %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("ror error\n");
+ }
+
+ b = 0x80000001;
+ result = 0x18000000;
+ __asm
+ ("l.rori %0, %1, 0x4\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("rori error\n");
+ }
+
+ b = 0x80000001;
+ c = 0x03;
+ result = 0xf0000000;
+ __asm
+ ("l.sra %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sra error\n");
+ }
+
+ b = 0x80000001;
+ result = 0xf0000000;
+
+ __asm
+ ("l.srai %0, %1, 0x3\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("srai error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lx.c b/tests/tcg/openrisc/test_lx.c
new file mode 100644
index 0000000..854deef
--- /dev/null
+++ b/tests/tcg/openrisc/test_lx.c
@@ -0,0 +1,78 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int p[50];
+ int result;
+
+ result = 0x23;
+ __asm
+ ("l.ori r8, r0, 0x123\n\t"
+ "l.sb 0x4 + %1, r8\n\t"
+ "\n\t"
+ "l.lbz %0, 0x4 + %1\n\t"
+ : "=r"(a), "+m"(*p)
+ );
+ if (a != result) {
+ printf("lbz error, %x\n", a);
+ }
+
+ result = 0x23;
+ __asm
+ ("l.lbs %0, 0x4 + %1\n\t"
+ : "=r"(a)
+ : "m"(*p)
+ );
+ if (a != result) {
+ printf("lbs error\n");
+ }
+
+ result = 0x1111;
+ __asm
+ ("l.ori r8, r0, 0x1111\n\t"
+ "l.sh 0x20 + %1, r8\n\t"
+ "\n\t"
+ "l.lhs %0, 0x20 + %1\n\t"
+ : "=r"(a), "=m"(*p)
+ );
+ if (a != result) {
+ printf("lhs error, %x\n", a);
+ }
+
+ result = 0x1111;
+ __asm
+ ("l.lhz %0, 0x20 + %1\n\t"
+ : "=r"(a)
+ : "m"(*p)
+ );
+ if (a != result) {
+ printf("lhz error\n");
+ }
+
+ result = 0x1111233;
+ __asm
+ ("l.ori r8, r0, 0x1233\n\t"
+ "l.movhi r1, 0x111\n\t"
+ "l.or r8, r8, r1\n\t"
+ "l.sw 0x123 + %1, r8\n\t"
+ "\n\t"
+ "l.lws %0, 0x123 + %1\n\t"
+ : "=r"(a), "+m"(*p)
+ );
+ if (a != result) {
+ printf("lws error, %x\n", a);
+ }
+
+ result = 0x1111233;
+ __asm
+ ("l.lwz %0, 0x123 + %1\n\t"
+ : "=r"(a)
+ : "m"(*p)
+ );
+ if (a != result) {
+ printf("lwz error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_movhi.c b/tests/tcg/openrisc/test_movhi.c
new file mode 100644
index 0000000..9548a7a
--- /dev/null
+++ b/tests/tcg/openrisc/test_movhi.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ result = 0x1222;
+
+ __asm
+ ("l.movhi r3, 0x1222\n\t"
+ "l.srli %0, r3, 16\n\t"
+ : "=r"(a)
+ );
+ if (a != result) {
+ printf("movhi error\n");
+ }
+
+ result = 0x1111;
+ __asm
+ ("l.movhi r8, 0x1111\n\t"
+ "l.srli %0, r8, 16\n\t"
+ : "=r"(a)
+ );
+ if (a != result) {
+ printf("movhi error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_mul.c b/tests/tcg/openrisc/test_mul.c
new file mode 100644
index 0000000..d992d98
--- /dev/null
+++ b/tests/tcg/openrisc/test_mul.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x4;
+ c = 0x1;
+ result = 0x4;
+
+ __asm
+ ("l.mul %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("mul error\n");
+ }
+
+ b = 0x1;
+ c = 0x0;
+ result = 0x0;
+
+ __asm
+ ("l.mul %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("mul error\n");
+ }
+
+ b = 0x1;
+ c = 0xff;
+ result = 0xff;
+ __asm
+ ("l.mul %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("mul error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfeq.c b/tests/tcg/openrisc/test_sfeq.c
new file mode 100644
index 0000000..e89e5df
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfeq.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0x1;
+ b = 0x80;
+ result = 0x2;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.sfeq %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfeq error\n");
+ }
+
+ a = 0x7f;
+ b = 0x80;
+ result = 0x81;
+
+ __asm
+ ("2:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.sfeq %0, %1\n\t"
+ "l.bf 2b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ )
+ if (a != result) {
+ printf("sfeq error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfeqi.c b/tests/tcg/openrisc/test_sfeqi.c
new file mode 100644
index 0000000..6c9690d
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfeqi.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 1;
+ result = 2;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.sfeqi %0, 0x80\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfeqi error\n");
+ }
+
+ a = 0x7f;
+ result = 0x81;
+
+ __asm
+ ("2:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.sfeqi %0, 0x80\n\t"
+ "l.bf 2b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfeqi error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfges.c b/tests/tcg/openrisc/test_sfges.c
new file mode 100644
index 0000000..3505002
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfges.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 1;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfges %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfges error\n");
+ }
+
+ a = 0xff;
+ b = 3;
+ c = 0x1;
+ result = 2;
+
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %2\n\t"
+ "l.sfges %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sfges error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgesi.c b/tests/tcg/openrisc/test_sfgesi.c
new file mode 100644
index 0000000..5c2bc8a
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfgesi.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ result = 1;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfgesi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfgesi error\n");
+ }
+
+ a = 0xff;
+ b = 1;
+ result = 2;
+
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %1\n\t"
+ "l.sfgesi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfgesi error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgeu.c b/tests/tcg/openrisc/test_sfgeu.c
new file mode 100644
index 0000000..c084c5f
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfgeu.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 1;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfgeu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfgeu error\n");
+ }
+
+ a = 0xff;
+ b = 3;
+ c = 1;
+ result = 2;
+
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %2\n\t"
+ "l.sfgeu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sfgeu error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgeui.c b/tests/tcg/openrisc/test_sfgeui.c
new file mode 100644
index 0000000..ac4bd7f
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfgeui.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ result = 1;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfgeui %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfgeui error\n");
+ }
+
+ a = 0xff;
+ b = 1;
+ result = 2;
+
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %1\n\t"
+ "l.sfgeui %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfgeui error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgts.c b/tests/tcg/openrisc/test_sfgts.c
new file mode 100644
index 0000000..d2aeb0a
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfgts.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 1;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfgts %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfgts error\n");
+ }
+
+
+ a = 0xff;
+ b = 3;
+ c = 1;
+ result = 3;
+
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %2\n\t"
+ "l.sfgts %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sfgts error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgtsi.c b/tests/tcg/openrisc/test_sfgtsi.c
new file mode 100644
index 0000000..4ad398c
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfgtsi.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ result = 1;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfgtsi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfgtsi error\n");
+ }
+
+ a = 0xff;
+ b = 1;
+ result = 3;
+
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %1\n\t"
+ "l.sfgtsi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfgtsi error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgtu.c b/tests/tcg/openrisc/test_sfgtu.c
new file mode 100644
index 0000000..4b65127
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfgtu.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 1;
+
+ __asm
+ ("1:\n\t"
+ "l.addi%0, %0, 1\n\t"
+ "l.sfgtu%0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfgtu error\n");
+ }
+
+ a = 0xff;
+ b = 3;
+ c = 1;
+ result = 3;
+
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %2\n\t"
+ "l.sfgtu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sfgtu error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgtui.c b/tests/tcg/openrisc/test_sfgtui.c
new file mode 100644
index 0000000..755907a
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfgtui.c
@@ -0,0 +1,42 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ result = 1;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfgtui %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfgtui error\n");
+ }
+
+
+ a = 0xff;
+ b = 1;
+ result = 3;
+
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %1\n\t"
+ "l.sfgtui %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfgtui error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfles.c b/tests/tcg/openrisc/test_sfles.c
new file mode 100644
index 0000000..3215936
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfles.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 4;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sfles %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfles error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sflesi.c b/tests/tcg/openrisc/test_sflesi.c
new file mode 100644
index 0000000..5ae6585
--- /dev/null
+++ b/tests/tcg/openrisc/test_sflesi.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 0;
+ result = 4;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sflesi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sflesi error\n");
+ }
+
+ a = 0;
+ result = 4;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sflesi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sflesi error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfleu.c b/tests/tcg/openrisc/test_sfleu.c
new file mode 100644
index 0000000..59fdaf7
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfleu.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 4;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sfleu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfleu error\n");
+ }
+
+ a = 0;
+ b = 3;
+ result = 4;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfleu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfleu error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfleui.c b/tests/tcg/openrisc/test_sfleui.c
new file mode 100644
index 0000000..df1ba07
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfleui.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 0;
+ result = 4;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sfleui %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfleui error\n");
+ }
+
+ a = 0;
+ result = 4;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfleui %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfleui error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sflts.c b/tests/tcg/openrisc/test_sflts.c
new file mode 100644
index 0000000..e4134ea
--- /dev/null
+++ b/tests/tcg/openrisc/test_sflts.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 4;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sflts %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sflts error\n");
+ }
+
+ a = 0;
+ b = 3;
+ result = 3;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sflts %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sflts error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfltsi.c b/tests/tcg/openrisc/test_sfltsi.c
new file mode 100644
index 0000000..68c2d79
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfltsi.c
@@ -0,0 +1,38 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 0;
+ result = 4;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sfltsi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfltsi error\n");
+ }
+
+ a = 0;
+ result = 3;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfltsi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfltsi error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfltu.c b/tests/tcg/openrisc/test_sfltu.c
new file mode 100644
index 0000000..2b50c9c
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfltu.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 4;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sfltu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfltu error\n");
+ }
+
+ a = 0;
+ b = 3;
+ result = 3;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfltu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfltu error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfltui.c b/tests/tcg/openrisc/test_sfltui.c
new file mode 100644
index 0000000..8660d8f
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfltui.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 0;
+ result = 4;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sfltsi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfltui error\n");
+ }
+
+ a = 0;
+ result = 3;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfltsi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfltui error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfne.c b/tests/tcg/openrisc/test_sfne.c
new file mode 100644
index 0000000..064650c
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfne.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 3;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 3\n\t"
+ "l.sfne %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfne error\n");
+ }
+
+ a = 0;
+ b = 3;
+ result = 3;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfne %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfne error\n");
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfnei.c b/tests/tcg/openrisc/test_sfnei.c
new file mode 100644
index 0000000..cbc48d4
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfnei.c
@@ -0,0 +1,38 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 0;
+ result = 3;
+
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 3\n\t"
+ "l.sfnei %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfnei error\n");
+ }
+
+ a = 0;
+ result = 3;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfnei %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfnei error\n");
+ }
+
+ return 0;
+}
--
1.7.9.5
Jia Liu
2012-05-27 05:32:57 UTC
Permalink
add linux syscall, signal and termbits from linux-openrisc codes.

Signed-off-by: Jia Liu <***@gmail.com>
---
linux-user/openrisc/syscall.h | 24 ++
linux-user/openrisc/syscall_nr.h | 506 +++++++++++++++++++++++++++++++++++
linux-user/openrisc/target_signal.h | 26 ++
linux-user/openrisc/termbits.h | 294 ++++++++++++++++++++
4 files changed, 850 insertions(+)
create mode 100644 linux-user/openrisc/syscall.h
create mode 100644 linux-user/openrisc/syscall_nr.h
create mode 100644 linux-user/openrisc/target_signal.h
create mode 100644 linux-user/openrisc/termbits.h

diff --git a/linux-user/openrisc/syscall.h b/linux-user/openrisc/syscall.h
new file mode 100644
index 0000000..bdbb577
--- /dev/null
+++ b/linux-user/openrisc/syscall.h
@@ -0,0 +1,24 @@
+struct target_pt_regs {
+ union {
+ struct {
+ /* Named registers */
+ uint32_t sr; /* Stored in place of r0 */
+ target_ulong sp; /* r1 */
+ };
+ struct {
+ /* Old style */
+ target_ulong offset[2];
+ target_ulong gprs[30];
+ };
+ struct {
+ /* New style */
+ target_ulong gpr[32];
+ };
+ };
+ target_ulong pc;
+ target_ulong orig_gpr11; /* For restarting system calls */
+ uint32_t syscallno; /* Syscall number (used by strace) */
+ target_ulong dummy; /* Cheap alignment fix */
+};
+
+#define UNAME_MACHINE "openrisc"
diff --git a/linux-user/openrisc/syscall_nr.h b/linux-user/openrisc/syscall_nr.h
new file mode 100644
index 0000000..f4ac91e
--- /dev/null
+++ b/linux-user/openrisc/syscall_nr.h
@@ -0,0 +1,506 @@
+#define TARGET_NR_io_setup 0
+#define TARGET_NR_io_destroy 1
+#define TARGET_NR_io_submit 2
+#define TARGET_NR_io_cancel 3
+#define TARGET_NR_io_getevents 4
+
+/* fs/xattr.c */
+#define TARGET_NR_setxattr 5
+#define TARGET_NR_lsetxattr 6
+#define TARGET_NR_fsetxattr 7
+#define TARGET_NR_getxattr 8
+#define TARGET_NR_lgetxattr 9
+#define TARGET_NR_fgetxattr 10
+#define TARGET_NR_listxattr 11
+#define TARGET_NR_llistxattr 12
+#define TARGET_NR_flistxattr 13
+#define TARGET_NR_removexattr 14
+#define TARGET_NR_lremovexattr 15
+#define TARGET_NR_fremovexattr 16
+
+/* fs/dcache.c */
+#define TARGET_NR_getcwd 17
+
+/* fs/cookies.c */
+#define TARGET_NR_lookup_dcookie 18
+
+/* fs/eventfd.c */
+#define TARGET_NR_eventfd2 19
+
+/* fs/eventpoll.c */
+#define TARGET_NR_epoll_create1 20
+#define TARGET_NR_epoll_ctl 21
+#define TARGET_NR_epoll_pwait 22
+
+/* fs/fcntl.c */
+#define TARGET_NR_dup 23
+#define TARGET_NR_dup3 24
+#define TARGET_NR_3264_fcntl 25
+
+/* fs/inotify_user.c */
+#define TARGET_NR_inotify_init1 26
+#define TARGET_NR_inotify_add_watch 27
+#define TARGET_NR_inotify_rm_watch 28
+
+/* fs/ioctl.c */
+#define TARGET_NR_ioctl 29
+
+/* fs/ioprio.c */
+#define TARGET_NR_ioprio_set 30
+#define TARGET_NR_ioprio_get 31
+
+/* fs/locks.c */
+#define TARGET_NR_flock 32
+
+/* fs/namei.c */
+#define TARGET_NR_mknodat 33
+#define TARGET_NR_mkdirat 34
+#define TARGET_NR_unlinkat 35
+#define TARGET_NR_symlinkat 36
+#define TARGET_NR_linkat 37
+#define TARGET_NR_renameat 38
+
+/* fs/namespace.c */
+#define TARGET_NR_umount2 39
+#define TARGET_NR_mount 40
+#define TARGET_NR_pivot_root 41
+
+/* fs/nfsctl.c */
+#define TARGET_NR_nfsservctl 42
+
+/* fs/open.c */
+#define TARGET_NR_3264_statfs 43
+#define TARGET_NR_3264_fstatfs 44
+#define TARGET_NR_3264_truncate 45
+#define TARGET_NR_3264_ftruncate 46
+
+#define TARGET_NR_fallocate 47
+#define TARGET_NR_faccessat 48
+#define TARGET_NR_chdir 49
+#define TARGET_NR_fchdir 50
+#define TARGET_NR_chroot 51
+#define TARGET_NR_fchmod 52
+#define TARGET_NR_fchmodat 53
+#define TARGET_NR_fchownat 54
+#define TARGET_NR_fchown 55
+#define TARGET_NR_openat 56
+#define TARGET_NR_close 57
+#define TARGET_NR_vhangup 58
+
+/* fs/pipe.c */
+#define TARGET_NR_pipe2 59
+
+/* fs/quota.c */
+#define TARGET_NR_quotactl 60
+
+/* fs/readdir.c */
+#define TARGET_NR_getdents64 61
+
+/* fs/read_write.c */
+#define TARGET_NR_3264_lseek 62
+#define TARGET_NR_read 63
+#define TARGET_NR_write 64
+#define TARGET_NR_readv 65
+#define TARGET_NR_writev 66
+#define TARGET_NR_pread64 67
+#define TARGET_NR_pwrite64 68
+#define TARGET_NR_preadv 69
+#define TARGET_NR_pwritev 70
+
+/* fs/sendfile.c */
+#define TARGET_NR_3264_sendfile 71
+
+/* fs/select.c */
+#define TARGET_NR_pselect6 72
+#define TARGET_NR_ppoll 73
+
+/* fs/signalfd.c */
+#define TARGET_NR_signalfd4 74
+
+/* fs/splice.c */
+#define TARGET_NR_vmsplice 75
+#define TARGET_NR_splice 76
+#define TARGET_NR_tee 77
+
+/* fs/stat.c */
+#define TARGET_NR_readlinkat 78
+#define TARGET_NR_3264_fstatat 79
+#define TARGET_NR_3264_fstat 80
+
+/* fs/sync.c */
+#define TARGET_NR_sync 81
+#define TARGET_NR_fsync 82
+#define TARGET_NR_fdatasync 83
+
+#ifdef __ARCH_WANT_SYNC_FILE_RANGE2
+#define TARGET_NR_sync_file_range2 84
+#else
+#define TARGET_NR_sync_file_range 84
+#endif
+
+/* fs/timerfd.c */
+#define TARGET_NR_timerfd_create 85
+#define TARGET_NR_timerfd_settime 86
+#define TARGET_NR_timerfd_gettime 87
+
+/* fs/utimes.c */
+#define TARGET_NR_utimensat 88
+
+/* kernel/acct.c */
+#define TARGET_NR_acct 89
+
+/* kernel/capability.c */
+#define TARGET_NR_capget 90
+#define TARGET_NR_capset 91
+
+/* kernel/exec_domain.c */
+#define TARGET_NR_personality 92
+
+/* kernel/exit.c */
+#define TARGET_NR_exit 93
+#define TARGET_NR_exit_group 94
+#define TARGET_NR_waitid 95
+
+/* kernel/fork.c */
+#define TARGET_NR_set_tid_address 96
+#define TARGET_NR_unshare 97
+
+/* kernel/futex.c */
+#define TARGET_NR_futex 98
+#define TARGET_NR_set_robust_list 99
+#define TARGET_NR_get_robust_list 100
+
+/* kernel/hrtimer.c */
+#define TARGET_NR_nanosleep 101
+
+/* kernel/itimer.c */
+#define TARGET_NR_getitimer 102
+#define TARGET_NR_setitimer 103
+
+/* kernel/kexec.c */
+#define TARGET_NR_kexec_load 104
+
+/* kernel/module.c */
+#define TARGET_NR_init_module 105
+#define TARGET_NR_delete_module 106
+
+/* kernel/posix-timers.c */
+#define TARGET_NR_timer_create 107
+#define TARGET_NR_timer_gettime 108
+#define TARGET_NR_timer_getoverrun 109
+#define TARGET_NR_timer_settime 110
+#define TARGET_NR_timer_delete 111
+#define TARGET_NR_clock_settime 112
+#define TARGET_NR_clock_gettime 113
+#define TARGET_NR_clock_getres 114
+#define TARGET_NR_clock_nanosleep 115
+
+/* kernel/printk.c */
+#define TARGET_NR_syslog 116
+
+/* kernel/ptrace.c */
+#define TARGET_NR_ptrace 117
+
+/* kernel/sched.c */
+#define TARGET_NR_sched_setparam 118
+#define TARGET_NR_sched_setscheduler 119
+#define TARGET_NR_sched_getscheduler 120
+#define TARGET_NR_sched_getparam 121
+#define TARGET_NR_sched_setaffinity 122
+#define TARGET_NR_sched_getaffinity 123
+#define TARGET_NR_sched_yield 124
+#define TARGET_NR_sched_get_priority_max 125
+#define TARGET_NR_sched_get_priority_min 126
+#define TARGET_NR_sched_rr_get_interval 127
+
+/* kernel/signal.c */
+#define TARGET_NR_restart_syscall 128
+#define TARGET_NR_kill 129
+#define TARGET_NR_tkill 130
+#define TARGET_NR_tgkill 131
+#define TARGET_NR_sigaltstack 132
+#define TARGET_NR_rt_sigsuspend 133
+#define TARGET_NR_rt_sigaction 134
+#define TARGET_NR_rt_sigprocmask 135
+#define TARGET_NR_rt_sigpending 136
+#define TARGET_NR_rt_sigtimedwait 137
+#define TARGET_NR_rt_sigqueueinfo 138
+#define TARGET_NR_rt_sigreturn 139
+
+/* kernel/sys.c */
+#define TARGET_NR_setpriority 140
+#define TARGET_NR_getpriority 141
+#define TARGET_NR_reboot 142
+#define TARGET_NR_setregid 143
+#define TARGET_NR_setgid 144
+#define TARGET_NR_setreuid 145
+#define TARGET_NR_setuid 146
+#define TARGET_NR_setresuid 147
+#define TARGET_NR_getresuid 148
+#define TARGET_NR_setresgid 149
+#define TARGET_NR_getresgid 150
+#define TARGET_NR_setfsuid 151
+#define TARGET_NR_setfsgid 152
+#define TARGET_NR_times 153
+#define TARGET_NR_setpgid 154
+#define TARGET_NR_getpgid 155
+#define TARGET_NR_getsid 156
+#define TARGET_NR_setsid 157
+#define TARGET_NR_getgroups 158
+#define TARGET_NR_setgroups 159
+#define TARGET_NR_uname 160
+#define TARGET_NR_sethostname 161
+#define TARGET_NR_setdomainname 162
+#define TARGET_NR_getrlimit 163
+#define TARGET_NR_setrlimit 164
+#define TARGET_NR_getrusage 165
+#define TARGET_NR_umask 166
+#define TARGET_NR_prctl 167
+#define TARGET_NR_getcpu 168
+
+/* kernel/time.c */
+#define TARGET_NR_gettimeofday 169
+#define TARGET_NR_settimeofday 170
+#define TARGET_NR_adjtimex 171
+
+/* kernel/timer.c */
+#define TARGET_NR_getpid 172
+#define TARGET_NR_getppid 173
+#define TARGET_NR_getuid 174
+#define TARGET_NR_geteuid 175
+#define TARGET_NR_getgid 176
+#define TARGET_NR_getegid 177
+#define TARGET_NR_gettid 178
+#define TARGET_NR_sysinfo 179
+
+/* ipc/mqueue.c */
+#define TARGET_NR_mq_open 180
+#define TARGET_NR_mq_unlink 181
+#define TARGET_NR_mq_timedsend 182
+#define TARGET_NR_mq_timedreceive 183
+#define TARGET_NR_mq_notify 184
+#define TARGET_NR_mq_getsetattr 185
+
+/* ipc/msg.c */
+#define TARGET_NR_msgget 186
+#define TARGET_NR_msgctl 187
+#define TARGET_NR_msgrcv 188
+#define TARGET_NR_msgsnd 189
+
+/* ipc/sem.c */
+#define TARGET_NR_semget 190
+#define TARGET_NR_semctl 191
+#define TARGET_NR_semtimedop 192
+#define TARGET_NR_semop 193
+
+/* ipc/shm.c */
+#define TARGET_NR_shmget 194
+#define TARGET_NR_shmctl 195
+#define TARGET_NR_shmat 196
+#define TARGET_NR_shmdt 197
+
+/* net/socket.c */
+#define TARGET_NR_socket 198
+#define TARGET_NR_socketpair 199
+#define TARGET_NR_bind 200
+#define TARGET_NR_listen 201
+#define TARGET_NR_accept 202
+#define TARGET_NR_connect 203
+#define TARGET_NR_getsockname 204
+#define TARGET_NR_getpeername 205
+#define TARGET_NR_sendto 206
+#define TARGET_NR_recvfrom 207
+#define TARGET_NR_setsockopt 208
+#define TARGET_NR_getsockopt 209
+#define TARGET_NR_shutdown 210
+#define TARGET_NR_sendmsg 211
+#define TARGET_NR_recvmsg 212
+
+/* mm/filemap.c */
+#define TARGET_NR_readahead 213
+
+/* mm/nommu.c, also with MMU */
+#define TARGET_NR_brk 214
+#define TARGET_NR_munmap 215
+#define TARGET_NR_mremap 216
+
+/* security/keys/keyctl.c */
+#define TARGET_NR_add_key 217
+#define TARGET_NR_request_key 218
+#define TARGET_NR_keyctl 219
+
+/* arch/example/kernel/sys_example.c */
+#define TARGET_NR_clone 220
+#define TARGET_NR_execve 221
+
+#define TARGET_NR_3264_mmap 222
+/* mm/fadvise.c */
+#define TARGET_NR_3264_fadvise64 223
+
+/* mm/, CONFIG_MMU only */
+#ifndef __ARCH_NOMMU
+#define TARGET_NR_swapon 224
+#define TARGET_NR_swapoff 225
+#define TARGET_NR_mprotect 226
+#define TARGET_NR_msync 227
+#define TARGET_NR_mlock 228
+#define TARGET_NR_munlock 229
+#define TARGET_NR_mlockall 230
+#define TARGET_NR_munlockall 231
+#define TARGET_NR_mincore 232
+#define TARGET_NR_madvise 233
+#define TARGET_NR_remap_file_pages 234
+#define TARGET_NR_mbind 235
+#define TARGET_NR_get_mempolicy 236
+#define TARGET_NR_set_mempolicy 237
+#define TARGET_NR_migrate_pages 238
+#define TARGET_NR_move_pages 239
+#endif
+
+#define TARGET_NR_rt_tgsigqueueinfo 240
+#define TARGET_NR_perf_event_open 241
+#define TARGET_NR_accept4 242
+#define TARGET_NR_recvmmsg 243
+
+/*
+ * Architectures may provide up to 16 syscalls of their own
+ * starting with this value.
+ */
+#define TARGET_NR_arch_specific_syscall 244
+
+#define TARGET_NR_wait4 260
+#define TARGET_NR_prlimit64 261
+#define TARGET_NR_fanotify_init 262
+#define TARGET_NR_fanotify_mark 263
+#define TARGET_NR_name_to_handle_at 264
+#define TARGET_NR_open_by_handle_at 265
+#define TARGET_NR_clock_adjtime 266
+#define TARGET_NR_syncfs 267
+#define TARGET_NR_setns 268
+#define TARGET_NR_sendmmsg 269
+
+#undef TARGET_NR_syscalls
+#define TARGET_NR_syscalls 270
+
+/*
+ * All syscalls below here should go away really,
+ * these are provided for both review and as a porting
+ * help for the C library version.
+*
+ * Last chance: are any of these important enough to
+ * enable by default?
+ */
+#define TARGET_NR_open 1024
+#define TARGET_NR_link 1025
+#define TARGET_NR_unlink 1026
+#define TARGET_NR_mknod 1027
+#define TARGET_NR_chmod 1028
+#define TARGET_NR_chown 1029
+#define TARGET_NR_mkdir 1030
+#define TARGET_NR_rmdir 1031
+#define TARGET_NR_lchown 1032
+#define TARGET_NR_access 1033
+#define TARGET_NR_rename 1034
+#define TARGET_NR_readlink 1035
+#define TARGET_NR_symlink 1036
+#define TARGET_NR_utimes 1037
+#define TARGET_NR_3264_stat 1038
+#define TARGET_NR_3264_lstat 1039
+
+#undef TARGET_NR_syscalls
+#define TARGET_NR_syscalls (TARGET_NR_3264_lstat+1)
+
+#define TARGET_NR_pipe 1040
+#define TARGET_NR_dup2 1041
+#define TARGET_NR_epoll_create 1042
+#define TARGET_NR_inotify_init 1043
+#define TARGET_NR_eventfd 1044
+#define TARGET_NR_signalfd 1045
+
+#undef TARGET_NR_syscalls
+#define TARGET_NR_syscalls (TARGET_NR_signalfd+1)
+
+
+#define TARGET_NR_sendfile 1046
+#define TARGET_NR_ftruncate 1047
+#define TARGET_NR_truncate 1048
+#define TARGET_NR_stat 1049
+#define TARGET_NR_lstat 1050
+#define TARGET_NR_fstat 1051
+#define TARGET_NR_fcntl 1052
+#define TARGET_NR_fadvise64 1053
+#define __ARCH_WANT_SYS_FADVISE64
+#define TARGET_NR_newfstatat 1054
+#define __ARCH_WANT_SYS_NEWFSTATAT
+#define TARGET_NR_fstatfs 1055
+#define TARGET_NR_statfs 1056
+#define TARGET_NR_lseek 1057
+#define TARGET_NR_mmap 1058
+
+#undef TARGET_NR_syscalls
+#define TARGET_NR_syscalls (TARGET_NR_mmap+1)
+
+#define TARGET_NR_alarm 1059
+#define __ARCH_WANT_SYS_ALARM
+#define TARGET_NR_getpgrp 1060
+#define __ARCH_WANT_SYS_GETPGRP
+#define TARGET_NR_pause 1061
+#define __ARCH_WANT_SYS_PAUSE
+#define TARGET_NR_time 1062
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_COMPAT_SYS_TIME
+#define TARGET_NR_utime 1063
+#define __ARCH_WANT_SYS_UTIME
+
+#define TARGET_NR_creat 1064
+#define TARGET_NR_getdents 1065
+#define __ARCH_WANT_SYS_GETDENTS
+#define TARGET_NR_futimesat 1066
+#define TARGET_NR_select 1067
+#define __ARCH_WANT_SYS_SELECT
+#define TARGET_NR_poll 1068
+#define TARGET_NR_epoll_wait 1069
+#define TARGET_NR_ustat 1070
+#define TARGET_NR_vfork 1071
+#define TARGET_NR_oldwait4 1072
+#define TARGET_NR_recv 1073
+#define TARGET_NR_send 1074
+#define TARGET_NR_bdflush 1075
+#define TARGET_NR_umount 1076
+#define __ARCH_WANT_SYS_OLDUMOUNT
+#define TARGET_NR_uselib 1077
+#define TARGET_NR__sysctl 1078
+
+#define TARGET_NR_fork 1079
+
+#undef TARGET_NR_syscalls
+#define TARGET_NR_syscalls (TARGET_NR_fork+1)
+
+
+/*
+ * 32 bit systems traditionally used different
+ * syscalls for off_t and loff_t arguments, while
+ * 64 bit systems only need the off_t version.
+ * For new 32 bit platforms, there is no need to
+ * implement the old 32 bit off_t syscalls, so
+ * they take different names.
+ * Here we map the numbers so that both versions
+ * use the same syscall table layout.
+ */
+
+#define TARGET_NR_fcntl64 TARGET_NR_3264_fcntl
+#define TARGET_NR_statfs64 TARGET_NR_3264_statfs
+#define TARGET_NR_fstatfs64 TARGET_NR_3264_fstatfs
+#define TARGET_NR_truncate64 TARGET_NR_3264_truncate
+#define TARGET_NR_ftruncate64 TARGET_NR_3264_ftruncate
+#define TARGET_NR_llseek TARGET_NR_3264_lseek
+#define TARGET_NR_sendfile64 TARGET_NR_3264_sendfile
+#define TARGET_NR_fstatat64 TARGET_NR_3264_fstatat
+#define TARGET_NR_fstat64 TARGET_NR_3264_fstat
+#define TARGET_NR_mmap2 TARGET_NR_3264_mmap
+#define TARGET_NR_fadvise64_64 TARGET_NR_3264_fadvise64
+
+#ifdef TARGET_NR_3264_stat
+#define TARGET_NR_stat64 TARGET_NR_3264_stat
+#define TARGET_NR_lstat64 TARGET_NR_3264_lstat
+#endif
diff --git a/linux-user/openrisc/target_signal.h b/linux-user/openrisc/target_signal.h
new file mode 100644
index 0000000..a212143
--- /dev/null
+++ b/linux-user/openrisc/target_signal.h
@@ -0,0 +1,26 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_long ss_sp;
+ abi_ulong ss_size;
+ abi_long ss_flags;
+} target_stack_t;
+
+/* sigaltstack controls */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 2048
+#define TARGET_SIGSTKSZ 8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUOpenriscState *state)
+{
+ return state->gpr[1];
+}
+
+#endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/openrisc/termbits.h b/linux-user/openrisc/termbits.h
new file mode 100644
index 0000000..373af77
--- /dev/null
+++ b/linux-user/openrisc/termbits.h
@@ -0,0 +1,294 @@
+typedef unsigned char target_openrisc_cc; /*cc_t*/
+typedef unsigned int target_openrisc_speed; /*speed_t*/
+typedef unsigned int target_openrisc_tcflag; /*tcflag_t*/
+
+#define TARGET_NCCS 19
+struct target_termios {
+ target_openrisc_tcflag c_iflag; /* input mode flags */
+ target_openrisc_tcflag c_oflag; /* output mode flags */
+ target_openrisc_tcflag c_cflag; /* control mode flags */
+ target_openrisc_tcflag c_lflag; /* local mode flags */
+ target_openrisc_cc c_line; /* line discipline */
+ target_openrisc_cc c_cc[TARGET_NCCS]; /* control characters */
+};
+
+struct target_termios2 {
+ target_openrisc_tcflag c_iflag; /* input mode flags */
+ target_openrisc_tcflag c_oflag; /* output mode flags */
+ target_openrisc_tcflag c_cflag; /* control mode flags */
+ target_openrisc_tcflag c_lflag; /* local mode flags */
+ target_openrisc_cc c_line; /* line discipline */
+ target_openrisc_cc c_cc[TARGET_NCCS]; /* control characters */
+ target_openrisc_speed c_ispeed; /* input speed */
+ target_openrisc_speed c_ospeed; /* output speed */
+};
+
+struct target_termios3 {
+ target_openrisc_tcflag c_iflag; /* input mode flags */
+ target_openrisc_tcflag c_oflag; /* output mode flags */
+ target_openrisc_tcflag c_cflag; /* control mode flags */
+ target_openrisc_tcflag c_lflag; /* local mode flags */
+ target_openrisc_cc c_line; /* line discipline */
+ target_openrisc_cc c_cc[TARGET_NCCS]; /* control characters */
+ target_openrisc_speed c_ispeed; /* input speed */
+ target_openrisc_speed c_ospeed; /* output speed */
+};
+
+/* c_cc characters */
+#define TARGET_VINTR 0
+#define TARGET_VQUIT 1
+#define TARGET_VERASE 2
+#define TARGET_VKILL 3
+#define TARGET_VEOF 4
+#define TARGET_VTIME 5
+#define TARGET_VMIN 6
+#define TARGET_VSWTC 7
+#define TARGET_VSTART 8
+#define TARGET_VSTOP 9
+#define TARGET_VSUSP 10
+#define TARGET_VEOL 11
+#define TARGET_VREPRINT 12
+#define TARGET_VDISCARD 13
+#define TARGET_VWERASE 14
+#define TARGET_VLNEXT 15
+#define TARGET_VEOL2 16
+
+/* c_iflag bits */
+#define TARGET_IGNBRK 0000001
+#define TARGET_BRKINT 0000002
+#define TARGET_IGNPAR 0000004
+#define TARGET_PARMRK 0000010
+#define TARGET_INPCK 0000020
+#define TARGET_ISTRIP 0000040
+#define TARGET_INLCR 0000100
+#define TARGET_IGNCR 0000200
+#define TARGET_ICRNL 0000400
+#define TARGET_IUCLC 0001000
+#define TARGET_IXON 0002000
+#define TARGET_IXANY 0004000
+#define TARGET_IXOFF 0010000
+#define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8 0040000
+
+/* c_oflag bits */
+#define TARGET_OPOST 0000001
+#define TARGET_OLCUC 0000002
+#define TARGET_ONLCR 0000004
+#define TARGET_OCRNL 0000010
+#define TARGET_ONOCR 0000020
+#define TARGET_ONLRET 0000040
+#define TARGET_OFILL 0000100
+#define TARGET_OFDEL 0000200
+#define TARGET_NLDLY 0000400
+#define TARGET_NL0 0000000
+#define TARGET_NL1 0000400
+#define TARGET_CRDLY 0003000
+#define TARGET_CR0 0000000
+#define TARGET_CR1 0001000
+#define TARGET_CR2 0002000
+#define TARGET_CR3 0003000
+#define TARGET_TABDLY 0014000
+#define TARGET_TAB0 0000000
+#define TARGET_TAB1 0004000
+#define TARGET_TAB2 0010000
+#define TARGET_TAB3 0014000
+#define TARGET_XTABS 0014000
+#define TARGET_BSDLY 0020000
+#define TARGET_BS0 0000000
+#define TARGET_BS1 0020000
+#define TARGET_VTDLY 0040000
+#define TARGET_VT0 0000000
+#define TARGET_VT1 0040000
+#define TARGET_FFDLY 0100000
+#define TARGET_FF0 0000000
+#define TARGET_FF1 0100000
+
+/* c_cflag bit meaning */
+#define TARGET_CBAUD 0010017
+#define TARGET_B0 0000000 /* hang up */
+#define TARGET_B50 0000001
+#define TARGET_B75 0000002
+#define TARGET_B110 0000003
+#define TARGET_B134 0000004
+#define TARGET_B150 0000005
+#define TARGET_B200 0000006
+#define TARGET_B300 0000007
+#define TARGET_B600 0000010
+#define TARGET_B1200 0000011
+#define TARGET_B1800 0000012
+#define TARGET_B2400 0000013
+#define TARGET_B4800 0000014
+#define TARGET_B9600 0000015
+#define TARGET_B19200 0000016
+#define TARGET_B38400 0000017
+#define TARGET_EXTA B19200
+#define TARGET_EXTB B38400
+#define TARGET_CSIZE 0000060
+#define TARGET_CS5 0000000
+#define TARGET_CS6 0000020
+#define TARGET_CS7 0000040
+#define TARGET_CS8 0000060
+#define TARGET_CSTOPB 0000100
+#define TARGET_CREAD 0000200
+#define TARGET_PARENB 0000400
+#define TARGET_PARODD 0001000
+#define TARGET_HUPCL 0002000
+#define TARGET_CLOCAL 0004000
+#define TARGET_CBAUDEX 0010000
+#define TARGET_BOTHER 0010000
+#define TARGET_B57600 0010001
+#define TARGET_B115200 0010002
+#define TARGET_B230400 0010003
+#define TARGET_B460800 0010004
+#define TARGET_B500000 0010005
+#define TARGET_B576000 0010006
+#define TARGET_B921600 0010007
+#define TARGET_B1000000 0010010
+#define TARGET_B1152000 0010011
+#define TARGET_B1500000 0010012
+#define TARGET_B2000000 0010013
+#define TARGET_B2500000 0010014
+#define TARGET_B3000000 0010015
+#define TARGET_B3500000 0010016
+#define TARGET_B4000000 0010017
+#define TARGET_CIBAUD 002003600000 /* input baud rate */
+#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */
+#define TARGET_CRTSCTS 020000000000 /* flow control */
+
+#define TARGET_IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
+
+/* c_lflag bits */
+#define TARGET_ISIG 0000001
+#define TARGET_ICANON 0000002
+#define TARGET_XCASE 0000004
+#define TARGET_ECHO 0000010
+#define TARGET_ECHOE 0000020
+#define TARGET_ECHOK 0000040
+#define TARGET_ECHONL 0000100
+#define TARGET_NOFLSH 0000200
+#define TARGET_TOSTOP 0000400
+#define TARGET_ECHOCTL 0001000
+#define TARGET_ECHOPRT 0002000
+#define TARGET_ECHOKE 0004000
+#define TARGET_FLUSHO 0010000
+#define TARGET_PENDIN 0040000
+#define TARGET_IEXTEN 0100000
+#define TARGET_EXTPROC 0200000
+
+/* tcflow() and TCXONC use these */
+#define TARGET_TCOOFF 0
+#define TARGET_TCOON 1
+#define TARGET_TCIOFF 2
+#define TARGET_TCION 3
+
+/* tcflush() and TCFLSH use these */
+#define TARGET_TCIFLUSH 0
+#define TARGET_TCOFLUSH 1
+#define TARGET_TCIOFLUSH 2
+
+/* tcsetattr uses these */
+#define TARGET_TCSANOW 0
+#define TARGET_TCSADRAIN 1
+#define TARGET_TCSAFLUSH 2
+
+/* ioctls */
+#define TARGET_TCGETS 0x5401
+#define TARGET_TCSETS 0x5402
+#define TARGET_TCSETSW 0x5403
+#define TARGET_TCSETSF 0x5404
+#define TARGET_TCGETA 0x5405
+#define TARGET_TCSETA 0x5406
+#define TARGET_TCSETAW 0x5407
+#define TARGET_TCSETAF 0x5408
+#define TARGET_TCSBRK 0x5409
+#define TARGET_TCXONC 0x540A
+#define TARGET_TCFLSH 0x540B
+#define TARGET_TIOCEXCL 0x540C
+#define TARGET_TIOCNXCL 0x540D
+#define TARGET_TIOCSCTTY 0x540E
+#define TARGET_TIOCGPGRP 0x540F
+#define TARGET_TIOCSPGRP 0x5410
+#define TARGET_TIOCOUTQ 0x5411
+#define TARGET_TIOCSTI 0x5412
+#define TARGET_TIOCGWINSZ 0x5413
+#define TARGET_TIOCSWINSZ 0x5414
+#define TARGET_TIOCMGET 0x5415
+#define TARGET_TIOCMBIS 0x5416
+#define TARGET_TIOCMBIC 0x5417
+#define TARGET_TIOCMSET 0x5418
+#define TARGET_TIOCGSOFTCAR 0x5419
+#define TARGET_TIOCSSOFTCAR 0x541A
+#define TARGET_FIONREAD 0x541B
+#define TARGET_TIOCINQ FIONREAD
+#define TARGET_TIOCLINUX 0x541C
+#define TARGET_TIOCCONS 0x541D
+#define TARGET_TIOCGSERIAL 0x541E
+#define TARGET_TIOCSSERIAL 0x541F
+#define TARGET_TIOCPKT 0x5420
+#define TARGET_FIONBIO 0x5421
+#define TARGET_TIOCNOTTY 0x5422
+#define TARGET_TIOCSETD 0x5423
+#define TARGET_TIOCGETD 0x5424
+#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
+#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */
+#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */
+#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TARGET_TCGETS2 TARGET_IOR('T', 0x2A, struct termios2)
+#define TARGET_TCSETS2 TARGET_IOW('T', 0x2B, struct termios2)
+#define TARGET_TCSETSW2 TARGET_IOW('T', 0x2C, struct termios2)
+#define TARGET_TCSETSF2 TARGET_IOW('T', 0x2D, struct termios2)
+#define TARGET_TIOCGRS485 0x542E
+#ifndef TARGET_TIOCSRS485
+#define TARGET_TIOCSRS485 0x542F
+#endif
+/* Get Pty Number (of pty-mux device) */
+#define TARGET_TIOCGPTN TARGET_IOR('T', 0x30, unsigned int)
+/* Lock/unlock Pty */
+#define TARGET_TIOCSPTLCK TARGET_IOW('T', 0x31, int)
+/* Get primary device node of /dev/console */
+#define TARGET_TIOCGDEV TARGET_IOR('T', 0x32, unsigned int)
+#define TARGET_TCGETX 0x5432 /* SYS5 TCGETX compatibility */
+#define TARGET_TCSETX 0x5433
+#define TARGET_TCSETXF 0x5434
+#define TARGET_TCSETXW 0x5435
+/* pty: generate signal */
+#define TARGET_TIOCSIG TARGET_IOW('T', 0x36, int)
+#define TARGET_TIOCVHANGUP 0x5437
+
+#define TARGET_FIONCLEX 0x5450
+#define TARGET_FIOCLEX 0x5451
+#define TARGET_FIOASYNC 0x5452
+#define TARGET_TIOCSERCONFIG 0x5453
+#define TARGET_TIOCSERGWILD 0x5454
+#define TARGET_TIOCSERSWILD 0x5455
+#define TARGET_TIOCGLCKTRMIOS 0x5456
+#define TARGET_TIOCSLCKTRMIOS 0x5457
+#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */
+#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */
+#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */
+#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+/* wait for a change on serial input line(s) */
+#define TARGET_TIOCMIWAIT 0x545C
+/* read serial port inline interrupt counts */
+#define TARGET_TIOCGICOUNT 0x545D
+
+/*
+ * Some arches already define TARGET_FIOQSIZE due to a historical
+ * conflict with a Hayes modem-specific ioctl value.
+ */
+#ifndef TARGET_FIOQSIZE
+#define TARGET_FIOQSIZE 0x5460
+#endif
+
+/* Used for packet mode */
+#define TARGET_TIOCPKT_DATA 0
+#define TARGET_TIOCPKT_FLUSHREAD 1
+#define TARGET_TIOCPKT_FLUSHWRITE 2
+#define TARGET_TIOCPKT_STOP 4
+#define TARGET_TIOCPKT_START 8
+#define TARGET_TIOCPKT_NOSTOP 16
+#define TARGET_TIOCPKT_DOSTOP 32
+#define TARGET_TIOCPKT_IOCTL 64
+
+#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */
--
1.7.9.5
Jia Liu
2012-05-27 05:32:56 UTC
Permalink
add gdb stub support for openrisc.

Signed-off-by: Jia Liu <***@gmail.com>
---
gdbstub.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)

diff --git a/gdbstub.c b/gdbstub.c
index 6a77a66..98a0d18 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1155,6 +1155,68 @@ static int cpu_gdb_write_register(CPUMIPSState *env, uint8_t *mem_buf, int n)

return sizeof(target_ulong);
}
+#elif defined(TARGET_OPENRISC)
+
+#define NUM_CORE_REGS (32 + 3)
+
+static int cpu_gdb_read_register(CPUOpenriscState *env, uint8_t *mem_buf, int n)
+{
+ if (n < 32) {
+ GET_REG32(env->gpr[n]);
+ } else {
+ switch (n) {
+ case 32: /* PPC */
+ GET_REG32(env->ppc);
+ break;
+
+ case 33: /* NPC */
+ GET_REG32(env->npc);
+ break;
+
+ case 34: /* SR */
+ GET_REG32(env->sr);
+ break;
+
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+static int cpu_gdb_write_register(CPUOpenriscState *env,
+ uint8_t *mem_buf, int n)
+{
+ uint32_t tmp;
+
+ if (n > NUM_CORE_REGS) {
+ return 0;
+ }
+
+ tmp = ldl_p(mem_buf);
+
+ if (n < 32) {
+ env->gpr[n] = tmp;
+ } else {
+ switch (n) {
+ case 32: /* PPC */
+ env->ppc = tmp;
+ break;
+
+ case 33: /* NPC */
+ env->npc = tmp;
+ break;
+
+ case 34: /* SR */
+ env->sr = tmp;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return 4;
+}
#elif defined (TARGET_SH4)

/* Hint: Use "set architecture sh4" in GDB to see fpu registers */
@@ -1924,6 +1986,8 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
}
#elif defined (TARGET_MICROBLAZE)
s->c_cpu->sregs[SR_PC] = pc;
+#elif defined(TARGET_OPENRISC)
+ s->c_cpu->pc = pc;
#elif defined (TARGET_CRIS)
s->c_cpu->pc = pc;
#elif defined (TARGET_ALPHA)
--
1.7.9.5
Stefan Weil
2012-05-27 06:01:29 UTC
Permalink
Post by Jia Liu
This is the Opencores Openrisc 1200 support for Qemu.
Full implementation of the system-model and linux-user-model support.
The official name is 'QEMU', not 'Qemu'.

Please fix this in the patches, too.

Regards,

Stefan Weil
Jia Liu
2012-05-27 06:10:06 UTC
Permalink
Post by Stefan Weil
Post by Jia Liu
This is the Opencores Openrisc 1200 support for Qemu.
Full implementation of the system-model and linux-user-model support.
The official name is 'QEMU', not 'Qemu'.
Please fix this in the patches, too.
Thank you Stefan, I'll fix them all.
Post by Stefan Weil
Regards,
Stefan Weil
Regards,
Jia.
Jia Liu
2012-05-27 05:32:50 UTC
Permalink
add float point instruction helpers for openrisc.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 2 +-
target-openrisc/cpu.h | 3 +
target-openrisc/fpu_helper.c | 275 ++++++++++++++++++++++++++++++++++++++++++
target-openrisc/helper.h | 33 +++++
4 files changed, 312 insertions(+), 1 deletion(-)
create mode 100644 target-openrisc/fpu_helper.c

diff --git a/Makefile.target b/Makefile.target
index d68c168..f2dfa2a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -101,7 +101,7 @@ endif
libobj-$(TARGET_SPARC) += int32_helper.o
libobj-$(TARGET_SPARC64) += int64_helper.o
libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
-libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o int_helper.o\
+libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o fpu_helper.o int_helper.o\
intrpt.o intrpt_helper.o mmu.o mmu_helper.o

libobj-y += disas.o
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 977dd06..0f332ab 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -178,6 +178,8 @@ struct CPUOpenriscState {
uint32_t sr; /* Supervisor register */
target_ulong machi; /* Multiply register MACHI */
target_ulong maclo; /* Multiply register MACLO */
+ target_ulong fpmaddhi; /* Multiply and add float register FPMADDHI */
+ target_ulong fpmaddlo; /* Multiply and add float register FPMADDLO */
target_ulong epcr; /* Exception PC register */
target_ulong eear; /* Exception EA register */
uint32_t esr; /* Exception supervisor register */
@@ -198,6 +200,7 @@ struct CPUOpenriscState {
target_ulong address, int rw);
#endif
uint32_t fpcsr; /* Float register */
+ float_status fp_status;
target_ulong pc; /* Program counter */
target_ulong npc; /* Next PC */
target_ulong ppc; /* Prev PC */
diff --git a/target-openrisc/fpu_helper.c b/target-openrisc/fpu_helper.c
new file mode 100644
index 0000000..8311c67
--- /dev/null
+++ b/target-openrisc/fpu_helper.c
@@ -0,0 +1,275 @@
+/*
+ * Openrisc float helper routines
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ * Feng Gao <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "excp.h"
+
+static inline uint32_t ieee_ex_to_openrisc(CPUOpenriscState *env, int fexcp)
+{
+ int ret = 0;
+ if (fexcp) {
+ if (fexcp & float_flag_invalid) {
+ env->fpcsr |= FPCSR_IVF;
+ ret = 1;
+ }
+ if (fexcp & float_flag_overflow) {
+ env->fpcsr |= FPCSR_OVF;
+ ret = 1;
+ }
+ if (fexcp & float_flag_underflow) {
+ env->fpcsr |= FPCSR_UNF;
+ ret = 1;
+ }
+ if (fexcp & float_flag_divbyzero) {
+ env->fpcsr |= FPCSR_DZF;
+ ret = 1;
+ }
+ if (fexcp & float_flag_inexact) {
+ env->fpcsr |= FPCSR_IXF;
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
+static inline void update_fpcsr(CPUOpenriscState *env)
+{
+ int tmp = ieee_ex_to_openrisc(env,
+ get_float_exception_flags(&env->fp_status));
+
+ SET_FP_CAUSE(env->fpcsr, tmp);
+ if ((GET_FP_ENABLE(env->fpcsr) & tmp) && (env->fpcsr & FPCSR_FPEE)) {
+ helper_exception(env, EXCP_FPE);
+ } else {
+ UPDATE_FP_FLAGS(env->fpcsr, tmp);
+ }
+}
+
+uint64_t HELPER(itofd)(CPUOpenriscState *env, uint64_t val)
+{
+ uint64_t itofd;
+ set_float_exception_flags(0, &env->fp_status);
+ itofd = int32_to_float64(val, &env->fp_status);
+ update_fpcsr(env);
+ return itofd;
+}
+
+uint32_t HELPER(itofs)(CPUOpenriscState *env, uint32_t val)
+{
+ uint32_t itofs;
+ set_float_exception_flags(0, &env->fp_status);
+ itofs = int32_to_float32(val, &env->fp_status);
+ update_fpcsr(env);
+ return itofs;
+}
+
+uint64_t HELPER(ftoid)(CPUOpenriscState *env, uint64_t val)
+{
+ uint64_t ftoid;
+ set_float_exception_flags(0, &env->fp_status);
+ ftoid = float32_to_int64(val, &env->fp_status);
+ update_fpcsr(env);
+ return ftoid;
+}
+
+uint32_t HELPER(ftois)(CPUOpenriscState *env, uint32_t val)
+{
+ uint32_t ftois;
+ set_float_exception_flags(0, &env->fp_status);
+ ftois = float32_to_int32(val, &env->fp_status);
+ update_fpcsr(env);
+ return ftois;
+}
+
+#define FLOAT_OP(name, p) void helper_float_##_##p(void)
+
+#define FLOAT_CALC(name) \
+uint64_t helper_float_ ## name ## _d(CPUOpenriscState *env, \
+ uint64_t fdt0, uint64_t fdt1) \
+{ \
+ uint64_t result; \
+ set_float_exception_flags(0, &env->fp_status); \
+ result = float64_ ## name(fdt0, fdt1, &env->fp_status); \
+ update_fpcsr(env); \
+ return result; \
+} \
+ \
+uint32_t helper_float_ ## name ## _s(CPUOpenriscState *env, \
+ uint32_t fdt0, uint32_t fdt1) \
+{ \
+ uint32_t result; \
+ set_float_exception_flags(0, &env->fp_status); \
+ result = float32_ ## name(fdt0, fdt1, &env->fp_status); \
+ update_fpcsr(env); \
+ return result; \
+} \
+
+FLOAT_CALC(add)
+FLOAT_CALC(sub)
+FLOAT_CALC(mul)
+FLOAT_CALC(div)
+FLOAT_CALC(rem)
+#undef FLOAT_CALC
+
+#define FLOAT_TERNOP(name1, name2) \
+uint64_t helper_float_ ## name1 ## name2 ## _d(CPUOpenriscState *env, \
+ uint64_t fdt0, \
+ uint64_t fdt1) \
+{ \
+ uint64_t result, temp, hi, lo; \
+ uint32_t val1, val2; \
+ hi = env->fpmaddhi; \
+ lo = env->fpmaddlo; \
+ set_float_exception_flags(0, &env->fp_status); \
+ result = float64_ ## name1(fdt0, fdt1, &env->fp_status); \
+ lo &= 0xffffffff; \
+ hi &= 0xffffffff; \
+ temp = (hi << 32) | lo; \
+ result = float64_ ## name2(result, temp, &env->fp_status); \
+ val1 = result >> 32; \
+ val2 = (uint32_t) (result & 0xffffffff); \
+ update_fpcsr(env); \
+ env->fpmaddlo = val2; \
+ env->fpmaddhi = val1; \
+ return 0; \
+} \
+ \
+uint32_t helper_float_ ## name1 ## name2 ## _s(CPUOpenriscState *env, \
+ uint32_t fdt0, uint32_t fdt1) \
+{ \
+ uint64_t result, temp, hi, lo; \
+ uint32_t val1, val2; \
+ hi = env->fpmaddhi; \
+ lo = env->fpmaddlo; \
+ set_float_exception_flags(0, &env->fp_status); \
+ result = float64_ ## name1(fdt0, fdt1, &env->fp_status); \
+ temp = (hi << 32) | lo; \
+ result = float64_ ## name2(result, temp, &env->fp_status); \
+ val1 = result >> 32; \
+ val2 = (uint32_t) (result & 0xffffffff); \
+ update_fpcsr(env); \
+ env->fpmaddlo = val2; \
+ env->fpmaddhi = val1; \
+ return 0; \
+}
+
+FLOAT_TERNOP(mul, add)
+#undef FLOAT_TERNOP
+
+
+#define FLOAT_CMP(name) \
+uint64_t helper_float_ ## name ## _d(CPUOpenriscState *env, \
+ uint64_t fdt0, uint64_t fdt1) \
+{ \
+ int res; \
+ set_float_exception_flags(0, &env->fp_status); \
+ res = float64_ ## name(fdt0, fdt1, &env->fp_status); \
+ update_fpcsr(env); \
+ return res; \
+} \
+ \
+uint32_t helper_float_ ## name ## _s(CPUOpenriscState *env, \
+ uint32_t fdt0, uint32_t fdt1)\
+{ \
+ int res; \
+ set_float_exception_flags(0, &env->fp_status); \
+ res = float32_ ## name(fdt0, fdt1, &env->fp_status); \
+ update_fpcsr(env); \
+ return res; \
+}
+
+FLOAT_CMP(le)
+FLOAT_CMP(eq)
+FLOAT_CMP(lt)
+#undef FLOAT_CMP
+
+
+#define FLOAT_CMPNE(name) \
+uint64_t helper_float_ ## name ## _d(CPUOpenriscState *env, \
+ uint64_t fdt0, uint64_t fdt1) \
+{ \
+ int res; \
+ set_float_exception_flags(0, &env->fp_status); \
+ res = !float64_eq_quiet(fdt0, fdt1, &env->fp_status); \
+ update_fpcsr(env); \
+ return res; \
+} \
+ \
+uint32_t helper_float_ ## name ## _s(CPUOpenriscState *env, \
+ uint32_t fdt0, uint32_t fdt1) \
+{ \
+ int res; \
+ set_float_exception_flags(0, &env->fp_status); \
+ res = !float32_eq_quiet(fdt0, fdt1, &env->fp_status); \
+ update_fpcsr(env); \
+ return res; \
+}
+
+FLOAT_CMPNE(ne)
+#undef FLOAT_CMPNE
+
+#define FLOAT_CMPGT(name) \
+uint64_t helper_float_ ## name ## _d(CPUOpenriscState *env, \
+ uint64_t fdt0, uint64_t fdt1) \
+{ \
+ int res; \
+ set_float_exception_flags(0, &env->fp_status); \
+ res = !float64_le(fdt0, fdt1, &env->fp_status); \
+ update_fpcsr(env); \
+ return res; \
+} \
+ \
+uint32_t helper_float_ ## name ## _s(CPUOpenriscState *env, \
+ uint32_t fdt0, uint32_t fdt1) \
+{ \
+ int res; \
+ set_float_exception_flags(0, &env->fp_status); \
+ res = !float32_le(fdt0, fdt1, &env->fp_status); \
+ update_fpcsr(env); \
+ return res; \
+}
+FLOAT_CMPGT(gt)
+#undef FLOAT_CMPGT
+
+#define FLOAT_CMPGE(name) \
+uint64_t helper_float_ ## name ## _d(CPUOpenriscState *env, \
+ uint64_t fdt0, uint64_t fdt1) \
+{ \
+ int res; \
+ set_float_exception_flags(0, &env->fp_status); \
+ res = !float64_lt(fdt0, fdt1, &env->fp_status); \
+ update_fpcsr(env); \
+ return res; \
+} \
+ \
+uint32_t helper_float_ ## name ## _s(CPUOpenriscState *env, \
+ uint32_t fdt0, uint32_t fdt1) \
+{ \
+ int res; \
+ set_float_exception_flags(0, &env->fp_status); \
+ res = !float32_lt(fdt0, fdt1, &env->fp_status); \
+ update_fpcsr(env); \
+ return res; \
+}
+
+FLOAT_CMPGE(ge)
+#undef FLOAT_CMPGE
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index 3d82d24..b26aad8 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -22,6 +22,39 @@
/* exception */
DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)

+/* float */
+DEF_HELPER_FLAGS_2(itofd, 0, i64, env, i64)
+DEF_HELPER_FLAGS_2(itofs, 0, i32, env, i32)
+DEF_HELPER_FLAGS_2(ftoid, 0, i64, env, i64)
+DEF_HELPER_FLAGS_2(ftois, 0, i32, env, i32)
+
+#define FOP_MADD(op) \
+DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \
+DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
+FOP_MADD(muladd)
+#undef FOP_MADD
+
+#define FOP_CALC(op) \
+DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \
+DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
+FOP_CALC(add)
+FOP_CALC(sub)
+FOP_CALC(mul)
+FOP_CALC(div)
+FOP_CALC(rem)
+#undef FOP_CALC
+
+#define FOP_CMP(op) \
+DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \
+DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
+FOP_CMP(eq)
+FOP_CMP(lt)
+FOP_CMP(le)
+FOP_CMP(ne)
+FOP_CMP(gt)
+FOP_CMP(ge)
+#undef FOP_CMP
+
/* int */
DEF_HELPER_FLAGS_1(ff1, 0, tl, tl)
DEF_HELPER_FLAGS_1(fl1, 0, tl, tl)
--
1.7.9.5
Jia Liu
2012-05-27 05:32:52 UTC
Permalink
add Programmable Interrupt Controller for openrisc.

Signed-off-by: Jia Liu <***@gmail.com>
---
hw/openrisc_pic.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++
target-openrisc/cpu.h | 5 +++++
2 files changed, 55 insertions(+)

diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
index 201c6bc..1c28904 100644
--- a/hw/openrisc_pic.c
+++ b/hw/openrisc_pic.c
@@ -25,4 +25,54 @@
/* Reset PIC */
void cpu_openrisc_pic_reset(CPUOpenriscState *env)
{
+ env->picmr = 0x00000000;
+ env->picsr = 0x00000000;
+}
+
+/* openrisc pic handler */
+static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
+{
+ CPUOpenriscState *env = (CPUOpenriscState *)opaque;
+ int i;
+ uint32_t irq_bit = 1 << irq;
+
+ if (irq > 31 || irq < 0) {
+ return;
+ }
+
+ if (level) {
+ env->picsr |= irq_bit;
+ } else {
+ env->picsr &= ~irq_bit;
+ }
+
+ for (i = 0; i < 32; i++) {
+ if ((env->picsr && (1 << i)) && (env->picmr && (1 << i))) {
+ cpu_interrupt(env, CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+ env->picsr &= ~(1 << i);
+ }
+ }
+}
+
+void cpu_openrisc_pic_init(CPUOpenriscState *env)
+{
+ int i;
+ qemu_irq *qi;
+ qi = qemu_allocate_irqs(openrisc_pic_cpu_handler, env, NR_IRQS);
+
+ for (i = 0; i < NR_IRQS; i++) {
+ env->irq[i] = qi[i];
+ }
+}
+
+void cpu_openrisc_store_picmr(CPUOpenriscState *env, uint32_t value)
+{
+ env->picmr |= value;
+}
+
+void cpu_openrisc_store_picsr(CPUOpenriscState *env, uint32_t value)
+{
+ env->picsr &= ~value;
}
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 0f332ab..7417dcc 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -198,6 +198,9 @@ struct CPUOpenriscState {
int (*map_address_data)(struct CPUOpenriscState *env,
target_phys_addr_t *physical, int *prot,
target_ulong address, int rw);
+
+ uint32_t picmr; /* Interrupt mask register */
+ uint32_t picsr; /* Interrupt contrl register*/
#endif
uint32_t fpcsr; /* Float register */
float_status fp_status;
@@ -274,6 +277,8 @@ int cpu_openrisc_handle_mmu_fault(CPUOpenriscState *env, target_ulong address,
void openrisc_reset(CPUOpenriscState *env);
#if !defined(CONFIG_USER_ONLY)
void cpu_openrisc_pic_reset(CPUOpenriscState *env);
+void cpu_openrisc_store_picsr(CPUOpenriscState *env, uint32_t value);
+void cpu_openrisc_store_picmr(CPUOpenriscState *env, uint32_t value);

void openrisc_mmu_init(CPUOpenriscState *env);
int get_phys_nommu(CPUOpenriscState *env, target_phys_addr_t *physical,
--
1.7.9.5
Jia Liu
2012-05-27 05:32:51 UTC
Permalink
add openrisc instruction translation routines.

Signed-off-by: Jia Liu <***@gmail.com>
---
target-openrisc/translate.c | 1421 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1421 insertions(+)

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 5bbad9e..965fa0e 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -26,14 +26,1429 @@
#include "qemu-log.h"
#include "config.h"

+#include "helper.h"
+#define GEN_HELPER 1
+#include "helper.h"
+
+#define DISAS_OPENRISC 1
+#if DISAS_OPENRISC
+# define LOG_DIS(...) do { } while (0)
+#endif
+
+typedef struct DisasContext {
+ CPUOpenriscState *env;
+ TranslationBlock *tb;
+ target_ulong pc, ppc, npc;
+ uint32_t tb_flags, synced_flags;
+ uint32_t is_jmp;
+ uint32_t mem_idx;
+ int singlestep_enabled;
+ uint32_t delayed_branch;
+} DisasContext;
+
+static TCGv_ptr cpu_env;
+static TCGv cpu_sr;
+static TCGv cpu_R[32];
+static TCGv cpu_pc;
+static TCGv jmp_pc; /* l.jr/l.jalr temp pc */
+static TCGv cpu_npc;
+static TCGv cpu_ppc;
+static TCGv_i32 env_btaken; /* bf/bnf , F flag taken */
+static TCGv_i32 fpcsr;
+static TCGv machi, maclo;
+static TCGv fpmaddhi, fpmaddlo;
+static TCGv_i32 env_flags;
+#include "gen-icount.h"
+
void openrisc_translate_init(void)
{
+ static const char * const regnames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+ };
+ int i;
+
+ cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+ cpu_sr = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenriscState, sr), "sr");
+ env_flags = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUOpenriscState, flags),
+ "flags");
+ cpu_pc = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenriscState, pc), "pc");
+ cpu_npc = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenriscState, npc), "npc");
+ cpu_ppc = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenriscState, ppc), "ppc");
+ jmp_pc = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenriscState, jmp_pc), "jmp_pc");
+ env_btaken = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUOpenriscState, btaken),
+ "btaken");
+ fpcsr = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUOpenriscState, fpcsr),
+ "fpcsr");
+ machi = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenriscState, machi),
+ "machi");
+ maclo = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenriscState, maclo),
+ "maclo");
+ fpmaddhi = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenriscState, fpmaddhi),
+ "fpmaddhi");
+ fpmaddlo = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenriscState, fpmaddlo),
+ "fpmaddlo");
+ for (i = 0; i < 32; i++) {
+ cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenriscState, gpr[i]),
+ regnames[i]);
+ }
+#define GEN_HELPER 2
+#include "helper.h"
+}
+
+/* Writeback SR_F transaltion-space to execution-space. */
+static inline void wb_SR_F(void)
+{
+ int label;
+
+ label = gen_new_label();
+ tcg_gen_andi_tl(cpu_sr, cpu_sr, ~SR_F);
+ tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, label);
+ tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_F);
+ gen_set_label(label);
+}
+
+static inline int zero_extend(unsigned int val, int width)
+{
+ return val & ((1 << width) - 1);
+}
+
+static inline int sign_extend(unsigned int val, int width)
+{
+ int sval;
+
+ /* LSL. */
+ val <<= 32 - width;
+ sval = val;
+ /* ASR. */
+ sval >>= 32 - width;
+ return sval;
+}
+
+static inline void gen_sync_flags(DisasContext *dc)
+{
+ /* Sync the tb dependent flag between translate and runtime. */
+ if (dc->tb_flags != dc->synced_flags) {
+ tcg_gen_movi_tl(env_flags, dc->tb_flags);
+ dc->synced_flags = dc->tb_flags;
+ }
+}
+
+static void gen_exception(DisasContext *dc, unsigned int excp)
+{
+ TCGv_i32 tmp = tcg_const_i32(excp);
+ gen_helper_exception(cpu_env, tmp);
+ tcg_temp_free(tmp);
+}
+
+static void gen_illegal_exception(DisasContext *dc)
+{
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ gen_exception(dc, EXCP_ILLEGAL);
+ dc->is_jmp = DISAS_UPDATE;
+}
+
+static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
+{
+ TranslationBlock *tb;
+ tb = dc->tb;
+ if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
+ likely(!dc->singlestep_enabled)) {
+ tcg_gen_movi_tl(cpu_pc, dest);
+ tcg_gen_goto_tb(n);
+ tcg_gen_exit_tb((tcg_target_long)tb + n);
+ } else {
+ tcg_gen_movi_tl(cpu_pc, dest);
+ if (dc->singlestep_enabled) {
+ gen_exception(dc, EXCP_DEBUG);
+ }
+ tcg_gen_exit_tb(0);
+ }
+}
+
+static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
+{
+ target_ulong tmp_pc;
+ int lab = gen_new_label();
+ TCGv sr_f = tcg_temp_new();
+ /* N26, 26bits imm */
+ tmp_pc = sign_extend((imm<<2), 26) + dc->pc;
+ tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+
+ if (op0 == 0x0) {
+ /*l.j*/
+ tcg_gen_movi_tl(jmp_pc, tmp_pc);
+ } else if (op0 == 0x1) {
+ /*l.jal*/
+ tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+ tcg_gen_movi_tl(jmp_pc, tmp_pc);
+ } else if (op0 == 0x3) {
+ /*l.bnf*/
+ tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, sr_f, SR_F, lab);
+ tcg_gen_movi_tl(jmp_pc, tmp_pc);
+ gen_set_label(lab);
+ } else if (op0 == 0x4) {
+ /*l.bf*/
+ tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+ tcg_gen_brcondi_i32(TCG_COND_NE, sr_f, SR_F, lab);
+ tcg_gen_movi_tl(jmp_pc, tmp_pc);
+ gen_set_label(lab);
+ } else if (op0 == 0x11) {
+ /*l.jr*/
+ tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
+ } else if (op0 == 0x12) {
+ /*l.jalr*/
+ tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+ tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
+ } else {
+ gen_illegal_exception(dc);
+ }
+
+ tcg_temp_free(sr_f);
+ dc->delayed_branch = 2;
+ dc->tb_flags |= D_FLAG;
+ gen_sync_flags(dc);
+}
+
+static inline uint32_t field(uint32_t val, int start, int length)
+{
+ val >>= start;
+ val &= ~(~0 << length);
+ return val;
+}
+
+static void dec_calc(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+ uint32_t op0, op1, op2;
+ uint32_t ra, rb, rd;
+ op0 = field(insn, 0, 4);
+ op1 = field(insn, 8, 2);
+ op2 = field(insn, 6, 2);
+ ra = field(insn, 16, 5);
+ rb = field(insn, 11, 5);
+ rd = field(insn, 21, 5);
+
+ switch (op0) {
+ case 0x0000:
+ switch (op1) {
+ case 0x00: /*l.add*/
+ LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_add(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0001: /*l.addc*/
+ switch (op1) {
+ case 0x00:
+ LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_addc(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0002: /*l.sub*/
+ switch (op1) {
+ case 0x00:
+ LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_sub(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0003: /*l.and*/
+ switch (op1) {
+ case 0x00:
+ LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0004: /*l.or*/
+ switch (op1) {
+ case 0x00:
+ LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0005:
+ switch (op1) {
+ case 0x00: /*l.xor*/
+ LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0006:
+ switch (op1) {
+ case 0x03: /*l.mul*/
+ LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb);
+ if (ra != 0 && rb != 0) {
+ gen_helper_mul(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ } else {
+ tcg_gen_movi_tl(cpu_R[rd], 0x0);
+ }
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0009:
+ switch (op1) {
+ case 0x03: /*l.div*/
+ LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
+ if (rb == 0) {
+ TCGv_i32 sr_ove;
+ int lab = gen_new_label();
+ sr_ove = tcg_temp_new();
+ tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV);
+ tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY);
+ tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+ tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab);
+ gen_exception(dc, EXCP_RANGE);
+ gen_set_label(lab);
+ tcg_temp_free(sr_ove);
+ } else if (rb != 0) {
+ tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ } else {
+ break;
+ }
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x000a:
+ switch (op1) {
+ case 0x03: /*l.divu*/
+ LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb);
+ if (rb == 0) {
+ TCGv_i32 sr_ove;
+ int lab = gen_new_label();
+ sr_ove = tcg_temp_new();
+ tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV);
+ tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY);
+ tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+ tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab);
+ gen_exception(dc, EXCP_RANGE);
+ gen_set_label(lab);
+ tcg_temp_free(sr_ove);
+ } else if (rb != 0) {
+ tcg_gen_extu_i32_tl(cpu_R[ra], cpu_R[ra]);
+ tcg_gen_extu_i32_tl(cpu_R[rb], cpu_R[rb]);
+ tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ } else {
+ break;
+ }
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x000b:
+ switch (op1) {
+ case 0x03: /*l.mulu*/
+ LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb);
+ if (rb != 0 && ra != 0) {
+ TCGv_i64 result = tcg_temp_new();
+ TCGv_i32 high = tcg_temp_new();
+ TCGv_i32 sr_ove = tcg_temp_new();
+ int lab = gen_new_label();
+ int lab2 = gen_new_label();
+ tcg_gen_extu_i32_tl(cpu_R[ra], cpu_R[ra]);
+ tcg_gen_extu_i32_tl(cpu_R[rb], cpu_R[rb]);
+ tcg_gen_mul_tl(result, cpu_R[ra], cpu_R[rb]);
+ tcg_gen_shri_tl(high, result, (sizeof(target_ulong) * 8));
+ tcg_gen_brcondi_tl(TCG_COND_EQ, high, 0x0, lab);
+ tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY);
+ tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV);
+ tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+ tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab2);
+ gen_exception(dc, EXCP_RANGE);
+ gen_set_label(lab);
+ tcg_gen_trunc_i64_tl(cpu_R[rd], result);
+ gen_set_label(lab2);
+ tcg_temp_free(result);
+ tcg_temp_free(high);
+ tcg_temp_free(sr_ove);
+ } else {
+ tcg_gen_movi_tl(cpu_R[rd], 0);
+ }
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x000e:
+ switch (op1) {
+ case 0x00: /*l.cmov*/
+ LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb);
+ {
+ int lab = gen_new_label();
+ TCGv sr_f = tcg_temp_new();
+ tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+ tcg_gen_mov_tl(cpu_R[rd], cpu_R[rb]);
+ tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
+ tcg_gen_mov_tl(cpu_R[rd], cpu_R[ra]);
+ gen_set_label(lab);
+ tcg_temp_free(sr_f);
+ }
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x000f:
+ switch (op1) {
+ case 0x00: /*l.ff1*/
+ LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_ff1(cpu_R[rd], cpu_R[ra]);
+ break;
+ case 0x01: /*l.fl1*/
+ LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_fl1(cpu_R[rd], cpu_R[ra]);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0008:
+ switch (op1) {
+ case 0x00:
+ switch (op2) {
+ case 0x00: /*l.sll*/
+ LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ break;
+ case 0x01: /*l.srl*/
+ LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ break;
+ case 0x02: /*l.sra*/
+ LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ break;
+ case 0x03: /*l.ror*/
+ LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x000c:
+ switch (op1) {
+ case 0x00:
+ switch (op2) {
+ case 0x00: /*l.exths*/
+ LOG_DIS("l.exths r%d, r%d\n", rd, ra);
+ tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]);
+ break;
+ case 0x01: /*l.extbs*/
+ LOG_DIS("l.extbs r%d, r%d\n", rd, ra);
+ tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]);
+ break;
+ case 0x02: /*l.exthz*/
+ LOG_DIS("l.exthz r%d, r%d\n", rd, ra);
+ tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]);
+ break;
+ case 0x03: /*l.extbz*/
+ LOG_DIS("l.extbz r%d, r%d\n", rd, ra);
+ tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x000d:
+ switch (op1) {
+ case 0x00:
+ switch (op2) {
+ case 0x00: /*l.extws*/
+ LOG_DIS("l.extws r%d, r%d\n", rd, ra);
+ tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]);
+ break;
+ case 0x01: /*l.extwz*/
+ LOG_DIS("l.extwz r%d, r%d\n", rd, ra);
+ tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+}
+
+static void dec_misc(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+ uint32_t op0, op1;
+ uint32_t ra, rb, rd;
+ uint32_t /*L6, K5, */I16, I5, I11, N26, tmp;
+ op0 = field(insn, 26, 6);
+ op1 = field(insn, 24, 2);
+ ra = field(insn, 16, 5);
+ rb = field(insn, 11, 5);
+ rd = field(insn, 21, 5);
+ /*L6 = field(insn, 5, 6);
+ K5 = field(insn, 0, 5);*/
+ I16 = field(insn, 0, 16);
+ I5 = field(insn, 21, 5);
+ I11 = field(insn, 0, 11);
+ N26 = field(insn, 0, 26);
+ tmp = (I5<<11) + I11;
+ TCGv t0 = tcg_temp_new();
+
+ switch (op0) {
+ case 0x00: /*l.j*/
+ LOG_DIS("l.j %d\n", N26);
+ case 0x01: /*l.jal*/
+ LOG_DIS("l.jal %d\n", N26);
+ case 0x03: /*l.bnf*/
+ LOG_DIS("l.bnf %d\n", N26);
+ case 0x04: /*l.bf*/
+ LOG_DIS("l.bf %d\n", N26);
+
+ gen_jump(dc, N26, 0, op0);
+ break;
+
+ case 0x05:
+ switch (op1) {
+ case 0x01: /*l.nop*/
+ LOG_DIS("l.nop %d\n", I16);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x11: /*l.jr*/
+ LOG_DIS("l.jr r%d\n", rb);
+ case 0x12: /*l.jalr*/
+ LOG_DIS("l.jalr r%d\n", rb);
+
+ gen_jump(dc, 0, rb, op0);
+ break;
+
+ case 0x13: /*l.maci*/
+ LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I11);
+ {
+ TCGv_i64 tra = tcg_temp_new_i64(); /* store cpu_R[ra]*/
+ TCGv_i64 tmac = tcg_temp_new_i64(); /* store machi maclo*/
+ tcg_gen_movi_tl(t0, tmp);
+ tcg_gen_ext32s_i64(tra, cpu_R[ra]);
+ tcg_gen_ext32s_i64(tmac, t0);
+ tcg_gen_mul_tl(tmac, tra, tmac);
+ tcg_gen_trunc_i64_i32(cpu_R[ra], tmac);
+ tcg_gen_add_i64(machi, machi, cpu_R[ra]);
+ tcg_gen_add_i64(maclo, maclo, cpu_R[ra]);
+ tcg_temp_free(tra);
+ tcg_temp_free(tmac);
+ }
+ break;
+
+ case 0x09: /*l.rfe*/
+ LOG_DIS("l.rfe\n");
+ {
+ gen_helper_rfe(cpu_env);
+ dc->is_jmp = DISAS_UPDATE;
+ }
+ break;
+
+ case 0x1c: /*l.cust1*/
+ LOG_DIS("l.cust1\n");
+ break;
+
+ case 0x1d: /*l.cust2*/
+ LOG_DIS("l.cust2\n");
+ break;
+
+ case 0x1e: /*l.cust3*/
+ LOG_DIS("l.cust3\n");
+ break;
+
+ case 0x1f: /*l.cust4*/
+ LOG_DIS("l.cust4\n");
+ break;
+
+ case 0x3c: /*l.cust5*/
+ /*LOG_DIS("l.cust5 r%d, r%d, r%d, %d, %d\n", rd, ra, rb, L6, K5);*/
+ break;
+
+ case 0x3d: /*l.cust6*/
+ LOG_DIS("l.cust6\n");
+ break;
+
+ case 0x3e: /*l.cust7*/
+ LOG_DIS("l.cust7\n");
+ break;
+
+ case 0x3f: /*l.cust8*/
+ LOG_DIS("l.cust8\n");
+ break;
+
+ case 0x20: /*l.ld*/
+ LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16);
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+ tcg_gen_qemu_ld64(cpu_R[rd], t0, dc->mem_idx);
+ break;
+
+ case 0x21: /*l.lwz*/
+ LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16);
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+ tcg_gen_qemu_ld32u(cpu_R[rd], t0, dc->mem_idx);
+ break;
+
+ case 0x22: /*l.lws*/
+ LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16);
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+ tcg_gen_qemu_ld32s(cpu_R[rd], t0, dc->mem_idx);
+ break;
+
+ case 0x23: /*l.lbz*/
+ LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16);
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+ tcg_gen_qemu_ld8u(cpu_R[rd], t0, dc->mem_idx);
+ break;
+
+ case 0x24: /*l.lbs*/
+ LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16);
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+ tcg_gen_qemu_ld8s(cpu_R[rd], t0, dc->mem_idx);
+ break;
+
+ case 0x25: /*l.lhz*/
+ LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16);
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+ tcg_gen_qemu_ld16u(cpu_R[rd], t0, dc->mem_idx);
+ break;
+
+ case 0x26: /*l.lhs*/
+ LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16);
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+ tcg_gen_qemu_ld16s(cpu_R[rd], t0, dc->mem_idx);
+ break;
+
+ case 0x27: /*l.addi*/
+ LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
+ {
+ TCGv t0 = tcg_const_tl(sign_extend(I16, 16));
+ gen_helper_add(cpu_R[rd], cpu_env, cpu_R[ra], t0);
+ tcg_temp_free(t0);
+ }
+ break;
+
+ case 0x28: /*l.addic*/
+ LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16);
+ {
+ TCGv t0 = tcg_const_tl(sign_extend(I16, 16));
+ gen_helper_addc(cpu_R[rd], cpu_env, cpu_R[ra], t0);
+ tcg_temp_free(t0);
+ }
+ break;
+
+ case 0x29: /*l.andi*/
+ LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, I16);
+ tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], zero_extend(I16, 16));
+ break;
+
+ case 0x2a: /*l.ori*/
+ LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, zero_extend(I16, 16));
+ tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], I16);
+ break;
+
+ case 0x2b: /*l.xori*/
+ LOG_DIS("l.xori r%d, r%d, %d\n", rd, ra, I16);
+ tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], sign_extend(I16, 16));
+ break;
+
+ case 0x2c: /*l.muli*/
+ LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16);
+ if (ra != 0 && I16 != 0) {
+ TCGv i16 = tcg_const_tl(I16);
+ gen_helper_mul(cpu_R[rd], cpu_env, cpu_R[ra], i16);
+ tcg_temp_free(i16);
+ } else {
+ tcg_gen_movi_tl(cpu_R[rd], 0x0);
+ }
+ break;
+
+ case 0x2d: /*l.mfspr*/
+ LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
+ break;
+
+ case 0x30: /*l.mtspr*/
+ LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+ break;
+
+ case 0x34: /*l.sd*/
+ LOG_DIS("l.sd %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+ tcg_gen_qemu_st64(cpu_R[rb], t0, dc->mem_idx);
+ break;
+
+ case 0x35: /*l.sw*/
+ LOG_DIS("l.sw %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+ tcg_gen_qemu_st32(cpu_R[rb], t0, dc->mem_idx);
+ break;
+
+ case 0x36: /*l.sb*/
+ LOG_DIS("l.sb %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+ tcg_gen_qemu_st8(cpu_R[rb], t0, dc->mem_idx);
+ break;
+
+ case 0x37: /*l.sh*/
+ LOG_DIS("l.sh %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+ tcg_gen_qemu_st16(cpu_R[rb], t0, dc->mem_idx);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ tcg_temp_free(t0);
+}
+
+static void dec_mac(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+ uint32_t op0;
+ uint32_t ra, rb;
+ op0 = field(insn, 0, 4);
+ ra = field(insn, 16, 5);
+ rb = field(insn, 11, 5);
+ TCGv_i64 t0 = tcg_temp_new();
+ TCGv_i64 t1 = tcg_temp_new();
+ TCGv_i64 t2 = tcg_temp_new();
+ switch (op0) {
+ case 0x0001: /*l.mac*/
+ LOG_DIS("l.mac r%d, r%d\n", ra, rb);
+ {
+ tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]);
+ tcg_gen_ext_i32_i64(t1, t0);
+ tcg_gen_concat_i32_i64(t2, maclo, machi);
+ tcg_gen_add_i64(t2, t2, t1);
+ tcg_gen_trunc_i64_i32(maclo, t2);
+ tcg_gen_shri_i64(t2, t2, 32);
+ tcg_gen_trunc_i64_i32(machi, t2);
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ tcg_temp_free(t2);
+ }
+ break;
+
+ case 0x0002: /*l.msb*/
+ LOG_DIS("l.msb r%d, r%d\n", ra, rb);
+ {
+ tcg_gen_ext_i32_i64(t0, cpu_R[ra]);
+ tcg_gen_ext_i32_i64(t1, cpu_R[rb]);
+ tcg_gen_mul_i64(t0, t0, t1);
+ tcg_gen_trunc_i64_i32(cpu_R[ra], t0);
+ tcg_gen_sub_i32(maclo, maclo, cpu_R[ra]);
+ tcg_gen_sub_i32(machi, machi, cpu_R[ra]);
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ }
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+}
+
+static void dec_logic(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+ uint32_t op0;
+ uint32_t rd, ra, L6;
+ op0 = field(insn, 6, 2);
+ rd = field(insn, 21, 5);
+ ra = field(insn, 16, 5);
+ L6 = field(insn, 0, 6);
+
+ switch (op0) {
+ case 0x00: /*l.slli*/
+ LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6);
+ tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+ break;
+
+ case 0x01: /*l.srli*/
+ LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6);
+ tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+ break;
+
+ case 0x02: /*l.srai*/
+ LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6);
+ tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f)); break;
+
+ case 0x03: /*l.rori*/
+ LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6);
+ tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+}
+
+static void dec_M(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+ uint32_t op0;
+ uint32_t rd;
+ uint32_t K16;
+ op0 = field(insn, 16, 1);
+ rd = field(insn, 21, 5);
+ K16 = field(insn, 0, 16);
+
+ switch (op0) {
+ case 0x0: /*l.movhi*/
+ LOG_DIS("l.movhi r%d, %d\n", rd, K16);
+ tcg_gen_movi_tl(cpu_R[rd], (K16 << 16));
+ break;
+
+ case 0x1: /*l.macrc*/
+ LOG_DIS("l.macrc r%d\n", rd);
+ tcg_gen_mov_tl(cpu_R[rd], maclo);
+ tcg_gen_movi_tl(maclo, 0x0);
+ tcg_gen_movi_tl(machi, 0x0);
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+}
+
+static void dec_comp(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+ uint32_t op0;
+ uint32_t ra, rb;
+
+ op0 = field(insn, 21, 5);
+ ra = field(insn, 16, 5);
+ rb = field(insn, 11, 5);
+
+ tcg_gen_movi_i32(env_btaken, 0x0);
+ /* unsigned integers */
+ tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+ tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
+
+ switch (op0) {
+ case 0x0: /*l.sfeq*/
+ LOG_DIS("l.sfeq r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x1: /*l.sfne*/
+ LOG_DIS("l.sfne r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x2: /*l.sfgtu*/
+ LOG_DIS("l.sfgtu r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_GTU, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x3: /*l.sfgeu*/
+ LOG_DIS("l.sfgeu r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_GEU, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x4: /*l.sfltu*/
+ LOG_DIS("l.sfltu r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_LTU, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x5: /*l.sfleu*/
+ LOG_DIS("l.sfleu r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0xa: /*l.sfgts*/
+ LOG_DIS("l.sfgts r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0xb: /*l.sfges*/
+ LOG_DIS("l.sfges r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0xc: /*l.sflts*/
+ LOG_DIS("l.sflts r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0xd: /*l.sfles*/
+ LOG_DIS("l.sfles r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ wb_SR_F();
+}
+
+static void dec_compi(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+ uint32_t op0;
+ uint32_t ra, I16;
+
+ op0 = field(insn, 21, 5);
+ ra = field(insn, 16, 5);
+ I16 = field(insn, 0, 16);
+
+ tcg_gen_movi_i32(env_btaken, 0x0);
+ tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+ I16 = sign_extend(I16, 16);
+
+ switch (op0) {
+ case 0x0: /*l.sfeqi*/
+ LOG_DIS("l.sfeqi r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], I16);
+ break;
+
+ case 0x1: /*l.sfnei*/
+ LOG_DIS("l.sfnei r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_NE, env_btaken, cpu_R[ra], I16);
+ break;
+
+ case 0x2: /*l.sfgtui*/
+ LOG_DIS("l.sfgtui r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_GTU, env_btaken, cpu_R[ra], I16);
+ break;
+
+ case 0x3: /*l.sfgeui*/
+ LOG_DIS("l.sfgeui r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_GEU, env_btaken, cpu_R[ra], I16);
+ break;
+
+ case 0x4: /*l.sfltui*/
+ LOG_DIS("l.sfltui r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_LTU, env_btaken, cpu_R[ra],
+ sign_extend(I16, 16));
+ break;
+
+ case 0x5: /*l.sfleui*/
+ LOG_DIS("l.sfleui r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], I16);
+ break;
+
+ case 0xa: /*l.sfgtsi*/
+ LOG_DIS("l.sfgtsi r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_GT, env_btaken, cpu_R[ra], I16);
+ break;
+
+ case 0xb: /*l.sfgesi*/
+ LOG_DIS("l.sfgesi r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_GE, env_btaken, cpu_R[ra], I16);
+ break;
+
+ case 0xc: /*l.sfltsi*/
+ LOG_DIS("l.sfltsi r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_LT, env_btaken, cpu_R[ra], I16);
+ break;
+
+ case 0xd: /*l.sflesi*/
+ LOG_DIS("l.sflesi r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_LE, env_btaken, cpu_R[ra], I16);
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ wb_SR_F();
+}
+
+static void dec_sys(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+ uint32_t op0;
+ /*uint32_t K16;*/
+ op0 = field(insn, 16, 8);
+ /*K16 = field(insn, 0, 16);*/
+
+ switch (op0) {
+ case 0x000: /*l.sys*/
+ /*LOG_DIS("l.sys %d\n", K16);*/
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ gen_exception(dc, EXCP_SYSCALL);
+ dc->is_jmp = DISAS_UPDATE;
+ break;
+
+ case 0x100: /*l.trap*/
+ /*LOG_DIS("l.trap %d\n", K16);*/
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ gen_exception(dc, EXCP_TRAP);
+ break;
+
+ case 0x300: /*l.csync*/
+ LOG_DIS("l.csync\n");
+ break;
+
+ case 0x200: /*l.msync*/
+ LOG_DIS("l.msync\n");
+ break;
+
+ case 0x270: /*l.psync*/
+ LOG_DIS("l.psync\n");
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+}
+
+static void dec_float(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+ uint32_t op0;
+ uint32_t ra, rb, rd;
+ op0 = field(insn, 0, 8);
+ ra = field(insn, 16, 5);
+ rb = field(insn, 11, 5);
+ rd = field(insn, 21, 5);
+
+ switch (op0) {
+ case 0x10: /*lf.add.d*/
+ LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x00: /*lf.add.s*/
+ LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x11: /*lf.sub.d*/
+ LOG_DIS("lf.sub.d r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_sub_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x01: /*lf.sub.s*/
+ LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x12: /*lf.mul.d*/
+ LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb);
+ if (cpu_R[ra] != 0 && cpu_R[rb] != 0) {
+ gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ } else {
+ tcg_gen_ori_tl(fpcsr, fpcsr, FPCSR_ZF);
+ tcg_gen_movi_i64(cpu_R[rd], 0x0);
+ }
+ break;
+
+ case 0x02: /*lf.mul.s*/
+ LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb);
+ if (cpu_R[ra] != 0 && cpu_R[rb] != 0) {
+ gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ } else {
+ tcg_gen_ori_tl(fpcsr, fpcsr, FPCSR_ZF);
+ tcg_gen_movi_i32(cpu_R[rd], 0x0);
+ }
+ break;
+
+ case 0x13: /*lf.div.d*/
+ LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x03: /*lf.div.s*/
+ LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x14: /*lf.itof.d*/
+ LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+ gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]);
+ break;
+
+ case 0x04: /*lf.itof.s*/
+ LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+ gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]);
+ break;
+
+ case 0x15: /*lf.ftoi.d*/
+ LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+ gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]);
+ break;
+
+ case 0x05: /*lf.ftoi.s*/
+ LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+ gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]);
+ break;
+
+ case 0x16: /*lf.rem.d*/
+ LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x06: /*lf.rem.s*/
+ LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x17: /*lf.madd.d*/
+ LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_muladd_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x07: /*lf.madd.s*/
+ LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_muladd_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x18: /*lf.sfeq.d*/
+ LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
+ gen_helper_float_eq_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x08: /*lf.sfeq.s*/
+ LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
+ gen_helper_float_eq_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x19: /*lf.sfne.d*/
+ LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
+ gen_helper_float_ne_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x09: /*lf.sfne.s*/
+ LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
+ gen_helper_float_ne_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x1a: /*lf.sfgt.d*/
+ LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
+ gen_helper_float_gt_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x0a: /*lf.sfgt.s*/
+ LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
+ gen_helper_float_gt_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x1b: /*lf.sfge.d*/
+ LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
+ gen_helper_float_ge_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x0b: /*lf.sfge.s*/
+ LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
+ gen_helper_float_ge_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x1c: /*lf.sflt.d*/
+ LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
+ gen_helper_float_lt_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x0c: /*lf.sflt.s*/
+ LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
+ gen_helper_float_lt_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x1d: /*lf.sfle.d*/
+ LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
+ gen_helper_float_le_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x0d: /*lf.sfle.s*/
+ LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
+ gen_helper_float_le_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ wb_SR_F();
+}
+
+static void disas_openrisc_insn(DisasContext *dc, CPUOpenriscState *env)
+{
+ uint32_t op0;
+ uint32_t insn;
+ insn = cpu_ldl_code(env, dc->pc);
+ op0 = field(insn, 26, 6);
+
+ switch (op0) {
+ case 0x06:
+ dec_M(dc, env, insn);
+ break;
+
+ case 0x08:
+ dec_sys(dc, env, insn);
+ break;
+
+ case 0x2e:
+ dec_logic(dc, env, insn);
+ break;
+
+ case 0x2f:
+ dec_compi(dc, env, insn);
+ break;
+
+ case 0x31:
+ dec_mac(dc, env, insn);
+ break;
+
+ case 0x32:
+ dec_float(dc, env, insn);
+ break;
+
+ case 0x38:
+ dec_calc(dc, env, insn);
+ break;
+
+ case 0x39:
+ dec_comp(dc, env, insn);
+ break;
+
+ default:
+ dec_misc(dc, env, insn);
+ break;
+ }
+}
+
+static void check_breakpoint(CPUOpenriscState *env, DisasContext *dc)
+{
+ CPUBreakpoint *bp;
+
+ if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
+ QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+ if (bp->pc == dc->pc) {
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ gen_exception(dc, EXCP_DEBUG);
+ dc->is_jmp = DISAS_UPDATE;
+ }
+ }
+ }
}

static inline void gen_intermediate_code_internal(CPUOpenriscState *env,
TranslationBlock *tb,
int search_pc)
{
+ struct DisasContext ctx, *dc = &ctx;
+ uint16_t *gen_opc_end;
+ uint32_t pc_start;
+ int j, k;
+ uint32_t next_page_start;
+ int num_insns;
+ int max_insns;
+
+ qemu_log_try_set_file(stderr);
+
+ pc_start = tb->pc;
+ dc->env = env;
+ dc->tb = tb;
+
+ gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+ dc->is_jmp = DISAS_NEXT;
+ dc->ppc = pc_start;
+ dc->pc = pc_start;
+ dc->mem_idx = cpu_mmu_index(env);
+ dc->synced_flags = dc->tb_flags = tb->flags;
+ dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
+ dc->singlestep_enabled = env->singlestep_enabled;
+ if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+ qemu_log("-----------------------------------------\n");
+ log_cpu_state(env, 0);
+ }
+
+ next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+ k = -1;
+ num_insns = 0;
+ max_insns = tb->cflags & CF_COUNT_MASK;
+
+ if (max_insns == 0) {
+ max_insns = CF_COUNT_MASK;
+ }
+
+ gen_icount_start();
+
+ do {
+ check_breakpoint(env, dc);
+ if (search_pc) {
+ j = gen_opc_ptr - gen_opc_buf;
+ if (k < j) {
+ k++;
+ while (k < j) {
+ gen_opc_instr_start[k++] = 0;
+ }
+ }
+ gen_opc_pc[k] = dc->pc;
+ gen_opc_instr_start[k] = 1;
+ gen_opc_icount[k] = num_insns;
+ }
+
+ if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
+ tcg_gen_debug_insn_start(dc->pc);
+ }
+
+ if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ gen_io_start();
+ }
+ dc->ppc = dc->pc - 4;
+ dc->npc = dc->pc + 4;
+ tcg_gen_movi_tl(cpu_ppc, dc->ppc);
+ tcg_gen_movi_tl(cpu_npc, dc->npc);
+ disas_openrisc_insn(dc, env);
+ dc->pc = dc->npc;
+ num_insns++;
+ /* delay slot */
+ if (dc->delayed_branch) {
+ dc->delayed_branch--;
+ if (!dc->delayed_branch) {
+ dc->tb_flags &= ~D_FLAG;
+ gen_sync_flags(dc);
+ tcg_gen_mov_tl(cpu_pc, jmp_pc);
+ tcg_gen_mov_tl(cpu_npc, jmp_pc);
+ tcg_gen_movi_tl(jmp_pc, 0);
+ tcg_gen_exit_tb(0);
+ dc->is_jmp = DISAS_JUMP;
+ break;
+ }
+ }
+ } while (!dc->is_jmp
+ && gen_opc_ptr < gen_opc_end
+ && !env->singlestep_enabled
+ && !singlestep
+ && (dc->pc < next_page_start)
+ && num_insns < max_insns);
+
+ if (tb->cflags & CF_LAST_IO) {
+ gen_io_end();
+ }
+ if (dc->is_jmp == DISAS_NEXT) {
+ dc->is_jmp = DISAS_UPDATE;
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ }
+ if (unlikely(env->singlestep_enabled)) {
+ if (dc->is_jmp == DISAS_NEXT) {
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ }
+ gen_exception(dc, EXCP_DEBUG);
+ } else {
+ switch (dc->is_jmp) {
+ case DISAS_NEXT:
+ gen_goto_tb(dc, 0, dc->pc);
+ break;
+ default:
+ case DISAS_JUMP:
+ break;
+ case DISAS_UPDATE:
+ /* indicate that the hash table must be used
+ to find the next TB */
+ tcg_gen_exit_tb(0);
+ break;
+ case DISAS_TB_JUMP:
+ /* nothing more to generate */
+ break;
+ }
+ }
+
+ gen_icount_end(tb, num_insns);
+ *gen_opc_ptr = INDEX_op_end;
+ if (search_pc) {
+ j = gen_opc_ptr - gen_opc_buf;
+ k++;
+ while (k <= j) {
+ gen_opc_instr_start[k++] = 0;
+ }
+ } else {
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
+ }
+
+#ifdef DEBUG_DISAS
+ if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+ qemu_log("\n");
+ log_target_disas(pc_start, dc->pc - pc_start, 0);
+ qemu_log("\nisize=%d osize=%td\n",
+ dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
+ }
+#endif
}

void gen_intermediate_code(CPUOpenriscState *env, struct TranslationBlock *tb)
@@ -51,7 +1466,13 @@ void cpu_dump_state(CPUOpenriscState *env, FILE *f,
fprintf_function cpu_fprintf,
int flags)
{
+ int i;
+ uint32_t *regs = env->gpr;
cpu_fprintf(f, "PC=%08x\n", env->pc);
+ for (i = 0; i < 32; ++i) {
+ cpu_fprintf(f, "R%02d=%08x%c", i, regs[i],
+ (i % 4) == 3 ? '\n' : ' ');
+ }
}

void restore_state_to_opc(CPUOpenriscState *env, TranslationBlock *tb,
--
1.7.9.5
Max Filippov
2012-05-28 11:38:21 UTC
Permalink
Hi Jia.
Post by Jia Liu
add openrisc instruction translation routines.
---
 target-openrisc/translate.c | 1421 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1421 insertions(+)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 5bbad9e..965fa0e 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -26,14 +26,1429 @@
 #include "qemu-log.h"
 #include "config.h"
+#include "helper.h"
+#define GEN_HELPER 1
+#include "helper.h"
+
+#define DISAS_OPENRISC 1
+#if DISAS_OPENRISC
+#  define LOG_DIS(...) do { } while (0)
+#endif
+
+typedef struct DisasContext {
+    CPUOpenriscState *env;
+    TranslationBlock *tb;
+    target_ulong pc, ppc, npc;
+    uint32_t tb_flags, synced_flags;
+    uint32_t is_jmp;
+    uint32_t mem_idx;
+    int singlestep_enabled;
+    uint32_t delayed_branch;
+} DisasContext;
+
+static TCGv_ptr cpu_env;
+static TCGv cpu_sr;
+static TCGv cpu_R[32];
+static TCGv cpu_pc;
+static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
+static TCGv cpu_npc;
+static TCGv cpu_ppc;
+static TCGv_i32 env_btaken;    /* bf/bnf , F flag taken */
+static TCGv_i32 fpcsr;
+static TCGv machi, maclo;
+static TCGv fpmaddhi, fpmaddlo;
+static TCGv_i32 env_flags;
+#include "gen-icount.h"
+
 void openrisc_translate_init(void)
 {
+    static const char * const regnames[] = {
+        "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+        "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+        "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+        "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+    };
+    int i;
+
+    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    cpu_sr = tcg_global_mem_new(TCG_AREG0,
+                                offsetof(CPUOpenriscState, sr), "sr");
+    env_flags = tcg_global_mem_new_i32(TCG_AREG0,
+                                       offsetof(CPUOpenriscState, flags),
+                                       "flags");
+    cpu_pc = tcg_global_mem_new(TCG_AREG0,
+                                offsetof(CPUOpenriscState, pc), "pc");
+    cpu_npc = tcg_global_mem_new(TCG_AREG0,
+                                 offsetof(CPUOpenriscState, npc), "npc");
+    cpu_ppc = tcg_global_mem_new(TCG_AREG0,
+                                 offsetof(CPUOpenriscState, ppc), "ppc");
+    jmp_pc = tcg_global_mem_new(TCG_AREG0,
+                                offsetof(CPUOpenriscState, jmp_pc), "jmp_pc");
+    env_btaken = tcg_global_mem_new_i32(TCG_AREG0,
+                                        offsetof(CPUOpenriscState, btaken),
+                                        "btaken");
+    fpcsr = tcg_global_mem_new_i32(TCG_AREG0,
+                                   offsetof(CPUOpenriscState, fpcsr),
+                                   "fpcsr");
+    machi = tcg_global_mem_new(TCG_AREG0,
+                               offsetof(CPUOpenriscState, machi),
+                               "machi");
+    maclo = tcg_global_mem_new(TCG_AREG0,
+                               offsetof(CPUOpenriscState, maclo),
+                               "maclo");
+    fpmaddhi = tcg_global_mem_new(TCG_AREG0,
+                                  offsetof(CPUOpenriscState, fpmaddhi),
+                                  "fpmaddhi");
+    fpmaddlo = tcg_global_mem_new(TCG_AREG0,
+                                  offsetof(CPUOpenriscState, fpmaddlo),
+                                  "fpmaddlo");
+    for (i = 0; i < 32; i++) {
+        cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
+                                      offsetof(CPUOpenriscState, gpr[i]),
+                                      regnames[i]);
+    }
+#define GEN_HELPER 2
+#include "helper.h"
+}
+
+/* Writeback SR_F transaltion-space to execution-space.  */
+static inline void wb_SR_F(void)
+{
+    int label;
+
+    label = gen_new_label();
+    tcg_gen_andi_tl(cpu_sr, cpu_sr, ~SR_F);
+    tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, label);
+    tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_F);
+    gen_set_label(label);
+}
+
+static inline int zero_extend(unsigned int val, int width)
+{
+    return val & ((1 << width) - 1);
+}
+
+static inline int sign_extend(unsigned int val, int width)
+{
+    int sval;
+
+    /* LSL.  */
+    val <<= 32 - width;
+    sval = val;
+    /* ASR.  */
+    sval >>= 32 - width;
There should be TARGET_LONG_BITS instead of 32, as you use this function
with tcg_gen_*_tl.
Post by Jia Liu
+    return sval;
+}
+
+static inline void gen_sync_flags(DisasContext *dc)
+{
+    /* Sync the tb dependent flag between translate and runtime.  */
+    if (dc->tb_flags != dc->synced_flags) {
+        tcg_gen_movi_tl(env_flags, dc->tb_flags);
+        dc->synced_flags = dc->tb_flags;
+    }
+}
+
+static void gen_exception(DisasContext *dc, unsigned int excp)
+{
+    TCGv_i32 tmp = tcg_const_i32(excp);
+    gen_helper_exception(cpu_env, tmp);
+    tcg_temp_free(tmp);
+}
+
+static void gen_illegal_exception(DisasContext *dc)
+{
+    tcg_gen_movi_tl(cpu_pc, dc->pc);
+    gen_exception(dc, EXCP_ILLEGAL);
+    dc->is_jmp = DISAS_UPDATE;
+}
+
+static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
+{
+    TranslationBlock *tb;
+    tb = dc->tb;
+    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
+                                       likely(!dc->singlestep_enabled)) {
+        tcg_gen_movi_tl(cpu_pc, dest);
+        tcg_gen_goto_tb(n);
+        tcg_gen_exit_tb((tcg_target_long)tb + n);
+    } else {
+        tcg_gen_movi_tl(cpu_pc, dest);
+        if (dc->singlestep_enabled) {
+            gen_exception(dc, EXCP_DEBUG);
+        }
+        tcg_gen_exit_tb(0);
+    }
+}
+
+static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
+{
+    target_ulong tmp_pc;
+    int lab = gen_new_label();
+    TCGv sr_f = tcg_temp_new();
+    /* N26, 26bits imm */
+    tmp_pc = sign_extend((imm<<2), 26) + dc->pc;
+    tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+
+    if (op0 == 0x0) {
+        /*l.j*/
+        tcg_gen_movi_tl(jmp_pc, tmp_pc);
+    } else if (op0 == 0x1) {
+        /*l.jal*/
+        tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+        tcg_gen_movi_tl(jmp_pc, tmp_pc);
+    } else if (op0 == 0x3) {
+        /*l.bnf*/
+        tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+        tcg_gen_brcondi_i32(TCG_COND_EQ, sr_f, SR_F, lab);
+        tcg_gen_movi_tl(jmp_pc, tmp_pc);
+        gen_set_label(lab);
+    } else if (op0 == 0x4) {
+        /*l.bf*/
+        tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+        tcg_gen_brcondi_i32(TCG_COND_NE, sr_f, SR_F, lab);
+        tcg_gen_movi_tl(jmp_pc, tmp_pc);
+        gen_set_label(lab);
+    } else if (op0 == 0x11) {
+        /*l.jr*/
+        tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
+    } else if (op0 == 0x12) {
+        /*l.jalr*/
+        tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+        tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
+    } else {
+        gen_illegal_exception(dc);
+    }
+
+    tcg_temp_free(sr_f);
+    dc->delayed_branch = 2;
+    dc->tb_flags |= D_FLAG;
+    gen_sync_flags(dc);
+}
+
+static inline uint32_t field(uint32_t val, int start, int length)
+{
+    val >>= start;
+    val &= ~(~0 << length);
+    return val;
+}
+
+static void dec_calc(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0, op1, op2;
+    uint32_t ra, rb, rd;
+    op0 = field(insn, 0, 4);
+    op1 = field(insn, 8, 2);
+    op2 = field(insn, 6, 2);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+    rd = field(insn, 21, 5);
+
+    switch (op0) {
+        switch (op1) {
+        case 0x00:     /*l.add*/
+            LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb);
+            gen_helper_add(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+    break;
+
+    case 0x0001:    /*l.addc*/
+        switch (op1) {
+            LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
+            gen_helper_addc(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+    break;
+
+    case 0x0002:    /*l.sub*/
+        switch (op1) {
+            LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
+            gen_helper_sub(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+    break;
+
+    case 0x0003:   /*l.and*/
+        switch (op1) {
+            LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb);
+            tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+    break;
+
+    case 0x0004:   /*l.or*/
+        switch (op1) {
+            LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb);
+            tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+    break;
+
+        switch (op1) {
+        case 0x00:   /*l.xor*/
+            LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb);
+            tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+    break;
+
+        switch (op1) {
+        case 0x03:   /*l.mul*/
+            LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb);
+            if (ra != 0 && rb != 0) {
+                gen_helper_mul(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0x0);
+            }
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+    break;
+
+        switch (op1) {
+        case 0x03:   /*l.div*/
+            LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
+            if (rb == 0) {
+                TCGv_i32 sr_ove;
+                int lab = gen_new_label();
+                sr_ove = tcg_temp_new();
+                tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV);
+                tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY);
+                tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+                tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab);
+                gen_exception(dc, EXCP_RANGE);
+                gen_set_label(lab);
+                tcg_temp_free(sr_ove);
+            } else if (rb != 0) {
'if (rb != 0)' is redundant here.
You need similar handling here for the case 'rb contains 0' as in the
'if' block above.
You also need to handle the case 'ra contains 0x80000000, rb contains
0xffffffff' here,
as it will cause integer overflow.
Post by Jia Liu
+                tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                break;
+            }
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        switch (op1) {
+        case 0x03:   /*l.divu*/
+            LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb);
+            if (rb == 0) {
+                TCGv_i32 sr_ove;
+                int lab = gen_new_label();
+                sr_ove = tcg_temp_new();
+                tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV);
+                tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY);
+                tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+                tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab);
+                gen_exception(dc, EXCP_RANGE);
+                gen_set_label(lab);
+                tcg_temp_free(sr_ove);
+            } else if (rb != 0) {
'if (rb != 0)' is redundant here.
You need similar handling here for the case 'rb contains 0' as in the
'if' block above.
Post by Jia Liu
+                tcg_gen_extu_i32_tl(cpu_R[ra], cpu_R[ra]);
+                tcg_gen_extu_i32_tl(cpu_R[rb], cpu_R[rb]);
These extu's are not needed, they are no-op in 32 bit wide register case,
and they clobber ra and rb and yield wrong result in 64 bit wide register case.
Post by Jia Liu
+                tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                break;
+            }
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        switch (op1) {
+        case 0x03:   /*l.mulu*/
+            LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb);
+            if (rb != 0 && ra != 0) {
+                TCGv_i64 result = tcg_temp_new();
+                TCGv_i32 high = tcg_temp_new();
+                TCGv_i32 sr_ove = tcg_temp_new();
+                int lab = gen_new_label();
+                int lab2 = gen_new_label();
+                tcg_gen_extu_i32_tl(cpu_R[ra], cpu_R[ra]);
+                tcg_gen_extu_i32_tl(cpu_R[rb], cpu_R[rb]);
These extu's are not needed, they are no-op in 32 bit wide register case,
and they clobber ra and rb and yield wrong result in 64 bit wide register case.
Post by Jia Liu
+                tcg_gen_mul_tl(result, cpu_R[ra], cpu_R[rb]);
This is wrong, all three mul parameters must have the same width. If you need
wider result, please use corresponding width temporaries and explicit mul_i64
Post by Jia Liu
+                tcg_gen_shri_tl(high, result, (sizeof(target_ulong) * 8));
Ditto.
Post by Jia Liu
+                tcg_gen_brcondi_tl(TCG_COND_EQ, high, 0x0, lab);
+                tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY);
+                tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV);
+                tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+                tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab2);
When this branch is taken the multiplication result is not written to cpu_R[rd],
is that correct?
Post by Jia Liu
+                gen_exception(dc, EXCP_RANGE);
+                gen_set_label(lab);
+                tcg_gen_trunc_i64_tl(cpu_R[rd], result);
+                gen_set_label(lab2);
+                tcg_temp_free(result);
+                tcg_temp_free(high);
+                tcg_temp_free(sr_ove);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0);
+            }
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        switch (op1) {
+        case 0x00:   /*l.cmov*/
+            LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb);
+            {
+                int lab = gen_new_label();
+                TCGv sr_f = tcg_temp_new();
+                tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+                tcg_gen_mov_tl(cpu_R[rd], cpu_R[rb]);
+                tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
+                tcg_gen_mov_tl(cpu_R[rd], cpu_R[ra]);
+                gen_set_label(lab);
+                tcg_temp_free(sr_f);
In case rd == ra and SR_F == 0 the result is wrong here.
It may be rewritten as

int lab = gen_new_label();
TCGv res = tcg_temp_new();
TCGv sr_f = tcg_temp_new();
tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
tcg_gen_mov_tl(res, cpu_R[rb]);
tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
tcg_gen_mov_tl(res, cpu_R[ra]);
gen_set_label(lab);
tcg_gen_mov_tl(cpu_R[rd], res);
tcg_temp_free(res);
tcg_temp_free(sr_f);
Post by Jia Liu
+            }
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        switch (op1) {
+        case 0x00:   /*l.ff1*/
+            LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
+            gen_helper_ff1(cpu_R[rd], cpu_R[ra]);
+            break;
+        case 0x01:   /*l.fl1*/
+            LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
+            gen_helper_fl1(cpu_R[rd], cpu_R[ra]);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        switch (op1) {
+            switch (op2) {
+            case 0x00:   /*l.sll*/
+                LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb);
+                tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                break;
+            case 0x01:   /*l.srl*/
+                LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb);
+                tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                break;
+            case 0x02:   /*l.sra*/
+                LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb);
+                tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                break;
+            case 0x03:   /*l.ror*/
+                LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb);
+                tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                break;
+                gen_illegal_exception(dc);
+                break;
+            }
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        switch (op1) {
+            switch (op2) {
+            case 0x00:   /*l.exths*/
+                LOG_DIS("l.exths r%d, r%d\n", rd, ra);
+                tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]);
+                break;
+            case 0x01:   /*l.extbs*/
+                LOG_DIS("l.extbs r%d, r%d\n", rd, ra);
+                tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]);
+                break;
+            case 0x02:   /*l.exthz*/
+                LOG_DIS("l.exthz r%d, r%d\n", rd, ra);
+                tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]);
+                break;
+            case 0x03:   /*l.extbz*/
+                LOG_DIS("l.extbz r%d, r%d\n", rd, ra);
+                tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]);
+                break;
+                gen_illegal_exception(dc);
+                break;
+            }
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        switch (op1) {
+            switch (op2) {
+            case 0x00:   /*l.extws*/
+                LOG_DIS("l.extws r%d, r%d\n", rd, ra);
+                tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]);
+                break;
+            case 0x01:    /*l.extwz*/
+                LOG_DIS("l.extwz r%d, r%d\n", rd, ra);
+                tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]);
+                break;
+                gen_illegal_exception(dc);
+                break;
+            }
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+    }
+}
+
+static void dec_misc(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0, op1;
+    uint32_t ra, rb, rd;
+    uint32_t /*L6, K5, */I16, I5, I11, N26, tmp;
+    op0 = field(insn, 26, 6);
+    op1 = field(insn, 24, 2);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+    rd = field(insn, 21, 5);
+    /*L6 = field(insn, 5, 6);
+    K5 = field(insn, 0, 5);*/
+    I16 = field(insn, 0, 16);
+    I5 = field(insn, 21, 5);
+    I11 = field(insn, 0, 11);
+    N26 = field(insn, 0, 26);
+    tmp = (I5<<11) + I11;
+    TCGv t0 = tcg_temp_new();
+
+    switch (op0) {
+    case 0x00:   /*l.j*/
+        LOG_DIS("l.j %d\n", N26);
+    case 0x01:   /*l.jal*/
+        LOG_DIS("l.jal %d\n", N26);
+    case 0x03:   /*l.bnf*/
+        LOG_DIS("l.bnf %d\n", N26);
+    case 0x04:   /*l.bf*/
+        LOG_DIS("l.bf %d\n", N26);
+
+        gen_jump(dc, N26, 0, op0);
+        break;
+
+        switch (op1) {
+        case 0x01:   /*l.nop*/
+            LOG_DIS("l.nop %d\n", I16);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+    case 0x11:    /*l.jr*/
+        LOG_DIS("l.jr r%d\n", rb);
+    case 0x12:    /*l.jalr*/
+        LOG_DIS("l.jalr r%d\n", rb);
+
+        gen_jump(dc, 0, rb, op0);
+        break;
+
+    case 0x13:    /*l.maci*/
+        LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I11);
+        {
+            TCGv_i64 tra = tcg_temp_new_i64();    /*  store cpu_R[ra]*/
+            TCGv_i64 tmac = tcg_temp_new_i64();   /*  store machi maclo*/
+            tcg_gen_movi_tl(t0, tmp);
+            tcg_gen_ext32s_i64(tra, cpu_R[ra]);
+            tcg_gen_ext32s_i64(tmac, t0);
+            tcg_gen_mul_tl(tmac, tra, tmac);
+            tcg_gen_trunc_i64_i32(cpu_R[ra], tmac);
+            tcg_gen_add_i64(machi, machi, cpu_R[ra]);
+            tcg_gen_add_i64(maclo, maclo, cpu_R[ra]);
This needs the same treatment as l.mac.
Post by Jia Liu
+            tcg_temp_free(tra);
+            tcg_temp_free(tmac);
+        }
+        break;
+
+    case 0x09:    /*l.rfe*/
+        LOG_DIS("l.rfe\n");
+        {
+            gen_helper_rfe(cpu_env);
+            dc->is_jmp = DISAS_UPDATE;
+        }
+        break;
+
+    case 0x1c:    /*l.cust1*/
+        LOG_DIS("l.cust1\n");
+        break;
+
+    case 0x1d:    /*l.cust2*/
+        LOG_DIS("l.cust2\n");
+        break;
+
+    case 0x1e:    /*l.cust3*/
+        LOG_DIS("l.cust3\n");
+        break;
+
+    case 0x1f:    /*l.cust4*/
+        LOG_DIS("l.cust4\n");
+        break;
+
+    case 0x3c:   /*l.cust5*/
+        /*LOG_DIS("l.cust5 r%d, r%d, r%d, %d, %d\n", rd, ra, rb, L6, K5);*/
+        break;
+
+    case 0x3d:   /*l.cust6*/
+        LOG_DIS("l.cust6\n");
+        break;
+
+    case 0x3e:   /*l.cust7*/
+        LOG_DIS("l.cust7\n");
+        break;
+
+    case 0x3f:   /*l.cust8*/
+        LOG_DIS("l.cust8\n");
+        break;
+
+    case 0x20:   /*l.ld*/
+        LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_qemu_ld64(cpu_R[rd], t0, dc->mem_idx);
+        break;
+
+    case 0x21:   /*l.lwz*/
+        LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_qemu_ld32u(cpu_R[rd], t0, dc->mem_idx);
+        break;
+
+    case 0x22:   /*l.lws*/
+        LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_qemu_ld32s(cpu_R[rd], t0, dc->mem_idx);
+        break;
+
+    case 0x23:   /*l.lbz*/
+        LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_qemu_ld8u(cpu_R[rd], t0, dc->mem_idx);
+        break;
+
+    case 0x24:   /*l.lbs*/
+        LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_qemu_ld8s(cpu_R[rd], t0, dc->mem_idx);
+        break;
+
+    case 0x25:   /*l.lhz*/
+        LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_qemu_ld16u(cpu_R[rd], t0, dc->mem_idx);
+        break;
+
+    case 0x26:   /*l.lhs*/
+        LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_qemu_ld16s(cpu_R[rd], t0, dc->mem_idx);
+        break;
+
+    case 0x27:   /*l.addi*/
+        LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
+        {
+            TCGv t0 = tcg_const_tl(sign_extend(I16, 16));
+            gen_helper_add(cpu_R[rd], cpu_env, cpu_R[ra], t0);
+            tcg_temp_free(t0);
+        }
+        break;
+
+    case 0x28:   /*l.addic*/
+        LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16);
+        {
+            TCGv t0 = tcg_const_tl(sign_extend(I16, 16));
+            gen_helper_addc(cpu_R[rd], cpu_env, cpu_R[ra], t0);
+            tcg_temp_free(t0);
+        }
+        break;
+
+    case 0x29:   /*l.andi*/
+        LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], zero_extend(I16, 16));
+        break;
+
+    case 0x2a:   /*l.ori*/
+        LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, zero_extend(I16, 16));
+        tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], I16);
+        break;
+
+    case 0x2b:   /*l.xori*/
+        LOG_DIS("l.xori r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], sign_extend(I16, 16));
+        break;
+
+    case 0x2c:   /*l.muli*/
+        LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16);
+        if (ra != 0 && I16 != 0) {
+            TCGv i16 = tcg_const_tl(I16);
+            gen_helper_mul(cpu_R[rd], cpu_env, cpu_R[ra], i16);
+            tcg_temp_free(i16);
+        } else {
+            tcg_gen_movi_tl(cpu_R[rd], 0x0);
+        }
+        break;
+
+    case 0x2d:   /*l.mfspr*/
+        LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
+        break;
+
+    case 0x30:  /*l.mtspr*/
+        LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        break;
+
+    case 0x34:   /*l.sd*/
+        LOG_DIS("l.sd %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+        tcg_gen_qemu_st64(cpu_R[rb], t0, dc->mem_idx);
+        break;
+
+    case 0x35:   /*l.sw*/
+        LOG_DIS("l.sw %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+        tcg_gen_qemu_st32(cpu_R[rb], t0, dc->mem_idx);
+        break;
+
+    case 0x36:   /*l.sb*/
+        LOG_DIS("l.sb %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+        tcg_gen_qemu_st8(cpu_R[rb], t0, dc->mem_idx);
+        break;
+
+    case 0x37:   /*l.sh*/
+        LOG_DIS("l.sh %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+        tcg_gen_qemu_st16(cpu_R[rb], t0, dc->mem_idx);
+        break;
+        gen_illegal_exception(dc);
+        break;
+    }
+    tcg_temp_free(t0);
+}
+
+static void dec_mac(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t ra, rb;
+    op0 = field(insn, 0, 4);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+    TCGv_i64 t0 = tcg_temp_new();
+    TCGv_i64 t1 = tcg_temp_new();
+    TCGv_i64 t2 = tcg_temp_new();
+    switch (op0) {
+    case 0x0001:   /*l.mac*/
+        LOG_DIS("l.mac r%d, r%d\n", ra, rb);
+        {
+            tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]);
+            tcg_gen_ext_i32_i64(t1, t0);
+            tcg_gen_concat_i32_i64(t2, maclo, machi);
+            tcg_gen_add_i64(t2, t2, t1);
+            tcg_gen_trunc_i64_i32(maclo, t2);
+            tcg_gen_shri_i64(t2, t2, 32);
+            tcg_gen_trunc_i64_i32(machi, t2);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+            tcg_temp_free(t2);
+        }
+        break;
+
+    case 0x0002:   /*l.msb*/
+        LOG_DIS("l.msb r%d, r%d\n", ra, rb);
+        {
+            tcg_gen_ext_i32_i64(t0, cpu_R[ra]);
+            tcg_gen_ext_i32_i64(t1, cpu_R[rb]);
+            tcg_gen_mul_i64(t0, t0, t1);
+            tcg_gen_trunc_i64_i32(cpu_R[ra], t0);
+            tcg_gen_sub_i32(maclo, maclo, cpu_R[ra]);
+            tcg_gen_sub_i32(machi, machi, cpu_R[ra]);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
This needs the same treatment as l.mac.
Post by Jia Liu
+        }
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+   }
+}
+
+static void dec_logic(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t rd, ra, L6;
+    op0 = field(insn, 6, 2);
+    rd = field(insn, 21, 5);
+    ra = field(insn, 16, 5);
+    L6 = field(insn, 0, 6);
+
+    switch (op0) {
+    case 0x00:    /*l.slli*/
+        LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6);
+        tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+        break;
+
+    case 0x01:    /*l.srli*/
+        LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6);
+        tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+        break;
+
+    case 0x02:    /*l.srai*/
+        LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6);
+        tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f)); break;
+
+    case 0x03:    /*l.rori*/
+        LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6);
+        tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+    }
+}
+
+static void dec_M(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t rd;
+    uint32_t K16;
+    op0 = field(insn, 16, 1);
+    rd = field(insn, 21, 5);
+    K16 = field(insn, 0, 16);
+
+    switch (op0) {
+    case 0x0:    /*l.movhi*/
+        LOG_DIS("l.movhi  r%d, %d\n", rd, K16);
+        tcg_gen_movi_tl(cpu_R[rd], (K16 << 16));
+        break;
+
+    case 0x1:    /*l.macrc*/
+        LOG_DIS("l.macrc  r%d\n", rd);
+        tcg_gen_mov_tl(cpu_R[rd], maclo);
+        tcg_gen_movi_tl(maclo, 0x0);
+        tcg_gen_movi_tl(machi, 0x0);
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+    }
+}
+
+static void dec_comp(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t ra, rb;
+
+    op0 = field(insn, 21, 5);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+
+    tcg_gen_movi_i32(env_btaken, 0x0);
+    /* unsigned integers  */
+    tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+    tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
These extu's are not needed, they are no-op in 32 bit wide register case,
and they clobber ra and rb in 64 bit wide register case. Comparison signedness
is chosen by TCG_COND_* constants below.
Post by Jia Liu
+    switch (op0) {
+    case 0x0:    /*l.sfeq*/
+        LOG_DIS("l.sfeq  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1:    /*l.sfne*/
+        LOG_DIS("l.sfne  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x2:    /*l.sfgtu*/
+        LOG_DIS("l.sfgtu  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GTU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x3:    /*l.sfgeu*/
+        LOG_DIS("l.sfgeu  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GEU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x4:    /*l.sfltu*/
+        LOG_DIS("l.sfltu  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LTU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x5:    /*l.sfleu*/
+        LOG_DIS("l.sfleu  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0xa:    /*l.sfgts*/
+        LOG_DIS("l.sfgts  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0xb:    /*l.sfges*/
+        LOG_DIS("l.sfges  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0xc:    /*l.sflts*/
+        LOG_DIS("l.sflts  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0xd:    /*l.sfles*/
+        LOG_DIS("l.sfles  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+    }
+    wb_SR_F();
+}
+
+static void dec_compi(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t ra, I16;
+
+    op0 = field(insn, 21, 5);
+    ra = field(insn, 16, 5);
+    I16 = field(insn, 0, 16);
+
+    tcg_gen_movi_i32(env_btaken, 0x0);
+    tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
This extu is not needed, it is no-op in 32 bit wide register case,
and it clobbers ra in 64 bit wide register case. Comparison signedness
is chosen by TCG_COND_* constants below.
Post by Jia Liu
+    I16 = sign_extend(I16, 16);
+
+    switch (op0) {
+    case 0x0:    /*l.sfeqi*/
+        LOG_DIS("l.sfeqi  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0x1:    /*l.sfnei*/
+        LOG_DIS("l.sfnei  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_NE, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0x2:    /*l.sfgtui*/
+        LOG_DIS("l.sfgtui  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_GTU, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0x3:    /*l.sfgeui*/
+        LOG_DIS("l.sfgeui  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_GEU, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0x4:    /*l.sfltui*/
+        LOG_DIS("l.sfltui  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_LTU, env_btaken, cpu_R[ra],
+                            sign_extend(I16, 16));
Redundant sign_extend.
Post by Jia Liu
+        break;
+
+    case 0x5:    /*l.sfleui*/
+        LOG_DIS("l.sfleui  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0xa:    /*l.sfgtsi*/
+        LOG_DIS("l.sfgtsi  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_GT, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0xb:    /*l.sfgesi*/
+        LOG_DIS("l.sfgesi  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_GE, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0xc:    /*l.sfltsi*/
+        LOG_DIS("l.sfltsi  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_LT, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0xd:    /*l.sflesi*/
+        LOG_DIS("l.sflesi  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_LE, env_btaken, cpu_R[ra], I16);
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+    }
+    wb_SR_F();
+}
+
+static void dec_sys(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0;
+    /*uint32_t K16;*/
+    op0 = field(insn, 16, 8);
+    /*K16 = field(insn, 0, 16);*/
+
+    switch (op0) {
+    case 0x000:  /*l.sys*/
+        /*LOG_DIS("l.sys %d\n", K16);*/
+        tcg_gen_movi_tl(cpu_pc, dc->pc);
+        gen_exception(dc, EXCP_SYSCALL);
+        dc->is_jmp = DISAS_UPDATE;
+        break;
+
+    case 0x100:  /*l.trap*/
+        /*LOG_DIS("l.trap %d\n", K16);*/
+        tcg_gen_movi_tl(cpu_pc, dc->pc);
+        gen_exception(dc, EXCP_TRAP);
+        break;
+
+    case 0x300:  /*l.csync*/
+        LOG_DIS("l.csync\n");
+        break;
+
+    case 0x200:  /*l.msync*/
+        LOG_DIS("l.msync\n");
+        break;
+
+    case 0x270:  /*l.psync*/
+        LOG_DIS("l.psync\n");
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+    }
+}
+
+static void dec_float(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t ra, rb, rd;
+    op0 = field(insn, 0, 8);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+    rd = field(insn, 21, 5);
+
+    switch (op0) {
+    case 0x10:    /*lf.add.d*/
+        LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x00:    /*lf.add.s*/
+        LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x11:    /*lf.sub.d*/
+        LOG_DIS("lf.sub.d r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_sub_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x01:    /*lf.sub.s*/
+        LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x12:    /*lf.mul.d*/
+        LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb);
+        if (cpu_R[ra] != 0 && cpu_R[rb] != 0) {
Should be "if (ra != 0 && rb != 0)".
Post by Jia Liu
+            gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        } else {
+            tcg_gen_ori_tl(fpcsr, fpcsr, FPCSR_ZF);
+            tcg_gen_movi_i64(cpu_R[rd], 0x0);
+        }
+        break;
+
+    case 0x02:    /*lf.mul.s*/
+        LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb);
+        if (cpu_R[ra] != 0 && cpu_R[rb] != 0) {
Ditto.
Post by Jia Liu
+            gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        } else {
+            tcg_gen_ori_tl(fpcsr, fpcsr, FPCSR_ZF);
+            tcg_gen_movi_i32(cpu_R[rd], 0x0);
+        }
+        break;
+
+    case 0x13:    /*lf.div.d*/
+        LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x03:    /*lf.div.s*/
+        LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x14:    /*lf.itof.d*/
+        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+        gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]);
+        break;
+
+    case 0x04:    /*lf.itof.s*/
+        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+        gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]);
+        break;
+
+    case 0x15:    /*lf.ftoi.d*/
+        LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+        gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]);
+        break;
+
+    case 0x05:    /*lf.ftoi.s*/
+        LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+        gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]);
+        break;
+
+    case 0x16:    /*lf.rem.d*/
+        LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x06:    /*lf.rem.s*/
+        LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x17:    /*lf.madd.d*/
+        LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_muladd_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x07:    /*lf.madd.s*/
+        LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_muladd_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x18:    /*lf.sfeq.d*/
+        LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
+        gen_helper_float_eq_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x08:    /*lf.sfeq.s*/
+        LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
+        gen_helper_float_eq_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x19:    /*lf.sfne.d*/
+        LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
+        gen_helper_float_ne_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x09:    /*lf.sfne.s*/
+        LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
+        gen_helper_float_ne_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1a:    /*lf.sfgt.d*/
+        LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
+        gen_helper_float_gt_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0a:    /*lf.sfgt.s*/
+        LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
+        gen_helper_float_gt_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1b:    /*lf.sfge.d*/
+        LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
+        gen_helper_float_ge_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0b:    /*lf.sfge.s*/
+        LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
+        gen_helper_float_ge_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1c:    /*lf.sflt.d*/
+        LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
+        gen_helper_float_lt_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0c:    /*lf.sflt.s*/
+        LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
+        gen_helper_float_lt_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1d:    /*lf.sfle.d*/
+        LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
+        gen_helper_float_le_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0d:    /*lf.sfle.s*/
+        LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
+        gen_helper_float_le_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+    }
+    wb_SR_F();
+}
+
+static void disas_openrisc_insn(DisasContext *dc, CPUOpenriscState *env)
+{
+    uint32_t op0;
+    uint32_t insn;
+    insn = cpu_ldl_code(env, dc->pc);
+    op0 = field(insn, 26, 6);
+
+    switch (op0) {
+        dec_M(dc, env, insn);
+        break;
+
+        dec_sys(dc, env, insn);
+        break;
+
+        dec_logic(dc, env, insn);
+        break;
+
+        dec_compi(dc, env, insn);
+        break;
+
+        dec_mac(dc, env, insn);
+        break;
+
+        dec_float(dc, env, insn);
+        break;
+
+        dec_calc(dc, env, insn);
+        break;
+
+        dec_comp(dc, env, insn);
+        break;
+
+        dec_misc(dc, env, insn);
+        break;
+    }
+}
+
+static void check_breakpoint(CPUOpenriscState *env, DisasContext *dc)
+{
+    CPUBreakpoint *bp;
+
+    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
+        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+            if (bp->pc == dc->pc) {
+                tcg_gen_movi_tl(cpu_pc, dc->pc);
+                gen_exception(dc, EXCP_DEBUG);
+                dc->is_jmp = DISAS_UPDATE;
+            }
+        }
+    }
 }
 static inline void gen_intermediate_code_internal(CPUOpenriscState *env,
                                                  TranslationBlock *tb,
                                                  int search_pc)
 {
+    struct DisasContext ctx, *dc = &ctx;
+    uint16_t *gen_opc_end;
+    uint32_t pc_start;
+    int j, k;
+    uint32_t next_page_start;
+    int num_insns;
+    int max_insns;
+
+    qemu_log_try_set_file(stderr);
+
+    pc_start = tb->pc;
+    dc->env = env;
+    dc->tb = tb;
+
+    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    dc->is_jmp = DISAS_NEXT;
+    dc->ppc = pc_start;
+    dc->pc = pc_start;
+    dc->mem_idx = cpu_mmu_index(env);
+    dc->synced_flags = dc->tb_flags = tb->flags;
+    dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
+    dc->singlestep_enabled = env->singlestep_enabled;
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+        qemu_log("-----------------------------------------\n");
+        log_cpu_state(env, 0);
+    }
+
+    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+    k = -1;
+    num_insns = 0;
+    max_insns = tb->cflags & CF_COUNT_MASK;
+
+    if (max_insns == 0) {
+        max_insns = CF_COUNT_MASK;
+    }
+
+    gen_icount_start();
+
+    do {
+        check_breakpoint(env, dc);
+        if (search_pc) {
+            j = gen_opc_ptr - gen_opc_buf;
+            if (k < j) {
+                k++;
+                while (k < j) {
+                    gen_opc_instr_start[k++] = 0;
+                }
+            }
+            gen_opc_pc[k] = dc->pc;
+            gen_opc_instr_start[k] = 1;
+            gen_opc_icount[k] = num_insns;
+        }
+
+        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
+            tcg_gen_debug_insn_start(dc->pc);
+        }
+
+        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+            gen_io_start();
+        }
+        dc->ppc = dc->pc - 4;
+        dc->npc = dc->pc + 4;
+        tcg_gen_movi_tl(cpu_ppc, dc->ppc);
+        tcg_gen_movi_tl(cpu_npc, dc->npc);
+        disas_openrisc_insn(dc, env);
+        dc->pc = dc->npc;
+        num_insns++;
+        /* delay slot */
+        if (dc->delayed_branch) {
+            dc->delayed_branch--;
+            if (!dc->delayed_branch) {
+                dc->tb_flags &= ~D_FLAG;
+                gen_sync_flags(dc);
+                tcg_gen_mov_tl(cpu_pc, jmp_pc);
+                tcg_gen_mov_tl(cpu_npc, jmp_pc);
+                tcg_gen_movi_tl(jmp_pc, 0);
+                tcg_gen_exit_tb(0);
+                dc->is_jmp = DISAS_JUMP;
+                break;
+            }
+        }
+    } while (!dc->is_jmp
+             && gen_opc_ptr < gen_opc_end
+             && !env->singlestep_enabled
+             && !singlestep
+             && (dc->pc < next_page_start)
+             && num_insns < max_insns);
+
+    if (tb->cflags & CF_LAST_IO) {
+        gen_io_end();
+    }
+    if (dc->is_jmp == DISAS_NEXT) {
+        dc->is_jmp = DISAS_UPDATE;
+        tcg_gen_movi_tl(cpu_pc, dc->pc);
+    }
+    if (unlikely(env->singlestep_enabled)) {
+        if (dc->is_jmp == DISAS_NEXT) {
+            tcg_gen_movi_tl(cpu_pc, dc->pc);
+        }
+        gen_exception(dc, EXCP_DEBUG);
+    } else {
+        switch (dc->is_jmp) {
+            gen_goto_tb(dc, 0, dc->pc);
+            break;
+            break;
+            /* indicate that the hash table must be used
+               to find the next TB */
+            tcg_gen_exit_tb(0);
+            break;
+            /* nothing more to generate */
+            break;
+        }
+    }
+
+    gen_icount_end(tb, num_insns);
+    *gen_opc_ptr = INDEX_op_end;
+    if (search_pc) {
+        j = gen_opc_ptr - gen_opc_buf;
+        k++;
+        while (k <= j) {
+            gen_opc_instr_start[k++] = 0;
+        }
+    } else {
+        tb->size = dc->pc - pc_start;
+        tb->icount = num_insns;
+    }
+
+#ifdef DEBUG_DISAS
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+        qemu_log("\n");
+        log_target_disas(pc_start, dc->pc - pc_start, 0);
+        qemu_log("\nisize=%d osize=%td\n",
+            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
+    }
+#endif
 }
 void gen_intermediate_code(CPUOpenriscState *env, struct TranslationBlock *tb)
@@ -51,7 +1466,13 @@ void cpu_dump_state(CPUOpenriscState *env, FILE *f,
                    fprintf_function cpu_fprintf,
                    int flags)
 {
+    int i;
+    uint32_t *regs = env->gpr;
    cpu_fprintf(f, "PC=%08x\n", env->pc);
+    for (i = 0; i < 32; ++i) {
+        cpu_fprintf(f, "R%02d=%08x%c", i, regs[i],
+                    (i % 4) == 3 ? '\n' : ' ');
+    }
 }
 void restore_state_to_opc(CPUOpenriscState *env, TranslationBlock *tb,
--
1.7.9.5
--
Thanks.
-- Max
Jia Liu
2012-05-30 02:17:51 UTC
Permalink
Hi Max,

Thank you very much for comments, I've fix them all.
Post by Max Filippov
Hi Jia.
Post by Jia Liu
add openrisc instruction translation routines.
---
 target-openrisc/translate.c | 1421 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1421 insertions(+)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 5bbad9e..965fa0e 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -26,14 +26,1429 @@
 #include "qemu-log.h"
 #include "config.h"
+#include "helper.h"
+#define GEN_HELPER 1
+#include "helper.h"
+
+#define DISAS_OPENRISC 1
+#if DISAS_OPENRISC
+#  define LOG_DIS(...) do { } while (0)
+#endif
+
+typedef struct DisasContext {
+    CPUOpenriscState *env;
+    TranslationBlock *tb;
+    target_ulong pc, ppc, npc;
+    uint32_t tb_flags, synced_flags;
+    uint32_t is_jmp;
+    uint32_t mem_idx;
+    int singlestep_enabled;
+    uint32_t delayed_branch;
+} DisasContext;
+
+static TCGv_ptr cpu_env;
+static TCGv cpu_sr;
+static TCGv cpu_R[32];
+static TCGv cpu_pc;
+static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
+static TCGv cpu_npc;
+static TCGv cpu_ppc;
+static TCGv_i32 env_btaken;    /* bf/bnf , F flag taken */
+static TCGv_i32 fpcsr;
+static TCGv machi, maclo;
+static TCGv fpmaddhi, fpmaddlo;
+static TCGv_i32 env_flags;
+#include "gen-icount.h"
+
 void openrisc_translate_init(void)
 {
+    static const char * const regnames[] = {
+        "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+        "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+        "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+        "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+    };
+    int i;
+
+    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    cpu_sr = tcg_global_mem_new(TCG_AREG0,
+                                offsetof(CPUOpenriscState, sr), "sr");
+    env_flags = tcg_global_mem_new_i32(TCG_AREG0,
+                                       offsetof(CPUOpenriscState, flags),
+                                       "flags");
+    cpu_pc = tcg_global_mem_new(TCG_AREG0,
+                                offsetof(CPUOpenriscState, pc), "pc");
+    cpu_npc = tcg_global_mem_new(TCG_AREG0,
+                                 offsetof(CPUOpenriscState, npc), "npc");
+    cpu_ppc = tcg_global_mem_new(TCG_AREG0,
+                                 offsetof(CPUOpenriscState, ppc), "ppc");
+    jmp_pc = tcg_global_mem_new(TCG_AREG0,
+                                offsetof(CPUOpenriscState, jmp_pc), "jmp_pc");
+    env_btaken = tcg_global_mem_new_i32(TCG_AREG0,
+                                        offsetof(CPUOpenriscState, btaken),
+                                        "btaken");
+    fpcsr = tcg_global_mem_new_i32(TCG_AREG0,
+                                   offsetof(CPUOpenriscState, fpcsr),
+                                   "fpcsr");
+    machi = tcg_global_mem_new(TCG_AREG0,
+                               offsetof(CPUOpenriscState, machi),
+                               "machi");
+    maclo = tcg_global_mem_new(TCG_AREG0,
+                               offsetof(CPUOpenriscState, maclo),
+                               "maclo");
+    fpmaddhi = tcg_global_mem_new(TCG_AREG0,
+                                  offsetof(CPUOpenriscState, fpmaddhi),
+                                  "fpmaddhi");
+    fpmaddlo = tcg_global_mem_new(TCG_AREG0,
+                                  offsetof(CPUOpenriscState, fpmaddlo),
+                                  "fpmaddlo");
+    for (i = 0; i < 32; i++) {
+        cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
+                                      offsetof(CPUOpenriscState, gpr[i]),
+                                      regnames[i]);
+    }
+#define GEN_HELPER 2
+#include "helper.h"
+}
+
+/* Writeback SR_F transaltion-space to execution-space.  */
+static inline void wb_SR_F(void)
+{
+    int label;
+
+    label = gen_new_label();
+    tcg_gen_andi_tl(cpu_sr, cpu_sr, ~SR_F);
+    tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, label);
+    tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_F);
+    gen_set_label(label);
+}
+
+static inline int zero_extend(unsigned int val, int width)
+{
+    return val & ((1 << width) - 1);
+}
+
+static inline int sign_extend(unsigned int val, int width)
+{
+    int sval;
+
+    /* LSL.  */
+    val <<= 32 - width;
+    sval = val;
+    /* ASR.  */
+    sval >>= 32 - width;
There should be TARGET_LONG_BITS instead of 32, as you use this function
with tcg_gen_*_tl.
Post by Jia Liu
+    return sval;
+}
+
+static inline void gen_sync_flags(DisasContext *dc)
+{
+    /* Sync the tb dependent flag between translate and runtime.  */
+    if (dc->tb_flags != dc->synced_flags) {
+        tcg_gen_movi_tl(env_flags, dc->tb_flags);
+        dc->synced_flags = dc->tb_flags;
+    }
+}
+
+static void gen_exception(DisasContext *dc, unsigned int excp)
+{
+    TCGv_i32 tmp = tcg_const_i32(excp);
+    gen_helper_exception(cpu_env, tmp);
+    tcg_temp_free(tmp);
+}
+
+static void gen_illegal_exception(DisasContext *dc)
+{
+    tcg_gen_movi_tl(cpu_pc, dc->pc);
+    gen_exception(dc, EXCP_ILLEGAL);
+    dc->is_jmp = DISAS_UPDATE;
+}
+
+static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
+{
+    TranslationBlock *tb;
+    tb = dc->tb;
+    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
+                                       likely(!dc->singlestep_enabled)) {
+        tcg_gen_movi_tl(cpu_pc, dest);
+        tcg_gen_goto_tb(n);
+        tcg_gen_exit_tb((tcg_target_long)tb + n);
+    } else {
+        tcg_gen_movi_tl(cpu_pc, dest);
+        if (dc->singlestep_enabled) {
+            gen_exception(dc, EXCP_DEBUG);
+        }
+        tcg_gen_exit_tb(0);
+    }
+}
+
+static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
+{
+    target_ulong tmp_pc;
+    int lab = gen_new_label();
+    TCGv sr_f = tcg_temp_new();
+    /* N26, 26bits imm */
+    tmp_pc = sign_extend((imm<<2), 26) + dc->pc;
+    tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+
+    if (op0 == 0x0) {
+        /*l.j*/
+        tcg_gen_movi_tl(jmp_pc, tmp_pc);
+    } else if (op0 == 0x1) {
+        /*l.jal*/
+        tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+        tcg_gen_movi_tl(jmp_pc, tmp_pc);
+    } else if (op0 == 0x3) {
+        /*l.bnf*/
+        tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+        tcg_gen_brcondi_i32(TCG_COND_EQ, sr_f, SR_F, lab);
+        tcg_gen_movi_tl(jmp_pc, tmp_pc);
+        gen_set_label(lab);
+    } else if (op0 == 0x4) {
+        /*l.bf*/
+        tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+        tcg_gen_brcondi_i32(TCG_COND_NE, sr_f, SR_F, lab);
+        tcg_gen_movi_tl(jmp_pc, tmp_pc);
+        gen_set_label(lab);
+    } else if (op0 == 0x11) {
+        /*l.jr*/
+        tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
+    } else if (op0 == 0x12) {
+        /*l.jalr*/
+        tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+        tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
+    } else {
+        gen_illegal_exception(dc);
+    }
+
+    tcg_temp_free(sr_f);
+    dc->delayed_branch = 2;
+    dc->tb_flags |= D_FLAG;
+    gen_sync_flags(dc);
+}
+
+static inline uint32_t field(uint32_t val, int start, int length)
+{
+    val >>= start;
+    val &= ~(~0 << length);
+    return val;
+}
+
+static void dec_calc(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0, op1, op2;
+    uint32_t ra, rb, rd;
+    op0 = field(insn, 0, 4);
+    op1 = field(insn, 8, 2);
+    op2 = field(insn, 6, 2);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+    rd = field(insn, 21, 5);
+
+    switch (op0) {
+        switch (op1) {
+        case 0x00:     /*l.add*/
+            LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb);
+            gen_helper_add(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+    break;
+
+    case 0x0001:    /*l.addc*/
+        switch (op1) {
+            LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
+            gen_helper_addc(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+    break;
+
+    case 0x0002:    /*l.sub*/
+        switch (op1) {
+            LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
+            gen_helper_sub(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+    break;
+
+    case 0x0003:   /*l.and*/
+        switch (op1) {
+            LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb);
+            tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+    break;
+
+    case 0x0004:   /*l.or*/
+        switch (op1) {
+            LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb);
+            tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+    break;
+
+        switch (op1) {
+        case 0x00:   /*l.xor*/
+            LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb);
+            tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+    break;
+
+        switch (op1) {
+        case 0x03:   /*l.mul*/
+            LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb);
+            if (ra != 0 && rb != 0) {
+                gen_helper_mul(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0x0);
+            }
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+    break;
+
+        switch (op1) {
+        case 0x03:   /*l.div*/
+            LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
+            if (rb == 0) {
+                TCGv_i32 sr_ove;
+                int lab = gen_new_label();
+                sr_ove = tcg_temp_new();
+                tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV);
+                tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY);
+                tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+                tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab);
+                gen_exception(dc, EXCP_RANGE);
+                gen_set_label(lab);
+                tcg_temp_free(sr_ove);
+            } else if (rb != 0) {
'if (rb != 0)' is redundant here.
You need similar handling here for the case 'rb contains 0' as in the
'if' block above.
You also need to handle the case 'ra contains 0x80000000, rb contains
0xffffffff' here,
as it will cause integer overflow.
Post by Jia Liu
+                tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                break;
+            }
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        switch (op1) {
+        case 0x03:   /*l.divu*/
+            LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb);
+            if (rb == 0) {
+                TCGv_i32 sr_ove;
+                int lab = gen_new_label();
+                sr_ove = tcg_temp_new();
+                tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV);
+                tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY);
+                tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+                tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab);
+                gen_exception(dc, EXCP_RANGE);
+                gen_set_label(lab);
+                tcg_temp_free(sr_ove);
+            } else if (rb != 0) {
'if (rb != 0)' is redundant here.
You need similar handling here for the case 'rb contains 0' as in the
'if' block above.
Post by Jia Liu
+                tcg_gen_extu_i32_tl(cpu_R[ra], cpu_R[ra]);
+                tcg_gen_extu_i32_tl(cpu_R[rb], cpu_R[rb]);
These extu's are not needed, they are no-op in 32 bit wide register case,
and they clobber ra and rb and yield wrong result in 64 bit wide register case.
Post by Jia Liu
+                tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                break;
+            }
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        switch (op1) {
+        case 0x03:   /*l.mulu*/
+            LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb);
+            if (rb != 0 && ra != 0) {
+                TCGv_i64 result = tcg_temp_new();
+                TCGv_i32 high = tcg_temp_new();
+                TCGv_i32 sr_ove = tcg_temp_new();
+                int lab = gen_new_label();
+                int lab2 = gen_new_label();
+                tcg_gen_extu_i32_tl(cpu_R[ra], cpu_R[ra]);
+                tcg_gen_extu_i32_tl(cpu_R[rb], cpu_R[rb]);
These extu's are not needed, they are no-op in 32 bit wide register case,
and they clobber ra and rb and yield wrong result in 64 bit wide register case.
Post by Jia Liu
+                tcg_gen_mul_tl(result, cpu_R[ra], cpu_R[rb]);
This is wrong, all three mul parameters must have the same width. If you need
wider result, please use corresponding width temporaries and explicit mul_i64
Post by Jia Liu
+                tcg_gen_shri_tl(high, result, (sizeof(target_ulong) * 8));
Ditto.
Post by Jia Liu
+                tcg_gen_brcondi_tl(TCG_COND_EQ, high, 0x0, lab);
+                tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY);
+                tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV);
+                tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+                tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab2);
When this branch is taken the multiplication result is not written to cpu_R[rd],
is that correct?
Post by Jia Liu
+                gen_exception(dc, EXCP_RANGE);
+                gen_set_label(lab);
+                tcg_gen_trunc_i64_tl(cpu_R[rd], result);
+                gen_set_label(lab2);
+                tcg_temp_free(result);
+                tcg_temp_free(high);
+                tcg_temp_free(sr_ove);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0);
+            }
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        switch (op1) {
+        case 0x00:   /*l.cmov*/
+            LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb);
+            {
+                int lab = gen_new_label();
+                TCGv sr_f = tcg_temp_new();
+                tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+                tcg_gen_mov_tl(cpu_R[rd], cpu_R[rb]);
+                tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
+                tcg_gen_mov_tl(cpu_R[rd], cpu_R[ra]);
+                gen_set_label(lab);
+                tcg_temp_free(sr_f);
In case rd == ra and SR_F == 0 the result is wrong here.
It may be rewritten as
               int lab = gen_new_label();
               TCGv res = tcg_temp_new();
               TCGv sr_f = tcg_temp_new();
               tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
               tcg_gen_mov_tl(res, cpu_R[rb]);
               tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
               tcg_gen_mov_tl(res, cpu_R[ra]);
               gen_set_label(lab);
               tcg_gen_mov_tl(cpu_R[rd], res);
               tcg_temp_free(res);
               tcg_temp_free(sr_f);
Post by Jia Liu
+            }
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        switch (op1) {
+        case 0x00:   /*l.ff1*/
+            LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
+            gen_helper_ff1(cpu_R[rd], cpu_R[ra]);
+            break;
+        case 0x01:   /*l.fl1*/
+            LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
+            gen_helper_fl1(cpu_R[rd], cpu_R[ra]);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        switch (op1) {
+            switch (op2) {
+            case 0x00:   /*l.sll*/
+                LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb);
+                tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                break;
+            case 0x01:   /*l.srl*/
+                LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb);
+                tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                break;
+            case 0x02:   /*l.sra*/
+                LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb);
+                tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                break;
+            case 0x03:   /*l.ror*/
+                LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb);
+                tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                break;
+                gen_illegal_exception(dc);
+                break;
+            }
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        switch (op1) {
+            switch (op2) {
+            case 0x00:   /*l.exths*/
+                LOG_DIS("l.exths r%d, r%d\n", rd, ra);
+                tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]);
+                break;
+            case 0x01:   /*l.extbs*/
+                LOG_DIS("l.extbs r%d, r%d\n", rd, ra);
+                tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]);
+                break;
+            case 0x02:   /*l.exthz*/
+                LOG_DIS("l.exthz r%d, r%d\n", rd, ra);
+                tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]);
+                break;
+            case 0x03:   /*l.extbz*/
+                LOG_DIS("l.extbz r%d, r%d\n", rd, ra);
+                tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]);
+                break;
+                gen_illegal_exception(dc);
+                break;
+            }
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        switch (op1) {
+            switch (op2) {
+            case 0x00:   /*l.extws*/
+                LOG_DIS("l.extws r%d, r%d\n", rd, ra);
+                tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]);
+                break;
+            case 0x01:    /*l.extwz*/
+                LOG_DIS("l.extwz r%d, r%d\n", rd, ra);
+                tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]);
+                break;
+                gen_illegal_exception(dc);
+                break;
+            }
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+    }
+}
+
+static void dec_misc(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0, op1;
+    uint32_t ra, rb, rd;
+    uint32_t /*L6, K5, */I16, I5, I11, N26, tmp;
+    op0 = field(insn, 26, 6);
+    op1 = field(insn, 24, 2);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+    rd = field(insn, 21, 5);
+    /*L6 = field(insn, 5, 6);
+    K5 = field(insn, 0, 5);*/
+    I16 = field(insn, 0, 16);
+    I5 = field(insn, 21, 5);
+    I11 = field(insn, 0, 11);
+    N26 = field(insn, 0, 26);
+    tmp = (I5<<11) + I11;
+    TCGv t0 = tcg_temp_new();
+
+    switch (op0) {
+    case 0x00:   /*l.j*/
+        LOG_DIS("l.j %d\n", N26);
+    case 0x01:   /*l.jal*/
+        LOG_DIS("l.jal %d\n", N26);
+    case 0x03:   /*l.bnf*/
+        LOG_DIS("l.bnf %d\n", N26);
+    case 0x04:   /*l.bf*/
+        LOG_DIS("l.bf %d\n", N26);
+
+        gen_jump(dc, N26, 0, op0);
+        break;
+
+        switch (op1) {
+        case 0x01:   /*l.nop*/
+            LOG_DIS("l.nop %d\n", I16);
+            break;
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+    case 0x11:    /*l.jr*/
+        LOG_DIS("l.jr r%d\n", rb);
+    case 0x12:    /*l.jalr*/
+        LOG_DIS("l.jalr r%d\n", rb);
+
+        gen_jump(dc, 0, rb, op0);
+        break;
+
+    case 0x13:    /*l.maci*/
+        LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I11);
+        {
+            TCGv_i64 tra = tcg_temp_new_i64();    /*  store cpu_R[ra]*/
+            TCGv_i64 tmac = tcg_temp_new_i64();   /*  store machi maclo*/
+            tcg_gen_movi_tl(t0, tmp);
+            tcg_gen_ext32s_i64(tra, cpu_R[ra]);
+            tcg_gen_ext32s_i64(tmac, t0);
+            tcg_gen_mul_tl(tmac, tra, tmac);
+            tcg_gen_trunc_i64_i32(cpu_R[ra], tmac);
+            tcg_gen_add_i64(machi, machi, cpu_R[ra]);
+            tcg_gen_add_i64(maclo, maclo, cpu_R[ra]);
This needs the same treatment as l.mac.
Post by Jia Liu
+            tcg_temp_free(tra);
+            tcg_temp_free(tmac);
+        }
+        break;
+
+    case 0x09:    /*l.rfe*/
+        LOG_DIS("l.rfe\n");
+        {
+            gen_helper_rfe(cpu_env);
+            dc->is_jmp = DISAS_UPDATE;
+        }
+        break;
+
+    case 0x1c:    /*l.cust1*/
+        LOG_DIS("l.cust1\n");
+        break;
+
+    case 0x1d:    /*l.cust2*/
+        LOG_DIS("l.cust2\n");
+        break;
+
+    case 0x1e:    /*l.cust3*/
+        LOG_DIS("l.cust3\n");
+        break;
+
+    case 0x1f:    /*l.cust4*/
+        LOG_DIS("l.cust4\n");
+        break;
+
+    case 0x3c:   /*l.cust5*/
+        /*LOG_DIS("l.cust5 r%d, r%d, r%d, %d, %d\n", rd, ra, rb, L6, K5);*/
+        break;
+
+    case 0x3d:   /*l.cust6*/
+        LOG_DIS("l.cust6\n");
+        break;
+
+    case 0x3e:   /*l.cust7*/
+        LOG_DIS("l.cust7\n");
+        break;
+
+    case 0x3f:   /*l.cust8*/
+        LOG_DIS("l.cust8\n");
+        break;
+
+    case 0x20:   /*l.ld*/
+        LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_qemu_ld64(cpu_R[rd], t0, dc->mem_idx);
+        break;
+
+    case 0x21:   /*l.lwz*/
+        LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_qemu_ld32u(cpu_R[rd], t0, dc->mem_idx);
+        break;
+
+    case 0x22:   /*l.lws*/
+        LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_qemu_ld32s(cpu_R[rd], t0, dc->mem_idx);
+        break;
+
+    case 0x23:   /*l.lbz*/
+        LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_qemu_ld8u(cpu_R[rd], t0, dc->mem_idx);
+        break;
+
+    case 0x24:   /*l.lbs*/
+        LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_qemu_ld8s(cpu_R[rd], t0, dc->mem_idx);
+        break;
+
+    case 0x25:   /*l.lhz*/
+        LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_qemu_ld16u(cpu_R[rd], t0, dc->mem_idx);
+        break;
+
+    case 0x26:   /*l.lhs*/
+        LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_qemu_ld16s(cpu_R[rd], t0, dc->mem_idx);
+        break;
+
+    case 0x27:   /*l.addi*/
+        LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
+        {
+            TCGv t0 = tcg_const_tl(sign_extend(I16, 16));
+            gen_helper_add(cpu_R[rd], cpu_env, cpu_R[ra], t0);
+            tcg_temp_free(t0);
+        }
+        break;
+
+    case 0x28:   /*l.addic*/
+        LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16);
+        {
+            TCGv t0 = tcg_const_tl(sign_extend(I16, 16));
+            gen_helper_addc(cpu_R[rd], cpu_env, cpu_R[ra], t0);
+            tcg_temp_free(t0);
+        }
+        break;
+
+    case 0x29:   /*l.andi*/
+        LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], zero_extend(I16, 16));
+        break;
+
+    case 0x2a:   /*l.ori*/
+        LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, zero_extend(I16, 16));
+        tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], I16);
+        break;
+
+    case 0x2b:   /*l.xori*/
+        LOG_DIS("l.xori r%d, r%d, %d\n", rd, ra, I16);
+        tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], sign_extend(I16, 16));
+        break;
+
+    case 0x2c:   /*l.muli*/
+        LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16);
+        if (ra != 0 && I16 != 0) {
+            TCGv i16 = tcg_const_tl(I16);
+            gen_helper_mul(cpu_R[rd], cpu_env, cpu_R[ra], i16);
+            tcg_temp_free(i16);
+        } else {
+            tcg_gen_movi_tl(cpu_R[rd], 0x0);
+        }
+        break;
+
+    case 0x2d:   /*l.mfspr*/
+        LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
+        break;
+
+    case 0x30:  /*l.mtspr*/
+        LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        break;
+
+    case 0x34:   /*l.sd*/
+        LOG_DIS("l.sd %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+        tcg_gen_qemu_st64(cpu_R[rb], t0, dc->mem_idx);
+        break;
+
+    case 0x35:   /*l.sw*/
+        LOG_DIS("l.sw %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+        tcg_gen_qemu_st32(cpu_R[rb], t0, dc->mem_idx);
+        break;
+
+    case 0x36:   /*l.sb*/
+        LOG_DIS("l.sb %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+        tcg_gen_qemu_st8(cpu_R[rb], t0, dc->mem_idx);
+        break;
+
+    case 0x37:   /*l.sh*/
+        LOG_DIS("l.sh %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+        tcg_gen_qemu_st16(cpu_R[rb], t0, dc->mem_idx);
+        break;
+        gen_illegal_exception(dc);
+        break;
+    }
+    tcg_temp_free(t0);
+}
+
+static void dec_mac(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t ra, rb;
+    op0 = field(insn, 0, 4);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+    TCGv_i64 t0 = tcg_temp_new();
+    TCGv_i64 t1 = tcg_temp_new();
+    TCGv_i64 t2 = tcg_temp_new();
+    switch (op0) {
+    case 0x0001:   /*l.mac*/
+        LOG_DIS("l.mac r%d, r%d\n", ra, rb);
+        {
+            tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]);
+            tcg_gen_ext_i32_i64(t1, t0);
+            tcg_gen_concat_i32_i64(t2, maclo, machi);
+            tcg_gen_add_i64(t2, t2, t1);
+            tcg_gen_trunc_i64_i32(maclo, t2);
+            tcg_gen_shri_i64(t2, t2, 32);
+            tcg_gen_trunc_i64_i32(machi, t2);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+            tcg_temp_free(t2);
+        }
+        break;
+
+    case 0x0002:   /*l.msb*/
+        LOG_DIS("l.msb r%d, r%d\n", ra, rb);
+        {
+            tcg_gen_ext_i32_i64(t0, cpu_R[ra]);
+            tcg_gen_ext_i32_i64(t1, cpu_R[rb]);
+            tcg_gen_mul_i64(t0, t0, t1);
+            tcg_gen_trunc_i64_i32(cpu_R[ra], t0);
+            tcg_gen_sub_i32(maclo, maclo, cpu_R[ra]);
+            tcg_gen_sub_i32(machi, machi, cpu_R[ra]);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
This needs the same treatment as l.mac.
Post by Jia Liu
+        }
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+   }
+}
+
+static void dec_logic(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t rd, ra, L6;
+    op0 = field(insn, 6, 2);
+    rd = field(insn, 21, 5);
+    ra = field(insn, 16, 5);
+    L6 = field(insn, 0, 6);
+
+    switch (op0) {
+    case 0x00:    /*l.slli*/
+        LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6);
+        tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+        break;
+
+    case 0x01:    /*l.srli*/
+        LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6);
+        tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+        break;
+
+    case 0x02:    /*l.srai*/
+        LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6);
+        tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f)); break;
+
+    case 0x03:    /*l.rori*/
+        LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6);
+        tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+    }
+}
+
+static void dec_M(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t rd;
+    uint32_t K16;
+    op0 = field(insn, 16, 1);
+    rd = field(insn, 21, 5);
+    K16 = field(insn, 0, 16);
+
+    switch (op0) {
+    case 0x0:    /*l.movhi*/
+        LOG_DIS("l.movhi  r%d, %d\n", rd, K16);
+        tcg_gen_movi_tl(cpu_R[rd], (K16 << 16));
+        break;
+
+    case 0x1:    /*l.macrc*/
+        LOG_DIS("l.macrc  r%d\n", rd);
+        tcg_gen_mov_tl(cpu_R[rd], maclo);
+        tcg_gen_movi_tl(maclo, 0x0);
+        tcg_gen_movi_tl(machi, 0x0);
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+    }
+}
+
+static void dec_comp(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t ra, rb;
+
+    op0 = field(insn, 21, 5);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+
+    tcg_gen_movi_i32(env_btaken, 0x0);
+    /* unsigned integers  */
+    tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+    tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
These extu's are not needed, they are no-op in 32 bit wide register case,
and they clobber ra and rb in 64 bit wide register case. Comparison signedness
is chosen by TCG_COND_* constants below.
Post by Jia Liu
+    switch (op0) {
+    case 0x0:    /*l.sfeq*/
+        LOG_DIS("l.sfeq  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1:    /*l.sfne*/
+        LOG_DIS("l.sfne  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x2:    /*l.sfgtu*/
+        LOG_DIS("l.sfgtu  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GTU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x3:    /*l.sfgeu*/
+        LOG_DIS("l.sfgeu  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GEU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x4:    /*l.sfltu*/
+        LOG_DIS("l.sfltu  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LTU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x5:    /*l.sfleu*/
+        LOG_DIS("l.sfleu  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0xa:    /*l.sfgts*/
+        LOG_DIS("l.sfgts  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0xb:    /*l.sfges*/
+        LOG_DIS("l.sfges  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0xc:    /*l.sflts*/
+        LOG_DIS("l.sflts  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0xd:    /*l.sfles*/
+        LOG_DIS("l.sfles  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+    }
+    wb_SR_F();
+}
+
+static void dec_compi(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t ra, I16;
+
+    op0 = field(insn, 21, 5);
+    ra = field(insn, 16, 5);
+    I16 = field(insn, 0, 16);
+
+    tcg_gen_movi_i32(env_btaken, 0x0);
+    tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
This extu is not needed, it is no-op in 32 bit wide register case,
and it clobbers ra in 64 bit wide register case. Comparison signedness
is chosen by TCG_COND_* constants below.
Post by Jia Liu
+    I16 = sign_extend(I16, 16);
+
+    switch (op0) {
+    case 0x0:    /*l.sfeqi*/
+        LOG_DIS("l.sfeqi  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0x1:    /*l.sfnei*/
+        LOG_DIS("l.sfnei  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_NE, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0x2:    /*l.sfgtui*/
+        LOG_DIS("l.sfgtui  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_GTU, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0x3:    /*l.sfgeui*/
+        LOG_DIS("l.sfgeui  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_GEU, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0x4:    /*l.sfltui*/
+        LOG_DIS("l.sfltui  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_LTU, env_btaken, cpu_R[ra],
+                            sign_extend(I16, 16));
Redundant sign_extend.
Post by Jia Liu
+        break;
+
+    case 0x5:    /*l.sfleui*/
+        LOG_DIS("l.sfleui  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0xa:    /*l.sfgtsi*/
+        LOG_DIS("l.sfgtsi  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_GT, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0xb:    /*l.sfgesi*/
+        LOG_DIS("l.sfgesi  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_GE, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0xc:    /*l.sfltsi*/
+        LOG_DIS("l.sfltsi  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_LT, env_btaken, cpu_R[ra], I16);
+        break;
+
+    case 0xd:    /*l.sflesi*/
+        LOG_DIS("l.sflesi  r%d, %d\n", ra, I16);
+        tcg_gen_setcondi_tl(TCG_COND_LE, env_btaken, cpu_R[ra], I16);
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+    }
+    wb_SR_F();
+}
+
+static void dec_sys(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0;
+    /*uint32_t K16;*/
+    op0 = field(insn, 16, 8);
+    /*K16 = field(insn, 0, 16);*/
+
+    switch (op0) {
+    case 0x000:  /*l.sys*/
+        /*LOG_DIS("l.sys %d\n", K16);*/
+        tcg_gen_movi_tl(cpu_pc, dc->pc);
+        gen_exception(dc, EXCP_SYSCALL);
+        dc->is_jmp = DISAS_UPDATE;
+        break;
+
+    case 0x100:  /*l.trap*/
+        /*LOG_DIS("l.trap %d\n", K16);*/
+        tcg_gen_movi_tl(cpu_pc, dc->pc);
+        gen_exception(dc, EXCP_TRAP);
+        break;
+
+    case 0x300:  /*l.csync*/
+        LOG_DIS("l.csync\n");
+        break;
+
+    case 0x200:  /*l.msync*/
+        LOG_DIS("l.msync\n");
+        break;
+
+    case 0x270:  /*l.psync*/
+        LOG_DIS("l.psync\n");
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+    }
+}
+
+static void dec_float(DisasContext *dc, CPUOpenriscState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t ra, rb, rd;
+    op0 = field(insn, 0, 8);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+    rd = field(insn, 21, 5);
+
+    switch (op0) {
+    case 0x10:    /*lf.add.d*/
+        LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x00:    /*lf.add.s*/
+        LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x11:    /*lf.sub.d*/
+        LOG_DIS("lf.sub.d r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_sub_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x01:    /*lf.sub.s*/
+        LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x12:    /*lf.mul.d*/
+        LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb);
+        if (cpu_R[ra] != 0 && cpu_R[rb] != 0) {
Should be "if (ra != 0 && rb != 0)".
Post by Jia Liu
+            gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        } else {
+            tcg_gen_ori_tl(fpcsr, fpcsr, FPCSR_ZF);
+            tcg_gen_movi_i64(cpu_R[rd], 0x0);
+        }
+        break;
+
+    case 0x02:    /*lf.mul.s*/
+        LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb);
+        if (cpu_R[ra] != 0 && cpu_R[rb] != 0) {
Ditto.
Post by Jia Liu
+            gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        } else {
+            tcg_gen_ori_tl(fpcsr, fpcsr, FPCSR_ZF);
+            tcg_gen_movi_i32(cpu_R[rd], 0x0);
+        }
+        break;
+
+    case 0x13:    /*lf.div.d*/
+        LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x03:    /*lf.div.s*/
+        LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x14:    /*lf.itof.d*/
+        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+        gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]);
+        break;
+
+    case 0x04:    /*lf.itof.s*/
+        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+        gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]);
+        break;
+
+    case 0x15:    /*lf.ftoi.d*/
+        LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+        gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]);
+        break;
+
+    case 0x05:    /*lf.ftoi.s*/
+        LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+        gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]);
+        break;
+
+    case 0x16:    /*lf.rem.d*/
+        LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x06:    /*lf.rem.s*/
+        LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x17:    /*lf.madd.d*/
+        LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_muladd_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x07:    /*lf.madd.s*/
+        LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
+        gen_helper_float_muladd_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x18:    /*lf.sfeq.d*/
+        LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
+        gen_helper_float_eq_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x08:    /*lf.sfeq.s*/
+        LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
+        gen_helper_float_eq_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x19:    /*lf.sfne.d*/
+        LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
+        gen_helper_float_ne_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x09:    /*lf.sfne.s*/
+        LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
+        gen_helper_float_ne_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1a:    /*lf.sfgt.d*/
+        LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
+        gen_helper_float_gt_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0a:    /*lf.sfgt.s*/
+        LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
+        gen_helper_float_gt_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1b:    /*lf.sfge.d*/
+        LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
+        gen_helper_float_ge_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0b:    /*lf.sfge.s*/
+        LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
+        gen_helper_float_ge_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1c:    /*lf.sflt.d*/
+        LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
+        gen_helper_float_lt_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0c:    /*lf.sflt.s*/
+        LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
+        gen_helper_float_lt_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1d:    /*lf.sfle.d*/
+        LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
+        gen_helper_float_le_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0d:    /*lf.sfle.s*/
+        LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
+        gen_helper_float_le_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        break;
+
+        gen_illegal_exception(dc);
+        break;
+    }
+    wb_SR_F();
+}
+
+static void disas_openrisc_insn(DisasContext *dc, CPUOpenriscState *env)
+{
+    uint32_t op0;
+    uint32_t insn;
+    insn = cpu_ldl_code(env, dc->pc);
+    op0 = field(insn, 26, 6);
+
+    switch (op0) {
+        dec_M(dc, env, insn);
+        break;
+
+        dec_sys(dc, env, insn);
+        break;
+
+        dec_logic(dc, env, insn);
+        break;
+
+        dec_compi(dc, env, insn);
+        break;
+
+        dec_mac(dc, env, insn);
+        break;
+
+        dec_float(dc, env, insn);
+        break;
+
+        dec_calc(dc, env, insn);
+        break;
+
+        dec_comp(dc, env, insn);
+        break;
+
+        dec_misc(dc, env, insn);
+        break;
+    }
+}
+
+static void check_breakpoint(CPUOpenriscState *env, DisasContext *dc)
+{
+    CPUBreakpoint *bp;
+
+    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
+        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+            if (bp->pc == dc->pc) {
+                tcg_gen_movi_tl(cpu_pc, dc->pc);
+                gen_exception(dc, EXCP_DEBUG);
+                dc->is_jmp = DISAS_UPDATE;
+            }
+        }
+    }
 }
 static inline void gen_intermediate_code_internal(CPUOpenriscState *env,
                                                  TranslationBlock *tb,
                                                  int search_pc)
 {
+    struct DisasContext ctx, *dc = &ctx;
+    uint16_t *gen_opc_end;
+    uint32_t pc_start;
+    int j, k;
+    uint32_t next_page_start;
+    int num_insns;
+    int max_insns;
+
+    qemu_log_try_set_file(stderr);
+
+    pc_start = tb->pc;
+    dc->env = env;
+    dc->tb = tb;
+
+    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    dc->is_jmp = DISAS_NEXT;
+    dc->ppc = pc_start;
+    dc->pc = pc_start;
+    dc->mem_idx = cpu_mmu_index(env);
+    dc->synced_flags = dc->tb_flags = tb->flags;
+    dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
+    dc->singlestep_enabled = env->singlestep_enabled;
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+        qemu_log("-----------------------------------------\n");
+        log_cpu_state(env, 0);
+    }
+
+    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+    k = -1;
+    num_insns = 0;
+    max_insns = tb->cflags & CF_COUNT_MASK;
+
+    if (max_insns == 0) {
+        max_insns = CF_COUNT_MASK;
+    }
+
+    gen_icount_start();
+
+    do {
+        check_breakpoint(env, dc);
+        if (search_pc) {
+            j = gen_opc_ptr - gen_opc_buf;
+            if (k < j) {
+                k++;
+                while (k < j) {
+                    gen_opc_instr_start[k++] = 0;
+                }
+            }
+            gen_opc_pc[k] = dc->pc;
+            gen_opc_instr_start[k] = 1;
+            gen_opc_icount[k] = num_insns;
+        }
+
+        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
+            tcg_gen_debug_insn_start(dc->pc);
+        }
+
+        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+            gen_io_start();
+        }
+        dc->ppc = dc->pc - 4;
+        dc->npc = dc->pc + 4;
+        tcg_gen_movi_tl(cpu_ppc, dc->ppc);
+        tcg_gen_movi_tl(cpu_npc, dc->npc);
+        disas_openrisc_insn(dc, env);
+        dc->pc = dc->npc;
+        num_insns++;
+        /* delay slot */
+        if (dc->delayed_branch) {
+            dc->delayed_branch--;
+            if (!dc->delayed_branch) {
+                dc->tb_flags &= ~D_FLAG;
+                gen_sync_flags(dc);
+                tcg_gen_mov_tl(cpu_pc, jmp_pc);
+                tcg_gen_mov_tl(cpu_npc, jmp_pc);
+                tcg_gen_movi_tl(jmp_pc, 0);
+                tcg_gen_exit_tb(0);
+                dc->is_jmp = DISAS_JUMP;
+                break;
+            }
+        }
+    } while (!dc->is_jmp
+             && gen_opc_ptr < gen_opc_end
+             && !env->singlestep_enabled
+             && !singlestep
+             && (dc->pc < next_page_start)
+             && num_insns < max_insns);
+
+    if (tb->cflags & CF_LAST_IO) {
+        gen_io_end();
+    }
+    if (dc->is_jmp == DISAS_NEXT) {
+        dc->is_jmp = DISAS_UPDATE;
+        tcg_gen_movi_tl(cpu_pc, dc->pc);
+    }
+    if (unlikely(env->singlestep_enabled)) {
+        if (dc->is_jmp == DISAS_NEXT) {
+            tcg_gen_movi_tl(cpu_pc, dc->pc);
+        }
+        gen_exception(dc, EXCP_DEBUG);
+    } else {
+        switch (dc->is_jmp) {
+            gen_goto_tb(dc, 0, dc->pc);
+            break;
+            break;
+            /* indicate that the hash table must be used
+               to find the next TB */
+            tcg_gen_exit_tb(0);
+            break;
+            /* nothing more to generate */
+            break;
+        }
+    }
+
+    gen_icount_end(tb, num_insns);
+    *gen_opc_ptr = INDEX_op_end;
+    if (search_pc) {
+        j = gen_opc_ptr - gen_opc_buf;
+        k++;
+        while (k <= j) {
+            gen_opc_instr_start[k++] = 0;
+        }
+    } else {
+        tb->size = dc->pc - pc_start;
+        tb->icount = num_insns;
+    }
+
+#ifdef DEBUG_DISAS
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+        qemu_log("\n");
+        log_target_disas(pc_start, dc->pc - pc_start, 0);
+        qemu_log("\nisize=%d osize=%td\n",
+            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
+    }
+#endif
 }
 void gen_intermediate_code(CPUOpenriscState *env, struct TranslationBlock *tb)
@@ -51,7 +1466,13 @@ void cpu_dump_state(CPUOpenriscState *env, FILE *f,
                    fprintf_function cpu_fprintf,
                    int flags)
 {
+    int i;
+    uint32_t *regs = env->gpr;
    cpu_fprintf(f, "PC=%08x\n", env->pc);
+    for (i = 0; i < 32; ++i) {
+        cpu_fprintf(f, "R%02d=%08x%c", i, regs[i],
+                    (i % 4) == 3 ? '\n' : ' ');
+    }
 }
 void restore_state_to_opc(CPUOpenriscState *env, TranslationBlock *tb,
--
1.7.9.5
--
Thanks.
-- Max
Regards,
Jia.

Jia Liu
2012-05-27 05:32:47 UTC
Permalink
add openrisc interrupt support.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 2 +-
cpu-exec.c | 13 ++++++++++
target-openrisc/cpu.h | 4 +++
target-openrisc/helper.h | 25 +++++++++++++++++++
target-openrisc/intrpt.c | 42 +++++++++++++++++++++++++++++++
target-openrisc/intrpt_helper.c | 52 +++++++++++++++++++++++++++++++++++++++
6 files changed, 137 insertions(+), 1 deletion(-)
create mode 100644 target-openrisc/helper.h
create mode 100644 target-openrisc/intrpt_helper.c

diff --git a/Makefile.target b/Makefile.target
index 0efabd2..47836c6 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -101,7 +101,7 @@ endif
libobj-$(TARGET_SPARC) += int32_helper.o
libobj-$(TARGET_SPARC64) += int64_helper.o
libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
-libobj-$(TARGET_OPENRISC) += intrpt.o mmu.o mmu_helper.o
+libobj-$(TARGET_OPENRISC) += intrpt.o intrpt_helper.o mmu.o mmu_helper.o

libobj-y += disas.o
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/cpu-exec.c b/cpu-exec.c
index ba10db1..ee9afd7 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -375,6 +375,19 @@ int cpu_exec(CPUArchState *env)
do_interrupt(env);
next_tb = 0;
}
+#elif defined(TARGET_OPENRISC)
+ {
+ int idx = -1;
+ if ((interrupt_request & CPU_INTERRUPT_HARD)
+ && (env->sr & SR_IEE)) {
+ idx = EXCP_INT;
+ }
+ if (idx >= 0) {
+ env->exception_index = idx;
+ do_interrupt(env);
+ next_tb = 0;
+ }
+ }
#elif defined(TARGET_SPARC)
if (interrupt_request & CPU_INTERRUPT_HARD) {
if (cpu_interrupts_enabled(env) &&
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 779c889..977dd06 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -58,6 +58,9 @@ struct CPUOpenriscState;
/* Internel flags, delay slot flag */
#define D_FLAG 1

+#define NR_IRQS 32
+#define PIC_MASK 0xFFFFFFFF
+
/* Verison Register */
#define SPR_VR 0x12000001
#define SPR_CPUCFGR 0x12000001
@@ -178,6 +181,7 @@ struct CPUOpenriscState {
target_ulong epcr; /* Exception PC register */
target_ulong eear; /* Exception EA register */
uint32_t esr; /* Exception supervisor register */
+ void *irq[32]; /* Interrupt irq input */
#if !defined(CONFIG_USER_ONLY)
tlb_entry itlb[ITLB_WAYS][ITLB_SIZE];
tlb_entry dtlb[DTLB_WAYS][DTLB_SIZE];
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
new file mode 100644
index 0000000..66cd05c
--- /dev/null
+++ b/target-openrisc/helper.h
@@ -0,0 +1,25 @@
+/*
+ * Openrisc helper defines
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "def-helper.h"
+
+/* interrupt */
+DEF_HELPER_FLAGS_1(rfe, 0, void, env)
+
+#include "def-helper.h"
diff --git a/target-openrisc/intrpt.c b/target-openrisc/intrpt.c
index a77116f..7272458 100644
--- a/target-openrisc/intrpt.c
+++ b/target-openrisc/intrpt.c
@@ -27,4 +27,46 @@

void do_interrupt(CPUOpenriscState *env)
{
+#if !defined(CONFIG_USER_ONLY)
+ if (env->flags & D_FLAG) { /* Delay Slot insn */
+ env->flags &= ~D_FLAG;
+ env->sr |= SR_DSX;
+ if (env->exception_index == EXCP_TICK ||
+ env->exception_index == EXCP_INT ||
+ env->exception_index == EXCP_SYSCALL ||
+ env->exception_index == EXCP_FPE) {
+ env->epcr = env->jmp_pc;
+ } else {
+ env->epcr = env->pc - 4;
+ }
+ } else {
+ if (env->exception_index == EXCP_TICK ||
+ env->exception_index == EXCP_INT ||
+ env->exception_index == EXCP_SYSCALL ||
+ env->exception_index == EXCP_FPE) {
+ env->epcr = env->npc;
+ } else {
+ env->epcr = env->pc;
+ }
+ }
+
+ tlb_flush(env, 1);
+
+ env->esr = env->sr;
+ env->sr &= ~SR_DME;
+ env->sr &= ~SR_IME;
+ env->sr |= SR_SM;
+ env->sr &= ~SR_IEE;
+ env->sr &= ~SR_TEE;
+ env->map_address_data = &get_phys_nommu;
+ env->map_address_code = &get_phys_nommu;
+
+ if (env->exception_index > 0 && env->exception_index < EXCP_NR) {
+ env->pc = (env->exception_index << 8);
+ } else {
+ cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
+ }
+#endif
+
+ env->exception_index = -1;
}
diff --git a/target-openrisc/intrpt_helper.c b/target-openrisc/intrpt_helper.c
new file mode 100644
index 0000000..f14f0ce
--- /dev/null
+++ b/target-openrisc/intrpt_helper.c
@@ -0,0 +1,52 @@
+/*
+ * Openrisc interrupt helper routines
+ *
+ * Copyright (c) 2011-2012 Jia Liu <***@gmail.com>
+ * Feng Gao <***@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+
+void HELPER(rfe)(CPUOpenriscState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+ int need_flush_tlb = (env->sr & (SR_SM | SR_IME | SR_DME)) ^
+ (env->esr & (SR_SM | SR_IME | SR_DME));
+#endif
+ env->pc = env->epcr;
+ env->npc = env->epcr;
+ env->sr = env->esr;
+
+#if !defined(CONFIG_USER_ONLY)
+ if (env->sr & SR_DME) {
+ env->map_address_data = &get_phys_data;
+ } else {
+ env->map_address_data = &get_phys_nommu;
+ }
+
+ if (env->sr & SR_IME) {
+ env->map_address_code = &get_phys_code;
+ } else {
+ env->map_address_code = &get_phys_nommu;
+ }
+
+ if (need_flush_tlb) {
+ tlb_flush(env, 1);
+ }
+#endif
+ env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+}
--
1.7.9.5
Loading...