All of lore.kernel.org
 help / color / mirror / Atom feed
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)

  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.