diff options
author | Thomas Huth <thuth@redhat.com> | 2016-10-11 08:56:52 +0200 |
---|---|---|
committer | Thomas Huth <thuth@redhat.com> | 2016-12-20 21:52:12 +0100 |
commit | fcf5ef2ab52c621a4617ebbef36bf43b4003f4c0 (patch) | |
tree | 2b450d96b01455df8ed908bf8f26ddc388a03380 /target-openrisc | |
parent | 82ecffa8c050bf5bbc13329e9b65eac1caa5b55c (diff) | |
download | qemu-fcf5ef2ab52c621a4617ebbef36bf43b4003f4c0.zip qemu-fcf5ef2ab52c621a4617ebbef36bf43b4003f4c0.tar.gz qemu-fcf5ef2ab52c621a4617ebbef36bf43b4003f4c0.tar.bz2 |
Move target-* CPU file into a target/ folder
We've currently got 18 architectures in QEMU, and thus 18 target-xxx
folders in the root folder of the QEMU source tree. More architectures
(e.g. RISC-V, AVR) are likely to be included soon, too, so the main
folder of the QEMU sources slowly gets quite overcrowded with the
target-xxx folders.
To disburden the main folder a little bit, let's move the target-xxx
folders into a dedicated target/ folder, so that target-xxx/ simply
becomes target/xxx/ instead.
Acked-by: Laurent Vivier <laurent@vivier.eu> [m68k part]
Acked-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> [tricore part]
Acked-by: Michael Walle <michael@walle.cc> [lm32 part]
Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com> [s390x part]
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> [s390x part]
Acked-by: Eduardo Habkost <ehabkost@redhat.com> [i386 part]
Acked-by: Artyom Tarasenko <atar4qemu@gmail.com> [sparc part]
Acked-by: Richard Henderson <rth@twiddle.net> [alpha part]
Acked-by: Max Filippov <jcmvbkbc@gmail.com> [xtensa part]
Reviewed-by: David Gibson <david@gibson.dropbear.id.au> [ppc part]
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> [crisµblaze part]
Acked-by: Guan Xuetao <gxt@mprc.pku.edu.cn> [unicore32 part]
Signed-off-by: Thomas Huth <thuth@redhat.com>
Diffstat (limited to 'target-openrisc')
-rw-r--r-- | target-openrisc/Makefile.objs | 5 | ||||
-rw-r--r-- | target-openrisc/cpu.c | 278 | ||||
-rw-r--r-- | target-openrisc/cpu.h | 411 | ||||
-rw-r--r-- | target-openrisc/exception.c | 31 | ||||
-rw-r--r-- | target-openrisc/exception.h | 28 | ||||
-rw-r--r-- | target-openrisc/exception_helper.c | 30 | ||||
-rw-r--r-- | target-openrisc/fpu_helper.c | 301 | ||||
-rw-r--r-- | target-openrisc/gdbstub.c | 84 | ||||
-rw-r--r-- | target-openrisc/helper.h | 66 | ||||
-rw-r--r-- | target-openrisc/int_helper.c | 80 | ||||
-rw-r--r-- | target-openrisc/interrupt.c | 87 | ||||
-rw-r--r-- | target-openrisc/interrupt_helper.c | 60 | ||||
-rw-r--r-- | target-openrisc/machine.c | 54 | ||||
-rw-r--r-- | target-openrisc/mmu.c | 238 | ||||
-rw-r--r-- | target-openrisc/mmu_helper.c | 44 | ||||
-rw-r--r-- | target-openrisc/sys_helper.c | 288 | ||||
-rw-r--r-- | target-openrisc/translate.c | 1783 |
17 files changed, 0 insertions, 3868 deletions
diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs deleted file mode 100644 index 397d016..0000000 --- a/target-openrisc/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -obj-$(CONFIG_SOFTMMU) += machine.o -obj-y += cpu.o exception.o interrupt.o mmu.o translate.o -obj-y += exception_helper.o fpu_helper.o int_helper.o \ - interrupt_helper.o mmu_helper.o sys_helper.o -obj-y += gdbstub.o diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c deleted file mode 100644 index 698e87b..0000000 --- a/target-openrisc/cpu.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * QEMU OpenRISC CPU - * - * Copyright (c) 2012 Jia Liu <proljc@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "cpu.h" -#include "qemu-common.h" -#include "exec/exec-all.h" - -static void openrisc_cpu_set_pc(CPUState *cs, vaddr value) -{ - OpenRISCCPU *cpu = OPENRISC_CPU(cs); - - cpu->env.pc = value; -} - -static bool openrisc_cpu_has_work(CPUState *cs) -{ - return cs->interrupt_request & (CPU_INTERRUPT_HARD | - CPU_INTERRUPT_TIMER); -} - -/* CPUClass::reset() */ -static void openrisc_cpu_reset(CPUState *s) -{ - OpenRISCCPU *cpu = OPENRISC_CPU(s); - OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu); - - occ->parent_reset(s); - -#ifndef CONFIG_USER_ONLY - memset(&cpu->env, 0, offsetof(CPUOpenRISCState, tlb)); -#else - memset(&cpu->env, 0, offsetof(CPUOpenRISCState, irq)); -#endif - - tlb_flush(s, 1); - /*tb_flush(&cpu->env); FIXME: Do we need it? */ - - cpu->env.pc = 0x100; - cpu->env.sr = SR_FO | SR_SM; - s->exception_index = -1; - - cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP; - cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S; - cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2)); - cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2)); - -#ifndef CONFIG_USER_ONLY - cpu->env.picmr = 0x00000000; - cpu->env.picsr = 0x00000000; - - cpu->env.ttmr = 0x00000000; - cpu->env.ttcr = 0x00000000; -#endif -} - -static inline void set_feature(OpenRISCCPU *cpu, int feature) -{ - cpu->feature |= feature; - cpu->env.cpucfgr = cpu->feature; -} - -static void openrisc_cpu_realizefn(DeviceState *dev, Error **errp) -{ - CPUState *cs = CPU(dev); - OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(dev); - Error *local_err = NULL; - - cpu_exec_realizefn(cs, &local_err); - if (local_err != NULL) { - error_propagate(errp, local_err); - return; - } - - qemu_init_vcpu(cs); - cpu_reset(cs); - - occ->parent_realize(dev, errp); -} - -static void openrisc_cpu_initfn(Object *obj) -{ - CPUState *cs = CPU(obj); - OpenRISCCPU *cpu = OPENRISC_CPU(obj); - static int inited; - - cs->env_ptr = &cpu->env; - -#ifndef CONFIG_USER_ONLY - cpu_openrisc_mmu_init(cpu); -#endif - - if (tcg_enabled() && !inited) { - inited = 1; - openrisc_translate_init(); - } -} - -/* CPU models */ - -static ObjectClass *openrisc_cpu_class_by_name(const char *cpu_model) -{ - ObjectClass *oc; - char *typename; - - if (cpu_model == NULL) { - return NULL; - } - - typename = g_strdup_printf("%s-" TYPE_OPENRISC_CPU, cpu_model); - oc = object_class_by_name(typename); - g_free(typename); - if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_OPENRISC_CPU) || - object_class_is_abstract(oc))) { - return NULL; - } - return oc; -} - -static void or1200_initfn(Object *obj) -{ - OpenRISCCPU *cpu = OPENRISC_CPU(obj); - - set_feature(cpu, OPENRISC_FEATURE_OB32S); - set_feature(cpu, OPENRISC_FEATURE_OF32S); -} - -static void openrisc_any_initfn(Object *obj) -{ - OpenRISCCPU *cpu = OPENRISC_CPU(obj); - - set_feature(cpu, OPENRISC_FEATURE_OB32S); -} - -typedef struct OpenRISCCPUInfo { - const char *name; - void (*initfn)(Object *obj); -} OpenRISCCPUInfo; - -static const OpenRISCCPUInfo openrisc_cpus[] = { - { .name = "or1200", .initfn = or1200_initfn }, - { .name = "any", .initfn = openrisc_any_initfn }, -}; - -static void openrisc_cpu_class_init(ObjectClass *oc, void *data) -{ - OpenRISCCPUClass *occ = OPENRISC_CPU_CLASS(oc); - CPUClass *cc = CPU_CLASS(occ); - DeviceClass *dc = DEVICE_CLASS(oc); - - occ->parent_realize = dc->realize; - dc->realize = openrisc_cpu_realizefn; - - occ->parent_reset = cc->reset; - cc->reset = openrisc_cpu_reset; - - cc->class_by_name = openrisc_cpu_class_by_name; - cc->has_work = openrisc_cpu_has_work; - cc->do_interrupt = openrisc_cpu_do_interrupt; - cc->cpu_exec_interrupt = openrisc_cpu_exec_interrupt; - cc->dump_state = openrisc_cpu_dump_state; - cc->set_pc = openrisc_cpu_set_pc; - cc->gdb_read_register = openrisc_cpu_gdb_read_register; - cc->gdb_write_register = openrisc_cpu_gdb_write_register; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = openrisc_cpu_handle_mmu_fault; -#else - cc->get_phys_page_debug = openrisc_cpu_get_phys_page_debug; - dc->vmsd = &vmstate_openrisc_cpu; -#endif - cc->gdb_num_core_regs = 32 + 3; -} - -static void cpu_register(const OpenRISCCPUInfo *info) -{ - TypeInfo type_info = { - .parent = TYPE_OPENRISC_CPU, - .instance_size = sizeof(OpenRISCCPU), - .instance_init = info->initfn, - .class_size = sizeof(OpenRISCCPUClass), - }; - - type_info.name = g_strdup_printf("%s-" TYPE_OPENRISC_CPU, info->name); - type_register(&type_info); - g_free((void *)type_info.name); -} - -static const TypeInfo openrisc_cpu_type_info = { - .name = TYPE_OPENRISC_CPU, - .parent = TYPE_CPU, - .instance_size = sizeof(OpenRISCCPU), - .instance_init = openrisc_cpu_initfn, - .abstract = true, - .class_size = sizeof(OpenRISCCPUClass), - .class_init = openrisc_cpu_class_init, -}; - -static void openrisc_cpu_register_types(void) -{ - int i; - - type_register_static(&openrisc_cpu_type_info); - for (i = 0; i < ARRAY_SIZE(openrisc_cpus); i++) { - cpu_register(&openrisc_cpus[i]); - } -} - -OpenRISCCPU *cpu_openrisc_init(const char *cpu_model) -{ - return OPENRISC_CPU(cpu_generic_init(TYPE_OPENRISC_CPU, cpu_model)); -} - -/* Sort alphabetically by type name, except for "any". */ -static gint openrisc_cpu_list_compare(gconstpointer a, gconstpointer b) -{ - ObjectClass *class_a = (ObjectClass *)a; - ObjectClass *class_b = (ObjectClass *)b; - const char *name_a, *name_b; - - name_a = object_class_get_name(class_a); - name_b = object_class_get_name(class_b); - if (strcmp(name_a, "any-" TYPE_OPENRISC_CPU) == 0) { - return 1; - } else if (strcmp(name_b, "any-" TYPE_OPENRISC_CPU) == 0) { - return -1; - } else { - return strcmp(name_a, name_b); - } -} - -static void openrisc_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_OPENRISC_CPU)); - (*s->cpu_fprintf)(s->file, " %s\n", - name); - g_free(name); -} - -void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf) -{ - CPUListState s = { - .file = f, - .cpu_fprintf = cpu_fprintf, - }; - GSList *list; - - list = object_class_get_list(TYPE_OPENRISC_CPU, false); - list = g_slist_sort(list, openrisc_cpu_list_compare); - (*cpu_fprintf)(f, "Available CPUs:\n"); - g_slist_foreach(list, openrisc_cpu_list_entry, &s); - g_slist_free(list); -} - -type_init(openrisc_cpu_register_types) diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h deleted file mode 100644 index aaf1535..0000000 --- a/target-openrisc/cpu.h +++ /dev/null @@ -1,411 +0,0 @@ -/* - * OpenRISC virtual CPU header. - * - * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -#ifndef OPENRISC_CPU_H -#define OPENRISC_CPU_H - -#define TARGET_LONG_BITS 32 - -#define CPUArchState struct CPUOpenRISCState - -/* cpu_openrisc_map_address_* in CPUOpenRISCTLBContext need this decl. */ -struct OpenRISCCPU; - -#include "qemu-common.h" -#include "exec/cpu-defs.h" -#include "fpu/softfloat.h" -#include "qom/cpu.h" - -#define TYPE_OPENRISC_CPU "or32-cpu" - -#define OPENRISC_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU) -#define OPENRISC_CPU(obj) \ - OBJECT_CHECK(OpenRISCCPU, (obj), TYPE_OPENRISC_CPU) -#define OPENRISC_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(OpenRISCCPUClass, (obj), TYPE_OPENRISC_CPU) - -/** - * OpenRISCCPUClass: - * @parent_realize: The parent class' realize handler. - * @parent_reset: The parent class' reset handler. - * - * A OpenRISC CPU model. - */ -typedef struct OpenRISCCPUClass { - /*< private >*/ - CPUClass parent_class; - /*< public >*/ - - DeviceRealize parent_realize; - void (*parent_reset)(CPUState *cpu); -} OpenRISCCPUClass; - -#define NB_MMU_MODES 3 - -enum { - MMU_NOMMU_IDX = 0, - MMU_SUPERVISOR_IDX = 1, - MMU_USER_IDX = 2, -}; - -#define TARGET_PAGE_BITS 13 - -#define TARGET_PHYS_ADDR_SPACE_BITS 32 -#define TARGET_VIRT_ADDR_SPACE_BITS 32 - -#define SET_FP_CAUSE(reg, v) do {\ - (reg) = ((reg) & ~(0x3f << 12)) | \ - ((v & 0x3f) << 12);\ - } while (0) -#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f) -#define UPDATE_FP_FLAGS(reg, v) do {\ - (reg) |= ((v & 0x1f) << 2);\ - } while (0) - -/* Version Register */ -#define SPR_VR 0xFFFF003F - -/* Internal flags, delay slot flag */ -#define D_FLAG 1 - -/* Interrupt */ -#define NR_IRQS 32 - -/* Unit presece register */ -enum { - UPR_UP = (1 << 0), - UPR_DCP = (1 << 1), - UPR_ICP = (1 << 2), - UPR_DMP = (1 << 3), - UPR_IMP = (1 << 4), - UPR_MP = (1 << 5), - UPR_DUP = (1 << 6), - UPR_PCUR = (1 << 7), - UPR_PMP = (1 << 8), - UPR_PICP = (1 << 9), - UPR_TTP = (1 << 10), - UPR_CUP = (255 << 24), -}; - -/* CPU configure register */ -enum { - CPUCFGR_NSGF = (15 << 0), - CPUCFGR_CGF = (1 << 4), - CPUCFGR_OB32S = (1 << 5), - CPUCFGR_OB64S = (1 << 6), - CPUCFGR_OF32S = (1 << 7), - CPUCFGR_OF64S = (1 << 8), - CPUCFGR_OV64S = (1 << 9), -}; - -/* DMMU configure register */ -enum { - DMMUCFGR_NTW = (3 << 0), - DMMUCFGR_NTS = (7 << 2), - DMMUCFGR_NAE = (7 << 5), - DMMUCFGR_CRI = (1 << 8), - DMMUCFGR_PRI = (1 << 9), - DMMUCFGR_TEIRI = (1 << 10), - DMMUCFGR_HTR = (1 << 11), -}; - -/* IMMU configure register */ -enum { - IMMUCFGR_NTW = (3 << 0), - IMMUCFGR_NTS = (7 << 2), - IMMUCFGR_NAE = (7 << 5), - IMMUCFGR_CRI = (1 << 8), - IMMUCFGR_PRI = (1 << 9), - IMMUCFGR_TEIRI = (1 << 10), - IMMUCFGR_HTR = (1 << 11), -}; - -/* Float point control status register */ -enum { - FPCSR_FPEE = 1, - FPCSR_RM = (3 << 1), - FPCSR_OVF = (1 << 3), - FPCSR_UNF = (1 << 4), - FPCSR_SNF = (1 << 5), - FPCSR_QNF = (1 << 6), - FPCSR_ZF = (1 << 7), - FPCSR_IXF = (1 << 8), - FPCSR_IVF = (1 << 9), - FPCSR_INF = (1 << 10), - FPCSR_DZF = (1 << 11), -}; - -/* Exceptions indices */ -enum { - EXCP_RESET = 0x1, - EXCP_BUSERR = 0x2, - EXCP_DPF = 0x3, - EXCP_IPF = 0x4, - EXCP_TICK = 0x5, - EXCP_ALIGN = 0x6, - EXCP_ILLEGAL = 0x7, - EXCP_INT = 0x8, - EXCP_DTLBMISS = 0x9, - EXCP_ITLBMISS = 0xa, - EXCP_RANGE = 0xb, - EXCP_SYSCALL = 0xc, - EXCP_FPE = 0xd, - EXCP_TRAP = 0xe, - EXCP_NR, -}; - -/* Supervisor register */ -enum { - SR_SM = (1 << 0), - SR_TEE = (1 << 1), - SR_IEE = (1 << 2), - SR_DCE = (1 << 3), - SR_ICE = (1 << 4), - SR_DME = (1 << 5), - SR_IME = (1 << 6), - SR_LEE = (1 << 7), - SR_CE = (1 << 8), - SR_F = (1 << 9), - SR_CY = (1 << 10), - SR_OV = (1 << 11), - SR_OVE = (1 << 12), - SR_DSX = (1 << 13), - SR_EPH = (1 << 14), - SR_FO = (1 << 15), - SR_SUMRA = (1 << 16), - SR_SCE = (1 << 17), -}; - -/* OpenRISC Hardware Capabilities */ -enum { - OPENRISC_FEATURE_NSGF = (15 << 0), - OPENRISC_FEATURE_CGF = (1 << 4), - OPENRISC_FEATURE_OB32S = (1 << 5), - OPENRISC_FEATURE_OB64S = (1 << 6), - OPENRISC_FEATURE_OF32S = (1 << 7), - OPENRISC_FEATURE_OF64S = (1 << 8), - OPENRISC_FEATURE_OV64S = (1 << 9), -}; - -/* Tick Timer Mode Register */ -enum { - TTMR_TP = (0xfffffff), - TTMR_IP = (1 << 28), - TTMR_IE = (1 << 29), - TTMR_M = (3 << 30), -}; - -/* Timer Mode */ -enum { - TIMER_NONE = (0 << 30), - TIMER_INTR = (1 << 30), - TIMER_SHOT = (2 << 30), - TIMER_CONT = (3 << 30), -}; - -/* TLB size */ -enum { - DTLB_WAYS = 1, - DTLB_SIZE = 64, - DTLB_MASK = (DTLB_SIZE-1), - ITLB_WAYS = 1, - ITLB_SIZE = 64, - ITLB_MASK = (ITLB_SIZE-1), -}; - -/* TLB prot */ -enum { - URE = (1 << 6), - UWE = (1 << 7), - SRE = (1 << 8), - SWE = (1 << 9), - - SXE = (1 << 6), - UXE = (1 << 7), -}; - -/* check if tlb available */ -enum { - TLBRET_INVALID = -3, - TLBRET_NOMATCH = -2, - TLBRET_BADADDR = -1, - TLBRET_MATCH = 0 -}; - -typedef struct OpenRISCTLBEntry { - uint32_t mr; - uint32_t tr; -} OpenRISCTLBEntry; - -#ifndef CONFIG_USER_ONLY -typedef struct CPUOpenRISCTLBContext { - OpenRISCTLBEntry itlb[ITLB_WAYS][ITLB_SIZE]; - OpenRISCTLBEntry dtlb[DTLB_WAYS][DTLB_SIZE]; - - int (*cpu_openrisc_map_address_code)(struct OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, - target_ulong address, int rw); - int (*cpu_openrisc_map_address_data)(struct OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, - target_ulong address, int rw); -} CPUOpenRISCTLBContext; -#endif - -typedef struct CPUOpenRISCState { - target_ulong gpr[32]; /* General registers */ - target_ulong pc; /* Program counter */ - target_ulong npc; /* Next PC */ - target_ulong ppc; /* Prev PC */ - target_ulong jmp_pc; /* Jump PC */ - - target_ulong machi; /* Multiply register MACHI */ - target_ulong maclo; /* Multiply register MACLO */ - - target_ulong fpmaddhi; /* Multiply and add float register FPMADDHI */ - target_ulong fpmaddlo; /* Multiply and add float register FPMADDLO */ - - target_ulong epcr; /* Exception PC register */ - target_ulong eear; /* Exception EA register */ - - uint32_t sr; /* Supervisor register */ - uint32_t vr; /* Version register */ - uint32_t upr; /* Unit presence register */ - uint32_t cpucfgr; /* CPU configure register */ - uint32_t dmmucfgr; /* DMMU configure register */ - uint32_t immucfgr; /* IMMU configure register */ - uint32_t esr; /* Exception supervisor register */ - uint32_t fpcsr; /* Float register */ - float_status fp_status; - - uint32_t flags; /* cpu_flags, we only use it for exception - in solt so far. */ - uint32_t btaken; /* the SR_F bit */ - - CPU_COMMON - - /* Fields from here on are preserved across CPU reset. */ -#ifndef CONFIG_USER_ONLY - CPUOpenRISCTLBContext * tlb; - - QEMUTimer *timer; - uint32_t ttmr; /* Timer tick mode register */ - uint32_t ttcr; /* Timer tick count register */ - - uint32_t picmr; /* Interrupt mask register */ - uint32_t picsr; /* Interrupt contrl register*/ -#endif - void *irq[32]; /* Interrupt irq input */ -} CPUOpenRISCState; - -/** - * OpenRISCCPU: - * @env: #CPUOpenRISCState - * - * A OpenRISC CPU. - */ -typedef struct OpenRISCCPU { - /*< private >*/ - CPUState parent_obj; - /*< public >*/ - - CPUOpenRISCState env; - - uint32_t feature; /* CPU Capabilities */ -} OpenRISCCPU; - -static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env) -{ - return container_of(env, OpenRISCCPU, env); -} - -#define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e)) - -#define ENV_OFFSET offsetof(OpenRISCCPU, env) - -OpenRISCCPU *cpu_openrisc_init(const char *cpu_model); - -void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf); -void openrisc_cpu_do_interrupt(CPUState *cpu); -bool openrisc_cpu_exec_interrupt(CPUState *cpu, int int_req); -void openrisc_cpu_dump_state(CPUState *cpu, FILE *f, - fprintf_function cpu_fprintf, int flags); -hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); -int openrisc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); -int openrisc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); -void openrisc_translate_init(void); -int openrisc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, - int rw, int mmu_idx); -int cpu_openrisc_signal_handler(int host_signum, void *pinfo, void *puc); - -#define cpu_list cpu_openrisc_list -#define cpu_signal_handler cpu_openrisc_signal_handler - -#ifndef CONFIG_USER_ONLY -extern const struct VMStateDescription vmstate_openrisc_cpu; - -/* hw/openrisc_pic.c */ -void cpu_openrisc_pic_init(OpenRISCCPU *cpu); - -/* hw/openrisc_timer.c */ -void cpu_openrisc_clock_init(OpenRISCCPU *cpu); -void cpu_openrisc_count_update(OpenRISCCPU *cpu); -void cpu_openrisc_timer_update(OpenRISCCPU *cpu); -void cpu_openrisc_count_start(OpenRISCCPU *cpu); -void cpu_openrisc_count_stop(OpenRISCCPU *cpu); - -void cpu_openrisc_mmu_init(OpenRISCCPU *cpu); -int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, target_ulong address, int rw); -int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, target_ulong address, int rw); -int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, target_ulong address, int rw); -#endif - -#define cpu_init(cpu_model) CPU(cpu_openrisc_init(cpu_model)) - -#include "exec/cpu-all.h" - -static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, - target_ulong *pc, - target_ulong *cs_base, uint32_t *flags) -{ - *pc = env->pc; - *cs_base = 0; - /* D_FLAG -- branch instruction exception */ - *flags = (env->flags & D_FLAG); -} - -static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch) -{ - if (!(env->sr & SR_IME)) { - return MMU_NOMMU_IDX; - } - return (env->sr & SR_SM) == 0 ? MMU_USER_IDX : MMU_SUPERVISOR_IDX; -} - -#define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_INT_0 - -#endif /* OPENRISC_CPU_H */ diff --git a/target-openrisc/exception.c b/target-openrisc/exception.c deleted file mode 100644 index 49470be..0000000 --- a/target-openrisc/exception.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * OpenRISC exception. - * - * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/exec-all.h" -#include "exception.h" - -void QEMU_NORETURN raise_exception(OpenRISCCPU *cpu, uint32_t excp) -{ - CPUState *cs = CPU(cpu); - - cs->exception_index = excp; - cpu_loop_exit(cs); -} diff --git a/target-openrisc/exception.h b/target-openrisc/exception.h deleted file mode 100644 index 4ec56b4..0000000 --- a/target-openrisc/exception.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * OpenRISC exception header. - * - * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -#ifndef TARGET_OPENRISC_EXCEPTION_H -#define TARGET_OPENRISC_EXCEPTION_H - -#include "cpu.h" -#include "qemu-common.h" - -void QEMU_NORETURN raise_exception(OpenRISCCPU *cpu, uint32_t excp); - -#endif /* TARGET_OPENRISC_EXCEPTION_H */ diff --git a/target-openrisc/exception_helper.c b/target-openrisc/exception_helper.c deleted file mode 100644 index 329a9e4..0000000 --- a/target-openrisc/exception_helper.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * OpenRISC exception helper routines - * - * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/helper-proto.h" -#include "exception.h" - -void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp) -{ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - - raise_exception(cpu, excp); -} diff --git a/target-openrisc/fpu_helper.c b/target-openrisc/fpu_helper.c deleted file mode 100644 index c54404b..0000000 --- a/target-openrisc/fpu_helper.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * OpenRISC float helper routines - * - * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> - * Feng Gao <gf91597@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/helper-proto.h" -#include "exception.h" - -static inline uint32_t ieee_ex_to_openrisc(OpenRISCCPU *cpu, int fexcp) -{ - int ret = 0; - if (fexcp) { - if (fexcp & float_flag_invalid) { - cpu->env.fpcsr |= FPCSR_IVF; - ret = 1; - } - if (fexcp & float_flag_overflow) { - cpu->env.fpcsr |= FPCSR_OVF; - ret = 1; - } - if (fexcp & float_flag_underflow) { - cpu->env.fpcsr |= FPCSR_UNF; - ret = 1; - } - if (fexcp & float_flag_divbyzero) { - cpu->env.fpcsr |= FPCSR_DZF; - ret = 1; - } - if (fexcp & float_flag_inexact) { - cpu->env.fpcsr |= FPCSR_IXF; - ret = 1; - } - } - - return ret; -} - -static inline void update_fpcsr(OpenRISCCPU *cpu) -{ - int tmp = ieee_ex_to_openrisc(cpu, - get_float_exception_flags(&cpu->env.fp_status)); - - SET_FP_CAUSE(cpu->env.fpcsr, tmp); - if ((GET_FP_ENABLE(cpu->env.fpcsr) & tmp) && - (cpu->env.fpcsr & FPCSR_FPEE)) { - helper_exception(&cpu->env, EXCP_FPE); - } else { - UPDATE_FP_FLAGS(cpu->env.fpcsr, tmp); - } -} - -uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val) -{ - uint64_t itofd; - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - - set_float_exception_flags(0, &cpu->env.fp_status); - itofd = int32_to_float64(val, &cpu->env.fp_status); - update_fpcsr(cpu); - - return itofd; -} - -uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val) -{ - uint32_t itofs; - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - - set_float_exception_flags(0, &cpu->env.fp_status); - itofs = int32_to_float32(val, &cpu->env.fp_status); - update_fpcsr(cpu); - - return itofs; -} - -uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val) -{ - uint64_t ftoid; - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - - set_float_exception_flags(0, &cpu->env.fp_status); - ftoid = float32_to_int64(val, &cpu->env.fp_status); - update_fpcsr(cpu); - - return ftoid; -} - -uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val) -{ - uint32_t ftois; - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - - set_float_exception_flags(0, &cpu->env.fp_status); - ftois = float32_to_int32(val, &cpu->env.fp_status); - update_fpcsr(cpu); - - return ftois; -} - -#define FLOAT_OP(name, p) void helper_float_##_##p(void) - -#define FLOAT_CALC(name) \ -uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \ - uint64_t fdt0, uint64_t fdt1) \ -{ \ - uint64_t result; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - result = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return result; \ -} \ - \ -uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \ - uint32_t fdt0, uint32_t fdt1) \ -{ \ - uint32_t result; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - result = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return result; \ -} \ - -FLOAT_CALC(add) -FLOAT_CALC(sub) -FLOAT_CALC(mul) -FLOAT_CALC(div) -FLOAT_CALC(rem) -#undef FLOAT_CALC - -#define FLOAT_TERNOP(name1, name2) \ -uint64_t helper_float_ ## name1 ## name2 ## _d(CPUOpenRISCState *env, \ - uint64_t fdt0, \ - uint64_t fdt1) \ -{ \ - uint64_t result, temp, hi, lo; \ - uint32_t val1, val2; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - hi = env->fpmaddhi; \ - lo = env->fpmaddlo; \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - result = float64_ ## name1(fdt0, fdt1, &cpu->env.fp_status); \ - lo &= 0xffffffff; \ - hi &= 0xffffffff; \ - temp = (hi << 32) | lo; \ - result = float64_ ## name2(result, temp, &cpu->env.fp_status); \ - val1 = result >> 32; \ - val2 = (uint32_t) (result & 0xffffffff); \ - update_fpcsr(cpu); \ - cpu->env.fpmaddlo = val2; \ - cpu->env.fpmaddhi = val1; \ - return 0; \ -} \ - \ -uint32_t helper_float_ ## name1 ## name2 ## _s(CPUOpenRISCState *env, \ - uint32_t fdt0, uint32_t fdt1) \ -{ \ - uint64_t result, temp, hi, lo; \ - uint32_t val1, val2; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - hi = cpu->env.fpmaddhi; \ - lo = cpu->env.fpmaddlo; \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - result = float64_ ## name1(fdt0, fdt1, &cpu->env.fp_status); \ - temp = (hi << 32) | lo; \ - result = float64_ ## name2(result, temp, &cpu->env.fp_status); \ - val1 = result >> 32; \ - val2 = (uint32_t) (result & 0xffffffff); \ - update_fpcsr(cpu); \ - cpu->env.fpmaddlo = val2; \ - cpu->env.fpmaddhi = val1; \ - return 0; \ -} - -FLOAT_TERNOP(mul, add) -#undef FLOAT_TERNOP - - -#define FLOAT_CMP(name) \ -uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \ - uint64_t fdt0, uint64_t fdt1) \ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} \ - \ -uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \ - uint32_t fdt0, uint32_t fdt1)\ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} - -FLOAT_CMP(le) -FLOAT_CMP(eq) -FLOAT_CMP(lt) -#undef FLOAT_CMP - - -#define FLOAT_CMPNE(name) \ -uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \ - uint64_t fdt0, uint64_t fdt1) \ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = !float64_eq_quiet(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} \ - \ -uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \ - uint32_t fdt0, uint32_t fdt1) \ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = !float32_eq_quiet(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} - -FLOAT_CMPNE(ne) -#undef FLOAT_CMPNE - -#define FLOAT_CMPGT(name) \ -uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \ - uint64_t fdt0, uint64_t fdt1) \ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = !float64_le(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} \ - \ -uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \ - uint32_t fdt0, uint32_t fdt1) \ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = !float32_le(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} -FLOAT_CMPGT(gt) -#undef FLOAT_CMPGT - -#define FLOAT_CMPGE(name) \ -uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \ - uint64_t fdt0, uint64_t fdt1) \ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = !float64_lt(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} \ - \ -uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \ - uint32_t fdt0, uint32_t fdt1) \ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = !float32_lt(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} - -FLOAT_CMPGE(ge) -#undef FLOAT_CMPGE diff --git a/target-openrisc/gdbstub.c b/target-openrisc/gdbstub.c deleted file mode 100644 index cb16e76..0000000 --- a/target-openrisc/gdbstub.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * OpenRISC gdb server stub - * - * Copyright (c) 2003-2005 Fabrice Bellard - * Copyright (c) 2013 SUSE LINUX Products GmbH - * - * 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 Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - */ -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "cpu.h" -#include "exec/gdbstub.h" - -int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) -{ - OpenRISCCPU *cpu = OPENRISC_CPU(cs); - CPUOpenRISCState *env = &cpu->env; - - if (n < 32) { - return gdb_get_reg32(mem_buf, env->gpr[n]); - } else { - switch (n) { - case 32: /* PPC */ - return gdb_get_reg32(mem_buf, env->ppc); - - case 33: /* NPC */ - return gdb_get_reg32(mem_buf, env->npc); - - case 34: /* SR */ - return gdb_get_reg32(mem_buf, env->sr); - - default: - break; - } - } - return 0; -} - -int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) -{ - OpenRISCCPU *cpu = OPENRISC_CPU(cs); - CPUClass *cc = CPU_GET_CLASS(cs); - CPUOpenRISCState *env = &cpu->env; - uint32_t tmp; - - if (n > cc->gdb_num_core_regs) { - return 0; - } - - tmp = ldl_p(mem_buf); - - if (n < 32) { - env->gpr[n] = tmp; - } else { - switch (n) { - case 32: /* PPC */ - env->ppc = tmp; - break; - - case 33: /* NPC */ - env->npc = tmp; - break; - - case 34: /* SR */ - env->sr = tmp; - break; - - default: - break; - } - } - return 4; -} diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h deleted file mode 100644 index f53fa21..0000000 --- a/target-openrisc/helper.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * OpenRISC helper defines - * - * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -/* exception */ -DEF_HELPER_FLAGS_2(exception, 0, void, env, i32) - -/* float */ -DEF_HELPER_FLAGS_2(itofd, 0, i64, env, i64) -DEF_HELPER_FLAGS_2(itofs, 0, i32, env, i32) -DEF_HELPER_FLAGS_2(ftoid, 0, i64, env, i64) -DEF_HELPER_FLAGS_2(ftois, 0, i32, env, i32) - -#define FOP_MADD(op) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64) -FOP_MADD(muladd) -#undef FOP_MADD - -#define FOP_CALC(op) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64) -FOP_CALC(add) -FOP_CALC(sub) -FOP_CALC(mul) -FOP_CALC(div) -FOP_CALC(rem) -#undef FOP_CALC - -#define FOP_CMP(op) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64) -FOP_CMP(eq) -FOP_CMP(lt) -FOP_CMP(le) -FOP_CMP(ne) -FOP_CMP(gt) -FOP_CMP(ge) -#undef FOP_CMP - -/* int */ -DEF_HELPER_FLAGS_1(ff1, 0, tl, tl) -DEF_HELPER_FLAGS_1(fl1, 0, tl, tl) -DEF_HELPER_FLAGS_3(mul32, 0, i32, env, i32, i32) - -/* interrupt */ -DEF_HELPER_FLAGS_1(rfe, 0, void, env) - -/* sys */ -DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl) -DEF_HELPER_FLAGS_4(mfspr, 0, tl, env, tl, tl, tl) diff --git a/target-openrisc/int_helper.c b/target-openrisc/int_helper.c deleted file mode 100644 index 4d1f958..0000000 --- a/target-openrisc/int_helper.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * OpenRISC int helper routines - * - * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> - * Feng Gao <gf91597@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/helper-proto.h" -#include "exception.h" -#include "qemu/host-utils.h" - -target_ulong HELPER(ff1)(target_ulong x) -{ -/*#ifdef TARGET_OPENRISC64 - return x ? ctz64(x) + 1 : 0; -#else*/ - return x ? ctz32(x) + 1 : 0; -/*#endif*/ -} - -target_ulong HELPER(fl1)(target_ulong x) -{ -/* not used yet, open it when we need or64. */ -/*#ifdef TARGET_OPENRISC64 - return 64 - clz64(x); -#else*/ - return 32 - clz32(x); -/*#endif*/ -} - -uint32_t HELPER(mul32)(CPUOpenRISCState *env, - uint32_t ra, uint32_t rb) -{ - uint64_t result; - uint32_t high, cy; - - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - - result = (uint64_t)ra * rb; - /* regisiers in or32 is 32bit, so 32 is NOT a magic number. - or64 is not handled in this function, and not implement yet, - TARGET_LONG_BITS for or64 is 64, it will break this function, - so, we didn't use TARGET_LONG_BITS here. */ - high = result >> 32; - cy = result >> (32 - 1); - - if ((cy & 0x1) == 0x0) { - if (high == 0x0) { - return result; - } - } - - if ((cy & 0x1) == 0x1) { - if (high == 0xffffffff) { - return result; - } - } - - cpu->env.sr |= (SR_OV | SR_CY); - if (cpu->env.sr & SR_OVE) { - raise_exception(cpu, EXCP_RANGE); - } - - return result; -} diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c deleted file mode 100644 index 5fe3f11..0000000 --- a/target-openrisc/interrupt.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * OpenRISC interrupt. - * - * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/exec-all.h" -#include "qemu-common.h" -#include "exec/gdbstub.h" -#include "qemu/host-utils.h" -#ifndef CONFIG_USER_ONLY -#include "hw/loader.h" -#endif - -void openrisc_cpu_do_interrupt(CPUState *cs) -{ -#ifndef CONFIG_USER_ONLY - OpenRISCCPU *cpu = OPENRISC_CPU(cs); - CPUOpenRISCState *env = &cpu->env; - - env->epcr = env->pc; - if (env->flags & D_FLAG) { - env->flags &= ~D_FLAG; - env->sr |= SR_DSX; - env->epcr -= 4; - } - if (cs->exception_index == EXCP_SYSCALL) { - env->epcr += 4; - } - - /* For machine-state changed between user-mode and supervisor mode, - we need flush TLB when we enter&exit EXCP. */ - tlb_flush(cs, 1); - - env->esr = env->sr; - env->sr &= ~SR_DME; - env->sr &= ~SR_IME; - env->sr |= SR_SM; - env->sr &= ~SR_IEE; - env->sr &= ~SR_TEE; - env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; - env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; - - if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) { - env->pc = (cs->exception_index << 8); - } else { - cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index); - } -#endif - - cs->exception_index = -1; -} - -bool openrisc_cpu_exec_interrupt(CPUState *cs, int interrupt_request) -{ - OpenRISCCPU *cpu = OPENRISC_CPU(cs); - CPUOpenRISCState *env = &cpu->env; - int idx = -1; - - if ((interrupt_request & CPU_INTERRUPT_HARD) && (env->sr & SR_IEE)) { - idx = EXCP_INT; - } - if ((interrupt_request & CPU_INTERRUPT_TIMER) && (env->sr & SR_TEE)) { - idx = EXCP_TICK; - } - if (idx >= 0) { - cs->exception_index = idx; - openrisc_cpu_do_interrupt(cs); - return true; - } - return false; -} diff --git a/target-openrisc/interrupt_helper.c b/target-openrisc/interrupt_helper.c deleted file mode 100644 index 116f9109..0000000 --- a/target-openrisc/interrupt_helper.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * OpenRISC interrupt helper routines - * - * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> - * Feng Gao <gf91597@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/exec-all.h" -#include "exec/helper-proto.h" - -void HELPER(rfe)(CPUOpenRISCState *env) -{ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - CPUState *cs = CPU(cpu); -#ifndef CONFIG_USER_ONLY - int need_flush_tlb = (cpu->env.sr & (SR_SM | SR_IME | SR_DME)) ^ - (cpu->env.esr & (SR_SM | SR_IME | SR_DME)); -#endif - cpu->env.pc = cpu->env.epcr; - cpu->env.npc = cpu->env.epcr; - cpu->env.sr = cpu->env.esr; - -#ifndef CONFIG_USER_ONLY - if (cpu->env.sr & SR_DME) { - cpu->env.tlb->cpu_openrisc_map_address_data = - &cpu_openrisc_get_phys_data; - } else { - cpu->env.tlb->cpu_openrisc_map_address_data = - &cpu_openrisc_get_phys_nommu; - } - - if (cpu->env.sr & SR_IME) { - cpu->env.tlb->cpu_openrisc_map_address_code = - &cpu_openrisc_get_phys_code; - } else { - cpu->env.tlb->cpu_openrisc_map_address_code = - &cpu_openrisc_get_phys_nommu; - } - - if (need_flush_tlb) { - tlb_flush(cs, 1); - } -#endif - cs->interrupt_request |= CPU_INTERRUPT_EXITTB; -} diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c deleted file mode 100644 index 17b0c77..0000000 --- a/target-openrisc/machine.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * OpenRISC Machine - * - * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "cpu.h" -#include "hw/hw.h" -#include "hw/boards.h" -#include "migration/cpu.h" - -static const VMStateDescription vmstate_env = { - .name = "env", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(gpr, CPUOpenRISCState, 32), - VMSTATE_UINT32(sr, CPUOpenRISCState), - VMSTATE_UINT32(epcr, CPUOpenRISCState), - VMSTATE_UINT32(eear, CPUOpenRISCState), - VMSTATE_UINT32(esr, CPUOpenRISCState), - VMSTATE_UINT32(fpcsr, CPUOpenRISCState), - VMSTATE_UINT32(pc, CPUOpenRISCState), - VMSTATE_UINT32(npc, CPUOpenRISCState), - VMSTATE_UINT32(ppc, CPUOpenRISCState), - VMSTATE_END_OF_LIST() - } -}; - -const VMStateDescription vmstate_openrisc_cpu = { - .name = "cpu", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_CPU(), - VMSTATE_STRUCT(env, OpenRISCCPU, 1, vmstate_env, CPUOpenRISCState), - VMSTATE_END_OF_LIST() - } -}; diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c deleted file mode 100644 index 505dcdc..0000000 --- a/target-openrisc/mmu.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * OpenRISC MMU. - * - * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> - * Zhizhou Zhang <etouzh@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/exec-all.h" -#include "qemu-common.h" -#include "exec/gdbstub.h" -#include "qemu/host-utils.h" -#ifndef CONFIG_USER_ONLY -#include "hw/loader.h" -#endif - -#ifndef CONFIG_USER_ONLY -int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, target_ulong address, int rw) -{ - *physical = address; - *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; - return TLBRET_MATCH; -} - -int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, target_ulong address, int rw) -{ - int vpn = address >> TARGET_PAGE_BITS; - int idx = vpn & ITLB_MASK; - int right = 0; - - if ((cpu->env.tlb->itlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) { - return TLBRET_NOMATCH; - } - if (!(cpu->env.tlb->itlb[0][idx].mr & 1)) { - return TLBRET_INVALID; - } - - if (cpu->env.sr & SR_SM) { /* supervisor mode */ - if (cpu->env.tlb->itlb[0][idx].tr & SXE) { - right |= PAGE_EXEC; - } - } else { - if (cpu->env.tlb->itlb[0][idx].tr & UXE) { - right |= PAGE_EXEC; - } - } - - if ((rw & 2) && ((right & PAGE_EXEC) == 0)) { - return TLBRET_BADADDR; - } - - *physical = (cpu->env.tlb->itlb[0][idx].tr & TARGET_PAGE_MASK) | - (address & (TARGET_PAGE_SIZE-1)); - *prot = right; - return TLBRET_MATCH; -} - -int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, target_ulong address, int rw) -{ - int vpn = address >> TARGET_PAGE_BITS; - int idx = vpn & DTLB_MASK; - int right = 0; - - if ((cpu->env.tlb->dtlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) { - return TLBRET_NOMATCH; - } - if (!(cpu->env.tlb->dtlb[0][idx].mr & 1)) { - return TLBRET_INVALID; - } - - if (cpu->env.sr & SR_SM) { /* supervisor mode */ - if (cpu->env.tlb->dtlb[0][idx].tr & SRE) { - right |= PAGE_READ; - } - if (cpu->env.tlb->dtlb[0][idx].tr & SWE) { - right |= PAGE_WRITE; - } - } else { - if (cpu->env.tlb->dtlb[0][idx].tr & URE) { - right |= PAGE_READ; - } - if (cpu->env.tlb->dtlb[0][idx].tr & UWE) { - right |= PAGE_WRITE; - } - } - - if (!(rw & 1) && ((right & PAGE_READ) == 0)) { - return TLBRET_BADADDR; - } - if ((rw & 1) && ((right & PAGE_WRITE) == 0)) { - return TLBRET_BADADDR; - } - - *physical = (cpu->env.tlb->dtlb[0][idx].tr & TARGET_PAGE_MASK) | - (address & (TARGET_PAGE_SIZE-1)); - *prot = right; - return TLBRET_MATCH; -} - -static int cpu_openrisc_get_phys_addr(OpenRISCCPU *cpu, - hwaddr *physical, - int *prot, target_ulong address, - int rw) -{ - int ret = TLBRET_MATCH; - - if (rw == 2) { /* ITLB */ - *physical = 0; - ret = cpu->env.tlb->cpu_openrisc_map_address_code(cpu, physical, - prot, address, rw); - } else { /* DTLB */ - ret = cpu->env.tlb->cpu_openrisc_map_address_data(cpu, physical, - prot, address, rw); - } - - return ret; -} -#endif - -static void cpu_openrisc_raise_mmu_exception(OpenRISCCPU *cpu, - target_ulong address, - int rw, int tlb_error) -{ - CPUState *cs = CPU(cpu); - int exception = 0; - - switch (tlb_error) { - default: - if (rw == 2) { - exception = EXCP_IPF; - } else { - exception = EXCP_DPF; - } - break; -#ifndef CONFIG_USER_ONLY - case TLBRET_BADADDR: - if (rw == 2) { - exception = EXCP_IPF; - } else { - exception = EXCP_DPF; - } - break; - case TLBRET_INVALID: - case TLBRET_NOMATCH: - /* No TLB match for a mapped address */ - if (rw == 2) { - exception = EXCP_ITLBMISS; - } else { - exception = EXCP_DTLBMISS; - } - break; -#endif - } - - cs->exception_index = exception; - cpu->env.eear = address; -} - -#ifndef CONFIG_USER_ONLY -int openrisc_cpu_handle_mmu_fault(CPUState *cs, - vaddr address, int rw, int mmu_idx) -{ - OpenRISCCPU *cpu = OPENRISC_CPU(cs); - int ret = 0; - hwaddr physical = 0; - int prot = 0; - - ret = cpu_openrisc_get_phys_addr(cpu, &physical, &prot, - address, rw); - - if (ret == TLBRET_MATCH) { - tlb_set_page(cs, address & TARGET_PAGE_MASK, - physical & TARGET_PAGE_MASK, prot, - mmu_idx, TARGET_PAGE_SIZE); - ret = 0; - } else if (ret < 0) { - cpu_openrisc_raise_mmu_exception(cpu, address, rw, ret); - ret = 1; - } - - return ret; -} -#else -int openrisc_cpu_handle_mmu_fault(CPUState *cs, - vaddr address, int rw, int mmu_idx) -{ - OpenRISCCPU *cpu = OPENRISC_CPU(cs); - int ret = 0; - - cpu_openrisc_raise_mmu_exception(cpu, address, rw, ret); - ret = 1; - - return ret; -} -#endif - -#ifndef CONFIG_USER_ONLY -hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) -{ - OpenRISCCPU *cpu = OPENRISC_CPU(cs); - hwaddr phys_addr; - int prot; - - if (cpu_openrisc_get_phys_addr(cpu, &phys_addr, &prot, addr, 0)) { - return -1; - } - - return phys_addr; -} - -void cpu_openrisc_mmu_init(OpenRISCCPU *cpu) -{ - cpu->env.tlb = g_malloc0(sizeof(CPUOpenRISCTLBContext)); - - cpu->env.tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; - cpu->env.tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; -} -#endif diff --git a/target-openrisc/mmu_helper.c b/target-openrisc/mmu_helper.c deleted file mode 100644 index a44d0aa..0000000 --- a/target-openrisc/mmu_helper.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * OpenRISC MMU helper routines - * - * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> - * Zhizhou Zhang <etouzh@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/exec-all.h" -#include "exec/cpu_ldst.h" - -#ifndef CONFIG_USER_ONLY - -void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type, - int mmu_idx, uintptr_t retaddr) -{ - int ret; - - ret = openrisc_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx); - - if (ret) { - if (retaddr) { - /* now we have a real cpu fault. */ - cpu_restore_state(cs, retaddr); - } - /* Raise Exception. */ - cpu_loop_exit(cs); - } -} -#endif diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c deleted file mode 100644 index a719e45..0000000 --- a/target-openrisc/sys_helper.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * OpenRISC system instructions helper routines - * - * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> - * Zhizhou Zhang <etouzh@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/exec-all.h" -#include "exec/helper-proto.h" - -#define TO_SPR(group, number) (((group) << 11) + (number)) - -void HELPER(mtspr)(CPUOpenRISCState *env, - target_ulong ra, target_ulong rb, target_ulong offset) -{ -#ifndef CONFIG_USER_ONLY - int spr = (ra | offset); - int idx; - - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - CPUState *cs = CPU(cpu); - - switch (spr) { - case TO_SPR(0, 0): /* VR */ - env->vr = rb; - break; - - case TO_SPR(0, 16): /* NPC */ - env->npc = rb; - break; - - case TO_SPR(0, 17): /* SR */ - if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^ - (rb & (SR_IME | SR_DME | SR_SM))) { - tlb_flush(cs, 1); - } - env->sr = rb; - env->sr |= SR_FO; /* FO is const equal to 1 */ - if (env->sr & SR_DME) { - env->tlb->cpu_openrisc_map_address_data = - &cpu_openrisc_get_phys_data; - } else { - env->tlb->cpu_openrisc_map_address_data = - &cpu_openrisc_get_phys_nommu; - } - - if (env->sr & SR_IME) { - env->tlb->cpu_openrisc_map_address_code = - &cpu_openrisc_get_phys_code; - } else { - env->tlb->cpu_openrisc_map_address_code = - &cpu_openrisc_get_phys_nommu; - } - break; - - case TO_SPR(0, 18): /* PPC */ - env->ppc = rb; - break; - - case TO_SPR(0, 32): /* EPCR */ - env->epcr = rb; - break; - - case TO_SPR(0, 48): /* EEAR */ - env->eear = rb; - break; - - case TO_SPR(0, 64): /* ESR */ - env->esr = rb; - break; - case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */ - idx = spr - TO_SPR(1, 512); - if (!(rb & 1)) { - tlb_flush_page(cs, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK); - } - env->tlb->dtlb[0][idx].mr = rb; - break; - - case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */ - idx = spr - TO_SPR(1, 640); - env->tlb->dtlb[0][idx].tr = rb; - break; - case TO_SPR(1, 768) ... TO_SPR(1, 895): /* DTLBW1MR 0-127 */ - case TO_SPR(1, 896) ... TO_SPR(1, 1023): /* DTLBW1TR 0-127 */ - case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */ - case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */ - case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */ - case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */ - break; - case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* ITLBW0MR 0-127 */ - idx = spr - TO_SPR(2, 512); - if (!(rb & 1)) { - tlb_flush_page(cs, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK); - } - env->tlb->itlb[0][idx].mr = rb; - break; - - case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */ - idx = spr - TO_SPR(2, 640); - env->tlb->itlb[0][idx].tr = rb; - break; - case TO_SPR(2, 768) ... TO_SPR(2, 895): /* ITLBW1MR 0-127 */ - case TO_SPR(2, 896) ... TO_SPR(2, 1023): /* ITLBW1TR 0-127 */ - case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */ - case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 0-127 */ - case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */ - case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */ - break; - case TO_SPR(9, 0): /* PICMR */ - env->picmr |= rb; - break; - case TO_SPR(9, 2): /* PICSR */ - env->picsr &= ~rb; - break; - case TO_SPR(10, 0): /* TTMR */ - { - if ((env->ttmr & TTMR_M) ^ (rb & TTMR_M)) { - switch (rb & TTMR_M) { - case TIMER_NONE: - cpu_openrisc_count_stop(cpu); - break; - case TIMER_INTR: - case TIMER_SHOT: - case TIMER_CONT: - cpu_openrisc_count_start(cpu); - break; - default: - break; - } - } - - int ip = env->ttmr & TTMR_IP; - - if (rb & TTMR_IP) { /* Keep IP bit. */ - env->ttmr = (rb & ~TTMR_IP) | ip; - } else { /* Clear IP bit. */ - env->ttmr = rb & ~TTMR_IP; - cs->interrupt_request &= ~CPU_INTERRUPT_TIMER; - } - - cpu_openrisc_timer_update(cpu); - } - break; - - case TO_SPR(10, 1): /* TTCR */ - env->ttcr = rb; - if (env->ttmr & TIMER_NONE) { - return; - } - cpu_openrisc_timer_update(cpu); - break; - default: - - break; - } -#endif -} - -target_ulong HELPER(mfspr)(CPUOpenRISCState *env, - target_ulong rd, target_ulong ra, uint32_t offset) -{ -#ifndef CONFIG_USER_ONLY - int spr = (ra | offset); - int idx; - - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - - switch (spr) { - case TO_SPR(0, 0): /* VR */ - return env->vr & SPR_VR; - - case TO_SPR(0, 1): /* UPR */ - return env->upr; /* TT, DM, IM, UP present */ - - case TO_SPR(0, 2): /* CPUCFGR */ - return env->cpucfgr; - - case TO_SPR(0, 3): /* DMMUCFGR */ - return env->dmmucfgr; /* 1Way, 64 entries */ - - case TO_SPR(0, 4): /* IMMUCFGR */ - return env->immucfgr; - - case TO_SPR(0, 16): /* NPC */ - return env->npc; - - case TO_SPR(0, 17): /* SR */ - return env->sr; - - case TO_SPR(0, 18): /* PPC */ - return env->ppc; - - case TO_SPR(0, 32): /* EPCR */ - return env->epcr; - - case TO_SPR(0, 48): /* EEAR */ - return env->eear; - - case TO_SPR(0, 64): /* ESR */ - return env->esr; - - case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */ - idx = spr - TO_SPR(1, 512); - return env->tlb->dtlb[0][idx].mr; - - case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */ - idx = spr - TO_SPR(1, 640); - return env->tlb->dtlb[0][idx].tr; - - case TO_SPR(1, 768) ... TO_SPR(1, 895): /* DTLBW1MR 0-127 */ - case TO_SPR(1, 896) ... TO_SPR(1, 1023): /* DTLBW1TR 0-127 */ - case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */ - case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */ - case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */ - case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */ - break; - - case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* ITLBW0MR 0-127 */ - idx = spr - TO_SPR(2, 512); - return env->tlb->itlb[0][idx].mr; - - case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */ - idx = spr - TO_SPR(2, 640); - return env->tlb->itlb[0][idx].tr; - - case TO_SPR(2, 768) ... TO_SPR(2, 895): /* ITLBW1MR 0-127 */ - case TO_SPR(2, 896) ... TO_SPR(2, 1023): /* ITLBW1TR 0-127 */ - case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */ - case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 0-127 */ - case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */ - case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */ - break; - - case TO_SPR(9, 0): /* PICMR */ - return env->picmr; - - case TO_SPR(9, 2): /* PICSR */ - return env->picsr; - - case TO_SPR(10, 0): /* TTMR */ - return env->ttmr; - - case TO_SPR(10, 1): /* TTCR */ - cpu_openrisc_count_update(cpu); - return env->ttcr; - - default: - break; - } -#endif - -/*If we later need to add tracepoints (or debug printfs) for the return -value, it may be useful to structure the code like this: - -target_ulong ret = 0; - -switch() { -case x: - ret = y; - break; -case z: - ret = 42; - break; -... -} - -later something like trace_spr_read(ret); - -return ret;*/ - - /* for rd is passed in, if rd unchanged, just keep it back. */ - return rd; -} diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c deleted file mode 100644 index 229361a..0000000 --- a/target-openrisc/translate.c +++ /dev/null @@ -1,1783 +0,0 @@ -/* - * OpenRISC translation - * - * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> - * Feng Gao <gf91597@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 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/>. - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/exec-all.h" -#include "disas/disas.h" -#include "tcg-op.h" -#include "qemu-common.h" -#include "qemu/log.h" -#include "qemu/bitops.h" -#include "exec/cpu_ldst.h" - -#include "exec/helper-proto.h" -#include "exec/helper-gen.h" - -#include "trace-tcg.h" -#include "exec/log.h" - - -#define OPENRISC_DISAS - -#ifdef OPENRISC_DISAS -# define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__) -#else -# define LOG_DIS(...) do { } while (0) -#endif - -typedef struct DisasContext { - TranslationBlock *tb; - target_ulong pc, ppc, npc; - uint32_t tb_flags, synced_flags, flags; - uint32_t is_jmp; - uint32_t mem_idx; - int singlestep_enabled; - uint32_t delayed_branch; -} DisasContext; - -static TCGv_env cpu_env; -static TCGv cpu_sr; -static TCGv cpu_R[32]; -static TCGv cpu_pc; -static TCGv jmp_pc; /* l.jr/l.jalr temp pc */ -static TCGv cpu_npc; -static TCGv cpu_ppc; -static TCGv_i32 env_btaken; /* bf/bnf , F flag taken */ -static TCGv_i32 fpcsr; -static TCGv machi, maclo; -static TCGv fpmaddhi, fpmaddlo; -static TCGv_i32 env_flags; -#include "exec/gen-icount.h" - -void openrisc_translate_init(void) -{ - static const char * const regnames[] = { - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", - }; - int i; - - cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); - tcg_ctx.tcg_env = cpu_env; - cpu_sr = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, sr), "sr"); - env_flags = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUOpenRISCState, flags), - "flags"); - cpu_pc = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, pc), "pc"); - cpu_npc = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, npc), "npc"); - cpu_ppc = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, ppc), "ppc"); - jmp_pc = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc"); - env_btaken = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUOpenRISCState, btaken), - "btaken"); - fpcsr = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUOpenRISCState, fpcsr), - "fpcsr"); - machi = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, machi), - "machi"); - maclo = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, maclo), - "maclo"); - fpmaddhi = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, fpmaddhi), - "fpmaddhi"); - fpmaddlo = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, fpmaddlo), - "fpmaddlo"); - for (i = 0; i < 32; i++) { - cpu_R[i] = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, gpr[i]), - regnames[i]); - } -} - -/* Writeback SR_F translation space to execution space. */ -static inline void wb_SR_F(void) -{ - TCGLabel *label = gen_new_label(); - tcg_gen_andi_tl(cpu_sr, cpu_sr, ~SR_F); - tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, label); - tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_F); - gen_set_label(label); -} - -static inline int zero_extend(unsigned int val, int width) -{ - return val & ((1 << width) - 1); -} - -static inline int sign_extend(unsigned int val, int width) -{ - int sval; - - /* LSL */ - val <<= TARGET_LONG_BITS - width; - sval = val; - /* ASR. */ - sval >>= TARGET_LONG_BITS - width; - return sval; -} - -static inline void gen_sync_flags(DisasContext *dc) -{ - /* Sync the tb dependent flag between translate and runtime. */ - if (dc->tb_flags != dc->synced_flags) { - tcg_gen_movi_tl(env_flags, dc->tb_flags); - dc->synced_flags = dc->tb_flags; - } -} - -static void gen_exception(DisasContext *dc, unsigned int excp) -{ - TCGv_i32 tmp = tcg_const_i32(excp); - gen_helper_exception(cpu_env, tmp); - tcg_temp_free_i32(tmp); -} - -static void gen_illegal_exception(DisasContext *dc) -{ - tcg_gen_movi_tl(cpu_pc, dc->pc); - gen_exception(dc, EXCP_ILLEGAL); - dc->is_jmp = DISAS_UPDATE; -} - -/* not used yet, open it when we need or64. */ -/*#ifdef TARGET_OPENRISC64 -static void check_ob64s(DisasContext *dc) -{ - if (!(dc->flags & CPUCFGR_OB64S)) { - gen_illegal_exception(dc); - } -} - -static void check_of64s(DisasContext *dc) -{ - if (!(dc->flags & CPUCFGR_OF64S)) { - gen_illegal_exception(dc); - } -} - -static void check_ov64s(DisasContext *dc) -{ - if (!(dc->flags & CPUCFGR_OV64S)) { - gen_illegal_exception(dc); - } -} -#endif*/ - -static inline bool use_goto_tb(DisasContext *dc, target_ulong dest) -{ - if (unlikely(dc->singlestep_enabled)) { - return false; - } - -#ifndef CONFIG_USER_ONLY - return (dc->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); -#else - return true; -#endif -} - -static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) -{ - if (use_goto_tb(dc, dest)) { - tcg_gen_movi_tl(cpu_pc, dest); - tcg_gen_goto_tb(n); - tcg_gen_exit_tb((uintptr_t)dc->tb + n); - } else { - tcg_gen_movi_tl(cpu_pc, dest); - if (dc->singlestep_enabled) { - gen_exception(dc, EXCP_DEBUG); - } - tcg_gen_exit_tb(0); - } -} - -static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0) -{ - target_ulong tmp_pc; - /* N26, 26bits imm */ - tmp_pc = sign_extend((imm<<2), 26) + dc->pc; - - switch (op0) { - case 0x00: /* l.j */ - tcg_gen_movi_tl(jmp_pc, tmp_pc); - break; - case 0x01: /* l.jal */ - tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8)); - tcg_gen_movi_tl(jmp_pc, tmp_pc); - break; - case 0x03: /* l.bnf */ - case 0x04: /* l.bf */ - { - TCGLabel *lab = gen_new_label(); - TCGv sr_f = tcg_temp_new(); - tcg_gen_movi_tl(jmp_pc, dc->pc+8); - tcg_gen_andi_tl(sr_f, cpu_sr, SR_F); - tcg_gen_brcondi_i32(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE, - sr_f, SR_F, lab); - tcg_gen_movi_tl(jmp_pc, tmp_pc); - gen_set_label(lab); - tcg_temp_free(sr_f); - } - break; - case 0x11: /* l.jr */ - tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); - break; - case 0x12: /* l.jalr */ - tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8)); - tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); - break; - default: - gen_illegal_exception(dc); - break; - } - - dc->delayed_branch = 2; - dc->tb_flags |= D_FLAG; - gen_sync_flags(dc); -} - - -static void dec_calc(DisasContext *dc, uint32_t insn) -{ - uint32_t op0, op1, op2; - uint32_t ra, rb, rd; - op0 = extract32(insn, 0, 4); - op1 = extract32(insn, 8, 2); - op2 = extract32(insn, 6, 2); - ra = extract32(insn, 16, 5); - rb = extract32(insn, 11, 5); - rd = extract32(insn, 21, 5); - - switch (op0) { - case 0x0000: - switch (op1) { - case 0x00: /* l.add */ - LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb); - { - TCGLabel *lab = gen_new_label(); - TCGv_i64 ta = tcg_temp_new_i64(); - TCGv_i64 tb = tcg_temp_new_i64(); - TCGv_i64 td = tcg_temp_local_new_i64(); - TCGv_i32 res = tcg_temp_local_new_i32(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - tcg_gen_extu_i32_i64(ta, cpu_R[ra]); - tcg_gen_extu_i32_i64(tb, cpu_R[rb]); - tcg_gen_add_i64(td, ta, tb); - tcg_gen_extrl_i64_i32(res, td); - tcg_gen_shri_i64(td, td, 31); - tcg_gen_andi_i64(td, td, 0x3); - /* Jump to lab when no overflow. */ - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); - tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab); - tcg_gen_mov_i32(cpu_R[rd], res); - tcg_temp_free_i64(ta); - tcg_temp_free_i64(tb); - tcg_temp_free_i64(td); - tcg_temp_free_i32(res); - tcg_temp_free_i32(sr_ove); - } - break; - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x0001: /* l.addc */ - switch (op1) { - case 0x00: - LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb); - { - TCGLabel *lab = gen_new_label(); - TCGv_i64 ta = tcg_temp_new_i64(); - TCGv_i64 tb = tcg_temp_new_i64(); - TCGv_i64 tcy = tcg_temp_local_new_i64(); - TCGv_i64 td = tcg_temp_local_new_i64(); - TCGv_i32 res = tcg_temp_local_new_i32(); - TCGv_i32 sr_cy = tcg_temp_local_new_i32(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - tcg_gen_extu_i32_i64(ta, cpu_R[ra]); - tcg_gen_extu_i32_i64(tb, cpu_R[rb]); - tcg_gen_andi_i32(sr_cy, cpu_sr, SR_CY); - tcg_gen_extu_i32_i64(tcy, sr_cy); - tcg_gen_shri_i64(tcy, tcy, 10); - tcg_gen_add_i64(td, ta, tb); - tcg_gen_add_i64(td, td, tcy); - tcg_gen_extrl_i64_i32(res, td); - tcg_gen_shri_i64(td, td, 32); - tcg_gen_andi_i64(td, td, 0x3); - /* Jump to lab when no overflow. */ - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); - tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab); - tcg_gen_mov_i32(cpu_R[rd], res); - tcg_temp_free_i64(ta); - tcg_temp_free_i64(tb); - tcg_temp_free_i64(tcy); - tcg_temp_free_i64(td); - tcg_temp_free_i32(res); - tcg_temp_free_i32(sr_cy); - tcg_temp_free_i32(sr_ove); - } - break; - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x0002: /* l.sub */ - switch (op1) { - case 0x00: - LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb); - { - TCGLabel *lab = gen_new_label(); - TCGv_i64 ta = tcg_temp_new_i64(); - TCGv_i64 tb = tcg_temp_new_i64(); - TCGv_i64 td = tcg_temp_local_new_i64(); - TCGv_i32 res = tcg_temp_local_new_i32(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - - tcg_gen_extu_i32_i64(ta, cpu_R[ra]); - tcg_gen_extu_i32_i64(tb, cpu_R[rb]); - tcg_gen_sub_i64(td, ta, tb); - tcg_gen_extrl_i64_i32(res, td); - tcg_gen_shri_i64(td, td, 31); - tcg_gen_andi_i64(td, td, 0x3); - /* Jump to lab when no overflow. */ - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); - tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab); - tcg_gen_mov_i32(cpu_R[rd], res); - tcg_temp_free_i64(ta); - tcg_temp_free_i64(tb); - tcg_temp_free_i64(td); - tcg_temp_free_i32(res); - tcg_temp_free_i32(sr_ove); - } - break; - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x0003: /* l.and */ - switch (op1) { - case 0x00: - LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x0004: /* l.or */ - switch (op1) { - case 0x00: - LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x0005: - switch (op1) { - case 0x00: /* l.xor */ - LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x0006: - switch (op1) { - case 0x03: /* l.mul */ - LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb); - if (ra != 0 && rb != 0) { - gen_helper_mul32(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - } else { - tcg_gen_movi_tl(cpu_R[rd], 0x0); - } - break; - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x0009: - switch (op1) { - case 0x03: /* l.div */ - LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb); - { - TCGLabel *lab0 = gen_new_label(); - TCGLabel *lab1 = gen_new_label(); - TCGLabel *lab2 = gen_new_label(); - TCGLabel *lab3 = gen_new_label(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - if (rb == 0) { - tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab0); - } else { - tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[rb], - 0x00000000, lab1); - tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[ra], - 0x80000000, lab2); - tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb], - 0xffffffff, lab2); - gen_set_label(lab1); - tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab3); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab2); - tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - gen_set_label(lab3); - } - tcg_temp_free_i32(sr_ove); - } - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x000a: - switch (op1) { - case 0x03: /* l.divu */ - LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb); - { - TCGLabel *lab0 = gen_new_label(); - TCGLabel *lab1 = gen_new_label(); - TCGLabel *lab2 = gen_new_label(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - if (rb == 0) { - tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab0); - } else { - tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb], - 0x00000000, lab1); - tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab2); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab1); - tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - gen_set_label(lab2); - } - tcg_temp_free_i32(sr_ove); - } - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x000b: - switch (op1) { - case 0x03: /* l.mulu */ - LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb); - if (rb != 0 && ra != 0) { - TCGv_i64 result = tcg_temp_local_new_i64(); - TCGv_i64 tra = tcg_temp_local_new_i64(); - TCGv_i64 trb = tcg_temp_local_new_i64(); - TCGv_i64 high = tcg_temp_new_i64(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - TCGLabel *lab = gen_new_label(); - /* Calculate each result. */ - tcg_gen_extu_i32_i64(tra, cpu_R[ra]); - tcg_gen_extu_i32_i64(trb, cpu_R[rb]); - tcg_gen_mul_i64(result, tra, trb); - tcg_temp_free_i64(tra); - tcg_temp_free_i64(trb); - tcg_gen_shri_i64(high, result, TARGET_LONG_BITS); - /* Overflow or not. */ - tcg_gen_brcondi_i64(TCG_COND_EQ, high, 0x00000000, lab); - tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab); - tcg_temp_free_i64(high); - tcg_gen_trunc_i64_tl(cpu_R[rd], result); - tcg_temp_free_i64(result); - tcg_temp_free_i32(sr_ove); - } else { - tcg_gen_movi_tl(cpu_R[rd], 0); - } - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x000e: - switch (op1) { - case 0x00: /* l.cmov */ - LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb); - { - TCGLabel *lab = gen_new_label(); - TCGv res = tcg_temp_local_new(); - TCGv sr_f = tcg_temp_new(); - tcg_gen_andi_tl(sr_f, cpu_sr, SR_F); - tcg_gen_mov_tl(res, cpu_R[rb]); - tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab); - tcg_gen_mov_tl(res, cpu_R[ra]); - gen_set_label(lab); - tcg_gen_mov_tl(cpu_R[rd], res); - tcg_temp_free(sr_f); - tcg_temp_free(res); - } - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x000f: - switch (op1) { - case 0x00: /* l.ff1 */ - LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb); - gen_helper_ff1(cpu_R[rd], cpu_R[ra]); - break; - case 0x01: /* l.fl1 */ - LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb); - gen_helper_fl1(cpu_R[rd], cpu_R[ra]); - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x0008: - switch (op1) { - case 0x00: - switch (op2) { - case 0x00: /* l.sll */ - LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - case 0x01: /* l.srl */ - LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - case 0x02: /* l.sra */ - LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - case 0x03: /* l.ror */ - LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x000c: - switch (op1) { - case 0x00: - switch (op2) { - case 0x00: /* l.exths */ - LOG_DIS("l.exths r%d, r%d\n", rd, ra); - tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]); - break; - case 0x01: /* l.extbs */ - LOG_DIS("l.extbs r%d, r%d\n", rd, ra); - tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]); - break; - case 0x02: /* l.exthz */ - LOG_DIS("l.exthz r%d, r%d\n", rd, ra); - tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]); - break; - case 0x03: /* l.extbz */ - LOG_DIS("l.extbz r%d, r%d\n", rd, ra); - tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]); - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x000d: - switch (op1) { - case 0x00: - switch (op2) { - case 0x00: /* l.extws */ - LOG_DIS("l.extws r%d, r%d\n", rd, ra); - tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]); - break; - case 0x01: /* l.extwz */ - LOG_DIS("l.extwz r%d, r%d\n", rd, ra); - tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]); - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - default: - gen_illegal_exception(dc); - break; - } -} - -static void dec_misc(DisasContext *dc, uint32_t insn) -{ - uint32_t op0, op1; - uint32_t ra, rb, rd; -#ifdef OPENRISC_DISAS - uint32_t L6, K5; -#endif - uint32_t I16, I5, I11, N26, tmp; - TCGMemOp mop; - - op0 = extract32(insn, 26, 6); - op1 = extract32(insn, 24, 2); - ra = extract32(insn, 16, 5); - rb = extract32(insn, 11, 5); - rd = extract32(insn, 21, 5); -#ifdef OPENRISC_DISAS - L6 = extract32(insn, 5, 6); - K5 = extract32(insn, 0, 5); -#endif - I16 = extract32(insn, 0, 16); - I5 = extract32(insn, 21, 5); - I11 = extract32(insn, 0, 11); - N26 = extract32(insn, 0, 26); - tmp = (I5<<11) + I11; - - switch (op0) { - case 0x00: /* l.j */ - LOG_DIS("l.j %d\n", N26); - gen_jump(dc, N26, 0, op0); - break; - - case 0x01: /* l.jal */ - LOG_DIS("l.jal %d\n", N26); - gen_jump(dc, N26, 0, op0); - break; - - case 0x03: /* l.bnf */ - LOG_DIS("l.bnf %d\n", N26); - gen_jump(dc, N26, 0, op0); - break; - - case 0x04: /* l.bf */ - LOG_DIS("l.bf %d\n", N26); - gen_jump(dc, N26, 0, op0); - break; - - case 0x05: - switch (op1) { - case 0x01: /* l.nop */ - LOG_DIS("l.nop %d\n", I16); - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x11: /* l.jr */ - LOG_DIS("l.jr r%d\n", rb); - gen_jump(dc, 0, rb, op0); - break; - - case 0x12: /* l.jalr */ - LOG_DIS("l.jalr r%d\n", rb); - gen_jump(dc, 0, rb, op0); - break; - - case 0x13: /* l.maci */ - LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I11); - { - TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGv_i32 dst = tcg_temp_new_i32(); - TCGv ttmp = tcg_const_tl(tmp); - tcg_gen_mul_tl(dst, cpu_R[ra], ttmp); - tcg_gen_ext_i32_i64(t1, dst); - tcg_gen_concat_i32_i64(t2, maclo, machi); - tcg_gen_add_i64(t2, t2, t1); - tcg_gen_extrl_i64_i32(maclo, t2); - tcg_gen_shri_i64(t2, t2, 32); - tcg_gen_extrl_i64_i32(machi, t2); - tcg_temp_free_i32(dst); - tcg_temp_free(ttmp); - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t2); - } - break; - - case 0x09: /* l.rfe */ - LOG_DIS("l.rfe\n"); - { -#if defined(CONFIG_USER_ONLY) - return; -#else - if (dc->mem_idx == MMU_USER_IDX) { - gen_illegal_exception(dc); - return; - } - gen_helper_rfe(cpu_env); - dc->is_jmp = DISAS_UPDATE; -#endif - } - break; - - case 0x1c: /* l.cust1 */ - LOG_DIS("l.cust1\n"); - break; - - case 0x1d: /* l.cust2 */ - LOG_DIS("l.cust2\n"); - break; - - case 0x1e: /* l.cust3 */ - LOG_DIS("l.cust3\n"); - break; - - case 0x1f: /* l.cust4 */ - LOG_DIS("l.cust4\n"); - break; - - case 0x3c: /* l.cust5 */ - LOG_DIS("l.cust5 r%d, r%d, r%d, %d, %d\n", rd, ra, rb, L6, K5); - break; - - case 0x3d: /* l.cust6 */ - LOG_DIS("l.cust6\n"); - break; - - case 0x3e: /* l.cust7 */ - LOG_DIS("l.cust7\n"); - break; - - case 0x3f: /* l.cust8 */ - LOG_DIS("l.cust8\n"); - break; - -/* not used yet, open it when we need or64. */ -/*#ifdef TARGET_OPENRISC64 - case 0x20: l.ld - LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16); - check_ob64s(dc); - mop = MO_TEQ; - goto do_load; -#endif*/ - - case 0x21: /* l.lwz */ - LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16); - mop = MO_TEUL; - goto do_load; - - case 0x22: /* l.lws */ - LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16); - mop = MO_TESL; - goto do_load; - - case 0x23: /* l.lbz */ - LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16); - mop = MO_UB; - goto do_load; - - case 0x24: /* l.lbs */ - LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16); - mop = MO_SB; - goto do_load; - - case 0x25: /* l.lhz */ - LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16); - mop = MO_TEUW; - goto do_load; - - case 0x26: /* l.lhs */ - LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16); - mop = MO_TESW; - goto do_load; - - do_load: - { - TCGv t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); - tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop); - tcg_temp_free(t0); - } - break; - - case 0x27: /* l.addi */ - LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16); - { - if (I16 == 0) { - tcg_gen_mov_tl(cpu_R[rd], cpu_R[ra]); - } else { - TCGLabel *lab = gen_new_label(); - TCGv_i64 ta = tcg_temp_new_i64(); - TCGv_i64 td = tcg_temp_local_new_i64(); - TCGv_i32 res = tcg_temp_local_new_i32(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - tcg_gen_extu_i32_i64(ta, cpu_R[ra]); - tcg_gen_addi_i64(td, ta, sign_extend(I16, 16)); - tcg_gen_extrl_i64_i32(res, td); - tcg_gen_shri_i64(td, td, 32); - tcg_gen_andi_i64(td, td, 0x3); - /* Jump to lab when no overflow. */ - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); - tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab); - tcg_gen_mov_i32(cpu_R[rd], res); - tcg_temp_free_i64(ta); - tcg_temp_free_i64(td); - tcg_temp_free_i32(res); - tcg_temp_free_i32(sr_ove); - } - } - break; - - case 0x28: /* l.addic */ - LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16); - { - TCGLabel *lab = gen_new_label(); - TCGv_i64 ta = tcg_temp_new_i64(); - TCGv_i64 td = tcg_temp_local_new_i64(); - TCGv_i64 tcy = tcg_temp_local_new_i64(); - TCGv_i32 res = tcg_temp_local_new_i32(); - TCGv_i32 sr_cy = tcg_temp_local_new_i32(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - tcg_gen_extu_i32_i64(ta, cpu_R[ra]); - tcg_gen_andi_i32(sr_cy, cpu_sr, SR_CY); - tcg_gen_shri_i32(sr_cy, sr_cy, 10); - tcg_gen_extu_i32_i64(tcy, sr_cy); - tcg_gen_addi_i64(td, ta, sign_extend(I16, 16)); - tcg_gen_add_i64(td, td, tcy); - tcg_gen_extrl_i64_i32(res, td); - tcg_gen_shri_i64(td, td, 32); - tcg_gen_andi_i64(td, td, 0x3); - /* Jump to lab when no overflow. */ - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); - tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab); - tcg_gen_mov_i32(cpu_R[rd], res); - tcg_temp_free_i64(ta); - tcg_temp_free_i64(td); - tcg_temp_free_i64(tcy); - tcg_temp_free_i32(res); - tcg_temp_free_i32(sr_cy); - tcg_temp_free_i32(sr_ove); - } - break; - - case 0x29: /* l.andi */ - LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, I16); - tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], zero_extend(I16, 16)); - break; - - case 0x2a: /* l.ori */ - LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, I16); - tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], zero_extend(I16, 16)); - break; - - case 0x2b: /* l.xori */ - LOG_DIS("l.xori r%d, r%d, %d\n", rd, ra, I16); - tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], sign_extend(I16, 16)); - break; - - case 0x2c: /* l.muli */ - LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16); - if (ra != 0 && I16 != 0) { - TCGv_i32 im = tcg_const_i32(I16); - gen_helper_mul32(cpu_R[rd], cpu_env, cpu_R[ra], im); - tcg_temp_free_i32(im); - } else { - tcg_gen_movi_tl(cpu_R[rd], 0x0); - } - break; - - case 0x2d: /* l.mfspr */ - LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); - { -#if defined(CONFIG_USER_ONLY) - return; -#else - TCGv_i32 ti = tcg_const_i32(I16); - if (dc->mem_idx == MMU_USER_IDX) { - gen_illegal_exception(dc); - return; - } - gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti); - tcg_temp_free_i32(ti); -#endif - } - break; - - case 0x30: /* l.mtspr */ - LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); - { -#if defined(CONFIG_USER_ONLY) - return; -#else - TCGv_i32 im = tcg_const_i32(tmp); - if (dc->mem_idx == MMU_USER_IDX) { - gen_illegal_exception(dc); - return; - } - gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im); - tcg_temp_free_i32(im); -#endif - } - break; - -/* not used yet, open it when we need or64. */ -/*#ifdef TARGET_OPENRISC64 - case 0x34: l.sd - LOG_DIS("l.sd %d, r%d, r%d, %d\n", I5, ra, rb, I11); - check_ob64s(dc); - mop = MO_TEQ; - goto do_store; -#endif*/ - - case 0x35: /* l.sw */ - LOG_DIS("l.sw %d, r%d, r%d, %d\n", I5, ra, rb, I11); - mop = MO_TEUL; - goto do_store; - - case 0x36: /* l.sb */ - LOG_DIS("l.sb %d, r%d, r%d, %d\n", I5, ra, rb, I11); - mop = MO_UB; - goto do_store; - - case 0x37: /* l.sh */ - LOG_DIS("l.sh %d, r%d, r%d, %d\n", I5, ra, rb, I11); - mop = MO_TEUW; - goto do_store; - - do_store: - { - TCGv t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); - tcg_gen_qemu_st_tl(cpu_R[rb], t0, dc->mem_idx, mop); - tcg_temp_free(t0); - } - break; - - default: - gen_illegal_exception(dc); - break; - } -} - -static void dec_mac(DisasContext *dc, uint32_t insn) -{ - uint32_t op0; - uint32_t ra, rb; - op0 = extract32(insn, 0, 4); - ra = extract32(insn, 16, 5); - rb = extract32(insn, 11, 5); - - switch (op0) { - case 0x0001: /* l.mac */ - LOG_DIS("l.mac r%d, r%d\n", ra, rb); - { - TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]); - tcg_gen_ext_i32_i64(t1, t0); - tcg_gen_concat_i32_i64(t2, maclo, machi); - tcg_gen_add_i64(t2, t2, t1); - tcg_gen_extrl_i64_i32(maclo, t2); - tcg_gen_shri_i64(t2, t2, 32); - tcg_gen_extrl_i64_i32(machi, t2); - tcg_temp_free_i32(t0); - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t2); - } - break; - - case 0x0002: /* l.msb */ - LOG_DIS("l.msb r%d, r%d\n", ra, rb); - { - TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]); - tcg_gen_ext_i32_i64(t1, t0); - tcg_gen_concat_i32_i64(t2, maclo, machi); - tcg_gen_sub_i64(t2, t2, t1); - tcg_gen_extrl_i64_i32(maclo, t2); - tcg_gen_shri_i64(t2, t2, 32); - tcg_gen_extrl_i64_i32(machi, t2); - tcg_temp_free_i32(t0); - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t2); - } - break; - - default: - gen_illegal_exception(dc); - break; - } -} - -static void dec_logic(DisasContext *dc, uint32_t insn) -{ - uint32_t op0; - uint32_t rd, ra, L6; - op0 = extract32(insn, 6, 2); - rd = extract32(insn, 21, 5); - ra = extract32(insn, 16, 5); - L6 = extract32(insn, 0, 6); - - switch (op0) { - case 0x00: /* l.slli */ - LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6); - tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f)); - break; - - case 0x01: /* l.srli */ - LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6); - tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f)); - break; - - case 0x02: /* l.srai */ - LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6); - tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f)); break; - - case 0x03: /* l.rori */ - LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6); - tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f)); - break; - - default: - gen_illegal_exception(dc); - break; - } -} - -static void dec_M(DisasContext *dc, uint32_t insn) -{ - uint32_t op0; - uint32_t rd; - uint32_t K16; - op0 = extract32(insn, 16, 1); - rd = extract32(insn, 21, 5); - K16 = extract32(insn, 0, 16); - - switch (op0) { - case 0x0: /* l.movhi */ - LOG_DIS("l.movhi r%d, %d\n", rd, K16); - tcg_gen_movi_tl(cpu_R[rd], (K16 << 16)); - break; - - case 0x1: /* l.macrc */ - LOG_DIS("l.macrc r%d\n", rd); - tcg_gen_mov_tl(cpu_R[rd], maclo); - tcg_gen_movi_tl(maclo, 0x0); - tcg_gen_movi_tl(machi, 0x0); - break; - - default: - gen_illegal_exception(dc); - break; - } -} - -static void dec_comp(DisasContext *dc, uint32_t insn) -{ - uint32_t op0; - uint32_t ra, rb; - - op0 = extract32(insn, 21, 5); - ra = extract32(insn, 16, 5); - rb = extract32(insn, 11, 5); - - tcg_gen_movi_i32(env_btaken, 0x0); - /* unsigned integers */ - tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]); - tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]); - - switch (op0) { - case 0x0: /* l.sfeq */ - LOG_DIS("l.sfeq r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], cpu_R[rb]); - break; - - case 0x1: /* l.sfne */ - LOG_DIS("l.sfne r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]); - break; - - case 0x2: /* l.sfgtu */ - LOG_DIS("l.sfgtu r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_GTU, env_btaken, cpu_R[ra], cpu_R[rb]); - break; - - case 0x3: /* l.sfgeu */ - LOG_DIS("l.sfgeu r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_GEU, env_btaken, cpu_R[ra], cpu_R[rb]); - break; - - case 0x4: /* l.sfltu */ - LOG_DIS("l.sfltu r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_LTU, env_btaken, cpu_R[ra], cpu_R[rb]); - break; - - case 0x5: /* l.sfleu */ - LOG_DIS("l.sfleu r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], cpu_R[rb]); - break; - - case 0xa: /* l.sfgts */ - LOG_DIS("l.sfgts r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]); - break; - - case 0xb: /* l.sfges */ - LOG_DIS("l.sfges r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]); - break; - - case 0xc: /* l.sflts */ - LOG_DIS("l.sflts r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]); - break; - - case 0xd: /* l.sfles */ - LOG_DIS("l.sfles r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]); - break; - - default: - gen_illegal_exception(dc); - break; - } - wb_SR_F(); -} - -static void dec_compi(DisasContext *dc, uint32_t insn) -{ - uint32_t op0; - uint32_t ra, I16; - - op0 = extract32(insn, 21, 5); - ra = extract32(insn, 16, 5); - I16 = extract32(insn, 0, 16); - - tcg_gen_movi_i32(env_btaken, 0x0); - I16 = sign_extend(I16, 16); - - switch (op0) { - case 0x0: /* l.sfeqi */ - LOG_DIS("l.sfeqi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], I16); - break; - - case 0x1: /* l.sfnei */ - LOG_DIS("l.sfnei r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_NE, env_btaken, cpu_R[ra], I16); - break; - - case 0x2: /* l.sfgtui */ - LOG_DIS("l.sfgtui r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_GTU, env_btaken, cpu_R[ra], I16); - break; - - case 0x3: /* l.sfgeui */ - LOG_DIS("l.sfgeui r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_GEU, env_btaken, cpu_R[ra], I16); - break; - - case 0x4: /* l.sfltui */ - LOG_DIS("l.sfltui r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_LTU, env_btaken, cpu_R[ra], I16); - break; - - case 0x5: /* l.sfleui */ - LOG_DIS("l.sfleui r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], I16); - break; - - case 0xa: /* l.sfgtsi */ - LOG_DIS("l.sfgtsi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_GT, env_btaken, cpu_R[ra], I16); - break; - - case 0xb: /* l.sfgesi */ - LOG_DIS("l.sfgesi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_GE, env_btaken, cpu_R[ra], I16); - break; - - case 0xc: /* l.sfltsi */ - LOG_DIS("l.sfltsi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_LT, env_btaken, cpu_R[ra], I16); - break; - - case 0xd: /* l.sflesi */ - LOG_DIS("l.sflesi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_LE, env_btaken, cpu_R[ra], I16); - break; - - default: - gen_illegal_exception(dc); - break; - } - wb_SR_F(); -} - -static void dec_sys(DisasContext *dc, uint32_t insn) -{ - uint32_t op0; -#ifdef OPENRISC_DISAS - uint32_t K16; -#endif - op0 = extract32(insn, 16, 10); -#ifdef OPENRISC_DISAS - K16 = extract32(insn, 0, 16); -#endif - - switch (op0) { - case 0x000: /* l.sys */ - LOG_DIS("l.sys %d\n", K16); - tcg_gen_movi_tl(cpu_pc, dc->pc); - gen_exception(dc, EXCP_SYSCALL); - dc->is_jmp = DISAS_UPDATE; - break; - - case 0x100: /* l.trap */ - LOG_DIS("l.trap %d\n", K16); -#if defined(CONFIG_USER_ONLY) - return; -#else - if (dc->mem_idx == MMU_USER_IDX) { - gen_illegal_exception(dc); - return; - } - tcg_gen_movi_tl(cpu_pc, dc->pc); - gen_exception(dc, EXCP_TRAP); -#endif - break; - - case 0x300: /* l.csync */ - LOG_DIS("l.csync\n"); -#if defined(CONFIG_USER_ONLY) - return; -#else - if (dc->mem_idx == MMU_USER_IDX) { - gen_illegal_exception(dc); - return; - } -#endif - break; - - case 0x200: /* l.msync */ - LOG_DIS("l.msync\n"); -#if defined(CONFIG_USER_ONLY) - return; -#else - if (dc->mem_idx == MMU_USER_IDX) { - gen_illegal_exception(dc); - return; - } -#endif - break; - - case 0x270: /* l.psync */ - LOG_DIS("l.psync\n"); -#if defined(CONFIG_USER_ONLY) - return; -#else - if (dc->mem_idx == MMU_USER_IDX) { - gen_illegal_exception(dc); - return; - } -#endif - break; - - default: - gen_illegal_exception(dc); - break; - } -} - -static void dec_float(DisasContext *dc, uint32_t insn) -{ - uint32_t op0; - uint32_t ra, rb, rd; - op0 = extract32(insn, 0, 8); - ra = extract32(insn, 16, 5); - rb = extract32(insn, 11, 5); - rd = extract32(insn, 21, 5); - - switch (op0) { - case 0x00: /* lf.add.s */ - LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb); - gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x01: /* lf.sub.s */ - LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb); - gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - - case 0x02: /* lf.mul.s */ - LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb); - if (ra != 0 && rb != 0) { - gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - } else { - tcg_gen_ori_tl(fpcsr, fpcsr, FPCSR_ZF); - tcg_gen_movi_i32(cpu_R[rd], 0x0); - } - break; - - case 0x03: /* lf.div.s */ - LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb); - gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x04: /* lf.itof.s */ - LOG_DIS("lf.itof r%d, r%d\n", rd, ra); - gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]); - break; - - case 0x05: /* lf.ftoi.s */ - LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra); - gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]); - break; - - case 0x06: /* lf.rem.s */ - LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb); - gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x07: /* lf.madd.s */ - LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb); - gen_helper_float_muladd_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x08: /* lf.sfeq.s */ - LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb); - gen_helper_float_eq_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x09: /* lf.sfne.s */ - LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb); - gen_helper_float_ne_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x0a: /* lf.sfgt.s */ - LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb); - gen_helper_float_gt_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x0b: /* lf.sfge.s */ - LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb); - gen_helper_float_ge_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x0c: /* lf.sflt.s */ - LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb); - gen_helper_float_lt_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x0d: /* lf.sfle.s */ - LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb); - gen_helper_float_le_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - -/* not used yet, open it when we need or64. */ -/*#ifdef TARGET_OPENRISC64 - case 0x10: lf.add.d - LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb); - check_of64s(dc); - gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x11: lf.sub.d - LOG_DIS("lf.sub.d r%d, r%d, r%d\n", rd, ra, rb); - check_of64s(dc); - gen_helper_float_sub_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x12: lf.mul.d - LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb); - check_of64s(dc); - if (ra != 0 && rb != 0) { - gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - } else { - tcg_gen_ori_tl(fpcsr, fpcsr, FPCSR_ZF); - tcg_gen_movi_i64(cpu_R[rd], 0x0); - } - break; - - case 0x13: lf.div.d - LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb); - check_of64s(dc); - gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x14: lf.itof.d - LOG_DIS("lf.itof r%d, r%d\n", rd, ra); - check_of64s(dc); - gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]); - break; - - case 0x15: lf.ftoi.d - LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra); - check_of64s(dc); - gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]); - break; - - case 0x16: lf.rem.d - LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb); - check_of64s(dc); - gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x17: lf.madd.d - LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb); - check_of64s(dc); - gen_helper_float_muladd_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x18: lf.sfeq.d - LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb); - check_of64s(dc); - gen_helper_float_eq_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x1a: lf.sfgt.d - LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb); - check_of64s(dc); - gen_helper_float_gt_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x1b: lf.sfge.d - LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb); - check_of64s(dc); - gen_helper_float_ge_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x19: lf.sfne.d - LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb); - check_of64s(dc); - gen_helper_float_ne_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x1c: lf.sflt.d - LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb); - check_of64s(dc); - gen_helper_float_lt_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x1d: lf.sfle.d - LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb); - check_of64s(dc); - gen_helper_float_le_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); - break; -#endif*/ - - default: - gen_illegal_exception(dc); - break; - } - wb_SR_F(); -} - -static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu) -{ - uint32_t op0; - uint32_t insn; - insn = cpu_ldl_code(&cpu->env, dc->pc); - op0 = extract32(insn, 26, 6); - - switch (op0) { - case 0x06: - dec_M(dc, insn); - break; - - case 0x08: - dec_sys(dc, insn); - break; - - case 0x2e: - dec_logic(dc, insn); - break; - - case 0x2f: - dec_compi(dc, insn); - break; - - case 0x31: - dec_mac(dc, insn); - break; - - case 0x32: - dec_float(dc, insn); - break; - - case 0x38: - dec_calc(dc, insn); - break; - - case 0x39: - dec_comp(dc, insn); - break; - - default: - dec_misc(dc, insn); - break; - } -} - -void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) -{ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - CPUState *cs = CPU(cpu); - struct DisasContext ctx, *dc = &ctx; - uint32_t pc_start; - uint32_t next_page_start; - int num_insns; - int max_insns; - - pc_start = tb->pc; - dc->tb = tb; - - dc->is_jmp = DISAS_NEXT; - dc->ppc = pc_start; - dc->pc = pc_start; - dc->flags = cpu->env.cpucfgr; - dc->mem_idx = cpu_mmu_index(&cpu->env, false); - dc->synced_flags = dc->tb_flags = tb->flags; - dc->delayed_branch = !!(dc->tb_flags & D_FLAG); - dc->singlestep_enabled = cs->singlestep_enabled; - - next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - 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); - - do { - tcg_gen_insn_start(dc->pc); - num_insns++; - - if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { - tcg_gen_movi_tl(cpu_pc, dc->pc); - gen_exception(dc, EXCP_DEBUG); - dc->is_jmp = DISAS_UPDATE; - /* 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. */ - dc->pc += 4; - break; - } - - if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { - gen_io_start(); - } - dc->ppc = dc->pc - 4; - dc->npc = dc->pc + 4; - tcg_gen_movi_tl(cpu_ppc, dc->ppc); - tcg_gen_movi_tl(cpu_npc, dc->npc); - disas_openrisc_insn(dc, cpu); - dc->pc = dc->npc; - /* delay slot */ - if (dc->delayed_branch) { - dc->delayed_branch--; - if (!dc->delayed_branch) { - dc->tb_flags &= ~D_FLAG; - gen_sync_flags(dc); - tcg_gen_mov_tl(cpu_pc, jmp_pc); - tcg_gen_mov_tl(cpu_npc, jmp_pc); - tcg_gen_movi_tl(jmp_pc, 0); - tcg_gen_exit_tb(0); - dc->is_jmp = DISAS_JUMP; - break; - } - } - } while (!dc->is_jmp - && !tcg_op_buf_full() - && !cs->singlestep_enabled - && !singlestep - && (dc->pc < next_page_start) - && num_insns < max_insns); - - if (tb->cflags & CF_LAST_IO) { - gen_io_end(); - } - if (dc->is_jmp == DISAS_NEXT) { - dc->is_jmp = DISAS_UPDATE; - tcg_gen_movi_tl(cpu_pc, dc->pc); - } - if (unlikely(cs->singlestep_enabled)) { - if (dc->is_jmp == DISAS_NEXT) { - tcg_gen_movi_tl(cpu_pc, dc->pc); - } - gen_exception(dc, EXCP_DEBUG); - } else { - switch (dc->is_jmp) { - case DISAS_NEXT: - gen_goto_tb(dc, 0, dc->pc); - break; - default: - case DISAS_JUMP: - break; - case DISAS_UPDATE: - /* indicate that the hash table must be used - to find the next TB */ - tcg_gen_exit_tb(0); - break; - case DISAS_TB_JUMP: - /* nothing more to generate */ - break; - } - } - - gen_tb_end(tb, num_insns); - - tb->size = dc->pc - pc_start; - tb->icount = num_insns; - -#ifdef DEBUG_DISAS - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) - && qemu_log_in_addr_range(pc_start)) { - qemu_log_lock(); - qemu_log("----------------\n"); - qemu_log("IN: %s\n", lookup_symbol(pc_start)); - log_target_disas(cs, pc_start, dc->pc - pc_start, 0); - qemu_log("\nisize=%d osize=%d\n", - dc->pc - pc_start, tcg_op_buf_count()); - qemu_log_unlock(); - } -#endif -} - -void openrisc_cpu_dump_state(CPUState *cs, FILE *f, - fprintf_function cpu_fprintf, - int flags) -{ - OpenRISCCPU *cpu = OPENRISC_CPU(cs); - CPUOpenRISCState *env = &cpu->env; - int i; - - cpu_fprintf(f, "PC=%08x\n", env->pc); - for (i = 0; i < 32; ++i) { - cpu_fprintf(f, "R%02d=%08x%c", i, env->gpr[i], - (i % 4) == 3 ? '\n' : ' '); - } -} - -void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb, - target_ulong *data) -{ - env->pc = data[0]; -} |