diff options
-rw-r--r-- | hw/block/pflash_cfi01.c | 3 | ||||
-rw-r--r-- | hw/mips/mips_fulong2e.c | 2 | ||||
-rw-r--r-- | hw/mips/mips_malta.c | 233 | ||||
-rw-r--r-- | hw/mips/mips_mipssim.c | 2 | ||||
-rw-r--r-- | hw/mips/mips_r4k.c | 2 | ||||
-rw-r--r-- | include/hw/mips/mips.h | 3 | ||||
-rw-r--r-- | target-mips/dsp_helper.c | 22 | ||||
-rw-r--r-- | target-mips/translate.c | 62 | ||||
-rw-r--r-- | tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c | 64 | ||||
-rw-r--r-- | tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c | 4 | ||||
-rw-r--r-- | tests/tcg/mips/mips32-dsp/mulq_rs_ph.c | 19 | ||||
-rw-r--r-- | tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c | 24 |
12 files changed, 308 insertions, 132 deletions
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index 2bcd7318bc..29738598ac 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -192,6 +192,9 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset, case 0xe8: /* Write block */ /* Status register read */ ret = pfl->status; + if (width > 2) { + ret |= pfl->status << 16; + } DPRINTF("%s: status %x\n", __func__, ret); break; case 0x90: diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index a7e9dcf4bf..99014415ca 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -126,7 +126,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 + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK; + initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK; if (initrd_offset + initrd_size > ram_size) { fprintf(stderr, "qemu: memory too small for initial ram disk '%s'\n", diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index dad58c0ed2..1589b59194 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -47,6 +47,7 @@ #include "sysemu/blockdev.h" #include "exec/address-spaces.h" #include "hw/sysbus.h" /* SysBusDevice */ +#include "qemu/host-utils.h" //#define DEBUG_BOARD_INIT @@ -79,8 +80,12 @@ typedef struct { SerialState *uart; } MaltaFPGAState; +#define TYPE_MIPS_MALTA "mips-malta" +#define MIPS_MALTA(obj) OBJECT_CHECK(MaltaState, (obj), TYPE_MIPS_MALTA) + typedef struct { - SysBusDevice busdev; + SysBusDevice parent_obj; + qemu_irq *i8259; } MaltaState; @@ -144,12 +149,12 @@ struct _eeprom24c0x_t { typedef struct _eeprom24c0x_t eeprom24c0x_t; -static eeprom24c0x_t eeprom = { +static eeprom24c0x_t spd_eeprom = { .contents = { - /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00, + /* 00000000: */ 0x80,0x08,0xFF,0x0D,0x0A,0xFF,0x40,0x00, /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01, - /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00, - /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40, + /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x00,0x00, + /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0xFF, /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00, /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, @@ -165,69 +170,157 @@ static eeprom24c0x_t eeprom = { }, }; -static uint8_t eeprom24c0x_read(void) +static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size) +{ + enum { SDR = 0x4, DDR2 = 0x8 } type; + uint8_t *spd = spd_eeprom.contents; + uint8_t nbanks = 0; + uint16_t density = 0; + int i; + + /* work in terms of MB */ + ram_size >>= 20; + + while ((ram_size >= 4) && (nbanks <= 2)) { + int sz_log2 = MIN(31 - clz32(ram_size), 14); + nbanks++; + density |= 1 << (sz_log2 - 2); + ram_size -= 1 << sz_log2; + } + + /* split to 2 banks if possible */ + if ((nbanks == 1) && (density > 1)) { + nbanks++; + density >>= 1; + } + + if (density & 0xff00) { + density = (density & 0xe0) | ((density >> 8) & 0x1f); + type = DDR2; + } else if (!(density & 0x1f)) { + type = DDR2; + } else { + type = SDR; + } + + if (ram_size) { + fprintf(stderr, "Warning: SPD cannot represent final %dMB" + " of SDRAM\n", (int)ram_size); + } + + /* fill in SPD memory information */ + spd[2] = type; + spd[5] = nbanks; + spd[31] = density; + + /* checksum */ + spd[63] = 0; + for (i = 0; i < 63; i++) { + spd[63] += spd[i]; + } + + /* copy for SMBUS */ + memcpy(eeprom, spd, sizeof(spd_eeprom.contents)); +} + +static void generate_eeprom_serial(uint8_t *eeprom) +{ + int i, pos = 0; + uint8_t mac[6] = { 0x00 }; + uint8_t sn[5] = { 0x01, 0x23, 0x45, 0x67, 0x89 }; + + /* version */ + eeprom[pos++] = 0x01; + + /* count */ + eeprom[pos++] = 0x02; + + /* MAC address */ + eeprom[pos++] = 0x01; /* MAC */ + eeprom[pos++] = 0x06; /* length */ + memcpy(&eeprom[pos], mac, sizeof(mac)); + pos += sizeof(mac); + + /* serial number */ + eeprom[pos++] = 0x02; /* serial */ + eeprom[pos++] = 0x05; /* length */ + memcpy(&eeprom[pos], sn, sizeof(sn)); + pos += sizeof(sn); + + /* checksum */ + eeprom[pos] = 0; + for (i = 0; i < pos; i++) { + eeprom[pos] += eeprom[i]; + } +} + +static uint8_t eeprom24c0x_read(eeprom24c0x_t *eeprom) { logout("%u: scl = %u, sda = %u, data = 0x%02x\n", - eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data); - return eeprom.sda; + eeprom->tick, eeprom->scl, eeprom->sda, eeprom->data); + return eeprom->sda; } -static void eeprom24c0x_write(int scl, int sda) +static void eeprom24c0x_write(eeprom24c0x_t *eeprom, int scl, int sda) { - if (eeprom.scl && scl && (eeprom.sda != sda)) { + if (eeprom->scl && scl && (eeprom->sda != sda)) { logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n", - eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start"); + eeprom->tick, eeprom->scl, scl, eeprom->sda, sda, + sda ? "stop" : "start"); if (!sda) { - eeprom.tick = 1; - eeprom.command = 0; + eeprom->tick = 1; + eeprom->command = 0; } - } else if (eeprom.tick == 0 && !eeprom.ack) { + } else if (eeprom->tick == 0 && !eeprom->ack) { /* Waiting for start. */ logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n", - eeprom.tick, eeprom.scl, scl, eeprom.sda, sda); - } else if (!eeprom.scl && scl) { + eeprom->tick, eeprom->scl, scl, eeprom->sda, sda); + } else if (!eeprom->scl && scl) { logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n", - eeprom.tick, eeprom.scl, scl, eeprom.sda, sda); - if (eeprom.ack) { + eeprom->tick, eeprom->scl, scl, eeprom->sda, sda); + if (eeprom->ack) { logout("\ti2c ack bit = 0\n"); sda = 0; - eeprom.ack = 0; - } else if (eeprom.sda == sda) { + eeprom->ack = 0; + } else if (eeprom->sda == sda) { uint8_t bit = (sda != 0); logout("\ti2c bit = %d\n", bit); - if (eeprom.tick < 9) { - eeprom.command <<= 1; - eeprom.command += bit; - eeprom.tick++; - if (eeprom.tick == 9) { - logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write"); - eeprom.ack = 1; + if (eeprom->tick < 9) { + eeprom->command <<= 1; + eeprom->command += bit; + eeprom->tick++; + if (eeprom->tick == 9) { + logout("\tcommand 0x%04x, %s\n", eeprom->command, + bit ? "read" : "write"); + eeprom->ack = 1; } - } else if (eeprom.tick < 17) { - if (eeprom.command & 1) { - sda = ((eeprom.data & 0x80) != 0); + } else if (eeprom->tick < 17) { + if (eeprom->command & 1) { + sda = ((eeprom->data & 0x80) != 0); } - eeprom.address <<= 1; - eeprom.address += bit; - eeprom.tick++; - eeprom.data <<= 1; - if (eeprom.tick == 17) { - eeprom.data = eeprom.contents[eeprom.address]; - logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data); - eeprom.ack = 1; - eeprom.tick = 0; + eeprom->address <<= 1; + eeprom->address += bit; + eeprom->tick++; + eeprom->data <<= 1; + if (eeprom->tick == 17) { + eeprom->data = eeprom->contents[eeprom->address]; + logout("\taddress 0x%04x, data 0x%02x\n", + eeprom->address, eeprom->data); + eeprom->ack = 1; + eeprom->tick = 0; } - } else if (eeprom.tick >= 17) { + } else if (eeprom->tick >= 17) { sda = 0; } } else { logout("\tsda changed with raising scl\n"); } } else { - logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda); + logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom->tick, eeprom->scl, + scl, eeprom->sda, sda); } - eeprom.scl = scl; - eeprom.sda = sda; + eeprom->scl = scl; + eeprom->sda = sda; } static uint64_t malta_fpga_read(void *opaque, hwaddr addr, @@ -290,7 +383,7 @@ static uint64_t malta_fpga_read(void *opaque, hwaddr addr, /* I2CINP Register */ case 0x00b00: - val = ((s->i2cin & ~1) | eeprom24c0x_read()); + val = ((s->i2cin & ~1) | eeprom24c0x_read(&spd_eeprom)); break; /* I2COE Register */ @@ -386,7 +479,7 @@ static void malta_fpga_write(void *opaque, hwaddr addr, /* I2COUT Register */ case 0x00b10: - eeprom24c0x_write(val & 0x02, val & 0x01); + eeprom24c0x_write(&spd_eeprom, val & 0x02, val & 0x01); s->i2cout = val; break; @@ -699,7 +792,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 + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK; + initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK; if (initrd_offset + initrd_size > ram_size) { fprintf(stderr, "qemu: memory too small for initial ram disk '%s'\n", @@ -789,8 +882,10 @@ void mips_malta_init(QEMUMachineInitArgs *args) pflash_t *fl; MemoryRegion *system_memory = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); - MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1); + MemoryRegion *bios, *bios_copy = g_new(MemoryRegion, 1); target_long bios_size = FLASH_SIZE; + const size_t smbus_eeprom_size = 8 * 256; + uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size); int64_t kernel_entry; PCIBus *pci_bus; ISABus *isa_bus; @@ -808,8 +903,8 @@ void mips_malta_init(QEMUMachineInitArgs *args) int fl_sectors = bios_size >> 16; int be; - DeviceState *dev = qdev_create(NULL, "mips-malta"); - MaltaState *s = DO_UPCAST(MaltaState, busdev.qdev, dev); + DeviceState *dev = qdev_create(NULL, TYPE_MIPS_MALTA); + MaltaState *s = MIPS_MALTA(dev); qdev_init_nofail(dev); @@ -858,6 +953,10 @@ void mips_malta_init(QEMUMachineInitArgs *args) vmstate_register_ram_global(ram); memory_region_add_subregion(system_memory, 0, ram); + /* generate SPD EEPROM data */ + generate_eeprom_spd(&smbus_eeprom_buf[0 * 256], ram_size); + generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]); + #ifdef TARGET_WORDS_BIGENDIAN be = 1; #else @@ -916,8 +1015,11 @@ void mips_malta_init(QEMUMachineInitArgs *args) a neat trick which allows bi-endian firmware. */ #ifndef TARGET_WORDS_BIGENDIAN { - uint32_t *addr = memory_region_get_ram_ptr(bios); - uint32_t *end = addr + bios_size; + uint32_t *end, *addr = rom_ptr(FLASH_ADDRESS); + if (!addr) { + addr = memory_region_get_ram_ptr(bios); + } + end = (void *)addr + MIN(bios_size, 0x3e0000); while (addr < end) { bswap32s(addr); addr++; @@ -926,14 +1028,23 @@ void mips_malta_init(QEMUMachineInitArgs *args) #endif } - /* Map the BIOS at a 2nd physical location, as on the real board. */ - memory_region_init_alias(bios_alias, NULL, "bios.1fc", bios, 0, BIOS_SIZE); - memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_alias); + /* + * Map the BIOS at a 2nd physical location, as on the real board. + * Copy it so that we can patch in the MIPS revision, which cannot be + * handled by an overlapping region as the resulting ROM code subpage + * regions are not executable. + */ + memory_region_init_ram(bios_copy, NULL, "bios.1fc", BIOS_SIZE); + if (!rom_copy(memory_region_get_ram_ptr(bios_copy), + FLASH_ADDRESS, BIOS_SIZE)) { + memcpy(memory_region_get_ram_ptr(bios_copy), + memory_region_get_ram_ptr(bios), BIOS_SIZE); + } + memory_region_set_readonly(bios_copy, true); + memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_copy); - /* Board ID = 0x420 (Malta Board with CoreLV) - XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should - map to the board ID. */ - stl_p(memory_region_get_ram_ptr(bios) + 0x10, 0x00000420); + /* Board ID = 0x420 (Malta Board with CoreLV) */ + stl_p(memory_region_get_ram_ptr(bios_copy) + 0x10, 0x00000420); /* Init internal devices */ cpu_mips_irq_init_cpu(env); @@ -965,8 +1076,8 @@ void mips_malta_init(QEMUMachineInitArgs *args) pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci"); smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_get_irq(NULL, 9), NULL, 0, NULL); - /* TODO: Populate SPD eeprom data. */ - smbus_eeprom_init(smbus, 8, NULL, 0); + smbus_eeprom_init(smbus, 8, smbus_eeprom_buf, smbus_eeprom_size); + g_free(smbus_eeprom_buf); pit = pit_init(isa_bus, 0x40, 0, NULL); cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1); DMA_init(0, cpu_exit_irq); @@ -1004,7 +1115,7 @@ static void mips_malta_class_init(ObjectClass *klass, void *data) } static const TypeInfo mips_malta_device = { - .name = "mips-malta", + .name = TYPE_MIPS_MALTA, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(MaltaState), .class_init = mips_malta_class_init, diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c index e8802c128e..fea1a15916 100644 --- a/hw/mips/mips_mipssim.c +++ b/hw/mips/mips_mipssim.c @@ -83,7 +83,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 + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK; + initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK; if (initrd_offset + initrd_size > loaderparams.ram_size) { fprintf(stderr, "qemu: memory too small for initial ram disk '%s'\n", diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c index 4bc2e3fa7a..7af08b8d0f 100644 --- a/hw/mips/mips_r4k.c +++ b/hw/mips/mips_r4k.c @@ -102,7 +102,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 + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK; + initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK; if (initrd_offset + initrd_size > ram_size) { fprintf(stderr, "qemu: memory too small for initial ram disk '%s'\n", diff --git a/include/hw/mips/mips.h b/include/hw/mips/mips.h index 291e85f6b9..2a7a9c9f42 100644 --- a/include/hw/mips/mips.h +++ b/include/hw/mips/mips.h @@ -2,6 +2,9 @@ #define HW_MIPS_H /* Definitions for mips board emulation. */ +/* Kernels can be configured with 64KB pages */ +#define INITRD_PAGE_MASK (~((1 << 16) - 1)) + #include "exec/memory.h" /* gt64xxx.c */ diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index 4116de93c3..b088a25017 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -390,7 +390,7 @@ static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t b, temp = 0x7FFFFFFF; set_DSPControl_overflow_flag(1, 21, env); } else { - temp = ((int32_t)(int16_t)a * (int32_t)(int16_t)b) << 1; + temp = ((int16_t)a * (int16_t)b) << 1; } return temp; @@ -583,7 +583,7 @@ static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b, temp = (0x01ull << 63) - 1; set_DSPControl_overflow_flag(1, 16 + ac, env); } else { - temp = ((uint64_t)a * (uint64_t)b) << 1; + temp = ((int64_t)(int32_t)a * (int32_t)b) << 1; } return temp; @@ -622,7 +622,7 @@ static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b, temp = 0x7FFF0000; set_DSPControl_overflow_flag(1, 21, env); } else { - temp = (a * b) << 1; + temp = ((int16_t)a * (int16_t)b) << 1; temp = temp + 0x00008000; } @@ -648,16 +648,22 @@ static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b, static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a, CPUMIPSState *env) { - int64_t temp; + uint16_t temp; - temp = (int32_t)a + 0x00008000; - if (a > (int)0x7fff8000) { - temp = 0x7FFFFFFF; + /* + * The value 0x00008000 will be added to the input Q31 value, and the code + * needs to check if the addition causes an overflow. Since a positive value + * is added, overflow can happen in one direction only. + */ + if (a > 0x7FFF7FFF) { + temp = 0x7FFF; set_DSPControl_overflow_flag(1, 22, env); + } else { + temp = ((a + 0x8000) >> 16) & 0xFFFF; } - return (temp >> 16) & 0xFFFF; + return temp; } static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a, diff --git a/target-mips/translate.c b/target-mips/translate.c index 877f8dfe88..c1d57a791e 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -9571,8 +9571,7 @@ static void decode_i64_mips16 (DisasContext *ctx, } #endif -static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx, - int *is_branch) +static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx) { int extend = cpu_lduw_code(env, ctx->pc + 2); int op, rx, ry, funct, sa; @@ -9763,8 +9762,7 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx, return 4; } -static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, - int *is_branch) +static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) { int rx, ry; int sa; @@ -9807,7 +9805,6 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS; gen_compute_branch(ctx, op, 4, rx, ry, offset); n_bytes = 4; - *is_branch = 1; break; case M16_OPC_BEQZ: gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1); @@ -10046,9 +10043,6 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, } gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0); - if (!nd) { - *is_branch = 1; - } } break; case RR_SDBBP: @@ -10193,7 +10187,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, } break; case M16_OPC_EXTEND: - decode_extended_mips16_opc(env, ctx, is_branch); + decode_extended_mips16_opc(env, ctx); n_bytes = 4; break; #if defined(TARGET_MIPS64) @@ -10802,7 +10796,7 @@ static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist, } -static void gen_pool16c_insn(DisasContext *ctx, int *is_branch) +static void gen_pool16c_insn(DisasContext *ctx) { int rd = mmreg((ctx->opcode >> 3) & 0x7); int rs = mmreg(ctx->opcode & 0x7); @@ -10864,7 +10858,6 @@ static void gen_pool16c_insn(DisasContext *ctx, int *is_branch) gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0); } - *is_branch = 1; break; case JRC16 + 0: case JRC16 + 1: @@ -10889,7 +10882,6 @@ static void gen_pool16c_insn(DisasContext *ctx, int *is_branch) gen_compute_branch(ctx, opc, 2, reg, 31, 0); } - *is_branch = 1; break; case MFHI16 + 0: case MFHI16 + 1: @@ -11020,8 +11012,7 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, tcg_temp_free(t1); } -static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs, - int *is_branch) +static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs) { int extension = (ctx->opcode >> 6) & 0x3f; int minor = (ctx->opcode >> 12) & 0xf; @@ -11147,12 +11138,10 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs, case JALR: case JALR_HB: gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0); - *is_branch = 1; break; case JALRS: case JALRS_HB: gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0); - *is_branch = 1; break; default: goto pool32axf_invalid; @@ -11551,7 +11540,7 @@ static void gen_pool32fxf(DisasContext *ctx, int rt, int rs) } static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, - uint16_t insn_hw1, int *is_branch) + uint16_t insn_hw1) { int32_t offset; uint16_t insn; @@ -11685,7 +11674,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd); return; case POOL32AXF: - gen_pool32axf(env, ctx, rt, rs, is_branch); + gen_pool32axf(env, ctx, rt, rs); break; case 0x07: generate_exception(ctx, EXCP_BREAK); @@ -12048,7 +12037,6 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, mips32_op = OPC_BGTZ; do_branch: gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1); - *is_branch = 1; break; /* Traps */ @@ -12109,7 +12097,6 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, do_cp1branch: gen_compute_branch1(ctx, mips32_op, (ctx->opcode >> 18) & 0x7, imm << 1); - *is_branch = 1; break; case BPOSGE64: case BPOSGE32: @@ -12216,30 +12203,24 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, case JALX32: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset); - *is_branch = 1; break; case JALS32: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1; gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset); - *is_branch = 1; break; case BEQ32: gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1); - *is_branch = 1; break; case BNE32: gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1); - *is_branch = 1; break; case J32: gen_compute_branch(ctx, OPC_J, 4, rt, rs, (int32_t)(ctx->opcode & 0x3FFFFFF) << 1); - *is_branch = 1; break; case JAL32: gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, (int32_t)(ctx->opcode & 0x3FFFFFF) << 1); - *is_branch = 1; break; /* Floating point (COP1) */ case LWC132: @@ -12309,7 +12290,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, } } -static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) +static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx) { uint32_t op; @@ -12442,7 +12423,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b } break; case POOL16C: - gen_pool16c_insn(ctx, is_branch); + gen_pool16c_insn(ctx); break; case LWGP16: { @@ -12582,14 +12563,12 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b case B16: gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, SIMM(ctx->opcode, 0, 10) << 1); - *is_branch = 1; break; case BNEZ16: case BEQZ16: gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2, mmreg(uMIPS_RD(ctx->opcode)), 0, SIMM(ctx->opcode, 0, 7) << 1); - *is_branch = 1; break; case LI16: { @@ -12610,7 +12589,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b generate_exception(ctx, EXCP_RI); break; default: - decode_micromips32_opc (env, ctx, op, is_branch); + decode_micromips32_opc (env, ctx, op); return 4; } @@ -14346,7 +14325,7 @@ static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, /* End MIPSDSP functions. */ -static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) +static void decode_opc (CPUMIPSState *env, DisasContext *ctx) { int32_t offset; int rs, rt, rd, sa; @@ -14460,7 +14439,6 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) break; case OPC_JR ... OPC_JALR: gen_compute_branch(ctx, op1, 4, rs, rd, sa); - *is_branch = 1; break; case OPC_TGE ... OPC_TEQ: /* Traps */ case OPC_TNE: @@ -15227,7 +15205,6 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */ case OPC_BLTZAL ... OPC_BGEZALL: gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2); - *is_branch = 1; break; case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */ case OPC_TNEI: @@ -15243,7 +15220,6 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) #endif check_dsp(ctx); gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2); - *is_branch = 1; break; default: /* Invalid */ MIPS_INVAL("regimm"); @@ -15355,12 +15331,10 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_J ... OPC_JAL: /* Jump */ offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; gen_compute_branch(ctx, op, 4, rs, rt, offset); - *is_branch = 1; break; case OPC_BEQ ... OPC_BGTZ: /* Branch */ case OPC_BEQL ... OPC_BGTZL: gen_compute_branch(ctx, op, 4, rs, rt, imm << 2); - *is_branch = 1; break; case OPC_LB ... OPC_LWR: /* Load and stores */ case OPC_LL: @@ -15420,7 +15394,6 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_BC1: gen_compute_branch1(ctx, MASK_BC1(ctx->opcode), (rt >> 2) & 0x7, imm << 2); - *is_branch = 1; break; case OPC_S_FMT: case OPC_D_FMT: @@ -15527,7 +15500,6 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS); offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; gen_compute_branch(ctx, op, 4, rs, rt, offset); - *is_branch = 1; break; case OPC_MDMX: check_insn(ctx, ASE_MDMX); @@ -15553,7 +15525,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, int num_insns; int max_insns; int insn_bytes; - int is_branch; + int is_delay; if (search_pc) qemu_log("search pc %d\n", search_pc); @@ -15611,23 +15583,23 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) gen_io_start(); - is_branch = 0; + is_delay = ctx.hflags & MIPS_HFLAG_BMASK; if (!(ctx.hflags & MIPS_HFLAG_M16)) { ctx.opcode = cpu_ldl_code(env, ctx.pc); insn_bytes = 4; - decode_opc(env, &ctx, &is_branch); + decode_opc(env, &ctx); } else if (ctx.insn_flags & ASE_MICROMIPS) { ctx.opcode = cpu_lduw_code(env, ctx.pc); - insn_bytes = decode_micromips_opc(env, &ctx, &is_branch); + insn_bytes = decode_micromips_opc(env, &ctx); } else if (ctx.insn_flags & ASE_MIPS16) { ctx.opcode = cpu_lduw_code(env, ctx.pc); - insn_bytes = decode_mips16_opc(env, &ctx, &is_branch); + insn_bytes = decode_mips16_opc(env, &ctx); } else { generate_exception(&ctx, EXCP_RI); ctx.bstate = BS_STOP; break; } - if (!is_branch) { + if (is_delay) { handle_delay_slot(&ctx, insn_bytes); } ctx.pc += insn_bytes; diff --git a/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c b/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c index ce864844d9..cbf900713f 100644 --- a/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c +++ b/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c @@ -14,7 +14,7 @@ int main() resultdsp = 0x01; __asm ("mthi %0, $ac1\n\t" - "mtlo %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" "dpaq_sa.l.w $ac1, %3, %4\n\t" "mfhi %0, $ac1\n\t" "mflo %1, $ac1\n\t" @@ -27,8 +27,8 @@ int main() assert(ach == resulth); assert(acl == resultl); - ach = 0x12; - acl = 0x48; + ach = 0x00000012; + acl = 0x00000048; rs = 0x80000000; rt = 0x80000000; @@ -37,7 +37,7 @@ int main() resultdsp = 0x01; __asm ("mthi %0, $ac1\n\t" - "mtlo %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" "dpaq_sa.l.w $ac1, %3, %4\n\t" "mfhi %0, $ac1\n\t" "mflo %1, $ac1\n\t" @@ -51,16 +51,64 @@ int main() assert(acl == resultl); ach = 0x741532A0; - acl = 0xfceabb08; + acl = 0xFCEABB08; rs = 0x80000000; rt = 0x80000000; - resulth = 0x7fffffff; - resultl = 0xffffffff; + resulth = 0x7FFFFFFF; + resultl = 0xFFFFFFFF; resultdsp = 0x01; __asm ("mthi %0, $ac1\n\t" - "mtlo %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpaq_sa.l.w $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + ach = 0; + acl = 0; + rs = 0xC0000000; + rt = 0x7FFFFFFF; + + resulth = 0xC0000000; + resultl = 0x80000000; + resultdsp = 0; + __asm + ("wrdsp $0\n\t" + "mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpaq_sa.l.w $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + ach = 0x20000000; + acl = 0; + rs = 0xE0000000; + rt = 0x7FFFFFFF; + + resulth = 0; + resultl = 0x40000000; + resultdsp = 0; + __asm + ("wrdsp $0\n\t" + "mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" "dpaq_sa.l.w $ac1, %3, %4\n\t" "mfhi %0, $ac1\n\t" "mflo %1, $ac1\n\t" diff --git a/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c b/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c index b7b73fdb66..eda3b14e2b 100644 --- a/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c +++ b/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c @@ -9,8 +9,8 @@ int main() rs = 0xBC0123AD; rt = 0x01643721; - resulth = 0xfdf4cbe0; - resultl = 0xd138776b; + resulth = 0x00BD3A22; + resultl = 0xD138776B; resultdsp = 0x00; __asm ("mthi %0, $ac1\n\t" diff --git a/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c b/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c index c7206039ea..370c2a8018 100644 --- a/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c +++ b/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c @@ -12,7 +12,24 @@ int main() resultdsp = 1; __asm - ("mulq_rs.ph %0, %2, %3\n\t" + ("wrdsp $0\n\t" + "mulq_rs.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + rs = 0x80011234; + rt = 0x80024321; + result = 0x7FFD098C; + resultdsp = 0; + + __asm + ("wrdsp $0\n\t" + "mulq_rs.ph %0, %2, %3\n\t" "rddsp %1\n\t" : "=r"(rd), "=r"(dsp) : "r"(rs), "r"(rt) diff --git a/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c b/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c index 3535b37a58..da6845bf24 100644 --- a/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c +++ b/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c @@ -12,18 +12,34 @@ int main() result = 0x12348765; __asm - ("precrq_rs.ph.w %0, %1, %2\n\t" + ("wrdsp $0\n\t" + "precrq_rs.ph.w %0, %1, %2\n\t" : "=r"(rd) : "r"(rs), "r"(rt) ); assert(result == rd); - rs = 0x7fffC678; + rs = 0x7FFFC678; rt = 0x865432A0; - result = 0x7fff8654; + result = 0x7FFF8654; __asm - ("precrq_rs.ph.w %0, %2, %3\n\t" + ("wrdsp $0\n\t" + "precrq_rs.ph.w %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + assert(((dsp >> 22) & 0x01) == 1); + assert(result == rd); + + rs = 0xBEEFFEED; + rt = 0x7FFF8000; + result = 0xBEF07FFF; + + __asm + ("wrdsp $0\n\t" + "precrq_rs.ph.w %0, %2, %3\n\t" "rddsp %1\n\t" : "=r"(rd), "=r"(dsp) : "r"(rs), "r"(rt) |