* [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support
@ 2012-07-13 4:34 Jia Liu
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 01/15] target-or32: Add target stubs and QOM cpu Jia Liu
` (14 more replies)
0 siblings, 15 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:34 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
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 found at
http://opencores.org/svnget,or1k?file=/trunk/docs/openrisc_arch.pdf
A OpenRISC Linux kernel contain initramfs for qemu-system-or32 testing
can be found at
https://docs.google.com/file/d/0BxeTrz3x0CBLSjR3Sk5Vd3h1eDA/edit?pli=1
A OpenRISC hello-world program for qemu-or32 testing can be found at
https://docs.google.com/file/d/0BxeTrz3x0CBLN3RSWUFNYktrU2M/edit?pli=1
---
to Andears,
If I missed something, or didn't truely understand what you mean,
please give me more comment.
Thank you very much!
Signed-off-by: Jia Liu <proljc@gmail.com>
---
Version History:
v9:
Addressed Blue's review comments:
- fix jump instructions
- fix some instruction decoding
Addressed Andreas&Paolo's review comments:
- rename intrpt*.c to interrupt*.c
- use one-space indentation in Copyright Notice
- remove unused header in cpu.c
- remove/comment unimplement or64 code
- remove unused macro
- move feature into OpenRISCCPU from CPUOpenRISCState
- move tcg_inited into initfn
- remove reset in openrisc_*_initfn
-combine target-machine into target-stubs
v8:
Addressed Max's review comments:
- fix l.div*.
Addressed Blue's review comments:
- using qemu_log instead of printf.
Addressed Peter's review comments:
- fix load_kernel.
Addressed Peter&Andreas's review comments:
- thanks Andreas's r178 example, switch to QOM from CPUArchState.
v7:
Addressed Max's review comments:
- fix l.div*.
- add a div testcase.
- add return -1 to every failed test.
Addressed Peter's review comments:
- fix load_kernel().
Addressed WeiRen's review comments:
- fix typo, l.div and load_kernel().
V6:
Addressed Blue's review comments:
- reimplement l.mul* l.mfspr.
- fix l.mtspr l.sub.
- some English typo fix.
- some coding style fix.
Addressed Max's review comments:
- replace NE2000 with OpenCores 10/100 ethernet adapter, thanks for his patch.
V5:
Addressed Blue's review comments:
- reimplement l.mul* l.mtspr l.add* l.sub* and more.
- shoot bugs with "--enable-debug-tcg".
V4:
Addressed Max's review comments:
- fix l.div l.mac* l.mul*, and more.
Addressed Richard, Wei-Ren and Andreas's review comments:
- replace tcg_temp_new_i32 with tcg_temp_local_new_i32 in l.div translation.
Addressed Andreas's review comments:
- update to suit Makefile system.
- add UPR CPUCFGR and MMUCFGR impelement.
- add instruction check functions.
Version History:
V3:
Addressed Stefan and Andreas's review comments:
- use QEMU and OpenRISC's official name.
Addressed Andreas's review comments:
- reimplement cpu QOM.
- combine target stubs and QOM implement.
- use new commit message and subject.
Addressed Max's review comments:
- handle div zero exception.
- reimplement float point instructions.
- fix l.mac*, l.mul*, and more.
V2:
Addressed Malc, Weiren, Andreas and Blue's review comments:
- reimplement cpu QOM.
Addressed Andreas's review comments:
- reimplement machine.
- rewrite the Copyright Notice using better format.
Addressed Blue and Weiren's review comments:
- compiling with AREG0 and remove global env, no dyngen-exe longer.
Addressed Max, Blue and Weiren's review comments:
- handle div zero exception.
- handle illegal instruction.
Addressed Blue's review comments:
- separate do_interrupt into intrpt.c form intrpt_helper.c.
- add QEMU_NORETURN to raise_exception.
- reimplement float instrutions.
- fix type of linux syscall and termbits.
- reimplement sim board.
- use the LGPL web URL in Copyright Notice.
- reimplemt branch instructions.
- split taregt stubs, QOM and machine.
V1:
- add QEMU OpenRISC support.
- well tested on x64 machine, and final tested x86 machine.
Jia Liu (15):
target-or32: Add target stubs and QOM cpu
target-or32: Add MMU support
target-or32: Add interrupt support
target-or32: Add exception support
target-or32: Add int instruction helpers
target-or32: Add float instruction helpers
target-or32: Add instruction translation
target-or32: Add PIC support
target-or32: Add timer support
target-or32: Add a IIS dummy board
target-or32: Add system instructions
target-or32: Add gdb stub support
target-or32: Add linux syscall, signal and termbits
target-or32: Add linux user support
target-or32: Add testcases
arch_init.c | 2 +
arch_init.h | 1 +
configure | 15 +-
cpu-exec.c | 19 +
default-configs/or32-linux-user.mak | 1 +
default-configs/or32-softmmu.mak | 4 +
elf.h | 2 +
gdbstub.c | 64 ++
hw/openrisc/Makefile.objs | 3 +
hw/openrisc_pic.c | 60 ++
hw/openrisc_sim.c | 150 +++
hw/openrisc_timer.c | 101 ++
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/Makefile.objs | 4 +
target-openrisc/cpu.c | 220 +++++
target-openrisc/cpu.h | 458 +++++++++
target-openrisc/exception.c | 27 +
target-openrisc/exception.h | 28 +
target-openrisc/exception_helper.c | 29 +
target-openrisc/fpu_helper.c | 300 ++++++
target-openrisc/helper.h | 70 ++
target-openrisc/int_helper.c | 87 ++
target-openrisc/interrupt.c | 74 ++
target-openrisc/interrupt_helper.c | 57 ++
target-openrisc/machine.c | 47 +
target-openrisc/mmu.c | 243 +++++
target-openrisc/mmu_helper.c | 63 ++
target-openrisc/sys_helper.c | 287 ++++++
target-openrisc/translate.c | 1785 +++++++++++++++++++++++++++++++++++
tests/tcg/openrisc/Makefile | 71 ++
tests/tcg/openrisc/test_add.c | 43 +
tests/tcg/openrisc/test_addc.c | 38 +
tests/tcg/openrisc/test_addi.c | 33 +
tests/tcg/openrisc/test_addic.c | 33 +
tests/tcg/openrisc/test_and_or.c | 65 ++
tests/tcg/openrisc/test_bf.c | 47 +
tests/tcg/openrisc/test_bnf.c | 51 +
tests/tcg/openrisc/test_div.c | 54 ++
tests/tcg/openrisc/test_divu.c | 34 +
tests/tcg/openrisc/test_extx.c | 78 ++
tests/tcg/openrisc/test_fx.c | 57 ++
tests/tcg/openrisc/test_j.c | 26 +
tests/tcg/openrisc/test_jal.c | 26 +
tests/tcg/openrisc/test_lf_add.c | 39 +
tests/tcg/openrisc/test_lf_div.c | 37 +
tests/tcg/openrisc/test_lf_eqs.c | 88 ++
tests/tcg/openrisc/test_lf_ges.c | 88 ++
tests/tcg/openrisc/test_lf_gts.c | 86 ++
tests/tcg/openrisc/test_lf_les.c | 88 ++
tests/tcg/openrisc/test_lf_lts.c | 92 ++
tests/tcg/openrisc/test_lf_mul.c | 22 +
tests/tcg/openrisc/test_lf_nes.c | 89 ++
tests/tcg/openrisc/test_lf_rem.c | 32 +
tests/tcg/openrisc/test_lf_sub.c | 35 +
tests/tcg/openrisc/test_logic.c | 105 +++
tests/tcg/openrisc/test_lx.c | 84 ++
tests/tcg/openrisc/test_movhi.c | 31 +
tests/tcg/openrisc/test_mul.c | 48 +
tests/tcg/openrisc/test_muli.c | 48 +
tests/tcg/openrisc/test_mulu.c | 48 +
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 | 39 +
tests/tcg/openrisc/test_sfltu.c | 43 +
tests/tcg/openrisc/test_sfltui.c | 39 +
tests/tcg/openrisc/test_sfne.c | 43 +
tests/tcg/openrisc/test_sfnei.c | 39 +
tests/tcg/openrisc/test_sub.c | 35 +
90 files changed, 8024 insertions(+), 6 deletions(-)
create mode 100644 default-configs/or32-linux-user.mak
create mode 100644 default-configs/or32-softmmu.mak
create mode 100644 hw/openrisc/Makefile.objs
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/Makefile.objs
create mode 100644 target-openrisc/cpu.c
create mode 100644 target-openrisc/cpu.h
create mode 100644 target-openrisc/exception.c
create mode 100644 target-openrisc/exception.h
create mode 100644 target-openrisc/exception_helper.c
create mode 100644 target-openrisc/fpu_helper.c
create mode 100644 target-openrisc/helper.h
create mode 100644 target-openrisc/int_helper.c
create mode 100644 target-openrisc/interrupt.c
create mode 100644 target-openrisc/interrupt_helper.c
create mode 100644 target-openrisc/machine.c
create mode 100644 target-openrisc/mmu.c
create mode 100644 target-openrisc/mmu_helper.c
create mode 100644 target-openrisc/sys_helper.c
create mode 100644 target-openrisc/translate.c
create mode 100644 tests/tcg/openrisc/Makefile
create mode 100644 tests/tcg/openrisc/test_add.c
create mode 100644 tests/tcg/openrisc/test_addc.c
create mode 100644 tests/tcg/openrisc/test_addi.c
create mode 100644 tests/tcg/openrisc/test_addic.c
create mode 100644 tests/tcg/openrisc/test_and_or.c
create mode 100644 tests/tcg/openrisc/test_bf.c
create mode 100644 tests/tcg/openrisc/test_bnf.c
create mode 100644 tests/tcg/openrisc/test_div.c
create mode 100644 tests/tcg/openrisc/test_divu.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_eqs.c
create mode 100644 tests/tcg/openrisc/test_lf_ges.c
create mode 100644 tests/tcg/openrisc/test_lf_gts.c
create mode 100644 tests/tcg/openrisc/test_lf_les.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_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_muli.c
create mode 100644 tests/tcg/openrisc/test_mulu.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
create mode 100644 tests/tcg/openrisc/test_sub.c
--
1.7.9.5
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 01/15] target-or32: Add target stubs and QOM cpu
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
@ 2012-07-13 4:34 ` Jia Liu
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 02/15] target-or32: Add MMU support Jia Liu
` (13 subsequent siblings)
14 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:34 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add OpenRISC target stubs and cpu support.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
arch_init.c | 2 +
arch_init.h | 1 +
configure | 14 +-
cpu-exec.c | 2 +
default-configs/or32-softmmu.mak | 4 +
elf.h | 2 +
hw/openrisc/Makefile.objs | 1 +
poison.h | 1 +
target-openrisc/Makefile.objs | 3 +
target-openrisc/cpu.c | 220 +++++++++++++++++++++++++
target-openrisc/cpu.h | 335 ++++++++++++++++++++++++++++++++++++++
target-openrisc/interrupt.c | 30 ++++
target-openrisc/machine.c | 47 ++++++
target-openrisc/mmu.c | 39 +++++
target-openrisc/mmu_helper.c | 43 +++++
target-openrisc/translate.c | 75 +++++++++
16 files changed, 817 insertions(+), 2 deletions(-)
create mode 100644 default-configs/or32-softmmu.mak
create mode 100644 hw/openrisc/Makefile.objs
create mode 100644 target-openrisc/Makefile.objs
create mode 100644 target-openrisc/cpu.c
create mode 100644 target-openrisc/cpu.h
create mode 100644 target-openrisc/interrupt.c
create mode 100644 target-openrisc/machine.c
create mode 100644 target-openrisc/mmu.c
create mode 100644 target-openrisc/mmu_helper.c
create mode 100644 target-openrisc/translate.c
diff --git a/arch_init.c b/arch_init.c
index 5b0f562..ebdad3a 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -79,6 +79,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 500fe24..3a53a92 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 \
@@ -3501,7 +3502,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
@@ -3617,6 +3618,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
@@ -3695,7 +3701,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile"
case "$target_arch2" in
- alpha | sparc* | xtensa* | ppc*)
+ alpha | or32 | sparc* | xtensa* | ppc*)
echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
;;
esac
@@ -3869,6 +3875,10 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
echo "CONFIG_MIPS_DIS=y" >> $config_target_mak
echo "CONFIG_MIPS_DIS=y" >> $libdis_config_mak
;;
+ or32)
+ echo "CONFIG_OPENRISC_DIS=y" >> $config_target_mak
+ echo "CONFIG_OPENRISC_DIS=y" >> $libdis_config_mak
+ ;;
ppc*)
echo "CONFIG_PPC_DIS=y" >> $config_target_mak
echo "CONFIG_PPC_DIS=y" >> $libdis_config_mak
diff --git a/cpu-exec.c b/cpu-exec.c
index 08c35f7..ce2d569 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -225,6 +225,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)
@@ -634,6 +635,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..cce4746
--- /dev/null
+++ b/default-configs/or32-softmmu.mak
@@ -0,0 +1,4 @@
+# Default configuration for or32-softmmu
+
+CONFIG_SERIAL=y
+CONFIG_OPENCORES_ETH=y
diff --git a/elf.h b/elf.h
index 9c9acfa..a21ea53 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/hw/openrisc/Makefile.objs b/hw/openrisc/Makefile.objs
new file mode 100644
index 0000000..bfead21
--- /dev/null
+++ b/hw/openrisc/Makefile.objs
@@ -0,0 +1 @@
+obj-y := $(addprefix ../,$(obj-y))
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/Makefile.objs b/target-openrisc/Makefile.objs
new file mode 100644
index 0000000..ef933ef
--- /dev/null
+++ b/target-openrisc/Makefile.objs
@@ -0,0 +1,3 @@
+obj-$(CONFIG_SOFTMMU) += machine.o
+obj-y += cpu.o interrupt.o mmu.o translate.o
+obj-y += mmu_helper.o
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
new file mode 100644
index 0000000..9400aea
--- /dev/null
+++ b/target-openrisc/cpu.c
@@ -0,0 +1,220 @@
+/*
+ * QEMU OpenRISC CPU
+ *
+ * Copyright (c) 2012 Jia Liu <proljc@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"
+
+/* CPUClass::reset() */
+static void openrisc_cpu_reset(CPUState *s)
+{
+ OpenRISCCPU *cpu = OPENRISC_CPU(s);
+ OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu);
+
+ if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+ qemu_log("CPU Reset (CPU %d)\n", cpu->env.cpu_index);
+ log_cpu_state(&cpu->env, 0);
+ }
+
+ occ->parent_reset(s);
+
+ memset(&cpu->env, 0, offsetof(CPUOpenRISCState, breakpoints));
+
+ tlb_flush(&cpu->env, 1);
+ /*tb_flush(&cpu->env); FIXME: Do we need it? */
+
+ cpu->env.pc = 0x100;
+ cpu->env.sr = SR_FO | SR_SM;
+ cpu->env.exception_index = -1;
+
+ cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP;
+ cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S;
+ cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2));
+ cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2));
+
+#ifndef CONFIG_USER_ONLY
+ cpu->env.picmr = 0x00000000;
+ cpu->env.picsr = 0x00000000;
+
+ cpu->env.ttmr = 0x00000000;
+ cpu->env.ttcr = 0x00000000;
+#endif
+}
+
+static inline void set_feature(OpenRISCCPU *cpu, int feature)
+{
+ cpu->feature |= feature;
+ cpu->env.cpucfgr = cpu->feature;
+}
+
+void openrisc_cpu_realize(Object *obj, Error **errp)
+{
+ OpenRISCCPU *cpu = OPENRISC_CPU(obj);
+
+ qemu_init_vcpu(&cpu->env);
+ cpu_reset(CPU(cpu));
+}
+
+static void openrisc_cpu_initfn(Object *obj)
+{
+ OpenRISCCPU *cpu = OPENRISC_CPU(obj);
+ static int inited;
+
+ cpu_exec_init(&cpu->env);
+
+#ifndef CONFIG_USER_ONLY
+ cpu_openrisc_mmu_init(cpu);
+#endif
+
+ if (tcg_enabled() && !inited) {
+ inited = 1;
+ openrisc_translate_init();
+ }
+}
+
+/* CPU models */
+static void or1200_initfn(Object *obj)
+{
+ OpenRISCCPU *cpu = OPENRISC_CPU(obj);
+
+ set_feature(cpu, OPENRISC_FEATURE_OB32S);
+ set_feature(cpu, OPENRISC_FEATURE_OF32S);
+}
+
+static void openrisc_any_initfn(Object *obj)
+{
+ OpenRISCCPU *cpu = OPENRISC_CPU(obj);
+
+ set_feature(cpu, OPENRISC_FEATURE_OB32S);
+}
+
+typedef struct OpenRISCCPUInfo {
+ const char *name;
+ void (*initfn)(Object *obj);
+} OpenRISCCPUInfo;
+
+static const OpenRISCCPUInfo openrisc_cpus[] = {
+ { .name = "or1200", .initfn = or1200_initfn },
+ { .name = "any", .initfn = openrisc_any_initfn },
+};
+
+static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
+{
+ OpenRISCCPUClass *occ = OPENRISC_CPU_CLASS(oc);
+ CPUClass *cc = CPU_CLASS(occ);
+
+ occ->parent_reset = cc->reset;
+ cc->reset = openrisc_cpu_reset;
+}
+
+static void cpu_register(const OpenRISCCPUInfo *info)
+{
+ TypeInfo type_info = {
+ .name = info->name,
+ .parent = TYPE_OPENRISC_CPU,
+ .instance_size = sizeof(OpenRISCCPU),
+ .instance_init = info->initfn,
+ .class_size = sizeof(OpenRISCCPUClass),
+ };
+
+ type_register_static(&type_info);
+}
+
+static const TypeInfo openrisc_cpu_type_info = {
+ .name = TYPE_OPENRISC_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(OpenRISCCPU),
+ .instance_init = openrisc_cpu_initfn,
+ .abstract = false,
+ .class_size = sizeof(OpenRISCCPUClass),
+ .class_init = openrisc_cpu_class_init,
+};
+
+static void openrisc_cpu_register_types(void)
+{
+ int i;
+
+ type_register_static(&openrisc_cpu_type_info);
+ for (i = 0; i < ARRAY_SIZE(openrisc_cpus); i++) {
+ cpu_register(&openrisc_cpus[i]);
+ }
+}
+
+OpenRISCCPU *cpu_openrisc_init(const char *cpu_model)
+{
+ OpenRISCCPU *cpu;
+
+ if (!object_class_by_name(cpu_model)) {
+ return NULL;
+ }
+ cpu = OPENRISC_CPU(object_new(cpu_model));
+ cpu->env.cpu_model_str = cpu_model;
+
+ openrisc_cpu_realize(OBJECT(cpu), NULL);
+
+ return cpu;
+}
+
+typedef struct OpenRISCCPUList {
+ fprintf_function cpu_fprintf;
+ FILE *file;
+} OpenRISCCPUList;
+
+/* Sort alphabetically by type name, except for "any". */
+static gint openrisc_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+ ObjectClass *class_a = (ObjectClass *)a;
+ ObjectClass *class_b = (ObjectClass *)b;
+ const char *name_a, *name_b;
+
+ name_a = object_class_get_name(class_a);
+ name_b = object_class_get_name(class_b);
+ if (strcmp(name_a, "any") == 0) {
+ return 1;
+ } else if (strcmp(name_b, "any") == 0) {
+ return -1;
+ } else {
+ return strcmp(name_a, name_b);
+ }
+}
+
+static void openrisc_cpu_list_entry(gpointer data, gpointer user_data)
+{
+ ObjectClass *oc = data;
+ OpenRISCCPUList *s = user_data;
+
+ (*s->cpu_fprintf)(s->file, " %s\n",
+ object_class_get_name(oc));
+}
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
+{
+ OpenRISCCPUList s = {
+ .file = f,
+ .cpu_fprintf = cpu_fprintf,
+ };
+ GSList *list;
+
+ list = object_class_get_list(TYPE_OPENRISC_CPU, false);
+ list = g_slist_sort(list, openrisc_cpu_list_compare);
+ (*cpu_fprintf)(f, "Available CPUs:\n");
+ g_slist_foreach(list, openrisc_cpu_list_entry, &s);
+ g_slist_free(list);
+}
+
+type_init(openrisc_cpu_register_types)
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
new file mode 100644
index 0000000..58c63fa
--- /dev/null
+++ b/target-openrisc/cpu.h
@@ -0,0 +1,335 @@
+/*
+ * OpenRISC virtual CPU header.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@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_LONG_BITS 32
+#define ELF_MACHINE EM_OPENRISC
+
+#define CPUArchState struct CPUOpenRISCState
+
+#include "config.h"
+#include "qemu-common.h"
+#include "cpu-defs.h"
+#include "softfloat.h"
+#include "qemu/cpu.h"
+#include "error.h"
+
+#define TYPE_OPENRISC_CPU "or32-cpu"
+
+#define OPENRISC_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU)
+#define OPENRISC_CPU(obj) \
+ OBJECT_CHECK(OpenRISCCPU, (obj), TYPE_OPENRISC_CPU)
+#define OPENRISC_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(OpenRISCCPUClass, (obj), TYPE_OPENRISC_CPU)
+
+/**
+ * OpenRISCCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A OpenRISC CPU model.
+ */
+typedef struct OpenRISCCPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ void (*parent_reset)(CPUState *cpu);
+} OpenRISCCPUClass;
+
+#define NB_MMU_MODES 3
+
+#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)
+
+/* Internal flags, delay slot flag */
+#define D_FLAG 1
+
+/* 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
+};
+
+/* Unit presece register */
+enum {
+ UPR_UP = (1 << 0),
+ UPR_DCP = (1 << 1),
+ UPR_ICP = (1 << 2),
+ UPR_DMP = (1 << 3),
+ UPR_IMP = (1 << 4),
+ UPR_MP = (1 << 5),
+ UPR_DUP = (1 << 6),
+ UPR_PCUR = (1 << 7),
+ UPR_PMP = (1 << 8),
+ UPR_PICP = (1 << 9),
+ UPR_TTP = (1 << 10),
+ UPR_CUP = (255 << 24),
+};
+
+/* CPU configure register */
+enum {
+ CPUCFGR_NSGF = (15 << 0),
+ CPUCFGR_CGF = (1 << 4),
+ CPUCFGR_OB32S = (1 << 5),
+ CPUCFGR_OB64S = (1 << 6),
+ CPUCFGR_OF32S = (1 << 7),
+ CPUCFGR_OF64S = (1 << 8),
+ CPUCFGR_OV64S = (1 << 9),
+};
+
+/* DMMU configure register */
+enum {
+ DMMUCFGR_NTW = (3 << 0),
+ DMMUCFGR_NTS = (7 << 2),
+ DMMUCFGR_NAE = (7 << 5),
+ DMMUCFGR_CRI = (1 << 8),
+ DMMUCFGR_PRI = (1 << 9),
+ DMMUCFGR_TEIRI = (1 << 10),
+ DMMUCFGR_HTR = (1 << 11),
+};
+
+/* IMMU configure register */
+enum {
+ IMMUCFGR_NTW = (3 << 0),
+ IMMUCFGR_NTS = (7 << 2),
+ IMMUCFGR_NAE = (7 << 5),
+ IMMUCFGR_CRI = (1 << 8),
+ IMMUCFGR_PRI = (1 << 9),
+ IMMUCFGR_TEIRI = (1 << 10),
+ IMMUCFGR_HTR = (1 << 11),
+};
+
+/* Float point control status 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),
+};
+
+/* 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 << 0),
+ 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),
+};
+
+/* OpenRISC Hardware Capabilities */
+enum {
+ OPENRISC_FEATURE_NSGF = (15 << 0),
+ OPENRISC_FEATURE_CGF = (1 << 4),
+ OPENRISC_FEATURE_OB32S = (1 << 5),
+ OPENRISC_FEATURE_OB64S = (1 << 6),
+ OPENRISC_FEATURE_OF32S = (1 << 7),
+ OPENRISC_FEATURE_OF64S = (1 << 8),
+ OPENRISC_FEATURE_OV64S = (1 << 9),
+};
+
+typedef struct CPUOpenRISCState {
+ target_ulong gpr[32]; /* General registers */
+ target_ulong pc; /* Program counter */
+ target_ulong npc; /* Next PC */
+ target_ulong ppc; /* Prev PC */
+ target_ulong jmp_pc; /* Jump PC */
+
+ 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 sr; /* Supervisor register */
+ uint32_t vr; /* Version register */
+ uint32_t upr; /* Unit presence register */
+ uint32_t cpucfgr; /* CPU configure register */
+ uint32_t dmmucfgr; /* DMMU configure register */
+ uint32_t immucfgr; /* IMMU configure register */
+ uint32_t esr; /* Exception supervisor register */
+ uint32_t fpcsr; /* Float register */
+ float_status fp_status;
+
+ uint32_t flags; /* cpu_flags, we only use it for exception
+ in solt so far. */
+ uint32_t btaken; /* the SR_F bit */
+
+ CPU_COMMON
+
+#ifndef CONFIG_USER_ONLY
+ 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
+} CPUOpenRISCState;
+
+/**
+ * OpenRISCCPU:
+ * @env: #CPUOpenRISCState
+ *
+ * A OpenRISC CPU.
+ */
+typedef struct OpenRISCCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUOpenRISCState env;
+
+ uint32_t feature; /* CPU Capabilities */
+} 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))
+
+OpenRISCCPU *cpu_openrisc_init(const char *cpu_model);
+void openrisc_cpu_realize(Object *obj, Error **errp);
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
+int cpu_openrisc_exec(CPUOpenRISCState *s);
+void do_interrupt(CPUOpenRISCState *env);
+void openrisc_translate_init(void);
+
+#define cpu_list cpu_openrisc_list
+#define cpu_exec cpu_openrisc_exec
+#define cpu_gen_code cpu_openrisc_gen_code
+
+#ifndef CONFIG_USER_ONLY
+void cpu_openrisc_mmu_init(OpenRISCCPU *cpu);
+#endif
+
+static inline CPUOpenRISCState *cpu_init(const char *cpu_model)
+{
+ OpenRISCCPU *cpu = cpu_openrisc_init(cpu_model);
+ if (cpu) {
+ return &cpu->env;
+ }
+ return NULL;
+}
+
+#include "cpu-all.h"
+
+static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
+ target_ulong *pc,
+ target_ulong *cs_base, int *flags)
+{
+ *pc = env->pc;
+ *cs_base = 0;
+ /* D_FLAG -- branch instruction exception */
+ *flags = (env->flags & D_FLAG);
+}
+
+static inline int cpu_mmu_index(CPUOpenRISCState *env)
+{
+ return 0;
+}
+
+static inline bool cpu_has_work(CPUOpenRISCState *env)
+{
+ return true;
+}
+
+#include "exec-all.h"
+
+static inline target_ulong cpu_get_pc(CPUOpenRISCState *env)
+{
+ return env->pc;
+}
+
+static inline void cpu_pc_from_tb(CPUOpenRISCState *env, TranslationBlock *tb)
+{
+ env->pc = tb->pc;
+}
+
+#endif /* CPU_OPENRISC_H */
diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c
new file mode 100644
index 0000000..7a9ee0b
--- /dev/null
+++ b/target-openrisc/interrupt.c
@@ -0,0 +1,30 @@
+/*
+ * OpenRISC interrupt.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "host-utils.h"
+#ifndef CONFIG_USER_ONLY
+#include "hw/loader.h"
+#endif
+
+void do_interrupt(CPUOpenRISCState *env)
+{
+}
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
new file mode 100644
index 0000000..cba9811
--- /dev/null
+++ b/target-openrisc/machine.c
@@ -0,0 +1,47 @@
+/*
+ * OpenRISC Machine
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+
+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)
+{
+ 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);
+}
diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c
new file mode 100644
index 0000000..1a72aaa
--- /dev/null
+++ b/target-openrisc/mmu.c
@@ -0,0 +1,39 @@
+/*
+ * OpenRISC MMU.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ * Zhizhou Zhang <etouzh@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "host-utils.h"
+#ifndef CONFIG_USER_ONLY
+#include "hw/loader.h"
+#endif
+
+#ifndef CONFIG_USER_ONLY
+target_phys_addr_t cpu_get_phys_page_debug(CPUOpenRISCState *env,
+ target_ulong addr)
+{
+ return addr;
+}
+
+void cpu_openrisc_mmu_init(OpenRISCCPU *cpu)
+{
+}
+#endif
diff --git a/target-openrisc/mmu_helper.c b/target-openrisc/mmu_helper.c
new file mode 100644
index 0000000..7c28079
--- /dev/null
+++ b/target-openrisc/mmu_helper.c
@@ -0,0 +1,43 @@
+/*
+ * OpenRISC MMU helper routines
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ * Zhizhou Zhang <etouzh@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"
+
+#ifndef CONFIG_USER_ONLY
+#include "softmmu_exec.h"
+#define MMUSUFFIX _mmu
+
+#define SHIFT 0
+#include "softmmu_template.h"
+
+#define SHIFT 1
+#include "softmmu_template.h"
+
+#define SHIFT 2
+#include "softmmu_template.h"
+
+#define SHIFT 3
+#include "softmmu_template.h"
+
+void tlb_fill(CPUOpenRISCState *env, target_ulong addr, int is_write,
+ int mmu_idx, uintptr_t retaddr)
+{
+}
+#endif
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
new file mode 100644
index 0000000..a2b9b4f
--- /dev/null
+++ b/target-openrisc/translate.c
@@ -0,0 +1,75 @@
+/*
+ * OpenRISC translation
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ * Feng Gao <gf91597@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "disas.h"
+#include "tcg-op.h"
+#include "qemu-common.h"
+#include "qemu-log.h"
+#include "config.h"
+
+#define OPENRISC_DISAS
+
+#ifdef OPENRISC_DISAS
+# define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
+#else
+# define LOG_DIS(...) do { } while (0)
+#endif
+
+void openrisc_translate_init(void)
+{
+}
+
+static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
+ TranslationBlock *tb,
+ int search_pc)
+{
+}
+
+void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
+{
+ gen_intermediate_code_internal(openrisc_env_get_cpu(env), tb, 0);
+}
+
+void gen_intermediate_code_pc(CPUOpenRISCState *env,
+ struct TranslationBlock *tb)
+{
+ gen_intermediate_code_internal(openrisc_env_get_cpu(env), tb, 1);
+}
+
+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,
+ int pc_pos)
+{
+ env->pc = gen_opc_pc[pc_pos];
+}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 02/15] target-or32: Add MMU support
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 01/15] target-or32: Add target stubs and QOM cpu Jia Liu
@ 2012-07-13 4:34 ` Jia Liu
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 03/15] target-or32: Add interrupt support Jia Liu
` (12 subsequent siblings)
14 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:34 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add OpenRISC MMU support.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-openrisc/cpu.h | 79 +++++++++++++++-
target-openrisc/mmu.c | 206 +++++++++++++++++++++++++++++++++++++++++-
target-openrisc/mmu_helper.c | 20 ++++
3 files changed, 303 insertions(+), 2 deletions(-)
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 58c63fa..9423e77 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -25,6 +25,9 @@
#define CPUArchState struct CPUOpenRISCState
+/* cpu_openrisc_map_address_* in CPUOpenRISCTLBContext need this decl. */
+struct OpenRISCCPU;
+
#include "config.h"
#include "qemu-common.h"
#include "cpu-defs.h"
@@ -57,6 +60,12 @@ typedef struct OpenRISCCPUClass {
#define NB_MMU_MODES 3
+enum {
+ MMU_NOMMU_IDX = 0,
+ MMU_SUPERVISOR_IDX = 1,
+ MMU_USER_IDX = 2,
+};
+
#define TARGET_PAGE_BITS 13
#define TARGET_PHYS_ADDR_SPACE_BITS 32
@@ -208,6 +217,56 @@ enum {
OPENRISC_FEATURE_OV64S = (1 << 9),
};
+/* TLB size */
+enum {
+ DTLB_WAYS = 1,
+ DTLB_SIZE = 64,
+ DTLB_MASK = (DTLB_SIZE-1),
+ ITLB_WAYS = 1,
+ ITLB_SIZE = 64,
+ ITLB_MASK = (ITLB_SIZE-1),
+};
+
+/* TLB prot */
+enum {
+ URE = (1 << 6),
+ UWE = (1 << 7),
+ SRE = (1 << 8),
+ SWE = (1 << 9),
+
+ SXE = (1 << 6),
+ UXE = (1 << 7),
+};
+
+/* check if tlb available */
+enum {
+ TLBRET_INVALID = -3,
+ TLBRET_NOMATCH = -2,
+ TLBRET_BADADDR = -1,
+ TLBRET_MATCH = 0
+};
+
+typedef struct OpenRISCTLBEntry {
+ uint32_t mr;
+ uint32_t tr;
+} OpenRISCTLBEntry;
+
+#ifndef CONFIG_USER_ONLY
+typedef struct CPUOpenRISCTLBContext {
+ OpenRISCTLBEntry itlb[ITLB_WAYS][ITLB_SIZE];
+ OpenRISCTLBEntry dtlb[DTLB_WAYS][DTLB_SIZE];
+
+ int (*cpu_openrisc_map_address_code)(struct OpenRISCCPU *cpu,
+ target_phys_addr_t *physical,
+ int *prot,
+ target_ulong address, int rw);
+ int (*cpu_openrisc_map_address_data)(struct OpenRISCCPU *cpu,
+ target_phys_addr_t *physical,
+ int *prot,
+ target_ulong address, int rw);
+} CPUOpenRISCTLBContext;
+#endif
+
typedef struct CPUOpenRISCState {
target_ulong gpr[32]; /* General registers */
target_ulong pc; /* Program counter */
@@ -241,6 +300,8 @@ typedef struct CPUOpenRISCState {
CPU_COMMON
#ifndef CONFIG_USER_ONLY
+ CPUOpenRISCTLBContext * tlb;
+
struct QEMUTimer *timer;
uint32_t ttmr; /* Timer tick mode register */
uint32_t ttcr; /* Timer tick count register */
@@ -280,13 +341,26 @@ void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
int cpu_openrisc_exec(CPUOpenRISCState *s);
void do_interrupt(CPUOpenRISCState *env);
void openrisc_translate_init(void);
+int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env,
+ target_ulong address,
+ int rw, int mmu_idx);
#define cpu_list cpu_openrisc_list
#define cpu_exec cpu_openrisc_exec
#define cpu_gen_code cpu_openrisc_gen_code
+#define cpu_handle_mmu_fault cpu_openrisc_handle_mmu_fault
#ifndef CONFIG_USER_ONLY
void cpu_openrisc_mmu_init(OpenRISCCPU *cpu);
+int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu,
+ target_phys_addr_t *physical,
+ int *prot, target_ulong address, int rw);
+int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu,
+ target_phys_addr_t *physical,
+ int *prot, target_ulong address, int rw);
+int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu,
+ target_phys_addr_t *physical,
+ int *prot, target_ulong address, int rw);
#endif
static inline CPUOpenRISCState *cpu_init(const char *cpu_model)
@@ -312,7 +386,10 @@ static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
static inline int cpu_mmu_index(CPUOpenRISCState *env)
{
- return 0;
+ if (!(env->sr & SR_IME)) {
+ return MMU_NOMMU_IDX;
+ }
+ return (env->sr & SR_SM) == 0 ? MMU_USER_IDX : MMU_SUPERVISOR_IDX;
}
static inline bool cpu_has_work(CPUOpenRISCState *env)
diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c
index 1a72aaa..0be1d41 100644
--- a/target-openrisc/mmu.c
+++ b/target-openrisc/mmu.c
@@ -27,13 +27,217 @@
#endif
#ifndef CONFIG_USER_ONLY
+int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu,
+ target_phys_addr_t *physical,
+ int *prot, target_ulong address, int rw)
+{
+ *physical = address;
+ *prot = PAGE_READ | PAGE_WRITE;
+ return TLBRET_MATCH;
+}
+
+int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu,
+ 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 ((cpu->env.tlb->itlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) {
+ return TLBRET_NOMATCH;
+ }
+ if (!(cpu->env.tlb->itlb[0][idx].mr & 1)) {
+ return TLBRET_INVALID;
+ }
+
+ if (cpu->env.sr & SR_SM) { /* supervisor mode */
+ if (cpu->env.tlb->itlb[0][idx].tr & SXE) {
+ right |= PAGE_EXEC;
+ }
+ } else {
+ if (cpu->env.tlb->itlb[0][idx].tr & UXE) {
+ right |= PAGE_EXEC;
+ }
+ }
+
+ if ((rw & 2) && ((right & PAGE_EXEC) == 0)) {
+ return TLBRET_BADADDR;
+ }
+
+ *physical = (cpu->env.tlb->itlb[0][idx].tr & TARGET_PAGE_MASK) |
+ (address & (TARGET_PAGE_SIZE-1));
+ *prot = right;
+ return TLBRET_MATCH;
+}
+
+int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu,
+ 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 ((cpu->env.tlb->dtlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) {
+ return TLBRET_NOMATCH;
+ }
+ if (!(cpu->env.tlb->dtlb[0][idx].mr & 1)) {
+ return TLBRET_INVALID;
+ }
+
+ if (cpu->env.sr & SR_SM) { /* supervisor mode */
+ if (cpu->env.tlb->dtlb[0][idx].tr & SRE) {
+ right |= PAGE_READ;
+ }
+ if (cpu->env.tlb->dtlb[0][idx].tr & SWE) {
+ right |= PAGE_WRITE;
+ }
+ } else {
+ if (cpu->env.tlb->dtlb[0][idx].tr & URE) {
+ right |= PAGE_READ;
+ }
+ if (cpu->env.tlb->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 = (cpu->env.tlb->dtlb[0][idx].tr & TARGET_PAGE_MASK) |
+ (address & (TARGET_PAGE_SIZE-1));
+ *prot = right;
+ return TLBRET_MATCH;
+}
+
+static int cpu_openrisc_get_phys_addr(OpenRISCCPU *cpu,
+ target_phys_addr_t *physical,
+ int *prot, target_ulong address,
+ int rw)
+{
+ int ret = TLBRET_MATCH;
+
+ /* [0x0000--0x2000]: unmapped */
+ if (address < 0x2000 && (cpu->env.sr & SR_SM)) {
+ *physical = address;
+ *prot = PAGE_READ | PAGE_WRITE;
+ return ret;
+ }
+
+ if (rw == 2) { /* ITLB */
+ *physical = 0;
+ ret = cpu->env.tlb->cpu_openrisc_map_address_code(cpu, physical,
+ prot, address, rw);
+ } else { /* DTLB */
+ ret = cpu->env.tlb->cpu_openrisc_map_address_data(cpu, physical,
+ prot, address, rw);
+ }
+
+ return ret;
+}
+#endif
+
+static void cpu_openrisc_raise_mmu_exception(OpenRISCCPU *cpu,
+ 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;
+#ifndef 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
+ }
+
+ cpu->env.exception_index = exception;
+ cpu->env.eear = address;
+}
+
+#ifndef 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;
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
+
+ ret = cpu_openrisc_get_phys_addr(cpu, &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) {
+ cpu_openrisc_raise_mmu_exception(cpu, 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;
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
+
+ cpu_openrisc_raise_mmu_exception(cpu, address, rw, ret);
+ ret = 1;
+
+ return ret;
+}
+#endif
+
+#ifndef CONFIG_USER_ONLY
target_phys_addr_t cpu_get_phys_page_debug(CPUOpenRISCState *env,
target_ulong addr)
{
- return addr;
+ target_phys_addr_t phys_addr;
+ int prot;
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
+
+ if (cpu_openrisc_get_phys_addr(cpu, &phys_addr, &prot, addr, 0)) {
+ return -1;
+ }
+
+ return phys_addr;
}
void cpu_openrisc_mmu_init(OpenRISCCPU *cpu)
{
+ cpu->env.tlb = g_malloc0(sizeof(CPUOpenRISCTLBContext));
+
+ cpu->env.tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu;
+ cpu->env.tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu;
}
#endif
diff --git a/target-openrisc/mmu_helper.c b/target-openrisc/mmu_helper.c
index 7c28079..59ed371 100644
--- a/target-openrisc/mmu_helper.c
+++ b/target-openrisc/mmu_helper.c
@@ -39,5 +39,25 @@
void tlb_fill(CPUOpenRISCState *env, target_ulong addr, int is_write,
int mmu_idx, uintptr_t retaddr)
{
+ TranslationBlock *tb;
+ unsigned long pc;
+ int ret;
+
+ ret = cpu_openrisc_handle_mmu_fault(env, addr, is_write, mmu_idx);
+
+ if (ret) {
+ if (retaddr) {
+ /* now we have a real cpu fault. */
+ pc = (unsigned long)retaddr;
+ tb = tb_find_pc(pc);
+ if (tb) {
+ /* the PC is inside the translated code. It means that we
+ have a virtual CPU fault. */
+ cpu_restore_state(tb, env, pc);
+ }
+ }
+ /* Raise Exception. */
+ cpu_loop_exit(env);
+ }
}
#endif
--
1.7.9.5
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 03/15] target-or32: Add interrupt support
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 01/15] target-or32: Add target stubs and QOM cpu Jia Liu
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 02/15] target-or32: Add MMU support Jia Liu
@ 2012-07-13 4:34 ` Jia Liu
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 04/15] target-or32: Add exception support Jia Liu
` (11 subsequent siblings)
14 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:34 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add OpenRISC interrupt support.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
cpu-exec.c | 17 +++++++++++
target-openrisc/Makefile.objs | 2 +-
target-openrisc/cpu.h | 8 ++++-
target-openrisc/helper.h | 25 ++++++++++++++++
target-openrisc/interrupt.c | 44 ++++++++++++++++++++++++++++
target-openrisc/interrupt_helper.c | 57 ++++++++++++++++++++++++++++++++++++
6 files changed, 151 insertions(+), 2 deletions(-)
create mode 100644 target-openrisc/helper.h
create mode 100644 target-openrisc/interrupt_helper.c
diff --git a/cpu-exec.c b/cpu-exec.c
index ce2d569..c1fa2d1 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -382,6 +382,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/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
index ef933ef..74c4b8d 100644
--- a/target-openrisc/Makefile.objs
+++ b/target-openrisc/Makefile.objs
@@ -1,3 +1,3 @@
obj-$(CONFIG_SOFTMMU) += machine.o
obj-y += cpu.o interrupt.o mmu.o translate.o
-obj-y += mmu_helper.o
+obj-y += interrupt_helper.o mmu_helper.o
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 9423e77..51013f3 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -83,6 +83,9 @@ enum {
/* Internal flags, delay slot flag */
#define D_FLAG 1
+/* Interrupt */
+#define NR_IRQS 32
+
/* Registers */
enum {
R0 = 0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10,
@@ -309,6 +312,7 @@ typedef struct CPUOpenRISCState {
uint32_t picmr; /* Interrupt mask register */
uint32_t picsr; /* Interrupt contrl register*/
#endif
+ void *irq[32]; /* Interrupt irq input */
} CPUOpenRISCState;
/**
@@ -392,9 +396,11 @@ static inline int cpu_mmu_index(CPUOpenRISCState *env)
return (env->sr & SR_SM) == 0 ? MMU_USER_IDX : MMU_SUPERVISOR_IDX;
}
+#define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_INT_0
static inline bool cpu_has_work(CPUOpenRISCState *env)
{
- return true;
+ return env->interrupt_request & (CPU_INTERRUPT_HARD |
+ CPU_INTERRUPT_TIMER);
}
#include "exec-all.h"
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
new file mode 100644
index 0000000..16d99b6
--- /dev/null
+++ b/target-openrisc/helper.h
@@ -0,0 +1,25 @@
+/*
+ * OpenRISC helper defines
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "def-helper.h"
+
+/* interrupt */
+DEF_HELPER_FLAGS_1(rfe, 0, void, env)
+
+#include "def-helper.h"
diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c
index 7a9ee0b..642da7d 100644
--- a/target-openrisc/interrupt.c
+++ b/target-openrisc/interrupt.c
@@ -27,4 +27,48 @@
void do_interrupt(CPUOpenRISCState *env)
{
+#ifndef 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;
+ }
+ }
+
+ /* For machine-state changed between user-mode and supervisor mode,
+ we need flush TLB when we enter&exit EXCP. */
+ 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->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu;
+ env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu;
+
+ if (env->exception_index > 0 && env->exception_index < EXCP_NR) {
+ env->pc = (env->exception_index << 8);
+ } else {
+ cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
+ }
+#endif
+
+ env->exception_index = -1;
}
diff --git a/target-openrisc/interrupt_helper.c b/target-openrisc/interrupt_helper.c
new file mode 100644
index 0000000..c5d033b
--- /dev/null
+++ b/target-openrisc/interrupt_helper.c
@@ -0,0 +1,57 @@
+/*
+ * OpenRISC interrupt helper routines
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ * Feng Gao <gf91597@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+
+void HELPER(rfe)(CPUOpenRISCState *env)
+{
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
+#ifndef CONFIG_USER_ONLY
+ int need_flush_tlb = (cpu->env.sr & (SR_SM | SR_IME | SR_DME)) ^
+ (cpu->env.esr & (SR_SM | SR_IME | SR_DME));
+#endif
+ cpu->env.pc = cpu->env.epcr;
+ cpu->env.npc = cpu->env.epcr;
+ cpu->env.sr = cpu->env.esr;
+
+#ifndef CONFIG_USER_ONLY
+ if (cpu->env.sr & SR_DME) {
+ cpu->env.tlb->cpu_openrisc_map_address_data =
+ &cpu_openrisc_get_phys_data;
+ } else {
+ cpu->env.tlb->cpu_openrisc_map_address_data =
+ &cpu_openrisc_get_phys_nommu;
+ }
+
+ if (cpu->env.sr & SR_IME) {
+ cpu->env.tlb->cpu_openrisc_map_address_code =
+ &cpu_openrisc_get_phys_code;
+ } else {
+ cpu->env.tlb->cpu_openrisc_map_address_code =
+ &cpu_openrisc_get_phys_nommu;
+ }
+
+ if (need_flush_tlb) {
+ tlb_flush(&cpu->env, 1);
+ }
+#endif
+ cpu->env.interrupt_request |= CPU_INTERRUPT_EXITTB;
+}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 04/15] target-or32: Add exception support
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
` (2 preceding siblings ...)
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 03/15] target-or32: Add interrupt support Jia Liu
@ 2012-07-13 4:34 ` Jia Liu
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 05/15] target-or32: Add int instruction helpers Jia Liu
` (10 subsequent siblings)
14 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:34 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add OpenRISC exception support.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-openrisc/Makefile.objs | 4 ++--
target-openrisc/exception.c | 27 +++++++++++++++++++++++++++
target-openrisc/exception.h | 28 ++++++++++++++++++++++++++++
target-openrisc/exception_helper.c | 29 +++++++++++++++++++++++++++++
target-openrisc/helper.h | 3 +++
5 files changed, 89 insertions(+), 2 deletions(-)
create mode 100644 target-openrisc/exception.c
create mode 100644 target-openrisc/exception.h
create mode 100644 target-openrisc/exception_helper.c
diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
index 74c4b8d..52d0158 100644
--- a/target-openrisc/Makefile.objs
+++ b/target-openrisc/Makefile.objs
@@ -1,3 +1,3 @@
obj-$(CONFIG_SOFTMMU) += machine.o
-obj-y += cpu.o interrupt.o mmu.o translate.o
-obj-y += interrupt_helper.o mmu_helper.o
+obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
+obj-y += exception_helper.o interrupt_helper.o mmu_helper.o
diff --git a/target-openrisc/exception.c b/target-openrisc/exception.c
new file mode 100644
index 0000000..67f6054
--- /dev/null
+++ b/target-openrisc/exception.c
@@ -0,0 +1,27 @@
+/*
+ * OpenRISC exception.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@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 "exception.h"
+
+void QEMU_NORETURN raise_exception(OpenRISCCPU *cpu, uint32_t excp)
+{
+ cpu->env.exception_index = excp;
+ cpu_loop_exit(&cpu->env);
+}
diff --git a/target-openrisc/exception.h b/target-openrisc/exception.h
new file mode 100644
index 0000000..902c89c
--- /dev/null
+++ b/target-openrisc/exception.h
@@ -0,0 +1,28 @@
+/*
+ * OpenRISC exception header.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_OPENRISC_EXCP_H
+#define QEMU_OPENRISC_EXCP_H
+
+#include "cpu.h"
+#include "qemu-common.h"
+
+void QEMU_NORETURN raise_exception(OpenRISCCPU *cpu, uint32_t excp);
+
+#endif /* QEMU_OPENRISC_EXCP_H */
diff --git a/target-openrisc/exception_helper.c b/target-openrisc/exception_helper.c
new file mode 100644
index 0000000..dfc6dfa
--- /dev/null
+++ b/target-openrisc/exception_helper.c
@@ -0,0 +1,29 @@
+/*
+ * OpenRISC exception helper routines
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "exception.h"
+
+void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp)
+{
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
+
+ raise_exception(cpu, excp);
+}
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index 16d99b6..4e2a49f 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -19,6 +19,9 @@
#include "def-helper.h"
+/* exception */
+DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)
+
/* interrupt */
DEF_HELPER_FLAGS_1(rfe, 0, void, env)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 05/15] target-or32: Add int instruction helpers
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
` (3 preceding siblings ...)
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 04/15] target-or32: Add exception support Jia Liu
@ 2012-07-13 4:34 ` Jia Liu
2012-07-13 9:18 ` Max Filippov
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 06/15] target-or32: Add float " Jia Liu
` (9 subsequent siblings)
14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:34 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add OpenRISC int instruction helpers.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-openrisc/Makefile.objs | 2 +-
target-openrisc/helper.h | 5 +++
target-openrisc/int_helper.c | 87 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 93 insertions(+), 1 deletion(-)
create mode 100644 target-openrisc/int_helper.c
diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
index 52d0158..e2a3715 100644
--- a/target-openrisc/Makefile.objs
+++ b/target-openrisc/Makefile.objs
@@ -1,3 +1,3 @@
obj-$(CONFIG_SOFTMMU) += machine.o
obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
-obj-y += exception_helper.o interrupt_helper.o mmu_helper.o
+obj-y += exception_helper.o int_helper.o interrupt_helper.o mmu_helper.o
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index 4e2a49f..c772951 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -22,6 +22,11 @@
/* 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(mul32, 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..45a9bfd
--- /dev/null
+++ b/target-openrisc/int_helper.c
@@ -0,0 +1,87 @@
+/*
+ * OpenRISC int helper routines
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ * Feng Gao <gf91597@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "exception.h"
+
+target_ulong HELPER(ff1)(target_ulong x)
+{
+ target_ulong n = 0;
+
+ if (x == 0) {
+ return 0;
+ }
+
+ for (n = 32; x; n--) {
+ x <<= 1;
+ }
+ return n+1;
+}
+
+target_ulong HELPER(fl1)(target_ulong x)
+{
+ target_ulong n = 0;
+
+ if (x == 0) {
+ return 0;
+ }
+
+ for (n = 0; x; n++) {
+ x >>= 1;
+ }
+ return n;
+}
+
+target_ulong HELPER(mul32)(CPUOpenRISCState *env,
+ target_ulong ra, target_ulong rb)
+{
+ uint64_t result;
+ target_ulong high, cy;
+
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
+
+ result = ra * rb;
+ /* regisiers in or32 is 32bit, so 32 is NOT a magic number.
+ or64 is not handled in this function, and not implement yet,
+ TARGET_LONG_BITS for or64 is 64, it will break this function,
+ so, we didn't use TARGET_LONG_BITS here. */
+ high = result >> 32;
+ cy = result >> (32 - 1);
+
+ if ((cy & 0x1) == 0x0) {
+ if (high == 0x0) {
+ return result;
+ }
+ }
+
+ if ((cy & 0x1) == 0x1) {
+ if (high == 0xffffffff) {
+ return result;
+ }
+ }
+
+ cpu->env.sr |= (SR_OV | SR_CY);
+ if (cpu->env.sr & SR_OVE) {
+ raise_exception(cpu, EXCP_RANGE);
+ }
+
+ return result;
+}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 06/15] target-or32: Add float instruction helpers
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
` (4 preceding siblings ...)
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 05/15] target-or32: Add int instruction helpers Jia Liu
@ 2012-07-13 4:34 ` Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 07/15] target-or32: Add instruction translation Jia Liu
` (8 subsequent siblings)
14 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:34 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add OpenRISC float instruction helpers.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-openrisc/Makefile.objs | 3 +-
target-openrisc/fpu_helper.c | 300 +++++++++++++++++++++++++++++++++++++++++
target-openrisc/helper.h | 33 +++++
3 files changed, 335 insertions(+), 1 deletion(-)
create mode 100644 target-openrisc/fpu_helper.c
diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
index e2a3715..926fc2f 100644
--- a/target-openrisc/Makefile.objs
+++ b/target-openrisc/Makefile.objs
@@ -1,3 +1,4 @@
obj-$(CONFIG_SOFTMMU) += machine.o
obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
-obj-y += exception_helper.o int_helper.o interrupt_helper.o mmu_helper.o
+obj-y += exception_helper.o fpu_helper.o int_helper.o \
+ interrupt_helper.o mmu_helper.o
diff --git a/target-openrisc/fpu_helper.c b/target-openrisc/fpu_helper.c
new file mode 100644
index 0000000..c2520a4
--- /dev/null
+++ b/target-openrisc/fpu_helper.c
@@ -0,0 +1,300 @@
+/*
+ * OpenRISC float helper routines
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ * Feng Gao <gf91597@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "exception.h"
+
+static inline uint32_t ieee_ex_to_openrisc(OpenRISCCPU *cpu, int fexcp)
+{
+ int ret = 0;
+ if (fexcp) {
+ if (fexcp & float_flag_invalid) {
+ cpu->env.fpcsr |= FPCSR_IVF;
+ ret = 1;
+ }
+ if (fexcp & float_flag_overflow) {
+ cpu->env.fpcsr |= FPCSR_OVF;
+ ret = 1;
+ }
+ if (fexcp & float_flag_underflow) {
+ cpu->env.fpcsr |= FPCSR_UNF;
+ ret = 1;
+ }
+ if (fexcp & float_flag_divbyzero) {
+ cpu->env.fpcsr |= FPCSR_DZF;
+ ret = 1;
+ }
+ if (fexcp & float_flag_inexact) {
+ cpu->env.fpcsr |= FPCSR_IXF;
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
+static inline void update_fpcsr(OpenRISCCPU *cpu)
+{
+ int tmp = ieee_ex_to_openrisc(cpu,
+ get_float_exception_flags(&cpu->env.fp_status));
+
+ SET_FP_CAUSE(cpu->env.fpcsr, tmp);
+ if ((GET_FP_ENABLE(cpu->env.fpcsr) & tmp) &&
+ (cpu->env.fpcsr & FPCSR_FPEE)) {
+ helper_exception(&cpu->env, EXCP_FPE);
+ } else {
+ UPDATE_FP_FLAGS(cpu->env.fpcsr, tmp);
+ }
+}
+
+uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val)
+{
+ uint64_t itofd;
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
+
+ set_float_exception_flags(0, &cpu->env.fp_status);
+ itofd = int32_to_float64(val, &cpu->env.fp_status);
+ update_fpcsr(cpu);
+
+ return itofd;
+}
+
+uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val)
+{
+ uint32_t itofs;
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
+
+ set_float_exception_flags(0, &cpu->env.fp_status);
+ itofs = int32_to_float32(val, &cpu->env.fp_status);
+ update_fpcsr(cpu);
+
+ return itofs;
+}
+
+uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val)
+{
+ uint64_t ftoid;
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
+
+ set_float_exception_flags(0, &cpu->env.fp_status);
+ ftoid = float32_to_int64(val, &cpu->env.fp_status);
+ update_fpcsr(cpu);
+
+ return ftoid;
+}
+
+uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val)
+{
+ uint32_t ftois;
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
+
+ set_float_exception_flags(0, &cpu->env.fp_status);
+ ftois = float32_to_int32(val, &cpu->env.fp_status);
+ update_fpcsr(cpu);
+
+ return ftois;
+}
+
+#define FLOAT_OP(name, p) void helper_float_##_##p(void)
+
+#define FLOAT_CALC(name) \
+uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
+ uint64_t fdt0, uint64_t fdt1) \
+{ \
+ uint64_t result; \
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
+ set_float_exception_flags(0, &cpu->env.fp_status); \
+ result = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status); \
+ update_fpcsr(cpu); \
+ return result; \
+} \
+ \
+uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
+ uint32_t fdt0, uint32_t fdt1) \
+{ \
+ uint32_t result; \
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
+ set_float_exception_flags(0, &cpu->env.fp_status); \
+ result = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status); \
+ update_fpcsr(cpu); \
+ return result; \
+} \
+
+FLOAT_CALC(add)
+FLOAT_CALC(sub)
+FLOAT_CALC(mul)
+FLOAT_CALC(div)
+FLOAT_CALC(rem)
+#undef FLOAT_CALC
+
+#define FLOAT_TERNOP(name1, name2) \
+uint64_t helper_float_ ## name1 ## name2 ## _d(CPUOpenRISCState *env, \
+ uint64_t fdt0, \
+ uint64_t fdt1) \
+{ \
+ uint64_t result, temp, hi, lo; \
+ uint32_t val1, val2; \
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
+ hi = env->fpmaddhi; \
+ lo = env->fpmaddlo; \
+ set_float_exception_flags(0, &cpu->env.fp_status); \
+ result = float64_ ## name1(fdt0, fdt1, &cpu->env.fp_status); \
+ lo &= 0xffffffff; \
+ hi &= 0xffffffff; \
+ temp = (hi << 32) | lo; \
+ result = float64_ ## name2(result, temp, &cpu->env.fp_status); \
+ val1 = result >> 32; \
+ val2 = (uint32_t) (result & 0xffffffff); \
+ update_fpcsr(cpu); \
+ cpu->env.fpmaddlo = val2; \
+ cpu->env.fpmaddhi = val1; \
+ return 0; \
+} \
+ \
+uint32_t helper_float_ ## name1 ## name2 ## _s(CPUOpenRISCState *env, \
+ uint32_t fdt0, uint32_t fdt1) \
+{ \
+ uint64_t result, temp, hi, lo; \
+ uint32_t val1, val2; \
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
+ hi = cpu->env.fpmaddhi; \
+ lo = cpu->env.fpmaddlo; \
+ set_float_exception_flags(0, &cpu->env.fp_status); \
+ result = float64_ ## name1(fdt0, fdt1, &cpu->env.fp_status); \
+ temp = (hi << 32) | lo; \
+ result = float64_ ## name2(result, temp, &cpu->env.fp_status); \
+ val1 = result >> 32; \
+ val2 = (uint32_t) (result & 0xffffffff); \
+ update_fpcsr(cpu); \
+ cpu->env.fpmaddlo = val2; \
+ cpu->env.fpmaddhi = val1; \
+ return 0; \
+}
+
+FLOAT_TERNOP(mul, add)
+#undef FLOAT_TERNOP
+
+
+#define FLOAT_CMP(name) \
+uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
+ uint64_t fdt0, uint64_t fdt1) \
+{ \
+ int res; \
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
+ set_float_exception_flags(0, &cpu->env.fp_status); \
+ res = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status); \
+ update_fpcsr(cpu); \
+ return res; \
+} \
+ \
+uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
+ uint32_t fdt0, uint32_t fdt1)\
+{ \
+ int res; \
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
+ set_float_exception_flags(0, &cpu->env.fp_status); \
+ res = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status); \
+ update_fpcsr(cpu); \
+ return res; \
+}
+
+FLOAT_CMP(le)
+FLOAT_CMP(eq)
+FLOAT_CMP(lt)
+#undef FLOAT_CMP
+
+
+#define FLOAT_CMPNE(name) \
+uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
+ uint64_t fdt0, uint64_t fdt1) \
+{ \
+ int res; \
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
+ set_float_exception_flags(0, &cpu->env.fp_status); \
+ res = !float64_eq_quiet(fdt0, fdt1, &cpu->env.fp_status); \
+ update_fpcsr(cpu); \
+ return res; \
+} \
+ \
+uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
+ uint32_t fdt0, uint32_t fdt1) \
+{ \
+ int res; \
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
+ set_float_exception_flags(0, &cpu->env.fp_status); \
+ res = !float32_eq_quiet(fdt0, fdt1, &cpu->env.fp_status); \
+ update_fpcsr(cpu); \
+ return res; \
+}
+
+FLOAT_CMPNE(ne)
+#undef FLOAT_CMPNE
+
+#define FLOAT_CMPGT(name) \
+uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
+ uint64_t fdt0, uint64_t fdt1) \
+{ \
+ int res; \
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
+ set_float_exception_flags(0, &cpu->env.fp_status); \
+ res = !float64_le(fdt0, fdt1, &cpu->env.fp_status); \
+ update_fpcsr(cpu); \
+ return res; \
+} \
+ \
+uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
+ uint32_t fdt0, uint32_t fdt1) \
+{ \
+ int res; \
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
+ set_float_exception_flags(0, &cpu->env.fp_status); \
+ res = !float32_le(fdt0, fdt1, &cpu->env.fp_status); \
+ update_fpcsr(cpu); \
+ return res; \
+}
+FLOAT_CMPGT(gt)
+#undef FLOAT_CMPGT
+
+#define FLOAT_CMPGE(name) \
+uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
+ uint64_t fdt0, uint64_t fdt1) \
+{ \
+ int res; \
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
+ set_float_exception_flags(0, &cpu->env.fp_status); \
+ res = !float64_lt(fdt0, fdt1, &cpu->env.fp_status); \
+ update_fpcsr(cpu); \
+ return res; \
+} \
+ \
+uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
+ uint32_t fdt0, uint32_t fdt1) \
+{ \
+ int res; \
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
+ set_float_exception_flags(0, &cpu->env.fp_status); \
+ res = !float32_lt(fdt0, fdt1, &cpu->env.fp_status); \
+ update_fpcsr(cpu); \
+ return res; \
+}
+
+FLOAT_CMPGE(ge)
+#undef FLOAT_CMPGE
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index c772951..6eb259a 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -22,6 +22,39 @@
/* exception */
DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)
+/* float */
+DEF_HELPER_FLAGS_2(itofd, 0, i64, env, i64)
+DEF_HELPER_FLAGS_2(itofs, 0, i32, env, i32)
+DEF_HELPER_FLAGS_2(ftoid, 0, i64, env, i64)
+DEF_HELPER_FLAGS_2(ftois, 0, i32, env, i32)
+
+#define FOP_MADD(op) \
+DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \
+DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
+FOP_MADD(muladd)
+#undef FOP_MADD
+
+#define FOP_CALC(op) \
+DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \
+DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
+FOP_CALC(add)
+FOP_CALC(sub)
+FOP_CALC(mul)
+FOP_CALC(div)
+FOP_CALC(rem)
+#undef FOP_CALC
+
+#define FOP_CMP(op) \
+DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \
+DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
+FOP_CMP(eq)
+FOP_CMP(lt)
+FOP_CMP(le)
+FOP_CMP(ne)
+FOP_CMP(gt)
+FOP_CMP(ge)
+#undef FOP_CMP
+
/* int */
DEF_HELPER_FLAGS_1(ff1, 0, tl, tl)
DEF_HELPER_FLAGS_1(fl1, 0, tl, tl)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 07/15] target-or32: Add instruction translation
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
` (5 preceding siblings ...)
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 06/15] target-or32: Add float " Jia Liu
@ 2012-07-13 4:35 ` Jia Liu
2012-07-13 8:09 ` Peter Maydell
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 08/15] target-or32: Add PIC support Jia Liu
` (7 subsequent siblings)
14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:35 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add OpenRISC instruction tanslation routines.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-openrisc/translate.c | 1700 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1700 insertions(+)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index a2b9b4f..ed25604 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -26,6 +26,10 @@
#include "qemu-log.h"
#include "config.h"
+#include "helper.h"
+#define GEN_HELPER 1
+#include "helper.h"
+
#define OPENRISC_DISAS
#ifdef OPENRISC_DISAS
@@ -34,14 +38,1710 @@
# define LOG_DIS(...) do { } while (0)
#endif
+typedef struct DisasContext {
+ TranslationBlock *tb;
+ target_ulong pc, ppc, npc;
+ uint32_t tb_flags, synced_flags, flags;
+ uint32_t is_jmp;
+ uint32_t mem_idx;
+ int singlestep_enabled;
+ uint32_t delayed_branch;
+} DisasContext;
+
+static TCGv_ptr cpu_env;
+static TCGv cpu_sr;
+static TCGv cpu_R[32];
+static TCGv cpu_pc;
+static TCGv jmp_pc; /* l.jr/l.jalr temp pc */
+static TCGv cpu_npc;
+static TCGv cpu_ppc;
+static TCGv_i32 env_btaken; /* bf/bnf , F flag taken */
+static TCGv_i32 fpcsr;
+static TCGv machi, maclo;
+static TCGv fpmaddhi, fpmaddlo;
+static TCGv_i32 env_flags;
+#include "gen-icount.h"
+
void openrisc_translate_init(void)
{
+ static const char * const regnames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+ };
+ int i;
+
+ cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+ cpu_sr = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenRISCState, sr), "sr");
+ env_flags = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUOpenRISCState, flags),
+ "flags");
+ cpu_pc = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenRISCState, pc), "pc");
+ cpu_npc = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenRISCState, npc), "npc");
+ cpu_ppc = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenRISCState, ppc), "ppc");
+ jmp_pc = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
+ env_btaken = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUOpenRISCState, btaken),
+ "btaken");
+ fpcsr = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUOpenRISCState, fpcsr),
+ "fpcsr");
+ machi = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenRISCState, machi),
+ "machi");
+ maclo = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenRISCState, maclo),
+ "maclo");
+ fpmaddhi = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenRISCState, fpmaddhi),
+ "fpmaddhi");
+ fpmaddlo = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenRISCState, fpmaddlo),
+ "fpmaddlo");
+ for (i = 0; i < 32; i++) {
+ cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenRISCState, gpr[i]),
+ regnames[i]);
+ }
+#define GEN_HELPER 2
+#include "helper.h"
+}
+
+/* Writeback SR_F transaltion-space to execution-space. */
+static inline void wb_SR_F(void)
+{
+ int label;
+
+ label = gen_new_label();
+ tcg_gen_andi_tl(cpu_sr, cpu_sr, ~SR_F);
+ tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, label);
+ tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_F);
+ gen_set_label(label);
+}
+
+static inline int zero_extend(unsigned int val, int width)
+{
+ return val & ((1 << width) - 1);
+}
+
+static inline int sign_extend(unsigned int val, int width)
+{
+ int sval;
+
+ /* LSL */
+ val <<= TARGET_LONG_BITS - width;
+ sval = val;
+ /* ASR. */
+ sval >>= TARGET_LONG_BITS - width;
+ return sval;
+}
+
+static inline void gen_sync_flags(DisasContext *dc)
+{
+ /* Sync the tb dependent flag between translate and runtime. */
+ if (dc->tb_flags != dc->synced_flags) {
+ tcg_gen_movi_tl(env_flags, dc->tb_flags);
+ dc->synced_flags = dc->tb_flags;
+ }
+}
+
+static void gen_exception(DisasContext *dc, unsigned int excp)
+{
+ TCGv_i32 tmp = tcg_const_i32(excp);
+ gen_helper_exception(cpu_env, tmp);
+ tcg_temp_free_i32(tmp);
+}
+
+static void gen_illegal_exception(DisasContext *dc)
+{
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ gen_exception(dc, EXCP_ILLEGAL);
+ dc->is_jmp = DISAS_UPDATE;
+}
+
+/* not used yet, open it when we need or64. */
+/*#ifdef TARGET_OPENRISC64
+static void check_ob64s(DisasContext *dc)
+{
+ if (!(dc->flags & CPUCFGR_OB64S)) {
+ gen_illegal_exception(dc);
+ }
+}
+
+static void check_of64s(DisasContext *dc)
+{
+ if (!(dc->flags & CPUCFGR_OF64S)) {
+ gen_illegal_exception(dc);
+ }
+}
+
+static void check_ov64s(DisasContext *dc)
+{
+ if (!(dc->flags & CPUCFGR_OV64S)) {
+ gen_illegal_exception(dc);
+ }
+}
+#endif*/
+
+static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
+{
+ TranslationBlock *tb;
+ tb = dc->tb;
+ if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
+ likely(!dc->singlestep_enabled)) {
+ tcg_gen_movi_tl(cpu_pc, dest);
+ tcg_gen_goto_tb(n);
+ tcg_gen_exit_tb((tcg_target_long)tb + n);
+ } else {
+ tcg_gen_movi_tl(cpu_pc, dest);
+ if (dc->singlestep_enabled) {
+ gen_exception(dc, EXCP_DEBUG);
+ }
+ tcg_gen_exit_tb(0);
+ }
+}
+
+static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
+{
+ target_ulong tmp_pc;
+ int lab = gen_new_label();
+ TCGv sr_f = tcg_temp_new();
+ /* N26, 26bits imm */
+ tmp_pc = sign_extend((imm<<2), 26) + dc->pc;
+ tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+
+ if (op0 == 0x00) { /* l.j */
+ tcg_gen_movi_tl(jmp_pc, tmp_pc);
+ } else if (op0 == 0x01) { /* l.jal */
+ tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+ tcg_gen_movi_tl(jmp_pc, tmp_pc);
+ } else if (op0 == 0x03) { /* l.bnf */
+ tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, sr_f, SR_F, lab);
+ tcg_gen_movi_tl(jmp_pc, tmp_pc);
+ gen_set_label(lab);
+ } else if (op0 == 0x04) { /* l.bf */
+ tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+ tcg_gen_brcondi_i32(TCG_COND_NE, sr_f, SR_F, lab);
+ tcg_gen_movi_tl(jmp_pc, tmp_pc);
+ gen_set_label(lab);
+ } else if (op0 == 0x11) { /* l.jr */
+ tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
+ } else if (op0 == 0x12) { /* l.jalr */
+ tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+ tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
+ } else {
+ gen_illegal_exception(dc);
+ }
+
+ tcg_temp_free(sr_f);
+ dc->delayed_branch = 2;
+ dc->tb_flags |= D_FLAG;
+ gen_sync_flags(dc);
+}
+
+static inline uint32_t field(uint32_t val, int start, int length)
+{
+ val >>= start;
+ val &= ~(~0 << length);
+ return val;
+}
+
+static void dec_calc(DisasContext *dc, 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);
+ {
+ int lab = gen_new_label();
+ TCGv_i64 ta = tcg_temp_new_i64();
+ TCGv_i64 tb = tcg_temp_new_i64();
+ TCGv_i64 td = tcg_temp_local_new_i64();
+ TCGv_i32 res = tcg_temp_local_new_i32();
+ TCGv_i32 sr_ove = tcg_temp_local_new_i32();
+ tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
+ tcg_gen_extu_i32_i64(tb, cpu_R[rb]);
+ tcg_gen_add_i64(td, ta, tb);
+ tcg_gen_trunc_i64_i32(res, td);
+ tcg_gen_shri_i64(td, td, 31);
+ tcg_gen_andi_i64(td, td, 0x3);
+ /* Jump to lab when no overflow. */
+ tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
+ tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
+ tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
+ tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
+ tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
+ gen_exception(dc, EXCP_RANGE);
+ gen_set_label(lab);
+ tcg_gen_mov_i32(cpu_R[rd], res);
+ tcg_temp_free_i64(ta);
+ tcg_temp_free_i64(tb);
+ tcg_temp_free_i64(td);
+ tcg_temp_free_i32(res);
+ tcg_temp_free_i32(sr_ove);
+ }
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0001: /* l.addc */
+ switch (op1) {
+ case 0x00:
+ LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
+ {
+ int lab = gen_new_label();
+ TCGv_i64 ta = tcg_temp_new_i64();
+ TCGv_i64 tb = tcg_temp_new_i64();
+ TCGv_i64 tcy = tcg_temp_local_new_i64();
+ TCGv_i64 td = tcg_temp_local_new_i64();
+ TCGv_i32 res = tcg_temp_local_new_i32();
+ TCGv_i32 sr_cy = tcg_temp_local_new_i32();
+ TCGv_i32 sr_ove = tcg_temp_local_new_i32();
+ tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
+ tcg_gen_extu_i32_i64(tb, cpu_R[rb]);
+ tcg_gen_andi_i32(sr_cy, cpu_sr, SR_CY);
+ tcg_gen_extu_i32_i64(tcy, sr_cy);
+ tcg_gen_shri_i64(tcy, tcy, 10);
+ tcg_gen_add_i64(td, ta, tb);
+ tcg_gen_add_i64(td, td, tcy);
+ tcg_gen_trunc_i64_i32(res, td);
+ tcg_gen_shri_i64(td, td, 32);
+ tcg_gen_andi_i64(td, td, 0x3);
+ /* Jump to lab when no overflow. */
+ tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
+ tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
+ tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
+ tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
+ tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
+ gen_exception(dc, EXCP_RANGE);
+ gen_set_label(lab);
+ tcg_gen_mov_i32(cpu_R[rd], res);
+ tcg_temp_free_i64(ta);
+ tcg_temp_free_i64(tb);
+ tcg_temp_free_i64(tcy);
+ tcg_temp_free_i64(td);
+ tcg_temp_free_i32(res);
+ tcg_temp_free_i32(sr_cy);
+ tcg_temp_free_i32(sr_ove);
+ }
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0002: /* l.sub */
+ switch (op1) {
+ case 0x00:
+ LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
+ {
+ int lab = gen_new_label();
+ TCGv_i64 ta = tcg_temp_new_i64();
+ TCGv_i64 tb = tcg_temp_new_i64();
+ TCGv_i64 td = tcg_temp_local_new_i64();
+ TCGv_i32 res = tcg_temp_local_new_i32();
+ TCGv_i32 sr_ove = tcg_temp_local_new_i32();
+
+ tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
+ tcg_gen_extu_i32_i64(tb, cpu_R[rb]);
+ tcg_gen_sub_i64(td, ta, tb);
+ tcg_gen_trunc_i64_i32(res, td);
+ tcg_gen_shri_i64(td, td, 31);
+ tcg_gen_andi_i64(td, td, 0x3);
+ /* Jump to lab when no overflow. */
+ tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
+ tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
+ tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
+ tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
+ tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
+ gen_exception(dc, EXCP_RANGE);
+ gen_set_label(lab);
+ tcg_gen_mov_i32(cpu_R[rd], res);
+ tcg_temp_free_i64(ta);
+ tcg_temp_free_i64(tb);
+ tcg_temp_free_i64(td);
+ tcg_temp_free_i32(res);
+ tcg_temp_free_i32(sr_ove);
+ }
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0003: /* l.and */
+ switch (op1) {
+ case 0x00:
+ LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0004: /* l.or */
+ switch (op1) {
+ case 0x00:
+ LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0005:
+ switch (op1) {
+ case 0x00: /* l.xor */
+ LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0006:
+ switch (op1) {
+ case 0x03: /* l.mul */
+ LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb);
+ if (ra != 0 && rb != 0) {
+ gen_helper_mul32(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ } else {
+ tcg_gen_movi_tl(cpu_R[rd], 0x0);
+ }
+ break;
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0009:
+ switch (op1) {
+ case 0x03: /* l.div */
+ LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
+ {
+ int lab0 = gen_new_label();
+ int lab1 = gen_new_label();
+ int lab2 = gen_new_label();
+ int lab3 = gen_new_label();
+ TCGv_i32 sr_ove = tcg_temp_local_new_i32();
+ if (rb == 0) {
+ tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY));
+ tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+ tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0);
+ gen_exception(dc, EXCP_RANGE);
+ gen_set_label(lab0);
+ } else {
+ tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[rb],
+ 0x00000000, lab1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[ra],
+ 0x80000000, lab2);
+ tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb],
+ 0xffffffff, lab2);
+ gen_set_label(lab1);
+ tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY));
+ tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+ tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab3);
+ gen_exception(dc, EXCP_RANGE);
+ gen_set_label(lab2);
+ tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ gen_set_label(lab3);
+ }
+ tcg_temp_free_i32(sr_ove);
+ }
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x000a:
+ switch (op1) {
+ case 0x03: /* l.divu */
+ LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb);
+ {
+ int lab0 = gen_new_label();
+ int lab1 = gen_new_label();
+ int lab2 = gen_new_label();
+ TCGv_i32 sr_ove = tcg_temp_local_new_i32();
+ if (rb == 0) {
+ tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY));
+ tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+ tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0);
+ gen_exception(dc, EXCP_RANGE);
+ gen_set_label(lab0);
+ } else {
+ tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb],
+ 0x00000000, lab1);
+ tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY));
+ tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+ tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab2);
+ gen_exception(dc, EXCP_RANGE);
+ gen_set_label(lab1);
+ tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ gen_set_label(lab2);
+ }
+ tcg_temp_free_i32(sr_ove);
+ }
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x000b:
+ switch (op1) {
+ case 0x03: /* l.mulu */
+ LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb);
+ if (rb != 0 && ra != 0) {
+ TCGv_i64 result = tcg_temp_local_new_i64();
+ TCGv_i64 tra = tcg_temp_local_new_i64();
+ TCGv_i64 trb = tcg_temp_local_new_i64();
+ TCGv_i64 high = tcg_temp_new_i64();
+ TCGv_i32 sr_ove = tcg_temp_local_new_i32();
+ int lab = gen_new_label();
+ /* Calculate the each result. */
+ tcg_gen_extu_i32_i64(tra, cpu_R[ra]);
+ tcg_gen_extu_i32_i64(trb, cpu_R[rb]);
+ tcg_gen_mul_i64(result, tra, trb);
+ tcg_temp_free_i64(tra);
+ tcg_temp_free_i64(trb);
+ tcg_gen_shri_i64(high, result, TARGET_LONG_BITS);
+ /* Overflow or not. */
+ tcg_gen_brcondi_i64(TCG_COND_EQ, high, 0x00000000, lab);
+ tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY));
+ tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+ tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab);
+ gen_exception(dc, EXCP_RANGE);
+ gen_set_label(lab);
+ tcg_temp_free_i64(high);
+ tcg_gen_trunc_i64_tl(cpu_R[rd], result);
+ tcg_temp_free_i64(result);
+ tcg_temp_free_i32(sr_ove);
+ } else {
+ tcg_gen_movi_tl(cpu_R[rd], 0);
+ }
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x000e:
+ switch (op1) {
+ case 0x00: /* l.cmov */
+ LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb);
+ {
+ int lab = gen_new_label();
+ TCGv res = tcg_temp_local_new();
+ TCGv sr_f = tcg_temp_new();
+ tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+ tcg_gen_mov_tl(res, cpu_R[rb]);
+ tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
+ tcg_gen_mov_tl(res, cpu_R[ra]);
+ gen_set_label(lab);
+ tcg_gen_mov_tl(cpu_R[rd], res);
+ tcg_temp_free(sr_f);
+ tcg_temp_free(res);
+ }
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x000f:
+ switch (op1) {
+ case 0x00: /* l.ff1 */
+ LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_ff1(cpu_R[rd], cpu_R[ra]);
+ break;
+ case 0x01: /* l.fl1 */
+ LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_fl1(cpu_R[rd], cpu_R[ra]);
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x0008:
+ switch (op1) {
+ case 0x00:
+ switch (op2) {
+ case 0x00: /* l.sll */
+ LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ break;
+ case 0x01: /* l.srl */
+ LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ break;
+ case 0x02: /* l.sra */
+ LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ break;
+ case 0x03: /* l.ror */
+ LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb);
+ tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x000c:
+ switch (op1) {
+ case 0x00:
+ switch (op2) {
+ case 0x00: /* l.exths */
+ LOG_DIS("l.exths r%d, r%d\n", rd, ra);
+ tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]);
+ break;
+ case 0x01: /* l.extbs */
+ LOG_DIS("l.extbs r%d, r%d\n", rd, ra);
+ tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]);
+ break;
+ case 0x02: /* l.exthz */
+ LOG_DIS("l.exthz r%d, r%d\n", rd, ra);
+ tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]);
+ break;
+ case 0x03: /* l.extbz */
+ LOG_DIS("l.extbz r%d, r%d\n", rd, ra);
+ tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]);
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x000d:
+ switch (op1) {
+ case 0x00:
+ switch (op2) {
+ case 0x00: /* l.extws */
+ LOG_DIS("l.extws r%d, r%d\n", rd, ra);
+ tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]);
+ break;
+ case 0x01: /* l.extwz */
+ LOG_DIS("l.extwz r%d, r%d\n", rd, ra);
+ tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]);
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+}
+
+static void dec_misc(DisasContext *dc, uint32_t insn)
+{
+ uint32_t op0, op1;
+ uint32_t ra, rb, rd;
+#ifdef OPENRISC_DISAS
+ uint32_t L6, K5;
+#endif
+ uint32_t 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);
+#ifdef OPENRISC_DISAS
+ L6 = field(insn, 5, 6);
+ K5 = field(insn, 0, 5);
+#endif
+ I16 = field(insn, 0, 16);
+ I5 = field(insn, 21, 5);
+ I11 = field(insn, 0, 11);
+ N26 = field(insn, 0, 26);
+ tmp = (I5<<11) + I11;
+
+ switch (op0) {
+ case 0x00: /* l.j */
+ LOG_DIS("l.j %d\n", N26);
+ gen_jump(dc, N26, 0, op0);
+ break;
+
+ case 0x01: /* l.jal */
+ LOG_DIS("l.jal %d\n", N26);
+ gen_jump(dc, N26, 0, op0);
+ break;
+
+ case 0x03: /* l.bnf */
+ LOG_DIS("l.bnf %d\n", N26);
+ gen_jump(dc, N26, 0, op0);
+ break;
+
+ case 0x04: /* l.bf */
+ LOG_DIS("l.bf %d\n", N26);
+ gen_jump(dc, N26, 0, op0);
+ break;
+
+ case 0x05:
+ switch (op1) {
+ case 0x01: /* l.nop */
+ LOG_DIS("l.nop %d\n", I16);
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ break;
+
+ case 0x11: /* l.jr */
+ LOG_DIS("l.jr r%d\n", rb);
+ gen_jump(dc, 0, rb, op0);
+ break;
+
+ case 0x12: /* l.jalr */
+ LOG_DIS("l.jalr r%d\n", rb);
+ gen_jump(dc, 0, rb, op0);
+ break;
+
+ case 0x13: /* l.maci */
+ LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I11);
+ {
+ TCGv_i64 t1 = tcg_temp_new_i64();
+ TCGv_i64 t2 = tcg_temp_new_i64();
+ TCGv_i32 dst = tcg_temp_new_i32();
+ TCGv ttmp = tcg_const_tl(tmp);
+ tcg_gen_mul_tl(dst, cpu_R[ra], ttmp);
+ tcg_gen_ext_i32_i64(t1, dst);
+ tcg_gen_concat_i32_i64(t2, maclo, machi);
+ tcg_gen_add_i64(t2, t2, t1);
+ tcg_gen_trunc_i64_i32(maclo, t2);
+ tcg_gen_shri_i64(t2, t2, 32);
+ tcg_gen_trunc_i64_i32(machi, t2);
+ tcg_temp_free_i32(dst);
+ tcg_temp_free(ttmp);
+ tcg_temp_free_i64(t1);
+ tcg_temp_free_i64(t2);
+ }
+ break;
+
+ case 0x09: /* l.rfe */
+ LOG_DIS("l.rfe\n");
+ {
+ gen_helper_rfe(cpu_env);
+ dc->is_jmp = DISAS_UPDATE;
+ }
+ break;
+
+ case 0x1c: /* l.cust1 */
+ LOG_DIS("l.cust1\n");
+ break;
+
+ case 0x1d: /* l.cust2 */
+ LOG_DIS("l.cust2\n");
+ break;
+
+ case 0x1e: /* l.cust3 */
+ LOG_DIS("l.cust3\n");
+ break;
+
+ case 0x1f: /* l.cust4 */
+ LOG_DIS("l.cust4\n");
+ break;
+
+ case 0x3c: /* l.cust5 */
+ LOG_DIS("l.cust5 r%d, r%d, r%d, %d, %d\n", rd, ra, rb, L6, K5);
+ break;
+
+ case 0x3d: /* l.cust6 */
+ LOG_DIS("l.cust6\n");
+ break;
+
+ case 0x3e: /* l.cust7 */
+ LOG_DIS("l.cust7\n");
+ break;
+
+ case 0x3f: /* l.cust8 */
+ LOG_DIS("l.cust8\n");
+ break;
+
+/* not used yet, open it when we need or64. */
+/*#ifdef TARGET_OPENRISC64
+ case 0x20: l.ld
+ LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16);
+ {
+ check_ob64s(dc);
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ tcg_gen_addi_i64(t0, cpu_R[ra], sign_extend(I16, 16));
+ tcg_gen_qemu_ld64(cpu_R[rd], t0, dc->mem_idx);
+ tcg_temp_free_i64(t0);
+ }
+ break;
+#endif*/
+
+ case 0x21: /* l.lwz */
+ LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16);
+ {
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+ tcg_gen_qemu_ld32u(cpu_R[rd], t0, dc->mem_idx);
+ tcg_temp_free(t0);
+ }
+ break;
+
+ case 0x22: /* l.lws */
+ LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16);
+ {
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+ tcg_gen_qemu_ld32s(cpu_R[rd], t0, dc->mem_idx);
+ tcg_temp_free(t0);
+ }
+ break;
+
+ case 0x23: /* l.lbz */
+ LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16);
+ {
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+ tcg_gen_qemu_ld8u(cpu_R[rd], t0, dc->mem_idx);
+ tcg_temp_free(t0);
+ }
+ break;
+
+ case 0x24: /* l.lbs */
+ LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16);
+ {
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+ tcg_gen_qemu_ld8s(cpu_R[rd], t0, dc->mem_idx);
+ tcg_temp_free(t0);
+ }
+ break;
+
+ case 0x25: /* l.lhz */
+ LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16);
+ {
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+ tcg_gen_qemu_ld16u(cpu_R[rd], t0, dc->mem_idx);
+ tcg_temp_free(t0);
+ }
+ break;
+
+ case 0x26: /* l.lhs */
+ LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16);
+ {
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
+ tcg_gen_qemu_ld16s(cpu_R[rd], t0, dc->mem_idx);
+ tcg_temp_free(t0);
+ }
+ break;
+
+ case 0x27: /* l.addi */
+ LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
+ {
+ int lab = gen_new_label();
+ TCGv_i64 ta = tcg_temp_new_i64();
+ TCGv_i64 td = tcg_temp_local_new_i64();
+ TCGv_i32 res = tcg_temp_local_new_i32();
+ TCGv_i32 sr_ove = tcg_temp_local_new_i32();
+ tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
+ tcg_gen_addi_i64(td, ta, sign_extend(I16, 16));
+ tcg_gen_trunc_i64_i32(res, td);
+ tcg_gen_shri_i64(td, td, 32);
+ tcg_gen_andi_i64(td, td, 0x3);
+ /* Jump to lab when no overflow. */
+ tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
+ tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
+ tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
+ tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
+ tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
+ gen_exception(dc, EXCP_RANGE);
+ gen_set_label(lab);
+ tcg_gen_mov_i32(cpu_R[rd], res);
+ tcg_temp_free_i64(ta);
+ tcg_temp_free_i64(td);
+ tcg_temp_free_i32(res);
+ tcg_temp_free_i32(sr_ove);
+ }
+ break;
+
+ case 0x28: /* l.addic */
+ LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16);
+ {
+ int lab = gen_new_label();
+ TCGv_i64 ta = tcg_temp_new_i64();
+ TCGv_i64 td = tcg_temp_local_new_i64();
+ TCGv_i64 tcy = tcg_temp_local_new_i64();
+ TCGv_i32 res = tcg_temp_local_new_i32();
+ TCGv_i32 sr_cy = tcg_temp_local_new_i32();
+ TCGv_i32 sr_ove = tcg_temp_local_new_i32();
+ tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
+ tcg_gen_andi_i32(sr_cy, cpu_sr, SR_CY);
+ tcg_gen_shri_i32(sr_cy, sr_cy, 10);
+ tcg_gen_extu_i32_i64(tcy, sr_cy);
+ tcg_gen_addi_i64(td, ta, sign_extend(I16, 16));
+ tcg_gen_add_i64(td, td, tcy);
+ tcg_gen_trunc_i64_i32(res, td);
+ tcg_gen_shri_i64(td, td, 32);
+ tcg_gen_andi_i64(td, td, 0x3);
+ /* Jump to lab when no overflow. */
+ tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
+ tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
+ tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
+ tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
+ tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
+ gen_exception(dc, EXCP_RANGE);
+ gen_set_label(lab);
+ tcg_gen_mov_i32(cpu_R[rd], res);
+ tcg_temp_free_i64(ta);
+ tcg_temp_free_i64(td);
+ tcg_temp_free_i64(tcy);
+ tcg_temp_free_i32(res);
+ tcg_temp_free_i32(sr_cy);
+ tcg_temp_free_i32(sr_ove);
+ }
+ 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, I16);
+ tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], zero_extend(I16, 16));
+ break;
+
+ case 0x2b: /* l.xori */
+ LOG_DIS("l.xori r%d, r%d, %d\n", rd, ra, I16);
+ tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], sign_extend(I16, 16));
+ break;
+
+ case 0x2c: /* l.muli */
+ LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16);
+ if (ra != 0 && I16 != 0) {
+ TCGv_i32 im = tcg_const_i32(I16);
+ gen_helper_mul32(cpu_R[rd], cpu_env, cpu_R[ra], im);
+ tcg_temp_free_i32(im);
+ } else {
+ tcg_gen_movi_tl(cpu_R[rd], 0x0);
+ }
+ break;
+
+ case 0x2d: /* l.mfspr */
+ LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
+ break;
+
+ case 0x30: /* l.mtspr */
+ LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+ break;
+
+/* not used yet, open it when we need or64. */
+/*#ifdef TARGET_OPENRISC64
+ case 0x34: l.sd
+ LOG_DIS("l.sd %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+ {
+ check_ob64s(dc);
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+ tcg_gen_qemu_st64(cpu_R[rb], t0, dc->mem_idx);
+ tcg_temp_free_i64(t0);
+ }
+ break;
+#endif*/
+
+ case 0x35: /* l.sw */
+ LOG_DIS("l.sw %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+ {
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+ tcg_gen_qemu_st32(cpu_R[rb], t0, dc->mem_idx);
+ tcg_temp_free(t0);
+ }
+ break;
+
+ case 0x36: /* l.sb */
+ LOG_DIS("l.sb %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+ {
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+ tcg_gen_qemu_st8(cpu_R[rb], t0, dc->mem_idx);
+ tcg_temp_free(t0);
+ }
+ break;
+
+ case 0x37: /* l.sh */
+ LOG_DIS("l.sh %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+ {
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
+ tcg_gen_qemu_st16(cpu_R[rb], t0, dc->mem_idx);
+ tcg_temp_free(t0);
+ }
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+}
+
+static void dec_mac(DisasContext *dc, 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);
+
+ switch (op0) {
+ case 0x0001: /* l.mac */
+ LOG_DIS("l.mac r%d, r%d\n", ra, rb);
+ {
+ TCGv_i32 t0 = tcg_temp_new_i32();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+ TCGv_i64 t2 = tcg_temp_new_i64();
+ tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]);
+ tcg_gen_ext_i32_i64(t1, t0);
+ tcg_gen_concat_i32_i64(t2, maclo, machi);
+ tcg_gen_add_i64(t2, t2, t1);
+ tcg_gen_trunc_i64_i32(maclo, t2);
+ tcg_gen_shri_i64(t2, t2, 32);
+ tcg_gen_trunc_i64_i32(machi, t2);
+ tcg_temp_free_i32(t0);
+ tcg_temp_free_i64(t1);
+ tcg_temp_free_i64(t2);
+ }
+ break;
+
+ case 0x0002: /* l.msb */
+ LOG_DIS("l.msb r%d, r%d\n", ra, rb);
+ {
+ TCGv_i32 t0 = tcg_temp_new_i32();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+ TCGv_i64 t2 = tcg_temp_new_i64();
+ 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_sub_i64(t2, t2, t1);
+ tcg_gen_trunc_i64_i32(maclo, t2);
+ tcg_gen_shri_i64(t2, t2, 32);
+ tcg_gen_trunc_i64_i32(machi, t2);
+ tcg_temp_free_i32(t0);
+ tcg_temp_free_i64(t1);
+ tcg_temp_free_i64(t2);
+ }
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+}
+
+static void dec_logic(DisasContext *dc, uint32_t insn)
+{
+ uint32_t op0;
+ uint32_t rd, ra, L6;
+ op0 = field(insn, 6, 2);
+ rd = field(insn, 21, 5);
+ ra = field(insn, 16, 5);
+ L6 = field(insn, 0, 6);
+
+ switch (op0) {
+ case 0x00: /* l.slli */
+ LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6);
+ tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+ break;
+
+ case 0x01: /* l.srli */
+ LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6);
+ tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+ break;
+
+ case 0x02: /* l.srai */
+ LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6);
+ tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f)); break;
+
+ case 0x03: /* l.rori */
+ LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6);
+ tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+}
+
+static void dec_M(DisasContext *dc, uint32_t insn)
+{
+ uint32_t op0;
+ uint32_t rd;
+ uint32_t K16;
+ op0 = field(insn, 16, 1);
+ rd = field(insn, 21, 5);
+ K16 = field(insn, 0, 16);
+
+ switch (op0) {
+ case 0x0: /* l.movhi */
+ LOG_DIS("l.movhi r%d, %d\n", rd, K16);
+ tcg_gen_movi_tl(cpu_R[rd], (K16 << 16));
+ break;
+
+ case 0x1: /* l.macrc */
+ LOG_DIS("l.macrc r%d\n", rd);
+ tcg_gen_mov_tl(cpu_R[rd], maclo);
+ tcg_gen_movi_tl(maclo, 0x0);
+ tcg_gen_movi_tl(machi, 0x0);
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+}
+
+static void dec_comp(DisasContext *dc, uint32_t insn)
+{
+ uint32_t op0;
+ uint32_t ra, rb;
+
+ op0 = field(insn, 21, 5);
+ ra = field(insn, 16, 5);
+ rb = field(insn, 11, 5);
+
+ tcg_gen_movi_i32(env_btaken, 0x0);
+ /* unsigned integers */
+ tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+ tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
+
+ switch (op0) {
+ case 0x0: /* l.sfeq */
+ LOG_DIS("l.sfeq r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x1: /* l.sfne */
+ LOG_DIS("l.sfne r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x2: /* l.sfgtu */
+ LOG_DIS("l.sfgtu r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_GTU, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x3: /* l.sfgeu */
+ LOG_DIS("l.sfgeu r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_GEU, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x4: /* l.sfltu */
+ LOG_DIS("l.sfltu r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_LTU, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x5: /* l.sfleu */
+ LOG_DIS("l.sfleu r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0xa: /* l.sfgts */
+ LOG_DIS("l.sfgts r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0xb: /* l.sfges */
+ LOG_DIS("l.sfges r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0xc: /* l.sflts */
+ LOG_DIS("l.sflts r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0xd: /* l.sfles */
+ LOG_DIS("l.sfles r%d, r%d\n", ra, rb);
+ tcg_gen_setcond_tl(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ wb_SR_F();
+}
+
+static void dec_compi(DisasContext *dc, 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);
+ 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], I16);
+ break;
+
+ case 0x5: /* l.sfleui */
+ LOG_DIS("l.sfleui r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], I16);
+ break;
+
+ case 0xa: /* l.sfgtsi */
+ LOG_DIS("l.sfgtsi r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_GT, env_btaken, cpu_R[ra], I16);
+ break;
+
+ case 0xb: /* l.sfgesi */
+ LOG_DIS("l.sfgesi r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_GE, env_btaken, cpu_R[ra], I16);
+ break;
+
+ case 0xc: /* l.sfltsi */
+ LOG_DIS("l.sfltsi r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_LT, env_btaken, cpu_R[ra], I16);
+ break;
+
+ case 0xd: /* l.sflesi */
+ LOG_DIS("l.sflesi r%d, %d\n", ra, I16);
+ tcg_gen_setcondi_tl(TCG_COND_LE, env_btaken, cpu_R[ra], I16);
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ wb_SR_F();
+}
+
+static void dec_sys(DisasContext *dc, uint32_t insn)
+{
+ uint32_t op0;
+#ifdef OPENRISC_DISAS
+ uint32_t K16;
+#endif
+ op0 = field(insn, 16, 8);
+#ifdef OPENRISC_DISAS
+ K16 = field(insn, 0, 16);
+#endif
+
+ switch (op0) {
+ case 0x000: /* l.sys */
+ LOG_DIS("l.sys %d\n", K16);
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ gen_exception(dc, EXCP_SYSCALL);
+ dc->is_jmp = DISAS_UPDATE;
+ break;
+
+ case 0x100: /* l.trap */
+ LOG_DIS("l.trap %d\n", K16);
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ gen_exception(dc, EXCP_TRAP);
+ break;
+
+ case 0x300: /* l.csync */
+ LOG_DIS("l.csync\n");
+ break;
+
+ case 0x200: /* l.msync */
+ LOG_DIS("l.msync\n");
+ break;
+
+ case 0x270: /* l.psync */
+ LOG_DIS("l.psync\n");
+ break;
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+}
+
+static void dec_float(DisasContext *dc, 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 0x00: /* lf.add.s */
+ LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x01: /* lf.sub.s */
+ LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+
+ case 0x02: /* lf.mul.s */
+ LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb);
+ if (ra != 0 && rb != 0) {
+ gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ } else {
+ tcg_gen_ori_tl(fpcsr, fpcsr, FPCSR_ZF);
+ tcg_gen_movi_i32(cpu_R[rd], 0x0);
+ }
+ break;
+
+ case 0x03: /* lf.div.s */
+ LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x04: /* lf.itof.s */
+ LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+ gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]);
+ break;
+
+ case 0x05: /* lf.ftoi.s */
+ LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
+ gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]);
+ break;
+
+ case 0x06: /* lf.rem.s */
+ LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x07: /* lf.madd.s */
+ LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
+ gen_helper_float_muladd_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x08: /* lf.sfeq.s */
+ LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
+ gen_helper_float_eq_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x09: /* lf.sfne.s */
+ LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
+ gen_helper_float_ne_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x0a: /* lf.sfgt.s */
+ LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
+ gen_helper_float_gt_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x0b: /* lf.sfge.s */
+ LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
+ gen_helper_float_ge_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x0c: /* lf.sflt.s */
+ LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
+ gen_helper_float_lt_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x0d: /* lf.sfle.s */
+ LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
+ gen_helper_float_le_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+/* not used yet, open it when we need or64. */
+/*#ifdef TARGET_OPENRISC64
+ case 0x10: lf.add.d
+ LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb);
+ check_of64s(dc);
+ gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x11: lf.sub.d
+ LOG_DIS("lf.sub.d r%d, r%d, r%d\n", rd, ra, rb);
+ check_of64s(dc);
+ gen_helper_float_sub_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x12: lf.mul.d
+ LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb);
+ check_of64s(dc);
+ if (ra != 0 && rb != 0) {
+ gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ } else {
+ tcg_gen_ori_tl(fpcsr, fpcsr, FPCSR_ZF);
+ tcg_gen_movi_i64(cpu_R[rd], 0x0);
+ }
+ break;
+
+ case 0x13: lf.div.d
+ LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb);
+ check_of64s(dc);
+ gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x14: lf.itof.d
+ LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
+ check_of64s(dc);
+ gen_helper_itofd(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);
+ check_of64s(dc);
+ gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]);
+ break;
+
+ case 0x16: lf.rem.d
+ LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
+ check_of64s(dc);
+ gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x17: lf.madd.d
+ LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb);
+ check_of64s(dc);
+ gen_helper_float_muladd_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x18: lf.sfeq.d
+ LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
+ check_of64s(dc);
+ gen_helper_float_eq_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x1a: lf.sfgt.d
+ LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
+ check_of64s(dc);
+ gen_helper_float_gt_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x1b: lf.sfge.d
+ LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
+ check_of64s(dc);
+ gen_helper_float_ge_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x19: lf.sfne.d
+ LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
+ check_of64s(dc);
+ gen_helper_float_ne_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x1c: lf.sflt.d
+ LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
+ check_of64s(dc);
+ gen_helper_float_lt_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+
+ case 0x1d: lf.sfle.d
+ LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
+ check_of64s(dc);
+ gen_helper_float_le_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+ break;
+#endif*/
+
+ default:
+ gen_illegal_exception(dc);
+ break;
+ }
+ wb_SR_F();
+}
+
+static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
+{
+ uint32_t op0;
+ uint32_t insn;
+ insn = cpu_ldl_code(&cpu->env, dc->pc);
+ op0 = field(insn, 26, 6);
+
+ switch (op0) {
+ case 0x06:
+ dec_M(dc, insn);
+ break;
+
+ case 0x08:
+ dec_sys(dc, insn);
+ break;
+
+ case 0x2e:
+ dec_logic(dc, insn);
+ break;
+
+ case 0x2f:
+ dec_compi(dc, insn);
+ break;
+
+ case 0x31:
+ dec_mac(dc, insn);
+ break;
+
+ case 0x32:
+ dec_float(dc, insn);
+ break;
+
+ case 0x38:
+ dec_calc(dc, insn);
+ break;
+
+ case 0x39:
+ dec_comp(dc, insn);
+ break;
+
+ default:
+ dec_misc(dc, insn);
+ break;
+ }
+}
+
+static void check_breakpoint(OpenRISCCPU *cpu, DisasContext *dc)
+{
+ CPUBreakpoint *bp;
+
+ if (unlikely(!QTAILQ_EMPTY(&cpu->env.breakpoints))) {
+ QTAILQ_FOREACH(bp, &cpu->env.breakpoints, entry) {
+ if (bp->pc == dc->pc) {
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ gen_exception(dc, EXCP_DEBUG);
+ dc->is_jmp = DISAS_UPDATE;
+ }
+ }
+ }
}
static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
TranslationBlock *tb,
int search_pc)
{
+ struct DisasContext ctx, *dc = &ctx;
+ uint16_t *gen_opc_end;
+ uint32_t pc_start;
+ int j, k;
+ uint32_t next_page_start;
+ int num_insns;
+ int max_insns;
+
+ qemu_log_try_set_file(stderr);
+
+ pc_start = tb->pc;
+ dc->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->flags = cpu->env.cpucfgr;
+ dc->mem_idx = cpu_mmu_index(&cpu->env);
+ dc->synced_flags = dc->tb_flags = tb->flags;
+ dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
+ dc->singlestep_enabled = cpu->env.singlestep_enabled;
+ if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+ qemu_log("-----------------------------------------\n");
+ log_cpu_state(&cpu->env, 0);
+ }
+
+ next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+ k = -1;
+ num_insns = 0;
+ max_insns = tb->cflags & CF_COUNT_MASK;
+
+ if (max_insns == 0) {
+ max_insns = CF_COUNT_MASK;
+ }
+
+ gen_icount_start();
+
+ do {
+ check_breakpoint(cpu, dc);
+ if (search_pc) {
+ j = gen_opc_ptr - gen_opc_buf;
+ if (k < j) {
+ k++;
+ while (k < j) {
+ gen_opc_instr_start[k++] = 0;
+ }
+ }
+ gen_opc_pc[k] = dc->pc;
+ gen_opc_instr_start[k] = 1;
+ gen_opc_icount[k] = num_insns;
+ }
+
+ if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
+ tcg_gen_debug_insn_start(dc->pc);
+ }
+
+ if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ gen_io_start();
+ }
+ dc->ppc = dc->pc - 4;
+ dc->npc = dc->pc + 4;
+ tcg_gen_movi_tl(cpu_ppc, dc->ppc);
+ tcg_gen_movi_tl(cpu_npc, dc->npc);
+ disas_openrisc_insn(dc, cpu);
+ dc->pc = dc->npc;
+ num_insns++;
+ /* delay slot */
+ if (dc->delayed_branch) {
+ dc->delayed_branch--;
+ if (!dc->delayed_branch) {
+ dc->tb_flags &= ~D_FLAG;
+ gen_sync_flags(dc);
+ tcg_gen_mov_tl(cpu_pc, jmp_pc);
+ tcg_gen_mov_tl(cpu_npc, jmp_pc);
+ tcg_gen_movi_tl(jmp_pc, 0);
+ tcg_gen_exit_tb(0);
+ dc->is_jmp = DISAS_JUMP;
+ break;
+ }
+ }
+ } while (!dc->is_jmp
+ && gen_opc_ptr < gen_opc_end
+ && !cpu->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(cpu->env.singlestep_enabled)) {
+ if (dc->is_jmp == DISAS_NEXT) {
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ }
+ gen_exception(dc, EXCP_DEBUG);
+ } else {
+ switch (dc->is_jmp) {
+ case DISAS_NEXT:
+ gen_goto_tb(dc, 0, dc->pc);
+ break;
+ default:
+ case DISAS_JUMP:
+ break;
+ case DISAS_UPDATE:
+ /* indicate that the hash table must be used
+ to find the next TB */
+ tcg_gen_exit_tb(0);
+ break;
+ case DISAS_TB_JUMP:
+ /* nothing more to generate */
+ break;
+ }
+ }
+
+ gen_icount_end(tb, num_insns);
+ *gen_opc_ptr = INDEX_op_end;
+ if (search_pc) {
+ j = gen_opc_ptr - gen_opc_buf;
+ k++;
+ while (k <= j) {
+ gen_opc_instr_start[k++] = 0;
+ }
+ } else {
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
+ }
+
+#ifdef DEBUG_DISAS
+ if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+ qemu_log("\n");
+ log_target_disas(pc_start, dc->pc - pc_start, 0);
+ qemu_log("\nisize=%d osize=%td\n",
+ dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
+ }
+#endif
}
void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 08/15] target-or32: Add PIC support
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
` (6 preceding siblings ...)
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 07/15] target-or32: Add instruction translation Jia Liu
@ 2012-07-13 4:35 ` Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 09/15] target-or32: Add timer support Jia Liu
` (6 subsequent siblings)
14 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:35 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add OpenRISC Programmable Interrupt Controller support.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
hw/openrisc/Makefile.objs | 2 ++
hw/openrisc_pic.c | 60 +++++++++++++++++++++++++++++++++++++++++++++
target-openrisc/cpu.h | 3 +++
3 files changed, 65 insertions(+)
create mode 100644 hw/openrisc_pic.c
diff --git a/hw/openrisc/Makefile.objs b/hw/openrisc/Makefile.objs
index bfead21..98900aa 100644
--- a/hw/openrisc/Makefile.objs
+++ b/hw/openrisc/Makefile.objs
@@ -1 +1,3 @@
+obj-y = openrisc_pic.o
+
obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
new file mode 100644
index 0000000..6b5b0f4
--- /dev/null
+++ b/hw/openrisc_pic.c
@@ -0,0 +1,60 @@
+/*
+ * OpenRISC Programmable Interrupt Controller support.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ * Feng Gao <gf91597@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 "cpu.h"
+
+/* OpenRISC pic handler */
+static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
+{
+ OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
+ int i;
+ uint32_t irq_bit = 1 << irq;
+
+ if (irq > 31 || irq < 0) {
+ return;
+ }
+
+ if (level) {
+ cpu->env.picsr |= irq_bit;
+ } else {
+ cpu->env.picsr &= ~irq_bit;
+ }
+
+ for (i = 0; i < 32; i++) {
+ if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
+ cpu_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
+ cpu->env.picsr &= ~(1 << i);
+ }
+ }
+}
+
+void cpu_openrisc_pic_init(OpenRISCCPU *cpu)
+{
+ int i;
+ qemu_irq *qi;
+ qi = qemu_allocate_irqs(openrisc_pic_cpu_handler, cpu, NR_IRQS);
+
+ for (i = 0; i < NR_IRQS; i++) {
+ cpu->env.irq[i] = qi[i];
+ }
+}
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 51013f3..419c31a 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -355,6 +355,9 @@ int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env,
#define cpu_handle_mmu_fault cpu_openrisc_handle_mmu_fault
#ifndef CONFIG_USER_ONLY
+/* hw/openrisc_pic.c */
+void cpu_openrisc_pic_init(OpenRISCCPU *cpu);
+
void cpu_openrisc_mmu_init(OpenRISCCPU *cpu);
int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu,
target_phys_addr_t *physical,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 09/15] target-or32: Add timer support
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
` (7 preceding siblings ...)
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 08/15] target-or32: Add PIC support Jia Liu
@ 2012-07-13 4:35 ` Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 10/15] target-or32: Add a IIS dummy board Jia Liu
` (5 subsequent siblings)
14 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:35 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add OpenRISC timer support.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
hw/openrisc/Makefile.objs | 2 +-
hw/openrisc_timer.c | 101 +++++++++++++++++++++++++++++++++++++++++++++
target-openrisc/cpu.h | 22 ++++++++++
3 files changed, 124 insertions(+), 1 deletion(-)
create mode 100644 hw/openrisc_timer.c
diff --git a/hw/openrisc/Makefile.objs b/hw/openrisc/Makefile.objs
index 98900aa..1c541a5 100644
--- a/hw/openrisc/Makefile.objs
+++ b/hw/openrisc/Makefile.objs
@@ -1,3 +1,3 @@
-obj-y = openrisc_pic.o
+obj-y = openrisc_pic.o openrisc_timer.o
obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/openrisc_timer.c b/hw/openrisc_timer.c
new file mode 100644
index 0000000..b420d28
--- /dev/null
+++ b/hw/openrisc_timer.c
@@ -0,0 +1,101 @@
+/*
+ * QEMU OpenRISC timer support
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ * Zhizhou Zhang <etouzh@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 "hw.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;
+
+void cpu_openrisc_count_update(OpenRISCCPU *cpu)
+{
+ uint64_t now, next;
+ uint32_t wait;
+
+ now = qemu_get_clock_ns(vm_clock);
+ if (!is_counting) {
+ qemu_del_timer(cpu->env.timer);
+ last_clk = now;
+ return;
+ }
+
+ cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
+ get_ticks_per_sec());
+ last_clk = now;
+
+ if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
+ wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
+ wait += cpu->env.ttmr & TTMR_TP;
+ } else {
+ wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
+ }
+
+ next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
+ qemu_mod_timer(cpu->env.timer, next);
+}
+
+void cpu_openrisc_count_start(OpenRISCCPU *cpu)
+{
+ is_counting = 1;
+ cpu_openrisc_count_update(cpu);
+}
+
+void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
+{
+ is_counting = 0;
+ cpu_openrisc_count_update(cpu);
+}
+
+static void openrisc_timer_cb(void *opaque)
+{
+ OpenRISCCPU *cpu = opaque;
+
+ if ((cpu->env.ttmr & TTMR_IE) &&
+ qemu_timer_expired(cpu->env.timer, qemu_get_clock_ns(vm_clock))) {
+ cpu->env.ttmr |= TTMR_IP;
+ cpu->env.interrupt_request |= CPU_INTERRUPT_TIMER;
+ }
+
+ switch (cpu->env.ttmr & TTMR_M) {
+ case TIMER_NONE:
+ break;
+ case TIMER_INTR:
+ cpu->env.ttcr = 0;
+ cpu_openrisc_count_start(cpu);
+ break;
+ case TIMER_SHOT:
+ cpu_openrisc_count_stop(cpu);
+ break;
+ case TIMER_CONT:
+ cpu_openrisc_count_start(cpu);
+ break;
+ }
+}
+
+void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
+{
+ cpu->env.timer = qemu_new_timer_ns(vm_clock, &openrisc_timer_cb, cpu);
+ cpu->env.ttmr = 0x00000000;
+ cpu->env.ttcr = 0x00000000;
+}
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 419c31a..df07eaf 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -220,6 +220,22 @@ enum {
OPENRISC_FEATURE_OV64S = (1 << 9),
};
+/* Tick Timer Mode Register */
+enum {
+ TTMR_TP = (0xfffffff),
+ TTMR_IP = (1 << 28),
+ TTMR_IE = (1 << 29),
+ TTMR_M = (3 << 30),
+};
+
+/* Timer Mode */
+enum {
+ TIMER_NONE = (0 << 30),
+ TIMER_INTR = (1 << 30),
+ TIMER_SHOT = (2 << 30),
+ TIMER_CONT = (3 << 30),
+};
+
/* TLB size */
enum {
DTLB_WAYS = 1,
@@ -358,6 +374,12 @@ int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env,
/* hw/openrisc_pic.c */
void cpu_openrisc_pic_init(OpenRISCCPU *cpu);
+/* hw/openrisc_timer.c */
+void cpu_openrisc_clock_init(OpenRISCCPU *cpu);
+void cpu_openrisc_count_update(OpenRISCCPU *cpu);
+void cpu_openrisc_count_start(OpenRISCCPU *cpu);
+void cpu_openrisc_count_stop(OpenRISCCPU *cpu);
+
void cpu_openrisc_mmu_init(OpenRISCCPU *cpu);
int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu,
target_phys_addr_t *physical,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 10/15] target-or32: Add a IIS dummy board
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
` (8 preceding siblings ...)
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 09/15] target-or32: Add timer support Jia Liu
@ 2012-07-13 4:35 ` Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions Jia Liu
` (4 subsequent siblings)
14 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:35 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add a IIS dummy board.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
hw/openrisc/Makefile.objs | 2 +-
hw/openrisc_sim.c | 150 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 151 insertions(+), 1 deletion(-)
create mode 100644 hw/openrisc_sim.c
diff --git a/hw/openrisc/Makefile.objs b/hw/openrisc/Makefile.objs
index 1c541a5..38ff8f5 100644
--- a/hw/openrisc/Makefile.objs
+++ b/hw/openrisc/Makefile.objs
@@ -1,3 +1,3 @@
-obj-y = openrisc_pic.o openrisc_timer.o
+obj-y = openrisc_pic.o openrisc_sim.o openrisc_timer.o
obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c
new file mode 100644
index 0000000..ce9ade8
--- /dev/null
+++ b/hw/openrisc_sim.c
@@ -0,0 +1,150 @@
+/*
+ * OpenRISC simulator for use as an IIS.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ * Feng Gao <gf91597@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 "boards.h"
+#include "elf.h"
+#include "pc.h"
+#include "loader.h"
+#include "exec-memory.h"
+#include "sysemu.h"
+#include "sysbus.h"
+#include "qtest.h"
+
+#define KERNEL_LOAD_ADDR 0x100
+
+static void main_cpu_reset(void *opaque)
+{
+ OpenRISCCPU *cpu = opaque;
+
+ cpu_reset(CPU(cpu));
+}
+
+static void openrisc_sim_net_init(MemoryRegion *address_space,
+ target_phys_addr_t base,
+ target_phys_addr_t descriptors,
+ qemu_irq irq, NICInfo *nd)
+{
+ DeviceState *dev;
+ SysBusDevice *s;
+
+ dev = qdev_create(NULL, "open_eth");
+ qdev_set_nic_properties(dev, nd);
+ qdev_init_nofail(dev);
+
+ s = sysbus_from_qdev(dev);
+ sysbus_connect_irq(s, 0, irq);
+ memory_region_add_subregion(address_space, base,
+ sysbus_mmio_get_region(s, 0));
+ memory_region_add_subregion(address_space, descriptors,
+ sysbus_mmio_get_region(s, 1));
+}
+
+static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
+ const char *kernel_filename,
+ OpenRISCCPU *cpu)
+{
+ long kernel_size;
+ uint64_t elf_entry;
+ target_phys_addr_t entry;
+
+ if (kernel_filename && !qtest_enabled()) {
+ kernel_size = load_elf(kernel_filename, NULL, NULL,
+ &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) {
+ qemu_log("QEMU: couldn't load the kernel '%s'\n",
+ kernel_filename);
+ exit(1);
+ }
+ }
+
+ cpu->env.pc = entry;
+}
+
+static void openrisc_sim_init(ram_addr_t ram_size,
+ const char *boot_device,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename,
+ const char *cpu_model)
+{
+ OpenRISCCPU *cpu = NULL;
+ MemoryRegion *ram;
+ int n;
+
+ if (!cpu_model) {
+ cpu_model = "or1200";
+ }
+
+ for (n = 0; n < smp_cpus; n++) {
+ cpu = cpu_openrisc_init(cpu_model);
+ if (cpu == NULL) {
+ qemu_log("Unable to find CPU defineition!\n");
+ exit(1);
+ }
+ qemu_register_reset(main_cpu_reset, cpu);
+ main_cpu_reset(cpu);
+ }
+
+ ram = g_malloc(sizeof(*ram));
+ memory_region_init_ram(ram, "openrisc.ram", ram_size);
+ vmstate_register_ram_global(ram);
+ memory_region_add_subregion(get_system_memory(), 0, ram);
+
+ cpu_openrisc_pic_init(cpu);
+ cpu_openrisc_clock_init(cpu);
+
+ serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2],
+ 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
+
+ if (nd_table[0].vlan) {
+ openrisc_sim_net_init(get_system_memory(), 0x92000000,
+ 0x92000400, cpu->env.irq[4], nd_table);
+ }
+
+ cpu_openrisc_load_kernel(ram_size, kernel_filename, cpu);
+}
+
+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
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
` (9 preceding siblings ...)
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 10/15] target-or32: Add a IIS dummy board Jia Liu
@ 2012-07-13 4:35 ` Jia Liu
2012-07-13 9:27 ` Max Filippov
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 12/15] target-or32: Add gdb stub support Jia Liu
` (3 subsequent siblings)
14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:35 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add OpenRISC system instructions.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-openrisc/Makefile.objs | 2 +-
target-openrisc/cpu.h | 3 +
target-openrisc/helper.h | 4 +
target-openrisc/sys_helper.c | 287 +++++++++++++++++++++++++++++++++++++++++
target-openrisc/translate.c | 10 ++
5 files changed, 305 insertions(+), 1 deletion(-)
create mode 100644 target-openrisc/sys_helper.c
diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
index 926fc2f..44dc539 100644
--- a/target-openrisc/Makefile.objs
+++ b/target-openrisc/Makefile.objs
@@ -1,4 +1,4 @@
obj-$(CONFIG_SOFTMMU) += machine.o
obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
obj-y += exception_helper.o fpu_helper.o int_helper.o \
- interrupt_helper.o mmu_helper.o
+ interrupt_helper.o mmu_helper.o sys_helper.o
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index df07eaf..6506665 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -80,6 +80,9 @@ enum {
(reg) |= ((v & 0x1f) << 2);\
} while (0)
+/* Version Register */
+#define SPR_VR 0xFFFF003F
+
/* Internal flags, delay slot flag */
#define D_FLAG 1
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index 6eb259a..836a70b 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -63,4 +63,8 @@ DEF_HELPER_FLAGS_3(mul32, 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, tl, 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..7ff8e15
--- /dev/null
+++ b/target-openrisc/sys_helper.c
@@ -0,0 +1,287 @@
+/*
+ * OpenRISC system instructions helper routines
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ * Zhizhou Zhang <etouzh@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+
+#define TO_SPR(group, number) (((group) << 11) + (number))
+
+void HELPER(mtspr)(CPUOpenRISCState *env,
+ target_ulong ra, target_ulong rb, target_ulong offset)
+{
+#ifndef CONFIG_USER_ONLY
+ int spr = (ra | offset);
+ int idx;
+
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
+
+ switch (spr) {
+ case TO_SPR(0, 0): /* VR */
+ env->vr = rb;
+ break;
+
+ case TO_SPR(0, 16): /* NPC */
+ env->npc = rb;
+ break;
+
+ case TO_SPR(0, 17): /* SR */
+ if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
+ (rb & (SR_IME | SR_DME | SR_SM))) {
+ tlb_flush(env, 1);
+ }
+ env->sr = rb;
+ env->sr |= SR_FO; /* FO is const equal to 1 */
+ if (env->sr & SR_DME) {
+ env->tlb->cpu_openrisc_map_address_data =
+ &cpu_openrisc_get_phys_data;
+ } else {
+ env->tlb->cpu_openrisc_map_address_data =
+ &cpu_openrisc_get_phys_nommu;
+ }
+
+ if (env->sr & SR_IME) {
+ env->tlb->cpu_openrisc_map_address_code =
+ &cpu_openrisc_get_phys_code;
+ } else {
+ env->tlb->cpu_openrisc_map_address_code =
+ &cpu_openrisc_get_phys_nommu;
+ }
+ break;
+
+ case TO_SPR(0, 18): /* PPC */
+ env->ppc = rb;
+ break;
+
+ case TO_SPR(0, 32): /* EPCR */
+ env->epcr = rb;
+ break;
+
+ case TO_SPR(0, 48): /* EEAR */
+ env->eear = rb;
+ break;
+
+ case TO_SPR(0, 64): /* ESR */
+ env->esr = rb;
+ break;
+ case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
+ idx = spr - TO_SPR(1, 512);
+ if (!(rb & 1)) {
+ tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
+ }
+ env->tlb->dtlb[0][idx].mr = rb;
+ break;
+
+ case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
+ idx = spr - TO_SPR(1, 640);
+ env->tlb->dtlb[0][idx].tr = 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 (!(rb & 1)) {
+ tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
+ }
+ env->tlb->itlb[0][idx].mr = rb;
+ break;
+
+ case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
+ idx = spr - TO_SPR(2, 640);
+ env->tlb->itlb[0][idx].tr = rb;
+ 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->picmr |= rb;
+ break;
+ case TO_SPR(9, 2): /* PICSR */
+ env->picsr &= ~rb;
+ break;
+ case TO_SPR(10, 0): /* TTMR */
+ {
+ int ip = env->ttmr & TTMR_IP;
+
+ if (rb & TTMR_IP) { /* Keep IP bit. */
+ env->ttmr = (rb & ~TTMR_IP) + ip;
+ } else { /* Clear IP bit. */
+ env->ttmr = rb & ~TTMR_IP;
+ env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
+ }
+
+ cpu_openrisc_count_update(cpu);
+
+ switch (env->ttmr & TTMR_M) {
+ case TIMER_NONE:
+ cpu_openrisc_count_stop(cpu);
+ break;
+ case TIMER_INTR:
+ cpu_openrisc_count_start(cpu);
+ break;
+ case TIMER_SHOT:
+ cpu_openrisc_count_start(cpu);
+ break;
+ case TIMER_CONT:
+ cpu_openrisc_count_start(cpu);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+
+ case TO_SPR(10, 1): /* TTCR */
+ env->ttcr = rb;
+ if (env->ttmr & TIMER_NONE) {
+ return;
+ }
+ cpu_openrisc_count_start(cpu);
+ break;
+ default:
+
+ break;
+ }
+#endif
+}
+
+target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
+ target_ulong rd, target_ulong ra, uint32_t offset)
+{
+#ifndef CONFIG_USER_ONLY
+ int spr = (ra | offset);
+ int idx;
+
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
+
+ switch (spr) {
+ case TO_SPR(0, 0): /* VR */
+ return env->vr & SPR_VR;
+
+ case TO_SPR(0, 1): /* UPR */
+ return env->upr; /* TT, DM, IM, UP present */
+
+ case TO_SPR(0, 2): /* CPUCFGR */
+ return env->cpucfgr;
+
+ case TO_SPR(0, 3): /* DMMUCFGR */
+ return env->dmmucfgr; /* 1Way, 64 entries */
+
+ case TO_SPR(0, 4): /* IMMUCFGR */
+ return env->immucfgr;
+
+ case TO_SPR(0, 16): /* NPC */
+ return env->npc;
+
+ case TO_SPR(0, 17): /* SR */
+ return env->sr;
+
+ case TO_SPR(0, 18): /* PPC */
+ return env->ppc;
+
+ case TO_SPR(0, 32): /* EPCR */
+ return env->epcr;
+
+ case TO_SPR(0, 48): /* EEAR */
+ return env->eear;
+
+ case TO_SPR(0, 64): /* ESR */
+ return env->esr;
+
+ case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
+ idx = spr - TO_SPR(1, 512);
+ return env->tlb->dtlb[0][idx].mr;
+
+ case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
+ idx = spr - TO_SPR(1, 640);
+ return env->tlb->dtlb[0][idx].tr;
+
+ 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);
+ return env->tlb->itlb[0][idx].mr;
+
+ case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
+ idx = spr - TO_SPR(2, 640);
+ return env->tlb->itlb[0][idx].tr;
+
+ 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 */
+ return env->picmr;
+
+ case TO_SPR(9, 2): /* PICSR */
+ return env->picsr;
+
+ case TO_SPR(10, 0): /* TTMR */
+ return env->ttmr;
+
+ case TO_SPR(10, 1): /* TTCR */
+ cpu_openrisc_count_update(cpu);
+ return env->ttcr;
+
+ default:
+ break;
+ }
+#endif
+
+/*If we later need to add tracepoints (or debug printfs) for the return
+value, it may be useful to structure the code like this:
+
+target_ulong ret = 0;
+
+switch() {
+case x:
+ ret = y;
+ break;
+case z:
+ ret = 42;
+ break;
+...
+}
+
+later something like trace_spr_read(ret);
+
+return ret;*/
+
+ /* for rd is passed in, if rd unchanged, just keep it back. */
+ return rd;
+}
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index ed25604..8069edb 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -995,10 +995,20 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
case 0x2d: /* l.mfspr */
LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
+ {
+ TCGv_i32 ti = tcg_const_i32(I16);
+ gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
+ tcg_temp_free_i32(ti);
+ }
break;
case 0x30: /* l.mtspr */
LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+ {
+ TCGv_i32 im = tcg_const_i32(tmp);
+ gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
+ tcg_temp_free_i32(im);
+ }
break;
/* not used yet, open it when we need or64. */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 12/15] target-or32: Add gdb stub support
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
` (10 preceding siblings ...)
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions Jia Liu
@ 2012-07-13 4:35 ` Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 13/15] target-or32: Add linux syscall, signal and termbits Jia Liu
` (2 subsequent siblings)
14 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:35 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add OpenRISC gdb stub support.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
gdbstub.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/gdbstub.c b/gdbstub.c
index 08cf864..5d37dd9 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
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 13/15] target-or32: Add linux syscall, signal and termbits
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
` (11 preceding siblings ...)
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 12/15] target-or32: Add gdb stub support Jia Liu
@ 2012-07-13 4:35 ` Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 14/15] target-or32: Add linux user support Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 15/15] target-or32: Add testcases Jia Liu
14 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:35 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add OpenRISC linux syscall, signal and termbits.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
linux-user/openrisc/syscall.h | 24 ++
linux-user/openrisc/syscall_nr.h | 506 +++++++++++++++++++++++++++++++++++
linux-user/openrisc/target_signal.h | 26 ++
linux-user/openrisc/termbits.h | 294 ++++++++++++++++++++
4 files changed, 850 insertions(+)
create mode 100644 linux-user/openrisc/syscall.h
create mode 100644 linux-user/openrisc/syscall_nr.h
create mode 100644 linux-user/openrisc/target_signal.h
create mode 100644 linux-user/openrisc/termbits.h
diff --git a/linux-user/openrisc/syscall.h b/linux-user/openrisc/syscall.h
new file mode 100644
index 0000000..bdbb577
--- /dev/null
+++ b/linux-user/openrisc/syscall.h
@@ -0,0 +1,24 @@
+struct target_pt_regs {
+ union {
+ struct {
+ /* Named registers */
+ uint32_t sr; /* Stored in place of r0 */
+ target_ulong sp; /* r1 */
+ };
+ struct {
+ /* Old style */
+ target_ulong offset[2];
+ target_ulong gprs[30];
+ };
+ struct {
+ /* New style */
+ target_ulong gpr[32];
+ };
+ };
+ target_ulong pc;
+ target_ulong orig_gpr11; /* For restarting system calls */
+ uint32_t syscallno; /* Syscall number (used by strace) */
+ target_ulong dummy; /* Cheap alignment fix */
+};
+
+#define UNAME_MACHINE "openrisc"
diff --git a/linux-user/openrisc/syscall_nr.h b/linux-user/openrisc/syscall_nr.h
new file mode 100644
index 0000000..f4ac91e
--- /dev/null
+++ b/linux-user/openrisc/syscall_nr.h
@@ -0,0 +1,506 @@
+#define TARGET_NR_io_setup 0
+#define TARGET_NR_io_destroy 1
+#define TARGET_NR_io_submit 2
+#define TARGET_NR_io_cancel 3
+#define TARGET_NR_io_getevents 4
+
+/* fs/xattr.c */
+#define TARGET_NR_setxattr 5
+#define TARGET_NR_lsetxattr 6
+#define TARGET_NR_fsetxattr 7
+#define TARGET_NR_getxattr 8
+#define TARGET_NR_lgetxattr 9
+#define TARGET_NR_fgetxattr 10
+#define TARGET_NR_listxattr 11
+#define TARGET_NR_llistxattr 12
+#define TARGET_NR_flistxattr 13
+#define TARGET_NR_removexattr 14
+#define TARGET_NR_lremovexattr 15
+#define TARGET_NR_fremovexattr 16
+
+/* fs/dcache.c */
+#define TARGET_NR_getcwd 17
+
+/* fs/cookies.c */
+#define TARGET_NR_lookup_dcookie 18
+
+/* fs/eventfd.c */
+#define TARGET_NR_eventfd2 19
+
+/* fs/eventpoll.c */
+#define TARGET_NR_epoll_create1 20
+#define TARGET_NR_epoll_ctl 21
+#define TARGET_NR_epoll_pwait 22
+
+/* fs/fcntl.c */
+#define TARGET_NR_dup 23
+#define TARGET_NR_dup3 24
+#define TARGET_NR_3264_fcntl 25
+
+/* fs/inotify_user.c */
+#define TARGET_NR_inotify_init1 26
+#define TARGET_NR_inotify_add_watch 27
+#define TARGET_NR_inotify_rm_watch 28
+
+/* fs/ioctl.c */
+#define TARGET_NR_ioctl 29
+
+/* fs/ioprio.c */
+#define TARGET_NR_ioprio_set 30
+#define TARGET_NR_ioprio_get 31
+
+/* fs/locks.c */
+#define TARGET_NR_flock 32
+
+/* fs/namei.c */
+#define TARGET_NR_mknodat 33
+#define TARGET_NR_mkdirat 34
+#define TARGET_NR_unlinkat 35
+#define TARGET_NR_symlinkat 36
+#define TARGET_NR_linkat 37
+#define TARGET_NR_renameat 38
+
+/* fs/namespace.c */
+#define TARGET_NR_umount2 39
+#define TARGET_NR_mount 40
+#define TARGET_NR_pivot_root 41
+
+/* fs/nfsctl.c */
+#define TARGET_NR_nfsservctl 42
+
+/* fs/open.c */
+#define TARGET_NR_3264_statfs 43
+#define TARGET_NR_3264_fstatfs 44
+#define TARGET_NR_3264_truncate 45
+#define TARGET_NR_3264_ftruncate 46
+
+#define TARGET_NR_fallocate 47
+#define TARGET_NR_faccessat 48
+#define TARGET_NR_chdir 49
+#define TARGET_NR_fchdir 50
+#define TARGET_NR_chroot 51
+#define TARGET_NR_fchmod 52
+#define TARGET_NR_fchmodat 53
+#define TARGET_NR_fchownat 54
+#define TARGET_NR_fchown 55
+#define TARGET_NR_openat 56
+#define TARGET_NR_close 57
+#define TARGET_NR_vhangup 58
+
+/* fs/pipe.c */
+#define TARGET_NR_pipe2 59
+
+/* fs/quota.c */
+#define TARGET_NR_quotactl 60
+
+/* fs/readdir.c */
+#define TARGET_NR_getdents64 61
+
+/* fs/read_write.c */
+#define TARGET_NR_3264_lseek 62
+#define TARGET_NR_read 63
+#define TARGET_NR_write 64
+#define TARGET_NR_readv 65
+#define TARGET_NR_writev 66
+#define TARGET_NR_pread64 67
+#define TARGET_NR_pwrite64 68
+#define TARGET_NR_preadv 69
+#define TARGET_NR_pwritev 70
+
+/* fs/sendfile.c */
+#define TARGET_NR_3264_sendfile 71
+
+/* fs/select.c */
+#define TARGET_NR_pselect6 72
+#define TARGET_NR_ppoll 73
+
+/* fs/signalfd.c */
+#define TARGET_NR_signalfd4 74
+
+/* fs/splice.c */
+#define TARGET_NR_vmsplice 75
+#define TARGET_NR_splice 76
+#define TARGET_NR_tee 77
+
+/* fs/stat.c */
+#define TARGET_NR_readlinkat 78
+#define TARGET_NR_3264_fstatat 79
+#define TARGET_NR_3264_fstat 80
+
+/* fs/sync.c */
+#define TARGET_NR_sync 81
+#define TARGET_NR_fsync 82
+#define TARGET_NR_fdatasync 83
+
+#ifdef __ARCH_WANT_SYNC_FILE_RANGE2
+#define TARGET_NR_sync_file_range2 84
+#else
+#define TARGET_NR_sync_file_range 84
+#endif
+
+/* fs/timerfd.c */
+#define TARGET_NR_timerfd_create 85
+#define TARGET_NR_timerfd_settime 86
+#define TARGET_NR_timerfd_gettime 87
+
+/* fs/utimes.c */
+#define TARGET_NR_utimensat 88
+
+/* kernel/acct.c */
+#define TARGET_NR_acct 89
+
+/* kernel/capability.c */
+#define TARGET_NR_capget 90
+#define TARGET_NR_capset 91
+
+/* kernel/exec_domain.c */
+#define TARGET_NR_personality 92
+
+/* kernel/exit.c */
+#define TARGET_NR_exit 93
+#define TARGET_NR_exit_group 94
+#define TARGET_NR_waitid 95
+
+/* kernel/fork.c */
+#define TARGET_NR_set_tid_address 96
+#define TARGET_NR_unshare 97
+
+/* kernel/futex.c */
+#define TARGET_NR_futex 98
+#define TARGET_NR_set_robust_list 99
+#define TARGET_NR_get_robust_list 100
+
+/* kernel/hrtimer.c */
+#define TARGET_NR_nanosleep 101
+
+/* kernel/itimer.c */
+#define TARGET_NR_getitimer 102
+#define TARGET_NR_setitimer 103
+
+/* kernel/kexec.c */
+#define TARGET_NR_kexec_load 104
+
+/* kernel/module.c */
+#define TARGET_NR_init_module 105
+#define TARGET_NR_delete_module 106
+
+/* kernel/posix-timers.c */
+#define TARGET_NR_timer_create 107
+#define TARGET_NR_timer_gettime 108
+#define TARGET_NR_timer_getoverrun 109
+#define TARGET_NR_timer_settime 110
+#define TARGET_NR_timer_delete 111
+#define TARGET_NR_clock_settime 112
+#define TARGET_NR_clock_gettime 113
+#define TARGET_NR_clock_getres 114
+#define TARGET_NR_clock_nanosleep 115
+
+/* kernel/printk.c */
+#define TARGET_NR_syslog 116
+
+/* kernel/ptrace.c */
+#define TARGET_NR_ptrace 117
+
+/* kernel/sched.c */
+#define TARGET_NR_sched_setparam 118
+#define TARGET_NR_sched_setscheduler 119
+#define TARGET_NR_sched_getscheduler 120
+#define TARGET_NR_sched_getparam 121
+#define TARGET_NR_sched_setaffinity 122
+#define TARGET_NR_sched_getaffinity 123
+#define TARGET_NR_sched_yield 124
+#define TARGET_NR_sched_get_priority_max 125
+#define TARGET_NR_sched_get_priority_min 126
+#define TARGET_NR_sched_rr_get_interval 127
+
+/* kernel/signal.c */
+#define TARGET_NR_restart_syscall 128
+#define TARGET_NR_kill 129
+#define TARGET_NR_tkill 130
+#define TARGET_NR_tgkill 131
+#define TARGET_NR_sigaltstack 132
+#define TARGET_NR_rt_sigsuspend 133
+#define TARGET_NR_rt_sigaction 134
+#define TARGET_NR_rt_sigprocmask 135
+#define TARGET_NR_rt_sigpending 136
+#define TARGET_NR_rt_sigtimedwait 137
+#define TARGET_NR_rt_sigqueueinfo 138
+#define TARGET_NR_rt_sigreturn 139
+
+/* kernel/sys.c */
+#define TARGET_NR_setpriority 140
+#define TARGET_NR_getpriority 141
+#define TARGET_NR_reboot 142
+#define TARGET_NR_setregid 143
+#define TARGET_NR_setgid 144
+#define TARGET_NR_setreuid 145
+#define TARGET_NR_setuid 146
+#define TARGET_NR_setresuid 147
+#define TARGET_NR_getresuid 148
+#define TARGET_NR_setresgid 149
+#define TARGET_NR_getresgid 150
+#define TARGET_NR_setfsuid 151
+#define TARGET_NR_setfsgid 152
+#define TARGET_NR_times 153
+#define TARGET_NR_setpgid 154
+#define TARGET_NR_getpgid 155
+#define TARGET_NR_getsid 156
+#define TARGET_NR_setsid 157
+#define TARGET_NR_getgroups 158
+#define TARGET_NR_setgroups 159
+#define TARGET_NR_uname 160
+#define TARGET_NR_sethostname 161
+#define TARGET_NR_setdomainname 162
+#define TARGET_NR_getrlimit 163
+#define TARGET_NR_setrlimit 164
+#define TARGET_NR_getrusage 165
+#define TARGET_NR_umask 166
+#define TARGET_NR_prctl 167
+#define TARGET_NR_getcpu 168
+
+/* kernel/time.c */
+#define TARGET_NR_gettimeofday 169
+#define TARGET_NR_settimeofday 170
+#define TARGET_NR_adjtimex 171
+
+/* kernel/timer.c */
+#define TARGET_NR_getpid 172
+#define TARGET_NR_getppid 173
+#define TARGET_NR_getuid 174
+#define TARGET_NR_geteuid 175
+#define TARGET_NR_getgid 176
+#define TARGET_NR_getegid 177
+#define TARGET_NR_gettid 178
+#define TARGET_NR_sysinfo 179
+
+/* ipc/mqueue.c */
+#define TARGET_NR_mq_open 180
+#define TARGET_NR_mq_unlink 181
+#define TARGET_NR_mq_timedsend 182
+#define TARGET_NR_mq_timedreceive 183
+#define TARGET_NR_mq_notify 184
+#define TARGET_NR_mq_getsetattr 185
+
+/* ipc/msg.c */
+#define TARGET_NR_msgget 186
+#define TARGET_NR_msgctl 187
+#define TARGET_NR_msgrcv 188
+#define TARGET_NR_msgsnd 189
+
+/* ipc/sem.c */
+#define TARGET_NR_semget 190
+#define TARGET_NR_semctl 191
+#define TARGET_NR_semtimedop 192
+#define TARGET_NR_semop 193
+
+/* ipc/shm.c */
+#define TARGET_NR_shmget 194
+#define TARGET_NR_shmctl 195
+#define TARGET_NR_shmat 196
+#define TARGET_NR_shmdt 197
+
+/* net/socket.c */
+#define TARGET_NR_socket 198
+#define TARGET_NR_socketpair 199
+#define TARGET_NR_bind 200
+#define TARGET_NR_listen 201
+#define TARGET_NR_accept 202
+#define TARGET_NR_connect 203
+#define TARGET_NR_getsockname 204
+#define TARGET_NR_getpeername 205
+#define TARGET_NR_sendto 206
+#define TARGET_NR_recvfrom 207
+#define TARGET_NR_setsockopt 208
+#define TARGET_NR_getsockopt 209
+#define TARGET_NR_shutdown 210
+#define TARGET_NR_sendmsg 211
+#define TARGET_NR_recvmsg 212
+
+/* mm/filemap.c */
+#define TARGET_NR_readahead 213
+
+/* mm/nommu.c, also with MMU */
+#define TARGET_NR_brk 214
+#define TARGET_NR_munmap 215
+#define TARGET_NR_mremap 216
+
+/* security/keys/keyctl.c */
+#define TARGET_NR_add_key 217
+#define TARGET_NR_request_key 218
+#define TARGET_NR_keyctl 219
+
+/* arch/example/kernel/sys_example.c */
+#define TARGET_NR_clone 220
+#define TARGET_NR_execve 221
+
+#define TARGET_NR_3264_mmap 222
+/* mm/fadvise.c */
+#define TARGET_NR_3264_fadvise64 223
+
+/* mm/, CONFIG_MMU only */
+#ifndef __ARCH_NOMMU
+#define TARGET_NR_swapon 224
+#define TARGET_NR_swapoff 225
+#define TARGET_NR_mprotect 226
+#define TARGET_NR_msync 227
+#define TARGET_NR_mlock 228
+#define TARGET_NR_munlock 229
+#define TARGET_NR_mlockall 230
+#define TARGET_NR_munlockall 231
+#define TARGET_NR_mincore 232
+#define TARGET_NR_madvise 233
+#define TARGET_NR_remap_file_pages 234
+#define TARGET_NR_mbind 235
+#define TARGET_NR_get_mempolicy 236
+#define TARGET_NR_set_mempolicy 237
+#define TARGET_NR_migrate_pages 238
+#define TARGET_NR_move_pages 239
+#endif
+
+#define TARGET_NR_rt_tgsigqueueinfo 240
+#define TARGET_NR_perf_event_open 241
+#define TARGET_NR_accept4 242
+#define TARGET_NR_recvmmsg 243
+
+/*
+ * Architectures may provide up to 16 syscalls of their own
+ * starting with this value.
+ */
+#define TARGET_NR_arch_specific_syscall 244
+
+#define TARGET_NR_wait4 260
+#define TARGET_NR_prlimit64 261
+#define TARGET_NR_fanotify_init 262
+#define TARGET_NR_fanotify_mark 263
+#define TARGET_NR_name_to_handle_at 264
+#define TARGET_NR_open_by_handle_at 265
+#define TARGET_NR_clock_adjtime 266
+#define TARGET_NR_syncfs 267
+#define TARGET_NR_setns 268
+#define TARGET_NR_sendmmsg 269
+
+#undef TARGET_NR_syscalls
+#define TARGET_NR_syscalls 270
+
+/*
+ * All syscalls below here should go away really,
+ * these are provided for both review and as a porting
+ * help for the C library version.
+*
+ * Last chance: are any of these important enough to
+ * enable by default?
+ */
+#define TARGET_NR_open 1024
+#define TARGET_NR_link 1025
+#define TARGET_NR_unlink 1026
+#define TARGET_NR_mknod 1027
+#define TARGET_NR_chmod 1028
+#define TARGET_NR_chown 1029
+#define TARGET_NR_mkdir 1030
+#define TARGET_NR_rmdir 1031
+#define TARGET_NR_lchown 1032
+#define TARGET_NR_access 1033
+#define TARGET_NR_rename 1034
+#define TARGET_NR_readlink 1035
+#define TARGET_NR_symlink 1036
+#define TARGET_NR_utimes 1037
+#define TARGET_NR_3264_stat 1038
+#define TARGET_NR_3264_lstat 1039
+
+#undef TARGET_NR_syscalls
+#define TARGET_NR_syscalls (TARGET_NR_3264_lstat+1)
+
+#define TARGET_NR_pipe 1040
+#define TARGET_NR_dup2 1041
+#define TARGET_NR_epoll_create 1042
+#define TARGET_NR_inotify_init 1043
+#define TARGET_NR_eventfd 1044
+#define TARGET_NR_signalfd 1045
+
+#undef TARGET_NR_syscalls
+#define TARGET_NR_syscalls (TARGET_NR_signalfd+1)
+
+
+#define TARGET_NR_sendfile 1046
+#define TARGET_NR_ftruncate 1047
+#define TARGET_NR_truncate 1048
+#define TARGET_NR_stat 1049
+#define TARGET_NR_lstat 1050
+#define TARGET_NR_fstat 1051
+#define TARGET_NR_fcntl 1052
+#define TARGET_NR_fadvise64 1053
+#define __ARCH_WANT_SYS_FADVISE64
+#define TARGET_NR_newfstatat 1054
+#define __ARCH_WANT_SYS_NEWFSTATAT
+#define TARGET_NR_fstatfs 1055
+#define TARGET_NR_statfs 1056
+#define TARGET_NR_lseek 1057
+#define TARGET_NR_mmap 1058
+
+#undef TARGET_NR_syscalls
+#define TARGET_NR_syscalls (TARGET_NR_mmap+1)
+
+#define TARGET_NR_alarm 1059
+#define __ARCH_WANT_SYS_ALARM
+#define TARGET_NR_getpgrp 1060
+#define __ARCH_WANT_SYS_GETPGRP
+#define TARGET_NR_pause 1061
+#define __ARCH_WANT_SYS_PAUSE
+#define TARGET_NR_time 1062
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_COMPAT_SYS_TIME
+#define TARGET_NR_utime 1063
+#define __ARCH_WANT_SYS_UTIME
+
+#define TARGET_NR_creat 1064
+#define TARGET_NR_getdents 1065
+#define __ARCH_WANT_SYS_GETDENTS
+#define TARGET_NR_futimesat 1066
+#define TARGET_NR_select 1067
+#define __ARCH_WANT_SYS_SELECT
+#define TARGET_NR_poll 1068
+#define TARGET_NR_epoll_wait 1069
+#define TARGET_NR_ustat 1070
+#define TARGET_NR_vfork 1071
+#define TARGET_NR_oldwait4 1072
+#define TARGET_NR_recv 1073
+#define TARGET_NR_send 1074
+#define TARGET_NR_bdflush 1075
+#define TARGET_NR_umount 1076
+#define __ARCH_WANT_SYS_OLDUMOUNT
+#define TARGET_NR_uselib 1077
+#define TARGET_NR__sysctl 1078
+
+#define TARGET_NR_fork 1079
+
+#undef TARGET_NR_syscalls
+#define TARGET_NR_syscalls (TARGET_NR_fork+1)
+
+
+/*
+ * 32 bit systems traditionally used different
+ * syscalls for off_t and loff_t arguments, while
+ * 64 bit systems only need the off_t version.
+ * For new 32 bit platforms, there is no need to
+ * implement the old 32 bit off_t syscalls, so
+ * they take different names.
+ * Here we map the numbers so that both versions
+ * use the same syscall table layout.
+ */
+
+#define TARGET_NR_fcntl64 TARGET_NR_3264_fcntl
+#define TARGET_NR_statfs64 TARGET_NR_3264_statfs
+#define TARGET_NR_fstatfs64 TARGET_NR_3264_fstatfs
+#define TARGET_NR_truncate64 TARGET_NR_3264_truncate
+#define TARGET_NR_ftruncate64 TARGET_NR_3264_ftruncate
+#define TARGET_NR_llseek TARGET_NR_3264_lseek
+#define TARGET_NR_sendfile64 TARGET_NR_3264_sendfile
+#define TARGET_NR_fstatat64 TARGET_NR_3264_fstatat
+#define TARGET_NR_fstat64 TARGET_NR_3264_fstat
+#define TARGET_NR_mmap2 TARGET_NR_3264_mmap
+#define TARGET_NR_fadvise64_64 TARGET_NR_3264_fadvise64
+
+#ifdef TARGET_NR_3264_stat
+#define TARGET_NR_stat64 TARGET_NR_3264_stat
+#define TARGET_NR_lstat64 TARGET_NR_3264_lstat
+#endif
diff --git a/linux-user/openrisc/target_signal.h b/linux-user/openrisc/target_signal.h
new file mode 100644
index 0000000..964aed6
--- /dev/null
+++ b/linux-user/openrisc/target_signal.h
@@ -0,0 +1,26 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_long ss_sp;
+ abi_ulong ss_size;
+ abi_long ss_flags;
+} target_stack_t;
+
+/* sigaltstack controls */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 2048
+#define TARGET_SIGSTKSZ 8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUOpenRISCState *state)
+{
+ return state->gpr[1];
+}
+
+#endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/openrisc/termbits.h b/linux-user/openrisc/termbits.h
new file mode 100644
index 0000000..373af77
--- /dev/null
+++ b/linux-user/openrisc/termbits.h
@@ -0,0 +1,294 @@
+typedef unsigned char target_openrisc_cc; /*cc_t*/
+typedef unsigned int target_openrisc_speed; /*speed_t*/
+typedef unsigned int target_openrisc_tcflag; /*tcflag_t*/
+
+#define TARGET_NCCS 19
+struct target_termios {
+ target_openrisc_tcflag c_iflag; /* input mode flags */
+ target_openrisc_tcflag c_oflag; /* output mode flags */
+ target_openrisc_tcflag c_cflag; /* control mode flags */
+ target_openrisc_tcflag c_lflag; /* local mode flags */
+ target_openrisc_cc c_line; /* line discipline */
+ target_openrisc_cc c_cc[TARGET_NCCS]; /* control characters */
+};
+
+struct target_termios2 {
+ target_openrisc_tcflag c_iflag; /* input mode flags */
+ target_openrisc_tcflag c_oflag; /* output mode flags */
+ target_openrisc_tcflag c_cflag; /* control mode flags */
+ target_openrisc_tcflag c_lflag; /* local mode flags */
+ target_openrisc_cc c_line; /* line discipline */
+ target_openrisc_cc c_cc[TARGET_NCCS]; /* control characters */
+ target_openrisc_speed c_ispeed; /* input speed */
+ target_openrisc_speed c_ospeed; /* output speed */
+};
+
+struct target_termios3 {
+ target_openrisc_tcflag c_iflag; /* input mode flags */
+ target_openrisc_tcflag c_oflag; /* output mode flags */
+ target_openrisc_tcflag c_cflag; /* control mode flags */
+ target_openrisc_tcflag c_lflag; /* local mode flags */
+ target_openrisc_cc c_line; /* line discipline */
+ target_openrisc_cc c_cc[TARGET_NCCS]; /* control characters */
+ target_openrisc_speed c_ispeed; /* input speed */
+ target_openrisc_speed c_ospeed; /* output speed */
+};
+
+/* c_cc characters */
+#define TARGET_VINTR 0
+#define TARGET_VQUIT 1
+#define TARGET_VERASE 2
+#define TARGET_VKILL 3
+#define TARGET_VEOF 4
+#define TARGET_VTIME 5
+#define TARGET_VMIN 6
+#define TARGET_VSWTC 7
+#define TARGET_VSTART 8
+#define TARGET_VSTOP 9
+#define TARGET_VSUSP 10
+#define TARGET_VEOL 11
+#define TARGET_VREPRINT 12
+#define TARGET_VDISCARD 13
+#define TARGET_VWERASE 14
+#define TARGET_VLNEXT 15
+#define TARGET_VEOL2 16
+
+/* c_iflag bits */
+#define TARGET_IGNBRK 0000001
+#define TARGET_BRKINT 0000002
+#define TARGET_IGNPAR 0000004
+#define TARGET_PARMRK 0000010
+#define TARGET_INPCK 0000020
+#define TARGET_ISTRIP 0000040
+#define TARGET_INLCR 0000100
+#define TARGET_IGNCR 0000200
+#define TARGET_ICRNL 0000400
+#define TARGET_IUCLC 0001000
+#define TARGET_IXON 0002000
+#define TARGET_IXANY 0004000
+#define TARGET_IXOFF 0010000
+#define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8 0040000
+
+/* c_oflag bits */
+#define TARGET_OPOST 0000001
+#define TARGET_OLCUC 0000002
+#define TARGET_ONLCR 0000004
+#define TARGET_OCRNL 0000010
+#define TARGET_ONOCR 0000020
+#define TARGET_ONLRET 0000040
+#define TARGET_OFILL 0000100
+#define TARGET_OFDEL 0000200
+#define TARGET_NLDLY 0000400
+#define TARGET_NL0 0000000
+#define TARGET_NL1 0000400
+#define TARGET_CRDLY 0003000
+#define TARGET_CR0 0000000
+#define TARGET_CR1 0001000
+#define TARGET_CR2 0002000
+#define TARGET_CR3 0003000
+#define TARGET_TABDLY 0014000
+#define TARGET_TAB0 0000000
+#define TARGET_TAB1 0004000
+#define TARGET_TAB2 0010000
+#define TARGET_TAB3 0014000
+#define TARGET_XTABS 0014000
+#define TARGET_BSDLY 0020000
+#define TARGET_BS0 0000000
+#define TARGET_BS1 0020000
+#define TARGET_VTDLY 0040000
+#define TARGET_VT0 0000000
+#define TARGET_VT1 0040000
+#define TARGET_FFDLY 0100000
+#define TARGET_FF0 0000000
+#define TARGET_FF1 0100000
+
+/* c_cflag bit meaning */
+#define TARGET_CBAUD 0010017
+#define TARGET_B0 0000000 /* hang up */
+#define TARGET_B50 0000001
+#define TARGET_B75 0000002
+#define TARGET_B110 0000003
+#define TARGET_B134 0000004
+#define TARGET_B150 0000005
+#define TARGET_B200 0000006
+#define TARGET_B300 0000007
+#define TARGET_B600 0000010
+#define TARGET_B1200 0000011
+#define TARGET_B1800 0000012
+#define TARGET_B2400 0000013
+#define TARGET_B4800 0000014
+#define TARGET_B9600 0000015
+#define TARGET_B19200 0000016
+#define TARGET_B38400 0000017
+#define TARGET_EXTA B19200
+#define TARGET_EXTB B38400
+#define TARGET_CSIZE 0000060
+#define TARGET_CS5 0000000
+#define TARGET_CS6 0000020
+#define TARGET_CS7 0000040
+#define TARGET_CS8 0000060
+#define TARGET_CSTOPB 0000100
+#define TARGET_CREAD 0000200
+#define TARGET_PARENB 0000400
+#define TARGET_PARODD 0001000
+#define TARGET_HUPCL 0002000
+#define TARGET_CLOCAL 0004000
+#define TARGET_CBAUDEX 0010000
+#define TARGET_BOTHER 0010000
+#define TARGET_B57600 0010001
+#define TARGET_B115200 0010002
+#define TARGET_B230400 0010003
+#define TARGET_B460800 0010004
+#define TARGET_B500000 0010005
+#define TARGET_B576000 0010006
+#define TARGET_B921600 0010007
+#define TARGET_B1000000 0010010
+#define TARGET_B1152000 0010011
+#define TARGET_B1500000 0010012
+#define TARGET_B2000000 0010013
+#define TARGET_B2500000 0010014
+#define TARGET_B3000000 0010015
+#define TARGET_B3500000 0010016
+#define TARGET_B4000000 0010017
+#define TARGET_CIBAUD 002003600000 /* input baud rate */
+#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */
+#define TARGET_CRTSCTS 020000000000 /* flow control */
+
+#define TARGET_IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
+
+/* c_lflag bits */
+#define TARGET_ISIG 0000001
+#define TARGET_ICANON 0000002
+#define TARGET_XCASE 0000004
+#define TARGET_ECHO 0000010
+#define TARGET_ECHOE 0000020
+#define TARGET_ECHOK 0000040
+#define TARGET_ECHONL 0000100
+#define TARGET_NOFLSH 0000200
+#define TARGET_TOSTOP 0000400
+#define TARGET_ECHOCTL 0001000
+#define TARGET_ECHOPRT 0002000
+#define TARGET_ECHOKE 0004000
+#define TARGET_FLUSHO 0010000
+#define TARGET_PENDIN 0040000
+#define TARGET_IEXTEN 0100000
+#define TARGET_EXTPROC 0200000
+
+/* tcflow() and TCXONC use these */
+#define TARGET_TCOOFF 0
+#define TARGET_TCOON 1
+#define TARGET_TCIOFF 2
+#define TARGET_TCION 3
+
+/* tcflush() and TCFLSH use these */
+#define TARGET_TCIFLUSH 0
+#define TARGET_TCOFLUSH 1
+#define TARGET_TCIOFLUSH 2
+
+/* tcsetattr uses these */
+#define TARGET_TCSANOW 0
+#define TARGET_TCSADRAIN 1
+#define TARGET_TCSAFLUSH 2
+
+/* ioctls */
+#define TARGET_TCGETS 0x5401
+#define TARGET_TCSETS 0x5402
+#define TARGET_TCSETSW 0x5403
+#define TARGET_TCSETSF 0x5404
+#define TARGET_TCGETA 0x5405
+#define TARGET_TCSETA 0x5406
+#define TARGET_TCSETAW 0x5407
+#define TARGET_TCSETAF 0x5408
+#define TARGET_TCSBRK 0x5409
+#define TARGET_TCXONC 0x540A
+#define TARGET_TCFLSH 0x540B
+#define TARGET_TIOCEXCL 0x540C
+#define TARGET_TIOCNXCL 0x540D
+#define TARGET_TIOCSCTTY 0x540E
+#define TARGET_TIOCGPGRP 0x540F
+#define TARGET_TIOCSPGRP 0x5410
+#define TARGET_TIOCOUTQ 0x5411
+#define TARGET_TIOCSTI 0x5412
+#define TARGET_TIOCGWINSZ 0x5413
+#define TARGET_TIOCSWINSZ 0x5414
+#define TARGET_TIOCMGET 0x5415
+#define TARGET_TIOCMBIS 0x5416
+#define TARGET_TIOCMBIC 0x5417
+#define TARGET_TIOCMSET 0x5418
+#define TARGET_TIOCGSOFTCAR 0x5419
+#define TARGET_TIOCSSOFTCAR 0x541A
+#define TARGET_FIONREAD 0x541B
+#define TARGET_TIOCINQ FIONREAD
+#define TARGET_TIOCLINUX 0x541C
+#define TARGET_TIOCCONS 0x541D
+#define TARGET_TIOCGSERIAL 0x541E
+#define TARGET_TIOCSSERIAL 0x541F
+#define TARGET_TIOCPKT 0x5420
+#define TARGET_FIONBIO 0x5421
+#define TARGET_TIOCNOTTY 0x5422
+#define TARGET_TIOCSETD 0x5423
+#define TARGET_TIOCGETD 0x5424
+#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
+#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */
+#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */
+#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TARGET_TCGETS2 TARGET_IOR('T', 0x2A, struct termios2)
+#define TARGET_TCSETS2 TARGET_IOW('T', 0x2B, struct termios2)
+#define TARGET_TCSETSW2 TARGET_IOW('T', 0x2C, struct termios2)
+#define TARGET_TCSETSF2 TARGET_IOW('T', 0x2D, struct termios2)
+#define TARGET_TIOCGRS485 0x542E
+#ifndef TARGET_TIOCSRS485
+#define TARGET_TIOCSRS485 0x542F
+#endif
+/* Get Pty Number (of pty-mux device) */
+#define TARGET_TIOCGPTN TARGET_IOR('T', 0x30, unsigned int)
+/* Lock/unlock Pty */
+#define TARGET_TIOCSPTLCK TARGET_IOW('T', 0x31, int)
+/* Get primary device node of /dev/console */
+#define TARGET_TIOCGDEV TARGET_IOR('T', 0x32, unsigned int)
+#define TARGET_TCGETX 0x5432 /* SYS5 TCGETX compatibility */
+#define TARGET_TCSETX 0x5433
+#define TARGET_TCSETXF 0x5434
+#define TARGET_TCSETXW 0x5435
+/* pty: generate signal */
+#define TARGET_TIOCSIG TARGET_IOW('T', 0x36, int)
+#define TARGET_TIOCVHANGUP 0x5437
+
+#define TARGET_FIONCLEX 0x5450
+#define TARGET_FIOCLEX 0x5451
+#define TARGET_FIOASYNC 0x5452
+#define TARGET_TIOCSERCONFIG 0x5453
+#define TARGET_TIOCSERGWILD 0x5454
+#define TARGET_TIOCSERSWILD 0x5455
+#define TARGET_TIOCGLCKTRMIOS 0x5456
+#define TARGET_TIOCSLCKTRMIOS 0x5457
+#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */
+#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */
+#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */
+#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+/* wait for a change on serial input line(s) */
+#define TARGET_TIOCMIWAIT 0x545C
+/* read serial port inline interrupt counts */
+#define TARGET_TIOCGICOUNT 0x545D
+
+/*
+ * Some arches already define TARGET_FIOQSIZE due to a historical
+ * conflict with a Hayes modem-specific ioctl value.
+ */
+#ifndef TARGET_FIOQSIZE
+#define TARGET_FIOQSIZE 0x5460
+#endif
+
+/* Used for packet mode */
+#define TARGET_TIOCPKT_DATA 0
+#define TARGET_TIOCPKT_FLUSHREAD 1
+#define TARGET_TIOCPKT_FLUSHWRITE 2
+#define TARGET_TIOCPKT_STOP 4
+#define TARGET_TIOCPKT_START 8
+#define TARGET_TIOCPKT_NOSTOP 16
+#define TARGET_TIOCPKT_DOSTOP 32
+#define TARGET_TIOCPKT_IOCTL 64
+
+#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 14/15] target-or32: Add linux user support
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
` (12 preceding siblings ...)
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 13/15] target-or32: Add linux syscall, signal and termbits Jia Liu
@ 2012-07-13 4:35 ` Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 15/15] target-or32: Add testcases Jia Liu
14 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:35 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add QEMU OpenRISC linux user support.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
configure | 1 +
default-configs/or32-linux-user.mak | 1 +
linux-user/elfload.c | 41 +++++++
linux-user/main.c | 100 +++++++++++++++
linux-user/signal.c | 229 +++++++++++++++++++++++++++++++++++
linux-user/syscall.c | 2 +-
linux-user/syscall_defs.h | 40 +++++-
target-openrisc/cpu.h | 12 ++
8 files changed, 422 insertions(+), 4 deletions(-)
create mode 100644 default-configs/or32-linux-user.mak
diff --git a/configure b/configure
index 3a53a92..2acb97e 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..808c1f9
--- /dev/null
+++ b/default-configs/or32-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for or32-linux-user
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index f3b1552..6b622d4 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 d0e0e4f..a0ab8e8 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2306,6 +2306,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:
+ qemu_log("\nReset request, exit, pc is %#x\n", env->pc);
+ exit(1);
+ break;
+ case EXCP_BUSERR:
+ qemu_log("\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:
+ qemu_log("\nTick time interrupt pc is %#x\n", env->pc);
+ break;
+ case EXCP_ALIGN:
+ qemu_log("\nAlignment pc is %#x\n", env->pc);
+ gdbsig = SIGBUS;
+ break;
+ case EXCP_ILLEGAL:
+ qemu_log("\nIllegal instructionpc is %#x\n", env->pc);
+ gdbsig = SIGILL;
+ break;
+ case EXCP_INT:
+ qemu_log("\nExternal interruptpc is %#x\n", env->pc);
+ break;
+ case EXCP_DTLBMISS:
+ case EXCP_ITLBMISS:
+ qemu_log("\nTLB miss\n");
+ break;
+ case EXCP_RANGE:
+ qemu_log("\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:
+ qemu_log("\nFloating point error\n");
+ break;
+ case EXCP_TRAP:
+ qemu_log("\nTrap\n");
+ gdbsig = SIGTRAP;
+ break;
+ case EXCP_NR:
+ qemu_log("\nNR\n");
+ break;
+ default:
+ qemu_log("\nqemu: 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)
{
@@ -3386,6 +3473,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";
@@ -3788,6 +3877,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 43346dc..97f30d9 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)
+{
+ qemu_log("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)
+{
+
+ qemu_log("do_sigreturn: not implemented\n");
+ return -TARGET_ENOSYS;
+}
+
+long do_rt_sigreturn(CPUOpenRISCState *env)
+{
+ qemu_log("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 539af3f..630a455 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..cfece21 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -59,7 +59,7 @@
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
|| defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) \
- || defined(TARGET_S390X)
+ || defined(TARGET_S390X) || defined(TARGET_OPENRISC)
#define TARGET_IOC_SIZEBITS 14
#define TARGET_IOC_DIRBITS 2
@@ -323,7 +323,7 @@ int do_sigaction(int sig, const struct target_sigaction *act,
|| defined(TARGET_PPC) || defined(TARGET_MIPS) || defined(TARGET_SH4) \
|| defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) \
|| defined(TARGET_MICROBLAZE) || defined(TARGET_UNICORE32) \
- || defined(TARGET_S390X)
+ || defined(TARGET_S390X) || defined(TARGET_OPENRISC)
#if defined(TARGET_SPARC)
#define TARGET_SA_NOCLDSTOP 8u
@@ -344,6 +344,14 @@ int do_sigaction(int sig, const struct target_sigaction *act,
#if !defined(TARGET_ABI_MIPSN32) && !defined(TARGET_ABI_MIPSN64)
#define TARGET_SA_RESTORER 0x04000000 /* Only for O32 */
#endif
+#elif defined(TARGET_OPENRISC)
+#define TARGET_SA_NOCLDSTOP 0x00000001
+#define TARGET_SA_NOCLDWAIT 0x00000002
+#define TARGET_SA_SIGINFO 0x00000004
+#define TARGET_SA_ONSTACK 0x08000000
+#define TARGET_SA_RESTART 0x10000000
+#define TARGET_SA_NODEFER 0x40000000
+#define TARGET_SA_RESETHAND 0x80000000
#elif defined(TARGET_ALPHA)
#define TARGET_SA_ONSTACK 0x00000001
#define TARGET_SA_RESTART 0x00000002
@@ -448,6 +456,7 @@ int do_sigaction(int sig, const struct target_sigaction *act,
#else
+/* OpenRISC Using the general signals */
#define TARGET_SIGHUP 1
#define TARGET_SIGINT 2
#define TARGET_SIGQUIT 3
@@ -1086,7 +1095,8 @@ struct target_winsize {
#endif
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) \
- || defined(TARGET_CRIS) || defined(TARGET_UNICORE32)
+ || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) \
+ || defined(TARGET_OPENRISC)
struct target_stat {
unsigned short st_dev;
unsigned short __pad1;
@@ -1783,6 +1793,30 @@ struct target_stat {
abi_long st_blocks;
abi_ulong __unused[3];
};
+#elif defined(TARGET_OPENRISC)
+struct target_stat {
+ abi_ulong st_dev;
+ abi_ulong st_ino;
+ abi_ulong st_nlink;
+
+ unsigned int st_mode;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned int __pad0;
+ abi_ulong st_rdev;
+ abi_long st_size;
+ abi_long st_blksize;
+ abi_long st_blocks; /* Number 512-byte blocks allocated. */
+
+ abi_ulong target_st_atime;
+ abi_ulong target_st_atime_nsec;
+ abi_ulong target_st_mtime;
+ abi_ulong target_st_mtime_nsec;
+ abi_ulong target_st_ctime;
+ abi_ulong target_st_ctime_nsec;
+
+ abi_long __unused[3];
+};
#else
#error unsupported CPU
#endif
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 6506665..de21a87 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -367,11 +367,13 @@ void openrisc_translate_init(void);
int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env,
target_ulong address,
int rw, int mmu_idx);
+int cpu_openrisc_signal_handler(int host_signum, void *pinfo, void *puc);
#define cpu_list cpu_openrisc_list
#define cpu_exec cpu_openrisc_exec
#define cpu_gen_code cpu_openrisc_gen_code
#define cpu_handle_mmu_fault cpu_openrisc_handle_mmu_fault
+#define cpu_signal_handler cpu_openrisc_signal_handler
#ifndef CONFIG_USER_ONLY
/* hw/openrisc_pic.c */
@@ -404,6 +406,16 @@ static inline CPUOpenRISCState *cpu_init(const char *cpu_model)
return NULL;
}
+#if defined(CONFIG_USER_ONLY)
+static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->gpr[1] = newsp;
+ }
+ env->gpr[2] = 0;
+}
+#endif
+
#include "cpu-all.h"
static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH v9 15/15] target-or32: Add testcases
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
` (13 preceding siblings ...)
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 14/15] target-or32: Add linux user support Jia Liu
@ 2012-07-13 4:35 ` Jia Liu
14 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-13 4:35 UTC (permalink / raw)
To: qemu-devel; +Cc: afaerber
Add testcases for OpenRISC.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
tests/tcg/openrisc/Makefile | 71 ++++++++++++++++++++++++++
tests/tcg/openrisc/test_add.c | 43 ++++++++++++++++
tests/tcg/openrisc/test_addc.c | 38 ++++++++++++++
tests/tcg/openrisc/test_addi.c | 33 ++++++++++++
tests/tcg/openrisc/test_addic.c | 33 ++++++++++++
tests/tcg/openrisc/test_and_or.c | 65 +++++++++++++++++++++++
tests/tcg/openrisc/test_bf.c | 47 +++++++++++++++++
tests/tcg/openrisc/test_bnf.c | 51 ++++++++++++++++++
tests/tcg/openrisc/test_div.c | 54 ++++++++++++++++++++
tests/tcg/openrisc/test_divu.c | 34 ++++++++++++
tests/tcg/openrisc/test_extx.c | 78 ++++++++++++++++++++++++++++
tests/tcg/openrisc/test_fx.c | 57 +++++++++++++++++++++
tests/tcg/openrisc/test_j.c | 26 ++++++++++
tests/tcg/openrisc/test_jal.c | 26 ++++++++++
tests/tcg/openrisc/test_lf_add.c | 39 ++++++++++++++
tests/tcg/openrisc/test_lf_div.c | 37 ++++++++++++++
tests/tcg/openrisc/test_lf_eqs.c | 88 ++++++++++++++++++++++++++++++++
tests/tcg/openrisc/test_lf_ges.c | 88 ++++++++++++++++++++++++++++++++
tests/tcg/openrisc/test_lf_gts.c | 86 +++++++++++++++++++++++++++++++
tests/tcg/openrisc/test_lf_les.c | 88 ++++++++++++++++++++++++++++++++
tests/tcg/openrisc/test_lf_lts.c | 92 +++++++++++++++++++++++++++++++++
tests/tcg/openrisc/test_lf_mul.c | 22 ++++++++
tests/tcg/openrisc/test_lf_nes.c | 89 ++++++++++++++++++++++++++++++++
tests/tcg/openrisc/test_lf_rem.c | 32 ++++++++++++
tests/tcg/openrisc/test_lf_sub.c | 35 +++++++++++++
tests/tcg/openrisc/test_logic.c | 105 ++++++++++++++++++++++++++++++++++++++
tests/tcg/openrisc/test_lx.c | 84 ++++++++++++++++++++++++++++++
tests/tcg/openrisc/test_movhi.c | 31 +++++++++++
tests/tcg/openrisc/test_mul.c | 48 +++++++++++++++++
tests/tcg/openrisc/test_muli.c | 48 +++++++++++++++++
tests/tcg/openrisc/test_mulu.c | 48 +++++++++++++++++
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 | 39 ++++++++++++++
tests/tcg/openrisc/test_sfltu.c | 43 ++++++++++++++++
tests/tcg/openrisc/test_sfltui.c | 39 ++++++++++++++
tests/tcg/openrisc/test_sfne.c | 43 ++++++++++++++++
tests/tcg/openrisc/test_sfnei.c | 39 ++++++++++++++
tests/tcg/openrisc/test_sub.c | 35 +++++++++++++
52 files changed, 2566 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_divu.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_eqs.c
create mode 100644 tests/tcg/openrisc/test_lf_ges.c
create mode 100644 tests/tcg/openrisc/test_lf_gts.c
create mode 100644 tests/tcg/openrisc/test_lf_les.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_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_muli.c
create mode 100644 tests/tcg/openrisc/test_mulu.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
create mode 100644 tests/tcg/openrisc/test_sub.c
diff --git a/tests/tcg/openrisc/Makefile b/tests/tcg/openrisc/Makefile
new file mode 100644
index 0000000..7e65888
--- /dev/null
+++ b/tests/tcg/openrisc/Makefile
@@ -0,0 +1,71 @@
+-include ../../config-host.mak
+
+CROSS = or32-linux-
+
+SIM = qemu-or32
+
+CC = $(CROSS)gcc
+
+TESTCASES = test_add.tst
+TESTCASES += test_sub.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_divu.tst
+TESTCASES += test_extx.tst
+TESTCASES += test_fx.tst
+TESTCASES += test_jal.tst
+TESTCASES += test_j.tst
+TESTCASES += test_lf_div.tst
+TESTCASES += test_lf_eqs.tst
+TESTCASES += test_lf_ges.tst
+TESTCASES += test_lf_gts.tst
+TESTCASES += test_lf_les.tst
+TESTCASES += test_lf_lts.tst
+TESTCASES += test_lf_mul.tst
+TESTCASES += test_lf_nes.tst
+TESTCASES += test_lf_rem.tst
+TESTCASES += test_lf_sub.tst
+TESTCASES += test_lf_add.tst
+TESTCASES += test_logic.tst
+TESTCASES += test_lx.tst
+TESTCASES += test_movhi.tst
+TESTCASES += test_mul.tst
+TESTCASES += test_mulu.tst
+TESTCASES += test_muli.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) -rf $(TESTCASES)
diff --git a/tests/tcg/openrisc/test_add.c b/tests/tcg/openrisc/test_add.c
new file mode 100644
index 0000000..3d23592
--- /dev/null
+++ b/tests/tcg/openrisc/test_add.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, d;
+ 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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ a = 0x7fffffff;
+ b = 0x1;
+ __asm
+ ("l.add %0, %1, %2\n\t"
+ : "=r"(d)
+ : "r"(b), "r"(a)
+ );
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_addc.c b/tests/tcg/openrisc/test_addc.c
new file mode 100644
index 0000000..05d18f8
--- /dev/null
+++ b/tests/tcg/openrisc/test_addc.c
@@ -0,0 +1,38 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x01;
+ c = 0xffffffff;
+ result = 1;
+ __asm
+ ("l.addc %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("first addc error\n");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_addi.c b/tests/tcg/openrisc/test_addi.c
new file mode 100644
index 0000000..bbf5a5f
--- /dev/null
+++ b/tests/tcg/openrisc/test_addi.c
@@ -0,0 +1,33 @@
+#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");
+ return -1;
+ }
+
+ b = 0x010000;
+ result = 0xffff;
+ __asm
+ ("l.addi %0, %1, 0xffff\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("addi error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_addic.c b/tests/tcg/openrisc/test_addic.c
new file mode 100644
index 0000000..4ba7432
--- /dev/null
+++ b/tests/tcg/openrisc/test_addic.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 1;
+ result = 0x1;
+ __asm
+ ("l.addic %0, %0, 0xffff\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("first addic error\n");
+ return -1;
+ }
+
+ 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("second addic error\n");
+ return -1;
+ }
+
+ 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..810d868
--- /dev/null
+++ b/tests/tcg/openrisc/test_and_or.c
@@ -0,0 +1,65 @@
+#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");
+ return -1;
+ }
+
+ result = 0x2;
+ __asm
+ ("l.andi %0, %1, 0x3\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("andi error %x\n", a);
+ return -1;
+ }
+
+ result = 0x3;
+ __asm
+ ("l.or %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("or error\n");
+ return -1;
+ }
+
+ result = 0x3;
+ __asm
+ ("l.xor %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("xor error\n");
+ return -1;
+ }
+
+ __asm
+ ("l.xori %0, %1, 0x1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("xori error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_bf.c b/tests/tcg/openrisc/test_bf.c
new file mode 100644
index 0000000..79f3fb9
--- /dev/null
+++ b/tests/tcg/openrisc/test_bf.c
@@ -0,0 +1,47 @@
+#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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_bnf.c b/tests/tcg/openrisc/test_bnf.c
new file mode 100644
index 0000000..f716215
--- /dev/null
+++ b/tests/tcg/openrisc/test_bnf.c
@@ -0,0 +1,51 @@
+#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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_div.c b/tests/tcg/openrisc/test_div.c
new file mode 100644
index 0000000..9b65f6e
--- /dev/null
+++ b/tests/tcg/openrisc/test_div.c
@@ -0,0 +1,54 @@
+#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");
+ return -1;
+ }
+
+ result = 0x4;
+ __asm
+ ("l.div %0, %1, %0\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("div error\n");
+ return -1;
+ }
+
+ b = 0xffffffff;
+ c = 0x80000000;
+ result = 0;
+ __asm
+ ("l.div %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("div error\n");
+ return -1;
+ }
+
+ b = 0x80000000;
+ c = 0xffffffff;
+ __asm
+ ("l.div %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_divu.c b/tests/tcg/openrisc/test_divu.c
new file mode 100644
index 0000000..bff9e3e
--- /dev/null
+++ b/tests/tcg/openrisc/test_divu.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x120;
+ c = 0x4;
+ result = 0x48;
+
+ __asm
+ ("l.divu %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("divu error\n");
+ return -1;
+ }
+
+ result = 0x4;
+ __asm
+ ("l.divu %0, %1, %0\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("divu error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_extx.c b/tests/tcg/openrisc/test_extx.c
new file mode 100644
index 0000000..0922148
--- /dev/null
+++ b/tests/tcg/openrisc/test_extx.c
@@ -0,0 +1,78 @@
+#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");
+ return -1;
+ }
+
+ result = 0x83;
+ __asm
+ ("l.extbz %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("extbz error\n");
+ return -1;
+ }
+
+ b = 0x8083;
+ result = 0xffff8083;
+ __asm
+ ("l.exths %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("exths error\n");
+ return -1;
+ }
+
+ result = 0x8083;
+ __asm
+ ("l.exthz %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("exthz error\n");
+ return -1;
+ }
+
+ b = 0x11;
+ result = 0x11;
+ __asm
+ ("l.extws %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+
+ if (a != result) {
+ printf("extws error\n");
+ return -1;
+ }
+
+ __asm
+ ("l.extwz %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("extwz error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_fx.c b/tests/tcg/openrisc/test_fx.c
new file mode 100644
index 0000000..df86000
--- /dev/null
+++ b/tests/tcg/openrisc/test_fx.c
@@ -0,0 +1,57 @@
+#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");
+ return -1;
+ }
+
+ b = 0x0;
+ result = 0;
+ __asm
+ ("l.ff1 %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("ff1 error\n");
+ return -1;
+ }
+
+ b = 0x123;
+ result = 9;
+ __asm
+ ("l.fl1 %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("fl1 error\n");
+ return -1;
+ }
+
+ b = 0x0;
+ result = 0;
+ __asm
+ ("l.fl1 %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("fl1 error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_j.c b/tests/tcg/openrisc/test_j.c
new file mode 100644
index 0000000..9ddf8bf
--- /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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_jal.c b/tests/tcg/openrisc/test_jal.c
new file mode 100644
index 0000000..7e2da40
--- /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 -1;
+ }
+
+ 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..e00212d
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_add.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+ float a, b;
+ float res2;
+
+ a = 1.5;
+ b = 2.5;
+ res2 = 4.0;
+ __asm
+ ("lf.add.s %0, %0, %1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != res2) {
+ printf("lf.add.s error, %f\n", a);
+ return -1;
+ }
+
+/* double c, d;
+ double res1;
+
+ c = 1.5;
+ d = 1.5;
+ res1 = 3.00;
+ __asm
+ ("lf.add.d %0, %1, %2\n\t"
+ : "+r"(c)
+ : "r"(d)
+ );
+
+ if ((e - res1) > 0.002) {
+ printf("lf.add.d error, %f\n", e - res1);
+ return -1;
+ }*/
+
+ 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..70b5d1c
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_div.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+
+int main(void)
+{
+ float a, b, c;
+ float result;
+
+ b = 1.5;
+ c = 0.5;
+ result = 3.0;
+ __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 -1;
+ }
+
+/* double a, b, c, res;
+
+ 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");
+ return -1;
+ }*/
+
+ 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..a176bd6
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_eqs.c
@@ -0,0 +1,88 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, result;
+ float b, c;
+
+ a = 0x1;
+ b = 122.5;
+ c = 123.5;
+ 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");
+ return -1;
+ }
+
+ b = 13.5;
+ c = 13.5;
+ 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 -1;
+ }
+
+/* double b, c;
+ double result;
+ int a;
+
+ a = 0x1;
+ b = 122.5;
+ c = 133.5;
+ 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");
+ return -1;
+ }
+
+ double c, d, res;
+ int e = 0;
+ c = 11.5;
+ d = 11.5;
+ res = 1;
+ __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"(e)
+ : "r"(c), "r"(d)
+ );
+ if (e != res) {
+ printf("lf.sfeq.d error\n");
+ return -1;
+ }*/
+
+ 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..98e7f50
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_ges.c
@@ -0,0 +1,88 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, result;
+ float b, c;
+
+ a = 0;
+ b = 122.5;
+ c = 123.5;
+ 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");
+ return -1;
+ }
+
+ b = 133.5;
+ c = 13.5;
+ 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 -1;
+ }
+
+/* int a, result;
+ double b, c;
+
+ a = 0x1;
+ b = 122.5;
+ c = 123.5;
+ 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");
+ return -1;
+ }
+
+ b = 133.5;
+ c = 13.5;
+ 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 -1;
+ }*/
+
+ 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..f3df279
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_gts.c
@@ -0,0 +1,86 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, result;
+ float b, c;
+
+ a = 0;
+ b = 122.5;
+ c = 123.5;
+ 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");
+ return -1;
+ }
+
+ b = 133.5;
+ c = 13.5;
+ 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 -1;
+ }
+
+/* int a, result;
+ double b, c;
+
+ a = 0;
+ b = 122.5;
+ c = 123.5;
+ 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");
+ return -1;
+ }
+
+ b = 133.5;
+ c = 13.5;
+ 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 -1;
+ }*/
+
+ 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..046c511
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_les.c
@@ -0,0 +1,88 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ float b, c;
+ int result;
+
+ a = 0;
+ b = 1234.2;
+ c = 12.4;
+ 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");
+ return -1;
+ }
+
+ b = 1.1;
+ c = 19.4;
+ 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 -1;
+ }
+
+/* int a;
+ double b, c;
+ int result;
+
+ a = 0;
+ b = 1212.5;
+ c = 123.5;
+ 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");
+ return -1;
+ }
+
+ b = 13.5;
+ c = 113.5;
+ 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 -1;
+ }*/
+
+ 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..fa56721
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_lts.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ float b, c, d;
+ int result;
+
+ a = 0;
+ b = 124.5;
+ c = 1.4;
+ result = 1;
+ __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");
+ return -1;
+ }
+
+ a = 0;
+ b = 11.1;
+ c = 13.1;
+ d = 1.0;
+ result = 2;
+ __asm
+ ("1:\n\t"
+ "lf.add.s %1, %1, %3\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "lf.sflt.s %1, %2\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c), "r"(d)
+ );
+ if (a != result) {
+ printf("lf.sflt.s error\n");
+ return -1;
+ }
+
+/* int a;
+ double b, c;
+ int result;
+
+ a = 0;
+ b = 1432.1;
+ c = 2.4;
+ 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");
+ return -1;
+ }
+
+ a = 0;
+ b = 1.1;
+ c = 19.7;
+ result = 2;
+ __asm
+ ("lf.sflt.d %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.addi %0, %0, 1\n\t"
+ : "+r"(a), "+r"(b)
+ : "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sflt.d error\n");
+ return -1;
+ }*/
+
+ 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..bc8ad80
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_mul.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+int main(void)
+{
+ float a, b, c;
+ float result;
+
+ b = 1.5;
+ c = 4.0;
+ result = 6.0;
+ __asm
+ ("lf.mul.s %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.mul.s error\n");
+ return -1;
+ }
+
+ 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..6136310
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_nes.c
@@ -0,0 +1,89 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ float b, c;
+ int result;
+
+ a = 0;
+ b = 23.1;
+ c = 23.1;
+ 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");
+ return -1;
+ }
+
+ b = 12.4;
+ c = 7.8;
+ 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 -1;
+ }
+/* int a;
+ double b, c;
+ int result;
+
+ a = 0;
+ b = 124.3;
+ c = 124.3;
+ 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");
+ return -1;
+ }
+
+ b = 11.5;
+ c = 16.7;
+ 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 -1;
+ }*/
+
+ 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..bd6090d
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_rem.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+
+int main(void)
+{
+ float a, b, c;
+ float result;
+
+ b = 101.5;
+ c = 10;
+ result = 1.5;
+/* __asm
+ ("lf.rem.d %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.rem.d error\n");
+ return -1;
+ }*/
+
+ __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 -1;
+ }
+
+ 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..5ee9b03
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_sub.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+
+int main(void)
+{
+ float a, b, c;
+ float result;
+
+ b = 10.5;
+ c = 1.5;
+ result = 9.0;
+ __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 -1;
+ }
+
+/* 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");
+ return -1;
+ }*/
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_logic.c b/tests/tcg/openrisc/test_logic.c
new file mode 100644
index 0000000..46d173f
--- /dev/null
+++ b/tests/tcg/openrisc/test_logic.c
@@ -0,0 +1,105 @@
+#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");
+ return -1;
+ }
+
+ b = 0x9743;
+ result = 0x25d0c;
+ __asm
+ ("l.slli %0, %1, 0x2\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("slli error\n");
+ return -1;
+ }
+
+ 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");
+ return -1;
+ }
+
+ 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");
+ return -1;
+ }
+
+ b = 0x80000001;
+ result = 0x18000000;
+ __asm
+ ("l.rori %0, %1, 0x4\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("rori error\n");
+ return -1;
+ }
+
+ 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");
+ return -1;
+ }
+
+ b = 0x80000001;
+ result = 0xf0000000;
+ __asm
+ ("l.srai %0, %1, 0x3\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("srai error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_lx.c b/tests/tcg/openrisc/test_lx.c
new file mode 100644
index 0000000..792e3d5
--- /dev/null
+++ b/tests/tcg/openrisc/test_lx.c
@@ -0,0 +1,84 @@
+#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);
+ return -1;
+ }
+
+ result = 0x23;
+ __asm
+ ("l.lbs %0, 0x4 + %1\n\t"
+ : "=r"(a)
+ : "m"(*p)
+ );
+ if (a != result) {
+ printf("lbs error\n");
+ return -1;
+ }
+
+ 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);
+ return -1;
+ }
+
+ result = 0x1111;
+ __asm
+ ("l.lhz %0, 0x20 + %1\n\t"
+ : "=r"(a)
+ : "m"(*p)
+ );
+ if (a != result) {
+ printf("lhz error\n");
+ return -1;
+ }
+
+ 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);
+ return -1;
+ }
+
+ result = 0x1111233;
+ __asm
+ ("l.lwz %0, 0x123 + %1\n\t"
+ : "=r"(a)
+ : "m"(*p)
+ );
+ if (a != result) {
+ printf("lwz error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_movhi.c b/tests/tcg/openrisc/test_movhi.c
new file mode 100644
index 0000000..737f75b
--- /dev/null
+++ b/tests/tcg/openrisc/test_movhi.c
@@ -0,0 +1,31 @@
+#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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_mul.c b/tests/tcg/openrisc/test_mul.c
new file mode 100644
index 0000000..fdcb86d
--- /dev/null
+++ b/tests/tcg/openrisc/test_mul.c
@@ -0,0 +1,48 @@
+#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");
+ return -1;
+ }
+
+ 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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_muli.c b/tests/tcg/openrisc/test_muli.c
new file mode 100644
index 0000000..f1042e9
--- /dev/null
+++ b/tests/tcg/openrisc/test_muli.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x4;
+ c = 0x1;
+ result = 0x4;
+ __asm
+ ("l.muli %0, %1, 0x1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("muli error\n");
+ return -1;
+ }
+
+ b = 0x1;
+ c = 0x0;
+ result = 0x0;
+ __asm
+ ("l.muli %0, %1, 0x0\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("muli error\n");
+ return -1;
+ }
+
+ b = 0x1;
+ c = 0xff;
+ result = 0xff;
+ __asm
+ ("l.muli %0, %1, 0xff\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("muli error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_mulu.c b/tests/tcg/openrisc/test_mulu.c
new file mode 100644
index 0000000..2d1e97d
--- /dev/null
+++ b/tests/tcg/openrisc/test_mulu.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x4;
+ c = 0x1;
+ result = 0x4;
+ __asm
+ ("l.mulu %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("mulu error\n");
+ return -1;
+ }
+
+ b = 0x1;
+ c = 0x0;
+ result = 0x0;
+ __asm
+ ("l.mulu %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("mulu error\n");
+ return -1;
+ }
+
+ b = 0x1;
+ c = 0xff;
+ result = 0xff;
+ __asm
+ ("l.mulu %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("mulu error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfeq.c b/tests/tcg/openrisc/test_sfeq.c
new file mode 100644
index 0000000..bd7f875
--- /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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfeqi.c b/tests/tcg/openrisc/test_sfeqi.c
new file mode 100644
index 0000000..5742613
--- /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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfges.c b/tests/tcg/openrisc/test_sfges.c
new file mode 100644
index 0000000..23761d7
--- /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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgesi.c b/tests/tcg/openrisc/test_sfgesi.c
new file mode 100644
index 0000000..54a2d51
--- /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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgeu.c b/tests/tcg/openrisc/test_sfgeu.c
new file mode 100644
index 0000000..2a491d9
--- /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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgeui.c b/tests/tcg/openrisc/test_sfgeui.c
new file mode 100644
index 0000000..40af35c
--- /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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgts.c b/tests/tcg/openrisc/test_sfgts.c
new file mode 100644
index 0000000..4481a9c
--- /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");
+ return -1;
+ }
+
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgtsi.c b/tests/tcg/openrisc/test_sfgtsi.c
new file mode 100644
index 0000000..7366e12
--- /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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgtu.c b/tests/tcg/openrisc/test_sfgtu.c
new file mode 100644
index 0000000..da28689
--- /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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgtui.c b/tests/tcg/openrisc/test_sfgtui.c
new file mode 100644
index 0000000..565d44f
--- /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");
+ return -1;
+ }
+
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfles.c b/tests/tcg/openrisc/test_sfles.c
new file mode 100644
index 0000000..f573522
--- /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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sflesi.c b/tests/tcg/openrisc/test_sflesi.c
new file mode 100644
index 0000000..16fe605
--- /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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfleu.c b/tests/tcg/openrisc/test_sfleu.c
new file mode 100644
index 0000000..be0a3c3
--- /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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfleui.c b/tests/tcg/openrisc/test_sfleui.c
new file mode 100644
index 0000000..38d3c89
--- /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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sflts.c b/tests/tcg/openrisc/test_sflts.c
new file mode 100644
index 0000000..7deeb48
--- /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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfltsi.c b/tests/tcg/openrisc/test_sfltsi.c
new file mode 100644
index 0000000..3cb1f02
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfltsi.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("sfltsi error\n");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfltu.c b/tests/tcg/openrisc/test_sfltu.c
new file mode 100644
index 0000000..7ed3b26
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfltu.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.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 -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfltui.c b/tests/tcg/openrisc/test_sfltui.c
new file mode 100644
index 0000000..a5cb9f6
--- /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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfne.c b/tests/tcg/openrisc/test_sfne.c
new file mode 100644
index 0000000..b33a35c
--- /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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfnei.c b/tests/tcg/openrisc/test_sfnei.c
new file mode 100644
index 0000000..d311c9e
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfnei.c
@@ -0,0 +1,39 @@
+#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");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/openrisc/test_sub.c b/tests/tcg/openrisc/test_sub.c
new file mode 100644
index 0000000..474ec60
--- /dev/null
+++ b/tests/tcg/openrisc/test_sub.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0x100;
+ b = 0x100;
+ result = 0x0;
+ __asm
+ ("l.sub %0, %0, %1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sub error\n");
+ return -1;
+ }
+
+ a = 0xffff;
+ b = 0x1;
+ result = 0xfffe;
+ __asm
+ ("l.sub %0, %0, %1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sub error\n");
+ return -1;
+ }
+
+ return 0;
+}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH v9 07/15] target-or32: Add instruction translation
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 07/15] target-or32: Add instruction translation Jia Liu
@ 2012-07-13 8:09 ` Peter Maydell
2012-07-13 8:26 ` Jia Liu
0 siblings, 1 reply; 30+ messages in thread
From: Peter Maydell @ 2012-07-13 8:09 UTC (permalink / raw)
To: Jia Liu; +Cc: qemu-devel, afaerber
On 13 July 2012 05:35, Jia Liu <proljc@gmail.com> wrote:
> +static inline uint32_t field(uint32_t val, int start, int length)
> +{
> + val >>= start;
> + val &= ~(~0 << length);
> + return val;
> +}
extract32() is in bitops.h now, so it would be better to
use that instead. Thanks for prodding us to actually write
this utility routine :-)
-- PMM
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH v9 07/15] target-or32: Add instruction translation
2012-07-13 8:09 ` Peter Maydell
@ 2012-07-13 8:26 ` Jia Liu
0 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-13 8:26 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-devel, afaerber
Hi Peter,
On Fri, Jul 13, 2012 at 4:09 PM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 13 July 2012 05:35, Jia Liu <proljc@gmail.com> wrote:
>> +static inline uint32_t field(uint32_t val, int start, int length)
>> +{
>> + val >>= start;
>> + val &= ~(~0 << length);
>> + return val;
>> +}
>
> extract32() is in bitops.h now, so it would be better to
> use that instead. Thanks for prodding us to actually write
> this utility routine :-)
I've replace field extract32 after I receive your mail in one minute :-)
Thank you for mind me.
>
> -- PMM
Regards,
Jia
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH v9 05/15] target-or32: Add int instruction helpers
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 05/15] target-or32: Add int instruction helpers Jia Liu
@ 2012-07-13 9:18 ` Max Filippov
2012-07-14 11:44 ` Jia Liu
0 siblings, 1 reply; 30+ messages in thread
From: Max Filippov @ 2012-07-13 9:18 UTC (permalink / raw)
To: Jia Liu; +Cc: qemu-devel, afaerber
Hi.
On Fri, Jul 13, 2012 at 8:34 AM, Jia Liu <proljc@gmail.com> wrote:
> Add OpenRISC int instruction helpers.
>
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
> target-openrisc/Makefile.objs | 2 +-
> target-openrisc/helper.h | 5 +++
> target-openrisc/int_helper.c | 87 +++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 93 insertions(+), 1 deletion(-)
> create mode 100644 target-openrisc/int_helper.c
>
> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
> index 52d0158..e2a3715 100644
> --- a/target-openrisc/Makefile.objs
> +++ b/target-openrisc/Makefile.objs
> @@ -1,3 +1,3 @@
> obj-$(CONFIG_SOFTMMU) += machine.o
> obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
> -obj-y += exception_helper.o interrupt_helper.o mmu_helper.o
> +obj-y += exception_helper.o int_helper.o interrupt_helper.o mmu_helper.o
> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
> index 4e2a49f..c772951 100644
> --- a/target-openrisc/helper.h
> +++ b/target-openrisc/helper.h
> @@ -22,6 +22,11 @@
> /* 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(mul32, 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..45a9bfd
> --- /dev/null
> +++ b/target-openrisc/int_helper.c
> @@ -0,0 +1,87 @@
> +/*
> + * OpenRISC int helper routines
> + *
> + * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
> + * Feng Gao <gf91597@gmail.com>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "cpu.h"
> +#include "helper.h"
> +#include "exception.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;
> +}
This may be implemented more efficiently with "return x ? ctz32(x) + 1 : 0;"...
> +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;
> +}
...and this with "return 32 - clz32(x);"
> +target_ulong HELPER(mul32)(CPUOpenRISCState *env,
> + target_ulong ra, target_ulong rb)
> +{
> + uint64_t result;
> + target_ulong high, cy;
> +
> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
> +
> + result = ra * rb;
I believe that this multiplication should have been written as
result = (uint64_t)ra * rb;
in order to get 64 x 64 => 64 instead of 32 x 32 => 32 => 64.
> + /* regisiers in or32 is 32bit, so 32 is NOT a magic number.
> + or64 is not handled in this function, and not implement yet,
> + TARGET_LONG_BITS for or64 is 64, it will break this function,
> + so, we didn't use TARGET_LONG_BITS here. */
> + high = result >> 32;
> + cy = result >> (32 - 1);
> +
> + if ((cy & 0x1) == 0x0) {
> + if (high == 0x0) {
> + return result;
> + }
> + }
> +
> + if ((cy & 0x1) == 0x1) {
> + if (high == 0xffffffff) {
> + return result;
> + }
> + }
> +
> + cpu->env.sr |= (SR_OV | SR_CY);
> + if (cpu->env.sr & SR_OVE) {
> + raise_exception(cpu, EXCP_RANGE);
> + }
> +
> + return result;
> +}
> --
> 1.7.9.5
--
Thanks.
-- Max
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions Jia Liu
@ 2012-07-13 9:27 ` Max Filippov
2012-07-14 11:12 ` Jia Liu
0 siblings, 1 reply; 30+ messages in thread
From: Max Filippov @ 2012-07-13 9:27 UTC (permalink / raw)
To: Jia Liu; +Cc: qemu-devel, afaerber
On Fri, Jul 13, 2012 at 8:35 AM, Jia Liu <proljc@gmail.com> wrote:
> Add OpenRISC system instructions.
>
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
> target-openrisc/Makefile.objs | 2 +-
> target-openrisc/cpu.h | 3 +
> target-openrisc/helper.h | 4 +
> target-openrisc/sys_helper.c | 287 +++++++++++++++++++++++++++++++++++++++++
> target-openrisc/translate.c | 10 ++
> 5 files changed, 305 insertions(+), 1 deletion(-)
> create mode 100644 target-openrisc/sys_helper.c
>
> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
> index 926fc2f..44dc539 100644
> --- a/target-openrisc/Makefile.objs
> +++ b/target-openrisc/Makefile.objs
> @@ -1,4 +1,4 @@
> obj-$(CONFIG_SOFTMMU) += machine.o
> obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
> obj-y += exception_helper.o fpu_helper.o int_helper.o \
> - interrupt_helper.o mmu_helper.o
> + interrupt_helper.o mmu_helper.o sys_helper.o
> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
> index df07eaf..6506665 100644
> --- a/target-openrisc/cpu.h
> +++ b/target-openrisc/cpu.h
> @@ -80,6 +80,9 @@ enum {
> (reg) |= ((v & 0x1f) << 2);\
> } while (0)
>
> +/* Version Register */
> +#define SPR_VR 0xFFFF003F
> +
> /* Internal flags, delay slot flag */
> #define D_FLAG 1
>
> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
> index 6eb259a..836a70b 100644
> --- a/target-openrisc/helper.h
> +++ b/target-openrisc/helper.h
> @@ -63,4 +63,8 @@ DEF_HELPER_FLAGS_3(mul32, 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, tl, 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..7ff8e15
> --- /dev/null
> +++ b/target-openrisc/sys_helper.c
> @@ -0,0 +1,287 @@
> +/*
> + * OpenRISC system instructions helper routines
> + *
> + * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
> + * Zhizhou Zhang <etouzh@gmail.com>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "cpu.h"
> +#include "helper.h"
> +
> +#define TO_SPR(group, number) (((group) << 11) + (number))
> +
> +void HELPER(mtspr)(CPUOpenRISCState *env,
> + target_ulong ra, target_ulong rb, target_ulong offset)
> +{
> +#ifndef CONFIG_USER_ONLY
> + int spr = (ra | offset);
> + int idx;
> +
> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
> +
> + switch (spr) {
> + case TO_SPR(0, 0): /* VR */
> + env->vr = rb;
> + break;
> +
> + case TO_SPR(0, 16): /* NPC */
> + env->npc = rb;
> + break;
> +
> + case TO_SPR(0, 17): /* SR */
> + if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
> + (rb & (SR_IME | SR_DME | SR_SM))) {
> + tlb_flush(env, 1);
> + }
> + env->sr = rb;
> + env->sr |= SR_FO; /* FO is const equal to 1 */
> + if (env->sr & SR_DME) {
> + env->tlb->cpu_openrisc_map_address_data =
> + &cpu_openrisc_get_phys_data;
> + } else {
> + env->tlb->cpu_openrisc_map_address_data =
> + &cpu_openrisc_get_phys_nommu;
> + }
> +
> + if (env->sr & SR_IME) {
> + env->tlb->cpu_openrisc_map_address_code =
> + &cpu_openrisc_get_phys_code;
> + } else {
> + env->tlb->cpu_openrisc_map_address_code =
> + &cpu_openrisc_get_phys_nommu;
> + }
> + break;
> +
> + case TO_SPR(0, 18): /* PPC */
> + env->ppc = rb;
> + break;
> +
> + case TO_SPR(0, 32): /* EPCR */
> + env->epcr = rb;
> + break;
> +
> + case TO_SPR(0, 48): /* EEAR */
> + env->eear = rb;
> + break;
> +
> + case TO_SPR(0, 64): /* ESR */
> + env->esr = rb;
> + break;
> + case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
> + idx = spr - TO_SPR(1, 512);
> + if (!(rb & 1)) {
> + tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
> + }
> + env->tlb->dtlb[0][idx].mr = rb;
> + break;
> +
> + case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
> + idx = spr - TO_SPR(1, 640);
> + env->tlb->dtlb[0][idx].tr = 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 (!(rb & 1)) {
> + tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
> + }
> + env->tlb->itlb[0][idx].mr = rb;
> + break;
> +
> + case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
> + idx = spr - TO_SPR(2, 640);
> + env->tlb->itlb[0][idx].tr = rb;
> + 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->picmr |= rb;
> + break;
> + case TO_SPR(9, 2): /* PICSR */
> + env->picsr &= ~rb;
> + break;
> + case TO_SPR(10, 0): /* TTMR */
> + {
> + int ip = env->ttmr & TTMR_IP;
> +
> + if (rb & TTMR_IP) { /* Keep IP bit. */
> + env->ttmr = (rb & ~TTMR_IP) + ip;
> + } else { /* Clear IP bit. */
> + env->ttmr = rb & ~TTMR_IP;
> + env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
> + }
> +
> + cpu_openrisc_count_update(cpu);
> +
> + switch (env->ttmr & TTMR_M) {
> + case TIMER_NONE:
> + cpu_openrisc_count_stop(cpu);
> + break;
> + case TIMER_INTR:
> + cpu_openrisc_count_start(cpu);
> + break;
> + case TIMER_SHOT:
> + cpu_openrisc_count_start(cpu);
> + break;
> + case TIMER_CONT:
> + cpu_openrisc_count_start(cpu);
> + break;
> + default:
> + break;
> + }
> + }
> + break;
> +
> + case TO_SPR(10, 1): /* TTCR */
> + env->ttcr = rb;
> + if (env->ttmr & TIMER_NONE) {
> + return;
> + }
> + cpu_openrisc_count_start(cpu);
> + break;
> + default:
> +
> + break;
> + }
> +#endif
> +}
> +
> +target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
> + target_ulong rd, target_ulong ra, uint32_t offset)
> +{
> +#ifndef CONFIG_USER_ONLY
> + int spr = (ra | offset);
> + int idx;
> +
> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
> +
> + switch (spr) {
> + case TO_SPR(0, 0): /* VR */
> + return env->vr & SPR_VR;
> +
> + case TO_SPR(0, 1): /* UPR */
> + return env->upr; /* TT, DM, IM, UP present */
> +
> + case TO_SPR(0, 2): /* CPUCFGR */
> + return env->cpucfgr;
> +
> + case TO_SPR(0, 3): /* DMMUCFGR */
> + return env->dmmucfgr; /* 1Way, 64 entries */
> +
> + case TO_SPR(0, 4): /* IMMUCFGR */
> + return env->immucfgr;
> +
> + case TO_SPR(0, 16): /* NPC */
> + return env->npc;
> +
> + case TO_SPR(0, 17): /* SR */
> + return env->sr;
> +
> + case TO_SPR(0, 18): /* PPC */
> + return env->ppc;
> +
> + case TO_SPR(0, 32): /* EPCR */
> + return env->epcr;
> +
> + case TO_SPR(0, 48): /* EEAR */
> + return env->eear;
> +
> + case TO_SPR(0, 64): /* ESR */
> + return env->esr;
> +
> + case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
> + idx = spr - TO_SPR(1, 512);
> + return env->tlb->dtlb[0][idx].mr;
> +
> + case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
> + idx = spr - TO_SPR(1, 640);
> + return env->tlb->dtlb[0][idx].tr;
> +
> + 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);
> + return env->tlb->itlb[0][idx].mr;
> +
> + case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
> + idx = spr - TO_SPR(2, 640);
> + return env->tlb->itlb[0][idx].tr;
> +
> + 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 */
> + return env->picmr;
> +
> + case TO_SPR(9, 2): /* PICSR */
> + return env->picsr;
> +
> + case TO_SPR(10, 0): /* TTMR */
> + return env->ttmr;
> +
> + case TO_SPR(10, 1): /* TTCR */
> + cpu_openrisc_count_update(cpu);
> + return env->ttcr;
> +
> + default:
> + break;
> + }
> +#endif
> +
> +/*If we later need to add tracepoints (or debug printfs) for the return
> +value, it may be useful to structure the code like this:
> +
> +target_ulong ret = 0;
> +
> +switch() {
> +case x:
> + ret = y;
> + break;
> +case z:
> + ret = 42;
> + break;
> +...
> +}
> +
> +later something like trace_spr_read(ret);
> +
> +return ret;*/
> +
> + /* for rd is passed in, if rd unchanged, just keep it back. */
> + return rd;
> +}
> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
> index ed25604..8069edb 100644
> --- a/target-openrisc/translate.c
> +++ b/target-openrisc/translate.c
> @@ -995,10 +995,20 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
>
> case 0x2d: /* l.mfspr */
> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
> + {
> + TCGv_i32 ti = tcg_const_i32(I16);
> + gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
> + tcg_temp_free_i32(ti);
> + }
> break;
>
> case 0x30: /* l.mtspr */
> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
> + {
> + TCGv_i32 im = tcg_const_i32(tmp);
> + gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
> + tcg_temp_free_i32(im);
> + }
> break;
openrisc ISA says that l.mtspr/l.mfspr are only accessible in supervisor mode,
but I don't see where it is enforced.
--
Thanks.
-- Max
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions
2012-07-13 9:27 ` Max Filippov
@ 2012-07-14 11:12 ` Jia Liu
2012-07-14 13:19 ` Blue Swirl
0 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-07-14 11:12 UTC (permalink / raw)
To: Max Filippov; +Cc: qemu-devel
Hi Max
On Fri, Jul 13, 2012 at 5:27 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> On Fri, Jul 13, 2012 at 8:35 AM, Jia Liu <proljc@gmail.com> wrote:
>> Add OpenRISC system instructions.
>>
>> Signed-off-by: Jia Liu <proljc@gmail.com>
>> ---
>> target-openrisc/Makefile.objs | 2 +-
>> target-openrisc/cpu.h | 3 +
>> target-openrisc/helper.h | 4 +
>> target-openrisc/sys_helper.c | 287 +++++++++++++++++++++++++++++++++++++++++
>> target-openrisc/translate.c | 10 ++
>> 5 files changed, 305 insertions(+), 1 deletion(-)
>> create mode 100644 target-openrisc/sys_helper.c
>>
>> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
>> index 926fc2f..44dc539 100644
>> --- a/target-openrisc/Makefile.objs
>> +++ b/target-openrisc/Makefile.objs
>> @@ -1,4 +1,4 @@
>> obj-$(CONFIG_SOFTMMU) += machine.o
>> obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
>> obj-y += exception_helper.o fpu_helper.o int_helper.o \
>> - interrupt_helper.o mmu_helper.o
>> + interrupt_helper.o mmu_helper.o sys_helper.o
>> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
>> index df07eaf..6506665 100644
>> --- a/target-openrisc/cpu.h
>> +++ b/target-openrisc/cpu.h
>> @@ -80,6 +80,9 @@ enum {
>> (reg) |= ((v & 0x1f) << 2);\
>> } while (0)
>>
>> +/* Version Register */
>> +#define SPR_VR 0xFFFF003F
>> +
>> /* Internal flags, delay slot flag */
>> #define D_FLAG 1
>>
>> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
>> index 6eb259a..836a70b 100644
>> --- a/target-openrisc/helper.h
>> +++ b/target-openrisc/helper.h
>> @@ -63,4 +63,8 @@ DEF_HELPER_FLAGS_3(mul32, 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, tl, 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..7ff8e15
>> --- /dev/null
>> +++ b/target-openrisc/sys_helper.c
>> @@ -0,0 +1,287 @@
>> +/*
>> + * OpenRISC system instructions helper routines
>> + *
>> + * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
>> + * Zhizhou Zhang <etouzh@gmail.com>
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2 of the License, or (at your option) any later version.
>> + *
>> + * This library is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "cpu.h"
>> +#include "helper.h"
>> +
>> +#define TO_SPR(group, number) (((group) << 11) + (number))
>> +
>> +void HELPER(mtspr)(CPUOpenRISCState *env,
>> + target_ulong ra, target_ulong rb, target_ulong offset)
>> +{
>> +#ifndef CONFIG_USER_ONLY
>> + int spr = (ra | offset);
>> + int idx;
>> +
>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
>> +
>> + switch (spr) {
>> + case TO_SPR(0, 0): /* VR */
>> + env->vr = rb;
>> + break;
>> +
>> + case TO_SPR(0, 16): /* NPC */
>> + env->npc = rb;
>> + break;
>> +
>> + case TO_SPR(0, 17): /* SR */
>> + if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
>> + (rb & (SR_IME | SR_DME | SR_SM))) {
>> + tlb_flush(env, 1);
>> + }
>> + env->sr = rb;
>> + env->sr |= SR_FO; /* FO is const equal to 1 */
>> + if (env->sr & SR_DME) {
>> + env->tlb->cpu_openrisc_map_address_data =
>> + &cpu_openrisc_get_phys_data;
>> + } else {
>> + env->tlb->cpu_openrisc_map_address_data =
>> + &cpu_openrisc_get_phys_nommu;
>> + }
>> +
>> + if (env->sr & SR_IME) {
>> + env->tlb->cpu_openrisc_map_address_code =
>> + &cpu_openrisc_get_phys_code;
>> + } else {
>> + env->tlb->cpu_openrisc_map_address_code =
>> + &cpu_openrisc_get_phys_nommu;
>> + }
>> + break;
>> +
>> + case TO_SPR(0, 18): /* PPC */
>> + env->ppc = rb;
>> + break;
>> +
>> + case TO_SPR(0, 32): /* EPCR */
>> + env->epcr = rb;
>> + break;
>> +
>> + case TO_SPR(0, 48): /* EEAR */
>> + env->eear = rb;
>> + break;
>> +
>> + case TO_SPR(0, 64): /* ESR */
>> + env->esr = rb;
>> + break;
>> + case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>> + idx = spr - TO_SPR(1, 512);
>> + if (!(rb & 1)) {
>> + tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
>> + }
>> + env->tlb->dtlb[0][idx].mr = rb;
>> + break;
>> +
>> + case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>> + idx = spr - TO_SPR(1, 640);
>> + env->tlb->dtlb[0][idx].tr = 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 (!(rb & 1)) {
>> + tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
>> + }
>> + env->tlb->itlb[0][idx].mr = rb;
>> + break;
>> +
>> + case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>> + idx = spr - TO_SPR(2, 640);
>> + env->tlb->itlb[0][idx].tr = rb;
>> + 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->picmr |= rb;
>> + break;
>> + case TO_SPR(9, 2): /* PICSR */
>> + env->picsr &= ~rb;
>> + break;
>> + case TO_SPR(10, 0): /* TTMR */
>> + {
>> + int ip = env->ttmr & TTMR_IP;
>> +
>> + if (rb & TTMR_IP) { /* Keep IP bit. */
>> + env->ttmr = (rb & ~TTMR_IP) + ip;
>> + } else { /* Clear IP bit. */
>> + env->ttmr = rb & ~TTMR_IP;
>> + env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
>> + }
>> +
>> + cpu_openrisc_count_update(cpu);
>> +
>> + switch (env->ttmr & TTMR_M) {
>> + case TIMER_NONE:
>> + cpu_openrisc_count_stop(cpu);
>> + break;
>> + case TIMER_INTR:
>> + cpu_openrisc_count_start(cpu);
>> + break;
>> + case TIMER_SHOT:
>> + cpu_openrisc_count_start(cpu);
>> + break;
>> + case TIMER_CONT:
>> + cpu_openrisc_count_start(cpu);
>> + break;
>> + default:
>> + break;
>> + }
>> + }
>> + break;
>> +
>> + case TO_SPR(10, 1): /* TTCR */
>> + env->ttcr = rb;
>> + if (env->ttmr & TIMER_NONE) {
>> + return;
>> + }
>> + cpu_openrisc_count_start(cpu);
>> + break;
>> + default:
>> +
>> + break;
>> + }
>> +#endif
>> +}
>> +
>> +target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
>> + target_ulong rd, target_ulong ra, uint32_t offset)
>> +{
>> +#ifndef CONFIG_USER_ONLY
>> + int spr = (ra | offset);
>> + int idx;
>> +
>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
>> +
>> + switch (spr) {
>> + case TO_SPR(0, 0): /* VR */
>> + return env->vr & SPR_VR;
>> +
>> + case TO_SPR(0, 1): /* UPR */
>> + return env->upr; /* TT, DM, IM, UP present */
>> +
>> + case TO_SPR(0, 2): /* CPUCFGR */
>> + return env->cpucfgr;
>> +
>> + case TO_SPR(0, 3): /* DMMUCFGR */
>> + return env->dmmucfgr; /* 1Way, 64 entries */
>> +
>> + case TO_SPR(0, 4): /* IMMUCFGR */
>> + return env->immucfgr;
>> +
>> + case TO_SPR(0, 16): /* NPC */
>> + return env->npc;
>> +
>> + case TO_SPR(0, 17): /* SR */
>> + return env->sr;
>> +
>> + case TO_SPR(0, 18): /* PPC */
>> + return env->ppc;
>> +
>> + case TO_SPR(0, 32): /* EPCR */
>> + return env->epcr;
>> +
>> + case TO_SPR(0, 48): /* EEAR */
>> + return env->eear;
>> +
>> + case TO_SPR(0, 64): /* ESR */
>> + return env->esr;
>> +
>> + case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>> + idx = spr - TO_SPR(1, 512);
>> + return env->tlb->dtlb[0][idx].mr;
>> +
>> + case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>> + idx = spr - TO_SPR(1, 640);
>> + return env->tlb->dtlb[0][idx].tr;
>> +
>> + 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);
>> + return env->tlb->itlb[0][idx].mr;
>> +
>> + case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>> + idx = spr - TO_SPR(2, 640);
>> + return env->tlb->itlb[0][idx].tr;
>> +
>> + 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 */
>> + return env->picmr;
>> +
>> + case TO_SPR(9, 2): /* PICSR */
>> + return env->picsr;
>> +
>> + case TO_SPR(10, 0): /* TTMR */
>> + return env->ttmr;
>> +
>> + case TO_SPR(10, 1): /* TTCR */
>> + cpu_openrisc_count_update(cpu);
>> + return env->ttcr;
>> +
>> + default:
>> + break;
>> + }
>> +#endif
>> +
>> +/*If we later need to add tracepoints (or debug printfs) for the return
>> +value, it may be useful to structure the code like this:
>> +
>> +target_ulong ret = 0;
>> +
>> +switch() {
>> +case x:
>> + ret = y;
>> + break;
>> +case z:
>> + ret = 42;
>> + break;
>> +...
>> +}
>> +
>> +later something like trace_spr_read(ret);
>> +
>> +return ret;*/
>> +
>> + /* for rd is passed in, if rd unchanged, just keep it back. */
>> + return rd;
>> +}
>> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
>> index ed25604..8069edb 100644
>> --- a/target-openrisc/translate.c
>> +++ b/target-openrisc/translate.c
>> @@ -995,10 +995,20 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
>>
>> case 0x2d: /* l.mfspr */
>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>> + {
>> + TCGv_i32 ti = tcg_const_i32(I16);
>> + gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
>> + tcg_temp_free_i32(ti);
>> + }
>> break;
>>
>> case 0x30: /* l.mtspr */
>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>> + {
>> + TCGv_i32 im = tcg_const_i32(tmp);
>> + gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>> + tcg_temp_free_i32(im);
>> + }
>> break;
>
> openrisc ISA says that l.mtspr/l.mfspr are only accessible in supervisor mode,
> but I don't see where it is enforced.
>
Thank you for mind me, it is the new code. Is it OK?
#ifndef CONFIG_USER_ONLY
case 0x2d: /* l.mfspr */
LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
{
TCGv_i32 ti = tcg_const_i32(I16);
gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
tcg_temp_free_i32(ti);
}
break;
case 0x30: /* l.mtspr */
LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
{
TCGv_i32 im = tcg_const_i32(tmp);
gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
tcg_temp_free_i32(im);
}
break;
#endif
> --
> Thanks.
> -- Max
Regards,
Jia
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH v9 05/15] target-or32: Add int instruction helpers
2012-07-13 9:18 ` Max Filippov
@ 2012-07-14 11:44 ` Jia Liu
0 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-14 11:44 UTC (permalink / raw)
To: Max Filippov; +Cc: qemu-devel
Hi Max
On Fri, Jul 13, 2012 at 5:18 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> Hi.
>
> On Fri, Jul 13, 2012 at 8:34 AM, Jia Liu <proljc@gmail.com> wrote:
>> Add OpenRISC int instruction helpers.
>>
>> Signed-off-by: Jia Liu <proljc@gmail.com>
>> ---
>> target-openrisc/Makefile.objs | 2 +-
>> target-openrisc/helper.h | 5 +++
>> target-openrisc/int_helper.c | 87 +++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 93 insertions(+), 1 deletion(-)
>> create mode 100644 target-openrisc/int_helper.c
>>
>> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
>> index 52d0158..e2a3715 100644
>> --- a/target-openrisc/Makefile.objs
>> +++ b/target-openrisc/Makefile.objs
>> @@ -1,3 +1,3 @@
>> obj-$(CONFIG_SOFTMMU) += machine.o
>> obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
>> -obj-y += exception_helper.o interrupt_helper.o mmu_helper.o
>> +obj-y += exception_helper.o int_helper.o interrupt_helper.o mmu_helper.o
>> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
>> index 4e2a49f..c772951 100644
>> --- a/target-openrisc/helper.h
>> +++ b/target-openrisc/helper.h
>> @@ -22,6 +22,11 @@
>> /* 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(mul32, 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..45a9bfd
>> --- /dev/null
>> +++ b/target-openrisc/int_helper.c
>> @@ -0,0 +1,87 @@
>> +/*
>> + * OpenRISC int helper routines
>> + *
>> + * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
>> + * Feng Gao <gf91597@gmail.com>
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2 of the License, or (at your option) any later version.
>> + *
>> + * This library is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "cpu.h"
>> +#include "helper.h"
>> +#include "exception.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;
>> +}
>
> This may be implemented more efficiently with "return x ? ctz32(x) + 1 : 0;"...
>
>> +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;
>> +}
>
> ...and this with "return 32 - clz32(x);"
>
Thank you very much! And I made them like this:
target_ulong HELPER(ff1)(target_ulong x)
{
/*#ifdef TARGET_OPENRISC64
return x ? ctz64(x) + 1 : 0;
#else*/
return x ? ctz32(x) + 1 : 0;
/*#endif*/
}
target_ulong HELPER(fl1)(target_ulong x)
{
/* not used yet, open it when we need or64. */
/*#ifdef TARGET_OPENRISC64
return 64 - clz64(x);
#else*/
return 32 - clz32(x);
/*#endif*/
}
I have to comment out all of the or64 code,for now.
Is it OK?
>> +target_ulong HELPER(mul32)(CPUOpenRISCState *env,
>> + target_ulong ra, target_ulong rb)
>> +{
>> + uint64_t result;
>> + target_ulong high, cy;
>> +
>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
>> +
>> + result = ra * rb;
>
> I believe that this multiplication should have been written as
>
> result = (uint64_t)ra * rb;
>
> in order to get 64 x 64 => 64 instead of 32 x 32 => 32 => 64.
>
Thank you!
Is this better?
uint32_t HELPER(mul32)(CPUOpenRISCState *env,
uint32_t ra, uint32_t rb)
{
uint64_t result;
uint32_t high, cy;
OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
result = (uint64_t)ra * rb;
I made it a pure 32bit mul.
>> + /* regisiers in or32 is 32bit, so 32 is NOT a magic number.
>> + or64 is not handled in this function, and not implement yet,
>> + TARGET_LONG_BITS for or64 is 64, it will break this function,
>> + so, we didn't use TARGET_LONG_BITS here. */
>> + high = result >> 32;
>> + cy = result >> (32 - 1);
>> +
>> + if ((cy & 0x1) == 0x0) {
>> + if (high == 0x0) {
>> + return result;
>> + }
>> + }
>> +
>> + if ((cy & 0x1) == 0x1) {
>> + if (high == 0xffffffff) {
>> + return result;
>> + }
>> + }
>> +
>> + cpu->env.sr |= (SR_OV | SR_CY);
>> + if (cpu->env.sr & SR_OVE) {
>> + raise_exception(cpu, EXCP_RANGE);
>> + }
>> +
>> + return result;
>> +}
>> --
>> 1.7.9.5
>
> --
> Thanks.
> -- Max
Regards,
Jia
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions
2012-07-14 11:12 ` Jia Liu
@ 2012-07-14 13:19 ` Blue Swirl
2012-07-14 13:39 ` Jia Liu
0 siblings, 1 reply; 30+ messages in thread
From: Blue Swirl @ 2012-07-14 13:19 UTC (permalink / raw)
To: Jia Liu; +Cc: Max Filippov, qemu-devel
On Sat, Jul 14, 2012 at 11:12 AM, Jia Liu <proljc@gmail.com> wrote:
> Hi Max
>
> On Fri, Jul 13, 2012 at 5:27 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
>> On Fri, Jul 13, 2012 at 8:35 AM, Jia Liu <proljc@gmail.com> wrote:
>>> Add OpenRISC system instructions.
>>>
>>> Signed-off-by: Jia Liu <proljc@gmail.com>
>>> ---
>>> target-openrisc/Makefile.objs | 2 +-
>>> target-openrisc/cpu.h | 3 +
>>> target-openrisc/helper.h | 4 +
>>> target-openrisc/sys_helper.c | 287 +++++++++++++++++++++++++++++++++++++++++
>>> target-openrisc/translate.c | 10 ++
>>> 5 files changed, 305 insertions(+), 1 deletion(-)
>>> create mode 100644 target-openrisc/sys_helper.c
>>>
>>> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
>>> index 926fc2f..44dc539 100644
>>> --- a/target-openrisc/Makefile.objs
>>> +++ b/target-openrisc/Makefile.objs
>>> @@ -1,4 +1,4 @@
>>> obj-$(CONFIG_SOFTMMU) += machine.o
>>> obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
>>> obj-y += exception_helper.o fpu_helper.o int_helper.o \
>>> - interrupt_helper.o mmu_helper.o
>>> + interrupt_helper.o mmu_helper.o sys_helper.o
>>> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
>>> index df07eaf..6506665 100644
>>> --- a/target-openrisc/cpu.h
>>> +++ b/target-openrisc/cpu.h
>>> @@ -80,6 +80,9 @@ enum {
>>> (reg) |= ((v & 0x1f) << 2);\
>>> } while (0)
>>>
>>> +/* Version Register */
>>> +#define SPR_VR 0xFFFF003F
>>> +
>>> /* Internal flags, delay slot flag */
>>> #define D_FLAG 1
>>>
>>> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
>>> index 6eb259a..836a70b 100644
>>> --- a/target-openrisc/helper.h
>>> +++ b/target-openrisc/helper.h
>>> @@ -63,4 +63,8 @@ DEF_HELPER_FLAGS_3(mul32, 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, tl, 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..7ff8e15
>>> --- /dev/null
>>> +++ b/target-openrisc/sys_helper.c
>>> @@ -0,0 +1,287 @@
>>> +/*
>>> + * OpenRISC system instructions helper routines
>>> + *
>>> + * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
>>> + * Zhizhou Zhang <etouzh@gmail.com>
>>> + *
>>> + * This library is free software; you can redistribute it and/or
>>> + * modify it under the terms of the GNU Lesser General Public
>>> + * License as published by the Free Software Foundation; either
>>> + * version 2 of the License, or (at your option) any later version.
>>> + *
>>> + * This library is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>>> + * Lesser General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU Lesser General Public
>>> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include "cpu.h"
>>> +#include "helper.h"
>>> +
>>> +#define TO_SPR(group, number) (((group) << 11) + (number))
>>> +
>>> +void HELPER(mtspr)(CPUOpenRISCState *env,
>>> + target_ulong ra, target_ulong rb, target_ulong offset)
>>> +{
>>> +#ifndef CONFIG_USER_ONLY
>>> + int spr = (ra | offset);
>>> + int idx;
>>> +
>>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
>>> +
>>> + switch (spr) {
>>> + case TO_SPR(0, 0): /* VR */
>>> + env->vr = rb;
>>> + break;
>>> +
>>> + case TO_SPR(0, 16): /* NPC */
>>> + env->npc = rb;
>>> + break;
>>> +
>>> + case TO_SPR(0, 17): /* SR */
>>> + if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
>>> + (rb & (SR_IME | SR_DME | SR_SM))) {
>>> + tlb_flush(env, 1);
>>> + }
>>> + env->sr = rb;
>>> + env->sr |= SR_FO; /* FO is const equal to 1 */
>>> + if (env->sr & SR_DME) {
>>> + env->tlb->cpu_openrisc_map_address_data =
>>> + &cpu_openrisc_get_phys_data;
>>> + } else {
>>> + env->tlb->cpu_openrisc_map_address_data =
>>> + &cpu_openrisc_get_phys_nommu;
>>> + }
>>> +
>>> + if (env->sr & SR_IME) {
>>> + env->tlb->cpu_openrisc_map_address_code =
>>> + &cpu_openrisc_get_phys_code;
>>> + } else {
>>> + env->tlb->cpu_openrisc_map_address_code =
>>> + &cpu_openrisc_get_phys_nommu;
>>> + }
>>> + break;
>>> +
>>> + case TO_SPR(0, 18): /* PPC */
>>> + env->ppc = rb;
>>> + break;
>>> +
>>> + case TO_SPR(0, 32): /* EPCR */
>>> + env->epcr = rb;
>>> + break;
>>> +
>>> + case TO_SPR(0, 48): /* EEAR */
>>> + env->eear = rb;
>>> + break;
>>> +
>>> + case TO_SPR(0, 64): /* ESR */
>>> + env->esr = rb;
>>> + break;
>>> + case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>>> + idx = spr - TO_SPR(1, 512);
>>> + if (!(rb & 1)) {
>>> + tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
>>> + }
>>> + env->tlb->dtlb[0][idx].mr = rb;
>>> + break;
>>> +
>>> + case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>>> + idx = spr - TO_SPR(1, 640);
>>> + env->tlb->dtlb[0][idx].tr = 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 (!(rb & 1)) {
>>> + tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
>>> + }
>>> + env->tlb->itlb[0][idx].mr = rb;
>>> + break;
>>> +
>>> + case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>>> + idx = spr - TO_SPR(2, 640);
>>> + env->tlb->itlb[0][idx].tr = rb;
>>> + 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->picmr |= rb;
>>> + break;
>>> + case TO_SPR(9, 2): /* PICSR */
>>> + env->picsr &= ~rb;
>>> + break;
>>> + case TO_SPR(10, 0): /* TTMR */
>>> + {
>>> + int ip = env->ttmr & TTMR_IP;
>>> +
>>> + if (rb & TTMR_IP) { /* Keep IP bit. */
>>> + env->ttmr = (rb & ~TTMR_IP) + ip;
>>> + } else { /* Clear IP bit. */
>>> + env->ttmr = rb & ~TTMR_IP;
>>> + env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
>>> + }
>>> +
>>> + cpu_openrisc_count_update(cpu);
>>> +
>>> + switch (env->ttmr & TTMR_M) {
>>> + case TIMER_NONE:
>>> + cpu_openrisc_count_stop(cpu);
>>> + break;
>>> + case TIMER_INTR:
>>> + cpu_openrisc_count_start(cpu);
>>> + break;
>>> + case TIMER_SHOT:
>>> + cpu_openrisc_count_start(cpu);
>>> + break;
>>> + case TIMER_CONT:
>>> + cpu_openrisc_count_start(cpu);
>>> + break;
>>> + default:
>>> + break;
>>> + }
>>> + }
>>> + break;
>>> +
>>> + case TO_SPR(10, 1): /* TTCR */
>>> + env->ttcr = rb;
>>> + if (env->ttmr & TIMER_NONE) {
>>> + return;
>>> + }
>>> + cpu_openrisc_count_start(cpu);
>>> + break;
>>> + default:
>>> +
>>> + break;
>>> + }
>>> +#endif
>>> +}
>>> +
>>> +target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
>>> + target_ulong rd, target_ulong ra, uint32_t offset)
>>> +{
>>> +#ifndef CONFIG_USER_ONLY
>>> + int spr = (ra | offset);
>>> + int idx;
>>> +
>>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
>>> +
>>> + switch (spr) {
>>> + case TO_SPR(0, 0): /* VR */
>>> + return env->vr & SPR_VR;
>>> +
>>> + case TO_SPR(0, 1): /* UPR */
>>> + return env->upr; /* TT, DM, IM, UP present */
>>> +
>>> + case TO_SPR(0, 2): /* CPUCFGR */
>>> + return env->cpucfgr;
>>> +
>>> + case TO_SPR(0, 3): /* DMMUCFGR */
>>> + return env->dmmucfgr; /* 1Way, 64 entries */
>>> +
>>> + case TO_SPR(0, 4): /* IMMUCFGR */
>>> + return env->immucfgr;
>>> +
>>> + case TO_SPR(0, 16): /* NPC */
>>> + return env->npc;
>>> +
>>> + case TO_SPR(0, 17): /* SR */
>>> + return env->sr;
>>> +
>>> + case TO_SPR(0, 18): /* PPC */
>>> + return env->ppc;
>>> +
>>> + case TO_SPR(0, 32): /* EPCR */
>>> + return env->epcr;
>>> +
>>> + case TO_SPR(0, 48): /* EEAR */
>>> + return env->eear;
>>> +
>>> + case TO_SPR(0, 64): /* ESR */
>>> + return env->esr;
>>> +
>>> + case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>>> + idx = spr - TO_SPR(1, 512);
>>> + return env->tlb->dtlb[0][idx].mr;
>>> +
>>> + case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>>> + idx = spr - TO_SPR(1, 640);
>>> + return env->tlb->dtlb[0][idx].tr;
>>> +
>>> + 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);
>>> + return env->tlb->itlb[0][idx].mr;
>>> +
>>> + case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>>> + idx = spr - TO_SPR(2, 640);
>>> + return env->tlb->itlb[0][idx].tr;
>>> +
>>> + 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 */
>>> + return env->picmr;
>>> +
>>> + case TO_SPR(9, 2): /* PICSR */
>>> + return env->picsr;
>>> +
>>> + case TO_SPR(10, 0): /* TTMR */
>>> + return env->ttmr;
>>> +
>>> + case TO_SPR(10, 1): /* TTCR */
>>> + cpu_openrisc_count_update(cpu);
>>> + return env->ttcr;
>>> +
>>> + default:
>>> + break;
>>> + }
>>> +#endif
>>> +
>>> +/*If we later need to add tracepoints (or debug printfs) for the return
>>> +value, it may be useful to structure the code like this:
>>> +
>>> +target_ulong ret = 0;
>>> +
>>> +switch() {
>>> +case x:
>>> + ret = y;
>>> + break;
>>> +case z:
>>> + ret = 42;
>>> + break;
>>> +...
>>> +}
>>> +
>>> +later something like trace_spr_read(ret);
>>> +
>>> +return ret;*/
>>> +
>>> + /* for rd is passed in, if rd unchanged, just keep it back. */
>>> + return rd;
>>> +}
>>> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
>>> index ed25604..8069edb 100644
>>> --- a/target-openrisc/translate.c
>>> +++ b/target-openrisc/translate.c
>>> @@ -995,10 +995,20 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
>>>
>>> case 0x2d: /* l.mfspr */
>>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>>> + {
>>> + TCGv_i32 ti = tcg_const_i32(I16);
>>> + gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
>>> + tcg_temp_free_i32(ti);
>>> + }
>>> break;
>>>
>>> case 0x30: /* l.mtspr */
>>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>>> + {
>>> + TCGv_i32 im = tcg_const_i32(tmp);
>>> + gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>>> + tcg_temp_free_i32(im);
>>> + }
>>> break;
>>
>> openrisc ISA says that l.mtspr/l.mfspr are only accessible in supervisor mode,
>> but I don't see where it is enforced.
>>
>
> Thank you for mind me, it is the new code. Is it OK?
I don't think so, please check for example target-ppc/translate.c:4192
on how supervisor only mfsr is handled there.
>
> #ifndef CONFIG_USER_ONLY
> case 0x2d: /* l.mfspr */
> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
> {
> TCGv_i32 ti = tcg_const_i32(I16);
> gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
> tcg_temp_free_i32(ti);
> }
> break;
>
> case 0x30: /* l.mtspr */
> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
> {
> TCGv_i32 im = tcg_const_i32(tmp);
> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
> tcg_temp_free_i32(im);
> }
> break;
> #endif
>
>
>> --
>> Thanks.
>> -- Max
>
> Regards,
> Jia
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions
2012-07-14 13:19 ` Blue Swirl
@ 2012-07-14 13:39 ` Jia Liu
2012-07-14 13:49 ` Max Filippov
0 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-07-14 13:39 UTC (permalink / raw)
To: Blue Swirl; +Cc: Max Filippov, qemu-devel
Hi Blue,
On Sat, Jul 14, 2012 at 9:19 PM, Blue Swirl <blauwirbel@gmail.com> wrote:
> On Sat, Jul 14, 2012 at 11:12 AM, Jia Liu <proljc@gmail.com> wrote:
>> Hi Max
>>
>> On Fri, Jul 13, 2012 at 5:27 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
>>> On Fri, Jul 13, 2012 at 8:35 AM, Jia Liu <proljc@gmail.com> wrote:
>>>> Add OpenRISC system instructions.
>>>>
>>>> Signed-off-by: Jia Liu <proljc@gmail.com>
>>>> ---
>>>> target-openrisc/Makefile.objs | 2 +-
>>>> target-openrisc/cpu.h | 3 +
>>>> target-openrisc/helper.h | 4 +
>>>> target-openrisc/sys_helper.c | 287 +++++++++++++++++++++++++++++++++++++++++
>>>> target-openrisc/translate.c | 10 ++
>>>> 5 files changed, 305 insertions(+), 1 deletion(-)
>>>> create mode 100644 target-openrisc/sys_helper.c
>>>>
>>>> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
>>>> index 926fc2f..44dc539 100644
>>>> --- a/target-openrisc/Makefile.objs
>>>> +++ b/target-openrisc/Makefile.objs
>>>> @@ -1,4 +1,4 @@
>>>> obj-$(CONFIG_SOFTMMU) += machine.o
>>>> obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
>>>> obj-y += exception_helper.o fpu_helper.o int_helper.o \
>>>> - interrupt_helper.o mmu_helper.o
>>>> + interrupt_helper.o mmu_helper.o sys_helper.o
>>>> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
>>>> index df07eaf..6506665 100644
>>>> --- a/target-openrisc/cpu.h
>>>> +++ b/target-openrisc/cpu.h
>>>> @@ -80,6 +80,9 @@ enum {
>>>> (reg) |= ((v & 0x1f) << 2);\
>>>> } while (0)
>>>>
>>>> +/* Version Register */
>>>> +#define SPR_VR 0xFFFF003F
>>>> +
>>>> /* Internal flags, delay slot flag */
>>>> #define D_FLAG 1
>>>>
>>>> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
>>>> index 6eb259a..836a70b 100644
>>>> --- a/target-openrisc/helper.h
>>>> +++ b/target-openrisc/helper.h
>>>> @@ -63,4 +63,8 @@ DEF_HELPER_FLAGS_3(mul32, 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, tl, 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..7ff8e15
>>>> --- /dev/null
>>>> +++ b/target-openrisc/sys_helper.c
>>>> @@ -0,0 +1,287 @@
>>>> +/*
>>>> + * OpenRISC system instructions helper routines
>>>> + *
>>>> + * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
>>>> + * Zhizhou Zhang <etouzh@gmail.com>
>>>> + *
>>>> + * This library is free software; you can redistribute it and/or
>>>> + * modify it under the terms of the GNU Lesser General Public
>>>> + * License as published by the Free Software Foundation; either
>>>> + * version 2 of the License, or (at your option) any later version.
>>>> + *
>>>> + * This library is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>>>> + * Lesser General Public License for more details.
>>>> + *
>>>> + * You should have received a copy of the GNU Lesser General Public
>>>> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
>>>> + */
>>>> +
>>>> +#include "cpu.h"
>>>> +#include "helper.h"
>>>> +
>>>> +#define TO_SPR(group, number) (((group) << 11) + (number))
>>>> +
>>>> +void HELPER(mtspr)(CPUOpenRISCState *env,
>>>> + target_ulong ra, target_ulong rb, target_ulong offset)
>>>> +{
>>>> +#ifndef CONFIG_USER_ONLY
>>>> + int spr = (ra | offset);
>>>> + int idx;
>>>> +
>>>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
>>>> +
>>>> + switch (spr) {
>>>> + case TO_SPR(0, 0): /* VR */
>>>> + env->vr = rb;
>>>> + break;
>>>> +
>>>> + case TO_SPR(0, 16): /* NPC */
>>>> + env->npc = rb;
>>>> + break;
>>>> +
>>>> + case TO_SPR(0, 17): /* SR */
>>>> + if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
>>>> + (rb & (SR_IME | SR_DME | SR_SM))) {
>>>> + tlb_flush(env, 1);
>>>> + }
>>>> + env->sr = rb;
>>>> + env->sr |= SR_FO; /* FO is const equal to 1 */
>>>> + if (env->sr & SR_DME) {
>>>> + env->tlb->cpu_openrisc_map_address_data =
>>>> + &cpu_openrisc_get_phys_data;
>>>> + } else {
>>>> + env->tlb->cpu_openrisc_map_address_data =
>>>> + &cpu_openrisc_get_phys_nommu;
>>>> + }
>>>> +
>>>> + if (env->sr & SR_IME) {
>>>> + env->tlb->cpu_openrisc_map_address_code =
>>>> + &cpu_openrisc_get_phys_code;
>>>> + } else {
>>>> + env->tlb->cpu_openrisc_map_address_code =
>>>> + &cpu_openrisc_get_phys_nommu;
>>>> + }
>>>> + break;
>>>> +
>>>> + case TO_SPR(0, 18): /* PPC */
>>>> + env->ppc = rb;
>>>> + break;
>>>> +
>>>> + case TO_SPR(0, 32): /* EPCR */
>>>> + env->epcr = rb;
>>>> + break;
>>>> +
>>>> + case TO_SPR(0, 48): /* EEAR */
>>>> + env->eear = rb;
>>>> + break;
>>>> +
>>>> + case TO_SPR(0, 64): /* ESR */
>>>> + env->esr = rb;
>>>> + break;
>>>> + case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>>>> + idx = spr - TO_SPR(1, 512);
>>>> + if (!(rb & 1)) {
>>>> + tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
>>>> + }
>>>> + env->tlb->dtlb[0][idx].mr = rb;
>>>> + break;
>>>> +
>>>> + case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>>>> + idx = spr - TO_SPR(1, 640);
>>>> + env->tlb->dtlb[0][idx].tr = 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 (!(rb & 1)) {
>>>> + tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
>>>> + }
>>>> + env->tlb->itlb[0][idx].mr = rb;
>>>> + break;
>>>> +
>>>> + case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>>>> + idx = spr - TO_SPR(2, 640);
>>>> + env->tlb->itlb[0][idx].tr = rb;
>>>> + 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->picmr |= rb;
>>>> + break;
>>>> + case TO_SPR(9, 2): /* PICSR */
>>>> + env->picsr &= ~rb;
>>>> + break;
>>>> + case TO_SPR(10, 0): /* TTMR */
>>>> + {
>>>> + int ip = env->ttmr & TTMR_IP;
>>>> +
>>>> + if (rb & TTMR_IP) { /* Keep IP bit. */
>>>> + env->ttmr = (rb & ~TTMR_IP) + ip;
>>>> + } else { /* Clear IP bit. */
>>>> + env->ttmr = rb & ~TTMR_IP;
>>>> + env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
>>>> + }
>>>> +
>>>> + cpu_openrisc_count_update(cpu);
>>>> +
>>>> + switch (env->ttmr & TTMR_M) {
>>>> + case TIMER_NONE:
>>>> + cpu_openrisc_count_stop(cpu);
>>>> + break;
>>>> + case TIMER_INTR:
>>>> + cpu_openrisc_count_start(cpu);
>>>> + break;
>>>> + case TIMER_SHOT:
>>>> + cpu_openrisc_count_start(cpu);
>>>> + break;
>>>> + case TIMER_CONT:
>>>> + cpu_openrisc_count_start(cpu);
>>>> + break;
>>>> + default:
>>>> + break;
>>>> + }
>>>> + }
>>>> + break;
>>>> +
>>>> + case TO_SPR(10, 1): /* TTCR */
>>>> + env->ttcr = rb;
>>>> + if (env->ttmr & TIMER_NONE) {
>>>> + return;
>>>> + }
>>>> + cpu_openrisc_count_start(cpu);
>>>> + break;
>>>> + default:
>>>> +
>>>> + break;
>>>> + }
>>>> +#endif
>>>> +}
>>>> +
>>>> +target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
>>>> + target_ulong rd, target_ulong ra, uint32_t offset)
>>>> +{
>>>> +#ifndef CONFIG_USER_ONLY
>>>> + int spr = (ra | offset);
>>>> + int idx;
>>>> +
>>>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
>>>> +
>>>> + switch (spr) {
>>>> + case TO_SPR(0, 0): /* VR */
>>>> + return env->vr & SPR_VR;
>>>> +
>>>> + case TO_SPR(0, 1): /* UPR */
>>>> + return env->upr; /* TT, DM, IM, UP present */
>>>> +
>>>> + case TO_SPR(0, 2): /* CPUCFGR */
>>>> + return env->cpucfgr;
>>>> +
>>>> + case TO_SPR(0, 3): /* DMMUCFGR */
>>>> + return env->dmmucfgr; /* 1Way, 64 entries */
>>>> +
>>>> + case TO_SPR(0, 4): /* IMMUCFGR */
>>>> + return env->immucfgr;
>>>> +
>>>> + case TO_SPR(0, 16): /* NPC */
>>>> + return env->npc;
>>>> +
>>>> + case TO_SPR(0, 17): /* SR */
>>>> + return env->sr;
>>>> +
>>>> + case TO_SPR(0, 18): /* PPC */
>>>> + return env->ppc;
>>>> +
>>>> + case TO_SPR(0, 32): /* EPCR */
>>>> + return env->epcr;
>>>> +
>>>> + case TO_SPR(0, 48): /* EEAR */
>>>> + return env->eear;
>>>> +
>>>> + case TO_SPR(0, 64): /* ESR */
>>>> + return env->esr;
>>>> +
>>>> + case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>>>> + idx = spr - TO_SPR(1, 512);
>>>> + return env->tlb->dtlb[0][idx].mr;
>>>> +
>>>> + case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>>>> + idx = spr - TO_SPR(1, 640);
>>>> + return env->tlb->dtlb[0][idx].tr;
>>>> +
>>>> + 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);
>>>> + return env->tlb->itlb[0][idx].mr;
>>>> +
>>>> + case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>>>> + idx = spr - TO_SPR(2, 640);
>>>> + return env->tlb->itlb[0][idx].tr;
>>>> +
>>>> + 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 */
>>>> + return env->picmr;
>>>> +
>>>> + case TO_SPR(9, 2): /* PICSR */
>>>> + return env->picsr;
>>>> +
>>>> + case TO_SPR(10, 0): /* TTMR */
>>>> + return env->ttmr;
>>>> +
>>>> + case TO_SPR(10, 1): /* TTCR */
>>>> + cpu_openrisc_count_update(cpu);
>>>> + return env->ttcr;
>>>> +
>>>> + default:
>>>> + break;
>>>> + }
>>>> +#endif
>>>> +
>>>> +/*If we later need to add tracepoints (or debug printfs) for the return
>>>> +value, it may be useful to structure the code like this:
>>>> +
>>>> +target_ulong ret = 0;
>>>> +
>>>> +switch() {
>>>> +case x:
>>>> + ret = y;
>>>> + break;
>>>> +case z:
>>>> + ret = 42;
>>>> + break;
>>>> +...
>>>> +}
>>>> +
>>>> +later something like trace_spr_read(ret);
>>>> +
>>>> +return ret;*/
>>>> +
>>>> + /* for rd is passed in, if rd unchanged, just keep it back. */
>>>> + return rd;
>>>> +}
>>>> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
>>>> index ed25604..8069edb 100644
>>>> --- a/target-openrisc/translate.c
>>>> +++ b/target-openrisc/translate.c
>>>> @@ -995,10 +995,20 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
>>>>
>>>> case 0x2d: /* l.mfspr */
>>>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>>>> + {
>>>> + TCGv_i32 ti = tcg_const_i32(I16);
>>>> + gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
>>>> + tcg_temp_free_i32(ti);
>>>> + }
>>>> break;
>>>>
>>>> case 0x30: /* l.mtspr */
>>>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>>>> + {
>>>> + TCGv_i32 im = tcg_const_i32(tmp);
>>>> + gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>>>> + tcg_temp_free_i32(im);
>>>> + }
>>>> break;
>>>
>>> openrisc ISA says that l.mtspr/l.mfspr are only accessible in supervisor mode,
>>> but I don't see where it is enforced.
>>>
>>
>> Thank you for mind me, it is the new code. Is it OK?
>
> I don't think so, please check for example target-ppc/translate.c:4192
> on how supervisor only mfsr is handled there.
>
Thank you for comment, Blue.
is this code OK?
case 0x2d: /* l.mfspr */
LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
{
#if defined(CONFIG_USER_ONLY)
gen_illegal_exception(dc);
#else
TCGv_i32 ti = tcg_const_i32(I16);
gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
tcg_temp_free_i32(ti);
#endif
}
break;
case 0x30: /* l.mtspr */
LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
{
#if defined(CONFIG_USER_ONLY)
gen_illegal_exception(dc);
#else
TCGv_i32 im = tcg_const_i32(tmp);
gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
tcg_temp_free_i32(im);
#endif
}
break;
>>
>> #ifndef CONFIG_USER_ONLY
>> case 0x2d: /* l.mfspr */
>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>> {
>> TCGv_i32 ti = tcg_const_i32(I16);
>> gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
>> tcg_temp_free_i32(ti);
>> }
>> break;
>>
>> case 0x30: /* l.mtspr */
>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>> {
>> TCGv_i32 im = tcg_const_i32(tmp);
>> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>> tcg_temp_free_i32(im);
>> }
>> break;
>> #endif
>>
>>
>>> --
>>> Thanks.
>>> -- Max
>>
>> Regards,
>> Jia
>>
Regards,
Jia
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions
2012-07-14 13:39 ` Jia Liu
@ 2012-07-14 13:49 ` Max Filippov
2012-07-14 14:08 ` Jia Liu
0 siblings, 1 reply; 30+ messages in thread
From: Max Filippov @ 2012-07-14 13:49 UTC (permalink / raw)
To: Jia Liu; +Cc: Blue Swirl, qemu-devel
On Sat, Jul 14, 2012 at 5:39 PM, Jia Liu <proljc@gmail.com> wrote:
> Hi Blue,
>
> On Sat, Jul 14, 2012 at 9:19 PM, Blue Swirl <blauwirbel@gmail.com> wrote:
>> On Sat, Jul 14, 2012 at 11:12 AM, Jia Liu <proljc@gmail.com> wrote:
>>> Hi Max
>>>
>>> On Fri, Jul 13, 2012 at 5:27 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
>>>> On Fri, Jul 13, 2012 at 8:35 AM, Jia Liu <proljc@gmail.com> wrote:
>>>>> Add OpenRISC system instructions.
>>>>>
>>>>> Signed-off-by: Jia Liu <proljc@gmail.com>
>>>>> ---
>>>>> target-openrisc/Makefile.objs | 2 +-
>>>>> target-openrisc/cpu.h | 3 +
>>>>> target-openrisc/helper.h | 4 +
>>>>> target-openrisc/sys_helper.c | 287 +++++++++++++++++++++++++++++++++++++++++
>>>>> target-openrisc/translate.c | 10 ++
>>>>> 5 files changed, 305 insertions(+), 1 deletion(-)
>>>>> create mode 100644 target-openrisc/sys_helper.c
>>>>>
>>>>> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
>>>>> index 926fc2f..44dc539 100644
>>>>> --- a/target-openrisc/Makefile.objs
>>>>> +++ b/target-openrisc/Makefile.objs
>>>>> @@ -1,4 +1,4 @@
>>>>> obj-$(CONFIG_SOFTMMU) += machine.o
>>>>> obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
>>>>> obj-y += exception_helper.o fpu_helper.o int_helper.o \
>>>>> - interrupt_helper.o mmu_helper.o
>>>>> + interrupt_helper.o mmu_helper.o sys_helper.o
>>>>> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
>>>>> index df07eaf..6506665 100644
>>>>> --- a/target-openrisc/cpu.h
>>>>> +++ b/target-openrisc/cpu.h
>>>>> @@ -80,6 +80,9 @@ enum {
>>>>> (reg) |= ((v & 0x1f) << 2);\
>>>>> } while (0)
>>>>>
>>>>> +/* Version Register */
>>>>> +#define SPR_VR 0xFFFF003F
>>>>> +
>>>>> /* Internal flags, delay slot flag */
>>>>> #define D_FLAG 1
>>>>>
>>>>> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
>>>>> index 6eb259a..836a70b 100644
>>>>> --- a/target-openrisc/helper.h
>>>>> +++ b/target-openrisc/helper.h
>>>>> @@ -63,4 +63,8 @@ DEF_HELPER_FLAGS_3(mul32, 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, tl, 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..7ff8e15
>>>>> --- /dev/null
>>>>> +++ b/target-openrisc/sys_helper.c
>>>>> @@ -0,0 +1,287 @@
>>>>> +/*
>>>>> + * OpenRISC system instructions helper routines
>>>>> + *
>>>>> + * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
>>>>> + * Zhizhou Zhang <etouzh@gmail.com>
>>>>> + *
>>>>> + * This library is free software; you can redistribute it and/or
>>>>> + * modify it under the terms of the GNU Lesser General Public
>>>>> + * License as published by the Free Software Foundation; either
>>>>> + * version 2 of the License, or (at your option) any later version.
>>>>> + *
>>>>> + * This library is distributed in the hope that it will be useful,
>>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>>>>> + * Lesser General Public License for more details.
>>>>> + *
>>>>> + * You should have received a copy of the GNU Lesser General Public
>>>>> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
>>>>> + */
>>>>> +
>>>>> +#include "cpu.h"
>>>>> +#include "helper.h"
>>>>> +
>>>>> +#define TO_SPR(group, number) (((group) << 11) + (number))
>>>>> +
>>>>> +void HELPER(mtspr)(CPUOpenRISCState *env,
>>>>> + target_ulong ra, target_ulong rb, target_ulong offset)
>>>>> +{
>>>>> +#ifndef CONFIG_USER_ONLY
>>>>> + int spr = (ra | offset);
>>>>> + int idx;
>>>>> +
>>>>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
>>>>> +
>>>>> + switch (spr) {
>>>>> + case TO_SPR(0, 0): /* VR */
>>>>> + env->vr = rb;
>>>>> + break;
>>>>> +
>>>>> + case TO_SPR(0, 16): /* NPC */
>>>>> + env->npc = rb;
>>>>> + break;
>>>>> +
>>>>> + case TO_SPR(0, 17): /* SR */
>>>>> + if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
>>>>> + (rb & (SR_IME | SR_DME | SR_SM))) {
>>>>> + tlb_flush(env, 1);
>>>>> + }
>>>>> + env->sr = rb;
>>>>> + env->sr |= SR_FO; /* FO is const equal to 1 */
>>>>> + if (env->sr & SR_DME) {
>>>>> + env->tlb->cpu_openrisc_map_address_data =
>>>>> + &cpu_openrisc_get_phys_data;
>>>>> + } else {
>>>>> + env->tlb->cpu_openrisc_map_address_data =
>>>>> + &cpu_openrisc_get_phys_nommu;
>>>>> + }
>>>>> +
>>>>> + if (env->sr & SR_IME) {
>>>>> + env->tlb->cpu_openrisc_map_address_code =
>>>>> + &cpu_openrisc_get_phys_code;
>>>>> + } else {
>>>>> + env->tlb->cpu_openrisc_map_address_code =
>>>>> + &cpu_openrisc_get_phys_nommu;
>>>>> + }
>>>>> + break;
>>>>> +
>>>>> + case TO_SPR(0, 18): /* PPC */
>>>>> + env->ppc = rb;
>>>>> + break;
>>>>> +
>>>>> + case TO_SPR(0, 32): /* EPCR */
>>>>> + env->epcr = rb;
>>>>> + break;
>>>>> +
>>>>> + case TO_SPR(0, 48): /* EEAR */
>>>>> + env->eear = rb;
>>>>> + break;
>>>>> +
>>>>> + case TO_SPR(0, 64): /* ESR */
>>>>> + env->esr = rb;
>>>>> + break;
>>>>> + case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>>>>> + idx = spr - TO_SPR(1, 512);
>>>>> + if (!(rb & 1)) {
>>>>> + tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
>>>>> + }
>>>>> + env->tlb->dtlb[0][idx].mr = rb;
>>>>> + break;
>>>>> +
>>>>> + case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>>>>> + idx = spr - TO_SPR(1, 640);
>>>>> + env->tlb->dtlb[0][idx].tr = 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 (!(rb & 1)) {
>>>>> + tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
>>>>> + }
>>>>> + env->tlb->itlb[0][idx].mr = rb;
>>>>> + break;
>>>>> +
>>>>> + case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>>>>> + idx = spr - TO_SPR(2, 640);
>>>>> + env->tlb->itlb[0][idx].tr = rb;
>>>>> + 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->picmr |= rb;
>>>>> + break;
>>>>> + case TO_SPR(9, 2): /* PICSR */
>>>>> + env->picsr &= ~rb;
>>>>> + break;
>>>>> + case TO_SPR(10, 0): /* TTMR */
>>>>> + {
>>>>> + int ip = env->ttmr & TTMR_IP;
>>>>> +
>>>>> + if (rb & TTMR_IP) { /* Keep IP bit. */
>>>>> + env->ttmr = (rb & ~TTMR_IP) + ip;
>>>>> + } else { /* Clear IP bit. */
>>>>> + env->ttmr = rb & ~TTMR_IP;
>>>>> + env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
>>>>> + }
>>>>> +
>>>>> + cpu_openrisc_count_update(cpu);
>>>>> +
>>>>> + switch (env->ttmr & TTMR_M) {
>>>>> + case TIMER_NONE:
>>>>> + cpu_openrisc_count_stop(cpu);
>>>>> + break;
>>>>> + case TIMER_INTR:
>>>>> + cpu_openrisc_count_start(cpu);
>>>>> + break;
>>>>> + case TIMER_SHOT:
>>>>> + cpu_openrisc_count_start(cpu);
>>>>> + break;
>>>>> + case TIMER_CONT:
>>>>> + cpu_openrisc_count_start(cpu);
>>>>> + break;
>>>>> + default:
>>>>> + break;
>>>>> + }
>>>>> + }
>>>>> + break;
>>>>> +
>>>>> + case TO_SPR(10, 1): /* TTCR */
>>>>> + env->ttcr = rb;
>>>>> + if (env->ttmr & TIMER_NONE) {
>>>>> + return;
>>>>> + }
>>>>> + cpu_openrisc_count_start(cpu);
>>>>> + break;
>>>>> + default:
>>>>> +
>>>>> + break;
>>>>> + }
>>>>> +#endif
>>>>> +}
>>>>> +
>>>>> +target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
>>>>> + target_ulong rd, target_ulong ra, uint32_t offset)
>>>>> +{
>>>>> +#ifndef CONFIG_USER_ONLY
>>>>> + int spr = (ra | offset);
>>>>> + int idx;
>>>>> +
>>>>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
>>>>> +
>>>>> + switch (spr) {
>>>>> + case TO_SPR(0, 0): /* VR */
>>>>> + return env->vr & SPR_VR;
>>>>> +
>>>>> + case TO_SPR(0, 1): /* UPR */
>>>>> + return env->upr; /* TT, DM, IM, UP present */
>>>>> +
>>>>> + case TO_SPR(0, 2): /* CPUCFGR */
>>>>> + return env->cpucfgr;
>>>>> +
>>>>> + case TO_SPR(0, 3): /* DMMUCFGR */
>>>>> + return env->dmmucfgr; /* 1Way, 64 entries */
>>>>> +
>>>>> + case TO_SPR(0, 4): /* IMMUCFGR */
>>>>> + return env->immucfgr;
>>>>> +
>>>>> + case TO_SPR(0, 16): /* NPC */
>>>>> + return env->npc;
>>>>> +
>>>>> + case TO_SPR(0, 17): /* SR */
>>>>> + return env->sr;
>>>>> +
>>>>> + case TO_SPR(0, 18): /* PPC */
>>>>> + return env->ppc;
>>>>> +
>>>>> + case TO_SPR(0, 32): /* EPCR */
>>>>> + return env->epcr;
>>>>> +
>>>>> + case TO_SPR(0, 48): /* EEAR */
>>>>> + return env->eear;
>>>>> +
>>>>> + case TO_SPR(0, 64): /* ESR */
>>>>> + return env->esr;
>>>>> +
>>>>> + case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>>>>> + idx = spr - TO_SPR(1, 512);
>>>>> + return env->tlb->dtlb[0][idx].mr;
>>>>> +
>>>>> + case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>>>>> + idx = spr - TO_SPR(1, 640);
>>>>> + return env->tlb->dtlb[0][idx].tr;
>>>>> +
>>>>> + 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);
>>>>> + return env->tlb->itlb[0][idx].mr;
>>>>> +
>>>>> + case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>>>>> + idx = spr - TO_SPR(2, 640);
>>>>> + return env->tlb->itlb[0][idx].tr;
>>>>> +
>>>>> + 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 */
>>>>> + return env->picmr;
>>>>> +
>>>>> + case TO_SPR(9, 2): /* PICSR */
>>>>> + return env->picsr;
>>>>> +
>>>>> + case TO_SPR(10, 0): /* TTMR */
>>>>> + return env->ttmr;
>>>>> +
>>>>> + case TO_SPR(10, 1): /* TTCR */
>>>>> + cpu_openrisc_count_update(cpu);
>>>>> + return env->ttcr;
>>>>> +
>>>>> + default:
>>>>> + break;
>>>>> + }
>>>>> +#endif
>>>>> +
>>>>> +/*If we later need to add tracepoints (or debug printfs) for the return
>>>>> +value, it may be useful to structure the code like this:
>>>>> +
>>>>> +target_ulong ret = 0;
>>>>> +
>>>>> +switch() {
>>>>> +case x:
>>>>> + ret = y;
>>>>> + break;
>>>>> +case z:
>>>>> + ret = 42;
>>>>> + break;
>>>>> +...
>>>>> +}
>>>>> +
>>>>> +later something like trace_spr_read(ret);
>>>>> +
>>>>> +return ret;*/
>>>>> +
>>>>> + /* for rd is passed in, if rd unchanged, just keep it back. */
>>>>> + return rd;
>>>>> +}
>>>>> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
>>>>> index ed25604..8069edb 100644
>>>>> --- a/target-openrisc/translate.c
>>>>> +++ b/target-openrisc/translate.c
>>>>> @@ -995,10 +995,20 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
>>>>>
>>>>> case 0x2d: /* l.mfspr */
>>>>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>>>>> + {
>>>>> + TCGv_i32 ti = tcg_const_i32(I16);
>>>>> + gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
>>>>> + tcg_temp_free_i32(ti);
>>>>> + }
>>>>> break;
>>>>>
>>>>> case 0x30: /* l.mtspr */
>>>>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>>>>> + {
>>>>> + TCGv_i32 im = tcg_const_i32(tmp);
>>>>> + gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>>>>> + tcg_temp_free_i32(im);
>>>>> + }
>>>>> break;
>>>>
>>>> openrisc ISA says that l.mtspr/l.mfspr are only accessible in supervisor mode,
>>>> but I don't see where it is enforced.
>>>>
>>>
>>> Thank you for mind me, it is the new code. Is it OK?
>>
>> I don't think so, please check for example target-ppc/translate.c:4192
>> on how supervisor only mfsr is handled there.
>>
>
> Thank you for comment, Blue.
>
> is this code OK?
Shouldn't there also be an exception in softmmu mode
if the CPU is not in supervisor mode?
>
> case 0x2d: /* l.mfspr */
> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
> {
> #if defined(CONFIG_USER_ONLY)
> gen_illegal_exception(dc);
> #else
> TCGv_i32 ti = tcg_const_i32(I16);
> gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
> tcg_temp_free_i32(ti);
> #endif
> }
> break;
>
> case 0x30: /* l.mtspr */
> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
> {
> #if defined(CONFIG_USER_ONLY)
> gen_illegal_exception(dc);
> #else
> TCGv_i32 im = tcg_const_i32(tmp);
> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
> tcg_temp_free_i32(im);
> #endif
> }
> break;
>
>>>
>>> #ifndef CONFIG_USER_ONLY
>>> case 0x2d: /* l.mfspr */
>>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>>> {
>>> TCGv_i32 ti = tcg_const_i32(I16);
>>> gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
>>> tcg_temp_free_i32(ti);
>>> }
>>> break;
>>>
>>> case 0x30: /* l.mtspr */
>>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>>> {
>>> TCGv_i32 im = tcg_const_i32(tmp);
>>> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>>> tcg_temp_free_i32(im);
>>> }
>>> break;
>>> #endif
>>>
>>>
>>>> --
>>>> Thanks.
>>>> -- Max
>>>
>>> Regards,
>>> Jia
>>>
>
> Regards,
> Jia
--
Thanks.
-- Max
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions
2012-07-14 13:49 ` Max Filippov
@ 2012-07-14 14:08 ` Jia Liu
2012-07-14 14:42 ` Blue Swirl
0 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-07-14 14:08 UTC (permalink / raw)
To: Max Filippov; +Cc: Blue Swirl, qemu-devel
Hi Max
On Sat, Jul 14, 2012 at 9:49 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
>>> I don't think so, please check for example target-ppc/translate.c:4192
>>> on how supervisor only mfsr is handled there.
>>>
>>
>> Thank you for comment, Blue.
>>
>> is this code OK?
>
> Shouldn't there also be an exception in softmmu mode
> if the CPU is not in supervisor mode?
>
Sorry, I...
May you give me more comment? I'm not sure about this.
>>
>> case 0x2d: /* l.mfspr */
>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>> {
>> #if defined(CONFIG_USER_ONLY)
>> gen_illegal_exception(dc);
>> #else
>> TCGv_i32 ti = tcg_const_i32(I16);
>> gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
>> tcg_temp_free_i32(ti);
>> #endif
>> }
>> break;
>>
>> case 0x30: /* l.mtspr */
>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>> {
>> #if defined(CONFIG_USER_ONLY)
>> gen_illegal_exception(dc);
>> #else
>> TCGv_i32 im = tcg_const_i32(tmp);
>> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>> tcg_temp_free_i32(im);
>> #endif
>> }
>> break;
>>
>
> --
> Thanks.
> -- Max
Regards,
Jia.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions
2012-07-14 14:08 ` Jia Liu
@ 2012-07-14 14:42 ` Blue Swirl
2012-07-15 0:39 ` Jia Liu
0 siblings, 1 reply; 30+ messages in thread
From: Blue Swirl @ 2012-07-14 14:42 UTC (permalink / raw)
To: Jia Liu; +Cc: Max Filippov, qemu-devel
On Sat, Jul 14, 2012 at 2:08 PM, Jia Liu <proljc@gmail.com> wrote:
> Hi Max
>
> On Sat, Jul 14, 2012 at 9:49 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
>>>> I don't think so, please check for example target-ppc/translate.c:4192
>>>> on how supervisor only mfsr is handled there.
>>>>
>>>
>>> Thank you for comment, Blue.
>>>
>>> is this code OK?
>>
>> Shouldn't there also be an exception in softmmu mode
>> if the CPU is not in supervisor mode?
>>
>
> Sorry, I...
> May you give me more comment? I'm not sure about this.
If a user tries to execute a supervisor instruction (only allowed for
kernel level code, not applications), the instruction won't be
executed but an exception will be raised.
This is the PPC mfsr instruction part of target-ppc/translate.c:
/* mfsr */
static void gen_mfsr(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
#else
TCGv t0;
if (unlikely(!ctx->mem_idx)) {
Here the MMU mode is checked for user mode. I'd use more explicit
check ctx->mmu_idx == MMU_USER_IDX.
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
return;
}
t0 = tcg_const_tl(SR(ctx->opcode));
gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
tcg_temp_free(t0);
#endif
}
>
>>>
>>> case 0x2d: /* l.mfspr */
>>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>>> {
>>> #if defined(CONFIG_USER_ONLY)
>>> gen_illegal_exception(dc);
>>> #else
>>> TCGv_i32 ti = tcg_const_i32(I16);
>>> gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
>>> tcg_temp_free_i32(ti);
>>> #endif
>>> }
>>> break;
>>>
>>> case 0x30: /* l.mtspr */
>>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>>> {
>>> #if defined(CONFIG_USER_ONLY)
>>> gen_illegal_exception(dc);
>>> #else
>>> TCGv_i32 im = tcg_const_i32(tmp);
>>> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>>> tcg_temp_free_i32(im);
>>> #endif
>>> }
>>> break;
>>>
>>
>> --
>> Thanks.
>> -- Max
>
> Regards,
> Jia.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions
2012-07-14 14:42 ` Blue Swirl
@ 2012-07-15 0:39 ` Jia Liu
2012-07-15 7:54 ` Blue Swirl
0 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-07-15 0:39 UTC (permalink / raw)
To: Blue Swirl; +Cc: Max Filippov, qemu-devel
Hi Blue
On Sat, Jul 14, 2012 at 10:42 PM, Blue Swirl <blauwirbel@gmail.com> wrote:
> On Sat, Jul 14, 2012 at 2:08 PM, Jia Liu <proljc@gmail.com> wrote:
>> Hi Max
>>
>> On Sat, Jul 14, 2012 at 9:49 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
>>>>> I don't think so, please check for example target-ppc/translate.c:4192
>>>>> on how supervisor only mfsr is handled there.
>>>>>
>>>>
>>>> Thank you for comment, Blue.
>>>>
>>>> is this code OK?
>>>
>>> Shouldn't there also be an exception in softmmu mode
>>> if the CPU is not in supervisor mode?
>>>
>>
>> Sorry, I...
>> May you give me more comment? I'm not sure about this.
>
> If a user tries to execute a supervisor instruction (only allowed for
> kernel level code, not applications), the instruction won't be
> executed but an exception will be raised.
>
> This is the PPC mfsr instruction part of target-ppc/translate.c:
> /* mfsr */
> static void gen_mfsr(DisasContext *ctx)
> {
> #if defined(CONFIG_USER_ONLY)
> gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
> #else
> TCGv t0;
> if (unlikely(!ctx->mem_idx)) {
>
> Here the MMU mode is checked for user mode. I'd use more explicit
> check ctx->mmu_idx == MMU_USER_IDX.
>
> gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
> return;
> }
> t0 = tcg_const_tl(SR(ctx->opcode));
> gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
> tcg_temp_free(t0);
> #endif
> }
>
Thank you very much for this nice example.
Is this code OK?
case 0x2d: /* l.mfspr */
LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
{
#if defined(CONFIG_USER_ONLY)
gen_illegal_exception(dc);
#else
TCGv_i32 ti = tcg_const_i32(I16);
if (dc->mem_idx == MMU_USER_IDX) {
gen_illegal_exception(dc);
return;
}
gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
tcg_temp_free_i32(ti);
#endif
}
break;
case 0x30: /* l.mtspr */
LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
{
#if defined(CONFIG_USER_ONLY)
gen_illegal_exception(dc);
#else
TCGv_i32 im = tcg_const_i32(tmp);
if (dc->mem_idx == MMU_USER_IDX) {
gen_illegal_exception(dc);
return;
}
gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
tcg_temp_free_i32(im);
#endif
}
break;
>>
>>>>
>>>> case 0x2d: /* l.mfspr */
>>>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>>>> {
>>>> #if defined(CONFIG_USER_ONLY)
>>>> gen_illegal_exception(dc);
>>>> #else
>>>> TCGv_i32 ti = tcg_const_i32(I16);
>>>> gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
>>>> tcg_temp_free_i32(ti);
>>>> #endif
>>>> }
>>>> break;
>>>>
>>>> case 0x30: /* l.mtspr */
>>>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>>>> {
>>>> #if defined(CONFIG_USER_ONLY)
>>>> gen_illegal_exception(dc);
>>>> #else
>>>> TCGv_i32 im = tcg_const_i32(tmp);
>>>> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>>>> tcg_temp_free_i32(im);
>>>> #endif
>>>> }
>>>> break;
>>>>
>>>
>>> --
>>> Thanks.
>>> -- Max
>>
>> Regards,
>> Jia.
Regards,
Jia
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions
2012-07-15 0:39 ` Jia Liu
@ 2012-07-15 7:54 ` Blue Swirl
2012-07-15 13:31 ` Jia Liu
0 siblings, 1 reply; 30+ messages in thread
From: Blue Swirl @ 2012-07-15 7:54 UTC (permalink / raw)
To: Jia Liu; +Cc: Max Filippov, qemu-devel
On Sun, Jul 15, 2012 at 12:39 AM, Jia Liu <proljc@gmail.com> wrote:
> Hi Blue
>
> On Sat, Jul 14, 2012 at 10:42 PM, Blue Swirl <blauwirbel@gmail.com> wrote:
>> On Sat, Jul 14, 2012 at 2:08 PM, Jia Liu <proljc@gmail.com> wrote:
>>> Hi Max
>>>
>>> On Sat, Jul 14, 2012 at 9:49 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
>>>>>> I don't think so, please check for example target-ppc/translate.c:4192
>>>>>> on how supervisor only mfsr is handled there.
>>>>>>
>>>>>
>>>>> Thank you for comment, Blue.
>>>>>
>>>>> is this code OK?
>>>>
>>>> Shouldn't there also be an exception in softmmu mode
>>>> if the CPU is not in supervisor mode?
>>>>
>>>
>>> Sorry, I...
>>> May you give me more comment? I'm not sure about this.
>>
>> If a user tries to execute a supervisor instruction (only allowed for
>> kernel level code, not applications), the instruction won't be
>> executed but an exception will be raised.
>>
>> This is the PPC mfsr instruction part of target-ppc/translate.c:
>> /* mfsr */
>> static void gen_mfsr(DisasContext *ctx)
>> {
>> #if defined(CONFIG_USER_ONLY)
>> gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
>> #else
>> TCGv t0;
>> if (unlikely(!ctx->mem_idx)) {
>>
>> Here the MMU mode is checked for user mode. I'd use more explicit
>> check ctx->mmu_idx == MMU_USER_IDX.
>>
>> gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
>> return;
>> }
>> t0 = tcg_const_tl(SR(ctx->opcode));
>> gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
>> tcg_temp_free(t0);
>> #endif
>> }
>>
>
> Thank you very much for this nice example.
> Is this code OK?
> case 0x2d: /* l.mfspr */
> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
> {
> #if defined(CONFIG_USER_ONLY)
> gen_illegal_exception(dc);
> #else
> TCGv_i32 ti = tcg_const_i32(I16);
> if (dc->mem_idx == MMU_USER_IDX) {
> gen_illegal_exception(dc);
> return;
> }
> gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
> tcg_temp_free_i32(ti);
> #endif
> }
> break;
>
> case 0x30: /* l.mtspr */
> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
> {
> #if defined(CONFIG_USER_ONLY)
> gen_illegal_exception(dc);
Maybe return?
> #else
> TCGv_i32 im = tcg_const_i32(tmp);
> if (dc->mem_idx == MMU_USER_IDX) {
> gen_illegal_exception(dc);
> return;
> }
> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
> tcg_temp_free_i32(im);
> #endif
> }
> break;
Otherwise looks OK. Perhaps there are other supervisor mode only
instructions which need this kind of checks?
>
>
>>>
>>>>>
>>>>> case 0x2d: /* l.mfspr */
>>>>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>>>>> {
>>>>> #if defined(CONFIG_USER_ONLY)
>>>>> gen_illegal_exception(dc);
>>>>> #else
>>>>> TCGv_i32 ti = tcg_const_i32(I16);
>>>>> gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
>>>>> tcg_temp_free_i32(ti);
>>>>> #endif
>>>>> }
>>>>> break;
>>>>>
>>>>> case 0x30: /* l.mtspr */
>>>>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>>>>> {
>>>>> #if defined(CONFIG_USER_ONLY)
>>>>> gen_illegal_exception(dc);
>>>>> #else
>>>>> TCGv_i32 im = tcg_const_i32(tmp);
>>>>> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>>>>> tcg_temp_free_i32(im);
>>>>> #endif
>>>>> }
>>>>> break;
>>>>>
>>>>
>>>> --
>>>> Thanks.
>>>> -- Max
>>>
>>> Regards,
>>> Jia.
>
> Regards,
> Jia
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions
2012-07-15 7:54 ` Blue Swirl
@ 2012-07-15 13:31 ` Jia Liu
0 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-07-15 13:31 UTC (permalink / raw)
To: Blue Swirl; +Cc: Max Filippov, qemu-devel
Hi Blue,
On Sun, Jul 15, 2012 at 3:54 PM, Blue Swirl <blauwirbel@gmail.com> wrote:
> On Sun, Jul 15, 2012 at 12:39 AM, Jia Liu <proljc@gmail.com> wrote:
>> Hi Blue
>>
>> On Sat, Jul 14, 2012 at 10:42 PM, Blue Swirl <blauwirbel@gmail.com> wrote:
>>> On Sat, Jul 14, 2012 at 2:08 PM, Jia Liu <proljc@gmail.com> wrote:
>>>> Hi Max
>>>>
>>>> On Sat, Jul 14, 2012 at 9:49 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
>>>>>>> I don't think so, please check for example target-ppc/translate.c:4192
>>>>>>> on how supervisor only mfsr is handled there.
>>>>>>>
>>>>>>
>>>>>> Thank you for comment, Blue.
>>>>>>
>>>>>> is this code OK?
>>>>>
>>>>> Shouldn't there also be an exception in softmmu mode
>>>>> if the CPU is not in supervisor mode?
>>>>>
>>>>
>>>> Sorry, I...
>>>> May you give me more comment? I'm not sure about this.
>>>
>>> If a user tries to execute a supervisor instruction (only allowed for
>>> kernel level code, not applications), the instruction won't be
>>> executed but an exception will be raised.
>>>
>>> This is the PPC mfsr instruction part of target-ppc/translate.c:
>>> /* mfsr */
>>> static void gen_mfsr(DisasContext *ctx)
>>> {
>>> #if defined(CONFIG_USER_ONLY)
>>> gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
>>> #else
>>> TCGv t0;
>>> if (unlikely(!ctx->mem_idx)) {
>>>
>>> Here the MMU mode is checked for user mode. I'd use more explicit
>>> check ctx->mmu_idx == MMU_USER_IDX.
>>>
>>> gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
>>> return;
>>> }
>>> t0 = tcg_const_tl(SR(ctx->opcode));
>>> gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
>>> tcg_temp_free(t0);
>>> #endif
>>> }
>>>
>>
>> Thank you very much for this nice example.
>> Is this code OK?
>> case 0x2d: /* l.mfspr */
>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>> {
>> #if defined(CONFIG_USER_ONLY)
>> gen_illegal_exception(dc);
>> #else
>> TCGv_i32 ti = tcg_const_i32(I16);
>> if (dc->mem_idx == MMU_USER_IDX) {
>> gen_illegal_exception(dc);
>> return;
>> }
>> gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
>> tcg_temp_free_i32(ti);
>> #endif
>> }
>> break;
>>
>> case 0x30: /* l.mtspr */
>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>> {
>> #if defined(CONFIG_USER_ONLY)
>> gen_illegal_exception(dc);
>
> Maybe return?
Thank you! I think return is a better way.
>
>> #else
>> TCGv_i32 im = tcg_const_i32(tmp);
>> if (dc->mem_idx == MMU_USER_IDX) {
>> gen_illegal_exception(dc);
>> return;
>> }
>> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>> tcg_temp_free_i32(im);
>> #endif
>> }
>> break;
>
>
> Otherwise looks OK. Perhaps there are other supervisor mode only
> instructions which need this kind of checks?
>
I'll make a check, thank you.
>>
>>
>>>>
>>>>>>
>>>>>> case 0x2d: /* l.mfspr */
>>>>>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>>>>>> {
>>>>>> #if defined(CONFIG_USER_ONLY)
>>>>>> gen_illegal_exception(dc);
>>>>>> #else
>>>>>> TCGv_i32 ti = tcg_const_i32(I16);
>>>>>> gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
>>>>>> tcg_temp_free_i32(ti);
>>>>>> #endif
>>>>>> }
>>>>>> break;
>>>>>>
>>>>>> case 0x30: /* l.mtspr */
>>>>>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>>>>>> {
>>>>>> #if defined(CONFIG_USER_ONLY)
>>>>>> gen_illegal_exception(dc);
>>>>>> #else
>>>>>> TCGv_i32 im = tcg_const_i32(tmp);
>>>>>> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>>>>>> tcg_temp_free_i32(im);
>>>>>> #endif
>>>>>> }
>>>>>> break;
>>>>>>
>>>>>
>>>>> --
>>>>> Thanks.
>>>>> -- Max
>>>>
>>>> Regards,
>>>> Jia.
>>
>> Regards,
>> Jia
Regards,
Jia
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2012-07-15 13:31 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-13 4:34 [Qemu-devel] [PATCH v9 00/15] QEMU OpenRISC support Jia Liu
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 01/15] target-or32: Add target stubs and QOM cpu Jia Liu
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 02/15] target-or32: Add MMU support Jia Liu
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 03/15] target-or32: Add interrupt support Jia Liu
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 04/15] target-or32: Add exception support Jia Liu
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 05/15] target-or32: Add int instruction helpers Jia Liu
2012-07-13 9:18 ` Max Filippov
2012-07-14 11:44 ` Jia Liu
2012-07-13 4:34 ` [Qemu-devel] [PATCH v9 06/15] target-or32: Add float " Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 07/15] target-or32: Add instruction translation Jia Liu
2012-07-13 8:09 ` Peter Maydell
2012-07-13 8:26 ` Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 08/15] target-or32: Add PIC support Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 09/15] target-or32: Add timer support Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 10/15] target-or32: Add a IIS dummy board Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 11/15] target-or32: Add system instructions Jia Liu
2012-07-13 9:27 ` Max Filippov
2012-07-14 11:12 ` Jia Liu
2012-07-14 13:19 ` Blue Swirl
2012-07-14 13:39 ` Jia Liu
2012-07-14 13:49 ` Max Filippov
2012-07-14 14:08 ` Jia Liu
2012-07-14 14:42 ` Blue Swirl
2012-07-15 0:39 ` Jia Liu
2012-07-15 7:54 ` Blue Swirl
2012-07-15 13:31 ` Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 12/15] target-or32: Add gdb stub support Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 13/15] target-or32: Add linux syscall, signal and termbits Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 14/15] target-or32: Add linux user support Jia Liu
2012-07-13 4:35 ` [Qemu-devel] [PATCH v9 15/15] target-or32: Add testcases Jia Liu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).