* [Qemu-devel] [PATCH v6 0/4] Moxie CPU port
@ 2013-03-02 12:24 Anthony Green
2013-03-02 12:24 ` [Qemu-devel] [PATCH v6 1/4] Add moxie target code Anthony Green
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Anthony Green @ 2013-03-02 12:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anthony Green
Here's the latest incarnation of the moxie patch set. I believe I've
addressed all of the major concerns and then some.
I ended up implementing moxie's new exception semantics so now
division by zero and illegal instructions both trap to an exception
handler routine. I was able to test this with a little C/asm code and
it works nicely.
Thanks!
AG
Anthony Green (4):
Add moxie target code
Add moxie disassembler
Add sample moxie system
Add top level changes for moxie
MAINTAINERS | 5 +
arch_init.c | 2 +
configure | 9 +-
cpu-exec.c | 2 +
default-configs/moxie-softmmu.mak | 2 +
disas.c | 6 +
disas/Makefile.objs | 1 +
disas/moxie.c | 360 +++++++++++++
hw/moxie/Makefile.objs | 6 +
hw/moxie/moxiesim.c | 174 +++++++
include/disas/bfd.h | 2 +
include/sysemu/arch_init.h | 1 +
qapi-schema.json | 6 +-
target-moxie/Makefile.objs | 2 +
target-moxie/cpu.c | 172 +++++++
target-moxie/cpu.h | 170 +++++++
target-moxie/helper.c | 97 ++++
target-moxie/helper.h | 9 +
target-moxie/machine.c | 27 +
target-moxie/machine.h | 2 +
target-moxie/mmu.c | 36 ++
target-moxie/mmu.h | 19 +
target-moxie/op_helper.c | 90 ++++
target-moxie/translate.c | 1003 +++++++++++++++++++++++++++++++++++++
24 files changed, 2199 insertions(+), 4 deletions(-)
create mode 100644 default-configs/moxie-softmmu.mak
create mode 100644 disas/moxie.c
create mode 100644 hw/moxie/Makefile.objs
create mode 100644 hw/moxie/moxiesim.c
create mode 100644 target-moxie/Makefile.objs
create mode 100644 target-moxie/cpu.c
create mode 100644 target-moxie/cpu.h
create mode 100644 target-moxie/helper.c
create mode 100644 target-moxie/helper.h
create mode 100644 target-moxie/machine.c
create mode 100644 target-moxie/machine.h
create mode 100644 target-moxie/mmu.c
create mode 100644 target-moxie/mmu.h
create mode 100644 target-moxie/op_helper.c
create mode 100644 target-moxie/translate.c
--
1.8.1.2
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH v6 1/4] Add moxie target code
2013-03-02 12:24 [Qemu-devel] [PATCH v6 0/4] Moxie CPU port Anthony Green
@ 2013-03-02 12:24 ` Anthony Green
2013-03-02 13:45 ` Peter Maydell
2013-03-02 12:24 ` [Qemu-devel] [PATCH v6 2/4] Add moxie disassembler Anthony Green
` (2 subsequent siblings)
3 siblings, 1 reply; 6+ messages in thread
From: Anthony Green @ 2013-03-02 12:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anthony Green
Signed-off-by: Anthony Green <green@moxielogic.com>
---
target-moxie/Makefile.objs | 2 +
target-moxie/cpu.c | 172 ++++++++
target-moxie/cpu.h | 170 ++++++++
target-moxie/helper.c | 97 +++++
target-moxie/helper.h | 9 +
target-moxie/machine.c | 27 ++
target-moxie/machine.h | 2 +
target-moxie/mmu.c | 36 ++
target-moxie/mmu.h | 19 +
target-moxie/op_helper.c | 90 ++++
target-moxie/translate.c | 1003 ++++++++++++++++++++++++++++++++++++++++++++
11 files changed, 1627 insertions(+)
create mode 100644 target-moxie/Makefile.objs
create mode 100644 target-moxie/cpu.c
create mode 100644 target-moxie/cpu.h
create mode 100644 target-moxie/helper.c
create mode 100644 target-moxie/helper.h
create mode 100644 target-moxie/machine.c
create mode 100644 target-moxie/machine.h
create mode 100644 target-moxie/mmu.c
create mode 100644 target-moxie/mmu.h
create mode 100644 target-moxie/op_helper.c
create mode 100644 target-moxie/translate.c
diff --git a/target-moxie/Makefile.objs b/target-moxie/Makefile.objs
new file mode 100644
index 0000000..130db4c
--- /dev/null
+++ b/target-moxie/Makefile.objs
@@ -0,0 +1,2 @@
+obj-y += translate.o op_helper.o helper.o machine.o cpu.o machine.o
+obj-$(CONFIG_SOFTMMU) += mmu.o
diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c
new file mode 100644
index 0000000..c17d3f0
--- /dev/null
+++ b/target-moxie/cpu.c
@@ -0,0 +1,172 @@
+/*
+ * QEMU Moxie CPU
+ *
+ * Copyright (c) 2013 Anthony Green
+ *
+ * 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 General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "migration/vmstate.h"
+#include "machine.h"
+
+static void moxie_cpu_reset(CPUState *s)
+{
+ MoxieCPU *cpu = MOXIE_CPU(s);
+ MoxieCPUClass *mcc = MOXIE_CPU_GET_CLASS(cpu);
+ CPUMoxieState *env = &cpu->env;
+
+ if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+ qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
+ log_cpu_state(env, 0);
+ }
+
+ mcc->parent_reset(s);
+
+ memset(env, 0, offsetof(CPUMoxieState, breakpoints));
+ env->pc = 0x1000;
+
+ tlb_flush(env, 1);
+}
+
+static void moxie_cpu_realizefn(DeviceState *dev, Error **errp)
+{
+ MoxieCPU *cpu = MOXIE_CPU(dev);
+ MoxieCPUClass *occ = MOXIE_CPU_GET_CLASS(dev);
+
+ qemu_init_vcpu(&cpu->env);
+ cpu_reset(CPU(cpu));
+
+ occ->parent_realize(dev, errp);
+}
+
+static void moxie_cpu_initfn(Object *obj)
+{
+ CPUState *cs = CPU(obj);
+ MoxieCPU *cpu = MOXIE_CPU(obj);
+ static int inited;
+
+ cs->env_ptr = &cpu->env;
+ cpu_exec_init(&cpu->env);
+
+ if (tcg_enabled() && !inited) {
+ inited = 1;
+ moxie_translate_init();
+ }
+}
+
+static ObjectClass *moxie_cpu_class_by_name(const char *cpu_model)
+{
+ ObjectClass *oc;
+
+ if (cpu_model == NULL) {
+ return NULL;
+ }
+
+ oc = object_class_by_name(cpu_model);
+ if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_MOXIE_CPU) ||
+ object_class_is_abstract(oc))) {
+ return NULL;
+ }
+ return oc;
+}
+
+static void moxie_cpu_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ CPUClass *cc = CPU_CLASS(oc);
+ MoxieCPUClass *mcc = MOXIE_CPU_CLASS(oc);
+
+ mcc->parent_realize = dc->realize;
+ dc->realize = moxie_cpu_realizefn;
+
+ mcc->parent_reset = cc->reset;
+ cc->reset = moxie_cpu_reset;
+
+ cc->class_by_name = moxie_cpu_class_by_name;
+
+ dc->vmsd = &vmstate_moxie_cpu;
+}
+
+static void moxielite_initfn(Object *obj)
+{
+ /* Set cpu feature flags */
+}
+
+static void moxie_any_initfn(Object *obj)
+{
+ /* Set cpu feature flags */
+}
+
+typedef struct MoxieCPUInfo {
+ const char *name;
+ void (*initfn)(Object *obj);
+} MoxieCPUInfo;
+
+static const MoxieCPUInfo moxie_cpus[] = {
+ { .name = "MoxieLite", .initfn = moxielite_initfn },
+ { .name = "any", .initfn = moxie_any_initfn },
+};
+
+MoxieCPU *cpu_moxie_init(const char *cpu_model)
+{
+ MoxieCPU *cpu;
+ ObjectClass *oc;
+
+ oc = moxie_cpu_class_by_name(cpu_model);
+ if (oc == NULL) {
+ return NULL;
+ }
+ cpu = MOXIE_CPU(object_new(object_class_get_name(oc)));
+ cpu->env.cpu_model_str = cpu_model;
+
+ object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
+
+ return cpu;
+}
+
+static void cpu_register(const MoxieCPUInfo *info)
+{
+ TypeInfo type_info = {
+ .parent = TYPE_MOXIE_CPU,
+ .instance_size = sizeof(MoxieCPU),
+ .instance_init = info->initfn,
+ .class_size = sizeof(MoxieCPUClass),
+ };
+
+ type_info.name = g_strdup_printf("%s-" TYPE_MOXIE_CPU, info->name);
+ type_register(&type_info);
+ g_free((void *)type_info.name);
+}
+
+static const TypeInfo moxie_cpu_type_info = {
+ .name = TYPE_MOXIE_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(MoxieCPU),
+ .instance_init = moxie_cpu_initfn,
+ .class_size = sizeof(MoxieCPUClass),
+ .class_init = moxie_cpu_class_init,
+};
+
+static void moxie_cpu_register_types(void)
+{
+ int i;
+ type_register_static(&moxie_cpu_type_info);
+ for (i = 0; i < ARRAY_SIZE(moxie_cpus); i++) {
+ cpu_register(&moxie_cpus[i]);
+ }
+}
+
+type_init(moxie_cpu_register_types)
diff --git a/target-moxie/cpu.h b/target-moxie/cpu.h
new file mode 100644
index 0000000..eb7354f
--- /dev/null
+++ b/target-moxie/cpu.h
@@ -0,0 +1,170 @@
+/*
+ * Moxie emulation
+ *
+ * Copyright (c) 2008, 2010, 2013 Anthony Green
+ *
+ * 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 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 General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _CPU_MOXIE_H
+#define _CPU_MOXIE_H
+
+#include "config.h"
+#include "qemu-common.h"
+
+#define TARGET_LONG_BITS 32
+
+#define CPUArchState struct CPUMoxieState
+
+#define TARGET_HAS_ICE 1
+
+#define CPU_SAVE_VERSION 1
+
+#define ELF_MACHINE 0xFEED /* EM_MOXIE */
+
+#define MOXIE_EX_DIV0 0
+#define MOXIE_EX_BAD 1
+#define MOXIE_EX_IRQ 2
+#define MOXIE_EX_SWI 3
+#define MOXIE_EX_MMU_MISS 4
+#define MOXIE_EX_BREAK 16
+
+#include "exec/cpu-defs.h"
+#include "fpu/softfloat.h"
+
+#define TARGET_PAGE_BITS 12 /* 4k */
+
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+
+#define NB_MMU_MODES 1
+
+#define CC_GT (1<<0)
+#define CC_LT (1<<1)
+#define CC_EQ (1<<2)
+#define CC_GTU (1<<3)
+#define CC_LTU (1<<4)
+
+typedef struct CPUMoxieState {
+
+ uint32_t flags; /* general execution flags */
+ uint32_t gregs[16]; /* general registers */
+ uint32_t sregs[256]; /* special registers */
+ uint32_t pc; /* program counter */
+ uint32_t cc; /* condition codes */
+
+ void *irq[8];
+
+ CPU_COMMON
+
+} CPUMoxieState;
+
+#include "qom/cpu.h"
+
+#define TYPE_MOXIE_CPU "moxie-cpu"
+
+#define MOXIE_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(MoxieCPUClass, (klass), TYPE_MOXIE_CPU)
+#define MOXIE_CPU(obj) \
+ OBJECT_CHECK(MoxieCPU, (obj), TYPE_MOXIE_CPU)
+#define MOXIE_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(MoxieCPUClass, (obj), TYPE_MOXIE_CPU)
+
+/**
+ * MoxieCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A Moxie CPU model.
+ */
+typedef struct MoxieCPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ DeviceRealize parent_realize;
+ void (*parent_reset)(CPUState *cpu);
+} MoxieCPUClass;
+
+/**
+ * MoxieCPU:
+ * @env: #CPUMoxieState
+ *
+ * A Moxie CPU.
+ */
+typedef struct MoxieCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUMoxieState env;
+} MoxieCPU;
+
+static inline MoxieCPU *moxie_env_get_cpu(CPUMoxieState *env)
+{
+ return MOXIE_CPU(container_of(env, MoxieCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(moxie_env_get_cpu(e))
+
+MoxieCPU *cpu_moxie_init(const char *cpu_model);
+int cpu_moxie_exec(CPUMoxieState *s);
+void do_interrupt(CPUMoxieState *env);
+void moxie_translate_init(void);
+int cpu_moxie_signal_handler(int host_signum, void *pinfo,
+ void *puc);
+
+static inline CPUMoxieState *cpu_init(const char *cpu_model)
+{
+ MoxieCPU *cpu = cpu_moxie_init(cpu_model);
+ if (cpu == NULL) {
+ return NULL;
+ }
+ return &cpu->env;
+}
+
+#define cpu_exec cpu_moxie_exec
+#define cpu_gen_code cpu_moxie_gen_code
+#define cpu_signal_handler cpu_moxie_signal_handler
+
+static inline int cpu_mmu_index(CPUMoxieState *env)
+{
+ return 0;
+}
+
+#include "exec/cpu-all.h"
+#include "exec/exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUMoxieState *env, TranslationBlock *tb)
+{
+ env->pc = tb->pc;
+}
+
+static inline void cpu_get_tb_cpu_state(CPUMoxieState *env, target_ulong *pc,
+ target_ulong *cs_base, int *flags)
+{
+ *pc = env->pc;
+ *cs_base = 0;
+ *flags = 0;
+}
+
+static inline int cpu_has_work(CPUState *cpu)
+{
+ CPUMoxieState *env = &MOXIE_CPU(cpu)->env;
+
+ return env->interrupt_request & CPU_INTERRUPT_HARD;
+}
+
+int cpu_moxie_handle_mmu_fault(CPUMoxieState *env, target_ulong address,
+ int rw, int mmu_idx);
+
+#endif /* _CPU_MOXIE_H */
diff --git a/target-moxie/helper.c b/target-moxie/helper.c
new file mode 100644
index 0000000..db6deb9
--- /dev/null
+++ b/target-moxie/helper.c
@@ -0,0 +1,97 @@
+/*
+ * Moxie helper routines.
+ *
+ * Copyright (c) 2008, 2009, 2010, 2013 Anthony Green
+ *
+ * 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 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 General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"
+#include "cpu.h"
+#include "mmu.h"
+#include "exec/exec-all.h"
+#include "qemu/host-utils.h"
+
+#if defined(CONFIG_USER_ONLY)
+
+void do_interrupt(CPUState *env)
+{
+ env->exception_index = -1;
+}
+
+int cpu_moxie_handle_mmu_fault(CPUMoxieState *env, target_ulong address,
+ int rw, int mmu_idx)
+{
+ env->exception_index = 0xaa;
+ env->debug1 = address;
+ cpu_dump_state(env, stderr, fprintf, 0);
+ return 1;
+}
+
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+{
+ return addr;
+}
+
+#else /* !CONFIG_USER_ONLY */
+
+int cpu_moxie_handle_mmu_fault(CPUMoxieState *env, target_ulong address,
+ int rw, int mmu_idx)
+{
+ struct moxie_mmu_result_t res;
+ int prot, miss;
+ target_ulong phy;
+ int r = 1;
+
+ address &= TARGET_PAGE_MASK;
+ prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ miss = moxie_mmu_translate(&res, env, address, rw, mmu_idx);
+ if (miss) {
+ /* handle the miss. */
+ phy = 0;
+ env->exception_index = MOXIE_EX_MMU_MISS;
+ } else {
+ phy = res.phy;
+ r = 0;
+ }
+ tlb_set_page(env, address, phy, prot, mmu_idx, TARGET_PAGE_SIZE);
+ return r;
+}
+
+
+void do_interrupt(CPUMoxieState *env)
+{
+ switch (env->exception_index) {
+ case MOXIE_EX_BREAK:
+ break;
+ default:
+ break;
+ }
+}
+
+hwaddr cpu_get_phys_page_debug(CPUMoxieState *env, target_ulong addr)
+{
+ uint32_t phy = addr;
+ struct moxie_mmu_result_t res;
+ int miss;
+ miss = moxie_mmu_translate(&res, env, addr, 0, 0);
+ if (!miss) {
+ phy = res.phy;
+ }
+ return phy;
+}
+#endif
diff --git a/target-moxie/helper.h b/target-moxie/helper.h
new file mode 100644
index 0000000..36ce126
--- /dev/null
+++ b/target-moxie/helper.h
@@ -0,0 +1,9 @@
+#include "exec/def-helper.h"
+
+DEF_HELPER_3(raise_exception, void, env, i32, int)
+DEF_HELPER_1(debug, void, env)
+DEF_HELPER_4(div, i32, env, i32, i32, i32)
+DEF_HELPER_4(udiv, i32, env, i32, i32, i32)
+
+#include "exec/def-helper.h"
+
diff --git a/target-moxie/machine.c b/target-moxie/machine.c
new file mode 100644
index 0000000..b8ed253
--- /dev/null
+++ b/target-moxie/machine.c
@@ -0,0 +1,27 @@
+#include "hw/hw.h"
+#include "hw/boards.h"
+
+const VMStateDescription vmstate_moxie_cpu = {
+ .name = "cpu",
+ .version_id = CPU_SAVE_VERSION,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(flags, CPUMoxieState),
+ VMSTATE_UINT32_ARRAY(gregs, CPUMoxieState, 16),
+ VMSTATE_UINT32_ARRAY(sregs, CPUMoxieState, 256),
+ VMSTATE_UINT32(pc, CPUMoxieState),
+ VMSTATE_UINT32(cc, CPUMoxieState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+void cpu_save(QEMUFile *f, void *opaque)
+{
+ vmstate_save_state(f, &vmstate_moxie_cpu, opaque);
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+ return vmstate_load_state(f, &vmstate_moxie_cpu, opaque, version_id);
+}
diff --git a/target-moxie/machine.h b/target-moxie/machine.h
new file mode 100644
index 0000000..eeb1b73
--- /dev/null
+++ b/target-moxie/machine.h
@@ -0,0 +1,2 @@
+extern const VMStateDescription vmstate_moxie_cpu;
+
diff --git a/target-moxie/mmu.c b/target-moxie/mmu.c
new file mode 100644
index 0000000..5217eed
--- /dev/null
+++ b/target-moxie/mmu.c
@@ -0,0 +1,36 @@
+/*
+ * Moxie mmu emulation.
+ *
+ * Copyright (c) 2008, 2013 Anthony Green
+ *
+ * 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 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 General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "cpu.h"
+#include "mmu.h"
+#include "exec/exec-all.h"
+
+int moxie_mmu_translate(MoxieMMUResult *res,
+ CPUMoxieState *env, uint32_t vaddr,
+ int rw, int mmu_idx)
+{
+ /* Perform no translation yet. */
+ res->phy = vaddr;
+ return 0;
+}
diff --git a/target-moxie/mmu.h b/target-moxie/mmu.h
new file mode 100644
index 0000000..25a7609
--- /dev/null
+++ b/target-moxie/mmu.h
@@ -0,0 +1,19 @@
+#define MOXIE_MMU_ERR_EXEC 0
+#define MOXIE_MMU_ERR_READ 1
+#define MOXIE_MMU_ERR_WRITE 2
+#define MOXIE_MMU_ERR_FLUSH 3
+
+typedef struct moxie_mmu_result_t {
+ uint32_t phy;
+ uint32_t pfn;
+ int g:1;
+ int v:1;
+ int k:1;
+ int w:1;
+ int e:1;
+ int cause_op;
+} MoxieMMUResult;
+
+int moxie_mmu_translate(MoxieMMUResult *res,
+ CPUMoxieState *env, uint32_t vaddr,
+ int rw, int mmu_idx);
diff --git a/target-moxie/op_helper.c b/target-moxie/op_helper.c
new file mode 100644
index 0000000..e157f4f
--- /dev/null
+++ b/target-moxie/op_helper.c
@@ -0,0 +1,90 @@
+/*
+ * Moxie helper routines
+ *
+ * Copyright (c) 2008, 2009, 2013 Anthony Green
+ *
+ * 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 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 General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include "cpu.h"
+#include "helper.h"
+
+#define MMUSUFFIX _mmu
+
+#define SHIFT 0
+#include "exec/softmmu_template.h"
+
+#define SHIFT 1
+#include "exec/softmmu_template.h"
+
+#define SHIFT 2
+#include "exec/softmmu_template.h"
+
+#define SHIFT 3
+#include "exec/softmmu_template.h"
+
+/* Try to fill the TLB and return an exception if error. If retaddr is
+ NULL, it means that the function was called in C code (i.e. not
+ from generated code or from helper.c) */
+void tlb_fill(CPUMoxieState *env, target_ulong addr, int is_write, int mmu_idx,
+ uintptr_t retaddr)
+{
+ int ret;
+
+ ret = cpu_moxie_handle_mmu_fault(env, addr, is_write, mmu_idx);
+ if (unlikely(ret)) {
+ if (retaddr) {
+ cpu_restore_state(env, retaddr);
+ }
+ }
+ cpu_loop_exit(env);
+}
+
+void helper_raise_exception(CPUMoxieState *env, uint32_t pc, int ex)
+{
+ env->exception_index = ex;
+ /* Stash the exception type. */
+ env->sregs[2] = ex;
+ /* Stash the address where the exception occurred. */
+ env->sregs[5] = pc;
+ /* Jump the the exception handline routine. */
+ env->pc = env->sregs[1];
+ cpu_loop_exit(env);
+}
+
+uint32_t helper_div(CPUMoxieState *env, uint32_t pc, uint32_t a, uint32_t b)
+{
+ if (unlikely(b == 0)) {
+ helper_raise_exception(env, pc, MOXIE_EX_DIV0);
+ return 0;
+ }
+ return (int32_t)a / (int32_t)b;
+}
+
+uint32_t helper_udiv(CPUMoxieState *env, uint32_t pc, uint32_t a, uint32_t b)
+{
+ if (unlikely(b == 0)) {
+ helper_raise_exception(env, pc, MOXIE_EX_DIV0);
+ return 0;
+ }
+ return a / b;
+}
+
+void helper_debug(CPUMoxieState *env)
+{
+ env->exception_index = EXCP_DEBUG;
+ cpu_loop_exit(env);
+}
+
diff --git a/target-moxie/translate.c b/target-moxie/translate.c
new file mode 100644
index 0000000..7ed4c0b
--- /dev/null
+++ b/target-moxie/translate.c
@@ -0,0 +1,1003 @@
+/*
+ * Moxie emulation for qemu: main translation routines.
+ *
+ * Copyright (c) 2009, 2013 Anthony Green
+ *
+ * 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 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 General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* For information on the Moxie architecture, see
+ * http://moxielogic.org/wiki
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "disas/disas.h"
+#include "tcg-op.h"
+
+#include "helper.h"
+#define GEN_HELPER 1
+#include "helper.h"
+
+/* This is the state at translation time. */
+typedef struct DisasContext {
+ struct TranslationBlock *tb;
+ target_ulong pc, saved_pc;
+ uint32_t opcode;
+ uint32_t fp_status;
+ /* Routine used to access memory */
+ int memidx;
+ int bstate;
+ target_ulong btarget;
+ int singlestep_enabled;
+} DisasContext;
+
+enum {
+ BS_NONE = 0, /* We go out of the TB without reaching a branch or an
+ * exception condition */
+ BS_STOP = 1, /* We want to stop translation for any reason */
+ BS_BRANCH = 2, /* We reached a branch condition */
+ BS_EXCP = 3, /* We reached an exception condition */
+};
+
+static TCGv cpu_pc;
+static TCGv cpu_gregs[16];
+static TCGv_ptr cpu_env;
+static TCGv cc;
+
+#define REG(x) (cpu_gregs[x])
+
+/* Extract the signed 10-bit offset from a 16-bit branch
+ instruction. */
+#define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
+
+void cpu_dump_state(CPUArchState *env, FILE *f, fprintf_function cpu_fprintf,
+ int flags)
+{
+ int i;
+ cpu_fprintf(f, "pc=0x%08x\n", env->pc);
+ cpu_fprintf(f, "$fp=0x%08x $sp=0x%08x $r0=0x%08x $r1=0x%08x\n",
+ env->gregs[0], env->gregs[1], env->gregs[2], env->gregs[3]);
+ for (i = 4; i < 16; i += 4) {
+ cpu_fprintf(f, "$r%d=0x%08x $r%d=0x%08x $r%d=0x%08x $r%d=0x%08x\n",
+ i-2, env->gregs[i], i-1, env->gregs[i + 1],
+ i, env->gregs[i + 2], i+1, env->gregs[i + 3]);
+ }
+ cpu_fprintf(f, "sr0=0x%08x $r1=0x%08x\n",
+ env->sregs[0], env->sregs[1]);
+}
+
+void moxie_translate_init(void)
+{
+ int i;
+ static int done_init;
+ static const char * const gregnames[16] = {
+ "$fp", "$sp", "$r0", "$r1",
+ "$r2", "$r3", "$r4", "$r5",
+ "$r6", "$r7", "$r8", "$r9",
+ "$r10", "$r11", "$r12", "$r13"
+ };
+
+ if (done_init) {
+ return;
+ }
+ cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+ cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUMoxieState, pc), "$pc");
+ for (i = 0; i < 24; i++)
+ cpu_gregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUMoxieState, gregs[i]),
+ gregnames[i]);
+
+ cc = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUMoxieState, cc), "cc");
+
+ done_init = 1;
+}
+
+static inline void gen_goto_tb(CPUMoxieState *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_enabled) {
+ tcg_gen_goto_tb(n);
+ tcg_gen_movi_i32(cpu_pc, dest);
+ tcg_gen_exit_tb((long) tb + n);
+ } else {
+ tcg_gen_movi_i32(cpu_pc, dest);
+ if (ctx->singlestep_enabled) {
+ gen_helper_debug(cpu_env);
+ }
+ tcg_gen_exit_tb(0);
+ }
+}
+
+static int decode_opc(MoxieCPU *cpu, DisasContext *ctx)
+{
+ CPUMoxieState *env = &cpu->env;
+
+ /* Local cache for the instruction opcode. */
+ int opcode;
+ /* Set the default instruction length. */
+ int length = 2;
+
+ if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
+ tcg_gen_debug_insn_start(ctx->pc);
+ }
+
+ /* Examine the 16-bit opcode. */
+ opcode = ctx->opcode;
+
+ /* Decode instruction. */
+ if (opcode & (1 << 15)) {
+ if (opcode & (1 << 14)) {
+ /* This is a Form 3 instruction. */
+ int inst = (opcode >> 10 & 0xf);
+
+ switch (inst) {
+ case 0x00: /* beq */
+ {
+ int l1 = gen_new_label();
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cc, CC_EQ, l1);
+ gen_goto_tb(env, ctx, 1, ctx->pc + 2);
+ gen_set_label(l1);
+ gen_goto_tb(env, ctx, 0, INST2OFFSET(opcode) + ctx->pc + 2);
+ ctx->bstate = BS_BRANCH;
+ }
+ break;
+ case 0x01: /* bne */
+ {
+ int l1 = gen_new_label();
+ tcg_gen_brcondi_i32(TCG_COND_NE, cc, CC_EQ, l1);
+ gen_goto_tb(env, ctx, 1, ctx->pc + 2);
+ gen_set_label(l1);
+ gen_goto_tb(env, ctx, 0, INST2OFFSET(opcode) + ctx->pc + 2);
+ ctx->bstate = BS_BRANCH;
+ }
+ break;
+ case 0x02: /* blt */
+ {
+ int l1 = gen_new_label();
+ TCGv t1 = tcg_temp_new_i32();
+ tcg_gen_andi_i32(t1, cc, CC_LT);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, t1, CC_LT, l1);
+ tcg_temp_free_i32(t1);
+ gen_goto_tb(env, ctx, 1, ctx->pc + 2);
+ gen_set_label(l1);
+ gen_goto_tb(env, ctx, 0, INST2OFFSET(opcode) + ctx->pc + 2);
+ ctx->bstate = BS_BRANCH;
+ }
+ break;
+ case 0x03: /* bgt */
+ {
+ int l1 = gen_new_label();
+ TCGv t1 = tcg_temp_new_i32();
+ tcg_gen_andi_i32(t1, cc, CC_GT);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, t1, CC_GT, l1);
+ tcg_temp_free_i32(t1);
+ gen_goto_tb(env, ctx, 1, ctx->pc + 2);
+ gen_set_label(l1);
+ gen_goto_tb(env, ctx, 0, INST2OFFSET(opcode) + ctx->pc + 2);
+ ctx->bstate = BS_BRANCH;
+ }
+ break;
+ case 0x04: /* bltu */
+ {
+ int l1 = gen_new_label();
+ TCGv t1 = tcg_temp_new_i32();
+ tcg_gen_andi_i32(t1, cc, CC_LTU);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, t1, CC_LTU, l1);
+ tcg_temp_free_i32(t1);
+ gen_goto_tb(env, ctx, 1, ctx->pc + 2);
+ gen_set_label(l1);
+ gen_goto_tb(env, ctx, 0, INST2OFFSET(opcode) + ctx->pc + 2);
+ ctx->bstate = BS_BRANCH;
+ }
+ break;
+ case 0x05: /* bgtu */
+ {
+ int l1 = gen_new_label();
+ TCGv t1 = tcg_temp_new_i32();
+ tcg_gen_andi_i32(t1, cc, CC_GTU);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, t1, CC_GTU, l1);
+ tcg_temp_free_i32(t1);
+ gen_goto_tb(env, ctx, 1, ctx->pc + 2);
+ gen_set_label(l1);
+ gen_goto_tb(env, ctx, 0, INST2OFFSET(opcode) + ctx->pc + 2);
+ ctx->bstate = BS_BRANCH;
+ }
+ break;
+ case 0x06: /* bge */
+ {
+ int l1 = gen_new_label();
+ TCGv t1 = tcg_temp_new_i32();
+ tcg_gen_andi_i32(t1, cc, CC_GT|CC_EQ);
+ tcg_gen_brcondi_i32(TCG_COND_GT, t1, 0, l1);
+ tcg_temp_free_i32(t1);
+ gen_goto_tb(env, ctx, 1, ctx->pc + 2);
+ gen_set_label(l1);
+ gen_goto_tb(env, ctx, 0, INST2OFFSET(opcode) + ctx->pc + 2);
+ ctx->bstate = BS_BRANCH;
+ }
+ break;
+ case 0x07: /* ble */
+ {
+ int l1 = gen_new_label();
+ TCGv t1 = tcg_temp_new_i32();
+ tcg_gen_andi_i32(t1, cc, CC_LT|CC_EQ);
+ tcg_gen_brcondi_i32(TCG_COND_GT, t1, 0, l1);
+ tcg_temp_free_i32(t1);
+ gen_goto_tb(env, ctx, 1, ctx->pc + 2);
+ gen_set_label(l1);
+ gen_goto_tb(env, ctx, 0, INST2OFFSET(opcode) + ctx->pc + 2);
+ ctx->bstate = BS_BRANCH;
+ }
+ break;
+ case 0x08: /* bgeu */
+ {
+ int l1 = gen_new_label();
+ TCGv t1 = tcg_temp_new_i32();
+ tcg_gen_andi_i32(t1, cc, CC_GTU|CC_EQ);
+ tcg_gen_brcondi_i32(TCG_COND_GT, t1, 0, l1);
+ tcg_temp_free_i32(t1);
+ gen_goto_tb(env, ctx, 1, ctx->pc + 2);
+ gen_set_label(l1);
+ gen_goto_tb(env, ctx, 0, INST2OFFSET(opcode) + ctx->pc + 2);
+ ctx->bstate = BS_BRANCH;
+ }
+ break;
+ case 0x09: /* bleu */
+ {
+ int l1 = gen_new_label();
+ TCGv t1 = tcg_temp_new_i32();
+ tcg_gen_andi_i32(t1, cc, CC_LTU|CC_EQ);
+ tcg_gen_brcondi_i32(TCG_COND_GT, t1, 0, l1);
+ tcg_temp_free_i32(t1);
+ gen_goto_tb(env, ctx, 1, ctx->pc + 2);
+ gen_set_label(l1);
+ gen_goto_tb(env, ctx, 0, INST2OFFSET(opcode) + ctx->pc + 2);
+ ctx->bstate = BS_BRANCH;
+ }
+ break;
+ default:
+ {
+ TCGv temp = tcg_temp_new_i32();
+ tcg_gen_movi_i32(cpu_pc, ctx->pc);
+ tcg_gen_movi_i32(temp, MOXIE_EX_BAD);
+ gen_helper_raise_exception(cpu_env, cpu_pc, temp);
+ tcg_temp_free_i32(temp);
+ }
+ break;
+ }
+ } else {
+ /* This is a Form 2 instruction. */
+ int inst = (opcode >> 12 & 0x3);
+ switch (inst) {
+ case 0x00: /* inc */
+ {
+ int a = (opcode >> 8) & 0xf;
+ unsigned int v = (opcode & 0xff);
+ tcg_gen_addi_i32(REG(a), REG(a), v);
+ }
+ break;
+ case 0x01: /* dec */
+ {
+ int a = (opcode >> 8) & 0xf;
+ unsigned int v = (opcode & 0xff);
+ tcg_gen_subi_i32(REG(a), REG(a), v);
+ }
+ break;
+ case 0x02: /* gsr */
+ {
+ int a = (opcode >> 8) & 0xf;
+ unsigned v = (opcode & 0xff);
+ tcg_gen_ld_i32(REG(a), cpu_env,
+ offsetof(CPUMoxieState, sregs[v]));
+ }
+ break;
+ case 0x03: /* ssr */
+ {
+ int a = (opcode >> 8) & 0xf;
+ unsigned v = (opcode & 0xff);
+ tcg_gen_st_i32(REG(a), cpu_env,
+ offsetof(CPUMoxieState, sregs[v]));
+ }
+ break;
+ default:
+ {
+ TCGv temp = tcg_temp_new_i32();
+ tcg_gen_movi_i32(cpu_pc, ctx->pc);
+ tcg_gen_movi_i32(temp, MOXIE_EX_BAD);
+ gen_helper_raise_exception(cpu_env, cpu_pc, temp);
+ tcg_temp_free_i32(temp);
+ }
+ break;
+ }
+ }
+ } else {
+ /* This is a Form 1 instruction. */
+ int inst = opcode >> 8;
+ switch (inst) {
+ case 0x00: /* nop */
+ break;
+ case 0x01: /* ldi.l (immediate) */
+ {
+ int reg = (opcode >> 4) & 0xf;
+ int val = cpu_ldl_code(env, ctx->pc + 2);
+ tcg_gen_movi_i32(REG(reg), val);
+ length = 6;
+ }
+ break;
+ case 0x02: /* mov (register-to-register) */
+ {
+ int dest = (opcode >> 4) & 0xf;
+ int src = opcode & 0xf;
+ tcg_gen_mov_i32(REG(dest), REG(src));
+ }
+ break;
+ case 0x03: /* jsra */
+ {
+ TCGv t1 = tcg_temp_new_i32();
+ TCGv t2 = tcg_temp_new_i32();
+
+ tcg_gen_movi_i32(t1, ctx->pc + 6);
+
+ /* Make space for the static chain and return address. */
+ tcg_gen_subi_i32(t2, REG(1), 8);
+ tcg_gen_mov_i32(REG(1), t2);
+ tcg_gen_qemu_st32(t1, REG(1), ctx->memidx);
+
+ /* Push the current frame pointer. */
+ tcg_gen_subi_i32(t2, REG(1), 4);
+ tcg_gen_mov_i32(REG(1), t2);
+ tcg_gen_qemu_st32(REG(0), REG(1), ctx->memidx);
+
+ /* Set the pc and $fp. */
+ tcg_gen_mov_i32(REG(0), REG(1));
+
+ gen_goto_tb(env, ctx, 0, cpu_ldl_code(env, ctx->pc + 2));
+
+ tcg_temp_free_i32(t1);
+ tcg_temp_free_i32(t2);
+
+ ctx->bstate = BS_BRANCH;
+ length = 6;
+ }
+ break;
+ case 0x04: /* ret */
+ {
+ TCGv t1 = tcg_temp_new_i32();
+
+ /* The new $sp is the old $fp. */
+ tcg_gen_mov_i32(REG(1), REG(0));
+
+ /* Pop the frame pointer. */
+ tcg_gen_qemu_ld32u(REG(0), REG(1), ctx->memidx);
+ tcg_gen_addi_i32(t1, REG(1), 4);
+ tcg_gen_mov_i32(REG(1), t1);
+
+
+ /* Pop the return address and skip over the static chain
+ slot. */
+ tcg_gen_qemu_ld32u(cpu_pc, REG(1), ctx->memidx);
+ tcg_gen_addi_i32(t1, REG(1), 8);
+ tcg_gen_mov_i32(REG(1), t1);
+
+ tcg_temp_free_i32(t1);
+
+ /* Jump... */
+ tcg_gen_exit_tb(0);
+
+ ctx->bstate = BS_BRANCH;
+ }
+ break;
+ case 0x05: /* add.l */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ tcg_gen_add_i32(REG(a), REG(a), REG(b));
+ }
+ break;
+ case 0x06: /* push */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ TCGv t1 = tcg_temp_new_i32();
+ tcg_gen_subi_i32(t1, REG(a), 4);
+ tcg_gen_mov_i32(REG(a), t1);
+ tcg_gen_qemu_st32(REG(b), REG(a), ctx->memidx);
+ tcg_temp_free_i32(t1);
+ }
+ break;
+ case 0x07: /* pop */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+ TCGv t1 = tcg_temp_new_i32();
+
+ tcg_gen_qemu_ld32u(REG(b), REG(a), ctx->memidx);
+ tcg_gen_addi_i32(t1, REG(a), 4);
+ tcg_gen_mov_i32(REG(a), t1);
+ tcg_temp_free_i32(t1);
+ }
+ break;
+ case 0x08: /* lda.l */
+ {
+ int reg = (opcode >> 4) & 0xf;
+
+ TCGv ptr = tcg_temp_new_i32();
+ tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc + 2));
+ tcg_gen_qemu_ld32u(REG(reg), ptr, ctx->memidx);
+ tcg_temp_free_i32(ptr);
+
+ length = 6;
+ }
+ break;
+ case 0x09: /* sta.l */
+ {
+ int val = (opcode >> 4) & 0xf;
+
+ TCGv ptr = tcg_temp_new_i32();
+ tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc + 2));
+ tcg_gen_qemu_st32(REG(val), ptr, ctx->memidx);
+ tcg_temp_free_i32(ptr);
+
+ length = 6;
+ }
+ break;
+ case 0x0a: /* ld.l (register indirect) */
+ {
+ int src = opcode & 0xf;
+ int dest = (opcode >> 4) & 0xf;
+
+ tcg_gen_qemu_ld32u(REG(dest), REG(src), ctx->memidx);
+ }
+ break;
+ case 0x0b: /* st.l */
+ {
+ int dest = (opcode >> 4) & 0xf;
+ int val = opcode & 0xf;
+
+ tcg_gen_qemu_st32(REG(val), REG(dest), ctx->memidx);
+ }
+ break;
+ case 0x0c: /* ldo.l */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ TCGv t1 = tcg_temp_new_i32();
+ TCGv t2 = tcg_temp_new_i32();
+ tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc + 2));
+ tcg_gen_qemu_ld32u(t2, t1, ctx->memidx);
+ tcg_gen_mov_i32(REG(a), t2);
+
+ tcg_temp_free_i32(t1);
+ tcg_temp_free_i32(t2);
+
+ length = 6;
+ }
+ break;
+ case 0x0d: /* sto.l */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ TCGv t1 = tcg_temp_new_i32();
+ TCGv t2 = tcg_temp_new_i32();
+ tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc + 2));
+ tcg_gen_qemu_st32(REG(b), t1, ctx->memidx);
+
+ tcg_temp_free_i32(t1);
+ tcg_temp_free_i32(t2);
+
+ length = 6;
+ }
+ break;
+ case 0x0e: /* cmp */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ int label_equal = gen_new_label();
+ int label_done = gen_new_label();
+
+ /* Clear CC */
+ tcg_gen_movi_i32(cc, 0);
+
+ tcg_gen_brcond_i32(TCG_COND_EQ, REG(a), REG(b), label_equal);
+
+#define CMPTEST(t, CODE) \
+ { \
+ int lyes = gen_new_label(); \
+ int lno = gen_new_label(); \
+ tcg_gen_brcond_i32(t, REG(a), REG(b), lyes); \
+ tcg_gen_br(lno); \
+ gen_set_label(lyes); \
+ tcg_gen_ori_i32(cc, cc, CODE); \
+ gen_set_label(lno); \
+ }
+ CMPTEST(TCG_COND_LT, CC_LT);
+ CMPTEST(TCG_COND_GT, CC_GT);
+ CMPTEST(TCG_COND_LTU, CC_LTU);
+ CMPTEST(TCG_COND_GTU, CC_GTU);
+ tcg_gen_br(label_done);
+ gen_set_label(label_equal);
+ tcg_gen_movi_i32(cc, CC_EQ);
+ gen_set_label(label_done);
+ }
+ break;
+ case 0x19: /* jsr */
+ {
+ int fnreg = (opcode >> 4) & 0xf;
+
+ /* Load the stack pointer into T0. */
+ TCGv t1 = tcg_temp_new_i32();
+ TCGv t2 = tcg_temp_new_i32();
+
+ tcg_gen_movi_i32(t1, ctx->pc + 2);
+
+ /* Make space for the static chain and return address. */
+ tcg_gen_subi_i32(t2, REG(1), 8);
+ tcg_gen_mov_i32(REG(1), t2);
+ tcg_gen_qemu_st32(t1, REG(1), ctx->memidx);
+
+ /* Push the current frame pointer. */
+ tcg_gen_subi_i32(t2, REG(1), 4);
+ tcg_gen_mov_i32(REG(1), t2);
+ tcg_gen_qemu_st32(REG(0), REG(1), ctx->memidx);
+
+ /* Set the pc and $fp. */
+ tcg_gen_mov_i32(REG(0), REG(1));
+ tcg_gen_mov_i32(cpu_pc, REG(fnreg));
+ tcg_temp_free_i32(t1);
+ tcg_temp_free_i32(t2);
+ tcg_gen_exit_tb(0);
+ ctx->bstate = BS_BRANCH;
+ }
+ break;
+ case 0x1a: /* jmpa */
+ {
+ tcg_gen_movi_i32(cpu_pc, cpu_ldl_code(env, ctx->pc + 2));
+ tcg_gen_exit_tb(0);
+ ctx->bstate = BS_BRANCH;
+ length = 6;
+ }
+ break;
+ case 0x1b: /* ldi.b (immediate) */
+ {
+ int reg = (opcode >> 4) & 0xf;
+ int val = cpu_ldl_code(env, ctx->pc + 2);
+ tcg_gen_movi_i32(REG(reg), val);
+ length = 6;
+ }
+ break;
+ case 0x1c: /* ld.b (register indirect) */
+ {
+ int src = opcode & 0xf;
+ int dest = (opcode >> 4) & 0xf;
+
+ tcg_gen_qemu_ld8u(REG(dest), REG(src), ctx->memidx);
+ }
+ break;
+ case 0x1d: /* lda.b */
+ {
+ int reg = (opcode >> 4) & 0xf;
+
+ TCGv ptr = tcg_temp_new_i32();
+ tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc + 2));
+ tcg_gen_qemu_ld8u(REG(reg), ptr, ctx->memidx);
+ tcg_temp_free_i32(ptr);
+
+ length = 6;
+ }
+ break;
+ case 0x1e: /* st.b */
+ {
+ int dest = (opcode >> 4) & 0xf;
+ int val = opcode & 0xf;
+
+ tcg_gen_qemu_st8(REG(val), REG(dest), ctx->memidx);
+ }
+ break;
+ case 0x1f: /* sta.b */
+ {
+ int val = (opcode >> 4) & 0xf;
+
+ TCGv ptr = tcg_temp_new_i32();
+ tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc + 2));
+ tcg_gen_qemu_st8(REG(val), ptr, ctx->memidx);
+ tcg_temp_free_i32(ptr);
+
+ length = 6;
+ }
+ break;
+ case 0x20: /* ldi.s (immediate) */
+ {
+ int reg = (opcode >> 4) & 0xf;
+ int val = cpu_ldl_code(env, ctx->pc + 2);
+ tcg_gen_movi_i32(REG(reg), val);
+ length = 6;
+ }
+ break;
+ case 0x21: /* ld.s (register indirect) */
+ {
+ int src = opcode & 0xf;
+ int dest = (opcode >> 4) & 0xf;
+
+ tcg_gen_qemu_ld16u(REG(dest), REG(src), ctx->memidx);
+ }
+ break;
+ case 0x22: /* lda.s */
+ {
+ int reg = (opcode >> 4) & 0xf;
+
+ TCGv ptr = tcg_temp_new_i32();
+ tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc + 2));
+ tcg_gen_qemu_ld16u(REG(reg), ptr, ctx->memidx);
+ tcg_temp_free_i32(ptr);
+
+ length = 6;
+ }
+ break;
+ case 0x23: /* st.s */
+ {
+ int dest = (opcode >> 4) & 0xf;
+ int val = opcode & 0xf;
+
+ tcg_gen_qemu_st16(REG(val), REG(dest), ctx->memidx);
+ }
+ break;
+ case 0x24: /* sta.s */
+ {
+ int val = (opcode >> 4) & 0xf;
+
+ TCGv ptr = tcg_temp_new_i32();
+ tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc + 2));
+ tcg_gen_qemu_st16(REG(val), ptr, ctx->memidx);
+ tcg_temp_free_i32(ptr);
+
+ length = 6;
+ }
+ break;
+ case 0x25: /* jmp */
+ {
+ int reg = (opcode >> 4) & 0xf;
+ tcg_gen_mov_i32(cpu_pc, REG(reg));
+ tcg_gen_exit_tb(0);
+ ctx->bstate = BS_BRANCH;
+ }
+ break;
+ case 0x26: /* and */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ tcg_gen_and_i32(REG(a), REG(a), REG(b));
+ }
+ break;
+ case 0x27: /* lshr */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ tcg_gen_shr_i32(REG(a), REG(a), REG(b));
+ }
+ break;
+ case 0x28: /* ashl */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ tcg_gen_shl_i32(REG(a), REG(a), REG(b));
+ }
+ break;
+ case 0x29: /* sub.l */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ tcg_gen_sub_i32(REG(a), REG(a), REG(b));
+ }
+ break;
+ case 0x2a: /* neg */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ tcg_gen_neg_i32(REG(a), REG(b));
+ }
+ break;
+ case 0x2b: /* or */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ tcg_gen_or_i32(REG(a), REG(a), REG(b));
+ }
+ break;
+ case 0x2c: /* not */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ tcg_gen_not_i32(REG(a), REG(b));
+ }
+ break;
+ case 0x2d: /* ashr */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ tcg_gen_sar_i32(REG(a), REG(a), REG(b));
+ }
+ break;
+ case 0x2e: /* xor */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ tcg_gen_xor_i32(REG(a), REG(a), REG(b));
+ }
+ break;
+ case 0x2f: /* mul.l */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ tcg_gen_mul_i32(REG(a), REG(a), REG(b));
+ }
+ break;
+ case 0x30: /* swi */
+ {
+ int val = cpu_ldl_code(env, ctx->pc + 2);
+
+ TCGv temp = tcg_temp_new_i32();
+ tcg_gen_movi_i32(temp, val);
+ tcg_gen_st_i32(temp, cpu_env,
+ offsetof(CPUMoxieState, sregs[3]));
+ tcg_gen_movi_i32(cpu_pc, ctx->pc);
+ tcg_gen_movi_i32(temp, MOXIE_EX_SWI);
+ gen_helper_raise_exception(cpu_env, cpu_pc, temp);
+ tcg_temp_free_i32(temp);
+
+ length = 6;
+ }
+ break;
+ case 0x31: /* div.l */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+ tcg_gen_movi_i32(cpu_pc, ctx->pc);
+ gen_helper_div(REG(a), cpu_env, cpu_pc, REG(a), REG(b));
+ }
+ break;
+ case 0x32: /* udiv.l */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+ tcg_gen_movi_i32(cpu_pc, ctx->pc);
+ gen_helper_udiv(REG(a), cpu_env, cpu_pc, REG(a), REG(b));
+ }
+ break;
+ case 0x33: /* mod.l */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+ tcg_gen_rem_i32(REG(a), REG(a), REG(b));
+ }
+ break;
+ case 0x34: /* umod.l */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+ tcg_gen_remu_i32(REG(a), REG(a), REG(b));
+ }
+ break;
+ case 0x35: /* brk */
+ {
+ gen_helper_debug(cpu_env);
+ }
+ break;
+ case 0x36: /* ldo.b */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ TCGv t1 = tcg_temp_new_i32();
+ TCGv t2 = tcg_temp_new_i32();
+ tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc + 2));
+ tcg_gen_qemu_ld8u(t2, t1, ctx->memidx);
+ tcg_gen_mov_i32(REG(a), t2);
+
+ tcg_temp_free_i32(t1);
+ tcg_temp_free_i32(t2);
+
+ length = 6;
+ }
+ break;
+ case 0x37: /* sto.b */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ TCGv t1 = tcg_temp_new_i32();
+ TCGv t2 = tcg_temp_new_i32();
+ tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc + 2));
+ tcg_gen_qemu_st8(REG(b), t1, ctx->memidx);
+
+ tcg_temp_free_i32(t1);
+ tcg_temp_free_i32(t2);
+
+ length = 6;
+ }
+ break;
+ case 0x38: /* ldo.s */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ TCGv t1 = tcg_temp_new_i32();
+ TCGv t2 = tcg_temp_new_i32();
+ tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc + 2));
+ tcg_gen_qemu_ld16u(t2, t1, ctx->memidx);
+ tcg_gen_mov_i32(REG(a), t2);
+
+ tcg_temp_free_i32(t1);
+ tcg_temp_free_i32(t2);
+
+ length = 6;
+ }
+ break;
+ case 0x39: /* sto.s */
+ {
+ int a = (opcode >> 4) & 0xf;
+ int b = opcode & 0xf;
+
+ TCGv t1 = tcg_temp_new_i32();
+ TCGv t2 = tcg_temp_new_i32();
+ tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc + 2));
+ tcg_gen_qemu_st16(REG(b), t1, ctx->memidx);
+ tcg_temp_free_i32(t1);
+ tcg_temp_free_i32(t2);
+
+ length = 6;
+ }
+ break;
+ default:
+ {
+ TCGv temp = tcg_temp_new_i32();
+ tcg_gen_movi_i32(cpu_pc, ctx->pc);
+ tcg_gen_movi_i32(temp, MOXIE_EX_BAD);
+ gen_helper_raise_exception(cpu_env, cpu_pc, temp);
+ tcg_temp_free_i32(temp);
+ }
+ break;
+ }
+ }
+
+ return length;
+}
+
+/* generate intermediate code for basic block 'tb'. */
+static void
+gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
+ bool search_pc)
+{
+ DisasContext ctx;
+ target_ulong pc_start;
+ uint16_t *gen_opc_end;
+ CPUBreakpoint *bp;
+ int j, lj = -1;
+ CPUMoxieState *env = &cpu->env;
+
+ pc_start = tb->pc;
+ gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
+ ctx.pc = pc_start;
+ ctx.saved_pc = -1;
+ ctx.tb = tb;
+ ctx.memidx = 0;
+ ctx.singlestep_enabled = 0;
+ ctx.bstate = BS_NONE;
+
+ do {
+ if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
+ QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+ if (ctx.pc == bp->pc) {
+ tcg_gen_movi_i32(cpu_pc, ctx.pc);
+ gen_helper_debug(cpu_env);
+ ctx.bstate = BS_EXCP;
+ goto done_generating;
+ }
+ }
+ }
+
+ if (search_pc) {
+ j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
+ if (lj < j) {
+ lj++;
+ while (lj < j) {
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
+ }
+ }
+ tcg_ctx.gen_opc_pc[lj] = ctx.pc;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ }
+ ctx.opcode = cpu_lduw_code(env, ctx.pc);
+ ctx.pc += decode_opc(cpu, &ctx);
+
+ if (env->singlestep_enabled) {
+ break;
+ }
+
+ if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) {
+ break;
+ }
+ } while (ctx.bstate == BS_NONE && tcg_ctx.gen_opc_ptr < gen_opc_end);
+
+ if (env->singlestep_enabled) {
+ tcg_gen_movi_tl(cpu_pc, ctx.pc);
+ gen_helper_debug(cpu_env);
+ } else {
+ switch (ctx.bstate) {
+ case BS_STOP:
+ case BS_NONE:
+ gen_goto_tb(env, &ctx, 0, ctx.pc);
+ break;
+ case BS_EXCP:
+ tcg_gen_exit_tb(0);
+ break;
+ case BS_BRANCH:
+ default:
+ break;
+ }
+ }
+ done_generating:
+ *tcg_ctx.gen_opc_ptr = INDEX_op_end;
+ if (search_pc) {
+ j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
+ lj++;
+ while (lj <= j) {
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
+ }
+ } else {
+ tb->size = ctx.pc - pc_start;
+ }
+}
+
+void gen_intermediate_code(CPUMoxieState *env, struct TranslationBlock *tb)
+{
+ gen_intermediate_code_internal(moxie_env_get_cpu(env), tb, false);
+}
+
+void gen_intermediate_code_pc(CPUMoxieState *env, struct TranslationBlock *tb)
+{
+ gen_intermediate_code_internal(moxie_env_get_cpu(env), tb, true);
+}
+
+void restore_state_to_opc(CPUMoxieState *env, TranslationBlock *tb, int pc_pos)
+{
+ env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+}
--
1.8.1.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH v6 2/4] Add moxie disassembler
2013-03-02 12:24 [Qemu-devel] [PATCH v6 0/4] Moxie CPU port Anthony Green
2013-03-02 12:24 ` [Qemu-devel] [PATCH v6 1/4] Add moxie target code Anthony Green
@ 2013-03-02 12:24 ` Anthony Green
2013-03-02 12:24 ` [Qemu-devel] [PATCH v6 3/4] Add sample moxie system Anthony Green
2013-03-02 12:24 ` [Qemu-devel] [PATCH v6 4/4] Add top level changes for moxie Anthony Green
3 siblings, 0 replies; 6+ messages in thread
From: Anthony Green @ 2013-03-02 12:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anthony Green
Signed-off-by: Anthony Green <green@moxielogic.com>
---
disas.c | 6 +
disas/Makefile.objs | 1 +
disas/moxie.c | 360 ++++++++++++++++++++++++++++++++++++++++++++++++++++
include/disas/bfd.h | 2 +
4 files changed, 369 insertions(+)
create mode 100644 disas/moxie.c
diff --git a/disas.c b/disas.c
index a46faee..74d3ba0 100644
--- a/disas.c
+++ b/disas.c
@@ -256,6 +256,9 @@ void target_disas(FILE *out, CPUArchState *env, target_ulong code,
#elif defined(TARGET_MICROBLAZE)
s.info.mach = bfd_arch_microblaze;
print_insn = print_insn_microblaze;
+#elif defined(TARGET_MOXIE)
+ s.info.mach = bfd_arch_moxie;
+ print_insn = print_insn_moxie;
#elif defined(TARGET_LM32)
s.info.mach = bfd_mach_lm32;
print_insn = print_insn_lm32;
@@ -462,6 +465,9 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
#elif defined(TARGET_S390X)
s.info.mach = bfd_mach_s390_64;
print_insn = print_insn_s390;
+#elif defined(TARGET_MOXIE)
+ s.info.mach = bfd_arch_moxie;
+ print_insn = print_insn_moxie;
#elif defined(TARGET_LM32)
s.info.mach = bfd_mach_lm32;
print_insn = print_insn_lm32;
diff --git a/disas/Makefile.objs b/disas/Makefile.objs
index ed75f9a..3b1e77a 100644
--- a/disas/Makefile.objs
+++ b/disas/Makefile.objs
@@ -7,6 +7,7 @@ common-obj-$(CONFIG_IA64_DIS) += ia64.o
common-obj-$(CONFIG_M68K_DIS) += m68k.o
common-obj-$(CONFIG_MICROBLAZE_DIS) += microblaze.o
common-obj-$(CONFIG_MIPS_DIS) += mips.o
+common-obj-$(CONFIG_MOXIE_DIS) += moxie.o
common-obj-$(CONFIG_PPC_DIS) += ppc.o
common-obj-$(CONFIG_S390_DIS) += s390.o
common-obj-$(CONFIG_SH4_DIS) += sh4.o
diff --git a/disas/moxie.c b/disas/moxie.c
new file mode 100644
index 0000000..4c5f180
--- /dev/null
+++ b/disas/moxie.c
@@ -0,0 +1,360 @@
+/* Disassemble moxie instructions.
+ Copyright (c) 2009 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#define STATIC_TABLE
+#define DEFINE_TABLE
+
+#include "disas/bfd.h"
+
+static void *stream;
+
+/* Form 1 instructions come in different flavors:
+
+ Some have no arguments (MOXIE_F1_NARG)
+ Some only use the A operand (MOXIE_F1_A)
+ Some use A and B registers (MOXIE_F1_AB)
+ Some use A and consume a 4 byte immediate value (MOXIE_F1_A4)
+ Some use just a 4 byte immediate value (MOXIE_F1_4)
+ Some use just a 4 byte memory address (MOXIE_F1_M)
+ Some use B and an indirect A (MOXIE_F1_AiB)
+ Some use A and an indirect B (MOXIE_F1_ABi)
+ Some consume a 4 byte immediate value and use X (MOXIE_F1_4A)
+ Some use B and an indirect A plus 4 bytes (MOXIE_F1_AiB4)
+ Some use A and an indirect B plus 4 bytes (MOXIE_F1_ABi4)
+
+ Form 2 instructions also come in different flavors:
+
+ Some have no arguments (MOXIE_F2_NARG)
+ Some use the A register and an 8-bit value (MOXIE_F2_A8V)
+
+ Form 3 instructions also come in different flavors:
+
+ Some have no arguments (MOXIE_F3_NARG)
+ Some have a 10-bit PC relative operand (MOXIE_F3_PCREL). */
+
+#define MOXIE_F1_NARG 0x100
+#define MOXIE_F1_A 0x101
+#define MOXIE_F1_AB 0x102
+/* #define MOXIE_F1_ABC 0x103 */
+#define MOXIE_F1_A4 0x104
+#define MOXIE_F1_4 0x105
+#define MOXIE_F1_AiB 0x106
+#define MOXIE_F1_ABi 0x107
+#define MOXIE_F1_4A 0x108
+#define MOXIE_F1_AiB4 0x109
+#define MOXIE_F1_ABi4 0x10a
+#define MOXIE_F1_M 0x10b
+
+#define MOXIE_F2_NARG 0x200
+#define MOXIE_F2_A8V 0x201
+
+#define MOXIE_F3_NARG 0x300
+#define MOXIE_F3_PCREL 0x301
+
+typedef struct moxie_opc_info_t {
+ short opcode;
+ unsigned itype;
+ const char * name;
+} moxie_opc_info_t;
+
+extern const moxie_opc_info_t moxie_form1_opc_info[64];
+extern const moxie_opc_info_t moxie_form2_opc_info[4];
+extern const moxie_opc_info_t moxie_form3_opc_info[16];
+
+/* The moxie processor's 16-bit instructions come in two forms:
+
+ FORM 1 instructions start with a 0 bit...
+
+ 0oooooooaaaabbbb
+ 0 F
+
+ ooooooo - form 1 opcode number
+ aaaa - operand A
+ bbbb - operand B
+
+ FORM 2 instructions start with bits "10"...
+
+ 10ooaaaavvvvvvvv
+ 0 F
+
+ oo - form 2 opcode number
+ aaaa - operand A
+ vvvvvvvv - 8-bit immediate value
+
+ FORM 3 instructions start with a bits "11"...
+
+ 11oooovvvvvvvvvv
+ 0 F
+
+ oooo - form 3 opcode number
+ vvvvvvvvvv - 10-bit immediate value. */
+
+const moxie_opc_info_t moxie_form1_opc_info[64] =
+ {
+ { 0x00, MOXIE_F1_NARG, "nop" },
+ { 0x01, MOXIE_F1_A4, "ldi.l" },
+ { 0x02, MOXIE_F1_AB, "mov" },
+ { 0x03, MOXIE_F1_M, "jsra" },
+ { 0x04, MOXIE_F1_NARG, "ret" },
+ { 0x05, MOXIE_F1_AB, "add.l" },
+ { 0x06, MOXIE_F1_AB, "push" },
+ { 0x07, MOXIE_F1_AB, "pop" },
+ { 0x08, MOXIE_F1_A4, "lda.l" },
+ { 0x09, MOXIE_F1_4A, "sta.l" },
+ { 0x0a, MOXIE_F1_ABi, "ld.l" },
+ { 0x0b, MOXIE_F1_AiB, "st.l" },
+ { 0x0c, MOXIE_F1_ABi4, "ldo.l" },
+ { 0x0d, MOXIE_F1_AiB4, "sto.l" },
+ { 0x0e, MOXIE_F1_AB, "cmp" },
+ { 0x0f, MOXIE_F1_NARG, "bad" },
+ { 0x10, MOXIE_F1_NARG, "bad" },
+ { 0x11, MOXIE_F1_NARG, "bad" },
+ { 0x12, MOXIE_F1_NARG, "bad" },
+ { 0x13, MOXIE_F1_NARG, "bad" },
+ { 0x14, MOXIE_F1_NARG, "bad" },
+ { 0x15, MOXIE_F1_NARG, "bad" },
+ { 0x16, MOXIE_F1_NARG, "bad" },
+ { 0x17, MOXIE_F1_NARG, "bad" },
+ { 0x18, MOXIE_F1_NARG, "bad" },
+ { 0x19, MOXIE_F1_A, "jsr" },
+ { 0x1a, MOXIE_F1_M, "jmpa" },
+ { 0x1b, MOXIE_F1_A4, "ldi.b" },
+ { 0x1c, MOXIE_F1_ABi, "ld.b" },
+ { 0x1d, MOXIE_F1_A4, "lda.b" },
+ { 0x1e, MOXIE_F1_AiB, "st.b" },
+ { 0x1f, MOXIE_F1_4A, "sta.b" },
+ { 0x20, MOXIE_F1_A4, "ldi.s" },
+ { 0x21, MOXIE_F1_ABi, "ld.s" },
+ { 0x22, MOXIE_F1_A4, "lda.s" },
+ { 0x23, MOXIE_F1_AiB, "st.s" },
+ { 0x24, MOXIE_F1_4A, "sta.s" },
+ { 0x25, MOXIE_F1_A, "jmp" },
+ { 0x26, MOXIE_F1_AB, "and" },
+ { 0x27, MOXIE_F1_AB, "lshr" },
+ { 0x28, MOXIE_F1_AB, "ashl" },
+ { 0x29, MOXIE_F1_AB, "sub.l" },
+ { 0x2a, MOXIE_F1_AB, "neg" },
+ { 0x2b, MOXIE_F1_AB, "or" },
+ { 0x2c, MOXIE_F1_AB, "not" },
+ { 0x2d, MOXIE_F1_AB, "ashr" },
+ { 0x2e, MOXIE_F1_AB, "xor" },
+ { 0x2f, MOXIE_F1_AB, "mul.l" },
+ { 0x30, MOXIE_F1_4, "swi" },
+ { 0x31, MOXIE_F1_AB, "div.l" },
+ { 0x32, MOXIE_F1_AB, "udiv.l" },
+ { 0x33, MOXIE_F1_AB, "mod.l" },
+ { 0x34, MOXIE_F1_AB, "umod.l" },
+ { 0x35, MOXIE_F1_NARG, "brk" },
+ { 0x36, MOXIE_F1_ABi4, "ldo.b" },
+ { 0x37, MOXIE_F1_AiB4, "sto.b" },
+ { 0x38, MOXIE_F1_ABi4, "ldo.s" },
+ { 0x39, MOXIE_F1_AiB4, "sto.s" },
+ { 0x3a, MOXIE_F1_NARG, "bad" },
+ { 0x3b, MOXIE_F1_NARG, "bad" },
+ { 0x3c, MOXIE_F1_NARG, "bad" },
+ { 0x3d, MOXIE_F1_NARG, "bad" },
+ { 0x3e, MOXIE_F1_NARG, "bad" },
+ { 0x3f, MOXIE_F1_NARG, "bad" }
+ };
+
+const moxie_opc_info_t moxie_form2_opc_info[4] =
+ {
+ { 0x00, MOXIE_F2_A8V, "inc" },
+ { 0x01, MOXIE_F2_A8V, "dec" },
+ { 0x02, MOXIE_F2_A8V, "gsr" },
+ { 0x03, MOXIE_F2_A8V, "ssr" }
+ };
+
+const moxie_opc_info_t moxie_form3_opc_info[16] =
+ {
+ { 0x00, MOXIE_F3_PCREL,"beq" },
+ { 0x01, MOXIE_F3_PCREL,"bne" },
+ { 0x02, MOXIE_F3_PCREL,"blt" },
+ { 0x03, MOXIE_F3_PCREL,"bgt" },
+ { 0x04, MOXIE_F3_PCREL,"bltu" },
+ { 0x05, MOXIE_F3_PCREL,"bgtu" },
+ { 0x06, MOXIE_F3_PCREL,"bge" },
+ { 0x07, MOXIE_F3_PCREL,"ble" },
+ { 0x08, MOXIE_F3_PCREL,"bgeu" },
+ { 0x09, MOXIE_F3_PCREL,"bleu" },
+ { 0x0a, MOXIE_F3_NARG, "bad" },
+ { 0x0b, MOXIE_F3_NARG, "bad" },
+ { 0x0c, MOXIE_F3_NARG, "bad" },
+ { 0x0d, MOXIE_F3_NARG, "bad" },
+ { 0x0e, MOXIE_F3_NARG, "bad" },
+ { 0x0f, MOXIE_F3_NARG, "bad" }
+ };
+
+/* Macros to extract operands from the instruction word. */
+#define OP_A(i) ((i >> 4) & 0xf)
+#define OP_B(i) (i & 0xf)
+#define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
+
+static const char * reg_names[16] =
+ { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
+ "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
+
+int
+print_insn_moxie(bfd_vma addr, struct disassemble_info * info)
+{
+ int length = 2;
+ int status;
+ stream = info->stream;
+ const moxie_opc_info_t * opcode;
+ bfd_byte buffer[4];
+ unsigned short iword;
+ fprintf_function fpr = info->fprintf_func;
+
+ if ((status = info->read_memory_func(addr, buffer, 2, info)))
+ goto fail;
+ iword = (bfd_getb16(buffer) >> 16);
+
+ /* Form 1 instructions have the high bit set to 0. */
+ if ((iword & (1<<15)) == 0) {
+ /* Extract the Form 1 opcode. */
+ opcode = &moxie_form1_opc_info[iword >> 8];
+ switch (opcode->itype) {
+ case MOXIE_F1_NARG:
+ fpr(stream, "%s", opcode->name);
+ break;
+ case MOXIE_F1_A:
+ fpr(stream, "%s\t%s", opcode->name,
+ reg_names[OP_A(iword)]);
+ break;
+ case MOXIE_F1_AB:
+ fpr(stream, "%s\t%s, %s", opcode->name,
+ reg_names[OP_A(iword)],
+ reg_names[OP_B(iword)]);
+ break;
+ case MOXIE_F1_A4:
+ {
+ unsigned imm;
+ if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
+ goto fail;
+ imm = bfd_getb32(buffer);
+ fpr(stream, "%s\t%s, 0x%x", opcode->name,
+ reg_names[OP_A(iword)], imm);
+ length = 6;
+ }
+ break;
+ case MOXIE_F1_4:
+ {
+ unsigned imm;
+ if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
+ goto fail;
+ imm = bfd_getb32(buffer);
+ fpr(stream, "%s\t0x%x", opcode->name, imm);
+ length = 6;
+ }
+ break;
+ case MOXIE_F1_M:
+ {
+ unsigned imm;
+ if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
+ goto fail;
+ imm = bfd_getb32(buffer);
+ fpr(stream, "%s\t", opcode->name);
+ info->print_address_func((bfd_vma) imm, info);
+ length = 6;
+ }
+ break;
+ case MOXIE_F1_AiB:
+ fpr (stream, "%s\t(%s), %s", opcode->name,
+ reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
+ break;
+ case MOXIE_F1_ABi:
+ fpr(stream, "%s\t%s, (%s)", opcode->name,
+ reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
+ break;
+ case MOXIE_F1_4A:
+ {
+ unsigned imm;
+ if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
+ goto fail;
+ imm = bfd_getb32(buffer);
+ fpr(stream, "%s\t0x%x, %s",
+ opcode->name, imm, reg_names[OP_A(iword)]);
+ length = 6;
+ }
+ break;
+ case MOXIE_F1_AiB4:
+ {
+ unsigned imm;
+ if ((status = info->read_memory_func(addr+2, buffer, 4, info)))
+ goto fail;
+ imm = bfd_getb32(buffer);
+ fpr(stream, "%s\t0x%x(%s), %s", opcode->name,
+ imm,
+ reg_names[OP_A(iword)],
+ reg_names[OP_B(iword)]);
+ length = 6;
+ }
+ break;
+ case MOXIE_F1_ABi4:
+ {
+ unsigned imm;
+ if ((status = info->read_memory_func(addr+2, buffer, 4, info)))
+ goto fail;
+ imm = bfd_getb32(buffer);
+ fpr(stream, "%s\t%s, 0x%x(%s)",
+ opcode->name,
+ reg_names[OP_A(iword)],
+ imm,
+ reg_names[OP_B(iword)]);
+ length = 6;
+ }
+ break;
+ default:
+ abort();
+ }
+ }
+ else if ((iword & (1<<14)) == 0) {
+ /* Extract the Form 2 opcode. */
+ opcode = &moxie_form2_opc_info[(iword >> 12) & 3];
+ switch (opcode->itype) {
+ case MOXIE_F2_A8V:
+ fpr(stream, "%s\t%s, 0x%x",
+ opcode->name,
+ reg_names[(iword >> 8) & 0xf],
+ iword & ((1 << 8) - 1));
+ break;
+ case MOXIE_F2_NARG:
+ fpr(stream, "%s", opcode->name);
+ break;
+ default:
+ abort();
+ }
+ } else {
+ /* Extract the Form 3 opcode. */
+ opcode = &moxie_form3_opc_info[(iword >> 10) & 15];
+ switch (opcode->itype) {
+ case MOXIE_F3_PCREL:
+ fpr(stream, "%s\t", opcode->name);
+ info->print_address_func((bfd_vma) (addr + INST2OFFSET(iword) + 2),
+ info);
+ break;
+ default:
+ abort();
+ }
+ }
+
+ return length;
+
+ fail:
+ info->memory_error_func(status, addr, info);
+ return -1;
+}
diff --git a/include/disas/bfd.h b/include/disas/bfd.h
index 3944b3c..803b6ef 100644
--- a/include/disas/bfd.h
+++ b/include/disas/bfd.h
@@ -218,6 +218,7 @@ enum bfd_architecture
#define bfd_mach_cris_v32 32
#define bfd_mach_cris_v10_v32 1032
bfd_arch_microblaze, /* Xilinx MicroBlaze. */
+ bfd_arch_moxie, /* The Moxie core. */
bfd_arch_ia64, /* HP/Intel ia64 */
#define bfd_mach_ia64_elf64 64
#define bfd_mach_ia64_elf32 32
@@ -392,6 +393,7 @@ int print_insn_m32r (bfd_vma, disassemble_info*);
int print_insn_m88k (bfd_vma, disassemble_info*);
int print_insn_mn10200 (bfd_vma, disassemble_info*);
int print_insn_mn10300 (bfd_vma, disassemble_info*);
+int print_insn_moxie (bfd_vma, disassemble_info*);
int print_insn_ns32k (bfd_vma, disassemble_info*);
int print_insn_big_powerpc (bfd_vma, disassemble_info*);
int print_insn_little_powerpc (bfd_vma, disassemble_info*);
--
1.8.1.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH v6 3/4] Add sample moxie system
2013-03-02 12:24 [Qemu-devel] [PATCH v6 0/4] Moxie CPU port Anthony Green
2013-03-02 12:24 ` [Qemu-devel] [PATCH v6 1/4] Add moxie target code Anthony Green
2013-03-02 12:24 ` [Qemu-devel] [PATCH v6 2/4] Add moxie disassembler Anthony Green
@ 2013-03-02 12:24 ` Anthony Green
2013-03-02 12:24 ` [Qemu-devel] [PATCH v6 4/4] Add top level changes for moxie Anthony Green
3 siblings, 0 replies; 6+ messages in thread
From: Anthony Green @ 2013-03-02 12:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anthony Green
Signed-off-by: Anthony Green <green@moxielogic.com>
---
hw/moxie/Makefile.objs | 6 ++
hw/moxie/moxiesim.c | 174 +++++++++++++++++++++++++++++++++++++++++++++
include/sysemu/arch_init.h | 1 +
3 files changed, 181 insertions(+)
create mode 100644 hw/moxie/Makefile.objs
create mode 100644 hw/moxie/moxiesim.c
diff --git a/hw/moxie/Makefile.objs b/hw/moxie/Makefile.objs
new file mode 100644
index 0000000..d0772d1
--- /dev/null
+++ b/hw/moxie/Makefile.objs
@@ -0,0 +1,6 @@
+# moxie boards
+obj-y = serial.o mc146818rtc.o vga.o
+obj-$(CONFIG_FDT) += device_tree.o
+
+obj-y := $(addprefix ../,$(obj-y))
+obj-y += moxiesim.o
diff --git a/hw/moxie/moxiesim.c b/hw/moxie/moxiesim.c
new file mode 100644
index 0000000..e1e88a9
--- /dev/null
+++ b/hw/moxie/moxiesim.c
@@ -0,0 +1,174 @@
+/*
+ * QEMU/moxiesim emulation
+ *
+ * Emulates a very simple machine model similiar to the one use by the
+ * GDB moxie simulator.
+ *
+ * Copyright (c) 2008, 2009, 2010, 2013 Anthony Green
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/serial.h"
+#include "exec/address-spaces.h"
+
+#define PHYS_MEM_BASE 0x80000000
+
+typedef struct {
+ uint64_t ram_size;
+ const char *kernel_filename;
+ const char *kernel_cmdline;
+ const char *initrd_filename;
+} LoaderParams;
+
+static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params)
+{
+ uint64_t entry, kernel_low, kernel_high;
+ long kernel_size;
+ long initrd_size;
+ ram_addr_t initrd_offset;
+
+ kernel_size = load_elf(loader_params->kernel_filename, NULL, NULL,
+ &entry, &kernel_low, &kernel_high, 1,
+ ELF_MACHINE, 0);
+
+ if (!kernel_size) {
+ fprintf(stderr, "qemu: could not load kernel '%s'\n",
+ loader_params->kernel_filename);
+ exit(1);
+ }
+
+ /* load initrd */
+ initrd_size = 0;
+ initrd_offset = 0;
+ if (loader_params->initrd_filename) {
+ initrd_size = get_image_size(loader_params->initrd_filename);
+ if (initrd_size > 0) {
+ initrd_offset = (kernel_high + ~TARGET_PAGE_MASK)
+ & TARGET_PAGE_MASK;
+ if (initrd_offset + initrd_size > loader_params->ram_size) {
+ fprintf(stderr,
+ "qemu: memory too small for initial ram disk '%s'\n",
+ loader_params->initrd_filename);
+ exit(1);
+ }
+ initrd_size = load_image_targphys(loader_params->initrd_filename,
+ initrd_offset,
+ ram_size);
+ }
+ if (initrd_size == (target_ulong)-1) {
+ fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+ loader_params->initrd_filename);
+ exit(1);
+ }
+ }
+}
+
+static void main_cpu_reset(void *opaque)
+{
+ MoxieCPU *cpu = opaque;
+
+ cpu_reset(CPU(cpu));
+}
+
+static inline DeviceState *
+moxie_intc_create(hwaddr base, qemu_irq irq, int kind_of_intr)
+{
+ DeviceState *dev;
+
+ dev = qdev_create(NULL, "moxie,intc");
+ qdev_prop_set_uint32(dev, "kind-of-intr", kind_of_intr);
+ qdev_init_nofail(dev);
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
+ return dev;
+}
+
+static void moxiesim_init(QEMUMachineInitArgs *args)
+{
+ MoxieCPU *cpu = NULL;
+ ram_addr_t ram_size = args->ram_size;
+ const char *cpu_model = args->cpu_model;
+ const char *kernel_filename = args->kernel_filename;
+ const char *kernel_cmdline = args->kernel_cmdline;
+ const char *initrd_filename = args->initrd_filename;
+ CPUMoxieState *env;
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *ram = g_new(MemoryRegion, 1);
+ MemoryRegion *rom = g_new(MemoryRegion, 1);
+ hwaddr ram_base = 0x200000;
+ LoaderParams loader_params;
+
+ /* Init CPUs. */
+ if (cpu_model == NULL) {
+ cpu_model = "MoxieLite-moxie-cpu";
+ }
+ cpu = cpu_moxie_init(cpu_model);
+ if (!cpu) {
+ fprintf(stderr, "Unable to find CPU definition\n");
+ exit(1);
+ }
+ env = &cpu->env;
+
+ qemu_register_reset(main_cpu_reset, cpu);
+
+ /* Allocate RAM. */
+ memory_region_init_ram(ram, "moxiesim.ram", ram_size);
+ vmstate_register_ram_global(ram);
+ memory_region_add_subregion(address_space_mem, ram_base, ram);
+
+ memory_region_init_ram(rom, "moxie.rom", 128*0x1000);
+ vmstate_register_ram_global(rom);
+ memory_region_add_subregion(get_system_memory(), 0x1000, rom);
+
+ if (kernel_filename) {
+ loader_params.ram_size = ram_size;
+ loader_params.kernel_filename = kernel_filename;
+ loader_params.kernel_cmdline = kernel_cmdline;
+ loader_params.initrd_filename = initrd_filename;
+ load_kernel(cpu, &loader_params);
+ }
+
+ /* A single 16450 sits at offset 0x3f8. */
+ if (serial_hds[0]) {
+ serial_mm_init(address_space_mem, 0x3f8, 0, env->irq[4],
+ 8000000/16, serial_hds[0], DEVICE_LITTLE_ENDIAN);
+ }
+}
+
+static QEMUMachine moxiesim_machine = {
+ .name = "moxiesim",
+ .desc = "Moxie simulator platform",
+ .init = moxiesim_init,
+ .is_default = 1,
+};
+
+static void moxie_machine_init(void)
+{
+ qemu_register_machine(&moxiesim_machine);
+}
+
+machine_init(moxie_machine_init)
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 5fc780c..8c8d78e 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -20,6 +20,7 @@ enum {
QEMU_ARCH_XTENSA = 4096,
QEMU_ARCH_OPENRISC = 8192,
QEMU_ARCH_UNICORE32 = 0x4000,
+ QEMU_ARCH_MOXIE = 0x8000,
};
extern const uint32_t arch_type;
--
1.8.1.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH v6 4/4] Add top level changes for moxie
2013-03-02 12:24 [Qemu-devel] [PATCH v6 0/4] Moxie CPU port Anthony Green
` (2 preceding siblings ...)
2013-03-02 12:24 ` [Qemu-devel] [PATCH v6 3/4] Add sample moxie system Anthony Green
@ 2013-03-02 12:24 ` Anthony Green
3 siblings, 0 replies; 6+ messages in thread
From: Anthony Green @ 2013-03-02 12:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Anthony Green
Signed-off-by: Anthony Green <green@moxielogic.com>
---
MAINTAINERS | 5 +++++
arch_init.c | 2 ++
configure | 9 ++++++++-
cpu-exec.c | 2 ++
default-configs/moxie-softmmu.mak | 2 ++
qapi-schema.json | 6 +++---
6 files changed, 22 insertions(+), 4 deletions(-)
create mode 100644 default-configs/moxie-softmmu.mak
diff --git a/MAINTAINERS b/MAINTAINERS
index 21043e4..b970159 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -91,6 +91,11 @@ M: Aurelien Jarno <aurelien@aurel32.net>
S: Odd Fixes
F: target-mips/
+Moxie
+M: Anthony Green <green@moxielogic.com>
+S: Maintained
+F: target-moxie/
+
PowerPC
M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
diff --git a/arch_init.c b/arch_init.c
index 8daeafa..ddae1b7 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -85,6 +85,8 @@ int graphic_depth = 15;
#define QEMU_ARCH QEMU_ARCH_MICROBLAZE
#elif defined(TARGET_MIPS)
#define QEMU_ARCH QEMU_ARCH_MIPS
+#elif defined(TARGET_MOXIE)
+#define QEMU_ARCH QEMU_ARCH_MOXIE
#elif defined(TARGET_OPENRISC)
#define QEMU_ARCH QEMU_ARCH_OPENRISC
#elif defined(TARGET_PPC)
diff --git a/configure b/configure
index 19738ac..ae5b3bc 100755
--- a/configure
+++ b/configure
@@ -958,6 +958,7 @@ mips-softmmu \
mipsel-softmmu \
mips64-softmmu \
mips64el-softmmu \
+moxie-softmmu \
or32-softmmu \
ppc-softmmu \
ppcemb-softmmu \
@@ -3913,7 +3914,7 @@ target_arch2=`echo $target | cut -d '-' -f 1`
target_bigendian="no"
case "$target_arch2" in
- armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|or32|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
+ armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or32|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
target_bigendian=yes
;;
esac
@@ -4018,6 +4019,8 @@ case "$target_arch2" in
echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak
target_long_alignment=8
;;
+ moxie)
+ ;;
or32)
TARGET_ARCH=openrisc
TARGET_BASE_ARCH=openrisc
@@ -4262,6 +4265,10 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
echo "CONFIG_MIPS_DIS=y" >> $config_target_mak
echo "CONFIG_MIPS_DIS=y" >> config-all-disas.mak
;;
+ moxie*)
+ echo "CONFIG_MOXIE_DIS=y" >> $config_target_mak
+ echo "CONFIG_MOXIE_DIS=y" >> config-all-disas.mak
+ ;;
or32)
echo "CONFIG_OPENRISC_DIS=y" >> $config_target_mak
echo "CONFIG_OPENRISC_DIS=y" >> config-all-disas.mak
diff --git a/cpu-exec.c b/cpu-exec.c
index afbe497..ba7ea41 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -221,6 +221,7 @@ int cpu_exec(CPUArchState *env)
#elif defined(TARGET_LM32)
#elif defined(TARGET_MICROBLAZE)
#elif defined(TARGET_MIPS)
+#elif defined(TARGET_MOXIE)
#elif defined(TARGET_OPENRISC)
#elif defined(TARGET_SH4)
#elif defined(TARGET_CRIS)
@@ -655,6 +656,7 @@ int cpu_exec(CPUArchState *env)
| env->cc_dest | (env->cc_x << 4);
#elif defined(TARGET_MICROBLAZE)
#elif defined(TARGET_MIPS)
+#elif defined(TARGET_MOXIE)
#elif defined(TARGET_OPENRISC)
#elif defined(TARGET_SH4)
#elif defined(TARGET_ALPHA)
diff --git a/default-configs/moxie-softmmu.mak b/default-configs/moxie-softmmu.mak
new file mode 100644
index 0000000..d378363
--- /dev/null
+++ b/default-configs/moxie-softmmu.mak
@@ -0,0 +1,2 @@
+# Default configuration for moxie-softmmu
+
diff --git a/qapi-schema.json b/qapi-schema.json
index 28b070f..233ea1b 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2994,9 +2994,9 @@
##
{ 'enum': 'TargetType',
'data': [ 'alpha', 'arm', 'cris', 'i386', 'lm32', 'm68k', 'microblazeel',
- 'microblaze', 'mips64el', 'mips64', 'mipsel', 'mips', 'or32',
- 'ppc64', 'ppcemb', 'ppc', 's390x', 'sh4eb', 'sh4', 'sparc64',
- 'sparc', 'unicore32', 'x86_64', 'xtensaeb', 'xtensa' ] }
+ 'microblaze', 'mips64el', 'mips64', 'mipsel', 'mips', 'moxie',
+ 'or32', 'ppc64', 'ppcemb', 'ppc', 's390x', 'sh4eb', 'sh4',
+ 'sparc64', 'sparc', 'unicore32', 'x86_64', 'xtensaeb', 'xtensa' ] }
##
# @TargetInfo:
--
1.8.1.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH v6 1/4] Add moxie target code
2013-03-02 12:24 ` [Qemu-devel] [PATCH v6 1/4] Add moxie target code Anthony Green
@ 2013-03-02 13:45 ` Peter Maydell
0 siblings, 0 replies; 6+ messages in thread
From: Peter Maydell @ 2013-03-02 13:45 UTC (permalink / raw)
To: Anthony Green; +Cc: qemu-devel
On 2 March 2013 12:24, Anthony Green <green@moxielogic.com> wrote:
> +uint32_t helper_div(CPUMoxieState *env, uint32_t pc, uint32_t a, uint32_t b)
> +{
> + if (unlikely(b == 0)) {
> + helper_raise_exception(env, pc, MOXIE_EX_DIV0);
This never returns, so the following 'return' is unreachable.
> + return 0;
> + }
> + return (int32_t)a / (int32_t)b;
> +}
You need to handle MININT / -1 too, because MININT idiv -1 is
undefined behaviour in C, and we mustn't allow the guest to
cause us to do that. (Does the Moxie architecture spec specify
the result here or does it say it's an unknown value, or does
it cause an exception, or is it genuinely unpredictable?)
Do you have a coherent rationale for what code you are putting
into op_helper.c and what into helper.c? (In most of QEMU's
existing targets the split is purely for historical reasons
since these files used to be compiled differently.)
-- PMM
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2013-03-02 13:45 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-02 12:24 [Qemu-devel] [PATCH v6 0/4] Moxie CPU port Anthony Green
2013-03-02 12:24 ` [Qemu-devel] [PATCH v6 1/4] Add moxie target code Anthony Green
2013-03-02 13:45 ` Peter Maydell
2013-03-02 12:24 ` [Qemu-devel] [PATCH v6 2/4] Add moxie disassembler Anthony Green
2013-03-02 12:24 ` [Qemu-devel] [PATCH v6 3/4] Add sample moxie system Anthony Green
2013-03-02 12:24 ` [Qemu-devel] [PATCH v6 4/4] Add top level changes for moxie Anthony Green
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).