All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH RFC v1 00/29] ARC cores
@ 2016-09-08 22:31 Michael Rolnik
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit Michael Rolnik
                   ` (29 more replies)
  0 siblings, 30 replies; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

This series of patches adds ARC target to QEMU. It indends to support
    - ARCtangent-A5 processor
    - ARC 600 processor
    - ARC 700 processor

All instructions except ASLS are implemented. Not fully tested yet.
However I was able to execute correctly recursive fibonacci calculation.
Reset vector is assumed to be some hardcoded value which worked for my test.
I am planning to get FreeRTOS for ARC, once I get it, I will able to verify
and complete interrupt support.



Michael Rolnik (29):
  target-arc: initial commit
  target-arc: ADC, ADD, ADD1, ADD2, ADD3
  target-arc: SUB, SUB1, SUB2, SUB3, SBC, RSUB, CMP
  target-arc: AND, OR, XOR, BIC, TST
  target-arc: ASL(m), ASR(m), LSR(m), ROR(m)
  target-arc: EX, LD, ST, SYNC, PREFETCH
  target-arc: MAX, MIN
  target-arc: MOV, EXT, SEX, SWAP
  target-arc: NEG, ABS, NOT
  target-arc: POP, PUSH
  target-arc: BCLR, BMSK, BSET, BTST, BXOR
  target-arc: RLC, RRC
  target-arc: NORM, NORMW
  target-arc: MPY, MPYH, MPYHU, MPYU
  target-arc: MUL64, MULU64, DIVAW
  target-arc: BBIT0, BBIT1, BR
  target-arc: B, BL
  target-arc: J, JL
  target-arc: LR, SR
  target-arc: ADDS, ADDSDW, SUBS, SUBSDW
  target-arc: ABSS, ABSSW, NEGS, NEGSW, RND16, SAT16
  target-arc: ASLS, ASRS
  target-arc: FLAG, BRK, SLEEP
  target-arc: NOP, UNIMP
  target-arc: TRAP, SWI
  target-arc: RTIE
  target-arc: LP
  target-arc: decode
  target-arc: sample board

 .gitignore                      |    2 +
 MAINTAINERS                     |    6 +
 arch_init.c                     |    2 +
 configure                       |    5 +
 default-configs/arc-softmmu.mak |    0
 hw/arc/Makefile.objs            |   21 +
 hw/arc/sample.c                 |   80 ++
 include/sysemu/arch_init.h      |    1 +
 target-arc/Makefile.objs        |   28 +
 target-arc/cpu-qom.h            |   84 ++
 target-arc/cpu.c                |  269 ++++
 target-arc/cpu.h                |  174 +++
 target-arc/decode.c             | 2212 ++++++++++++++++++++++++++++++
 target-arc/gdbstub.c            |  138 ++
 target-arc/helper.c             |   74 +
 target-arc/helper.h             |   29 +
 target-arc/machine.c            |   35 +
 target-arc/machine.h            |   21 +
 target-arc/op_helper.c          |  443 ++++++
 target-arc/translate-inst.c     | 2855 +++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h     |  175 +++
 target-arc/translate.c          |  424 ++++++
 target-arc/translate.h          |  223 +++
 23 files changed, 7301 insertions(+)
 create mode 100644 default-configs/arc-softmmu.mak
 create mode 100644 hw/arc/Makefile.objs
 create mode 100644 hw/arc/sample.c
 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/op_helper.c
 create mode 100644 target-arc/translate-inst.c
 create mode 100644 target-arc/translate-inst.h
 create mode 100644 target-arc/translate.c
 create mode 100644 target-arc/translate.h

-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
@ 2016-09-08 22:31 ` Michael Rolnik
  2016-09-20 23:31   ` Richard Henderson
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 02/29] target-arc: ADC, ADD, ADD1, ADD2, ADD3 Michael Rolnik
                   ` (28 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

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)

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

* [Qemu-devel] [PATCH RFC v1 02/29] target-arc: ADC, ADD, ADD1, ADD2, ADD3
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit Michael Rolnik
@ 2016-09-08 22:31 ` 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
                   ` (27 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/Makefile.objs    |   1 +
 target-arc/translate-inst.c | 170 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  30 ++++++++
 3 files changed, 201 insertions(+)
 create mode 100644 target-arc/translate-inst.c
 create mode 100644 target-arc/translate-inst.h

diff --git a/target-arc/Makefile.objs b/target-arc/Makefile.objs
index a3475dd..6fdb000 100644
--- a/target-arc/Makefile.objs
+++ b/target-arc/Makefile.objs
@@ -21,6 +21,7 @@
 obj-y   += translate.o
 obj-y   += helper.o
 obj-y   += cpu.o
+obj-y   += translate-inst.o
 obj-y   += gdbstub.o
 obj-y   += decode.o
 obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
new file mode 100644
index 0000000..50119bf
--- /dev/null
+++ b/target-arc/translate-inst.c
@@ -0,0 +1,170 @@
+/*
+ *  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 dest 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>
+ */
+
+/*
+    see http://me.bios.io/images/d/dd/ARCompactISA_ProgrammersReference.pdf
+*/
+
+#include "translate.h"
+#include "qemu/bitops.h"
+#include "tcg/tcg.h"
+#include "translate-inst.h"
+
+static void gen_add_Cf(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+    TCGv t3 = tcg_temp_new_i32();
+
+    tcg_gen_and_tl(t1, src1, src2); /*  t1 = src1 & src2                    */
+    tcg_gen_andc_tl(t2, src1, dest);/*  t2 = src1 & ~dest                   */
+    tcg_gen_andc_tl(t3, src2, dest);/*  t3 = src2 & ~dest                   */
+    tcg_gen_or_tl(t1, t1, t2);      /*  t1 = t1 | t2 | t3                   */
+    tcg_gen_or_tl(t1, t1, t3);
+
+    tcg_gen_shri_tl(cpu_Cf, t1, 31);/*  Cf = t1(31)                         */
+
+    tcg_temp_free_i32(t3);
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+static void gen_add_Vf(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+
+    /*
+
+    src1 & src2 & ~dest | ~src1 & ~src2 & dest = (src1 ^ dest) & ~(src1 ^ src2)
+
+    */
+    tcg_gen_xor_tl(t1, src1, dest); /*  t1 = src1 ^ dest                    */
+    tcg_gen_xor_tl(t2, src1, src2); /*  t2 = src1 ^ src2                    */
+    tcg_gen_andc_tl(t1, t1, t2);    /*  t1 = (src1 ^ src2) & ~(src1 ^ src2) */
+
+    tcg_gen_shri_tl(cpu_Vf, t1, 31);/*  Vf = t1(31)                         */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+/*
+    ADC
+*/
+int arc_gen_ADC(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_add_tl(rslt, src1, src2);
+    tcg_gen_add_tl(rslt, rslt, cpu_Cf);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        gen_add_Cf(rslt, src1, src2);
+        gen_add_Vf(rslt, src1, src2);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    ADD
+*/
+int arc_gen_ADD(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_add_tl(rslt, src1, src2);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        gen_add_Cf(rslt, src1, src2);
+        gen_add_Vf(rslt, src1, src2);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    ADD1
+*/
+int arc_gen_ADD1(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t0, src2, 1);
+    arc_gen_ADD(ctx, dest, src1, t0);
+
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    ADD2
+*/
+int arc_gen_ADD2(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t0, src2, 2);
+    arc_gen_ADD(ctx, dest, src1, t0);
+
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    ADD3
+*/
+int arc_gen_ADD3(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t0, src2, 3);
+    arc_gen_ADD(ctx, dest, src1, t0);
+
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
new file mode 100644
index 0000000..08e23c7
--- /dev/null
+++ b/target-arc/translate-inst.h
@@ -0,0 +1,30 @@
+/*
+ *  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 dest 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"
+#include "qemu/bitops.h"
+#include "tcg/tcg.h"
+
+int arc_gen_ADC(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ADD(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ADD1(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ADD2(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ADD3(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 03/29] target-arc: SUB, SUB1, SUB2, SUB3, SBC, RSUB, CMP
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit Michael Rolnik
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 02/29] target-arc: ADC, ADD, ADD1, ADD2, ADD3 Michael Rolnik
@ 2016-09-08 22:31 ` 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
                   ` (26 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 165 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   8 +++
 2 files changed, 173 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 50119bf..7389e5c 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -66,6 +66,44 @@ static void gen_add_Vf(TCGv dest, TCGv src1, TCGv src2)
     tcg_temp_free_i32(t1);
 }
 
+static void gen_sub_Cf(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+    TCGv t3 = tcg_temp_new_i32();
+
+    tcg_gen_not_tl(t1, src1);       /*  t1 = ~src1                          */
+    tcg_gen_and_tl(t2, t1, src2);   /*  t2 = ~src1 & src2                   */
+    tcg_gen_or_tl(t3, t1, src2);    /*  t3 = (~src1 | src2) & dest          */
+    tcg_gen_and_tl(t3, t3, dest);
+    tcg_gen_or_tl(t2, t2, t3);      /*  t2 = ~src1 & src2
+                                           | ~src1 & dest
+                                           | dest & src2                    */
+    tcg_gen_shri_tl(cpu_Cf, t2, 31);/*  Cf = t2(31)                         */
+
+    tcg_temp_free_i32(t3);
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+static void gen_sub_Vf(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+
+    /*
+        t1 = src1 & ~src2 & ~dest
+           | ~src1 & src2 & dest
+           = (src1 ^ dest) & (src1 ^ dest)*/
+    tcg_gen_xor_tl(t1, src1, dest);
+    tcg_gen_xor_tl(t2, src1, src2);
+    tcg_gen_and_tl(t1, t1, t2);
+    tcg_gen_shri_tl(cpu_Vf, t1, 31);/*  Vf = t1(31) */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
 /*
     ADC
 */
@@ -168,3 +206,130 @@ int arc_gen_ADD3(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    SUB
+*/
+int arc_gen_SUB(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_sub_tl(rslt, src1, src2);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        gen_sub_Cf(rslt, src1, src2);
+        gen_sub_Vf(rslt, src1, src2);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    SBC
+*/
+int arc_gen_SBC(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_sub_tl(rslt, src1, src2);
+    tcg_gen_sub_tl(rslt, rslt, cpu_Cf);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        gen_sub_Cf(rslt, src1, src2);
+        gen_sub_Vf(rslt, src1, src2);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+/*
+    SUB1
+*/
+int arc_gen_SUB1(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t0, src2, 1);
+    arc_gen_SUB(ctx, dest, src1, t0);
+
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    SUB2
+*/
+int arc_gen_SUB2(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t0, src2, 2);
+    arc_gen_SUB(ctx, dest, src1, t0);
+
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    SUB3
+*/
+int arc_gen_SUB3(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t0, src2, 3);
+    arc_gen_SUB(ctx, dest, src1, t0);
+
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    RSUB
+*/
+int arc_gen_RSUB(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    return arc_gen_SUB(ctx, dest, src2, src1);
+}
+
+/*
+    CMP
+*/
+int arc_gen_CMP(DisasCtxt *ctx, TCGv src1, TCGv src2)
+{
+    TCGv rslt = tcg_temp_new_i32();
+
+    tcg_gen_sub_tl(rslt, src1, src2);
+
+    tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+    tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    gen_sub_Cf(rslt, src1, src2);
+    gen_sub_Vf(rslt, src1, src2);
+
+    tcg_temp_free_i32(rslt);
+
+    return  BS_NONE;
+}
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 08e23c7..40ed8a0 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -28,3 +28,11 @@ int arc_gen_ADD1(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_ADD2(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_ADD3(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 
+int arc_gen_SUB(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_SUB1(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_SUB2(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_SUB3(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_SBC(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_RSUB(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_CMP(DisasCtxt *c, TCGv src1, TCGv src2);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 04/29] target-arc: AND, OR, XOR, BIC, TST
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (2 preceding siblings ...)
  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-08 22:31 ` 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
                   ` (25 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 119 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   6 +++
 2 files changed, 125 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 7389e5c..5192f41 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -333,3 +333,122 @@ int arc_gen_CMP(DisasCtxt *ctx, TCGv src1, TCGv src2)
 
     return  BS_NONE;
 }
+
+/*
+    TST
+*/
+int arc_gen_TST(DisasCtxt *ctx, TCGv src1, TCGv src2)
+{
+    TCGv temp = tcg_temp_new_i32();
+
+    ctx->opt.f = 1;
+    arc_gen_AND(ctx, temp, src1, src2);
+    tcg_temp_free_i32(temp);
+
+    return BS_NONE;
+}
+
+/*
+    AND
+*/
+int arc_gen_AND(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_and_tl(rslt, src1, src2);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    OR
+*/
+int arc_gen_OR(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_or_tl(rslt, src1, src2);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    BIC
+*/
+int arc_gen_BIC(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andc_tl(rslt, src1, src2);  /*  rslt = src1 & ~src2             */
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    XOR
+*/
+int arc_gen_XOR(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_xor_tl(rslt, src1, src2);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 40ed8a0..40ce696 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -36,3 +36,9 @@ int arc_gen_SBC(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_RSUB(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_CMP(DisasCtxt *c, TCGv src1, TCGv src2);
 
+int arc_gen_AND(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_OR(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_BIC(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_XOR(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_TST(DisasCtxt *c, TCGv src1, TCGv src2);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 05/29] target-arc: ASL(m), ASR(m), LSR(m), ROR(m)
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (3 preceding siblings ...)
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 04/29] target-arc: AND, OR, XOR, BIC, TST Michael Rolnik
@ 2016-09-08 22:31 ` Michael Rolnik
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 06/29] target-arc: EX, LD, ST, SYNC, PREFETCH Michael Rolnik
                   ` (24 subsequent siblings)
  29 siblings, 0 replies; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 212 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   9 ++
 2 files changed, 221 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 5192f41..2032823 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -452,3 +452,215 @@ int arc_gen_XOR(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    ASL
+*/
+int arc_gen_ASL(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    arc_gen_ADD(ctx, dest, src1, src1);
+
+    return  BS_NONE;
+}
+
+/*
+    ASLm
+*/
+int arc_gen_ASLm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+    TCGv t0 = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(t0, src2, 31);
+    tcg_gen_shl_tl(rslt, src1, t0);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_rotl_tl(cpu_Cf, src1, t0);
+        tcg_gen_andi_tl(cpu_Cf, cpu_Cf, 1);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    ASR
+*/
+int arc_gen_ASR(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_sari_tl(rslt, src1, 1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_andi_tl(cpu_Cf, src1, 1);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    ASRm
+*/
+int arc_gen_ASRm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+    TCGv t0 = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(t0, src2, 31);
+    tcg_gen_sar_tl(rslt, src1, t0);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_rotr_tl(cpu_Cf, src1, src2);
+        tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    LSR
+*/
+int arc_gen_LSR(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_shri_tl(rslt, src1, 1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_movi_tl(cpu_Nf, 0);
+        tcg_gen_andi_tl(cpu_Cf, src1, 1);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    LSRm
+*/
+int arc_gen_LSRm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+    TCGv t0 = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(t0, src2, 31);
+    tcg_gen_shr_tl(rslt, src1, t0);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_rotr_tl(cpu_Cf, src1, t0);
+        tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    ROR
+*/
+int arc_gen_ROR(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_rotri_tl(rslt, src1, 1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_mov_tl(cpu_Cf, cpu_Nf);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    RORm
+*/
+int arc_gen_RORm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(rslt, src2, 0x1f);
+    tcg_gen_rotr_tl(rslt, src1, rslt);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_mov_tl(cpu_Cf, cpu_Nf);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 40ce696..325f708 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -42,3 +42,12 @@ int arc_gen_BIC(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_XOR(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_TST(DisasCtxt *c, TCGv src1, TCGv src2);
 
+int arc_gen_ASL(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_ASLm(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ASR(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_ASRm(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_LSR(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_LSRm(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ROR(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_RORm(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 06/29] target-arc: EX, LD, ST, SYNC, PREFETCH
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (4 preceding siblings ...)
  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 ` 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
                   ` (23 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 230 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  10 ++
 2 files changed, 240 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 2032823..ac13c86 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -664,3 +664,233 @@ int arc_gen_RORm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    EX
+*/
+int arc_gen_EX(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv temp = tcg_temp_new_i32();
+
+    tcg_gen_mov_tl(temp, dest);
+
+    tcg_gen_qemu_ld_tl(dest, src1, ctx->memidx, MO_UL);
+    tcg_gen_qemu_st_tl(temp, src1, ctx->memidx, MO_UL);
+
+    tcg_temp_free_i32(temp);
+
+    return BS_NONE;
+}
+
+/*
+    LD
+*/
+int arc_gen_LD(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv addr = tcg_temp_new_i32();
+
+    /*  address             */
+    switch (ctx->opt.aa) {
+        case 0x00: {
+            tcg_gen_add_tl(addr, src1, src2);
+        } break;
+
+        case 0x01: {
+            tcg_gen_add_tl(addr, src1, src2);
+        } break;
+
+        case 0x02: {
+            tcg_gen_mov_tl(addr, src1);
+        } break;
+
+        case 0x03: {
+            if (ctx->opt.zz == 0x02) {
+                tcg_gen_shli_tl(addr, src2, 1);
+            } else if (ctx->opt.zz == 0x00) {
+                tcg_gen_shli_tl(addr, src2, 2);
+            } else {
+                assert(!"bad format");
+            }
+
+            tcg_gen_add_tl(addr, src1, addr);
+        } break;
+    }
+
+    /*  memory read         */
+    switch (ctx->opt.zz) {
+        case 0x00: {
+            tcg_gen_qemu_ld_tl(dest, addr, ctx->memidx, MO_UL);
+        } break;
+
+        case 0x01: {
+            if (ctx->opt.x) {
+                tcg_gen_qemu_ld_tl(dest, addr, ctx->memidx, MO_SB);
+            } else {
+                tcg_gen_qemu_ld_tl(dest, addr, ctx->memidx, MO_UB);
+            }
+        } break;
+
+        case 0x02: {
+            if (ctx->opt.x) {
+                tcg_gen_qemu_ld_tl(dest, addr, ctx->memidx, MO_SW);
+            } else {
+                tcg_gen_qemu_ld_tl(dest, addr, ctx->memidx, MO_UW);
+            }
+        } break;
+
+        case 0x03: {
+            assert(!"reserved");
+        } break;
+    }
+
+    /*  address write back      */
+    if (ctx->opt.aa == 0x01 || ctx->opt.aa == 0x02) {
+        tcg_gen_add_tl(src1, src1, src2);
+    }
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+    LDB
+*/
+int arc_gen_LDB(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+
+    ctx->opt.zz = 1;    /*  byte                        */
+    ctx->opt.x = 0;     /*  no sign extension           */
+    ctx->opt.aa = 0;    /*  no address write back       */
+    ctx->opt.di = 0;    /*  cached data memory access   */
+
+    return arc_gen_LD(ctx, dest, src1, src2);
+}
+
+/*
+    LDW
+*/
+int arc_gen_LDW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+
+    ctx->opt.zz = 2;    /*  word                        */
+    ctx->opt.x = 0;     /*  no sign extension           */
+    ctx->opt.aa = 0;    /*  no address write back       */
+    ctx->opt.di = 0;    /*  cached data memory access   */
+
+    return arc_gen_LD(ctx, dest, src1, src2);
+}
+
+/*
+    ST
+*/
+int arc_gen_ST(DisasCtxt *ctx, TCGv src1, TCGv src2, TCGv src3)
+{
+    TCGv addr = tcg_temp_new_i32();
+
+    /*  address         */
+    switch (ctx->opt.aa) {
+        case 0x00: {
+            tcg_gen_add_tl(addr, src2, src3);
+        } break;
+
+        case 0x01: {
+            tcg_gen_add_tl(addr, src2, src3);
+        } break;
+
+        case 0x02: {
+            tcg_gen_mov_tl(addr, src2);
+        } break;
+
+        case 0x03: {
+            if (ctx->opt.zz == 0x02) {
+                tcg_gen_shli_tl(addr, src3, 1);
+            } else if (ctx->opt.zz == 0x00) {
+                tcg_gen_shli_tl(addr, src3, 2);
+            } else {
+                assert(!"bad format");
+            }
+
+            tcg_gen_add_tl(addr, src2, addr);
+        } break;
+    }
+
+    /*  write               */
+    switch (ctx->opt.zz) {
+        case 0x00: {
+            tcg_gen_qemu_st_tl(src1, addr, ctx->memidx, MO_UL);
+        } break;
+
+        case 0x01: {
+            tcg_gen_qemu_st_tl(src1, addr, ctx->memidx, MO_UB);
+        } break;
+
+        case 0x02: {
+            tcg_gen_qemu_st_tl(src1, addr, ctx->memidx, MO_UW);
+        } break;
+
+        case 0x03: {
+            assert(!"reserved");
+        } break;
+    }
+
+    /*  address write back  */
+    if (ctx->opt.aa == 0x01 || ctx->opt.aa == 0x02) {
+        tcg_gen_add_tl(src2, src2, src3);
+    }
+
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
+/*
+    STB
+*/
+int arc_gen_STB(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+
+    ctx->opt.zz = 1;    /*  byte                        */
+    ctx->opt.x = 0;     /*  no sign extension           */
+    ctx->opt.aa = 0;    /*  no address write back       */
+    ctx->opt.di = 0;    /*  cached data memory access   */
+
+    return arc_gen_ST(ctx, dest, src1, src2);
+}
+
+/*
+    STW
+*/
+int arc_gen_STW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+
+    ctx->opt.zz = 2;    /*  word                        */
+    ctx->opt.x = 0;     /*  no sign extension           */
+    ctx->opt.aa = 0;    /*  no address write back       */
+    ctx->opt.di = 0;    /*  cached data memory access   */
+
+    return arc_gen_ST(ctx, dest, src1, src2);
+}
+
+/*
+    PREFETCH
+*/
+int arc_gen_PREFETCH(DisasCtxt *ctx, TCGv src1, TCGv src2)
+{
+    TCGv temp = tcg_temp_new_i32();
+
+    arc_gen_LD(ctx, temp, src1, src2);
+
+    tcg_temp_free_i32(temp);
+
+    return BS_NONE;
+}
+
+/*
+    SYNC
+*/
+int arc_gen_SYNC(DisasCtxt *ctx)
+{
+    /*  nothing to do*/
+
+    return BS_NONE;
+}
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 325f708..0038645 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -51,3 +51,13 @@ int arc_gen_LSRm(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_ROR(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_RORm(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 
+int arc_gen_EX(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_LD(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_LDW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_LDB(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ST(DisasCtxt *c, TCGv src1, TCGv src2, TCGv src3);
+int arc_gen_STW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_STB(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_PREFETCH(DisasCtxt *c, TCGv src1, TCGv src2);
+int arc_gen_SYNC(DisasCtxt *c);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 07/29] target-arc: MAX, MIN
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (5 preceding siblings ...)
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 06/29] target-arc: EX, LD, ST, SYNC, PREFETCH Michael Rolnik
@ 2016-09-08 22:31 ` 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
                   ` (22 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 29 +++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  3 +++
 2 files changed, 32 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index ac13c86..5404f35 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -894,3 +894,32 @@ int arc_gen_SYNC(DisasCtxt *ctx)
 
     return BS_NONE;
 }
+
+/*
+    MAX
+*/
+int arc_gen_MAX(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    if (ctx->opt.f) {
+        arc_gen_CMP(ctx, src1, src2);
+    }
+
+    tcg_gen_movcond_tl(TCG_COND_GEU, dest, src1, src2, src1, src2);
+
+    return  BS_NONE;
+}
+
+/*
+    MIN
+*/
+int arc_gen_MIN(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    if (ctx->opt.f) {
+        arc_gen_CMP(ctx, src1, src2);
+    }
+
+    tcg_gen_movcond_tl(TCG_COND_GEU, dest, src1, src2, src2, src1);
+
+    return  BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 0038645..0dc7f4c 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -61,3 +61,6 @@ int arc_gen_STB(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_PREFETCH(DisasCtxt *c, TCGv src1, TCGv src2);
 int arc_gen_SYNC(DisasCtxt *c);
 
+int arc_gen_MAX(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_MIN(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 08/29] target-arc: MOV, EXT, SEX, SWAP
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (6 preceding siblings ...)
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 07/29] target-arc: MAX, MIN Michael Rolnik
@ 2016-09-08 22:31 ` Michael Rolnik
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 09/29] target-arc: NEG, ABS, NOT Michael Rolnik
                   ` (21 subsequent siblings)
  29 siblings, 0 replies; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 156 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   7 ++
 2 files changed, 163 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 5404f35..4d756a9 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -923,3 +923,159 @@ int arc_gen_MIN(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    MOV
+*/
+int arc_gen_MOV(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_mov_tl(rslt, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    EXTB
+*/
+int arc_gen_EXTB(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_ext8u_tl(rslt, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_movi_tl(cpu_Nf, 0);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return BS_NONE;
+}
+
+/*
+    EXTW
+*/
+int arc_gen_EXTW(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_ext16u_tl(rslt, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_movi_tl(cpu_Nf, 0);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return BS_NONE;
+}
+
+/*
+    SEXB
+*/
+int arc_gen_SEXB(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_ext8s_tl(rslt, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    SEXW
+*/
+int arc_gen_SEXW(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_ext16s_tl(rslt, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    SWAP
+*/
+int arc_gen_SWAP(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_rotli_tl(rslt, src1, 16);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 0dc7f4c..916d94e 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -64,3 +64,10 @@ int arc_gen_SYNC(DisasCtxt *c);
 int arc_gen_MAX(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_MIN(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 
+int arc_gen_MOV(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_EXTB(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_EXTW(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_SEXB(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_SEXW(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_SWAP(DisasCtxt *c, TCGv dest, TCGv src1);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 09/29] target-arc: NEG, ABS, NOT
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (7 preceding siblings ...)
  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 ` 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
                   ` (20 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  4 +++
 2 files changed, 72 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 4d756a9..7f7e951 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -1079,3 +1079,71 @@ int arc_gen_SWAP(DisasCtxt *ctx, TCGv dest, TCGv src1)
     return  BS_NONE;
 }
 
+/*
+    ABS
+*/
+int arc_gen_ABS(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+    TCGv_i32 t0 = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_neg_i32(t0, src1);
+    tcg_gen_movcond_tl(TCG_COND_GEU, rslt, src1, ctx->msb32, src1, t0);
+
+    tcg_temp_free_i32(t0);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Cf, src1, 31);
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Nf, src1, ctx->msb32);
+        tcg_gen_mov_tl(cpu_Vf, cpu_Nf);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    NEG
+*/
+int arc_gen_NEG(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    arc_gen_SUB(ctx, dest, ctx->zero, src1);
+
+    return  BS_NONE;
+}
+
+/*
+    NOT
+*/
+int arc_gen_NOT(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_not_tl(rslt, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 916d94e..36ce19b 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -71,3 +71,7 @@ int arc_gen_SEXB(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_SEXW(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_SWAP(DisasCtxt *c, TCGv dest, TCGv src1);
 
+int arc_gen_NEG(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_ABS(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_NOT(DisasCtxt *c, TCGv dest, TCGv src1);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 10/29] target-arc: POP, PUSH
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (8 preceding siblings ...)
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 09/29] target-arc: NEG, ABS, NOT Michael Rolnik
@ 2016-09-08 22:31 ` 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
                   ` (19 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 22 ++++++++++++++++++++++
 target-arc/translate-inst.h |  3 +++
 2 files changed, 25 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 7f7e951..2a579f8 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -1147,3 +1147,25 @@ int arc_gen_NOT(DisasCtxt *ctx, TCGv dest, TCGv src1)
     return  BS_NONE;
 }
 
+/*
+    POP
+*/
+int arc_gen_POP(DisasCtxt *ctx, TCGv src1)
+{
+    tcg_gen_qemu_ld_tl(src1, cpu_sp, ctx->memidx, MO_UL);
+    tcg_gen_addi_tl(cpu_sp, cpu_sp, 4);
+
+    return BS_NONE;
+}
+
+/*
+    PUSH
+*/
+int arc_gen_PUSH(DisasCtxt *ctx, TCGv src1)
+{
+    tcg_gen_subi_tl(cpu_sp, cpu_sp, 4);
+    tcg_gen_qemu_st_tl(src1, cpu_sp, ctx->memidx, MO_UL);
+
+    return BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 36ce19b..d088a43 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -75,3 +75,6 @@ int arc_gen_NEG(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_ABS(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_NOT(DisasCtxt *c, TCGv dest, TCGv src1);
 
+int arc_gen_POP(DisasCtxt *c, TCGv src1);
+int arc_gen_PUSH(DisasCtxt *c, TCGv src1);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 11/29] target-arc: BCLR, BMSK, BSET, BTST, BXOR
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (9 preceding siblings ...)
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 10/29] target-arc: POP, PUSH Michael Rolnik
@ 2016-09-08 22:31 ` 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
                   ` (18 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 139 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   6 ++
 2 files changed, 145 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 2a579f8..91b7037 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -1169,3 +1169,142 @@ int arc_gen_PUSH(DisasCtxt *ctx, TCGv src1)
     return BS_NONE;
 }
 
+/*
+    BCLR
+*/
+int arc_gen_BCLR(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(rslt, src2, 0x3f);
+    tcg_gen_shr_tl(rslt, ctx->one, rslt);
+    tcg_gen_andc_tl(rslt, src1, rslt);  /*  rslt = src1 & ~(1 << src2)      */
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    BMSK
+*/
+int arc_gen_BMSK(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+    TCGv mask = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(mask, src2, 0x3f);
+    tcg_gen_add_tl(mask, mask, ctx->one);
+    tcg_gen_shr_tl(mask, ctx->one, mask);
+    tcg_gen_sub_tl(mask, mask, ctx->one);
+
+    tcg_gen_and_tl(rslt, src1, mask);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    tcg_temp_free_i32(mask);
+
+    return  BS_NONE;
+}
+
+/*
+    BSET
+*/
+int arc_gen_BSET(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(rslt, src2, 0x3f);
+    tcg_gen_shr_tl(rslt, ctx->one, rslt);
+    tcg_gen_or_tl(rslt, src1, rslt);    /*  rslt = src1 | (1 << src2)   */
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    BTST
+*/
+int arc_gen_BTST(DisasCtxt *ctx, TCGv src1, TCGv src2)
+{
+    TCGv rslt = tcg_temp_new_i32();
+
+    tcg_gen_andi_tl(rslt, src2, 0x3f);
+    tcg_gen_shr_tl(rslt, ctx->one, rslt);
+    tcg_gen_and_tl(rslt, src1, rslt);       /*  rslt = src1 & (1 << src2)   */
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    tcg_temp_free_i32(rslt);
+
+    return  BS_NONE;
+}
+
+/*
+    BXOR
+*/
+int arc_gen_BXOR(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(rslt, src2, 0x3f);
+    tcg_gen_shr_tl(rslt, ctx->one, rslt);
+    tcg_gen_xor_tl(rslt, src1, rslt);       /*  rslt = src1 ^ (1 << src2)   */
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index d088a43..88cae1c 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -78,3 +78,9 @@ int arc_gen_NOT(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_POP(DisasCtxt *c, TCGv src1);
 int arc_gen_PUSH(DisasCtxt *c, TCGv src1);
 
+int arc_gen_BCLR(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_BMSK(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_BSET(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_BTST(DisasCtxt *c, TCGv src1, TCGv src2);
+int arc_gen_BXOR(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 12/29] target-arc: RLC, RRC
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (10 preceding siblings ...)
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 11/29] target-arc: BCLR, BMSK, BSET, BTST, BXOR Michael Rolnik
@ 2016-09-08 22:31 ` Michael Rolnik
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 13/29] target-arc: NORM, NORMW Michael Rolnik
                   ` (17 subsequent siblings)
  29 siblings, 0 replies; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  2 ++
 2 files changed, 59 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 91b7037..a0d601e 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -1308,3 +1308,60 @@ int arc_gen_BXOR(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    RLC
+*/
+int arc_gen_RLC(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_shli_tl(rslt, src1, 1);
+    tcg_gen_or_tl(rslt, rslt, cpu_Cf);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_shri_tl(cpu_Cf, src1, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    RRC
+*/
+int arc_gen_RRC(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(rslt, src1, 0xfffffffe);
+    tcg_gen_or_tl(rslt, rslt, cpu_Cf);
+    tcg_gen_rotri_tl(rslt, rslt, 1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_andi_tl(cpu_Cf, src1, 1);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 88cae1c..5e1c52d 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -84,3 +84,5 @@ int arc_gen_BSET(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_BTST(DisasCtxt *c, TCGv src1, TCGv src2);
 int arc_gen_BXOR(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 
+int arc_gen_RRC(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_RLC(DisasCtxt *c, TCGv dest, TCGv src1);
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 13/29] target-arc: NORM, NORMW
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (11 preceding siblings ...)
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 12/29] target-arc: RLC, RRC Michael Rolnik
@ 2016-09-08 22:31 ` 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
                   ` (16 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/Makefile.objs    |  1 +
 target-arc/helper.h         |  3 ++
 target-arc/op_helper.c      | 91 +++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.c | 52 ++++++++++++++++++++++++++
 target-arc/translate-inst.h |  4 ++
 5 files changed, 151 insertions(+)
 create mode 100644 target-arc/op_helper.c

diff --git a/target-arc/Makefile.objs b/target-arc/Makefile.objs
index 6fdb000..cd3eebc 100644
--- a/target-arc/Makefile.objs
+++ b/target-arc/Makefile.objs
@@ -21,6 +21,7 @@
 obj-y   += translate.o
 obj-y   += helper.o
 obj-y   += cpu.o
+obj-y   += op_helper.o
 obj-y   += translate-inst.o
 obj-y   += gdbstub.o
 obj-y   += decode.o
diff --git a/target-arc/helper.h b/target-arc/helper.h
index 69c91fb..d480052 100644
--- a/target-arc/helper.h
+++ b/target-arc/helper.h
@@ -19,3 +19,6 @@
  */
 
 DEF_HELPER_1(debug, void, env)
+DEF_HELPER_2(norm, i32, env, i32)
+DEF_HELPER_2(normw, i32, env, i32)
+
diff --git a/target-arc/op_helper.c b/target-arc/op_helper.c
new file mode 100644
index 0000000..f372bbf
--- /dev/null
+++ b/target-arc/op_helper.c
@@ -0,0 +1,91 @@
+/*
+ * 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 "exec/helper-proto.h"
+#include "exec/ioport.h"
+
+#define AUX_ID_STATUS           0x000
+#define AUX_ID_SEMAPHORE        0x001
+#define AUX_ID_LP_START         0x002
+#define AUX_ID_LP_END           0x003
+#define AUX_ID_IDENTITY         0x004
+#define AUX_ID_DEBUG            0x005
+#define AUX_ID_PC               0x006
+
+#define AUX_ID_STATUS32         0x00A
+#define AUX_ID_STATUS32_L1      0x00B
+#define AUX_ID_STATUS32_L2      0x00C
+
+#define AUX_ID_MULHI            0x012
+
+#define AUX_ID_INT_VECTOR_BASE  0x025
+
+#define AUX_ID_INT_MACMODE      0x041
+
+#define AUX_ID_IRQ_LV12         0x043
+
+#define AUX_ID_IRQ_LEV          0x200
+#define AUX_ID_IRQ_HINT         0x201
+
+#define AUX_ID_ERET             0x400
+#define AUX_ID_ERBTA            0x401
+#define AUX_ID_ERSTATUS         0x402
+#define AUX_ID_ECR              0x403
+#define AUX_ID_EFA              0x404
+
+#define AUX_ID_ICAUSE1          0x40A
+#define AUX_ID_ICAUSE2          0x40B
+#define AUX_ID_IENABLE          0x40C
+#define AUX_ID_ITRIGGER         0x40D
+
+#define AUX_ID_BTA              0x412
+#define AUX_ID_BTA_L1           0x413
+#define AUX_ID_BTA_L2           0x414
+#define AUX_ID_IRQ_PULSE_CANSEL 0x415
+#define AUX_ID_IRQ_PENDING      0x416
+
+target_ulong helper_norm(CPUARCState *env, uint32_t src1)
+{
+    if (src1 == 0x00000000 || src1 == 0xffffffff) {
+        return 31;
+    } else {
+        if ((src1 & 0x80000000) == 0x80000000) {
+            src1 = ~src1;
+        }
+        return clz32(src1) - 1;
+    }
+}
+
+target_ulong helper_normw(CPUARCState *env, uint32_t src1)
+{
+    src1 &= 0xffff;
+
+    if (src1 == 0x0000 || src1 == 0xffff) {
+        return 15;
+    } else {
+        if ((src1 & 0x8000) == 0x8000) {
+            src1 = ~src1 & 0xffff;
+        }
+        return clz32(src1) - 17;
+    }
+}
+
diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index a0d601e..00785bf 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -1365,3 +1365,55 @@ int arc_gen_RRC(DisasCtxt *ctx, TCGv dest, TCGv src1)
     return  BS_NONE;
 }
 
+/*
+    NORMW
+*/
+int arc_gen_NORMW(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    gen_helper_normw(rslt, cpu_env, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, src1, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, src1, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return BS_NONE;
+}
+
+/*
+    NORM
+*/
+int arc_gen_NORM(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    gen_helper_norm(rslt, cpu_env, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, src1, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, src1, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 5e1c52d..811c914 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -86,3 +86,7 @@ int arc_gen_BXOR(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 
 int arc_gen_RRC(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_RLC(DisasCtxt *c, TCGv dest, TCGv src1);
+
+int arc_gen_NORMW(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_NORM(DisasCtxt *c, TCGv dest, TCGv src1);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 14/29] target-arc: MPY, MPYH, MPYHU, MPYU
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (12 preceding siblings ...)
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 13/29] target-arc: NORM, NORMW Michael Rolnik
@ 2016-09-08 22:31 ` 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
                   ` (15 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 129 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   5 ++
 2 files changed, 134 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 00785bf..92c75ac 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -1417,3 +1417,132 @@ int arc_gen_NORM(DisasCtxt *ctx, TCGv dest, TCGv src1)
     return BS_NONE;
 }
 
+/*
+    MPY
+*/
+int arc_gen_MPY(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv_i64 rslt = tcg_temp_new_i64();
+    TCGv_i64 srcA = tcg_temp_new_i64();
+    TCGv_i64 srcB = tcg_temp_new_i64();
+
+    tcg_gen_ext_i32_i64(srcA, src1);
+    tcg_gen_ext_i32_i64(srcB, src2);
+
+    tcg_gen_mul_i64(rslt, srcA, srcB);
+
+    tcg_gen_trunc_i64_tl(dest, rslt);
+
+    if (ctx->opt.f) {
+        TCGv_i64 temp = tcg_temp_new_i64();
+
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, dest, ctx->zero);
+
+        tcg_gen_trunc_i64_tl(cpu_Nf, rslt);
+        tcg_gen_shri_tl(cpu_Nf, cpu_Nf, 31);
+
+        tcg_gen_ext_i32_i64(temp, dest);
+        tcg_gen_setcond_i64(TCG_COND_NE, temp, temp, rslt);
+        tcg_gen_trunc_i64_tl(cpu_Cf, temp);
+
+        tcg_temp_free_i64(temp);
+    }
+
+    tcg_temp_free_i64(rslt);
+    tcg_temp_free_i64(srcA);
+    tcg_temp_free_i64(srcB);
+
+    return BS_NONE;
+}
+
+/*
+    MPYH
+*/
+int arc_gen_MPYH(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv_i64    rslt = tcg_temp_new_i64();
+    TCGv_i64    srcA = tcg_temp_new_i64();
+    TCGv_i64    srcB = tcg_temp_new_i64();
+
+    tcg_gen_ext_i32_i64(srcA, src1);
+    tcg_gen_ext_i32_i64(srcB, src2);
+
+    tcg_gen_mul_i64(rslt, srcA, srcB);
+
+    tcg_gen_sari_i64(rslt, rslt, 32);
+    tcg_gen_trunc_i64_tl(dest, rslt);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, dest, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, dest, 31);
+        tcg_gen_movi_tl(cpu_Vf, 0);
+    }
+
+    tcg_temp_free_i64(rslt);
+    tcg_temp_free_i64(srcA);
+    tcg_temp_free_i64(srcB);
+
+    return BS_NONE;
+}
+
+/*
+    MPYHU
+*/
+int arc_gen_MPYHU(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv_i64    rslt = tcg_temp_new_i64();
+    TCGv_i64    srcA = tcg_temp_new_i64();
+    TCGv_i64    srcB = tcg_temp_new_i64();
+
+    tcg_gen_extu_i32_i64(srcA, src1);
+    tcg_gen_extu_i32_i64(srcB, src2);
+
+    tcg_gen_mul_i64(rslt, srcA, srcB);
+
+    tcg_gen_shri_i64(rslt, rslt, 32);
+    tcg_gen_trunc_i64_tl(dest, rslt);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, dest, ctx->zero);
+        tcg_gen_movi_tl(cpu_Nf, 0);
+        tcg_gen_movi_tl(cpu_Vf, 0);
+    }
+
+    tcg_temp_free_i64(rslt);
+    tcg_temp_free_i64(srcA);
+    tcg_temp_free_i64(srcB);
+
+    return BS_NONE;
+}
+
+/*
+    MPYU
+*/
+int arc_gen_MPYU(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv_i64    rslt = tcg_temp_new_i64();
+    TCGv_i64    srcA = tcg_temp_new_i64();
+    TCGv_i64    srcB = tcg_temp_new_i64();
+
+    tcg_gen_extu_i32_i64(srcA, src1);
+    tcg_gen_extu_i32_i64(srcB, src2);
+
+    tcg_gen_mul_i64(rslt, srcA, srcB);
+
+    tcg_gen_trunc_i64_tl(dest, rslt);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, dest, ctx->zero);
+        tcg_gen_movi_tl(cpu_Nf, 0);
+        tcg_gen_shri_i64(rslt, rslt, 32);
+        tcg_gen_trunc_i64_tl(cpu_Vf, rslt);
+        tcg_gen_setcondi_tl(TCG_COND_NE, cpu_Vf, cpu_Vf, 0);
+    }
+
+    tcg_temp_free_i64(rslt);
+    tcg_temp_free_i64(srcA);
+    tcg_temp_free_i64(srcB);
+
+    return BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 811c914..084c282 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -90,3 +90,8 @@ int arc_gen_RLC(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_NORMW(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_NORM(DisasCtxt *c, TCGv dest, TCGv src1);
 
+int arc_gen_MPY(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_MPYH(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_MPYHU(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_MPYU(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 15/29] target-arc: MUL64, MULU64, DIVAW
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (13 preceding siblings ...)
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 14/29] target-arc: MPY, MPYH, MPYHU, MPYU Michael Rolnik
@ 2016-09-08 22:31 ` 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
                   ` (14 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 105 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   4 ++
 2 files changed, 109 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 92c75ac..c3795fe 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -1546,3 +1546,108 @@ int arc_gen_MPYU(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return BS_NONE;
 }
 
+/*
+    DIVAW
+*/
+int arc_gen_DIVAW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGLabel *label_else = gen_new_label();
+    TCGLabel *label_done = gen_new_label();
+    TCGv rslt = dest;
+    TCGv temp = dest;
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    /*
+        if (src1 == 0)
+            dest = 0
+        else
+        {
+            src1_temp = src1 << 1
+            if (src1_temp >= src2)
+                dest = ((src1_temp - src2) | 0x0000_0001)
+            else
+                dest = src1_temp
+        }
+    */
+
+    tcg_gen_brcondi_tl(TCG_COND_NE, src1, 0, label_else);
+
+    tcg_gen_xor_tl(rslt, rslt, rslt);
+    tcg_gen_br(label_done);
+
+gen_set_label(label_else);
+    tcg_gen_shli_tl(temp, src1, 1);
+    tcg_gen_mov_tl(rslt, temp);
+    tcg_gen_brcond_tl(TCG_COND_LT, temp, src2, label_done);
+        tcg_gen_sub_tl(rslt, temp, src2);
+        tcg_gen_ori_tl(rslt, rslt, 1);
+
+gen_set_label(label_done);
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    tcg_temp_free_i32(temp);
+
+    return  BS_NONE;
+}
+
+/*
+    MUL64
+*/
+int arc_gen_MUL64(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv_i64    rslt = tcg_temp_new_i64();
+    TCGv_i64    srcA = tcg_temp_new_i64();
+    TCGv_i64    srcB = tcg_temp_new_i64();
+
+    tcg_gen_ext_i32_i64(srcA, src1);
+    tcg_gen_ext_i32_i64(srcB, src2);
+
+    tcg_gen_mul_i64(rslt, srcA, srcB);
+
+    tcg_gen_trunc_i64_tl(cpu_mlo, rslt);
+    tcg_gen_sari_i64(rslt, rslt, 16);
+    tcg_gen_trunc_i64_tl(cpu_mmi, rslt);
+    tcg_gen_sari_i64(rslt, rslt, 16);
+    tcg_gen_trunc_i64_tl(cpu_mhi, rslt);
+
+    tcg_temp_free_i64(rslt);
+    tcg_temp_free_i64(srcA);
+    tcg_temp_free_i64(srcB);
+
+    return BS_NONE;
+}
+
+/*
+    MULU64
+*/
+int arc_gen_MULU64(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv_i64    rslt = tcg_temp_new_i64();
+    TCGv_i64    srcA = tcg_temp_new_i64();
+    TCGv_i64    srcB = tcg_temp_new_i64();
+
+    tcg_gen_extu_i32_i64(srcA, src1);
+    tcg_gen_extu_i32_i64(srcB, src2);
+
+    tcg_gen_mul_i64(rslt, srcA, srcB);
+
+    tcg_gen_trunc_i64_tl(cpu_mlo, rslt);
+    tcg_gen_shri_i64(rslt, rslt, 16);
+    tcg_gen_trunc_i64_tl(cpu_mmi, rslt);
+    tcg_gen_shri_i64(rslt, rslt, 16);
+    tcg_gen_trunc_i64_tl(cpu_mhi, rslt);
+
+    tcg_temp_free_i64(rslt);
+    tcg_temp_free_i64(srcA);
+    tcg_temp_free_i64(srcB);
+
+    return BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 084c282..e017237 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -95,3 +95,7 @@ int arc_gen_MPYH(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_MPYHU(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_MPYU(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 
+int arc_gen_DIVAW(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_MUL64(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_MULU64(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 16/29] target-arc: BBIT0, BBIT1, BR
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (14 preceding siblings ...)
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 15/29] target-arc: MUL64, MULU64, DIVAW Michael Rolnik
@ 2016-09-08 22:31 ` 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
                   ` (13 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 136 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  35 ++++++++++++
 2 files changed, 171 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index c3795fe..8288edd 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -104,6 +104,42 @@ static void gen_sub_Vf(TCGv dest, TCGv src1, TCGv src2)
     tcg_temp_free_i32(t1);
 }
 
+static void arc_gen_exec_delayslot(DisasCtxt *ctx)
+{
+    if (ctx->opt.limm == 0) {
+        uint32_t cpc = ctx->cpc;
+        uint32_t npc = ctx->npc;
+        uint32_t dpc = ctx->dpc;
+        uint32_t pcl = ctx->pcl;
+        options_t opt = ctx->opt;
+        int bstate = ctx->bstate;
+
+        ctx->cpc = ctx->npc;
+        ctx->pcl = ctx->cpc & 0xfffffffc;
+
+        ++ctx->ds;
+
+        /* TODO: check for illegal instruction sequence */
+
+        memset(&ctx->opt, 0, sizeof(ctx->opt));
+        arc_decode(ctx);
+
+        --ctx->ds;
+
+        ctx->cpc = cpc;
+        ctx->npc = npc;
+        ctx->dpc = dpc;
+        ctx->pcl = pcl;
+        ctx->opt = opt;
+        ctx->bstate = bstate;
+    }
+}
+
+static void arc_gen_kill_delayslot(DisasCtxt *ctx)
+{
+    /*  nothing to do   */
+}
+
 /*
     ADC
 */
@@ -1651,3 +1687,103 @@ int arc_gen_MULU64(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return BS_NONE;
 }
 
+/*
+    BBIT0
+*/
+int arc_gen_BBIT0(DisasCtxt *ctx, TCGv src1, TCGv src2, TCGv rd)
+{
+    TCGv mask = tcg_temp_new_i32();
+    TCGv cond = tcg_temp_new_i32();
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_jump = gen_new_label();
+
+    tcg_gen_andi_tl(mask, src2, 0x31);
+    tcg_gen_shr_tl(mask, ctx->one, mask);
+    tcg_gen_andc_tl(cond, src1, mask);      /*  cond = src1 & ~(1 << src2)   */
+
+    tcg_gen_brcond_tl(TCG_COND_EQ, cond, ctx->zero, label_jump);
+
+    tcg_gen_movi_tl(cpu_pc, ctx->npc);
+    arc_gen_exec_delayslot(ctx);
+    tcg_gen_br(label_done);
+
+gen_set_label(label_jump);
+    tcg_gen_shli_tl(cpu_pc, rd, 1);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, ctx->pcl);
+    if (ctx->opt.d == 0) {
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        arc_gen_exec_delayslot(ctx);
+    }
+
+gen_set_label(label_done);
+    tcg_temp_free_i32(cond);
+    tcg_temp_free_i32(mask);
+
+    return  BS_BRANCH_DS;
+}
+
+/*
+    BBIT1
+*/
+int arc_gen_BBIT1(DisasCtxt *ctx, TCGv src1, TCGv src2, TCGv rd)
+{
+    TCGv mask = tcg_temp_new_i32();
+    TCGv cond = tcg_temp_new_i32();
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_jump = gen_new_label();
+
+    tcg_gen_andi_tl(mask, src2, 0x31);
+    tcg_gen_shr_tl(mask, ctx->one, mask);
+    tcg_gen_and_tl(cond, src1, mask);       /*  cond = src1 & (1 << src2)   */
+
+    tcg_gen_brcond_tl(TCG_COND_EQ, cond, ctx->zero, label_jump);
+
+    tcg_gen_movi_tl(cpu_pc, ctx->dpc);
+    arc_gen_exec_delayslot(ctx);
+    tcg_gen_br(label_done);
+
+gen_set_label(label_jump);
+    tcg_gen_shli_tl(cpu_pc, rd, 1);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, ctx->pcl);
+    if (ctx->opt.d == 0) {
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        arc_gen_exec_delayslot(ctx);
+    }
+
+gen_set_label(label_done);
+    tcg_temp_free_i32(cond);
+    tcg_temp_free_i32(mask);
+
+    return  BS_BRANCH_DS;
+}
+
+/*
+    BR
+*/
+int arc_gen_BR(DisasCtxt *ctx, TCGv src1, TCGv src2, TCGv Rd, TCGCond cond)
+{
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_jump = gen_new_label();
+
+    tcg_gen_brcond_tl(cond, src1, src2, label_jump);
+
+    tcg_gen_movi_tl(cpu_pc, ctx->dpc);
+    arc_gen_exec_delayslot(ctx);
+    tcg_gen_br(label_done);
+
+gen_set_label(label_jump);
+    tcg_gen_shli_tl(cpu_pc, Rd, 1);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, ctx->pcl);
+    if (ctx->opt.d == 0) {
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        arc_gen_exec_delayslot(ctx);
+    }
+
+gen_set_label(label_done);
+
+    return  BS_BRANCH_DS;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index e017237..c78ed24 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -22,6 +22,37 @@
 #include "qemu/bitops.h"
 #include "tcg/tcg.h"
 
+typedef enum ARC_COND {
+    ARC_COND_AL      = 0x00,
+    ARC_COND_RA      = 0x00,
+    ARC_COND_EQ      = 0x01,
+    ARC_COND_Z       = 0x01,
+    ARC_COND_NE      = 0x02,
+    ARC_COND_NZ      = 0x02,
+    ARC_COND_PL      = 0x03,
+    ARC_COND_P       = 0x03,
+    ARC_COND_MI      = 0x04,
+    ARC_COND_N       = 0x04,
+    ARC_COND_CS      = 0x05,
+    ARC_COND_C       = 0x05,
+    ARC_COND_LO      = 0x05,
+    ARC_COND_CC      = 0x06,
+    ARC_COND_NC      = 0x06,
+    ARC_COND_HS      = 0x06,
+    ARC_COND_VS      = 0x07,
+    ARC_COND_V       = 0x07,
+    ARC_COND_VC      = 0x08,
+    ARC_COND_NV      = 0x08,
+    ARC_COND_GT      = 0x09,
+    ARC_COND_GE      = 0x0a,
+    ARC_COND_LT      = 0x0b,
+    ARC_COND_LE      = 0x0c,
+    ARC_COND_HI      = 0x0d,
+    ARC_COND_LS      = 0x0e,
+    ARC_COND_PNZ     = 0x0f,
+} ARC_COND;
+
+
 int arc_gen_ADC(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_ADD(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_ADD1(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
@@ -99,3 +130,7 @@ int arc_gen_DIVAW(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_MUL64(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_MULU64(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 
+int arc_gen_BBIT0(DisasCtxt *c, TCGv src1, TCGv src2, TCGv rd);
+int arc_gen_BBIT1(DisasCtxt *c, TCGv src1, TCGv src2, TCGv rd);
+int arc_gen_BR(DisasCtxt *c, TCGv src1, TCGv src2, TCGv Rd, TCGCond cond);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 17/29] target-arc: B, BL
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (15 preceding siblings ...)
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 16/29] target-arc: BBIT0, BBIT1, BR Michael Rolnik
@ 2016-09-08 22:31 ` 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
                   ` (12 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 189 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   4 +
 2 files changed, 193 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 8288edd..ed2ced0 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -140,6 +140,137 @@ static void arc_gen_kill_delayslot(DisasCtxt *ctx)
     /*  nothing to do   */
 }
 
+#define ARC_COND_IF_1(flag, label) \
+                    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_ ## flag ## f, 0, label)
+#define ARC_COND_IF_0(flag, label) \
+                    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_ ## flag ## f, 0, label)
+
+void arc_gen_jump_ifnot(DisasCtxt *ctx, ARC_COND cond, TCGLabel *label_skip)
+{
+    TCGLabel *label_cont = gen_new_label();
+
+    switch (cond) {
+        /*
+            Always
+        */
+        case    ARC_COND_AL: {
+        } break;
+
+        /*
+            Zero
+        */
+        case    ARC_COND_Z: {
+            ARC_COND_IF_0(Z, label_skip);
+        } break;
+
+        /*
+            Non-Zero
+        */
+        case    ARC_COND_NZ: {
+            ARC_COND_IF_1(Z, label_skip);
+        } break;
+
+        /*
+            Positive
+        */
+        case    ARC_COND_P: {
+            tcg_gen_brcondi_tl(TCG_COND_LT, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Negative
+        */
+        case    ARC_COND_N: {
+            tcg_gen_brcondi_tl(TCG_COND_GE, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Carry set, lower than (unsigned)
+        */
+        case    ARC_COND_C: {
+            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_Cf, 0, label_skip);
+        } break;
+
+        /*
+            Carry clear, higher or same (unsigned)
+        */
+        case    ARC_COND_CC: {
+            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_Cf, 0, label_skip);
+        } break;
+
+        /*
+            Over-flow set
+        */
+        case    ARC_COND_VS: {
+            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_Cf, 0, label_skip);
+        } break;
+
+        /*
+            Over-flow clear
+        */
+        case    ARC_COND_VC: {
+            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_Cf, 0, label_skip);
+        } break;
+
+        /*
+            Greater than (signed)
+        */
+        case    ARC_COND_GT: {
+            tcg_gen_brcondi_tl(TCG_COND_LE, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Greater than or equal to (signed)
+        */
+        case    ARC_COND_GE: {
+            tcg_gen_brcondi_tl(TCG_COND_LT, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Less than (signed)
+        */
+        case    ARC_COND_LT: {
+            tcg_gen_brcondi_tl(TCG_COND_GE, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Less than or equal to (signed)
+        */
+        case    ARC_COND_LE: {
+            tcg_gen_brcondi_tl(TCG_COND_GT, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Higher than (unsigned)
+            !C and !Z
+        */
+        case    ARC_COND_HI: {
+            ARC_COND_IF_1(C, label_skip);
+            ARC_COND_IF_1(Z, label_skip);
+        } break;
+
+        /*
+            Lower than
+            C or Z
+        */
+        case    ARC_COND_LS: {
+            ARC_COND_IF_1(C, label_cont);
+            ARC_COND_IF_0(Z, label_skip);
+        } break;
+
+        /*
+            Positive non-zero
+            !N and !Z
+        */
+        case    ARC_COND_PNZ: {
+            ARC_COND_IF_1(N, label_skip);
+            ARC_COND_IF_1(Z, label_skip);
+        } break;
+    }
+
+    gen_set_label(label_cont);
+}
+
 /*
     ADC
 */
@@ -1787,3 +1918,61 @@ gen_set_label(label_done);
     return  BS_BRANCH_DS;
 }
 
+/*
+    B
+*/
+int arc_gen_B(DisasCtxt *ctx, TCGv rd, ARC_COND cond)
+{
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_fall = gen_new_label();
+
+    arc_gen_jump_ifnot(ctx, cond, label_fall);
+
+    tcg_gen_shli_tl(cpu_pc, rd, 1);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, ctx->pcl);
+    if (ctx->opt.d == 0) {
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        arc_gen_exec_delayslot(ctx);
+    }
+    tcg_gen_br(label_done);
+
+gen_set_label(label_fall);
+    tcg_gen_movi_tl(cpu_pc, ctx->dpc);
+    arc_gen_exec_delayslot(ctx);
+
+gen_set_label(label_done);
+
+    return  BS_BRANCH_DS;
+}
+
+/*
+    BL
+*/
+int arc_gen_BL(DisasCtxt *ctx, TCGv Rd, ARC_COND cond)
+{
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_fall = gen_new_label();
+
+    arc_gen_jump_ifnot(ctx, cond, label_fall);
+
+    tcg_gen_shli_tl(cpu_pc, Rd, 2);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, ctx->pcl);
+    if (ctx->opt.d == 0) {
+        tcg_gen_movi_tl(cpu_blink, ctx->npc);
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        tcg_gen_movi_tl(cpu_blink, ctx->dpc);
+        arc_gen_exec_delayslot(ctx);
+    }
+    tcg_gen_br(label_done);
+
+gen_set_label(label_fall);
+    tcg_gen_movi_tl(cpu_pc, ctx->dpc);
+    arc_gen_exec_delayslot(ctx);
+
+gen_set_label(label_done);
+
+    return  BS_BRANCH_DS;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index c78ed24..065570e 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -134,3 +134,7 @@ int arc_gen_BBIT0(DisasCtxt *c, TCGv src1, TCGv src2, TCGv rd);
 int arc_gen_BBIT1(DisasCtxt *c, TCGv src1, TCGv src2, TCGv rd);
 int arc_gen_BR(DisasCtxt *c, TCGv src1, TCGv src2, TCGv Rd, TCGCond cond);
 
+void arc_gen_jump_ifnot(DisasCtxt *ctx, ARC_COND cond, TCGLabel *label_skip);
+int arc_gen_B(DisasCtxt *c, TCGv rd, ARC_COND cond);
+int arc_gen_BL(DisasCtxt *c, TCGv Rd, ARC_COND cond);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 18/29] target-arc: J, JL
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (16 preceding siblings ...)
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 17/29] target-arc: B, BL Michael Rolnik
@ 2016-09-08 22:31 ` Michael Rolnik
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 19/29] target-arc: LR, SR Michael Rolnik
                   ` (11 subsequent siblings)
  29 siblings, 0 replies; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 93 +++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  3 ++
 2 files changed, 96 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index ed2ced0..fd49a16 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -1976,3 +1976,96 @@ gen_set_label(label_done);
     return  BS_BRANCH_DS;
 }
 
+/*
+    J
+*/
+int arc_gen_J(DisasCtxt *ctx, TCGv src1, ARC_COND cond)
+{
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_fall = gen_new_label();
+
+    arc_gen_jump_ifnot(ctx, cond, label_fall);
+
+    if (ctx->opt.f) {
+        if (TCGV_EQUAL(src1, cpu_ilink1)) {
+            tcg_gen_mov_tl(cpu_Lf, cpu_l1_Lf);
+            tcg_gen_mov_tl(cpu_Zf, cpu_l1_Zf);
+            tcg_gen_mov_tl(cpu_Nf, cpu_l1_Nf);
+            tcg_gen_mov_tl(cpu_Cf, cpu_l1_Cf);
+            tcg_gen_mov_tl(cpu_Vf, cpu_l1_Vf);
+            tcg_gen_mov_tl(cpu_Uf, cpu_l1_Uf);
+
+            tcg_gen_mov_tl(cpu_DEf, cpu_l1_DEf);
+            tcg_gen_mov_tl(cpu_AEf, cpu_l1_AEf);
+            tcg_gen_mov_tl(cpu_A2f, cpu_l1_A2f);
+            tcg_gen_mov_tl(cpu_A1f, cpu_l1_A1f);
+            tcg_gen_mov_tl(cpu_E2f, cpu_l1_E2f);
+            tcg_gen_mov_tl(cpu_E1f, cpu_l1_E1f);
+
+            tcg_gen_mov_tl(cpu_bta, cpu_bta_l1);
+        }
+        if (TCGV_EQUAL(src1, cpu_ilink2)) {
+            tcg_gen_mov_tl(cpu_Lf, cpu_l2_Lf);
+            tcg_gen_mov_tl(cpu_Zf, cpu_l2_Zf);
+            tcg_gen_mov_tl(cpu_Nf, cpu_l2_Nf);
+            tcg_gen_mov_tl(cpu_Cf, cpu_l2_Cf);
+            tcg_gen_mov_tl(cpu_Vf, cpu_l2_Vf);
+            tcg_gen_mov_tl(cpu_Uf, cpu_l2_Uf);
+
+            tcg_gen_mov_tl(cpu_DEf, cpu_l2_DEf);
+            tcg_gen_mov_tl(cpu_AEf, cpu_l2_AEf);
+            tcg_gen_mov_tl(cpu_A2f, cpu_l2_A2f);
+            tcg_gen_mov_tl(cpu_A1f, cpu_l2_A1f);
+            tcg_gen_mov_tl(cpu_E2f, cpu_l2_E2f);
+            tcg_gen_mov_tl(cpu_E1f, cpu_l2_E1f);
+
+            tcg_gen_mov_tl(cpu_bta, cpu_bta_l2);
+        }
+    }
+
+    tcg_gen_mov_tl(cpu_pc, src1);
+    if (ctx->opt.d == 0) {
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        arc_gen_exec_delayslot(ctx);
+    }
+    tcg_gen_br(label_done);
+
+gen_set_label(label_fall);
+    tcg_gen_movi_tl(cpu_pc, ctx->dpc);
+    arc_gen_exec_delayslot(ctx);
+
+gen_set_label(label_done);
+
+    return  BS_BRANCH_DS;
+}
+
+/*
+    JL
+*/
+int arc_gen_JL(DisasCtxt *ctx, TCGv src1, ARC_COND cond)
+{
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_fall = gen_new_label();
+
+    arc_gen_jump_ifnot(ctx, cond, label_fall);
+
+    tcg_gen_mov_tl(cpu_pc, src1);
+    if (ctx->opt.d == 0) {
+        tcg_gen_movi_tl(cpu_blink, ctx->npc);
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        tcg_gen_movi_tl(cpu_blink, ctx->dpc);
+        arc_gen_exec_delayslot(ctx);
+    }
+    tcg_gen_br(label_done);
+
+gen_set_label(label_fall);
+    tcg_gen_movi_tl(cpu_pc, ctx->dpc);
+    arc_gen_exec_delayslot(ctx);
+
+gen_set_label(label_done);
+
+    return  BS_BRANCH_DS;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 065570e..7d76707 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -138,3 +138,6 @@ void arc_gen_jump_ifnot(DisasCtxt *ctx, ARC_COND cond, TCGLabel *label_skip);
 int arc_gen_B(DisasCtxt *c, TCGv rd, ARC_COND cond);
 int arc_gen_BL(DisasCtxt *c, TCGv Rd, ARC_COND cond);
 
+int arc_gen_J(DisasCtxt *c, TCGv src1, ARC_COND cond);
+int arc_gen_JL(DisasCtxt *c, TCGv src1, ARC_COND cond);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 19/29] target-arc: LR, SR
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (17 preceding siblings ...)
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 18/29] target-arc: J, JL Michael Rolnik
@ 2016-09-08 22:32 ` 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
                   ` (10 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/helper.h         |   2 +
 target-arc/op_helper.c      | 322 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.c |  26 ++++
 target-arc/translate-inst.h |   3 +
 4 files changed, 353 insertions(+)

diff --git a/target-arc/helper.h b/target-arc/helper.h
index d480052..1d84935 100644
--- a/target-arc/helper.h
+++ b/target-arc/helper.h
@@ -21,4 +21,6 @@
 DEF_HELPER_1(debug, void, env)
 DEF_HELPER_2(norm, i32, env, i32)
 DEF_HELPER_2(normw, i32, env, i32)
+DEF_HELPER_2(lr, tl, env, i32)
+DEF_HELPER_2(sr, void, i32, i32)
 
diff --git a/target-arc/op_helper.c b/target-arc/op_helper.c
index f372bbf..3cf9080 100644
--- a/target-arc/op_helper.c
+++ b/target-arc/op_helper.c
@@ -89,3 +89,325 @@ target_ulong helper_normw(CPUARCState *env, uint32_t src1)
     }
 }
 
+void helper_sr(uint32_t val, uint32_t aux)
+{
+    switch (aux) {
+        case AUX_ID_STATUS: {
+        } break;
+
+        case AUX_ID_SEMAPHORE: {
+        } break;
+
+        case AUX_ID_LP_START: {
+        } break;
+
+        case AUX_ID_LP_END: {
+        } break;
+
+        case AUX_ID_IDENTITY: {
+        } break;
+
+        case AUX_ID_DEBUG: {
+        } break;
+
+        case AUX_ID_PC: {
+        } break;
+
+        case AUX_ID_STATUS32: {
+        } break;
+
+        case AUX_ID_STATUS32_L1: {
+        } break;
+
+        case AUX_ID_STATUS32_L2: {
+        } break;
+
+        case AUX_ID_MULHI: {
+        } break;
+
+        case AUX_ID_INT_VECTOR_BASE: {
+        } break;
+
+        case AUX_ID_INT_MACMODE: {
+        } break;
+
+        case AUX_ID_IRQ_LV12: {
+        } break;
+
+        case AUX_ID_IRQ_LEV: {
+        } break;
+
+        case AUX_ID_IRQ_HINT: {
+        } break;
+
+        case AUX_ID_ERET: {
+        } break;
+
+        case AUX_ID_ERBTA: {
+        } break;
+
+        case AUX_ID_ERSTATUS: {
+        } break;
+
+        case AUX_ID_ECR: {
+        } break;
+
+        case AUX_ID_EFA: {
+        } break;
+
+        case AUX_ID_ICAUSE1: {
+        } break;
+
+        case AUX_ID_ICAUSE2: {
+        } break;
+
+        case AUX_ID_IENABLE: {
+        } break;
+
+        case AUX_ID_ITRIGGER: {
+        } break;
+
+        case AUX_ID_BTA: {
+        } break;
+
+        case AUX_ID_BTA_L1: {
+        } break;
+
+        case AUX_ID_BTA_L2: {
+        } break;
+
+        case AUX_ID_IRQ_PULSE_CANSEL: {
+        } break;
+
+        case AUX_ID_IRQ_PENDING: {
+        } break;
+
+        default: {
+            cpu_outl(aux, val);
+        }
+    }
+    cpu_outl(aux, val);
+}
+
+static target_ulong get_status(CPUARCState *env)
+{
+    target_ulong res = 0x00000000;
+
+    res |= (env->stat.Zf) ? BIT(31) : 0;
+    res |= (env->stat.Nf) ? BIT(30) : 0;
+    res |= (env->stat.Cf) ? BIT(29) : 0;
+    res |= (env->stat.Vf) ? BIT(28) : 0;
+    res |= (env->stat.E2f) ? BIT(27) : 0;
+    res |= (env->stat.E1f) ? BIT(26) : 0;
+
+    if (env->stopped) {
+        res |= BIT(25);
+    }
+
+    res |= (env->r[63] >> 2) & 0x03ffffff;
+
+    return res;
+}
+
+static target_ulong get_status32(CPUARCState *env)
+{
+    target_ulong res = 0x00000000;
+
+    res |= (env->stat.Lf) ? BIT(12) : 0;
+    res |= (env->stat.Zf) ? BIT(11) : 0;
+    res |= (env->stat.Nf) ? BIT(10) : 0;
+    res |= (env->stat.Cf) ? BIT(9)  : 0;
+    res |= (env->stat.Vf) ? BIT(8)  : 0;
+    res |= (env->stat.Uf) ? BIT(7)  : 0;
+    res |= (env->stat.DEf) ? BIT(6)  : 0;
+    res |= (env->stat.AEf) ? BIT(5)  : 0;
+    res |= (env->stat.A2f) ? BIT(4)  : 0;
+    res |= (env->stat.A1f) ? BIT(3)  : 0;
+    res |= (env->stat.E2f) ? BIT(2)  : 0;
+    res |= (env->stat.E1f) ? BIT(1)  : 0;
+
+    if (env->stopped) {
+        res |= BIT(0);
+    }
+
+    return res;
+}
+
+static target_ulong get_status32_l1(CPUARCState *env)
+{
+    target_ulong res = 0x00000000;
+
+    res |= (env->stat_l1.Lf) ? BIT(12) : 0;
+    res |= (env->stat_l1.Zf) ? BIT(11) : 0;
+    res |= (env->stat_l1.Nf) ? BIT(10) : 0;
+    res |= (env->stat_l1.Cf) ? BIT(9)  : 0;
+    res |= (env->stat_l1.Vf) ? BIT(8)  : 0;
+    res |= (env->stat_l1.Uf) ? BIT(7)  : 0;
+    res |= (env->stat_l1.DEf) ? BIT(6)  : 0;
+    res |= (env->stat_l1.AEf) ? BIT(5)  : 0;
+    res |= (env->stat_l1.A2f) ? BIT(4)  : 0;
+    res |= (env->stat_l1.A1f) ? BIT(3)  : 0;
+    res |= (env->stat_l1.E2f) ? BIT(2)  : 0;
+    res |= (env->stat_l1.E1f) ? BIT(1)  : 0;
+
+    return res;
+}
+
+static target_ulong get_status32_l2(CPUARCState *env)
+{
+    target_ulong res = 0x00000000;
+
+    res |= (env->stat_l2.Lf) ? BIT(12) : 0;
+    res |= (env->stat_l2.Zf) ? BIT(11) : 0;
+    res |= (env->stat_l2.Nf) ? BIT(10) : 0;
+    res |= (env->stat_l2.Cf) ? BIT(9)  : 0;
+    res |= (env->stat_l2.Vf) ? BIT(8)  : 0;
+    res |= (env->stat_l2.Uf) ? BIT(7)  : 0;
+    res |= (env->stat_l2.DEf) ? BIT(6)  : 0;
+    res |= (env->stat_l2.AEf) ? BIT(5)  : 0;
+    res |= (env->stat_l2.A2f) ? BIT(4)  : 0;
+    res |= (env->stat_l2.A1f) ? BIT(3)  : 0;
+    res |= (env->stat_l2.E2f) ? BIT(2)  : 0;
+    res |= (env->stat_l2.E1f) ? BIT(1)  : 0;
+
+    return res;
+}
+
+static target_ulong get_debug(CPUARCState *env)
+{
+    target_ulong res = 0x00000000;
+
+    res |= (env->debug.LD) ? BIT(31) : 0;
+    res |= (env->debug.SH) ? BIT(30) : 0;
+    res |= (env->debug.BH) ? BIT(29) : 0;
+    res |= (env->debug.UB) ? BIT(28) : 0;
+    res |= (env->debug.ZZ) ? BIT(27) : 0;
+    res |= (env->debug.RA) ? BIT(22) : 0;
+    res |= (env->debug.IS) ? BIT(11) : 0;
+    res |= (env->debug.FH) ? BIT(1)  : 0;
+    res |= (env->debug.SS) ? BIT(0)  : 0;
+
+    return res;
+}
+
+target_ulong helper_lr(CPUARCState *env, uint32_t aux)
+{
+    target_ulong result = 0;
+
+    switch (aux) {
+        case AUX_ID_STATUS: {
+            result = get_status(env);
+        } break;
+
+        /*
+            NOTE: SEMAPHORE should be handled by a device
+        */
+
+        case AUX_ID_LP_START: {
+            result = env->lps;
+        } break;
+
+        case AUX_ID_LP_END: {
+            result = env->lpe;
+        } break;
+
+        case AUX_ID_IDENTITY: {
+        } break;
+
+        case AUX_ID_DEBUG: {
+            result = get_debug(env);
+        } break;
+
+        case AUX_ID_PC: {
+            result = env->pc & 0xfffffffe;
+        } break;
+
+        case AUX_ID_STATUS32: {
+            result = get_status32(env);
+        } break;
+
+        case AUX_ID_STATUS32_L1: {
+            result = get_status32_l1(env);
+        } break;
+
+        case AUX_ID_STATUS32_L2: {
+            result = get_status32_l2(env);
+        } break;
+
+        case AUX_ID_MULHI: {
+            result = CPU_MHI(env);
+        } break;
+
+        case AUX_ID_INT_VECTOR_BASE: {
+            result = env->intvec;
+        } break;
+
+        case AUX_ID_INT_MACMODE: {
+        } break;
+
+        case AUX_ID_IRQ_LV12: {
+        } break;
+
+        case AUX_ID_IRQ_LEV: {
+        } break;
+
+        case AUX_ID_IRQ_HINT: {
+        } break;
+
+        case AUX_ID_ERET: {
+            result = env->eret;
+        } break;
+
+        case AUX_ID_ERBTA: {
+            result = env->erbta;
+        } break;
+
+        case AUX_ID_ERSTATUS: {
+        } break;
+
+        case AUX_ID_ECR: {
+            result = env->ecr;
+        } break;
+
+        case AUX_ID_EFA: {
+            result = env->efa;
+        } break;
+
+        case AUX_ID_ICAUSE1: {
+        } break;
+
+        case AUX_ID_ICAUSE2: {
+        } break;
+
+        case AUX_ID_IENABLE: {
+        } break;
+
+        case AUX_ID_ITRIGGER: {
+        } break;
+
+        case AUX_ID_BTA: {
+            result = env->bta;
+        } break;
+
+        case AUX_ID_BTA_L1: {
+            result = env->bta_l1;
+        } break;
+
+        case AUX_ID_BTA_L2: {
+            result = env->bta_l2;
+        } break;
+
+        case AUX_ID_IRQ_PULSE_CANSEL: {
+        } break;
+
+        case AUX_ID_IRQ_PENDING: {
+        } break;
+
+        default: {
+            result = cpu_inl(aux);
+        }
+    }
+
+    return  result;
+}
+
diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index fd49a16..603a0a8 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -2069,3 +2069,29 @@ gen_set_label(label_done);
     return  BS_BRANCH_DS;
 }
 
+/*
+    LR
+*/
+int arc_gen_LR(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv cpc = tcg_const_local_i32((ctx->cpc + 3) & 0xfffffffc);
+    TCGv npc = tcg_const_local_i32((ctx->npc + 3) & 0xfffffffc);
+
+    gen_helper_lr(dest, cpu_env, src1);
+
+    tcg_temp_free_i32(cpc);
+    tcg_temp_free_i32(npc);
+
+    return BS_NONE;
+}
+
+/*
+    SR
+*/
+int arc_gen_SR(DisasCtxt *ctx, TCGv src1, TCGv src2)
+{
+    gen_helper_sr(src1, src2);
+
+    return  BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 7d76707..74beb33 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -141,3 +141,6 @@ int arc_gen_BL(DisasCtxt *c, TCGv Rd, ARC_COND cond);
 int arc_gen_J(DisasCtxt *c, TCGv src1, ARC_COND cond);
 int arc_gen_JL(DisasCtxt *c, TCGv src1, ARC_COND cond);
 
+int arc_gen_LR(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_SR(DisasCtxt *c, TCGv src1, TCGv src2);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 20/29] target-arc: ADDS, ADDSDW, SUBS, SUBSDW
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (18 preceding siblings ...)
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 19/29] target-arc: LR, SR Michael Rolnik
@ 2016-09-08 22:32 ` Michael Rolnik
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 21/29] target-arc: ABSS, ABSSW, NEGS, NEGSW, RND16, SAT16 Michael Rolnik
                   ` (9 subsequent siblings)
  29 siblings, 0 replies; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 227 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   4 +
 2 files changed, 231 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 603a0a8..d5c739e 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -271,6 +271,45 @@ void arc_gen_jump_ifnot(DisasCtxt *ctx, ARC_COND cond, TCGLabel *label_skip)
     gen_set_label(label_cont);
 }
 
+static void gen_add16_Vf(TCGv v, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+
+    /*
+
+    src1 & src2 & ~dest | ~src1 & ~src2 & dest = (src1 ^ dest) & ~(src1 ^ src2)
+
+    */
+    tcg_gen_xor_tl(t1, src1, dest); /*  t1 = src1 ^ dest                    */
+    tcg_gen_xor_tl(t2, src1, src2); /*  t2 = src1 ^ src2                    */
+    tcg_gen_andc_tl(t1, t1, t2);    /*  t1 = (src1 ^ src2) & ~(src1 ^ src2) */
+
+    tcg_gen_shri_tl(v, t1, 15);/*  Vf = t1(15)                         */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+
+static void gen_sub16_Vf(TCGv v, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+
+    /*
+        t1 = src1 & ~src2 & ~dest
+           | ~src1 & src2 & dest
+           = (src1 ^ dest) & (src1 ^ dest)*/
+    tcg_gen_xor_tl(t1, src1, dest);
+    tcg_gen_xor_tl(t2, src1, src2);
+    tcg_gen_and_tl(t1, t1, t2);
+    tcg_gen_shri_tl(v, t1, 15);     /*  Vf = t1(15) */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
 /*
     ADC
 */
@@ -2095,3 +2134,191 @@ int arc_gen_SR(DisasCtxt *ctx, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    ADDS
+*/
+int arc_gen_ADDS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+    TCGv sat = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_add_tl(rslt, src1, src2);
+
+    /*
+        src1 & src2 & ~dest | ~src1 & ~src2 & dest
+                            = (src1 ^ dest) & ~(src1 ^ src2)
+    */
+    tcg_gen_xor_tl(t1, src1, rslt); /*  t1 = src1 ^ dest                    */
+    tcg_gen_xor_tl(t2, src1, src2); /*  t2 = src1 ^ src2                    */
+    tcg_gen_andc_tl(t1, t1, t2);    /*  t1 = (src1 ^ src2) & ~(src1 ^ src2) */
+
+    tcg_gen_shri_tl(sat, t1, 31);   /*  sat= t1(31)                         */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+
+    tcg_gen_movcond_tl(TCG_COND_LTU, rslt, dest, ctx->msb32, dest, ctx->smax32);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_mov_tl(cpu_Cf, ctx->zero);
+        tcg_gen_mov_tl(cpu_Vf, sat);
+        tcg_gen_or_tl(cpu_S1f, cpu_S2f, sat);
+        tcg_gen_or_tl(cpu_S1f, cpu_S2f, sat);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    ADDSDW
+*/
+int arc_gen_ADDSDW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+    TCGv loB = tcg_temp_new_i32();
+    TCGv hiB = tcg_temp_new_i32();
+    TCGv loC = tcg_temp_new_i32();
+    TCGv hiC = tcg_temp_new_i32();
+    TCGv loA = tcg_temp_new_i32();
+    TCGv hiA = tcg_temp_new_i32();
+    TCGv hiS = tcg_temp_new_i32();
+    TCGv loS = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(loB, src1, 0xffff);
+    tcg_gen_shri_tl(hiB, src1, 16);
+
+    tcg_gen_andi_tl(loC, src2, 0xffff);
+    tcg_gen_shri_tl(hiC, src2, 16);
+
+    tcg_gen_add_tl(loA, loB, loC);
+    tcg_gen_add_tl(hiA, hiB, hiC);
+
+    tcg_gen_movcond_tl(TCG_COND_LTU, loA, loA, ctx->msb16, loA, ctx->smax16);
+    tcg_gen_movcond_tl(TCG_COND_LTU, hiA, hiA, ctx->msb16, hiA, ctx->smax16);
+
+    tcg_gen_deposit_tl(rslt, loA, hiA, 16, 16);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_movi_tl(cpu_Cf, 0);
+
+        gen_add16_Vf(hiS, hiA, hiB, hiC);
+        gen_add16_Vf(loS, loA, loB, loC);
+
+        tcg_gen_or_tl(cpu_Vf, hiS, loS);
+        tcg_gen_or_tl(cpu_S1f, cpu_S1f, hiS);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, loS);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+    tcg_temp_free_i32(loA);
+    tcg_temp_free_i32(hiA);
+    tcg_temp_free_i32(loB);
+    tcg_temp_free_i32(hiB);
+    tcg_temp_free_i32(loC);
+    tcg_temp_free_i32(hiC);
+    tcg_temp_free_i32(hiS);
+    tcg_temp_free_i32(loS);
+
+    return  BS_NONE;
+}
+
+/*
+    SUBS
+*/
+int arc_gen_SUBS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv temp = tcg_temp_new_i32();
+
+    tcg_gen_mov_tl(temp, src2);
+
+    arc_gen_ADDS(ctx, dest, src1, temp);
+
+    tcg_temp_free_i32(temp);
+
+    return  BS_NONE;
+}
+
+/*
+    SUBSDW
+*/
+int arc_gen_SUBSDW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv rslt = dest;
+    TCGv loB = tcg_temp_new_i32();
+    TCGv hiB = tcg_temp_new_i32();
+    TCGv loC = tcg_temp_new_i32();
+    TCGv hiC = tcg_temp_new_i32();
+    TCGv loA = tcg_temp_new_i32();
+    TCGv hiA = tcg_temp_new_i32();
+    TCGv hiS = tcg_temp_new_i32();
+    TCGv loS = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(loB, src1, 0xffff);
+    tcg_gen_shri_tl(hiB, src1, 16);
+
+    tcg_gen_andi_tl(loC, src2, 0xffff);
+    tcg_gen_shri_tl(hiC, src2, 16);
+
+    tcg_gen_sub_tl(loA, loB, loC);
+    tcg_gen_sub_tl(hiA, hiB, hiC);
+
+    tcg_gen_movcond_tl(TCG_COND_LTU, loA, loA, ctx->msb16, loA, ctx->smax16);
+    tcg_gen_movcond_tl(TCG_COND_LTU, hiA, hiA, ctx->msb16, hiA, ctx->smax16);
+
+    tcg_gen_deposit_tl(rslt, loA, hiA, 16, 16);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_movi_tl(cpu_Cf, 0);
+
+        gen_sub16_Vf(hiS, hiA, hiB, hiC);
+        gen_sub16_Vf(loS, loA, loB, loC);
+
+        tcg_gen_or_tl(cpu_Vf, hiS, loS);
+        tcg_gen_or_tl(cpu_S1f, cpu_S1f, hiS);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, loS);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+    tcg_temp_free_i32(loA);
+    tcg_temp_free_i32(hiA);
+    tcg_temp_free_i32(loB);
+    tcg_temp_free_i32(hiB);
+    tcg_temp_free_i32(loC);
+    tcg_temp_free_i32(hiC);
+    tcg_temp_free_i32(hiS);
+    tcg_temp_free_i32(loS);
+
+    return  BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 74beb33..a4699e3 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -144,3 +144,7 @@ int arc_gen_JL(DisasCtxt *c, TCGv src1, ARC_COND cond);
 int arc_gen_LR(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_SR(DisasCtxt *c, TCGv src1, TCGv src2);
 
+int arc_gen_ADDS(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ADDSDW(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_SUBS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_SUBSDW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 21/29] target-arc: ABSS, ABSSW, NEGS, NEGSW, RND16, SAT16
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (19 preceding siblings ...)
  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 ` Michael Rolnik
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 22/29] target-arc: ASLS, ASRS Michael Rolnik
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 238 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   8 ++
 2 files changed, 246 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index d5c739e..2a62f30 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -2322,3 +2322,241 @@ int arc_gen_SUBSDW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
     return  BS_NONE;
 }
 
+/*
+    ABSS
+*/
+int arc_gen_ABSS(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+    TCGv_i32 t0 = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_neg_i32(t0, src1);
+    tcg_gen_movcond_tl(TCG_COND_LEU, rslt, src1, ctx->smax16, src1, t0);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, src1, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, src1, 31);
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Vf, src1, ctx->msb32);
+        tcg_gen_or_tl(cpu_S1f, cpu_S1f, cpu_Vf);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, cpu_Vf);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+    tcg_temp_free_i32(t0);
+
+    return  BS_NONE;
+}
+
+/*
+    ABSSW
+*/
+int arc_gen_ABSSW(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+    TCGv_i32 lo = tcg_temp_new_i32();
+    TCGv_i32 neg = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_andi_tl(lo, src1, 0x0000ffff);
+    tcg_gen_neg_tl(neg, lo);
+
+    tcg_gen_movcond_tl(TCG_COND_LEU, rslt, lo, ctx->smax16, lo, neg);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, src1, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, src1, 31);
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Vf, lo, ctx->msb16);
+        tcg_gen_or_tl(cpu_S1f, cpu_S1f, cpu_Vf);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, cpu_Vf);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+    tcg_temp_free_i32(lo);
+    tcg_temp_free_i32(neg);
+
+    return  BS_NONE;
+}
+
+/*
+    NEGS
+*/
+int arc_gen_NEGS(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+    TCGv_i32 sat = tcg_temp_new_i32();
+    TCGLabel *label_else = gen_new_label();
+    TCGLabel *label_done = gen_new_label();
+
+    tcg_gen_brcondi_tl(TCG_COND_NE, src1, 0x80000000, label_else);
+
+    tcg_gen_movi_tl(sat, 1);
+    tcg_gen_movi_tl(rslt, 0x7fffffff);
+    tcg_gen_br(label_done);
+
+gen_set_label(label_else);
+    tcg_gen_movi_tl(sat, 0);
+    tcg_gen_neg_tl(rslt, src1);
+
+gen_set_label(label_done);
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_mov_tl(cpu_Vf, sat);
+        tcg_gen_or_tl(cpu_S1f, cpu_S1f, cpu_Vf);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, cpu_Vf);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    tcg_temp_free(sat);
+
+    return  BS_NONE;
+}
+
+/*
+    NEGSW
+*/
+int arc_gen_NEGSW(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+    TCGv_i32 src16 = tcg_temp_new_i32();
+    TCGv_i32 sat = tcg_temp_new_i32();
+    TCGLabel *label_else = gen_new_label();
+    TCGLabel *label_done = gen_new_label();
+
+    tcg_gen_andi_tl(src16, src1, 0x0000ffff);
+
+    tcg_gen_brcondi_tl(TCG_COND_NE, src1, 0x8000, label_else);
+
+    tcg_gen_movi_tl(sat, 1);
+    tcg_gen_movi_tl(rslt, 0x7fff);
+    tcg_gen_br(label_done);
+
+gen_set_label(label_else);
+    tcg_gen_movi_tl(sat, 0);
+    tcg_gen_neg_tl(rslt, src1);
+
+gen_set_label(label_done);
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_mov_tl(cpu_Vf, sat);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, cpu_Vf);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    tcg_temp_free(src16);
+    tcg_temp_free(sat);
+
+    return  BS_NONE;
+}
+
+/*
+    RND16
+*/
+int arc_gen_RND16(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+    TCGv_i32 hi = tcg_const_local_i32(0x00007fff);    /*  max sint16  */
+    TCGv_i32 lo = tcg_const_local_i32(0xffff8000);    /*  min sint16  */
+    TCGv_i32 sat = tcg_temp_new_i32();
+    TCGv_i32 temp = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_addi_tl(temp, src1, 0x00008000);
+    tcg_gen_shri_tl(temp, temp, 16);
+
+    tcg_gen_movcond_tl(TCG_COND_LT, rslt, src1, lo, hi, temp);
+    tcg_gen_movcond_tl(TCG_COND_GT, rslt, src1, hi, hi, temp);
+    tcg_gen_setcond_tl(TCG_COND_NE, sat, rslt, temp);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_mov_tl(cpu_Vf, sat);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, sat);
+    }
+
+    tcg_temp_free_i32(temp);
+    tcg_temp_free_i32(sat);
+    tcg_temp_free_i32(lo);
+    tcg_temp_free_i32(hi);
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
+/*
+    SAT16
+*/
+int arc_gen_SAT16(DisasCtxt *ctx, TCGv dest, TCGv src1)
+{
+    TCGv rslt = dest;
+    TCGv_i32 hi = tcg_const_local_i32(0x00007fff);    /*  max sint16  */
+    TCGv_i32 lo = tcg_const_local_i32(0xffff8000);    /*  min sint16  */
+    TCGv_i32 sat = tcg_temp_new_i32();
+
+    if (TCGV_EQUAL(dest, src1)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_movcond_tl(TCG_COND_LT, rslt, src1, lo, lo, src1);
+    tcg_gen_movcond_tl(TCG_COND_GT, rslt, src1, hi, hi, src1);
+    tcg_gen_setcond_tl(TCG_COND_NE, sat, rslt, src1);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
+        tcg_gen_mov_tl(cpu_Vf, sat);
+        tcg_gen_or_tl(cpu_S2f, cpu_S2f, sat);
+    }
+
+    tcg_temp_free_i32(sat);
+    tcg_temp_free_i32(lo);
+    tcg_temp_free_i32(hi);
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    return  BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index a4699e3..c84d989 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -148,3 +148,11 @@ int arc_gen_ADDS(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_ADDSDW(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_SUBS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_SUBSDW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
+
+int arc_gen_ABSS(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_ABSSW(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_SAT16(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_RND16(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_NEGS(DisasCtxt *c, TCGv dest, TCGv src1);
+int arc_gen_NEGSW(DisasCtxt *c, TCGv dest, TCGv src1);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 22/29] target-arc: ASLS, ASRS
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (20 preceding siblings ...)
  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 ` 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
                   ` (7 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  3 +++
 2 files changed, 60 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 2a62f30..524b213 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -2560,3 +2560,60 @@ int arc_gen_SAT16(DisasCtxt *ctx, TCGv dest, TCGv src1)
     return  BS_NONE;
 }
 
+/*
+    ASLS
+*/
+int arc_gen_ASLS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    /* TODO */
+
+    return  BS_NONE;
+}
+
+
+/*
+    ASRS
+*/
+int arc_gen_ASRS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
+{
+    /* TODO: check */
+    TCGv rslt = dest;
+    TCGv shft = tcg_temp_new_i32();
+    TCGLabel *label_pos = gen_new_label();
+    TCGLabel *label_done = gen_new_label();
+
+    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
+        rslt = tcg_temp_new_i32();
+    }
+
+    tcg_gen_brcond_tl(TCG_COND_LEU, src2, ctx->smax32, label_pos);
+
+    /*  negative    */
+    tcg_gen_movcond_tl(TCG_COND_GT, shft, src2, ctx->smin5, src2, ctx->smin5);
+    tcg_gen_neg_tl(shft, shft);
+    tcg_gen_shl_tl(rslt, src1, shft);
+
+    tcg_gen_br(label_done);
+
+gen_set_label(label_pos);
+    /*  positive    */
+    tcg_gen_movcond_tl(TCG_COND_LT, shft, src2, ctx->smax5, src2, ctx->smax5);
+    tcg_gen_sar_tl(rslt, src1, shft);
+
+gen_set_label(label_done);
+
+    if (ctx->opt.f) {
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
+        tcg_gen_sari_tl(cpu_Nf, rslt, 31);
+    }
+
+    if (!TCGV_EQUAL(dest, rslt)) {
+        tcg_gen_mov_tl(dest, rslt);
+        tcg_temp_free_i32(rslt);
+    }
+
+    tcg_temp_free_i32(shft);
+
+    return BS_NONE;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index c84d989..e2b76d4 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -156,3 +156,6 @@ int arc_gen_RND16(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_NEGS(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_NEGSW(DisasCtxt *c, TCGv dest, TCGv src1);
 
+int arc_gen_ASLS(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
+int arc_gen_ASRS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 23/29] target-arc: FLAG, BRK, SLEEP
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (21 preceding siblings ...)
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 22/29] target-arc: ASLS, ASRS Michael Rolnik
@ 2016-09-08 22:32 ` Michael Rolnik
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 24/29] target-arc: NOP, UNIMP Michael Rolnik
                   ` (6 subsequent siblings)
  29 siblings, 0 replies; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/helper.h         |  1 +
 target-arc/op_helper.c      |  6 +++++
 target-arc/translate-inst.c | 61 +++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  4 +++
 4 files changed, 72 insertions(+)

diff --git a/target-arc/helper.h b/target-arc/helper.h
index 1d84935..14769b1 100644
--- a/target-arc/helper.h
+++ b/target-arc/helper.h
@@ -23,4 +23,5 @@ DEF_HELPER_2(norm, i32, env, i32)
 DEF_HELPER_2(normw, i32, env, i32)
 DEF_HELPER_2(lr, tl, env, i32)
 DEF_HELPER_2(sr, void, i32, i32)
+DEF_HELPER_1(halt, void, env)
 
diff --git a/target-arc/op_helper.c b/target-arc/op_helper.c
index 3cf9080..b07939c 100644
--- a/target-arc/op_helper.c
+++ b/target-arc/op_helper.c
@@ -411,3 +411,9 @@ target_ulong helper_lr(CPUARCState *env, uint32_t aux)
     return  result;
 }
 
+void helper_halt(CPUARCState *env)
+{
+    /* TODO: implement */
+}
+
+
diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 524b213..9d0f195 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -2617,3 +2617,64 @@ gen_set_label(label_done);
     return BS_NONE;
 }
 
+/*
+    BRK
+*/
+int arc_gen_BRK(DisasCtxt *ctx)
+{
+    tcg_gen_movi_tl(cpu_debug_BH, 1);
+    gen_helper_halt(cpu_env);
+    return  BS_BREAK;
+}
+
+/*
+    FLAG
+*/
+int arc_gen_FLAG(DisasCtxt *ctx, TCGv src1)
+{
+    TCGLabel *label_else = gen_new_label();
+    TCGLabel *label_done = gen_new_label();
+    TCGv temp = tcg_temp_new_i32();
+
+    tcg_gen_mov_tl(temp, src1);
+
+    tcg_gen_andi_tl(cpu_Hf, temp, 1);
+    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_Hf, 0, label_else);
+
+    gen_helper_halt(cpu_env);
+
+gen_set_label(label_else);
+    tcg_gen_shri_tl(temp, temp, 1);
+    tcg_gen_andi_tl(cpu_E1f, temp, 1);
+
+    tcg_gen_shri_tl(temp, temp, 1);
+    tcg_gen_andi_tl(cpu_E2f, temp, 1);
+
+    tcg_gen_shri_tl(temp, temp, 6);
+    tcg_gen_andi_tl(cpu_Vf, temp, 1);
+
+    tcg_gen_shri_tl(temp, temp, 1);
+    tcg_gen_andi_tl(cpu_Cf, temp, 1);
+
+    tcg_gen_shri_tl(temp, temp, 1);
+    tcg_gen_andi_tl(cpu_Nf, temp, 1);
+
+    tcg_gen_shri_tl(temp, temp, 1);
+    tcg_gen_andi_tl(cpu_Zf, temp, 1);
+gen_set_label(label_done);
+
+    return BS_NONE;
+}
+
+/*
+    SLEEP
+*/
+int arc_gen_SLEEP(DisasCtxt *ctx, TCGv src1)
+{
+    tcg_gen_movi_tl(cpu_debug_ZZ, 1);
+    tcg_gen_andi_tl(cpu_E1f, src1, 0x01);
+    tcg_gen_andi_tl(cpu_E2f, src1, 0x02);
+
+    return  BS_BREAK;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index e2b76d4..5794cad 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -159,3 +159,7 @@ int arc_gen_NEGSW(DisasCtxt *c, TCGv dest, TCGv src1);
 int arc_gen_ASLS(DisasCtxt *c, TCGv dest, TCGv src1, TCGv src2);
 int arc_gen_ASRS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2);
 
+int arc_gen_SLEEP(DisasCtxt *c, TCGv src1);
+int arc_gen_BRK(DisasCtxt *c);
+int arc_gen_FLAG(DisasCtxt *c, TCGv src1);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 24/29] target-arc: NOP, UNIMP
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (22 preceding siblings ...)
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 23/29] target-arc: FLAG, BRK, SLEEP Michael Rolnik
@ 2016-09-08 22:32 ` 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
                   ` (5 subsequent siblings)
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 20 ++++++++++++++++++++
 target-arc/translate-inst.h |  2 ++
 2 files changed, 22 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 9d0f195..4c4318f 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -2678,3 +2678,23 @@ int arc_gen_SLEEP(DisasCtxt *ctx, TCGv src1)
     return  BS_BREAK;
 }
 
+/*
+    NOP
+*/
+int arc_gen_NOP(DisasCtxt *ctx)
+{
+    /*  literally no operation  */
+    return  BS_NONE;
+}
+
+/*
+    UNIMP
+*/
+int arc_gen_UNIMP(DisasCtxt *ctx)
+{
+    /* PC = INT_VECTOR_BACE + 0x10 */
+    tcg_gen_andi_tl(cpu_pc, cpu_intvec, 0xffffffc0);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, 0x10);
+
+    return  BS_EXCP;
+}
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 5794cad..9f88d03 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -163,3 +163,5 @@ int arc_gen_SLEEP(DisasCtxt *c, TCGv src1);
 int arc_gen_BRK(DisasCtxt *c);
 int arc_gen_FLAG(DisasCtxt *c, TCGv src1);
 
+int arc_gen_NOP(DisasCtxt *c);
+int arc_gen_UNIMP(DisasCtxt *c);
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 25/29] target-arc: TRAP, SWI
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (23 preceding siblings ...)
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 24/29] target-arc: NOP, UNIMP Michael Rolnik
@ 2016-09-08 22:32 ` Michael Rolnik
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 26/29] target-arc: RTIE Michael Rolnik
                   ` (4 subsequent siblings)
  29 siblings, 0 replies; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 105 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   4 ++
 2 files changed, 109 insertions(+)

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 4c4318f..87a00ca 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -2698,3 +2698,108 @@ int arc_gen_UNIMP(DisasCtxt *ctx)
 
     return  BS_EXCP;
 }
+
+/*
+    TRAP
+*/
+int arc_gen_TRAP(DisasCtxt *ctx, TCGv src1)
+{
+    if (arc_feature(ctx->env, ARC_FEATURE_ARC700)) {
+        tcg_gen_mov_tl(cpu_er_Lf, cpu_Lf);
+        tcg_gen_mov_tl(cpu_er_Zf, cpu_Zf);
+        tcg_gen_mov_tl(cpu_er_Nf, cpu_Nf);
+        tcg_gen_mov_tl(cpu_er_Cf, cpu_Cf);
+        tcg_gen_mov_tl(cpu_er_Vf, cpu_Vf);
+        tcg_gen_mov_tl(cpu_er_Uf, cpu_Uf);
+
+        tcg_gen_mov_tl(cpu_er_DEf, cpu_DEf);
+        tcg_gen_mov_tl(cpu_er_AEf, cpu_AEf);
+        tcg_gen_mov_tl(cpu_er_A2f, cpu_A2f);
+        tcg_gen_mov_tl(cpu_er_A1f, cpu_A1f);
+        tcg_gen_mov_tl(cpu_er_E2f, cpu_E2f);
+        tcg_gen_mov_tl(cpu_er_E1f, cpu_E1f);
+        tcg_gen_mov_tl(cpu_er_Hf, cpu_Hf);
+
+        tcg_gen_movi_tl(cpu_E1f, 0);
+        tcg_gen_movi_tl(cpu_E2f, 0);
+        tcg_gen_movi_tl(cpu_AEf, 1);
+        tcg_gen_movi_tl(cpu_Uf, 0);
+
+        tcg_gen_movi_tl(cpu_eret, ctx->npc);
+        tcg_gen_movi_tl(cpu_efa, ctx->cpc);
+        tcg_gen_andi_tl(cpu_ecr, src1, 0x000000ff);
+        tcg_gen_ori_tl(cpu_ecr, cpu_ecr, 0x00250000);
+        tcg_gen_movcond_tl(TCG_COND_NE, cpu_erbta, cpu_DEf, ctx->zero,
+                                                    cpu_bta, cpu_erbta);
+
+        tcg_gen_andi_tl(cpu_pc, cpu_intvec, 0xffffffc0);
+        tcg_gen_addi_tl(cpu_pc, cpu_pc, 0x128);
+    } else {
+        arc_gen_UNIMP(ctx);
+    }
+
+    return  BS_EXCP;
+}
+
+/*
+    SWI
+*/
+int arc_gen_SWI(DisasCtxt *ctx)
+{
+    if (arc_feature(ctx->env, ARC_FEATURE_ARC700)) {
+        tcg_gen_mov_tl(cpu_er_Lf, cpu_Lf);
+        tcg_gen_mov_tl(cpu_er_Zf, cpu_Zf);
+        tcg_gen_mov_tl(cpu_er_Nf, cpu_Nf);
+        tcg_gen_mov_tl(cpu_er_Cf, cpu_Cf);
+        tcg_gen_mov_tl(cpu_er_Vf, cpu_Vf);
+        tcg_gen_mov_tl(cpu_er_Uf, cpu_Uf);
+
+        tcg_gen_mov_tl(cpu_er_DEf, cpu_DEf);
+        tcg_gen_mov_tl(cpu_er_AEf, cpu_AEf);
+        tcg_gen_mov_tl(cpu_er_A2f, cpu_A2f);
+        tcg_gen_mov_tl(cpu_er_A1f, cpu_A1f);
+        tcg_gen_mov_tl(cpu_er_E2f, cpu_E2f);
+        tcg_gen_mov_tl(cpu_er_E1f, cpu_E1f);
+        tcg_gen_mov_tl(cpu_er_Hf, cpu_Hf);
+
+        tcg_gen_movi_tl(cpu_E1f, 0);
+        tcg_gen_movi_tl(cpu_E2f, 0);
+        tcg_gen_movi_tl(cpu_AEf, 1);
+        tcg_gen_movi_tl(cpu_Uf, 0);
+
+        tcg_gen_movi_tl(cpu_eret, ctx->npc);
+        tcg_gen_movi_tl(cpu_efa, ctx->cpc);
+        tcg_gen_movi_tl(cpu_ecr, 0x00250000);
+        tcg_gen_movcond_tl(TCG_COND_NE, cpu_erbta, cpu_DEf, ctx->zero,
+                                                    cpu_bta, cpu_erbta);
+
+        tcg_gen_andi_tl(cpu_pc, cpu_intvec, 0xffffffc0);
+        tcg_gen_addi_tl(cpu_pc, cpu_pc, 0x128);
+    } else {
+        tcg_gen_movi_tl(cpu_ilink2, ctx->npc);
+
+        tcg_gen_mov_tl(cpu_l2_Lf, cpu_Lf);
+        tcg_gen_mov_tl(cpu_l2_Zf, cpu_Zf);
+        tcg_gen_mov_tl(cpu_l2_Nf, cpu_Nf);
+        tcg_gen_mov_tl(cpu_l2_Cf, cpu_Cf);
+        tcg_gen_mov_tl(cpu_l2_Vf, cpu_Vf);
+        tcg_gen_mov_tl(cpu_l2_Uf, cpu_Uf);
+
+        tcg_gen_mov_tl(cpu_l2_DEf, cpu_DEf);
+        tcg_gen_mov_tl(cpu_l2_AEf, cpu_AEf);
+        tcg_gen_mov_tl(cpu_l2_A2f, cpu_A2f);
+        tcg_gen_mov_tl(cpu_l2_A1f, cpu_A1f);
+        tcg_gen_mov_tl(cpu_l2_E2f, cpu_E2f);
+        tcg_gen_mov_tl(cpu_l2_E1f, cpu_E1f);
+        tcg_gen_mov_tl(cpu_l2_Hf, cpu_Hf);
+
+        tcg_gen_movi_tl(cpu_E1f, 0);
+        tcg_gen_movi_tl(cpu_E2f, 0);
+
+        tcg_gen_andi_tl(cpu_pc, cpu_intvec, 0xffffffc0);
+        tcg_gen_addi_tl(cpu_pc, cpu_pc, 0x10);
+    }
+
+    return  BS_EXCP;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 9f88d03..f7f988b 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -165,3 +165,7 @@ int arc_gen_FLAG(DisasCtxt *c, TCGv src1);
 
 int arc_gen_NOP(DisasCtxt *c);
 int arc_gen_UNIMP(DisasCtxt *c);
+
+int arc_gen_SWI(DisasCtxt *c);
+int arc_gen_TRAP(DisasCtxt *c, TCGv src1);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 26/29] target-arc: RTIE
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (24 preceding siblings ...)
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 25/29] target-arc: TRAP, SWI Michael Rolnik
@ 2016-09-08 22:32 ` Michael Rolnik
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 27/29] target-arc: LP Michael Rolnik
                   ` (3 subsequent siblings)
  29 siblings, 0 replies; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/helper.h         |  1 +
 target-arc/op_helper.c      | 21 +++++++++++++++++++++
 target-arc/translate-inst.c | 10 ++++++++++
 target-arc/translate-inst.h |  2 ++
 4 files changed, 34 insertions(+)

diff --git a/target-arc/helper.h b/target-arc/helper.h
index 14769b1..abfd0d2 100644
--- a/target-arc/helper.h
+++ b/target-arc/helper.h
@@ -24,4 +24,5 @@ DEF_HELPER_2(normw, i32, env, i32)
 DEF_HELPER_2(lr, tl, env, i32)
 DEF_HELPER_2(sr, void, i32, i32)
 DEF_HELPER_1(halt, void, env)
+DEF_HELPER_1(rtie, void, env)
 
diff --git a/target-arc/op_helper.c b/target-arc/op_helper.c
index b07939c..a3f6a46 100644
--- a/target-arc/op_helper.c
+++ b/target-arc/op_helper.c
@@ -416,4 +416,25 @@ void helper_halt(CPUARCState *env)
     /* TODO: implement */
 }
 
+void helper_rtie(CPUARCState *env)
+{
+    if (env->stat.AEf) {
+        CPU_PCL(env) = env->eret;
+        env->stat = env->stat_er;
+        env->bta = env->erbta;
+    } else if (env->stat.A2f) {
+        CPU_PCL(env) = CPU_ILINK2(env);
+        env->stat = env->stat_l2;
+        env->bta = env->bta_l2;
+    } else if (env->stat.A1f) {
+        CPU_PCL(env) = CPU_ILINK1(env);
+        env->stat = env->stat_l1;
+        env->bta = env->bta_l1;
+    } else {
+        CPU_PCL(env) = env->eret;
+        env->stat = env->stat_er;
+        env->bta = env->stat.AEf;
+    }
+}
+
 
diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 87a00ca..743f2be 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -2803,3 +2803,13 @@ int arc_gen_SWI(DisasCtxt *ctx)
     return  BS_EXCP;
 }
 
+/*
+    RTIE
+*/
+int arc_gen_RTIE(DisasCtxt *ctx)
+{
+    gen_helper_rtie(cpu_env);
+
+    return  BS_BRANCH;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index f7f988b..8bbac4f 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -169,3 +169,5 @@ int arc_gen_UNIMP(DisasCtxt *c);
 int arc_gen_SWI(DisasCtxt *c);
 int arc_gen_TRAP(DisasCtxt *c, TCGv src1);
 
+int arc_gen_RTIE(DisasCtxt *c);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 27/29] target-arc: LP
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (25 preceding siblings ...)
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 26/29] target-arc: RTIE Michael Rolnik
@ 2016-09-08 22:32 ` Michael Rolnik
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 28/29] target-arc: decode Michael Rolnik
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/helper.h         |  1 +
 target-arc/op_helper.c      |  5 ++++-
 target-arc/translate-inst.c | 40 ++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |  2 ++
 4 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/target-arc/helper.h b/target-arc/helper.h
index abfd0d2..ef5c12e 100644
--- a/target-arc/helper.h
+++ b/target-arc/helper.h
@@ -25,4 +25,5 @@ DEF_HELPER_2(lr, tl, env, i32)
 DEF_HELPER_2(sr, void, i32, i32)
 DEF_HELPER_1(halt, void, env)
 DEF_HELPER_1(rtie, void, env)
+DEF_HELPER_1(flush, void, env)
 
diff --git a/target-arc/op_helper.c b/target-arc/op_helper.c
index a3f6a46..61e790e 100644
--- a/target-arc/op_helper.c
+++ b/target-arc/op_helper.c
@@ -437,4 +437,7 @@ void helper_rtie(CPUARCState *env)
     }
 }
 
-
+void helper_flush(CPUARCState *env)
+{
+    tb_flush((CPUState *)arc_env_get_cpu(env));
+}
diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 743f2be..87940ed 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -2813,3 +2813,43 @@ int arc_gen_RTIE(DisasCtxt *ctx)
     return  BS_BRANCH;
 }
 
+/*
+    LPcc
+*/
+int arc_gen_LPcc(DisasCtxt *ctx, TCGv rd, unsigned Q)
+{
+    TCGLabel *label_done = gen_new_label();
+    TCGv t0 = tcg_const_local_i32(ctx->npc);
+
+    /*
+        if cc is false, pc will be updated here
+        pc = pcl + rd
+    */
+    tcg_gen_shli_tl(cpu_pc, rd, 1);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, ctx->pcl);
+
+    /*
+        if cc is false we will jump to done label
+    */
+    arc_gen_jump_ifnot(ctx, Q, label_done);
+
+    /*
+        cc is true
+    */
+    tcg_gen_movi_tl(t0, ctx->lpe);
+
+    tcg_gen_movi_tl(cpu_lps, ctx->npc);
+    tcg_gen_mov_tl(cpu_lpe, cpu_pc);
+    tcg_gen_movi_tl(cpu_pc, ctx->npc);
+
+    tcg_gen_brcond_tl(TCG_COND_EQ, t0, cpu_lpe, label_done);
+
+    gen_helper_flush(cpu_env);
+
+gen_set_label(label_done);
+
+    tcg_temp_free_i32(t0);
+
+    return  BS_BRANCH;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index 8bbac4f..7ea20a0 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -171,3 +171,5 @@ int arc_gen_TRAP(DisasCtxt *c, TCGv src1);
 
 int arc_gen_RTIE(DisasCtxt *c);
 
+int arc_gen_LPcc(DisasCtxt *ctx, TCGv Rd, unsigned Q);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 28/29] target-arc: decode
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (26 preceding siblings ...)
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 27/29] target-arc: LP Michael Rolnik
@ 2016-09-08 22:32 ` 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   ` [Qemu-devel] " Alexey Brodkin
  29 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/decode.c | 2209 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 2207 insertions(+), 2 deletions(-)

diff --git a/target-arc/decode.c b/target-arc/decode.c
index 1bb859a..0efc23d 100644
--- a/target-arc/decode.c
+++ b/target-arc/decode.c
@@ -1,7 +1,2212 @@
 #include "translate.h"
+#include "translate-inst.h"
 
-int arc_decode(DisasCtxt *ctx)
+typedef int (*decode_f)(DisasCtxt *ctx, uint32_t opcode);
+
+static void arc_decode_src(DisasCtxt *ctx, TCGv src)
+{
+    if (TCGV_EQUAL(src, cpu_limm)   /* register refers to limm  */
+        && ctx->opt.limm == 0) {    /* limm is not yet decoded  */
+        uint32_t limm;
+
+        limm    = cpu_ldl_code(ctx->env, ctx->npc);
+        limm    = (limm & 0xffff0000) >> 16
+                | (limm & 0x0000ffff) << 16;
+
+        tcg_gen_movi_tl(cpu_limm, limm);
+
+        ctx->npc += sizeof(limm);
+        ctx->opt.limm = 1;
+        ctx->opt.d = 0;
+    }
+
+    if (TCGV_EQUAL(src, cpu_pcl)) {
+        tcg_gen_movi_tl(cpu_pcl, ctx->pcl);
+    }
+}
+
+static int arc_decode_invalid(DisasCtxt *ctx, uint32_t opcode)
+{
+    return BS_EXCP;
+}
+
+
+/*
+    Branch Conditionally
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------|-------------------|-|-------------------|-|----------+
+    | major   |S[10:1]            |0|S[20:11]           |N|Q[4:0]    |
+    +---------|-------------------|-|-------------------|-|----------+
+    |0 0 0 0 0|s s s s s s s s s s|0|S S S S S S S S S S|N|Q Q Q Q Q |
+    +---------+-------------------+-+-------------------+-+----------+
+
+    Branch Unconditional Far
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------|-------------------|-|-------------------|-|-|--------+
+    | major   |S[10:1]            |1|S[20:11]           |N|R|S[24:21]|
+    +---------|-------------------|-|-------------------|-|-|--------+
+    |0 0 0 0 0|s s s s s s s s s s|1|S S S S S S S S S S|N|0|T T T T |
+    +---------+-------------------+-+-------------------+-+-+--------+
+*/
+static int arc_decode_major00(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret;
+    TCGv s;
+
+    if (extract32(opcode, 16, 1) == 0) {
+        unsigned _Q = extract32(opcode, 0, 5);
+        unsigned _N = extract32(opcode, 5, 1);
+        unsigned _S = extract32(opcode, 6, 10);
+        unsigned _s = extract32(opcode, 17, 10);
+
+        s = tcg_const_local_i32(sextract32((_S << 10) | _s, 0, 20));
+        ctx->opt.d = _N;
+
+        ret = arc_gen_B(ctx, s, _Q);
+
+    } else {
+        unsigned _T = extract32(opcode, 0, 4);
+        unsigned _N = extract32(opcode, 5, 1);
+        unsigned _S = extract32(opcode, 6, 10);
+        unsigned _s = extract32(opcode, 17, 10);
+
+        s = tcg_const_local_i32(sextract32((((_T << 10) | _S) << 10) | _s, 0,
+                                                                           24));
+        ctx->opt.d = _N;
+
+        ret = arc_gen_B(ctx, s, ARC_COND_AL);
+    }
+
+    tcg_temp_free_i32(s);
+
+    return ret;
+}
+
+/*
+
+    Branch and Link Conditionally
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------|-----------------|-|-|-------------------|-|----------+
+    | major   |S[10:2]          |0|0|S[20:11]           |N|Q[4:0]    |
+    +---------|-----------------|-|-|-------------------|-|----------+
+    |0 0 0 0 1|s s s s s s s s s|0|0|S S S S S S S S S S|N|Q Q Q Q Q |
+    +---------+-----------------+-+-+-------------------+-+----------+
+
+    Branch and Link Unconditional Far
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------|-----------------|-|-|-------------------|-|----------+
+    | major   |S[10:2]          |0|0|S[20:11]           |N|Q[4:0]    |
+    +---------|-----------------|-|-|-------------------|-|----------+
+    |0 0 0 0 1|s s s s s s s s s|0|0|S S S S S S S S S S|N|Q Q Q Q Q |
+    +---------+-----------------+-+-+-------------------+-+----------+
+
+    Branch on Compare Register-Register
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------|-----|-------------|-|-|-----|-----------|-|-|--------+
+    | major   |b    |S[7:1]       |1|S|B    |C[5:0]     |N|0| minor  |
+    +---------|-----|-------------|-|-|-----|-----------|-|-|--------+
+    |0 0 0 0 1|b b b|s s s s s s s|1|S|B B B|C C C C C C|N|0|i i i i |
+    +---------+-----+-------------+-+-+-----+-----------+-+-+--------+
+
+    Branch on Compare/Bit Test Register-Immediate
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------|-----|-------------|-|-|-----|-----------|-|-|--------+
+    | major   |b    |S[7:1]       |1|S|B    |U[5:0]     |N|1| minor  |
+    +---------|-----|-------------|-|-|-----|-----------|-|-|--------+
+    |0 0 0 0 1|b b b|s s s s s s s|1|S|B B B|U U U U U U|N|1|i i i i |
+    +---------+-----+-------------+-+-+-----+-----------+-+-+--------+
+*/
+static int arc_decode_major01_body(DisasCtxt *ctx,
+                                        unsigned minor, TCGv a, TCGv b, TCGv c)
+{
+    int ret;
+
+    switch (minor) {
+        case 0x00: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BR(ctx, a, b, c, TCG_COND_EQ);
+            break;
+        }
+        case 0x01: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BR(ctx, a, b, c, TCG_COND_NE);
+            break;
+        }
+        case 0x02: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BR(ctx, a, b, c, TCG_COND_LT);
+            break;
+        }
+        case 0x03: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BR(ctx, a, b, c, TCG_COND_GE);
+            break;
+        }
+        case 0x04: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BR(ctx, a, b, c, TCG_COND_LTU);
+            break;
+        }
+        case 0x05: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BR(ctx, a, b, c, TCG_COND_GEU);
+            break;
+        }
+
+        case 0x06 ... 0x0d: {
+            ret = arc_gen_INVALID(ctx);
+            break;
+        }
+
+        case 0x0E: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BBIT0(ctx, a, b, c);
+            break;
+        }
+        case 0x0F: {
+            arc_decode_src(ctx, a);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BBIT1(ctx, a, b, c);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    return ret;
+}
+
+static int arc_decode_major01(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret;
+
+    if (extract32(opcode, 16, 1) == 0) {
+
+        if (extract32(opcode, 17, 1) == 0) {
+            /*  Branch and Link Conditionally   */
+            unsigned _Q = extract32(opcode, 0, 5);
+            unsigned _N = extract32(opcode, 5, 1);
+            unsigned _S = extract32(opcode, 6, 10);
+            unsigned _s = extract32(opcode, 18, 9);
+            TCGv s = tcg_const_local_i32(sextract32((_S << 9) | _s, 0, 19));
+
+            ctx->opt.d = _N;
+
+            ret = arc_gen_BL(ctx, s, _Q);
+
+            tcg_temp_free_i32(s);
+        } else {
+            /*  Branch and Link Unconditional Far   */
+            unsigned _T = extract32(opcode, 0, 4);
+            unsigned _N = extract32(opcode, 5, 1);
+            unsigned _S = extract32(opcode, 6, 10);
+            unsigned _s = extract32(opcode, 18, 9);
+            TCGv s = tcg_const_local_i32(sextract32((((_T << 10) | _S) << 9) |
+                                                                    _s, 0, 23));
+
+            ctx->opt.d = _N;
+
+            ret = arc_gen_BL(ctx, s, ARC_COND_AL);
+
+            tcg_temp_free_i32(s);
+        }
+    } else {
+        unsigned minor;
+
+        minor = extract32(opcode, 0, 4);
+
+        if (extract32(opcode, 4, 1) == 0) {
+            /*  Branch on Compare Register-Register */
+            unsigned _N = extract32(opcode, 5, 1);
+            unsigned _C = extract32(opcode, 6, 6);
+            unsigned _B = extract32(opcode, 12, 3);
+            unsigned _S = extract32(opcode, 15, 1);
+            unsigned _s = extract32(opcode, 17, 7);
+            unsigned _b = extract32(opcode, 24, 3);
+
+            TCGv b = cpu_r[(_B << 3) | _b];
+            TCGv c = cpu_r[_C];
+            TCGv s = tcg_const_local_i32(sextract32((_S << 7) | _s, 0, 8));
+
+            ctx->opt.d = _N;
+
+            ret = arc_decode_major01_body(ctx, minor, b, c, s);
+
+            tcg_temp_free_i32(s);
+        } else {
+            /*  Branch on Compare/Bit Test Register-Immediate   */
+            unsigned _N = extract32(opcode, 5, 1);
+            unsigned _u = extract32(opcode, 6, 6);
+            unsigned _B = extract32(opcode, 12, 3);
+            unsigned _S = extract32(opcode, 15, 1);
+            unsigned _s = extract32(opcode, 17, 7);
+            unsigned _b = extract32(opcode, 24, 3);
+
+            TCGv b = cpu_r[(_B << 3) | _b];
+            TCGv u = tcg_const_local_i32(_u);
+            TCGv s = tcg_const_local_i32(sextract32((_S << 7) | _s, 0, 8));
+            ctx->opt.d = _N;
+
+            ret = arc_decode_major01_body(ctx, minor, b, u, s);
+
+            tcg_temp_free_i32(s);
+            tcg_temp_free_i32(u);
+        }
+    }
+
+    return ret;
+}
+
+
+/*
+    Load Register with Offset
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---------------+-+-----+-+---+---+-+------------+
+    | major   | b   |S[7:0]         |S|B    |D|aa |zz |x| A[5:0]     |
+    +---------+-----+---------------+-+-----+-+---+---+-+------------+
+    |0 0 0 1 0|b b b|s s s s s s s s|S|B B B|D|a a|Z Z|X|A A A A A A |
+    +---------+-----+---------------+-+-----+-+---+---+-+------------+
+*/
+static int arc_decode_major02(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+
+    unsigned _A = extract32(opcode, 0, 6);
+    unsigned _X = extract32(opcode, 6, 1);
+    unsigned _ZZ = extract32(opcode, 7, 2);
+    unsigned _AA = extract32(opcode, 9, 2);
+    unsigned _DI = extract32(opcode, 11, 1);
+    unsigned _B = extract32(opcode, 12, 3);
+    unsigned _S = extract32(opcode, 15, 1);
+    unsigned _s = extract32(opcode, 16, 8);
+    unsigned _b = extract32(opcode, 24, 3);
+
+    TCGv a = cpu_r[_A];
+    TCGv b = cpu_r[(_B << 3) | _b];
+    TCGv s = tcg_const_local_i32(sextract32((_S << 8) | _s, 0, 9));
+    ctx->opt.zz = _ZZ;
+    ctx->opt.x = _X;
+    ctx->opt.aa = _AA;
+    ctx->opt.di = _DI;
+
+    arc_decode_src(ctx, b);
+    ret = arc_gen_LD(ctx, a, b, s);
+
+    tcg_temp_free_i32(s);
+
+    return ret;
+}
+
+/*
+    Store Register with Offset
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---------------+-+-----+-----------+-+---+---+--+
+    | major   | b   | S[7:0]        |S| B   | C[5:0]    |D|aa |zz |R |
+    +---------+-----+---------------+-+-----+-----------+-+---+---+--+
+    |0 0 0 1 1|b b b|s s s s s s s s|S|B B B|C C C C C C|D|a a|Z Z|0 |
+    +---------+-----+---------------+-+-----+-----------+-+---+---+--+
+*/
+static int arc_decode_major03(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _ZZ = extract32(opcode, 1, 2);
+    unsigned _AA = extract32(opcode, 3, 2);
+    unsigned _DI = extract32(opcode, 5, 1);
+    unsigned _C = extract32(opcode, 6, 6);
+    unsigned _B = extract32(opcode, 12, 3);
+    unsigned _S = extract32(opcode, 15, 1);
+    unsigned _s = extract32(opcode, 16, 8);
+    unsigned _b = extract32(opcode, 24, 3);
+
+    TCGv b = cpu_r[(_B << 3) | _b];
+    TCGv c = cpu_r[_C];
+    TCGv s = tcg_const_local_i32(sextract32((_S << 8) | _s, 0, 9));
+    ctx->opt.zz = _ZZ;
+    ctx->opt.aa = _AA;
+    ctx->opt.di = _DI;
+
+    arc_decode_src(ctx, b);
+    arc_decode_src(ctx, c);
+    ret = arc_gen_ST(ctx, c, b, s);
+
+    tcg_temp_free_i32(s);
+    return ret;
+}
+
+/*
+    General Operations Register-Register
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   | b   |P  | minor     |F| B   | C[5:0]    | A[5:0]     |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    |0 0 1 0 0|b b b|0 0|i i i i i i|F|B B B|C C C C C C|A A A A A A |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+
+    General Operations Register with Unsigned 6-bit Immediate
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   | b   |P  | minor     |F| B   | U[5:0]    | A[5:0]     |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    |0 0 1 0 0|b b b|0 1|i i i i i i|F|B B B|U U U U U U|A A A A A A |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+
+    General Operations Register with Signed 12-bit Immediate
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   | b   |P  | minor     |F| B   | S[5:0]    | S[11:6]    |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    |0 0 1 0 0|b b b|0 1|i i i i i i|F|B B B|s s s s s s|S S S S S S |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+
+    General Operations Conditional Register
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+    | major   | b   |P  | minor     |F| B   | C[5:0]    |M|Q[4:0]    |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+    |0 0 1 0 0|b b b|1 1|i i i i i i|F|B B B|C C C C C C|0|Q Q Q Q Q |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+
+    General Operations Conditional Register with Unsigned 6-bit Immediate
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+    | major   | b   |P  | minor     |F| B   | U[5:0]    |M|Q[4:0]    |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+    |0 0 1 0 0|b b b|1 1|i i i i i i|F|B B B|U U U U U U|1|Q Q Q Q Q |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+
+    Load Register-Register
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+---+-+---+-+-+-----+-----------+------------+
+    | major   | b   |aa |1 1 0|zz |x|d|B    | C[5:0]    | A[5:0]     |
+    +---------+-----+---+-----+---+-+-+-----+-----------+------------+
+    |0 0 1 0 0|b b b|a a|1 1 0|Z Z|X|D|B B B|C C C C C C|A A A A A A |
+    +---------+-----+---+---+-+---+-+-+-----+-----------+------------+
+
+*/
+static int arc_decode_major04_zop(DisasCtxt *ctx,
+                                        unsigned _B, TCGv c)
+{
+    int ret = BS_NONE;
+
+    switch (_B) {
+        case 0x01: {
+            ret = arc_gen_SLEEP(ctx, c);
+            break;
+        }
+        case 0x02: {
+            ret = arc_gen_SWI(ctx);
+            break;
+        }
+        case 0x03: {
+            ret = arc_gen_SYNC(ctx);
+            break;
+        }
+        case 0x04: {
+            ret = arc_gen_RTIE(ctx);
+            break;
+        }
+        case 0x05: {
+            ret = arc_gen_BRK(ctx);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    return ret;
+}
+
+static int arc_decode_major04_sop(DisasCtxt *ctx,
+                                    unsigned _A, unsigned _B, TCGv b, TCGv c)
+{
+    int ret = BS_NONE;
+
+    switch (_A) {
+        case 0x00: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ASL(ctx, b, c);
+            break;
+        }
+        case 0x01: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ASR(ctx, b, c);
+            break;
+        }
+        case 0x02: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_LSR(ctx, b, c);
+            break;
+        }
+        case 0x03: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ROR(ctx, b, c);
+            break;
+        }
+        case 0x04: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_RRC(ctx, b, c);
+            break;
+        }
+        case 0x05: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SEXB(ctx, b, c);
+            break;
+        }
+        case 0x06: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SEXW(ctx, b, c);
+            break;
+        }
+        case 0x07: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_EXTB(ctx, b, c);
+            break;
+        }
+        case 0x08: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_EXTW(ctx, b, c);
+            break;
+        }
+        case 0x09: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ABS(ctx, b, c);
+            break;
+        }
+        case 0x0A: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_NOT(ctx, b, c);
+            break;
+        }
+        case 0x0B: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_RLC(ctx, b, c);
+            break;
+        }
+        case 0x0C: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_EX(ctx, b, c);
+            break;
+        }
+        case 0x3F: {
+            ret = arc_decode_major04_zop(ctx, _B, c);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    return ret;
+}
+static int arc_decode_major04_op(DisasCtxt *ctx,
+                           uint32_t opcode, TCGv a, TCGv b, TCGv c, unsigned _Q)
+{
+    int ret = BS_NONE;
+    unsigned _A = extract32(opcode, 0, 6);
+    unsigned _B = extract32(opcode, 12, 3);
+    unsigned _b = extract32(opcode, 24, 3);
+    unsigned minor = extract32(opcode, 16, 6);
+    TCGLabel *skip = gen_new_label();
+
+    _B = (_B << 3) | _b;
+
+    switch (minor) {
+        case    0x00: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ADD(ctx, a, b, c);
+            break;
+        }
+        case    0x01: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ADC(ctx, a, b, c);
+            break;
+        }
+        case    0x02: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SUB(ctx, a, b, c);
+            break;
+        }
+        case    0x03: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SBC(ctx, a, b, c);
+            break;
+        }
+        case    0x04: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_AND(ctx, a, b, c);
+            break;
+        }
+        case    0x05: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_OR(ctx, a, b, c);
+            break;
+        }
+        case    0x06: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BIC(ctx, a, b, c);
+            break;
+        }
+        case    0x07: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_XOR(ctx, a, b, c);
+            break;
+        }
+        case    0x08: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MAX(ctx, a, b, c);
+            break;
+        }
+        case    0x09: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MIN(ctx, a, b, c);
+            break;
+        }
+        case    0x0A: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MOV(ctx, b, c);
+            break;
+        }
+        case    0x0B: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_TST(ctx, b, c);
+            break;
+        }
+        case    0x0C: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_CMP(ctx, b, c);
+            break;
+        }
+        case    0x0D: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_CMP(ctx, c, b);
+            break;
+        }
+        case    0x0E: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_RSUB(ctx, a, b, c);
+            break;
+        }
+        case    0x0F: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BSET(ctx, a, b, c);
+            break;
+        }
+        case    0x10: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BCLR(ctx, a, b, c);
+            break;
+        }
+        case    0x11: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BTST(ctx, b, c);
+            break;
+        }
+        case    0x12: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BXOR(ctx, a, b, c);
+            break;
+        }
+        case    0x13: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_BMSK(ctx, a, b, c);
+            break;
+        }
+        case    0x14: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ADD1(ctx, a, b, c);
+            break;
+        }
+        case    0x15: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ADD2(ctx, a, b, c);
+            break;
+        }
+        case    0x16: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ADD3(ctx, a, b, c);
+            break;
+        }
+        case    0x17: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SUB1(ctx, a, b, c);
+            break;
+        }
+        case    0x18: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SUB2(ctx, a, b, c);
+            break;
+        }
+        case    0x19: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SUB3(ctx, a, b, c);
+            break;
+        }
+        case    0x1A: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MPY(ctx, a, b, c);
+            break;
+        }
+        case    0x1B: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MPYH(ctx, a, b, c);
+            break;
+        }
+        case    0x1C: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MPYHU(ctx, a, b, c);
+            break;
+        }
+        case    0x1D: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MPYU(ctx, a, b, c);
+            break;
+        }
+        case    0x20: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_J(ctx, c, ARC_COND_AL);
+            break;
+        }
+        case    0x21: {
+            ctx->opt.d = 1;
+            arc_decode_src(ctx, c);
+            ret = arc_gen_J(ctx, c, ARC_COND_AL);
+            break;
+        }
+        case    0x22: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_JL(ctx, c, _Q);
+            break;
+        }
+        case    0x23: {
+            ctx->opt.d = 1;
+            arc_decode_src(ctx, c);
+            ret = arc_gen_JL(ctx, c, _Q);
+            break;
+        }
+        case    0x28: {
+            ret = arc_gen_LPcc(ctx, c, _Q);
+            break;
+        }
+        case    0x29: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_FLAG(ctx, c);
+            break;
+        }
+        case    0x2A: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_LR(ctx, b, c);
+            break;
+        }
+        case    0x2B: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SR(ctx, b, c);
+            break;
+        }
+        case    0x2F: {
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            ret = arc_decode_major04_sop(ctx, _A, _B, b, c);
+            break;
+        }
+        case    0x30 ... 0x37: {
+            unsigned _DI = extract32(opcode, 15, 1);
+            unsigned _X = extract32(opcode, 16, 1);
+            unsigned _ZZ = extract32(opcode, 17, 2);
+            unsigned _AA = extract32(opcode, 22, 2);
+
+            ctx->opt.zz = _ZZ;
+            ctx->opt.x = _X;
+            ctx->opt.aa = _AA;
+            ctx->opt.di = _DI;
+
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_LD(ctx, a, b, c);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    gen_set_label(skip);
+
+    return ret;
+}
+
+static int arc_decode_major04(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _A = extract32(opcode, 0, 6);
+    unsigned _B = extract32(opcode, 12, 3);
+    unsigned _C = extract32(opcode, 6, 6);
+    unsigned _F = extract32(opcode, 15, 1);
+    unsigned _Q = extract32(opcode, 0, 5);
+    unsigned _S = extract32(opcode, 0, 6);
+    unsigned _b = extract32(opcode, 24, 3);
+    unsigned _s = extract32(opcode, 6, 6);
+    unsigned _u = extract32(opcode, 6, 6);
+
+    _B = (_B << 3) | _b;
+
+    switch (extract32(opcode, 22, 2)) {
+        case 0x00: {
+            /*  General Operations Register-Register    */
+
+            TCGv a = cpu_r[_A];
+            TCGv b = cpu_r[_B];
+            TCGv c = cpu_r[_C];
+            ctx->opt.f = _F;
+
+            ret = arc_decode_major04_op(ctx, opcode, a, b, c, ARC_COND_AL);
+
+            break;
+        }
+        case 0x01: {
+            /*  General Operations Register with Unsigned 6-bit Immediate   */
+
+            TCGv a = cpu_r[_A];
+            TCGv b = cpu_r[_B];
+            TCGv u = tcg_const_local_i32(_u);
+            ctx->opt.f = _F;
+
+            ret = arc_decode_major04_op(ctx, opcode, a, b, u, ARC_COND_AL);
+
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x02: {
+            /*  General Operations Register with Signed 12-bit Immediate    */
+
+            TCGv b = cpu_r[_B];
+            TCGv s = tcg_const_local_i32(sextract32((_S << 6) | _s, 0, 12));
+            ctx->opt.f = _F;
+
+            ret = arc_decode_major04_op(ctx, opcode, b, b, s, ARC_COND_AL);
+
+            tcg_temp_free_i32(s);
+            break;
+        }
+        case 0x03: {
+            if (extract32(opcode, 5, 1) == 0) {
+                /*  General Operations Conditional Register */
+
+                TCGv b = cpu_r[_B];
+                TCGv c = cpu_r[_C];
+                ctx->opt.f = _F;
+
+                ret = arc_decode_major04_op(ctx, opcode, b, b, c, _Q);
+            } else {
+                TCGv b = cpu_r[_B];
+                TCGv u = tcg_const_local_i32(_u);
+
+                ctx->opt.f = _F;
+
+                ret = arc_decode_major04_op(ctx, opcode, b, b, u, _Q);
+            }
+
+            break;
+        }
+    }
+    return ret;
+}
+
+/*
+    Extension ALU Operation, Register-Register
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   |b    |P  | minor     |F|B    | C[5:0]    | A[5:0]     |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    |0 0 1 0 1|b b b|0 0|i i i i i i|F|B B B|C C C C C C|A A A A A A |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+
+    Extension ALU Operation, Register with Unsigned 6-bit Immediate
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   |b    |P  | minor     |F|B    | U[5:0]    | A[5:0]     |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    |0 0 1 0 1|b b b|0 1|i i i i i i|F|B B B|U U U U U U|A A A A A A |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+
+    Extension ALU Operation, Register with Signed 12-bit Immediate
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   |b    |P  | minor     |F|B    | S[5:0]    | S[11:6]    |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    |0 0 1 0 1|b b b|1 0|i i i i i i|F|B B B|s s s s s s|S S S S S S |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+
+    Extension ALU Operation, Conditional Register
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   |b    |P  | minor     |F|B    | C[5:0]    |M| Q[5:0]   |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+    |0 0 1 0 1|b b b|1 1|i i i i i i|F|B B B|C C C C C C|0|Q Q Q Q Q |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+
+    Extension ALU Operation, Conditional Register with Unsigned 6-bit Immediate
+    +----------------------------------------------------------------+
+    |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+---+-----------+-+-----+-----------+------------+
+    | major   |b    |P  | minor     |F|B    | U[5:0]    |M| Q[5:0]   |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+    |0 0 1 0 1|b b b|1 1|i i i i i i|F|B B B|U U U U U U|1|Q Q Q Q Q |
+    +---------+-----+---+-----------+-+-----+-----------+-+----------+
+
+*/
+static int arc_decode_major05_zop(DisasCtxt *ctx,
+                                                            unsigned _B, TCGv c)
 {
-    return BS_STOP;
+    int ret = BS_NONE;
+
+    ret = arc_gen_INVALID(ctx);
+
+    return ret;
 }
 
+static int arc_decode_major05_sop(DisasCtxt *ctx,
+                                       unsigned _A, unsigned _B, TCGv b, TCGv c)
+{
+    int ret = BS_NONE;
+    switch (_A) {
+        case 0x00: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SWAP(ctx, b, c);
+            break;
+        }
+        case 0x01: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_NORM(ctx, b, c);
+            break;
+        }
+        case 0x02: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SAT16(ctx, b, c);
+            break;
+        }
+        case 0x03: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_RND16(ctx, b, c);
+            break;
+        }
+        case 0x04: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ABSSW(ctx, b, c);
+            break;
+        }
+        case 0x05: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ABSS(ctx, b, c);
+            break;
+        }
+        case 0x06: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_NEGSW(ctx, b, c);
+            break;
+        }
+        case 0x07: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_NEGS(ctx, b, c);
+            break;
+        }
+        case 0x08: {
+            arc_decode_src(ctx, c);
+            ret = arc_gen_NORMW(ctx, b, c);
+            break;
+        }
+        case 0x3F: {
+            ret = arc_decode_major05_zop(ctx, _B, c);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+    return ret;
+}
+static int arc_decode_major05_op(DisasCtxt *ctx,
+                                        uint32_t opcode, TCGv a, TCGv b, TCGv c)
+{
+    int ret = BS_NONE;
+    unsigned _i = extract32(opcode, 16, 6);
+    unsigned _A = extract32(opcode, 0, 6);
+    unsigned _B = extract32(opcode, 12, 3);
+    unsigned _b = extract32(opcode, 24, 3);
+
+    _B = (_B << 3) | _b;
+
+    switch (_i) {
+        case 0x00: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ASLm(ctx, a, b, c);
+            break;
+        }
+        case 0x01: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_LSRm(ctx, a, b, c);
+            break;
+        }
+        case 0x02: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ASRm(ctx, a, b, c);
+            break;
+        }
+        case 0x03: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_RORm(ctx, a, b, c);
+            break;
+        }
+        case 0x04: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MUL64(ctx, a, b, c);
+            break;
+        }
+        case 0x05: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_MULU64(ctx, a, b, c);
+            break;
+        }
+        case 0x06: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ADDS(ctx, a, b, c);
+            break;
+        }
+        case 0x07: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SUBS(ctx, a, b, c);
+            break;
+        }
+        case 0x08: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_DIVAW(ctx, a, b, c);
+            break;
+        }
+        case 0x0A: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ASLS(ctx, a, b, c);
+            break;
+        }
+        case 0x0B: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ASRS(ctx, a, b, c);
+            break;
+        }
+        case 0x28: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_ADDSDW(ctx, a, b, c);
+            break;
+        }
+        case 0x29: {
+            arc_decode_src(ctx, b);
+            arc_decode_src(ctx, c);
+            ret = arc_gen_SUBSDW(ctx, a, b, c);
+            break;
+        }
+        case 0x2F: {
+            ret = arc_decode_major05_sop(ctx, _A, _B, b, c);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    return ret;
+}
+
+static int arc_decode_major05(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _A = extract32(opcode, 0, 6);
+    unsigned _B = extract32(opcode, 12, 3);
+    unsigned _C = extract32(opcode, 6, 6);
+    unsigned _F = extract32(opcode, 15, 1);
+    unsigned _Q = extract32(opcode, 0, 5);
+    unsigned _S = extract32(opcode, 0, 6);
+    unsigned _b = extract32(opcode, 24, 3);
+    unsigned _s = extract32(opcode, 6, 6);
+    unsigned _u = extract32(opcode, 6, 6);
+
+    _B = (_B << 3) | _b;
+
+    switch (extract32(opcode, 22, 2)) {
+        case 0x00: {
+            /*
+                Extension ALU Operation, Register-Register
+            */
+            TCGv a = cpu_r[_A];
+            TCGv b = cpu_r[_B];
+            TCGv c = cpu_r[_C];
+            ctx->opt.f = _F;
+
+            ret = arc_decode_major05_op(ctx, opcode, a, b, c);
+            break;
+        }
+        case 0x01: {
+            /*
+                Extension ALU Operation, Register with Unsigned 6-bit Immediate
+            */
+            TCGv a = cpu_r[_A];
+            TCGv b = cpu_r[_B];
+            TCGv u = tcg_const_local_i32(_u);
+            ctx->opt.f = _F;
+
+            ret = arc_decode_major05_op(ctx, opcode, a, b, u);
+
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x02: {
+            /*
+                Extension ALU Operation, Register with Signed 12-bit Immediate
+            */
+            TCGv b = cpu_r[_B];
+            TCGv s = tcg_const_local_i32(sextract32((_S << 6) | _s, 0, 12));
+            ctx->opt.f = _F;
+
+            ret = arc_decode_major05_op(ctx, opcode, b, b, s);
+
+            tcg_temp_free_i32(s);
+            break;
+        }
+        case 0x03: {
+            ctx->opt.f = _F;
+            TCGLabel *skip = gen_new_label();
+
+            arc_gen_jump_ifnot(ctx, _Q, skip);
+
+            if (extract32(opcode, 5, 1) == 0) {
+                /*
+                    Extension ALU Operation, Conditional Register
+                */
+                TCGv b = cpu_r[_B];
+                TCGv c = cpu_r[_C];
+
+                ret = arc_decode_major05_op(ctx, opcode, b, b, c);
+
+            } else {
+                /*
+                    Extension ALU Operation, Conditional Register with
+                    Unsigned 6-bit Immediate
+                */
+                TCGv b = cpu_r[_B];
+                TCGv u = tcg_const_local_i32(_u);
+
+                ret = arc_decode_major05_op(ctx, opcode, b, b, u);
+
+                tcg_temp_free_i32(u);
+            }
+
+            gen_set_label(skip);
+            break;
+        }
+    }
+    return ret;
+}
+
+/*
+
+    Load /Add Register-Register
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+---+------+
+    | major   | b   | c   | i | a    |
+    +---------+-----+-----+---+------+
+    |0 1 1 0 0|b b b|c c c|i i|a a a |
+    +---------+-----+-----+---+------+
+*/
+static int arc_decode_major0C(DisasCtxt *ctx, uint32_t opcode)
+{
+    unsigned _a = extract32(opcode, 0, 3);
+    unsigned _c = extract32(opcode, 5, 3);
+    unsigned _b = extract32(opcode, 8, 3);
+    unsigned _i = extract32(opcode, 3, 2);
+    int ret = BS_NONE;
+
+    TCGv a = cpu_r[(_a / 4) * 12 + _a % 4];
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv c = cpu_r[(_c / 4) * 12 + _c % 4];
+
+    switch (_i) {
+        case 0x00: {
+            ctx->opt.zz = 0;
+            ret = arc_gen_LD(ctx, a, b, c);
+            break;
+        }
+        case 0x01: {
+            ctx->opt.zz = 1;
+            ret = arc_gen_LD(ctx, a, b, c);
+            break;
+        }
+        case 0x02: {
+            ctx->opt.zz = 2;
+            ret = arc_gen_LD(ctx, a, b, c);
+            break;
+        }
+        case 0x03: {
+            ret = arc_gen_ADD(ctx, a, b, c);
+            break;
+        }
+    }
+    return ret;
+}
+
+/*
+
+    Load /Add Register-Register
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+---+------+
+    | major   | b   | c   | i | u    |
+    +---------+-----+-----+---+------+
+    |0 1 1 0 1|b b b|c c c|i i|u u u |
+    +---------+-----+-----+---+------+
+*/
+static int arc_decode_major0D(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _u = extract32(opcode, 0, 3);
+    unsigned _c = extract32(opcode, 5, 3);
+    unsigned _b = extract32(opcode, 8, 3);
+    unsigned _i = extract32(opcode, 3, 2);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv c = cpu_r[(_c / 4) * 12 + _c % 4];
+    TCGv u = tcg_const_local_i32(_u);
+
+    switch (_i) {
+        case 0x00: {
+            ret = arc_gen_ADD(ctx, c, b, u);
+            break;
+        }
+        case 0x01: {
+            ret = arc_gen_SUB(ctx, c, b, u);
+            break;
+        }
+        case 0x02: {
+            ret = arc_gen_ASLm(ctx, c, b, u);
+            break;
+        }
+        case 0x03: {
+            ret = arc_gen_ASRm(ctx, c, b, u);
+            break;
+        }
+    }
+
+    tcg_temp_free_i32(u);
+    return ret;
+}
+
+/*
+
+    Mov/Cmp/Add with High Register
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+---+------+
+    | major   | b   | h   | i | H    |
+    +---------+-----+-----+---+------+
+    |0 1 1 1 0|b b b|h h h|i i|H H H |
+    +---------+-----+-----+---+------+
+*/
+static int arc_decode_major0E(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _H = extract32(opcode, 0, 3);
+    unsigned _h = extract32(opcode, 5, 3);
+    unsigned _b = extract32(opcode, 8, 3);
+    unsigned _i = extract32(opcode, 3, 2);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv h = cpu_r[(_H << 3) | _h];
+
+    switch (_i) {
+        case 0x00: {
+            arc_decode_src(ctx, h);
+            ret = arc_gen_ADD(ctx, b, b, h);
+            break;
+        }
+        case 0x01: {
+            arc_decode_src(ctx, h);
+            ret = arc_gen_MOV(ctx, b, h);
+            break;
+        }
+        case 0x02: {
+            arc_decode_src(ctx, h);
+            ret = arc_gen_CMP(ctx, b, h);
+            break;
+        }
+        case 0x03: {
+            ret = arc_gen_MOV(ctx, h, b);
+            break;
+        }
+    }
+
+    return ret;
+}
+
+/*
+
+    General Operations, register-register
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+----------+
+    | major   | b   | c   | i        |
+    +---------+-----+-----+----------+
+    |0 1 1 1 1|b b b|c c c|i i i i i |
+    +---------+-----+-----+----------+
+
+    General Operations, register
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+----------+
+    | major   | b   | i   | 0        |
+    +---------+-----+-----+----------+
+    |0 1 1 1 1|b b b|i i i|0 0 0 0 0 |
+    +---------+-----+-----+----------+
+
+    General Operations, no register
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+----------+
+    | major   | i   | 7   | 0        |
+    +---------+-----+-----+----------+
+    |0 1 1 1 1|i i i|1 1 1|0 0 0 0 0 |
+    +---------+-----+-----+----------+
+*/
+static int arc_decode_major0F_zop(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _i = extract32(opcode, 8, 3);
+
+    switch (_i) {
+        case 0x00: {
+            ret = arc_gen_NOP(ctx);
+            break;
+        }
+        case 0x01: {
+            ret = arc_gen_UNIMP(ctx);
+            break;
+        }
+        case 0x04: {
+            ret = arc_gen_J(ctx, cpu_blink, ARC_COND_EQ);
+            break;
+        }
+        case 0x05: {
+            ret = arc_gen_J(ctx, cpu_blink, ARC_COND_NE);
+            break;
+        }
+        case 0x06: {
+            ret = arc_gen_J(ctx, cpu_blink, ARC_COND_AL);
+            break;
+        }
+        case 0x07: {
+            ctx->opt.d = 1;
+            ret = arc_gen_J(ctx, cpu_blink, ARC_COND_AL);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    return ret;
+}
+
+static int arc_decode_major0F_sop(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _i = extract32(opcode, 5, 3);
+    unsigned _b = extract32(opcode, 8, 3);
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    switch (_i) {
+        case 0x00: {
+            ret = arc_gen_J(ctx, b, ARC_COND_AL);
+            break;
+        }
+        case 0x01: {
+            ctx->opt.d = 1;
+            ret = arc_gen_J(ctx, b, ARC_COND_AL);
+            break;
+        }
+        case 0x02: {
+            ret = arc_gen_JL(ctx, b, ARC_COND_AL);
+            break;
+        }
+        case 0x03: {
+            ctx->opt.d = 1;
+            ret = arc_gen_JL(ctx, b, ARC_COND_AL);
+            break;
+        }
+        case 0x06: {
+            TCGLabel *skip = gen_new_label();
+
+            arc_gen_jump_ifnot(ctx, ARC_COND_NE, skip);
+
+            ret = arc_gen_SUB(ctx, b, b, b);
+
+            gen_set_label(skip);
+
+            break;
+        }
+        case 0x07: {
+            ret = arc_decode_major0F_zop(ctx, opcode);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    return ret;
+}
+
+static int arc_decode_major0F(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _c = extract32(opcode, 5, 3);
+    unsigned _b = extract32(opcode, 8, 3);
+    unsigned _i = extract32(opcode, 0, 5);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv c = cpu_r[(_c / 4) * 12 + _c % 4];
+
+    switch (_i) {
+        case 0x00: {
+            ret = arc_decode_major0F_sop(ctx, opcode);
+            break;
+        }
+        case 0x02: {
+            ret = arc_gen_SUB(ctx, b, b, c);
+            break;
+        }
+        case 0x04: {
+            ret = arc_gen_AND(ctx, b, b, c);
+            break;
+        }
+        case 0x05: {
+            ret = arc_gen_OR(ctx, b, b, c);
+            break;
+        }
+        case 0x06: {
+            ret = arc_gen_BIC(ctx, b, b, c);
+            break;
+        }
+        case 0x07: {
+            ret = arc_gen_XOR(ctx, b, b, c);
+            break;
+        }
+        case 0x0B: {
+            ret = arc_gen_TST(ctx, b, c);
+            break;
+        }
+        case 0x0C: {
+            ret = arc_gen_MUL64(ctx, b, b, c);
+            break;
+        }
+        case 0x0D: {
+            ret = arc_gen_SEXB(ctx, b, c);
+            break;
+        }
+        case 0x0E: {
+            ret = arc_gen_SEXW(ctx, b, c);
+            break;
+        }
+        case 0x0F: {
+            ret = arc_gen_EXTB(ctx, b, c);
+            break;
+        }
+        case 0x10: {
+            ret = arc_gen_EXTW(ctx, b, c);
+            break;
+        }
+        case 0x11: {
+            ret = arc_gen_ABS(ctx, b, c);
+            break;
+        }
+        case 0x12: {
+            ret = arc_gen_NOT(ctx, b, c);
+            break;
+        }
+        case 0x13: {
+            ret = arc_gen_NEG(ctx, b, c);
+            break;
+        }
+        case 0x14: {
+            ret = arc_gen_ADD1(ctx, b, b, c);
+            break;
+        }
+        case 0x15: {
+            ret = arc_gen_ADD2(ctx, b, b, c);
+            break;
+        }
+        case 0x16: {
+            ret = arc_gen_ADD3(ctx, b, b, c);
+            break;
+        }
+        case 0x18: {
+            ret = arc_gen_ASLm(ctx, b, b, c);
+            break;
+        }
+        case 0x19: {
+            ret = arc_gen_LSRm(ctx, b, b, c);
+            break;
+        }
+        case 0x1A: {
+            ret = arc_gen_ASRm(ctx, b, b, c);
+            break;
+        }
+        case 0x1B: {
+            ret = arc_gen_ASL(ctx, b, c);
+            break;
+        }
+        case 0x1C: {
+            ret = arc_gen_ASR(ctx, b, c);
+            break;
+        }
+        case 0x1D: {
+            ret = arc_gen_LSR(ctx, b, c);
+            break;
+        }
+        case 0x1E: {
+            unsigned _u = extract32(opcode, 5, 6);
+            TCGv u = tcg_const_local_i32(_u);
+            ret = arc_gen_TRAP(ctx, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x1F: {
+            ret = arc_gen_BRK(ctx);
+            break;
+        }
+        default: {
+            ret = arc_gen_INVALID(ctx);
+        }
+    }
+
+    return ret;
+}
+
+/*
+    Load/Store with Offset
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+----------+
+    | major   | b   | c   | u        |
+    +---------+-----+-----+----------+
+    |I I I I I|b b b|c c c|u u u u u |
+    +---------+-----+-----+----------+
+
+*/
+static int arc_decode_major10_16(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _i = extract32(opcode, 11, 5);
+    unsigned _u = extract32(opcode, 0, 5);
+    unsigned _c = extract32(opcode, 5, 3);
+    unsigned _b = extract32(opcode, 8, 3);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv c = cpu_r[(_c / 4) * 12 + _c % 4];
+    TCGv u;
+
+    switch (_i) {
+        case 0x10: {
+            ctx->opt.zz = 0;
+            u = tcg_const_local_i32(_u << 2);
+            ret = arc_gen_LD(ctx, c, b, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x11: {
+            ctx->opt.zz = 1;
+            u = tcg_const_local_i32(_u);
+            ret = arc_gen_LD(ctx, c, b, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x12: {
+            ctx->opt.zz = 2;
+            u = tcg_const_local_i32(_u << 1);
+            ret = arc_gen_LD(ctx, c, b, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x13: {
+            ctx->opt.zz = 2;
+            ctx->opt.x = 1;
+            u = tcg_const_local_i32(_u << 1);
+            ret = arc_gen_LD(ctx, c, b, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x14: {
+            ctx->opt.zz = 0;
+            u = tcg_const_local_i32(_u << 2);
+            ret = arc_gen_ST(ctx, c, b, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x15: {
+            ctx->opt.zz = 1;
+            u = tcg_const_local_i32(_u);
+            ret = arc_gen_ST(ctx, c, b, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+        case 0x16: {
+            ctx->opt.zz = 2;
+            u = tcg_const_local_i32(_u << 1);
+            ret = arc_gen_ST(ctx, c, b, u);
+            tcg_temp_free_i32(u);
+            break;
+        }
+    }
+
+
+    return ret;
+}
+
+/*
+    Shift/Subtract/Bit Immediate
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+----------+
+    | major   | b   | i   | u        |
+    +---------+-----+-----+----------+
+    |1 0 1 1 1|b b b|i i i|u u u u u |
+    +---------+-----+-----+----------+
+
+*/
+static int arc_decode_major17(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _i = extract32(opcode, 5, 3);
+    unsigned _u = extract32(opcode, 0, 5);
+    unsigned _b = extract32(opcode, 8, 3);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv u = tcg_const_local_i32(_u);
+
+    switch (_i) {
+        case 0x00: {
+            ret = arc_gen_ASLm(ctx, b, b, u);
+            break;
+        }
+        case 0x01: {
+            ret = arc_gen_LSRm(ctx, b, b, u);
+            break;
+        }
+        case 0x02: {
+            ret = arc_gen_ASRm(ctx, b, b, u);
+            break;
+        }
+        case 0x03: {
+            ret = arc_gen_SUB(ctx, b, b, u);
+            break;
+        }
+        case 0x04: {
+            ret = arc_gen_BSET(ctx, b, b, u);
+            break;
+        }
+        case 0x05: {
+            ret = arc_gen_BCLR(ctx, b, b, u);
+            break;
+        }
+        case 0x06: {
+            ret = arc_gen_BMSK(ctx, b, b, u);
+            break;
+        }
+        case 0x07: {
+            ret = arc_gen_BTST(ctx, b, u);
+            break;
+        }
+    }
+
+    tcg_temp_free_i32(u);
+
+    return ret;
+}
+
+/*
+    Stack Pointer Based Instructions
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-----+----------+
+    | major   | b   | i   | u        |
+    +---------+-----+-----+----------+
+    |1 1 0 0 0|b b b|i i i|u u u u u |
+    +---------+-----+-----+----------+
+
+*/
+static int arc_decode_major18(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _i = extract32(opcode, 5, 3);
+    unsigned _u = extract32(opcode, 0, 5);
+    unsigned _b = extract32(opcode, 8, 3);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv u = tcg_const_local_i32(_u << 2);
+
+    switch (_i) {
+        case 0x00: {
+            ret = arc_gen_LD(ctx, b, cpu_sp, u);
+            break;
+        }
+        case 0x01: {
+            ctx->opt.zz = 1;
+            ret = arc_gen_LD(ctx, b, cpu_sp, u);
+            break;
+        }
+        case 0x02: {
+            ret = arc_gen_ST(ctx, b, cpu_sp, u);
+            break;
+        }
+        case 0x03: {
+            ctx->opt.zz = 1;
+            ret = arc_gen_ST(ctx, b, cpu_sp, u);
+            break;
+        }
+        case 0x04: {
+            ret = arc_gen_ADD(ctx, b, cpu_sp, u);
+            break;
+        }
+        case 0x05: {
+            switch (_b) {
+                case 0x00: {
+                    ret = arc_gen_ADD(ctx, cpu_sp, cpu_sp, u);
+                    break;
+                }
+                case 0x01: {
+                    ret = arc_gen_SUB(ctx, cpu_sp, cpu_sp, u);
+                    break;
+                }
+                default: {
+                    ret = arc_gen_INVALID(ctx);
+                }
+            }
+            break;
+        }
+        case 0x06: {
+            switch (_u) {
+                case 0x01: {
+                    ret = arc_gen_POP(ctx, b);
+                    break;
+                }
+                case 0x11: {
+                    ret = arc_gen_POP(ctx, cpu_blink);
+                    break;
+                }
+                default: {
+                    ret = arc_gen_INVALID(ctx);
+                }
+            }
+            break;
+        }
+        case 0x07: {
+            switch (_u) {
+                case 0x01: {
+                    ret = arc_gen_PUSH(ctx, b);
+                    break;
+                }
+                case 0x11: {
+                    ret = arc_gen_PUSH(ctx, cpu_blink);
+                    break;
+                }
+                default: {
+                    ret = arc_gen_INVALID(ctx);
+                }
+            }
+            break;
+        }
+    }
+
+    tcg_temp_free_i32(u);
+
+    return ret;
+}
+
+/*
+    Stack Pointer Based Instructions
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+---+------------------+
+    | major   | i | s                |
+    +---------+---+------------------+
+    |1 1 0 0 1|i i|s s s s s s s s s |
+    +---------+---+------------------+
+*/
+static int arc_decode_major19(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    signed _s = sextract32(opcode, 0, 9);
+    unsigned _i = extract32(opcode, 9, 2);
+    TCGv s;
+
+    switch (_i) {
+        case 0x00: {
+            ctx->opt.zz = 0;
+            s = tcg_const_local_i32(_s << 2);
+            ret = arc_gen_LD(ctx, cpu_r[0], cpu_gp, s);
+            break;
+        }
+        case 0x01: {
+            ctx->opt.zz = 1;
+            s = tcg_const_local_i32(_s);
+            ret = arc_gen_LD(ctx, cpu_r[0], cpu_gp, s);
+            break;
+        }
+        case 0x02: {
+            ctx->opt.zz = 2;
+            s = tcg_const_local_i32(_s << 1);
+            ret = arc_gen_LD(ctx, cpu_r[0], cpu_gp, s);
+            break;
+        }
+        case 0x03: {
+            s = tcg_const_local_i32(_s << 2);
+            ret = arc_gen_ADD(ctx, cpu_r[0], cpu_gp, s);
+            break;
+        }
+    }
+
+    tcg_temp_free_i32(s);
+    return ret;
+}
+
+/*
+    Load PCL-Relative
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+----------------+
+    | major   | b   | s              |
+    +---------+-----+----------------+
+    |1 1 0 1 0|b b b|s s s s s s s s |
+    +---------+-----+----------------+
+
+*/
+static int arc_decode_major1A(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _u = extract32(opcode, 0, 8);
+    unsigned _b = extract32(opcode, 8, 3);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv u = tcg_const_local_i32(_u << 2);
+
+    ret = arc_gen_LD(ctx, b, cpu_pcl, u);
+
+    tcg_temp_free_i32(u);
+    return ret;
+}
+
+/*
+    Move Immediate
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+----------------+
+    | major   | b   | u              |
+    +---------+-----+----------------+
+    |1 1 0 1 1|b b b|u u u u u u u u |
+    +---------+-----+----------------+
+*/
+static int arc_decode_major1B(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _u = extract32(opcode, 0, 8);
+    unsigned _b = extract32(opcode, 8, 3);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv u = tcg_const_local_i32(_u);
+
+    ret = arc_gen_MOV(ctx, b, u);
+
+    tcg_temp_free_i32(u);
+    return ret;
+}
+
+/*
+    ADD/CMP Immediate
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-+--------------+
+    | major   | b   |i| u            |
+    +---------+-----+-+--------------+
+    |1 1 1 0 0|b b b|i|u u u u u u u |
+    +---------+-----+-+--------------+
+*/
+static int arc_decode_major1C(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    unsigned _u = extract32(opcode, 0, 7);
+    unsigned _b = extract32(opcode, 8, 3);
+    unsigned _i = extract32(opcode, 7, 1);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv u = tcg_const_local_i32(_u);
+
+    if (_i == 0) {
+        ret = arc_gen_ADD(ctx, b, b, u);
+    } else {
+        ret = arc_gen_CMP(ctx, b, u);
+    }
+
+    tcg_temp_free_i32(u);
+    return ret;
+}
+
+/*
+    Branch on Compare Register with Zero
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+-----+-+--------------+
+    | major   | b   |i| s            |
+    +---------+-----+-+--------------+
+    |1 1 1 0 1|b b b|i|s s s s s s s |
+    +---------+-----+-+--------------+
+*/
+static int arc_decode_major1D(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    signed _s = sextract32(opcode, 0, 7);
+    unsigned _b = extract32(opcode, 8, 3);
+    unsigned _i = extract32(opcode, 7, 1);
+
+    TCGv b = cpu_r[(_b / 4) * 12 + _b % 4];
+    TCGv s = tcg_const_local_i32(_s);
+
+    if (_i == 0) {
+        ret = arc_gen_BR(ctx, b, ctx->zero, s, TCG_COND_EQ);
+    } else {
+        ret = arc_gen_BR(ctx, b, ctx->zero, s, TCG_COND_NE);
+    }
+
+    tcg_temp_free_i32(s);
+    return ret;
+}
+
+/*
+    Branch on Compare Register with Zero
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+---+------------------+
+    | major   | b | s                |
+    +---------+---+------------------+
+    |1 1 1 1 0|i i|s s s s s s s s s |
+    +---------+---+------------------+
+*/
+static int arc_decode_major1E(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    signed _s = sextract32(opcode, 0, 9);
+    unsigned _i = extract32(opcode, 9, 2);
+    TCGv s = tcg_const_local_i32(_s);
+
+    switch (_i) {
+        case 0x00: {
+            ret = arc_gen_B(ctx, s, ARC_COND_AL);
+            break;
+        }
+        case 0x01: {
+            ret = arc_gen_B(ctx, s, ARC_COND_EQ);
+            break;
+        }
+        case 0x02: {
+            ret = arc_gen_B(ctx, s, ARC_COND_NE);
+            break;
+        }
+        case 0x03: {
+            signed _s = sextract32(opcode, 0, 6);
+            unsigned _i = extract32(opcode, 5, 3);
+            TCGv s = tcg_const_local_i32(_s);
+
+            switch (_i) {
+                case 0x00: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_GT);
+                    break;
+                }
+                case 0x01: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_GE);
+                    break;
+                }
+                case 0x02: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_LT);
+                    break;
+                }
+                case 0x03: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_LE);
+                    break;
+                }
+                case 0x04: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_HI);
+                    break;
+                }
+                case 0x05: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_HS);
+                    break;
+                }
+                case 0x06: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_LO);
+                    break;
+                }
+                case 0x07: {
+                    ret = arc_gen_B(ctx, s, ARC_COND_LS);
+                    break;
+                }
+            }
+
+            tcg_temp_free_i32(s);
+            break;
+        }
+    }
+
+    tcg_temp_free_i32(s);
+    return ret;
+}
+
+/*
+    Branch on Compare Register with Zero
+    +--------------------------------+
+    |1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 |
+    |5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
+    +---------+----------------------+
+    | major   | s                    |
+    +---------+----------------------+
+    |1 1 1 1 1|s s s s s s s s s s s |
+    +---------+----------------------+
+*/
+static int arc_decode_major1F(DisasCtxt *ctx, uint32_t opcode)
+{
+    int ret = BS_NONE;
+    signed _s = sextract32(opcode, 0, 11);
+
+    TCGv s = tcg_const_local_i32(_s);
+
+    ret = arc_gen_BL(ctx, s, ARC_COND_AL);
+
+    tcg_temp_free_i32(s);
+    return ret;
+}
+
+int arc_decode(DisasCtxt *ctx)
+{
+    unsigned curr_major;
+    uint32_t curr_opcode;
+
+    unsigned next_major;
+    uint32_t next_opcode;
+
+    decode_f    decode[32] = {
+        [0x00]  = arc_decode_major00,
+        [0x01]  = arc_decode_major01,
+        [0x02]  = arc_decode_major02,
+        [0x03]  = arc_decode_major03,
+        [0x04]  = arc_decode_major04,
+        [0x05]  = arc_decode_major05,
+
+        [0x06]  = arc_decode_invalid,
+        [0x07]  = arc_decode_invalid,
+        [0x08]  = arc_decode_invalid,
+        [0x09]  = arc_decode_invalid,
+        [0x0a]  = arc_decode_invalid,
+        [0x0b]  = arc_decode_invalid,
+
+        [0x0c]  = arc_decode_major0C,
+        [0x0d]  = arc_decode_major0D,
+        [0x0e]  = arc_decode_major0E,
+        [0x0f]  = arc_decode_major0F,
+
+        [0x10]  = arc_decode_major10_16,
+        [0x11]  = arc_decode_major10_16,
+        [0x12]  = arc_decode_major10_16,
+        [0x13]  = arc_decode_major10_16,
+        [0x14]  = arc_decode_major10_16,
+        [0x15]  = arc_decode_major10_16,
+        [0x16]  = arc_decode_major10_16,
+
+        [0x17]  = arc_decode_major17,
+        [0x18]  = arc_decode_major18,
+        [0x19]  = arc_decode_major19,
+        [0x1a]  = arc_decode_major1A,
+        [0x1b]  = arc_decode_major1B,
+        [0x1c]  = arc_decode_major1C,
+        [0x1d]  = arc_decode_major1D,
+        [0x1e]  = arc_decode_major1E,
+        [0x1f]  = arc_decode_major1F,
+
+    };
+    memset(&ctx->opt, 0, sizeof(ctx->opt));
+
+    /*
+        1. get current opcode
+        2. set npc
+    */
+    curr_opcode = cpu_ldl_code(ctx->env, ctx->cpc);
+    curr_major  = extract32(curr_opcode, 11, 5);
+
+    if (curr_major <= 5) {
+        curr_opcode = (curr_opcode << 16) | (curr_opcode >> 16);
+        ctx->npc = ctx->cpc + 4;
+    } else {
+        ctx->npc = ctx->cpc + 2;
+    }
+
+    /*
+        3. set dpc (used by BL)
+    */
+    next_opcode = cpu_ldl_code(ctx->env, ctx->npc);
+    next_major  = extract32(next_opcode, 11, 5);
+    if (next_major <= 5) {
+        ctx->dpc = ctx->npc + 4;
+    } else {
+        ctx->dpc = ctx->npc + 2;
+    }
+
+    ctx->pcl = ctx->cpc & 0xfffffffc;
+
+    return  decode[curr_major](ctx, curr_opcode);
+}
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH RFC v1 29/29] target-arc: sample board
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
                   ` (27 preceding siblings ...)
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 28/29] target-arc: decode Michael Rolnik
@ 2016-09-08 22:32 ` Michael Rolnik
  2016-09-16 15:01   ` [Qemu-devel] " Alexey Brodkin
  29 siblings, 0 replies; 56+ messages in thread
From: Michael Rolnik @ 2016-09-08 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 MAINTAINERS          |  1 +
 hw/arc/Makefile.objs | 21 ++++++++++++++
 hw/arc/sample.c      | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 102 insertions(+)
 create mode 100644 hw/arc/Makefile.objs
 create mode 100644 hw/arc/sample.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 0500cf5..6d7ce0b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -103,6 +103,7 @@ ARC
 M: Michael Rolnik <mrolnik@gmail.com>
 S: Maintained
 F: target-arc/
+F: hw/arc
 
 ARM
 M: Peter Maydell <peter.maydell@linaro.org>
diff --git a/hw/arc/Makefile.objs b/hw/arc/Makefile.objs
new file mode 100644
index 0000000..5ac5cb7
--- /dev/null
+++ b/hw/arc/Makefile.objs
@@ -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>
+#
+
+obj-y   += sample.o
diff --git a/hw/arc/sample.c b/hw/arc/sample.c
new file mode 100644
index 0000000..e8620af
--- /dev/null
+++ b/hw/arc/sample.c
@@ -0,0 +1,80 @@
+/*
+ * 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 "qemu-common.h"
+#include "cpu.h"
+#include "hw/hw.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
+#include "ui/console.h"
+#include "hw/boards.h"
+#include "hw/devices.h"
+#include "hw/loader.h"
+#include "qemu/error-report.h"
+#include "exec/address-spaces.h"
+#include "include/hw/sysbus.h"
+
+#define SIZE_RAM    0x00020000
+
+static void sample_init(MachineState *machine)
+{
+    MemoryRegion *mem;
+    MemoryRegion *ram;
+
+    ARCCPU *cpu_arc ATTRIBUTE_UNUSED;
+
+    mem = g_new(MemoryRegion, 1);
+    ram = g_new(MemoryRegion, 1);
+
+    cpu_arc = cpu_arc_init("any");
+
+    memory_region_allocate_system_memory(mem, NULL, "arc.mem", SIZE_RAM);
+
+    memory_region_init_ram(ram, NULL, "ram", SIZE_RAM, &error_fatal);
+    memory_region_add_subregion(get_system_memory(), PHYS_BASE_RAM, ram);
+    vmstate_register_ram_global(ram);
+
+    char const *firmware = NULL;
+    char const *filename;
+
+    if (machine->firmware) {
+        firmware = machine->firmware;
+    }
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware);
+    if (!filename) {
+        error_report("Could not find flash image file '%s'", firmware);
+        exit(1);
+    }
+
+    load_image_targphys(filename, PHYS_BASE_RAM + 0x100, SIZE_RAM);
+}
+
+static void sample_machine_init(MachineClass *mc)
+{
+    mc->desc = "ARC sample/example board";
+    mc->init = sample_init;
+    mc->is_default = 1;
+}
+
+DEFINE_MACHINE("sample", sample_machine_init)
+
-- 
2.4.9 (Apple Git-60)

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

* [PATCH RFC v1 00/29] ARC cores
  2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
@ 2016-09-16 15:01   ` Alexey Brodkin
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 02/29] target-arc: ADC, ADD, ADD1, ADD2, ADD3 Michael Rolnik
                     ` (28 subsequent siblings)
  29 siblings, 0 replies; 56+ messages in thread
From: Alexey Brodkin @ 2016-09-16 15:01 UTC (permalink / raw)
  To: linux-snps-arc

Hi Michael,

On Fri, 2016-09-09@01:31 +0300, Michael Rolnik wrote:
> This series of patches adds ARC target to QEMU. It indends to support
> ????- ARCtangent-A5 processor
> ????- ARC 600 processor
> ????- ARC 700 processor
> 
> All instructions except ASLS are implemented. Not fully tested yet.
> However I was able to execute correctly recursive fibonacci calculation.
> Reset vector is assumed to be some hardcoded value which worked for my test.
> I am planning to get FreeRTOS for ARC, once I get it, I will able to verify
> and complete interrupt support.

That's both very unexpected and cool!

I tried your patches on top of current QEMU git master and it:
?a) Builds for ARC
?b) Very simple code really works!

I was able to single-step with GDB through program as simple as:
--------------------->8---------------------
.global _start
_start:
	mov	r0, 1
	mov	r1, 2
	mov	r1, r0
--------------------->8---------------------

That's what I saw in GDB:
--------------------->8---------------------
(gdb) disassemble?
Dump of assembler code for function _start:
=> 0x00000100 <+0>:	mov	r0,0x1
???0x00000104 <+4>:	mov	r1,0x2
???0x00000108 <+8>:	mov	r1,r0
End of assembler dump.
(gdb) p $r0
$1 = 0
(gdb) stepi
0x00000104 in _start ()
(gdb) p $r0
$2 = 1
(gdb) stepi
0x00000108 in _start ()
(gdb) p $r1
$3 = 2
(gdb) stepi
0x0000010c in ?? ()
(gdb) p $r1
$4 = 1
--------------------->8---------------------

So again this is very promising even though a lot is essentially missing from
this very first implementation.

Anyways IMHO it would be good to have these patches accepted so people may start
playing with that stuff adding missing things one by one.

Let me know if you need any help from my side.

Regards,
Alexey

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

* Re: [Qemu-devel] [PATCH RFC v1 00/29] ARC cores
@ 2016-09-16 15:01   ` Alexey Brodkin
  0 siblings, 0 replies; 56+ messages in thread
From: Alexey Brodkin @ 2016-09-16 15:01 UTC (permalink / raw)
  To: mrolnik; +Cc: qemu-devel, linux-snps-arc

Hi Michael,

On Fri, 2016-09-09 at 01:31 +0300, Michael Rolnik wrote:
> This series of patches adds ARC target to QEMU. It indends to support
>     - ARCtangent-A5 processor
>     - ARC 600 processor
>     - ARC 700 processor
> 
> All instructions except ASLS are implemented. Not fully tested yet.
> However I was able to execute correctly recursive fibonacci calculation.
> Reset vector is assumed to be some hardcoded value which worked for my test.
> I am planning to get FreeRTOS for ARC, once I get it, I will able to verify
> and complete interrupt support.

That's both very unexpected and cool!

I tried your patches on top of current QEMU git master and it:
 a) Builds for ARC
 b) Very simple code really works!

I was able to single-step with GDB through program as simple as:
--------------------->8---------------------
.global _start
_start:
	mov	r0, 1
	mov	r1, 2
	mov	r1, r0
--------------------->8---------------------

That's what I saw in GDB:
--------------------->8---------------------
(gdb) disassemble 
Dump of assembler code for function _start:
=> 0x00000100 <+0>:	mov	r0,0x1
   0x00000104 <+4>:	mov	r1,0x2
   0x00000108 <+8>:	mov	r1,r0
End of assembler dump.
(gdb) p $r0
$1 = 0
(gdb) stepi
0x00000104 in _start ()
(gdb) p $r0
$2 = 1
(gdb) stepi
0x00000108 in _start ()
(gdb) p $r1
$3 = 2
(gdb) stepi
0x0000010c in ?? ()
(gdb) p $r1
$4 = 1
--------------------->8---------------------

So again this is very promising even though a lot is essentially missing from
this very first implementation.

Anyways IMHO it would be good to have these patches accepted so people may start
playing with that stuff adding missing things one by one.

Let me know if you need any help from my side.

Regards,
Alexey

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

* Re: [Qemu-devel] [PATCH RFC v1 00/29] ARC cores
  2016-09-16 15:01   ` [Qemu-devel] " Alexey Brodkin
  (?)
@ 2016-09-17 18:26   ` Michael Rolnik
  2016-09-19 12:40     ` Alexey Brodkin
  -1 siblings, 1 reply; 56+ messages in thread
From: Michael Rolnik @ 2016-09-17 18:26 UTC (permalink / raw)
  To: Alexey Brodkin; +Cc: qemu-devel, linux-snps-arc

H Alexey.

Thanks.

I need some help in getting a small code that exercises interrupts. For
several years I wrote FW for ARC based platforms (ARC4 & ARC6), but it
seems I forgot some of the things related to interrupts. I compiled
FreeRTOS demo from embARC, however I could not find interrupt vectors
there, I assume their board has ROM.
So, if you can help me with such a code, it would be great.

thanks,
Michael



On Fri, Sep 16, 2016 at 6:01 PM, Alexey Brodkin <Alexey.Brodkin@synopsys.com
> wrote:

> Hi Michael,
>
> On Fri, 2016-09-09 at 01:31 +0300, Michael Rolnik wrote:
> > This series of patches adds ARC target to QEMU. It indends to support
> >     - ARCtangent-A5 processor
> >     - ARC 600 processor
> >     - ARC 700 processor
> >
> > All instructions except ASLS are implemented. Not fully tested yet.
> > However I was able to execute correctly recursive fibonacci calculation.
> > Reset vector is assumed to be some hardcoded value which worked for my
> test.
> > I am planning to get FreeRTOS for ARC, once I get it, I will able to
> verify
> > and complete interrupt support.
>
> That's both very unexpected and cool!
>
> I tried your patches on top of current QEMU git master and it:
>  a) Builds for ARC
>  b) Very simple code really works!
>
> I was able to single-step with GDB through program as simple as:
> --------------------->8---------------------
> .global _start
> _start:
>         mov     r0, 1
>         mov     r1, 2
>         mov     r1, r0
> --------------------->8---------------------
>
> That's what I saw in GDB:
> --------------------->8---------------------
> (gdb) disassemble
> Dump of assembler code for function _start:
> => 0x00000100 <+0>:     mov     r0,0x1
>    0x00000104 <+4>:     mov     r1,0x2
>    0x00000108 <+8>:     mov     r1,r0
> End of assembler dump.
> (gdb) p $r0
> $1 = 0
> (gdb) stepi
> 0x00000104 in _start ()
> (gdb) p $r0
> $2 = 1
> (gdb) stepi
> 0x00000108 in _start ()
> (gdb) p $r1
> $3 = 2
> (gdb) stepi
> 0x0000010c in ?? ()
> (gdb) p $r1
> $4 = 1
> --------------------->8---------------------
>
> So again this is very promising even though a lot is essentially missing
> from
> this very first implementation.
>
> Anyways IMHO it would be good to have these patches accepted so people may
> start
> playing with that stuff adding missing things one by one.
>
> Let me know if you need any help from my side.
>
> Regards,
> Alexey




-- 
Best Regards,
Michael Rolnik

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

* Re: [Qemu-devel] [PATCH RFC v1 00/29] ARC cores
  2016-09-17 18:26   ` Michael Rolnik
@ 2016-09-19 12:40     ` Alexey Brodkin
  2016-09-19 12:55       ` Igor Guryanov
  0 siblings, 1 reply; 56+ messages in thread
From: Alexey Brodkin @ 2016-09-19 12:40 UTC (permalink / raw)
  To: mrolnik; +Cc: qemu-devel, Igor Guryanov, linux-snps-arc

Hi Michael,

I'm pretty sure embARC was not meant to be run on ARCompact (AKA ISAv1 cores like ARC600 & ARC700) instead targets were ARCv2 cores like ARC EM and ARC HS. Unfortunately I have no experience with embARC so adding more experienced person in the thread (Igor Guryanov) who may shed some light on interrupts in embARC.

-Alexey

On Sat, 2016-09-17 at 21:26 +0300, Michael Rolnik wrote:
H Alexey.

Thanks.

I need some help in getting a small code that exercises interrupts. For several years I wrote FW for ARC based platforms (ARC4 & ARC6), but it seems I forgot some of the things related to interrupts. I compiled FreeRTOS demo from embARC, however I could not find interrupt vectors there, I assume their board has ROM.
So, if you can help me with such a code, it would be great.

thanks,
Michael



On Fri, Sep 16, 2016 at 6:01 PM, Alexey Brodkin <Alexey.Brodkin@synopsys.com<mailto:Alexey.Brodkin@synopsys.com>> wrote:
Hi Michael,

On Fri, 2016-09-09 at 01:31 +0300, Michael Rolnik wrote:
> This series of patches adds ARC target to QEMU. It indends to support
>     - ARCtangent-A5 processor
>     - ARC 600 processor
>     - ARC 700 processor
>
> All instructions except ASLS are implemented. Not fully tested yet.
> However I was able to execute correctly recursive fibonacci calculation.
> Reset vector is assumed to be some hardcoded value which worked for my test.
> I am planning to get FreeRTOS for ARC, once I get it, I will able to verify
> and complete interrupt support.

That's both very unexpected and cool!

I tried your patches on top of current QEMU git master and it:
 a) Builds for ARC
 b) Very simple code really works!

I was able to single-step with GDB through program as simple as:
--------------------->8---------------------
.global _start
_start:
        mov     r0, 1
        mov     r1, 2
        mov     r1, r0
--------------------->8---------------------

That's what I saw in GDB:
--------------------->8---------------------
(gdb) disassemble
Dump of assembler code for function _start:
=> 0x00000100 <+0>:     mov     r0,0x1
   0x00000104 <+4>:     mov     r1,0x2
   0x00000108 <+8>:     mov     r1,r0
End of assembler dump.
(gdb) p $r0
$1 = 0
(gdb) stepi
0x00000104 in _start ()
(gdb) p $r0
$2 = 1
(gdb) stepi
0x00000108 in _start ()
(gdb) p $r1
$3 = 2
(gdb) stepi
0x0000010c in ?? ()
(gdb) p $r1
$4 = 1
--------------------->8---------------------

So again this is very promising even though a lot is essentially missing from
this very first implementation.

Anyways IMHO it would be good to have these patches accepted so people may start
playing with that stuff adding missing things one by one.

Let me know if you need any help from my side.

Regards,
Alexey



--
Best Regards,
Michael Rolnik

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

* Re: [Qemu-devel] [PATCH RFC v1 00/29] ARC cores
  2016-09-19 12:40     ` Alexey Brodkin
@ 2016-09-19 12:55       ` Igor Guryanov
  2016-09-19 13:45         ` Michael Rolnik
  0 siblings, 1 reply; 56+ messages in thread
From: Igor Guryanov @ 2016-09-19 12:55 UTC (permalink / raw)
  To: Alexey Brodkin, mrolnik; +Cc: qemu-devel, linux-snps-arc

Hi Michael,

Long time ago debugged one problem with embARC and I remember I was also puzzled with itss interrupt handling approach.
The board itself can fit only prebootloader in the ROM, and interrupt handling is kept in embARC itself.

But, the projects is aimed to support several different RTOS. As I remember, BSP was separated and made ‘universal’.
In other words, not very transparent and obvious ☺. If I recall it there were a single entry for interrupt/exceptions which scanned OS defined data structure in a search for pointers for actual handlers. i.e. it was very different from what you can find in simple baremetal example (like this one - https://github.com/foss-for-synopsys-dwc-arc-processors/ARC-Development-Systems-Forum/tree/master/examples/EMSK/timer_IRQ )

Let me refresh my memory on embARC internals which might have already evolved and I give you overview in a day or two.

Regards,
Igor.

From: Alexey Brodkin
Sent: Monday, September 19, 2016 3:41 PM
To: mrolnik@gmail.com
Cc: qemu-devel@nongnu.org; Igor Guryanov <guryanov@synopsys.com>; linux-snps-arc@lists.infradead.org
Subject: Re: [PATCH RFC v1 00/29] ARC cores

Hi Michael,

I'm pretty sure embARC was not meant to be run on ARCompact (AKA ISAv1 cores like ARC600 & ARC700) instead targets were ARCv2 cores like ARC EM and ARC HS. Unfortunately I have no experience with embARC so adding more experienced person in the thread (Igor Guryanov) who may shed some light on interrupts in embARC.

-Alexey

On Sat, 2016-09-17 at 21:26 +0300, Michael Rolnik wrote:
H Alexey.

Thanks.

I need some help in getting a small code that exercises interrupts. For several years I wrote FW for ARC based platforms (ARC4 & ARC6), but it seems I forgot some of the things related to interrupts. I compiled FreeRTOS demo from embARC, however I could not find interrupt vectors there, I assume their board has ROM.
So, if you can help me with such a code, it would be great.

thanks,
Michael



On Fri, Sep 16, 2016 at 6:01 PM, Alexey Brodkin <Alexey.Brodkin@synopsys.com<mailto:Alexey.Brodkin@synopsys.com>> wrote:

Hi Michael,

On Fri, 2016-09-09 at 01:31 +0300, Michael Rolnik wrote:
> This series of patches adds ARC target to QEMU. It indends to support
>     - ARCtangent-A5 processor
>     - ARC 600 processor
>     - ARC 700 processor
>
> All instructions except ASLS are implemented. Not fully tested yet.
> However I was able to execute correctly recursive fibonacci calculation.
> Reset vector is assumed to be some hardcoded value which worked for my test.
> I am planning to get FreeRTOS for ARC, once I get it, I will able to verify
> and complete interrupt support.

That's both very unexpected and cool!

I tried your patches on top of current QEMU git master and it:
 a) Builds for ARC
 b) Very simple code really works!

I was able to single-step with GDB through program as simple as:
--------------------->8---------------------
.global _start
_start:
        mov     r0, 1
        mov     r1, 2
        mov     r1, r0
--------------------->8---------------------

That's what I saw in GDB:
--------------------->8---------------------
(gdb) disassemble
Dump of assembler code for function _start:
=> 0x00000100 <+0>:     mov     r0,0x1
   0x00000104 <+4>:     mov     r1,0x2
   0x00000108 <+8>:     mov     r1,r0
End of assembler dump.
(gdb) p $r0
$1 = 0
(gdb) stepi
0x00000104 in _start ()
(gdb) p $r0
$2 = 1
(gdb) stepi
0x00000108 in _start ()
(gdb) p $r1
$3 = 2
(gdb) stepi
0x0000010c in ?? ()
(gdb) p $r1
$4 = 1
--------------------->8---------------------

So again this is very promising even though a lot is essentially missing from
this very first implementation.

Anyways IMHO it would be good to have these patches accepted so people may start
playing with that stuff adding missing things one by one.

Let me know if you need any help from my side.

Regards,
Alexey



--
Best Regards,
Michael Rolnik

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

* Re: [Qemu-devel] [PATCH RFC v1 00/29] ARC cores
  2016-09-19 12:55       ` Igor Guryanov
@ 2016-09-19 13:45         ` Michael Rolnik
  0 siblings, 0 replies; 56+ messages in thread
From: Michael Rolnik @ 2016-09-19 13:45 UTC (permalink / raw)
  To: Igor Guryanov; +Cc: Alexey Brodkin, qemu-devel, linux-snps-arc

Hi Igor,

I will try to compile this example and test my implementations.

Thank you,
Michael


On Mon, Sep 19, 2016 at 3:55 PM, Igor Guryanov <Igor.Guryanov@synopsys.com>
wrote:

> Hi Michael,
>
>
>
> Long time ago debugged one problem with embARC and I remember I was also
> puzzled with itss interrupt handling approach.
>
> The board itself can fit only prebootloader in the ROM, and interrupt
> handling is kept in embARC itself.
>
>
>
> But, the projects is aimed to support several different RTOS. As I
> remember, BSP was separated and made ‘universal’.
> In other words, not very transparent and obvious J. If I recall it there
> were a single entry for interrupt/exceptions which scanned OS defined data
> structure in a search for pointers for actual handlers. i.e. it was very
> different from what you can find in simple baremetal example (like this one
> - https://github.com/foss-for-synopsys-dwc-arc-processors/
> ARC-Development-Systems-Forum/tree/master/examples/EMSK/timer_IRQ )
>
>
>
> Let me refresh my memory on embARC internals which might have already
> evolved and I give you overview in a day or two.
>
>
>
> Regards,
>
> Igor.
>
>
>
> *From:* Alexey Brodkin
> *Sent:* Monday, September 19, 2016 3:41 PM
> *To:* mrolnik@gmail.com
> *Cc:* qemu-devel@nongnu.org; Igor Guryanov <guryanov@synopsys.com>;
> linux-snps-arc@lists.infradead.org
> *Subject:* Re: [PATCH RFC v1 00/29] ARC cores
>
>
>
> Hi Michael,
>
>
>
> I'm pretty sure embARC was not meant to be run on ARCompact (AKA ISAv1
> cores like ARC600 & ARC700) instead targets were ARCv2 cores like ARC EM
> and ARC HS. Unfortunately I have no experience with embARC so adding more
> experienced person in the thread (Igor Guryanov) who may shed some light on
> interrupts in embARC.
>
>
>
> -Alexey
>
>
>
> On Sat, 2016-09-17 at 21:26 +0300, Michael Rolnik wrote:
>
> H Alexey.
>
>
>
> Thanks.
>
>
>
> I need some help in getting a small code that exercises interrupts. For
> several years I wrote FW for ARC based platforms (ARC4 & ARC6), but it
> seems I forgot some of the things related to interrupts. I compiled
> FreeRTOS demo from embARC, however I could not find interrupt vectors
> there, I assume their board has ROM.
>
> So, if you can help me with such a code, it would be great.
>
>
>
> thanks,
>
> Michael
>
>
>
>
>
>
>
> On Fri, Sep 16, 2016 at 6:01 PM, Alexey Brodkin <
> Alexey.Brodkin@synopsys.com> wrote:
>
> Hi Michael,
>
> On Fri, 2016-09-09 at 01:31 +0300, Michael Rolnik wrote:
> > This series of patches adds ARC target to QEMU. It indends to support
> >     - ARCtangent-A5 processor
> >     - ARC 600 processor
> >     - ARC 700 processor
> >
> > All instructions except ASLS are implemented. Not fully tested yet.
> > However I was able to execute correctly recursive fibonacci calculation.
> > Reset vector is assumed to be some hardcoded value which worked for my
> test.
> > I am planning to get FreeRTOS for ARC, once I get it, I will able to
> verify
> > and complete interrupt support.
>
> That's both very unexpected and cool!
>
> I tried your patches on top of current QEMU git master and it:
>  a) Builds for ARC
>  b) Very simple code really works!
>
> I was able to single-step with GDB through program as simple as:
> --------------------->8---------------------
> .global _start
> _start:
>         mov     r0, 1
>         mov     r1, 2
>         mov     r1, r0
> --------------------->8---------------------
>
> That's what I saw in GDB:
> --------------------->8---------------------
> (gdb) disassemble
> Dump of assembler code for function _start:
> => 0x00000100 <+0>:     mov     r0,0x1
>    0x00000104 <+4>:     mov     r1,0x2
>    0x00000108 <+8>:     mov     r1,r0
> End of assembler dump.
> (gdb) p $r0
> $1 = 0
> (gdb) stepi
> 0x00000104 in _start ()
> (gdb) p $r0
> $2 = 1
> (gdb) stepi
> 0x00000108 in _start ()
> (gdb) p $r1
> $3 = 2
> (gdb) stepi
> 0x0000010c in ?? ()
> (gdb) p $r1
> $4 = 1
> --------------------->8---------------------
>
> So again this is very promising even though a lot is essentially missing
> from
> this very first implementation.
>
> Anyways IMHO it would be good to have these patches accepted so people may
> start
> playing with that stuff adding missing things one by one.
>
> Let me know if you need any help from my side.
>
> Regards,
> Alexey
>
>
>
>
>
> --
>
> Best Regards,
> Michael Rolnik
>
>


-- 
Best Regards,
Michael Rolnik

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

* Re: [Qemu-devel] [PATCH RFC v1 02/29] target-arc: ADC, ADD, ADD1, ADD2, ADD3
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-20 20:51 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
> ---
>  target-arc/Makefile.objs    |   1 +
>  target-arc/translate-inst.c | 170 ++++++++++++++++++++++++++++++++++++++++++++
>  target-arc/translate-inst.h |  30 ++++++++
>  3 files changed, 201 insertions(+)
>  create mode 100644 target-arc/translate-inst.c
>  create mode 100644 target-arc/translate-inst.h

Please don't split translate.c into translate-inst.* and decode.c like you did
for AVR.  Since you're not generating any source from a template, there's even
less call for it here than before.

> +static void gen_add_Cf(TCGv dest, TCGv src1, TCGv src2)
> +{
> +    TCGv t1 = tcg_temp_new_i32();
> +    TCGv t2 = tcg_temp_new_i32();
> +    TCGv t3 = tcg_temp_new_i32();
> +
> +    tcg_gen_and_tl(t1, src1, src2); /*  t1 = src1 & src2                    */
> +    tcg_gen_andc_tl(t2, src1, dest);/*  t2 = src1 & ~dest                   */
> +    tcg_gen_andc_tl(t3, src2, dest);/*  t3 = src2 & ~dest                   */
> +    tcg_gen_or_tl(t1, t1, t2);      /*  t1 = t1 | t2 | t3                   */
> +    tcg_gen_or_tl(t1, t1, t3);
> +
> +    tcg_gen_shri_tl(cpu_Cf, t1, 31);/*  Cf = t1(31)                         */

I've shown you before how to generate a carry bit from tcg_gen_add2_tl.

> +int arc_gen_ADC(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
> +{
> +    TCGv rslt = dest;
> +
> +    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
> +        rslt = tcg_temp_new_i32();
> +    }

It would be cleaner to simply always use a temporary.  The tcg optimizer will
generate the same code either way.


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit
  2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit Michael Rolnik
@ 2016-09-20 23:31   ` Richard Henderson
  2016-09-26  1:22     ` Max Filippov
  0 siblings, 1 reply; 56+ messages in thread
From: Richard Henderson @ 2016-09-20 23:31 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> +#define CPU_IMM(env)    ((env)->r[62])
> +#define CPU_PCL(env)    ((env)->r[63])

You don't need to represent these as actual registers.  These are better 
considered placeholder regnums to be filled in with actual values during 
translation.

> +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;

There is no reason to represent each bit as a whole word, and even less to have 
four copies.

Only the current NZCV bits are relevant for expansion to a word, and even then 
you should consider not canonicalizing N, Z and V to a pure boolean value.

> +
> +    struct {
> +        uint32_t    S2;
> +        uint32_t    S1;
> +        uint32_t    CS;
> +    } macmod;

Does CS really need to be represented at all?  It appears to me to be a field 
that you write to that clears S1 and S2.

> +    switch (n) {
> +        case 0x00 ... 0x3f: {
> +            val = env->r[n];
> +            break;
> +        }

Please use the proper format for all switch statements.

     switch (n) {
     case 0x00 ... 0x3f:
         val = env->r[n];
         break;

> +
> +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_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    */

Why are these separate variables?  They overlap cpu_r[N].  If you want them as 
names for clarity in translation, #define seems good enough.

> +int arc_gen_INVALID(DisasCtxt *ctx)
> +{
> +    printf("invalid inst @:%08x\n", ctx->cpc);

No printf.  It's not useful, even temporarily.

> +    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);

Why are you creating all of these?  Creating local temps containing immediates 
is a horrible waste.

> +        if (ctx.npc == env->lpe) {

You can't look at the contents of ENV during translation.

You'll need to implement this feature similar to how it's done for xtensa.  See 
helper_wsr_lbeg, helper_wsr_lend, and gen_check_loop_end.


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 03/29] target-arc: SUB, SUB1, SUB2, SUB3, SBC, RSUB, CMP
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-20 23:32 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> +static void gen_sub_Cf(TCGv dest, TCGv src1, TCGv src2)
> +{
> +    TCGv t1 = tcg_temp_new_i32();
> +    TCGv t2 = tcg_temp_new_i32();
> +    TCGv t3 = tcg_temp_new_i32();
> +
> +    tcg_gen_not_tl(t1, src1);       /*  t1 = ~src1                          */
> +    tcg_gen_and_tl(t2, t1, src2);   /*  t2 = ~src1 & src2                   */
> +    tcg_gen_or_tl(t3, t1, src2);    /*  t3 = (~src1 | src2) & dest          */
> +    tcg_gen_and_tl(t3, t3, dest);
> +    tcg_gen_or_tl(t2, t2, t3);      /*  t2 = ~src1 & src2
> +                                           | ~src1 & dest
> +                                           | dest & src2                    */
> +    tcg_gen_shri_tl(cpu_Cf, t2, 31);/*  Cf = t2(31)                         */

Again, this can be done with tcg_gen_sub2_tl.


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 04/29] target-arc: AND, OR, XOR, BIC, TST
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-20 23:35 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> +int arc_gen_AND(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
> +{
> +    TCGv rslt = dest;
> +
> +    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
> +        rslt = tcg_temp_new_i32();
> +    }
> +
> +    tcg_gen_and_tl(rslt, src1, src2);
> +
> +    if (ctx->opt.f) {
> +        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, rslt, ctx->zero);
> +        tcg_gen_shri_tl(cpu_Nf, rslt, 31);
> +    }
> +
> +    if (!TCGV_EQUAL(dest, rslt)) {
> +        tcg_gen_mov_tl(dest, rslt);
> +        tcg_temp_free_i32(rslt);
> +    }

There is no reason for this rslt temporary stuff.
Unlike with add & sub, src1 & src2 are not used after the operation, for any of 
the logical operations.


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 06/29] target-arc: EX, LD, ST, SYNC, PREFETCH
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-20 23:46 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
> ---
>  target-arc/translate-inst.c | 230 ++++++++++++++++++++++++++++++++++++++++++++
>  target-arc/translate-inst.h |  10 ++
>  2 files changed, 240 insertions(+)
>
> diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
> index 2032823..ac13c86 100644
> --- a/target-arc/translate-inst.c
> +++ b/target-arc/translate-inst.c
> @@ -664,3 +664,233 @@ int arc_gen_RORm(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
>      return  BS_NONE;
>  }
>
> +/*
> +    EX
> +*/
> +int arc_gen_EX(DisasCtxt *ctx, TCGv dest, TCGv src1)
> +{
> +    TCGv temp = tcg_temp_new_i32();
> +
> +    tcg_gen_mov_tl(temp, dest);
> +
> +    tcg_gen_qemu_ld_tl(dest, src1, ctx->memidx, MO_UL);
> +    tcg_gen_qemu_st_tl(temp, src1, ctx->memidx, MO_UL);
> +
> +    tcg_temp_free_i32(temp);

You need to load into temp and store directly from dest.  Otherwise you 
incorrectly clobber dest when the page is read-only.


> +int arc_gen_LD(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
> +{
> +    TCGv addr = tcg_temp_new_i32();
> +
> +    /*  address             */
> +    switch (ctx->opt.aa) {

You should have a common subroutine for computing addresses.  And probably for 
implementing all loads and all stores.  Use TCGMemOp to distinguish the cases.

> +int arc_gen_PREFETCH(DisasCtxt *ctx, TCGv src1, TCGv src2)
> +{
> +    TCGv temp = tcg_temp_new_i32();
> +
> +    arc_gen_LD(ctx, temp, src1, src2);

A prefetch should be implemented as a NOP.  Otherwise you'll generate 
exceptions when you shouldn't.


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 07/29] target-arc: MAX, MIN
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-20 23:48 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> +int arc_gen_MAX(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
> +{
> +    if (ctx->opt.f) {
> +        arc_gen_CMP(ctx, src1, src2);
> +    }
> +
> +    tcg_gen_movcond_tl(TCG_COND_GEU, dest, src1, src2, src1, src2);

These are supposed to be signed comparisons.


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 09/29] target-arc: NEG, ABS, NOT
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-20 23:55 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> +    tcg_gen_movcond_tl(TCG_COND_GEU, rslt, src1, ctx->msb32, src1, t0);

Better as a signed comparison vs zero.


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 10/29] target-arc: POP, PUSH
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-20 23:57 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> +    tcg_gen_subi_tl(cpu_sp, cpu_sp, 4);
> +    tcg_gen_qemu_st_tl(src1, cpu_sp, ctx->memidx, MO_UL);

You need to delay the write to the stack pointer until after the store, 
otherwise sp will have the incorrect contents if the page is not writable.


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 11/29] target-arc: BCLR, BMSK, BSET, BTST, BXOR
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-21  0:07 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> +int arc_gen_BCLR(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
> +{
> +    TCGv rslt = dest;
> +
> +    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
> +        rslt = tcg_temp_new_i32();
> +    }
> +
> +    tcg_gen_andi_tl(rslt, src2, 0x3f);

0x1f, in all of the functions.

> +    tcg_gen_add_tl(mask, mask, ctx->one);
> +    tcg_gen_shr_tl(mask, ctx->one, mask);
> +    tcg_gen_sub_tl(mask, mask, ctx->one);

I know this is the description in the manual, but this will produce a shift of 
32 with an input of 31, which is illegal in tcg.

You need to use

   mask = -1u >> (src2 ^ 31)


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 13/29] target-arc: NORM, NORMW
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-21  0:14 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> +target_ulong helper_norm(CPUARCState *env, uint32_t src1)
> +{
> +    if (src1 == 0x00000000 || src1 == 0xffffffff) {
> +        return 31;
> +    } else {
> +        if ((src1 & 0x80000000) == 0x80000000) {
> +            src1 = ~src1;
> +        }
> +        return clz32(src1) - 1;
> +    }

This is clrsb32.

> +target_ulong helper_normw(CPUARCState *env, uint32_t src1)
> +{
> +    src1 &= 0xffff;
> +
> +    if (src1 == 0x0000 || src1 == 0xffff) {
> +        return 15;
> +    } else {
> +        if ((src1 & 0x8000) == 0x8000) {
> +            src1 = ~src1 & 0xffff;
> +        }
> +        return clz32(src1) - 17;
> +    }

clrsb32((int16_t)src1) - 16


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 14/29] target-arc: MPY, MPYH, MPYHU, MPYU
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-21  0:17 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> +    tcg_gen_ext_i32_i64(srcA, src1);
> +    tcg_gen_ext_i32_i64(srcB, src2);
> +
> +    tcg_gen_mul_i64(rslt, srcA, srcB);
> +
> +    tcg_gen_trunc_i64_tl(dest, rslt);
> +
> +    if (ctx->opt.f) {
> +        TCGv_i64 temp = tcg_temp_new_i64();
> +
> +        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_Zf, dest, ctx->zero);
> +
> +        tcg_gen_trunc_i64_tl(cpu_Nf, rslt);
> +        tcg_gen_shri_tl(cpu_Nf, cpu_Nf, 31);
> +
> +        tcg_gen_ext_i32_i64(temp, dest);
> +        tcg_gen_setcond_i64(TCG_COND_NE, temp, temp, rslt);
> +        tcg_gen_trunc_i64_tl(cpu_Cf, temp);
> +
> +        tcg_temp_free_i64(temp);
> +    }

It's probably easier to do this with tcg_gen_muls2_tl.


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 15/29] target-arc: MUL64, MULU64, DIVAW
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-21  0:20 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
> ---
>  target-arc/translate-inst.c | 105 ++++++++++++++++++++++++++++++++++++++++++++
>  target-arc/translate-inst.h |   4 ++
>  2 files changed, 109 insertions(+)
>
> diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
> index 92c75ac..c3795fe 100644
> --- a/target-arc/translate-inst.c
> +++ b/target-arc/translate-inst.c
> @@ -1546,3 +1546,108 @@ int arc_gen_MPYU(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
>      return BS_NONE;
>  }
>
> +/*
> +    DIVAW
> +*/
> +int arc_gen_DIVAW(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)
> +{
> +    TCGLabel *label_else = gen_new_label();
> +    TCGLabel *label_done = gen_new_label();
> +    TCGv rslt = dest;
> +    TCGv temp = dest;
> +
> +    if (TCGV_EQUAL(dest, src1) || TCGV_EQUAL(dest, src2)) {
> +        rslt = tcg_temp_new_i32();
> +    }
> +
> +    /*
> +        if (src1 == 0)
> +            dest = 0
> +        else
> +        {
> +            src1_temp = src1 << 1
> +            if (src1_temp >= src2)
> +                dest = ((src1_temp - src2) | 0x0000_0001)
> +            else
> +                dest = src1_temp
> +        }
> +    */

Probably better with two movcond instead of branches.


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 16/29] target-arc: BBIT0, BBIT1, BR
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-21  0:25 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> +static void arc_gen_exec_delayslot(DisasCtxt *ctx)
> +{
> +    if (ctx->opt.limm == 0) {
> +        uint32_t cpc = ctx->cpc;
> +        uint32_t npc = ctx->npc;
> +        uint32_t dpc = ctx->dpc;
> +        uint32_t pcl = ctx->pcl;
> +        options_t opt = ctx->opt;
> +        int bstate = ctx->bstate;
> +
> +        ctx->cpc = ctx->npc;
> +        ctx->pcl = ctx->cpc & 0xfffffffc;
> +
> +        ++ctx->ds;
> +
> +        /* TODO: check for illegal instruction sequence */
> +
> +        memset(&ctx->opt, 0, sizeof(ctx->opt));
> +        arc_decode(ctx);
> +
> +        --ctx->ds;
> +
> +        ctx->cpc = cpc;
> +        ctx->npc = npc;
> +        ctx->dpc = dpc;
> +        ctx->pcl = pcl;
> +        ctx->opt = opt;
> +        ctx->bstate = bstate;
> +    }
> +}

It might be easier to put the delay slot into a TB by itself.  That will avoid 
having to duplicate the decoding here.


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 17/29] target-arc: B, BL
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-21  0:28 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> +        case    ARC_COND_HI: {
> +            ARC_COND_IF_1(C, label_skip);
> +            ARC_COND_IF_1(Z, label_skip);
> +        } break;

Why aren't you using AND / OR to combine these conditions?


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 19/29] target-arc: LR, SR
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-21  0:31 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:32 PM, Michael Rolnik wrote:
> +int arc_gen_LR(DisasCtxt *ctx, TCGv dest, TCGv src1)
> +{
> +    TCGv cpc = tcg_const_local_i32((ctx->cpc + 3) & 0xfffffffc);
> +    TCGv npc = tcg_const_local_i32((ctx->npc + 3) & 0xfffffffc);

No need for _local here.


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 22/29] target-arc: ASLS, ASRS
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-21  0:36 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:32 PM, Michael Rolnik wrote:
> +int arc_gen_ASLS(DisasCtxt *ctx, TCGv dest, TCGv src1, TCGv src2)

Just do these as helpers.


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 24/29] target-arc: NOP, UNIMP
  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
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-21  0:39 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:32 PM, Michael Rolnik wrote:
> +int arc_gen_UNIMP(DisasCtxt *ctx)
> +{
> +    /* PC = INT_VECTOR_BACE + 0x10 */
> +    tcg_gen_andi_tl(cpu_pc, cpu_intvec, 0xffffffc0);
> +    tcg_gen_addi_tl(cpu_pc, cpu_pc, 0x10);
> +
> +    return  BS_EXCP;
> +}

This should be done via an exception, with the pc change done in do_interrupt.


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 28/29] target-arc: decode
  2016-09-08 22:32 ` [Qemu-devel] [PATCH RFC v1 28/29] target-arc: decode Michael Rolnik
@ 2016-09-21  0:49   ` Richard Henderson
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-21  0:49 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel

On 09/08/2016 03:32 PM, Michael Rolnik wrote:
> +    decode_f    decode[32] = {

There's no reason to use an array here, and worse, a non-static non-const 
array.  Just use a switch here

> +    return  decode[curr_major](ctx, curr_opcode);


r~

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

* Re: [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit
  2016-09-20 23:31   ` Richard Henderson
@ 2016-09-26  1:22     ` Max Filippov
  2016-09-27 18:46       ` Richard Henderson
  0 siblings, 1 reply; 56+ messages in thread
From: Max Filippov @ 2016-09-26  1:22 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Michael Rolnik, qemu-devel

Hello,

On Tue, Sep 20, 2016 at 4:31 PM, Richard Henderson <rth@twiddle.net> wrote:
>> +        if (ctx.npc == env->lpe) {
> You can't look at the contents of ENV during translation.
>
> You'll need to implement this feature similar to how it's done for xtensa.
> See helper_wsr_lbeg, helper_wsr_lend, and gen_check_loop_end.

I think it's fairly expensive solution, as it allows to have only one TB with
zero overhead loop at a time. I'm looking at ways to optimize it,
perhaps recording lbeg in the TB's cs_base.

-- 
Thanks.
-- Max

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

* Re: [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit
  2016-09-26  1:22     ` Max Filippov
@ 2016-09-27 18:46       ` Richard Henderson
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Henderson @ 2016-09-27 18:46 UTC (permalink / raw)
  To: Max Filippov; +Cc: Michael Rolnik, qemu-devel

On 09/25/2016 06:22 PM, Max Filippov wrote:
> Hello,
> 
> On Tue, Sep 20, 2016 at 4:31 PM, Richard Henderson <rth@twiddle.net> wrote:
>>> +        if (ctx.npc == env->lpe) {
>> You can't look at the contents of ENV during translation.
>>
>> You'll need to implement this feature similar to how it's done for xtensa.
>> See helper_wsr_lbeg, helper_wsr_lend, and gen_check_loop_end.
> 
> I think it's fairly expensive solution, as it allows to have only one TB with
> zero overhead loop at a time. I'm looking at ways to optimize it,
> perhaps recording lbeg in the TB's cs_base.
> 

It may be expensive, but at least it works.  Unlike the mechanism quoted above,
which doesn't work at all.


r~

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

end of thread, other threads:[~2016-09-27 18:46 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-08 22:31 [Qemu-devel] [PATCH RFC v1 00/29] ARC cores Michael Rolnik
2016-09-08 22:31 ` [Qemu-devel] [PATCH RFC v1 01/29] target-arc: initial commit Michael Rolnik
2016-09-20 23:31   ` 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

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.