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-microblaze | |
parent | 82ecffa8c050bf5bbc13329e9b65eac1caa5b55c (diff) |
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-microblaze')
-rw-r--r-- | target-microblaze/Makefile.objs | 3 | ||||
-rw-r--r-- | target-microblaze/cpu-qom.h | 52 | ||||
-rw-r--r-- | target-microblaze/cpu.c | 292 | ||||
-rw-r--r-- | target-microblaze/cpu.h | 381 | ||||
-rw-r--r-- | target-microblaze/gdbstub.c | 57 | ||||
-rw-r--r-- | target-microblaze/helper.c | 307 | ||||
-rw-r--r-- | target-microblaze/helper.h | 37 | ||||
-rw-r--r-- | target-microblaze/microblaze-decode.h | 55 | ||||
-rw-r--r-- | target-microblaze/mmu.c | 303 | ||||
-rw-r--r-- | target-microblaze/mmu.h | 90 | ||||
-rw-r--r-- | target-microblaze/op_helper.c | 523 | ||||
-rw-r--r-- | target-microblaze/translate.c | 1872 |
12 files changed, 0 insertions, 3972 deletions
diff --git a/target-microblaze/Makefile.objs b/target-microblaze/Makefile.objs deleted file mode 100644 index f3d7b44c89..0000000000 --- a/target-microblaze/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -obj-y += translate.o op_helper.o helper.o cpu.o -obj-y += gdbstub.o -obj-$(CONFIG_SOFTMMU) += mmu.o diff --git a/target-microblaze/cpu-qom.h b/target-microblaze/cpu-qom.h deleted file mode 100644 index 1a61db77d0..0000000000 --- a/target-microblaze/cpu-qom.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * QEMU MicroBlaze CPU - * - * Copyright (c) 2012 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.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see - * <http://www.gnu.org/licenses/lgpl-2.1.html> - */ -#ifndef QEMU_MICROBLAZE_CPU_QOM_H -#define QEMU_MICROBLAZE_CPU_QOM_H - -#include "qom/cpu.h" - -#define TYPE_MICROBLAZE_CPU "microblaze-cpu" - -#define MICROBLAZE_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(MicroBlazeCPUClass, (klass), TYPE_MICROBLAZE_CPU) -#define MICROBLAZE_CPU(obj) \ - OBJECT_CHECK(MicroBlazeCPU, (obj), TYPE_MICROBLAZE_CPU) -#define MICROBLAZE_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(MicroBlazeCPUClass, (obj), TYPE_MICROBLAZE_CPU) - -/** - * MicroBlazeCPUClass: - * @parent_realize: The parent class' realize handler. - * @parent_reset: The parent class' reset handler. - * - * A MicroBlaze CPU model. - */ -typedef struct MicroBlazeCPUClass { - /*< private >*/ - CPUClass parent_class; - /*< public >*/ - - DeviceRealize parent_realize; - void (*parent_reset)(CPUState *cpu); -} MicroBlazeCPUClass; - -typedef struct MicroBlazeCPU MicroBlazeCPU; - -#endif diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c deleted file mode 100644 index 389c7b691e..0000000000 --- a/target-microblaze/cpu.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * QEMU MicroBlaze CPU - * - * Copyright (c) 2009 Edgar E. Iglesias - * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd. - * Copyright (c) 2012 SUSE LINUX Products GmbH - * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see - * <http://www.gnu.org/licenses/lgpl-2.1.html> - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "cpu.h" -#include "qemu-common.h" -#include "hw/qdev-properties.h" -#include "migration/vmstate.h" -#include "exec/exec-all.h" - -static const struct { - const char *name; - uint8_t version_id; -} mb_cpu_lookup[] = { - /* These key value are as per MBV field in PVR0 */ - {"5.00.a", 0x01}, - {"5.00.b", 0x02}, - {"5.00.c", 0x03}, - {"6.00.a", 0x04}, - {"6.00.b", 0x06}, - {"7.00.a", 0x05}, - {"7.00.b", 0x07}, - {"7.10.a", 0x08}, - {"7.10.b", 0x09}, - {"7.10.c", 0x0a}, - {"7.10.d", 0x0b}, - {"7.20.a", 0x0c}, - {"7.20.b", 0x0d}, - {"7.20.c", 0x0e}, - {"7.20.d", 0x0f}, - {"7.30.a", 0x10}, - {"7.30.b", 0x11}, - {"8.00.a", 0x12}, - {"8.00.b", 0x13}, - {"8.10.a", 0x14}, - {"8.20.a", 0x15}, - {"8.20.b", 0x16}, - {"8.30.a", 0x17}, - {"8.40.a", 0x18}, - {"8.40.b", 0x19}, - {"8.50.a", 0x1A}, - {"9.0", 0x1B}, - {"9.1", 0x1D}, - {"9.2", 0x1F}, - {"9.3", 0x20}, - {NULL, 0}, -}; - -static void mb_cpu_set_pc(CPUState *cs, vaddr value) -{ - MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); - - cpu->env.sregs[SR_PC] = value; -} - -static bool mb_cpu_has_work(CPUState *cs) -{ - return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); -} - -#ifndef CONFIG_USER_ONLY -static void microblaze_cpu_set_irq(void *opaque, int irq, int level) -{ - MicroBlazeCPU *cpu = opaque; - CPUState *cs = CPU(cpu); - int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD; - - if (level) { - cpu_interrupt(cs, type); - } else { - cpu_reset_interrupt(cs, type); - } -} -#endif - -/* CPUClass::reset() */ -static void mb_cpu_reset(CPUState *s) -{ - MicroBlazeCPU *cpu = MICROBLAZE_CPU(s); - MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(cpu); - CPUMBState *env = &cpu->env; - - mcc->parent_reset(s); - - memset(env, 0, offsetof(CPUMBState, pvr)); - env->res_addr = RES_ADDR_NONE; - tlb_flush(s, 1); - - /* Disable stack protector. */ - env->shr = ~0; - - env->sregs[SR_PC] = cpu->cfg.base_vectors; - -#if defined(CONFIG_USER_ONLY) - /* start in user mode with interrupts enabled. */ - env->sregs[SR_MSR] = MSR_EE | MSR_IE | MSR_VM | MSR_UM; -#else - env->sregs[SR_MSR] = 0; - mmu_init(&env->mmu); - env->mmu.c_mmu = 3; - env->mmu.c_mmu_tlb_access = 3; - env->mmu.c_mmu_zones = 16; -#endif -} - -static void mb_disas_set_info(CPUState *cpu, disassemble_info *info) -{ - info->mach = bfd_arch_microblaze; - info->print_insn = print_insn_microblaze; -} - -static void mb_cpu_realizefn(DeviceState *dev, Error **errp) -{ - CPUState *cs = CPU(dev); - MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(dev); - MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); - CPUMBState *env = &cpu->env; - uint8_t version_code = 0; - int i = 0; - Error *local_err = NULL; - - cpu_exec_realizefn(cs, &local_err); - if (local_err != NULL) { - error_propagate(errp, local_err); - return; - } - - qemu_init_vcpu(cs); - - env->pvr.regs[0] = PVR0_USE_BARREL_MASK \ - | PVR0_USE_DIV_MASK \ - | PVR0_USE_HW_MUL_MASK \ - | PVR0_USE_EXC_MASK \ - | PVR0_USE_ICACHE_MASK \ - | PVR0_USE_DCACHE_MASK \ - | (0xb << 8); - env->pvr.regs[2] = PVR2_D_OPB_MASK \ - | PVR2_D_LMB_MASK \ - | PVR2_I_OPB_MASK \ - | PVR2_I_LMB_MASK \ - | PVR2_USE_MSR_INSTR \ - | PVR2_USE_PCMP_INSTR \ - | PVR2_USE_BARREL_MASK \ - | PVR2_USE_DIV_MASK \ - | PVR2_USE_HW_MUL_MASK \ - | PVR2_USE_MUL64_MASK \ - | PVR2_FPU_EXC_MASK \ - | 0; - - for (i = 0; mb_cpu_lookup[i].name && cpu->cfg.version; i++) { - if (strcmp(mb_cpu_lookup[i].name, cpu->cfg.version) == 0) { - version_code = mb_cpu_lookup[i].version_id; - break; - } - } - - if (!version_code) { - qemu_log("Invalid MicroBlaze version number: %s\n", cpu->cfg.version); - } - - env->pvr.regs[0] |= (cpu->cfg.stackprot ? PVR0_SPROT_MASK : 0) | - (cpu->cfg.use_fpu ? PVR0_USE_FPU_MASK : 0) | - (cpu->cfg.use_mmu ? PVR0_USE_MMU_MASK : 0) | - (cpu->cfg.endi ? PVR0_ENDI_MASK : 0) | - (version_code << 16) | - (cpu->cfg.pvr == C_PVR_FULL ? PVR0_PVR_FULL_MASK : 0); - - env->pvr.regs[2] |= (cpu->cfg.use_fpu ? PVR2_USE_FPU_MASK : 0) | - (cpu->cfg.use_fpu > 1 ? PVR2_USE_FPU2_MASK : 0); - - env->pvr.regs[5] |= cpu->cfg.dcache_writeback ? - PVR5_DCACHE_WRITEBACK_MASK : 0; - - env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family. */ - env->pvr.regs[11] = PVR11_USE_MMU | (16 << 17); - - mcc->parent_realize(dev, errp); -} - -static void mb_cpu_initfn(Object *obj) -{ - CPUState *cs = CPU(obj); - MicroBlazeCPU *cpu = MICROBLAZE_CPU(obj); - CPUMBState *env = &cpu->env; - static bool tcg_initialized; - - cs->env_ptr = env; - - set_float_rounding_mode(float_round_nearest_even, &env->fp_status); - -#ifndef CONFIG_USER_ONLY - /* Inbound IRQ and FIR lines */ - qdev_init_gpio_in(DEVICE(cpu), microblaze_cpu_set_irq, 2); -#endif - - if (tcg_enabled() && !tcg_initialized) { - tcg_initialized = true; - mb_tcg_init(); - } -} - -static const VMStateDescription vmstate_mb_cpu = { - .name = "cpu", - .unmigratable = 1, -}; - -static Property mb_properties[] = { - DEFINE_PROP_UINT32("base-vectors", MicroBlazeCPU, cfg.base_vectors, 0), - DEFINE_PROP_BOOL("use-stack-protection", MicroBlazeCPU, cfg.stackprot, - false), - /* If use-fpu > 0 - FPU is enabled - * If use-fpu = 2 - Floating point conversion and square root instructions - * are enabled - */ - DEFINE_PROP_UINT8("use-fpu", MicroBlazeCPU, cfg.use_fpu, 2), - DEFINE_PROP_BOOL("use-mmu", MicroBlazeCPU, cfg.use_mmu, true), - DEFINE_PROP_BOOL("dcache-writeback", MicroBlazeCPU, cfg.dcache_writeback, - false), - DEFINE_PROP_BOOL("endianness", MicroBlazeCPU, cfg.endi, false), - DEFINE_PROP_STRING("version", MicroBlazeCPU, cfg.version), - DEFINE_PROP_UINT8("pvr", MicroBlazeCPU, cfg.pvr, C_PVR_FULL), - DEFINE_PROP_END_OF_LIST(), -}; - -static void mb_cpu_class_init(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - CPUClass *cc = CPU_CLASS(oc); - MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_CLASS(oc); - - mcc->parent_realize = dc->realize; - dc->realize = mb_cpu_realizefn; - - mcc->parent_reset = cc->reset; - cc->reset = mb_cpu_reset; - - cc->has_work = mb_cpu_has_work; - cc->do_interrupt = mb_cpu_do_interrupt; - cc->cpu_exec_interrupt = mb_cpu_exec_interrupt; - cc->dump_state = mb_cpu_dump_state; - cc->set_pc = mb_cpu_set_pc; - cc->gdb_read_register = mb_cpu_gdb_read_register; - cc->gdb_write_register = mb_cpu_gdb_write_register; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = mb_cpu_handle_mmu_fault; -#else - cc->do_unassigned_access = mb_cpu_unassigned_access; - cc->get_phys_page_debug = mb_cpu_get_phys_page_debug; -#endif - dc->vmsd = &vmstate_mb_cpu; - dc->props = mb_properties; - cc->gdb_num_core_regs = 32 + 5; - - cc->disas_set_info = mb_disas_set_info; -} - -static const TypeInfo mb_cpu_type_info = { - .name = TYPE_MICROBLAZE_CPU, - .parent = TYPE_CPU, - .instance_size = sizeof(MicroBlazeCPU), - .instance_init = mb_cpu_initfn, - .class_size = sizeof(MicroBlazeCPUClass), - .class_init = mb_cpu_class_init, -}; - -static void mb_cpu_register_types(void) -{ - type_register_static(&mb_cpu_type_info); -} - -type_init(mb_cpu_register_types) diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h deleted file mode 100644 index beb75ffd26..0000000000 --- a/target-microblaze/cpu.h +++ /dev/null @@ -1,381 +0,0 @@ -/* - * MicroBlaze virtual CPU header - * - * Copyright (c) 2009 Edgar E. Iglesias - * - * 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 - * 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 MICROBLAZE_CPU_H -#define MICROBLAZE_CPU_H - -#include "qemu-common.h" -#include "cpu-qom.h" - -#define TARGET_LONG_BITS 32 - -#define CPUArchState struct CPUMBState - -#include "exec/cpu-defs.h" -#include "fpu/softfloat.h" -struct CPUMBState; -typedef struct CPUMBState CPUMBState; -#if !defined(CONFIG_USER_ONLY) -#include "mmu.h" -#endif - -#define EXCP_MMU 1 -#define EXCP_IRQ 2 -#define EXCP_BREAK 3 -#define EXCP_HW_BREAK 4 -#define EXCP_HW_EXCP 5 - -/* MicroBlaze-specific interrupt pending bits. */ -#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3 - -/* Meanings of the MBCPU object's two inbound GPIO lines */ -#define MB_CPU_IRQ 0 -#define MB_CPU_FIR 1 - -/* Register aliases. R0 - R15 */ -#define R_SP 1 -#define SR_PC 0 -#define SR_MSR 1 -#define SR_EAR 3 -#define SR_ESR 5 -#define SR_FSR 7 -#define SR_BTR 0xb -#define SR_EDR 0xd - -/* MSR flags. */ -#define MSR_BE (1<<0) /* 0x001 */ -#define MSR_IE (1<<1) /* 0x002 */ -#define MSR_C (1<<2) /* 0x004 */ -#define MSR_BIP (1<<3) /* 0x008 */ -#define MSR_FSL (1<<4) /* 0x010 */ -#define MSR_ICE (1<<5) /* 0x020 */ -#define MSR_DZ (1<<6) /* 0x040 */ -#define MSR_DCE (1<<7) /* 0x080 */ -#define MSR_EE (1<<8) /* 0x100 */ -#define MSR_EIP (1<<9) /* 0x200 */ -#define MSR_PVR (1<<10) /* 0x400 */ -#define MSR_CC (1<<31) - -/* Machine State Register (MSR) Fields */ -#define MSR_UM (1<<11) /* User Mode */ -#define MSR_UMS (1<<12) /* User Mode Save */ -#define MSR_VM (1<<13) /* Virtual Mode */ -#define MSR_VMS (1<<14) /* Virtual Mode Save */ - -#define MSR_KERNEL MSR_EE|MSR_VM -//#define MSR_USER MSR_KERNEL|MSR_UM|MSR_IE -#define MSR_KERNEL_VMS MSR_EE|MSR_VMS -//#define MSR_USER_VMS MSR_KERNEL_VMS|MSR_UMS|MSR_IE - -/* Exception State Register (ESR) Fields */ -#define ESR_DIZ (1<<11) /* Zone Protection */ -#define ESR_S (1<<10) /* Store instruction */ - -#define ESR_ESS_FSL_OFFSET 5 - -#define ESR_EC_FSL 0 -#define ESR_EC_UNALIGNED_DATA 1 -#define ESR_EC_ILLEGAL_OP 2 -#define ESR_EC_INSN_BUS 3 -#define ESR_EC_DATA_BUS 4 -#define ESR_EC_DIVZERO 5 -#define ESR_EC_FPU 6 -#define ESR_EC_PRIVINSN 7 -#define ESR_EC_STACKPROT 7 /* Same as PRIVINSN. */ -#define ESR_EC_DATA_STORAGE 8 -#define ESR_EC_INSN_STORAGE 9 -#define ESR_EC_DATA_TLB 10 -#define ESR_EC_INSN_TLB 11 -#define ESR_EC_MASK 31 - -/* Floating Point Status Register (FSR) Bits */ -#define FSR_IO (1<<4) /* Invalid operation */ -#define FSR_DZ (1<<3) /* Divide-by-zero */ -#define FSR_OF (1<<2) /* Overflow */ -#define FSR_UF (1<<1) /* Underflow */ -#define FSR_DO (1<<0) /* Denormalized operand error */ - -/* Version reg. */ -/* Basic PVR mask */ -#define PVR0_PVR_FULL_MASK 0x80000000 -#define PVR0_USE_BARREL_MASK 0x40000000 -#define PVR0_USE_DIV_MASK 0x20000000 -#define PVR0_USE_HW_MUL_MASK 0x10000000 -#define PVR0_USE_FPU_MASK 0x08000000 -#define PVR0_USE_EXC_MASK 0x04000000 -#define PVR0_USE_ICACHE_MASK 0x02000000 -#define PVR0_USE_DCACHE_MASK 0x01000000 -#define PVR0_USE_MMU_MASK 0x00800000 -#define PVR0_USE_BTC 0x00400000 -#define PVR0_ENDI_MASK 0x00200000 -#define PVR0_FAULT 0x00100000 -#define PVR0_VERSION_MASK 0x0000FF00 -#define PVR0_USER1_MASK 0x000000FF -#define PVR0_SPROT_MASK 0x00000001 - -/* User 2 PVR mask */ -#define PVR1_USER2_MASK 0xFFFFFFFF - -/* Configuration PVR masks */ -#define PVR2_D_OPB_MASK 0x80000000 -#define PVR2_D_LMB_MASK 0x40000000 -#define PVR2_I_OPB_MASK 0x20000000 -#define PVR2_I_LMB_MASK 0x10000000 -#define PVR2_INTERRUPT_IS_EDGE_MASK 0x08000000 -#define PVR2_EDGE_IS_POSITIVE_MASK 0x04000000 -#define PVR2_D_PLB_MASK 0x02000000 /* new */ -#define PVR2_I_PLB_MASK 0x01000000 /* new */ -#define PVR2_INTERCONNECT 0x00800000 /* new */ -#define PVR2_USE_EXTEND_FSL 0x00080000 /* new */ -#define PVR2_USE_FSL_EXC 0x00040000 /* new */ -#define PVR2_USE_MSR_INSTR 0x00020000 -#define PVR2_USE_PCMP_INSTR 0x00010000 -#define PVR2_AREA_OPTIMISED 0x00008000 -#define PVR2_USE_BARREL_MASK 0x00004000 -#define PVR2_USE_DIV_MASK 0x00002000 -#define PVR2_USE_HW_MUL_MASK 0x00001000 -#define PVR2_USE_FPU_MASK 0x00000800 -#define PVR2_USE_MUL64_MASK 0x00000400 -#define PVR2_USE_FPU2_MASK 0x00000200 /* new */ -#define PVR2_USE_IPLBEXC 0x00000100 -#define PVR2_USE_DPLBEXC 0x00000080 -#define PVR2_OPCODE_0x0_ILL_MASK 0x00000040 -#define PVR2_UNALIGNED_EXC_MASK 0x00000020 -#define PVR2_ILL_OPCODE_EXC_MASK 0x00000010 -#define PVR2_IOPB_BUS_EXC_MASK 0x00000008 -#define PVR2_DOPB_BUS_EXC_MASK 0x00000004 -#define PVR2_DIV_ZERO_EXC_MASK 0x00000002 -#define PVR2_FPU_EXC_MASK 0x00000001 - -/* Debug and exception PVR masks */ -#define PVR3_DEBUG_ENABLED_MASK 0x80000000 -#define PVR3_NUMBER_OF_PC_BRK_MASK 0x1E000000 -#define PVR3_NUMBER_OF_RD_ADDR_BRK_MASK 0x00380000 -#define PVR3_NUMBER_OF_WR_ADDR_BRK_MASK 0x0000E000 -#define PVR3_FSL_LINKS_MASK 0x00000380 - -/* ICache config PVR masks */ -#define PVR4_USE_ICACHE_MASK 0x80000000 -#define PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000 -#define PVR4_ICACHE_USE_FSL_MASK 0x02000000 -#define PVR4_ICACHE_ALLOW_WR_MASK 0x01000000 -#define PVR4_ICACHE_LINE_LEN_MASK 0x00E00000 -#define PVR4_ICACHE_BYTE_SIZE_MASK 0x001F0000 - -/* DCache config PVR masks */ -#define PVR5_USE_DCACHE_MASK 0x80000000 -#define PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000 -#define PVR5_DCACHE_USE_FSL_MASK 0x02000000 -#define PVR5_DCACHE_ALLOW_WR_MASK 0x01000000 -#define PVR5_DCACHE_LINE_LEN_MASK 0x00E00000 -#define PVR5_DCACHE_BYTE_SIZE_MASK 0x001F0000 -#define PVR5_DCACHE_WRITEBACK_MASK 0x00004000 - -/* ICache base address PVR mask */ -#define PVR6_ICACHE_BASEADDR_MASK 0xFFFFFFFF - -/* ICache high address PVR mask */ -#define PVR7_ICACHE_HIGHADDR_MASK 0xFFFFFFFF - -/* DCache base address PVR mask */ -#define PVR8_DCACHE_BASEADDR_MASK 0xFFFFFFFF - -/* DCache high address PVR mask */ -#define PVR9_DCACHE_HIGHADDR_MASK 0xFFFFFFFF - -/* Target family PVR mask */ -#define PVR10_TARGET_FAMILY_MASK 0xFF000000 - -/* MMU descrtiption */ -#define PVR11_USE_MMU 0xC0000000 -#define PVR11_MMU_ITLB_SIZE 0x38000000 -#define PVR11_MMU_DTLB_SIZE 0x07000000 -#define PVR11_MMU_TLB_ACCESS 0x00C00000 -#define PVR11_MMU_ZONES 0x003E0000 -/* MSR Reset value PVR mask */ -#define PVR11_MSR_RESET_VALUE_MASK 0x000007FF - -#define C_PVR_NONE 0 -#define C_PVR_BASIC 1 -#define C_PVR_FULL 2 - -/* CPU flags. */ - -/* Condition codes. */ -#define CC_GE 5 -#define CC_GT 4 -#define CC_LE 3 -#define CC_LT 2 -#define CC_NE 1 -#define CC_EQ 0 - -#define NB_MMU_MODES 3 - -#define STREAM_EXCEPTION (1 << 0) -#define STREAM_ATOMIC (1 << 1) -#define STREAM_TEST (1 << 2) -#define STREAM_CONTROL (1 << 3) -#define STREAM_NONBLOCK (1 << 4) - -struct CPUMBState { - uint32_t debug; - uint32_t btaken; - uint32_t btarget; - uint32_t bimm; - - uint32_t imm; - uint32_t regs[33]; - uint32_t sregs[24]; - float_status fp_status; - /* Stack protectors. Yes, it's a hw feature. */ - uint32_t slr, shr; - - /* lwx/swx reserved address */ -#define RES_ADDR_NONE 0xffffffff /* Use 0xffffffff to indicate no reservation */ - uint32_t res_addr; - uint32_t res_val; - - /* Internal flags. */ -#define IMM_FLAG 4 -#define MSR_EE_FLAG (1 << 8) -#define DRTI_FLAG (1 << 16) -#define DRTE_FLAG (1 << 17) -#define DRTB_FLAG (1 << 18) -#define D_FLAG (1 << 19) /* Bit in ESR. */ -/* TB dependent CPUMBState. */ -#define IFLAGS_TB_MASK (D_FLAG | IMM_FLAG | DRTI_FLAG | DRTE_FLAG | DRTB_FLAG) - uint32_t iflags; - -#if !defined(CONFIG_USER_ONLY) - /* Unified MMU. */ - struct microblaze_mmu mmu; -#endif - - CPU_COMMON - - /* These fields are preserved on reset. */ - - struct { - uint32_t regs[16]; - } pvr; -}; - -/** - * MicroBlazeCPU: - * @env: #CPUMBState - * - * A MicroBlaze CPU. - */ -struct MicroBlazeCPU { - /*< private >*/ - CPUState parent_obj; - - /*< public >*/ - - /* Microblaze Configuration Settings */ - struct { - bool stackprot; - uint32_t base_vectors; - uint8_t use_fpu; - bool use_mmu; - bool dcache_writeback; - bool endi; - char *version; - uint8_t pvr; - } cfg; - - CPUMBState env; -}; - -static inline MicroBlazeCPU *mb_env_get_cpu(CPUMBState *env) -{ - return container_of(env, MicroBlazeCPU, env); -} - -#define ENV_GET_CPU(e) CPU(mb_env_get_cpu(e)) - -#define ENV_OFFSET offsetof(MicroBlazeCPU, env) - -void mb_cpu_do_interrupt(CPUState *cs); -bool mb_cpu_exec_interrupt(CPUState *cs, int int_req); -void mb_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf, - int flags); -hwaddr mb_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); -int mb_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); -int mb_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); - -void mb_tcg_init(void); -MicroBlazeCPU *cpu_mb_init(const char *cpu_model); -/* you can call this signal handler from your SIGBUS and SIGSEGV - signal handlers to inform the virtual CPU of exceptions. non zero - is returned if the signal was handled by the virtual CPU. */ -int cpu_mb_signal_handler(int host_signum, void *pinfo, - void *puc); - -/* FIXME: MB uses variable pages down to 1K but linux only uses 4k. */ -#define TARGET_PAGE_BITS 12 - -#define TARGET_PHYS_ADDR_SPACE_BITS 32 -#define TARGET_VIRT_ADDR_SPACE_BITS 32 - -#define cpu_init(cpu_model) CPU(cpu_mb_init(cpu_model)) - -#define cpu_signal_handler cpu_mb_signal_handler - -/* MMU modes definitions */ -#define MMU_MODE0_SUFFIX _nommu -#define MMU_MODE1_SUFFIX _kernel -#define MMU_MODE2_SUFFIX _user -#define MMU_NOMMU_IDX 0 -#define MMU_KERNEL_IDX 1 -#define MMU_USER_IDX 2 -/* See NB_MMU_MODES further up the file. */ - -static inline int cpu_mmu_index (CPUMBState *env, bool ifetch) -{ - /* Are we in nommu mode?. */ - if (!(env->sregs[SR_MSR] & MSR_VM)) - return MMU_NOMMU_IDX; - - if (env->sregs[SR_MSR] & MSR_UM) - return MMU_USER_IDX; - return MMU_KERNEL_IDX; -} - -int mb_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw, - int mmu_idx); - -#include "exec/cpu-all.h" - -static inline void cpu_get_tb_cpu_state(CPUMBState *env, target_ulong *pc, - target_ulong *cs_base, uint32_t *flags) -{ - *pc = env->sregs[SR_PC]; - *cs_base = 0; - *flags = (env->iflags & IFLAGS_TB_MASK) | - (env->sregs[SR_MSR] & (MSR_UM | MSR_VM | MSR_EE)); -} - -#if !defined(CONFIG_USER_ONLY) -void mb_cpu_unassigned_access(CPUState *cpu, hwaddr addr, - bool is_write, bool is_exec, int is_asi, - unsigned size); -#endif - -#endif diff --git a/target-microblaze/gdbstub.c b/target-microblaze/gdbstub.c deleted file mode 100644 index 7fb076c2e9..0000000000 --- a/target-microblaze/gdbstub.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * MicroBlaze 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 mb_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) -{ - MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); - CPUMBState *env = &cpu->env; - - if (n < 32) { - return gdb_get_reg32(mem_buf, env->regs[n]); - } else { - return gdb_get_reg32(mem_buf, env->sregs[n - 32]); - } - return 0; -} - -int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) -{ - MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); - CPUClass *cc = CPU_GET_CLASS(cs); - CPUMBState *env = &cpu->env; - uint32_t tmp; - - if (n > cc->gdb_num_core_regs) { - return 0; - } - - tmp = ldl_p(mem_buf); - - if (n < 32) { - env->regs[n] = tmp; - } else { - env->sregs[n - 32] = tmp; - } - return 4; -} diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c deleted file mode 100644 index da394d1dfc..0000000000 --- a/target-microblaze/helper.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - * MicroBlaze helper routines. - * - * Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias@gmail.com> - * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd. - * - * 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/host-utils.h" -#include "exec/log.h" - -#define D(x) - -#if defined(CONFIG_USER_ONLY) - -void mb_cpu_do_interrupt(CPUState *cs) -{ - MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); - CPUMBState *env = &cpu->env; - - cs->exception_index = -1; - env->res_addr = RES_ADDR_NONE; - env->regs[14] = env->sregs[SR_PC]; -} - -int mb_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, - int mmu_idx) -{ - cs->exception_index = 0xaa; - cpu_dump_state(cs, stderr, fprintf, 0); - return 1; -} - -#else /* !CONFIG_USER_ONLY */ - -int mb_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, - int mmu_idx) -{ - MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); - CPUMBState *env = &cpu->env; - unsigned int hit; - unsigned int mmu_available; - int r = 1; - int prot; - - mmu_available = 0; - if (cpu->cfg.use_mmu) { - mmu_available = 1; - if ((cpu->cfg.pvr == C_PVR_FULL) && - (env->pvr.regs[11] & PVR11_USE_MMU) != PVR11_USE_MMU) { - mmu_available = 0; - } - } - - /* Translate if the MMU is available and enabled. */ - if (mmu_available && (env->sregs[SR_MSR] & MSR_VM)) { - target_ulong vaddr, paddr; - struct microblaze_mmu_lookup lu; - - hit = mmu_translate(&env->mmu, &lu, address, rw, mmu_idx); - if (hit) { - vaddr = address & TARGET_PAGE_MASK; - paddr = lu.paddr + vaddr - lu.vaddr; - - qemu_log_mask(CPU_LOG_MMU, "MMU map mmu=%d v=%x p=%x prot=%x\n", - mmu_idx, vaddr, paddr, lu.prot); - tlb_set_page(cs, vaddr, paddr, lu.prot, mmu_idx, TARGET_PAGE_SIZE); - r = 0; - } else { - env->sregs[SR_EAR] = address; - qemu_log_mask(CPU_LOG_MMU, "mmu=%d miss v=%" VADDR_PRIx "\n", - mmu_idx, address); - - switch (lu.err) { - case ERR_PROT: - env->sregs[SR_ESR] = rw == 2 ? 17 : 16; - env->sregs[SR_ESR] |= (rw == 1) << 10; - break; - case ERR_MISS: - env->sregs[SR_ESR] = rw == 2 ? 19 : 18; - env->sregs[SR_ESR] |= (rw == 1) << 10; - break; - default: - abort(); - break; - } - - if (cs->exception_index == EXCP_MMU) { - cpu_abort(cs, "recursive faults\n"); - } - - /* TLB miss. */ - cs->exception_index = EXCP_MMU; - } - } else { - /* MMU disabled or not available. */ - address &= TARGET_PAGE_MASK; - prot = PAGE_BITS; - tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE); - r = 0; - } - return r; -} - -void mb_cpu_do_interrupt(CPUState *cs) -{ - MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); - CPUMBState *env = &cpu->env; - uint32_t t; - - /* IMM flag cannot propagate across a branch and into the dslot. */ - assert(!((env->iflags & D_FLAG) && (env->iflags & IMM_FLAG))); - assert(!(env->iflags & (DRTI_FLAG | DRTE_FLAG | DRTB_FLAG))); -/* assert(env->sregs[SR_MSR] & (MSR_EE)); Only for HW exceptions. */ - env->res_addr = RES_ADDR_NONE; - switch (cs->exception_index) { - case EXCP_HW_EXCP: - if (!(env->pvr.regs[0] & PVR0_USE_EXC_MASK)) { - qemu_log_mask(LOG_GUEST_ERROR, "Exception raised on system without exceptions!\n"); - return; - } - - env->regs[17] = env->sregs[SR_PC] + 4; - env->sregs[SR_ESR] &= ~(1 << 12); - - /* Exception breaks branch + dslot sequence? */ - if (env->iflags & D_FLAG) { - env->sregs[SR_ESR] |= 1 << 12 ; - env->sregs[SR_BTR] = env->btarget; - } - - /* Disable the MMU. */ - t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1; - env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM); - env->sregs[SR_MSR] |= t; - /* Exception in progress. */ - env->sregs[SR_MSR] |= MSR_EIP; - - qemu_log_mask(CPU_LOG_INT, - "hw exception at pc=%x ear=%x esr=%x iflags=%x\n", - env->sregs[SR_PC], env->sregs[SR_EAR], - env->sregs[SR_ESR], env->iflags); - log_cpu_state_mask(CPU_LOG_INT, cs, 0); - env->iflags &= ~(IMM_FLAG | D_FLAG); - env->sregs[SR_PC] = cpu->cfg.base_vectors + 0x20; - break; - - case EXCP_MMU: - env->regs[17] = env->sregs[SR_PC]; - - env->sregs[SR_ESR] &= ~(1 << 12); - /* Exception breaks branch + dslot sequence? */ - if (env->iflags & D_FLAG) { - D(qemu_log("D_FLAG set at exception bimm=%d\n", env->bimm)); - env->sregs[SR_ESR] |= 1 << 12 ; - env->sregs[SR_BTR] = env->btarget; - - /* Reexecute the branch. */ - env->regs[17] -= 4; - /* was the branch immprefixed?. */ - if (env->bimm) { - qemu_log_mask(CPU_LOG_INT, - "bimm exception at pc=%x iflags=%x\n", - env->sregs[SR_PC], env->iflags); - env->regs[17] -= 4; - log_cpu_state_mask(CPU_LOG_INT, cs, 0); - } - } else if (env->iflags & IMM_FLAG) { - D(qemu_log("IMM_FLAG set at exception\n")); - env->regs[17] -= 4; - } - - /* Disable the MMU. */ - t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1; - env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM); - env->sregs[SR_MSR] |= t; - /* Exception in progress. */ - env->sregs[SR_MSR] |= MSR_EIP; - - qemu_log_mask(CPU_LOG_INT, - "exception at pc=%x ear=%x iflags=%x\n", - env->sregs[SR_PC], env->sregs[SR_EAR], env->iflags); - log_cpu_state_mask(CPU_LOG_INT, cs, 0); - env->iflags &= ~(IMM_FLAG | D_FLAG); - env->sregs[SR_PC] = cpu->cfg.base_vectors + 0x20; - break; - - case EXCP_IRQ: - assert(!(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))); - assert(env->sregs[SR_MSR] & MSR_IE); - assert(!(env->iflags & D_FLAG)); - - t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1; - -#if 0 -#include "disas/disas.h" - -/* Useful instrumentation when debugging interrupt issues in either - the models or in sw. */ - { - const char *sym; - - sym = lookup_symbol(env->sregs[SR_PC]); - if (sym - && (!strcmp("netif_rx", sym) - || !strcmp("process_backlog", sym))) { - - qemu_log( - "interrupt at pc=%x msr=%x %x iflags=%x sym=%s\n", - env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags, - sym); - - log_cpu_state(cs, 0); - } - } -#endif - qemu_log_mask(CPU_LOG_INT, - "interrupt at pc=%x msr=%x %x iflags=%x\n", - env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags); - - env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM \ - | MSR_UM | MSR_IE); - env->sregs[SR_MSR] |= t; - - env->regs[14] = env->sregs[SR_PC]; - env->sregs[SR_PC] = cpu->cfg.base_vectors + 0x10; - //log_cpu_state_mask(CPU_LOG_INT, cs, 0); - break; - - case EXCP_BREAK: - case EXCP_HW_BREAK: - assert(!(env->iflags & IMM_FLAG)); - assert(!(env->iflags & D_FLAG)); - t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1; - qemu_log_mask(CPU_LOG_INT, - "break at pc=%x msr=%x %x iflags=%x\n", - env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags); - log_cpu_state_mask(CPU_LOG_INT, cs, 0); - env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM); - env->sregs[SR_MSR] |= t; - env->sregs[SR_MSR] |= MSR_BIP; - if (cs->exception_index == EXCP_HW_BREAK) { - env->regs[16] = env->sregs[SR_PC]; - env->sregs[SR_MSR] |= MSR_BIP; - env->sregs[SR_PC] = cpu->cfg.base_vectors + 0x18; - } else - env->sregs[SR_PC] = env->btarget; - break; - default: - cpu_abort(cs, "unhandled exception type=%d\n", - cs->exception_index); - break; - } -} - -hwaddr mb_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) -{ - MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); - CPUMBState *env = &cpu->env; - target_ulong vaddr, paddr = 0; - struct microblaze_mmu_lookup lu; - unsigned int hit; - - if (env->sregs[SR_MSR] & MSR_VM) { - hit = mmu_translate(&env->mmu, &lu, addr, 0, 0); - if (hit) { - vaddr = addr & TARGET_PAGE_MASK; - paddr = lu.paddr + vaddr - lu.vaddr; - } else - paddr = 0; /* ???. */ - } else - paddr = addr & TARGET_PAGE_MASK; - - return paddr; -} -#endif - -bool mb_cpu_exec_interrupt(CPUState *cs, int interrupt_request) -{ - MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); - CPUMBState *env = &cpu->env; - - if ((interrupt_request & CPU_INTERRUPT_HARD) - && (env->sregs[SR_MSR] & MSR_IE) - && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP)) - && !(env->iflags & (D_FLAG | IMM_FLAG))) { - cs->exception_index = EXCP_IRQ; - mb_cpu_do_interrupt(cs); - return true; - } - return false; -} diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h deleted file mode 100644 index bd13826de0..0000000000 --- a/target-microblaze/helper.h +++ /dev/null @@ -1,37 +0,0 @@ -DEF_HELPER_2(raise_exception, void, env, i32) -DEF_HELPER_1(debug, void, env) -DEF_HELPER_FLAGS_3(carry, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) -DEF_HELPER_2(cmp, i32, i32, i32) -DEF_HELPER_2(cmpu, i32, i32, i32) -DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i32, i32) - -DEF_HELPER_3(divs, i32, env, i32, i32) -DEF_HELPER_3(divu, i32, env, i32, i32) - -DEF_HELPER_3(fadd, i32, env, i32, i32) -DEF_HELPER_3(frsub, i32, env, i32, i32) -DEF_HELPER_3(fmul, i32, env, i32, i32) -DEF_HELPER_3(fdiv, i32, env, i32, i32) -DEF_HELPER_2(flt, i32, env, i32) -DEF_HELPER_2(fint, i32, env, i32) -DEF_HELPER_2(fsqrt, i32, env, i32) - -DEF_HELPER_3(fcmp_un, i32, env, i32, i32) -DEF_HELPER_3(fcmp_lt, i32, env, i32, i32) -DEF_HELPER_3(fcmp_eq, i32, env, i32, i32) -DEF_HELPER_3(fcmp_le, i32, env, i32, i32) -DEF_HELPER_3(fcmp_gt, i32, env, i32, i32) -DEF_HELPER_3(fcmp_ne, i32, env, i32, i32) -DEF_HELPER_3(fcmp_ge, i32, env, i32, i32) - -DEF_HELPER_FLAGS_2(pcmpbf, TCG_CALL_NO_RWG_SE, i32, i32, i32) -#if !defined(CONFIG_USER_ONLY) -DEF_HELPER_2(mmu_read, i32, env, i32) -DEF_HELPER_3(mmu_write, void, env, i32, i32) -#endif - -DEF_HELPER_5(memalign, void, env, i32, i32, i32, i32) -DEF_HELPER_2(stackprot, void, env, i32) - -DEF_HELPER_2(get, i32, i32, i32) -DEF_HELPER_3(put, void, i32, i32, i32) diff --git a/target-microblaze/microblaze-decode.h b/target-microblaze/microblaze-decode.h deleted file mode 100644 index 401319ed46..0000000000 --- a/target-microblaze/microblaze-decode.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * MicroBlaze insn decoding macros. - * - * Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias@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/>. - */ - -/* Convenient binary macros. */ -#define HEX__(n) 0x##n##LU -#define B8__(x) ((x&0x0000000FLU)?1:0) \ - + ((x&0x000000F0LU)?2:0) \ - + ((x&0x00000F00LU)?4:0) \ - + ((x&0x0000F000LU)?8:0) \ - + ((x&0x000F0000LU)?16:0) \ - + ((x&0x00F00000LU)?32:0) \ - + ((x&0x0F000000LU)?64:0) \ - + ((x&0xF0000000LU)?128:0) -#define B8(d) ((unsigned char)B8__(HEX__(d))) - -/* Decode logic, value and mask. */ -#define DEC_ADD {B8(00000000), B8(00110001)} -#define DEC_SUB {B8(00000001), B8(00110001)} -#define DEC_AND {B8(00100001), B8(00110101)} -#define DEC_XOR {B8(00100010), B8(00110111)} -#define DEC_OR {B8(00100000), B8(00110111)} -#define DEC_BIT {B8(00100100), B8(00111111)} -#define DEC_MSR {B8(00100101), B8(00111111)} - -#define DEC_BARREL {B8(00010001), B8(00110111)} -#define DEC_MUL {B8(00010000), B8(00110111)} -#define DEC_DIV {B8(00010010), B8(00110111)} -#define DEC_FPU {B8(00010110), B8(00111111)} - -#define DEC_LD {B8(00110000), B8(00110100)} -#define DEC_ST {B8(00110100), B8(00110100)} -#define DEC_IMM {B8(00101100), B8(00111111)} - -#define DEC_BR {B8(00100110), B8(00110111)} -#define DEC_BCC {B8(00100111), B8(00110111)} -#define DEC_RTS {B8(00101101), B8(00111111)} - -#define DEC_STREAM {B8(00010011), B8(00110111)} - diff --git a/target-microblaze/mmu.c b/target-microblaze/mmu.c deleted file mode 100644 index a22a496ebb..0000000000 --- a/target-microblaze/mmu.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Microblaze MMU emulation for qemu. - * - * Copyright (c) 2009 Edgar E. Iglesias - * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd. - * - * 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" - -#define D(x) - -static unsigned int tlb_decode_size(unsigned int f) -{ - static const unsigned int sizes[] = { - 1 * 1024, 4 * 1024, 16 * 1024, 64 * 1024, 256 * 1024, - 1 * 1024 * 1024, 4 * 1024 * 1024, 16 * 1024 * 1024 - }; - assert(f < ARRAY_SIZE(sizes)); - return sizes[f]; -} - -static void mmu_flush_idx(CPUMBState *env, unsigned int idx) -{ - CPUState *cs = CPU(mb_env_get_cpu(env)); - struct microblaze_mmu *mmu = &env->mmu; - unsigned int tlb_size; - uint32_t tlb_tag, end, t; - - t = mmu->rams[RAM_TAG][idx]; - if (!(t & TLB_VALID)) - return; - - tlb_tag = t & TLB_EPN_MASK; - tlb_size = tlb_decode_size((t & TLB_PAGESZ_MASK) >> 7); - end = tlb_tag + tlb_size; - - while (tlb_tag < end) { - tlb_flush_page(cs, tlb_tag); - tlb_tag += TARGET_PAGE_SIZE; - } -} - -static void mmu_change_pid(CPUMBState *env, unsigned int newpid) -{ - struct microblaze_mmu *mmu = &env->mmu; - unsigned int i; - uint32_t t; - - if (newpid & ~0xff) - qemu_log_mask(LOG_GUEST_ERROR, "Illegal rpid=%x\n", newpid); - - for (i = 0; i < ARRAY_SIZE(mmu->rams[RAM_TAG]); i++) { - /* Lookup and decode. */ - t = mmu->rams[RAM_TAG][i]; - if (t & TLB_VALID) { - if (mmu->tids[i] && ((mmu->regs[MMU_R_PID] & 0xff) == mmu->tids[i])) - mmu_flush_idx(env, i); - } - } -} - -/* rw - 0 = read, 1 = write, 2 = fetch. */ -unsigned int mmu_translate(struct microblaze_mmu *mmu, - struct microblaze_mmu_lookup *lu, - target_ulong vaddr, int rw, int mmu_idx) -{ - unsigned int i, hit = 0; - unsigned int tlb_ex = 0, tlb_wr = 0, tlb_zsel; - unsigned int tlb_size; - uint32_t tlb_tag, tlb_rpn, mask, t0; - - lu->err = ERR_MISS; - for (i = 0; i < ARRAY_SIZE(mmu->rams[RAM_TAG]); i++) { - uint32_t t, d; - - /* Lookup and decode. */ - t = mmu->rams[RAM_TAG][i]; - D(qemu_log("TLB %d valid=%d\n", i, t & TLB_VALID)); - if (t & TLB_VALID) { - tlb_size = tlb_decode_size((t & TLB_PAGESZ_MASK) >> 7); - if (tlb_size < TARGET_PAGE_SIZE) { - qemu_log("%d pages not supported\n", tlb_size); - abort(); - } - - mask = ~(tlb_size - 1); - tlb_tag = t & TLB_EPN_MASK; - if ((vaddr & mask) != (tlb_tag & mask)) { - D(qemu_log("TLB %d vaddr=%x != tag=%x\n", - i, vaddr & mask, tlb_tag & mask)); - continue; - } - if (mmu->tids[i] - && ((mmu->regs[MMU_R_PID] & 0xff) != mmu->tids[i])) { - D(qemu_log("TLB %d pid=%x != tid=%x\n", - i, mmu->regs[MMU_R_PID], mmu->tids[i])); - continue; - } - - /* Bring in the data part. */ - d = mmu->rams[RAM_DATA][i]; - tlb_ex = d & TLB_EX; - tlb_wr = d & TLB_WR; - - /* Now let's see if there is a zone that overrides the protbits. */ - tlb_zsel = (d >> 4) & 0xf; - t0 = mmu->regs[MMU_R_ZPR] >> (30 - (tlb_zsel * 2)); - t0 &= 0x3; - - if (tlb_zsel > mmu->c_mmu_zones) { - qemu_log_mask(LOG_GUEST_ERROR, "tlb zone select out of range! %d\n", tlb_zsel); - t0 = 1; /* Ignore. */ - } - - if (mmu->c_mmu == 1) { - t0 = 1; /* Zones are disabled. */ - } - - switch (t0) { - case 0: - if (mmu_idx == MMU_USER_IDX) - continue; - break; - case 2: - if (mmu_idx != MMU_USER_IDX) { - tlb_ex = 1; - tlb_wr = 1; - } - break; - case 3: - tlb_ex = 1; - tlb_wr = 1; - break; - default: break; - } - - lu->err = ERR_PROT; - lu->prot = PAGE_READ; - if (tlb_wr) - lu->prot |= PAGE_WRITE; - else if (rw == 1) - goto done; - if (tlb_ex) - lu->prot |=PAGE_EXEC; - else if (rw == 2) { - goto done; - } - - tlb_rpn = d & TLB_RPN_MASK; - - lu->vaddr = tlb_tag; - lu->paddr = tlb_rpn; - lu->size = tlb_size; - lu->err = ERR_HIT; - lu->idx = i; - hit = 1; - goto done; - } - } -done: - D(qemu_log("MMU vaddr=%x rw=%d tlb_wr=%d tlb_ex=%d hit=%d\n", - vaddr, rw, tlb_wr, tlb_ex, hit)); - return hit; -} - -/* Writes/reads to the MMU's special regs end up here. */ -uint32_t mmu_read(CPUMBState *env, uint32_t rn) -{ - unsigned int i; - uint32_t r; - - if (env->mmu.c_mmu < 2 || !env->mmu.c_mmu_tlb_access) { - qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n"); - return 0; - } - - switch (rn) { - /* Reads to HI/LO trig reads from the mmu rams. */ - case MMU_R_TLBLO: - case MMU_R_TLBHI: - if (!(env->mmu.c_mmu_tlb_access & 1)) { - qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); - return 0; - } - - i = env->mmu.regs[MMU_R_TLBX] & 0xff; - r = env->mmu.rams[rn & 1][i]; - if (rn == MMU_R_TLBHI) - env->mmu.regs[MMU_R_PID] = env->mmu.tids[i]; - break; - case MMU_R_PID: - case MMU_R_ZPR: - if (!(env->mmu.c_mmu_tlb_access & 1)) { - qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); - return 0; - } - r = env->mmu.regs[rn]; - break; - default: - r = env->mmu.regs[rn]; - break; - } - D(qemu_log("%s rn=%d=%x\n", __func__, rn, r)); - return r; -} - -void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v) -{ - MicroBlazeCPU *cpu = mb_env_get_cpu(env); - unsigned int i; - D(qemu_log("%s rn=%d=%x old=%x\n", __func__, rn, v, env->mmu.regs[rn])); - - if (env->mmu.c_mmu < 2 || !env->mmu.c_mmu_tlb_access) { - qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n"); - return; - } - - switch (rn) { - /* Writes to HI/LO trig writes to the mmu rams. */ - case MMU_R_TLBLO: - case MMU_R_TLBHI: - i = env->mmu.regs[MMU_R_TLBX] & 0xff; - if (rn == MMU_R_TLBHI) { - if (i < 3 && !(v & TLB_VALID) && qemu_loglevel_mask(~0)) - qemu_log_mask(LOG_GUEST_ERROR, "invalidating index %x at pc=%x\n", - i, env->sregs[SR_PC]); - env->mmu.tids[i] = env->mmu.regs[MMU_R_PID] & 0xff; - mmu_flush_idx(env, i); - } - env->mmu.rams[rn & 1][i] = v; - - D(qemu_log("%s ram[%d][%d]=%x\n", __func__, rn & 1, i, v)); - break; - case MMU_R_ZPR: - if (env->mmu.c_mmu_tlb_access <= 1) { - qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); - return; - } - - /* Changes to the zone protection reg flush the QEMU TLB. - Fortunately, these are very uncommon. */ - if (v != env->mmu.regs[rn]) { - tlb_flush(CPU(cpu), 1); - } - env->mmu.regs[rn] = v; - break; - case MMU_R_PID: - if (env->mmu.c_mmu_tlb_access <= 1) { - qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); - return; - } - - if (v != env->mmu.regs[rn]) { - mmu_change_pid(env, v); - env->mmu.regs[rn] = v; - } - break; - case MMU_R_TLBSX: - { - struct microblaze_mmu_lookup lu; - int hit; - - if (env->mmu.c_mmu_tlb_access <= 1) { - qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); - return; - } - - hit = mmu_translate(&env->mmu, &lu, - v & TLB_EPN_MASK, 0, cpu_mmu_index(env, false)); - if (hit) { - env->mmu.regs[MMU_R_TLBX] = lu.idx; - } else - env->mmu.regs[MMU_R_TLBX] |= 0x80000000; - break; - } - default: - env->mmu.regs[rn] = v; - break; - } -} - -void mmu_init(struct microblaze_mmu *mmu) -{ - int i; - for (i = 0; i < ARRAY_SIZE(mmu->regs); i++) { - mmu->regs[i] = 0; - } -} diff --git a/target-microblaze/mmu.h b/target-microblaze/mmu.h deleted file mode 100644 index 3b7a9983d5..0000000000 --- a/target-microblaze/mmu.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Microblaze MMU emulation for qemu. - * - * Copyright (c) 2009 Edgar E. Iglesias - * - * 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/>. - */ - -#define MMU_R_PID 0 -#define MMU_R_ZPR 1 -#define MMU_R_TLBX 2 -#define MMU_R_TLBLO 3 -#define MMU_R_TLBHI 4 -#define MMU_R_TLBSX 5 - -#define RAM_DATA 1 -#define RAM_TAG 0 - -/* Tag portion */ -#define TLB_EPN_MASK 0xFFFFFC00 /* Effective Page Number */ -#define TLB_PAGESZ_MASK 0x00000380 -#define TLB_PAGESZ(x) (((x) & 0x7) << 7) -#define PAGESZ_1K 0 -#define PAGESZ_4K 1 -#define PAGESZ_16K 2 -#define PAGESZ_64K 3 -#define PAGESZ_256K 4 -#define PAGESZ_1M 5 -#define PAGESZ_4M 6 -#define PAGESZ_16M 7 -#define TLB_VALID 0x00000040 /* Entry is valid */ - -/* Data portion */ -#define TLB_RPN_MASK 0xFFFFFC00 /* Real Page Number */ -#define TLB_PERM_MASK 0x00000300 -#define TLB_EX 0x00000200 /* Instruction execution allowed */ -#define TLB_WR 0x00000100 /* Writes permitted */ -#define TLB_ZSEL_MASK 0x000000F0 -#define TLB_ZSEL(x) (((x) & 0xF) << 4) -#define TLB_ATTR_MASK 0x0000000F -#define TLB_W 0x00000008 /* Caching is write-through */ -#define TLB_I 0x00000004 /* Caching is inhibited */ -#define TLB_M 0x00000002 /* Memory is coherent */ -#define TLB_G 0x00000001 /* Memory is guarded from prefetch */ - -#define TLB_ENTRIES 64 - -struct microblaze_mmu -{ - /* Data and tag brams. */ - uint32_t rams[2][TLB_ENTRIES]; - /* We keep a separate ram for the tids to avoid the 48 bit tag width. */ - uint8_t tids[TLB_ENTRIES]; - /* Control flops. */ - uint32_t regs[8]; - - int c_mmu; - int c_mmu_tlb_access; - int c_mmu_zones; -}; - -struct microblaze_mmu_lookup -{ - uint32_t paddr; - uint32_t vaddr; - unsigned int size; - unsigned int idx; - int prot; - enum { - ERR_PROT, ERR_MISS, ERR_HIT - } err; -}; - -unsigned int mmu_translate(struct microblaze_mmu *mmu, - struct microblaze_mmu_lookup *lu, - target_ulong vaddr, int rw, int mmu_idx); -uint32_t mmu_read(CPUMBState *env, uint32_t rn); -void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v); -void mmu_init(struct microblaze_mmu *mmu); diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c deleted file mode 100644 index 4a856e6204..0000000000 --- a/target-microblaze/op_helper.c +++ /dev/null @@ -1,523 +0,0 @@ -/* - * Microblaze helper routines. - * - * Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias@gmail.com>. - * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd. - * - * 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 "qemu/host-utils.h" -#include "exec/exec-all.h" -#include "exec/cpu_ldst.h" - -#define D(x) - -#if !defined(CONFIG_USER_ONLY) - -/* Try to fill the TLB and return an exception if error. If retaddr is - * NULL, it means that the function was called in C code (i.e. not - * from generated code or from helper.c) - */ -void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type, - int mmu_idx, uintptr_t retaddr) -{ - int ret; - - ret = mb_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx); - if (unlikely(ret)) { - if (retaddr) { - /* now we have a real cpu fault */ - cpu_restore_state(cs, retaddr); - } - cpu_loop_exit(cs); - } -} -#endif - -void helper_put(uint32_t id, uint32_t ctrl, uint32_t data) -{ - int test = ctrl & STREAM_TEST; - int atomic = ctrl & STREAM_ATOMIC; - int control = ctrl & STREAM_CONTROL; - int nonblock = ctrl & STREAM_NONBLOCK; - int exception = ctrl & STREAM_EXCEPTION; - - qemu_log_mask(LOG_UNIMP, "Unhandled stream put to stream-id=%d data=%x %s%s%s%s%s\n", - id, data, - test ? "t" : "", - nonblock ? "n" : "", - exception ? "e" : "", - control ? "c" : "", - atomic ? "a" : ""); -} - -uint32_t helper_get(uint32_t id, uint32_t ctrl) -{ - int test = ctrl & STREAM_TEST; - int atomic = ctrl & STREAM_ATOMIC; - int control = ctrl & STREAM_CONTROL; - int nonblock = ctrl & STREAM_NONBLOCK; - int exception = ctrl & STREAM_EXCEPTION; - - qemu_log_mask(LOG_UNIMP, "Unhandled stream get from stream-id=%d %s%s%s%s%s\n", - id, - test ? "t" : "", - nonblock ? "n" : "", - exception ? "e" : "", - control ? "c" : "", - atomic ? "a" : ""); - return 0xdead0000 | id; -} - -void helper_raise_exception(CPUMBState *env, uint32_t index) -{ - CPUState *cs = CPU(mb_env_get_cpu(env)); - - cs->exception_index = index; - cpu_loop_exit(cs); -} - -void helper_debug(CPUMBState *env) -{ - int i; - - qemu_log("PC=%8.8x\n", env->sregs[SR_PC]); - qemu_log("rmsr=%x resr=%x rear=%x debug[%x] imm=%x iflags=%x\n", - env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR], - env->debug, env->imm, env->iflags); - qemu_log("btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n", - env->btaken, env->btarget, - (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel", - (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel", - (env->sregs[SR_MSR] & MSR_EIP), - (env->sregs[SR_MSR] & MSR_IE)); - for (i = 0; i < 32; i++) { - qemu_log("r%2.2d=%8.8x ", i, env->regs[i]); - if ((i + 1) % 4 == 0) - qemu_log("\n"); - } - qemu_log("\n\n"); -} - -static inline uint32_t compute_carry(uint32_t a, uint32_t b, uint32_t cin) -{ - uint32_t cout = 0; - - if ((b == ~0) && cin) - cout = 1; - else if ((~0 - a) < (b + cin)) - cout = 1; - return cout; -} - -uint32_t helper_cmp(uint32_t a, uint32_t b) -{ - uint32_t t; - - t = b + ~a + 1; - if ((b & 0x80000000) ^ (a & 0x80000000)) - t = (t & 0x7fffffff) | (b & 0x80000000); - return t; -} - -uint32_t helper_cmpu(uint32_t a, uint32_t b) -{ - uint32_t t; - - t = b + ~a + 1; - if ((b & 0x80000000) ^ (a & 0x80000000)) - t = (t & 0x7fffffff) | (a & 0x80000000); - return t; -} - -uint32_t helper_clz(uint32_t t0) -{ - return clz32(t0); -} - -uint32_t helper_carry(uint32_t a, uint32_t b, uint32_t cf) -{ - return compute_carry(a, b, cf); -} - -static inline int div_prepare(CPUMBState *env, uint32_t a, uint32_t b) -{ - if (b == 0) { - env->sregs[SR_MSR] |= MSR_DZ; - - if ((env->sregs[SR_MSR] & MSR_EE) - && !(env->pvr.regs[2] & PVR2_DIV_ZERO_EXC_MASK)) { - env->sregs[SR_ESR] = ESR_EC_DIVZERO; - helper_raise_exception(env, EXCP_HW_EXCP); - } - return 0; - } - env->sregs[SR_MSR] &= ~MSR_DZ; - return 1; -} - -uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b) -{ - if (!div_prepare(env, a, b)) { - return 0; - } - return (int32_t)a / (int32_t)b; -} - -uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b) -{ - if (!div_prepare(env, a, b)) { - return 0; - } - return a / b; -} - -/* raise FPU exception. */ -static void raise_fpu_exception(CPUMBState *env) -{ - env->sregs[SR_ESR] = ESR_EC_FPU; - helper_raise_exception(env, EXCP_HW_EXCP); -} - -static void update_fpu_flags(CPUMBState *env, int flags) -{ - int raise = 0; - - if (flags & float_flag_invalid) { - env->sregs[SR_FSR] |= FSR_IO; - raise = 1; - } - if (flags & float_flag_divbyzero) { - env->sregs[SR_FSR] |= FSR_DZ; - raise = 1; - } - if (flags & float_flag_overflow) { - env->sregs[SR_FSR] |= FSR_OF; - raise = 1; - } - if (flags & float_flag_underflow) { - env->sregs[SR_FSR] |= FSR_UF; - raise = 1; - } - if (raise - && (env->pvr.regs[2] & PVR2_FPU_EXC_MASK) - && (env->sregs[SR_MSR] & MSR_EE)) { - raise_fpu_exception(env); - } -} - -uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b) -{ - CPU_FloatU fd, fa, fb; - int flags; - - set_float_exception_flags(0, &env->fp_status); - fa.l = a; - fb.l = b; - fd.f = float32_add(fa.f, fb.f, &env->fp_status); - - flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags); - return fd.l; -} - -uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b) -{ - CPU_FloatU fd, fa, fb; - int flags; - - set_float_exception_flags(0, &env->fp_status); - fa.l = a; - fb.l = b; - fd.f = float32_sub(fb.f, fa.f, &env->fp_status); - flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags); - return fd.l; -} - -uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b) -{ - CPU_FloatU fd, fa, fb; - int flags; - - set_float_exception_flags(0, &env->fp_status); - fa.l = a; - fb.l = b; - fd.f = float32_mul(fa.f, fb.f, &env->fp_status); - flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags); - - return fd.l; -} - -uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b) -{ - CPU_FloatU fd, fa, fb; - int flags; - - set_float_exception_flags(0, &env->fp_status); - fa.l = a; - fb.l = b; - fd.f = float32_div(fb.f, fa.f, &env->fp_status); - flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags); - - return fd.l; -} - -uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b) -{ - CPU_FloatU fa, fb; - uint32_t r = 0; - - fa.l = a; - fb.l = b; - - if (float32_is_signaling_nan(fa.f, &env->fp_status) || - float32_is_signaling_nan(fb.f, &env->fp_status)) { - update_fpu_flags(env, float_flag_invalid); - r = 1; - } - - if (float32_is_quiet_nan(fa.f, &env->fp_status) || - float32_is_quiet_nan(fb.f, &env->fp_status)) { - r = 1; - } - - return r; -} - -uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b) -{ - CPU_FloatU fa, fb; - int r; - int flags; - - set_float_exception_flags(0, &env->fp_status); - fa.l = a; - fb.l = b; - r = float32_lt(fb.f, fa.f, &env->fp_status); - flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags & float_flag_invalid); - - return r; -} - -uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b) -{ - CPU_FloatU fa, fb; - int flags; - int r; - - set_float_exception_flags(0, &env->fp_status); - fa.l = a; - fb.l = b; - r = float32_eq_quiet(fa.f, fb.f, &env->fp_status); - flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags & float_flag_invalid); - - return r; -} - -uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b) -{ - CPU_FloatU fa, fb; - int flags; - int r; - - fa.l = a; - fb.l = b; - set_float_exception_flags(0, &env->fp_status); - r = float32_le(fa.f, fb.f, &env->fp_status); - flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags & float_flag_invalid); - - - return r; -} - -uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b) -{ - CPU_FloatU fa, fb; - int flags, r; - - fa.l = a; - fb.l = b; - set_float_exception_flags(0, &env->fp_status); - r = float32_lt(fa.f, fb.f, &env->fp_status); - flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags & float_flag_invalid); - return r; -} - -uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b) -{ - CPU_FloatU fa, fb; - int flags, r; - - fa.l = a; - fb.l = b; - set_float_exception_flags(0, &env->fp_status); - r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status); - flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags & float_flag_invalid); - - return r; -} - -uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b) -{ - CPU_FloatU fa, fb; - int flags, r; - - fa.l = a; - fb.l = b; - set_float_exception_flags(0, &env->fp_status); - r = !float32_lt(fa.f, fb.f, &env->fp_status); - flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags & float_flag_invalid); - - return r; -} - -uint32_t helper_flt(CPUMBState *env, uint32_t a) -{ - CPU_FloatU fd, fa; - - fa.l = a; - fd.f = int32_to_float32(fa.l, &env->fp_status); - return fd.l; -} - -uint32_t helper_fint(CPUMBState *env, uint32_t a) -{ - CPU_FloatU fa; - uint32_t r; - int flags; - - set_float_exception_flags(0, &env->fp_status); - fa.l = a; - r = float32_to_int32(fa.f, &env->fp_status); - flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags); - - return r; -} - -uint32_t helper_fsqrt(CPUMBState *env, uint32_t a) -{ - CPU_FloatU fd, fa; - int flags; - - set_float_exception_flags(0, &env->fp_status); - fa.l = a; - fd.l = float32_sqrt(fa.f, &env->fp_status); - flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags); - - return fd.l; -} - -uint32_t helper_pcmpbf(uint32_t a, uint32_t b) -{ - unsigned int i; - uint32_t mask = 0xff000000; - - for (i = 0; i < 4; i++) { - if ((a & mask) == (b & mask)) - return i + 1; - mask >>= 8; - } - return 0; -} - -void helper_memalign(CPUMBState *env, uint32_t addr, uint32_t dr, uint32_t wr, - uint32_t mask) -{ - if (addr & mask) { - qemu_log_mask(CPU_LOG_INT, - "unaligned access addr=%x mask=%x, wr=%d dr=r%d\n", - addr, mask, wr, dr); - env->sregs[SR_EAR] = addr; - env->sregs[SR_ESR] = ESR_EC_UNALIGNED_DATA | (wr << 10) \ - | (dr & 31) << 5; - if (mask == 3) { - env->sregs[SR_ESR] |= 1 << 11; - } - if (!(env->sregs[SR_MSR] & MSR_EE)) { - return; - } - helper_raise_exception(env, EXCP_HW_EXCP); - } -} - -void helper_stackprot(CPUMBState *env, uint32_t addr) -{ - if (addr < env->slr || addr > env->shr) { - qemu_log_mask(CPU_LOG_INT, "Stack protector violation at %x %x %x\n", - addr, env->slr, env->shr); - env->sregs[SR_EAR] = addr; - env->sregs[SR_ESR] = ESR_EC_STACKPROT; - helper_raise_exception(env, EXCP_HW_EXCP); - } -} - -#if !defined(CONFIG_USER_ONLY) -/* Writes/reads to the MMU's special regs end up here. */ -uint32_t helper_mmu_read(CPUMBState *env, uint32_t rn) -{ - return mmu_read(env, rn); -} - -void helper_mmu_write(CPUMBState *env, uint32_t rn, uint32_t v) -{ - mmu_write(env, rn, v); -} - -void mb_cpu_unassigned_access(CPUState *cs, hwaddr addr, - bool is_write, bool is_exec, int is_asi, - unsigned size) -{ - MicroBlazeCPU *cpu; - CPUMBState *env; - - qemu_log_mask(CPU_LOG_INT, "Unassigned " TARGET_FMT_plx " wr=%d exe=%d\n", - addr, is_write ? 1 : 0, is_exec ? 1 : 0); - if (cs == NULL) { - return; - } - cpu = MICROBLAZE_CPU(cs); - env = &cpu->env; - if (!(env->sregs[SR_MSR] & MSR_EE)) { - return; - } - - env->sregs[SR_EAR] = addr; - if (is_exec) { - if ((env->pvr.regs[2] & PVR2_IOPB_BUS_EXC_MASK)) { - env->sregs[SR_ESR] = ESR_EC_INSN_BUS; - helper_raise_exception(env, EXCP_HW_EXCP); - } - } else { - if ((env->pvr.regs[2] & PVR2_DOPB_BUS_EXC_MASK)) { - env->sregs[SR_ESR] = ESR_EC_DATA_BUS; - helper_raise_exception(env, EXCP_HW_EXCP); - } - } -} -#endif diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c deleted file mode 100644 index de2090ac71..0000000000 --- a/target-microblaze/translate.c +++ /dev/null @@ -1,1872 +0,0 @@ -/* - * Xilinx MicroBlaze emulation for qemu: main translation routines. - * - * Copyright (c) 2009 Edgar E. Iglesias. - * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd. - * - * 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 "disas/disas.h" -#include "exec/exec-all.h" -#include "tcg-op.h" -#include "exec/helper-proto.h" -#include "microblaze-decode.h" -#include "exec/cpu_ldst.h" -#include "exec/helper-gen.h" - -#include "trace-tcg.h" -#include "exec/log.h" - - -#define SIM_COMPAT 0 -#define DISAS_GNU 1 -#define DISAS_MB 1 -#if DISAS_MB && !SIM_COMPAT -# define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__) -#else -# define LOG_DIS(...) do { } while (0) -#endif - -#define D(x) - -#define EXTRACT_FIELD(src, start, end) \ - (((src) >> start) & ((1 << (end - start + 1)) - 1)) - -static TCGv env_debug; -static TCGv_env cpu_env; -static TCGv cpu_R[32]; -static TCGv cpu_SR[18]; -static TCGv env_imm; -static TCGv env_btaken; -static TCGv env_btarget; -static TCGv env_iflags; -static TCGv env_res_addr; -static TCGv env_res_val; - -#include "exec/gen-icount.h" - -/* This is the state at translation time. */ -typedef struct DisasContext { - MicroBlazeCPU *cpu; - target_ulong pc; - - /* Decoder. */ - int type_b; - uint32_t ir; - uint8_t opcode; - uint8_t rd, ra, rb; - uint16_t imm; - - unsigned int cpustate_changed; - unsigned int delayed_branch; - unsigned int tb_flags, synced_flags; /* tb dependent flags. */ - unsigned int clear_imm; - int is_jmp; - -#define JMP_NOJMP 0 -#define JMP_DIRECT 1 -#define JMP_DIRECT_CC 2 -#define JMP_INDIRECT 3 - unsigned int jmp; - uint32_t jmp_pc; - - int abort_at_next_insn; - int nr_nops; - struct TranslationBlock *tb; - int singlestep_enabled; -} DisasContext; - -static const char *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", -}; - -static const char *special_regnames[] = -{ - "rpc", "rmsr", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7", - "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15", - "sr16", "sr17", "sr18" -}; - -static inline void t_sync_flags(DisasContext *dc) -{ - /* Synch the tb dependent flags between translator and runtime. */ - if (dc->tb_flags != dc->synced_flags) { - tcg_gen_movi_tl(env_iflags, dc->tb_flags); - dc->synced_flags = dc->tb_flags; - } -} - -static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index) -{ - TCGv_i32 tmp = tcg_const_i32(index); - - t_sync_flags(dc); - tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); - gen_helper_raise_exception(cpu_env, tmp); - tcg_temp_free_i32(tmp); - dc->is_jmp = DISAS_UPDATE; -} - -static inline bool use_goto_tb(DisasContext *dc, target_ulong dest) -{ -#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_goto_tb(n); - tcg_gen_movi_tl(cpu_SR[SR_PC], dest); - tcg_gen_exit_tb((uintptr_t)dc->tb + n); - } else { - tcg_gen_movi_tl(cpu_SR[SR_PC], dest); - tcg_gen_exit_tb(0); - } -} - -static void read_carry(DisasContext *dc, TCGv d) -{ - tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31); -} - -/* - * write_carry sets the carry bits in MSR based on bit 0 of v. - * v[31:1] are ignored. - */ -static void write_carry(DisasContext *dc, TCGv v) -{ - TCGv t0 = tcg_temp_new(); - tcg_gen_shli_tl(t0, v, 31); - tcg_gen_sari_tl(t0, t0, 31); - tcg_gen_andi_tl(t0, t0, (MSR_C | MSR_CC)); - tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], - ~(MSR_C | MSR_CC)); - tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0); - tcg_temp_free(t0); -} - -static void write_carryi(DisasContext *dc, bool carry) -{ - TCGv t0 = tcg_temp_new(); - tcg_gen_movi_tl(t0, carry); - write_carry(dc, t0); - tcg_temp_free(t0); -} - -/* True if ALU operand b is a small immediate that may deserve - faster treatment. */ -static inline int dec_alu_op_b_is_small_imm(DisasContext *dc) -{ - /* Immediate insn without the imm prefix ? */ - return dc->type_b && !(dc->tb_flags & IMM_FLAG); -} - -static inline TCGv *dec_alu_op_b(DisasContext *dc) -{ - if (dc->type_b) { - if (dc->tb_flags & IMM_FLAG) - tcg_gen_ori_tl(env_imm, env_imm, dc->imm); - else - tcg_gen_movi_tl(env_imm, (int32_t)((int16_t)dc->imm)); - return &env_imm; - } else - return &cpu_R[dc->rb]; -} - -static void dec_add(DisasContext *dc) -{ - unsigned int k, c; - TCGv cf; - - k = dc->opcode & 4; - c = dc->opcode & 2; - - LOG_DIS("add%s%s%s r%d r%d r%d\n", - dc->type_b ? "i" : "", k ? "k" : "", c ? "c" : "", - dc->rd, dc->ra, dc->rb); - - /* Take care of the easy cases first. */ - if (k) { - /* k - keep carry, no need to update MSR. */ - /* If rd == r0, it's a nop. */ - if (dc->rd) { - tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); - - if (c) { - /* c - Add carry into the result. */ - cf = tcg_temp_new(); - - read_carry(dc, cf); - tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf); - tcg_temp_free(cf); - } - } - return; - } - - /* From now on, we can assume k is zero. So we need to update MSR. */ - /* Extract carry. */ - cf = tcg_temp_new(); - if (c) { - read_carry(dc, cf); - } else { - tcg_gen_movi_tl(cf, 0); - } - - if (dc->rd) { - TCGv ncf = tcg_temp_new(); - gen_helper_carry(ncf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf); - tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); - tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf); - write_carry(dc, ncf); - tcg_temp_free(ncf); - } else { - gen_helper_carry(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf); - write_carry(dc, cf); - } - tcg_temp_free(cf); -} - -static void dec_sub(DisasContext *dc) -{ - unsigned int u, cmp, k, c; - TCGv cf, na; - - u = dc->imm & 2; - k = dc->opcode & 4; - c = dc->opcode & 2; - cmp = (dc->imm & 1) && (!dc->type_b) && k; - - if (cmp) { - LOG_DIS("cmp%s r%d, r%d ir=%x\n", u ? "u" : "", dc->rd, dc->ra, dc->ir); - if (dc->rd) { - if (u) - gen_helper_cmpu(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); - else - gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); - } - return; - } - - LOG_DIS("sub%s%s r%d, r%d r%d\n", - k ? "k" : "", c ? "c" : "", dc->rd, dc->ra, dc->rb); - - /* Take care of the easy cases first. */ - if (k) { - /* k - keep carry, no need to update MSR. */ - /* If rd == r0, it's a nop. */ - if (dc->rd) { - tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]); - - if (c) { - /* c - Add carry into the result. */ - cf = tcg_temp_new(); - - read_carry(dc, cf); - tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf); - tcg_temp_free(cf); - } - } - return; - } - - /* From now on, we can assume k is zero. So we need to update MSR. */ - /* Extract carry. And complement a into na. */ - cf = tcg_temp_new(); - na = tcg_temp_new(); - if (c) { - read_carry(dc, cf); - } else { - tcg_gen_movi_tl(cf, 1); - } - - /* d = b + ~a + c. carry defaults to 1. */ - tcg_gen_not_tl(na, cpu_R[dc->ra]); - - if (dc->rd) { - TCGv ncf = tcg_temp_new(); - gen_helper_carry(ncf, na, *(dec_alu_op_b(dc)), cf); - tcg_gen_add_tl(cpu_R[dc->rd], na, *(dec_alu_op_b(dc))); - tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf); - write_carry(dc, ncf); - tcg_temp_free(ncf); - } else { - gen_helper_carry(cf, na, *(dec_alu_op_b(dc)), cf); - write_carry(dc, cf); - } - tcg_temp_free(cf); - tcg_temp_free(na); -} - -static void dec_pattern(DisasContext *dc) -{ - unsigned int mode; - - if ((dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && !((dc->cpu->env.pvr.regs[2] & PVR2_USE_PCMP_INSTR))) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - } - - mode = dc->opcode & 3; - switch (mode) { - case 0: - /* pcmpbf. */ - LOG_DIS("pcmpbf r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - if (dc->rd) - gen_helper_pcmpbf(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 2: - LOG_DIS("pcmpeq r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - if (dc->rd) { - tcg_gen_setcond_tl(TCG_COND_EQ, cpu_R[dc->rd], - cpu_R[dc->ra], cpu_R[dc->rb]); - } - break; - case 3: - LOG_DIS("pcmpne r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - if (dc->rd) { - tcg_gen_setcond_tl(TCG_COND_NE, cpu_R[dc->rd], - cpu_R[dc->ra], cpu_R[dc->rb]); - } - break; - default: - cpu_abort(CPU(dc->cpu), - "unsupported pattern insn opcode=%x\n", dc->opcode); - break; - } -} - -static void dec_and(DisasContext *dc) -{ - unsigned int not; - - if (!dc->type_b && (dc->imm & (1 << 10))) { - dec_pattern(dc); - return; - } - - not = dc->opcode & (1 << 1); - LOG_DIS("and%s\n", not ? "n" : ""); - - if (!dc->rd) - return; - - if (not) { - tcg_gen_andc_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); - } else - tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); -} - -static void dec_or(DisasContext *dc) -{ - if (!dc->type_b && (dc->imm & (1 << 10))) { - dec_pattern(dc); - return; - } - - LOG_DIS("or r%d r%d r%d imm=%x\n", dc->rd, dc->ra, dc->rb, dc->imm); - if (dc->rd) - tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); -} - -static void dec_xor(DisasContext *dc) -{ - if (!dc->type_b && (dc->imm & (1 << 10))) { - dec_pattern(dc); - return; - } - - LOG_DIS("xor r%d\n", dc->rd); - if (dc->rd) - tcg_gen_xor_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); -} - -static inline void msr_read(DisasContext *dc, TCGv d) -{ - tcg_gen_mov_tl(d, cpu_SR[SR_MSR]); -} - -static inline void msr_write(DisasContext *dc, TCGv v) -{ - TCGv t; - - t = tcg_temp_new(); - dc->cpustate_changed = 1; - /* PVR bit is not writable. */ - tcg_gen_andi_tl(t, v, ~MSR_PVR); - tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], MSR_PVR); - tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], v); - tcg_temp_free(t); -} - -static void dec_msr(DisasContext *dc) -{ - CPUState *cs = CPU(dc->cpu); - TCGv t0, t1; - unsigned int sr, to, rn; - int mem_index = cpu_mmu_index(&dc->cpu->env, false); - - sr = dc->imm & ((1 << 14) - 1); - to = dc->imm & (1 << 14); - dc->type_b = 1; - if (to) - dc->cpustate_changed = 1; - - /* msrclr and msrset. */ - if (!(dc->imm & (1 << 15))) { - unsigned int clr = dc->ir & (1 << 16); - - LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set", - dc->rd, dc->imm); - - if (!(dc->cpu->env.pvr.regs[2] & PVR2_USE_MSR_INSTR)) { - /* nop??? */ - return; - } - - if ((dc->tb_flags & MSR_EE_FLAG) - && mem_index == MMU_USER_IDX && (dc->imm != 4 && dc->imm != 0)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } - - if (dc->rd) - msr_read(dc, cpu_R[dc->rd]); - - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - msr_read(dc, t0); - tcg_gen_mov_tl(t1, *(dec_alu_op_b(dc))); - - if (clr) { - tcg_gen_not_tl(t1, t1); - tcg_gen_and_tl(t0, t0, t1); - } else - tcg_gen_or_tl(t0, t0, t1); - msr_write(dc, t0); - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4); - dc->is_jmp = DISAS_UPDATE; - return; - } - - if (to) { - if ((dc->tb_flags & MSR_EE_FLAG) - && mem_index == MMU_USER_IDX) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } - } - -#if !defined(CONFIG_USER_ONLY) - /* Catch read/writes to the mmu block. */ - if ((sr & ~0xff) == 0x1000) { - sr &= 7; - LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm); - if (to) - gen_helper_mmu_write(cpu_env, tcg_const_tl(sr), cpu_R[dc->ra]); - else - gen_helper_mmu_read(cpu_R[dc->rd], cpu_env, tcg_const_tl(sr)); - return; - } -#endif - - if (to) { - LOG_DIS("m%ss sr%x r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm); - switch (sr) { - case 0: - break; - case 1: - msr_write(dc, cpu_R[dc->ra]); - break; - case 0x3: - tcg_gen_mov_tl(cpu_SR[SR_EAR], cpu_R[dc->ra]); - break; - case 0x5: - tcg_gen_mov_tl(cpu_SR[SR_ESR], cpu_R[dc->ra]); - break; - case 0x7: - tcg_gen_andi_tl(cpu_SR[SR_FSR], cpu_R[dc->ra], 31); - break; - case 0x800: - tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUMBState, slr)); - break; - case 0x802: - tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUMBState, shr)); - break; - default: - cpu_abort(CPU(dc->cpu), "unknown mts reg %x\n", sr); - break; - } - } else { - LOG_DIS("m%ss r%d sr%x imm=%x\n", to ? "t" : "f", dc->rd, sr, dc->imm); - - switch (sr) { - case 0: - tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc); - break; - case 1: - msr_read(dc, cpu_R[dc->rd]); - break; - case 0x3: - tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_EAR]); - break; - case 0x5: - tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_ESR]); - break; - case 0x7: - tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_FSR]); - break; - case 0xb: - tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_BTR]); - break; - case 0x800: - tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUMBState, slr)); - break; - case 0x802: - tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUMBState, shr)); - break; - case 0x2000: - case 0x2001: - case 0x2002: - case 0x2003: - case 0x2004: - case 0x2005: - case 0x2006: - case 0x2007: - case 0x2008: - case 0x2009: - case 0x200a: - case 0x200b: - case 0x200c: - rn = sr & 0xf; - tcg_gen_ld_tl(cpu_R[dc->rd], - cpu_env, offsetof(CPUMBState, pvr.regs[rn])); - break; - default: - cpu_abort(cs, "unknown mfs reg %x\n", sr); - break; - } - } - - if (dc->rd == 0) { - tcg_gen_movi_tl(cpu_R[0], 0); - } -} - -/* Multiplier unit. */ -static void dec_mul(DisasContext *dc) -{ - TCGv tmp; - unsigned int subcode; - - if ((dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && !(dc->cpu->env.pvr.regs[0] & PVR0_USE_HW_MUL_MASK)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } - - subcode = dc->imm & 3; - - if (dc->type_b) { - LOG_DIS("muli r%d r%d %x\n", dc->rd, dc->ra, dc->imm); - tcg_gen_mul_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); - return; - } - - /* mulh, mulhsu and mulhu are not available if C_USE_HW_MUL is < 2. */ - if (subcode >= 1 && subcode <= 3 - && !((dc->cpu->env.pvr.regs[2] & PVR2_USE_MUL64_MASK))) { - /* nop??? */ - } - - tmp = tcg_temp_new(); - switch (subcode) { - case 0: - LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - tcg_gen_mul_tl(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 1: - LOG_DIS("mulh r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - tcg_gen_muls2_tl(tmp, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 2: - LOG_DIS("mulhsu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - tcg_gen_mulsu2_tl(tmp, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 3: - LOG_DIS("mulhu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - tcg_gen_mulu2_tl(tmp, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); - break; - default: - cpu_abort(CPU(dc->cpu), "unknown MUL insn %x\n", subcode); - break; - } - tcg_temp_free(tmp); -} - -/* Div unit. */ -static void dec_div(DisasContext *dc) -{ - unsigned int u; - - u = dc->imm & 2; - LOG_DIS("div\n"); - - if ((dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && !((dc->cpu->env.pvr.regs[0] & PVR0_USE_DIV_MASK))) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - } - - if (u) - gen_helper_divu(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)), - cpu_R[dc->ra]); - else - gen_helper_divs(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)), - cpu_R[dc->ra]); - if (!dc->rd) - tcg_gen_movi_tl(cpu_R[dc->rd], 0); -} - -static void dec_barrel(DisasContext *dc) -{ - TCGv t0; - unsigned int s, t; - - if ((dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && !(dc->cpu->env.pvr.regs[0] & PVR0_USE_BARREL_MASK)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } - - s = dc->imm & (1 << 10); - t = dc->imm & (1 << 9); - - LOG_DIS("bs%s%s r%d r%d r%d\n", - s ? "l" : "r", t ? "a" : "l", dc->rd, dc->ra, dc->rb); - - t0 = tcg_temp_new(); - - tcg_gen_mov_tl(t0, *(dec_alu_op_b(dc))); - tcg_gen_andi_tl(t0, t0, 31); - - if (s) - tcg_gen_shl_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0); - else { - if (t) - tcg_gen_sar_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0); - else - tcg_gen_shr_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0); - } -} - -static void dec_bit(DisasContext *dc) -{ - CPUState *cs = CPU(dc->cpu); - TCGv t0; - unsigned int op; - int mem_index = cpu_mmu_index(&dc->cpu->env, false); - - op = dc->ir & ((1 << 9) - 1); - switch (op) { - case 0x21: - /* src. */ - t0 = tcg_temp_new(); - - LOG_DIS("src r%d r%d\n", dc->rd, dc->ra); - tcg_gen_andi_tl(t0, cpu_SR[SR_MSR], MSR_CC); - write_carry(dc, cpu_R[dc->ra]); - if (dc->rd) { - tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1); - tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->rd], t0); - } - tcg_temp_free(t0); - break; - - case 0x1: - case 0x41: - /* srl. */ - LOG_DIS("srl r%d r%d\n", dc->rd, dc->ra); - - /* Update carry. Note that write carry only looks at the LSB. */ - write_carry(dc, cpu_R[dc->ra]); - if (dc->rd) { - if (op == 0x41) - tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1); - else - tcg_gen_sari_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1); - } - break; - case 0x60: - LOG_DIS("ext8s r%d r%d\n", dc->rd, dc->ra); - tcg_gen_ext8s_i32(cpu_R[dc->rd], cpu_R[dc->ra]); - break; - case 0x61: - LOG_DIS("ext16s r%d r%d\n", dc->rd, dc->ra); - tcg_gen_ext16s_i32(cpu_R[dc->rd], cpu_R[dc->ra]); - break; - case 0x64: - case 0x66: - case 0x74: - case 0x76: - /* wdc. */ - LOG_DIS("wdc r%d\n", dc->ra); - if ((dc->tb_flags & MSR_EE_FLAG) - && mem_index == MMU_USER_IDX) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } - break; - case 0x68: - /* wic. */ - LOG_DIS("wic r%d\n", dc->ra); - if ((dc->tb_flags & MSR_EE_FLAG) - && mem_index == MMU_USER_IDX) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } - break; - case 0xe0: - if ((dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && !((dc->cpu->env.pvr.regs[2] & PVR2_USE_PCMP_INSTR))) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - } - if (dc->cpu->env.pvr.regs[2] & PVR2_USE_PCMP_INSTR) { - gen_helper_clz(cpu_R[dc->rd], cpu_R[dc->ra]); - } - break; - case 0x1e0: - /* swapb */ - LOG_DIS("swapb r%d r%d\n", dc->rd, dc->ra); - tcg_gen_bswap32_i32(cpu_R[dc->rd], cpu_R[dc->ra]); - break; - case 0x1e2: - /*swaph */ - LOG_DIS("swaph r%d r%d\n", dc->rd, dc->ra); - tcg_gen_rotri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 16); - break; - default: - cpu_abort(cs, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n", - dc->pc, op, dc->rd, dc->ra, dc->rb); - break; - } -} - -static inline void sync_jmpstate(DisasContext *dc) -{ - if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) { - if (dc->jmp == JMP_DIRECT) { - tcg_gen_movi_tl(env_btaken, 1); - } - dc->jmp = JMP_INDIRECT; - tcg_gen_movi_tl(env_btarget, dc->jmp_pc); - } -} - -static void dec_imm(DisasContext *dc) -{ - LOG_DIS("imm %x\n", dc->imm << 16); - tcg_gen_movi_tl(env_imm, (dc->imm << 16)); - dc->tb_flags |= IMM_FLAG; - dc->clear_imm = 0; -} - -static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t) -{ - unsigned int extimm = dc->tb_flags & IMM_FLAG; - /* Should be set to one if r1 is used by loadstores. */ - int stackprot = 0; - - /* All load/stores use ra. */ - if (dc->ra == 1 && dc->cpu->cfg.stackprot) { - stackprot = 1; - } - - /* Treat the common cases first. */ - if (!dc->type_b) { - /* If any of the regs is r0, return a ptr to the other. */ - if (dc->ra == 0) { - return &cpu_R[dc->rb]; - } else if (dc->rb == 0) { - return &cpu_R[dc->ra]; - } - - if (dc->rb == 1 && dc->cpu->cfg.stackprot) { - stackprot = 1; - } - - *t = tcg_temp_new(); - tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]); - - if (stackprot) { - gen_helper_stackprot(cpu_env, *t); - } - return t; - } - /* Immediate. */ - if (!extimm) { - if (dc->imm == 0) { - return &cpu_R[dc->ra]; - } - *t = tcg_temp_new(); - tcg_gen_movi_tl(*t, (int32_t)((int16_t)dc->imm)); - tcg_gen_add_tl(*t, cpu_R[dc->ra], *t); - } else { - *t = tcg_temp_new(); - tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc))); - } - - if (stackprot) { - gen_helper_stackprot(cpu_env, *t); - } - return t; -} - -static void dec_load(DisasContext *dc) -{ - TCGv t, v, *addr; - unsigned int size, rev = 0, ex = 0; - TCGMemOp mop; - - mop = dc->opcode & 3; - size = 1 << mop; - if (!dc->type_b) { - rev = (dc->ir >> 9) & 1; - ex = (dc->ir >> 10) & 1; - } - mop |= MO_TE; - if (rev) { - mop ^= MO_BSWAP; - } - - if (size > 4 && (dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } - - LOG_DIS("l%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", - ex ? "x" : ""); - - t_sync_flags(dc); - addr = compute_ldst_addr(dc, &t); - - /* - * When doing reverse accesses we need to do two things. - * - * 1. Reverse the address wrt endianness. - * 2. Byteswap the data lanes on the way back into the CPU core. - */ - if (rev && size != 4) { - /* Endian reverse the address. t is addr. */ - switch (size) { - case 1: - { - /* 00 -> 11 - 01 -> 10 - 10 -> 10 - 11 -> 00 */ - TCGv low = tcg_temp_new(); - - /* Force addr into the temp. */ - if (addr != &t) { - t = tcg_temp_new(); - tcg_gen_mov_tl(t, *addr); - addr = &t; - } - - tcg_gen_andi_tl(low, t, 3); - tcg_gen_sub_tl(low, tcg_const_tl(3), low); - tcg_gen_andi_tl(t, t, ~3); - tcg_gen_or_tl(t, t, low); - tcg_gen_mov_tl(env_imm, t); - tcg_temp_free(low); - break; - } - - case 2: - /* 00 -> 10 - 10 -> 00. */ - /* Force addr into the temp. */ - if (addr != &t) { - t = tcg_temp_new(); - tcg_gen_xori_tl(t, *addr, 2); - addr = &t; - } else { - tcg_gen_xori_tl(t, t, 2); - } - break; - default: - cpu_abort(CPU(dc->cpu), "Invalid reverse size\n"); - break; - } - } - - /* lwx does not throw unaligned access errors, so force alignment */ - if (ex) { - /* Force addr into the temp. */ - if (addr != &t) { - t = tcg_temp_new(); - tcg_gen_mov_tl(t, *addr); - addr = &t; - } - tcg_gen_andi_tl(t, t, ~3); - } - - /* If we get a fault on a dslot, the jmpstate better be in sync. */ - sync_jmpstate(dc); - - /* Verify alignment if needed. */ - /* - * Microblaze gives MMU faults priority over faults due to - * unaligned addresses. That's why we speculatively do the load - * into v. If the load succeeds, we verify alignment of the - * address and if that succeeds we write into the destination reg. - */ - v = tcg_temp_new(); - tcg_gen_qemu_ld_tl(v, *addr, cpu_mmu_index(&dc->cpu->env, false), mop); - - if ((dc->cpu->env.pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) { - tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); - gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd), - tcg_const_tl(0), tcg_const_tl(size - 1)); - } - - if (ex) { - tcg_gen_mov_tl(env_res_addr, *addr); - tcg_gen_mov_tl(env_res_val, v); - } - if (dc->rd) { - tcg_gen_mov_tl(cpu_R[dc->rd], v); - } - tcg_temp_free(v); - - if (ex) { /* lwx */ - /* no support for AXI exclusive so always clear C */ - write_carryi(dc, 0); - } - - if (addr == &t) - tcg_temp_free(t); -} - -static void dec_store(DisasContext *dc) -{ - TCGv t, *addr, swx_addr; - TCGLabel *swx_skip = NULL; - unsigned int size, rev = 0, ex = 0; - TCGMemOp mop; - - mop = dc->opcode & 3; - size = 1 << mop; - if (!dc->type_b) { - rev = (dc->ir >> 9) & 1; - ex = (dc->ir >> 10) & 1; - } - mop |= MO_TE; - if (rev) { - mop ^= MO_BSWAP; - } - - if (size > 4 && (dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } - - LOG_DIS("s%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", - ex ? "x" : ""); - t_sync_flags(dc); - /* If we get a fault on a dslot, the jmpstate better be in sync. */ - sync_jmpstate(dc); - addr = compute_ldst_addr(dc, &t); - - swx_addr = tcg_temp_local_new(); - if (ex) { /* swx */ - TCGv tval; - - /* Force addr into the swx_addr. */ - tcg_gen_mov_tl(swx_addr, *addr); - addr = &swx_addr; - /* swx does not throw unaligned access errors, so force alignment */ - tcg_gen_andi_tl(swx_addr, swx_addr, ~3); - - write_carryi(dc, 1); - swx_skip = gen_new_label(); - tcg_gen_brcond_tl(TCG_COND_NE, env_res_addr, swx_addr, swx_skip); - - /* Compare the value loaded at lwx with current contents of - the reserved location. - FIXME: This only works for system emulation where we can expect - this compare and the following write to be atomic. For user - emulation we need to add atomicity between threads. */ - tval = tcg_temp_new(); - tcg_gen_qemu_ld_tl(tval, swx_addr, cpu_mmu_index(&dc->cpu->env, false), - MO_TEUL); - tcg_gen_brcond_tl(TCG_COND_NE, env_res_val, tval, swx_skip); - write_carryi(dc, 0); - tcg_temp_free(tval); - } - - if (rev && size != 4) { - /* Endian reverse the address. t is addr. */ - switch (size) { - case 1: - { - /* 00 -> 11 - 01 -> 10 - 10 -> 10 - 11 -> 00 */ - TCGv low = tcg_temp_new(); - - /* Force addr into the temp. */ - if (addr != &t) { - t = tcg_temp_new(); - tcg_gen_mov_tl(t, *addr); - addr = &t; - } - - tcg_gen_andi_tl(low, t, 3); - tcg_gen_sub_tl(low, tcg_const_tl(3), low); - tcg_gen_andi_tl(t, t, ~3); - tcg_gen_or_tl(t, t, low); - tcg_gen_mov_tl(env_imm, t); - tcg_temp_free(low); - break; - } - - case 2: - /* 00 -> 10 - 10 -> 00. */ - /* Force addr into the temp. */ - if (addr != &t) { - t = tcg_temp_new(); - tcg_gen_xori_tl(t, *addr, 2); - addr = &t; - } else { - tcg_gen_xori_tl(t, t, 2); - } - break; - default: - cpu_abort(CPU(dc->cpu), "Invalid reverse size\n"); - break; - } - } - tcg_gen_qemu_st_tl(cpu_R[dc->rd], *addr, cpu_mmu_index(&dc->cpu->env, false), mop); - - /* Verify alignment if needed. */ - if ((dc->cpu->env.pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) { - tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); - /* FIXME: if the alignment is wrong, we should restore the value - * in memory. One possible way to achieve this is to probe - * the MMU prior to the memaccess, thay way we could put - * the alignment checks in between the probe and the mem - * access. - */ - gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd), - tcg_const_tl(1), tcg_const_tl(size - 1)); - } - - if (ex) { - gen_set_label(swx_skip); - } - tcg_temp_free(swx_addr); - - if (addr == &t) - tcg_temp_free(t); -} - -static inline void eval_cc(DisasContext *dc, unsigned int cc, - TCGv d, TCGv a, TCGv b) -{ - switch (cc) { - case CC_EQ: - tcg_gen_setcond_tl(TCG_COND_EQ, d, a, b); - break; - case CC_NE: - tcg_gen_setcond_tl(TCG_COND_NE, d, a, b); - break; - case CC_LT: - tcg_gen_setcond_tl(TCG_COND_LT, d, a, b); - break; - case CC_LE: - tcg_gen_setcond_tl(TCG_COND_LE, d, a, b); - break; - case CC_GE: - tcg_gen_setcond_tl(TCG_COND_GE, d, a, b); - break; - case CC_GT: - tcg_gen_setcond_tl(TCG_COND_GT, d, a, b); - break; - default: - cpu_abort(CPU(dc->cpu), "Unknown condition code %x.\n", cc); - break; - } -} - -static void eval_cond_jmp(DisasContext *dc, TCGv pc_true, TCGv pc_false) -{ - TCGLabel *l1 = gen_new_label(); - /* Conditional jmp. */ - tcg_gen_mov_tl(cpu_SR[SR_PC], pc_false); - tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1); - tcg_gen_mov_tl(cpu_SR[SR_PC], pc_true); - gen_set_label(l1); -} - -static void dec_bcc(DisasContext *dc) -{ - unsigned int cc; - unsigned int dslot; - - cc = EXTRACT_FIELD(dc->ir, 21, 23); - dslot = dc->ir & (1 << 25); - LOG_DIS("bcc%s r%d %x\n", dslot ? "d" : "", dc->ra, dc->imm); - - dc->delayed_branch = 1; - if (dslot) { - dc->delayed_branch = 2; - dc->tb_flags |= D_FLAG; - tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)), - cpu_env, offsetof(CPUMBState, bimm)); - } - - if (dec_alu_op_b_is_small_imm(dc)) { - int32_t offset = (int32_t)((int16_t)dc->imm); /* sign-extend. */ - - tcg_gen_movi_tl(env_btarget, dc->pc + offset); - dc->jmp = JMP_DIRECT_CC; - dc->jmp_pc = dc->pc + offset; - } else { - dc->jmp = JMP_INDIRECT; - tcg_gen_movi_tl(env_btarget, dc->pc); - tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc))); - } - eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0)); -} - -static void dec_br(DisasContext *dc) -{ - unsigned int dslot, link, abs, mbar; - int mem_index = cpu_mmu_index(&dc->cpu->env, false); - - dslot = dc->ir & (1 << 20); - abs = dc->ir & (1 << 19); - link = dc->ir & (1 << 18); - - /* Memory barrier. */ - mbar = (dc->ir >> 16) & 31; - if (mbar == 2 && dc->imm == 4) { - /* mbar IMM & 16 decodes to sleep. */ - if (dc->rd & 16) { - TCGv_i32 tmp_hlt = tcg_const_i32(EXCP_HLT); - TCGv_i32 tmp_1 = tcg_const_i32(1); - - LOG_DIS("sleep\n"); - - t_sync_flags(dc); - tcg_gen_st_i32(tmp_1, cpu_env, - -offsetof(MicroBlazeCPU, env) - +offsetof(CPUState, halted)); - tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4); - gen_helper_raise_exception(cpu_env, tmp_hlt); - tcg_temp_free_i32(tmp_hlt); - tcg_temp_free_i32(tmp_1); - return; - } - LOG_DIS("mbar %d\n", dc->rd); - /* Break the TB. */ - dc->cpustate_changed = 1; - return; - } - - LOG_DIS("br%s%s%s%s imm=%x\n", - abs ? "a" : "", link ? "l" : "", - dc->type_b ? "i" : "", dslot ? "d" : "", - dc->imm); - - dc->delayed_branch = 1; - if (dslot) { - dc->delayed_branch = 2; - dc->tb_flags |= D_FLAG; - tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)), - cpu_env, offsetof(CPUMBState, bimm)); - } - if (link && dc->rd) - tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc); - - dc->jmp = JMP_INDIRECT; - if (abs) { - tcg_gen_movi_tl(env_btaken, 1); - tcg_gen_mov_tl(env_btarget, *(dec_alu_op_b(dc))); - if (link && !dslot) { - if (!(dc->tb_flags & IMM_FLAG) && (dc->imm == 8 || dc->imm == 0x18)) - t_gen_raise_exception(dc, EXCP_BREAK); - if (dc->imm == 0) { - if ((dc->tb_flags & MSR_EE_FLAG) && mem_index == MMU_USER_IDX) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } - - t_gen_raise_exception(dc, EXCP_DEBUG); - } - } - } else { - if (dec_alu_op_b_is_small_imm(dc)) { - dc->jmp = JMP_DIRECT; - dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm); - } else { - tcg_gen_movi_tl(env_btaken, 1); - tcg_gen_movi_tl(env_btarget, dc->pc); - tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc))); - } - } -} - -static inline void do_rti(DisasContext *dc) -{ - TCGv t0, t1; - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - tcg_gen_shri_tl(t0, cpu_SR[SR_MSR], 1); - tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_IE); - tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM)); - - tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM)); - tcg_gen_or_tl(t1, t1, t0); - msr_write(dc, t1); - tcg_temp_free(t1); - tcg_temp_free(t0); - dc->tb_flags &= ~DRTI_FLAG; -} - -static inline void do_rtb(DisasContext *dc) -{ - TCGv t0, t1; - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - tcg_gen_andi_tl(t1, cpu_SR[SR_MSR], ~MSR_BIP); - tcg_gen_shri_tl(t0, t1, 1); - tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM)); - - tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM)); - tcg_gen_or_tl(t1, t1, t0); - msr_write(dc, t1); - tcg_temp_free(t1); - tcg_temp_free(t0); - dc->tb_flags &= ~DRTB_FLAG; -} - -static inline void do_rte(DisasContext *dc) -{ - TCGv t0, t1; - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - - tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_EE); - tcg_gen_andi_tl(t1, t1, ~MSR_EIP); - tcg_gen_shri_tl(t0, t1, 1); - tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM)); - - tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM)); - tcg_gen_or_tl(t1, t1, t0); - msr_write(dc, t1); - tcg_temp_free(t1); - tcg_temp_free(t0); - dc->tb_flags &= ~DRTE_FLAG; -} - -static void dec_rts(DisasContext *dc) -{ - unsigned int b_bit, i_bit, e_bit; - int mem_index = cpu_mmu_index(&dc->cpu->env, false); - - i_bit = dc->ir & (1 << 21); - b_bit = dc->ir & (1 << 22); - e_bit = dc->ir & (1 << 23); - - dc->delayed_branch = 2; - dc->tb_flags |= D_FLAG; - tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)), - cpu_env, offsetof(CPUMBState, bimm)); - - if (i_bit) { - LOG_DIS("rtid ir=%x\n", dc->ir); - if ((dc->tb_flags & MSR_EE_FLAG) - && mem_index == MMU_USER_IDX) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - } - dc->tb_flags |= DRTI_FLAG; - } else if (b_bit) { - LOG_DIS("rtbd ir=%x\n", dc->ir); - if ((dc->tb_flags & MSR_EE_FLAG) - && mem_index == MMU_USER_IDX) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - } - dc->tb_flags |= DRTB_FLAG; - } else if (e_bit) { - LOG_DIS("rted ir=%x\n", dc->ir); - if ((dc->tb_flags & MSR_EE_FLAG) - && mem_index == MMU_USER_IDX) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - } - dc->tb_flags |= DRTE_FLAG; - } else - LOG_DIS("rts ir=%x\n", dc->ir); - - dc->jmp = JMP_INDIRECT; - tcg_gen_movi_tl(env_btaken, 1); - tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc))); -} - -static int dec_check_fpuv2(DisasContext *dc) -{ - if ((dc->cpu->cfg.use_fpu != 2) && (dc->tb_flags & MSR_EE_FLAG)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_FPU); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - } - return (dc->cpu->cfg.use_fpu == 2) ? 0 : PVR2_USE_FPU2_MASK; -} - -static void dec_fpu(DisasContext *dc) -{ - unsigned int fpu_insn; - - if ((dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && (dc->cpu->cfg.use_fpu != 1)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } - - fpu_insn = (dc->ir >> 7) & 7; - - switch (fpu_insn) { - case 0: - gen_helper_fadd(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], - cpu_R[dc->rb]); - break; - - case 1: - gen_helper_frsub(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], - cpu_R[dc->rb]); - break; - - case 2: - gen_helper_fmul(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], - cpu_R[dc->rb]); - break; - - case 3: - gen_helper_fdiv(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], - cpu_R[dc->rb]); - break; - - case 4: - switch ((dc->ir >> 4) & 7) { - case 0: - gen_helper_fcmp_un(cpu_R[dc->rd], cpu_env, - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 1: - gen_helper_fcmp_lt(cpu_R[dc->rd], cpu_env, - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 2: - gen_helper_fcmp_eq(cpu_R[dc->rd], cpu_env, - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 3: - gen_helper_fcmp_le(cpu_R[dc->rd], cpu_env, - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 4: - gen_helper_fcmp_gt(cpu_R[dc->rd], cpu_env, - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 5: - gen_helper_fcmp_ne(cpu_R[dc->rd], cpu_env, - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 6: - gen_helper_fcmp_ge(cpu_R[dc->rd], cpu_env, - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - default: - qemu_log_mask(LOG_UNIMP, - "unimplemented fcmp fpu_insn=%x pc=%x" - " opc=%x\n", - fpu_insn, dc->pc, dc->opcode); - dc->abort_at_next_insn = 1; - break; - } - break; - - case 5: - if (!dec_check_fpuv2(dc)) { - return; - } - gen_helper_flt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]); - break; - - case 6: - if (!dec_check_fpuv2(dc)) { - return; - } - gen_helper_fint(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]); - break; - - case 7: - if (!dec_check_fpuv2(dc)) { - return; - } - gen_helper_fsqrt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]); - break; - - default: - qemu_log_mask(LOG_UNIMP, "unimplemented FPU insn fpu_insn=%x pc=%x" - " opc=%x\n", - fpu_insn, dc->pc, dc->opcode); - dc->abort_at_next_insn = 1; - break; - } -} - -static void dec_null(DisasContext *dc) -{ - if ((dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } - qemu_log_mask(LOG_GUEST_ERROR, "unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode); - dc->abort_at_next_insn = 1; -} - -/* Insns connected to FSL or AXI stream attached devices. */ -static void dec_stream(DisasContext *dc) -{ - int mem_index = cpu_mmu_index(&dc->cpu->env, false); - TCGv_i32 t_id, t_ctrl; - int ctrl; - - LOG_DIS("%s%s imm=%x\n", dc->rd ? "get" : "put", - dc->type_b ? "" : "d", dc->imm); - - if ((dc->tb_flags & MSR_EE_FLAG) && (mem_index == MMU_USER_IDX)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } - - t_id = tcg_temp_new(); - if (dc->type_b) { - tcg_gen_movi_tl(t_id, dc->imm & 0xf); - ctrl = dc->imm >> 10; - } else { - tcg_gen_andi_tl(t_id, cpu_R[dc->rb], 0xf); - ctrl = dc->imm >> 5; - } - - t_ctrl = tcg_const_tl(ctrl); - - if (dc->rd == 0) { - gen_helper_put(t_id, t_ctrl, cpu_R[dc->ra]); - } else { - gen_helper_get(cpu_R[dc->rd], t_id, t_ctrl); - } - tcg_temp_free(t_id); - tcg_temp_free(t_ctrl); -} - -static struct decoder_info { - struct { - uint32_t bits; - uint32_t mask; - }; - void (*dec)(DisasContext *dc); -} decinfo[] = { - {DEC_ADD, dec_add}, - {DEC_SUB, dec_sub}, - {DEC_AND, dec_and}, - {DEC_XOR, dec_xor}, - {DEC_OR, dec_or}, - {DEC_BIT, dec_bit}, - {DEC_BARREL, dec_barrel}, - {DEC_LD, dec_load}, - {DEC_ST, dec_store}, - {DEC_IMM, dec_imm}, - {DEC_BR, dec_br}, - {DEC_BCC, dec_bcc}, - {DEC_RTS, dec_rts}, - {DEC_FPU, dec_fpu}, - {DEC_MUL, dec_mul}, - {DEC_DIV, dec_div}, - {DEC_MSR, dec_msr}, - {DEC_STREAM, dec_stream}, - {{0, 0}, dec_null} -}; - -static inline void decode(DisasContext *dc, uint32_t ir) -{ - int i; - - dc->ir = ir; - LOG_DIS("%8.8x\t", dc->ir); - - if (dc->ir) - dc->nr_nops = 0; - else { - if ((dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && (dc->cpu->env.pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } - - LOG_DIS("nr_nops=%d\t", dc->nr_nops); - dc->nr_nops++; - if (dc->nr_nops > 4) { - cpu_abort(CPU(dc->cpu), "fetching nop sequence\n"); - } - } - /* bit 2 seems to indicate insn type. */ - dc->type_b = ir & (1 << 29); - - dc->opcode = EXTRACT_FIELD(ir, 26, 31); - dc->rd = EXTRACT_FIELD(ir, 21, 25); - dc->ra = EXTRACT_FIELD(ir, 16, 20); - dc->rb = EXTRACT_FIELD(ir, 11, 15); - dc->imm = EXTRACT_FIELD(ir, 0, 15); - - /* Large switch for all insns. */ - for (i = 0; i < ARRAY_SIZE(decinfo); i++) { - if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) { - decinfo[i].dec(dc); - break; - } - } -} - -/* generate intermediate code for basic block 'tb'. */ -void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb) -{ - MicroBlazeCPU *cpu = mb_env_get_cpu(env); - CPUState *cs = CPU(cpu); - uint32_t pc_start; - struct DisasContext ctx; - struct DisasContext *dc = &ctx; - uint32_t next_page_start, org_flags; - target_ulong npc; - int num_insns; - int max_insns; - - pc_start = tb->pc; - dc->cpu = cpu; - dc->tb = tb; - org_flags = dc->synced_flags = dc->tb_flags = tb->flags; - - dc->is_jmp = DISAS_NEXT; - dc->jmp = 0; - dc->delayed_branch = !!(dc->tb_flags & D_FLAG); - if (dc->delayed_branch) { - dc->jmp = JMP_INDIRECT; - } - dc->pc = pc_start; - dc->singlestep_enabled = cs->singlestep_enabled; - dc->cpustate_changed = 0; - dc->abort_at_next_insn = 0; - dc->nr_nops = 0; - - if (pc_start & 3) { - cpu_abort(cs, "Microblaze: unaligned PC=%x\n", pc_start); - } - - 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 SIM_COMPAT - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { - tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); - gen_helper_debug(); - } -#endif - - if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { - t_gen_raise_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; - } - - /* Pretty disas. */ - LOG_DIS("%8.8x:\t", dc->pc); - - if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { - gen_io_start(); - } - - dc->clear_imm = 1; - decode(dc, cpu_ldl_code(env, dc->pc)); - if (dc->clear_imm) - dc->tb_flags &= ~IMM_FLAG; - dc->pc += 4; - - if (dc->delayed_branch) { - dc->delayed_branch--; - if (!dc->delayed_branch) { - if (dc->tb_flags & DRTI_FLAG) - do_rti(dc); - if (dc->tb_flags & DRTB_FLAG) - do_rtb(dc); - if (dc->tb_flags & DRTE_FLAG) - do_rte(dc); - /* Clear the delay slot flag. */ - dc->tb_flags &= ~D_FLAG; - /* If it is a direct jump, try direct chaining. */ - if (dc->jmp == JMP_INDIRECT) { - eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc)); - dc->is_jmp = DISAS_JUMP; - } else if (dc->jmp == JMP_DIRECT) { - t_sync_flags(dc); - gen_goto_tb(dc, 0, dc->jmp_pc); - dc->is_jmp = DISAS_TB_JUMP; - } else if (dc->jmp == JMP_DIRECT_CC) { - TCGLabel *l1 = gen_new_label(); - t_sync_flags(dc); - /* Conditional jmp. */ - tcg_gen_brcondi_tl(TCG_COND_NE, env_btaken, 0, l1); - gen_goto_tb(dc, 1, dc->pc); - gen_set_label(l1); - gen_goto_tb(dc, 0, dc->jmp_pc); - - dc->is_jmp = DISAS_TB_JUMP; - } - break; - } - } - if (cs->singlestep_enabled) { - break; - } - } while (!dc->is_jmp && !dc->cpustate_changed - && !tcg_op_buf_full() - && !singlestep - && (dc->pc < next_page_start) - && num_insns < max_insns); - - npc = dc->pc; - if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) { - if (dc->tb_flags & D_FLAG) { - dc->is_jmp = DISAS_UPDATE; - tcg_gen_movi_tl(cpu_SR[SR_PC], npc); - sync_jmpstate(dc); - } else - npc = dc->jmp_pc; - } - - if (tb->cflags & CF_LAST_IO) - gen_io_end(); - /* Force an update if the per-tb cpu state has changed. */ - if (dc->is_jmp == DISAS_NEXT - && (dc->cpustate_changed || org_flags != dc->tb_flags)) { - dc->is_jmp = DISAS_UPDATE; - tcg_gen_movi_tl(cpu_SR[SR_PC], npc); - } - t_sync_flags(dc); - - if (unlikely(cs->singlestep_enabled)) { - TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG); - - if (dc->is_jmp != DISAS_JUMP) { - tcg_gen_movi_tl(cpu_SR[SR_PC], npc); - } - gen_helper_raise_exception(cpu_env, tmp); - tcg_temp_free_i32(tmp); - } else { - switch(dc->is_jmp) { - case DISAS_NEXT: - gen_goto_tb(dc, 1, npc); - break; - default: - case DISAS_JUMP: - 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 !SIM_COMPAT - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) - && qemu_log_in_addr_range(pc_start)) { - qemu_log_lock(); - qemu_log("--------------\n"); -#if DISAS_GNU - log_target_disas(cs, pc_start, dc->pc - pc_start, 0); -#endif - qemu_log("\nisize=%d osize=%d\n", - dc->pc - pc_start, tcg_op_buf_count()); - qemu_log_unlock(); - } -#endif -#endif - assert(!dc->abort_at_next_insn); -} - -void mb_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, - int flags) -{ - MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); - CPUMBState *env = &cpu->env; - int i; - - if (!env || !f) - return; - - cpu_fprintf(f, "IN: PC=%x %s\n", - env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC])); - cpu_fprintf(f, "rmsr=%x resr=%x rear=%x debug=%x imm=%x iflags=%x fsr=%x\n", - env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR], - env->debug, env->imm, env->iflags, env->sregs[SR_FSR]); - cpu_fprintf(f, "btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n", - env->btaken, env->btarget, - (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel", - (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel", - (env->sregs[SR_MSR] & MSR_EIP), - (env->sregs[SR_MSR] & MSR_IE)); - - for (i = 0; i < 32; i++) { - cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]); - if ((i + 1) % 4 == 0) - cpu_fprintf(f, "\n"); - } - cpu_fprintf(f, "\n\n"); -} - -MicroBlazeCPU *cpu_mb_init(const char *cpu_model) -{ - MicroBlazeCPU *cpu; - - cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU)); - - object_property_set_bool(OBJECT(cpu), true, "realized", NULL); - - return cpu; -} - -void mb_tcg_init(void) -{ - int i; - - cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); - tcg_ctx.tcg_env = cpu_env; - - env_debug = tcg_global_mem_new(cpu_env, - offsetof(CPUMBState, debug), - "debug0"); - env_iflags = tcg_global_mem_new(cpu_env, - offsetof(CPUMBState, iflags), - "iflags"); - env_imm = tcg_global_mem_new(cpu_env, - offsetof(CPUMBState, imm), - "imm"); - env_btarget = tcg_global_mem_new(cpu_env, - offsetof(CPUMBState, btarget), - "btarget"); - env_btaken = tcg_global_mem_new(cpu_env, - offsetof(CPUMBState, btaken), - "btaken"); - env_res_addr = tcg_global_mem_new(cpu_env, - offsetof(CPUMBState, res_addr), - "res_addr"); - env_res_val = tcg_global_mem_new(cpu_env, - offsetof(CPUMBState, res_val), - "res_val"); - for (i = 0; i < ARRAY_SIZE(cpu_R); i++) { - cpu_R[i] = tcg_global_mem_new(cpu_env, - offsetof(CPUMBState, regs[i]), - regnames[i]); - } - for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) { - cpu_SR[i] = tcg_global_mem_new(cpu_env, - offsetof(CPUMBState, sregs[i]), - special_regnames[i]); - } -} - -void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, - target_ulong *data) -{ - env->sregs[SR_PC] = data[0]; -} |