diff mbox series

[01/15] arc: Add initial core cpu files

Message ID 20201111161758.9636-2-cupertinomiranda@gmail.com (mailing list archive)
State New, archived
Headers show
Series *** ARC port for review *** | expand

Commit Message

Cupertino Miranda Nov. 11, 2020, 4:17 p.m. UTC
From: Cupertino Miranda <cmiranda@synopsys.com>

Signed-off-by: Cupertino Miranda <cmiranda@synopsys.com>
---
 target/arc/arc-common.h |  54 ++++
 target/arc/cpu-param.h  |  32 +++
 target/arc/cpu-qom.h    |  52 ++++
 target/arc/cpu.c        | 467 +++++++++++++++++++++++++++++++++++
 target/arc/cpu.h        | 531 ++++++++++++++++++++++++++++++++++++++++
 target/arc/internals.h  |  38 +++
 target/arc/meson.build  |  20 ++
 7 files changed, 1194 insertions(+)
 create mode 100644 target/arc/arc-common.h
 create mode 100644 target/arc/cpu-param.h
 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/internals.h
 create mode 100644 target/arc/meson.build

Comments

Richard Henderson Dec. 1, 2020, 7:06 p.m. UTC | #1
On 11/11/20 10:17 AM, cupertinomiranda@gmail.com wrote:
> +enum arc_cpu_family {
> +  ARC_OPCODE_NONE    = 0,
> +  ARC_OPCODE_DEFAULT = 1 << 0,
> +  ARC_OPCODE_ARC600  = 1 << 1,
> +  ARC_OPCODE_ARC700  = 1 << 2,
> +  ARC_OPCODE_ARCv2EM = 1 << 3,
> +  ARC_OPCODE_ARCv2HS = 1 << 4
> +};

Indentation is off.

> +/*-*-indent-tabs-mode:nil;tab-width:4;indent-line-function:'insert-tab'-*-*/
> +/* vim: set ts=4 sw=4 et: */

This ought to be covered by the top-level .editorconfig.

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

Indentation is off all through cpu.c.

> +#ifndef CPU_ARC_H
> +#define CPU_ARC_H
> +
> +#include "cpu-qom.h"
> +#include "exec/cpu-defs.h"
> +#include "fpu/softfloat.h"

You probably only need softfloat-types.h in cpu.h.

> +#define MMU_IDX       0

What's this?

> +#define PHYS_BASE_RAM 0x00000000
> +#define VIRT_BASE_RAM 0x00000000

This seems like board stuff, not cpu stuff.

> +enum gdb_regs {
> +    GDB_REG_0 = 0,
> +    GDB_REG_1,
> +    GDB_REG_2,
> +    GDB_REG_3,
> +    GDB_REG_4,
> +    GDB_REG_5,
> +    GDB_REG_6,
> +    GDB_REG_7,
> +    GDB_REG_8,
> +    GDB_REG_9,
> +    GDB_REG_10,
> +    GDB_REG_11,
> +    GDB_REG_12,
> +    GDB_REG_13,
> +    GDB_REG_14,
> +    GDB_REG_15,
> +    GDB_REG_16,
> +    GDB_REG_17,
> +    GDB_REG_18,
> +    GDB_REG_19,
> +    GDB_REG_20,
> +    GDB_REG_21,
> +    GDB_REG_22,
> +    GDB_REG_23,
> +    GDB_REG_24,
> +    GDB_REG_25,
> +    GDB_REG_26,         /* GP                         */
> +    GDB_REG_27,         /* FP                         */
> +    GDB_REG_28,         /* SP                         */
> +    GDB_REG_29,         /* ILINK                      */
> +    GDB_REG_30,         /* R30                        */
> +    GDB_REG_31,         /* BLINK                      */
> +    GDB_REG_58,         /* little_endian? ACCL : ACCH */
> +    GDB_REG_59,         /* little_endian? ACCH : ACCL */
> +    GDB_REG_60,         /* LP                         */
> +    GDB_REG_63,         /* Immediate                  */
> +    GDB_REG_LAST
> +};

Why is this in cpu.h and not gdbstub.c?

> +#define CPU_GP(env)     ((env)->r[26])
> +#define CPU_FP(env)     ((env)->r[27])
> +#define CPU_SP(env)     ((env)->r[28])
> +#define CPU_ILINK(env)  ((env)->r[29])
> +#define CPU_ILINK1(env) ((env)->r[29])
> +#define CPU_ILINK2(env) ((env)->r[30])
> +#define CPU_BLINK(env)  ((env)->r[31])
> +#define CPU_LP(env)     ((env)->r[60])
> +#define CPU_IMM(env)    ((env)->r[62])
> +#define CPU_PCL(env)    ((env)->r[63])

Does it make more sense to define these in terms of numbers than lvalue macros?

> +typedef struct status_register {
> +    uint32_t Hf;     /* halt                    */
> +    uint32_t Ef;     /* irq priority treshold. */
> +    uint32_t AEf;
> +    uint32_t DEf;
> +    uint32_t Uf;
> +    uint32_t Vf;     /*  overflow                */
> +    uint32_t Cf;     /*  carry                   */
> +    uint32_t Nf;     /*  negative                */
> +    uint32_t Zf;     /*  zero                    */
> +    uint32_t Lf;
> +    uint32_t DZf;
> +    uint32_t SCf;
> +    uint32_t ESf;
> +    uint32_t RBf;
> +    uint32_t ADf;
> +    uint32_t USf;
> +    uint32_t IEf;
> +
> +    /* Reserved bits */
> +
> +    /* Next instruction is a delayslot instruction */
> +    uint32_t is_delay_slot_instruction;
> +} status_t;

"status_t" is much too general a name, and is not unlikely to conflict with
something from somewhere else.

Why are you exploding all of the bits of status anyway?  I would think that
only VCNZ should be handled specially, and only for the current context.

You should be using CamelCase as per CODING_STYLE, and probably using a prefix
of Arc or ARC for *everything*.

> +
> +/* ARC processor timer module. */
> +typedef struct {
> +    /*
> +     * TODO: This volatile is needed to pass RTC tests. We need to
> +     * verify why.
> +     */
> +    volatile uint32_t T_Cntrl;
> +    volatile uint32_t T_Limit;
> +    volatile uint64_t last_clk;

That is a serious bug, probably incorrect usage of locks.

> +typedef struct CPUARCState {
> +    uint32_t        r[64];
> +
> +    status_t stat, stat_l1, 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         */

Why is this here?  Surely it's redundant with r[63].

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

Why are these bits expanded to words?

> +    /* used for propagatinng "hostpc/return address" to sub-functions */
> +    uintptr_t host_pc;

This is a bad idea, IMO.

> +    /* Fields after this point are preserved across CPU reset. */
> +    uint64_t features;
> +    uint32_t family;

Usually such fields belong in ArchCPU (ArcCPU) and not CPUArchState.

> +  /* ARC Configuration Settings. */
> +  struct {
> +    uint32_t addr_size;
> +    bool     aps_feature;
> +    bool     byte_order;
> +    bool     bitscan_option;
> +    uint32_t br_bc_entries;

Please sort the fields by size/alignment.  This ordering is wasteful.

> +/* are we in user mode? */
> +static inline bool is_user_mode(const CPUARCState *env)
> +{
> +    return env->stat.Uf != false;
> +}

Well, ignoring for the moment that stat should not be expanded to words, this
is a silly way to return a bool.  Better as just

    return env->stat.Uf.

> +static inline int arc_feature(const CPUARCState *env, int feature)

Return bool.

> +static inline void  arc_set_feature(CPUARCState *env, int feature)

extra space.

> +static inline int cpu_mmu_index(const CPUARCState *env, bool ifetch)
> +{
> +    return env->stat.Uf != 0 ? 1 : 0;
> +}

That's a silly way to write Uf != 0.

> +    *pc = env->pc;
> +    *cs_base = 0;
> +#ifdef CONFIG_USER_ONLY
> +    *pflags = TB_FLAGS_FP_ENABLE;
> +#else
> +    *pflags = cpu_mmu_index(env, 0);
> +#endif

Why does !CONFIG_USER_ONLY never set TB_FLAGS_FP_ENABLE?

> +static inline int cpu_interrupts_enabled(const CPUARCState *env)
> +{
> +    return env->stat.IEf;
> +}

This is not used.  Copy and paste from some other target?

> +/* these are the helper functions used both by translation and gdbstub */
> +target_ulong helper_lr(CPUARCState *env, uint32_t aux);
> +void helper_sr(CPUARCState *env, uint32_t val, uint32_t aux);

Don't declare these twice, just include "exec/helper-proto.h" in gdbstub.c.


r~
diff mbox series

Patch

diff --git a/target/arc/arc-common.h b/target/arc/arc-common.h
new file mode 100644
index 0000000000..d931944149
--- /dev/null
+++ b/target/arc/arc-common.h
@@ -0,0 +1,54 @@ 
+/*
+ *  Common header file to be used by cpu and disassembler.
+ *  Copyright (C) 2017 Free Software Foundation, Inc.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GAS or GDB; see the file COPYING3. If not, write to
+ *  the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+ *  MA 02110-1301, USA.
+ */
+
+#ifndef ARC_COMMON_H
+#define ARC_COMMON_H
+
+
+/* CPU combi. */
+#define ARC_OPCODE_ARCALL  (ARC_OPCODE_ARC600 | ARC_OPCODE_ARC700       \
+                            | ARC_OPCODE_ARCv2EM | ARC_OPCODE_ARCv2HS)
+#define ARC_OPCODE_ARCFPX  (ARC_OPCODE_ARC700 | ARC_OPCODE_ARCv2EM)
+#define ARC_OPCODE_ARCV1   (ARC_OPCODE_ARC700 | ARC_OPCODE_ARC600)
+#define ARC_OPCODE_ARCV2   (ARC_OPCODE_ARCv2EM | ARC_OPCODE_ARCv2HS)
+#define ARC_OPCODE_ARCMPY6E  (ARC_OPCODE_ARC700 | ARC_OPCODE_ARCV2)
+
+
+enum arc_cpu_family {
+  ARC_OPCODE_NONE    = 0,
+  ARC_OPCODE_DEFAULT = 1 << 0,
+  ARC_OPCODE_ARC600  = 1 << 1,
+  ARC_OPCODE_ARC700  = 1 << 2,
+  ARC_OPCODE_ARCv2EM = 1 << 3,
+  ARC_OPCODE_ARCv2HS = 1 << 4
+};
+
+typedef struct {
+    uint32_t value;
+    uint32_t type;
+} operand_t;
+
+typedef struct {
+    uint32_t class;
+    uint32_t limm;
+    uint8_t len;
+    bool limm_p;
+    operand_t operands[3];
+    uint8_t n_ops;
+    uint8_t cc;
+    uint8_t aa;
+    uint8_t zz;
+    bool d;
+    bool f;
+    bool di;
+    bool x;
+} insn_t;
+
+#endif
diff --git a/target/arc/cpu-param.h b/target/arc/cpu-param.h
new file mode 100644
index 0000000000..512f4c8b75
--- /dev/null
+++ b/target/arc/cpu-param.h
@@ -0,0 +1,32 @@ 
+/*
+ * ARC cpu parameters for qemu.
+ *
+ * Copyright (c) 2020 Synopsys Inc.
+ * Contributed by Shahab Vahedi <shahab@synopsys.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ARC_CPU_PARAM_H
+#define ARC_CPU_PARAM_H 1
+
+#define TARGET_LONG_BITS            32
+#define TARGET_PAGE_BITS            13
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+#define NB_MMU_MODES                2
+
+#endif
+
+/*-*-indent-tabs-mode:nil;tab-width:4;indent-line-function:'insert-tab'-*-*/
+/* vim: set ts=4 sw=4 et: */
diff --git a/target/arc/cpu-qom.h b/target/arc/cpu-qom.h
new file mode 100644
index 0000000000..ee60db158d
--- /dev/null
+++ b/target/arc/cpu-qom.h
@@ -0,0 +1,52 @@ 
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2020 Synopsys Inc.
+ * Contributed by Cupertino Miranda <cmiranda@synopsys.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_ARC_CPU_QOM_H
+#define QEMU_ARC_CPU_QOM_H
+
+#include "hw/core/cpu.h"
+
+#define TYPE_ARC_CPU            "arc-cpu"
+
+#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.
+ *
+ *  A ARC CPU model.
+ */
+typedef struct ARCCPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    DeviceRealize parent_realize;
+    DeviceReset parent_reset;
+} ARCCPUClass;
+
+typedef struct ARCCPU ARCCPU;
+
+#endif
diff --git a/target/arc/cpu.c b/target/arc/cpu.c
new file mode 100644
index 0000000000..2baa19486d
--- /dev/null
+++ b/target/arc/cpu.c
@@ -0,0 +1,467 @@ 
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2020 Synopsys Inc.
+ * Contributed by Cupertino Miranda <cmiranda@synopsys.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "migration/vmstate.h"
+#include "exec/log.h"
+#include "mmu.h"
+#include "mpu.h"
+#include "hw/qdev-properties.h"
+#include "irq.h"
+#include "hw/arc/cpudevs.h"
+#include "timer.h"
+#include "internals.h"
+
+static const VMStateDescription vms_arc_cpu = {
+    .name               = "cpu",
+    .version_id         = 0,
+    .minimum_version_id = 0,
+    .fields = (VMStateField[]) {
+      VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property arc_cpu_properties[] = {
+    DEFINE_PROP_UINT32("address-size", ARCCPU, cfg.addr_size, 32),
+    DEFINE_PROP_BOOL("aps", ARCCPU, cfg.aps_feature, false),
+    DEFINE_PROP_BOOL("byte-order", ARCCPU, cfg.byte_order, false),
+    DEFINE_PROP_BOOL("bitscan", ARCCPU, cfg.bitscan_option, true),
+    DEFINE_PROP_UINT32("br_bc-entries", ARCCPU, cfg.br_bc_entries, -1),
+    DEFINE_PROP_UINT32("br_pt-entries", ARCCPU, cfg.br_pt_entries, -1),
+    DEFINE_PROP_BOOL("full-tag", ARCCPU, cfg.br_bc_full_tag, false),
+    DEFINE_PROP_UINT8("rs-entries", ARCCPU, cfg.br_rs_entries, -1),
+    DEFINE_PROP_UINT32("tag-size", ARCCPU, cfg.br_bc_tag_size, -1),
+    DEFINE_PROP_UINT8("tosq-entries", ARCCPU, cfg.br_tosq_entries, -1),
+    DEFINE_PROP_UINT8("fb-entries", ARCCPU, cfg.br_fb_entries, -1),
+    DEFINE_PROP_BOOL("code-density", ARCCPU, cfg.code_density, true),
+    DEFINE_PROP_BOOL("code-protect", ARCCPU, cfg.code_protect, false),
+    DEFINE_PROP_UINT8("dcc-memcyc", ARCCPU, cfg.dccm_mem_cycles, -1),
+    DEFINE_PROP_BOOL("ddcm-posedge", ARCCPU, cfg.dccm_posedge, false),
+    DEFINE_PROP_UINT8("dcc-mem-banks", ARCCPU, cfg.dccm_mem_bancks, -1),
+    DEFINE_PROP_UINT8("mem-cycles", ARCCPU, cfg.dc_mem_cycles, -1),
+    DEFINE_PROP_BOOL("dc-posedge", ARCCPU, cfg.dc_posedge, false),
+    DEFINE_PROP_BOOL("unaligned", ARCCPU, cfg.dmp_unaligned, true),
+    DEFINE_PROP_BOOL("ecc-excp", ARCCPU, cfg.ecc_exception, false),
+    DEFINE_PROP_UINT32("ext-irq", ARCCPU, cfg.external_interrupts, 128),
+    DEFINE_PROP_UINT8("ecc-option", ARCCPU, cfg.ecc_option, -1),
+    DEFINE_PROP_BOOL("firq", ARCCPU, cfg.firq_option, true),
+    DEFINE_PROP_BOOL("fpu-dp", ARCCPU, cfg.fpu_dp_option, false),
+    DEFINE_PROP_BOOL("fpu-fma", ARCCPU, cfg.fpu_fma_option, false),
+    DEFINE_PROP_BOOL("fpu-div", ARCCPU, cfg.fpu_div_option, false),
+    DEFINE_PROP_BOOL("actionpoints", ARCCPU, cfg.has_actionpoints, false),
+    DEFINE_PROP_BOOL("fpu", ARCCPU, cfg.has_fpu, false),
+    DEFINE_PROP_BOOL("has-irq", ARCCPU, cfg.has_interrupts, true),
+    DEFINE_PROP_BOOL("has-mmu", ARCCPU, cfg.has_mmu, true),
+    DEFINE_PROP_BOOL("has-mpu", ARCCPU, cfg.has_mpu, true),
+    DEFINE_PROP_BOOL("timer0", ARCCPU, cfg.has_timer_0, true),
+    DEFINE_PROP_BOOL("timer1", ARCCPU, cfg.has_timer_1, true),
+    DEFINE_PROP_BOOL("has-pct", ARCCPU, cfg.has_pct, false),
+    DEFINE_PROP_BOOL("has-rtt", ARCCPU, cfg.has_rtt, false),
+    DEFINE_PROP_BOOL("has-smart", ARCCPU, cfg.has_smart, false),
+    DEFINE_PROP_UINT32("intv-base", ARCCPU, cfg.intvbase_preset, 0x0),
+    DEFINE_PROP_UINT32("lpc-size", ARCCPU, cfg.lpc_size, 32),
+    DEFINE_PROP_UINT8("mpu-numreg", ARCCPU, cfg.mpu_num_regions, 0),
+    DEFINE_PROP_UINT8("mpy-option", ARCCPU, cfg.mpy_option, 2),
+    DEFINE_PROP_UINT32("mmu-pagesize0", ARCCPU, cfg.mmu_page_size_sel0, -1),
+    DEFINE_PROP_UINT32("mmu-pagesize1", ARCCPU, cfg.mmu_page_size_sel1, -1),
+    DEFINE_PROP_UINT32("mmu-pae", ARCCPU, cfg.mmu_pae_enabled, -1),
+    DEFINE_PROP_UINT32("ntlb-numentries", ARCCPU, cfg.ntlb_num_entries, -1),
+    DEFINE_PROP_UINT32("num-actionpoints", ARCCPU, cfg.num_actionpoints, -1),
+    DEFINE_PROP_UINT32("num-irq", ARCCPU, cfg.number_of_interrupts, 240),
+    DEFINE_PROP_UINT32("num-irqlevels", ARCCPU, cfg.number_of_levels, 15),
+    DEFINE_PROP_UINT32("pct-counters", ARCCPU, cfg.pct_counters, -1),
+    DEFINE_PROP_UINT32("pct-irq", ARCCPU, cfg.pct_interrupt, -1),
+    DEFINE_PROP_UINT32("pc-size", ARCCPU, cfg.pc_size, 32),
+    DEFINE_PROP_UINT32("num-regs", ARCCPU, cfg.rgf_num_regs, 32),
+    DEFINE_PROP_UINT32("banked-regs", ARCCPU, cfg.rgf_banked_regs, -1),
+    DEFINE_PROP_UINT32("num-banks", ARCCPU, cfg.rgf_num_banks, 0),
+    DEFINE_PROP_BOOL("rtc-opt", ARCCPU, cfg.rtc_option, false),
+    DEFINE_PROP_UINT32("rtt-featurelevel", ARCCPU, cfg.rtt_feature_level, -1),
+    DEFINE_PROP_BOOL("stack-check", ARCCPU, cfg.stack_checking, false),
+    DEFINE_PROP_BOOL("swap-option", ARCCPU, cfg.swap_option, true),
+    DEFINE_PROP_UINT32("smrt-stackentries", ARCCPU, cfg.smar_stack_entries, -1),
+    DEFINE_PROP_UINT32("smrt-impl", ARCCPU, cfg.smart_implementation, -1),
+    DEFINE_PROP_UINT32("stlb", ARCCPU, cfg.stlb_num_entries, -1),
+    DEFINE_PROP_UINT32("slc-size", ARCCPU, cfg.slc_size, -1),
+    DEFINE_PROP_UINT32("slc-linesize", ARCCPU, cfg.slc_line_size, -1),
+    DEFINE_PROP_UINT32("slc-ways", ARCCPU, cfg.slc_ways, -1),
+    DEFINE_PROP_UINT32("slc-tagbanks", ARCCPU, cfg.slc_tag_banks, -1),
+    DEFINE_PROP_UINT32("slc-tram", ARCCPU, cfg.slc_tram_delay, -1),
+    DEFINE_PROP_UINT32("slc-dbank", ARCCPU, cfg.slc_dbank_width, -1),
+    DEFINE_PROP_UINT32("slc-data", ARCCPU, cfg.slc_data_banks, -1),
+    DEFINE_PROP_UINT32("slc-delay", ARCCPU, cfg.slc_dram_delay, -1),
+    DEFINE_PROP_BOOL("slc-memwidth", ARCCPU, cfg.slc_mem_bus_width, false),
+    DEFINE_PROP_UINT32("slc-ecc", ARCCPU, cfg.slc_ecc_option, -1),
+    DEFINE_PROP_BOOL("slc-datahalf", ARCCPU, cfg.slc_data_halfcycle_steal, false),
+    DEFINE_PROP_BOOL("slc-dataadd", ARCCPU, cfg.slc_data_add_pre_pipeline, false),
+    DEFINE_PROP_BOOL("uaux", ARCCPU, cfg.uaux_option, false),
+    DEFINE_PROP_UINT32("freq_hz", ARCCPU, cfg.freq_hz, 4600000),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+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 cs->interrupt_request & CPU_INTERRUPT_HARD;
+}
+
+static void arc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
+{
+  ARCCPU      *cpu = ARC_CPU(cs);
+  CPUARCState *env = &cpu->env;
+
+  CPU_PCL(&cpu->env) = tb->pc & 0xfffffffc;
+  env->pc = tb->pc;
+}
+
+static void arc_cpu_reset(DeviceState *dev)
+{
+  CPUState *s = CPU(dev);
+  ARCCPU *cpu = ARC_CPU(s);
+  ARCCPUClass *arcc = ARC_CPU_GET_CLASS(cpu);
+  CPUARCState *env = &cpu->env;
+
+  if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+    qemu_log("CPU Reset (CPU)\n");
+    log_cpu_state(s, 0);
+  }
+
+  /* Initialize mmu/reset it. */
+  arc_mmu_init(&env->mmu);
+
+  arc_mpu_init(cpu);
+
+  arc_resetTIMER(cpu);
+  arc_resetIRQ(cpu);
+
+  arcc->parent_reset(dev);
+
+  memset(env->r, 0, sizeof(env->r));
+  env->lock_lf_var = 0;
+
+  env->stat.is_delay_slot_instruction = 0;
+    /*
+     * kernel expects MPY support to check for presence of
+     * extension core regs r58/r59.
+     *
+     * VERSION32x32=0x06: ARCv2 32x32 Multiply
+     * DSP=0x1: MPY_OPTION 7
+     */
+    env->mpy_build = 0x00001006;
+}
+
+static void arc_cpu_disas_set_info(CPUState *cs, disassemble_info *info)
+{
+  ARCCPU *cpu = ARC_CPU(cs);
+  CPUARCState *env = &cpu->env;
+
+  switch (env->family) {
+  case ARC_OPCODE_ARC700:
+    info->mach = bfd_mach_arc_arc700;
+    break;
+  case ARC_OPCODE_ARC600:
+    info->mach = bfd_mach_arc_arc600;
+    break;
+  case ARC_OPCODE_ARCv2EM:
+    info->mach = bfd_mach_arc_arcv2em;
+    break;
+  case ARC_OPCODE_ARCv2HS:
+    info->mach = bfd_mach_arc_arcv2hs;
+    break;
+  default:
+    info->mach = bfd_mach_arc_arcv2;
+    break;
+  }
+
+  info->print_insn = print_insn_arc;
+  info->endian = BFD_ENDIAN_LITTLE;
+}
+
+
+static void arc_cpu_realizefn(DeviceState *dev, Error **errp)
+{
+  CPUState *cs = CPU(dev);
+  ARCCPU *cpu = ARC_CPU(dev);
+  ARCCPUClass *arcc = ARC_CPU_GET_CLASS(dev);
+  Error *local_err = NULL;
+  CPUARCState *env = &cpu->env;
+
+  cpu_exec_realizefn(cs, &local_err);
+  if (local_err != NULL) {
+    error_propagate(errp, local_err);
+    return;
+  }
+
+  arc_cpu_register_gdb_regs_for_features(cpu);
+
+  qemu_init_vcpu(cs);
+
+  /*
+   * Initialize build registers depending on the simulation
+   * parameters.
+   */
+  env->freq_hz = cpu->cfg.freq_hz;
+
+  env->isa_config = 0x02;
+  switch (cpu->cfg.pc_size) {
+  case 16:
+    break;
+  case 20:
+    env->isa_config |= 1 << 8;
+    break;
+  case 24:
+    env->isa_config |= 2 << 8;
+    break;
+  case 28:
+    env->isa_config |= 3 << 8;
+    break;
+  default:
+    env->isa_config |= 4 << 8;
+    break;
+  }
+
+  switch (cpu->cfg.lpc_size) {
+  case 0:
+    break;
+  case 8:
+    env->isa_config |= 1 << 12;
+    break;
+  case 12:
+    env->isa_config |= 2 << 12;
+    break;
+  case 16:
+    env->isa_config |= 3 << 12;
+    break;
+  case 20:
+    env->isa_config |= 4 << 12;
+    break;
+  case 24:
+    env->isa_config |= 5 << 12;
+    break;
+  case 28:
+    env->isa_config |= 6 << 12;
+    break;
+  default:
+    env->isa_config |= 7 << 12;
+    break;
+  }
+
+  switch (cpu->cfg.addr_size) {
+  case 16:
+    break;
+  case 20:
+    env->isa_config |= 1 << 16;
+    break;
+  case 24:
+    env->isa_config |= 2 << 16;
+    break;
+  case 28:
+    env->isa_config |= 3 << 16;
+    break;
+  default:
+    env->isa_config |= 4 << 16;
+    break;
+  }
+
+  env->isa_config |= (cpu->cfg.byte_order ? BIT(20) : 0) | BIT(21)
+    | (cpu->cfg.dmp_unaligned ? BIT(22) : 0) | BIT(23)
+    | (cpu->cfg.code_density ? (2 << 24) : 0) | BIT(28);
+
+  arc_initializeTIMER(cpu);
+  arc_initializeIRQ(cpu);
+
+  cpu_reset(cs);
+
+  arcc->parent_realize(dev, errp);
+}
+
+static void arc_cpu_initfn(Object *obj)
+{
+  ARCCPU *cpu = ARC_CPU(obj);
+
+  /* Initialize aux-regs. */
+  arc_aux_regs_init();
+
+  cpu_set_cpustate_pointers(cpu);
+}
+
+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 gchar *arc_gdb_arch_name(CPUState *cs)
+{
+    return g_strdup("arc:ARCv2");
+}
+
+static void arc_cpu_class_init(ObjectClass *oc, void *data)
+{
+  DeviceClass *dc = DEVICE_CLASS(oc);
+  CPUClass *cc = CPU_CLASS(oc);
+  ARCCPUClass *arcc = ARC_CPU_CLASS(oc);
+
+  device_class_set_parent_realize(dc, arc_cpu_realizefn,
+                                  &arcc->parent_realize);
+
+  device_class_set_parent_reset(dc, arc_cpu_reset, &arcc->parent_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;
+#ifndef CONFIG_USER_ONLY
+  cc->memory_rw_debug = arc_cpu_memory_rw_debug;
+  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;
+
+  /* Core GDB support */
+  cc->gdb_core_xml_file = "arc-v2-core.xml";
+  cc->gdb_num_core_regs = GDB_REG_LAST;
+  cc->gdb_arch_name = arc_gdb_arch_name;
+
+#ifdef CONFIG_TCG
+    cc->tcg_initialize = arc_translate_init;
+    cc->tlb_fill = arc_cpu_tlb_fill;
+#endif
+    device_class_set_props(dc, arc_cpu_properties);
+}
+
+static void arc_any_initfn(Object *obj)
+{
+  /* Set cpu feature flags */
+  ARCCPU *cpu = ARC_CPU(obj);
+  cpu->env.family = ARC_OPCODE_ARC700;
+}
+
+static void arc600_initfn(Object *obj)
+{
+  ARCCPU *cpu = ARC_CPU(obj);
+  cpu->env.family = ARC_OPCODE_ARC600;
+}
+
+static void arc700_initfn(Object *obj)
+{
+  ARCCPU *cpu = ARC_CPU(obj);
+  cpu->env.family = ARC_OPCODE_ARC700;
+}
+
+static void arcem_initfn(Object *obj)
+{
+  ARCCPU *cpu = ARC_CPU(obj);
+  cpu->env.family = ARC_OPCODE_ARCv2EM;
+}
+
+static void archs_initfn(Object *obj)
+{
+  ARCCPU *cpu = ARC_CPU(obj);
+  cpu->env.family = ARC_OPCODE_ARCv2HS;
+}
+
+typedef struct ARCCPUInfo {
+  const char     *name;
+  void (*initfn)(Object *obj);
+} ARCCPUInfo;
+
+static const ARCCPUInfo arc_cpus[] = {
+  { .name = "arc600", .initfn = arc600_initfn },
+  { .name = "arc700", .initfn = arc700_initfn },
+  { .name = "arcem", .initfn = arcem_initfn },
+  { .name = "archs", .initfn = archs_initfn },
+  { .name = "any", .initfn = arc_any_initfn },
+};
+
+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)
+
+
+/*-*-indent-tabs-mode:nil;tab-width:4;indent-line-function:'insert-tab'-*-*/
+/* vim: set ts=4 sw=4 et: */
diff --git a/target/arc/cpu.h b/target/arc/cpu.h
new file mode 100644
index 0000000000..d5408c6fea
--- /dev/null
+++ b/target/arc/cpu.h
@@ -0,0 +1,531 @@ 
+/*
+ * QEMU ARC CPU
+ *
+ * Copyright (c) 2020 Synopsys Inc.
+ * Contributed by Cupertino Miranda <cmiranda@synopsys.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CPU_ARC_H
+#define CPU_ARC_H
+
+#include "cpu-qom.h"
+#include "exec/cpu-defs.h"
+#include "fpu/softfloat.h"
+
+#include "target/arc/arc-common.h"
+#include "target/arc/mmu.h"
+#include "target/arc/mpu.h"
+#include "target/arc/cache.h"
+
+#define ARC_CPU_TYPE_SUFFIX "-" TYPE_ARC_CPU
+#define ARC_CPU_TYPE_NAME(model) model ARC_CPU_TYPE_SUFFIX
+#define CPU_RESOLVING_TYPE TYPE_ARC_CPU
+
+#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,
+};
+
+enum arc_endianess {
+    ARC_ENDIANNESS_LE = 0,
+    ARC_ENDIANNESS_BE,
+};
+
+/* U-Boot - kernel ABI */
+#define ARC_UBOOT_CMDLINE 1
+#define ARC_UBOOT_DTB     2
+
+enum gdb_regs {
+    GDB_REG_0 = 0,
+    GDB_REG_1,
+    GDB_REG_2,
+    GDB_REG_3,
+    GDB_REG_4,
+    GDB_REG_5,
+    GDB_REG_6,
+    GDB_REG_7,
+    GDB_REG_8,
+    GDB_REG_9,
+    GDB_REG_10,
+    GDB_REG_11,
+    GDB_REG_12,
+    GDB_REG_13,
+    GDB_REG_14,
+    GDB_REG_15,
+    GDB_REG_16,
+    GDB_REG_17,
+    GDB_REG_18,
+    GDB_REG_19,
+    GDB_REG_20,
+    GDB_REG_21,
+    GDB_REG_22,
+    GDB_REG_23,
+    GDB_REG_24,
+    GDB_REG_25,
+    GDB_REG_26,         /* GP                         */
+    GDB_REG_27,         /* FP                         */
+    GDB_REG_28,         /* SP                         */
+    GDB_REG_29,         /* ILINK                      */
+    GDB_REG_30,         /* R30                        */
+    GDB_REG_31,         /* BLINK                      */
+    GDB_REG_58,         /* little_endian? ACCL : ACCH */
+    GDB_REG_59,         /* little_endian? ACCH : ACCL */
+    GDB_REG_60,         /* LP                         */
+    GDB_REG_63,         /* Immediate                  */
+    GDB_REG_LAST
+};
+
+enum gdb_aux_min_regs {
+    GDB_AUX_MIN_REG_PC = 0, /* program counter */
+    GDB_AUX_MIN_REG_LPS,    /* loop body start */
+    GDB_AUX_MIN_REG_LPE,    /* loop body end   */
+    GDB_AUX_MIN_REG_STATUS, /* status flag     */
+    GDB_AUX_MIN_REG_LAST
+};
+
+enum gdb_aux_other_regs {
+    /* builds */
+    GDB_AUX_OTHER_REG_TIMER_BUILD = 0,  /* timer build                */
+    GDB_AUX_OTHER_REG_IRQ_BUILD,        /* irq build                  */
+    GDB_AUX_OTHER_REG_MPY_BUILD,        /* multiply configuration     */
+    GDB_AUX_OTHER_REG_VECBASE_BUILD,    /* vector base address config */
+    GDB_AUX_OTHER_REG_ISA_CONFIG,       /* isa config                 */
+    /* timers */
+    GDB_AUX_OTHER_REG_TIMER_CNT0,       /* timer 0 counter */
+    GDB_AUX_OTHER_REG_TIMER_CTRL0,      /* timer 0 control */
+    GDB_AUX_OTHER_REG_TIMER_LIM0,       /* timer 0 limit   */
+    GDB_AUX_OTHER_REG_TIMER_CNT1,       /* timer 1 counter */
+    GDB_AUX_OTHER_REG_TIMER_CTRL1,      /* timer 1 control */
+    GDB_AUX_OTHER_REG_TIMER_LIM1,       /* timer 1 limit   */
+    /* mmu */
+    GDB_AUX_OTHER_REG_PID,              /* process identity  */
+    GDB_AUX_OTHER_REG_TLBPD0,           /* page descriptor 0 */
+    GDB_AUX_OTHER_REG_TLBPD1,           /* page descriptor 1 */
+    GDB_AUX_OTHER_REG_TLB_INDEX,        /* tlb index         */
+    GDB_AUX_OTHER_REG_TLB_CMD,          /* tlb command       */
+    /* mpu */
+    GDB_AUX_OTHER_REG_MPU_BUILD,        /* MPU build           */
+    GDB_AUX_OTHER_REG_MPU_EN,           /* MPU enable          */
+    GDB_AUX_OTHER_REG_MPU_ECR,          /* MPU exception cause */
+    GDB_AUX_OTHER_REG_MPU_BASE0,        /* MPU base 0          */
+    GDB_AUX_OTHER_REG_MPU_BASE1,        /* MPU base 1          */
+    GDB_AUX_OTHER_REG_MPU_BASE2,        /* MPU base 2          */
+    GDB_AUX_OTHER_REG_MPU_BASE3,        /* MPU base 3          */
+    GDB_AUX_OTHER_REG_MPU_BASE4,        /* MPU base 4          */
+    GDB_AUX_OTHER_REG_MPU_BASE5,        /* MPU base 5          */
+    GDB_AUX_OTHER_REG_MPU_BASE6,        /* MPU base 6          */
+    GDB_AUX_OTHER_REG_MPU_BASE7,        /* MPU base 7          */
+    GDB_AUX_OTHER_REG_MPU_BASE8,        /* MPU base 8          */
+    GDB_AUX_OTHER_REG_MPU_BASE9,        /* MPU base 9          */
+    GDB_AUX_OTHER_REG_MPU_BASE10,       /* MPU base 10         */
+    GDB_AUX_OTHER_REG_MPU_BASE11,       /* MPU base 11         */
+    GDB_AUX_OTHER_REG_MPU_BASE12,       /* MPU base 12         */
+    GDB_AUX_OTHER_REG_MPU_BASE13,       /* MPU base 13         */
+    GDB_AUX_OTHER_REG_MPU_BASE14,       /* MPU base 14         */
+    GDB_AUX_OTHER_REG_MPU_BASE15,       /* MPU base 15         */
+    GDB_AUX_OTHER_REG_MPU_PERM0,        /* MPU permission 0    */
+    GDB_AUX_OTHER_REG_MPU_PERM1,        /* MPU permission 1    */
+    GDB_AUX_OTHER_REG_MPU_PERM2,        /* MPU permission 2    */
+    GDB_AUX_OTHER_REG_MPU_PERM3,        /* MPU permission 3    */
+    GDB_AUX_OTHER_REG_MPU_PERM4,        /* MPU permission 4    */
+    GDB_AUX_OTHER_REG_MPU_PERM5,        /* MPU permission 5    */
+    GDB_AUX_OTHER_REG_MPU_PERM6,        /* MPU permission 6    */
+    GDB_AUX_OTHER_REG_MPU_PERM7,        /* MPU permission 7    */
+    GDB_AUX_OTHER_REG_MPU_PERM8,        /* MPU permission 8    */
+    GDB_AUX_OTHER_REG_MPU_PERM9,        /* MPU permission 9    */
+    GDB_AUX_OTHER_REG_MPU_PERM10,       /* MPU permission 10   */
+    GDB_AUX_OTHER_REG_MPU_PERM11,       /* MPU permission 11   */
+    GDB_AUX_OTHER_REG_MPU_PERM12,       /* MPU permission 12   */
+    GDB_AUX_OTHER_REG_MPU_PERM13,       /* MPU permission 13   */
+    GDB_AUX_OTHER_REG_MPU_PERM14,       /* MPU permission 14   */
+    GDB_AUX_OTHER_REG_MPU_PERM15,       /* MPU permission 15   */
+    /* excpetions */
+    GDB_AUX_OTHER_REG_ERSTATUS,         /* exception return status  */
+    GDB_AUX_OTHER_REG_ERBTA,            /* exception return BTA     */
+    GDB_AUX_OTHER_REG_ECR,              /* exception cause register */
+    GDB_AUX_OTHER_REG_ERET,             /* exception return address */
+    GDB_AUX_OTHER_REG_EFA,              /* exception fault address  */
+    /* irq */
+    GDB_AUX_OTHER_REG_ICAUSE,           /* interrupt cause        */
+    GDB_AUX_OTHER_REG_IRQ_CTRL,         /* context saving control */
+    GDB_AUX_OTHER_REG_IRQ_ACT,          /* active                 */
+    GDB_AUX_OTHER_REG_IRQ_PRIO_PEND,    /* priority pending       */
+    GDB_AUX_OTHER_REG_IRQ_HINT,         /* hint                   */
+    GDB_AUX_OTHER_REG_IRQ_SELECT,       /* select                 */
+    GDB_AUX_OTHER_REG_IRQ_ENABLE,       /* enable                 */
+    GDB_AUX_OTHER_REG_IRQ_TRIGGER,      /* trigger                */
+    GDB_AUX_OTHER_REG_IRQ_STATUS,       /* status                 */
+    GDB_AUX_OTHER_REG_IRQ_PULSE,        /* pulse cancel           */
+    GDB_AUX_OTHER_REG_IRQ_PENDING,      /* pending                */
+    GDB_AUX_OTHER_REG_IRQ_PRIO,         /* priority               */
+    /* miscellaneous */
+    GDB_AUX_OTHER_REG_BTA,              /* branch target address */
+
+    GDB_AUX_OTHER_REG_LAST
+};
+
+#define CPU_GP(env)     ((env)->r[26])
+#define CPU_FP(env)     ((env)->r[27])
+#define CPU_SP(env)     ((env)->r[28])
+#define CPU_ILINK(env)  ((env)->r[29])
+#define CPU_ILINK1(env) ((env)->r[29])
+#define CPU_ILINK2(env) ((env)->r[30])
+#define CPU_BLINK(env)  ((env)->r[31])
+#define CPU_LP(env)     ((env)->r[60])
+#define CPU_IMM(env)    ((env)->r[62])
+#define CPU_PCL(env)    ((env)->r[63])
+
+enum exception_code_list {
+    EXCP_NO_EXCEPTION = -1,
+    EXCP_RESET = 0,
+    EXCP_MEMORY_ERROR,
+    EXCP_INST_ERROR,
+    EXCP_MACHINE_CHECK,
+    EXCP_TLB_MISS_I,
+    EXCP_TLB_MISS_D,
+    EXCP_PROTV,
+    EXCP_PRIVILEGEV,
+    EXCP_SWI,
+    EXCP_TRAP,
+    EXCP_EXTENSION,
+    EXCP_DIVZERO,
+    EXCP_DCERROR,
+    EXCP_MISALIGNED,
+    EXCP_IRQ,
+    EXCP_LPEND_REACHED = 9000,
+    EXCP_FAKE
+};
+
+typedef struct status_register {
+    uint32_t Hf;     /* halt                    */
+    uint32_t Ef;     /* irq priority treshold. */
+    uint32_t AEf;
+    uint32_t DEf;
+    uint32_t Uf;
+    uint32_t Vf;     /*  overflow                */
+    uint32_t Cf;     /*  carry                   */
+    uint32_t Nf;     /*  negative                */
+    uint32_t Zf;     /*  zero                    */
+    uint32_t Lf;
+    uint32_t DZf;
+    uint32_t SCf;
+    uint32_t ESf;
+    uint32_t RBf;
+    uint32_t ADf;
+    uint32_t USf;
+    uint32_t IEf;
+
+    /* Reserved bits */
+
+    /* Next instruction is a delayslot instruction */
+    uint32_t is_delay_slot_instruction;
+} status_t;
+
+/* ARC processor timer module. */
+typedef struct {
+    /*
+     * TODO: This volatile is needed to pass RTC tests. We need to
+     * verify why.
+     */
+    volatile uint32_t T_Cntrl;
+    volatile uint32_t T_Limit;
+    volatile uint64_t last_clk;
+} arc_timer_t;
+
+/* ARC PIC interrupt bancked regs. */
+typedef struct {
+    uint32_t priority;
+    uint32_t trigger;
+    uint32_t pulse_cancel;
+    uint32_t enable;
+    uint32_t pending;
+    uint32_t status;
+} arc_irq_t;
+
+typedef struct CPUARCState {
+    uint32_t        r[64];
+
+    status_t stat, stat_l1, 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               */
+
+    uint32_t npc;    /* required for LP - zero overhead loops. */
+
+    uint32_t lock_lf_var;
+
+    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;
+
+#define TMR_IE  (1 << 0)
+#define TMR_NH  (1 << 1)
+#define TMR_W   (1 << 2)
+#define TMR_IP  (1 << 3)
+#define TMR_PD  (1 << 4)
+    arc_timer_t timer[2];    /* ARC CPU-Timer 0/1 */
+
+    arc_irq_t irq_bank[256]; /* IRQ register bank */
+    uint32_t irq_select;     /* AUX register */
+    uint32_t aux_irq_act;    /* AUX register */
+    uint32_t irq_priority_pending; /* AUX register */
+    uint32_t icause[16];     /* Banked cause register */
+    uint32_t aux_irq_hint;   /* AUX register, used to trigger soft irq */
+    uint32_t aux_user_sp;
+    uint32_t aux_irq_ctrl;
+    uint32_t aux_rtc_ctrl;
+    uint32_t aux_rtc_low;
+    uint32_t aux_rtc_high;
+
+    /* Fields required by exception handling. */
+    uint32_t causecode;
+    uint32_t param;
+
+    struct arc_mmu mmu;       /* mmu.h */
+    ARCMPU mpu;               /* mpu.h */
+    struct arc_cache cache;   /* cache.h */
+
+    /* used for propagatinng "hostpc/return address" to sub-functions */
+    uintptr_t host_pc;
+
+    bool      stopped;
+
+    /* Fields up to this point are cleared by a CPU reset */
+    struct {} end_reset_fields;
+
+    /* Fields after this point are preserved across CPU reset. */
+    uint64_t features;
+    uint32_t family;
+
+    uint32_t freq_hz; /* CPU frequency in hz, needed for timers. */
+    uint64_t last_clk_rtc;
+
+    void *irq[256];
+    QEMUTimer *cpu_timer[2]; /* Internal timer. */
+    QEMUTimer *cpu_rtc;      /* Internal RTC. */
+
+    /* Build AUX regs. */
+#define TIMER0_IRQ 16
+#define TIMER1_IRQ 17
+#define TB_T0  (1 << 8)
+#define TB_T1  (1 << 9)
+#define TB_RTC (1 << 10)
+#define TB_P0_MSK (0x0f0000)
+#define TB_P1_MSK (0xf00000)
+    uint32_t timer_build;   /* Timer configuration AUX register. */
+    uint32_t irq_build;     /* Interrupt Build Configuration Register. */
+    uint32_t vecbase_build; /* Interrupt Vector Base Address Configuration. */
+    uint32_t mpy_build;     /* Multiply configuration register. */
+    uint32_t isa_config;    /* Instruction Set Configuration Register. */
+
+    const struct arc_boot_info *boot_info;
+} CPUARCState;
+
+/*
+ * ArcCPU:
+ * @env: #CPUMBState
+ *
+ * An ARC CPU.
+ */
+struct ARCCPU {
+  /*< private >*/
+  CPUState parent_obj;
+
+  /*< public >*/
+
+  /* ARC Configuration Settings. */
+  struct {
+    uint32_t addr_size;
+    bool     aps_feature;
+    bool     byte_order;
+    bool     bitscan_option;
+    uint32_t br_bc_entries;
+    uint32_t br_pt_entries;
+    bool     br_bc_full_tag;
+    uint8_t  br_rs_entries;
+    uint32_t br_bc_tag_size;
+    uint8_t  br_tosq_entries;
+    uint8_t  br_fb_entries;
+    bool     code_density;
+    bool     code_protect;
+    uint8_t  dccm_mem_cycles;
+    bool     dccm_posedge;
+    uint8_t  dccm_mem_bancks;
+    uint8_t  dc_mem_cycles;
+    bool     dc_posedge;
+    bool     dmp_unaligned;
+    bool     ecc_exception;
+    uint32_t external_interrupts;
+    uint8_t  ecc_option;
+    bool     firq_option;
+    bool     fpu_dp_option;
+    bool     fpu_fma_option;
+    bool     fpu_div_option;
+    bool     has_actionpoints;
+    bool     has_fpu;
+    bool     has_interrupts;
+    bool     has_mmu;
+    bool     has_mpu;
+    bool     has_timer_0;
+    bool     has_timer_1;
+    bool     has_pct;
+    bool     has_rtt;
+    bool     has_smart;
+    uint32_t intvbase_preset;
+    uint32_t lpc_size;
+    uint8_t  mpu_num_regions;
+    uint8_t  mpy_option;
+    uint32_t mmu_page_size_sel0;
+    uint32_t mmu_page_size_sel1;
+    uint32_t mmu_pae_enabled;
+    uint32_t ntlb_num_entries;
+    uint32_t num_actionpoints;
+    uint32_t number_of_interrupts;
+    uint32_t number_of_levels;
+    uint32_t pct_counters;
+    uint32_t pct_interrupt;
+    uint32_t pc_size;
+    uint32_t rgf_num_regs;
+    uint32_t rgf_banked_regs;
+    uint32_t rgf_num_banks;
+    bool     rtc_option;
+    uint32_t rtt_feature_level;
+    bool     stack_checking;
+    bool     swap_option;
+    uint32_t smar_stack_entries;
+    uint32_t smart_implementation;
+    uint32_t stlb_num_entries;
+    uint32_t slc_size;
+    uint32_t slc_line_size;
+    uint32_t slc_ways;
+    uint32_t slc_tag_banks;
+    uint32_t slc_tram_delay;
+    uint32_t slc_dbank_width;
+    uint32_t slc_data_banks;
+    uint32_t slc_dram_delay;
+    bool     slc_mem_bus_width;
+    uint32_t slc_ecc_option;
+    bool     slc_data_halfcycle_steal;
+    bool     slc_data_add_pre_pipeline;
+    bool     uaux_option;
+    uint32_t freq_hz; /* CPU frequency in hz, needed for timers. */
+  } cfg;
+
+  CPUNegativeOffsetState neg;
+  CPUARCState env;
+};
+
+/* are we in user mode? */
+static inline bool is_user_mode(const CPUARCState *env)
+{
+    return env->stat.Uf != false;
+}
+
+static inline int arc_feature(const 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
+#define cpu_init(cpu_model) cpu_generic_init(TYPE_ARC_CPU, cpu_model)
+
+typedef CPUARCState CPUArchState;
+typedef ARCCPU ArchCPU;
+
+#include "exec/cpu-all.h"
+
+static inline int cpu_mmu_index(const CPUARCState *env, bool ifetch)
+{
+    return env->stat.Uf != 0 ? 1 : 0;
+}
+
+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;
+#ifdef CONFIG_USER_ONLY
+    *pflags = TB_FLAGS_FP_ENABLE;
+#else
+    *pflags = cpu_mmu_index(env, 0);
+#endif
+}
+
+static inline int cpu_interrupts_enabled(const CPUARCState *env)
+{
+    return env->stat.IEf;
+}
+
+void arc_translate_init(void);
+
+void arc_cpu_list(void);
+int cpu_arc_exec(CPUState *cpu);
+int cpu_arc_signal_handler(int host_signum, void *pinfo, void *puc);
+bool arc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+                      MMUAccessType access_type, int mmu_idx,
+                      bool probe, uintptr_t retaddr);
+int arc_cpu_memory_rw_debug(CPUState *cs, vaddr address, uint8_t *buf,
+                            int len, bool is_write);
+void arc_cpu_do_interrupt(CPUState *cpu);
+
+void arc_cpu_dump_state(CPUState *cs, FILE *f, int flags);
+hwaddr arc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int arc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
+int arc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+
+void QEMU_NORETURN arc_raise_exception(CPUARCState *env, int32_t excp_idx);
+
+#include "exec/cpu-all.h"
+
+#endif /* !defined (CPU_ARC_H) */
diff --git a/target/arc/internals.h b/target/arc/internals.h
new file mode 100644
index 0000000000..ee054e186a
--- /dev/null
+++ b/target/arc/internals.h
@@ -0,0 +1,38 @@ 
+/*
+ * QEMU ARC CPU -- internal functions
+ *
+ * Copyright (c) 2019 Synopsys Inc
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * This header shares funtions prototypes between codes in
+ * target/arc/ that must remain private to it and not to be
+ * used by QEMU itself.
+ */
+
+#ifndef TARGET_ARC_INTERNALS_H
+#define TARGET_ARC_INTERNALS_H
+
+#include "cpu.h"
+
+/* add auxiliary registers to set of supported registers for GDB */
+void arc_cpu_register_gdb_regs_for_features(ARCCPU *cpu);
+
+/* these are the helper functions used both by translation and gdbstub */
+target_ulong helper_lr(CPUARCState *env, uint32_t aux);
+void helper_sr(CPUARCState *env, uint32_t val, uint32_t aux);
+
+#endif
diff --git a/target/arc/meson.build b/target/arc/meson.build
new file mode 100644
index 0000000000..67f1e4bfa2
--- /dev/null
+++ b/target/arc/meson.build
@@ -0,0 +1,20 @@ 
+arc_softmmu_ss = ss.source_set()
+arc_softmmu_ss.add(files(
+  'translate.c',
+  'helper.c',
+  'cpu.c',
+  'op_helper.c',
+  'gdbstub.c',
+  'decoder.c',
+  'regs.c',
+  'semfunc.c',
+  'semfunc-helper.c',
+  'mmu.c',
+  'mpu.c',
+  'timer.c',
+  'irq.c',
+  'cache.c',
+))
+
+target_arch += {'arc': arc_softmmu_ss}
+target_softmmu_arch += {'arc': arc_softmmu_ss}