From: Michael Rolnik <mrolnik@gmail.com>
To: qemu-devel@nongnu.org
Cc: rth@twiddle.net, peter.maydell@linaro.org,
Michael Rolnik <mrolnik@gmail.com>
Subject: [Qemu-devel] [PATCH v9 01/10] target-avr: AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions 4. saving sreg, rampD, rampX, rampY, rampD, eind in HW representation saving cpu features
Date: Wed, 22 Jun 2016 12:51:46 +0300 [thread overview]
Message-ID: <1466589115-57738-2-git-send-email-mrolnik@gmail.com> (raw)
In-Reply-To: <1466589115-57738-1-git-send-email-mrolnik@gmail.com>
Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
arch_init.c | 2 +
configure | 5 +
default-configs/avr-softmmu.mak | 21 +++
include/disas/bfd.h | 6 +
include/sysemu/arch_init.h | 1 +
target-avr/Makefile.objs | 23 +++
target-avr/cpu-qom.h | 84 +++++++++++
target-avr/cpu.c | 304 ++++++++++++++++++++++++++++++++++++++++
target-avr/cpu.h | 167 ++++++++++++++++++++++
target-avr/gdbstub.c | 84 +++++++++++
target-avr/helper.c | 87 ++++++++++++
target-avr/helper.h | 21 +++
target-avr/machine.c | 116 +++++++++++++++
target-avr/machine.h | 21 +++
target-avr/translate.c | 291 ++++++++++++++++++++++++++++++++++++++
15 files changed, 1233 insertions(+)
create mode 100644 default-configs/avr-softmmu.mak
create mode 100644 target-avr/Makefile.objs
create mode 100644 target-avr/cpu-qom.h
create mode 100644 target-avr/cpu.c
create mode 100644 target-avr/cpu.h
create mode 100644 target-avr/gdbstub.c
create mode 100644 target-avr/helper.c
create mode 100644 target-avr/helper.h
create mode 100644 target-avr/machine.c
create mode 100644 target-avr/machine.h
create mode 100644 target-avr/translate.c
diff --git a/arch_init.c b/arch_init.c
index fa05973..be6e6de 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -80,6 +80,8 @@ int graphic_depth = 32;
#define QEMU_ARCH QEMU_ARCH_UNICORE32
#elif defined(TARGET_TRICORE)
#define QEMU_ARCH QEMU_ARCH_TRICORE
+#elif defined(TARGET_AVR)
+#define QEMU_ARCH QEMU_ARCH_AVR
#endif
const uint32_t arch_type = QEMU_ARCH;
diff --git a/configure b/configure
index 5929aba..f828922 100755
--- a/configure
+++ b/configure
@@ -5624,6 +5624,8 @@ case "$target_name" in
x86_64)
TARGET_BASE_ARCH=i386
;;
+ avr)
+ ;;
alpha)
;;
arm|armeb)
@@ -5820,6 +5822,9 @@ disas_config() {
for i in $ARCH $TARGET_BASE_ARCH ; do
case "$i" in
+ avr)
+ disas_config "AVR"
+ ;;
alpha)
disas_config "ALPHA"
;;
diff --git a/default-configs/avr-softmmu.mak b/default-configs/avr-softmmu.mak
new file mode 100644
index 0000000..003465d
--- /dev/null
+++ b/default-configs/avr-softmmu.mak
@@ -0,0 +1,21 @@
+#
+# QEMU AVR CPU
+#
+# Copyright (c) 2016 Michael Rolnik
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see
+# <http://www.gnu.org/licenses/lgpl-2.1.html>
+#
+
+# Default configuration for avr-softmmu
diff --git a/include/disas/bfd.h b/include/disas/bfd.h
index a112e9c..b13fc53 100644
--- a/include/disas/bfd.h
+++ b/include/disas/bfd.h
@@ -213,6 +213,12 @@ enum bfd_architecture
#define bfd_mach_m32r 0 /* backwards compatibility */
bfd_arch_mn10200, /* Matsushita MN10200 */
bfd_arch_mn10300, /* Matsushita MN10300 */
+ bfd_arch_avr, /* Atmel AVR microcontrollers. */
+#define bfd_mach_avr1 1
+#define bfd_mach_avr2 2
+#define bfd_mach_avr3 3
+#define bfd_mach_avr4 4
+#define bfd_mach_avr5 5
bfd_arch_cris, /* Axis CRIS */
#define bfd_mach_cris_v0_v10 255
#define bfd_mach_cris_v32 32
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index d690dfa..8c75777 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -23,6 +23,7 @@ enum {
QEMU_ARCH_UNICORE32 = (1 << 14),
QEMU_ARCH_MOXIE = (1 << 15),
QEMU_ARCH_TRICORE = (1 << 16),
+ QEMU_ARCH_AVR = (1 << 17),
};
extern const uint32_t arch_type;
diff --git a/target-avr/Makefile.objs b/target-avr/Makefile.objs
new file mode 100644
index 0000000..2a10104
--- /dev/null
+++ b/target-avr/Makefile.objs
@@ -0,0 +1,23 @@
+#
+# QEMU AVR CPU
+#
+# Copyright (c) 2016 Michael Rolnik
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see
+# <http://www.gnu.org/licenses/lgpl-2.1.html>
+#
+
+obj-y += translate.o cpu.o helper.o
+obj-y += gdbstub.o
+obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-avr/cpu-qom.h b/target-avr/cpu-qom.h
new file mode 100644
index 0000000..c5d4f92
--- /dev/null
+++ b/target-avr/cpu-qom.h
@@ -0,0 +1,84 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#ifndef QEMU_AVR_CPU_QOM_H
+#define QEMU_AVR_CPU_QOM_H
+
+#include "qom/cpu.h"
+
+#define TYPE_AVR_CPU "avr"
+
+#define AVR_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(AVRCPUClass, (klass), TYPE_AVR_CPU)
+#define AVR_CPU(obj) \
+ OBJECT_CHECK(AVRCPU, (obj), TYPE_AVR_CPU)
+#define AVR_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(AVRCPUClass, (obj), TYPE_AVR_CPU)
+
+/**
+* AVRCPUClass:
+* @parent_realize: The parent class' realize handler.
+* @parent_reset: The parent class' reset handler.
+* @vr: Version Register value.
+*
+* A AVR CPU model.
+*/
+typedef struct AVRCPUClass {
+ CPUClass parent_class;
+
+ DeviceRealize parent_realize;
+ void (*parent_reset)(CPUState *cpu);
+} AVRCPUClass;
+
+/**
+* AVRCPU:
+* @env: #CPUAVRState
+*
+* A AVR CPU.
+*/
+typedef struct AVRCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUAVRState env;
+} AVRCPU;
+
+static inline AVRCPU *avr_env_get_cpu(CPUAVRState *env)
+{
+ return container_of(env, AVRCPU, env);
+}
+
+#define ENV_GET_CPU(e) CPU(avr_env_get_cpu(e))
+#define ENV_OFFSET offsetof(AVRCPU, env)
+
+#ifndef CONFIG_USER_ONLY
+extern const struct VMStateDescription vms_avr_cpu;
+#endif
+
+void avr_cpu_do_interrupt(CPUState *cpu);
+bool avr_cpu_exec_interrupt(CPUState *cpu, int int_req);
+void avr_cpu_dump_state(CPUState *cs, FILE *f,
+ fprintf_function cpu_fprintf, int flags);
+hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int avr_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+
+#endif
diff --git a/target-avr/cpu.c b/target-avr/cpu.c
new file mode 100644
index 0000000..1fdc1e6
--- /dev/null
+++ b/target-avr/cpu.c
@@ -0,0 +1,304 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "qemu-common.h"
+#include "migration/vmstate.h"
+#include "machine.h"
+
+static void avr_cpu_set_pc(CPUState *cs, vaddr value)
+{
+ AVRCPU *cpu = AVR_CPU(cs);
+
+ cpu->env.pc_w = value / 2; /* internally PC points to words */
+}
+
+static bool avr_cpu_has_work(CPUState *cs)
+{
+ AVRCPU *cpu = AVR_CPU(cs);
+ CPUAVRState *env = &cpu->env;
+
+ return (cs->interrupt_request
+ & (CPU_INTERRUPT_HARD
+ | CPU_INTERRUPT_RESET))
+ && cpu_interrupts_enabled(env);
+}
+static void avr_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
+{
+ AVRCPU *cpu = AVR_CPU(cs);
+ CPUAVRState *env = &cpu->env;
+
+ env->pc_w = tb->pc / 2; /* internally PC points to words */
+}
+
+static void avr_cpu_reset(CPUState *s)
+{
+ AVRCPU *cpu = AVR_CPU(s);
+ AVRCPUClass *mcc = AVR_CPU_GET_CLASS(cpu);
+ CPUAVRState *env = &cpu->env;
+
+ mcc->parent_reset(s);
+
+ env->pc_w = 0;
+ env->sregI = 1;
+ env->sregC = 0;
+ env->sregZ = 0;
+ env->sregN = 0;
+ env->sregV = 0;
+ env->sregS = 0;
+ env->sregH = 0;
+ env->sregT = 0;
+
+ env->rampD = 0;
+ env->rampX = 0;
+ env->rampY = 0;
+ env->rampZ = 0;
+ env->eind = 0;
+ env->sp = 0;
+
+ memset(env->io, 0, sizeof(env->io));
+ memset(env->r, 0, sizeof(env->r));
+
+ tlb_flush(s, 1);
+}
+
+static void avr_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
+{
+ info->mach = bfd_arch_avr;
+ info->print_insn = NULL;
+}
+
+static void avr_cpu_realizefn(DeviceState *dev, Error **errp)
+{
+ CPUState *cs = CPU(dev);
+ AVRCPUClass *mcc = AVR_CPU_GET_CLASS(dev);
+
+ qemu_init_vcpu(cs);
+ cpu_reset(cs);
+
+ mcc->parent_realize(dev, errp);
+}
+
+static void avr_cpu_set_int(void *opaque, int irq, int level)
+{
+ AVRCPU *cpu = opaque;
+ CPUAVRState *env = &cpu->env;
+ CPUState *cs = CPU(cpu);
+
+ uint64_t mask = (1ull << irq);
+ if (level) {
+ env->intsrc |= mask;
+ cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+ } else {
+ env->intsrc &= ~mask;
+ if (env->intsrc == 0) {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+ }
+ }
+}
+
+static void avr_cpu_initfn(Object *obj)
+{
+ CPUState *cs = CPU(obj);
+ AVRCPU *cpu = AVR_CPU(obj);
+ static int inited;
+
+ cs->env_ptr = &cpu->env;
+ cpu_exec_init(cs, &error_abort);
+
+#ifndef CONFIG_USER_ONLY
+ qdev_init_gpio_in(DEVICE(cpu), avr_cpu_set_int, 37);
+#endif
+
+ if (tcg_enabled() && !inited) {
+ inited = 1;
+ avr_translate_init();
+ }
+}
+
+static ObjectClass *avr_cpu_class_by_name(const char *cpu_model)
+{
+ ObjectClass *oc;
+ char *typename;
+ char **cpuname;
+
+ if (!cpu_model) {
+ return NULL;
+ }
+
+ cpuname = g_strsplit(cpu_model, ",", 1);
+ typename = g_strdup_printf("%s-" TYPE_AVR_CPU, cpuname[0]);
+ oc = object_class_by_name(typename);
+
+ g_strfreev(cpuname);
+ g_free(typename);
+
+ if (!oc
+ || !object_class_dynamic_cast(oc, TYPE_AVR_CPU)
+ || object_class_is_abstract(oc)) {
+ return NULL;
+ }
+
+ return oc;
+}
+
+static void avr_cpu_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ CPUClass *cc = CPU_CLASS(oc);
+ AVRCPUClass *mcc = AVR_CPU_CLASS(oc);
+
+ mcc->parent_realize = dc->realize;
+ dc->realize = avr_cpu_realizefn;
+
+ mcc->parent_reset = cc->reset;
+ cc->reset = avr_cpu_reset;
+
+ cc->class_by_name = avr_cpu_class_by_name;
+
+ cc->has_work = avr_cpu_has_work;
+ cc->do_interrupt = avr_cpu_do_interrupt;
+ cc->cpu_exec_interrupt = avr_cpu_exec_interrupt;
+ cc->dump_state = avr_cpu_dump_state;
+ cc->set_pc = avr_cpu_set_pc;
+#if !defined(CONFIG_USER_ONLY)
+ cc->memory_rw_debug = avr_cpu_memory_rw_debug;
+#endif
+#ifdef CONFIG_USER_ONLY
+ cc->handle_mmu_fault = avr_cpu_handle_mmu_fault;
+#else
+ cc->get_phys_page_debug = avr_cpu_get_phys_page_debug;
+ cc->vmsd = &vms_avr_cpu;
+#endif
+ cc->disas_set_info = avr_cpu_disas_set_info;
+ cc->synchronize_from_tb = avr_cpu_synchronize_from_tb;
+ cc->gdb_read_register = avr_cpu_gdb_read_register;
+ cc->gdb_write_register = avr_cpu_gdb_write_register;
+ cc->gdb_num_core_regs = 35;
+
+ /*
+ * Reason: avr_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
+}
+
+static void avr_any_initfn(Object *obj)
+{
+ /* Set cpu feature flags */
+}
+
+typedef struct AVRCPUInfo {
+ const char *name;
+ void (*initfn)(Object *obj);
+} AVRCPUInfo;
+
+static const AVRCPUInfo avr_cpus[] = {
+ { .name = "any", .initfn = avr_any_initfn },
+};
+
+static gint avr_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+ ObjectClass *class_a = (ObjectClass *)a;
+ ObjectClass *class_b = (ObjectClass *)b;
+ const char *name_a;
+ const char *name_b;
+
+ name_a = object_class_get_name(class_a);
+ name_b = object_class_get_name(class_b);
+ if (strcmp(name_a, "any-" TYPE_AVR_CPU) == 0) {
+ return 1;
+ } else if (strcmp(name_b, "any-" TYPE_AVR_CPU) == 0) {
+ return -1;
+ } else {
+ return strcmp(name_a, name_b);
+ }
+}
+
+static void avr_cpu_list_entry(gpointer data, gpointer user_data)
+{
+ ObjectClass *oc = data;
+ CPUListState *s = user_data;
+ const char *typename;
+ char *name;
+
+ typename = object_class_get_name(oc);
+ name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_AVR_CPU));
+ (*s->cpu_fprintf)(s->file, " %s\n", name);
+ g_free(name);
+}
+
+void avr_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+ CPUListState s = {
+ .file = f,
+ .cpu_fprintf = cpu_fprintf,
+ };
+ GSList *list;
+
+ list = object_class_get_list(TYPE_AVR_CPU, false);
+ list = g_slist_sort(list, avr_cpu_list_compare);
+ (*cpu_fprintf)(f, "Available CPUs:\n");
+ g_slist_foreach(list, avr_cpu_list_entry, &s);
+ g_slist_free(list);
+}
+AVRCPU *cpu_avr_init(const char *cpu_model)
+{
+ return AVR_CPU(cpu_generic_init(TYPE_AVR_CPU, cpu_model));
+}
+
+static void cpu_register(const AVRCPUInfo *info)
+{
+ TypeInfo type_info = {
+ .parent = TYPE_AVR_CPU,
+ .instance_size = sizeof(AVRCPU),
+ .instance_init = info->initfn,
+ .class_size = sizeof(AVRCPUClass),
+ };
+
+ type_info.name = g_strdup_printf("%s-" TYPE_AVR_CPU, info->name);
+ type_register(&type_info);
+ g_free((void *)type_info.name);
+}
+
+static const TypeInfo avr_cpu_type_info = {
+ .name = TYPE_AVR_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(AVRCPU),
+ .instance_init = avr_cpu_initfn,
+ .class_size = sizeof(AVRCPUClass),
+ .class_init = avr_cpu_class_init,
+ .abstract = true,
+};
+
+static void avr_cpu_register_types(void)
+{
+ int i;
+ type_register_static(&avr_cpu_type_info);
+
+ for (i = 0; i < ARRAY_SIZE(avr_cpus); i++) {
+ cpu_register(&avr_cpus[i]);
+ }
+}
+
+type_init(avr_cpu_register_types)
diff --git a/target-avr/cpu.h b/target-avr/cpu.h
new file mode 100644
index 0000000..aa351f4
--- /dev/null
+++ b/target-avr/cpu.h
@@ -0,0 +1,167 @@
+ /*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#if !defined(CPU_AVR_H)
+#define CPU_AVR_H
+
+#include "qemu-common.h"
+
+#define TARGET_LONG_BITS 32
+
+#define CPUArchState struct CPUAVRState
+
+#include "exec/cpu-defs.h"
+#include "fpu/softfloat.h"
+
+/*
+ TARGET_PAGE_BITS cannot be more than 8 bits because
+ 1. all IO registers occupy [0x0000 .. 0x00ff] address range, and they
+ should be implemented as a device and not memory
+ 2. SRAM starts at the address 0x0100
+*/
+#define TARGET_PAGE_BITS 8
+#define TARGET_PHYS_ADDR_SPACE_BITS 24
+#define TARGET_VIRT_ADDR_SPACE_BITS 24
+#define NB_MMU_MODES 2
+
+#define MMU_CODE_IDX 0
+#define MMU_DATA_IDX 1
+
+#define EXCP_RESET 1
+#define EXCP_INT(n) (EXCP_RESET + (n) + 1)
+
+#define PHYS_ADDR_MASK 0xfff00000
+
+#define PHYS_BASE_CODE 0x00000000
+#define PHYS_BASE_DATA 0x00800000
+#define PHYS_BASE_REGS 0x10000000
+
+#define IO_REGS 64
+#define EXT_IO_REGS 160
+#define SIZE_REGS 0x00000100
+
+#define VIRT_BASE_CODE 0x00000000
+#define VIRT_BASE_DATA 0x00000000
+#define VIRT_BASE_REGS 0x00000000
+
+#define OFFS_IOREGS 0x00000020
+
+
+typedef struct CPUAVRState CPUAVRState;
+
+struct CPUAVRState {
+ uint32_t pc_w; /* 0x003fffff up to 22 bits */
+
+ uint32_t sregC; /* 0x00000001 1 bits */
+ uint32_t sregZ; /* 0x0000ffff 16 bits, negative logic */
+ uint32_t sregN; /* 0x00000001 1 bits */
+ uint32_t sregV; /* 0x00000001 1 bits */
+ uint32_t sregS; /* 0x00000001 1 bits */
+ uint32_t sregH; /* 0x00000001 1 bits */
+ uint32_t sregT; /* 0x00000001 1 bits */
+ uint32_t sregI; /* 0x00000001 1 bits */
+
+ uint32_t rampD; /* 0x00ff0000 8 bits */
+ uint32_t rampX; /* 0x00ff0000 8 bits */
+ uint32_t rampY; /* 0x00ff0000 8 bits */
+ uint32_t rampZ; /* 0x00ff0000 8 bits */
+ uint32_t eind; /* 0x00ff0000 8 bits */
+
+ uint32_t io[IO_REGS];
+ /* 8 bits each */
+ uint32_t r[32]; /* 8 bits each */
+ uint32_t sp; /* 16 bits */
+
+
+ uint64_t intsrc; /* interrupt sources */
+
+ bool fullwr; /* CPU/MEM if true MEM only otherwise */
+ /* Those resources are used only in QEMU core */
+ CPU_COMMON
+};
+
+#define cpu_list avr_cpu_list
+#define cpu_exec cpu_avr_exec
+#define cpu_signal_handler cpu_avr_signal_handler
+
+#include "exec/cpu-all.h"
+#include "cpu-qom.h"
+
+static inline int cpu_mmu_index(CPUAVRState *env, bool ifetch)
+{
+ return ifetch ? MMU_CODE_IDX : MMU_DATA_IDX;
+}
+
+void avr_translate_init(void);
+
+AVRCPU *cpu_avr_init(const char *cpu_model);
+
+#define cpu_init(cpu_model) CPU(cpu_avr_init(cpu_model))
+
+void avr_cpu_list(FILE *f, fprintf_function cpu_fprintf);
+int cpu_avr_exec(CPUState *cpu);
+int cpu_avr_signal_handler(int host_signum, void *pinfo, void *puc);
+int avr_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
+ int mmu_idx);
+int avr_cpu_memory_rw_debug(CPUState *cs, vaddr address, uint8_t *buf,
+ int len, bool is_write);
+
+static inline void cpu_get_tb_cpu_state(CPUAVRState *env, target_ulong *pc,
+ target_ulong *cs_base, uint32_t *pflags)
+{
+ *pc = env->pc_w * 2;
+ *cs_base = 0;
+ *pflags = 0;
+}
+
+static inline int cpu_interrupts_enabled(CPUAVRState *env1)
+{
+ return env1->sregI != 0;
+}
+
+static inline uint8_t cpu_get_sreg(CPUAVRState *env)
+{
+ uint8_t sreg;
+ sreg = (env->sregC & 0x01) << 0
+ | (env->sregZ == 0 ? 1 : 0) << 1
+ | (env->sregN) << 2
+ | (env->sregV) << 3
+ | (env->sregS) << 4
+ | (env->sregH) << 5
+ | (env->sregT) << 6
+ | (env->sregI) << 7;
+ return sreg;
+}
+
+static inline void cpu_set_sreg(CPUAVRState *env, uint8_t sreg)
+{
+ env->sregC = (sreg >> 0) & 0x01;
+ env->sregZ = (sreg >> 1) & 0x01 ? 0 : 1;
+ env->sregN = (sreg >> 2) & 0x01;
+ env->sregV = (sreg >> 3) & 0x01;
+ env->sregS = (sreg >> 4) & 0x01;
+ env->sregH = (sreg >> 5) & 0x01;
+ env->sregT = (sreg >> 6) & 0x01;
+ env->sregI = (sreg >> 7) & 0x01;
+}
+
+#include "exec/exec-all.h"
+
+#endif /* !defined (CPU_AVR_H) */
diff --git a/target-avr/gdbstub.c b/target-avr/gdbstub.c
new file mode 100644
index 0000000..a53ba09
--- /dev/null
+++ b/target-avr/gdbstub.c
@@ -0,0 +1,84 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+int avr_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ AVRCPU *cpu = AVR_CPU(cs);
+ CPUAVRState *env = &cpu->env;
+
+ /* R */
+ if (n < 32) {
+ return gdb_get_reg8(mem_buf, env->r[n]);
+ }
+
+ /* SREG */
+ if (n == 32) {
+ uint8_t sreg = cpu_get_sreg(env);
+
+ return gdb_get_reg8(mem_buf, sreg);
+ }
+
+ /* SP */
+ if (n == 33) {
+ return gdb_get_reg16(mem_buf, env->sp & 0x0000ffff);
+ }
+
+ /* PC */
+ if (n == 34) {
+ return gdb_get_reg32(mem_buf, env->pc_w * 2);
+ }
+
+ return 0;
+}
+
+int avr_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ AVRCPU *cpu = AVR_CPU(cs);
+ CPUAVRState *env = &cpu->env;
+ uint16_t tmp = ldl_p(mem_buf);
+
+ /* R */
+ if (n < 32) {
+ env->r[n] = tmp;
+ }
+
+ /* SREG */
+ if (n == 32) {
+ cpu_set_sreg(env, tmp);
+ }
+
+ /* SP */
+ if (n == 33) {
+ env->sp = tmp;
+ return 2;
+ }
+
+ /* PC */
+ if (n == 34) {
+ env->pc_w = tmp / 2;
+ return 4;
+ }
+
+ return 1;
+}
diff --git a/target-avr/helper.c b/target-avr/helper.c
new file mode 100644
index 0000000..3e23646
--- /dev/null
+++ b/target-avr/helper.c
@@ -0,0 +1,87 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+
+#include "cpu.h"
+#include "hw/irq.h"
+#include "include/hw/sysbus.h"
+#include "include/sysemu/sysemu.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+
+bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+ return false;
+}
+
+void avr_cpu_do_interrupt(CPUState *cs)
+{
+}
+
+int avr_cpu_memory_rw_debug(CPUState *cs, vaddr addr, uint8_t *buf,
+ int len, bool is_write)
+{
+ return cpu_memory_rw_debug(cs, addr, buf, len, is_write);
+}
+
+hwaddr avr_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
+{
+ return addr; /* I assume 1:1 address correspondance */
+}
+
+int avr_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, int mmu_idx)
+{
+ cs->exception_index = EXCP_DEBUG;
+ cpu_dump_state(cs, stderr, fprintf, 0);
+ return 1;
+}
+
+void tlb_fill(CPUState *cs, target_ulong vaddr, int is_write,
+ int mmu_idx, uintptr_t retaddr)
+{
+ target_ulong page_size = TARGET_PAGE_SIZE;
+ int prot = 0;
+ MemTxAttrs attrs = {};
+ uint32_t paddr;
+
+ vaddr &= TARGET_PAGE_MASK;
+
+ if (mmu_idx == MMU_CODE_IDX) {
+ paddr = PHYS_BASE_CODE + vaddr;
+ prot = PAGE_READ | PAGE_EXEC;
+ } else {
+ paddr = PHYS_BASE_DATA + vaddr;
+ prot = PAGE_READ | PAGE_WRITE;
+ }
+
+ tlb_set_page_with_attrs(cs, vaddr, paddr, attrs, prot, mmu_idx, page_size);
+}
+
+void helper_debug(CPUAVRState *env)
+{
+ CPUState *cs = CPU(avr_env_get_cpu(env));
+
+ cs->exception_index = EXCP_DEBUG;
+ cpu_loop_exit(cs);
+}
+
diff --git a/target-avr/helper.h b/target-avr/helper.h
new file mode 100644
index 0000000..b5ef3bf
--- /dev/null
+++ b/target-avr/helper.h
@@ -0,0 +1,21 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+DEF_HELPER_1(debug, void, env)
diff --git a/target-avr/machine.c b/target-avr/machine.c
new file mode 100644
index 0000000..9f6e463
--- /dev/null
+++ b/target-avr/machine.c
@@ -0,0 +1,116 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "cpu.h"
+#include "hw/boards.h"
+#include "machine.h"
+#include "migration/qemu-file.h"
+
+static int get_sreg(QEMUFile *f, void *opaque, size_t size)
+{
+ CPUAVRState *env = opaque;
+ uint8_t sreg;
+
+ qemu_get_8s(f, &sreg);
+ cpu_set_sreg(env, sreg);
+ return 0;
+}
+
+static void put_sreg(QEMUFile *f, void *opaque, size_t size)
+{
+ CPUAVRState *env = opaque;
+ uint8_t sreg = cpu_get_sreg(env);
+
+ qemu_put_8s(f, &sreg);
+}
+
+static const VMStateInfo vms_sreg = {
+ .name = "sreg",
+ .get = get_sreg,
+ .put = put_sreg,
+};
+
+static int get_segment(QEMUFile *f, void *opaque, size_t size)
+{
+ uint32_t *ramp = opaque;
+ uint8_t temp = *ramp >> 16;
+
+ qemu_get_8s(f, &temp);
+ return 0;
+}
+
+static void put_segment(QEMUFile *f, void *opaque, size_t size)
+{
+ uint32_t *ramp = opaque;
+ uint8_t temp = 0;
+
+ qemu_put_8s(f, &temp);
+ *ramp = ((uint32_t)temp) << 16;
+}
+
+static const VMStateInfo vms_rampD = {
+ .name = "rampD",
+ .get = get_segment,
+ .put = put_segment,
+};
+static const VMStateInfo vms_rampX = {
+ .name = "rampX",
+ .get = get_segment,
+ .put = put_segment,
+};
+static const VMStateInfo vms_rampY = {
+ .name = "rampY",
+ .get = get_segment,
+ .put = put_segment,
+};
+static const VMStateInfo vms_rampZ = {
+ .name = "rampZ",
+ .get = get_segment,
+ .put = put_segment,
+};
+static const VMStateInfo vms_eind = {
+ .name = "eind",
+ .get = get_segment,
+ .put = put_segment,
+};
+
+const VMStateDescription vms_avr_cpu = {
+ .name = "cpu",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(env.pc_w, AVRCPU),
+ VMSTATE_UINT32(env.sp, AVRCPU),
+
+ VMSTATE_UINT32_ARRAY(env.r, AVRCPU, 32),
+ VMSTATE_UINT32_ARRAY(env.io, AVRCPU, 64),
+
+ VMSTATE_SINGLE_TEST(env, AVRCPU, NULL, 0, vms_sreg, CPUAVRState),
+ VMSTATE_SINGLE_TEST(env.rampD, AVRCPU, NULL, 0, vms_rampD, uint32_t),
+ VMSTATE_SINGLE_TEST(env.rampX, AVRCPU, NULL, 0, vms_rampX, uint32_t),
+ VMSTATE_SINGLE_TEST(env.rampY, AVRCPU, NULL, 0, vms_rampY, uint32_t),
+ VMSTATE_SINGLE_TEST(env.rampZ, AVRCPU, NULL, 0, vms_rampZ, uint32_t),
+ VMSTATE_SINGLE_TEST(env.eind, AVRCPU, NULL, 0, vms_eind, uint32_t),
+
+ VMSTATE_END_OF_LIST()
+ }
+};
diff --git a/target-avr/machine.h b/target-avr/machine.h
new file mode 100644
index 0000000..4cc8d6b
--- /dev/null
+++ b/target-avr/machine.h
@@ -0,0 +1,21 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+extern const VMStateDescription vmstate_avr_cpu;
diff --git a/target-avr/translate.c b/target-avr/translate.c
new file mode 100644
index 0000000..66ec98b
--- /dev/null
+++ b/target-avr/translate.c
@@ -0,0 +1,291 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "disas/disas.h"
+#include "tcg-op.h"
+#include "exec/cpu_ldst.h"
+
+#include "exec/helper-proto.h"
+#include "exec/helper-gen.h"
+#include "exec/log.h"
+
+typedef struct DisasContext DisasContext;
+typedef struct InstInfo InstInfo;
+
+/*This is the state at translation time. */
+struct DisasContext {
+ struct TranslationBlock *tb;
+
+ /*Routine used to access memory */
+ int memidx;
+ int bstate;
+ int singlestep;
+};
+
+enum {
+ BS_NONE = 0, /* Nothing special (none of the below */
+ BS_STOP = 1, /* We want to stop translation for any reason */
+ BS_BRANCH = 2, /* A branch condition is reached */
+ BS_EXCP = 3, /* An exception condition is reached */
+};
+
+static TCGv_env cpu_env;
+
+static TCGv cpu_pc;
+
+static TCGv cpu_Cf;
+static TCGv cpu_Zf;
+static TCGv cpu_Nf;
+static TCGv cpu_Vf;
+static TCGv cpu_Sf;
+static TCGv cpu_Hf;
+static TCGv cpu_Tf;
+static TCGv cpu_If;
+
+static TCGv cpu_rampD;
+static TCGv cpu_rampX;
+static TCGv cpu_rampY;
+static TCGv cpu_rampZ;
+
+static TCGv cpu_io[64];
+static TCGv cpu_r[32];
+static TCGv cpu_eind;
+static TCGv cpu_sp;
+
+#include "exec/gen-icount.h"
+#define REG(x) (cpu_r[x])
+
+void avr_translate_init(void)
+{
+ int i;
+ static int done_init;
+
+ if (done_init) {
+ return;
+ }
+#define AVR_REG_OFFS(x) offsetof(CPUAVRState, x)
+ cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+ cpu_pc = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(pc_w), "pc");
+ cpu_Cf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregC), "Cf");
+ cpu_Zf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregZ), "Zf");
+ cpu_Nf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregN), "Nf");
+ cpu_Vf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregV), "Vf");
+ cpu_Sf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregS), "Sf");
+ cpu_Hf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregH), "Hf");
+ cpu_Tf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregT), "Tf");
+ cpu_If = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregI), "If");
+ cpu_rampD = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampD), "rampD");
+ cpu_rampX = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampX), "rampX");
+ cpu_rampY = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampY), "rampY");
+ cpu_rampZ = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampZ), "rampZ");
+ cpu_eind = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(eind), "eind");
+ cpu_sp = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sp), "sp");
+
+ for (i = 0; i < 64; i++) {
+ char name[16];
+
+ sprintf(name, "io[%d]", i);
+
+ cpu_io[i] = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(io[i]), name);
+ }
+ for (i = 0; i < 32; i++) {
+ char name[16];
+
+ sprintf(name, "r[%d]", i);
+
+ cpu_r[i] = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(r[i]), name);
+ }
+
+ done_init = 1;
+}
+
+static inline void gen_goto_tb(CPUAVRState *env, DisasContext *ctx, int n,
+ target_ulong dest)
+{
+ TranslationBlock *tb;
+
+ tb = ctx->tb;
+
+ if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)
+ && (ctx->singlestep == 0)) {
+ tcg_gen_goto_tb(n);
+ tcg_gen_movi_i32(cpu_pc, dest);
+ tcg_gen_exit_tb((uintptr_t)tb + n);
+ } else {
+ tcg_gen_movi_i32(cpu_pc, dest);
+
+ if (ctx->singlestep) {
+ gen_helper_debug(cpu_env);
+ }
+ tcg_gen_exit_tb(0);
+ }
+}
+
+/*generate intermediate code for basic block 'tb'. */
+void gen_intermediate_code(CPUAVRState *env, struct TranslationBlock *tb)
+{
+ AVRCPU *cpu = avr_env_get_cpu(env);
+ CPUState *cs = CPU(cpu);
+ DisasContext ctx;
+ target_ulong pc_start;
+ int num_insns,
+ max_insns;
+ target_ulong cpc;
+ target_ulong npc;
+
+ pc_start = tb->pc / 2;
+ ctx.tb = tb;
+ ctx.memidx = 0;
+ ctx.bstate = BS_NONE;
+ ctx.singlestep = cs->singlestep_enabled;
+ num_insns = 0;
+ max_insns = tb->cflags & CF_COUNT_MASK;
+
+ if (max_insns == 0) {
+ max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
+
+ gen_tb_start(tb);
+
+ /* decode first instruction */
+ cpc = pc_start;
+ npc = cpc + 1;
+ do {
+ /* translate current instruction */
+ tcg_gen_insn_start(cpc);
+ num_insns++;
+
+ /* just skip to next instruction */
+ cpc++;
+ npc++;
+ ctx.bstate = BS_NONE;
+
+ if (unlikely(cpu_breakpoint_test(cs, cpc * 2, BP_ANY))) {
+ tcg_gen_movi_i32(cpu_pc, cpc);
+ gen_helper_debug(cpu_env);
+ ctx.bstate = BS_EXCP;
+ /*The address covered by the breakpoint must be included in
+ [tb->pc, tb->pc + tb->size) in order to for it to be
+ properly cleared -- thus we increment the PC here so that
+ the logic setting tb->size below does the right thing. */
+ goto done_generating;
+ }
+
+ if (num_insns >= max_insns) {
+ break; /* max translated instructions limit reached */
+ }
+ if (ctx.singlestep) {
+ break; /* single step */
+ }
+ if ((cpc & (TARGET_PAGE_SIZE - 1)) == 0) {
+ break; /* page boundary */
+ }
+ } while (ctx.bstate == BS_NONE && !tcg_op_buf_full());
+
+ if (tb->cflags & CF_LAST_IO) {
+ gen_io_end();
+ }
+
+ if (ctx.singlestep) {
+ if (ctx.bstate == BS_STOP || ctx.bstate == BS_NONE) {
+ tcg_gen_movi_tl(cpu_pc, npc);
+ }
+ gen_helper_debug(cpu_env);
+ tcg_gen_exit_tb(0);
+ } else {
+ switch (ctx.bstate) {
+ case BS_STOP:
+ case BS_NONE:
+ gen_goto_tb(env, &ctx, 0, npc);
+ break;
+ case BS_EXCP:
+ tcg_gen_exit_tb(0);
+ break;
+ default:
+ break;
+ }
+ }
+
+done_generating:
+ env->fullwr = false;
+ gen_tb_end(tb, num_insns);
+
+ tb->size = (npc - pc_start) * 2;
+ tb->icount = num_insns;
+}
+
+void restore_state_to_opc(CPUAVRState *env, TranslationBlock *tb,
+ target_ulong *data)
+{
+ env->pc_w = data[0];
+}
+
+void avr_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
+ int flags)
+{
+ AVRCPU *cpu = AVR_CPU(cs);
+ CPUAVRState *env = &cpu->env;
+
+ cpu_fprintf(f, "\n");
+ cpu_fprintf(f, "PC: %06x\n", env->pc_w);
+ cpu_fprintf(f, "SP: %04x\n", env->sp);
+ cpu_fprintf(f, "rampD: %02x\n", env->rampD >> 16);
+ cpu_fprintf(f, "rampX: %02x\n", env->rampX >> 16);
+ cpu_fprintf(f, "rampY: %02x\n", env->rampY >> 16);
+ cpu_fprintf(f, "rampZ: %02x\n", env->rampZ >> 16);
+ cpu_fprintf(f, "EIND: %02x\n", env->eind);
+ cpu_fprintf(f, "X: %02x%02x\n", env->r[27], env->r[26]);
+ cpu_fprintf(f, "Y: %02x%02x\n", env->r[29], env->r[28]);
+ cpu_fprintf(f, "Z: %02x%02x\n", env->r[31], env->r[30]);
+ cpu_fprintf(f, "SREG: [ %c %c %c %c %c %c %c %c ]\n",
+ env->sregI ? 'I' : '-',
+ env->sregT ? 'T' : '-',
+ env->sregH ? 'H' : '-',
+ env->sregS ? 'S' : '-',
+ env->sregV ? 'V' : '-',
+ env->sregN ? '-' : 'N', /* Zf has negative logic */
+ env->sregZ ? 'Z' : '-',
+ env->sregC ? 'I' : '-');
+
+ cpu_fprintf(f, "\n");
+ for (int i = 0; i < ARRAY_SIZE(env->r); i++) {
+ cpu_fprintf(f, "R[%02d]: %02x ", i, env->r[i]);
+
+ if ((i % 8) == 7) {
+ cpu_fprintf(f, "\n");
+ }
+ }
+
+ cpu_fprintf(f, "\n");
+ for (int i = 0; i < ARRAY_SIZE(env->io); i++) {
+ cpu_fprintf(f, "IO[%02d]: %02x ", i, env->io[i]);
+
+ if ((i % 8) == 7) {
+ cpu_fprintf(f, "\n");
+ }
+ }
+}
--
2.4.9 (Apple Git-60)
next prev parent reply other threads:[~2016-06-22 9:52 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-06-22 9:51 [Qemu-devel] [PATCH v9 00/10] 8bit AVR cores Michael Rolnik
2016-06-22 9:51 ` Michael Rolnik [this message]
2016-06-22 9:51 ` [Qemu-devel] [PATCH v9 02/10] target-avr: adding AVR CPU features/flavors Michael Rolnik
2016-06-22 9:51 ` [Qemu-devel] [PATCH v9 03/10] target-avr: adding a sample AVR board Michael Rolnik
2016-06-22 9:51 ` [Qemu-devel] [PATCH v9 04/10] target-avr: adding instructions encodings Michael Rolnik
2016-06-22 9:51 ` [Qemu-devel] [PATCH v9 05/10] target-avr: adding AVR interrupt handling Michael Rolnik
2016-06-22 9:51 ` [Qemu-devel] [PATCH v9 06/10] target-avr: adding helpers for IN, OUT, SLEEP, WBR & unsupported instructions Michael Rolnik
2016-06-22 9:51 ` [Qemu-devel] [PATCH v9 07/10] target-avr: adding instruction decoder Michael Rolnik
2016-06-22 9:51 ` [Qemu-devel] [PATCH v9 08/10] target-avr: adding instruction translation Michael Rolnik
2016-06-22 9:51 ` [Qemu-devel] [PATCH v9 09/10] target-avr: updating translate.c to use instructions translation Michael Rolnik
2016-06-22 9:51 ` [Qemu-devel] [PATCH v9 10/10] target-avr: decoder generator. currently not used by the build, can be used manually Michael Rolnik
-- strict thread matches above, loose matches on Subject: below --
2016-07-01 14:47 [Qemu-devel] [PATCH v9 00/10] 8bit AVR cores Michael Rolnik
2016-07-01 14:47 ` [Qemu-devel] [PATCH v9 01/10] target-avr: AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions 4. saving sreg, rampD, rampX, rampY, rampD, eind in HW representation saving cpu features Michael Rolnik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1466589115-57738-2-git-send-email-mrolnik@gmail.com \
--to=mrolnik@gmail.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is 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).