qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/4] Altera NiosII Support (v2)
@ 2012-11-11  4:18 crwulff
  2012-11-11  4:18 ` [Qemu-devel] [PATCH 1/4] NiosII: Add support for the Altera NiosII soft-core CPU. (v2) crwulff
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: crwulff @ 2012-11-11  4:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: Chris Wulff

From: Chris Wulff <crwulff@gmail.com>

This set of patches adds support for the Altera NiosII soft-core processor. Included are support for the CPU core and the drivers needed to boot Linux (Interrupt controller, Timer and Serial port.) There are quite a few changes suggested by the first round review. These include:

  * Better CPU code generation
  * Better support for QOM
  * A bunch of coding style cleanups (struct naming, merging GDB imported disassembly, etc.)
  * Updated for changes to the current head of the tree

I've also dropped the device-tree based board configurations from this patch set. Those currently depend heavily on fdt-generic patches from Peter Crosthwaite that have yet to make it into the main tree. This set of patches builds the NiosII core without errors but will report no machine found. I will resubmit those board configurations under a separate patch set once the integration and cleanup is complete for the fdt-generic board configurations is completed.


Chris Wulff (4):
  NiosII: Add support for the Altera NiosII soft-core CPU.
  NiosII: Disassembly of NiosII instructions ported from GDB.
  Altera: Add support for devices needed to boot Linux on NiosII.
  NiosII: Build system and documentation integration.

 MAINTAINERS                          |    5 +
 Makefile.objs                        |    1 +
 arch_init.c                          |    2 +
 arch_init.h                          |    1 +
 configure                            |   11 +
 cpu-exec.c                           |   12 +-
 default-configs/nios2-linux-user.mak |    1 +
 default-configs/nios2-softmmu.mak    |    5 +
 dis-asm.h                            |    3 +
 disas.c                              |    3 +
 elf.h                                |    2 +
 exec.c                               |    6 +-
 gdbstub.c                            |   29 +
 hw/Makefile.objs                     |    5 +
 hw/altera_timer.c                    |  207 ++
 hw/altera_uart.c                     |  217 +++
 hw/altera_vic.c                      |  194 ++
 hw/nios2.h                           |   52 +
 hw/nios2/Makefile.objs               |    3 +
 hw/nios2_pic_cpu.c                   |   39 +
 linux-user/elfload.c                 |   29 +
 monitor.c                            |    5 +-
 nios2-dis.c                          | 3478 ++++++++++++++++++++++++++++++++++
 qapi-schema.json                     |    2 +-
 qemu-doc.texi                        |    3 +
 target-nios2/Makefile.objs           |    5 +
 target-nios2/altera_iic.c            |  101 +
 target-nios2/cpu.c                   |   83 +
 target-nios2/cpu.h                   |  302 +++
 target-nios2/helper.c                |  291 +++
 target-nios2/helper.h                |   45 +
 target-nios2/instruction.c           | 1405 ++++++++++++++
 target-nios2/instruction.h           |  279 +++
 target-nios2/machine.c               |   33 +
 target-nios2/mmu.c                   |  273 +++
 target-nios2/mmu.h                   |   49 +
 target-nios2/op_helper.c             |  119 ++
 target-nios2/translate.c             |  253 +++
 38 files changed, 7547 insertions(+), 6 deletions(-)
 create mode 100644 default-configs/nios2-linux-user.mak
 create mode 100644 default-configs/nios2-softmmu.mak
 create mode 100644 hw/altera_timer.c
 create mode 100644 hw/altera_uart.c
 create mode 100644 hw/altera_vic.c
 create mode 100644 hw/nios2.h
 create mode 100644 hw/nios2/Makefile.objs
 create mode 100644 hw/nios2_pic_cpu.c
 create mode 100644 nios2-dis.c
 create mode 100644 target-nios2/Makefile.objs
 create mode 100644 target-nios2/altera_iic.c
 create mode 100644 target-nios2/cpu.c
 create mode 100644 target-nios2/cpu.h
 create mode 100644 target-nios2/helper.c
 create mode 100644 target-nios2/helper.h
 create mode 100644 target-nios2/instruction.c
 create mode 100644 target-nios2/instruction.h
 create mode 100644 target-nios2/machine.c
 create mode 100644 target-nios2/mmu.c
 create mode 100644 target-nios2/mmu.h
 create mode 100644 target-nios2/op_helper.c
 create mode 100644 target-nios2/translate.c

-- 
1.7.10.4

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

* [Qemu-devel] [PATCH 1/4] NiosII: Add support for the Altera NiosII soft-core CPU. (v2)
  2012-11-11  4:18 [Qemu-devel] [PATCH 0/4] Altera NiosII Support (v2) crwulff
@ 2012-11-11  4:18 ` crwulff
  2012-11-11  4:18 ` [Qemu-devel] [PATCH 2/4] NiosII: Disassembly of NiosII instructions ported from GDB. (v2) crwulff
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: crwulff @ 2012-11-11  4:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: Chris Wulff

From: Chris Wulff <crwulff@gmail.com>

Signed-off-by: Chris Wulff <crwulff@gmail.com>
---
 target-nios2/Makefile.objs |    5 +
 target-nios2/altera_iic.c  |  101 ++++
 target-nios2/cpu.c         |   83 +++
 target-nios2/cpu.h         |  302 ++++++++++
 target-nios2/helper.c      |  291 +++++++++
 target-nios2/helper.h      |   45 ++
 target-nios2/instruction.c | 1405 ++++++++++++++++++++++++++++++++++++++++++++
 target-nios2/instruction.h |  279 +++++++++
 target-nios2/machine.c     |   33 ++
 target-nios2/mmu.c         |  273 +++++++++
 target-nios2/mmu.h         |   49 ++
 target-nios2/op_helper.c   |  119 ++++
 target-nios2/translate.c   |  253 ++++++++
 13 files changed, 3238 insertions(+)
 create mode 100644 target-nios2/Makefile.objs
 create mode 100644 target-nios2/altera_iic.c
 create mode 100644 target-nios2/cpu.c
 create mode 100644 target-nios2/cpu.h
 create mode 100644 target-nios2/helper.c
 create mode 100644 target-nios2/helper.h
 create mode 100644 target-nios2/instruction.c
 create mode 100644 target-nios2/instruction.h
 create mode 100644 target-nios2/machine.c
 create mode 100644 target-nios2/mmu.c
 create mode 100644 target-nios2/mmu.h
 create mode 100644 target-nios2/op_helper.c
 create mode 100644 target-nios2/translate.c

diff --git a/target-nios2/Makefile.objs b/target-nios2/Makefile.objs
new file mode 100644
index 0000000..d072795
--- /dev/null
+++ b/target-nios2/Makefile.objs
@@ -0,0 +1,5 @@
+obj-y += translate.o op_helper.o helper.o cpu.o instruction.o
+obj-$(CONFIG_SOFTMMU) += mmu.o machine.o
+obj-y += altera_iic.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-nios2/altera_iic.c b/target-nios2/altera_iic.c
new file mode 100644
index 0000000..8b7aeb8
--- /dev/null
+++ b/target-nios2/altera_iic.c
@@ -0,0 +1,101 @@
+/*
+ * QEMU Altera Internal Interrupt Controller.
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 "hw/sysbus.h"
+#include "cpu.h"
+
+typedef struct AlteraIIC {
+    SysBusDevice busdev;
+    void        *cpu;
+    qemu_irq     parent_irq;
+} AlteraIIC;
+
+static void update_irq(AlteraIIC *pv)
+{
+    uint32_t i;
+    CPUNios2State *env = &((Nios2CPU*)(pv->cpu))->env;
+
+    if ((env->regs[CR_STATUS] & CR_STATUS_PIE) == 0) {
+        qemu_irq_lower(pv->parent_irq);
+        return;
+    }
+
+    for (i = 0; i < 32; i++) {
+        if (env->regs[CR_IPENDING] &
+            env->regs[CR_IENABLE] & (1 << i)) {
+            break;
+        }
+    }
+    if (i == 32) {
+        qemu_irq_lower(pv->parent_irq);
+    } else {
+        qemu_irq_raise(pv->parent_irq);
+    }
+}
+
+static void irq_handler(void *opaque, int irq, int level)
+{
+    AlteraIIC *pv = opaque;
+    CPUNios2State *env = &((Nios2CPU*)(pv->cpu))->env;
+
+    env->regs[CR_IPENDING] &= ~(1 << irq);
+    env->regs[CR_IPENDING] |= level << irq;
+
+    update_irq(pv);
+}
+
+static int altera_iic_init(SysBusDevice *dev)
+{
+    AlteraIIC *pv = FROM_SYSBUS(typeof(*pv), dev);
+
+    qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
+    sysbus_init_irq(dev, &pv->parent_irq);
+
+    return 0;
+}
+
+static Property altera_iic_properties[] = {
+    DEFINE_PROP_PTR("cpu", AlteraIIC, cpu),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void altera_iic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = altera_iic_init;
+    dc->props = altera_iic_properties;
+}
+
+static TypeInfo altera_iic_info = {
+    .name          = "altera,iic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AlteraIIC),
+    .class_init    = altera_iic_class_init,
+};
+
+static void altera_iic_register(void)
+{
+    type_register_static(&altera_iic_info);
+}
+
+type_init(altera_iic_register)
+
diff --git a/target-nios2/cpu.c b/target-nios2/cpu.c
new file mode 100644
index 0000000..bd819c4
--- /dev/null
+++ b/target-nios2/cpu.c
@@ -0,0 +1,83 @@
+/*
+ * QEMU Nios II CPU
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 "cpu.h"
+#include "qemu-common.h"
+
+
+/* CPUClass::reset() */
+static void nios2_cpu_reset(CPUState *s)
+{
+    Nios2CPU *cpu = NIOS2_CPU(s);
+    Nios2CPUClass *mcc = NIOS2_CPU_GET_CLASS(cpu);
+    CPUNios2State *env = &cpu->env;
+
+    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        log_cpu_state(env, 0);
+    }
+
+    mcc->parent_reset(s);
+
+    tlb_flush(env, 1);
+
+    memset(env->regs, 0, sizeof(uint32_t) * NUM_CORE_REGS);
+    env->regs[R_PC] = env->reset_addr;
+
+#if defined(CONFIG_USER_ONLY)
+    /* start in user mode with interrupts enabled.  */
+    env->regs[CR_STATUS] = CR_STATUS_U | CR_STATUS_PIE;
+#else
+    mmu_init(&env->mmu);
+#endif
+}
+
+static void nios2_cpu_initfn(Object *obj)
+{
+    Nios2CPU *cpu = NIOS2_CPU(obj);
+    CPUNios2State *env = &cpu->env;
+
+    cpu_exec_init(env);
+}
+
+static void nios2_cpu_class_init(ObjectClass *oc, void *data)
+{
+    CPUClass *cc = CPU_CLASS(oc);
+    Nios2CPUClass *mcc = NIOS2_CPU_CLASS(oc);
+
+    mcc->parent_reset = cc->reset;
+    cc->reset = nios2_cpu_reset;
+}
+
+static const TypeInfo nios2_cpu_type_info = {
+    .name = TYPE_NIOS2_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(Nios2CPU),
+    .instance_init = nios2_cpu_initfn,
+    .class_size = sizeof(Nios2CPUClass),
+    .class_init = nios2_cpu_class_init,
+};
+
+static void nios2_cpu_register_types(void)
+{
+    type_register_static(&nios2_cpu_type_info);
+}
+
+type_init(nios2_cpu_register_types)
diff --git a/target-nios2/cpu.h b/target-nios2/cpu.h
new file mode 100644
index 0000000..fc29a95
--- /dev/null
+++ b/target-nios2/cpu.h
@@ -0,0 +1,302 @@
+/*
+ * Altera Nios II virtual CPU header
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 CPU_NIOS2_H
+#define CPU_NIOS2_H
+
+#include "config.h"
+#include "qemu-common.h"
+
+#define TARGET_LONG_BITS 32
+
+#define CPUArchState struct CPUNios2State
+
+#include "cpu-defs.h"
+#include "softfloat.h"
+#include "qemu/cpu.h"
+struct CPUNios2State;
+typedef struct CPUNios2State CPUNios2State;
+#if !defined(CONFIG_USER_ONLY)
+#include "mmu.h"
+#endif
+
+#define TYPE_NIOS2_CPU "nios2-cpu"
+
+#define NIOS2_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(Nios2CPUClass, (klass), TYPE_NIOS2_CPU)
+#define NIOS2_CPU(obj) \
+    OBJECT_CHECK(Nios2CPU, (obj), TYPE_NIOS2_CPU)
+#define NIOS2_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(Nios2CPUClass, (obj), TYPE_NIOS2_CPU)
+
+/**
+ * Nios2CPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A Nios2 CPU model.
+ */
+typedef struct Nios2CPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    void (*parent_reset)(CPUState *cpu);
+} Nios2CPUClass;
+
+#define TARGET_HAS_ICE 1
+
+/* Configuration options for Nios II */
+#define RESET_ADDRESS         0x00000000
+#define EXCEPTION_ADDRESS     0x00000004
+#define FAST_TLB_MISS_ADDRESS 0x00000008
+
+
+#define ELF_MACHINE EM_ALTERA_NIOS2
+
+/* GP regs + CR regs + PC */
+#define NUM_CORE_REGS (32 + 32 + 1)
+
+/* General purpose egister aliases */
+#define R_ZERO   0
+#define R_AT     1
+#define R_RET0   2
+#define R_RET1   3
+#define R_ARG0   4
+#define R_ARG1   5
+#define R_ARG2   6
+#define R_ARG3   7
+#define R_ET     24
+#define R_BT     25
+#define R_GP     26
+#define R_SP     27
+#define R_FP     28
+#define R_EA     29
+#define R_BA     30
+#define R_RA     31
+
+/* Control register aliases */
+#define CR_BASE  32
+#define CR_STATUS    (CR_BASE + 0)
+#define   CR_STATUS_PIE  (1<<0)
+#define   CR_STATUS_U    (1<<1)
+#define   CR_STATUS_EH   (1<<2)
+#define   CR_STATUS_IH   (1<<3)
+#define   CR_STATUS_IL   (63<<4)
+#define   CR_STATUS_CRS  (63<<10)
+#define   CR_STATUS_PRS  (63<<16)
+#define   CR_STATUS_NMI  (1<<22)
+#define   CR_STATUS_RSIE (1<<23)
+#define CR_ESTATUS   (CR_BASE + 1)
+#define CR_BSTATUS   (CR_BASE + 2)
+#define CR_IENABLE   (CR_BASE + 3)
+#define CR_IPENDING  (CR_BASE + 4)
+#define CR_CPUID     (CR_BASE + 5)
+#define CR_EXCEPTION (CR_BASE + 7)
+#define CR_PTEADDR   (CR_BASE + 8)
+#define   CR_PTEADDR_PTBASE_SHIFT 22
+#define   CR_PTEADDR_PTBASE_MASK  (0x3FF << CR_PTEADDR_PTBASE_SHIFT)
+#define   CR_PTEADDR_VPN_SHIFT    2
+#define   CR_PTEADDR_VPN_MASK     (0xFFFFF << CR_PTEADDR_VPN_SHIFT)
+#define CR_TLBACC    (CR_BASE + 9)
+#define   CR_TLBACC_IGN_SHIFT 25
+#define   CR_TLBACC_IGN_MASK  (0x7F << CR_TLBACC_IGN_SHIFT)
+#define   CR_TLBACC_C         (1<<24)
+#define   CR_TLBACC_R         (1<<23)
+#define   CR_TLBACC_W         (1<<22)
+#define   CR_TLBACC_X         (1<<21)
+#define   CR_TLBACC_G         (1<<20)
+#define   CR_TLBACC_PFN_MASK  0x000FFFFF
+#define CR_TLBMISC   (CR_BASE + 10)
+#define   CR_TLBMISC_WAY_SHIFT 20
+#define   CR_TLBMISC_WAY_MASK  (0xF << CR_TLBMISC_WAY_SHIFT)
+#define   CR_TLBMISC_RD        (1<<19)
+#define   CR_TLBMISC_WR        (1<<18)
+#define   CR_TLBMISC_PID_SHIFT 4
+#define   CR_TLBMISC_PID_MASK  (0x3FFF << CR_TLBMISC_PID_SHIFT)
+#define   CR_TLBMISC_DBL       (1<<3)
+#define   CR_TLBMISC_BAD       (1<<2)
+#define   CR_TLBMISC_PERM      (1<<1)
+#define   CR_TLBMISC_D         (1<<0)
+#define CR_BADADDR   (CR_BASE + 12)
+#define CR_CONFIG    (CR_BASE + 13)
+#define CR_MPUBASE   (CR_BASE + 14)
+#define CR_MPUACC    (CR_BASE + 15)
+
+/* Other registers */
+#define R_PC         64
+
+/* Exceptions */
+#define EXCP_BREAK    -1
+#define EXCP_RESET    0
+#define EXCP_PRESET   1
+#define EXCP_IRQ      2
+#define EXCP_TRAP     3
+#define EXCP_UNIMPL   4
+#define EXCP_ILLEGAL  5
+#define EXCP_UNALIGN  6
+#define EXCP_UNALIGND 7
+#define EXCP_DIV      8
+#define EXCP_SUPERA   9
+#define EXCP_SUPERI   10
+#define EXCP_SUPERD   11
+#define EXCP_TLBD     12
+#define EXCP_TLBX     13
+#define EXCP_TLBR     14
+#define EXCP_TLBW     15
+#define EXCP_MPUI     16
+#define EXCP_MPUD     17
+
+#define CPU_INTERRUPT_NMI       CPU_INTERRUPT_TGT_EXT_3
+
+#define NB_MMU_MODES 2
+
+typedef struct CPUNios2State {
+    uint32_t regs[NUM_CORE_REGS];
+
+    /* Addresses that are hard-coded in the FPGA build settings */
+    uint32_t reset_addr;
+    uint32_t exception_addr;
+    uint32_t fast_tlb_miss_addr;
+
+#if !defined(CONFIG_USER_ONLY)
+    Nios2MMU mmu;
+#endif
+
+    CPU_COMMON
+} CPUNios2State;
+
+/**
+ * Nios2CPU:
+ * @env: #CPUNios2State
+ *
+ * A Nios2 CPU.
+ */
+typedef struct Nios2CPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUNios2State env;
+} Nios2CPU;
+
+static inline Nios2CPU *nios2_env_get_cpu(CPUNios2State *env)
+{
+    return NIOS2_CPU(container_of(env, Nios2CPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(nios2_env_get_cpu(e))
+
+Nios2CPU *cpu_nios2_init(const char *cpu_model);
+int cpu_nios2_exec(CPUNios2State *s);
+void cpu_nios2_close(CPUNios2State *s);
+void do_interrupt(CPUNios2State *env);
+int cpu_nios2_signal_handler(int host_signum, void *pinfo, void *puc);
+void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUNios2State *env);
+
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+
+static inline CPUNios2State *cpu_init(const char *cpu_model)
+{
+    Nios2CPU *cpu = cpu_nios2_init(cpu_model);
+    if (cpu == NULL) {
+        return NULL;
+    }
+    return &cpu->env;
+}
+
+#define cpu_exec cpu_nios2_exec
+#define cpu_gen_code cpu_nios2_gen_code
+#define cpu_signal_handler cpu_nios2_signal_handler
+
+#define CPU_SAVE_VERSION 1
+
+#define TARGET_PAGE_BITS 12
+
+/* MMU modes definitions */
+#define MMU_MODE0_SUFFIX _kernel
+#define MMU_MODE1_SUFFIX _user
+#define MMU_SUPERVISOR_IDX  0
+#define MMU_USER_IDX        1
+
+static inline int cpu_mmu_index(CPUNios2State *env)
+{
+    return (env->regs[CR_STATUS] & CR_STATUS_U) ? MMU_USER_IDX :
+                                                  MMU_SUPERVISOR_IDX;
+}
+
+int cpu_nios2_handle_mmu_fault(CPUNios2State *env, target_ulong address,
+                               int rw, int mmu_idx, int is_softmmu);
+#define cpu_handle_mmu_fault cpu_nios2_handle_mmu_fault
+
+#if defined(CONFIG_USER_ONLY)
+static inline void cpu_clone_regs(CPUNios2State *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->regs[R_SP] = newsp;
+    }
+    env->regs[R_RET0] = 0;
+}
+#endif
+
+static inline void cpu_set_tls(CPUNios2State *env, target_ulong newtls)
+{
+}
+
+static inline int cpu_interrupts_enabled(CPUNios2State *env)
+{
+    return env->regs[CR_STATUS] & CR_STATUS_PIE;
+}
+
+#include "cpu-all.h"
+
+static inline target_ulong cpu_get_pc(CPUNios2State *env)
+{
+    return env->regs[R_PC];
+}
+
+static inline void cpu_get_tb_cpu_state(CPUNios2State *env, target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->regs[R_PC];
+    *cs_base = 0;
+    *flags = (env->regs[CR_STATUS] & (CR_STATUS_EH | CR_STATUS_U));
+}
+
+#if !defined(CONFIG_USER_ONLY)
+void cpu_unassigned_access(CPUNios2State *env1, hwaddr addr,
+                           int is_write, int is_exec, int is_asi, int size);
+#endif
+
+static inline bool cpu_has_work(CPUState *cpu)
+{
+    CPUNios2State *env = &NIOS2_CPU(cpu)->env;
+
+    return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUNios2State *env, TranslationBlock *tb)
+{
+    env->regs[R_PC] = tb->pc;
+}
+
+#endif /* CPU_NIOS2_H */
+
diff --git a/target-nios2/helper.c b/target-nios2/helper.c
new file mode 100644
index 0000000..fad8c04
--- /dev/null
+++ b/target-nios2/helper.c
@@ -0,0 +1,291 @@
+/*
+ * Altera Nios II helper routines.
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "config.h"
+#include "cpu.h"
+#include "exec-all.h"
+#include "host-utils.h"
+
+#if defined(CONFIG_USER_ONLY)
+
+void do_interrupt(CPUNios2State *env)
+{
+    env->exception_index = -1;
+    env->regs[R_EA] = env->regs[R_PC] + 4;
+}
+
+int cpu_nios2_handle_mmu_fault(CPUNios2State *env, target_ulong address,
+                               int rw, int mmu_idx, int is_softmmu)
+{
+    env->exception_index = 0xaa;
+    cpu_dump_state(env, stderr, fprintf, 0);
+    return 1;
+}
+
+#else /* !CONFIG_USER_ONLY */
+
+bool has_mmu = true;
+
+void do_interrupt(CPUNios2State *env)
+{
+    switch (env->exception_index) {
+    case EXCP_IRQ:
+        assert(env->regs[CR_STATUS] & CR_STATUS_PIE);
+
+        qemu_log_mask(CPU_LOG_INT, "interrupt at pc=%x\n", env->regs[R_PC]);
+
+        env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
+        env->regs[CR_STATUS] |= CR_STATUS_IH;
+        env->regs[CR_STATUS] &= ~(CR_STATUS_PIE|CR_STATUS_U);
+
+        env->regs[CR_EXCEPTION] &= ~(0x1F << 2);
+        env->regs[CR_EXCEPTION] |= (env->exception_index & 0x1F) << 2;
+
+        env->regs[R_EA] = env->regs[R_PC] + 4;
+        env->regs[R_PC] = env->exception_addr;
+        break;
+
+    case EXCP_TLBD:
+        if ((env->regs[CR_STATUS] & CR_STATUS_EH) == 0) {
+            qemu_log_mask(CPU_LOG_INT, "TLB MISS (fast) at pc=%x\n",
+                          env->regs[R_PC]);
+            log_cpu_state(env, 0);
+
+            /* Fast TLB miss */
+            /* Variation from the spec. Table 3-35 of the cpu reference shows
+             * estatus not being changed for TLB miss but this appears to
+             * be incorrect. */
+            env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
+            env->regs[CR_STATUS] |= CR_STATUS_EH;
+            env->regs[CR_STATUS] &= ~(CR_STATUS_PIE|CR_STATUS_U);
+
+            env->regs[CR_EXCEPTION] &= ~(0x1F << 2);
+            env->regs[CR_EXCEPTION] |= (env->exception_index & 0x1F) << 2;
+
+            env->regs[CR_TLBMISC] &= ~CR_TLBMISC_DBL;
+            env->regs[CR_TLBMISC] |= CR_TLBMISC_WR;
+
+            env->regs[R_EA] = env->regs[R_PC] + 4;
+            env->regs[R_PC] = env->fast_tlb_miss_addr;
+        } else {
+            qemu_log_mask(CPU_LOG_INT, "TLB MISS (double) at pc=%x\n",
+                          env->regs[R_PC]);
+
+            /* Double TLB miss */
+            env->regs[CR_STATUS] |= CR_STATUS_EH;
+            env->regs[CR_STATUS] &= ~(CR_STATUS_PIE|CR_STATUS_U);
+
+            env->regs[CR_EXCEPTION] &= ~(0x1F << 2);
+            env->regs[CR_EXCEPTION] |= (env->exception_index & 0x1F) << 2;
+
+            env->regs[CR_TLBMISC] |= CR_TLBMISC_DBL;
+
+            env->regs[R_PC] = env->exception_addr;
+        }
+        break;
+
+    case EXCP_TLBR:
+    case EXCP_TLBW:
+    case EXCP_TLBX:
+        qemu_log_mask(CPU_LOG_INT, "TLB PERM at pc=%x\n", env->regs[R_PC]);
+        log_cpu_state(env, 0);
+
+        env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
+        env->regs[CR_STATUS] |= CR_STATUS_EH;
+        env->regs[CR_STATUS] &= ~(CR_STATUS_PIE|CR_STATUS_U);
+
+        env->regs[CR_EXCEPTION] &= ~(0x1F << 2);
+        env->regs[CR_EXCEPTION] |= (env->exception_index & 0x1F) << 2;
+
+        if ((env->regs[CR_STATUS] & CR_STATUS_EH) == 0) {
+            env->regs[CR_TLBMISC] |= CR_TLBMISC_WR;
+        }
+
+        env->regs[R_EA] = env->regs[R_PC] + 4;
+        env->regs[R_PC] = env->exception_addr;
+        break;
+
+    case EXCP_SUPERA:
+    case EXCP_SUPERI:
+    case EXCP_SUPERD:
+        qemu_log_mask(CPU_LOG_INT, "SUPERVISOR exception at pc=%x\n",
+                      env->regs[R_PC]);
+
+        if ((env->regs[CR_STATUS] & CR_STATUS_EH) == 0) {
+            env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
+            env->regs[R_EA] = env->regs[R_PC] + 4;
+        }
+
+        env->regs[CR_STATUS] |= CR_STATUS_EH;
+        env->regs[CR_STATUS] &= ~(CR_STATUS_PIE|CR_STATUS_U);
+
+        env->regs[CR_EXCEPTION] &= ~(0x1F << 2);
+        env->regs[CR_EXCEPTION] |= (env->exception_index & 0x1F) << 2;
+
+        env->regs[R_PC] = env->exception_addr;
+        break;
+
+    case EXCP_ILLEGAL:
+    case EXCP_TRAP:
+        qemu_log_mask(CPU_LOG_INT, "TRAP exception at pc=%x\n",
+                      env->regs[R_PC]);
+
+        if ((env->regs[CR_STATUS] & CR_STATUS_EH) == 0) {
+            env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
+            env->regs[R_EA] = env->regs[R_PC] + 4;
+        }
+
+        env->regs[CR_STATUS] |= CR_STATUS_EH;
+        env->regs[CR_STATUS] &= ~(CR_STATUS_PIE|CR_STATUS_U);
+
+        env->regs[CR_EXCEPTION] &= ~(0x1F << 2);
+        env->regs[CR_EXCEPTION] |= (env->exception_index & 0x1F) << 2;
+
+        env->regs[R_PC] = env->exception_addr;
+        break;
+
+    case EXCP_BREAK:
+        if ((env->regs[CR_STATUS] & CR_STATUS_EH) == 0) {
+            env->regs[CR_BSTATUS] = env->regs[CR_STATUS];
+            env->regs[R_BA] = env->regs[R_PC] + 4;
+        }
+
+        env->regs[CR_STATUS] |= CR_STATUS_EH;
+        env->regs[CR_STATUS] &= ~(CR_STATUS_PIE|CR_STATUS_U);
+
+        env->regs[CR_EXCEPTION] &= ~(0x1F << 2);
+        env->regs[CR_EXCEPTION] |= (env->exception_index & 0x1F) << 2;
+
+        env->regs[R_PC] = env->exception_addr;
+        break;
+
+    default:
+        cpu_abort(env, "unhandled exception type=%d\n",
+                  env->exception_index);
+        break;
+    }
+}
+
+static int cpu_nios2_handle_virtual_page(
+    CPUNios2State *env, target_ulong address, int rw, int mmu_idx)
+{
+    target_ulong vaddr, paddr;
+    Nios2MMULookup lu;
+    unsigned int hit;
+    hit = mmu_translate(env, &lu, address, rw, mmu_idx);
+    if (hit) {
+        vaddr = address & TARGET_PAGE_MASK;
+        paddr = lu.paddr + vaddr - lu.vaddr;
+
+        if (((rw == 0) && (lu.prot & PAGE_READ)) ||
+            ((rw == 1) && (lu.prot & PAGE_WRITE)) ||
+            ((rw == 2) && (lu.prot & PAGE_EXEC))) {
+
+            tlb_set_page(env, vaddr, paddr, lu.prot,
+                         mmu_idx, TARGET_PAGE_SIZE);
+            return 0;
+        } else {
+            /* Permission violation */
+            env->exception_index = (rw == 0) ? EXCP_TLBR :
+                                               ((rw == 1) ? EXCP_TLBW :
+                                                            EXCP_TLBX);
+        }
+    } else {
+        env->exception_index = EXCP_TLBD;
+    }
+
+    if (rw == 2) {
+        env->regs[CR_TLBMISC] &= ~CR_TLBMISC_D;
+    } else {
+        env->regs[CR_TLBMISC] |= CR_TLBMISC_D;
+    }
+    env->regs[CR_PTEADDR] &= CR_PTEADDR_PTBASE_MASK;
+    env->regs[CR_PTEADDR] |= (address >> 10) & CR_PTEADDR_VPN_MASK;
+    env->mmu.pteaddr_wr = env->regs[CR_PTEADDR];
+    env->regs[CR_BADADDR] = address;
+    return 1;
+}
+
+int cpu_nios2_handle_mmu_fault(CPUNios2State *env, target_ulong address,
+                               int rw, int mmu_idx, int is_softmmu)
+{
+    if (has_mmu) {
+        if (MMU_SUPERVISOR_IDX == mmu_idx) {
+            if (address >= 0xC0000000) {
+                /* Kernel physical page - TLB bypassed */
+                address &= TARGET_PAGE_MASK;
+                tlb_set_page(env, address, address, PAGE_BITS,
+                             mmu_idx, TARGET_PAGE_SIZE);
+            } else if (address >= 0x80000000) {
+                /* Kernel virtual page */
+                return cpu_nios2_handle_virtual_page(env, address, rw, mmu_idx);
+            } else {
+                /* User virtual page */
+                return cpu_nios2_handle_virtual_page(env, address, rw, mmu_idx);
+            }
+        } else {
+            if (address >= 0x80000000) {
+                /* Illegal access from user mode */
+                env->exception_index = EXCP_SUPERA;
+                env->regs[CR_BADADDR] = address;
+                return 1;
+            } else {
+                /* User virtual page */
+                return cpu_nios2_handle_virtual_page(env, address, rw, mmu_idx);
+            }
+        }
+    } else {
+        /* No MMU */
+        address &= TARGET_PAGE_MASK;
+        tlb_set_page(env, address, address, PAGE_BITS,
+                     mmu_idx, TARGET_PAGE_SIZE);
+    }
+
+    return 0;
+}
+
+hwaddr cpu_get_phys_page_debug(CPUNios2State *env, target_ulong addr)
+{
+    target_ulong vaddr, paddr = 0;
+    Nios2MMULookup lu;
+    unsigned int hit;
+
+    if (has_mmu && (addr < 0xC0000000)) {
+        hit = mmu_translate(env, &lu, addr, 0, 0);
+        if (hit) {
+            vaddr = addr & TARGET_PAGE_MASK;
+            paddr = lu.paddr + vaddr - lu.vaddr;
+        } else {
+            paddr = -1;
+            qemu_log("cpu_get_phys_page debug MISS: %08X\n", addr);
+        }
+    } else {
+        paddr = addr & TARGET_PAGE_MASK;
+    }
+
+    return paddr;
+}
+
+#endif /* !CONFIG_USER_ONLY */
+
diff --git a/target-nios2/helper.h b/target-nios2/helper.h
new file mode 100644
index 0000000..8434cfa
--- /dev/null
+++ b/target-nios2/helper.h
@@ -0,0 +1,45 @@
+/*
+ * Altera Nios II helper routines header.
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 "def-helper.h"
+
+/* Define this to enable tracing calls/returns */
+/* #define CALL_TRACING */
+
+#ifdef CALL_TRACING
+DEF_HELPER_2(call_status, void, i32, i32)
+DEF_HELPER_1(eret_status, void, i32)
+DEF_HELPER_1(ret_status, void, i32)
+#endif
+
+DEF_HELPER_2(raise_exception, void, env, i32)
+
+#if !defined(CONFIG_USER_ONLY)
+DEF_HELPER_2(mmu_read, i32, env, i32)
+DEF_HELPER_3(mmu_write, void, env, i32, i32)
+#endif
+
+DEF_HELPER_2(divs, i32, i32, i32)
+DEF_HELPER_2(divu, i32, i32, i32)
+
+DEF_HELPER_5(memalign, void, env, i32, i32, i32, i32)
+
+#include "def-helper.h"
+
diff --git a/target-nios2/instruction.c b/target-nios2/instruction.c
new file mode 100644
index 0000000..2f5319d
--- /dev/null
+++ b/target-nios2/instruction.c
@@ -0,0 +1,1405 @@
+/*
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ *  (Portions of this file that were originally from nios2sim-ng.)
+ *
+ * Copyright (C) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 <stdio.h>
+
+#include "instruction.h"
+#include "exec-all.h"
+#include "helper.h"
+
+#define GEN_HELPER 1
+#include "helper.h"
+
+static inline uint32_t get_opcode(uint32_t code)
+{
+    I_TYPE(instr, code);
+    return instr->op;
+}
+
+static inline uint32_t get_opxcode(uint32_t code)
+{
+    R_TYPE(instr, code);
+    return instr->opx6;
+}
+
+static inline void t_gen_helper_raise_exception(DisasContext *dc,
+                                                uint32_t index)
+{
+    TCGv_i32 tmp = tcg_const_i32(index);
+
+    tcg_gen_movi_tl(dc->cpu_R[R_PC], dc->pc);
+    gen_helper_raise_exception(dc->cpu_env, tmp);
+    tcg_temp_free_i32(tmp);
+    dc->is_jmp = DISAS_UPDATE;
+}
+
+static inline void gen_goto_tb(DisasContext *dc, int n, uint32_t dest)
+{
+    TranslationBlock *tb = dc->tb;
+
+    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
+        tcg_gen_goto_tb(n);
+        tcg_gen_movi_tl(dc->cpu_R[R_PC], dest);
+        tcg_gen_exit_tb((tcg_target_long)tb + n);
+    } else {
+        tcg_gen_movi_tl(dc->cpu_R[R_PC], dest);
+        tcg_gen_exit_tb(0);
+    }
+}
+
+/*
+ * Instructions not implemented by the simulator.
+ */
+static void unimplemented(DisasContext *dc, uint32_t code)
+{
+    t_gen_helper_raise_exception(dc, EXCP_UNIMPL);
+}
+
+/*
+ * Illegal instruction
+ */
+static void illegal_instruction(DisasContext *dc,
+                                uint32_t code __attribute__((unused)))
+{
+    t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
+}
+
+static void gen_check_supervisor(DisasContext *dc, int label)
+{
+    int l1 = gen_new_label();
+
+    TCGv_i32 tmp = tcg_temp_new();
+    tcg_gen_andi_tl(tmp, dc->cpu_R[CR_STATUS], CR_STATUS_U);
+    tcg_gen_brcond_tl(TCG_COND_EQ, dc->cpu_R[R_ZERO], tmp, l1);
+    t_gen_helper_raise_exception(dc, EXCP_SUPERI);
+    tcg_gen_br(label);
+
+    gen_set_label(l1);
+    tcg_temp_free_i32(tmp);
+
+    /* If we aren't taking the exception, update the PC to the
+     * next instruction */
+    tcg_gen_movi_tl(dc->cpu_R[R_PC], dc->pc+4);
+}
+
+/*
+ * Used as a placeholder for all instructions which do not have an effect on the
+ * simulator (e.g. flush, sync)
+ */
+static void nop(DisasContext *dc __attribute__((unused)),
+                uint32_t code __attribute__((unused)))
+{
+    /* Nothing to do here */
+}
+
+/*
+ * J-Type instructions
+ */
+
+/*
+ * ra <- PC + 4
+ * PC <- (PC(31..28) : IMM26 * 4)
+ */
+static void call(DisasContext *dc, uint32_t code)
+{
+    J_TYPE(instr, code);
+
+#ifdef CALL_TRACING
+    TCGv_i32 tmp = tcg_const_i32(dc->pc);
+    TCGv_i32 tmp2 = tcg_const_i32((dc->pc & 0xF0000000) | (instr->imm26 * 4));
+    gen_helper_call_status(tmp, tmp2);
+    tcg_temp_free_i32(tmp);
+    tcg_temp_free_i32(tmp2);
+#endif
+
+    tcg_gen_movi_tl(dc->cpu_R[R_RA], dc->pc + 4);
+
+    gen_goto_tb(dc, 0, (dc->pc & 0xF0000000) | (instr->imm26 * 4));
+
+    dc->is_jmp = DISAS_TB_JUMP;
+}
+
+/* PC <- (PC(31..28) : IMM26 * 4) */
+static void jmpi(DisasContext *dc, uint32_t code)
+{
+    J_TYPE(instr, code);
+
+    gen_goto_tb(dc, 0, (dc->pc & 0xF0000000) | (instr->imm26 * 4));
+
+    dc->is_jmp = DISAS_TB_JUMP;
+}
+
+/*
+ * I-Type instructions
+ */
+
+/* rB <- 0x000000 : Mem8[rA + @(IMM16)] */
+static void ldbu(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_ld8u(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/* rB <- rA + IMM16 */
+static void addi(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv imm = tcg_temp_new();
+    tcg_gen_addi_tl(dc->cpu_R[instr->b], dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+    tcg_temp_free(imm);
+}
+
+/* Mem8[rA + @(IMM16)] <- rB(7..0) */
+static void stb(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_st8(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/* PC <- PC + 4 + IMM16 */
+static void br(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    gen_goto_tb(dc, 0, dc->pc + 4 + (int16_t)(instr->imm16 & 0xFFFC));
+
+    dc->is_jmp = DISAS_TB_JUMP;
+}
+
+/* rB <- @(Mem8[rA + @(IMM16)]) */
+static void ldb(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_ld8s(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/*
+ * if ((signed) rA >= (signed) @(IMM16))
+ *   rB <- 1
+ * else
+ *   rB <- 0
+ */
+static void cmpgei(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    tcg_gen_setcondi_tl(TCG_COND_GE, dc->cpu_R[instr->b], dc->cpu_R[instr->a],
+                        (int32_t)((int16_t)instr->imm16));
+}
+
+/* rB <- 0x0000 : Mem16[rA + @IMM16)] */
+static void ldhu(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_ld16u(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/* rB <- rA & IMM16 */
+static void andi(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    tcg_gen_andi_tl(dc->cpu_R[instr->b], dc->cpu_R[instr->a], instr->imm16);
+}
+
+/* Mem16[rA + @(IMM16)] <- rB(15..0) */
+static void sth(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_st16(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/*
+ * if ((signed) rA >= (signed) rB)
+ *   PC <- PC + 4 + @(IMM16)
+ * else
+ *   PC <- PC + 4
+ */
+static void bge(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    int l1 = gen_new_label();
+
+    tcg_gen_brcond_tl(TCG_COND_GE, dc->cpu_R[instr->a],
+                      dc->cpu_R[instr->b], l1);
+
+    gen_goto_tb(dc, 0, dc->pc + 4);
+
+    gen_set_label(l1);
+
+    gen_goto_tb(dc, 1, dc->pc + 4 + (int16_t)(instr->imm16 & 0xFFFC));
+
+    dc->is_jmp = DISAS_TB_JUMP;
+}
+
+/* rB <- Mem16[rA + @IMM16)] */
+static void ldh(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_ld16s(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/*
+ * if ((signed) rA < (signed) @(IMM16))
+ *   rB <- 1
+ * else
+ *   rB <- 0
+ */
+static void cmplti(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    tcg_gen_setcondi_tl(TCG_COND_LT, dc->cpu_R[instr->b], dc->cpu_R[instr->a],
+                        (int32_t)((int16_t)instr->imm16));
+}
+
+/* Initializes the data cache line currently caching address rA + @(IMM16) */
+static void initda(DisasContext *dc __attribute__((unused)),
+                   uint32_t code __attribute__((unused)))
+{
+    /* TODO */
+}
+
+/* rB <- rA | IMM16 */
+static void ori(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    tcg_gen_ori_tl(dc->cpu_R[instr->b], dc->cpu_R[instr->a], instr->imm16);
+}
+
+/* Mem32[rA + @(IMM16)] <- rB */
+static void stw(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_st32(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/*
+ * if ((signed) rA < (signed) rB)
+ *   PC <- PC + 4 + @(IMM16)
+ * else
+ *   PC <- PC + 4
+ */
+static void blt(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    int l1 = gen_new_label();
+
+    tcg_gen_brcond_tl(TCG_COND_LT, dc->cpu_R[instr->a],
+                      dc->cpu_R[instr->b], l1);
+
+    gen_goto_tb(dc, 0, dc->pc + 4);
+
+    gen_set_label(l1);
+
+    gen_goto_tb(dc, 1, dc->pc + 4 + (int16_t)(instr->imm16 & 0xFFFC));
+
+    dc->is_jmp = DISAS_TB_JUMP;
+}
+
+/* rB <- @(Mem32[rA + @(IMM16)]) */
+static void ldw(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_ld32u(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/*
+ * if ((signed) rA != (signed) @(IMM16))
+ *   rB <- 1
+ * else
+ *   rB <- 0
+ */
+static void cmpnei(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    tcg_gen_setcondi_tl(TCG_COND_NE, dc->cpu_R[instr->b], dc->cpu_R[instr->a],
+                        (int32_t)((int16_t)instr->imm16));
+}
+
+/* rB <- rA ^ IMM16 */
+static void xori(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    tcg_gen_xori_tl(dc->cpu_R[instr->b], dc->cpu_R[instr->a], instr->imm16);
+}
+
+/*
+ * if (rA != rB)
+ *   PC <- PC + 4 + @(IMM16)
+ * else
+ *   PC <- PC + 4
+ */
+static void bne(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    int l1 = gen_new_label();
+
+    tcg_gen_brcond_tl(TCG_COND_NE, dc->cpu_R[instr->a],
+                      dc->cpu_R[instr->b], l1);
+
+    gen_goto_tb(dc, 0, dc->pc + 4);
+
+    gen_set_label(l1);
+
+    gen_goto_tb(dc, 1, dc->pc + 4 + (int16_t)(instr->imm16 & 0xFFFC));
+
+    dc->is_jmp = DISAS_TB_JUMP;
+}
+
+/*
+ * if ((signed) rA == (signed) @(IMM16))
+ *   rB <- 1
+ * else
+ *   rB <- 0
+ */
+static void cmpeqi(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    tcg_gen_setcondi_tl(TCG_COND_EQ, dc->cpu_R[instr->b], dc->cpu_R[instr->a],
+                        (int32_t)((int16_t)instr->imm16));
+}
+
+/* rB <- 0x000000 : Mem8[rA + @(IMM16)] (bypassing cache) */
+static void ldbuio(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_ld8u(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/* rB <- (rA * @(IMM16))(31..0) */
+static void muli(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv imm = tcg_temp_new();
+    tcg_gen_muli_i32(dc->cpu_R[instr->b], dc->cpu_R[instr->a],
+                     (int32_t)((int16_t)instr->imm16));
+    tcg_temp_free(imm);
+}
+
+/* Mem8[rA + @(IMM16)] <- rB(7..0) (bypassing cache) */
+static void stbio(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_st8(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/*
+ * if (rA == rB)
+ *   PC <- PC + 4 + @(IMM16)
+ * else
+ *   PC <- PC + 4
+ */
+static void beq(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    int l1 = gen_new_label();
+
+    tcg_gen_brcond_tl(TCG_COND_EQ, dc->cpu_R[instr->a],
+                      dc->cpu_R[instr->b], l1);
+
+    gen_goto_tb(dc, 0, dc->pc + 4);
+
+    gen_set_label(l1);
+
+    gen_goto_tb(dc, 1, dc->pc + 4 + (int16_t)(instr->imm16 & 0xFFFC));
+
+    dc->is_jmp = DISAS_TB_JUMP;
+}
+
+/* rB <- @(Mem8[rA + @(IMM16)]) (bypassing cache) */
+static void ldbio(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_ld8s(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/*
+ * if (rA >= 0x0000 : @(IMM16))
+ *   rB <- 1
+ * else
+ *   rB <- 0
+ */
+static void cmpgeui(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    tcg_gen_setcondi_tl(TCG_COND_GEU, dc->cpu_R[instr->b], dc->cpu_R[instr->a],
+                        (int32_t)((int16_t)instr->imm16));
+}
+
+/* rB <- 0x0000 : Mem16[rA + @IMM16)] (bypassing cache) */
+static void ldhuio(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_ld16u(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/* rB <- rA & (IMM16 : 0x0000) */
+static void andhi(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    tcg_gen_andi_tl(dc->cpu_R[instr->b], dc->cpu_R[instr->a],
+                    instr->imm16 << 16);
+}
+
+/* Mem16[rA + @(IMM16)] <- rB(15..0) (bypassing cache) */
+static void sthio(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_st16(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/*
+ * if (rA >= rB)
+ *   PC <- PC + 4 + @(IMM16)
+ * else
+ *   PC <- PC + 4
+ */
+static void bgeu(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    int l1 = gen_new_label();
+
+    tcg_gen_brcond_tl(TCG_COND_GEU, dc->cpu_R[instr->a],
+                      dc->cpu_R[instr->b], l1);
+
+    gen_goto_tb(dc, 0, dc->pc + 4);
+
+    gen_set_label(l1);
+
+    gen_goto_tb(dc, 1, dc->pc + 4 + (int16_t)(instr->imm16 & 0xFFFC));
+
+    dc->is_jmp = DISAS_TB_JUMP;
+}
+
+/* rB <- Mem16[rA + @IMM16)] (bypassing cache) */
+static void ldhio(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_ld16s(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/*
+ * if (rA < 0x0000 : @(IMM16))
+ *   rB <- 1
+ * else
+ *   rB <- 0
+ */
+static void cmpltui(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    tcg_gen_setcondi_tl(TCG_COND_LTU, dc->cpu_R[instr->b], dc->cpu_R[instr->a],
+                        (int32_t)((int16_t)instr->imm16));
+}
+
+/* */
+static void initd(DisasContext *dc __attribute__((unused)),
+                  uint32_t code __attribute((unused)))
+{
+    /* TODO */
+}
+
+/* rB <- rA | (IMM16 : 0x0000) */
+static void orhi(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    tcg_gen_ori_tl(dc->cpu_R[instr->b], dc->cpu_R[instr->a],
+                   instr->imm16 << 16);
+}
+
+/* Mem32[rA + @(IMM16)] <- rB (bypassing cache) */
+static void stwio(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_st32(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/*
+ * if ((unsigned) rA < (unsigned) rB)
+ *   PC <- PC + 4 + @(IMM16)
+ * else
+ *   PC <- PC + 4
+ */
+static void bltu(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    int l1 = gen_new_label();
+
+    tcg_gen_brcond_tl(TCG_COND_LTU, dc->cpu_R[instr->a],
+                      dc->cpu_R[instr->b], l1);
+
+    gen_goto_tb(dc, 0, dc->pc + 4);
+
+    gen_set_label(l1);
+
+    gen_goto_tb(dc, 1, dc->pc + 4 + (int16_t)(instr->imm16 & 0xFFFC));
+
+    dc->is_jmp = DISAS_TB_JUMP;
+}
+
+/* rB <- @(Mem32[rA + @(IMM16)]) (bypassing cache) */
+static void ldwio(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    TCGv addr = tcg_temp_new();
+    tcg_gen_addi_tl(addr, dc->cpu_R[instr->a],
+                    (int32_t)((int16_t)instr->imm16));
+
+    tcg_gen_qemu_ld32u(dc->cpu_R[instr->b], addr, dc->mem_idx);
+
+    tcg_temp_free(addr);
+}
+
+/* Prototype only, defined below */
+static void handle_r_type_instr(DisasContext *dc, uint32_t code);
+
+/* rB <- rA ^ (IMM16 : 0x0000) */
+static void xorhi(DisasContext *dc, uint32_t code)
+{
+    I_TYPE(instr, code);
+
+    tcg_gen_xori_tl(dc->cpu_R[instr->b], dc->cpu_R[instr->a],
+                    instr->imm16 << 16);
+}
+
+static const Nios2Instruction i_type_instructions[I_TYPE_COUNT] = {
+    [CALL]    = INSTRUCTION(call),
+    [JMPI]    = INSTRUCTION(jmpi),
+    [0x02]    = INSTRUCTION_ILLEGAL(),
+    [LDBU]    = INSTRUCTION(ldbu),
+    [ADDI]    = INSTRUCTION(addi),
+    [STB]     = INSTRUCTION(stb),
+    [BR]      = INSTRUCTION(br),
+    [LDB]     = INSTRUCTION(ldb),
+    [CMPGEI]  = INSTRUCTION(cmpgei),
+    [0x09]    = INSTRUCTION_ILLEGAL(),
+    [0x0a]    = INSTRUCTION_ILLEGAL(),
+    [LDHU]    = INSTRUCTION(ldhu),
+    [ANDI]    = INSTRUCTION(andi),
+    [STH]     = INSTRUCTION(sth),
+    [BGE]     = INSTRUCTION(bge),
+    [LDH]     = INSTRUCTION(ldh),
+    [CMPLTI]  = INSTRUCTION(cmplti),
+    [0x11]    = INSTRUCTION_ILLEGAL(),
+    [0x12]    = INSTRUCTION_ILLEGAL(),
+    [INITDA]  = INSTRUCTION(initda),
+    [ORI]     = INSTRUCTION(ori),
+    [STW]     = INSTRUCTION(stw),
+    [BLT]     = INSTRUCTION(blt),
+    [LDW]     = INSTRUCTION(ldw),
+    [CMPNEI]  = INSTRUCTION(cmpnei),
+    [0x19]    = INSTRUCTION_ILLEGAL(),
+    [0x1a]    = INSTRUCTION_ILLEGAL(),
+    [FLUSHDA] = INSTRUCTION_NOP(flushda),
+    [XORI]    = INSTRUCTION(xori),
+    [0x1d]    = INSTRUCTION_ILLEGAL(),
+    [BNE]     = INSTRUCTION(bne),
+    [0x1f]    = INSTRUCTION_ILLEGAL(),
+    [CMPEQI]  = INSTRUCTION(cmpeqi),
+    [0x21]    = INSTRUCTION_ILLEGAL(),
+    [0x22]    = INSTRUCTION_ILLEGAL(),
+    [LDBUIO]  = INSTRUCTION(ldbuio),
+    [MULI]    = INSTRUCTION(muli),
+    [STBIO]   = INSTRUCTION(stbio),
+    [BEQ]     = INSTRUCTION(beq),
+    [LDBIO]   = INSTRUCTION(ldbio),
+    [CMPGEUI] = INSTRUCTION(cmpgeui),
+    [0x29]    = INSTRUCTION_ILLEGAL(),
+    [0x2a]    = INSTRUCTION_ILLEGAL(),
+    [LDHUIO]  = INSTRUCTION(ldhuio),
+    [ANDHI]   = INSTRUCTION(andhi),
+    [STHIO]   = INSTRUCTION(sthio),
+    [BGEU]    = INSTRUCTION(bgeu),
+    [LDHIO]   = INSTRUCTION(ldhio),
+    [CMPLTUI] = INSTRUCTION(cmpltui),
+    [0x31]    = INSTRUCTION_ILLEGAL(),
+    [CUSTOM]  = INSTRUCTION_UNIMPLEMENTED(custom),
+    [INITD]   = INSTRUCTION(initd),
+    [ORHI]    = INSTRUCTION(orhi),
+    [STWIO]   = INSTRUCTION(stwio),
+    [BLTU]    = INSTRUCTION(bltu),
+    [LDWIO]   = INSTRUCTION(ldwio),
+    [RDPRS]   = INSTRUCTION_UNIMPLEMENTED(rdprs),
+    [0x39]    = INSTRUCTION_ILLEGAL(),
+    [R_TYPE]  = { "<R-type instruction>", handle_r_type_instr },
+    [FLUSHD]  = INSTRUCTION_NOP(flushd),
+    [XORHI]   = INSTRUCTION(xorhi),
+    [0x3d]    = INSTRUCTION_ILLEGAL(),
+    [0x3e]    = INSTRUCTION_ILLEGAL(),
+    [0x3f]    = INSTRUCTION_ILLEGAL(),
+};
+
+/*
+ * R-Type instructions
+ */
+
+/*
+ * status <- estatus
+ * PC <- ea
+ */
+static void eret(DisasContext *dc, uint32_t code __attribute__((unused)))
+{
+#ifdef CALL_TRACING
+    TCGv_i32 tmp = tcg_const_i32(dc->pc);
+    gen_helper_eret_status(tmp);
+    tcg_temp_free_i32(tmp);
+#endif
+
+    tcg_gen_mov_tl(dc->cpu_R[CR_STATUS], dc->cpu_R[CR_ESTATUS]);
+    tcg_gen_mov_tl(dc->cpu_R[R_PC], dc->cpu_R[R_EA]);
+
+    dc->is_jmp = DISAS_JUMP;
+}
+
+/* rC <- rA rotated left IMM5 bit positions */
+static void roli(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_rotli_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a], instr->imm5);
+}
+
+/* rC <- rA rotated left rB(4..0) bit positions */
+static void rol(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    TCGv t0 = tcg_temp_new();
+
+    tcg_gen_andi_tl(t0, dc->cpu_R[instr->b], 31);
+    tcg_gen_rotl_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a], t0);
+
+    tcg_temp_free(t0);
+}
+
+/* */
+static void flushp(DisasContext *dc __attribute__((unused)),
+                   uint32_t code __attribute__((unused)))
+{
+    /* TODO */
+}
+
+/* PC <- ra */
+static void ret(DisasContext *dc, uint32_t code __attribute__((unused)))
+{
+#ifdef CALL_TRACING
+    TCGv_i32 tmp = tcg_const_i32(dc->pc);
+    gen_helper_ret_status(tmp);
+    tcg_temp_free_i32(tmp);
+#endif
+
+    tcg_gen_mov_tl(dc->cpu_R[R_PC], dc->cpu_R[R_RA]);
+
+    dc->is_jmp = DISAS_JUMP;
+}
+
+/* rC <- ~(A | rB) */
+static void nor(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_nor_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                   dc->cpu_R[instr->b]);
+}
+
+/* rC <- ((unsigned)rA * (unsigned)rB))(31..0) */
+static void mulxuu(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    TCGv_i64 t0, t1;
+
+    t0 = tcg_temp_new_i64();
+    t1 = tcg_temp_new_i64();
+
+    tcg_gen_extu_i32_i64(t0, dc->cpu_R[instr->a]);
+    tcg_gen_extu_i32_i64(t1, dc->cpu_R[instr->b]);
+    tcg_gen_mul_i64(t0, t0, t1);
+
+    tcg_gen_shri_i64(t0, t0, 32);
+    tcg_gen_trunc_i64_i32(dc->cpu_R[instr->c], t0);
+
+    tcg_temp_free_i64(t0);
+    tcg_temp_free_i64(t1);
+}
+
+/*
+ * if (rA >= rB)
+ *   rC <- 1
+ * else
+ *   rC <- 0
+ */
+static void cmpge(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_setcond_tl(TCG_COND_GE, dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                       dc->cpu_R[instr->b]);
+}
+
+/* PC <- ba */
+static void bret(DisasContext *dc, uint32_t code __attribute__((unused)))
+{
+    tcg_gen_mov_tl(dc->cpu_R[R_PC], dc->cpu_R[R_BA]);
+
+    dc->is_jmp = DISAS_JUMP;
+}
+
+/*  rC <- rA rotated right rb(4..0) bit positions */
+static void ror(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    TCGv t0 = tcg_temp_new();
+
+    tcg_gen_andi_tl(t0, dc->cpu_R[instr->b], 31);
+    tcg_gen_rotr_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a], t0);
+
+    tcg_temp_free(t0);
+}
+
+/* */
+static void flushi(DisasContext *dc __attribute__((unused)),
+                   uint32_t code __attribute__((unused)))
+{
+    /* TODO */
+}
+
+/* PC <- rA */
+static void jmp(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_mov_tl(dc->cpu_R[R_PC], dc->cpu_R[instr->a]);
+
+    dc->is_jmp = DISAS_JUMP;
+}
+
+/* rC <- rA & rB */
+static void and(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_and_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                   dc->cpu_R[instr->b]);
+}
+
+/*
+ * if ((signed) rA < (signed) rB)
+ *   rC <- 1
+ * else
+ *   rC <- 0
+ */
+static void cmplt(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_setcond_tl(TCG_COND_LT, dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                       dc->cpu_R[instr->b]);
+}
+
+/* rC <- rA << IMM5 */
+static void slli(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_shli_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a], instr->imm5);
+}
+
+/* rC <- rA << rB(4..0) */
+static void sll(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    TCGv t0 = tcg_temp_new();
+
+    tcg_gen_andi_tl(t0, dc->cpu_R[instr->b], 31);
+    tcg_gen_shl_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a], t0);
+
+    tcg_temp_free(t0);
+}
+
+/* rC <- rA | rB */
+static void or(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_or_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                  dc->cpu_R[instr->b]);
+}
+
+/* rC <- ((signed)rA * (unsigned)rB))(31..0) */
+static void mulxsu(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    TCGv_i64 t0, t1;
+
+    t0 = tcg_temp_new_i64();
+    t1 = tcg_temp_new_i64();
+
+    tcg_gen_ext_i32_i64(t0, dc->cpu_R[instr->a]);
+    tcg_gen_extu_i32_i64(t1, dc->cpu_R[instr->b]);
+    tcg_gen_mul_i64(t0, t0, t1);
+
+    tcg_gen_shri_i64(t0, t0, 32);
+    tcg_gen_trunc_i64_i32(dc->cpu_R[instr->c], t0);
+
+    tcg_temp_free_i64(t0);
+    tcg_temp_free_i64(t1);
+}
+
+/*
+ * if (rA != rB)
+ *   rC <- 1
+ * else
+ *   rC <- 0
+ */
+static void cmpne(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_setcond_tl(TCG_COND_NE, dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                       dc->cpu_R[instr->b]);
+}
+
+/* rC <- (unsigned) rA >> ((unsigned) IMM5)*/
+static void srli(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_shri_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a], instr->imm5);
+}
+
+/* rC <- (unsigned) rA >> ((unsigned) rB(4..0))*/
+static void srl(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    TCGv t0 = tcg_temp_new();
+
+    tcg_gen_andi_tl(t0, dc->cpu_R[instr->b], 31);
+    tcg_gen_shr_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a], t0);
+
+    tcg_temp_free(t0);
+}
+
+/* rC <- PC + 4 */
+static void nextpc(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_movi_tl(dc->cpu_R[instr->c], dc->pc + 4);
+}
+
+/*
+ * ra <- PC + 4
+ * PC <- rA
+ */
+static void callr(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+#ifdef CALL_TRACING
+    TCGv_i32 tmp = tcg_const_i32(dc->pc);
+    gen_helper_call_status(tmp, dc->cpu_R[instr->a]);
+    tcg_temp_free_i32(tmp);
+#endif
+
+    tcg_gen_movi_tl(dc->cpu_R[R_RA], dc->pc + 4);
+    tcg_gen_mov_tl(dc->cpu_R[R_PC], dc->cpu_R[instr->a]);
+
+    dc->is_jmp = DISAS_JUMP;
+}
+
+/* rC <- rA ^ rB */
+static void xor(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_xor_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                   dc->cpu_R[instr->b]);
+}
+
+/* rC <- ((signed)rA * (signed)rB))(31..0) */
+static void mulxss(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    TCGv_i64 t0, t1;
+
+    t0 = tcg_temp_new_i64();
+    t1 = tcg_temp_new_i64();
+
+    tcg_gen_ext_i32_i64(t0, dc->cpu_R[instr->a]);
+    tcg_gen_ext_i32_i64(t1, dc->cpu_R[instr->b]);
+    tcg_gen_mul_i64(t0, t0, t1);
+
+    tcg_gen_shri_i64(t0, t0, 32);
+    tcg_gen_trunc_i64_i32(dc->cpu_R[instr->c], t0);
+
+    tcg_temp_free_i64(t0);
+    tcg_temp_free_i64(t1);
+}
+
+/*
+ * if (rA == rB)
+ *   rC <- 1
+ * else
+ *   rC <- 0
+ */
+static void cmpeq(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_setcond_tl(TCG_COND_EQ, dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                       dc->cpu_R[instr->b]);
+}
+
+/* rC <- rA / rB */
+static void divu(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    gen_helper_divu(dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                    dc->cpu_R[instr->b]);
+}
+
+/* rC <- rA / rB */
+static void _div(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    gen_helper_divs(dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                    dc->cpu_R[instr->b]);
+}
+
+/* rC <- ctlN */
+static void rdctl(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    int l1 = gen_new_label();
+    gen_check_supervisor(dc, l1);
+
+    switch (instr->imm5 + 32) {
+    case CR_PTEADDR:
+    case CR_TLBACC:
+    case CR_TLBMISC:
+    {
+        TCGv_i32 tmp = tcg_const_i32(instr->imm5 + 32);
+        gen_helper_mmu_read(dc->cpu_R[instr->c], dc->cpu_env, tmp);
+        tcg_temp_free_i32(tmp);
+        break;
+    }
+
+    default:
+        tcg_gen_mov_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->imm5 + 32]);
+        break;
+    }
+
+    gen_set_label(l1);
+}
+
+/* rC <- (rA * rB))(31..0) */
+static void mul(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_mul_i32(dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                    dc->cpu_R[instr->b]);
+}
+
+/*
+ * if (rA >= rB)
+ *   rC <- 1
+ * else
+ *   rC <- 0
+ */
+static void cmpgeu(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_setcond_tl(TCG_COND_GEU, dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                       dc->cpu_R[instr->b]);
+}
+
+/* */
+static void initi(DisasContext *dc __attribute__((unused)),
+                  uint32_t code __attribute__((unused)))
+{
+    /* TODO */
+}
+
+/*
+ * estatus <- status
+ * PIE <- 0
+ * U <- 0
+ * ea <- PC + 4
+ * PC <- exception handler address
+ */
+static void trap(DisasContext *dc, uint32_t code __attribute__((unused)))
+{
+    t_gen_helper_raise_exception(dc, EXCP_TRAP);
+}
+
+/* ctlN <- rA */
+static void wrctl(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    int l1 = gen_new_label();
+    gen_check_supervisor(dc, l1);
+
+    switch (instr->imm5 + 32) {
+    case CR_PTEADDR:
+    case CR_TLBACC:
+    case CR_TLBMISC:
+    {
+        TCGv_i32 tmp = tcg_const_i32(instr->imm5 + 32);
+        gen_helper_mmu_write(dc->cpu_env, tmp, dc->cpu_R[instr->a]);
+        tcg_temp_free_i32(tmp);
+        break;
+    }
+
+    default:
+        tcg_gen_mov_tl(dc->cpu_R[instr->imm5 + 32], dc->cpu_R[instr->a]);
+        break;
+    }
+
+    gen_set_label(l1);
+}
+
+/*
+ * if (rA < rB)
+ *   rC <- 1
+ * else
+ *   rC <- 0
+ */
+static void cmpltu(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_setcond_tl(TCG_COND_LTU, dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                       dc->cpu_R[instr->b]);
+}
+
+/* rC <- rA + rB */
+static void add(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_add_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                   dc->cpu_R[instr->b]);
+}
+
+/*
+ * bstatus ← status
+ * PIE <- 0
+ * U <- 0
+ * ba <- PC + 4
+ * PC <- break handler address
+ */
+static void __break(DisasContext *dc, uint32_t code __attribute__((unused)))
+{
+    t_gen_helper_raise_exception(dc, EXCP_BREAK);
+}
+
+/* rC <- rA - rB */
+static void sub(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_sub_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a],
+                   dc->cpu_R[instr->b]);
+}
+
+/* rC <- (signed) rA >> ((unsigned) IMM5) */
+static void srai(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    tcg_gen_sari_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a], instr->imm5);
+}
+
+/* rC <- (signed) rA >> ((unsigned) rB(4..0)) */
+static void sra(DisasContext *dc, uint32_t code)
+{
+    R_TYPE(instr, code);
+
+    TCGv t0 = tcg_temp_new();
+
+    tcg_gen_andi_tl(t0, dc->cpu_R[instr->b], 31);
+    tcg_gen_sar_tl(dc->cpu_R[instr->c], dc->cpu_R[instr->a], t0);
+
+    tcg_temp_free(t0);
+}
+
+static const Nios2Instruction r_type_instructions[R_TYPE_COUNT] = {
+    [0x00]   = INSTRUCTION_ILLEGAL(),
+    [ERET]   = INSTRUCTION(eret),
+    [ROLI]   = INSTRUCTION(roli),
+    [ROL]    = INSTRUCTION(rol),
+    [FLUSHP] = INSTRUCTION(flushp),
+    [RET]    = INSTRUCTION(ret),
+    [NOR]    = INSTRUCTION(nor),
+    [MULXUU] = INSTRUCTION(mulxuu),
+    [CMPGE]  = INSTRUCTION(cmpge),
+    [BRET]   = INSTRUCTION(bret),
+    [0x0a]   = INSTRUCTION_ILLEGAL(),
+    [ROR]    = INSTRUCTION(ror),
+    [FLUSHI] = INSTRUCTION(flushi),
+    [JMP]    = INSTRUCTION(jmp),
+    [AND]    = INSTRUCTION(and),
+    [0x0f]   = INSTRUCTION_ILLEGAL(),
+    [CMPLT]  = INSTRUCTION(cmplt),
+    [0x11]   = INSTRUCTION_ILLEGAL(),
+    [SLLI]   = INSTRUCTION(slli),
+    [SLL]    = INSTRUCTION(sll),
+    [WRPRS]  = INSTRUCTION_UNIMPLEMENTED(wrprs),
+    [0x15]   = INSTRUCTION_ILLEGAL(),
+    [OR]     = INSTRUCTION(or),
+    [MULXSU] = INSTRUCTION(mulxsu),
+    [CMPNE]  = INSTRUCTION(cmpne),
+    [0x19]   = INSTRUCTION_ILLEGAL(),
+    [SRLI]   = INSTRUCTION(srli),
+    [SRL]    = INSTRUCTION(srl),
+    [NEXTPC] = INSTRUCTION(nextpc),
+    [CALLR]  = INSTRUCTION(callr),
+    [XOR]    = INSTRUCTION(xor),
+    [MULXSS] = INSTRUCTION(mulxss),
+    [CMPEQ]  = INSTRUCTION(cmpeq),
+    [0x21]   = INSTRUCTION_ILLEGAL(),
+    [0x22]   = INSTRUCTION_ILLEGAL(),
+    [0x23]   = INSTRUCTION_ILLEGAL(),
+    [DIVU]   = INSTRUCTION(divu),
+    [DIV]    = { "div", _div },
+    [RDCTL]  = INSTRUCTION(rdctl),
+    [MUL]    = INSTRUCTION(mul),
+    [CMPGEU] = INSTRUCTION(cmpgeu),
+    [INITI]  = INSTRUCTION(initi),
+    [0x2a]   = INSTRUCTION_ILLEGAL(),
+    [0x2b]   = INSTRUCTION_ILLEGAL(),
+    [0x2c]   = INSTRUCTION_ILLEGAL(),
+    [TRAP]   = INSTRUCTION(trap),
+    [WRCTL]  = INSTRUCTION(wrctl),
+    [0x2f]   = INSTRUCTION_ILLEGAL(),
+    [CMPLTU] = INSTRUCTION(cmpltu),
+    [ADD]    = INSTRUCTION(add),
+    [0x32]   = INSTRUCTION_ILLEGAL(),
+    [0x33]   = INSTRUCTION_ILLEGAL(),
+    [BREAK]  = { "break", __break },
+    [0x35]   = INSTRUCTION_ILLEGAL(),
+    [SYNC]   = INSTRUCTION(nop),
+    [0x37]   = INSTRUCTION_ILLEGAL(),
+    [0x38]   = INSTRUCTION_ILLEGAL(),
+    [SUB]    = INSTRUCTION(sub),
+    [SRAI]   = INSTRUCTION(srai),
+    [SRA]    = INSTRUCTION(sra),
+    [0x3c]   = INSTRUCTION_ILLEGAL(),
+    [0x3d]   = INSTRUCTION_ILLEGAL(),
+    [0x3e]   = INSTRUCTION_ILLEGAL(),
+    [0x3f]   = INSTRUCTION_ILLEGAL(),
+};
+
+static void handle_r_type_instr(DisasContext *dc, uint32_t code)
+{
+    uint32_t opx;
+    instruction_handler handle_instr;
+
+    opx = get_opxcode(code);
+    if (unlikely(opx >= R_TYPE_COUNT)) {
+        goto illegal_op;
+    }
+
+    LOG_DIS("R: %s (%08x)\n", r_type_instructions[opx].name, code);
+    handle_instr = r_type_instructions[opx].handler;
+
+    handle_instr(dc, code);
+
+    return;
+
+illegal_op:
+    t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
+}
+
+void handle_instruction(DisasContext *dc, CPUNios2State *env)
+{
+    uint32_t insn = cpu_ldl_code(env, dc->pc);
+    uint32_t op = get_opcode(insn);
+
+    LOG_DIS("%8.8x\t", insn);
+
+    if (unlikely(op >= I_TYPE_COUNT)) {
+        goto illegal_op;
+    }
+
+    if (op != R_TYPE) {
+        LOG_DIS("I: %s (%08x)\n", i_type_instructions[op].name, insn);
+    }
+    i_type_instructions[op].handler(dc, insn);
+
+    return;
+
+illegal_op:
+    t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
+}
+
+const char *instruction_get_string(uint32_t code)
+{
+    uint32_t op = get_opcode(code);
+
+    if (unlikely(op >= I_TYPE_COUNT)) {
+        return "";
+    } else if (op == R_TYPE) {
+        uint32_t opx = get_opxcode(code);
+        if (unlikely(opx >= R_TYPE_COUNT)) {
+            return "";
+        }
+        return r_type_instructions[opx].name;
+    } else {
+        return i_type_instructions[op].name;
+    }
+}
+
diff --git a/target-nios2/instruction.h b/target-nios2/instruction.h
new file mode 100644
index 0000000..3758899
--- /dev/null
+++ b/target-nios2/instruction.h
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2010 chysun2000@gmail.com
+ *  (Portions of this file that were originally from nios2sim-ng.)
+ *
+ * Copyright (C) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 _INSTRUCTION_H_
+#define _INSTRUCTION_H_
+
+#include <stdint.h>
+#include "cpu.h"
+#include "tcg-op.h"
+
+/*
+ * Instruction Word Formats
+ */
+
+/* I-Type instruction */
+typedef struct Nios2IType {
+    uint32_t op:6;
+    uint32_t imm16:16;
+    uint32_t b:5;
+    uint32_t a:5;
+} QEMU_PACKED Nios2IType;
+
+union i_type_u {
+    uint32_t      v;
+    Nios2IType i;
+};
+
+#define I_TYPE(instr, op) \
+    union i_type_u instr_u = { .v = op }; \
+    Nios2IType *instr = &instr_u.i
+
+/* R-Type instruction */
+typedef struct Nios2RType {
+    uint32_t op:6;
+    /*
+     * Some R-Type instructions embed a small immediate value in the
+     * low-order bits of OPX.
+     */
+    uint32_t imm5:5;
+    uint32_t opx6:6;
+    uint32_t c:5;
+    uint32_t b:5;
+    uint32_t a:5;
+} QEMU_PACKED Nios2RType;
+
+union r_type_u {
+    uint32_t      v;
+    Nios2RType i;
+};
+
+#define R_TYPE(instr, op) \
+    union r_type_u instr_u = { .v = op }; \
+    Nios2RType *instr = &instr_u.i
+
+/* J-Type instruction */
+typedef struct Nios2JType {
+    uint32_t op:6;
+    uint32_t imm26:26;
+} QEMU_PACKED Nios2JType;
+
+#define J_TYPE(instr, op) \
+    Nios2JType *instr = (Nios2JType *) &op
+
+/*
+ * Instruction Opcodes
+ */
+
+/*
+ * OP Encodings for I-Type instructions (except for CALL and JMPI, which are
+ * J-type instructions)
+ */
+enum {
+    CALL    = 0x00,  /* J-type */
+    JMPI    = 0x01,  /* J-type */
+           /* 0x02 */
+    LDBU    = 0x03,
+    ADDI    = 0x04,
+    STB     = 0x05,
+    BR      = 0x06,
+    LDB     = 0x07,
+    CMPGEI  = 0x08,
+           /* 0x09 */
+           /* 0x0A */
+    LDHU    = 0x0B,
+    ANDI    = 0x0C,
+    STH     = 0x0D,
+    BGE     = 0x0E,
+    LDH     = 0x0F,
+    CMPLTI  = 0x10,
+           /* 0x11 */
+           /* 0x12 */
+    INITDA  = 0x13,
+    ORI     = 0x14,
+    STW     = 0x15,
+    BLT     = 0x16,
+    LDW     = 0x17,
+    CMPNEI  = 0x18,
+           /* 0x19 */
+           /* 0x1A */
+    FLUSHDA = 0x1B,
+    XORI    = 0x1C,
+           /* 0x1D */
+    BNE     = 0x1E,
+           /* 0x1F */
+    CMPEQI  = 0x20,
+           /* 0x21 */
+           /* 0x22 */
+    LDBUIO  = 0x23,
+    MULI    = 0x24,
+    STBIO   = 0x25,
+    BEQ     = 0x26,
+    LDBIO   = 0x27,
+    CMPGEUI = 0x28,
+           /* 0x29 */
+           /* 0x2A */
+    LDHUIO  = 0x2B,
+    ANDHI   = 0x2C,
+    STHIO   = 0x2D,
+    BGEU    = 0x2E,
+    LDHIO   = 0x2F,
+    CMPLTUI = 0x30,
+           /* 0x31 */
+    CUSTOM  = 0x32,
+    INITD   = 0x33,
+    ORHI    = 0x34,
+    STWIO   = 0x35,
+    BLTU    = 0x36,
+    LDWIO   = 0x37,
+    RDPRS   = 0x38,
+           /* 0x39 */
+    R_TYPE  = 0x3A,
+    FLUSHD  = 0x3B,
+    XORHI   = 0x3C,
+           /* 0x3D */
+           /* 0x3E */
+           /* 0x3F */
+};
+#define I_TYPE_COUNT  0x40
+
+/* OPX Encodings for R-Type instructions */
+enum {
+          /* 0x00 */
+    ERET   = 0x01,
+    ROLI   = 0x02,
+    ROL    = 0x03,
+    FLUSHP = 0x04,
+    RET    = 0x05,
+    NOR    = 0x06,
+    MULXUU = 0x07,
+    CMPGE  = 0x08,
+    BRET   = 0x09,
+          /* 0x0A */
+    ROR    = 0x0B,
+    FLUSHI = 0x0C,
+    JMP    = 0x0D,
+    AND    = 0x0E,
+          /* 0x0F */
+    CMPLT  = 0x10,
+          /* 0x11 */
+    SLLI   = 0x12,
+    SLL    = 0x13,
+    WRPRS  = 0x14,
+          /* 0x15 */
+    OR     = 0x16,
+    MULXSU = 0x17,
+    CMPNE  = 0x18,
+          /* 0x19 */
+    SRLI   = 0x1A,
+    SRL    = 0x1B,
+    NEXTPC = 0x1C,
+    CALLR  = 0x1D,
+    XOR    = 0x1E,
+    MULXSS = 0x1F,
+    CMPEQ  = 0x20,
+          /* 0x21 */
+          /* 0x22 */
+          /* 0x23 */
+    DIVU   = 0x24,
+    DIV    = 0x25,
+    RDCTL  = 0x26,
+    MUL    = 0x27,
+    CMPGEU = 0x28,
+    INITI  = 0x29,
+          /* 0x2A */
+          /* 0x2B */
+          /* 0x2C */
+    TRAP   = 0x2D,
+    WRCTL  = 0x2E,
+          /* 0x2F */
+    CMPLTU = 0x30,
+    ADD    = 0x31,
+          /* 0x32 */
+          /* 0x33 */
+    BREAK  = 0x34,
+          /* 0x35 */
+    SYNC   = 0x36,
+          /* 0x37 */
+          /* 0x38 */
+    SUB    = 0x39,
+    SRAI   = 0x3A,
+    SRA    = 0x3B,
+          /* 0x3C */
+          /* 0x3D */
+          /* 0x3E */
+          /* 0x3F */
+};
+#define R_TYPE_COUNT  0x40
+
+/*
+ * Return values for instruction handlers
+ */
+#define INSTR_UNIMPL     -2  /* Unimplemented instruction */
+#define INSTR_ERR        -1  /* Error in instruction */
+#define PC_INC_NORMAL     0  /* Normal PC increment after instruction */
+#define PC_INC_BY_INSTR   1  /* PC got incremented by instruction */
+#define INSTR_BREAK       2  /* Break encountered */
+#define INSTR_EXCEPTION 255  /* Instruction generated an exception
+                                (the exception cause will be stored
+                                in struct nios2 */
+
+#define EXCEPTION(cpu, cause)           \
+    ({                                  \
+        (cpu)->exception_cause = cause; \
+        INSTR_EXCEPTION;                \
+    })
+
+typedef struct DisasContext {
+    TCGv_ptr          cpu_env;
+    TCGv             *cpu_R;
+    int               is_jmp;
+    target_ulong      pc;
+    TranslationBlock *tb;
+    int               mem_idx;
+} DisasContext;
+
+typedef void (*instruction_handler)(DisasContext *dc, uint32_t opcode);
+
+typedef struct Nios2Instruction {
+    const char         *name;
+    instruction_handler handler;
+} Nios2Instruction;
+
+#define INSTRUCTION(name)    { stringify(name), name }
+#define INSTRUCTION_NOP(name)    { stringify(name), nop }
+#define INSTRUCTION_UNIMPLEMENTED(name)  { stringify(name), unimplemented }
+#define INSTRUCTION_ILLEGAL()  { "", illegal_instruction }
+
+extern void handle_instruction(DisasContext *dc, CPUNios2State *env);
+extern const char *instruction_get_string(uint32_t code);
+
+#define SIM_COMPAT 0
+#define DISAS_GNU 1   /* Disassembly via GNU gdb derived routines */
+#define DISAS_NIOS2 0 /* Disassembly via routines in instruction.c */
+#if DISAS_NIOS2 && !SIM_COMPAT
+#  define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
+#else
+#  define LOG_DIS(...) do { } while (0)
+#endif
+
+#endif /* _INSTRUCTION_H_ */
diff --git a/target-nios2/machine.c b/target-nios2/machine.c
new file mode 100644
index 0000000..09198db
--- /dev/null
+++ b/target-nios2/machine.c
@@ -0,0 +1,33 @@
+/*
+ * Altera Nios II MMU emulation for qemu.
+ *
+ * Copyright (C) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 "hw/hw.h"
+#include "hw/boards.h"
+
+void cpu_save(QEMUFile *f, void *opaque)
+{
+    /* TODO */
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    /* TODO */
+    return 0;
+}
diff --git a/target-nios2/mmu.c b/target-nios2/mmu.c
new file mode 100644
index 0000000..2c50128
--- /dev/null
+++ b/target-nios2/mmu.c
@@ -0,0 +1,273 @@
+/*
+ * Altera Nios II MMU emulation for qemu.
+ *
+ * Copyright (C) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "config.h"
+#include "cpu.h"
+#include "exec-all.h"
+
+/* Define this to enable MMU debug messages */
+/* #define DEBUG_MMU */
+
+#ifdef DEBUG_MMU
+#define MMU_LOG(x) x
+#else
+#define MMU_LOG(x)
+#endif
+
+uint32_t mmu_read(CPUNios2State *env, uint32_t rn)
+{
+    switch (rn) {
+    case CR_TLBACC:
+        MMU_LOG(qemu_log("TLBACC READ %08X\n", env->regs[rn]));
+        break;
+
+    case CR_TLBMISC:
+        MMU_LOG(qemu_log("TLBMISC READ %08X\n", env->regs[rn]));
+        break;
+
+    case CR_PTEADDR:
+        MMU_LOG(qemu_log("PTEADDR READ %08X\n", env->regs[rn]));
+        break;
+
+    default:
+        break;
+    }
+    return env->regs[rn];
+}
+
+/* rw - 0 = read, 1 = write, 2 = fetch.  */
+unsigned int mmu_translate(CPUNios2State *env,
+                           Nios2MMULookup *lu,
+                           target_ulong vaddr, int rw, int mmu_idx)
+{
+    int pid = (env->mmu.tlbmisc_wr & CR_TLBMISC_PID_MASK) >> 4;
+    int vpn = vaddr >> 12;
+
+    MMU_LOG(qemu_log("mmu_translate vaddr %08X, pid %08X, vpn %08X\n",
+                     vaddr, pid, vpn));
+
+    int way;
+    for (way = 0; way < env->mmu.tlb_num_ways; way++) {
+
+        Nios2TLBEntry *entry =
+            &env->mmu.tlb[(way * env->mmu.tlb_num_ways) +
+                          (vpn & env->mmu.tlb_entry_mask)];
+
+        MMU_LOG(qemu_log("TLB[%d] TAG %08X, VPN %08X\n",
+                         (way * env->mmu.tlb_num_ways) +
+                         (vpn & env->mmu.tlb_entry_mask),
+                         entry->tag, (entry->tag >> 12)));
+
+        if (((entry->tag >> 12) != vpn) ||
+            (((entry->tag & (1<<11)) == 0) &&
+            ((entry->tag & ((1<<env->mmu.pid_bits)-1)) != pid))) {
+            continue;
+        }
+        lu->vaddr = vaddr & TARGET_PAGE_MASK;
+        lu->paddr = (entry->data & CR_TLBACC_PFN_MASK) << TARGET_PAGE_BITS;
+        lu->prot = ((entry->data & CR_TLBACC_R) ? PAGE_READ : 0) |
+                   ((entry->data & CR_TLBACC_W) ? PAGE_WRITE : 0) |
+                   ((entry->data & CR_TLBACC_X) ? PAGE_EXEC : 0);
+
+        MMU_LOG(qemu_log("HIT TLB[%d] %08X %08X %08X\n",
+                         (way * env->mmu.tlb_num_ways) +
+                         (vpn & env->mmu.tlb_entry_mask),
+                         lu->vaddr, lu->paddr, lu->prot));
+        return 1;
+    }
+    return 0;
+}
+
+static void mmu_flush_pid(CPUNios2State *env, uint32_t pid)
+{
+    int idx;
+    MMU_LOG(qemu_log("TLB Flush PID %d\n", pid));
+
+    for (idx = 0; idx < env->mmu.tlb_num_entries; idx++) {
+        Nios2TLBEntry *entry = &env->mmu.tlb[idx];
+
+        MMU_LOG(qemu_log("TLB[%d] => %08X %08X\n",
+                         idx, entry->tag, entry->data));
+
+        if ((entry->tag & (1<<10)) && (!(entry->tag & (1<<11))) &&
+            ((entry->tag & ((1<<env->mmu.pid_bits)-1)) == pid)) {
+            uint32_t vaddr = entry->tag & TARGET_PAGE_MASK;
+
+            MMU_LOG(qemu_log("TLB Flush Page %08X\n", vaddr));
+
+            tlb_flush_page(env, vaddr);
+        }
+    }
+}
+
+void mmu_write(CPUNios2State *env, uint32_t rn, uint32_t v)
+{
+    MMU_LOG(qemu_log("mmu_write %08X = %08X\n", rn, v));
+
+    switch (rn) {
+    case CR_TLBACC:
+        MMU_LOG(qemu_log("TLBACC: IG %02X, FLAGS %c%c%c%c%c, PFN %05X\n",
+                         v >> CR_TLBACC_IGN_SHIFT,
+                         (v & CR_TLBACC_C) ? 'C' : '.',
+                         (v & CR_TLBACC_R) ? 'R' : '.',
+                         (v & CR_TLBACC_W) ? 'W' : '.',
+                         (v & CR_TLBACC_X) ? 'X' : '.',
+                         (v & CR_TLBACC_G) ? 'G' : '.',
+                         v & CR_TLBACC_PFN_MASK));
+
+        /* if tlbmisc.WE == 1 then trigger a TLB write on writes to TLBACC */
+        if (env->regs[CR_TLBMISC] & CR_TLBMISC_WR) {
+            int way = (env->regs[CR_TLBMISC] >> CR_TLBMISC_WAY_SHIFT);
+            int vpn = (env->mmu.pteaddr_wr & CR_PTEADDR_VPN_MASK) >> 2;
+            int pid = (env->mmu.tlbmisc_wr & CR_TLBMISC_PID_MASK) >> 4;
+            int g = (v & CR_TLBACC_G) ? 1 : 0;
+            int valid = ((vpn & CR_TLBACC_PFN_MASK) < 0xC0000) ? 1 : 0;
+            Nios2TLBEntry *entry =
+                &env->mmu.tlb[(way * env->mmu.tlb_num_ways) +
+                              (vpn & env->mmu.tlb_entry_mask)];
+            uint32_t newTag = (vpn << 12) | (g << 11) | (valid << 10) | pid;
+            uint32_t newData = v & (CR_TLBACC_C | CR_TLBACC_R | CR_TLBACC_W |
+                                    CR_TLBACC_X | CR_TLBACC_PFN_MASK);
+
+            if ((entry->tag != newTag) || (entry->data != newData)) {
+                if (entry->tag & (1<<10)) {
+                    /* Flush existing entry */
+                    MMU_LOG(qemu_log("TLB Flush Page (OLD) %08X\n",
+                                     entry->tag & TARGET_PAGE_MASK));
+                    tlb_flush_page(env, entry->tag & TARGET_PAGE_MASK);
+                }
+                entry->tag = newTag;
+                entry->data = newData;
+                MMU_LOG(qemu_log("TLB[%d] = %08X %08X\n",
+                                 (way * env->mmu.tlb_num_ways) +
+                                 (vpn & env->mmu.tlb_entry_mask),
+                                 entry->tag, entry->data));
+            }
+            /* Auto-increment tlbmisc.WAY */
+            env->regs[CR_TLBMISC] =
+                (env->regs[CR_TLBMISC] & ~CR_TLBMISC_WAY_MASK) |
+                (((way+1) & (env->mmu.tlb_num_ways-1)) << CR_TLBMISC_WAY_SHIFT);
+        }
+
+        /* Writes to TLBACC don't change the read-back value */
+        env->mmu.tlbacc_wr = v;
+        break;
+
+    case CR_TLBMISC:
+        MMU_LOG(qemu_log("TLBMISC: WAY %X, FLAGS %c%c%c%c%c%c, PID %04X\n",
+                         v >> CR_TLBMISC_WAY_SHIFT,
+                         (v & CR_TLBMISC_RD) ? 'R' : '.',
+                         (v & CR_TLBMISC_WR) ? 'W' : '.',
+                         (v & CR_TLBMISC_DBL) ? '2' : '.',
+                         (v & CR_TLBMISC_BAD) ? 'B' : '.',
+                         (v & CR_TLBMISC_PERM) ? 'P' : '.',
+                         (v & CR_TLBMISC_D) ? 'D' : '.',
+                         (v & CR_TLBMISC_PID_MASK) >> 4));
+
+        if ((v & CR_TLBMISC_PID_MASK) !=
+            (env->mmu.tlbmisc_wr & CR_TLBMISC_PID_MASK)) {
+            mmu_flush_pid(env, (env->mmu.tlbmisc_wr & CR_TLBMISC_PID_MASK) >>
+                               CR_TLBMISC_PID_SHIFT);
+        }
+        /* if tlbmisc.RD == 1 then trigger a TLB read on writes to TLBMISC */
+        if (v & CR_TLBMISC_RD) {
+            int way = (v >> CR_TLBMISC_WAY_SHIFT);
+            int vpn = (env->mmu.pteaddr_wr & CR_PTEADDR_VPN_MASK) >> 2;
+            Nios2TLBEntry *entry =
+                &env->mmu.tlb[(way * env->mmu.tlb_num_ways) +
+                              (vpn & env->mmu.tlb_entry_mask)];
+
+            env->regs[CR_TLBACC] &= CR_TLBACC_IGN_MASK;
+            env->regs[CR_TLBACC] |= entry->data |
+                                    ((entry->tag & (1<<11)) ? CR_TLBACC_G : 0);
+            env->regs[CR_TLBMISC] =
+                (v & ~CR_TLBMISC_PID_MASK) |
+                ((entry->tag & ((1<<env->mmu.pid_bits)-1)) <<
+                 CR_TLBMISC_PID_SHIFT);
+            env->regs[CR_PTEADDR] &= ~CR_PTEADDR_VPN_MASK;
+            env->regs[CR_PTEADDR] |= (entry->tag >> 12) << CR_PTEADDR_VPN_SHIFT;
+            MMU_LOG(qemu_log("TLB READ way %d, vpn %05X, tag %08X, data %08X, "
+                             "tlbacc %08X, tlbmisc %08X, pteaddr %08X\n",
+                             way, vpn, entry->tag, entry->data,
+                             env->regs[CR_TLBACC], env->regs[CR_TLBMISC],
+                             env->regs[CR_PTEADDR]));
+        } else {
+            env->regs[CR_TLBMISC] = v;
+        }
+
+        env->mmu.tlbmisc_wr = v;
+        break;
+
+    case CR_PTEADDR:
+        MMU_LOG(qemu_log("PTEADDR: PTBASE %03X, VPN %05X\n",
+                         v >> CR_PTEADDR_PTBASE_SHIFT,
+                         (v & CR_PTEADDR_VPN_MASK) >> CR_PTEADDR_VPN_SHIFT));
+
+        /* Writes to PTEADDR don't change the read-back VPN value */
+        env->regs[CR_PTEADDR] = (v & ~CR_PTEADDR_VPN_MASK) |
+                                (env->regs[CR_PTEADDR] & CR_PTEADDR_VPN_MASK);
+        env->mmu.pteaddr_wr = v;
+        break;
+
+    default:
+        break;
+    }
+}
+
+void mmu_init(Nios2MMU *mmu)
+{
+    MMU_LOG(qemu_log("mmu_init\n"));
+
+    mmu->pid_bits = 8;          /* TODO: get this from ALTR,pid-num-bits */
+    mmu->tlb_num_ways = 16;     /* TODO: get this from ALTR,tlb-num-ways */
+    mmu->tlb_num_entries = 256; /* TODO: get this from ALTR,tlb-num-entries */
+    mmu->tlb_entry_mask = (mmu->tlb_num_entries/mmu->tlb_num_ways) - 1;
+
+    mmu->tlb = (Nios2TLBEntry *)g_malloc0(
+        sizeof(Nios2TLBEntry) * mmu->tlb_num_entries);
+}
+
+void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUNios2State *env)
+{
+    int i;
+    cpu_fprintf(f, "MMU: ways %d, entries %d, pid bits %d\n",
+                env->mmu.tlb_num_ways, env->mmu.tlb_num_entries,
+                env->mmu.pid_bits);
+
+    for (i = 0; i < env->mmu.tlb_num_entries; i++) {
+        Nios2TLBEntry *entry = &env->mmu.tlb[i];
+        cpu_fprintf(f, "TLB[%d] = %08X %08X %c VPN %05X "
+                    "PID %02X %c PFN %05X %c%c%c%c\n",
+                    i, entry->tag, entry->data,
+                    (entry->tag & (1<<10)) ? 'V' : '-',
+                    entry->tag >> 12, entry->tag & ((1<<env->mmu.pid_bits)-1),
+                    (entry->tag & (1<<11)) ? 'G' : '-',
+                    entry->data & CR_TLBACC_PFN_MASK,
+                    (entry->data & CR_TLBACC_C) ? 'C' : '-',
+                    (entry->data & CR_TLBACC_R) ? 'R' : '-',
+                    (entry->data & CR_TLBACC_W) ? 'W' : '-',
+                    (entry->data & CR_TLBACC_X) ? 'X' : '-');
+    }
+}
+
diff --git a/target-nios2/mmu.h b/target-nios2/mmu.h
new file mode 100644
index 0000000..710b053
--- /dev/null
+++ b/target-nios2/mmu.h
@@ -0,0 +1,49 @@
+/*
+ * Altera Nios II MMU emulation for qemu.
+ *
+ * Copyright (C) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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>
+ */
+
+typedef struct Nios2TLBEntry {
+    target_ulong tag;
+    target_ulong data;
+} Nios2TLBEntry;
+
+typedef struct Nios2MMU {
+    int pid_bits;
+    int tlb_num_ways;
+    int tlb_num_entries;
+    int tlb_entry_mask;
+    uint32_t pteaddr_wr;
+    uint32_t tlbacc_wr;
+    uint32_t tlbmisc_wr;
+    Nios2TLBEntry *tlb;
+} Nios2MMU;
+
+typedef struct Nios2MMULookup {
+    target_ulong vaddr;
+    target_ulong paddr;
+    int prot;
+} Nios2MMULookup;
+
+void mmu_flip_um(CPUNios2State *env, unsigned int um);
+unsigned int mmu_translate(CPUNios2State *env,
+                           Nios2MMULookup *lu,
+                           target_ulong vaddr, int rw, int mmu_idx);
+uint32_t mmu_read(CPUNios2State *env, uint32_t rn);
+void mmu_write(CPUNios2State *env, uint32_t rn, uint32_t v);
+void mmu_init(Nios2MMU *mmu);
diff --git a/target-nios2/op_helper.c b/target-nios2/op_helper.c
new file mode 100644
index 0000000..7f67c4c
--- /dev/null
+++ b/target-nios2/op_helper.c
@@ -0,0 +1,119 @@
+/*
+ * Altera Nios II helper routines.
+ *
+ * Copyright (C) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 "cpu.h"
+#include "helper.h"
+
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#define MMUSUFFIX _mmu
+#define SHIFT 0
+#include "softmmu_template.h"
+#define SHIFT 1
+#include "softmmu_template.h"
+#define SHIFT 2
+#include "softmmu_template.h"
+#define SHIFT 3
+#include "softmmu_template.h"
+
+void tlb_fill(CPUNios2State *env, target_ulong addr, int is_write, int mmu_idx,
+              uintptr_t retaddr)
+{
+    TranslationBlock *tb;
+    int ret;
+
+    ret = cpu_nios2_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    if (unlikely(ret)) {
+        if (retaddr) {
+            /* now we have a real cpu fault */
+            tb = tb_find_pc(retaddr);
+            if (tb) {
+                /* The PC is inside the translated code. It means that we have
+                   a virtual CPU fault */
+                cpu_restore_state(tb, env, retaddr);
+            }
+        }
+        cpu_loop_exit(env);
+    }
+}
+
+void helper_raise_exception(CPUNios2State *env, uint32_t index)
+{
+    env->exception_index = index;
+    cpu_loop_exit(env);
+}
+
+uint32_t helper_mmu_read(CPUNios2State *env, uint32_t rn)
+{
+    return mmu_read(env, rn);
+}
+
+void helper_mmu_write(CPUNios2State *env, uint32_t rn, uint32_t v)
+{
+    mmu_write(env, rn, v);
+}
+
+void helper_memalign(CPUNios2State *env, uint32_t addr, uint32_t dr, uint32_t wr, uint32_t mask)
+{
+    if (addr & mask) {
+        qemu_log("unaligned access addr=%x mask=%x, wr=%d dr=r%d\n",
+                 addr, mask, wr, dr);
+        env->regs[CR_BADADDR] = addr;
+        env->regs[CR_EXCEPTION] = EXCP_UNALIGN << 2;
+        helper_raise_exception(env, EXCP_UNALIGN);
+    }
+}
+
+void cpu_unassigned_access(CPUNios2State *env1, hwaddr addr,
+                           int is_write, int is_exec, int is_asi, int size)
+{
+    qemu_log("unassigned access to %"HWADDR_PRIX"\n", addr);
+}
+
+uint32_t helper_divs(uint32_t a, uint32_t b)
+{
+    return (int32_t)a / (int32_t)b;
+}
+
+uint32_t helper_divu(uint32_t a, uint32_t b)
+{
+    return a / b;
+}
+
+#ifdef CALL_TRACING
+void helper_call_status(uint32_t pc, uint32_t target)
+{
+    qemu_log("%08X: CALL %08X %s\n", pc, target, lookup_symbol(target));
+}
+
+void helper_eret_status(uint32_t pc)
+{
+    qemu_log("%08X: ERET STATUS %08X, ESTATUS %08X, EA %08X\n",
+             pc, env->regs[CR_STATUS], env->regs[CR_ESTATUS], env->regs[R_EA]);
+}
+
+void helper_ret_status(uint32_t pc)
+{
+    qemu_log("%08X: RET RA %08X\n", pc, env->regs[R_RA]);
+}
+#endif
+
+#endif /* !CONFIG_USER_ONLY */
+
diff --git a/target-nios2/translate.c b/target-nios2/translate.c
new file mode 100644
index 0000000..5507ccb
--- /dev/null
+++ b/target-nios2/translate.c
@@ -0,0 +1,253 @@
+/*
+ * Altera Nios II emulation for qemu: main translation routines.
+ *
+ * Copyright (C) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "disas.h"
+#include "helper.h"
+#include "qemu-common.h"
+
+#include "instruction.h"
+
+#define GEN_HELPER 1
+#include "helper.h"
+
+static const char *regnames[] = {
+    "zero",     "at",       "r2",       "r3",
+    "r4",       "r5",       "r6",       "r7",
+    "r8",       "r9",       "r10",      "r11",
+    "r12",      "r13",      "r14",      "r15",
+    "r16",      "r17",      "r18",      "r19",
+    "r20",      "r21",      "r22",      "r23",
+    "et",       "bt",       "gp",       "sp",
+    "fp",       "ea",       "ba",       "ra",
+    "status",   "estatus",  "bstatus",  "ienable",
+    "ipending", "cpuid",    "reserved", "exception",
+    "pteaddr",  "tlbacc",   "tlbmisc",  "reserved",
+    "badaddr",  "config",   "mpubase",  "mpuacc",
+    "reserved", "reserved", "reserved", "reserved",
+    "reserved", "reserved", "reserved", "reserved",
+    "reserved", "reserved", "reserved", "reserved",
+    "reserved", "reserved", "reserved", "reserved",
+    "rpc"
+};
+
+static TCGv_ptr cpu_env;
+static TCGv cpu_R[NUM_CORE_REGS];
+
+#include "gen-icount.h"
+
+/* generate intermediate code for basic block 'tb'.  */
+static void gen_intermediate_code_internal(
+    CPUNios2State *env, TranslationBlock *tb, int search_pc)
+{
+    DisasContext dc1, *dc = &dc1;
+    int num_insns;
+    int max_insns;
+    uint32_t next_page_start;
+    int j, lj = -1;
+    uint16_t *gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+
+    /* Initialize DC */
+    dc->cpu_env = cpu_env;
+    dc->cpu_R   = cpu_R;
+    dc->is_jmp  = DISAS_NEXT;
+    dc->pc      = tb->pc;
+    dc->tb      = tb;
+    dc->mem_idx = cpu_mmu_index(env);
+
+    /* Dump the CPU state to the log */
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+        qemu_log("--------------\n");
+        log_cpu_state(env, 0);
+    }
+
+    /* Set up instruction counts */
+    num_insns = 0;
+    max_insns = tb->cflags & CF_COUNT_MASK;
+    if (max_insns == 0) {
+        max_insns = CF_COUNT_MASK;
+    }
+    next_page_start = (tb->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+
+    gen_icount_start();
+    do {
+        /* Mark instruction start with associated PC */
+        if (search_pc) {
+            j = gen_opc_ptr - gen_opc_buf;
+            if (lj < j) {
+                lj++;
+                while (lj < j) {
+                    gen_opc_instr_start[lj++] = 0;
+                }
+            }
+            gen_opc_pc[lj] = dc->pc;
+            gen_opc_instr_start[lj] = 1;
+            gen_opc_icount[lj] = num_insns;
+        }
+
+        LOG_DIS("%8.8x:\t", dc->pc);
+
+        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+            gen_io_start();
+        }
+
+        /* Decode an instruction */
+        handle_instruction(dc, env);
+
+        dc->pc += 4;
+        num_insns++;
+
+        /* Translation stops when a conditional branch is encountered.
+         * Otherwise the subsequent code could get translated several times.
+         * Also stop translation when a page boundary is reached.  This
+         * ensures prefetch aborts occur at the right place.  */
+    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
+             !env->singlestep_enabled &&
+             !singlestep &&
+             dc->pc < next_page_start &&
+             num_insns < max_insns);
+
+    if (tb->cflags & CF_LAST_IO) {
+        gen_io_end();
+    }
+
+    /* Indicate where the next block should start */
+    switch (dc->is_jmp) {
+    case DISAS_NEXT:
+        /* Save the current PC back into the CPU register */
+        tcg_gen_movi_tl(cpu_R[R_PC], dc->pc);
+        tcg_gen_exit_tb(0);
+        break;
+
+    default:
+    case DISAS_JUMP:
+    case DISAS_UPDATE:
+        /* The jump will already have updated the PC register */
+        tcg_gen_exit_tb(0);
+        break;
+
+    case DISAS_TB_JUMP:
+        /* nothing more to generate */
+        break;
+    }
+
+    /* End off the block */
+    gen_icount_end(tb, num_insns);
+    *gen_opc_ptr = INDEX_op_end;
+
+    /* Mark instruction starts for the final generated instruction */
+    if (search_pc) {
+        j = gen_opc_ptr - gen_opc_buf;
+        lj++;
+        while (lj <= j) {
+            gen_opc_instr_start[lj++] = 0;
+        }
+    } else {
+        tb->size = dc->pc - tb->pc;
+        tb->icount = num_insns;
+    }
+
+#ifdef DEBUG_DISAS
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+        qemu_log("----------------\n");
+        qemu_log("IN: %s\n", lookup_symbol(tb->pc));
+        log_target_disas(tb->pc, dc->pc - tb->pc, 0);
+        qemu_log("\nisize=%d osize=%td\n",
+                 dc->pc - tb->pc, gen_opc_ptr - gen_opc_buf);
+    }
+#endif
+}
+
+void gen_intermediate_code(CPUNios2State *env, TranslationBlock *tb)
+{
+    gen_intermediate_code_internal(env, tb, 0);
+}
+
+void gen_intermediate_code_pc(CPUNios2State *env, TranslationBlock *tb)
+{
+    gen_intermediate_code_internal(env, tb, 1);
+}
+
+void cpu_dump_state(CPUNios2State *env, FILE *f, fprintf_function cpu_fprintf,
+                    int flags)
+{
+    int i;
+
+    if (!env || !f) {
+        return;
+    }
+
+    cpu_fprintf(f, "IN: PC=%x %s\n",
+                env->regs[R_PC], lookup_symbol(env->regs[R_PC]));
+
+    for (i = 0; i < NUM_CORE_REGS; i++) {
+        cpu_fprintf(f, "%9s=%8.8x ", regnames[i], env->regs[i]);
+        if ((i + 1) % 4 == 0) {
+            cpu_fprintf(f, "\n");
+        }
+    }
+    cpu_fprintf(f, " mmu write: VPN=%05X PID %02X TLBACC %08X\n",
+                env->mmu.pteaddr_wr & CR_PTEADDR_VPN_MASK,
+                (env->mmu.tlbmisc_wr & CR_TLBMISC_PID_MASK) >> 4,
+                env->mmu.tlbacc_wr);
+    cpu_fprintf(f, "\n\n");
+}
+
+Nios2CPU *cpu_nios2_init(const char *cpu_model)
+{
+    Nios2CPU *cpu;
+    int i;
+
+    cpu = NIOS2_CPU(object_new(TYPE_NIOS2_CPU));
+
+    cpu->env.reset_addr = RESET_ADDRESS;
+    cpu->env.exception_addr = EXCEPTION_ADDRESS;
+    cpu->env.fast_tlb_miss_addr = FAST_TLB_MISS_ADDRESS;
+
+    cpu_reset(CPU(cpu));
+    qemu_init_vcpu(&cpu->env);
+
+    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+
+    for (i = 0; i < NUM_CORE_REGS; i++) {
+        cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
+                                      offsetof(CPUNios2State, regs[i]),
+                                      regnames[i]);
+    }
+
+#define GEN_HELPER 2
+#include "helper.h"
+
+  return cpu;
+}
+
+void restore_state_to_opc(CPUNios2State *env, TranslationBlock *tb, int pc_pos)
+{
+    env->regs[R_PC] = gen_opc_pc[pc_pos];
+}
+
-- 
1.7.10.4

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

* [Qemu-devel] [PATCH 2/4] NiosII: Disassembly of NiosII instructions ported from GDB. (v2)
  2012-11-11  4:18 [Qemu-devel] [PATCH 0/4] Altera NiosII Support (v2) crwulff
  2012-11-11  4:18 ` [Qemu-devel] [PATCH 1/4] NiosII: Add support for the Altera NiosII soft-core CPU. (v2) crwulff
@ 2012-11-11  4:18 ` crwulff
  2012-11-11  4:18 ` [Qemu-devel] [PATCH 3/4] Altera: Add support for devices needed to boot Linux on NiosII. (v2) crwulff
  2012-11-11  4:18 ` [Qemu-devel] [PATCH 4/4] NiosII: Build system and documentation integration crwulff
  3 siblings, 0 replies; 5+ messages in thread
From: crwulff @ 2012-11-11  4:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: Chris Wulff

From: Chris Wulff <crwulff@gmail.com>

Signed-off-by: Chris Wulff <crwulff@gmail.com>
---
 Makefile.objs |    1 +
 nios2-dis.c   | 3478 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 3479 insertions(+)
 create mode 100644 nios2-dis.c

diff --git a/Makefile.objs b/Makefile.objs
index 593a592..2d6db47 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -133,6 +133,7 @@ libdis-$(CONFIG_IA64_DIS) += ia64-dis.o
 libdis-$(CONFIG_M68K_DIS) += m68k-dis.o
 libdis-$(CONFIG_MICROBLAZE_DIS) += microblaze-dis.o
 libdis-$(CONFIG_MIPS_DIS) += mips-dis.o
+libdis-$(CONFIG_NIOS2_DIS) += nios2-dis.o
 libdis-$(CONFIG_PPC_DIS) += ppc-dis.o
 libdis-$(CONFIG_S390_DIS) += s390-dis.o
 libdis-$(CONFIG_SH4_DIS) += sh4-dis.o
diff --git a/nios2-dis.c b/nios2-dis.c
new file mode 100644
index 0000000..1b4c06c
--- /dev/null
+++ b/nios2-dis.c
@@ -0,0 +1,3478 @@
+/*
+ * These files from binutils are concatenated:
+ * nios2.h, nios2-isa.h, nios2-opc.c, nios2-dis.c
+ */
+
+/* nios2.h.  Altera New Jersey opcode list for GAS, the GNU assembler.
+
+   Copyright (C) 2003
+   by Nigel Gray (ngray@altera.com).
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+1, or (at your option) any later version.
+
+GDB, GAS, and the GNU binutils are distributed in the hope that they
+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 file; see the file COPYING.  If not,
+see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _NIOS2_H_
+#define _NIOS2_H_
+
+
+/****************************************************************************
+ * This file contains structures, bit masks and shift counts used
+ * by the GNU toolchain to define the New Jersey instruction set and
+ * access various opcode fields.
+ ****************************************************************************/
+
+enum overflow_type {
+    call_target_overflow = 0,
+    branch_target_overflow,
+    address_offset_overflow,
+    signed_immed16_overflow,
+    unsigned_immed16_overflow,
+    unsigned_immed5_overflow,
+    custom_opcode_overflow,
+    no_overflow
+};
+
+/*---------------------------------------------------------------------------
+   This structure holds information for a particular instruction
+  ---------------------------------------------------------------------------*/
+
+/* match When assembling, this
+     opcode is modified by the arguments to produce the actual opcode
+     that is used.  If pinfo is INSN_MACRO, then this is 0.  */
+
+/* mask If pinfo is not INSN_MACRO, then this is a bit mask for the
+     relevant portions of the opcode when disassembling.  If the
+     actual opcode anded with the match field equals the opcode field,
+     then we have found the correct instruction.  If pinfo is
+     INSN_MACRO, then this field is the macro identifier.  */
+
+/* For a macro, this is INSN_MACRO.  Otherwise, it is a collection
+     of bits describing the instruction, notably any relevant hazard
+     information.  */
+
+struct nios2_opcode {
+    const char *name;                /* The name of the instruction.  */
+    const char *args;                /* A string describing the arguments
+                                        for this instruction.  */
+    const char *args_test;           /* Like args, but with an extra argument
+                                        for the expected opcode */
+    unsigned long num_args;          /* the number of arguments the instruction
+                                        takes */
+    unsigned long match;             /* The basic opcode for the instruction. */
+    unsigned long mask;              /* mask for the opcode field of the
+                                        instruction */
+    unsigned long pinfo;             /* is this a real instruction or
+                                        instruction macro */
+    enum overflow_type overflow_msg; /* msg template used to generate
+                                        informative message when fixup
+                                        overflows */
+};
+
+/* This value is used in the nios2_opcode.pinfo field to indicate that the
+   instruction is a macro or pseudo-op. This requires special treatment by
+   the assembler, and is used by the disassembler to determine whether to
+   check for a nop */
+#define NIOS2_INSN_MACRO        0x80000000
+#define NIOS2_INSN_MACRO_MOV    0x80000001
+#define NIOS2_INSN_MACRO_MOVI   0x80000002
+#define NIOS2_INSN_MACRO_MOVIA  0x80000004
+
+#define NIOS2_INSN_RELAXABLE    0x40000000
+#define NIOS2_INSN_UBRANCH      0x00000010
+#define NIOS2_INSN_CBRANCH      0x00000020
+#define NIOS2_INSN_CALL         0x00000040
+
+#define NIOS2_INSN_ADDI         0x00000080
+#define NIOS2_INSN_ANDI         0x00000100
+#define NIOS2_INSN_ORI          0x00000200
+#define NIOS2_INSN_XORI         0x00000400
+
+
+
+/* Associates a register name ($6) with a 5-bit index (eg 6) */
+struct nios2_reg {
+    const char *name;
+    const int index;
+};
+
+
+/* -------------------------------------------------------------------------
+    Bitfield masks for New Jersey instructions
+   -------------------------------------------------------------------------*/
+
+/* These are bit masks and shift counts to use to access the various
+   fields of an instruction. */
+
+/* Macros for getting and setting an instruction field */
+#define GET_INSN_FIELD(X, i)     (((i) & OP_MASK_##X) >> OP_SH_##X)
+#define SET_INSN_FIELD(X, i, j)  ((i) = ((i) & ~(OP_MASK_##X)) | \
+                                        ((j) << OP_SH_##X))
+
+
+/*
+   We include the auto-generated file nios2-isa.h and define the mask
+   and shifts below in terms of those in nios2-isa.h. This ensures
+   that the binutils and hardware are always in sync
+*/
+
+/*#include "nios2-isa.h"*/
+
+#define OP_MASK_OP              (IW_OP_MASK << IW_OP_LSB)
+#define OP_SH_OP                IW_OP_LSB
+
+
+/* Masks and shifts for I-type instructions */
+
+#define OP_MASK_IOP             (IW_OP_MASK << IW_OP_LSB)
+#define OP_SH_IOP               IW_OP_LSB
+
+#define OP_MASK_IMM16           (IW_IMM16_MASK << IW_IMM16_LSB)
+#define OP_SH_IMM16             IW_IMM16_LSB
+
+#define OP_MASK_IRD             (IW_B_MASK << IW_B_LSB)
+#define OP_SH_IRD               IW_B_LSB
+
+#define OP_MASK_IRT             (IW_B_MASK << IW_B_LSB)
+#define OP_SH_IRT               IW_B_LSB
+
+#define OP_MASK_IRS             (IW_A_MASK << IW_A_LSB)
+#define OP_SH_IRS               IW_A_LSB
+
+/* Masks and shifts for R-type instructions */
+
+#define OP_MASK_ROP             (IW_OP_MASK << IW_OP_LSB)
+#define OP_SH_ROP               IW_OP_LSB
+
+#define OP_MASK_ROPX            (IW_OPX_MASK << IW_OPX_LSB)
+#define OP_SH_ROPX              IW_OPX_LSB
+
+#define OP_MASK_RRD             (IW_C_MASK << IW_C_LSB)
+#define OP_SH_RRD               IW_C_LSB
+
+#define OP_MASK_RRT             (IW_B_MASK << IW_B_LSB)
+#define OP_SH_RRT               IW_B_LSB
+
+#define OP_MASK_RRS             (IW_A_MASK << IW_A_LSB)
+#define OP_SH_RRS               IW_A_LSB
+
+/* Masks and shifts for J-type instructions */
+
+#define OP_MASK_JOP             (IW_OP_MASK << IW_OP_LSB)
+#define OP_SH_JOP               IW_OP_LSB
+
+#define OP_MASK_IMM26           (IW_IMM26_MASK << IW_IMM26_LSB)
+#define OP_SH_IMM26             IW_IMM26_LSB
+
+/* Masks and shifts for CTL instructions */
+
+#define OP_MASK_RCTL    0x000007c0
+#define OP_SH_RCTL              6
+
+/* break instruction imm5 field */
+#define OP_MASK_TRAP_IMM5 0x000007c0
+#define OP_SH_TRAP_IMM5   6
+
+/* instruction imm5 field */
+#define OP_MASK_IMM5            (IW_SHIFT_IMM5_MASK << IW_SHIFT_IMM5_LSB)
+#define OP_SH_IMM5              IW_SHIFT_IMM5_LSB
+
+/* cache operation fields (type j,i(s)) */
+#define OP_MASK_CACHE_OPX       (IW_B_MASK << IW_B_LSB)
+#define OP_SH_CACHE_OPX         IW_B_LSB
+#define OP_MASK_CACHE_RRS       (IW_A_MASK << IW_A_LSB)
+#define OP_SH_CACHE_RRS         IW_A_LSB
+
+/* custom instruction masks */
+#define OP_MASK_CUSTOM_A                0x00010000
+#define OP_SH_CUSTOM_A                          16
+
+#define OP_MASK_CUSTOM_B                0x00008000
+#define OP_SH_CUSTOM_B                          15
+
+#define OP_MASK_CUSTOM_C                0x00004000
+#define OP_SH_CUSTOM_C                          14
+
+#define OP_MASK_CUSTOM_N                0x00003fc0
+#define OP_SH_CUSTOM_N                           6
+#define OP_MAX_CUSTOM_N                        255
+
+/*
+       The following macros define the opcode matches for each
+       instruction
+       code & OP_MASK_INST == OP_MATCH_INST
+ */
+
+/* OP instruction matches */
+#define OP_MATCH_ADDI           OP_ADDI
+#define OP_MATCH_ANDHI          OP_ANDHI
+#define OP_MATCH_ANDI           OP_ANDI
+#define OP_MATCH_BEQ            OP_BEQ
+#define OP_MATCH_BGE            OP_BGE
+#define OP_MATCH_BGEU           OP_BGEU
+#define OP_MATCH_BLT            OP_BLT
+#define OP_MATCH_BLTU           OP_BLTU
+#define OP_MATCH_BNE            OP_BNE
+#define OP_MATCH_BR             OP_BR
+#define OP_MATCH_FLUSHD         OP_FLUSHD
+#define OP_MATCH_FLUSHDA        OP_FLUSHDA
+#define OP_MATCH_INITD          OP_INITD
+#define OP_MATCH_INITDA         OP_INITDA
+#define OP_MATCH_CALL           OP_CALL
+#define OP_MATCH_CMPEQI         OP_CMPEQI
+#define OP_MATCH_CMPGEI         OP_CMPGEI
+#define OP_MATCH_CMPGEUI        OP_CMPGEUI
+#define OP_MATCH_CMPLTI         OP_CMPLTI
+#define OP_MATCH_CMPLTUI        OP_CMPLTUI
+#define OP_MATCH_CMPNEI         OP_CMPNEI
+#define OP_MATCH_JMPI           OP_JMPI
+#define OP_MATCH_LDB            OP_LDB
+#define OP_MATCH_LDBIO          OP_LDBIO
+#define OP_MATCH_LDBU           OP_LDBU
+#define OP_MATCH_LDBUIO         OP_LDBUIO
+#define OP_MATCH_LDH            OP_LDH
+#define OP_MATCH_LDHIO          OP_LDHIO
+#define OP_MATCH_LDHU           OP_LDHU
+#define OP_MATCH_LDHUIO         OP_LDHUIO
+#define OP_MATCH_LDL            OP_LDL
+#define OP_MATCH_LDW            OP_LDW
+#define OP_MATCH_LDWIO          OP_LDWIO
+#define OP_MATCH_MULI           OP_MULI
+#define OP_MATCH_OPX            OP_OPX
+#define OP_MATCH_ORHI           OP_ORHI
+#define OP_MATCH_ORI            OP_ORI
+#define OP_MATCH_STB            OP_STB
+#define OP_MATCH_STBIO          OP_STBIO
+#define OP_MATCH_STC            OP_STC
+#define OP_MATCH_STH            OP_STH
+#define OP_MATCH_STHIO          OP_STHIO
+#define OP_MATCH_STW            OP_STW
+#define OP_MATCH_STWIO          OP_STWIO
+#define OP_MATCH_CUSTOM         OP_CUSTOM
+#define OP_MATCH_XORHI          OP_XORHI
+#define OP_MATCH_XORI           OP_XORI
+#define OP_MATCH_OPX            OP_OPX
+
+
+
+/* OPX instruction values */
+#define OP_MATCH_ADD    ((OPX_ADD << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_AND    ((OPX_AND << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_BREAK  ((0x1e << 17) | (OPX_BREAK << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_BRET   ((0xf0000000) | (OPX_BRET << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_CALLR  ((0x1f << 17) | (OPX_CALLR << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_CMPEQ  ((OPX_CMPEQ << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_CMPGE  ((OPX_CMPGE << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_CMPGEU ((OPX_CMPGEU << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_CMPLT  ((OPX_CMPLT << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_CMPLTU ((OPX_CMPLTU << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_CMPNE  ((OPX_CMPNE << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_DIV    ((OPX_DIV << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_DIVU   ((OPX_DIVU << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_JMP    ((OPX_JMP << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_MUL    ((OPX_MUL << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_MULXSS ((OPX_MULXSS << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_MULXSU ((OPX_MULXSU << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_MULXUU ((OPX_MULXUU << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_NEXTPC ((OPX_NEXTPC << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_NOR    ((OPX_NOR << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_OR     ((OPX_OR << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_RDCTL  ((OPX_RDCTL << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_RET    ((0xf8000000) | (OPX_RET << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_ROL    ((OPX_ROL << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_ROLI   ((OPX_ROLI << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_ROR    ((OPX_ROR << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_SLL    ((OPX_SLL << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_SLLI   ((OPX_SLLI << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_SRA    ((OPX_SRA << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_SRAI   ((OPX_SRAI << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_SRL    ((OPX_SRL << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_SRLI   ((OPX_SRLI << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_SUB    ((OPX_SUB << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_SYNC   ((OPX_SYNC << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_TRAP   ((0x1d << 17) | (OPX_TRAP << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_ERET   ((0xe8000000) | (OPX_ERET << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_WRCTL  ((OPX_WRCTL << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_XOR    ((OPX_XOR << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_FLUSHI ((OPX_FLUSHI << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_FLUSHP ((OPX_FLUSHP << IW_OPX_LSB) | (OP_OPX))
+#define OP_MATCH_INITI  ((OPX_INITI << IW_OPX_LSB) | (OP_OPX))
+
+/*
+       Some unusual op masks
+*/
+#define OP_MASK_BREAK  ((OP_MASK_RRS | OP_MASK_RRT | OP_MASK_RRD | \
+                         OP_MASK_ROPX | OP_MASK_OP) & 0xfffff03f)
+#define OP_MASK_CALLR  ((OP_MASK_RRT | OP_MASK_RRD | OP_MASK_ROPX | OP_MASK_OP))
+#define OP_MASK_JMP    ((OP_MASK_RRT | OP_MASK_RRD | OP_MASK_ROPX | OP_MASK_OP))
+#define OP_MASK_SYNC   ((OP_MASK_RRT | OP_MASK_RRD | OP_MASK_ROPX | OP_MASK_OP))
+#define OP_MASK_TRAP   ((OP_MASK_RRS | OP_MASK_RRT | OP_MASK_RRD | \
+                         OP_MASK_ROPX | OP_MASK_OP) & 0xfffff83f)
+#define OP_MASK_WRCTL  ((OP_MASK_RRT | OP_MASK_RRD | OP_MASK_ROPX | OP_MASK_OP))
+#define OP_MASK_NEXTPC ((OP_MASK_RRS | OP_MASK_RRT | OP_MASK_ROPX | OP_MASK_OP))
+#define OP_MASK_FLUSHI ((OP_MASK_RRT | OP_MASK_RRD | OP_MASK_ROPX | OP_MASK_OP))
+#define OP_MASK_INITI  ((OP_MASK_RRT | OP_MASK_RRD | OP_MASK_ROPX | OP_MASK_OP))
+
+#define OP_MASK_ROLI   ((OP_MASK_RRT | OP_MASK_ROPX | OP_MASK_OP))
+#define OP_MASK_SLLI   ((OP_MASK_RRT | OP_MASK_ROPX | OP_MASK_OP))
+#define OP_MASK_SRAI   ((OP_MASK_RRT | OP_MASK_ROPX | OP_MASK_OP))
+#define OP_MASK_SRLI   ((OP_MASK_RRT | OP_MASK_ROPX | OP_MASK_OP))
+#define OP_MASK_RDCTL  ((OP_MASK_RRS | OP_MASK_RRT | OP_MASK_ROPX | OP_MASK_OP))
+
+#ifndef OP_MASK
+#define OP_MASK                         0xffffffff
+#endif
+
+/* These are the data structures we use to hold the instruction information */
+
+extern const struct nios2_opcode nios2_builtin_opcodes[];
+extern const int bfd_nios2_num_builtin_opcodes;
+extern struct nios2_opcode *nios2_opcodes;
+extern int bfd_nios2_num_opcodes;
+
+/* These are the data structures used to hold the register information */
+extern const struct nios2_reg nios2_builtin_regs[];
+extern struct nios2_reg *nios2_regs;
+extern const int nios2_num_builtin_regs;
+extern int nios2_num_regs;
+
+/* Machine-independent macro for number of opcodes */
+
+#define NUMOPCODES bfd_nios2_num_opcodes
+#define NUMREGISTERS nios2_num_regs;
+
+/* these are used in disassembly to get the correct register names */
+#define NUMREGNAMES 32
+#define NUMCTLREGNAMES 32
+#define CTLREGBASE     42
+#define COPROCREGBASE  83
+#define NUMCOPROCREGNAMES 32
+
+
+/* this is made extern so that the assembler can use it to find out
+   what instruction caused an error */
+extern const struct nios2_opcode *nios2_find_opcode_hash(unsigned long);
+
+/* overflow message strings used in the assembler */
+extern const char *overflow_msgs[];
+
+#endif /* _NIOS2_H */
+/*
+ * This file defines Nios II instruction set constants.
+ * To include it in assembly code (.S file), define ALT_ASM_SRC
+ * before including this file.
+ *
+ * This file is automatically generated by gen_isa.pl - do not edit
+ */
+
+#ifndef _NIOS2_ISA_H_
+#define _NIOS2_ISA_H_
+
+/* OP instruction opcode values (index is OP field) */
+#define NUM_OP_INSTS 64
+
+#ifndef ALT_ASM_SRC
+extern const char *op_names[NUM_OP_INSTS];
+#endif /* ALT_ASM_SRC */
+
+/* OPX instruction opcode values (index is OPX field) */
+#define NUM_OPX_INSTS 64
+
+#ifndef ALT_ASM_SRC
+extern const char *opx_names[NUM_OPX_INSTS];
+#endif /* ALT_ASM_SRC */
+
+/* Constants for instruction fields and ISA */
+#define BREAK_INST_EXC_ID 7
+#define CPU_RESET_CAUSE_ID 1
+#define CPU_RESET_EXC_ID 1
+#define DIV_ERROR_CAUSE_ID 8
+#define DIV_ERROR_EXC_ID 10
+#define EMPTY_SLAVE_DATA_ACCESS_ERROR_CAUSE_ID 30
+#define EMPTY_SLAVE_DATA_ACCESS_ERROR_EXC_ID 22
+#define EMPTY_SLAVE_INST_ACCESS_ERROR_CAUSE_ID 29
+#define EMPTY_SLAVE_INST_ACCESS_ERROR_EXC_ID 21
+#define HBREAK_EXC_ID 2
+#define ILLEGAL_INST_CAUSE_ID 5
+#define ILLEGAL_INST_EXC_ID 6
+#define MAX_CAUSE_ID 31
+#define MISALIGNED_DATA_ADDR_CAUSE_ID 6
+#define MISALIGNED_DATA_ADDR_EXC_ID 8
+#define MISALIGNED_TARGET_PC_CAUSE_ID 7
+#define MISALIGNED_TARGET_PC_EXC_ID 9
+#define MPU_DATA_REGION_VIOLATION_CAUSE_ID 17
+#define MPU_DATA_REGION_VIOLATION_EXC_ID 20
+#define MPU_INST_REGION_VIOLATION_CAUSE_ID 16
+#define MPU_INST_REGION_VIOLATION_EXC_ID 19
+#define NIOS2_DISPLAY_INST_TRACE 1
+#define NIOS2_DISPLAY_MEM_TRAFFIC 2
+#define NONE_EXC_ID 0
+#define NORM_INTR_CAUSE_ID 2
+#define NORM_INTR_EXC_ID 3
+#define NUM_EXC_IDS 24
+#define READONLY_SLAVE_DATA_ACCESS_ERROR_CAUSE_ID 31
+#define READONLY_SLAVE_DATA_ACCESS_ERROR_EXC_ID 23
+#define RECORD_DATA_ADDR 2
+#define RECORD_NOTHING 0
+#define RECORD_TARGET_PCB 1
+#define RESET_CAUSE_ID 0
+#define SUPERVISOR_DATA_ADDR_CAUSE_ID 11
+#define SUPERVISOR_DATA_ADDR_EXC_ID 13
+#define SUPERVISOR_INST_ADDR_CAUSE_ID 9
+#define SUPERVISOR_INST_ADDR_EXC_ID 11
+#define SUPERVISOR_INST_CAUSE_ID 10
+#define SUPERVISOR_INST_EXC_ID 12
+#define TLB_DATA_MISS_EXC_ID 15
+#define TLB_INST_MISS_EXC_ID 14
+#define TLB_MISS_CAUSE_ID 12
+#define TLB_R_PERM_CAUSE_ID 14
+#define TLB_R_PERM_EXC_ID 17
+#define TLB_W_PERM_CAUSE_ID 15
+#define TLB_W_PERM_EXC_ID 18
+#define TLB_X_PERM_CAUSE_ID 13
+#define TLB_X_PERM_EXC_ID 16
+#define TRAP_INST_CAUSE_ID 3
+#define TRAP_INST_EXC_ID 4
+#define UNIMP_INST_CAUSE_ID 4
+#define UNIMP_INST_EXC_ID 5
+#define AT_REGNUM 1
+#define BADADDR_REG_BADDR_LSB 0
+#define BADADDR_REG_BADDR_MSB 31
+#define BADADDR_REG_BADDR_SZ 32
+#define BADADDR_REG_BADDR_MASK 0xffffffff
+#define BADADDR_REG_LSB 0
+#define BADADDR_REG_MSB 31
+#define BADADDR_REG_REGNUM 12
+#define BADADDR_REG_SZ 32
+#define BADADDR_REG_MASK 0xffffffff
+#define BRETADDR_REGNUM 30
+#define BSTATUS_REG_LSB 0
+#define BSTATUS_REG_MMU_LSB 0
+#define BSTATUS_REG_MMU_MSB 2
+#define BSTATUS_REG_MMU_SZ 3
+#define BSTATUS_REG_MMU_MASK 0x7
+#define BSTATUS_REG_MPU_LSB 0
+#define BSTATUS_REG_MPU_MSB 1
+#define BSTATUS_REG_MPU_SZ 2
+#define BSTATUS_REG_MPU_MASK 0x3
+#define BSTATUS_REG_MSB 2
+#define BSTATUS_REG_NO_MMU_LSB 0
+#define BSTATUS_REG_NO_MMU_MSB 0
+#define BSTATUS_REG_NO_MMU_SZ 1
+#define BSTATUS_REG_NO_MMU_MASK 0x1
+#define BSTATUS_REG_REGNUM 2
+#define BSTATUS_REG_SZ 3
+#define BSTATUS_REG_MASK 0x7
+#define BT_REGNUM 25
+#define CACHE_MAX_BYTES 65536
+#define CACHE_MAX_LINE_BYTES 32
+#define CACHE_MIN_LINE_BYTES 4
+#define COMPARE_OP_EQ 0x0
+#define COMPARE_OP_GE 0x1
+#define COMPARE_OP_LSB 3
+#define COMPARE_OP_LT 0x2
+#define COMPARE_OP_MSB 4
+#define COMPARE_OP_NE 0x3
+#define COMPARE_OP_SZ 2
+#define COMPARE_OP_MASK 0x3
+#define CONFIG_REG_LSB 0
+#define CONFIG_REG_MSB 0
+#define CONFIG_REG_PE_LSB 0
+#define CONFIG_REG_PE_MSB 0
+#define CONFIG_REG_PE_SZ 1
+#define CONFIG_REG_PE_MASK 0x1
+#define CONFIG_REG_REGNUM 13
+#define CONFIG_REG_SZ 1
+#define CONFIG_REG_MASK 0x1
+#define CPUID_REG_LSB 0
+#define CPUID_REG_MSB 31
+#define CPUID_REG_REGNUM 5
+#define CPUID_REG_SZ 32
+#define CPUID_REG_MASK 0xffffffff
+#define DATAPATH_LOG2_SZ 5
+#define DATAPATH_LOG2_MASK 0x1f
+#define DATAPATH_LSB 0
+#define DATAPATH_MSB 31
+#define DATAPATH_SZ 32
+#define DATAPATH_MASK 0xffffffff
+#define EMPTY_CRST_IW 127034
+#define EMPTY_HBREAK_IW 4040762
+#define EMPTY_INTR_IW 3926074
+#define EMPTY_NOP_IW 100410
+#define EMPTY_RET_IW 4160759866
+#define ERETADDR_REGNUM 29
+#define ESTATUS_REG_LSB 0
+#define ESTATUS_REG_MMU_LSB 0
+#define ESTATUS_REG_MMU_MSB 2
+#define ESTATUS_REG_MMU_SZ 3
+#define ESTATUS_REG_MMU_MASK 0x7
+#define ESTATUS_REG_MPU_LSB 0
+#define ESTATUS_REG_MPU_MSB 1
+#define ESTATUS_REG_MPU_SZ 2
+#define ESTATUS_REG_MPU_MASK 0x3
+#define ESTATUS_REG_MSB 2
+#define ESTATUS_REG_NO_MMU_LSB 0
+#define ESTATUS_REG_NO_MMU_MSB 0
+#define ESTATUS_REG_NO_MMU_SZ 1
+#define ESTATUS_REG_NO_MMU_MASK 0x1
+#define ESTATUS_REG_REGNUM 1
+#define ESTATUS_REG_SZ 3
+#define ESTATUS_REG_MASK 0x7
+#define ET_REGNUM 24
+#define EXCEPTION_REG_CAUSE_LSB 2
+#define EXCEPTION_REG_CAUSE_MSB 6
+#define EXCEPTION_REG_CAUSE_SZ 5
+#define EXCEPTION_REG_CAUSE_MASK 0x1f
+#define EXCEPTION_REG_LSB 0
+#define EXCEPTION_REG_MEA_LSB 0
+#define EXCEPTION_REG_MEA_MSB 0
+#define EXCEPTION_REG_MEA_SZ 1
+#define EXCEPTION_REG_MEA_MASK 0x1
+#define EXCEPTION_REG_MEE_LSB 1
+#define EXCEPTION_REG_MEE_MSB 1
+#define EXCEPTION_REG_MEE_SZ 1
+#define EXCEPTION_REG_MEE_MASK 0x1
+#define EXCEPTION_REG_MSB 6
+#define EXCEPTION_REG_REGNUM 7
+#define EXCEPTION_REG_SZ 7
+#define EXCEPTION_REG_MASK 0x7f
+#define FP_REGNUM 28
+#define FSTATUS_REG_REGNUM 11
+#define GP_REGNUM 26
+#define IENABLE_REG_LSB 0
+#define IENABLE_REG_MSB 31
+#define IENABLE_REG_REGNUM 3
+#define IENABLE_REG_SZ 32
+#define IENABLE_REG_MASK 0xffffffff
+#define IPENDING_REG_LSB 0
+#define IPENDING_REG_MSB 31
+#define IPENDING_REG_REGNUM 4
+#define IPENDING_REG_SZ 32
+#define IPENDING_REG_MASK 0xffffffff
+#define IW_A_LSB 27
+#define IW_A_MSB 31
+#define IW_A_SZ 5
+#define IW_A_MASK 0x1f
+#define IW_B_LSB 22
+#define IW_B_MSB 26
+#define IW_B_SZ 5
+#define IW_B_MASK 0x1f
+#define IW_C_LSB 17
+#define IW_C_MSB 21
+#define IW_C_SZ 5
+#define IW_C_MASK 0x1f
+#define IW_CONTROL_REGNUM_BASE 0
+#define IW_CONTROL_REGNUM_LSB 6
+#define IW_CONTROL_REGNUM_MSB 9
+#define IW_CONTROL_REGNUM_SZ 4
+#define IW_CONTROL_REGNUM_MASK 0xf
+#define IW_CUSTOM_N_LSB 6
+#define IW_CUSTOM_N_MSB 13
+#define IW_CUSTOM_N_SZ 8
+#define IW_CUSTOM_N_MASK 0xff
+#define IW_CUSTOM_READRA_LSB 16
+#define IW_CUSTOM_READRA_MSB 16
+#define IW_CUSTOM_READRA_SZ 1
+#define IW_CUSTOM_READRA_MASK 0x1
+#define IW_CUSTOM_READRB_LSB 15
+#define IW_CUSTOM_READRB_MSB 15
+#define IW_CUSTOM_READRB_SZ 1
+#define IW_CUSTOM_READRB_MASK 0x1
+#define IW_CUSTOM_WRITERC_LSB 14
+#define IW_CUSTOM_WRITERC_MSB 14
+#define IW_CUSTOM_WRITERC_SZ 1
+#define IW_CUSTOM_WRITERC_MASK 0x1
+#define IW_IMM16_LSB 6
+#define IW_IMM16_MSB 21
+#define IW_IMM16_SZ 16
+#define IW_IMM16_MASK 0xffff
+#define IW_IMM26_LSB 6
+#define IW_IMM26_MSB 31
+#define IW_IMM26_SZ 26
+#define IW_IMM26_MASK 0x3ffffff
+#define IW_MEMSZ_BYTE 0x0
+#define IW_MEMSZ_HWORD 0x1
+#define IW_MEMSZ_LSB 3
+#define IW_MEMSZ_MSB 4
+#define IW_MEMSZ_SZ 2
+#define IW_MEMSZ_MASK 0x3
+#define IW_MEMSZ_WORD_MSB 0x1
+#define IW_OP_LSB 0
+#define IW_OP_MSB 5
+#define IW_OP_SZ 6
+#define IW_OP_MASK 0x3f
+#define IW_OPX_LSB 11
+#define IW_OPX_MSB 16
+#define IW_OPX_SZ 6
+#define IW_OPX_MASK 0x3f
+#define IW_SHIFT_IMM5_LSB 6
+#define IW_SHIFT_IMM5_MSB 10
+#define IW_SHIFT_IMM5_SZ 5
+#define IW_SHIFT_IMM5_MASK 0x1f
+#define IW_SZ 32
+#define IW_MASK 0xffffffff
+#define IW_TRAP_BREAK_IMM5_LSB 6
+#define IW_TRAP_BREAK_IMM5_MSB 10
+#define IW_TRAP_BREAK_IMM5_SZ 5
+#define IW_TRAP_BREAK_IMM5_MASK 0x1f
+#define JMP_CALLR_VS_RET_IS_RET 0
+#define JMP_CALLR_VS_RET_OPX_BIT 3
+#define LOGIC_OP_AND 0x1
+#define LOGIC_OP_LSB 3
+#define LOGIC_OP_MSB 4
+#define LOGIC_OP_NOR 0x0
+#define LOGIC_OP_OR 0x2
+#define LOGIC_OP_SZ 2
+#define LOGIC_OP_MASK 0x3
+#define LOGIC_OP_XOR 0x3
+#define MMU_ADDR_BYPASS_TLB 0x3
+#define MMU_ADDR_BYPASS_TLB_CACHEABLE 0x0
+#define MMU_ADDR_BYPASS_TLB_CACHEABLE_LSB 29
+#define MMU_ADDR_BYPASS_TLB_CACHEABLE_MSB 29
+#define MMU_ADDR_BYPASS_TLB_CACHEABLE_SZ 1
+#define MMU_ADDR_BYPASS_TLB_CACHEABLE_MASK 0x1
+#define MMU_ADDR_BYPASS_TLB_LSB 30
+#define MMU_ADDR_BYPASS_TLB_MSB 31
+#define MMU_ADDR_BYPASS_TLB_PADDR_LSB 0
+#define MMU_ADDR_BYPASS_TLB_PADDR_MSB 28
+#define MMU_ADDR_BYPASS_TLB_PADDR_SZ 29
+#define MMU_ADDR_BYPASS_TLB_PADDR_MASK 0x1fffffff
+#define MMU_ADDR_BYPASS_TLB_SZ 2
+#define MMU_ADDR_BYPASS_TLB_MASK 0x3
+#define MMU_ADDR_IO_REGION 0x7
+#define MMU_ADDR_IO_REGION_LSB 29
+#define MMU_ADDR_IO_REGION_MSB 31
+#define MMU_ADDR_IO_REGION_SZ 3
+#define MMU_ADDR_IO_REGION_MASK 0x7
+#define MMU_ADDR_IO_REGION_VPN 0xe0000
+#define MMU_ADDR_KERNEL_MMU_REGION 0x2
+#define MMU_ADDR_KERNEL_MMU_REGION_LSB 30
+#define MMU_ADDR_KERNEL_MMU_REGION_MSB 31
+#define MMU_ADDR_KERNEL_MMU_REGION_SZ 2
+#define MMU_ADDR_KERNEL_MMU_REGION_MASK 0x3
+#define MMU_ADDR_KERNEL_REGION 0x6
+#define MMU_ADDR_KERNEL_REGION_INT 6
+#define MMU_ADDR_KERNEL_REGION_LSB 29
+#define MMU_ADDR_KERNEL_REGION_MSB 31
+#define MMU_ADDR_KERNEL_REGION_SZ 3
+#define MMU_ADDR_KERNEL_REGION_MASK 0x7
+#define MMU_ADDR_PAGE_OFFSET_LSB 0
+#define MMU_ADDR_PAGE_OFFSET_MSB 11
+#define MMU_ADDR_PAGE_OFFSET_SZ 12
+#define MMU_ADDR_PAGE_OFFSET_MASK 0xfff
+#define MMU_ADDR_PFN_LSB 12
+#define MMU_ADDR_PFN_MSB 31
+#define MMU_ADDR_PFN_SZ 20
+#define MMU_ADDR_PFN_MASK 0xfffff
+#define MMU_ADDR_USER_REGION 0x0
+#define MMU_ADDR_USER_REGION_LSB 31
+#define MMU_ADDR_USER_REGION_MSB 31
+#define MMU_ADDR_USER_REGION_SZ 1
+#define MMU_ADDR_USER_REGION_MASK 0x1
+#define MMU_ADDR_VPN_LSB 12
+#define MMU_ADDR_VPN_MSB 31
+#define MMU_ADDR_VPN_SZ 20
+#define MMU_ADDR_VPN_MASK 0xfffff
+#define MPU_DATA_PERM_SUPER_NONE_USER_NONE 0
+#define MPU_DATA_PERM_SUPER_RD_USER_NONE 1
+#define MPU_DATA_PERM_SUPER_RD_USER_RD 2
+#define MPU_DATA_PERM_SUPER_RW_USER_NONE 4
+#define MPU_DATA_PERM_SUPER_RW_USER_RD 5
+#define MPU_DATA_PERM_SUPER_RW_USER_RW 6
+#define MPU_DATA_PERM_SZ 3
+#define MPU_DATA_PERM_MASK 0x7
+#define MPU_INST_PERM_SUPER_EXEC_USER_EXEC 2
+#define MPU_INST_PERM_SUPER_EXEC_USER_NONE 1
+#define MPU_INST_PERM_SUPER_NONE_USER_NONE 0
+#define MPU_INST_PERM_SZ 2
+#define MPU_INST_PERM_MASK 0x3
+#define MPU_MAX_REGION_SIZE_LOG2 20
+#define MPU_MAX_REGIONS 32
+#define MPU_MIN_REGION_SIZE_LOG2 6
+#define MPU_MIN_REGIONS 1
+#define MPUACC_REG_C_LSB 5
+#define MPUACC_REG_C_MSB 5
+#define MPUACC_REG_C_SZ 1
+#define MPUACC_REG_C_MASK 0x1
+#define MPUACC_REG_LIMIT_LSB 6
+#define MPUACC_REG_LIMIT_MSB 31
+#define MPUACC_REG_LIMIT_SZ 26
+#define MPUACC_REG_LIMIT_MASK 0x3ffffff
+#define MPUACC_REG_LSB 0
+#define MPUACC_REG_MASK_LSB 6
+#define MPUACC_REG_MASK_MSB 30
+#define MPUACC_REG_MASK_SZ 25
+#define MPUACC_REG_MASK_MASK 0x1ffffff
+#define MPUACC_REG_MSB 31
+#define MPUACC_REG_PERM_LSB 2
+#define MPUACC_REG_PERM_MSB 4
+#define MPUACC_REG_PERM_SZ 3
+#define MPUACC_REG_PERM_MASK 0x7
+#define MPUACC_REG_RD_LSB 1
+#define MPUACC_REG_RD_MSB 1
+#define MPUACC_REG_RD_SZ 1
+#define MPUACC_REG_RD_MASK 0x1
+#define MPUACC_REG_REGNUM 15
+#define MPUACC_REG_RSV1_LSB 31
+#define MPUACC_REG_RSV1_MSB 31
+#define MPUACC_REG_RSV1_SZ 1
+#define MPUACC_REG_RSV1_MASK 0x1
+#define MPUACC_REG_SZ 32
+#define MPUACC_REG_MASK 0xffffffff
+#define MPUACC_REG_WR_LSB 0
+#define MPUACC_REG_WR_MSB 0
+#define MPUACC_REG_WR_SZ 1
+#define MPUACC_REG_WR_MASK 0x1
+#define MPUBASE_REG_BASE_LSB 6
+#define MPUBASE_REG_BASE_MSB 30
+#define MPUBASE_REG_BASE_SZ 25
+#define MPUBASE_REG_BASE_MASK 0x1ffffff
+#define MPUBASE_REG_D_LSB 0
+#define MPUBASE_REG_D_MSB 0
+#define MPUBASE_REG_D_SZ 1
+#define MPUBASE_REG_D_MASK 0x1
+#define MPUBASE_REG_INDEX_LSB 1
+#define MPUBASE_REG_INDEX_MSB 5
+#define MPUBASE_REG_INDEX_SZ 5
+#define MPUBASE_REG_INDEX_MASK 0x1f
+#define MPUBASE_REG_LSB 0
+#define MPUBASE_REG_MSB 31
+#define MPUBASE_REG_REGNUM 14
+#define MPUBASE_REG_RSV1_LSB 31
+#define MPUBASE_REG_RSV1_MSB 31
+#define MPUBASE_REG_RSV1_SZ 1
+#define MPUBASE_REG_RSV1_MASK 0x1
+#define MPUBASE_REG_SZ 32
+#define MPUBASE_REG_MASK 0xffffffff
+#define PTEADDR_REG_LSB 0
+#define PTEADDR_REG_MSB 31
+#define PTEADDR_REG_PTBASE_LSB 22
+#define PTEADDR_REG_PTBASE_MSB 31
+#define PTEADDR_REG_PTBASE_SZ 10
+#define PTEADDR_REG_PTBASE_MASK 0x3ff
+#define PTEADDR_REG_REGNUM 8
+#define PTEADDR_REG_RSV_LSB 0
+#define PTEADDR_REG_RSV_MSB 1
+#define PTEADDR_REG_RSV_SZ 2
+#define PTEADDR_REG_RSV_MASK 0x3
+#define PTEADDR_REG_SZ 32
+#define PTEADDR_REG_MASK 0xffffffff
+#define PTEADDR_REG_VPN_LSB 2
+#define PTEADDR_REG_VPN_MSB 21
+#define PTEADDR_REG_VPN_SZ 20
+#define PTEADDR_REG_VPN_MASK 0xfffff
+#define REGNUM_SZ 5
+#define REGNUM_MASK 0x1f
+#define RETADDR_REGNUM 31
+#define RF_ADDR_SZ 5
+#define RF_ADDR_MASK 0x1f
+#define RF_NUM_REG 32
+#define SIM_REG_LSB 0
+#define SIM_REG_MSB 2
+#define SIM_REG_PERF_CNT_CLR_LSB 2
+#define SIM_REG_PERF_CNT_CLR_MSB 2
+#define SIM_REG_PERF_CNT_CLR_SZ 1
+#define SIM_REG_PERF_CNT_CLR_MASK 0x1
+#define SIM_REG_PERF_CNT_EN_LSB 1
+#define SIM_REG_PERF_CNT_EN_MSB 1
+#define SIM_REG_PERF_CNT_EN_SZ 1
+#define SIM_REG_PERF_CNT_EN_MASK 0x1
+#define SIM_REG_REGNUM 6
+#define SIM_REG_SHOW_MMU_REGS_LSB 4
+#define SIM_REG_SHOW_MMU_REGS_MSB 4
+#define SIM_REG_SHOW_MMU_REGS_SZ 1
+#define SIM_REG_SHOW_MMU_REGS_MASK 0x1
+#define SIM_REG_SHOW_TLB_LSB 3
+#define SIM_REG_SHOW_TLB_MSB 3
+#define SIM_REG_SHOW_TLB_SZ 1
+#define SIM_REG_SHOW_TLB_MASK 0x1
+#define SIM_REG_STOP_LSB 0
+#define SIM_REG_STOP_MSB 0
+#define SIM_REG_STOP_SZ 1
+#define SIM_REG_STOP_MASK 0x1
+#define SIM_REG_SZ 3
+#define SIM_REG_MASK 0x7
+#define SP_REGNUM 27
+#define STATUS_REG_EH_LSB 2
+#define STATUS_REG_EH_MSB 2
+#define STATUS_REG_EH_SZ 1
+#define STATUS_REG_EH_MASK 0x1
+#define STATUS_REG_LSB 0
+#define STATUS_REG_MMU_LSB 0
+#define STATUS_REG_MMU_MSB 2
+#define STATUS_REG_MMU_RSV_LSB 3
+#define STATUS_REG_MMU_RSV_MSB 31
+#define STATUS_REG_MMU_RSV_SZ 29
+#define STATUS_REG_MMU_RSV_MASK 0x1fffffff
+#define STATUS_REG_MMU_SZ 3
+#define STATUS_REG_MMU_MASK 0x7
+#define STATUS_REG_MPU_LSB 0
+#define STATUS_REG_MPU_MSB 1
+#define STATUS_REG_MPU_RSV_LSB 2
+#define STATUS_REG_MPU_RSV_MSB 31
+#define STATUS_REG_MPU_RSV_SZ 30
+#define STATUS_REG_MPU_RSV_MASK 0x3fffffff
+#define STATUS_REG_MPU_SZ 2
+#define STATUS_REG_MPU_MASK 0x3
+#define STATUS_REG_MSB 2
+#define STATUS_REG_NO_MMU_LSB 0
+#define STATUS_REG_NO_MMU_MSB 0
+#define STATUS_REG_NO_MMU_RSV_LSB 1
+#define STATUS_REG_NO_MMU_RSV_MSB 31
+#define STATUS_REG_NO_MMU_RSV_SZ 31
+#define STATUS_REG_NO_MMU_RSV_MASK 0x7fffffff
+#define STATUS_REG_NO_MMU_SZ 1
+#define STATUS_REG_NO_MMU_MASK 0x1
+#define STATUS_REG_PIE_LSB 0
+#define STATUS_REG_PIE_MSB 0
+#define STATUS_REG_PIE_SZ 1
+#define STATUS_REG_PIE_MASK 0x1
+#define STATUS_REG_REGNUM 0
+#define STATUS_REG_SZ 3
+#define STATUS_REG_MASK 0x7
+#define STATUS_REG_U_LSB 1
+#define STATUS_REG_U_MSB 1
+#define STATUS_REG_U_SZ 1
+#define STATUS_REG_U_MASK 0x1
+#define TLB_MAX_ENTRIES 1024
+#define TLB_MAX_LINES 128
+#define TLB_MAX_PID_SZ 14
+#define TLB_MAX_PID_MASK 0x3fff
+#define TLB_MAX_PTR_SZ 10
+#define TLB_MAX_PTR_MASK 0x3ff
+#define TLB_MAX_WAYS 16
+#define TLB_MIN_PID_SZ 8
+#define TLB_MIN_PID_MASK 0xff
+#define TLB_MIN_PTR_SZ 7
+#define TLB_MIN_PTR_MASK 0x7f
+#define TLB_MIN_WAYS 8
+#define TLBACC_REG_C_LSB 24
+#define TLBACC_REG_C_MSB 24
+#define TLBACC_REG_C_SZ 1
+#define TLBACC_REG_C_MASK 0x1
+#define TLBACC_REG_G_LSB 20
+#define TLBACC_REG_G_MSB 20
+#define TLBACC_REG_G_SZ 1
+#define TLBACC_REG_G_MASK 0x1
+#define TLBACC_REG_IG_LSB 25
+#define TLBACC_REG_IG_MSB 31
+#define TLBACC_REG_IG_SZ 7
+#define TLBACC_REG_IG_MASK 0x7f
+#define TLBACC_REG_LSB 0
+#define TLBACC_REG_MSB 24
+#define TLBACC_REG_PFN_LSB 0
+#define TLBACC_REG_PFN_MSB 19
+#define TLBACC_REG_PFN_SZ 20
+#define TLBACC_REG_PFN_MASK 0xfffff
+#define TLBACC_REG_R_LSB 23
+#define TLBACC_REG_R_MSB 23
+#define TLBACC_REG_R_SZ 1
+#define TLBACC_REG_R_MASK 0x1
+#define TLBACC_REG_REGNUM 9
+#define TLBACC_REG_SZ 25
+#define TLBACC_REG_MASK 0x1ffffff
+#define TLBACC_REG_W_LSB 22
+#define TLBACC_REG_W_MSB 22
+#define TLBACC_REG_W_SZ 1
+#define TLBACC_REG_W_MASK 0x1
+#define TLBACC_REG_X_LSB 21
+#define TLBACC_REG_X_MSB 21
+#define TLBACC_REG_X_SZ 1
+#define TLBACC_REG_X_MASK 0x1
+#define TLBMISC_REG_BAD_LSB 2
+#define TLBMISC_REG_BAD_MSB 2
+#define TLBMISC_REG_BAD_SZ 1
+#define TLBMISC_REG_BAD_MASK 0x1
+#define TLBMISC_REG_D_LSB 0
+#define TLBMISC_REG_D_MSB 0
+#define TLBMISC_REG_D_SZ 1
+#define TLBMISC_REG_D_MASK 0x1
+#define TLBMISC_REG_DBL_LSB 3
+#define TLBMISC_REG_DBL_MSB 3
+#define TLBMISC_REG_DBL_SZ 1
+#define TLBMISC_REG_DBL_MASK 0x1
+#define TLBMISC_REG_LSB 0
+#define TLBMISC_REG_MSB 23
+#define TLBMISC_REG_PERM_LSB 1
+#define TLBMISC_REG_PERM_MSB 1
+#define TLBMISC_REG_PERM_SZ 1
+#define TLBMISC_REG_PERM_MASK 0x1
+#define TLBMISC_REG_PID_LSB 4
+#define TLBMISC_REG_PID_MSB 17
+#define TLBMISC_REG_PID_SZ 14
+#define TLBMISC_REG_PID_MASK 0x3fff
+#define TLBMISC_REG_RD_LSB 19
+#define TLBMISC_REG_RD_MSB 19
+#define TLBMISC_REG_RD_SZ 1
+#define TLBMISC_REG_RD_MASK 0x1
+#define TLBMISC_REG_REGNUM 10
+#define TLBMISC_REG_RSV1_LSB 24
+#define TLBMISC_REG_RSV1_MSB 31
+#define TLBMISC_REG_RSV1_SZ 8
+#define TLBMISC_REG_RSV1_MASK 0xff
+#define TLBMISC_REG_SZ 24
+#define TLBMISC_REG_MASK 0xffffff
+#define TLBMISC_REG_WAY_LSB 20
+#define TLBMISC_REG_WAY_MSB 23
+#define TLBMISC_REG_WAY_SZ 4
+#define TLBMISC_REG_WAY_MASK 0xf
+#define TLBMISC_REG_WE_LSB 18
+#define TLBMISC_REG_WE_MSB 18
+#define TLBMISC_REG_WE_SZ 1
+#define TLBMISC_REG_WE_MASK 0x1
+
+/* Macros to extract instruction fields */
+#define GET_IW_A(Iw) \
+    (((Iw) >> IW_A_LSB) & IW_A_MASK)
+#define SET_IW_A(Iw, Val) \
+    Iw = (((Iw) & (~(IW_A_MASK << IW_A_LSB))) | \
+         (((Val) & IW_A_MASK) << IW_A_LSB))
+#define GET_IW_B(Iw) \
+    (((Iw) >> IW_B_LSB) & IW_B_MASK)
+#define SET_IW_B(Iw, Val) \
+    Iw = (((Iw) & (~(IW_B_MASK << IW_B_LSB))) | \
+         (((Val) & IW_B_MASK) << IW_B_LSB))
+#define GET_IW_C(Iw) \
+    (((Iw) >> IW_C_LSB) & IW_C_MASK)
+#define SET_IW_C(Iw, Val) \
+    Iw = (((Iw) & (~(IW_C_MASK << IW_C_LSB))) | \
+         (((Val) & IW_C_MASK) << IW_C_LSB))
+#define GET_IW_CONTROL_REGNUM(Iw) \
+    (((Iw) >> IW_CONTROL_REGNUM_LSB) & IW_CONTROL_REGNUM_MASK)
+#define SET_IW_CONTROL_REGNUM(Iw, Val) \
+    Iw = (((Iw) & (~(IW_CONTROL_REGNUM_MASK << IW_CONTROL_REGNUM_LSB))) | \
+         (((Val) & IW_CONTROL_REGNUM_MASK) << IW_CONTROL_REGNUM_LSB))
+#define GET_IW_CUSTOM_N(Iw) \
+    (((Iw) >> IW_CUSTOM_N_LSB) & IW_CUSTOM_N_MASK)
+#define SET_IW_CUSTOM_N(Iw, Val) \
+    Iw = (((Iw) & (~(IW_CUSTOM_N_MASK << IW_CUSTOM_N_LSB))) | \
+         (((Val) & IW_CUSTOM_N_MASK) << IW_CUSTOM_N_LSB))
+#define GET_IW_CUSTOM_READRA(Iw) \
+    (((Iw) >> IW_CUSTOM_READRA_LSB) & IW_CUSTOM_READRA_MASK)
+#define SET_IW_CUSTOM_READRA(Iw, Val) \
+    Iw = (((Iw) & (~(IW_CUSTOM_READRA_MASK << IW_CUSTOM_READRA_LSB))) | \
+         (((Val) & IW_CUSTOM_READRA_MASK) << IW_CUSTOM_READRA_LSB))
+#define GET_IW_CUSTOM_READRB(Iw) \
+    (((Iw) >> IW_CUSTOM_READRB_LSB) & IW_CUSTOM_READRB_MASK)
+#define SET_IW_CUSTOM_READRB(Iw, Val) \
+    Iw = (((Iw) & (~(IW_CUSTOM_READRB_MASK << IW_CUSTOM_READRB_LSB))) | \
+         (((Val) & IW_CUSTOM_READRB_MASK) << IW_CUSTOM_READRB_LSB))
+#define GET_IW_CUSTOM_WRITERC(Iw) \
+    (((Iw) >> IW_CUSTOM_WRITERC_LSB) & IW_CUSTOM_WRITERC_MASK)
+#define SET_IW_CUSTOM_WRITERC(Iw, Val) \
+    Iw = (((Iw) & (~(IW_CUSTOM_WRITERC_MASK << IW_CUSTOM_WRITERC_LSB))) | \
+         (((Val) & IW_CUSTOM_WRITERC_MASK) << IW_CUSTOM_WRITERC_LSB))
+#define GET_IW_IMM16(Iw) \
+    (((Iw) >> IW_IMM16_LSB) & IW_IMM16_MASK)
+#define SET_IW_IMM16(Iw, Val) \
+    Iw = (((Iw) & (~(IW_IMM16_MASK << IW_IMM16_LSB))) | \
+         (((Val) & IW_IMM16_MASK) << IW_IMM16_LSB))
+#define GET_IW_IMM26(Iw) \
+    (((Iw) >> IW_IMM26_LSB) & IW_IMM26_MASK)
+#define SET_IW_IMM26(Iw, Val) \
+    Iw = (((Iw) & (~(IW_IMM26_MASK << IW_IMM26_LSB))) | \
+         (((Val) & IW_IMM26_MASK) << IW_IMM26_LSB))
+#define GET_IW_MEMSZ(Iw) \
+    (((Iw) >> IW_MEMSZ_LSB) & IW_MEMSZ_MASK)
+#define SET_IW_MEMSZ(Iw, Val) \
+    Iw = (((Iw) & (~(IW_MEMSZ_MASK << IW_MEMSZ_LSB))) | \
+         (((Val) & IW_MEMSZ_MASK) << IW_MEMSZ_LSB))
+#define GET_IW_OP(Iw) \
+    (((Iw) >> IW_OP_LSB) & IW_OP_MASK)
+#define SET_IW_OP(Iw, Val) \
+    Iw = (((Iw) & (~(IW_OP_MASK << IW_OP_LSB))) | \
+         (((Val) & IW_OP_MASK) << IW_OP_LSB))
+#define GET_IW_OPX(Iw) \
+    (((Iw) >> IW_OPX_LSB) & IW_OPX_MASK)
+#define SET_IW_OPX(Iw, Val) \
+    Iw = (((Iw) & (~(IW_OPX_MASK << IW_OPX_LSB))) | \
+         (((Val) & IW_OPX_MASK) << IW_OPX_LSB))
+#define GET_IW_SHIFT_IMM5(Iw) \
+    (((Iw) >> IW_SHIFT_IMM5_LSB) & IW_SHIFT_IMM5_MASK)
+#define SET_IW_SHIFT_IMM5(Iw, Val) \
+    Iw = (((Iw) & (~(IW_SHIFT_IMM5_MASK << IW_SHIFT_IMM5_LSB))) | \
+         (((Val) & IW_SHIFT_IMM5_MASK) << IW_SHIFT_IMM5_LSB))
+#define GET_IW_TRAP_BREAK_IMM5(Iw) \
+    (((Iw) >> IW_TRAP_BREAK_IMM5_LSB) & IW_TRAP_BREAK_IMM5_MASK)
+#define SET_IW_TRAP_BREAK_IMM5(Iw, Val) \
+    Iw = (((Iw) & (~(IW_TRAP_BREAK_IMM5_MASK << IW_TRAP_BREAK_IMM5_LSB))) | \
+         (((Val) & IW_TRAP_BREAK_IMM5_MASK) << IW_TRAP_BREAK_IMM5_LSB))
+
+/* Macros to extract control register fields */
+#define GET_BADADDR_REG_BADDR(Reg) \
+    (((Reg) >> BADADDR_REG_BADDR_LSB) & BADADDR_REG_BADDR_MASK)
+#define SET_BADADDR_REG_BADDR(Reg, Val) \
+    Reg = (((Reg) & (~(BADADDR_REG_BADDR_MASK << BADADDR_REG_BADDR_LSB))) | \
+         (((Val) & BADADDR_REG_BADDR_MASK) << BADADDR_REG_BADDR_LSB))
+#define GET_BSTATUS_REG_MMU(Reg) \
+    (((Reg) >> BSTATUS_REG_MMU_LSB) & BSTATUS_REG_MMU_MASK)
+#define SET_BSTATUS_REG_MMU(Reg, Val) \
+    Reg = (((Reg) & (~(BSTATUS_REG_MMU_MASK << BSTATUS_REG_MMU_LSB))) | \
+         (((Val) & BSTATUS_REG_MMU_MASK) << BSTATUS_REG_MMU_LSB))
+#define GET_BSTATUS_REG_MPU(Reg) \
+    (((Reg) >> BSTATUS_REG_MPU_LSB) & BSTATUS_REG_MPU_MASK)
+#define SET_BSTATUS_REG_MPU(Reg, Val) \
+    Reg = (((Reg) & (~(BSTATUS_REG_MPU_MASK << BSTATUS_REG_MPU_LSB))) | \
+         (((Val) & BSTATUS_REG_MPU_MASK) << BSTATUS_REG_MPU_LSB))
+#define GET_BSTATUS_REG_NO_MMU(Reg) \
+    (((Reg) >> BSTATUS_REG_NO_MMU_LSB) & BSTATUS_REG_NO_MMU_MASK)
+#define SET_BSTATUS_REG_NO_MMU(Reg, Val) \
+    Reg = (((Reg) & (~(BSTATUS_REG_NO_MMU_MASK << BSTATUS_REG_NO_MMU_LSB))) | \
+         (((Val) & BSTATUS_REG_NO_MMU_MASK) << BSTATUS_REG_NO_MMU_LSB))
+#define GET_CONFIG_REG_PE(Reg) \
+    (((Reg) >> CONFIG_REG_PE_LSB) & CONFIG_REG_PE_MASK)
+#define SET_CONFIG_REG_PE(Reg, Val) \
+    Reg = (((Reg) & (~(CONFIG_REG_PE_MASK << CONFIG_REG_PE_LSB))) | \
+         (((Val) & CONFIG_REG_PE_MASK) << CONFIG_REG_PE_LSB))
+#define GET_ESTATUS_REG_MMU(Reg) \
+    (((Reg) >> ESTATUS_REG_MMU_LSB) & ESTATUS_REG_MMU_MASK)
+#define SET_ESTATUS_REG_MMU(Reg, Val) \
+    Reg = (((Reg) & (~(ESTATUS_REG_MMU_MASK << ESTATUS_REG_MMU_LSB))) | \
+         (((Val) & ESTATUS_REG_MMU_MASK) << ESTATUS_REG_MMU_LSB))
+#define GET_ESTATUS_REG_MPU(Reg) \
+    (((Reg) >> ESTATUS_REG_MPU_LSB) & ESTATUS_REG_MPU_MASK)
+#define SET_ESTATUS_REG_MPU(Reg, Val) \
+    Reg = (((Reg) & (~(ESTATUS_REG_MPU_MASK << ESTATUS_REG_MPU_LSB))) | \
+         (((Val) & ESTATUS_REG_MPU_MASK) << ESTATUS_REG_MPU_LSB))
+#define GET_ESTATUS_REG_NO_MMU(Reg) \
+    (((Reg) >> ESTATUS_REG_NO_MMU_LSB) & ESTATUS_REG_NO_MMU_MASK)
+#define SET_ESTATUS_REG_NO_MMU(Reg, Val) \
+    Reg = (((Reg) & (~(ESTATUS_REG_NO_MMU_MASK << ESTATUS_REG_NO_MMU_LSB))) | \
+         (((Val) & ESTATUS_REG_NO_MMU_MASK) << ESTATUS_REG_NO_MMU_LSB))
+#define GET_EXCEPTION_REG_CAUSE(Reg) \
+    (((Reg) >> EXCEPTION_REG_CAUSE_LSB) & EXCEPTION_REG_CAUSE_MASK)
+#define SET_EXCEPTION_REG_CAUSE(Reg, Val) \
+    Reg = (((Reg) & (~(EXCEPTION_REG_CAUSE_MASK << \
+                       EXCEPTION_REG_CAUSE_LSB))) | \
+         (((Val) & EXCEPTION_REG_CAUSE_MASK) << EXCEPTION_REG_CAUSE_LSB))
+#define GET_EXCEPTION_REG_MEA(Reg) \
+    (((Reg) >> EXCEPTION_REG_MEA_LSB) & EXCEPTION_REG_MEA_MASK)
+#define SET_EXCEPTION_REG_MEA(Reg, Val) \
+    Reg = (((Reg) & (~(EXCEPTION_REG_MEA_MASK << EXCEPTION_REG_MEA_LSB))) | \
+         (((Val) & EXCEPTION_REG_MEA_MASK) << EXCEPTION_REG_MEA_LSB))
+#define GET_EXCEPTION_REG_MEE(Reg) \
+    (((Reg) >> EXCEPTION_REG_MEE_LSB) & EXCEPTION_REG_MEE_MASK)
+#define SET_EXCEPTION_REG_MEE(Reg, Val) \
+    Reg = (((Reg) & (~(EXCEPTION_REG_MEE_MASK << EXCEPTION_REG_MEE_LSB))) | \
+         (((Val) & EXCEPTION_REG_MEE_MASK) << EXCEPTION_REG_MEE_LSB))
+#define GET_MPUACC_REG_C(Reg) \
+    (((Reg) >> MPUACC_REG_C_LSB) & MPUACC_REG_C_MASK)
+#define SET_MPUACC_REG_C(Reg, Val) \
+    Reg = (((Reg) & (~(MPUACC_REG_C_MASK << MPUACC_REG_C_LSB))) | \
+         (((Val) & MPUACC_REG_C_MASK) << MPUACC_REG_C_LSB))
+#define GET_MPUACC_REG_LIMIT(Reg) \
+    (((Reg) >> MPUACC_REG_LIMIT_LSB) & MPUACC_REG_LIMIT_MASK)
+#define SET_MPUACC_REG_LIMIT(Reg, Val) \
+    Reg = (((Reg) & (~(MPUACC_REG_LIMIT_MASK << MPUACC_REG_LIMIT_LSB))) | \
+         (((Val) & MPUACC_REG_LIMIT_MASK) << MPUACC_REG_LIMIT_LSB))
+#define GET_MPUACC_REG_MASK(Reg) \
+    (((Reg) >> MPUACC_REG_MASK_LSB) & MPUACC_REG_MASK_MASK)
+#define SET_MPUACC_REG_MASK(Reg, Val) \
+    Reg = (((Reg) & (~(MPUACC_REG_MASK_MASK << MPUACC_REG_MASK_LSB))) | \
+         (((Val) & MPUACC_REG_MASK_MASK) << MPUACC_REG_MASK_LSB))
+#define GET_MPUACC_REG_PERM(Reg) \
+    (((Reg) >> MPUACC_REG_PERM_LSB) & MPUACC_REG_PERM_MASK)
+#define SET_MPUACC_REG_PERM(Reg, Val) \
+    Reg = (((Reg) & (~(MPUACC_REG_PERM_MASK << MPUACC_REG_PERM_LSB))) | \
+         (((Val) & MPUACC_REG_PERM_MASK) << MPUACC_REG_PERM_LSB))
+#define GET_MPUACC_REG_RD(Reg) \
+    (((Reg) >> MPUACC_REG_RD_LSB) & MPUACC_REG_RD_MASK)
+#define SET_MPUACC_REG_RD(Reg, Val) \
+    Reg = (((Reg) & (~(MPUACC_REG_RD_MASK << MPUACC_REG_RD_LSB))) | \
+         (((Val) & MPUACC_REG_RD_MASK) << MPUACC_REG_RD_LSB))
+#define GET_MPUACC_REG_RSV1(Reg) \
+    (((Reg) >> MPUACC_REG_RSV1_LSB) & MPUACC_REG_RSV1_MASK)
+#define SET_MPUACC_REG_RSV1(Reg, Val) \
+    Reg = (((Reg) & (~(MPUACC_REG_RSV1_MASK << MPUACC_REG_RSV1_LSB))) | \
+         (((Val) & MPUACC_REG_RSV1_MASK) << MPUACC_REG_RSV1_LSB))
+#define GET_MPUACC_REG_WR(Reg) \
+    (((Reg) >> MPUACC_REG_WR_LSB) & MPUACC_REG_WR_MASK)
+#define SET_MPUACC_REG_WR(Reg, Val) \
+    Reg = (((Reg) & (~(MPUACC_REG_WR_MASK << MPUACC_REG_WR_LSB))) | \
+         (((Val) & MPUACC_REG_WR_MASK) << MPUACC_REG_WR_LSB))
+#define GET_MPUBASE_REG_BASE(Reg) \
+    (((Reg) >> MPUBASE_REG_BASE_LSB) & MPUBASE_REG_BASE_MASK)
+#define SET_MPUBASE_REG_BASE(Reg, Val) \
+    Reg = (((Reg) & (~(MPUBASE_REG_BASE_MASK << MPUBASE_REG_BASE_LSB))) | \
+         (((Val) & MPUBASE_REG_BASE_MASK) << MPUBASE_REG_BASE_LSB))
+#define GET_MPUBASE_REG_D(Reg) \
+    (((Reg) >> MPUBASE_REG_D_LSB) & MPUBASE_REG_D_MASK)
+#define SET_MPUBASE_REG_D(Reg, Val) \
+    Reg = (((Reg) & (~(MPUBASE_REG_D_MASK << MPUBASE_REG_D_LSB))) | \
+         (((Val) & MPUBASE_REG_D_MASK) << MPUBASE_REG_D_LSB))
+#define GET_MPUBASE_REG_INDEX(Reg) \
+    (((Reg) >> MPUBASE_REG_INDEX_LSB) & MPUBASE_REG_INDEX_MASK)
+#define SET_MPUBASE_REG_INDEX(Reg, Val) \
+    Reg = (((Reg) & (~(MPUBASE_REG_INDEX_MASK << MPUBASE_REG_INDEX_LSB))) | \
+         (((Val) & MPUBASE_REG_INDEX_MASK) << MPUBASE_REG_INDEX_LSB))
+#define GET_MPUBASE_REG_RSV1(Reg) \
+    (((Reg) >> MPUBASE_REG_RSV1_LSB) & MPUBASE_REG_RSV1_MASK)
+#define SET_MPUBASE_REG_RSV1(Reg, Val) \
+    Reg = (((Reg) & (~(MPUBASE_REG_RSV1_MASK << MPUBASE_REG_RSV1_LSB))) | \
+         (((Val) & MPUBASE_REG_RSV1_MASK) << MPUBASE_REG_RSV1_LSB))
+#define GET_PTEADDR_REG_PTBASE(Reg) \
+    (((Reg) >> PTEADDR_REG_PTBASE_LSB) & PTEADDR_REG_PTBASE_MASK)
+#define SET_PTEADDR_REG_PTBASE(Reg, Val) \
+    Reg = (((Reg) & (~(PTEADDR_REG_PTBASE_MASK << PTEADDR_REG_PTBASE_LSB))) | \
+         (((Val) & PTEADDR_REG_PTBASE_MASK) << PTEADDR_REG_PTBASE_LSB))
+#define GET_PTEADDR_REG_RSV(Reg) \
+    (((Reg) >> PTEADDR_REG_RSV_LSB) & PTEADDR_REG_RSV_MASK)
+#define SET_PTEADDR_REG_RSV(Reg, Val) \
+    Reg = (((Reg) & (~(PTEADDR_REG_RSV_MASK << PTEADDR_REG_RSV_LSB))) | \
+         (((Val) & PTEADDR_REG_RSV_MASK) << PTEADDR_REG_RSV_LSB))
+#define GET_PTEADDR_REG_VPN(Reg) \
+    (((Reg) >> PTEADDR_REG_VPN_LSB) & PTEADDR_REG_VPN_MASK)
+#define SET_PTEADDR_REG_VPN(Reg, Val) \
+    Reg = (((Reg) & (~(PTEADDR_REG_VPN_MASK << PTEADDR_REG_VPN_LSB))) | \
+         (((Val) & PTEADDR_REG_VPN_MASK) << PTEADDR_REG_VPN_LSB))
+#define GET_SIM_REG_PERF_CNT_CLR(Reg) \
+    (((Reg) >> SIM_REG_PERF_CNT_CLR_LSB) & SIM_REG_PERF_CNT_CLR_MASK)
+#define SET_SIM_REG_PERF_CNT_CLR(Reg, Val) \
+    Reg = (((Reg) & (~(SIM_REG_PERF_CNT_CLR_MASK << \
+                       SIM_REG_PERF_CNT_CLR_LSB))) | \
+         (((Val) & SIM_REG_PERF_CNT_CLR_MASK) << SIM_REG_PERF_CNT_CLR_LSB))
+#define GET_SIM_REG_PERF_CNT_EN(Reg) \
+    (((Reg) >> SIM_REG_PERF_CNT_EN_LSB) & SIM_REG_PERF_CNT_EN_MASK)
+#define SET_SIM_REG_PERF_CNT_EN(Reg, Val) \
+    Reg = (((Reg) & (~(SIM_REG_PERF_CNT_EN_MASK << \
+                       SIM_REG_PERF_CNT_EN_LSB))) | \
+         (((Val) & SIM_REG_PERF_CNT_EN_MASK) << SIM_REG_PERF_CNT_EN_LSB))
+#define GET_SIM_REG_SHOW_MMU_REGS(Reg) \
+    (((Reg) >> SIM_REG_SHOW_MMU_REGS_LSB) & SIM_REG_SHOW_MMU_REGS_MASK)
+#define SET_SIM_REG_SHOW_MMU_REGS(Reg, Val) \
+    Reg = (((Reg) & (~(SIM_REG_SHOW_MMU_REGS_MASK << \
+                       SIM_REG_SHOW_MMU_REGS_LSB))) | \
+         (((Val) & SIM_REG_SHOW_MMU_REGS_MASK) << SIM_REG_SHOW_MMU_REGS_LSB))
+#define GET_SIM_REG_SHOW_TLB(Reg) \
+    (((Reg) >> SIM_REG_SHOW_TLB_LSB) & SIM_REG_SHOW_TLB_MASK)
+#define SET_SIM_REG_SHOW_TLB(Reg, Val) \
+    Reg = (((Reg) & (~(SIM_REG_SHOW_TLB_MASK << SIM_REG_SHOW_TLB_LSB))) | \
+         (((Val) & SIM_REG_SHOW_TLB_MASK) << SIM_REG_SHOW_TLB_LSB))
+#define GET_SIM_REG_STOP(Reg) \
+    (((Reg) >> SIM_REG_STOP_LSB) & SIM_REG_STOP_MASK)
+#define SET_SIM_REG_STOP(Reg, Val) \
+    Reg = (((Reg) & (~(SIM_REG_STOP_MASK << SIM_REG_STOP_LSB))) | \
+         (((Val) & SIM_REG_STOP_MASK) << SIM_REG_STOP_LSB))
+#define GET_STATUS_REG_EH(Reg) \
+    (((Reg) >> STATUS_REG_EH_LSB) & STATUS_REG_EH_MASK)
+#define SET_STATUS_REG_EH(Reg, Val) \
+    Reg = (((Reg) & (~(STATUS_REG_EH_MASK << STATUS_REG_EH_LSB))) | \
+         (((Val) & STATUS_REG_EH_MASK) << STATUS_REG_EH_LSB))
+#define GET_STATUS_REG_MMU(Reg) \
+    (((Reg) >> STATUS_REG_MMU_LSB) & STATUS_REG_MMU_MASK)
+#define SET_STATUS_REG_MMU(Reg, Val) \
+    Reg = (((Reg) & (~(STATUS_REG_MMU_MASK << STATUS_REG_MMU_LSB))) | \
+         (((Val) & STATUS_REG_MMU_MASK) << STATUS_REG_MMU_LSB))
+#define GET_STATUS_REG_MMU_RSV(Reg) \
+    (((Reg) >> STATUS_REG_MMU_RSV_LSB) & STATUS_REG_MMU_RSV_MASK)
+#define SET_STATUS_REG_MMU_RSV(Reg, Val) \
+    Reg = (((Reg) & (~(STATUS_REG_MMU_RSV_MASK << STATUS_REG_MMU_RSV_LSB))) | \
+         (((Val) & STATUS_REG_MMU_RSV_MASK) << STATUS_REG_MMU_RSV_LSB))
+#define GET_STATUS_REG_MPU(Reg) \
+    (((Reg) >> STATUS_REG_MPU_LSB) & STATUS_REG_MPU_MASK)
+#define SET_STATUS_REG_MPU(Reg, Val) \
+    Reg = (((Reg) & (~(STATUS_REG_MPU_MASK << STATUS_REG_MPU_LSB))) | \
+         (((Val) & STATUS_REG_MPU_MASK) << STATUS_REG_MPU_LSB))
+#define GET_STATUS_REG_MPU_RSV(Reg) \
+    (((Reg) >> STATUS_REG_MPU_RSV_LSB) & STATUS_REG_MPU_RSV_MASK)
+#define SET_STATUS_REG_MPU_RSV(Reg, Val) \
+    Reg = (((Reg) & (~(STATUS_REG_MPU_RSV_MASK << STATUS_REG_MPU_RSV_LSB))) | \
+         (((Val) & STATUS_REG_MPU_RSV_MASK) << STATUS_REG_MPU_RSV_LSB))
+#define GET_STATUS_REG_NO_MMU(Reg) \
+    (((Reg) >> STATUS_REG_NO_MMU_LSB) & STATUS_REG_NO_MMU_MASK)
+#define SET_STATUS_REG_NO_MMU(Reg, Val) \
+    Reg = (((Reg) & (~(STATUS_REG_NO_MMU_MASK << STATUS_REG_NO_MMU_LSB))) | \
+         (((Val) & STATUS_REG_NO_MMU_MASK) << STATUS_REG_NO_MMU_LSB))
+#define GET_STATUS_REG_NO_MMU_RSV(Reg) \
+    (((Reg) >> STATUS_REG_NO_MMU_RSV_LSB) & STATUS_REG_NO_MMU_RSV_MASK)
+#define SET_STATUS_REG_NO_MMU_RSV(Reg, Val) \
+    Reg = (((Reg) & (~(STATUS_REG_NO_MMU_RSV_MASK << \
+                       STATUS_REG_NO_MMU_RSV_LSB))) | \
+         (((Val) & STATUS_REG_NO_MMU_RSV_MASK) << STATUS_REG_NO_MMU_RSV_LSB))
+#define GET_STATUS_REG_PIE(Reg) \
+    (((Reg) >> STATUS_REG_PIE_LSB) & STATUS_REG_PIE_MASK)
+#define SET_STATUS_REG_PIE(Reg, Val) \
+    Reg = (((Reg) & (~(STATUS_REG_PIE_MASK << STATUS_REG_PIE_LSB))) | \
+         (((Val) & STATUS_REG_PIE_MASK) << STATUS_REG_PIE_LSB))
+#define GET_STATUS_REG_U(Reg) \
+    (((Reg) >> STATUS_REG_U_LSB) & STATUS_REG_U_MASK)
+#define SET_STATUS_REG_U(Reg, Val) \
+    Reg = (((Reg) & (~(STATUS_REG_U_MASK << STATUS_REG_U_LSB))) | \
+         (((Val) & STATUS_REG_U_MASK) << STATUS_REG_U_LSB))
+#define GET_TLBACC_REG_C(Reg) \
+    (((Reg) >> TLBACC_REG_C_LSB) & TLBACC_REG_C_MASK)
+#define SET_TLBACC_REG_C(Reg, Val) \
+    Reg = (((Reg) & (~(TLBACC_REG_C_MASK << TLBACC_REG_C_LSB))) | \
+         (((Val) & TLBACC_REG_C_MASK) << TLBACC_REG_C_LSB))
+#define GET_TLBACC_REG_G(Reg) \
+    (((Reg) >> TLBACC_REG_G_LSB) & TLBACC_REG_G_MASK)
+#define SET_TLBACC_REG_G(Reg, Val) \
+    Reg = (((Reg) & (~(TLBACC_REG_G_MASK << TLBACC_REG_G_LSB))) | \
+         (((Val) & TLBACC_REG_G_MASK) << TLBACC_REG_G_LSB))
+#define GET_TLBACC_REG_IG(Reg) \
+    (((Reg) >> TLBACC_REG_IG_LSB) & TLBACC_REG_IG_MASK)
+#define SET_TLBACC_REG_IG(Reg, Val) \
+    Reg = (((Reg) & (~(TLBACC_REG_IG_MASK << TLBACC_REG_IG_LSB))) | \
+         (((Val) & TLBACC_REG_IG_MASK) << TLBACC_REG_IG_LSB))
+#define GET_TLBACC_REG_PFN(Reg) \
+    (((Reg) >> TLBACC_REG_PFN_LSB) & TLBACC_REG_PFN_MASK)
+#define SET_TLBACC_REG_PFN(Reg, Val) \
+    Reg = (((Reg) & (~(TLBACC_REG_PFN_MASK << TLBACC_REG_PFN_LSB))) | \
+         (((Val) & TLBACC_REG_PFN_MASK) << TLBACC_REG_PFN_LSB))
+#define GET_TLBACC_REG_R(Reg) \
+    (((Reg) >> TLBACC_REG_R_LSB) & TLBACC_REG_R_MASK)
+#define SET_TLBACC_REG_R(Reg, Val) \
+    Reg = (((Reg) & (~(TLBACC_REG_R_MASK << TLBACC_REG_R_LSB))) | \
+         (((Val) & TLBACC_REG_R_MASK) << TLBACC_REG_R_LSB))
+#define GET_TLBACC_REG_W(Reg) \
+    (((Reg) >> TLBACC_REG_W_LSB) & TLBACC_REG_W_MASK)
+#define SET_TLBACC_REG_W(Reg, Val) \
+    Reg = (((Reg) & (~(TLBACC_REG_W_MASK << TLBACC_REG_W_LSB))) | \
+         (((Val) & TLBACC_REG_W_MASK) << TLBACC_REG_W_LSB))
+#define GET_TLBACC_REG_X(Reg) \
+    (((Reg) >> TLBACC_REG_X_LSB) & TLBACC_REG_X_MASK)
+#define SET_TLBACC_REG_X(Reg, Val) \
+    Reg = (((Reg) & (~(TLBACC_REG_X_MASK << TLBACC_REG_X_LSB))) | \
+         (((Val) & TLBACC_REG_X_MASK) << TLBACC_REG_X_LSB))
+#define GET_TLBMISC_REG_BAD(Reg) \
+    (((Reg) >> TLBMISC_REG_BAD_LSB) & TLBMISC_REG_BAD_MASK)
+#define SET_TLBMISC_REG_BAD(Reg, Val) \
+    Reg = (((Reg) & (~(TLBMISC_REG_BAD_MASK << TLBMISC_REG_BAD_LSB))) | \
+         (((Val) & TLBMISC_REG_BAD_MASK) << TLBMISC_REG_BAD_LSB))
+#define GET_TLBMISC_REG_D(Reg) \
+    (((Reg) >> TLBMISC_REG_D_LSB) & TLBMISC_REG_D_MASK)
+#define SET_TLBMISC_REG_D(Reg, Val) \
+    Reg = (((Reg) & (~(TLBMISC_REG_D_MASK << TLBMISC_REG_D_LSB))) | \
+         (((Val) & TLBMISC_REG_D_MASK) << TLBMISC_REG_D_LSB))
+#define GET_TLBMISC_REG_DBL(Reg) \
+    (((Reg) >> TLBMISC_REG_DBL_LSB) & TLBMISC_REG_DBL_MASK)
+#define SET_TLBMISC_REG_DBL(Reg, Val) \
+    Reg = (((Reg) & (~(TLBMISC_REG_DBL_MASK << TLBMISC_REG_DBL_LSB))) | \
+         (((Val) & TLBMISC_REG_DBL_MASK) << TLBMISC_REG_DBL_LSB))
+#define GET_TLBMISC_REG_PERM(Reg) \
+    (((Reg) >> TLBMISC_REG_PERM_LSB) & TLBMISC_REG_PERM_MASK)
+#define SET_TLBMISC_REG_PERM(Reg, Val) \
+    Reg = (((Reg) & (~(TLBMISC_REG_PERM_MASK << TLBMISC_REG_PERM_LSB))) | \
+         (((Val) & TLBMISC_REG_PERM_MASK) << TLBMISC_REG_PERM_LSB))
+#define GET_TLBMISC_REG_PID(Reg) \
+    (((Reg) >> TLBMISC_REG_PID_LSB) & TLBMISC_REG_PID_MASK)
+#define SET_TLBMISC_REG_PID(Reg, Val) \
+    Reg = (((Reg) & (~(TLBMISC_REG_PID_MASK << TLBMISC_REG_PID_LSB))) | \
+         (((Val) & TLBMISC_REG_PID_MASK) << TLBMISC_REG_PID_LSB))
+#define GET_TLBMISC_REG_RD(Reg) \
+    (((Reg) >> TLBMISC_REG_RD_LSB) & TLBMISC_REG_RD_MASK)
+#define SET_TLBMISC_REG_RD(Reg, Val) \
+    Reg = (((Reg) & (~(TLBMISC_REG_RD_MASK << TLBMISC_REG_RD_LSB))) | \
+         (((Val) & TLBMISC_REG_RD_MASK) << TLBMISC_REG_RD_LSB))
+#define GET_TLBMISC_REG_RSV1(Reg) \
+    (((Reg) >> TLBMISC_REG_RSV1_LSB) & TLBMISC_REG_RSV1_MASK)
+#define SET_TLBMISC_REG_RSV1(Reg, Val) \
+    Reg = (((Reg) & (~(TLBMISC_REG_RSV1_MASK << TLBMISC_REG_RSV1_LSB))) | \
+         (((Val) & TLBMISC_REG_RSV1_MASK) << TLBMISC_REG_RSV1_LSB))
+#define GET_TLBMISC_REG_WAY(Reg) \
+    (((Reg) >> TLBMISC_REG_WAY_LSB) & TLBMISC_REG_WAY_MASK)
+#define SET_TLBMISC_REG_WAY(Reg, Val) \
+    Reg = (((Reg) & (~(TLBMISC_REG_WAY_MASK << TLBMISC_REG_WAY_LSB))) | \
+         (((Val) & TLBMISC_REG_WAY_MASK) << TLBMISC_REG_WAY_LSB))
+#define GET_TLBMISC_REG_WE(Reg) \
+    (((Reg) >> TLBMISC_REG_WE_LSB) & TLBMISC_REG_WE_MASK)
+#define SET_TLBMISC_REG_WE(Reg, Val) \
+    Reg = (((Reg) & (~(TLBMISC_REG_WE_MASK << TLBMISC_REG_WE_LSB))) | \
+         (((Val) & TLBMISC_REG_WE_MASK) << TLBMISC_REG_WE_LSB))
+
+/* Macros to extract MMU fields */
+#define GET_MMU_ADDR_BYPASS_TLB_CACHEABLE(Addr) \
+    (((Addr) >> MMU_ADDR_BYPASS_TLB_CACHEABLE_LSB) & \
+     MMU_ADDR_BYPASS_TLB_CACHEABLE_MASK)
+#define SET_MMU_ADDR_BYPASS_TLB_CACHEABLE(Addr, Val) \
+    Addr = (((Addr) & (~(MMU_ADDR_BYPASS_TLB_CACHEABLE_MASK << \
+                         MMU_ADDR_BYPASS_TLB_CACHEABLE_LSB))) | \
+         (((Val) & MMU_ADDR_BYPASS_TLB_CACHEABLE_MASK) << \
+          MMU_ADDR_BYPASS_TLB_CACHEABLE_LSB))
+#define GET_MMU_ADDR_BYPASS_TLB(Addr) \
+    (((Addr) >> MMU_ADDR_BYPASS_TLB_LSB) & MMU_ADDR_BYPASS_TLB_MASK)
+#define SET_MMU_ADDR_BYPASS_TLB(Addr, Val) \
+    Addr = (((Addr) & (~(MMU_ADDR_BYPASS_TLB_MASK << \
+                         MMU_ADDR_BYPASS_TLB_LSB))) | \
+         (((Val) & MMU_ADDR_BYPASS_TLB_MASK) << MMU_ADDR_BYPASS_TLB_LSB))
+#define GET_MMU_ADDR_BYPASS_TLB_PADDR(Addr) \
+    (((Addr) >> MMU_ADDR_BYPASS_TLB_PADDR_LSB) & MMU_ADDR_BYPASS_TLB_PADDR_MASK)
+#define SET_MMU_ADDR_BYPASS_TLB_PADDR(Addr, Val) \
+    Addr = (((Addr) & (~(MMU_ADDR_BYPASS_TLB_PADDR_MASK << \
+                         MMU_ADDR_BYPASS_TLB_PADDR_LSB))) | \
+         (((Val) & MMU_ADDR_BYPASS_TLB_PADDR_MASK) << \
+          MMU_ADDR_BYPASS_TLB_PADDR_LSB))
+#define GET_MMU_ADDR_IO_REGION(Addr) \
+    (((Addr) >> MMU_ADDR_IO_REGION_LSB) & MMU_ADDR_IO_REGION_MASK)
+#define SET_MMU_ADDR_IO_REGION(Addr, Val) \
+    Addr = (((Addr) & (~(MMU_ADDR_IO_REGION_MASK << \
+                         MMU_ADDR_IO_REGION_LSB))) | \
+         (((Val) & MMU_ADDR_IO_REGION_MASK) << MMU_ADDR_IO_REGION_LSB))
+#define GET_MMU_ADDR_KERNEL_MMU_REGION(Addr) \
+    (((Addr) >> MMU_ADDR_KERNEL_MMU_REGION_LSB) & \
+     MMU_ADDR_KERNEL_MMU_REGION_MASK)
+#define SET_MMU_ADDR_KERNEL_MMU_REGION(Addr, Val) \
+    Addr = (((Addr) & (~(MMU_ADDR_KERNEL_MMU_REGION_MASK << \
+                         MMU_ADDR_KERNEL_MMU_REGION_LSB))) | \
+         (((Val) & MMU_ADDR_KERNEL_MMU_REGION_MASK) << \
+          MMU_ADDR_KERNEL_MMU_REGION_LSB))
+#define GET_MMU_ADDR_KERNEL_REGION(Addr) \
+    (((Addr) >> MMU_ADDR_KERNEL_REGION_LSB) & MMU_ADDR_KERNEL_REGION_MASK)
+#define SET_MMU_ADDR_KERNEL_REGION(Addr, Val) \
+    Addr = (((Addr) & (~(MMU_ADDR_KERNEL_REGION_MASK << \
+                         MMU_ADDR_KERNEL_REGION_LSB))) | \
+         (((Val) & MMU_ADDR_KERNEL_REGION_MASK) << MMU_ADDR_KERNEL_REGION_LSB))
+#define GET_MMU_ADDR_PAGE_OFFSET(Addr) \
+    (((Addr) >> MMU_ADDR_PAGE_OFFSET_LSB) & MMU_ADDR_PAGE_OFFSET_MASK)
+#define SET_MMU_ADDR_PAGE_OFFSET(Addr, Val) \
+    Addr = (((Addr) & (~(MMU_ADDR_PAGE_OFFSET_MASK << \
+                         MMU_ADDR_PAGE_OFFSET_LSB))) | \
+         (((Val) & MMU_ADDR_PAGE_OFFSET_MASK) << MMU_ADDR_PAGE_OFFSET_LSB))
+#define GET_MMU_ADDR_PFN(Addr) \
+    (((Addr) >> MMU_ADDR_PFN_LSB) & MMU_ADDR_PFN_MASK)
+#define SET_MMU_ADDR_PFN(Addr, Val) \
+    Addr = (((Addr) & (~(MMU_ADDR_PFN_MASK << MMU_ADDR_PFN_LSB))) | \
+         (((Val) & MMU_ADDR_PFN_MASK) << MMU_ADDR_PFN_LSB))
+#define GET_MMU_ADDR_USER_REGION(Addr) \
+    (((Addr) >> MMU_ADDR_USER_REGION_LSB) & MMU_ADDR_USER_REGION_MASK)
+#define SET_MMU_ADDR_USER_REGION(Addr, Val) \
+    Addr = (((Addr) & (~(MMU_ADDR_USER_REGION_MASK << \
+                         MMU_ADDR_USER_REGION_LSB))) | \
+         (((Val) & MMU_ADDR_USER_REGION_MASK) << MMU_ADDR_USER_REGION_LSB))
+#define GET_MMU_ADDR_VPN(Addr) \
+    (((Addr) >> MMU_ADDR_VPN_LSB) & MMU_ADDR_VPN_MASK)
+#define SET_MMU_ADDR_VPN(Addr, Val) \
+    Addr = (((Addr) & (~(MMU_ADDR_VPN_MASK << MMU_ADDR_VPN_LSB))) | \
+         (((Val) & MMU_ADDR_VPN_MASK) << MMU_ADDR_VPN_LSB))
+
+/* OP instruction values */
+#define OP_ADDI 4
+#define OP_ANDHI 44
+#define OP_ANDI 12
+#define OP_BEQ 38
+#define OP_BGE 14
+#define OP_BGEU 46
+#define OP_BLT 22
+#define OP_BLTU 54
+#define OP_BNE 30
+#define OP_BR 6
+#define OP_CALL 0
+#define OP_CMPEQI 32
+#define OP_CMPGEI 8
+#define OP_CMPGEUI 40
+#define OP_CMPLTI 16
+#define OP_CMPLTUI 48
+#define OP_CMPNEI 24
+#define OP_CUSTOM 50
+#define OP_FLUSHD 59
+#define OP_FLUSHDA 27
+#define OP_INITD 51
+#define OP_INITDA 19
+#define OP_JMPI 1
+#define OP_LDB 7
+#define OP_LDBIO 39
+#define OP_LDBU 3
+#define OP_LDBUIO 35
+#define OP_LDH 15
+#define OP_LDHIO 47
+#define OP_LDHU 11
+#define OP_LDHUIO 43
+#define OP_LDL 31
+#define OP_LDW 23
+#define OP_LDWIO 55
+#define OP_MULI 36
+#define OP_OPX 58
+#define OP_ORHI 52
+#define OP_ORI 20
+#define OP_STB 5
+#define OP_STBIO 37
+#define OP_STC 29
+#define OP_STH 13
+#define OP_STHIO 45
+#define OP_STW 21
+#define OP_STWIO 53
+#define OP_XORHI 60
+#define OP_XORI 28
+
+/* OPX instruction values */
+#define OPX_ADD 49
+#define OPX_AND 14
+#define OPX_BREAK 52
+#define OPX_BRET 9
+#define OPX_CALLR 29
+#define OPX_CMPEQ 32
+#define OPX_CMPGE 8
+#define OPX_CMPGEU 40
+#define OPX_CMPLT 16
+#define OPX_CMPLTU 48
+#define OPX_CMPNE 24
+#define OPX_CRST 62
+#define OPX_DIV 37
+#define OPX_DIVU 36
+#define OPX_ERET 1
+#define OPX_FLUSHI 12
+#define OPX_FLUSHP 4
+#define OPX_HBREAK 53
+#define OPX_INITI 41
+#define OPX_INTR 61
+#define OPX_JMP 13
+#define OPX_MUL 39
+#define OPX_MULXSS 31
+#define OPX_MULXSU 23
+#define OPX_MULXUU 7
+#define OPX_NEXTPC 28
+#define OPX_NOR 6
+#define OPX_OR 22
+#define OPX_RDCTL 38
+#define OPX_RET 5
+#define OPX_ROL 3
+#define OPX_ROLI 2
+#define OPX_ROR 11
+#define OPX_SLL 19
+#define OPX_SLLI 18
+#define OPX_SRA 59
+#define OPX_SRAI 58
+#define OPX_SRL 27
+#define OPX_SRLI 26
+#define OPX_SUB 57
+#define OPX_SYNC 54
+#define OPX_TRAP 45
+#define OPX_WRCTL 46
+#define OPX_XOR 30
+
+/* Macros to detect sub-opcode instructions */
+#define IS_OPX_INST(Iw) (GET_IW_OP(Iw) == OP_OPX)
+#define IS_CUSTOM_INST(Iw) (GET_IW_OP(Iw) == OP_CUSTOM)
+
+/* Instruction property macros */
+#define IW_PROP_RESERVED_OP(Iw) (0)
+
+#define IW_PROP_RESERVED_OPX(Iw) (0)
+
+#define IW_PROP_RESERVED(Iw) (0)
+
+#define IW_PROP_SUPERVISOR_ONLY(Iw) ( \
+    (op_prop_supervisor_only[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_supervisor_only[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_supervisor_only[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_supervisor_only[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_INITI_FLUSHI(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_INITI) && IS_OPX_INST(Iw)) || \
+    ((GET_IW_OPX((Iw)) == OPX_FLUSHI) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_FLUSH_PIPE(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_flush_pipe[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_flush_pipe[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_JMP_INDIRECT_NON_TRAP(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_jmp_indirect_non_trap[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_jmp_indirect_non_trap[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_JMP_INDIRECT(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_jmp_indirect[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_jmp_indirect[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_JMP_DIRECT(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_CALL)) || \
+    ((GET_IW_OP((Iw)) == OP_JMPI)) \
+  ) \
+ \
+)
+
+#define IW_PROP_MUL_LSW(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_MULI)) || \
+    ((GET_IW_OPX((Iw)) == OPX_MUL) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_MULX(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_mulx[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_mulx[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_MUL(Iw) ( \
+    (op_prop_mul[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_mul[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_mul[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_mul[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_DIV_UNSIGNED(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_DIVU) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_DIV_SIGNED(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_DIV) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_DIV(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_DIVU) && IS_OPX_INST(Iw)) || \
+    ((GET_IW_OPX((Iw)) == OPX_DIV) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_UNIMPLEMENTED(Iw) (0)
+
+#define IW_PROP_ILLEGAL(Iw) (0)
+
+#define IW_PROP_IMPLICIT_DST_RETADDR(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_CALL)) \
+  ) \
+ \
+)
+
+#define IW_PROP_IMPLICIT_DST_ERETADDR(Iw) (0)
+
+#define IW_PROP_INTR(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_INTR) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_EXCEPTION(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_TRAP) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_BREAK(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_BREAK) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_CRST(Iw) (0)
+
+#define IW_PROP_WR_CTL_REG(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_wr_ctl_reg[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_wr_ctl_reg[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_UNCOND_CTI_NON_BR(Iw) ( \
+    (op_prop_uncond_cti_non_br[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_uncond_cti_non_br[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_uncond_cti_non_br[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_uncond_cti_non_br[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_RETADDR(Iw) ( \
+    (op_prop_retaddr[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_retaddr[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_retaddr[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_retaddr[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_SHIFT_LEFT(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_SLLI) && IS_OPX_INST(Iw)) || \
+    ((GET_IW_OPX((Iw)) == OPX_SLL) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_SHIFT_LOGICAL(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_shift_logical[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_shift_logical[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_ROT_LEFT(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_ROLI) && IS_OPX_INST(Iw)) || \
+    ((GET_IW_OPX((Iw)) == OPX_ROL) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_SHIFT_ROT_LEFT(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_shift_rot_left[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_shift_rot_left[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_SHIFT_RIGHT_LOGICAL(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_SRLI) && IS_OPX_INST(Iw)) || \
+    ((GET_IW_OPX((Iw)) == OPX_SRL) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_SHIFT_RIGHT_ARITH(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_SRAI) && IS_OPX_INST(Iw)) || \
+    ((GET_IW_OPX((Iw)) == OPX_SRA) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_SHIFT_RIGHT(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_shift_right[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_shift_right[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_ROT_RIGHT(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_ROR) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_SHIFT_ROT_RIGHT(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_shift_rot_right[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_shift_rot_right[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_SHIFT_ROT(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_shift_rot[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_shift_rot[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_SHIFT_ROT_IMM(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_shift_rot_imm[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_shift_rot_imm[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_ROTATE(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_rotate[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_rotate[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_LOGIC_REG(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_logic_reg[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_logic_reg[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_LOGIC_HI_IMM16(Iw) ( \
+    (op_prop_logic_hi_imm16[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_logic_hi_imm16[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_LOGIC_LO_IMM16(Iw) ( \
+    (op_prop_logic_lo_imm16[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_logic_lo_imm16[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_LOGIC_IMM16(Iw) ( \
+    (op_prop_logic_imm16[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_logic_imm16[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_LOGIC(Iw) ( \
+    (op_prop_logic[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_logic[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_logic[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_logic[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_UNSIGNED_LO_IMM16(Iw) ( \
+    (op_prop_unsigned_lo_imm16[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_unsigned_lo_imm16[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_unsigned_lo_imm16[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_unsigned_lo_imm16[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_ARITH_IMM16(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_ADDI)) || \
+    ((GET_IW_OP((Iw)) == OP_MULI)) \
+  ) \
+ \
+)
+
+#define IW_PROP_CMP_IMM16(Iw) ( \
+    (op_prop_cmp_imm16[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_cmp_imm16[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_JMPI(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_JMPI)) \
+  ) \
+ \
+)
+
+#define IW_PROP_CMP_IMM16_WITH_CALL_JMPI(Iw) ( \
+    (op_prop_cmp_imm16_with_call_jmpi[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_cmp_imm16_with_call_jmpi[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_CMP_REG(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_cmp_reg[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_cmp_reg[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_SRC_IMM5(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_src_imm5[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_src_imm5[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_CMP_WITH_LT(Iw) ( \
+    (op_prop_cmp_with_lt[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_cmp_with_lt[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_cmp_with_lt[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_cmp_with_lt[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_CMP_WITH_EQ(Iw) ( \
+    (op_prop_cmp_with_eq[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_cmp_with_eq[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_cmp_with_eq[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_cmp_with_eq[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_CMP_WITH_GE(Iw) ( \
+    (op_prop_cmp_with_ge[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_cmp_with_ge[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_cmp_with_ge[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_cmp_with_ge[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_CMP_WITH_NE(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_CMPNEI)) || \
+    ((GET_IW_OPX((Iw)) == OPX_CMPNE) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_CMP_ALU_SIGNED(Iw) ( \
+    (op_prop_cmp_alu_signed[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_cmp_alu_signed[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_cmp_alu_signed[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_cmp_alu_signed[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_CMP(Iw) ( \
+    (op_prop_cmp[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_cmp[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_cmp[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_cmp[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_BR_WITH_LT(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_BLT)) || \
+    ((GET_IW_OP((Iw)) == OP_BLTU)) \
+  ) \
+ \
+)
+
+#define IW_PROP_BR_WITH_GE(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_BGE)) || \
+    ((GET_IW_OP((Iw)) == OP_BGEU)) \
+  ) \
+ \
+)
+
+#define IW_PROP_BR_WITH_EQ(Iw) ( \
+    (op_prop_br_with_eq[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_br_with_eq[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_BR_WITH_NE(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_BNE)) \
+  ) \
+ \
+)
+
+#define IW_PROP_BR_ALU_SIGNED(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_BGE)) || \
+    ((GET_IW_OP((Iw)) == OP_BLT)) \
+  ) \
+ \
+)
+
+#define IW_PROP_BR_COND(Iw) ( \
+    (op_prop_br_cond[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_br_cond[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_BR_UNCOND(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_BR)) \
+  ) \
+ \
+)
+
+#define IW_PROP_BR(Iw) ( \
+    (op_prop_br[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_br[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_ALU_SUB(Iw) ( \
+    (op_prop_alu_sub[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_alu_sub[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_alu_sub[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_alu_sub[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_FORCE_XOR(Iw) ( \
+    (op_prop_force_xor[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_force_xor[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_force_xor[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_force_xor[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_LOAD8(Iw) ( \
+    (op_prop_load8[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_load8[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_LOAD16(Iw) ( \
+    (op_prop_load16[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_load16[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_LOAD32(Iw) ( \
+    (op_prop_load32[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_load32[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_LOAD_SIGNED(Iw) ( \
+    (op_prop_load_signed[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_load_signed[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_LOAD_UNSIGNED(Iw) ( \
+    (op_prop_load_unsigned[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_load_unsigned[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_LOAD(Iw) ( \
+    (op_prop_load[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_load[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_DCACHE_MANAGEMENT_NOP(Iw) ( \
+    (op_prop_dcache_management_nop[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_dcache_management_nop[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_LOAD_DCACHE_MANAGEMENT(Iw) ( \
+    (op_prop_load_dcache_management[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_load_dcache_management[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_LOAD_NON_IO(Iw) ( \
+    (op_prop_load_non_io[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_load_non_io[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_STORE8(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_STB)) || \
+    ((GET_IW_OP((Iw)) == OP_STBIO)) \
+  ) \
+ \
+)
+
+#define IW_PROP_STORE16(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_STH)) || \
+    ((GET_IW_OP((Iw)) == OP_STHIO)) \
+  ) \
+ \
+)
+
+#define IW_PROP_STORE32(Iw) ( \
+    (op_prop_store32[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_store32[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_STORE(Iw) ( \
+    (op_prop_store[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_store[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_STORE_NON_IO(Iw) ( \
+    (op_prop_store_non_io[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_store_non_io[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_MEM(Iw) ( \
+    (op_prop_mem[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_mem[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_INITD(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_INITD)) \
+  ) \
+ \
+)
+
+#define IW_PROP_INITDA(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_INITDA)) \
+  ) \
+ \
+)
+
+#define IW_PROP_FLUSHD(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_FLUSHD)) \
+  ) \
+ \
+)
+
+#define IW_PROP_FLUSHDA(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_FLUSHDA)) \
+  ) \
+ \
+)
+
+#define IW_PROP_INITD_FLUSHD(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_INITD)) || \
+    ((GET_IW_OP((Iw)) == OP_FLUSHD)) \
+  ) \
+ \
+)
+
+#define IW_PROP_INITDA_FLUSHDA(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_INITDA)) || \
+    ((GET_IW_OP((Iw)) == OP_FLUSHDA)) \
+  ) \
+ \
+)
+
+#define IW_PROP_INITD_INITDA(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_INITD)) || \
+    ((GET_IW_OP((Iw)) == OP_INITDA)) \
+  ) \
+ \
+)
+
+#define IW_PROP_FLUSHD_FLUSHDA(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_FLUSHD)) || \
+    ((GET_IW_OP((Iw)) == OP_FLUSHDA)) \
+  ) \
+ \
+)
+
+#define IW_PROP_INITD_FLUSHD_FLUSHDA(Iw) ( \
+    (op_prop_initd_flushd_flushda[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_initd_flushd_flushda[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_DCACHE_MANAGEMENT(Iw) ( \
+    (op_prop_dcache_management[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_dcache_management[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_LOAD_IO(Iw) ( \
+    (op_prop_load_io[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_load_io[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_STORE_IO(Iw) ( \
+    (op_prop_store_io[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_store_io[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_MEM_IO(Iw) ( \
+    (op_prop_mem_io[GET_IW_OP(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_mem_io[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_ARITH(Iw) ( \
+    (op_prop_arith[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_arith[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_arith[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_arith[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_A_NOT_SRC(Iw) ( \
+  ( \
+    ((GET_IW_OP((Iw)) == OP_CALL)) || \
+    ((GET_IW_OP((Iw)) == OP_JMPI)) \
+  ) \
+  || (IS_CUSTOM_INST(Iw) && !GET_IW_CUSTOM_READRA(Iw)) \
+)
+
+#define IW_PROP_B_NOT_SRC(Iw) ( \
+    (op_prop_b_not_src[GET_IW_OP(Iw)]) \
+  || (IS_CUSTOM_INST(Iw) && !GET_IW_CUSTOM_READRB(Iw)))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_b_not_src[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_IGNORE_DST(Iw) ( \
+    (op_prop_ignore_dst[GET_IW_OP(Iw)]) \
+  || (IS_CUSTOM_INST(Iw) && !GET_IW_CUSTOM_WRITERC(Iw)))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_ignore_dst[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_SRC2_CHOOSE_IMM(Iw) ( \
+    (op_prop_src2_choose_imm[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_src2_choose_imm[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_src2_choose_imm[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_src2_choose_imm[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_WRCTL_INST(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_WRCTL) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_RDCTL_INST(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_RDCTL) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_MUL_SRC1_SIGNED(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_MULXSS) && IS_OPX_INST(Iw)) || \
+    ((GET_IW_OPX((Iw)) == OPX_MULXSU) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_MUL_SRC2_SIGNED(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_MULXSS) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_MUL_SHIFT_SRC1_SIGNED(Iw) ( \
+    (IS_OPX_INST(Iw) && opx_prop_mul_shift_src1_signed[GET_IW_OPX(Iw)]))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_mul_shift_src1_signed[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_MUL_SHIFT_SRC2_SIGNED(Iw) ( \
+  ( \
+    ((GET_IW_OPX((Iw)) == OPX_MULXSS) && IS_OPX_INST(Iw)) \
+  ) \
+ \
+)
+
+#define IW_PROP_DONT_DISPLAY_DST_REG(Iw) ( \
+    (op_prop_dont_display_dst_reg[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_dont_display_dst_reg[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_dont_display_dst_reg[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_dont_display_dst_reg[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_DONT_DISPLAY_SRC1_REG(Iw) ( \
+    (op_prop_dont_display_src1_reg[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_dont_display_src1_reg[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_dont_display_src1_reg[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_dont_display_src1_reg[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_DONT_DISPLAY_SRC2_REG(Iw) ( \
+    (op_prop_dont_display_src2_reg[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_dont_display_src2_reg[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_dont_display_src2_reg[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_dont_display_src2_reg[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_SRC1_NO_X(Iw) ( \
+    (op_prop_src1_no_x[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_src1_no_x[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_src1_no_x[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_src1_no_x[64];
+#endif /* ALT_ASM_SRC */
+
+#define IW_PROP_SRC2_NO_X(Iw) ( \
+    (op_prop_src2_no_x[GET_IW_OP(Iw)] || \
+    (IS_OPX_INST(Iw) && opx_prop_src2_no_x[GET_IW_OPX(Iw)])))
+
+#ifndef ALT_ASM_SRC
+extern unsigned char op_prop_src2_no_x[64];
+#endif /* ALT_ASM_SRC */
+
+#ifndef ALT_ASM_SRC
+extern unsigned char opx_prop_src2_no_x[64];
+#endif /* ALT_ASM_SRC */
+
+/* Instruction types */
+#define INST_TYPE_OP  0
+#define INST_TYPE_OPX 1
+
+/* Canonical instruction codes independent of encoding */
+#define CALL_INST_CODE 0
+#define JMPI_INST_CODE 1
+#define LDBU_INST_CODE 2
+#define ADDI_INST_CODE 3
+#define STB_INST_CODE 4
+#define BR_INST_CODE 5
+#define LDB_INST_CODE 6
+#define CMPGEI_INST_CODE 7
+#define LDHU_INST_CODE 8
+#define ANDI_INST_CODE 9
+#define STH_INST_CODE 10
+#define BGE_INST_CODE 11
+#define LDH_INST_CODE 12
+#define CMPLTI_INST_CODE 13
+#define INITDA_INST_CODE 14
+#define ORI_INST_CODE 15
+#define STW_INST_CODE 16
+#define BLT_INST_CODE 17
+#define LDW_INST_CODE 18
+#define CMPNEI_INST_CODE 19
+#define FLUSHDA_INST_CODE 20
+#define XORI_INST_CODE 21
+#define STC_INST_CODE 22
+#define BNE_INST_CODE 23
+#define LDL_INST_CODE 24
+#define CMPEQI_INST_CODE 25
+#define LDBUIO_INST_CODE 26
+#define MULI_INST_CODE 27
+#define STBIO_INST_CODE 28
+#define BEQ_INST_CODE 29
+#define LDBIO_INST_CODE 30
+#define CMPGEUI_INST_CODE 31
+#define LDHUIO_INST_CODE 32
+#define ANDHI_INST_CODE 33
+#define STHIO_INST_CODE 34
+#define BGEU_INST_CODE 35
+#define LDHIO_INST_CODE 36
+#define CMPLTUI_INST_CODE 37
+#define CUSTOM_INST_CODE 38
+#define INITD_INST_CODE 39
+#define ORHI_INST_CODE 40
+#define STWIO_INST_CODE 41
+#define BLTU_INST_CODE 42
+#define LDWIO_INST_CODE 43
+#define FLUSHD_INST_CODE 44
+#define XORHI_INST_CODE 45
+#define ERET_INST_CODE 46
+#define ROLI_INST_CODE 47
+#define ROL_INST_CODE 48
+#define FLUSHP_INST_CODE 49
+#define RET_INST_CODE 50
+#define NOR_INST_CODE 51
+#define MULXUU_INST_CODE 52
+#define CMPGE_INST_CODE 53
+#define BRET_INST_CODE 54
+#define ROR_INST_CODE 55
+#define FLUSHI_INST_CODE 56
+#define JMP_INST_CODE 57
+#define AND_INST_CODE 58
+#define CMPLT_INST_CODE 59
+#define SLLI_INST_CODE 60
+#define SLL_INST_CODE 61
+#define OR_INST_CODE 62
+#define MULXSU_INST_CODE 63
+#define CMPNE_INST_CODE 64
+#define SRLI_INST_CODE 65
+#define SRL_INST_CODE 66
+#define NEXTPC_INST_CODE 67
+#define CALLR_INST_CODE 68
+#define XOR_INST_CODE 69
+#define MULXSS_INST_CODE 70
+#define CMPEQ_INST_CODE 71
+#define DIVU_INST_CODE 72
+#define DIV_INST_CODE 73
+#define RDCTL_INST_CODE 74
+#define MUL_INST_CODE 75
+#define CMPGEU_INST_CODE 76
+#define INITI_INST_CODE 77
+#define TRAP_INST_CODE 78
+#define WRCTL_INST_CODE 79
+#define CMPLTU_INST_CODE 80
+#define ADD_INST_CODE 81
+#define BREAK_INST_CODE 82
+#define HBREAK_INST_CODE 83
+#define SYNC_INST_CODE 84
+#define SUB_INST_CODE 85
+#define SRAI_INST_CODE 86
+#define SRA_INST_CODE 87
+#define INTR_INST_CODE 88
+#define CRST_INST_CODE 89
+#define RSV_INST_CODE 90
+#define NUM_NIOS2_INST_CODES 91
+
+#ifndef ALT_ASM_SRC
+/* Instruction information entry */
+typedef struct {
+     const char *name;     /* Assembly-language instruction name */
+     int         instType; /* INST_TYPE_OP or INST_TYPE_OPX */
+     unsigned    opcode;   /* Value of instruction word OP/OPX field */
+} Nios2InstInfo;
+
+extern Nios2InstInfo nios2InstInfo[NUM_NIOS2_INST_CODES];
+#endif /* ALT_ASM_SRC */
+
+/* Returns the instruction code given the 32-bit instruction word */
+#define GET_INST_CODE(Iw) \
+         (IS_OPX_INST(Iw) ? opxToInstCode[GET_IW_OPX(Iw)] : \
+                            opToInstCode[GET_IW_OP(Iw)])
+
+#ifndef ALT_ASM_SRC
+extern int opToInstCode[64];
+extern int opxToInstCode[64];
+#endif /* ALT_ASM_SRC */
+
+/*
+ * MMU Memory Region Macros
+ */
+#define USER_REGION_MIN_VADDR       0x00000000
+#define USER_REGION_MAX_VADDR       0x7fffffff
+#define KERNEL_MMU_REGION_MIN_VADDR 0x80000000
+#define KERNEL_MMU_REGION_MAX_VADDR 0xbfffffff
+#define KERNEL_REGION_MIN_VADDR     0xc0000000
+#define KERNEL_REGION_MAX_VADDR     0xdfffffff
+#define IO_REGION_MIN_VADDR         0xe0000000
+#define IO_REGION_MAX_VADDR         0xffffffff
+
+#define MMU_PAGE_SIZE (0x1 << (MMU_ADDR_PAGE_OFFSET_SZ))
+
+#define isMmuUserRegion(Vaddr)          \
+    (GET_MMU_ADDR_USER_REGION(Vaddr) == MMU_ADDR_USER_REGION)
+#define isMmuKernelMmuRegion(Vaddr)     \
+    (GET_MMU_ADDR_KERNEL_MMU_REGION(Vaddr) == MMU_ADDR_KERNEL_MMU_REGION)
+#define isMmuKernelRegion(Vaddr)        \
+    (GET_MMU_ADDR_KERNEL_REGION(Vaddr) == MMU_ADDR_KERNEL_REGION)
+#define isMmuIORegion(Vaddr)            \
+    (GET_MMU_ADDR_IO_REGION(Vaddr) == MMU_ADDR_IO_REGION)
+
+/* Does this virtual address bypass the TLB? */
+#define vaddrBypassTlb(Vaddr)                \
+    (GET_MMU_ADDR_BYPASS_TLB(Vaddr) == MMU_ADDR_BYPASS_TLB)
+
+/* If TLB is bypassed, is the address cacheable or uncachable. */
+#define vaddrBypassTlbCacheable(Vaddr)       \
+    (GET_MMU_ADDR_BYPASS_TLB_CACHEABLE(Vaddr) == MMU_ADDR_BYPASS_TLB_CACHEABLE)
+
+/*
+ * Compute physical address for regions that bypass the TLB.
+ * Just need to clear some top bits.
+ */
+#define bypassTlbVaddrToPaddr(Vaddr)    \
+    ((Vaddr) & (MMU_ADDR_BYPASS_TLB_PADDR_MASK << \
+                MMU_ADDR_BYPASS_TLB_PADDR_LSB))
+
+/*
+ * Will the physical address fit in the Kernel/IO region virtual address space?
+ */
+#define fitsInKernelRegion(Paddr)       \
+    (GET_MMU_ADDR_KERNEL_REGION(Paddr) == 0)
+#define fitsInIORegion(Paddr)           \
+    (GET_MMU_ADDR_IO_REGION(Paddr) == 0)
+
+/* Convert a physical address to a Kernel/IO region virtual address. */
+#define paddrToKernelRegionVaddr(Paddr) \
+    ((Paddr) | (MMU_ADDR_KERNEL_REGION << MMU_ADDR_KERNEL_REGION_LSB))
+#define paddrToIORegionVaddr(Paddr)     \
+    ((Paddr) | (MMU_ADDR_IO_REGION << MMU_ADDR_IO_REGION_LSB))
+
+/*
+ * Convert a virtual address to a Kernel/IO region virtual address.
+ * Uses bypassTlbVaddrToPaddr to clear top bits.
+ */
+#define vaddrToKernelRegionVaddr(Vaddr) \
+    paddrToKernelRegionVaddr(bypassTlbVaddrToPaddr(Vaddr))
+#define vaddrToIORegionVaddr(Vaddr) \
+    paddrToIORegionVaddr(bypassTlbVaddrToPaddr(Vaddr))
+
+/* Convert between VPN/PFN and virtual/physical addresses. */
+#define vpnToVaddr(Vpn) ((Vpn) << MMU_ADDR_VPN_LSB)
+#define pfnToPaddr(Pfn) ((Pfn) << MMU_ADDR_PFN_LSB)
+#define vaddrToVpn(Vaddr) GET_MMU_ADDR_VPN(Vaddr)
+#define paddrToPfn(Paddr) GET_MMU_ADDR_PFN(Paddr)
+
+/* Bitwise OR with a KERNEL region address to make it an IO region address */
+#define KERNEL_TO_IO_REGION 0x20000000
+
+/* Exception information */
+#ifndef ALT_ASM_SRC
+typedef struct {
+    const char *name;
+    int priority;
+    int subPriority; /* -1 if none */
+    int causeId; /* -1 if none */
+    int recordAddr;
+} ExcInfo;
+
+extern ExcInfo excInfo[NUM_EXC_IDS];
+#endif /* ALT_ASM_SRC */
+
+#endif /* _NIOS2_ISA_H_ */
+/* nios2-opc.c -- Altera New Jersey opcode list.
+
+   Copyright (C) 2003
+   by Nigel Gray (ngray@altera.com).
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+1, or (at your option) any later version.
+
+GDB, GAS, and the GNU binutils are distributed in the hope that they
+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 file; see the file COPYING.  If not,
+see <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+/*#include "nios2.h" */
+
+/* Register string table */
+
+const struct nios2_reg nios2_builtin_regs[] = {
+  {"zero", 0},
+  {"at", 1},  /* assembler temporary */
+  {"r2", 2},
+  {"r3", 3},
+  {"r4", 4},
+  {"r5", 5},
+  {"r6", 6},
+  {"r7", 7},
+  {"r8", 8},
+  {"r9", 9},
+  {"r10", 10},
+  {"r11", 11},
+  {"r12", 12},
+  {"r13", 13},
+  {"r14", 14},
+  {"r15", 15},
+  {"r16", 16},
+  {"r17", 17},
+  {"r18", 18},
+  {"r19", 19},
+  {"r20", 20},
+  {"r21", 21},
+  {"r22", 22},
+  {"r23", 23},
+  {"et", 24},
+  {"bt", 25},
+  {"gp", 26},  /* global pointer */
+  {"sp", 27},  /* stack pointer */
+  {"fp", 28},  /* frame pointer */
+  {"ea", 29},  /* exception return address */
+  {"ba", 30},  /* breakpoint return address */
+  {"ra", 31},  /* return address */
+
+  /* alternative names for special registers */
+  {"r0", 0},
+  {"r1", 1},
+  {"r24", 24},
+  {"r25", 25},
+  {"r26", 26},
+  {"r27", 27},
+  {"r28", 28},
+  {"r29", 29},
+  {"r30", 30},
+  {"r31", 31},
+
+  /* control register names */
+  {"status", 0},
+  {"estatus", 1},
+  {"bstatus", 2},
+  {"ienable", 3},
+  {"ipending", 4},
+  {"cpuid", 5},
+  {"ctl6", 6},
+  {"exception", 7},
+  {"pteaddr", 8},
+  {"tlbacc", 9},
+  {"tlbmisc", 10},
+  {"fstatus", 11},
+  {"badaddr", 12},
+  {"config", 13},
+  {"mpubase", 14},
+  {"mpuacc", 15},
+  {"ctl16", 16},
+  {"ctl17", 17},
+  {"ctl18", 18},
+  {"ctl19", 19},
+  {"ctl20", 20},
+  {"ctl21", 21},
+  {"ctl22", 22},
+  {"ctl23", 23},
+  {"ctl24", 24},
+  {"ctl25", 25},
+  {"ctl26", 26},
+  {"ctl27", 27},
+  {"ctl28", 28},
+  {"ctl29", 29},
+  {"ctl30", 30},
+  {"ctl31", 31},
+
+  /* alternative names for special control registers */
+  {"ctl0", 0},
+  {"ctl1", 1},
+  {"ctl2", 2},
+  {"ctl3", 3},
+  {"ctl4", 4},
+  {"ctl5", 5},
+  {"ctl7", 7},
+  {"ctl8", 8},
+  {"ctl9", 9},
+  {"ctl10", 10},
+  {"ctl11", 11},
+  {"ctl12", 12},
+  {"ctl13", 13},
+  {"ctl14", 14},
+  {"ctl15", 15},
+
+
+  /* coprocessor register names */
+  {"c0", 0},
+  {"c1", 1},
+  {"c2", 2},
+  {"c3", 3},
+  {"c4", 4},
+  {"c5", 5},
+  {"c6", 6},
+  {"c7", 7},
+  {"c8", 8},
+  {"c9", 9},
+  {"c10", 10},
+  {"c11", 11},
+  {"c12", 12},
+  {"c13", 13},
+  {"c14", 14},
+  {"c15", 15},
+  {"c16", 16},
+  {"c17", 17},
+  {"c18", 18},
+  {"c19", 19},
+  {"c20", 20},
+  {"c21", 21},
+  {"c22", 22},
+  {"c23", 23},
+  {"c24", 24},
+  {"c25", 25},
+  {"c26", 26},
+  {"c27", 27},
+  {"c28", 28},
+  {"c29", 29},
+  {"c30", 30},
+  {"c31", 31},
+};
+
+#define NIOS2_NUM_REGS \
+       ((sizeof(nios2_builtin_regs)) / (sizeof(nios2_builtin_regs[0])))
+const int nios2_num_builtin_regs = NIOS2_NUM_REGS;
+
+/* const removed from the following to allow for dynamic extensions to the
+ * built-in instruction set. */
+struct nios2_reg *nios2_regs = (struct nios2_reg *) nios2_builtin_regs;
+int nios2_num_regs = NIOS2_NUM_REGS;
+#undef NIOS2_NUM_REGS
+
+/* overflow message string templates */
+
+const char *overflow_msgs[] = {
+    "call target address 0x%08x out of range 0x%08x to 0x%08x",
+    "branch offset %d out of range %d to %d",
+    "%s offset %d out of range %d to %d",
+    "immediate value %d out of range %d to %d",
+    "immediate value %u out of range %u to %u",
+    "immediate value %u out of range %u to %u",
+    "custom instruction opcode %u out of range %u to %u",
+};
+
+
+
+/*------------------------------------------------------------------------------
+   This is the opcode table used by the New Jersey GNU as, disassembler and GDB
+  ----------------------------------------------------------------------------*/
+
+/*
+       The following letters can appear in the args field of the nios2_opcode
+       structure:
+
+       c - a 5-bit control register index or break opcode
+       d - a 5-bit destination register index
+       s - a 5-bit left source register index
+       t - a 5-bit right source register index
+       i - a 16-bit signed immediate
+       u - a 16-bit unsigned immediate
+
+       j - a 5-bit unsigned immediate
+       k - a 6-bit unsigned immediate
+       l - an 8-bit unsigned immediate
+       m - a 26-bit unsigned immediate
+*/
+
+/* *INDENT-OFF* */
+/* FIXME: Re-format for GNU standards */
+const struct nios2_opcode nios2_builtin_opcodes[] = {
+    /* name, args, args_test, num_args, match, mask, pinfo */
+    {"add", "d,s,t", "d,s,t,E", 3, OP_MATCH_ADD,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"addi", "t,s,i", "t,s,i,E", 3, OP_MATCH_ADDI,
+        OP_MASK_IOP, NIOS2_INSN_ADDI,
+        signed_immed16_overflow },
+    {"subi", "t,s,i", "t,s,i,E", 3, OP_MATCH_ADDI,
+        OP_MASK_IOP, NIOS2_INSN_MACRO,
+        signed_immed16_overflow },
+    {"and", "d,s,t", "d,s,t,E", 3, OP_MATCH_AND,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"andhi", "t,s,u", "t,s,u,E", 3, OP_MATCH_ANDHI,
+        OP_MASK_IOP, 0,
+        unsigned_immed16_overflow },
+    {"andi", "t,s,u", "t,s,u,E", 3, OP_MATCH_ANDI,
+        OP_MASK_IOP, NIOS2_INSN_ANDI,
+        unsigned_immed16_overflow },
+    {"beq", "s,t,o", "s,t,o,E", 3, OP_MATCH_BEQ,
+        OP_MASK_IOP, NIOS2_INSN_CBRANCH,
+        branch_target_overflow },
+    {"bge", "s,t,o", "s,t,o,E", 3, OP_MATCH_BGE,
+        OP_MASK_IOP, NIOS2_INSN_CBRANCH,
+        branch_target_overflow },
+    {"bgeu", "s,t,o", "s,t,o,E", 3, OP_MATCH_BGEU,
+        OP_MASK_IOP, NIOS2_INSN_CBRANCH,
+        branch_target_overflow },
+    {"bgt", "s,t,o", "s,t,o,E", 3, OP_MATCH_BLT,
+        OP_MASK_IOP, NIOS2_INSN_MACRO|NIOS2_INSN_CBRANCH,
+        branch_target_overflow },
+    {"bgtu", "s,t,o", "s,t,o,E", 3, OP_MATCH_BLTU,
+        OP_MASK_IOP, NIOS2_INSN_MACRO|NIOS2_INSN_CBRANCH,
+        branch_target_overflow },
+    {"ble", "s,t,o", "s,t,o,E", 3, OP_MATCH_BGE,
+        OP_MASK_IOP, NIOS2_INSN_MACRO|NIOS2_INSN_CBRANCH,
+        branch_target_overflow },
+    {"bleu", "s,t,o", "s,t,o,E", 3, OP_MATCH_BGEU,
+        OP_MASK_IOP, NIOS2_INSN_MACRO|NIOS2_INSN_CBRANCH,
+        branch_target_overflow },
+    {"blt", "s,t,o", "s,t,o,E", 3, OP_MATCH_BLT,
+        OP_MASK_IOP, NIOS2_INSN_CBRANCH,
+        branch_target_overflow },
+    {"bltu", "s,t,o", "s,t,o,E", 3, OP_MATCH_BLTU,
+        OP_MASK_IOP, NIOS2_INSN_CBRANCH,
+        branch_target_overflow },
+    {"bne", "s,t,o", "s,t,o,E", 3, OP_MATCH_BNE,
+        OP_MASK_IOP, NIOS2_INSN_CBRANCH,
+        branch_target_overflow },
+    {"br", "o", "o,E", 1, OP_MATCH_BR,
+        OP_MASK_IOP, NIOS2_INSN_UBRANCH,
+        branch_target_overflow },
+    {"break", "b", "b,E", 1, OP_MATCH_BREAK,
+        OP_MASK_BREAK, 0,
+        no_overflow },
+    {"bret", "", "E", 0, OP_MATCH_BRET,
+        OP_MASK, 0,
+        no_overflow },
+    {"flushd", "i(s)", "i(s)E", 2, OP_MATCH_FLUSHD,
+        OP_MASK_IOP, 0,
+        signed_immed16_overflow },
+    {"flushda", "i(s)", "i(s)E", 2, OP_MATCH_FLUSHDA,
+        OP_MASK_IOP, 0,
+        signed_immed16_overflow },
+    {"flushi", "s", "s,E", 1, OP_MATCH_FLUSHI,
+        OP_MASK_FLUSHI, 0,
+        no_overflow },
+    {"flushp", "", "E", 0, OP_MATCH_FLUSHP,
+        OP_MASK, 0,
+        no_overflow },
+    {"initd", "i(s)", "i(s)E", 2, OP_MATCH_INITD,
+        OP_MASK_IOP, 0,
+        signed_immed16_overflow },
+    {"initda", "i(s)", "i(s)E", 2, OP_MATCH_INITDA,
+        OP_MASK_IOP, 0,
+        signed_immed16_overflow },
+    {"initi", "s", "s,E", 1, OP_MATCH_INITI,
+        OP_MASK_INITI, 0,
+        no_overflow },
+    {"call", "m", "m,E", 1, OP_MATCH_CALL,
+        OP_MASK_IOP, NIOS2_INSN_CALL,
+        call_target_overflow },
+    {"callr", "s", "s,E", 1, OP_MATCH_CALLR,
+        OP_MASK_CALLR, 0,
+        no_overflow },
+    {"cmpeq", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPEQ,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"cmpeqi", "t,s,i", "t,s,i,E", 3, OP_MATCH_CMPEQI,
+        OP_MASK_IOP, 0,
+        signed_immed16_overflow },
+    {"cmpge", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPGE,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"cmpgei", "t,s,i", "t,s,i,E", 3, OP_MATCH_CMPGEI,
+        OP_MASK_IOP, 0,
+        signed_immed16_overflow },
+    {"cmpgeu", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPGEU,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"cmpgeui", "t,s,u", "t,s,u,E", 3, OP_MATCH_CMPGEUI,
+        OP_MASK_IOP, 0,
+        unsigned_immed16_overflow },
+    {"cmpgt", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPLT,
+        OP_MASK_ROPX | OP_MASK_ROP, NIOS2_INSN_MACRO,
+        no_overflow },
+    {"cmpgti", "t,s,i", "t,s,i,E", 3, OP_MATCH_CMPGEI,
+        OP_MASK_IOP, NIOS2_INSN_MACRO,
+        signed_immed16_overflow },
+    {"cmpgtu", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPLTU,
+        OP_MASK_ROPX | OP_MASK_ROP, NIOS2_INSN_MACRO,
+        no_overflow },
+    {"cmpgtui", "t,s,u", "t,s,u,E", 3, OP_MATCH_CMPGEUI,
+        OP_MASK_IOP, NIOS2_INSN_MACRO,
+        unsigned_immed16_overflow },
+    {"cmple", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPGE,
+        OP_MASK_ROPX | OP_MASK_ROP, NIOS2_INSN_MACRO,
+        no_overflow },
+    {"cmplei", "t,s,i", "t,s,i,E", 3, OP_MATCH_CMPLTI,
+        OP_MASK_IOP, NIOS2_INSN_MACRO,
+        signed_immed16_overflow },
+    {"cmpleu", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPGEU,
+        OP_MASK_ROPX | OP_MASK_ROP, NIOS2_INSN_MACRO,
+        no_overflow },
+    {"cmpleui", "t,s,u", "t,s,u,E", 3, OP_MATCH_CMPLTUI,
+        OP_MASK_IOP, NIOS2_INSN_MACRO,
+        unsigned_immed16_overflow },
+    {"cmplt", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPLT,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"cmplti", "t,s,i", "t,s,i,E", 3, OP_MATCH_CMPLTI,
+        OP_MASK_IOP, 0,
+        signed_immed16_overflow },
+    {"cmpltu", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPLTU,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"cmpltui", "t,s,u", "t,s,u,E", 3, OP_MATCH_CMPLTUI,
+        OP_MASK_IOP, 0,
+        unsigned_immed16_overflow },
+    {"cmpne", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPNE,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"cmpnei", "t,s,i", "t,s,i,E", 3, OP_MATCH_CMPNEI,
+        OP_MASK_IOP, 0,
+        signed_immed16_overflow },
+    {"div", "d,s,t", "d,s,t,E", 3, OP_MATCH_DIV,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"divu", "d,s,t", "d,s,t,E", 3, OP_MATCH_DIVU,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"jmp", "s", "s,E", 1, OP_MATCH_JMP,
+        OP_MASK_JMP, 0,
+        no_overflow },
+    {"jmpi", "m", "m,E", 1, OP_MATCH_JMPI,
+        OP_MASK_IOP, 0,
+        no_overflow },
+    {"ldb", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDB,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"ldbio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDBIO,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"ldbu", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDBU,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"ldbuio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDBUIO,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"ldh", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDH,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"ldhio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDHIO,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"ldhu", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDHU,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"ldhuio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDHUIO,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"ldl", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDL,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"ldw", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDW,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"ldwio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDWIO,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"mov", "d,s", "d,s,E", 2, OP_MATCH_ADD,
+        OP_MASK_RRT|OP_MASK_ROPX|OP_MASK_ROP, NIOS2_INSN_MACRO_MOV,
+        no_overflow },
+    {"movhi", "t,u", "t,u,E", 2, OP_MATCH_ORHI,
+        OP_MASK_IRS|OP_MASK_IOP, NIOS2_INSN_MACRO_MOVI,
+        unsigned_immed16_overflow },
+    {"movui", "t,u", "t,u,E", 2, OP_MATCH_ORI,
+        OP_MASK_IRS|OP_MASK_IOP, NIOS2_INSN_MACRO_MOVI,
+        unsigned_immed16_overflow },
+    {"movi", "t,i", "t,i,E", 2, OP_MATCH_ADDI,
+        OP_MASK_IRS|OP_MASK_IOP, NIOS2_INSN_MACRO_MOVI,
+        signed_immed16_overflow },
+    /* movia expands to two instructions so there is no mask or match */
+    {"movia", "t,o", "t,o,E", 2, OP_MATCH_ORHI,
+        OP_MASK_IOP, NIOS2_INSN_MACRO_MOVIA,
+        no_overflow },
+    {"mul", "d,s,t", "d,s,t,E", 3, OP_MATCH_MUL,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"muli", "t,s,i", "t,s,i,E", 3, OP_MATCH_MULI,
+        OP_MASK_IOP, 0,
+        signed_immed16_overflow },
+    {"mulxss", "d,s,t", "d,s,t,E", 3, OP_MATCH_MULXSS,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"mulxsu", "d,s,t", "d,s,t,E", 3, OP_MATCH_MULXSU,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"mulxuu", "d,s,t", "d,s,t,E", 3, OP_MATCH_MULXUU,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"nextpc", "d", "d,E", 1, OP_MATCH_NEXTPC,
+        OP_MASK_NEXTPC, 0,
+        no_overflow },
+    {"nop", "", "E", 0, OP_MATCH_ADD,
+        OP_MASK, NIOS2_INSN_MACRO_MOV,
+        no_overflow },
+    {"nor", "d,s,t", "d,s,t,E", 3, OP_MATCH_NOR,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"or", "d,s,t", "d,s,t,E", 3, OP_MATCH_OR,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"orhi", "t,s,u", "t,s,u,E", 3, OP_MATCH_ORHI,
+        OP_MASK_IOP, 0,
+        unsigned_immed16_overflow },
+    {"ori", "t,s,u", "t,s,u,E", 3, OP_MATCH_ORI,
+        OP_MASK_IOP, NIOS2_INSN_ORI,
+        unsigned_immed16_overflow },
+    {"rdctl", "d,c", "d,c,E", 2, OP_MATCH_RDCTL,
+        OP_MASK_RDCTL, 0,
+        no_overflow },
+    {"ret", "", "E", 0, OP_MATCH_RET,
+        OP_MASK, 0,
+        no_overflow },
+    {"rol", "d,s,t", "d,s,t,E", 3, OP_MATCH_ROL,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"roli", "d,s,j", "d,s,j,E", 3, OP_MATCH_ROLI,
+        OP_MASK_ROLI, 0,
+        unsigned_immed5_overflow },
+    {"ror", "d,s,t", "d,s,t,E", 3, OP_MATCH_ROR,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"sll", "d,s,t", "d,s,t,E", 3, OP_MATCH_SLL,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"slli", "d,s,j", "d,s,j,E", 3, OP_MATCH_SLLI,
+        OP_MASK_SLLI, 0,
+        unsigned_immed5_overflow },
+    {"sra", "d,s,t", "d,s,t,E", 3, OP_MATCH_SRA,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"srai", "d,s,j", "d,s,j,E", 3, OP_MATCH_SRAI,
+        OP_MASK_SRAI, 0,
+        unsigned_immed5_overflow },
+    {"srl", "d,s,t", "d,s,t,E", 3, OP_MATCH_SRL,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"srli", "d,s,j", "d,s,j,E", 3, OP_MATCH_SRLI,
+        OP_MASK_SRLI, 0,
+        unsigned_immed5_overflow },
+    {"stb", "t,i(s)", "t,i(s)E", 3, OP_MATCH_STB,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"stbio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_STBIO,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"stc", "t,i(s)", "t,i(s)E", 3, OP_MATCH_STC,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"sth", "t,i(s)", "t,i(s)E", 3, OP_MATCH_STH,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"sthio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_STHIO,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"stw", "t,i(s)", "t,i(s)E", 3, OP_MATCH_STW,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"stwio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_STWIO,
+        OP_MASK_IOP, 0,
+        address_offset_overflow },
+    {"sub", "d,s,t", "d,s,t,E", 3, OP_MATCH_SUB,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"sync", "", "E", 0, OP_MATCH_SYNC,
+        OP_MASK_SYNC, 0,
+        no_overflow },
+    {"trap", "", "E", 0, OP_MATCH_TRAP,
+        OP_MASK_TRAP, 0,
+        no_overflow },
+    {"eret", "", "E", 0, OP_MATCH_ERET,
+        OP_MASK, 0,
+        no_overflow },
+    {"custom", "l,d,s,t", "l,d,s,t,E", 4, OP_MATCH_CUSTOM,
+        OP_MASK_ROP, 0,
+        custom_opcode_overflow },
+    {"wrctl", "c,s", "c,s,E", 2, OP_MATCH_WRCTL,
+        OP_MASK_WRCTL, 0,
+        no_overflow },
+    {"xor", "d,s,t", "d,s,t,E", 3, OP_MATCH_XOR,
+        OP_MASK_ROPX | OP_MASK_ROP, 0,
+        no_overflow },
+    {"xorhi", "t,s,u", "t,s,u,E", 3, OP_MATCH_XORHI,
+        OP_MASK_IOP, 0,
+        unsigned_immed16_overflow },
+    {"xori", "t,s,u", "t,s,u,E", 3, OP_MATCH_XORI,
+        OP_MASK_IOP, NIOS2_INSN_XORI,
+        unsigned_immed16_overflow }
+};
+/* *INDENT-ON* */
+
+#define NIOS2_NUM_OPCODES \
+       ((sizeof(nios2_builtin_opcodes)) / (sizeof(nios2_builtin_opcodes[0])))
+const int bfd_nios2_num_builtin_opcodes = NIOS2_NUM_OPCODES;
+
+/* const removed from the following to allow for dynamic extensions to the
+ * built-in instruction set. */
+struct nios2_opcode *nios2_opcodes =
+  (struct nios2_opcode *) nios2_builtin_opcodes;
+int bfd_nios2_num_opcodes = NIOS2_NUM_OPCODES;
+#undef NIOS2_NUM_OPCODES
+/* nios2-dis.c -- Altera New Jersey disassemble routines.
+
+   Copyright (C) 2003
+   by Nigel Gray (ngray@altera.com).
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+1, or (at your option) any later version.
+
+GDB, GAS, and the GNU binutils are distributed in the hope that they
+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 file; see the file COPYING.  If not,
+see <http://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include "dis-asm.h"
+/*#include "nios2.h"*/
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+/* length of New Jersey instruction in bytes */
+#define INSNLEN 4
+
+/* helper function prototypes */
+static int nios2_disassemble(bfd_vma, unsigned long, disassemble_info *);
+static void nios2_init_opcode_hash(void);
+
+
+static int nios2_print_insn_arg(const char *argptr, unsigned long opcode,
+                                bfd_vma address, disassemble_info *info);
+
+
+/* print_insn_nios2 is the main disassemble function for New Jersey.
+   The function diassembler(abfd) (source in disassemble.c) returns a
+   pointer to this either print_insn_big_nios2 or
+   print_insn_little_nios2, which in turn call this function, when the
+   bfd machine type is New Jersey. print_insn_nios2 reads the
+   instruction word at the address given, and prints the disassembled
+   instruction on the stream info->stream using info->fprintf_func. */
+
+int
+print_insn_nios2(bfd_vma address, disassemble_info *info)
+{
+    /* buffer into which the instruction bytes are written */
+    bfd_byte buffer[INSNLEN];
+    /* used to indicate return status from function calls */
+    int status;
+
+    assert(info != NULL);
+
+    status = (*info->read_memory_func) (address, buffer, INSNLEN, info);
+    if (status == 0) {
+        unsigned long insn;
+        insn = (unsigned long) bfd_getl32(buffer);
+        status = nios2_disassemble(address, insn, info);
+    } else {
+        (*info->memory_error_func) (status, address, info);
+        status = -1;
+    }
+    return status;
+}
+
+/* Data structures used by the opcode hash table */
+
+typedef struct _nios2_opcode_hash {
+    const struct nios2_opcode *opcode;
+    struct _nios2_opcode_hash *next;
+} nios2_opcode_hash;
+
+static bfd_boolean nios2_hash_init;
+static nios2_opcode_hash *nios2_hash[(OP_MASK_OP) + 1];
+
+/* separate hash table for pseudo-ops */
+static nios2_opcode_hash *nios2_ps_hash[(OP_MASK_OP) + 1];
+
+/* Function to initialize the opcode hash table */
+
+void
+nios2_init_opcode_hash(void)
+{
+    unsigned int i;
+    register const struct nios2_opcode *op;
+    nios2_opcode_hash *tmp_hash;
+
+    for (i = 0; i <= OP_MASK_OP; ++i) {
+        nios2_hash[0] = NULL;
+    }
+    for (i = 0; i <= OP_MASK_OP; i++) {
+        for (op = nios2_opcodes; op < &nios2_opcodes[NUMOPCODES]; op++) {
+            if ((op->pinfo & NIOS2_INSN_MACRO) == NIOS2_INSN_MACRO) {
+                if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP) &&
+                    (op->pinfo &
+                     (NIOS2_INSN_MACRO_MOV | NIOS2_INSN_MACRO_MOVI) &
+                     0x7fffffff) != 0) {
+                    tmp_hash = nios2_ps_hash[i];
+                    if (tmp_hash == NULL) {
+                        tmp_hash =
+                            (nios2_opcode_hash *)
+                            malloc(sizeof(nios2_opcode_hash));
+                        nios2_ps_hash[i] = tmp_hash;
+                    } else {
+                        while (tmp_hash->next != NULL) {
+                            tmp_hash = tmp_hash->next;
+                        }
+                        tmp_hash->next =
+                            (nios2_opcode_hash *)
+                            malloc(sizeof(nios2_opcode_hash));
+                        tmp_hash = tmp_hash->next;
+                    }
+                    if (tmp_hash == NULL) {
+                        fprintf(stderr,
+                            "error allocating memory...broken disassembler\n");
+                        abort();
+                    }
+                    tmp_hash->opcode = op;
+                    tmp_hash->next = NULL;
+                }
+            } else if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP)) {
+                tmp_hash = nios2_hash[i];
+                if (tmp_hash == NULL) {
+                    tmp_hash =
+                        (nios2_opcode_hash *)malloc(sizeof(nios2_opcode_hash));
+                    nios2_hash[i] = tmp_hash;
+                } else {
+                    while (tmp_hash->next != NULL) {
+                        tmp_hash = tmp_hash->next;
+                    }
+                    tmp_hash->next =
+                        (nios2_opcode_hash *)malloc(sizeof(nios2_opcode_hash));
+                    tmp_hash = tmp_hash->next;
+                }
+                if (tmp_hash == NULL) {
+                    fprintf(stderr,
+                            "error allocating memory...broken disassembler\n");
+                    abort();
+                }
+                tmp_hash->opcode = op;
+                tmp_hash->next = NULL;
+            }
+        }
+    }
+    nios2_hash_init = 1;
+#ifdef DEBUG_HASHTABLE
+    for (i = 0; i <= OP_MASK_OP; ++i) {
+        printf("index: 0x%02X    ops: ", i);
+        tmp_hash = nios2_hash[i];
+        if (tmp_hash != NULL) {
+            while (tmp_hash != NULL) {
+                printf("%s ", tmp_hash->opcode->name);
+                tmp_hash = tmp_hash->next;
+            }
+        }
+        printf("\n");
+    }
+
+    for (i = 0; i <= OP_MASK_OP; ++i) {
+        printf("index: 0x%02X    ops: ", i);
+        tmp_hash = nios2_ps_hash[i];
+        if (tmp_hash != NULL) {
+            while (tmp_hash != NULL) {
+                printf("%s ", tmp_hash->opcode->name);
+                tmp_hash = tmp_hash->next;
+            }
+        }
+        printf("\n");
+    }
+#endif
+}
+
+/* Function which returns a pointer to an nios2_opcode struct for
+   a given instruction opcode, or NULL if there is an error */
+
+const struct nios2_opcode *
+nios2_find_opcode_hash(unsigned long opcode)
+{
+    nios2_opcode_hash *entry;
+
+    /* Build a hash table to shorten the search time. */
+    if (!nios2_hash_init) {
+        nios2_init_opcode_hash();
+    }
+
+    /* first look in the pseudo-op hashtable */
+    entry = nios2_ps_hash[(opcode >> OP_SH_OP) & OP_MASK_OP];
+
+    /* look for a match and if we get one, this is the instruction we decode */
+    while (entry != NULL) {
+        if ((entry->opcode->match) == (opcode & entry->opcode->mask)) {
+            return entry->opcode;
+        } else {
+            entry = entry->next;
+        }
+    }
+
+    /* if we haven't yet returned, then we need to look in the main
+       hashtable */
+    entry = nios2_hash[(opcode >> OP_SH_OP) & OP_MASK_OP];
+
+    if (entry == NULL) {
+        return NULL;
+    }
+
+    while (entry != NULL) {
+        if ((entry->opcode->match) == (opcode & entry->opcode->mask)) {
+            return entry->opcode;
+        } else {
+            entry = entry->next;
+        }
+    }
+
+    return NULL;
+}
+
+/* nios2_disassemble does all the work of disassembling a New Jersey
+       instruction opcode */
+
+int
+nios2_disassemble(bfd_vma address, unsigned long opcode,
+                  disassemble_info *info)
+{
+    const struct nios2_opcode *op;
+    const char *argstr;
+
+    info->bytes_per_line = INSNLEN;
+    info->bytes_per_chunk = INSNLEN;
+    info->display_endian = info->endian;
+    info->insn_info_valid = 1;
+    info->branch_delay_insns = 0;
+    info->data_size = 0;
+    info->insn_type = dis_nonbranch;
+    info->target = 0;
+    info->target2 = 0;
+
+    (*info->fprintf_func) (info->stream, "%08x %08x   ",
+                           (int)address, (int)opcode);
+
+    /* Find the major opcode and use this to disassemble
+       the instruction and its arguments */
+    op = nios2_find_opcode_hash(opcode);
+
+    if (op != NULL) {
+        bfd_boolean is_nop = FALSE;
+        if (op->pinfo == NIOS2_INSN_MACRO_MOV) {
+            /* check for mov r0, r0 and if it is
+               change to nop */
+            int dst, src;
+            dst = GET_INSN_FIELD(RRD, opcode);
+            src = GET_INSN_FIELD(RRS, opcode);
+            if (dst == 0 && src == 0) {
+                (*info->fprintf_func) (info->stream, "nop");
+                is_nop = TRUE;
+            } else {
+                (*info->fprintf_func) (info->stream, "%s", op->name);
+            }
+        } else {
+          (*info->fprintf_func) (info->stream, "%s", op->name);
+        }
+
+        if (!is_nop) {
+            argstr = op->args;
+            if (argstr != NULL && *argstr != '\0') {
+                (*info->fprintf_func) (info->stream, "\t");
+                while (*argstr != '\0') {
+                    nios2_print_insn_arg(argstr, opcode, address, info);
+                    ++argstr;
+                }
+            }
+        }
+    } else {
+        /* Handle undefined instructions. */
+        info->insn_type = dis_noninsn;
+        (*info->fprintf_func) (info->stream, "0x%x", (int)opcode);
+    }
+    /* this tells the caller how far to advance the program counter */
+    return INSNLEN;
+}
+
+/* The function nios2_print_insn_arg uses the character pointed
+   to by argptr to determine how it print the next token or separator
+   character in the arguments to an instruction */
+int
+nios2_print_insn_arg(const char *argptr,
+                     unsigned long opcode, bfd_vma address,
+                     disassemble_info *info)
+{
+    unsigned long i = 0;
+    unsigned long reg_base;
+
+    assert(argptr != NULL);
+    assert(info != NULL);
+
+    switch (*argptr) {
+    case ',':
+    case '(':
+    case ')':
+        (*info->fprintf_func) (info->stream, "%c", *argptr);
+        break;
+    case 'd':
+        i = GET_INSN_FIELD(RRD, opcode);
+
+        if (GET_INSN_FIELD(OP, opcode) == OP_MATCH_CUSTOM
+            && GET_INSN_FIELD(CUSTOM_C, opcode) == 0) {
+            reg_base = COPROCREGBASE;
+        } else {
+            reg_base = 0;
+        }
+
+        if (i < NUMREGNAMES) {
+            (*info->fprintf_func) (info->stream, "%s",
+                                   nios2_regs[i + reg_base].name);
+        } else {
+            (*info->fprintf_func) (info->stream, "unknown");
+        }
+        break;
+    case 's':
+        i = GET_INSN_FIELD(RRS, opcode);
+
+        if (GET_INSN_FIELD(OP, opcode) == OP_MATCH_CUSTOM
+            && GET_INSN_FIELD(CUSTOM_A, opcode) == 0) {
+            reg_base = COPROCREGBASE;
+        } else {
+            reg_base = 0;
+        }
+
+        if (i < NUMREGNAMES) {
+            (*info->fprintf_func) (info->stream, "%s",
+                                   nios2_regs[i + reg_base].name);
+        } else {
+            (*info->fprintf_func) (info->stream, "unknown");
+        }
+        break;
+    case 't':
+        i = GET_INSN_FIELD(RRT, opcode);
+
+        if (GET_INSN_FIELD(OP, opcode) == OP_MATCH_CUSTOM
+            && GET_INSN_FIELD(CUSTOM_B, opcode) == 0) {
+            reg_base = COPROCREGBASE;
+        } else {
+            reg_base = 0;
+        }
+
+        if (i < NUMREGNAMES) {
+            (*info->fprintf_func) (info->stream, "%s",
+                                   nios2_regs[i + reg_base].name);
+        } else {
+            (*info->fprintf_func) (info->stream, "unknown");
+        }
+        break;
+    case 'i':
+        /* 16-bit signed immediate */
+        i = (signed) (GET_INSN_FIELD(IMM16, opcode) << 16) >> 16;
+        (*info->fprintf_func) (info->stream, "%d", (int)i);
+        break;
+    case 'u':
+        /* 16-bit unsigned immediate */
+        i = GET_INSN_FIELD(IMM16, opcode);
+        (*info->fprintf_func) (info->stream, "%d", (int)i);
+        break;
+    case 'o':
+        /* 16-bit signed immediate address offset */
+        i = (signed) (GET_INSN_FIELD(IMM16, opcode) << 16) >> 16;
+        address = address + 4 + i;        /* NG changed to byte offset 1/9/03 */
+        (*info->print_address_func) (address, info);
+        break;
+    case 'p':
+        /* 5-bit unsigned immediate */
+        i = GET_INSN_FIELD(CACHE_OPX, opcode);
+        (*info->fprintf_func) (info->stream, "%d", (int)i);
+        break;
+    case 'j':
+        /* 5-bit unsigned immediate */
+        i = GET_INSN_FIELD(IMM5, opcode);
+        (*info->fprintf_func) (info->stream, "%d", (int)i);
+        break;
+    case 'l':
+        /* 8-bit unsigned immediate */
+        /* FIXME - not yet implemented */
+        i = GET_INSN_FIELD(CUSTOM_N, opcode);
+        (*info->fprintf_func) (info->stream, "%u", (int)i);
+        break;
+    case 'm':
+        /* 26-bit unsigned immediate */
+        i = GET_INSN_FIELD(IMM26, opcode);
+        /* this translates to an address because its only used in
+           call instructions */
+        address = (address & 0xf0000000) | (i << 2);
+        (*info->print_address_func) (address, info);
+        break;
+    case 'c':
+        i = GET_INSN_FIELD(IMM5, opcode);        /* ctrl register index */
+        (*info->fprintf_func) (info->stream, "%s",
+                               nios2_regs[CTLREGBASE + i].name);
+        break;
+    case 'b':
+        i = GET_INSN_FIELD(IMM5, opcode);
+        (*info->fprintf_func) (info->stream, "%d", (int)i);
+        break;
+    default:
+        (*info->fprintf_func) (info->stream, "unknown");
+        break;
+    }
+    return 0;
+}
-- 
1.7.10.4

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

* [Qemu-devel] [PATCH 3/4] Altera: Add support for devices needed to boot Linux on NiosII. (v2)
  2012-11-11  4:18 [Qemu-devel] [PATCH 0/4] Altera NiosII Support (v2) crwulff
  2012-11-11  4:18 ` [Qemu-devel] [PATCH 1/4] NiosII: Add support for the Altera NiosII soft-core CPU. (v2) crwulff
  2012-11-11  4:18 ` [Qemu-devel] [PATCH 2/4] NiosII: Disassembly of NiosII instructions ported from GDB. (v2) crwulff
@ 2012-11-11  4:18 ` crwulff
  2012-11-11  4:18 ` [Qemu-devel] [PATCH 4/4] NiosII: Build system and documentation integration crwulff
  3 siblings, 0 replies; 5+ messages in thread
From: crwulff @ 2012-11-11  4:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: Chris Wulff

From: Chris Wulff <crwulff@gmail.com>

Signed-off-by: Chris Wulff <crwulff@gmail.com>
---
 hw/Makefile.objs   |    5 ++
 hw/altera_timer.c  |  207 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/altera_uart.c   |  217 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/altera_vic.c    |  194 ++++++++++++++++++++++++++++++++++++++++++++++
 hw/nios2.h         |   52 +++++++++++++
 hw/nios2_pic_cpu.c |   39 ++++++++++
 6 files changed, 714 insertions(+)
 create mode 100644 hw/altera_timer.c
 create mode 100644 hw/altera_uart.c
 create mode 100644 hw/altera_vic.c
 create mode 100644 hw/nios2.h
 create mode 100644 hw/nios2_pic_cpu.c

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index af4ab0c..32275a5 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -69,6 +69,11 @@ common-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o
 common-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o
 common-obj-$(CONFIG_XILINX_AXI) += stream.o
 
+# Altera devices
+common-obj-$(CONFIG_ALTERA) += altera_vic.o
+common-obj-$(CONFIG_ALTERA) += altera_uart.o
+common-obj-$(CONFIG_ALTERA) += altera_timer.o
+
 # PKUnity SoC devices
 common-obj-$(CONFIG_PUV3) += puv3_intc.o
 common-obj-$(CONFIG_PUV3) += puv3_ost.o
diff --git a/hw/altera_timer.c b/hw/altera_timer.c
new file mode 100644
index 0000000..9c31e59
--- /dev/null
+++ b/hw/altera_timer.c
@@ -0,0 +1,207 @@
+/*
+ * QEMU model of the Altera timer.
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 "sysbus.h"
+#include "sysemu.h"
+#include "ptimer.h"
+
+#define R_STATUS     0
+#define R_CONTROL    1
+#define R_PERIODL    2
+#define R_PERIODH    3
+#define R_SNAPL      4
+#define R_SNAPH      5
+#define R_MAX        6
+
+#define STATUS_TO  0x0001
+#define STATUS_RUN 0x0002
+
+#define CONTROL_ITO   0x0001
+#define CONTROL_CONT  0x0002
+#define CONTROL_START 0x0004
+#define CONTROL_STOP  0x0008
+
+typedef struct AlteraTimer {
+    SysBusDevice  busdev;
+    MemoryRegion  mmio;
+    qemu_irq      irq;
+    uint32_t      freq_hz;
+    QEMUBH       *bh;
+    ptimer_state *ptimer;
+    uint32_t      regs[R_MAX];
+} AlteraTimer;
+
+static uint64_t timer_read(void *opaque, hwaddr addr,
+                           unsigned int size)
+{
+    AlteraTimer *t = opaque;
+    uint64_t r = 0;
+
+    addr >>= 2;
+    addr &= 0x7;
+    switch (addr) {
+    case R_STATUS:
+        r = t->regs[R_STATUS];
+        break;
+
+    default:
+        if (addr < ARRAY_SIZE(t->regs)) {
+            r = t->regs[addr];
+        }
+        break;
+    }
+
+    return r;
+}
+
+static void timer_start(AlteraTimer *t)
+{
+    ptimer_stop(t->ptimer);
+    ptimer_set_count(t->ptimer, (t->regs[R_PERIODH]<<16) | t->regs[R_PERIODL]);
+    ptimer_run(t->ptimer, 1);
+}
+
+static inline int timer_irq_state(AlteraTimer *t)
+{
+    return (t->regs[R_STATUS] & t->regs[R_CONTROL] & CONTROL_ITO) ? 1 : 0;
+}
+
+static void timer_write(void *opaque, hwaddr addr,
+                        uint64_t val64, unsigned int size)
+{
+    AlteraTimer *t = opaque;
+    uint32_t value = val64;
+    uint32_t count = 0;
+    int irqState = timer_irq_state(t);
+
+    addr >>= 2;
+    addr &= 0x7;
+    switch (addr) {
+    case R_STATUS:
+        /* Writing zero clears the timeout */
+        t->regs[R_STATUS] &= ~STATUS_TO;
+        break;
+
+    case R_CONTROL:
+        t->regs[R_CONTROL] = value & (CONTROL_ITO | CONTROL_CONT);
+        if ((value & CONTROL_START) &&
+            ((t->regs[R_STATUS] & STATUS_RUN) == 0)) {
+            timer_start(t);
+        }
+        if ((value & CONTROL_STOP) && (t->regs[R_STATUS] & STATUS_RUN)) {
+            ptimer_stop(t->ptimer);
+        }
+        break;
+
+    case R_PERIODL:
+    case R_PERIODH:
+        t->regs[addr] = value & 0xFFFF;
+        if (t->regs[R_STATUS] & STATUS_RUN) {
+            timer_start(t);
+        }
+        break;
+
+    case R_SNAPL:
+    case R_SNAPH:
+        count = ptimer_get_count(t->ptimer);
+        t->regs[R_SNAPL] = count & 0xFFFF;
+        t->regs[R_SNAPH] = (count>>16) & 0xFFFF;
+        break;
+
+    default:
+        if (addr < ARRAY_SIZE(t->regs)) {
+            t->regs[addr] = value;
+        }
+        break;
+    }
+
+    if (irqState != timer_irq_state(t)) {
+        qemu_set_irq(t->irq, timer_irq_state(t));
+    }
+}
+
+static const MemoryRegionOps timer_ops = {
+    .read = timer_read,
+    .write = timer_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4
+    }
+};
+
+static void timer_hit(void *opaque)
+{
+    AlteraTimer *t = opaque;
+
+    t->regs[R_STATUS] |= STATUS_TO;
+
+    if (t->regs[R_CONTROL] & CONTROL_CONT) {
+        timer_start(t);
+    }
+
+    qemu_set_irq(t->irq, timer_irq_state(t));
+}
+
+static int altera_timer_init(SysBusDevice *dev)
+{
+    AlteraTimer *t = FROM_SYSBUS(typeof(*t), dev);
+
+    assert(t->freq_hz != 0);
+
+    sysbus_init_irq(dev, &t->irq);
+
+    t->bh = qemu_bh_new(timer_hit, t);
+    t->ptimer = ptimer_init(t->bh);
+    ptimer_set_freq(t->ptimer, t->freq_hz);
+
+    memory_region_init_io(&t->mmio, &timer_ops, t, "ALTR.timer",
+                          R_MAX * sizeof(uint32_t));
+    sysbus_init_mmio(dev, &t->mmio);
+    return 0;
+}
+
+static Property altera_timer_properties[] = {
+    DEFINE_PROP_UINT32("clock-frequency", AlteraTimer, freq_hz, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void altera_timer_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = altera_timer_init;
+    dc->props = altera_timer_properties;
+}
+
+static const TypeInfo altera_timer_info = {
+    .name          = "ALTR.timer",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AlteraTimer),
+    .class_init    = altera_timer_class_init,
+};
+
+static void altera_timer_register(void)
+{
+    type_register_static(&altera_timer_info);
+}
+
+type_init(altera_timer_register)
diff --git a/hw/altera_uart.c b/hw/altera_uart.c
new file mode 100644
index 0000000..862c99e
--- /dev/null
+++ b/hw/altera_uart.c
@@ -0,0 +1,217 @@
+/*
+ * QEMU model of the Altera uart.
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 "sysbus.h"
+#include "qemu-char.h"
+
+#define R_RXDATA        0
+#define R_TXDATA        1
+#define R_STATUS        2
+#define R_CONTROL       3
+#define R_DIVISOR       4
+#define R_ENDOFPACKET   5
+#define R_MAX           6
+
+#define STATUS_PE        0x0001
+#define STATUS_FE        0x0002
+#define STATUS_BRK       0x0004
+#define STATUS_ROE       0x0008
+#define STATUS_TOE       0x0010
+#define STATUS_TMT       0x0020
+#define STATUS_TRDY      0x0040
+#define STATUS_RRDY      0x0080
+#define STATUS_E         0x0100
+#define STATUS_DTCS      0x0400
+#define STATUS_CTS       0x0800
+#define STATUS_EOP       0x1000
+
+#define CONTROL_IPE      0x0001
+#define CONTROL_IFE      0x0002
+#define CONTROL_IBRK     0x0004
+#define CONTROL_IROE     0x0008
+#define CONTROL_ITOE     0x0010
+#define CONTROL_ITMT     0x0020
+#define CONTROL_ITRDY    0x0040
+#define CONTROL_IRRDY    0x0080
+#define CONTROL_IE       0x0100
+#define CONTROL_TBRK     0x0200
+#define CONTROL_IDTCS    0x0400
+#define CONTROL_RTS      0x0800
+#define CONTROL_IEOP     0x1000
+
+typedef struct AlteraUART {
+    SysBusDevice busdev;
+    MemoryRegion mmio;
+    CharDriverState *chr;
+    qemu_irq irq;
+
+    uint32_t regs[R_MAX];
+} AlteraUART;
+
+static void uart_update_irq(AlteraUART *s)
+{
+    unsigned int irq;
+
+    irq = (s->regs[R_STATUS] & s->regs[R_CONTROL] &
+          (STATUS_PE | STATUS_FE | STATUS_BRK | STATUS_ROE | STATUS_TOE |
+           STATUS_TMT | STATUS_TRDY | STATUS_RRDY | STATUS_E | STATUS_DTCS));
+    irq = (irq == 0) ? 0 : 1;
+    qemu_set_irq(s->irq, irq);
+}
+
+static uint64_t uart_read(void *opaque, hwaddr addr,
+                          unsigned int size)
+{
+    AlteraUART *s = opaque;
+    uint32_t r = 0;
+    addr >>= 2;
+    addr &= 0x7;
+    switch (addr) {
+    case R_RXDATA:
+        r = s->regs[R_RXDATA];
+        s->regs[R_STATUS] &= ~STATUS_RRDY;
+        uart_update_irq(s);
+        break;
+
+    case R_STATUS:
+        r = s->regs[R_STATUS];
+        s->regs[R_STATUS] &= ~(STATUS_PE | STATUS_FE | STATUS_BRK |
+                               STATUS_ROE | STATUS_TOE | STATUS_E |
+                               STATUS_DTCS);
+        uart_update_irq(s);
+        break;
+
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            r = s->regs[addr];
+        }
+        break;
+    }
+
+    return r;
+}
+
+static void uart_write(void *opaque, hwaddr addr,
+                       uint64_t val64, unsigned int size)
+{
+    AlteraUART *s = opaque;
+    uint32_t value = val64;
+    unsigned char ch = value;
+
+    addr >>= 2;
+    addr &= 0x7;
+
+    switch (addr) {
+    case R_TXDATA:
+        if (s->chr) {
+            qemu_chr_fe_write(s->chr, &ch, 1);
+        }
+
+        s->regs[addr] = value;
+        break;
+
+    case R_RXDATA:
+    case R_STATUS:
+        /* No writeable bits */
+        break;
+
+    default:
+        s->regs[addr] = value;
+        break;
+    }
+    uart_update_irq(s);
+}
+
+static void uart_rx(void *opaque, const uint8_t *buf, int size)
+{
+    AlteraUART *s = opaque;
+
+    s->regs[R_RXDATA] = *buf;
+    s->regs[R_STATUS] |= STATUS_RRDY;
+
+    uart_update_irq(s);
+}
+
+static int uart_can_rx(void *opaque)
+{
+    AlteraUART *s = opaque;
+    return ((s->regs[R_STATUS] & STATUS_RRDY) == 0);
+}
+
+static void uart_event(void *opaque, int event)
+{
+}
+
+static const MemoryRegionOps uart_ops = {
+    .read = uart_read,
+    .write = uart_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4
+    }
+};
+
+static int altera_uart_init(SysBusDevice *dev)
+{
+    AlteraUART *s = FROM_SYSBUS(typeof(*s), dev);
+
+    s->regs[R_STATUS] = STATUS_TMT | STATUS_TRDY; /* Always ready to tx */
+
+    sysbus_init_irq(dev, &s->irq);
+
+    memory_region_init_io(&s->mmio, &uart_ops, s,
+                          "ALTR.uart", R_MAX * sizeof(uint32_t));
+    sysbus_init_mmio(dev, &s->mmio);
+
+    s->chr = qemu_char_get_next_serial();
+    if (s->chr) {
+        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+    }
+
+    return 0;
+}
+
+static Property altera_uart_properties[] = {
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void altera_uart_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = altera_uart_init;
+    dc->props = altera_uart_properties;
+}
+
+static const TypeInfo altera_uart_info = {
+    .name          = "ALTR.uart",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AlteraUART),
+    .class_init    = altera_uart_class_init,
+};
+
+static void altera_uart_register(void)
+{
+    type_register_static(&altera_uart_info);
+}
+
+type_init(altera_uart_register)
diff --git a/hw/altera_vic.c b/hw/altera_vic.c
new file mode 100644
index 0000000..9f6f8b9
--- /dev/null
+++ b/hw/altera_vic.c
@@ -0,0 +1,194 @@
+/*
+ * QEMU Altera Vectored Interrupt Controller.
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 "sysbus.h"
+#include "hw.h"
+
+#define R_INT_CONFIG_0      0
+#define R_INT_ENABLE       32
+#define R_INT_ENABLE_SET   33
+#define R_INT_ENABLE_CLR   34
+#define R_INT_PENDING      35
+#define R_INT_RAW_STATUS   36
+#define R_SW_INTERRUPT     37
+#define R_SW_INTERRUPT_SET 38
+#define R_SW_INTERRUPT_CLR 39
+#define R_VIC_CONFIG       40
+#define R_VIC_STATUS       41
+#define R_VEC_TBL_BASE     42
+#define R_VEC_TBL_ADDR     43
+#define R_MAX              44
+
+typedef struct AlteraVIC {
+    SysBusDevice busdev;
+    MemoryRegion mmio;
+    qemu_irq parent_irq;
+
+    /* Runtime control registers.  */
+    uint32_t regs[R_MAX];
+} AlteraVIC;
+
+static void update_irq(AlteraVIC *pv)
+{
+    uint32_t i;
+    pv->regs[R_INT_PENDING] = (pv->regs[R_INT_RAW_STATUS] |
+                               pv->regs[R_SW_INTERRUPT]) &
+                              pv->regs[R_INT_ENABLE];
+
+    for (i = 0; i < 32; i++) {
+        if (pv->regs[R_INT_PENDING] & (1 << i)) {
+            break;
+        }
+    }
+    if (i == 32) {
+        pv->regs[R_VEC_TBL_ADDR] = 0;
+        pv->regs[R_VIC_STATUS] = 0;
+        qemu_irq_lower(pv->parent_irq);
+    } else {
+        pv->regs[R_VEC_TBL_ADDR] = pv->regs[R_VEC_TBL_BASE] +
+                                   i * (4 << (pv->regs[R_VIC_CONFIG] & 7));
+        pv->regs[R_VIC_STATUS] = 0x80000000 | i;
+        qemu_irq_raise(pv->parent_irq);
+    }
+}
+
+static uint64_t pic_read(void *opaque, hwaddr addr,
+                         unsigned int size)
+{
+    AlteraVIC *pv = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    if (addr < R_MAX) {
+        r = pv->regs[addr];
+    }
+
+    return r;
+}
+
+static void pic_write(void *opaque, hwaddr addr,
+                      uint64_t val64, unsigned int size)
+{
+    AlteraVIC *pv = opaque;
+    uint32_t value = val64;
+
+    addr >>= 2;
+    if (addr < R_INT_ENABLE) {
+        /* R_INT_CONFIG_XX */
+        pv->regs[addr] = value & 0x00001FFF;
+    } else {
+        switch (addr) {
+        case R_INT_PENDING:
+        case R_INT_RAW_STATUS:
+        case R_VIC_STATUS:
+        case R_VEC_TBL_ADDR:
+            /* read only */
+            break;
+
+        case R_INT_ENABLE_SET:
+            pv->regs[R_INT_ENABLE] |= value;
+            break;
+
+        case R_SW_INTERRUPT_SET:
+            pv->regs[R_SW_INTERRUPT] |= value;
+            break;
+
+        case R_INT_ENABLE_CLR:
+            pv->regs[R_INT_ENABLE] &= ~value;
+            break;
+
+        case R_SW_INTERRUPT_CLR:
+            pv->regs[R_SW_INTERRUPT] &= ~value;
+            break;
+
+        case R_VIC_CONFIG:
+            pv->regs[addr] = value & 0x0000000F;
+            break;
+
+        default:
+            if (addr < ARRAY_SIZE(pv->regs)) {
+                pv->regs[addr] = value;
+            }
+            break;
+        }
+    }
+    update_irq(pv);
+}
+
+static const MemoryRegionOps pic_ops = {
+    .read = pic_read,
+    .write = pic_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    }
+};
+
+static void irq_handler(void *opaque, int irq, int level)
+{
+    AlteraVIC *pv = opaque;
+
+    pv->regs[R_INT_RAW_STATUS] &= ~(1 << irq);
+    pv->regs[R_INT_RAW_STATUS] |= level << irq;
+
+    update_irq(pv);
+}
+
+static int altera_vic_init(SysBusDevice *dev)
+{
+    AlteraVIC *pv = FROM_SYSBUS(typeof(*pv), dev);
+
+    qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
+    sysbus_init_irq(dev, &pv->parent_irq);
+
+    memset(pv->regs, 0, sizeof(uint32_t) * R_MAX);
+    memory_region_init_io(&pv->mmio, &pic_ops, pv,
+                          "ALTR.vic", R_MAX * sizeof(uint32_t));
+    sysbus_init_mmio(dev, &pv->mmio);
+    return 0;
+}
+
+static Property altera_vic_properties[] = {
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void altera_vic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = altera_vic_init;
+    dc->props = altera_vic_properties;
+}
+
+static const TypeInfo altera_vic_info = {
+    .name          = "ALTR.vic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AlteraVIC),
+    .class_init    = altera_vic_class_init,
+};
+
+static void altera_vic_register(void)
+{
+    type_register_static(&altera_vic_info);
+}
+
+type_init(altera_vic_register)
diff --git a/hw/nios2.h b/hw/nios2.h
new file mode 100644
index 0000000..4f1325a
--- /dev/null
+++ b/hw/nios2.h
@@ -0,0 +1,52 @@
+/*
+ * Altera Nios II CPU interrupt controllers
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 _NIOS2_H_INCLUDED_
+#define _NIOS2_H_INCLUDED_
+
+#include "sysbus.h"
+
+qemu_irq *nios2_pic_init_cpu(Nios2CPU *cpu);
+
+static inline DeviceState *
+altera_vic_create(hwaddr base, qemu_irq irq, int kind_of_intr)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "altera,vic");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    return dev;
+}
+
+static inline DeviceState *
+altera_iic_create(Nios2CPU *cpu, qemu_irq irq, int kind_of_intr)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "altera,iic");
+    qdev_prop_set_ptr(dev, "cpu", cpu);
+    qdev_init_nofail(dev);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    return dev;
+}
+
+#endif /* _NIOS2_H_INCLUDED_ */
diff --git a/hw/nios2_pic_cpu.c b/hw/nios2_pic_cpu.c
new file mode 100644
index 0000000..5b6d05b
--- /dev/null
+++ b/hw/nios2_pic_cpu.c
@@ -0,0 +1,39 @@
+/*
+ * QEMU Altera Nios II CPU interrupt wrapper logic.
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * 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 "hw.h"
+#include "nios2.h"
+
+static void nios2_pic_cpu_handler(void *opaque, int irq, int level)
+{
+    Nios2CPU *cpu = opaque;
+    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
+
+    if (level) {
+        cpu_interrupt(&cpu->env, type);
+    } else {
+        cpu_reset_interrupt(&cpu->env, type);
+    }
+}
+
+qemu_irq *nios2_pic_init_cpu(Nios2CPU *cpu)
+{
+    return qemu_allocate_irqs(nios2_pic_cpu_handler, cpu, 2);
+}
-- 
1.7.10.4

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

* [Qemu-devel] [PATCH 4/4] NiosII: Build system and documentation integration.
  2012-11-11  4:18 [Qemu-devel] [PATCH 0/4] Altera NiosII Support (v2) crwulff
                   ` (2 preceding siblings ...)
  2012-11-11  4:18 ` [Qemu-devel] [PATCH 3/4] Altera: Add support for devices needed to boot Linux on NiosII. (v2) crwulff
@ 2012-11-11  4:18 ` crwulff
  3 siblings, 0 replies; 5+ messages in thread
From: crwulff @ 2012-11-11  4:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: Chris Wulff

From: Chris Wulff <crwulff@gmail.com>

Signed-off-by: Chris Wulff <crwulff@gmail.com>
---
 MAINTAINERS                          |    5 +++++
 arch_init.c                          |    2 ++
 arch_init.h                          |    1 +
 configure                            |   11 +++++++++++
 cpu-exec.c                           |   12 +++++++++++-
 default-configs/nios2-linux-user.mak |    1 +
 default-configs/nios2-softmmu.mak    |    5 +++++
 dis-asm.h                            |    3 +++
 disas.c                              |    3 +++
 elf.h                                |    2 ++
 exec.c                               |    6 ++++--
 gdbstub.c                            |   29 +++++++++++++++++++++++++++++
 hw/nios2/Makefile.objs               |    3 +++
 linux-user/elfload.c                 |   29 +++++++++++++++++++++++++++++
 monitor.c                            |    5 +++--
 qapi-schema.json                     |    2 +-
 qemu-doc.texi                        |    3 +++
 17 files changed, 116 insertions(+), 6 deletions(-)
 create mode 100644 default-configs/nios2-linux-user.mak
 create mode 100644 default-configs/nios2-softmmu.mak
 create mode 100644 hw/nios2/Makefile.objs

diff --git a/MAINTAINERS b/MAINTAINERS
index 8f5681f..615df35 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -91,6 +91,11 @@ M: Aurelien Jarno <aurelien@aurel32.net>
 S: Odd Fixes
 F: target-mips/
 
+NiosII
+M: Chris Wulff <crwulff@gmail.com>
+S: Odd Fixes
+F: target-nios2/
+
 PowerPC
 M: Alexander Graf <agraf@suse.de>
 L: qemu-ppc@nongnu.org
diff --git a/arch_init.c b/arch_init.c
index e6effe8..0aafe8e 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -84,6 +84,8 @@ int graphic_depth = 15;
 #define QEMU_ARCH QEMU_ARCH_MICROBLAZE
 #elif defined(TARGET_MIPS)
 #define QEMU_ARCH QEMU_ARCH_MIPS
+#elif defined(TARGET_NIOS2)
+#define QEMU_ARCH QEMU_ARCH_NIOS2
 #elif defined(TARGET_OPENRISC)
 #define QEMU_ARCH QEMU_ARCH_OPENRISC
 #elif defined(TARGET_PPC)
diff --git a/arch_init.h b/arch_init.h
index 5fc780c..b2d736a 100644
--- a/arch_init.h
+++ b/arch_init.h
@@ -20,6 +20,7 @@ enum {
     QEMU_ARCH_XTENSA = 4096,
     QEMU_ARCH_OPENRISC = 8192,
     QEMU_ARCH_UNICORE32 = 0x4000,
+    QEMU_ARCH_NIOS2 = 0x8000,
 };
 
 extern const uint32_t arch_type;
diff --git a/configure b/configure
index 7290f50..554e44a 100755
--- a/configure
+++ b/configure
@@ -924,6 +924,7 @@ mips-softmmu \
 mipsel-softmmu \
 mips64-softmmu \
 mips64el-softmmu \
+nios2-softmmu \
 or32-softmmu \
 ppc-softmmu \
 ppcemb-softmmu \
@@ -952,6 +953,7 @@ microblaze-linux-user \
 microblazeel-linux-user \
 mips-linux-user \
 mipsel-linux-user \
+nios2-linux-user \
 or32-linux-user \
 ppc-linux-user \
 ppc64-linux-user \
@@ -3808,6 +3810,11 @@ case "$target_arch2" in
     echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak
     target_long_alignment=8
   ;;
+  nios2)
+    target_nptl="yes"
+    target_phys_bits=32
+    target_libs_softmmu="$fdt_libs"
+  ;;
   or32)
     TARGET_ARCH=openrisc
     TARGET_BASE_ARCH=openrisc
@@ -4061,6 +4068,10 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
     echo "CONFIG_MIPS_DIS=y"  >> $config_target_mak
     echo "CONFIG_MIPS_DIS=y"  >> $libdis_config_mak
   ;;
+  nios2)
+    echo "CONFIG_NIOS2_DIS=y"  >> $config_target_mak
+    echo "CONFIG_NIOS2_DIS=y"  >> $libdis_config_mak
+  ;;
   or32)
     echo "CONFIG_OPENRISC_DIS=y"  >> $config_target_mak
     echo "CONFIG_OPENRISC_DIS=y"  >> $libdis_config_mak
diff --git a/cpu-exec.c b/cpu-exec.c
index 904ee73..f9da4d1 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -220,6 +220,7 @@ int cpu_exec(CPUArchState *env)
 #elif defined(TARGET_LM32)
 #elif defined(TARGET_MICROBLAZE)
 #elif defined(TARGET_MIPS)
+#elif defined(TARGET_NIOS2)
 #elif defined(TARGET_OPENRISC)
 #elif defined(TARGET_SH4)
 #elif defined(TARGET_CRIS)
@@ -275,7 +276,8 @@ int cpu_exec(CPUArchState *env)
                     }
 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
-    defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
+    defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || \
+    defined(TARGET_UNICORE32) || defined(TARGET_NIOS2)
                     if (interrupt_request & CPU_INTERRUPT_HALT) {
                         env->interrupt_request &= ~CPU_INTERRUPT_HALT;
                         env->halted = 1;
@@ -529,6 +531,13 @@ int cpu_exec(CPUArchState *env)
                         do_interrupt(env);
                         next_tb = 0;
                     }
+#elif defined(TARGET_NIOS2)
+                    if ((interrupt_request & CPU_INTERRUPT_HARD)
+                        && (env->regs[CR_STATUS] & CR_STATUS_PIE)) {
+                        env->exception_index = EXCP_IRQ;
+                        do_interrupt(env);
+                        next_tb = 0;
+                    }
 #endif
                    /* Don't use the cached interrupt_request value,
                       do_interrupt may have updated the EXITTB flag. */
@@ -654,6 +663,7 @@ int cpu_exec(CPUArchState *env)
               | env->cc_dest | (env->cc_x << 4);
 #elif defined(TARGET_MICROBLAZE)
 #elif defined(TARGET_MIPS)
+#elif defined(TARGET_NIOS2)
 #elif defined(TARGET_OPENRISC)
 #elif defined(TARGET_SH4)
 #elif defined(TARGET_ALPHA)
diff --git a/default-configs/nios2-linux-user.mak b/default-configs/nios2-linux-user.mak
new file mode 100644
index 0000000..5be3eb7
--- /dev/null
+++ b/default-configs/nios2-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for nios2-linux-user
diff --git a/default-configs/nios2-softmmu.mak b/default-configs/nios2-softmmu.mak
new file mode 100644
index 0000000..a14708a
--- /dev/null
+++ b/default-configs/nios2-softmmu.mak
@@ -0,0 +1,5 @@
+# Default configuration for nios2-softmmu
+
+CONFIG_PTIMER=y
+CONFIG_PFLASH_CFI01=y
+CONFIG_ALTERA=y
diff --git a/dis-asm.h b/dis-asm.h
index 3944b3c..a7010bf 100644
--- a/dis-asm.h
+++ b/dis-asm.h
@@ -221,6 +221,8 @@ enum bfd_architecture
   bfd_arch_ia64,      /* HP/Intel ia64 */
 #define bfd_mach_ia64_elf64    64
 #define bfd_mach_ia64_elf32    32
+  bfd_arch_nios2,
+#define bfd_mach_nios2          1
   bfd_arch_lm32,       /* Lattice Mico32 */
 #define bfd_mach_lm32 1
   bfd_arch_last
@@ -407,6 +409,7 @@ int print_insn_crisv10          (bfd_vma, disassemble_info*);
 int print_insn_microblaze       (bfd_vma, disassemble_info*);
 int print_insn_ia64             (bfd_vma, disassemble_info*);
 int print_insn_lm32             (bfd_vma, disassemble_info*);
+int print_insn_nios2            (bfd_vma, disassemble_info*);
 
 #if 0
 /* Fetch the disassembler for a given BFD, if that support is available.  */
diff --git a/disas.c b/disas.c
index b801c8f..8469c2e 100644
--- a/disas.c
+++ b/disas.c
@@ -245,6 +245,9 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
 #elif defined(TARGET_MICROBLAZE)
     disasm_info.mach = bfd_arch_microblaze;
     print_insn = print_insn_microblaze;
+#elif defined(TARGET_NIOS2)
+    disasm_info.mach = bfd_arch_nios2;
+    print_insn = print_insn_nios2;
 #elif defined(TARGET_LM32)
     disasm_info.mach = bfd_mach_lm32;
     print_insn = print_insn_lm32;
diff --git a/elf.h b/elf.h
index a21ea53..e5e667b 100644
--- a/elf.h
+++ b/elf.h
@@ -124,6 +124,8 @@ typedef int64_t  Elf64_Sxword;
  */
 #define EM_S390_OLD     0xA390
 
+#define EM_ALTERA_NIOS2 113     /* Altera Nios II soft-core processor */
+
 #define EM_MICROBLAZE      189
 #define EM_MICROBLAZE_OLD  0xBAAB
 
diff --git a/exec.c b/exec.c
index af94f9c..e6faf0f 100644
--- a/exec.c
+++ b/exec.c
@@ -2860,7 +2860,8 @@ static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
 #endif
-#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
+#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || \
+    defined(TARGET_MICROBLAZE) || defined(TARGET_NIOS2)
     cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
 #endif
     return 0;
@@ -2872,7 +2873,8 @@ static void unassigned_mem_write(void *opaque, hwaddr addr,
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem write " TARGET_FMT_plx " = 0x%"PRIx64"\n", addr, val);
 #endif
-#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
+#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || \
+    defined(TARGET_MICROBLAZE) || defined(TARGET_NIOS2)
     cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
 #endif
 }
diff --git a/gdbstub.c b/gdbstub.c
index d02ec75..3c741fb 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1367,6 +1367,33 @@ static int cpu_gdb_write_register(CPUMBState *env, uint8_t *mem_buf, int n)
     }
     return 4;
 }
+
+#elif defined(TARGET_NIOS2)
+
+static int cpu_gdb_read_register(CPUNios2State *env, uint8_t *mem_buf, int n)
+{
+    if (n > NUM_CORE_REGS) {
+        return 0;
+    }
+
+    GET_REG32(env->regs[n]);
+    return 0;
+}
+
+static int cpu_gdb_write_register(CPUNios2State *env, uint8_t *mem_buf, int n)
+{
+    uint32_t tmp;
+
+    if (n > NUM_CORE_REGS) {
+        return 0;
+    }
+
+    tmp = ldl_p(mem_buf);
+
+    env->regs[n] = tmp;
+    return 4;
+}
+
 #elif defined (TARGET_CRIS)
 
 #define NUM_CORE_REGS 49
@@ -2030,6 +2057,8 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
     }
 #elif defined (TARGET_MICROBLAZE)
     s->c_cpu->sregs[SR_PC] = pc;
+#elif defined(TARGET_NIOS2)
+    s->c_cpu->regs[R_PC] = pc;
 #elif defined(TARGET_OPENRISC)
     s->c_cpu->pc = pc;
 #elif defined (TARGET_CRIS)
diff --git a/hw/nios2/Makefile.objs b/hw/nios2/Makefile.objs
new file mode 100644
index 0000000..5a92c78
--- /dev/null
+++ b/hw/nios2/Makefile.objs
@@ -0,0 +1,3 @@
+obj-y += nios2_pic_cpu.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 1d8bcb4..31e77a9 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -804,6 +804,35 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env
 
 #endif /* TARGET_MICROBLAZE */
 
+#ifdef TARGET_NIOS2
+
+#define ELF_START_MMAP 0x80000000
+
+#define elf_check_arch(x) ((x) == EM_ALTERA_NIOS2)
+
+#define ELF_CLASS   ELFCLASS32
+#define ELF_ARCH    EM_ALTERA_NIOS2
+
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
+{
+    /* TODO */
+}
+
+#define ELF_EXEC_PAGESIZE        4096
+
+#define USE_ELF_CORE_DUMP
+/* TODO - #define ELF_NREG 38 */
+typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
+
+/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+{
+    /* TODO */
+}
+
+#endif /* TARGET_NIOS2 */
+
 #ifdef TARGET_OPENRISC
 
 #define ELF_START_MMAP 0x08000000
diff --git a/monitor.c b/monitor.c
index c0e32d6..ca93008 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1764,7 +1764,8 @@ static void tlb_info(Monitor *mon)
 
 #endif
 
-#if defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_XTENSA)
+#if defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_XTENSA) || \
+    defined(TARGET_NIOS2)
 static void tlb_info(Monitor *mon)
 {
     CPUArchState *env1 = mon_get_cpu();
@@ -2529,7 +2530,7 @@ static mon_cmd_t info_cmds[] = {
         .mhandler.info = hmp_info_pci,
     },
 #if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC) || \
-    defined(TARGET_PPC) || defined(TARGET_XTENSA)
+    defined(TARGET_PPC) || defined(TARGET_XTENSA) || defined(TARGET_NIOS2)
     {
         .name       = "tlb",
         .args_type  = "",
diff --git a/qapi-schema.json b/qapi-schema.json
index 542e3ac..b7e72d9 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2871,7 +2871,7 @@
 ##
 { 'enum': 'TargetType',
   'data': [ 'alpha', 'arm', 'cris', 'i386', 'lm32', 'm68k', 'microblazeel',
-            'microblaze', 'mips64el', 'mips64', 'mipsel', 'mips', 'or32',
+            'microblaze', 'mips64el', 'mips64', 'mipsel', 'mips', 'nios2', 'or32',
             'ppc64', 'ppcemb', 'ppc', 's390x', 'sh4eb', 'sh4', 'sparc64',
             'sparc', 'unicore32', 'x86_64', 'xtensaeb', 'xtensa' ] }
 
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 35cabbc..3515f15 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -2475,6 +2475,9 @@ The binary format is detected automatically.
 @command{qemu-mips} TODO.
 @command{qemu-mipsel} TODO.
 
+@cindex user mode (NiosII)
+@command{qemu-nios2} TODO.
+
 @cindex user mode (PowerPC)
 @command{qemu-ppc64abi32} TODO.
 @command{qemu-ppc64} TODO.
-- 
1.7.10.4

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

end of thread, other threads:[~2012-11-11  4:20 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-11  4:18 [Qemu-devel] [PATCH 0/4] Altera NiosII Support (v2) crwulff
2012-11-11  4:18 ` [Qemu-devel] [PATCH 1/4] NiosII: Add support for the Altera NiosII soft-core CPU. (v2) crwulff
2012-11-11  4:18 ` [Qemu-devel] [PATCH 2/4] NiosII: Disassembly of NiosII instructions ported from GDB. (v2) crwulff
2012-11-11  4:18 ` [Qemu-devel] [PATCH 3/4] Altera: Add support for devices needed to boot Linux on NiosII. (v2) crwulff
2012-11-11  4:18 ` [Qemu-devel] [PATCH 4/4] NiosII: Build system and documentation integration crwulff

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).