qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit


From: Michael Rolnik
Subject: [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit
Date: Fri, 9 Sep 2016 01:31:42 +0300

Signed-off-by: Michael Rolnik <address@hidden>
---
 .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 <address@hidden>
+S: Maintained
+F: target-arc/
+
 ARM
 M: Peter Maydell <address@hidden>
 L: address@hidden
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 via email to

[Prev in Thread] Current Thread [Next in Thread]