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:
Markus Armbruster 2021-05-03 10:40:34 +02:00
parent 9d49bcf699
commit 4369223902
42 changed files with 16 additions and 4582 deletions

View File

@ -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:

View File

@ -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
View File

@ -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=""

View File

@ -1,6 +0,0 @@
# Default configuration for unicore32-softmmu
# Boards:
#
CONFIG_PUV3=y
CONFIG_SEMIHOSTING=y

View File

@ -1 +0,0 @@
TARGET_ARCH=unicore32

View File

@ -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)
''''''''''''''''''''''''''''''''''''''''''

View File

@ -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
------------------------

View File

@ -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 */

View File

@ -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

View File

@ -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'))

View File

@ -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)

View File

@ -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'))

View File

@ -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)

View File

@ -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'))

View File

@ -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)

View File

@ -61,5 +61,4 @@ subdir('sh4')
subdir('sparc')
subdir('sparc64')
subdir('tricore')
subdir('unicore32')
subdir('xtensa')

View File

@ -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'))

View File

@ -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)

View File

@ -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'))

View File

@ -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)

View File

@ -1,5 +0,0 @@
config PUV3
bool
select ISA_BUS
select PCKBD
select PTIMER

View File

@ -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}

View File

@ -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)

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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),

View File

@ -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' ] }
##

View File

@ -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)

View File

@ -17,5 +17,4 @@ subdir('s390x')
subdir('sh4')
subdir('sparc')
subdir('tricore')
subdir('unicore32')
subdir('xtensa')

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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 */

View File

@ -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;
}

View File

@ -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)

View File

@ -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}

View File

@ -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));
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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" },