Fourth RISC-V PR for QEMU 7.1
* Update MAINTAINERS * Add support for Zmmul extension * Fixup FDT errors when supplying device tree from the command line for virt machine * Avoid overflowing the addr_config buffer in the SiFive PLIC * Support -device loader addresses above 2GB * Correctly wake from WFI on VS-level external interrupts * Fixes for RV128 support * Support Vector extension tail agnostic setting elements' bits to all 1s * Don't expose the CPU properties on named CPUs * Fix vector extension assert for RV32 -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEE9sSsRtSTSGjTuM6PIeENKd+XcFQFAmKix74ACgkQIeENKd+X cFTKdgf8DP85Mf91+m1Dd1zji6d4JiFa+i7wer5T6la7qQAiIbyyq6kax0K31YYF QuX3x7i9erF8Z/kox3MlYjjytPS0iJK9+Fica1ttslBJLv/o2K7SAaLmUwS65AB5 rHjRCWDdeA3zPv7tcHEIpYZNFb163N2ZYqhmTTmL6Q0KTaa73OWKuJIbJzB8iT85 LH1cUTfCEWNzsG0PLAD4Xh4ug4Hq6sW54NXXMDZiDSVak/FdNSEzuUMUsNW12XA1 ib1uhfygHGYfSXFUgYmCiHK7iEey7A9IZtGKdNIXObx1/QVOrvyW+E90XRQqEHHC XeOkdTUB2YfPsC0Qs4VVqsVEQVjUCw== =gz3H -----END PGP SIGNATURE----- Merge tag 'pull-riscv-to-apply-20220610' of github.com:alistair23/qemu into staging Fourth RISC-V PR for QEMU 7.1 * Update MAINTAINERS * Add support for Zmmul extension * Fixup FDT errors when supplying device tree from the command line for virt machine * Avoid overflowing the addr_config buffer in the SiFive PLIC * Support -device loader addresses above 2GB * Correctly wake from WFI on VS-level external interrupts * Fixes for RV128 support * Support Vector extension tail agnostic setting elements' bits to all 1s * Don't expose the CPU properties on named CPUs * Fix vector extension assert for RV32 # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCAAdFiEE9sSsRtSTSGjTuM6PIeENKd+XcFQFAmKix74ACgkQIeENKd+X # cFTKdgf8DP85Mf91+m1Dd1zji6d4JiFa+i7wer5T6la7qQAiIbyyq6kax0K31YYF # QuX3x7i9erF8Z/kox3MlYjjytPS0iJK9+Fica1ttslBJLv/o2K7SAaLmUwS65AB5 # rHjRCWDdeA3zPv7tcHEIpYZNFb163N2ZYqhmTTmL6Q0KTaa73OWKuJIbJzB8iT85 # LH1cUTfCEWNzsG0PLAD4Xh4ug4Hq6sW54NXXMDZiDSVak/FdNSEzuUMUsNW12XA1 # ib1uhfygHGYfSXFUgYmCiHK7iEey7A9IZtGKdNIXObx1/QVOrvyW+E90XRQqEHHC # XeOkdTUB2YfPsC0Qs4VVqsVEQVjUCw== # =gz3H # -----END PGP SIGNATURE----- # gpg: Signature made Thu 09 Jun 2022 09:25:34 PM PDT # gpg: using RSA key F6C4AC46D4934868D3B8CE8F21E10D29DF977054 # gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: F6C4 AC46 D493 4868 D3B8 CE8F 21E1 0D29 DF97 7054 * tag 'pull-riscv-to-apply-20220610' of github.com:alistair23/qemu: (25 commits) target/riscv: trans_rvv: Avoid assert for RV32 and e64 target/riscv: Don't expose the CPU properties on names CPUs target/riscv: rvv: Add option 'rvv_ta_all_1s' to enable optional tail agnostic behavior target/riscv: rvv: Add tail agnostic for vector permutation instructions target/riscv: rvv: Add tail agnostic for vector mask instructions target/riscv: rvv: Add tail agnostic for vector reduction instructions target/riscv: rvv: Add tail agnostic for vector floating-point instructions target/riscv: rvv: Add tail agnostic for vector fix-point arithmetic instructions target/riscv: rvv: Add tail agnostic for vector integer merge and move instructions target/riscv: rvv: Add tail agnostic for vector integer comparison instructions target/riscv: rvv: Add tail agnostic for vector integer shift instructions target/riscv: rvv: Add tail agnostic for vx, vvm, vxm instructions target/riscv: rvv: Add tail agnostic for vector load / store instructions target/riscv: rvv: Add tail agnostic for vv instructions target/riscv: rvv: Early exit when vstart >= vl target/riscv: rvv: Rename ambiguous esz target/riscv: rvv: Prune redundant access_type parameter passed target/riscv: rvv: Prune redundant ESZ, DSZ parameter passed target/riscv/debug.c: keep experimental rv128 support working target/riscv: Wake on VS-level external interrupts ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
b3cd3b5a66
|
@ -2198,6 +2198,7 @@ Generic Loader
|
|||
M: Alistair Francis <alistair@alistair23.me>
|
||||
S: Maintained
|
||||
F: hw/core/generic-loader.c
|
||||
F: hw/core/uboot_image.h
|
||||
F: include/hw/core/generic-loader.h
|
||||
F: docs/system/generic-loader.rst
|
||||
|
||||
|
|
|
@ -570,7 +570,7 @@ static void armv7m_reset(void *opaque)
|
|||
|
||||
void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
|
||||
{
|
||||
int image_size;
|
||||
ssize_t image_size;
|
||||
uint64_t entry;
|
||||
int big_endian;
|
||||
AddressSpace *as;
|
||||
|
|
|
@ -881,7 +881,7 @@ static int do_arm_linux_init(Object *obj, void *opaque)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
|
||||
static ssize_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
|
||||
uint64_t *lowaddr, uint64_t *highaddr,
|
||||
int elf_machine, AddressSpace *as)
|
||||
{
|
||||
|
@ -892,7 +892,7 @@ static int64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
|
|||
} elf_header;
|
||||
int data_swab = 0;
|
||||
bool big_endian;
|
||||
int64_t ret = -1;
|
||||
ssize_t ret = -1;
|
||||
Error *err = NULL;
|
||||
|
||||
|
||||
|
@ -1014,7 +1014,7 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
|
|||
/* Set up for a direct boot of a kernel image file. */
|
||||
CPUState *cs;
|
||||
AddressSpace *as = arm_boot_address_space(cpu, info);
|
||||
int kernel_size;
|
||||
ssize_t kernel_size;
|
||||
int initrd_size;
|
||||
int is_linux = 0;
|
||||
uint64_t elf_entry;
|
||||
|
@ -1093,7 +1093,7 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
|
|||
|
||||
if (kernel_size > info->ram_size) {
|
||||
error_report("kernel '%s' is too large to fit in RAM "
|
||||
"(kernel size %d, RAM size %" PRId64 ")",
|
||||
"(kernel size %zd, RAM size %" PRId64 ")",
|
||||
info->kernel_filename, kernel_size, info->ram_size);
|
||||
exit(1);
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ static void generic_loader_realize(DeviceState *dev, Error **errp)
|
|||
GenericLoaderState *s = GENERIC_LOADER(dev);
|
||||
hwaddr entry;
|
||||
int big_endian;
|
||||
int size = 0;
|
||||
ssize_t size = 0;
|
||||
|
||||
s->set_pc = false;
|
||||
|
||||
|
|
|
@ -114,17 +114,17 @@ ssize_t read_targphys(const char *name,
|
|||
return did;
|
||||
}
|
||||
|
||||
int load_image_targphys(const char *filename,
|
||||
hwaddr addr, uint64_t max_sz)
|
||||
ssize_t load_image_targphys(const char *filename,
|
||||
hwaddr addr, uint64_t max_sz)
|
||||
{
|
||||
return load_image_targphys_as(filename, addr, max_sz, NULL);
|
||||
}
|
||||
|
||||
/* return the size or -1 if error */
|
||||
int load_image_targphys_as(const char *filename,
|
||||
hwaddr addr, uint64_t max_sz, AddressSpace *as)
|
||||
ssize_t load_image_targphys_as(const char *filename,
|
||||
hwaddr addr, uint64_t max_sz, AddressSpace *as)
|
||||
{
|
||||
int size;
|
||||
ssize_t size;
|
||||
|
||||
size = get_image_size(filename);
|
||||
if (size < 0 || size > max_sz) {
|
||||
|
@ -138,9 +138,9 @@ int load_image_targphys_as(const char *filename,
|
|||
return size;
|
||||
}
|
||||
|
||||
int load_image_mr(const char *filename, MemoryRegion *mr)
|
||||
ssize_t load_image_mr(const char *filename, MemoryRegion *mr)
|
||||
{
|
||||
int size;
|
||||
ssize_t size;
|
||||
|
||||
if (!memory_access_is_direct(mr, false)) {
|
||||
/* Can only load an image into RAM or ROM */
|
||||
|
@ -222,8 +222,8 @@ static void bswap_ahdr(struct exec *e)
|
|||
: (_N_SEGMENT_ROUND (_N_TXTENDADDR(x, target_page_size), target_page_size)))
|
||||
|
||||
|
||||
int load_aout(const char *filename, hwaddr addr, int max_sz,
|
||||
int bswap_needed, hwaddr target_page_size)
|
||||
ssize_t load_aout(const char *filename, hwaddr addr, int max_sz,
|
||||
int bswap_needed, hwaddr target_page_size)
|
||||
{
|
||||
int fd;
|
||||
ssize_t size, ret;
|
||||
|
@ -617,13 +617,14 @@ toosmall:
|
|||
}
|
||||
|
||||
/* Load a U-Boot image. */
|
||||
static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,
|
||||
int *is_linux, uint8_t image_type,
|
||||
uint64_t (*translate_fn)(void *, uint64_t),
|
||||
void *translate_opaque, AddressSpace *as)
|
||||
static ssize_t load_uboot_image(const char *filename, hwaddr *ep,
|
||||
hwaddr *loadaddr, int *is_linux,
|
||||
uint8_t image_type,
|
||||
uint64_t (*translate_fn)(void *, uint64_t),
|
||||
void *translate_opaque, AddressSpace *as)
|
||||
{
|
||||
int fd;
|
||||
int size;
|
||||
ssize_t size;
|
||||
hwaddr address;
|
||||
uboot_image_header_t h;
|
||||
uboot_image_header_t *hdr = &h;
|
||||
|
@ -760,40 +761,40 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int load_uimage(const char *filename, hwaddr *ep, hwaddr *loadaddr,
|
||||
int *is_linux,
|
||||
uint64_t (*translate_fn)(void *, uint64_t),
|
||||
void *translate_opaque)
|
||||
ssize_t load_uimage(const char *filename, hwaddr *ep, hwaddr *loadaddr,
|
||||
int *is_linux,
|
||||
uint64_t (*translate_fn)(void *, uint64_t),
|
||||
void *translate_opaque)
|
||||
{
|
||||
return load_uboot_image(filename, ep, loadaddr, is_linux, IH_TYPE_KERNEL,
|
||||
translate_fn, translate_opaque, NULL);
|
||||
}
|
||||
|
||||
int load_uimage_as(const char *filename, hwaddr *ep, hwaddr *loadaddr,
|
||||
int *is_linux,
|
||||
uint64_t (*translate_fn)(void *, uint64_t),
|
||||
void *translate_opaque, AddressSpace *as)
|
||||
ssize_t load_uimage_as(const char *filename, hwaddr *ep, hwaddr *loadaddr,
|
||||
int *is_linux,
|
||||
uint64_t (*translate_fn)(void *, uint64_t),
|
||||
void *translate_opaque, AddressSpace *as)
|
||||
{
|
||||
return load_uboot_image(filename, ep, loadaddr, is_linux, IH_TYPE_KERNEL,
|
||||
translate_fn, translate_opaque, as);
|
||||
}
|
||||
|
||||
/* Load a ramdisk. */
|
||||
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
|
||||
ssize_t load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
|
||||
{
|
||||
return load_ramdisk_as(filename, addr, max_sz, NULL);
|
||||
}
|
||||
|
||||
int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
|
||||
AddressSpace *as)
|
||||
ssize_t load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
|
||||
AddressSpace *as)
|
||||
{
|
||||
return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK,
|
||||
NULL, NULL, as);
|
||||
}
|
||||
|
||||
/* Load a gzip-compressed kernel to a dynamically allocated buffer. */
|
||||
int load_image_gzipped_buffer(const char *filename, uint64_t max_sz,
|
||||
uint8_t **buffer)
|
||||
ssize_t load_image_gzipped_buffer(const char *filename, uint64_t max_sz,
|
||||
uint8_t **buffer)
|
||||
{
|
||||
uint8_t *compressed_data = NULL;
|
||||
uint8_t *data = NULL;
|
||||
|
@ -838,9 +839,9 @@ int load_image_gzipped_buffer(const char *filename, uint64_t max_sz,
|
|||
}
|
||||
|
||||
/* Load a gzip-compressed kernel. */
|
||||
int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz)
|
||||
ssize_t load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz)
|
||||
{
|
||||
int bytes;
|
||||
ssize_t bytes;
|
||||
uint8_t *data;
|
||||
|
||||
bytes = load_image_gzipped_buffer(filename, max_sz, &data);
|
||||
|
@ -970,14 +971,15 @@ static void *rom_set_mr(Rom *rom, Object *owner, const char *name, bool ro)
|
|||
return data;
|
||||
}
|
||||
|
||||
int rom_add_file(const char *file, const char *fw_dir,
|
||||
hwaddr addr, int32_t bootindex,
|
||||
bool option_rom, MemoryRegion *mr,
|
||||
AddressSpace *as)
|
||||
ssize_t rom_add_file(const char *file, const char *fw_dir,
|
||||
hwaddr addr, int32_t bootindex,
|
||||
bool option_rom, MemoryRegion *mr,
|
||||
AddressSpace *as)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
|
||||
Rom *rom;
|
||||
int rc, fd = -1;
|
||||
ssize_t rc;
|
||||
int fd = -1;
|
||||
char devpath[100];
|
||||
|
||||
if (as && mr) {
|
||||
|
@ -1019,7 +1021,7 @@ int rom_add_file(const char *file, const char *fw_dir,
|
|||
lseek(fd, 0, SEEK_SET);
|
||||
rc = read(fd, rom->data, rom->datasize);
|
||||
if (rc != rom->datasize) {
|
||||
fprintf(stderr, "rom: file %-20s: read error: rc=%d (expected %zd)\n",
|
||||
fprintf(stderr, "rom: file %-20s: read error: rc=%zd (expected %zd)\n",
|
||||
rom->name, rc, rom->datasize);
|
||||
goto err;
|
||||
}
|
||||
|
@ -1138,12 +1140,12 @@ int rom_add_elf_program(const char *name, GMappedFile *mapped_file, void *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int rom_add_vga(const char *file)
|
||||
ssize_t rom_add_vga(const char *file)
|
||||
{
|
||||
return rom_add_file(file, "vgaroms", 0, -1, true, NULL, NULL);
|
||||
}
|
||||
|
||||
int rom_add_option(const char *file, int32_t bootindex)
|
||||
ssize_t rom_add_option(const char *file, int32_t bootindex)
|
||||
{
|
||||
return rom_add_file(file, "genroms", 0, bootindex, true, NULL, NULL);
|
||||
}
|
||||
|
@ -1846,11 +1848,12 @@ out:
|
|||
}
|
||||
|
||||
/* return size or -1 if error */
|
||||
int load_targphys_hex_as(const char *filename, hwaddr *entry, AddressSpace *as)
|
||||
ssize_t load_targphys_hex_as(const char *filename, hwaddr *entry,
|
||||
AddressSpace *as)
|
||||
{
|
||||
gsize hex_blob_size;
|
||||
gchar *hex_blob;
|
||||
int total_size = 0;
|
||||
ssize_t total_size = 0;
|
||||
|
||||
if (!g_file_get_contents(filename, &hex_blob, &hex_blob_size, NULL)) {
|
||||
return -1;
|
||||
|
|
|
@ -1115,7 +1115,7 @@ void x86_bios_rom_init(MachineState *ms, const char *default_firmware,
|
|||
char *filename;
|
||||
MemoryRegion *bios, *isa_bios;
|
||||
int bios_size, isa_bios_size;
|
||||
int ret;
|
||||
ssize_t ret;
|
||||
|
||||
/* BIOS load */
|
||||
bios_name = ms->firmware ?: default_firmware;
|
||||
|
|
|
@ -431,7 +431,7 @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
|
|||
uint32_t context_stride, uint32_t aperture_size)
|
||||
{
|
||||
DeviceState *dev = qdev_new(TYPE_SIFIVE_PLIC);
|
||||
int i, j = 0;
|
||||
int i;
|
||||
SiFivePLICState *plic;
|
||||
|
||||
assert(enable_stride == (enable_stride & -enable_stride));
|
||||
|
@ -451,18 +451,17 @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
|
|||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
|
||||
|
||||
plic = SIFIVE_PLIC(dev);
|
||||
for (i = 0; i < num_harts; i++) {
|
||||
CPUState *cpu = qemu_get_cpu(hartid_base + i);
|
||||
|
||||
if (plic->addr_config[j].mode == PLICMode_M) {
|
||||
j++;
|
||||
qdev_connect_gpio_out(dev, num_harts + i,
|
||||
for (i = 0; i < plic->num_addrs; i++) {
|
||||
int cpu_num = plic->addr_config[i].hartid;
|
||||
CPUState *cpu = qemu_get_cpu(hartid_base + cpu_num);
|
||||
|
||||
if (plic->addr_config[i].mode == PLICMode_M) {
|
||||
qdev_connect_gpio_out(dev, num_harts + cpu_num,
|
||||
qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT));
|
||||
}
|
||||
|
||||
if (plic->addr_config[j].mode == PLICMode_S) {
|
||||
j++;
|
||||
qdev_connect_gpio_out(dev, i,
|
||||
if (plic->addr_config[i].mode == PLICMode_S) {
|
||||
qdev_connect_gpio_out(dev, cpu_num,
|
||||
qdev_get_gpio_in(DEVICE(cpu), IRQ_S_EXT));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,7 +129,8 @@ target_ulong riscv_load_firmware(const char *firmware_filename,
|
|||
hwaddr firmware_load_addr,
|
||||
symbol_fn_t sym_cb)
|
||||
{
|
||||
uint64_t firmware_entry, firmware_size, firmware_end;
|
||||
uint64_t firmware_entry, firmware_end;
|
||||
ssize_t firmware_size;
|
||||
|
||||
if (load_elf_ram_sym(firmware_filename, NULL, NULL, NULL,
|
||||
&firmware_entry, NULL, &firmware_end, NULL,
|
||||
|
@ -185,7 +186,7 @@ target_ulong riscv_load_kernel(const char *kernel_filename,
|
|||
hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size,
|
||||
uint64_t kernel_entry, hwaddr *start)
|
||||
{
|
||||
int size;
|
||||
ssize_t size;
|
||||
|
||||
/*
|
||||
* We want to put the initrd far enough into RAM that when the
|
||||
|
|
|
@ -975,6 +975,23 @@ static void create_fdt_flash(RISCVVirtState *s, const MemMapEntry *memmap)
|
|||
g_free(name);
|
||||
}
|
||||
|
||||
static void create_fdt_fw_cfg(RISCVVirtState *s, const MemMapEntry *memmap)
|
||||
{
|
||||
char *nodename;
|
||||
MachineState *mc = MACHINE(s);
|
||||
hwaddr base = memmap[VIRT_FW_CFG].base;
|
||||
hwaddr size = memmap[VIRT_FW_CFG].size;
|
||||
|
||||
nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
|
||||
qemu_fdt_add_subnode(mc->fdt, nodename);
|
||||
qemu_fdt_setprop_string(mc->fdt, nodename,
|
||||
"compatible", "qemu,fw-cfg-mmio");
|
||||
qemu_fdt_setprop_sized_cells(mc->fdt, nodename, "reg",
|
||||
2, base, 2, size);
|
||||
qemu_fdt_setprop(mc->fdt, nodename, "dma-coherent", NULL, 0);
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
|
||||
uint64_t mem_size, const char *cmdline, bool is_32_bit)
|
||||
{
|
||||
|
@ -1023,6 +1040,7 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
|
|||
create_fdt_rtc(s, memmap, irq_mmio_phandle);
|
||||
|
||||
create_fdt_flash(s, memmap);
|
||||
create_fdt_fw_cfg(s, memmap);
|
||||
|
||||
update_bootargs:
|
||||
if (cmdline && *cmdline) {
|
||||
|
@ -1082,22 +1100,12 @@ static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem,
|
|||
static FWCfgState *create_fw_cfg(const MachineState *mc)
|
||||
{
|
||||
hwaddr base = virt_memmap[VIRT_FW_CFG].base;
|
||||
hwaddr size = virt_memmap[VIRT_FW_CFG].size;
|
||||
FWCfgState *fw_cfg;
|
||||
char *nodename;
|
||||
|
||||
fw_cfg = fw_cfg_init_mem_wide(base + 8, base, 8, base + 16,
|
||||
&address_space_memory);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)mc->smp.cpus);
|
||||
|
||||
nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
|
||||
qemu_fdt_add_subnode(mc->fdt, nodename);
|
||||
qemu_fdt_setprop_string(mc->fdt, nodename,
|
||||
"compatible", "qemu,fw-cfg-mmio");
|
||||
qemu_fdt_setprop_sized_cells(mc->fdt, nodename, "reg",
|
||||
2, base, 2, size);
|
||||
qemu_fdt_setprop(mc->fdt, nodename, "dma-coherent", NULL, 0);
|
||||
g_free(nodename);
|
||||
return fw_cfg;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,8 +40,8 @@ ssize_t load_image_size(const char *filename, void *addr, size_t size);
|
|||
*
|
||||
* Returns the size of the loaded image on success, -1 otherwise.
|
||||
*/
|
||||
int load_image_targphys_as(const char *filename,
|
||||
hwaddr addr, uint64_t max_sz, AddressSpace *as);
|
||||
ssize_t load_image_targphys_as(const char *filename,
|
||||
hwaddr addr, uint64_t max_sz, AddressSpace *as);
|
||||
|
||||
/**load_targphys_hex_as:
|
||||
* @filename: Path to the .hex file
|
||||
|
@ -53,14 +53,15 @@ int load_image_targphys_as(const char *filename,
|
|||
*
|
||||
* Returns the size of the loaded .hex file on success, -1 otherwise.
|
||||
*/
|
||||
int load_targphys_hex_as(const char *filename, hwaddr *entry, AddressSpace *as);
|
||||
ssize_t load_targphys_hex_as(const char *filename, hwaddr *entry,
|
||||
AddressSpace *as);
|
||||
|
||||
/** load_image_targphys:
|
||||
* Same as load_image_targphys_as(), but doesn't allow the caller to specify
|
||||
* an AddressSpace.
|
||||
*/
|
||||
int load_image_targphys(const char *filename, hwaddr,
|
||||
uint64_t max_sz);
|
||||
ssize_t load_image_targphys(const char *filename, hwaddr,
|
||||
uint64_t max_sz);
|
||||
|
||||
/**
|
||||
* load_image_mr: load an image into a memory region
|
||||
|
@ -73,7 +74,7 @@ int load_image_targphys(const char *filename, hwaddr,
|
|||
* If the file is larger than the memory region's size the call will fail.
|
||||
* Returns -1 on failure, or the size of the file.
|
||||
*/
|
||||
int load_image_mr(const char *filename, MemoryRegion *mr);
|
||||
ssize_t load_image_mr(const char *filename, MemoryRegion *mr);
|
||||
|
||||
/* This is the limit on the maximum uncompressed image size that
|
||||
* load_image_gzipped_buffer() and load_image_gzipped() will read. It prevents
|
||||
|
@ -81,9 +82,9 @@ int load_image_mr(const char *filename, MemoryRegion *mr);
|
|||
*/
|
||||
#define LOAD_IMAGE_MAX_GUNZIP_BYTES (256 << 20)
|
||||
|
||||
int load_image_gzipped_buffer(const char *filename, uint64_t max_sz,
|
||||
uint8_t **buffer);
|
||||
int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
|
||||
ssize_t load_image_gzipped_buffer(const char *filename, uint64_t max_sz,
|
||||
uint8_t **buffer);
|
||||
ssize_t load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
|
||||
|
||||
#define ELF_LOAD_FAILED -1
|
||||
#define ELF_LOAD_NOT_ELF -2
|
||||
|
@ -183,8 +184,8 @@ ssize_t load_elf(const char *filename,
|
|||
*/
|
||||
void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
|
||||
|
||||
int load_aout(const char *filename, hwaddr addr, int max_sz,
|
||||
int bswap_needed, hwaddr target_page_size);
|
||||
ssize_t load_aout(const char *filename, hwaddr addr, int max_sz,
|
||||
int bswap_needed, hwaddr target_page_size);
|
||||
|
||||
#define LOAD_UIMAGE_LOADADDR_INVALID (-1)
|
||||
|
||||
|
@ -205,19 +206,19 @@ int load_aout(const char *filename, hwaddr addr, int max_sz,
|
|||
*
|
||||
* Returns the size of the loaded image on success, -1 otherwise.
|
||||
*/
|
||||
int load_uimage_as(const char *filename, hwaddr *ep,
|
||||
hwaddr *loadaddr, int *is_linux,
|
||||
uint64_t (*translate_fn)(void *, uint64_t),
|
||||
void *translate_opaque, AddressSpace *as);
|
||||
ssize_t load_uimage_as(const char *filename, hwaddr *ep,
|
||||
hwaddr *loadaddr, int *is_linux,
|
||||
uint64_t (*translate_fn)(void *, uint64_t),
|
||||
void *translate_opaque, AddressSpace *as);
|
||||
|
||||
/** load_uimage:
|
||||
* Same as load_uimage_as(), but doesn't allow the caller to specify an
|
||||
* AddressSpace.
|
||||
*/
|
||||
int load_uimage(const char *filename, hwaddr *ep,
|
||||
hwaddr *loadaddr, int *is_linux,
|
||||
uint64_t (*translate_fn)(void *, uint64_t),
|
||||
void *translate_opaque);
|
||||
ssize_t load_uimage(const char *filename, hwaddr *ep,
|
||||
hwaddr *loadaddr, int *is_linux,
|
||||
uint64_t (*translate_fn)(void *, uint64_t),
|
||||
void *translate_opaque);
|
||||
|
||||
/**
|
||||
* load_ramdisk_as:
|
||||
|
@ -232,15 +233,15 @@ int load_uimage(const char *filename, hwaddr *ep,
|
|||
*
|
||||
* Returns the size of the loaded image on success, -1 otherwise.
|
||||
*/
|
||||
int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
|
||||
AddressSpace *as);
|
||||
ssize_t load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
|
||||
AddressSpace *as);
|
||||
|
||||
/**
|
||||
* load_ramdisk:
|
||||
* Same as load_ramdisk_as(), but doesn't allow the caller to specify
|
||||
* an AddressSpace.
|
||||
*/
|
||||
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz);
|
||||
ssize_t load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz);
|
||||
|
||||
ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen);
|
||||
|
||||
|
@ -253,9 +254,9 @@ void pstrcpy_targphys(const char *name,
|
|||
extern bool option_rom_has_mr;
|
||||
extern bool rom_file_has_mr;
|
||||
|
||||
int rom_add_file(const char *file, const char *fw_dir,
|
||||
hwaddr addr, int32_t bootindex,
|
||||
bool option_rom, MemoryRegion *mr, AddressSpace *as);
|
||||
ssize_t rom_add_file(const char *file, const char *fw_dir,
|
||||
hwaddr addr, int32_t bootindex,
|
||||
bool option_rom, MemoryRegion *mr, AddressSpace *as);
|
||||
MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
|
||||
size_t max_len, hwaddr addr,
|
||||
const char *fw_file_name,
|
||||
|
@ -336,8 +337,8 @@ void hmp_info_roms(Monitor *mon, const QDict *qdict);
|
|||
#define rom_add_blob_fixed_as(_f, _b, _l, _a, _as) \
|
||||
rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL, _as, true)
|
||||
|
||||
int rom_add_vga(const char *file);
|
||||
int rom_add_option(const char *file, int32_t bootindex);
|
||||
ssize_t rom_add_vga(const char *file);
|
||||
ssize_t rom_add_option(const char *file, int32_t bootindex);
|
||||
|
||||
/* This is the usual maximum in uboot, so if a uImage overflows this, it would
|
||||
* overflow on real hardware too. */
|
||||
|
|
|
@ -118,6 +118,8 @@ static const char * const riscv_intr_names[] = {
|
|||
"reserved"
|
||||
};
|
||||
|
||||
static void register_cpu_props(DeviceState *dev);
|
||||
|
||||
const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
|
||||
{
|
||||
if (async) {
|
||||
|
@ -161,6 +163,7 @@ static void riscv_any_cpu_init(Object *obj)
|
|||
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
|
||||
#endif
|
||||
set_priv_version(env, PRIV_VERSION_1_12_0);
|
||||
register_cpu_props(DEVICE(obj));
|
||||
}
|
||||
|
||||
#if defined(TARGET_RISCV64)
|
||||
|
@ -169,6 +172,7 @@ static void rv64_base_cpu_init(Object *obj)
|
|||
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
||||
/* We set this in the realise function */
|
||||
set_misa(env, MXL_RV64, 0);
|
||||
register_cpu_props(DEVICE(obj));
|
||||
}
|
||||
|
||||
static void rv64_sifive_u_cpu_init(Object *obj)
|
||||
|
@ -181,9 +185,11 @@ static void rv64_sifive_u_cpu_init(Object *obj)
|
|||
static void rv64_sifive_e_cpu_init(Object *obj)
|
||||
{
|
||||
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
||||
RISCVCPU *cpu = RISCV_CPU(obj);
|
||||
|
||||
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
|
||||
set_priv_version(env, PRIV_VERSION_1_10_0);
|
||||
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
|
||||
cpu->cfg.mmu = false;
|
||||
}
|
||||
|
||||
static void rv128_base_cpu_init(Object *obj)
|
||||
|
@ -197,6 +203,7 @@ static void rv128_base_cpu_init(Object *obj)
|
|||
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
||||
/* We set this in the realise function */
|
||||
set_misa(env, MXL_RV128, 0);
|
||||
register_cpu_props(DEVICE(obj));
|
||||
}
|
||||
#else
|
||||
static void rv32_base_cpu_init(Object *obj)
|
||||
|
@ -204,6 +211,7 @@ static void rv32_base_cpu_init(Object *obj)
|
|||
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
||||
/* We set this in the realise function */
|
||||
set_misa(env, MXL_RV32, 0);
|
||||
register_cpu_props(DEVICE(obj));
|
||||
}
|
||||
|
||||
static void rv32_sifive_u_cpu_init(Object *obj)
|
||||
|
@ -216,27 +224,33 @@ static void rv32_sifive_u_cpu_init(Object *obj)
|
|||
static void rv32_sifive_e_cpu_init(Object *obj)
|
||||
{
|
||||
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
||||
RISCVCPU *cpu = RISCV_CPU(obj);
|
||||
|
||||
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU);
|
||||
set_priv_version(env, PRIV_VERSION_1_10_0);
|
||||
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
|
||||
cpu->cfg.mmu = false;
|
||||
}
|
||||
|
||||
static void rv32_ibex_cpu_init(Object *obj)
|
||||
{
|
||||
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
||||
RISCVCPU *cpu = RISCV_CPU(obj);
|
||||
|
||||
set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU);
|
||||
set_priv_version(env, PRIV_VERSION_1_10_0);
|
||||
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
|
||||
qdev_prop_set_bit(DEVICE(obj), "x-epmp", true);
|
||||
cpu->cfg.mmu = false;
|
||||
cpu->cfg.epmp = true;
|
||||
}
|
||||
|
||||
static void rv32_imafcu_nommu_cpu_init(Object *obj)
|
||||
{
|
||||
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
||||
RISCVCPU *cpu = RISCV_CPU(obj);
|
||||
|
||||
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU);
|
||||
set_priv_version(env, PRIV_VERSION_1_10_0);
|
||||
set_resetvec(env, DEFAULT_RSTVEC);
|
||||
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
|
||||
cpu->cfg.mmu = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -249,6 +263,7 @@ static void riscv_host_cpu_init(Object *obj)
|
|||
#elif defined(TARGET_RISCV64)
|
||||
set_misa(env, MXL_RV64, 0);
|
||||
#endif
|
||||
register_cpu_props(DEVICE(obj));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -391,7 +406,7 @@ static bool riscv_cpu_has_work(CPUState *cs)
|
|||
* Definition of the WFI instruction requires it to ignore the privilege
|
||||
* mode and delegation registers, but respect individual enables
|
||||
*/
|
||||
return (env->mip & env->mie) != 0;
|
||||
return riscv_cpu_all_pending(env) != 0;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
@ -600,6 +615,11 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
|||
cpu->cfg.ext_ifencei = true;
|
||||
}
|
||||
|
||||
if (cpu->cfg.ext_m && cpu->cfg.ext_zmmul) {
|
||||
warn_report("Zmmul will override M");
|
||||
cpu->cfg.ext_m = false;
|
||||
}
|
||||
|
||||
if (cpu->cfg.ext_i && cpu->cfg.ext_e) {
|
||||
error_setg(errp,
|
||||
"I and E extensions are incompatible");
|
||||
|
@ -831,6 +851,12 @@ static void riscv_cpu_init(Object *obj)
|
|||
{
|
||||
RISCVCPU *cpu = RISCV_CPU(obj);
|
||||
|
||||
cpu->cfg.ext_counters = true;
|
||||
cpu->cfg.ext_ifencei = true;
|
||||
cpu->cfg.ext_icsr = true;
|
||||
cpu->cfg.mmu = true;
|
||||
cpu->cfg.pmp = true;
|
||||
|
||||
cpu_set_cpustate_pointers(cpu);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
@ -839,7 +865,7 @@ static void riscv_cpu_init(Object *obj)
|
|||
#endif /* CONFIG_USER_ONLY */
|
||||
}
|
||||
|
||||
static Property riscv_cpu_properties[] = {
|
||||
static Property riscv_cpu_extensions[] = {
|
||||
/* Defaults for standard extensions */
|
||||
DEFINE_PROP_BOOL("i", RISCVCPU, cfg.ext_i, true),
|
||||
DEFINE_PROP_BOOL("e", RISCVCPU, cfg.ext_e, false),
|
||||
|
@ -862,17 +888,12 @@ static Property riscv_cpu_properties[] = {
|
|||
DEFINE_PROP_BOOL("Zve64f", RISCVCPU, cfg.ext_zve64f, false),
|
||||
DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
|
||||
DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
|
||||
DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true),
|
||||
|
||||
DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
|
||||
DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
|
||||
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
|
||||
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
|
||||
|
||||
DEFINE_PROP_UINT32("mvendorid", RISCVCPU, cfg.mvendorid, 0),
|
||||
DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, RISCV_CPU_MARCHID),
|
||||
DEFINE_PROP_UINT64("mimpid", RISCVCPU, cfg.mimpid, RISCV_CPU_MIMPID),
|
||||
|
||||
DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
|
||||
DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
|
||||
DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
|
||||
|
@ -905,13 +926,35 @@ static Property riscv_cpu_properties[] = {
|
|||
|
||||
/* These are experimental so mark with 'x-' */
|
||||
DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false),
|
||||
DEFINE_PROP_BOOL("x-zmmul", RISCVCPU, cfg.ext_zmmul, false),
|
||||
/* ePMP 0.9.3 */
|
||||
DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
|
||||
DEFINE_PROP_BOOL("x-aia", RISCVCPU, cfg.aia, false),
|
||||
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void register_cpu_props(DeviceState *dev)
|
||||
{
|
||||
Property *prop;
|
||||
|
||||
for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
|
||||
qdev_property_add_static(dev, prop);
|
||||
}
|
||||
}
|
||||
|
||||
static Property riscv_cpu_properties[] = {
|
||||
DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true),
|
||||
|
||||
DEFINE_PROP_UINT32("mvendorid", RISCVCPU, cfg.mvendorid, 0),
|
||||
DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, RISCV_CPU_MARCHID),
|
||||
DEFINE_PROP_UINT64("mimpid", RISCVCPU, cfg.mimpid, RISCV_CPU_MIMPID),
|
||||
|
||||
DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec, DEFAULT_RSTVEC),
|
||||
|
||||
DEFINE_PROP_BOOL("short-isa-string", RISCVCPU, cfg.short_isa_string, false),
|
||||
|
||||
DEFINE_PROP_BOOL("rvv_ta_all_1s", RISCVCPU, cfg.rvv_ta_all_1s, false),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@ -1031,6 +1074,7 @@ static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int max_str_len)
|
|||
struct isa_ext_data isa_edata_arr[] = {
|
||||
ISA_EDATA_ENTRY(zicsr, ext_icsr),
|
||||
ISA_EDATA_ENTRY(zifencei, ext_ifencei),
|
||||
ISA_EDATA_ENTRY(zmmul, ext_zmmul),
|
||||
ISA_EDATA_ENTRY(zfh, ext_zfh),
|
||||
ISA_EDATA_ENTRY(zfhmin, ext_zfhmin),
|
||||
ISA_EDATA_ENTRY(zfinx, ext_zfinx),
|
||||
|
|
|
@ -411,6 +411,8 @@ struct RISCVCPUConfig {
|
|||
bool ext_zhinxmin;
|
||||
bool ext_zve32f;
|
||||
bool ext_zve64f;
|
||||
bool ext_zmmul;
|
||||
bool rvv_ta_all_1s;
|
||||
|
||||
uint32_t mvendorid;
|
||||
uint64_t marchid;
|
||||
|
@ -488,6 +490,7 @@ int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
|||
int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero);
|
||||
uint8_t riscv_cpu_default_priority(int irq);
|
||||
uint64_t riscv_cpu_all_pending(CPURISCVState *env);
|
||||
int riscv_cpu_mirq_pending(CPURISCVState *env);
|
||||
int riscv_cpu_sirq_pending(CPURISCVState *env);
|
||||
int riscv_cpu_vsirq_pending(CPURISCVState *env);
|
||||
|
@ -565,6 +568,7 @@ FIELD(TB_FLAGS, XL, 20, 2)
|
|||
/* If PointerMasking should be applied */
|
||||
FIELD(TB_FLAGS, PM_MASK_ENABLED, 22, 1)
|
||||
FIELD(TB_FLAGS, PM_BASE_ENABLED, 23, 1)
|
||||
FIELD(TB_FLAGS, VTA, 24, 1)
|
||||
|
||||
#ifdef TARGET_RISCV32
|
||||
#define riscv_cpu_mxl(env) ((void)(env), MXL_RV32)
|
||||
|
|
|
@ -65,6 +65,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
|
|||
flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
|
||||
FIELD_EX64(env->vtype, VTYPE, VLMUL));
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VTA,
|
||||
FIELD_EX64(env->vtype, VTYPE, VTA));
|
||||
} else {
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
|
||||
}
|
||||
|
@ -340,7 +342,7 @@ static int riscv_cpu_pending_to_irq(CPURISCVState *env,
|
|||
return best_irq;
|
||||
}
|
||||
|
||||
static uint64_t riscv_cpu_all_pending(CPURISCVState *env)
|
||||
uint64_t riscv_cpu_all_pending(CPURISCVState *env)
|
||||
{
|
||||
uint32_t gein = get_field(env->hstatus, HSTATUS_VGEIN);
|
||||
uint64_t vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
|
||||
|
|
|
@ -77,6 +77,7 @@ static inline target_ulong trigger_type(CPURISCVState *env,
|
|||
tdata1 = RV32_TYPE(type);
|
||||
break;
|
||||
case MXL_RV64:
|
||||
case MXL_RV128:
|
||||
tdata1 = RV64_TYPE(type);
|
||||
break;
|
||||
default:
|
||||
|
@ -123,6 +124,7 @@ static target_ulong tdata1_validate(CPURISCVState *env, target_ulong val,
|
|||
tdata1 = RV32_TYPE(t);
|
||||
break;
|
||||
case MXL_RV64:
|
||||
case MXL_RV128:
|
||||
type = extract64(val, 60, 4);
|
||||
dmode = extract64(val, 59, 1);
|
||||
tdata1 = RV64_TYPE(t);
|
||||
|
|
|
@ -18,6 +18,12 @@
|
|||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define REQUIRE_M_OR_ZMMUL(ctx) do { \
|
||||
if (!ctx->cfg_ptr->ext_zmmul && !has_ext(ctx, RVM)) { \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static void gen_mulhu_i128(TCGv r2, TCGv r3, TCGv al, TCGv ah, TCGv bl, TCGv bh)
|
||||
{
|
||||
TCGv tmpl = tcg_temp_new();
|
||||
|
@ -65,7 +71,7 @@ static void gen_mul_i128(TCGv rl, TCGv rh,
|
|||
|
||||
static bool trans_mul(DisasContext *ctx, arg_mul *a)
|
||||
{
|
||||
REQUIRE_EXT(ctx, RVM);
|
||||
REQUIRE_M_OR_ZMMUL(ctx);
|
||||
return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl, gen_mul_i128);
|
||||
}
|
||||
|
||||
|
@ -109,7 +115,7 @@ static void gen_mulh_w(TCGv ret, TCGv s1, TCGv s2)
|
|||
|
||||
static bool trans_mulh(DisasContext *ctx, arg_mulh *a)
|
||||
{
|
||||
REQUIRE_EXT(ctx, RVM);
|
||||
REQUIRE_M_OR_ZMMUL(ctx);
|
||||
return gen_arith_per_ol(ctx, a, EXT_SIGN, gen_mulh, gen_mulh_w,
|
||||
gen_mulh_i128);
|
||||
}
|
||||
|
@ -161,7 +167,7 @@ static void gen_mulhsu_w(TCGv ret, TCGv arg1, TCGv arg2)
|
|||
|
||||
static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a)
|
||||
{
|
||||
REQUIRE_EXT(ctx, RVM);
|
||||
REQUIRE_M_OR_ZMMUL(ctx);
|
||||
return gen_arith_per_ol(ctx, a, EXT_NONE, gen_mulhsu, gen_mulhsu_w,
|
||||
gen_mulhsu_i128);
|
||||
}
|
||||
|
@ -176,7 +182,7 @@ static void gen_mulhu(TCGv ret, TCGv s1, TCGv s2)
|
|||
|
||||
static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a)
|
||||
{
|
||||
REQUIRE_EXT(ctx, RVM);
|
||||
REQUIRE_M_OR_ZMMUL(ctx);
|
||||
/* gen_mulh_w works for either sign as input. */
|
||||
return gen_arith_per_ol(ctx, a, EXT_ZERO, gen_mulhu, gen_mulh_w,
|
||||
gen_mulhu_i128);
|
||||
|
@ -349,7 +355,7 @@ static bool trans_remu(DisasContext *ctx, arg_remu *a)
|
|||
static bool trans_mulw(DisasContext *ctx, arg_mulw *a)
|
||||
{
|
||||
REQUIRE_64_OR_128BIT(ctx);
|
||||
REQUIRE_EXT(ctx, RVM);
|
||||
REQUIRE_M_OR_ZMMUL(ctx);
|
||||
ctx->ol = MXL_RV32;
|
||||
return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl, NULL);
|
||||
}
|
||||
|
@ -389,7 +395,7 @@ static bool trans_remuw(DisasContext *ctx, arg_remuw *a)
|
|||
static bool trans_muld(DisasContext *ctx, arg_muld *a)
|
||||
{
|
||||
REQUIRE_128BIT(ctx);
|
||||
REQUIRE_EXT(ctx, RVM);
|
||||
REQUIRE_M_OR_ZMMUL(ctx);
|
||||
ctx->ol = MXL_RV64;
|
||||
return gen_arith(ctx, a, EXT_SIGN, tcg_gen_mul_tl, NULL);
|
||||
}
|
||||
|
|
|
@ -652,6 +652,7 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data,
|
|||
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
dest = tcg_temp_new_ptr();
|
||||
mask = tcg_temp_new_ptr();
|
||||
|
@ -710,6 +711,7 @@ static bool ld_us_op(DisasContext *s, arg_r2nfvm *a, uint8_t eew)
|
|||
data = FIELD_DP32(data, VDATA, VM, a->vm);
|
||||
data = FIELD_DP32(data, VDATA, LMUL, emul);
|
||||
data = FIELD_DP32(data, VDATA, NF, a->nf);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
return ldst_us_trans(a->rd, a->rs1, data, fn, s, false);
|
||||
}
|
||||
|
||||
|
@ -773,6 +775,8 @@ static bool ld_us_mask_op(DisasContext *s, arg_vlm_v *a, uint8_t eew)
|
|||
/* EMUL = 1, NFIELDS = 1 */
|
||||
data = FIELD_DP32(data, VDATA, LMUL, 0);
|
||||
data = FIELD_DP32(data, VDATA, NF, 1);
|
||||
/* Mask destination register are always tail-agnostic */
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->cfg_vta_all_1s);
|
||||
return ldst_us_trans(a->rd, a->rs1, data, fn, s, false);
|
||||
}
|
||||
|
||||
|
@ -818,6 +822,7 @@ static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, uint32_t rs2,
|
|||
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
dest = tcg_temp_new_ptr();
|
||||
mask = tcg_temp_new_ptr();
|
||||
|
@ -860,6 +865,7 @@ static bool ld_stride_op(DisasContext *s, arg_rnfvm *a, uint8_t eew)
|
|||
data = FIELD_DP32(data, VDATA, VM, a->vm);
|
||||
data = FIELD_DP32(data, VDATA, LMUL, emul);
|
||||
data = FIELD_DP32(data, VDATA, NF, a->nf);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s, false);
|
||||
}
|
||||
|
||||
|
@ -925,6 +931,7 @@ static bool ldst_index_trans(uint32_t vd, uint32_t rs1, uint32_t vs2,
|
|||
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
dest = tcg_temp_new_ptr();
|
||||
mask = tcg_temp_new_ptr();
|
||||
|
@ -988,6 +995,7 @@ static bool ld_index_op(DisasContext *s, arg_rnfvm *a, uint8_t eew)
|
|||
data = FIELD_DP32(data, VDATA, VM, a->vm);
|
||||
data = FIELD_DP32(data, VDATA, LMUL, emul);
|
||||
data = FIELD_DP32(data, VDATA, NF, a->nf);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
return ldst_index_trans(a->rd, a->rs1, a->rs2, data, fn, s, false);
|
||||
}
|
||||
|
||||
|
@ -1067,6 +1075,7 @@ static bool ldff_trans(uint32_t vd, uint32_t rs1, uint32_t data,
|
|||
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
dest = tcg_temp_new_ptr();
|
||||
mask = tcg_temp_new_ptr();
|
||||
|
@ -1104,6 +1113,7 @@ static bool ldff_op(DisasContext *s, arg_r2nfvm *a, uint8_t eew)
|
|||
data = FIELD_DP32(data, VDATA, VM, a->vm);
|
||||
data = FIELD_DP32(data, VDATA, LMUL, emul);
|
||||
data = FIELD_DP32(data, VDATA, NF, a->nf);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
return ldff_trans(a->rd, a->rs1, data, fn, s);
|
||||
}
|
||||
|
||||
|
@ -1225,8 +1235,9 @@ do_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn *gvec_fn,
|
|||
}
|
||||
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
if (a->vm && s->vl_eq_vlmax) {
|
||||
if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
|
||||
gvec_fn(s->sew, vreg_ofs(s, a->rd),
|
||||
vreg_ofs(s, a->rs2), vreg_ofs(s, a->rs1),
|
||||
MAXSZ(s), MAXSZ(s));
|
||||
|
@ -1235,6 +1246,7 @@ do_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn *gvec_fn,
|
|||
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm);
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
|
||||
vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2),
|
||||
cpu_env, s->cfg_ptr->vlen / 8,
|
||||
|
@ -1272,6 +1284,7 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm,
|
|||
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
dest = tcg_temp_new_ptr();
|
||||
mask = tcg_temp_new_ptr();
|
||||
|
@ -1280,6 +1293,8 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm,
|
|||
|
||||
data = FIELD_DP32(data, VDATA, VM, vm);
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
|
||||
desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
|
||||
s->cfg_ptr->vlen / 8, data));
|
||||
|
||||
|
@ -1315,7 +1330,7 @@ do_opivx_gvec(DisasContext *s, arg_rmrr *a, GVecGen2sFn *gvec_fn,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (a->vm && s->vl_eq_vlmax) {
|
||||
if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
|
||||
TCGv_i64 src1 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_ext_tl_i64(src1, get_gpr(s, a->rs1, EXT_SIGN));
|
||||
|
@ -1436,6 +1451,7 @@ static bool opivi_trans(uint32_t vd, uint32_t imm, uint32_t vs2, uint32_t vm,
|
|||
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
dest = tcg_temp_new_ptr();
|
||||
mask = tcg_temp_new_ptr();
|
||||
|
@ -1444,6 +1460,8 @@ static bool opivi_trans(uint32_t vd, uint32_t imm, uint32_t vs2, uint32_t vm,
|
|||
|
||||
data = FIELD_DP32(data, VDATA, VM, vm);
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
|
||||
desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
|
||||
s->cfg_ptr->vlen / 8, data));
|
||||
|
||||
|
@ -1472,7 +1490,7 @@ do_opivi_gvec(DisasContext *s, arg_rmrr *a, GVecGen2iFn *gvec_fn,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (a->vm && s->vl_eq_vlmax) {
|
||||
if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
|
||||
gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2),
|
||||
extract_imm(s, a->rs1, imm_mode), MAXSZ(s), MAXSZ(s));
|
||||
mark_vs_dirty(s);
|
||||
|
@ -1522,9 +1540,11 @@ static bool do_opivv_widen(DisasContext *s, arg_rmrr *a,
|
|||
uint32_t data = 0;
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm);
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
|
||||
vreg_ofs(s, a->rs1),
|
||||
vreg_ofs(s, a->rs2),
|
||||
|
@ -1602,9 +1622,11 @@ static bool do_opiwv_widen(DisasContext *s, arg_rmrr *a,
|
|||
uint32_t data = 0;
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm);
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
|
||||
vreg_ofs(s, a->rs1),
|
||||
vreg_ofs(s, a->rs2),
|
||||
|
@ -1679,9 +1701,13 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
|||
}; \
|
||||
TCGLabel *over = gen_new_label(); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
|
||||
\
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm); \
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta); \
|
||||
data = \
|
||||
FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\
|
||||
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
|
||||
vreg_ofs(s, a->rs1), \
|
||||
vreg_ofs(s, a->rs2), cpu_env, \
|
||||
|
@ -1805,7 +1831,7 @@ do_opivx_gvec_shift(DisasContext *s, arg_rmrr *a, GVecGen2sFn32 *gvec_fn,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (a->vm && s->vl_eq_vlmax) {
|
||||
if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
|
||||
TCGv_i32 src1 = tcg_temp_new_i32();
|
||||
|
||||
tcg_gen_trunc_tl_i32(src1, get_gpr(s, a->rs1, EXT_NONE));
|
||||
|
@ -1860,9 +1886,11 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
|||
}; \
|
||||
TCGLabel *over = gen_new_label(); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
|
||||
\
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm); \
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta); \
|
||||
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
|
||||
vreg_ofs(s, a->rs1), \
|
||||
vreg_ofs(s, a->rs2), cpu_env, \
|
||||
|
@ -2058,18 +2086,20 @@ static bool trans_vmv_v_v(DisasContext *s, arg_vmv_v_v *a)
|
|||
vext_check_isa_ill(s) &&
|
||||
/* vmv.v.v has rs2 = 0 and vm = 1 */
|
||||
vext_check_sss(s, a->rd, a->rs1, 0, 1)) {
|
||||
if (s->vl_eq_vlmax) {
|
||||
if (s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
|
||||
tcg_gen_gvec_mov(s->sew, vreg_ofs(s, a->rd),
|
||||
vreg_ofs(s, a->rs1),
|
||||
MAXSZ(s), MAXSZ(s));
|
||||
} else {
|
||||
uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
static gen_helper_gvec_2_ptr * const fns[4] = {
|
||||
gen_helper_vmv_v_v_b, gen_helper_vmv_v_v_h,
|
||||
gen_helper_vmv_v_v_w, gen_helper_vmv_v_v_d,
|
||||
};
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
|
||||
cpu_env, s->cfg_ptr->vlen / 8,
|
||||
|
@ -2093,17 +2123,27 @@ static bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x *a)
|
|||
TCGv s1;
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
s1 = get_gpr(s, a->rs1, EXT_SIGN);
|
||||
|
||||
if (s->vl_eq_vlmax) {
|
||||
tcg_gen_gvec_dup_tl(s->sew, vreg_ofs(s, a->rd),
|
||||
MAXSZ(s), MAXSZ(s), s1);
|
||||
if (s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
|
||||
if (get_xl(s) == MXL_RV32 && s->sew == MO_64) {
|
||||
TCGv_i64 s1_i64 = tcg_temp_new_i64();
|
||||
tcg_gen_ext_tl_i64(s1_i64, s1);
|
||||
tcg_gen_gvec_dup_i64(s->sew, vreg_ofs(s, a->rd),
|
||||
MAXSZ(s), MAXSZ(s), s1_i64);
|
||||
tcg_temp_free_i64(s1_i64);
|
||||
} else {
|
||||
tcg_gen_gvec_dup_tl(s->sew, vreg_ofs(s, a->rd),
|
||||
MAXSZ(s), MAXSZ(s), s1);
|
||||
}
|
||||
} else {
|
||||
TCGv_i32 desc;
|
||||
TCGv_i64 s1_i64 = tcg_temp_new_i64();
|
||||
TCGv_ptr dest = tcg_temp_new_ptr();
|
||||
uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
static gen_helper_vmv_vx * const fns[4] = {
|
||||
gen_helper_vmv_v_x_b, gen_helper_vmv_v_x_h,
|
||||
gen_helper_vmv_v_x_w, gen_helper_vmv_v_x_d,
|
||||
|
@ -2133,7 +2173,7 @@ static bool trans_vmv_v_i(DisasContext *s, arg_vmv_v_i *a)
|
|||
/* vmv.v.i has rs2 = 0 and vm = 1 */
|
||||
vext_check_ss(s, a->rd, 0, 1)) {
|
||||
int64_t simm = sextract64(a->rs1, 0, 5);
|
||||
if (s->vl_eq_vlmax) {
|
||||
if (s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
|
||||
tcg_gen_gvec_dup_imm(s->sew, vreg_ofs(s, a->rd),
|
||||
MAXSZ(s), MAXSZ(s), simm);
|
||||
mark_vs_dirty(s);
|
||||
|
@ -2142,12 +2182,14 @@ static bool trans_vmv_v_i(DisasContext *s, arg_vmv_v_i *a)
|
|||
TCGv_i64 s1;
|
||||
TCGv_ptr dest;
|
||||
uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
static gen_helper_vmv_vx * const fns[4] = {
|
||||
gen_helper_vmv_v_x_b, gen_helper_vmv_v_x_h,
|
||||
gen_helper_vmv_v_x_w, gen_helper_vmv_v_x_d,
|
||||
};
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
s1 = tcg_constant_i64(simm);
|
||||
dest = tcg_temp_new_ptr();
|
||||
|
@ -2300,9 +2342,13 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
|||
TCGLabel *over = gen_new_label(); \
|
||||
gen_set_rm(s, RISCV_FRM_DYN); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
|
||||
\
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm); \
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta); \
|
||||
data = \
|
||||
FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\
|
||||
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
|
||||
vreg_ofs(s, a->rs1), \
|
||||
vreg_ofs(s, a->rs2), cpu_env, \
|
||||
|
@ -2330,6 +2376,7 @@ static bool opfvf_trans(uint32_t vd, uint32_t rs1, uint32_t vs2,
|
|||
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
dest = tcg_temp_new_ptr();
|
||||
mask = tcg_temp_new_ptr();
|
||||
|
@ -2384,6 +2431,9 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
|||
gen_set_rm(s, RISCV_FRM_DYN); \
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm); \
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta); \
|
||||
data = FIELD_DP32(data, VDATA, VTA_ALL_1S, \
|
||||
s->cfg_vta_all_1s); \
|
||||
return opfvf_trans(a->rd, a->rs1, a->rs2, data, \
|
||||
fns[s->sew - 1], s); \
|
||||
} \
|
||||
|
@ -2418,9 +2468,11 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
|||
TCGLabel *over = gen_new_label(); \
|
||||
gen_set_rm(s, RISCV_FRM_DYN); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);\
|
||||
\
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm); \
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta); \
|
||||
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
|
||||
vreg_ofs(s, a->rs1), \
|
||||
vreg_ofs(s, a->rs2), cpu_env, \
|
||||
|
@ -2460,6 +2512,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
|||
gen_set_rm(s, RISCV_FRM_DYN); \
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm); \
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta); \
|
||||
return opfvf_trans(a->rd, a->rs1, a->rs2, data, \
|
||||
fns[s->sew - 1], s); \
|
||||
} \
|
||||
|
@ -2492,9 +2545,11 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
|||
TCGLabel *over = gen_new_label(); \
|
||||
gen_set_rm(s, RISCV_FRM_DYN); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
|
||||
\
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm); \
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta); \
|
||||
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
|
||||
vreg_ofs(s, a->rs1), \
|
||||
vreg_ofs(s, a->rs2), cpu_env, \
|
||||
|
@ -2534,6 +2589,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
|||
gen_set_rm(s, RISCV_FRM_DYN); \
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm); \
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta); \
|
||||
return opfvf_trans(a->rd, a->rs1, a->rs2, data, \
|
||||
fns[s->sew - 1], s); \
|
||||
} \
|
||||
|
@ -2613,9 +2669,11 @@ static bool do_opfv(DisasContext *s, arg_rmr *a,
|
|||
TCGLabel *over = gen_new_label();
|
||||
gen_set_rm(s, rm);
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm);
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
|
||||
vreg_ofs(s, a->rs2), cpu_env,
|
||||
s->cfg_ptr->vlen / 8,
|
||||
|
@ -2707,7 +2765,7 @@ static bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a)
|
|||
|
||||
TCGv_i64 t1;
|
||||
|
||||
if (s->vl_eq_vlmax) {
|
||||
if (s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
|
||||
t1 = tcg_temp_new_i64();
|
||||
/* NaN-box f[rs1] */
|
||||
do_nanbox(s, t1, cpu_fpr[a->rs1]);
|
||||
|
@ -2719,6 +2777,7 @@ static bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a)
|
|||
TCGv_ptr dest;
|
||||
TCGv_i32 desc;
|
||||
uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
static gen_helper_vmv_vx * const fns[3] = {
|
||||
gen_helper_vmv_v_x_h,
|
||||
gen_helper_vmv_v_x_w,
|
||||
|
@ -2726,6 +2785,7 @@ static bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a)
|
|||
};
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
t1 = tcg_temp_new_i64();
|
||||
/* NaN-box f[rs1] */
|
||||
|
@ -2814,9 +2874,11 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
|
|||
TCGLabel *over = gen_new_label(); \
|
||||
gen_set_rm(s, FRM); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
|
||||
\
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm); \
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta); \
|
||||
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
|
||||
vreg_ofs(s, a->rs2), cpu_env, \
|
||||
s->cfg_ptr->vlen / 8, \
|
||||
|
@ -2865,8 +2927,11 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
|
|||
TCGLabel *over = gen_new_label(); \
|
||||
gen_set_rm(s, RISCV_FRM_DYN); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
|
||||
\
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm); \
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta); \
|
||||
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
|
||||
vreg_ofs(s, a->rs2), cpu_env, \
|
||||
s->cfg_ptr->vlen / 8, \
|
||||
|
@ -2930,9 +2995,11 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
|
|||
TCGLabel *over = gen_new_label(); \
|
||||
gen_set_rm(s, FRM); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
|
||||
\
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm); \
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta); \
|
||||
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
|
||||
vreg_ofs(s, a->rs2), cpu_env, \
|
||||
s->cfg_ptr->vlen / 8, \
|
||||
|
@ -2983,8 +3050,11 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
|
|||
TCGLabel *over = gen_new_label(); \
|
||||
gen_set_rm(s, FRM); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
|
||||
\
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm); \
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta); \
|
||||
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
|
||||
vreg_ofs(s, a->rs2), cpu_env, \
|
||||
s->cfg_ptr->vlen / 8, \
|
||||
|
@ -3070,8 +3140,11 @@ static bool trans_##NAME(DisasContext *s, arg_r *a) \
|
|||
gen_helper_gvec_4_ptr *fn = gen_helper_##NAME; \
|
||||
TCGLabel *over = gen_new_label(); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
|
||||
\
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
data = \
|
||||
FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\
|
||||
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
|
||||
vreg_ofs(s, a->rs1), \
|
||||
vreg_ofs(s, a->rs2), cpu_env, \
|
||||
|
@ -3176,6 +3249,8 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
|
|||
\
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm); \
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
data = \
|
||||
FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\
|
||||
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), \
|
||||
vreg_ofs(s, 0), vreg_ofs(s, a->rs2), \
|
||||
cpu_env, s->cfg_ptr->vlen / 8, \
|
||||
|
@ -3213,6 +3288,7 @@ static bool trans_viota_m(DisasContext *s, arg_viota_m *a)
|
|||
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm);
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
static gen_helper_gvec_3_ptr * const fns[4] = {
|
||||
gen_helper_viota_m_b, gen_helper_viota_m_h,
|
||||
gen_helper_viota_m_w, gen_helper_viota_m_d,
|
||||
|
@ -3238,9 +3314,11 @@ static bool trans_vid_v(DisasContext *s, arg_vid_v *a)
|
|||
uint32_t data = 0;
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm);
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
static gen_helper_gvec_2_ptr * const fns[4] = {
|
||||
gen_helper_vid_v_b, gen_helper_vid_v_h,
|
||||
gen_helper_vid_v_w, gen_helper_vid_v_d,
|
||||
|
@ -3599,7 +3677,7 @@ static bool trans_vrgather_vx(DisasContext *s, arg_rmrr *a)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (a->vm && s->vl_eq_vlmax) {
|
||||
if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
|
||||
int scale = s->lmul - (s->sew + 3);
|
||||
int vlmax = s->cfg_ptr->vlen >> -scale;
|
||||
TCGv_i64 dest = tcg_temp_new_i64();
|
||||
|
@ -3631,7 +3709,7 @@ static bool trans_vrgather_vi(DisasContext *s, arg_rmrr *a)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (a->vm && s->vl_eq_vlmax) {
|
||||
if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
|
||||
int scale = s->lmul - (s->sew + 3);
|
||||
int vlmax = s->cfg_ptr->vlen >> -scale;
|
||||
if (a->rs1 >= vlmax) {
|
||||
|
@ -3683,6 +3761,7 @@ static bool trans_vcompress_vm(DisasContext *s, arg_r *a)
|
|||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
|
||||
vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2),
|
||||
cpu_env, s->cfg_ptr->vlen / 8,
|
||||
|
@ -3748,6 +3827,7 @@ static bool int_ext_op(DisasContext *s, arg_rmr *a, uint8_t seq)
|
|||
gen_helper_gvec_3_ptr *fn;
|
||||
TCGLabel *over = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
|
||||
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
|
||||
|
||||
static gen_helper_gvec_3_ptr * const fns[6][4] = {
|
||||
{
|
||||
|
@ -3782,6 +3862,8 @@ static bool int_ext_op(DisasContext *s, arg_rmr *a, uint8_t seq)
|
|||
}
|
||||
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm);
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
|
||||
data = FIELD_DP32(data, VDATA, VTA, s->vta);
|
||||
|
||||
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
|
||||
vreg_ofs(s, a->rs2), cpu_env,
|
||||
|
|
|
@ -24,8 +24,10 @@
|
|||
/* share data between vector helpers and decode code */
|
||||
FIELD(VDATA, VM, 0, 1)
|
||||
FIELD(VDATA, LMUL, 1, 3)
|
||||
FIELD(VDATA, NF, 4, 4)
|
||||
FIELD(VDATA, WD, 4, 1)
|
||||
FIELD(VDATA, VTA, 4, 1)
|
||||
FIELD(VDATA, VTA_ALL_1S, 5, 1)
|
||||
FIELD(VDATA, NF, 6, 4)
|
||||
FIELD(VDATA, WD, 6, 1)
|
||||
|
||||
/* float point classify helpers */
|
||||
target_ulong fclass_h(uint64_t frs1);
|
||||
|
|
|
@ -94,6 +94,8 @@ typedef struct DisasContext {
|
|||
*/
|
||||
int8_t lmul;
|
||||
uint8_t sew;
|
||||
uint8_t vta;
|
||||
bool cfg_vta_all_1s;
|
||||
target_ulong vstart;
|
||||
bool vl_eq_vlmax;
|
||||
uint8_t ntemp;
|
||||
|
@ -1099,6 +1101,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
|||
ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
|
||||
ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
|
||||
ctx->lmul = sextract32(FIELD_EX32(tb_flags, TB_FLAGS, LMUL), 0, 3);
|
||||
ctx->vta = FIELD_EX32(tb_flags, TB_FLAGS, VTA) && cpu->cfg.rvv_ta_all_1s;
|
||||
ctx->cfg_vta_all_1s = cpu->cfg.rvv_ta_all_1s;
|
||||
ctx->vstart = env->vstart;
|
||||
ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
|
||||
ctx->misa_mxl_max = env->misa_mxl_max;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue