All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture
@ 2011-05-17 22:32 Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 01/26] target-xtensa: add target stubs Max Filippov
                   ` (25 more replies)
  0 siblings, 26 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel

This series adds support for Tensilica Xtensa target.

Overall RFC -> PATCH changes:
- implement TB chaining;
- replace stray printfs with qemu_logs;
- consolidate big endianness support with corresponding little endianness counterparts;
- removed gdbstub patch from this series, will post a separate RFC for it;
- fix copyrights.

 Makefile.target                      |    4 +
 arch_init.c                          |    2 +
 arch_init.h                          |    1 +
 configure                            |   12 +-
 cpu-exec.c                           |   10 +
 default-configs/xtensa-softmmu.mak   |    1 +
 default-configs/xtensaeb-softmmu.mak |    1 +
 elf.h                                |    2 +
 hw/xtensa_pic.c                      |  121 ++
 hw/xtensa_sample.c                   |  100 ++
 qemu-options.hx                      |    4 +-
 target-xtensa/cpu.h                  |  328 ++++++
 target-xtensa/exec.h                 |   50 +
 target-xtensa/helper.c               |  227 ++++
 target-xtensa/helpers.h              |   24 +
 target-xtensa/machine.c              |   38 +
 target-xtensa/op_helper.c            |  346 ++++++
 target-xtensa/translate.c            | 2152 ++++++++++++++++++++++++++++++++++
 xtensa-semi.c                        |  176 +++
 19 files changed, 3596 insertions(+), 3 deletions(-)

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

* [Qemu-devel] [PATCH 01/26] target-xtensa: add target stubs
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 02/26] target-xtensa: add target to the configure script Max Filippov
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
RFC -> PATCH changes:
- remove cpu_reset from cpu_xtensa_init;
---
 Makefile.target           |    2 +
 arch_init.c               |    2 +
 arch_init.h               |    1 +
 cpu-exec.c                |    4 ++
 elf.h                     |    2 +
 hw/xtensa_pic.c           |   38 ++++++++++++++++++++
 target-xtensa/cpu.h       |   84 +++++++++++++++++++++++++++++++++++++++++++++
 target-xtensa/exec.h      |   50 ++++++++++++++++++++++++++
 target-xtensa/helper.c    |   73 +++++++++++++++++++++++++++++++++++++++
 target-xtensa/machine.c   |   38 ++++++++++++++++++++
 target-xtensa/op_helper.c |   51 +++++++++++++++++++++++++++
 target-xtensa/translate.c |   67 +++++++++++++++++++++++++++++++++++
 12 files changed, 412 insertions(+), 0 deletions(-)
 create mode 100644 hw/xtensa_pic.c
 create mode 100644 target-xtensa/cpu.h
 create mode 100644 target-xtensa/exec.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 2e281a4..2b056d1 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -378,6 +378,8 @@ obj-s390x-y = s390-virtio-bus.o s390-virtio.o
 
 obj-alpha-y = alpha_palcode.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 484b39d..ff48155 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 7323f3c..8787825 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -275,6 +275,7 @@ int cpu_exec(CPUState *env1)
 #elif defined(TARGET_SH4)
 #elif defined(TARGET_CRIS)
 #elif defined(TARGET_S390X)
+#elif defined(TARGET_XTENSA)
     /* XXXXX */
 #else
 #error unsupported target CPU
@@ -348,6 +349,8 @@ int cpu_exec(CPUState *env1)
                     do_interrupt(0);
 #elif defined(TARGET_S390X)
                     do_interrupt(env);
+#elif defined(TARGET_XTENSA)
+                    do_interrupt(env);
 #endif
                     env->exception_index = -1;
 #endif
@@ -690,6 +693,7 @@ int cpu_exec(CPUState *env1)
 #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..176d352
--- /dev/null
+++ b/target-xtensa/cpu.h
@@ -0,0 +1,84 @@
+/*
+ * 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 2
+
+#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"
+
+#endif
diff --git a/target-xtensa/exec.h b/target-xtensa/exec.h
new file mode 100644
index 0000000..9c114ef
--- /dev/null
+++ b/target-xtensa/exec.h
@@ -0,0 +1,50 @@
+/*
+ * 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 "config.h"
+#include "dyngen-exec.h"
+
+register struct CPUXtensaState *env asm(AREG0);
+
+#include "cpu.h"
+#include "exec-all.h"
+
+static inline int cpu_has_work(CPUState *env)
+{
+    return 1;
+}
+
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif
+
+void raise_exception(int);
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+    env->pc = tb->pc;
+}
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
new file mode 100644
index 0000000..7003259
--- /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 = qemu_mallocz(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..43f7772
--- /dev/null
+++ b/target-xtensa/op_helper.c
@@ -0,0 +1,51 @@
+/*
+ * 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 "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.3.4

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

* [Qemu-devel] [PATCH 02/26] target-xtensa: add target to the configure script
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 01/26] target-xtensa: add target stubs Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 03/26] target-xtensa: implement disas_xtensa_insn Max Filippov
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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 d7dba5d..56a06ef 100755
--- a/configure
+++ b/configure
@@ -848,6 +848,8 @@ sh4-softmmu \
 sh4eb-softmmu \
 sparc-softmmu \
 sparc64-softmmu \
+xtensa-softmmu \
+xtensaeb-softmmu \
 "
 fi
 # the following are Linux specific
@@ -3099,7 +3101,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
@@ -3294,6 +3296,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
@@ -3476,6 +3482,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.3.4

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

* [Qemu-devel] [PATCH 03/26] target-xtensa: implement disas_xtensa_insn
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 01/26] target-xtensa: add target stubs Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 02/26] target-xtensa: add target to the configure script Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 04/26] target-xtensa: implement narrow instructions Max Filippov
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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>
---
RFC -> PATCH changes:
- put gen_exit_tb into else clause in gen_jump;
---
 target-xtensa/cpu.h       |   65 +++++++
 target-xtensa/helper.c    |   27 +++-
 target-xtensa/helpers.h   |    5 +
 target-xtensa/op_helper.c |    7 +
 target-xtensa/translate.c |  445 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 547 insertions(+), 2 deletions(-)
 create mode 100644 target-xtensa/helpers.h

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 176d352..d8cd923 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_OPTIN_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,11 @@ 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 xtensa_option_enabled(const XtensaConfig *config, int opt)
+{
+    return (config->options & (((uint64_t)1) << (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 7003259..c6ffcc9 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 = qemu_mallocz(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 43f7772..ecc2f6e 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -26,6 +26,7 @@
  */
 
 #include "exec.h"
+#include "helpers.h"
 
 #define MMUSUFFIX _mmu
 
@@ -49,3 +50,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();
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index e91d8a5..59a28fc 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -36,17 +36,462 @@
 #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]);
+    }
+}
+
+static inline int 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 next_page_start =
+        (env->pc & 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 = env->pc;
+    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;
+
 }
 
 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.3.4

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

* [Qemu-devel] [PATCH 04/26] target-xtensa: implement narrow instructions
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (2 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 03/26] target-xtensa: implement disas_xtensa_insn Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 05/26] target-xtensa: implement RT0 group Max Filippov
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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 59a28fc..d27a47c 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -104,6 +104,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);
@@ -375,22 +380,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.3.4

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

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

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 d27a47c..41ac4f2 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -253,6 +253,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.3.4

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

* [Qemu-devel] [PATCH 06/26] target-xtensa: add sample board
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (4 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 05/26] target-xtensa: implement RT0 group Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 07/26] target-xtensa: implement conditional jumps Max Filippov
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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 |   99 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 100 insertions(+), 0 deletions(-)
 create mode 100644 hw/xtensa_sample.c

diff --git a/Makefile.target b/Makefile.target
index 2b056d1..ca0db72 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -379,6 +379,7 @@ obj-s390x-y = s390-virtio-bus.o s390-virtio.o
 obj-alpha-y = alpha_palcode.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..b818fed
--- /dev/null
+++ b/hw/xtensa_sample.c
@@ -0,0 +1,99 @@
+/*
+ * 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_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);
+        }
+    }
+
+    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.3.4

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

* [Qemu-devel] [PATCH 07/26] target-xtensa: implement conditional jumps
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (5 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 06/26] target-xtensa: add sample board Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 08/26] target-xtensa: implement JX/RET0/CALLX Max Filippov
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

- 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>
---
RFC -> PATCH changes:
- extract common branching code into functions;
---
 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 41ac4f2..3b9ce91 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -119,6 +119,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 { \
@@ -200,6 +219,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);
@@ -393,10 +420,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 { \
@@ -429,6 +589,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.3.4

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

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

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 3b9ce91..0a43ec0 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -246,6 +246,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.3.4

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

* [Qemu-devel] [PATCH 09/26] target-xtensa: add special and user registers
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (7 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 08/26] target-xtensa: implement JX/RET0/CALLX Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-19 20:59   ` Richard Henderson
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 10/26] target-xtensa: implement RST3 group Max Filippov
                   ` (16 subsequent siblings)
  25 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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 d8cd923..0b40fa8 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -99,6 +99,12 @@ enum {
     XTENSA_OPTIN_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 0a43ec0..2fcd36d 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]);
+        }
+    }
 }
 
 static inline int option_enabled(DisasContext *dc, int opt)
@@ -777,9 +804,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.3.4

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

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

- 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>
---
RFC -> PATCH changes:
- optimize SEXT from bits 7 and 15;
---
 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 2fcd36d..b8e7813 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -165,6 +165,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 { \
@@ -413,6 +447,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.3.4

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

* [Qemu-devel] [PATCH 11/26] target-xtensa: implement shifts (ST1 and RST1 groups)
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (9 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 10/26] target-xtensa: implement RST3 group Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-19 21:15   ` Richard Henderson
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 12/26] target-xtensa: implement LSAI group Max Filippov
                   ` (14 subsequent siblings)
  25 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
RFC -> PATCH changes:
- make NSA/NSAU helpers;
- optimize shifts for 5 bit wide SAR;
---
 target-xtensa/cpu.h       |    4 +
 target-xtensa/helpers.h   |    2 +
 target-xtensa/op_helper.c |   14 +++
 target-xtensa/translate.c |  237 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 257 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 0b40fa8..5383a9a 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 ecc2f6e..91a24cf 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -27,6 +27,7 @@
 
 #include "exec.h"
 #include "helpers.h"
+#include "host-utils.h"
 
 #define MMUSUFFIX _mmu
 
@@ -56,3 +57,16 @@ void HELPER(exception)(uint32_t excp)
     env->exception_index = excp;
     cpu_loop_exit();
 }
+
+uint32_t HELPER(nsa)(uint32_t v)
+{
+    if (v & 0x80000000) {
+        v = ~v;
+    }
+    return v ? 31 : clz32(v) - 1;
+}
+
+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 b8e7813..0b84895 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] = {
@@ -108,6 +114,37 @@ static inline int option_enabled(DisasContext *dc, int opt)
     return xtensa_option_enabled(dc->config, opt);
 }
 
+static void reset_sar_tracker(DisasContext *dc)
+{
+    dc->sar_5bit = false;
+    dc->sar_m32_5bit = false;
+    dc->sar_m32_allocated = false;
+}
+
+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);
@@ -182,10 +219,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]) {
@@ -378,6 +426,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*/
@@ -441,6 +548,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*/
@@ -578,6 +800,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*/
@@ -910,6 +1141,8 @@ static void gen_intermediate_code_internal(
     dc.pc = env->pc;
     dc.is_jmp = DISAS_NEXT;
 
+    reset_sar_tracker(&dc);
+
     gen_icount_start();
 
     do {
@@ -944,6 +1177,10 @@ static void gen_intermediate_code_internal(
             dc.pc < next_page_start &&
             gen_opc_ptr < gen_opc_end);
 
+    if (dc.sar_m32_allocated) {
+        tcg_temp_free(dc.sar_m32);
+    }
+
     if (dc.is_jmp == DISAS_NEXT) {
         gen_jumpi(&dc, dc.pc, 0);
     }
-- 
1.7.3.4

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

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

- 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 |   88 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 89 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 5383a9a..d518cab 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 0b84895..a2a1e78 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] = {
@@ -851,7 +852,94 @@ 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, tmp, 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.3.4

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

* [Qemu-devel] [PATCH 13/26] target-xtensa: mark reserved and TBD opcodes
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (11 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 12/26] target-xtensa: implement LSAI group Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 14/26] target-xtensa: implement SYNC group Max Filippov
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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 a2a1e78..6a45bb0 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -258,6 +258,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)
@@ -358,9 +366,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*/
@@ -372,9 +382,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;
@@ -395,6 +407,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                         case 2: /*CALLX8w*/
                         case 3: /*CALLX12w*/
                             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                            TBD();
                             break;
                         }
                         break;
@@ -403,12 +416,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;
 
                 }
@@ -464,13 +524,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*/
@@ -484,11 +547,13 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 default: /*reserved*/
+                    RESERVED();
                     break;
                 }
                 break;
 
             case 5: /*TLB*/
+                TBD();
                 break;
 
             case 6: /*RT0*/
@@ -509,11 +574,13 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 default: /*reserved*/
+                    RESERVED();
                     break;
                 }
                 break;
 
             case 7: /*reserved*/
+                RESERVED();
                 break;
 
             case 8: /*ADD*/
@@ -573,6 +640,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;
 
@@ -662,21 +732,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*/
@@ -769,10 +847,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*/
@@ -782,6 +862,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;
@@ -792,6 +873,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;
@@ -813,27 +895,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;
@@ -885,6 +974,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 7: /*CACHEc*/
+            TBD();
             break;
 
         case 9: /*L16SI*/
@@ -936,6 +1026,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         default: /*reserved*/
+            RESERVED();
             break;
         }
         break;
@@ -943,10 +1034,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*/
@@ -960,6 +1053,7 @@ static void disas_xtensa_insn(DisasContext *dc)
         case 2: /*CALL8w*/
         case 3: /*CALL12w*/
             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+            TBD();
             break;
         }
         break;
@@ -1002,28 +1096,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;
 
                 }
@@ -1159,28 +1260,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.3.4

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

* [Qemu-devel] [PATCH 14/26] target-xtensa: implement SYNC group
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (12 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 13/26] target-xtensa: mark reserved and TBD opcodes Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 15/26] target-xtensa: implement CACHE group Max Filippov
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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 6a45bb0..3a58444 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -420,7 +420,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.3.4

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

* [Qemu-devel] [PATCH 15/26] target-xtensa: implement CACHE group
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (13 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 14/26] target-xtensa: implement SYNC group Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 16/26] target-xtensa: implement exceptions Max Filippov
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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 3a58444..d3509b3 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -1003,7 +1003,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.3.4

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

* [Qemu-devel] [PATCH 16/26] target-xtensa: implement exceptions
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (14 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 15/26] target-xtensa: implement CACHE group Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 17/26] target-xtensa: implement RST2 group (32 bit mul/div/rem) Max Filippov
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
RFC -> PATCH changes:
- make privilege_check based on mem_index;
---
 cpu-exec.c                |    6 +++
 target-xtensa/cpu.h       |  103 +++++++++++++++++++++++++++++++++++++++++-
 target-xtensa/helper.c    |   39 +++++++++++++++-
 target-xtensa/helpers.h   |    2 +
 target-xtensa/op_helper.c |   29 ++++++++++++
 target-xtensa/translate.c |  110 ++++++++++++++++++++++++++++++++++++++++++--
 6 files changed, 282 insertions(+), 7 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index 8787825..d7ad74d 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -565,6 +565,12 @@ int cpu_exec(CPUState *env1)
                         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 d518cab..52fcf18 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -108,11 +108,86 @@ enum {
 enum {
     SAR = 3,
     SCOMPARE1 = 12,
+    EPC1 = 177,
+    DEPC = 192,
+    EXCSAVE1 = 209,
+    PS = 230,
+    EXCCAUSE = 232,
+    EXCVADDR = 238,
+};
+
+#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
+
+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 {
@@ -122,6 +197,8 @@ typedef struct CPUXtensaState {
     uint32_t sregs[256];
     uint32_t uregs[256];
 
+    int exception_taken;
+
     CPU_COMMON
 } CPUXtensaState;
 
@@ -143,9 +220,33 @@ static inline int xtensa_option_enabled(const XtensaConfig *config, int opt)
     return (config->options & (((uint64_t)1) << (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_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 _kernel
+#define MMU_MODE1_SUFFIX _user
+#define MMU_USER_IDX 1
+
 static inline int cpu_mmu_index(CPUState *env)
 {
-    return 0;
+    return xtensa_get_cring(env) != 0;
 }
 
 static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index c6ffcc9..db61bbb 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -36,13 +36,29 @@
 
 void cpu_reset(CPUXtensaState *env)
 {
-    env->pc = 0;
+    env->exception_taken = 0;
+    env->pc = env->config->exception_vector[EXC_RESET];
+    env->sregs[PS] = 0x1f;
 }
 
 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,
+        },
     },
 };
 
@@ -93,4 +109,25 @@ 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;
+
+    }
+    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
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 91a24cf..c10671a 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -58,6 +58,35 @@ void HELPER(exception)(uint32_t excp)
     cpu_loop_exit();
 }
 
+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 d3509b3..7deda1b 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -45,6 +45,7 @@ typedef struct DisasContext {
     TranslationBlock *tb;
     uint32_t pc;
     uint32_t next_pc;
+    int mem_idx;
     int is_jmp;
     int singlestep_enabled;
 
@@ -65,6 +66,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] = {
@@ -153,6 +160,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->mem_idx) {
+        gen_exception_cause(dc, PRIVILEGED_CAUSE);
+    }
+}
+
 static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
 {
     tcg_gen_mov_i32(cpu_pc, dest);
@@ -366,7 +389,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*/
@@ -453,7 +476,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*/
@@ -463,12 +531,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*/
@@ -665,6 +749,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);
@@ -773,6 +860,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();
@@ -780,6 +870,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();
@@ -1394,7 +1487,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 6: /*ILL.Nn*/
-                TBD();
+                gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
                 break;
 
             default: /*reserved*/
@@ -1457,12 +1550,19 @@ static void gen_intermediate_code_internal(
     dc.singlestep_enabled = env->singlestep_enabled;
     dc.tb = tb;
     dc.pc = env->pc;
+    dc.mem_idx = cpu_mmu_index(env);
     dc.is_jmp = DISAS_NEXT;
 
     reset_sar_tracker(&dc);
 
     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.3.4

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

* [Qemu-devel] [PATCH 17/26] target-xtensa: implement RST2 group (32 bit mul/div/rem)
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (15 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 16/26] target-xtensa: implement exceptions Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 18/26] target-xtensa: implement windowed registers Max Filippov
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 7deda1b..8933e5a 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -854,7 +854,65 @@ 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*/
+                tcg_gen_div_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                break;
+
+            case 14: /*REMUi*/
+                tcg_gen_remu_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                break;
+
+            case 15: /*REMSi*/
+                tcg_gen_rem_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                break;
+
+            default: /*reserved*/
+                RESERVED();
+                break;
+            }
             break;
 
         case 3: /*RST3*/
-- 
1.7.3.4

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

* [Qemu-devel] [PATCH 18/26] target-xtensa: implement windowed registers
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (16 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 17/26] target-xtensa: implement RST2 group (32 bit mul/div/rem) Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 19/26] target-xtensa: implement loop option Max Filippov
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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 |  146 +++++++++++++++++++++++++++++++++--
 5 files changed, 339 insertions(+), 9 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 52fcf18..223535c 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);
 
 static inline int xtensa_option_enabled(const XtensaConfig *config, int opt)
 {
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index db61bbb..0eb3b9a 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 c10671a..61d82cf 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -99,3 +99,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 8933e5a..323d67b 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -66,6 +66,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",
@@ -207,6 +209,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)
 {
@@ -253,11 +283,17 @@ 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(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,
     };
 
     if (sregnames[sr]) {
@@ -405,7 +441,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*/
@@ -430,7 +471,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;
@@ -439,7 +486,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*/
@@ -499,7 +551,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*/
@@ -646,7 +718,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*/
@@ -1088,7 +1166,37 @@ 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)));
+                    /*TODO protection control*/
+                    tcg_gen_qemu_ld32u(cpu_R[RRR_T], addr, 0);
+                    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)));
+                    /*TODO protection control*/
+                    tcg_gen_qemu_st32(cpu_R[RRR_T], addr, 0);
+                    tcg_temp_free(addr);
+                }
+                break;
+
+            default:
+                RESERVED();
+                break;
+            }
             break;
 
         case 10: /*FP0*/
@@ -1326,7 +1434,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;
@@ -1369,7 +1478,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*/
@@ -1534,7 +1651,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*/
@@ -1701,6 +1823,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.3.4

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

* [Qemu-devel] [PATCH 19/26] target-xtensa: implement loop option
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (17 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 18/26] target-xtensa: implement windowed registers Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-19 21:51   ` Richard Henderson
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 20/26] target-xtensa: implement extended L32R Max Filippov
                   ` (6 subsequent siblings)
  25 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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>
---
RFC -> PATCH changes:
- add XTENSA_TBFLAG_EXCM, use it in loop ending check;
---
 target-xtensa/cpu.h       |    8 +++++
 target-xtensa/helpers.h   |    1 +
 target-xtensa/op_helper.c |   11 +++++++
 target-xtensa/translate.c |   65 +++++++++++++++++++++++++++++++++++++++-----
 4 files changed, 77 insertions(+), 8 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 223535c..026b854 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,
@@ -257,12 +260,17 @@ static inline int cpu_mmu_index(CPUState *env)
     return xtensa_get_cring(env) != 0;
 }
 
+#define XTENSA_TBFLAG_EXCM 0x1
+
 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;
+    if (env->sregs[PS] & PS_EXCM) {
+        *flags |= XTENSA_TBFLAG_EXCM;
+    }
 }
 
 #include "cpu-all.h"
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index 0971fde..7babf73 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -12,6 +12,7 @@ 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_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 61d82cf..3a0fa01 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -280,6 +280,17 @@ void HELPER(movsp)(uint32_t pc)
     }
 }
 
+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 323d67b..e5e4ce7 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -46,6 +46,7 @@ typedef struct DisasContext {
     uint32_t pc;
     uint32_t next_pc;
     int mem_idx;
+    uint32_t lend;
     int is_jmp;
     int singlestep_enabled;
 
@@ -64,6 +65,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",
@@ -237,13 +241,35 @@ static void gen_callwi(DisasContext *dc, int callinc, uint32_t dest, int slot)
     tcg_temp_free(tmp);
 }
 
+static void 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_NE, cpu_SR[LEND], dc->next_pc, 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_jump(dc, cpu_SR[LBEG]);
+        gen_set_label(label);
+        gen_jumpi(dc, dc->next_pc, slot);
+    }
+}
+
+static void gen_jumpi_check_loop_end(DisasContext *dc, int slot)
+{
+    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);
 }
@@ -273,6 +299,11 @@ static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
     }
 }
 
+static void gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    gen_helper_wsr_lend(v);
+}
+
 static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 {
     tcg_gen_andi_i32(cpu_SR[sr], s, 0x3f);
@@ -292,6 +323,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) = {
+        [LEND] = gen_wsr_lend,
         [SAR] = gen_wsr_sar,
         [WINDOW_BASE] = gen_wsr_windowbase,
     };
@@ -1502,15 +1534,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*/
@@ -1687,7 +1733,9 @@ static void disas_xtensa_insn(DisasContext *dc)
         break;
     }
 
+    gen_check_loop_end(dc, 0);
     dc->pc = dc->next_pc;
+
     return;
 
 invalid_opcode:
@@ -1731,6 +1779,7 @@ static void gen_intermediate_code_internal(
     dc.tb = tb;
     dc.pc = env->pc;
     dc.mem_idx = cpu_mmu_index(env);
+    dc.lend = env->sregs[LEND];
     dc.is_jmp = DISAS_NEXT;
 
     reset_sar_tracker(&dc);
-- 
1.7.3.4

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

* [Qemu-devel] [PATCH 20/26] target-xtensa: implement extended L32R
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (18 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 19/26] target-xtensa: implement loop option Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-19 22:00   ` Richard Henderson
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 21/26] target-xtensa: implement unaligned exception option Max Filippov
                   ` (5 subsequent siblings)
  25 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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>
---
RFC -> PATCH changes:
- add XTENSA_TBFLAG_LITBASE, use it in L32R;
---
 target-xtensa/cpu.h       |    6 ++++++
 target-xtensa/helper.c    |    1 +
 target-xtensa/translate.c |   19 +++++++++++++++----
 3 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 026b854..793a6b5 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,
@@ -261,6 +262,7 @@ static inline int cpu_mmu_index(CPUState *env)
 }
 
 #define XTENSA_TBFLAG_EXCM 0x1
+#define XTENSA_TBFLAG_LITBASE 0x2
 
 static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
         target_ulong *cs_base, int *flags)
@@ -271,6 +273,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 0eb3b9a..ffa5590 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 e5e4ce7..592072a 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -47,6 +47,7 @@ typedef struct DisasContext {
     uint32_t next_pc;
     int mem_idx;
     uint32_t lend;
+    uint32_t litbase;
     int is_jmp;
     int singlestep_enabled;
 
@@ -69,6 +70,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",
@@ -314,6 +316,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_mov_i32(cpu_SR[sr], s);
+    /* 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);
@@ -325,6 +334,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
             uint32_t sr, TCGv_i32 v) = {
         [LEND] = gen_wsr_lend,
         [SAR] = gen_wsr_sar,
+        [LITBASE] = gen_wsr_litbase,
         [WINDOW_BASE] = gen_wsr_windowbase,
     };
 
@@ -1250,10 +1260,10 @@ 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) ?
+                     dc->litbase :
+                     ((dc->pc + 3) & ~3)) +
+                    (0xfffc0000 | (RI16_IMM16 << 2)));
 
             tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, 0);
             tcg_temp_free(tmp);
@@ -1780,6 +1790,7 @@ static void gen_intermediate_code_internal(
     dc.pc = env->pc;
     dc.mem_idx = cpu_mmu_index(env);
     dc.lend = env->sregs[LEND];
+    dc.litbase = env->sregs[LITBASE] & 0xfffff000;
     dc.is_jmp = DISAS_NEXT;
 
     reset_sar_tracker(&dc);
-- 
1.7.3.4

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

* [Qemu-devel] [PATCH 21/26] target-xtensa: implement unaligned exception option
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (19 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 20/26] target-xtensa: implement extended L32R Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-19 22:04   ` Richard Henderson
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 22/26] target-xtensa: implement SIMCALL Max Filippov
                   ` (4 subsequent siblings)
  25 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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/translate.c |   33 +++++++++++++++++++++++++++++++--
 1 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 592072a..6e66f3f 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -177,6 +177,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->mem_idx) {
@@ -349,6 +359,20 @@ 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)
+{
+    TCGv_i32 tmp = tcg_temp_local_new_i32();
+    tcg_gen_mov_i32(tmp, addr);
+    tcg_gen_andi_i32(addr, addr, ~0 << shift);
+    if (option_enabled(dc, XTENSA_OPTION_UNALIGNED_EXCEPTION)) {
+        int label = gen_new_label();
+        tcg_gen_brcond_i32(TCG_COND_EQ, addr, tmp, label);
+        gen_exception_cause_vaddr(dc, LOAD_STORE_ALIGNMENT_CAUSE, tmp);
+        gen_set_label(label);
+    }
+    tcg_temp_free(tmp);
+}
+
 static void disas_xtensa_insn(DisasContext *dc)
 {
 #define HAS_OPTION(opt) do { \
@@ -1272,8 +1296,11 @@ static void disas_xtensa_insn(DisasContext *dc)
 
     case 2: /*LSAI*/
 #define gen_load_store(type, shift) do { \
-            TCGv_i32 addr = tcg_temp_new_i32(); \
+            TCGv_i32 addr = tcg_temp_local_new_i32(); \
             tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \
+            if (shift) { \
+                gen_load_store_alignment(dc, shift, addr); \
+            } \
             tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, 0); \
             tcg_temp_free(addr); \
         } while (0)
@@ -1432,6 +1459,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);
                 tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, 0);
                 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_SR[SCOMPARE1], label);
 
@@ -1657,8 +1685,9 @@ static void disas_xtensa_insn(DisasContext *dc)
         break;
 
 #define gen_narrow_load_store(type) do { \
-            TCGv_i32 addr = tcg_temp_new_i32(); \
+            TCGv_i32 addr = tcg_temp_local_new_i32(); \
             tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
+            gen_load_store_alignment(dc, 2, addr); \
             tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, 0); \
             tcg_temp_free(addr); \
         } while (0)
-- 
1.7.3.4

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

* [Qemu-devel] [PATCH 22/26] target-xtensa: implement SIMCALL
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (20 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 21/26] target-xtensa: implement unaligned exception option Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-19 22:07   ` Richard Henderson
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 23/26] target-xtensa: implement interrupt option Max Filippov
                   ` (3 subsequent siblings)
  25 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
RFC -> PATCH changes:
- use -semihosting to implement SIMCALL;
- fix user memory manipulation code;
- fill in errno for failure cases;
- rename SYS_* to TARGET_SYS_*;
---
 Makefile.target           |    1 +
 qemu-options.hx           |    4 +-
 target-xtensa/cpu.h       |    1 +
 target-xtensa/helpers.h   |    1 +
 target-xtensa/op_helper.c |    5 ++
 target-xtensa/translate.c |    8 ++-
 xtensa-semi.c             |  176 +++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 193 insertions(+), 3 deletions(-)
 create mode 100644 xtensa-semi.c

diff --git a/Makefile.target b/Makefile.target
index ca0db72..1ce0521 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -380,6 +380,7 @@ obj-alpha-y = alpha_palcode.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 82e085a..e2acbf4 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2328,11 +2328,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/cpu.h b/target-xtensa/cpu.h
index 793a6b5..55d81e9 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -226,6 +226,7 @@ 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);
+void simcall(CPUState *env);
 
 static inline int xtensa_option_enabled(const XtensaConfig *config, int opt)
 {
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index 7babf73..87c7cc5 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -13,6 +13,7 @@ DEF_HELPER_2(window_check, void, i32, i32)
 DEF_HELPER_0(restore_owb, void)
 DEF_HELPER_1(movsp, void, i32)
 DEF_HELPER_1(wsr_lend, void, i32)
+DEF_HELPER_0(simcall, void)
 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 3a0fa01..b170dbe 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -291,6 +291,11 @@ void HELPER(wsr_lend)(uint32_t v)
     }
 }
 
+void HELPER(simcall)(void)
+{
+    simcall(env);
+}
+
 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 6e66f3f..b40218d 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
@@ -675,7 +676,12 @@ static void disas_xtensa_insn(DisasContext *dc)
                         break;
 
                     case 1: /*SIMCALL*/
-                        TBD();
+                        if (semihosting_enabled) {
+                            gen_helper_simcall();
+                        } 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..2ce6cc1
--- /dev/null
+++ b/xtensa-semi.c
@@ -0,0 +1,176 @@
+/*
+ * 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 "exec.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_argc = 1000,
+    TARGET_SYS_argv_sz = 1001,
+    TARGET_SYS_argv = 1002,
+    TARGET_SYS_memset = 1004,
+};
+
+void 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:
+        {
+            target_phys_addr_t len = regs[5];
+            void *buf = cpu_physical_memory_map(regs[4], &len, 1);
+
+            if (buf) {
+                regs[2] = read(regs[3], buf, len);
+                regs[3] = errno;
+                cpu_physical_memory_unmap(buf, len, 1, len);
+            } else {
+                regs[2] = -1;
+                regs[3] = EINVAL;
+            }
+        }
+        break;
+
+    case TARGET_SYS_write:
+        {
+            target_phys_addr_t len = regs[5];
+            void *buf = cpu_physical_memory_map(regs[4], &len, 0);
+
+            if (buf) {
+                regs[2] = write(regs[3], buf, len);
+                regs[3] = errno;
+                cpu_physical_memory_unmap(buf, len, 0, len);
+            } else {
+                regs[2] = -1;
+                regs[3] = EINVAL;
+            }
+        }
+        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_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.3.4

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

* [Qemu-devel] [PATCH 23/26] target-xtensa: implement interrupt option
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (21 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 22/26] target-xtensa: implement SIMCALL Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-20 15:44   ` Richard Henderson
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 24/26] target-xtensa: implement accurate window check Max Filippov
                   ` (2 subsequent siblings)
  25 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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>
---
RFC -> PATCH changes:
- halt CPU on waiti, use qemu timer to wake up on CCOMPARE match;
- advance CCOUNT on TB exit, on exception and on RSR.CCOUNT;
---
 hw/xtensa_pic.c           |   83 +++++++++++++++++++++++++++++++
 target-xtensa/cpu.h       |   39 ++++++++++++++
 target-xtensa/exec.h      |    2 +-
 target-xtensa/helper.c    |   80 +++++++++++++++++++++++++++++-
 target-xtensa/helpers.h   |    5 ++
 target-xtensa/op_helper.c |   44 ++++++++++++++++
 target-xtensa/translate.c |  121 ++++++++++++++++++++++++++++++++++++++++++---
 7 files changed, 365 insertions(+), 9 deletions(-)

diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
index 91a5445..de0cdc4 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,84 @@ 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) {
+                env->halted = 0;
+                xtensa_timer_irq(env, i, 1);
+            }
+        }
+    }
+}
+
+void check_interrupts(CPUState *env)
+{
+    int minlevel = xtensa_get_cintlevel(env);
+    int level;
+
+    for (level = env->config->nlevel; level > minlevel; --level) {
+        if (env->config->level_mask[level] &
+                env->sregs[INTSET] &
+                env->sregs[INTENABLE]) {
+            if (env->halted) {
+                xtensa_advance_ccount(env,
+                        muldiv64(qemu_get_clock_ns(vm_clock) - env->halt_clock,
+                            env->config->clock_freq_khz, 1000000));
+            }
+            env->pending_irq_level = level;
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            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 {
+            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 55d81e9..31d3e7e 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,16 @@ enum {
     COPROCESSOR0_DISABLED = 32,
 };
 
+typedef enum {
+    INTTYPE_LEVEL,
+    INTTYPE_EDGE,
+    INTTYPE_NMI,
+    INTTYPE_SOFTWARE,
+    INTTYPE_TIMER,
+    INTTYPE_DEBUG,
+    INTTYPE_WRITE_ERR,
+} interrupt_type_t;
+
 typedef struct XtensaConfig {
     const char *name;
     uint64_t options;
@@ -197,6 +217,15 @@ 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[MAX_NINTERRUPT];
+    uint32_t level_mask[MAX_NLEVEL + MAX_NNMI + 1];
+    interrupt_type_t inttype[MAX_NINTERRUPT];
+    unsigned nccompare;
+    uint32_t timerint[MAX_NCCOMPARE];
+    uint32_t clock_freq_khz;
 } XtensaConfig;
 
 typedef struct CPUXtensaState {
@@ -207,6 +236,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 +257,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);
diff --git a/target-xtensa/exec.h b/target-xtensa/exec.h
index 9c114ef..4f02a85 100644
--- a/target-xtensa/exec.h
+++ b/target-xtensa/exec.h
@@ -35,7 +35,7 @@ register struct CPUXtensaState *env asm(AREG0);
 
 static inline int cpu_has_work(CPUState *env)
 {
-    return 1;
+    return env->pending_irq_level;
 }
 
 #if !defined(CONFIG_USER_ONLY)
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index ffa5590..4c3069f 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -40,6 +40,8 @@ void cpu_reset(CPUXtensaState *env)
     env->pc = env->config->exception_vector[EXC_RESET];
     env->sregs[LITBASE] &= ~1;
     env->sregs[PS] = 0x1f;
+
+    env->pending_irq_level = 0;
 }
 
 static const XtensaConfig core_config[] = {
@@ -61,6 +63,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 = {
+            [0] = 4,
+        },
+        .level_mask = {
+            [4] = 1,
+        },
+        .inttype = {
+            [0] = INTTYPE_TIMER,
+        },
+        .nccompare = 1,
+        .timerint = {
+            [0] = 0,
+        },
+        .clock_freq_khz = 912000,
     },
 };
 
@@ -90,6 +117,7 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
         xtensa_translate_init();
     }
 
+    xtensa_irq_init(env);
     qemu_init_vcpu(env);
     return env;
 }
@@ -109,9 +137,55 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
     return addr;
 }
 
+static int handle_interrupt(CPUState *env)
+{
+    int handled = 1;
+    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->pc = env->config->interrupt_vector[level];
+        } else {
+            handled = 0;
+            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] = (env->sregs[PS] & ~PS_INTLEVEL) | PS_EXCM | level;
+        env->exception_taken = 1;
+        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+    }
+    return handled;
+}
+
 void do_interrupt(CPUState *env)
 {
     switch (env->exception_index) {
+    case EXC_IRQ:
+        if (handle_interrupt(env)) {
+            break;
+        }
+        /* not handled interrupt falls through,
+         * env->exception_index is updated
+         */
+
     case EXC_WINDOW_OVERFLOW4:
     case EXC_WINDOW_UNDERFLOW4:
     case EXC_WINDOW_OVERFLOW8:
@@ -124,12 +198,16 @@ void do_interrupt(CPUState *env)
         if (env->config->exception_vector[env->exception_index]) {
             env->pc = env->config->exception_vector[env->exception_index];
             env->exception_taken = 1;
+            env->interrupt_request |= CPU_INTERRUPT_EXITTB;
         } else {
             qemu_log("%s(pc = %08x) bad exception_index: %d\n",
                     __func__, env->pc, env->exception_index);
         }
         break;
 
+    default:
+        qemu_log("%s(pc = %08x) unknown exception_index: %d\n",
+                __func__, env->pc, env->exception_index);
+        break;
     }
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index 87c7cc5..bbc0ebc 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -16,4 +16,9 @@ DEF_HELPER_1(wsr_lend, void, i32)
 DEF_HELPER_0(simcall, void)
 DEF_HELPER_0(dump_state, void)
 
+DEF_HELPER_0(check_interrupts, void)
+DEF_HELPER_2(waiti, void, i32, i32)
+DEF_HELPER_2(timer_irq, void, i32, i32)
+DEF_HELPER_1(advance_ccount, void, i32)
+
 #include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index b170dbe..d742f1b 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -300,3 +300,47 @@ void HELPER(dump_state)(void)
 {
     cpu_dump_state(env, stderr, fprintf, 0);
 }
+
+void HELPER(check_interrupts)(void)
+{
+    check_interrupts(env);
+}
+
+void HELPER(waiti)(uint32_t pc, uint32_t intlevel)
+{
+    env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) |
+        (intlevel << PS_INTLEVEL_SHIFT);
+    check_interrupts(env);
+    if (env->pending_irq_level) {
+        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);
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index b40218d..450c302 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -56,6 +56,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;
@@ -76,11 +78,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] = {
@@ -162,9 +189,27 @@ 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_check_interrupts(DisasContext *dc)
+{
+    gen_advance_ccount(dc);
+    tcg_gen_movi_i32(cpu_pc, dc->pc);
+    gen_helper_check_interrupts();
+}
+
+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);
 }
@@ -173,6 +218,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);
@@ -183,6 +229,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);
@@ -199,8 +246,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);
@@ -295,10 +343,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]) {
@@ -339,6 +394,25 @@ 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)
+{
+    tcg_gen_mov_i32(cpu_SR[sr], v);
+    gen_check_interrupts(dc);
+    /* This can change 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)
+{
+    TCGv_i32 id = tcg_const_i32(sr - CCOMPARE);
+    TCGv_i32 active = tcg_const_i32(0);
+    gen_advance_ccount(dc);
+    tcg_gen_mov_i32(cpu_SR[sr], v);
+    gen_helper_timer_irq(id, active);
+    tcg_temp_free(id);
+    tcg_temp_free(active);
+}
+
 static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 {
     static void (* const wsr_handler[256])(DisasContext *dc,
@@ -347,6 +421,10 @@ 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,
+        [PS] = gen_wsr_ps,
+        [CCOMPARE] = gen_wsr_ccompare,
+        [CCOMPARE + 1] = gen_wsr_ccompare,
+        [CCOMPARE + 2] = gen_wsr_ccompare,
     };
 
     if (sregnames[sr]) {
@@ -374,6 +452,16 @@ static void gen_load_store_alignment(DisasContext *dc, int shift, TCGv_i32 addr)
     tcg_temp_free(tmp);
 }
 
+static void gen_waiti(DisasContext *dc, uint32_t imm4)
+{
+    TCGv_i32 pc = tcg_const_i32(dc->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 { \
@@ -510,6 +598,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);
@@ -555,6 +644,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);
@@ -649,7 +739,9 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                     case 1: /*RFIx*/
                         HAS_OPTION(XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT);
-                        TBD();
+                        gen_check_privilege(dc);
+                        tcg_gen_mov_i32(cpu_SR[PS], cpu_SR[EPS2 + RRR_S - 2]);
+                        gen_jump(dc, cpu_SR[EPC1 + RRR_S - 1]);
                         break;
 
                     case 2: /*RFME*/
@@ -697,11 +789,13 @@ static void disas_xtensa_insn(DisasContext *dc)
                     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_check_interrupts(dc);
                     break;
 
                 case 7: /*WAITIx*/
                     HAS_OPTION(XTENSA_OPTION_INTERRUPT);
-                    TBD();
+                    gen_check_privilege(dc);
+                    gen_waiti(dc, RRR_S);
                     break;
 
                 case 8: /*ANY4p*/
@@ -1558,6 +1652,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);
@@ -1744,6 +1839,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);
@@ -1797,7 +1893,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;
              }
         }
@@ -1827,6 +1923,7 @@ static void gen_intermediate_code_internal(
     dc.lend = env->sregs[LEND];
     dc.litbase = env->sregs[LITBASE] & 0xfffff000;
     dc.is_jmp = DISAS_NEXT;
+    dc.ccount_delta = 0;
 
     reset_sar_tracker(&dc);
 
@@ -1835,7 +1932,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 {
@@ -1858,11 +1955,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 &&
@@ -1874,6 +1977,10 @@ static void gen_intermediate_code_internal(
         tcg_temp_free(dc.sar_m32);
     }
 
+    if (tb->cflags & CF_LAST_IO) {
+        gen_io_end();
+    }
+
     if (dc.is_jmp == DISAS_NEXT) {
         gen_jumpi(&dc, dc.pc, 0);
     }
-- 
1.7.3.4

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

* [Qemu-devel] [PATCH 24/26] target-xtensa: implement accurate window check
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (22 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 23/26] target-xtensa: implement interrupt option Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-20 15:58   ` Richard Henderson
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 25/26] target-xtensa: implement CPENABLE and PRID SRs Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 26/26] target-xtensa: implement relocatable vectors Max Filippov
  25 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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 |  105 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 105 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 450c302..9fcd2aa 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -58,6 +58,7 @@ typedef struct DisasContext {
     TCGv_i32 sar_m32;
 
     uint32_t ccount_delta;
+    unsigned used_window;
 } DisasContext;
 
 static TCGv_ptr cpu_env;
@@ -206,6 +207,11 @@ static void gen_check_interrupts(DisasContext *dc)
     gen_helper_check_interrupts();
 }
 
+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);
@@ -392,11 +398,19 @@ 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_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     tcg_gen_mov_i32(cpu_SR[sr], v);
+    reset_used_window(dc);
     gen_check_interrupts(dc);
     /* This can change tb->flags, so exit tb */
     gen_jumpi_check_loop_end(dc, -1);
@@ -421,6 +435,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,
         [PS] = gen_wsr_ps,
         [CCOMPARE] = gen_wsr_ccompare,
         [CCOMPARE + 1] = gen_wsr_ccompare,
@@ -462,6 +477,32 @@ static void gen_waiti(DisasContext *dc, uint32_t imm4)
     tcg_temp_free(intlevel);
 }
 
+static void gen_window_check1(DisasContext *dc, unsigned r1)
+{
+    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);
+
+        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 { \
@@ -591,6 +632,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;
 
@@ -612,6 +654,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*/
                             {
@@ -642,6 +685,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);
@@ -785,6 +829,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_ori_i32(cpu_SR[PS], cpu_SR[PS], RRR_S);
                     tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS],
@@ -826,28 +871,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);
@@ -857,6 +908,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);
@@ -890,16 +942,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;
 
@@ -914,6 +969,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]);
@@ -941,12 +997,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);
@@ -956,12 +1014,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);
@@ -976,17 +1036,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;
 
@@ -996,6 +1059,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);
@@ -1022,6 +1086,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]);
@@ -1030,6 +1095,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 {
@@ -1040,6 +1106,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 {
@@ -1054,6 +1121,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 {
@@ -1067,6 +1135,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();
@@ -1080,6 +1149,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();
@@ -1098,6 +1168,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();
@@ -1165,6 +1237,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();
@@ -1175,6 +1248,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();
@@ -1183,6 +1257,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;
 
@@ -1201,6 +1276,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();
@@ -1228,6 +1304,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,
@@ -1255,6 +1332,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,
@@ -1280,6 +1358,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]) {
@@ -1292,6 +1371,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]);
@@ -1307,6 +1387,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;
@@ -1332,6 +1413,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);
@@ -1382,6 +1464,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) ?
@@ -1397,6 +1480,7 @@ static void disas_xtensa_insn(DisasContext *dc)
     case 2: /*LSAI*/
 #define gen_load_store(type, shift) 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 << shift); \
             if (shift) { \
                 gen_load_store_alignment(dc, shift, addr); \
@@ -1532,6 +1616,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         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));
@@ -1543,15 +1628,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();
@@ -1604,6 +1692,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;
@@ -1617,6 +1706,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*/
@@ -1631,6 +1721,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*/
@@ -1657,6 +1748,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;
 
@@ -1676,6 +1768,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);
@@ -1707,6 +1800,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;
@@ -1722,6 +1816,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]);
@@ -1733,6 +1828,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,
@@ -1748,6 +1844,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]);
@@ -1758,6 +1855,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();
@@ -1772,6 +1870,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],
@@ -1787,6 +1886,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
 #define gen_narrow_load_store(type) do { \
             TCGv_i32 addr = tcg_temp_local_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); \
             tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, 0); \
@@ -1803,14 +1903,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) |
@@ -1826,6 +1929,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;
 
@@ -1926,6 +2030,7 @@ static void gen_intermediate_code_internal(
     dc.ccount_delta = 0;
 
     reset_sar_tracker(&dc);
+    reset_used_window(&dc);
 
     gen_icount_start();
 
-- 
1.7.3.4

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

* [Qemu-devel] [PATCH 25/26] target-xtensa: implement CPENABLE and PRID SRs
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (23 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 24/26] target-xtensa: implement accurate window check Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 26/26] target-xtensa: implement relocatable vectors Max Filippov
  25 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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 b818fed..0657b65 100644
--- a/hw/xtensa_sample.c
+++ b/hw/xtensa_sample.c
@@ -45,6 +45,7 @@ static void xtensa_init(ram_addr_t ram_size,
             fprintf(stderr, "Unable to find CPU definition\n");
             exit(1);
         }
+        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 31d3e7e..de3408f 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 9fcd2aa..8d25bde 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -99,12 +99,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",
@@ -416,6 +418,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)
 {
     TCGv_i32 id = tcg_const_i32(sr - CCOMPARE);
@@ -437,6 +443,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [WINDOW_BASE] = gen_wsr_windowbase,
         [WINDOW_START] = gen_wsr_windowstart,
         [PS] = gen_wsr_ps,
+        [PRID] = gen_wsr_prid,
         [CCOMPARE] = gen_wsr_ccompare,
         [CCOMPARE + 1] = gen_wsr_ccompare,
         [CCOMPARE + 2] = gen_wsr_ccompare,
-- 
1.7.3.4

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

* [Qemu-devel] [PATCH 26/26] target-xtensa: implement relocatable vectors
  2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
                   ` (24 preceding siblings ...)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 25/26] target-xtensa: implement CPENABLE and PRID SRs Max Filippov
@ 2011-05-17 22:32 ` Max Filippov
  25 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-17 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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 de3408f..d1d5b2b 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,
@@ -218,6 +219,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 4c3069f..28d36ae 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -40,6 +40,7 @@ void cpu_reset(CPUXtensaState *env)
     env->pc = env->config->exception_vector[EXC_RESET];
     env->sregs[LITBASE] &= ~1;
     env->sregs[PS] = 0x1f;
+    env->sregs[VECBASE] = env->config->vecbase;
 
     env->pending_irq_level = 0;
 }
@@ -51,6 +52,7 @@ static const XtensaConfig core_config[] = {
         .nareg = 64,
         .ndepc = 1,
         .excm_level = 16,
+        .vecbase = 0x5fff8400,
         .exception_vector = {
             [EXC_RESET] = 0x5fff8000,
             [EXC_WINDOW_OVERFLOW4] = 0x5fff8400,
@@ -137,6 +139,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;
+    }
+}
+
 static int handle_interrupt(CPUState *env)
 {
     int handled = 1;
@@ -150,7 +162,8 @@ static int handle_interrupt(CPUState *env)
         if (level > 1) {
             env->sregs[EPC1 + level - 1] = env->pc;
             env->sregs[EPS2 + level - 2] = env->sregs[PS];
-            env->pc = env->config->interrupt_vector[level];
+            env->pc = relocated_vector(env,
+                    env->config->interrupt_vector[level]);
         } else {
             handled = 0;
             env->sregs[EXCCAUSE] = LEVEL1_INTERRUPT_CAUSE;
@@ -196,7 +209,8 @@ void do_interrupt(CPUState *env)
     case EXC_USER:
     case EXC_DOUBLE:
         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;
             env->interrupt_request |= CPU_INTERRUPT_EXITTB;
         } else {
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 8d25bde..8efe609 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -104,6 +104,7 @@ static const char * const sregnames[256] = {
     [INTCLEAR] = "INTCLEAR",
     [INTENABLE] = "INTENABLE",
     [PS] = "PS",
+    [VECBASE] = "VECBASE",
     [EXCCAUSE] = "EXCCAUSE",
     [CCOUNT] = "CCOUNT",
     [PRID] = "PRID",
-- 
1.7.3.4

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

* Re: [Qemu-devel] [PATCH 09/26] target-xtensa: add special and user registers
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 09/26] target-xtensa: add special and user registers Max Filippov
@ 2011-05-19 20:59   ` Richard Henderson
  2011-05-20  7:34     ` Max Filippov
  0 siblings, 1 reply; 56+ messages in thread
From: Richard Henderson @ 2011-05-19 20:59 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/17/2011 03:32 PM, Max Filippov wrote:
> +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];

Is it really worthwhile allocating 2k worth of space in the
CPUState when only several of the slots are actually used?

I would think that it might be better to have a function to
map between number to offset/register.  E.g.

int ur_offset(int ur)
{
    switch (ur) {
    case THREADPTR:
        return offsetof(CPUState, ur_threadptr);
    case FCR:
        return offsetof(CPUState, ur_fcr);
    case FSR:
        return offsetof(CPUState, ur_fsr);
    }
    return -1;
}

where the individual slots are allocated by hand in the
CPUState.  The fact that they'll be named in the struct
will also make it easier to dump the value inside gdb and
see what the individual values are.


r~

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

* Re: [Qemu-devel] [PATCH 11/26] target-xtensa: implement shifts (ST1 and RST1 groups)
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 11/26] target-xtensa: implement shifts (ST1 and RST1 groups) Max Filippov
@ 2011-05-19 21:15   ` Richard Henderson
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2011-05-19 21:15 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/17/2011 03:32 PM, Max Filippov wrote:
> +uint32_t HELPER(nsa)(uint32_t v)
> +{
> +    if (v & 0x80000000) {
> +        v = ~v;
> +    }
> +    return v ? 31 : clz32(v) - 1;

Condition is reversed here.


r~

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

* Re: [Qemu-devel] [PATCH 19/26] target-xtensa: implement loop option
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 19/26] target-xtensa: implement loop option Max Filippov
@ 2011-05-19 21:51   ` Richard Henderson
  2011-05-20  7:25     ` Max Filippov
  0 siblings, 1 reply; 56+ messages in thread
From: Richard Henderson @ 2011-05-19 21:51 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/17/2011 03:32 PM, Max Filippov wrote:
> +    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);
> +    }

Why are you invalidating twice?

> +static void 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_NE, cpu_SR[LEND], dc->next_pc, 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_jump(dc, cpu_SR[LBEG]);
> +        gen_set_label(label);
> +        gen_jumpi(dc, dc->next_pc, slot);

If you're going to pretend that LEND is a constant, you might as well
pretend that LBEG is also a constant, so that you get to chain the TB's
around the loop.

> +static void gen_jumpi_check_loop_end(DisasContext *dc, int slot)
> +{
> +    gen_check_loop_end(dc, slot);
> +    gen_jumpi(dc, dc->next_pc, slot);

You're generating duplicate jumpi's here; that can probably be avoided
fairly easily.


r~

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

* Re: [Qemu-devel] [PATCH 20/26] target-xtensa: implement extended L32R
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 20/26] target-xtensa: implement extended L32R Max Filippov
@ 2011-05-19 22:00   ` Richard Henderson
  2011-05-20  7:14     ` Max Filippov
  0 siblings, 1 reply; 56+ messages in thread
From: Richard Henderson @ 2011-05-19 22:00 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/17/2011 03:32 PM, Max Filippov wrote:
> +static void gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s)
> +{
> +    tcg_gen_mov_i32(cpu_SR[sr], s);
> +    /* This can change tb->flags, so exit tb */
> +    gen_jumpi_check_loop_end(dc, -1);
> +}

Surely you have to flush all TB's when changing litbase?

> +                    ((dc->tb->flags & XTENSA_TBFLAG_LITBASE) ?
> +                     dc->litbase :
> +                     ((dc->pc + 3) & ~3)) +
> +                    (0xfffc0000 | (RI16_IMM16 << 2)));

Unless you actually read from env->sr[LITBASE] here, instead
of building the value into the TB.


r~

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

* Re: [Qemu-devel] [PATCH 21/26] target-xtensa: implement unaligned exception option
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 21/26] target-xtensa: implement unaligned exception option Max Filippov
@ 2011-05-19 22:04   ` Richard Henderson
  2011-05-22 12:10     ` Max Filippov
  0 siblings, 1 reply; 56+ messages in thread
From: Richard Henderson @ 2011-05-19 22:04 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/17/2011 03:32 PM, Max Filippov 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/translate.c |   33 +++++++++++++++++++++++++++++++--
>  1 files changed, 31 insertions(+), 2 deletions(-)
> 
> diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
> index 592072a..6e66f3f 100644
> --- a/target-xtensa/translate.c
> +++ b/target-xtensa/translate.c
> @@ -177,6 +177,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->mem_idx) {
> @@ -349,6 +359,20 @@ 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)
> +{
> +    TCGv_i32 tmp = tcg_temp_local_new_i32();
> +    tcg_gen_mov_i32(tmp, addr);
> +    tcg_gen_andi_i32(addr, addr, ~0 << shift);
> +    if (option_enabled(dc, XTENSA_OPTION_UNALIGNED_EXCEPTION)) {
> +        int label = gen_new_label();
> +        tcg_gen_brcond_i32(TCG_COND_EQ, addr, tmp, label);
> +        gen_exception_cause_vaddr(dc, LOAD_STORE_ALIGNMENT_CAUSE, tmp);
> +        gen_set_label(label);
> +    }
> +    tcg_temp_free(tmp);
> +}

This is not the correct method for this.  Set ALIGNED_ONLY before
defining the softmmu_templates.  Define do_unaligned_access to raise
the exception.  See e.g. target-sparc/op_helper.c.


r~

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

* Re: [Qemu-devel] [PATCH 22/26] target-xtensa: implement SIMCALL
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 22/26] target-xtensa: implement SIMCALL Max Filippov
@ 2011-05-19 22:07   ` Richard Henderson
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2011-05-19 22:07 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/17/2011 03:32 PM, Max Filippov wrote:
> +DEF_HELPER_0(simcall, void)
>  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 3a0fa01..b170dbe 100644
> --- a/target-xtensa/op_helper.c
> +++ b/target-xtensa/op_helper.c
> @@ -291,6 +291,11 @@ void HELPER(wsr_lend)(uint32_t v)
>      }
>  }
>  
> +void HELPER(simcall)(void)
> +{
> +    simcall(env);
> +}
> +

You can explicitly pass env as an argument to the helper
and avoid this wrapper function.  See e.g. the ARM port
and its many non-op_helper.c functions.


r~

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

* Re: [Qemu-devel] [PATCH 20/26] target-xtensa: implement extended L32R
  2011-05-19 22:00   ` Richard Henderson
@ 2011-05-20  7:14     ` Max Filippov
  2011-05-20 15:30       ` Richard Henderson
  0 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-20  7:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson

> > +static void gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s)
> > +{
> > +    tcg_gen_mov_i32(cpu_SR[sr], s);
> > +    /* This can change tb->flags, so exit tb */
> > +    gen_jumpi_check_loop_end(dc, -1);
> > +}
> 
> Surely you have to flush all TB's when changing litbase?
> 
> > +                    ((dc->tb->flags & XTENSA_TBFLAG_LITBASE) ?
> > +                     dc->litbase :
> > +                     ((dc->pc + 3) & ~3)) +
> > +                    (0xfffc0000 | (RI16_IMM16 << 2)));
> 
> Unless you actually read from env->sr[LITBASE] here, instead
> of building the value into the TB.

You're right, I have to flush all TBs at gen_wsr_litbase for this code to always work correctly.
As far as I can see LITBASE usage pattern is that it is set up once in early initialization and is never changed after.

Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH 19/26] target-xtensa: implement loop option
  2011-05-19 21:51   ` Richard Henderson
@ 2011-05-20  7:25     ` Max Filippov
  2011-05-20  9:10       ` Max Filippov
  0 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-20  7:25 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

> > +    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);
> > +    }
> 
> Why are you invalidating twice?

TB at the old LEND and at the new. Although it will work correctly without first invalidation.

> > +static void 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_NE, cpu_SR[LEND], dc->next_pc, 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_jump(dc, cpu_SR[LBEG]);
> > +        gen_set_label(label);
> > +        gen_jumpi(dc, dc->next_pc, slot);
> 
> If you're going to pretend that LEND is a constant, you might as well
> pretend that LBEG is also a constant, so that you get to chain the TB's
> around the loop.

But there may be three exits from TB at the LEND if its last command is a branch: to the LBEG, to the branch target and to the next insn.

Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH 09/26] target-xtensa: add special and user registers
  2011-05-19 20:59   ` Richard Henderson
@ 2011-05-20  7:34     ` Max Filippov
  2011-05-20 14:18       ` Richard Henderson
  0 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-20  7:34 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

> > +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];
> 
> Is it really worthwhile allocating 2k worth of space in the
> CPUState when only several of the slots are actually used?
> 
> I would think that it might be better to have a function to
> map between number to offset/register.  E.g.
> 
> int ur_offset(int ur)
> {
>     switch (ur) {
>     case THREADPTR:
>         return offsetof(CPUState, ur_threadptr);
>     case FCR:
>         return offsetof(CPUState, ur_fcr);
>     case FSR:
>         return offsetof(CPUState, ur_fsr);
>     }
>     return -1;
> }
> 
> where the individual slots are allocated by hand in the
> CPUState.  The fact that they'll be named in the struct
> will also make it easier to dump the value inside gdb and
> see what the individual values are.

User registers represent TIE states that may appear in custom xtensa configurations. I'd better change RUR and WUR so that they can access all user registers but warn on those not defined globally or in the CPUEnv::config.
Is it OK?

Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH 19/26] target-xtensa: implement loop option
  2011-05-20  7:25     ` Max Filippov
@ 2011-05-20  9:10       ` Max Filippov
  2011-05-20 14:14         ` Richard Henderson
  0 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-20  9:10 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

>> > +    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);
>> > +    }
>>
>> Why are you invalidating twice?
>
> TB at the old LEND and at the new. Although it will work correctly without first invalidation.
>
>> > +static void 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_NE, cpu_SR[LEND], dc->next_pc, 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_jump(dc, cpu_SR[LBEG]);
>> > +        gen_set_label(label);
>> > +        gen_jumpi(dc, dc->next_pc, slot);
>>
>> If you're going to pretend that LEND is a constant, you might as well
>> pretend that LBEG is also a constant, so that you get to chain the TB's
>> around the loop.
>
> But there may be three exits from TB at the LEND if its last command is a branch: to the LBEG, to the branch target and to the next insn.

Ok, I guess that I need to add gen_wsr_lbeg that invalidates TB at the
current LEND, pretend that LBEG is constant and use given slot to jump
to it. And also to get rid of tcg_gen_brcondi_i32(TCG_COND_NE,
cpu_SR[LEND], dc->next_pc, label);

-- 
Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH 19/26] target-xtensa: implement loop option
  2011-05-20  9:10       ` Max Filippov
@ 2011-05-20 14:14         ` Richard Henderson
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2011-05-20 14:14 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/20/2011 02:10 AM, Max Filippov wrote:
>>> If you're going to pretend that LEND is a constant, you might as well
>>> pretend that LBEG is also a constant, so that you get to chain the TB's
>>> around the loop.
>>
>> But there may be three exits from TB at the LEND if its last
>> command is a branch: to the LBEG, to the branch target and to the
>> next insn.
> 
> Ok, I guess that I need to add gen_wsr_lbeg that invalidates TB at the
> current LEND, pretend that LBEG is constant and use given slot to jump
> to it. And also to get rid of tcg_gen_brcondi_i32(TCG_COND_NE,
> cpu_SR[LEND], dc->next_pc, label);

Yes.

Consider that the code is written to assume that the loop cycles,
so the most likely exit at LEND is LBEG.  If we choose to mirror
that logic inside TCG, then of the 3 possible exits from the block
one of them should be LBEG so that the most likely edge can get
chained.


r~

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

* Re: [Qemu-devel] [PATCH 09/26] target-xtensa: add special and user registers
  2011-05-20  7:34     ` Max Filippov
@ 2011-05-20 14:18       ` Richard Henderson
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2011-05-20 14:18 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/20/2011 12:34 AM, Max Filippov wrote:
> User registers represent TIE states that may appear in custom xtensa
> configurations. I'd better change RUR and WUR so that they can access
> all user registers but warn on those not defined globally or in the
> CPUEnv::config. Is it OK?

Well, it's ok if you change nothing.  However, I wanted you to think
about other ways that might make sense than simply allocating all of
the registers.


r~

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

* Re: [Qemu-devel] [PATCH 20/26] target-xtensa: implement extended L32R
  2011-05-20  7:14     ` Max Filippov
@ 2011-05-20 15:30       ` Richard Henderson
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2011-05-20 15:30 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/20/2011 12:14 AM, Max Filippov wrote:
> As far as I can see LITBASE usage pattern is that it is set up once
> in early initialization and is never changed after.

That's probably true on a per-program basis.  I.e. for semi-hosting or userland
emulation, hard-coding litbase into the TB could make sense.

However, for full system emulation, with kernel and userland et al, I would 
expect that litbase would tend to be set per-application.  At which point it
would almost certainly be more efficient to read the value at runtime.


r~

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

* Re: [Qemu-devel] [PATCH 23/26] target-xtensa: implement interrupt option
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 23/26] target-xtensa: implement interrupt option Max Filippov
@ 2011-05-20 15:44   ` Richard Henderson
  2011-05-20 20:05     ` Max Filippov
  0 siblings, 1 reply; 56+ messages in thread
From: Richard Henderson @ 2011-05-20 15:44 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/17/2011 03:32 PM, Max Filippov wrote:
> +    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) {
> +                env->halted = 0;
> +                xtensa_timer_irq(env, i, 1);

I don't think you should be writing to halted here; this is done by
the code in cpu-exec.c, when noticing when cpu_has_work.  Which will
be true as a function of env->interrupt_request and the interrupt mask.


> +            if (env->halted) {
> +                xtensa_advance_ccount(env,
> +                        muldiv64(qemu_get_clock_ns(vm_clock) - env->halt_clock,
> +                            env->config->clock_freq_khz, 1000000));
> +            }

Why are you polling the vm_clock rather than setting up a timer?

> +        env->ccompare_timer =
> +            qemu_new_timer_ns(vm_clock, &xtensa_ccompare_cb, env);

... er, actually you are setting up a timer.  So why aren't you using it?

>  void do_interrupt(CPUState *env)
>  {
>      switch (env->exception_index) {
> +    case EXC_IRQ:
> +        if (handle_interrupt(env)) {
> +            break;
> +        }
> +        /* not handled interrupt falls through,
> +         * env->exception_index is updated
> +         */

Do you really want to fall through, rather than restart the switch?

> @@ -124,12 +198,16 @@ void do_interrupt(CPUState *env)
>          if (env->config->exception_vector[env->exception_index]) {
>              env->pc = env->config->exception_vector[env->exception_index];
>              env->exception_taken = 1;
> +            env->interrupt_request |= CPU_INTERRUPT_EXITTB;

Huh?  What are you trying to accomplish here?
EXITTB is supposed to be used when a device external to the cpu
changes the memory mapping of the system.  E.g. the x86 a20 line.

> +DEF_HELPER_0(check_interrupts, void)
> +DEF_HELPER_2(waiti, void, i32, i32)
> +DEF_HELPER_2(timer_irq, void, i32, i32)
> +DEF_HELPER_1(advance_ccount, void, i32)

You shouldn't have to manage any of this from within the translator.


r~

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

* Re: [Qemu-devel] [PATCH 24/26] target-xtensa: implement accurate window check
  2011-05-17 22:32 ` [Qemu-devel] [PATCH 24/26] target-xtensa: implement accurate window check Max Filippov
@ 2011-05-20 15:58   ` Richard Henderson
  2011-05-20 19:04     ` Max Filippov
  0 siblings, 1 reply; 56+ messages in thread
From: Richard Henderson @ 2011-05-20 15:58 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/17/2011 03:32 PM, Max Filippov wrote:
> +static void gen_window_check1(DisasContext *dc, unsigned r1)
> +{
> +    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);
> +
> +        gen_advance_ccount(dc);
> +        gen_helper_window_check(pc, w);
> +
> +        tcg_temp_free(w);
> +        tcg_temp_free(pc);
> +    }

dc->used_window is never set to non-zero.  I assume you meant
to do that here?



r~

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

* Re: [Qemu-devel] [PATCH 24/26] target-xtensa: implement accurate window check
  2011-05-20 15:58   ` Richard Henderson
@ 2011-05-20 19:04     ` Max Filippov
  0 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-20 19:04 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

> > +static void gen_window_check1(DisasContext *dc, unsigned r1)
> > +{
> > +    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);
> > +
> > +        gen_advance_ccount(dc);
> > +        gen_helper_window_check(pc, w);
> > +
> > +        tcg_temp_free(w);
> > +        tcg_temp_free(pc);
> > +    }
> 
> dc->used_window is never set to non-zero.  I assume you meant
> to do that here?

Oops (. Thank you, indeed.

Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH 23/26] target-xtensa: implement interrupt option
  2011-05-20 15:44   ` Richard Henderson
@ 2011-05-20 20:05     ` Max Filippov
  2011-05-20 20:49       ` Richard Henderson
  0 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-20 20:05 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

> > +    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) {
> > +                env->halted = 0;
> > +                xtensa_timer_irq(env, i, 1);
> 
> I don't think you should be writing to halted here; this is done by
> the code in cpu-exec.c, when noticing when cpu_has_work.  Which will
> be true as a function of env->interrupt_request and the interrupt mask.

I do it here to distinguish interrupt caused by CCOMPARE match, for which I want exact CCOUNT value, from other interrupt sources, when CCOUNT may be advanced approximately.

> > +            if (env->halted) {
> > +                xtensa_advance_ccount(env,
> > +                        muldiv64(qemu_get_clock_ns(vm_clock) - env->halt_clock,
> > +                            env->config->clock_freq_khz, 1000000));
> > +            }
> 
> Why are you polling the vm_clock rather than setting up a timer?

I'm not polling, I'm adjusting ccount according to vm_clock time passed since we were halted.

> > +        env->ccompare_timer =
> > +            qemu_new_timer_ns(vm_clock, &xtensa_ccompare_cb, env);
> 
> ... er, actually you are setting up a timer.  So why aren't you using it?

I'm using it: it is wound up by HELPER(waiti) when there's no currently pending interrupts and xtensa_ccompare_cb calls xtensa_advance_ccount, which in turn calls xtensa_timer_irq.

> >  void do_interrupt(CPUState *env)
> >  {
> >      switch (env->exception_index) {
> > +    case EXC_IRQ:
> > +        if (handle_interrupt(env)) {
> > +            break;
> > +        }
> > +        /* not handled interrupt falls through,
> > +         * env->exception_index is updated
> > +         */
> 
> Do you really want to fall through, rather than restart the switch?

Handle_interrupt will handle high-priority interrupt requests, leaving only level-1 interrupts, which it converts into EXC_USER or EXC_KERNEL. If only for the sake of readability...

> > @@ -124,12 +198,16 @@ void do_interrupt(CPUState *env)
> >          if (env->config->exception_vector[env->exception_index]) {
> >              env->pc = env->config->exception_vector[env->exception_index];
> >              env->exception_taken = 1;
> > +            env->interrupt_request |= CPU_INTERRUPT_EXITTB;
> 
> Huh?  What are you trying to accomplish here?
> EXITTB is supposed to be used when a device external to the cpu
> changes the memory mapping of the system.  E.g. the x86 a20 line.

I used it to have next_tb = 0 in cpu_exec, after return from do_interrupt, but now it is done unconditionally, so there's no need in CPU_INTERRUPT_EXITTB.
By the way, do I understand it right that if I chain TBs than I need to periodically check for pending interrupts myself, otherwise e.g. "j $" will create uninterruptible infinite loop?

> > +DEF_HELPER_0(check_interrupts, void)
> > +DEF_HELPER_2(waiti, void, i32, i32)
> > +DEF_HELPER_2(timer_irq, void, i32, i32)
> > +DEF_HELPER_1(advance_ccount, void, i32)
> 
> You shouldn't have to manage any of this from within the translator.

Please explain.

Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH 23/26] target-xtensa: implement interrupt option
  2011-05-20 20:05     ` Max Filippov
@ 2011-05-20 20:49       ` Richard Henderson
  2011-05-20 21:30         ` Max Filippov
  0 siblings, 1 reply; 56+ messages in thread
From: Richard Henderson @ 2011-05-20 20:49 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/20/2011 01:05 PM, Max Filippov wrote:
> By the way, do I understand it right that if I chain TBs than I need
> to periodically check for pending interrupts myself, otherwise e.g.
> "j $" will create uninterruptible infinite loop?

No, it won't.  It'll create a loop, but it'll be broken by the host
signal handler.  Notice no other target is checking for this.

>>> +DEF_HELPER_0(check_interrupts, void)
>>> +DEF_HELPER_2(waiti, void, i32, i32)
>>> +DEF_HELPER_2(timer_irq, void, i32, i32)
>>> +DEF_HELPER_1(advance_ccount, void, i32)
>>
>> You shouldn't have to manage any of this from within the translator.

You should *never* have to check for interrupts, or advance cycle counters,
from within the translated code.  Interrupt processing, and thus timers,
are handled in between TBs as necessary by generic code.


r~

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

* Re: [Qemu-devel] [PATCH 23/26] target-xtensa: implement interrupt option
  2011-05-20 20:49       ` Richard Henderson
@ 2011-05-20 21:30         ` Max Filippov
  2011-05-20 22:19           ` Richard Henderson
  0 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-20 21:30 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

> > By the way, do I understand it right that if I chain TBs than I need
> > to periodically check for pending interrupts myself, otherwise e.g.
> > "j $" will create uninterruptible infinite loop?
> 
> No, it won't.  It'll create a loop, but it'll be broken by the host
> signal handler.  Notice no other target is checking for this.
> 
> >>> +DEF_HELPER_0(check_interrupts, void)
> >>> +DEF_HELPER_2(waiti, void, i32, i32)
> >>> +DEF_HELPER_2(timer_irq, void, i32, i32)
> >>> +DEF_HELPER_1(advance_ccount, void, i32)
> >>
> >> You shouldn't have to manage any of this from within the translator.
> 
> You should *never* have to check for interrupts, or advance cycle counters,
> from within the translated code.  Interrupt processing, and thus timers,
> are handled in between TBs as necessary by generic code.

Well,
- cycles fed into advance_ccount may (and on real hardware actually do) depend on executed commands/pipeline/cache hits. Most of this stuff may be counted at the translation time;
- timer_irq is a helper that raises IRQ generated by CCOMPARE match;
- waiti is a helper for the instruction of the same name;
- check_interrupts converts IRQs on enabled interrupt sources into current irq level.

Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH 23/26] target-xtensa: implement interrupt option
  2011-05-20 21:30         ` Max Filippov
@ 2011-05-20 22:19           ` Richard Henderson
  2011-05-24 10:28             ` Max Filippov
  0 siblings, 1 reply; 56+ messages in thread
From: Richard Henderson @ 2011-05-20 22:19 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/20/2011 02:30 PM, Max Filippov wrote:
> - cycles fed into advance_ccount may (and on real hardware actually
> do) depend on executed commands/pipeline/cache hits. Most of this
> stuff may be counted at the translation time;

Since CCOUNT, as seen by any one thread of execution, on real hw depends
on cache hits, interrupts, and other asynchronous stuff, then don't bother
trying to account for it on a per-instruction basis.  Just define a clock
that runs at a given rate and be done.  No need to advance it manually.

> - timer_irq is a helper that raises IRQ generated by CCOMPARE match;

That's what the callback from qemu_new_timer_ns is for.

You've got N CCOMPARE registers, you can create N timers all of which
are setup to raise the IRQ.

cpu_xtensa_init(...)
{
    ...
    for (i = 0; i < N; ++i)
        env->ccompare_timer[i] = qemu_new_timer(vm_clock, HZ, xtensa_ccompare_cb, env);
}

void xtensa_ccompare_cb(CPUState *env)
{
    /* Set something in the processor state.  */
    cpu_interrupt(env, CPU_INTERRUPT_HARD);
}

void HELPER(wsr_ccompare)(int which, uint32_t match)
{
    qemu_mod_timer(env->ccompare_timer[which], match);
}

> - waiti is a helper for the instruction of the same name;

Sure, this one should exist for the translator.  But it should do nothing
except change PS.INTLEVEL, set env->halted, and do cpu_loop_exit.  All of
the actual waiting should be in the main QEMU loop.

Because it exits to the main loop, it should also end the TB.

> - check_interrupts converts IRQs on enabled interrupt sources into current irq level.

This is needed during do_interrupt, but should not be used by the translator itself.

You may find some of this easier if you utilize the IRQ cleanup patch series that
was recently committed to HEAD.  See CPU_INTERRUPT_TGT_EXT_[0-4] in cpu-all.h and
its uses in the various targets.


r~

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

* Re: [Qemu-devel] [PATCH 21/26] target-xtensa: implement unaligned exception option
  2011-05-19 22:04   ` Richard Henderson
@ 2011-05-22 12:10     ` Max Filippov
  2011-05-22 16:57       ` Richard Henderson
  0 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-22 12:10 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

> > +static void gen_load_store_alignment(DisasContext *dc, int shift, TCGv_i32 addr)
> > +{
> > +    TCGv_i32 tmp = tcg_temp_local_new_i32();
> > +    tcg_gen_mov_i32(tmp, addr);
> > +    tcg_gen_andi_i32(addr, addr, ~0 << shift);
> > +    if (option_enabled(dc, XTENSA_OPTION_UNALIGNED_EXCEPTION)) {
> > +        int label = gen_new_label();
> > +        tcg_gen_brcond_i32(TCG_COND_EQ, addr, tmp, label);
> > +        gen_exception_cause_vaddr(dc, LOAD_STORE_ALIGNMENT_CAUSE, tmp);
> > +        gen_set_label(label);
> > +    }
> > +    tcg_temp_free(tmp);
> > +}
> 
> This is not the correct method for this.  Set ALIGNED_ONLY before
> defining the softmmu_templates.  Define do_unaligned_access to raise
> the exception.  See e.g. target-sparc/op_helper.c.

There are three alignment possibilities for xtensa: no unaligned exception, unaligned exception and hardware alignment.
In the first case unaligned access silently goes to aligned address. It looks like it cannot be done via do_unaligned_access, can it?
In the third case most unaligned accesses are handled transparently by the hardware. But e.g. unaligned access by multiprocessor synchronization instructions still cause alignment exception. Do I need to implement a different alignment checking mechanism for those unhandled cases?

Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH 21/26] target-xtensa: implement unaligned exception option
  2011-05-22 12:10     ` Max Filippov
@ 2011-05-22 16:57       ` Richard Henderson
  2011-05-22 20:12         ` Max Filippov
  0 siblings, 1 reply; 56+ messages in thread
From: Richard Henderson @ 2011-05-22 16:57 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/22/2011 05:10 AM, Max Filippov wrote:
> There are three alignment possibilities for xtensa: no unaligned
> exception, unaligned exception and hardware alignment. In the first
> case unaligned access silently goes to aligned address. It looks like
> it cannot be done via do_unaligned_access, can it? In the third case
> most unaligned accesses are handled transparently by the hardware.
> But e.g. unaligned access by multiprocessor synchronization
> instructions still cause alignment exception. Do I need to implement
> a different alignment checking mechanism for those unhandled cases?

Case (1), silently going to an aligned address, should be handled
inside the translator by masking the address before the load.  See
the ARM and Alpha targets for examples.

Case (2) and (3) are both handled by using ALIGNED_ONLY.  All you
need to do to handle (3) is *not* throw an exception from the
do_unaligned_access function.  See how the code is structured
inside softmmu_template.h.

As for sync insns... You may need to handle it all out-of-line
and check for alignment there.


r~

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

* Re: [Qemu-devel] [PATCH 21/26] target-xtensa: implement unaligned exception option
  2011-05-22 16:57       ` Richard Henderson
@ 2011-05-22 20:12         ` Max Filippov
  2011-05-23 13:51           ` Richard Henderson
  0 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-22 20:12 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

> > There are three alignment possibilities for xtensa: no unaligned
> > exception, unaligned exception and hardware alignment. In the first
> > case unaligned access silently goes to aligned address. It looks like
> > it cannot be done via do_unaligned_access, can it? In the third case
> > most unaligned accesses are handled transparently by the hardware.
> > But e.g. unaligned access by multiprocessor synchronization
> > instructions still cause alignment exception. Do I need to implement
> > a different alignment checking mechanism for those unhandled cases?
> 
> Case (1), silently going to an aligned address, should be handled
> inside the translator by masking the address before the load.  See
> the ARM and Alpha targets for examples.

This is what gen_load_store_alignment does.

> Case (2) and (3) are both handled by using ALIGNED_ONLY.  All you
> need to do to handle (3) is *not* throw an exception from the
> do_unaligned_access function.  See how the code is structured
> inside softmmu_template.h.
> 
> As for sync insns... You may need to handle it all out-of-line
> and check for alignment there.

This is also done by gen_load_store_alignment.
Does it really worth copying part of this logic to do_unaligned_access just to use ALIGNED_ONLY framework?

Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH 21/26] target-xtensa: implement unaligned exception option
  2011-05-22 20:12         ` Max Filippov
@ 2011-05-23 13:51           ` Richard Henderson
  2011-05-23 23:20             ` Max Filippov
  0 siblings, 1 reply; 56+ messages in thread
From: Richard Henderson @ 2011-05-23 13:51 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/22/2011 01:12 PM, Max Filippov wrote:
> This is also done by gen_load_store_alignment.
> Does it really worth copying part of this logic to do_unaligned_access just to use ALIGNED_ONLY framework?

Yes, because it is done out-of-line, as a part of the TLB load slow path.


r~

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

* Re: [Qemu-devel] [PATCH 21/26] target-xtensa: implement unaligned exception option
  2011-05-23 13:51           ` Richard Henderson
@ 2011-05-23 23:20             ` Max Filippov
  2011-05-24 14:57               ` Richard Henderson
  0 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-23 23:20 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

> > This is also done by gen_load_store_alignment.
> > Does it really worth copying part of this logic to do_unaligned_access just to use ALIGNED_ONLY framework?
> 
> Yes, because it is done out-of-line, as a part of the TLB load slow path.

I probably just don't get what you call 'out-of-line'. In fact do_unaligned_access will be called for every unaligned access, and alignment condition will be checked for every access. It just happens in other place.
Does it have more chances to be optimized better than TCG code, or is it less TCG code itself that makes difference?

Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH 23/26] target-xtensa: implement interrupt option
  2011-05-20 22:19           ` Richard Henderson
@ 2011-05-24 10:28             ` Max Filippov
  2011-05-24 14:59               ` Richard Henderson
  0 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2011-05-24 10:28 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

>> - cycles fed into advance_ccount may (and on real hardware actually
>> do) depend on executed commands/pipeline/cache hits. Most of this
>> stuff may be counted at the translation time;
>
> Since CCOUNT, as seen by any one thread of execution, on real hw depends
> on cache hits, interrupts, and other asynchronous stuff, then don't bother
> trying to account for it on a per-instruction basis.  Just define a clock
> that runs at a given rate and be done.  No need to advance it manually.

It means no cycle-accurate emulation. This was one of my goals, maybe
not closest one. Is it acceptable to have two simulation modes -- fast
functional and slower cycle-accurate?

>> - check_interrupts converts IRQs on enabled interrupt sources into current irq level.
> This is needed during do_interrupt, but should not be used by the translator itself.

Not only during do_interrupt, but also in cpu_has_work.

Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH 21/26] target-xtensa: implement unaligned exception option
  2011-05-23 23:20             ` Max Filippov
@ 2011-05-24 14:57               ` Richard Henderson
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2011-05-24 14:57 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/23/2011 04:20 PM, Max Filippov wrote:
> I probably just don't get what you call 'out-of-line'. In fact
> do_unaligned_access will be called for every unaligned access, and
> alignment condition will be checked for every access. It just happens
> in other place. Does it have more chances to be optimized better than
> TCG code, or is it less TCG code itself that makes difference?

Out of line meaning not inside TCG code at all.

The fast-path through a tcg_qemu_ld operation handles aligned memory
accesses that hit the TLB.  Unaligned accesses or TLB misses go to
the slow path, in __ld[bwlq]_mmu.  It is in these functions that we
test for ALIGNED_ONLY, which enables the do_unaligned_access hook.


r~

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

* Re: [Qemu-devel] [PATCH 23/26] target-xtensa: implement interrupt option
  2011-05-24 10:28             ` Max Filippov
@ 2011-05-24 14:59               ` Richard Henderson
  2011-05-24 15:11                 ` Max Filippov
  0 siblings, 1 reply; 56+ messages in thread
From: Richard Henderson @ 2011-05-24 14:59 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/24/2011 03:28 AM, Max Filippov wrote:
>>> - cycles fed into advance_ccount may (and on real hardware actually
>>> do) depend on executed commands/pipeline/cache hits. Most of this
>>> stuff may be counted at the translation time;
>>
>> Since CCOUNT, as seen by any one thread of execution, on real hw depends
>> on cache hits, interrupts, and other asynchronous stuff, then don't bother
>> trying to account for it on a per-instruction basis.  Just define a clock
>> that runs at a given rate and be done.  No need to advance it manually.
> 
> It means no cycle-accurate emulation. This was one of my goals, maybe
> not closest one. Is it acceptable to have two simulation modes -- fast
> functional and slower cycle-accurate?

Huh.  Given that you're not modeling the caches, I don't see how you could
hope for true cycle accuracy.  As for whether a mostly-cycle-accurate mode
should be a goal...  I'll have to defer to other QEMU maintainers.


r~

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

* Re: [Qemu-devel] [PATCH 23/26] target-xtensa: implement interrupt option
  2011-05-24 14:59               ` Richard Henderson
@ 2011-05-24 15:11                 ` Max Filippov
  0 siblings, 0 replies; 56+ messages in thread
From: Max Filippov @ 2011-05-24 15:11 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

>>>> - cycles fed into advance_ccount may (and on real hardware actually
>>>> do) depend on executed commands/pipeline/cache hits. Most of this
>>>> stuff may be counted at the translation time;
>>>
>>> Since CCOUNT, as seen by any one thread of execution, on real hw depends
>>> on cache hits, interrupts, and other asynchronous stuff, then don't bother
>>> trying to account for it on a per-instruction basis.  Just define a clock
>>> that runs at a given rate and be done.  No need to advance it manually.
>>
>> It means no cycle-accurate emulation. This was one of my goals, maybe
>> not closest one. Is it acceptable to have two simulation modes -- fast
>> functional and slower cycle-accurate?
>
> Huh.  Given that you're not modeling the caches, I don't see how you could
> hope for true cycle accuracy.  As for whether a mostly-cycle-accurate mode
> should be a goal...  I'll have to defer to other QEMU maintainers.

I'm going to model them finally, as well as pipeline and TCM/external
memory. Just need a stable basis to start with (:

-- 
Thanks.
-- Max

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

end of thread, other threads:[~2011-05-24 15:12 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-17 22:32 [Qemu-devel] [PATCH 00/26] target-xtensa: introduce new target architecture Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 01/26] target-xtensa: add target stubs Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 02/26] target-xtensa: add target to the configure script Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 03/26] target-xtensa: implement disas_xtensa_insn Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 04/26] target-xtensa: implement narrow instructions Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 05/26] target-xtensa: implement RT0 group Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 06/26] target-xtensa: add sample board Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 07/26] target-xtensa: implement conditional jumps Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 08/26] target-xtensa: implement JX/RET0/CALLX Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 09/26] target-xtensa: add special and user registers Max Filippov
2011-05-19 20:59   ` Richard Henderson
2011-05-20  7:34     ` Max Filippov
2011-05-20 14:18       ` Richard Henderson
2011-05-17 22:32 ` [Qemu-devel] [PATCH 10/26] target-xtensa: implement RST3 group Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 11/26] target-xtensa: implement shifts (ST1 and RST1 groups) Max Filippov
2011-05-19 21:15   ` Richard Henderson
2011-05-17 22:32 ` [Qemu-devel] [PATCH 12/26] target-xtensa: implement LSAI group Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 13/26] target-xtensa: mark reserved and TBD opcodes Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 14/26] target-xtensa: implement SYNC group Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 15/26] target-xtensa: implement CACHE group Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 16/26] target-xtensa: implement exceptions Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 17/26] target-xtensa: implement RST2 group (32 bit mul/div/rem) Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 18/26] target-xtensa: implement windowed registers Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 19/26] target-xtensa: implement loop option Max Filippov
2011-05-19 21:51   ` Richard Henderson
2011-05-20  7:25     ` Max Filippov
2011-05-20  9:10       ` Max Filippov
2011-05-20 14:14         ` Richard Henderson
2011-05-17 22:32 ` [Qemu-devel] [PATCH 20/26] target-xtensa: implement extended L32R Max Filippov
2011-05-19 22:00   ` Richard Henderson
2011-05-20  7:14     ` Max Filippov
2011-05-20 15:30       ` Richard Henderson
2011-05-17 22:32 ` [Qemu-devel] [PATCH 21/26] target-xtensa: implement unaligned exception option Max Filippov
2011-05-19 22:04   ` Richard Henderson
2011-05-22 12:10     ` Max Filippov
2011-05-22 16:57       ` Richard Henderson
2011-05-22 20:12         ` Max Filippov
2011-05-23 13:51           ` Richard Henderson
2011-05-23 23:20             ` Max Filippov
2011-05-24 14:57               ` Richard Henderson
2011-05-17 22:32 ` [Qemu-devel] [PATCH 22/26] target-xtensa: implement SIMCALL Max Filippov
2011-05-19 22:07   ` Richard Henderson
2011-05-17 22:32 ` [Qemu-devel] [PATCH 23/26] target-xtensa: implement interrupt option Max Filippov
2011-05-20 15:44   ` Richard Henderson
2011-05-20 20:05     ` Max Filippov
2011-05-20 20:49       ` Richard Henderson
2011-05-20 21:30         ` Max Filippov
2011-05-20 22:19           ` Richard Henderson
2011-05-24 10:28             ` Max Filippov
2011-05-24 14:59               ` Richard Henderson
2011-05-24 15:11                 ` Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 24/26] target-xtensa: implement accurate window check Max Filippov
2011-05-20 15:58   ` Richard Henderson
2011-05-20 19:04     ` Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 25/26] target-xtensa: implement CPENABLE and PRID SRs Max Filippov
2011-05-17 22:32 ` [Qemu-devel] [PATCH 26/26] target-xtensa: implement relocatable vectors Max Filippov

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.