Discussion:
[PATCH 00/15] Qemu Openrisc support
Jia Liu
2012-05-17 08:35:43 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

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

Version History:

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

Jia Liu (15):
Openrisc: add target stub
Openrisc: add MMU support
Openrisc: add instructions translation
Openrisc: add interrupt support
Openrisc: add exception support
Openrisc: add int instruction helpers
Openrisc: add float instruction helpers
Openrisc: add programmable interrupt controller support
Openrisc: add timer support
Openrisc: add a simulation 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 | 7 +
arch_init.c | 2 +
arch_init.h | 1 +
configure | 9 +-
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 | 30 +
hw/openrisc_pic.c | 79 ++
hw/openrisc_sim.c | 140 ++++
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-qom.h | 70 ++
target-openrisc/cpu.c | 74 ++
target-openrisc/cpu.h | 299 +++++++
target-openrisc/excp.c | 27 +
target-openrisc/excp.h | 28 +
target-openrisc/excp_helper.c | 28 +
target-openrisc/fpu_helper.c | 93 +++
target-openrisc/helper.c | 109 +++
target-openrisc/helper.h | 46 ++
target-openrisc/int_helper.c | 126 +++
target-openrisc/intrp_helper.c | 53 ++
target-openrisc/machine.c | 76 ++
target-openrisc/mem.c | 261 ++++++
target-openrisc/mem_helper.c | 71 ++
target-openrisc/sys_helper.c | 227 ++++++
target-openrisc/translate.c | 1484 +++++++++++++++++++++++++++++++++++
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, 7168 insertions(+), 5 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-qom.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/intrp_helper.c
create mode 100644 target-openrisc/machine.c
create mode 100644 target-openrisc/mem.c
create mode 100644 target-openrisc/mem_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-17 08:35:44 UTC
Permalink
add the openrisc target stub and basic implementation.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 3 +
arch_init.c | 2 +
arch_init.h | 1 +
configure | 8 +-
cpu-exec.c | 2 +
default-configs/or32-softmmu.mak | 6 +
elf.h | 2 +
poison.h | 1 +
target-openrisc/cpu-qom.h | 70 +++++++++
target-openrisc/cpu.c | 74 ++++++++++
target-openrisc/cpu.h | 299 ++++++++++++++++++++++++++++++++++++++
target-openrisc/helper.c | 67 +++++++++
target-openrisc/helper.h | 23 +++
target-openrisc/machine.c | 76 ++++++++++
target-openrisc/mem.c | 43 ++++++
target-openrisc/mem_helper.c | 46 ++++++
target-openrisc/translate.c | 90 ++++++++++++
17 files changed, 812 insertions(+), 1 deletion(-)
create mode 100644 default-configs/or32-softmmu.mak
create mode 100644 target-openrisc/cpu-qom.h
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/helper.h
create mode 100644 target-openrisc/machine.c
create mode 100644 target-openrisc/mem.c
create mode 100644 target-openrisc/mem_helper.c
create mode 100644 target-openrisc/translate.c

diff --git a/Makefile.target b/Makefile.target
index 1582904..0ffb29c 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) += mem.o mem_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..63e2372 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
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-qom.h b/target-openrisc/cpu-qom.h
new file mode 100644
index 0000000..8c936df
--- /dev/null
+++ b/target-openrisc/cpu-qom.h
@@ -0,0 +1,70 @@
+/*
+ * 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/>.
+ */
+
+#ifndef QEMU_OPENRISC_CPU_QOM_H
+#define QEMU_OPENRISC_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#define TYPE_OPENRISC_CPU "or32"
+
+#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))
+
+#endif /* QEMU_OPENRISC_CPU_QOM_H */
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
new file mode 100644
index 0000000..01e65a2
--- /dev/null
+++ b/target-openrisc/cpu.c
@@ -0,0 +1,74 @@
+/*
+ * 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 "cpu-qom.h"
+#include "qemu-common.h"
+
+
+/* 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;
+
+ occ->parent_reset(s);
+
+ openrisc_reset(env);
+
+}
+
+static void openrisc_cpu_initfn(Object *obj)
+{
+ OPENRISCCPU *cpu = OPENRISC_CPU(obj);
+ CPUOPENRISCState *env = &cpu->env;
+
+ cpu_exec_init(env);
+
+ env->flags = 0;
+
+ cpu_reset(CPU(cpu));
+}
+
+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 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)
+{
+ type_register_static(&openrisc_cpu_type_info);
+}
+
+type_init(openrisc_cpu_register_types)
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
new file mode 100644
index 0000000..11ea13c
--- /dev/null
+++ b/target-openrisc/cpu.h
@@ -0,0 +1,299 @@
+/*
+ * 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"
+
+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
+
+#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)
+
+/* 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
+
+/* 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
+};
+
+/* 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,
+ 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),
+};
+
+/* 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),
+};
+
+/* 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,
+ 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),
+};
+
+typedef struct tlb_entry {
+ uint32_t mr;
+ uint32_t tr;
+} tlb_entry;
+
+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 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 */
+ void *irq[32]; /* Interrupt irq input */
+ uint32_t fpcsr; /* Float register */
+ float_status fp_status;
+ 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 */
+
+#if !defined(CONFIG_USER_ONLY)
+ /* MMU */
+ tlb_entry(*itlb)[ITLB_SIZE], (*dtlb)[DTLB_SIZE];
+ 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);
+
+ /* Internal Timer */
+ 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
+
+ CPU_COMMON
+};
+
+#include "cpu-qom.h"
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
+CPUOPENRISCState *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_init cpu_openrisc_init
+#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
+
+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);
+
+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
+
+#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,
+ target_ulong *pc,
+ target_ulong *cs_base, int *flags)
+{
+ *pc = env->pc;
+ *cs_base = 0;
+ *flags = env->flags;
+}
+
+static inline int cpu_mmu_index(CPUOPENRISCState *env)
+{
+ if (!(env->sr & SR_IME)) {
+ return MMU_NOMMU_IDX;
+ }
+ 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 env->interrupt_request & (CPU_INTERRUPT_HARD |
+ CPU_INTERRUPT_TIMER);
+}
+
+#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..dcb61c9
--- /dev/null
+++ b/target-openrisc/helper.c
@@ -0,0 +1,67 @@
+/*
+ * 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 Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "helper.h"
+#include "host-utils.h"
+#if !defined(CONFIG_USER_ONLY)
+#include "hw/loader.h"
+#endif
+
+typedef struct {
+ const char *name;
+} OPENRISCDef;
+
+static const OPENRISCDef openrisc_defs[] = {
+ {.name = "or1200",}
+};
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
+{
+ int i;
+
+ cpu_fprintf(f, "Available CPUs:\n");
+ for (i = 0; i < ARRAY_SIZE(openrisc_defs); ++i) {
+ cpu_fprintf(f, " %s\n", openrisc_defs[i].name);
+ }
+}
+
+CPUOPENRISCState *cpu_openrisc_init(const char *cpu_model)
+{
+ CPUOPENRISCState *env;
+ static int tcg_inited;
+
+ env = g_malloc0(sizeof(*env));
+ memset(env, 0, sizeof(*env));
+ cpu_exec_init(env);
+ qemu_init_vcpu(env);
+ if (!tcg_inited) {
+ tcg_inited = 1;
+ openrisc_translate_init();
+ }
+
+ return env;
+}
+
+void do_interrupt(CPUOPENRISCState *env)
+{
+}
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
new file mode 100644
index 0000000..103d9b4
--- /dev/null
+++ b/target-openrisc/helper.h
@@ -0,0 +1,23 @@
+/*
+ * 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 Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#include "def-helper.h"
+
+#include "def-helper.h"
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
new file mode 100644
index 0000000..c7ac0ea
--- /dev/null
+++ b/target-openrisc/machine.c
@@ -0,0 +1,76 @@
+/*
+ * 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 Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "kvm.h"
+
+static const VMStateDescription vmstate_cpu = {
+ .name = "cpu",
+ .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)
+{
+ CPUOPENRISCState *env = (CPUOPENRISCState *)opaque;
+ unsigned int i;
+
+ for (i = 0; i < 32; i++) {
+ qemu_put_betls(f, &env->gpr[i]);
+ }
+
+ qemu_put_betls(f, &env->epcr);
+ qemu_put_betls(f, &env->eear);
+ qemu_put_betls(f, &env->esr);
+
+ qemu_put_betls(f, &env->sr);
+ qemu_put_be32s(f, &env->pc);
+ qemu_put_be32s(f, &env->fpcsr);
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+ CPUOPENRISCState *env = (CPUOPENRISCState *)opaque;
+ unsigned int i;
+
+ for (i = 0; i < 32; i++) {
+ qemu_get_betls(f, &env->gpr[i]);
+ }
+
+ qemu_get_betls(f, &env->epcr);
+ qemu_get_betls(f, &env->eear);
+ qemu_get_betls(f, &env->esr);
+
+ qemu_get_betls(f, &env->sr);
+ qemu_get_betls(f, &env->pc);
+ qemu_get_be32s(f, &env->fpcsr);
+ tlb_flush(env, 1);
+
+ return 0;
+}
diff --git a/target-openrisc/mem.c b/target-openrisc/mem.c
new file mode 100644
index 0000000..57a0b1b
--- /dev/null
+++ b/target-openrisc/mem.c
@@ -0,0 +1,43 @@
+/*
+ * 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 "helper.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
+
+void openrisc_reset(CPUOPENRISCState *env)
+{
+ env->pc = 0x100;
+ env->sr = SR_FO | SR_SM;
+ env->exception_index = -1;
+}
diff --git a/target-openrisc/mem_helper.c b/target-openrisc/mem_helper.c
new file mode 100644
index 0000000..a2d93c7
--- /dev/null
+++ b/target-openrisc/mem_helper.c
@@ -0,0 +1,46 @@
+/*
+ * 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 Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#include "cpu.h"
+#include "dyngen-exec.h"
+#include "helper.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 *env1, 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..aae483a
--- /dev/null
+++ b/target-openrisc/translate.c
@@ -0,0 +1,90 @@
+/*
+ * 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 Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#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"
+
+#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;
+ target_ulong ppc, npc;
+ uint32_t tb_flags;
+ uint32_t is_jmp;
+ uint32_t mem_idx;
+ int singlestep_enabled;
+ uint32_t delayed_branch;
+} DisasContext;
+
+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
陳韋任
2012-05-17 09:38:12 UTC
Permalink
Post by Jia Liu
+CPUOPENRISCState *cpu_openrisc_init(const char *cpu_model)
+{
+ CPUOPENRISCState *env;
+ static int tcg_inited;
+
+ env = g_malloc0(sizeof(*env));
+ memset(env, 0, sizeof(*env));
^^^^^^
No need to memset env to zero, since g_malloc0 already did it for you.
Post by Jia Liu
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
new file mode 100644
index 0000000..103d9b4
--- /dev/null
+++ b/target-openrisc/helper.h
[snip]
Post by Jia Liu
+#include "def-helper.h"
+
+#include "def-helper.h"
I suppose you only need to #include "def-helper.h" once?

Regards,
chenwj
--
Wei-Ren Chen (陳韋任)
Computer Systems Lab, Institute of Information Science,
Academia Sinica, Taiwan (R.O.C.)
Tel:886-2-2788-3799 #1667
Homepage: http://people.cs.nctu.edu.tw/~chenwj
Andreas Färber
2012-05-17 14:14:15 UTC
Permalink
Post by Jia Liu
add the openrisc target stub and basic implementation.
---
diff --git a/target-openrisc/cpu-qom.h b/target-openrisc/cpu-qom.h
new file mode 100644
index 0000000..8c936df
--- /dev/null
+++ b/target-openrisc/cpu-qom.h
First of all, if you design your new target cleanly, there's no strict
need for a cpu-qom.h header - it mainly served to separate new QOM code
from legacy code. If you want, you can put the code directly into cpu.h
just as well.
Post by Jia Liu
@@ -0,0 +1,70 @@
+/*
+ * QEMU Openrisc CPU
+ *
Minor nitpick: I guess this was copied from some other header? Uses a
two-space indentation here and one-space below.
Post by Jia Liu
+ *
+ * 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_CPU_QOM_H
+#define QEMU_OPENRISC_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
Please don't. This was a big mistake of mine that I've been correcting
on the qom-next branch, onto which you should rebase a new target such
as this by the way. It leads to really ugly problems when someone
includes cpu-qom.h and the new struct below is not yet defined for
functions using it there.
Post by Jia Liu
+
+#define TYPE_OPENRISC_CPU "or32"
+
+#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;
Pleave avoid unnecessary uppercase spelling: OpenRISCCPUClass? That
distinguishes it from the all-uppercase cast macros.

Or OpenriscCPUClass as you spell it elsewhere?
Post by Jia Liu
+
+/**
+ *
+ * A Openrisc CPU.
+ */
+typedef struct OPENRISCCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUOPENRISCState env;
+} OPENRISCCPU;
OpenRISCCPU? OpenriscCPU?
Post by Jia Liu
+
+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))
+
+#endif /* QEMU_OPENRISC_CPU_QOM_H */
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
new file mode 100644
index 0000000..01e65a2
--- /dev/null
+++ b/target-openrisc/cpu.c
@@ -0,0 +1,74 @@
+/*
+ * 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 "cpu-qom.h"
cpu.h already does #include "cpu-qom.h", so no need to include it here
again.
Post by Jia Liu
+#include "qemu-common.h"
+
+
+/* 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;
+
+ occ->parent_reset(s);
+
+ openrisc_reset(env);
Shouldn't this be inline here? And don't forget to reset the common
fields, too. The usual way I think is to let a helper signal an
interrupt_request and then from outside the thread call cpu_reset(),
which will call the above function.

Be warned that over time more and more fields will be moved from
CPU_COMMON into CPUState, so env is not ideal long-term.
Post by Jia Liu
+
+}
+
+static void openrisc_cpu_initfn(Object *obj)
+{
+ OPENRISCCPU *cpu = OPENRISC_CPU(obj);
+ CPUOPENRISCState *env = &cpu->env;
+
+ cpu_exec_init(env);
+
+ env->flags = 0;
+
+ cpu_reset(CPU(cpu));
This should be part of a realizefn, not of the initfn. We don't have the
former just yet, so it should go into the cpu_xxx_init() function for now.
Post by Jia Liu
+}
+
+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 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)
+{
+ type_register_static(&openrisc_cpu_type_info);
+}
+
+type_init(openrisc_cpu_register_types)
[...]
Post by Jia Liu
diff --git a/target-openrisc/helper.c b/target-openrisc/helper.c
new file mode 100644
index 0000000..dcb61c9
--- /dev/null
+++ b/target-openrisc/helper.c
@@ -0,0 +1,67 @@
+/*
+ * Openrisc helpers
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "helper.h"
+#include "host-utils.h"
+#if !defined(CONFIG_USER_ONLY)
+#include "hw/loader.h"
+#endif
+
+typedef struct {
+ const char *name;
+} OPENRISCDef;
+
+static const OPENRISCDef openrisc_defs[] = {
+ {.name = "or1200",}
+};
Don't. Use QOM subclasses for modelling CPU types.
Post by Jia Liu
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
+{
+ int i;
+
+ cpu_fprintf(f, "Available CPUs:\n");
+ for (i = 0; i < ARRAY_SIZE(openrisc_defs); ++i) {
+ cpu_fprintf(f, " %s\n", openrisc_defs[i].name);
+ }
+}
This can then walk types to list models, cf. target-arm.
Post by Jia Liu
+
+CPUOPENRISCState *cpu_openrisc_init(const char *cpu_model)
This should return OpenRISCCPU instead.

cpu_init() can return CPUOpenRISCState for backwards compatibility,
there's lots of examples on the list.
Post by Jia Liu
+{
+ CPUOPENRISCState *env;
+ static int tcg_inited;
+
+ env = g_malloc0(sizeof(*env));
No. This needs to instantiate the QOM type with object_new().
Post by Jia Liu
+ memset(env, 0, sizeof(*env));
+ cpu_exec_init(env);
This is already in the initn, so drop it here.
Post by Jia Liu
+ qemu_init_vcpu(env);
This is the second candidate for a realizefn.
Post by Jia Liu
+ if (!tcg_inited) {
if (tcg_enabled() && !tcg_inited) {

Note that besides TCG there's qtest that your new target should support.
Post by Jia Liu
+ tcg_inited = 1;
+ openrisc_translate_init();
+ }
+
+ return env;
+}
+
+void do_interrupt(CPUOPENRISCState *env)
+{
+}
[...]
Post by Jia Liu
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
new file mode 100644
index 0000000..c7ac0ea
--- /dev/null
+++ b/target-openrisc/machine.c
@@ -0,0 +1,76 @@
+/*
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "kvm.h"
+
+static const VMStateDescription vmstate_cpu = {
+ .name = "cpu",
+ .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)
+{
+ CPUOPENRISCState *env = (CPUOPENRISCState *)opaque;
+ unsigned int i;
+
+ for (i = 0; i < 32; i++) {
+ qemu_put_betls(f, &env->gpr[i]);
+ }
+
+ qemu_put_betls(f, &env->epcr);
+ qemu_put_betls(f, &env->eear);
+ qemu_put_betls(f, &env->esr);
+
+ qemu_put_betls(f, &env->sr);
+ qemu_put_be32s(f, &env->pc);
+ qemu_put_be32s(f, &env->fpcsr);
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+ CPUOPENRISCState *env = (CPUOPENRISCState *)opaque;
+ unsigned int i;
+
+ for (i = 0; i < 32; i++) {
+ qemu_get_betls(f, &env->gpr[i]);
+ }
+
+ qemu_get_betls(f, &env->epcr);
+ qemu_get_betls(f, &env->eear);
+ qemu_get_betls(f, &env->esr);
+
+ qemu_get_betls(f, &env->sr);
+ qemu_get_betls(f, &env->pc);
+ qemu_get_be32s(f, &env->fpcsr);
+ tlb_flush(env, 1);
+
+ return 0;
+}
[snip]

This is a mix of two ways of doing the same thing. You should only use
VMState for new code.

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-18 01:34:26 UTC
Permalink
Hi Andreas,

Thanks for your comment.
Post by Andreas Färber
Post by Jia Liu
add the openrisc target stub and basic implementation.
---
diff --git a/target-openrisc/cpu-qom.h b/target-openrisc/cpu-qom.h
new file mode 100644
index 0000000..8c936df
--- /dev/null
+++ b/target-openrisc/cpu-qom.h
First of all, if you design your new target cleanly, there's no strict
need for a cpu-qom.h header - it mainly served to separate new QOM code
from legacy code. If you want, you can put the code directly into cpu.h
just as well.
I see the other targets patched by QOM, so I copied the code from mips
without fully understand.
Post by Andreas Färber
Post by Jia Liu
@@ -0,0 +1,70 @@
+/*
+ *  QEMU Openrisc CPU
+ *
Minor nitpick: I guess this was copied from some other header? Uses a
two-space indentation here and one-space below.
Thanks, I'll fix this all in V2.
Post by Andreas Färber
Post by Jia Liu
+ *
+ * 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_CPU_QOM_H
+#define QEMU_OPENRISC_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
Please don't. This was a big mistake of mine that I've been correcting
on the qom-next branch, onto which you should rebase a new target such
as this by the way. It leads to really ugly problems when someone
includes cpu-qom.h and the new struct below is not yet defined for
functions using it there.
I'm not truly understand it, did you mean I should not use QOM until
you make it more perfect?
Post by Andreas Färber
Post by Jia Liu
+
+#define TYPE_OPENRISC_CPU "or32"
+
+#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;
Pleave avoid unnecessary uppercase spelling: OpenRISCCPUClass? That
distinguishes it from the all-uppercase cast macros.
Or OpenriscCPUClass as you spell it elsewhere?
I used OPENRISCCPU in the code, if it is not good, I can change it
into OpenriscCPU.
Post by Andreas Färber
Post by Jia Liu
+
+/**
+ *
+ * A Openrisc CPU.
+ */
+typedef struct OPENRISCCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUOPENRISCState env;
+} OPENRISCCPU;
OpenRISCCPU? OpenriscCPU?
Post by Jia Liu
+
+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))
+
+#endif /* QEMU_OPENRISC_CPU_QOM_H */
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
new file mode 100644
index 0000000..01e65a2
--- /dev/null
+++ b/target-openrisc/cpu.c
@@ -0,0 +1,74 @@
+/*
+ *  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 "cpu-qom.h"
cpu.h already does #include "cpu-qom.h", so no need to include it here
again.
thanks, I'll delete it.
Post by Andreas Färber
Post by Jia Liu
+#include "qemu-common.h"
+
+
+/* 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;
+
+    occ->parent_reset(s);
+
+    openrisc_reset(env);
Shouldn't this be inline here? And don't forget to reset the common
fields, too. The usual way I think is to let a helper signal an
interrupt_request and then from outside the thread call cpu_reset(),
which will call the above function.
Thanks, I'll check this, and reset the other fields.
Post by Andreas Färber
Be warned that over time more and more fields will be moved from
CPU_COMMON into CPUState, so env is not ideal long-term.
did you mean I should use a memset(0) clean the all fields here?
Post by Andreas Färber
Post by Jia Liu
+
+}
+
+static void openrisc_cpu_initfn(Object *obj)
+{
+    OPENRISCCPU *cpu = OPENRISC_CPU(obj);
+    CPUOPENRISCState *env = &cpu->env;
+
+    cpu_exec_init(env);
+
+    env->flags = 0;
+
+    cpu_reset(CPU(cpu));
This should be part of a realizefn, not of the initfn. We don't have the
former just yet, so it should go into the cpu_xxx_init() function for now.
sorry, you mean I should rename it static void
openrisc_cpu_realizefn(Object *obj)?
Post by Andreas Färber
Post by Jia Liu
+}
+
+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 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)
+{
+    type_register_static(&openrisc_cpu_type_info);
+}
+
+type_init(openrisc_cpu_register_types)
[...]
Post by Jia Liu
diff --git a/target-openrisc/helper.c b/target-openrisc/helper.c
new file mode 100644
index 0000000..dcb61c9
--- /dev/null
+++ b/target-openrisc/helper.c
@@ -0,0 +1,67 @@
+/*
+ * Openrisc helpers
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "helper.h"
+#include "host-utils.h"
+#if !defined(CONFIG_USER_ONLY)
+#include "hw/loader.h"
+#endif
+
+typedef struct {
+    const char *name;
+} OPENRISCDef;
+
+static const OPENRISCDef openrisc_defs[] = {
+    {.name = "or1200",}
+};
Don't. Use QOM subclasses for modelling CPU types.
OK, let me find some code to copy. I'm not sure about QOM for now, yet.
Post by Andreas Färber
Post by Jia Liu
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    int i;
+
+    cpu_fprintf(f, "Available CPUs:\n");
+    for (i = 0; i < ARRAY_SIZE(openrisc_defs); ++i) {
+        cpu_fprintf(f, "  %s\n", openrisc_defs[i].name);
+    }
+}
This can then walk types to list models, cf. target-arm.
Thanks, I'll read ARM's code.
Post by Andreas Färber
Post by Jia Liu
+
+CPUOPENRISCState *cpu_openrisc_init(const char *cpu_model)
This should return OpenRISCCPU instead.
cpu_init() can return CPUOpenRISCState for backwards compatibility,
there's lots of examples on the list.
Thanks, I'll check and fix.
Post by Andreas Färber
Post by Jia Liu
+{
+    CPUOPENRISCState *env;
+    static int tcg_inited;
+
+    env = g_malloc0(sizeof(*env));
No. This needs to instantiate the QOM type with object_new().
Thanks, I'll use object_new()
Post by Andreas Färber
Post by Jia Liu
+    memset(env, 0, sizeof(*env));
+    cpu_exec_init(env);
This is already in the initn, so drop it here.
Thank you, I'll drop it.
Post by Andreas Färber
Post by Jia Liu
+    qemu_init_vcpu(env);
This is the second candidate for a realizefn.
Post by Jia Liu
+    if (!tcg_inited) {
if (tcg_enabled() && !tcg_inited) {
Note that besides TCG there's qtest that your new target should support.
Sorry, I'm not sure about this.
Post by Andreas Färber
Post by Jia Liu
+        tcg_inited = 1;
+        openrisc_translate_init();
+    }
+
+    return env;
+}
+
+void do_interrupt(CPUOPENRISCState *env)
+{
+}
[...]
Post by Jia Liu
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
new file mode 100644
index 0000000..c7ac0ea
--- /dev/null
+++ b/target-openrisc/machine.c
@@ -0,0 +1,76 @@
+/*
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "kvm.h"
+
+static const VMStateDescription vmstate_cpu = {
+    .name = "cpu",
+    .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)
+{
+    CPUOPENRISCState *env = (CPUOPENRISCState *)opaque;
+    unsigned int i;
+
+    for (i = 0; i < 32; i++) {
+        qemu_put_betls(f, &env->gpr[i]);
+    }
+
+    qemu_put_betls(f, &env->epcr);
+    qemu_put_betls(f, &env->eear);
+    qemu_put_betls(f, &env->esr);
+
+    qemu_put_betls(f, &env->sr);
+    qemu_put_be32s(f, &env->pc);
+    qemu_put_be32s(f, &env->fpcsr);
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    CPUOPENRISCState *env = (CPUOPENRISCState *)opaque;
+    unsigned int i;
+
+    for (i = 0; i < 32; i++) {
+        qemu_get_betls(f, &env->gpr[i]);
+    }
+
+    qemu_get_betls(f, &env->epcr);
+    qemu_get_betls(f, &env->eear);
+    qemu_get_betls(f, &env->esr);
+
+    qemu_get_betls(f, &env->sr);
+    qemu_get_betls(f, &env->pc);
+    qemu_get_be32s(f, &env->fpcsr);
+    tlb_flush(env, 1);
+
+    return 0;
+}
[snip]
This is a mix of two ways of doing the same thing. You should only use
VMState for new code.
did you mean I should not use QEMUFile?
Post by Andreas Färber
Andreas
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
Thanks very much for your comment.
And I hope I can get more information from you for I can not
understand all of your comment, your comment is good and useful, but
for me, a newbie, I need more time to follow your step.

Regard,
Jia.
陳韋任
2012-05-18 02:30:15 UTC
Permalink
Post by Jia Liu
Post by Andreas Färber
Pleave avoid unnecessary uppercase spelling: OpenRISCCPUClass? That
distinguishes it from the all-uppercase cast macros.
Or OpenriscCPUClass as you spell it elsewhere?
I used OPENRISCCPU in the code, if it is not good, I can change it
into OpenriscCPU.
I think OpenRISC is better [1].

Regards,
chenwj

[1] http://en.wikipedia.org/wiki/OpenRISC
--
Wei-Ren Chen (陳韋任)
Computer Systems Lab, Institute of Information Science,
Academia Sinica, Taiwan (R.O.C.)
Tel:886-2-2788-3799 #1667
Homepage: http://people.cs.nctu.edu.tw/~chenwj
陳韋任
2012-05-18 02:56:49 UTC
Permalink
Post by Jia Liu
Post by Andreas Färber
This is a mix of two ways of doing the same thing. You should only use
VMState for new code.
did you mean I should not use QEMUFile?
I guess what Andreas means is there are two ways to do cpu_save/cpu_load,
the one you wrote is the old style. For the brand new target, you should use
VMState completely. You can take target-lm32/machine.c as an example.

---
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 vmstate_load_state(f, &vmstate_cpu, opaque, version_id);
}
---

Leave to vmstate_save_state/vmstate_load_state (savevm.c) do the real things.

Regards,
chenwj
--
Wei-Ren Chen (陳韋任)
Computer Systems Lab, Institute of Information Science,
Academia Sinica, Taiwan (R.O.C.)
Tel:886-2-2788-3799 #1667
Homepage: http://people.cs.nctu.edu.tw/~chenwj
Andreas Färber
2012-05-20 14:14:26 UTC
Permalink
Post by 陳韋任
Post by Jia Liu
Post by Andreas Färber
This is a mix of two ways of doing the same thing. You should only use
VMState for new code.
did you mean I should not use QEMUFile?
I guess what Andreas means is there are two ways to do cpu_save/cpu_load,
the one you wrote is the old style. For the brand new target, you should use
VMState completely.
Exactly what I meant. Although I'm working towards making that even
easier by leveraging code from Juan's vmstate series and having the CPUs
just store a pointer to their VMStateDescription like devices do.

Andreas
Post by 陳韋任
You can take target-lm32/machine.c as an example.
---
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 vmstate_load_state(f, &vmstate_cpu, opaque, version_id);
}
---
Leave to vmstate_save_state/vmstate_load_state (savevm.c) do the real things.
Regards,
chenwj
--
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-21 03:01:37 UTC
Permalink
Hi Andreas,

Thanks, I'm trying fix them all.
Post by Andreas Färber
Post by Jia Liu
add the openrisc target stub and basic implementation.
---
diff --git a/target-openrisc/cpu-qom.h b/target-openrisc/cpu-qom.h
new file mode 100644
index 0000000..8c936df
--- /dev/null
+++ b/target-openrisc/cpu-qom.h
First of all, if you design your new target cleanly, there's no strict
need for a cpu-qom.h header - it mainly served to separate new QOM code
from legacy code. If you want, you can put the code directly into cpu.h
just as well.
Post by Jia Liu
@@ -0,0 +1,70 @@
+/*
+ *  QEMU Openrisc CPU
+ *
Minor nitpick: I guess this was copied from some other header? Uses a
two-space indentation here and one-space below.
Post by Jia Liu
+ *
+ * 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_CPU_QOM_H
+#define QEMU_OPENRISC_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
Please don't. This was a big mistake of mine that I've been correcting
on the qom-next branch, onto which you should rebase a new target such
as this by the way. It leads to really ugly problems when someone
includes cpu-qom.h and the new struct below is not yet defined for
functions using it there.
Post by Jia Liu
+
+#define TYPE_OPENRISC_CPU "or32"
+
+#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;
Pleave avoid unnecessary uppercase spelling: OpenRISCCPUClass? That
distinguishes it from the all-uppercase cast macros.
Or OpenriscCPUClass as you spell it elsewhere?
Post by Jia Liu
+
+/**
+ *
+ * A Openrisc CPU.
+ */
+typedef struct OPENRISCCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUOPENRISCState env;
+} OPENRISCCPU;
OpenRISCCPU? OpenriscCPU?
Post by Jia Liu
+
+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))
+
+#endif /* QEMU_OPENRISC_CPU_QOM_H */
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
new file mode 100644
index 0000000..01e65a2
--- /dev/null
+++ b/target-openrisc/cpu.c
@@ -0,0 +1,74 @@
+/*
+ *  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 "cpu-qom.h"
cpu.h already does #include "cpu-qom.h", so no need to include it here
again.
Post by Jia Liu
+#include "qemu-common.h"
+
+
+/* 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;
+
+    occ->parent_reset(s);
+
+    openrisc_reset(env);
Shouldn't this be inline here? And don't forget to reset the common
fields, too. The usual way I think is to let a helper signal an
interrupt_request and then from outside the thread call cpu_reset(),
which will call the above function.
Be warned that over time more and more fields will be moved from
CPU_COMMON into CPUState, so env is not ideal long-term.
Post by Jia Liu
+
+}
+
+static void openrisc_cpu_initfn(Object *obj)
+{
+    OPENRISCCPU *cpu = OPENRISC_CPU(obj);
+    CPUOPENRISCState *env = &cpu->env;
+
+    cpu_exec_init(env);
+
+    env->flags = 0;
+
+    cpu_reset(CPU(cpu));
This should be part of a realizefn, not of the initfn. We don't have the
former just yet, so it should go into the cpu_xxx_init() function for now.
Post by Jia Liu
+}
+
+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 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)
+{
+    type_register_static(&openrisc_cpu_type_info);
+}
+
+type_init(openrisc_cpu_register_types)
[...]
Post by Jia Liu
diff --git a/target-openrisc/helper.c b/target-openrisc/helper.c
new file mode 100644
index 0000000..dcb61c9
--- /dev/null
+++ b/target-openrisc/helper.c
@@ -0,0 +1,67 @@
+/*
+ * Openrisc helpers
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "helper.h"
+#include "host-utils.h"
+#if !defined(CONFIG_USER_ONLY)
+#include "hw/loader.h"
+#endif
+
+typedef struct {
+    const char *name;
+} OPENRISCDef;
+
+static const OPENRISCDef openrisc_defs[] = {
+    {.name = "or1200",}
+};
Don't. Use QOM subclasses for modelling CPU types.
Post by Jia Liu
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    int i;
+
+    cpu_fprintf(f, "Available CPUs:\n");
+    for (i = 0; i < ARRAY_SIZE(openrisc_defs); ++i) {
+        cpu_fprintf(f, "  %s\n", openrisc_defs[i].name);
+    }
+}
This can then walk types to list models, cf. target-arm.
Post by Jia Liu
+
+CPUOPENRISCState *cpu_openrisc_init(const char *cpu_model)
This should return OpenRISCCPU instead.
cpu_init() can return CPUOpenRISCState for backwards compatibility,
there's lots of examples on the list.
Post by Jia Liu
+{
+    CPUOPENRISCState *env;
+    static int tcg_inited;
+
+    env = g_malloc0(sizeof(*env));
No. This needs to instantiate the QOM type with object_new().
Post by Jia Liu
+    memset(env, 0, sizeof(*env));
+    cpu_exec_init(env);
This is already in the initn, so drop it here.
Post by Jia Liu
+    qemu_init_vcpu(env);
This is the second candidate for a realizefn.
Post by Jia Liu
+    if (!tcg_inited) {
if (tcg_enabled() && !tcg_inited) {
Note that besides TCG there's qtest that your new target should support.
Post by Jia Liu
+        tcg_inited = 1;
+        openrisc_translate_init();
+    }
+
+    return env;
+}
+
+void do_interrupt(CPUOPENRISCState *env)
+{
+}
[...]
Post by Jia Liu
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
new file mode 100644
index 0000000..c7ac0ea
--- /dev/null
+++ b/target-openrisc/machine.c
@@ -0,0 +1,76 @@
+/*
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "kvm.h"
+
+static const VMStateDescription vmstate_cpu = {
+    .name = "cpu",
+    .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)
+{
+    CPUOPENRISCState *env = (CPUOPENRISCState *)opaque;
+    unsigned int i;
+
+    for (i = 0; i < 32; i++) {
+        qemu_put_betls(f, &env->gpr[i]);
+    }
+
+    qemu_put_betls(f, &env->epcr);
+    qemu_put_betls(f, &env->eear);
+    qemu_put_betls(f, &env->esr);
+
+    qemu_put_betls(f, &env->sr);
+    qemu_put_be32s(f, &env->pc);
+    qemu_put_be32s(f, &env->fpcsr);
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    CPUOPENRISCState *env = (CPUOPENRISCState *)opaque;
+    unsigned int i;
+
+    for (i = 0; i < 32; i++) {
+        qemu_get_betls(f, &env->gpr[i]);
+    }
+
+    qemu_get_betls(f, &env->epcr);
+    qemu_get_betls(f, &env->eear);
+    qemu_get_betls(f, &env->esr);
+
+    qemu_get_betls(f, &env->sr);
+    qemu_get_betls(f, &env->pc);
+    qemu_get_be32s(f, &env->fpcsr);
+    tlb_flush(env, 1);
+
+    return 0;
+}
[snip]
This is a mix of two ways of doing the same thing. You should only use
VMState for new code.
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.
Blue Swirl
2012-05-19 08:51:06 UTC
Permalink
Post by Jia Liu
add the openrisc target stub and basic implementation.
---
 Makefile.target                  |    3 +
 arch_init.c                      |    2 +
 arch_init.h                      |    1 +
 configure                        |    8 +-
 cpu-exec.c                       |    2 +
 default-configs/or32-softmmu.mak |    6 +
 elf.h                            |    2 +
 poison.h                         |    1 +
 target-openrisc/cpu-qom.h        |   70 +++++++++
 target-openrisc/cpu.c            |   74 ++++++++++
 target-openrisc/cpu.h            |  299 ++++++++++++++++++++++++++++++++++++++
 target-openrisc/helper.c         |   67 +++++++++
 target-openrisc/helper.h         |   23 +++
 target-openrisc/machine.c        |   76 ++++++++++
 target-openrisc/mem.c            |   43 ++++++
 target-openrisc/mem_helper.c     |   46 ++++++
 target-openrisc/translate.c      |   90 ++++++++++++
 17 files changed, 812 insertions(+), 1 deletion(-)
 create mode 100644 default-configs/or32-softmmu.mak
 create mode 100644 target-openrisc/cpu-qom.h
 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/helper.h
 create mode 100644 target-openrisc/machine.c
 create mode 100644 target-openrisc/mem.c
 create mode 100644 target-openrisc/mem_helper.c
 create mode 100644 target-openrisc/translate.c
diff --git a/Makefile.target b/Makefile.target
index 1582904..0ffb29c 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) += mem.o mem_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..63e2372 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
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
Probably not needed?
Post by Jia Liu
+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-qom.h b/target-openrisc/cpu-qom.h
new file mode 100644
index 0000000..8c936df
--- /dev/null
+++ b/target-openrisc/cpu-qom.h
@@ -0,0 +1,70 @@
+/*
+ *  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/>.
+ */
+
+#ifndef QEMU_OPENRISC_CPU_QOM_H
+#define QEMU_OPENRISC_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#define TYPE_OPENRISC_CPU "or32"
+
+#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))
+
+#endif /* QEMU_OPENRISC_CPU_QOM_H */
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
new file mode 100644
index 0000000..01e65a2
--- /dev/null
+++ b/target-openrisc/cpu.c
@@ -0,0 +1,74 @@
+/*
+ *  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 "cpu-qom.h"
+#include "qemu-common.h"
+
+
+/* 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;
+
+    occ->parent_reset(s);
+
+    openrisc_reset(env);
+
+}
+
+static void openrisc_cpu_initfn(Object *obj)
+{
+    OPENRISCCPU *cpu = OPENRISC_CPU(obj);
+    CPUOPENRISCState *env = &cpu->env;
+
+    cpu_exec_init(env);
+
+    env->flags = 0;
+
+    cpu_reset(CPU(cpu));
+}
+
+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 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)
+{
+    type_register_static(&openrisc_cpu_type_info);
+}
+
+type_init(openrisc_cpu_register_types)
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
new file mode 100644
index 0000000..11ea13c
--- /dev/null
+++ b/target-openrisc/cpu.h
@@ -0,0 +1,299 @@
+/*
+ *  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"
+
+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
+
+#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)
+
+/* 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
+
+/* 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
+};
+
+/* 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,
+    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),
+};
+
+/* 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),
+};
+
+/* 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,
+    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),
+};
+
+typedef struct tlb_entry {
+    uint32_t mr;
+    uint32_t tr;
+} tlb_entry;
TLBEntry
Post by Jia Liu
+
+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 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 */
+    void *irq[32];          /* Interrupt irq input */
CPU reset usually zeros all fields up to breakpoints field in
CPU_COMMON. Then these and the MMU function pointers below would be
broken, please move below CPU_COMMON.
Post by Jia Liu
+    uint32_t fpcsr;         /* Float register */
+    float_status fp_status;
+    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 */
+
+#if !defined(CONFIG_USER_ONLY)
+    /* MMU */
+    tlb_entry(*itlb)[ITLB_SIZE], (*dtlb)[DTLB_SIZE];
+    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);
+
+    /* Internal Timer */
+    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
+
+    CPU_COMMON
+};
+
+#include "cpu-qom.h"
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
+CPUOPENRISCState *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_init cpu_openrisc_init
+#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
+
+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);
+
+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
+
+#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,
+                                        target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->pc;
+    *cs_base = 0;
+    *flags = env->flags;
Maybe it's fixed in later patches, but this does not look correct, the
TB flags tell when the CPU mode is compatible with the previously
generated translated blocks. I'd expect only MMU enable/disable flags
to be included here (assuming that if MMU state changes, TBs are
flushed), supervisor flag also if the translator checks the status
during translation.
Post by Jia Liu
+}
+
+static inline int cpu_mmu_index(CPUOPENRISCState *env)
+{
+    if (!(env->sr & SR_IME)) {
+        return MMU_NOMMU_IDX;
+    }
+    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 env->interrupt_request & (CPU_INTERRUPT_HARD |
+                                     CPU_INTERRUPT_TIMER);
+}
+
+#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..dcb61c9
--- /dev/null
+++ b/target-openrisc/helper.c
@@ -0,0 +1,67 @@
+/*
+ * Openrisc helpers
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "helper.h"
+#include "host-utils.h"
+#if !defined(CONFIG_USER_ONLY)
+#include "hw/loader.h"
Trim?
Post by Jia Liu
+#endif
+
+typedef struct {
+    const char *name;
+} OPENRISCDef;
+
+static const OPENRISCDef openrisc_defs[] = {
+    {.name = "or1200",}
+};
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    int i;
+
+    cpu_fprintf(f, "Available CPUs:\n");
+    for (i = 0; i < ARRAY_SIZE(openrisc_defs); ++i) {
+        cpu_fprintf(f, "  %s\n", openrisc_defs[i].name);
+    }
+}
+
+CPUOPENRISCState *cpu_openrisc_init(const char *cpu_model)
+{
+    CPUOPENRISCState *env;
+    static int tcg_inited;
+
+    env = g_malloc0(sizeof(*env));
+    memset(env, 0, sizeof(*env));
+    cpu_exec_init(env);
+    qemu_init_vcpu(env);
+    if (!tcg_inited) {
To enable qtest, please add && tcg_enabled().
Post by Jia Liu
+        tcg_inited = 1;
+        openrisc_translate_init();
+    }
+
+    return env;
+}
+
+void do_interrupt(CPUOPENRISCState *env)
+{
+}
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
new file mode 100644
index 0000000..103d9b4
--- /dev/null
+++ b/target-openrisc/helper.h
@@ -0,0 +1,23 @@
+/*
+ * OpenRISC helper defines
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "def-helper.h"
+
+#include "def-helper.h"
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
new file mode 100644
index 0000000..c7ac0ea
--- /dev/null
+++ b/target-openrisc/machine.c
@@ -0,0 +1,76 @@
+/*
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "kvm.h"
+
+static const VMStateDescription vmstate_cpu = {
+    .name = "cpu",
+    .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)
+{
+    CPUOPENRISCState *env = (CPUOPENRISCState *)opaque;
+    unsigned int i;
+
+    for (i = 0; i < 32; i++) {
+        qemu_put_betls(f, &env->gpr[i]);
+    }
+
+    qemu_put_betls(f, &env->epcr);
+    qemu_put_betls(f, &env->eear);
+    qemu_put_betls(f, &env->esr);
+
+    qemu_put_betls(f, &env->sr);
+    qemu_put_be32s(f, &env->pc);
+    qemu_put_be32s(f, &env->fpcsr);
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    CPUOPENRISCState *env = (CPUOPENRISCState *)opaque;
+    unsigned int i;
+
+    for (i = 0; i < 32; i++) {
+        qemu_get_betls(f, &env->gpr[i]);
+    }
+
+    qemu_get_betls(f, &env->epcr);
+    qemu_get_betls(f, &env->eear);
+    qemu_get_betls(f, &env->esr);
+
+    qemu_get_betls(f, &env->sr);
+    qemu_get_betls(f, &env->pc);
+    qemu_get_be32s(f, &env->fpcsr);
+    tlb_flush(env, 1);
+
+    return 0;
+}
diff --git a/target-openrisc/mem.c b/target-openrisc/mem.c
new file mode 100644
index 0000000..57a0b1b
--- /dev/null
+++ b/target-openrisc/mem.c
@@ -0,0 +1,43 @@
+/*
+ *  Openrisc MMU.
+ *
+ *
+ * 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 "helper.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
+
+void openrisc_reset(CPUOPENRISCState *env)
+{
+    env->pc = 0x100;
+    env->sr = SR_FO | SR_SM;
+    env->exception_index = -1;
+}
diff --git a/target-openrisc/mem_helper.c b/target-openrisc/mem_helper.c
new file mode 100644
index 0000000..a2d93c7
--- /dev/null
+++ b/target-openrisc/mem_helper.c
@@ -0,0 +1,46 @@
+/*
+ * OpenRISC mmu helper routines
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "cpu.h"
+#include "dyngen-exec.h"
As I mention in the later patch, this makes AREG0 to be used for
CPUState (also HELPER_CFLAGS is not used to compile mem_helper.o).
Please avoid it, then you also need to adjust CONFIG_TCG_PASS_AREG0
case in configure.
Post by Jia Liu
+#include "helper.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 *env1, 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..aae483a
--- /dev/null
+++ b/target-openrisc/translate.c
@@ -0,0 +1,90 @@
+/*
+ * Openrisc translation
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#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"
+
+#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;
+    target_ulong ppc, npc;
+    uint32_t tb_flags;
+    uint32_t is_jmp;
+    uint32_t mem_idx;
+    int singlestep_enabled;
+    uint32_t delayed_branch;
+} DisasContext;
+
+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-20 14:11:07 UTC
Permalink
Post by Blue Swirl
Post by Jia Liu
+
+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 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 */
+ void *irq[32]; /* Interrupt irq input */
CPU reset usually zeros all fields up to breakpoints field in
CPU_COMMON. Then these and the MMU function pointers below would be
broken, please move below CPU_COMMON.
...or into OpenRISCCPU, if it is not used with offsetof().

/-F
--
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-21 06:25:23 UTC
Permalink
Hi Blue,
Post by Blue Swirl
Post by Jia Liu
add the openrisc target stub and basic implementation.
---
 Makefile.target                  |    3 +
 arch_init.c                      |    2 +
 arch_init.h                      |    1 +
 configure                        |    8 +-
 cpu-exec.c                       |    2 +
 default-configs/or32-softmmu.mak |    6 +
 elf.h                            |    2 +
 poison.h                         |    1 +
 target-openrisc/cpu-qom.h        |   70 +++++++++
 target-openrisc/cpu.c            |   74 ++++++++++
 target-openrisc/cpu.h            |  299 ++++++++++++++++++++++++++++++++++++++
 target-openrisc/helper.c         |   67 +++++++++
 target-openrisc/helper.h         |   23 +++
 target-openrisc/machine.c        |   76 ++++++++++
 target-openrisc/mem.c            |   43 ++++++
 target-openrisc/mem_helper.c     |   46 ++++++
 target-openrisc/translate.c      |   90 ++++++++++++
 17 files changed, 812 insertions(+), 1 deletion(-)
 create mode 100644 default-configs/or32-softmmu.mak
 create mode 100644 target-openrisc/cpu-qom.h
 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/helper.h
 create mode 100644 target-openrisc/machine.c
 create mode 100644 target-openrisc/mem.c
 create mode 100644 target-openrisc/mem_helper.c
 create mode 100644 target-openrisc/translate.c
diff --git a/Makefile.target b/Makefile.target
index 1582904..0ffb29c 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) += mem.o mem_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..63e2372 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
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
Probably not needed?
NE2000 need it.
Post by Blue Swirl
Post by Jia Liu
+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-qom.h b/target-openrisc/cpu-qom.h
new file mode 100644
index 0000000..8c936df
--- /dev/null
+++ b/target-openrisc/cpu-qom.h
@@ -0,0 +1,70 @@
+/*
+ *  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/>.
+ */
+
+#ifndef QEMU_OPENRISC_CPU_QOM_H
+#define QEMU_OPENRISC_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#define TYPE_OPENRISC_CPU "or32"
+
+#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))
+
+#endif /* QEMU_OPENRISC_CPU_QOM_H */
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
new file mode 100644
index 0000000..01e65a2
--- /dev/null
+++ b/target-openrisc/cpu.c
@@ -0,0 +1,74 @@
+/*
+ *  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 "cpu-qom.h"
+#include "qemu-common.h"
+
+
+/* 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;
+
+    occ->parent_reset(s);
+
+    openrisc_reset(env);
+
+}
+
+static void openrisc_cpu_initfn(Object *obj)
+{
+    OPENRISCCPU *cpu = OPENRISC_CPU(obj);
+    CPUOPENRISCState *env = &cpu->env;
+
+    cpu_exec_init(env);
+
+    env->flags = 0;
+
+    cpu_reset(CPU(cpu));
+}
+
+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 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)
+{
+    type_register_static(&openrisc_cpu_type_info);
+}
+
+type_init(openrisc_cpu_register_types)
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
new file mode 100644
index 0000000..11ea13c
--- /dev/null
+++ b/target-openrisc/cpu.h
@@ -0,0 +1,299 @@
+/*
+ *  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"
+
+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
+
+#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)
+
+/* 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
+
+/* 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
+};
+
+/* 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,
+    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),
+};
+
+/* 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),
+};
+
+/* 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,
+    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),
+};
+
+typedef struct tlb_entry {
+    uint32_t mr;
+    uint32_t tr;
+} tlb_entry;
TLBEntry
Post by Jia Liu
+
+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 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 */
+    void *irq[32];          /* Interrupt irq input */
CPU reset usually zeros all fields up to breakpoints field in
CPU_COMMON. Then these and the MMU function pointers below would be
broken, please move below CPU_COMMON.
thanks, I will.
Post by Blue Swirl
Post by Jia Liu
+    uint32_t fpcsr;         /* Float register */
+    float_status fp_status;
+    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 */
+
+#if !defined(CONFIG_USER_ONLY)
+    /* MMU */
+    tlb_entry(*itlb)[ITLB_SIZE], (*dtlb)[DTLB_SIZE];
+    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);
+
+    /* Internal Timer */
+    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
+
+    CPU_COMMON
+};
+
+#include "cpu-qom.h"
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
+CPUOPENRISCState *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_init cpu_openrisc_init
+#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
+
+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);
+
+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
+
+#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,
+                                        target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->pc;
+    *cs_base = 0;
+    *flags = env->flags;
Maybe it's fixed in later patches, but this does not look correct, the
TB flags tell when the CPU mode is compatible with the previously
generated translated blocks. I'd expect only MMU enable/disable flags
to be included here (assuming that if MMU state changes, TBs are
flushed), supervisor flag also if the translator checks the status
during translation.
thank, I'll fix it.
Post by Blue Swirl
Post by Jia Liu
+}
+
+static inline int cpu_mmu_index(CPUOPENRISCState *env)
+{
+    if (!(env->sr & SR_IME)) {
+        return MMU_NOMMU_IDX;
+    }
+    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 env->interrupt_request & (CPU_INTERRUPT_HARD |
+                                     CPU_INTERRUPT_TIMER);
+}
+
+#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..dcb61c9
--- /dev/null
+++ b/target-openrisc/helper.c
@@ -0,0 +1,67 @@
+/*
+ * Openrisc helpers
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "helper.h"
+#include "host-utils.h"
+#if !defined(CONFIG_USER_ONLY)
+#include "hw/loader.h"
Trim?
deleted.
Post by Blue Swirl
Post by Jia Liu
+#endif
+
+typedef struct {
+    const char *name;
+} OPENRISCDef;
+
+static const OPENRISCDef openrisc_defs[] = {
+    {.name = "or1200",}
+};
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    int i;
+
+    cpu_fprintf(f, "Available CPUs:\n");
+    for (i = 0; i < ARRAY_SIZE(openrisc_defs); ++i) {
+        cpu_fprintf(f, "  %s\n", openrisc_defs[i].name);
+    }
+}
+
+CPUOPENRISCState *cpu_openrisc_init(const char *cpu_model)
+{
+    CPUOPENRISCState *env;
+    static int tcg_inited;
+
+    env = g_malloc0(sizeof(*env));
+    memset(env, 0, sizeof(*env));
+    cpu_exec_init(env);
+    qemu_init_vcpu(env);
+    if (!tcg_inited) {
To enable qtest, please add && tcg_enabled().
Post by Jia Liu
+        tcg_inited = 1;
+        openrisc_translate_init();
+    }
+
+    return env;
+}
+
+void do_interrupt(CPUOPENRISCState *env)
+{
+}
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
new file mode 100644
index 0000000..103d9b4
--- /dev/null
+++ b/target-openrisc/helper.h
@@ -0,0 +1,23 @@
+/*
+ * OpenRISC helper defines
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "def-helper.h"
+
+#include "def-helper.h"
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
new file mode 100644
index 0000000..c7ac0ea
--- /dev/null
+++ b/target-openrisc/machine.c
@@ -0,0 +1,76 @@
+/*
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "kvm.h"
+
+static const VMStateDescription vmstate_cpu = {
+    .name = "cpu",
+    .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)
+{
+    CPUOPENRISCState *env = (CPUOPENRISCState *)opaque;
+    unsigned int i;
+
+    for (i = 0; i < 32; i++) {
+        qemu_put_betls(f, &env->gpr[i]);
+    }
+
+    qemu_put_betls(f, &env->epcr);
+    qemu_put_betls(f, &env->eear);
+    qemu_put_betls(f, &env->esr);
+
+    qemu_put_betls(f, &env->sr);
+    qemu_put_be32s(f, &env->pc);
+    qemu_put_be32s(f, &env->fpcsr);
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    CPUOPENRISCState *env = (CPUOPENRISCState *)opaque;
+    unsigned int i;
+
+    for (i = 0; i < 32; i++) {
+        qemu_get_betls(f, &env->gpr[i]);
+    }
+
+    qemu_get_betls(f, &env->epcr);
+    qemu_get_betls(f, &env->eear);
+    qemu_get_betls(f, &env->esr);
+
+    qemu_get_betls(f, &env->sr);
+    qemu_get_betls(f, &env->pc);
+    qemu_get_be32s(f, &env->fpcsr);
+    tlb_flush(env, 1);
+
+    return 0;
+}
diff --git a/target-openrisc/mem.c b/target-openrisc/mem.c
new file mode 100644
index 0000000..57a0b1b
--- /dev/null
+++ b/target-openrisc/mem.c
@@ -0,0 +1,43 @@
+/*
+ *  Openrisc MMU.
+ *
+ *
+ * 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 "helper.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
+
+void openrisc_reset(CPUOPENRISCState *env)
+{
+    env->pc = 0x100;
+    env->sr = SR_FO | SR_SM;
+    env->exception_index = -1;
+}
diff --git a/target-openrisc/mem_helper.c b/target-openrisc/mem_helper.c
new file mode 100644
index 0000000..a2d93c7
--- /dev/null
+++ b/target-openrisc/mem_helper.c
@@ -0,0 +1,46 @@
+/*
+ * OpenRISC mmu helper routines
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "cpu.h"
+#include "dyngen-exec.h"
As I mention in the later patch, this makes AREG0 to be used for
CPUState (also HELPER_CFLAGS is not used to compile mem_helper.o).
Please avoid it, then you also need to adjust CONFIG_TCG_PASS_AREG0
case in configure.
I'm trying, but I'm not very clear for now. thanks.
Post by Blue Swirl
Post by Jia Liu
+#include "helper.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 *env1, 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..aae483a
--- /dev/null
+++ b/target-openrisc/translate.c
@@ -0,0 +1,90 @@
+/*
+ * Openrisc translation
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#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"
+
+#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;
+    target_ulong ppc, npc;
+    uint32_t tb_flags;
+    uint32_t is_jmp;
+    uint32_t mem_idx;
+    int singlestep_enabled;
+    uint32_t delayed_branch;
+} DisasContext;
+
+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
Jia Liu
2012-05-17 08:35:45 UTC
Permalink
add the openrisc MMU support.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 2 +
hw/openrisc_cpudev.h | 30 ++++++
hw/openrisc_pic.c | 31 ++++++
target-openrisc/mem.c | 220 +++++++++++++++++++++++++++++++++++++++++-
target-openrisc/mem_helper.c | 25 +++++
5 files changed, 307 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 0ffb29c..79c75f6 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..ca7d064
--- /dev/null
+++ b/hw/openrisc_cpudev.h
@@ -0,0 +1,30 @@
+/*
+ * 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 Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#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..0abdd50
--- /dev/null
+++ b/hw/openrisc_pic.c
@@ -0,0 +1,31 @@
+/*
+ * 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 Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#include "hw.h"
+#include "openrisc_cpudev.h"
+#include "cpu.h"
+
+/* Reset PIC */
+void cpu_openrisc_pic_reset(CPUOPENRISCState *env)
+{
+ env->picmr = 0x00000000;
+ env->picsr = 0x00000000;
+}
diff --git a/target-openrisc/mem.c b/target-openrisc/mem.c
index 57a0b1b..b26da38 100644
--- a/target-openrisc/mem.c
+++ b/target-openrisc/mem.c
@@ -28,10 +28,224 @@
#endif

#if !defined(CONFIG_USER_ONLY)
+enum {
+ TLBRET_INVALID = -3,
+ TLBRET_NOMATCH = -2,
+ TLBRET_BADADDR = -1,
+ TLBRET_MATCH = 0
+};
+
+tlb_entry itlb_table[ITLB_WAYS][ITLB_SIZE];
+tlb_entry dtlb_table[DTLB_WAYS][DTLB_SIZE];
+#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;
+ env->dtlb = dtlb_table;
+ env->itlb = itlb_table;
+ memset(dtlb_table, 0, sizeof(tlb_entry)*DTLB_SIZE*DTLB_WAYS);
+ memset(itlb_table, 0, sizeof(tlb_entry)*ITLB_SIZE*ITLB_WAYS);
}
#endif

@@ -40,4 +254,8 @@ void openrisc_reset(CPUOPENRISCState *env)
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
}
diff --git a/target-openrisc/mem_helper.c b/target-openrisc/mem_helper.c
index a2d93c7..922dd6b 100644
--- a/target-openrisc/mem_helper.c
+++ b/target-openrisc/mem_helper.c
@@ -42,5 +42,30 @@
void tlb_fill(CPUOPENRISCState *env1, target_ulong addr, int is_write,
int mmu_idx, uintptr_t retaddr)
{
+ TranslationBlock *tb;
+ CPUOPENRISCState *saved_env;
+ unsigned long pc;
+ int ret;
+
+ saved_env = env;
+ env = env1;
+
+ 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);
+ }
+ env = saved_env;
}
#endif
--
1.7.9.5
Blue Swirl
2012-05-19 07:41:00 UTC
Permalink
Post by Jia Liu
add the openrisc MMU support.
---
 Makefile.target              |    2 +
 hw/openrisc_cpudev.h         |   30 ++++++
 hw/openrisc_pic.c            |   31 ++++++
 target-openrisc/mem.c        |  220 +++++++++++++++++++++++++++++++++++++++++-
 target-openrisc/mem_helper.c |   25 +++++
 5 files changed, 307 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 0ffb29c..79c75f6 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..ca7d064
--- /dev/null
+++ b/hw/openrisc_cpudev.h
@@ -0,0 +1,30 @@
+/*
+ * Qemu Openrisc CPU device support.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#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);
The implementation is not added by this patch.
Post by Jia Liu
+
+#endif
diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
new file mode 100644
index 0000000..0abdd50
--- /dev/null
+++ b/hw/openrisc_pic.c
@@ -0,0 +1,31 @@
+/*
+ * Generic  OPENRISC Programmable Interrupt Controller support.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "hw.h"
+#include "openrisc_cpudev.h"
+#include "cpu.h"
+
+/* Reset PIC */
+void cpu_openrisc_pic_reset(CPUOPENRISCState *env)
+{
+    env->picmr = 0x00000000;
+    env->picsr = 0x00000000;
+}
diff --git a/target-openrisc/mem.c b/target-openrisc/mem.c
index 57a0b1b..b26da38 100644
--- a/target-openrisc/mem.c
+++ b/target-openrisc/mem.c
@@ -28,10 +28,224 @@
 #endif
 #if !defined(CONFIG_USER_ONLY)
+enum {
+    TLBRET_INVALID = -3,
+    TLBRET_NOMATCH = -2,
+    TLBRET_BADADDR = -1,
+    TLBRET_MATCH = 0
+};
+
+tlb_entry itlb_table[ITLB_WAYS][ITLB_SIZE];
+tlb_entry dtlb_table[DTLB_WAYS][DTLB_SIZE];
These should be inside CPUOPENRISCState, not globals.
Post by Jia Liu
+#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)) {
This is pretty strange, isn't the virtual to physical mapping handled
by TLB so why this shortcut?
Post by Jia Liu
+        *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) {
+        if (rw == 2) {
+            exception = EXCP_IPF;
+        } else {
+            exception = EXCP_DPF;
+        }
+        break;
+#if !defined(CONFIG_USER_ONLY)
+        if (rw == 2) {
+            exception = EXCP_IPF;
+        } else {
+            exception = EXCP_DPF;
+        }
+        break;
+        /* 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;
+    env->dtlb = dtlb_table;
+    env->itlb = itlb_table;
+    memset(dtlb_table, 0, sizeof(tlb_entry)*DTLB_SIZE*DTLB_WAYS);
+    memset(itlb_table, 0, sizeof(tlb_entry)*ITLB_SIZE*ITLB_WAYS);
 }
 #endif
@@ -40,4 +254,8 @@ void openrisc_reset(CPUOPENRISCState *env)
    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
 }
diff --git a/target-openrisc/mem_helper.c b/target-openrisc/mem_helper.c
index a2d93c7..922dd6b 100644
--- a/target-openrisc/mem_helper.c
+++ b/target-openrisc/mem_helper.c
@@ -42,5 +42,30 @@
 void tlb_fill(CPUOPENRISCState *env1, target_ulong addr, int is_write,
              int mmu_idx, uintptr_t retaddr)
 {
+    TranslationBlock *tb;
+    CPUOPENRISCState *saved_env;
+    unsigned long pc;
+    int ret;
+
+    saved_env = env;
+    env = env1;
Please avoid compiling with AREG0 and remove this.
Post by Jia Liu
+
+    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);
+    }
+    env = saved_env;
 }
 #endif
--
1.7.9.5
Jia Liu
2012-05-21 06:24:21 UTC
Permalink
Hi Blue,
Post by Blue Swirl
Post by Jia Liu
add the openrisc MMU support.
---
 Makefile.target              |    2 +
 hw/openrisc_cpudev.h         |   30 ++++++
 hw/openrisc_pic.c            |   31 ++++++
 target-openrisc/mem.c        |  220 +++++++++++++++++++++++++++++++++++++++++-
 target-openrisc/mem_helper.c |   25 +++++
 5 files changed, 307 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 0ffb29c..79c75f6 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..ca7d064
--- /dev/null
+++ b/hw/openrisc_cpudev.h
@@ -0,0 +1,30 @@
+/*
+ * Qemu Openrisc CPU device support.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#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);
The implementation is not added by this patch.
I'll add it here.
Post by Blue Swirl
Post by Jia Liu
+
+#endif
diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
new file mode 100644
index 0000000..0abdd50
--- /dev/null
+++ b/hw/openrisc_pic.c
@@ -0,0 +1,31 @@
+/*
+ * Generic  OPENRISC Programmable Interrupt Controller support.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "hw.h"
+#include "openrisc_cpudev.h"
+#include "cpu.h"
+
+/* Reset PIC */
+void cpu_openrisc_pic_reset(CPUOPENRISCState *env)
+{
+    env->picmr = 0x00000000;
+    env->picsr = 0x00000000;
+}
diff --git a/target-openrisc/mem.c b/target-openrisc/mem.c
index 57a0b1b..b26da38 100644
--- a/target-openrisc/mem.c
+++ b/target-openrisc/mem.c
@@ -28,10 +28,224 @@
 #endif
 #if !defined(CONFIG_USER_ONLY)
+enum {
+    TLBRET_INVALID = -3,
+    TLBRET_NOMATCH = -2,
+    TLBRET_BADADDR = -1,
+    TLBRET_MATCH = 0
+};
+
+tlb_entry itlb_table[ITLB_WAYS][ITLB_SIZE];
+tlb_entry dtlb_table[DTLB_WAYS][DTLB_SIZE];
These should be inside CPUOPENRISCState, not globals.
thanks, I'll move them there.
Post by Blue Swirl
Post by Jia Liu
+#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)) {
This is pretty strange, isn't the virtual to physical mapping handled
by TLB so why this shortcut?
The Openrisc Arch said that, so I have to obey.
Post by Blue Swirl
Post by Jia Liu
+        *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) {
+        if (rw == 2) {
+            exception = EXCP_IPF;
+        } else {
+            exception = EXCP_DPF;
+        }
+        break;
+#if !defined(CONFIG_USER_ONLY)
+        if (rw == 2) {
+            exception = EXCP_IPF;
+        } else {
+            exception = EXCP_DPF;
+        }
+        break;
+        /* 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;
+    env->dtlb = dtlb_table;
+    env->itlb = itlb_table;
+    memset(dtlb_table, 0, sizeof(tlb_entry)*DTLB_SIZE*DTLB_WAYS);
+    memset(itlb_table, 0, sizeof(tlb_entry)*ITLB_SIZE*ITLB_WAYS);
 }
 #endif
@@ -40,4 +254,8 @@ void openrisc_reset(CPUOPENRISCState *env)
    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
 }
diff --git a/target-openrisc/mem_helper.c b/target-openrisc/mem_helper.c
index a2d93c7..922dd6b 100644
--- a/target-openrisc/mem_helper.c
+++ b/target-openrisc/mem_helper.c
@@ -42,5 +42,30 @@
 void tlb_fill(CPUOPENRISCState *env1, target_ulong addr, int is_write,
              int mmu_idx, uintptr_t retaddr)
 {
+    TranslationBlock *tb;
+    CPUOPENRISCState *saved_env;
+    unsigned long pc;
+    int ret;
+
+    saved_env = env;
+    env = env1;
Please avoid compiling with AREG0 and remove this.
Sorry, I'm not very sure about it, may you give me more hits?
Post by Blue Swirl
Post by Jia Liu
+
+    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);
+    }
+    env = saved_env;
 }
 #endif
--
1.7.9.5
陳韋任
2012-05-21 09:03:14 UTC
Permalink
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
diff --git a/target-openrisc/mem_helper.c b/target-openrisc/mem_helper.c
index a2d93c7..922dd6b 100644
--- a/target-openrisc/mem_helper.c
+++ b/target-openrisc/mem_helper.c
@@ -42,5 +42,30 @@
戹oid tlb_fill(CPUOPENRISCState *env1, target_ulong addr, int is_write,
? ? ? ? ? ? ? int mmu_idx, uintptr_t retaddr)
𣏵
+ ? ?TranslationBlock *tb;
+ ? 蟖PUOPENRISCState *saved_env;
+ ? 抦nsigned long pc;
+ ? 犲nt ret;
+
+ ? 坟aved_env = env;
+ ? 猬nv = env1;
Please avoid compiling with AREG0 and remove this.
Sorry, I'm not very sure about it, may you give me more hits?
In dyngen-exec.h, the CPUArchState *env is kept in particular host register
(AREG0), so you shouldn't use env here somehow. Maybe Blue can show you some
example how to do that, target-sparc/* might be a place?

Regards,
chenwj
--
Wei-Ren Chen (陳韋任)
Computer Systems Lab, Institute of Information Science,
Academia Sinica, Taiwan (R.O.C.)
Tel:886-2-2788-3799 #1667
Homepage: http://people.cs.nctu.edu.tw/~chenwj
Blue Swirl
2012-05-21 17:41:39 UTC
Permalink
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
diff --git a/target-openrisc/mem_helper.c b/target-openrisc/mem_helper.c
index a2d93c7..922dd6b 100644
--- a/target-openrisc/mem_helper.c
+++ b/target-openrisc/mem_helper.c
@@ -42,5 +42,30 @@
戹oid tlb_fill(CPUOPENRISCState *env1, target_ulong addr, int is_write,
? ? ? ? ? ? ? int mmu_idx, uintptr_t retaddr)
𣏵
+ ? ?TranslationBlock *tb;
+ ? 蟖PUOPENRISCState *saved_env;
+ ? 抦nsigned long pc;
+ ? 犲nt ret;
+
+ ? 坟aved_env = env;
+ ? 猬nv = env1;
Please avoid compiling with AREG0 and remove this.
Sorry, I'm not very sure about it, may you give me more hits?
 In dyngen-exec.h, the CPUArchState *env is kept in particular host register
(AREG0), so you shouldn't use env here somehow. Maybe Blue can show you some
example how to do that, target-sparc/* might be a place?
For example this patch replaces AREG0 env with a parameter:
http://repo.or.cz/w/qemu/blueswirl.git/commitdiff/addb3b03425550d677d9d8d466398f715d090233
Regards,
chenwj
--
Wei-Ren Chen (陳韋任)
Computer Systems Lab, Institute of Information Science,
Academia Sinica, Taiwan (R.O.C.)
Tel:886-2-2788-3799 #1667
Homepage: http://people.cs.nctu.edu.tw/~chenwj
Jia Liu
2012-05-17 08:35:46 UTC
Permalink
add the openrisc instructions translation.

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

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index aae483a..4828ae6 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -55,14 +55,1395 @@ typedef struct DisasContext {
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 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");
+ 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;
+}
+
+/* General purpose registers moves. */
+static inline void gen_load_gpr(TCGv t, unsigned int reg)
+{
+ if (reg == 0) {
+ tcg_gen_movi_tl(t, 0);
+ } else {
+ tcg_gen_mov_tl(t, cpu_R[reg]);
+ }
+}
+
+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) {
+ /* exception here */
+ }
+ tcg_gen_exit_tb(0);
+ }
+}
+
+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);
+ /* Aha, we do need a helper here for add */
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case 0x0001: /*l.addc*/
+ switch (op1) {
+ case 0x00:
+ LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
+ /* Aha, we do need a helper here for addc */
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case 0x0002: /*l.sub*/
+ switch (op1) {
+ case 0x00:
+ LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
+ /* Aha, we do need a helper here for sub */
+ break;
+ default:
+ 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:
+ 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:
+ 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:
+ 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) {
+ tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[rd]);
+ } else {
+ tcg_gen_movi_tl(cpu_R[rd], 0x0);
+ }
+ break;
+ default:
+ 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) {
+ tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ } else {
+ /* exception here */
+ }
+ break;
+ default:
+ 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) {
+ tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ } else {
+ /* exception here */
+ }
+ break;
+ default:
+ 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) {
+ tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+ tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
+ tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ } else {
+ tcg_gen_movi_tl(cpu_R[rd], 0);
+ }
+ break;
+ default:
+ 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:
+ break;
+ }
+ break;
+
+ case 0x000f:
+ switch (op1) {
+ case 0x00: /*l.ff1*/
+ LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
+ /* ff1 need a helper here */
+ break;
+ case 0x01: /*l.fl1*/
+ LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
+ /* fl1 need a helper here */
+ break;
+ default:
+ 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:
+ break;
+ }
+ break;
+ default:
+ 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:
+ break;
+ }
+ break;
+ default:
+ 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:
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ default:
+ 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);
+ tmp = sign_extend((N26<<2), 26) + dc->pc;
+ tcg_gen_movi_tl(jmp_pc, tmp);
+ dc->delayed_branch = 2;
+ dc->tb_flags |= D_FLAG;
+ tcg_gen_movi_i32(env_flags, dc->tb_flags);
+ }
+ break;
+
+ case 0x01: /*l.jal*/
+ {
+ LOG_DIS("l.jal %d\n", N26);
+ tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+ tmp = sign_extend((N26<<2), 26) + dc->pc;
+ tcg_gen_movi_tl(jmp_pc, tmp);
+ dc->delayed_branch = 2;
+ dc->tb_flags |= D_FLAG;
+ tcg_gen_movi_i32(env_flags, dc->tb_flags);
+ }
+ break;
+
+ case 0x03: /*l.bnf*/
+ LOG_DIS("l.bnf %d\n", N26);
+ {
+ int lab = gen_new_label();
+ TCGv sr_f = tcg_temp_new();
+ tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+ tmp = sign_extend((N26 << 2), 26) + dc->pc;
+ tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+ tcg_gen_brcondi_tl(TCG_COND_EQ, sr_f, SR_F, lab);
+ tcg_gen_movi_tl(jmp_pc, tmp);
+ gen_set_label(lab);
+ dc->delayed_branch = 2;
+ dc->tb_flags |= D_FLAG;
+ tcg_gen_movi_i32(env_flags, dc->tb_flags);
+ tcg_temp_free(sr_f);
+ }
+ break;
+
+ case 0x04: /*l.bf*/
+ LOG_DIS("l.bf %d\n", N26);
+ {
+ int lab = gen_new_label();
+ TCGv sr_f = tcg_temp_new();
+ tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+ tmp = sign_extend((N26 << 2), 26) + dc->pc;
+ tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+ tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
+ tcg_gen_movi_tl(jmp_pc, tmp);
+ gen_set_label(lab);
+ dc->delayed_branch = 2;
+ dc->tb_flags |= D_FLAG;
+ tcg_gen_movi_i32(env_flags, dc->tb_flags);
+ tcg_temp_free(sr_f);
+ }
+ break;
+
+ case 0x05:
+ switch (op1) {
+ case 0x01: /*l.nop*/
+ LOG_DIS("l.nop %d\n", I16);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case 0x11: /*l.jr*/
+ LOG_DIS("l.jr r%d\n", rb);
+ {
+ tcg_gen_mov_tl(jmp_pc, cpu_R[rb]);
+ dc->delayed_branch = 2;
+ dc->tb_flags |= D_FLAG;
+ tcg_gen_movi_i32(env_flags, dc->tb_flags);
+ }
+ break;
+
+ case 0x12: /*l.jalr*/
+ LOG_DIS("l.jalr r%d\n", rb);
+ {
+ tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+ gen_load_gpr(jmp_pc, rb);
+ dc->delayed_branch = 2;
+ dc->tb_flags |= D_FLAG;
+ tcg_gen_movi_i32(env_flags, dc->tb_flags);
+ }
+ 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");
+ {
+ /* rfe need a helper here */
+ 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));
+ /* Aha, we do need a helper here for addi */
+ 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));
+ /* Aha, we do need a helper here for addic */
+ 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) {
+ tcg_gen_muli_tl(cpu_R[rd], cpu_R[ra], I16);
+ tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[rd]);
+ } else {
+ tcg_gen_movi_tl(cpu_R[rd], 0);
+ }
+ break;
+
+ 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);
+ /* mfspr need a helper here */
+ 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);
+ /* mtspr need a helper here */
+ tcg_temp_free_i32(ti);
+ tcg_temp_free(ta);
+ tcg_temp_free(tb);
+ }
+ 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:
+ 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();
+ switch (op0) {
+ case 0x0001: /*l.mac*/
+ {
+ LOG_DIS("l.mac 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_add_tl(maclo, maclo, cpu_R[ra]);
+ tcg_gen_add_tl(machi, machi, cpu_R[ra]);
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ }
+ 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_tl(maclo, maclo, cpu_R[ra]);
+ tcg_gen_sub_tl(machi, machi, cpu_R[ra]);
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ }
+ break;
+
+ default:
+ 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:
+ 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:
+ 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:
+ 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:
+ 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);
+ /* exception here */
+ 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);
+ /* exception here */
+ 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:
+ 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);
+ tcg_gen_add_i64(cpu_R[rd], 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);
+ tcg_gen_add_tl(cpu_R[rd], 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);
+ tcg_gen_sub_i64(cpu_R[rd], 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);
+ tcg_gen_sub_tl(cpu_R[rd], 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) {
+ tcg_gen_mul_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ } else {
+ 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) {
+ tcg_gen_mul_i32(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ } else {
+ tcg_gen_movi_i64(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);
+ if (cpu_R[rb] != 0) {
+ tcg_gen_div_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ } else {
+ /* exception here */
+ }
+ break;
+
+ case 0x03: /*lf.div.s*/
+ LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
+ if (cpu_R[rb] != 0) {
+ tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ } else {
+ /* exception here */
+ }
+ break;
+
+ case 0x14: /*lf.itof.d*/
+ LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+ /* itof.d need a helper here */
+ break;
+
+ case 0x04: /*lf.itof.s*/
+ LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+ /* itof.s need a helper here */
+ break;
+
+ case 0x15: /*lf.ftoi.d*/
+ LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+ /* ftoi.d need a helper here */
+ break;
+
+ case 0x05: /*lf.ftoi.s*/
+ LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+ /* ftoi.s need a helper here */
+ break;
+
+ case 0x16: /*lf.rem.d*/
+ LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_rem_i64(cpu_R[rd], 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);
+ tcg_gen_rem_tl(cpu_R[rd], 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);
+ {
+ TCGv_i64 t0, t1;
+
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+
+ 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_add_tl(fpmaddlo, cpu_R[ra], fpmaddlo);
+ tcg_gen_shri_i64(t0, t0, 32);
+ tcg_gen_trunc_i64_i32(cpu_R[rb], t0);
+ tcg_gen_add_tl(fpmaddhi, cpu_R[rb], fpmaddhi);
+
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+ }
+ break;
+
+ case 0x07: /*lf.madd.s*/
+ LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
+ {
+ TCGv_i64 t0, t1;
+
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+
+ 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_add_tl(fpmaddlo, cpu_R[ra], fpmaddlo);
+ tcg_gen_shri_i64(t0, t0, 32);
+ tcg_gen_trunc_i64_i32(cpu_R[rb], t0);
+ tcg_gen_add_tl(fpmaddhi, cpu_R[rb], fpmaddhi);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+
+ }
+ break;
+
+ case 0x18: /*lf.sfeq.d*/
+ LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_i64(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x08: /*lf.sfeq.s*/
+ LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x19: /*lf.sfne.d*/
+ LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_i64(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x09: /*lf.sfne.s*/
+ LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x1a: /*lf.sfgt.d*/
+ LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_i64(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x0a: /*lf.sfgt.s*/
+ LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x1b: /*lf.sfge.d*/
+ LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_i64(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x0b: /*lf.sfge.s*/
+ LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x1c: /*lf.sflt.d*/
+ LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_i64(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x0c: /*lf.sflt.s*/
+ LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x1d: /*lf.sfle.d*/
+ LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_i64(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x0d: /*lf.sfle.s*/
+ LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ default:
+ break;
+ }
+ wb_SR_F();
+}
+
+static void disas_openrisc_insn(DisasContext *dc, CPUOPENRISCState *env)
+{
+ uint32_t op0;
+ uint32_t insn;
+ insn = ldl_code(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);
+ /* exception here */
+ 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, lj;
+ 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->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;
+ lj = -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 (lj < j) {
+ lj++;
+ while (lj < j) {
+ gen_opc_instr_start[lj++] = 0;
+ }
+ }
+ gen_opc_pc[lj] = dc->pc;
+ gen_opc_instr_start[lj] = 1;
+ gen_opc_icount[lj] = 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;
+ tcg_gen_movi_i32(env_flags, dc->tb_flags);
+ 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);
+ }
+ /* exception here*/
+ } 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;
+ lj++;
+ while (lj <= j) {
+ gen_opc_instr_start[lj++] = 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)
@@ -80,7 +1461,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-17 12:11:45 UTC
Permalink
Hi.

I've got a couple of questions/suggestions regarding the code.
Post by Jia Liu
add the openrisc instructions translation.
[...]
Post by Jia Liu
+        switch (op1) {
+        case 0x03:   /*l.div*/
+            LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
+            if (rb != 0) {
+                tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
You also need to take care of integer overflow/division by zero here,
otherwise it may crash QEMU.
Post by Jia Liu
+            } else {
+                /* exception here */
+            }
+            break;
+            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) {
+                tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                /* exception here */
+            }
+            break;
+            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) {
+                tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+                tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
This code would clobber high 32 bits of ra and rb if it was compiled
for 64 bit registers.
Are you going to support both 32 and 64 bit version of the ISA?
Could you please clarify *_tl usage here?
Post by Jia Liu
+                tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0);
+            }
+            break;
+            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);
There may be an issue when rd == ra and the branch is not taken
Post by Jia Liu
+                tcg_gen_mov_tl(cpu_R[rd], cpu_R[ra]);
+                gen_set_label(lab);
+                tcg_temp_free(sr_f);
+            }
+            break;
+            break;
+        }
+        break;
[...]
Post by Jia Liu
+    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;
[...]
Post by Jia Liu
+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();
+    switch (op0) {
+    case 0x0001:   /*l.mac*/
+        {
+            LOG_DIS("l.mac 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_add_tl(maclo, maclo, cpu_R[ra]);
+            tcg_gen_add_tl(machi, machi, cpu_R[ra]);
From the ISA I've got an impression that mac/maci should be
implemented like this (signedness left alone):

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(maclo, t2);
tcg_gen_shri_i64(t2, t2, 32);
tcg_gen_trunc_i64(machi, t2);

[...]
Post by Jia Liu
+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);
+        tcg_gen_add_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
Through this function you generate integer operations on the
registers, although ISA
suggests that there should be either single- or double-precision
floating point operations.
--
Thanks.
-- Max
Jia Liu
2012-05-18 01:04:01 UTC
Permalink
Hi Max

Thanks for comments.
Post by Max Filippov
Hi.
I've got a couple of questions/suggestions regarding the code.
Post by Jia Liu
add the openrisc instructions translation.
[...]
Post by Jia Liu
+        switch (op1) {
+        case 0x03:   /*l.div*/
+            LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
+            if (rb != 0) {
+                tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
You also need to take care of integer overflow/division by zero here,
otherwise it may crash QEMU.
Post by Jia Liu
+            } else {
+                /* exception here */
overflow/division by zero is handled here by patch 05/15.
Post by Max Filippov
Post by Jia Liu
+            }
+            break;
+            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) {
+                tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                /* exception here */
+            }
+            break;
+            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) {
+                tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+                tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
This code would clobber high 32 bits of ra and rb if it was compiled
for 64 bit registers.
Are you going to support both 32 and 64 bit version of the ISA?
Could you please clarify *_tl usage here?
I used uint32_t at first, change it into *_tl for 64bit support in the future.
May I keep it *_tl? If I can not, I'll back it to uint32.
Post by Max Filippov
Post by Jia Liu
+                tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0);
+            }
+            break;
+            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);
There may be an issue when rd == ra and the branch is not taken
Thanks, I'll check this.
Post by Max Filippov
Post by Jia Liu
+                tcg_gen_mov_tl(cpu_R[rd], cpu_R[ra]);
+                gen_set_label(lab);
+                tcg_temp_free(sr_f);
+            }
+            break;
+            break;
+        }
+        break;
[...]
Post by Jia Liu
+    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;
[...]
Post by Jia Liu
+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();
+    switch (op0) {
+    case 0x0001:   /*l.mac*/
+        {
+            LOG_DIS("l.mac 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_add_tl(maclo, maclo, cpu_R[ra]);
+            tcg_gen_add_tl(machi, machi, cpu_R[ra]);
From the ISA I've got an impression that mac/maci should be
           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(maclo, t2);
           tcg_gen_shri_i64(t2, t2, 32);
           tcg_gen_trunc_i64(machi, t2);
[...]
Thanks very much, I'll replace it in V2.
Post by Max Filippov
Post by Jia Liu
+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);
+        tcg_gen_add_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
Through this function you generate integer operations on the
registers, although ISA
suggests that there should be either single- or double-precision
floating point operations.
Sorry, I didn't find a TCG-IR that make single- or double-precision
floating point operations, may you give me some hits?
Post by Max Filippov
--
Thanks.
-- Max
Regards,
Jia.
陳韋任
2012-05-18 03:53:36 UTC
Permalink
Post by Jia Liu
Post by Max Filippov
+ ? 坟witch (op0) {
+ ? ?case 0x10: ? ?/*lf.add.d*/
+ ? ? ? 猂OG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb);
+ ? ? ? 慯cg_gen_add_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
Through this function you generate integer operations on the
registers, although ISA
suggests that there should be either single- or double-precision
floating point operations.
Sorry, I didn't find a TCG-IR that make single- or double-precision
floating point operations, may you give me some hits?
I guest you need to write your own floating helper functions to do that.
Am I right, Max?

Regards,
chenwj
--
Wei-Ren Chen (陳韋任)
Computer Systems Lab, Institute of Information Science,
Academia Sinica, Taiwan (R.O.C.)
Tel:886-2-2788-3799 #1667
Homepage: http://people.cs.nctu.edu.tw/~chenwj
Max Filippov
2012-05-18 10:33:13 UTC
Permalink
Hi Jia.
Post by Jia Liu
Post by Max Filippov
Post by Jia Liu
+        switch (op1) {
+        case 0x03:   /*l.div*/
+            LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
+            if (rb != 0) {
+                tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
You also need to take care of integer overflow/division by zero here,
otherwise it may crash QEMU.
Post by Jia Liu
+            } else {
+                /* exception here */
overflow/division by zero is handled here by patch 05/15.
In that patch I have found only exception generation in the 'else' branch.
However code generated by tcg_gen_div_tl in the 'if' branch will crash QEMU
in case rb register carries zero or ra/rb gives integer overflow.
Post by Jia Liu
Post by Max Filippov
Post by Jia Liu
+        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) {
+                tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+                tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
This code would clobber high 32 bits of ra and rb if it was compiled
for 64 bit registers.
Are you going to support both 32 and 64 bit version of the ISA?
Could you please clarify *_tl usage here?
I used uint32_t at first, change it into *_tl for 64bit support in the future.
May I keep it *_tl? If I can not, I'll back it to uint32.
Ok, to me *_tl looks pretty reasonable for instructions that scale uniformly
with register width, like simple l.and/l.or/l.add/l.div/etc.

For instructions that has less symmetry regarding register width or that
operate on registers of different widths at once, like l.maci, I'd say that
explicit *_i32/*_i64 would be more informative.

For this particular mulu I guess the correct implementation, suitable for both
32 and 64 bit wide registers would be just

tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);

however it doesn't take care of SR[OV], SR[CY]. I haven't found a place
where you update these bits.
Post by Jia Liu
Post by Max Filippov
Post by Jia Liu
+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);
+        tcg_gen_add_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
Through this function you generate integer operations on the
registers, although ISA
suggests that there should be either single- or double-precision
floating point operations.
Sorry, I  didn't find a TCG-IR that make single- or double-precision
floating point operations, may you give me some hits?
As chenwj said it is usually done in helper functions.
Software floating point structures, prototypes and implementations
live in the fpu/ directory.

Good example of how to use them is MIPS:
target-mips/translate.c, function gen_farith and
target-mips/op_helper.c, macro FLOAT_BINOP
--
Thanks.
-- Max
Blue Swirl
2012-05-19 10:02:44 UTC
Permalink
Post by Jia Liu
add the openrisc instructions translation.
---
 target-openrisc/translate.c | 1387 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1387 insertions(+)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index aae483a..4828ae6 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -55,14 +55,1395 @@ typedef struct DisasContext {
    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 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");
+    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;
+}
+
+/* General purpose registers moves. */
+static inline void gen_load_gpr(TCGv t, unsigned int reg)
+{
+    if (reg == 0) {
+        tcg_gen_movi_tl(t, 0);
+    } else {
+        tcg_gen_mov_tl(t, cpu_R[reg]);
+    }
+}
This does not seem to be used. Does the code handle the cases where
one or several of the registers is number 0? If this is the always-0
register, are stores to register 0 handled correctly?
Post by Jia Liu
+
+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) {
+            /* exception here */
+        }
+        tcg_gen_exit_tb(0);
+    }
+}
+
+static inline uint32_t field(uint32_t val, int start, int length)
+{
+    val >>= start;
+    val &= ~(~0 << length);
+    return val;
+}
Nice function, maybe I could use it in Sparc as well if generalized (later).
Post by Jia Liu
+
+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);
+            /* Aha, we do need a helper here for add */
+            break;
+            break;
+        }
+    break;
+
+    case 0x0001:    /*l.addc*/
+        switch (op1) {
+            LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
+            /* Aha, we do need a helper here for addc */
+            break;
+            break;
+        }
+    break;
+
+    case 0x0002:    /*l.sub*/
+        switch (op1) {
+            LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
+            /* Aha, we do need a helper here for sub */
+            break;
What happens on a real CPU when an illegal instruction is executed,
shouldn't there be an exception?
Post by Jia Liu
+            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;
+            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;
+            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;
+            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) {
+                tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[rd]);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0x0);
+            }
+        break;
Indentation.
Post by Jia Liu
+            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) {
+                tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                /* exception here */
+            }
+            break;
+            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) {
+                tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                /* exception here */
+            }
+            break;
+            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) {
+                tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+                tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
+                tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0);
+            }
+            break;
+            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);
+            }
+            break;
+            break;
+        }
+        break;
+
+        switch (op1) {
+        case 0x00:   /*l.ff1*/
+            LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
+            /* ff1 need a helper here */
+            break;
+        case 0x01:   /*l.fl1*/
+            LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
+            /* fl1 need a helper here */
+            break;
+            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;
+                break;
+            }
+            break;
+            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;
+                break;
+            }
+            break;
+            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;
+                break;
+            }
+            break;
+        }
+        break;
+
+        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);
+            tmp = sign_extend((N26<<2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x01:   /*l.jal*/
+        {
+            LOG_DIS("l.jal %d\n", N26);
+            tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+            tmp = sign_extend((N26<<2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x03:   /*l.bnf*/
+        LOG_DIS("l.bnf %d\n", N26);
+        {
+            int lab = gen_new_label();
+            TCGv sr_f = tcg_temp_new();
+            tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+            tmp = sign_extend((N26 << 2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+            tcg_gen_brcondi_tl(TCG_COND_EQ, sr_f, SR_F, lab);
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            gen_set_label(lab);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+            tcg_temp_free(sr_f);
+        }
+        break;
+
+    case 0x04:   /*l.bf*/
+        LOG_DIS("l.bf %d\n", N26);
+        {
+            int lab = gen_new_label();
+            TCGv sr_f = tcg_temp_new();
+            tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+            tmp = sign_extend((N26 << 2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+            tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            gen_set_label(lab);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+            tcg_temp_free(sr_f);
+        }
+        break;
+
+        switch (op1) {
+        case 0x01:   /*l.nop*/
+            LOG_DIS("l.nop %d\n", I16);
+            break;
+            break;
+        }
+        break;
+
+    case 0x11:    /*l.jr*/
+        LOG_DIS("l.jr r%d\n", rb);
+        {
+            tcg_gen_mov_tl(jmp_pc, cpu_R[rb]);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x12:    /*l.jalr*/
+        LOG_DIS("l.jalr r%d\n", rb);
+        {
+            tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+            gen_load_gpr(jmp_pc, rb);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        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*/
Variable definitions should be before code, like LOG_DIS() call in this case.
Post by Jia Liu
+            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");
+        {
+            /* rfe need a helper here */
+            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));
+            /* Aha, we do need a helper here for addi */
+            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));
+            /* Aha, we do need a helper here for addic */
+            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) {
+            tcg_gen_muli_tl(cpu_R[rd], cpu_R[ra], I16);
+            tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[rd]);
+        } else {
+            tcg_gen_movi_tl(cpu_R[rd], 0);
+        }
+        break;
+
+    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);
+            /* mfspr need a helper here */
+            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);
+            /* mtspr need a helper here */
+            tcg_temp_free_i32(ti);
+            tcg_temp_free(ta);
+            tcg_temp_free(tb);
+        }
+        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;
+        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();
+    switch (op0) {
+    case 0x0001:   /*l.mac*/
+        {
+            LOG_DIS("l.mac 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_add_tl(maclo, maclo, cpu_R[ra]);
+            tcg_gen_add_tl(machi, machi, cpu_R[ra]);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+        }
+        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_tl(maclo, maclo, cpu_R[ra]);
+            tcg_gen_sub_tl(machi, machi, cpu_R[ra]);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+        }
+        break;
+
+        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;
+
+        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;
+
+        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;
+
+        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;
+
+        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);
+        /* exception here */
+        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);
+        /* exception here */
+        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;
+
+        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);
+        tcg_gen_add_i64(cpu_R[rd], 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);
+        tcg_gen_add_tl(cpu_R[rd], 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);
+        tcg_gen_sub_i64(cpu_R[rd], 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);
+        tcg_gen_sub_tl(cpu_R[rd], 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) {
+                tcg_gen_mul_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                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) {
+            tcg_gen_mul_i32(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            tcg_gen_movi_i64(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);
+        if (cpu_R[rb] != 0) {
+            tcg_gen_div_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            /* exception here */
+        }
+        break;
+
+    case 0x03:    /*lf.div.s*/
+        LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
+        if (cpu_R[rb] != 0) {
+            tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            /* exception here */
+        }
+        break;
+
+    case 0x14:    /*lf.itof.d*/
+        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+        /* itof.d need a helper here */
+        break;
+
+    case 0x04:    /*lf.itof.s*/
+        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+        /* itof.s need a helper here */
+        break;
+
+    case 0x15:    /*lf.ftoi.d*/
+        LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+        /* ftoi.d need a helper here */
+        break;
+
+    case 0x05:    /*lf.ftoi.s*/
+        LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+        /* ftoi.s need a helper here */
+        break;
+
+    case 0x16:    /*lf.rem.d*/
+        LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
+        tcg_gen_rem_i64(cpu_R[rd], 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);
+        tcg_gen_rem_tl(cpu_R[rd], 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);
+        {
+            TCGv_i64 t0, t1;
+
+            t0 = tcg_temp_new_i64();
+            t1 = tcg_temp_new_i64();
+
+            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_add_tl(fpmaddlo, cpu_R[ra], fpmaddlo);
+            tcg_gen_shri_i64(t0, t0, 32);
+            tcg_gen_trunc_i64_i32(cpu_R[rb], t0);
+            tcg_gen_add_tl(fpmaddhi, cpu_R[rb], fpmaddhi);
+
+            tcg_temp_free_i64(t0);
+            tcg_temp_free_i64(t1);
+        }
+        break;
+
+    case 0x07:    /*lf.madd.s*/
+        LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
+        {
+            TCGv_i64 t0, t1;
+
+            t0 = tcg_temp_new_i64();
+            t1 = tcg_temp_new_i64();
+
+            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_add_tl(fpmaddlo, cpu_R[ra], fpmaddlo);
+            tcg_gen_shri_i64(t0, t0, 32);
+            tcg_gen_trunc_i64_i32(cpu_R[rb], t0);
+            tcg_gen_add_tl(fpmaddhi, cpu_R[rb], fpmaddhi);
+            tcg_temp_free_i64(t0);
+            tcg_temp_free_i64(t1);
+
+        }
+        break;
+
+    case 0x18:    /*lf.sfeq.d*/
+        LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x08:    /*lf.sfeq.s*/
+        LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x19:    /*lf.sfne.d*/
+        LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x09:    /*lf.sfne.s*/
+        LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1a:    /*lf.sfgt.d*/
+        LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0a:    /*lf.sfgt.s*/
+        LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1b:    /*lf.sfge.d*/
+        LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0b:    /*lf.sfge.s*/
+        LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1c:    /*lf.sflt.d*/
+        LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0c:    /*lf.sflt.s*/
+        LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1d:    /*lf.sfle.d*/
+        LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0d:    /*lf.sfle.s*/
+        LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+        break;
+    }
+    wb_SR_F();
+}
+
+static void disas_openrisc_insn(DisasContext *dc, CPUOPENRISCState *env)
+{
+    uint32_t op0;
+    uint32_t insn;
+    insn = ldl_code(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);
+                /* exception here */
+                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, lj;
+    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->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;
+    lj = -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 (lj < j) {
+                lj++;
+                while (lj < j) {
+                    gen_opc_instr_start[lj++] = 0;
+                }
+            }
+            gen_opc_pc[lj] = dc->pc;
+            gen_opc_instr_start[lj] = 1;
+            gen_opc_icount[lj] = 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;
Isn't now npc == pc and ppc == pc - 8?
Post by Jia Liu
+        num_insns++;
+        /* delay slot */
+        if (dc->delayed_branch) {
+            dc->delayed_branch--;
+            if (!dc->delayed_branch) {
+                dc->tb_flags &= ~D_FLAG;
+                tcg_gen_movi_i32(env_flags, dc->tb_flags);
This does not look correct.
Post by Jia Liu
+                tcg_gen_mov_tl(cpu_pc, jmp_pc);
+                tcg_gen_mov_tl(cpu_npc, jmp_pc);
+ 4?
Post by Jia Liu
+                tcg_gen_movi_tl(jmp_pc, 0);
+                tcg_gen_exit_tb(0);
+                dc->is_jmp = DISAS_JUMP;
+                break;
+            }
Is it possible to have a jump instruction in the delay slot and if so,
is it handled too?
Post by Jia Liu
+        }
+    } 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);
+        }
+        /* exception here*/
+    } 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;
+        lj++;
+        while (lj <= j) {
+            gen_opc_instr_start[lj++] = 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)
@@ -80,7 +1461,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
Peter Maydell
2012-05-19 10:57:11 UTC
Permalink
Post by Blue Swirl
Post by Jia Liu
+static inline uint32_t field(uint32_t val, int start, int length)
+{
+    val >>= start;
+    val &= ~(~0 << length);
+    return val;
+}
Nice function, maybe I could use it in Sparc as well if generalized (later).
We should totally have something like this in our generic bitops
header file. I've previously worked on a codebase that used something
similar consistently, and it's much easier to read than code which
does inline mask-and-shift code.

We probably want a 64 bit variant (or maybe we can just work
on uint64_t and trust the compiler to throw away the top halves
in the 32 bit case?)

-- PMM
Blue Swirl
2012-05-19 11:29:31 UTC
Permalink
On Sat, May 19, 2012 at 10:57 AM, Peter Maydell
Post by Peter Maydell
Post by Blue Swirl
Post by Jia Liu
+static inline uint32_t field(uint32_t val, int start, int length)
+{
+    val >>= start;
+    val &= ~(~0 << length);
+    return val;
+}
Nice function, maybe I could use it in Sparc as well if generalized (later).
We should totally have something like this in our generic bitops
header file. I've previously worked on a codebase that used something
similar consistently, and it's much easier to read than code which
does inline mask-and-shift code.
Yes. A generic method to construct bit field #defines/enums with nice
printout would be nice too. I think I saw something like that in BSD
land, can't remember where.
Post by Peter Maydell
We probably want a 64 bit variant (or maybe we can just work
on uint64_t and trust the compiler to throw away the top halves
in the 32 bit case?)
For Sparc the it would be used to extract fields from an instruction,
they are always 32 bits. But IA64 would need a 64 bit version.

I'd make two variants, maybe also target_ulong version if ever needed.
Post by Peter Maydell
-- PMM
Jia Liu
2012-05-23 06:11:42 UTC
Permalink
Thanks Blue.
Post by Blue Swirl
Post by Jia Liu
add the openrisc instructions translation.
---
 target-openrisc/translate.c | 1387 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1387 insertions(+)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index aae483a..4828ae6 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -55,14 +55,1395 @@ typedef struct DisasContext {
    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 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");
+    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;
+}
+
+/* General purpose registers moves. */
+static inline void gen_load_gpr(TCGv t, unsigned int reg)
+{
+    if (reg == 0) {
+        tcg_gen_movi_tl(t, 0);
+    } else {
+        tcg_gen_mov_tl(t, cpu_R[reg]);
+    }
+}
This does not seem to be used. Does the code handle the cases where
one or several of the registers is number 0? If this is the always-0
register, are stores to register 0 handled correctly?
I'll remove it.
Post by Blue Swirl
Post by Jia Liu
+
+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) {
+            /* exception here */
+        }
+        tcg_gen_exit_tb(0);
+    }
+}
+
+static inline uint32_t field(uint32_t val, int start, int length)
+{
+    val >>= start;
+    val &= ~(~0 << length);
+    return val;
+}
Nice function, maybe I could use it in Sparc as well if generalized (later).
Post by Jia Liu
+
+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);
+            /* Aha, we do need a helper here for add */
+            break;
+            break;
+        }
+    break;
+
+    case 0x0001:    /*l.addc*/
+        switch (op1) {
+            LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
+            /* Aha, we do need a helper here for addc */
+            break;
+            break;
+        }
+    break;
+
+    case 0x0002:    /*l.sub*/
+        switch (op1) {
+            LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
+            /* Aha, we do need a helper here for sub */
+            break;
What happens on a real CPU when an illegal instruction is executed,
shouldn't there be an exception?
I'll add a exception for illegal instruction.
Post by Blue Swirl
Post by Jia Liu
+            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;
+            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;
+            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;
+            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) {
+                tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[rd]);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0x0);
+            }
+        break;
Indentation.
Post by Jia Liu
+            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) {
+                tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                /* exception here */
+            }
+            break;
+            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) {
+                tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                /* exception here */
+            }
+            break;
+            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) {
+                tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+                tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
+                tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0);
+            }
+            break;
+            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);
+            }
+            break;
+            break;
+        }
+        break;
+
+        switch (op1) {
+        case 0x00:   /*l.ff1*/
+            LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
+            /* ff1 need a helper here */
+            break;
+        case 0x01:   /*l.fl1*/
+            LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
+            /* fl1 need a helper here */
+            break;
+            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;
+                break;
+            }
+            break;
+            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;
+                break;
+            }
+            break;
+            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;
+                break;
+            }
+            break;
+        }
+        break;
+
+        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);
+            tmp = sign_extend((N26<<2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x01:   /*l.jal*/
+        {
+            LOG_DIS("l.jal %d\n", N26);
+            tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+            tmp = sign_extend((N26<<2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x03:   /*l.bnf*/
+        LOG_DIS("l.bnf %d\n", N26);
+        {
+            int lab = gen_new_label();
+            TCGv sr_f = tcg_temp_new();
+            tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+            tmp = sign_extend((N26 << 2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+            tcg_gen_brcondi_tl(TCG_COND_EQ, sr_f, SR_F, lab);
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            gen_set_label(lab);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+            tcg_temp_free(sr_f);
+        }
+        break;
+
+    case 0x04:   /*l.bf*/
+        LOG_DIS("l.bf %d\n", N26);
+        {
+            int lab = gen_new_label();
+            TCGv sr_f = tcg_temp_new();
+            tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+            tmp = sign_extend((N26 << 2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+            tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            gen_set_label(lab);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+            tcg_temp_free(sr_f);
+        }
+        break;
+
+        switch (op1) {
+        case 0x01:   /*l.nop*/
+            LOG_DIS("l.nop %d\n", I16);
+            break;
+            break;
+        }
+        break;
+
+    case 0x11:    /*l.jr*/
+        LOG_DIS("l.jr r%d\n", rb);
+        {
+            tcg_gen_mov_tl(jmp_pc, cpu_R[rb]);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x12:    /*l.jalr*/
+        LOG_DIS("l.jalr r%d\n", rb);
+        {
+            tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+            gen_load_gpr(jmp_pc, rb);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        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*/
Variable definitions should be before code, like LOG_DIS() call in this case.
OK, thx.
Post by Blue Swirl
Post by Jia Liu
+            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");
+        {
+            /* rfe need a helper here */
+            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));
+            /* Aha, we do need a helper here for addi */
+            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));
+            /* Aha, we do need a helper here for addic */
+            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) {
+            tcg_gen_muli_tl(cpu_R[rd], cpu_R[ra], I16);
+            tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[rd]);
+        } else {
+            tcg_gen_movi_tl(cpu_R[rd], 0);
+        }
+        break;
+
+    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);
+            /* mfspr need a helper here */
+            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);
+            /* mtspr need a helper here */
+            tcg_temp_free_i32(ti);
+            tcg_temp_free(ta);
+            tcg_temp_free(tb);
+        }
+        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;
+        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();
+    switch (op0) {
+    case 0x0001:   /*l.mac*/
+        {
+            LOG_DIS("l.mac 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_add_tl(maclo, maclo, cpu_R[ra]);
+            tcg_gen_add_tl(machi, machi, cpu_R[ra]);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+        }
+        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_tl(maclo, maclo, cpu_R[ra]);
+            tcg_gen_sub_tl(machi, machi, cpu_R[ra]);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+        }
+        break;
+
+        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;
+
+        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;
+
+        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;
+
+        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;
+
+        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);
+        /* exception here */
+        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);
+        /* exception here */
+        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;
+
+        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);
+        tcg_gen_add_i64(cpu_R[rd], 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);
+        tcg_gen_add_tl(cpu_R[rd], 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);
+        tcg_gen_sub_i64(cpu_R[rd], 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);
+        tcg_gen_sub_tl(cpu_R[rd], 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) {
+                tcg_gen_mul_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                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) {
+            tcg_gen_mul_i32(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            tcg_gen_movi_i64(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);
+        if (cpu_R[rb] != 0) {
+            tcg_gen_div_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            /* exception here */
+        }
+        break;
+
+    case 0x03:    /*lf.div.s*/
+        LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
+        if (cpu_R[rb] != 0) {
+            tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            /* exception here */
+        }
+        break;
+
+    case 0x14:    /*lf.itof.d*/
+        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+        /* itof.d need a helper here */
+        break;
+
+    case 0x04:    /*lf.itof.s*/
+        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+        /* itof.s need a helper here */
+        break;
+
+    case 0x15:    /*lf.ftoi.d*/
+        LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+        /* ftoi.d need a helper here */
+        break;
+
+    case 0x05:    /*lf.ftoi.s*/
+        LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+        /* ftoi.s need a helper here */
+        break;
+
+    case 0x16:    /*lf.rem.d*/
+        LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
+        tcg_gen_rem_i64(cpu_R[rd], 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);
+        tcg_gen_rem_tl(cpu_R[rd], 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);
+        {
+            TCGv_i64 t0, t1;
+
+            t0 = tcg_temp_new_i64();
+            t1 = tcg_temp_new_i64();
+
+            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_add_tl(fpmaddlo, cpu_R[ra], fpmaddlo);
+            tcg_gen_shri_i64(t0, t0, 32);
+            tcg_gen_trunc_i64_i32(cpu_R[rb], t0);
+            tcg_gen_add_tl(fpmaddhi, cpu_R[rb], fpmaddhi);
+
+            tcg_temp_free_i64(t0);
+            tcg_temp_free_i64(t1);
+        }
+        break;
+
+    case 0x07:    /*lf.madd.s*/
+        LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
+        {
+            TCGv_i64 t0, t1;
+
+            t0 = tcg_temp_new_i64();
+            t1 = tcg_temp_new_i64();
+
+            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_add_tl(fpmaddlo, cpu_R[ra], fpmaddlo);
+            tcg_gen_shri_i64(t0, t0, 32);
+            tcg_gen_trunc_i64_i32(cpu_R[rb], t0);
+            tcg_gen_add_tl(fpmaddhi, cpu_R[rb], fpmaddhi);
+            tcg_temp_free_i64(t0);
+            tcg_temp_free_i64(t1);
+
+        }
+        break;
+
+    case 0x18:    /*lf.sfeq.d*/
+        LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x08:    /*lf.sfeq.s*/
+        LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x19:    /*lf.sfne.d*/
+        LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x09:    /*lf.sfne.s*/
+        LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1a:    /*lf.sfgt.d*/
+        LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0a:    /*lf.sfgt.s*/
+        LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1b:    /*lf.sfge.d*/
+        LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0b:    /*lf.sfge.s*/
+        LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1c:    /*lf.sflt.d*/
+        LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0c:    /*lf.sflt.s*/
+        LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1d:    /*lf.sfle.d*/
+        LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0d:    /*lf.sfle.s*/
+        LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+        break;
+    }
+    wb_SR_F();
+}
+
+static void disas_openrisc_insn(DisasContext *dc, CPUOPENRISCState *env)
+{
+    uint32_t op0;
+    uint32_t insn;
+    insn = ldl_code(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);
+                /* exception here */
+                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, lj;
+    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->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;
+    lj = -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 (lj < j) {
+                lj++;
+                while (lj < j) {
+                    gen_opc_instr_start[lj++] = 0;
+                }
+            }
+            gen_opc_pc[lj] = dc->pc;
+            gen_opc_instr_start[lj] = 1;
+            gen_opc_icount[lj] = 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;
Isn't now npc == pc and ppc == pc - 8?
I don't think so, but I'll check it.
Post by Blue Swirl
Post by Jia Liu
+        num_insns++;
+        /* delay slot */
+        if (dc->delayed_branch) {
+            dc->delayed_branch--;
+            if (!dc->delayed_branch) {
+                dc->tb_flags &= ~D_FLAG;
+                tcg_gen_movi_i32(env_flags, dc->tb_flags);
This does not look correct.
for exception in delay slot, it is.
Post by Blue Swirl
Post by Jia Liu
+                tcg_gen_mov_tl(cpu_pc, jmp_pc);
+                tcg_gen_mov_tl(cpu_npc, jmp_pc);
+ 4?
Post by Jia Liu
+                tcg_gen_movi_tl(jmp_pc, 0);
+                tcg_gen_exit_tb(0);
+                dc->is_jmp = DISAS_JUMP;
+                break;
+            }
Is it possible to have a jump instruction in the delay slot and if so,
is it handled too?
I've done for this.
Post by Blue Swirl
Post by Jia Liu
+        }
+    } 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);
+        }
+        /* exception here*/
+    } 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;
+        lj++;
+        while (lj <= j) {
+            gen_opc_instr_start[lj++] = 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)
@@ -80,7 +1461,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
Jia,
Regards.
Blue Swirl
2012-05-23 18:59:39 UTC
Permalink
Post by Jia Liu
Thanks Blue.
Post by Blue Swirl
Post by Jia Liu
add the openrisc instructions translation.
---
 target-openrisc/translate.c | 1387 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1387 insertions(+)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index aae483a..4828ae6 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -55,14 +55,1395 @@ typedef struct DisasContext {
    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 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");
+    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;
+}
+
+/* General purpose registers moves. */
+static inline void gen_load_gpr(TCGv t, unsigned int reg)
+{
+    if (reg == 0) {
+        tcg_gen_movi_tl(t, 0);
+    } else {
+        tcg_gen_mov_tl(t, cpu_R[reg]);
+    }
+}
This does not seem to be used. Does the code handle the cases where
one or several of the registers is number 0? If this is the always-0
register, are stores to register 0 handled correctly?
I'll remove it.
Post by Blue Swirl
Post by Jia Liu
+
+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) {
+            /* exception here */
+        }
+        tcg_gen_exit_tb(0);
+    }
+}
+
+static inline uint32_t field(uint32_t val, int start, int length)
+{
+    val >>= start;
+    val &= ~(~0 << length);
+    return val;
+}
Nice function, maybe I could use it in Sparc as well if generalized (later).
Post by Jia Liu
+
+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);
+            /* Aha, we do need a helper here for add */
+            break;
+            break;
+        }
+    break;
+
+    case 0x0001:    /*l.addc*/
+        switch (op1) {
+            LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
+            /* Aha, we do need a helper here for addc */
+            break;
+            break;
+        }
+    break;
+
+    case 0x0002:    /*l.sub*/
+        switch (op1) {
+            LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
+            /* Aha, we do need a helper here for sub */
+            break;
What happens on a real CPU when an illegal instruction is executed,
shouldn't there be an exception?
I'll add a exception for illegal instruction.
Post by Blue Swirl
Post by Jia Liu
+            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;
+            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;
+            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;
+            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) {
+                tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[rd]);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0x0);
+            }
+        break;
Indentation.
Post by Jia Liu
+            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) {
+                tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                /* exception here */
+            }
+            break;
+            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) {
+                tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
By the way, a division by zero will crash QEMU. Please add a runtime
check, something like this:
http://git.qemu.org/?p=qemu.git;a=blob;f=target-sparc/translate.c;h=b95f91cd3baf9c02305f8583662b8eba664b17ba;hb=HEAD#l765
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+            } else {
+                /* exception here */
+            }
+            break;
+            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) {
+                tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+                tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
+                tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0);
+            }
+            break;
+            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);
+            }
+            break;
+            break;
+        }
+        break;
+
+        switch (op1) {
+        case 0x00:   /*l.ff1*/
+            LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
+            /* ff1 need a helper here */
+            break;
+        case 0x01:   /*l.fl1*/
+            LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
+            /* fl1 need a helper here */
+            break;
+            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;
+                break;
+            }
+            break;
+            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;
+                break;
+            }
+            break;
+            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;
+                break;
+            }
+            break;
+        }
+        break;
+
+        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);
+            tmp = sign_extend((N26<<2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x01:   /*l.jal*/
+        {
+            LOG_DIS("l.jal %d\n", N26);
+            tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+            tmp = sign_extend((N26<<2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x03:   /*l.bnf*/
+        LOG_DIS("l.bnf %d\n", N26);
+        {
+            int lab = gen_new_label();
+            TCGv sr_f = tcg_temp_new();
+            tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+            tmp = sign_extend((N26 << 2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+            tcg_gen_brcondi_tl(TCG_COND_EQ, sr_f, SR_F, lab);
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            gen_set_label(lab);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+            tcg_temp_free(sr_f);
+        }
+        break;
+
+    case 0x04:   /*l.bf*/
+        LOG_DIS("l.bf %d\n", N26);
+        {
+            int lab = gen_new_label();
+            TCGv sr_f = tcg_temp_new();
+            tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+            tmp = sign_extend((N26 << 2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+            tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            gen_set_label(lab);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+            tcg_temp_free(sr_f);
+        }
+        break;
+
+        switch (op1) {
+        case 0x01:   /*l.nop*/
+            LOG_DIS("l.nop %d\n", I16);
+            break;
+            break;
+        }
+        break;
+
+    case 0x11:    /*l.jr*/
+        LOG_DIS("l.jr r%d\n", rb);
+        {
+            tcg_gen_mov_tl(jmp_pc, cpu_R[rb]);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x12:    /*l.jalr*/
+        LOG_DIS("l.jalr r%d\n", rb);
+        {
+            tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+            gen_load_gpr(jmp_pc, rb);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        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*/
Variable definitions should be before code, like LOG_DIS() call in this case.
OK, thx.
Post by Blue Swirl
Post by Jia Liu
+            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");
+        {
+            /* rfe need a helper here */
+            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));
+            /* Aha, we do need a helper here for addi */
+            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));
+            /* Aha, we do need a helper here for addic */
+            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) {
+            tcg_gen_muli_tl(cpu_R[rd], cpu_R[ra], I16);
+            tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[rd]);
+        } else {
+            tcg_gen_movi_tl(cpu_R[rd], 0);
+        }
+        break;
+
+    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);
+            /* mfspr need a helper here */
+            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);
+            /* mtspr need a helper here */
+            tcg_temp_free_i32(ti);
+            tcg_temp_free(ta);
+            tcg_temp_free(tb);
+        }
+        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;
+        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();
+    switch (op0) {
+    case 0x0001:   /*l.mac*/
+        {
+            LOG_DIS("l.mac 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_add_tl(maclo, maclo, cpu_R[ra]);
+            tcg_gen_add_tl(machi, machi, cpu_R[ra]);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+        }
+        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_tl(maclo, maclo, cpu_R[ra]);
+            tcg_gen_sub_tl(machi, machi, cpu_R[ra]);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+        }
+        break;
+
+        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;
+
+        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;
+
+        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;
+
+        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;
+
+        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);
+        /* exception here */
+        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);
+        /* exception here */
+        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;
+
+        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);
+        tcg_gen_add_i64(cpu_R[rd], 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);
+        tcg_gen_add_tl(cpu_R[rd], 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);
+        tcg_gen_sub_i64(cpu_R[rd], 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);
+        tcg_gen_sub_tl(cpu_R[rd], 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) {
+                tcg_gen_mul_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                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) {
+            tcg_gen_mul_i32(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            tcg_gen_movi_i64(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);
+        if (cpu_R[rb] != 0) {
+            tcg_gen_div_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            /* exception here */
+        }
+        break;
+
+    case 0x03:    /*lf.div.s*/
+        LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
+        if (cpu_R[rb] != 0) {
+            tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            /* exception here */
+        }
+        break;
+
+    case 0x14:    /*lf.itof.d*/
+        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+        /* itof.d need a helper here */
+        break;
+
+    case 0x04:    /*lf.itof.s*/
+        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+        /* itof.s need a helper here */
+        break;
+
+    case 0x15:    /*lf.ftoi.d*/
+        LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+        /* ftoi.d need a helper here */
+        break;
+
+    case 0x05:    /*lf.ftoi.s*/
+        LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+        /* ftoi.s need a helper here */
+        break;
+
+    case 0x16:    /*lf.rem.d*/
+        LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
+        tcg_gen_rem_i64(cpu_R[rd], 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);
+        tcg_gen_rem_tl(cpu_R[rd], 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);
+        {
+            TCGv_i64 t0, t1;
+
+            t0 = tcg_temp_new_i64();
+            t1 = tcg_temp_new_i64();
+
+            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_add_tl(fpmaddlo, cpu_R[ra], fpmaddlo);
+            tcg_gen_shri_i64(t0, t0, 32);
+            tcg_gen_trunc_i64_i32(cpu_R[rb], t0);
+            tcg_gen_add_tl(fpmaddhi, cpu_R[rb], fpmaddhi);
+
+            tcg_temp_free_i64(t0);
+            tcg_temp_free_i64(t1);
+        }
+        break;
+
+    case 0x07:    /*lf.madd.s*/
+        LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
+        {
+            TCGv_i64 t0, t1;
+
+            t0 = tcg_temp_new_i64();
+            t1 = tcg_temp_new_i64();
+
+            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_add_tl(fpmaddlo, cpu_R[ra], fpmaddlo);
+            tcg_gen_shri_i64(t0, t0, 32);
+            tcg_gen_trunc_i64_i32(cpu_R[rb], t0);
+            tcg_gen_add_tl(fpmaddhi, cpu_R[rb], fpmaddhi);
+            tcg_temp_free_i64(t0);
+            tcg_temp_free_i64(t1);
+
+        }
+        break;
+
+    case 0x18:    /*lf.sfeq.d*/
+        LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x08:    /*lf.sfeq.s*/
+        LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x19:    /*lf.sfne.d*/
+        LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x09:    /*lf.sfne.s*/
+        LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1a:    /*lf.sfgt.d*/
+        LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0a:    /*lf.sfgt.s*/
+        LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1b:    /*lf.sfge.d*/
+        LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0b:    /*lf.sfge.s*/
+        LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1c:    /*lf.sflt.d*/
+        LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0c:    /*lf.sflt.s*/
+        LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1d:    /*lf.sfle.d*/
+        LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0d:    /*lf.sfle.s*/
+        LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+        break;
+    }
+    wb_SR_F();
+}
+
+static void disas_openrisc_insn(DisasContext *dc, CPUOPENRISCState *env)
+{
+    uint32_t op0;
+    uint32_t insn;
+    insn = ldl_code(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);
+                /* exception here */
+                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, lj;
+    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->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;
+    lj = -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 (lj < j) {
+                lj++;
+                while (lj < j) {
+                    gen_opc_instr_start[lj++] = 0;
+                }
+            }
+            gen_opc_pc[lj] = dc->pc;
+            gen_opc_instr_start[lj] = 1;
+            gen_opc_icount[lj] = 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;
Isn't now npc == pc and ppc == pc - 8?
I don't think so, but I'll check it.
OK, I'm just commenting based on my Sparc knowledge which also has PC
and NPC with at least similar names. There NPC should be PC + 4 unless
there is a control transfer instruction.

This reminds me that I forgot to ask to put a link to CPU
documentation in a comment somewhere.
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+        num_insns++;
+        /* delay slot */
+        if (dc->delayed_branch) {
+            dc->delayed_branch--;
+            if (!dc->delayed_branch) {
+                dc->tb_flags &= ~D_FLAG;
+                tcg_gen_movi_i32(env_flags, dc->tb_flags);
This does not look correct.
for exception in delay slot, it is.
The TB flags are very different from CPU flags (NZVC etc.), isn't that
what env_flags is for?
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+                tcg_gen_mov_tl(cpu_pc, jmp_pc);
+                tcg_gen_mov_tl(cpu_npc, jmp_pc);
+ 4?
Post by Jia Liu
+                tcg_gen_movi_tl(jmp_pc, 0);
+                tcg_gen_exit_tb(0);
+                dc->is_jmp = DISAS_JUMP;
+                break;
+            }
Is it possible to have a jump instruction in the delay slot and if so,
is it handled too?
I've done for this.
Post by Blue Swirl
Post by Jia Liu
+        }
+    } 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);
+        }
+        /* exception here*/
+    } 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;
+        lj++;
+        while (lj <= j) {
+            gen_opc_instr_start[lj++] = 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)
@@ -80,7 +1461,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
Jia Liu
2012-05-25 23:50:28 UTC
Permalink
Post by Blue Swirl
Post by Jia Liu
Thanks Blue.
Post by Blue Swirl
Post by Jia Liu
add the openrisc instructions translation.
---
 target-openrisc/translate.c | 1387 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1387 insertions(+)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index aae483a..4828ae6 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -55,14 +55,1395 @@ typedef struct DisasContext {
    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 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");
+    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;
+}
+
+/* General purpose registers moves. */
+static inline void gen_load_gpr(TCGv t, unsigned int reg)
+{
+    if (reg == 0) {
+        tcg_gen_movi_tl(t, 0);
+    } else {
+        tcg_gen_mov_tl(t, cpu_R[reg]);
+    }
+}
This does not seem to be used. Does the code handle the cases where
one or several of the registers is number 0? If this is the always-0
register, are stores to register 0 handled correctly?
I'll remove it.
Post by Blue Swirl
Post by Jia Liu
+
+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) {
+            /* exception here */
+        }
+        tcg_gen_exit_tb(0);
+    }
+}
+
+static inline uint32_t field(uint32_t val, int start, int length)
+{
+    val >>= start;
+    val &= ~(~0 << length);
+    return val;
+}
Nice function, maybe I could use it in Sparc as well if generalized (later).
Post by Jia Liu
+
+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);
+            /* Aha, we do need a helper here for add */
+            break;
+            break;
+        }
+    break;
+
+    case 0x0001:    /*l.addc*/
+        switch (op1) {
+            LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
+            /* Aha, we do need a helper here for addc */
+            break;
+            break;
+        }
+    break;
+
+    case 0x0002:    /*l.sub*/
+        switch (op1) {
+            LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
+            /* Aha, we do need a helper here for sub */
+            break;
What happens on a real CPU when an illegal instruction is executed,
shouldn't there be an exception?
I'll add a exception for illegal instruction.
Post by Blue Swirl
Post by Jia Liu
+            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;
+            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;
+            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;
+            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) {
+                tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[rd]);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0x0);
+            }
+        break;
Indentation.
Post by Jia Liu
+            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) {
+                tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                /* exception here */
+            }
+            break;
+            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) {
+                tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
By the way, a division by zero will crash QEMU. Please add a runtime
http://git.qemu.org/?p=qemu.git;a=blob;f=target-sparc/translate.c;h=b95f91cd3baf9c02305f8583662b8eba664b17ba;hb=HEAD#l765
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+            } else {
+                /* exception here */
+            }
+            break;
+            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) {
+                tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+                tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
+                tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0);
+            }
+            break;
+            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);
+            }
+            break;
+            break;
+        }
+        break;
+
+        switch (op1) {
+        case 0x00:   /*l.ff1*/
+            LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
+            /* ff1 need a helper here */
+            break;
+        case 0x01:   /*l.fl1*/
+            LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
+            /* fl1 need a helper here */
+            break;
+            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;
+                break;
+            }
+            break;
+            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;
+                break;
+            }
+            break;
+            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;
+                break;
+            }
+            break;
+        }
+        break;
+
+        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);
+            tmp = sign_extend((N26<<2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x01:   /*l.jal*/
+        {
+            LOG_DIS("l.jal %d\n", N26);
+            tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+            tmp = sign_extend((N26<<2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x03:   /*l.bnf*/
+        LOG_DIS("l.bnf %d\n", N26);
+        {
+            int lab = gen_new_label();
+            TCGv sr_f = tcg_temp_new();
+            tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+            tmp = sign_extend((N26 << 2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+            tcg_gen_brcondi_tl(TCG_COND_EQ, sr_f, SR_F, lab);
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            gen_set_label(lab);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+            tcg_temp_free(sr_f);
+        }
+        break;
+
+    case 0x04:   /*l.bf*/
+        LOG_DIS("l.bf %d\n", N26);
+        {
+            int lab = gen_new_label();
+            TCGv sr_f = tcg_temp_new();
+            tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+            tmp = sign_extend((N26 << 2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+            tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            gen_set_label(lab);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+            tcg_temp_free(sr_f);
+        }
+        break;
+
+        switch (op1) {
+        case 0x01:   /*l.nop*/
+            LOG_DIS("l.nop %d\n", I16);
+            break;
+            break;
+        }
+        break;
+
+    case 0x11:    /*l.jr*/
+        LOG_DIS("l.jr r%d\n", rb);
+        {
+            tcg_gen_mov_tl(jmp_pc, cpu_R[rb]);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x12:    /*l.jalr*/
+        LOG_DIS("l.jalr r%d\n", rb);
+        {
+            tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+            gen_load_gpr(jmp_pc, rb);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        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*/
Variable definitions should be before code, like LOG_DIS() call in this case.
OK, thx.
Post by Blue Swirl
Post by Jia Liu
+            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");
+        {
+            /* rfe need a helper here */
+            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));
+            /* Aha, we do need a helper here for addi */
+            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));
+            /* Aha, we do need a helper here for addic */
+            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) {
+            tcg_gen_muli_tl(cpu_R[rd], cpu_R[ra], I16);
+            tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[rd]);
+        } else {
+            tcg_gen_movi_tl(cpu_R[rd], 0);
+        }
+        break;
+
+    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);
+            /* mfspr need a helper here */
+            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);
+            /* mtspr need a helper here */
+            tcg_temp_free_i32(ti);
+            tcg_temp_free(ta);
+            tcg_temp_free(tb);
+        }
+        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;
+        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();
+    switch (op0) {
+    case 0x0001:   /*l.mac*/
+        {
+            LOG_DIS("l.mac 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_add_tl(maclo, maclo, cpu_R[ra]);
+            tcg_gen_add_tl(machi, machi, cpu_R[ra]);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+        }
+        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_tl(maclo, maclo, cpu_R[ra]);
+            tcg_gen_sub_tl(machi, machi, cpu_R[ra]);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+        }
+        break;
+
+        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;
+
+        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;
+
+        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;
+
+        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;
+
+        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);
+        /* exception here */
+        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);
+        /* exception here */
+        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;
+
+        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);
+        tcg_gen_add_i64(cpu_R[rd], 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);
+        tcg_gen_add_tl(cpu_R[rd], 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);
+        tcg_gen_sub_i64(cpu_R[rd], 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);
+        tcg_gen_sub_tl(cpu_R[rd], 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) {
+                tcg_gen_mul_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                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) {
+            tcg_gen_mul_i32(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            tcg_gen_movi_i64(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);
+        if (cpu_R[rb] != 0) {
+            tcg_gen_div_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            /* exception here */
+        }
+        break;
+
+    case 0x03:    /*lf.div.s*/
+        LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
+        if (cpu_R[rb] != 0) {
+            tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            /* exception here */
+        }
+        break;
+
+    case 0x14:    /*lf.itof.d*/
+        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+        /* itof.d need a helper here */
+        break;
+
+    case 0x04:    /*lf.itof.s*/
+        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+        /* itof.s need a helper here */
+        break;
+
+    case 0x15:    /*lf.ftoi.d*/
+        LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+        /* ftoi.d need a helper here */
+        break;
+
+    case 0x05:    /*lf.ftoi.s*/
+        LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+        /* ftoi.s need a helper here */
+        break;
+
+    case 0x16:    /*lf.rem.d*/
+        LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
+        tcg_gen_rem_i64(cpu_R[rd], 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);
+        tcg_gen_rem_tl(cpu_R[rd], 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);
+        {
+            TCGv_i64 t0, t1;
+
+            t0 = tcg_temp_new_i64();
+            t1 = tcg_temp_new_i64();
+
+            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_add_tl(fpmaddlo, cpu_R[ra], fpmaddlo);
+            tcg_gen_shri_i64(t0, t0, 32);
+            tcg_gen_trunc_i64_i32(cpu_R[rb], t0);
+            tcg_gen_add_tl(fpmaddhi, cpu_R[rb], fpmaddhi);
+
+            tcg_temp_free_i64(t0);
+            tcg_temp_free_i64(t1);
+        }
+        break;
+
+    case 0x07:    /*lf.madd.s*/
+        LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
+        {
+            TCGv_i64 t0, t1;
+
+            t0 = tcg_temp_new_i64();
+            t1 = tcg_temp_new_i64();
+
+            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_add_tl(fpmaddlo, cpu_R[ra], fpmaddlo);
+            tcg_gen_shri_i64(t0, t0, 32);
+            tcg_gen_trunc_i64_i32(cpu_R[rb], t0);
+            tcg_gen_add_tl(fpmaddhi, cpu_R[rb], fpmaddhi);
+            tcg_temp_free_i64(t0);
+            tcg_temp_free_i64(t1);
+
+        }
+        break;
+
+    case 0x18:    /*lf.sfeq.d*/
+        LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x08:    /*lf.sfeq.s*/
+        LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x19:    /*lf.sfne.d*/
+        LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x09:    /*lf.sfne.s*/
+        LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1a:    /*lf.sfgt.d*/
+        LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0a:    /*lf.sfgt.s*/
+        LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1b:    /*lf.sfge.d*/
+        LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0b:    /*lf.sfge.s*/
+        LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1c:    /*lf.sflt.d*/
+        LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0c:    /*lf.sflt.s*/
+        LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1d:    /*lf.sfle.d*/
+        LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0d:    /*lf.sfle.s*/
+        LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+        break;
+    }
+    wb_SR_F();
+}
+
+static void disas_openrisc_insn(DisasContext *dc, CPUOPENRISCState *env)
+{
+    uint32_t op0;
+    uint32_t insn;
+    insn = ldl_code(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);
+                /* exception here */
+                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, lj;
+    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->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;
+    lj = -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 (lj < j) {
+                lj++;
+                while (lj < j) {
+                    gen_opc_instr_start[lj++] = 0;
+                }
+            }
+            gen_opc_pc[lj] = dc->pc;
+            gen_opc_instr_start[lj] = 1;
+            gen_opc_icount[lj] = 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;
Isn't now npc == pc and ppc == pc - 8?
I don't think so, but I'll check it.
OK, I'm just commenting based on my Sparc knowledge which also has PC
and NPC with at least similar names. There NPC should be PC + 4 unless
there is a control transfer instruction.
This reminds me that I forgot to ask to put a link to CPU
documentation in a comment somewhere.
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+        num_insns++;
+        /* delay slot */
+        if (dc->delayed_branch) {
+            dc->delayed_branch--;
+            if (!dc->delayed_branch) {
+                dc->tb_flags &= ~D_FLAG;
+                tcg_gen_movi_i32(env_flags, dc->tb_flags);
This does not look correct.
for exception in delay slot, it is.
The TB flags are very different from CPU flags (NZVC etc.), isn't that
what env_flags is for?
Thanks, fixed.
Post by Blue Swirl
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+                tcg_gen_mov_tl(cpu_pc, jmp_pc);
+                tcg_gen_mov_tl(cpu_npc, jmp_pc);
+ 4?
Post by Jia Liu
+                tcg_gen_movi_tl(jmp_pc, 0);
+                tcg_gen_exit_tb(0);
+                dc->is_jmp = DISAS_JUMP;
+                break;
+            }
Is it possible to have a jump instruction in the delay slot and if so,
is it handled too?
I've done for this.
Post by Blue Swirl
Post by Jia Liu
+        }
+    } 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);
+        }
+        /* exception here*/
+    } 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;
+        lj++;
+        while (lj <= j) {
+            gen_opc_instr_start[lj++] = 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)
@@ -80,7 +1461,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
Jia,
Regards.
Jia Liu
2012-05-26 00:37:19 UTC
Permalink
Post by Blue Swirl
Post by Jia Liu
Thanks Blue.
Post by Blue Swirl
Post by Jia Liu
add the openrisc instructions translation.
---
 target-openrisc/translate.c | 1387 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1387 insertions(+)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index aae483a..4828ae6 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -55,14 +55,1395 @@ typedef struct DisasContext {
    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 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");
+    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;
+}
+
+/* General purpose registers moves. */
+static inline void gen_load_gpr(TCGv t, unsigned int reg)
+{
+    if (reg == 0) {
+        tcg_gen_movi_tl(t, 0);
+    } else {
+        tcg_gen_mov_tl(t, cpu_R[reg]);
+    }
+}
This does not seem to be used. Does the code handle the cases where
one or several of the registers is number 0? If this is the always-0
register, are stores to register 0 handled correctly?
I'll remove it.
Post by Blue Swirl
Post by Jia Liu
+
+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) {
+            /* exception here */
+        }
+        tcg_gen_exit_tb(0);
+    }
+}
+
+static inline uint32_t field(uint32_t val, int start, int length)
+{
+    val >>= start;
+    val &= ~(~0 << length);
+    return val;
+}
Nice function, maybe I could use it in Sparc as well if generalized (later).
Post by Jia Liu
+
+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);
+            /* Aha, we do need a helper here for add */
+            break;
+            break;
+        }
+    break;
+
+    case 0x0001:    /*l.addc*/
+        switch (op1) {
+            LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
+            /* Aha, we do need a helper here for addc */
+            break;
+            break;
+        }
+    break;
+
+    case 0x0002:    /*l.sub*/
+        switch (op1) {
+            LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
+            /* Aha, we do need a helper here for sub */
+            break;
What happens on a real CPU when an illegal instruction is executed,
shouldn't there be an exception?
I'll add a exception for illegal instruction.
Post by Blue Swirl
Post by Jia Liu
+            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;
+            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;
+            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;
+            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) {
+                tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[rd]);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0x0);
+            }
+        break;
Indentation.
Post by Jia Liu
+            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) {
+                tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                /* exception here */
+            }
+            break;
+            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) {
+                tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
By the way, a division by zero will crash QEMU. Please add a runtime
http://git.qemu.org/?p=qemu.git;a=blob;f=target-sparc/translate.c;h=b95f91cd3baf9c02305f8583662b8eba664b17ba;hb=HEAD#l765
Thanks, I've reimplement l.div, and I think it is fixed.
Post by Blue Swirl
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+            } else {
+                /* exception here */
+            }
+            break;
+            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) {
+                tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+                tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
+                tcg_gen_mul_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                tcg_gen_movi_tl(cpu_R[rd], 0);
+            }
+            break;
+            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);
+            }
+            break;
+            break;
+        }
+        break;
+
+        switch (op1) {
+        case 0x00:   /*l.ff1*/
+            LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
+            /* ff1 need a helper here */
+            break;
+        case 0x01:   /*l.fl1*/
+            LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
+            /* fl1 need a helper here */
+            break;
+            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;
+                break;
+            }
+            break;
+            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;
+                break;
+            }
+            break;
+            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;
+                break;
+            }
+            break;
+        }
+        break;
+
+        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);
+            tmp = sign_extend((N26<<2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x01:   /*l.jal*/
+        {
+            LOG_DIS("l.jal %d\n", N26);
+            tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+            tmp = sign_extend((N26<<2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x03:   /*l.bnf*/
+        LOG_DIS("l.bnf %d\n", N26);
+        {
+            int lab = gen_new_label();
+            TCGv sr_f = tcg_temp_new();
+            tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+            tmp = sign_extend((N26 << 2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+            tcg_gen_brcondi_tl(TCG_COND_EQ, sr_f, SR_F, lab);
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            gen_set_label(lab);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+            tcg_temp_free(sr_f);
+        }
+        break;
+
+    case 0x04:   /*l.bf*/
+        LOG_DIS("l.bf %d\n", N26);
+        {
+            int lab = gen_new_label();
+            TCGv sr_f = tcg_temp_new();
+            tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+            tmp = sign_extend((N26 << 2), 26) + dc->pc;
+            tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+            tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
+            tcg_gen_movi_tl(jmp_pc, tmp);
+            gen_set_label(lab);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+            tcg_temp_free(sr_f);
+        }
+        break;
+
+        switch (op1) {
+        case 0x01:   /*l.nop*/
+            LOG_DIS("l.nop %d\n", I16);
+            break;
+            break;
+        }
+        break;
+
+    case 0x11:    /*l.jr*/
+        LOG_DIS("l.jr r%d\n", rb);
+        {
+            tcg_gen_mov_tl(jmp_pc, cpu_R[rb]);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        break;
+
+    case 0x12:    /*l.jalr*/
+        LOG_DIS("l.jalr r%d\n", rb);
+        {
+            tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+            gen_load_gpr(jmp_pc, rb);
+            dc->delayed_branch = 2;
+            dc->tb_flags |= D_FLAG;
+            tcg_gen_movi_i32(env_flags, dc->tb_flags);
+        }
+        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*/
Variable definitions should be before code, like LOG_DIS() call in this case.
OK, thx.
Post by Blue Swirl
Post by Jia Liu
+            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");
+        {
+            /* rfe need a helper here */
+            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));
+            /* Aha, we do need a helper here for addi */
+            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));
+            /* Aha, we do need a helper here for addic */
+            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) {
+            tcg_gen_muli_tl(cpu_R[rd], cpu_R[ra], I16);
+            tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[rd]);
+        } else {
+            tcg_gen_movi_tl(cpu_R[rd], 0);
+        }
+        break;
+
+    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);
+            /* mfspr need a helper here */
+            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);
+            /* mtspr need a helper here */
+            tcg_temp_free_i32(ti);
+            tcg_temp_free(ta);
+            tcg_temp_free(tb);
+        }
+        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;
+        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();
+    switch (op0) {
+    case 0x0001:   /*l.mac*/
+        {
+            LOG_DIS("l.mac 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_add_tl(maclo, maclo, cpu_R[ra]);
+            tcg_gen_add_tl(machi, machi, cpu_R[ra]);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+        }
+        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_tl(maclo, maclo, cpu_R[ra]);
+            tcg_gen_sub_tl(machi, machi, cpu_R[ra]);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+        }
+        break;
+
+        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;
+
+        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;
+
+        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;
+
+        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;
+
+        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);
+        /* exception here */
+        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);
+        /* exception here */
+        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;
+
+        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);
+        tcg_gen_add_i64(cpu_R[rd], 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);
+        tcg_gen_add_tl(cpu_R[rd], 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);
+        tcg_gen_sub_i64(cpu_R[rd], 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);
+        tcg_gen_sub_tl(cpu_R[rd], 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) {
+                tcg_gen_mul_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            } else {
+                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) {
+            tcg_gen_mul_i32(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            tcg_gen_movi_i64(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);
+        if (cpu_R[rb] != 0) {
+            tcg_gen_div_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            /* exception here */
+        }
+        break;
+
+    case 0x03:    /*lf.div.s*/
+        LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
+        if (cpu_R[rb] != 0) {
+            tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+        } else {
+            /* exception here */
+        }
+        break;
+
+    case 0x14:    /*lf.itof.d*/
+        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+        /* itof.d need a helper here */
+        break;
+
+    case 0x04:    /*lf.itof.s*/
+        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+        /* itof.s need a helper here */
+        break;
+
+    case 0x15:    /*lf.ftoi.d*/
+        LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+        /* ftoi.d need a helper here */
+        break;
+
+    case 0x05:    /*lf.ftoi.s*/
+        LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+        /* ftoi.s need a helper here */
+        break;
+
+    case 0x16:    /*lf.rem.d*/
+        LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
+        tcg_gen_rem_i64(cpu_R[rd], 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);
+        tcg_gen_rem_tl(cpu_R[rd], 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);
+        {
+            TCGv_i64 t0, t1;
+
+            t0 = tcg_temp_new_i64();
+            t1 = tcg_temp_new_i64();
+
+            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_add_tl(fpmaddlo, cpu_R[ra], fpmaddlo);
+            tcg_gen_shri_i64(t0, t0, 32);
+            tcg_gen_trunc_i64_i32(cpu_R[rb], t0);
+            tcg_gen_add_tl(fpmaddhi, cpu_R[rb], fpmaddhi);
+
+            tcg_temp_free_i64(t0);
+            tcg_temp_free_i64(t1);
+        }
+        break;
+
+    case 0x07:    /*lf.madd.s*/
+        LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
+        {
+            TCGv_i64 t0, t1;
+
+            t0 = tcg_temp_new_i64();
+            t1 = tcg_temp_new_i64();
+
+            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_add_tl(fpmaddlo, cpu_R[ra], fpmaddlo);
+            tcg_gen_shri_i64(t0, t0, 32);
+            tcg_gen_trunc_i64_i32(cpu_R[rb], t0);
+            tcg_gen_add_tl(fpmaddhi, cpu_R[rb], fpmaddhi);
+            tcg_temp_free_i64(t0);
+            tcg_temp_free_i64(t1);
+
+        }
+        break;
+
+    case 0x18:    /*lf.sfeq.d*/
+        LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x08:    /*lf.sfeq.s*/
+        LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x19:    /*lf.sfne.d*/
+        LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x09:    /*lf.sfne.s*/
+        LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1a:    /*lf.sfgt.d*/
+        LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0a:    /*lf.sfgt.s*/
+        LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1b:    /*lf.sfge.d*/
+        LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0b:    /*lf.sfge.s*/
+        LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1c:    /*lf.sflt.d*/
+        LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0c:    /*lf.sflt.s*/
+        LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1d:    /*lf.sfle.d*/
+        LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_i64(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0d:    /*lf.sfle.s*/
+        LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+        break;
+    }
+    wb_SR_F();
+}
+
+static void disas_openrisc_insn(DisasContext *dc, CPUOPENRISCState *env)
+{
+    uint32_t op0;
+    uint32_t insn;
+    insn = ldl_code(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);
+                /* exception here */
+                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, lj;
+    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->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;
+    lj = -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 (lj < j) {
+                lj++;
+                while (lj < j) {
+                    gen_opc_instr_start[lj++] = 0;
+                }
+            }
+            gen_opc_pc[lj] = dc->pc;
+            gen_opc_instr_start[lj] = 1;
+            gen_opc_icount[lj] = 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;
Isn't now npc == pc and ppc == pc - 8?
I don't think so, but I'll check it.
OK, I'm just commenting based on my Sparc knowledge which also has PC
and NPC with at least similar names. There NPC should be PC + 4 unless
there is a control transfer instruction.
This reminds me that I forgot to ask to put a link to CPU
documentation in a comment somewhere.
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+        num_insns++;
+        /* delay slot */
+        if (dc->delayed_branch) {
+            dc->delayed_branch--;
+            if (!dc->delayed_branch) {
+                dc->tb_flags &= ~D_FLAG;
+                tcg_gen_movi_i32(env_flags, dc->tb_flags);
This does not look correct.
for exception in delay slot, it is.
The TB flags are very different from CPU flags (NZVC etc.), isn't that
what env_flags is for?
maybe not, Openrisc does not have flag bit in some register for this,
so we have to add it by ourselves, so, the code look like what you see
now.
I'll rewrite this code, maybe it looks better now.
Post by Blue Swirl
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+                tcg_gen_mov_tl(cpu_pc, jmp_pc);
+                tcg_gen_mov_tl(cpu_npc, jmp_pc);
+ 4?
Post by Jia Liu
+                tcg_gen_movi_tl(jmp_pc, 0);
+                tcg_gen_exit_tb(0);
+                dc->is_jmp = DISAS_JUMP;
+                break;
+            }
Is it possible to have a jump instruction in the delay slot and if so,
is it handled too?
I've done for this.
Post by Blue Swirl
Post by Jia Liu
+        }
+    } 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);
+        }
+        /* exception here*/
+    } 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;
+        lj++;
+        while (lj <= j) {
+            gen_opc_instr_start[lj++] = 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)
@@ -80,7 +1461,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
Jia,
Regards.
Jia Liu
2012-05-17 08:35:48 UTC
Permalink
add the openrisc exception support.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 2 +-
target-openrisc/excp.c | 27 +++++++++++++++++++++++++++
target-openrisc/excp.h | 28 ++++++++++++++++++++++++++++
target-openrisc/excp_helper.c | 28 ++++++++++++++++++++++++++++
target-openrisc/helper.h | 3 +++
target-openrisc/translate.c | 25 ++++++++++++++++---------
6 files changed, 103 insertions(+), 10 deletions(-)
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 975c9a8..ed5f0b0 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) += intrp_helper.o mem.o mem_helper.o
+libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o intrp_helper.o mem.o mem_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..fc9391a
--- /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 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..4c32e46
--- /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 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..0cad14b
--- /dev/null
+++ b/target-openrisc/excp_helper.c
@@ -0,0 +1,28 @@
+/*
+ * 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 Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#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 bb394ad..a0fb8c4 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -20,6 +20,9 @@

#include "def-helper.h"

+/* exception */
+DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)
+
/* interrupt */
DEF_HELPER_FLAGS_1(rfe, 0, void, env)

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index dd0240c..a1264c9 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -155,6 +155,13 @@ static inline void gen_load_gpr(TCGv t, unsigned int reg)
}
}

+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_goto_tb(DisasContext *dc, int n, target_ulong dest)
{
TranslationBlock *tb;
@@ -167,7 +174,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
} else {
tcg_gen_movi_tl(cpu_pc, dest);
if (dc->singlestep_enabled) {
- /* exception here */
+ gen_exception(dc, EXCP_DEBUG);
}
tcg_gen_exit_tb(0);
}
@@ -281,7 +288,7 @@ static void dec_calc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
if (rb != 0) {
tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
} else {
- /* exception here */
+ gen_exception(dc, EXCP_RANGE);
}
break;
default:
@@ -296,7 +303,7 @@ static void dec_calc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
if (rb != 0) {
tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
} else {
- /* exception here */
+ gen_exception(dc, EXCP_RANGE);
}
break;
default:
@@ -1003,14 +1010,14 @@ static void dec_sys(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
case 0x000: /*l.sys*/
/*LOG_DIS("l.sys %d\n", K16);*/
tcg_gen_movi_tl(cpu_pc, dc->pc);
- /* exception here */
+ 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);
- /* exception here */
+ gen_exception(dc, EXCP_TRAP);
break;

case 0x300: /*l.csync*/
@@ -1085,7 +1092,7 @@ static void dec_float(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
if (cpu_R[rb] != 0) {
tcg_gen_div_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
} else {
- /* exception here */
+ gen_exception(dc, EXCP_RANGE);
}
break;

@@ -1094,7 +1101,7 @@ static void dec_float(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
if (cpu_R[rb] != 0) {
tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
} else {
- /* exception here */
+ gen_exception(dc, EXCP_RANGE);
}
break;

@@ -1294,7 +1301,7 @@ static void check_breakpoint(CPUOPENRISCState *env, DisasContext *dc)
QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
if (bp->pc == dc->pc) {
tcg_gen_movi_tl(cpu_pc, dc->pc);
- /* exception here */
+ gen_exception(dc, EXCP_DEBUG);
dc->is_jmp = DISAS_UPDATE;
}
}
@@ -1403,7 +1410,7 @@ static inline void gen_intermediate_code_internal(CPUOPENRISCState *env,
if (dc->is_jmp == DISAS_NEXT) {
tcg_gen_movi_tl(cpu_pc, dc->pc);
}
- /* exception here*/
+ gen_exception(dc, EXCP_DEBUG);
} else {
switch (dc->is_jmp) {
case DISAS_NEXT:
--
1.7.9.5
Blue Swirl
2012-05-19 07:22:16 UTC
Permalink
Post by Jia Liu
add the openrisc exception support.
---
 Makefile.target               |    2 +-
 target-openrisc/excp.c        |   27 +++++++++++++++++++++++++++
 target-openrisc/excp.h        |   28 ++++++++++++++++++++++++++++
 target-openrisc/excp_helper.c |   28 ++++++++++++++++++++++++++++
 target-openrisc/helper.h      |    3 +++
 target-openrisc/translate.c   |   25 ++++++++++++++++---------
 6 files changed, 103 insertions(+), 10 deletions(-)
 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 975c9a8..ed5f0b0 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) += intrp_helper.o mem.o mem_helper.o
+libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o intrp_helper.o mem.o mem_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..fc9391a
--- /dev/null
+++ b/target-openrisc/excp.c
@@ -0,0 +1,27 @@
+/*
+ *  Openrisc exception.
+ *
+ *
+ * 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 raise_exception(CPUOPENRISCState *env, uint32_t excp)
QEMU_NORETURN?
Post by Jia Liu
+{
+    env->exception_index = excp;
+    cpu_loop_exit(env);
+}
I'd just merge this file with excp_helper.c for simplicity, though
it's not incorrect either.
Post by Jia Liu
diff --git a/target-openrisc/excp.h b/target-openrisc/excp.h
new file mode 100644
index 0000000..4c32e46
--- /dev/null
+++ b/target-openrisc/excp.h
@@ -0,0 +1,28 @@
+/*
+ *  Openrisc exception 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 QEMU_OPENRISC_EXCP_H
+#define QEMU_OPENRISC_EXCP_H
+
+#include "cpu.h"
+#include "qemu-common.h"
+
+void 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..0cad14b
--- /dev/null
+++ b/target-openrisc/excp_helper.c
@@ -0,0 +1,28 @@
+/*
+ * OpenRISC exception helper routines
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
Please use the web version instead.
Post by Jia Liu
+ */
+
+#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 bb394ad..a0fb8c4 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -20,6 +20,9 @@
 #include "def-helper.h"
+/* exception */
+DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)
+
 /* interrupt */
 DEF_HELPER_FLAGS_1(rfe, 0, void, env)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index dd0240c..a1264c9 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -155,6 +155,13 @@ static inline void gen_load_gpr(TCGv t, unsigned int reg)
    }
 }
+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_goto_tb(DisasContext *dc, int n, target_ulong dest)
 {
    TranslationBlock *tb;
@@ -167,7 +174,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
    } else {
        tcg_gen_movi_tl(cpu_pc, dest);
        if (dc->singlestep_enabled) {
-            /* exception here */
+            gen_exception(dc, EXCP_DEBUG);
        }
        tcg_gen_exit_tb(0);
    }
@@ -281,7 +288,7 @@ static void dec_calc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
            if (rb != 0) {
                tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
            } else {
-                /* exception here */
+                gen_exception(dc, EXCP_RANGE);
            }
            break;
@@ -296,7 +303,7 @@ static void dec_calc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
            if (rb != 0) {
                tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
            } else {
-                /* exception here */
+                gen_exception(dc, EXCP_RANGE);
            }
            break;
@@ -1003,14 +1010,14 @@ static void dec_sys(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
    case 0x000:  /*l.sys*/
        /*LOG_DIS("l.sys %d\n", K16);*/
        tcg_gen_movi_tl(cpu_pc, dc->pc);
-        /* exception here */
+        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);
-        /* exception here */
+        gen_exception(dc, EXCP_TRAP);
        break;
    case 0x300:  /*l.csync*/
@@ -1085,7 +1092,7 @@ static void dec_float(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
        if (cpu_R[rb] != 0) {
            tcg_gen_div_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
        } else {
-            /* exception here */
+            gen_exception(dc, EXCP_RANGE);
        }
        break;
@@ -1094,7 +1101,7 @@ static void dec_float(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
        if (cpu_R[rb] != 0) {
            tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
        } else {
-            /* exception here */
+            gen_exception(dc, EXCP_RANGE);
        }
        break;
@@ -1294,7 +1301,7 @@ static void check_breakpoint(CPUOPENRISCState *env, DisasContext *dc)
        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
            if (bp->pc == dc->pc) {
                tcg_gen_movi_tl(cpu_pc, dc->pc);
-                /* exception here */
+                gen_exception(dc, EXCP_DEBUG);
                dc->is_jmp = DISAS_UPDATE;
            }
        }
@@ -1403,7 +1410,7 @@ static inline void gen_intermediate_code_internal(CPUOPENRISCState *env,
        if (dc->is_jmp == DISAS_NEXT) {
            tcg_gen_movi_tl(cpu_pc, dc->pc);
        }
-        /* exception here*/
+        gen_exception(dc, EXCP_DEBUG);
    } else {
        switch (dc->is_jmp) {
--
1.7.9.5
Jia Liu
2012-05-23 07:09:37 UTC
Permalink
Hi Blue,
Post by Blue Swirl
Post by Jia Liu
add the openrisc exception support.
---
 Makefile.target               |    2 +-
 target-openrisc/excp.c        |   27 +++++++++++++++++++++++++++
 target-openrisc/excp.h        |   28 ++++++++++++++++++++++++++++
 target-openrisc/excp_helper.c |   28 ++++++++++++++++++++++++++++
 target-openrisc/helper.h      |    3 +++
 target-openrisc/translate.c   |   25 ++++++++++++++++---------
 6 files changed, 103 insertions(+), 10 deletions(-)
 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 975c9a8..ed5f0b0 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) += intrp_helper.o mem.o mem_helper.o
+libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o intrp_helper.o mem.o mem_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..fc9391a
--- /dev/null
+++ b/target-openrisc/excp.c
@@ -0,0 +1,27 @@
+/*
+ *  Openrisc exception.
+ *
+ *
+ * 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 raise_exception(CPUOPENRISCState *env, uint32_t excp)
QEMU_NORETURN?
Does it have to return?
Post by Blue Swirl
Post by Jia Liu
+{
+    env->exception_index = excp;
+    cpu_loop_exit(env);
+}
I'd just merge this file with excp_helper.c for simplicity, though
it's not incorrect either.
Post by Jia Liu
diff --git a/target-openrisc/excp.h b/target-openrisc/excp.h
new file mode 100644
index 0000000..4c32e46
--- /dev/null
+++ b/target-openrisc/excp.h
@@ -0,0 +1,28 @@
+/*
+ *  Openrisc exception 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 QEMU_OPENRISC_EXCP_H
+#define QEMU_OPENRISC_EXCP_H
+
+#include "cpu.h"
+#include "qemu-common.h"
+
+void 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..0cad14b
--- /dev/null
+++ b/target-openrisc/excp_helper.c
@@ -0,0 +1,28 @@
+/*
+ * OpenRISC exception helper routines
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
Please use the web version instead.
fixed.
Post by Blue Swirl
Post by Jia Liu
+ */
+
+#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 bb394ad..a0fb8c4 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -20,6 +20,9 @@
 #include "def-helper.h"
+/* exception */
+DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)
+
 /* interrupt */
 DEF_HELPER_FLAGS_1(rfe, 0, void, env)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index dd0240c..a1264c9 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -155,6 +155,13 @@ static inline void gen_load_gpr(TCGv t, unsigned int reg)
    }
 }
+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_goto_tb(DisasContext *dc, int n, target_ulong dest)
 {
    TranslationBlock *tb;
@@ -167,7 +174,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
    } else {
        tcg_gen_movi_tl(cpu_pc, dest);
        if (dc->singlestep_enabled) {
-            /* exception here */
+            gen_exception(dc, EXCP_DEBUG);
        }
        tcg_gen_exit_tb(0);
    }
@@ -281,7 +288,7 @@ static void dec_calc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
            if (rb != 0) {
                tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
            } else {
-                /* exception here */
+                gen_exception(dc, EXCP_RANGE);
            }
            break;
@@ -296,7 +303,7 @@ static void dec_calc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
            if (rb != 0) {
                tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
            } else {
-                /* exception here */
+                gen_exception(dc, EXCP_RANGE);
            }
            break;
@@ -1003,14 +1010,14 @@ static void dec_sys(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
    case 0x000:  /*l.sys*/
        /*LOG_DIS("l.sys %d\n", K16);*/
        tcg_gen_movi_tl(cpu_pc, dc->pc);
-        /* exception here */
+        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);
-        /* exception here */
+        gen_exception(dc, EXCP_TRAP);
        break;
    case 0x300:  /*l.csync*/
@@ -1085,7 +1092,7 @@ static void dec_float(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
        if (cpu_R[rb] != 0) {
            tcg_gen_div_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
        } else {
-            /* exception here */
+            gen_exception(dc, EXCP_RANGE);
        }
        break;
@@ -1094,7 +1101,7 @@ static void dec_float(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
        if (cpu_R[rb] != 0) {
            tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
        } else {
-            /* exception here */
+            gen_exception(dc, EXCP_RANGE);
        }
        break;
@@ -1294,7 +1301,7 @@ static void check_breakpoint(CPUOPENRISCState *env, DisasContext *dc)
        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
            if (bp->pc == dc->pc) {
                tcg_gen_movi_tl(cpu_pc, dc->pc);
-                /* exception here */
+                gen_exception(dc, EXCP_DEBUG);
                dc->is_jmp = DISAS_UPDATE;
            }
        }
@@ -1403,7 +1410,7 @@ static inline void gen_intermediate_code_internal(CPUOPENRISCState *env,
        if (dc->is_jmp == DISAS_NEXT) {
            tcg_gen_movi_tl(cpu_pc, dc->pc);
        }
-        /* exception here*/
+        gen_exception(dc, EXCP_DEBUG);
    } else {
        switch (dc->is_jmp) {
--
1.7.9.5
Blue Swirl
2012-05-23 19:11:14 UTC
Permalink
Post by Jia Liu
Hi Blue,
Post by Blue Swirl
Post by Jia Liu
add the openrisc exception support.
---
 Makefile.target               |    2 +-
 target-openrisc/excp.c        |   27 +++++++++++++++++++++++++++
 target-openrisc/excp.h        |   28 ++++++++++++++++++++++++++++
 target-openrisc/excp_helper.c |   28 ++++++++++++++++++++++++++++
 target-openrisc/helper.h      |    3 +++
 target-openrisc/translate.c   |   25 ++++++++++++++++---------
 6 files changed, 103 insertions(+), 10 deletions(-)
 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 975c9a8..ed5f0b0 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) += intrp_helper.o mem.o mem_helper.o
+libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o intrp_helper.o mem.o mem_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..fc9391a
--- /dev/null
+++ b/target-openrisc/excp.c
@@ -0,0 +1,27 @@
+/*
+ *  Openrisc exception.
+ *
+ *
+ * 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 raise_exception(CPUOPENRISCState *env, uint32_t excp)
QEMU_NORETURN?
Does it have to return?
No, QEMU_NORETURN just tells the compiler that the function does not
return, because it executes a longjmp() etc. That way the compiler can
optimize the code.

Here we could propagate QEMU_NORETURN from cpu_loop_exit() which has this flag:
void QEMU_NORETURN cpu_loop_exit(CPUArchState *env1);
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+{
+    env->exception_index = excp;
+    cpu_loop_exit(env);
+}
I'd just merge this file with excp_helper.c for simplicity, though
it's not incorrect either.
Post by Jia Liu
diff --git a/target-openrisc/excp.h b/target-openrisc/excp.h
new file mode 100644
index 0000000..4c32e46
--- /dev/null
+++ b/target-openrisc/excp.h
@@ -0,0 +1,28 @@
+/*
+ *  Openrisc exception 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 QEMU_OPENRISC_EXCP_H
+#define QEMU_OPENRISC_EXCP_H
+
+#include "cpu.h"
+#include "qemu-common.h"
+
+void 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..0cad14b
--- /dev/null
+++ b/target-openrisc/excp_helper.c
@@ -0,0 +1,28 @@
+/*
+ * OpenRISC exception helper routines
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
Please use the web version instead.
fixed.
Post by Blue Swirl
Post by Jia Liu
+ */
+
+#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 bb394ad..a0fb8c4 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -20,6 +20,9 @@
 #include "def-helper.h"
+/* exception */
+DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)
+
 /* interrupt */
 DEF_HELPER_FLAGS_1(rfe, 0, void, env)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index dd0240c..a1264c9 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -155,6 +155,13 @@ static inline void gen_load_gpr(TCGv t, unsigned int reg)
    }
 }
+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_goto_tb(DisasContext *dc, int n, target_ulong dest)
 {
    TranslationBlock *tb;
@@ -167,7 +174,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
    } else {
        tcg_gen_movi_tl(cpu_pc, dest);
        if (dc->singlestep_enabled) {
-            /* exception here */
+            gen_exception(dc, EXCP_DEBUG);
        }
        tcg_gen_exit_tb(0);
    }
@@ -281,7 +288,7 @@ static void dec_calc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
            if (rb != 0) {
                tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
            } else {
-                /* exception here */
+                gen_exception(dc, EXCP_RANGE);
            }
            break;
@@ -296,7 +303,7 @@ static void dec_calc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
            if (rb != 0) {
                tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
            } else {
-                /* exception here */
+                gen_exception(dc, EXCP_RANGE);
            }
            break;
@@ -1003,14 +1010,14 @@ static void dec_sys(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
    case 0x000:  /*l.sys*/
        /*LOG_DIS("l.sys %d\n", K16);*/
        tcg_gen_movi_tl(cpu_pc, dc->pc);
-        /* exception here */
+        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);
-        /* exception here */
+        gen_exception(dc, EXCP_TRAP);
        break;
    case 0x300:  /*l.csync*/
@@ -1085,7 +1092,7 @@ static void dec_float(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
        if (cpu_R[rb] != 0) {
            tcg_gen_div_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
        } else {
-            /* exception here */
+            gen_exception(dc, EXCP_RANGE);
        }
        break;
@@ -1094,7 +1101,7 @@ static void dec_float(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
        if (cpu_R[rb] != 0) {
            tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
        } else {
-            /* exception here */
+            gen_exception(dc, EXCP_RANGE);
        }
        break;
@@ -1294,7 +1301,7 @@ static void check_breakpoint(CPUOPENRISCState *env, DisasContext *dc)
        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
            if (bp->pc == dc->pc) {
                tcg_gen_movi_tl(cpu_pc, dc->pc);
-                /* exception here */
+                gen_exception(dc, EXCP_DEBUG);
                dc->is_jmp = DISAS_UPDATE;
            }
        }
@@ -1403,7 +1410,7 @@ static inline void gen_intermediate_code_internal(CPUOPENRISCState *env,
        if (dc->is_jmp == DISAS_NEXT) {
            tcg_gen_movi_tl(cpu_pc, dc->pc);
        }
-        /* exception here*/
+        gen_exception(dc, EXCP_DEBUG);
    } else {
        switch (dc->is_jmp) {
--
1.7.9.5
Jia Liu
2012-05-25 01:25:39 UTC
Permalink
Post by Blue Swirl
Post by Jia Liu
Hi Blue,
Post by Blue Swirl
Post by Jia Liu
add the openrisc exception support.
---
 Makefile.target               |    2 +-
 target-openrisc/excp.c        |   27 +++++++++++++++++++++++++++
 target-openrisc/excp.h        |   28 ++++++++++++++++++++++++++++
 target-openrisc/excp_helper.c |   28 ++++++++++++++++++++++++++++
 target-openrisc/helper.h      |    3 +++
 target-openrisc/translate.c   |   25 ++++++++++++++++---------
 6 files changed, 103 insertions(+), 10 deletions(-)
 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 975c9a8..ed5f0b0 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) += intrp_helper.o mem.o mem_helper.o
+libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o intrp_helper.o mem.o mem_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..fc9391a
--- /dev/null
+++ b/target-openrisc/excp.c
@@ -0,0 +1,27 @@
+/*
+ *  Openrisc exception.
+ *
+ *
+ * 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 raise_exception(CPUOPENRISCState *env, uint32_t excp)
QEMU_NORETURN?
Does it have to return?
No, QEMU_NORETURN just tells the compiler that the function does not
return, because it executes a longjmp() etc. That way the compiler can
optimize the code.
void QEMU_NORETURN cpu_loop_exit(CPUArchState *env1);
Thanks, added.
Post by Blue Swirl
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+{
+    env->exception_index = excp;
+    cpu_loop_exit(env);
+}
I'd just merge this file with excp_helper.c for simplicity, though
it's not incorrect either.
Post by Jia Liu
diff --git a/target-openrisc/excp.h b/target-openrisc/excp.h
new file mode 100644
index 0000000..4c32e46
--- /dev/null
+++ b/target-openrisc/excp.h
@@ -0,0 +1,28 @@
+/*
+ *  Openrisc exception 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 QEMU_OPENRISC_EXCP_H
+#define QEMU_OPENRISC_EXCP_H
+
+#include "cpu.h"
+#include "qemu-common.h"
+
+void 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..0cad14b
--- /dev/null
+++ b/target-openrisc/excp_helper.c
@@ -0,0 +1,28 @@
+/*
+ * OpenRISC exception helper routines
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
Please use the web version instead.
fixed.
Post by Blue Swirl
Post by Jia Liu
+ */
+
+#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 bb394ad..a0fb8c4 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -20,6 +20,9 @@
 #include "def-helper.h"
+/* exception */
+DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)
+
 /* interrupt */
 DEF_HELPER_FLAGS_1(rfe, 0, void, env)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index dd0240c..a1264c9 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -155,6 +155,13 @@ static inline void gen_load_gpr(TCGv t, unsigned int reg)
    }
 }
+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_goto_tb(DisasContext *dc, int n, target_ulong dest)
 {
    TranslationBlock *tb;
@@ -167,7 +174,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
    } else {
        tcg_gen_movi_tl(cpu_pc, dest);
        if (dc->singlestep_enabled) {
-            /* exception here */
+            gen_exception(dc, EXCP_DEBUG);
        }
        tcg_gen_exit_tb(0);
    }
@@ -281,7 +288,7 @@ static void dec_calc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
            if (rb != 0) {
                tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
            } else {
-                /* exception here */
+                gen_exception(dc, EXCP_RANGE);
            }
            break;
@@ -296,7 +303,7 @@ static void dec_calc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
            if (rb != 0) {
                tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
            } else {
-                /* exception here */
+                gen_exception(dc, EXCP_RANGE);
            }
            break;
@@ -1003,14 +1010,14 @@ static void dec_sys(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
    case 0x000:  /*l.sys*/
        /*LOG_DIS("l.sys %d\n", K16);*/
        tcg_gen_movi_tl(cpu_pc, dc->pc);
-        /* exception here */
+        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);
-        /* exception here */
+        gen_exception(dc, EXCP_TRAP);
        break;
    case 0x300:  /*l.csync*/
@@ -1085,7 +1092,7 @@ static void dec_float(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
        if (cpu_R[rb] != 0) {
            tcg_gen_div_i64(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
        } else {
-            /* exception here */
+            gen_exception(dc, EXCP_RANGE);
        }
        break;
@@ -1094,7 +1101,7 @@ static void dec_float(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
        if (cpu_R[rb] != 0) {
            tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
        } else {
-            /* exception here */
+            gen_exception(dc, EXCP_RANGE);
        }
        break;
@@ -1294,7 +1301,7 @@ static void check_breakpoint(CPUOPENRISCState *env, DisasContext *dc)
        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
            if (bp->pc == dc->pc) {
                tcg_gen_movi_tl(cpu_pc, dc->pc);
-                /* exception here */
+                gen_exception(dc, EXCP_DEBUG);
                dc->is_jmp = DISAS_UPDATE;
            }
        }
@@ -1403,7 +1410,7 @@ static inline void gen_intermediate_code_internal(CPUOPENRISCState *env,
        if (dc->is_jmp == DISAS_NEXT) {
            tcg_gen_movi_tl(cpu_pc, dc->pc);
        }
-        /* exception here*/
+        gen_exception(dc, EXCP_DEBUG);
    } else {
        switch (dc->is_jmp) {
--
1.7.9.5
Jia Liu
2012-05-17 08:35:50 UTC
Permalink
add the openrisc float instruction helpers.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 2 +-
target-openrisc/fpu_helper.c | 93 ++++++++++++++++++++++++++++++++++++++++++
target-openrisc/helper.h | 6 +++
target-openrisc/translate.c | 8 ++--
4 files changed, 104 insertions(+), 5 deletions(-)
create mode 100644 target-openrisc/fpu_helper.c

diff --git a/Makefile.target b/Makefile.target
index 9bebdb3..8a7b743 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 intrp_helper.o mem.o mem_helper.o
+libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o fpu_helper.o int_helper.o intrp_helper.o mem.o mem_helper.o

libobj-y += disas.o
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-openrisc/fpu_helper.c b/target-openrisc/fpu_helper.c
new file mode 100644
index 0000000..be2bfb5
--- /dev/null
+++ b/target-openrisc/fpu_helper.c
@@ -0,0 +1,93 @@
+/*
+ * 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 Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "excp.h"
+
+static inline int ieee_ex_to_openrisc(int xcpt)
+{
+ int ret = 0;
+
+ if (xcpt) {
+ if (xcpt & float_flag_invalid) {
+ ret &= FPCSR_FPEE;
+ }
+ if (xcpt & float_flag_overflow) {
+ ret |= FPCSR_OVF;
+ }
+ if (xcpt & float_flag_underflow) {
+ ret |= FPCSR_UNF;
+ }
+ if (xcpt & float_flag_divbyzero) {
+ ret |= FPCSR_DZF;
+ }
+ }
+
+ return ret;
+}
+
+static inline void update_fpcsr(CPUOPENRISCState *env)
+{
+ int tmp = ieee_ex_to_openrisc(get_float_exception_flags(&env->fp_status));
+ SET_FP_CAUSE(env->fpcsr, tmp);
+ if (GET_FP_ENABLE(env->fpcsr) & tmp) {
+ helper_exception(env, EXCP_FPE);
+ } else {
+ UPDATE_FP_FLAGS(env->fpcsr, tmp);
+ }
+}
+
+target_ulong HELPER(itofd)(CPUOPENRISCState *env, target_ulong 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;
+}
+
+target_ulong HELPER(itofs)(CPUOPENRISCState *env, target_ulong val)
+{
+ target_ulong itofs;
+ set_float_exception_flags(0, &env->fp_status);
+ itofs = int32_to_float32(val, &env->fp_status);
+ update_fpcsr(env);
+ return itofs;
+}
+
+target_ulong HELPER(ftoid)(CPUOPENRISCState *env, target_ulong val)
+{
+ target_ulong ftoid;
+ set_float_exception_flags(0, &env->fp_status);
+ ftoid = float32_to_int64(val, &env->fp_status);
+ update_fpcsr(env);
+ return ftoid;
+}
+
+target_ulong HELPER(ftois)(CPUOPENRISCState *env, target_ulong val)
+{
+ target_ulong ftois;
+ set_float_exception_flags(0, &env->fp_status);
+ ftois = float32_to_int32(val, &env->fp_status);
+ update_fpcsr(env);
+ return ftois;
+}
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index f5ed117..b9b1d67 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -23,6 +23,12 @@
/* exception */
DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)

+/* float */
+DEF_HELPER_FLAGS_2(itofd, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(itofs, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(ftoid, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(ftois, 0, tl, env, tl)
+
/* int */
DEF_HELPER_FLAGS_1(ff1, 0, tl, tl)
DEF_HELPER_FLAGS_1(fl1, 0, tl, tl)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index dffc8a7..7d942b5 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1107,22 +1107,22 @@ static void dec_float(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)

case 0x14: /*lf.itof.d*/
LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
- /* itof.d need a helper here */
+ 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);
- /* itof.s need a helper here */
+ 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);
- /* ftoi.d need a helper here */
+ 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);
- /* ftoi.s need a helper here */
+ gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]);
break;

case 0x16: /*lf.rem.d*/
--
1.7.9.5
Blue Swirl
2012-05-19 08:29:49 UTC
Permalink
Post by Jia Liu
add the openrisc float instruction helpers.
---
 Makefile.target              |    2 +-
 target-openrisc/fpu_helper.c |   93 ++++++++++++++++++++++++++++++++++++++++++
 target-openrisc/helper.h     |    6 +++
 target-openrisc/translate.c  |    8 ++--
 4 files changed, 104 insertions(+), 5 deletions(-)
 create mode 100644 target-openrisc/fpu_helper.c
diff --git a/Makefile.target b/Makefile.target
index 9bebdb3..8a7b743 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 intrp_helper.o mem.o mem_helper.o
+libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o fpu_helper.o int_helper.o intrp_helper.o mem.o mem_helper.o
 libobj-y += disas.o
 libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-openrisc/fpu_helper.c b/target-openrisc/fpu_helper.c
new file mode 100644
index 0000000..be2bfb5
--- /dev/null
+++ b/target-openrisc/fpu_helper.c
@@ -0,0 +1,93 @@
+/*
+ * OpenRISC float helper routines
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "excp.h"
+
+static inline int ieee_ex_to_openrisc(int xcpt)
+{
+    int ret = 0;
+
+    if (xcpt) {
+        if (xcpt & float_flag_invalid) {
+            ret &= FPCSR_FPEE;
+        }
+        if (xcpt & float_flag_overflow) {
+            ret |= FPCSR_OVF;
+        }
+        if (xcpt & float_flag_underflow) {
+            ret |= FPCSR_UNF;
+        }
+        if (xcpt & float_flag_divbyzero) {
+            ret |= FPCSR_DZF;
+        }
+    }
+
+    return ret;
+}
+
+static inline void update_fpcsr(CPUOPENRISCState *env)
+{
+    int tmp = ieee_ex_to_openrisc(get_float_exception_flags(&env->fp_status));
A blank line after variable declarations would be nice.
Post by Jia Liu
+    SET_FP_CAUSE(env->fpcsr, tmp);
+    if (GET_FP_ENABLE(env->fpcsr) & tmp) {
+        helper_exception(env, EXCP_FPE);
+    } else {
+      UPDATE_FP_FLAGS(env->fpcsr, tmp);
+    }
+}
+
+target_ulong HELPER(itofd)(CPUOPENRISCState *env, target_ulong val)
This will truncate the 64 bit value to 32 bits if that is the size of
target_ulong, I don't think that is correct.
Post by Jia Liu
+{
+    uint64_t itofd;
+    set_float_exception_flags(0, &env->fp_status);
+    itofd = int32_to_float64(val, &env->fp_status);
+    update_fpcsr(env);
+    return itofd;
+}
+
+target_ulong HELPER(itofs)(CPUOPENRISCState *env, target_ulong val)
+{
+    target_ulong itofs;
+    set_float_exception_flags(0, &env->fp_status);
+    itofs = int32_to_float32(val, &env->fp_status);
+    update_fpcsr(env);
+    return itofs;
+}
+
+target_ulong HELPER(ftoid)(CPUOPENRISCState *env, target_ulong val)
Ditto.
Post by Jia Liu
+{
+    target_ulong ftoid;
+    set_float_exception_flags(0, &env->fp_status);
+    ftoid = float32_to_int64(val, &env->fp_status);
+    update_fpcsr(env);
+    return ftoid;
+}
+
+target_ulong HELPER(ftois)(CPUOPENRISCState *env, target_ulong val)
+{
+    target_ulong ftois;
+    set_float_exception_flags(0, &env->fp_status);
+    ftois = float32_to_int32(val, &env->fp_status);
+    update_fpcsr(env);
+    return ftois;
+}
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index f5ed117..b9b1d67 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -23,6 +23,12 @@
 /* exception */
 DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)
+/* float */
+DEF_HELPER_FLAGS_2(itofd, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(itofs, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(ftoid, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(ftois, 0, tl, env, tl)
+
 /* int */
 DEF_HELPER_FLAGS_1(ff1, 0, tl, tl)
 DEF_HELPER_FLAGS_1(fl1, 0, tl, tl)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index dffc8a7..7d942b5 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1107,22 +1107,22 @@ static void dec_float(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
    case 0x14:    /*lf.itof.d*/
        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
-        /* itof.d need a helper here */
+        gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]);
You probably need to save PC etc. if this instruction can cause
exceptions, otherwise return PC will not be correct and guest
exception handler will return to start of the block.
Post by Jia Liu
        break;
    case 0x04:    /*lf.itof.s*/
        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
-        /* itof.s need a helper here */
+        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);
-        /* ftoi.d need a helper here */
+        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);
-        /* ftoi.s need a helper here */
+        gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]);
        break;
    case 0x16:    /*lf.rem.d*/
--
1.7.9.5
Jia Liu
2012-05-23 07:21:23 UTC
Permalink
Hi Blue,
Post by Blue Swirl
Post by Jia Liu
add the openrisc float instruction helpers.
---
 Makefile.target              |    2 +-
 target-openrisc/fpu_helper.c |   93 ++++++++++++++++++++++++++++++++++++++++++
 target-openrisc/helper.h     |    6 +++
 target-openrisc/translate.c  |    8 ++--
 4 files changed, 104 insertions(+), 5 deletions(-)
 create mode 100644 target-openrisc/fpu_helper.c
diff --git a/Makefile.target b/Makefile.target
index 9bebdb3..8a7b743 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 intrp_helper.o mem.o mem_helper.o
+libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o fpu_helper.o int_helper.o intrp_helper.o mem.o mem_helper.o
 libobj-y += disas.o
 libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-openrisc/fpu_helper.c b/target-openrisc/fpu_helper.c
new file mode 100644
index 0000000..be2bfb5
--- /dev/null
+++ b/target-openrisc/fpu_helper.c
@@ -0,0 +1,93 @@
+/*
+ * OpenRISC float helper routines
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "excp.h"
+
+static inline int ieee_ex_to_openrisc(int xcpt)
+{
+    int ret = 0;
+
+    if (xcpt) {
+        if (xcpt & float_flag_invalid) {
+            ret &= FPCSR_FPEE;
+        }
+        if (xcpt & float_flag_overflow) {
+            ret |= FPCSR_OVF;
+        }
+        if (xcpt & float_flag_underflow) {
+            ret |= FPCSR_UNF;
+        }
+        if (xcpt & float_flag_divbyzero) {
+            ret |= FPCSR_DZF;
+        }
+    }
+
+    return ret;
+}
+
+static inline void update_fpcsr(CPUOPENRISCState *env)
+{
+    int tmp = ieee_ex_to_openrisc(get_float_exception_flags(&env->fp_status));
A blank line after variable declarations would be nice.
Post by Jia Liu
+    SET_FP_CAUSE(env->fpcsr, tmp);
+    if (GET_FP_ENABLE(env->fpcsr) & tmp) {
+        helper_exception(env, EXCP_FPE);
+    } else {
+      UPDATE_FP_FLAGS(env->fpcsr, tmp);
+    }
+}
+
+target_ulong HELPER(itofd)(CPUOPENRISCState *env, target_ulong val)
This will truncate the 64 bit value to 32 bits if that is the size of
target_ulong, I don't think that is correct.
Post by Jia Liu
+{
+    uint64_t itofd;
+    set_float_exception_flags(0, &env->fp_status);
+    itofd = int32_to_float64(val, &env->fp_status);
+    update_fpcsr(env);
+    return itofd;
+}
+
+target_ulong HELPER(itofs)(CPUOPENRISCState *env, target_ulong val)
+{
+    target_ulong itofs;
+    set_float_exception_flags(0, &env->fp_status);
+    itofs = int32_to_float32(val, &env->fp_status);
+    update_fpcsr(env);
+    return itofs;
+}
+
+target_ulong HELPER(ftoid)(CPUOPENRISCState *env, target_ulong val)
Ditto.
fixed.
Post by Blue Swirl
Post by Jia Liu
+{
+    target_ulong ftoid;
+    set_float_exception_flags(0, &env->fp_status);
+    ftoid = float32_to_int64(val, &env->fp_status);
+    update_fpcsr(env);
+    return ftoid;
+}
+
+target_ulong HELPER(ftois)(CPUOPENRISCState *env, target_ulong val)
+{
+    target_ulong ftois;
+    set_float_exception_flags(0, &env->fp_status);
+    ftois = float32_to_int32(val, &env->fp_status);
+    update_fpcsr(env);
+    return ftois;
+}
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index f5ed117..b9b1d67 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -23,6 +23,12 @@
 /* exception */
 DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)
+/* float */
+DEF_HELPER_FLAGS_2(itofd, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(itofs, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(ftoid, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(ftois, 0, tl, env, tl)
+
 /* int */
 DEF_HELPER_FLAGS_1(ff1, 0, tl, tl)
 DEF_HELPER_FLAGS_1(fl1, 0, tl, tl)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index dffc8a7..7d942b5 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1107,22 +1107,22 @@ static void dec_float(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
    case 0x14:    /*lf.itof.d*/
        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
-        /* itof.d need a helper here */
+        gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]);
You probably need to save PC etc. if this instruction can cause
exceptions, otherwise return PC will not be correct and guest
exception handler will return to start of the block.
there is already a exception handle in helpers.
Post by Blue Swirl
Post by Jia Liu
        break;
    case 0x04:    /*lf.itof.s*/
        LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
-        /* itof.s need a helper here */
+        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);
-        /* ftoi.d need a helper here */
+        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);
-        /* ftoi.s need a helper here */
+        gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]);
        break;
    case 0x16:    /*lf.rem.d*/
--
1.7.9.5
Regards,
Jia.
Jia Liu
2012-05-17 08:35:54 UTC
Permalink
add the openrisc system instruction helpers.

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

diff --git a/Makefile.target b/Makefile.target
index 433dd3c..ca1f45a 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 fpu_helper.o int_helper.o intrp_helper.o mem.o mem_helper.o
+libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o fpu_helper.o int_helper.o intrp_helper.o mem.o mem_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 b9b1d67..b515f92 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -39,4 +39,8 @@ DEF_HELPER_FLAGS_3(sub, 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..59e9f20
--- /dev/null
+++ b/target-openrisc/sys_helper.c
@@ -0,0 +1,227 @@
+/*
+ * 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 Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#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 7d942b5..7617a34 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -704,7 +704,7 @@ static void dec_misc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
TCGv_i32 ti = tcg_const_i32(I16);
TCGv td = tcg_const_tl(rd);
TCGv ta = tcg_const_tl(ra);
- /* mfspr need a helper here */
+ gen_helper_mfspr(cpu_env, td, ta, ti);
tcg_temp_free_i32(ti);
tcg_temp_free(td);
tcg_temp_free(ta);
@@ -717,7 +717,7 @@ static void dec_misc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
TCGv_i32 ti = tcg_const_i32(tmp);
TCGv ta = tcg_const_tl(ra);
TCGv tb = tcg_const_tl(rb);
- /* mtspr need a helper here */
+ gen_helper_mtspr(cpu_env, ta, tb, ti);
tcg_temp_free_i32(ti);
tcg_temp_free(ta);
tcg_temp_free(tb);
--
1.7.9.5
Jia Liu
2012-05-17 08:35:55 UTC
Permalink
add the qemu 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..fb86f22 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
Jia Liu
2012-05-17 08:35:56 UTC
Permalink
add the openrisc syscall, signal and termbits for linux-user.

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..9c51893
--- /dev/null
+++ b/linux-user/openrisc/syscall.h
@@ -0,0 +1,24 @@
+struct target_pt_regs {
+ union {
+ struct {
+ /* Named registers */
+ long sr; /* Stored in place of r0 */
+ long sp; /* r1 */
+ };
+ struct {
+ /* Old style */
+ long offset[2];
+ long gprs[30];
+ };
+ struct {
+ /* New style */
+ long gpr[32];
+ };
+ };
+ long pc;
+ long orig_gpr11; /* For restarting system calls */
+ long syscallno; /* Syscall number (used by strace) */
+ long 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..6980d1e
--- /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..a65149e
--- /dev/null
+++ b/linux-user/openrisc/termbits.h
@@ -0,0 +1,294 @@
+typedef unsigned char cc_t;
+typedef unsigned int speed_t;
+typedef unsigned int tcflag_t;
+
+#define TARGET_NCCS 19
+struct target_termios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[TARGET_NCCS]; /* control characters */
+};
+
+struct target_termios2 {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[TARGET_NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
+struct target_termios3 {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[TARGET_NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t 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
Blue Swirl
2012-05-19 07:17:55 UTC
Permalink
Post by Jia Liu
add the openrisc syscall, signal and termbits for linux-user.
---
 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..9c51893
--- /dev/null
+++ b/linux-user/openrisc/syscall.h
@@ -0,0 +1,24 @@
+struct target_pt_regs {
+    union {
+        struct {
+            /* Named registers */
+            long  sr;   /* Stored in place of r0 */
+             long  sp;   /* r1 */
'long' is not correct, it could be 64 bits or 32. Please use target_ulong.
Post by Jia Liu
+         };
+         struct {
+             /* Old style */
+             long offset[2];
+             long gprs[30];
+         };
+         struct {
+             /* New style */
+             long gpr[32];
+         };
+     };
+    long  pc;
+    long  orig_gpr11;   /* For restarting system calls */
+    long  syscallno;    /* Syscall number (used by strace) */
+    long 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..6980d1e
--- /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..a65149e
--- /dev/null
+++ b/linux-user/openrisc/termbits.h
@@ -0,0 +1,294 @@
+typedef unsigned char   cc_t;
+typedef unsigned int    speed_t;
+typedef unsigned int    tcflag_t;
These could conflict with system definitions, please use for example
target_ prefix. Also, suffix _t is reserved to system use, as
explained in HACKING.
Post by Jia Liu
+
+#define TARGET_NCCS 19
+struct target_termios {
+    tcflag_t c_iflag;               /* input mode flags */
+    tcflag_t c_oflag;               /* output mode flags */
+    tcflag_t c_cflag;               /* control mode flags */
+    tcflag_t c_lflag;               /* local mode flags */
+    cc_t c_line;                    /* line discipline */
+    cc_t c_cc[TARGET_NCCS];         /* control characters */
+};
+
+struct target_termios2 {
+    tcflag_t c_iflag;               /* input mode flags */
+    tcflag_t c_oflag;               /* output mode flags */
+    tcflag_t c_cflag;               /* control mode flags */
+    tcflag_t c_lflag;               /* local mode flags */
+    cc_t c_line;                    /* line discipline */
+    cc_t c_cc[TARGET_NCCS];         /* control characters */
+    speed_t c_ispeed;               /* input speed */
+    speed_t c_ospeed;               /* output speed */
+};
+
+struct target_termios3 {
+    tcflag_t c_iflag;               /* input mode flags */
+    tcflag_t c_oflag;               /* output mode flags */
+    tcflag_t c_cflag;               /* control mode flags */
+    tcflag_t c_lflag;               /* local mode flags */
+    cc_t c_line;                    /* line discipline */
+    cc_t c_cc[TARGET_NCCS];                /* control characters */
+    speed_t c_ispeed;               /* input speed */
+    speed_t 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-19 08:57:19 UTC
Permalink
Hi Blue,

Thank you very much for helpful comment.
Post by Blue Swirl
Post by Jia Liu
add the openrisc syscall, signal and termbits for linux-user.
---
 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..9c51893
--- /dev/null
+++ b/linux-user/openrisc/syscall.h
@@ -0,0 +1,24 @@
+struct target_pt_regs {
+    union {
+        struct {
+            /* Named registers */
+            long  sr;   /* Stored in place of r0 */
+             long  sp;   /* r1 */
'long' is not correct, it could be 64 bits or 32. Please use target_ulong.
Thanks, I'll fix it.
Post by Blue Swirl
Post by Jia Liu
+         };
+         struct {
+             /* Old style */
+             long offset[2];
+             long gprs[30];
+         };
+         struct {
+             /* New style */
+             long gpr[32];
+         };
+     };
+    long  pc;
+    long  orig_gpr11;   /* For restarting system calls */
+    long  syscallno;    /* Syscall number (used by strace) */
+    long 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..6980d1e
--- /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..a65149e
--- /dev/null
+++ b/linux-user/openrisc/termbits.h
@@ -0,0 +1,294 @@
+typedef unsigned char   cc_t;
+typedef unsigned int    speed_t;
+typedef unsigned int    tcflag_t;
These could conflict with system definitions, please use for example
target_ prefix. Also, suffix _t is reserved to system use, as
explained in HACKING.
I'll read HACKING and fix this.
Post by Blue Swirl
Post by Jia Liu
+
+#define TARGET_NCCS 19
+struct target_termios {
+    tcflag_t c_iflag;               /* input mode flags */
+    tcflag_t c_oflag;               /* output mode flags */
+    tcflag_t c_cflag;               /* control mode flags */
+    tcflag_t c_lflag;               /* local mode flags */
+    cc_t c_line;                    /* line discipline */
+    cc_t c_cc[TARGET_NCCS];         /* control characters */
+};
+
+struct target_termios2 {
+    tcflag_t c_iflag;               /* input mode flags */
+    tcflag_t c_oflag;               /* output mode flags */
+    tcflag_t c_cflag;               /* control mode flags */
+    tcflag_t c_lflag;               /* local mode flags */
+    cc_t c_line;                    /* line discipline */
+    cc_t c_cc[TARGET_NCCS];         /* control characters */
+    speed_t c_ispeed;               /* input speed */
+    speed_t c_ospeed;               /* output speed */
+};
+
+struct target_termios3 {
+    tcflag_t c_iflag;               /* input mode flags */
+    tcflag_t c_oflag;               /* output mode flags */
+    tcflag_t c_cflag;               /* control mode flags */
+    tcflag_t c_lflag;               /* local mode flags */
+    cc_t c_line;                    /* line discipline */
+    cc_t c_cc[TARGET_NCCS];                /* control characters */
+    speed_t c_ispeed;               /* input speed */
+    speed_t 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
Regards,
Jia.
Jia Liu
2012-05-17 08:35:57 UTC
Permalink
add the 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 +++++-
7 files changed, 411 insertions(+), 4 deletions(-)
create mode 100644 default-configs/or32-linux-user.mak

diff --git a/configure b/configure
index 63e2372..d0979d2 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..5215ccd 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..68eee14 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..df35b04 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
--
1.7.9.5
Jia Liu
2012-05-17 08:35:58 UTC
Permalink
add the 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-17 08:35:47 UTC
Permalink
add the openrisc interrupt support.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 2 +-
target-openrisc/helper.c | 42 +++++++++++++++++++++++++++++++
target-openrisc/helper.h | 3 +++
target-openrisc/intrp_helper.c | 53 ++++++++++++++++++++++++++++++++++++++++
target-openrisc/translate.c | 2 +-
5 files changed, 100 insertions(+), 2 deletions(-)
create mode 100644 target-openrisc/intrp_helper.c

diff --git a/Makefile.target b/Makefile.target
index 79c75f6..975c9a8 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) += mem.o mem_helper.o
+libobj-$(TARGET_OPENRISC) += intrp_helper.o mem.o mem_helper.o

libobj-y += disas.o
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-openrisc/helper.c b/target-openrisc/helper.c
index dcb61c9..3aee996 100644
--- a/target-openrisc/helper.c
+++ b/target-openrisc/helper.c
@@ -64,4 +64,46 @@ CPUOPENRISCState *cpu_openrisc_init(const char *cpu_model)

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 * 0x100;
+ } else {
+ cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
+ }
+#endif
+
+ env->exception_index = -1;
}
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index 103d9b4..bb394ad 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -20,4 +20,7 @@

#include "def-helper.h"

+/* interrupt */
+DEF_HELPER_FLAGS_1(rfe, 0, void, env)
+
#include "def-helper.h"
diff --git a/target-openrisc/intrp_helper.c b/target-openrisc/intrp_helper.c
new file mode 100644
index 0000000..c617068
--- /dev/null
+++ b/target-openrisc/intrp_helper.c
@@ -0,0 +1,53 @@
+/*
+ * 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 Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#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;
+}
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 4828ae6..dd0240c 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -569,7 +569,7 @@ static void dec_misc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
case 0x09: /*l.rfe*/
LOG_DIS("l.rfe\n");
{
- /* rfe need a helper here */
+ gen_helper_rfe(cpu_env);
dc->is_jmp = DISAS_UPDATE;
}
break;
--
1.7.9.5
Blue Swirl
2012-05-19 07:30:27 UTC
Permalink
Post by Jia Liu
add the openrisc interrupt support.
---
 Makefile.target                |    2 +-
 target-openrisc/helper.c       |   42 +++++++++++++++++++++++++++++++
 target-openrisc/helper.h       |    3 +++
 target-openrisc/intrp_helper.c |   53 ++++++++++++++++++++++++++++++++++++++++
 target-openrisc/translate.c    |    2 +-
 5 files changed, 100 insertions(+), 2 deletions(-)
 create mode 100644 target-openrisc/intrp_helper.c
diff --git a/Makefile.target b/Makefile.target
index 79c75f6..975c9a8 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) += mem.o mem_helper.o
+libobj-$(TARGET_OPENRISC) += intrp_helper.o mem.o mem_helper.o
 libobj-y += disas.o
 libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-openrisc/helper.c b/target-openrisc/helper.c
index dcb61c9..3aee996 100644
--- a/target-openrisc/helper.c
+++ b/target-openrisc/helper.c
@@ -64,4 +64,46 @@ CPUOPENRISCState *cpu_openrisc_init(const char *cpu_model)
 void do_interrupt(CPUOPENRISCState *env)
I'd put the function to intrp_helper.c too, or if you prefer, intrp.c
to match excp.c.
Post by Jia Liu
 {
+#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 * 0x100;
<< 8
Post by Jia Liu
+    } else {
+        cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
+    }
+#endif
+
+    env->exception_index = -1;
 }
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index 103d9b4..bb394ad 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -20,4 +20,7 @@
 #include "def-helper.h"
+/* interrupt */
+DEF_HELPER_FLAGS_1(rfe, 0, void, env)
+
 #include "def-helper.h"
diff --git a/target-openrisc/intrp_helper.c b/target-openrisc/intrp_helper.c
new file mode 100644
index 0000000..c617068
--- /dev/null
+++ b/target-openrisc/intrp_helper.c
@@ -0,0 +1,53 @@
+/*
+ * OpenRISC interrupt helper routines
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#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));
If SR_SM is like supervisor mode flag, changes in it shouldn't cause
TLB flushes if you put it also to TB flags. The same is also true to
other flags but MMU enable/disable flags are commonly handled like
this.
Post by Jia Liu
+#endif
+    env->pc = env->epcr;
+    env->npc = env->epcr;
+ 4?
Post by Jia Liu
+    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;
+}
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 4828ae6..dd0240c 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -569,7 +569,7 @@ static void dec_misc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
    case 0x09:    /*l.rfe*/
        LOG_DIS("l.rfe\n");
        {
-            /* rfe need a helper here */
+            gen_helper_rfe(cpu_env);
            dc->is_jmp = DISAS_UPDATE;
        }
        break;
--
1.7.9.5
Jia Liu
2012-05-23 07:06:50 UTC
Permalink
Hi Blue,
Post by Blue Swirl
Post by Jia Liu
add the openrisc interrupt support.
---
 Makefile.target                |    2 +-
 target-openrisc/helper.c       |   42 +++++++++++++++++++++++++++++++
 target-openrisc/helper.h       |    3 +++
 target-openrisc/intrp_helper.c |   53 ++++++++++++++++++++++++++++++++++++++++
 target-openrisc/translate.c    |    2 +-
 5 files changed, 100 insertions(+), 2 deletions(-)
 create mode 100644 target-openrisc/intrp_helper.c
diff --git a/Makefile.target b/Makefile.target
index 79c75f6..975c9a8 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) += mem.o mem_helper.o
+libobj-$(TARGET_OPENRISC) += intrp_helper.o mem.o mem_helper.o
 libobj-y += disas.o
 libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-openrisc/helper.c b/target-openrisc/helper.c
index dcb61c9..3aee996 100644
--- a/target-openrisc/helper.c
+++ b/target-openrisc/helper.c
@@ -64,4 +64,46 @@ CPUOPENRISCState *cpu_openrisc_init(const char *cpu_model)
 void do_interrupt(CPUOPENRISCState *env)
I'd put the function to intrp_helper.c too, or if you prefer, intrp.c
to match excp.c.
OK.
Post by Blue Swirl
Post by Jia Liu
 {
+#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 * 0x100;
<< 8
all right, fixed.
Post by Blue Swirl
Post by Jia Liu
+    } else {
+        cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
+    }
+#endif
+
+    env->exception_index = -1;
 }
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index 103d9b4..bb394ad 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -20,4 +20,7 @@
 #include "def-helper.h"
+/* interrupt */
+DEF_HELPER_FLAGS_1(rfe, 0, void, env)
+
 #include "def-helper.h"
diff --git a/target-openrisc/intrp_helper.c b/target-openrisc/intrp_helper.c
new file mode 100644
index 0000000..c617068
--- /dev/null
+++ b/target-openrisc/intrp_helper.c
@@ -0,0 +1,53 @@
+/*
+ * OpenRISC interrupt helper routines
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#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));
If SR_SM is like supervisor mode flag, changes in it shouldn't cause
TLB flushes if you put it also to TB flags. The same is also true to
other flags but MMU enable/disable flags are commonly handled like
this.
SR_SM changed when we jump back to user-model from supervisor-mode, we
need flush TLB at that time.
Post by Blue Swirl
Post by Jia Liu
+#endif
+    env->pc = env->epcr;
+    env->npc = env->epcr;
+ 4?
npc and pc be calced separately, so can not +4.
Post by Blue Swirl
Post by Jia Liu
+    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;
+}
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 4828ae6..dd0240c 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -569,7 +569,7 @@ static void dec_misc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
    case 0x09:    /*l.rfe*/
        LOG_DIS("l.rfe\n");
        {
-            /* rfe need a helper here */
+            gen_helper_rfe(cpu_env);
            dc->is_jmp = DISAS_UPDATE;
        }
        break;
--
1.7.9.5
Regards,
Jia.
Jia Liu
2012-05-17 08:35:49 UTC
Permalink
add the openrisc int instruction helpers.

Signed-off-by: Jia Liu <***@gmail.com>
---
Makefile.target | 2 +-
target-openrisc/helper.h | 7 +++
target-openrisc/int_helper.c | 126 ++++++++++++++++++++++++++++++++++++++++++
target-openrisc/translate.c | 14 ++---
4 files changed, 141 insertions(+), 8 deletions(-)
create mode 100644 target-openrisc/int_helper.c

diff --git a/Makefile.target b/Makefile.target
index ed5f0b0..9bebdb3 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 intrp_helper.o mem.o mem_helper.o
+libobj-$(TARGET_OPENRISC) += excp.o excp_helper.o int_helper.o intrp_helper.o mem.o mem_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 a0fb8c4..f5ed117 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -23,6 +23,13 @@
/* 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)
+
/* 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..540b941
--- /dev/null
+++ b/target-openrisc/int_helper.c
@@ -0,0 +1,126 @@
+/*
+ * 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 Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#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;
+}
+
+/* l.add, l.addc, l.addi, l.addic, l.sub. for overflow exception. */
+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;
+}
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index a1264c9..dffc8a7 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -203,7 +203,7 @@ static void dec_calc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
switch (op1) {
case 0x00: /*l.add*/
LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb);
- /* Aha, we do need a helper here for add */
+ gen_helper_add(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
break;
default:
break;
@@ -214,7 +214,7 @@ static void dec_calc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
switch (op1) {
case 0x00:
LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
- /* Aha, we do need a helper here for addc */
+ gen_helper_addc(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
break;
default:
break;
@@ -225,7 +225,7 @@ static void dec_calc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
switch (op1) {
case 0x00:
LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
- /* Aha, we do need a helper here for sub */
+ gen_helper_sub(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
break;
default:
break;
@@ -352,11 +352,11 @@ static void dec_calc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
switch (op1) {
case 0x00: /*l.ff1*/
LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
- /* ff1 need a helper here */
+ 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);
- /* fl1 need a helper here */
+ gen_helper_fl1(cpu_R[rd], cpu_R[ra]);
break;
default:
break;
@@ -659,7 +659,7 @@ static void dec_misc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
{
TCGv t0 = tcg_const_tl(sign_extend(I16, 16));
- /* Aha, we do need a helper here for addi */
+ gen_helper_add(cpu_R[rd], cpu_env, cpu_R[ra], t0);
tcg_temp_free(t0);
}
break;
@@ -668,7 +668,7 @@ static void dec_misc(DisasContext *dc, CPUOPENRISCState *env, uint32_t insn)
LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16);
{
TCGv t0 = tcg_const_tl(sign_extend(I16, 16));
- /* Aha, we do need a helper here for addic */
+ gen_helper_addc(cpu_R[rd], cpu_env, cpu_R[ra], t0);
tcg_temp_free(t0);
}
break;
--
1.7.9.5
Jia Liu
2012-05-17 08:35:51 UTC
Permalink
add the openrisc programmable interrupt controller support.

Signed-off-by: Jia Liu <***@gmail.com>
---
cpu-exec.c | 17 +++++++++++++++++
hw/openrisc_pic.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+)

diff --git a/cpu-exec.c b/cpu-exec.c
index ba10db1..845b2ae 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -375,6 +375,23 @@ 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 ((interrupt_request & CPU_INTERRUPT_TIMER)
+ && (env->sr & SR_TEE)) {
+ idx = EXCP_TICK;
+ }
+ 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/hw/openrisc_pic.c b/hw/openrisc_pic.c
index 0abdd50..52e48ec 100644
--- a/hw/openrisc_pic.c
+++ b/hw/openrisc_pic.c
@@ -29,3 +29,51 @@ 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;
+}
--
1.7.9.5
Blue Swirl
2012-05-19 08:33:39 UTC
Permalink
Post by Jia Liu
add the openrisc programmable interrupt controller support.
---
 cpu-exec.c        |   17 +++++++++++++++++
 hw/openrisc_pic.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)
diff --git a/cpu-exec.c b/cpu-exec.c
index ba10db1..845b2ae 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -375,6 +375,23 @@ 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 ((interrupt_request & CPU_INTERRUPT_TIMER)
+                            && (env->sr & SR_TEE)) {
+                            idx = EXCP_TICK;
+                        }
+                        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/hw/openrisc_pic.c b/hw/openrisc_pic.c
index 0abdd50..52e48ec 100644
--- a/hw/openrisc_pic.c
+++ b/hw/openrisc_pic.c
@@ -29,3 +29,51 @@ 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);
The CPU could have one IRQ line input (set up at board or CPU level),
which the device toggles. That way the PIC does not need to be coupled
so tightly with the CPU (no need to access CPUState).
Post by Jia Liu
+        } 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)
+{
+
Jia Liu
2012-05-17 08:35:52 UTC
Permalink
add the openrisc timer support.

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

diff --git a/Makefile.target b/Makefile.target
index 8a7b743..6b1d2d0 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -391,6 +391,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/hw/openrisc_timer.c b/hw/openrisc_timer.c
new file mode 100644
index 0000000..987149f
--- /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;
+}
--
1.7.9.5
Jia Liu
2012-05-17 08:35:53 UTC
Permalink
add a simulation board for openrisc.

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

diff --git a/Makefile.target b/Makefile.target
index 6b1d2d0..433dd3c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -391,6 +391,7 @@ obj-xtensa-y += core-dc233c.o
obj-xtensa-y += core-fsf.o

obj-openrisc-y += openrisc_pic.o
+obj-openrisc-y += openrisc_sim.o
obj-openrisc-y += openrisc_timer.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..869a02e
--- /dev/null
+++ b/hw/openrisc_sim.c
@@ -0,0 +1,140 @@
+/*
+ * 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 Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+
+#include "hw.h"
+#include "fdc.h"
+#include "net.h"
+#include "openrisc_cpudev.h"
+#include "boards.h"
+#include "pci.h"
+#include "elf.h"
+#include "smbus.h"
+#include "memory.h"
+#include "pc.h"
+#include "pci.h"
+#include "sysbus.h"
+#include "flash.h"
+#include "loader.h"
+#include "exec-memory.h"
+#include "sysemu.h"
+#include "isa.h"
+#include "mc146818rtc.h"
+#include "blockdev.h"
+#include "qemu-log.h"
+
+#define KERNEL_LOAD_ADDR 0x100
+
+static uint64_t translate_phys_addr(void *env, uint64_t addr)
+{
+ return cpu_get_phys_page_debug(env, addr);
+}
+
+static void main_cpu_reset(void *opaque)
+{
+ CPUOPENRISCState *env = opaque;
+ openrisc_reset(env);
+}
+
+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);
+ int kernel_size;
+ uint64_t elf_entry;
+ target_phys_addr_t entry;
+ 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) {
+ kernel_size = load_elf(kernel_filename, translate_phys_addr, env,
+ &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
+ entry = elf_entry;
+ if (kernel_size < 0) {
+ kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+ }
+ if (kernel_size < 0) {
+ kernel_size = load_image_targphys(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",
+ kernel_filename);
+ exit(1);
+ }
+
+ if (kernel_size > 0) {
+ env->pc = elf_entry;
+ }
+ } else {
+ entry = 0;
+ }
+
+ 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
Blue Swirl
2012-05-19 07:51:16 UTC
Permalink
Post by Jia Liu
add a simulation board for openrisc.
---
 Makefile.target   |    1 +
 hw/openrisc_sim.c |  140 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 141 insertions(+)
 create mode 100644 hw/openrisc_sim.c
diff --git a/Makefile.target b/Makefile.target
index 6b1d2d0..433dd3c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -391,6 +391,7 @@ obj-xtensa-y += core-dc233c.o
 obj-xtensa-y += core-fsf.o
 obj-openrisc-y += openrisc_pic.o
+obj-openrisc-y += openrisc_sim.o
 obj-openrisc-y += openrisc_timer.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..869a02e
--- /dev/null
+++ b/hw/openrisc_sim.c
@@ -0,0 +1,140 @@
+/*
+ * Openrisc simulator for use as an ISS.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "hw.h"
+#include "fdc.h"
+#include "net.h"
+#include "openrisc_cpudev.h"
+#include "boards.h"
+#include "pci.h"
+#include "elf.h"
+#include "smbus.h"
+#include "memory.h"
+#include "pc.h"
+#include "pci.h"
+#include "sysbus.h"
+#include "flash.h"
+#include "loader.h"
+#include "exec-memory.h"
+#include "sysemu.h"
+#include "isa.h"
+#include "mc146818rtc.h"
There's no rtc, so this shouldn't be needed. Please trim other includes as well.
Post by Jia Liu
+#include "blockdev.h"
+#include "qemu-log.h"
+
+#define KERNEL_LOAD_ADDR 0x100
+
+static uint64_t translate_phys_addr(void *env, uint64_t addr)
+{
+    return cpu_get_phys_page_debug(env, addr);
There's no virtual to physical mapping during CPU init, I suppose. Then just
return addr;
Post by Jia Liu
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUOPENRISCState *env = opaque;
+    openrisc_reset(env);
+}
+
+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);
+    int kernel_size;
target_ulong, target_phys_addr_t or uint64_t?
Post by Jia Liu
+    uint64_t elf_entry;
+    target_phys_addr_t entry;
This is not really used.
Post by Jia Liu
+    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) {
Please add && !qtest_enabled().
Post by Jia Liu
+        kernel_size = load_elf(kernel_filename, translate_phys_addr, env,
+                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
+        entry = elf_entry;
+        if (kernel_size < 0) {
+            kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+        }
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(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",
+                    kernel_filename);
+            exit(1);
+        }
+
+        if (kernel_size > 0) {
+            env->pc = elf_entry;
+        }
+    } else {
+        entry = 0;
+    }
+
+    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-23 07:54:43 UTC
Permalink
Hi Blue,
Post by Blue Swirl
Post by Jia Liu
add a simulation board for openrisc.
---
 Makefile.target   |    1 +
 hw/openrisc_sim.c |  140 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 141 insertions(+)
 create mode 100644 hw/openrisc_sim.c
diff --git a/Makefile.target b/Makefile.target
index 6b1d2d0..433dd3c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -391,6 +391,7 @@ obj-xtensa-y += core-dc233c.o
 obj-xtensa-y += core-fsf.o
 obj-openrisc-y += openrisc_pic.o
+obj-openrisc-y += openrisc_sim.o
 obj-openrisc-y += openrisc_timer.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..869a02e
--- /dev/null
+++ b/hw/openrisc_sim.c
@@ -0,0 +1,140 @@
+/*
+ * Openrisc simulator for use as an ISS.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "hw.h"
+#include "fdc.h"
+#include "net.h"
+#include "openrisc_cpudev.h"
+#include "boards.h"
+#include "pci.h"
+#include "elf.h"
+#include "smbus.h"
+#include "memory.h"
+#include "pc.h"
+#include "pci.h"
+#include "sysbus.h"
+#include "flash.h"
+#include "loader.h"
+#include "exec-memory.h"
+#include "sysemu.h"
+#include "isa.h"
+#include "mc146818rtc.h"
There's no rtc, so this shouldn't be needed. Please trim other includes as well.
deleted, thanks.
Post by Blue Swirl
Post by Jia Liu
+#include "blockdev.h"
+#include "qemu-log.h"
+
+#define KERNEL_LOAD_ADDR 0x100
+
+static uint64_t translate_phys_addr(void *env, uint64_t addr)
+{
+    return cpu_get_phys_page_debug(env, addr);
There's no virtual to physical mapping during CPU init, I suppose. Then just
return addr;
this func is useless, deleted, thanks.
Post by Blue Swirl
Post by Jia Liu
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUOPENRISCState *env = opaque;
+    openrisc_reset(env);
+}
+
+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);
+    int kernel_size;
target_ulong, target_phys_addr_t or uint64_t?
we need it int here, for load error, it return -1.
Post by Blue Swirl
Post by Jia Liu
+    uint64_t elf_entry;
+    target_phys_addr_t entry;
This is not really used.
it is used by somewhere.
Post by Blue Swirl
Post by Jia Liu
+    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) {
Please add && !qtest_enabled().
Thanks, added.
Post by Blue Swirl
Post by Jia Liu
+        kernel_size = load_elf(kernel_filename, translate_phys_addr, env,
+                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
+        entry = elf_entry;
+        if (kernel_size < 0) {
+            kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+        }
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(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",
+                    kernel_filename);
+            exit(1);
+        }
+
+        if (kernel_size > 0) {
+            env->pc = elf_entry;
+        }
+    } else {
+        entry = 0;
+    }
+
+    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
Regards,
Jia.
Blue Swirl
2012-05-23 19:17:02 UTC
Permalink
Post by Jia Liu
Hi Blue,
Post by Blue Swirl
Post by Jia Liu
add a simulation board for openrisc.
---
 Makefile.target   |    1 +
 hw/openrisc_sim.c |  140 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 141 insertions(+)
 create mode 100644 hw/openrisc_sim.c
diff --git a/Makefile.target b/Makefile.target
index 6b1d2d0..433dd3c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -391,6 +391,7 @@ obj-xtensa-y += core-dc233c.o
 obj-xtensa-y += core-fsf.o
 obj-openrisc-y += openrisc_pic.o
+obj-openrisc-y += openrisc_sim.o
 obj-openrisc-y += openrisc_timer.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..869a02e
--- /dev/null
+++ b/hw/openrisc_sim.c
@@ -0,0 +1,140 @@
+/*
+ * Openrisc simulator for use as an ISS.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "hw.h"
+#include "fdc.h"
+#include "net.h"
+#include "openrisc_cpudev.h"
+#include "boards.h"
+#include "pci.h"
+#include "elf.h"
+#include "smbus.h"
+#include "memory.h"
+#include "pc.h"
+#include "pci.h"
+#include "sysbus.h"
+#include "flash.h"
+#include "loader.h"
+#include "exec-memory.h"
+#include "sysemu.h"
+#include "isa.h"
+#include "mc146818rtc.h"
There's no rtc, so this shouldn't be needed. Please trim other includes as well.
deleted, thanks.
Post by Blue Swirl
Post by Jia Liu
+#include "blockdev.h"
+#include "qemu-log.h"
+
+#define KERNEL_LOAD_ADDR 0x100
+
+static uint64_t translate_phys_addr(void *env, uint64_t addr)
+{
+    return cpu_get_phys_page_debug(env, addr);
There's no virtual to physical mapping during CPU init, I suppose. Then just
return addr;
this func is useless, deleted, thanks.
Post by Blue Swirl
Post by Jia Liu
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUOPENRISCState *env = opaque;
+    openrisc_reset(env);
+}
+
+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);
+    int kernel_size;
target_ulong, target_phys_addr_t or uint64_t?
we need it int here, for load error, it return -1.
Well, you could use for example (uint64_t)-1 in the comparison. My
point with this change is to prepare for a 64 bit architecture while
int could be 32 bits. Kernels larger than 4G are still a bit rare...
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+    uint64_t elf_entry;
+    target_phys_addr_t entry;
This is not really used.
it is used by somewhere.
It's written to in a few places, but there are no readers.
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+    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) {
Please add && !qtest_enabled().
Thanks, added.
Post by Blue Swirl
Post by Jia Liu
+        kernel_size = load_elf(kernel_filename, translate_phys_addr, env,
+                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
+        entry = elf_entry;
+        if (kernel_size < 0) {
+            kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+        }
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(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",
+                    kernel_filename);
+            exit(1);
+        }
+
+        if (kernel_size > 0) {
+            env->pc = elf_entry;
+        }
+    } else {
+        entry = 0;
+    }
+
+    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
Regards,
Jia.
Jia Liu
2012-05-25 02:31:01 UTC
Permalink
Post by Blue Swirl
Post by Jia Liu
Hi Blue,
Post by Blue Swirl
Post by Jia Liu
add a simulation board for openrisc.
---
 Makefile.target   |    1 +
 hw/openrisc_sim.c |  140 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 141 insertions(+)
 create mode 100644 hw/openrisc_sim.c
diff --git a/Makefile.target b/Makefile.target
index 6b1d2d0..433dd3c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -391,6 +391,7 @@ obj-xtensa-y += core-dc233c.o
 obj-xtensa-y += core-fsf.o
 obj-openrisc-y += openrisc_pic.o
+obj-openrisc-y += openrisc_sim.o
 obj-openrisc-y += openrisc_timer.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..869a02e
--- /dev/null
+++ b/hw/openrisc_sim.c
@@ -0,0 +1,140 @@
+/*
+ * Openrisc simulator for use as an ISS.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "hw.h"
+#include "fdc.h"
+#include "net.h"
+#include "openrisc_cpudev.h"
+#include "boards.h"
+#include "pci.h"
+#include "elf.h"
+#include "smbus.h"
+#include "memory.h"
+#include "pc.h"
+#include "pci.h"
+#include "sysbus.h"
+#include "flash.h"
+#include "loader.h"
+#include "exec-memory.h"
+#include "sysemu.h"
+#include "isa.h"
+#include "mc146818rtc.h"
There's no rtc, so this shouldn't be needed. Please trim other includes as well.
deleted, thanks.
Post by Blue Swirl
Post by Jia Liu
+#include "blockdev.h"
+#include "qemu-log.h"
+
+#define KERNEL_LOAD_ADDR 0x100
+
+static uint64_t translate_phys_addr(void *env, uint64_t addr)
+{
+    return cpu_get_phys_page_debug(env, addr);
There's no virtual to physical mapping during CPU init, I suppose. Then just
return addr;
this func is useless, deleted, thanks.
Post by Blue Swirl
Post by Jia Liu
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUOPENRISCState *env = opaque;
+    openrisc_reset(env);
+}
+
+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);
+    int kernel_size;
target_ulong, target_phys_addr_t or uint64_t?
we need it int here, for load error, it return -1.
Well, you could use for example (uint64_t)-1 in the comparison. My
point with this change is to prepare for a 64 bit architecture while
int could be 32 bits. Kernels larger than 4G are still a bit rare...
thanks, fixed.
Post by Blue Swirl
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+    uint64_t elf_entry;
+    target_phys_addr_t entry;
This is not really used.
it is used by somewhere.
It's written to in a few places, but there are no readers.
Post by Jia Liu
Post by Blue Swirl
Post by Jia Liu
+    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) {
Please add && !qtest_enabled().
Thanks, added.
Post by Blue Swirl
Post by Jia Liu
+        kernel_size = load_elf(kernel_filename, translate_phys_addr, env,
+                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
+        entry = elf_entry;
+        if (kernel_size < 0) {
+            kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+        }
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(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",
+                    kernel_filename);
+            exit(1);
+        }
+
+        if (kernel_size > 0) {
+            env->pc = elf_entry;
+        }
+    } else {
+        entry = 0;
+    }
+
+    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
Regards,
Jia.
Loading...