From: Michael Rolnik <mrolnik@gmail.com>
To: qemu-devel@nongnu.org
Cc: Michael Rolnik <mrolnik@gmail.com>
Subject: [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit
Date: Fri, 9 Sep 2016 01:31:42 +0300 [thread overview]
Message-ID: <1473373930-31547-2-git-send-email-mrolnik@gmail.com> (raw)
In-Reply-To: <1473373930-31547-1-git-send-email-mrolnik@gmail.com>
Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
.gitignore | 2 +
MAINTAINERS | 5 +
arch_init.c | 2 +
configure | 5 +
default-configs/arc-softmmu.mak | 0
include/sysemu/arch_init.h | 1 +
target-arc/Makefile.objs | 26 +++
target-arc/cpu-qom.h | 84 ++++++++
target-arc/cpu.c | 269 +++++++++++++++++++++++++
target-arc/cpu.h | 174 +++++++++++++++++
target-arc/decode.c | 7 +
target-arc/gdbstub.c | 138 +++++++++++++
target-arc/helper.c | 74 +++++++
target-arc/helper.h | 21 ++
target-arc/machine.c | 35 ++++
target-arc/machine.h | 21 ++
target-arc/translate.c | 424 ++++++++++++++++++++++++++++++++++++++++
target-arc/translate.h | 223 +++++++++++++++++++++
18 files changed, 1511 insertions(+)
create mode 100644 default-configs/arc-softmmu.mak
create mode 100644 target-arc/Makefile.objs
create mode 100644 target-arc/cpu-qom.h
create mode 100644 target-arc/cpu.c
create mode 100644 target-arc/cpu.h
create mode 100644 target-arc/decode.c
create mode 100644 target-arc/gdbstub.c
create mode 100644 target-arc/helper.c
create mode 100644 target-arc/helper.h
create mode 100644 target-arc/machine.c
create mode 100644 target-arc/machine.h
create mode 100644 target-arc/translate.c
create mode 100644 target-arc/translate.h
diff --git a/.gitignore b/.gitignore
index 88ec249..37a71af 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,6 +58,8 @@
/fsdev/virtfs-proxy-helper
*.[1-9]
*.a
+*.swp
+*.swo
*.aux
*.cp
*.dvi
diff --git a/MAINTAINERS b/MAINTAINERS
index b6fb84e..0500cf5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -99,6 +99,11 @@ F: hw/alpha/
F: tests/tcg/alpha/
F: disas/alpha.c
+ARC
+M: Michael Rolnik <mrolnik@gmail.com>
+S: Maintained
+F: target-arc/
+
ARM
M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
diff --git a/arch_init.c b/arch_init.c
index fa05973..04b51f5 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -80,6 +80,8 @@ int graphic_depth = 32;
#define QEMU_ARCH QEMU_ARCH_UNICORE32
#elif defined(TARGET_TRICORE)
#define QEMU_ARCH QEMU_ARCH_TRICORE
+#elif defined(TARGET_ARC)
+#define QEMU_ARCH QEMU_ARCH_ARC
#endif
const uint32_t arch_type = QEMU_ARCH;
diff --git a/configure b/configure
index 5a9bda1..8aee641 100755
--- a/configure
+++ b/configure
@@ -5672,6 +5672,8 @@ case "$target_name" in
;;
alpha)
;;
+ arc)
+ ;;
arm|armeb)
TARGET_ARCH=arm
bflt="yes"
@@ -5874,6 +5876,9 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
disas_config "ARM_A64"
fi
;;
+ arc)
+ disas_config "ARC"
+ ;;
arm)
disas_config "ARM"
if test -n "${cxx}"; then
diff --git a/default-configs/arc-softmmu.mak b/default-configs/arc-softmmu.mak
new file mode 100644
index 0000000..e69de29
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 1c9dad1..35148a6 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -23,6 +23,7 @@ enum {
QEMU_ARCH_UNICORE32 = (1 << 14),
QEMU_ARCH_MOXIE = (1 << 15),
QEMU_ARCH_TRICORE = (1 << 16),
+ QEMU_ARCH_ARC = (1 << 16),
};
extern const uint32_t arch_type;
diff --git a/target-arc/Makefile.objs b/target-arc/Makefile.objs
new file mode 100644
index 0000000..a3475dd
--- /dev/null
+++ b/target-arc/Makefile.objs
@@ -0,0 +1,26 @@
+#
+# QEMU ARC CPU
+#
+# Copyright (c) 2016 Michael Rolnik
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see
+# <http://www.gnu.org/licenses/lgpl-2.1.html>
+#
+
+obj-y += translate.o
+obj-y += helper.o
+obj-y += cpu.o
+obj-y += gdbstub.o
+obj-y += decode.o
+obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-arc/cpu-qom.h b/target-arc/cpu-qom.h
new file mode 100644
index 0000000..b9cb1b2
--- /dev/null
+++ b/target-arc/cpu-qom.h
@@ -0,0 +1,84 @@
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#ifndef QEMU_ARC_CPU_QOM_H
+#define QEMU_ARC_CPU_QOM_H
+
+#include "qom/cpu.h"
+
+#define TYPE_ARC_CPU "arc"
+
+#define ARC_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(ARCCPUClass, (klass), TYPE_ARC_CPU)
+#define ARC_CPU(obj) \
+ OBJECT_CHECK(ARCCPU, (obj), TYPE_ARC_CPU)
+#define ARC_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(ARCCPUClass, (obj), TYPE_ARC_CPU)
+
+/**
+* ARCCPUClass:
+* @parent_realize: The parent class' realize handler.
+* @parent_reset: The parent class' reset handler.
+* @vr: Version Register value.
+*
+* A ARC CPU model.
+*/
+typedef struct ARCCPUClass {
+ CPUClass parent_class;
+
+ DeviceRealize parent_realize;
+ void (*parent_reset)(CPUState *cpu);
+} ARCCPUClass;
+
+/**
+* ARCCPU:
+* @env: #CPUARCState
+*
+* A ARC CPU.
+*/
+typedef struct ARCCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUARCState env;
+} ARCCPU;
+
+static inline ARCCPU *arc_env_get_cpu(CPUARCState *env)
+{
+ return container_of(env, ARCCPU, env);
+}
+
+#define ENV_GET_CPU(e) CPU(arc_env_get_cpu(e))
+#define ENV_OFFSET offsetof(ARCCPU, env)
+
+#ifndef CONFIG_USER_ONLY
+extern const struct VMStateDescription vms_arc_cpu;
+#endif
+
+void arc_cpu_do_interrupt(CPUState *cpu);
+bool arc_cpu_exec_interrupt(CPUState *cpu, int int_req);
+void arc_cpu_dump_state(CPUState *cs, FILE *f,
+ fprintf_function cpu_fprintf, int flags);
+hwaddr arc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int arc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int arc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+
+#endif
diff --git a/target-arc/cpu.c b/target-arc/cpu.c
new file mode 100644
index 0000000..b162274
--- /dev/null
+++ b/target-arc/cpu.c
@@ -0,0 +1,269 @@
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "qemu-common.h"
+#include "migration/vmstate.h"
+#include "machine.h"
+
+static void arc_cpu_set_pc(CPUState *cs, vaddr value)
+{
+ ARCCPU *cpu = ARC_CPU(cs);
+
+ CPU_PCL(&cpu->env) = value & 0xfffffffc;
+ cpu->env.pc = value;
+}
+
+static bool arc_cpu_has_work(CPUState *cs)
+{
+ return false;
+}
+static void arc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
+{
+ ARCCPU *cpu = ARC_CPU(cs);
+ CPUARCState *env = &cpu->env;
+
+ env->pc = tb->pc;
+}
+
+static void arc_cpu_reset(CPUState *s)
+{
+ ARCCPU *cpu = ARC_CPU(s);
+ ARCCPUClass *mcc = ARC_CPU_GET_CLASS(cpu);
+ CPUARCState *env = &cpu->env;
+
+ mcc->parent_reset(s);
+
+ memset(env->r, 0, sizeof(env->r));
+ env->pc = 0x12c; /* TODO: this is just for testing */
+ CPU_PCL(env) = 0x12c; /* TODO: this is just for testing */
+
+ tlb_flush(s, 1);
+}
+
+static void arc_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
+{
+ info->mach = bfd_arch_arc;
+ info->print_insn = NULL;
+}
+
+static void arc_cpu_realizefn(DeviceState *dev, Error **errp)
+{
+ CPUState *cs = CPU(dev);
+ ARCCPUClass *mcc = ARC_CPU_GET_CLASS(dev);
+
+ qemu_init_vcpu(cs);
+ cpu_reset(cs);
+
+ mcc->parent_realize(dev, errp);
+}
+
+static void arc_cpu_set_int(void *opaque, int irq, int level)
+{
+}
+
+static void arc_cpu_initfn(Object *obj)
+{
+ CPUState *cs = CPU(obj);
+ ARCCPU *cpu = ARC_CPU(obj);
+ static int inited;
+
+ cs->env_ptr = &cpu->env;
+ cpu_exec_init(cs, &error_abort);
+
+#ifndef CONFIG_USER_ONLY
+ qdev_init_gpio_in(DEVICE(cpu), arc_cpu_set_int, 37);
+#endif
+
+ if (tcg_enabled() && !inited) {
+ inited = 1;
+ arc_translate_init();
+ }
+}
+
+static ObjectClass *arc_cpu_class_by_name(const char *cpu_model)
+{
+ ObjectClass *oc;
+ char *typename;
+ char **cpuname;
+
+ if (!cpu_model) {
+ return NULL;
+ }
+
+ cpuname = g_strsplit(cpu_model, ",", 1);
+ typename = g_strdup_printf("%s-" TYPE_ARC_CPU, cpuname[0]);
+ oc = object_class_by_name(typename);
+
+ g_strfreev(cpuname);
+ g_free(typename);
+
+ if (!oc
+ || !object_class_dynamic_cast(oc, TYPE_ARC_CPU)
+ || object_class_is_abstract(oc)) {
+ return NULL;
+ }
+
+ return oc;
+}
+
+static void arc_cpu_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ CPUClass *cc = CPU_CLASS(oc);
+ ARCCPUClass *mcc = ARC_CPU_CLASS(oc);
+
+ mcc->parent_realize = dc->realize;
+ dc->realize = arc_cpu_realizefn;
+
+ mcc->parent_reset = cc->reset;
+ cc->reset = arc_cpu_reset;
+
+ cc->class_by_name = arc_cpu_class_by_name;
+
+ cc->has_work = arc_cpu_has_work;
+ cc->do_interrupt = arc_cpu_do_interrupt;
+ cc->cpu_exec_interrupt = arc_cpu_exec_interrupt;
+ cc->dump_state = arc_cpu_dump_state;
+ cc->set_pc = arc_cpu_set_pc;
+#if !defined(CONFIG_USER_ONLY)
+ cc->memory_rw_debug = arc_cpu_memory_rw_debug;
+#endif
+#ifdef CONFIG_USER_ONLY
+ cc->handle_mmu_fault = arc_cpu_handle_mmu_fault;
+#else
+ cc->get_phys_page_debug = arc_cpu_get_phys_page_debug;
+ cc->vmsd = &vms_arc_cpu;
+#endif
+ cc->disas_set_info = arc_cpu_disas_set_info;
+ cc->synchronize_from_tb = arc_cpu_synchronize_from_tb;
+ cc->gdb_read_register = arc_cpu_gdb_read_register;
+ cc->gdb_write_register = arc_cpu_gdb_write_register;
+ cc->gdb_num_core_regs = 68;
+
+ /*
+ * Reason: arc_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
+}
+
+static void arc_any_initfn(Object *obj)
+{
+ /* Set cpu feature flags */
+}
+
+typedef struct ARCCPUInfo {
+ const char *name;
+ void (*initfn)(Object *obj);
+} ARCCPUInfo;
+
+static const ARCCPUInfo arc_cpus[] = {
+ { .name = "any", .initfn = arc_any_initfn },
+};
+
+static gint arc_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+ ObjectClass *class_a = (ObjectClass *)a;
+ ObjectClass *class_b = (ObjectClass *)b;
+ const char *name_a;
+ const char *name_b;
+
+ name_a = object_class_get_name(class_a);
+ name_b = object_class_get_name(class_b);
+ if (strcmp(name_a, "any-" TYPE_ARC_CPU) == 0) {
+ return 1;
+ } else if (strcmp(name_b, "any-" TYPE_ARC_CPU) == 0) {
+ return -1;
+ } else {
+ return strcmp(name_a, name_b);
+ }
+}
+
+static void arc_cpu_list_entry(gpointer data, gpointer user_data)
+{
+ ObjectClass *oc = data;
+ CPUListState *s = user_data;
+ const char *typename;
+ char *name;
+
+ typename = object_class_get_name(oc);
+ name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_ARC_CPU));
+ (*s->cpu_fprintf)(s->file, " %s\n", name);
+ g_free(name);
+}
+
+void arc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+ CPUListState s = {
+ .file = f,
+ .cpu_fprintf = cpu_fprintf,
+ };
+ GSList *list;
+
+ list = object_class_get_list(TYPE_ARC_CPU, false);
+ list = g_slist_sort(list, arc_cpu_list_compare);
+ (*cpu_fprintf)(f, "Available CPUs:\n");
+ g_slist_foreach(list, arc_cpu_list_entry, &s);
+ g_slist_free(list);
+}
+ARCCPU *cpu_arc_init(const char *cpu_model)
+{
+ return ARC_CPU(cpu_generic_init(TYPE_ARC_CPU, cpu_model));
+}
+
+static void cpu_register(const ARCCPUInfo *info)
+{
+ TypeInfo type_info = {
+ .parent = TYPE_ARC_CPU,
+ .instance_size = sizeof(ARCCPU),
+ .instance_init = info->initfn,
+ .class_size = sizeof(ARCCPUClass),
+ };
+
+ type_info.name = g_strdup_printf("%s-" TYPE_ARC_CPU, info->name);
+ type_register(&type_info);
+ g_free((void *)type_info.name);
+}
+
+static const TypeInfo arc_cpu_type_info = {
+ .name = TYPE_ARC_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(ARCCPU),
+ .instance_init = arc_cpu_initfn,
+ .class_size = sizeof(ARCCPUClass),
+ .class_init = arc_cpu_class_init,
+ .abstract = true,
+};
+
+static void arc_cpu_register_types(void)
+{
+ int i;
+ type_register_static(&arc_cpu_type_info);
+
+ for (i = 0; i < ARRAY_SIZE(arc_cpus); i++) {
+ cpu_register(&arc_cpus[i]);
+ }
+}
+
+type_init(arc_cpu_register_types)
diff --git a/target-arc/cpu.h b/target-arc/cpu.h
new file mode 100644
index 0000000..253a1bc
--- /dev/null
+++ b/target-arc/cpu.h
@@ -0,0 +1,174 @@
+ /*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#if !defined(CPU_ARC_H)
+#define CPU_ARC_H
+
+#include "qemu-common.h"
+
+#define TARGET_LONG_BITS 32
+
+#define CPUArchState struct CPUARCState
+
+#include "exec/cpu-defs.h"
+#include "fpu/softfloat.h"
+
+#define TARGET_PAGE_BITS 12
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+#define NB_MMU_MODES 1
+
+#define MMU_IDX 0
+
+#define PHYS_BASE_RAM 0x00000000
+#define VIRT_BASE_RAM 0x00000000
+
+enum arc_features {
+ ARC_FEATURE_ARC5,
+ ARC_FEATURE_ARC600,
+ ARC_FEATURE_ARC700,
+ no_features,
+};
+
+
+typedef struct CPUARCState CPUARCState;
+#define CPU_GP(env) ((env)->r[26])
+#define CPU_FP(env) ((env)->r[27])
+#define CPU_SP(env) ((env)->r[28])
+#define CPU_ILINK1(env) ((env)->r[29])
+#define CPU_ILINK2(env) ((env)->r[30])
+#define CPU_BLINK(env) ((env)->r[31])
+#define CPU_MLO(env) ((env)->r[57])
+#define CPU_MMI(env) ((env)->r[58])
+#define CPU_MHI(env) ((env)->r[59])
+#define CPU_LP(env) ((env)->r[60])
+#define CPU_IMM(env) ((env)->r[62])
+#define CPU_PCL(env) ((env)->r[63])
+
+
+struct CPUARCState {
+ uint32_t r[64];
+
+ struct {
+ uint32_t Lf;
+ uint32_t Zf; /* zero */
+ uint32_t Nf; /* negative */
+ uint32_t Cf; /* carry */
+ uint32_t Vf; /* overflow */
+ uint32_t Uf;
+
+ uint32_t DEf;
+ uint32_t AEf;
+ uint32_t A2f; /* interrupt 1 is active */
+ uint32_t A1f; /* interrupt 2 is active */
+ uint32_t E2f; /* interrupt 1 mask */
+ uint32_t E1f; /* interrupt 2 mask */
+ uint32_t Hf; /* halt */
+ } stat, stat_l1, stat_l2, stat_er;
+
+ struct {
+ uint32_t S2;
+ uint32_t S1;
+ uint32_t CS;
+ } macmod;
+
+ uint32_t intvec;
+
+ uint32_t eret;
+ uint32_t erbta;
+ uint32_t ecr;
+ uint32_t efa;
+ uint32_t bta;
+ uint32_t bta_l1;
+ uint32_t bta_l2;
+
+ uint32_t pc; /* program counter */
+ uint32_t lps; /* loops start */
+ uint32_t lpe; /* loops end */
+
+ struct {
+ uint32_t LD; /* load pending bit */
+ uint32_t SH; /* self halt */
+ uint32_t BH; /* breakpoint halt */
+ uint32_t UB; /* user mode break enabled */
+ uint32_t ZZ; /* sleep mode */
+ uint32_t RA; /* reset applied */
+ uint32_t IS; /* single instruction step */
+ uint32_t FH; /* force halt */
+ uint32_t SS; /* single step */
+ } debug;
+ uint32_t features;
+ bool stopped;
+
+ /* Those resources are used only in QEMU core */
+ CPU_COMMON
+};
+
+static inline int arc_feature(CPUARCState *env, int feature)
+{
+ return (env->features & (1U << feature)) != 0;
+}
+
+static inline void arc_set_feature(CPUARCState *env, int feature)
+{
+ env->features |= (1U << feature);
+}
+
+#define cpu_list arc_cpu_list
+#define cpu_signal_handler cpu_arc_signal_handler
+
+#include "exec/cpu-all.h"
+#include "cpu-qom.h"
+
+static inline int cpu_mmu_index(CPUARCState *env, bool ifetch)
+{
+ return 0;
+}
+
+void arc_translate_init(void);
+
+ARCCPU *cpu_arc_init(const char *cpu_model);
+
+#define cpu_init(cpu_model) CPU(cpu_arc_init(cpu_model))
+
+void arc_cpu_list(FILE *f, fprintf_function cpu_fprintf);
+int cpu_arc_exec(CPUState *cpu);
+int cpu_arc_signal_handler(int host_signum, void *pinfo, void *puc);
+int arc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
+ int mmu_idx);
+int arc_cpu_memory_rw_debug(CPUState *cs, vaddr address, uint8_t *buf,
+ int len, bool is_write);
+
+static inline void cpu_get_tb_cpu_state(CPUARCState *env, target_ulong *pc,
+ target_ulong *cs_base, uint32_t *pflags)
+{
+ *pc = env->pc;
+ *cs_base = 0;
+ *pflags = 0;
+}
+
+static inline int cpu_interrupts_enabled(CPUARCState *env1)
+{
+ return 0;
+}
+
+#include "exec/exec-all.h"
+
+#endif /* !defined (CPU_ARC_H) */
diff --git a/target-arc/decode.c b/target-arc/decode.c
new file mode 100644
index 0000000..1bb859a
--- /dev/null
+++ b/target-arc/decode.c
@@ -0,0 +1,7 @@
+#include "translate.h"
+
+int arc_decode(DisasCtxt *ctx)
+{
+ return BS_STOP;
+}
+
diff --git a/target-arc/gdbstub.c b/target-arc/gdbstub.c
new file mode 100644
index 0000000..69b8cdc
--- /dev/null
+++ b/target-arc/gdbstub.c
@@ -0,0 +1,138 @@
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+static uint32_t arc_cpu_get_stat32(CPUState *cs)
+{
+ ARCCPU *cpu = ARC_CPU(cs);
+ CPUARCState *env = &cpu->env;
+ uint32_t val = 0;
+
+ val |= env->stat.Hf ? BIT(0) : 0;
+ val |= env->stat.E1f ? BIT(1) : 0;
+ val |= env->stat.E2f ? BIT(2) : 0;
+ val |= env->stat.A1f ? BIT(3) : 0;
+ val |= env->stat.A2f ? BIT(4) : 0;
+ val |= env->stat.AEf ? BIT(5) : 0;
+ val |= env->stat.DEf ? BIT(6) : 0;
+ val |= env->stat.Uf ? BIT(7) : 0;
+ val |= env->stat.Vf ? BIT(8) : 0;
+ val |= env->stat.Cf ? BIT(9) : 0;
+ val |= env->stat.Nf ? BIT(10) : 0;
+ val |= env->stat.Zf ? BIT(11) : 0;
+ val |= env->stat.Lf ? BIT(12) : 0;
+
+ return val;
+}
+
+static void arc_cpu_set_stat32(CPUState *cs, uint32_t val)
+{
+ ARCCPU *cpu = ARC_CPU(cs);
+ CPUARCState *env = &cpu->env;
+
+ env->stat.Hf = 0 != (val & BIT(0));
+ env->stat.E1f = 0 != (val & BIT(1));
+ env->stat.E2f = 0 != (val & BIT(2));
+ env->stat.A1f = 0 != (val & BIT(3));
+ env->stat.A2f = 0 != (val & BIT(4));
+ env->stat.AEf = 0 != (val & BIT(5));
+ env->stat.DEf = 0 != (val & BIT(6));
+ env->stat.Uf = 0 != (val & BIT(7));
+ env->stat.Vf = 0 != (val & BIT(8));
+ env->stat.Cf = 0 != (val & BIT(9));
+ env->stat.Nf = 0 != (val & BIT(10));
+ env->stat.Zf = 0 != (val & BIT(11));
+ env->stat.Lf = 0 != (val & BIT(12));
+}
+
+int arc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ ARCCPU *cpu = ARC_CPU(cs);
+ CPUARCState *env = &cpu->env;
+ uint32_t val = 0;
+
+ switch (n) {
+ case 0x00 ... 0x3f: {
+ val = env->r[n];
+ break;
+ }
+
+ case 0x40: {
+ val = env->pc;
+ break;
+ }
+
+ case 0x41: {
+ val = env->lps;
+ break;
+ }
+
+ case 0x42: {
+ val = env->lpe;
+ break;
+ }
+
+ case 0x43: {
+ val = arc_cpu_get_stat32(cs);
+ break;
+ }
+ }
+
+ return gdb_get_reg32(mem_buf, val);
+}
+
+int arc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ ARCCPU *cpu = ARC_CPU(cs);
+ CPUARCState *env = &cpu->env;
+ uint16_t val = ldl_p(mem_buf);
+
+ switch (n) {
+ case 0x00 ... 0x3f: {
+ env->r[n] = val;
+ break;
+ }
+
+ case 0x40: {
+ env->pc = val;
+ break;
+ }
+
+ case 0x41: {
+ env->lps = val;
+ break;
+ }
+
+ case 0x42: {
+ env->lpe = val;
+ break;
+ }
+
+ case 0x43: {
+ arc_cpu_set_stat32(cs, val);
+ break;
+ }
+ }
+
+ return 4;
+}
diff --git a/target-arc/helper.c b/target-arc/helper.c
new file mode 100644
index 0000000..ace3b5d
--- /dev/null
+++ b/target-arc/helper.c
@@ -0,0 +1,74 @@
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+
+#include "cpu.h"
+#include "hw/irq.h"
+#include "include/hw/sysbus.h"
+#include "include/sysemu/sysemu.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+
+void tlb_fill(CPUState *cs, target_ulong vaddr, MMUAccessType access_type,
+ int mmu_idx, uintptr_t retaddr)
+{
+ target_ulong page_size = TARGET_PAGE_SIZE;
+ int prot = 0;
+ MemTxAttrs attrs = {};
+ uint32_t paddr;
+
+ vaddr &= TARGET_PAGE_MASK;
+ paddr = PHYS_BASE_RAM + vaddr - VIRT_BASE_RAM;
+ prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+
+ tlb_set_page_with_attrs(cs, vaddr, paddr, attrs, prot, mmu_idx, page_size);
+}
+
+void arc_cpu_do_interrupt(CPUState *cs)
+{
+ cs->exception_index = -1;
+}
+
+bool arc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+ return false;
+}
+
+int arc_cpu_memory_rw_debug(CPUState *cs, vaddr addr, uint8_t *buf,
+ int len, bool is_write)
+{
+ return cpu_memory_rw_debug(cs, addr, buf, len, is_write);
+}
+
+hwaddr arc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
+{
+ return addr; /* I assume 1:1 address correspondance */
+}
+
+void helper_debug(CPUARCState *env)
+{
+ CPUState *cs = CPU(arc_env_get_cpu(env));
+
+ cs->exception_index = EXCP_DEBUG;
+ cpu_loop_exit(cs);
+}
diff --git a/target-arc/helper.h b/target-arc/helper.h
new file mode 100644
index 0000000..69c91fb
--- /dev/null
+++ b/target-arc/helper.h
@@ -0,0 +1,21 @@
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+DEF_HELPER_1(debug, void, env)
diff --git a/target-arc/machine.c b/target-arc/machine.c
new file mode 100644
index 0000000..b008942
--- /dev/null
+++ b/target-arc/machine.c
@@ -0,0 +1,35 @@
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "cpu.h"
+#include "hw/boards.h"
+#include "machine.h"
+#include "migration/qemu-file.h"
+
+const VMStateDescription vms_arc_cpu = {
+ .name = "cpu",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_END_OF_LIST()
+ }
+};
diff --git a/target-arc/machine.h b/target-arc/machine.h
new file mode 100644
index 0000000..6190f3d
--- /dev/null
+++ b/target-arc/machine.h
@@ -0,0 +1,21 @@
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+extern const VMStateDescription vmstate_arc_cpu;
diff --git a/target-arc/translate.c b/target-arc/translate.c
new file mode 100644
index 0000000..fc09403
--- /dev/null
+++ b/target-arc/translate.c
@@ -0,0 +1,424 @@
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "translate.h"
+
+TCGv_env cpu_env;
+
+TCGv cpu_gp; /* Global Pointer */
+TCGv cpu_fp; /* Frame Pointer */
+TCGv cpu_sp; /* Stack Pointer */
+TCGv cpu_ilink1; /* Level 1 interrupt link register */
+TCGv cpu_ilink2; /* Level 2 interrupt link register */
+TCGv cpu_blink; /* Branch link register */
+TCGv cpu_limm; /* Long immediate data indicator */
+TCGv cpu_pcl; /* Program Counter [31:2], read-only,
+ 32-bit aligned address. */
+
+TCGv cpu_mlo; /* Multiply low 32 bits, read only */
+TCGv cpu_mmi; /* Multiply middle 32 bits, read only */
+TCGv cpu_mhi; /* Multiply high 32 bits, read only */
+
+TCGv cpu_S1f;
+TCGv cpu_S2f;
+TCGv cpu_CSf;
+
+TCGv cpu_Lf;
+TCGv cpu_Zf;
+TCGv cpu_Nf;
+TCGv cpu_Cf;
+TCGv cpu_Vf;
+TCGv cpu_Uf;
+
+TCGv cpu_DEf;
+TCGv cpu_AEf;
+TCGv cpu_A2f;
+TCGv cpu_A1f;
+TCGv cpu_E2f;
+TCGv cpu_E1f;
+TCGv cpu_Hf;
+
+TCGv cpu_l1_Lf;
+TCGv cpu_l1_Zf;
+TCGv cpu_l1_Nf;
+TCGv cpu_l1_Cf;
+TCGv cpu_l1_Vf;
+TCGv cpu_l1_Uf;
+
+TCGv cpu_l1_DEf;
+TCGv cpu_l1_AEf;
+TCGv cpu_l1_A2f;
+TCGv cpu_l1_A1f;
+TCGv cpu_l1_E2f;
+TCGv cpu_l1_E1f;
+TCGv cpu_l1_Hf;
+
+TCGv cpu_l2_Lf;
+TCGv cpu_l2_Zf;
+TCGv cpu_l2_Nf;
+TCGv cpu_l2_Cf;
+TCGv cpu_l2_Vf;
+TCGv cpu_l2_Uf;
+
+TCGv cpu_l2_DEf;
+TCGv cpu_l2_AEf;
+TCGv cpu_l2_A2f;
+TCGv cpu_l2_A1f;
+TCGv cpu_l2_E2f;
+TCGv cpu_l2_E1f;
+TCGv cpu_l2_Hf;
+
+TCGv cpu_er_Lf;
+TCGv cpu_er_Zf;
+TCGv cpu_er_Nf;
+TCGv cpu_er_Cf;
+TCGv cpu_er_Vf;
+TCGv cpu_er_Uf;
+
+TCGv cpu_er_DEf;
+TCGv cpu_er_AEf;
+TCGv cpu_er_A2f;
+TCGv cpu_er_A1f;
+TCGv cpu_er_E2f;
+TCGv cpu_er_E1f;
+TCGv cpu_er_Hf;
+
+TCGv cpu_eret;
+TCGv cpu_erbta;
+TCGv cpu_ecr;
+TCGv cpu_efa;
+
+TCGv cpu_bta;
+TCGv cpu_bta_l1;
+TCGv cpu_bta_l2;
+
+TCGv cpu_pc;
+TCGv cpu_lpc;
+TCGv cpu_lps;
+TCGv cpu_lpe;
+
+TCGv cpu_r[64];
+
+TCGv cpu_intvec;
+
+TCGv cpu_debug_LD;
+TCGv cpu_debug_SH;
+TCGv cpu_debug_BH;
+TCGv cpu_debug_UB;
+TCGv cpu_debug_ZZ;
+TCGv cpu_debug_RA;
+TCGv cpu_debug_IS;
+TCGv cpu_debug_FH;
+TCGv cpu_debug_SS;
+
+#include "exec/gen-icount.h"
+#define REG(x) (cpu_r[x])
+
+void arc_translate_init(void)
+{
+ int i;
+ static int init_not_done = 1;
+
+ if (init_not_done == 0) {
+ return;
+ }
+#define ARC_REG_OFFS(x) offsetof(CPUARCState, x)
+#define NEW_ARC_REG(x) \
+ tcg_global_mem_new_i32(cpu_env, offsetof(CPUARCState, x), #x)
+
+ cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+
+ cpu_S1f = NEW_ARC_REG(macmod.S1);
+ cpu_S2f = NEW_ARC_REG(macmod.S2);
+ cpu_CSf = NEW_ARC_REG(macmod.CS);
+
+ cpu_Zf = NEW_ARC_REG(stat.Zf);
+ cpu_Lf = NEW_ARC_REG(stat.Lf);
+ cpu_Nf = NEW_ARC_REG(stat.Nf);
+ cpu_Cf = NEW_ARC_REG(stat.Cf);
+ cpu_Vf = NEW_ARC_REG(stat.Vf);
+ cpu_Uf = NEW_ARC_REG(stat.Uf);
+ cpu_DEf = NEW_ARC_REG(stat.DEf);
+ cpu_AEf = NEW_ARC_REG(stat.AEf);
+ cpu_A2f = NEW_ARC_REG(stat.A2f);
+ cpu_A1f = NEW_ARC_REG(stat.A1f);
+ cpu_E2f = NEW_ARC_REG(stat.E2f);
+ cpu_E1f = NEW_ARC_REG(stat.E1f);
+ cpu_Hf = NEW_ARC_REG(stat.Hf);
+
+ cpu_l1_Zf = NEW_ARC_REG(stat_l1.Zf);
+ cpu_l1_Lf = NEW_ARC_REG(stat_l1.Lf);
+ cpu_l1_Nf = NEW_ARC_REG(stat_l1.Nf);
+ cpu_l1_Cf = NEW_ARC_REG(stat_l1.Cf);
+ cpu_l1_Vf = NEW_ARC_REG(stat_l1.Vf);
+ cpu_l1_Uf = NEW_ARC_REG(stat_l1.Uf);
+ cpu_l1_DEf = NEW_ARC_REG(stat_l1.DEf);
+ cpu_l1_AEf = NEW_ARC_REG(stat_l1.AEf);
+ cpu_l1_A2f = NEW_ARC_REG(stat_l1.A2f);
+ cpu_l1_A1f = NEW_ARC_REG(stat_l1.A1f);
+ cpu_l1_E2f = NEW_ARC_REG(stat_l1.E2f);
+ cpu_l1_E1f = NEW_ARC_REG(stat_l1.E1f);
+ cpu_l1_Hf = NEW_ARC_REG(stat_l1.Hf);
+
+ cpu_l2_Zf = NEW_ARC_REG(stat_l2.Zf);
+ cpu_l2_Lf = NEW_ARC_REG(stat_l2.Lf);
+ cpu_l2_Nf = NEW_ARC_REG(stat_l2.Nf);
+ cpu_l2_Cf = NEW_ARC_REG(stat_l2.Cf);
+ cpu_l2_Vf = NEW_ARC_REG(stat_l2.Vf);
+ cpu_l2_Uf = NEW_ARC_REG(stat_l2.Uf);
+ cpu_l2_DEf = NEW_ARC_REG(stat_l2.DEf);
+ cpu_l2_AEf = NEW_ARC_REG(stat_l2.AEf);
+ cpu_l2_A2f = NEW_ARC_REG(stat_l2.A2f);
+ cpu_l2_A1f = NEW_ARC_REG(stat_l2.A1f);
+ cpu_l2_E2f = NEW_ARC_REG(stat_l2.E2f);
+ cpu_l2_E1f = NEW_ARC_REG(stat_l2.E1f);
+ cpu_l2_Hf = NEW_ARC_REG(stat_l2.Hf);
+
+ cpu_er_Zf = NEW_ARC_REG(stat_er.Zf);
+ cpu_er_Lf = NEW_ARC_REG(stat_er.Lf);
+ cpu_er_Nf = NEW_ARC_REG(stat_er.Nf);
+ cpu_er_Cf = NEW_ARC_REG(stat_er.Cf);
+ cpu_er_Vf = NEW_ARC_REG(stat_er.Vf);
+ cpu_er_Uf = NEW_ARC_REG(stat_er.Uf);
+ cpu_er_DEf = NEW_ARC_REG(stat_er.DEf);
+ cpu_er_AEf = NEW_ARC_REG(stat_er.AEf);
+ cpu_er_A2f = NEW_ARC_REG(stat_er.A2f);
+ cpu_er_A1f = NEW_ARC_REG(stat_er.A1f);
+ cpu_er_E2f = NEW_ARC_REG(stat_er.E2f);
+ cpu_er_E1f = NEW_ARC_REG(stat_er.E1f);
+ cpu_er_Hf = NEW_ARC_REG(stat_er.Hf);
+
+ cpu_eret = NEW_ARC_REG(eret);
+ cpu_erbta = NEW_ARC_REG(erbta);
+ cpu_ecr = NEW_ARC_REG(ecr);
+ cpu_efa = NEW_ARC_REG(efa);
+ cpu_bta = NEW_ARC_REG(bta);
+ cpu_lps = NEW_ARC_REG(lps);
+ cpu_lpe = NEW_ARC_REG(lpe);
+ cpu_pc = NEW_ARC_REG(pc);
+
+ cpu_bta_l1 = NEW_ARC_REG(bta_l1);
+ cpu_bta_l2 = NEW_ARC_REG(bta_l2);
+
+ cpu_intvec = NEW_ARC_REG(intvec);
+
+ for (i = 0; i < 64; i++) {
+ char name[16];
+
+ sprintf(name, "r[%d]", i);
+
+ cpu_r[i] = tcg_global_mem_new_i32(cpu_env, ARC_REG_OFFS(r[i]), name);
+ }
+
+ cpu_gp = cpu_r[26];
+ cpu_fp = cpu_r[27];
+ cpu_sp = cpu_r[28];
+ cpu_ilink1 = cpu_r[29];
+ cpu_ilink2 = cpu_r[30];
+ cpu_blink = cpu_r[31];
+ cpu_mlo = cpu_r[57];
+ cpu_mmi = cpu_r[58];
+ cpu_mhi = cpu_r[59];
+ cpu_lpc = cpu_r[60];
+ cpu_limm = cpu_r[62];
+ cpu_pcl = cpu_r[63];
+
+ cpu_debug_LD = NEW_ARC_REG(debug.LD);
+ cpu_debug_SH = NEW_ARC_REG(debug.SH);
+ cpu_debug_BH = NEW_ARC_REG(debug.BH);
+ cpu_debug_UB = NEW_ARC_REG(debug.UB);
+ cpu_debug_ZZ = NEW_ARC_REG(debug.ZZ);
+ cpu_debug_RA = NEW_ARC_REG(debug.RA);
+ cpu_debug_IS = NEW_ARC_REG(debug.IS);
+ cpu_debug_FH = NEW_ARC_REG(debug.FH);
+ cpu_debug_SS = NEW_ARC_REG(debug.SS);
+
+ init_not_done = 0;
+}
+
+int arc_gen_INVALID(DisasCtxt *ctx)
+{
+ printf("invalid inst @:%08x\n", ctx->cpc);
+ return BS_NONE;
+}
+
+void gen_intermediate_code(CPUARCState *env, struct TranslationBlock *tb)
+{
+ ARCCPU *cpu = arc_env_get_cpu(env);
+ CPUState *cs = CPU(cpu);
+ DisasCtxt ctx;
+ target_ulong pc_start;
+ int num_insns;
+ int max_insns;
+
+ pc_start = tb->pc;
+ ctx.tb = tb;
+ ctx.memidx = 0;
+ ctx.bstate = BS_NONE;
+ ctx.singlestep = cs->singlestep_enabled;
+ num_insns = 0;
+ max_insns = tb->cflags & CF_COUNT_MASK;
+
+ if (max_insns == 0) {
+ max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
+
+ gen_tb_start(tb);
+
+ ctx.zero = tcg_const_local_i32(0);
+ ctx.one = tcg_const_local_i32(1);
+ ctx.msb32 = tcg_const_local_i32(0x80000000);
+ ctx.msb16 = tcg_const_local_i32(0x00008000);
+ ctx.smax16 = tcg_const_local_i32(0x7fffffff);
+ ctx.smax32 = tcg_const_local_i32(0x00007fff);
+ ctx.smax5 = tcg_const_local_i32(0x0000001f);
+ ctx.smin5 = tcg_const_local_i32(0xffffffe1);
+
+ ctx.npc = pc_start;
+ ctx.env = env;
+ ctx.ds = 0;
+ do {
+ ctx.cpc = ctx.npc;
+ ctx.pcl = ctx.cpc & 0xfffffffc;
+
+ tcg_gen_insn_start(ctx.cpc);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, ctx.cpc, BP_ANY))) {
+ tcg_gen_movi_i32(cpu_pc, ctx.cpc);
+ gen_helper_debug(cpu_env);
+ ctx.bstate = BS_EXCP;
+ goto done_generating;
+ }
+
+ ctx.bstate = arc_decode(&ctx);
+
+ if (ctx.npc == env->lpe) {
+ TCGLabel *label_next = gen_new_label();
+
+ tcg_gen_subi_tl(cpu_lpc, cpu_lpc, 1);
+
+ tcg_gen_movi_tl(cpu_pc, ctx.npc);
+
+ tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_lpc, 0, label_next);
+
+ tcg_gen_mov_tl(cpu_pc, cpu_lps);
+
+gen_set_label(label_next);
+
+ ctx.bstate = BS_BRANCH;
+ }
+
+ if (num_insns >= max_insns) {
+ break; /* max translated instructions limit reached */
+ }
+ if (ctx.singlestep) {
+ break; /* single step */
+ }
+ if ((ctx.cpc & (TARGET_PAGE_SIZE - 1)) == 0) {
+ break; /* page boundary */
+ }
+
+ } while (ctx.bstate == BS_NONE && !tcg_op_buf_full());
+
+ if (tb->cflags & CF_LAST_IO) {
+ gen_io_end();
+ }
+
+ if (ctx.singlestep) {
+ if (ctx.bstate == BS_STOP || ctx.bstate == BS_NONE) {
+ tcg_gen_movi_tl(cpu_pc, ctx.npc);
+ tcg_gen_movi_tl(cpu_pcl, ctx.npc & 0xfffffffc);
+ }
+ gen_helper_debug(cpu_env);
+ tcg_gen_exit_tb(0);
+ } else {
+ switch (ctx.bstate) {
+ case BS_STOP:
+ case BS_NONE:
+ gen_goto_tb(env, &ctx, 0, ctx.npc);
+ break;
+ case BS_BRANCH:
+ case BS_BRANCH_DS:
+ case BS_EXCP:
+ tcg_gen_exit_tb(0);
+ break;
+ default:
+ break;
+ }
+ }
+
+done_generating:
+ tcg_temp_free_i32(ctx.one);
+ tcg_temp_free_i32(ctx.zero);
+ tcg_temp_free_i32(ctx.msb32);
+ tcg_temp_free_i32(ctx.msb16);
+ tcg_temp_free_i32(ctx.smax16);
+ tcg_temp_free_i32(ctx.smax32);
+ tcg_temp_free_i32(ctx.smax5);
+ tcg_temp_free_i32(ctx.smin5);
+
+ gen_tb_end(tb, num_insns);
+
+ tb->size = (ctx.npc - pc_start);
+ tb->icount = num_insns;
+}
+
+void restore_state_to_opc(CPUARCState *env, TranslationBlock *tb,
+ target_ulong *data)
+{
+ env->pc = data[0];
+}
+
+void arc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
+ int flags)
+{
+ ARCCPU *cpu = ARC_CPU(cs);
+ CPUARCState *env = &cpu->env;
+ int i;
+
+ cpu_fprintf(f, "STATUS: [ %c %c %c %c %c %c %s %s %s %s %s %s %c]\n",
+ env->stat.Lf ? 'L' : '-',
+ env->stat.Zf ? 'Z' : '-',
+ env->stat.Nf ? 'N' : '-',
+ env->stat.Cf ? 'C' : '-',
+ env->stat.Vf ? 'V' : '-',
+ env->stat.Uf ? 'U' : '-',
+ env->stat.DEf ? "DE" : "--",
+ env->stat.AEf ? "AE" : "--",
+ env->stat.A2f ? "A2" : "--",
+ env->stat.A1f ? "A1" : "--",
+ env->stat.E2f ? "E2" : "--",
+ env->stat.E1f ? "E1" : "--",
+ env->stat.Hf ? 'H' : '-'
+ );
+
+ cpu_fprintf(f, "\n");
+ for (i = 0; i < ARRAY_SIZE(env->r); i++) {
+ cpu_fprintf(f, "R[%02d]: %02x ", i, env->r[i]);
+
+ if ((i % 8) == 7) {
+ cpu_fprintf(f, "\n");
+ }
+ }
+}
diff --git a/target-arc/translate.h b/target-arc/translate.h
new file mode 100644
index 0000000..470df47
--- /dev/null
+++ b/target-arc/translate.h
@@ -0,0 +1,223 @@
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#ifndef ARC_TRANSLATE_H_
+#define ARC_TRANSLATE_H_
+
+
+#include "qemu/osdep.h"
+
+#include "tcg/tcg.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "disas/disas.h"
+#include "tcg-op.h"
+#include "exec/cpu_ldst.h"
+
+#include "exec/helper-proto.h"
+#include "exec/helper-gen.h"
+#include "exec/log.h"
+
+extern TCGv_env cpu_env;
+
+extern TCGv cpu_gp;
+extern TCGv cpu_fp;
+extern TCGv cpu_sp;
+extern TCGv cpu_ilink1;
+extern TCGv cpu_ilink2;
+extern TCGv cpu_blink;
+extern TCGv cpu_pcl;
+extern TCGv cpu_limm;
+
+extern TCGv cpu_mlo;
+extern TCGv cpu_mmi;
+extern TCGv cpu_mhi;
+
+extern TCGv cpu_S1f;
+extern TCGv cpu_S2f;
+extern TCGv cpu_CSf;
+
+extern TCGv cpu_Lf;
+extern TCGv cpu_Zf;
+extern TCGv cpu_Nf;
+extern TCGv cpu_Cf;
+extern TCGv cpu_Vf;
+extern TCGv cpu_Uf;
+
+extern TCGv cpu_DEf;
+extern TCGv cpu_AEf;
+extern TCGv cpu_A2f;
+extern TCGv cpu_A1f;
+extern TCGv cpu_E2f;
+extern TCGv cpu_E1f;
+extern TCGv cpu_Hf;
+
+extern TCGv cpu_l1_Lf;
+extern TCGv cpu_l1_Zf;
+extern TCGv cpu_l1_Nf;
+extern TCGv cpu_l1_Cf;
+extern TCGv cpu_l1_Vf;
+extern TCGv cpu_l1_Uf;
+
+extern TCGv cpu_l1_DEf;
+extern TCGv cpu_l1_AEf;
+extern TCGv cpu_l1_A2f;
+extern TCGv cpu_l1_A1f;
+extern TCGv cpu_l1_E2f;
+extern TCGv cpu_l1_E1f;
+extern TCGv cpu_l1_Hf;
+
+extern TCGv cpu_l2_Lf;
+extern TCGv cpu_l2_Zf;
+extern TCGv cpu_l2_Nf;
+extern TCGv cpu_l2_Cf;
+extern TCGv cpu_l2_Vf;
+extern TCGv cpu_l2_Uf;
+
+extern TCGv cpu_l2_DEf;
+extern TCGv cpu_l2_AEf;
+extern TCGv cpu_l2_A2f;
+extern TCGv cpu_l2_A1f;
+extern TCGv cpu_l2_E2f;
+extern TCGv cpu_l2_E1f;
+extern TCGv cpu_l2_Hf;
+
+extern TCGv cpu_er_Lf;
+extern TCGv cpu_er_Zf;
+extern TCGv cpu_er_Nf;
+extern TCGv cpu_er_Cf;
+extern TCGv cpu_er_Vf;
+extern TCGv cpu_er_Uf;
+
+extern TCGv cpu_er_DEf;
+extern TCGv cpu_er_AEf;
+extern TCGv cpu_er_A2f;
+extern TCGv cpu_er_A1f;
+extern TCGv cpu_er_E2f;
+extern TCGv cpu_er_E1f;
+extern TCGv cpu_er_Hf;
+
+extern TCGv cpu_eret;
+extern TCGv cpu_erbta;
+extern TCGv cpu_ecr;
+extern TCGv cpu_efa;
+
+extern TCGv cpu_pc;
+extern TCGv cpu_lpc;
+extern TCGv cpu_lps;
+extern TCGv cpu_lpe;
+
+extern TCGv cpu_bta;
+extern TCGv cpu_bta_l1;
+extern TCGv cpu_bta_l2;
+
+extern TCGv cpu_r[64];
+
+extern TCGv cpu_intvec;
+
+extern TCGv cpu_debug_LD;
+extern TCGv cpu_debug_SH;
+extern TCGv cpu_debug_BH;
+extern TCGv cpu_debug_UB;
+extern TCGv cpu_debug_ZZ;
+extern TCGv cpu_debug_RA;
+extern TCGv cpu_debug_IS;
+extern TCGv cpu_debug_FH;
+extern TCGv cpu_debug_SS;
+
+enum {
+ BS_NONE = 0x00, /* Nothing special (none of the below */
+ BS_STOP = 0x01, /* We want to stop translation for any reason */
+ BS_BRANCH = 0x02, /* A branch condition is reached */
+ BS_BRANCH_DS = 0x03, /* A branch condition is reached */
+ BS_EXCP = 0x04, /* An exception condition is reached */
+ BS_BREAK = 0x05,
+};
+
+#define BS_DELAYED_SLOT(n) ((n) ? BS_BRANCH_DS : BS_BRANCH)
+
+typedef struct DisasCtxt DisasCtxt;
+
+/*This is the state at translation time. */
+typedef struct options_s {
+ bool di; /* direct data cache bypass */
+ bool f; /* set flags */
+ bool d; /* delay slot mode*/
+ bool x; /* sign extend */
+ bool limm;
+ uint8_t aa; /* address writeback */
+ uint8_t zz; /* data size */
+} options_t;
+
+struct DisasCtxt {
+ struct TranslationBlock *tb;
+
+ uint32_t cpc; /* current pc */
+ uint32_t npc; /* next pc */
+ uint32_t dpc; /* next next pc */
+ uint32_t pcl;
+ uint32_t lpe;
+
+ unsigned ds; /* we are within ds*/
+
+ TCGv one; /* 0x00000000 */
+ TCGv zero; /* 0x00000000 */
+ TCGv msb32; /* 0x80000000 */
+ TCGv msb16; /* 0x00008000 */
+ TCGv smax16; /* 0x7fffffff */
+ TCGv smax32; /* 0x00007fff */
+ TCGv smax5; /* 0x0000001f */
+ TCGv smin5; /* 0xffffffe1 */
+
+ options_t opt;
+
+ int memidx;
+ int bstate;
+ int singlestep;
+
+ CPUARCState *env;
+};
+
+int arc_decode(DisasCtxt *ctx);
+int arc_gen_INVALID(DisasCtxt *ctx);
+
+static inline void gen_goto_tb(CPUARCState *env, DisasCtxt *ctx,
+ int n, target_ulong dest)
+{
+ TranslationBlock *tb;
+
+ tb = ctx->tb;
+
+ if (ctx->singlestep == 0) {
+ tcg_gen_goto_tb(n);
+ tcg_gen_movi_tl(cpu_pc, dest & 0xfffffffe); /* TODO ??? */
+ tcg_gen_movi_tl(cpu_pcl, dest & 0xfffffffc);
+ tcg_gen_exit_tb((uintptr_t)tb + n);
+ } else {
+ tcg_gen_movi_tl(cpu_pc, dest & 0xfffffffe); /* TODO ??? */
+ tcg_gen_movi_tl(cpu_pcl, dest & 0xfffffffc);
+ gen_helper_debug(cpu_env);
+ tcg_gen_exit_tb(0);
+ }
+}
+
+
+#endif
+
--
2.4.9 (Apple Git-60)
next prev parent reply other threads:[~2016-09-08 22:32 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
2016-09-08 22:31 ` Michael Rolnik [this message]
2016-09-20 23:31 ` [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit Richard Henderson
2016-09-26 1:22 ` Max Filippov
2016-09-27 18:46 ` Richard Henderson
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 02/29] target-arc: ADC, ADD, ADD1, ADD2, ADD3 Michael Rolnik
2016-09-20 20:51 ` Richard Henderson
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 03/29] target-arc: SUB, SUB1, SUB2, SUB3, SBC, RSUB, CMP Michael Rolnik
2016-09-20 23:32 ` Richard Henderson
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 04/29] target-arc: AND, OR, XOR, BIC, TST Michael Rolnik
2016-09-20 23:35 ` Richard Henderson
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 05/29] target-arc: ASL(m), ASR(m), LSR(m), ROR(m) Michael Rolnik
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 06/29] target-arc: EX, LD, ST, SYNC, PREFETCH Michael Rolnik
2016-09-20 23:46 ` Richard Henderson
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 07/29] target-arc: MAX, MIN Michael Rolnik
2016-09-20 23:48 ` Richard Henderson
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 08/29] target-arc: MOV, EXT, SEX, SWAP Michael Rolnik
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 09/29] target-arc: NEG, ABS, NOT Michael Rolnik
2016-09-20 23:55 ` Richard Henderson
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 10/29] target-arc: POP, PUSH Michael Rolnik
2016-09-20 23:57 ` Richard Henderson
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 11/29] target-arc: BCLR, BMSK, BSET, BTST, BXOR Michael Rolnik
2016-09-21 0:07 ` Richard Henderson
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 12/29] target-arc: RLC, RRC Michael Rolnik
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 13/29] target-arc: NORM, NORMW Michael Rolnik
2016-09-21 0:14 ` Richard Henderson
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 14/29] target-arc: MPY, MPYH, MPYHU, MPYU Michael Rolnik
2016-09-21 0:17 ` Richard Henderson
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 15/29] target-arc: MUL64, MULU64, DIVAW Michael Rolnik
2016-09-21 0:20 ` Richard Henderson
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 16/29] target-arc: BBIT0, BBIT1, BR Michael Rolnik
2016-09-21 0:25 ` Richard Henderson
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 17/29] target-arc: B, BL Michael Rolnik
2016-09-21 0:28 ` Richard Henderson
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 18/29] target-arc: J, JL Michael Rolnik
2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 19/29] target-arc: LR, SR Michael Rolnik
2016-09-21 0:31 ` Richard Henderson
2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 20/29] target-arc: ADDS, ADDSDW, SUBS, SUBSDW Michael Rolnik
2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 21/29] target-arc: ABSS, ABSSW, NEGS, NEGSW, RND16, SAT16 Michael Rolnik
2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 22/29] target-arc: ASLS, ASRS Michael Rolnik
2016-09-21 0:36 ` Richard Henderson
2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 23/29] target-arc: FLAG, BRK, SLEEP Michael Rolnik
2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 24/29] target-arc: NOP, UNIMP Michael Rolnik
2016-09-21 0:39 ` Richard Henderson
2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 25/29] target-arc: TRAP, SWI Michael Rolnik
2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 26/29] target-arc: RTIE Michael Rolnik
2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 27/29] target-arc: LP Michael Rolnik
2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 28/29] target-arc: decode Michael Rolnik
2016-09-21 0:49 ` Richard Henderson
2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 29/29] target-arc: sample board Michael Rolnik
2016-09-16 15:01 ` [PATCH RFC v1 00/29] ARC cores Alexey Brodkin
2016-09-16 15:01 ` [Qemu-devel] " Alexey Brodkin
2016-09-17 18:26 ` Michael Rolnik
2016-09-19 12:40 ` Alexey Brodkin
2016-09-19 12:55 ` Igor Guryanov
2016-09-19 13:45 ` Michael Rolnik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1473373930-31547-2-git-send-email-mrolnik@gmail.com \
--to=mrolnik@gmail.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.