mirror of
https://github.com/qemu/qemu.git
synced 2024-11-25 11:53:39 +08:00
Drop the deprecated unicore32 target
Target unicore32 was deprecated in commit 8e4ff4a8d2
, v5.2.0. See
there for rationale.
Cc: Guan Xuetao <gxt@mprc.pku.edu.cn>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20210503084034.3804963-3-armbru@redhat.com>
Acked-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
parent
9d49bcf699
commit
4369223902
@ -624,7 +624,7 @@ build-deprecated:
|
||||
IMAGE: debian-all-test-cross
|
||||
CONFIGURE_ARGS: --disable-tools
|
||||
MAKE_CHECK_ARGS: build-tcg
|
||||
TARGETS: ppc64abi32-linux-user unicore32-softmmu
|
||||
TARGETS: ppc64abi32-linux-user
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
|
15
MAINTAINERS
15
MAINTAINERS
@ -318,13 +318,6 @@ F: hw/sparc64/
|
||||
F: include/hw/sparc/sparc64.h
|
||||
F: disas/sparc.c
|
||||
|
||||
UniCore32 TCG CPUs
|
||||
M: Guan Xuetao <gxt@mprc.pku.edu.cn>
|
||||
S: Maintained
|
||||
F: target/unicore32/
|
||||
F: hw/unicore32/
|
||||
F: include/hw/unicore32/
|
||||
|
||||
X86 TCG CPUs
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
M: Richard Henderson <richard.henderson@linaro.org>
|
||||
@ -1508,14 +1501,6 @@ F: hw/s390x/s390-pci*
|
||||
F: include/hw/s390x/s390-pci*
|
||||
L: qemu-s390x@nongnu.org
|
||||
|
||||
UniCore32 Machines
|
||||
------------------
|
||||
PKUnity-3 SoC initramfs-with-busybox
|
||||
M: Guan Xuetao <gxt@mprc.pku.edu.cn>
|
||||
S: Maintained
|
||||
F: hw/*/puv3*
|
||||
F: hw/unicore32/
|
||||
|
||||
X86 Machines
|
||||
------------
|
||||
PC
|
||||
|
2
configure
vendored
2
configure
vendored
@ -1663,7 +1663,7 @@ if [ "$ARCH" = "unknown" ]; then
|
||||
fi
|
||||
|
||||
default_target_list=""
|
||||
deprecated_targets_list=ppc64abi32-linux-user,unicore32-softmmu
|
||||
deprecated_targets_list=ppc64abi32-linux-user
|
||||
deprecated_features=""
|
||||
mak_wilds=""
|
||||
|
||||
|
@ -1,6 +0,0 @@
|
||||
# Default configuration for unicore32-softmmu
|
||||
|
||||
# Boards:
|
||||
#
|
||||
CONFIG_PUV3=y
|
||||
CONFIG_SEMIHOSTING=y
|
@ -1 +0,0 @@
|
||||
TARGET_ARCH=unicore32
|
@ -198,14 +198,6 @@ from Linux upstream kernel, declare it deprecated.
|
||||
System emulator CPUS
|
||||
--------------------
|
||||
|
||||
``unicore32`` CPUs (since 5.2.0)
|
||||
''''''''''''''''''''''''''''''''
|
||||
|
||||
The ``unicore32`` guest CPU support is deprecated and will be removed in
|
||||
a future version of QEMU. Support for this CPU was removed from the
|
||||
upstream Linux kernel, and there is no available upstream toolchain
|
||||
to build binaries for it.
|
||||
|
||||
``Icelake-Client`` CPU Model (since 5.2.0)
|
||||
''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
|
@ -305,6 +305,13 @@ The only public user of this architecture was the milkymist project,
|
||||
which has been dead for years; there was never an upstream Linux
|
||||
port. Removed without replacement.
|
||||
|
||||
``unicore32`` CPUs (since 6.1.0)
|
||||
''''''''''''''''''''''''''''''''
|
||||
|
||||
Support for this CPU was removed from the upstream Linux kernel, and
|
||||
there is no available upstream toolchain to build binaries for it.
|
||||
Removed without replacement.
|
||||
|
||||
System emulator machines
|
||||
------------------------
|
||||
|
||||
|
@ -103,7 +103,7 @@ static inline bool snan_bit_is_one(float_status *status)
|
||||
{
|
||||
#if defined(TARGET_MIPS)
|
||||
return status->snan_bit_is_one;
|
||||
#elif defined(TARGET_HPPA) || defined(TARGET_UNICORE32) || defined(TARGET_SH4)
|
||||
#elif defined(TARGET_HPPA) || defined(TARGET_SH4)
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
@ -149,11 +149,10 @@ static FloatParts parts_default_nan(float_status *status)
|
||||
sign = 1;
|
||||
frac = ~0ULL;
|
||||
#else
|
||||
/* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
|
||||
* S390, SH4, TriCore, and Xtensa. I cannot find documentation
|
||||
* for Unicore32; the choice from the original commit is unchanged.
|
||||
* Our other supported targets, CRIS, Nios2, and Tile,
|
||||
* do not have floating-point.
|
||||
/*
|
||||
* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
|
||||
* S390, SH4, TriCore, and Xtensa. Our other supported targets,
|
||||
* CRIS, Nios2, and Tile, do not have floating-point.
|
||||
*/
|
||||
if (snan_bit_is_one(status)) {
|
||||
/* set all bits other than msb */
|
||||
|
@ -60,7 +60,6 @@ source sh4/Kconfig
|
||||
source sparc/Kconfig
|
||||
source sparc64/Kconfig
|
||||
source tricore/Kconfig
|
||||
source unicore32/Kconfig
|
||||
source xtensa/Kconfig
|
||||
|
||||
# Symbols used by multiple targets
|
||||
|
@ -1,4 +1,3 @@
|
||||
softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_dma.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_RC4030', if_true: files('rc4030.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_PL080', if_true: files('pl080.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_PL330', if_true: files('pl330.c'))
|
||||
|
@ -1,119 +0,0 @@
|
||||
/*
|
||||
* DMA device simulation in PKUnity SoC
|
||||
*
|
||||
* Copyright (C) 2010-2012 Guan Xuetao
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or any later version.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#undef DEBUG_PUV3
|
||||
#include "hw/unicore32/puv3.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
#define PUV3_DMA_CH_NR (6)
|
||||
#define PUV3_DMA_CH_MASK (0xff)
|
||||
#define PUV3_DMA_CH(offset) ((offset) >> 8)
|
||||
|
||||
#define TYPE_PUV3_DMA "puv3_dma"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(PUV3DMAState, PUV3_DMA)
|
||||
|
||||
struct PUV3DMAState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion iomem;
|
||||
uint32_t reg_CFG[PUV3_DMA_CH_NR];
|
||||
};
|
||||
|
||||
static uint64_t puv3_dma_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
PUV3DMAState *s = opaque;
|
||||
uint32_t ret = 0;
|
||||
|
||||
assert(PUV3_DMA_CH(offset) < PUV3_DMA_CH_NR);
|
||||
|
||||
switch (offset & PUV3_DMA_CH_MASK) {
|
||||
case 0x10:
|
||||
ret = s->reg_CFG[PUV3_DMA_CH(offset)];
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad read offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
}
|
||||
DPRINTF("offset 0x%x, value 0x%x\n", offset, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void puv3_dma_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
PUV3DMAState *s = opaque;
|
||||
|
||||
assert(PUV3_DMA_CH(offset) < PUV3_DMA_CH_NR);
|
||||
|
||||
switch (offset & PUV3_DMA_CH_MASK) {
|
||||
case 0x10:
|
||||
s->reg_CFG[PUV3_DMA_CH(offset)] = value;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad write offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
}
|
||||
DPRINTF("offset 0x%x, value 0x%x\n", offset, value);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps puv3_dma_ops = {
|
||||
.read = puv3_dma_read,
|
||||
.write = puv3_dma_write,
|
||||
.impl = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void puv3_dma_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PUV3DMAState *s = PUV3_DMA(dev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PUV3_DMA_CH_NR; i++) {
|
||||
s->reg_CFG[i] = 0x0;
|
||||
}
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_dma_ops, s, "puv3_dma",
|
||||
PUV3_REGS_OFFSET);
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
|
||||
}
|
||||
|
||||
static void puv3_dma_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = puv3_dma_realize;
|
||||
}
|
||||
|
||||
static const TypeInfo puv3_dma_info = {
|
||||
.name = TYPE_PUV3_DMA,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(PUV3DMAState),
|
||||
.class_init = puv3_dma_class_init,
|
||||
};
|
||||
|
||||
static void puv3_dma_register_type(void)
|
||||
{
|
||||
type_register_static(&puv3_dma_info);
|
||||
}
|
||||
|
||||
type_init(puv3_dma_register_type)
|
@ -3,7 +3,6 @@ softmmu_ss.add(when: 'CONFIG_GPIO_KEY', if_true: files('gpio_key.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_GPIO_PWR', if_true: files('gpio_pwr.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_MAX7310', if_true: files('max7310.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_PL061', if_true: files('pl061.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_gpio.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_ZAURUS', if_true: files('zaurus.c'))
|
||||
|
||||
softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_gpio.c'))
|
||||
|
@ -1,154 +0,0 @@
|
||||
/*
|
||||
* GPIO device simulation in PKUnity SoC
|
||||
*
|
||||
* Copyright (C) 2010-2012 Guan Xuetao
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or any later version.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#undef DEBUG_PUV3
|
||||
#include "hw/unicore32/puv3.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
#define TYPE_PUV3_GPIO "puv3_gpio"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(PUV3GPIOState, PUV3_GPIO)
|
||||
|
||||
struct PUV3GPIOState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion iomem;
|
||||
qemu_irq irq[9];
|
||||
|
||||
uint32_t reg_GPLR;
|
||||
uint32_t reg_GPDR;
|
||||
uint32_t reg_GPIR;
|
||||
};
|
||||
|
||||
static uint64_t puv3_gpio_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
PUV3GPIOState *s = opaque;
|
||||
uint32_t ret = 0;
|
||||
|
||||
switch (offset) {
|
||||
case 0x00:
|
||||
ret = s->reg_GPLR;
|
||||
break;
|
||||
case 0x04:
|
||||
ret = s->reg_GPDR;
|
||||
break;
|
||||
case 0x20:
|
||||
ret = s->reg_GPIR;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad read offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
}
|
||||
DPRINTF("offset 0x%x, value 0x%x\n", offset, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void puv3_gpio_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
PUV3GPIOState *s = opaque;
|
||||
|
||||
DPRINTF("offset 0x%x, value 0x%x\n", offset, value);
|
||||
switch (offset) {
|
||||
case 0x04:
|
||||
s->reg_GPDR = value;
|
||||
break;
|
||||
case 0x08:
|
||||
if (s->reg_GPDR & value) {
|
||||
s->reg_GPLR |= value;
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Write gpio input port\n",
|
||||
__func__);
|
||||
}
|
||||
break;
|
||||
case 0x0c:
|
||||
if (s->reg_GPDR & value) {
|
||||
s->reg_GPLR &= ~value;
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Write gpio input port\n",
|
||||
__func__);
|
||||
}
|
||||
break;
|
||||
case 0x10: /* GRER */
|
||||
case 0x14: /* GFER */
|
||||
case 0x18: /* GEDR */
|
||||
break;
|
||||
case 0x20: /* GPIR */
|
||||
s->reg_GPIR = value;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad write offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps puv3_gpio_ops = {
|
||||
.read = puv3_gpio_read,
|
||||
.write = puv3_gpio_write,
|
||||
.impl = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void puv3_gpio_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PUV3GPIOState *s = PUV3_GPIO(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
|
||||
s->reg_GPLR = 0;
|
||||
s->reg_GPDR = 0;
|
||||
|
||||
/* FIXME: these irqs not handled yet */
|
||||
sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW0]);
|
||||
sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW1]);
|
||||
sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW2]);
|
||||
sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW3]);
|
||||
sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW4]);
|
||||
sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW5]);
|
||||
sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW6]);
|
||||
sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW7]);
|
||||
sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOHIGH]);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_gpio_ops, s, "puv3_gpio",
|
||||
PUV3_REGS_OFFSET);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
|
||||
static void puv3_gpio_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = puv3_gpio_realize;
|
||||
}
|
||||
|
||||
static const TypeInfo puv3_gpio_info = {
|
||||
.name = TYPE_PUV3_GPIO,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(PUV3GPIOState),
|
||||
.class_init = puv3_gpio_class_init,
|
||||
};
|
||||
|
||||
static void puv3_gpio_register_type(void)
|
||||
{
|
||||
type_register_static(&puv3_gpio_info);
|
||||
}
|
||||
|
||||
type_init(puv3_gpio_register_type)
|
@ -16,7 +16,6 @@ softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_avic.c', 'imx_gpcv2.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic_common.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_OPENPIC', if_true: files('openpic.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_PL190', if_true: files('pl190.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_intc.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_REALVIEW', if_true: files('realview_gic.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_intctl.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_intc.c'))
|
||||
|
@ -1,147 +0,0 @@
|
||||
/*
|
||||
* INTC device simulation in PKUnity SoC
|
||||
*
|
||||
* Copyright (C) 2010-2012 Guan Xuetao
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or any later version.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#undef DEBUG_PUV3
|
||||
#include "hw/unicore32/puv3.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
#define TYPE_PUV3_INTC "puv3_intc"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(PUV3INTCState, PUV3_INTC)
|
||||
|
||||
struct PUV3INTCState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion iomem;
|
||||
qemu_irq parent_irq;
|
||||
|
||||
uint32_t reg_ICMR;
|
||||
uint32_t reg_ICPR;
|
||||
};
|
||||
|
||||
/* Update interrupt status after enabled or pending bits have been changed. */
|
||||
static void puv3_intc_update(PUV3INTCState *s)
|
||||
{
|
||||
if (s->reg_ICMR & s->reg_ICPR) {
|
||||
qemu_irq_raise(s->parent_irq);
|
||||
} else {
|
||||
qemu_irq_lower(s->parent_irq);
|
||||
}
|
||||
}
|
||||
|
||||
/* Process a change in an external INTC input. */
|
||||
static void puv3_intc_handler(void *opaque, int irq, int level)
|
||||
{
|
||||
PUV3INTCState *s = opaque;
|
||||
|
||||
DPRINTF("irq 0x%x, level 0x%x\n", irq, level);
|
||||
if (level) {
|
||||
s->reg_ICPR |= (1 << irq);
|
||||
} else {
|
||||
s->reg_ICPR &= ~(1 << irq);
|
||||
}
|
||||
puv3_intc_update(s);
|
||||
}
|
||||
|
||||
static uint64_t puv3_intc_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
PUV3INTCState *s = opaque;
|
||||
uint32_t ret = 0;
|
||||
|
||||
switch (offset) {
|
||||
case 0x04: /* INTC_ICMR */
|
||||
ret = s->reg_ICMR;
|
||||
break;
|
||||
case 0x0c: /* INTC_ICIP */
|
||||
ret = s->reg_ICPR; /* the same value with ICPR */
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad read offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
}
|
||||
DPRINTF("offset 0x%x, value 0x%x\n", offset, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void puv3_intc_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
PUV3INTCState *s = opaque;
|
||||
|
||||
DPRINTF("offset 0x%x, value 0x%x\n", offset, value);
|
||||
switch (offset) {
|
||||
case 0x00: /* INTC_ICLR */
|
||||
case 0x14: /* INTC_ICCR */
|
||||
break;
|
||||
case 0x04: /* INTC_ICMR */
|
||||
s->reg_ICMR = value;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad write offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
return;
|
||||
}
|
||||
puv3_intc_update(s);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps puv3_intc_ops = {
|
||||
.read = puv3_intc_read,
|
||||
.write = puv3_intc_write,
|
||||
.impl = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void puv3_intc_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PUV3INTCState *s = PUV3_INTC(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
|
||||
qdev_init_gpio_in(dev, puv3_intc_handler, PUV3_IRQS_NR);
|
||||
sysbus_init_irq(sbd, &s->parent_irq);
|
||||
|
||||
s->reg_ICMR = 0;
|
||||
s->reg_ICPR = 0;
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_intc_ops, s, "puv3_intc",
|
||||
PUV3_REGS_OFFSET);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
|
||||
static void puv3_intc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
dc->realize = puv3_intc_realize;
|
||||
}
|
||||
|
||||
static const TypeInfo puv3_intc_info = {
|
||||
.name = TYPE_PUV3_INTC,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(PUV3INTCState),
|
||||
.class_init = puv3_intc_class_init,
|
||||
};
|
||||
|
||||
static void puv3_intc_register_type(void)
|
||||
{
|
||||
type_register_static(&puv3_intc_info);
|
||||
}
|
||||
|
||||
type_init(puv3_intc_register_type)
|
@ -61,5 +61,4 @@ subdir('sh4')
|
||||
subdir('sparc')
|
||||
subdir('sparc64')
|
||||
subdir('tricore')
|
||||
subdir('unicore32')
|
||||
subdir('xtensa')
|
||||
|
@ -36,9 +36,6 @@ softmmu_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: files('sifive_e_prci.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_prci.c'))
|
||||
|
||||
# PKUnity SoC devices
|
||||
softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_pm.c'))
|
||||
|
||||
subdir('macio')
|
||||
|
||||
softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
|
||||
|
@ -1,159 +0,0 @@
|
||||
/*
|
||||
* Power Management device simulation in PKUnity SoC
|
||||
*
|
||||
* Copyright (C) 2010-2012 Guan Xuetao
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or any later version.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#undef DEBUG_PUV3
|
||||
#include "hw/unicore32/puv3.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
#define TYPE_PUV3_PM "puv3_pm"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(PUV3PMState, PUV3_PM)
|
||||
|
||||
struct PUV3PMState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion iomem;
|
||||
|
||||
uint32_t reg_PMCR;
|
||||
uint32_t reg_PCGR;
|
||||
uint32_t reg_PLL_SYS_CFG;
|
||||
uint32_t reg_PLL_DDR_CFG;
|
||||
uint32_t reg_PLL_VGA_CFG;
|
||||
uint32_t reg_DIVCFG;
|
||||
};
|
||||
|
||||
static uint64_t puv3_pm_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
PUV3PMState *s = opaque;
|
||||
uint32_t ret = 0;
|
||||
|
||||
switch (offset) {
|
||||
case 0x14:
|
||||
ret = s->reg_PCGR;
|
||||
break;
|
||||
case 0x18:
|
||||
ret = s->reg_PLL_SYS_CFG;
|
||||
break;
|
||||
case 0x1c:
|
||||
ret = s->reg_PLL_DDR_CFG;
|
||||
break;
|
||||
case 0x20:
|
||||
ret = s->reg_PLL_VGA_CFG;
|
||||
break;
|
||||
case 0x24:
|
||||
ret = s->reg_DIVCFG;
|
||||
break;
|
||||
case 0x28: /* PLL SYS STATUS */
|
||||
ret = 0x00002401;
|
||||
break;
|
||||
case 0x2c: /* PLL DDR STATUS */
|
||||
ret = 0x00100c00;
|
||||
break;
|
||||
case 0x30: /* PLL VGA STATUS */
|
||||
ret = 0x00003801;
|
||||
break;
|
||||
case 0x34: /* DIV STATUS */
|
||||
ret = 0x22f52015;
|
||||
break;
|
||||
case 0x38: /* SW RESET */
|
||||
ret = 0x0;
|
||||
break;
|
||||
case 0x44: /* PLL DFC DONE */
|
||||
ret = 0x7;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad read offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
}
|
||||
DPRINTF("offset 0x%x, value 0x%x\n", offset, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void puv3_pm_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
PUV3PMState *s = opaque;
|
||||
|
||||
switch (offset) {
|
||||
case 0x0:
|
||||
s->reg_PMCR = value;
|
||||
break;
|
||||
case 0x14:
|
||||
s->reg_PCGR = value;
|
||||
break;
|
||||
case 0x18:
|
||||
s->reg_PLL_SYS_CFG = value;
|
||||
break;
|
||||
case 0x1c:
|
||||
s->reg_PLL_DDR_CFG = value;
|
||||
break;
|
||||
case 0x20:
|
||||
s->reg_PLL_VGA_CFG = value;
|
||||
break;
|
||||
case 0x24:
|
||||
case 0x38:
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad write offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
}
|
||||
DPRINTF("offset 0x%x, value 0x%x\n", offset, value);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps puv3_pm_ops = {
|
||||
.read = puv3_pm_read,
|
||||
.write = puv3_pm_write,
|
||||
.impl = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void puv3_pm_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PUV3PMState *s = PUV3_PM(dev);
|
||||
|
||||
s->reg_PCGR = 0x0;
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_pm_ops, s, "puv3_pm",
|
||||
PUV3_REGS_OFFSET);
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
|
||||
}
|
||||
|
||||
static void puv3_pm_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = puv3_pm_realize;
|
||||
}
|
||||
|
||||
static const TypeInfo puv3_pm_info = {
|
||||
.name = TYPE_PUV3_PM,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(PUV3PMState),
|
||||
.class_init = puv3_pm_class_init,
|
||||
};
|
||||
|
||||
static void puv3_pm_register_type(void)
|
||||
{
|
||||
type_register_static(&puv3_pm_info);
|
||||
}
|
||||
|
||||
type_init(puv3_pm_register_type)
|
@ -25,7 +25,6 @@ softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_timer.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_timer.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gptimer.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_synctimer.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_ost.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_timer.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_systmr.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_SH_TIMER', if_true: files('sh_timer.c'))
|
||||
|
@ -1,166 +0,0 @@
|
||||
/*
|
||||
* OSTimer device simulation in PKUnity SoC
|
||||
*
|
||||
* Copyright (C) 2010-2012 Guan Xuetao
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or any later version.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/ptimer.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#undef DEBUG_PUV3
|
||||
#include "hw/unicore32/puv3.h"
|
||||
|
||||
#define TYPE_PUV3_OST "puv3_ost"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(PUV3OSTState, PUV3_OST)
|
||||
|
||||
/* puv3 ostimer implementation. */
|
||||
struct PUV3OSTState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion iomem;
|
||||
qemu_irq irq;
|
||||
ptimer_state *ptimer;
|
||||
|
||||
uint32_t reg_OSMR0;
|
||||
uint32_t reg_OSCR;
|
||||
uint32_t reg_OSSR;
|
||||
uint32_t reg_OIER;
|
||||
};
|
||||
|
||||
static uint64_t puv3_ost_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
PUV3OSTState *s = opaque;
|
||||
uint32_t ret = 0;
|
||||
|
||||
switch (offset) {
|
||||
case 0x10: /* Counter Register */
|
||||
ret = s->reg_OSMR0 - (uint32_t)ptimer_get_count(s->ptimer);
|
||||
break;
|
||||
case 0x14: /* Status Register */
|
||||
ret = s->reg_OSSR;
|
||||
break;
|
||||
case 0x1c: /* Interrupt Enable Register */
|
||||
ret = s->reg_OIER;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad read offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
}
|
||||
DPRINTF("offset 0x%x, value 0x%x\n", offset, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void puv3_ost_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
PUV3OSTState *s = opaque;
|
||||
|
||||
DPRINTF("offset 0x%x, value 0x%x\n", offset, value);
|
||||
switch (offset) {
|
||||
case 0x00: /* Match Register 0 */
|
||||
ptimer_transaction_begin(s->ptimer);
|
||||
s->reg_OSMR0 = value;
|
||||
if (s->reg_OSMR0 > s->reg_OSCR) {
|
||||
ptimer_set_count(s->ptimer, s->reg_OSMR0 - s->reg_OSCR);
|
||||
} else {
|
||||
ptimer_set_count(s->ptimer, s->reg_OSMR0 +
|
||||
(0xffffffff - s->reg_OSCR));
|
||||
}
|
||||
ptimer_run(s->ptimer, 2);
|
||||
ptimer_transaction_commit(s->ptimer);
|
||||
break;
|
||||
case 0x14: /* Status Register */
|
||||
assert(value == 0);
|
||||
if (s->reg_OSSR) {
|
||||
s->reg_OSSR = value;
|
||||
qemu_irq_lower(s->irq);
|
||||
}
|
||||
break;
|
||||
case 0x1c: /* Interrupt Enable Register */
|
||||
s->reg_OIER = value;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad write offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps puv3_ost_ops = {
|
||||
.read = puv3_ost_read,
|
||||
.write = puv3_ost_write,
|
||||
.impl = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void puv3_ost_tick(void *opaque)
|
||||
{
|
||||
PUV3OSTState *s = opaque;
|
||||
|
||||
DPRINTF("ost hit when ptimer counter from 0x%x to 0x%x!\n",
|
||||
s->reg_OSCR, s->reg_OSMR0);
|
||||
|
||||
s->reg_OSCR = s->reg_OSMR0;
|
||||
if (s->reg_OIER) {
|
||||
s->reg_OSSR = 1;
|
||||
qemu_irq_raise(s->irq);
|
||||
}
|
||||
}
|
||||
|
||||
static void puv3_ost_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PUV3OSTState *s = PUV3_OST(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
|
||||
s->reg_OIER = 0;
|
||||
s->reg_OSSR = 0;
|
||||
s->reg_OSMR0 = 0;
|
||||
s->reg_OSCR = 0;
|
||||
|
||||
sysbus_init_irq(sbd, &s->irq);
|
||||
|
||||
s->ptimer = ptimer_init(puv3_ost_tick, s, PTIMER_POLICY_DEFAULT);
|
||||
ptimer_transaction_begin(s->ptimer);
|
||||
ptimer_set_freq(s->ptimer, 50 * 1000 * 1000);
|
||||
ptimer_transaction_commit(s->ptimer);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost",
|
||||
PUV3_REGS_OFFSET);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
|
||||
static void puv3_ost_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = puv3_ost_realize;
|
||||
}
|
||||
|
||||
static const TypeInfo puv3_ost_info = {
|
||||
.name = TYPE_PUV3_OST,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(PUV3OSTState),
|
||||
.class_init = puv3_ost_class_init,
|
||||
};
|
||||
|
||||
static void puv3_ost_register_type(void)
|
||||
{
|
||||
type_register_static(&puv3_ost_info);
|
||||
}
|
||||
|
||||
type_init(puv3_ost_register_type)
|
@ -1,5 +0,0 @@
|
||||
config PUV3
|
||||
bool
|
||||
select ISA_BUS
|
||||
select PCKBD
|
||||
select PTIMER
|
@ -1,5 +0,0 @@
|
||||
unicore32_ss = ss.source_set()
|
||||
# PKUnity-v3 SoC and board information
|
||||
unicore32_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3.c'))
|
||||
|
||||
hw_arch += {'unicore32': unicore32_ss}
|
@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Generic PKUnity SoC machine and board descriptor
|
||||
*
|
||||
* Copyright (C) 2010-2012 Guan Xuetao
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or any later version.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "cpu.h"
|
||||
#include "ui/console.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/loader.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/unicore32/puv3.h"
|
||||
#include "hw/input/i8042.h"
|
||||
#include "hw/irq.h"
|
||||
|
||||
#define KERNEL_LOAD_ADDR 0x03000000
|
||||
#define KERNEL_MAX_SIZE 0x00800000 /* Just a guess */
|
||||
|
||||
/* PKUnity System bus (AHB): 0xc0000000 - 0xedffffff (640MB) */
|
||||
#define PUV3_DMA_BASE (0xc0200000) /* AHB-4 */
|
||||
|
||||
/* PKUnity Peripheral bus (APB): 0xee000000 - 0xefffffff (128MB) */
|
||||
#define PUV3_GPIO_BASE (0xee500000) /* APB-5 */
|
||||
#define PUV3_INTC_BASE (0xee600000) /* APB-6 */
|
||||
#define PUV3_OST_BASE (0xee800000) /* APB-8 */
|
||||
#define PUV3_PM_BASE (0xeea00000) /* APB-10 */
|
||||
#define PUV3_PS2_BASE (0xeeb00000) /* APB-11 */
|
||||
|
||||
static void puv3_intc_cpu_handler(void *opaque, int irq, int level)
|
||||
{
|
||||
UniCore32CPU *cpu = opaque;
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
assert(irq == 0);
|
||||
if (level) {
|
||||
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
} else {
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
}
|
||||
}
|
||||
|
||||
static void puv3_soc_init(CPUUniCore32State *env)
|
||||
{
|
||||
qemu_irq cpu_intc, irqs[PUV3_IRQS_NR];
|
||||
DeviceState *dev;
|
||||
MemoryRegion *i8042 = g_new(MemoryRegion, 1);
|
||||
int i;
|
||||
|
||||
/* Initialize interrupt controller */
|
||||
cpu_intc = qemu_allocate_irq(puv3_intc_cpu_handler,
|
||||
env_archcpu(env), 0);
|
||||
dev = sysbus_create_simple("puv3_intc", PUV3_INTC_BASE, cpu_intc);
|
||||
for (i = 0; i < PUV3_IRQS_NR; i++) {
|
||||
irqs[i] = qdev_get_gpio_in(dev, i);
|
||||
}
|
||||
|
||||
/* Initialize minimal necessary devices for kernel booting */
|
||||
sysbus_create_simple("puv3_pm", PUV3_PM_BASE, NULL);
|
||||
sysbus_create_simple("puv3_dma", PUV3_DMA_BASE, NULL);
|
||||
sysbus_create_simple("puv3_ost", PUV3_OST_BASE, irqs[PUV3_IRQS_OST0]);
|
||||
sysbus_create_varargs("puv3_gpio", PUV3_GPIO_BASE,
|
||||
irqs[PUV3_IRQS_GPIOLOW0], irqs[PUV3_IRQS_GPIOLOW1],
|
||||
irqs[PUV3_IRQS_GPIOLOW2], irqs[PUV3_IRQS_GPIOLOW3],
|
||||
irqs[PUV3_IRQS_GPIOLOW4], irqs[PUV3_IRQS_GPIOLOW5],
|
||||
irqs[PUV3_IRQS_GPIOLOW6], irqs[PUV3_IRQS_GPIOLOW7],
|
||||
irqs[PUV3_IRQS_GPIOHIGH], NULL);
|
||||
|
||||
/* Keyboard (i8042), mouse disabled for nographic */
|
||||
i8042_mm_init(irqs[PUV3_IRQS_PS2_KBD], NULL, i8042, PUV3_REGS_OFFSET, 4);
|
||||
memory_region_add_subregion(get_system_memory(), PUV3_PS2_BASE, i8042);
|
||||
}
|
||||
|
||||
static void puv3_board_init(CPUUniCore32State *env, ram_addr_t ram_size)
|
||||
{
|
||||
MemoryRegion *ram_memory = g_new(MemoryRegion, 1);
|
||||
|
||||
/* SDRAM at address zero. */
|
||||
memory_region_init_ram(ram_memory, NULL, "puv3.ram", ram_size,
|
||||
&error_fatal);
|
||||
memory_region_add_subregion(get_system_memory(), 0, ram_memory);
|
||||
}
|
||||
|
||||
static const GraphicHwOps no_ops;
|
||||
|
||||
static void puv3_load_kernel(const char *kernel_filename)
|
||||
{
|
||||
int size;
|
||||
|
||||
if (kernel_filename == NULL && qtest_enabled()) {
|
||||
return;
|
||||
}
|
||||
if (kernel_filename == NULL) {
|
||||
error_report("kernel parameter cannot be empty");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* only zImage format supported */
|
||||
size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR,
|
||||
KERNEL_MAX_SIZE);
|
||||
if (size < 0) {
|
||||
error_report("Load kernel error: '%s'", kernel_filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* cheat curses that we have a graphic console, only under ocd console */
|
||||
graphic_console_init(NULL, 0, &no_ops, NULL);
|
||||
}
|
||||
|
||||
static void puv3_init(MachineState *machine)
|
||||
{
|
||||
ram_addr_t ram_size = machine->ram_size;
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
CPUUniCore32State *env;
|
||||
UniCore32CPU *cpu;
|
||||
|
||||
if (initrd_filename) {
|
||||
error_report("Please use kernel built-in initramdisk");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cpu = UNICORE32_CPU(cpu_create(machine->cpu_type));
|
||||
env = &cpu->env;
|
||||
|
||||
puv3_soc_init(env);
|
||||
puv3_board_init(env, ram_size);
|
||||
puv3_load_kernel(kernel_filename);
|
||||
}
|
||||
|
||||
static void puv3_machine_init(MachineClass *mc)
|
||||
{
|
||||
mc->desc = "PKUnity Version-3 based on UniCore32";
|
||||
mc->init = puv3_init;
|
||||
mc->is_default = true;
|
||||
mc->default_cpu_type = UNICORE32_CPU_TYPE_NAME("UniCore-II");
|
||||
}
|
||||
|
||||
DEFINE_MACHINE("puv3", puv3_machine_init)
|
@ -174,9 +174,8 @@ typedef struct mips_elf_abiflags_v0 {
|
||||
|
||||
#define EM_OPENRISC 92 /* OpenCores OpenRISC */
|
||||
|
||||
#define EM_UNICORE32 110 /* UniCore32 */
|
||||
|
||||
#define EM_HEXAGON 164 /* Qualcomm Hexagon */
|
||||
|
||||
#define EM_RX 173 /* Renesas RX family */
|
||||
|
||||
#define EM_RISCV 243 /* RISC-V */
|
||||
|
@ -30,7 +30,6 @@
|
||||
#pragma GCC poison TARGET_SPARC
|
||||
#pragma GCC poison TARGET_SPARC64
|
||||
#pragma GCC poison TARGET_TRICORE
|
||||
#pragma GCC poison TARGET_UNICORE32
|
||||
#pragma GCC poison TARGET_XTENSA
|
||||
|
||||
#pragma GCC poison TARGET_ALIGNED_ONLY
|
||||
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Misc PKUnity SoC declarations
|
||||
*
|
||||
* Copyright (C) 2010-2012 Guan Xuetao
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or any later version.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_HW_PUV3_H
|
||||
#define QEMU_HW_PUV3_H
|
||||
|
||||
#define PUV3_REGS_OFFSET (0x1000) /* 4K is reasonable */
|
||||
|
||||
/* Hardware interrupts */
|
||||
#define PUV3_IRQS_NR (32)
|
||||
|
||||
#define PUV3_IRQS_GPIOLOW0 (0)
|
||||
#define PUV3_IRQS_GPIOLOW1 (1)
|
||||
#define PUV3_IRQS_GPIOLOW2 (2)
|
||||
#define PUV3_IRQS_GPIOLOW3 (3)
|
||||
#define PUV3_IRQS_GPIOLOW4 (4)
|
||||
#define PUV3_IRQS_GPIOLOW5 (5)
|
||||
#define PUV3_IRQS_GPIOLOW6 (6)
|
||||
#define PUV3_IRQS_GPIOLOW7 (7)
|
||||
#define PUV3_IRQS_GPIOHIGH (8)
|
||||
#define PUV3_IRQS_PS2_KBD (22)
|
||||
#define PUV3_IRQS_PS2_AUX (23)
|
||||
#define PUV3_IRQS_OST0 (26)
|
||||
|
||||
/* All puv3_*.c use DPRINTF for debug. */
|
||||
#ifdef DEBUG_PUV3
|
||||
#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__)
|
||||
#else
|
||||
#define DPRINTF(fmt, ...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* QEMU_HW_PUV3_H */
|
@ -17,7 +17,6 @@ enum {
|
||||
QEMU_ARCH_SPARC = (1 << 11),
|
||||
QEMU_ARCH_XTENSA = (1 << 12),
|
||||
QEMU_ARCH_OPENRISC = (1 << 13),
|
||||
QEMU_ARCH_UNICORE32 = (1 << 14),
|
||||
QEMU_ARCH_TRICORE = (1 << 16),
|
||||
QEMU_ARCH_NIOS2 = (1 << 17),
|
||||
QEMU_ARCH_HPPA = (1 << 18),
|
||||
|
@ -33,7 +33,7 @@
|
||||
'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
|
||||
'mips64el', 'mipsel', 'nios2', 'or1k', 'ppc',
|
||||
'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4',
|
||||
'sh4eb', 'sparc', 'sparc64', 'tricore', 'unicore32',
|
||||
'sh4eb', 'sparc', 'sparc64', 'tricore',
|
||||
'x86_64', 'xtensa', 'xtensaeb' ] }
|
||||
|
||||
##
|
||||
|
@ -80,8 +80,6 @@ int graphic_depth = 32;
|
||||
#define QEMU_ARCH QEMU_ARCH_SPARC
|
||||
#elif defined(TARGET_TRICORE)
|
||||
#define QEMU_ARCH QEMU_ARCH_TRICORE
|
||||
#elif defined(TARGET_UNICORE32)
|
||||
#define QEMU_ARCH QEMU_ARCH_UNICORE32
|
||||
#elif defined(TARGET_XTENSA)
|
||||
#define QEMU_ARCH QEMU_ARCH_XTENSA
|
||||
#elif defined(TARGET_AVR)
|
||||
|
@ -17,5 +17,4 @@ subdir('s390x')
|
||||
subdir('sh4')
|
||||
subdir('sparc')
|
||||
subdir('tricore')
|
||||
subdir('unicore32')
|
||||
subdir('xtensa')
|
||||
|
@ -1,17 +0,0 @@
|
||||
/*
|
||||
* UniCore32 cpu parameters for qemu.
|
||||
*
|
||||
* Copyright (C) 2010-2012 Guan Xuetao
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef UNICORE32_CPU_PARAM_H
|
||||
#define UNICORE32_CPU_PARAM_H 1
|
||||
|
||||
#define TARGET_LONG_BITS 32
|
||||
#define TARGET_PAGE_BITS 12
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 32
|
||||
#define TARGET_VIRT_ADDR_SPACE_BITS 32
|
||||
#define NB_MMU_MODES 2
|
||||
|
||||
#endif
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* QEMU UniCore32 CPU
|
||||
*
|
||||
* Copyright (c) 2012 SUSE LINUX Products GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or (at your option) any
|
||||
* later version. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#ifndef QEMU_UC32_CPU_QOM_H
|
||||
#define QEMU_UC32_CPU_QOM_H
|
||||
|
||||
#include "hw/core/cpu.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_UNICORE32_CPU "unicore32-cpu"
|
||||
|
||||
OBJECT_DECLARE_TYPE(UniCore32CPU, UniCore32CPUClass,
|
||||
UNICORE32_CPU)
|
||||
|
||||
/**
|
||||
* UniCore32CPUClass:
|
||||
* @parent_realize: The parent class' realize handler.
|
||||
*
|
||||
* A UniCore32 CPU model.
|
||||
*/
|
||||
struct UniCore32CPUClass {
|
||||
/*< private >*/
|
||||
CPUClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
DeviceRealize parent_realize;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -1,174 +0,0 @@
|
||||
/*
|
||||
* QEMU UniCore32 CPU
|
||||
*
|
||||
* Copyright (c) 2010-2012 Guan Xuetao
|
||||
* Copyright (c) 2012 SUSE LINUX Products GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Contributions from 2012-04-01 on are considered under GPL version 2,
|
||||
* or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "cpu.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
static void uc32_cpu_set_pc(CPUState *cs, vaddr value)
|
||||
{
|
||||
UniCore32CPU *cpu = UNICORE32_CPU(cs);
|
||||
|
||||
cpu->env.regs[31] = value;
|
||||
}
|
||||
|
||||
static bool uc32_cpu_has_work(CPUState *cs)
|
||||
{
|
||||
return cs->interrupt_request &
|
||||
(CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
|
||||
}
|
||||
|
||||
static inline void set_feature(CPUUniCore32State *env, int feature)
|
||||
{
|
||||
env->features |= feature;
|
||||
}
|
||||
|
||||
/* CPU models */
|
||||
|
||||
static ObjectClass *uc32_cpu_class_by_name(const char *cpu_model)
|
||||
{
|
||||
ObjectClass *oc;
|
||||
char *typename;
|
||||
|
||||
typename = g_strdup_printf(UNICORE32_CPU_TYPE_NAME("%s"), cpu_model);
|
||||
oc = object_class_by_name(typename);
|
||||
g_free(typename);
|
||||
if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_UNICORE32_CPU) ||
|
||||
object_class_is_abstract(oc))) {
|
||||
oc = NULL;
|
||||
}
|
||||
return oc;
|
||||
}
|
||||
|
||||
static void unicore_ii_cpu_initfn(Object *obj)
|
||||
{
|
||||
UniCore32CPU *cpu = UNICORE32_CPU(obj);
|
||||
CPUUniCore32State *env = &cpu->env;
|
||||
|
||||
env->cp0.c0_cpuid = 0x4d000863;
|
||||
env->cp0.c0_cachetype = 0x0d152152;
|
||||
env->cp0.c1_sys = 0x2000;
|
||||
env->cp0.c2_base = 0x0;
|
||||
env->cp0.c3_faultstatus = 0x0;
|
||||
env->cp0.c4_faultaddr = 0x0;
|
||||
env->ucf64.xregs[UC32_UCF64_FPSCR] = 0;
|
||||
|
||||
set_feature(env, UC32_HWCAP_CMOV);
|
||||
set_feature(env, UC32_HWCAP_UCF64);
|
||||
}
|
||||
|
||||
static void uc32_any_cpu_initfn(Object *obj)
|
||||
{
|
||||
UniCore32CPU *cpu = UNICORE32_CPU(obj);
|
||||
CPUUniCore32State *env = &cpu->env;
|
||||
|
||||
env->cp0.c0_cpuid = 0xffffffff;
|
||||
env->ucf64.xregs[UC32_UCF64_FPSCR] = 0;
|
||||
|
||||
set_feature(env, UC32_HWCAP_CMOV);
|
||||
set_feature(env, UC32_HWCAP_UCF64);
|
||||
}
|
||||
|
||||
static void uc32_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
UniCore32CPUClass *ucc = UNICORE32_CPU_GET_CLASS(dev);
|
||||
Error *local_err = NULL;
|
||||
|
||||
cpu_exec_realizefn(cs, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_init_vcpu(cs);
|
||||
|
||||
ucc->parent_realize(dev, errp);
|
||||
}
|
||||
|
||||
static void uc32_cpu_initfn(Object *obj)
|
||||
{
|
||||
UniCore32CPU *cpu = UNICORE32_CPU(obj);
|
||||
CPUUniCore32State *env = &cpu->env;
|
||||
|
||||
cpu_set_cpustate_pointers(cpu);
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
env->uncached_asr = ASR_MODE_USER;
|
||||
env->regs[31] = 0;
|
||||
#else
|
||||
env->uncached_asr = ASR_MODE_PRIV;
|
||||
env->regs[31] = 0x03000000;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_uc32_cpu = {
|
||||
.name = "cpu",
|
||||
.unmigratable = 1,
|
||||
};
|
||||
|
||||
#include "hw/core/tcg-cpu-ops.h"
|
||||
|
||||
static struct TCGCPUOps uc32_tcg_ops = {
|
||||
.initialize = uc32_translate_init,
|
||||
.cpu_exec_interrupt = uc32_cpu_exec_interrupt,
|
||||
.tlb_fill = uc32_cpu_tlb_fill,
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
.do_interrupt = uc32_cpu_do_interrupt,
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
};
|
||||
|
||||
static void uc32_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
CPUClass *cc = CPU_CLASS(oc);
|
||||
UniCore32CPUClass *ucc = UNICORE32_CPU_CLASS(oc);
|
||||
|
||||
device_class_set_parent_realize(dc, uc32_cpu_realizefn,
|
||||
&ucc->parent_realize);
|
||||
|
||||
cc->class_by_name = uc32_cpu_class_by_name;
|
||||
cc->has_work = uc32_cpu_has_work;
|
||||
cc->dump_state = uc32_cpu_dump_state;
|
||||
cc->set_pc = uc32_cpu_set_pc;
|
||||
cc->get_phys_page_debug = uc32_cpu_get_phys_page_debug;
|
||||
dc->vmsd = &vmstate_uc32_cpu;
|
||||
cc->tcg_ops = &uc32_tcg_ops;
|
||||
}
|
||||
|
||||
#define DEFINE_UNICORE32_CPU_TYPE(cpu_model, initfn) \
|
||||
{ \
|
||||
.parent = TYPE_UNICORE32_CPU, \
|
||||
.instance_init = initfn, \
|
||||
.name = UNICORE32_CPU_TYPE_NAME(cpu_model), \
|
||||
}
|
||||
|
||||
static const TypeInfo uc32_cpu_type_infos[] = {
|
||||
{
|
||||
.name = TYPE_UNICORE32_CPU,
|
||||
.parent = TYPE_CPU,
|
||||
.instance_size = sizeof(UniCore32CPU),
|
||||
.instance_init = uc32_cpu_initfn,
|
||||
.abstract = true,
|
||||
.class_size = sizeof(UniCore32CPUClass),
|
||||
.class_init = uc32_cpu_class_init,
|
||||
},
|
||||
DEFINE_UNICORE32_CPU_TYPE("UniCore-II", unicore_ii_cpu_initfn),
|
||||
DEFINE_UNICORE32_CPU_TYPE("any", uc32_any_cpu_initfn),
|
||||
};
|
||||
|
||||
DEFINE_TYPES(uc32_cpu_type_infos)
|
@ -1,168 +0,0 @@
|
||||
/*
|
||||
* UniCore32 virtual CPU header
|
||||
*
|
||||
* Copyright (C) 2010-2012 Guan Xuetao
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or (at your option) any
|
||||
* later version. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef UNICORE32_CPU_H
|
||||
#define UNICORE32_CPU_H
|
||||
|
||||
#include "cpu-qom.h"
|
||||
#include "exec/cpu-defs.h"
|
||||
|
||||
typedef struct CPUUniCore32State {
|
||||
/* Regs for current mode. */
|
||||
uint32_t regs[32];
|
||||
/* Frequently accessed ASR bits are stored separately for efficiently.
|
||||
This contains all the other bits. Use asr_{read,write} to access
|
||||
the whole ASR. */
|
||||
uint32_t uncached_asr;
|
||||
uint32_t bsr;
|
||||
|
||||
/* Banked registers. */
|
||||
uint32_t banked_bsr[6];
|
||||
uint32_t banked_r29[6];
|
||||
uint32_t banked_r30[6];
|
||||
|
||||
/* asr flag cache for faster execution */
|
||||
uint32_t CF; /* 0 or 1 */
|
||||
uint32_t VF; /* V is the bit 31. All other bits are undefined */
|
||||
uint32_t NF; /* N is bit 31. All other bits are undefined. */
|
||||
uint32_t ZF; /* Z set if zero. */
|
||||
|
||||
/* System control coprocessor (cp0) */
|
||||
struct {
|
||||
uint32_t c0_cpuid;
|
||||
uint32_t c0_cachetype;
|
||||
uint32_t c1_sys; /* System control register. */
|
||||
uint32_t c2_base; /* MMU translation table base. */
|
||||
uint32_t c3_faultstatus; /* Fault status registers. */
|
||||
uint32_t c4_faultaddr; /* Fault address registers. */
|
||||
uint32_t c5_cacheop; /* Cache operation registers. */
|
||||
uint32_t c6_tlbop; /* TLB operation registers. */
|
||||
} cp0;
|
||||
|
||||
/* UniCore-F64 coprocessor state. */
|
||||
struct {
|
||||
float64 regs[16];
|
||||
uint32_t xregs[32];
|
||||
float_status fp_status;
|
||||
} ucf64;
|
||||
|
||||
/* Internal CPU feature flags. */
|
||||
uint32_t features;
|
||||
|
||||
} CPUUniCore32State;
|
||||
|
||||
/**
|
||||
* UniCore32CPU:
|
||||
* @env: #CPUUniCore32State
|
||||
*
|
||||
* A UniCore32 CPU.
|
||||
*/
|
||||
struct UniCore32CPU {
|
||||
/*< private >*/
|
||||
CPUState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
CPUNegativeOffsetState neg;
|
||||
CPUUniCore32State env;
|
||||
};
|
||||
|
||||
|
||||
void uc32_cpu_do_interrupt(CPUState *cpu);
|
||||
bool uc32_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||
void uc32_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
|
||||
hwaddr uc32_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
||||
|
||||
#define ASR_M (0x1f)
|
||||
#define ASR_MODE_USER (0x10)
|
||||
#define ASR_MODE_INTR (0x12)
|
||||
#define ASR_MODE_PRIV (0x13)
|
||||
#define ASR_MODE_TRAP (0x17)
|
||||
#define ASR_MODE_EXTN (0x1b)
|
||||
#define ASR_MODE_SUSR (0x1f)
|
||||
#define ASR_I (1 << 7)
|
||||
#define ASR_V (1 << 28)
|
||||
#define ASR_C (1 << 29)
|
||||
#define ASR_Z (1 << 30)
|
||||
#define ASR_N (1 << 31)
|
||||
#define ASR_NZCV (ASR_N | ASR_Z | ASR_C | ASR_V)
|
||||
#define ASR_RESERVED (~(ASR_M | ASR_I | ASR_NZCV))
|
||||
|
||||
#define UC32_EXCP_PRIV (1)
|
||||
#define UC32_EXCP_ITRAP (2)
|
||||
#define UC32_EXCP_DTRAP (3)
|
||||
#define UC32_EXCP_INTR (4)
|
||||
|
||||
/* Return the current ASR value. */
|
||||
target_ulong cpu_asr_read(CPUUniCore32State *env1);
|
||||
/* Set the ASR. Note that some bits of mask must be all-set or all-clear. */
|
||||
void cpu_asr_write(CPUUniCore32State *env1, target_ulong val, target_ulong mask);
|
||||
|
||||
/* UniCore-F64 system registers. */
|
||||
#define UC32_UCF64_FPSCR (31)
|
||||
#define UCF64_FPSCR_MASK (0x27ffffff)
|
||||
#define UCF64_FPSCR_RND_MASK (0x7)
|
||||
#define UCF64_FPSCR_RND(r) (((r) >> 0) & UCF64_FPSCR_RND_MASK)
|
||||
#define UCF64_FPSCR_TRAPEN_MASK (0x7f)
|
||||
#define UCF64_FPSCR_TRAPEN(r) (((r) >> 10) & UCF64_FPSCR_TRAPEN_MASK)
|
||||
#define UCF64_FPSCR_FLAG_MASK (0x3ff)
|
||||
#define UCF64_FPSCR_FLAG(r) (((r) >> 17) & UCF64_FPSCR_FLAG_MASK)
|
||||
#define UCF64_FPSCR_FLAG_ZERO (1 << 17)
|
||||
#define UCF64_FPSCR_FLAG_INFINITY (1 << 18)
|
||||
#define UCF64_FPSCR_FLAG_INVALID (1 << 19)
|
||||
#define UCF64_FPSCR_FLAG_UNDERFLOW (1 << 20)
|
||||
#define UCF64_FPSCR_FLAG_OVERFLOW (1 << 21)
|
||||
#define UCF64_FPSCR_FLAG_INEXACT (1 << 22)
|
||||
#define UCF64_FPSCR_FLAG_HUGEINT (1 << 23)
|
||||
#define UCF64_FPSCR_FLAG_DENORMAL (1 << 24)
|
||||
#define UCF64_FPSCR_FLAG_UNIMP (1 << 25)
|
||||
#define UCF64_FPSCR_FLAG_DIVZERO (1 << 26)
|
||||
|
||||
#define UC32_HWCAP_CMOV 4 /* 1 << 2 */
|
||||
#define UC32_HWCAP_UCF64 8 /* 1 << 3 */
|
||||
|
||||
#define cpu_signal_handler uc32_cpu_signal_handler
|
||||
|
||||
int uc32_cpu_signal_handler(int host_signum, void *pinfo, void *puc);
|
||||
|
||||
/* MMU modes definitions */
|
||||
#define MMU_USER_IDX 1
|
||||
static inline int cpu_mmu_index(CPUUniCore32State *env, bool ifetch)
|
||||
{
|
||||
return (env->uncached_asr & ASR_M) == ASR_MODE_USER ? 1 : 0;
|
||||
}
|
||||
|
||||
typedef CPUUniCore32State CPUArchState;
|
||||
typedef UniCore32CPU ArchCPU;
|
||||
|
||||
#include "exec/cpu-all.h"
|
||||
|
||||
#define UNICORE32_CPU_TYPE_SUFFIX "-" TYPE_UNICORE32_CPU
|
||||
#define UNICORE32_CPU_TYPE_NAME(model) model UNICORE32_CPU_TYPE_SUFFIX
|
||||
#define CPU_RESOLVING_TYPE TYPE_UNICORE32_CPU
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUUniCore32State *env, target_ulong *pc,
|
||||
target_ulong *cs_base, uint32_t *flags)
|
||||
{
|
||||
*pc = env->regs[31];
|
||||
*cs_base = 0;
|
||||
*flags = 0;
|
||||
if ((env->uncached_asr & ASR_M) != ASR_MODE_USER) {
|
||||
*flags |= (1 << 6);
|
||||
}
|
||||
}
|
||||
|
||||
bool uc32_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool probe, uintptr_t retaddr);
|
||||
void uc32_translate_init(void);
|
||||
void switch_mode(CPUUniCore32State *, int);
|
||||
|
||||
#endif /* UNICORE32_CPU_H */
|
@ -1,183 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2012 Guan Xuetao
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Contributions from 2012-04-01 on are considered under GPL version 2,
|
||||
* or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "semihosting/console.h"
|
||||
|
||||
#undef DEBUG_UC32
|
||||
|
||||
#ifdef DEBUG_UC32
|
||||
#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__)
|
||||
#else
|
||||
#define DPRINTF(fmt, ...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
void helper_cp0_set(CPUUniCore32State *env, uint32_t val, uint32_t creg,
|
||||
uint32_t cop)
|
||||
{
|
||||
/*
|
||||
* movc pp.nn, rn, #imm9
|
||||
* rn: UCOP_REG_D
|
||||
* nn: UCOP_REG_N
|
||||
* 1: sys control reg.
|
||||
* 2: page table base reg.
|
||||
* 3: data fault status reg.
|
||||
* 4: insn fault status reg.
|
||||
* 5: cache op. reg.
|
||||
* 6: tlb op. reg.
|
||||
* imm9: split UCOP_IMM10 with bit5 is 0
|
||||
*/
|
||||
switch (creg) {
|
||||
case 1:
|
||||
if (cop != 0) {
|
||||
goto unrecognized;
|
||||
}
|
||||
env->cp0.c1_sys = val;
|
||||
break;
|
||||
case 2:
|
||||
if (cop != 0) {
|
||||
goto unrecognized;
|
||||
}
|
||||
env->cp0.c2_base = val;
|
||||
break;
|
||||
case 3:
|
||||
if (cop != 0) {
|
||||
goto unrecognized;
|
||||
}
|
||||
env->cp0.c3_faultstatus = val;
|
||||
break;
|
||||
case 4:
|
||||
if (cop != 0) {
|
||||
goto unrecognized;
|
||||
}
|
||||
env->cp0.c4_faultaddr = val;
|
||||
break;
|
||||
case 5:
|
||||
switch (cop) {
|
||||
case 28:
|
||||
DPRINTF("Invalidate Entire I&D cache\n");
|
||||
return;
|
||||
case 20:
|
||||
DPRINTF("Invalidate Entire Icache\n");
|
||||
return;
|
||||
case 12:
|
||||
DPRINTF("Invalidate Entire Dcache\n");
|
||||
return;
|
||||
case 10:
|
||||
DPRINTF("Clean Entire Dcache\n");
|
||||
return;
|
||||
case 14:
|
||||
DPRINTF("Flush Entire Dcache\n");
|
||||
return;
|
||||
case 13:
|
||||
DPRINTF("Invalidate Dcache line\n");
|
||||
return;
|
||||
case 11:
|
||||
DPRINTF("Clean Dcache line\n");
|
||||
return;
|
||||
case 15:
|
||||
DPRINTF("Flush Dcache line\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if ((cop <= 6) && (cop >= 2)) {
|
||||
/* invalid all tlb */
|
||||
tlb_flush(env_cpu(env));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto unrecognized;
|
||||
}
|
||||
return;
|
||||
unrecognized:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"Wrong register (%d) or wrong operation (%d) in cp0_set!\n",
|
||||
creg, cop);
|
||||
}
|
||||
|
||||
uint32_t helper_cp0_get(CPUUniCore32State *env, uint32_t creg, uint32_t cop)
|
||||
{
|
||||
/*
|
||||
* movc rd, pp.nn, #imm9
|
||||
* rd: UCOP_REG_D
|
||||
* nn: UCOP_REG_N
|
||||
* 0: cpuid and cachetype
|
||||
* 1: sys control reg.
|
||||
* 2: page table base reg.
|
||||
* 3: data fault status reg.
|
||||
* 4: insn fault status reg.
|
||||
* imm9: split UCOP_IMM10 with bit5 is 0
|
||||
*/
|
||||
switch (creg) {
|
||||
case 0:
|
||||
switch (cop) {
|
||||
case 0:
|
||||
return env->cp0.c0_cpuid;
|
||||
case 1:
|
||||
return env->cp0.c0_cachetype;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (cop == 0) {
|
||||
return env->cp0.c1_sys;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (cop == 0) {
|
||||
return env->cp0.c2_base;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (cop == 0) {
|
||||
return env->cp0.c3_faultstatus;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (cop == 0) {
|
||||
return env->cp0.c4_faultaddr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"Wrong register (%d) or wrong operation (%d) in cp0_set!\n",
|
||||
creg, cop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void helper_cp1_putc(target_ulong regval)
|
||||
{
|
||||
const char c = regval;
|
||||
|
||||
qemu_semihosting_log_out(&c, sizeof(c));
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
bool uc32_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
{
|
||||
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
||||
UniCore32CPU *cpu = UNICORE32_CPU(cs);
|
||||
CPUUniCore32State *env = &cpu->env;
|
||||
|
||||
if (!(env->uncached_asr & ASR_I)) {
|
||||
cs->exception_index = UC32_EXCP_INTR;
|
||||
uc32_cpu_do_interrupt(cs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2012 Guan Xuetao
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or (at your option) any
|
||||
* later version. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
DEF_HELPER_4(cp0_set, void, env, i32, i32, i32)
|
||||
DEF_HELPER_3(cp0_get, i32, env, i32, i32)
|
||||
DEF_HELPER_1(cp1_putc, void, i32)
|
||||
#endif
|
||||
|
||||
DEF_HELPER_2(exception, void, env, i32)
|
||||
|
||||
DEF_HELPER_3(asr_write, void, env, i32, i32)
|
||||
DEF_HELPER_1(asr_read, i32, env)
|
||||
|
||||
DEF_HELPER_2(get_user_reg, i32, env, i32)
|
||||
DEF_HELPER_3(set_user_reg, void, env, i32, i32)
|
||||
|
||||
DEF_HELPER_3(add_cc, i32, env, i32, i32)
|
||||
DEF_HELPER_3(adc_cc, i32, env, i32, i32)
|
||||
DEF_HELPER_3(sub_cc, i32, env, i32, i32)
|
||||
DEF_HELPER_3(sbc_cc, i32, env, i32, i32)
|
||||
|
||||
DEF_HELPER_2(shl, i32, i32, i32)
|
||||
DEF_HELPER_2(shr, i32, i32, i32)
|
||||
DEF_HELPER_2(sar, i32, i32, i32)
|
||||
DEF_HELPER_3(shl_cc, i32, env, i32, i32)
|
||||
DEF_HELPER_3(shr_cc, i32, env, i32, i32)
|
||||
DEF_HELPER_3(sar_cc, i32, env, i32, i32)
|
||||
DEF_HELPER_3(ror_cc, i32, env, i32, i32)
|
||||
|
||||
DEF_HELPER_1(ucf64_get_fpscr, i32, env)
|
||||
DEF_HELPER_2(ucf64_set_fpscr, void, env, i32)
|
||||
|
||||
DEF_HELPER_3(ucf64_adds, f32, f32, f32, env)
|
||||
DEF_HELPER_3(ucf64_addd, f64, f64, f64, env)
|
||||
DEF_HELPER_3(ucf64_subs, f32, f32, f32, env)
|
||||
DEF_HELPER_3(ucf64_subd, f64, f64, f64, env)
|
||||
DEF_HELPER_3(ucf64_muls, f32, f32, f32, env)
|
||||
DEF_HELPER_3(ucf64_muld, f64, f64, f64, env)
|
||||
DEF_HELPER_3(ucf64_divs, f32, f32, f32, env)
|
||||
DEF_HELPER_3(ucf64_divd, f64, f64, f64, env)
|
||||
DEF_HELPER_1(ucf64_negs, f32, f32)
|
||||
DEF_HELPER_1(ucf64_negd, f64, f64)
|
||||
DEF_HELPER_1(ucf64_abss, f32, f32)
|
||||
DEF_HELPER_1(ucf64_absd, f64, f64)
|
||||
DEF_HELPER_4(ucf64_cmps, void, f32, f32, i32, env)
|
||||
DEF_HELPER_4(ucf64_cmpd, void, f64, f64, i32, env)
|
||||
|
||||
DEF_HELPER_2(ucf64_sf2df, f64, f32, env)
|
||||
DEF_HELPER_2(ucf64_df2sf, f32, f64, env)
|
||||
|
||||
DEF_HELPER_2(ucf64_si2sf, f32, f32, env)
|
||||
DEF_HELPER_2(ucf64_si2df, f64, f32, env)
|
||||
|
||||
DEF_HELPER_2(ucf64_sf2si, f32, f32, env)
|
||||
DEF_HELPER_2(ucf64_df2si, f32, f64, env)
|
@ -1,14 +0,0 @@
|
||||
unicore32_ss = ss.source_set()
|
||||
unicore32_ss.add(files(
|
||||
'cpu.c',
|
||||
'helper.c',
|
||||
'op_helper.c',
|
||||
'translate.c',
|
||||
'ucf64_helper.c',
|
||||
), curses)
|
||||
|
||||
unicore32_softmmu_ss = ss.source_set()
|
||||
unicore32_softmmu_ss.add(files('softmmu.c'))
|
||||
|
||||
target_arch += {'unicore32': unicore32_ss}
|
||||
target_softmmu_arch += {'unicore32': unicore32_softmmu_ss}
|
@ -1,244 +0,0 @@
|
||||
/*
|
||||
* UniCore32 helper routines
|
||||
*
|
||||
* Copyright (C) 2010-2012 Guan Xuetao
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or (at your option) any
|
||||
* later version. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
|
||||
#define SIGNBIT (uint32_t)0x80000000
|
||||
#define SIGNBIT64 ((uint64_t)1 << 63)
|
||||
|
||||
void HELPER(exception)(CPUUniCore32State *env, uint32_t excp)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
cs->exception_index = excp;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
static target_ulong asr_read(CPUUniCore32State *env)
|
||||
{
|
||||
int ZF;
|
||||
ZF = (env->ZF == 0);
|
||||
return env->uncached_asr | (env->NF & 0x80000000) | (ZF << 30) |
|
||||
(env->CF << 29) | ((env->VF & 0x80000000) >> 3);
|
||||
}
|
||||
|
||||
target_ulong cpu_asr_read(CPUUniCore32State *env)
|
||||
{
|
||||
return asr_read(env);
|
||||
}
|
||||
|
||||
target_ulong HELPER(asr_read)(CPUUniCore32State *env)
|
||||
{
|
||||
return asr_read(env);
|
||||
}
|
||||
|
||||
static void asr_write(CPUUniCore32State *env, target_ulong val,
|
||||
target_ulong mask)
|
||||
{
|
||||
if (mask & ASR_NZCV) {
|
||||
env->ZF = (~val) & ASR_Z;
|
||||
env->NF = val;
|
||||
env->CF = (val >> 29) & 1;
|
||||
env->VF = (val << 3) & 0x80000000;
|
||||
}
|
||||
|
||||
if ((env->uncached_asr ^ val) & mask & ASR_M) {
|
||||
switch_mode(env, val & ASR_M);
|
||||
}
|
||||
mask &= ~ASR_NZCV;
|
||||
env->uncached_asr = (env->uncached_asr & ~mask) | (val & mask);
|
||||
}
|
||||
|
||||
void cpu_asr_write(CPUUniCore32State *env, target_ulong val, target_ulong mask)
|
||||
{
|
||||
asr_write(env, val, mask);
|
||||
}
|
||||
|
||||
void HELPER(asr_write)(CPUUniCore32State *env, target_ulong val,
|
||||
target_ulong mask)
|
||||
{
|
||||
asr_write(env, val, mask);
|
||||
}
|
||||
|
||||
/* Access to user mode registers from privileged modes. */
|
||||
uint32_t HELPER(get_user_reg)(CPUUniCore32State *env, uint32_t regno)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
if (regno == 29) {
|
||||
val = env->banked_r29[0];
|
||||
} else if (regno == 30) {
|
||||
val = env->banked_r30[0];
|
||||
} else {
|
||||
val = env->regs[regno];
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
void HELPER(set_user_reg)(CPUUniCore32State *env, uint32_t regno, uint32_t val)
|
||||
{
|
||||
if (regno == 29) {
|
||||
env->banked_r29[0] = val;
|
||||
} else if (regno == 30) {
|
||||
env->banked_r30[0] = val;
|
||||
} else {
|
||||
env->regs[regno] = val;
|
||||
}
|
||||
}
|
||||
|
||||
/* ??? Flag setting arithmetic is awkward because we need to do comparisons.
|
||||
The only way to do that in TCG is a conditional branch, which clobbers
|
||||
all our temporaries. For now implement these as helper functions. */
|
||||
|
||||
uint32_t HELPER(add_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
|
||||
{
|
||||
uint32_t result;
|
||||
result = a + b;
|
||||
env->NF = env->ZF = result;
|
||||
env->CF = result < a;
|
||||
env->VF = (a ^ b ^ -1) & (a ^ result);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t HELPER(adc_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
|
||||
{
|
||||
uint32_t result;
|
||||
if (!env->CF) {
|
||||
result = a + b;
|
||||
env->CF = result < a;
|
||||
} else {
|
||||
result = a + b + 1;
|
||||
env->CF = result <= a;
|
||||
}
|
||||
env->VF = (a ^ b ^ -1) & (a ^ result);
|
||||
env->NF = env->ZF = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t HELPER(sub_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
|
||||
{
|
||||
uint32_t result;
|
||||
result = a - b;
|
||||
env->NF = env->ZF = result;
|
||||
env->CF = a >= b;
|
||||
env->VF = (a ^ b) & (a ^ result);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t HELPER(sbc_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
|
||||
{
|
||||
uint32_t result;
|
||||
if (!env->CF) {
|
||||
result = a - b - 1;
|
||||
env->CF = a > b;
|
||||
} else {
|
||||
result = a - b;
|
||||
env->CF = a >= b;
|
||||
}
|
||||
env->VF = (a ^ b) & (a ^ result);
|
||||
env->NF = env->ZF = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Similarly for variable shift instructions. */
|
||||
|
||||
uint32_t HELPER(shl)(uint32_t x, uint32_t i)
|
||||
{
|
||||
int shift = i & 0xff;
|
||||
if (shift >= 32) {
|
||||
return 0;
|
||||
}
|
||||
return x << shift;
|
||||
}
|
||||
|
||||
uint32_t HELPER(shr)(uint32_t x, uint32_t i)
|
||||
{
|
||||
int shift = i & 0xff;
|
||||
if (shift >= 32) {
|
||||
return 0;
|
||||
}
|
||||
return (uint32_t)x >> shift;
|
||||
}
|
||||
|
||||
uint32_t HELPER(sar)(uint32_t x, uint32_t i)
|
||||
{
|
||||
int shift = i & 0xff;
|
||||
if (shift >= 32) {
|
||||
shift = 31;
|
||||
}
|
||||
return (int32_t)x >> shift;
|
||||
}
|
||||
|
||||
uint32_t HELPER(shl_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
|
||||
{
|
||||
int shift = i & 0xff;
|
||||
if (shift >= 32) {
|
||||
if (shift == 32) {
|
||||
env->CF = x & 1;
|
||||
} else {
|
||||
env->CF = 0;
|
||||
}
|
||||
return 0;
|
||||
} else if (shift != 0) {
|
||||
env->CF = (x >> (32 - shift)) & 1;
|
||||
return x << shift;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
uint32_t HELPER(shr_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
|
||||
{
|
||||
int shift = i & 0xff;
|
||||
if (shift >= 32) {
|
||||
if (shift == 32) {
|
||||
env->CF = (x >> 31) & 1;
|
||||
} else {
|
||||
env->CF = 0;
|
||||
}
|
||||
return 0;
|
||||
} else if (shift != 0) {
|
||||
env->CF = (x >> (shift - 1)) & 1;
|
||||
return x >> shift;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
uint32_t HELPER(sar_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
|
||||
{
|
||||
int shift = i & 0xff;
|
||||
if (shift >= 32) {
|
||||
env->CF = (x >> 31) & 1;
|
||||
return (int32_t)x >> 31;
|
||||
} else if (shift != 0) {
|
||||
env->CF = (x >> (shift - 1)) & 1;
|
||||
return (int32_t)x >> shift;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
uint32_t HELPER(ror_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
|
||||
{
|
||||
int shift1, shift;
|
||||
shift1 = i & 0xff;
|
||||
shift = shift1 & 0x1f;
|
||||
if (shift == 0) {
|
||||
if (shift1 != 0) {
|
||||
env->CF = (x >> 31) & 1;
|
||||
}
|
||||
return x;
|
||||
} else {
|
||||
env->CF = (x >> (shift - 1)) & 1;
|
||||
return ((uint32_t)x >> shift) | (x << (32 - shift));
|
||||
}
|
||||
}
|
@ -1,280 +0,0 @@
|
||||
/*
|
||||
* Softmmu related functions
|
||||
*
|
||||
* Copyright (C) 2010-2012 Guan Xuetao
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or any later version.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
#error This file only exist under softmmu circumstance
|
||||
#endif
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#undef DEBUG_UC32
|
||||
|
||||
#ifdef DEBUG_UC32
|
||||
#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__)
|
||||
#else
|
||||
#define DPRINTF(fmt, ...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define SUPERPAGE_SIZE (1 << 22)
|
||||
#define UC32_PAGETABLE_READ (1 << 8)
|
||||
#define UC32_PAGETABLE_WRITE (1 << 7)
|
||||
#define UC32_PAGETABLE_EXEC (1 << 6)
|
||||
#define UC32_PAGETABLE_EXIST (1 << 2)
|
||||
#define PAGETABLE_TYPE(x) ((x) & 3)
|
||||
|
||||
|
||||
/* Map CPU modes onto saved register banks. */
|
||||
static inline int bank_number(CPUUniCore32State *env, int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case ASR_MODE_USER:
|
||||
case ASR_MODE_SUSR:
|
||||
return 0;
|
||||
case ASR_MODE_PRIV:
|
||||
return 1;
|
||||
case ASR_MODE_TRAP:
|
||||
return 2;
|
||||
case ASR_MODE_EXTN:
|
||||
return 3;
|
||||
case ASR_MODE_INTR:
|
||||
return 4;
|
||||
}
|
||||
cpu_abort(env_cpu(env), "Bad mode %x\n", mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void switch_mode(CPUUniCore32State *env, int mode)
|
||||
{
|
||||
int old_mode;
|
||||
int i;
|
||||
|
||||
old_mode = env->uncached_asr & ASR_M;
|
||||
if (mode == old_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
i = bank_number(env, old_mode);
|
||||
env->banked_r29[i] = env->regs[29];
|
||||
env->banked_r30[i] = env->regs[30];
|
||||
env->banked_bsr[i] = env->bsr;
|
||||
|
||||
i = bank_number(env, mode);
|
||||
env->regs[29] = env->banked_r29[i];
|
||||
env->regs[30] = env->banked_r30[i];
|
||||
env->bsr = env->banked_bsr[i];
|
||||
}
|
||||
|
||||
/* Handle a CPU exception. */
|
||||
void uc32_cpu_do_interrupt(CPUState *cs)
|
||||
{
|
||||
UniCore32CPU *cpu = UNICORE32_CPU(cs);
|
||||
CPUUniCore32State *env = &cpu->env;
|
||||
uint32_t addr;
|
||||
int new_mode;
|
||||
|
||||
switch (cs->exception_index) {
|
||||
case UC32_EXCP_PRIV:
|
||||
new_mode = ASR_MODE_PRIV;
|
||||
addr = 0x08;
|
||||
break;
|
||||
case UC32_EXCP_ITRAP:
|
||||
DPRINTF("itrap happened at %x\n", env->regs[31]);
|
||||
new_mode = ASR_MODE_TRAP;
|
||||
addr = 0x0c;
|
||||
break;
|
||||
case UC32_EXCP_DTRAP:
|
||||
DPRINTF("dtrap happened at %x\n", env->regs[31]);
|
||||
new_mode = ASR_MODE_TRAP;
|
||||
addr = 0x10;
|
||||
break;
|
||||
case UC32_EXCP_INTR:
|
||||
new_mode = ASR_MODE_INTR;
|
||||
addr = 0x18;
|
||||
break;
|
||||
default:
|
||||
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
|
||||
return;
|
||||
}
|
||||
/* High vectors. */
|
||||
if (env->cp0.c1_sys & (1 << 13)) {
|
||||
addr += 0xffff0000;
|
||||
}
|
||||
|
||||
switch_mode(env, new_mode);
|
||||
env->bsr = cpu_asr_read(env);
|
||||
env->uncached_asr = (env->uncached_asr & ~ASR_M) | new_mode;
|
||||
env->uncached_asr |= ASR_I;
|
||||
/* The PC already points to the proper instruction. */
|
||||
env->regs[30] = env->regs[31];
|
||||
env->regs[31] = addr;
|
||||
cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
|
||||
}
|
||||
|
||||
static int get_phys_addr_ucv2(CPUUniCore32State *env, uint32_t address,
|
||||
int access_type, int is_user, uint32_t *phys_ptr, int *prot,
|
||||
target_ulong *page_size)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
int code;
|
||||
uint32_t table;
|
||||
uint32_t desc;
|
||||
uint32_t phys_addr;
|
||||
|
||||
/* Pagetable walk. */
|
||||
/* Lookup l1 descriptor. */
|
||||
table = env->cp0.c2_base & 0xfffff000;
|
||||
table |= (address >> 20) & 0xffc;
|
||||
desc = ldl_phys(cs->as, table);
|
||||
code = 0;
|
||||
switch (PAGETABLE_TYPE(desc)) {
|
||||
case 3:
|
||||
/* Superpage */
|
||||
if (!(desc & UC32_PAGETABLE_EXIST)) {
|
||||
code = 0x0b; /* superpage miss */
|
||||
goto do_fault;
|
||||
}
|
||||
phys_addr = (desc & 0xffc00000) | (address & 0x003fffff);
|
||||
*page_size = SUPERPAGE_SIZE;
|
||||
break;
|
||||
case 0:
|
||||
/* Lookup l2 entry. */
|
||||
if (is_user) {
|
||||
DPRINTF("PGD address %x, desc %x\n", table, desc);
|
||||
}
|
||||
if (!(desc & UC32_PAGETABLE_EXIST)) {
|
||||
code = 0x05; /* second pagetable miss */
|
||||
goto do_fault;
|
||||
}
|
||||
table = (desc & 0xfffff000) | ((address >> 10) & 0xffc);
|
||||
desc = ldl_phys(cs->as, table);
|
||||
/* 4k page. */
|
||||
if (is_user) {
|
||||
DPRINTF("PTE address %x, desc %x\n", table, desc);
|
||||
}
|
||||
if (!(desc & UC32_PAGETABLE_EXIST)) {
|
||||
code = 0x08; /* page miss */
|
||||
goto do_fault;
|
||||
}
|
||||
switch (PAGETABLE_TYPE(desc)) {
|
||||
case 0:
|
||||
phys_addr = (desc & 0xfffff000) | (address & 0xfff);
|
||||
*page_size = TARGET_PAGE_SIZE;
|
||||
break;
|
||||
default:
|
||||
cpu_abort(cs, "wrong page type!");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cpu_abort(cs, "wrong page type!");
|
||||
}
|
||||
|
||||
*phys_ptr = phys_addr;
|
||||
*prot = 0;
|
||||
/* Check access permissions. */
|
||||
if (desc & UC32_PAGETABLE_READ) {
|
||||
*prot |= PAGE_READ;
|
||||
} else {
|
||||
if (is_user && (access_type == 0)) {
|
||||
code = 0x11; /* access unreadable area */
|
||||
goto do_fault;
|
||||
}
|
||||
}
|
||||
|
||||
if (desc & UC32_PAGETABLE_WRITE) {
|
||||
*prot |= PAGE_WRITE;
|
||||
} else {
|
||||
if (is_user && (access_type == 1)) {
|
||||
code = 0x12; /* access unwritable area */
|
||||
goto do_fault;
|
||||
}
|
||||
}
|
||||
|
||||
if (desc & UC32_PAGETABLE_EXEC) {
|
||||
*prot |= PAGE_EXEC;
|
||||
} else {
|
||||
if (is_user && (access_type == 2)) {
|
||||
code = 0x13; /* access unexecutable area */
|
||||
goto do_fault;
|
||||
}
|
||||
}
|
||||
|
||||
do_fault:
|
||||
return code;
|
||||
}
|
||||
|
||||
bool uc32_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool probe, uintptr_t retaddr)
|
||||
{
|
||||
UniCore32CPU *cpu = UNICORE32_CPU(cs);
|
||||
CPUUniCore32State *env = &cpu->env;
|
||||
uint32_t phys_addr;
|
||||
target_ulong page_size;
|
||||
int prot;
|
||||
int ret, is_user;
|
||||
|
||||
ret = 1;
|
||||
is_user = mmu_idx == MMU_USER_IDX;
|
||||
|
||||
if ((env->cp0.c1_sys & 1) == 0) {
|
||||
/* MMU disabled. */
|
||||
phys_addr = address;
|
||||
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||
page_size = TARGET_PAGE_SIZE;
|
||||
ret = 0;
|
||||
} else {
|
||||
if ((address & (1 << 31)) || (is_user)) {
|
||||
ret = get_phys_addr_ucv2(env, address, access_type, is_user,
|
||||
&phys_addr, &prot, &page_size);
|
||||
if (is_user) {
|
||||
DPRINTF("user space access: ret %x, address %" VADDR_PRIx ", "
|
||||
"access_type %x, phys_addr %x, prot %x\n",
|
||||
ret, address, access_type, phys_addr, prot);
|
||||
}
|
||||
} else {
|
||||
/*IO memory */
|
||||
phys_addr = address | (1 << 31);
|
||||
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||
page_size = TARGET_PAGE_SIZE;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
/* Map a single page. */
|
||||
phys_addr &= TARGET_PAGE_MASK;
|
||||
address &= TARGET_PAGE_MASK;
|
||||
tlb_set_page(cs, address, phys_addr, prot, mmu_idx, page_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (probe) {
|
||||
return false;
|
||||
}
|
||||
|
||||
env->cp0.c3_faultstatus = ret;
|
||||
env->cp0.c4_faultaddr = address;
|
||||
if (access_type == 2) {
|
||||
cs->exception_index = UC32_EXCP_ITRAP;
|
||||
} else {
|
||||
cs->exception_index = UC32_EXCP_DTRAP;
|
||||
}
|
||||
cpu_loop_exit_restore(cs, retaddr);
|
||||
}
|
||||
|
||||
hwaddr uc32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||
{
|
||||
error_report("function uc32_cpu_get_phys_page_debug not "
|
||||
"implemented, aborting");
|
||||
return -1;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,324 +0,0 @@
|
||||
/*
|
||||
* UniCore-F64 simulation helpers for QEMU.
|
||||
*
|
||||
* Copyright (C) 2010-2012 Guan Xuetao
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or any later version.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "fpu/softfloat.h"
|
||||
|
||||
/*
|
||||
* The convention used for UniCore-F64 instructions:
|
||||
* Single precition routines have a "s" suffix
|
||||
* Double precision routines have a "d" suffix.
|
||||
*/
|
||||
|
||||
/* Convert host exception flags to f64 form. */
|
||||
static inline int ucf64_exceptbits_from_host(int host_bits)
|
||||
{
|
||||
int target_bits = 0;
|
||||
|
||||
if (host_bits & float_flag_invalid) {
|
||||
target_bits |= UCF64_FPSCR_FLAG_INVALID;
|
||||
}
|
||||
if (host_bits & float_flag_divbyzero) {
|
||||
target_bits |= UCF64_FPSCR_FLAG_DIVZERO;
|
||||
}
|
||||
if (host_bits & float_flag_overflow) {
|
||||
target_bits |= UCF64_FPSCR_FLAG_OVERFLOW;
|
||||
}
|
||||
if (host_bits & float_flag_underflow) {
|
||||
target_bits |= UCF64_FPSCR_FLAG_UNDERFLOW;
|
||||
}
|
||||
if (host_bits & float_flag_inexact) {
|
||||
target_bits |= UCF64_FPSCR_FLAG_INEXACT;
|
||||
}
|
||||
return target_bits;
|
||||
}
|
||||
|
||||
uint32_t HELPER(ucf64_get_fpscr)(CPUUniCore32State *env)
|
||||
{
|
||||
int i;
|
||||
uint32_t fpscr;
|
||||
|
||||
fpscr = (env->ucf64.xregs[UC32_UCF64_FPSCR] & UCF64_FPSCR_MASK);
|
||||
i = get_float_exception_flags(&env->ucf64.fp_status);
|
||||
fpscr |= ucf64_exceptbits_from_host(i);
|
||||
return fpscr;
|
||||
}
|
||||
|
||||
/* Convert ucf64 exception flags to target form. */
|
||||
static inline int ucf64_exceptbits_to_host(int target_bits)
|
||||
{
|
||||
int host_bits = 0;
|
||||
|
||||
if (target_bits & UCF64_FPSCR_FLAG_INVALID) {
|
||||
host_bits |= float_flag_invalid;
|
||||
}
|
||||
if (target_bits & UCF64_FPSCR_FLAG_DIVZERO) {
|
||||
host_bits |= float_flag_divbyzero;
|
||||
}
|
||||
if (target_bits & UCF64_FPSCR_FLAG_OVERFLOW) {
|
||||
host_bits |= float_flag_overflow;
|
||||
}
|
||||
if (target_bits & UCF64_FPSCR_FLAG_UNDERFLOW) {
|
||||
host_bits |= float_flag_underflow;
|
||||
}
|
||||
if (target_bits & UCF64_FPSCR_FLAG_INEXACT) {
|
||||
host_bits |= float_flag_inexact;
|
||||
}
|
||||
return host_bits;
|
||||
}
|
||||
|
||||
void HELPER(ucf64_set_fpscr)(CPUUniCore32State *env, uint32_t val)
|
||||
{
|
||||
UniCore32CPU *cpu = env_archcpu(env);
|
||||
int i;
|
||||
uint32_t changed;
|
||||
|
||||
changed = env->ucf64.xregs[UC32_UCF64_FPSCR];
|
||||
env->ucf64.xregs[UC32_UCF64_FPSCR] = (val & UCF64_FPSCR_MASK);
|
||||
|
||||
changed ^= val;
|
||||
if (changed & (UCF64_FPSCR_RND_MASK)) {
|
||||
i = UCF64_FPSCR_RND(val);
|
||||
switch (i) {
|
||||
case 0:
|
||||
i = float_round_nearest_even;
|
||||
break;
|
||||
case 1:
|
||||
i = float_round_to_zero;
|
||||
break;
|
||||
case 2:
|
||||
i = float_round_up;
|
||||
break;
|
||||
case 3:
|
||||
i = float_round_down;
|
||||
break;
|
||||
default: /* 100 and 101 not implement */
|
||||
cpu_abort(CPU(cpu), "Unsupported UniCore-F64 round mode");
|
||||
}
|
||||
set_float_rounding_mode(i, &env->ucf64.fp_status);
|
||||
}
|
||||
|
||||
i = ucf64_exceptbits_to_host(UCF64_FPSCR_TRAPEN(val));
|
||||
set_float_exception_flags(i, &env->ucf64.fp_status);
|
||||
}
|
||||
|
||||
float32 HELPER(ucf64_adds)(float32 a, float32 b, CPUUniCore32State *env)
|
||||
{
|
||||
return float32_add(a, b, &env->ucf64.fp_status);
|
||||
}
|
||||
|
||||
float64 HELPER(ucf64_addd)(float64 a, float64 b, CPUUniCore32State *env)
|
||||
{
|
||||
return float64_add(a, b, &env->ucf64.fp_status);
|
||||
}
|
||||
|
||||
float32 HELPER(ucf64_subs)(float32 a, float32 b, CPUUniCore32State *env)
|
||||
{
|
||||
return float32_sub(a, b, &env->ucf64.fp_status);
|
||||
}
|
||||
|
||||
float64 HELPER(ucf64_subd)(float64 a, float64 b, CPUUniCore32State *env)
|
||||
{
|
||||
return float64_sub(a, b, &env->ucf64.fp_status);
|
||||
}
|
||||
|
||||
float32 HELPER(ucf64_muls)(float32 a, float32 b, CPUUniCore32State *env)
|
||||
{
|
||||
return float32_mul(a, b, &env->ucf64.fp_status);
|
||||
}
|
||||
|
||||
float64 HELPER(ucf64_muld)(float64 a, float64 b, CPUUniCore32State *env)
|
||||
{
|
||||
return float64_mul(a, b, &env->ucf64.fp_status);
|
||||
}
|
||||
|
||||
float32 HELPER(ucf64_divs)(float32 a, float32 b, CPUUniCore32State *env)
|
||||
{
|
||||
return float32_div(a, b, &env->ucf64.fp_status);
|
||||
}
|
||||
|
||||
float64 HELPER(ucf64_divd)(float64 a, float64 b, CPUUniCore32State *env)
|
||||
{
|
||||
return float64_div(a, b, &env->ucf64.fp_status);
|
||||
}
|
||||
|
||||
float32 HELPER(ucf64_negs)(float32 a)
|
||||
{
|
||||
return float32_chs(a);
|
||||
}
|
||||
|
||||
float64 HELPER(ucf64_negd)(float64 a)
|
||||
{
|
||||
return float64_chs(a);
|
||||
}
|
||||
|
||||
float32 HELPER(ucf64_abss)(float32 a)
|
||||
{
|
||||
return float32_abs(a);
|
||||
}
|
||||
|
||||
float64 HELPER(ucf64_absd)(float64 a)
|
||||
{
|
||||
return float64_abs(a);
|
||||
}
|
||||
|
||||
void HELPER(ucf64_cmps)(float32 a, float32 b, uint32_t c,
|
||||
CPUUniCore32State *env)
|
||||
{
|
||||
FloatRelation flag = float32_compare_quiet(a, b, &env->ucf64.fp_status);
|
||||
env->CF = 0;
|
||||
switch (c & 0x7) {
|
||||
case 0: /* F */
|
||||
break;
|
||||
case 1: /* UN */
|
||||
if (flag == 2) {
|
||||
env->CF = 1;
|
||||
}
|
||||
break;
|
||||
case 2: /* EQ */
|
||||
if (flag == 0) {
|
||||
env->CF = 1;
|
||||
}
|
||||
break;
|
||||
case 3: /* UEQ */
|
||||
if ((flag == 0) || (flag == 2)) {
|
||||
env->CF = 1;
|
||||
}
|
||||
break;
|
||||
case 4: /* OLT */
|
||||
if (flag == -1) {
|
||||
env->CF = 1;
|
||||
}
|
||||
break;
|
||||
case 5: /* ULT */
|
||||
if ((flag == -1) || (flag == 2)) {
|
||||
env->CF = 1;
|
||||
}
|
||||
break;
|
||||
case 6: /* OLE */
|
||||
if ((flag == -1) || (flag == 0)) {
|
||||
env->CF = 1;
|
||||
}
|
||||
break;
|
||||
case 7: /* ULE */
|
||||
if (flag != 1) {
|
||||
env->CF = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
env->ucf64.xregs[UC32_UCF64_FPSCR] = (env->CF << 29)
|
||||
| (env->ucf64.xregs[UC32_UCF64_FPSCR] & 0x0fffffff);
|
||||
}
|
||||
|
||||
void HELPER(ucf64_cmpd)(float64 a, float64 b, uint32_t c,
|
||||
CPUUniCore32State *env)
|
||||
{
|
||||
FloatRelation flag = float64_compare_quiet(a, b, &env->ucf64.fp_status);
|
||||
env->CF = 0;
|
||||
switch (c & 0x7) {
|
||||
case 0: /* F */
|
||||
break;
|
||||
case 1: /* UN */
|
||||
if (flag == 2) {
|
||||
env->CF = 1;
|
||||
}
|
||||
break;
|
||||
case 2: /* EQ */
|
||||
if (flag == 0) {
|
||||
env->CF = 1;
|
||||
}
|
||||
break;
|
||||
case 3: /* UEQ */
|
||||
if ((flag == 0) || (flag == 2)) {
|
||||
env->CF = 1;
|
||||
}
|
||||
break;
|
||||
case 4: /* OLT */
|
||||
if (flag == -1) {
|
||||
env->CF = 1;
|
||||
}
|
||||
break;
|
||||
case 5: /* ULT */
|
||||
if ((flag == -1) || (flag == 2)) {
|
||||
env->CF = 1;
|
||||
}
|
||||
break;
|
||||
case 6: /* OLE */
|
||||
if ((flag == -1) || (flag == 0)) {
|
||||
env->CF = 1;
|
||||
}
|
||||
break;
|
||||
case 7: /* ULE */
|
||||
if (flag != 1) {
|
||||
env->CF = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
env->ucf64.xregs[UC32_UCF64_FPSCR] = (env->CF << 29)
|
||||
| (env->ucf64.xregs[UC32_UCF64_FPSCR] & 0x0fffffff);
|
||||
}
|
||||
|
||||
/* Helper routines to perform bitwise copies between float and int. */
|
||||
static inline float32 ucf64_itos(uint32_t i)
|
||||
{
|
||||
union {
|
||||
uint32_t i;
|
||||
float32 s;
|
||||
} v;
|
||||
|
||||
v.i = i;
|
||||
return v.s;
|
||||
}
|
||||
|
||||
static inline uint32_t ucf64_stoi(float32 s)
|
||||
{
|
||||
union {
|
||||
uint32_t i;
|
||||
float32 s;
|
||||
} v;
|
||||
|
||||
v.s = s;
|
||||
return v.i;
|
||||
}
|
||||
|
||||
/* Integer to float conversion. */
|
||||
float32 HELPER(ucf64_si2sf)(float32 x, CPUUniCore32State *env)
|
||||
{
|
||||
return int32_to_float32(ucf64_stoi(x), &env->ucf64.fp_status);
|
||||
}
|
||||
|
||||
float64 HELPER(ucf64_si2df)(float32 x, CPUUniCore32State *env)
|
||||
{
|
||||
return int32_to_float64(ucf64_stoi(x), &env->ucf64.fp_status);
|
||||
}
|
||||
|
||||
/* Float to integer conversion. */
|
||||
float32 HELPER(ucf64_sf2si)(float32 x, CPUUniCore32State *env)
|
||||
{
|
||||
return ucf64_itos(float32_to_int32(x, &env->ucf64.fp_status));
|
||||
}
|
||||
|
||||
float32 HELPER(ucf64_df2si)(float64 x, CPUUniCore32State *env)
|
||||
{
|
||||
return ucf64_itos(float64_to_int32(x, &env->ucf64.fp_status));
|
||||
}
|
||||
|
||||
/* floating point conversion */
|
||||
float64 HELPER(ucf64_sf2df)(float32 x, CPUUniCore32State *env)
|
||||
{
|
||||
return float32_to_float64(x, &env->ucf64.fp_status);
|
||||
}
|
||||
|
||||
float32 HELPER(ucf64_df2sf)(float64 x, CPUUniCore32State *env)
|
||||
{
|
||||
return float64_to_float32(x, &env->ucf64.fp_status);
|
||||
}
|
@ -49,7 +49,6 @@ static struct arch2cpu cpus_map[] = {
|
||||
{ "sparc", "LEON2" },
|
||||
{ "sparc64", "Fujitsu Sparc64" },
|
||||
{ "tricore", "tc1796" },
|
||||
{ "unicore32", "UniCore-II" },
|
||||
{ "xtensa", "dc233c" },
|
||||
{ "xtensaeb", "fsf" },
|
||||
{ "hppa", "hppa" },
|
||||
|
Loading…
Reference in New Issue
Block a user