All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs
@ 2011-05-04  0:59 Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 02/28] target-xtensa: add target to the configure script Max Filippov
                   ` (28 more replies)
  0 siblings, 29 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 Makefile.target           |    2 +
 arch_init.c               |    2 +
 arch_init.h               |    1 +
 cpu-exec.c                |   10 +++++
 elf.h                     |    2 +
 hw/xtensa_pic.c           |   11 ++++++
 target-xtensa/cpu.h       |   84 +++++++++++++++++++++++++++++++++++++++++++++
 target-xtensa/exec.h      |   55 +++++++++++++++++++++++++++++
 target-xtensa/helper.c    |   74 +++++++++++++++++++++++++++++++++++++++
 target-xtensa/machine.c   |   38 ++++++++++++++++++++
 target-xtensa/op_helper.c |   51 +++++++++++++++++++++++++++
 target-xtensa/translate.c |   67 +++++++++++++++++++++++++++++++++++
 12 files changed, 397 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 21f864a..7e7afd2 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -366,6 +366,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 0c09f91..c1f0005 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 86ebc14..61ad347 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 395cd8c..a692daf 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
@@ -568,6 +571,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 interupt_request value,
                       do_interrupt may have updated the EXITTB flag. */
@@ -696,6 +705,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..5ff1697
--- /dev/null
+++ b/hw/xtensa_pic.c
@@ -0,0 +1,11 @@
+#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..ef6881a
--- /dev/null
+++ b/target-xtensa/cpu.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Motorola Solutions, Inc.
+ * 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 Motorola Solutions 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..5a0cb6f
--- /dev/null
+++ b/target-xtensa/exec.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Motorola Solutions, Inc.
+ * 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 Motorola Solutions 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;
+}
+
+static inline int cpu_halted(CPUState *env)
+{
+    return 0;
+}
+
+#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..6b6e17b
--- /dev/null
+++ b/target-xtensa/helper.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Motorola Solutions, Inc.
+ * 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 Motorola Solutions 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();
+    }
+
+    cpu_reset(env);
+    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..ea45d01
--- /dev/null
+++ b/target-xtensa/machine.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Motorola Solutions, Inc.
+ * 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 Motorola Solutions 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..5a0e068
--- /dev/null
+++ b/target-xtensa/op_helper.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Motorola Solutions, Inc.
+ * 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 Motorola Solutions 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..c47feab
--- /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, Motorola Solutions, Inc.
+ * 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 Motorola Solutions 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] 49+ messages in thread

* [Qemu-devel] [RFC 02/28] target-xtensa: add target to the configure script
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 03/28] target-xtensa: implement disas_xtensa_insn Max Filippov
                   ` (27 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

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

diff --git a/configure b/configure
index 6f75e2e..d8c33b9 100755
--- a/configure
+++ b/configure
@@ -1028,6 +1028,7 @@ sh4-softmmu \
 sh4eb-softmmu \
 sparc-softmmu \
 sparc64-softmmu \
+xtensa-softmmu \
 "
     fi
 # the following are Linux specific
@@ -3210,6 +3211,10 @@ case "$target_arch2" in
   unicore32)
     target_phys_bits=32
   ;;
+  xtensa)
+    TARGET_ARCH=xtensa
+    target_phys_bits=32
+  ;;
   *)
     echo "Unsupported target CPU"
     exit 1
@@ -3385,6 +3390,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
-- 
1.7.3.4

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

* [Qemu-devel] [RFC 03/28] target-xtensa: implement disas_xtensa_insn
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 02/28] target-xtensa: add target to the configure script Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04 15:39   ` Richard Henderson
  2011-05-04  0:59 ` [Qemu-devel] [RFC 04/28] target-xtensa: implement narrow instructions Max Filippov
                   ` (26 subsequent siblings)
  28 siblings, 1 reply; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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>
---
 target-xtensa/cpu.h       |   60 +++++++
 target-xtensa/helper.c    |   27 +++-
 target-xtensa/helpers.h   |    5 +
 target-xtensa/op_helper.c |    7 +
 target-xtensa/translate.c |  374 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 471 insertions(+), 2 deletions(-)
 create mode 100644 target-xtensa/helpers.h

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index ef6881a..cf19fce 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];
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 6b6e17b..6f374d3 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) {
@@ -60,8 +80,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 5a0e068..d1e620c 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 c47feab..16efcfd 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -36,17 +36,391 @@
 #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;
+    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 void gen_exception(int excp)
+{
+    TCGv_i32 tmp = tcg_const_i32(excp);
+    gen_helper_exception(tmp);
+    tcg_temp_free(tmp);
+}
+
+static void gen_jump(DisasContext *dc, TCGv dest)
+{
+    tcg_gen_mov_i32(cpu_pc, dest);
+    if (dc->singlestep_enabled) {
+        gen_exception(EXCP_DEBUG);
+    }
+    tcg_gen_exit_tb(0);
+    dc->is_jmp = DISAS_UPDATE;
+}
+
+static void gen_jumpi(DisasContext *dc, uint32_t dest)
+{
+    TCGv_i32 tmp = tcg_const_i32(dest);
+    gen_jump(dc, tmp);
+    tcg_temp_free(tmp);
+}
+
+static void disas_xtensa_insn(DisasContext *dc)
+{
+#define HAS_OPTION(opt) do { \
+        if (!(dc->config->options & (((uint64_t)1) << (opt)))) { \
+            goto invalid_opcode; \
+        } \
+    } while (0)
+
+#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)
+
+#define RRRN_R RRR_R
+#define RRRN_S RRR_S
+#define RRRN_T RRR_T
+
+#define RI16_IMM16 (((_b1) << 8) | (_b2))
+
+#define CALL_N (((_b0) & 0xc) >> 2)
+#define CALL_OFFSET ((((_b0) & 0x3) << 16) | ((_b1) << 8) | (_b2))
+#define CALL_OFFSET_SE (((_b0 & 0x2) ? 0xfffc0000 : 0) | CALL_OFFSET)
+
+    uint8_t _b0 = ldub_code(dc->pc);
+    uint8_t _b1 = ldub_code(dc->pc + 1);
+    uint8_t _b2 = ldub_code(dc->pc + 2);
+
+    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->pc + 3);
+            gen_jumpi(dc, (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4);
+            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);
+            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;
+    }
+
+    if (_OP0 >= 8) {
+        dc->pc += 2;
+        HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
+    } else {
+        dc->pc += 3;
+    }
+    return;
+
+invalid_opcode:
+    printf("INVALID(pc = %08x): %s:%d\n", dc->pc, __FILE__, __LINE__);
+    dc->pc += (_OP0 >= 8) ? 2 : 3;
+#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;
+
+    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 &&
+            gen_opc_ptr < gen_opc_end);
+
+    if (dc.is_jmp == DISAS_NEXT) {
+        tcg_gen_movi_i32(cpu_pc, dc.pc);
+        tcg_gen_exit_tb(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] 49+ messages in thread

* [Qemu-devel] [RFC 04/28] target-xtensa: implement narrow instructions
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 02/28] target-xtensa: add target to the configure script Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 03/28] target-xtensa: implement disas_xtensa_insn Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 05/28] target-xtensa: implement RT0 group Max Filippov
                   ` (25 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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 |   57 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 16efcfd..26fc28b 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -301,22 +301,79 @@ 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*/
+            int label = gen_new_label();
+            int inv = RRRN_T & 4;
+
+            tcg_gen_brcondi_i32(inv ? TCG_COND_EQ : TCG_COND_NE,
+                    cpu_R[RRRN_S], 0, label);
+            gen_jumpi(dc, dc->pc + 4 + (RRRN_R | ((RRRN_T & 3) << 4)));
+            gen_set_label(label);
+            gen_jumpi(dc, dc->pc + 2);
+        }
         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] 49+ messages in thread

* [Qemu-devel] [RFC 05/28] target-xtensa: implement RT0 group
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (2 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 04/28] target-xtensa: implement narrow instructions Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 06/28] target-xtensa: add sample board Max Filippov
                   ` (24 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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 26fc28b..49f4940 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -174,6 +174,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] 49+ messages in thread

* [Qemu-devel] [RFC 06/28] target-xtensa: add sample board
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (3 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 05/28] target-xtensa: implement RT0 group Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 07/28] target-xtensa: add gdb support Max Filippov
                   ` (23 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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 |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+), 0 deletions(-)
 create mode 100644 hw/xtensa_sample.c

diff --git a/Makefile.target b/Makefile.target
index 7e7afd2..8d6d081 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -367,6 +367,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..8103675
--- /dev/null
+++ b/hw/xtensa_sample.c
@@ -0,0 +1,68 @@
+#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;
+
+        int success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                &elf_lowaddr, NULL, 0, ELF_MACHINE, 0);
+        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] 49+ messages in thread

* [Qemu-devel] [RFC 07/28] target-xtensa: add gdb support
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (4 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 06/28] target-xtensa: add sample board Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 08/28] target-xtensa: implement conditional jumps Max Filippov
                   ` (22 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 configure                          |    1 +
 default-configs/xtensa-softmmu.mak |    1 +
 gdb-xml/xtensa-core.xml            |   24 ++++++++++++++++++++++
 gdbstub.c                          |   39 ++++++++++++++++++++++++++++++++++++
 4 files changed, 65 insertions(+), 0 deletions(-)
 create mode 100644 gdb-xml/xtensa-core.xml

diff --git a/configure b/configure
index d8c33b9..41a7007 100755
--- a/configure
+++ b/configure
@@ -3213,6 +3213,7 @@ case "$target_arch2" in
   ;;
   xtensa)
     TARGET_ARCH=xtensa
+    gdb_xml_files="xtensa-core.xml"
     target_phys_bits=32
   ;;
   *)
diff --git a/default-configs/xtensa-softmmu.mak b/default-configs/xtensa-softmmu.mak
index e5faa09..57ad848 100644
--- a/default-configs/xtensa-softmmu.mak
+++ b/default-configs/xtensa-softmmu.mak
@@ -1 +1,2 @@
 # Default configuration for Xtensa
+CONFIG_GDBSTUB_XML=y
diff --git a/gdb-xml/xtensa-core.xml b/gdb-xml/xtensa-core.xml
new file mode 100644
index 0000000..e71d8bc
--- /dev/null
+++ b/gdb-xml/xtensa-core.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.xtensa.core">
+  <reg name="pc" bitsize="32" type="code_ptr"/>
+  <reg name="a0" bitsize="32"/>
+  <reg name="a1" bitsize="32"/>
+  <reg name="a2" bitsize="32"/>
+  <reg name="a3" bitsize="32"/>
+  <reg name="a4" bitsize="32"/>
+  <reg name="a5" bitsize="32"/>
+  <reg name="a6" bitsize="32"/>
+  <reg name="a7" bitsize="32"/>
+  <reg name="a8" bitsize="32"/>
+  <reg name="a9" bitsize="32"/>
+  <reg name="a10" bitsize="32"/>
+  <reg name="a11" bitsize="32"/>
+  <reg name="a12" bitsize="32"/>
+  <reg name="a13" bitsize="32"/>
+  <reg name="a14" bitsize="32"/>
+  <reg name="a15" bitsize="32"/>
+
+  <reg name="windowbase" bitsize="32" regnum="38"/>
+  <reg name="ps" bitsize="32" regnum="42"/>
+</feature>
diff --git a/gdbstub.c b/gdbstub.c
index 0838948..9f6145f 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1541,6 +1541,43 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
     }
     return 4;
 }
+#elif defined(TARGET_XTENSA)
+
+#define GDB_CORE_XML "xtensa-core.xml"
+#define NUM_CORE_REGS (45)
+
+static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+{
+    if (n < 0 || n >= NUM_CORE_REGS) {
+        return 0;
+    }
+    if (n == 0) {
+        GET_REG32(env->pc);
+    } else if (n < 17) {
+        GET_REG32(env->regs[n - 1]);
+    } else {
+        GET_REG32(env->sregs[n - 17]);
+    }
+}
+
+static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+{
+    uint32_t tmp;
+
+    if (n < 0 || n >= NUM_CORE_REGS) {
+        return 0;
+    }
+    tmp = ldl_p(mem_buf);
+
+    if (n == 0) {
+        env->pc = tmp;
+    } else if (n < 17) {
+        env->regs[n - 1] = tmp;
+    } else {
+        env->sregs[n - 17] = tmp;
+    }
+    return 4;
+}
 #else
 
 #define NUM_CORE_REGS 0
@@ -1818,6 +1855,8 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
     s->c_cpu->psw.addr = pc;
 #elif defined (TARGET_LM32)
     s->c_cpu->pc = pc;
+#elif defined(TARGET_XTENSA)
+    s->c_cpu->pc = pc;
 #endif
 }
 
-- 
1.7.3.4

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

* [Qemu-devel] [RFC 08/28] target-xtensa: implement conditional jumps
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (5 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 07/28] target-xtensa: add gdb support Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04 15:45   ` Richard Henderson
  2011-05-04  0:59 ` [Qemu-devel] [RFC 09/28] target-xtensa: implement JX/RET0/CALLX Max Filippov
                   ` (21 subsequent siblings)
  28 siblings, 1 reply; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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).

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

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 49f4940..2bfa801 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -118,16 +118,41 @@ static void disas_xtensa_insn(DisasContext *dc)
 #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)
+
 #define RI16_IMM16 (((_b1) << 8) | (_b2))
 
 #define CALL_N (((_b0) & 0xc) >> 2)
 #define CALL_OFFSET ((((_b0) & 0x3) << 16) | ((_b1) << 8) | (_b2))
 #define CALL_OFFSET_SE (((_b0 & 0x2) ? 0xfffc0000 : 0) | CALL_OFFSET)
 
+#define BRI12_M ((_b0) & 0x3)
+#define BRI12_S RRR_S
+#define BRI12_IMM12 ((((_b1) & 0xf) << 8) | (_b2))
+#define BRI12_IMM12_SE ((((_b1) & 0x8) ? 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
+
     uint8_t _b0 = ldub_code(dc->pc);
     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
+    };
+
     switch (_OP0) {
     case 0: /*QRST*/
         switch (_OP1) {
@@ -314,10 +339,173 @@ static void disas_xtensa_insn(DisasContext *dc)
             gen_jumpi(dc, dc->pc + 4 + CALL_OFFSET_SE);
             break;
 
+        case 1: /*BZ*/
+            {
+                int label = gen_new_label();
+                int inv = BRI12_M & 1;
+
+                switch (BRI12_M & 2) {
+                case 0: /*BEQZ*/
+                    tcg_gen_brcondi_i32(inv ? TCG_COND_EQ : TCG_COND_NE,
+                            cpu_R[BRI12_S], 0, label);
+                    break;
+
+                case 2: /*BLTZ*/
+                    tcg_gen_brcondi_i32(inv ? TCG_COND_LT : TCG_COND_GE,
+                            cpu_R[BRI12_S], 0, label);
+                    break;
+                }
+                gen_jumpi(dc, dc->pc + 4 + BRI12_IMM12_SE);
+                gen_set_label(label);
+                gen_jumpi(dc, dc->pc + 3);
+            }
+            break;
+
+        case 2: /*BI0*/
+            {
+                int label = gen_new_label();
+                int inv = BRI8_M & 1;
+
+                switch (BRI8_M & 2) {
+                case 0: /*BEQI*/
+                    tcg_gen_brcondi_i32(inv ? TCG_COND_EQ : TCG_COND_NE,
+                            cpu_R[BRI8_S], B4CONST[BRI8_R], label);
+                    break;
+
+                case 2: /*BLTI*/
+                    tcg_gen_brcondi_i32(inv ? TCG_COND_LT : TCG_COND_GE,
+                            cpu_R[BRI8_S], B4CONST[BRI8_R], label);
+                    break;
+                }
+                gen_jumpi(dc, dc->pc + 4 + BRI8_IMM8_SE);
+                gen_set_label(label);
+                gen_jumpi(dc, dc->pc + 3);
+            }
+            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*/
+                {
+                    int label = gen_new_label();
+                    int inv = BRI8_M & 1;
+
+                    tcg_gen_brcondi_i32(inv ? TCG_COND_LTU : TCG_COND_GEU,
+                            cpu_R[BRI8_S], B4CONSTU[BRI8_R], label);
+
+                    gen_jumpi(dc, dc->pc + 4 + BRI8_IMM8_SE);
+                    gen_set_label(label);
+                    gen_jumpi(dc, dc->pc + 3);
+                }
+                break;
+            }
+            break;
+
         }
         break;
 
     case 7: /*B*/
+        {
+            int label = gen_new_label();
+            int inv = RRI8_R & 8;
+
+            switch (RRI8_R & 7) {
+            case 0: /*BNONE*/
+                {
+                    TCGv_i32 tmp = tcg_temp_new_i32();
+                    tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
+                    tcg_gen_brcondi_i32(inv ? TCG_COND_EQ : TCG_COND_NE,
+                            tmp, 0, label);
+                    tcg_temp_free(tmp);
+                }
+                break;
+
+            case 1: /*BEQ*/
+                tcg_gen_brcond_i32(inv ? TCG_COND_EQ : TCG_COND_NE,
+                        cpu_R[RRI8_S], cpu_R[RRI8_T], label);
+                break;
+
+            case 2: /*BLT*/
+                tcg_gen_brcond_i32(inv ? TCG_COND_LT : TCG_COND_GE,
+                        cpu_R[RRI8_S], cpu_R[RRI8_T], label);
+                break;
+
+            case 3: /*BLTU*/
+                tcg_gen_brcond_i32(inv ? TCG_COND_LTU : TCG_COND_GEU,
+                        cpu_R[RRI8_S], cpu_R[RRI8_T], label);
+                break;
+
+            case 4: /*BALL*/
+                {
+                    TCGv_i32 tmp = tcg_temp_new_i32();
+                    tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
+                    tcg_gen_brcond_i32(inv ? TCG_COND_EQ : TCG_COND_NE,
+                            tmp, cpu_R[RRI8_T], label);
+                    tcg_temp_free(tmp);
+                }
+                break;
+
+            case 5: /*BBC*/
+                {
+                    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);
+                    tcg_gen_brcondi_i32(inv ? TCG_COND_EQ : TCG_COND_NE,
+                            tmp, 0, label);
+                    tcg_temp_free(tmp);
+                    tcg_temp_free(bit);
+                }
+                break;
+
+            case 6: /*BBCI*/
+            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));
+                    tcg_gen_brcondi_i32(inv ? TCG_COND_EQ : TCG_COND_NE,
+                            tmp, 0, label);
+                    tcg_temp_free(tmp);
+                }
+                break;
+
+            }
+            gen_jumpi(dc, dc->pc + 4 + RRI8_IMM8_SE);
+            gen_set_label(label);
+            gen_jumpi(dc, dc->pc + 3);
+        }
         break;
 
 #define gen_narrow_load_store(type) do { \
-- 
1.7.3.4

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

* [Qemu-devel] [RFC 09/28] target-xtensa: implement JX/RET0/CALLX
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (6 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 08/28] target-xtensa: implement conditional jumps Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 10/28] target-xtensa: add special and user registers Max Filippov
                   ` (20 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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 |   49 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 48 insertions(+), 1 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 2bfa801..f4d74e0 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -130,7 +130,11 @@ static void disas_xtensa_insn(DisasContext *dc)
 #define CALL_OFFSET ((((_b0) & 0x3) << 16) | ((_b1) << 8) | (_b2))
 #define CALL_OFFSET_SE (((_b0 & 0x2) ? 0xfffc0000 : 0) | CALL_OFFSET)
 
-#define BRI12_M ((_b0) & 0x3)
+#define CALLX_N CALL_N
+#define CALLX_M ((_b0) & 0x3)
+#define CALLX_S RRR_S
+
+#define BRI12_M CALLX_M
 #define BRI12_S RRR_S
 #define BRI12_IMM12 ((((_b1) & 0xf) << 8) | (_b2))
 #define BRI12_IMM12_SE ((((_b1) & 0x8) ? 0xfffff000 : 0) | BRI12_IMM12)
@@ -165,6 +169,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->pc + 3);
+                                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] 49+ messages in thread

* [Qemu-devel] [RFC 10/28] target-xtensa: add special and user registers
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (7 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 09/28] target-xtensa: implement JX/RET0/CALLX Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 11/28] target-xtensa: implement RST3 group Max Filippov
                   ` (19 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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 cf19fce..e99e3bb 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 f4d74e0..f1f01bc 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -51,9 +51,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[] = {
@@ -73,6 +84,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 void gen_exception(int excp)
@@ -737,9 +764,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] 49+ messages in thread

* [Qemu-devel] [RFC 11/28] target-xtensa: implement RST3 group
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (8 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 10/28] target-xtensa: add special and user registers Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04 15:51   ` Richard Henderson
  2011-05-04  0:59 ` [Qemu-devel] [RFC 12/28] target-xtensa: implement shifts (ST1 and RST1 groups) Max Filippov
                   ` (18 subsequent siblings)
  28 siblings, 1 reply; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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>
---
 target-xtensa/translate.c |  147 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 147 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index f1f01bc..031873e 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -102,6 +102,32 @@ void xtensa_translate_init(void)
     }
 }
 
+static void gen_rsr(TCGv_i32 d, int sr)
+{
+    if (sregnames[sr]) {
+        tcg_gen_mov_i32(d, cpu_SR[sr]);
+    } else {
+        printf("SR %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 {
+        printf("SR %d not implemented, ", sr);
+    }
+}
+
 static void gen_exception(int excp)
 {
     TCGv_i32 tmp = tcg_const_i32(excp);
@@ -172,6 +198,8 @@ static void disas_xtensa_insn(DisasContext *dc)
 #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);
@@ -336,6 +364,125 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 3: /*RST3*/
+            switch (_OP2) {
+            case 0: /*RSR*/
+                gen_rsr(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);
+                {
+                    TCGv_i32 tmp = tcg_temp_new_i32();
+                    tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 24 - RRR_T);
+                    tcg_gen_sari_i32(cpu_R[RRR_R], tmp, 24 - RRR_T);
+                    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 {
+                        printf("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 {
+                        printf("wur %d not implemented, ", RSR_SR);
+                    }
+                }
+                break;
+
+            }
             break;
 
         case 4: /*EXTUI*/
-- 
1.7.3.4

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

* [Qemu-devel] [RFC 12/28] target-xtensa: implement shifts (ST1 and RST1 groups)
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (9 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 11/28] target-xtensa: implement RST3 group Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04 16:16   ` Richard Henderson
  2011-05-04  0:59 ` [Qemu-devel] [RFC 13/28] target-xtensa: implement LSAI group Max Filippov
                   ` (17 subsequent siblings)
  28 siblings, 1 reply; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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>
---
 target-xtensa/cpu.h       |    4 +
 target-xtensa/translate.c |  210 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 214 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index e99e3bb..a13a6cb 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/translate.c b/target-xtensa/translate.c
index 031873e..a940417 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -57,6 +57,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] = {
@@ -295,6 +296,101 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 4: /*ST1*/
+                switch (RRR_R) {
+                case 0: /*SSR*/
+                    tcg_gen_andi_i32(cpu_SR[SAR], cpu_R[RRR_S], 0x1f);
+                    break;
+
+                case 1: /*SSL*/
+                    {
+                        TCGv_i32 base = tcg_const_i32(32);
+                        TCGv_i32 tmp = tcg_temp_new_i32();
+                        tcg_gen_andi_i32(tmp, cpu_R[RRR_S], 0x1f);
+                        tcg_gen_sub_i32(cpu_SR[SAR], base, tmp);
+                        tcg_temp_free(tmp);
+                        tcg_temp_free(base);
+                    }
+                    break;
+
+                case 2: /*SSA8L*/
+                    {
+                        TCGv_i32 tmp = tcg_temp_new_i32();
+                        tcg_gen_andi_i32(tmp, cpu_R[RRR_S], 0x3);
+                        tcg_gen_shli_i32(cpu_SR[SAR], tmp, 3);
+                        tcg_temp_free(tmp);
+                    }
+                    break;
+
+                case 3: /*SSA8B*/
+                    {
+                        TCGv_i32 base = tcg_const_i32(32);
+                        TCGv_i32 tmp = tcg_temp_new_i32();
+                        tcg_gen_andi_i32(tmp, cpu_R[RRR_S], 0x3);
+                        tcg_gen_shli_i32(tmp, tmp, 3);
+                        tcg_gen_sub_i32(cpu_SR[SAR], base, tmp);
+                        tcg_temp_free(tmp);
+                        tcg_temp_free(base);
+                    }
+                    break;
+
+                case 4: /*SSAI*/
+                    tcg_gen_movi_i32(cpu_SR[SAR], RRR_S | ((RRR_T & 1) << 4));
+                    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);
+                    break;
+
+                case 15: /*NSAUu*/
+                    HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                    {
+#define gen_bit_bisect(w) do { \
+        int label = gen_new_label(); \
+        tcg_gen_brcondi_i32(TCG_COND_LTU, tmp, 1 << (w), label); \
+        tcg_gen_shri_i32(tmp, tmp, (w)); \
+        tcg_gen_subi_i32(res, res, (w)); \
+        gen_set_label(label); \
+    } while (0)
+
+                        int label = gen_new_label();
+                        TCGv_i32 res = tcg_temp_local_new_i32();
+
+                        tcg_gen_movi_i32(res, 32);
+                        tcg_gen_brcondi_i32(
+                                TCG_COND_EQ, cpu_R[RRR_S], 0, label);
+                        {
+                            TCGv_i32 tmp = tcg_temp_local_new_i32();
+                            tcg_gen_mov_i32(tmp, cpu_R[RRR_S]);
+                            tcg_gen_movi_i32(res, 31);
+
+                            gen_bit_bisect(16);
+                            gen_bit_bisect(8);
+                            gen_bit_bisect(4);
+                            gen_bit_bisect(2);
+                            gen_bit_bisect(1);
+
+                            tcg_temp_free(tmp);
+                        }
+                        gen_set_label(label);
+                        tcg_gen_mov_i32(cpu_R[RRR_T], res);
+                        tcg_temp_free(res);
+#undef gen_bit_bisect
+                    }
+                    break;
+
+                default: /*reserved*/
+                    break;
+                }
                 break;
 
             case 5: /*TLB*/
@@ -358,6 +454,111 @@ 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(cpu_R[RRR_T], RSR_SR);
+                    gen_wsr(dc, RSR_SR, tmp);
+                    tcg_temp_free(tmp);
+                }
+                break;
+
+#define gen_shift_reg(cmd, reg) do { \
+                    TCGv_i64 tmp = tcg_temp_new_i64(); \
+                    tcg_gen_extu_i32_i64(tmp, reg); \
+                    tcg_gen_andi_i64(tmp, tmp, 63); \
+                    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*/
+                {
+                    TCGv_i64 v = tcg_temp_new_i64();
+                    tcg_gen_extu_i32_i64(v, cpu_R[RRR_T]);
+                    gen_shift(shr);
+                }
+                break;
+
+            case 10: /*SLL*/
+                {
+                    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_extu_i32_i64(v, cpu_R[RRR_S]);
+                    gen_shift_reg(shl, s);
+                    tcg_temp_free(s);
+                }
+                break;
+
+            case 11: /*SRA*/
+                {
+                    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*/
@@ -487,6 +688,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*/
-- 
1.7.3.4

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

* [Qemu-devel] [RFC 13/28] target-xtensa: implement LSAI group
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (10 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 12/28] target-xtensa: implement shifts (ST1 and RST1 groups) Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 14/28] target-xtensa: mark reserved and TBD opcodes Max Filippov
                   ` (16 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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 a13a6cb..a12db8f 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 a940417..41f3abe 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -58,6 +58,7 @@ static TCGv_i32 cpu_UR[256];
 
 static const char * const sregnames[256] = {
     [SAR] = "SAR",
+    [SCOMPARE1] = "SCOMPARE1",
 };
 
 static const char * const uregnames[256] = {
@@ -739,7 +740,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] 49+ messages in thread

* [Qemu-devel] [RFC 14/28] target-xtensa: mark reserved and TBD opcodes
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (11 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 13/28] target-xtensa: implement LSAI group Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 15/28] target-xtensa: big endian support Max Filippov
                   ` (15 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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 |  111 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 110 insertions(+), 1 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 41f3abe..a47efb0 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -162,6 +162,14 @@ static void disas_xtensa_insn(DisasContext *dc)
         } \
     } while (0)
 
+#define TBD() printf("TBD(pc = %08x): %s:%d\n", dc->pc, __FILE__, __LINE__)
+#define RESERVED() do { \
+        printf("RESERVED(pc = %08x, %02x%02x%02x): %s:%d\n", \
+                dc->pc, _b0, _b1, _b2, __FILE__, __LINE__); \
+        goto invalid_opcode; \
+    } while (0)
+
+
 #define _OP0 (((_b0) & 0xf0) >> 4)
 #define _OP1 (((_b2) & 0xf0) >> 4)
 #define _OP2 ((_b2) & 0xf)
@@ -228,9 +236,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*/
@@ -242,9 +252,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;
@@ -265,6 +277,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                         case 2: /*CALLX8w*/
                         case 3: /*CALLX12w*/
                             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                            TBD();
                             break;
                         }
                         break;
@@ -273,12 +286,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;
 
                 }
@@ -339,17 +399,21 @@ 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*/
                     HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                    TBD();
                     break;
 
                 case 15: /*NSAUu*/
@@ -390,11 +454,13 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 default: /*reserved*/
+                    RESERVED();
                     break;
                 }
                 break;
 
             case 5: /*TLB*/
+                TBD();
                 break;
 
             case 6: /*RT0*/
@@ -415,11 +481,13 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 default: /*reserved*/
+                    RESERVED();
                     break;
                 }
                 break;
 
             case 7: /*reserved*/
+                RESERVED();
                 break;
 
             case 8: /*ADD*/
@@ -479,6 +547,9 @@ static void disas_xtensa_insn(DisasContext *dc)
                     gen_rsr(cpu_R[RRR_T], RSR_SR);
                     gen_wsr(dc, RSR_SR, tmp);
                     tcg_temp_free(tmp);
+                    if (!sregnames[RSR_SR]) {
+                        TBD();
+                    }
                 }
                 break;
 
@@ -558,21 +629,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(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*/
@@ -657,10 +736,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*/
@@ -670,6 +751,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                         tcg_gen_mov_i32(cpu_R[RRR_R], cpu_UR[st]);
                     } else {
                         printf("rur %d not implemented, ", st);
+                        TBD();
                     }
                 }
                 break;
@@ -680,6 +762,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                         tcg_gen_mov_i32(cpu_UR[RSR_SR], cpu_R[RRR_T]);
                     } else {
                         printf("wur %d not implemented, ", RSR_SR);
+                        TBD();
                     }
                 }
                 break;
@@ -701,27 +784,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;
@@ -773,6 +863,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 7: /*CACHEc*/
+            TBD();
             break;
 
         case 9: /*L16SI*/
@@ -824,6 +915,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         default: /*reserved*/
+            RESERVED();
             break;
         }
         break;
@@ -831,10 +923,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*/
@@ -848,6 +942,7 @@ static void disas_xtensa_insn(DisasContext *dc)
         case 2: /*CALL8w*/
         case 3: /*CALL12w*/
             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+            TBD();
             break;
         }
         break;
@@ -906,28 +1001,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;
 
                 }
@@ -1081,28 +1183,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] 49+ messages in thread

* [Qemu-devel] [RFC 15/28] target-xtensa: big endian support
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (12 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 14/28] target-xtensa: mark reserved and TBD opcodes Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 16/28] target-xtensa: implement SYNC group Max Filippov
                   ` (14 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

Big endian opcode decoding is slightly different.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 configure                 |    7 ++++---
 hw/xtensa_sample.c        |    6 +++++-
 target-xtensa/translate.c |   31 +++++++++++++++++++++++++++++--
 3 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/configure b/configure
index 41a7007..c45c2a3 100755
--- a/configure
+++ b/configure
@@ -1029,6 +1029,7 @@ sh4eb-softmmu \
 sparc-softmmu \
 sparc64-softmmu \
 xtensa-softmmu \
+xtensaeb-softmmu \
 "
     fi
 # the following are Linux specific
@@ -3016,7 +3017,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
@@ -3211,7 +3212,7 @@ case "$target_arch2" in
   unicore32)
     target_phys_bits=32
   ;;
-  xtensa)
+  xtensa|xtensaeb)
     TARGET_ARCH=xtensa
     gdb_xml_files="xtensa-core.xml"
     target_phys_bits=32
@@ -3391,7 +3392,7 @@ 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)
+  xtensa*)
     echo "CONFIG_XTENSA_DIS=y"  >> $config_target_mak
     echo "CONFIG_XTENSA_DIS=y"  >> $libdis_config_mak
   ;;
diff --git a/hw/xtensa_sample.c b/hw/xtensa_sample.c
index 8103675..b1da7e1 100644
--- a/hw/xtensa_sample.c
+++ b/hw/xtensa_sample.c
@@ -32,9 +32,13 @@ static void xtensa_init(ram_addr_t ram_size,
     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;
         }
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index a47efb0..da3120f 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -170,12 +170,21 @@ static void disas_xtensa_insn(DisasContext *dc)
     } 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
@@ -187,20 +196,38 @@ static void disas_xtensa_insn(DisasContext *dc)
 #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))
-#define CALL_OFFSET_SE (((_b0 & 0x2) ? 0xfffc0000 : 0) | CALL_OFFSET)
+#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))
-#define BRI12_IMM12_SE ((((_b1) & 0x8) ? 0xfffff000 : 0) | BRI12_IMM12)
+#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
-- 
1.7.3.4

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

* [Qemu-devel] [RFC 16/28] target-xtensa: implement SYNC group
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (13 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 15/28] target-xtensa: big endian support Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 17/28] target-xtensa: implement CACHE group Max Filippov
                   ` (13 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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 da3120f..3959d80 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -317,7 +317,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] 49+ messages in thread

* [Qemu-devel] [RFC 17/28] target-xtensa: implement CACHE group
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (14 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 16/28] target-xtensa: implement SYNC group Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 18/28] target-xtensa: implement exceptions Max Filippov
                   ` (12 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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 3959d80..4b5edc3 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -919,7 +919,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] 49+ messages in thread

* [Qemu-devel] [RFC 18/28] target-xtensa: implement exceptions
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (15 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 17/28] target-xtensa: implement CACHE group Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04 16:33   ` Richard Henderson
  2011-05-04  0:59 ` [Qemu-devel] [RFC 19/28] target-xtensa: implement RST2 group (32 bit mul/div/rem) Max Filippov
                   ` (11 subsequent siblings)
  28 siblings, 1 reply; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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>
---
 target-xtensa/cpu.h       |   91 +++++++++++++++++++++++++++++++++
 target-xtensa/helper.c    |   39 ++++++++++++++-
 target-xtensa/helpers.h   |    2 +
 target-xtensa/op_helper.c |   29 +++++++++++
 target-xtensa/translate.c |  124 +++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 279 insertions(+), 6 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index a12db8f..25041be 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_DIVIE_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;
 
@@ -151,6 +228,20 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
     *flags = 0;
 }
 
+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(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;
+}
+
 #include "cpu-all.h"
 
 #endif
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 6f374d3..e641360 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,
+        },
     },
 };
 
@@ -94,4 +110,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 {
+            printf("%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 c298d74..f13e005 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_2(exception_cause, void, i32, i32)
+DEF_HELPER_3(exception_cause_vaddr, void, i32, i32, i32)
 
 #include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index d1e620c..9bfe493 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -56,3 +56,32 @@ void HELPER(exception)(uint32_t excp)
     env->exception_index = 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);
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 4b5edc3..faf1adc 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -59,6 +59,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] = {
@@ -104,6 +110,11 @@ void xtensa_translate_init(void)
     }
 }
 
+static inline int option_enabled(DisasContext *dc, int opt)
+{
+    return xtensa_option_enabled(dc->config, opt);
+}
+
 static void gen_rsr(TCGv_i32 d, int sr)
 {
     if (sregnames[sr]) {
@@ -137,6 +148,33 @@ 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 (option_enabled(dc, XTENSA_OPTION_MMU)) {
+        TCGv_i32 tmp = tcg_temp_new_i32();
+        int label = gen_new_label();
+
+        tcg_gen_andi_i32(tmp, cpu_SR[PS], PS_EXCM);
+        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, PS_EXCM, label);
+        tcg_gen_andi_i32(tmp, cpu_SR[PS], PS_RING);
+        tcg_gen_brcondi_i32(TCG_COND_GEU, tmp, 0, label);
+
+        gen_exception_cause(dc, PRIVILEGED_CAUSE);
+
+        gen_set_label(label);
+        tcg_temp_free(tmp);
+    }
+}
+
 static void gen_jump(DisasContext *dc, TCGv dest)
 {
     tcg_gen_mov_i32(cpu_pc, dest);
@@ -263,7 +301,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*/
@@ -350,7 +388,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*/
@@ -360,12 +443,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*/
@@ -599,6 +698,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(cpu_R[RRR_T], RSR_SR);
                     gen_wsr(dc, RSR_SR, tmp);
@@ -697,6 +799,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(cpu_R[RRR_T], RSR_SR);
                 if (!sregnames[RSR_SR]) {
                     TBD();
@@ -704,6 +809,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();
@@ -1344,7 +1452,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 6: /*ILL.Nn*/
-                TBD();
+                gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
                 break;
 
             default: /*reserved*/
@@ -1414,6 +1522,12 @@ static void gen_intermediate_code_internal(
 
     gen_icount_start();
 
+    if (env->singlestep_enabled && env->exception_taken) {
+        env->exception_taken = 0;
+        tcg_gen_movi_i32(cpu_pc, dc.pc);
+        gen_exception(EXCP_DEBUG);
+    }
+
     do {
         check_breakpoint(env, &dc);
 
-- 
1.7.3.4

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

* [Qemu-devel] [RFC 19/28] target-xtensa: implement RST2 group (32 bit mul/div/rem)
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (16 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 18/28] target-xtensa: implement exceptions Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04 19:36   ` Blue Swirl
  2011-05-04  0:59 ` [Qemu-devel] [RFC 20/28] target-xtensa: implement windowed registers Max Filippov
                   ` (10 subsequent siblings)
  28 siblings, 1 reply; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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 faf1adc..d635229 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -793,7 +793,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_DIVIE_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] 49+ messages in thread

* [Qemu-devel] [RFC 20/28] target-xtensa: implement windowed registers
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (17 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 19/28] target-xtensa: implement RST2 group (32 bit mul/div/rem) Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04 19:35   ` Blue Swirl
  2011-05-04  0:59 ` [Qemu-devel] [RFC 21/28] target-xtensa: implement loop option Max Filippov
                   ` (9 subsequent siblings)
  28 siblings, 1 reply; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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       |    6 ++
 target-xtensa/helper.c    |    1 +
 target-xtensa/helpers.h   |    8 ++
 target-xtensa/op_helper.c |  172 +++++++++++++++++++++++++++++++++++++++++++++
 target-xtensa/translate.c |  134 ++++++++++++++++++++++++++++++++---
 5 files changed, 312 insertions(+), 9 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 25041be..3ebccd1 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;
 
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index e641360..61d1ab3 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 f13e005..4a50280 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -3,5 +3,13 @@
 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(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 9bfe493..b5925dd 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -85,3 +85,175 @@ void HELPER(exception_cause_vaddr)(uint32_t pc, uint32_t cause, uint32_t vaddr)
     env->sregs[EXCVADDR] = vaddr;
     HELPER(exception_cause)(pc, cause);
 }
+
+static void copy_window_from_phys(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(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))
+
+static void rotate_window_abs(uint32_t position)
+{
+    copy_phys_from_window(env->sregs[WINDOW_BASE] * 4, 0, 16);
+    env->sregs[WINDOW_BASE] = WINDOWBASE_BOUND(position);
+    copy_window_from_phys(0, env->sregs[WINDOW_BASE] * 4, 16);
+}
+
+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) {
+        printf("Illegal entry instruction (%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 <= w; ++n)
+        if (windowstart & WINDOWSTART_BIT(windowbase + n)) {
+            break;
+        }
+
+    if (n > w) {
+        return;
+    }
+
+    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) {
+        printf("Illegal retw instruction (%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 d635229..f3aecaa 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -59,6 +59,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",
@@ -124,10 +126,16 @@ static void gen_rsr(TCGv_i32 d, int sr)
     }
 }
 
+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) = {
+        [WINDOW_BASE] = gen_wsr_windowbase,
     };
 
     if (sregnames[sr]) {
@@ -192,6 +200,18 @@ static void gen_jumpi(DisasContext *dc, uint32_t dest)
     tcg_temp_free(tmp);
 }
 
+static void gen_callw(DisasContext *dc, int _callinc, TCGv_i32 target)
+{
+    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->pc + 3) & 0x3fffffff));
+    gen_jump(dc, target);
+}
+
 static void disas_xtensa_insn(DisasContext *dc)
 {
 #define HAS_OPTION(opt) do { \
@@ -317,7 +337,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*/
@@ -342,7 +367,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;
@@ -351,7 +382,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*/
@@ -411,7 +447,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*/
@@ -563,7 +619,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*/
@@ -1019,7 +1081,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*/
@@ -1257,7 +1349,12 @@ static void disas_xtensa_insn(DisasContext *dc)
         case 2: /*CALL8w*/
         case 3: /*CALL12w*/
             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-            TBD();
+            {
+                TCGv_i32 tmp = tcg_const_i32(
+                        (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4);
+                gen_callw(dc, CALL_N, tmp);
+                tcg_temp_free(tmp);
+            }
             break;
         }
         break;
@@ -1316,7 +1413,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*/
@@ -1499,7 +1604,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*/
@@ -1662,6 +1772,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] 49+ messages in thread

* [Qemu-devel] [RFC 21/28] target-xtensa: implement loop option
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (18 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 20/28] target-xtensa: implement windowed registers Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 22/28] target-xtensa: implement extended L32R Max Filippov
                   ` (8 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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>
---
 target-xtensa/cpu.h       |    3 ++
 target-xtensa/helpers.h   |    1 +
 target-xtensa/op_helper.c |   11 ++++++
 target-xtensa/translate.c |   80 +++++++++++++++++++++++++++++++++++++-------
 4 files changed, 82 insertions(+), 13 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 3ebccd1..7fade0c 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -106,6 +106,9 @@ enum {
 };
 
 enum {
+    LBEG = 0,
+    LEND = 1,
+    LCOUNT = 2,
     SAR = 3,
     SCOMPARE1 = 12,
     WINDOW_BASE = 72,
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index 4a50280..7e212a3 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -10,6 +10,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 b5925dd..f0690ee 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -253,6 +253,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 f3aecaa..e33c2fa 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -44,6 +44,7 @@ typedef struct DisasContext {
     const XtensaConfig *config;
     TranslationBlock *tb;
     uint32_t pc;
+    uint32_t lend;
     int is_jmp;
     int singlestep_enabled;
 } DisasContext;
@@ -57,6 +58,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",
@@ -126,6 +130,11 @@ static void gen_rsr(TCGv_i32 d, int sr)
     }
 }
 
+static void gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    gen_helper_wsr_lend(v);
+}
+
 static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     gen_helper_wsr_windowbase(v);
@@ -135,6 +144,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,
         [WINDOW_BASE] = gen_wsr_windowbase,
     };
 
@@ -212,10 +222,36 @@ static void gen_callw(DisasContext *dc, int _callinc, TCGv_i32 target)
     gen_jump(dc, target);
 }
 
+static void gen_check_loop_end(DisasContext *dc)
+{
+    if (option_enabled(dc, XTENSA_OPTION_LOOP) &&
+            dc->pc == dc->lend) {
+        TCGv_i32 tmp = tcg_temp_new_i32();
+        int label = gen_new_label();
+
+        tcg_gen_andi_i32(tmp, cpu_SR[PS], PS_EXCM);
+        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, PS_EXCM, label);
+        tcg_gen_brcondi_i32(TCG_COND_NE, cpu_SR[LEND], dc->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->pc);
+        tcg_temp_free(tmp);
+    }
+}
+
+static void gen_jumpi_check_loop_end(DisasContext *dc, uint32_t dest)
+{
+    dc->pc = dest;
+    gen_check_loop_end(dc);
+    gen_jumpi(dc, dest);
+}
+
 static void disas_xtensa_insn(DisasContext *dc)
 {
 #define HAS_OPTION(opt) do { \
-        if (!(dc->config->options & (((uint64_t)1) << (opt)))) { \
+        if (!option_enabled(dc, opt)) { \
             goto invalid_opcode; \
         } \
     } while (0)
@@ -1383,7 +1419,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 }
                 gen_jumpi(dc, dc->pc + 4 + BRI12_IMM12_SE);
                 gen_set_label(label);
-                gen_jumpi(dc, dc->pc + 3);
+                gen_jumpi_check_loop_end(dc, dc->pc + 3);
             }
             break;
 
@@ -1405,7 +1441,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 }
                 gen_jumpi(dc, dc->pc + 4 + BRI8_IMM8_SE);
                 gen_set_label(label);
-                gen_jumpi(dc, dc->pc + 3);
+                gen_jumpi_check_loop_end(dc, dc->pc + 3);
             }
             break;
 
@@ -1437,15 +1473,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->pc + 3);
+                        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);
+                            gen_set_label(label);
+                        }
+
+                        gen_jumpi(dc, dc->pc + 3);
+                    }
                     break;
 
                 default: /*reserved*/
@@ -1466,7 +1516,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                     gen_jumpi(dc, dc->pc + 4 + BRI8_IMM8_SE);
                     gen_set_label(label);
-                    gen_jumpi(dc, dc->pc + 3);
+                    gen_jumpi_check_loop_end(dc, dc->pc + 3);
                 }
                 break;
             }
@@ -1545,7 +1595,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             }
             gen_jumpi(dc, dc->pc + 4 + RRI8_IMM8_SE);
             gen_set_label(label);
-            gen_jumpi(dc, dc->pc + 3);
+            gen_jumpi_check_loop_end(dc, dc->pc + 3);
         }
         break;
 
@@ -1586,7 +1636,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     cpu_R[RRRN_S], 0, label);
             gen_jumpi(dc, dc->pc + 4 + (RRRN_R | ((RRRN_T & 3) << 4)));
             gen_set_label(label);
-            gen_jumpi(dc, dc->pc + 2);
+            gen_jumpi_check_loop_end(dc, dc->pc + 2);
         }
         break;
 
@@ -1646,6 +1696,9 @@ static void disas_xtensa_insn(DisasContext *dc)
     } else {
         dc->pc += 3;
     }
+
+    gen_check_loop_end(dc);
+
     return;
 
 invalid_opcode:
@@ -1686,6 +1739,7 @@ static void gen_intermediate_code_internal(
     dc.singlestep_enabled = env->singlestep_enabled;
     dc.tb = tb;
     dc.pc = env->pc;
+    dc.lend = env->sregs[LEND];
     dc.is_jmp = DISAS_NEXT;
 
     gen_icount_start();
-- 
1.7.3.4

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

* [Qemu-devel] [RFC 22/28] target-xtensa: implement extended L32R
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (19 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 21/28] target-xtensa: implement loop option Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 23/28] target-xtensa: implement unaligned exception option Max Filippov
                   ` (7 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

See ISA, 4.3.3 for details.

Enable bit of LITBASE may be stored separately for further speedup.

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

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 7fade0c..8110665 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,
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 61d1ab3..6df2e50 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 e33c2fa..53e0d02 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -62,6 +62,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",
@@ -1168,12 +1169,25 @@ static void disas_xtensa_insn(DisasContext *dc)
 
     case 1: /*L32R*/
         {
-            TCGv_i32 tmp = tcg_const_i32(
+            TCGv_i32 tmp = tcg_temp_local_new_i32();
+
+            tcg_gen_movi_i32(tmp,
                     (0xfffc0000 | (RI16_IMM16 << 2)) +
                     ((dc->pc + 3) & ~3));
 
-            /* no ext L32R */
+            if (option_enabled(dc, XTENSA_OPTION_EXTENDED_L32R)) {
+                TCGv_i32 tmp1 = tcg_temp_new_i32();
+                int label = gen_new_label();
+
+                tcg_gen_andi_i32(tmp1, cpu_SR[LITBASE], 1);
+                tcg_gen_brcondi_i32(TCG_COND_EQ, tmp1, 0, label);
+                tcg_gen_andi_i32(tmp1, cpu_SR[LITBASE], 0xfffff000);
+                tcg_gen_addi_i32(tmp, tmp1, (0xfffc0000 | (RI16_IMM16 << 2)));
+                gen_set_label(label);
+                tcg_temp_free(tmp1);
+            }
 
+            /* much simplified, no MMU */
             tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, 0);
             tcg_temp_free(tmp);
         }
-- 
1.7.3.4

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

* [Qemu-devel] [RFC 23/28] target-xtensa: implement unaligned exception option
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (20 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 22/28] target-xtensa: implement extended L32R Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 24/28] target-xtensa: implement SIMCALL Max Filippov
                   ` (6 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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 53e0d02..d63f53a 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -176,6 +176,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 (option_enabled(dc, XTENSA_OPTION_MMU)) {
@@ -249,6 +259,20 @@ static void gen_jumpi_check_loop_end(DisasContext *dc, uint32_t dest)
     gen_jumpi(dc, dest);
 }
 
+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 { \
@@ -1195,8 +1219,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)
@@ -1355,6 +1382,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);
 
@@ -1614,8 +1642,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] 49+ messages in thread

* [Qemu-devel] [RFC 24/28] target-xtensa: implement SIMCALL
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (21 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 23/28] target-xtensa: implement unaligned exception option Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04 19:48   ` Blue Swirl
  2011-05-04  0:59 ` [Qemu-devel] [RFC 25/28] target-xtensa: implement interrupt option Max Filippov
                   ` (5 subsequent siblings)
  28 siblings, 1 reply; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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>
---
 target-xtensa/helpers.h   |    1 +
 target-xtensa/op_helper.c |    7 ++
 target-xtensa/simcall.c   |  157 +++++++++++++++++++++++++++++++++++++++++++++
 target-xtensa/translate.c |    2 +-
 4 files changed, 166 insertions(+), 1 deletions(-)
 create mode 100644 target-xtensa/simcall.c

diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index 7e212a3..55eb0d8 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -11,6 +11,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 f0690ee..68b1526 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -264,6 +264,13 @@ void HELPER(wsr_lend)(uint32_t v)
     }
 }
 
+#include "simcall.c"
+
+void HELPER(simcall)(void)
+{
+    simcall(env->regs);
+}
+
 void HELPER(dump_state)(void)
 {
     cpu_dump_state(env, stderr, fprintf, 0);
diff --git a/target-xtensa/simcall.c b/target-xtensa/simcall.c
new file mode 100644
index 0000000..3446275
--- /dev/null
+++ b/target-xtensa/simcall.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Motorola Solutions, Inc.
+ * 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 Motorola Solutions 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 <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stddef.h>
+
+enum {
+    SYS_exit = 1,
+    SYS_read = 3,
+    SYS_write = 4,
+    SYS_open = 5,
+    SYS_close = 6,
+
+    SYS_argc = 1000,
+    SYS_argv_sz = 1001,
+    SYS_argv = 1002,
+    SYS_memset = 1004,
+};
+
+static void simcall(uint32_t regs[16])
+{
+    switch (regs[2]) {
+    case SYS_exit:
+        printf("exit(%d)\n", regs[3]);
+        exit(regs[3]);
+        break;
+
+    case 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] = 0;
+            }
+        }
+        break;
+
+    case 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] = 0;
+            }
+        }
+        break;
+
+    case SYS_open:
+        {
+            target_phys_addr_t len = 1024;
+            void *buf = cpu_physical_memory_map(regs[3], &len, 0);
+
+            if (buf && strnlen((char *)buf, len) < len) {
+                regs[2] = open((char *)buf, regs[4], regs[5]);
+                regs[3] = errno;
+            } else {
+                regs[2] = -1;
+                regs[3] = 0;
+            }
+        }
+        break;
+
+    case SYS_close:
+        if (regs[3] < 3) {
+            regs[2] = regs[3] = 0;
+        } else {
+            regs[2] = close(regs[3]);
+            regs[3] = errno;
+        }
+        break;
+
+    case SYS_argc:
+        regs[2] = 1;
+        regs[3] = 0;
+        break;
+
+    case SYS_argv_sz:
+        regs[2] = 128;
+        regs[3] = 0;
+        break;
+
+    case SYS_argv:
+        {
+            struct Argv {
+                uint32_t argptr[2];
+                char text[120];
+            } argv = {
+                {0, 0},
+                "test"
+            };
+
+            argv.argptr[0] = regs[3] + offsetof(struct Argv, text);
+            cpu_memory_rw_debug(
+                    env, regs[3], (uint8_t *)&argv, sizeof(argv), 1);
+        }
+        break;
+
+    case SYS_memset:
+        {
+            target_phys_addr_t len = regs[5];
+            void *buf = cpu_physical_memory_map(regs[3], &len, 1);
+
+            assert(len == regs[5]);
+
+            if (buf) {
+                memset(buf, regs[4], len);
+                regs[2] = regs[3];
+                regs[3] = 0;
+                cpu_physical_memory_unmap(buf, len, 1, len);
+            }
+        }
+        break;
+
+    default:
+        printf("%s(%d)\n", __func__, regs[2]);
+        break;
+    }
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index d63f53a..ab86db8 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -566,7 +566,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                         break;
 
                     case 1: /*SIMCALL*/
-                        TBD();
+                        gen_helper_simcall();
                         break;
 
                     default:
-- 
1.7.3.4

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

* [Qemu-devel] [RFC 25/28] target-xtensa: implement interrupt option
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (22 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 24/28] target-xtensa: implement SIMCALL Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 26/28] target-xtensa: implement accurate window check Max Filippov
                   ` (4 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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.7 (timer interrupt option) for details.

CCOUNT SR is incremented before every command and timer interrupt
checking is inserted before every command. It may be done on TB boundary
for optimization.

WAITI doesn't go to sleep, but just sets PS.INTLEVEL. Timer may be used
to avoid busy looping.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 hw/xtensa_pic.c           |   43 ++++++++++++++++++++
 target-xtensa/cpu.h       |   33 +++++++++++++++
 target-xtensa/helper.c    |   79 +++++++++++++++++++++++++++++++++++-
 target-xtensa/helpers.h   |    4 ++
 target-xtensa/op_helper.c |   18 ++++++++
 target-xtensa/translate.c |   98 ++++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 272 insertions(+), 3 deletions(-)

diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
index 5ff1697..aa1ae3b 100644
--- a/hw/xtensa_pic.c
+++ b/hw/xtensa_pic.c
@@ -9,3 +9,46 @@ void pic_info(Monitor *mon)
 void irq_info(Monitor *mon)
 {
 }
+
+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]) {
+            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) {
+        printf("%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_irq_init(CPUState *env)
+{
+    env->irq_inputs = (void **)qemu_allocate_irqs(
+            xtensa_set_irq, env, env->config->ninterrupt);
+}
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 8110665..f3028a7 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,14 @@ 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];
 } XtensaConfig;
 
 typedef struct CPUXtensaState {
@@ -207,6 +235,9 @@ 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;
+
     int exception_taken;
 
     CPU_COMMON
@@ -222,6 +253,8 @@ 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);
 int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
 void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 6df2e50..0325b03 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,30 @@ 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,
+        },
     },
 };
 
@@ -90,6 +116,7 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
         xtensa_translate_init();
     }
 
+    xtensa_irq_init(env);
     cpu_reset(env);
     qemu_init_vcpu(env);
     return env;
@@ -110,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:
@@ -125,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 {
             printf("%s(pc = %08x) bad exception_index: %d\n",
                     __func__, env->pc, env->exception_index);
         }
         break;
 
+    default:
+        printf("%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 55eb0d8..3f492e3 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -14,4 +14,8 @@ 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)
+
 #include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 68b1526..022dbb9 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -27,6 +27,7 @@
 
 #include "exec.h"
 #include "helpers.h"
+#include "hw/irq.h"
 
 #define MMUSUFFIX _mmu
 
@@ -275,3 +276,20 @@ 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);
+}
+
+void HELPER(timer_irq)(uint32_t id, uint32_t active)
+{
+    qemu_set_irq(env->irq_inputs[env->config->timerint[id]], active);
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index ab86db8..ce1fbf6 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -67,11 +67,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] = {
@@ -122,6 +147,12 @@ static inline int option_enabled(DisasContext *dc, int opt)
     return xtensa_option_enabled(dc->config, opt);
 }
 
+static void gen_check_interrupts(DisasContext *dc)
+{
+    tcg_gen_movi_i32(cpu_pc, dc->pc);
+    gen_helper_check_interrupts();
+}
+
 static void gen_rsr(TCGv_i32 d, int sr)
 {
     if (sregnames[sr]) {
@@ -141,12 +172,32 @@ 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);
+}
+
+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);
+    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,
             uint32_t sr, TCGv_i32 v) = {
         [LEND] = gen_wsr_lend,
         [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]) {
@@ -273,6 +324,15 @@ 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_helper_waiti(pc, intlevel);
+    tcg_temp_free(pc);
+    tcg_temp_free(intlevel);
+}
+
 static void disas_xtensa_insn(DisasContext *dc)
 {
 #define HAS_OPTION(opt) do { \
@@ -539,7 +599,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*/
@@ -582,11 +644,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*/
@@ -1765,6 +1829,26 @@ static void check_breakpoint(CPUState *env, DisasContext *dc)
     }
 }
 
+static void gen_timer(CPUState *env, DisasContext *dc)
+{
+    int id;
+    tcg_gen_addi_i32(cpu_SR[CCOUNT], cpu_SR[CCOUNT], 1);
+    for (id = 0; id < env->config->nccompare; ++id) {
+        int label = gen_new_label();
+        tcg_gen_brcond_i32(
+                TCG_COND_NE, cpu_SR[CCOUNT], cpu_SR[CCOMPARE + id], label);
+        {
+            TCGv_i32 tid = tcg_const_i32(id);
+            TCGv_i32 active = tcg_const_i32(1);
+            tcg_gen_movi_i32(cpu_pc, dc->pc);
+            gen_helper_timer_irq(tid, active);
+            tcg_temp_free(tid);
+            tcg_temp_free(active);
+        }
+        gen_set_label(label);
+    }
+}
+
 static void gen_intermediate_code_internal(
         CPUState *env, TranslationBlock *tb, int search_pc)
 {
@@ -1813,6 +1897,12 @@ static void gen_intermediate_code_internal(
             tcg_gen_debug_insn_start(dc.pc);
         }
 
+        gen_timer(env, &dc);
+
+        if (insn_count + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+            gen_io_start();
+        }
+
         disas_xtensa_insn(&dc);
         ++insn_count;
         if (env->singlestep_enabled) {
@@ -1824,6 +1914,10 @@ static void gen_intermediate_code_internal(
             insn_count < max_insns &&
             gen_opc_ptr < gen_opc_end);
 
+    if (tb->cflags & CF_LAST_IO) {
+        gen_io_end();
+    }
+
     if (dc.is_jmp == DISAS_NEXT) {
         tcg_gen_movi_i32(cpu_pc, dc.pc);
         tcg_gen_exit_tb(0);
-- 
1.7.3.4

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

* [Qemu-devel] [RFC 26/28] target-xtensa: implement accurate window check
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (23 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 25/28] target-xtensa: implement interrupt option Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 27/28] target-xtensa: implement CPENABLE and PRID SRs Max Filippov
                   ` (3 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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 ce1fbf6..4df1b57 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -47,6 +47,7 @@ typedef struct DisasContext {
     uint32_t lend;
     int is_jmp;
     int singlestep_enabled;
+    unsigned used_window;
 } DisasContext;
 
 static TCGv_ptr cpu_env;
@@ -153,6 +154,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_rsr(TCGv_i32 d, int sr)
 {
     if (sregnames[sr]) {
@@ -170,11 +176,19 @@ static void gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 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);
 }
 
@@ -194,6 +208,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
             uint32_t sr, TCGv_i32 v) = {
         [LEND] = gen_wsr_lend,
         [WINDOW_BASE] = gen_wsr_windowbase,
+        [WINDOW_START] = gen_wsr_windowstart,
         [PS] = gen_wsr_ps,
         [CCOMPARE] = gen_wsr_ccompare,
         [CCOMPARE + 1] = gen_wsr_ccompare,
@@ -333,6 +348,31 @@ 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_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 { \
@@ -453,6 +493,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;
 
@@ -473,6 +514,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*/
                             {
@@ -503,6 +545,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_helper_movsp(pc);
@@ -640,6 +683,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],
@@ -681,24 +725,29 @@ 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);
                     tcg_gen_andi_i32(cpu_SR[SAR], cpu_R[RRR_S], 0x1f);
                     break;
 
                 case 1: /*SSL*/
+                    gen_window_check1(dc, RRR_S);
                     {
                         TCGv_i32 base = tcg_const_i32(32);
                         TCGv_i32 tmp = tcg_temp_new_i32();
@@ -710,6 +759,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 case 2: /*SSA8L*/
+                    gen_window_check1(dc, RRR_S);
                     {
                         TCGv_i32 tmp = tcg_temp_new_i32();
                         tcg_gen_andi_i32(tmp, cpu_R[RRR_S], 0x3);
@@ -719,6 +769,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 case 3: /*SSA8B*/
+                    gen_window_check1(dc, RRR_S);
                     {
                         TCGv_i32 base = tcg_const_i32(32);
                         TCGv_i32 tmp = tcg_temp_new_i32();
@@ -750,6 +801,7 @@ 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;
 
@@ -760,6 +812,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                 case 15: /*NSAUu*/
                     HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                    gen_window_check2(dc, RRR_S, RRR_T);
                     {
 #define gen_bit_bisect(w) do { \
         int label = gen_new_label(); \
@@ -806,6 +859,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]);
@@ -833,12 +887,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);
@@ -848,12 +904,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);
@@ -868,17 +926,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;
 
@@ -888,6 +949,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(cpu_R[RRR_T], RSR_SR);
                     gen_wsr(dc, RSR_SR, tmp);
@@ -913,6 +975,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             case 8: /*SRC*/
                 {
                     TCGv_i64 v = tcg_temp_new_i64();
+                    gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                     tcg_gen_concat_i32_i64(v, cpu_R[RRR_T], cpu_R[RRR_S]);
                     gen_shift(shr);
                 }
@@ -921,6 +984,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             case 9: /*SRL*/
                 {
                     TCGv_i64 v = tcg_temp_new_i64();
+                    gen_window_check2(dc, RRR_R, RRR_T);
                     tcg_gen_extu_i32_i64(v, cpu_R[RRR_T]);
                     gen_shift(shr);
                 }
@@ -930,6 +994,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 {
                     TCGv_i64 v = tcg_temp_new_i64();
                     TCGv_i32 s = tcg_const_i32(32);
+                    gen_window_check2(dc, RRR_R, RRR_S);
                     tcg_gen_sub_i32(s, s, cpu_SR[SAR]);
                     tcg_gen_extu_i32_i64(v, cpu_R[RRR_S]);
                     gen_shift_reg(shl, s);
@@ -940,6 +1005,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             case 11: /*SRA*/
                 {
                     TCGv_i64 v = tcg_temp_new_i64();
+                    gen_window_check2(dc, RRR_R, RRR_T);
                     tcg_gen_ext_i32_i64(v, cpu_R[RRR_T]);
                     gen_shift(sar);
                 }
@@ -949,6 +1015,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();
@@ -962,6 +1029,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();
@@ -980,6 +1048,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();
@@ -1047,6 +1117,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 if (RSR_SR >= 64) {
                     gen_check_privilege(dc);
                 }
+                gen_window_check1(dc, RRR_T);
                 gen_rsr(cpu_R[RRR_T], RSR_SR);
                 if (!sregnames[RSR_SR]) {
                     TBD();
@@ -1057,6 +1128,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();
@@ -1065,6 +1137,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);
                 {
                     TCGv_i32 tmp = tcg_temp_new_i32();
                     tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 24 - RRR_T);
@@ -1075,6 +1148,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();
@@ -1102,6 +1176,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,
@@ -1129,6 +1204,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,
@@ -1154,6 +1230,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]) {
@@ -1166,6 +1243,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]);
@@ -1181,6 +1259,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;
@@ -1206,6 +1285,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);
@@ -1256,6 +1336,7 @@ static void disas_xtensa_insn(DisasContext *dc)
         break;
 
     case 1: /*L32R*/
+        gen_window_check1(dc, RRR_T);
         {
             TCGv_i32 tmp = tcg_temp_local_new_i32();
 
@@ -1284,6 +1365,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); \
@@ -1419,6 +1501,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));
@@ -1430,15 +1513,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();
@@ -1491,6 +1577,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);
             {
                 TCGv_i32 tmp = tcg_const_i32(
                         (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4);
@@ -1508,6 +1595,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 1: /*BZ*/
+            gen_window_check1(dc, BRI12_S);
             {
                 int label = gen_new_label();
                 int inv = BRI12_M & 1;
@@ -1530,6 +1618,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 2: /*BI0*/
+            gen_window_check1(dc, BRI8_S);
             {
                 int label = gen_new_label();
                 int inv = BRI8_M & 1;
@@ -1563,6 +1652,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;
 
@@ -1582,6 +1672,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);
@@ -1613,6 +1704,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 2: /*BLTUI*/
             case 3: /*BGEUI*/
+                gen_window_check1(dc, BRI8_S);
                 {
                     int label = gen_new_label();
                     int inv = BRI8_M & 1;
@@ -1638,6 +1730,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             switch (RRI8_R & 7) {
             case 0: /*BNONE*/
+                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]);
@@ -1648,21 +1741,25 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 1: /*BEQ*/
+                gen_window_check2(dc, RRI8_S, RRI8_T);
                 tcg_gen_brcond_i32(inv ? TCG_COND_EQ : TCG_COND_NE,
                         cpu_R[RRI8_S], cpu_R[RRI8_T], label);
                 break;
 
             case 2: /*BLT*/
+                gen_window_check2(dc, RRI8_S, RRI8_T);
                 tcg_gen_brcond_i32(inv ? TCG_COND_LT : TCG_COND_GE,
                         cpu_R[RRI8_S], cpu_R[RRI8_T], label);
                 break;
 
             case 3: /*BLTU*/
+                gen_window_check2(dc, RRI8_S, RRI8_T);
                 tcg_gen_brcond_i32(inv ? TCG_COND_LTU : TCG_COND_GEU,
                         cpu_R[RRI8_S], cpu_R[RRI8_T], label);
                 break;
 
             case 4: /*BALL*/
+                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]);
@@ -1673,6 +1770,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 5: /*BBC*/
+                gen_window_check2(dc, RRI8_S, RRI8_T);
                 {
                     TCGv_i32 bit = tcg_const_i32(1);
                     TCGv_i32 tmp = tcg_temp_new_i32();
@@ -1688,6 +1786,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 6: /*BBCI*/
             case 7:
+                gen_window_check1(dc, RRI8_S);
                 {
                     TCGv_i32 tmp = tcg_temp_new_i32();
                     tcg_gen_andi_i32(tmp, cpu_R[RRI8_S],
@@ -1707,6 +1806,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); \
@@ -1723,14 +1823,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) |
@@ -1750,6 +1853,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;
 
@@ -1868,6 +1972,7 @@ static void gen_intermediate_code_internal(
     dc.pc = env->pc;
     dc.lend = env->sregs[LEND];
     dc.is_jmp = DISAS_NEXT;
+    reset_used_window(&dc);
 
     gen_icount_start();
 
-- 
1.7.3.4

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

* [Qemu-devel] [RFC 27/28] target-xtensa: implement CPENABLE and PRID SRs
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (24 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 26/28] target-xtensa: implement accurate window check Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  0:59 ` [Qemu-devel] [RFC 28/28] target-xtensa: implement relocatable vectors Max Filippov
                   ` (2 subsequent siblings)
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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 b1da7e1..797a0c4 100644
--- a/hw/xtensa_sample.c
+++ b/hw/xtensa_sample.c
@@ -18,6 +18,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 f3028a7..dbd3550 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 4df1b57..b72f1cf 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -88,12 +88,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",
@@ -192,6 +194,10 @@ static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     gen_check_interrupts(dc);
 }
 
+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);
@@ -210,6 +216,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] 49+ messages in thread

* [Qemu-devel] [RFC 28/28] target-xtensa: implement relocatable vectors
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (25 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 27/28] target-xtensa: implement CPENABLE and PRID SRs Max Filippov
@ 2011-05-04  0:59 ` Max Filippov
  2011-05-04  6:04 ` [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
  2011-05-04 19:51 ` Blue Swirl
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  0:59 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 dbd3550..2f21091 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 0325b03..17e2053 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 b72f1cf..a4e7403 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -93,6 +93,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] 49+ messages in thread

* Re: [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (26 preceding siblings ...)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 28/28] target-xtensa: implement relocatable vectors Max Filippov
@ 2011-05-04  6:04 ` Max Filippov
  2011-05-04 19:51 ` Blue Swirl
  28 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-04  6:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

> +#elif defined(TARGET_XTENSA)
> +                    if (interrupt_request & CPU_INTERRUPT_HARD) {
> +                        env->exception_index = EXC_IRQ;
> +                        do_interrupt(env);
> +                        next_tb = 0;
> +                    }

Looks like I've moved this hunk here from 'target-xtensa: implement
exceptions' by mistake ): It will not compile until then.

Thanks.
-- Max

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

* Re: [Qemu-devel] [RFC 03/28] target-xtensa: implement disas_xtensa_insn
  2011-05-04  0:59 ` [Qemu-devel] [RFC 03/28] target-xtensa: implement disas_xtensa_insn Max Filippov
@ 2011-05-04 15:39   ` Richard Henderson
  0 siblings, 0 replies; 49+ messages in thread
From: Richard Henderson @ 2011-05-04 15:39 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/03/2011 05:59 PM, Max Filippov wrote:
> +static void gen_jump(DisasContext *dc, TCGv dest)
> +{
> +    tcg_gen_mov_i32(cpu_pc, dest);
> +    if (dc->singlestep_enabled) {
> +        gen_exception(EXCP_DEBUG);
> +    }
> +    tcg_gen_exit_tb(0);
> +    dc->is_jmp = DISAS_UPDATE;

You're generating useless instructions here.  The exception
is a noreturn function.  It performs a longjmp to back out
of the cpu loop.

Thus the exit_tb should be in an else here.

> +invalid_opcode:
> +    printf("INVALID(pc = %08x): %s:%d\n", dc->pc, __FILE__, __LINE__);

Don't printf.  Use the logging functions properly.


r~

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

* Re: [Qemu-devel] [RFC 08/28] target-xtensa: implement conditional jumps
  2011-05-04  0:59 ` [Qemu-devel] [RFC 08/28] target-xtensa: implement conditional jumps Max Filippov
@ 2011-05-04 15:45   ` Richard Henderson
  0 siblings, 0 replies; 49+ messages in thread
From: Richard Henderson @ 2011-05-04 15:45 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/03/2011 05:59 PM, Max Filippov wrote:
> +                int label = gen_new_label();
> +                int inv = BRI12_M & 1;
> +
> +                switch (BRI12_M & 2) {
> +                case 0: /*BEQZ*/
> +                    tcg_gen_brcondi_i32(inv ? TCG_COND_EQ : TCG_COND_NE,
> +                            cpu_R[BRI12_S], 0, label);
> +                    break;
> +
> +                case 2: /*BLTZ*/
> +                    tcg_gen_brcondi_i32(inv ? TCG_COND_LT : TCG_COND_GE,
> +                            cpu_R[BRI12_S], 0, label);
> +                    break;
> +                }
> +                gen_jumpi(dc, dc->pc + 4 + BRI12_IMM12_SE);
> +                gen_set_label(label);
> +                gen_jumpi(dc, dc->pc + 3);

It seems to me that this code could be cleaned up by extracting
the branching and jumpi'ing into a function.  There's a lot of
repetition here.

Also, once you do get around to using chained TB's, there'll be
only one place to have to update to get that to happen.


r~

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

* Re: [Qemu-devel] [RFC 11/28] target-xtensa: implement RST3 group
  2011-05-04  0:59 ` [Qemu-devel] [RFC 11/28] target-xtensa: implement RST3 group Max Filippov
@ 2011-05-04 15:51   ` Richard Henderson
  0 siblings, 0 replies; 49+ messages in thread
From: Richard Henderson @ 2011-05-04 15:51 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/03/2011 05:59 PM, Max Filippov wrote:
> +            case 2: /*SEXTu*/
> +                HAS_OPTION(XTENSA_OPTION_MISC_OP);
> +                {
> +                    TCGv_i32 tmp = tcg_temp_new_i32();
> +                    tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 24 - RRR_T);
> +                    tcg_gen_sari_i32(cpu_R[RRR_R], tmp, 24 - RRR_T);
> +                    tcg_temp_free(tmp);

It's probably worth special-casing extensions from bit 7 and 15
as normal 8 and 16-bit sign-extensions.  Those are likely to be
99% of all extension operations actually performed.


r~

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

* Re: [Qemu-devel] [RFC 12/28] target-xtensa: implement shifts (ST1 and RST1 groups)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 12/28] target-xtensa: implement shifts (ST1 and RST1 groups) Max Filippov
@ 2011-05-04 16:16   ` Richard Henderson
  2011-05-04 16:39     ` Max Filippov
  0 siblings, 1 reply; 49+ messages in thread
From: Richard Henderson @ 2011-05-04 16:16 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/03/2011 05:59 PM, Max Filippov wrote:
> +                    HAS_OPTION(XTENSA_OPTION_MISC_OP);
> +                    {
> +#define gen_bit_bisect(w) do { \
> +        int label = gen_new_label(); \
> +        tcg_gen_brcondi_i32(TCG_COND_LTU, tmp, 1 << (w), label); \
> +        tcg_gen_shri_i32(tmp, tmp, (w)); \
> +        tcg_gen_subi_i32(res, res, (w)); \
> +        gen_set_label(label); \
> +    } while (0)
> +
> +                        int label = gen_new_label();
> +                        TCGv_i32 res = tcg_temp_local_new_i32();
> +
> +                        tcg_gen_movi_i32(res, 32);
> +                        tcg_gen_brcondi_i32(
> +                                TCG_COND_EQ, cpu_R[RRR_S], 0, label);
> +                        {
> +                            TCGv_i32 tmp = tcg_temp_local_new_i32();
> +                            tcg_gen_mov_i32(tmp, cpu_R[RRR_S]);
> +                            tcg_gen_movi_i32(res, 31);
> +
> +                            gen_bit_bisect(16);
> +                            gen_bit_bisect(8);
> +                            gen_bit_bisect(4);
> +                            gen_bit_bisect(2);
> +                            gen_bit_bisect(1);
> +
> +                            tcg_temp_free(tmp);
> +                        }
> +                        gen_set_label(label);
> +                        tcg_gen_mov_i32(cpu_R[RRR_T], res);
> +                        tcg_temp_free(res);
> +#undef gen_bit_bisect

This instruction is probably right at the edge of the size restrictions
on the number of ops allowed to be emitted per guest insn.  It probably
makes more sense to move this to an out-of-line helper function.

Also note that this is implementable more efficiently on hosts that have
a count-leading-zeros function:

uint32_t HELPER(nsau)(uint32_t val)
{
    return val ? clz32(val) : 32;
}

uint32_t HELPER(nsa)(int32_t val)
{
    if (val < 0) {
        val = ~val;
    }
    if (val == 0) {
        return 31;
    }
    return clz32(val) - 1;
}

> +            case 9: /*SRL*/
> +                {
> +                    TCGv_i64 v = tcg_temp_new_i64();
> +                    tcg_gen_extu_i32_i64(v, cpu_R[RRR_T]);
> +                    gen_shift(shr);
> +                }
> +                break;
> +
> +            case 10: /*SLL*/
> +                {
> +                    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_extu_i32_i64(v, cpu_R[RRR_S]);
> +                    gen_shift_reg(shl, s);
> +                    tcg_temp_free(s);
> +                }
> +                break;
> +
> +            case 11: /*SRA*/
> +                {
> +                    TCGv_i64 v = tcg_temp_new_i64();
> +                    tcg_gen_ext_i32_i64(v, cpu_R[RRR_T]);
> +                    gen_shift(sar);
> +                }

Are you implementing some of these as 64-bit shifts simply
to get a shift count of 32 correct?  While I admit that it's
probably the most efficient mechanism when the host is 64-bit,
it's somewhat less than clear.  You could stand to add some
commentary here about your choice.

As a future enhancement, it might be worthwhile to track any
known contents of SAR within the TB (see how other ports put
information about the state of the flags register in the 
DisassContext).  If you have a known value in the SAR, you
can emit the proper 32-bit shift directly.


r~

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

* Re: [Qemu-devel] [RFC 18/28] target-xtensa: implement exceptions
  2011-05-04  0:59 ` [Qemu-devel] [RFC 18/28] target-xtensa: implement exceptions Max Filippov
@ 2011-05-04 16:33   ` Richard Henderson
  2011-05-04 17:00     ` Richard Henderson
  0 siblings, 1 reply; 49+ messages in thread
From: Richard Henderson @ 2011-05-04 16:33 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/03/2011 05:59 PM, Max Filippov wrote:
> +static void gen_check_privilege(DisasContext *dc)
> +{
> +    if (option_enabled(dc, XTENSA_OPTION_MMU)) {
> +        TCGv_i32 tmp = tcg_temp_new_i32();
> +        int label = gen_new_label();
> +
> +        tcg_gen_andi_i32(tmp, cpu_SR[PS], PS_EXCM);
> +        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, PS_EXCM, label);
> +        tcg_gen_andi_i32(tmp, cpu_SR[PS], PS_RING);
> +        tcg_gen_brcondi_i32(TCG_COND_GEU, tmp, 0, label);
> +
> +        gen_exception_cause(dc, PRIVILEGED_CAUSE);
> +
> +        gen_set_label(label);
> +        tcg_temp_free(tmp);
> +    }
> +}

This is a case where you almost certainly want to check this 
condition inside QEMU and translate the opcode differently.

See cpu_get_tb_cpu_state, which sets bits in *flags.  These
flags can then be checked in tb->flags while translating.
At which point you'd avoid all the conditionalization on
the value in PS here in check_privilege and merely issue
the exception_cause.

The ARM port is a good example for testing these sorts of bits.


r~

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

* Re: [Qemu-devel] [RFC 12/28] target-xtensa: implement shifts (ST1 and RST1 groups)
  2011-05-04 16:16   ` Richard Henderson
@ 2011-05-04 16:39     ` Max Filippov
  2011-05-04 19:07       ` Richard Henderson
  0 siblings, 1 reply; 49+ messages in thread
From: Max Filippov @ 2011-05-04 16:39 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

>> +                    HAS_OPTION(XTENSA_OPTION_MISC_OP);
>> +                    {
>> +#define gen_bit_bisect(w) do { \
>> +        int label = gen_new_label(); \
>> +        tcg_gen_brcondi_i32(TCG_COND_LTU, tmp, 1 << (w), label); \
>> +        tcg_gen_shri_i32(tmp, tmp, (w)); \
>> +        tcg_gen_subi_i32(res, res, (w)); \
>> +        gen_set_label(label); \
>> +    } while (0)
>> +
>> +                        int label = gen_new_label();
>> +                        TCGv_i32 res = tcg_temp_local_new_i32();
>> +
>> +                        tcg_gen_movi_i32(res, 32);
>> +                        tcg_gen_brcondi_i32(
>> +                                TCG_COND_EQ, cpu_R[RRR_S], 0, label);
>> +                        {
>> +                            TCGv_i32 tmp = tcg_temp_local_new_i32();
>> +                            tcg_gen_mov_i32(tmp, cpu_R[RRR_S]);
>> +                            tcg_gen_movi_i32(res, 31);
>> +
>> +                            gen_bit_bisect(16);
>> +                            gen_bit_bisect(8);
>> +                            gen_bit_bisect(4);
>> +                            gen_bit_bisect(2);
>> +                            gen_bit_bisect(1);
>> +
>> +                            tcg_temp_free(tmp);
>> +                        }
>> +                        gen_set_label(label);
>> +                        tcg_gen_mov_i32(cpu_R[RRR_T], res);
>> +                        tcg_temp_free(res);
>> +#undef gen_bit_bisect
>
> This instruction is probably right at the edge of the size restrictions
> on the number of ops allowed to be emitted per guest insn.  It probably
> makes more sense to move this to an out-of-line helper function.
>
> Also note that this is implementable more efficiently on hosts that have
> a count-leading-zeros function:
>
> uint32_t HELPER(nsau)(uint32_t val)
> {
>    return val ? clz32(val) : 32;
> }
>
> uint32_t HELPER(nsa)(int32_t val)
> {
>    if (val < 0) {
>        val = ~val;
>    }
>    if (val == 0) {
>        return 31;
>    }
>    return clz32(val) - 1;
> }

Thanks for the hint, this way it looks much better.

>> +            case 9: /*SRL*/
>> +                {
>> +                    TCGv_i64 v = tcg_temp_new_i64();
>> +                    tcg_gen_extu_i32_i64(v, cpu_R[RRR_T]);
>> +                    gen_shift(shr);
>> +                }
>> +                break;
>> +
>> +            case 10: /*SLL*/
>> +                {
>> +                    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_extu_i32_i64(v, cpu_R[RRR_S]);
>> +                    gen_shift_reg(shl, s);
>> +                    tcg_temp_free(s);
>> +                }
>> +                break;
>> +
>> +            case 11: /*SRA*/
>> +                {
>> +                    TCGv_i64 v = tcg_temp_new_i64();
>> +                    tcg_gen_ext_i32_i64(v, cpu_R[RRR_T]);
>> +                    gen_shift(sar);
>> +                }
>
> Are you implementing some of these as 64-bit shifts simply
> to get a shift count of 32 correct?  While I admit that it's
> probably the most efficient mechanism when the host is 64-bit,
> it's somewhat less than clear.  You could stand to add some
> commentary here about your choice.

Yes, possibility of indirect 32 bit shift was the only reason for that.
Will document that.

> As a future enhancement, it might be worthwhile to track any
> known contents of SAR within the TB (see how other ports put
> information about the state of the flags register in the
> DisassContext).  If you have a known value in the SAR, you
> can emit the proper 32-bit shift directly.

To track immediate values written to SAR? You mean that there may be
some performance difference of fixed size shift vs indirect shift and
TCG is able to tell them apart?

Thanks.
-- Max

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

* Re: [Qemu-devel] [RFC 18/28] target-xtensa: implement exceptions
  2011-05-04 16:33   ` Richard Henderson
@ 2011-05-04 17:00     ` Richard Henderson
  2011-05-09 19:38       ` Max Filippov
  0 siblings, 1 reply; 49+ messages in thread
From: Richard Henderson @ 2011-05-04 17:00 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/04/2011 09:33 AM, Richard Henderson wrote:
> This is a case where you almost certainly want to check this 
> condition inside QEMU and translate the opcode differently.
> 
> See cpu_get_tb_cpu_state, which sets bits in *flags.  These
> flags can then be checked in tb->flags while translating.
> At which point you'd avoid all the conditionalization on
> the value in PS here in check_privilege and merely issue
> the exception_cause.
> 
> The ARM port is a good example for testing these sorts of bits.

Actually, while the tb flags are useful, privileged instructions
are usually checked by testing mmu_index, since we already have
to generate different code for the TB based on which TLB entry we
need to access.


r~

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

* Re: [Qemu-devel] [RFC 12/28] target-xtensa: implement shifts (ST1 and RST1 groups)
  2011-05-04 16:39     ` Max Filippov
@ 2011-05-04 19:07       ` Richard Henderson
  2011-05-05  8:40         ` Max Filippov
  0 siblings, 1 reply; 49+ messages in thread
From: Richard Henderson @ 2011-05-04 19:07 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/04/2011 09:39 AM, Max Filippov wrote:
> To track immediate values written to SAR? You mean that there may be
> some performance difference of fixed size shift vs indirect shift and
> TCG is able to tell them apart?

Well, not really fixed vs indirect, but if you know that the value
in the SAR register is in the right range, you can avoid using a
64-bit shift.

For instance,

	SSL	ar2
	SLL	ar0, ar1

could be implemented with

	tcg_gen_sll_i32(ar0, ar1, ar2);

assuming we have enough context.

Let us decompose the SAR register into two parts, storing both the
true value, and 32-value.

    struct DisasContext {
        // Current Stuff
	// ...

	// When valid, holds 32-SAR.
        TCGv sar_m32;
	bool sar_m32_alloc;
	bool sar_m32_valid;
	bool sar_5bit;
    };

At the beginning of the TB:

	TCGV_UNUSED_I32(dc->sar_m32);
	dc->sar_m32_alloc = false;
	dc->sar_m32_valid = false;
	dc->sar_5bit = false;



static void gen_set_sra_m32(DisasContext *dc, TCGv val)
{
    if (!dc->sar_m32_alloc) {
        dc->sar_m32_alloc = true;
        dc->sar_m32 = tcg_temp_local_new_i32();
    }
    dc->sar_m32_valid = true;

    /* Clear 5 bit because the SAR value could be 32.  */
    dc->sar_5bit = false;

    tcg_gen_movi_i32(cpu_SR[SAR], 32);
    tcg_gen_sub_i32(cpu_SR[SAR], cpu_SR[SAR], val);
    tcg_gen_mov_i32(dc->sar_m32, val);
}

static void gen_set_sra(DisasContext *dc, TCGv val, bool is_5bit)
{
    if (dc->sar_m32_alloc && dc->sar_m32_valid) {
	tcg_gen_discard_i32(dc->sar_m32);
    }
    dc->sar_m32_valid = false;
    dc->sar_5bit = is_5bit;

    tcg_gen_mov_i32(cpu_SR[SAR], val);
}

	/* SSL */
	tcg_gen_andi_i32(tmp, cpu_R[AS], 31);
	gen_set_sra_m32(dc, tmp);
	break;

	/* SRL */
	tcg_gen_andi_i32(tmp, cpu_R[AS], 31);
	gen_set_sra(dc, tmp, true);
	break;

	/* WSR.SAR */
	tcg_gen_andi_i32(tmp, cpu_R[AS], 63);
	gen_set_sra(dc, tmp, false);
	break;

	/* SSAI */
	tcg_gen_movi_i32(tmp, constant);
	gen_gen_sra(dc, tmp, true);
	break;

	/* SLL */
	if (dc->sar_m32_valid) {
	    tcg_gen_sll_i32(cpu_R[AR], cpu_R[AS], dc->sar_m32);
        } else {
	    /* your existing 64-bit shift emulation.  */
	}
	break;

	/* SRL */
	if (dc->sar_5bit) {
	    tcg_gen_srl_i32(cpu_R[AR], cpu_R[AS], cpu_SR[SAR]);
	} else {
	    /* your existing 64-bit shift emulation.  */
	}


A couple of points: The use of the local temp avoids problems with
intervening insns that might generate branch opcodes.  For the
simplest cases, as with the case at the start of the message, we
ought to be able to propagate the values into the TCG shift insn
directly.

Does that make sense?


r~

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

* Re: [Qemu-devel] [RFC 20/28] target-xtensa: implement windowed registers
  2011-05-04  0:59 ` [Qemu-devel] [RFC 20/28] target-xtensa: implement windowed registers Max Filippov
@ 2011-05-04 19:35   ` Blue Swirl
  2011-05-04 20:07     ` Richard Henderson
  0 siblings, 1 reply; 49+ messages in thread
From: Blue Swirl @ 2011-05-04 19:35 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On Wed, May 4, 2011 at 3:59 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> See ISA, 4.7.1 for details.
>
> Physical registers and currently visible window are separate fields in
> CPUEnv. Only current window is accessible to TCG. On operations that
> change window base helpers copy current window to and from physical
> registers.

I'm not sure how the register windows work, but maybe you could use
the same trick used for Sparc. There is a pool of registers
(env->regbase[]), a register window pointer (env->regwptr,
cpu_regwptr) tracks which are the currently accessible ones. The
advantage is to avoid copying (not entirely for Sparc due to the
window overlap).

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

* Re: [Qemu-devel] [RFC 19/28] target-xtensa: implement RST2 group (32 bit mul/div/rem)
  2011-05-04  0:59 ` [Qemu-devel] [RFC 19/28] target-xtensa: implement RST2 group (32 bit mul/div/rem) Max Filippov
@ 2011-05-04 19:36   ` Blue Swirl
  2011-05-05  8:27     ` Max Filippov
  0 siblings, 1 reply; 49+ messages in thread
From: Blue Swirl @ 2011-05-04 19:36 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On Wed, May 4, 2011 at 3:59 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> 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 faf1adc..d635229 100644
> --- a/target-xtensa/translate.c
> +++ b/target-xtensa/translate.c
> @@ -793,7 +793,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_DIVIE_BY_ZERO_CAUSE);

DIVIE?

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

* Re: [Qemu-devel] [RFC 24/28] target-xtensa: implement SIMCALL
  2011-05-04  0:59 ` [Qemu-devel] [RFC 24/28] target-xtensa: implement SIMCALL Max Filippov
@ 2011-05-04 19:48   ` Blue Swirl
  2011-05-04 20:31     ` Peter Maydell
  0 siblings, 1 reply; 49+ messages in thread
From: Blue Swirl @ 2011-05-04 19:48 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On Wed, May 4, 2011 at 3:59 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> 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>
> ---
>  target-xtensa/helpers.h   |    1 +
>  target-xtensa/op_helper.c |    7 ++
>  target-xtensa/simcall.c   |  157 +++++++++++++++++++++++++++++++++++++++++++++
>  target-xtensa/translate.c |    2 +-
>  4 files changed, 166 insertions(+), 1 deletions(-)
>  create mode 100644 target-xtensa/simcall.c
>
> diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
> index 7e212a3..55eb0d8 100644
> --- a/target-xtensa/helpers.h
> +++ b/target-xtensa/helpers.h
> @@ -11,6 +11,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 f0690ee..68b1526 100644
> --- a/target-xtensa/op_helper.c
> +++ b/target-xtensa/op_helper.c
> @@ -264,6 +264,13 @@ void HELPER(wsr_lend)(uint32_t v)
>     }
>  }
>
> +#include "simcall.c"
> +
> +void HELPER(simcall)(void)
> +{
> +    simcall(env->regs);

Maybe this should be enabled only with -semihosting parameter, like
ARM and m68k. Consider for example what could happen if this would be
issued from userland when used with an OS.

> +}
> +
>  void HELPER(dump_state)(void)
>  {
>     cpu_dump_state(env, stderr, fprintf, 0);
> diff --git a/target-xtensa/simcall.c b/target-xtensa/simcall.c
> new file mode 100644
> index 0000000..3446275
> --- /dev/null
> +++ b/target-xtensa/simcall.c
> @@ -0,0 +1,157 @@
> +/*
> + * Copyright (c) 2011, Max Filippov, Motorola Solutions, Inc.
> + * 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 Motorola Solutions 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 <assert.h>
> +#include <errno.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <stddef.h>
> +
> +enum {
> +    SYS_exit = 1,
> +    SYS_read = 3,
> +    SYS_write = 4,
> +    SYS_open = 5,
> +    SYS_close = 6,
> +
> +    SYS_argc = 1000,
> +    SYS_argv_sz = 1001,
> +    SYS_argv = 1002,
> +    SYS_memset = 1004,

I think these names may easily conflict with system defines, please
use for example TARGET_SYS_exit etc.

> +};
> +
> +static void simcall(uint32_t regs[16])
> +{
> +    switch (regs[2]) {
> +    case SYS_exit:
> +        printf("exit(%d)\n", regs[3]);
> +        exit(regs[3]);
> +        break;
> +
> +    case 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] = 0;
> +            }
> +        }
> +        break;
> +
> +    case 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] = 0;
> +            }
> +        }
> +        break;
> +
> +    case SYS_open:
> +        {
> +            target_phys_addr_t len = 1024;
> +            void *buf = cpu_physical_memory_map(regs[3], &len, 0);
> +
> +            if (buf && strnlen((char *)buf, len) < len) {
> +                regs[2] = open((char *)buf, regs[4], regs[5]);
> +                regs[3] = errno;
> +            } else {
> +                regs[2] = -1;
> +                regs[3] = 0;
> +            }
> +        }
> +        break;
> +
> +    case SYS_close:
> +        if (regs[3] < 3) {
> +            regs[2] = regs[3] = 0;
> +        } else {
> +            regs[2] = close(regs[3]);
> +            regs[3] = errno;
> +        }
> +        break;
> +
> +    case SYS_argc:
> +        regs[2] = 1;
> +        regs[3] = 0;
> +        break;
> +
> +    case SYS_argv_sz:
> +        regs[2] = 128;
> +        regs[3] = 0;
> +        break;
> +
> +    case SYS_argv:
> +        {
> +            struct Argv {
> +                uint32_t argptr[2];
> +                char text[120];
> +            } argv = {
> +                {0, 0},
> +                "test"
> +            };
> +
> +            argv.argptr[0] = regs[3] + offsetof(struct Argv, text);
> +            cpu_memory_rw_debug(
> +                    env, regs[3], (uint8_t *)&argv, sizeof(argv), 1);
> +        }
> +        break;
> +
> +    case SYS_memset:
> +        {
> +            target_phys_addr_t len = regs[5];
> +            void *buf = cpu_physical_memory_map(regs[3], &len, 1);
> +
> +            assert(len == regs[5]);

The guest can probably trigger this assertion, which would not be safe.

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

* Re: [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs
  2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
                   ` (27 preceding siblings ...)
  2011-05-04  6:04 ` [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
@ 2011-05-04 19:51 ` Blue Swirl
  28 siblings, 0 replies; 49+ messages in thread
From: Blue Swirl @ 2011-05-04 19:51 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On Wed, May 4, 2011 at 3:59 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
> ---
>  Makefile.target           |    2 +
>  arch_init.c               |    2 +
>  arch_init.h               |    1 +
>  cpu-exec.c                |   10 +++++
>  elf.h                     |    2 +
>  hw/xtensa_pic.c           |   11 ++++++
>  target-xtensa/cpu.h       |   84 +++++++++++++++++++++++++++++++++++++++++++++
>  target-xtensa/exec.h      |   55 +++++++++++++++++++++++++++++
>  target-xtensa/helper.c    |   74 +++++++++++++++++++++++++++++++++++++++
>  target-xtensa/machine.c   |   38 ++++++++++++++++++++
>  target-xtensa/op_helper.c |   51 +++++++++++++++++++++++++++
>  target-xtensa/translate.c |   67 +++++++++++++++++++++++++++++++++++
>  12 files changed, 397 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 21f864a..7e7afd2 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -366,6 +366,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 0c09f91..c1f0005 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 86ebc14..61ad347 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 395cd8c..a692daf 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
> @@ -568,6 +571,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 interupt_request value,
>                       do_interrupt may have updated the EXITTB flag. */
> @@ -696,6 +705,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..5ff1697
> --- /dev/null
> +++ b/hw/xtensa_pic.c
> @@ -0,0 +1,11 @@
> +#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..ef6881a
> --- /dev/null
> +++ b/target-xtensa/cpu.h
> @@ -0,0 +1,84 @@
> +/*
> + * Copyright (c) 2011, Max Filippov, Motorola Solutions, Inc.
> + * 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 Motorola Solutions 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..5a0cb6f
> --- /dev/null
> +++ b/target-xtensa/exec.h
> @@ -0,0 +1,55 @@
> +/*
> + * Copyright (c) 2011, Max Filippov, Motorola Solutions, Inc.
> + * 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 Motorola Solutions 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;
> +}
> +
> +static inline int cpu_halted(CPUState *env)
> +{
> +    return 0;
> +}
> +
> +#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..6b6e17b
> --- /dev/null
> +++ b/target-xtensa/helper.c
> @@ -0,0 +1,74 @@
> +/*
> + * Copyright (c) 2011, Max Filippov, Motorola Solutions, Inc.
> + * 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 Motorola Solutions 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();
> +    }
> +
> +    cpu_reset(env);

CPU init should not call reset anymore, this is done elsewhere nowadays.

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

* Re: [Qemu-devel] [RFC 20/28] target-xtensa: implement windowed registers
  2011-05-04 19:35   ` Blue Swirl
@ 2011-05-04 20:07     ` Richard Henderson
  2011-05-04 20:13       ` Blue Swirl
  0 siblings, 1 reply; 49+ messages in thread
From: Richard Henderson @ 2011-05-04 20:07 UTC (permalink / raw)
  To: Blue Swirl; +Cc: Max Filippov, qemu-devel

On 05/04/2011 12:35 PM, Blue Swirl wrote:
> On Wed, May 4, 2011 at 3:59 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
>> See ISA, 4.7.1 for details.
>>
>> Physical registers and currently visible window are separate fields in
>> CPUEnv. Only current window is accessible to TCG. On operations that
>> change window base helpers copy current window to and from physical
>> registers.
> 
> I'm not sure how the register windows work, but maybe you could use
> the same trick used for Sparc. There is a pool of registers
> (env->regbase[]), a register window pointer (env->regwptr,
> cpu_regwptr) tracks which are the currently accessible ones. The
> advantage is to avoid copying (not entirely for Sparc due to the
> window overlap).

Sparc loses out on some TCG optimizations because of that, although
to be fair the most effective of these are still in Aurlien's trees.

That said, I still would not recommend a new port to follow suit.


r~

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

* Re: [Qemu-devel] [RFC 20/28] target-xtensa: implement windowed registers
  2011-05-04 20:07     ` Richard Henderson
@ 2011-05-04 20:13       ` Blue Swirl
  2011-05-04 20:30         ` Richard Henderson
  0 siblings, 1 reply; 49+ messages in thread
From: Blue Swirl @ 2011-05-04 20:13 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Max Filippov, qemu-devel

On Wed, May 4, 2011 at 11:07 PM, Richard Henderson <rth@twiddle.net> wrote:
> On 05/04/2011 12:35 PM, Blue Swirl wrote:
>> On Wed, May 4, 2011 at 3:59 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
>>> See ISA, 4.7.1 for details.
>>>
>>> Physical registers and currently visible window are separate fields in
>>> CPUEnv. Only current window is accessible to TCG. On operations that
>>> change window base helpers copy current window to and from physical
>>> registers.
>>
>> I'm not sure how the register windows work, but maybe you could use
>> the same trick used for Sparc. There is a pool of registers
>> (env->regbase[]), a register window pointer (env->regwptr,
>> cpu_regwptr) tracks which are the currently accessible ones. The
>> advantage is to avoid copying (not entirely for Sparc due to the
>> window overlap).
>
> Sparc loses out on some TCG optimizations because of that, although
> to be fair the most effective of these are still in Aurlien's trees.

Interesting. Which optimizations? What trees? How would you implement
the register windows then?

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

* Re: [Qemu-devel] [RFC 20/28] target-xtensa: implement windowed registers
  2011-05-04 20:13       ` Blue Swirl
@ 2011-05-04 20:30         ` Richard Henderson
  0 siblings, 0 replies; 49+ messages in thread
From: Richard Henderson @ 2011-05-04 20:30 UTC (permalink / raw)
  To: Blue Swirl; +Cc: Max Filippov, qemu-devel

On 05/04/2011 01:13 PM, Blue Swirl wrote:
>> Sparc loses out on some TCG optimizations because of that, although
>> to be fair the most effective of these are still in Aurlien's trees.
> 
> Interesting. Which optimizations? What trees? How would you implement
> the register windows then?

Constant propagation for one.  This one in particular would allow the
tcg backend to see full constants, rather than seeing the constant 
being built up from risc instructions.

  git://git.aurel32.net/qemu.git tcg-optimizations

I have previously built on this to streamline the code generated for
target load/store operations.  We currently always force the address
into a register and do the arithmetic on that.  If we have the full
constant for the address, we can push the parts of that constant into
the TLB load etc.

  git://repo.or.cz/qemu/rth.git tcg-const-addr-1

As for how to implement the register windows...

I'm not 100% sure.  The easiest way is indeed to copy values to and
fro a consolidated register file, as Max is doing here.  I've also
experimented briefly with extending TCG to handle "indirect" registers.
Where the register values are consistent as far as the TCG optimizers
are concerned, but when it comes time to expand the code, we perform
the indirect read, just as you currently expand by hand ahead of time.
I never got either solution totally working for sparc.


r~

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

* Re: [Qemu-devel] [RFC 24/28] target-xtensa: implement SIMCALL
  2011-05-04 19:48   ` Blue Swirl
@ 2011-05-04 20:31     ` Peter Maydell
  0 siblings, 0 replies; 49+ messages in thread
From: Peter Maydell @ 2011-05-04 20:31 UTC (permalink / raw)
  To: Blue Swirl; +Cc: Max Filippov, qemu-devel

On 4 May 2011 20:48, Blue Swirl <blauwirbel@gmail.com> wrote:
> On Wed, May 4, 2011 at 3:59 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
>> 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>
>> ---
>>  target-xtensa/helpers.h   |    1 +
>>  target-xtensa/op_helper.c |    7 ++
>>  target-xtensa/simcall.c   |  157 +++++++++++++++++++++++++++++++++++++++++++++

The existing simcall/semihosting implementations
are in arm-semi.c and m68k-semi.c in the top level
directory. I think xtensa should do the same
(unless somebody wants to propose moving arm and
m68k instead...)

>> +void HELPER(simcall)(void)
>> +{
>> +    simcall(env->regs);
>
> Maybe this should be enabled only with -semihosting parameter, like
> ARM and m68k. Consider for example what could happen if this would be
> issued from userland when used with an OS.

+1 for consistency with arm/m68k. This applies more generally:
for example if there's any chance there might be a linux-user
implementation for xtensa then you want to use the softmmu-semi.h
helpers so the memory access will work in both setups.

m68k and ARM also both funnel semihosting through the interrupt/
exception mechanisms; I haven't figured out if there's a good
reason for that that would make it worth copying in xtensa :-)

>> +    SYS_exit = 1,

> I think these names may easily conflict with system defines, please
> use for example TARGET_SYS_exit etc.

Renaming's safe, but as it happens arm-semi.c has been
using SYS_EXIT &c with no problems, so I don't think it's
a big deal either way.

-- PMM

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

* Re: [Qemu-devel] [RFC 19/28] target-xtensa: implement RST2 group (32 bit mul/div/rem)
  2011-05-04 19:36   ` Blue Swirl
@ 2011-05-05  8:27     ` Max Filippov
  0 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-05  8:27 UTC (permalink / raw)
  To: Blue Swirl; +Cc: qemu-devel

>>         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_DIVIE_BY_ZERO_CAUSE);
>
> DIVIE?

Oops (: Looks like I overuse ^n.

Thanks.
-- Max

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

* Re: [Qemu-devel] [RFC 12/28] target-xtensa: implement shifts (ST1 and RST1 groups)
  2011-05-04 19:07       ` Richard Henderson
@ 2011-05-05  8:40         ` Max Filippov
  0 siblings, 0 replies; 49+ messages in thread
From: Max Filippov @ 2011-05-05  8:40 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

>> To track immediate values written to SAR? You mean that there may be
>> some performance difference of fixed size shift vs indirect shift and
>> TCG is able to tell them apart?
>
> Well, not really fixed vs indirect, but if you know that the value
> in the SAR register is in the right range, you can avoid using a
> 64-bit shift.
>
> For instance,
>
>        SSL     ar2
>        SLL     ar0, ar1
>
> could be implemented with
>
>        tcg_gen_sll_i32(ar0, ar1, ar2);
>
> assuming we have enough context.
>
> Let us decompose the SAR register into two parts, storing both the
> true value, and 32-value.
>
>    struct DisasContext {
>        // Current Stuff
>        // ...
>
>        // When valid, holds 32-SAR.
>        TCGv sar_m32;
>        bool sar_m32_alloc;
>        bool sar_m32_valid;
>        bool sar_5bit;
>    };
>
> At the beginning of the TB:
>
>        TCGV_UNUSED_I32(dc->sar_m32);
>        dc->sar_m32_alloc = false;
>        dc->sar_m32_valid = false;
>        dc->sar_5bit = false;
>
>
>
> static void gen_set_sra_m32(DisasContext *dc, TCGv val)
> {
>    if (!dc->sar_m32_alloc) {
>        dc->sar_m32_alloc = true;
>        dc->sar_m32 = tcg_temp_local_new_i32();
>    }
>    dc->sar_m32_valid = true;
>
>    /* Clear 5 bit because the SAR value could be 32.  */
>    dc->sar_5bit = false;
>
>    tcg_gen_movi_i32(cpu_SR[SAR], 32);
>    tcg_gen_sub_i32(cpu_SR[SAR], cpu_SR[SAR], val);
>    tcg_gen_mov_i32(dc->sar_m32, val);
> }
>
> static void gen_set_sra(DisasContext *dc, TCGv val, bool is_5bit)
> {
>    if (dc->sar_m32_alloc && dc->sar_m32_valid) {
>        tcg_gen_discard_i32(dc->sar_m32);
>    }
>    dc->sar_m32_valid = false;
>    dc->sar_5bit = is_5bit;
>
>    tcg_gen_mov_i32(cpu_SR[SAR], val);
> }
>
>        /* SSL */
>        tcg_gen_andi_i32(tmp, cpu_R[AS], 31);
>        gen_set_sra_m32(dc, tmp);
>        break;
>
>        /* SRL */
>        tcg_gen_andi_i32(tmp, cpu_R[AS], 31);
>        gen_set_sra(dc, tmp, true);
>        break;
>
>        /* WSR.SAR */
>        tcg_gen_andi_i32(tmp, cpu_R[AS], 63);
>        gen_set_sra(dc, tmp, false);
>        break;
>
>        /* SSAI */
>        tcg_gen_movi_i32(tmp, constant);
>        gen_gen_sra(dc, tmp, true);
>        break;
>
>        /* SLL */
>        if (dc->sar_m32_valid) {
>            tcg_gen_sll_i32(cpu_R[AR], cpu_R[AS], dc->sar_m32);
>        } else {
>            /* your existing 64-bit shift emulation.  */
>        }
>        break;
>
>        /* SRL */
>        if (dc->sar_5bit) {
>            tcg_gen_srl_i32(cpu_R[AR], cpu_R[AS], cpu_SR[SAR]);
>        } else {
>            /* your existing 64-bit shift emulation.  */
>        }
>
>
> A couple of points: The use of the local temp avoids problems with
> intervening insns that might generate branch opcodes.  For the
> simplest cases, as with the case at the start of the message, we
> ought to be able to propagate the values into the TCG shift insn
> directly.
>
> Does that make sense?

Yes it does. Thanks for the good explanation.
I tried to keep it all as simple as possible to have a working
prototype qickly. Now that it works optimizations should be no
problem.

Thanks.
-- Max

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

* Re: [Qemu-devel] [RFC 18/28] target-xtensa: implement exceptions
  2011-05-04 17:00     ` Richard Henderson
@ 2011-05-09 19:38       ` Max Filippov
  2011-05-09 20:32         ` Richard Henderson
  0 siblings, 1 reply; 49+ messages in thread
From: Max Filippov @ 2011-05-09 19:38 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

> > This is a case where you almost certainly want to check this 
> > condition inside QEMU and translate the opcode differently.
> > 
> > See cpu_get_tb_cpu_state, which sets bits in *flags.  These
> > flags can then be checked in tb->flags while translating.
> > At which point you'd avoid all the conditionalization on
> > the value in PS here in check_privilege and merely issue
> > the exception_cause.
> > 
> > The ARM port is a good example for testing these sorts of bits.
> 
> Actually, while the tb flags are useful, privileged instructions
> are usually checked by testing mmu_index, since we already have
> to generate different code for the TB based on which TLB entry we
> need to access.

Richard,
do I understand it right that if I use tb->flags or mem_index to make decisions during translation, then I must issue exit_tb on instructions that can change state they reflect?

Thanks.
-- Max

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

* Re: [Qemu-devel] [RFC 18/28] target-xtensa: implement exceptions
  2011-05-09 19:38       ` Max Filippov
@ 2011-05-09 20:32         ` Richard Henderson
  0 siblings, 0 replies; 49+ messages in thread
From: Richard Henderson @ 2011-05-09 20:32 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

On 05/09/2011 12:38 PM, Max Filippov wrote:
> do I understand it right that if I use tb->flags or mem_index to make
> decisions during translation, then I must issue exit_tb on
> instructions that can change state they reflect?

Yes.

Quite often it's some sort of branch instruction anyway, such as
return-from-interrupt changing from kernel mode back to user mode.
However, there are some non-branch instructions that may require
the TB to end, such as TLB flushes.


r~

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

end of thread, other threads:[~2011-05-09 20:32 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-04  0:59 [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 02/28] target-xtensa: add target to the configure script Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 03/28] target-xtensa: implement disas_xtensa_insn Max Filippov
2011-05-04 15:39   ` Richard Henderson
2011-05-04  0:59 ` [Qemu-devel] [RFC 04/28] target-xtensa: implement narrow instructions Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 05/28] target-xtensa: implement RT0 group Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 06/28] target-xtensa: add sample board Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 07/28] target-xtensa: add gdb support Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 08/28] target-xtensa: implement conditional jumps Max Filippov
2011-05-04 15:45   ` Richard Henderson
2011-05-04  0:59 ` [Qemu-devel] [RFC 09/28] target-xtensa: implement JX/RET0/CALLX Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 10/28] target-xtensa: add special and user registers Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 11/28] target-xtensa: implement RST3 group Max Filippov
2011-05-04 15:51   ` Richard Henderson
2011-05-04  0:59 ` [Qemu-devel] [RFC 12/28] target-xtensa: implement shifts (ST1 and RST1 groups) Max Filippov
2011-05-04 16:16   ` Richard Henderson
2011-05-04 16:39     ` Max Filippov
2011-05-04 19:07       ` Richard Henderson
2011-05-05  8:40         ` Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 13/28] target-xtensa: implement LSAI group Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 14/28] target-xtensa: mark reserved and TBD opcodes Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 15/28] target-xtensa: big endian support Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 16/28] target-xtensa: implement SYNC group Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 17/28] target-xtensa: implement CACHE group Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 18/28] target-xtensa: implement exceptions Max Filippov
2011-05-04 16:33   ` Richard Henderson
2011-05-04 17:00     ` Richard Henderson
2011-05-09 19:38       ` Max Filippov
2011-05-09 20:32         ` Richard Henderson
2011-05-04  0:59 ` [Qemu-devel] [RFC 19/28] target-xtensa: implement RST2 group (32 bit mul/div/rem) Max Filippov
2011-05-04 19:36   ` Blue Swirl
2011-05-05  8:27     ` Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 20/28] target-xtensa: implement windowed registers Max Filippov
2011-05-04 19:35   ` Blue Swirl
2011-05-04 20:07     ` Richard Henderson
2011-05-04 20:13       ` Blue Swirl
2011-05-04 20:30         ` Richard Henderson
2011-05-04  0:59 ` [Qemu-devel] [RFC 21/28] target-xtensa: implement loop option Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 22/28] target-xtensa: implement extended L32R Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 23/28] target-xtensa: implement unaligned exception option Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 24/28] target-xtensa: implement SIMCALL Max Filippov
2011-05-04 19:48   ` Blue Swirl
2011-05-04 20:31     ` Peter Maydell
2011-05-04  0:59 ` [Qemu-devel] [RFC 25/28] target-xtensa: implement interrupt option Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 26/28] target-xtensa: implement accurate window check Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 27/28] target-xtensa: implement CPENABLE and PRID SRs Max Filippov
2011-05-04  0:59 ` [Qemu-devel] [RFC 28/28] target-xtensa: implement relocatable vectors Max Filippov
2011-05-04  6:04 ` [Qemu-devel] [RFC 01/28] target-xtensa: add target stubs Max Filippov
2011-05-04 19:51 ` Blue Swirl

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.