All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture
@ 2011-09-01 20:45 Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 01/32] target-xtensa: add target stubs Max Filippov
                   ` (32 more replies)
  0 siblings, 33 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

This series adds support for Tensilica Xtensa target.
Port status: Linux for DC232B works in the qemu.
  Not implemented xtensa options: MAC16, floating point coprocessor,
  boolean option, cache option, debug option.

v3 -> v4 changes:
- fix usage of type names ending with _t;
- fix usage of identifiers starting with _[A-Z].

Git tree is available at git://jcmvbkbc.spb.ru/dumb/qemu-xtensa.git xtensa

Max Filippov (32):
  target-xtensa: add target stubs
  target-xtensa: add target to the configure script
  target-xtensa: implement disas_xtensa_insn
  target-xtensa: implement narrow instructions
  target-xtensa: implement RT0 group
  target-xtensa: add sample board
  target-xtensa: implement conditional jumps
  target-xtensa: implement JX/RET0/CALLX
  target-xtensa: add special and user registers
  target-xtensa: implement RST3 group
  target-xtensa: implement shifts (ST1 and RST1 groups)
  target-xtensa: implement LSAI group
  target-xtensa: mark reserved and TBD opcodes
  target-xtensa: implement SYNC group
  target-xtensa: implement CACHE group
  target-xtensa: add PS register and access control
  target-xtensa: implement exceptions
  target-xtensa: implement RST2 group (32 bit mul/div/rem)
  target-xtensa: implement windowed registers
  target-xtensa: implement loop option
  target-xtensa: implement extended L32R
  target-xtensa: implement unaligned exception option
  target-xtensa: implement SIMCALL
  target-xtensa: implement interrupt option
  target-xtensa: implement accurate window check
  target-xtensa: implement CPENABLE and PRID SRs
  target-xtensa: implement relocatable vectors
  target-xtensa: add gdb support
  target-xtensa: implement memory protection options
  target-xtensa: add dc232b core and board
  MAINTAINERS: add xtensa maintainer
  target-xtensa: add regression testsuite

 MAINTAINERS                                   |   13 +
 Makefile.target                               |    5 +
 arch_init.c                                   |    2 +
 arch_init.h                                   |    1 +
 configure                                     |   12 +-
 cpu-exec.c                                    |    8 +
 default-configs/xtensa-softmmu.mak            |    1 +
 default-configs/xtensaeb-softmmu.mak          |    1 +
 elf.h                                         |    2 +
 gdbstub.c                                     |   96 +
 hw/xtensa_dc232b.c                            |  112 ++
 hw/xtensa_pic.c                               |  134 ++
 hw/xtensa_sample.c                            |  106 ++
 qemu-options.hx                               |    4 +-
 target-xtensa/cpu.h                           |  424 +++++
 target-xtensa/gdb-config-dc232b.c             |  261 +++
 target-xtensa/gdb-config-sample-xtensa-core.c |  375 ++++
 target-xtensa/helper.c                        |  763 ++++++++
 target-xtensa/helpers.h                       |   32 +
 target-xtensa/machine.c                       |   38 +
 target-xtensa/op_helper.c                     |  668 +++++++
 target-xtensa/translate.c                     | 2349 +++++++++++++++++++++++++
 tests/xtensa/Makefile                         |   72 +
 tests/xtensa/crt.S                            |   24 +
 tests/xtensa/linker.ld                        |  113 ++
 tests/xtensa/macros.inc                       |   68 +
 tests/xtensa/test_b.S                         |  221 +++
 tests/xtensa/test_bi.S                        |  103 ++
 tests/xtensa/test_bz.S                        |   57 +
 tests/xtensa/test_clamps.S                    |   42 +
 tests/xtensa/test_fail.S                      |    9 +
 tests/xtensa/test_interrupt.S                 |  194 ++
 tests/xtensa/test_loop.S                      |   77 +
 tests/xtensa/test_max.S                       |   81 +
 tests/xtensa/test_min.S                       |   81 +
 tests/xtensa/test_mmu.S                       |  318 ++++
 tests/xtensa/test_mul16.S                     |   83 +
 tests/xtensa/test_mul32.S                     |   20 +
 tests/xtensa/test_nsa.S                       |   59 +
 tests/xtensa/test_pipeline.S                  |  157 ++
 tests/xtensa/test_quo.S                       |  147 ++
 tests/xtensa/test_rem.S                       |  147 ++
 tests/xtensa/test_rst0.S                      |  148 ++
 tests/xtensa/test_sar.S                       |  111 ++
 tests/xtensa/test_sext.S                      |   69 +
 tests/xtensa/test_shift.S                     |  206 +++
 tests/xtensa/test_timer.S                     |  115 ++
 tests/xtensa/test_windowed.S                  |  302 ++++
 tests/xtensa/vectors.S                        |   39 +
 xtensa-semi.c                                 |  224 +++
 50 files changed, 8691 insertions(+), 3 deletions(-)
 create mode 100644 default-configs/xtensa-softmmu.mak
 create mode 100644 default-configs/xtensaeb-softmmu.mak
 create mode 100644 hw/xtensa_dc232b.c
 create mode 100644 hw/xtensa_pic.c
 create mode 100644 hw/xtensa_sample.c
 create mode 100644 target-xtensa/cpu.h
 create mode 100644 target-xtensa/gdb-config-dc232b.c
 create mode 100644 target-xtensa/gdb-config-sample-xtensa-core.c
 create mode 100644 target-xtensa/helper.c
 create mode 100644 target-xtensa/helpers.h
 create mode 100644 target-xtensa/machine.c
 create mode 100644 target-xtensa/op_helper.c
 create mode 100644 target-xtensa/translate.c
 create mode 100644 tests/xtensa/Makefile
 create mode 100644 tests/xtensa/crt.S
 create mode 100644 tests/xtensa/linker.ld
 create mode 100644 tests/xtensa/macros.inc
 create mode 100644 tests/xtensa/test_b.S
 create mode 100644 tests/xtensa/test_bi.S
 create mode 100644 tests/xtensa/test_bz.S
 create mode 100644 tests/xtensa/test_clamps.S
 create mode 100644 tests/xtensa/test_fail.S
 create mode 100644 tests/xtensa/test_interrupt.S
 create mode 100644 tests/xtensa/test_loop.S
 create mode 100644 tests/xtensa/test_max.S
 create mode 100644 tests/xtensa/test_min.S
 create mode 100644 tests/xtensa/test_mmu.S
 create mode 100644 tests/xtensa/test_mul16.S
 create mode 100644 tests/xtensa/test_mul32.S
 create mode 100644 tests/xtensa/test_nsa.S
 create mode 100644 tests/xtensa/test_pipeline.S
 create mode 100644 tests/xtensa/test_quo.S
 create mode 100644 tests/xtensa/test_rem.S
 create mode 100644 tests/xtensa/test_rst0.S
 create mode 100644 tests/xtensa/test_sar.S
 create mode 100644 tests/xtensa/test_sext.S
 create mode 100644 tests/xtensa/test_shift.S
 create mode 100644 tests/xtensa/test_timer.S
 create mode 100644 tests/xtensa/test_windowed.S
 create mode 100644 tests/xtensa/vectors.S
 create mode 100644 xtensa-semi.c

-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 01/32] target-xtensa: add target stubs
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-04 18:14   ` Blue Swirl
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 02/32] target-xtensa: add target to the configure script Max Filippov
                   ` (31 subsequent siblings)
  32 siblings, 1 reply; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 Makefile.target           |    2 +
 arch_init.c               |    2 +
 arch_init.h               |    1 +
 cpu-exec.c                |    2 +
 elf.h                     |    2 +
 hw/xtensa_pic.c           |   38 ++++++++++++++++++
 target-xtensa/cpu.h       |   95 +++++++++++++++++++++++++++++++++++++++++++++
 target-xtensa/helper.c    |   73 ++++++++++++++++++++++++++++++++++
 target-xtensa/machine.c   |   38 ++++++++++++++++++
 target-xtensa/op_helper.c |   52 ++++++++++++++++++++++++
 target-xtensa/translate.c |   67 +++++++++++++++++++++++++++++++
 11 files changed, 372 insertions(+), 0 deletions(-)
 create mode 100644 hw/xtensa_pic.c
 create mode 100644 target-xtensa/cpu.h
 create mode 100644 target-xtensa/helper.c
 create mode 100644 target-xtensa/machine.c
 create mode 100644 target-xtensa/op_helper.c
 create mode 100644 target-xtensa/translate.c

diff --git a/Makefile.target b/Makefile.target
index 07af4d4..b833c10 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -373,6 +373,8 @@ obj-s390x-y = s390-virtio-bus.o s390-virtio.o
 obj-alpha-y = i8259.o mc146818rtc.o
 obj-alpha-y += vga.o cirrus_vga.o
 
+obj-xtensa-y += xtensa_pic.o
+
 main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
 monitor.o: hmp-commands.h qmp-commands.h
diff --git a/arch_init.c b/arch_init.c
index 567ab32..9a5a0e3 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -78,6 +78,8 @@ const char arch_config_name[] = CONFIG_QEMU_CONFDIR "/target-" TARGET_ARCH ".con
 #define QEMU_ARCH QEMU_ARCH_SH4
 #elif defined(TARGET_SPARC)
 #define QEMU_ARCH QEMU_ARCH_SPARC
+#elif defined(TARGET_XTENSA)
+#define QEMU_ARCH QEMU_ARCH_XTENSA
 #endif
 
 const uint32_t arch_type = QEMU_ARCH;
diff --git a/arch_init.h b/arch_init.h
index 2de9f08..a74187a 100644
--- a/arch_init.h
+++ b/arch_init.h
@@ -17,6 +17,7 @@ enum {
     QEMU_ARCH_S390X = 512,
     QEMU_ARCH_SH4 = 1024,
     QEMU_ARCH_SPARC = 2048,
+    QEMU_ARCH_XTENSA = 4096,
 };
 
 extern const uint32_t arch_type;
diff --git a/cpu-exec.c b/cpu-exec.c
index de0d716..3fce033 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -222,6 +222,7 @@ int cpu_exec(CPUState *env)
 #elif defined(TARGET_SH4)
 #elif defined(TARGET_CRIS)
 #elif defined(TARGET_S390X)
+#elif defined(TARGET_XTENSA)
     /* XXXXX */
 #else
 #error unsupported target CPU
@@ -616,6 +617,7 @@ int cpu_exec(CPUState *env)
 #elif defined(TARGET_ALPHA)
 #elif defined(TARGET_CRIS)
 #elif defined(TARGET_S390X)
+#elif defined(TARGET_XTENSA)
     /* XXXXX */
 #else
 #error unsupported target CPU
diff --git a/elf.h b/elf.h
index ffcac7e..2e05d34 100644
--- a/elf.h
+++ b/elf.h
@@ -125,6 +125,8 @@ typedef int64_t  Elf64_Sxword;
 #define EM_MICROBLAZE      189
 #define EM_MICROBLAZE_OLD  0xBAAB
 
+#define EM_XTENSA   94      /* Tensilica Xtensa */
+
 /* This is the info that is needed to parse the dynamic section of the file */
 #define DT_NULL		0
 #define DT_NEEDED	1
diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
new file mode 100644
index 0000000..91a5445
--- /dev/null
+++ b/hw/xtensa_pic.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "hw.h"
+#include "pc.h"
+
+/* Stub functions for hardware that doesn't exist.  */
+void pic_info(Monitor *mon)
+{
+}
+
+void irq_info(Monitor *mon)
+{
+}
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
new file mode 100644
index 0000000..a51ffc8
--- /dev/null
+++ b/target-xtensa/cpu.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CPU_XTENSA_H
+#define CPU_XTENSA_H
+
+#define TARGET_LONG_BITS 32
+#define ELF_MACHINE EM_XTENSA
+
+#define CPUState struct CPUXtensaState
+
+#include "config.h"
+#include "qemu-common.h"
+#include "cpu-defs.h"
+
+#define TARGET_HAS_ICE 1
+
+#define NB_MMU_MODES 4
+
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+#define TARGET_PAGE_BITS 12
+
+typedef struct CPUXtensaState {
+    uint32_t regs[16];
+    uint32_t pc;
+    uint32_t sregs[256];
+
+    CPU_COMMON
+} CPUXtensaState;
+
+#define cpu_init cpu_xtensa_init
+#define cpu_exec cpu_xtensa_exec
+#define cpu_gen_code cpu_xtensa_gen_code
+#define cpu_signal_handler cpu_xtensa_signal_handler
+#define cpu_list xtensa_cpu_list
+
+CPUXtensaState *cpu_xtensa_init(const char *cpu_model);
+void xtensa_translate_init(void);
+int cpu_xtensa_exec(CPUXtensaState *s);
+void do_interrupt(CPUXtensaState *s);
+int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
+void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
+
+static inline int cpu_mmu_index(CPUState *env)
+{
+    return 0;
+}
+
+static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+        target_ulong *cs_base, int *flags)
+{
+    *pc = env->pc;
+    *cs_base = 0;
+    *flags = 0;
+}
+
+#include "cpu-all.h"
+#include "exec-all.h"
+
+static inline int cpu_has_work(CPUState *env)
+{
+    return 1;
+}
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+    env->pc = tb->pc;
+}
+
+#endif
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
new file mode 100644
index 0000000..dc30e00
--- /dev/null
+++ b/target-xtensa/helper.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "gdbstub.h"
+#include "qemu-common.h"
+#include "host-utils.h"
+#if !defined(CONFIG_USER_ONLY)
+#include "hw/loader.h"
+#endif
+
+void cpu_reset(CPUXtensaState *env)
+{
+    env->pc = 0;
+}
+
+CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
+{
+    static int tcg_inited;
+    CPUXtensaState *env;
+
+    env = g_malloc0(sizeof(*env));
+    cpu_exec_init(env);
+
+    if (!tcg_inited) {
+        tcg_inited = 1;
+        xtensa_translate_init();
+    }
+
+    qemu_init_vcpu(env);
+    return env;
+}
+
+
+void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    cpu_fprintf(f, "Available CPUs:\n"
+            "  Xtensa core\n");
+}
+
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+{
+    return addr;
+}
+
+void do_interrupt(CPUState *env)
+{
+}
diff --git a/target-xtensa/machine.c b/target-xtensa/machine.c
new file mode 100644
index 0000000..ddeffb2
--- /dev/null
+++ b/target-xtensa/machine.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#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-xtensa/op_helper.c b/target-xtensa/op_helper.c
new file mode 100644
index 0000000..aafa33d
--- /dev/null
+++ b/target-xtensa/op_helper.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cpu.h"
+#include "dyngen-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(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
+{
+    tlb_set_page(cpu_single_env,
+            addr & ~(TARGET_PAGE_SIZE - 1),
+            addr & ~(TARGET_PAGE_SIZE - 1),
+            PAGE_READ | PAGE_WRITE | PAGE_EXEC,
+            mmu_idx, TARGET_PAGE_SIZE);
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
new file mode 100644
index 0000000..e91d8a5
--- /dev/null
+++ b/target-xtensa/translate.c
@@ -0,0 +1,67 @@
+/*
+ * Xtensa ISA:
+ * http://www.tensilica.com/products/literature-docs/documentation/xtensa-isa-databook.htm
+ *
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "disas.h"
+#include "tcg-op.h"
+#include "qemu-log.h"
+
+
+void xtensa_translate_init(void)
+{
+}
+
+void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
+{
+}
+
+void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
+{
+}
+
+void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+        int flags)
+{
+    int i;
+
+    cpu_fprintf(f, "PC=%08x\n", env->pc);
+
+    for (i = 0; i < 16; ++i)
+        cpu_fprintf(f, "A%02d=%08x%c", i, env->regs[i],
+                (i % 4) == 3 ? '\n' : ' ');
+}
+
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+{
+    env->pc = gen_opc_pc[pc_pos];
+}
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 02/32] target-xtensa: add target to the configure script
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 01/32] target-xtensa: add target stubs Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 03/32] target-xtensa: implement disas_xtensa_insn Max Filippov
                   ` (30 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 configure                            |   12 +++++++++++-
 default-configs/xtensa-softmmu.mak   |    1 +
 default-configs/xtensaeb-softmmu.mak |    1 +
 3 files changed, 13 insertions(+), 1 deletions(-)
 create mode 100644 default-configs/xtensa-softmmu.mak
 create mode 100644 default-configs/xtensaeb-softmmu.mak

diff --git a/configure b/configure
index 1340c33..fe2d4fd 100755
--- a/configure
+++ b/configure
@@ -872,6 +872,8 @@ sh4eb-softmmu \
 sparc-softmmu \
 sparc64-softmmu \
 s390x-softmmu \
+xtensa-softmmu \
+xtensaeb-softmmu \
 "
 fi
 # the following are Linux specific
@@ -3138,7 +3140,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)
+  armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
   target_bigendian=yes
   ;;
 esac
@@ -3333,6 +3335,10 @@ case "$target_arch2" in
   unicore32)
     target_phys_bits=32
   ;;
+  xtensa|xtensaeb)
+    TARGET_ARCH=xtensa
+    target_phys_bits=32
+  ;;
   *)
     echo "Unsupported target CPU"
     exit 1
@@ -3507,6 +3513,10 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
     echo "CONFIG_SPARC_DIS=y"  >> $config_target_mak
     echo "CONFIG_SPARC_DIS=y"  >> $libdis_config_mak
   ;;
+  xtensa*)
+    echo "CONFIG_XTENSA_DIS=y"  >> $config_target_mak
+    echo "CONFIG_XTENSA_DIS=y"  >> $libdis_config_mak
+  ;;
   esac
 done
 
diff --git a/default-configs/xtensa-softmmu.mak b/default-configs/xtensa-softmmu.mak
new file mode 100644
index 0000000..e5faa09
--- /dev/null
+++ b/default-configs/xtensa-softmmu.mak
@@ -0,0 +1 @@
+# Default configuration for Xtensa
diff --git a/default-configs/xtensaeb-softmmu.mak b/default-configs/xtensaeb-softmmu.mak
new file mode 100644
index 0000000..e5faa09
--- /dev/null
+++ b/default-configs/xtensaeb-softmmu.mak
@@ -0,0 +1 @@
+# Default configuration for Xtensa
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 03/32] target-xtensa: implement disas_xtensa_insn
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 01/32] target-xtensa: add target stubs Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 02/32] target-xtensa: add target to the configure script Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 04/32] target-xtensa: implement narrow instructions Max Filippov
                   ` (29 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Set up disas_xtensa_insn switch structure, mark required options on high
level groups. Implement arithmetic/bit logic/jump/call0.

Implement code generation loop with single step/breakpoint checking.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/cpu.h       |   67 +++++++
 target-xtensa/helper.c    |   27 +++-
 target-xtensa/helpers.h   |    5 +
 target-xtensa/op_helper.c |    7 +
 target-xtensa/translate.c |  452 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 556 insertions(+), 2 deletions(-)
 create mode 100644 target-xtensa/helpers.h

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index a51ffc8..c323891 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -45,7 +45,67 @@
 #define TARGET_VIRT_ADDR_SPACE_BITS 32
 #define TARGET_PAGE_BITS 12
 
+enum {
+    /* Additional instructions */
+    XTENSA_OPTION_CODE_DENSITY,
+    XTENSA_OPTION_LOOP,
+    XTENSA_OPTION_EXTENDED_L32R,
+    XTENSA_OPTION_16_BIT_IMUL,
+    XTENSA_OPTION_32_BIT_IMUL,
+    XTENSA_OPTION_32_BIT_IDIV,
+    XTENSA_OPTION_MAC16,
+    XTENSA_OPTION_MISC_OP,
+    XTENSA_OPTION_COPROCESSOR,
+    XTENSA_OPTION_BOOLEAN,
+    XTENSA_OPTION_FP_COPROCESSOR,
+    XTENSA_OPTION_MP_SYNCHRO,
+    XTENSA_OPTION_CONDITIONAL_STORE,
+
+    /* Interrupts and exceptions */
+    XTENSA_OPTION_EXCEPTION,
+    XTENSA_OPTION_RELOCATABLE_VECTOR,
+    XTENSA_OPTION_UNALIGNED_EXCEPTION,
+    XTENSA_OPTION_INTERRUPT,
+    XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+    XTENSA_OPTION_TIMER_INTERRUPT,
+
+    /* Local memory */
+    XTENSA_OPTION_ICACHE,
+    XTENSA_OPTION_ICACHE_TEST,
+    XTENSA_OPTION_ICACHE_INDEX_LOCK,
+    XTENSA_OPTION_DCACHE,
+    XTENSA_OPTION_DCACHE_TEST,
+    XTENSA_OPTION_DCACHE_INDEX_LOCK,
+    XTENSA_OPTION_IRAM,
+    XTENSA_OPTION_IROM,
+    XTENSA_OPTION_DRAM,
+    XTENSA_OPTION_DROM,
+    XTENSA_OPTION_XLMI,
+    XTENSA_OPTION_HW_ALIGNMENT,
+    XTENSA_OPTION_MEMORY_ECC_PARITY,
+
+    /* Memory protection and translation */
+    XTENSA_OPTION_REGION_PROTECTION,
+    XTENSA_OPTION_REGION_TRANSLATION,
+    XTENSA_OPTION_MMU,
+
+    /* Other */
+    XTENSA_OPTION_WINDOWED_REGISTER,
+    XTENSA_OPTION_PROCESSOR_INTERFACE,
+    XTENSA_OPTION_MISC_SR,
+    XTENSA_OPTION_THREAD_POINTER,
+    XTENSA_OPTION_PROCESSOR_ID,
+    XTENSA_OPTION_DEBUG,
+    XTENSA_OPTION_TRACE_PORT,
+};
+
+typedef struct XtensaConfig {
+    const char *name;
+    uint64_t options;
+} XtensaConfig;
+
 typedef struct CPUXtensaState {
+    const XtensaConfig *config;
     uint32_t regs[16];
     uint32_t pc;
     uint32_t sregs[256];
@@ -66,6 +126,13 @@ void do_interrupt(CPUXtensaState *s);
 int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
 void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 
+#define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
+
+static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt)
+{
+    return (config->options & XTENSA_OPTION_BIT(opt)) != 0;
+}
+
 static inline int cpu_mmu_index(CPUState *env)
 {
     return 0;
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index dc30e00..c119fd0 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -39,12 +39,32 @@ void cpu_reset(CPUXtensaState *env)
     env->pc = 0;
 }
 
+static const XtensaConfig core_config[] = {
+    {
+        .name = "sample-xtensa-core",
+        .options = -1,
+    },
+};
+
 CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
 {
     static int tcg_inited;
     CPUXtensaState *env;
+    const XtensaConfig *config = NULL;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(core_config); ++i)
+        if (strcmp(core_config[i].name, cpu_model) == 0) {
+            config = core_config + i;
+            break;
+        }
+
+    if (config == NULL) {
+        return NULL;
+    }
 
     env = g_malloc0(sizeof(*env));
+    env->config = config;
     cpu_exec_init(env);
 
     if (!tcg_inited) {
@@ -59,8 +79,11 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
 
 void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf)
 {
-    cpu_fprintf(f, "Available CPUs:\n"
-            "  Xtensa core\n");
+    int i;
+    cpu_fprintf(f, "Available CPUs:\n");
+    for (i = 0; i < ARRAY_SIZE(core_config); ++i) {
+        cpu_fprintf(f, "  %s\n", core_config[i].name);
+    }
 }
 
 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
new file mode 100644
index 0000000..c298d74
--- /dev/null
+++ b/target-xtensa/helpers.h
@@ -0,0 +1,5 @@
+#include "def-helper.h"
+
+DEF_HELPER_1(exception, void, i32)
+
+#include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index aafa33d..0392fbe 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -27,6 +27,7 @@
 
 #include "cpu.h"
 #include "dyngen-exec.h"
+#include "helpers.h"
 
 #define MMUSUFFIX _mmu
 
@@ -50,3 +51,9 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
             PAGE_READ | PAGE_WRITE | PAGE_EXEC,
             mmu_idx, TARGET_PAGE_SIZE);
 }
+
+void HELPER(exception)(uint32_t excp)
+{
+    env->exception_index = excp;
+    cpu_loop_exit(env);
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index e91d8a5..83d8837 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -36,17 +36,469 @@
 #include "tcg-op.h"
 #include "qemu-log.h"
 
+#include "helpers.h"
+#define GEN_HELPER 1
+#include "helpers.h"
+
+typedef struct DisasContext {
+    const XtensaConfig *config;
+    TranslationBlock *tb;
+    uint32_t pc;
+    uint32_t next_pc;
+    int is_jmp;
+    int singlestep_enabled;
+} DisasContext;
+
+static TCGv_ptr cpu_env;
+static TCGv_i32 cpu_pc;
+static TCGv_i32 cpu_R[16];
+
+#include "gen-icount.h"
 
 void xtensa_translate_init(void)
 {
+    static const char * const regnames[] = {
+        "ar0", "ar1", "ar2", "ar3",
+        "ar4", "ar5", "ar6", "ar7",
+        "ar8", "ar9", "ar10", "ar11",
+        "ar12", "ar13", "ar14", "ar15",
+    };
+    int i;
+
+    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
+            offsetof(CPUState, pc), "pc");
+
+    for (i = 0; i < 16; i++) {
+        cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
+                offsetof(CPUState, regs[i]),
+                regnames[i]);
+    }
+#define GEN_HELPER 2
+#include "helpers.h"
+}
+
+static inline bool option_enabled(DisasContext *dc, int opt)
+{
+    return xtensa_option_enabled(dc->config, opt);
+}
+
+static void gen_exception(int excp)
+{
+    TCGv_i32 tmp = tcg_const_i32(excp);
+    gen_helper_exception(tmp);
+    tcg_temp_free(tmp);
+}
+
+static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
+{
+    tcg_gen_mov_i32(cpu_pc, dest);
+    if (dc->singlestep_enabled) {
+        gen_exception(EXCP_DEBUG);
+    } else {
+        if (slot >= 0) {
+            tcg_gen_goto_tb(slot);
+            tcg_gen_exit_tb((tcg_target_long)dc->tb + slot);
+        } else {
+            tcg_gen_exit_tb(0);
+        }
+    }
+    dc->is_jmp = DISAS_UPDATE;
+}
+
+static void gen_jumpi(DisasContext *dc, uint32_t dest, int slot)
+{
+    TCGv_i32 tmp = tcg_const_i32(dest);
+    if (((dc->pc ^ dest) & TARGET_PAGE_MASK) != 0) {
+        slot = -1;
+    }
+    gen_jump_slot(dc, tmp, slot);
+    tcg_temp_free(tmp);
+}
+
+static void disas_xtensa_insn(DisasContext *dc)
+{
+#define HAS_OPTION(opt) do { \
+        if (!option_enabled(dc, opt)) { \
+            qemu_log("Option %d is not enabled %s:%d\n", \
+                    (opt), __FILE__, __LINE__); \
+            goto invalid_opcode; \
+        } \
+    } while (0)
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define OP0 (((_b0) & 0xf0) >> 4)
+#define OP1 (((_b2) & 0xf0) >> 4)
+#define OP2 ((_b2) & 0xf)
+#define RRR_R ((_b1) & 0xf)
+#define RRR_S (((_b1) & 0xf0) >> 4)
+#define RRR_T ((_b0) & 0xf)
+#else
+#define OP0 (((_b0) & 0xf))
+#define OP1 (((_b2) & 0xf))
+#define OP2 (((_b2) & 0xf0) >> 4)
+#define RRR_R (((_b1) & 0xf0) >> 4)
+#define RRR_S (((_b1) & 0xf))
+#define RRR_T (((_b0) & 0xf0) >> 4)
+#endif
+
+#define RRRN_R RRR_R
+#define RRRN_S RRR_S
+#define RRRN_T RRR_T
+
+#define RRI8_R RRR_R
+#define RRI8_S RRR_S
+#define RRI8_T RRR_T
+#define RRI8_IMM8 (_b2)
+#define RRI8_IMM8_SE ((((_b2) & 0x80) ? 0xffffff00 : 0) | RRI8_IMM8)
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define RI16_IMM16 (((_b1) << 8) | (_b2))
+#else
+#define RI16_IMM16 (((_b2) << 8) | (_b1))
+#endif
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define CALL_N (((_b0) & 0xc) >> 2)
+#define CALL_OFFSET ((((_b0) & 0x3) << 16) | ((_b1) << 8) | (_b2))
+#else
+#define CALL_N (((_b0) & 0x30) >> 4)
+#define CALL_OFFSET ((((_b0) & 0xc0) >> 6) | ((_b1) << 2) | ((_b2) << 10))
+#endif
+#define CALL_OFFSET_SE \
+    (((CALL_OFFSET & 0x20000) ? 0xfffc0000 : 0) | CALL_OFFSET)
+
+#define CALLX_N CALL_N
+#ifdef TARGET_WORDS_BIGENDIAN
+#define CALLX_M ((_b0) & 0x3)
+#else
+#define CALLX_M (((_b0) & 0xc0) >> 6)
+#endif
+#define CALLX_S RRR_S
+
+#define BRI12_M CALLX_M
+#define BRI12_S RRR_S
+#ifdef TARGET_WORDS_BIGENDIAN
+#define BRI12_IMM12 ((((_b1) & 0xf) << 8) | (_b2))
+#else
+#define BRI12_IMM12 ((((_b1) & 0xf0) >> 4) | ((_b2) << 4))
+#endif
+#define BRI12_IMM12_SE (((BRI12_IMM12 & 0x800) ? 0xfffff000 : 0) | BRI12_IMM12)
+
+#define BRI8_M BRI12_M
+#define BRI8_R RRI8_R
+#define BRI8_S RRI8_S
+#define BRI8_IMM8 RRI8_IMM8
+#define BRI8_IMM8_SE RRI8_IMM8_SE
+
+#define RSR_SR (_b1)
+
+    uint8_t _b0 = ldub_code(dc->pc);
+    uint8_t _b1 = ldub_code(dc->pc + 1);
+    uint8_t _b2 = ldub_code(dc->pc + 2);
+
+    if (OP0 >= 8) {
+        dc->next_pc = dc->pc + 2;
+        HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
+    } else {
+        dc->next_pc = dc->pc + 3;
+    }
+
+    switch (OP0) {
+    case 0: /*QRST*/
+        switch (OP1) {
+        case 0: /*RST0*/
+            switch (OP2) {
+            case 0: /*ST0*/
+                if ((RRR_R & 0xc) == 0x8) {
+                    HAS_OPTION(XTENSA_OPTION_BOOLEAN);
+                }
+
+                switch (RRR_R) {
+                case 0: /*SNM0*/
+                    break;
+
+                case 1: /*MOVSPw*/
+                    HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                    break;
+
+                case 2: /*SYNC*/
+                    break;
+
+                case 3:
+                    break;
+
+                }
+                break;
+
+            case 1: /*AND*/
+                tcg_gen_and_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                break;
+
+            case 2: /*OR*/
+                tcg_gen_or_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                break;
+
+            case 3: /*XOR*/
+                tcg_gen_xor_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                break;
+
+            case 4: /*ST1*/
+                break;
+
+            case 5: /*TLB*/
+                break;
+
+            case 6: /*RT0*/
+                break;
+
+            case 7: /*reserved*/
+                break;
+
+            case 8: /*ADD*/
+                tcg_gen_add_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                break;
+
+            case 9: /*ADD**/
+            case 10:
+            case 11:
+                {
+                    TCGv_i32 tmp = tcg_temp_new_i32();
+                    tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 8);
+                    tcg_gen_add_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]);
+                    tcg_temp_free(tmp);
+                }
+                break;
+
+            case 12: /*SUB*/
+                tcg_gen_sub_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                break;
+
+            case 13: /*SUB**/
+            case 14:
+            case 15:
+                {
+                    TCGv_i32 tmp = tcg_temp_new_i32();
+                    tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 12);
+                    tcg_gen_sub_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]);
+                    tcg_temp_free(tmp);
+                }
+                break;
+            }
+            break;
+
+        case 1: /*RST1*/
+            break;
+
+        case 2: /*RST2*/
+            break;
+
+        case 3: /*RST3*/
+            break;
+
+        case 4: /*EXTUI*/
+        case 5:
+            break;
+
+        case 6: /*CUST0*/
+            break;
+
+        case 7: /*CUST1*/
+            break;
+
+        case 8: /*LSCXp*/
+            HAS_OPTION(XTENSA_OPTION_COPROCESSOR);
+            break;
+
+        case 9: /*LSC4*/
+            break;
+
+        case 10: /*FP0*/
+            HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
+            break;
+
+        case 11: /*FP1*/
+            HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
+            break;
+
+        default: /*reserved*/
+            break;
+        }
+        break;
+
+    case 1: /*L32R*/
+        {
+            TCGv_i32 tmp = tcg_const_i32(
+                    (0xfffc0000 | (RI16_IMM16 << 2)) +
+                    ((dc->pc + 3) & ~3));
+
+            /* no ext L32R */
+
+            tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, 0);
+            tcg_temp_free(tmp);
+        }
+        break;
+
+    case 2: /*LSAI*/
+        break;
+
+    case 3: /*LSCIp*/
+        HAS_OPTION(XTENSA_OPTION_COPROCESSOR);
+        break;
+
+    case 4: /*MAC16d*/
+        HAS_OPTION(XTENSA_OPTION_MAC16);
+        break;
+
+    case 5: /*CALLN*/
+        switch (CALL_N) {
+        case 0: /*CALL0*/
+            tcg_gen_movi_i32(cpu_R[0], dc->next_pc);
+            gen_jumpi(dc, (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0);
+            break;
+
+        case 1: /*CALL4w*/
+        case 2: /*CALL8w*/
+        case 3: /*CALL12w*/
+            HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+            break;
+        }
+        break;
+
+    case 6: /*SI*/
+        switch (CALL_N) {
+        case 0: /*J*/
+            gen_jumpi(dc, dc->pc + 4 + CALL_OFFSET_SE, 0);
+            break;
+
+        }
+        break;
+
+    case 7: /*B*/
+        break;
+
+    case 8: /*L32I.Nn*/
+        break;
+
+    case 9: /*S32I.Nn*/
+        break;
+
+    case 10: /*ADD.Nn*/
+        break;
+
+    case 11: /*ADDI.Nn*/
+        break;
+
+    case 12: /*ST2n*/
+        break;
+
+    case 13: /*ST3n*/
+        break;
+
+    default: /*reserved*/
+        break;
+    }
+
+    dc->pc = dc->next_pc;
+    return;
+
+invalid_opcode:
+    qemu_log("INVALID(pc = %08x)\n", dc->pc);
+    dc->pc = dc->next_pc;
+#undef HAS_OPTION
+}
+
+static void check_breakpoint(CPUState *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_i32(cpu_pc, dc->pc);
+                gen_exception(EXCP_DEBUG);
+                dc->is_jmp = DISAS_UPDATE;
+             }
+        }
+    }
+}
+
+static void gen_intermediate_code_internal(
+        CPUState *env, TranslationBlock *tb, int search_pc)
+{
+    DisasContext dc;
+    int insn_count = 0;
+    int j, lj = -1;
+    uint16_t *gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    int max_insns = tb->cflags & CF_COUNT_MASK;
+    uint32_t pc_start = tb->pc;
+    uint32_t next_page_start =
+        (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+
+    if (max_insns == 0) {
+        max_insns = CF_COUNT_MASK;
+    }
+
+    dc.config = env->config;
+    dc.singlestep_enabled = env->singlestep_enabled;
+    dc.tb = tb;
+    dc.pc = pc_start;
+    dc.is_jmp = DISAS_NEXT;
+
+    gen_icount_start();
+
+    do {
+        check_breakpoint(env, &dc);
+
+        if (search_pc) {
+            j = gen_opc_ptr - gen_opc_buf;
+            if (lj < j) {
+                lj++;
+                while (lj < j) {
+                    gen_opc_instr_start[lj++] = 0;
+                }
+            }
+            gen_opc_pc[lj] = dc.pc;
+            gen_opc_instr_start[lj] = 1;
+            gen_opc_icount[lj] = insn_count;
+        }
+
+        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
+            tcg_gen_debug_insn_start(dc.pc);
+        }
+
+        disas_xtensa_insn(&dc);
+        ++insn_count;
+        if (env->singlestep_enabled) {
+            tcg_gen_movi_i32(cpu_pc, dc.pc);
+            gen_exception(EXCP_DEBUG);
+            break;
+        }
+    } while (dc.is_jmp == DISAS_NEXT &&
+            insn_count < max_insns &&
+            dc.pc < next_page_start &&
+            gen_opc_ptr < gen_opc_end);
+
+    if (dc.is_jmp == DISAS_NEXT) {
+        gen_jumpi(&dc, dc.pc, 0);
+    }
+    gen_icount_end(tb, insn_count);
+    *gen_opc_ptr = INDEX_op_end;
+
+    if (!search_pc) {
+        tb->size = dc.pc - pc_start;
+        tb->icount = insn_count;
+    }
 }
 
 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
 {
+    gen_intermediate_code_internal(env, tb, 0);
 }
 
 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
 {
+    gen_intermediate_code_internal(env, tb, 1);
 }
 
 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 04/32] target-xtensa: implement narrow instructions
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (2 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 03/32] target-xtensa: implement disas_xtensa_insn Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 05/32] target-xtensa: implement RT0 group Max Filippov
                   ` (28 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Instructions with op0 >= 8 are 2 bytes long, others are 3 bytes long.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/translate.c |   54 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 83d8837..7404098 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -106,6 +106,11 @@ static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
     dc->is_jmp = DISAS_UPDATE;
 }
 
+static void gen_jump(DisasContext *dc, TCGv dest)
+{
+    gen_jump_slot(dc, dest, -1);
+}
+
 static void gen_jumpi(DisasContext *dc, uint32_t dest, int slot)
 {
     TCGv_i32 tmp = tcg_const_i32(dest);
@@ -377,22 +382,71 @@ static void disas_xtensa_insn(DisasContext *dc)
     case 7: /*B*/
         break;
 
+#define gen_narrow_load_store(type) do { \
+            TCGv_i32 addr = tcg_temp_new_i32(); \
+            tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
+            tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, 0); \
+            tcg_temp_free(addr); \
+        } while (0)
+
     case 8: /*L32I.Nn*/
+        gen_narrow_load_store(ld32u);
         break;
 
     case 9: /*S32I.Nn*/
+        gen_narrow_load_store(st32);
         break;
+#undef gen_narrow_load_store
 
     case 10: /*ADD.Nn*/
+        tcg_gen_add_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], cpu_R[RRRN_T]);
         break;
 
     case 11: /*ADDI.Nn*/
+        tcg_gen_addi_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], RRRN_T ? RRRN_T : -1);
         break;
 
     case 12: /*ST2n*/
+        if (RRRN_T < 8) { /*MOVI.Nn*/
+            tcg_gen_movi_i32(cpu_R[RRRN_S],
+                    RRRN_R | (RRRN_T << 4) |
+                    ((RRRN_T & 6) == 6 ? 0xffffff80 : 0));
+        } else { /*BEQZ.Nn*/ /*BNEZ.Nn*/
+        }
         break;
 
     case 13: /*ST3n*/
+        switch (RRRN_R) {
+        case 0: /*MOV.Nn*/
+            tcg_gen_mov_i32(cpu_R[RRRN_T], cpu_R[RRRN_S]);
+            break;
+
+        case 15: /*S3*/
+            switch (RRRN_T) {
+            case 0: /*RET.Nn*/
+                gen_jump(dc, cpu_R[0]);
+                break;
+
+            case 1: /*RETW.Nn*/
+                break;
+
+            case 2: /*BREAK.Nn*/
+                break;
+
+            case 3: /*NOP.Nn*/
+                break;
+
+            case 6: /*ILL.Nn*/
+                break;
+
+            default: /*reserved*/
+                break;
+            }
+            break;
+
+        default: /*reserved*/
+            break;
+        }
         break;
 
     default: /*reserved*/
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 05/32] target-xtensa: implement RT0 group
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (3 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 04/32] target-xtensa: implement narrow instructions Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 06/32] target-xtensa: add sample board Max Filippov
                   ` (27 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

NEG and ABS are the only members of RT0 group.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/translate.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 7404098..c9e2c06 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -255,6 +255,25 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 6: /*RT0*/
+                switch (RRR_S) {
+                case 0: /*NEG*/
+                    tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
+                    break;
+
+                case 1: /*ABS*/
+                    {
+                        int label = gen_new_label();
+                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
+                        tcg_gen_brcondi_i32(
+                                TCG_COND_GE, cpu_R[RRR_R], 0, label);
+                        tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
+                        gen_set_label(label);
+                    }
+                    break;
+
+                default: /*reserved*/
+                    break;
+                }
                 break;
 
             case 7: /*reserved*/
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 06/32] target-xtensa: add sample board
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (4 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 05/32] target-xtensa: implement RT0 group Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-04 18:17   ` Blue Swirl
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 07/32] target-xtensa: implement conditional jumps Max Filippov
                   ` (26 subsequent siblings)
  32 siblings, 1 reply; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Sample board and sample CPU core are used for debug and may be used for
development of custom SoC emulators.

This board has two fixed size memory regions for DTCM and ITCM and
variable length SRAM region.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 Makefile.target    |    1 +
 hw/xtensa_sample.c |  105 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 106 insertions(+), 0 deletions(-)
 create mode 100644 hw/xtensa_sample.c

diff --git a/Makefile.target b/Makefile.target
index b833c10..98455e3 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -374,6 +374,7 @@ obj-alpha-y = i8259.o mc146818rtc.o
 obj-alpha-y += vga.o cirrus_vga.o
 
 obj-xtensa-y += xtensa_pic.o
+obj-xtensa-y += xtensa_sample.o
 
 main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
diff --git a/hw/xtensa_sample.c b/hw/xtensa_sample.c
new file mode 100644
index 0000000..9f7733b
--- /dev/null
+++ b/hw/xtensa_sample.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sysemu.h"
+#include "boards.h"
+#include "loader.h"
+#include "elf.h"
+
+static void xtensa_sample_reset(void *env)
+{
+    cpu_reset(env);
+}
+
+static void xtensa_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)
+{
+    CPUState *env = NULL;
+    ram_addr_t ram_offset;
+    int n;
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        qemu_register_reset(xtensa_sample_reset, env);
+    }
+
+    ram_offset = qemu_ram_alloc(NULL, "xtensa.dram", 0x10000);
+    cpu_register_physical_memory(0x5ffd0000, 0x10000, ram_offset);
+
+    ram_offset = qemu_ram_alloc(NULL, "xtensa.iram", 0x20000);
+    cpu_register_physical_memory(0x5ffe0000, 0x20000, ram_offset);
+
+    ram_offset = qemu_ram_alloc(NULL, "xtensa.sram", ram_size);
+    cpu_register_physical_memory(0x60000000, ram_size, ram_offset);
+
+    if (kernel_filename) {
+        uint64_t elf_entry;
+        uint64_t elf_lowaddr;
+#ifdef TARGET_WORDS_BIGENDIAN
+        int success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
+#else
+        int success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                &elf_lowaddr, NULL, 0, ELF_MACHINE, 0);
+#endif
+        if (success > 0) {
+            env->pc = elf_entry;
+        }
+    }
+}
+
+static void xtensa_sample_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)
+{
+    if (!cpu_model) {
+        cpu_model = "sample-xtensa-core";
+    }
+    xtensa_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
+                  initrd_filename, cpu_model);
+}
+
+static QEMUMachine xtensa_sample_machine = {
+    .name = "sample-xtensa-machine",
+    .desc = "Sample Xtensa machine (sample Xtensa core)",
+    .init = xtensa_sample_init,
+    .max_cpus = 4,
+};
+
+static void xtensa_sample_machine_init(void)
+{
+    qemu_register_machine(&xtensa_sample_machine);
+}
+
+machine_init(xtensa_sample_machine_init);
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 07/32] target-xtensa: implement conditional jumps
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (5 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 06/32] target-xtensa: add sample board Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 08/32] target-xtensa: implement JX/RET0/CALLX Max Filippov
                   ` (25 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

- BZ (comparison to zero);
- BI0 (comparison to signed immediate);
- BI1 (comparison to unsigned immediate);
- B (two registers comparison, bit sets comparison);
- BEQZ.N/BNEZ.N (narrow comparison to zero).

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/translate.c |  164 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 164 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index c9e2c06..433e1ba 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -121,6 +121,25 @@ static void gen_jumpi(DisasContext *dc, uint32_t dest, int slot)
     tcg_temp_free(tmp);
 }
 
+static void gen_brcond(DisasContext *dc, TCGCond cond,
+        TCGv_i32 t0, TCGv_i32 t1, uint32_t offset)
+{
+    int label = gen_new_label();
+
+    tcg_gen_brcond_i32(cond, t0, t1, label);
+    gen_jumpi(dc, dc->next_pc, 0);
+    gen_set_label(label);
+    gen_jumpi(dc, dc->pc + offset, 1);
+}
+
+static void gen_brcondi(DisasContext *dc, TCGCond cond,
+        TCGv_i32 t0, uint32_t t1, uint32_t offset)
+{
+    TCGv_i32 tmp = tcg_const_i32(t1);
+    gen_brcond(dc, cond, t0, tmp, offset);
+    tcg_temp_free(tmp);
+}
+
 static void disas_xtensa_insn(DisasContext *dc)
 {
 #define HAS_OPTION(opt) do { \
@@ -202,6 +221,14 @@ static void disas_xtensa_insn(DisasContext *dc)
     uint8_t _b1 = ldub_code(dc->pc + 1);
     uint8_t _b2 = ldub_code(dc->pc + 2);
 
+    static const uint32_t B4CONST[] = {
+        0xffffffff, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
+    };
+
+    static const uint32_t B4CONSTU[] = {
+        32768, 65536, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
+    };
+
     if (OP0 >= 8) {
         dc->next_pc = dc->pc + 2;
         HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
@@ -395,10 +422,143 @@ static void disas_xtensa_insn(DisasContext *dc)
             gen_jumpi(dc, dc->pc + 4 + CALL_OFFSET_SE, 0);
             break;
 
+        case 1: /*BZ*/
+            {
+                static const TCGCond cond[] = {
+                    TCG_COND_EQ, /*BEQZ*/
+                    TCG_COND_NE, /*BNEZ*/
+                    TCG_COND_LT, /*BLTZ*/
+                    TCG_COND_GE, /*BGEZ*/
+                };
+
+                gen_brcondi(dc, cond[BRI12_M & 3], cpu_R[BRI12_S], 0,
+                        4 + BRI12_IMM12_SE);
+            }
+            break;
+
+        case 2: /*BI0*/
+            {
+                static const TCGCond cond[] = {
+                    TCG_COND_EQ, /*BEQI*/
+                    TCG_COND_NE, /*BNEI*/
+                    TCG_COND_LT, /*BLTI*/
+                    TCG_COND_GE, /*BGEI*/
+                };
+
+                gen_brcondi(dc, cond[BRI8_M & 3],
+                        cpu_R[BRI8_S], B4CONST[BRI8_R], 4 + BRI8_IMM8_SE);
+            }
+            break;
+
+        case 3: /*BI1*/
+            switch (BRI8_M) {
+            case 0: /*ENTRYw*/
+                HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                break;
+
+            case 1: /*B1*/
+                switch (BRI8_R) {
+                case 0: /*BFp*/
+                    HAS_OPTION(XTENSA_OPTION_BOOLEAN);
+                    break;
+
+                case 1: /*BTp*/
+                    HAS_OPTION(XTENSA_OPTION_BOOLEAN);
+                    break;
+
+                case 8: /*LOOP*/
+                    break;
+
+                case 9: /*LOOPNEZ*/
+                    break;
+
+                case 10: /*LOOPGTZ*/
+                    break;
+
+                default: /*reserved*/
+                    break;
+
+                }
+                break;
+
+            case 2: /*BLTUI*/
+            case 3: /*BGEUI*/
+                gen_brcondi(dc, BRI8_M == 2 ? TCG_COND_LTU : TCG_COND_GEU,
+                        cpu_R[BRI8_S], B4CONSTU[BRI8_R], 4 + BRI8_IMM8_SE);
+                break;
+            }
+            break;
+
         }
         break;
 
     case 7: /*B*/
+        {
+            TCGCond eq_ne = (RRI8_R & 8) ? TCG_COND_NE : TCG_COND_EQ;
+
+            switch (RRI8_R & 7) {
+            case 0: /*BNONE*/ /*BANY*/
+                {
+                    TCGv_i32 tmp = tcg_temp_new_i32();
+                    tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
+                    gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
+                    tcg_temp_free(tmp);
+                }
+                break;
+
+            case 1: /*BEQ*/ /*BNE*/
+            case 2: /*BLT*/ /*BGE*/
+            case 3: /*BLTU*/ /*BGEU*/
+                {
+                    static const TCGCond cond[] = {
+                        [1] = TCG_COND_EQ,
+                        [2] = TCG_COND_LT,
+                        [3] = TCG_COND_LTU,
+                        [9] = TCG_COND_NE,
+                        [10] = TCG_COND_GE,
+                        [11] = TCG_COND_GEU,
+                    };
+                    gen_brcond(dc, cond[RRI8_R], cpu_R[RRI8_S], cpu_R[RRI8_T],
+                            4 + RRI8_IMM8_SE);
+                }
+                break;
+
+            case 4: /*BALL*/ /*BNALL*/
+                {
+                    TCGv_i32 tmp = tcg_temp_new_i32();
+                    tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
+                    gen_brcond(dc, eq_ne, tmp, cpu_R[RRI8_T],
+                            4 + RRI8_IMM8_SE);
+                    tcg_temp_free(tmp);
+                }
+                break;
+
+            case 5: /*BBC*/ /*BBS*/
+                {
+                    TCGv_i32 bit = tcg_const_i32(1);
+                    TCGv_i32 tmp = tcg_temp_new_i32();
+                    tcg_gen_andi_i32(tmp, cpu_R[RRI8_T], 0x1f);
+                    tcg_gen_shl_i32(bit, bit, tmp);
+                    tcg_gen_and_i32(tmp, cpu_R[RRI8_S], bit);
+                    gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
+                    tcg_temp_free(tmp);
+                    tcg_temp_free(bit);
+                }
+                break;
+
+            case 6: /*BBCI*/ /*BBSI*/
+            case 7:
+                {
+                    TCGv_i32 tmp = tcg_temp_new_i32();
+                    tcg_gen_andi_i32(tmp, cpu_R[RRI8_S],
+                            1 << (((RRI8_R & 1) << 4) | RRI8_T));
+                    gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
+                    tcg_temp_free(tmp);
+                }
+                break;
+
+            }
+        }
         break;
 
 #define gen_narrow_load_store(type) do { \
@@ -431,6 +591,10 @@ static void disas_xtensa_insn(DisasContext *dc)
                     RRRN_R | (RRRN_T << 4) |
                     ((RRRN_T & 6) == 6 ? 0xffffff80 : 0));
         } else { /*BEQZ.Nn*/ /*BNEZ.Nn*/
+            TCGCond eq_ne = (RRRN_T & 4) ? TCG_COND_NE : TCG_COND_EQ;
+
+            gen_brcondi(dc, eq_ne, cpu_R[RRRN_S], 0,
+                    4 + (RRRN_R | ((RRRN_T & 3) << 4)));
         }
         break;
 
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 08/32] target-xtensa: implement JX/RET0/CALLX
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (6 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 07/32] target-xtensa: implement conditional jumps Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 09/32] target-xtensa: add special and user registers Max Filippov
                   ` (24 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Group SNM0 (indirect jumps and calls).

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/translate.c |   43 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 433e1ba..26cce83 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -248,6 +248,49 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                 switch (RRR_R) {
                 case 0: /*SNM0*/
+                    switch (CALLX_M) {
+                    case 0: /*ILL*/
+                        break;
+
+                    case 1: /*reserved*/
+                        break;
+
+                    case 2: /*JR*/
+                        switch (CALLX_N) {
+                        case 0: /*RET*/
+                        case 2: /*JX*/
+                            gen_jump(dc, cpu_R[CALLX_S]);
+                            break;
+
+                        case 1: /*RETWw*/
+                            HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                            break;
+
+                        case 3: /*reserved*/
+                            break;
+                        }
+                        break;
+
+                    case 3: /*CALLX*/
+                        switch (CALLX_N) {
+                        case 0: /*CALLX0*/
+                            {
+                                TCGv_i32 tmp = tcg_temp_new_i32();
+                                tcg_gen_mov_i32(tmp, cpu_R[CALLX_S]);
+                                tcg_gen_movi_i32(cpu_R[0], dc->next_pc);
+                                gen_jump(dc, tmp);
+                                tcg_temp_free(tmp);
+                            }
+                            break;
+
+                        case 1: /*CALLX4w*/
+                        case 2: /*CALLX8w*/
+                        case 3: /*CALLX12w*/
+                            HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                            break;
+                        }
+                        break;
+                    }
                     break;
 
                 case 1: /*MOVSPw*/
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 09/32] target-xtensa: add special and user registers
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (7 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 08/32] target-xtensa: implement JX/RET0/CALLX Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-04 18:18   ` Blue Swirl
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 10/32] target-xtensa: implement RST3 group Max Filippov
                   ` (23 subsequent siblings)
  32 siblings, 1 reply; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Special Registers hold the majority of the state added to the processor
by the options. See ISA, 5.3 for details.

User Registers hold state added in support of designer's TIE and in some
cases of options that Tensilica provides. See ISA, 5.4 for details.

Only registers mapped in sregnames or uregnames are considered valid.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/cpu.h       |    7 ++++++
 target-xtensa/translate.c |   47 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index c323891..8c3fe2e 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -99,6 +99,12 @@ enum {
     XTENSA_OPTION_TRACE_PORT,
 };
 
+enum {
+    THREADPTR = 231,
+    FCR = 232,
+    FSR = 233,
+};
+
 typedef struct XtensaConfig {
     const char *name;
     uint64_t options;
@@ -109,6 +115,7 @@ typedef struct CPUXtensaState {
     uint32_t regs[16];
     uint32_t pc;
     uint32_t sregs[256];
+    uint32_t uregs[256];
 
     CPU_COMMON
 } CPUXtensaState;
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 26cce83..3c8d877 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -52,9 +52,20 @@ typedef struct DisasContext {
 static TCGv_ptr cpu_env;
 static TCGv_i32 cpu_pc;
 static TCGv_i32 cpu_R[16];
+static TCGv_i32 cpu_SR[256];
+static TCGv_i32 cpu_UR[256];
 
 #include "gen-icount.h"
 
+static const char * const sregnames[256] = {
+};
+
+static const char * const uregnames[256] = {
+    [THREADPTR] = "THREADPTR",
+    [FCR] = "FCR",
+    [FSR] = "FSR",
+};
+
 void xtensa_translate_init(void)
 {
     static const char * const regnames[] = {
@@ -74,6 +85,22 @@ void xtensa_translate_init(void)
                 offsetof(CPUState, regs[i]),
                 regnames[i]);
     }
+
+    for (i = 0; i < 256; ++i) {
+        if (sregnames[i]) {
+            cpu_SR[i] = tcg_global_mem_new_i32(TCG_AREG0,
+                    offsetof(CPUState, sregs[i]),
+                    sregnames[i]);
+        }
+    }
+
+    for (i = 0; i < 256; ++i) {
+        if (uregnames[i]) {
+            cpu_UR[i] = tcg_global_mem_new_i32(TCG_AREG0,
+                    offsetof(CPUState, uregs[i]),
+                    uregnames[i]);
+        }
+    }
 #define GEN_HELPER 2
 #include "helpers.h"
 }
@@ -784,9 +811,25 @@ void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
         int flags)
 {
-    int i;
+    int i, j;
+
+    cpu_fprintf(f, "PC=%08x\n\n", env->pc);
+
+    for (i = j = 0; i < 256; ++i)
+        if (sregnames[i]) {
+            cpu_fprintf(f, "%s=%08x%c", sregnames[i], env->sregs[i],
+                    (j++ % 4) == 3 ? '\n' : ' ');
+        }
+
+    cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
+
+    for (i = j = 0; i < 256; ++i)
+        if (uregnames[i]) {
+            cpu_fprintf(f, "%s=%08x%c", uregnames[i], env->uregs[i],
+                    (j++ % 4) == 3 ? '\n' : ' ');
+        }
 
-    cpu_fprintf(f, "PC=%08x\n", env->pc);
+    cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
 
     for (i = 0; i < 16; ++i)
         cpu_fprintf(f, "A%02d=%08x%c", i, env->regs[i],
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 10/32] target-xtensa: implement RST3 group
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (8 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 09/32] target-xtensa: add special and user registers Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 11/32] target-xtensa: implement shifts (ST1 and RST1 groups) Max Filippov
                   ` (22 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

- access to Special Registers (wsr, rsr);
- access to User Registers (wur, rur);
- misc. operations option (value clamp, sign extension, min, max);
- conditional moves.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/translate.c |  161 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 161 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 3c8d877..0d723d0 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -167,6 +167,40 @@ static void gen_brcondi(DisasContext *dc, TCGCond cond,
     tcg_temp_free(tmp);
 }
 
+static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
+{
+    static void (* const rsr_handler[256])(DisasContext *dc,
+            TCGv_i32 d, uint32_t sr) = {
+    };
+
+    if (sregnames[sr]) {
+        if (rsr_handler[sr]) {
+            rsr_handler[sr](dc, d, sr);
+        } else {
+            tcg_gen_mov_i32(d, cpu_SR[sr]);
+        }
+    } else {
+        qemu_log("RSR %d not implemented, ", sr);
+    }
+}
+
+static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
+{
+    static void (* const wsr_handler[256])(DisasContext *dc,
+            uint32_t sr, TCGv_i32 v) = {
+    };
+
+    if (sregnames[sr]) {
+        if (wsr_handler[sr]) {
+            wsr_handler[sr](dc, sr, s);
+        } else {
+            tcg_gen_mov_i32(cpu_SR[sr], s);
+        }
+    } else {
+        qemu_log("WSR %d not implemented, ", sr);
+    }
+}
+
 static void disas_xtensa_insn(DisasContext *dc)
 {
 #define HAS_OPTION(opt) do { \
@@ -415,6 +449,133 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 3: /*RST3*/
+            switch (OP2) {
+            case 0: /*RSR*/
+                gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
+                break;
+
+            case 1: /*WSR*/
+                gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
+                break;
+
+            case 2: /*SEXTu*/
+                HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                {
+                    int shift = 24 - RRR_T;
+
+                    if (shift == 24) {
+                        tcg_gen_ext8s_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
+                    } else if (shift == 16) {
+                        tcg_gen_ext16s_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
+                    } else {
+                        TCGv_i32 tmp = tcg_temp_new_i32();
+                        tcg_gen_shli_i32(tmp, cpu_R[RRR_S], shift);
+                        tcg_gen_sari_i32(cpu_R[RRR_R], tmp, shift);
+                        tcg_temp_free(tmp);
+                    }
+                }
+                break;
+
+            case 3: /*CLAMPSu*/
+                HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                {
+                    TCGv_i32 tmp1 = tcg_temp_new_i32();
+                    TCGv_i32 tmp2 = tcg_temp_new_i32();
+                    int label = gen_new_label();
+
+                    tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 24 - RRR_T);
+                    tcg_gen_xor_i32(tmp2, tmp1, cpu_R[RRR_S]);
+                    tcg_gen_andi_i32(tmp2, tmp2, 0xffffffff << (RRR_T + 7));
+                    tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
+                    tcg_gen_brcondi_i32(TCG_COND_EQ, tmp2, 0, label);
+
+                    tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 31);
+                    tcg_gen_xori_i32(cpu_R[RRR_R], tmp1,
+                            0xffffffff >> (25 - RRR_T));
+
+                    gen_set_label(label);
+
+                    tcg_temp_free(tmp1);
+                    tcg_temp_free(tmp2);
+                }
+                break;
+
+            case 4: /*MINu*/
+            case 5: /*MAXu*/
+            case 6: /*MINUu*/
+            case 7: /*MAXUu*/
+                HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                {
+                    static const TCGCond cond[] = {
+                        TCG_COND_LE,
+                        TCG_COND_GE,
+                        TCG_COND_LEU,
+                        TCG_COND_GEU
+                    };
+                    int label = gen_new_label();
+
+                    if (RRR_R != RRR_T) {
+                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
+                        tcg_gen_brcond_i32(cond[OP2 - 4],
+                                cpu_R[RRR_S], cpu_R[RRR_T], label);
+                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
+                    } else {
+                        tcg_gen_brcond_i32(cond[OP2 - 4],
+                                cpu_R[RRR_T], cpu_R[RRR_S], label);
+                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
+                    }
+                    gen_set_label(label);
+                }
+                break;
+
+            case 8: /*MOVEQZ*/
+            case 9: /*MOVNEZ*/
+            case 10: /*MOVLTZ*/
+            case 11: /*MOVGEZ*/
+                {
+                    static const TCGCond cond[] = {
+                        TCG_COND_NE,
+                        TCG_COND_EQ,
+                        TCG_COND_GE,
+                        TCG_COND_LT
+                    };
+                    int label = gen_new_label();
+                    tcg_gen_brcondi_i32(cond[OP2 - 8], cpu_R[RRR_T], 0, label);
+                    tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
+                    gen_set_label(label);
+                }
+                break;
+
+            case 12: /*MOVFp*/
+                HAS_OPTION(XTENSA_OPTION_BOOLEAN);
+                break;
+
+            case 13: /*MOVTp*/
+                HAS_OPTION(XTENSA_OPTION_BOOLEAN);
+                break;
+
+            case 14: /*RUR*/
+                {
+                    int st = (RRR_S << 4) + RRR_T;
+                    if (uregnames[st]) {
+                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_UR[st]);
+                    } else {
+                        qemu_log("RUR %d not implemented, ", st);
+                    }
+                }
+                break;
+
+            case 15: /*WUR*/
+                {
+                    if (uregnames[RSR_SR]) {
+                        tcg_gen_mov_i32(cpu_UR[RSR_SR], cpu_R[RRR_T]);
+                    } else {
+                        qemu_log("WUR %d not implemented, ", RSR_SR);
+                    }
+                }
+                break;
+
+            }
             break;
 
         case 4: /*EXTUI*/
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 11/32] target-xtensa: implement shifts (ST1 and RST1 groups)
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (9 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 10/32] target-xtensa: implement RST3 group Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 12/32] target-xtensa: implement LSAI group Max Filippov
                   ` (21 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

- ST1: SAR (shift amount special register) manipulation, NSA(U);
- RST1: shifts, 16-bit multiplication.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/cpu.h       |    4 +
 target-xtensa/helpers.h   |    2 +
 target-xtensa/op_helper.c |   14 +++
 target-xtensa/translate.c |  242 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 262 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 8c3fe2e..f756b43 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -105,6 +105,10 @@ enum {
     FSR = 233,
 };
 
+enum {
+    SAR = 3,
+};
+
 typedef struct XtensaConfig {
     const char *name;
     uint64_t options;
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index c298d74..976c8d8 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -1,5 +1,7 @@
 #include "def-helper.h"
 
 DEF_HELPER_1(exception, void, i32)
+DEF_HELPER_1(nsa, i32, i32)
+DEF_HELPER_1(nsau, i32, i32)
 
 #include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 0392fbe..c1cfd2e 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -28,6 +28,7 @@
 #include "cpu.h"
 #include "dyngen-exec.h"
 #include "helpers.h"
+#include "host-utils.h"
 
 #define MMUSUFFIX _mmu
 
@@ -57,3 +58,16 @@ void HELPER(exception)(uint32_t excp)
     env->exception_index = excp;
     cpu_loop_exit(env);
 }
+
+uint32_t HELPER(nsa)(uint32_t v)
+{
+    if (v & 0x80000000) {
+        v = ~v;
+    }
+    return v ? clz32(v) - 1 : 31;
+}
+
+uint32_t HELPER(nsau)(uint32_t v)
+{
+    return v ? clz32(v) : 32;
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 0d723d0..f55e68f 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -47,6 +47,11 @@ typedef struct DisasContext {
     uint32_t next_pc;
     int is_jmp;
     int singlestep_enabled;
+
+    bool sar_5bit;
+    bool sar_m32_5bit;
+    bool sar_m32_allocated;
+    TCGv_i32 sar_m32;
 } DisasContext;
 
 static TCGv_ptr cpu_env;
@@ -58,6 +63,7 @@ static TCGv_i32 cpu_UR[256];
 #include "gen-icount.h"
 
 static const char * const sregnames[256] = {
+    [SAR] = "SAR",
 };
 
 static const char * const uregnames[256] = {
@@ -110,6 +116,44 @@ static inline bool option_enabled(DisasContext *dc, int opt)
     return xtensa_option_enabled(dc->config, opt);
 }
 
+static void init_sar_tracker(DisasContext *dc)
+{
+    dc->sar_5bit = false;
+    dc->sar_m32_5bit = false;
+    dc->sar_m32_allocated = false;
+}
+
+static void reset_sar_tracker(DisasContext *dc)
+{
+    if (dc->sar_m32_allocated) {
+        tcg_temp_free(dc->sar_m32);
+    }
+}
+
+static void gen_right_shift_sar(DisasContext *dc, TCGv_i32 sa)
+{
+    tcg_gen_andi_i32(cpu_SR[SAR], sa, 0x1f);
+    if (dc->sar_m32_5bit) {
+        tcg_gen_discard_i32(dc->sar_m32);
+    }
+    dc->sar_5bit = true;
+    dc->sar_m32_5bit = false;
+}
+
+static void gen_left_shift_sar(DisasContext *dc, TCGv_i32 sa)
+{
+    TCGv_i32 tmp = tcg_const_i32(32);
+    if (!dc->sar_m32_allocated) {
+        dc->sar_m32 = tcg_temp_local_new_i32();
+        dc->sar_m32_allocated = true;
+    }
+    tcg_gen_andi_i32(dc->sar_m32, sa, 0x1f);
+    tcg_gen_sub_i32(cpu_SR[SAR], tmp, dc->sar_m32);
+    dc->sar_5bit = false;
+    dc->sar_m32_5bit = true;
+    tcg_temp_free(tmp);
+}
+
 static void gen_exception(int excp)
 {
     TCGv_i32 tmp = tcg_const_i32(excp);
@@ -184,10 +228,21 @@ static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
     }
 }
 
+static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
+{
+    tcg_gen_andi_i32(cpu_SR[sr], s, 0x3f);
+    if (dc->sar_m32_5bit) {
+        tcg_gen_discard_i32(dc->sar_m32);
+    }
+    dc->sar_5bit = false;
+    dc->sar_m32_5bit = false;
+}
+
 static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 {
     static void (* const wsr_handler[256])(DisasContext *dc,
             uint32_t sr, TCGv_i32 v) = {
+        [SAR] = gen_wsr_sar,
     };
 
     if (sregnames[sr]) {
@@ -380,6 +435,65 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 4: /*ST1*/
+                switch (RRR_R) {
+                case 0: /*SSR*/
+                    gen_right_shift_sar(dc, cpu_R[RRR_S]);
+                    break;
+
+                case 1: /*SSL*/
+                    gen_left_shift_sar(dc, cpu_R[RRR_S]);
+                    break;
+
+                case 2: /*SSA8L*/
+                    {
+                        TCGv_i32 tmp = tcg_temp_new_i32();
+                        tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3);
+                        gen_right_shift_sar(dc, tmp);
+                        tcg_temp_free(tmp);
+                    }
+                    break;
+
+                case 3: /*SSA8B*/
+                    {
+                        TCGv_i32 tmp = tcg_temp_new_i32();
+                        tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3);
+                        gen_left_shift_sar(dc, tmp);
+                        tcg_temp_free(tmp);
+                    }
+                    break;
+
+                case 4: /*SSAI*/
+                    {
+                        TCGv_i32 tmp = tcg_const_i32(
+                                RRR_S | ((RRR_T & 1) << 4));
+                        gen_right_shift_sar(dc, tmp);
+                        tcg_temp_free(tmp);
+                    }
+                    break;
+
+                case 6: /*RER*/
+                    break;
+
+                case 7: /*WER*/
+                    break;
+
+                case 8: /*ROTWw*/
+                    HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                    break;
+
+                case 14: /*NSAu*/
+                    HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                    gen_helper_nsa(cpu_R[RRR_T], cpu_R[RRR_S]);
+                    break;
+
+                case 15: /*NSAUu*/
+                    HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                    gen_helper_nsau(cpu_R[RRR_T], cpu_R[RRR_S]);
+                    break;
+
+                default: /*reserved*/
+                    break;
+                }
                 break;
 
             case 5: /*TLB*/
@@ -443,6 +557,121 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 1: /*RST1*/
+            switch (OP2) {
+            case 0: /*SLLI*/
+            case 1:
+                tcg_gen_shli_i32(cpu_R[RRR_R], cpu_R[RRR_S],
+                        32 - (RRR_T | ((OP2 & 1) << 4)));
+                break;
+
+            case 2: /*SRAI*/
+            case 3:
+                tcg_gen_sari_i32(cpu_R[RRR_R], cpu_R[RRR_T],
+                        RRR_S | ((OP2 & 1) << 4));
+                break;
+
+            case 4: /*SRLI*/
+                tcg_gen_shri_i32(cpu_R[RRR_R], cpu_R[RRR_T], RRR_S);
+                break;
+
+            case 6: /*XSR*/
+                {
+                    TCGv_i32 tmp = tcg_temp_new_i32();
+                    tcg_gen_mov_i32(tmp, cpu_R[RRR_T]);
+                    gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
+                    gen_wsr(dc, RSR_SR, tmp);
+                    tcg_temp_free(tmp);
+                }
+                break;
+
+                /*
+                 * Note: 64 bit ops are used here solely because SAR values
+                 * have range 0..63
+                 */
+#define gen_shift_reg(cmd, reg) do { \
+                    TCGv_i64 tmp = tcg_temp_new_i64(); \
+                    tcg_gen_extu_i32_i64(tmp, reg); \
+                    tcg_gen_##cmd##_i64(v, v, tmp); \
+                    tcg_gen_trunc_i64_i32(cpu_R[RRR_R], v); \
+                    tcg_temp_free_i64(v); \
+                    tcg_temp_free_i64(tmp); \
+                } while (0)
+
+#define gen_shift(cmd) gen_shift_reg(cmd, cpu_SR[SAR])
+
+            case 8: /*SRC*/
+                {
+                    TCGv_i64 v = tcg_temp_new_i64();
+                    tcg_gen_concat_i32_i64(v, cpu_R[RRR_T], cpu_R[RRR_S]);
+                    gen_shift(shr);
+                }
+                break;
+
+            case 9: /*SRL*/
+                if (dc->sar_5bit) {
+                    tcg_gen_shr_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]);
+                } else {
+                    TCGv_i64 v = tcg_temp_new_i64();
+                    tcg_gen_extu_i32_i64(v, cpu_R[RRR_T]);
+                    gen_shift(shr);
+                }
+                break;
+
+            case 10: /*SLL*/
+                if (dc->sar_m32_5bit) {
+                    tcg_gen_shl_i32(cpu_R[RRR_R], cpu_R[RRR_S], dc->sar_m32);
+                } else {
+                    TCGv_i64 v = tcg_temp_new_i64();
+                    TCGv_i32 s = tcg_const_i32(32);
+                    tcg_gen_sub_i32(s, s, cpu_SR[SAR]);
+                    tcg_gen_andi_i32(s, s, 0x3f);
+                    tcg_gen_extu_i32_i64(v, cpu_R[RRR_S]);
+                    gen_shift_reg(shl, s);
+                    tcg_temp_free(s);
+                }
+                break;
+
+            case 11: /*SRA*/
+                if (dc->sar_5bit) {
+                    tcg_gen_sar_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]);
+                } else {
+                    TCGv_i64 v = tcg_temp_new_i64();
+                    tcg_gen_ext_i32_i64(v, cpu_R[RRR_T]);
+                    gen_shift(sar);
+                }
+                break;
+#undef gen_shift
+#undef gen_shift_reg
+
+            case 12: /*MUL16U*/
+                HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);
+                {
+                    TCGv_i32 v1 = tcg_temp_new_i32();
+                    TCGv_i32 v2 = tcg_temp_new_i32();
+                    tcg_gen_ext16u_i32(v1, cpu_R[RRR_S]);
+                    tcg_gen_ext16u_i32(v2, cpu_R[RRR_T]);
+                    tcg_gen_mul_i32(cpu_R[RRR_R], v1, v2);
+                    tcg_temp_free(v2);
+                    tcg_temp_free(v1);
+                }
+                break;
+
+            case 13: /*MUL16S*/
+                HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);
+                {
+                    TCGv_i32 v1 = tcg_temp_new_i32();
+                    TCGv_i32 v2 = tcg_temp_new_i32();
+                    tcg_gen_ext16s_i32(v1, cpu_R[RRR_S]);
+                    tcg_gen_ext16s_i32(v2, cpu_R[RRR_T]);
+                    tcg_gen_mul_i32(cpu_R[RRR_R], v1, v2);
+                    tcg_temp_free(v2);
+                    tcg_temp_free(v1);
+                }
+                break;
+
+            default: /*reserved*/
+                break;
+            }
             break;
 
         case 2: /*RST2*/
@@ -580,6 +809,15 @@ static void disas_xtensa_insn(DisasContext *dc)
 
         case 4: /*EXTUI*/
         case 5:
+            {
+                int shiftimm = RRR_S | (OP1 << 4);
+                int maskimm = (1 << (OP2 + 1)) - 1;
+
+                TCGv_i32 tmp = tcg_temp_new_i32();
+                tcg_gen_shri_i32(tmp, cpu_R[RRR_T], shiftimm);
+                tcg_gen_andi_i32(cpu_R[RRR_R], tmp, maskimm);
+                tcg_temp_free(tmp);
+            }
             break;
 
         case 6: /*CUST0*/
@@ -913,6 +1151,8 @@ static void gen_intermediate_code_internal(
     dc.pc = pc_start;
     dc.is_jmp = DISAS_NEXT;
 
+    init_sar_tracker(&dc);
+
     gen_icount_start();
 
     do {
@@ -947,6 +1187,8 @@ static void gen_intermediate_code_internal(
             dc.pc < next_page_start &&
             gen_opc_ptr < gen_opc_end);
 
+    reset_sar_tracker(&dc);
+
     if (dc.is_jmp == DISAS_NEXT) {
         gen_jumpi(&dc, dc.pc, 0);
     }
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 12/32] target-xtensa: implement LSAI group
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (10 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 11/32] target-xtensa: implement shifts (ST1 and RST1 groups) Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 13/32] target-xtensa: mark reserved and TBD opcodes Max Filippov
                   ` (20 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

- base + offset load/store operations for 1/2/4 byte values;
- cache operations (not implemented);
- multiprocessor synchronization operations.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/cpu.h       |    1 +
 target-xtensa/translate.c |   89 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index f756b43..ac9bbb4 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -107,6 +107,7 @@ enum {
 
 enum {
     SAR = 3,
+    SCOMPARE1 = 12,
 };
 
 typedef struct XtensaConfig {
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index f55e68f..e37d75c 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -64,6 +64,7 @@ static TCGv_i32 cpu_UR[256];
 
 static const char * const sregnames[256] = {
     [SAR] = "SAR",
+    [SCOMPARE1] = "SCOMPARE1",
 };
 
 static const char * const uregnames[256] = {
@@ -860,7 +861,95 @@ static void disas_xtensa_insn(DisasContext *dc)
         break;
 
     case 2: /*LSAI*/
+#define gen_load_store(type, shift) do { \
+            TCGv_i32 addr = tcg_temp_new_i32(); \
+            tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \
+            tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, 0); \
+            tcg_temp_free(addr); \
+        } while (0)
+
+        switch (RRI8_R) {
+        case 0: /*L8UI*/
+            gen_load_store(ld8u, 0);
+            break;
+
+        case 1: /*L16UI*/
+            gen_load_store(ld16u, 1);
+            break;
+
+        case 2: /*L32I*/
+            gen_load_store(ld32u, 2);
+            break;
+
+        case 4: /*S8I*/
+            gen_load_store(st8, 0);
+            break;
+
+        case 5: /*S16I*/
+            gen_load_store(st16, 1);
+            break;
+
+        case 6: /*S32I*/
+            gen_load_store(st32, 2);
+            break;
+
+        case 7: /*CACHEc*/
+            break;
+
+        case 9: /*L16SI*/
+            gen_load_store(ld16s, 1);
+            break;
+
+        case 10: /*MOVI*/
+            tcg_gen_movi_i32(cpu_R[RRI8_T],
+                    RRI8_IMM8 | (RRI8_S << 8) |
+                    ((RRI8_S & 0x8) ? 0xfffff000 : 0));
+            break;
+
+        case 11: /*L32AIy*/
+            HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
+            gen_load_store(ld32u, 2); /*TODO acquire?*/
+            break;
+
+        case 12: /*ADDI*/
+            tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE);
+            break;
+
+        case 13: /*ADDMI*/
+            tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE << 8);
+            break;
+
+        case 14: /*S32C1Iy*/
+            HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
+            {
+                int label = gen_new_label();
+                TCGv_i32 tmp = tcg_temp_local_new_i32();
+                TCGv_i32 addr = tcg_temp_local_new_i32();
+
+                tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]);
+                tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
+                tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, 0);
+                tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T],
+                        cpu_SR[SCOMPARE1], label);
+
+                tcg_gen_qemu_st32(tmp, addr, 0);
+
+                gen_set_label(label);
+                tcg_temp_free(addr);
+                tcg_temp_free(tmp);
+            }
+            break;
+
+        case 15: /*S32RIy*/
+            HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
+            gen_load_store(st32, 2); /*TODO release?*/
+            break;
+
+        default: /*reserved*/
+            break;
+        }
         break;
+#undef gen_load_store
 
     case 3: /*LSCIp*/
         HAS_OPTION(XTENSA_OPTION_COPROCESSOR);
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 13/32] target-xtensa: mark reserved and TBD opcodes
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (11 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 12/32] target-xtensa: implement LSAI group Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 14/32] target-xtensa: implement SYNC group Max Filippov
                   ` (19 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Reserved opcodes must generate illegal instruction exception. Usually
they signal emulation quality problems.
Not implemented opcodes are good to see.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/translate.c |  110 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 109 insertions(+), 1 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index e37d75c..e6d749f 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -267,6 +267,14 @@ static void disas_xtensa_insn(DisasContext *dc)
         } \
     } while (0)
 
+#define TBD() qemu_log("TBD(pc = %08x): %s:%d\n", dc->pc, __FILE__, __LINE__)
+#define RESERVED() do { \
+        qemu_log("RESERVED(pc = %08x, %02x%02x%02x): %s:%d\n", \
+                dc->pc, _b0, _b1, _b2, __FILE__, __LINE__); \
+        goto invalid_opcode; \
+    } while (0)
+
+
 #ifdef TARGET_WORDS_BIGENDIAN
 #define OP0 (((_b0) & 0xf0) >> 4)
 #define OP1 (((_b2) & 0xf0) >> 4)
@@ -367,9 +375,11 @@ static void disas_xtensa_insn(DisasContext *dc)
                 case 0: /*SNM0*/
                     switch (CALLX_M) {
                     case 0: /*ILL*/
+                        TBD();
                         break;
 
                     case 1: /*reserved*/
+                        RESERVED();
                         break;
 
                     case 2: /*JR*/
@@ -381,9 +391,11 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                         case 1: /*RETWw*/
                             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                            TBD();
                             break;
 
                         case 3: /*reserved*/
+                            RESERVED();
                             break;
                         }
                         break;
@@ -404,6 +416,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                         case 2: /*CALLX8w*/
                         case 3: /*CALLX12w*/
                             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                            TBD();
                             break;
                         }
                         break;
@@ -412,12 +425,59 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                 case 1: /*MOVSPw*/
                     HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                    TBD();
                     break;
 
                 case 2: /*SYNC*/
+                    TBD();
+                    break;
+
+                case 3: /*RFEIx*/
+                    TBD();
+                    break;
+
+                case 4: /*BREAKx*/
+                    HAS_OPTION(XTENSA_OPTION_EXCEPTION);
+                    TBD();
+                    break;
+
+                case 5: /*SYSCALLx*/
+                    HAS_OPTION(XTENSA_OPTION_EXCEPTION);
+                    TBD();
+                    break;
+
+                case 6: /*RSILx*/
+                    HAS_OPTION(XTENSA_OPTION_INTERRUPT);
+                    TBD();
+                    break;
+
+                case 7: /*WAITIx*/
+                    HAS_OPTION(XTENSA_OPTION_INTERRUPT);
+                    TBD();
+                    break;
+
+                case 8: /*ANY4p*/
+                    HAS_OPTION(XTENSA_OPTION_BOOLEAN);
+                    TBD();
+                    break;
+
+                case 9: /*ALL4p*/
+                    HAS_OPTION(XTENSA_OPTION_BOOLEAN);
+                    TBD();
                     break;
 
-                case 3:
+                case 10: /*ANY8p*/
+                    HAS_OPTION(XTENSA_OPTION_BOOLEAN);
+                    TBD();
+                    break;
+
+                case 11: /*ALL8p*/
+                    HAS_OPTION(XTENSA_OPTION_BOOLEAN);
+                    TBD();
+                    break;
+
+                default: /*reserved*/
+                    RESERVED();
                     break;
 
                 }
@@ -473,13 +533,16 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 case 6: /*RER*/
+                    TBD();
                     break;
 
                 case 7: /*WER*/
+                    TBD();
                     break;
 
                 case 8: /*ROTWw*/
                     HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                    TBD();
                     break;
 
                 case 14: /*NSAu*/
@@ -493,11 +556,13 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 default: /*reserved*/
+                    RESERVED();
                     break;
                 }
                 break;
 
             case 5: /*TLB*/
+                TBD();
                 break;
 
             case 6: /*RT0*/
@@ -518,11 +583,13 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 default: /*reserved*/
+                    RESERVED();
                     break;
                 }
                 break;
 
             case 7: /*reserved*/
+                RESERVED();
                 break;
 
             case 8: /*ADD*/
@@ -582,6 +649,9 @@ static void disas_xtensa_insn(DisasContext *dc)
                     gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
                     gen_wsr(dc, RSR_SR, tmp);
                     tcg_temp_free(tmp);
+                    if (!sregnames[RSR_SR]) {
+                        TBD();
+                    }
                 }
                 break;
 
@@ -671,21 +741,29 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             default: /*reserved*/
+                RESERVED();
                 break;
             }
             break;
 
         case 2: /*RST2*/
+            TBD();
             break;
 
         case 3: /*RST3*/
             switch (OP2) {
             case 0: /*RSR*/
                 gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
+                if (!sregnames[RSR_SR]) {
+                    TBD();
+                }
                 break;
 
             case 1: /*WSR*/
                 gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
+                if (!sregnames[RSR_SR]) {
+                    TBD();
+                }
                 break;
 
             case 2: /*SEXTu*/
@@ -778,10 +856,12 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 12: /*MOVFp*/
                 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
+                TBD();
                 break;
 
             case 13: /*MOVTp*/
                 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
+                TBD();
                 break;
 
             case 14: /*RUR*/
@@ -791,6 +871,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                         tcg_gen_mov_i32(cpu_R[RRR_R], cpu_UR[st]);
                     } else {
                         qemu_log("RUR %d not implemented, ", st);
+                        TBD();
                     }
                 }
                 break;
@@ -801,6 +882,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                         tcg_gen_mov_i32(cpu_UR[RSR_SR], cpu_R[RRR_T]);
                     } else {
                         qemu_log("WUR %d not implemented, ", RSR_SR);
+                        TBD();
                     }
                 }
                 break;
@@ -822,27 +904,34 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 6: /*CUST0*/
+            RESERVED();
             break;
 
         case 7: /*CUST1*/
+            RESERVED();
             break;
 
         case 8: /*LSCXp*/
             HAS_OPTION(XTENSA_OPTION_COPROCESSOR);
+            TBD();
             break;
 
         case 9: /*LSC4*/
+            TBD();
             break;
 
         case 10: /*FP0*/
             HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
+            TBD();
             break;
 
         case 11: /*FP1*/
             HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
+            TBD();
             break;
 
         default: /*reserved*/
+            RESERVED();
             break;
         }
         break;
@@ -894,6 +983,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 7: /*CACHEc*/
+            TBD();
             break;
 
         case 9: /*L16SI*/
@@ -946,6 +1036,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         default: /*reserved*/
+            RESERVED();
             break;
         }
         break;
@@ -953,10 +1044,12 @@ static void disas_xtensa_insn(DisasContext *dc)
 
     case 3: /*LSCIp*/
         HAS_OPTION(XTENSA_OPTION_COPROCESSOR);
+        TBD();
         break;
 
     case 4: /*MAC16d*/
         HAS_OPTION(XTENSA_OPTION_MAC16);
+        TBD();
         break;
 
     case 5: /*CALLN*/
@@ -970,6 +1063,7 @@ static void disas_xtensa_insn(DisasContext *dc)
         case 2: /*CALL8w*/
         case 3: /*CALL12w*/
             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+            TBD();
             break;
         }
         break;
@@ -1012,28 +1106,35 @@ static void disas_xtensa_insn(DisasContext *dc)
             switch (BRI8_M) {
             case 0: /*ENTRYw*/
                 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                TBD();
                 break;
 
             case 1: /*B1*/
                 switch (BRI8_R) {
                 case 0: /*BFp*/
                     HAS_OPTION(XTENSA_OPTION_BOOLEAN);
+                    TBD();
                     break;
 
                 case 1: /*BTp*/
                     HAS_OPTION(XTENSA_OPTION_BOOLEAN);
+                    TBD();
                     break;
 
                 case 8: /*LOOP*/
+                    TBD();
                     break;
 
                 case 9: /*LOOPNEZ*/
+                    TBD();
                     break;
 
                 case 10: /*LOOPGTZ*/
+                    TBD();
                     break;
 
                 default: /*reserved*/
+                    RESERVED();
                     break;
 
                 }
@@ -1169,28 +1270,35 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 1: /*RETW.Nn*/
+                HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                TBD();
                 break;
 
             case 2: /*BREAK.Nn*/
+                TBD();
                 break;
 
             case 3: /*NOP.Nn*/
                 break;
 
             case 6: /*ILL.Nn*/
+                TBD();
                 break;
 
             default: /*reserved*/
+                RESERVED();
                 break;
             }
             break;
 
         default: /*reserved*/
+            RESERVED();
             break;
         }
         break;
 
     default: /*reserved*/
+        RESERVED();
         break;
     }
 
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 14/32] target-xtensa: implement SYNC group
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (12 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 13/32] target-xtensa: mark reserved and TBD opcodes Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 15/32] target-xtensa: implement CACHE group Max Filippov
                   ` (18 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

All operations in this group are no-ops, because there are no delayed
side effects.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/translate.c |   31 ++++++++++++++++++++++++++++++-
 1 files changed, 30 insertions(+), 1 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index e6d749f..cc4a4ad 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -429,7 +429,36 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 case 2: /*SYNC*/
-                    TBD();
+                    switch (RRR_T) {
+                    case 0: /*ISYNC*/
+                        break;
+
+                    case 1: /*RSYNC*/
+                        break;
+
+                    case 2: /*ESYNC*/
+                        break;
+
+                    case 3: /*DSYNC*/
+                        break;
+
+                    case 8: /*EXCW*/
+                        HAS_OPTION(XTENSA_OPTION_EXCEPTION);
+                        break;
+
+                    case 12: /*MEMW*/
+                        break;
+
+                    case 13: /*EXTW*/
+                        break;
+
+                    case 15: /*NOP*/
+                        break;
+
+                    default: /*reserved*/
+                        RESERVED();
+                        break;
+                    }
                     break;
 
                 case 3: /*RFEIx*/
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 15/32] target-xtensa: implement CACHE group
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (13 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 14/32] target-xtensa: implement SYNC group Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 16/32] target-xtensa: add PS register and access control Max Filippov
                   ` (17 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

All operations in this group are no-ops, because cache ought to be
transparent to applications. However cache may be abused, then we'll
need to actually implement these opcodes.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/translate.c |   95 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 94 insertions(+), 1 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index cc4a4ad..5768ae0 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -1012,7 +1012,100 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 7: /*CACHEc*/
-            TBD();
+            if (RRI8_T < 8) {
+                HAS_OPTION(XTENSA_OPTION_DCACHE);
+            }
+
+            switch (RRI8_T) {
+            case 0: /*DPFRc*/
+                break;
+
+            case 1: /*DPFWc*/
+                break;
+
+            case 2: /*DPFROc*/
+                break;
+
+            case 3: /*DPFWOc*/
+                break;
+
+            case 4: /*DHWBc*/
+                break;
+
+            case 5: /*DHWBIc*/
+                break;
+
+            case 6: /*DHIc*/
+                break;
+
+            case 7: /*DIIc*/
+                break;
+
+            case 8: /*DCEc*/
+                switch (OP1) {
+                case 0: /*DPFLl*/
+                    HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
+                    break;
+
+                case 2: /*DHUl*/
+                    HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
+                    break;
+
+                case 3: /*DIUl*/
+                    HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
+                    break;
+
+                case 4: /*DIWBc*/
+                    HAS_OPTION(XTENSA_OPTION_DCACHE);
+                    break;
+
+                case 5: /*DIWBIc*/
+                    HAS_OPTION(XTENSA_OPTION_DCACHE);
+                    break;
+
+                default: /*reserved*/
+                    RESERVED();
+                    break;
+
+                }
+                break;
+
+            case 12: /*IPFc*/
+                HAS_OPTION(XTENSA_OPTION_ICACHE);
+                break;
+
+            case 13: /*ICEc*/
+                switch (OP1) {
+                case 0: /*IPFLl*/
+                    HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
+                    break;
+
+                case 2: /*IHUl*/
+                    HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
+                    break;
+
+                case 3: /*IIUl*/
+                    HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
+                    break;
+
+                default: /*reserved*/
+                    RESERVED();
+                    break;
+                }
+                break;
+
+            case 14: /*IHIc*/
+                HAS_OPTION(XTENSA_OPTION_ICACHE);
+                break;
+
+            case 15: /*IIIc*/
+                HAS_OPTION(XTENSA_OPTION_ICACHE);
+                break;
+
+            default: /*reserved*/
+                RESERVED();
+                break;
+            }
             break;
 
         case 9: /*L16SI*/
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 16/32] target-xtensa: add PS register and access control
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (14 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 15/32] target-xtensa: implement CACHE group Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 17/32] target-xtensa: implement exceptions Max Filippov
                   ` (16 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/cpu.h       |   53 ++++++++++++++++++++++++++++++++++++++++++++-
 target-xtensa/helper.c    |    1 +
 target-xtensa/translate.c |   29 ++++++++++++++++++++----
 3 files changed, 77 insertions(+), 6 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index ac9bbb4..939222c 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -108,8 +108,27 @@ enum {
 enum {
     SAR = 3,
     SCOMPARE1 = 12,
+    PS = 230,
 };
 
+#define PS_INTLEVEL 0xf
+#define PS_INTLEVEL_SHIFT 0
+
+#define PS_EXCM 0x10
+#define PS_UM 0x20
+
+#define PS_RING 0xc0
+#define PS_RING_SHIFT 6
+
+#define PS_OWB 0xf00
+#define PS_OWB_SHIFT 8
+
+#define PS_CALLINC 0x30000
+#define PS_CALLINC_SHIFT 16
+#define PS_CALLINC_LEN 2
+
+#define PS_WOE 0x40000
+
 typedef struct XtensaConfig {
     const char *name;
     uint64_t options;
@@ -145,17 +164,49 @@ static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt)
     return (config->options & XTENSA_OPTION_BIT(opt)) != 0;
 }
 
+static inline int xtensa_get_ring(const CPUState *env)
+{
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+        return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
+    } else {
+        return 0;
+    }
+}
+
+static inline int xtensa_get_cring(const CPUState *env)
+{
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) &&
+            (env->sregs[PS] & PS_EXCM) == 0) {
+        return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
+    } else {
+        return 0;
+    }
+}
+
+/* MMU modes definitions */
+#define MMU_MODE0_SUFFIX _ring0
+#define MMU_MODE1_SUFFIX _ring1
+#define MMU_MODE2_SUFFIX _ring2
+#define MMU_MODE3_SUFFIX _ring3
+
 static inline int cpu_mmu_index(CPUState *env)
 {
-    return 0;
+    return xtensa_get_cring(env);
 }
 
+#define XTENSA_TBFLAG_RING_MASK 0x3
+#define XTENSA_TBFLAG_EXCM 0x4
+
 static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
         target_ulong *cs_base, int *flags)
 {
     *pc = env->pc;
     *cs_base = 0;
     *flags = 0;
+    *flags |= xtensa_get_ring(env);
+    if (env->sregs[PS] & PS_EXCM) {
+        *flags |= XTENSA_TBFLAG_EXCM;
+    }
 }
 
 #include "cpu-all.h"
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index c119fd0..83b8a04 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -37,6 +37,7 @@
 void cpu_reset(CPUXtensaState *env)
 {
     env->pc = 0;
+    env->sregs[PS] = 0x1f;
 }
 
 static const XtensaConfig core_config[] = {
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 5768ae0..b6d0210 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -45,6 +45,8 @@ typedef struct DisasContext {
     TranslationBlock *tb;
     uint32_t pc;
     uint32_t next_pc;
+    int cring;
+    int ring;
     int is_jmp;
     int singlestep_enabled;
 
@@ -65,6 +67,7 @@ static TCGv_i32 cpu_UR[256];
 static const char * const sregnames[256] = {
     [SAR] = "SAR",
     [SCOMPARE1] = "SCOMPARE1",
+    [PS] = "PS",
 };
 
 static const char * const uregnames[256] = {
@@ -239,11 +242,25 @@ static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
     dc->sar_m32_5bit = false;
 }
 
+static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    uint32_t mask = PS_WOE | PS_CALLINC | PS_OWB |
+        PS_UM | PS_EXCM | PS_INTLEVEL;
+
+    if (option_enabled(dc, XTENSA_OPTION_MMU)) {
+        mask |= PS_RING;
+    }
+    tcg_gen_andi_i32(cpu_SR[sr], v, mask);
+    /* This can change mmu index, so exit tb */
+    gen_jumpi(dc, dc->next_pc, -1);
+}
+
 static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 {
     static void (* const wsr_handler[256])(DisasContext *dc,
             uint32_t sr, TCGv_i32 v) = {
         [SAR] = gen_wsr_sar,
+        [PS] = gen_wsr_ps,
     };
 
     if (sregnames[sr]) {
@@ -973,7 +990,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             /* no ext L32R */
 
-            tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, 0);
+            tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, dc->cring);
             tcg_temp_free(tmp);
         }
         break;
@@ -982,7 +999,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 #define gen_load_store(type, shift) do { \
             TCGv_i32 addr = tcg_temp_new_i32(); \
             tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \
-            tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, 0); \
+            tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
             tcg_temp_free(addr); \
         } while (0)
 
@@ -1140,11 +1157,11 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                 tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]);
                 tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
-                tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, 0);
+                tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, dc->cring);
                 tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T],
                         cpu_SR[SCOMPARE1], label);
 
-                tcg_gen_qemu_st32(tmp, addr, 0);
+                tcg_gen_qemu_st32(tmp, addr, dc->cring);
 
                 gen_set_label(label);
                 tcg_temp_free(addr);
@@ -1345,7 +1362,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 #define gen_narrow_load_store(type) do { \
             TCGv_i32 addr = tcg_temp_new_i32(); \
             tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
-            tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, 0); \
+            tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, dc->cring); \
             tcg_temp_free(addr); \
         } while (0)
 
@@ -1468,6 +1485,8 @@ static void gen_intermediate_code_internal(
     dc.singlestep_enabled = env->singlestep_enabled;
     dc.tb = tb;
     dc.pc = pc_start;
+    dc.ring = tb->flags & XTENSA_TBFLAG_RING_MASK;
+    dc.cring = (tb->flags & XTENSA_TBFLAG_EXCM) ? 0 : dc.ring;
     dc.is_jmp = DISAS_NEXT;
 
     init_sar_tracker(&dc);
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 17/32] target-xtensa: implement exceptions
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (15 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 16/32] target-xtensa: add PS register and access control Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-04 18:22   ` Blue Swirl
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 18/32] target-xtensa: implement RST2 group (32 bit mul/div/rem) Max Filippov
                   ` (15 subsequent siblings)
  32 siblings, 1 reply; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

- mark privileged opcodes with ring check;
- make debug exception on exception handler entry.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 cpu-exec.c                |    6 +++
 target-xtensa/cpu.h       |   67 ++++++++++++++++++++++++++++
 target-xtensa/helper.c    |   37 +++++++++++++++-
 target-xtensa/helpers.h   |    2 +
 target-xtensa/op_helper.c |   29 ++++++++++++
 target-xtensa/translate.c |  107 ++++++++++++++++++++++++++++++++++++++++++--
 6 files changed, 242 insertions(+), 6 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index 3fce033..2fc37d8 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -488,6 +488,12 @@ int cpu_exec(CPUState *env)
                         do_interrupt(env);
                         next_tb = 0;
                     }
+#elif defined(TARGET_XTENSA)
+                    if (interrupt_request & CPU_INTERRUPT_HARD) {
+                        env->exception_index = EXC_IRQ;
+                        do_interrupt(env);
+                        next_tb = 0;
+                    }
 #endif
                    /* Don't use the cached interrupt_request value,
                       do_interrupt may have updated the EXITTB flag. */
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 939222c..cae6637 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -108,7 +108,12 @@ enum {
 enum {
     SAR = 3,
     SCOMPARE1 = 12,
+    EPC1 = 177,
+    DEPC = 192,
+    EXCSAVE1 = 209,
     PS = 230,
+    EXCCAUSE = 232,
+    EXCVADDR = 238,
 };
 
 #define PS_INTLEVEL 0xf
@@ -129,9 +134,60 @@ enum {
 
 #define PS_WOE 0x40000
 
+enum {
+    /* Static vectors */
+    EXC_RESET,
+    EXC_MEMORY_ERROR,
+
+    /* Dynamic vectors */
+    EXC_WINDOW_OVERFLOW4,
+    EXC_WINDOW_UNDERFLOW4,
+    EXC_WINDOW_OVERFLOW8,
+    EXC_WINDOW_UNDERFLOW8,
+    EXC_WINDOW_OVERFLOW12,
+    EXC_WINDOW_UNDERFLOW12,
+    EXC_IRQ,
+    EXC_KERNEL,
+    EXC_USER,
+    EXC_DOUBLE,
+    EXC_MAX
+};
+
+enum {
+    ILLEGAL_INSTRUCTION_CAUSE = 0,
+    SYSCALL_CAUSE,
+    INSTRUCTION_FETCH_ERROR_CAUSE,
+    LOAD_STORE_ERROR_CAUSE,
+    LEVEL1_INTERRUPT_CAUSE,
+    ALLOCA_CAUSE,
+    INTEGER_DIVIDE_BY_ZERO_CAUSE,
+    PRIVILEGED_CAUSE = 8,
+    LOAD_STORE_ALIGNMENT_CAUSE,
+
+    INSTR_PIF_DATA_ERROR_CAUSE = 12,
+    LOAD_STORE_PIF_DATA_ERROR_CAUSE,
+    INSTR_PIF_ADDR_ERROR_CAUSE,
+    LOAD_STORE_PIF_ADDR_ERROR_CAUSE,
+
+    INST_TLB_MISS_CAUSE,
+    INST_TLB_MULTI_HIT_CAUSE,
+    INST_FETCH_PRIVILEGE_CAUSE,
+    INST_FETCH_PROHIBITED_CAUSE = 20,
+    LOAD_STORE_TLB_MISS_CAUSE = 24,
+    LOAD_STORE_TLB_MULTI_HIT_CAUSE,
+    LOAD_STORE_PRIVILEGE_CAUSE,
+    LOAD_PROHIBITED_CAUSE = 28,
+    STORE_PROHIBITED_CAUSE,
+
+    COPROCESSOR0_DISABLED = 32,
+};
+
 typedef struct XtensaConfig {
     const char *name;
     uint64_t options;
+    int excm_level;
+    int ndepc;
+    uint32_t exception_vector[EXC_MAX];
 } XtensaConfig;
 
 typedef struct CPUXtensaState {
@@ -141,6 +197,8 @@ typedef struct CPUXtensaState {
     uint32_t sregs[256];
     uint32_t uregs[256];
 
+    int exception_taken;
+
     CPU_COMMON
 } CPUXtensaState;
 
@@ -164,6 +222,15 @@ static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt)
     return (config->options & XTENSA_OPTION_BIT(opt)) != 0;
 }
 
+static inline int xtensa_get_cintlevel(const CPUState *env)
+{
+    int level = (env->sregs[PS] & PS_INTLEVEL) >> PS_INTLEVEL_SHIFT;
+    if ((env->sregs[PS] & PS_EXCM) && env->config->excm_level > level) {
+        level = env->config->excm_level;
+    }
+    return level;
+}
+
 static inline int xtensa_get_ring(const CPUState *env)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 83b8a04..44ebb9f 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -36,7 +36,8 @@
 
 void cpu_reset(CPUXtensaState *env)
 {
-    env->pc = 0;
+    env->exception_taken = 0;
+    env->pc = env->config->exception_vector[EXC_RESET];
     env->sregs[PS] = 0x1f;
 }
 
@@ -44,6 +45,20 @@ static const XtensaConfig core_config[] = {
     {
         .name = "sample-xtensa-core",
         .options = -1,
+        .ndepc = 1,
+        .excm_level = 16,
+        .exception_vector = {
+            [EXC_RESET] = 0x5fff8000,
+            [EXC_WINDOW_OVERFLOW4] = 0x5fff8400,
+            [EXC_WINDOW_UNDERFLOW4] = 0x5fff8440,
+            [EXC_WINDOW_OVERFLOW8] = 0x5fff8480,
+            [EXC_WINDOW_UNDERFLOW8] = 0x5fff84c0,
+            [EXC_WINDOW_OVERFLOW12] = 0x5fff8500,
+            [EXC_WINDOW_UNDERFLOW12] = 0x5fff8540,
+            [EXC_KERNEL] = 0x5fff861c,
+            [EXC_USER] = 0x5fff863c,
+            [EXC_DOUBLE] = 0x5fff865c,
+        },
     },
 };
 
@@ -94,4 +109,24 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 
 void do_interrupt(CPUState *env)
 {
+    switch (env->exception_index) {
+    case EXC_WINDOW_OVERFLOW4:
+    case EXC_WINDOW_UNDERFLOW4:
+    case EXC_WINDOW_OVERFLOW8:
+    case EXC_WINDOW_UNDERFLOW8:
+    case EXC_WINDOW_OVERFLOW12:
+    case EXC_WINDOW_UNDERFLOW12:
+    case EXC_KERNEL:
+    case EXC_USER:
+    case EXC_DOUBLE:
+        if (env->config->exception_vector[env->exception_index]) {
+            env->pc = env->config->exception_vector[env->exception_index];
+            env->exception_taken = 1;
+        } else {
+            qemu_log("%s(pc = %08x) bad exception_index: %d\n",
+                    __func__, env->pc, env->exception_index);
+        }
+        break;
+
+    }
 }
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index 976c8d8..6329c43 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -1,6 +1,8 @@
 #include "def-helper.h"
 
 DEF_HELPER_1(exception, void, i32)
+DEF_HELPER_2(exception_cause, void, i32, i32)
+DEF_HELPER_3(exception_cause_vaddr, void, i32, i32, i32)
 DEF_HELPER_1(nsa, i32, i32)
 DEF_HELPER_1(nsau, i32, i32)
 
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index c1cfd2e..794a834 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -59,6 +59,35 @@ void HELPER(exception)(uint32_t excp)
     cpu_loop_exit(env);
 }
 
+void HELPER(exception_cause)(uint32_t pc, uint32_t cause)
+{
+    uint32_t vector;
+
+    env->pc = pc;
+    if (env->sregs[PS] & PS_EXCM) {
+        if (env->config->ndepc) {
+            env->sregs[DEPC] = pc;
+        } else {
+            env->sregs[EPC1] = pc;
+        }
+        vector = EXC_DOUBLE;
+    } else {
+        env->sregs[EPC1] = pc;
+        vector = (env->sregs[PS] & PS_UM) ? EXC_USER : EXC_KERNEL;
+    }
+
+    env->sregs[EXCCAUSE] = cause;
+    env->sregs[PS] |= PS_EXCM;
+
+    HELPER(exception)(vector);
+}
+
+void HELPER(exception_cause_vaddr)(uint32_t pc, uint32_t cause, uint32_t vaddr)
+{
+    env->sregs[EXCVADDR] = vaddr;
+    HELPER(exception_cause)(pc, cause);
+}
+
 uint32_t HELPER(nsa)(uint32_t v)
 {
     if (v & 0x80000000) {
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index b6d0210..4c9db9e 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -67,7 +67,12 @@ static TCGv_i32 cpu_UR[256];
 static const char * const sregnames[256] = {
     [SAR] = "SAR",
     [SCOMPARE1] = "SCOMPARE1",
+    [EPC1] = "EPC1",
+    [DEPC] = "DEPC",
+    [EXCSAVE1] = "EXCSAVE1",
     [PS] = "PS",
+    [EXCCAUSE] = "EXCCAUSE",
+    [EXCVADDR] = "EXCVADDR",
 };
 
 static const char * const uregnames[256] = {
@@ -165,6 +170,22 @@ static void gen_exception(int excp)
     tcg_temp_free(tmp);
 }
 
+static void gen_exception_cause(DisasContext *dc, uint32_t cause)
+{
+    TCGv_i32 _pc = tcg_const_i32(dc->pc);
+    TCGv_i32 _cause = tcg_const_i32(cause);
+    gen_helper_exception_cause(_pc, _cause);
+    tcg_temp_free(_pc);
+    tcg_temp_free(_cause);
+}
+
+static void gen_check_privilege(DisasContext *dc)
+{
+    if (dc->cring) {
+        gen_exception_cause(dc, PRIVILEGED_CAUSE);
+    }
+}
+
 static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
 {
     tcg_gen_mov_i32(cpu_pc, dest);
@@ -392,7 +413,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 case 0: /*SNM0*/
                     switch (CALLX_M) {
                     case 0: /*ILL*/
-                        TBD();
+                        gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
                         break;
 
                     case 1: /*reserved*/
@@ -479,7 +500,52 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 case 3: /*RFEIx*/
-                    TBD();
+                    switch (RRR_T) {
+                    case 0: /*RFETx*/
+                        HAS_OPTION(XTENSA_OPTION_EXCEPTION);
+                        switch (RRR_S) {
+                        case 0: /*RFEx*/
+                            gen_check_privilege(dc);
+                            tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);
+                            gen_jump(dc, cpu_SR[EPC1]);
+                            break;
+
+                        case 1: /*RFUEx*/
+                            RESERVED();
+                            break;
+
+                        case 2: /*RFDEx*/
+                            gen_check_privilege(dc);
+                            gen_jump(dc, cpu_SR[
+                                    dc->config->ndepc ? DEPC : EPC1]);
+                            break;
+
+                        case 4: /*RFWOw*/
+                        case 5: /*RFWUw*/
+                            HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                            TBD();
+                            break;
+
+                        default: /*reserved*/
+                            RESERVED();
+                            break;
+                        }
+                        break;
+
+                    case 1: /*RFIx*/
+                        HAS_OPTION(XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT);
+                        TBD();
+                        break;
+
+                    case 2: /*RFME*/
+                        TBD();
+                        break;
+
+                    default: /*reserved*/
+                        RESERVED();
+                        break;
+
+                    }
                     break;
 
                 case 4: /*BREAKx*/
@@ -489,12 +555,28 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                 case 5: /*SYSCALLx*/
                     HAS_OPTION(XTENSA_OPTION_EXCEPTION);
-                    TBD();
+                    switch (RRR_S) {
+                    case 0: /*SYSCALLx*/
+                        gen_exception_cause(dc, SYSCALL_CAUSE);
+                        break;
+
+                    case 1: /*SIMCALL*/
+                        TBD();
+                        break;
+
+                    default:
+                        RESERVED();
+                        break;
+                    }
                     break;
 
                 case 6: /*RSILx*/
                     HAS_OPTION(XTENSA_OPTION_INTERRUPT);
-                    TBD();
+                    gen_check_privilege(dc);
+                    tcg_gen_mov_i32(cpu_R[RRR_T], cpu_SR[PS]);
+                    tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], RRR_S);
+                    tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS],
+                            RRR_S | ~PS_INTLEVEL);
                     break;
 
                 case 7: /*WAITIx*/
@@ -691,6 +773,9 @@ static void disas_xtensa_insn(DisasContext *dc)
             case 6: /*XSR*/
                 {
                     TCGv_i32 tmp = tcg_temp_new_i32();
+                    if (RSR_SR >= 64) {
+                        gen_check_privilege(dc);
+                    }
                     tcg_gen_mov_i32(tmp, cpu_R[RRR_T]);
                     gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
                     gen_wsr(dc, RSR_SR, tmp);
@@ -799,6 +884,9 @@ static void disas_xtensa_insn(DisasContext *dc)
         case 3: /*RST3*/
             switch (OP2) {
             case 0: /*RSR*/
+                if (RSR_SR >= 64) {
+                    gen_check_privilege(dc);
+                }
                 gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
                 if (!sregnames[RSR_SR]) {
                     TBD();
@@ -806,6 +894,9 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 1: /*WSR*/
+                if (RSR_SR >= 64) {
+                    gen_check_privilege(dc);
+                }
                 gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
                 if (!sregnames[RSR_SR]) {
                     TBD();
@@ -1421,7 +1512,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 6: /*ILL.Nn*/
-                TBD();
+                gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
                 break;
 
             default: /*reserved*/
@@ -1493,6 +1584,12 @@ static void gen_intermediate_code_internal(
 
     gen_icount_start();
 
+    if (env->singlestep_enabled && env->exception_taken) {
+        env->exception_taken = 0;
+        tcg_gen_movi_i32(cpu_pc, dc.pc);
+        gen_exception(EXCP_DEBUG);
+    }
+
     do {
         check_breakpoint(env, &dc);
 
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 18/32] target-xtensa: implement RST2 group (32 bit mul/div/rem)
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (16 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 17/32] target-xtensa: implement exceptions Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 19/32] target-xtensa: implement windowed registers Max Filippov
                   ` (14 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/translate.c |   77 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 76 insertions(+), 1 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 4c9db9e..de5f947 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -878,7 +878,82 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 2: /*RST2*/
-            TBD();
+            if (OP2 >= 12) {
+                HAS_OPTION(XTENSA_OPTION_32_BIT_IDIV);
+                int label = gen_new_label();
+                tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_T], 0, label);
+                gen_exception_cause(dc, INTEGER_DIVIDE_BY_ZERO_CAUSE);
+                gen_set_label(label);
+            }
+
+            switch (OP2) {
+            case 8: /*MULLi*/
+                HAS_OPTION(XTENSA_OPTION_32_BIT_IMUL);
+                tcg_gen_mul_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                break;
+
+            case 10: /*MULUHi*/
+            case 11: /*MULSHi*/
+                HAS_OPTION(XTENSA_OPTION_32_BIT_IMUL);
+                {
+                    TCGv_i64 r = tcg_temp_new_i64();
+                    TCGv_i64 s = tcg_temp_new_i64();
+                    TCGv_i64 t = tcg_temp_new_i64();
+
+                    if (OP2 == 10) {
+                        tcg_gen_extu_i32_i64(s, cpu_R[RRR_S]);
+                        tcg_gen_extu_i32_i64(t, cpu_R[RRR_T]);
+                    } else {
+                        tcg_gen_ext_i32_i64(s, cpu_R[RRR_S]);
+                        tcg_gen_ext_i32_i64(t, cpu_R[RRR_T]);
+                    }
+                    tcg_gen_mul_i64(r, s, t);
+                    tcg_gen_shri_i64(r, r, 32);
+                    tcg_gen_trunc_i64_i32(cpu_R[RRR_R], r);
+
+                    tcg_temp_free_i64(r);
+                    tcg_temp_free_i64(s);
+                    tcg_temp_free_i64(t);
+                }
+                break;
+
+            case 12: /*QUOUi*/
+                tcg_gen_divu_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                break;
+
+            case 13: /*QUOSi*/
+            case 15: /*REMSi*/
+                {
+                    int label1 = gen_new_label();
+                    int label2 = gen_new_label();
+
+                    tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_S], 0x80000000,
+                            label1);
+                    tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_T], 0xffffffff,
+                            label1);
+                    tcg_gen_movi_i32(cpu_R[RRR_R],
+                            OP2 == 13 ? 0x80000000 : 0);
+                    tcg_gen_br(label2);
+                    gen_set_label(label1);
+                    if (OP2 == 13) {
+                        tcg_gen_div_i32(cpu_R[RRR_R],
+                                cpu_R[RRR_S], cpu_R[RRR_T]);
+                    } else {
+                        tcg_gen_rem_i32(cpu_R[RRR_R],
+                                cpu_R[RRR_S], cpu_R[RRR_T]);
+                    }
+                    gen_set_label(label2);
+                }
+                break;
+
+            case 14: /*REMUi*/
+                tcg_gen_remu_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                break;
+
+            default: /*reserved*/
+                RESERVED();
+                break;
+            }
             break;
 
         case 3: /*RST3*/
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 19/32] target-xtensa: implement windowed registers
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (17 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 18/32] target-xtensa: implement RST2 group (32 bit mul/div/rem) Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-04 18:27   ` Blue Swirl
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 20/32] target-xtensa: implement loop option Max Filippov
                   ` (13 subsequent siblings)
  32 siblings, 1 reply; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

See ISA, 4.7.1 for details.

Physical registers and currently visible window are separate fields in
CPUEnv. Only current window is accessible to TCG. On operations that
change window base helpers copy current window to and from physical
registers.

Window overflow check described in 4.7.1.3 is in separate patch.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/cpu.h       |    8 ++
 target-xtensa/helper.c    |    1 +
 target-xtensa/helpers.h   |    8 ++
 target-xtensa/op_helper.c |  185 +++++++++++++++++++++++++++++++++++++++++++++
 target-xtensa/translate.c |  144 +++++++++++++++++++++++++++++++++--
 5 files changed, 337 insertions(+), 9 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index cae6637..7e662f5 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -108,6 +108,8 @@ enum {
 enum {
     SAR = 3,
     SCOMPARE1 = 12,
+    WINDOW_BASE = 72,
+    WINDOW_START = 73,
     EPC1 = 177,
     DEPC = 192,
     EXCSAVE1 = 209,
@@ -134,6 +136,8 @@ enum {
 
 #define PS_WOE 0x40000
 
+#define MAX_NAREG 64
+
 enum {
     /* Static vectors */
     EXC_RESET,
@@ -185,6 +189,7 @@ enum {
 typedef struct XtensaConfig {
     const char *name;
     uint64_t options;
+    unsigned nareg;
     int excm_level;
     int ndepc;
     uint32_t exception_vector[EXC_MAX];
@@ -196,6 +201,7 @@ typedef struct CPUXtensaState {
     uint32_t pc;
     uint32_t sregs[256];
     uint32_t uregs[256];
+    uint32_t phys_regs[MAX_NAREG];
 
     int exception_taken;
 
@@ -214,6 +220,8 @@ int cpu_xtensa_exec(CPUXtensaState *s);
 void do_interrupt(CPUXtensaState *s);
 int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
 void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
+void xtensa_sync_window_from_phys(CPUState *env);
+void xtensa_sync_phys_from_window(CPUState *env);
 
 #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
 
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 44ebb9f..4f86934 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -45,6 +45,7 @@ static const XtensaConfig core_config[] = {
     {
         .name = "sample-xtensa-core",
         .options = -1,
+        .nareg = 64,
         .ndepc = 1,
         .excm_level = 16,
         .exception_vector = {
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index 6329c43..0971fde 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -5,5 +5,13 @@ DEF_HELPER_2(exception_cause, void, i32, i32)
 DEF_HELPER_3(exception_cause_vaddr, void, i32, i32, i32)
 DEF_HELPER_1(nsa, i32, i32)
 DEF_HELPER_1(nsau, i32, i32)
+DEF_HELPER_1(wsr_windowbase, void, i32)
+DEF_HELPER_3(entry, void, i32, i32, i32)
+DEF_HELPER_1(retw, i32, i32)
+DEF_HELPER_1(rotw, void, i32)
+DEF_HELPER_2(window_check, void, i32, i32)
+DEF_HELPER_0(restore_owb, void)
+DEF_HELPER_1(movsp, void, i32)
+DEF_HELPER_0(dump_state, void)
 
 #include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 794a834..7f75422 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -100,3 +100,188 @@ uint32_t HELPER(nsau)(uint32_t v)
 {
     return v ? clz32(v) : 32;
 }
+
+static void copy_window_from_phys(CPUState *env,
+        uint32_t window, uint32_t phys, uint32_t n)
+{
+    assert(phys < env->config->nareg);
+    if (phys + n <= env->config->nareg) {
+        memcpy(env->regs + window, env->phys_regs + phys,
+                n * sizeof(uint32_t));
+    } else {
+        uint32_t n1 = env->config->nareg - phys;
+        memcpy(env->regs + window, env->phys_regs + phys,
+                n1 * sizeof(uint32_t));
+        memcpy(env->regs + window + n1, env->phys_regs,
+                (n - n1) * sizeof(uint32_t));
+    }
+}
+
+static void copy_phys_from_window(CPUState *env,
+        uint32_t phys, uint32_t window, uint32_t n)
+{
+    assert(phys < env->config->nareg);
+    if (phys + n <= env->config->nareg) {
+        memcpy(env->phys_regs + phys, env->regs + window,
+                n * sizeof(uint32_t));
+    } else {
+        uint32_t n1 = env->config->nareg - phys;
+        memcpy(env->phys_regs + phys, env->regs + window,
+                n1 * sizeof(uint32_t));
+        memcpy(env->phys_regs, env->regs + window + n1,
+                (n - n1) * sizeof(uint32_t));
+    }
+}
+
+
+#define WINDOWBASE_BOUND(a) ((a) & (env->config->nareg / 4 - 1))
+#define WINDOW_BOUND(a) ((a) & (env->config->nareg - 1))
+#define WINDOWSTART_BIT(a) (1 << WINDOWBASE_BOUND(a))
+
+void xtensa_sync_window_from_phys(CPUState *env)
+{
+    copy_window_from_phys(env, 0, env->sregs[WINDOW_BASE] * 4, 16);
+}
+
+void xtensa_sync_phys_from_window(CPUState *env)
+{
+    copy_phys_from_window(env, env->sregs[WINDOW_BASE] * 4, 0, 16);
+}
+
+static void rotate_window_abs(uint32_t position)
+{
+    xtensa_sync_phys_from_window(env);
+    env->sregs[WINDOW_BASE] = WINDOWBASE_BOUND(position);
+    xtensa_sync_window_from_phys(env);
+}
+
+static void rotate_window(uint32_t delta)
+{
+    rotate_window_abs(env->sregs[WINDOW_BASE] + delta);
+}
+
+void HELPER(wsr_windowbase)(uint32_t v)
+{
+    rotate_window_abs(v);
+}
+
+void HELPER(entry)(uint32_t pc, uint32_t s, uint32_t imm)
+{
+    int callinc = (env->sregs[PS] & PS_CALLINC) >> PS_CALLINC_SHIFT;
+    if (s > 3 || ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) != 0) {
+        qemu_log("Illegal entry instruction(pc = %08x), PS = %08x\n",
+                pc, env->sregs[PS]);
+        HELPER(exception_cause)(pc, ILLEGAL_INSTRUCTION_CAUSE);
+    } else {
+        env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - (imm << 3);
+        rotate_window(callinc);
+        env->sregs[WINDOW_START] |= WINDOWSTART_BIT(env->sregs[WINDOW_BASE]);
+    }
+}
+
+void HELPER(window_check)(uint32_t pc, uint32_t w)
+{
+    uint32_t windowbase = WINDOWBASE_BOUND(env->sregs[WINDOW_BASE]);
+    uint32_t windowstart = env->sregs[WINDOW_START];
+    uint32_t m, n;
+
+    if ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) {
+        return;
+    }
+
+    for (n = 1; ; ++n) {
+        if (n > w) {
+            return;
+        }
+        if (windowstart & WINDOWSTART_BIT(windowbase + n)) {
+            break;
+        }
+    }
+
+    m = WINDOWBASE_BOUND(windowbase + n);
+    rotate_window(n);
+    env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) |
+        (windowbase << PS_OWB_SHIFT) | PS_EXCM;
+    env->sregs[EPC1] = env->pc = pc;
+
+    if (windowstart & WINDOWSTART_BIT(m + 1)) {
+        HELPER(exception)(EXC_WINDOW_OVERFLOW4);
+    } else if (windowstart & WINDOWSTART_BIT(m + 2)) {
+        HELPER(exception)(EXC_WINDOW_OVERFLOW8);
+    } else {
+        HELPER(exception)(EXC_WINDOW_OVERFLOW12);
+    }
+}
+
+uint32_t HELPER(retw)(uint32_t pc)
+{
+    int n = (env->regs[0] >> 30) & 0x3;
+    int m = 0;
+    uint32_t windowbase = WINDOWBASE_BOUND(env->sregs[WINDOW_BASE]);
+    uint32_t windowstart = env->sregs[WINDOW_START];
+    uint32_t ret_pc = 0;
+
+    if (windowstart & WINDOWSTART_BIT(windowbase - 1)) {
+        m = 1;
+    } else if (windowstart & WINDOWSTART_BIT(windowbase - 2)) {
+        m = 2;
+    } else if (windowstart & WINDOWSTART_BIT(windowbase - 3)) {
+        m = 3;
+    }
+
+    if (n == 0 || (m != 0 && m != n) ||
+            ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) != 0) {
+        qemu_log("Illegal retw instruction(pc = %08x), "
+                "PS = %08x, m = %d, n = %d\n",
+                pc, env->sregs[PS], m, n);
+        HELPER(exception_cause)(pc, ILLEGAL_INSTRUCTION_CAUSE);
+    } else {
+        int owb = windowbase;
+
+        ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff);
+
+        rotate_window(-n);
+        if (windowstart & WINDOWSTART_BIT(env->sregs[WINDOW_BASE])) {
+            env->sregs[WINDOW_START] &= ~WINDOWSTART_BIT(owb);
+        } else {
+            /* window underflow */
+            env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) |
+                (windowbase << PS_OWB_SHIFT) | PS_EXCM;
+            env->sregs[EPC1] = env->pc = pc;
+
+            if (n == 1) {
+                HELPER(exception)(EXC_WINDOW_UNDERFLOW4);
+            } else if (n == 2) {
+                HELPER(exception)(EXC_WINDOW_UNDERFLOW8);
+            } else if (n == 3) {
+                HELPER(exception)(EXC_WINDOW_UNDERFLOW12);
+            }
+        }
+    }
+    return ret_pc;
+}
+
+void HELPER(rotw)(uint32_t imm4)
+{
+    rotate_window(imm4);
+}
+
+void HELPER(restore_owb)(void)
+{
+    rotate_window_abs((env->sregs[PS] & PS_OWB) >> PS_OWB_SHIFT);
+}
+
+void HELPER(movsp)(uint32_t pc)
+{
+    if ((env->sregs[WINDOW_START] &
+            (WINDOWSTART_BIT(env->sregs[WINDOW_BASE] - 3) |
+             WINDOWSTART_BIT(env->sregs[WINDOW_BASE] - 2) |
+             WINDOWSTART_BIT(env->sregs[WINDOW_BASE] - 1))) == 0) {
+        HELPER(exception_cause)(pc, ALLOCA_CAUSE);
+    }
+}
+
+void HELPER(dump_state)(void)
+{
+    cpu_dump_state(env, stderr, fprintf, 0);
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index de5f947..de393ff 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -67,6 +67,8 @@ static TCGv_i32 cpu_UR[256];
 static const char * const sregnames[256] = {
     [SAR] = "SAR",
     [SCOMPARE1] = "SCOMPARE1",
+    [WINDOW_BASE] = "WINDOW_BASE",
+    [WINDOW_START] = "WINDOW_START",
     [EPC1] = "EPC1",
     [DEPC] = "DEPC",
     [EXCSAVE1] = "EXCSAVE1",
@@ -217,6 +219,34 @@ static void gen_jumpi(DisasContext *dc, uint32_t dest, int slot)
     tcg_temp_free(tmp);
 }
 
+static void gen_callw_slot(DisasContext *dc, int _callinc, TCGv_i32 dest,
+        int slot)
+{
+    TCGv_i32 callinc = tcg_const_i32(_callinc);
+
+    tcg_gen_deposit_i32(cpu_SR[PS], cpu_SR[PS],
+            callinc, PS_CALLINC_SHIFT, PS_CALLINC_LEN);
+    tcg_temp_free(callinc);
+    tcg_gen_movi_i32(cpu_R[_callinc << 2],
+            (_callinc << 30) | (dc->next_pc & 0x3fffffff));
+    gen_jump_slot(dc, dest, slot);
+}
+
+static void gen_callw(DisasContext *dc, int callinc, TCGv_i32 dest)
+{
+    gen_callw_slot(dc, callinc, dest, -1);
+}
+
+static void gen_callwi(DisasContext *dc, int callinc, uint32_t dest, int slot)
+{
+    TCGv_i32 tmp = tcg_const_i32(dest);
+    if (((dc->pc ^ dest) & TARGET_PAGE_MASK) != 0) {
+        slot = -1;
+    }
+    gen_callw_slot(dc, callinc, tmp, slot);
+    tcg_temp_free(tmp);
+}
+
 static void gen_brcond(DisasContext *dc, TCGCond cond,
         TCGv_i32 t0, TCGv_i32 t1, uint32_t offset)
 {
@@ -263,6 +293,11 @@ static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
     dc->sar_m32_5bit = false;
 }
 
+static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    gen_helper_wsr_windowbase(v);
+}
+
 static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     uint32_t mask = PS_WOE | PS_CALLINC | PS_OWB |
@@ -281,6 +316,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
     static void (* const wsr_handler[256])(DisasContext *dc,
             uint32_t sr, TCGv_i32 v) = {
         [SAR] = gen_wsr_sar,
+        [WINDOW_BASE] = gen_wsr_windowbase,
         [PS] = gen_wsr_ps,
     };
 
@@ -429,7 +465,12 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                         case 1: /*RETWw*/
                             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-                            TBD();
+                            {
+                                TCGv_i32 tmp = tcg_const_i32(dc->pc);
+                                gen_helper_retw(tmp, tmp);
+                                gen_jump(dc, tmp);
+                                tcg_temp_free(tmp);
+                            }
                             break;
 
                         case 3: /*reserved*/
@@ -454,7 +495,13 @@ static void disas_xtensa_insn(DisasContext *dc)
                         case 2: /*CALLX8w*/
                         case 3: /*CALLX12w*/
                             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-                            TBD();
+                            {
+                                TCGv_i32 tmp = tcg_temp_new_i32();
+
+                                tcg_gen_mov_i32(tmp, cpu_R[CALLX_S]);
+                                gen_callw(dc, CALLX_N, tmp);
+                                tcg_temp_free(tmp);
+                            }
                             break;
                         }
                         break;
@@ -463,7 +510,12 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                 case 1: /*MOVSPw*/
                     HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-                    TBD();
+                    {
+                        TCGv_i32 pc = tcg_const_i32(dc->pc);
+                        gen_helper_movsp(pc);
+                        tcg_gen_mov_i32(cpu_R[RRR_T], cpu_R[RRR_S]);
+                        tcg_temp_free(pc);
+                    }
                     break;
 
                 case 2: /*SYNC*/
@@ -523,7 +575,27 @@ static void disas_xtensa_insn(DisasContext *dc)
                         case 4: /*RFWOw*/
                         case 5: /*RFWUw*/
                             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-                            TBD();
+                            gen_check_privilege(dc);
+                            {
+                                TCGv_i32 tmp = tcg_const_i32(1);
+
+                                tcg_gen_andi_i32(
+                                        cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);
+                                tcg_gen_shl_i32(tmp, tmp, cpu_SR[WINDOW_BASE]);
+
+                                if (RRR_S == 4) {
+                                    tcg_gen_andc_i32(cpu_SR[WINDOW_START],
+                                            cpu_SR[WINDOW_START], tmp);
+                                } else {
+                                    tcg_gen_or_i32(cpu_SR[WINDOW_START],
+                                            cpu_SR[WINDOW_START], tmp);
+                                }
+
+                                gen_helper_restore_owb();
+                                gen_jump(dc, cpu_SR[EPC1]);
+
+                                tcg_temp_free(tmp);
+                            }
                             break;
 
                         default: /*reserved*/
@@ -670,7 +742,13 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                 case 8: /*ROTWw*/
                     HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-                    TBD();
+                    gen_check_privilege(dc);
+                    {
+                        TCGv_i32 tmp = tcg_const_i32(
+                                RRR_T | ((RRR_T & 8) ? 0xfffffff0 : 0));
+                        gen_helper_rotw(tmp);
+                        tcg_temp_free(tmp);
+                    }
                     break;
 
                 case 14: /*NSAu*/
@@ -1129,7 +1207,35 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 9: /*LSC4*/
-            TBD();
+            switch (OP2) {
+            case 0: /*L32E*/
+                HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                gen_check_privilege(dc);
+                {
+                    TCGv_i32 addr = tcg_temp_new_i32();
+                    tcg_gen_addi_i32(addr, cpu_R[RRR_S],
+                            (0xffffffc0 | (RRR_R << 2)));
+                    tcg_gen_qemu_ld32u(cpu_R[RRR_T], addr, dc->ring);
+                    tcg_temp_free(addr);
+                }
+                break;
+
+            case 4: /*S32E*/
+                HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                gen_check_privilege(dc);
+                {
+                    TCGv_i32 addr = tcg_temp_new_i32();
+                    tcg_gen_addi_i32(addr, cpu_R[RRR_S],
+                            (0xffffffc0 | (RRR_R << 2)));
+                    tcg_gen_qemu_st32(cpu_R[RRR_T], addr, dc->ring);
+                    tcg_temp_free(addr);
+                }
+                break;
+
+            default:
+                RESERVED();
+                break;
+            }
             break;
 
         case 10: /*FP0*/
@@ -1368,7 +1474,8 @@ static void disas_xtensa_insn(DisasContext *dc)
         case 2: /*CALL8w*/
         case 3: /*CALL12w*/
             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-            TBD();
+            gen_callwi(dc, CALL_N,
+                    (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0);
             break;
         }
         break;
@@ -1411,7 +1518,15 @@ static void disas_xtensa_insn(DisasContext *dc)
             switch (BRI8_M) {
             case 0: /*ENTRYw*/
                 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-                TBD();
+                {
+                    TCGv_i32 pc = tcg_const_i32(dc->pc);
+                    TCGv_i32 s = tcg_const_i32(BRI12_S);
+                    TCGv_i32 imm = tcg_const_i32(BRI12_IMM12);
+                    gen_helper_entry(pc, s, imm);
+                    tcg_temp_free(imm);
+                    tcg_temp_free(s);
+                    tcg_temp_free(pc);
+                }
                 break;
 
             case 1: /*B1*/
@@ -1576,7 +1691,12 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 1: /*RETW.Nn*/
                 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-                TBD();
+                {
+                    TCGv_i32 tmp = tcg_const_i32(dc->pc);
+                    gen_helper_retw(tmp, tmp);
+                    gen_jump(dc, tmp);
+                    tcg_temp_free(tmp);
+                }
                 break;
 
             case 2: /*BREAK.Nn*/
@@ -1747,6 +1867,12 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
     for (i = 0; i < 16; ++i)
         cpu_fprintf(f, "A%02d=%08x%c", i, env->regs[i],
                 (i % 4) == 3 ? '\n' : ' ');
+
+    cpu_fprintf(f, "\n");
+
+    for (i = 0; i < env->config->nareg; ++i)
+        cpu_fprintf(f, "AR%02d=%08x%c", i, env->phys_regs[i],
+                (i % 4) == 3 ? '\n' : ' ');
 }
 
 void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 20/32] target-xtensa: implement loop option
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (18 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 19/32] target-xtensa: implement windowed registers Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 21/32] target-xtensa: implement extended L32R Max Filippov
                   ` (12 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

See ISA, 4.3.2 for details.

Operations that change LEND SR value invalidate TBs at the old and at
the new LEND. LEND value at TB compilation time is considered constant
and loop instruction is generated based on this value.

Invalidation may be avoided for the TB at the old LEND address, since
looping code verifies actual LEND value.

Invalidation may be avoided for the TB at the new LEND address if
there's a way to associate LEND address with TB at compilation time and
later verify that it doesn't change.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/cpu.h       |    3 ++
 target-xtensa/helpers.h   |    2 +
 target-xtensa/op_helper.c |   20 ++++++++++++
 target-xtensa/translate.c |   77 +++++++++++++++++++++++++++++++++++++++-----
 4 files changed, 93 insertions(+), 9 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 7e662f5..97badf2 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -106,6 +106,9 @@ enum {
 };
 
 enum {
+    LBEG = 0,
+    LEND = 1,
+    LCOUNT = 2,
     SAR = 3,
     SCOMPARE1 = 12,
     WINDOW_BASE = 72,
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index 0971fde..b318c5a 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -12,6 +12,8 @@ DEF_HELPER_1(rotw, void, i32)
 DEF_HELPER_2(window_check, void, i32, i32)
 DEF_HELPER_0(restore_owb, void)
 DEF_HELPER_1(movsp, void, i32)
+DEF_HELPER_1(wsr_lbeg, void, i32)
+DEF_HELPER_1(wsr_lend, void, i32)
 DEF_HELPER_0(dump_state, void)
 
 #include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 7f75422..26d2d2e 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -281,6 +281,26 @@ void HELPER(movsp)(uint32_t pc)
     }
 }
 
+void HELPER(wsr_lbeg)(uint32_t v)
+{
+    if (env->sregs[LBEG] != v) {
+        tb_invalidate_phys_page_range(
+                env->sregs[LEND] - 1, env->sregs[LEND], 0);
+        env->sregs[LBEG] = v;
+    }
+}
+
+void HELPER(wsr_lend)(uint32_t v)
+{
+    if (env->sregs[LEND] != v) {
+        tb_invalidate_phys_page_range(
+                env->sregs[LEND] - 1, env->sregs[LEND], 0);
+        env->sregs[LEND] = v;
+        tb_invalidate_phys_page_range(
+                env->sregs[LEND] - 1, env->sregs[LEND], 0);
+    }
+}
+
 void HELPER(dump_state)(void)
 {
     cpu_dump_state(env, stderr, fprintf, 0);
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index de393ff..9371cd2 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -47,6 +47,8 @@ typedef struct DisasContext {
     uint32_t next_pc;
     int cring;
     int ring;
+    uint32_t lbeg;
+    uint32_t lend;
     int is_jmp;
     int singlestep_enabled;
 
@@ -65,6 +67,9 @@ static TCGv_i32 cpu_UR[256];
 #include "gen-icount.h"
 
 static const char * const sregnames[256] = {
+    [LBEG] = "LBEG",
+    [LEND] = "LEND",
+    [LCOUNT] = "LCOUNT",
     [SAR] = "SAR",
     [SCOMPARE1] = "SCOMPARE1",
     [WINDOW_BASE] = "WINDOW_BASE",
@@ -247,13 +252,37 @@ static void gen_callwi(DisasContext *dc, int callinc, uint32_t dest, int slot)
     tcg_temp_free(tmp);
 }
 
+static bool gen_check_loop_end(DisasContext *dc, int slot)
+{
+    if (option_enabled(dc, XTENSA_OPTION_LOOP) &&
+            !(dc->tb->flags & XTENSA_TBFLAG_EXCM) &&
+            dc->next_pc == dc->lend) {
+        int label = gen_new_label();
+
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_SR[LCOUNT], 0, label);
+        tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_SR[LCOUNT], 1);
+        gen_jumpi(dc, dc->lbeg, slot);
+        gen_set_label(label);
+        gen_jumpi(dc, dc->next_pc, -1);
+        return true;
+    }
+    return false;
+}
+
+static void gen_jumpi_check_loop_end(DisasContext *dc, int slot)
+{
+    if (!gen_check_loop_end(dc, slot)) {
+        gen_jumpi(dc, dc->next_pc, slot);
+    }
+}
+
 static void gen_brcond(DisasContext *dc, TCGCond cond,
         TCGv_i32 t0, TCGv_i32 t1, uint32_t offset)
 {
     int label = gen_new_label();
 
     tcg_gen_brcond_i32(cond, t0, t1, label);
-    gen_jumpi(dc, dc->next_pc, 0);
+    gen_jumpi_check_loop_end(dc, 0);
     gen_set_label(label);
     gen_jumpi(dc, dc->pc + offset, 1);
 }
@@ -283,6 +312,16 @@ static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
     }
 }
 
+static void gen_wsr_lbeg(DisasContext *dc, uint32_t sr, TCGv_i32 s)
+{
+    gen_helper_wsr_lbeg(s);
+}
+
+static void gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 s)
+{
+    gen_helper_wsr_lend(s);
+}
+
 static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 {
     tcg_gen_andi_i32(cpu_SR[sr], s, 0x3f);
@@ -308,13 +347,15 @@ static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     }
     tcg_gen_andi_i32(cpu_SR[sr], v, mask);
     /* This can change mmu index, so exit tb */
-    gen_jumpi(dc, dc->next_pc, -1);
+    gen_jumpi_check_loop_end(dc, -1);
 }
 
 static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 {
     static void (* const wsr_handler[256])(DisasContext *dc,
             uint32_t sr, TCGv_i32 v) = {
+        [LBEG] = gen_wsr_lbeg,
+        [LEND] = gen_wsr_lend,
         [SAR] = gen_wsr_sar,
         [WINDOW_BASE] = gen_wsr_windowbase,
         [PS] = gen_wsr_ps,
@@ -1542,15 +1583,29 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 case 8: /*LOOP*/
-                    TBD();
-                    break;
-
                 case 9: /*LOOPNEZ*/
-                    TBD();
-                    break;
-
                 case 10: /*LOOPGTZ*/
-                    TBD();
+                    HAS_OPTION(XTENSA_OPTION_LOOP);
+                    {
+                        uint32_t lend = dc->pc + RRI8_IMM8 + 4;
+                        TCGv_i32 tmp = tcg_const_i32(lend);
+
+                        tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_R[RRI8_S], 1);
+                        tcg_gen_movi_i32(cpu_SR[LBEG], dc->next_pc);
+                        gen_wsr_lend(dc, LEND, tmp);
+                        tcg_temp_free(tmp);
+
+                        if (BRI8_R > 8) {
+                            int label = gen_new_label();
+                            tcg_gen_brcondi_i32(
+                                    BRI8_R == 9 ? TCG_COND_NE : TCG_COND_GT,
+                                    cpu_R[RRI8_S], 0, label);
+                            gen_jumpi(dc, lend, 1);
+                            gen_set_label(label);
+                        }
+
+                        gen_jumpi(dc, dc->next_pc, 0);
+                    }
                     break;
 
                 default: /*reserved*/
@@ -1727,7 +1782,9 @@ static void disas_xtensa_insn(DisasContext *dc)
         break;
     }
 
+    gen_check_loop_end(dc, 0);
     dc->pc = dc->next_pc;
+
     return;
 
 invalid_opcode:
@@ -1773,6 +1830,8 @@ static void gen_intermediate_code_internal(
     dc.pc = pc_start;
     dc.ring = tb->flags & XTENSA_TBFLAG_RING_MASK;
     dc.cring = (tb->flags & XTENSA_TBFLAG_EXCM) ? 0 : dc.ring;
+    dc.lbeg = env->sregs[LBEG];
+    dc.lend = env->sregs[LEND];
     dc.is_jmp = DISAS_NEXT;
 
     init_sar_tracker(&dc);
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 21/32] target-xtensa: implement extended L32R
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (19 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 20/32] target-xtensa: implement loop option Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 22/32] target-xtensa: implement unaligned exception option Max Filippov
                   ` (11 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

See ISA, 4.3.3 for details.

TB flag XTENSA_TBFLAG_LITBASE is used to track enable bit of LITBASE SR.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/cpu.h       |    6 ++++++
 target-xtensa/helper.c    |    1 +
 target-xtensa/translate.c |   37 +++++++++++++++++++++++++++++++++----
 3 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 97badf2..1283fd9 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -110,6 +110,7 @@ enum {
     LEND = 1,
     LCOUNT = 2,
     SAR = 3,
+    LITBASE = 5,
     SCOMPARE1 = 12,
     WINDOW_BASE = 72,
     WINDOW_START = 73,
@@ -274,6 +275,7 @@ static inline int cpu_mmu_index(CPUState *env)
 
 #define XTENSA_TBFLAG_RING_MASK 0x3
 #define XTENSA_TBFLAG_EXCM 0x4
+#define XTENSA_TBFLAG_LITBASE 0x8
 
 static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
         target_ulong *cs_base, int *flags)
@@ -285,6 +287,10 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
     if (env->sregs[PS] & PS_EXCM) {
         *flags |= XTENSA_TBFLAG_EXCM;
     }
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_EXTENDED_L32R) &&
+            (env->sregs[LITBASE] & 1)) {
+        *flags |= XTENSA_TBFLAG_LITBASE;
+    }
 }
 
 #include "cpu-all.h"
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 4f86934..074207f 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -38,6 +38,7 @@ void cpu_reset(CPUXtensaState *env)
 {
     env->exception_taken = 0;
     env->pc = env->config->exception_vector[EXC_RESET];
+    env->sregs[LITBASE] &= ~1;
     env->sregs[PS] = 0x1f;
 }
 
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 9371cd2..7bcbe4f 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -49,6 +49,7 @@ typedef struct DisasContext {
     int ring;
     uint32_t lbeg;
     uint32_t lend;
+    TCGv_i32 litbase;
     int is_jmp;
     int singlestep_enabled;
 
@@ -71,6 +72,7 @@ static const char * const sregnames[256] = {
     [LEND] = "LEND",
     [LCOUNT] = "LCOUNT",
     [SAR] = "SAR",
+    [LITBASE] = "LITBASE",
     [SCOMPARE1] = "SCOMPARE1",
     [WINDOW_BASE] = "WINDOW_BASE",
     [WINDOW_START] = "WINDOW_START",
@@ -132,6 +134,21 @@ static inline bool option_enabled(DisasContext *dc, int opt)
     return xtensa_option_enabled(dc->config, opt);
 }
 
+static void init_litbase(DisasContext *dc)
+{
+    if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
+        dc->litbase = tcg_temp_local_new_i32();
+        tcg_gen_andi_i32(dc->litbase, cpu_SR[LITBASE], 0xfffff000);
+    }
+}
+
+static void reset_litbase(DisasContext *dc)
+{
+    if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
+        tcg_temp_free(dc->litbase);
+    }
+}
+
 static void init_sar_tracker(DisasContext *dc)
 {
     dc->sar_5bit = false;
@@ -332,6 +349,13 @@ static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
     dc->sar_m32_5bit = false;
 }
 
+static void gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s)
+{
+    tcg_gen_andi_i32(cpu_SR[sr], s, 0xfffff001);
+    /* This can change tb->flags, so exit tb */
+    gen_jumpi_check_loop_end(dc, -1);
+}
+
 static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     gen_helper_wsr_windowbase(v);
@@ -357,6 +381,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [LBEG] = gen_wsr_lbeg,
         [LEND] = gen_wsr_lend,
         [SAR] = gen_wsr_sar,
+        [LITBASE] = gen_wsr_litbase,
         [WINDOW_BASE] = gen_wsr_windowbase,
         [PS] = gen_wsr_ps,
     };
@@ -1298,11 +1323,13 @@ static void disas_xtensa_insn(DisasContext *dc)
     case 1: /*L32R*/
         {
             TCGv_i32 tmp = tcg_const_i32(
-                    (0xfffc0000 | (RI16_IMM16 << 2)) +
-                    ((dc->pc + 3) & ~3));
-
-            /* no ext L32R */
+                    ((dc->tb->flags & XTENSA_TBFLAG_LITBASE) ?
+                     0 : ((dc->pc + 3) & ~3)) +
+                    (0xfffc0000 | (RI16_IMM16 << 2)));
 
+            if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
+                tcg_gen_add_i32(tmp, tmp, dc->litbase);
+            }
             tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, dc->cring);
             tcg_temp_free(tmp);
         }
@@ -1834,6 +1861,7 @@ static void gen_intermediate_code_internal(
     dc.lend = env->sregs[LEND];
     dc.is_jmp = DISAS_NEXT;
 
+    init_litbase(&dc);
     init_sar_tracker(&dc);
 
     gen_icount_start();
@@ -1876,6 +1904,7 @@ static void gen_intermediate_code_internal(
             dc.pc < next_page_start &&
             gen_opc_ptr < gen_opc_end);
 
+    reset_litbase(&dc);
     reset_sar_tracker(&dc);
 
     if (dc.is_jmp == DISAS_NEXT) {
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 22/32] target-xtensa: implement unaligned exception option
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (20 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 21/32] target-xtensa: implement extended L32R Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-04 18:28   ` Blue Swirl
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 23/32] target-xtensa: implement SIMCALL Max Filippov
                   ` (10 subsequent siblings)
  32 siblings, 1 reply; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

See ISA, 4.4.4 for details.

Correct (aligned as per ISA) address for unaligned access is generated
in case this option is not enabled.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/helper.c    |    4 ++-
 target-xtensa/op_helper.c |   26 ++++++++++++++++++++++++
 target-xtensa/translate.c |   47 ++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 73 insertions(+), 4 deletions(-)

diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 074207f..bcd6c77 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -45,7 +45,9 @@ void cpu_reset(CPUXtensaState *env)
 static const XtensaConfig core_config[] = {
     {
         .name = "sample-xtensa-core",
-        .options = -1,
+        .options = -1 ^
+            (XTENSA_OPTION_BIT(XTENSA_OPTION_HW_ALIGNMENT) |
+             XTENSA_OPTION_BIT(XTENSA_OPTION_MMU)),
         .nareg = 64,
         .ndepc = 1,
         .excm_level = 16,
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 26d2d2e..8577f5d 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -30,6 +30,10 @@
 #include "helpers.h"
 #include "host-utils.h"
 
+static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
+        void *retaddr);
+
+#define ALIGNED_ONLY
 #define MMUSUFFIX _mmu
 
 #define SHIFT 0
@@ -44,6 +48,28 @@
 #define SHIFT 3
 #include "softmmu_template.h"
 
+static void do_restore_state(void *pc_ptr)
+{
+    TranslationBlock *tb;
+    uint32_t pc = (uint32_t)(intptr_t)pc_ptr;
+
+    tb = tb_find_pc(pc);
+    if (tb) {
+        cpu_restore_state(tb, env, pc);
+    }
+}
+
+static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
+        void *retaddr)
+{
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_UNALIGNED_EXCEPTION) &&
+            !xtensa_option_enabled(env->config, XTENSA_OPTION_HW_ALIGNMENT)) {
+        do_restore_state(retaddr);
+        HELPER(exception_cause_vaddr)(
+                env->pc, LOAD_STORE_ALIGNMENT_CAUSE, addr);
+    }
+}
+
 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 {
     tlb_set_page(cpu_single_env,
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 7bcbe4f..ad2b699 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -203,6 +203,16 @@ static void gen_exception_cause(DisasContext *dc, uint32_t cause)
     tcg_temp_free(_cause);
 }
 
+static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
+        TCGv_i32 vaddr)
+{
+    TCGv_i32 _pc = tcg_const_i32(dc->pc);
+    TCGv_i32 _cause = tcg_const_i32(cause);
+    gen_helper_exception_cause_vaddr(_pc, _cause, vaddr);
+    tcg_temp_free(_pc);
+    tcg_temp_free(_cause);
+}
+
 static void gen_check_privilege(DisasContext *dc)
 {
     if (dc->cring) {
@@ -397,6 +407,23 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
     }
 }
 
+static void gen_load_store_alignment(DisasContext *dc, int shift,
+        TCGv_i32 addr, bool no_hw_alignment)
+{
+    if (!option_enabled(dc, XTENSA_OPTION_UNALIGNED_EXCEPTION)) {
+        tcg_gen_andi_i32(addr, addr, ~0 << shift);
+    } else if (option_enabled(dc, XTENSA_OPTION_HW_ALIGNMENT) &&
+            no_hw_alignment) {
+        int label = gen_new_label();
+        TCGv_i32 tmp = tcg_temp_new_i32();
+        tcg_gen_andi_i32(tmp, addr, ~(~0 << shift));
+        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
+        gen_exception_cause_vaddr(dc, LOAD_STORE_ALIGNMENT_CAUSE, addr);
+        gen_set_label(label);
+        tcg_temp_free(tmp);
+    }
+}
+
 static void disas_xtensa_insn(DisasContext *dc)
 {
 #define HAS_OPTION(opt) do { \
@@ -1339,6 +1366,9 @@ static void disas_xtensa_insn(DisasContext *dc)
 #define gen_load_store(type, shift) do { \
             TCGv_i32 addr = tcg_temp_new_i32(); \
             tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \
+            if (shift) { \
+                gen_load_store_alignment(dc, shift, addr, false); \
+            } \
             tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
             tcg_temp_free(addr); \
         } while (0)
@@ -1468,6 +1498,7 @@ static void disas_xtensa_insn(DisasContext *dc)
         case 9: /*L16SI*/
             gen_load_store(ld16s, 1);
             break;
+#undef gen_load_store
 
         case 10: /*MOVI*/
             tcg_gen_movi_i32(cpu_R[RRI8_T],
@@ -1475,9 +1506,17 @@ static void disas_xtensa_insn(DisasContext *dc)
                     ((RRI8_S & 0x8) ? 0xfffff000 : 0));
             break;
 
+#define gen_load_store_no_hw_align(type) do { \
+            TCGv_i32 addr = tcg_temp_local_new_i32(); \
+            tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); \
+            gen_load_store_alignment(dc, 2, addr, true); \
+            tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
+            tcg_temp_free(addr); \
+        } while (0)
+
         case 11: /*L32AIy*/
             HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
-            gen_load_store(ld32u, 2); /*TODO acquire?*/
+            gen_load_store_no_hw_align(ld32u); /*TODO acquire?*/
             break;
 
         case 12: /*ADDI*/
@@ -1497,6 +1536,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                 tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]);
                 tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
+                gen_load_store_alignment(dc, 2, addr, true);
                 tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, dc->cring);
                 tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T],
                         cpu_SR[SCOMPARE1], label);
@@ -1511,15 +1551,15 @@ static void disas_xtensa_insn(DisasContext *dc)
 
         case 15: /*S32RIy*/
             HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
-            gen_load_store(st32, 2); /*TODO release?*/
+            gen_load_store_no_hw_align(st32); /*TODO release?*/
             break;
+#undef gen_load_store_no_hw_align
 
         default: /*reserved*/
             RESERVED();
             break;
         }
         break;
-#undef gen_load_store
 
     case 3: /*LSCIp*/
         HAS_OPTION(XTENSA_OPTION_COPROCESSOR);
@@ -1725,6 +1765,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 #define gen_narrow_load_store(type) do { \
             TCGv_i32 addr = tcg_temp_new_i32(); \
             tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
+            gen_load_store_alignment(dc, 2, addr, false); \
             tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, dc->cring); \
             tcg_temp_free(addr); \
         } while (0)
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 23/32] target-xtensa: implement SIMCALL
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (21 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 22/32] target-xtensa: implement unaligned exception option Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 24/32] target-xtensa: implement interrupt option Max Filippov
                   ` (9 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Tensilica iss provides support for applications running in freestanding
environment through SIMCALL command. It is used by Tensilica libc to
access argc/argv, for file I/O, etc.

Note that simcalls that accept buffer addresses expect virtual addresses.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 Makefile.target           |    1 +
 qemu-options.hx           |    4 +-
 target-xtensa/helpers.h   |    1 +
 target-xtensa/translate.c |    9 ++-
 xtensa-semi.c             |  224 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 236 insertions(+), 3 deletions(-)
 create mode 100644 xtensa-semi.c

diff --git a/Makefile.target b/Makefile.target
index 98455e3..9bbb668 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -375,6 +375,7 @@ obj-alpha-y += vga.o cirrus_vga.o
 
 obj-xtensa-y += xtensa_pic.o
 obj-xtensa-y += xtensa_sample.o
+obj-xtensa-y += xtensa-semi.o
 
 main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
diff --git a/qemu-options.hx b/qemu-options.hx
index 35d95d1..e2bb700 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2396,11 +2396,11 @@ STEXI
 Set OpenBIOS nvram @var{variable} to given @var{value} (PPC, SPARC only).
 ETEXI
 DEF("semihosting", 0, QEMU_OPTION_semihosting,
-    "-semihosting    semihosting mode\n", QEMU_ARCH_ARM | QEMU_ARCH_M68K)
+    "-semihosting    semihosting mode\n", QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA)
 STEXI
 @item -semihosting
 @findex -semihosting
-Semihosting mode (ARM, M68K only).
+Semihosting mode (ARM, M68K, Xtensa only).
 ETEXI
 DEF("old-param", 0, QEMU_OPTION_old_param,
     "-old-param      old param mode\n", QEMU_ARCH_ARM)
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index b318c5a..6e02d26 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -14,6 +14,7 @@ DEF_HELPER_0(restore_owb, void)
 DEF_HELPER_1(movsp, void, i32)
 DEF_HELPER_1(wsr_lbeg, void, i32)
 DEF_HELPER_1(wsr_lend, void, i32)
+DEF_HELPER_1(simcall, void, env)
 DEF_HELPER_0(dump_state, void)
 
 #include "def-helper.h"
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index ad2b699..f58a5fc 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -35,6 +35,7 @@
 #include "disas.h"
 #include "tcg-op.h"
 #include "qemu-log.h"
+#include "sysemu.h"
 
 #include "helpers.h"
 #define GEN_HELPER 1
@@ -726,7 +727,13 @@ static void disas_xtensa_insn(DisasContext *dc)
                         break;
 
                     case 1: /*SIMCALL*/
-                        TBD();
+                        if (semihosting_enabled) {
+                            gen_check_privilege(dc);
+                            gen_helper_simcall(cpu_env);
+                        } else {
+                            qemu_log("SIMCALL but semihosting is disabled\n");
+                            gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
+                        }
                         break;
 
                     default:
diff --git a/xtensa-semi.c b/xtensa-semi.c
new file mode 100644
index 0000000..ba0e828
--- /dev/null
+++ b/xtensa-semi.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stddef.h>
+#include "cpu.h"
+#include "dyngen-exec.h"
+#include "helpers.h"
+#include "qemu-log.h"
+
+enum {
+    TARGET_SYS_exit = 1,
+    TARGET_SYS_read = 3,
+    TARGET_SYS_write = 4,
+    TARGET_SYS_open = 5,
+    TARGET_SYS_close = 6,
+    TARGET_SYS_lseek = 19,
+    TARGET_SYS_select_one = 29,
+
+    TARGET_SYS_argc = 1000,
+    TARGET_SYS_argv_sz = 1001,
+    TARGET_SYS_argv = 1002,
+    TARGET_SYS_memset = 1004,
+};
+
+enum {
+    SELECT_ONE_READ   = 1,
+    SELECT_ONE_WRITE  = 2,
+    SELECT_ONE_EXCEPT = 3,
+};
+
+void HELPER(simcall)(CPUState *env)
+{
+    uint32_t *regs = env->regs;
+
+    switch (regs[2]) {
+    case TARGET_SYS_exit:
+        qemu_log("exit(%d) simcall\n", regs[3]);
+        exit(regs[3]);
+        break;
+
+    case TARGET_SYS_read:
+    case TARGET_SYS_write:
+        {
+            bool is_write = regs[2] == TARGET_SYS_write;
+            uint32_t fd = regs[3];
+            uint32_t vaddr = regs[4];
+            uint32_t len = regs[5];
+
+            while (len > 0) {
+                target_phys_addr_t paddr =
+                    cpu_get_phys_page_debug(env, vaddr);
+                uint32_t page_left =
+                    TARGET_PAGE_SIZE - (vaddr & (TARGET_PAGE_SIZE - 1));
+                uint32_t io_sz = page_left < len ? page_left : len;
+                target_phys_addr_t sz = io_sz;
+                void *buf = cpu_physical_memory_map(paddr, &sz, is_write);
+
+                if (buf) {
+                    vaddr += io_sz;
+                    len -= io_sz;
+                    regs[2] = is_write ?
+                        write(fd, buf, io_sz) :
+                        read(fd, buf, io_sz);
+                    regs[3] = errno;
+                    cpu_physical_memory_unmap(buf, sz, is_write, sz);
+                    if (regs[2] == -1) {
+                        break;
+                    }
+                } else {
+                    regs[2] = -1;
+                    regs[3] = EINVAL;
+                    break;
+                }
+            }
+        }
+        break;
+
+    case TARGET_SYS_open:
+        {
+            char name[1024];
+            int rc;
+            int i;
+
+            for (i = 0; i < ARRAY_SIZE(name); ++i) {
+                rc = cpu_memory_rw_debug(
+                        env, regs[3] + i, (uint8_t *)name + i, 1, 0);
+                if (rc != 0 || name[i] == 0) {
+                    break;
+                }
+            }
+
+            if (rc == 0 && i < ARRAY_SIZE(name)) {
+                regs[2] = open(name, regs[4], regs[5]);
+                regs[3] = errno;
+            } else {
+                regs[2] = -1;
+                regs[3] = EINVAL;
+            }
+        }
+        break;
+
+    case TARGET_SYS_close:
+        if (regs[3] < 3) {
+            regs[2] = regs[3] = 0;
+        } else {
+            regs[2] = close(regs[3]);
+            regs[3] = errno;
+        }
+        break;
+
+    case TARGET_SYS_lseek:
+        regs[2] = lseek(regs[3], (off_t)(int32_t)regs[4], regs[5]);
+        regs[3] = errno;
+        break;
+
+    case TARGET_SYS_select_one:
+        {
+            uint32_t fd = regs[3];
+            uint32_t rq = regs[4];
+            uint32_t target_tv = regs[5];
+            uint32_t target_tvv[2];
+
+            struct timeval tv = {0};
+            fd_set fdset;
+
+            FD_ZERO(&fdset);
+            FD_SET(fd, &fdset);
+
+            if (target_tv) {
+                cpu_memory_rw_debug(env, target_tv,
+                        (uint8_t *)target_tvv, sizeof(target_tvv), 0);
+                tv.tv_sec = (int32_t)tswap32(target_tvv[0]);
+                tv.tv_usec = (int32_t)tswap32(target_tvv[1]);
+            }
+            regs[2] = select(fd + 1,
+                    rq == SELECT_ONE_READ   ? &fdset : NULL,
+                    rq == SELECT_ONE_WRITE  ? &fdset : NULL,
+                    rq == SELECT_ONE_EXCEPT ? &fdset : NULL,
+                    target_tv ? &tv : NULL);
+            regs[3] = errno;
+        }
+        break;
+
+    case TARGET_SYS_argc:
+        regs[2] = 1;
+        regs[3] = 0;
+        break;
+
+    case TARGET_SYS_argv_sz:
+        regs[2] = 128;
+        regs[3] = 0;
+        break;
+
+    case TARGET_SYS_argv:
+        {
+            struct Argv {
+                uint32_t argptr[2];
+                char text[120];
+            } argv = {
+                {0, 0},
+                "test"
+            };
+
+            argv.argptr[0] = tswap32(regs[3] + offsetof(struct Argv, text));
+            cpu_memory_rw_debug(
+                    env, regs[3], (uint8_t *)&argv, sizeof(argv), 1);
+        }
+        break;
+
+    case TARGET_SYS_memset:
+        {
+            uint32_t base = regs[3];
+            uint32_t sz = regs[5];
+
+            while (sz) {
+                target_phys_addr_t len = sz;
+                void *buf = cpu_physical_memory_map(base, &len, 1);
+
+                if (buf && len) {
+                    memset(buf, regs[4], len);
+                    cpu_physical_memory_unmap(buf, len, 1, len);
+                } else {
+                    len = 1;
+                }
+                base += len;
+                sz -= len;
+            }
+            regs[2] = regs[3];
+            regs[3] = 0;
+        }
+        break;
+
+    default:
+        qemu_log("%s(%d): not implemented\n", __func__, regs[2]);
+        break;
+    }
+}
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 24/32] target-xtensa: implement interrupt option
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (22 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 23/32] target-xtensa: implement SIMCALL Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 25/32] target-xtensa: implement accurate window check Max Filippov
                   ` (8 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

See ISA, 4.4.6 (interrupt option), 4.4.7 (high priority interrupt
option) and 4.4.8 (timer interrupt option) for details.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 hw/xtensa_pic.c           |   96 ++++++++++++++++++++++++++++
 target-xtensa/cpu.h       |   45 +++++++++++++-
 target-xtensa/helper.c    |   98 ++++++++++++++++++++++++++++-
 target-xtensa/helpers.h   |    5 ++
 target-xtensa/op_helper.c |   46 ++++++++++++++
 target-xtensa/translate.c |  153 ++++++++++++++++++++++++++++++++++++++++++---
 6 files changed, 431 insertions(+), 12 deletions(-)

diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
index 91a5445..3033ae2 100644
--- a/hw/xtensa_pic.c
+++ b/hw/xtensa_pic.c
@@ -27,6 +27,8 @@
 
 #include "hw.h"
 #include "pc.h"
+#include "qemu-log.h"
+#include "qemu-timer.h"
 
 /* Stub functions for hardware that doesn't exist.  */
 void pic_info(Monitor *mon)
@@ -36,3 +38,97 @@ void pic_info(Monitor *mon)
 void irq_info(Monitor *mon)
 {
 }
+
+void xtensa_advance_ccount(CPUState *env, uint32_t d)
+{
+    uint32_t old_ccount = env->sregs[CCOUNT];
+
+    env->sregs[CCOUNT] += d;
+
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
+        int i;
+        for (i = 0; i < env->config->nccompare; ++i) {
+            if (env->sregs[CCOMPARE + i] - old_ccount <= d) {
+                xtensa_timer_irq(env, i, 1);
+            }
+        }
+    }
+}
+
+void check_interrupts(CPUState *env)
+{
+    int minlevel = xtensa_get_cintlevel(env);
+    uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE];
+    int level;
+
+    /* If the CPU is halted advance CCOUNT according to the vm_clock time
+     * elapsed since the moment when it was advanced last time.
+     */
+    if (env->halted) {
+        int64_t now = qemu_get_clock_ns(vm_clock);
+
+        xtensa_advance_ccount(env,
+                muldiv64(now - env->halt_clock,
+                    env->config->clock_freq_khz, 1000000));
+        env->halt_clock = now;
+    }
+    for (level = env->config->nlevel; level > minlevel; --level) {
+        if (env->config->level_mask[level] & int_set_enabled) {
+            env->pending_irq_level = level;
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            qemu_log_mask(CPU_LOG_INT,
+                    "%s level = %d, cintlevel = %d, "
+                    "pc = %08x, a0 = %08x, ps = %08x, "
+                    "intset = %08x, intenable = %08x, "
+                    "ccount = %08x\n",
+                    __func__, level, xtensa_get_cintlevel(env),
+                    env->pc, env->regs[0], env->sregs[PS],
+                    env->sregs[INTSET], env->sregs[INTENABLE],
+                    env->sregs[CCOUNT]);
+            return;
+        }
+    }
+    env->pending_irq_level = 0;
+    cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+}
+
+static void xtensa_set_irq(void *opaque, int irq, int active)
+{
+    CPUState *env = opaque;
+
+    if (irq >= env->config->ninterrupt) {
+        qemu_log("%s: bad IRQ %d\n", __func__, irq);
+    } else {
+        uint32_t irq_bit = 1 << irq;
+
+        if (active) {
+            env->sregs[INTSET] |= irq_bit;
+        } else if (env->config->interrupt[irq].inttype == INTTYPE_LEVEL) {
+            env->sregs[INTSET] &= ~irq_bit;
+        }
+
+        check_interrupts(env);
+    }
+}
+
+void xtensa_timer_irq(CPUState *env, uint32_t id, uint32_t active)
+{
+    qemu_set_irq(env->irq_inputs[env->config->timerint[id]], active);
+}
+
+static void xtensa_ccompare_cb(void *opaque)
+{
+    CPUState *env = opaque;
+    xtensa_advance_ccount(env, env->wake_ccount - env->sregs[CCOUNT]);
+}
+
+void xtensa_irq_init(CPUState *env)
+{
+    env->irq_inputs = (void **)qemu_allocate_irqs(
+            xtensa_set_irq, env, env->config->ninterrupt);
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT) &&
+            env->config->nccompare > 0) {
+        env->ccompare_timer =
+            qemu_new_timer_ns(vm_clock, &xtensa_ccompare_cb, env);
+    }
+}
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 1283fd9..474466c 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -116,10 +116,16 @@ enum {
     WINDOW_START = 73,
     EPC1 = 177,
     DEPC = 192,
+    EPS2 = 194,
     EXCSAVE1 = 209,
+    INTSET = 226,
+    INTCLEAR = 227,
+    INTENABLE = 228,
     PS = 230,
     EXCCAUSE = 232,
+    CCOUNT = 234,
     EXCVADDR = 238,
+    CCOMPARE = 240,
 };
 
 #define PS_INTLEVEL 0xf
@@ -141,6 +147,10 @@ enum {
 #define PS_WOE 0x40000
 
 #define MAX_NAREG 64
+#define MAX_NINTERRUPT 32
+#define MAX_NLEVEL 6
+#define MAX_NNMI 1
+#define MAX_NCCOMPARE 3
 
 enum {
     /* Static vectors */
@@ -190,6 +200,17 @@ enum {
     COPROCESSOR0_DISABLED = 32,
 };
 
+typedef enum {
+    INTTYPE_LEVEL,
+    INTTYPE_EDGE,
+    INTTYPE_NMI,
+    INTTYPE_SOFTWARE,
+    INTTYPE_TIMER,
+    INTTYPE_DEBUG,
+    INTTYPE_WRITE_ERR,
+    INTTYPE_MAX
+} interrupt_type;
+
 typedef struct XtensaConfig {
     const char *name;
     uint64_t options;
@@ -197,6 +218,18 @@ typedef struct XtensaConfig {
     int excm_level;
     int ndepc;
     uint32_t exception_vector[EXC_MAX];
+    unsigned ninterrupt;
+    unsigned nlevel;
+    uint32_t interrupt_vector[MAX_NLEVEL + MAX_NNMI + 1];
+    uint32_t level_mask[MAX_NLEVEL + MAX_NNMI + 1];
+    uint32_t inttype_mask[INTTYPE_MAX];
+    struct {
+        uint32_t level;
+        interrupt_type inttype;
+    } interrupt[MAX_NINTERRUPT];
+    unsigned nccompare;
+    uint32_t timerint[MAX_NCCOMPARE];
+    uint32_t clock_freq_khz;
 } XtensaConfig;
 
 typedef struct CPUXtensaState {
@@ -207,6 +240,12 @@ typedef struct CPUXtensaState {
     uint32_t uregs[256];
     uint32_t phys_regs[MAX_NAREG];
 
+    int pending_irq_level; /* level of last raised IRQ */
+    void **irq_inputs;
+    QEMUTimer *ccompare_timer;
+    uint32_t wake_ccount;
+    int64_t halt_clock;
+
     int exception_taken;
 
     CPU_COMMON
@@ -222,6 +261,10 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model);
 void xtensa_translate_init(void);
 int cpu_xtensa_exec(CPUXtensaState *s);
 void do_interrupt(CPUXtensaState *s);
+void check_interrupts(CPUXtensaState *s);
+void xtensa_irq_init(CPUState *env);
+void xtensa_advance_ccount(CPUState *env, uint32_t d);
+void xtensa_timer_irq(CPUState *env, uint32_t id, uint32_t active);
 int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
 void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 void xtensa_sync_window_from_phys(CPUState *env);
@@ -298,7 +341,7 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 
 static inline int cpu_has_work(CPUState *env)
 {
-    return 1;
+    return env->pending_irq_level;
 }
 
 static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index bcd6c77..c24a38a 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -39,7 +39,10 @@ void cpu_reset(CPUXtensaState *env)
     env->exception_taken = 0;
     env->pc = env->config->exception_vector[EXC_RESET];
     env->sregs[LITBASE] &= ~1;
-    env->sregs[PS] = 0x1f;
+    env->sregs[PS] = xtensa_option_enabled(env->config,
+            XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
+
+    env->pending_irq_level = 0;
 }
 
 static const XtensaConfig core_config[] = {
@@ -63,6 +66,31 @@ static const XtensaConfig core_config[] = {
             [EXC_USER] = 0x5fff863c,
             [EXC_DOUBLE] = 0x5fff865c,
         },
+        .ninterrupt = 13,
+        .nlevel = 6,
+        .interrupt_vector = {
+            0,
+            0,
+            0x5fff857c,
+            0x5fff859c,
+            0x5fff85bc,
+            0x5fff85dc,
+            0x5fff85fc,
+        },
+        .level_mask = {
+            [4] = 1,
+        },
+        .interrupt = {
+            [0] = {
+                .level = 4,
+                .inttype = INTTYPE_TIMER,
+            },
+        },
+        .nccompare = 1,
+        .timerint = {
+            [0] = 0,
+        },
+        .clock_freq_khz = 912000,
     },
 };
 
@@ -92,6 +120,7 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
         xtensa_translate_init();
     }
 
+    xtensa_irq_init(env);
     qemu_init_vcpu(env);
     return env;
 }
@@ -111,8 +140,63 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
     return addr;
 }
 
+/*!
+ * Handle penging IRQ.
+ * For the high priority interrupt jump to the corresponding interrupt vector.
+ * For the level-1 interrupt convert it to either user, kernel or double
+ * exception with the 'level-1 interrupt' exception cause.
+ */
+static void handle_interrupt(CPUState *env)
+{
+    int level = env->pending_irq_level;
+
+    if (level > xtensa_get_cintlevel(env) &&
+            level <= env->config->nlevel &&
+            (env->config->level_mask[level] &
+             env->sregs[INTSET] &
+             env->sregs[INTENABLE])) {
+        if (level > 1) {
+            env->sregs[EPC1 + level - 1] = env->pc;
+            env->sregs[EPS2 + level - 2] = env->sregs[PS];
+            env->sregs[PS] =
+                (env->sregs[PS] & ~PS_INTLEVEL) | level | PS_EXCM;
+            env->pc = env->config->interrupt_vector[level];
+        } else {
+            env->sregs[EXCCAUSE] = LEVEL1_INTERRUPT_CAUSE;
+
+            if (env->sregs[PS] & PS_EXCM) {
+                if (env->config->ndepc) {
+                    env->sregs[DEPC] = env->pc;
+                } else {
+                    env->sregs[EPC1] = env->pc;
+                }
+                env->exception_index = EXC_DOUBLE;
+            } else {
+                env->sregs[EPC1] = env->pc;
+                env->exception_index =
+                    (env->sregs[PS] & PS_UM) ? EXC_USER : EXC_KERNEL;
+            }
+            env->sregs[PS] |= PS_EXCM;
+        }
+        env->exception_taken = 1;
+    }
+}
+
 void do_interrupt(CPUState *env)
 {
+    if (env->exception_index == EXC_IRQ) {
+        qemu_log_mask(CPU_LOG_INT,
+                "%s(EXC_IRQ) level = %d, cintlevel = %d, "
+                "pc = %08x, a0 = %08x, ps = %08x, "
+                "intset = %08x, intenable = %08x, "
+                "ccount = %08x\n",
+                __func__, env->pending_irq_level, xtensa_get_cintlevel(env),
+                env->pc, env->regs[0], env->sregs[PS],
+                env->sregs[INTSET], env->sregs[INTENABLE],
+                env->sregs[CCOUNT]);
+        handle_interrupt(env);
+    }
+
     switch (env->exception_index) {
     case EXC_WINDOW_OVERFLOW4:
     case EXC_WINDOW_UNDERFLOW4:
@@ -123,6 +207,10 @@ void do_interrupt(CPUState *env)
     case EXC_KERNEL:
     case EXC_USER:
     case EXC_DOUBLE:
+        qemu_log_mask(CPU_LOG_INT, "%s(%d) "
+                "pc = %08x, a0 = %08x, ps = %08x, ccount = %08x\n",
+                __func__, env->exception_index,
+                env->pc, env->regs[0], env->sregs[PS], env->sregs[CCOUNT]);
         if (env->config->exception_vector[env->exception_index]) {
             env->pc = env->config->exception_vector[env->exception_index];
             env->exception_taken = 1;
@@ -132,5 +220,13 @@ void do_interrupt(CPUState *env)
         }
         break;
 
+    case EXC_IRQ:
+        break;
+
+    default:
+        qemu_log("%s(pc = %08x) unknown exception_index: %d\n",
+                __func__, env->pc, env->exception_index);
+        break;
     }
+    check_interrupts(env);
 }
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index 6e02d26..28689c3 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -17,4 +17,9 @@ DEF_HELPER_1(wsr_lend, void, i32)
 DEF_HELPER_1(simcall, void, env)
 DEF_HELPER_0(dump_state, void)
 
+DEF_HELPER_2(waiti, void, i32, i32)
+DEF_HELPER_2(timer_irq, void, i32, i32)
+DEF_HELPER_1(advance_ccount, void, i32)
+DEF_HELPER_1(check_interrupts, void, env)
+
 #include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 8577f5d..fcec506 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -331,3 +331,49 @@ void HELPER(dump_state)(void)
 {
     cpu_dump_state(env, stderr, fprintf, 0);
 }
+
+void HELPER(waiti)(uint32_t pc, uint32_t intlevel)
+{
+    env->pc = pc;
+    env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) |
+        (intlevel << PS_INTLEVEL_SHIFT);
+    check_interrupts(env);
+    if (env->pending_irq_level) {
+        cpu_loop_exit(env);
+        return;
+    }
+
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
+        int i;
+        uint32_t wake_ccount = env->sregs[CCOUNT] - 1;
+
+        for (i = 0; i < env->config->nccompare; ++i) {
+            if (env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] <
+                    wake_ccount - env->sregs[CCOUNT]) {
+                wake_ccount = env->sregs[CCOMPARE + i];
+            }
+        }
+        env->wake_ccount = wake_ccount;
+        qemu_mod_timer(env->ccompare_timer, qemu_get_clock_ns(vm_clock) +
+                muldiv64(wake_ccount - env->sregs[CCOUNT],
+                    1000000, env->config->clock_freq_khz));
+    }
+    env->halt_clock = qemu_get_clock_ns(vm_clock);
+    env->halted = 1;
+    HELPER(exception)(EXCP_HLT);
+}
+
+void HELPER(timer_irq)(uint32_t id, uint32_t active)
+{
+    xtensa_timer_irq(env, id, active);
+}
+
+void HELPER(advance_ccount)(uint32_t d)
+{
+    xtensa_advance_ccount(env, d);
+}
+
+void HELPER(check_interrupts)(CPUState *env)
+{
+    check_interrupts(env);
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index f58a5fc..eb49e98 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -58,6 +58,8 @@ typedef struct DisasContext {
     bool sar_m32_5bit;
     bool sar_m32_allocated;
     TCGv_i32 sar_m32;
+
+    uint32_t ccount_delta;
 } DisasContext;
 
 static TCGv_ptr cpu_env;
@@ -78,11 +80,36 @@ static const char * const sregnames[256] = {
     [WINDOW_BASE] = "WINDOW_BASE",
     [WINDOW_START] = "WINDOW_START",
     [EPC1] = "EPC1",
+    [EPC1 + 1] = "EPC2",
+    [EPC1 + 2] = "EPC3",
+    [EPC1 + 3] = "EPC4",
+    [EPC1 + 4] = "EPC5",
+    [EPC1 + 5] = "EPC6",
+    [EPC1 + 6] = "EPC7",
     [DEPC] = "DEPC",
+    [EPS2] = "EPS2",
+    [EPS2 + 1] = "EPS3",
+    [EPS2 + 2] = "EPS4",
+    [EPS2 + 3] = "EPS5",
+    [EPS2 + 4] = "EPS6",
+    [EPS2 + 5] = "EPS7",
     [EXCSAVE1] = "EXCSAVE1",
+    [EXCSAVE1 + 1] = "EXCSAVE2",
+    [EXCSAVE1 + 2] = "EXCSAVE3",
+    [EXCSAVE1 + 3] = "EXCSAVE4",
+    [EXCSAVE1 + 4] = "EXCSAVE5",
+    [EXCSAVE1 + 5] = "EXCSAVE6",
+    [EXCSAVE1 + 6] = "EXCSAVE7",
+    [INTSET] = "INTSET",
+    [INTCLEAR] = "INTCLEAR",
+    [INTENABLE] = "INTENABLE",
     [PS] = "PS",
     [EXCCAUSE] = "EXCCAUSE",
+    [CCOUNT] = "CCOUNT",
     [EXCVADDR] = "EXCVADDR",
+    [CCOMPARE] = "CCOMPARE0",
+    [CCOMPARE + 1] = "CCOMPARE1",
+    [CCOMPARE + 2] = "CCOMPARE2",
 };
 
 static const char * const uregnames[256] = {
@@ -188,9 +215,20 @@ static void gen_left_shift_sar(DisasContext *dc, TCGv_i32 sa)
     tcg_temp_free(tmp);
 }
 
-static void gen_exception(int excp)
+static void gen_advance_ccount(DisasContext *dc)
+{
+    if (dc->ccount_delta > 0) {
+        TCGv_i32 tmp = tcg_const_i32(dc->ccount_delta);
+        dc->ccount_delta = 0;
+        gen_helper_advance_ccount(tmp);
+        tcg_temp_free(tmp);
+    }
+}
+
+static void gen_exception(DisasContext *dc, int excp)
 {
     TCGv_i32 tmp = tcg_const_i32(excp);
+    gen_advance_ccount(dc);
     gen_helper_exception(tmp);
     tcg_temp_free(tmp);
 }
@@ -199,6 +237,7 @@ static void gen_exception_cause(DisasContext *dc, uint32_t cause)
 {
     TCGv_i32 _pc = tcg_const_i32(dc->pc);
     TCGv_i32 _cause = tcg_const_i32(cause);
+    gen_advance_ccount(dc);
     gen_helper_exception_cause(_pc, _cause);
     tcg_temp_free(_pc);
     tcg_temp_free(_cause);
@@ -209,6 +248,7 @@ static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
 {
     TCGv_i32 _pc = tcg_const_i32(dc->pc);
     TCGv_i32 _cause = tcg_const_i32(cause);
+    gen_advance_ccount(dc);
     gen_helper_exception_cause_vaddr(_pc, _cause, vaddr);
     tcg_temp_free(_pc);
     tcg_temp_free(_cause);
@@ -225,8 +265,9 @@ static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
 {
     tcg_gen_mov_i32(cpu_pc, dest);
     if (dc->singlestep_enabled) {
-        gen_exception(EXCP_DEBUG);
+        gen_exception(dc, EXCP_DEBUG);
     } else {
+        gen_advance_ccount(dc);
         if (slot >= 0) {
             tcg_gen_goto_tb(slot);
             tcg_gen_exit_tb((tcg_target_long)dc->tb + slot);
@@ -323,10 +364,17 @@ static void gen_brcondi(DisasContext *dc, TCGCond cond,
     tcg_temp_free(tmp);
 }
 
+static void gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr)
+{
+    gen_advance_ccount(dc);
+    tcg_gen_mov_i32(d, cpu_SR[sr]);
+}
+
 static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
 {
     static void (* const rsr_handler[256])(DisasContext *dc,
             TCGv_i32 d, uint32_t sr) = {
+        [CCOUNT] = gen_rsr_ccount,
     };
 
     if (sregnames[sr]) {
@@ -372,6 +420,34 @@ static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     gen_helper_wsr_windowbase(v);
 }
 
+static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    tcg_gen_andi_i32(cpu_SR[sr], v,
+            dc->config->inttype_mask[INTTYPE_SOFTWARE]);
+    gen_helper_check_interrupts(cpu_env);
+    gen_jumpi_check_loop_end(dc, 0);
+}
+
+static void gen_wsr_intclear(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    TCGv_i32 tmp = tcg_temp_new_i32();
+
+    tcg_gen_andi_i32(tmp, v,
+            dc->config->inttype_mask[INTTYPE_EDGE] |
+            dc->config->inttype_mask[INTTYPE_NMI] |
+            dc->config->inttype_mask[INTTYPE_SOFTWARE]);
+    tcg_gen_andc_i32(cpu_SR[INTSET], cpu_SR[INTSET], tmp);
+    tcg_temp_free(tmp);
+    gen_helper_check_interrupts(cpu_env);
+}
+
+static void gen_wsr_intenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    tcg_gen_mov_i32(cpu_SR[sr], v);
+    gen_helper_check_interrupts(cpu_env);
+    gen_jumpi_check_loop_end(dc, 0);
+}
+
 static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     uint32_t mask = PS_WOE | PS_CALLINC | PS_OWB |
@@ -381,10 +457,23 @@ static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
         mask |= PS_RING;
     }
     tcg_gen_andi_i32(cpu_SR[sr], v, mask);
-    /* This can change mmu index, so exit tb */
+    gen_helper_check_interrupts(cpu_env);
+    /* This can change mmu index and tb->flags, so exit tb */
     gen_jumpi_check_loop_end(dc, -1);
 }
 
+static void gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    uint32_t id = sr - CCOMPARE;
+    if (id < dc->config->nccompare) {
+        uint32_t int_bit = 1 << dc->config->timerint[id];
+        gen_advance_ccount(dc);
+        tcg_gen_mov_i32(cpu_SR[sr], v);
+        tcg_gen_andi_i32(cpu_SR[INTSET], cpu_SR[INTSET], ~int_bit);
+        gen_helper_check_interrupts(cpu_env);
+    }
+}
+
 static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 {
     static void (* const wsr_handler[256])(DisasContext *dc,
@@ -394,7 +483,13 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [SAR] = gen_wsr_sar,
         [LITBASE] = gen_wsr_litbase,
         [WINDOW_BASE] = gen_wsr_windowbase,
+        [INTSET] = gen_wsr_intset,
+        [INTCLEAR] = gen_wsr_intclear,
+        [INTENABLE] = gen_wsr_intenable,
         [PS] = gen_wsr_ps,
+        [CCOMPARE] = gen_wsr_ccompare,
+        [CCOMPARE + 1] = gen_wsr_ccompare,
+        [CCOMPARE + 2] = gen_wsr_ccompare,
     };
 
     if (sregnames[sr]) {
@@ -425,6 +520,16 @@ static void gen_load_store_alignment(DisasContext *dc, int shift,
     }
 }
 
+static void gen_waiti(DisasContext *dc, uint32_t imm4)
+{
+    TCGv_i32 pc = tcg_const_i32(dc->next_pc);
+    TCGv_i32 intlevel = tcg_const_i32(imm4);
+    gen_advance_ccount(dc);
+    gen_helper_waiti(pc, intlevel);
+    tcg_temp_free(pc);
+    tcg_temp_free(intlevel);
+}
+
 static void disas_xtensa_insn(DisasContext *dc)
 {
 #define HAS_OPTION(opt) do { \
@@ -561,6 +666,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
                             {
                                 TCGv_i32 tmp = tcg_const_i32(dc->pc);
+                                gen_advance_ccount(dc);
                                 gen_helper_retw(tmp, tmp);
                                 gen_jump(dc, tmp);
                                 tcg_temp_free(tmp);
@@ -606,6 +712,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
                     {
                         TCGv_i32 pc = tcg_const_i32(dc->pc);
+                        gen_advance_ccount(dc);
                         gen_helper_movsp(pc);
                         tcg_gen_mov_i32(cpu_R[RRR_T], cpu_R[RRR_S]);
                         tcg_temp_free(pc);
@@ -653,6 +760,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                         case 0: /*RFEx*/
                             gen_check_privilege(dc);
                             tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);
+                            gen_helper_check_interrupts(cpu_env);
                             gen_jump(dc, cpu_SR[EPC1]);
                             break;
 
@@ -686,6 +794,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                                 }
 
                                 gen_helper_restore_owb();
+                                gen_helper_check_interrupts(cpu_env);
                                 gen_jump(dc, cpu_SR[EPC1]);
 
                                 tcg_temp_free(tmp);
@@ -700,7 +809,16 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                     case 1: /*RFIx*/
                         HAS_OPTION(XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT);
-                        TBD();
+                        if (RRR_S >= 2 && RRR_S <= dc->config->nlevel) {
+                            gen_check_privilege(dc);
+                            tcg_gen_mov_i32(cpu_SR[PS],
+                                    cpu_SR[EPS2 + RRR_S - 2]);
+                            gen_helper_check_interrupts(cpu_env);
+                            gen_jump(dc, cpu_SR[EPC1 + RRR_S - 1]);
+                        } else {
+                            qemu_log("RFI %d is illegal\n", RRR_S);
+                            gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
+                        }
                         break;
 
                     case 2: /*RFME*/
@@ -746,14 +864,16 @@ static void disas_xtensa_insn(DisasContext *dc)
                     HAS_OPTION(XTENSA_OPTION_INTERRUPT);
                     gen_check_privilege(dc);
                     tcg_gen_mov_i32(cpu_R[RRR_T], cpu_SR[PS]);
+                    tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL);
                     tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], RRR_S);
-                    tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS],
-                            RRR_S | ~PS_INTLEVEL);
+                    gen_helper_check_interrupts(cpu_env);
+                    gen_jumpi_check_loop_end(dc, 0);
                     break;
 
                 case 7: /*WAITIx*/
                     HAS_OPTION(XTENSA_OPTION_INTERRUPT);
-                    TBD();
+                    gen_check_privilege(dc);
+                    gen_waiti(dc, RRR_S);
                     break;
 
                 case 8: /*ANY4p*/
@@ -1637,6 +1757,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     TCGv_i32 pc = tcg_const_i32(dc->pc);
                     TCGv_i32 s = tcg_const_i32(BRI12_S);
                     TCGv_i32 imm = tcg_const_i32(BRI12_IMM12);
+                    gen_advance_ccount(dc);
                     gen_helper_entry(pc, s, imm);
                     tcg_temp_free(imm);
                     tcg_temp_free(s);
@@ -1823,6 +1944,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
                 {
                     TCGv_i32 tmp = tcg_const_i32(dc->pc);
+                    gen_advance_ccount(dc);
                     gen_helper_retw(tmp, tmp);
                     gen_jump(dc, tmp);
                     tcg_temp_free(tmp);
@@ -1876,7 +1998,7 @@ static void check_breakpoint(CPUState *env, DisasContext *dc)
         QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
             if (bp->pc == dc->pc) {
                 tcg_gen_movi_i32(cpu_pc, dc->pc);
-                gen_exception(EXCP_DEBUG);
+                gen_exception(dc, EXCP_DEBUG);
                 dc->is_jmp = DISAS_UPDATE;
              }
         }
@@ -1908,6 +2030,7 @@ static void gen_intermediate_code_internal(
     dc.lbeg = env->sregs[LBEG];
     dc.lend = env->sregs[LEND];
     dc.is_jmp = DISAS_NEXT;
+    dc.ccount_delta = 0;
 
     init_litbase(&dc);
     init_sar_tracker(&dc);
@@ -1917,7 +2040,7 @@ static void gen_intermediate_code_internal(
     if (env->singlestep_enabled && env->exception_taken) {
         env->exception_taken = 0;
         tcg_gen_movi_i32(cpu_pc, dc.pc);
-        gen_exception(EXCP_DEBUG);
+        gen_exception(&dc, EXCP_DEBUG);
     }
 
     do {
@@ -1940,11 +2063,17 @@ static void gen_intermediate_code_internal(
             tcg_gen_debug_insn_start(dc.pc);
         }
 
+        ++dc.ccount_delta;
+
+        if (insn_count + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+            gen_io_start();
+        }
+
         disas_xtensa_insn(&dc);
         ++insn_count;
         if (env->singlestep_enabled) {
             tcg_gen_movi_i32(cpu_pc, dc.pc);
-            gen_exception(EXCP_DEBUG);
+            gen_exception(&dc, EXCP_DEBUG);
             break;
         }
     } while (dc.is_jmp == DISAS_NEXT &&
@@ -1955,6 +2084,10 @@ static void gen_intermediate_code_internal(
     reset_litbase(&dc);
     reset_sar_tracker(&dc);
 
+    if (tb->cflags & CF_LAST_IO) {
+        gen_io_end();
+    }
+
     if (dc.is_jmp == DISAS_NEXT) {
         gen_jumpi(&dc, dc.pc, 0);
     }
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 25/32] target-xtensa: implement accurate window check
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (23 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 24/32] target-xtensa: implement interrupt option Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 26/32] target-xtensa: implement CPENABLE and PRID SRs Max Filippov
                   ` (7 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

See ISA, 4.7.1.3 for details.

Window check is inserted before commands that push "used register
watermark" beyond its current level. Used register watermark is reset on
instructions that change WINDOW_BASE/WINDOW_START SRs.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/translate.c |  110 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 110 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index eb49e98..2b95a13 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -60,6 +60,7 @@ typedef struct DisasContext {
     TCGv_i32 sar_m32;
 
     uint32_t ccount_delta;
+    unsigned used_window;
 } DisasContext;
 
 static TCGv_ptr cpu_env;
@@ -225,6 +226,11 @@ static void gen_advance_ccount(DisasContext *dc)
     }
 }
 
+static void reset_used_window(DisasContext *dc)
+{
+    dc->used_window = 0;
+}
+
 static void gen_exception(DisasContext *dc, int excp)
 {
     TCGv_i32 tmp = tcg_const_i32(excp);
@@ -418,6 +424,13 @@ static void gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     gen_helper_wsr_windowbase(v);
+    reset_used_window(dc);
+}
+
+static void gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    tcg_gen_mov_i32(cpu_SR[sr], v);
+    reset_used_window(dc);
 }
 
 static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v)
@@ -457,6 +470,7 @@ static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
         mask |= PS_RING;
     }
     tcg_gen_andi_i32(cpu_SR[sr], v, mask);
+    reset_used_window(dc);
     gen_helper_check_interrupts(cpu_env);
     /* This can change mmu index and tb->flags, so exit tb */
     gen_jumpi_check_loop_end(dc, -1);
@@ -483,6 +497,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [SAR] = gen_wsr_sar,
         [LITBASE] = gen_wsr_litbase,
         [WINDOW_BASE] = gen_wsr_windowbase,
+        [WINDOW_START] = gen_wsr_windowstart,
         [INTSET] = gen_wsr_intset,
         [INTCLEAR] = gen_wsr_intclear,
         [INTENABLE] = gen_wsr_intenable,
@@ -530,6 +545,36 @@ static void gen_waiti(DisasContext *dc, uint32_t imm4)
     tcg_temp_free(intlevel);
 }
 
+static void gen_window_check1(DisasContext *dc, unsigned r1)
+{
+    if (dc->tb->flags & XTENSA_TBFLAG_EXCM) {
+        return;
+    }
+    if (option_enabled(dc, XTENSA_OPTION_WINDOWED_REGISTER) &&
+            r1 / 4 > dc->used_window) {
+        TCGv_i32 pc = tcg_const_i32(dc->pc);
+        TCGv_i32 w = tcg_const_i32(r1 / 4);
+
+        dc->used_window = r1 / 4;
+        gen_advance_ccount(dc);
+        gen_helper_window_check(pc, w);
+
+        tcg_temp_free(w);
+        tcg_temp_free(pc);
+    }
+}
+
+static void gen_window_check2(DisasContext *dc, unsigned r1, unsigned r2)
+{
+    gen_window_check1(dc, r1 > r2 ? r1 : r2);
+}
+
+static void gen_window_check3(DisasContext *dc, unsigned r1, unsigned r2,
+        unsigned r3)
+{
+    gen_window_check2(dc, r1, r2 > r3 ? r2 : r3);
+}
+
 static void disas_xtensa_insn(DisasContext *dc)
 {
 #define HAS_OPTION(opt) do { \
@@ -659,6 +704,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                         switch (CALLX_N) {
                         case 0: /*RET*/
                         case 2: /*JX*/
+                            gen_window_check1(dc, CALLX_S);
                             gen_jump(dc, cpu_R[CALLX_S]);
                             break;
 
@@ -680,6 +726,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                         break;
 
                     case 3: /*CALLX*/
+                        gen_window_check2(dc, CALLX_S, CALLX_N << 2);
                         switch (CALLX_N) {
                         case 0: /*CALLX0*/
                             {
@@ -710,6 +757,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                 case 1: /*MOVSPw*/
                     HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                    gen_window_check2(dc, RRR_T, RRR_S);
                     {
                         TCGv_i32 pc = tcg_const_i32(dc->pc);
                         gen_advance_ccount(dc);
@@ -863,6 +911,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 case 6: /*RSILx*/
                     HAS_OPTION(XTENSA_OPTION_INTERRUPT);
                     gen_check_privilege(dc);
+                    gen_window_check1(dc, RRR_T);
                     tcg_gen_mov_i32(cpu_R[RRR_T], cpu_SR[PS]);
                     tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL);
                     tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], RRR_S);
@@ -904,28 +953,34 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 1: /*AND*/
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 tcg_gen_and_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
                 break;
 
             case 2: /*OR*/
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 tcg_gen_or_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
                 break;
 
             case 3: /*XOR*/
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 tcg_gen_xor_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
                 break;
 
             case 4: /*ST1*/
                 switch (RRR_R) {
                 case 0: /*SSR*/
+                    gen_window_check1(dc, RRR_S);
                     gen_right_shift_sar(dc, cpu_R[RRR_S]);
                     break;
 
                 case 1: /*SSL*/
+                    gen_window_check1(dc, RRR_S);
                     gen_left_shift_sar(dc, cpu_R[RRR_S]);
                     break;
 
                 case 2: /*SSA8L*/
+                    gen_window_check1(dc, RRR_S);
                     {
                         TCGv_i32 tmp = tcg_temp_new_i32();
                         tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3);
@@ -935,6 +990,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 case 3: /*SSA8B*/
+                    gen_window_check1(dc, RRR_S);
                     {
                         TCGv_i32 tmp = tcg_temp_new_i32();
                         tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3);
@@ -968,16 +1024,19 @@ static void disas_xtensa_insn(DisasContext *dc)
                                 RRR_T | ((RRR_T & 8) ? 0xfffffff0 : 0));
                         gen_helper_rotw(tmp);
                         tcg_temp_free(tmp);
+                        reset_used_window(dc);
                     }
                     break;
 
                 case 14: /*NSAu*/
                     HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                    gen_window_check2(dc, RRR_S, RRR_T);
                     gen_helper_nsa(cpu_R[RRR_T], cpu_R[RRR_S]);
                     break;
 
                 case 15: /*NSAUu*/
                     HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                    gen_window_check2(dc, RRR_S, RRR_T);
                     gen_helper_nsau(cpu_R[RRR_T], cpu_R[RRR_S]);
                     break;
 
@@ -992,6 +1051,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 6: /*RT0*/
+                gen_window_check2(dc, RRR_R, RRR_T);
                 switch (RRR_S) {
                 case 0: /*NEG*/
                     tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
@@ -1019,12 +1079,14 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 8: /*ADD*/
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 tcg_gen_add_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
                 break;
 
             case 9: /*ADD**/
             case 10:
             case 11:
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 {
                     TCGv_i32 tmp = tcg_temp_new_i32();
                     tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 8);
@@ -1034,12 +1096,14 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 12: /*SUB*/
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 tcg_gen_sub_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
                 break;
 
             case 13: /*SUB**/
             case 14:
             case 15:
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 {
                     TCGv_i32 tmp = tcg_temp_new_i32();
                     tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 12);
@@ -1054,17 +1118,20 @@ static void disas_xtensa_insn(DisasContext *dc)
             switch (OP2) {
             case 0: /*SLLI*/
             case 1:
+                gen_window_check2(dc, RRR_R, RRR_S);
                 tcg_gen_shli_i32(cpu_R[RRR_R], cpu_R[RRR_S],
                         32 - (RRR_T | ((OP2 & 1) << 4)));
                 break;
 
             case 2: /*SRAI*/
             case 3:
+                gen_window_check2(dc, RRR_R, RRR_T);
                 tcg_gen_sari_i32(cpu_R[RRR_R], cpu_R[RRR_T],
                         RRR_S | ((OP2 & 1) << 4));
                 break;
 
             case 4: /*SRLI*/
+                gen_window_check2(dc, RRR_R, RRR_T);
                 tcg_gen_shri_i32(cpu_R[RRR_R], cpu_R[RRR_T], RRR_S);
                 break;
 
@@ -1074,6 +1141,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     if (RSR_SR >= 64) {
                         gen_check_privilege(dc);
                     }
+                    gen_window_check1(dc, RRR_T);
                     tcg_gen_mov_i32(tmp, cpu_R[RRR_T]);
                     gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
                     gen_wsr(dc, RSR_SR, tmp);
@@ -1100,6 +1168,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 #define gen_shift(cmd) gen_shift_reg(cmd, cpu_SR[SAR])
 
             case 8: /*SRC*/
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 {
                     TCGv_i64 v = tcg_temp_new_i64();
                     tcg_gen_concat_i32_i64(v, cpu_R[RRR_T], cpu_R[RRR_S]);
@@ -1108,6 +1177,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 9: /*SRL*/
+                gen_window_check2(dc, RRR_R, RRR_T);
                 if (dc->sar_5bit) {
                     tcg_gen_shr_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]);
                 } else {
@@ -1118,6 +1188,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 10: /*SLL*/
+                gen_window_check2(dc, RRR_R, RRR_S);
                 if (dc->sar_m32_5bit) {
                     tcg_gen_shl_i32(cpu_R[RRR_R], cpu_R[RRR_S], dc->sar_m32);
                 } else {
@@ -1132,6 +1203,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 11: /*SRA*/
+                gen_window_check2(dc, RRR_R, RRR_T);
                 if (dc->sar_5bit) {
                     tcg_gen_sar_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]);
                 } else {
@@ -1145,6 +1217,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 12: /*MUL16U*/
                 HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 {
                     TCGv_i32 v1 = tcg_temp_new_i32();
                     TCGv_i32 v2 = tcg_temp_new_i32();
@@ -1158,6 +1231,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 13: /*MUL16S*/
                 HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 {
                     TCGv_i32 v1 = tcg_temp_new_i32();
                     TCGv_i32 v2 = tcg_temp_new_i32();
@@ -1176,6 +1250,8 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 2: /*RST2*/
+            gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
+
             if (OP2 >= 12) {
                 HAS_OPTION(XTENSA_OPTION_32_BIT_IDIV);
                 int label = gen_new_label();
@@ -1260,6 +1336,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 if (RSR_SR >= 64) {
                     gen_check_privilege(dc);
                 }
+                gen_window_check1(dc, RRR_T);
                 gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
                 if (!sregnames[RSR_SR]) {
                     TBD();
@@ -1270,6 +1347,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 if (RSR_SR >= 64) {
                     gen_check_privilege(dc);
                 }
+                gen_window_check1(dc, RRR_T);
                 gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
                 if (!sregnames[RSR_SR]) {
                     TBD();
@@ -1278,6 +1356,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 2: /*SEXTu*/
                 HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                gen_window_check2(dc, RRR_R, RRR_S);
                 {
                     int shift = 24 - RRR_T;
 
@@ -1296,6 +1375,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 3: /*CLAMPSu*/
                 HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                gen_window_check2(dc, RRR_R, RRR_S);
                 {
                     TCGv_i32 tmp1 = tcg_temp_new_i32();
                     TCGv_i32 tmp2 = tcg_temp_new_i32();
@@ -1323,6 +1403,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             case 6: /*MINUu*/
             case 7: /*MAXUu*/
                 HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 {
                     static const TCGCond cond[] = {
                         TCG_COND_LE,
@@ -1350,6 +1431,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             case 9: /*MOVNEZ*/
             case 10: /*MOVLTZ*/
             case 11: /*MOVGEZ*/
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 {
                     static const TCGCond cond[] = {
                         TCG_COND_NE,
@@ -1375,6 +1457,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 14: /*RUR*/
+                gen_window_check1(dc, RRR_R);
                 {
                     int st = (RRR_S << 4) + RRR_T;
                     if (uregnames[st]) {
@@ -1387,6 +1470,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 15: /*WUR*/
+                gen_window_check1(dc, RRR_T);
                 {
                     if (uregnames[RSR_SR]) {
                         tcg_gen_mov_i32(cpu_UR[RSR_SR], cpu_R[RRR_T]);
@@ -1402,6 +1486,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
         case 4: /*EXTUI*/
         case 5:
+            gen_window_check2(dc, RRR_R, RRR_T);
             {
                 int shiftimm = RRR_S | (OP1 << 4);
                 int maskimm = (1 << (OP2 + 1)) - 1;
@@ -1427,6 +1512,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 9: /*LSC4*/
+            gen_window_check2(dc, RRR_S, RRR_T);
             switch (OP2) {
             case 0: /*L32E*/
                 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
@@ -1475,6 +1561,7 @@ static void disas_xtensa_insn(DisasContext *dc)
         break;
 
     case 1: /*L32R*/
+        gen_window_check1(dc, RRR_T);
         {
             TCGv_i32 tmp = tcg_const_i32(
                     ((dc->tb->flags & XTENSA_TBFLAG_LITBASE) ?
@@ -1492,6 +1579,7 @@ static void disas_xtensa_insn(DisasContext *dc)
     case 2: /*LSAI*/
 #define gen_load_store(type, shift) do { \
             TCGv_i32 addr = tcg_temp_new_i32(); \
+            gen_window_check2(dc, RRI8_S, RRI8_T); \
             tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \
             if (shift) { \
                 gen_load_store_alignment(dc, shift, addr, false); \
@@ -1628,6 +1716,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 #undef gen_load_store
 
         case 10: /*MOVI*/
+            gen_window_check1(dc, RRI8_T);
             tcg_gen_movi_i32(cpu_R[RRI8_T],
                     RRI8_IMM8 | (RRI8_S << 8) |
                     ((RRI8_S & 0x8) ? 0xfffff000 : 0));
@@ -1635,6 +1724,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
 #define gen_load_store_no_hw_align(type) do { \
             TCGv_i32 addr = tcg_temp_local_new_i32(); \
+            gen_window_check2(dc, RRI8_S, RRI8_T); \
             tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); \
             gen_load_store_alignment(dc, 2, addr, true); \
             tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
@@ -1647,15 +1737,18 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 12: /*ADDI*/
+            gen_window_check2(dc, RRI8_S, RRI8_T);
             tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE);
             break;
 
         case 13: /*ADDMI*/
+            gen_window_check2(dc, RRI8_S, RRI8_T);
             tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE << 8);
             break;
 
         case 14: /*S32C1Iy*/
             HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
+            gen_window_check2(dc, RRI8_S, RRI8_T);
             {
                 int label = gen_new_label();
                 TCGv_i32 tmp = tcg_temp_local_new_i32();
@@ -1709,6 +1802,7 @@ static void disas_xtensa_insn(DisasContext *dc)
         case 2: /*CALL8w*/
         case 3: /*CALL12w*/
             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+            gen_window_check1(dc, CALL_N << 2);
             gen_callwi(dc, CALL_N,
                     (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0);
             break;
@@ -1722,6 +1816,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 1: /*BZ*/
+            gen_window_check1(dc, BRI12_S);
             {
                 static const TCGCond cond[] = {
                     TCG_COND_EQ, /*BEQZ*/
@@ -1736,6 +1831,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 2: /*BI0*/
+            gen_window_check1(dc, BRI8_S);
             {
                 static const TCGCond cond[] = {
                     TCG_COND_EQ, /*BEQI*/
@@ -1762,6 +1858,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     tcg_temp_free(imm);
                     tcg_temp_free(s);
                     tcg_temp_free(pc);
+                    reset_used_window(dc);
                 }
                 break;
 
@@ -1781,6 +1878,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 case 9: /*LOOPNEZ*/
                 case 10: /*LOOPGTZ*/
                     HAS_OPTION(XTENSA_OPTION_LOOP);
+                    gen_window_check1(dc, RRI8_S);
                     {
                         uint32_t lend = dc->pc + RRI8_IMM8 + 4;
                         TCGv_i32 tmp = tcg_const_i32(lend);
@@ -1812,6 +1910,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 2: /*BLTUI*/
             case 3: /*BGEUI*/
+                gen_window_check1(dc, BRI8_S);
                 gen_brcondi(dc, BRI8_M == 2 ? TCG_COND_LTU : TCG_COND_GEU,
                         cpu_R[BRI8_S], B4CONSTU[BRI8_R], 4 + BRI8_IMM8_SE);
                 break;
@@ -1827,6 +1926,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             switch (RRI8_R & 7) {
             case 0: /*BNONE*/ /*BANY*/
+                gen_window_check2(dc, RRI8_S, RRI8_T);
                 {
                     TCGv_i32 tmp = tcg_temp_new_i32();
                     tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
@@ -1838,6 +1938,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             case 1: /*BEQ*/ /*BNE*/
             case 2: /*BLT*/ /*BGE*/
             case 3: /*BLTU*/ /*BGEU*/
+                gen_window_check2(dc, RRI8_S, RRI8_T);
                 {
                     static const TCGCond cond[] = {
                         [1] = TCG_COND_EQ,
@@ -1853,6 +1954,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 4: /*BALL*/ /*BNALL*/
+                gen_window_check2(dc, RRI8_S, RRI8_T);
                 {
                     TCGv_i32 tmp = tcg_temp_new_i32();
                     tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
@@ -1863,6 +1965,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 5: /*BBC*/ /*BBS*/
+                gen_window_check2(dc, RRI8_S, RRI8_T);
                 {
                     TCGv_i32 bit = tcg_const_i32(1);
                     TCGv_i32 tmp = tcg_temp_new_i32();
@@ -1877,6 +1980,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 6: /*BBCI*/ /*BBSI*/
             case 7:
+                gen_window_check1(dc, RRI8_S);
                 {
                     TCGv_i32 tmp = tcg_temp_new_i32();
                     tcg_gen_andi_i32(tmp, cpu_R[RRI8_S],
@@ -1892,6 +1996,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
 #define gen_narrow_load_store(type) do { \
             TCGv_i32 addr = tcg_temp_new_i32(); \
+            gen_window_check2(dc, RRRN_S, RRRN_T); \
             tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
             gen_load_store_alignment(dc, 2, addr, false); \
             tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, dc->cring); \
@@ -1908,14 +2013,17 @@ static void disas_xtensa_insn(DisasContext *dc)
 #undef gen_narrow_load_store
 
     case 10: /*ADD.Nn*/
+        gen_window_check3(dc, RRRN_R, RRRN_S, RRRN_T);
         tcg_gen_add_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], cpu_R[RRRN_T]);
         break;
 
     case 11: /*ADDI.Nn*/
+        gen_window_check2(dc, RRRN_R, RRRN_S);
         tcg_gen_addi_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], RRRN_T ? RRRN_T : -1);
         break;
 
     case 12: /*ST2n*/
+        gen_window_check1(dc, RRRN_S);
         if (RRRN_T < 8) { /*MOVI.Nn*/
             tcg_gen_movi_i32(cpu_R[RRRN_S],
                     RRRN_R | (RRRN_T << 4) |
@@ -1931,6 +2039,7 @@ static void disas_xtensa_insn(DisasContext *dc)
     case 13: /*ST3n*/
         switch (RRRN_R) {
         case 0: /*MOV.Nn*/
+            gen_window_check2(dc, RRRN_S, RRRN_T);
             tcg_gen_mov_i32(cpu_R[RRRN_T], cpu_R[RRRN_S]);
             break;
 
@@ -2034,6 +2143,7 @@ static void gen_intermediate_code_internal(
 
     init_litbase(&dc);
     init_sar_tracker(&dc);
+    reset_used_window(&dc);
 
     gen_icount_start();
 
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 26/32] target-xtensa: implement CPENABLE and PRID SRs
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (24 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 25/32] target-xtensa: implement accurate window check Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 27/32] target-xtensa: implement relocatable vectors Max Filippov
                   ` (6 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 hw/xtensa_sample.c        |    1 +
 target-xtensa/cpu.h       |    2 ++
 target-xtensa/translate.c |    7 +++++++
 3 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/hw/xtensa_sample.c b/hw/xtensa_sample.c
index 9f7733b..c2ad48a 100644
--- a/hw/xtensa_sample.c
+++ b/hw/xtensa_sample.c
@@ -51,6 +51,7 @@ static void xtensa_init(ram_addr_t ram_size,
             exit(1);
         }
         qemu_register_reset(xtensa_sample_reset, env);
+        env->sregs[PRID] = n;
     }
 
     ram_offset = qemu_ram_alloc(NULL, "xtensa.dram", 0x10000);
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 474466c..37f8b7f 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -118,12 +118,14 @@ enum {
     DEPC = 192,
     EPS2 = 194,
     EXCSAVE1 = 209,
+    CPENABLE = 224,
     INTSET = 226,
     INTCLEAR = 227,
     INTENABLE = 228,
     PS = 230,
     EXCCAUSE = 232,
     CCOUNT = 234,
+    PRID = 235,
     EXCVADDR = 238,
     CCOMPARE = 240,
 };
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 2b95a13..423cbae 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -101,12 +101,14 @@ static const char * const sregnames[256] = {
     [EXCSAVE1 + 4] = "EXCSAVE5",
     [EXCSAVE1 + 5] = "EXCSAVE6",
     [EXCSAVE1 + 6] = "EXCSAVE7",
+    [CPENABLE] = "CPENABLE",
     [INTSET] = "INTSET",
     [INTCLEAR] = "INTCLEAR",
     [INTENABLE] = "INTENABLE",
     [PS] = "PS",
     [EXCCAUSE] = "EXCCAUSE",
     [CCOUNT] = "CCOUNT",
+    [PRID] = "PRID",
     [EXCVADDR] = "EXCVADDR",
     [CCOMPARE] = "CCOMPARE0",
     [CCOMPARE + 1] = "CCOMPARE1",
@@ -476,6 +478,10 @@ static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     gen_jumpi_check_loop_end(dc, -1);
 }
 
+static void gen_wsr_prid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+}
+
 static void gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     uint32_t id = sr - CCOMPARE;
@@ -502,6 +508,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [INTCLEAR] = gen_wsr_intclear,
         [INTENABLE] = gen_wsr_intenable,
         [PS] = gen_wsr_ps,
+        [PRID] = gen_wsr_prid,
         [CCOMPARE] = gen_wsr_ccompare,
         [CCOMPARE + 1] = gen_wsr_ccompare,
         [CCOMPARE + 2] = gen_wsr_ccompare,
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 27/32] target-xtensa: implement relocatable vectors
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (25 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 26/32] target-xtensa: implement CPENABLE and PRID SRs Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 28/32] target-xtensa: add gdb support Max Filippov
                   ` (5 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

See ISA, 4.4.3 for details.

Vector addresses recorded in core configuration are absolute values that
correspond to default VECBASE value.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/cpu.h       |    2 ++
 target-xtensa/helper.c    |   18 ++++++++++++++++--
 target-xtensa/translate.c |    1 +
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 37f8b7f..c9094e9 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -123,6 +123,7 @@ enum {
     INTCLEAR = 227,
     INTENABLE = 228,
     PS = 230,
+    VECBASE = 231,
     EXCCAUSE = 232,
     CCOUNT = 234,
     PRID = 235,
@@ -219,6 +220,7 @@ typedef struct XtensaConfig {
     unsigned nareg;
     int excm_level;
     int ndepc;
+    uint32_t vecbase;
     uint32_t exception_vector[EXC_MAX];
     unsigned ninterrupt;
     unsigned nlevel;
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index c24a38a..dacb379 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -41,6 +41,7 @@ void cpu_reset(CPUXtensaState *env)
     env->sregs[LITBASE] &= ~1;
     env->sregs[PS] = xtensa_option_enabled(env->config,
             XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
+    env->sregs[VECBASE] = env->config->vecbase;
 
     env->pending_irq_level = 0;
 }
@@ -54,6 +55,7 @@ static const XtensaConfig core_config[] = {
         .nareg = 64,
         .ndepc = 1,
         .excm_level = 16,
+        .vecbase = 0x5fff8400,
         .exception_vector = {
             [EXC_RESET] = 0x5fff8000,
             [EXC_WINDOW_OVERFLOW4] = 0x5fff8400,
@@ -140,6 +142,16 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
     return addr;
 }
 
+static uint32_t relocated_vector(CPUState *env, uint32_t vector)
+{
+    if (xtensa_option_enabled(env->config,
+                XTENSA_OPTION_RELOCATABLE_VECTOR)) {
+        return vector - env->config->vecbase + env->sregs[VECBASE];
+    } else {
+        return vector;
+    }
+}
+
 /*!
  * Handle penging IRQ.
  * For the high priority interrupt jump to the corresponding interrupt vector.
@@ -160,7 +172,8 @@ static void handle_interrupt(CPUState *env)
             env->sregs[EPS2 + level - 2] = env->sregs[PS];
             env->sregs[PS] =
                 (env->sregs[PS] & ~PS_INTLEVEL) | level | PS_EXCM;
-            env->pc = env->config->interrupt_vector[level];
+            env->pc = relocated_vector(env,
+                    env->config->interrupt_vector[level]);
         } else {
             env->sregs[EXCCAUSE] = LEVEL1_INTERRUPT_CAUSE;
 
@@ -212,7 +225,8 @@ void do_interrupt(CPUState *env)
                 __func__, env->exception_index,
                 env->pc, env->regs[0], env->sregs[PS], env->sregs[CCOUNT]);
         if (env->config->exception_vector[env->exception_index]) {
-            env->pc = env->config->exception_vector[env->exception_index];
+            env->pc = relocated_vector(env,
+                    env->config->exception_vector[env->exception_index]);
             env->exception_taken = 1;
         } else {
             qemu_log("%s(pc = %08x) bad exception_index: %d\n",
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 423cbae..3b21bc4 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -106,6 +106,7 @@ static const char * const sregnames[256] = {
     [INTCLEAR] = "INTCLEAR",
     [INTENABLE] = "INTENABLE",
     [PS] = "PS",
+    [VECBASE] = "VECBASE",
     [EXCCAUSE] = "EXCCAUSE",
     [CCOUNT] = "CCOUNT",
     [PRID] = "PRID",
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 28/32] target-xtensa: add gdb support
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (26 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 27/32] target-xtensa: implement relocatable vectors Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 29/32] target-xtensa: implement memory protection options Max Filippov
                   ` (4 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Specific xtensa processor overlay for GDB contains register map in
the gdb/xtensa-config.c. This description is used by the GDB to e.g.
parse 'g' response packets and it may be reused in the qemu's gdbstub
(only XTREG definitions for non-pseudoregisters are needed).

Currently mainline GDB does not support operations with privileged SRs
(see http://sourceware.org/ml/gdb/2011-07/msg00075.html). This support
may be enabled, see NUM_CORE_REGS comment in the gdbstub.c

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 gdbstub.c                                     |   96 +++++++
 target-xtensa/cpu.h                           |   14 +
 target-xtensa/gdb-config-sample-xtensa-core.c |  375 +++++++++++++++++++++++++
 target-xtensa/helper.c                        |   11 +
 4 files changed, 496 insertions(+), 0 deletions(-)
 create mode 100644 target-xtensa/gdb-config-sample-xtensa-core.c

diff --git a/gdbstub.c b/gdbstub.c
index 3b87c27..9330885 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1541,6 +1541,94 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
     }
     return 4;
 }
+#elif defined(TARGET_XTENSA)
+
+/* Use num_core_regs to see only non-privileged registers in an unmodified gdb.
+ * Use num_regs to see all registers. gdb modification is required for that:
+ * reset bit 0 in the 'flags' field of the registers definitions in the
+ * gdb/xtensa-config.c inside gdb source tree or inside gdb overlay.
+ */
+#define NUM_CORE_REGS (env->config->gdb_regmap.num_regs)
+#define num_g_regs NUM_CORE_REGS
+
+static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+{
+    const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
+
+    if (n < 0 || n >= env->config->gdb_regmap.num_regs) {
+        return 0;
+    }
+
+    switch (reg->type) {
+    case 9: /*pc*/
+        GET_REG32(env->pc);
+        break;
+
+    case 1: /*ar*/
+        xtensa_sync_phys_from_window(env);
+        GET_REG32(env->phys_regs[(reg->targno & 0xff) % env->config->nareg]);
+        break;
+
+    case 2: /*SR*/
+        GET_REG32(env->sregs[reg->targno & 0xff]);
+        break;
+
+    case 3: /*UR*/
+        GET_REG32(env->uregs[reg->targno & 0xff]);
+        break;
+
+    case 8: /*a*/
+        GET_REG32(env->regs[reg->targno & 0x0f]);
+        break;
+
+    default:
+        qemu_log("%s from reg %d of unsupported type %d\n",
+                __func__, n, reg->type);
+        return 0;
+    }
+}
+
+static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+{
+    uint32_t tmp;
+    const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
+
+    if (n < 0 || n >= env->config->gdb_regmap.num_regs) {
+        return 0;
+    }
+
+    tmp = ldl_p(mem_buf);
+
+    switch (reg->type) {
+    case 9: /*pc*/
+        env->pc = tmp;
+        break;
+
+    case 1: /*ar*/
+        env->phys_regs[(reg->targno & 0xff) % env->config->nareg] = tmp;
+        xtensa_sync_window_from_phys(env);
+        break;
+
+    case 2: /*SR*/
+        env->sregs[reg->targno & 0xff] = tmp;
+        break;
+
+    case 3: /*UR*/
+        env->uregs[reg->targno & 0xff] = tmp;
+        break;
+
+    case 8: /*a*/
+        env->regs[reg->targno & 0x0f] = tmp;
+        break;
+
+    default:
+        qemu_log("%s to reg %d of unsupported type %d\n",
+                __func__, n, reg->type);
+        return 0;
+    }
+
+    return 4;
+}
 #else
 
 #define NUM_CORE_REGS 0
@@ -1557,7 +1645,9 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 
 #endif
 
+#if !defined(TARGET_XTENSA)
 static int num_g_regs = NUM_CORE_REGS;
+#endif
 
 #ifdef GDB_CORE_XML
 /* Encode data using the encoding for 'x' packets.  */
@@ -1654,6 +1744,7 @@ static int gdb_write_register(CPUState *env, uint8_t *mem_buf, int reg)
     return 0;
 }
 
+#if !defined(TARGET_XTENSA)
 /* Register a supplemental set of CPU registers.  If g_pos is nonzero it
    specifies the first register number and these registers are included in
    a standard "g" packet.  Direction is relative to gdb, i.e. get_reg is
@@ -1693,6 +1784,7 @@ void gdb_register_coprocessor(CPUState * env,
         }
     }
 }
+#endif
 
 #ifndef CONFIG_USER_ONLY
 static const int xlat_gdb_type[] = {
@@ -1818,6 +1910,8 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
     s->c_cpu->psw.addr = pc;
 #elif defined (TARGET_LM32)
     s->c_cpu->pc = pc;
+#elif defined(TARGET_XTENSA)
+    s->c_cpu->pc = pc;
 #endif
 }
 
@@ -1988,6 +2082,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
         break;
     case 'g':
         cpu_synchronize_state(s->g_cpu);
+        env = s->g_cpu;
         len = 0;
         for (addr = 0; addr < num_g_regs; addr++) {
             reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
@@ -1998,6 +2093,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
         break;
     case 'G':
         cpu_synchronize_state(s->g_cpu);
+        env = s->g_cpu;
         registers = mem_buf;
         len = strlen(p) / 2;
         hextomem((uint8_t *)registers, p, len);
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index c9094e9..93e17d1 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -214,9 +214,23 @@ typedef enum {
     INTTYPE_MAX
 } interrupt_type;
 
+typedef struct XtensaGdbReg {
+    int targno;
+    int type;
+    int group;
+} XtensaGdbReg;
+
+typedef struct XtensaGdbRegmap {
+    int num_regs;
+    int num_core_regs;
+    /* PC + a + ar + sr + ur */
+    XtensaGdbReg reg[1 + 16 + 64 + 256 + 256];
+} XtensaGdbRegmap;
+
 typedef struct XtensaConfig {
     const char *name;
     uint64_t options;
+    XtensaGdbRegmap gdb_regmap;
     unsigned nareg;
     int excm_level;
     int ndepc;
diff --git a/target-xtensa/gdb-config-sample-xtensa-core.c b/target-xtensa/gdb-config-sample-xtensa-core.c
new file mode 100644
index 0000000..bfbd7be
--- /dev/null
+++ b/target-xtensa/gdb-config-sample-xtensa-core.c
@@ -0,0 +1,375 @@
+/* Configuration for the Xtensa architecture for GDB, the GNU debugger.
+
+   Copyright (c) 2003-2010 Tensilica Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   "Software"), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+   CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+  XTREG(0,   0, 32, 4, 4, 0x0020, 0x0006, -2, 9, 0x0100, pc,
+          0, 0, 0, 0, 0, 0)
+  XTREG(1,   4, 32, 4, 4, 0x0100, 0x0006, -2, 1, 0x0002, ar0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(2,   8, 32, 4, 4, 0x0101, 0x0006, -2, 1, 0x0002, ar1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(3,  12, 32, 4, 4, 0x0102, 0x0006, -2, 1, 0x0002, ar2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(4,  16, 32, 4, 4, 0x0103, 0x0006, -2, 1, 0x0002, ar3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(5,  20, 32, 4, 4, 0x0104, 0x0006, -2, 1, 0x0002, ar4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(6,  24, 32, 4, 4, 0x0105, 0x0006, -2, 1, 0x0002, ar5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(7,  28, 32, 4, 4, 0x0106, 0x0006, -2, 1, 0x0002, ar6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(8,  32, 32, 4, 4, 0x0107, 0x0006, -2, 1, 0x0002, ar7,
+          0, 0, 0, 0, 0, 0)
+  XTREG(9,  36, 32, 4, 4, 0x0108, 0x0006, -2, 1, 0x0002, ar8,
+          0, 0, 0, 0, 0, 0)
+  XTREG(10,  40, 32, 4, 4, 0x0109, 0x0006, -2, 1, 0x0002, ar9,
+          0, 0, 0, 0, 0, 0)
+  XTREG(11,  44, 32, 4, 4, 0x010a, 0x0006, -2, 1, 0x0002, ar10,
+          0, 0, 0, 0, 0, 0)
+  XTREG(12,  48, 32, 4, 4, 0x010b, 0x0006, -2, 1, 0x0002, ar11,
+          0, 0, 0, 0, 0, 0)
+  XTREG(13,  52, 32, 4, 4, 0x010c, 0x0006, -2, 1, 0x0002, ar12,
+          0, 0, 0, 0, 0, 0)
+  XTREG(14,  56, 32, 4, 4, 0x010d, 0x0006, -2, 1, 0x0002, ar13,
+          0, 0, 0, 0, 0, 0)
+  XTREG(15,  60, 32, 4, 4, 0x010e, 0x0006, -2, 1, 0x0002, ar14,
+          0, 0, 0, 0, 0, 0)
+  XTREG(16,  64, 32, 4, 4, 0x010f, 0x0006, -2, 1, 0x0002, ar15,
+          0, 0, 0, 0, 0, 0)
+  XTREG(17,  68, 32, 4, 4, 0x0110, 0x0006, -2, 1, 0x0002, ar16,
+          0, 0, 0, 0, 0, 0)
+  XTREG(18,  72, 32, 4, 4, 0x0111, 0x0006, -2, 1, 0x0002, ar17,
+          0, 0, 0, 0, 0, 0)
+  XTREG(19,  76, 32, 4, 4, 0x0112, 0x0006, -2, 1, 0x0002, ar18,
+          0, 0, 0, 0, 0, 0)
+  XTREG(20,  80, 32, 4, 4, 0x0113, 0x0006, -2, 1, 0x0002, ar19,
+          0, 0, 0, 0, 0, 0)
+  XTREG(21,  84, 32, 4, 4, 0x0114, 0x0006, -2, 1, 0x0002, ar20,
+          0, 0, 0, 0, 0, 0)
+  XTREG(22,  88, 32, 4, 4, 0x0115, 0x0006, -2, 1, 0x0002, ar21,
+          0, 0, 0, 0, 0, 0)
+  XTREG(23,  92, 32, 4, 4, 0x0116, 0x0006, -2, 1, 0x0002, ar22,
+          0, 0, 0, 0, 0, 0)
+  XTREG(24,  96, 32, 4, 4, 0x0117, 0x0006, -2, 1, 0x0002, ar23,
+          0, 0, 0, 0, 0, 0)
+  XTREG(25, 100, 32, 4, 4, 0x0118, 0x0006, -2, 1, 0x0002, ar24,
+          0, 0, 0, 0, 0, 0)
+  XTREG(26, 104, 32, 4, 4, 0x0119, 0x0006, -2, 1, 0x0002, ar25,
+          0, 0, 0, 0, 0, 0)
+  XTREG(27, 108, 32, 4, 4, 0x011a, 0x0006, -2, 1, 0x0002, ar26,
+          0, 0, 0, 0, 0, 0)
+  XTREG(28, 112, 32, 4, 4, 0x011b, 0x0006, -2, 1, 0x0002, ar27,
+          0, 0, 0, 0, 0, 0)
+  XTREG(29, 116, 32, 4, 4, 0x011c, 0x0006, -2, 1, 0x0002, ar28,
+          0, 0, 0, 0, 0, 0)
+  XTREG(30, 120, 32, 4, 4, 0x011d, 0x0006, -2, 1, 0x0002, ar29,
+          0, 0, 0, 0, 0, 0)
+  XTREG(31, 124, 32, 4, 4, 0x011e, 0x0006, -2, 1, 0x0002, ar30,
+          0, 0, 0, 0, 0, 0)
+  XTREG(32, 128, 32, 4, 4, 0x011f, 0x0006, -2, 1, 0x0002, ar31,
+          0, 0, 0, 0, 0, 0)
+  XTREG(33, 132, 32, 4, 4, 0x0120, 0x0006, -2, 1, 0x0002, ar32,
+          0, 0, 0, 0, 0, 0)
+  XTREG(34, 136, 32, 4, 4, 0x0121, 0x0006, -2, 1, 0x0002, ar33,
+          0, 0, 0, 0, 0, 0)
+  XTREG(35, 140, 32, 4, 4, 0x0122, 0x0006, -2, 1, 0x0002, ar34,
+          0, 0, 0, 0, 0, 0)
+  XTREG(36, 144, 32, 4, 4, 0x0123, 0x0006, -2, 1, 0x0002, ar35,
+          0, 0, 0, 0, 0, 0)
+  XTREG(37, 148, 32, 4, 4, 0x0124, 0x0006, -2, 1, 0x0002, ar36,
+          0, 0, 0, 0, 0, 0)
+  XTREG(38, 152, 32, 4, 4, 0x0125, 0x0006, -2, 1, 0x0002, ar37,
+          0, 0, 0, 0, 0, 0)
+  XTREG(39, 156, 32, 4, 4, 0x0126, 0x0006, -2, 1, 0x0002, ar38,
+          0, 0, 0, 0, 0, 0)
+  XTREG(40, 160, 32, 4, 4, 0x0127, 0x0006, -2, 1, 0x0002, ar39,
+          0, 0, 0, 0, 0, 0)
+  XTREG(41, 164, 32, 4, 4, 0x0128, 0x0006, -2, 1, 0x0002, ar40,
+          0, 0, 0, 0, 0, 0)
+  XTREG(42, 168, 32, 4, 4, 0x0129, 0x0006, -2, 1, 0x0002, ar41,
+          0, 0, 0, 0, 0, 0)
+  XTREG(43, 172, 32, 4, 4, 0x012a, 0x0006, -2, 1, 0x0002, ar42,
+          0, 0, 0, 0, 0, 0)
+  XTREG(44, 176, 32, 4, 4, 0x012b, 0x0006, -2, 1, 0x0002, ar43,
+          0, 0, 0, 0, 0, 0)
+  XTREG(45, 180, 32, 4, 4, 0x012c, 0x0006, -2, 1, 0x0002, ar44,
+          0, 0, 0, 0, 0, 0)
+  XTREG(46, 184, 32, 4, 4, 0x012d, 0x0006, -2, 1, 0x0002, ar45,
+          0, 0, 0, 0, 0, 0)
+  XTREG(47, 188, 32, 4, 4, 0x012e, 0x0006, -2, 1, 0x0002, ar46,
+          0, 0, 0, 0, 0, 0)
+  XTREG(48, 192, 32, 4, 4, 0x012f, 0x0006, -2, 1, 0x0002, ar47,
+          0, 0, 0, 0, 0, 0)
+  XTREG(49, 196, 32, 4, 4, 0x0130, 0x0006, -2, 1, 0x0002, ar48,
+          0, 0, 0, 0, 0, 0)
+  XTREG(50, 200, 32, 4, 4, 0x0131, 0x0006, -2, 1, 0x0002, ar49,
+          0, 0, 0, 0, 0, 0)
+  XTREG(51, 204, 32, 4, 4, 0x0132, 0x0006, -2, 1, 0x0002, ar50,
+          0, 0, 0, 0, 0, 0)
+  XTREG(52, 208, 32, 4, 4, 0x0133, 0x0006, -2, 1, 0x0002, ar51,
+          0, 0, 0, 0, 0, 0)
+  XTREG(53, 212, 32, 4, 4, 0x0134, 0x0006, -2, 1, 0x0002, ar52,
+          0, 0, 0, 0, 0, 0)
+  XTREG(54, 216, 32, 4, 4, 0x0135, 0x0006, -2, 1, 0x0002, ar53,
+          0, 0, 0, 0, 0, 0)
+  XTREG(55, 220, 32, 4, 4, 0x0136, 0x0006, -2, 1, 0x0002, ar54,
+          0, 0, 0, 0, 0, 0)
+  XTREG(56, 224, 32, 4, 4, 0x0137, 0x0006, -2, 1, 0x0002, ar55,
+          0, 0, 0, 0, 0, 0)
+  XTREG(57, 228, 32, 4, 4, 0x0138, 0x0006, -2, 1, 0x0002, ar56,
+          0, 0, 0, 0, 0, 0)
+  XTREG(58, 232, 32, 4, 4, 0x0139, 0x0006, -2, 1, 0x0002, ar57,
+          0, 0, 0, 0, 0, 0)
+  XTREG(59, 236, 32, 4, 4, 0x013a, 0x0006, -2, 1, 0x0002, ar58,
+          0, 0, 0, 0, 0, 0)
+  XTREG(60, 240, 32, 4, 4, 0x013b, 0x0006, -2, 1, 0x0002, ar59,
+          0, 0, 0, 0, 0, 0)
+  XTREG(61, 244, 32, 4, 4, 0x013c, 0x0006, -2, 1, 0x0002, ar60,
+          0, 0, 0, 0, 0, 0)
+  XTREG(62, 248, 32, 4, 4, 0x013d, 0x0006, -2, 1, 0x0002, ar61,
+          0, 0, 0, 0, 0, 0)
+  XTREG(63, 252, 32, 4, 4, 0x013e, 0x0006, -2, 1, 0x0002, ar62,
+          0, 0, 0, 0, 0, 0)
+  XTREG(64, 256, 32, 4, 4, 0x013f, 0x0006, -2, 1, 0x0002, ar63,
+          0, 0, 0, 0, 0, 0)
+  XTREG(65, 260, 32, 4, 4, 0x0200, 0x0006, -2, 2, 0x1100, lbeg,
+          0, 0, 0, 0, 0, 0)
+  XTREG(66, 264, 32, 4, 4, 0x0201, 0x0006, -2, 2, 0x1100, lend,
+          0, 0, 0, 0, 0, 0)
+  XTREG(67, 268, 32, 4, 4, 0x0202, 0x0006, -2, 2, 0x1100, lcount,
+          0, 0, 0, 0, 0, 0)
+  XTREG(68, 272,  6, 4, 4, 0x0203, 0x0006, -2, 2, 0x1100, sar,
+          0, 0, 0, 0, 0, 0)
+  XTREG(69, 276, 32, 4, 4, 0x0205, 0x0006, -2, 2, 0x1100, litbase,
+          0, 0, 0, 0, 0, 0)
+  XTREG(70, 280,  4, 4, 4, 0x0248, 0x0006, -2, 2, 0x1002, windowbase,
+          0, 0, 0, 0, 0, 0)
+  XTREG(71, 284, 16, 4, 4, 0x0249, 0x0006, -2, 2, 0x1002, windowstart,
+          0, 0, 0, 0, 0, 0)
+  XTREG(72, 288, 32, 4, 4, 0x02b0, 0x0002, -2, 2, 0x1000, sr176,
+          0, 0, 0, 0, 0, 0)
+  XTREG(73, 292, 32, 4, 4, 0x02d0, 0x0002, -2, 2, 0x1000, sr208,
+          0, 0, 0, 0, 0, 0)
+  XTREG(74, 296, 19, 4, 4, 0x02e6, 0x0006, -2, 2, 0x1100, ps,
+          0, 0, 0, 0, 0, 0)
+  XTREG(75, 300, 32, 4, 4, 0x03e7, 0x0006, -2, 3, 0x0110, threadptr,
+          0, 0, 0, 0, 0, 0)
+  XTREG(76, 304, 32, 4, 4, 0x020c, 0x0006, -1, 2, 0x1100, scompare1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(77, 308, 32, 4, 4, 0x0327, 0x000e, -1, 3, 0x0210, expstate,
+          0, 0, 0, 0, 0, 0)
+  XTREG(78, 312, 32, 4, 4, 0x0300, 0x0006,  2, 3, 0x0210, stage1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(79, 316, 32, 4, 4, 0x0301, 0x0006,  2, 3, 0x0210, stage2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(80, 320, 32, 4, 4, 0x0302, 0x0006,  2, 3, 0x0210, input_align_reg,
+          0, 0, 0, 0, 0, 0)
+  XTREG(81, 324,  6, 4, 4, 0x0303, 0x0006,  2, 3, 0x0210, input_align_reg_pos,
+          0, 0, 0, 0, 0, 0)
+  XTREG(82, 328, 32, 4, 4, 0x0304, 0x0006,  2, 3, 0x0210, data_reg,
+          0, 0, 0, 0, 0, 0)
+  XTREG(83, 332,  7, 4, 4, 0x0305, 0x0006,  2, 3, 0x0210, data_reg_pos,
+          0, 0, 0, 0, 0, 0)
+  XTREG(84, 336, 32, 4, 4, 0x0306, 0x0006,  2, 3, 0x0210, crc_reg,
+          0, 0, 0, 0, 0, 0)
+  XTREG(85, 340, 32, 4, 4, 0x0307, 0x0006,  2, 3, 0x0210, pol_reg00,
+          0, 0, 0, 0, 0, 0)
+  XTREG(86, 344, 32, 4, 4, 0x0308, 0x0006,  2, 3, 0x0210, pol_reg01,
+          0, 0, 0, 0, 0, 0)
+  XTREG(87, 348, 32, 4, 4, 0x0309, 0x0006,  2, 3, 0x0210, pol_reg02,
+          0, 0, 0, 0, 0, 0)
+  XTREG(88, 352, 32, 4, 4, 0x030a, 0x0006,  2, 3, 0x0210, pol_reg03,
+          0, 0, 0, 0, 0, 0)
+  XTREG(89, 356, 32, 4, 4, 0x030b, 0x0006,  2, 3, 0x0210, pol_reg04,
+          0, 0, 0, 0, 0, 0)
+  XTREG(90, 360, 32, 4, 4, 0x030c, 0x0006,  2, 3, 0x0210, pol_reg05,
+          0, 0, 0, 0, 0, 0)
+  XTREG(91, 364, 32, 4, 4, 0x030d, 0x0006,  2, 3, 0x0210, pol_reg06,
+          0, 0, 0, 0, 0, 0)
+  XTREG(92, 368, 32, 4, 4, 0x030e, 0x0006,  2, 3, 0x0210, pol_reg07,
+          0, 0, 0, 0, 0, 0)
+  XTREG(93, 372, 32, 4, 4, 0x030f, 0x0006,  2, 3, 0x0210, pol_reg08,
+          0, 0, 0, 0, 0, 0)
+  XTREG(94, 376, 32, 4, 4, 0x0310, 0x0006,  2, 3, 0x0210, pol_reg09,
+          0, 0, 0, 0, 0, 0)
+  XTREG(95, 380, 32, 4, 4, 0x0311, 0x0006,  2, 3, 0x0210, pol_reg10,
+          0, 0, 0, 0, 0, 0)
+  XTREG(96, 384, 32, 4, 4, 0x0312, 0x0006,  2, 3, 0x0210, pol_reg11,
+          0, 0, 0, 0, 0, 0)
+  XTREG(97, 388, 32, 4, 4, 0x0313, 0x0006,  2, 3, 0x0210, pol_reg12,
+          0, 0, 0, 0, 0, 0)
+  XTREG(98, 392, 32, 4, 4, 0x0314, 0x0006,  2, 3, 0x0210, pol_reg13,
+          0, 0, 0, 0, 0, 0)
+  XTREG(99, 396, 32, 4, 4, 0x0315, 0x0006,  2, 3, 0x0210, pol_reg14,
+          0, 0, 0, 0, 0, 0)
+  XTREG(100, 400, 32, 4, 4, 0x0316, 0x0006,  2, 3, 0x0210, pol_reg15,
+          0, 0, 0, 0, 0, 0)
+  XTREG(101, 404, 32, 4, 4, 0x0317, 0x0006,  2, 3, 0x0210, pol_reg16,
+          0, 0, 0, 0, 0, 0)
+  XTREG(102, 408, 32, 4, 4, 0x0318, 0x0006,  2, 3, 0x0210, pol_reg17,
+          0, 0, 0, 0, 0, 0)
+  XTREG(103, 412, 32, 4, 4, 0x0319, 0x0006,  2, 3, 0x0210, pol_reg18,
+          0, 0, 0, 0, 0, 0)
+  XTREG(104, 416, 32, 4, 4, 0x031a, 0x0006,  2, 3, 0x0210, pol_reg19,
+          0, 0, 0, 0, 0, 0)
+  XTREG(105, 420, 32, 4, 4, 0x031b, 0x0006,  2, 3, 0x0210, pol_reg20,
+          0, 0, 0, 0, 0, 0)
+  XTREG(106, 424, 32, 4, 4, 0x031c, 0x0006,  2, 3, 0x0210, pol_reg21,
+          0, 0, 0, 0, 0, 0)
+  XTREG(107, 428, 32, 4, 4, 0x031d, 0x0006,  2, 3, 0x0210, pol_reg22,
+          0, 0, 0, 0, 0, 0)
+  XTREG(108, 432, 32, 4, 4, 0x031e, 0x0006,  2, 3, 0x0210, pol_reg23,
+          0, 0, 0, 0, 0, 0)
+  XTREG(109, 436, 32, 4, 4, 0x031f, 0x0006,  2, 3, 0x0210, pol_reg24,
+          0, 0, 0, 0, 0, 0)
+  XTREG(110, 440, 32, 4, 4, 0x0320, 0x0006,  2, 3, 0x0210, pol_reg25,
+          0, 0, 0, 0, 0, 0)
+  XTREG(111, 444, 32, 4, 4, 0x0321, 0x0006,  2, 3, 0x0210, pol_reg26,
+          0, 0, 0, 0, 0, 0)
+  XTREG(112, 448, 32, 4, 4, 0x0322, 0x0006,  2, 3, 0x0210, pol_reg27,
+          0, 0, 0, 0, 0, 0)
+  XTREG(113, 452, 32, 4, 4, 0x0323, 0x0006,  2, 3, 0x0210, pol_reg28,
+          0, 0, 0, 0, 0, 0)
+  XTREG(114, 456, 32, 4, 4, 0x0324, 0x0006,  2, 3, 0x0210, pol_reg29,
+          0, 0, 0, 0, 0, 0)
+  XTREG(115, 460, 32, 4, 4, 0x0325, 0x0006,  2, 3, 0x0210, pol_reg30,
+          0, 0, 0, 0, 0, 0)
+  XTREG(116, 464, 32, 4, 4, 0x0326, 0x0006,  2, 3, 0x0210, pol_reg31,
+          0, 0, 0, 0, 0, 0)
+  XTREG(117, 468, 32, 4, 4, 0x0259, 0x000d, -2, 2, 0x1000, mmid,
+          0, 0, 0, 0, 0, 0)
+  XTREG(118, 472,  2, 4, 4, 0x0260, 0x0007, -2, 2, 0x1000, ibreakenable,
+          0, 0, 0, 0, 0, 0)
+  XTREG(119, 476,  6, 4, 4, 0x0263, 0x0007, -2, 2, 0x1000, atomctl,
+          0, 0, 0, 0, 0, 0)
+  XTREG(120, 480, 32, 4, 4, 0x0268, 0x0007, -2, 2, 0x1000, ddr,
+          0, 0, 0, 0, 0, 0)
+  XTREG(121, 484, 32, 4, 4, 0x0280, 0x0007, -2, 2, 0x1000, ibreaka0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(122, 488, 32, 4, 4, 0x0281, 0x0007, -2, 2, 0x1000, ibreaka1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(123, 492, 32, 4, 4, 0x0290, 0x0007, -2, 2, 0x1000, dbreaka0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(124, 496, 32, 4, 4, 0x0291, 0x0007, -2, 2, 0x1000, dbreaka1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(125, 500, 32, 4, 4, 0x02a0, 0x0007, -2, 2, 0x1000, dbreakc0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(126, 504, 32, 4, 4, 0x02a1, 0x0007, -2, 2, 0x1000, dbreakc1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(127, 508, 32, 4, 4, 0x02b1, 0x0007, -2, 2, 0x1000, epc1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(128, 512, 32, 4, 4, 0x02b2, 0x0007, -2, 2, 0x1000, epc2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(129, 516, 32, 4, 4, 0x02b3, 0x0007, -2, 2, 0x1000, epc3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(130, 520, 32, 4, 4, 0x02b4, 0x0007, -2, 2, 0x1000, epc4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(131, 524, 32, 4, 4, 0x02b5, 0x0007, -2, 2, 0x1000, epc5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(132, 528, 32, 4, 4, 0x02b6, 0x0007, -2, 2, 0x1000, epc6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(133, 532, 32, 4, 4, 0x02c0, 0x0007, -2, 2, 0x1000, depc,
+          0, 0, 0, 0, 0, 0)
+  XTREG(134, 536, 19, 4, 4, 0x02c2, 0x0007, -2, 2, 0x1000, eps2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(135, 540, 19, 4, 4, 0x02c3, 0x0007, -2, 2, 0x1000, eps3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(136, 544, 19, 4, 4, 0x02c4, 0x0007, -2, 2, 0x1000, eps4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(137, 548, 19, 4, 4, 0x02c5, 0x0007, -2, 2, 0x1000, eps5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(138, 552, 19, 4, 4, 0x02c6, 0x0007, -2, 2, 0x1000, eps6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(139, 556, 32, 4, 4, 0x02d1, 0x0007, -2, 2, 0x1000, excsave1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(140, 560, 32, 4, 4, 0x02d2, 0x0007, -2, 2, 0x1000, excsave2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(141, 564, 32, 4, 4, 0x02d3, 0x0007, -2, 2, 0x1000, excsave3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(142, 568, 32, 4, 4, 0x02d4, 0x0007, -2, 2, 0x1000, excsave4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(143, 572, 32, 4, 4, 0x02d5, 0x0007, -2, 2, 0x1000, excsave5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(144, 576, 32, 4, 4, 0x02d6, 0x0007, -2, 2, 0x1000, excsave6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(145, 580,  4, 4, 4, 0x02e0, 0x0007, -2, 2, 0x1000, cpenable,
+          0, 0, 0, 0, 0, 0)
+  XTREG(146, 584, 13, 4, 4, 0x02e2, 0x000b, -2, 2, 0x1000, interrupt,
+          0, 0, 0, 0, 0, 0)
+  XTREG(147, 588, 13, 4, 4, 0x02e2, 0x000d, -2, 2, 0x1000, intset,
+          0, 0, 0, 0, 0, 0)
+  XTREG(148, 592, 13, 4, 4, 0x02e3, 0x000d, -2, 2, 0x1000, intclear,
+          0, 0, 0, 0, 0, 0)
+  XTREG(149, 596, 13, 4, 4, 0x02e4, 0x0007, -2, 2, 0x1000, intenable,
+          0, 0, 0, 0, 0, 0)
+  XTREG(150, 600, 32, 4, 4, 0x02e7, 0x0007, -2, 2, 0x1000, vecbase,
+          0, 0, 0, 0, 0, 0)
+  XTREG(151, 604,  6, 4, 4, 0x02e8, 0x0007, -2, 2, 0x1000, exccause,
+          0, 0, 0, 0, 0, 0)
+  XTREG(152, 608, 12, 4, 4, 0x02e9, 0x0003, -2, 2, 0x1000, debugcause,
+          0, 0, 0, 0, 0, 0)
+  XTREG(153, 612, 32, 4, 4, 0x02ea, 0x000f, -2, 2, 0x1000, ccount,
+          0, 0, 0, 0, 0, 0)
+  XTREG(154, 616, 32, 4, 4, 0x02eb, 0x0003, -2, 2, 0x1000, prid,
+          0, 0, 0, 0, 0, 0)
+  XTREG(155, 620, 32, 4, 4, 0x02ec, 0x000f, -2, 2, 0x1000, icount,
+          0, 0, 0, 0, 0, 0)
+  XTREG(156, 624,  4, 4, 4, 0x02ed, 0x0007, -2, 2, 0x1000, icountlevel,
+          0, 0, 0, 0, 0, 0)
+  XTREG(157, 628, 32, 4, 4, 0x02ee, 0x0007, -2, 2, 0x1000, excvaddr,
+          0, 0, 0, 0, 0, 0)
+  XTREG(158, 632, 32, 4, 4, 0x02f0, 0x000f, -2, 2, 0x1000, ccompare0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(159, 636, 32, 4, 4, 0x02f1, 0x000f, -2, 2, 0x1000, ccompare1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(160, 640, 32, 4, 4, 0x0000, 0x0006, -2, 8, 0x0100, a0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(161, 644, 32, 4, 4, 0x0001, 0x0006, -2, 8, 0x0100, a1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(162, 648, 32, 4, 4, 0x0002, 0x0006, -2, 8, 0x0100, a2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(163, 652, 32, 4, 4, 0x0003, 0x0006, -2, 8, 0x0100, a3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(164, 656, 32, 4, 4, 0x0004, 0x0006, -2, 8, 0x0100, a4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(165, 660, 32, 4, 4, 0x0005, 0x0006, -2, 8, 0x0100, a5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(166, 664, 32, 4, 4, 0x0006, 0x0006, -2, 8, 0x0100, a6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(167, 668, 32, 4, 4, 0x0007, 0x0006, -2, 8, 0x0100, a7,
+          0, 0, 0, 0, 0, 0)
+  XTREG(168, 672, 32, 4, 4, 0x0008, 0x0006, -2, 8, 0x0100, a8,
+          0, 0, 0, 0, 0, 0)
+  XTREG(169, 676, 32, 4, 4, 0x0009, 0x0006, -2, 8, 0x0100, a9,
+          0, 0, 0, 0, 0, 0)
+  XTREG(170, 680, 32, 4, 4, 0x000a, 0x0006, -2, 8, 0x0100, a10,
+          0, 0, 0, 0, 0, 0)
+  XTREG(171, 684, 32, 4, 4, 0x000b, 0x0006, -2, 8, 0x0100, a11,
+          0, 0, 0, 0, 0, 0)
+  XTREG(172, 688, 32, 4, 4, 0x000c, 0x0006, -2, 8, 0x0100, a12,
+          0, 0, 0, 0, 0, 0)
+  XTREG(173, 692, 32, 4, 4, 0x000d, 0x0006, -2, 8, 0x0100, a13,
+          0, 0, 0, 0, 0, 0)
+  XTREG(174, 696, 32, 4, 4, 0x000e, 0x0006, -2, 8, 0x0100, a14,
+          0, 0, 0, 0, 0, 0)
+  XTREG(175, 700, 32, 4, 4, 0x000f, 0x0006, -2, 8, 0x0100, a15,
+          0, 0, 0, 0, 0, 0)
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index dacb379..487847c 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -34,6 +34,10 @@
 #include "hw/loader.h"
 #endif
 
+#define XTREG(idx, ofs, bi, sz, al, _targno, flags, cp, typ, _group, name, \
+        a1, a2, a3, a4, a5, a6) \
+    { .targno = (_targno), .type = (typ), .group = (_group) },
+
 void cpu_reset(CPUXtensaState *env)
 {
     env->exception_taken = 0;
@@ -52,6 +56,13 @@ static const XtensaConfig core_config[] = {
         .options = -1 ^
             (XTENSA_OPTION_BIT(XTENSA_OPTION_HW_ALIGNMENT) |
              XTENSA_OPTION_BIT(XTENSA_OPTION_MMU)),
+        .gdb_regmap = {
+            .num_regs = 176,
+            .num_core_regs = 117,
+            .reg = {
+#include "gdb-config-sample-xtensa-core.c"
+            }
+        },
         .nareg = 64,
         .ndepc = 1,
         .excm_level = 16,
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 29/32] target-xtensa: implement memory protection options
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (27 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 28/32] target-xtensa: add gdb support Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-04 18:32   ` Blue Swirl
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 30/32] target-xtensa: add dc232b core and board Max Filippov
                   ` (3 subsequent siblings)
  32 siblings, 1 reply; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

- TLB opcode group;
- region protection option (ISA, 4.6.3);
- region translation option (ISA, 4.6.4);
- MMU option (ISA, 4.6.5).

Cache control attribute bits are not used by this implementation.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/cpu.h       |   56 ++++++++-
 target-xtensa/helper.c    |  340 ++++++++++++++++++++++++++++++++++++++++++++-
 target-xtensa/helpers.h   |    7 +
 target-xtensa/op_helper.c |  301 +++++++++++++++++++++++++++++++++++++++-
 target-xtensa/translate.c |   91 ++++++++++++-
 5 files changed, 782 insertions(+), 13 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 93e17d1..05948f1 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -114,6 +114,10 @@ enum {
     SCOMPARE1 = 12,
     WINDOW_BASE = 72,
     WINDOW_START = 73,
+    PTEVADDR = 83,
+    RASID = 90,
+    ITLBCFG = 91,
+    DTLBCFG = 92,
     EPC1 = 177,
     DEPC = 192,
     EPS2 = 194,
@@ -154,6 +158,9 @@ enum {
 #define MAX_NLEVEL 6
 #define MAX_NNMI 1
 #define MAX_NCCOMPARE 3
+#define MAX_TLB_WAY_SIZE 8
+
+#define REGION_PAGE_MASK 0xe0000000
 
 enum {
     /* Static vectors */
@@ -214,6 +221,21 @@ typedef enum {
     INTTYPE_MAX
 } interrupt_type;
 
+typedef struct xtensa_tlb_entry {
+    uint32_t vaddr;
+    uint32_t paddr;
+    uint8_t asid;
+    uint8_t attr;
+    bool variable;
+} xtensa_tlb_entry;
+
+typedef struct xtensa_tlb {
+    unsigned nways;
+    const unsigned way_size[10];
+    bool varway56;
+    unsigned nrefillentries;
+} xtensa_tlb;
+
 typedef struct XtensaGdbReg {
     int targno;
     int type;
@@ -248,6 +270,9 @@ typedef struct XtensaConfig {
     unsigned nccompare;
     uint32_t timerint[MAX_NCCOMPARE];
     uint32_t clock_freq_khz;
+
+    xtensa_tlb itlb;
+    xtensa_tlb dtlb;
 } XtensaConfig;
 
 typedef struct CPUXtensaState {
@@ -258,6 +283,10 @@ typedef struct CPUXtensaState {
     uint32_t uregs[256];
     uint32_t phys_regs[MAX_NAREG];
 
+    xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
+    xtensa_tlb_entry dtlb[10][MAX_TLB_WAY_SIZE];
+    unsigned autorefill_idx;
+
     int pending_irq_level; /* level of last raised IRQ */
     void **irq_inputs;
     QEMUTimer *ccompare_timer;
@@ -287,12 +316,29 @@ int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
 void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 void xtensa_sync_window_from_phys(CPUState *env);
 void xtensa_sync_phys_from_window(CPUState *env);
+uint32_t xtensa_tlb_get_addr_mask(const CPUState *env, bool dtlb, uint32_t way);
+void split_tlb_entry_spec_way(const CPUState *env, uint32_t v, bool dtlb,
+        uint32_t *vpn, uint32_t wi, uint32_t *ei);
+int xtensa_tlb_lookup(const CPUState *env, uint32_t addr, bool dtlb,
+        uint32_t *_wi, uint32_t *_ei, uint8_t *_ring);
+void xtensa_tlb_set_entry(CPUState *env, bool dtlb,
+        unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
+int xtensa_get_physical_addr(CPUState *env,
+        uint32_t vaddr, int is_write, int mmu_idx,
+        uint32_t *paddr, uint32_t *page_size, unsigned *access);
+
 
 #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
 
+static inline bool xtensa_option_bits_enabled(const XtensaConfig *config,
+        uint64_t opt)
+{
+    return (config->options & opt) != 0;
+}
+
 static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt)
 {
-    return (config->options & XTENSA_OPTION_BIT(opt)) != 0;
+    return xtensa_option_bits_enabled(config, XTENSA_OPTION_BIT(opt));
 }
 
 static inline int xtensa_get_cintlevel(const CPUState *env)
@@ -323,6 +369,14 @@ static inline int xtensa_get_cring(const CPUState *env)
     }
 }
 
+static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUState *env,
+        bool dtlb, unsigned wi, unsigned ei)
+{
+    return dtlb ?
+        env->dtlb[wi] + ei :
+        env->itlb[wi] + ei;
+}
+
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _ring0
 #define MMU_MODE1_SUFFIX _ring1
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 487847c..00571e8 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -38,6 +38,8 @@
         a1, a2, a3, a4, a5, a6) \
     { .targno = (_targno), .type = (typ), .group = (_group) },
 
+static void reset_mmu(CPUState *env);
+
 void cpu_reset(CPUXtensaState *env)
 {
     env->exception_taken = 0;
@@ -48,6 +50,7 @@ void cpu_reset(CPUXtensaState *env)
     env->sregs[VECBASE] = env->config->vecbase;
 
     env->pending_irq_level = 0;
+    reset_mmu(env);
 }
 
 static const XtensaConfig core_config[] = {
@@ -150,7 +153,19 @@ void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf)
 
 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
-    return addr;
+    uint32_t paddr;
+    uint32_t page_size;
+    unsigned access;
+
+    if (0 == xtensa_get_physical_addr(env, addr, 0, 0,
+                &paddr, &page_size, &access)) {
+        return paddr;
+    }
+    if (0 == xtensa_get_physical_addr(env, addr, 2, 0,
+                &paddr, &page_size, &access)) {
+        return paddr;
+    }
+    return ~0;
 }
 
 static uint32_t relocated_vector(CPUState *env, uint32_t vector)
@@ -255,3 +270,326 @@ void do_interrupt(CPUState *env)
     }
     check_interrupts(env);
 }
+
+static void reset_tlb_mmu_all_ways(CPUState *env,
+        const xtensa_tlb *tlb, xtensa_tlb_entry entry[][MAX_TLB_WAY_SIZE])
+{
+    unsigned wi, ei;
+
+    for (wi = 0; wi < tlb->nways; ++wi) {
+        for (ei = 0; ei < tlb->way_size[wi]; ++ei) {
+            entry[wi][ei].asid = 0;
+            entry[wi][ei].variable = true;
+        }
+    }
+}
+
+static void reset_tlb_mmu_ways56(CPUState *env,
+        const xtensa_tlb *tlb, xtensa_tlb_entry entry[][MAX_TLB_WAY_SIZE])
+{
+    if (!tlb->varway56) {
+        static const xtensa_tlb_entry way5[] = {
+            {
+                .vaddr = 0xd0000000,
+                .paddr = 0,
+                .asid = 1,
+                .attr = 7,
+                .variable = false,
+            }, {
+                .vaddr = 0xd8000000,
+                .paddr = 0,
+                .asid = 1,
+                .attr = 3,
+                .variable = false,
+            }
+        };
+        static const xtensa_tlb_entry way6[] = {
+            {
+                .vaddr = 0xe0000000,
+                .paddr = 0xf0000000,
+                .asid = 1,
+                .attr = 7,
+                .variable = false,
+            }, {
+                .vaddr = 0xf0000000,
+                .paddr = 0xf0000000,
+                .asid = 1,
+                .attr = 3,
+                .variable = false,
+            }
+        };
+        memcpy(entry[5], way5, sizeof(way5));
+        memcpy(entry[6], way6, sizeof(way6));
+    } else {
+        uint32_t ei;
+        for (ei = 0; ei < 8; ++ei) {
+            entry[6][ei].vaddr = ei << 29;
+            entry[6][ei].paddr = ei << 29;
+            entry[6][ei].asid = 1;
+            entry[6][ei].attr = 2;
+        }
+    }
+}
+
+static void reset_tlb_region_way0(CPUState *env,
+        xtensa_tlb_entry entry[][MAX_TLB_WAY_SIZE])
+{
+    unsigned ei;
+
+    for (ei = 0; ei < 8; ++ei) {
+        entry[0][ei].vaddr = ei << 29;
+        entry[0][ei].paddr = ei << 29;
+        entry[0][ei].asid = 1;
+        entry[0][ei].attr = 2;
+        entry[0][ei].variable = true;
+    }
+}
+
+static void reset_mmu(CPUState *env)
+{
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+        env->sregs[RASID] = 0x04030201;
+        env->sregs[ITLBCFG] = 0;
+        env->sregs[DTLBCFG] = 0;
+        env->autorefill_idx = 0;
+        reset_tlb_mmu_all_ways(env, &env->config->itlb, env->itlb);
+        reset_tlb_mmu_all_ways(env, &env->config->dtlb, env->dtlb);
+        reset_tlb_mmu_ways56(env, &env->config->itlb, env->itlb);
+        reset_tlb_mmu_ways56(env, &env->config->dtlb, env->dtlb);
+    } else {
+        reset_tlb_region_way0(env, env->itlb);
+        reset_tlb_region_way0(env, env->dtlb);
+    }
+}
+
+static unsigned get_ring(const CPUState *env, uint8_t asid)
+{
+    unsigned i;
+    for (i = 0; i < 4; ++i) {
+        if (((env->sregs[RASID] >> i * 8) & 0xff) == asid) {
+            return i;
+        }
+    }
+    return 0xff;
+}
+
+/*!
+ * Lookup xtensa TLB for the given virtual address.
+ * See ISA, 4.6.2.2
+ *
+ * \param _wi: [out] way index
+ * \param _ei: [out] entry index
+ * \param _ring: [out] access ring
+ * \return 0 if ok, exception cause code otherwise
+ */
+int xtensa_tlb_lookup(const CPUState *env, uint32_t addr, bool dtlb,
+        uint32_t *_wi, uint32_t *_ei, uint8_t *_ring)
+{
+    const xtensa_tlb *tlb = dtlb ?
+        &env->config->dtlb : &env->config->itlb;
+    const xtensa_tlb_entry (*entry)[MAX_TLB_WAY_SIZE] = dtlb ?
+        env->dtlb : env->itlb;
+
+    int nhits = 0;
+    unsigned wi;
+
+    for (wi = 0; wi < tlb->nways; ++wi) {
+        uint32_t vpn;
+        uint32_t ei;
+        split_tlb_entry_spec_way(env, addr, dtlb, &vpn, wi, &ei);
+        if (entry[wi][ei].vaddr == vpn && entry[wi][ei].asid) {
+            unsigned ring = get_ring(env, entry[wi][ei].asid);
+            if (ring < 4) {
+                if (++nhits > 1) {
+                    return dtlb ?
+                        LOAD_STORE_TLB_MULTI_HIT_CAUSE :
+                        INST_TLB_MULTI_HIT_CAUSE;
+                }
+                *_wi = wi;
+                *_ei = ei;
+                *_ring = ring;
+            }
+        }
+    }
+    return nhits ? 0 :
+        (dtlb ? LOAD_STORE_TLB_MISS_CAUSE : INST_TLB_MISS_CAUSE);
+}
+
+/*!
+ * Convert MMU ATTR to PAGE_{READ,WRITE,EXEC} mask.
+ * See ISA, 4.6.5.10
+ */
+static unsigned mmu_attr_to_access(uint32_t attr)
+{
+    unsigned access = 0;
+    if (attr < 12) {
+        access |= PAGE_READ;
+        if (attr & 0x1) {
+            access |= PAGE_EXEC;
+        }
+        if (attr & 0x2) {
+            access |= PAGE_WRITE;
+        }
+    } else if (attr == 13) {
+        access |= PAGE_READ | PAGE_WRITE;
+    }
+    return access;
+}
+
+/*!
+ * Convert region protection ATTR to PAGE_{READ,WRITE,EXEC} mask.
+ * See ISA, 4.6.3.3
+ */
+static unsigned region_attr_to_access(uint32_t attr)
+{
+    unsigned access = 0;
+    if ((attr < 6 && attr != 3) || attr == 14) {
+        access |= PAGE_READ | PAGE_WRITE;
+    }
+    if (attr > 0 && attr < 6) {
+        access |= PAGE_EXEC;
+    }
+    return access;
+}
+
+static bool is_access_granted(unsigned access, int is_write)
+{
+    switch (is_write) {
+    case 0:
+        return access & PAGE_READ;
+
+    case 1:
+        return access & PAGE_WRITE;
+
+    case 2:
+        return access & PAGE_EXEC;
+
+    default:
+        return 0;
+    }
+}
+
+static int autorefill_mmu(CPUState *env, uint32_t vaddr, bool dtlb,
+        uint32_t *wi, uint32_t *ei, uint8_t *ring);
+
+static int get_physical_addr_mmu(CPUState *env,
+        uint32_t vaddr, int is_write, int mmu_idx,
+        uint32_t *paddr, uint32_t *page_size, unsigned *access)
+{
+    bool dtlb = is_write != 2;
+    uint32_t wi;
+    uint32_t ei;
+    uint8_t ring;
+    int ret = xtensa_tlb_lookup(env, vaddr, dtlb, &wi, &ei, &ring);
+
+    if ((ret == INST_TLB_MISS_CAUSE || ret == LOAD_STORE_TLB_MISS_CAUSE) &&
+            (mmu_idx != 0 || ((vaddr ^ env->sregs[PTEVADDR]) & 0xffc00000)) &&
+            autorefill_mmu(env, vaddr, dtlb, &wi, &ei, &ring) == 0) {
+        ret = 0;
+    }
+    if (ret != 0) {
+        return ret;
+    }
+
+    const xtensa_tlb_entry *entry =
+        xtensa_tlb_get_entry(env, dtlb, wi, ei);
+
+    if (ring < mmu_idx) {
+        return dtlb ?
+            LOAD_STORE_PRIVILEGE_CAUSE :
+            INST_FETCH_PRIVILEGE_CAUSE;
+    }
+
+    *access = mmu_attr_to_access(entry->attr);
+    if (!is_access_granted(*access, is_write)) {
+        return dtlb ?
+            (is_write ?
+             STORE_PROHIBITED_CAUSE :
+             LOAD_PROHIBITED_CAUSE) :
+            INST_FETCH_PROHIBITED_CAUSE;
+    }
+
+    *paddr = entry->paddr | (vaddr & ~xtensa_tlb_get_addr_mask(env, dtlb, wi));
+    *page_size = ~xtensa_tlb_get_addr_mask(env, dtlb, wi) + 1;
+
+    return 0;
+}
+
+static int autorefill_mmu(CPUState *env, uint32_t vaddr, bool dtlb,
+        uint32_t *wi, uint32_t *ei, uint8_t *ring)
+{
+    uint32_t paddr;
+    uint32_t page_size;
+    unsigned access;
+    uint32_t pt_vaddr =
+        (env->sregs[PTEVADDR] | (vaddr >> 10)) & 0xfffffffc;
+    int ret = get_physical_addr_mmu(env, pt_vaddr, 0, 0,
+            &paddr, &page_size, &access);
+
+    qemu_log("%s: trying autorefill(%08x) -> %08x\n", __func__,
+            vaddr, ret ? ~0 : paddr);
+
+    if (ret == 0) {
+        uint32_t vpn;
+        uint32_t pte = ldl_phys(paddr);
+
+        *ring = (pte >> 4) & 0x3;
+        *wi = (++env->autorefill_idx) & 0x3;
+        split_tlb_entry_spec_way(env, vaddr, dtlb, &vpn, *wi, ei);
+        xtensa_tlb_set_entry(env, dtlb, *wi, *ei, vpn, pte);
+        qemu_log("%s: autorefill(%08x): %08x -> %08x\n",
+                __func__, vaddr, vpn, pte);
+    }
+    return ret;
+}
+
+static int get_physical_addr_region(CPUState *env,
+        uint32_t vaddr, int is_write, int mmu_idx,
+        uint32_t *paddr, uint32_t *page_size, unsigned *access)
+{
+    bool dtlb = is_write != 2;
+    uint32_t wi = 0;
+    uint32_t ei = (vaddr >> 29) & 0x7;
+    const xtensa_tlb_entry *entry =
+        xtensa_tlb_get_entry(env, dtlb, wi, ei);
+
+    *access = region_attr_to_access(entry->attr);
+    if (!is_access_granted(*access, is_write)) {
+        return dtlb ?
+            (is_write ?
+             STORE_PROHIBITED_CAUSE :
+             LOAD_PROHIBITED_CAUSE) :
+            INST_FETCH_PROHIBITED_CAUSE;
+    }
+
+    *paddr = entry->paddr | (vaddr & ~REGION_PAGE_MASK);
+    *page_size = ~REGION_PAGE_MASK + 1;
+
+    return 0;
+}
+
+/*!
+ * Convert virtual address to physical addr.
+ * MMU may issue pagewalk and change xtensa autorefill TLB way entry.
+ *
+ * \return 0 if ok, exception cause code otherwise
+ */
+int xtensa_get_physical_addr(CPUState *env,
+        uint32_t vaddr, int is_write, int mmu_idx,
+        uint32_t *paddr, uint32_t *page_size, unsigned *access)
+{
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+        return get_physical_addr_mmu(env, vaddr, is_write, mmu_idx,
+                paddr, page_size, access);
+    } else if (xtensa_option_bits_enabled(env->config,
+                XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
+                XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION))) {
+        return get_physical_addr_region(env, vaddr, is_write, mmu_idx,
+                paddr, page_size, access);
+    } else {
+        *paddr = vaddr;
+        *page_size = TARGET_PAGE_SIZE;
+        *access = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+        return 0;
+    }
+}
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index 28689c3..09ab332 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -22,4 +22,11 @@ DEF_HELPER_2(timer_irq, void, i32, i32)
 DEF_HELPER_1(advance_ccount, void, i32)
 DEF_HELPER_1(check_interrupts, void, env)
 
+DEF_HELPER_1(wsr_rasid, void, i32)
+DEF_HELPER_2(rtlb0, i32, i32, i32)
+DEF_HELPER_2(rtlb1, i32, i32, i32)
+DEF_HELPER_2(itlb, void, i32, i32)
+DEF_HELPER_2(ptlb, i32, i32, i32)
+DEF_HELPER_3(wtlb, void, i32, i32, i32)
+
 #include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index fcec506..6a9c886 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -70,13 +70,32 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
     }
 }
 
-void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
+void tlb_fill(target_ulong vaddr, int is_write, int mmu_idx, void *retaddr)
 {
-    tlb_set_page(cpu_single_env,
-            addr & ~(TARGET_PAGE_SIZE - 1),
-            addr & ~(TARGET_PAGE_SIZE - 1),
-            PAGE_READ | PAGE_WRITE | PAGE_EXEC,
-            mmu_idx, TARGET_PAGE_SIZE);
+    CPUState *saved_env = env;
+
+    env = cpu_single_env;
+    {
+        uint32_t paddr;
+        uint32_t page_size;
+        unsigned access;
+        int ret = xtensa_get_physical_addr(env, vaddr, is_write, mmu_idx,
+                &paddr, &page_size, &access);
+
+        qemu_log("%s(%08x, %d, %d) -> %08x, ret = %d\n", __func__,
+                vaddr, is_write, mmu_idx, paddr, ret);
+
+        if (ret == 0) {
+            tlb_set_page(env,
+                    vaddr & TARGET_PAGE_MASK,
+                    paddr & TARGET_PAGE_MASK,
+                    access, mmu_idx, page_size);
+        } else {
+            do_restore_state(retaddr);
+            HELPER(exception_cause_vaddr)(env->pc, ret, vaddr);
+        }
+    }
+    env = saved_env;
 }
 
 void HELPER(exception)(uint32_t excp)
@@ -377,3 +396,273 @@ void HELPER(check_interrupts)(CPUState *env)
 {
     check_interrupts(env);
 }
+
+void HELPER(wsr_rasid)(uint32_t v)
+{
+    v = (v & 0xffffff00) | 0x1;
+    if (v != env->sregs[RASID]) {
+        env->sregs[RASID] = v;
+        tlb_flush(env, 1);
+    }
+}
+
+static uint32_t get_page_size(const CPUState *env, bool dtlb, uint32_t way)
+{
+    uint32_t tlbcfg = env->sregs[dtlb ? DTLBCFG : ITLBCFG];
+
+    switch (way) {
+    case 4:
+        return (tlbcfg >> 16) & 0x3;
+
+    case 5:
+        return (tlbcfg >> 20) & 0x1;
+
+    case 6:
+        return (tlbcfg >> 24) & 0x1;
+
+    default:
+        return 0;
+    }
+}
+
+/*!
+ * Get bit mask for the virtual address bits translated by the TLB way
+ */
+uint32_t xtensa_tlb_get_addr_mask(const CPUState *env, bool dtlb, uint32_t way)
+{
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+        bool varway56 = dtlb ?
+            env->config->dtlb.varway56 :
+            env->config->itlb.varway56;
+
+        switch (way) {
+        case 4:
+            return 0xfff00000 << get_page_size(env, dtlb, way) * 2;
+
+        case 5:
+            if (varway56) {
+                return 0xf8000000 << get_page_size(env, dtlb, way);
+            } else {
+                return 0xf8000000;
+            }
+
+        case 6:
+            if (varway56) {
+                return 0xf0000000 << (1 - get_page_size(env, dtlb, way));
+            } else {
+                return 0xf0000000;
+            }
+
+        default:
+            return 0xfffff000;
+        }
+    } else {
+        return REGION_PAGE_MASK;
+    }
+}
+
+/*!
+ * Get bit mask for the 'VPN without index' field.
+ * See ISA, 4.6.5.6, data format for RxTLB0
+ */
+static uint32_t get_vpn_mask(const CPUState *env, bool dtlb, uint32_t way)
+{
+    if (way < 4) {
+        bool is32 = (dtlb ?
+                env->config->dtlb.nrefillentries :
+                env->config->itlb.nrefillentries) == 32;
+        return is32 ? 0xffff8000 : 0xffffc000;
+    } else if (way == 4) {
+        return xtensa_tlb_get_addr_mask(env, dtlb, way) << 2;
+    } else if (way <= 6) {
+        uint32_t mask = xtensa_tlb_get_addr_mask(env, dtlb, way);
+        bool varway56 = dtlb ?
+            env->config->dtlb.varway56 :
+            env->config->itlb.varway56;
+
+        if (varway56) {
+            return mask << (way == 5 ? 2 : 3);
+        } else {
+            return mask << 1;
+        }
+    } else {
+        return 0xfffff000;
+    }
+}
+
+/*!
+ * Split virtual address into VPN (with index) and entry index
+ * for the given TLB way
+ */
+void split_tlb_entry_spec_way(const CPUState *env, uint32_t v, bool dtlb,
+        uint32_t *vpn, uint32_t wi, uint32_t *ei)
+{
+    bool varway56 = dtlb ?
+        env->config->dtlb.varway56 :
+        env->config->itlb.varway56;
+
+    if (!dtlb) {
+        wi &= 7;
+    }
+
+    if (wi < 4) {
+        bool is32 = (dtlb ?
+                env->config->dtlb.nrefillentries :
+                env->config->itlb.nrefillentries) == 32;
+        *ei = (v >> 12) & (is32 ? 0x7 : 0x3);
+    } else {
+        switch (wi) {
+        case 4:
+            {
+                uint32_t eibase = 20 + get_page_size(env, dtlb, wi) * 2;
+                *ei = (v >> eibase) & 0x3;
+            }
+            break;
+
+        case 5:
+            if (varway56) {
+                uint32_t eibase = 27 + get_page_size(env, dtlb, wi);
+                *ei = (v >> eibase) & 0x3;
+            } else {
+                *ei = (v >> 27) & 0x1;
+            }
+            break;
+
+        case 6:
+            if (varway56) {
+                uint32_t eibase = 29 - get_page_size(env, dtlb, wi);
+                *ei = (v >> eibase) & 0x7;
+            } else {
+                *ei = (v >> 28) & 0x1;
+            }
+            break;
+
+        default:
+            *ei = 0;
+            break;
+        }
+    }
+    *vpn = v & xtensa_tlb_get_addr_mask(env, dtlb, wi);
+}
+
+/*!
+ * Split TLB address into TLB way, entry index and VPN (with index).
+ * See ISA, 4.6.5.5 - 4.6.5.8 for the TLB addressing format
+ */
+static void split_tlb_entry_spec(uint32_t v, bool dtlb,
+        uint32_t *vpn, uint32_t *wi, uint32_t *ei)
+{
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+        *wi = v & (dtlb ? 0xf : 0x7);
+        split_tlb_entry_spec_way(env, v, dtlb, vpn, *wi, ei);
+    } else {
+        *vpn = v & REGION_PAGE_MASK;
+        *wi = 0;
+        *ei = (v >> 29) & 0x7;
+    }
+}
+
+static xtensa_tlb_entry *get_tlb_entry(uint32_t v, bool dtlb, uint32_t *_wi)
+{
+    uint32_t vpn;
+    uint32_t wi;
+    uint32_t ei;
+
+    split_tlb_entry_spec(v, dtlb, &vpn, &wi, &ei);
+    if (_wi) {
+        *_wi = wi;
+    }
+    return xtensa_tlb_get_entry(env, dtlb, wi, ei);
+}
+
+uint32_t HELPER(rtlb0)(uint32_t v, uint32_t dtlb)
+{
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+        uint32_t wi;
+        const xtensa_tlb_entry *entry = get_tlb_entry(v, dtlb, &wi);
+        return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid;
+    } else {
+        return v & REGION_PAGE_MASK;
+    }
+}
+
+uint32_t HELPER(rtlb1)(uint32_t v, uint32_t dtlb)
+{
+    const xtensa_tlb_entry *entry = get_tlb_entry(v, dtlb, NULL);
+    return entry->paddr | entry->attr;
+}
+
+void HELPER(itlb)(uint32_t v, uint32_t dtlb)
+{
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+        uint32_t wi;
+        xtensa_tlb_entry *entry = get_tlb_entry(v, dtlb, &wi);
+        if (entry->variable && entry->asid) {
+            tlb_flush_page(env, entry->vaddr);
+            entry->asid = 0;
+        }
+    }
+}
+
+uint32_t HELPER(ptlb)(uint32_t v, uint32_t dtlb)
+{
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+        uint32_t wi;
+        uint32_t ei;
+        uint8_t ring;
+        int res = xtensa_tlb_lookup(env, v, dtlb, &wi, &ei, &ring);
+
+        switch (res) {
+        case 0:
+            if (ring >= xtensa_get_ring(env)) {
+                return (v & 0xfffff000) | wi | (dtlb ? 0x10 : 0x8);
+            }
+            break;
+
+        case INST_TLB_MULTI_HIT_CAUSE:
+        case LOAD_STORE_TLB_MULTI_HIT_CAUSE:
+            HELPER(exception_cause_vaddr)(env->pc, res, v);
+            break;
+        }
+        return 0;
+    } else {
+        return (v & REGION_PAGE_MASK) | 0x1;
+    }
+}
+
+void xtensa_tlb_set_entry(CPUState *env, bool dtlb,
+        unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte)
+{
+    xtensa_tlb_entry *entry = xtensa_tlb_get_entry(env, dtlb, wi, ei);
+
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+        if (entry->variable) {
+            if (entry->asid) {
+                tlb_flush_page(env, entry->vaddr);
+            }
+            entry->vaddr = vpn;
+            entry->paddr = pte & xtensa_tlb_get_addr_mask(env, dtlb, wi);
+            entry->asid = (env->sregs[RASID] >> ((pte >> 1) & 0x18)) & 0xff;
+            entry->attr = pte & 0xf;
+        } else {
+            qemu_log("%s %d, %d, %d trying to set immutable entry\n",
+                    __func__, dtlb, wi, ei);
+        }
+    } else {
+        tlb_flush_page(env, entry->vaddr);
+        if (xtensa_option_enabled(env->config,
+                    XTENSA_OPTION_REGION_TRANSLATION)) {
+            entry->paddr = pte & REGION_PAGE_MASK;
+        }
+        entry->attr = pte & 0xf;
+    }
+}
+
+void HELPER(wtlb)(uint32_t p, uint32_t v, uint32_t dtlb)
+{
+    uint32_t vpn;
+    uint32_t wi;
+    uint32_t ei;
+    split_tlb_entry_spec(v, dtlb, &vpn, &wi, &ei);
+    xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 3b21bc4..731f04f 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -80,6 +80,10 @@ static const char * const sregnames[256] = {
     [SCOMPARE1] = "SCOMPARE1",
     [WINDOW_BASE] = "WINDOW_BASE",
     [WINDOW_START] = "WINDOW_START",
+    [PTEVADDR] = "PTEVADDR",
+    [RASID] = "RASID",
+    [ITLBCFG] = "ITLBCFG",
+    [DTLBCFG] = "DTLBCFG",
     [EPC1] = "EPC1",
     [EPC1 + 1] = "EPC2",
     [EPC1 + 2] = "EPC3",
@@ -161,6 +165,11 @@ void xtensa_translate_init(void)
 #include "helpers.h"
 }
 
+static inline bool option_bits_enabled(DisasContext *dc, uint64_t opt)
+{
+    return xtensa_option_bits_enabled(dc->config, opt);
+}
+
 static inline bool option_enabled(DisasContext *dc, int opt)
 {
     return xtensa_option_enabled(dc->config, opt);
@@ -379,11 +388,19 @@ static void gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr)
     tcg_gen_mov_i32(d, cpu_SR[sr]);
 }
 
+static void gen_rsr_ptevaddr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
+{
+    tcg_gen_shri_i32(d, cpu_SR[EXCVADDR], 10);
+    tcg_gen_or_i32(d, d, cpu_SR[sr]);
+    tcg_gen_andi_i32(d, d, 0xfffffffc);
+}
+
 static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
 {
     static void (* const rsr_handler[256])(DisasContext *dc,
             TCGv_i32 d, uint32_t sr) = {
         [CCOUNT] = gen_rsr_ccount,
+        [PTEVADDR] = gen_rsr_ptevaddr,
     };
 
     if (sregnames[sr]) {
@@ -436,6 +453,23 @@ static void gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     reset_used_window(dc);
 }
 
+static void gen_wsr_ptevaddr(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    tcg_gen_andi_i32(cpu_SR[sr], v, 0xffc00000);
+}
+
+static void gen_wsr_rasid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    gen_helper_wsr_rasid(v);
+    /* This can change tb->flags, so exit tb */
+    gen_jumpi_check_loop_end(dc, -1);
+}
+
+static void gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    tcg_gen_andi_i32(cpu_SR[sr], v, 0x01130000);
+}
+
 static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     tcg_gen_andi_i32(cpu_SR[sr], v,
@@ -505,6 +539,10 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [LITBASE] = gen_wsr_litbase,
         [WINDOW_BASE] = gen_wsr_windowbase,
         [WINDOW_START] = gen_wsr_windowstart,
+        [PTEVADDR] = gen_wsr_ptevaddr,
+        [RASID] = gen_wsr_rasid,
+        [ITLBCFG] = gen_wsr_tlbcfg,
+        [DTLBCFG] = gen_wsr_tlbcfg,
         [INTSET] = gen_wsr_intset,
         [INTCLEAR] = gen_wsr_intclear,
         [INTENABLE] = gen_wsr_intenable,
@@ -585,14 +623,16 @@ static void gen_window_check3(DisasContext *dc, unsigned r1, unsigned r2,
 
 static void disas_xtensa_insn(DisasContext *dc)
 {
-#define HAS_OPTION(opt) do { \
-        if (!option_enabled(dc, opt)) { \
-            qemu_log("Option %d is not enabled %s:%d\n", \
-                    (opt), __FILE__, __LINE__); \
+#define HAS_OPTION_BITS(opt) do { \
+        if (!option_bits_enabled(dc, opt)) { \
+            qemu_log("Option is not enabled %s:%d\n", \
+                    __FILE__, __LINE__); \
             goto invalid_opcode; \
         } \
     } while (0)
 
+#define HAS_OPTION(opt) HAS_OPTION_BITS(XTENSA_OPTION_BIT(opt))
+
 #define TBD() qemu_log("TBD(pc = %08x): %s:%d\n", dc->pc, __FILE__, __LINE__)
 #define RESERVED() do { \
         qemu_log("RESERVED(pc = %08x, %02x%02x%02x): %s:%d\n", \
@@ -1055,7 +1095,48 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 5: /*TLB*/
-                TBD();
+                HAS_OPTION_BITS(
+                        XTENSA_OPTION_BIT(XTENSA_OPTION_MMU) |
+                        XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
+                        XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION));
+                gen_check_privilege(dc);
+                gen_window_check2(dc, RRR_S, RRR_T);
+                {
+                    TCGv_i32 dtlb = tcg_const_i32((RRR_R & 8) != 0);
+
+                    switch (RRR_R & 7) {
+                    case 3: /*RITLB0*/ /*RDTLB0*/
+                        gen_helper_rtlb0(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+                        break;
+
+                    case 4: /*IITLB*/ /*IDTLB*/
+                        gen_helper_itlb(cpu_R[RRR_S], dtlb);
+                        /* This could change memory mapping, so exit tb */
+                        gen_jumpi_check_loop_end(dc, -1);
+                        break;
+
+                    case 5: /*PITLB*/ /*PDTLB*/
+                        tcg_gen_movi_i32(cpu_pc, dc->pc);
+                        gen_helper_ptlb(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+                        break;
+
+                    case 6: /*WITLB*/ /*WDTLB*/
+                        gen_helper_wtlb(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+                        /* This could change memory mapping, so exit tb */
+                        gen_jumpi_check_loop_end(dc, -1);
+                        break;
+
+                    case 7: /*RITLB1*/ /*RDTLB1*/
+                        gen_helper_rtlb1(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+                        break;
+
+                    default:
+                        tcg_temp_free(dtlb);
+                        RESERVED();
+                        break;
+                    }
+                    tcg_temp_free(dtlb);
+                }
                 break;
 
             case 6: /*RT0*/
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 30/32] target-xtensa: add dc232b core and board
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (28 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 29/32] target-xtensa: implement memory protection options Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-04 18:33   ` Blue Swirl
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 31/32] MAINTAINERS: add xtensa maintainer Max Filippov
                   ` (2 subsequent siblings)
  32 siblings, 1 reply; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

This is Diamond 232L Standard Core Rev.B (LE).

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 Makefile.target                   |    1 +
 hw/xtensa_dc232b.c                |  112 ++++++++++++++++
 target-xtensa/gdb-config-dc232b.c |  261 +++++++++++++++++++++++++++++++++++++
 target-xtensa/helper.c            |  168 ++++++++++++++++++++++++
 4 files changed, 542 insertions(+), 0 deletions(-)
 create mode 100644 hw/xtensa_dc232b.c
 create mode 100644 target-xtensa/gdb-config-dc232b.c

diff --git a/Makefile.target b/Makefile.target
index 9bbb668..579820b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -375,6 +375,7 @@ obj-alpha-y += vga.o cirrus_vga.o
 
 obj-xtensa-y += xtensa_pic.o
 obj-xtensa-y += xtensa_sample.o
+obj-xtensa-y += xtensa_dc232b.o
 obj-xtensa-y += xtensa-semi.o
 
 main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
diff --git a/hw/xtensa_dc232b.c b/hw/xtensa_dc232b.c
new file mode 100644
index 0000000..9b0bac7
--- /dev/null
+++ b/hw/xtensa_dc232b.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sysemu.h"
+#include "boards.h"
+#include "loader.h"
+#include "elf.h"
+
+static uint64_t translate_phys_addr(void *env, uint64_t addr)
+{
+    return cpu_get_phys_page_debug(env, addr);
+}
+
+static void dc232b_reset(void *env)
+{
+    cpu_reset(env);
+}
+
+static void dc232b_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)
+{
+    CPUState *env = NULL;
+    ram_addr_t ram_offset;
+    int n;
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        env->sregs[PRID] = n;
+        qemu_register_reset(dc232b_reset, env);
+        /* Need MMU initialized prior to ELF loading,
+         * so that ELF gets loaded into virtual addresses
+         */
+        dc232b_reset(env);
+    }
+
+    ram_offset = qemu_ram_alloc(NULL, "xtensa.sram", ram_size);
+    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
+
+    ram_offset = qemu_ram_alloc(NULL, "xtensa.rom", 0x1000);
+    cpu_register_physical_memory(0xfe000000, 0x1000, ram_offset | IO_MEM_RAM);
+
+    if (kernel_filename) {
+        uint64_t elf_entry;
+        uint64_t elf_lowaddr;
+#ifdef TARGET_WORDS_BIGENDIAN
+        int success = load_elf(kernel_filename, translate_phys_addr, env,
+                &elf_entry, &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
+#else
+        int success = load_elf(kernel_filename, translate_phys_addr, env,
+                &elf_entry, &elf_lowaddr, NULL, 0, ELF_MACHINE, 0);
+#endif
+        if (success > 0) {
+            env->pc = elf_entry;
+        }
+    }
+}
+
+static void xtensa_dc232b_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)
+{
+    if (!cpu_model) {
+        cpu_model = "dc232b";
+    }
+    dc232b_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
+            initrd_filename, cpu_model);
+}
+
+static QEMUMachine xtensa_dc232b_machine = {
+    .name = "dc232b",
+    .desc = "Diamond 232L Standard Core Rev.B (LE) (dc232b)",
+    .init = xtensa_dc232b_init,
+    .max_cpus = 4,
+};
+
+static void xtensa_dc232b_machine_init(void)
+{
+    qemu_register_machine(&xtensa_dc232b_machine);
+}
+
+machine_init(xtensa_dc232b_machine_init);
diff --git a/target-xtensa/gdb-config-dc232b.c b/target-xtensa/gdb-config-dc232b.c
new file mode 100644
index 0000000..13aba5e
--- /dev/null
+++ b/target-xtensa/gdb-config-dc232b.c
@@ -0,0 +1,261 @@
+/* Configuration for the Xtensa architecture for GDB, the GNU debugger.
+
+   Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+  XTREG(0,   0, 32, 4, 4, 0x0020, 0x0006, -2, 9, 0x0100, pc,
+          0, 0, 0, 0, 0, 0)
+  XTREG(1,   4, 32, 4, 4, 0x0100, 0x0006, -2, 1, 0x0002, ar0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(2,   8, 32, 4, 4, 0x0101, 0x0006, -2, 1, 0x0002, ar1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(3,  12, 32, 4, 4, 0x0102, 0x0006, -2, 1, 0x0002, ar2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(4,  16, 32, 4, 4, 0x0103, 0x0006, -2, 1, 0x0002, ar3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(5,  20, 32, 4, 4, 0x0104, 0x0006, -2, 1, 0x0002, ar4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(6,  24, 32, 4, 4, 0x0105, 0x0006, -2, 1, 0x0002, ar5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(7,  28, 32, 4, 4, 0x0106, 0x0006, -2, 1, 0x0002, ar6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(8,  32, 32, 4, 4, 0x0107, 0x0006, -2, 1, 0x0002, ar7,
+          0, 0, 0, 0, 0, 0)
+  XTREG(9,  36, 32, 4, 4, 0x0108, 0x0006, -2, 1, 0x0002, ar8,
+          0, 0, 0, 0, 0, 0)
+  XTREG(10,  40, 32, 4, 4, 0x0109, 0x0006, -2, 1, 0x0002, ar9,
+          0, 0, 0, 0, 0, 0)
+  XTREG(11,  44, 32, 4, 4, 0x010a, 0x0006, -2, 1, 0x0002, ar10,
+          0, 0, 0, 0, 0, 0)
+  XTREG(12,  48, 32, 4, 4, 0x010b, 0x0006, -2, 1, 0x0002, ar11,
+          0, 0, 0, 0, 0, 0)
+  XTREG(13,  52, 32, 4, 4, 0x010c, 0x0006, -2, 1, 0x0002, ar12,
+          0, 0, 0, 0, 0, 0)
+  XTREG(14,  56, 32, 4, 4, 0x010d, 0x0006, -2, 1, 0x0002, ar13,
+          0, 0, 0, 0, 0, 0)
+  XTREG(15,  60, 32, 4, 4, 0x010e, 0x0006, -2, 1, 0x0002, ar14,
+          0, 0, 0, 0, 0, 0)
+  XTREG(16,  64, 32, 4, 4, 0x010f, 0x0006, -2, 1, 0x0002, ar15,
+          0, 0, 0, 0, 0, 0)
+  XTREG(17,  68, 32, 4, 4, 0x0110, 0x0006, -2, 1, 0x0002, ar16,
+          0, 0, 0, 0, 0, 0)
+  XTREG(18,  72, 32, 4, 4, 0x0111, 0x0006, -2, 1, 0x0002, ar17,
+          0, 0, 0, 0, 0, 0)
+  XTREG(19,  76, 32, 4, 4, 0x0112, 0x0006, -2, 1, 0x0002, ar18,
+          0, 0, 0, 0, 0, 0)
+  XTREG(20,  80, 32, 4, 4, 0x0113, 0x0006, -2, 1, 0x0002, ar19,
+          0, 0, 0, 0, 0, 0)
+  XTREG(21,  84, 32, 4, 4, 0x0114, 0x0006, -2, 1, 0x0002, ar20,
+          0, 0, 0, 0, 0, 0)
+  XTREG(22,  88, 32, 4, 4, 0x0115, 0x0006, -2, 1, 0x0002, ar21,
+          0, 0, 0, 0, 0, 0)
+  XTREG(23,  92, 32, 4, 4, 0x0116, 0x0006, -2, 1, 0x0002, ar22,
+          0, 0, 0, 0, 0, 0)
+  XTREG(24,  96, 32, 4, 4, 0x0117, 0x0006, -2, 1, 0x0002, ar23,
+          0, 0, 0, 0, 0, 0)
+  XTREG(25, 100, 32, 4, 4, 0x0118, 0x0006, -2, 1, 0x0002, ar24,
+          0, 0, 0, 0, 0, 0)
+  XTREG(26, 104, 32, 4, 4, 0x0119, 0x0006, -2, 1, 0x0002, ar25,
+          0, 0, 0, 0, 0, 0)
+  XTREG(27, 108, 32, 4, 4, 0x011a, 0x0006, -2, 1, 0x0002, ar26,
+          0, 0, 0, 0, 0, 0)
+  XTREG(28, 112, 32, 4, 4, 0x011b, 0x0006, -2, 1, 0x0002, ar27,
+          0, 0, 0, 0, 0, 0)
+  XTREG(29, 116, 32, 4, 4, 0x011c, 0x0006, -2, 1, 0x0002, ar28,
+          0, 0, 0, 0, 0, 0)
+  XTREG(30, 120, 32, 4, 4, 0x011d, 0x0006, -2, 1, 0x0002, ar29,
+          0, 0, 0, 0, 0, 0)
+  XTREG(31, 124, 32, 4, 4, 0x011e, 0x0006, -2, 1, 0x0002, ar30,
+          0, 0, 0, 0, 0, 0)
+  XTREG(32, 128, 32, 4, 4, 0x011f, 0x0006, -2, 1, 0x0002, ar31,
+          0, 0, 0, 0, 0, 0)
+  XTREG(33, 132, 32, 4, 4, 0x0200, 0x0006, -2, 2, 0x1100, lbeg,
+          0, 0, 0, 0, 0, 0)
+  XTREG(34, 136, 32, 4, 4, 0x0201, 0x0006, -2, 2, 0x1100, lend,
+          0, 0, 0, 0, 0, 0)
+  XTREG(35, 140, 32, 4, 4, 0x0202, 0x0006, -2, 2, 0x1100, lcount,
+          0, 0, 0, 0, 0, 0)
+  XTREG(36, 144,  6, 4, 4, 0x0203, 0x0006, -2, 2, 0x1100, sar,
+          0, 0, 0, 0, 0, 0)
+  XTREG(37, 148, 32, 4, 4, 0x0205, 0x0006, -2, 2, 0x1100, litbase,
+          0, 0, 0, 0, 0, 0)
+  XTREG(38, 152,  3, 4, 4, 0x0248, 0x0006, -2, 2, 0x1002, windowbase,
+          0, 0, 0, 0, 0, 0)
+  XTREG(39, 156,  8, 4, 4, 0x0249, 0x0006, -2, 2, 0x1002, windowstart,
+          0, 0, 0, 0, 0, 0)
+  XTREG(40, 160, 32, 4, 4, 0x02b0, 0x0002, -2, 2, 0x1000, sr176,
+          0, 0, 0, 0, 0, 0)
+  XTREG(41, 164, 32, 4, 4, 0x02d0, 0x0002, -2, 2, 0x1000, sr208,
+          0, 0, 0, 0, 0, 0)
+  XTREG(42, 168, 19, 4, 4, 0x02e6, 0x0006, -2, 2, 0x1100, ps,
+          0, 0, 0, 0, 0, 0)
+  XTREG(43, 172, 32, 4, 4, 0x03e7, 0x0006, -2, 3, 0x0110, threadptr,
+          0, 0, 0, 0, 0, 0)
+  XTREG(44, 176, 32, 4, 4, 0x020c, 0x0006, -1, 2, 0x1100, scompare1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(45, 180, 32, 4, 4, 0x0210, 0x0006, -1, 2, 0x1100, acclo,
+          0, 0, 0, 0, 0, 0)
+  XTREG(46, 184,  8, 4, 4, 0x0211, 0x0006, -1, 2, 0x1100, acchi,
+          0, 0, 0, 0, 0, 0)
+  XTREG(47, 188, 32, 4, 4, 0x0220, 0x0006, -1, 2, 0x1100, m0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(48, 192, 32, 4, 4, 0x0221, 0x0006, -1, 2, 0x1100, m1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(49, 196, 32, 4, 4, 0x0222, 0x0006, -1, 2, 0x1100, m2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(50, 200, 32, 4, 4, 0x0223, 0x0006, -1, 2, 0x1100, m3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(51, 204, 32, 4, 4, 0x03e6, 0x000e, -1, 3, 0x0110, expstate,
+          0, 0, 0, 0, 0, 0)
+  XTREG(52, 208, 32, 4, 4, 0x0253, 0x0007, -2, 2, 0x1000, ptevaddr,
+          0, 0, 0, 0, 0, 0)
+  XTREG(53, 212, 32, 4, 4, 0x0259, 0x000d, -2, 2, 0x1000, mmid,
+          0, 0, 0, 0, 0, 0)
+  XTREG(54, 216, 32, 4, 4, 0x025a, 0x0007, -2, 2, 0x1000, rasid,
+          0, 0, 0, 0, 0, 0)
+  XTREG(55, 220, 18, 4, 4, 0x025b, 0x0007, -2, 2, 0x1000, itlbcfg,
+          0, 0, 0, 0, 0, 0)
+  XTREG(56, 224, 18, 4, 4, 0x025c, 0x0007, -2, 2, 0x1000, dtlbcfg,
+          0, 0, 0, 0, 0, 0)
+  XTREG(57, 228,  2, 4, 4, 0x0260, 0x0007, -2, 2, 0x1000, ibreakenable,
+          0, 0, 0, 0, 0, 0)
+  XTREG(58, 232, 32, 4, 4, 0x0268, 0x0007, -2, 2, 0x1000, ddr,
+          0, 0, 0, 0, 0, 0)
+  XTREG(59, 236, 32, 4, 4, 0x0280, 0x0007, -2, 2, 0x1000, ibreaka0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(60, 240, 32, 4, 4, 0x0281, 0x0007, -2, 2, 0x1000, ibreaka1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(61, 244, 32, 4, 4, 0x0290, 0x0007, -2, 2, 0x1000, dbreaka0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(62, 248, 32, 4, 4, 0x0291, 0x0007, -2, 2, 0x1000, dbreaka1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(63, 252, 32, 4, 4, 0x02a0, 0x0007, -2, 2, 0x1000, dbreakc0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(64, 256, 32, 4, 4, 0x02a1, 0x0007, -2, 2, 0x1000, dbreakc1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(65, 260, 32, 4, 4, 0x02b1, 0x0007, -2, 2, 0x1000, epc1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(66, 264, 32, 4, 4, 0x02b2, 0x0007, -2, 2, 0x1000, epc2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(67, 268, 32, 4, 4, 0x02b3, 0x0007, -2, 2, 0x1000, epc3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(68, 272, 32, 4, 4, 0x02b4, 0x0007, -2, 2, 0x1000, epc4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(69, 276, 32, 4, 4, 0x02b5, 0x0007, -2, 2, 0x1000, epc5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(70, 280, 32, 4, 4, 0x02b6, 0x0007, -2, 2, 0x1000, epc6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(71, 284, 32, 4, 4, 0x02b7, 0x0007, -2, 2, 0x1000, epc7,
+          0, 0, 0, 0, 0, 0)
+  XTREG(72, 288, 32, 4, 4, 0x02c0, 0x0007, -2, 2, 0x1000, depc,
+          0, 0, 0, 0, 0, 0)
+  XTREG(73, 292, 19, 4, 4, 0x02c2, 0x0007, -2, 2, 0x1000, eps2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(74, 296, 19, 4, 4, 0x02c3, 0x0007, -2, 2, 0x1000, eps3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(75, 300, 19, 4, 4, 0x02c4, 0x0007, -2, 2, 0x1000, eps4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(76, 304, 19, 4, 4, 0x02c5, 0x0007, -2, 2, 0x1000, eps5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(77, 308, 19, 4, 4, 0x02c6, 0x0007, -2, 2, 0x1000, eps6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(78, 312, 19, 4, 4, 0x02c7, 0x0007, -2, 2, 0x1000, eps7,
+          0, 0, 0, 0, 0, 0)
+  XTREG(79, 316, 32, 4, 4, 0x02d1, 0x0007, -2, 2, 0x1000, excsave1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(80, 320, 32, 4, 4, 0x02d2, 0x0007, -2, 2, 0x1000, excsave2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(81, 324, 32, 4, 4, 0x02d3, 0x0007, -2, 2, 0x1000, excsave3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(82, 328, 32, 4, 4, 0x02d4, 0x0007, -2, 2, 0x1000, excsave4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(83, 332, 32, 4, 4, 0x02d5, 0x0007, -2, 2, 0x1000, excsave5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(84, 336, 32, 4, 4, 0x02d6, 0x0007, -2, 2, 0x1000, excsave6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(85, 340, 32, 4, 4, 0x02d7, 0x0007, -2, 2, 0x1000, excsave7,
+          0, 0, 0, 0, 0, 0)
+  XTREG(86, 344,  8, 4, 4, 0x02e0, 0x0007, -2, 2, 0x1000, cpenable,
+          0, 0, 0, 0, 0, 0)
+  XTREG(87, 348, 22, 4, 4, 0x02e2, 0x000b, -2, 2, 0x1000, interrupt,
+          0, 0, 0, 0, 0, 0)
+  XTREG(88, 352, 22, 4, 4, 0x02e2, 0x000d, -2, 2, 0x1000, intset,
+          0, 0, 0, 0, 0, 0)
+  XTREG(89, 356, 22, 4, 4, 0x02e3, 0x000d, -2, 2, 0x1000, intclear,
+          0, 0, 0, 0, 0, 0)
+  XTREG(90, 360, 22, 4, 4, 0x02e4, 0x0007, -2, 2, 0x1000, intenable,
+          0, 0, 0, 0, 0, 0)
+  XTREG(91, 364, 32, 4, 4, 0x02e7, 0x0007, -2, 2, 0x1000, vecbase,
+          0, 0, 0, 0, 0, 0)
+  XTREG(92, 368,  6, 4, 4, 0x02e8, 0x0007, -2, 2, 0x1000, exccause,
+          0, 0, 0, 0, 0, 0)
+  XTREG(93, 372, 12, 4, 4, 0x02e9, 0x0003, -2, 2, 0x1000, debugcause,
+          0, 0, 0, 0, 0, 0)
+  XTREG(94, 376, 32, 4, 4, 0x02ea, 0x000f, -2, 2, 0x1000, ccount,
+          0, 0, 0, 0, 0, 0)
+  XTREG(95, 380, 32, 4, 4, 0x02eb, 0x0003, -2, 2, 0x1000, prid,
+          0, 0, 0, 0, 0, 0)
+  XTREG(96, 384, 32, 4, 4, 0x02ec, 0x000f, -2, 2, 0x1000, icount,
+          0, 0, 0, 0, 0, 0)
+  XTREG(97, 388,  4, 4, 4, 0x02ed, 0x0007, -2, 2, 0x1000, icountlevel,
+          0, 0, 0, 0, 0, 0)
+  XTREG(98, 392, 32, 4, 4, 0x02ee, 0x0007, -2, 2, 0x1000, excvaddr,
+          0, 0, 0, 0, 0, 0)
+  XTREG(99, 396, 32, 4, 4, 0x02f0, 0x000f, -2, 2, 0x1000, ccompare0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(100, 400, 32, 4, 4, 0x02f1, 0x000f, -2, 2, 0x1000, ccompare1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(101, 404, 32, 4, 4, 0x02f2, 0x000f, -2, 2, 0x1000, ccompare2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(102, 408, 32, 4, 4, 0x02f4, 0x0007, -2, 2, 0x1000, misc0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(103, 412, 32, 4, 4, 0x02f5, 0x0007, -2, 2, 0x1000, misc1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(104, 416, 32, 4, 4, 0x0000, 0x0006, -2, 8, 0x0100, a0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(105, 420, 32, 4, 4, 0x0001, 0x0006, -2, 8, 0x0100, a1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(106, 424, 32, 4, 4, 0x0002, 0x0006, -2, 8, 0x0100, a2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(107, 428, 32, 4, 4, 0x0003, 0x0006, -2, 8, 0x0100, a3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(108, 432, 32, 4, 4, 0x0004, 0x0006, -2, 8, 0x0100, a4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(109, 436, 32, 4, 4, 0x0005, 0x0006, -2, 8, 0x0100, a5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(110, 440, 32, 4, 4, 0x0006, 0x0006, -2, 8, 0x0100, a6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(111, 444, 32, 4, 4, 0x0007, 0x0006, -2, 8, 0x0100, a7,
+          0, 0, 0, 0, 0, 0)
+  XTREG(112, 448, 32, 4, 4, 0x0008, 0x0006, -2, 8, 0x0100, a8,
+          0, 0, 0, 0, 0, 0)
+  XTREG(113, 452, 32, 4, 4, 0x0009, 0x0006, -2, 8, 0x0100, a9,
+          0, 0, 0, 0, 0, 0)
+  XTREG(114, 456, 32, 4, 4, 0x000a, 0x0006, -2, 8, 0x0100, a10,
+          0, 0, 0, 0, 0, 0)
+  XTREG(115, 460, 32, 4, 4, 0x000b, 0x0006, -2, 8, 0x0100, a11,
+          0, 0, 0, 0, 0, 0)
+  XTREG(116, 464, 32, 4, 4, 0x000c, 0x0006, -2, 8, 0x0100, a12,
+          0, 0, 0, 0, 0, 0)
+  XTREG(117, 468, 32, 4, 4, 0x000d, 0x0006, -2, 8, 0x0100, a13,
+          0, 0, 0, 0, 0, 0)
+  XTREG(118, 472, 32, 4, 4, 0x000e, 0x0006, -2, 8, 0x0100, a14,
+          0, 0, 0, 0, 0, 0)
+  XTREG(119, 476, 32, 4, 4, 0x000f, 0x0006, -2, 8, 0x0100, a15,
+          0, 0, 0, 0, 0, 0)
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 00571e8..9ed3c09 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -107,6 +107,174 @@ static const XtensaConfig core_config[] = {
             [0] = 0,
         },
         .clock_freq_khz = 912000,
+    }, {
+        .name = "dc232b",
+        .options = -1 ^
+            (XTENSA_OPTION_BIT(XTENSA_OPTION_HW_ALIGNMENT) |
+             XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
+             XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION)),
+        .gdb_regmap = {
+            .num_regs = 120,
+            .num_core_regs = 52,
+            .reg = {
+#include "gdb-config-dc232b.c"
+            }
+        },
+        .nareg = 32,
+        .ndepc = 1,
+        .excm_level = 3,
+        .vecbase = 0xd0000000,
+        .exception_vector = {
+            [EXC_RESET] = 0xfe000000,
+            [EXC_WINDOW_OVERFLOW4] = 0xd0000000,
+            [EXC_WINDOW_UNDERFLOW4] = 0xd0000040,
+            [EXC_WINDOW_OVERFLOW8] = 0xd0000080,
+            [EXC_WINDOW_UNDERFLOW8] = 0xd00000c0,
+            [EXC_WINDOW_OVERFLOW12] = 0xd0000100,
+            [EXC_WINDOW_UNDERFLOW12] = 0xd0000140,
+            [EXC_KERNEL] = 0xd0000300,
+            [EXC_USER] = 0xd0000340,
+            [EXC_DOUBLE] = 0xd00003c0,
+        },
+        .ninterrupt = 22,
+        .nlevel = 6,
+        .interrupt_vector = {
+            0,
+            0,
+            0xd0000180,
+            0xd00001c0,
+            0xd0000200,
+            0xd0000240,
+            0xd0000280,
+            0xd00002c0,
+        },
+        .level_mask = {
+            [1] = 0x1f80ff,
+            [2] = 0x000100,
+            [3] = 0x200e00,
+            [4] = 0x001000,
+            [5] = 0x002000,
+            [6] = 0x000000,
+            [7] = 0x004000,
+        },
+        .inttype_mask = {
+            [INTTYPE_EDGE] = 0x3f8000,
+            [INTTYPE_NMI] = 0x4000,
+            [INTTYPE_SOFTWARE] = 0x880,
+        },
+        .interrupt = {
+            [0] = {
+                .level = 1,
+                .inttype = INTTYPE_LEVEL,
+            },
+            [1] = {
+                .level = 1,
+                .inttype = INTTYPE_LEVEL,
+            },
+            [2] = {
+                .level = 1,
+                .inttype = INTTYPE_LEVEL,
+            },
+            [3] = {
+                .level = 1,
+                .inttype = INTTYPE_LEVEL,
+            },
+            [4] = {
+                .level = 1,
+                .inttype = INTTYPE_LEVEL,
+            },
+            [5] = {
+                .level = 1,
+                .inttype = INTTYPE_LEVEL,
+            },
+            [6] = {
+                .level = 1,
+                .inttype = INTTYPE_TIMER,
+            },
+            [7] = {
+                .level = 1,
+                .inttype = INTTYPE_SOFTWARE,
+            },
+            [8] = {
+                .level = 2,
+                .inttype = INTTYPE_LEVEL,
+            },
+            [9] = {
+                .level = 3,
+                .inttype = INTTYPE_LEVEL,
+            },
+            [10] = {
+                .level = 3,
+                .inttype = INTTYPE_TIMER,
+            },
+            [11] = {
+                .level = 3,
+                .inttype = INTTYPE_SOFTWARE,
+            },
+            [12] = {
+                .level = 4,
+                .inttype = INTTYPE_LEVEL,
+            },
+            [13] = {
+                .level = 5,
+                .inttype = INTTYPE_TIMER,
+            },
+            [14] = {
+                .level = 7,
+                .inttype = INTTYPE_NMI,
+            },
+            [15] = {
+                .level = 1,
+                .inttype = INTTYPE_EDGE,
+            },
+            [16] = {
+                .level = 1,
+                .inttype = INTTYPE_EDGE,
+            },
+            [17] = {
+                .level = 1,
+                .inttype = INTTYPE_EDGE,
+            },
+            [18] = {
+                .level = 1,
+                .inttype = INTTYPE_EDGE,
+            },
+            [19] = {
+                .level = 1,
+                .inttype = INTTYPE_EDGE,
+            },
+            [20] = {
+                .level = 1,
+                .inttype = INTTYPE_EDGE,
+            },
+            [21] = {
+                .level = 3,
+                .inttype = INTTYPE_EDGE,
+            },
+        },
+        .nccompare = 3,
+        .timerint = {
+            [0] = 6,
+            [1] = 10,
+            [2] = 13,
+        },
+        .clock_freq_khz = 912000,
+        .itlb = {
+            .nways = 7,
+            .way_size = {
+                4, 4, 4, 4, 4, 2, 2,
+            },
+            .varway56 = false,
+            .nrefillentries = 16,
+        },
+        .dtlb = {
+            .nways = 10,
+            .way_size = {
+                4, 4, 4, 4, 4, 2, 2, 1, 1, 1,
+            },
+            .varway56 = false,
+            .nrefillentries = 16,
+        },
     },
 };
 
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 31/32] MAINTAINERS: add xtensa maintainer
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (29 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 30/32] target-xtensa: add dc232b core and board Max Filippov
@ 2011-09-01 20:45 ` Max Filippov
  2011-09-01 20:46 ` [Qemu-devel] [PATCH v4 32/32] target-xtensa: add regression testsuite Max Filippov
  2011-09-04 18:35 ` [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Blue Swirl
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Add myself as target-xtensa and DC232B maintainer.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 MAINTAINERS |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 508ea1e..72b2099 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -115,6 +115,12 @@ M: qemu-devel@nongnu.org
 S: Odd Fixes
 F: target-i386/
 
+Xtensa
+M: Max Filippov <jcmvbkbc@gmail.com>
+W: http://kkv.spb.su/doku.php?id=etc:users:jcmvbkbc:qemu-target-xtensa
+S: Maintained
+F: target-xtensa/
+
 Guest CPU Cores (KVM):
 ----------------------
 
@@ -335,6 +341,13 @@ M: Anthony Liguori <aliguori@us.ibm.com>
 S: Supported
 F: hw/pc.[ch] hw/pc_piix.c
 
+Xtensa Machines
+---------------
+DC232B
+M: Max Filippov <jcmvbkbc@gmail.com>
+S: Maintained
+F: hw/xtensa_dc232b.c
+
 Devices
 -------
 IDE
-- 
1.7.6

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

* [Qemu-devel] [PATCH v4 32/32] target-xtensa: add regression testsuite
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (30 preceding siblings ...)
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 31/32] MAINTAINERS: add xtensa maintainer Max Filippov
@ 2011-09-01 20:46 ` Max Filippov
  2011-09-04 18:35 ` [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Blue Swirl
  32 siblings, 0 replies; 47+ messages in thread
From: Max Filippov @ 2011-09-01 20:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 tests/xtensa/Makefile         |   72 +++++++++
 tests/xtensa/crt.S            |   24 +++
 tests/xtensa/linker.ld        |  113 +++++++++++++++
 tests/xtensa/macros.inc       |   68 +++++++++
 tests/xtensa/test_b.S         |  221 ++++++++++++++++++++++++++++
 tests/xtensa/test_bi.S        |  103 +++++++++++++
 tests/xtensa/test_bz.S        |   57 ++++++++
 tests/xtensa/test_clamps.S    |   42 ++++++
 tests/xtensa/test_fail.S      |    9 ++
 tests/xtensa/test_interrupt.S |  194 +++++++++++++++++++++++++
 tests/xtensa/test_loop.S      |   77 ++++++++++
 tests/xtensa/test_max.S       |   81 +++++++++++
 tests/xtensa/test_min.S       |   81 +++++++++++
 tests/xtensa/test_mmu.S       |  318 +++++++++++++++++++++++++++++++++++++++++
 tests/xtensa/test_mul16.S     |   83 +++++++++++
 tests/xtensa/test_mul32.S     |   20 +++
 tests/xtensa/test_nsa.S       |   59 ++++++++
 tests/xtensa/test_pipeline.S  |  157 ++++++++++++++++++++
 tests/xtensa/test_quo.S       |  147 +++++++++++++++++++
 tests/xtensa/test_rem.S       |  147 +++++++++++++++++++
 tests/xtensa/test_rst0.S      |  148 +++++++++++++++++++
 tests/xtensa/test_sar.S       |  111 ++++++++++++++
 tests/xtensa/test_sext.S      |   69 +++++++++
 tests/xtensa/test_shift.S     |  206 ++++++++++++++++++++++++++
 tests/xtensa/test_timer.S     |  115 +++++++++++++++
 tests/xtensa/test_windowed.S  |  302 ++++++++++++++++++++++++++++++++++++++
 tests/xtensa/vectors.S        |   39 +++++
 27 files changed, 3063 insertions(+), 0 deletions(-)
 create mode 100644 tests/xtensa/Makefile
 create mode 100644 tests/xtensa/crt.S
 create mode 100644 tests/xtensa/linker.ld
 create mode 100644 tests/xtensa/macros.inc
 create mode 100644 tests/xtensa/test_b.S
 create mode 100644 tests/xtensa/test_bi.S
 create mode 100644 tests/xtensa/test_bz.S
 create mode 100644 tests/xtensa/test_clamps.S
 create mode 100644 tests/xtensa/test_fail.S
 create mode 100644 tests/xtensa/test_interrupt.S
 create mode 100644 tests/xtensa/test_loop.S
 create mode 100644 tests/xtensa/test_max.S
 create mode 100644 tests/xtensa/test_min.S
 create mode 100644 tests/xtensa/test_mmu.S
 create mode 100644 tests/xtensa/test_mul16.S
 create mode 100644 tests/xtensa/test_mul32.S
 create mode 100644 tests/xtensa/test_nsa.S
 create mode 100644 tests/xtensa/test_pipeline.S
 create mode 100644 tests/xtensa/test_quo.S
 create mode 100644 tests/xtensa/test_rem.S
 create mode 100644 tests/xtensa/test_rst0.S
 create mode 100644 tests/xtensa/test_sar.S
 create mode 100644 tests/xtensa/test_sext.S
 create mode 100644 tests/xtensa/test_shift.S
 create mode 100644 tests/xtensa/test_timer.S
 create mode 100644 tests/xtensa/test_windowed.S
 create mode 100644 tests/xtensa/vectors.S

diff --git a/tests/xtensa/Makefile b/tests/xtensa/Makefile
new file mode 100644
index 0000000..14b97ca
--- /dev/null
+++ b/tests/xtensa/Makefile
@@ -0,0 +1,72 @@
+-include ../../config-host.mak
+
+CROSS=xtensa-dc232b-elf-
+
+ifndef XT
+SIM = qemu-system-xtensa
+SIMFLAGS = -M dc232b -nographic -semihosting $(EXTFLAGS) -kernel
+SIMDEBUG = -s -S
+else
+SIM = xt-run
+SIMFLAGS = --xtensa-core=DC_B_232L --exit_with_target_code $(EXTFLAGS)
+SIMDEBUG = --gdbserve=0
+endif
+
+CC      = $(CROSS)gcc
+AS      = $(CROSS)gcc -x assembler
+LD      = $(CROSS)ld
+
+LDFLAGS = -Tlinker.ld
+
+CRT        = crt.o vectors.o
+TESTCASES += test_bz.tst
+TESTCASES += test_bi.tst
+TESTCASES += test_b.tst
+TESTCASES += test_clamps.tst
+TESTCASES += test_fail.tst
+TESTCASES += test_interrupt.tst
+TESTCASES += test_loop.tst
+TESTCASES += test_max.tst
+TESTCASES += test_min.tst
+TESTCASES += test_mmu.tst
+TESTCASES += test_mul16.tst
+TESTCASES += test_mul32.tst
+TESTCASES += test_nsa.tst
+ifdef XT
+TESTCASES += test_pipeline.tst
+endif
+TESTCASES += test_quo.tst
+TESTCASES += test_rem.tst
+TESTCASES += test_rst0.tst
+TESTCASES += test_sar.tst
+TESTCASES += test_sext.tst
+TESTCASES += test_shift.tst
+TESTCASES += test_timer.tst
+TESTCASES += test_windowed.tst
+
+all: build
+
+%.o: $(SRC_PATH)/tests/xtensa/%.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
+%.o: $(SRC_PATH)/tests/xtensa/%.S
+	$(AS) $(ASFLAGS) -c $< -o $@
+
+%.tst: %.o macros.inc $(CRT) Makefile
+	$(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
+
+build: $(TESTCASES)
+
+check: $(addprefix run-, $(TESTCASES))
+
+run-%.tst: %.tst
+	$(SIM) $(SIMFLAGS) ./$<
+
+run-test_fail.tst: test_fail.tst
+	! $(SIM) $(SIMFLAGS) ./$<
+
+debug-%.tst: %.tst
+	$(SIM) $(SIMDEBUG) $(SIMFLAGS) ./$<
+
+clean:
+	$(RM) -fr $(TESTCASES) $(CRT)
diff --git a/tests/xtensa/crt.S b/tests/xtensa/crt.S
new file mode 100644
index 0000000..d9846ac
--- /dev/null
+++ b/tests/xtensa/crt.S
@@ -0,0 +1,24 @@
+.section .init
+    j       1f
+.section .init.text
+1:
+    movi    a2, _start
+    jx      a2
+
+.text
+.global _start
+_start:
+    movi    a2, 1
+    wsr     a2, windowstart
+    movi    a2, 0
+    wsr     a2, windowbase
+    movi    a1, _fstack
+    movi    a2, 0x4000f
+    wsr     a2, ps
+    isync
+
+    call0   main
+
+    mov     a3, a2
+    movi    a2, 1
+    simcall
diff --git a/tests/xtensa/linker.ld b/tests/xtensa/linker.ld
new file mode 100644
index 0000000..f618ee3
--- /dev/null
+++ b/tests/xtensa/linker.ld
@@ -0,0 +1,113 @@
+OUTPUT_FORMAT("elf32-xtensa-le")
+ENTRY(_start)
+
+__DYNAMIC = 0;
+
+MEMORY {
+	ram : ORIGIN = 0xd0000000, LENGTH = 0x08000000  /* 128M */
+	rom : ORIGIN = 0xfe000000, LENGTH = 0x00001000  /* 4k */
+}
+
+SECTIONS
+{
+    .init :
+    {
+        *(.init)
+		*(.init.*)
+    } > rom
+
+    .vector :
+    {
+    . = 0x00000000;
+        *(.vector.window_overflow_4)
+        *(.vector.window_overflow_4.*)
+    . = 0x00000040;
+        *(.vector.window_underflow_4)
+        *(.vector.window_underflow_4.*)
+    . = 0x00000080;
+        *(.vector.window_overflow_8)
+        *(.vector.window_overflow_8.*)
+    . = 0x000000c0;
+        *(.vector.window_underflow_8)
+        *(.vector.window_underflow_8.*)
+    . = 0x00000100;
+        *(.vector.window_overflow_12)
+        *(.vector.window_overflow_12.*)
+    . = 0x00000140;
+        *(.vector.window_underflow_12)
+        *(.vector.window_underflow_12.*)
+
+    . = 0x00000180;
+        *(.vector.level2)
+        *(.vector.level2.*)
+    . = 0x000001c0;
+        *(.vector.level3)
+        *(.vector.level3.*)
+    . = 0x00000200;
+        *(.vector.level4)
+        *(.vector.level4.*)
+    . = 0x00000240;
+        *(.vector.level5)
+        *(.vector.level5.*)
+    . = 0x00000280;
+        *(.vector.level6)
+        *(.vector.level6.*)
+    . = 0x000002c0;
+        *(.vector.level7)
+        *(.vector.level7.*)
+
+    . = 0x00000300;
+        *(.vector.kernel)
+        *(.vector.kernel.*)
+    . = 0x00000340;
+        *(.vector.user)
+        *(.vector.user.*)
+    . = 0x000003c0;
+        *(.vector.double)
+        *(.vector.double.*)
+    } > ram
+
+	.text :
+	{
+		_ftext = .;
+		*(.text .stub .text.* .gnu.linkonce.t.* .literal .literal.*)
+		_etext = .;
+	} > ram
+
+	.rodata :
+	{
+		. = ALIGN(4);
+		_frodata = .;
+		*(.rodata .rodata.* .gnu.linkonce.r.*)
+		*(.rodata1)
+		_erodata = .;
+	} > ram
+
+	.data :
+	{
+		. = ALIGN(4);
+		_fdata = .;
+		*(.data .data.* .gnu.linkonce.d.*)
+		*(.data1)
+		_gp = ALIGN(16);
+		*(.sdata .sdata.* .gnu.linkonce.s.*)
+		_edata = .;
+	} > ram
+
+	.bss :
+	{
+		. = ALIGN(4);
+		_fbss = .;
+		*(.dynsbss)
+		*(.sbss .sbss.* .gnu.linkonce.sb.*)
+		*(.scommon)
+		*(.dynbss)
+		*(.bss .bss.* .gnu.linkonce.b.*)
+		*(COMMON)
+		_ebss = .;
+		_end = .;
+	} > ram
+}
+
+PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4);
+
diff --git a/tests/xtensa/macros.inc b/tests/xtensa/macros.inc
new file mode 100644
index 0000000..2d4515e
--- /dev/null
+++ b/tests/xtensa/macros.inc
@@ -0,0 +1,68 @@
+.macro test_suite name
+.data
+status: .word result
+result: .space 20
+.text
+.global main
+.align 4
+main:
+.endm
+
+.macro reset_ps
+    movi    a2, 0x4000f
+    wsr     a2, ps
+    isync
+.endm
+
+.macro test_suite_end
+    reset_ps
+    movi    a0, status
+    l32i    a2, a0, 0
+    movi    a0, result
+    sub     a2, a2, a0
+    movi    a3, 0
+    loopnez a2, 1f
+    l8ui    a2, a0, 0
+    or      a3, a3, a2
+    addi    a0, a0, 1
+1:
+    exit
+.endm
+
+.macro test name
+.endm
+
+.macro test_end
+99:
+    reset_ps
+    movi    a2, status
+    l32i    a3, a2, 0
+    addi    a3, a3, 1
+    s32i    a3, a2, 0
+.endm
+
+.macro exit
+    movi    a2, 1
+    simcall
+.endm
+
+.macro test_fail
+    movi    a2, status
+    l32i    a2, a2, 0
+    movi    a3, 1
+    s8i     a3, a2, 0
+    j       99f
+.endm
+
+.macro assert cond, arg1, arg2
+    b\cond  \arg1, \arg2, 90f
+    test_fail
+90:
+    nop
+.endm
+
+.macro set_vector vector, addr
+    movi    a2, handler_\vector
+    movi    a3, \addr
+    s32i    a3, a2, 0
+.endm
diff --git a/tests/xtensa/test_b.S b/tests/xtensa/test_b.S
new file mode 100644
index 0000000..6cbe5f1
--- /dev/null
+++ b/tests/xtensa/test_b.S
@@ -0,0 +1,221 @@
+.include "macros.inc"
+
+test_suite b
+
+test bnone
+    movi    a2, 0xa5a5ff00
+    movi    a3, 0x5a5a00ff
+    bnone   a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0xa5a5ff01
+    bnone   a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test beq
+    movi    a2, 0
+    movi    a3, 0
+    beq     a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 1
+    beq     a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test blt
+    movi    a2, 6
+    movi    a3, 7
+    blt     a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0xffffffff
+    blt     a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 7
+    blt     a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bltu
+    movi    a2, 6
+    movi    a3, 7
+    bltu    a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 7
+    bltu    a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+    movi    a2, 0xffffffff
+    bltu    a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test ball
+    movi    a2, 0xa5a5ffa5
+    movi    a3, 0xa5a5ff00
+    ball    a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0xa5a5a5a5
+    ball    a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bbc
+    movi    a2, 0xfffffffd
+    movi    a3, 0xffffff01
+    bbc     a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 8
+    movi    a3, 0xffffff03
+    bbc     a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bbci
+    movi    a2, 0xfffdffff
+    bbci    a2, 17, 1f
+    test_fail
+1:
+    movi    a2, 0x00020000
+    bbci    a2, 17, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bany
+    movi    a2, 0xa5a5ff01
+    movi    a3, 0x5a5a00ff
+    bany    a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0xa5a5ff00
+    bany    a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bne
+    movi    a2, 1
+    movi    a3, 0
+    bne     a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0
+    bne     a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bge
+    movi    a2, 7
+    movi    a3, 7
+    bge     a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 6
+    bge     a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+    movi    a2, 0xffffffff
+    bge     a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bgeu
+    movi    a2, 7
+    movi    a3, 7
+    bgeu    a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0xffffffff
+    bgeu    a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 6
+    bgeu    a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bnall
+    movi    a2, 0xa5a5a5a5
+    movi    a3, 0xa5a5ff00
+    bnall   a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0xa5a5ffa5
+    bnall   a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bbs
+    movi    a2, 8
+    movi    a3, 0xffffff03
+    bbs     a2, a3, 1f
+    test_fail
+1:
+    movi    a2, 0xfffffffd
+    movi    a3, 0xffffff01
+    bbs     a2, a3, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bbsi
+    movi    a2, 0x00020000
+    bbsi    a2, 17, 1f
+    test_fail
+1:
+    movi    a2, 0xfffdffff
+    bbsi    a2, 17, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_bi.S b/tests/xtensa/test_bi.S
new file mode 100644
index 0000000..6a5f1df
--- /dev/null
+++ b/tests/xtensa/test_bi.S
@@ -0,0 +1,103 @@
+.include "macros.inc"
+
+test_suite bi
+
+test beqi
+    movi    a2, 7
+    beqi    a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 1
+    beqi    a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bnei
+    movi    a2, 1
+    bnei    a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 7
+    bnei    a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test blti
+    movi    a2, 6
+    blti    a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 0xffffffff
+    blti    a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 7
+    blti    a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bgei
+    movi    a2, 7
+    bgei    a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 6
+    bgei    a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+    movi    a2, 0xffffffff
+    bgei    a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bltui
+    movi    a2, 6
+    bltui   a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 7
+    bltui   a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+    movi    a2, 0xffffffff
+    bltui   a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bgeui
+    movi    a2, 7
+    bgeui   a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 0xffffffff
+    bgeui   a2, 7, 1f
+    test_fail
+1:
+    movi    a2, 6
+    bgeui   a2, 7, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_bz.S b/tests/xtensa/test_bz.S
new file mode 100644
index 0000000..f9ba6e2
--- /dev/null
+++ b/tests/xtensa/test_bz.S
@@ -0,0 +1,57 @@
+.include "macros.inc"
+
+test_suite bz
+
+test beqz
+    movi    a2, 0
+    _beqz   a2, 1f
+    test_fail
+1:
+    movi    a2, 1
+    _beqz   a2, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bnez
+    movi    a2, 1
+    _bnez   a2, 1f
+    test_fail
+1:
+    movi    a2, 0
+    _bnez   a2, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bltz
+    movi    a2, 0xffffffff
+    bltz    a2, 1f
+    test_fail
+1:
+    movi    a2, 0
+    bltz    a2, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test bgez
+    movi    a2, 0
+    bgez    a2, 1f
+    test_fail
+1:
+    movi    a2, 0xffffffff
+    bgez    a2, 1f
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_clamps.S b/tests/xtensa/test_clamps.S
new file mode 100644
index 0000000..c186cc9
--- /dev/null
+++ b/tests/xtensa/test_clamps.S
@@ -0,0 +1,42 @@
+.include "macros.inc"
+
+test_suite clamps
+
+test clamps
+    movi    a2, 0
+    movi    a3, 0
+    clamps  a4, a2, 7
+    assert  eq, a3, a4
+
+    movi    a2, 0x7f
+    movi    a3, 0x7f
+    clamps  a4, a2, 7
+    assert  eq, a3, a4
+
+    movi    a2, 0xffffff80
+    movi    a3, 0xffffff80
+    clamps  a4, a2, 7
+    assert  eq, a3, a4
+
+    movi    a2, 0x80
+    movi    a3, 0x7f
+    clamps  a2, a2, 7
+    assert  eq, a3, a2
+
+    movi    a2, 0xffffff7f
+    movi    a3, 0xffffff80
+    clamps  a2, a2, 7
+    assert  eq, a3, a2
+
+    movi    a2, 0x7fffffff
+    movi    a3, 0x7f
+    clamps  a2, a2, 7
+    assert  eq, a3, a2
+
+    movi    a2, 0x80000000
+    movi    a3, 0xffffff80
+    clamps  a2, a2, 7
+    assert  eq, a3, a2
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_fail.S b/tests/xtensa/test_fail.S
new file mode 100644
index 0000000..e8d1b42
--- /dev/null
+++ b/tests/xtensa/test_fail.S
@@ -0,0 +1,9 @@
+.include "macros.inc"
+
+test_suite fail
+
+test fail
+    test_fail
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_interrupt.S b/tests/xtensa/test_interrupt.S
new file mode 100644
index 0000000..68b3ee1
--- /dev/null
+++ b/tests/xtensa/test_interrupt.S
@@ -0,0 +1,194 @@
+.include "macros.inc"
+
+test_suite interrupt
+
+.macro clear_interrupts
+    movi    a2, 0
+    wsr     a2, intenable
+    wsr     a2, ccompare0
+    wsr     a2, ccompare1
+    wsr     a2, ccompare2
+    esync
+    rsr     a2, interrupt
+    wsr     a2, intclear
+
+    esync
+    rsr     a2, interrupt
+    assert  eqi, a2, 0
+.endm
+
+.macro check_l1
+    rsr     a2, ps
+    movi    a3, 0x1f        /* EXCM | INTMASK */
+    and     a2, a2, a3
+    assert  eqi, a2, 0x10   /* only EXCM is set for level-1 interrupt */
+    rsr     a2, exccause
+    assert  eqi, a2, 4
+.endm
+
+test rsil
+    clear_interrupts
+
+    rsr     a2, ps
+    rsil    a3, 7
+    rsr     a4, ps
+    assert  eq, a2, a3
+    movi    a2, 0xf
+    and     a2, a4, a2
+    assert  eqi, a2, 7
+    xor     a3, a3, a4
+    movi    a2, 0xfffffff0
+    and     a2, a3, a2
+    assert  eqi, a2, 0
+test_end
+
+test soft_disabled
+    set_vector kernel, 1f
+    clear_interrupts
+
+    movi    a2, 0x80
+    wsr     a2, intset
+    esync
+    rsr     a3, interrupt
+    assert  eq, a2, a3
+    wsr     a2, intclear
+    esync
+    rsr     a3, interrupt
+    assert  eqi, a3, 0
+    j       2f
+1:
+    test_fail
+2:
+test_end
+
+test soft_intenable
+    set_vector kernel, 1f
+    clear_interrupts
+
+    movi    a2, 0x80
+    wsr     a2, intset
+    esync
+    rsr     a3, interrupt
+    assert  eq, a2, a3
+    rsil    a3, 0
+    wsr     a2, intenable
+    esync
+    test_fail
+1:
+    check_l1
+test_end
+
+test soft_rsil
+    set_vector kernel, 1f
+    clear_interrupts
+
+    movi    a2, 0x80
+    wsr     a2, intset
+    esync
+    rsr     a3, interrupt
+    assert  eq, a2, a3
+    wsr     a2, intenable
+    rsil    a3, 0
+    esync
+    test_fail
+1:
+    check_l1
+test_end
+
+test soft_waiti
+    set_vector kernel, 1f
+    clear_interrupts
+
+    movi    a2, 0x80
+    wsr     a2, intset
+    esync
+    rsr     a3, interrupt
+    assert  eq, a2, a3
+    wsr     a2, intenable
+    waiti   0
+    test_fail
+1:
+    check_l1
+test_end
+
+test soft_user
+    set_vector kernel, 1f
+    set_vector user, 2f
+    clear_interrupts
+
+    movi    a2, 0x80
+    wsr     a2, intset
+    esync
+    rsr     a3, interrupt
+    assert  eq, a2, a3
+    wsr     a2, intenable
+
+    rsr     a2, ps
+    movi    a3, 0x20
+    or      a2, a2, a3
+    wsr     a2, ps
+    waiti   0
+1:
+    test_fail
+2:
+    check_l1
+test_end
+
+test soft_priority
+    set_vector kernel, 1f
+    set_vector level3, 2f
+    clear_interrupts
+
+    movi    a2, 0x880
+    wsr     a2, intenable
+    rsil    a3, 0
+    esync
+    wsr     a2, intset
+    esync
+1:
+    test_fail
+2:
+    rsr     a2, ps
+    movi    a3, 0x1f        /* EXCM | INTMASK */
+    and     a2, a2, a3
+    movi    a3, 0x13
+    assert  eq, a2, a3      /* EXCM and INTMASK are set
+                               for high-priority interrupt */
+test_end
+
+test eps_epc_rfi
+    set_vector level3, 3f
+    clear_interrupts
+    reset_ps
+
+    movi    a2, 0x880
+    wsr     a2, intenable
+    rsil    a3, 0
+    rsr     a3, ps
+    esync
+    wsr     a2, intset
+1:
+    esync
+2:
+    test_fail
+3:
+    rsr     a2, eps3
+    assert  eq, a2, a3
+    rsr     a2, epc3
+    movi    a3, 1b
+    assert  ge, a2, a3
+    movi    a3, 2b
+    assert  ge, a3, a2
+    movi    a2, 4f
+    wsr     a2, epc3
+    movi    a2, 0x40003
+    wsr     a2, eps3
+    rfi     3
+    test_fail
+4:
+    rsr     a2, ps
+    movi    a3, 0x40003
+    assert  eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_loop.S b/tests/xtensa/test_loop.S
new file mode 100644
index 0000000..a5ea933
--- /dev/null
+++ b/tests/xtensa/test_loop.S
@@ -0,0 +1,77 @@
+.include "macros.inc"
+
+test_suite loop
+
+test loop
+    movi    a2, 0
+    movi    a3, 5
+    loop    a3, 1f
+    addi    a2, a2, 1
+1:
+    assert  eqi, a2, 5
+test_end
+
+test loop0
+    movi    a2, 0
+    loop    a2, 1f
+    rsr     a2, lcount
+    assert  eqi, a2, -1
+    j       1f
+1:
+test_end
+
+test loop_jump
+    movi    a2, 0
+    movi    a3, 5
+    loop    a3, 1f
+    addi    a2, a2, 1
+    j       1f
+1:
+    assert  eqi, a2, 1
+test_end
+
+test loop_branch
+    movi    a2, 0
+    movi    a3, 5
+    loop    a3, 1f
+    addi    a2, a2, 1
+    beqi    a2, 3, 1f
+1:
+    assert  eqi, a2, 3
+test_end
+
+test loop_manual
+    movi    a2, 0
+    movi    a3, 5
+    movi    a4, 1f
+    movi    a5, 2f
+    wsr     a3, lcount
+    wsr     a4, lbeg
+    wsr     a5, lend
+    isync
+    j       1f
+.align 4
+1:
+    addi    a2, a2, 1
+2:
+    assert  eqi, a2, 6
+test_end
+
+test loop_excm
+    movi    a2, 0
+    movi    a3, 5
+    rsr     a4, ps
+    movi    a5, 0x10
+    or      a4, a4, a5
+    wsr     a4, ps
+    isync
+    loop    a3, 1f
+    addi    a2, a2, 1
+1:
+    xor     a4, a4, a5
+    isync
+    wsr     a4, ps
+    assert  eqi, a2, 1
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_max.S b/tests/xtensa/test_max.S
new file mode 100644
index 0000000..2534c9d
--- /dev/null
+++ b/tests/xtensa/test_max.S
@@ -0,0 +1,81 @@
+.include "macros.inc"
+
+test_suite max
+
+test max
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 1
+    max     a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 1
+    max     a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 1
+    max     a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 1
+    max     a3, a2, a3
+    assert  eq, a3, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 1
+    max     a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 1
+    max     a3, a2, a3
+    assert  eq, a3, a4
+test_end
+
+test maxu
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 0xffffffff
+    maxu    a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 0xffffffff
+    maxu    a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 0xffffffff
+    maxu    a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 0xffffffff
+    maxu    a3, a2, a3
+    assert  eq, a3, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 0xffffffff
+    maxu    a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 0xffffffff
+    maxu    a3, a2, a3
+    assert  eq, a3, a4
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_min.S b/tests/xtensa/test_min.S
new file mode 100644
index 0000000..6d9ddeb
--- /dev/null
+++ b/tests/xtensa/test_min.S
@@ -0,0 +1,81 @@
+.include "macros.inc"
+
+test_suite min
+
+test min
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 0xffffffff
+    min     a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 0xffffffff
+    min     a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 0xffffffff
+    min     a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 0xffffffff
+    min     a3, a2, a3
+    assert  eq, a3, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 0xffffffff
+    min     a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 0xffffffff
+    min     a3, a2, a3
+    assert  eq, a3, a4
+test_end
+
+test minu
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 1
+    minu    a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 1
+    minu    a5, a2, a3
+    assert  eq, a5, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 1
+    minu    a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 1
+    movi    a4, 1
+    minu    a3, a2, a3
+    assert  eq, a3, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 1
+    minu    a2, a2, a3
+    assert  eq, a2, a4
+
+    movi    a2, 1
+    movi    a3, 0xffffffff
+    movi    a4, 1
+    minu    a3, a2, a3
+    assert  eq, a3, a4
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_mmu.S b/tests/xtensa/test_mmu.S
new file mode 100644
index 0000000..52d5774
--- /dev/null
+++ b/tests/xtensa/test_mmu.S
@@ -0,0 +1,318 @@
+.include "macros.inc"
+
+test_suite mmu
+
+.purgem test
+
+.macro test name
+    movi    a2, 0x00000004
+    idtlb   a2
+    movi    a2, 0x00100004
+    idtlb   a2
+    movi    a2, 0x00200004
+    idtlb   a2
+    movi    a2, 0x00300004
+    idtlb   a2
+    movi    a2, 0x00000007
+    idtlb   a2
+.endm
+
+test tlb_group
+    movi    a2, 0x04000002 /* PPN */
+    movi    a3, 0x01200004 /* VPN */
+    wdtlb   a2, a3
+    witlb   a2, a3
+    movi    a3, 0x00200004
+    rdtlb0  a1, a3
+    ritlb0  a2, a3
+    movi    a3, 0x01000001
+    assert  eq, a1, a3
+    assert  eq, a2, a3
+    movi    a3, 0x00200004
+    rdtlb1  a1, a3
+    ritlb1  a2, a3
+    movi    a3, 0x04000002
+    assert  eq, a1, a3
+    assert  eq, a2, a3
+    movi    a3, 0x01234567
+    pdtlb   a1, a3
+    pitlb   a2, a3
+    movi    a3, 0x01234014
+    assert  eq, a1, a3
+    movi    a3, 0x0123400c
+    assert  eq, a2, a3
+    movi    a3, 0x00200004
+    idtlb   a3
+    iitlb   a3
+    movi    a3, 0x01234567
+    pdtlb   a1, a3
+    pitlb   a2, a3
+    movi    a3, 0x00000010
+    and     a1, a1, a3
+    assert  eqi, a1, 0
+    movi    a3, 0x00000008
+    and     a2, a2, a3
+    assert  eqi, a2, 0
+test_end
+
+test itlb_miss
+    set_vector kernel, 1f
+
+    movi    a3, 0x00100000
+    jx      a3
+    test_fail
+1:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+    rsr     a2, exccause
+    movi    a3, 16
+    assert  eq, a2, a3
+test_end
+
+test dtlb_miss
+    set_vector kernel, 1f
+
+    movi    a3, 0x00100000
+    l8ui    a2, a3, 0
+    test_fail
+1:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+    rsr     a2, exccause
+    movi    a3, 24
+    assert  eq, a2, a3
+test_end
+
+test itlb_multi_hit
+    set_vector kernel, 1f
+
+    movi    a2, 0x04000002 /* PPN */
+    movi    a3, 0xf0000004 /* VPN */
+    witlb   a2, a3
+    movi    a3, 0xf0000000
+    pitlb   a2, a3
+    test_fail
+1:
+    rsr     a2, exccause
+    movi    a3, 17
+    assert  eq, a2, a3
+test_end
+
+test dtlb_multi_hit
+    set_vector kernel, 1f
+
+    movi    a2, 0x04000002 /* PPN */
+    movi    a3, 0x01200004 /* VPN */
+    wdtlb   a2, a3
+    movi    a3, 0x01200007 /* VPN */
+    wdtlb   a2, a3
+    movi    a3, 0x01200000
+    pdtlb   a2, a3
+    test_fail
+1:
+    rsr     a2, exccause
+    movi    a3, 25
+    assert  eq, a2, a3
+test_end
+
+test inst_fetch_privilege
+    set_vector kernel, 3f
+
+    movi    a2, 0x4004f
+    wsr     a2, ps
+1:
+    isync
+    nop
+2:
+    test_fail
+3:
+    movi    a1, 1b
+    rsr     a2, excvaddr
+    rsr     a3, epc1
+    assert  ge, a2, a1
+    assert  ge, a3, a1
+    movi    a1, 2b
+    assert  lt, a2, a1
+    assert  lt, a3, a1
+    rsr     a2, exccause
+    movi    a3, 18
+    assert  eq, a2, a3
+    rsr     a2, ps
+    movi    a3, 0x4005f
+    assert  eq, a2, a3
+test_end
+
+test load_store_privilege
+    set_vector kernel, 2f
+
+    movi    a3, 10f
+    pitlb   a3, a3
+    ritlb1  a2, a3
+    movi    a1, 0x10
+    or      a2, a2, a1
+    movi    a1, 0x000ff000
+    and     a3, a3, a1
+    movi    a1, 4
+    or      a3, a3, a1
+    witlb   a2, a3
+    movi    a3, 10f
+    movi    a1, 0x000fffff
+    and     a1, a3, a1
+
+    movi    a2, 0x04000003 /* PPN */
+    movi    a3, 0x01200004 /* VPN */
+    wdtlb   a2, a3
+    movi    a3, 0x01200001
+    movi    a2, 0x4004f
+    jx      a1
+10:
+    wsr     a2, ps
+    isync
+1:
+    l8ui    a2, a3, 0
+    test_fail
+2:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+    rsr     a2, epc1
+    movi    a3, 1b
+    movi    a1, 0x000fffff
+    and     a3, a3, a1
+    assert  eq, a2, a3
+    rsr     a2, exccause
+    movi    a3, 26
+    assert  eq, a2, a3
+    rsr     a2, ps
+    movi    a3, 0x4005f
+    assert  eq, a2, a3
+test_end
+
+test cring_load_store_privilege
+    set_vector kernel, 0
+    set_vector double, 2f
+
+    movi    a2, 0x04000003 /* PPN */
+    movi    a3, 0x01200004 /* VPN */
+    wdtlb   a2, a3
+    movi    a3, 0x01200004
+    movi    a2, 0x4005f    /* ring 1 + excm => cring == 0 */
+    wsr     a2, ps
+    isync
+    l8ui    a2, a3, 0      /* cring used */
+1:
+    l32e    a2, a3, -4     /* ring used */
+    test_fail
+2:
+    rsr     a2, excvaddr
+    addi    a2, a2, 4
+    assert  eq, a2, a3
+    rsr     a2, depc
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, exccause
+    movi    a3, 26
+    assert  eq, a2, a3
+    rsr     a2, ps
+    movi    a3, 0x4005f
+    assert  eq, a2, a3
+test_end
+
+test inst_fetch_prohibited
+    set_vector kernel, 2f
+
+    movi    a3, 10f
+    pitlb   a3, a3
+    ritlb1  a2, a3
+    movi    a1, 0xfffff000
+    and     a2, a2, a1
+    movi    a1, 0x4
+    or      a2, a2, a1
+    movi    a1, 0x000ff000
+    and     a3, a3, a1
+    movi    a1, 4
+    or      a3, a3, a1
+    witlb   a2, a3
+    movi    a3, 10f
+    movi    a1, 0x000fffff
+    and     a1, a3, a1
+    jx      a1
+    .align  4
+10:
+    nop
+    test_fail
+2:
+    rsr     a2, excvaddr
+    assert  eq, a2, a1
+    rsr     a2, epc1
+    assert  eq, a2, a1
+    rsr     a2, exccause
+    movi    a3, 20
+    assert  eq, a2, a3
+test_end
+
+test load_prohibited
+    set_vector kernel, 2f
+
+    movi    a2, 0x0400000c /* PPN */
+    movi    a3, 0x01200004 /* VPN */
+    wdtlb   a2, a3
+    movi    a3, 0x01200002
+1:
+    l8ui    a2, a3, 0
+    test_fail
+2:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, exccause
+    movi    a3, 28
+    assert  eq, a2, a3
+test_end
+
+test store_prohibited
+    set_vector kernel, 2f
+
+    movi    a2, 0x04000001 /* PPN */
+    movi    a3, 0x01200004 /* VPN */
+    wdtlb   a2, a3
+    movi    a3, 0x01200003
+    l8ui    a2, a3, 0
+1:
+    s8i     a2, a3, 0
+    test_fail
+2:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, exccause
+    movi    a3, 29
+    assert  eq, a2, a3
+test_end
+
+test dtlb_autoload
+    set_vector kernel, 0
+
+    movi    a2, 0xd4000000
+    wsr     a2, ptevaddr
+    movi    a3, 0x00001013
+    s32i    a3, a2, 4
+    pdtlb   a2, a3
+    movi    a1, 0x10
+    and     a1, a1, a2
+    assert  eqi, a1, 0
+    l8ui    a1, a3, 0
+    pdtlb   a2, a3
+    movi    a1, 0xfffff010
+    and     a1, a1, a2
+    movi    a3, 0x00001010
+    assert  eq, a1, a3
+    movi    a1, 0xf
+    and     a1, a1, a2
+    assert  lti, a1, 4
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_mul16.S b/tests/xtensa/test_mul16.S
new file mode 100644
index 0000000..bf94376
--- /dev/null
+++ b/tests/xtensa/test_mul16.S
@@ -0,0 +1,83 @@
+.include "macros.inc"
+
+test_suite mul16
+
+test mul16u_pp
+    movi    a2, 0x137f5a5a
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x06e180a6
+    mul16u  a5, a2, a4
+    assert  eq, a5, a6
+    mul16u  a2, a2, a4
+    assert  eq, a2, a6
+    mul16u  a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test mul16u_np
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x0c9d6bdb
+    mul16u  a5, a2, a4
+    assert  eq, a5, a6
+    mul16u  a2, a2, a4
+    assert  eq, a2, a6
+    mul16u  a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test mul16u_nn
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5f731
+    movi    a6, 0x9ff1e795
+    mul16u  a5, a2, a4
+    assert  eq, a5, a6
+    mul16u  a2, a2, a4
+    assert  eq, a2, a6
+    mul16u  a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test mul16s_pp
+    movi    a2, 0x137f5a5a
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x06e180a6
+    mul16s  a5, a2, a4
+    assert  eq, a5, a6
+    mul16s  a2, a2, a4
+    assert  eq, a2, a6
+    mul16s  a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test mul16s_np
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xf91e6bdb
+    mul16s  a5, a2, a4
+    assert  eq, a5, a6
+    mul16s  a2, a2, a4
+    assert  eq, a2, a6
+    mul16s  a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test mul16s_nn
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5f731
+    movi    a6, 0x031be795
+    mul16s  a5, a2, a4
+    assert  eq, a5, a6
+    mul16s  a2, a2, a4
+    assert  eq, a2, a6
+    mul16s  a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_mul32.S b/tests/xtensa/test_mul32.S
new file mode 100644
index 0000000..fdaf573
--- /dev/null
+++ b/tests/xtensa/test_mul32.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+test_suite mul32
+
+test mull
+    movi    a2, 0x137f5a5a
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x5de480a6
+    mull    a5, a2, a4
+    assert  eq, a5, a6
+    mull    a2, a2, a4
+    assert  eq, a2, a6
+    mull    a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+/* unfortunately dc232b doesn't have muluh/mulsh*/
+
+test_suite_end
diff --git a/tests/xtensa/test_nsa.S b/tests/xtensa/test_nsa.S
new file mode 100644
index 0000000..a5fe5de
--- /dev/null
+++ b/tests/xtensa/test_nsa.S
@@ -0,0 +1,59 @@
+.include "macros.inc"
+
+test_suite nsa
+
+test nsa
+    movi    a2, 0
+    movi    a3, 31
+    nsa     a4, a2
+    assert  eq, a3, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 31
+    nsa     a4, a2
+    assert  eq, a3, a4
+
+    movi    a2, 1
+    movi    a3, 30
+    nsa     a2, a2
+    assert  eq, a3, a2
+
+    movi    a2, 0xfffffffe
+    movi    a3, 30
+    nsa     a2, a2
+    assert  eq, a3, a2
+
+    movi    a2, 0x5a5a5a5a
+    movi    a3, 0
+    nsa     a4, a2
+    assert  eq, a3, a4
+
+    movi    a2, 0xa5a5a5a5
+    movi    a3, 0
+    nsa     a4, a2
+    assert  eq, a3, a4
+test_end
+
+test nsau
+    movi    a2, 0
+    movi    a3, 32
+    nsau    a4, a2
+    assert  eq, a3, a4
+
+    movi    a2, 0xffffffff
+    movi    a3, 0
+    nsau    a4, a2
+    assert  eq, a3, a4
+
+    movi    a2, 1
+    movi    a3, 31
+    nsau    a2, a2
+    assert  eq, a3, a2
+
+    movi    a2, 0x5a5a5a5a
+    movi    a3, 1
+    nsau    a2, a2
+    assert  eq, a3, a2
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_pipeline.S b/tests/xtensa/test_pipeline.S
new file mode 100644
index 0000000..6be6085
--- /dev/null
+++ b/tests/xtensa/test_pipeline.S
@@ -0,0 +1,157 @@
+.include "macros.inc"
+
+.purgem test
+.macro test name
+    movi    a2, 1f
+    movi    a3, 99f
+0:
+    ipf     a2, 0
+    ipf     a2, 4
+    ipf     a2, 8
+    ipf     a2, 12
+    addi    a2, a2, 16
+    blt     a2, a3, 0b
+    j       1f
+    .align 4
+1:
+.endm
+
+test_suite pipeline
+
+test register_no_stall
+    rsr     a3, ccount
+    add     a5, a6, a6
+    add     a6, a5, a5
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 3
+test_end
+
+test register_stall
+    l32i    a5, a1, 0   /* data cache preload */
+    nop
+    rsr     a3, ccount
+    l32i    a5, a1, 0
+    add     a6, a5, a5  /* M-to-E interlock */
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 4
+test_end
+
+test j0_stall
+    rsr     a3, ccount
+    j       1f          /* E + 2-cycle penalty */
+1:
+    rsr     a4, ccount  /* E */
+    sub     a3, a4, a3
+    assert  eqi, a3, 4
+test_end
+
+test j1_stall
+    rsr     a3, ccount
+    j       1f
+    nop
+1:
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 4
+test_end
+
+test j5_stall
+    rsr     a3, ccount
+    j       1f
+    nop
+    nop
+    nop
+    nop
+    nop
+1:
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 4
+test_end
+
+test b_no_stall
+    movi    a5, 1
+    rsr     a3, ccount
+    beqi    a5, 2, 1f
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 2
+1:
+test_end
+
+test b1_stall
+    movi    a5, 1
+    rsr     a3, ccount
+    beqi    a5, 1, 1f
+    nop
+1:
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 4
+test_end
+
+test b5_stall
+    movi    a5, 1
+    rsr     a3, ccount
+    beqi    a5, 1, 1f
+    nop
+    nop
+    nop
+    nop
+    nop
+1:
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 4
+test_end
+
+/* PS *SYNC */
+
+test ps_dsync
+    rsr     a5, ps
+    isync
+    rsr     a3, ccount
+    wsr     a5, ps
+    dsync
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 5
+test_end
+
+test ps_esync
+    rsr     a5, ps
+    isync
+    rsr     a3, ccount
+    wsr     a5, ps
+    esync
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 5
+test_end
+
+test ps_rsync
+    rsr     a5, ps
+    isync
+    rsr     a3, ccount
+    wsr     a5, ps
+    rsync
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 5
+test_end
+
+test ps_isync
+    rsr     a5, ps
+    isync
+    rsr     a3, ccount
+    wsr     a5, ps
+    isync
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    movi    a4, 9
+    assert  eq, a3, a4
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_quo.S b/tests/xtensa/test_quo.S
new file mode 100644
index 0000000..12debf1
--- /dev/null
+++ b/tests/xtensa/test_quo.S
@@ -0,0 +1,147 @@
+.include "macros.inc"
+
+test_suite quo
+
+test quou_pp
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0x4
+    quou    a5, a2, a4
+    assert  eq, a5, a6
+    quou    a2, a2, a4
+    assert  eq, a2, a6
+    quou    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quou_np
+    movi    a2, 0xa5a5137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0x8
+    quou    a5, a2, a4
+    assert  eq, a5, a6
+    quou    a2, a2, a4
+    assert  eq, a2, a6
+    quou    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quou_pn
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0xf7315a5a
+    movi    a6, 0
+    quou    a5, a2, a4
+    assert  eq, a5, a6
+    quou    a2, a2, a4
+    assert  eq, a2, a6
+    quou    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quou_nn
+    movi    a2, 0xf7315a5a
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x1
+    quou    a5, a2, a4
+    assert  eq, a5, a6
+    quou    a2, a2, a4
+    assert  eq, a2, a6
+    quou    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quou_exc
+    set_vector kernel, 2f
+    movi    a2, 0xf7315a5a
+    movi    a4, 0x00000000
+1:
+    quou    a5, a2, a4
+    test_fail
+2:
+    rsr     a2, exccause
+    assert  eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+test_end
+
+test quos_pp
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0x4
+    quos    a5, a2, a4
+    assert  eq, a5, a6
+    quos    a2, a2, a4
+    assert  eq, a2, a6
+    quos    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quos_np
+    movi    a2, 0xa5a5137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0xfffffffc
+    quos    a5, a2, a4
+    assert  eq, a5, a6
+    quos    a2, a2, a4
+    assert  eq, a2, a6
+    quos    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quos_pn
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0xf7315a5a
+    movi    a6, 0xfffffff6
+    quos    a5, a2, a4
+    assert  eq, a5, a6
+    quos    a2, a2, a4
+    assert  eq, a2, a6
+    quos    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quos_nn
+    movi    a2, 0xf7315a5a
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0
+    quos    a5, a2, a4
+    assert  eq, a5, a6
+    quos    a2, a2, a4
+    assert  eq, a2, a6
+    quos    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test quos_over
+    movi    a2, 0x80000000
+    movi    a4, 0xffffffff
+    movi    a6, 0x80000000
+    quos    a5, a2, a4
+    assert  eq, a5, a6
+test_end
+
+test quos_exc
+    set_vector kernel, 2f
+    movi    a2, 0xf7315a5a
+    movi    a4, 0x00000000
+1:
+    quos    a5, a2, a4
+    test_fail
+2:
+    rsr     a2, exccause
+    assert  eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_rem.S b/tests/xtensa/test_rem.S
new file mode 100644
index 0000000..bb0d5fe
--- /dev/null
+++ b/tests/xtensa/test_rem.S
@@ -0,0 +1,147 @@
+.include "macros.inc"
+
+test_suite rem
+
+test remu_pp
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0x0c5caa17
+    remu    a5, a2, a4
+    assert  eq, a5, a6
+    remu    a2, a2, a4
+    assert  eq, a2, a6
+    remu    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test remu_np
+    movi    a2, 0xa5a5137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0x9aa40af
+    remu    a5, a2, a4
+    assert  eq, a5, a6
+    remu    a2, a2, a4
+    assert  eq, a2, a6
+    remu    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test remu_pn
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0xf7315a5a
+    movi    a6, 0x5a5a137f
+    remu    a5, a2, a4
+    assert  eq, a5, a6
+    remu    a2, a2, a4
+    assert  eq, a2, a6
+    remu    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test remu_nn
+    movi    a2, 0xf7315a5a
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x518c46db
+    remu    a5, a2, a4
+    assert  eq, a5, a6
+    remu    a2, a2, a4
+    assert  eq, a2, a6
+    remu    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test remu_exc
+    set_vector kernel, 2f
+    movi    a2, 0xf7315a5a
+    movi    a4, 0x00000000
+1:
+    remu    a5, a2, a4
+    test_fail
+2:
+    rsr     a2, exccause
+    assert  eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+test_end
+
+test rems_pp
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0x0c5caa17
+    rems    a5, a2, a4
+    assert  eq, a5, a6
+    rems    a2, a2, a4
+    assert  eq, a2, a6
+    rems    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test rems_np
+    movi    a2, 0xa5a5137f
+    mov     a3, a2
+    movi    a4, 0x137f5a5a
+    movi    a6, 0xf3a27ce7
+    rems    a5, a2, a4
+    assert  eq, a5, a6
+    rems    a2, a2, a4
+    assert  eq, a2, a6
+    rems    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test rems_pn
+    movi    a2, 0x5a5a137f
+    mov     a3, a2
+    movi    a4, 0xf7315a5a
+    movi    a6, 0x02479b03
+    rems    a5, a2, a4
+    assert  eq, a5, a6
+    rems    a2, a2, a4
+    assert  eq, a2, a6
+    rems    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test rems_nn
+    movi    a2, 0xf7315a5a
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xf7315a5a
+    rems    a5, a2, a4
+    assert  eq, a5, a6
+    rems    a2, a2, a4
+    assert  eq, a2, a6
+    rems    a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test rems_over
+    movi    a2, 0x80000000
+    movi    a4, 0xffffffff
+    movi    a6, 0
+    rems    a5, a2, a4
+    assert  eq, a5, a6
+test_end
+
+test rems_exc
+    set_vector kernel, 2f
+    movi    a2, 0xf7315a5a
+    movi    a4, 0x00000000
+1:
+    rems    a5, a2, a4
+    test_fail
+2:
+    rsr     a2, exccause
+    assert  eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_rst0.S b/tests/xtensa/test_rst0.S
new file mode 100644
index 0000000..3eda565
--- /dev/null
+++ b/tests/xtensa/test_rst0.S
@@ -0,0 +1,148 @@
+.include "macros.inc"
+
+test_suite rst0
+
+test and
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x01250125
+    and     a5, a2, a4
+    assert  eq, a5, a6
+    and     a2, a2, a4
+    assert  eq, a2, a6
+    and     a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test or
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xb7ffb7ff
+    or      a5, a2, a4
+    assert  eq, a5, a6
+    or      a2, a2, a4
+    assert  eq, a2, a6
+    or      a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test xor
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xb6dab6da
+    xor     a5, a2, a4
+    assert  eq, a5, a6
+    xor     a2, a2, a4
+    assert  eq, a2, a6
+    xor     a3, a4, a3
+    assert  eq, a3, a6
+test_end
+
+test add
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xb924b924
+    add     a5, a2, a4
+    assert  eq, a5, a6
+    add     a2, a2, a4
+    assert  eq, a2, a6
+    add     a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test addx2
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xcca45ec9
+    addx2   a5, a2, a4
+    assert  eq, a5, a6
+    addx2   a2, a2, a4
+    assert  eq, a2, a6
+    addx2   a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test addx4
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xf3a3aa13
+    addx4   a5, a2, a4
+    assert  eq, a5, a6
+    addx4   a2, a2, a4
+    assert  eq, a2, a6
+    addx4   a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test addx8
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x41a240a7
+    addx8   a5, a2, a4
+    assert  eq, a5, a6
+    addx8   a2, a2, a4
+    assert  eq, a2, a6
+    addx8   a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test sub
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x6dda9226
+    sub     a5, a2, a4
+    assert  eq, a5, a6
+    sub     a2, a2, a4
+    assert  eq, a2, a6
+    sub     a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test subx2
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0x815a37cb
+    subx2   a5, a2, a4
+    assert  eq, a5, a6
+    subx2   a2, a2, a4
+    assert  eq, a2, a6
+    subx2   a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test subx4
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xa8598315
+    subx4   a5, a2, a4
+    assert  eq, a5, a6
+    subx4   a2, a2, a4
+    assert  eq, a2, a6
+    subx4   a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test subx8
+    movi    a2, 0x137fa5a5
+    mov     a3, a2
+    movi    a4, 0xa5a5137f
+    movi    a6, 0xf65819a9
+    subx8   a5, a2, a4
+    assert  eq, a5, a6
+    subx8   a2, a2, a4
+    assert  eq, a2, a6
+    subx8   a4, a3, a4
+    assert  eq, a4, a6
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_sar.S b/tests/xtensa/test_sar.S
new file mode 100644
index 0000000..40c649f
--- /dev/null
+++ b/tests/xtensa/test_sar.S
@@ -0,0 +1,111 @@
+.include "macros.inc"
+
+test_suite sar
+
+.macro test_sar prefix, imm
+    \prefix\()_set \imm
+    \prefix\()_ver \imm
+.endm
+
+.macro tests_sar prefix
+    test_sar \prefix, 0
+    test_sar \prefix, 1
+    test_sar \prefix, 2
+    test_sar \prefix, 3
+    test_sar \prefix, 0x1f
+    test_sar \prefix, 0x20
+    test_sar \prefix, 0x3f
+    test_sar \prefix, 0x40
+    test_sar \prefix, 0xfffffffe
+.endm
+
+.macro sar_set imm
+    movi    a2, \imm
+    wsr     a2, sar
+.endm
+
+.macro sar_ver imm
+    rsr     a3, sar
+    movi    a2, \imm & 0x3f
+    assert  eq, a2, a3
+.endm
+
+test sar
+    tests_sar sar
+test_end
+
+.macro ssr_set imm
+    movi    a2, \imm
+    ssr     a2
+.endm
+
+.macro ssr_ver imm
+    rsr     a3, sar
+    movi    a2, \imm & 0x1f
+    assert  eq, a2, a3
+.endm
+
+test ssr
+    tests_sar ssr
+test_end
+
+.macro ssl_set imm
+    movi    a2, \imm
+    ssl     a2
+.endm
+
+.macro ssl_ver imm
+    rsr     a3, sar
+    movi    a2, 32 - (\imm & 0x1f)
+    assert  eq, a2, a3
+.endm
+
+test ssl
+    tests_sar ssl
+test_end
+
+.macro ssa8l_set imm
+    movi    a2, \imm
+    ssa8l   a2
+.endm
+
+.macro ssa8l_ver imm
+    rsr     a3, sar
+    movi    a2, (\imm & 0x3) << 3
+    assert  eq, a2, a3
+.endm
+
+test ssa8l
+    tests_sar ssa8l
+test_end
+
+.macro ssa8b_set imm
+    movi    a2, \imm
+    ssa8b   a2
+.endm
+
+.macro ssa8b_ver imm
+    rsr     a3, sar
+    movi    a2, 32 - ((\imm & 0x3) << 3)
+    assert  eq, a2, a3
+.endm
+
+test ssa8b
+    tests_sar ssa8b
+test_end
+
+.macro ssai_set imm
+    ssai    \imm & 0x1f
+.endm
+
+.macro ssai_ver imm
+    rsr     a3, sar
+    movi    a2, \imm & 0x1f
+    assert  eq, a2, a3
+.endm
+
+test ssai
+    tests_sar ssai
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_sext.S b/tests/xtensa/test_sext.S
new file mode 100644
index 0000000..04dc650
--- /dev/null
+++ b/tests/xtensa/test_sext.S
@@ -0,0 +1,69 @@
+.include "macros.inc"
+
+test_suite sext
+
+test sext
+    movi    a2, 0xffffff5a
+    movi    a3, 0x0000005a
+    sext    a4, a2, 7
+    assert  eq, a3, a4
+
+    movi    a2, 0x000000a5
+    movi    a3, 0xffffffa5
+    sext    a4, a2, 7
+    assert  eq, a3, a4
+
+    movi    a2, 0xfffffaa5
+    movi    a3, 0x000000a5
+    sext    a4, a2, 8
+    assert  eq, a3, a4
+
+    movi    a2, 0x0000055a
+    movi    a3, 0xffffff5a
+    sext    a4, a2, 8
+    assert  eq, a3, a4
+
+    movi    a2, 0xffff5a5a
+    movi    a3, 0x00005a5a
+    sext    a4, a2, 15
+    assert  eq, a3, a4
+
+    movi    a2, 0x0000a5a5
+    movi    a3, 0xffffa5a5
+    sext    a4, a2, 15
+    assert  eq, a3, a4
+
+    movi    a2, 0x00055a5a
+    movi    a3, 0xffff5a5a
+    sext    a4, a2, 16
+    assert  eq, a3, a4
+
+    movi    a2, 0x000aa5a5
+    movi    a3, 0x0000a5a5
+    sext    a4, a2, 16
+    assert  eq, a3, a4
+
+    movi    a2, 0x005a5a5a
+    movi    a3, 0xffda5a5a
+    sext    a4, a2, 22
+    assert  eq, a3, a4
+
+    movi    a2, 0xffa5a5a5
+    movi    a3, 0x0025a5a5
+    sext    a4, a2, 22
+    assert  eq, a3, a4
+test_end
+
+test sext_same_rs
+    movi    a2, 0xffffff5a
+    movi    a3, 0x0000005a
+    sext    a2, a2, 7
+    assert  eq, a3, a2
+
+    movi    a2, 0x000000a5
+    movi    a3, 0xffffffa5
+    sext    a2, a2, 7
+    assert  eq, a3, a2
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_shift.S b/tests/xtensa/test_shift.S
new file mode 100644
index 0000000..a8e4364
--- /dev/null
+++ b/tests/xtensa/test_shift.S
@@ -0,0 +1,206 @@
+.include "macros.inc"
+
+test_suite shift
+
+.macro test_shift prefix, dst, src, v, imm
+    \prefix\()_set \dst, \src, \v, \imm
+    \prefix\()_ver \dst, \v, \imm
+.endm
+
+.macro test_shift_sd prefix, v, imm
+    test_shift \prefix, a3, a2, \v, \imm
+    test_shift \prefix, a2, a2, \v, \imm
+.endm
+
+.macro tests_imm_shift prefix, v
+    test_shift_sd \prefix, \v, 1
+    test_shift_sd \prefix, \v, 2
+    test_shift_sd \prefix, \v, 7
+    test_shift_sd \prefix, \v, 8
+    test_shift_sd \prefix, \v, 15
+    test_shift_sd \prefix, \v, 16
+    test_shift_sd \prefix, \v, 31
+.endm
+
+.macro tests_shift prefix, v
+    test_shift_sd \prefix, \v, 0
+    tests_imm_shift \prefix, \v
+    test_shift_sd \prefix, \v, 32
+.endm
+
+
+.macro slli_set dst, src, v, imm
+    movi    \src, \v
+    slli    \dst, \src, \imm
+.endm
+
+.macro slli_ver dst, v, imm
+    mov     a2, \dst
+    movi    a3, ((\v) << (\imm)) & 0xffffffff
+    assert  eq, a2, a3
+.endm
+
+test slli
+    tests_imm_shift slli, 0xa3c51249
+test_end
+
+
+.macro srai_set dst, src, v, imm
+    movi    \src, \v
+    srai    \dst, \src, \imm
+.endm
+
+.macro srai_ver dst, v, imm
+    mov     a2, \dst
+    .if (\imm)
+    movi    a3, (((\v) >> (\imm)) & 0xffffffff) | \
+                ~((((\v) & 0x80000000) >> ((\imm) - 1)) - 1)
+    .else
+    movi    a3, \v
+    .endif
+    assert  eq, a2, a3
+.endm
+
+test srai
+    tests_imm_shift srai, 0x49a3c512
+    tests_imm_shift srai, 0xa3c51249
+test_end
+
+
+.macro srli_set dst, src, v, imm
+    movi    \src, \v
+    srli    \dst, \src, \imm
+.endm
+
+.macro srli_ver dst, v, imm
+    mov     a2, \dst
+    movi    a3, (((\v) >> (\imm)) & 0xffffffff)
+    assert  eq, a2, a3
+.endm
+
+test srli
+    tests_imm_shift srli, 0x49a3c512
+    tests_imm_shift srli, 0xa3c51249
+test_end
+
+
+.macro sll_set dst, src, v, imm
+    movi    a2, \imm
+    ssl     a2
+    movi    \src, \v
+    sll     \dst, \src
+.endm
+
+.macro sll_sar_set dst, src, v, imm
+    movi    a2, 32 - \imm
+    wsr     a2, sar
+    movi    \src, \v
+    sll     \dst, \src
+.endm
+
+.macro sll_ver dst, v, imm
+    slli_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro sll_sar_ver dst, v, imm
+    slli_ver \dst, \v, \imm
+.endm
+
+test sll
+    tests_shift sll, 0xa3c51249
+    tests_shift sll_sar, 0xa3c51249
+test_end
+
+
+.macro srl_set dst, src, v, imm
+    movi    a2, \imm
+    ssr     a2
+    movi    \src, \v
+    srl     \dst, \src
+.endm
+
+.macro srl_sar_set dst, src, v, imm
+    movi    a2, \imm
+    wsr     a2, sar
+    movi    \src, \v
+    srl     \dst, \src
+.endm
+
+.macro srl_ver dst, v, imm
+    srli_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro srl_sar_ver dst, v, imm
+    srli_ver \dst, \v, \imm
+.endm
+
+test srl
+    tests_shift srl, 0xa3c51249
+    tests_shift srl_sar, 0xa3c51249
+    tests_shift srl, 0x49a3c512
+    tests_shift srl_sar, 0x49a3c512
+test_end
+
+
+.macro sra_set dst, src, v, imm
+    movi    a2, \imm
+    ssr     a2
+    movi    \src, \v
+    sra     \dst, \src
+.endm
+
+.macro sra_sar_set dst, src, v, imm
+    movi    a2, \imm
+    wsr     a2, sar
+    movi    \src, \v
+    sra     \dst, \src
+.endm
+
+.macro sra_ver dst, v, imm
+    srai_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro sra_sar_ver dst, v, imm
+    srai_ver \dst, \v, \imm
+.endm
+
+test sra
+    tests_shift sra, 0xa3c51249
+    tests_shift sra_sar, 0xa3c51249
+    tests_shift sra, 0x49a3c512
+    tests_shift sra_sar, 0x49a3c512
+test_end
+
+
+.macro src_set dst, src, v, imm
+    movi    a2, \imm
+    ssr     a2
+    movi    \src, (\v) & 0xffffffff
+    movi    a4, (\v) >> 32
+    src     \dst, a4, \src
+.endm
+
+.macro src_sar_set dst, src, v, imm
+    movi    a2, \imm
+    wsr     a2, sar
+    movi    \src, (\v) & 0xffffffff
+    movi    a4, (\v) >> 32
+    src     \dst, a4, \src
+.endm
+
+.macro src_ver dst, v, imm
+    src_sar_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro src_sar_ver dst, v, imm
+    mov     a2, \dst
+    movi    a3, ((\v) >> (\imm)) & 0xffffffff
+    assert  eq, a2, a3
+.endm
+
+test src
+    tests_shift src, 0xa3c51249215c3a94
+    tests_shift src_sar, 0xa3c51249215c3a94
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_timer.S b/tests/xtensa/test_timer.S
new file mode 100644
index 0000000..ede6395
--- /dev/null
+++ b/tests/xtensa/test_timer.S
@@ -0,0 +1,115 @@
+.include "macros.inc"
+
+test_suite timer
+
+test ccount
+    rsr     a3, ccount
+    rsr     a4, ccount
+    sub     a3, a4, a3
+    assert  eqi, a3, 1
+test_end
+
+test ccompare
+    movi    a2, 0
+    wsr     a2, intenable
+    rsr     a2, interrupt
+    wsr     a2, intclear
+    wsr     a2, ccompare1
+    wsr     a2, ccompare2
+
+    movi    a3, 20
+    rsr     a2, ccount
+    addi    a2, a2, 20
+    wsr     a2, ccompare0
+    rsr     a2, interrupt
+    assert  eqi, a2, 0
+    loop    a3, 1f
+    rsr     a3, interrupt
+    bnez    a3, 2f
+1:
+    test_fail
+2:
+test_end
+
+test ccompare0_interrupt
+    set_vector kernel, 2f
+    movi    a2, 0
+    wsr     a2, intenable
+    rsr     a2, interrupt
+    wsr     a2, intclear
+    wsr     a2, ccompare1
+    wsr     a2, ccompare2
+
+    movi    a3, 20
+    rsr     a2, ccount
+    addi    a2, a2, 20
+    wsr     a2, ccompare0
+    rsync
+    rsr     a2, interrupt
+    assert  eqi, a2, 0
+
+    movi    a2, 0x40
+    wsr     a2, intenable
+    rsil    a2, 0
+    loop    a3, 1f
+    nop
+1:
+    test_fail
+2:
+    rsr     a2, exccause
+    assert  eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
+test_end
+
+test ccompare1_interrupt
+    set_vector level3, 2f
+    movi    a2, 0
+    wsr     a2, intenable
+    rsr     a2, interrupt
+    wsr     a2, intclear
+    wsr     a2, ccompare0
+    wsr     a2, ccompare2
+
+    movi    a3, 20
+    rsr     a2, ccount
+    addi    a2, a2, 20
+    wsr     a2, ccompare1
+    rsync
+    rsr     a2, interrupt
+    assert  eqi, a2, 0
+    movi    a2, 0x400
+    wsr     a2, intenable
+    rsil    a2, 2
+    loop    a3, 1f
+    nop
+1:
+    test_fail
+2:
+test_end
+
+test ccompare2_interrupt
+    set_vector level5, 2f
+    movi    a2, 0
+    wsr     a2, intenable
+    rsr     a2, interrupt
+    wsr     a2, intclear
+    wsr     a2, ccompare0
+    wsr     a2, ccompare1
+
+    movi    a3, 20
+    rsr     a2, ccount
+    addi    a2, a2, 20
+    wsr     a2, ccompare2
+    rsync
+    rsr     a2, interrupt
+    assert  eqi, a2, 0
+    movi    a2, 0x2000
+    wsr     a2, intenable
+    rsil    a2, 4
+    loop    a3, 1f
+    nop
+1:
+    test_fail
+2:
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/test_windowed.S b/tests/xtensa/test_windowed.S
new file mode 100644
index 0000000..cb2d39e
--- /dev/null
+++ b/tests/xtensa/test_windowed.S
@@ -0,0 +1,302 @@
+.include "macros.inc"
+
+test_suite windowed
+
+.altmacro
+
+.macro reset_window start
+    movi    a2, 0xff
+    wsr     a2, windowstart
+    rsync
+    movi    a2, 0
+    wsr     a2, windowbase
+    rsync
+    movi    a2, \start
+    wsr     a2, windowstart
+    rsync
+.endm
+
+.macro overflow_test shift, window, probe_ok, probe_ex
+    set_vector window_overflow_4, 0
+    set_vector window_overflow_8, 0
+    set_vector window_overflow_12, 0
+
+    movi    a2, 1 | (((1 << ((\window) / 4)) | 1) << ((\shift) / 4))
+    wsr     a2, windowstart
+    reset_ps
+
+    mov     a2, a\probe_ok
+    set_vector window_overflow_\window, 10f
+1:
+    mov     a2, a\probe_ex
+    test_fail
+10:
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+    movi    a2, 2f
+    wsr     a2, epc1
+
+    rsr     a2, windowbase
+    movi    a3, (\shift) / 4
+    assert  eq, a2, a3
+    rsr     a2, ps
+    movi    a3, 0x4001f
+    assert  eq, a2, a3
+    rfwo
+    test_fail
+2:
+    rsr     a2, windowbase
+    assert  eqi, a2, 0
+    rsr     a2, windowstart
+    movi    a3, 1 | ((1 << ((\window) / 4)) << ((\shift) / 4))
+    assert  eq, a2, a3
+    rsr     a2, ps
+    movi    a3, 0x4000f
+    assert  eq, a2, a3
+.endm
+
+.macro overflow_tests shift, window, probe
+    .if \probe < 15
+    overflow_test \shift, \window, %((\shift) - 1), \probe
+    overflow_tests \shift, \window, %((\probe) + 1)
+    .endif
+.endm
+
+.macro all_overflow_tests
+    .irp shift, 4, 8, 12
+    .irp window, 4, 8, 12
+    overflow_tests \shift, \window, \shift
+    .endr
+    .endr
+.endm
+
+test overflow
+    all_overflow_tests
+test_end
+
+
+.macro underflow_test window
+    set_vector window_underflow_4, 0
+    set_vector window_underflow_8, 0
+    set_vector window_underflow_12, 0
+
+    set_vector window_underflow_\window, 10f
+
+    reset_window 1
+    reset_ps
+
+    ssai    2
+    movi    a2, 2f
+    slli    a2, a2, 2
+    movi    a3, (\window) / 4
+    src     a0, a3, a2
+1:
+    retw
+    test_fail
+10:
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+    movi    a2, 2f
+    wsr     a2, epc1
+
+    rsr     a2, ps
+    movi    a3, 0x4001f
+    assert  eq, a2, a3
+    rsr     a2, windowbase
+    assert  eqi, a2, 8 - ((\window) / 4)
+    rsr     a2, windowstart
+    assert  eqi, a2, 1
+    rfwu
+2:
+    rsr     a2, ps
+    movi    a3, 0x4000f
+    assert  eq, a2, a3
+    rsr     a2, windowbase
+    assert  eqi, a2, 0
+    rsr     a2, windowstart
+    assert  bsi, a2, 0
+    assert  bsi, a2, 8 - ((\window) / 4)
+.endm
+
+test underflow
+    set_vector window_overflow_4, 0
+    set_vector window_overflow_8, 0
+    set_vector window_overflow_12, 0
+
+    underflow_test 4
+    underflow_test 8
+    underflow_test 12
+test_end
+
+
+.macro retw_test window
+    reset_window %(1 | (1 << (8 - (\window) / 4)))
+    reset_ps
+
+    ssai    2
+    movi    a2, 1f
+    slli    a2, a2, 2
+    movi    a3, (\window) / 4
+    src     a0, a3, a2
+    retw
+    test_fail
+1:
+    rsr     a2, ps
+    movi    a3, 0x4000f
+    assert  eq, a2, a3
+    rsr     a2, windowbase
+    assert  eqi, a2, 8 - ((\window) / 4)
+    rsr     a2, windowstart
+    assert  bci, a2, 0
+    assert  bsi, a2, 8 - ((\window) / 4)
+.endm
+
+test retw
+    set_vector window_underflow_4, 0
+    set_vector window_underflow_8, 0
+    set_vector window_underflow_12, 0
+
+    retw_test 4
+    retw_test 8
+    retw_test 12
+test_end
+
+test movsp
+    set_vector kernel, 2f
+
+    reset_window 1
+    reset_ps
+1:
+    movsp   a2, a3
+    test_fail
+2:
+    rsr     a2, exccause
+    assert  eqi, a2, 5
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+
+    set_vector kernel, 0
+
+    reset_window 0x81
+    reset_ps
+
+    movsp   a2, a3
+test_end
+
+test rotw
+    reset_window 0x4b
+    reset_ps
+
+    movi    a3, 0x10
+
+    rotw    1
+    rsr     a2, windowbase
+    assert  eqi, a2, 1
+    movi    a3, 0x11
+    movi    a7, 0x12
+
+    rotw    2
+    rsr     a2, windowbase
+    assert  eqi, a2, 3
+    movi    a3, 0x13
+    movi    a7, 0x14
+    movi    a11, 0x15
+
+    rotw    3
+    rsr     a2, windowbase
+    assert  eqi, a2, 6
+    movi    a3, 0x16
+    movi    a7, 0x17
+
+    movi    a2, 0x44
+    wsr     a2, windowstart
+    rsync
+
+    movi    a2, 0x10
+    assert  eq, a2, a11
+    movi    a11, 0x18
+    movi    a2, 0x11
+    assert  eq, a2, a15
+    movi    a15, 0x19
+
+    rotw    4
+    movi    a2, 0x12
+    assert  eq, a2, a3
+    movi    a2, 0x13
+    assert  eq, a2, a7
+    movi    a2, 0x14
+    assert  eq, a2, a11
+    movi    a2, 0x15
+    assert  eq, a2, a15
+
+    movi    a2, 0x5
+    wsr     a2, windowstart
+    rsync
+
+    rotw    -2
+    movi    a2, 0x18
+    assert  eq, a2, a3
+    movi    a2, 0x19
+    assert  eq, a2, a7
+test_end
+
+.macro callw_test window
+    call\window 2f
+1:
+    test_fail
+    .align  4
+2:
+    rsr     a2, windowbase
+    assert  eqi, a2, 0
+    rsr     a2, ps
+    movi    a3, 0x4000f | ((\window) << 14)
+    assert  eq, a2, a3
+    movi    a2, 1b
+    slli    a2, a2, 2
+    ssai    2
+    movi    a3, (\window) / 4
+    src     a2, a3, a2
+    assert  eq, a2, a\window
+.endm
+
+test callw
+    reset_window 0x1
+    reset_ps
+
+    callw_test 4
+    callw_test 8
+    callw_test 12
+test_end
+
+
+.macro entry_test window
+    reset_window 0x1
+    reset_ps
+    movi    a2, 0x4000f | ((\window) << 14)
+    wsr     a2, ps
+    isync
+    movi    a3, 0x12345678
+    j       1f
+    .align  4
+1:
+    entry   a3, 0x5678
+    movi    a2, 0x12340000
+    assert  eq, a2, a3
+    rsr     a2, windowbase
+    assert  eqi, a2, (\window) / 4
+    rsr     a2, windowstart
+    movi    a3, 1 | (1 << ((\window) / 4))
+    assert  eq, a2, a3
+    rotw    -(\window) / 4
+.endm
+
+test entry
+    entry_test 4
+    entry_test 8
+    entry_test 12
+test_end
+
+test_suite_end
diff --git a/tests/xtensa/vectors.S b/tests/xtensa/vectors.S
new file mode 100644
index 0000000..265a181
--- /dev/null
+++ b/tests/xtensa/vectors.S
@@ -0,0 +1,39 @@
+.macro vector name
+
+.section .vector.\name
+    j       1f
+.section .vector.\name\().text
+1:
+    wsr     a2, excsave1
+    movi    a2, handler_\name
+    l32i    a2, a2, 0
+    beqz    a2, 1f
+    jx      a2
+1:
+    movi    a3, 1b
+    movi    a2, 1
+    simcall
+
+.align 4
+.global handler_\name
+handler_\name\(): .word 0
+
+.endm
+
+vector window_overflow_4
+vector window_overflow_8
+vector window_overflow_12
+vector window_underflow_4
+vector window_underflow_8
+vector window_underflow_12
+
+vector level2
+vector level3
+vector level4
+vector level5
+vector level6
+vector level7
+
+vector kernel
+vector user
+vector double
-- 
1.7.6

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

* Re: [Qemu-devel] [PATCH v4 01/32] target-xtensa: add target stubs
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 01/32] target-xtensa: add target stubs Max Filippov
@ 2011-09-04 18:14   ` Blue Swirl
  0 siblings, 0 replies; 47+ messages in thread
From: Blue Swirl @ 2011-09-04 18:14 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On Thu, Sep 1, 2011 at 8:45 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
> ---
>  Makefile.target           |    2 +
>  arch_init.c               |    2 +
>  arch_init.h               |    1 +
>  cpu-exec.c                |    2 +
>  elf.h                     |    2 +
>  hw/xtensa_pic.c           |   38 ++++++++++++++++++
>  target-xtensa/cpu.h       |   95 +++++++++++++++++++++++++++++++++++++++++++++
>  target-xtensa/helper.c    |   73 ++++++++++++++++++++++++++++++++++
>  target-xtensa/machine.c   |   38 ++++++++++++++++++
>  target-xtensa/op_helper.c |   52 ++++++++++++++++++++++++
>  target-xtensa/translate.c |   67 +++++++++++++++++++++++++++++++
>  11 files changed, 372 insertions(+), 0 deletions(-)
>  create mode 100644 hw/xtensa_pic.c
>  create mode 100644 target-xtensa/cpu.h
>  create mode 100644 target-xtensa/helper.c
>  create mode 100644 target-xtensa/machine.c
>  create mode 100644 target-xtensa/op_helper.c
>  create mode 100644 target-xtensa/translate.c
>
> diff --git a/Makefile.target b/Makefile.target
> index 07af4d4..b833c10 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -373,6 +373,8 @@ obj-s390x-y = s390-virtio-bus.o s390-virtio.o
>  obj-alpha-y = i8259.o mc146818rtc.o
>  obj-alpha-y += vga.o cirrus_vga.o
>
> +obj-xtensa-y += xtensa_pic.o
> +
>  main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
>
>  monitor.o: hmp-commands.h qmp-commands.h
> diff --git a/arch_init.c b/arch_init.c
> index 567ab32..9a5a0e3 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -78,6 +78,8 @@ const char arch_config_name[] = CONFIG_QEMU_CONFDIR "/target-" TARGET_ARCH ".con
>  #define QEMU_ARCH QEMU_ARCH_SH4
>  #elif defined(TARGET_SPARC)
>  #define QEMU_ARCH QEMU_ARCH_SPARC
> +#elif defined(TARGET_XTENSA)
> +#define QEMU_ARCH QEMU_ARCH_XTENSA
>  #endif
>
>  const uint32_t arch_type = QEMU_ARCH;
> diff --git a/arch_init.h b/arch_init.h
> index 2de9f08..a74187a 100644
> --- a/arch_init.h
> +++ b/arch_init.h
> @@ -17,6 +17,7 @@ enum {
>     QEMU_ARCH_S390X = 512,
>     QEMU_ARCH_SH4 = 1024,
>     QEMU_ARCH_SPARC = 2048,
> +    QEMU_ARCH_XTENSA = 4096,
>  };
>
>  extern const uint32_t arch_type;
> diff --git a/cpu-exec.c b/cpu-exec.c
> index de0d716..3fce033 100644
> --- a/cpu-exec.c
> +++ b/cpu-exec.c
> @@ -222,6 +222,7 @@ int cpu_exec(CPUState *env)
>  #elif defined(TARGET_SH4)
>  #elif defined(TARGET_CRIS)
>  #elif defined(TARGET_S390X)
> +#elif defined(TARGET_XTENSA)
>     /* XXXXX */
>  #else
>  #error unsupported target CPU
> @@ -616,6 +617,7 @@ int cpu_exec(CPUState *env)
>  #elif defined(TARGET_ALPHA)
>  #elif defined(TARGET_CRIS)
>  #elif defined(TARGET_S390X)
> +#elif defined(TARGET_XTENSA)
>     /* XXXXX */
>  #else
>  #error unsupported target CPU
> diff --git a/elf.h b/elf.h
> index ffcac7e..2e05d34 100644
> --- a/elf.h
> +++ b/elf.h
> @@ -125,6 +125,8 @@ typedef int64_t  Elf64_Sxword;
>  #define EM_MICROBLAZE      189
>  #define EM_MICROBLAZE_OLD  0xBAAB
>
> +#define EM_XTENSA   94      /* Tensilica Xtensa */
> +
>  /* This is the info that is needed to parse the dynamic section of the file */
>  #define DT_NULL                0
>  #define DT_NEEDED      1
> diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
> new file mode 100644
> index 0000000..91a5445
> --- /dev/null
> +++ b/hw/xtensa_pic.c
> @@ -0,0 +1,38 @@
> +/*
> + * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions are met:
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in the
> + *       documentation and/or other materials provided with the distribution.
> + *     * Neither the name of the Open Source and Linux Lab nor the
> + *       names of its contributors may be used to endorse or promote products
> + *       derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include "hw.h"
> +#include "pc.h"
> +
> +/* Stub functions for hardware that doesn't exist.  */
> +void pic_info(Monitor *mon)
> +{
> +}
> +
> +void irq_info(Monitor *mon)
> +{
> +}
> diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
> new file mode 100644
> index 0000000..a51ffc8
> --- /dev/null
> +++ b/target-xtensa/cpu.h
> @@ -0,0 +1,95 @@
> +/*
> + * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions are met:
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in the
> + *       documentation and/or other materials provided with the distribution.
> + *     * Neither the name of the Open Source and Linux Lab nor the
> + *       names of its contributors may be used to endorse or promote products
> + *       derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifndef CPU_XTENSA_H
> +#define CPU_XTENSA_H
> +
> +#define TARGET_LONG_BITS 32
> +#define ELF_MACHINE EM_XTENSA
> +
> +#define CPUState struct CPUXtensaState
> +
> +#include "config.h"
> +#include "qemu-common.h"
> +#include "cpu-defs.h"
> +
> +#define TARGET_HAS_ICE 1
> +
> +#define NB_MMU_MODES 4
> +
> +#define TARGET_PHYS_ADDR_SPACE_BITS 32
> +#define TARGET_VIRT_ADDR_SPACE_BITS 32
> +#define TARGET_PAGE_BITS 12
> +
> +typedef struct CPUXtensaState {
> +    uint32_t regs[16];
> +    uint32_t pc;
> +    uint32_t sregs[256];
> +
> +    CPU_COMMON
> +} CPUXtensaState;
> +
> +#define cpu_init cpu_xtensa_init
> +#define cpu_exec cpu_xtensa_exec
> +#define cpu_gen_code cpu_xtensa_gen_code
> +#define cpu_signal_handler cpu_xtensa_signal_handler
> +#define cpu_list xtensa_cpu_list
> +
> +CPUXtensaState *cpu_xtensa_init(const char *cpu_model);
> +void xtensa_translate_init(void);
> +int cpu_xtensa_exec(CPUXtensaState *s);
> +void do_interrupt(CPUXtensaState *s);
> +int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
> +void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
> +
> +static inline int cpu_mmu_index(CPUState *env)
> +{
> +    return 0;
> +}
> +
> +static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
> +        target_ulong *cs_base, int *flags)
> +{
> +    *pc = env->pc;
> +    *cs_base = 0;
> +    *flags = 0;
> +}
> +
> +#include "cpu-all.h"
> +#include "exec-all.h"
> +
> +static inline int cpu_has_work(CPUState *env)
> +{
> +    return 1;
> +}
> +
> +static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
> +{
> +    env->pc = tb->pc;
> +}
> +
> +#endif
> diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
> new file mode 100644
> index 0000000..dc30e00
> --- /dev/null
> +++ b/target-xtensa/helper.c
> @@ -0,0 +1,73 @@
> +/*
> + * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions are met:
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in the
> + *       documentation and/or other materials provided with the distribution.
> + *     * Neither the name of the Open Source and Linux Lab nor the
> + *       names of its contributors may be used to endorse or promote products
> + *       derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include "cpu.h"
> +#include "exec-all.h"
> +#include "gdbstub.h"
> +#include "qemu-common.h"
> +#include "host-utils.h"
> +#if !defined(CONFIG_USER_ONLY)
> +#include "hw/loader.h"
> +#endif
> +
> +void cpu_reset(CPUXtensaState *env)
> +{
> +    env->pc = 0;
> +}
> +
> +CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
> +{
> +    static int tcg_inited;
> +    CPUXtensaState *env;
> +
> +    env = g_malloc0(sizeof(*env));
> +    cpu_exec_init(env);
> +
> +    if (!tcg_inited) {
> +        tcg_inited = 1;
> +        xtensa_translate_init();
> +    }
> +
> +    qemu_init_vcpu(env);
> +    return env;
> +}
> +
> +
> +void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf)
> +{
> +    cpu_fprintf(f, "Available CPUs:\n"
> +            "  Xtensa core\n");
> +}
> +
> +target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
> +{
> +    return addr;
> +}
> +
> +void do_interrupt(CPUState *env)
> +{
> +}
> diff --git a/target-xtensa/machine.c b/target-xtensa/machine.c
> new file mode 100644
> index 0000000..ddeffb2
> --- /dev/null
> +++ b/target-xtensa/machine.c
> @@ -0,0 +1,38 @@
> +/*
> + * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions are met:
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in the
> + *       documentation and/or other materials provided with the distribution.
> + *     * Neither the name of the Open Source and Linux Lab nor the
> + *       names of its contributors may be used to endorse or promote products
> + *       derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#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-xtensa/op_helper.c b/target-xtensa/op_helper.c
> new file mode 100644
> index 0000000..aafa33d
> --- /dev/null
> +++ b/target-xtensa/op_helper.c
> @@ -0,0 +1,52 @@
> +/*
> + * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions are met:
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in the
> + *       documentation and/or other materials provided with the distribution.
> + *     * Neither the name of the Open Source and Linux Lab nor the
> + *       names of its contributors may be used to endorse or promote products
> + *       derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include "cpu.h"
> +#include "dyngen-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(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
> +{
> +    tlb_set_page(cpu_single_env,
> +            addr & ~(TARGET_PAGE_SIZE - 1),
> +            addr & ~(TARGET_PAGE_SIZE - 1),
> +            PAGE_READ | PAGE_WRITE | PAGE_EXEC,
> +            mmu_idx, TARGET_PAGE_SIZE);
> +}
> diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
> new file mode 100644
> index 0000000..e91d8a5
> --- /dev/null
> +++ b/target-xtensa/translate.c
> @@ -0,0 +1,67 @@
> +/*
> + * Xtensa ISA:
> + * http://www.tensilica.com/products/literature-docs/documentation/xtensa-isa-databook.htm
> + *
> + * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions are met:
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in the
> + *       documentation and/or other materials provided with the distribution.
> + *     * Neither the name of the Open Source and Linux Lab nor the
> + *       names of its contributors may be used to endorse or promote products
> + *       derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <stdio.h>
> +
> +#include "cpu.h"
> +#include "exec-all.h"
> +#include "disas.h"
> +#include "tcg-op.h"
> +#include "qemu-log.h"
> +
> +
> +void xtensa_translate_init(void)
> +{
> +}
> +
> +void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
> +{
> +}
> +
> +void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
> +{
> +}
> +
> +void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
> +        int flags)
> +{
> +    int i;
> +
> +    cpu_fprintf(f, "PC=%08x\n", env->pc);
> +
> +    for (i = 0; i < 16; ++i)

Missing braces.

> +        cpu_fprintf(f, "A%02d=%08x%c", i, env->regs[i],
> +                (i % 4) == 3 ? '\n' : ' ');
> +}
> +
> +void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
> +{
> +    env->pc = gen_opc_pc[pc_pos];
> +}
> --
> 1.7.6
>
>
>

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

* Re: [Qemu-devel] [PATCH v4 06/32] target-xtensa: add sample board
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 06/32] target-xtensa: add sample board Max Filippov
@ 2011-09-04 18:17   ` Blue Swirl
  0 siblings, 0 replies; 47+ messages in thread
From: Blue Swirl @ 2011-09-04 18:17 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On Thu, Sep 1, 2011 at 8:45 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> Sample board and sample CPU core are used for debug and may be used for
> development of custom SoC emulators.
>
> This board has two fixed size memory regions for DTCM and ITCM and
> variable length SRAM region.
>
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
> ---
>  Makefile.target    |    1 +
>  hw/xtensa_sample.c |  105 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 106 insertions(+), 0 deletions(-)
>  create mode 100644 hw/xtensa_sample.c
>
> diff --git a/Makefile.target b/Makefile.target
> index b833c10..98455e3 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -374,6 +374,7 @@ obj-alpha-y = i8259.o mc146818rtc.o
>  obj-alpha-y += vga.o cirrus_vga.o
>
>  obj-xtensa-y += xtensa_pic.o
> +obj-xtensa-y += xtensa_sample.o
>
>  main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
>
> diff --git a/hw/xtensa_sample.c b/hw/xtensa_sample.c
> new file mode 100644
> index 0000000..9f7733b
> --- /dev/null
> +++ b/hw/xtensa_sample.c
> @@ -0,0 +1,105 @@
> +/*
> + * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions are met:
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in the
> + *       documentation and/or other materials provided with the distribution.
> + *     * Neither the name of the Open Source and Linux Lab nor the
> + *       names of its contributors may be used to endorse or promote products
> + *       derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include "sysemu.h"
> +#include "boards.h"
> +#include "loader.h"
> +#include "elf.h"
> +
> +static void xtensa_sample_reset(void *env)
> +{
> +    cpu_reset(env);
> +}
> +
> +static void xtensa_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)
> +{
> +    CPUState *env = NULL;
> +    ram_addr_t ram_offset;
> +    int n;
> +
> +    for (n = 0; n < smp_cpus; n++) {
> +        env = cpu_init(cpu_model);
> +        if (!env) {
> +            fprintf(stderr, "Unable to find CPU definition\n");
> +            exit(1);
> +        }
> +        qemu_register_reset(xtensa_sample_reset, env);
> +    }
> +
> +    ram_offset = qemu_ram_alloc(NULL, "xtensa.dram", 0x10000);
> +    cpu_register_physical_memory(0x5ffd0000, 0x10000, ram_offset);
> +
> +    ram_offset = qemu_ram_alloc(NULL, "xtensa.iram", 0x20000);
> +    cpu_register_physical_memory(0x5ffe0000, 0x20000, ram_offset);
> +
> +    ram_offset = qemu_ram_alloc(NULL, "xtensa.sram", ram_size);
> +    cpu_register_physical_memory(0x60000000, ram_size, ram_offset);

These should be converted to the new memory API. Please see pc.c for reference.

> +
> +    if (kernel_filename) {
> +        uint64_t elf_entry;
> +        uint64_t elf_lowaddr;
> +#ifdef TARGET_WORDS_BIGENDIAN
> +        int success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
> +                &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
> +#else
> +        int success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
> +                &elf_lowaddr, NULL, 0, ELF_MACHINE, 0);
> +#endif
> +        if (success > 0) {
> +            env->pc = elf_entry;
> +        }
> +    }
> +}
> +
> +static void xtensa_sample_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)
> +{
> +    if (!cpu_model) {
> +        cpu_model = "sample-xtensa-core";
> +    }
> +    xtensa_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
> +                  initrd_filename, cpu_model);
> +}
> +
> +static QEMUMachine xtensa_sample_machine = {
> +    .name = "sample-xtensa-machine",
> +    .desc = "Sample Xtensa machine (sample Xtensa core)",
> +    .init = xtensa_sample_init,
> +    .max_cpus = 4,
> +};
> +
> +static void xtensa_sample_machine_init(void)
> +{
> +    qemu_register_machine(&xtensa_sample_machine);
> +}
> +
> +machine_init(xtensa_sample_machine_init);
> --
> 1.7.6
>
>
>

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

* Re: [Qemu-devel] [PATCH v4 09/32] target-xtensa: add special and user registers
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 09/32] target-xtensa: add special and user registers Max Filippov
@ 2011-09-04 18:18   ` Blue Swirl
  0 siblings, 0 replies; 47+ messages in thread
From: Blue Swirl @ 2011-09-04 18:18 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On Thu, Sep 1, 2011 at 8:45 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> Special Registers hold the majority of the state added to the processor
> by the options. See ISA, 5.3 for details.
>
> User Registers hold state added in support of designer's TIE and in some
> cases of options that Tensilica provides. See ISA, 5.4 for details.
>
> Only registers mapped in sregnames or uregnames are considered valid.
>
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
> ---
>  target-xtensa/cpu.h       |    7 ++++++
>  target-xtensa/translate.c |   47 +++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 52 insertions(+), 2 deletions(-)
>
> diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
> index c323891..8c3fe2e 100644
> --- a/target-xtensa/cpu.h
> +++ b/target-xtensa/cpu.h
> @@ -99,6 +99,12 @@ enum {
>     XTENSA_OPTION_TRACE_PORT,
>  };
>
> +enum {
> +    THREADPTR = 231,
> +    FCR = 232,
> +    FSR = 233,
> +};
> +
>  typedef struct XtensaConfig {
>     const char *name;
>     uint64_t options;
> @@ -109,6 +115,7 @@ typedef struct CPUXtensaState {
>     uint32_t regs[16];
>     uint32_t pc;
>     uint32_t sregs[256];
> +    uint32_t uregs[256];
>
>     CPU_COMMON
>  } CPUXtensaState;
> diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
> index 26cce83..3c8d877 100644
> --- a/target-xtensa/translate.c
> +++ b/target-xtensa/translate.c
> @@ -52,9 +52,20 @@ typedef struct DisasContext {
>  static TCGv_ptr cpu_env;
>  static TCGv_i32 cpu_pc;
>  static TCGv_i32 cpu_R[16];
> +static TCGv_i32 cpu_SR[256];
> +static TCGv_i32 cpu_UR[256];
>
>  #include "gen-icount.h"
>
> +static const char * const sregnames[256] = {
> +};
> +
> +static const char * const uregnames[256] = {
> +    [THREADPTR] = "THREADPTR",
> +    [FCR] = "FCR",
> +    [FSR] = "FSR",
> +};
> +
>  void xtensa_translate_init(void)
>  {
>     static const char * const regnames[] = {
> @@ -74,6 +85,22 @@ void xtensa_translate_init(void)
>                 offsetof(CPUState, regs[i]),
>                 regnames[i]);
>     }
> +
> +    for (i = 0; i < 256; ++i) {
> +        if (sregnames[i]) {
> +            cpu_SR[i] = tcg_global_mem_new_i32(TCG_AREG0,
> +                    offsetof(CPUState, sregs[i]),
> +                    sregnames[i]);
> +        }
> +    }
> +
> +    for (i = 0; i < 256; ++i) {
> +        if (uregnames[i]) {
> +            cpu_UR[i] = tcg_global_mem_new_i32(TCG_AREG0,
> +                    offsetof(CPUState, uregs[i]),
> +                    uregnames[i]);
> +        }
> +    }
>  #define GEN_HELPER 2
>  #include "helpers.h"
>  }
> @@ -784,9 +811,25 @@ void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
>  void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
>         int flags)
>  {
> -    int i;
> +    int i, j;
> +
> +    cpu_fprintf(f, "PC=%08x\n\n", env->pc);
> +
> +    for (i = j = 0; i < 256; ++i)

Braces, please.

> +        if (sregnames[i]) {
> +            cpu_fprintf(f, "%s=%08x%c", sregnames[i], env->sregs[i],
> +                    (j++ % 4) == 3 ? '\n' : ' ');
> +        }
> +
> +    cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
> +
> +    for (i = j = 0; i < 256; ++i)

Also here.

> +        if (uregnames[i]) {
> +            cpu_fprintf(f, "%s=%08x%c", uregnames[i], env->uregs[i],
> +                    (j++ % 4) == 3 ? '\n' : ' ');
> +        }
>
> -    cpu_fprintf(f, "PC=%08x\n", env->pc);
> +    cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
>
>     for (i = 0; i < 16; ++i)
>         cpu_fprintf(f, "A%02d=%08x%c", i, env->regs[i],
> --
> 1.7.6
>
>
>

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

* Re: [Qemu-devel] [PATCH v4 17/32] target-xtensa: implement exceptions
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 17/32] target-xtensa: implement exceptions Max Filippov
@ 2011-09-04 18:22   ` Blue Swirl
  0 siblings, 0 replies; 47+ messages in thread
From: Blue Swirl @ 2011-09-04 18:22 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On Thu, Sep 1, 2011 at 8:45 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> - mark privileged opcodes with ring check;
> - make debug exception on exception handler entry.
>
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
> ---
>  cpu-exec.c                |    6 +++
>  target-xtensa/cpu.h       |   67 ++++++++++++++++++++++++++++
>  target-xtensa/helper.c    |   37 +++++++++++++++-
>  target-xtensa/helpers.h   |    2 +
>  target-xtensa/op_helper.c |   29 ++++++++++++
>  target-xtensa/translate.c |  107 ++++++++++++++++++++++++++++++++++++++++++--
>  6 files changed, 242 insertions(+), 6 deletions(-)
>
> diff --git a/cpu-exec.c b/cpu-exec.c
> index 3fce033..2fc37d8 100644
> --- a/cpu-exec.c
> +++ b/cpu-exec.c
> @@ -488,6 +488,12 @@ int cpu_exec(CPUState *env)
>                         do_interrupt(env);
>                         next_tb = 0;
>                     }
> +#elif defined(TARGET_XTENSA)
> +                    if (interrupt_request & CPU_INTERRUPT_HARD) {
> +                        env->exception_index = EXC_IRQ;
> +                        do_interrupt(env);
> +                        next_tb = 0;
> +                    }
>  #endif
>                    /* Don't use the cached interrupt_request value,
>                       do_interrupt may have updated the EXITTB flag. */
> diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
> index 939222c..cae6637 100644
> --- a/target-xtensa/cpu.h
> +++ b/target-xtensa/cpu.h
> @@ -108,7 +108,12 @@ enum {
>  enum {
>     SAR = 3,
>     SCOMPARE1 = 12,
> +    EPC1 = 177,
> +    DEPC = 192,
> +    EXCSAVE1 = 209,
>     PS = 230,
> +    EXCCAUSE = 232,
> +    EXCVADDR = 238,
>  };
>
>  #define PS_INTLEVEL 0xf
> @@ -129,9 +134,60 @@ enum {
>
>  #define PS_WOE 0x40000
>
> +enum {
> +    /* Static vectors */
> +    EXC_RESET,
> +    EXC_MEMORY_ERROR,
> +
> +    /* Dynamic vectors */
> +    EXC_WINDOW_OVERFLOW4,
> +    EXC_WINDOW_UNDERFLOW4,
> +    EXC_WINDOW_OVERFLOW8,
> +    EXC_WINDOW_UNDERFLOW8,
> +    EXC_WINDOW_OVERFLOW12,
> +    EXC_WINDOW_UNDERFLOW12,
> +    EXC_IRQ,
> +    EXC_KERNEL,
> +    EXC_USER,
> +    EXC_DOUBLE,
> +    EXC_MAX
> +};
> +
> +enum {
> +    ILLEGAL_INSTRUCTION_CAUSE = 0,
> +    SYSCALL_CAUSE,
> +    INSTRUCTION_FETCH_ERROR_CAUSE,
> +    LOAD_STORE_ERROR_CAUSE,
> +    LEVEL1_INTERRUPT_CAUSE,
> +    ALLOCA_CAUSE,
> +    INTEGER_DIVIDE_BY_ZERO_CAUSE,
> +    PRIVILEGED_CAUSE = 8,
> +    LOAD_STORE_ALIGNMENT_CAUSE,
> +
> +    INSTR_PIF_DATA_ERROR_CAUSE = 12,
> +    LOAD_STORE_PIF_DATA_ERROR_CAUSE,
> +    INSTR_PIF_ADDR_ERROR_CAUSE,
> +    LOAD_STORE_PIF_ADDR_ERROR_CAUSE,
> +
> +    INST_TLB_MISS_CAUSE,
> +    INST_TLB_MULTI_HIT_CAUSE,
> +    INST_FETCH_PRIVILEGE_CAUSE,
> +    INST_FETCH_PROHIBITED_CAUSE = 20,
> +    LOAD_STORE_TLB_MISS_CAUSE = 24,
> +    LOAD_STORE_TLB_MULTI_HIT_CAUSE,
> +    LOAD_STORE_PRIVILEGE_CAUSE,
> +    LOAD_PROHIBITED_CAUSE = 28,
> +    STORE_PROHIBITED_CAUSE,
> +
> +    COPROCESSOR0_DISABLED = 32,
> +};
> +
>  typedef struct XtensaConfig {
>     const char *name;
>     uint64_t options;
> +    int excm_level;
> +    int ndepc;
> +    uint32_t exception_vector[EXC_MAX];
>  } XtensaConfig;
>
>  typedef struct CPUXtensaState {
> @@ -141,6 +197,8 @@ typedef struct CPUXtensaState {
>     uint32_t sregs[256];
>     uint32_t uregs[256];
>
> +    int exception_taken;
> +
>     CPU_COMMON
>  } CPUXtensaState;
>
> @@ -164,6 +222,15 @@ static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt)
>     return (config->options & XTENSA_OPTION_BIT(opt)) != 0;
>  }
>
> +static inline int xtensa_get_cintlevel(const CPUState *env)
> +{
> +    int level = (env->sregs[PS] & PS_INTLEVEL) >> PS_INTLEVEL_SHIFT;
> +    if ((env->sregs[PS] & PS_EXCM) && env->config->excm_level > level) {
> +        level = env->config->excm_level;
> +    }
> +    return level;
> +}
> +
>  static inline int xtensa_get_ring(const CPUState *env)
>  {
>     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
> diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
> index 83b8a04..44ebb9f 100644
> --- a/target-xtensa/helper.c
> +++ b/target-xtensa/helper.c
> @@ -36,7 +36,8 @@
>
>  void cpu_reset(CPUXtensaState *env)
>  {
> -    env->pc = 0;
> +    env->exception_taken = 0;
> +    env->pc = env->config->exception_vector[EXC_RESET];
>     env->sregs[PS] = 0x1f;
>  }
>
> @@ -44,6 +45,20 @@ static const XtensaConfig core_config[] = {
>     {
>         .name = "sample-xtensa-core",
>         .options = -1,
> +        .ndepc = 1,
> +        .excm_level = 16,
> +        .exception_vector = {
> +            [EXC_RESET] = 0x5fff8000,
> +            [EXC_WINDOW_OVERFLOW4] = 0x5fff8400,
> +            [EXC_WINDOW_UNDERFLOW4] = 0x5fff8440,
> +            [EXC_WINDOW_OVERFLOW8] = 0x5fff8480,
> +            [EXC_WINDOW_UNDERFLOW8] = 0x5fff84c0,
> +            [EXC_WINDOW_OVERFLOW12] = 0x5fff8500,
> +            [EXC_WINDOW_UNDERFLOW12] = 0x5fff8540,
> +            [EXC_KERNEL] = 0x5fff861c,
> +            [EXC_USER] = 0x5fff863c,
> +            [EXC_DOUBLE] = 0x5fff865c,
> +        },
>     },
>  };
>
> @@ -94,4 +109,24 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
>
>  void do_interrupt(CPUState *env)
>  {
> +    switch (env->exception_index) {
> +    case EXC_WINDOW_OVERFLOW4:
> +    case EXC_WINDOW_UNDERFLOW4:
> +    case EXC_WINDOW_OVERFLOW8:
> +    case EXC_WINDOW_UNDERFLOW8:
> +    case EXC_WINDOW_OVERFLOW12:
> +    case EXC_WINDOW_UNDERFLOW12:
> +    case EXC_KERNEL:
> +    case EXC_USER:
> +    case EXC_DOUBLE:
> +        if (env->config->exception_vector[env->exception_index]) {
> +            env->pc = env->config->exception_vector[env->exception_index];
> +            env->exception_taken = 1;
> +        } else {
> +            qemu_log("%s(pc = %08x) bad exception_index: %d\n",
> +                    __func__, env->pc, env->exception_index);
> +        }
> +        break;
> +
> +    }
>  }
> diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
> index 976c8d8..6329c43 100644
> --- a/target-xtensa/helpers.h
> +++ b/target-xtensa/helpers.h
> @@ -1,6 +1,8 @@
>  #include "def-helper.h"
>
>  DEF_HELPER_1(exception, void, i32)
> +DEF_HELPER_2(exception_cause, void, i32, i32)
> +DEF_HELPER_3(exception_cause_vaddr, void, i32, i32, i32)
>  DEF_HELPER_1(nsa, i32, i32)
>  DEF_HELPER_1(nsau, i32, i32)
>
> diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
> index c1cfd2e..794a834 100644
> --- a/target-xtensa/op_helper.c
> +++ b/target-xtensa/op_helper.c
> @@ -59,6 +59,35 @@ void HELPER(exception)(uint32_t excp)
>     cpu_loop_exit(env);
>  }
>
> +void HELPER(exception_cause)(uint32_t pc, uint32_t cause)
> +{
> +    uint32_t vector;
> +
> +    env->pc = pc;
> +    if (env->sregs[PS] & PS_EXCM) {
> +        if (env->config->ndepc) {
> +            env->sregs[DEPC] = pc;
> +        } else {
> +            env->sregs[EPC1] = pc;
> +        }
> +        vector = EXC_DOUBLE;
> +    } else {
> +        env->sregs[EPC1] = pc;
> +        vector = (env->sregs[PS] & PS_UM) ? EXC_USER : EXC_KERNEL;
> +    }
> +
> +    env->sregs[EXCCAUSE] = cause;
> +    env->sregs[PS] |= PS_EXCM;
> +
> +    HELPER(exception)(vector);
> +}
> +
> +void HELPER(exception_cause_vaddr)(uint32_t pc, uint32_t cause, uint32_t vaddr)
> +{
> +    env->sregs[EXCVADDR] = vaddr;
> +    HELPER(exception_cause)(pc, cause);
> +}
> +
>  uint32_t HELPER(nsa)(uint32_t v)
>  {
>     if (v & 0x80000000) {
> diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
> index b6d0210..4c9db9e 100644
> --- a/target-xtensa/translate.c
> +++ b/target-xtensa/translate.c
> @@ -67,7 +67,12 @@ static TCGv_i32 cpu_UR[256];
>  static const char * const sregnames[256] = {
>     [SAR] = "SAR",
>     [SCOMPARE1] = "SCOMPARE1",
> +    [EPC1] = "EPC1",
> +    [DEPC] = "DEPC",
> +    [EXCSAVE1] = "EXCSAVE1",
>     [PS] = "PS",
> +    [EXCCAUSE] = "EXCCAUSE",
> +    [EXCVADDR] = "EXCVADDR",
>  };
>
>  static const char * const uregnames[256] = {
> @@ -165,6 +170,22 @@ static void gen_exception(int excp)
>     tcg_temp_free(tmp);
>  }
>
> +static void gen_exception_cause(DisasContext *dc, uint32_t cause)
> +{
> +    TCGv_i32 _pc = tcg_const_i32(dc->pc);
> +    TCGv_i32 _cause = tcg_const_i32(cause);

Please don't use identifiers starting with underscore.

> +    gen_helper_exception_cause(_pc, _cause);
> +    tcg_temp_free(_pc);
> +    tcg_temp_free(_cause);
> +}
> +
> +static void gen_check_privilege(DisasContext *dc)
> +{
> +    if (dc->cring) {
> +        gen_exception_cause(dc, PRIVILEGED_CAUSE);
> +    }
> +}
> +
>  static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
>  {
>     tcg_gen_mov_i32(cpu_pc, dest);
> @@ -392,7 +413,7 @@ static void disas_xtensa_insn(DisasContext *dc)
>                 case 0: /*SNM0*/
>                     switch (CALLX_M) {
>                     case 0: /*ILL*/
> -                        TBD();
> +                        gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
>                         break;
>
>                     case 1: /*reserved*/
> @@ -479,7 +500,52 @@ static void disas_xtensa_insn(DisasContext *dc)
>                     break;
>
>                 case 3: /*RFEIx*/
> -                    TBD();
> +                    switch (RRR_T) {
> +                    case 0: /*RFETx*/
> +                        HAS_OPTION(XTENSA_OPTION_EXCEPTION);
> +                        switch (RRR_S) {
> +                        case 0: /*RFEx*/
> +                            gen_check_privilege(dc);
> +                            tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);
> +                            gen_jump(dc, cpu_SR[EPC1]);
> +                            break;
> +
> +                        case 1: /*RFUEx*/
> +                            RESERVED();
> +                            break;
> +
> +                        case 2: /*RFDEx*/
> +                            gen_check_privilege(dc);
> +                            gen_jump(dc, cpu_SR[
> +                                    dc->config->ndepc ? DEPC : EPC1]);
> +                            break;
> +
> +                        case 4: /*RFWOw*/
> +                        case 5: /*RFWUw*/
> +                            HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
> +                            TBD();
> +                            break;
> +
> +                        default: /*reserved*/
> +                            RESERVED();
> +                            break;
> +                        }
> +                        break;
> +
> +                    case 1: /*RFIx*/
> +                        HAS_OPTION(XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT);
> +                        TBD();
> +                        break;
> +
> +                    case 2: /*RFME*/
> +                        TBD();
> +                        break;
> +
> +                    default: /*reserved*/
> +                        RESERVED();
> +                        break;
> +
> +                    }
>                     break;
>
>                 case 4: /*BREAKx*/
> @@ -489,12 +555,28 @@ static void disas_xtensa_insn(DisasContext *dc)
>
>                 case 5: /*SYSCALLx*/
>                     HAS_OPTION(XTENSA_OPTION_EXCEPTION);
> -                    TBD();
> +                    switch (RRR_S) {
> +                    case 0: /*SYSCALLx*/
> +                        gen_exception_cause(dc, SYSCALL_CAUSE);
> +                        break;
> +
> +                    case 1: /*SIMCALL*/
> +                        TBD();
> +                        break;
> +
> +                    default:
> +                        RESERVED();
> +                        break;
> +                    }
>                     break;
>
>                 case 6: /*RSILx*/
>                     HAS_OPTION(XTENSA_OPTION_INTERRUPT);
> -                    TBD();
> +                    gen_check_privilege(dc);
> +                    tcg_gen_mov_i32(cpu_R[RRR_T], cpu_SR[PS]);
> +                    tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], RRR_S);
> +                    tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS],
> +                            RRR_S | ~PS_INTLEVEL);
>                     break;
>
>                 case 7: /*WAITIx*/
> @@ -691,6 +773,9 @@ static void disas_xtensa_insn(DisasContext *dc)
>             case 6: /*XSR*/
>                 {
>                     TCGv_i32 tmp = tcg_temp_new_i32();
> +                    if (RSR_SR >= 64) {
> +                        gen_check_privilege(dc);
> +                    }
>                     tcg_gen_mov_i32(tmp, cpu_R[RRR_T]);
>                     gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
>                     gen_wsr(dc, RSR_SR, tmp);
> @@ -799,6 +884,9 @@ static void disas_xtensa_insn(DisasContext *dc)
>         case 3: /*RST3*/
>             switch (OP2) {
>             case 0: /*RSR*/
> +                if (RSR_SR >= 64) {
> +                    gen_check_privilege(dc);
> +                }
>                 gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
>                 if (!sregnames[RSR_SR]) {
>                     TBD();
> @@ -806,6 +894,9 @@ static void disas_xtensa_insn(DisasContext *dc)
>                 break;
>
>             case 1: /*WSR*/
> +                if (RSR_SR >= 64) {
> +                    gen_check_privilege(dc);
> +                }
>                 gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
>                 if (!sregnames[RSR_SR]) {
>                     TBD();
> @@ -1421,7 +1512,7 @@ static void disas_xtensa_insn(DisasContext *dc)
>                 break;
>
>             case 6: /*ILL.Nn*/
> -                TBD();
> +                gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
>                 break;
>
>             default: /*reserved*/
> @@ -1493,6 +1584,12 @@ static void gen_intermediate_code_internal(
>
>     gen_icount_start();
>
> +    if (env->singlestep_enabled && env->exception_taken) {
> +        env->exception_taken = 0;
> +        tcg_gen_movi_i32(cpu_pc, dc.pc);
> +        gen_exception(EXCP_DEBUG);
> +    }
> +
>     do {
>         check_breakpoint(env, &dc);
>
> --
> 1.7.6
>
>
>

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

* Re: [Qemu-devel] [PATCH v4 19/32] target-xtensa: implement windowed registers
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 19/32] target-xtensa: implement windowed registers Max Filippov
@ 2011-09-04 18:27   ` Blue Swirl
  0 siblings, 0 replies; 47+ messages in thread
From: Blue Swirl @ 2011-09-04 18:27 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On Thu, Sep 1, 2011 at 8:45 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> See ISA, 4.7.1 for details.
>
> Physical registers and currently visible window are separate fields in
> CPUEnv. Only current window is accessible to TCG. On operations that
> change window base helpers copy current window to and from physical
> registers.
>
> Window overflow check described in 4.7.1.3 is in separate patch.
>
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
> ---
>  target-xtensa/cpu.h       |    8 ++
>  target-xtensa/helper.c    |    1 +
>  target-xtensa/helpers.h   |    8 ++
>  target-xtensa/op_helper.c |  185 +++++++++++++++++++++++++++++++++++++++++++++
>  target-xtensa/translate.c |  144 +++++++++++++++++++++++++++++++++--
>  5 files changed, 337 insertions(+), 9 deletions(-)
>
> diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
> index cae6637..7e662f5 100644
> --- a/target-xtensa/cpu.h
> +++ b/target-xtensa/cpu.h
> @@ -108,6 +108,8 @@ enum {
>  enum {
>     SAR = 3,
>     SCOMPARE1 = 12,
> +    WINDOW_BASE = 72,
> +    WINDOW_START = 73,
>     EPC1 = 177,
>     DEPC = 192,
>     EXCSAVE1 = 209,
> @@ -134,6 +136,8 @@ enum {
>
>  #define PS_WOE 0x40000
>
> +#define MAX_NAREG 64
> +
>  enum {
>     /* Static vectors */
>     EXC_RESET,
> @@ -185,6 +189,7 @@ enum {
>  typedef struct XtensaConfig {
>     const char *name;
>     uint64_t options;
> +    unsigned nareg;
>     int excm_level;
>     int ndepc;
>     uint32_t exception_vector[EXC_MAX];
> @@ -196,6 +201,7 @@ typedef struct CPUXtensaState {
>     uint32_t pc;
>     uint32_t sregs[256];
>     uint32_t uregs[256];
> +    uint32_t phys_regs[MAX_NAREG];
>
>     int exception_taken;
>
> @@ -214,6 +220,8 @@ int cpu_xtensa_exec(CPUXtensaState *s);
>  void do_interrupt(CPUXtensaState *s);
>  int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
>  void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
> +void xtensa_sync_window_from_phys(CPUState *env);
> +void xtensa_sync_phys_from_window(CPUState *env);
>
>  #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
>
> diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
> index 44ebb9f..4f86934 100644
> --- a/target-xtensa/helper.c
> +++ b/target-xtensa/helper.c
> @@ -45,6 +45,7 @@ static const XtensaConfig core_config[] = {
>     {
>         .name = "sample-xtensa-core",
>         .options = -1,
> +        .nareg = 64,
>         .ndepc = 1,
>         .excm_level = 16,
>         .exception_vector = {
> diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
> index 6329c43..0971fde 100644
> --- a/target-xtensa/helpers.h
> +++ b/target-xtensa/helpers.h
> @@ -5,5 +5,13 @@ DEF_HELPER_2(exception_cause, void, i32, i32)
>  DEF_HELPER_3(exception_cause_vaddr, void, i32, i32, i32)
>  DEF_HELPER_1(nsa, i32, i32)
>  DEF_HELPER_1(nsau, i32, i32)
> +DEF_HELPER_1(wsr_windowbase, void, i32)
> +DEF_HELPER_3(entry, void, i32, i32, i32)
> +DEF_HELPER_1(retw, i32, i32)
> +DEF_HELPER_1(rotw, void, i32)
> +DEF_HELPER_2(window_check, void, i32, i32)
> +DEF_HELPER_0(restore_owb, void)
> +DEF_HELPER_1(movsp, void, i32)
> +DEF_HELPER_0(dump_state, void)
>
>  #include "def-helper.h"
> diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
> index 794a834..7f75422 100644
> --- a/target-xtensa/op_helper.c
> +++ b/target-xtensa/op_helper.c
> @@ -100,3 +100,188 @@ uint32_t HELPER(nsau)(uint32_t v)
>  {
>     return v ? clz32(v) : 32;
>  }
> +
> +static void copy_window_from_phys(CPUState *env,
> +        uint32_t window, uint32_t phys, uint32_t n)
> +{
> +    assert(phys < env->config->nareg);
> +    if (phys + n <= env->config->nareg) {
> +        memcpy(env->regs + window, env->phys_regs + phys,
> +                n * sizeof(uint32_t));
> +    } else {
> +        uint32_t n1 = env->config->nareg - phys;
> +        memcpy(env->regs + window, env->phys_regs + phys,
> +                n1 * sizeof(uint32_t));
> +        memcpy(env->regs + window + n1, env->phys_regs,
> +                (n - n1) * sizeof(uint32_t));
> +    }
> +}
> +
> +static void copy_phys_from_window(CPUState *env,
> +        uint32_t phys, uint32_t window, uint32_t n)
> +{
> +    assert(phys < env->config->nareg);
> +    if (phys + n <= env->config->nareg) {
> +        memcpy(env->phys_regs + phys, env->regs + window,
> +                n * sizeof(uint32_t));
> +    } else {
> +        uint32_t n1 = env->config->nareg - phys;
> +        memcpy(env->phys_regs + phys, env->regs + window,
> +                n1 * sizeof(uint32_t));
> +        memcpy(env->phys_regs, env->regs + window + n1,
> +                (n - n1) * sizeof(uint32_t));
> +    }
> +}
> +
> +
> +#define WINDOWBASE_BOUND(a) ((a) & (env->config->nareg / 4 - 1))
> +#define WINDOW_BOUND(a) ((a) & (env->config->nareg - 1))

'env' could be a parameter to the macro, though inline functions are
preferred over macros these days.

> +#define WINDOWSTART_BIT(a) (1 << WINDOWBASE_BOUND(a))
> +
> +void xtensa_sync_window_from_phys(CPUState *env)
> +{
> +    copy_window_from_phys(env, 0, env->sregs[WINDOW_BASE] * 4, 16);
> +}
> +
> +void xtensa_sync_phys_from_window(CPUState *env)
> +{
> +    copy_phys_from_window(env, env->sregs[WINDOW_BASE] * 4, 0, 16);
> +}
> +
> +static void rotate_window_abs(uint32_t position)
> +{
> +    xtensa_sync_phys_from_window(env);
> +    env->sregs[WINDOW_BASE] = WINDOWBASE_BOUND(position);
> +    xtensa_sync_window_from_phys(env);
> +}
> +
> +static void rotate_window(uint32_t delta)
> +{
> +    rotate_window_abs(env->sregs[WINDOW_BASE] + delta);
> +}
> +
> +void HELPER(wsr_windowbase)(uint32_t v)
> +{
> +    rotate_window_abs(v);
> +}
> +
> +void HELPER(entry)(uint32_t pc, uint32_t s, uint32_t imm)
> +{
> +    int callinc = (env->sregs[PS] & PS_CALLINC) >> PS_CALLINC_SHIFT;
> +    if (s > 3 || ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) != 0) {
> +        qemu_log("Illegal entry instruction(pc = %08x), PS = %08x\n",
> +                pc, env->sregs[PS]);
> +        HELPER(exception_cause)(pc, ILLEGAL_INSTRUCTION_CAUSE);
> +    } else {
> +        env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - (imm << 3);
> +        rotate_window(callinc);
> +        env->sregs[WINDOW_START] |= WINDOWSTART_BIT(env->sregs[WINDOW_BASE]);
> +    }
> +}
> +
> +void HELPER(window_check)(uint32_t pc, uint32_t w)
> +{
> +    uint32_t windowbase = WINDOWBASE_BOUND(env->sregs[WINDOW_BASE]);
> +    uint32_t windowstart = env->sregs[WINDOW_START];
> +    uint32_t m, n;
> +
> +    if ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) {
> +        return;
> +    }
> +
> +    for (n = 1; ; ++n) {
> +        if (n > w) {
> +            return;
> +        }
> +        if (windowstart & WINDOWSTART_BIT(windowbase + n)) {
> +            break;
> +        }
> +    }
> +
> +    m = WINDOWBASE_BOUND(windowbase + n);
> +    rotate_window(n);
> +    env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) |
> +        (windowbase << PS_OWB_SHIFT) | PS_EXCM;
> +    env->sregs[EPC1] = env->pc = pc;
> +
> +    if (windowstart & WINDOWSTART_BIT(m + 1)) {
> +        HELPER(exception)(EXC_WINDOW_OVERFLOW4);
> +    } else if (windowstart & WINDOWSTART_BIT(m + 2)) {
> +        HELPER(exception)(EXC_WINDOW_OVERFLOW8);
> +    } else {
> +        HELPER(exception)(EXC_WINDOW_OVERFLOW12);
> +    }
> +}
> +
> +uint32_t HELPER(retw)(uint32_t pc)
> +{
> +    int n = (env->regs[0] >> 30) & 0x3;
> +    int m = 0;
> +    uint32_t windowbase = WINDOWBASE_BOUND(env->sregs[WINDOW_BASE]);
> +    uint32_t windowstart = env->sregs[WINDOW_START];
> +    uint32_t ret_pc = 0;
> +
> +    if (windowstart & WINDOWSTART_BIT(windowbase - 1)) {
> +        m = 1;
> +    } else if (windowstart & WINDOWSTART_BIT(windowbase - 2)) {
> +        m = 2;
> +    } else if (windowstart & WINDOWSTART_BIT(windowbase - 3)) {
> +        m = 3;
> +    }
> +
> +    if (n == 0 || (m != 0 && m != n) ||
> +            ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) != 0) {
> +        qemu_log("Illegal retw instruction(pc = %08x), "
> +                "PS = %08x, m = %d, n = %d\n",
> +                pc, env->sregs[PS], m, n);
> +        HELPER(exception_cause)(pc, ILLEGAL_INSTRUCTION_CAUSE);
> +    } else {
> +        int owb = windowbase;
> +
> +        ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff);
> +
> +        rotate_window(-n);
> +        if (windowstart & WINDOWSTART_BIT(env->sregs[WINDOW_BASE])) {
> +            env->sregs[WINDOW_START] &= ~WINDOWSTART_BIT(owb);
> +        } else {
> +            /* window underflow */
> +            env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) |
> +                (windowbase << PS_OWB_SHIFT) | PS_EXCM;
> +            env->sregs[EPC1] = env->pc = pc;
> +
> +            if (n == 1) {
> +                HELPER(exception)(EXC_WINDOW_UNDERFLOW4);
> +            } else if (n == 2) {
> +                HELPER(exception)(EXC_WINDOW_UNDERFLOW8);
> +            } else if (n == 3) {
> +                HELPER(exception)(EXC_WINDOW_UNDERFLOW12);
> +            }
> +        }
> +    }
> +    return ret_pc;
> +}
> +
> +void HELPER(rotw)(uint32_t imm4)
> +{
> +    rotate_window(imm4);
> +}
> +
> +void HELPER(restore_owb)(void)
> +{
> +    rotate_window_abs((env->sregs[PS] & PS_OWB) >> PS_OWB_SHIFT);
> +}
> +
> +void HELPER(movsp)(uint32_t pc)
> +{
> +    if ((env->sregs[WINDOW_START] &
> +            (WINDOWSTART_BIT(env->sregs[WINDOW_BASE] - 3) |
> +             WINDOWSTART_BIT(env->sregs[WINDOW_BASE] - 2) |
> +             WINDOWSTART_BIT(env->sregs[WINDOW_BASE] - 1))) == 0) {
> +        HELPER(exception_cause)(pc, ALLOCA_CAUSE);
> +    }
> +}
> +
> +void HELPER(dump_state)(void)
> +{
> +    cpu_dump_state(env, stderr, fprintf, 0);
> +}
> diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
> index de5f947..de393ff 100644
> --- a/target-xtensa/translate.c
> +++ b/target-xtensa/translate.c
> @@ -67,6 +67,8 @@ static TCGv_i32 cpu_UR[256];
>  static const char * const sregnames[256] = {
>     [SAR] = "SAR",
>     [SCOMPARE1] = "SCOMPARE1",
> +    [WINDOW_BASE] = "WINDOW_BASE",
> +    [WINDOW_START] = "WINDOW_START",
>     [EPC1] = "EPC1",
>     [DEPC] = "DEPC",
>     [EXCSAVE1] = "EXCSAVE1",
> @@ -217,6 +219,34 @@ static void gen_jumpi(DisasContext *dc, uint32_t dest, int slot)
>     tcg_temp_free(tmp);
>  }
>
> +static void gen_callw_slot(DisasContext *dc, int _callinc, TCGv_i32 dest,
> +        int slot)
> +{
> +    TCGv_i32 callinc = tcg_const_i32(_callinc);
> +
> +    tcg_gen_deposit_i32(cpu_SR[PS], cpu_SR[PS],
> +            callinc, PS_CALLINC_SHIFT, PS_CALLINC_LEN);
> +    tcg_temp_free(callinc);
> +    tcg_gen_movi_i32(cpu_R[_callinc << 2],
> +            (_callinc << 30) | (dc->next_pc & 0x3fffffff));
> +    gen_jump_slot(dc, dest, slot);
> +}
> +
> +static void gen_callw(DisasContext *dc, int callinc, TCGv_i32 dest)
> +{
> +    gen_callw_slot(dc, callinc, dest, -1);
> +}
> +
> +static void gen_callwi(DisasContext *dc, int callinc, uint32_t dest, int slot)
> +{
> +    TCGv_i32 tmp = tcg_const_i32(dest);
> +    if (((dc->pc ^ dest) & TARGET_PAGE_MASK) != 0) {
> +        slot = -1;
> +    }
> +    gen_callw_slot(dc, callinc, tmp, slot);
> +    tcg_temp_free(tmp);
> +}
> +
>  static void gen_brcond(DisasContext *dc, TCGCond cond,
>         TCGv_i32 t0, TCGv_i32 t1, uint32_t offset)
>  {
> @@ -263,6 +293,11 @@ static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
>     dc->sar_m32_5bit = false;
>  }
>
> +static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
> +{
> +    gen_helper_wsr_windowbase(v);
> +}
> +
>  static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
>  {
>     uint32_t mask = PS_WOE | PS_CALLINC | PS_OWB |
> @@ -281,6 +316,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
>     static void (* const wsr_handler[256])(DisasContext *dc,
>             uint32_t sr, TCGv_i32 v) = {
>         [SAR] = gen_wsr_sar,
> +        [WINDOW_BASE] = gen_wsr_windowbase,
>         [PS] = gen_wsr_ps,
>     };
>
> @@ -429,7 +465,12 @@ static void disas_xtensa_insn(DisasContext *dc)
>
>                         case 1: /*RETWw*/
>                             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
> -                            TBD();
> +                            {
> +                                TCGv_i32 tmp = tcg_const_i32(dc->pc);
> +                                gen_helper_retw(tmp, tmp);
> +                                gen_jump(dc, tmp);
> +                                tcg_temp_free(tmp);
> +                            }
>                             break;
>
>                         case 3: /*reserved*/
> @@ -454,7 +495,13 @@ static void disas_xtensa_insn(DisasContext *dc)
>                         case 2: /*CALLX8w*/
>                         case 3: /*CALLX12w*/
>                             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
> -                            TBD();
> +                            {
> +                                TCGv_i32 tmp = tcg_temp_new_i32();
> +
> +                                tcg_gen_mov_i32(tmp, cpu_R[CALLX_S]);
> +                                gen_callw(dc, CALLX_N, tmp);
> +                                tcg_temp_free(tmp);
> +                            }
>                             break;
>                         }
>                         break;
> @@ -463,7 +510,12 @@ static void disas_xtensa_insn(DisasContext *dc)
>
>                 case 1: /*MOVSPw*/
>                     HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
> -                    TBD();
> +                    {
> +                        TCGv_i32 pc = tcg_const_i32(dc->pc);
> +                        gen_helper_movsp(pc);
> +                        tcg_gen_mov_i32(cpu_R[RRR_T], cpu_R[RRR_S]);
> +                        tcg_temp_free(pc);
> +                    }
>                     break;
>
>                 case 2: /*SYNC*/
> @@ -523,7 +575,27 @@ static void disas_xtensa_insn(DisasContext *dc)
>                         case 4: /*RFWOw*/
>                         case 5: /*RFWUw*/
>                             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
> -                            TBD();
> +                            gen_check_privilege(dc);
> +                            {
> +                                TCGv_i32 tmp = tcg_const_i32(1);
> +
> +                                tcg_gen_andi_i32(
> +                                        cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);
> +                                tcg_gen_shl_i32(tmp, tmp, cpu_SR[WINDOW_BASE]);
> +
> +                                if (RRR_S == 4) {
> +                                    tcg_gen_andc_i32(cpu_SR[WINDOW_START],
> +                                            cpu_SR[WINDOW_START], tmp);
> +                                } else {
> +                                    tcg_gen_or_i32(cpu_SR[WINDOW_START],
> +                                            cpu_SR[WINDOW_START], tmp);
> +                                }
> +
> +                                gen_helper_restore_owb();
> +                                gen_jump(dc, cpu_SR[EPC1]);
> +
> +                                tcg_temp_free(tmp);
> +                            }
>                             break;
>
>                         default: /*reserved*/
> @@ -670,7 +742,13 @@ static void disas_xtensa_insn(DisasContext *dc)
>
>                 case 8: /*ROTWw*/
>                     HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
> -                    TBD();
> +                    gen_check_privilege(dc);
> +                    {
> +                        TCGv_i32 tmp = tcg_const_i32(
> +                                RRR_T | ((RRR_T & 8) ? 0xfffffff0 : 0));
> +                        gen_helper_rotw(tmp);
> +                        tcg_temp_free(tmp);
> +                    }
>                     break;
>
>                 case 14: /*NSAu*/
> @@ -1129,7 +1207,35 @@ static void disas_xtensa_insn(DisasContext *dc)
>             break;
>
>         case 9: /*LSC4*/
> -            TBD();
> +            switch (OP2) {
> +            case 0: /*L32E*/
> +                HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
> +                gen_check_privilege(dc);
> +                {
> +                    TCGv_i32 addr = tcg_temp_new_i32();
> +                    tcg_gen_addi_i32(addr, cpu_R[RRR_S],
> +                            (0xffffffc0 | (RRR_R << 2)));
> +                    tcg_gen_qemu_ld32u(cpu_R[RRR_T], addr, dc->ring);
> +                    tcg_temp_free(addr);
> +                }
> +                break;
> +
> +            case 4: /*S32E*/
> +                HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
> +                gen_check_privilege(dc);
> +                {
> +                    TCGv_i32 addr = tcg_temp_new_i32();
> +                    tcg_gen_addi_i32(addr, cpu_R[RRR_S],
> +                            (0xffffffc0 | (RRR_R << 2)));
> +                    tcg_gen_qemu_st32(cpu_R[RRR_T], addr, dc->ring);
> +                    tcg_temp_free(addr);
> +                }
> +                break;
> +
> +            default:
> +                RESERVED();
> +                break;
> +            }
>             break;
>
>         case 10: /*FP0*/
> @@ -1368,7 +1474,8 @@ static void disas_xtensa_insn(DisasContext *dc)
>         case 2: /*CALL8w*/
>         case 3: /*CALL12w*/
>             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
> -            TBD();
> +            gen_callwi(dc, CALL_N,
> +                    (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0);
>             break;
>         }
>         break;
> @@ -1411,7 +1518,15 @@ static void disas_xtensa_insn(DisasContext *dc)
>             switch (BRI8_M) {
>             case 0: /*ENTRYw*/
>                 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
> -                TBD();
> +                {
> +                    TCGv_i32 pc = tcg_const_i32(dc->pc);
> +                    TCGv_i32 s = tcg_const_i32(BRI12_S);
> +                    TCGv_i32 imm = tcg_const_i32(BRI12_IMM12);
> +                    gen_helper_entry(pc, s, imm);
> +                    tcg_temp_free(imm);
> +                    tcg_temp_free(s);
> +                    tcg_temp_free(pc);
> +                }
>                 break;
>
>             case 1: /*B1*/
> @@ -1576,7 +1691,12 @@ static void disas_xtensa_insn(DisasContext *dc)
>
>             case 1: /*RETW.Nn*/
>                 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
> -                TBD();
> +                {
> +                    TCGv_i32 tmp = tcg_const_i32(dc->pc);
> +                    gen_helper_retw(tmp, tmp);
> +                    gen_jump(dc, tmp);
> +                    tcg_temp_free(tmp);
> +                }
>                 break;
>
>             case 2: /*BREAK.Nn*/
> @@ -1747,6 +1867,12 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
>     for (i = 0; i < 16; ++i)
>         cpu_fprintf(f, "A%02d=%08x%c", i, env->regs[i],
>                 (i % 4) == 3 ? '\n' : ' ');
> +
> +    cpu_fprintf(f, "\n");
> +
> +    for (i = 0; i < env->config->nareg; ++i)

Braces.

> +        cpu_fprintf(f, "AR%02d=%08x%c", i, env->phys_regs[i],
> +                (i % 4) == 3 ? '\n' : ' ');
>  }
>
>  void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
> --
> 1.7.6
>
>
>

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

* Re: [Qemu-devel] [PATCH v4 22/32] target-xtensa: implement unaligned exception option
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 22/32] target-xtensa: implement unaligned exception option Max Filippov
@ 2011-09-04 18:28   ` Blue Swirl
  0 siblings, 0 replies; 47+ messages in thread
From: Blue Swirl @ 2011-09-04 18:28 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On Thu, Sep 1, 2011 at 8:45 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> See ISA, 4.4.4 for details.
>
> Correct (aligned as per ISA) address for unaligned access is generated
> in case this option is not enabled.
>
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
> ---
>  target-xtensa/helper.c    |    4 ++-
>  target-xtensa/op_helper.c |   26 ++++++++++++++++++++++++
>  target-xtensa/translate.c |   47 ++++++++++++++++++++++++++++++++++++++++++--
>  3 files changed, 73 insertions(+), 4 deletions(-)
>
> diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
> index 074207f..bcd6c77 100644
> --- a/target-xtensa/helper.c
> +++ b/target-xtensa/helper.c
> @@ -45,7 +45,9 @@ void cpu_reset(CPUXtensaState *env)
>  static const XtensaConfig core_config[] = {
>     {
>         .name = "sample-xtensa-core",
> -        .options = -1,
> +        .options = -1 ^
> +            (XTENSA_OPTION_BIT(XTENSA_OPTION_HW_ALIGNMENT) |
> +             XTENSA_OPTION_BIT(XTENSA_OPTION_MMU)),
>         .nareg = 64,
>         .ndepc = 1,
>         .excm_level = 16,
> diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
> index 26d2d2e..8577f5d 100644
> --- a/target-xtensa/op_helper.c
> +++ b/target-xtensa/op_helper.c
> @@ -30,6 +30,10 @@
>  #include "helpers.h"
>  #include "host-utils.h"
>
> +static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
> +        void *retaddr);
> +
> +#define ALIGNED_ONLY
>  #define MMUSUFFIX _mmu
>
>  #define SHIFT 0
> @@ -44,6 +48,28 @@
>  #define SHIFT 3
>  #include "softmmu_template.h"
>
> +static void do_restore_state(void *pc_ptr)
> +{
> +    TranslationBlock *tb;
> +    uint32_t pc = (uint32_t)(intptr_t)pc_ptr;
> +
> +    tb = tb_find_pc(pc);
> +    if (tb) {
> +        cpu_restore_state(tb, env, pc);
> +    }
> +}
> +
> +static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
> +        void *retaddr)
> +{
> +    if (xtensa_option_enabled(env->config, XTENSA_OPTION_UNALIGNED_EXCEPTION) &&
> +            !xtensa_option_enabled(env->config, XTENSA_OPTION_HW_ALIGNMENT)) {
> +        do_restore_state(retaddr);
> +        HELPER(exception_cause_vaddr)(
> +                env->pc, LOAD_STORE_ALIGNMENT_CAUSE, addr);
> +    }
> +}
> +
>  void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
>  {
>     tlb_set_page(cpu_single_env,
> diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
> index 7bcbe4f..ad2b699 100644
> --- a/target-xtensa/translate.c
> +++ b/target-xtensa/translate.c
> @@ -203,6 +203,16 @@ static void gen_exception_cause(DisasContext *dc, uint32_t cause)
>     tcg_temp_free(_cause);
>  }
>
> +static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
> +        TCGv_i32 vaddr)
> +{
> +    TCGv_i32 _pc = tcg_const_i32(dc->pc);
> +    TCGv_i32 _cause = tcg_const_i32(cause);

Underscores.

> +    gen_helper_exception_cause_vaddr(_pc, _cause, vaddr);
> +    tcg_temp_free(_pc);
> +    tcg_temp_free(_cause);
> +}
> +
>  static void gen_check_privilege(DisasContext *dc)
>  {
>     if (dc->cring) {
> @@ -397,6 +407,23 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
>     }
>  }
>
> +static void gen_load_store_alignment(DisasContext *dc, int shift,
> +        TCGv_i32 addr, bool no_hw_alignment)
> +{
> +    if (!option_enabled(dc, XTENSA_OPTION_UNALIGNED_EXCEPTION)) {
> +        tcg_gen_andi_i32(addr, addr, ~0 << shift);
> +    } else if (option_enabled(dc, XTENSA_OPTION_HW_ALIGNMENT) &&
> +            no_hw_alignment) {
> +        int label = gen_new_label();
> +        TCGv_i32 tmp = tcg_temp_new_i32();
> +        tcg_gen_andi_i32(tmp, addr, ~(~0 << shift));
> +        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
> +        gen_exception_cause_vaddr(dc, LOAD_STORE_ALIGNMENT_CAUSE, addr);
> +        gen_set_label(label);
> +        tcg_temp_free(tmp);
> +    }
> +}
> +
>  static void disas_xtensa_insn(DisasContext *dc)
>  {
>  #define HAS_OPTION(opt) do { \
> @@ -1339,6 +1366,9 @@ static void disas_xtensa_insn(DisasContext *dc)
>  #define gen_load_store(type, shift) do { \
>             TCGv_i32 addr = tcg_temp_new_i32(); \
>             tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \
> +            if (shift) { \
> +                gen_load_store_alignment(dc, shift, addr, false); \
> +            } \
>             tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
>             tcg_temp_free(addr); \
>         } while (0)
> @@ -1468,6 +1498,7 @@ static void disas_xtensa_insn(DisasContext *dc)
>         case 9: /*L16SI*/
>             gen_load_store(ld16s, 1);
>             break;
> +#undef gen_load_store
>
>         case 10: /*MOVI*/
>             tcg_gen_movi_i32(cpu_R[RRI8_T],
> @@ -1475,9 +1506,17 @@ static void disas_xtensa_insn(DisasContext *dc)
>                     ((RRI8_S & 0x8) ? 0xfffff000 : 0));
>             break;
>
> +#define gen_load_store_no_hw_align(type) do { \
> +            TCGv_i32 addr = tcg_temp_local_new_i32(); \
> +            tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); \
> +            gen_load_store_alignment(dc, 2, addr, true); \
> +            tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
> +            tcg_temp_free(addr); \
> +        } while (0)
> +
>         case 11: /*L32AIy*/
>             HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
> -            gen_load_store(ld32u, 2); /*TODO acquire?*/
> +            gen_load_store_no_hw_align(ld32u); /*TODO acquire?*/
>             break;
>
>         case 12: /*ADDI*/
> @@ -1497,6 +1536,7 @@ static void disas_xtensa_insn(DisasContext *dc)
>
>                 tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]);
>                 tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
> +                gen_load_store_alignment(dc, 2, addr, true);
>                 tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, dc->cring);
>                 tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T],
>                         cpu_SR[SCOMPARE1], label);
> @@ -1511,15 +1551,15 @@ static void disas_xtensa_insn(DisasContext *dc)
>
>         case 15: /*S32RIy*/
>             HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
> -            gen_load_store(st32, 2); /*TODO release?*/
> +            gen_load_store_no_hw_align(st32); /*TODO release?*/
>             break;
> +#undef gen_load_store_no_hw_align
>
>         default: /*reserved*/
>             RESERVED();
>             break;
>         }
>         break;
> -#undef gen_load_store
>
>     case 3: /*LSCIp*/
>         HAS_OPTION(XTENSA_OPTION_COPROCESSOR);
> @@ -1725,6 +1765,7 @@ static void disas_xtensa_insn(DisasContext *dc)
>  #define gen_narrow_load_store(type) do { \
>             TCGv_i32 addr = tcg_temp_new_i32(); \
>             tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
> +            gen_load_store_alignment(dc, 2, addr, false); \
>             tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, dc->cring); \
>             tcg_temp_free(addr); \
>         } while (0)
> --
> 1.7.6
>
>
>

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

* Re: [Qemu-devel] [PATCH v4 29/32] target-xtensa: implement memory protection options
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 29/32] target-xtensa: implement memory protection options Max Filippov
@ 2011-09-04 18:32   ` Blue Swirl
  0 siblings, 0 replies; 47+ messages in thread
From: Blue Swirl @ 2011-09-04 18:32 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On Thu, Sep 1, 2011 at 8:45 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> - TLB opcode group;
> - region protection option (ISA, 4.6.3);
> - region translation option (ISA, 4.6.4);
> - MMU option (ISA, 4.6.5).
>
> Cache control attribute bits are not used by this implementation.
>
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
> ---
>  target-xtensa/cpu.h       |   56 ++++++++-
>  target-xtensa/helper.c    |  340 ++++++++++++++++++++++++++++++++++++++++++++-
>  target-xtensa/helpers.h   |    7 +
>  target-xtensa/op_helper.c |  301 +++++++++++++++++++++++++++++++++++++++-
>  target-xtensa/translate.c |   91 ++++++++++++-
>  5 files changed, 782 insertions(+), 13 deletions(-)
>
> diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
> index 93e17d1..05948f1 100644
> --- a/target-xtensa/cpu.h
> +++ b/target-xtensa/cpu.h
> @@ -114,6 +114,10 @@ enum {
>     SCOMPARE1 = 12,
>     WINDOW_BASE = 72,
>     WINDOW_START = 73,
> +    PTEVADDR = 83,
> +    RASID = 90,
> +    ITLBCFG = 91,
> +    DTLBCFG = 92,
>     EPC1 = 177,
>     DEPC = 192,
>     EPS2 = 194,
> @@ -154,6 +158,9 @@ enum {
>  #define MAX_NLEVEL 6
>  #define MAX_NNMI 1
>  #define MAX_NCCOMPARE 3
> +#define MAX_TLB_WAY_SIZE 8
> +
> +#define REGION_PAGE_MASK 0xe0000000
>
>  enum {
>     /* Static vectors */
> @@ -214,6 +221,21 @@ typedef enum {
>     INTTYPE_MAX
>  } interrupt_type;
>
> +typedef struct xtensa_tlb_entry {
> +    uint32_t vaddr;
> +    uint32_t paddr;
> +    uint8_t asid;
> +    uint8_t attr;
> +    bool variable;
> +} xtensa_tlb_entry;
> +
> +typedef struct xtensa_tlb {
> +    unsigned nways;
> +    const unsigned way_size[10];
> +    bool varway56;
> +    unsigned nrefillentries;
> +} xtensa_tlb;
> +
>  typedef struct XtensaGdbReg {
>     int targno;
>     int type;
> @@ -248,6 +270,9 @@ typedef struct XtensaConfig {
>     unsigned nccompare;
>     uint32_t timerint[MAX_NCCOMPARE];
>     uint32_t clock_freq_khz;
> +
> +    xtensa_tlb itlb;
> +    xtensa_tlb dtlb;
>  } XtensaConfig;
>
>  typedef struct CPUXtensaState {
> @@ -258,6 +283,10 @@ typedef struct CPUXtensaState {
>     uint32_t uregs[256];
>     uint32_t phys_regs[MAX_NAREG];
>
> +    xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
> +    xtensa_tlb_entry dtlb[10][MAX_TLB_WAY_SIZE];
> +    unsigned autorefill_idx;
> +
>     int pending_irq_level; /* level of last raised IRQ */
>     void **irq_inputs;
>     QEMUTimer *ccompare_timer;
> @@ -287,12 +316,29 @@ int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
>  void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
>  void xtensa_sync_window_from_phys(CPUState *env);
>  void xtensa_sync_phys_from_window(CPUState *env);
> +uint32_t xtensa_tlb_get_addr_mask(const CPUState *env, bool dtlb, uint32_t way);
> +void split_tlb_entry_spec_way(const CPUState *env, uint32_t v, bool dtlb,
> +        uint32_t *vpn, uint32_t wi, uint32_t *ei);
> +int xtensa_tlb_lookup(const CPUState *env, uint32_t addr, bool dtlb,
> +        uint32_t *_wi, uint32_t *_ei, uint8_t *_ring);
> +void xtensa_tlb_set_entry(CPUState *env, bool dtlb,
> +        unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
> +int xtensa_get_physical_addr(CPUState *env,
> +        uint32_t vaddr, int is_write, int mmu_idx,
> +        uint32_t *paddr, uint32_t *page_size, unsigned *access);
> +
>
>  #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
>
> +static inline bool xtensa_option_bits_enabled(const XtensaConfig *config,
> +        uint64_t opt)
> +{
> +    return (config->options & opt) != 0;
> +}
> +
>  static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt)
>  {
> -    return (config->options & XTENSA_OPTION_BIT(opt)) != 0;
> +    return xtensa_option_bits_enabled(config, XTENSA_OPTION_BIT(opt));
>  }
>
>  static inline int xtensa_get_cintlevel(const CPUState *env)
> @@ -323,6 +369,14 @@ static inline int xtensa_get_cring(const CPUState *env)
>     }
>  }
>
> +static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUState *env,
> +        bool dtlb, unsigned wi, unsigned ei)
> +{
> +    return dtlb ?
> +        env->dtlb[wi] + ei :
> +        env->itlb[wi] + ei;
> +}
> +
>  /* MMU modes definitions */
>  #define MMU_MODE0_SUFFIX _ring0
>  #define MMU_MODE1_SUFFIX _ring1
> diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
> index 487847c..00571e8 100644
> --- a/target-xtensa/helper.c
> +++ b/target-xtensa/helper.c
> @@ -38,6 +38,8 @@
>         a1, a2, a3, a4, a5, a6) \
>     { .targno = (_targno), .type = (typ), .group = (_group) },
>
> +static void reset_mmu(CPUState *env);
> +
>  void cpu_reset(CPUXtensaState *env)
>  {
>     env->exception_taken = 0;
> @@ -48,6 +50,7 @@ void cpu_reset(CPUXtensaState *env)
>     env->sregs[VECBASE] = env->config->vecbase;
>
>     env->pending_irq_level = 0;
> +    reset_mmu(env);
>  }
>
>  static const XtensaConfig core_config[] = {
> @@ -150,7 +153,19 @@ void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf)
>
>  target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
>  {
> -    return addr;
> +    uint32_t paddr;
> +    uint32_t page_size;
> +    unsigned access;
> +
> +    if (0 == xtensa_get_physical_addr(env, addr, 0, 0,
> +                &paddr, &page_size, &access)) {

This order in comparison looks alien.

> +        return paddr;
> +    }
> +    if (0 == xtensa_get_physical_addr(env, addr, 2, 0,
> +                &paddr, &page_size, &access)) {
> +        return paddr;
> +    }
> +    return ~0;
>  }
>
>  static uint32_t relocated_vector(CPUState *env, uint32_t vector)
> @@ -255,3 +270,326 @@ void do_interrupt(CPUState *env)
>     }
>     check_interrupts(env);
>  }
> +
> +static void reset_tlb_mmu_all_ways(CPUState *env,
> +        const xtensa_tlb *tlb, xtensa_tlb_entry entry[][MAX_TLB_WAY_SIZE])
> +{
> +    unsigned wi, ei;
> +
> +    for (wi = 0; wi < tlb->nways; ++wi) {
> +        for (ei = 0; ei < tlb->way_size[wi]; ++ei) {
> +            entry[wi][ei].asid = 0;
> +            entry[wi][ei].variable = true;
> +        }
> +    }
> +}
> +
> +static void reset_tlb_mmu_ways56(CPUState *env,
> +        const xtensa_tlb *tlb, xtensa_tlb_entry entry[][MAX_TLB_WAY_SIZE])
> +{
> +    if (!tlb->varway56) {
> +        static const xtensa_tlb_entry way5[] = {
> +            {
> +                .vaddr = 0xd0000000,
> +                .paddr = 0,
> +                .asid = 1,
> +                .attr = 7,
> +                .variable = false,
> +            }, {
> +                .vaddr = 0xd8000000,
> +                .paddr = 0,
> +                .asid = 1,
> +                .attr = 3,
> +                .variable = false,
> +            }
> +        };
> +        static const xtensa_tlb_entry way6[] = {
> +            {
> +                .vaddr = 0xe0000000,
> +                .paddr = 0xf0000000,
> +                .asid = 1,
> +                .attr = 7,
> +                .variable = false,
> +            }, {
> +                .vaddr = 0xf0000000,
> +                .paddr = 0xf0000000,
> +                .asid = 1,
> +                .attr = 3,
> +                .variable = false,
> +            }
> +        };
> +        memcpy(entry[5], way5, sizeof(way5));
> +        memcpy(entry[6], way6, sizeof(way6));
> +    } else {
> +        uint32_t ei;
> +        for (ei = 0; ei < 8; ++ei) {
> +            entry[6][ei].vaddr = ei << 29;
> +            entry[6][ei].paddr = ei << 29;
> +            entry[6][ei].asid = 1;
> +            entry[6][ei].attr = 2;
> +        }
> +    }
> +}
> +
> +static void reset_tlb_region_way0(CPUState *env,
> +        xtensa_tlb_entry entry[][MAX_TLB_WAY_SIZE])
> +{
> +    unsigned ei;
> +
> +    for (ei = 0; ei < 8; ++ei) {
> +        entry[0][ei].vaddr = ei << 29;
> +        entry[0][ei].paddr = ei << 29;
> +        entry[0][ei].asid = 1;
> +        entry[0][ei].attr = 2;
> +        entry[0][ei].variable = true;
> +    }
> +}
> +
> +static void reset_mmu(CPUState *env)
> +{
> +    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
> +        env->sregs[RASID] = 0x04030201;
> +        env->sregs[ITLBCFG] = 0;
> +        env->sregs[DTLBCFG] = 0;
> +        env->autorefill_idx = 0;
> +        reset_tlb_mmu_all_ways(env, &env->config->itlb, env->itlb);
> +        reset_tlb_mmu_all_ways(env, &env->config->dtlb, env->dtlb);
> +        reset_tlb_mmu_ways56(env, &env->config->itlb, env->itlb);
> +        reset_tlb_mmu_ways56(env, &env->config->dtlb, env->dtlb);
> +    } else {
> +        reset_tlb_region_way0(env, env->itlb);
> +        reset_tlb_region_way0(env, env->dtlb);
> +    }
> +}
> +
> +static unsigned get_ring(const CPUState *env, uint8_t asid)
> +{
> +    unsigned i;
> +    for (i = 0; i < 4; ++i) {
> +        if (((env->sregs[RASID] >> i * 8) & 0xff) == asid) {
> +            return i;
> +        }
> +    }
> +    return 0xff;
> +}
> +
> +/*!
> + * Lookup xtensa TLB for the given virtual address.
> + * See ISA, 4.6.2.2
> + *
> + * \param _wi: [out] way index
> + * \param _ei: [out] entry index
> + * \param _ring: [out] access ring
> + * \return 0 if ok, exception cause code otherwise
> + */
> +int xtensa_tlb_lookup(const CPUState *env, uint32_t addr, bool dtlb,
> +        uint32_t *_wi, uint32_t *_ei, uint8_t *_ring)

Underscores.

> +{
> +    const xtensa_tlb *tlb = dtlb ?
> +        &env->config->dtlb : &env->config->itlb;
> +    const xtensa_tlb_entry (*entry)[MAX_TLB_WAY_SIZE] = dtlb ?
> +        env->dtlb : env->itlb;
> +
> +    int nhits = 0;
> +    unsigned wi;
> +
> +    for (wi = 0; wi < tlb->nways; ++wi) {
> +        uint32_t vpn;
> +        uint32_t ei;
> +        split_tlb_entry_spec_way(env, addr, dtlb, &vpn, wi, &ei);
> +        if (entry[wi][ei].vaddr == vpn && entry[wi][ei].asid) {
> +            unsigned ring = get_ring(env, entry[wi][ei].asid);
> +            if (ring < 4) {
> +                if (++nhits > 1) {
> +                    return dtlb ?
> +                        LOAD_STORE_TLB_MULTI_HIT_CAUSE :
> +                        INST_TLB_MULTI_HIT_CAUSE;
> +                }
> +                *_wi = wi;
> +                *_ei = ei;
> +                *_ring = ring;
> +            }
> +        }
> +    }
> +    return nhits ? 0 :
> +        (dtlb ? LOAD_STORE_TLB_MISS_CAUSE : INST_TLB_MISS_CAUSE);
> +}
> +
> +/*!
> + * Convert MMU ATTR to PAGE_{READ,WRITE,EXEC} mask.
> + * See ISA, 4.6.5.10
> + */
> +static unsigned mmu_attr_to_access(uint32_t attr)
> +{
> +    unsigned access = 0;
> +    if (attr < 12) {
> +        access |= PAGE_READ;
> +        if (attr & 0x1) {
> +            access |= PAGE_EXEC;
> +        }
> +        if (attr & 0x2) {
> +            access |= PAGE_WRITE;
> +        }
> +    } else if (attr == 13) {
> +        access |= PAGE_READ | PAGE_WRITE;
> +    }
> +    return access;
> +}
> +
> +/*!
> + * Convert region protection ATTR to PAGE_{READ,WRITE,EXEC} mask.
> + * See ISA, 4.6.3.3
> + */
> +static unsigned region_attr_to_access(uint32_t attr)
> +{
> +    unsigned access = 0;
> +    if ((attr < 6 && attr != 3) || attr == 14) {
> +        access |= PAGE_READ | PAGE_WRITE;
> +    }
> +    if (attr > 0 && attr < 6) {
> +        access |= PAGE_EXEC;
> +    }
> +    return access;
> +}
> +
> +static bool is_access_granted(unsigned access, int is_write)
> +{
> +    switch (is_write) {
> +    case 0:
> +        return access & PAGE_READ;
> +
> +    case 1:
> +        return access & PAGE_WRITE;
> +
> +    case 2:
> +        return access & PAGE_EXEC;
> +
> +    default:
> +        return 0;
> +    }
> +}
> +
> +static int autorefill_mmu(CPUState *env, uint32_t vaddr, bool dtlb,
> +        uint32_t *wi, uint32_t *ei, uint8_t *ring);
> +
> +static int get_physical_addr_mmu(CPUState *env,
> +        uint32_t vaddr, int is_write, int mmu_idx,
> +        uint32_t *paddr, uint32_t *page_size, unsigned *access)
> +{
> +    bool dtlb = is_write != 2;
> +    uint32_t wi;
> +    uint32_t ei;
> +    uint8_t ring;
> +    int ret = xtensa_tlb_lookup(env, vaddr, dtlb, &wi, &ei, &ring);
> +
> +    if ((ret == INST_TLB_MISS_CAUSE || ret == LOAD_STORE_TLB_MISS_CAUSE) &&
> +            (mmu_idx != 0 || ((vaddr ^ env->sregs[PTEVADDR]) & 0xffc00000)) &&
> +            autorefill_mmu(env, vaddr, dtlb, &wi, &ei, &ring) == 0) {
> +        ret = 0;
> +    }
> +    if (ret != 0) {
> +        return ret;
> +    }
> +
> +    const xtensa_tlb_entry *entry =
> +        xtensa_tlb_get_entry(env, dtlb, wi, ei);
> +
> +    if (ring < mmu_idx) {
> +        return dtlb ?
> +            LOAD_STORE_PRIVILEGE_CAUSE :
> +            INST_FETCH_PRIVILEGE_CAUSE;
> +    }
> +
> +    *access = mmu_attr_to_access(entry->attr);
> +    if (!is_access_granted(*access, is_write)) {
> +        return dtlb ?
> +            (is_write ?
> +             STORE_PROHIBITED_CAUSE :
> +             LOAD_PROHIBITED_CAUSE) :
> +            INST_FETCH_PROHIBITED_CAUSE;
> +    }
> +
> +    *paddr = entry->paddr | (vaddr & ~xtensa_tlb_get_addr_mask(env, dtlb, wi));
> +    *page_size = ~xtensa_tlb_get_addr_mask(env, dtlb, wi) + 1;
> +
> +    return 0;
> +}
> +
> +static int autorefill_mmu(CPUState *env, uint32_t vaddr, bool dtlb,
> +        uint32_t *wi, uint32_t *ei, uint8_t *ring)
> +{
> +    uint32_t paddr;
> +    uint32_t page_size;
> +    unsigned access;
> +    uint32_t pt_vaddr =
> +        (env->sregs[PTEVADDR] | (vaddr >> 10)) & 0xfffffffc;
> +    int ret = get_physical_addr_mmu(env, pt_vaddr, 0, 0,
> +            &paddr, &page_size, &access);
> +
> +    qemu_log("%s: trying autorefill(%08x) -> %08x\n", __func__,
> +            vaddr, ret ? ~0 : paddr);
> +
> +    if (ret == 0) {
> +        uint32_t vpn;
> +        uint32_t pte = ldl_phys(paddr);
> +
> +        *ring = (pte >> 4) & 0x3;
> +        *wi = (++env->autorefill_idx) & 0x3;
> +        split_tlb_entry_spec_way(env, vaddr, dtlb, &vpn, *wi, ei);
> +        xtensa_tlb_set_entry(env, dtlb, *wi, *ei, vpn, pte);
> +        qemu_log("%s: autorefill(%08x): %08x -> %08x\n",
> +                __func__, vaddr, vpn, pte);
> +    }
> +    return ret;
> +}
> +
> +static int get_physical_addr_region(CPUState *env,
> +        uint32_t vaddr, int is_write, int mmu_idx,
> +        uint32_t *paddr, uint32_t *page_size, unsigned *access)
> +{
> +    bool dtlb = is_write != 2;
> +    uint32_t wi = 0;
> +    uint32_t ei = (vaddr >> 29) & 0x7;
> +    const xtensa_tlb_entry *entry =
> +        xtensa_tlb_get_entry(env, dtlb, wi, ei);
> +
> +    *access = region_attr_to_access(entry->attr);
> +    if (!is_access_granted(*access, is_write)) {
> +        return dtlb ?
> +            (is_write ?
> +             STORE_PROHIBITED_CAUSE :
> +             LOAD_PROHIBITED_CAUSE) :
> +            INST_FETCH_PROHIBITED_CAUSE;
> +    }
> +
> +    *paddr = entry->paddr | (vaddr & ~REGION_PAGE_MASK);
> +    *page_size = ~REGION_PAGE_MASK + 1;
> +
> +    return 0;
> +}
> +
> +/*!
> + * Convert virtual address to physical addr.
> + * MMU may issue pagewalk and change xtensa autorefill TLB way entry.
> + *
> + * \return 0 if ok, exception cause code otherwise
> + */
> +int xtensa_get_physical_addr(CPUState *env,
> +        uint32_t vaddr, int is_write, int mmu_idx,
> +        uint32_t *paddr, uint32_t *page_size, unsigned *access)
> +{
> +    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
> +        return get_physical_addr_mmu(env, vaddr, is_write, mmu_idx,
> +                paddr, page_size, access);
> +    } else if (xtensa_option_bits_enabled(env->config,
> +                XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
> +                XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION))) {
> +        return get_physical_addr_region(env, vaddr, is_write, mmu_idx,
> +                paddr, page_size, access);
> +    } else {
> +        *paddr = vaddr;
> +        *page_size = TARGET_PAGE_SIZE;
> +        *access = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
> +        return 0;
> +    }
> +}
> diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
> index 28689c3..09ab332 100644
> --- a/target-xtensa/helpers.h
> +++ b/target-xtensa/helpers.h
> @@ -22,4 +22,11 @@ DEF_HELPER_2(timer_irq, void, i32, i32)
>  DEF_HELPER_1(advance_ccount, void, i32)
>  DEF_HELPER_1(check_interrupts, void, env)
>
> +DEF_HELPER_1(wsr_rasid, void, i32)
> +DEF_HELPER_2(rtlb0, i32, i32, i32)
> +DEF_HELPER_2(rtlb1, i32, i32, i32)
> +DEF_HELPER_2(itlb, void, i32, i32)
> +DEF_HELPER_2(ptlb, i32, i32, i32)
> +DEF_HELPER_3(wtlb, void, i32, i32, i32)
> +
>  #include "def-helper.h"
> diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
> index fcec506..6a9c886 100644
> --- a/target-xtensa/op_helper.c
> +++ b/target-xtensa/op_helper.c
> @@ -70,13 +70,32 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
>     }
>  }
>
> -void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
> +void tlb_fill(target_ulong vaddr, int is_write, int mmu_idx, void *retaddr)
>  {
> -    tlb_set_page(cpu_single_env,
> -            addr & ~(TARGET_PAGE_SIZE - 1),
> -            addr & ~(TARGET_PAGE_SIZE - 1),
> -            PAGE_READ | PAGE_WRITE | PAGE_EXEC,
> -            mmu_idx, TARGET_PAGE_SIZE);
> +    CPUState *saved_env = env;
> +
> +    env = cpu_single_env;
> +    {
> +        uint32_t paddr;
> +        uint32_t page_size;
> +        unsigned access;
> +        int ret = xtensa_get_physical_addr(env, vaddr, is_write, mmu_idx,
> +                &paddr, &page_size, &access);
> +
> +        qemu_log("%s(%08x, %d, %d) -> %08x, ret = %d\n", __func__,
> +                vaddr, is_write, mmu_idx, paddr, ret);
> +
> +        if (ret == 0) {
> +            tlb_set_page(env,
> +                    vaddr & TARGET_PAGE_MASK,
> +                    paddr & TARGET_PAGE_MASK,
> +                    access, mmu_idx, page_size);
> +        } else {
> +            do_restore_state(retaddr);
> +            HELPER(exception_cause_vaddr)(env->pc, ret, vaddr);
> +        }
> +    }
> +    env = saved_env;
>  }
>
>  void HELPER(exception)(uint32_t excp)
> @@ -377,3 +396,273 @@ void HELPER(check_interrupts)(CPUState *env)
>  {
>     check_interrupts(env);
>  }
> +
> +void HELPER(wsr_rasid)(uint32_t v)
> +{
> +    v = (v & 0xffffff00) | 0x1;
> +    if (v != env->sregs[RASID]) {
> +        env->sregs[RASID] = v;
> +        tlb_flush(env, 1);
> +    }
> +}
> +
> +static uint32_t get_page_size(const CPUState *env, bool dtlb, uint32_t way)
> +{
> +    uint32_t tlbcfg = env->sregs[dtlb ? DTLBCFG : ITLBCFG];
> +
> +    switch (way) {
> +    case 4:
> +        return (tlbcfg >> 16) & 0x3;
> +
> +    case 5:
> +        return (tlbcfg >> 20) & 0x1;
> +
> +    case 6:
> +        return (tlbcfg >> 24) & 0x1;
> +
> +    default:
> +        return 0;
> +    }
> +}
> +
> +/*!
> + * Get bit mask for the virtual address bits translated by the TLB way
> + */
> +uint32_t xtensa_tlb_get_addr_mask(const CPUState *env, bool dtlb, uint32_t way)
> +{
> +    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
> +        bool varway56 = dtlb ?
> +            env->config->dtlb.varway56 :
> +            env->config->itlb.varway56;
> +
> +        switch (way) {
> +        case 4:
> +            return 0xfff00000 << get_page_size(env, dtlb, way) * 2;
> +
> +        case 5:
> +            if (varway56) {
> +                return 0xf8000000 << get_page_size(env, dtlb, way);
> +            } else {
> +                return 0xf8000000;
> +            }
> +
> +        case 6:
> +            if (varway56) {
> +                return 0xf0000000 << (1 - get_page_size(env, dtlb, way));
> +            } else {
> +                return 0xf0000000;
> +            }
> +
> +        default:
> +            return 0xfffff000;
> +        }
> +    } else {
> +        return REGION_PAGE_MASK;
> +    }
> +}
> +
> +/*!
> + * Get bit mask for the 'VPN without index' field.
> + * See ISA, 4.6.5.6, data format for RxTLB0
> + */
> +static uint32_t get_vpn_mask(const CPUState *env, bool dtlb, uint32_t way)
> +{
> +    if (way < 4) {
> +        bool is32 = (dtlb ?
> +                env->config->dtlb.nrefillentries :
> +                env->config->itlb.nrefillentries) == 32;
> +        return is32 ? 0xffff8000 : 0xffffc000;
> +    } else if (way == 4) {
> +        return xtensa_tlb_get_addr_mask(env, dtlb, way) << 2;
> +    } else if (way <= 6) {
> +        uint32_t mask = xtensa_tlb_get_addr_mask(env, dtlb, way);
> +        bool varway56 = dtlb ?
> +            env->config->dtlb.varway56 :
> +            env->config->itlb.varway56;
> +
> +        if (varway56) {
> +            return mask << (way == 5 ? 2 : 3);
> +        } else {
> +            return mask << 1;
> +        }
> +    } else {
> +        return 0xfffff000;
> +    }
> +}
> +
> +/*!
> + * Split virtual address into VPN (with index) and entry index
> + * for the given TLB way
> + */
> +void split_tlb_entry_spec_way(const CPUState *env, uint32_t v, bool dtlb,
> +        uint32_t *vpn, uint32_t wi, uint32_t *ei)
> +{
> +    bool varway56 = dtlb ?
> +        env->config->dtlb.varway56 :
> +        env->config->itlb.varway56;
> +
> +    if (!dtlb) {
> +        wi &= 7;
> +    }
> +
> +    if (wi < 4) {
> +        bool is32 = (dtlb ?
> +                env->config->dtlb.nrefillentries :
> +                env->config->itlb.nrefillentries) == 32;
> +        *ei = (v >> 12) & (is32 ? 0x7 : 0x3);
> +    } else {
> +        switch (wi) {
> +        case 4:
> +            {
> +                uint32_t eibase = 20 + get_page_size(env, dtlb, wi) * 2;
> +                *ei = (v >> eibase) & 0x3;
> +            }
> +            break;
> +
> +        case 5:
> +            if (varway56) {
> +                uint32_t eibase = 27 + get_page_size(env, dtlb, wi);
> +                *ei = (v >> eibase) & 0x3;
> +            } else {
> +                *ei = (v >> 27) & 0x1;
> +            }
> +            break;
> +
> +        case 6:
> +            if (varway56) {
> +                uint32_t eibase = 29 - get_page_size(env, dtlb, wi);
> +                *ei = (v >> eibase) & 0x7;
> +            } else {
> +                *ei = (v >> 28) & 0x1;
> +            }
> +            break;
> +
> +        default:
> +            *ei = 0;
> +            break;
> +        }
> +    }
> +    *vpn = v & xtensa_tlb_get_addr_mask(env, dtlb, wi);
> +}
> +
> +/*!
> + * Split TLB address into TLB way, entry index and VPN (with index).
> + * See ISA, 4.6.5.5 - 4.6.5.8 for the TLB addressing format
> + */
> +static void split_tlb_entry_spec(uint32_t v, bool dtlb,
> +        uint32_t *vpn, uint32_t *wi, uint32_t *ei)
> +{
> +    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
> +        *wi = v & (dtlb ? 0xf : 0x7);
> +        split_tlb_entry_spec_way(env, v, dtlb, vpn, *wi, ei);
> +    } else {
> +        *vpn = v & REGION_PAGE_MASK;
> +        *wi = 0;
> +        *ei = (v >> 29) & 0x7;
> +    }
> +}
> +
> +static xtensa_tlb_entry *get_tlb_entry(uint32_t v, bool dtlb, uint32_t *_wi)
> +{
> +    uint32_t vpn;
> +    uint32_t wi;
> +    uint32_t ei;
> +
> +    split_tlb_entry_spec(v, dtlb, &vpn, &wi, &ei);
> +    if (_wi) {
> +        *_wi = wi;
> +    }
> +    return xtensa_tlb_get_entry(env, dtlb, wi, ei);
> +}
> +
> +uint32_t HELPER(rtlb0)(uint32_t v, uint32_t dtlb)
> +{
> +    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
> +        uint32_t wi;
> +        const xtensa_tlb_entry *entry = get_tlb_entry(v, dtlb, &wi);
> +        return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid;
> +    } else {
> +        return v & REGION_PAGE_MASK;
> +    }
> +}
> +
> +uint32_t HELPER(rtlb1)(uint32_t v, uint32_t dtlb)
> +{
> +    const xtensa_tlb_entry *entry = get_tlb_entry(v, dtlb, NULL);
> +    return entry->paddr | entry->attr;
> +}
> +
> +void HELPER(itlb)(uint32_t v, uint32_t dtlb)
> +{
> +    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
> +        uint32_t wi;
> +        xtensa_tlb_entry *entry = get_tlb_entry(v, dtlb, &wi);
> +        if (entry->variable && entry->asid) {
> +            tlb_flush_page(env, entry->vaddr);
> +            entry->asid = 0;
> +        }
> +    }
> +}
> +
> +uint32_t HELPER(ptlb)(uint32_t v, uint32_t dtlb)
> +{
> +    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
> +        uint32_t wi;
> +        uint32_t ei;
> +        uint8_t ring;
> +        int res = xtensa_tlb_lookup(env, v, dtlb, &wi, &ei, &ring);
> +
> +        switch (res) {
> +        case 0:
> +            if (ring >= xtensa_get_ring(env)) {
> +                return (v & 0xfffff000) | wi | (dtlb ? 0x10 : 0x8);
> +            }
> +            break;
> +
> +        case INST_TLB_MULTI_HIT_CAUSE:
> +        case LOAD_STORE_TLB_MULTI_HIT_CAUSE:
> +            HELPER(exception_cause_vaddr)(env->pc, res, v);
> +            break;
> +        }
> +        return 0;
> +    } else {
> +        return (v & REGION_PAGE_MASK) | 0x1;
> +    }
> +}
> +
> +void xtensa_tlb_set_entry(CPUState *env, bool dtlb,
> +        unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte)
> +{
> +    xtensa_tlb_entry *entry = xtensa_tlb_get_entry(env, dtlb, wi, ei);
> +
> +    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
> +        if (entry->variable) {
> +            if (entry->asid) {
> +                tlb_flush_page(env, entry->vaddr);
> +            }
> +            entry->vaddr = vpn;
> +            entry->paddr = pte & xtensa_tlb_get_addr_mask(env, dtlb, wi);
> +            entry->asid = (env->sregs[RASID] >> ((pte >> 1) & 0x18)) & 0xff;
> +            entry->attr = pte & 0xf;
> +        } else {
> +            qemu_log("%s %d, %d, %d trying to set immutable entry\n",
> +                    __func__, dtlb, wi, ei);
> +        }
> +    } else {
> +        tlb_flush_page(env, entry->vaddr);
> +        if (xtensa_option_enabled(env->config,
> +                    XTENSA_OPTION_REGION_TRANSLATION)) {
> +            entry->paddr = pte & REGION_PAGE_MASK;
> +        }
> +        entry->attr = pte & 0xf;
> +    }
> +}
> +
> +void HELPER(wtlb)(uint32_t p, uint32_t v, uint32_t dtlb)
> +{
> +    uint32_t vpn;
> +    uint32_t wi;
> +    uint32_t ei;
> +    split_tlb_entry_spec(v, dtlb, &vpn, &wi, &ei);
> +    xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
> +}
> diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
> index 3b21bc4..731f04f 100644
> --- a/target-xtensa/translate.c
> +++ b/target-xtensa/translate.c
> @@ -80,6 +80,10 @@ static const char * const sregnames[256] = {
>     [SCOMPARE1] = "SCOMPARE1",
>     [WINDOW_BASE] = "WINDOW_BASE",
>     [WINDOW_START] = "WINDOW_START",
> +    [PTEVADDR] = "PTEVADDR",
> +    [RASID] = "RASID",
> +    [ITLBCFG] = "ITLBCFG",
> +    [DTLBCFG] = "DTLBCFG",
>     [EPC1] = "EPC1",
>     [EPC1 + 1] = "EPC2",
>     [EPC1 + 2] = "EPC3",
> @@ -161,6 +165,11 @@ void xtensa_translate_init(void)
>  #include "helpers.h"
>  }
>
> +static inline bool option_bits_enabled(DisasContext *dc, uint64_t opt)
> +{
> +    return xtensa_option_bits_enabled(dc->config, opt);
> +}
> +
>  static inline bool option_enabled(DisasContext *dc, int opt)
>  {
>     return xtensa_option_enabled(dc->config, opt);
> @@ -379,11 +388,19 @@ static void gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr)
>     tcg_gen_mov_i32(d, cpu_SR[sr]);
>  }
>
> +static void gen_rsr_ptevaddr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
> +{
> +    tcg_gen_shri_i32(d, cpu_SR[EXCVADDR], 10);
> +    tcg_gen_or_i32(d, d, cpu_SR[sr]);
> +    tcg_gen_andi_i32(d, d, 0xfffffffc);
> +}
> +
>  static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
>  {
>     static void (* const rsr_handler[256])(DisasContext *dc,
>             TCGv_i32 d, uint32_t sr) = {
>         [CCOUNT] = gen_rsr_ccount,
> +        [PTEVADDR] = gen_rsr_ptevaddr,
>     };
>
>     if (sregnames[sr]) {
> @@ -436,6 +453,23 @@ static void gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v)
>     reset_used_window(dc);
>  }
>
> +static void gen_wsr_ptevaddr(DisasContext *dc, uint32_t sr, TCGv_i32 v)
> +{
> +    tcg_gen_andi_i32(cpu_SR[sr], v, 0xffc00000);
> +}
> +
> +static void gen_wsr_rasid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
> +{
> +    gen_helper_wsr_rasid(v);
> +    /* This can change tb->flags, so exit tb */
> +    gen_jumpi_check_loop_end(dc, -1);
> +}
> +
> +static void gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v)
> +{
> +    tcg_gen_andi_i32(cpu_SR[sr], v, 0x01130000);
> +}
> +
>  static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v)
>  {
>     tcg_gen_andi_i32(cpu_SR[sr], v,
> @@ -505,6 +539,10 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
>         [LITBASE] = gen_wsr_litbase,
>         [WINDOW_BASE] = gen_wsr_windowbase,
>         [WINDOW_START] = gen_wsr_windowstart,
> +        [PTEVADDR] = gen_wsr_ptevaddr,
> +        [RASID] = gen_wsr_rasid,
> +        [ITLBCFG] = gen_wsr_tlbcfg,
> +        [DTLBCFG] = gen_wsr_tlbcfg,
>         [INTSET] = gen_wsr_intset,
>         [INTCLEAR] = gen_wsr_intclear,
>         [INTENABLE] = gen_wsr_intenable,
> @@ -585,14 +623,16 @@ static void gen_window_check3(DisasContext *dc, unsigned r1, unsigned r2,
>
>  static void disas_xtensa_insn(DisasContext *dc)
>  {
> -#define HAS_OPTION(opt) do { \
> -        if (!option_enabled(dc, opt)) { \
> -            qemu_log("Option %d is not enabled %s:%d\n", \
> -                    (opt), __FILE__, __LINE__); \
> +#define HAS_OPTION_BITS(opt) do { \
> +        if (!option_bits_enabled(dc, opt)) { \
> +            qemu_log("Option is not enabled %s:%d\n", \
> +                    __FILE__, __LINE__); \
>             goto invalid_opcode; \
>         } \
>     } while (0)
>
> +#define HAS_OPTION(opt) HAS_OPTION_BITS(XTENSA_OPTION_BIT(opt))
> +
>  #define TBD() qemu_log("TBD(pc = %08x): %s:%d\n", dc->pc, __FILE__, __LINE__)
>  #define RESERVED() do { \
>         qemu_log("RESERVED(pc = %08x, %02x%02x%02x): %s:%d\n", \
> @@ -1055,7 +1095,48 @@ static void disas_xtensa_insn(DisasContext *dc)
>                 break;
>
>             case 5: /*TLB*/
> -                TBD();
> +                HAS_OPTION_BITS(
> +                        XTENSA_OPTION_BIT(XTENSA_OPTION_MMU) |
> +                        XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
> +                        XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION));
> +                gen_check_privilege(dc);
> +                gen_window_check2(dc, RRR_S, RRR_T);
> +                {
> +                    TCGv_i32 dtlb = tcg_const_i32((RRR_R & 8) != 0);
> +
> +                    switch (RRR_R & 7) {
> +                    case 3: /*RITLB0*/ /*RDTLB0*/
> +                        gen_helper_rtlb0(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
> +                        break;
> +
> +                    case 4: /*IITLB*/ /*IDTLB*/
> +                        gen_helper_itlb(cpu_R[RRR_S], dtlb);
> +                        /* This could change memory mapping, so exit tb */
> +                        gen_jumpi_check_loop_end(dc, -1);
> +                        break;
> +
> +                    case 5: /*PITLB*/ /*PDTLB*/
> +                        tcg_gen_movi_i32(cpu_pc, dc->pc);
> +                        gen_helper_ptlb(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
> +                        break;
> +
> +                    case 6: /*WITLB*/ /*WDTLB*/
> +                        gen_helper_wtlb(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
> +                        /* This could change memory mapping, so exit tb */
> +                        gen_jumpi_check_loop_end(dc, -1);
> +                        break;
> +
> +                    case 7: /*RITLB1*/ /*RDTLB1*/
> +                        gen_helper_rtlb1(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
> +                        break;
> +
> +                    default:
> +                        tcg_temp_free(dtlb);
> +                        RESERVED();
> +                        break;
> +                    }
> +                    tcg_temp_free(dtlb);
> +                }
>                 break;
>
>             case 6: /*RT0*/
> --
> 1.7.6
>
>
>

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

* Re: [Qemu-devel] [PATCH v4 30/32] target-xtensa: add dc232b core and board
  2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 30/32] target-xtensa: add dc232b core and board Max Filippov
@ 2011-09-04 18:33   ` Blue Swirl
  0 siblings, 0 replies; 47+ messages in thread
From: Blue Swirl @ 2011-09-04 18:33 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On Thu, Sep 1, 2011 at 8:45 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> This is Diamond 232L Standard Core Rev.B (LE).
>
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
> ---
>  Makefile.target                   |    1 +
>  hw/xtensa_dc232b.c                |  112 ++++++++++++++++
>  target-xtensa/gdb-config-dc232b.c |  261 +++++++++++++++++++++++++++++++++++++
>  target-xtensa/helper.c            |  168 ++++++++++++++++++++++++
>  4 files changed, 542 insertions(+), 0 deletions(-)
>  create mode 100644 hw/xtensa_dc232b.c
>  create mode 100644 target-xtensa/gdb-config-dc232b.c
>
> diff --git a/Makefile.target b/Makefile.target
> index 9bbb668..579820b 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -375,6 +375,7 @@ obj-alpha-y += vga.o cirrus_vga.o
>
>  obj-xtensa-y += xtensa_pic.o
>  obj-xtensa-y += xtensa_sample.o
> +obj-xtensa-y += xtensa_dc232b.o
>  obj-xtensa-y += xtensa-semi.o
>
>  main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
> diff --git a/hw/xtensa_dc232b.c b/hw/xtensa_dc232b.c
> new file mode 100644
> index 0000000..9b0bac7
> --- /dev/null
> +++ b/hw/xtensa_dc232b.c
> @@ -0,0 +1,112 @@
> +/*
> + * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions are met:
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in the
> + *       documentation and/or other materials provided with the distribution.
> + *     * Neither the name of the Open Source and Linux Lab nor the
> + *       names of its contributors may be used to endorse or promote products
> + *       derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include "sysemu.h"
> +#include "boards.h"
> +#include "loader.h"
> +#include "elf.h"
> +
> +static uint64_t translate_phys_addr(void *env, uint64_t addr)
> +{
> +    return cpu_get_phys_page_debug(env, addr);
> +}
> +
> +static void dc232b_reset(void *env)
> +{
> +    cpu_reset(env);
> +}
> +
> +static void dc232b_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)
> +{
> +    CPUState *env = NULL;
> +    ram_addr_t ram_offset;
> +    int n;
> +
> +    for (n = 0; n < smp_cpus; n++) {
> +        env = cpu_init(cpu_model);
> +        if (!env) {
> +            fprintf(stderr, "Unable to find CPU definition\n");
> +            exit(1);
> +        }
> +        env->sregs[PRID] = n;
> +        qemu_register_reset(dc232b_reset, env);
> +        /* Need MMU initialized prior to ELF loading,
> +         * so that ELF gets loaded into virtual addresses
> +         */
> +        dc232b_reset(env);
> +    }
> +
> +    ram_offset = qemu_ram_alloc(NULL, "xtensa.sram", ram_size);
> +    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
> +
> +    ram_offset = qemu_ram_alloc(NULL, "xtensa.rom", 0x1000);
> +    cpu_register_physical_memory(0xfe000000, 0x1000, ram_offset | IO_MEM_RAM);

Memory API.

> +
> +    if (kernel_filename) {
> +        uint64_t elf_entry;
> +        uint64_t elf_lowaddr;
> +#ifdef TARGET_WORDS_BIGENDIAN
> +        int success = load_elf(kernel_filename, translate_phys_addr, env,
> +                &elf_entry, &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
> +#else
> +        int success = load_elf(kernel_filename, translate_phys_addr, env,
> +                &elf_entry, &elf_lowaddr, NULL, 0, ELF_MACHINE, 0);
> +#endif
> +        if (success > 0) {
> +            env->pc = elf_entry;
> +        }
> +    }
> +}
> +
> +static void xtensa_dc232b_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)
> +{
> +    if (!cpu_model) {
> +        cpu_model = "dc232b";
> +    }
> +    dc232b_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
> +            initrd_filename, cpu_model);
> +}
> +
> +static QEMUMachine xtensa_dc232b_machine = {
> +    .name = "dc232b",
> +    .desc = "Diamond 232L Standard Core Rev.B (LE) (dc232b)",
> +    .init = xtensa_dc232b_init,
> +    .max_cpus = 4,
> +};
> +
> +static void xtensa_dc232b_machine_init(void)
> +{
> +    qemu_register_machine(&xtensa_dc232b_machine);
> +}
> +
> +machine_init(xtensa_dc232b_machine_init);
> diff --git a/target-xtensa/gdb-config-dc232b.c b/target-xtensa/gdb-config-dc232b.c
> new file mode 100644
> index 0000000..13aba5e
> --- /dev/null
> +++ b/target-xtensa/gdb-config-dc232b.c
> @@ -0,0 +1,261 @@
> +/* Configuration for the Xtensa architecture for GDB, the GNU debugger.
> +
> +   Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
> +
> +   This file is part of GDB.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 2 of the License, or
> +   (at your option) any later version.
> +
> +   This program 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 General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program; if not, write to the Free Software
> +   Foundation, Inc., 51 Franklin Street, Fifth Floor,
> +   Boston, MA 02110-1301, USA.  */
> +
> +  XTREG(0,   0, 32, 4, 4, 0x0020, 0x0006, -2, 9, 0x0100, pc,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(1,   4, 32, 4, 4, 0x0100, 0x0006, -2, 1, 0x0002, ar0,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(2,   8, 32, 4, 4, 0x0101, 0x0006, -2, 1, 0x0002, ar1,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(3,  12, 32, 4, 4, 0x0102, 0x0006, -2, 1, 0x0002, ar2,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(4,  16, 32, 4, 4, 0x0103, 0x0006, -2, 1, 0x0002, ar3,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(5,  20, 32, 4, 4, 0x0104, 0x0006, -2, 1, 0x0002, ar4,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(6,  24, 32, 4, 4, 0x0105, 0x0006, -2, 1, 0x0002, ar5,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(7,  28, 32, 4, 4, 0x0106, 0x0006, -2, 1, 0x0002, ar6,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(8,  32, 32, 4, 4, 0x0107, 0x0006, -2, 1, 0x0002, ar7,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(9,  36, 32, 4, 4, 0x0108, 0x0006, -2, 1, 0x0002, ar8,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(10,  40, 32, 4, 4, 0x0109, 0x0006, -2, 1, 0x0002, ar9,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(11,  44, 32, 4, 4, 0x010a, 0x0006, -2, 1, 0x0002, ar10,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(12,  48, 32, 4, 4, 0x010b, 0x0006, -2, 1, 0x0002, ar11,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(13,  52, 32, 4, 4, 0x010c, 0x0006, -2, 1, 0x0002, ar12,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(14,  56, 32, 4, 4, 0x010d, 0x0006, -2, 1, 0x0002, ar13,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(15,  60, 32, 4, 4, 0x010e, 0x0006, -2, 1, 0x0002, ar14,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(16,  64, 32, 4, 4, 0x010f, 0x0006, -2, 1, 0x0002, ar15,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(17,  68, 32, 4, 4, 0x0110, 0x0006, -2, 1, 0x0002, ar16,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(18,  72, 32, 4, 4, 0x0111, 0x0006, -2, 1, 0x0002, ar17,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(19,  76, 32, 4, 4, 0x0112, 0x0006, -2, 1, 0x0002, ar18,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(20,  80, 32, 4, 4, 0x0113, 0x0006, -2, 1, 0x0002, ar19,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(21,  84, 32, 4, 4, 0x0114, 0x0006, -2, 1, 0x0002, ar20,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(22,  88, 32, 4, 4, 0x0115, 0x0006, -2, 1, 0x0002, ar21,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(23,  92, 32, 4, 4, 0x0116, 0x0006, -2, 1, 0x0002, ar22,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(24,  96, 32, 4, 4, 0x0117, 0x0006, -2, 1, 0x0002, ar23,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(25, 100, 32, 4, 4, 0x0118, 0x0006, -2, 1, 0x0002, ar24,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(26, 104, 32, 4, 4, 0x0119, 0x0006, -2, 1, 0x0002, ar25,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(27, 108, 32, 4, 4, 0x011a, 0x0006, -2, 1, 0x0002, ar26,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(28, 112, 32, 4, 4, 0x011b, 0x0006, -2, 1, 0x0002, ar27,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(29, 116, 32, 4, 4, 0x011c, 0x0006, -2, 1, 0x0002, ar28,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(30, 120, 32, 4, 4, 0x011d, 0x0006, -2, 1, 0x0002, ar29,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(31, 124, 32, 4, 4, 0x011e, 0x0006, -2, 1, 0x0002, ar30,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(32, 128, 32, 4, 4, 0x011f, 0x0006, -2, 1, 0x0002, ar31,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(33, 132, 32, 4, 4, 0x0200, 0x0006, -2, 2, 0x1100, lbeg,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(34, 136, 32, 4, 4, 0x0201, 0x0006, -2, 2, 0x1100, lend,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(35, 140, 32, 4, 4, 0x0202, 0x0006, -2, 2, 0x1100, lcount,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(36, 144,  6, 4, 4, 0x0203, 0x0006, -2, 2, 0x1100, sar,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(37, 148, 32, 4, 4, 0x0205, 0x0006, -2, 2, 0x1100, litbase,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(38, 152,  3, 4, 4, 0x0248, 0x0006, -2, 2, 0x1002, windowbase,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(39, 156,  8, 4, 4, 0x0249, 0x0006, -2, 2, 0x1002, windowstart,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(40, 160, 32, 4, 4, 0x02b0, 0x0002, -2, 2, 0x1000, sr176,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(41, 164, 32, 4, 4, 0x02d0, 0x0002, -2, 2, 0x1000, sr208,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(42, 168, 19, 4, 4, 0x02e6, 0x0006, -2, 2, 0x1100, ps,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(43, 172, 32, 4, 4, 0x03e7, 0x0006, -2, 3, 0x0110, threadptr,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(44, 176, 32, 4, 4, 0x020c, 0x0006, -1, 2, 0x1100, scompare1,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(45, 180, 32, 4, 4, 0x0210, 0x0006, -1, 2, 0x1100, acclo,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(46, 184,  8, 4, 4, 0x0211, 0x0006, -1, 2, 0x1100, acchi,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(47, 188, 32, 4, 4, 0x0220, 0x0006, -1, 2, 0x1100, m0,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(48, 192, 32, 4, 4, 0x0221, 0x0006, -1, 2, 0x1100, m1,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(49, 196, 32, 4, 4, 0x0222, 0x0006, -1, 2, 0x1100, m2,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(50, 200, 32, 4, 4, 0x0223, 0x0006, -1, 2, 0x1100, m3,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(51, 204, 32, 4, 4, 0x03e6, 0x000e, -1, 3, 0x0110, expstate,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(52, 208, 32, 4, 4, 0x0253, 0x0007, -2, 2, 0x1000, ptevaddr,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(53, 212, 32, 4, 4, 0x0259, 0x000d, -2, 2, 0x1000, mmid,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(54, 216, 32, 4, 4, 0x025a, 0x0007, -2, 2, 0x1000, rasid,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(55, 220, 18, 4, 4, 0x025b, 0x0007, -2, 2, 0x1000, itlbcfg,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(56, 224, 18, 4, 4, 0x025c, 0x0007, -2, 2, 0x1000, dtlbcfg,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(57, 228,  2, 4, 4, 0x0260, 0x0007, -2, 2, 0x1000, ibreakenable,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(58, 232, 32, 4, 4, 0x0268, 0x0007, -2, 2, 0x1000, ddr,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(59, 236, 32, 4, 4, 0x0280, 0x0007, -2, 2, 0x1000, ibreaka0,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(60, 240, 32, 4, 4, 0x0281, 0x0007, -2, 2, 0x1000, ibreaka1,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(61, 244, 32, 4, 4, 0x0290, 0x0007, -2, 2, 0x1000, dbreaka0,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(62, 248, 32, 4, 4, 0x0291, 0x0007, -2, 2, 0x1000, dbreaka1,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(63, 252, 32, 4, 4, 0x02a0, 0x0007, -2, 2, 0x1000, dbreakc0,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(64, 256, 32, 4, 4, 0x02a1, 0x0007, -2, 2, 0x1000, dbreakc1,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(65, 260, 32, 4, 4, 0x02b1, 0x0007, -2, 2, 0x1000, epc1,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(66, 264, 32, 4, 4, 0x02b2, 0x0007, -2, 2, 0x1000, epc2,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(67, 268, 32, 4, 4, 0x02b3, 0x0007, -2, 2, 0x1000, epc3,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(68, 272, 32, 4, 4, 0x02b4, 0x0007, -2, 2, 0x1000, epc4,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(69, 276, 32, 4, 4, 0x02b5, 0x0007, -2, 2, 0x1000, epc5,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(70, 280, 32, 4, 4, 0x02b6, 0x0007, -2, 2, 0x1000, epc6,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(71, 284, 32, 4, 4, 0x02b7, 0x0007, -2, 2, 0x1000, epc7,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(72, 288, 32, 4, 4, 0x02c0, 0x0007, -2, 2, 0x1000, depc,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(73, 292, 19, 4, 4, 0x02c2, 0x0007, -2, 2, 0x1000, eps2,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(74, 296, 19, 4, 4, 0x02c3, 0x0007, -2, 2, 0x1000, eps3,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(75, 300, 19, 4, 4, 0x02c4, 0x0007, -2, 2, 0x1000, eps4,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(76, 304, 19, 4, 4, 0x02c5, 0x0007, -2, 2, 0x1000, eps5,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(77, 308, 19, 4, 4, 0x02c6, 0x0007, -2, 2, 0x1000, eps6,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(78, 312, 19, 4, 4, 0x02c7, 0x0007, -2, 2, 0x1000, eps7,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(79, 316, 32, 4, 4, 0x02d1, 0x0007, -2, 2, 0x1000, excsave1,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(80, 320, 32, 4, 4, 0x02d2, 0x0007, -2, 2, 0x1000, excsave2,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(81, 324, 32, 4, 4, 0x02d3, 0x0007, -2, 2, 0x1000, excsave3,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(82, 328, 32, 4, 4, 0x02d4, 0x0007, -2, 2, 0x1000, excsave4,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(83, 332, 32, 4, 4, 0x02d5, 0x0007, -2, 2, 0x1000, excsave5,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(84, 336, 32, 4, 4, 0x02d6, 0x0007, -2, 2, 0x1000, excsave6,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(85, 340, 32, 4, 4, 0x02d7, 0x0007, -2, 2, 0x1000, excsave7,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(86, 344,  8, 4, 4, 0x02e0, 0x0007, -2, 2, 0x1000, cpenable,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(87, 348, 22, 4, 4, 0x02e2, 0x000b, -2, 2, 0x1000, interrupt,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(88, 352, 22, 4, 4, 0x02e2, 0x000d, -2, 2, 0x1000, intset,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(89, 356, 22, 4, 4, 0x02e3, 0x000d, -2, 2, 0x1000, intclear,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(90, 360, 22, 4, 4, 0x02e4, 0x0007, -2, 2, 0x1000, intenable,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(91, 364, 32, 4, 4, 0x02e7, 0x0007, -2, 2, 0x1000, vecbase,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(92, 368,  6, 4, 4, 0x02e8, 0x0007, -2, 2, 0x1000, exccause,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(93, 372, 12, 4, 4, 0x02e9, 0x0003, -2, 2, 0x1000, debugcause,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(94, 376, 32, 4, 4, 0x02ea, 0x000f, -2, 2, 0x1000, ccount,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(95, 380, 32, 4, 4, 0x02eb, 0x0003, -2, 2, 0x1000, prid,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(96, 384, 32, 4, 4, 0x02ec, 0x000f, -2, 2, 0x1000, icount,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(97, 388,  4, 4, 4, 0x02ed, 0x0007, -2, 2, 0x1000, icountlevel,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(98, 392, 32, 4, 4, 0x02ee, 0x0007, -2, 2, 0x1000, excvaddr,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(99, 396, 32, 4, 4, 0x02f0, 0x000f, -2, 2, 0x1000, ccompare0,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(100, 400, 32, 4, 4, 0x02f1, 0x000f, -2, 2, 0x1000, ccompare1,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(101, 404, 32, 4, 4, 0x02f2, 0x000f, -2, 2, 0x1000, ccompare2,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(102, 408, 32, 4, 4, 0x02f4, 0x0007, -2, 2, 0x1000, misc0,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(103, 412, 32, 4, 4, 0x02f5, 0x0007, -2, 2, 0x1000, misc1,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(104, 416, 32, 4, 4, 0x0000, 0x0006, -2, 8, 0x0100, a0,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(105, 420, 32, 4, 4, 0x0001, 0x0006, -2, 8, 0x0100, a1,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(106, 424, 32, 4, 4, 0x0002, 0x0006, -2, 8, 0x0100, a2,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(107, 428, 32, 4, 4, 0x0003, 0x0006, -2, 8, 0x0100, a3,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(108, 432, 32, 4, 4, 0x0004, 0x0006, -2, 8, 0x0100, a4,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(109, 436, 32, 4, 4, 0x0005, 0x0006, -2, 8, 0x0100, a5,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(110, 440, 32, 4, 4, 0x0006, 0x0006, -2, 8, 0x0100, a6,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(111, 444, 32, 4, 4, 0x0007, 0x0006, -2, 8, 0x0100, a7,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(112, 448, 32, 4, 4, 0x0008, 0x0006, -2, 8, 0x0100, a8,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(113, 452, 32, 4, 4, 0x0009, 0x0006, -2, 8, 0x0100, a9,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(114, 456, 32, 4, 4, 0x000a, 0x0006, -2, 8, 0x0100, a10,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(115, 460, 32, 4, 4, 0x000b, 0x0006, -2, 8, 0x0100, a11,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(116, 464, 32, 4, 4, 0x000c, 0x0006, -2, 8, 0x0100, a12,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(117, 468, 32, 4, 4, 0x000d, 0x0006, -2, 8, 0x0100, a13,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(118, 472, 32, 4, 4, 0x000e, 0x0006, -2, 8, 0x0100, a14,
> +          0, 0, 0, 0, 0, 0)
> +  XTREG(119, 476, 32, 4, 4, 0x000f, 0x0006, -2, 8, 0x0100, a15,
> +          0, 0, 0, 0, 0, 0)
> diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
> index 00571e8..9ed3c09 100644
> --- a/target-xtensa/helper.c
> +++ b/target-xtensa/helper.c
> @@ -107,6 +107,174 @@ static const XtensaConfig core_config[] = {
>             [0] = 0,
>         },
>         .clock_freq_khz = 912000,
> +    }, {
> +        .name = "dc232b",
> +        .options = -1 ^
> +            (XTENSA_OPTION_BIT(XTENSA_OPTION_HW_ALIGNMENT) |
> +             XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
> +             XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION)),
> +        .gdb_regmap = {
> +            .num_regs = 120,
> +            .num_core_regs = 52,
> +            .reg = {
> +#include "gdb-config-dc232b.c"
> +            }
> +        },
> +        .nareg = 32,
> +        .ndepc = 1,
> +        .excm_level = 3,
> +        .vecbase = 0xd0000000,
> +        .exception_vector = {
> +            [EXC_RESET] = 0xfe000000,
> +            [EXC_WINDOW_OVERFLOW4] = 0xd0000000,
> +            [EXC_WINDOW_UNDERFLOW4] = 0xd0000040,
> +            [EXC_WINDOW_OVERFLOW8] = 0xd0000080,
> +            [EXC_WINDOW_UNDERFLOW8] = 0xd00000c0,
> +            [EXC_WINDOW_OVERFLOW12] = 0xd0000100,
> +            [EXC_WINDOW_UNDERFLOW12] = 0xd0000140,
> +            [EXC_KERNEL] = 0xd0000300,
> +            [EXC_USER] = 0xd0000340,
> +            [EXC_DOUBLE] = 0xd00003c0,
> +        },
> +        .ninterrupt = 22,
> +        .nlevel = 6,
> +        .interrupt_vector = {
> +            0,
> +            0,
> +            0xd0000180,
> +            0xd00001c0,
> +            0xd0000200,
> +            0xd0000240,
> +            0xd0000280,
> +            0xd00002c0,
> +        },
> +        .level_mask = {
> +            [1] = 0x1f80ff,
> +            [2] = 0x000100,
> +            [3] = 0x200e00,
> +            [4] = 0x001000,
> +            [5] = 0x002000,
> +            [6] = 0x000000,
> +            [7] = 0x004000,
> +        },
> +        .inttype_mask = {
> +            [INTTYPE_EDGE] = 0x3f8000,
> +            [INTTYPE_NMI] = 0x4000,
> +            [INTTYPE_SOFTWARE] = 0x880,
> +        },
> +        .interrupt = {
> +            [0] = {
> +                .level = 1,
> +                .inttype = INTTYPE_LEVEL,
> +            },
> +            [1] = {
> +                .level = 1,
> +                .inttype = INTTYPE_LEVEL,
> +            },
> +            [2] = {
> +                .level = 1,
> +                .inttype = INTTYPE_LEVEL,
> +            },
> +            [3] = {
> +                .level = 1,
> +                .inttype = INTTYPE_LEVEL,
> +            },
> +            [4] = {
> +                .level = 1,
> +                .inttype = INTTYPE_LEVEL,
> +            },
> +            [5] = {
> +                .level = 1,
> +                .inttype = INTTYPE_LEVEL,
> +            },
> +            [6] = {
> +                .level = 1,
> +                .inttype = INTTYPE_TIMER,
> +            },
> +            [7] = {
> +                .level = 1,
> +                .inttype = INTTYPE_SOFTWARE,
> +            },
> +            [8] = {
> +                .level = 2,
> +                .inttype = INTTYPE_LEVEL,
> +            },
> +            [9] = {
> +                .level = 3,
> +                .inttype = INTTYPE_LEVEL,
> +            },
> +            [10] = {
> +                .level = 3,
> +                .inttype = INTTYPE_TIMER,
> +            },
> +            [11] = {
> +                .level = 3,
> +                .inttype = INTTYPE_SOFTWARE,
> +            },
> +            [12] = {
> +                .level = 4,
> +                .inttype = INTTYPE_LEVEL,
> +            },
> +            [13] = {
> +                .level = 5,
> +                .inttype = INTTYPE_TIMER,
> +            },
> +            [14] = {
> +                .level = 7,
> +                .inttype = INTTYPE_NMI,
> +            },
> +            [15] = {
> +                .level = 1,
> +                .inttype = INTTYPE_EDGE,
> +            },
> +            [16] = {
> +                .level = 1,
> +                .inttype = INTTYPE_EDGE,
> +            },
> +            [17] = {
> +                .level = 1,
> +                .inttype = INTTYPE_EDGE,
> +            },
> +            [18] = {
> +                .level = 1,
> +                .inttype = INTTYPE_EDGE,
> +            },
> +            [19] = {
> +                .level = 1,
> +                .inttype = INTTYPE_EDGE,
> +            },
> +            [20] = {
> +                .level = 1,
> +                .inttype = INTTYPE_EDGE,
> +            },
> +            [21] = {
> +                .level = 3,
> +                .inttype = INTTYPE_EDGE,
> +            },
> +        },
> +        .nccompare = 3,
> +        .timerint = {
> +            [0] = 6,
> +            [1] = 10,
> +            [2] = 13,
> +        },
> +        .clock_freq_khz = 912000,
> +        .itlb = {
> +            .nways = 7,
> +            .way_size = {
> +                4, 4, 4, 4, 4, 2, 2,
> +            },
> +            .varway56 = false,
> +            .nrefillentries = 16,
> +        },
> +        .dtlb = {
> +            .nways = 10,
> +            .way_size = {
> +                4, 4, 4, 4, 4, 2, 2, 1, 1, 1,
> +            },
> +            .varway56 = false,
> +            .nrefillentries = 16,
> +        },
>     },
>  };
>
> --
> 1.7.6
>
>
>

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

* Re: [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture
  2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
                   ` (31 preceding siblings ...)
  2011-09-01 20:46 ` [Qemu-devel] [PATCH v4 32/32] target-xtensa: add regression testsuite Max Filippov
@ 2011-09-04 18:35 ` Blue Swirl
  2011-09-05 10:55   ` Edgar E. Iglesias
  32 siblings, 1 reply; 47+ messages in thread
From: Blue Swirl @ 2011-09-04 18:35 UTC (permalink / raw)
  To: Max Filippov, Anthony Liguori, qemu-devel

On Thu, Sep 1, 2011 at 8:45 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> This series adds support for Tensilica Xtensa target.
> Port status: Linux for DC232B works in the qemu.
>  Not implemented xtensa options: MAC16, floating point coprocessor,
>  boolean option, cache option, debug option.

I had minor comments to a few patches, otherwise this looks nice to me.

Does anyone object to merging this?

> v3 -> v4 changes:
> - fix usage of type names ending with _t;
> - fix usage of identifiers starting with _[A-Z].
>
> Git tree is available at git://jcmvbkbc.spb.ru/dumb/qemu-xtensa.git xtensa
>
> Max Filippov (32):
>  target-xtensa: add target stubs
>  target-xtensa: add target to the configure script
>  target-xtensa: implement disas_xtensa_insn
>  target-xtensa: implement narrow instructions
>  target-xtensa: implement RT0 group
>  target-xtensa: add sample board
>  target-xtensa: implement conditional jumps
>  target-xtensa: implement JX/RET0/CALLX
>  target-xtensa: add special and user registers
>  target-xtensa: implement RST3 group
>  target-xtensa: implement shifts (ST1 and RST1 groups)
>  target-xtensa: implement LSAI group
>  target-xtensa: mark reserved and TBD opcodes
>  target-xtensa: implement SYNC group
>  target-xtensa: implement CACHE group
>  target-xtensa: add PS register and access control
>  target-xtensa: implement exceptions
>  target-xtensa: implement RST2 group (32 bit mul/div/rem)
>  target-xtensa: implement windowed registers
>  target-xtensa: implement loop option
>  target-xtensa: implement extended L32R
>  target-xtensa: implement unaligned exception option
>  target-xtensa: implement SIMCALL
>  target-xtensa: implement interrupt option
>  target-xtensa: implement accurate window check
>  target-xtensa: implement CPENABLE and PRID SRs
>  target-xtensa: implement relocatable vectors
>  target-xtensa: add gdb support
>  target-xtensa: implement memory protection options
>  target-xtensa: add dc232b core and board
>  MAINTAINERS: add xtensa maintainer
>  target-xtensa: add regression testsuite
>
>  MAINTAINERS                                   |   13 +
>  Makefile.target                               |    5 +
>  arch_init.c                                   |    2 +
>  arch_init.h                                   |    1 +
>  configure                                     |   12 +-
>  cpu-exec.c                                    |    8 +
>  default-configs/xtensa-softmmu.mak            |    1 +
>  default-configs/xtensaeb-softmmu.mak          |    1 +
>  elf.h                                         |    2 +
>  gdbstub.c                                     |   96 +
>  hw/xtensa_dc232b.c                            |  112 ++
>  hw/xtensa_pic.c                               |  134 ++
>  hw/xtensa_sample.c                            |  106 ++
>  qemu-options.hx                               |    4 +-
>  target-xtensa/cpu.h                           |  424 +++++
>  target-xtensa/gdb-config-dc232b.c             |  261 +++
>  target-xtensa/gdb-config-sample-xtensa-core.c |  375 ++++
>  target-xtensa/helper.c                        |  763 ++++++++
>  target-xtensa/helpers.h                       |   32 +
>  target-xtensa/machine.c                       |   38 +
>  target-xtensa/op_helper.c                     |  668 +++++++
>  target-xtensa/translate.c                     | 2349 +++++++++++++++++++++++++
>  tests/xtensa/Makefile                         |   72 +
>  tests/xtensa/crt.S                            |   24 +
>  tests/xtensa/linker.ld                        |  113 ++
>  tests/xtensa/macros.inc                       |   68 +
>  tests/xtensa/test_b.S                         |  221 +++
>  tests/xtensa/test_bi.S                        |  103 ++
>  tests/xtensa/test_bz.S                        |   57 +
>  tests/xtensa/test_clamps.S                    |   42 +
>  tests/xtensa/test_fail.S                      |    9 +
>  tests/xtensa/test_interrupt.S                 |  194 ++
>  tests/xtensa/test_loop.S                      |   77 +
>  tests/xtensa/test_max.S                       |   81 +
>  tests/xtensa/test_min.S                       |   81 +
>  tests/xtensa/test_mmu.S                       |  318 ++++
>  tests/xtensa/test_mul16.S                     |   83 +
>  tests/xtensa/test_mul32.S                     |   20 +
>  tests/xtensa/test_nsa.S                       |   59 +
>  tests/xtensa/test_pipeline.S                  |  157 ++
>  tests/xtensa/test_quo.S                       |  147 ++
>  tests/xtensa/test_rem.S                       |  147 ++
>  tests/xtensa/test_rst0.S                      |  148 ++
>  tests/xtensa/test_sar.S                       |  111 ++
>  tests/xtensa/test_sext.S                      |   69 +
>  tests/xtensa/test_shift.S                     |  206 +++
>  tests/xtensa/test_timer.S                     |  115 ++
>  tests/xtensa/test_windowed.S                  |  302 ++++
>  tests/xtensa/vectors.S                        |   39 +
>  xtensa-semi.c                                 |  224 +++
>  50 files changed, 8691 insertions(+), 3 deletions(-)
>  create mode 100644 default-configs/xtensa-softmmu.mak
>  create mode 100644 default-configs/xtensaeb-softmmu.mak
>  create mode 100644 hw/xtensa_dc232b.c
>  create mode 100644 hw/xtensa_pic.c
>  create mode 100644 hw/xtensa_sample.c
>  create mode 100644 target-xtensa/cpu.h
>  create mode 100644 target-xtensa/gdb-config-dc232b.c
>  create mode 100644 target-xtensa/gdb-config-sample-xtensa-core.c
>  create mode 100644 target-xtensa/helper.c
>  create mode 100644 target-xtensa/helpers.h
>  create mode 100644 target-xtensa/machine.c
>  create mode 100644 target-xtensa/op_helper.c
>  create mode 100644 target-xtensa/translate.c
>  create mode 100644 tests/xtensa/Makefile
>  create mode 100644 tests/xtensa/crt.S
>  create mode 100644 tests/xtensa/linker.ld
>  create mode 100644 tests/xtensa/macros.inc
>  create mode 100644 tests/xtensa/test_b.S
>  create mode 100644 tests/xtensa/test_bi.S
>  create mode 100644 tests/xtensa/test_bz.S
>  create mode 100644 tests/xtensa/test_clamps.S
>  create mode 100644 tests/xtensa/test_fail.S
>  create mode 100644 tests/xtensa/test_interrupt.S
>  create mode 100644 tests/xtensa/test_loop.S
>  create mode 100644 tests/xtensa/test_max.S
>  create mode 100644 tests/xtensa/test_min.S
>  create mode 100644 tests/xtensa/test_mmu.S
>  create mode 100644 tests/xtensa/test_mul16.S
>  create mode 100644 tests/xtensa/test_mul32.S
>  create mode 100644 tests/xtensa/test_nsa.S
>  create mode 100644 tests/xtensa/test_pipeline.S
>  create mode 100644 tests/xtensa/test_quo.S
>  create mode 100644 tests/xtensa/test_rem.S
>  create mode 100644 tests/xtensa/test_rst0.S
>  create mode 100644 tests/xtensa/test_sar.S
>  create mode 100644 tests/xtensa/test_sext.S
>  create mode 100644 tests/xtensa/test_shift.S
>  create mode 100644 tests/xtensa/test_timer.S
>  create mode 100644 tests/xtensa/test_windowed.S
>  create mode 100644 tests/xtensa/vectors.S
>  create mode 100644 xtensa-semi.c
>
> --
> 1.7.6
>
>
>

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

* Re: [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture
  2011-09-04 18:35 ` [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Blue Swirl
@ 2011-09-05 10:55   ` Edgar E. Iglesias
  2011-09-05 12:35     ` Max Filippov
  0 siblings, 1 reply; 47+ messages in thread
From: Edgar E. Iglesias @ 2011-09-05 10:55 UTC (permalink / raw)
  To: Blue Swirl; +Cc: Max Filippov, Anthony Liguori, qemu-devel

On Sun, Sep 04, 2011 at 06:35:10PM +0000, Blue Swirl wrote:
> On Thu, Sep 1, 2011 at 8:45 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> > This series adds support for Tensilica Xtensa target.
> > Port status: Linux for DC232B works in the qemu.
> >  Not implemented xtensa options: MAC16, floating point coprocessor,
> >  boolean option, cache option, debug option.
> 
> I had minor comments to a few patches, otherwise this looks nice to me.
> 
> Does anyone object to merging this?

I just had a very quick look and it Looks good to me too. Would be awesome
if Max could provide something to test with in binary form. Maybe we could
put it on the wiki's download page.

Cheers

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

* Re: [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture
  2011-09-05 10:55   ` Edgar E. Iglesias
@ 2011-09-05 12:35     ` Max Filippov
  2011-09-14 21:18       ` Edgar E. Iglesias
  0 siblings, 1 reply; 47+ messages in thread
From: Max Filippov @ 2011-09-05 12:35 UTC (permalink / raw)
  To: Edgar E. Iglesias; +Cc: Blue Swirl, Anthony Liguori, qemu-devel

> I just had a very quick look and it Looks good to me too. Would be awesome
> if Max could provide something to test with in binary form. Maybe we could
> put it on the wiki's download page.

Tarball of my current kernel and rootfs is available at
http://jcmvbkbc.spb.ru/~dumb/ws/osll/qemu-xtensa/20110829/xtensa-dc232b_kernel_rootfs.tgz

I can also publish unit tests binaries.

-- 
Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture
  2011-09-05 12:35     ` Max Filippov
@ 2011-09-14 21:18       ` Edgar E. Iglesias
  2011-09-14 22:24         ` Max Filippov
  0 siblings, 1 reply; 47+ messages in thread
From: Edgar E. Iglesias @ 2011-09-14 21:18 UTC (permalink / raw)
  To: Max Filippov; +Cc: Blue Swirl, Anthony Liguori, qemu-devel

On Mon, Sep 05, 2011 at 04:35:44PM +0400, Max Filippov wrote:
> > I just had a very quick look and it Looks good to me too. Would be awesome
> > if Max could provide something to test with in binary form. Maybe we could
> > put it on the wiki's download page.
> 
> Tarball of my current kernel and rootfs is available at
> http://jcmvbkbc.spb.ru/~dumb/ws/osll/qemu-xtensa/20110829/xtensa-dc232b_kernel_rootfs.tgz
> 
> I can also publish unit tests binaries.

Hi Max,

Unit tests would be good too, but it would also be helpful if you could put
the test programs into the rootfs with an easy to run script from within
the guest.

I've put your image on the wiki's download page. Feel free to send updates
and I'll replace the old one.

Cheers

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

* Re: [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture
  2011-09-14 21:18       ` Edgar E. Iglesias
@ 2011-09-14 22:24         ` Max Filippov
  2011-09-14 22:28           ` Edgar E. Iglesias
  0 siblings, 1 reply; 47+ messages in thread
From: Max Filippov @ 2011-09-14 22:24 UTC (permalink / raw)
  To: Edgar E. Iglesias; +Cc: Blue Swirl, Anthony Liguori, qemu-devel

> > Tarball of my current kernel and rootfs is available at
> > http://jcmvbkbc.spb.ru/~dumb/ws/osll/qemu-xtensa/20110829/xtensa-dc232b_kernel_rootfs.tgz
> > 
> > I can also publish unit tests binaries.
> 
> Hi Max,
> 
> Unit tests would be good too, but it would also be helpful if you could put
> the test programs into the rootfs with an easy to run script from within
> the guest.

I mean tests from qemu/tests/xtensa. They're standalone baremetal ELFs, much like tests for chris or lm32.
They don't seem to fit that download page, but if anybody would like to run them the archive is there:

http://jcmvbkbc.spb.ru/~dumb/ws/osll/qemu-xtensa/20110829/xtensa-tests-v5.tgz

> I've put your image on the wiki's download page. Feel free to send updates
> and I'll replace the old one.

Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture
  2011-09-14 22:24         ` Max Filippov
@ 2011-09-14 22:28           ` Edgar E. Iglesias
  0 siblings, 0 replies; 47+ messages in thread
From: Edgar E. Iglesias @ 2011-09-14 22:28 UTC (permalink / raw)
  To: Max Filippov; +Cc: Blue Swirl, Anthony Liguori, qemu-devel

On Thu, Sep 15, 2011 at 02:24:48AM +0400, Max Filippov wrote:
> > > Tarball of my current kernel and rootfs is available at
> > > http://jcmvbkbc.spb.ru/~dumb/ws/osll/qemu-xtensa/20110829/xtensa-dc232b_kernel_rootfs.tgz
> > > 
> > > I can also publish unit tests binaries.
> > 
> > Hi Max,
> > 
> > Unit tests would be good too, but it would also be helpful if you could put
> > the test programs into the rootfs with an easy to run script from within
> > the guest.
> 
> I mean tests from qemu/tests/xtensa. They're standalone baremetal ELFs, much like tests for chris or lm32.
> They don't seem to fit that download page, but if anybody would like to run them the archive is there:

OK, I see. (the CRIS tests are linux user-space programs that run on both
qemu-linux-user or from within a linux guest in system emulation).

Cheers

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

end of thread, other threads:[~2011-09-14 22:28 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 01/32] target-xtensa: add target stubs Max Filippov
2011-09-04 18:14   ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 02/32] target-xtensa: add target to the configure script Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 03/32] target-xtensa: implement disas_xtensa_insn Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 04/32] target-xtensa: implement narrow instructions Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 05/32] target-xtensa: implement RT0 group Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 06/32] target-xtensa: add sample board Max Filippov
2011-09-04 18:17   ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 07/32] target-xtensa: implement conditional jumps Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 08/32] target-xtensa: implement JX/RET0/CALLX Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 09/32] target-xtensa: add special and user registers Max Filippov
2011-09-04 18:18   ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 10/32] target-xtensa: implement RST3 group Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 11/32] target-xtensa: implement shifts (ST1 and RST1 groups) Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 12/32] target-xtensa: implement LSAI group Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 13/32] target-xtensa: mark reserved and TBD opcodes Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 14/32] target-xtensa: implement SYNC group Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 15/32] target-xtensa: implement CACHE group Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 16/32] target-xtensa: add PS register and access control Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 17/32] target-xtensa: implement exceptions Max Filippov
2011-09-04 18:22   ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 18/32] target-xtensa: implement RST2 group (32 bit mul/div/rem) Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 19/32] target-xtensa: implement windowed registers Max Filippov
2011-09-04 18:27   ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 20/32] target-xtensa: implement loop option Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 21/32] target-xtensa: implement extended L32R Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 22/32] target-xtensa: implement unaligned exception option Max Filippov
2011-09-04 18:28   ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 23/32] target-xtensa: implement SIMCALL Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 24/32] target-xtensa: implement interrupt option Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 25/32] target-xtensa: implement accurate window check Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 26/32] target-xtensa: implement CPENABLE and PRID SRs Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 27/32] target-xtensa: implement relocatable vectors Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 28/32] target-xtensa: add gdb support Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 29/32] target-xtensa: implement memory protection options Max Filippov
2011-09-04 18:32   ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 30/32] target-xtensa: add dc232b core and board Max Filippov
2011-09-04 18:33   ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 31/32] MAINTAINERS: add xtensa maintainer Max Filippov
2011-09-01 20:46 ` [Qemu-devel] [PATCH v4 32/32] target-xtensa: add regression testsuite Max Filippov
2011-09-04 18:35 ` [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Blue Swirl
2011-09-05 10:55   ` Edgar E. Iglesias
2011-09-05 12:35     ` Max Filippov
2011-09-14 21:18       ` Edgar E. Iglesias
2011-09-14 22:24         ` Max Filippov
2011-09-14 22:28           ` Edgar E. Iglesias

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.