Merge remote-tracking branch 'remotes/philmd-gitlab/tags/mips-next-20201017' into staging

MIPS patches queue

. Fix some comment spelling errors
. Demacro some TCG helpers
. Add loongson-ext lswc2/lsdc2 group of instructions
. Log unimplemented cache opcode
. Increase number of TLB entries on the 34Kf core
. Allow the CPU to use dynamic frequencies
. Calculate the CP0 timer period using the CPU frequency
. Set CPU frequency for each machine
. Fix Malta FPGA I/O region size
. Allow running qtests when ROM is missing
. Add record/replay acceptance tests
. Update MIPS CPU documentation
. MAINTAINERS updates

CI jobs results:
  https://gitlab.com/philmd/qemu/-/pipelines/203931842
  https://travis-ci.org/github/philmd/qemu/builds/736491461
  https://cirrus-ci.com/build/6272264062631936
  https://app.shippable.com/github/philmd/qemu/runs/886/summary/console

# gpg: Signature made Sat 17 Oct 2020 14:59:53 BST
# gpg:                using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD  6BB2 E3E3 2C2C DEAD C0DE

* remotes/philmd-gitlab/tags/mips-next-20201017: (44 commits)
  target/mips: Increase number of TLB entries on the 34Kf core (16 -> 64)
  MAINTAINERS: Remove duplicated Malta test entries
  MAINTAINERS: Downgrade MIPS Boston to 'Odd Fixes', fix Paul Burton mail
  MAINTAINERS: Put myself forward for MIPS target
  MAINTAINERS: Remove myself
  docs/system: Update MIPS CPU documentation
  tests/acceptance: Add MIPS record/replay tests
  hw/mips: Remove exit(1) in case of missing ROM
  hw/mips: Rename TYPE_MIPS_BOSTON to TYPE_BOSTON
  hw/mips: Simplify code using ROUND_UP(INITRD_PAGE_SIZE)
  hw/mips: Simplify loading 64-bit ELF kernels
  hw/mips/malta: Use clearer qdev style
  hw/mips/malta: Move gt64120 related code together
  hw/mips/malta: Fix FPGA I/O region size
  target/mips/cpu: Display warning when CPU is used without input clock
  hw/mips/cps: Do not allow use without input clock
  hw/mips/malta: Set CPU frequency to 320 MHz
  hw/mips/boston: Set CPU frequency to 1 GHz
  hw/mips/cps: Expose input clock and connect it to CPU cores
  hw/mips/jazz: Correct CPU frequencies
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2020-10-19 10:52:57 +01:00
26 changed files with 1119 additions and 195 deletions
+9 -16
View File
@@ -220,11 +220,11 @@ F: hw/microblaze/
F: disas/microblaze.c
MIPS TCG CPUs
M: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
R: Aurelien Jarno <aurelien@aurel32.net>
R: Jiaxun Yang <jiaxun.yang@flygoat.com>
R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
S: Maintained
S: Odd Fixes
F: target/mips/
F: default-configs/*mips*
F: disas/*mips*
@@ -237,8 +237,6 @@ F: include/hw/intc/mips_gic.h
F: include/hw/mips/
F: include/hw/misc/mips_*
F: include/hw/timer/mips_gictimer.h
F: tests/acceptance/linux_ssh_mips_malta.py
F: tests/acceptance/machine_mips_malta.py
F: tests/tcg/mips/
K: ^Subject:.*(?i)mips
@@ -386,7 +384,6 @@ F: target/arm/kvm.c
MIPS KVM CPUs
M: Huacai Chen <chenhc@lemote.com>
M: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
S: Odd Fixes
F: target/mips/kvm.c
@@ -1123,10 +1120,9 @@ F: hw/display/jazz_led.c
F: hw/dma/rc4030.c
Malta
M: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
R: Aurelien Jarno <aurelien@aurel32.net>
S: Maintained
S: Odd Fixes
F: hw/isa/piix4.c
F: hw/acpi/piix4.c
F: hw/mips/malta.c
@@ -1136,14 +1132,12 @@ F: tests/acceptance/linux_ssh_mips_malta.py
F: tests/acceptance/machine_mips_malta.py
Mipssim
M: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
S: Odd Fixes
S: Orphaned
F: hw/mips/mipssim.c
F: hw/net/mipsnet.c
R4000
M: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
R: Aurelien Jarno <aurelien@aurel32.net>
R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
S: Obsolete
@@ -1152,7 +1146,6 @@ F: hw/mips/r4k.c
Fuloong 2E
M: Huacai Chen <chenhc@lemote.com>
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
M: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
R: Jiaxun Yang <jiaxun.yang@flygoat.com>
S: Odd Fixes
F: hw/mips/fuloong2e.c
@@ -1167,9 +1160,9 @@ S: Maintained
F: hw/intc/loongson_liointc.c
Boston
M: Paul Burton <pburton@wavecomp.com>
M: Paul Burton <paulburton@kernel.org>
R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
S: Maintained
S: Odd Fixes
F: hw/core/loader-fit.c
F: hw/mips/boston.c
F: hw/pci-host/xilinx-pcie.c
@@ -2823,12 +2816,12 @@ F: tcg/i386/
F: disas/i386.c
MIPS TCG target
M: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
R: Aurelien Jarno <aurelien@aurel32.net>
R: Huacai Chen <chenhc@lemote.com>
R: Jiaxun Yang <jiaxun.yang@flygoat.com>
R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
S: Maintained
S: Odd Fixes
F: tcg/mips/
PPC TCG target
@@ -3169,7 +3162,7 @@ S: Odd Fixes
F: scripts/git-submodule.sh
UI translations
M: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
S: Orphaned
F: po/*.po
Sphinx documentation configuration and build machinery
+8 -2
View File
@@ -48,11 +48,17 @@ across all desired hosts.
``I6400``
MIPS64 Processor (Release 6, 2014)
``Loongson-2E``
MIPS64 Processor (Loongson 2, 2006)
``Loongson-2F``
MIPS64 Processor (Loongson 2, 2008)
``Loongson-2E``
MIPS64 Processor (Loongson 2, 2006)
``Loongson-3A1000``
MIPS64 Processor (Loongson 3, 2010)
``Loongson-3A4000``
MIPS64 Processor (Loongson 3, 2018)
``mips64dspr2``
MIPS64 Processor (Release 2, 2006)
+15
View File
@@ -23,6 +23,21 @@ void clock_setup_canonical_path(Clock *clk)
clk->canonical_path = object_get_canonical_path(OBJECT(clk));
}
Clock *clock_new(Object *parent, const char *name)
{
Object *obj;
Clock *clk;
obj = object_new(TYPE_CLOCK);
object_property_add_child(parent, name, obj);
object_unref(obj);
clk = CLOCK(obj);
clock_setup_canonical_path(clk);
return clk;
}
void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque)
{
clk->callback = cb;
+11
View File
@@ -12,6 +12,7 @@
*/
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "hw/qdev-clock.h"
#include "hw/qdev-core.h"
#include "qapi/error.h"
@@ -153,6 +154,11 @@ Clock *qdev_get_clock_in(DeviceState *dev, const char *name)
assert(name);
ncl = qdev_get_clocklist(dev, name);
if (!ncl) {
error_report("Can not find clock-in '%s' for device type '%s'",
name, object_get_typename(OBJECT(dev)));
abort();
}
assert(!ncl->output);
return ncl->clock;
@@ -165,6 +171,11 @@ Clock *qdev_get_clock_out(DeviceState *dev, const char *name)
assert(name);
ncl = qdev_get_clocklist(dev, name);
if (!ncl) {
error_report("Can not find clock-out '%s' for device type '%s'",
name, object_get_typename(OBJECT(dev)));
abort();
}
assert(ncl->output);
return ncl->clock;
+17 -4
View File
@@ -30,6 +30,7 @@
#include "hw/mips/cps.h"
#include "hw/mips/cpudevs.h"
#include "hw/pci-host/xilinx-pcie.h"
#include "hw/qdev-clock.h"
#include "hw/qdev-properties.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
@@ -43,10 +44,10 @@
#include <libfdt.h>
#include "qom/object.h"
#define TYPE_MIPS_BOSTON "mips-boston"
#define TYPE_BOSTON "mips-boston"
typedef struct BostonState BostonState;
DECLARE_INSTANCE_CHECKER(BostonState, BOSTON,
TYPE_MIPS_BOSTON)
TYPE_BOSTON)
struct BostonState {
SysBusDevice parent_obj;
@@ -54,6 +55,7 @@ struct BostonState {
MachineState *mach;
MIPSCPSState cps;
SerialMM *uart;
Clock *cpuclk;
CharBackend lcd_display;
char lcd_content[8];
@@ -251,10 +253,19 @@ static const MemoryRegionOps boston_platreg_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void mips_boston_instance_init(Object *obj)
{
BostonState *s = BOSTON(obj);
s->cpuclk = qdev_init_clock_out(DEVICE(obj), "cpu-refclk");
clock_set_hz(s->cpuclk, 1000000000); /* 1 GHz */
}
static const TypeInfo boston_device = {
.name = TYPE_MIPS_BOSTON,
.name = TYPE_BOSTON,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(BostonState),
.instance_init = mips_boston_instance_init,
};
static void boston_register_types(void)
@@ -444,7 +455,7 @@ static void boston_mach_init(MachineState *machine)
exit(1);
}
dev = qdev_new(TYPE_MIPS_BOSTON);
dev = qdev_new(TYPE_BOSTON);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
s = BOSTON(dev);
@@ -462,6 +473,8 @@ static void boston_mach_init(MachineState *machine)
&error_fatal);
object_property_set_int(OBJECT(&s->cps), "num-vp", machine->smp.cpus,
&error_fatal);
qdev_connect_clock_in(DEVICE(&s->cps), "clk-in",
qdev_get_clock_out(dev, "cpu-refclk"));
sysbus_realize(SYS_BUS_DEVICE(&s->cps), &error_fatal);
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->cps), 0, 0, 1);
+9
View File
@@ -22,6 +22,7 @@
#include "qemu/module.h"
#include "hw/mips/cps.h"
#include "hw/mips/mips.h"
#include "hw/qdev-clock.h"
#include "hw/qdev-properties.h"
#include "hw/mips/cpudevs.h"
#include "sysemu/kvm.h"
@@ -38,6 +39,7 @@ static void mips_cps_init(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
MIPSCPSState *s = MIPS_CPS(obj);
s->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, NULL);
/*
* Cover entire address space as there do not seem to be any
* constraints for the base address of CPC and GIC.
@@ -72,6 +74,11 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
bool itu_present = false;
bool saar_present = false;
if (!clock_get(s->clock)) {
error_setg(errp, "CPS input clock is not connected to an output clock");
return;
}
for (i = 0; i < s->num_vp; i++) {
cpu = MIPS_CPU(object_new(s->cpu_type));
@@ -80,6 +87,8 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
errp)) {
return;
}
/* All cores use the same clock tree */
qdev_connect_clock_in(DEVICE(cpu), "clk-in", s->clock);
if (!qdev_realize_and_unref(DEVICE(cpu), NULL, errp)) {
return;
+10 -8
View File
@@ -23,6 +23,7 @@
#include "qemu/units.h"
#include "qapi/error.h"
#include "cpu.h"
#include "hw/clock.h"
#include "hw/intc/i8259.h"
#include "hw/dma/i8257.h"
#include "hw/isa/superio.h"
@@ -132,8 +133,7 @@ static int64_t load_kernel(CPUMIPSState *env)
if (loaderparams.initrd_filename) {
initrd_size = get_image_size(loaderparams.initrd_filename);
if (initrd_size > 0) {
initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) &
INITRD_PAGE_MASK;
initrd_offset = ROUND_UP(kernel_high, INITRD_PAGE_SIZE);
if (initrd_offset + initrd_size > ram_size) {
error_report("memory too small for initial ram disk '%s'",
loaderparams.initrd_filename);
@@ -298,12 +298,16 @@ static void mips_fuloong2e_init(MachineState *machine)
PCIBus *pci_bus;
ISABus *isa_bus;
I2CBus *smbus;
Clock *cpuclk;
MIPSCPU *cpu;
CPUMIPSState *env;
DeviceState *dev;
cpuclk = clock_new(OBJECT(machine), "cpu-refclk");
clock_set_hz(cpuclk, 533080000); /* ~533 MHz */
/* init CPUs */
cpu = MIPS_CPU(cpu_create(machine->cpu_type));
cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk);
env = &cpu->env;
qemu_register_reset(main_cpu_reset, cpu);
@@ -333,10 +337,8 @@ static void mips_fuloong2e_init(MachineState *machine)
kernel_entry = load_kernel(env);
write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
} else {
if (bios_name == NULL) {
bios_name = FULOONG_BIOSNAME;
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
bios_name ?: FULOONG_BIOSNAME);
if (filename) {
bios_size = load_image_targphys(filename, 0x1fc00000LL,
BIOS_SIZE);
@@ -346,7 +348,7 @@ static void mips_fuloong2e_init(MachineState *machine)
}
if ((bios_size < 0 || bios_size > BIOS_SIZE) &&
!kernel_filename && !qtest_enabled()) {
bios_name && !qtest_enabled()) {
error_report("Could not load MIPS bios '%s'", bios_name);
exit(1);
}
+17 -6
View File
@@ -24,6 +24,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "hw/clock.h"
#include "hw/mips/mips.h"
#include "hw/mips/cpudevs.h"
#include "hw/intc/i8259.h"
@@ -142,6 +143,7 @@ static void mips_jazz_init(MachineState *machine,
MemoryRegion *address_space = get_system_memory();
char *filename;
int bios_size, n;
Clock *cpuclk;
MIPSCPU *cpu;
CPUClass *cc;
CPUMIPSState *env;
@@ -163,14 +165,25 @@ static void mips_jazz_init(MachineState *machine,
MemoryRegion *bios2 = g_new(MemoryRegion, 1);
SysBusESPState *sysbus_esp;
ESPState *esp;
static const struct {
unsigned freq_hz;
unsigned pll_mult;
} ext_clk[] = {
[JAZZ_MAGNUM] = {50000000, 2},
[JAZZ_PICA61] = {33333333, 4},
};
if (machine->ram_size > 256 * MiB) {
error_report("RAM size more than 256Mb is not supported");
exit(EXIT_FAILURE);
}
cpuclk = clock_new(OBJECT(machine), "cpu-refclk");
clock_set_hz(cpuclk, ext_clk[jazz_model].freq_hz
* ext_clk[jazz_model].pll_mult);
/* init CPUs */
cpu = MIPS_CPU(cpu_create(machine->cpu_type));
cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk);
env = &cpu->env;
qemu_register_reset(main_cpu_reset, cpu);
@@ -205,10 +218,7 @@ static void mips_jazz_init(MachineState *machine,
memory_region_add_subregion(address_space, 0xfff00000LL, bios2);
/* load the BIOS image. */
if (bios_name == NULL) {
bios_name = BIOS_FILENAME;
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name ?: BIOS_FILENAME);
if (filename) {
bios_size = load_image_targphys(filename, 0xfff00000LL,
MAGNUM_BIOS_SIZE);
@@ -216,7 +226,8 @@ static void mips_jazz_init(MachineState *machine,
} else {
bios_size = -1;
}
if ((bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) && !qtest_enabled()) {
if ((bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE)
&& bios_name && !qtest_enabled()) {
error_report("Could not load MIPS bios '%s'", bios_name);
exit(1);
}
+34 -25
View File
@@ -26,6 +26,7 @@
#include "qemu/units.h"
#include "qemu-common.h"
#include "cpu.h"
#include "hw/clock.h"
#include "hw/southbridge/piix.h"
#include "hw/isa/superio.h"
#include "hw/char/serial.h"
@@ -57,6 +58,7 @@
#include "sysemu/kvm.h"
#include "hw/semihosting/semihost.h"
#include "hw/mips/cps.h"
#include "hw/qdev-clock.h"
#define ENVP_ADDR 0x80002000l
#define ENVP_NB_ENTRIES 16
@@ -94,6 +96,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(MaltaState, MIPS_MALTA)
struct MaltaState {
SysBusDevice parent_obj;
Clock *cpuclk;
MIPSCPSState cps;
qemu_irq i8259[ISA_NUM_IRQS];
};
@@ -575,7 +578,7 @@ static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
memory_region_init_alias(&s->iomem_lo, NULL, "malta-fpga",
&s->iomem, 0, 0x900);
memory_region_init_alias(&s->iomem_hi, NULL, "malta-fpga",
&s->iomem, 0xa00, 0x10000 - 0xa00);
&s->iomem, 0xa00, 0x100000 - 0xa00);
memory_region_add_subregion(address_space, base, &s->iomem_lo);
memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi);
@@ -1074,9 +1077,9 @@ static int64_t load_kernel(void)
* the initrd. It takes at most 128kiB for 2GB RAM and 4kiB
* pages.
*/
initrd_offset = (loaderparams.ram_low_size - initrd_size
- (128 * KiB)
- ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK;
initrd_offset = ROUND_UP(loaderparams.ram_low_size
- (initrd_size + 128 * KiB),
INITRD_PAGE_SIZE);
if (kernel_high >= initrd_offset) {
error_report("memory too small for initial ram disk '%s'",
loaderparams.initrd_filename);
@@ -1159,7 +1162,7 @@ static void main_cpu_reset(void *opaque)
}
}
static void create_cpu_without_cps(MachineState *ms,
static void create_cpu_without_cps(MachineState *ms, MaltaState *s,
qemu_irq *cbus_irq, qemu_irq *i8259_irq)
{
CPUMIPSState *env;
@@ -1167,7 +1170,7 @@ static void create_cpu_without_cps(MachineState *ms,
int i;
for (i = 0; i < ms->smp.cpus; i++) {
cpu = MIPS_CPU(cpu_create(ms->cpu_type));
cpu = mips_cpu_create_with_clock(ms->cpu_type, s->cpuclk);
/* Init internal devices */
cpu_mips_irq_init_cpu(cpu);
@@ -1189,6 +1192,7 @@ static void create_cps(MachineState *ms, MaltaState *s,
&error_fatal);
object_property_set_int(OBJECT(&s->cps), "num-vp", ms->smp.cpus,
&error_fatal);
qdev_connect_clock_in(DEVICE(&s->cps), "clk-in", s->cpuclk);
sysbus_realize(SYS_BUS_DEVICE(&s->cps), &error_fatal);
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->cps), 0, 0, 1);
@@ -1203,7 +1207,7 @@ static void mips_create_cpu(MachineState *ms, MaltaState *s,
if ((ms->smp.cpus > 1) && cpu_supports_cps_smp(ms->cpu_type)) {
create_cps(ms, s, cbus_irq, i8259_irq);
} else {
create_cpu_without_cps(ms, cbus_irq, i8259_irq);
create_cpu_without_cps(ms, s, cbus_irq, i8259_irq);
}
}
@@ -1231,18 +1235,11 @@ void mips_malta_init(MachineState *machine)
DriveInfo *dinfo;
int fl_idx = 0;
int be;
MaltaState *s;
DeviceState *dev;
DeviceState *dev = qdev_new(TYPE_MIPS_MALTA);
MaltaState *s = MIPS_MALTA(dev);
/*
* The whole address space decoded by the GT-64120A doesn't generate
* exception when accessing invalid memory. Create an empty slot to
* emulate this feature.
*/
empty_slot_init("GT64120", 0, 0x20000000);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
s = MIPS_MALTA(qdev_new(TYPE_MIPS_MALTA));
sysbus_realize_and_unref(SYS_BUS_DEVICE(s), &error_fatal);
/* create CPU */
mips_create_cpu(machine, s, &cbus_irq, &i8259_irq);
@@ -1335,10 +1332,8 @@ void mips_malta_init(MachineState *machine)
/* Load firmware from flash. */
if (!dinfo) {
/* Load a BIOS image. */
if (bios_name == NULL) {
bios_name = BIOS_FILENAME;
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
bios_name ?: BIOS_FILENAME);
if (filename) {
bios_size = load_image_targphys(filename, FLASH_ADDRESS,
BIOS_SIZE);
@@ -1347,9 +1342,8 @@ void mips_malta_init(MachineState *machine)
bios_size = -1;
}
if ((bios_size < 0 || bios_size > BIOS_SIZE) &&
!kernel_filename && !qtest_enabled()) {
error_report("Could not load MIPS bios '%s', and no "
"-kernel argument was specified", bios_name);
bios_name && !qtest_enabled()) {
error_report("Could not load MIPS bios '%s'", bios_name);
exit(1);
}
}
@@ -1395,6 +1389,12 @@ void mips_malta_init(MachineState *machine)
/* Northbridge */
pci_bus = gt64120_register(s->i8259);
/*
* The whole address space decoded by the GT-64120A doesn't generate
* exception when accessing invalid memory. Create an empty slot to
* emulate this feature.
*/
empty_slot_init("GT64120", 0, 0x20000000);
/* Southbridge */
dev = piix4_create(pci_bus, &isa_bus, &smbus);
@@ -1421,10 +1421,19 @@ void mips_malta_init(MachineState *machine)
pci_vga_init(pci_bus);
}
static void mips_malta_instance_init(Object *obj)
{
MaltaState *s = MIPS_MALTA(obj);
s->cpuclk = qdev_init_clock_out(DEVICE(obj), "cpu-refclk");
clock_set_hz(s->cpuclk, 320000000); /* 320 MHz */
}
static const TypeInfo mips_malta_device = {
.name = TYPE_MIPS_MALTA,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MaltaState),
.instance_init = mips_malta_instance_init,
};
static void mips_malta_machine_init(MachineClass *mc)
+15 -15
View File
@@ -29,6 +29,7 @@
#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
#include "hw/clock.h"
#include "hw/mips/mips.h"
#include "hw/mips/cpudevs.h"
#include "hw/char/serial.h"
@@ -76,11 +77,7 @@ static int64_t load_kernel(void)
(uint64_t *)&entry, NULL,
(uint64_t *)&kernel_high, NULL, big_endian,
EM_MIPS, 1, 0);
if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000) {
entry = (int32_t)entry;
}
} else {
if (kernel_size < 0) {
error_report("could not load kernel '%s': %s",
loaderparams.kernel_filename,
load_elf_strerror(kernel_size));
@@ -93,8 +90,7 @@ static int64_t load_kernel(void)
if (loaderparams.initrd_filename) {
initrd_size = get_image_size(loaderparams.initrd_filename);
if (initrd_size > 0) {
initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) &
INITRD_PAGE_MASK;
initrd_offset = ROUND_UP(kernel_high, INITRD_PAGE_SIZE);
if (initrd_offset + initrd_size > loaderparams.ram_size) {
error_report("memory too small for initial ram disk '%s'",
loaderparams.initrd_filename);
@@ -150,13 +146,21 @@ mips_mipssim_init(MachineState *machine)
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *isa = g_new(MemoryRegion, 1);
MemoryRegion *bios = g_new(MemoryRegion, 1);
Clock *cpuclk;
MIPSCPU *cpu;
CPUMIPSState *env;
ResetData *reset_info;
int bios_size;
cpuclk = clock_new(OBJECT(machine), "cpu-refclk");
#ifdef TARGET_MIPS64
clock_set_hz(cpuclk, 6000000); /* 6 MHz */
#else
clock_set_hz(cpuclk, 12000000); /* 12 MHz */
#endif
/* Init CPUs. */
cpu = MIPS_CPU(cpu_create(machine->cpu_type));
cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk);
env = &cpu->env;
reset_info = g_malloc0(sizeof(ResetData));
@@ -173,10 +177,7 @@ mips_mipssim_init(MachineState *machine)
/* Map the BIOS / boot exception handler. */
memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
/* Load a BIOS / boot exception handler image. */
if (bios_name == NULL) {
bios_name = BIOS_FILENAME;
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name ?: BIOS_FILENAME);
if (filename) {
bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE);
g_free(filename);
@@ -184,10 +185,9 @@ mips_mipssim_init(MachineState *machine)
bios_size = -1;
}
if ((bios_size < 0 || bios_size > BIOS_SIZE) &&
!kernel_filename && !qtest_enabled()) {
bios_name && !qtest_enabled()) {
/* Bail out if we have neither a kernel image nor boot vector code. */
error_report("Could not load MIPS bios '%s', and no "
"-kernel argument was specified", bios_name);
error_report("Could not load MIPS bios '%s'", bios_name);
exit(1);
} else {
/* We have a boot vector start address. */
+8 -8
View File
@@ -13,6 +13,7 @@
#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
#include "hw/clock.h"
#include "hw/mips/mips.h"
#include "hw/mips/cpudevs.h"
#include "hw/intc/i8259.h"
@@ -101,11 +102,7 @@ static int64_t load_kernel(void)
(uint64_t *)&entry, NULL,
(uint64_t *)&kernel_high, NULL, big_endian,
EM_MIPS, 1, 0);
if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000) {
entry = (int32_t)entry;
}
} else {
if (kernel_size < 0) {
error_report("could not load kernel '%s': %s",
loaderparams.kernel_filename,
load_elf_strerror(kernel_size));
@@ -118,8 +115,7 @@ static int64_t load_kernel(void)
if (loaderparams.initrd_filename) {
initrd_size = get_image_size(loaderparams.initrd_filename);
if (initrd_size > 0) {
initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) &
INITRD_PAGE_MASK;
initrd_offset = ROUND_UP(kernel_high, INITRD_PAGE_SIZE);
if (initrd_offset + initrd_size > ram_size) {
error_report("memory too small for initial ram disk '%s'",
loaderparams.initrd_filename);
@@ -182,6 +178,7 @@ void mips_r4k_init(MachineState *machine)
MemoryRegion *isa_io = g_new(MemoryRegion, 1);
MemoryRegion *isa_mem = g_new(MemoryRegion, 1);
int bios_size;
Clock *cpuclk;
MIPSCPU *cpu;
CPUMIPSState *env;
ResetData *reset_info;
@@ -192,8 +189,11 @@ void mips_r4k_init(MachineState *machine)
DriveInfo *dinfo;
int be;
cpuclk = clock_new(OBJECT(machine), "cpu-refclk");
clock_set_hz(cpuclk, 200000000); /* 200 MHz */
/* init CPUs */
cpu = MIPS_CPU(cpu_create(machine->cpu_type));
cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk);
env = &cpu->env;
reset_info = g_malloc0(sizeof(ResetData));
+13
View File
@@ -90,6 +90,19 @@ extern const VMStateDescription vmstate_clock;
*/
void clock_setup_canonical_path(Clock *clk);
/**
* clock_new:
* @parent: the clock parent
* @name: the clock object name
*
* Helper function to create a new clock and parent it to @parent. There is no
* need to call clock_setup_canonical_path on the returned clock as it is done
* by this function.
*
* @return the newly created clock
*/
Clock *clock_new(Object *parent, const char *name);
/**
* clock_set_callback:
* @clk: the clock to register the callback into
+2
View File
@@ -21,6 +21,7 @@
#define MIPS_CPS_H
#include "hw/sysbus.h"
#include "hw/clock.h"
#include "hw/misc/mips_cmgcr.h"
#include "hw/intc/mips_gic.h"
#include "hw/misc/mips_cpc.h"
@@ -43,6 +44,7 @@ struct MIPSCPSState {
MIPSGICState gic;
MIPSCPCState cpc;
MIPSITUState itu;
Clock *clock;
};
qemu_irq get_cps_irq(MIPSCPSState *cps, int pin_number);
+3 -1
View File
@@ -2,8 +2,10 @@
#define HW_MIPS_H
/* Definitions for mips board emulation. */
#include "qemu/units.h"
/* Kernels can be configured with 64KB pages */
#define INITRD_PAGE_MASK (~((1 << 16) - 1))
#define INITRD_PAGE_SIZE (64 * KiB)
#include "exec/memory.h"
+12
View File
@@ -158,6 +158,18 @@ int qemu_strtosz_metric(const char *nptr, const char **end, uint64_t *result);
char *size_to_str(uint64_t val);
/**
* freq_to_str:
* @freq_hz: frequency to stringify
*
* Return human readable string for frequency @freq_hz.
* Use SI units like KHz, MHz, and so forth.
*
* The caller is responsible for releasing the value returned
* with g_free() after use.
*/
char *freq_to_str(uint64_t freq_hz);
/* used to print char* safely */
#define STR_OR_NULL(str) ((str) ? (str) : "null")
+25
View File
@@ -203,6 +203,31 @@ static void sync_c0_entryhi(CPUMIPSState *cpu, int tc)
*tcst |= asid;
}
/* XXX: do not use a global */
uint32_t cpu_mips_get_random(CPUMIPSState *env)
{
static uint32_t seed = 1;
static uint32_t prev_idx;
uint32_t idx;
uint32_t nb_rand_tlb = env->tlb->nb_tlb - env->CP0_Wired;
if (nb_rand_tlb == 1) {
return env->tlb->nb_tlb - 1;
}
/* Don't return same value twice, so get another value */
do {
/*
* Use a simple algorithm of Linear Congruential Generator
* from ISO/IEC 9899 standard.
*/
seed = 1103515245 * seed + 12345;
idx = (seed >> 16) % nb_rand_tlb + env->CP0_Wired;
} while (idx == prev_idx);
prev_idx = idx;
return idx;
}
/* CP0 helpers */
target_ulong helper_mfc0_mvpcontrol(CPUMIPSState *env)
{
+13 -38
View File
@@ -27,43 +27,17 @@
#include "sysemu/kvm.h"
#include "internal.h"
#define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */
/* XXX: do not use a global */
uint32_t cpu_mips_get_random(CPUMIPSState *env)
{
static uint32_t seed = 1;
static uint32_t prev_idx = 0;
uint32_t idx;
uint32_t nb_rand_tlb = env->tlb->nb_tlb - env->CP0_Wired;
if (nb_rand_tlb == 1) {
return env->tlb->nb_tlb - 1;
}
/* Don't return same value twice, so get another value */
do {
/*
* Use a simple algorithm of Linear Congruential Generator
* from ISO/IEC 9899 standard.
*/
seed = 1103515245 * seed + 12345;
idx = (seed >> 16) % nb_rand_tlb + env->CP0_Wired;
} while (idx == prev_idx);
prev_idx = idx;
return idx;
}
/* MIPS R4K timer */
static void cpu_mips_timer_update(CPUMIPSState *env)
{
uint64_t now, next;
uint64_t now_ns, next_ns;
uint32_t wait;
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
wait = env->CP0_Compare - env->CP0_Count - (uint32_t)(now / TIMER_PERIOD);
next = now + (uint64_t)wait * TIMER_PERIOD;
timer_mod(env->timer, next);
now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
wait = env->CP0_Compare - env->CP0_Count -
(uint32_t)(now_ns / env->cp0_count_ns);
next_ns = now_ns + (uint64_t)wait * env->cp0_count_ns;
timer_mod(env->timer, next_ns);
}
/* Expire the timer. */
@@ -81,16 +55,16 @@ uint32_t cpu_mips_get_count(CPUMIPSState *env)
if (env->CP0_Cause & (1 << CP0Ca_DC)) {
return env->CP0_Count;
} else {
uint64_t now;
uint64_t now_ns;
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
if (timer_pending(env->timer)
&& timer_expired(env->timer, now)) {
&& timer_expired(env->timer, now_ns)) {
/* The timer has already expired. */
cpu_mips_timer_expire(env);
}
return env->CP0_Count + (uint32_t)(now / TIMER_PERIOD);
return env->CP0_Count + (uint32_t)(now_ns / env->cp0_count_ns);
}
}
@@ -106,7 +80,8 @@ void cpu_mips_store_count(CPUMIPSState *env, uint32_t count)
} else {
/* Store new count register */
env->CP0_Count = count -
(uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD);
(uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) /
env->cp0_count_ns);
/* Update timer timer */
cpu_mips_timer_update(env);
}
@@ -133,7 +108,7 @@ void cpu_mips_stop_count(CPUMIPSState *env)
{
/* Store the current value */
env->CP0_Count += (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) /
TIMER_PERIOD);
env->cp0_count_ns);
}
static void mips_timer_cb(void *opaque)
+54 -1
View File
@@ -19,14 +19,17 @@
*/
#include "qemu/osdep.h"
#include "qemu/cutils.h"
#include "qapi/error.h"
#include "cpu.h"
#include "internal.h"
#include "kvm_mips.h"
#include "qemu/module.h"
#include "sysemu/kvm.h"
#include "sysemu/qtest.h"
#include "exec/exec-all.h"
#include "hw/qdev-properties.h"
#include "hw/qdev-clock.h"
static void mips_cpu_set_pc(CPUState *cs, vaddr value)
{
@@ -134,6 +137,21 @@ static void mips_cpu_disas_set_info(CPUState *s, disassemble_info *info)
}
}
/*
* Since commit 6af0bf9c7c3 this model assumes a CPU clocked at 200MHz.
*/
#define CPU_FREQ_HZ_DEFAULT 200000000
#define CP0_COUNT_RATE_DEFAULT 2
static void mips_cp0_period_set(MIPSCPU *cpu)
{
CPUMIPSState *env = &cpu->env;
env->cp0_count_ns = cpu->cp0_count_rate
* clock_get_ns(MIPS_CPU(cpu)->clock);
assert(env->cp0_count_ns);
}
static void mips_cpu_realizefn(DeviceState *dev, Error **errp)
{
CPUState *cs = CPU(dev);
@@ -141,6 +159,20 @@ static void mips_cpu_realizefn(DeviceState *dev, Error **errp)
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev);
Error *local_err = NULL;
if (!clock_get(cpu->clock)) {
#ifndef CONFIG_USER_ONLY
if (!qtest_enabled()) {
g_autofree char *cpu_freq_str = freq_to_str(CPU_FREQ_HZ_DEFAULT);
warn_report("CPU input clock is not connected to any output clock, "
"using default frequency of %s.", cpu_freq_str);
}
#endif
/* Initialize the frequency in case the clock remains unconnected. */
clock_set_hz(cpu->clock, CPU_FREQ_HZ_DEFAULT);
}
mips_cp0_period_set(cpu);
cpu_exec_realizefn(cs, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
@@ -162,6 +194,7 @@ static void mips_cpu_initfn(Object *obj)
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(obj);
cpu_set_cpustate_pointers(cpu);
cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu);
env->cpu_model = mcc->cpu_def;
}
@@ -181,6 +214,13 @@ static ObjectClass *mips_cpu_class_by_name(const char *cpu_model)
return oc;
}
static Property mips_cpu_properties[] = {
/* CP0 timer running at half the clock of the CPU */
DEFINE_PROP_UINT32("cp0-count-rate", MIPSCPU, cp0_count_rate,
CP0_COUNT_RATE_DEFAULT),
DEFINE_PROP_END_OF_LIST()
};
static void mips_cpu_class_init(ObjectClass *c, void *data)
{
MIPSCPUClass *mcc = MIPS_CPU_CLASS(c);
@@ -190,6 +230,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
device_class_set_parent_realize(dc, mips_cpu_realizefn,
&mcc->parent_realize);
device_class_set_parent_reset(dc, mips_cpu_reset, &mcc->parent_reset);
device_class_set_props(dc, mips_cpu_properties);
cc->class_by_name = mips_cpu_class_by_name;
cc->has_work = mips_cpu_has_work;
@@ -257,3 +298,15 @@ static void mips_cpu_register_types(void)
}
type_init(mips_cpu_register_types)
/* Could be used by generic CPU object */
MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk)
{
DeviceState *cpu;
cpu = DEVICE(object_new(cpu_type));
qdev_connect_clock_in(cpu, "clk-in", cpu_refclk);
qdev_realize(cpu, NULL, &error_abort);
return MIPS_CPU(cpu);
}
+26
View File
@@ -4,6 +4,7 @@
#include "cpu-qom.h"
#include "exec/cpu-defs.h"
#include "fpu/softfloat-types.h"
#include "hw/clock.h"
#include "mips-defs.h"
#define TCG_GUEST_DEFAULT_MO (0)
@@ -1145,11 +1146,15 @@ struct CPUMIPSState {
struct MIPSITUState *itu;
MemoryRegion *itc_tag; /* ITC Configuration Tags */
target_ulong exception_base; /* ExceptionBase input to the core */
uint64_t cp0_count_ns; /* CP0_Count clock period (in nanoseconds) */
};
/**
* MIPSCPU:
* @env: #CPUMIPSState
* @clock: this CPU input clock (may be connected
* to an output clock from another device).
* @cp0_count_rate: rate at which the coprocessor 0 counter increments
*
* A MIPS CPU.
*/
@@ -1158,8 +1163,17 @@ struct MIPSCPU {
CPUState parent_obj;
/*< public >*/
Clock *clock;
CPUNegativeOffsetState neg;
CPUMIPSState env;
/*
* The Count register acts as a timer, incrementing at a constant rate,
* whether or not an instruction is executed, retired, or any forward
* progress is made through the pipeline. The rate at which the counter
* increments is implementation dependent, and is a function of the
* pipeline clock of the processor, not the issue width of the processor.
*/
unsigned cp0_count_rate;
};
@@ -1293,4 +1307,16 @@ static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
MIPS_HFLAG_HWRENA_ULR);
}
/**
* mips_cpu_create_with_clock:
* @typename: a MIPS CPU type.
* @cpu_refclk: this cpu input clock (an output clock of another device)
*
* Instantiates a MIPS CPU, set the input clock of the CPU to @cpu_refclk,
* then realizes the CPU.
*
* Returns: A #CPUState or %NULL if an error occurred.
*/
MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk);
#endif /* MIPS_CPU_H */
+163 -57
View File
@@ -983,27 +983,46 @@ uint32_t helper_float_floor_2008_w_s(CPUMIPSState *env, uint32_t fst0)
}
/* unary operations, not modifying fp status */
#define FLOAT_UNOP(name) \
uint64_t helper_float_ ## name ## _d(uint64_t fdt0) \
{ \
return float64_ ## name(fdt0); \
} \
uint32_t helper_float_ ## name ## _s(uint32_t fst0) \
{ \
return float32_ ## name(fst0); \
} \
uint64_t helper_float_ ## name ## _ps(uint64_t fdt0) \
{ \
uint32_t wt0; \
uint32_t wth0; \
\
wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF); \
wth0 = float32_ ## name(fdt0 >> 32); \
return ((uint64_t)wth0 << 32) | wt0; \
uint64_t helper_float_abs_d(uint64_t fdt0)
{
return float64_abs(fdt0);
}
uint32_t helper_float_abs_s(uint32_t fst0)
{
return float32_abs(fst0);
}
uint64_t helper_float_abs_ps(uint64_t fdt0)
{
uint32_t wt0;
uint32_t wth0;
wt0 = float32_abs(fdt0 & 0XFFFFFFFF);
wth0 = float32_abs(fdt0 >> 32);
return ((uint64_t)wth0 << 32) | wt0;
}
uint64_t helper_float_chs_d(uint64_t fdt0)
{
return float64_chs(fdt0);
}
uint32_t helper_float_chs_s(uint32_t fst0)
{
return float32_chs(fst0);
}
uint64_t helper_float_chs_ps(uint64_t fdt0)
{
uint32_t wt0;
uint32_t wth0;
wt0 = float32_chs(fdt0 & 0XFFFFFFFF);
wth0 = float32_chs(fdt0 >> 32);
return ((uint64_t)wth0 << 32) | wt0;
}
FLOAT_UNOP(abs)
FLOAT_UNOP(chs)
#undef FLOAT_UNOP
/* MIPS specific unary operations */
uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0)
@@ -1456,29 +1475,87 @@ uint64_t helper_float_mulr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1)
return ((uint64_t)fsth2 << 32) | fstl2;
}
#define FLOAT_MINMAX(name, bits, minmaxfunc) \
uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \
uint ## bits ## _t fs, \
uint ## bits ## _t ft) \
{ \
uint ## bits ## _t fdret; \
\
fdret = float ## bits ## _ ## minmaxfunc(fs, ft, \
&env->active_fpu.fp_status); \
update_fcr31(env, GETPC()); \
return fdret; \
uint32_t helper_float_max_s(CPUMIPSState *env, uint32_t fs, uint32_t ft)
{
uint32_t fdret;
fdret = float32_maxnum(fs, ft, &env->active_fpu.fp_status);
update_fcr31(env, GETPC());
return fdret;
}
FLOAT_MINMAX(max_s, 32, maxnum)
FLOAT_MINMAX(max_d, 64, maxnum)
FLOAT_MINMAX(maxa_s, 32, maxnummag)
FLOAT_MINMAX(maxa_d, 64, maxnummag)
uint64_t helper_float_max_d(CPUMIPSState *env, uint64_t fs, uint64_t ft)
{
uint64_t fdret;
fdret = float64_maxnum(fs, ft, &env->active_fpu.fp_status);
update_fcr31(env, GETPC());
return fdret;
}
uint32_t helper_float_maxa_s(CPUMIPSState *env, uint32_t fs, uint32_t ft)
{
uint32_t fdret;
fdret = float32_maxnummag(fs, ft, &env->active_fpu.fp_status);
update_fcr31(env, GETPC());
return fdret;
}
uint64_t helper_float_maxa_d(CPUMIPSState *env, uint64_t fs, uint64_t ft)
{
uint64_t fdret;
fdret = float64_maxnummag(fs, ft, &env->active_fpu.fp_status);
update_fcr31(env, GETPC());
return fdret;
}
uint32_t helper_float_min_s(CPUMIPSState *env, uint32_t fs, uint32_t ft)
{
uint32_t fdret;
fdret = float32_minnum(fs, ft, &env->active_fpu.fp_status);
update_fcr31(env, GETPC());
return fdret;
}
uint64_t helper_float_min_d(CPUMIPSState *env, uint64_t fs, uint64_t ft)
{
uint64_t fdret;
fdret = float64_minnum(fs, ft, &env->active_fpu.fp_status);
update_fcr31(env, GETPC());
return fdret;
}
uint32_t helper_float_mina_s(CPUMIPSState *env, uint32_t fs, uint32_t ft)
{
uint32_t fdret;
fdret = float32_minnummag(fs, ft, &env->active_fpu.fp_status);
update_fcr31(env, GETPC());
return fdret;
}
uint64_t helper_float_mina_d(CPUMIPSState *env, uint64_t fs, uint64_t ft)
{
uint64_t fdret;
fdret = float64_minnummag(fs, ft, &env->active_fpu.fp_status);
update_fcr31(env, GETPC());
return fdret;
}
FLOAT_MINMAX(min_s, 32, minnum)
FLOAT_MINMAX(min_d, 64, minnum)
FLOAT_MINMAX(mina_s, 32, minnummag)
FLOAT_MINMAX(mina_d, 64, minnummag)
#undef FLOAT_MINMAX
/* ternary operations */
@@ -1647,25 +1724,54 @@ uint64_t helper_float_nmsub_ps(CPUMIPSState *env, uint64_t fdt0,
}
#define FLOAT_FMADDSUB(name, bits, muladd_arg) \
uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \
uint ## bits ## _t fs, \
uint ## bits ## _t ft, \
uint ## bits ## _t fd) \
{ \
uint ## bits ## _t fdret; \
\
fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg, \
&env->active_fpu.fp_status); \
update_fcr31(env, GETPC()); \
return fdret; \
uint32_t helper_float_maddf_s(CPUMIPSState *env, uint32_t fs,
uint32_t ft, uint32_t fd)
{
uint32_t fdret;
fdret = float32_muladd(fs, ft, fd, 0,
&env->active_fpu.fp_status);
update_fcr31(env, GETPC());
return fdret;
}
uint64_t helper_float_maddf_d(CPUMIPSState *env, uint64_t fs,
uint64_t ft, uint64_t fd)
{
uint64_t fdret;
fdret = float64_muladd(fs, ft, fd, 0,
&env->active_fpu.fp_status);
update_fcr31(env, GETPC());
return fdret;
}
uint32_t helper_float_msubf_s(CPUMIPSState *env, uint32_t fs,
uint32_t ft, uint32_t fd)
{
uint32_t fdret;
fdret = float32_muladd(fs, ft, fd, float_muladd_negate_product,
&env->active_fpu.fp_status);
update_fcr31(env, GETPC());
return fdret;
}
uint64_t helper_float_msubf_d(CPUMIPSState *env, uint64_t fs,
uint64_t ft, uint64_t fd)
{
uint64_t fdret;
fdret = float64_muladd(fs, ft, fd, float_muladd_negate_product,
&env->active_fpu.fp_status);
update_fcr31(env, GETPC());
return fdret;
}
FLOAT_FMADDSUB(maddf_s, 32, 0)
FLOAT_FMADDSUB(maddf_d, 64, 0)
FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_product)
FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_product)
#undef FLOAT_FMADDSUB
/* compare operations */
#define FOP_COND_D(op, cond) \

Some files were not shown because too many files have changed in this diff Show More