All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support
@ 2012-06-21  2:57 Jia Liu
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 01/16] target-or32: Add target stubs and cpu support Jia Liu
                   ` (15 more replies)
  0 siblings, 16 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:57 UTC (permalink / raw)
  To: qemu-devel

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

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

Version History:
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 (16):
  target-or32: Add target stubs and cpu support
  target-or32: Add target machine
  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 tanslation
  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
  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_cpudev.h                |   29 +
 hw/openrisc_pic.c                   |   78 ++
 hw/openrisc_sim.c                   |  160 ++++
 hw/openrisc_timer.c                 |  160 ++++
 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               |  240 +++++
 target-openrisc/cpu.h               |  449 +++++++++
 target-openrisc/excp.c              |   27 +
 target-openrisc/excp.h              |   28 +
 target-openrisc/excp_helper.c       |   27 +
 target-openrisc/fpu_helper.c        |  275 ++++++
 target-openrisc/helper.h            |   70 ++
 target-openrisc/int_helper.c        |   85 ++
 target-openrisc/intrpt.c            |   74 ++
 target-openrisc/intrpt_helper.c     |   52 ++
 target-openrisc/machine.c           |   50 +
 target-openrisc/mmu.c               |  236 +++++
 target-openrisc/mmu_helper.c        |   63 ++
 target-openrisc/sys_helper.c        |  244 +++++
 target-openrisc/translate.c         | 1761 +++++++++++++++++++++++++++++++++++
 tests/tcg/openrisc/Makefile         |   71 ++
 tests/tcg/openrisc/test_add.c       |   34 +
 tests/tcg/openrisc/test_addc.c      |   39 +
 tests/tcg/openrisc/test_addi.c      |   31 +
 tests/tcg/openrisc/test_addic.c     |   33 +
 tests/tcg/openrisc/test_and_or.c    |   61 ++
 tests/tcg/openrisc/test_bf.c        |   46 +
 tests/tcg/openrisc/test_bnf.c       |   50 +
 tests/tcg/openrisc/test_div.c       |   32 +
 tests/tcg/openrisc/test_divu.c      |   32 +
 tests/tcg/openrisc/test_extx.c      |   72 ++
 tests/tcg/openrisc/test_fx.c        |   53 ++
 tests/tcg/openrisc/test_j.c         |   26 +
 tests/tcg/openrisc/test_jal.c       |   26 +
 tests/tcg/openrisc/test_lf_add.c    |   39 +
 tests/tcg/openrisc/test_lf_div.c    |   34 +
 tests/tcg/openrisc/test_lf_eqs.c    |   84 ++
 tests/tcg/openrisc/test_lf_ges.c    |   84 ++
 tests/tcg/openrisc/test_lf_gts.c    |   84 ++
 tests/tcg/openrisc/test_lf_les.c    |   84 ++
 tests/tcg/openrisc/test_lf_lts.c    |   91 ++
 tests/tcg/openrisc/test_lf_mul.c    |   22 +
 tests/tcg/openrisc/test_lf_nes.c    |   87 ++
 tests/tcg/openrisc/test_lf_rem.c    |   32 +
 tests/tcg/openrisc/test_lf_sub.c    |   33 +
 tests/tcg/openrisc/test_logic.c     |  100 ++
 tests/tcg/openrisc/test_lx.c        |   78 ++
 tests/tcg/openrisc/test_movhi.c     |   30 +
 tests/tcg/openrisc/test_mul.c       |   47 +
 tests/tcg/openrisc/test_muli.c      |   47 +
 tests/tcg/openrisc/test_mulu.c      |   47 +
 tests/tcg/openrisc/test_sfeq.c      |   44 +
 tests/tcg/openrisc/test_sfeqi.c     |   39 +
 tests/tcg/openrisc/test_sfges.c     |   44 +
 tests/tcg/openrisc/test_sfgesi.c    |   40 +
 tests/tcg/openrisc/test_sfgeu.c     |   44 +
 tests/tcg/openrisc/test_sfgeui.c    |   41 +
 tests/tcg/openrisc/test_sfgts.c     |   45 +
 tests/tcg/openrisc/test_sfgtsi.c    |   41 +
 tests/tcg/openrisc/test_sfgtu.c     |   43 +
 tests/tcg/openrisc/test_sfgtui.c    |   42 +
 tests/tcg/openrisc/test_sfles.c     |   26 +
 tests/tcg/openrisc/test_sflesi.c    |   39 +
 tests/tcg/openrisc/test_sfleu.c     |   43 +
 tests/tcg/openrisc/test_sfleui.c    |   39 +
 tests/tcg/openrisc/test_sflts.c     |   43 +
 tests/tcg/openrisc/test_sfltsi.c    |   38 +
 tests/tcg/openrisc/test_sfltu.c     |   41 +
 tests/tcg/openrisc/test_sfltui.c    |   39 +
 tests/tcg/openrisc/test_sfne.c      |   43 +
 tests/tcg/openrisc/test_sfnei.c     |   38 +
 tests/tcg/openrisc/test_sub.c       |   34 +
 91 files changed, 7955 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_cpudev.h
 create mode 100644 hw/openrisc_pic.c
 create mode 100644 hw/openrisc_sim.c
 create mode 100644 hw/openrisc_timer.c
 create mode 100644 linux-user/openrisc/syscall.h
 create mode 100644 linux-user/openrisc/syscall_nr.h
 create mode 100644 linux-user/openrisc/target_signal.h
 create mode 100644 linux-user/openrisc/termbits.h
 create mode 100644 target-openrisc/Makefile.objs
 create mode 100644 target-openrisc/cpu.c
 create mode 100644 target-openrisc/cpu.h
 create mode 100644 target-openrisc/excp.c
 create mode 100644 target-openrisc/excp.h
 create mode 100644 target-openrisc/excp_helper.c
 create mode 100644 target-openrisc/fpu_helper.c
 create mode 100644 target-openrisc/helper.h
 create mode 100644 target-openrisc/int_helper.c
 create mode 100644 target-openrisc/intrpt.c
 create mode 100644 target-openrisc/intrpt_helper.c
 create mode 100644 target-openrisc/machine.c
 create mode 100644 target-openrisc/mmu.c
 create mode 100644 target-openrisc/mmu_helper.c
 create mode 100644 target-openrisc/sys_helper.c
 create mode 100644 target-openrisc/translate.c
 create mode 100644 tests/tcg/openrisc/Makefile
 create mode 100644 tests/tcg/openrisc/test_add.c
 create mode 100644 tests/tcg/openrisc/test_addc.c
 create mode 100644 tests/tcg/openrisc/test_addi.c
 create mode 100644 tests/tcg/openrisc/test_addic.c
 create mode 100644 tests/tcg/openrisc/test_and_or.c
 create mode 100644 tests/tcg/openrisc/test_bf.c
 create mode 100644 tests/tcg/openrisc/test_bnf.c
 create mode 100644 tests/tcg/openrisc/test_div.c
 create mode 100644 tests/tcg/openrisc/test_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] 25+ messages in thread

* [Qemu-devel] [PATCH v6 01/16] target-or32: Add target stubs and cpu support
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
@ 2012-06-21  2:57 ` Jia Liu
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 02/16] target-or32: Add target machine Jia Liu
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:57 UTC (permalink / raw)
  To: qemu-devel

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        |    3 +
 hw/openrisc_cpudev.h             |   29 ++++
 hw/openrisc_pic.c                |   30 ++++
 hw/openrisc_timer.c              |   30 ++++
 poison.h                         |    1 +
 target-openrisc/Makefile.objs    |    3 +
 target-openrisc/cpu.c            |  240 +++++++++++++++++++++++++++++++
 target-openrisc/cpu.h            |  292 ++++++++++++++++++++++++++++++++++++++
 target-openrisc/intrpt.c         |   30 ++++
 target-openrisc/machine.c        |   30 ++++
 target-openrisc/mmu.c            |   39 +++++
 target-openrisc/mmu_helper.c     |   43 ++++++
 target-openrisc/translate.c      |   75 ++++++++++
 19 files changed, 868 insertions(+), 2 deletions(-)
 create mode 100644 default-configs/or32-softmmu.mak
 create mode 100644 hw/openrisc/Makefile.objs
 create mode 100644 hw/openrisc_cpudev.h
 create mode 100644 hw/openrisc_pic.c
 create mode 100644 hw/openrisc_timer.c
 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/intrpt.c
 create mode 100644 target-openrisc/machine.c
 create mode 100644 target-openrisc/mmu.c
 create mode 100644 target-openrisc/mmu_helper.c
 create mode 100644 target-openrisc/translate.c

diff --git a/arch_init.c b/arch_init.c
index a9e8b74..4b521e5 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -71,6 +71,8 @@ int graphic_depth = 15;
 #define QEMU_ARCH QEMU_ARCH_MICROBLAZE
 #elif defined(TARGET_MIPS)
 #define QEMU_ARCH QEMU_ARCH_MIPS
+#elif defined(TARGET_OPENRISC)
+#define QEMU_ARCH QEMU_ARCH_OPENRISC
 #elif defined(TARGET_PPC)
 #define QEMU_ARCH QEMU_ARCH_PPC
 #elif defined(TARGET_S390X)
diff --git a/arch_init.h b/arch_init.h
index c7cb94a..3dfea3b 100644
--- a/arch_init.h
+++ b/arch_init.h
@@ -16,6 +16,7 @@ enum {
     QEMU_ARCH_SH4 = 1024,
     QEMU_ARCH_SPARC = 2048,
     QEMU_ARCH_XTENSA = 4096,
+    QEMU_ARCH_OPENRISC = 8192,
 };
 
 extern const uint32_t arch_type;
diff --git a/configure b/configure
index b68c0ca..80ee0be 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 \
@@ -3485,7 +3486,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
@@ -3601,6 +3602,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
@@ -3679,7 +3685,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile"
 
 
 case "$target_arch2" in
-  alpha | sparc* | xtensa*)
+  alpha | or32 | sparc* | xtensa*)
     echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
   ;;
 esac
@@ -3850,6 +3856,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 624c409..7d0d87b 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)
@@ -630,6 +631,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..1c541a5
--- /dev/null
+++ b/hw/openrisc/Makefile.objs
@@ -0,0 +1,3 @@
+obj-y = openrisc_pic.o openrisc_timer.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/openrisc_cpudev.h b/hw/openrisc_cpudev.h
new file mode 100644
index 0000000..01bd422
--- /dev/null
+++ b/hw/openrisc_cpudev.h
@@ -0,0 +1,29 @@
+/*
+ *  QEMU OpenRISC CPU device support.
+ *
+ *  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 HW_OPENRISC_CPUDEV_H
+#define HW_OPENRISC_CPUDEV_H
+
+/* openrisc_pic.c */
+void cpu_openrisc_pic_init(CPUOpenRISCState *env);
+
+/* openrisc_timer.c*/
+void cpu_openrisc_clock_init(CPUOpenRISCState *env);
+
+#endif
diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
new file mode 100644
index 0000000..0d14bbe
--- /dev/null
+++ b/hw/openrisc_pic.c
@@ -0,0 +1,30 @@
+/*
+ *  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 "openrisc_cpudev.h"
+#include "cpu.h"
+
+/* Reset PIC */
+void cpu_openrisc_pic_reset(CPUOpenRISCState *env)
+{
+    env->picmr = 0x00000000;
+    env->picsr = 0x00000000;
+}
diff --git a/hw/openrisc_timer.c b/hw/openrisc_timer.c
new file mode 100644
index 0000000..df384f6
--- /dev/null
+++ b/hw/openrisc_timer.c
@@ -0,0 +1,30 @@
+/*
+ *  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 "hw.h"
+#include "openrisc_cpudev.h"
+#include "qemu-timer.h"
+
+/* Reset Timer */
+void cpu_openrisc_timer_reset(CPUOpenRISCState *env)
+{
+    env->ttmr = 0x00000000;
+    env->ttcr = 0x00000000;
+}
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..21b76b2
--- /dev/null
+++ b/target-openrisc/Makefile.objs
@@ -0,0 +1,3 @@
+obj-$(CONFIG_SOFTMMU) += machine.o
+obj-y += cpu.o intrpt.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..a99910c
--- /dev/null
+++ b/target-openrisc/cpu.c
@@ -0,0 +1,240 @@
+/*
+ *  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"
+#ifndef CONFIG_USER_ONLY
+#include "hw/loader.h"
+#endif
+
+/* CPUClass::reset() */
+static void openrisc_cpu_reset(CPUState *s)
+{
+    OpenRISCCPU *cpu = OPENRISC_CPU(s);
+    OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu);
+    CPUOpenRISCState *env = &cpu->env;
+
+    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        log_cpu_state(env, 0);
+    }
+
+    occ->parent_reset(s);
+
+    memset(env, 0, offsetof(CPUOpenRISCState, breakpoints));
+
+    tlb_flush(env, 1);
+    /*tb_flush(env);    FIXME: Do we need it?  */
+
+    env->pc = 0x100;
+    env->sr = SR_FO | SR_SM;
+    env->exception_index = -1;
+
+    env->upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP;
+    env->cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S;
+    env->dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2));
+    env->immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2));
+
+#ifndef CONFIG_USER_ONLY
+    cpu_openrisc_timer_reset(env);
+    cpu_openrisc_pic_reset(env);
+#endif
+}
+
+static inline int openrisc_feature(CPUOpenRISCState *env, int feature)
+{
+    return (env->feature & (1u << feature)) != 0;
+}
+
+static inline void set_feature(CPUOpenRISCState *env, int feature)
+{
+    env->feature |= 1u << feature;
+}
+
+void openrisc_cpu_realize(Object *obj, Error **errp)
+{
+    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
+    CPUOpenRISCState *env = &cpu->env;
+    if (openrisc_feature(env, OPENRISC_FEATURE_OR1200)) {
+        set_feature(env, OPENRISC_FEATURE_OB32S);
+        set_feature(env, OPENRISC_FEATURE_OF32S);
+    }
+
+    qemu_init_vcpu(&cpu->env);
+}
+
+static void openrisc_cpu_initfn(Object *obj)
+{
+    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
+    cpu_exec_init(&cpu->env);
+}
+
+/* CPU models */
+static void or1200_initfn(Object *obj)
+{
+    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
+    CPUOpenRISCState *env = &cpu->env;
+
+    set_feature(env, OPENRISC_FEATURE_OR1200);
+
+    cpu_reset(CPU(cpu));
+
+}
+
+static void openrisc_any_initfn(Object *obj)
+{
+    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
+    CPUOpenRISCState *env = &cpu->env;
+
+    set_feature(env, OPENRISC_FEATURE_OB32S);
+    set_feature(env, OPENRISC_FEATURE_OF32S);
+
+    cpu_reset(CPU(cpu));
+}
+
+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;
+    CPUOpenRISCState *env;
+    static int inited;
+    inited = 0;
+
+    if (!object_class_by_name(cpu_model)) {
+        return NULL;
+    }
+    cpu = OPENRISC_CPU(object_new(cpu_model));
+    env = &cpu->env;
+    env->cpu_model_str = cpu_model;
+
+    openrisc_cpu_realize(OBJECT(cpu), NULL);
+
+#ifndef CONFIG_USER_ONLY
+    openrisc_mmu_init(env);
+#endif
+
+    if (tcg_enabled() && !inited) {
+        inited = 1;
+        openrisc_translate_init();
+    }
+
+    cpu_reset(CPU(cpu));
+
+    return cpu;
+}
+
+typedef struct OpenRISCCPUListState {
+    fprintf_function cpu_fprintf;
+    FILE *file;
+} OpenRISCCPUListState;
+
+/* Sort alphabetically by type name, except for "any". */
+static gint openrisc_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+    ObjectClass *class_a = (ObjectClass *)a;
+    ObjectClass *class_b = (ObjectClass *)b;
+    const char *name_a, *name_b;
+
+    name_a = object_class_get_name(class_a);
+    name_b = object_class_get_name(class_b);
+    if (strcmp(name_a, "any") == 0) {
+        return 1;
+    } else if (strcmp(name_b, "any") == 0) {
+        return -1;
+    } else {
+        return strcmp(name_a, name_b);
+    }
+}
+
+static void openrisc_cpu_list_entry(gpointer data, gpointer user_data)
+{
+    ObjectClass *oc = data;
+    OpenRISCCPUListState *s = user_data;
+
+    (*s->cpu_fprintf)(s->file, "  %s\n",
+                      object_class_get_name(oc));
+}
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    OpenRISCCPUListState s = {
+        .file = f,
+        .cpu_fprintf = cpu_fprintf,
+    };
+    GSList *list;
+
+    list = object_class_get_list(TYPE_OPENRISC_CPU, false);
+    list = g_slist_sort(list, openrisc_cpu_list_compare);
+    (*cpu_fprintf)(f, "Available CPUs:\n");
+    g_slist_foreach(list, openrisc_cpu_list_entry, &s);
+    g_slist_free(list);
+}
+
+type_init(openrisc_cpu_register_types)
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
new file mode 100644
index 0000000..0b8e836
--- /dev/null
+++ b/target-openrisc/cpu.h
@@ -0,0 +1,292 @@
+/*
+ *  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_HAS_ICE 1
+
+#define CPUArchState struct CPUOpenRISCState
+
+#if defined(TARGET_OPENRISC64)
+#define TARGET_LONG_BITS 64
+#define ELF_MACHINE    EM_NONE
+#else
+#define TARGET_LONG_BITS 32
+#define ELF_MACHINE    EM_OPENRISC
+#endif
+
+#include "config.h"
+#include "qemu-common.h"
+#include "cpu-defs.h"
+#include "softfloat.h"
+#include "qemu/cpu.h"
+#include "error.h"
+
+struct CPUOpenRISCState;
+
+#define NB_MMU_MODES    3
+
+#define TARGET_PAGE_BITS 13
+
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+
+/* Internal flags, delay slot flag */
+#define D_FLAG    1
+
+/* Verison Register */
+#define SPR_VR       0xFFFF003F
+
+/* 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),
+};
+
+/* Supervisor register */
+enum {
+    SR_SM = 1,
+    SR_TEE = (1 << 1),
+    SR_IEE = (1 << 2),
+    SR_DCE = (1 << 3),
+    SR_ICE = (1 << 4),
+    SR_DME = (1 << 5),
+    SR_IME = (1 << 6),
+    SR_LEE = (1 << 7),
+    SR_CE  = (1 << 8),
+    SR_F   = (1 << 9),
+    SR_CY  = (1 << 10),
+    SR_OV  = (1 << 11),
+    SR_OVE = (1 << 12),
+    SR_DSX = (1 << 13),
+    SR_EPH = (1 << 14),
+    SR_FO  = (1 << 15),
+    SR_SUMRA = (1 << 16),
+    SR_SCE = (1 << 17),
+};
+
+/* OpenRISC Hardware Capabilities */
+enum {
+    OPENRISC_FEATURE_NSGF,
+    OPENRISC_FEATURE_CGF,
+    OPENRISC_FEATURE_OB32S,
+    OPENRISC_FEATURE_OB64S,
+    OPENRISC_FEATURE_OF32S,
+    OPENRISC_FEATURE_OF64S,
+    OPENRISC_FEATURE_OV64S,
+    OPENRISC_FEATURE_OR1200,
+};
+
+typedef struct CPUOpenRISCState CPUOpenRISCState;
+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 */
+
+    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 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
+    uint32_t feature;       /* CPU Capabilities */
+};
+
+#define TYPE_OPENRISC_CPU "or32-cpu"
+
+#define OPENRISC_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU)
+#define OPENRISC_CPU(obj) \
+    OBJECT_CHECK(OpenRISCCPU, (obj), TYPE_OPENRISC_CPU)
+#define OPENRISC_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(OpenRISCCPUClass, (obj), TYPE_OPENRISC_CPU)
+
+/**
+ * OpenRISCCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A OpenRISC CPU model.
+ */
+typedef struct OpenRISCCPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    void (*parent_reset)(CPUState *cpu);
+} OpenRISCCPUClass;
+
+/**
+ * OpenRISCCPU:
+ * @env: #CPUOpenRISCState
+ *
+ * A OpenRISC CPU.
+ */
+typedef struct OpenRISCCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUOpenRISCState env;
+} OpenRISCCPU;
+
+static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env)
+{
+    return OPENRISC_CPU(container_of(env, OpenRISCCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e))
+
+void openrisc_cpu_realize(Object *obj, Error **errp);
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
+OpenRISCCPU *cpu_openrisc_init(const char *cpu_model);
+int cpu_openrisc_exec(CPUOpenRISCState *s);
+void do_interrupt(CPUOpenRISCState *env);
+void openrisc_translate_init(void);
+
+#define cpu_list cpu_openrisc_list
+#define cpu_exec cpu_openrisc_exec
+#define cpu_gen_code cpu_openrisc_gen_code
+
+#define CPU_SAVE_VERSION 1
+
+#ifndef CONFIG_USER_ONLY
+void cpu_openrisc_pic_reset(CPUOpenRISCState *env);
+
+void cpu_openrisc_timer_reset(CPUOpenRISCState *env);
+
+void openrisc_mmu_init(CPUOpenRISCState *env);
+#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;
+    *flags = 0;
+}
+
+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 void cpu_pc_from_tb(CPUOpenRISCState *env, TranslationBlock *tb)
+{
+    env->pc = tb->pc;
+}
+
+#endif /* CPU_OPENRISC_H */
diff --git a/target-openrisc/intrpt.c b/target-openrisc/intrpt.c
new file mode 100644
index 0000000..a3bb7f8
--- /dev/null
+++ b/target-openrisc/intrpt.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..11bf275
--- /dev/null
+++ b/target-openrisc/machine.c
@@ -0,0 +1,30 @@
+/*
+ *  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"
+
+void cpu_save(QEMUFile *f, void *opaque)
+{
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    return 0;
+}
diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c
new file mode 100644
index 0000000..cd82b7a
--- /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 openrisc_mmu_init(CPUOpenRISCState *env)
+{
+}
+#endif
diff --git a/target-openrisc/mmu_helper.c b/target-openrisc/mmu_helper.c
new file mode 100644
index 0000000..f526ba8
--- /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..1d87d76
--- /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(CPUOpenRISCState *env,
+                                                  TranslationBlock *tb,
+                                                  int search_pc)
+{
+}
+
+void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
+{
+    gen_intermediate_code_internal(env, tb, 0);
+}
+
+void gen_intermediate_code_pc(CPUOpenRISCState *env,
+                              struct TranslationBlock *tb)
+{
+    gen_intermediate_code_internal(env, tb, 1);
+}
+
+void cpu_dump_state(CPUOpenRISCState *env, FILE *f,
+                    fprintf_function cpu_fprintf,
+                    int flags)
+{
+    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] 25+ messages in thread

* [Qemu-devel] [PATCH v6 02/16] target-or32: Add target machine
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 01/16] target-or32: Add target stubs and cpu support Jia Liu
@ 2012-06-21  2:57 ` Jia Liu
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 03/16] target-or32: Add MMU support Jia Liu
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:57 UTC (permalink / raw)
  To: qemu-devel

Add OpenRISC machine.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-openrisc/cpu.h     |   67 ++++++++++++++++++++++++++++++++++++++++++++-
 target-openrisc/machine.c |   22 ++++++++++++++-
 2 files changed, 87 insertions(+), 2 deletions(-)

diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 0b8e836..58c8081 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -48,6 +48,15 @@ struct CPUOpenRISCState;
 #define TARGET_PHYS_ADDR_SPACE_BITS 32
 #define TARGET_VIRT_ADDR_SPACE_BITS 32
 
+#define SET_FP_CAUSE(reg, v)    do {\
+                                    (reg) = ((reg) & ~(0x3f << 12)) | \
+                                            ((v & 0x3f) << 12);\
+                                } while (0)
+#define GET_FP_ENABLE(reg)       (((reg) >>  7) & 0x1f)
+#define UPDATE_FP_FLAGS(reg, v)   do {\
+                                      (reg) |= ((v & 0x1f) << 2);\
+                                  } while (0)
+
 /* Internal flags, delay slot flag */
 #define D_FLAG    1
 
@@ -121,6 +130,40 @@ enum {
     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,
@@ -155,6 +198,14 @@ enum {
     OPENRISC_FEATURE_OR1200,
 };
 
+/* Tick Timer Mode Register */
+enum {
+    TTMR_TP = (0xfffffff),
+    TTMR_IP = (1 << 28),
+    TTMR_IE = (1 << 29),
+    TTMR_M  = (3 << 30),
+};
+
 typedef struct CPUOpenRISCState CPUOpenRISCState;
 struct CPUOpenRISCState {
     target_ulong gpr[32];     /* General registers */
@@ -163,12 +214,25 @@ struct CPUOpenRISCState {
     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 */
@@ -269,7 +333,8 @@ static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
 {
     *pc = env->pc;
     *cs_base = 0;
-    *flags = 0;
+    /* D_FLAG -- branch instruction exception */
+    *flags = (env->flags & D_FLAG);
 }
 
 static inline int cpu_mmu_index(CPUOpenRISCState *env)
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
index 11bf275..e5d59a7 100644
--- a/target-openrisc/machine.c
+++ b/target-openrisc/machine.c
@@ -20,11 +20,31 @@
 #include "hw/hw.h"
 #include "hw/boards.h"
 
+static const VMStateDescription vmstate_cpu = {
+    .name = "cpu",
+    .version_id = CPU_SAVE_VERSION,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(gpr, CPUOpenRISCState, 32),
+        VMSTATE_UINT32(sr, CPUOpenRISCState),
+        VMSTATE_UINT32(epcr, CPUOpenRISCState),
+        VMSTATE_UINT32(eear, CPUOpenRISCState),
+        VMSTATE_UINT32(esr, CPUOpenRISCState),
+        VMSTATE_UINT32(fpcsr, CPUOpenRISCState),
+        VMSTATE_UINT32(pc, CPUOpenRISCState),
+        VMSTATE_UINT32(npc, CPUOpenRISCState),
+        VMSTATE_UINT32(ppc, CPUOpenRISCState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 void cpu_save(QEMUFile *f, void *opaque)
 {
+    vmstate_save_state(f, &vmstate_cpu, opaque);
 }
 
 int cpu_load(QEMUFile *f, void *opaque, int version_id)
 {
-    return 0;
+    return vmstate_load_state(f, &vmstate_cpu, opaque, version_id);
 }
-- 
1.7.9.5

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

* [Qemu-devel] [PATCH v6 03/16] target-or32: Add MMU support
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 01/16] target-or32: Add target stubs and cpu support Jia Liu
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 02/16] target-or32: Add target machine Jia Liu
@ 2012-06-21  2:57 ` Jia Liu
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 04/16] target-or32: Add interrupt support Jia Liu
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:57 UTC (permalink / raw)
  To: qemu-devel

Add OpenRISC MMU support.

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

diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 58c8081..dbb3f17 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -43,6 +43,12 @@ struct CPUOpenRISCState;
 
 #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
@@ -206,6 +212,54 @@ enum {
     TTMR_M  = (3 << 30),
 };
 
+/* 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 (*map_address_code)(struct CPUOpenRISCState *env,
+                            target_phys_addr_t *physical, int *prot,
+                            target_ulong address, int rw);
+    int (*map_address_data)(struct CPUOpenRISCState *env,
+                            target_phys_addr_t *physical, int *prot,
+                            target_ulong address, int rw);
+} CPUOpenRISCTLBContext;
+#endif
+
 typedef struct CPUOpenRISCState CPUOpenRISCState;
 struct CPUOpenRISCState {
     target_ulong gpr[32];     /* General registers */
@@ -240,6 +294,8 @@ 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 */
@@ -301,19 +357,33 @@ OpenRISCCPU *cpu_openrisc_init(const char *cpu_model);
 int cpu_openrisc_exec(CPUOpenRISCState *s);
 void do_interrupt(CPUOpenRISCState *env);
 void openrisc_translate_init(void);
+int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env, target_ulong address,
+                                  int rw, int mmu_idx);
 
 #define cpu_list cpu_openrisc_list
 #define cpu_exec cpu_openrisc_exec
 #define cpu_gen_code cpu_openrisc_gen_code
+#define cpu_handle_mmu_fault cpu_openrisc_handle_mmu_fault
 
 #define CPU_SAVE_VERSION 1
 
 #ifndef CONFIG_USER_ONLY
 void cpu_openrisc_pic_reset(CPUOpenRISCState *env);
+void cpu_openrisc_store_picsr(CPUOpenRISCState *env, uint32_t value);
+void cpu_openrisc_store_picmr(CPUOpenRISCState *env, uint32_t value);
 
 void cpu_openrisc_timer_reset(CPUOpenRISCState *env);
+void cpu_openrisc_store_count(CPUOpenRISCState *env, target_ulong count);
+void cpu_openrisc_store_compare(CPUOpenRISCState *env, target_ulong value);
+uint32_t cpu_openrisc_get_count(CPUOpenRISCState *env);
 
 void openrisc_mmu_init(CPUOpenRISCState *env);
+int get_phys_nommu(CPUOpenRISCState *env, target_phys_addr_t *physical,
+                   int *prot, target_ulong address, int rw);
+int get_phys_code(CPUOpenRISCState *env, target_phys_addr_t *physical,
+                  int *prot, target_ulong address, int rw);
+int get_phys_data(CPUOpenRISCState *env, target_phys_addr_t *physical,
+                  int *prot, target_ulong address, int rw);
 #endif
 
 static inline CPUOpenRISCState *cpu_init(const char *cpu_model)
@@ -339,7 +409,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 cd82b7a..ecef2e1 100644
--- a/target-openrisc/mmu.c
+++ b/target-openrisc/mmu.c
@@ -27,13 +27,210 @@
 #endif
 
 #ifndef CONFIG_USER_ONLY
+int get_phys_nommu(CPUOpenRISCState *env, target_phys_addr_t *physical,
+                   int *prot, target_ulong address, int rw)
+{
+    *physical = address;
+    *prot = PAGE_READ | PAGE_WRITE;
+    return TLBRET_MATCH;
+}
+
+int get_phys_code(CPUOpenRISCState *env, target_phys_addr_t *physical,
+                  int *prot, target_ulong address, int rw)
+{
+    int vpn = address >> TARGET_PAGE_BITS;
+    int idx = vpn & ITLB_MASK;
+    int right = 0;
+
+    if ((env->tlb->itlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) {
+        return TLBRET_NOMATCH;
+    }
+    if (!(env->tlb->itlb[0][idx].mr & 1)) {
+        return TLBRET_INVALID;
+    }
+
+    if (env->sr & SR_SM) { /* supervisor mode */
+        if (env->tlb->itlb[0][idx].tr & SXE) {
+            right |= PAGE_EXEC;
+        }
+    } else {
+        if (env->tlb->itlb[0][idx].tr & UXE) {
+            right |= PAGE_EXEC;
+        }
+    }
+
+    if ((rw & 2) && ((right & PAGE_EXEC) == 0)) {
+        return TLBRET_BADADDR;
+    }
+
+    *physical = (env->tlb->itlb[0][idx].tr & TARGET_PAGE_MASK) |
+                (address & (TARGET_PAGE_SIZE-1));
+    *prot = right;
+    return TLBRET_MATCH;
+}
+
+int get_phys_data(CPUOpenRISCState *env, target_phys_addr_t *physical,
+                  int *prot, target_ulong address, int rw)
+{
+    int vpn = address >> TARGET_PAGE_BITS;
+    int idx = vpn & DTLB_MASK;
+    int right = 0;
+
+    if ((env->tlb->dtlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) {
+        return TLBRET_NOMATCH;
+    }
+    if (!(env->tlb->dtlb[0][idx].mr & 1)) {
+        return TLBRET_INVALID;
+    }
+
+    if (env->sr & SR_SM) { /* supervisor mode */
+        if (env->tlb->dtlb[0][idx].tr & SRE) {
+            right |= PAGE_READ;
+        }
+        if (env->tlb->dtlb[0][idx].tr & SWE) {
+            right |= PAGE_WRITE;
+        }
+    } else {
+        if (env->tlb->dtlb[0][idx].tr & URE) {
+            right |= PAGE_READ;
+        }
+        if (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 = (env->tlb->dtlb[0][idx].tr & TARGET_PAGE_MASK) |
+                (address & (TARGET_PAGE_SIZE-1));
+    *prot = right;
+    return TLBRET_MATCH;
+}
+
+static int get_physical_address(CPUOpenRISCState *env,
+                                target_phys_addr_t *physical,
+                                int *prot, target_ulong address,
+                                int rw)
+{
+    int ret = TLBRET_MATCH;
+
+    /* [0x0000--0x2000]: unmapped */
+    if (address < 0x2000 && (env->sr & SR_SM)) {
+        *physical = address;
+        *prot = PAGE_READ | PAGE_WRITE;
+        return ret;
+    }
+
+    if (rw == 2) {    /* ITLB */
+       *physical = 0;
+        ret = env->tlb->map_address_code(env, physical,
+                                         prot, address, rw);
+    } else {          /* DTLB */
+        ret = env->tlb->map_address_data(env, physical,
+                                         prot, address, rw);
+    }
+
+    return ret;
+}
+#endif
+
+static void raise_mmu_exception(CPUOpenRISCState *env, target_ulong address,
+                                int rw, int tlb_error)
+{
+    int exception = 0;
+
+    switch (tlb_error) {
+    default:
+        if (rw == 2) {
+            exception = EXCP_IPF;
+        } else {
+            exception = EXCP_DPF;
+        }
+        break;
+#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
+    }
+
+    env->exception_index = exception;
+    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;
+
+    ret = get_physical_address(env, &physical, &prot,
+                               address, rw);
+
+    if (ret == TLBRET_MATCH) {
+        tlb_set_page(env, address & TARGET_PAGE_MASK,
+                     physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
+                     mmu_idx, TARGET_PAGE_SIZE);
+        ret = 0;
+    } else if (ret < 0) {
+        raise_mmu_exception(env, address, rw, ret);
+        ret = 1;
+    }
+
+    return ret;
+}
+#else
+int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env,
+                                  target_ulong address, int rw, int mmu_idx)
+{
+    int ret = 0;
+
+    raise_mmu_exception(env, address, rw, ret);
+    ret = 1;
+
+    return ret;
+}
+#endif
+
+#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;
+
+    if (get_physical_address(env, &phys_addr, &prot, addr, 0)) {
+        return -1;
+    }
+
+    return phys_addr;
 }
 
 void openrisc_mmu_init(CPUOpenRISCState *env)
 {
+    env->tlb = g_malloc0(sizeof(CPUOpenRISCTLBContext));
+
+    env->tlb->map_address_code = &get_phys_nommu;
+    env->tlb->map_address_data = &get_phys_nommu;
 }
 #endif
diff --git a/target-openrisc/mmu_helper.c b/target-openrisc/mmu_helper.c
index f526ba8..29387e3 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] 25+ messages in thread

* [Qemu-devel] [PATCH v6 04/16] target-or32: Add interrupt support
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
                   ` (2 preceding siblings ...)
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 03/16] target-or32: Add MMU support Jia Liu
@ 2012-06-21  2:57 ` Jia Liu
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 05/16] target-or32: Add exception support Jia Liu
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:57 UTC (permalink / raw)
  To: qemu-devel

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           |    9 ++++++-
 target-openrisc/helper.h        |   25 +++++++++++++++++++
 target-openrisc/intrpt.c        |   44 +++++++++++++++++++++++++++++++++
 target-openrisc/intrpt_helper.c |   52 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 147 insertions(+), 2 deletions(-)
 create mode 100644 target-openrisc/helper.h
 create mode 100644 target-openrisc/intrpt_helper.c

diff --git a/cpu-exec.c b/cpu-exec.c
index 7d0d87b..1d2fe6b 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -378,6 +378,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 21b76b2..65f9391 100644
--- a/target-openrisc/Makefile.objs
+++ b/target-openrisc/Makefile.objs
@@ -1,3 +1,3 @@
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-y += cpu.o intrpt.o mmu.o translate.o
-obj-y += mmu_helper.o
+obj-y += intrpt_helper.o mmu_helper.o
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index dbb3f17..d499dc4 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -66,6 +66,10 @@ enum {
 /* Internal flags, delay slot flag */
 #define D_FLAG    1
 
+/* Interrupt */
+#define NR_IRQS  32
+#define PIC_MASK 0xFFFFFFFF
+
 /* Verison Register */
 #define SPR_VR       0xFFFF003F
 
@@ -304,6 +308,7 @@ struct CPUOpenRISCState {
     uint32_t picsr;         /* Interrupt contrl register*/
 #endif
     uint32_t feature;       /* CPU Capabilities */
+    void *irq[32];          /* Interrupt irq input */
 };
 
 #define TYPE_OPENRISC_CPU "or32-cpu"
@@ -415,9 +420,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/intrpt.c b/target-openrisc/intrpt.c
index a3bb7f8..9b02618 100644
--- a/target-openrisc/intrpt.c
+++ b/target-openrisc/intrpt.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->map_address_data = &get_phys_nommu;
+    env->tlb->map_address_code = &get_phys_nommu;
+
+    if (env->exception_index > 0 && env->exception_index < EXCP_NR) {
+        env->pc = (env->exception_index << 8);
+    } else {
+        cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
+    }
+#endif
+
+    env->exception_index = -1;
 }
diff --git a/target-openrisc/intrpt_helper.c b/target-openrisc/intrpt_helper.c
new file mode 100644
index 0000000..fca0202
--- /dev/null
+++ b/target-openrisc/intrpt_helper.c
@@ -0,0 +1,52 @@
+/*
+ *  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)
+{
+#ifndef CONFIG_USER_ONLY
+    int need_flush_tlb = (env->sr & (SR_SM | SR_IME | SR_DME)) ^
+                         (env->esr & (SR_SM | SR_IME | SR_DME));
+#endif
+    env->pc = env->epcr;
+    env->npc = env->epcr;
+    env->sr = env->esr;
+
+#ifndef CONFIG_USER_ONLY
+    if (env->sr & SR_DME) {
+        env->tlb->map_address_data = &get_phys_data;
+    } else {
+        env->tlb->map_address_data = &get_phys_nommu;
+    }
+
+    if (env->sr & SR_IME) {
+        env->tlb->map_address_code = &get_phys_code;
+    } else {
+        env->tlb->map_address_code = &get_phys_nommu;
+    }
+
+    if (need_flush_tlb) {
+        tlb_flush(env, 1);
+    }
+#endif
+    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+}
-- 
1.7.9.5

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

* [Qemu-devel] [PATCH v6 05/16] target-or32: Add exception support
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
                   ` (3 preceding siblings ...)
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 04/16] target-or32: Add interrupt support Jia Liu
@ 2012-06-21  2:57 ` Jia Liu
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 06/16] target-or32: Add int instruction helpers Jia Liu
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:57 UTC (permalink / raw)
  To: qemu-devel

Add OpenRISC exception support.

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

diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
index 65f9391..382190a 100644
--- a/target-openrisc/Makefile.objs
+++ b/target-openrisc/Makefile.objs
@@ -1,3 +1,3 @@
 obj-$(CONFIG_SOFTMMU) += machine.o
-obj-y += cpu.o intrpt.o mmu.o translate.o
-obj-y += intrpt_helper.o mmu_helper.o
+obj-y += cpu.o excp.o intrpt.o mmu.o translate.o
+obj-y += excp_helper.o intrpt_helper.o mmu_helper.o
diff --git a/target-openrisc/excp.c b/target-openrisc/excp.c
new file mode 100644
index 0000000..6d8c5dd
--- /dev/null
+++ b/target-openrisc/excp.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 "excp.h"
+
+void QEMU_NORETURN raise_exception(CPUOpenRISCState *env, uint32_t excp)
+{
+    env->exception_index = excp;
+    cpu_loop_exit(env);
+}
diff --git a/target-openrisc/excp.h b/target-openrisc/excp.h
new file mode 100644
index 0000000..885203b
--- /dev/null
+++ b/target-openrisc/excp.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(CPUOpenRISCState *env, uint32_t excp);
+
+#endif /* QEMU_OPENRISC_EXCP_H */
diff --git a/target-openrisc/excp_helper.c b/target-openrisc/excp_helper.c
new file mode 100644
index 0000000..c7d4110
--- /dev/null
+++ b/target-openrisc/excp_helper.c
@@ -0,0 +1,27 @@
+/*
+ *  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 "excp.h"
+
+void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp)
+{
+    raise_exception(env, excp);
+}
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index 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] 25+ messages in thread

* [Qemu-devel] [PATCH v6 06/16] target-or32: Add int instruction helpers
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
                   ` (4 preceding siblings ...)
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 05/16] target-or32: Add exception support Jia Liu
@ 2012-06-21  2:57 ` Jia Liu
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 07/16] target-or32: Add float " Jia Liu
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:57 UTC (permalink / raw)
  To: qemu-devel

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  |   85 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 91 insertions(+), 1 deletion(-)
 create mode 100644 target-openrisc/int_helper.c

diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
index 382190a..4286462 100644
--- a/target-openrisc/Makefile.objs
+++ b/target-openrisc/Makefile.objs
@@ -1,3 +1,3 @@
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-y += cpu.o excp.o intrpt.o mmu.o translate.o
-obj-y += excp_helper.o intrpt_helper.o mmu_helper.o
+obj-y += excp_helper.o int_helper.o intrpt_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..09cd70a
--- /dev/null
+++ b/target-openrisc/int_helper.c
@@ -0,0 +1,85 @@
+/*
+ *  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 "excp.h"
+
+target_ulong HELPER(ff1)(target_ulong x)
+{
+    target_ulong n = 0;
+
+    if (x == 0) {
+        return 0;
+    }
+
+    for (n = 32; x; n--) {
+        x <<= 1;
+    }
+    return n+1;
+}
+
+target_ulong HELPER(fl1)(target_ulong x)
+{
+    target_ulong n = 0;
+
+    if (x == 0) {
+        return 0;
+    }
+
+    for (n = 0; x; n++) {
+        x >>= 1;
+    }
+    return n;
+}
+
+target_ulong HELPER(mul32)(CPUOpenRISCState *env,
+                           target_ulong ra, target_ulong rb)
+{
+    uint64_t result;
+    target_ulong high, cy;
+
+    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;
+        }
+    }
+
+    env->sr |= (SR_OV | SR_CY);
+    if (env->sr & SR_OVE) {
+        raise_exception(env, EXCP_RANGE);
+    }
+
+    return result;
+}
-- 
1.7.9.5

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

* [Qemu-devel] [PATCH v6 07/16] target-or32: Add float instruction helpers
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
                   ` (5 preceding siblings ...)
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 06/16] target-or32: Add int instruction helpers Jia Liu
@ 2012-06-21  2:57 ` Jia Liu
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 08/16] target-or32: Add instruction tanslation Jia Liu
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:57 UTC (permalink / raw)
  To: qemu-devel

Add OpenRISC float instruction helpers.

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

diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
index 4286462..0d72c33 100644
--- a/target-openrisc/Makefile.objs
+++ b/target-openrisc/Makefile.objs
@@ -1,3 +1,3 @@
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-y += cpu.o excp.o intrpt.o mmu.o translate.o
-obj-y += excp_helper.o int_helper.o intrpt_helper.o mmu_helper.o
+obj-y += excp_helper.o fpu_helper.o int_helper.o intrpt_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..40f5857
--- /dev/null
+++ b/target-openrisc/fpu_helper.c
@@ -0,0 +1,275 @@
+/*
+ *  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 "excp.h"
+
+static inline uint32_t ieee_ex_to_openrisc(CPUOpenRISCState *env, int fexcp)
+{
+    int ret = 0;
+    if (fexcp) {
+        if (fexcp & float_flag_invalid) {
+            env->fpcsr |= FPCSR_IVF;
+            ret = 1;
+        }
+        if (fexcp & float_flag_overflow) {
+            env->fpcsr |= FPCSR_OVF;
+            ret = 1;
+        }
+        if (fexcp & float_flag_underflow) {
+            env->fpcsr |= FPCSR_UNF;
+            ret = 1;
+        }
+        if (fexcp & float_flag_divbyzero) {
+            env->fpcsr |= FPCSR_DZF;
+            ret = 1;
+        }
+        if (fexcp & float_flag_inexact) {
+            env->fpcsr |= FPCSR_IXF;
+            ret = 1;
+        }
+    }
+
+    return ret;
+}
+
+static inline void update_fpcsr(CPUOpenRISCState *env)
+{
+    int tmp = ieee_ex_to_openrisc(env,
+                                  get_float_exception_flags(&env->fp_status));
+
+    SET_FP_CAUSE(env->fpcsr, tmp);
+    if ((GET_FP_ENABLE(env->fpcsr) & tmp) && (env->fpcsr & FPCSR_FPEE)) {
+        helper_exception(env, EXCP_FPE);
+    } else {
+        UPDATE_FP_FLAGS(env->fpcsr, tmp);
+    }
+}
+
+uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val)
+{
+    uint64_t itofd;
+    set_float_exception_flags(0, &env->fp_status);
+    itofd = int32_to_float64(val, &env->fp_status);
+    update_fpcsr(env);
+    return itofd;
+}
+
+uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val)
+{
+    uint32_t itofs;
+    set_float_exception_flags(0, &env->fp_status);
+    itofs = int32_to_float32(val, &env->fp_status);
+    update_fpcsr(env);
+    return itofs;
+}
+
+uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val)
+{
+    uint64_t ftoid;
+    set_float_exception_flags(0, &env->fp_status);
+    ftoid = float32_to_int64(val, &env->fp_status);
+    update_fpcsr(env);
+    return ftoid;
+}
+
+uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val)
+{
+    uint32_t ftois;
+    set_float_exception_flags(0, &env->fp_status);
+    ftois = float32_to_int32(val, &env->fp_status);
+    update_fpcsr(env);
+    return ftois;
+}
+
+#define FLOAT_OP(name, p) void helper_float_##_##p(void)
+
+#define FLOAT_CALC(name)                                                  \
+uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
+                                     uint64_t fdt0, uint64_t fdt1)        \
+{                                                                         \
+    uint64_t result;                                                      \
+    set_float_exception_flags(0, &env->fp_status);                        \
+    result = float64_ ## name(fdt0, fdt1, &env->fp_status);               \
+    update_fpcsr(env);                                                    \
+    return result;                                                        \
+}                                                                         \
+                                                                          \
+uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
+                                     uint32_t fdt0, uint32_t fdt1)        \
+{                                                                         \
+    uint32_t result;                                                      \
+    set_float_exception_flags(0, &env->fp_status);                        \
+    result = float32_ ## name(fdt0, fdt1, &env->fp_status);               \
+    update_fpcsr(env);                                                    \
+    return result;                                                        \
+}                                                                         \
+
+FLOAT_CALC(add)
+FLOAT_CALC(sub)
+FLOAT_CALC(mul)
+FLOAT_CALC(div)
+FLOAT_CALC(rem)
+#undef FLOAT_CALC
+
+#define FLOAT_TERNOP(name1, name2)                                        \
+uint64_t helper_float_ ## name1 ## name2 ## _d(CPUOpenRISCState *env,     \
+                                               uint64_t fdt0,             \
+                                               uint64_t fdt1)             \
+{                                                                         \
+    uint64_t result, temp, hi, lo;                                        \
+    uint32_t val1, val2;                                                  \
+    hi = env->fpmaddhi;                                                   \
+    lo = env->fpmaddlo;                                                   \
+    set_float_exception_flags(0, &env->fp_status);                        \
+    result = float64_ ## name1(fdt0, fdt1, &env->fp_status);              \
+    lo &= 0xffffffff;                                                     \
+    hi &= 0xffffffff;                                                     \
+    temp = (hi << 32) | lo;                                               \
+    result = float64_ ## name2(result, temp, &env->fp_status);            \
+    val1 = result >> 32;                                                  \
+    val2 = (uint32_t) (result & 0xffffffff);                              \
+    update_fpcsr(env);                                                    \
+    env->fpmaddlo = val2;                                                 \
+    env->fpmaddhi = val1;                                                 \
+    return 0;                                                             \
+}                                                                         \
+                                                                          \
+uint32_t helper_float_ ## name1 ## name2 ## _s(CPUOpenRISCState *env,     \
+                                            uint32_t fdt0, uint32_t fdt1) \
+{                                                                         \
+    uint64_t result, temp, hi, lo;                                        \
+    uint32_t val1, val2;                                                  \
+    hi = env->fpmaddhi;                                                   \
+    lo = env->fpmaddlo;                                                   \
+    set_float_exception_flags(0, &env->fp_status);                        \
+    result = float64_ ## name1(fdt0, fdt1, &env->fp_status);              \
+    temp = (hi << 32) | lo;                                               \
+    result = float64_ ## name2(result, temp, &env->fp_status);            \
+    val1 = result >> 32;                                                  \
+    val2 = (uint32_t) (result & 0xffffffff);                              \
+    update_fpcsr(env);                                                    \
+    env->fpmaddlo = val2;                                                 \
+    env->fpmaddhi = val1;                                                 \
+    return 0;                                                             \
+}
+
+FLOAT_TERNOP(mul, add)
+#undef FLOAT_TERNOP
+
+
+#define FLOAT_CMP(name)                                                   \
+uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
+                                     uint64_t fdt0, uint64_t fdt1)        \
+{                                                                         \
+   int res;                                                               \
+   set_float_exception_flags(0, &env->fp_status);                         \
+   res = float64_ ## name(fdt0, fdt1, &env->fp_status);                   \
+   update_fpcsr(env);                                                     \
+   return res;                                                            \
+}                                                                         \
+                                                                          \
+uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
+                                             uint32_t fdt0, uint32_t fdt1)\
+{                                                                         \
+    int res;                                                              \
+    set_float_exception_flags(0, &env->fp_status);                        \
+    res = float32_ ## name(fdt0, fdt1, &env->fp_status);                  \
+    update_fpcsr(env);                                                    \
+    return res;                                                           \
+}
+
+FLOAT_CMP(le)
+FLOAT_CMP(eq)
+FLOAT_CMP(lt)
+#undef FLOAT_CMP
+
+
+#define FLOAT_CMPNE(name)                                                 \
+uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
+                                     uint64_t fdt0, uint64_t fdt1)        \
+{                                                                         \
+   int res;                                                               \
+   set_float_exception_flags(0, &env->fp_status);                         \
+   res = !float64_eq_quiet(fdt0, fdt1, &env->fp_status);                  \
+   update_fpcsr(env);                                                     \
+   return res;                                                            \
+}                                                                         \
+                                                                          \
+uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
+                                     uint32_t fdt0, uint32_t fdt1)        \
+{                                                                         \
+    int res;                                                              \
+    set_float_exception_flags(0, &env->fp_status);                        \
+    res = !float32_eq_quiet(fdt0, fdt1, &env->fp_status);                 \
+    update_fpcsr(env);                                                    \
+    return res;                                                           \
+}
+
+FLOAT_CMPNE(ne)
+#undef FLOAT_CMPNE
+
+#define FLOAT_CMPGT(name)                                                 \
+uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
+                                     uint64_t fdt0, uint64_t fdt1)        \
+{                                                                         \
+   int res;                                                               \
+   set_float_exception_flags(0, &env->fp_status);                         \
+   res = !float64_le(fdt0, fdt1, &env->fp_status);                        \
+   update_fpcsr(env);                                                     \
+   return res;                                                            \
+}                                                                         \
+                                                                          \
+uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
+                                     uint32_t fdt0, uint32_t fdt1)        \
+{                                                                         \
+    int res;                                                              \
+    set_float_exception_flags(0, &env->fp_status);                        \
+    res = !float32_le(fdt0, fdt1, &env->fp_status);                       \
+    update_fpcsr(env);                                                    \
+    return res;                                                           \
+}
+FLOAT_CMPGT(gt)
+#undef FLOAT_CMPGT
+
+#define FLOAT_CMPGE(name)                                                 \
+uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
+                                     uint64_t fdt0, uint64_t fdt1)        \
+{                                                                         \
+   int res;                                                               \
+   set_float_exception_flags(0, &env->fp_status);                         \
+   res = !float64_lt(fdt0, fdt1, &env->fp_status);                        \
+   update_fpcsr(env);                                                     \
+   return res;                                                            \
+}                                                                         \
+                                                                          \
+uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
+                                     uint32_t fdt0, uint32_t fdt1)        \
+{                                                                         \
+    int res;                                                              \
+    set_float_exception_flags(0, &env->fp_status);                        \
+    res = !float32_lt(fdt0, fdt1, &env->fp_status);                       \
+    update_fpcsr(env);                                                    \
+    return res;                                                           \
+}
+
+FLOAT_CMPGE(ge)
+#undef FLOAT_CMPGE
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index 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] 25+ messages in thread

* [Qemu-devel] [PATCH v6 08/16] target-or32: Add instruction tanslation
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
                   ` (6 preceding siblings ...)
  2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 07/16] target-or32: Add float " Jia Liu
@ 2012-06-21  2:58 ` Jia Liu
  2012-06-21 10:24   ` Max Filippov
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 09/16] target-or32: Add PIC support Jia Liu
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:58 UTC (permalink / raw)
  To: qemu-devel

Add OpenRISC instruction tanslation routines.

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

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 1d87d76..300236f 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,1686 @@
 #  define LOG_DIS(...) do { } while (0)
 #endif
 
+typedef struct DisasContext {
+    CPUOpenRISCState *env;
+    TranslationBlock *tb;
+    target_ulong pc, ppc, npc;
+    uint32_t tb_flags, synced_flags, 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;
+}
+
+#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);
+    }
+}
+
+/* not used yet, open it when we need or64.  */
+/*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, CPUOpenRISCState *env, uint32_t insn)
+{
+    uint32_t op0, op1, op2;
+    uint32_t ra, rb, rd;
+    op0 = field(insn, 0, 4);
+    op1 = field(insn, 8, 2);
+    op2 = field(insn, 6, 2);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+    rd = field(insn, 21, 5);
+
+    switch (op0) {
+    case 0x0000:
+        switch (op1) {
+        case 0x00:     /*l.add*/
+            LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb);
+            {
+                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();
+                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_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0);
+                    tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
+                    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],
+                                       0xffffffff, lab2);
+                    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb],
+                                       0x80000000, 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, lab2);
+                    gen_exception(dc, EXCP_RANGE);
+                    gen_set_label(lab2);
+                    tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                }
+                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();
+                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, lab1);
+                    gen_exception(dc, EXCP_RANGE);
+                    gen_set_label(lab1);
+                    tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+                }
+                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_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, CPUOpenRISCState *env, uint32_t insn)
+{
+    uint32_t op0, op1;
+    uint32_t ra, rb, rd;
+    uint32_t /*L6, K5, */I16, I5, I11, N26, tmp;
+    op0 = field(insn, 26, 6);
+    op1 = field(insn, 24, 2);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+    rd = field(insn, 21, 5);
+    /*L6 = field(insn, 5, 6);
+    K5 = field(insn, 0, 5);*/
+    I16 = field(insn, 0, 16);
+    I5 = field(insn, 21, 5);
+    I11 = field(insn, 0, 11);
+    N26 = field(insn, 0, 26);
+    tmp = (I5<<11) + I11;
+
+    switch (op0) {
+    case 0x00:   /*l.j*/
+        LOG_DIS("l.j %d\n", N26);
+    case 0x01:   /*l.jal*/
+        LOG_DIS("l.jal %d\n", N26);
+    case 0x03:   /*l.bnf*/
+        LOG_DIS("l.bnf %d\n", N26);
+    case 0x04:   /*l.bf*/
+        LOG_DIS("l.bf %d\n", N26);
+
+        gen_jump(dc, N26, 0, op0);
+        break;
+
+    case 0x05:
+        switch (op1) {
+        case 0x01:   /*l.nop*/
+            LOG_DIS("l.nop %d\n", I16);
+            break;
+
+        default:
+            gen_illegal_exception(dc);
+            break;
+        }
+        break;
+
+    case 0x11:    /*l.jr*/
+        LOG_DIS("l.jr r%d\n", rb);
+    case 0x12:    /*l.jalr*/
+        LOG_DIS("l.jalr r%d\n", rb);
+
+        gen_jump(dc, 0, rb, op0);
+        break;
+
+    case 0x13:    /*l.maci*/
+        LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I11);
+        {
+            TCGv_i64 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;
+
+    case 0x20:   /*l.ld*/
+        LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16);
+        {
+#ifdef TARGET_OPENRISC64
+            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);
+#endif
+        }
+        break;
+
+    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;
+
+    case 0x34:   /*l.sd*/
+        LOG_DIS("l.sd %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        {
+#ifdef TARGET_OPENRISC64
+            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);
+#endif
+        }
+        break;
+
+    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, CPUOpenRISCState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t ra, rb;
+    op0 = field(insn, 0, 4);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+
+    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, CPUOpenRISCState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t rd, ra, L6;
+    op0 = field(insn, 6, 2);
+    rd = field(insn, 21, 5);
+    ra = field(insn, 16, 5);
+    L6 = field(insn, 0, 6);
+
+    switch (op0) {
+    case 0x00:    /*l.slli*/
+        LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6);
+        tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+        break;
+
+    case 0x01:    /*l.srli*/
+        LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6);
+        tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+        break;
+
+    case 0x02:    /*l.srai*/
+        LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6);
+        tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f)); break;
+
+    case 0x03:    /*l.rori*/
+        LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6);
+        tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+        break;
+
+    default:
+        gen_illegal_exception(dc);
+        break;
+    }
+}
+
+static void dec_M(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t rd;
+    uint32_t K16;
+    op0 = field(insn, 16, 1);
+    rd = field(insn, 21, 5);
+    K16 = field(insn, 0, 16);
+
+    switch (op0) {
+    case 0x0:    /*l.movhi*/
+        LOG_DIS("l.movhi  r%d, %d\n", rd, K16);
+        tcg_gen_movi_tl(cpu_R[rd], (K16 << 16));
+        break;
+
+    case 0x1:    /*l.macrc*/
+        LOG_DIS("l.macrc  r%d\n", rd);
+        tcg_gen_mov_tl(cpu_R[rd], maclo);
+        tcg_gen_movi_tl(maclo, 0x0);
+        tcg_gen_movi_tl(machi, 0x0);
+        break;
+
+    default:
+        gen_illegal_exception(dc);
+        break;
+    }
+}
+
+static void dec_comp(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t ra, rb;
+
+    op0 = field(insn, 21, 5);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+
+    tcg_gen_movi_i32(env_btaken, 0x0);
+    /* unsigned integers  */
+    tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
+    tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
+
+    switch (op0) {
+    case 0x0:    /*l.sfeq*/
+        LOG_DIS("l.sfeq  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x1:    /*l.sfne*/
+        LOG_DIS("l.sfne  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x2:    /*l.sfgtu*/
+        LOG_DIS("l.sfgtu  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GTU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x3:    /*l.sfgeu*/
+        LOG_DIS("l.sfgeu  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GEU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x4:    /*l.sfltu*/
+        LOG_DIS("l.sfltu  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LTU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x5:    /*l.sfleu*/
+        LOG_DIS("l.sfleu  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0xa:    /*l.sfgts*/
+        LOG_DIS("l.sfgts  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0xb:    /*l.sfges*/
+        LOG_DIS("l.sfges  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0xc:    /*l.sflts*/
+        LOG_DIS("l.sflts  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0xd:    /*l.sfles*/
+        LOG_DIS("l.sfles  r%d, r%d\n", ra, rb);
+        tcg_gen_setcond_tl(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    default:
+        gen_illegal_exception(dc);
+        break;
+    }
+    wb_SR_F();
+}
+
+static void dec_compi(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t ra, I16;
+
+    op0 = field(insn, 21, 5);
+    ra = field(insn, 16, 5);
+    I16 = field(insn, 0, 16);
+
+    tcg_gen_movi_i32(env_btaken, 0x0);
+    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, CPUOpenRISCState *env, uint32_t insn)
+{
+    uint32_t op0;
+    /*uint32_t K16;*/
+    op0 = field(insn, 16, 8);
+    /*K16 = field(insn, 0, 16);*/
+
+    switch (op0) {
+    case 0x000:  /*l.sys*/
+        /*LOG_DIS("l.sys %d\n", K16);*/
+        tcg_gen_movi_tl(cpu_pc, dc->pc);
+        gen_exception(dc, EXCP_SYSCALL);
+        dc->is_jmp = DISAS_UPDATE;
+        break;
+
+    case 0x100:  /*l.trap*/
+        /*LOG_DIS("l.trap %d\n", K16);*/
+        tcg_gen_movi_tl(cpu_pc, dc->pc);
+        gen_exception(dc, EXCP_TRAP);
+        break;
+
+    case 0x300:  /*l.csync*/
+        LOG_DIS("l.csync\n");
+        break;
+
+    case 0x200:  /*l.msync*/
+        LOG_DIS("l.msync\n");
+        break;
+
+    case 0x270:  /*l.psync*/
+        LOG_DIS("l.psync\n");
+        break;
+
+    default:
+        gen_illegal_exception(dc);
+        break;
+    }
+}
+
+static void dec_float(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn)
+{
+    uint32_t op0;
+    uint32_t ra, rb, rd;
+    op0 = field(insn, 0, 8);
+    ra = field(insn, 16, 5);
+    rb = field(insn, 11, 5);
+    rd = field(insn, 21, 5);
+
+    switch (op0) {
+    case 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;
+
+#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, CPUOpenRISCState *env)
+{
+    uint32_t op0;
+    uint32_t insn;
+    insn = cpu_ldl_code(env, dc->pc);
+    op0 = field(insn, 26, 6);
+
+    switch (op0) {
+    case 0x06:
+        dec_M(dc, env, insn);
+        break;
+
+    case 0x08:
+        dec_sys(dc, env, insn);
+        break;
+
+    case 0x2e:
+        dec_logic(dc, env, insn);
+        break;
+
+    case 0x2f:
+        dec_compi(dc, env, insn);
+        break;
+
+    case 0x31:
+        dec_mac(dc, env, insn);
+        break;
+
+    case 0x32:
+        dec_float(dc, env, insn);
+        break;
+
+    case 0x38:
+        dec_calc(dc, env, insn);
+        break;
+
+    case 0x39:
+        dec_comp(dc, env, insn);
+        break;
+
+    default:
+        dec_misc(dc, env, insn);
+        break;
+    }
+}
+
+static void check_breakpoint(CPUOpenRISCState *env, DisasContext *dc)
+{
+    CPUBreakpoint *bp;
+
+    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
+        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+            if (bp->pc == dc->pc) {
+                tcg_gen_movi_tl(cpu_pc, dc->pc);
+                gen_exception(dc, EXCP_DEBUG);
+                dc->is_jmp = DISAS_UPDATE;
+            }
+        }
+    }
 }
 
 static inline void gen_intermediate_code_internal(CPUOpenRISCState *env,
                                                   TranslationBlock *tb,
                                                   int search_pc)
 {
+    struct DisasContext ctx, *dc = &ctx;
+    uint16_t *gen_opc_end;
+    uint32_t pc_start;
+    int j, k;
+    uint32_t next_page_start;
+    int num_insns;
+    int max_insns;
+
+    qemu_log_try_set_file(stderr);
+
+    pc_start = tb->pc;
+    dc->env = env;
+    dc->tb = tb;
+
+    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    dc->is_jmp = DISAS_NEXT;
+    dc->ppc = pc_start;
+    dc->pc = pc_start;
+    dc->flags = env->cpucfgr;
+    dc->mem_idx = cpu_mmu_index(env);
+    dc->synced_flags = dc->tb_flags = tb->flags;
+    dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
+    dc->singlestep_enabled = env->singlestep_enabled;
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+        qemu_log("-----------------------------------------\n");
+        log_cpu_state(env, 0);
+    }
+
+    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+    k = -1;
+    num_insns = 0;
+    max_insns = tb->cflags & CF_COUNT_MASK;
+
+    if (max_insns == 0) {
+        max_insns = CF_COUNT_MASK;
+    }
+
+    gen_icount_start();
+
+    do {
+        check_breakpoint(env, dc);
+        if (search_pc) {
+            j = gen_opc_ptr - gen_opc_buf;
+            if (k < j) {
+                k++;
+                while (k < j) {
+                    gen_opc_instr_start[k++] = 0;
+                }
+            }
+            gen_opc_pc[k] = dc->pc;
+            gen_opc_instr_start[k] = 1;
+            gen_opc_icount[k] = num_insns;
+        }
+
+        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
+            tcg_gen_debug_insn_start(dc->pc);
+        }
+
+        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+            gen_io_start();
+        }
+        dc->ppc = dc->pc - 4;
+        dc->npc = dc->pc + 4;
+        tcg_gen_movi_tl(cpu_ppc, dc->ppc);
+        tcg_gen_movi_tl(cpu_npc, dc->npc);
+        disas_openrisc_insn(dc, env);
+        dc->pc = dc->npc;
+        num_insns++;
+        /* delay slot */
+        if (dc->delayed_branch) {
+            dc->delayed_branch--;
+            if (!dc->delayed_branch) {
+                dc->tb_flags &= ~D_FLAG;
+                gen_sync_flags(dc);
+                tcg_gen_mov_tl(cpu_pc, jmp_pc);
+                tcg_gen_mov_tl(cpu_npc, jmp_pc);
+                tcg_gen_movi_tl(jmp_pc, 0);
+                tcg_gen_exit_tb(0);
+                dc->is_jmp = DISAS_JUMP;
+                break;
+            }
+        }
+    } while (!dc->is_jmp
+             && gen_opc_ptr < gen_opc_end
+             && !env->singlestep_enabled
+             && !singlestep
+             && (dc->pc < next_page_start)
+             && num_insns < max_insns);
+
+    if (tb->cflags & CF_LAST_IO) {
+        gen_io_end();
+    }
+    if (dc->is_jmp == DISAS_NEXT) {
+        dc->is_jmp = DISAS_UPDATE;
+        tcg_gen_movi_tl(cpu_pc, dc->pc);
+    }
+    if (unlikely(env->singlestep_enabled)) {
+        if (dc->is_jmp == DISAS_NEXT) {
+            tcg_gen_movi_tl(cpu_pc, dc->pc);
+        }
+        gen_exception(dc, EXCP_DEBUG);
+    } else {
+        switch (dc->is_jmp) {
+        case DISAS_NEXT:
+            gen_goto_tb(dc, 0, dc->pc);
+            break;
+        default:
+        case DISAS_JUMP:
+            break;
+        case DISAS_UPDATE:
+            /* indicate that the hash table must be used
+               to find the next TB */
+            tcg_gen_exit_tb(0);
+            break;
+        case DISAS_TB_JUMP:
+            /* nothing more to generate */
+            break;
+        }
+    }
+
+    gen_icount_end(tb, num_insns);
+    *gen_opc_ptr = INDEX_op_end;
+    if (search_pc) {
+        j = gen_opc_ptr - gen_opc_buf;
+        k++;
+        while (k <= j) {
+            gen_opc_instr_start[k++] = 0;
+        }
+    } else {
+        tb->size = dc->pc - pc_start;
+        tb->icount = num_insns;
+    }
+
+#ifdef DEBUG_DISAS
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+        qemu_log("\n");
+        log_target_disas(pc_start, dc->pc - pc_start, 0);
+        qemu_log("\nisize=%d osize=%td\n",
+            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
+    }
+#endif
 }
 
 void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
-- 
1.7.9.5

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

* [Qemu-devel] [PATCH v6 09/16] target-or32: Add PIC support
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
                   ` (7 preceding siblings ...)
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 08/16] target-or32: Add instruction tanslation Jia Liu
@ 2012-06-21  2:58 ` Jia Liu
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 10/16] target-or32: Add timer support Jia Liu
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:58 UTC (permalink / raw)
  To: qemu-devel

Add OpenRISC Programmable Interrupt Controller support.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 hw/openrisc_pic.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
index 0d14bbe..76bd792 100644
--- a/hw/openrisc_pic.c
+++ b/hw/openrisc_pic.c
@@ -28,3 +28,51 @@ void cpu_openrisc_pic_reset(CPUOpenRISCState *env)
     env->picmr = 0x00000000;
     env->picsr = 0x00000000;
 }
+
+/* OpenRISC pic handler */
+static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
+{
+    CPUOpenRISCState *env = (CPUOpenRISCState *)opaque;
+    int i;
+    uint32_t irq_bit = 1 << irq;
+
+    if (irq > 31 || irq < 0) {
+        return;
+    }
+
+    if (level) {
+        env->picsr |= irq_bit;
+    } else {
+        env->picsr &= ~irq_bit;
+    }
+
+    for (i = 0; i < 32; i++) {
+        if ((env->picsr && (1 << i)) && (env->picmr && (1 << i))) {
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        } else {
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+            env->picsr &= ~(1 << i);
+        }
+    }
+}
+
+void cpu_openrisc_pic_init(CPUOpenRISCState *env)
+{
+    int i;
+    qemu_irq *qi;
+    qi = qemu_allocate_irqs(openrisc_pic_cpu_handler, env, NR_IRQS);
+
+    for (i = 0; i < NR_IRQS; i++) {
+        env->irq[i] = qi[i];
+    }
+}
+
+void cpu_openrisc_store_picmr(CPUOpenRISCState *env, uint32_t value)
+{
+    env->picmr |= value;
+}
+
+void cpu_openrisc_store_picsr(CPUOpenRISCState *env, uint32_t value)
+{
+    env->picsr &= ~value;
+}
-- 
1.7.9.5

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

* [Qemu-devel] [PATCH v6 10/16] target-or32: Add timer support
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
                   ` (8 preceding siblings ...)
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 09/16] target-or32: Add PIC support Jia Liu
@ 2012-06-21  2:58 ` Jia Liu
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 11/16] target-or32: Add a IIS dummy board Jia Liu
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:58 UTC (permalink / raw)
  To: qemu-devel

Add OpenRISC timer support.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 hw/openrisc_timer.c |  130 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 130 insertions(+)

diff --git a/hw/openrisc_timer.c b/hw/openrisc_timer.c
index df384f6..25cde1a 100644
--- a/hw/openrisc_timer.c
+++ b/hw/openrisc_timer.c
@@ -22,9 +22,139 @@
 #include "openrisc_cpudev.h"
 #include "qemu-timer.h"
 
+#define TIMER_FREQ    (20 * 1000 * 1000)    /* 20MHz */
+
+/* The time when TTCR changes */
+static uint64_t last_clk;
+static int is_counting;
+
+/* Timer Mode */
+enum {
+    TIMER_NONE = (0 << 30),
+    TIMER_INTR = (1 << 30),
+    TIMER_SHOT = (2 << 30),
+    TIMER_CONT = (3 << 30),
+};
+
 /* Reset Timer */
 void cpu_openrisc_timer_reset(CPUOpenRISCState *env)
 {
     env->ttmr = 0x00000000;
     env->ttcr = 0x00000000;
 }
+
+static void count_update(CPUOpenRISCState *env)
+{
+    uint64_t now, next;
+    uint32_t wait;
+
+    now = qemu_get_clock_ns(vm_clock);
+    if (!is_counting) {
+        qemu_del_timer(env->timer);
+        last_clk = now;
+        return;
+    }
+
+    env->ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
+                                    get_ticks_per_sec());
+    last_clk = now;
+
+    if ((env->ttmr & TTMR_TP) <= (env->ttcr & TTMR_TP)) {
+        wait = TTMR_TP - (env->ttcr & TTMR_TP) + 1;
+        wait += env->ttmr & TTMR_TP;
+    } else {
+        wait = (env->ttmr & TTMR_TP) - (env->ttcr & TTMR_TP);
+    }
+
+    next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
+    qemu_mod_timer(env->timer, next);
+}
+
+static void count_start(CPUOpenRISCState *env)
+{
+    is_counting = 1;
+    count_update(env);
+}
+
+static void count_stop(CPUOpenRISCState *env)
+{
+    is_counting = 0;
+    count_update(env);
+}
+
+uint32_t cpu_openrisc_get_count(CPUOpenRISCState *env)
+{
+    count_update(env);
+    return env->ttcr;
+}
+
+void cpu_openrisc_store_count(CPUOpenRISCState *env, uint32_t count)
+{
+    /* Store new count register */
+    env->ttcr = count;
+    if (env->ttmr & TIMER_NONE) {
+        return;
+    }
+    count_start(env);
+}
+
+void cpu_openrisc_store_compare(CPUOpenRISCState *env, uint32_t value)
+{
+    int ip = env->ttmr & TTMR_IP;
+
+    if (value & TTMR_IP) { /* Keep IP bit */
+        env->ttmr = (value & ~TTMR_IP) + ip;
+    } else {               /* Clear IP bit */
+        env->ttmr = value & ~TTMR_IP;
+        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
+    }
+    count_update(env);
+
+    switch (env->ttmr & TTMR_M) {
+    case TIMER_NONE:
+        count_stop(env);
+        break;
+    case TIMER_INTR:
+        count_start(env);
+        break;
+    case TIMER_SHOT:
+        count_start(env);
+        break;
+    case TIMER_CONT:
+        count_start(env);
+        break;
+    }
+}
+
+static void openrisc_timer_cb(void *opaque)
+{
+    CPUOpenRISCState *env = opaque;
+
+    if ((env->ttmr & TTMR_IE) &&
+         qemu_timer_expired(env->timer, qemu_get_clock_ns(vm_clock))) {
+        env->ttmr |= TTMR_IP;
+        env->interrupt_request |= CPU_INTERRUPT_TIMER;
+    }
+
+    switch (env->ttmr & TTMR_M) {
+    case TIMER_NONE:
+        break;
+    case TIMER_INTR:
+        env->ttcr = 0;
+        count_start(env);
+        break;
+    case TIMER_SHOT:
+        count_stop(env);
+        break;
+    case TIMER_CONT:
+        count_start(env);
+        break;
+    }
+}
+
+void cpu_openrisc_clock_init(CPUOpenRISCState *env)
+{
+    env->timer = qemu_new_timer_ns(vm_clock, &openrisc_timer_cb, env);
+    env->ttmr = 0;
+    env->ttcr = 0;
+}
-- 
1.7.9.5

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

* [Qemu-devel] [PATCH v6 11/16] target-or32: Add a IIS dummy board
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
                   ` (9 preceding siblings ...)
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 10/16] target-or32: Add timer support Jia Liu
@ 2012-06-21  2:58 ` Jia Liu
  2012-06-21  8:19   ` 陳韋任 (Wei-Ren Chen)
  2012-06-21  9:03   ` Peter Crosthwaite
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 12/16] target-or32: Add system instructions Jia Liu
                   ` (4 subsequent siblings)
  15 siblings, 2 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:58 UTC (permalink / raw)
  To: qemu-devel

Add a IIS dummy board.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 hw/openrisc/Makefile.objs |    2 +-
 hw/openrisc_sim.c         |  160 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 161 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..892c67f
--- /dev/null
+++ b/hw/openrisc_sim.c
@@ -0,0 +1,160 @@
+/*
+ *  OpenRISC simulator for use as an ISS.
+ *
+ *  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 "openrisc_cpudev.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 struct _loaderparams {
+    uint64_t ram_size;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *initrd_filename;
+} loaderparams;
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUOpenRISCState *env = opaque;
+    cpu_reset(ENV_GET_CPU(env));
+}
+
+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 uint64_t openrisc_load_kernel(void)
+{
+    long kernel_size;
+    uint64_t elf_entry;
+    target_phys_addr_t entry;
+
+    if (loaderparams.kernel_filename && !qtest_enabled()) {
+        kernel_size = load_elf(loaderparams.kernel_filename, NULL, NULL,
+                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
+        entry = elf_entry;
+        if (kernel_size < 0) {
+            kernel_size = load_uimage(loaderparams.kernel_filename,
+                                      &entry, NULL, NULL);
+        }
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(loaderparams.kernel_filename,
+                                              KERNEL_LOAD_ADDR,
+                                              ram_size - KERNEL_LOAD_ADDR);
+            entry = KERNEL_LOAD_ADDR;
+        }
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    loaderparams.kernel_filename);
+            exit(1);
+        }
+
+        if (kernel_size > 0) {
+            return elf_entry;
+        }
+    } else {
+        entry = 0;
+    }
+
+    return entry;
+}
+
+static void openrisc_sim_init(ram_addr_t ram_size,
+                              const char *boot_device,
+                              const char *kernel_filename,
+                              const char *kernel_cmdline,
+                              const char *initrd_filename,
+                              const char *cpu_model)
+{
+    CPUOpenRISCState *env;
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+
+    if (!cpu_model) {
+        cpu_model = "or1200";
+    }
+    env = cpu_init(cpu_model);
+    if (!env) {
+        fprintf(stderr, "Unable to find CPU definition!\n");
+        exit(1);
+    }
+
+    qemu_register_reset(main_cpu_reset, env);
+    main_cpu_reset(env);
+
+    memory_region_init_ram(ram, "openrisc.ram", ram_size);
+    memory_region_add_subregion(get_system_memory(), 0, ram);
+
+    if (kernel_filename) {
+        loaderparams.ram_size = ram_size;
+        loaderparams.kernel_filename = kernel_filename;
+        loaderparams.kernel_cmdline = kernel_cmdline;
+        env->pc = openrisc_load_kernel();
+    }
+
+    cpu_openrisc_pic_init(env);
+    cpu_openrisc_clock_init(env);
+
+    serial_mm_init(get_system_memory(), 0x90000000, 0,
+                   env->irq[2], 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
+
+    if (nd_table[0].vlan) {
+        openrisc_sim_net_init(get_system_memory(), 0x92000000,
+                              0x92000400, env->irq[4], nd_table);
+    }
+}
+
+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] 25+ messages in thread

* [Qemu-devel] [PATCH v6 12/16] target-or32: Add system instructions
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
                   ` (10 preceding siblings ...)
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 11/16] target-or32: Add a IIS dummy board Jia Liu
@ 2012-06-21  2:58 ` Jia Liu
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 13/16] target-or32: Add gdb stub Jia Liu
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:58 UTC (permalink / raw)
  To: qemu-devel

Add OpenRISC system instructions.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-openrisc/Makefile.objs |    3 +-
 target-openrisc/helper.h      |    4 +
 target-openrisc/sys_helper.c  |  244 +++++++++++++++++++++++++++++++++++++++++
 target-openrisc/translate.c   |   10 ++
 4 files changed, 260 insertions(+), 1 deletion(-)
 create mode 100644 target-openrisc/sys_helper.c

diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
index 0d72c33..9d13a5d 100644
--- a/target-openrisc/Makefile.objs
+++ b/target-openrisc/Makefile.objs
@@ -1,3 +1,4 @@
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-y += cpu.o excp.o intrpt.o mmu.o translate.o
-obj-y += excp_helper.o fpu_helper.o int_helper.o intrpt_helper.o mmu_helper.o
+obj-y += excp_helper.o fpu_helper.o int_helper.o intrpt_helper.o \
+         mmu_helper.o sys_helper.o
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..a2691dc
--- /dev/null
+++ b/target-openrisc/sys_helper.c
@@ -0,0 +1,244 @@
+/*
+ *  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;
+
+    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->map_address_data = &get_phys_data;
+        } else {
+            env->tlb->map_address_data = &get_phys_nommu;
+        }
+
+        if (env->sr & SR_IME) {
+            env->tlb->map_address_code = &get_phys_code;
+        } else {
+            env->tlb->map_address_code = &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 */
+        cpu_openrisc_store_picmr(env, rb);
+        break;
+    case TO_SPR(9, 2):  /* PICSR */
+        cpu_openrisc_store_picsr(env, rb);
+        break;
+    case TO_SPR(10, 0): /* TTMR */
+        cpu_openrisc_store_compare(env, rb);
+        break;
+    case TO_SPR(10, 1): /* TTCR */
+        cpu_openrisc_store_count(env, rb);
+        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;
+
+    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 */
+        return cpu_openrisc_get_count(env);
+
+    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 300236f..0aa7b91 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -976,10 +976,20 @@ static void dec_misc(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn)
 
     case 0x2d:   /*l.mfspr*/
         LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
+        {
+            TCGv_i32 ti = tcg_const_i32(I16);
+            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;
 
     case 0x34:   /*l.sd*/
-- 
1.7.9.5

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

* [Qemu-devel] [PATCH v6 13/16] target-or32: Add gdb stub
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
                   ` (11 preceding siblings ...)
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 12/16] target-or32: Add system instructions Jia Liu
@ 2012-06-21  2:58 ` Jia Liu
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 14/16] target-or32: Add linux syscall, signal and termbits Jia Liu
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:58 UTC (permalink / raw)
  To: qemu-devel

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] 25+ messages in thread

* [Qemu-devel] [PATCH v6 14/16] target-or32: Add linux syscall, signal and termbits
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
                   ` (12 preceding siblings ...)
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 13/16] target-or32: Add gdb stub Jia Liu
@ 2012-06-21  2:58 ` Jia Liu
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 15/16] target-or32: Add linux user support Jia Liu
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 16/16] target-or32: Add testcases Jia Liu
  15 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:58 UTC (permalink / raw)
  To: qemu-devel

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] 25+ messages in thread

* [Qemu-devel] [PATCH v6 15/16] target-or32: Add linux user support
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
                   ` (13 preceding siblings ...)
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 14/16] target-or32: Add linux syscall, signal and termbits Jia Liu
@ 2012-06-21  2:58 ` Jia Liu
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 16/16] target-or32: Add testcases Jia Liu
  15 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:58 UTC (permalink / raw)
  To: qemu-devel

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 80ee0be..c4d6339 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 49108b8..a066479 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2305,6 +2305,93 @@ done_syscall:
 }
 #endif
 
+#ifdef TARGET_OPENRISC
+
+void cpu_loop(CPUOpenRISCState *env)
+{
+    int trapnr, gdbsig;
+
+    for (;;) {
+        trapnr = cpu_exec(env);
+        gdbsig = 0;
+
+        switch (trapnr) {
+        case EXCP_RESET:
+            fprintf(stderr, "\nReset request, exit, pc is %#x\n", env->pc);
+            exit(1);
+            break;
+        case EXCP_BUSERR:
+            fprintf(stderr, "\nBus error, exit, pc is %#x\n", env->pc);
+            gdbsig = SIGBUS;
+            break;
+        case EXCP_DPF:
+        case EXCP_IPF:
+            cpu_dump_state(env, stderr, fprintf, 0);
+            gdbsig = TARGET_SIGSEGV;
+            break;
+        case EXCP_TICK:
+            fprintf(stderr, "\nTick time interrupt pc is %#x\n", env->pc);
+            break;
+        case EXCP_ALIGN:
+            fprintf(stderr, "\nAlignment pc is %#x\n", env->pc);
+            gdbsig = SIGBUS;
+            break;
+        case EXCP_ILLEGAL:
+            fprintf(stderr, "\nIllegal instructionpc is %#x\n", env->pc);
+            gdbsig = SIGILL;
+            break;
+        case EXCP_INT:
+            fprintf(stderr, "\nExternal interruptpc is %#x\n", env->pc);
+            break;
+        case EXCP_DTLBMISS:
+        case EXCP_ITLBMISS:
+            printf("TLB miss\n");
+            break;
+        case EXCP_RANGE:
+            fprintf(stderr, "\nRange\n");
+            gdbsig = SIGSEGV;
+            break;
+        case EXCP_SYSCALL:
+            env->pc += 4;   /* 0xc00; */
+            env->gpr[11] = do_syscall(env,
+                                      env->gpr[11], /* return value       */
+                                      env->gpr[3],  /* r3 - r7 are params */
+                                      env->gpr[4],
+                                      env->gpr[5],
+                                      env->gpr[6],
+                                      env->gpr[7],
+                                      env->gpr[8], 0, 0);
+            break;
+        case EXCP_FPE:
+            fprintf(stderr, "Floating point error\n");
+            break;
+        case EXCP_TRAP:
+            fprintf(stderr, "Trap\n");
+            gdbsig = SIGTRAP;
+            break;
+        case EXCP_NR:
+            fprintf(stderr, "NR\n");
+            break;
+        default:
+            fprintf(stderr, "qemu: unhandled CPU exception %#x - aborting\n", \
+                    trapnr);
+            cpu_dump_state(env, stderr, fprintf, 0);
+            gdbsig = TARGET_SIGILL;
+            break;
+        }
+        if (gdbsig) {
+            gdb_handlesig(env, gdbsig);
+            if (gdbsig != TARGET_SIGTRAP) {
+                exit(1);
+            }
+        }
+
+        process_pending_signals(env);
+    }
+}
+
+#endif /* TARGET_OPENRISC */
+
 #ifdef TARGET_SH4
 void cpu_loop(CPUSH4State *env)
 {
@@ -3385,6 +3472,8 @@ int main(int argc, char **argv, char **envp)
 #else
         cpu_model = "24Kf";
 #endif
+#elif defined TARGET_OPENRISC
+        cpu_model = "or1200";
 #elif defined(TARGET_PPC)
 #ifdef TARGET_PPC64
         cpu_model = "970fx";
@@ -3787,6 +3876,17 @@ int main(int argc, char **argv, char **envp)
             env->hflags |= MIPS_HFLAG_M16;
         }
     }
+#elif defined(TARGET_OPENRISC)
+    {
+        int i;
+
+        for (i = 0; i < 32; i++) {
+            env->gpr[i] = regs->gpr[i];
+        }
+
+        env->sr = regs->sr;
+        env->pc = regs->pc;
+    }
 #elif defined(TARGET_SH4)
     {
         int i;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index b1e139d..e06b6a8 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -3629,6 +3629,235 @@ long do_rt_sigreturn(CPUCRISState *env)
     return -TARGET_ENOSYS;
 }
 
+#elif defined(TARGET_OPENRISC)
+
+struct target_sigcontext {
+    struct target_pt_regs regs;
+    abi_ulong oldmask;
+    abi_ulong usp;
+};
+
+struct target_ucontext {
+    abi_ulong tuc_flags;
+    abi_ulong tuc_link;
+    target_stack_t tuc_stack;
+    struct target_sigcontext tuc_mcontext;
+    target_sigset_t tuc_sigmask;   /* mask last for extensibility */
+};
+
+struct target_rt_sigframe {
+    abi_ulong pinfo;
+    uint64_t puc;
+    struct target_siginfo info;
+    struct target_sigcontext sc;
+    struct target_ucontext uc;
+    unsigned char retcode[16];  /* trampoline code */
+};
+
+/* This is the asm-generic/ucontext.h version */
+#if 0
+static int restore_sigcontext(CPUOpenRISCState *regs,
+                              struct target_sigcontext *sc)
+{
+    unsigned int err = 0;
+    unsigned long old_usp;
+
+    /* Alwys make any pending restarted system call return -EINTR */
+    current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+    /* restore the regs from &sc->regs (same as sc, since regs is first)
+     * (sc is already checked for VERIFY_READ since the sigframe was
+     *  checked in sys_sigreturn previously)
+     */
+
+    if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
+        goto badframe;
+    }
+
+    /* make sure the U-flag is set so user-mode cannot fool us */
+
+    regs->sr &= ~SR_SM;
+
+    /* restore the old USP as it was before we stacked the sc etc.
+     * (we cannot just pop the sigcontext since we aligned the sp and
+     *  stuff after pushing it)
+     */
+
+    err |= __get_user(old_usp, &sc->usp);
+    phx_signal("old_usp 0x%lx", old_usp);
+
+    __PHX__ REALLY           /* ??? */
+    wrusp(old_usp);
+    regs->gpr[1] = old_usp;
+
+    /* TODO: the other ports use regs->orig_XX to disable syscall checks
+     * after this completes, but we don't use that mechanism. maybe we can
+     * use it now ?
+     */
+
+    return err;
+
+badframe:
+    return 1;
+}
+#endif
+
+/* Set up a signal frame.  */
+
+static int setup_sigcontext(struct target_sigcontext *sc,
+                            CPUOpenRISCState *regs,
+                            unsigned long mask)
+{
+    int err = 0;
+    unsigned long usp = regs->gpr[1];
+
+    /* copy the regs. they are first in sc so we can use sc directly */
+
+    /*err |= copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
+
+    /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
+       the signal handler. The frametype will be restored to its previous
+       value in restore_sigcontext. */
+    /*regs->frametype = CRIS_FRAME_NORMAL;*/
+
+    /* then some other stuff */
+    err |= __put_user(mask, &sc->oldmask);
+    err |= __put_user(usp, &sc->usp); return err;
+}
+
+static inline unsigned long align_sigframe(unsigned long sp)
+{
+    unsigned long i;
+    i = sp & ~3UL;
+    return i;
+}
+
+static inline abi_ulong get_sigframe(struct target_sigaction *ka,
+                                     CPUOpenRISCState *regs,
+                                     size_t frame_size)
+{
+    unsigned long sp = regs->gpr[1];
+    int onsigstack = on_sig_stack(sp);
+
+    /* redzone */
+    /* This is the X/Open sanctioned signal stack switching.  */
+    if ((ka->sa_flags & SA_ONSTACK) != 0 && !onsigstack) {
+        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+    }
+
+    sp = align_sigframe(sp - frame_size);
+
+    /*
+     * If we are on the alternate signal stack and would overflow it, don't.
+     * Return an always-bogus address instead so we will die with SIGSEGV.
+     */
+
+    if (onsigstack && !likely(on_sig_stack(sp))) {
+        return -1L;
+    }
+
+    return sp;
+}
+
+static void setup_frame(int sig, struct target_sigaction *ka,
+                        target_sigset_t *set, CPUOpenRISCState *env)
+{
+    printf("Not implement.\n");
+}
+
+static void setup_rt_frame(int sig, struct target_sigaction *ka,
+                           target_siginfo_t *info,
+                           target_sigset_t *set, CPUOpenRISCState *env)
+{
+    int err = 0;
+    abi_ulong frame_addr;
+    unsigned long return_ip;
+    struct target_rt_sigframe *frame;
+    abi_ulong info_addr, uc_addr;
+
+    frame_addr = get_sigframe(ka, env, sizeof *frame);
+
+    frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto give_sigsegv;
+    }
+
+    info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
+    err |= __put_user(info_addr, &frame->pinfo);
+    uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
+    err |= __put_user(uc_addr, &frame->puc);
+
+    if (ka->sa_flags & SA_SIGINFO) {
+        err |= copy_siginfo_to_user(&frame->info, info);
+    }
+    if (err) {
+        goto give_sigsegv;
+    }
+
+    /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/
+    err |= __put_user(0, &frame->uc.tuc_flags);
+    err |= __put_user(0, &frame->uc.tuc_link);
+    err |= __put_user(target_sigaltstack_used.ss_sp,
+                      &frame->uc.tuc_stack.ss_sp);
+    err |= __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
+    err |= __put_user(target_sigaltstack_used.ss_size,
+                      &frame->uc.tuc_stack.ss_size);
+    err |= setup_sigcontext(&frame->sc, env, set->sig[0]);
+
+    /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
+
+    if (err) {
+        goto give_sigsegv;
+    }
+
+    /* trampoline - the desired return ip is the retcode itself */
+    return_ip = (unsigned long)&frame->retcode;
+    /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
+    err |= __put_user(0xa960, (short *)(frame->retcode + 0));
+    err |= __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
+    err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
+    err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
+
+    if (err) {
+        goto give_sigsegv;
+    }
+
+    /* TODO what is the current->exec_domain stuff and invmap ? */
+
+    /* Set up registers for signal handler */
+    env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
+    env->gpr[9] = (unsigned long)return_ip;     /* what we enter LATER */
+    env->gpr[3] = (unsigned long)sig;           /* arg 1: signo */
+    env->gpr[4] = (unsigned long)&frame->info;  /* arg 2: (siginfo_t*) */
+    env->gpr[5] = (unsigned long)&frame->uc;    /* arg 3: ucontext */
+
+    /* actually move the usp to reflect the stacked frame */
+    env->gpr[1] = (unsigned long)frame;
+
+    return;
+
+give_sigsegv:
+    unlock_user_struct(frame, frame_addr, 1);
+    if (sig == TARGET_SIGSEGV) {
+        ka->_sa_handler = TARGET_SIG_DFL;
+    }
+    force_sig(TARGET_SIGSEGV);
+}
+
+long do_sigreturn(CPUOpenRISCState *env)
+{
+
+    fprintf(stderr, "do_sigreturn: not implemented\n");
+    return -TARGET_ENOSYS;
+}
+
+long do_rt_sigreturn(CPUOpenRISCState *env)
+{
+    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
+    return -TARGET_ENOSYS;
+}
+/* TARGET_OPENRISC */
+
 #elif defined(TARGET_S390X)
 
 #define __NUM_GPRS 16
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 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 d499dc4..34dd844 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -364,11 +364,13 @@ 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);
+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
 
 #define CPU_SAVE_VERSION 1
 
@@ -400,6 +402,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] 25+ messages in thread

* [Qemu-devel] [PATCH v6 16/16] target-or32: Add testcases
  2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
                   ` (14 preceding siblings ...)
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 15/16] target-or32: Add linux user support Jia Liu
@ 2012-06-21  2:58 ` Jia Liu
  15 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  2:58 UTC (permalink / raw)
  To: qemu-devel

Add testcases for OpenRISC.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 tests/tcg/openrisc/Makefile      |   71 +++++++++++++++++++++++++++
 tests/tcg/openrisc/test_add.c    |   34 +++++++++++++
 tests/tcg/openrisc/test_addc.c   |   39 +++++++++++++++
 tests/tcg/openrisc/test_addi.c   |   31 ++++++++++++
 tests/tcg/openrisc/test_addic.c  |   33 +++++++++++++
 tests/tcg/openrisc/test_and_or.c |   61 +++++++++++++++++++++++
 tests/tcg/openrisc/test_bf.c     |   46 ++++++++++++++++++
 tests/tcg/openrisc/test_bnf.c    |   50 +++++++++++++++++++
 tests/tcg/openrisc/test_div.c    |   32 ++++++++++++
 tests/tcg/openrisc/test_divu.c   |   32 ++++++++++++
 tests/tcg/openrisc/test_extx.c   |   72 +++++++++++++++++++++++++++
 tests/tcg/openrisc/test_fx.c     |   53 ++++++++++++++++++++
 tests/tcg/openrisc/test_j.c      |   26 ++++++++++
 tests/tcg/openrisc/test_jal.c    |   26 ++++++++++
 tests/tcg/openrisc/test_lf_add.c |   39 +++++++++++++++
 tests/tcg/openrisc/test_lf_div.c |   34 +++++++++++++
 tests/tcg/openrisc/test_lf_eqs.c |   84 ++++++++++++++++++++++++++++++++
 tests/tcg/openrisc/test_lf_ges.c |   84 ++++++++++++++++++++++++++++++++
 tests/tcg/openrisc/test_lf_gts.c |   84 ++++++++++++++++++++++++++++++++
 tests/tcg/openrisc/test_lf_les.c |   84 ++++++++++++++++++++++++++++++++
 tests/tcg/openrisc/test_lf_lts.c |   91 ++++++++++++++++++++++++++++++++++
 tests/tcg/openrisc/test_lf_mul.c |   22 +++++++++
 tests/tcg/openrisc/test_lf_nes.c |   87 +++++++++++++++++++++++++++++++++
 tests/tcg/openrisc/test_lf_rem.c |   32 ++++++++++++
 tests/tcg/openrisc/test_lf_sub.c |   33 +++++++++++++
 tests/tcg/openrisc/test_logic.c  |  100 ++++++++++++++++++++++++++++++++++++++
 tests/tcg/openrisc/test_lx.c     |   78 +++++++++++++++++++++++++++++
 tests/tcg/openrisc/test_movhi.c  |   30 ++++++++++++
 tests/tcg/openrisc/test_mul.c    |   47 ++++++++++++++++++
 tests/tcg/openrisc/test_muli.c   |   47 ++++++++++++++++++
 tests/tcg/openrisc/test_mulu.c   |   47 ++++++++++++++++++
 tests/tcg/openrisc/test_sfeq.c   |   44 +++++++++++++++++
 tests/tcg/openrisc/test_sfeqi.c  |   39 +++++++++++++++
 tests/tcg/openrisc/test_sfges.c  |   44 +++++++++++++++++
 tests/tcg/openrisc/test_sfgesi.c |   40 +++++++++++++++
 tests/tcg/openrisc/test_sfgeu.c  |   44 +++++++++++++++++
 tests/tcg/openrisc/test_sfgeui.c |   41 ++++++++++++++++
 tests/tcg/openrisc/test_sfgts.c  |   45 +++++++++++++++++
 tests/tcg/openrisc/test_sfgtsi.c |   41 ++++++++++++++++
 tests/tcg/openrisc/test_sfgtu.c  |   43 ++++++++++++++++
 tests/tcg/openrisc/test_sfgtui.c |   42 ++++++++++++++++
 tests/tcg/openrisc/test_sfles.c  |   26 ++++++++++
 tests/tcg/openrisc/test_sflesi.c |   39 +++++++++++++++
 tests/tcg/openrisc/test_sfleu.c  |   43 ++++++++++++++++
 tests/tcg/openrisc/test_sfleui.c |   39 +++++++++++++++
 tests/tcg/openrisc/test_sflts.c  |   43 ++++++++++++++++
 tests/tcg/openrisc/test_sfltsi.c |   38 +++++++++++++++
 tests/tcg/openrisc/test_sfltu.c  |   41 ++++++++++++++++
 tests/tcg/openrisc/test_sfltui.c |   39 +++++++++++++++
 tests/tcg/openrisc/test_sfne.c   |   43 ++++++++++++++++
 tests/tcg/openrisc/test_sfnei.c  |   38 +++++++++++++++
 tests/tcg/openrisc/test_sub.c    |   34 +++++++++++++
 52 files changed, 2475 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..92d4fb7
--- /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..8845257
--- /dev/null
+++ b/tests/tcg/openrisc/test_add.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b;
+    int result;
+
+    a = 0x100;
+    b = 0x100;
+    result = 0x200;
+
+    __asm
+    ("l.add %0, %0, %1\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("add error\n");
+    }
+
+    a = 0xffff;
+    b = 0x1;
+    result = 0x10000;
+    __asm
+    ("l.add %0, %0, %1\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("add error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_addc.c b/tests/tcg/openrisc/test_addc.c
new file mode 100644
index 0000000..40b7f93
--- /dev/null
+++ b/tests/tcg/openrisc/test_addc.c
@@ -0,0 +1,39 @@
+#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");
+    }
+
+    b = 0x01;
+    c = 0xffffffff;
+    result = 0x80000001;
+    __asm
+    ("l.addc   %0, %1, %2\n\t"
+     "l.movhi  %2, 0x7fff\n\t"
+     "l.ori    %2, %2, 0xffff\n\t"
+     "l.addc   %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+
+    if (a != result) {
+        printf("addc error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_addi.c b/tests/tcg/openrisc/test_addi.c
new file mode 100644
index 0000000..4ee71f1
--- /dev/null
+++ b/tests/tcg/openrisc/test_addi.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b;
+    int result;
+
+    b = 0x01;
+    result = 0x00;
+    __asm
+    ("l.addi  %0, %1, 0xffff\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("addi error\n\t");
+    }
+
+    b = 0x010000;
+    result = 0xffff;
+    __asm
+    ("l.addi  %0, %1, 0xffff\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("addi error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_addic.c b/tests/tcg/openrisc/test_addic.c
new file mode 100644
index 0000000..b180aad
--- /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");
+    }
+
+    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 0;
+}
diff --git a/tests/tcg/openrisc/test_and_or.c b/tests/tcg/openrisc/test_and_or.c
new file mode 100644
index 0000000..e6f8828
--- /dev/null
+++ b/tests/tcg/openrisc/test_and_or.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b, c;
+    int result;
+
+    b = 0x2;
+    c = 0x1;
+    result = 0;
+
+    __asm
+    ("l.and  %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("and error\n");
+    }
+
+    result = 0x2;
+    __asm
+    ("l.andi  %0, %1, 0x3\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("andi error %x\n", a);
+    }
+
+    result = 0x3;
+    __asm
+    ("l.or   %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("or error\n");
+    }
+
+    result = 0x3;
+    __asm
+    ("l.xor  %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("xor error\n");
+    }
+
+    __asm
+    ("l.xori  %0, %1, 0x1\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("xori error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_bf.c b/tests/tcg/openrisc/test_bf.c
new file mode 100644
index 0000000..53ea96d
--- /dev/null
+++ b/tests/tcg/openrisc/test_bf.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b, c;
+    int result;
+
+    a = 0;
+    b = 10;
+    c = 11;
+    result = 0x2;
+
+    __asm
+    ("1:\n\t"
+     "l.addi %1, %1, 0x01\n\t"
+     "l.addi %0, %0, 0x01\n\t"
+     "l.sfeq %1, %2\n\t"
+     "l.bf   1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("sfeq error\n");
+    }
+
+    a = 0x00;
+    b = 0x11;
+    c = 0x11;
+    result = 0x01;
+    __asm
+    ("1:\n\t"
+     "l.addi %1, %1, 0x01\n\t"
+     "l.addi %0, %0, 0x01\n\t"
+     "l.sfeq %1, %2\n\t"
+     "l.bf   1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("sfeq error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_bnf.c b/tests/tcg/openrisc/test_bnf.c
new file mode 100644
index 0000000..bca94d9
--- /dev/null
+++ b/tests/tcg/openrisc/test_bnf.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b;
+    int result;
+
+    a = 0;
+    b = 0;
+    result = 0x3;
+
+    __asm
+    ("l.sfeqi %1, 0x0\n\t"
+     "l.bnf 1f\n\t"
+     "l.nop\n\t"
+     "\n\t"
+     "l.addi %0, %0, 0x1\n\t"
+     "l.addi %0, %0, 0x1\n\t"
+     "\n\t"
+     "1:\n\t"
+     "l.addi %0, %0, 0x1\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("l.bnf error\n");
+    }
+
+    a = 0;
+    b = 0;
+    result = 1;
+    __asm
+    ("l.sfeqi %1, 0x1\n\t"
+     "l.bnf 1f\n\t"
+     "l.nop\n\t"
+     "\n\t"
+     "l.addi %0, %0, 0x1\n\t"
+     "l.addi %0, %0, 0x1\n\t"
+     "\n\t"
+     "1:\n\t"
+     "l.addi %0, %0, 0x1\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("l.bnf error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_div.c b/tests/tcg/openrisc/test_div.c
new file mode 100644
index 0000000..2bd285b
--- /dev/null
+++ b/tests/tcg/openrisc/test_div.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b, c;
+    int result;
+
+    b = 0x120;
+    c = 0x4;
+    result = 0x48;
+
+    __asm
+    ("l.div  %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("div error\n");
+    }
+
+    result = 0x4;
+    __asm
+    ("l.div %0, %1, %0\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("div error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_divu.c b/tests/tcg/openrisc/test_divu.c
new file mode 100644
index 0000000..da8aad3
--- /dev/null
+++ b/tests/tcg/openrisc/test_divu.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b, c;
+    int result;
+
+    b = 0x120;
+    c = 0x4;
+    result = 0x48;
+
+    __asm
+    ("l.divu  %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("divu error\n");
+    }
+
+    result = 0x4;
+    __asm
+    ("l.divu %0, %1, %0\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("divu error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_extx.c b/tests/tcg/openrisc/test_extx.c
new file mode 100644
index 0000000..08e5083
--- /dev/null
+++ b/tests/tcg/openrisc/test_extx.c
@@ -0,0 +1,72 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b;
+    int result;
+
+    b = 0x83;
+    result = 0xffffff83;
+    __asm
+    ("l.extbs  %0, %1\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("extbs error\n");
+    }
+
+    result = 0x83;
+    __asm
+    ("l.extbz  %0, %1\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("extbz error\n");
+    }
+
+    b = 0x8083;
+    result = 0xffff8083;
+    __asm
+    ("l.exths  %0, %1\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("exths error\n");
+    }
+
+    result = 0x8083;
+    __asm
+    ("l.exthz  %0, %1\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("exthz error\n");
+    }
+
+    b = 0x11;
+    result = 0x11;
+    __asm
+    ("l.extws  %0, %1\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+
+    if (a != result) {
+        printf("extws error\n");
+    }
+
+    __asm
+    ("l.extwz  %0, %1\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("extwz error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_fx.c b/tests/tcg/openrisc/test_fx.c
new file mode 100644
index 0000000..238817e
--- /dev/null
+++ b/tests/tcg/openrisc/test_fx.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b;
+    int result;
+
+    b = 0x123;
+    result = 1;
+    __asm
+    ("l.ff1 %0, %1\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("ff1 error\n");
+    }
+
+    b = 0x0;
+    result = 0;
+    __asm
+    ("l.ff1 %0, %1\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("ff1 error\n");
+    }
+
+    b = 0x123;
+    result = 9;
+    __asm
+    ("l.fl1 %0, %1\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("fl1 error\n");
+    }
+
+    b = 0x0;
+    result = 0;
+    __asm
+    ("l.fl1 %0, %1\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("fl1 error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_j.c b/tests/tcg/openrisc/test_j.c
new file mode 100644
index 0000000..183d051
--- /dev/null
+++ b/tests/tcg/openrisc/test_j.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a;
+    int result;
+
+    a = 0;
+    result = 2;
+
+    __asm
+    ("l.addi %0, %0, 1\n\t"
+     "l.j j\n\t"
+     "l.nop\n\t"
+     "l.addi %0, %0, 1\n\t"
+     "l.nop\n\t"
+     "j:\n\t"
+     "l.addi %0, %0, 1\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("j error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_jal.c b/tests/tcg/openrisc/test_jal.c
new file mode 100644
index 0000000..4c9af9a
--- /dev/null
+++ b/tests/tcg/openrisc/test_jal.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a;
+    int result;
+
+    a = 0;
+    result = 2;
+
+    __asm
+    ("l.addi %0, %0, 1\n\t"
+     "l.jal jal\n\t"
+     "l.nop\n\t"
+     "l.addi %0, %0, 1\n\t"
+     "l.nop\n\t"
+     "jal:\n\t"
+     "l.addi %0, %0, 1\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("jal error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_add.c b/tests/tcg/openrisc/test_lf_add.c
new file mode 100644
index 0000000..212b135
--- /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);
+    }
+
+/*    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 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..c090ec6
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_div.c
@@ -0,0 +1,34 @@
+#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");
+    }
+
+/*    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 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..57bb779
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_eqs.c
@@ -0,0 +1,84 @@
+#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");
+    }
+
+    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");
+    }
+
+/*    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");
+    }
+
+    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 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..935c137
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_ges.c
@@ -0,0 +1,84 @@
+#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");
+    }
+
+    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");
+    }
+
+/*    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");
+    }
+
+    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 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..166a0bf
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_gts.c
@@ -0,0 +1,84 @@
+#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");
+    }
+
+    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");
+    }
+
+/*    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");
+    }
+
+    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 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..5e648ec
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_les.c
@@ -0,0 +1,84 @@
+#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");
+    }
+
+    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");
+    }
+
+/*    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");
+    }
+
+    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 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..0424bb4
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_lts.c
@@ -0,0 +1,91 @@
+#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");
+    }
+
+    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");
+    }
+
+/*    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");
+    }
+
+    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 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..1cffadb
--- /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 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..e66409d
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_nes.c
@@ -0,0 +1,87 @@
+#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");
+    }
+
+    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");
+    }
+/*    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");
+    }
+
+    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 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..4662c49
--- /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");
+    }*/
+
+    __asm
+    ("lf.rem.s      %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+
+    if (a != result) {
+        printf("lf.rem.s error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_lf_sub.c b/tests/tcg/openrisc/test_lf_sub.c
new file mode 100644
index 0000000..c29a522
--- /dev/null
+++ b/tests/tcg/openrisc/test_lf_sub.c
@@ -0,0 +1,33 @@
+#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");
+    }
+
+/*    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 0;
+}
diff --git a/tests/tcg/openrisc/test_logic.c b/tests/tcg/openrisc/test_logic.c
new file mode 100644
index 0000000..a01461b
--- /dev/null
+++ b/tests/tcg/openrisc/test_logic.c
@@ -0,0 +1,100 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b, c;
+    int result;
+
+    b = 0x9743;
+    c = 0x2;
+    result = 0x25d0c;
+
+    __asm
+    ("l.sll    %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("sll error\n");
+    }
+
+    b = 0x9743;
+    result = 0x25d0c;
+    __asm
+    ("l.slli   %0, %1, 0x2\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("slli error\n");
+    }
+
+    b = 0x7654;
+    c = 0x03;
+    result = 0xeca;
+    __asm
+    ("l.srl    %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+
+    b = 0x7654;
+    result = 0xeca;
+    __asm
+    ("l.srli   %0, %1, 0x3\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("srli error\n");
+    }
+
+    b = 0x80000001;
+    c = 0x4;
+    result = 0x18000000;
+    __asm
+    ("l.ror    %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("ror error\n");
+    }
+
+    b = 0x80000001;
+    result = 0x18000000;
+    __asm
+    ("l.rori   %0, %1, 0x4\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("rori error\n");
+    }
+
+    b = 0x80000001;
+    c = 0x03;
+    result = 0xf0000000;
+    __asm
+    ("l.sra    %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("sra error\n");
+    }
+
+    b = 0x80000001;
+    result = 0xf0000000;
+
+    __asm
+    ("l.srai   %0, %1, 0x3\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("srai error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_lx.c b/tests/tcg/openrisc/test_lx.c
new file mode 100644
index 0000000..854deef
--- /dev/null
+++ b/tests/tcg/openrisc/test_lx.c
@@ -0,0 +1,78 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a;
+    int p[50];
+    int result;
+
+    result = 0x23;
+    __asm
+    ("l.ori r8, r0, 0x123\n\t"
+     "l.sb  0x4 + %1, r8\n\t"
+     "\n\t"
+     "l.lbz %0, 0x4 + %1\n\t"
+     : "=r"(a), "+m"(*p)
+    );
+    if (a != result) {
+        printf("lbz error, %x\n", a);
+    }
+
+    result = 0x23;
+    __asm
+    ("l.lbs %0, 0x4 + %1\n\t"
+     : "=r"(a)
+     : "m"(*p)
+    );
+    if (a != result) {
+        printf("lbs error\n");
+    }
+
+    result = 0x1111;
+    __asm
+    ("l.ori r8, r0, 0x1111\n\t"
+     "l.sh  0x20 + %1, r8\n\t"
+     "\n\t"
+     "l.lhs %0, 0x20 + %1\n\t"
+     : "=r"(a), "=m"(*p)
+    );
+    if (a != result) {
+        printf("lhs error, %x\n", a);
+    }
+
+    result = 0x1111;
+    __asm
+    ("l.lhz %0, 0x20 + %1\n\t"
+     : "=r"(a)
+     : "m"(*p)
+    );
+    if (a != result) {
+        printf("lhz error\n");
+    }
+
+    result = 0x1111233;
+    __asm
+    ("l.ori r8, r0, 0x1233\n\t"
+     "l.movhi r1, 0x111\n\t"
+     "l.or  r8, r8, r1\n\t"
+     "l.sw  0x123 + %1, r8\n\t"
+     "\n\t"
+     "l.lws %0, 0x123 + %1\n\t"
+     : "=r"(a), "+m"(*p)
+    );
+    if (a != result) {
+        printf("lws error, %x\n", a);
+    }
+
+    result = 0x1111233;
+    __asm
+    ("l.lwz %0, 0x123 + %1\n\t"
+     : "=r"(a)
+     : "m"(*p)
+    );
+    if (a != result) {
+        printf("lwz error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_movhi.c b/tests/tcg/openrisc/test_movhi.c
new file mode 100644
index 0000000..9548a7a
--- /dev/null
+++ b/tests/tcg/openrisc/test_movhi.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a;
+    int result;
+
+    result = 0x1222;
+
+    __asm
+    ("l.movhi r3, 0x1222\n\t"
+     "l.srli   %0, r3, 16\n\t"
+     : "=r"(a)
+    );
+    if (a != result) {
+        printf("movhi error\n");
+    }
+
+    result = 0x1111;
+    __asm
+    ("l.movhi r8, 0x1111\n\t"
+     "l.srli   %0, r8, 16\n\t"
+     : "=r"(a)
+    );
+    if (a != result) {
+        printf("movhi error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_mul.c b/tests/tcg/openrisc/test_mul.c
new file mode 100644
index 0000000..d992d98
--- /dev/null
+++ b/tests/tcg/openrisc/test_mul.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b, c;
+    int result;
+
+    b = 0x4;
+    c = 0x1;
+    result = 0x4;
+
+    __asm
+    ("l.mul    %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("mul error\n");
+    }
+
+    b = 0x1;
+    c = 0x0;
+    result = 0x0;
+
+    __asm
+    ("l.mul    %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("mul error\n");
+    }
+
+    b = 0x1;
+    c = 0xff;
+    result = 0xff;
+    __asm
+    ("l.mul    %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("mul error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_muli.c b/tests/tcg/openrisc/test_muli.c
new file mode 100644
index 0000000..8630711
--- /dev/null
+++ b/tests/tcg/openrisc/test_muli.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b, c;
+    int result;
+
+    b = 0x4;
+    c = 0x1;
+    result = 0x4;
+
+    __asm
+    ("l.muli    %0, %1, 0x1\n\t"
+     : "=r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("muli error\n");
+    }
+
+    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");
+    }
+
+    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 0;
+}
diff --git a/tests/tcg/openrisc/test_mulu.c b/tests/tcg/openrisc/test_mulu.c
new file mode 100644
index 0000000..a62caff
--- /dev/null
+++ b/tests/tcg/openrisc/test_mulu.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b, c;
+    int result;
+
+    b = 0x4;
+    c = 0x1;
+    result = 0x4;
+
+    __asm
+    ("l.mulu    %0, %1, %2\n\t"
+     : "=r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("mulu error\n");
+    }
+
+    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");
+    }
+
+    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 0;
+}
diff --git a/tests/tcg/openrisc/test_sfeq.c b/tests/tcg/openrisc/test_sfeq.c
new file mode 100644
index 0000000..52577fa
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfeq.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b;
+    int result;
+
+    a = 0x1;
+    b = 0x80;
+    result = 0x2;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 0x1\n\t"
+     "l.sfeq   %0, %1\n\t"
+     "l.bf     1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfeq error\n");
+    }
+
+    a = 0x7f;
+    b = 0x80;
+    result = 0x81;
+
+    __asm
+    ("2:\n\t"
+     "l.addi   %0, %0, 0x1\n\t"
+     "l.sfeq   %0, %1\n\t"
+     "l.bf     2b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+
+    if (a != result) {
+        printf("sfeq error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfeqi.c b/tests/tcg/openrisc/test_sfeqi.c
new file mode 100644
index 0000000..6c9690d
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfeqi.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a;
+    int result;
+
+    a = 1;
+    result = 2;
+
+    __asm
+    ("1:\n\t"
+     "l.addi    %0, %0, 0x1\n\t"
+     "l.sfeqi   %0, 0x80\n\t"
+     "l.bf      1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sfeqi error\n");
+    }
+
+    a = 0x7f;
+    result = 0x81;
+
+    __asm
+    ("2:\n\t"
+     "l.addi    %0, %0, 0x1\n\t"
+     "l.sfeqi   %0, 0x80\n\t"
+     "l.bf      2b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sfeqi error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfges.c b/tests/tcg/openrisc/test_sfges.c
new file mode 100644
index 0000000..3505002
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfges.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b, c;
+    int result;
+
+    a = 0;
+    b = 3;
+    result = 1;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 1\n\t"
+     "l.sfges  %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfges error\n");
+    }
+
+    a = 0xff;
+    b = 3;
+    c = 0x1;
+    result = 2;
+
+    __asm
+    ("1:\n\t"
+     "l.sub    %0, %0, %2\n\t"
+     "l.sfges  %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("sfges error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgesi.c b/tests/tcg/openrisc/test_sfgesi.c
new file mode 100644
index 0000000..5c2bc8a
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfgesi.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+int main(void)
+{
+    int a, b;
+    int result;
+
+    a = 0;
+    result = 1;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 1\n\t"
+     "l.sfgesi %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sfgesi error\n");
+    }
+
+    a = 0xff;
+    b = 1;
+    result = 2;
+
+    __asm
+    ("1:\n\t"
+     "l.sub    %0, %0, %1\n\t"
+     "l.sfgesi %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfgesi error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgeu.c b/tests/tcg/openrisc/test_sfgeu.c
new file mode 100644
index 0000000..c084c5f
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfgeu.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b, c;
+    int result;
+
+    a = 0;
+    b = 3;
+    result = 1;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 1\n\t"
+     "l.sfgeu  %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfgeu error\n");
+    }
+
+    a = 0xff;
+    b = 3;
+    c = 1;
+    result = 2;
+
+    __asm
+    ("1:\n\t"
+     "l.sub    %0, %0, %2\n\t"
+     "l.sfgeu  %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("sfgeu error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgeui.c b/tests/tcg/openrisc/test_sfgeui.c
new file mode 100644
index 0000000..ac4bd7f
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfgeui.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b;
+    int result;
+
+    a = 0;
+    result = 1;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 1\n\t"
+     "l.sfgeui %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sfgeui error\n");
+    }
+
+    a = 0xff;
+    b = 1;
+    result = 2;
+
+    __asm
+    ("1:\n\t"
+     "l.sub    %0, %0, %1\n\t"
+     "l.sfgeui %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfgeui error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgts.c b/tests/tcg/openrisc/test_sfgts.c
new file mode 100644
index 0000000..d2aeb0a
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfgts.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b, c;
+    int result;
+
+    a = 0;
+    b = 3;
+    result = 1;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 1\n\t"
+     "l.sfgts  %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfgts error\n");
+    }
+
+
+    a = 0xff;
+    b = 3;
+    c = 1;
+    result = 3;
+
+    __asm
+    ("1:\n\t"
+     "l.sub    %0, %0, %2\n\t"
+     "l.sfgts  %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("sfgts error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgtsi.c b/tests/tcg/openrisc/test_sfgtsi.c
new file mode 100644
index 0000000..4ad398c
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfgtsi.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b;
+    int result;
+
+    a = 0;
+    result = 1;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 1\n\t"
+     "l.sfgtsi %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sfgtsi error\n");
+    }
+
+    a = 0xff;
+    b = 1;
+    result = 3;
+
+    __asm
+    ("1:\n\t"
+     "l.sub    %0, %0, %1\n\t"
+     "l.sfgtsi %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfgtsi error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgtu.c b/tests/tcg/openrisc/test_sfgtu.c
new file mode 100644
index 0000000..8a2b909
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfgtu.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+int main(void)
+{
+    int a, b, c;
+    int result;
+
+    a = 0;
+    b = 3;
+    result = 1;
+
+    __asm
+    ("1:\n\t"
+     "l.addi %0, %0, 1\n\t"
+     "l.sfgtu %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfgtu error\n");
+    }
+
+    a = 0xff;
+    b = 3;
+    c = 1;
+    result = 3;
+
+    __asm
+    ("1:\n\t"
+     "l.sub    %0, %0, %2\n\t"
+     "l.sfgtu  %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b), "r"(c)
+    );
+    if (a != result) {
+        printf("sfgtu error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfgtui.c b/tests/tcg/openrisc/test_sfgtui.c
new file mode 100644
index 0000000..755907a
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfgtui.c
@@ -0,0 +1,42 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b;
+    int result;
+
+    a = 0;
+    result = 1;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 1\n\t"
+     "l.sfgtui %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sfgtui error\n");
+    }
+
+
+    a = 0xff;
+    b = 1;
+    result = 3;
+
+    __asm
+    ("1:\n\t"
+     "l.sub     %0, %0, %1\n\t"
+     "l.sfgtui  %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfgtui error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfles.c b/tests/tcg/openrisc/test_sfles.c
new file mode 100644
index 0000000..3215936
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfles.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b;
+    int result;
+
+    a = 0;
+    b = 3;
+    result = 4;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 4\n\t"
+     "l.sfles  %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfles error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sflesi.c b/tests/tcg/openrisc/test_sflesi.c
new file mode 100644
index 0000000..5ae6585
--- /dev/null
+++ b/tests/tcg/openrisc/test_sflesi.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a;
+    int result;
+
+    a = 0;
+    result = 4;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 4\n\t"
+     "l.sflesi %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sflesi error\n");
+    }
+
+    a = 0;
+    result = 4;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 1\n\t"
+     "l.sflesi %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sflesi error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfleu.c b/tests/tcg/openrisc/test_sfleu.c
new file mode 100644
index 0000000..59fdaf7
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfleu.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b;
+    int result;
+
+    a = 0;
+    b = 3;
+    result = 4;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 4\n\t"
+     "l.sfleu  %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfleu error\n");
+    }
+
+    a = 0;
+    b = 3;
+    result = 4;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 1\n\t"
+     "l.sfleu  %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfleu error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfleui.c b/tests/tcg/openrisc/test_sfleui.c
new file mode 100644
index 0000000..df1ba07
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfleui.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a;
+    int result;
+
+    a = 0;
+    result = 4;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 4\n\t"
+     "l.sfleui %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sfleui error\n");
+    }
+
+    a = 0;
+    result = 4;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 1\n\t"
+     "l.sfleui %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sfleui error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sflts.c b/tests/tcg/openrisc/test_sflts.c
new file mode 100644
index 0000000..e4134ea
--- /dev/null
+++ b/tests/tcg/openrisc/test_sflts.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b;
+    int result;
+
+    a = 0;
+    b = 3;
+    result = 4;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 4\n\t"
+     "l.sflts  %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sflts error\n");
+    }
+
+    a = 0;
+    b = 3;
+    result = 3;
+
+    __asm
+    ("1:\n\t"
+     "l.addi    %0, %0, 1\n\t"
+     "l.sflts   %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sflts error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfltsi.c b/tests/tcg/openrisc/test_sfltsi.c
new file mode 100644
index 0000000..68c2d79
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfltsi.c
@@ -0,0 +1,38 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a;
+    int result;
+
+    a = 0;
+    result = 4;
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 4\n\t"
+     "l.sfltsi %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sfltsi error\n");
+    }
+
+    a = 0;
+    result = 3;
+
+    __asm
+    ("1:\n\t"
+     "l.addi    %0, %0, 1\n\t"
+     "l.sfltsi  %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sfltsi error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfltu.c b/tests/tcg/openrisc/test_sfltu.c
new file mode 100644
index 0000000..2b50c9c
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfltu.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b;
+    int result;
+
+    a = 0;
+    b = 3;
+    result = 4;
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 4\n\t"
+     "l.sfltu  %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfltu error\n");
+    }
+
+    a = 0;
+    b = 3;
+    result = 3;
+    __asm
+    ("1:\n\t"
+     "l.addi    %0, %0, 1\n\t"
+     "l.sfltu  %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfltu error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfltui.c b/tests/tcg/openrisc/test_sfltui.c
new file mode 100644
index 0000000..8660d8f
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfltui.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a;
+    int result;
+
+    a = 0;
+    result = 4;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 4\n\t"
+     "l.sfltsi %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sfltui error\n");
+    }
+
+    a = 0;
+    result = 3;
+
+    __asm
+    ("1:\n\t"
+     "l.addi    %0, %0, 1\n\t"
+     "l.sfltsi %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sfltui error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfne.c b/tests/tcg/openrisc/test_sfne.c
new file mode 100644
index 0000000..064650c
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfne.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a, b;
+    int result;
+
+    a = 0;
+    b = 3;
+    result = 3;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 3\n\t"
+     "l.sfne   %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfne error\n");
+    }
+
+    a = 0;
+    b = 3;
+    result = 3;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 1\n\t"
+     "l.sfne   %0, %1\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+     : "r"(b)
+    );
+    if (a != result) {
+        printf("sfne error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sfnei.c b/tests/tcg/openrisc/test_sfnei.c
new file mode 100644
index 0000000..cbc48d4
--- /dev/null
+++ b/tests/tcg/openrisc/test_sfnei.c
@@ -0,0 +1,38 @@
+#include <stdio.h>
+
+int main(void)
+{
+    int a;
+    int result;
+
+    a = 0;
+    result = 3;
+
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 3\n\t"
+     "l.sfnei  %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sfnei error\n");
+    }
+
+    a = 0;
+    result = 3;
+    __asm
+    ("1:\n\t"
+     "l.addi   %0, %0, 1\n\t"
+     "l.sfnei  %0, 0x3\n\t"
+     "l.bf 1b\n\t"
+     "l.nop\n\t"
+     : "+r"(a)
+    );
+    if (a != result) {
+        printf("sfnei error\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/openrisc/test_sub.c b/tests/tcg/openrisc/test_sub.c
new file mode 100644
index 0000000..f4b0174
--- /dev/null
+++ b/tests/tcg/openrisc/test_sub.c
@@ -0,0 +1,34 @@
+#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");
+    }
+
+    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 0;
+}
-- 
1.7.9.5

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

* Re: [Qemu-devel] [PATCH v6 11/16] target-or32: Add a IIS dummy board
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 11/16] target-or32: Add a IIS dummy board Jia Liu
@ 2012-06-21  8:19   ` 陳韋任 (Wei-Ren Chen)
  2012-06-21  9:10     ` Max Filippov
  2012-06-21  9:11     ` Jia Liu
  2012-06-21  9:03   ` Peter Crosthwaite
  1 sibling, 2 replies; 25+ messages in thread
From: 陳韋任 (Wei-Ren Chen) @ 2012-06-21  8:19 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

> + *  OpenRISC simulator for use as an ISS.
                                        ^^^
  Shoudld be IIS?

Regards,
chenwj

-- 
Wei-Ren Chen (陳韋任)
Computer Systems Lab, Institute of Information Science,
Academia Sinica, Taiwan (R.O.C.)
Tel:886-2-2788-3799 #1667
Homepage: http://people.cs.nctu.edu.tw/~chenwj

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

* Re: [Qemu-devel] [PATCH v6 11/16] target-or32: Add a IIS dummy board
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 11/16] target-or32: Add a IIS dummy board Jia Liu
  2012-06-21  8:19   ` 陳韋任 (Wei-Ren Chen)
@ 2012-06-21  9:03   ` Peter Crosthwaite
  2012-06-25  2:23     ` Jia Liu
  1 sibling, 1 reply; 25+ messages in thread
From: Peter Crosthwaite @ 2012-06-21  9:03 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Jun 21, 2012 at 12:58 PM, Jia Liu <proljc@gmail.com> wrote:
> Add a IIS dummy board.
>
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  hw/openrisc/Makefile.objs |    2 +-
>  hw/openrisc_sim.c         |  160 +++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 161 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..892c67f
> --- /dev/null
> +++ b/hw/openrisc_sim.c
> @@ -0,0 +1,160 @@
> +/*
> + *  OpenRISC simulator for use as an ISS.
> + *
> + *  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 "openrisc_cpudev.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 struct _loaderparams {
> +    uint64_t ram_size;
> +    const char *kernel_filename;
> +    const char *kernel_cmdline;
> +    const char *initrd_filename;
> +} loaderparams;
> +
> +static void main_cpu_reset(void *opaque)
> +{
> +    CPUOpenRISCState *env = opaque;
> +    cpu_reset(ENV_GET_CPU(env));
> +}
> +
> +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 uint64_t openrisc_load_kernel(void)
> +{
> +    long kernel_size;
> +    uint64_t elf_entry;
> +    target_phys_addr_t entry;
> +
> +    if (loaderparams.kernel_filename && !qtest_enabled()) {
> +        kernel_size = load_elf(loaderparams.kernel_filename, NULL, NULL,
> +                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
> +        entry = elf_entry;
> +        if (kernel_size < 0) {
> +            kernel_size = load_uimage(loaderparams.kernel_filename,
> +                                      &entry, NULL, NULL);
> +        }
> +        if (kernel_size < 0) {
> +            kernel_size = load_image_targphys(loaderparams.kernel_filename,
> +                                              KERNEL_LOAD_ADDR,
> +                                              ram_size - KERNEL_LOAD_ADDR);
> +            entry = KERNEL_LOAD_ADDR;
> +        }
> +        if (kernel_size < 0) {
> +            fprintf(stderr, "qemu: could not load kernel '%s'\n",
> +                    loaderparams.kernel_filename);
> +            exit(1);
> +        }
> +
> +        if (kernel_size > 0) {
> +            return elf_entry;
> +        }

Hi Jia,

This seems a little weird. What happens here when it successfully
loads a uimage or raw image? It returns the elf_entry (probably == 0)
as the load address?

Regards,
Peter

> +    } else {
> +        entry = 0;
> +    }
> +
> +    return entry;
> +}
> +
> +static void openrisc_sim_init(ram_addr_t ram_size,
> +                              const char *boot_device,
> +                              const char *kernel_filename,
> +                              const char *kernel_cmdline,
> +                              const char *initrd_filename,
> +                              const char *cpu_model)
> +{
> +    CPUOpenRISCState *env;
> +    MemoryRegion *ram = g_new(MemoryRegion, 1);
> +
> +    if (!cpu_model) {
> +        cpu_model = "or1200";
> +    }
> +    env = cpu_init(cpu_model);
> +    if (!env) {
> +        fprintf(stderr, "Unable to find CPU definition!\n");
> +        exit(1);
> +    }
> +
> +    qemu_register_reset(main_cpu_reset, env);
> +    main_cpu_reset(env);
> +
> +    memory_region_init_ram(ram, "openrisc.ram", ram_size);
> +    memory_region_add_subregion(get_system_memory(), 0, ram);
> +
> +    if (kernel_filename) {
> +        loaderparams.ram_size = ram_size;
> +        loaderparams.kernel_filename = kernel_filename;
> +        loaderparams.kernel_cmdline = kernel_cmdline;
> +        env->pc = openrisc_load_kernel();
> +    }
> +
> +    cpu_openrisc_pic_init(env);
> +    cpu_openrisc_clock_init(env);
> +
> +    serial_mm_init(get_system_memory(), 0x90000000, 0,
> +                   env->irq[2], 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
> +
> +    if (nd_table[0].vlan) {
> +        openrisc_sim_net_init(get_system_memory(), 0x92000000,
> +                              0x92000400, env->irq[4], nd_table);
> +    }
> +}
> +
> +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	[flat|nested] 25+ messages in thread

* Re: [Qemu-devel] [PATCH v6 11/16] target-or32: Add a IIS dummy board
  2012-06-21  8:19   ` 陳韋任 (Wei-Ren Chen)
@ 2012-06-21  9:10     ` Max Filippov
  2012-06-21  9:11     ` Jia Liu
  1 sibling, 0 replies; 25+ messages in thread
From: Max Filippov @ 2012-06-21  9:10 UTC (permalink / raw)
  To: 陳韋任 (Wei-Ren Chen); +Cc: Jia Liu, qemu-devel

On Thu, Jun 21, 2012 at 12:19 PM, 陳韋任 (Wei-Ren Chen)
<chenwj@iis.sinica.edu.tw> wrote:
>> + *  OpenRISC simulator for use as an ISS.
>                                        ^^^
>  Shoudld be IIS?

I guess it stands for Instruction Set Simulator, so rather the subject
should be changed.

-- 
Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH v6 11/16] target-or32: Add a IIS dummy board
  2012-06-21  8:19   ` 陳韋任 (Wei-Ren Chen)
  2012-06-21  9:10     ` Max Filippov
@ 2012-06-21  9:11     ` Jia Liu
  1 sibling, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-21  9:11 UTC (permalink / raw)
  To: 陳韋任 (Wei-Ren Chen); +Cc: qemu-devel

Hello Wei-Ren,

On Thu, Jun 21, 2012 at 4:19 PM, 陳韋任 (Wei-Ren Chen)
<chenwj@iis.sinica.edu.tw> wrote:
>> + *  OpenRISC simulator for use as an ISS.
>                                        ^^^
>  Shoudld be IIS?
>

Instruction Set Sim
Instruction Level Sim
What ever, I'll make it more clear :)

> Regards,
> chenwj
>
> --
> Wei-Ren Chen (陳韋任)
> Computer Systems Lab, Institute of Information Science,
> Academia Sinica, Taiwan (R.O.C.)
> Tel:886-2-2788-3799 #1667
> Homepage: http://people.cs.nctu.edu.tw/~chenwj

Regards,
Jia.

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

* Re: [Qemu-devel] [PATCH v6 08/16] target-or32: Add instruction tanslation
  2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 08/16] target-or32: Add instruction tanslation Jia Liu
@ 2012-06-21 10:24   ` Max Filippov
  2012-06-25  2:50     ` Jia Liu
  0 siblings, 1 reply; 25+ messages in thread
From: Max Filippov @ 2012-06-21 10:24 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Jun 21, 2012 at 6:58 AM, Jia Liu <proljc@gmail.com> wrote:
> Add OpenRISC instruction tanslation routines.
>
> Signed-off-by: Jia Liu <proljc@gmail.com>

[...]

> +    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();
> +                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_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0);
> +                    tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
> +                    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],
> +                                       0xffffffff, lab2);
> +                    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb],
> +                                       0x80000000, 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, lab2);

Causes host division by zero/overflow. I'd suggest to brcond to lab3 set after
the final tcg_gen_div.

> +                    gen_exception(dc, EXCP_RANGE);
> +                    gen_set_label(lab2);
> +                    tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
> +                }
> +                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();
> +                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, lab1);

Ditto.

> +                    gen_exception(dc, EXCP_RANGE);
> +                    gen_set_label(lab1);
> +                    tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
> +                }
> +                tcg_temp_free_i32(sr_ove);
> +            }
> +            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_new();

Need to be temp_local to survive brcond.

> +                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;

[...]

-- 
Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH v6 11/16] target-or32: Add a IIS dummy board
  2012-06-21  9:03   ` Peter Crosthwaite
@ 2012-06-25  2:23     ` Jia Liu
  2012-06-25  2:33       ` Peter Crosthwaite
  0 siblings, 1 reply; 25+ messages in thread
From: Jia Liu @ 2012-06-25  2:23 UTC (permalink / raw)
  To: Peter Crosthwaite; +Cc: qemu-devel

Hi Peter,

On Thu, Jun 21, 2012 at 5:03 PM, Peter Crosthwaite
<peter.crosthwaite@petalogix.com> wrote:
> On Thu, Jun 21, 2012 at 12:58 PM, Jia Liu <proljc@gmail.com> wrote:
>> Add a IIS dummy board.
>>
>> Signed-off-by: Jia Liu <proljc@gmail.com>
>> ---
>>  hw/openrisc/Makefile.objs |    2 +-
>>  hw/openrisc_sim.c         |  160 +++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 161 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..892c67f
>> --- /dev/null
>> +++ b/hw/openrisc_sim.c
>> @@ -0,0 +1,160 @@
>> +/*
>> + *  OpenRISC simulator for use as an ISS.
>> + *
>> + *  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 "openrisc_cpudev.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 struct _loaderparams {
>> +    uint64_t ram_size;
>> +    const char *kernel_filename;
>> +    const char *kernel_cmdline;
>> +    const char *initrd_filename;
>> +} loaderparams;
>> +
>> +static void main_cpu_reset(void *opaque)
>> +{
>> +    CPUOpenRISCState *env = opaque;
>> +    cpu_reset(ENV_GET_CPU(env));
>> +}
>> +
>> +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 uint64_t openrisc_load_kernel(void)
>> +{
>> +    long kernel_size;
>> +    uint64_t elf_entry;
>> +    target_phys_addr_t entry;
>> +
>> +    if (loaderparams.kernel_filename && !qtest_enabled()) {
>> +        kernel_size = load_elf(loaderparams.kernel_filename, NULL, NULL,
>> +                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
>> +        entry = elf_entry;
>> +        if (kernel_size < 0) {
>> +            kernel_size = load_uimage(loaderparams.kernel_filename,
>> +                                      &entry, NULL, NULL);
>> +        }
>> +        if (kernel_size < 0) {
>> +            kernel_size = load_image_targphys(loaderparams.kernel_filename,
>> +                                              KERNEL_LOAD_ADDR,
>> +                                              ram_size - KERNEL_LOAD_ADDR);
>> +            entry = KERNEL_LOAD_ADDR;
>> +        }
>> +        if (kernel_size < 0) {
>> +            fprintf(stderr, "qemu: could not load kernel '%s'\n",
>> +                    loaderparams.kernel_filename);
>> +            exit(1);
>> +        }
>> +
>> +        if (kernel_size > 0) {
>> +            return elf_entry;
>> +        }
>
> Hi Jia,
>
> This seems a little weird. What happens here when it successfully
> loads a uimage or raw image? It returns the elf_entry (probably == 0)
> as the load address?
>

Thank you for pointing this.
I copy this file from dummy_m68k.c without fully understood, my fault.

Is this code OK?

static uint64_t openrisc_load_kernel(void)
{
    long kernel_size;
    uint64_t elf_entry;
    target_phys_addr_t entry;

    if (loaderparams.kernel_filename && !qtest_enabled()) {
        kernel_size = load_uimage(loaderparams.kernel_filename,
                                  &entry, NULL, NULL);
        if (kernel_size < 0) {
            kernel_size = load_elf(loaderparams.kernel_filename, NULL, NULL,
                                   &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
            entry = elf_entry;
        }

        if (kernel_size < 0) {
            fprintf(stderr, "QEMU: couldn't load the kernel '%s'\n",
                    loaderparams.kernel_filename);
            exit(1);
        }
    }

    return entry;
}


> Regards,
> Peter
>
>> +    } else {
>> +        entry = 0;
>> +    }
>> +
>> +    return entry;
>> +}
>> +
>> +static void openrisc_sim_init(ram_addr_t ram_size,
>> +                              const char *boot_device,
>> +                              const char *kernel_filename,
>> +                              const char *kernel_cmdline,
>> +                              const char *initrd_filename,
>> +                              const char *cpu_model)
>> +{
>> +    CPUOpenRISCState *env;
>> +    MemoryRegion *ram = g_new(MemoryRegion, 1);
>> +
>> +    if (!cpu_model) {
>> +        cpu_model = "or1200";
>> +    }
>> +    env = cpu_init(cpu_model);
>> +    if (!env) {
>> +        fprintf(stderr, "Unable to find CPU definition!\n");
>> +        exit(1);
>> +    }
>> +
>> +    qemu_register_reset(main_cpu_reset, env);
>> +    main_cpu_reset(env);
>> +
>> +    memory_region_init_ram(ram, "openrisc.ram", ram_size);
>> +    memory_region_add_subregion(get_system_memory(), 0, ram);
>> +
>> +    if (kernel_filename) {
>> +        loaderparams.ram_size = ram_size;
>> +        loaderparams.kernel_filename = kernel_filename;
>> +        loaderparams.kernel_cmdline = kernel_cmdline;
>> +        env->pc = openrisc_load_kernel();
>> +    }
>> +
>> +    cpu_openrisc_pic_init(env);
>> +    cpu_openrisc_clock_init(env);
>> +
>> +    serial_mm_init(get_system_memory(), 0x90000000, 0,
>> +                   env->irq[2], 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
>> +
>> +    if (nd_table[0].vlan) {
>> +        openrisc_sim_net_init(get_system_memory(), 0x92000000,
>> +                              0x92000400, env->irq[4], nd_table);
>> +    }
>> +}
>> +
>> +static QEMUMachine openrisc_sim_machine = {
>> +    .name = "or32-sim",
>> +    .desc = "or32 simulation",
>> +    .init = openrisc_sim_init,
>> +    .max_cpus = 1,
>> +    .is_default = 1,
>> +};
>> +
>> +static void openrisc_sim_machine_init(void)
>> +{
>> +    qemu_register_machine(&openrisc_sim_machine);
>> +}
>> +
>> +machine_init(openrisc_sim_machine_init);
>> --
>> 1.7.9.5
>>
>>

Regards,
Jia.

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

* Re: [Qemu-devel] [PATCH v6 11/16] target-or32: Add a IIS dummy board
  2012-06-25  2:23     ` Jia Liu
@ 2012-06-25  2:33       ` Peter Crosthwaite
  0 siblings, 0 replies; 25+ messages in thread
From: Peter Crosthwaite @ 2012-06-25  2:33 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Mon, Jun 25, 2012 at 12:23 PM, Jia Liu <proljc@gmail.com> wrote:
> Hi Peter,
>
> On Thu, Jun 21, 2012 at 5:03 PM, Peter Crosthwaite
> <peter.crosthwaite@petalogix.com> wrote:
>> On Thu, Jun 21, 2012 at 12:58 PM, Jia Liu <proljc@gmail.com> wrote:
>>> Add a IIS dummy board.
>>>
>>> Signed-off-by: Jia Liu <proljc@gmail.com>
>>> ---
>>>  hw/openrisc/Makefile.objs |    2 +-
>>>  hw/openrisc_sim.c         |  160 +++++++++++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 161 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..892c67f
>>> --- /dev/null
>>> +++ b/hw/openrisc_sim.c
>>> @@ -0,0 +1,160 @@
>>> +/*
>>> + *  OpenRISC simulator for use as an ISS.
>>> + *
>>> + *  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 "openrisc_cpudev.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 struct _loaderparams {
>>> +    uint64_t ram_size;
>>> +    const char *kernel_filename;
>>> +    const char *kernel_cmdline;
>>> +    const char *initrd_filename;
>>> +} loaderparams;
>>> +
>>> +static void main_cpu_reset(void *opaque)
>>> +{
>>> +    CPUOpenRISCState *env = opaque;
>>> +    cpu_reset(ENV_GET_CPU(env));
>>> +}
>>> +
>>> +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 uint64_t openrisc_load_kernel(void)
>>> +{
>>> +    long kernel_size;
>>> +    uint64_t elf_entry;
>>> +    target_phys_addr_t entry;
>>> +
>>> +    if (loaderparams.kernel_filename && !qtest_enabled()) {
>>> +        kernel_size = load_elf(loaderparams.kernel_filename, NULL, NULL,
>>> +                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
>>> +        entry = elf_entry;
>>> +        if (kernel_size < 0) {
>>> +            kernel_size = load_uimage(loaderparams.kernel_filename,
>>> +                                      &entry, NULL, NULL);
>>> +        }
>>> +        if (kernel_size < 0) {
>>> +            kernel_size = load_image_targphys(loaderparams.kernel_filename,
>>> +                                              KERNEL_LOAD_ADDR,
>>> +                                              ram_size - KERNEL_LOAD_ADDR);
>>> +            entry = KERNEL_LOAD_ADDR;
>>> +        }
>>> +        if (kernel_size < 0) {
>>> +            fprintf(stderr, "qemu: could not load kernel '%s'\n",
>>> +                    loaderparams.kernel_filename);
>>> +            exit(1);
>>> +        }
>>> +
>>> +        if (kernel_size > 0) {
>>> +            return elf_entry;
>>> +        }
>>
>> Hi Jia,
>>
>> This seems a little weird. What happens here when it successfully
>> loads a uimage or raw image? It returns the elf_entry (probably == 0)
>> as the load address?
>>
>
> Thank you for pointing this.
> I copy this file from dummy_m68k.c without fully understood, my fault.
>
> Is this code OK?
>

Yep, Looks better.

Regards,
Peter

> static uint64_t openrisc_load_kernel(void)
> {
>    long kernel_size;
>    uint64_t elf_entry;
>    target_phys_addr_t entry;
>
>    if (loaderparams.kernel_filename && !qtest_enabled()) {
>        kernel_size = load_uimage(loaderparams.kernel_filename,
>                                  &entry, NULL, NULL);
>        if (kernel_size < 0) {
>            kernel_size = load_elf(loaderparams.kernel_filename, NULL, NULL,
>                                   &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
>            entry = elf_entry;
>        }
>
>        if (kernel_size < 0) {
>            fprintf(stderr, "QEMU: couldn't load the kernel '%s'\n",
>                    loaderparams.kernel_filename);
>            exit(1);
>        }
>    }
>
>    return entry;
> }
>
>
>> Regards,
>> Peter
>>
>>> +    } else {
>>> +        entry = 0;
>>> +    }
>>> +
>>> +    return entry;
>>> +}
>>> +
>>> +static void openrisc_sim_init(ram_addr_t ram_size,
>>> +                              const char *boot_device,
>>> +                              const char *kernel_filename,
>>> +                              const char *kernel_cmdline,
>>> +                              const char *initrd_filename,
>>> +                              const char *cpu_model)
>>> +{
>>> +    CPUOpenRISCState *env;
>>> +    MemoryRegion *ram = g_new(MemoryRegion, 1);
>>> +
>>> +    if (!cpu_model) {
>>> +        cpu_model = "or1200";
>>> +    }
>>> +    env = cpu_init(cpu_model);
>>> +    if (!env) {
>>> +        fprintf(stderr, "Unable to find CPU definition!\n");
>>> +        exit(1);
>>> +    }
>>> +
>>> +    qemu_register_reset(main_cpu_reset, env);
>>> +    main_cpu_reset(env);
>>> +
>>> +    memory_region_init_ram(ram, "openrisc.ram", ram_size);
>>> +    memory_region_add_subregion(get_system_memory(), 0, ram);
>>> +
>>> +    if (kernel_filename) {
>>> +        loaderparams.ram_size = ram_size;
>>> +        loaderparams.kernel_filename = kernel_filename;
>>> +        loaderparams.kernel_cmdline = kernel_cmdline;
>>> +        env->pc = openrisc_load_kernel();
>>> +    }
>>> +
>>> +    cpu_openrisc_pic_init(env);
>>> +    cpu_openrisc_clock_init(env);
>>> +
>>> +    serial_mm_init(get_system_memory(), 0x90000000, 0,
>>> +                   env->irq[2], 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
>>> +
>>> +    if (nd_table[0].vlan) {
>>> +        openrisc_sim_net_init(get_system_memory(), 0x92000000,
>>> +                              0x92000400, env->irq[4], nd_table);
>>> +    }
>>> +}
>>> +
>>> +static QEMUMachine openrisc_sim_machine = {
>>> +    .name = "or32-sim",
>>> +    .desc = "or32 simulation",
>>> +    .init = openrisc_sim_init,
>>> +    .max_cpus = 1,
>>> +    .is_default = 1,
>>> +};
>>> +
>>> +static void openrisc_sim_machine_init(void)
>>> +{
>>> +    qemu_register_machine(&openrisc_sim_machine);
>>> +}
>>> +
>>> +machine_init(openrisc_sim_machine_init);
>>> --
>>> 1.7.9.5
>>>
>>>
>
> Regards,
> Jia.

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

* Re: [Qemu-devel] [PATCH v6 08/16] target-or32: Add instruction tanslation
  2012-06-21 10:24   ` Max Filippov
@ 2012-06-25  2:50     ` Jia Liu
  0 siblings, 0 replies; 25+ messages in thread
From: Jia Liu @ 2012-06-25  2:50 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

Hi Max,

On Thu, Jun 21, 2012 at 6:24 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> On Thu, Jun 21, 2012 at 6:58 AM, Jia Liu <proljc@gmail.com> wrote:
>> Add OpenRISC instruction tanslation routines.
>>
>> Signed-off-by: Jia Liu <proljc@gmail.com>
>
> [...]
>
>> +    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();
>> +                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_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0);
>> +                    tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
>> +                    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],
>> +                                       0xffffffff, lab2);
>> +                    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb],
>> +                                       0x80000000, 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, lab2);
>
> Causes host division by zero/overflow. I'd suggest to brcond to lab3 set after
> the final tcg_gen_div.

Causes host division by zero/overflow? Can I handle the host code? I'm
confused about this.
May I get more comment about this? Sorry I didn't understand it.

>
>> +                    gen_exception(dc, EXCP_RANGE);
>> +                    gen_set_label(lab2);
>> +                    tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
>> +                }
>> +                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();
>> +                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, lab1);
>
> Ditto.
>
>> +                    gen_exception(dc, EXCP_RANGE);
>> +                    gen_set_label(lab1);
>> +                    tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
>> +                }
>> +                tcg_temp_free_i32(sr_ove);
>> +            }
>> +            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_new();
>
> Need to be temp_local to survive brcond.
>

Thank you, fixed.

>> +                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;
>
> [...]
>
> --
> Thanks.
> -- Max

Regards,
Jia.

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

end of thread, other threads:[~2012-06-25  2:50 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-21  2:57 [Qemu-devel] [PATCH v6 00/16] QEMU OpenRISC support Jia Liu
2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 01/16] target-or32: Add target stubs and cpu support Jia Liu
2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 02/16] target-or32: Add target machine Jia Liu
2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 03/16] target-or32: Add MMU support Jia Liu
2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 04/16] target-or32: Add interrupt support Jia Liu
2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 05/16] target-or32: Add exception support Jia Liu
2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 06/16] target-or32: Add int instruction helpers Jia Liu
2012-06-21  2:57 ` [Qemu-devel] [PATCH v6 07/16] target-or32: Add float " Jia Liu
2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 08/16] target-or32: Add instruction tanslation Jia Liu
2012-06-21 10:24   ` Max Filippov
2012-06-25  2:50     ` Jia Liu
2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 09/16] target-or32: Add PIC support Jia Liu
2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 10/16] target-or32: Add timer support Jia Liu
2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 11/16] target-or32: Add a IIS dummy board Jia Liu
2012-06-21  8:19   ` 陳韋任 (Wei-Ren Chen)
2012-06-21  9:10     ` Max Filippov
2012-06-21  9:11     ` Jia Liu
2012-06-21  9:03   ` Peter Crosthwaite
2012-06-25  2:23     ` Jia Liu
2012-06-25  2:33       ` Peter Crosthwaite
2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 12/16] target-or32: Add system instructions Jia Liu
2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 13/16] target-or32: Add gdb stub Jia Liu
2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 14/16] target-or32: Add linux syscall, signal and termbits Jia Liu
2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 15/16] target-or32: Add linux user support Jia Liu
2012-06-21  2:58 ` [Qemu-devel] [PATCH v6 16/16] target-or32: Add testcases Jia Liu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.