From 46b3e2548bd49f9bc8866bf5e20f74c86948cefc Mon Sep 17 00:00:00 2001 From: Vijai Kumar K Date: Sun, 1 Aug 2021 00:32:29 +0530 Subject: hw/char: Add config for shakti uart Use a dedicated UART config(CONFIG_SHAKTI_UART) to select shakti uart. Signed-off-by: Vijai Kumar K Reviewed-by: Alistair Francis Message-id: 20210731190229.137483-1-vijai@behindbytes.com Signed-off-by: Alistair Francis --- hw/char/Kconfig | 3 +++ hw/char/meson.build | 2 +- hw/riscv/Kconfig | 5 +---- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/char/Kconfig b/hw/char/Kconfig index 2e4f620b..6b6cf2f 100644 --- a/hw/char/Kconfig +++ b/hw/char/Kconfig @@ -68,3 +68,6 @@ config SIFIVE_UART config GOLDFISH_TTY bool + +config SHAKTI_UART + bool diff --git a/hw/char/meson.build b/hw/char/meson.build index 8361d0a..7b594f5 100644 --- a/hw/char/meson.build +++ b/hw/char/meson.build @@ -16,7 +16,7 @@ softmmu_ss.add(when: 'CONFIG_SERIAL', if_true: files('serial.c')) softmmu_ss.add(when: 'CONFIG_SERIAL_ISA', if_true: files('serial-isa.c')) softmmu_ss.add(when: 'CONFIG_SERIAL_PCI', if_true: files('serial-pci.c')) softmmu_ss.add(when: 'CONFIG_SERIAL_PCI_MULTI', if_true: files('serial-pci-multi.c')) -softmmu_ss.add(when: 'CONFIG_SHAKTI', if_true: files('shakti_uart.c')) +softmmu_ss.add(when: 'CONFIG_SHAKTI_UART', if_true: files('shakti_uart.c')) softmmu_ss.add(when: 'CONFIG_VIRTIO_SERIAL', if_true: files('virtio-console.c')) softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xen_console.c')) softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_uartlite.c')) diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 0590f44..ff75add 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -22,13 +22,10 @@ config OPENTITAN select IBEX select UNIMP -config SHAKTI - bool - config SHAKTI_C bool select UNIMP - select SHAKTI + select SHAKTI_UART select SIFIVE_CLINT select SIFIVE_PLIC -- cgit v1.1 From 58bde469ba0208497eea49650df7e9f832875e56 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sat, 7 Aug 2021 11:56:41 +0800 Subject: hw/riscv: virt: Move flash node to root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The flash is not inside the SoC, so it's inappropriate to put it under the /soc node. Move it to root instead. Signed-off-by: Bin Meng Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20210807035641.22449-1-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- hw/riscv/virt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 0e55411..aa279c1 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -454,7 +454,7 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap, qemu_fdt_setprop_cell(fdt, name, "interrupts", RTC_IRQ); g_free(name); - name = g_strdup_printf("/soc/flash@%" PRIx64, flashbase); + name = g_strdup_printf("/flash@%" PRIx64, flashbase); qemu_fdt_add_subnode(mc->fdt, name); qemu_fdt_setprop_string(mc->fdt, name, "compatible", "cfi-flash"); qemu_fdt_setprop_sized_cells(mc->fdt, name, "reg", -- cgit v1.1 From 65e728a28aa6c9df62711e2ece09f142b97825a6 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sat, 7 Aug 2021 22:10:25 +0800 Subject: target/riscv: Correct a comment in riscv_csrrw() When privilege check fails, RISCV_EXCP_ILLEGAL_INST is returned, not -1 (RISCV_EXCP_NONE). Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-id: 20210807141025.31808-1-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- target/riscv/csr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 9a4ed18..e747fbe 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1423,7 +1423,7 @@ RISCVException riscv_csrrw(CPURISCVState *env, int csrno, target_ulong old_value; RISCVCPU *cpu = env_archcpu(env); - /* check privileges and return -1 if check fails */ + /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */ #if !defined(CONFIG_USER_ONLY) int effective_priv = env->priv; int read_only = get_field(csrno, 0xC00) == 3; -- cgit v1.1 From a8b37120d459a7fdd353f08e9ccb75178086c6cc Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Wed, 11 Aug 2021 22:46:12 +0800 Subject: target/riscv: Don't wrongly override isa version For some cpu, the isa version has already been set in cpu init function. Thus only override the isa version when isa version is not set, or users set different isa version explicitly by cpu parameters. Signed-off-by: LIU Zhiwei Reviewed-by: Bin Meng Message-id: 20210811144612.68674-1-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 991a6bb..1a2b03d 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -392,9 +392,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) RISCVCPU *cpu = RISCV_CPU(dev); CPURISCVState *env = &cpu->env; RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev); - int priv_version = PRIV_VERSION_1_11_0; - int bext_version = BEXT_VERSION_0_93_0; - int vext_version = VEXT_VERSION_0_07_1; + int priv_version = 0; target_ulong target_misa = env->misa; Error *local_err = NULL; @@ -417,9 +415,11 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) } } - set_priv_version(env, priv_version); - set_bext_version(env, bext_version); - set_vext_version(env, vext_version); + if (priv_version) { + set_priv_version(env, priv_version); + } else if (!env->priv_ver) { + set_priv_version(env, PRIV_VERSION_1_11_0); + } if (cpu->cfg.mmu) { set_feature(env, RISCV_FEATURE_MMU); @@ -497,6 +497,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) target_misa |= RVH; } if (cpu->cfg.ext_b) { + int bext_version = BEXT_VERSION_0_93_0; target_misa |= RVB; if (cpu->cfg.bext_spec) { @@ -515,6 +516,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) set_bext_version(env, bext_version); } if (cpu->cfg.ext_v) { + int vext_version = VEXT_VERSION_0_07_1; target_misa |= RVV; if (!is_power_of_2(cpu->cfg.vlen)) { error_setg(errp, -- cgit v1.1 From 42109837b521e3a1f93e38f5058126a85ebc7f9f Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Tue, 10 Aug 2021 09:45:52 +0800 Subject: target/riscv: Add User CSRs read-only check For U-mode CSRs, read-only check is also needed. Signed-off-by: LIU Zhiwei Reviewed-by: Bin Meng Message-id: 20210810014552.4884-1-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/csr.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index e747fbe..6d7f2c2 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1422,11 +1422,11 @@ RISCVException riscv_csrrw(CPURISCVState *env, int csrno, RISCVException ret; target_ulong old_value; RISCVCPU *cpu = env_archcpu(env); + int read_only = get_field(csrno, 0xC00) == 3; /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */ #if !defined(CONFIG_USER_ONLY) int effective_priv = env->priv; - int read_only = get_field(csrno, 0xC00) == 3; if (riscv_has_ext(env, RVH) && env->priv == PRV_S && @@ -1439,11 +1439,13 @@ RISCVException riscv_csrrw(CPURISCVState *env, int csrno, effective_priv++; } - if ((write_mask && read_only) || - (!env->debugger && (effective_priv < get_field(csrno, 0x300)))) { + if (!env->debugger && (effective_priv < get_field(csrno, 0x300))) { return RISCV_EXCP_ILLEGAL_INST; } #endif + if (write_mask && read_only) { + return RISCV_EXCP_ILLEGAL_INST; + } /* ensure the CSR extension is enabled. */ if (!cpu->cfg.ext_icsr) { -- cgit v1.1 From 33fcedfac8af376afad478f029cebb9ddb09f74a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 12 Aug 2021 15:46:47 +0100 Subject: hw/riscv/virt.c: Assemble plic_hart_config string with g_strjoinv() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the riscv virt machine init function, We assemble a string plic_hart_config which is a comma-separated list of N copies of the VIRT_PLIC_HART_CONFIG string. The code that does this has a misunderstanding of the strncat() length argument. If the source string is too large strncat() will write a maximum of length+1 bytes (length bytes from the source string plus a trailing NUL), but the code here assumes that it will write only length bytes at most. This isn't an actual bug because the code has correctly precalculated the amount of memory it needs to allocate so that it will never be too small (i.e. we could have used plain old strcat()), but it does mean that the code looks like it has a guard against accidental overrun when it doesn't. Rewrite the string handling here to use the glib g_strjoinv() function, which means we don't need to do careful accountancy of string lengths, and makes it clearer that what we're doing is "create a comma-separated string". Fixes: Coverity 1460752 Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20210812144647.10516-1-peter.maydell@linaro.org Signed-off-by: Alistair Francis --- hw/riscv/virt.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index aa279c1..5624add 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -540,6 +540,24 @@ static FWCfgState *create_fw_cfg(const MachineState *mc) return fw_cfg; } +/* + * Return the per-socket PLIC hart topology configuration string + * (caller must free with g_free()) + */ +static char *plic_hart_config_string(int hart_count) +{ + g_autofree const char **vals = g_new(const char *, hart_count + 1); + int i; + + for (i = 0; i < hart_count; i++) { + vals[i] = VIRT_PLIC_HART_CONFIG; + } + vals[i] = NULL; + + /* g_strjoinv() obliges us to cast away const here */ + return g_strjoinv(",", (char **)vals); +} + static void virt_machine_init(MachineState *machine) { const MemMapEntry *memmap = virt_memmap; @@ -548,13 +566,12 @@ static void virt_machine_init(MachineState *machine) MemoryRegion *main_mem = g_new(MemoryRegion, 1); MemoryRegion *mask_rom = g_new(MemoryRegion, 1); char *plic_hart_config, *soc_name; - size_t plic_hart_config_len; target_ulong start_addr = memmap[VIRT_DRAM].base; target_ulong firmware_end_addr, kernel_start_addr; uint32_t fdt_load_addr; uint64_t kernel_entry; DeviceState *mmio_plic, *virtio_plic, *pcie_plic; - int i, j, base_hartid, hart_count; + int i, base_hartid, hart_count; /* Check socket count limit */ if (VIRT_SOCKETS_MAX < riscv_socket_count(machine)) { @@ -603,17 +620,7 @@ static void virt_machine_init(MachineState *machine) SIFIVE_CLINT_TIMEBASE_FREQ, true); /* Per-socket PLIC hart topology configuration string */ - plic_hart_config_len = - (strlen(VIRT_PLIC_HART_CONFIG) + 1) * hart_count; - plic_hart_config = g_malloc0(plic_hart_config_len); - for (j = 0; j < hart_count; j++) { - if (j != 0) { - strncat(plic_hart_config, ",", plic_hart_config_len); - } - strncat(plic_hart_config, VIRT_PLIC_HART_CONFIG, - plic_hart_config_len); - plic_hart_config_len -= (strlen(VIRT_PLIC_HART_CONFIG) + 1); - } + plic_hart_config = plic_hart_config_string(hart_count); /* Per-socket PLIC */ s->plic[i] = sifive_plic_create( -- cgit v1.1 From 4dc06bb8167fb18b8eb7e40762a94dcc36101047 Mon Sep 17 00:00:00 2001 From: David Hoppenbrouwers Date: Fri, 27 Aug 2021 17:23:25 +0200 Subject: hw/intc/sifive_clint: Fix muldiv64 overflow in sifive_clint_write_timecmp() `muldiv64` would overflow in cases where the final 96-bit value does not fit in a `uint64_t`. This would result in small values that cause an interrupt to be triggered much sooner than intended. The overflow can be detected in most cases by checking if the new value is smaller than the previous value. If the final result is larger than `diff` it is either correct or it doesn't matter as it is effectively infinite anyways. `next` is an `uint64_t` value, but `timer_mod` takes an `int64_t`. This resulted in high values such as `UINT64_MAX` being converted to `-1`, which caused an immediate timer interrupt. By limiting `next` to `INT64_MAX` no overflow will happen while the timer will still be effectively set to "infinitely" far in the future. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/493 Signed-off-by: David Hoppenbrouwers Reviewed-by: Alistair Francis Message-id: 20210827152324.5201-1-david@salt-inc.org Signed-off-by: Alistair Francis --- hw/intc/sifive_clint.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/hw/intc/sifive_clint.c b/hw/intc/sifive_clint.c index 0f41e5e..99c870c 100644 --- a/hw/intc/sifive_clint.c +++ b/hw/intc/sifive_clint.c @@ -59,8 +59,29 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value, riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(0)); diff = cpu->env.timecmp - rtc_r; /* back to ns (note args switched in muldiv64) */ - next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq); + uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq); + + /* + * check if ns_diff overflowed and check if the addition would potentially + * overflow + */ + if ((NANOSECONDS_PER_SECOND > timebase_freq && ns_diff < diff) || + ns_diff > INT64_MAX) { + next = INT64_MAX; + } else { + /* + * as it is very unlikely qemu_clock_get_ns will return a value + * greater than INT64_MAX, no additional check is needed for an + * unsigned integer overflow. + */ + next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns_diff; + /* + * if ns_diff is INT64_MAX next may still be outside the range + * of a signed integer. + */ + next = MIN(next, INT64_MAX); + } + timer_mod(cpu->env.timer, next); } -- cgit v1.1 From 4d63ef20cf970901be1d6dd98743a4851e48f938 Mon Sep 17 00:00:00 2001 From: Joe Komlodi Date: Tue, 20 Jul 2021 11:31:42 -0700 Subject: hw/core/register: Add more 64-bit utilities We already have some utilities to handle 64-bit wide registers, so this just adds some more for: - Initializing 64-bit registers - Extracting and depositing to an array of 64-bit registers Signed-off-by: Joe Komlodi Reviewed-by: Alistair Francis Message-id: 1626805903-162860-2-git-send-email-joe.komlodi@xilinx.com Signed-off-by: Alistair Francis --- hw/core/register.c | 12 ++++++++++++ include/hw/register.h | 8 ++++++++ include/hw/registerfields.h | 8 ++++++++ 3 files changed, 28 insertions(+) diff --git a/hw/core/register.c b/hw/core/register.c index d6f8c20..95b0150 100644 --- a/hw/core/register.c +++ b/hw/core/register.c @@ -300,6 +300,18 @@ RegisterInfoArray *register_init_block32(DeviceState *owner, data, ops, debug_enabled, memory_size, 32); } +RegisterInfoArray *register_init_block64(DeviceState *owner, + const RegisterAccessInfo *rae, + int num, RegisterInfo *ri, + uint64_t *data, + const MemoryRegionOps *ops, + bool debug_enabled, + uint64_t memory_size) +{ + return register_init_block(owner, rae, num, ri, (void *) + data, ops, debug_enabled, memory_size, 64); +} + void register_finalize_block(RegisterInfoArray *r_array) { object_unparent(OBJECT(&r_array->mem)); diff --git a/include/hw/register.h b/include/hw/register.h index b480e38..6a076cf 100644 --- a/include/hw/register.h +++ b/include/hw/register.h @@ -204,6 +204,14 @@ RegisterInfoArray *register_init_block32(DeviceState *owner, bool debug_enabled, uint64_t memory_size); +RegisterInfoArray *register_init_block64(DeviceState *owner, + const RegisterAccessInfo *rae, + int num, RegisterInfo *ri, + uint64_t *data, + const MemoryRegionOps *ops, + bool debug_enabled, + uint64_t memory_size); + /** * This function should be called to cleanup the registers that were initialized * when calling register_init_block32(). This function should only be called diff --git a/include/hw/registerfields.h b/include/hw/registerfields.h index 93fa4a8..9a03ac5 100644 --- a/include/hw/registerfields.h +++ b/include/hw/registerfields.h @@ -30,6 +30,10 @@ enum { A_ ## reg = (addr) }; \ enum { R_ ## reg = (addr) / 2 }; +#define REG64(reg, addr) \ + enum { A_ ## reg = (addr) }; \ + enum { R_ ## reg = (addr) / 8 }; + /* Define SHIFT, LENGTH and MASK constants for a field within a register */ /* This macro will define R_FOO_BAR_MASK, R_FOO_BAR_SHIFT and R_FOO_BAR_LENGTH @@ -58,6 +62,8 @@ /* Extract a field from an array of registers */ #define ARRAY_FIELD_EX32(regs, reg, field) \ FIELD_EX32((regs)[R_ ## reg], reg, field) +#define ARRAY_FIELD_EX64(regs, reg, field) \ + FIELD_EX64((regs)[R_ ## reg], reg, field) /* Deposit a register field. * Assigning values larger then the target field will result in @@ -99,5 +105,7 @@ /* Deposit a field to array of registers. */ #define ARRAY_FIELD_DP32(regs, reg, field, val) \ (regs)[R_ ## reg] = FIELD_DP32((regs)[R_ ## reg], reg, field, val); +#define ARRAY_FIELD_DP64(regs, reg, field, val) \ + (regs)[R_ ## reg] = FIELD_DP64((regs)[R_ ## reg], reg, field, val); #endif -- cgit v1.1 From 2a4b4089305daf98a42f165111474ae3e92d5f1f Mon Sep 17 00:00:00 2001 From: Joe Komlodi Date: Tue, 20 Jul 2021 11:31:43 -0700 Subject: hw/registerfields: Use 64-bit bitfield for FIELD_DP64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we have a field that's wider than 32-bits, we need a data type wide enough to be able to create the bitfield used to deposit the value. Signed-off-by: Joe Komlodi Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 1626805903-162860-3-git-send-email-joe.komlodi@xilinx.com Signed-off-by: Alistair Francis --- include/hw/registerfields.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hw/registerfields.h b/include/hw/registerfields.h index 9a03ac5..f2a3c9c 100644 --- a/include/hw/registerfields.h +++ b/include/hw/registerfields.h @@ -95,7 +95,7 @@ _d; }) #define FIELD_DP64(storage, reg, field, val) ({ \ struct { \ - unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \ + uint64_t v:R_ ## reg ## _ ## field ## _LENGTH; \ } _v = { .v = val }; \ uint64_t _d; \ _d = deposit64((storage), R_ ## reg ## _ ## field ## _SHIFT, \ -- cgit v1.1 From 05b80ed0a17201858a924f1bfc21508930e13073 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:06 -0700 Subject: target/riscv: Use tcg_constant_* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace uses of tcg_const_* with the allocate and free close together. Reviewed-by: Bin Meng Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20210823195529.560295-2-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvf.c.inc | 3 +- target/riscv/insn_trans/trans_rvv.c.inc | 65 ++++++++++++--------------------- target/riscv/translate.c | 36 +++++------------- 3 files changed, 34 insertions(+), 70 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvf.c.inc b/target/riscv/insn_trans/trans_rvf.c.inc index db1c0c9..89f7870 100644 --- a/target/riscv/insn_trans/trans_rvf.c.inc +++ b/target/riscv/insn_trans/trans_rvf.c.inc @@ -200,12 +200,11 @@ static bool trans_fsgnjn_s(DisasContext *ctx, arg_fsgnjn_s *a) * Replace bit 31 in rs1 with inverse in rs2. * This formulation retains the nanboxing of rs1. */ - mask = tcg_const_i64(~MAKE_64BIT_MASK(31, 1)); + mask = tcg_constant_i64(~MAKE_64BIT_MASK(31, 1)); tcg_gen_nor_i64(rs2, rs2, mask); tcg_gen_and_i64(rs1, mask, rs1); tcg_gen_or_i64(cpu_fpr[a->rd], rs1, rs2); - tcg_temp_free_i64(mask); tcg_temp_free_i64(rs2); } tcg_temp_free_i64(rs1); diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 83d9a28..a8e7272 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -33,7 +33,7 @@ static bool trans_vsetvl(DisasContext *ctx, arg_vsetvl *a) /* Using x0 as the rs1 register specifier, encodes an infinite AVL */ if (a->rs1 == 0) { /* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */ - s1 = tcg_const_tl(RV_VLEN_MAX); + s1 = tcg_constant_tl(RV_VLEN_MAX); } else { s1 = tcg_temp_new(); gen_get_gpr(s1, a->rs1); @@ -59,13 +59,13 @@ static bool trans_vsetvli(DisasContext *ctx, arg_vsetvli *a) return false; } - s2 = tcg_const_tl(a->zimm); + s2 = tcg_constant_tl(a->zimm); dst = tcg_temp_new(); /* Using x0 as the rs1 register specifier, encodes an infinite AVL */ if (a->rs1 == 0) { /* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */ - s1 = tcg_const_tl(RV_VLEN_MAX); + s1 = tcg_constant_tl(RV_VLEN_MAX); } else { s1 = tcg_temp_new(); gen_get_gpr(s1, a->rs1); @@ -76,7 +76,6 @@ static bool trans_vsetvli(DisasContext *ctx, arg_vsetvli *a) ctx->base.is_jmp = DISAS_NORETURN; tcg_temp_free(s1); - tcg_temp_free(s2); tcg_temp_free(dst); return true; } @@ -183,7 +182,7 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data, * The first part is vlen in bytes, encoded in maxsz of simd_desc. * The second part is lmul, encoded in data of simd_desc. */ - desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); + desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); gen_get_gpr(base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); @@ -194,7 +193,6 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data, tcg_temp_free_ptr(dest); tcg_temp_free_ptr(mask); tcg_temp_free(base); - tcg_temp_free_i32(desc); gen_set_label(over); return true; } @@ -334,7 +332,7 @@ static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, uint32_t rs2, mask = tcg_temp_new_ptr(); base = tcg_temp_new(); stride = tcg_temp_new(); - desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); + desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); gen_get_gpr(base, rs1); gen_get_gpr(stride, rs2); @@ -347,7 +345,6 @@ static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, uint32_t rs2, tcg_temp_free_ptr(mask); tcg_temp_free(base); tcg_temp_free(stride); - tcg_temp_free_i32(desc); gen_set_label(over); return true; } @@ -462,7 +459,7 @@ static bool ldst_index_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, mask = tcg_temp_new_ptr(); index = tcg_temp_new_ptr(); base = tcg_temp_new(); - desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); + desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); gen_get_gpr(base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); @@ -475,7 +472,6 @@ static bool ldst_index_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, tcg_temp_free_ptr(mask); tcg_temp_free_ptr(index); tcg_temp_free(base); - tcg_temp_free_i32(desc); gen_set_label(over); return true; } @@ -594,7 +590,7 @@ static bool ldff_trans(uint32_t vd, uint32_t rs1, uint32_t data, dest = tcg_temp_new_ptr(); mask = tcg_temp_new_ptr(); base = tcg_temp_new(); - desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); + desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); gen_get_gpr(base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); @@ -605,7 +601,6 @@ static bool ldff_trans(uint32_t vd, uint32_t rs1, uint32_t data, tcg_temp_free_ptr(dest); tcg_temp_free_ptr(mask); tcg_temp_free(base); - tcg_temp_free_i32(desc); gen_set_label(over); return true; } @@ -671,7 +666,7 @@ static bool amo_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, mask = tcg_temp_new_ptr(); index = tcg_temp_new_ptr(); base = tcg_temp_new(); - desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); + desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); gen_get_gpr(base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); @@ -684,7 +679,6 @@ static bool amo_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, tcg_temp_free_ptr(mask); tcg_temp_free_ptr(index); tcg_temp_free(base); - tcg_temp_free_i32(desc); gen_set_label(over); return true; } @@ -874,7 +868,7 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm, data = FIELD_DP32(data, VDATA, MLEN, s->mlen); data = FIELD_DP32(data, VDATA, VM, vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); - desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); + desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2)); @@ -886,7 +880,6 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm, tcg_temp_free_ptr(mask); tcg_temp_free_ptr(src2); tcg_temp_free(src1); - tcg_temp_free_i32(desc); gen_set_label(over); return true; } @@ -1014,14 +1007,14 @@ static bool opivi_trans(uint32_t vd, uint32_t imm, uint32_t vs2, uint32_t vm, mask = tcg_temp_new_ptr(); src2 = tcg_temp_new_ptr(); if (zx) { - src1 = tcg_const_tl(imm); + src1 = tcg_constant_tl(imm); } else { - src1 = tcg_const_tl(sextract64(imm, 0, 5)); + src1 = tcg_constant_tl(sextract64(imm, 0, 5)); } data = FIELD_DP32(data, VDATA, MLEN, s->mlen); data = FIELD_DP32(data, VDATA, VM, vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); - desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); + desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2)); @@ -1032,8 +1025,6 @@ static bool opivi_trans(uint32_t vd, uint32_t imm, uint32_t vs2, uint32_t vm, tcg_temp_free_ptr(dest); tcg_temp_free_ptr(mask); tcg_temp_free_ptr(src2); - tcg_temp_free(src1); - tcg_temp_free_i32(desc); gen_set_label(over); return true; } @@ -1080,9 +1071,8 @@ GEN_OPIVI_GVEC_TRANS(vadd_vi, 0, vadd_vx, addi) static void tcg_gen_gvec_rsubi(unsigned vece, uint32_t dofs, uint32_t aofs, int64_t c, uint32_t oprsz, uint32_t maxsz) { - TCGv_i64 tmp = tcg_const_i64(c); + TCGv_i64 tmp = tcg_constant_i64(c); tcg_gen_gvec_rsubs(vece, dofs, aofs, tmp, oprsz, maxsz); - tcg_temp_free_i64(tmp); } GEN_OPIVI_GVEC_TRANS(vrsub_vi, 0, vrsub_vx, rsubi) @@ -1682,7 +1672,7 @@ static bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x *a) tcg_gen_gvec_dup_tl(s->sew, vreg_ofs(s, a->rd), MAXSZ(s), MAXSZ(s), s1); } else { - TCGv_i32 desc ; + 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); @@ -1692,12 +1682,11 @@ static bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x *a) }; tcg_gen_ext_tl_i64(s1_i64, s1); - desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); + desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd)); fns[s->sew](dest, s1_i64, cpu_env, desc); tcg_temp_free_ptr(dest); - tcg_temp_free_i32(desc); tcg_temp_free_i64(s1_i64); } @@ -1729,15 +1718,13 @@ static bool trans_vmv_v_i(DisasContext *s, arg_vmv_v_i *a) TCGLabel *over = gen_new_label(); tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); - s1 = tcg_const_i64(simm); + s1 = tcg_constant_i64(simm); dest = tcg_temp_new_ptr(); - desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); + desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd)); fns[s->sew](dest, s1, cpu_env, desc); tcg_temp_free_ptr(dest); - tcg_temp_free_i32(desc); - tcg_temp_free_i64(s1); gen_set_label(over); } return true; @@ -1866,7 +1853,7 @@ static bool opfvf_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, dest = tcg_temp_new_ptr(); mask = tcg_temp_new_ptr(); src2 = tcg_temp_new_ptr(); - desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); + desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2)); @@ -1877,7 +1864,6 @@ static bool opfvf_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, tcg_temp_free_ptr(dest); tcg_temp_free_ptr(mask); tcg_temp_free_ptr(src2); - tcg_temp_free_i32(desc); gen_set_label(over); return true; } @@ -2231,12 +2217,11 @@ static bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a) tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); dest = tcg_temp_new_ptr(); - desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); + desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd)); fns[s->sew - 1](dest, cpu_fpr[a->rs1], cpu_env, desc); tcg_temp_free_ptr(dest); - tcg_temp_free_i32(desc); gen_set_label(over); } return true; @@ -2428,7 +2413,7 @@ static bool trans_vmpopc_m(DisasContext *s, arg_rmr *a) mask = tcg_temp_new_ptr(); src2 = tcg_temp_new_ptr(); dst = tcg_temp_new(); - desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); + desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); @@ -2439,7 +2424,6 @@ static bool trans_vmpopc_m(DisasContext *s, arg_rmr *a) tcg_temp_free_ptr(mask); tcg_temp_free_ptr(src2); tcg_temp_free(dst); - tcg_temp_free_i32(desc); return true; } return false; @@ -2460,7 +2444,7 @@ static bool trans_vmfirst_m(DisasContext *s, arg_rmr *a) mask = tcg_temp_new_ptr(); src2 = tcg_temp_new_ptr(); dst = tcg_temp_new(); - desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); + desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); @@ -2471,7 +2455,6 @@ static bool trans_vmfirst_m(DisasContext *s, arg_rmr *a) tcg_temp_free_ptr(mask); tcg_temp_free_ptr(src2); tcg_temp_free(dst); - tcg_temp_free_i32(desc); return true; } return false; @@ -2636,15 +2619,13 @@ static void vec_element_loadx(DisasContext *s, TCGv_i64 dest, tcg_temp_free_i32(ofs); /* Flush out-of-range indexing to zero. */ - t_vlmax = tcg_const_i64(vlmax); - t_zero = tcg_const_i64(0); + t_vlmax = tcg_constant_i64(vlmax); + t_zero = tcg_constant_i64(0); tcg_gen_extu_tl_i64(t_idx, idx); tcg_gen_movcond_i64(TCG_COND_LTU, dest, t_idx, t_vlmax, dest, t_zero); - tcg_temp_free_i64(t_vlmax); - tcg_temp_free_i64(t_zero); tcg_temp_free_i64(t_idx); } diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 6983be5..20a55c9 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -104,20 +104,16 @@ static void gen_nanbox_s(TCGv_i64 out, TCGv_i64 in) */ static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in) { - TCGv_i64 t_max = tcg_const_i64(0xffffffff00000000ull); - TCGv_i64 t_nan = tcg_const_i64(0xffffffff7fc00000ull); + TCGv_i64 t_max = tcg_constant_i64(0xffffffff00000000ull); + TCGv_i64 t_nan = tcg_constant_i64(0xffffffff7fc00000ull); tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan); - tcg_temp_free_i64(t_max); - tcg_temp_free_i64(t_nan); } static void generate_exception(DisasContext *ctx, int excp) { tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); - TCGv_i32 helper_tmp = tcg_const_i32(excp); - gen_helper_raise_exception(cpu_env, helper_tmp); - tcg_temp_free_i32(helper_tmp); + gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp)); ctx->base.is_jmp = DISAS_NORETURN; } @@ -125,17 +121,13 @@ static void generate_exception_mtval(DisasContext *ctx, int excp) { tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr)); - TCGv_i32 helper_tmp = tcg_const_i32(excp); - gen_helper_raise_exception(cpu_env, helper_tmp); - tcg_temp_free_i32(helper_tmp); + gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp)); ctx->base.is_jmp = DISAS_NORETURN; } static void gen_exception_debug(void) { - TCGv_i32 helper_tmp = tcg_const_i32(EXCP_DEBUG); - gen_helper_raise_exception(cpu_env, helper_tmp); - tcg_temp_free_i32(helper_tmp); + gen_helper_raise_exception(cpu_env, tcg_constant_i32(EXCP_DEBUG)); } /* Wrapper around tcg_gen_exit_tb that handles single stepping */ @@ -229,7 +221,7 @@ static void gen_div(TCGv ret, TCGv source1, TCGv source2) */ cond1 = tcg_temp_new(); cond2 = tcg_temp_new(); - zeroreg = tcg_const_tl(0); + zeroreg = tcg_constant_tl(0); resultopt1 = tcg_temp_new(); tcg_gen_movi_tl(resultopt1, (target_ulong)-1); @@ -250,7 +242,6 @@ static void gen_div(TCGv ret, TCGv source1, TCGv source2) tcg_temp_free(cond1); tcg_temp_free(cond2); - tcg_temp_free(zeroreg); tcg_temp_free(resultopt1); } @@ -259,7 +250,7 @@ static void gen_divu(TCGv ret, TCGv source1, TCGv source2) TCGv cond1, zeroreg, resultopt1; cond1 = tcg_temp_new(); - zeroreg = tcg_const_tl(0); + zeroreg = tcg_constant_tl(0); resultopt1 = tcg_temp_new(); tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); @@ -272,7 +263,6 @@ static void gen_divu(TCGv ret, TCGv source1, TCGv source2) tcg_gen_divu_tl(ret, source1, source2); tcg_temp_free(cond1); - tcg_temp_free(zeroreg); tcg_temp_free(resultopt1); } @@ -282,7 +272,7 @@ static void gen_rem(TCGv ret, TCGv source1, TCGv source2) cond1 = tcg_temp_new(); cond2 = tcg_temp_new(); - zeroreg = tcg_const_tl(0); + zeroreg = tcg_constant_tl(0); resultopt1 = tcg_temp_new(); tcg_gen_movi_tl(resultopt1, 1L); @@ -302,7 +292,6 @@ static void gen_rem(TCGv ret, TCGv source1, TCGv source2) tcg_temp_free(cond1); tcg_temp_free(cond2); - tcg_temp_free(zeroreg); tcg_temp_free(resultopt1); } @@ -310,7 +299,7 @@ static void gen_remu(TCGv ret, TCGv source1, TCGv source2) { TCGv cond1, zeroreg, resultopt1; cond1 = tcg_temp_new(); - zeroreg = tcg_const_tl(0); + zeroreg = tcg_constant_tl(0); resultopt1 = tcg_temp_new(); tcg_gen_movi_tl(resultopt1, (target_ulong)1); @@ -323,7 +312,6 @@ static void gen_remu(TCGv ret, TCGv source1, TCGv source2) source1); tcg_temp_free(cond1); - tcg_temp_free(zeroreg); tcg_temp_free(resultopt1); } @@ -384,15 +372,11 @@ static inline void mark_fs_dirty(DisasContext *ctx) { } static void gen_set_rm(DisasContext *ctx, int rm) { - TCGv_i32 t0; - if (ctx->frm == rm) { return; } ctx->frm = rm; - t0 = tcg_const_i32(rm); - gen_helper_set_rounding_mode(cpu_env, t0); - tcg_temp_free_i32(t0); + gen_helper_set_rounding_mode(cpu_env, tcg_constant_i32(rm)); } static int ex_plus_1(DisasContext *ctx, int nf) -- cgit v1.1 From 9b17ae9c6a143caebdbb9a0c0b2ba66bae900f56 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:07 -0700 Subject: tests/tcg/riscv64: Add test for division Tested-by: Bin Meng Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20210823195529.560295-3-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- tests/tcg/riscv64/Makefile.target | 5 ++++ tests/tcg/riscv64/test-div.c | 58 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 tests/tcg/riscv64/Makefile.target create mode 100644 tests/tcg/riscv64/test-div.c diff --git a/tests/tcg/riscv64/Makefile.target b/tests/tcg/riscv64/Makefile.target new file mode 100644 index 0000000..d41bf6d --- /dev/null +++ b/tests/tcg/riscv64/Makefile.target @@ -0,0 +1,5 @@ +# -*- Mode: makefile -*- +# RISC-V specific tweaks + +VPATH += $(SRC_PATH)/tests/tcg/riscv64 +TESTS += test-div diff --git a/tests/tcg/riscv64/test-div.c b/tests/tcg/riscv64/test-div.c new file mode 100644 index 0000000..a90480b --- /dev/null +++ b/tests/tcg/riscv64/test-div.c @@ -0,0 +1,58 @@ +#include +#include + +struct TestS { + long x, y, q, r; +}; + +static struct TestS test_s[] = { + { 4, 2, 2, 0 }, /* normal cases */ + { 9, 7, 1, 2 }, + { 0, 0, -1, 0 }, /* div by zero cases */ + { 9, 0, -1, 9 }, + { LONG_MIN, -1, LONG_MIN, 0 }, /* overflow case */ +}; + +struct TestU { + unsigned long x, y, q, r; +}; + +static struct TestU test_u[] = { + { 4, 2, 2, 0 }, /* normal cases */ + { 9, 7, 1, 2 }, + { 0, 0, ULONG_MAX, 0 }, /* div by zero cases */ + { 9, 0, ULONG_MAX, 9 }, +}; + +#define ARRAY_SIZE(X) (sizeof(X) / sizeof(*(X))) + +int main (void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(test_s); i++) { + long q, r; + + asm("div %0, %2, %3\n\t" + "rem %1, %2, %3" + : "=&r" (q), "=r" (r) + : "r" (test_s[i].x), "r" (test_s[i].y)); + + assert(q == test_s[i].q); + assert(r == test_s[i].r); + } + + for (i = 0; i < ARRAY_SIZE(test_u); i++) { + unsigned long q, r; + + asm("divu %0, %2, %3\n\t" + "remu %1, %2, %3" + : "=&r" (q), "=r" (r) + : "r" (test_u[i].x), "r" (test_u[i].y)); + + assert(q == test_u[i].q); + assert(r == test_u[i].r); + } + + return 0; +} -- cgit v1.1 From 4a083b563a2c1bfed9c2b9dc5267d149ea109bde Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:08 -0700 Subject: target/riscv: Clean up division helpers Utilize the condition in the movcond more; this allows some of the setcond that were feeding into movcond to be removed. Do not write into source1 and source2. Re-name "condN" to "tempN" and use the temporaries for more than holding conditions. Tested-by: Bin Meng Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20210823195529.560295-4-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/translate.c | 174 +++++++++++++++++++++++++---------------------- 1 file changed, 91 insertions(+), 83 deletions(-) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 20a55c9..147b9c2 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -213,106 +213,114 @@ static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2) static void gen_div(TCGv ret, TCGv source1, TCGv source2) { - TCGv cond1, cond2, zeroreg, resultopt1; + TCGv temp1, temp2, zero, one, mone, min; + + temp1 = tcg_temp_new(); + temp2 = tcg_temp_new(); + zero = tcg_constant_tl(0); + one = tcg_constant_tl(1); + mone = tcg_constant_tl(-1); + min = tcg_constant_tl(1ull << (TARGET_LONG_BITS - 1)); + /* - * Handle by altering args to tcg_gen_div to produce req'd results: - * For overflow: want source1 in source1 and 1 in source2 - * For div by zero: want -1 in source1 and 1 in source2 -> -1 result + * If overflow, set temp2 to 1, else source2. + * This produces the required result of min. */ - cond1 = tcg_temp_new(); - cond2 = tcg_temp_new(); - zeroreg = tcg_constant_tl(0); - resultopt1 = tcg_temp_new(); - - tcg_gen_movi_tl(resultopt1, (target_ulong)-1); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, (target_ulong)(~0L)); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1, - ((target_ulong)1) << (TARGET_LONG_BITS - 1)); - tcg_gen_and_tl(cond1, cond1, cond2); /* cond1 = overflow */ - tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, 0); /* cond2 = div 0 */ - /* if div by zero, set source1 to -1, otherwise don't change */ - tcg_gen_movcond_tl(TCG_COND_EQ, source1, cond2, zeroreg, source1, - resultopt1); - /* if overflow or div by zero, set source2 to 1, else don't change */ - tcg_gen_or_tl(cond1, cond1, cond2); - tcg_gen_movi_tl(resultopt1, (target_ulong)1); - tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, - resultopt1); - tcg_gen_div_tl(ret, source1, source2); - - tcg_temp_free(cond1); - tcg_temp_free(cond2); - tcg_temp_free(resultopt1); + tcg_gen_setcond_tl(TCG_COND_EQ, temp1, source1, min); + tcg_gen_setcond_tl(TCG_COND_EQ, temp2, source2, mone); + tcg_gen_and_tl(temp1, temp1, temp2); + tcg_gen_movcond_tl(TCG_COND_NE, temp2, temp1, zero, one, source2); + + /* + * If div by zero, set temp1 to -1 and temp2 to 1 to + * produce the required result of -1. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, temp1, source2, zero, mone, source1); + tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, temp2); + + tcg_gen_div_tl(ret, temp1, temp2); + + tcg_temp_free(temp1); + tcg_temp_free(temp2); } static void gen_divu(TCGv ret, TCGv source1, TCGv source2) { - TCGv cond1, zeroreg, resultopt1; - cond1 = tcg_temp_new(); + TCGv temp1, temp2, zero, one, max; - zeroreg = tcg_constant_tl(0); - resultopt1 = tcg_temp_new(); + temp1 = tcg_temp_new(); + temp2 = tcg_temp_new(); + zero = tcg_constant_tl(0); + one = tcg_constant_tl(1); + max = tcg_constant_tl(~0); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); - tcg_gen_movi_tl(resultopt1, (target_ulong)-1); - tcg_gen_movcond_tl(TCG_COND_EQ, source1, cond1, zeroreg, source1, - resultopt1); - tcg_gen_movi_tl(resultopt1, (target_ulong)1); - tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, - resultopt1); - tcg_gen_divu_tl(ret, source1, source2); + /* + * If div by zero, set temp1 to max and temp2 to 1 to + * produce the required result of max. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, temp1, source2, zero, max, source1); + tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, source2); + tcg_gen_divu_tl(ret, temp1, temp2); - tcg_temp_free(cond1); - tcg_temp_free(resultopt1); + tcg_temp_free(temp1); + tcg_temp_free(temp2); } static void gen_rem(TCGv ret, TCGv source1, TCGv source2) { - TCGv cond1, cond2, zeroreg, resultopt1; - - cond1 = tcg_temp_new(); - cond2 = tcg_temp_new(); - zeroreg = tcg_constant_tl(0); - resultopt1 = tcg_temp_new(); - - tcg_gen_movi_tl(resultopt1, 1L); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, (target_ulong)-1); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1, - (target_ulong)1 << (TARGET_LONG_BITS - 1)); - tcg_gen_and_tl(cond2, cond1, cond2); /* cond1 = overflow */ - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); /* cond2 = div 0 */ - /* if overflow or div by zero, set source2 to 1, else don't change */ - tcg_gen_or_tl(cond2, cond1, cond2); - tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond2, zeroreg, source2, - resultopt1); - tcg_gen_rem_tl(resultopt1, source1, source2); - /* if div by zero, just return the original dividend */ - tcg_gen_movcond_tl(TCG_COND_EQ, ret, cond1, zeroreg, resultopt1, - source1); - - tcg_temp_free(cond1); - tcg_temp_free(cond2); - tcg_temp_free(resultopt1); + TCGv temp1, temp2, zero, one, mone, min; + + temp1 = tcg_temp_new(); + temp2 = tcg_temp_new(); + zero = tcg_constant_tl(0); + one = tcg_constant_tl(1); + mone = tcg_constant_tl(-1); + min = tcg_constant_tl(1ull << (TARGET_LONG_BITS - 1)); + + /* + * If overflow, set temp1 to 0, else source1. + * This avoids a possible host trap, and produces the required result of 0. + */ + tcg_gen_setcond_tl(TCG_COND_EQ, temp1, source1, min); + tcg_gen_setcond_tl(TCG_COND_EQ, temp2, source2, mone); + tcg_gen_and_tl(temp1, temp1, temp2); + tcg_gen_movcond_tl(TCG_COND_NE, temp1, temp1, zero, zero, source1); + + /* + * If div by zero, set temp2 to 1, else source2. + * This avoids a possible host trap, but produces an incorrect result. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, source2); + + tcg_gen_rem_tl(temp1, temp1, temp2); + + /* If div by zero, the required result is the original dividend. */ + tcg_gen_movcond_tl(TCG_COND_EQ, ret, source2, zero, source1, temp1); + + tcg_temp_free(temp1); + tcg_temp_free(temp2); } static void gen_remu(TCGv ret, TCGv source1, TCGv source2) { - TCGv cond1, zeroreg, resultopt1; - cond1 = tcg_temp_new(); - zeroreg = tcg_constant_tl(0); - resultopt1 = tcg_temp_new(); - - tcg_gen_movi_tl(resultopt1, (target_ulong)1); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); - tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, - resultopt1); - tcg_gen_remu_tl(resultopt1, source1, source2); - /* if div by zero, just return the original dividend */ - tcg_gen_movcond_tl(TCG_COND_EQ, ret, cond1, zeroreg, resultopt1, - source1); - - tcg_temp_free(cond1); - tcg_temp_free(resultopt1); + TCGv temp, zero, one; + + temp = tcg_temp_new(); + zero = tcg_constant_tl(0); + one = tcg_constant_tl(1); + + /* + * If div by zero, set temp to 1, else source2. + * This avoids a possible host trap, but produces an incorrect result. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, temp, source2, zero, one, source2); + + tcg_gen_remu_tl(temp, source1, temp); + + /* If div by zero, the required result is the original dividend. */ + tcg_gen_movcond_tl(TCG_COND_EQ, ret, source2, zero, source1, temp); + + tcg_temp_free(temp); } static void gen_jal(DisasContext *ctx, int rd, target_ulong imm) -- cgit v1.1 From 867c81968a72e2250604963ea8cacf47c434651f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:09 -0700 Subject: target/riscv: Add DisasContext to gen_get_gpr, gen_set_gpr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We will require the context to handle RV64 word operations. Reviewed-by: Alistair Francis Reviewed-by: Bin Meng Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Message-id: 20210823195529.560295-5-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rva.c.inc | 18 +++++----- target/riscv/insn_trans/trans_rvb.c.inc | 4 +-- target/riscv/insn_trans/trans_rvd.c.inc | 32 +++++++++--------- target/riscv/insn_trans/trans_rvf.c.inc | 32 +++++++++--------- target/riscv/insn_trans/trans_rvh.c.inc | 52 ++++++++++++++--------------- target/riscv/insn_trans/trans_rvi.c.inc | 44 ++++++++++++------------- target/riscv/insn_trans/trans_rvm.c.inc | 12 +++---- target/riscv/insn_trans/trans_rvv.c.inc | 36 ++++++++++---------- target/riscv/translate.c | 58 ++++++++++++++++----------------- 9 files changed, 144 insertions(+), 144 deletions(-) diff --git a/target/riscv/insn_trans/trans_rva.c.inc b/target/riscv/insn_trans/trans_rva.c.inc index ab2ec4f..3cc3c3b 100644 --- a/target/riscv/insn_trans/trans_rva.c.inc +++ b/target/riscv/insn_trans/trans_rva.c.inc @@ -22,7 +22,7 @@ static inline bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop) { TCGv src1 = tcg_temp_new(); /* Put addr in load_res, data in load_val. */ - gen_get_gpr(src1, a->rs1); + gen_get_gpr(ctx, src1, a->rs1); if (a->rl) { tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL); } @@ -31,7 +31,7 @@ static inline bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop) tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ); } tcg_gen_mov_tl(load_res, src1); - gen_set_gpr(a->rd, load_val); + gen_set_gpr(ctx, a->rd, load_val); tcg_temp_free(src1); return true; @@ -45,10 +45,10 @@ static inline bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) TCGLabel *l1 = gen_new_label(); TCGLabel *l2 = gen_new_label(); - gen_get_gpr(src1, a->rs1); + gen_get_gpr(ctx, src1, a->rs1); tcg_gen_brcond_tl(TCG_COND_NE, load_res, src1, l1); - gen_get_gpr(src2, a->rs2); + gen_get_gpr(ctx, src2, a->rs2); /* * Note that the TCG atomic primitives are SC, * so we can ignore AQ/RL along this path. @@ -56,7 +56,7 @@ static inline bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) tcg_gen_atomic_cmpxchg_tl(src1, load_res, load_val, src2, ctx->mem_idx, mop); tcg_gen_setcond_tl(TCG_COND_NE, dat, src1, load_val); - gen_set_gpr(a->rd, dat); + gen_set_gpr(ctx, a->rd, dat); tcg_gen_br(l2); gen_set_label(l1); @@ -66,7 +66,7 @@ static inline bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) */ tcg_gen_mb(TCG_MO_ALL + a->aq * TCG_BAR_LDAQ + a->rl * TCG_BAR_STRL); tcg_gen_movi_tl(dat, 1); - gen_set_gpr(a->rd, dat); + gen_set_gpr(ctx, a->rd, dat); gen_set_label(l2); /* @@ -88,12 +88,12 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a, TCGv src1 = tcg_temp_new(); TCGv src2 = tcg_temp_new(); - gen_get_gpr(src1, a->rs1); - gen_get_gpr(src2, a->rs2); + gen_get_gpr(ctx, src1, a->rs1); + gen_get_gpr(ctx, src2, a->rs2); (*func)(src2, src1, src2, ctx->mem_idx, mop); - gen_set_gpr(a->rd, src2); + gen_set_gpr(ctx, a->rd, src2); tcg_temp_free(src1); tcg_temp_free(src2); return true; diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 9e81f6e..260e15b 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -424,7 +424,7 @@ static bool trans_slli_uw(DisasContext *ctx, arg_slli_uw *a) REQUIRE_EXT(ctx, RVB); TCGv source1 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); + gen_get_gpr(ctx, source1, a->rs1); if (a->shamt < 32) { tcg_gen_deposit_z_tl(source1, source1, a->shamt, 32); @@ -432,7 +432,7 @@ static bool trans_slli_uw(DisasContext *ctx, arg_slli_uw *a) tcg_gen_shli_tl(source1, source1, a->shamt); } - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); return true; } diff --git a/target/riscv/insn_trans/trans_rvd.c.inc b/target/riscv/insn_trans/trans_rvd.c.inc index 7e45538..11b9b3f 100644 --- a/target/riscv/insn_trans/trans_rvd.c.inc +++ b/target/riscv/insn_trans/trans_rvd.c.inc @@ -23,7 +23,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_addi_tl(t0, t0, a->imm); tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], t0, ctx->mem_idx, MO_TEQ); @@ -38,7 +38,7 @@ static bool trans_fsd(DisasContext *ctx, arg_fsd *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_addi_tl(t0, t0, a->imm); tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEQ); @@ -254,7 +254,7 @@ static bool trans_feq_d(DisasContext *ctx, arg_feq_d *a) TCGv t0 = tcg_temp_new(); gen_helper_feq_d(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; @@ -267,7 +267,7 @@ static bool trans_flt_d(DisasContext *ctx, arg_flt_d *a) TCGv t0 = tcg_temp_new(); gen_helper_flt_d(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; @@ -280,7 +280,7 @@ static bool trans_fle_d(DisasContext *ctx, arg_fle_d *a) TCGv t0 = tcg_temp_new(); gen_helper_fle_d(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; @@ -293,7 +293,7 @@ static bool trans_fclass_d(DisasContext *ctx, arg_fclass_d *a) TCGv t0 = tcg_temp_new(); gen_helper_fclass_d(t0, cpu_fpr[a->rs1]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; } @@ -306,7 +306,7 @@ static bool trans_fcvt_w_d(DisasContext *ctx, arg_fcvt_w_d *a) TCGv t0 = tcg_temp_new(); gen_set_rm(ctx, a->rm); gen_helper_fcvt_w_d(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; @@ -320,7 +320,7 @@ static bool trans_fcvt_wu_d(DisasContext *ctx, arg_fcvt_wu_d *a) TCGv t0 = tcg_temp_new(); gen_set_rm(ctx, a->rm); gen_helper_fcvt_wu_d(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; @@ -332,7 +332,7 @@ static bool trans_fcvt_d_w(DisasContext *ctx, arg_fcvt_d_w *a) REQUIRE_EXT(ctx, RVD); TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); gen_set_rm(ctx, a->rm); gen_helper_fcvt_d_w(cpu_fpr[a->rd], cpu_env, t0); @@ -348,7 +348,7 @@ static bool trans_fcvt_d_wu(DisasContext *ctx, arg_fcvt_d_wu *a) REQUIRE_EXT(ctx, RVD); TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); gen_set_rm(ctx, a->rm); gen_helper_fcvt_d_wu(cpu_fpr[a->rd], cpu_env, t0); @@ -367,7 +367,7 @@ static bool trans_fcvt_l_d(DisasContext *ctx, arg_fcvt_l_d *a) TCGv t0 = tcg_temp_new(); gen_set_rm(ctx, a->rm); gen_helper_fcvt_l_d(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; } @@ -381,7 +381,7 @@ static bool trans_fcvt_lu_d(DisasContext *ctx, arg_fcvt_lu_d *a) TCGv t0 = tcg_temp_new(); gen_set_rm(ctx, a->rm); gen_helper_fcvt_lu_d(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; } @@ -393,7 +393,7 @@ static bool trans_fmv_x_d(DisasContext *ctx, arg_fmv_x_d *a) REQUIRE_EXT(ctx, RVD); #ifdef TARGET_RISCV64 - gen_set_gpr(a->rd, cpu_fpr[a->rs1]); + gen_set_gpr(ctx, a->rd, cpu_fpr[a->rs1]); return true; #else qemu_build_not_reached(); @@ -407,7 +407,7 @@ static bool trans_fcvt_d_l(DisasContext *ctx, arg_fcvt_d_l *a) REQUIRE_EXT(ctx, RVD); TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); gen_set_rm(ctx, a->rm); gen_helper_fcvt_d_l(cpu_fpr[a->rd], cpu_env, t0); @@ -423,7 +423,7 @@ static bool trans_fcvt_d_lu(DisasContext *ctx, arg_fcvt_d_lu *a) REQUIRE_EXT(ctx, RVD); TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); gen_set_rm(ctx, a->rm); gen_helper_fcvt_d_lu(cpu_fpr[a->rd], cpu_env, t0); @@ -440,7 +440,7 @@ static bool trans_fmv_d_x(DisasContext *ctx, arg_fmv_d_x *a) #ifdef TARGET_RISCV64 TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_mov_tl(cpu_fpr[a->rd], t0); tcg_temp_free(t0); diff --git a/target/riscv/insn_trans/trans_rvf.c.inc b/target/riscv/insn_trans/trans_rvf.c.inc index 89f7870..fb9f7f9 100644 --- a/target/riscv/insn_trans/trans_rvf.c.inc +++ b/target/riscv/insn_trans/trans_rvf.c.inc @@ -28,7 +28,7 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_addi_tl(t0, t0, a->imm); tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], t0, ctx->mem_idx, MO_TEUL); @@ -44,7 +44,7 @@ static bool trans_fsw(DisasContext *ctx, arg_fsw *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_addi_tl(t0, t0, a->imm); @@ -274,7 +274,7 @@ static bool trans_fcvt_w_s(DisasContext *ctx, arg_fcvt_w_s *a) TCGv t0 = tcg_temp_new(); gen_set_rm(ctx, a->rm); gen_helper_fcvt_w_s(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; @@ -288,7 +288,7 @@ static bool trans_fcvt_wu_s(DisasContext *ctx, arg_fcvt_wu_s *a) TCGv t0 = tcg_temp_new(); gen_set_rm(ctx, a->rm); gen_helper_fcvt_wu_s(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; @@ -308,7 +308,7 @@ static bool trans_fmv_x_w(DisasContext *ctx, arg_fmv_x_w *a) tcg_gen_extrl_i64_i32(t0, cpu_fpr[a->rs1]); #endif - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; @@ -320,7 +320,7 @@ static bool trans_feq_s(DisasContext *ctx, arg_feq_s *a) REQUIRE_EXT(ctx, RVF); TCGv t0 = tcg_temp_new(); gen_helper_feq_s(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; } @@ -331,7 +331,7 @@ static bool trans_flt_s(DisasContext *ctx, arg_flt_s *a) REQUIRE_EXT(ctx, RVF); TCGv t0 = tcg_temp_new(); gen_helper_flt_s(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; } @@ -342,7 +342,7 @@ static bool trans_fle_s(DisasContext *ctx, arg_fle_s *a) REQUIRE_EXT(ctx, RVF); TCGv t0 = tcg_temp_new(); gen_helper_fle_s(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; } @@ -356,7 +356,7 @@ static bool trans_fclass_s(DisasContext *ctx, arg_fclass_s *a) gen_helper_fclass_s(t0, cpu_fpr[a->rs1]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; @@ -368,7 +368,7 @@ static bool trans_fcvt_s_w(DisasContext *ctx, arg_fcvt_s_w *a) REQUIRE_EXT(ctx, RVF); TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); gen_set_rm(ctx, a->rm); gen_helper_fcvt_s_w(cpu_fpr[a->rd], cpu_env, t0); @@ -385,7 +385,7 @@ static bool trans_fcvt_s_wu(DisasContext *ctx, arg_fcvt_s_wu *a) REQUIRE_EXT(ctx, RVF); TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); gen_set_rm(ctx, a->rm); gen_helper_fcvt_s_wu(cpu_fpr[a->rd], cpu_env, t0); @@ -403,7 +403,7 @@ static bool trans_fmv_w_x(DisasContext *ctx, arg_fmv_w_x *a) REQUIRE_EXT(ctx, RVF); TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_extu_tl_i64(cpu_fpr[a->rd], t0); gen_nanbox_s(cpu_fpr[a->rd], cpu_fpr[a->rd]); @@ -423,7 +423,7 @@ static bool trans_fcvt_l_s(DisasContext *ctx, arg_fcvt_l_s *a) TCGv t0 = tcg_temp_new(); gen_set_rm(ctx, a->rm); gen_helper_fcvt_l_s(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; } @@ -437,7 +437,7 @@ static bool trans_fcvt_lu_s(DisasContext *ctx, arg_fcvt_lu_s *a) TCGv t0 = tcg_temp_new(); gen_set_rm(ctx, a->rm); gen_helper_fcvt_lu_s(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(a->rd, t0); + gen_set_gpr(ctx, a->rd, t0); tcg_temp_free(t0); return true; } @@ -449,7 +449,7 @@ static bool trans_fcvt_s_l(DisasContext *ctx, arg_fcvt_s_l *a) REQUIRE_EXT(ctx, RVF); TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); gen_set_rm(ctx, a->rm); gen_helper_fcvt_s_l(cpu_fpr[a->rd], cpu_env, t0); @@ -466,7 +466,7 @@ static bool trans_fcvt_s_lu(DisasContext *ctx, arg_fcvt_s_lu *a) REQUIRE_EXT(ctx, RVF); TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); gen_set_rm(ctx, a->rm); gen_helper_fcvt_s_lu(cpu_fpr[a->rd], cpu_env, t0); diff --git a/target/riscv/insn_trans/trans_rvh.c.inc b/target/riscv/insn_trans/trans_rvh.c.inc index 6b5edf8..585eb1d 100644 --- a/target/riscv/insn_trans/trans_rvh.c.inc +++ b/target/riscv/insn_trans/trans_rvh.c.inc @@ -37,10 +37,10 @@ static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a) check_access(ctx); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_SB); - gen_set_gpr(a->rd, t1); + gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); @@ -59,10 +59,10 @@ static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a) check_access(ctx); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESW); - gen_set_gpr(a->rd, t1); + gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); @@ -81,10 +81,10 @@ static bool trans_hlv_w(DisasContext *ctx, arg_hlv_w *a) check_access(ctx); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESL); - gen_set_gpr(a->rd, t1); + gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); @@ -103,10 +103,10 @@ static bool trans_hlv_bu(DisasContext *ctx, arg_hlv_bu *a) check_access(ctx); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_UB); - gen_set_gpr(a->rd, t1); + gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); @@ -125,9 +125,9 @@ static bool trans_hlv_hu(DisasContext *ctx, arg_hlv_hu *a) check_access(ctx); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUW); - gen_set_gpr(a->rd, t1); + gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); @@ -146,8 +146,8 @@ static bool trans_hsv_b(DisasContext *ctx, arg_hsv_b *a) check_access(ctx); - gen_get_gpr(t0, a->rs1); - gen_get_gpr(dat, a->rs2); + gen_get_gpr(ctx, t0, a->rs1); + gen_get_gpr(ctx, dat, a->rs2); tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_SB); @@ -168,8 +168,8 @@ static bool trans_hsv_h(DisasContext *ctx, arg_hsv_h *a) check_access(ctx); - gen_get_gpr(t0, a->rs1); - gen_get_gpr(dat, a->rs2); + gen_get_gpr(ctx, t0, a->rs1); + gen_get_gpr(ctx, dat, a->rs2); tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESW); @@ -190,8 +190,8 @@ static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a) check_access(ctx); - gen_get_gpr(t0, a->rs1); - gen_get_gpr(dat, a->rs2); + gen_get_gpr(ctx, t0, a->rs1); + gen_get_gpr(ctx, dat, a->rs2); tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESL); @@ -214,10 +214,10 @@ static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a) check_access(ctx); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUL); - gen_set_gpr(a->rd, t1); + gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); @@ -238,10 +238,10 @@ static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a) check_access(ctx); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEQ); - gen_set_gpr(a->rd, t1); + gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); @@ -262,8 +262,8 @@ static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a) check_access(ctx); - gen_get_gpr(t0, a->rs1); - gen_get_gpr(dat, a->rs2); + gen_get_gpr(ctx, t0, a->rs1); + gen_get_gpr(ctx, dat, a->rs2); tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEQ); @@ -284,10 +284,10 @@ static bool trans_hlvx_hu(DisasContext *ctx, arg_hlvx_hu *a) check_access(ctx); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); gen_helper_hyp_hlvx_hu(t1, cpu_env, t0); - gen_set_gpr(a->rd, t1); + gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); @@ -306,10 +306,10 @@ static bool trans_hlvx_wu(DisasContext *ctx, arg_hlvx_wu *a) check_access(ctx); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); gen_helper_hyp_hlvx_wu(t1, cpu_env, t0); - gen_set_gpr(a->rd, t1); + gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 6e736c9..f1a5d8d 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -59,7 +59,7 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a) TCGv t0 = tcg_temp_new(); - gen_get_gpr(cpu_pc, a->rs1); + gen_get_gpr(ctx, cpu_pc, a->rs1); tcg_gen_addi_tl(cpu_pc, cpu_pc, a->imm); tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2); @@ -90,8 +90,8 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond) TCGv source1, source2; source1 = tcg_temp_new(); source2 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); + gen_get_gpr(ctx, source1, a->rs1); + gen_get_gpr(ctx, source2, a->rs2); tcg_gen_brcond_tl(cond, source1, source2, l); gen_goto_tb(ctx, 1, ctx->pc_succ_insn); @@ -145,11 +145,11 @@ static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop) { TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_addi_tl(t0, t0, a->imm); tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, memop); - gen_set_gpr(a->rd, t1); + gen_set_gpr(ctx, a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); return true; @@ -184,9 +184,9 @@ static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop) { TCGv t0 = tcg_temp_new(); TCGv dat = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); + gen_get_gpr(ctx, t0, a->rs1); tcg_gen_addi_tl(t0, t0, a->imm); - gen_get_gpr(dat, a->rs2); + gen_get_gpr(ctx, dat, a->rs2); tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx, memop); tcg_temp_free(t0); @@ -347,11 +347,11 @@ static bool trans_srliw(DisasContext *ctx, arg_srliw *a) { REQUIRE_64BIT(ctx); TCGv t = tcg_temp_new(); - gen_get_gpr(t, a->rs1); + gen_get_gpr(ctx, t, a->rs1); tcg_gen_extract_tl(t, t, a->shamt, 32 - a->shamt); /* sign-extend for W instructions */ tcg_gen_ext32s_tl(t, t); - gen_set_gpr(a->rd, t); + gen_set_gpr(ctx, a->rd, t); tcg_temp_free(t); return true; } @@ -360,9 +360,9 @@ static bool trans_sraiw(DisasContext *ctx, arg_sraiw *a) { REQUIRE_64BIT(ctx); TCGv t = tcg_temp_new(); - gen_get_gpr(t, a->rs1); + gen_get_gpr(ctx, t, a->rs1); tcg_gen_sextract_tl(t, t, a->shamt, 32 - a->shamt); - gen_set_gpr(a->rd, t); + gen_set_gpr(ctx, a->rd, t); tcg_temp_free(t); return true; } @@ -385,14 +385,14 @@ static bool trans_sllw(DisasContext *ctx, arg_sllw *a) TCGv source1 = tcg_temp_new(); TCGv source2 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); + gen_get_gpr(ctx, source1, a->rs1); + gen_get_gpr(ctx, source2, a->rs2); tcg_gen_andi_tl(source2, source2, 0x1F); tcg_gen_shl_tl(source1, source1, source2); tcg_gen_ext32s_tl(source1, source1); - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); tcg_temp_free(source2); return true; @@ -404,8 +404,8 @@ static bool trans_srlw(DisasContext *ctx, arg_srlw *a) TCGv source1 = tcg_temp_new(); TCGv source2 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); + gen_get_gpr(ctx, source1, a->rs1); + gen_get_gpr(ctx, source2, a->rs2); /* clear upper 32 */ tcg_gen_ext32u_tl(source1, source1); @@ -413,7 +413,7 @@ static bool trans_srlw(DisasContext *ctx, arg_srlw *a) tcg_gen_shr_tl(source1, source1, source2); tcg_gen_ext32s_tl(source1, source1); - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); tcg_temp_free(source2); return true; @@ -425,8 +425,8 @@ static bool trans_sraw(DisasContext *ctx, arg_sraw *a) TCGv source1 = tcg_temp_new(); TCGv source2 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); + gen_get_gpr(ctx, source1, a->rs1); + gen_get_gpr(ctx, source2, a->rs2); /* * first, trick to get it to act like working on 32 bits (get rid of @@ -436,7 +436,7 @@ static bool trans_sraw(DisasContext *ctx, arg_sraw *a) tcg_gen_andi_tl(source2, source2, 0x1F); tcg_gen_sar_tl(source1, source1, source2); - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); tcg_temp_free(source2); @@ -471,7 +471,7 @@ static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a) csr_store = tcg_temp_new(); \ dest = tcg_temp_new(); \ rs1_pass = tcg_temp_new(); \ - gen_get_gpr(source1, a->rs1); \ + gen_get_gpr(ctx, source1, a->rs1); \ tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); \ tcg_gen_movi_tl(rs1_pass, a->rs1); \ tcg_gen_movi_tl(csr_store, a->csr); \ @@ -479,7 +479,7 @@ static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a) } while (0) #define RISCV_OP_CSR_POST do {\ - gen_set_gpr(a->rd, dest); \ + gen_set_gpr(ctx, a->rd, dest); \ tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); \ exit_tb(ctx); \ ctx->base.is_jmp = DISAS_NORETURN; \ diff --git a/target/riscv/insn_trans/trans_rvm.c.inc b/target/riscv/insn_trans/trans_rvm.c.inc index 10ecc45..0a4318f 100644 --- a/target/riscv/insn_trans/trans_rvm.c.inc +++ b/target/riscv/insn_trans/trans_rvm.c.inc @@ -30,12 +30,12 @@ static bool trans_mulh(DisasContext *ctx, arg_mulh *a) REQUIRE_EXT(ctx, RVM); TCGv source1 = tcg_temp_new(); TCGv source2 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); + gen_get_gpr(ctx, source1, a->rs1); + gen_get_gpr(ctx, source2, a->rs2); tcg_gen_muls2_tl(source2, source1, source1, source2); - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); tcg_temp_free(source2); return true; @@ -52,12 +52,12 @@ static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a) REQUIRE_EXT(ctx, RVM); TCGv source1 = tcg_temp_new(); TCGv source2 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); + gen_get_gpr(ctx, source1, a->rs1); + gen_get_gpr(ctx, source2, a->rs2); tcg_gen_mulu2_tl(source2, source1, source1, source2); - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); tcg_temp_free(source2); return true; diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index a8e7272..de580c4 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -36,11 +36,11 @@ static bool trans_vsetvl(DisasContext *ctx, arg_vsetvl *a) s1 = tcg_constant_tl(RV_VLEN_MAX); } else { s1 = tcg_temp_new(); - gen_get_gpr(s1, a->rs1); + gen_get_gpr(ctx, s1, a->rs1); } - gen_get_gpr(s2, a->rs2); + gen_get_gpr(ctx, s2, a->rs2); gen_helper_vsetvl(dst, cpu_env, s1, s2); - gen_set_gpr(a->rd, dst); + gen_set_gpr(ctx, a->rd, dst); tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); lookup_and_goto_ptr(ctx); ctx->base.is_jmp = DISAS_NORETURN; @@ -68,10 +68,10 @@ static bool trans_vsetvli(DisasContext *ctx, arg_vsetvli *a) s1 = tcg_constant_tl(RV_VLEN_MAX); } else { s1 = tcg_temp_new(); - gen_get_gpr(s1, a->rs1); + gen_get_gpr(ctx, s1, a->rs1); } gen_helper_vsetvl(dst, cpu_env, s1, s2); - gen_set_gpr(a->rd, dst); + gen_set_gpr(ctx, a->rd, dst); gen_goto_tb(ctx, 0, ctx->pc_succ_insn); ctx->base.is_jmp = DISAS_NORETURN; @@ -184,7 +184,7 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data, */ desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); - gen_get_gpr(base, rs1); + gen_get_gpr(s, base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); @@ -334,8 +334,8 @@ static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, uint32_t rs2, stride = tcg_temp_new(); desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); - gen_get_gpr(base, rs1); - gen_get_gpr(stride, rs2); + gen_get_gpr(s, base, rs1); + gen_get_gpr(s, stride, rs2); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); @@ -461,7 +461,7 @@ static bool ldst_index_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, base = tcg_temp_new(); desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); - gen_get_gpr(base, rs1); + gen_get_gpr(s, base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(index, cpu_env, vreg_ofs(s, vs2)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); @@ -592,7 +592,7 @@ static bool ldff_trans(uint32_t vd, uint32_t rs1, uint32_t data, base = tcg_temp_new(); desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); - gen_get_gpr(base, rs1); + gen_get_gpr(s, base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); @@ -668,7 +668,7 @@ static bool amo_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, base = tcg_temp_new(); desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); - gen_get_gpr(base, rs1); + gen_get_gpr(s, base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(index, cpu_env, vreg_ofs(s, vs2)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); @@ -863,7 +863,7 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm, mask = tcg_temp_new_ptr(); src2 = tcg_temp_new_ptr(); src1 = tcg_temp_new(); - gen_get_gpr(src1, rs1); + gen_get_gpr(s, src1, rs1); data = FIELD_DP32(data, VDATA, MLEN, s->mlen); data = FIELD_DP32(data, VDATA, VM, vm); @@ -907,7 +907,7 @@ do_opivx_gvec(DisasContext *s, arg_rmrr *a, GVecGen2sFn *gvec_fn, TCGv_i64 src1 = tcg_temp_new_i64(); TCGv tmp = tcg_temp_new(); - gen_get_gpr(tmp, a->rs1); + gen_get_gpr(s, tmp, a->rs1); tcg_gen_ext_tl_i64(src1, tmp); gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), src1, MAXSZ(s), MAXSZ(s)); @@ -1400,7 +1400,7 @@ do_opivx_gvec_shift(DisasContext *s, arg_rmrr *a, GVecGen2sFn32 *gvec_fn, TCGv_i32 src1 = tcg_temp_new_i32(); TCGv tmp = tcg_temp_new(); - gen_get_gpr(tmp, a->rs1); + gen_get_gpr(s, tmp, a->rs1); tcg_gen_trunc_tl_i32(src1, tmp); tcg_gen_extract_i32(src1, src1, 0, s->sew + 3); gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), @@ -1666,7 +1666,7 @@ static bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x *a) tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); s1 = tcg_temp_new(); - gen_get_gpr(s1, a->rs1); + gen_get_gpr(s, s1, a->rs1); if (s->vl_eq_vlmax) { tcg_gen_gvec_dup_tl(s->sew, vreg_ofs(s, a->rd), @@ -2419,7 +2419,7 @@ static bool trans_vmpopc_m(DisasContext *s, arg_rmr *a) tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); gen_helper_vmpopc_m(dst, mask, src2, cpu_env, desc); - gen_set_gpr(a->rd, dst); + gen_set_gpr(s, a->rd, dst); tcg_temp_free_ptr(mask); tcg_temp_free_ptr(src2); @@ -2450,7 +2450,7 @@ static bool trans_vmfirst_m(DisasContext *s, arg_rmr *a) tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); gen_helper_vmfirst_m(dst, mask, src2, cpu_env, desc); - gen_set_gpr(a->rd, dst); + gen_set_gpr(s, a->rd, dst); tcg_temp_free_ptr(mask); tcg_temp_free_ptr(src2); @@ -2649,7 +2649,7 @@ static bool trans_vext_x_v(DisasContext *s, arg_r *a) vec_element_loadx(s, tmp, a->rs2, cpu_gpr[a->rs1], vlmax); } tcg_gen_trunc_i64_tl(dest, tmp); - gen_set_gpr(a->rd, dest); + gen_set_gpr(s, a->rd, dest); tcg_temp_free(dest); tcg_temp_free_i64(tmp); diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 147b9c2..ce4c56c 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -175,7 +175,7 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) /* Wrapper for getting reg values - need to check of reg is zero since * cpu_gpr[0] is not actually allocated */ -static inline void gen_get_gpr(TCGv t, int reg_num) +static void gen_get_gpr(DisasContext *ctx, TCGv t, int reg_num) { if (reg_num == 0) { tcg_gen_movi_tl(t, 0); @@ -189,7 +189,7 @@ static inline void gen_get_gpr(TCGv t, int reg_num) * since we usually avoid calling the OP_TYPE_gen function if we see a write to * $zero */ -static inline void gen_set_gpr(int reg_num_dst, TCGv t) +static void gen_set_gpr(DisasContext *ctx, int reg_num_dst, TCGv t) { if (reg_num_dst != 0) { tcg_gen_mov_tl(cpu_gpr[reg_num_dst], t); @@ -435,11 +435,11 @@ static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, TCGv source1; source1 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); + gen_get_gpr(ctx, source1, a->rs1); (*func)(source1, source1, a->imm); - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); return true; } @@ -451,12 +451,12 @@ static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, source1 = tcg_temp_new(); source2 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); + gen_get_gpr(ctx, source1, a->rs1); tcg_gen_movi_tl(source2, a->imm); (*func)(source1, source1, source2); - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); tcg_temp_free(source2); return true; @@ -487,15 +487,15 @@ static bool gen_arith_div_w(DisasContext *ctx, arg_r *a, source1 = tcg_temp_new(); source2 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); + gen_get_gpr(ctx, source1, a->rs1); + gen_get_gpr(ctx, source2, a->rs2); tcg_gen_ext32s_tl(source1, source1); tcg_gen_ext32s_tl(source2, source2); (*func)(source1, source1, source2); tcg_gen_ext32s_tl(source1, source1); - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); tcg_temp_free(source2); return true; @@ -508,15 +508,15 @@ static bool gen_arith_div_uw(DisasContext *ctx, arg_r *a, source1 = tcg_temp_new(); source2 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); + gen_get_gpr(ctx, source1, a->rs1); + gen_get_gpr(ctx, source2, a->rs2); tcg_gen_ext32u_tl(source1, source1); tcg_gen_ext32u_tl(source2, source2); (*func)(source1, source1, source2); tcg_gen_ext32s_tl(source1, source1); - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); tcg_temp_free(source2); return true; @@ -606,7 +606,7 @@ static bool gen_grevi(DisasContext *ctx, arg_grevi *a) TCGv source1 = tcg_temp_new(); TCGv source2; - gen_get_gpr(source1, a->rs1); + gen_get_gpr(ctx, source1, a->rs1); if (a->shamt == (TARGET_LONG_BITS - 8)) { /* rev8, byte swaps */ @@ -618,7 +618,7 @@ static bool gen_grevi(DisasContext *ctx, arg_grevi *a) tcg_temp_free(source2); } - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); return true; } @@ -752,12 +752,12 @@ static bool gen_arith(DisasContext *ctx, arg_r *a, source1 = tcg_temp_new(); source2 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); + gen_get_gpr(ctx, source1, a->rs1); + gen_get_gpr(ctx, source2, a->rs2); (*func)(source1, source1, source2); - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); tcg_temp_free(source2); return true; @@ -769,13 +769,13 @@ static bool gen_shift(DisasContext *ctx, arg_r *a, TCGv source1 = tcg_temp_new(); TCGv source2 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); + gen_get_gpr(ctx, source1, a->rs1); + gen_get_gpr(ctx, source2, a->rs2); tcg_gen_andi_tl(source2, source2, TARGET_LONG_BITS - 1); (*func)(source1, source1, source2); - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); tcg_temp_free(source2); return true; @@ -800,12 +800,12 @@ static bool gen_shifti(DisasContext *ctx, arg_shift *a, TCGv source1 = tcg_temp_new(); TCGv source2 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); + gen_get_gpr(ctx, source1, a->rs1); tcg_gen_movi_tl(source2, a->shamt); (*func)(source1, source1, source2); - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); tcg_temp_free(source2); return true; @@ -817,14 +817,14 @@ static bool gen_shiftw(DisasContext *ctx, arg_r *a, TCGv source1 = tcg_temp_new(); TCGv source2 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); + gen_get_gpr(ctx, source1, a->rs1); + gen_get_gpr(ctx, source2, a->rs2); tcg_gen_andi_tl(source2, source2, 31); (*func)(source1, source1, source2); tcg_gen_ext32s_tl(source1, source1); - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); tcg_temp_free(source2); return true; @@ -836,13 +836,13 @@ static bool gen_shiftiw(DisasContext *ctx, arg_shift *a, TCGv source1 = tcg_temp_new(); TCGv source2 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); + gen_get_gpr(ctx, source1, a->rs1); tcg_gen_movi_tl(source2, a->shamt); (*func)(source1, source1, source2); tcg_gen_ext32s_tl(source1, source1); - gen_set_gpr(a->rd, source1); + gen_set_gpr(ctx, a->rd, source1); tcg_temp_free(source1); tcg_temp_free(source2); return true; @@ -863,11 +863,11 @@ static bool gen_unary(DisasContext *ctx, arg_r2 *a, { TCGv source = tcg_temp_new(); - gen_get_gpr(source, a->rs1); + gen_get_gpr(ctx, source, a->rs1); (*func)(source, source); - gen_set_gpr(a->rd, source); + gen_set_gpr(ctx, a->rd, source); tcg_temp_free(source); return true; } -- cgit v1.1 From ecda15d137457ebed937dc209f4bad2e7f36b4e4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:10 -0700 Subject: target/riscv: Introduce DisasExtend and new helpers Introduce get_gpr, dest_gpr, temp_new -- new helpers that do not force tcg globals into temps, returning a constant 0 for $zero as source and a new temp for $zero as destination. Introduce ctx->w for simplifying word operations, such as addw. Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20210823195529.560295-6-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/translate.c | 97 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 16 deletions(-) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index ce4c56c..d7552dc 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -39,15 +39,25 @@ static TCGv load_val; #include "exec/gen-icount.h" +/* + * If an operation is being performed on less than TARGET_LONG_BITS, + * it may require the inputs to be sign- or zero-extended; which will + * depend on the exact operation being performed. + */ +typedef enum { + EXT_NONE, + EXT_SIGN, + EXT_ZERO, +} DisasExtend; + typedef struct DisasContext { DisasContextBase base; /* pc_succ_insn points to the instruction following base.pc_next */ target_ulong pc_succ_insn; target_ulong priv_ver; - bool virt_enabled; + target_ulong misa; uint32_t opcode; uint32_t mstatus_fs; - target_ulong misa; uint32_t mem_idx; /* Remember the rounding mode encoded in the previous fp instruction, which we have already installed into env->fp_status. Or -1 for @@ -55,6 +65,8 @@ typedef struct DisasContext { to any system register, which includes CSR_FRM, so we do not have to reset this known value. */ int frm; + bool w; + bool virt_enabled; bool ext_ifencei; bool hlsx; /* vector extension */ @@ -64,7 +76,11 @@ typedef struct DisasContext { uint16_t vlen; uint16_t mlen; bool vl_eq_vlmax; + uint8_t ntemp; CPUState *cs; + TCGv zero; + /* Space for 3 operands plus 1 extra for address computation. */ + TCGv temp[4]; } DisasContext; static inline bool has_ext(DisasContext *ctx, uint32_t ext) @@ -172,27 +188,64 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) } } -/* Wrapper for getting reg values - need to check of reg is zero since - * cpu_gpr[0] is not actually allocated +/* + * Wrappers for getting reg values. + * + * The $zero register does not have cpu_gpr[0] allocated -- we supply the + * constant zero as a source, and an uninitialized sink as destination. + * + * Further, we may provide an extension for word operations. */ -static void gen_get_gpr(DisasContext *ctx, TCGv t, int reg_num) +static TCGv temp_new(DisasContext *ctx) +{ + assert(ctx->ntemp < ARRAY_SIZE(ctx->temp)); + return ctx->temp[ctx->ntemp++] = tcg_temp_new(); +} + +static TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend ext) { + TCGv t; + if (reg_num == 0) { - tcg_gen_movi_tl(t, 0); - } else { - tcg_gen_mov_tl(t, cpu_gpr[reg_num]); + return ctx->zero; } + + switch (ctx->w ? ext : EXT_NONE) { + case EXT_NONE: + return cpu_gpr[reg_num]; + case EXT_SIGN: + t = temp_new(ctx); + tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]); + return t; + case EXT_ZERO: + t = temp_new(ctx); + tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]); + return t; + } + g_assert_not_reached(); } -/* Wrapper for setting reg values - need to check of reg is zero since - * cpu_gpr[0] is not actually allocated. this is more for safety purposes, - * since we usually avoid calling the OP_TYPE_gen function if we see a write to - * $zero - */ -static void gen_set_gpr(DisasContext *ctx, int reg_num_dst, TCGv t) +static void gen_get_gpr(DisasContext *ctx, TCGv t, int reg_num) +{ + tcg_gen_mov_tl(t, get_gpr(ctx, reg_num, EXT_NONE)); +} + +static TCGv __attribute__((unused)) dest_gpr(DisasContext *ctx, int reg_num) +{ + if (reg_num == 0 || ctx->w) { + return temp_new(ctx); + } + return cpu_gpr[reg_num]; +} + +static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t) { - if (reg_num_dst != 0) { - tcg_gen_mov_tl(cpu_gpr[reg_num_dst], t); + if (reg_num != 0) { + if (ctx->w) { + tcg_gen_ext32s_tl(cpu_gpr[reg_num], t); + } else { + tcg_gen_mov_tl(cpu_gpr[reg_num], t); + } } } @@ -940,6 +993,11 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->mlen = 1 << (ctx->sew + 3 - ctx->lmul); ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX); ctx->cs = cs; + ctx->w = false; + ctx->ntemp = 0; + memset(ctx->temp, 0, sizeof(ctx->temp)); + + ctx->zero = tcg_constant_tl(0); } static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu) @@ -961,6 +1019,13 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) decode_opc(env, ctx, opcode16); ctx->base.pc_next = ctx->pc_succ_insn; + ctx->w = false; + + for (int i = ctx->ntemp - 1; i >= 0; --i) { + tcg_temp_free(ctx->temp[i]); + ctx->temp[i] = NULL; + } + ctx->ntemp = 0; if (ctx->base.is_jmp == DISAS_NEXT) { target_ulong page_start; -- cgit v1.1 From 191d1dafae9cd502ef2d771f9e35c221815fe7ba Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:11 -0700 Subject: target/riscv: Add DisasExtend to gen_arith* Most arithmetic does not require extending the inputs. Exceptions include division, comparison and minmax. Begin using ctx->w, which allows elimination of gen_addw, gen_subw, gen_mulw. Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20210823195529.560295-7-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvb.c.inc | 30 +++++++------- target/riscv/insn_trans/trans_rvi.c.inc | 39 +++++++++++-------- target/riscv/insn_trans/trans_rvm.c.inc | 16 ++++---- target/riscv/translate.c | 69 +++++++++------------------------ 4 files changed, 64 insertions(+), 90 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 260e15b..217a7d1 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -38,61 +38,61 @@ static bool trans_cpop(DisasContext *ctx, arg_cpop *a) static bool trans_andn(DisasContext *ctx, arg_andn *a) { REQUIRE_EXT(ctx, RVB); - return gen_arith(ctx, a, tcg_gen_andc_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_andc_tl); } static bool trans_orn(DisasContext *ctx, arg_orn *a) { REQUIRE_EXT(ctx, RVB); - return gen_arith(ctx, a, tcg_gen_orc_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_orc_tl); } static bool trans_xnor(DisasContext *ctx, arg_xnor *a) { REQUIRE_EXT(ctx, RVB); - return gen_arith(ctx, a, tcg_gen_eqv_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_eqv_tl); } static bool trans_pack(DisasContext *ctx, arg_pack *a) { REQUIRE_EXT(ctx, RVB); - return gen_arith(ctx, a, gen_pack); + return gen_arith(ctx, a, EXT_NONE, gen_pack); } static bool trans_packu(DisasContext *ctx, arg_packu *a) { REQUIRE_EXT(ctx, RVB); - return gen_arith(ctx, a, gen_packu); + return gen_arith(ctx, a, EXT_NONE, gen_packu); } static bool trans_packh(DisasContext *ctx, arg_packh *a) { REQUIRE_EXT(ctx, RVB); - return gen_arith(ctx, a, gen_packh); + return gen_arith(ctx, a, EXT_NONE, gen_packh); } static bool trans_min(DisasContext *ctx, arg_min *a) { REQUIRE_EXT(ctx, RVB); - return gen_arith(ctx, a, tcg_gen_smin_tl); + return gen_arith(ctx, a, EXT_SIGN, tcg_gen_smin_tl); } static bool trans_max(DisasContext *ctx, arg_max *a) { REQUIRE_EXT(ctx, RVB); - return gen_arith(ctx, a, tcg_gen_smax_tl); + return gen_arith(ctx, a, EXT_SIGN, tcg_gen_smax_tl); } static bool trans_minu(DisasContext *ctx, arg_minu *a) { REQUIRE_EXT(ctx, RVB); - return gen_arith(ctx, a, tcg_gen_umin_tl); + return gen_arith(ctx, a, EXT_SIGN, tcg_gen_umin_tl); } static bool trans_maxu(DisasContext *ctx, arg_maxu *a) { REQUIRE_EXT(ctx, RVB); - return gen_arith(ctx, a, tcg_gen_umax_tl); + return gen_arith(ctx, a, EXT_SIGN, tcg_gen_umax_tl); } static bool trans_sext_b(DisasContext *ctx, arg_sext_b *a) @@ -230,7 +230,7 @@ static bool trans_gorci(DisasContext *ctx, arg_gorci *a) static bool trans_sh##SHAMT##add(DisasContext *ctx, arg_sh##SHAMT##add *a) \ { \ REQUIRE_EXT(ctx, RVB); \ - return gen_arith(ctx, a, gen_sh##SHAMT##add); \ + return gen_arith(ctx, a, EXT_NONE, gen_sh##SHAMT##add); \ } GEN_TRANS_SHADD(1) @@ -262,14 +262,14 @@ static bool trans_packw(DisasContext *ctx, arg_packw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_arith(ctx, a, gen_packw); + return gen_arith(ctx, a, EXT_NONE, gen_packw); } static bool trans_packuw(DisasContext *ctx, arg_packuw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_arith(ctx, a, gen_packuw); + return gen_arith(ctx, a, EXT_NONE, gen_packuw); } static bool trans_bsetw(DisasContext *ctx, arg_bsetw *a) @@ -404,7 +404,7 @@ static bool trans_sh##SHAMT##add_uw(DisasContext *ctx, \ { \ REQUIRE_64BIT(ctx); \ REQUIRE_EXT(ctx, RVB); \ - return gen_arith(ctx, a, gen_sh##SHAMT##add_uw); \ + return gen_arith(ctx, a, EXT_NONE, gen_sh##SHAMT##add_uw); \ } GEN_TRANS_SHADD_UW(1) @@ -415,7 +415,7 @@ static bool trans_add_uw(DisasContext *ctx, arg_add_uw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_arith(ctx, a, gen_add_uw); + return gen_arith(ctx, a, EXT_NONE, gen_add_uw); } static bool trans_slli_uw(DisasContext *ctx, arg_slli_uw *a) diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index f1a5d8d..bd80476 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -230,7 +230,7 @@ static bool trans_sd(DisasContext *ctx, arg_sd *a) static bool trans_addi(DisasContext *ctx, arg_addi *a) { - return gen_arith_imm_fn(ctx, a, &tcg_gen_addi_tl); + return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl); } static void gen_slt(TCGv ret, TCGv s1, TCGv s2) @@ -243,29 +243,31 @@ static void gen_sltu(TCGv ret, TCGv s1, TCGv s2) tcg_gen_setcond_tl(TCG_COND_LTU, ret, s1, s2); } - static bool trans_slti(DisasContext *ctx, arg_slti *a) { - return gen_arith_imm_tl(ctx, a, &gen_slt); + return gen_arith_imm_tl(ctx, a, EXT_SIGN, gen_slt); } static bool trans_sltiu(DisasContext *ctx, arg_sltiu *a) { - return gen_arith_imm_tl(ctx, a, &gen_sltu); + return gen_arith_imm_tl(ctx, a, EXT_SIGN, gen_sltu); } static bool trans_xori(DisasContext *ctx, arg_xori *a) { - return gen_arith_imm_fn(ctx, a, &tcg_gen_xori_tl); + return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_xori_tl); } + static bool trans_ori(DisasContext *ctx, arg_ori *a) { - return gen_arith_imm_fn(ctx, a, &tcg_gen_ori_tl); + return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_ori_tl); } + static bool trans_andi(DisasContext *ctx, arg_andi *a) { - return gen_arith_imm_fn(ctx, a, &tcg_gen_andi_tl); + return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_andi_tl); } + static bool trans_slli(DisasContext *ctx, arg_slli *a) { return gen_shifti(ctx, a, tcg_gen_shl_tl); @@ -283,12 +285,12 @@ static bool trans_srai(DisasContext *ctx, arg_srai *a) static bool trans_add(DisasContext *ctx, arg_add *a) { - return gen_arith(ctx, a, &tcg_gen_add_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl); } static bool trans_sub(DisasContext *ctx, arg_sub *a) { - return gen_arith(ctx, a, &tcg_gen_sub_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl); } static bool trans_sll(DisasContext *ctx, arg_sll *a) @@ -298,17 +300,17 @@ static bool trans_sll(DisasContext *ctx, arg_sll *a) static bool trans_slt(DisasContext *ctx, arg_slt *a) { - return gen_arith(ctx, a, &gen_slt); + return gen_arith(ctx, a, EXT_SIGN, gen_slt); } static bool trans_sltu(DisasContext *ctx, arg_sltu *a) { - return gen_arith(ctx, a, &gen_sltu); + return gen_arith(ctx, a, EXT_SIGN, gen_sltu); } static bool trans_xor(DisasContext *ctx, arg_xor *a) { - return gen_arith(ctx, a, &tcg_gen_xor_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_xor_tl); } static bool trans_srl(DisasContext *ctx, arg_srl *a) @@ -323,18 +325,19 @@ static bool trans_sra(DisasContext *ctx, arg_sra *a) static bool trans_or(DisasContext *ctx, arg_or *a) { - return gen_arith(ctx, a, &tcg_gen_or_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_or_tl); } static bool trans_and(DisasContext *ctx, arg_and *a) { - return gen_arith(ctx, a, &tcg_gen_and_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_and_tl); } static bool trans_addiw(DisasContext *ctx, arg_addiw *a) { REQUIRE_64BIT(ctx); - return gen_arith_imm_tl(ctx, a, &gen_addw); + ctx->w = true; + return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl); } static bool trans_slliw(DisasContext *ctx, arg_slliw *a) @@ -370,13 +373,15 @@ static bool trans_sraiw(DisasContext *ctx, arg_sraiw *a) static bool trans_addw(DisasContext *ctx, arg_addw *a) { REQUIRE_64BIT(ctx); - return gen_arith(ctx, a, &gen_addw); + ctx->w = true; + return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl); } static bool trans_subw(DisasContext *ctx, arg_subw *a) { REQUIRE_64BIT(ctx); - return gen_arith(ctx, a, &gen_subw); + ctx->w = true; + return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl); } static bool trans_sllw(DisasContext *ctx, arg_sllw *a) diff --git a/target/riscv/insn_trans/trans_rvm.c.inc b/target/riscv/insn_trans/trans_rvm.c.inc index 0a4318f..013b3f7 100644 --- a/target/riscv/insn_trans/trans_rvm.c.inc +++ b/target/riscv/insn_trans/trans_rvm.c.inc @@ -22,7 +22,7 @@ static bool trans_mul(DisasContext *ctx, arg_mul *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, &tcg_gen_mul_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl); } static bool trans_mulh(DisasContext *ctx, arg_mulh *a) @@ -44,7 +44,7 @@ static bool trans_mulh(DisasContext *ctx, arg_mulh *a) static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, &gen_mulhsu); + return gen_arith(ctx, a, EXT_NONE, gen_mulhsu); } static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a) @@ -66,33 +66,33 @@ static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a) static bool trans_div(DisasContext *ctx, arg_div *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, &gen_div); + return gen_arith(ctx, a, EXT_SIGN, gen_div); } static bool trans_divu(DisasContext *ctx, arg_divu *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, &gen_divu); + return gen_arith(ctx, a, EXT_ZERO, gen_divu); } static bool trans_rem(DisasContext *ctx, arg_rem *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, &gen_rem); + return gen_arith(ctx, a, EXT_SIGN, gen_rem); } static bool trans_remu(DisasContext *ctx, arg_remu *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, &gen_remu); + return gen_arith(ctx, a, EXT_ZERO, gen_remu); } static bool trans_mulw(DisasContext *ctx, arg_mulw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); - - return gen_arith(ctx, a, &gen_mulw); + ctx->w = true; + return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl); } static bool trans_divw(DisasContext *ctx, arg_divw *a) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index d7552dc..7dd2839 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -230,7 +230,7 @@ static void gen_get_gpr(DisasContext *ctx, TCGv t, int reg_num) tcg_gen_mov_tl(t, get_gpr(ctx, reg_num, EXT_NONE)); } -static TCGv __attribute__((unused)) dest_gpr(DisasContext *ctx, int reg_num) +static TCGv dest_gpr(DisasContext *ctx, int reg_num) { if (reg_num == 0 || ctx->w) { return temp_new(ctx); @@ -482,57 +482,31 @@ static int ex_rvc_shifti(DisasContext *ctx, int imm) /* Include the auto-generated decoder for 32 bit insn */ #include "decode-insn32.c.inc" -static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, +static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext, void (*func)(TCGv, TCGv, target_long)) { - TCGv source1; - source1 = tcg_temp_new(); - - gen_get_gpr(ctx, source1, a->rs1); + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); - (*func)(source1, source1, a->imm); + func(dest, src1, a->imm); - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); + gen_set_gpr(ctx, a->rd, dest); return true; } -static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, +static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, DisasExtend ext, void (*func)(TCGv, TCGv, TCGv)) { - TCGv source1, source2; - source1 = tcg_temp_new(); - source2 = tcg_temp_new(); + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); + TCGv src2 = tcg_constant_tl(a->imm); - gen_get_gpr(ctx, source1, a->rs1); - tcg_gen_movi_tl(source2, a->imm); + func(dest, src1, src2); - (*func)(source1, source1, source2); - - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); + gen_set_gpr(ctx, a->rd, dest); return true; } -static void gen_addw(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_add_tl(ret, arg1, arg2); - tcg_gen_ext32s_tl(ret, ret); -} - -static void gen_subw(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_sub_tl(ret, arg1, arg2); - tcg_gen_ext32s_tl(ret, ret); -} - -static void gen_mulw(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_mul_tl(ret, arg1, arg2); - tcg_gen_ext32s_tl(ret, ret); -} - static bool gen_arith_div_w(DisasContext *ctx, arg_r *a, void(*func)(TCGv, TCGv, TCGv)) { @@ -798,21 +772,16 @@ static void gen_add_uw(TCGv ret, TCGv arg1, TCGv arg2) tcg_gen_add_tl(ret, arg1, arg2); } -static bool gen_arith(DisasContext *ctx, arg_r *a, - void(*func)(TCGv, TCGv, TCGv)) +static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext, + void (*func)(TCGv, TCGv, TCGv)) { - TCGv source1, source2; - source1 = tcg_temp_new(); - source2 = tcg_temp_new(); + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); + TCGv src2 = get_gpr(ctx, a->rs2, ext); - gen_get_gpr(ctx, source1, a->rs1); - gen_get_gpr(ctx, source2, a->rs2); + func(dest, src1, src2); - (*func)(source1, source1, source2); - - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); + gen_set_gpr(ctx, a->rd, dest); return true; } -- cgit v1.1 From afbbec820149299943976ef8b957a37073f3a0b5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:12 -0700 Subject: target/riscv: Remove gen_arith_div* Use ctx->w and the enhanced gen_arith function. Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20210823195529.560295-8-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvm.c.inc | 16 ++++++------- target/riscv/translate.c | 42 --------------------------------- 2 files changed, 8 insertions(+), 50 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvm.c.inc b/target/riscv/insn_trans/trans_rvm.c.inc index 013b3f7..3d93b24 100644 --- a/target/riscv/insn_trans/trans_rvm.c.inc +++ b/target/riscv/insn_trans/trans_rvm.c.inc @@ -99,30 +99,30 @@ static bool trans_divw(DisasContext *ctx, arg_divw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); - - return gen_arith_div_w(ctx, a, &gen_div); + ctx->w = true; + return gen_arith(ctx, a, EXT_SIGN, gen_div); } static bool trans_divuw(DisasContext *ctx, arg_divuw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); - - return gen_arith_div_uw(ctx, a, &gen_divu); + ctx->w = true; + return gen_arith(ctx, a, EXT_ZERO, gen_divu); } static bool trans_remw(DisasContext *ctx, arg_remw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); - - return gen_arith_div_w(ctx, a, &gen_rem); + ctx->w = true; + return gen_arith(ctx, a, EXT_SIGN, gen_rem); } static bool trans_remuw(DisasContext *ctx, arg_remuw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); - - return gen_arith_div_uw(ctx, a, &gen_remu); + ctx->w = true; + return gen_arith(ctx, a, EXT_ZERO, gen_remu); } diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 7dd2839..1855eac 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -507,48 +507,6 @@ static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, DisasExtend ext, return true; } -static bool gen_arith_div_w(DisasContext *ctx, arg_r *a, - void(*func)(TCGv, TCGv, TCGv)) -{ - TCGv source1, source2; - source1 = tcg_temp_new(); - source2 = tcg_temp_new(); - - gen_get_gpr(ctx, source1, a->rs1); - gen_get_gpr(ctx, source2, a->rs2); - tcg_gen_ext32s_tl(source1, source1); - tcg_gen_ext32s_tl(source2, source2); - - (*func)(source1, source1, source2); - - tcg_gen_ext32s_tl(source1, source1); - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); - return true; -} - -static bool gen_arith_div_uw(DisasContext *ctx, arg_r *a, - void(*func)(TCGv, TCGv, TCGv)) -{ - TCGv source1, source2; - source1 = tcg_temp_new(); - source2 = tcg_temp_new(); - - gen_get_gpr(ctx, source1, a->rs1); - gen_get_gpr(ctx, source2, a->rs2); - tcg_gen_ext32u_tl(source1, source1); - tcg_gen_ext32u_tl(source2, source2); - - (*func)(source1, source1, source2); - - tcg_gen_ext32s_tl(source1, source1); - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); - return true; -} - static void gen_pack(TCGv ret, TCGv arg1, TCGv arg2) { tcg_gen_deposit_tl(ret, arg1, arg2, -- cgit v1.1 From 8a1b4917c576abf61c27cc74cb7cd28df3697c7c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:13 -0700 Subject: target/riscv: Use gen_arith for mulh and mulhu Split out gen_mulh and gen_mulhu and use the common helper. Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20210823195529.560295-9-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvm.c.inc | 40 +++++++++++++++------------------ 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvm.c.inc b/target/riscv/insn_trans/trans_rvm.c.inc index 3d93b24..80552be 100644 --- a/target/riscv/insn_trans/trans_rvm.c.inc +++ b/target/riscv/insn_trans/trans_rvm.c.inc @@ -25,20 +25,18 @@ static bool trans_mul(DisasContext *ctx, arg_mul *a) return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl); } -static bool trans_mulh(DisasContext *ctx, arg_mulh *a) +static void gen_mulh(TCGv ret, TCGv s1, TCGv s2) { - REQUIRE_EXT(ctx, RVM); - TCGv source1 = tcg_temp_new(); - TCGv source2 = tcg_temp_new(); - gen_get_gpr(ctx, source1, a->rs1); - gen_get_gpr(ctx, source2, a->rs2); + TCGv discard = tcg_temp_new(); - tcg_gen_muls2_tl(source2, source1, source1, source2); + tcg_gen_muls2_tl(discard, ret, s1, s2); + tcg_temp_free(discard); +} - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); - return true; +static bool trans_mulh(DisasContext *ctx, arg_mulh *a) +{ + REQUIRE_EXT(ctx, RVM); + return gen_arith(ctx, a, EXT_NONE, gen_mulh); } static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a) @@ -47,20 +45,18 @@ static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a) return gen_arith(ctx, a, EXT_NONE, gen_mulhsu); } -static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a) +static void gen_mulhu(TCGv ret, TCGv s1, TCGv s2) { - REQUIRE_EXT(ctx, RVM); - TCGv source1 = tcg_temp_new(); - TCGv source2 = tcg_temp_new(); - gen_get_gpr(ctx, source1, a->rs1); - gen_get_gpr(ctx, source2, a->rs2); + TCGv discard = tcg_temp_new(); - tcg_gen_mulu2_tl(source2, source1, source1, source2); + tcg_gen_mulu2_tl(discard, ret, s1, s2); + tcg_temp_free(discard); +} - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); - return true; +static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a) +{ + REQUIRE_EXT(ctx, RVM); + return gen_arith(ctx, a, EXT_NONE, gen_mulhu); } static bool trans_div(DisasContext *ctx, arg_div *a) -- cgit v1.1 From b66a0585f033a5505f1da2f624966b4fce40cddb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:14 -0700 Subject: target/riscv: Move gen_* helpers for RVM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move these helpers near their use by the trans_* functions within insn_trans/trans_rvm.c.inc. Reviewed-by: Bin Meng Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20210823195529.560295-10-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvm.c.inc | 127 ++++++++++++++++++++++++++++++++ target/riscv/translate.c | 127 -------------------------------- 2 files changed, 127 insertions(+), 127 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvm.c.inc b/target/riscv/insn_trans/trans_rvm.c.inc index 80552be..b89a85a 100644 --- a/target/riscv/insn_trans/trans_rvm.c.inc +++ b/target/riscv/insn_trans/trans_rvm.c.inc @@ -39,6 +39,21 @@ static bool trans_mulh(DisasContext *ctx, arg_mulh *a) return gen_arith(ctx, a, EXT_NONE, gen_mulh); } +static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv rl = tcg_temp_new(); + TCGv rh = tcg_temp_new(); + + tcg_gen_mulu2_tl(rl, rh, arg1, arg2); + /* fix up for one negative */ + tcg_gen_sari_tl(rl, arg1, TARGET_LONG_BITS - 1); + tcg_gen_and_tl(rl, rl, arg2); + tcg_gen_sub_tl(ret, rh, rl); + + tcg_temp_free(rl); + tcg_temp_free(rh); +} + static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a) { REQUIRE_EXT(ctx, RVM); @@ -59,24 +74,136 @@ static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a) return gen_arith(ctx, a, EXT_NONE, gen_mulhu); } +static void gen_div(TCGv ret, TCGv source1, TCGv source2) +{ + TCGv temp1, temp2, zero, one, mone, min; + + temp1 = tcg_temp_new(); + temp2 = tcg_temp_new(); + zero = tcg_constant_tl(0); + one = tcg_constant_tl(1); + mone = tcg_constant_tl(-1); + min = tcg_constant_tl(1ull << (TARGET_LONG_BITS - 1)); + + /* + * If overflow, set temp2 to 1, else source2. + * This produces the required result of min. + */ + tcg_gen_setcond_tl(TCG_COND_EQ, temp1, source1, min); + tcg_gen_setcond_tl(TCG_COND_EQ, temp2, source2, mone); + tcg_gen_and_tl(temp1, temp1, temp2); + tcg_gen_movcond_tl(TCG_COND_NE, temp2, temp1, zero, one, source2); + + /* + * If div by zero, set temp1 to -1 and temp2 to 1 to + * produce the required result of -1. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, temp1, source2, zero, mone, source1); + tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, temp2); + + tcg_gen_div_tl(ret, temp1, temp2); + + tcg_temp_free(temp1); + tcg_temp_free(temp2); +} + static bool trans_div(DisasContext *ctx, arg_div *a) { REQUIRE_EXT(ctx, RVM); return gen_arith(ctx, a, EXT_SIGN, gen_div); } +static void gen_divu(TCGv ret, TCGv source1, TCGv source2) +{ + TCGv temp1, temp2, zero, one, max; + + temp1 = tcg_temp_new(); + temp2 = tcg_temp_new(); + zero = tcg_constant_tl(0); + one = tcg_constant_tl(1); + max = tcg_constant_tl(~0); + + /* + * If div by zero, set temp1 to max and temp2 to 1 to + * produce the required result of max. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, temp1, source2, zero, max, source1); + tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, source2); + tcg_gen_divu_tl(ret, temp1, temp2); + + tcg_temp_free(temp1); + tcg_temp_free(temp2); +} + static bool trans_divu(DisasContext *ctx, arg_divu *a) { REQUIRE_EXT(ctx, RVM); return gen_arith(ctx, a, EXT_ZERO, gen_divu); } +static void gen_rem(TCGv ret, TCGv source1, TCGv source2) +{ + TCGv temp1, temp2, zero, one, mone, min; + + temp1 = tcg_temp_new(); + temp2 = tcg_temp_new(); + zero = tcg_constant_tl(0); + one = tcg_constant_tl(1); + mone = tcg_constant_tl(-1); + min = tcg_constant_tl(1ull << (TARGET_LONG_BITS - 1)); + + /* + * If overflow, set temp1 to 0, else source1. + * This avoids a possible host trap, and produces the required result of 0. + */ + tcg_gen_setcond_tl(TCG_COND_EQ, temp1, source1, min); + tcg_gen_setcond_tl(TCG_COND_EQ, temp2, source2, mone); + tcg_gen_and_tl(temp1, temp1, temp2); + tcg_gen_movcond_tl(TCG_COND_NE, temp1, temp1, zero, zero, source1); + + /* + * If div by zero, set temp2 to 1, else source2. + * This avoids a possible host trap, but produces an incorrect result. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, source2); + + tcg_gen_rem_tl(temp1, temp1, temp2); + + /* If div by zero, the required result is the original dividend. */ + tcg_gen_movcond_tl(TCG_COND_EQ, ret, source2, zero, source1, temp1); + + tcg_temp_free(temp1); + tcg_temp_free(temp2); +} + static bool trans_rem(DisasContext *ctx, arg_rem *a) { REQUIRE_EXT(ctx, RVM); return gen_arith(ctx, a, EXT_SIGN, gen_rem); } +static void gen_remu(TCGv ret, TCGv source1, TCGv source2) +{ + TCGv temp, zero, one; + + temp = tcg_temp_new(); + zero = tcg_constant_tl(0); + one = tcg_constant_tl(1); + + /* + * If div by zero, set temp to 1, else source2. + * This avoids a possible host trap, but produces an incorrect result. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, temp, source2, zero, one, source2); + + tcg_gen_remu_tl(temp, source1, temp); + + /* If div by zero, the required result is the original dividend. */ + tcg_gen_movcond_tl(TCG_COND_EQ, ret, source2, zero, source1, temp); + + tcg_temp_free(temp); +} + static bool trans_remu(DisasContext *ctx, arg_remu *a) { REQUIRE_EXT(ctx, RVM); diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 1855eac..7fbacfa 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -249,133 +249,6 @@ static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t) } } -static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv rl = tcg_temp_new(); - TCGv rh = tcg_temp_new(); - - tcg_gen_mulu2_tl(rl, rh, arg1, arg2); - /* fix up for one negative */ - tcg_gen_sari_tl(rl, arg1, TARGET_LONG_BITS - 1); - tcg_gen_and_tl(rl, rl, arg2); - tcg_gen_sub_tl(ret, rh, rl); - - tcg_temp_free(rl); - tcg_temp_free(rh); -} - -static void gen_div(TCGv ret, TCGv source1, TCGv source2) -{ - TCGv temp1, temp2, zero, one, mone, min; - - temp1 = tcg_temp_new(); - temp2 = tcg_temp_new(); - zero = tcg_constant_tl(0); - one = tcg_constant_tl(1); - mone = tcg_constant_tl(-1); - min = tcg_constant_tl(1ull << (TARGET_LONG_BITS - 1)); - - /* - * If overflow, set temp2 to 1, else source2. - * This produces the required result of min. - */ - tcg_gen_setcond_tl(TCG_COND_EQ, temp1, source1, min); - tcg_gen_setcond_tl(TCG_COND_EQ, temp2, source2, mone); - tcg_gen_and_tl(temp1, temp1, temp2); - tcg_gen_movcond_tl(TCG_COND_NE, temp2, temp1, zero, one, source2); - - /* - * If div by zero, set temp1 to -1 and temp2 to 1 to - * produce the required result of -1. - */ - tcg_gen_movcond_tl(TCG_COND_EQ, temp1, source2, zero, mone, source1); - tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, temp2); - - tcg_gen_div_tl(ret, temp1, temp2); - - tcg_temp_free(temp1); - tcg_temp_free(temp2); -} - -static void gen_divu(TCGv ret, TCGv source1, TCGv source2) -{ - TCGv temp1, temp2, zero, one, max; - - temp1 = tcg_temp_new(); - temp2 = tcg_temp_new(); - zero = tcg_constant_tl(0); - one = tcg_constant_tl(1); - max = tcg_constant_tl(~0); - - /* - * If div by zero, set temp1 to max and temp2 to 1 to - * produce the required result of max. - */ - tcg_gen_movcond_tl(TCG_COND_EQ, temp1, source2, zero, max, source1); - tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, source2); - tcg_gen_divu_tl(ret, temp1, temp2); - - tcg_temp_free(temp1); - tcg_temp_free(temp2); -} - -static void gen_rem(TCGv ret, TCGv source1, TCGv source2) -{ - TCGv temp1, temp2, zero, one, mone, min; - - temp1 = tcg_temp_new(); - temp2 = tcg_temp_new(); - zero = tcg_constant_tl(0); - one = tcg_constant_tl(1); - mone = tcg_constant_tl(-1); - min = tcg_constant_tl(1ull << (TARGET_LONG_BITS - 1)); - - /* - * If overflow, set temp1 to 0, else source1. - * This avoids a possible host trap, and produces the required result of 0. - */ - tcg_gen_setcond_tl(TCG_COND_EQ, temp1, source1, min); - tcg_gen_setcond_tl(TCG_COND_EQ, temp2, source2, mone); - tcg_gen_and_tl(temp1, temp1, temp2); - tcg_gen_movcond_tl(TCG_COND_NE, temp1, temp1, zero, zero, source1); - - /* - * If div by zero, set temp2 to 1, else source2. - * This avoids a possible host trap, but produces an incorrect result. - */ - tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, source2); - - tcg_gen_rem_tl(temp1, temp1, temp2); - - /* If div by zero, the required result is the original dividend. */ - tcg_gen_movcond_tl(TCG_COND_EQ, ret, source2, zero, source1, temp1); - - tcg_temp_free(temp1); - tcg_temp_free(temp2); -} - -static void gen_remu(TCGv ret, TCGv source1, TCGv source2) -{ - TCGv temp, zero, one; - - temp = tcg_temp_new(); - zero = tcg_constant_tl(0); - one = tcg_constant_tl(1); - - /* - * If div by zero, set temp to 1, else source2. - * This avoids a possible host trap, but produces an incorrect result. - */ - tcg_gen_movcond_tl(TCG_COND_EQ, temp, source2, zero, one, source2); - - tcg_gen_remu_tl(temp, source1, temp); - - /* If div by zero, the required result is the original dividend. */ - tcg_gen_movcond_tl(TCG_COND_EQ, ret, source2, zero, source1, temp); - - tcg_temp_free(temp); -} - static void gen_jal(DisasContext *ctx, int rd, target_ulong imm) { target_ulong next_pc; -- cgit v1.1 From f84ed8c2dffd938befc882cf5d347b57c4ee616f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:15 -0700 Subject: target/riscv: Move gen_* helpers for RVB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move these helpers near their use by the trans_* functions within insn_trans/trans_rvb.c.inc. Reviewed-by: Bin Meng Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20210823195529.560295-11-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvb.c.inc | 234 ++++++++++++++++++++++++++++++++ target/riscv/translate.c | 233 ------------------------------- 2 files changed, 234 insertions(+), 233 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 217a7d1..73f088b 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -17,12 +17,23 @@ * this program. If not, see . */ + +static void gen_clz(TCGv ret, TCGv arg1) +{ + tcg_gen_clzi_tl(ret, arg1, TARGET_LONG_BITS); +} + static bool trans_clz(DisasContext *ctx, arg_clz *a) { REQUIRE_EXT(ctx, RVB); return gen_unary(ctx, a, gen_clz); } +static void gen_ctz(TCGv ret, TCGv arg1) +{ + tcg_gen_ctzi_tl(ret, arg1, TARGET_LONG_BITS); +} + static bool trans_ctz(DisasContext *ctx, arg_ctz *a) { REQUIRE_EXT(ctx, RVB); @@ -53,18 +64,41 @@ static bool trans_xnor(DisasContext *ctx, arg_xnor *a) return gen_arith(ctx, a, EXT_NONE, tcg_gen_eqv_tl); } +static void gen_pack(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_deposit_tl(ret, arg1, arg2, + TARGET_LONG_BITS / 2, + TARGET_LONG_BITS / 2); +} + static bool trans_pack(DisasContext *ctx, arg_pack *a) { REQUIRE_EXT(ctx, RVB); return gen_arith(ctx, a, EXT_NONE, gen_pack); } +static void gen_packu(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv t = tcg_temp_new(); + tcg_gen_shri_tl(t, arg1, TARGET_LONG_BITS / 2); + tcg_gen_deposit_tl(ret, arg2, t, 0, TARGET_LONG_BITS / 2); + tcg_temp_free(t); +} + static bool trans_packu(DisasContext *ctx, arg_packu *a) { REQUIRE_EXT(ctx, RVB); return gen_arith(ctx, a, EXT_NONE, gen_packu); } +static void gen_packh(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv t = tcg_temp_new(); + tcg_gen_ext8u_tl(t, arg2); + tcg_gen_deposit_tl(ret, arg1, t, 8, TARGET_LONG_BITS - 8); + tcg_temp_free(t); +} + static bool trans_packh(DisasContext *ctx, arg_packh *a) { REQUIRE_EXT(ctx, RVB); @@ -107,6 +141,22 @@ static bool trans_sext_h(DisasContext *ctx, arg_sext_h *a) return gen_unary(ctx, a, tcg_gen_ext16s_tl); } +static void gen_sbop_mask(TCGv ret, TCGv shamt) +{ + tcg_gen_movi_tl(ret, 1); + tcg_gen_shl_tl(ret, ret, shamt); +} + +static void gen_bset(TCGv ret, TCGv arg1, TCGv shamt) +{ + TCGv t = tcg_temp_new(); + + gen_sbop_mask(t, shamt); + tcg_gen_or_tl(ret, arg1, t); + + tcg_temp_free(t); +} + static bool trans_bset(DisasContext *ctx, arg_bset *a) { REQUIRE_EXT(ctx, RVB); @@ -119,6 +169,16 @@ static bool trans_bseti(DisasContext *ctx, arg_bseti *a) return gen_shifti(ctx, a, gen_bset); } +static void gen_bclr(TCGv ret, TCGv arg1, TCGv shamt) +{ + TCGv t = tcg_temp_new(); + + gen_sbop_mask(t, shamt); + tcg_gen_andc_tl(ret, arg1, t); + + tcg_temp_free(t); +} + static bool trans_bclr(DisasContext *ctx, arg_bclr *a) { REQUIRE_EXT(ctx, RVB); @@ -131,6 +191,16 @@ static bool trans_bclri(DisasContext *ctx, arg_bclri *a) return gen_shifti(ctx, a, gen_bclr); } +static void gen_binv(TCGv ret, TCGv arg1, TCGv shamt) +{ + TCGv t = tcg_temp_new(); + + gen_sbop_mask(t, shamt); + tcg_gen_xor_tl(ret, arg1, t); + + tcg_temp_free(t); +} + static bool trans_binv(DisasContext *ctx, arg_binv *a) { REQUIRE_EXT(ctx, RVB); @@ -143,6 +213,12 @@ static bool trans_binvi(DisasContext *ctx, arg_binvi *a) return gen_shifti(ctx, a, gen_binv); } +static void gen_bext(TCGv ret, TCGv arg1, TCGv shamt) +{ + tcg_gen_shr_tl(ret, arg1, shamt); + tcg_gen_andi_tl(ret, ret, 1); +} + static bool trans_bext(DisasContext *ctx, arg_bext *a) { REQUIRE_EXT(ctx, RVB); @@ -155,6 +231,13 @@ static bool trans_bexti(DisasContext *ctx, arg_bexti *a) return gen_shifti(ctx, a, gen_bext); } +static void gen_slo(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_not_tl(ret, arg1); + tcg_gen_shl_tl(ret, ret, arg2); + tcg_gen_not_tl(ret, ret); +} + static bool trans_slo(DisasContext *ctx, arg_slo *a) { REQUIRE_EXT(ctx, RVB); @@ -167,6 +250,13 @@ static bool trans_sloi(DisasContext *ctx, arg_sloi *a) return gen_shifti(ctx, a, gen_slo); } +static void gen_sro(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_not_tl(ret, arg1); + tcg_gen_shr_tl(ret, ret, arg2); + tcg_gen_not_tl(ret, ret); +} + static bool trans_sro(DisasContext *ctx, arg_sro *a) { REQUIRE_EXT(ctx, RVB); @@ -203,6 +293,28 @@ static bool trans_grev(DisasContext *ctx, arg_grev *a) return gen_shift(ctx, a, gen_helper_grev); } +static bool gen_grevi(DisasContext *ctx, arg_grevi *a) +{ + TCGv source1 = tcg_temp_new(); + TCGv source2; + + gen_get_gpr(ctx, source1, a->rs1); + + if (a->shamt == (TARGET_LONG_BITS - 8)) { + /* rev8, byte swaps */ + tcg_gen_bswap_tl(source1, source1); + } else { + source2 = tcg_temp_new(); + tcg_gen_movi_tl(source2, a->shamt); + gen_helper_grev(source1, source1, source2); + tcg_temp_free(source2); + } + + gen_set_gpr(ctx, a->rd, source1); + tcg_temp_free(source1); + return true; +} + static bool trans_grevi(DisasContext *ctx, arg_grevi *a) { REQUIRE_EXT(ctx, RVB); @@ -226,6 +338,21 @@ static bool trans_gorci(DisasContext *ctx, arg_gorci *a) return gen_shifti(ctx, a, gen_helper_gorc); } +#define GEN_SHADD(SHAMT) \ +static void gen_sh##SHAMT##add(TCGv ret, TCGv arg1, TCGv arg2) \ +{ \ + TCGv t = tcg_temp_new(); \ + \ + tcg_gen_shli_tl(t, arg1, SHAMT); \ + tcg_gen_add_tl(ret, t, arg2); \ + \ + tcg_temp_free(t); \ +} + +GEN_SHADD(1) +GEN_SHADD(2) +GEN_SHADD(3) + #define GEN_TRANS_SHADD(SHAMT) \ static bool trans_sh##SHAMT##add(DisasContext *ctx, arg_sh##SHAMT##add *a) \ { \ @@ -237,6 +364,13 @@ GEN_TRANS_SHADD(1) GEN_TRANS_SHADD(2) GEN_TRANS_SHADD(3) +static void gen_clzw(TCGv ret, TCGv arg1) +{ + tcg_gen_ext32u_tl(ret, arg1); + tcg_gen_clzi_tl(ret, ret, 64); + tcg_gen_subi_tl(ret, ret, 32); +} + static bool trans_clzw(DisasContext *ctx, arg_clzw *a) { REQUIRE_64BIT(ctx); @@ -244,6 +378,12 @@ static bool trans_clzw(DisasContext *ctx, arg_clzw *a) return gen_unary(ctx, a, gen_clzw); } +static void gen_ctzw(TCGv ret, TCGv arg1) +{ + tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32)); + tcg_gen_ctzi_tl(ret, ret, 64); +} + static bool trans_ctzw(DisasContext *ctx, arg_ctzw *a) { REQUIRE_64BIT(ctx); @@ -251,6 +391,12 @@ static bool trans_ctzw(DisasContext *ctx, arg_ctzw *a) return gen_unary(ctx, a, gen_ctzw); } +static void gen_cpopw(TCGv ret, TCGv arg1) +{ + tcg_gen_ext32u_tl(arg1, arg1); + tcg_gen_ctpop_tl(ret, arg1); +} + static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a) { REQUIRE_64BIT(ctx); @@ -258,6 +404,14 @@ static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a) return gen_unary(ctx, a, gen_cpopw); } +static void gen_packw(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv t = tcg_temp_new(); + tcg_gen_ext16s_tl(t, arg2); + tcg_gen_deposit_tl(ret, arg1, t, 16, 48); + tcg_temp_free(t); +} + static bool trans_packw(DisasContext *ctx, arg_packw *a) { REQUIRE_64BIT(ctx); @@ -265,6 +419,15 @@ static bool trans_packw(DisasContext *ctx, arg_packw *a) return gen_arith(ctx, a, EXT_NONE, gen_packw); } +static void gen_packuw(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv t = tcg_temp_new(); + tcg_gen_shri_tl(t, arg1, 16); + tcg_gen_deposit_tl(ret, arg2, t, 0, 16); + tcg_gen_ext32s_tl(ret, ret); + tcg_temp_free(t); +} + static bool trans_packuw(DisasContext *ctx, arg_packuw *a) { REQUIRE_64BIT(ctx); @@ -349,6 +512,24 @@ static bool trans_sroiw(DisasContext *ctx, arg_sroiw *a) return gen_shiftiw(ctx, a, gen_sro); } +static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + /* truncate to 32-bits */ + tcg_gen_trunc_tl_i32(t1, arg1); + tcg_gen_trunc_tl_i32(t2, arg2); + + tcg_gen_rotr_i32(t1, t1, t2); + + /* sign-extend 64-bits */ + tcg_gen_ext_i32_tl(ret, t1); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); +} + static bool trans_rorw(DisasContext *ctx, arg_rorw *a) { REQUIRE_64BIT(ctx); @@ -363,6 +544,24 @@ static bool trans_roriw(DisasContext *ctx, arg_roriw *a) return gen_shiftiw(ctx, a, gen_rorw); } +static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + /* truncate to 32-bits */ + tcg_gen_trunc_tl_i32(t1, arg1); + tcg_gen_trunc_tl_i32(t2, arg2); + + tcg_gen_rotl_i32(t1, t1, t2); + + /* sign-extend 64-bits */ + tcg_gen_ext_i32_tl(ret, t1); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); +} + static bool trans_rolw(DisasContext *ctx, arg_rolw *a) { REQUIRE_64BIT(ctx); @@ -370,6 +569,12 @@ static bool trans_rolw(DisasContext *ctx, arg_rolw *a) return gen_shiftw(ctx, a, gen_rolw); } +static void gen_grevw(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_ext32u_tl(arg1, arg1); + gen_helper_grev(ret, arg1, arg2); +} + static bool trans_grevw(DisasContext *ctx, arg_grevw *a) { REQUIRE_64BIT(ctx); @@ -384,6 +589,12 @@ static bool trans_greviw(DisasContext *ctx, arg_greviw *a) return gen_shiftiw(ctx, a, gen_grevw); } +static void gen_gorcw(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_ext32u_tl(arg1, arg1); + gen_helper_gorcw(ret, arg1, arg2); +} + static bool trans_gorcw(DisasContext *ctx, arg_gorcw *a) { REQUIRE_64BIT(ctx); @@ -398,6 +609,23 @@ static bool trans_gorciw(DisasContext *ctx, arg_gorciw *a) return gen_shiftiw(ctx, a, gen_gorcw); } +#define GEN_SHADD_UW(SHAMT) \ +static void gen_sh##SHAMT##add_uw(TCGv ret, TCGv arg1, TCGv arg2) \ +{ \ + TCGv t = tcg_temp_new(); \ + \ + tcg_gen_ext32u_tl(t, arg1); \ + \ + tcg_gen_shli_tl(t, t, SHAMT); \ + tcg_gen_add_tl(ret, t, arg2); \ + \ + tcg_temp_free(t); \ +} + +GEN_SHADD_UW(1) +GEN_SHADD_UW(2) +GEN_SHADD_UW(3) + #define GEN_TRANS_SHADD_UW(SHAMT) \ static bool trans_sh##SHAMT##add_uw(DisasContext *ctx, \ arg_sh##SHAMT##add_uw *a) \ @@ -411,6 +639,12 @@ GEN_TRANS_SHADD_UW(1) GEN_TRANS_SHADD_UW(2) GEN_TRANS_SHADD_UW(3) +static void gen_add_uw(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_ext32u_tl(arg1, arg1); + tcg_gen_add_tl(ret, arg1, arg2); +} + static bool trans_add_uw(DisasContext *ctx, arg_add_uw *a) { REQUIRE_64BIT(ctx); diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 7fbacfa..0985353 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -380,229 +380,6 @@ static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, DisasExtend ext, return true; } -static void gen_pack(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_deposit_tl(ret, arg1, arg2, - TARGET_LONG_BITS / 2, - TARGET_LONG_BITS / 2); -} - -static void gen_packu(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv t = tcg_temp_new(); - tcg_gen_shri_tl(t, arg1, TARGET_LONG_BITS / 2); - tcg_gen_deposit_tl(ret, arg2, t, 0, TARGET_LONG_BITS / 2); - tcg_temp_free(t); -} - -static void gen_packh(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv t = tcg_temp_new(); - tcg_gen_ext8u_tl(t, arg2); - tcg_gen_deposit_tl(ret, arg1, t, 8, TARGET_LONG_BITS - 8); - tcg_temp_free(t); -} - -static void gen_sbop_mask(TCGv ret, TCGv shamt) -{ - tcg_gen_movi_tl(ret, 1); - tcg_gen_shl_tl(ret, ret, shamt); -} - -static void gen_bset(TCGv ret, TCGv arg1, TCGv shamt) -{ - TCGv t = tcg_temp_new(); - - gen_sbop_mask(t, shamt); - tcg_gen_or_tl(ret, arg1, t); - - tcg_temp_free(t); -} - -static void gen_bclr(TCGv ret, TCGv arg1, TCGv shamt) -{ - TCGv t = tcg_temp_new(); - - gen_sbop_mask(t, shamt); - tcg_gen_andc_tl(ret, arg1, t); - - tcg_temp_free(t); -} - -static void gen_binv(TCGv ret, TCGv arg1, TCGv shamt) -{ - TCGv t = tcg_temp_new(); - - gen_sbop_mask(t, shamt); - tcg_gen_xor_tl(ret, arg1, t); - - tcg_temp_free(t); -} - -static void gen_bext(TCGv ret, TCGv arg1, TCGv shamt) -{ - tcg_gen_shr_tl(ret, arg1, shamt); - tcg_gen_andi_tl(ret, ret, 1); -} - -static void gen_slo(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_not_tl(ret, arg1); - tcg_gen_shl_tl(ret, ret, arg2); - tcg_gen_not_tl(ret, ret); -} - -static void gen_sro(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_not_tl(ret, arg1); - tcg_gen_shr_tl(ret, ret, arg2); - tcg_gen_not_tl(ret, ret); -} - -static bool gen_grevi(DisasContext *ctx, arg_grevi *a) -{ - TCGv source1 = tcg_temp_new(); - TCGv source2; - - gen_get_gpr(ctx, source1, a->rs1); - - if (a->shamt == (TARGET_LONG_BITS - 8)) { - /* rev8, byte swaps */ - tcg_gen_bswap_tl(source1, source1); - } else { - source2 = tcg_temp_new(); - tcg_gen_movi_tl(source2, a->shamt); - gen_helper_grev(source1, source1, source2); - tcg_temp_free(source2); - } - - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - return true; -} - -#define GEN_SHADD(SHAMT) \ -static void gen_sh##SHAMT##add(TCGv ret, TCGv arg1, TCGv arg2) \ -{ \ - TCGv t = tcg_temp_new(); \ - \ - tcg_gen_shli_tl(t, arg1, SHAMT); \ - tcg_gen_add_tl(ret, t, arg2); \ - \ - tcg_temp_free(t); \ -} - -GEN_SHADD(1) -GEN_SHADD(2) -GEN_SHADD(3) - -static void gen_ctzw(TCGv ret, TCGv arg1) -{ - tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32)); - tcg_gen_ctzi_tl(ret, ret, 64); -} - -static void gen_clzw(TCGv ret, TCGv arg1) -{ - tcg_gen_ext32u_tl(ret, arg1); - tcg_gen_clzi_tl(ret, ret, 64); - tcg_gen_subi_tl(ret, ret, 32); -} - -static void gen_cpopw(TCGv ret, TCGv arg1) -{ - tcg_gen_ext32u_tl(arg1, arg1); - tcg_gen_ctpop_tl(ret, arg1); -} - -static void gen_packw(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv t = tcg_temp_new(); - tcg_gen_ext16s_tl(t, arg2); - tcg_gen_deposit_tl(ret, arg1, t, 16, 48); - tcg_temp_free(t); -} - -static void gen_packuw(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv t = tcg_temp_new(); - tcg_gen_shri_tl(t, arg1, 16); - tcg_gen_deposit_tl(ret, arg2, t, 0, 16); - tcg_gen_ext32s_tl(ret, ret); - tcg_temp_free(t); -} - -static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv_i32 t1 = tcg_temp_new_i32(); - TCGv_i32 t2 = tcg_temp_new_i32(); - - /* truncate to 32-bits */ - tcg_gen_trunc_tl_i32(t1, arg1); - tcg_gen_trunc_tl_i32(t2, arg2); - - tcg_gen_rotr_i32(t1, t1, t2); - - /* sign-extend 64-bits */ - tcg_gen_ext_i32_tl(ret, t1); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); -} - -static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv_i32 t1 = tcg_temp_new_i32(); - TCGv_i32 t2 = tcg_temp_new_i32(); - - /* truncate to 32-bits */ - tcg_gen_trunc_tl_i32(t1, arg1); - tcg_gen_trunc_tl_i32(t2, arg2); - - tcg_gen_rotl_i32(t1, t1, t2); - - /* sign-extend 64-bits */ - tcg_gen_ext_i32_tl(ret, t1); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); -} - -static void gen_grevw(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_ext32u_tl(arg1, arg1); - gen_helper_grev(ret, arg1, arg2); -} - -static void gen_gorcw(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_ext32u_tl(arg1, arg1); - gen_helper_gorcw(ret, arg1, arg2); -} - -#define GEN_SHADD_UW(SHAMT) \ -static void gen_sh##SHAMT##add_uw(TCGv ret, TCGv arg1, TCGv arg2) \ -{ \ - TCGv t = tcg_temp_new(); \ - \ - tcg_gen_ext32u_tl(t, arg1); \ - \ - tcg_gen_shli_tl(t, t, SHAMT); \ - tcg_gen_add_tl(ret, t, arg2); \ - \ - tcg_temp_free(t); \ -} - -GEN_SHADD_UW(1) -GEN_SHADD_UW(2) -GEN_SHADD_UW(3) - -static void gen_add_uw(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_ext32u_tl(arg1, arg1); - tcg_gen_add_tl(ret, arg1, arg2); -} - static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext, void (*func)(TCGv, TCGv, TCGv)) { @@ -701,16 +478,6 @@ static bool gen_shiftiw(DisasContext *ctx, arg_shift *a, return true; } -static void gen_ctz(TCGv ret, TCGv arg1) -{ - tcg_gen_ctzi_tl(ret, arg1, TARGET_LONG_BITS); -} - -static void gen_clz(TCGv ret, TCGv arg1) -{ - tcg_gen_clzi_tl(ret, arg1, TARGET_LONG_BITS); -} - static bool gen_unary(DisasContext *ctx, arg_r2 *a, void(*func)(TCGv, TCGv)) { -- cgit v1.1 From 609039150504306a33cd7abf091fd125019bda9d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:16 -0700 Subject: target/riscv: Add DisasExtend to gen_unary Use ctx->w for ctpopw, which is the only one that can re-use the generic algorithm for the narrow operation. Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20210823195529.560295-12-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvb.c.inc | 24 +++++++++--------------- target/riscv/translate.c | 14 ++++++-------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 73f088b..e255678 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -26,7 +26,7 @@ static void gen_clz(TCGv ret, TCGv arg1) static bool trans_clz(DisasContext *ctx, arg_clz *a) { REQUIRE_EXT(ctx, RVB); - return gen_unary(ctx, a, gen_clz); + return gen_unary(ctx, a, EXT_ZERO, gen_clz); } static void gen_ctz(TCGv ret, TCGv arg1) @@ -37,13 +37,13 @@ static void gen_ctz(TCGv ret, TCGv arg1) static bool trans_ctz(DisasContext *ctx, arg_ctz *a) { REQUIRE_EXT(ctx, RVB); - return gen_unary(ctx, a, gen_ctz); + return gen_unary(ctx, a, EXT_ZERO, gen_ctz); } static bool trans_cpop(DisasContext *ctx, arg_cpop *a) { REQUIRE_EXT(ctx, RVB); - return gen_unary(ctx, a, tcg_gen_ctpop_tl); + return gen_unary(ctx, a, EXT_ZERO, tcg_gen_ctpop_tl); } static bool trans_andn(DisasContext *ctx, arg_andn *a) @@ -132,13 +132,13 @@ static bool trans_maxu(DisasContext *ctx, arg_maxu *a) static bool trans_sext_b(DisasContext *ctx, arg_sext_b *a) { REQUIRE_EXT(ctx, RVB); - return gen_unary(ctx, a, tcg_gen_ext8s_tl); + return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext8s_tl); } static bool trans_sext_h(DisasContext *ctx, arg_sext_h *a) { REQUIRE_EXT(ctx, RVB); - return gen_unary(ctx, a, tcg_gen_ext16s_tl); + return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext16s_tl); } static void gen_sbop_mask(TCGv ret, TCGv shamt) @@ -366,7 +366,6 @@ GEN_TRANS_SHADD(3) static void gen_clzw(TCGv ret, TCGv arg1) { - tcg_gen_ext32u_tl(ret, arg1); tcg_gen_clzi_tl(ret, ret, 64); tcg_gen_subi_tl(ret, ret, 32); } @@ -375,7 +374,7 @@ static bool trans_clzw(DisasContext *ctx, arg_clzw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_unary(ctx, a, gen_clzw); + return gen_unary(ctx, a, EXT_ZERO, gen_clzw); } static void gen_ctzw(TCGv ret, TCGv arg1) @@ -388,20 +387,15 @@ static bool trans_ctzw(DisasContext *ctx, arg_ctzw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_unary(ctx, a, gen_ctzw); -} - -static void gen_cpopw(TCGv ret, TCGv arg1) -{ - tcg_gen_ext32u_tl(arg1, arg1); - tcg_gen_ctpop_tl(ret, arg1); + return gen_unary(ctx, a, EXT_NONE, gen_ctzw); } static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_unary(ctx, a, gen_cpopw); + ctx->w = true; + return gen_unary(ctx, a, EXT_ZERO, tcg_gen_ctpop_tl); } static void gen_packw(TCGv ret, TCGv arg1, TCGv arg2) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 0985353..785e9e58 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -478,17 +478,15 @@ static bool gen_shiftiw(DisasContext *ctx, arg_shift *a, return true; } -static bool gen_unary(DisasContext *ctx, arg_r2 *a, - void(*func)(TCGv, TCGv)) +static bool gen_unary(DisasContext *ctx, arg_r2 *a, DisasExtend ext, + void (*func)(TCGv, TCGv)) { - TCGv source = tcg_temp_new(); - - gen_get_gpr(ctx, source, a->rs1); + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); - (*func)(source, source); + func(dest, src1); - gen_set_gpr(ctx, a->rd, source); - tcg_temp_free(source); + gen_set_gpr(ctx, a->rd, dest); return true; } -- cgit v1.1 From 89c883091f257d5c2b46f9a5b6ea975b75f41301 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:17 -0700 Subject: target/riscv: Use DisasExtend in shift operations These operations are greatly simplified by ctx->w, which allows us to fold gen_shiftw into gen_shift. Split gen_shifti into gen_shift_imm_{fn,tl} like we do for gen_arith_imm_{fn,tl}. Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20210823195529.560295-13-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvb.c.inc | 129 +++++++++++++++----------------- target/riscv/insn_trans/trans_rvi.c.inc | 88 +++++----------------- target/riscv/translate.c | 110 ++++++++++++--------------- 3 files changed, 125 insertions(+), 202 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index e255678..b97c3ca 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -160,13 +160,13 @@ static void gen_bset(TCGv ret, TCGv arg1, TCGv shamt) static bool trans_bset(DisasContext *ctx, arg_bset *a) { REQUIRE_EXT(ctx, RVB); - return gen_shift(ctx, a, gen_bset); + return gen_shift(ctx, a, EXT_NONE, gen_bset); } static bool trans_bseti(DisasContext *ctx, arg_bseti *a) { REQUIRE_EXT(ctx, RVB); - return gen_shifti(ctx, a, gen_bset); + return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bset); } static void gen_bclr(TCGv ret, TCGv arg1, TCGv shamt) @@ -182,13 +182,13 @@ static void gen_bclr(TCGv ret, TCGv arg1, TCGv shamt) static bool trans_bclr(DisasContext *ctx, arg_bclr *a) { REQUIRE_EXT(ctx, RVB); - return gen_shift(ctx, a, gen_bclr); + return gen_shift(ctx, a, EXT_NONE, gen_bclr); } static bool trans_bclri(DisasContext *ctx, arg_bclri *a) { REQUIRE_EXT(ctx, RVB); - return gen_shifti(ctx, a, gen_bclr); + return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bclr); } static void gen_binv(TCGv ret, TCGv arg1, TCGv shamt) @@ -204,13 +204,13 @@ static void gen_binv(TCGv ret, TCGv arg1, TCGv shamt) static bool trans_binv(DisasContext *ctx, arg_binv *a) { REQUIRE_EXT(ctx, RVB); - return gen_shift(ctx, a, gen_binv); + return gen_shift(ctx, a, EXT_NONE, gen_binv); } static bool trans_binvi(DisasContext *ctx, arg_binvi *a) { REQUIRE_EXT(ctx, RVB); - return gen_shifti(ctx, a, gen_binv); + return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_binv); } static void gen_bext(TCGv ret, TCGv arg1, TCGv shamt) @@ -222,13 +222,13 @@ static void gen_bext(TCGv ret, TCGv arg1, TCGv shamt) static bool trans_bext(DisasContext *ctx, arg_bext *a) { REQUIRE_EXT(ctx, RVB); - return gen_shift(ctx, a, gen_bext); + return gen_shift(ctx, a, EXT_NONE, gen_bext); } static bool trans_bexti(DisasContext *ctx, arg_bexti *a) { REQUIRE_EXT(ctx, RVB); - return gen_shifti(ctx, a, gen_bext); + return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bext); } static void gen_slo(TCGv ret, TCGv arg1, TCGv arg2) @@ -241,13 +241,13 @@ static void gen_slo(TCGv ret, TCGv arg1, TCGv arg2) static bool trans_slo(DisasContext *ctx, arg_slo *a) { REQUIRE_EXT(ctx, RVB); - return gen_shift(ctx, a, gen_slo); + return gen_shift(ctx, a, EXT_NONE, gen_slo); } static bool trans_sloi(DisasContext *ctx, arg_sloi *a) { REQUIRE_EXT(ctx, RVB); - return gen_shifti(ctx, a, gen_slo); + return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_slo); } static void gen_sro(TCGv ret, TCGv arg1, TCGv arg2) @@ -260,82 +260,65 @@ static void gen_sro(TCGv ret, TCGv arg1, TCGv arg2) static bool trans_sro(DisasContext *ctx, arg_sro *a) { REQUIRE_EXT(ctx, RVB); - return gen_shift(ctx, a, gen_sro); + return gen_shift(ctx, a, EXT_ZERO, gen_sro); } static bool trans_sroi(DisasContext *ctx, arg_sroi *a) { REQUIRE_EXT(ctx, RVB); - return gen_shifti(ctx, a, gen_sro); + return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_sro); } static bool trans_ror(DisasContext *ctx, arg_ror *a) { REQUIRE_EXT(ctx, RVB); - return gen_shift(ctx, a, tcg_gen_rotr_tl); + return gen_shift(ctx, a, EXT_NONE, tcg_gen_rotr_tl); } static bool trans_rori(DisasContext *ctx, arg_rori *a) { REQUIRE_EXT(ctx, RVB); - return gen_shifti(ctx, a, tcg_gen_rotr_tl); + return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_rotri_tl); } static bool trans_rol(DisasContext *ctx, arg_rol *a) { REQUIRE_EXT(ctx, RVB); - return gen_shift(ctx, a, tcg_gen_rotl_tl); + return gen_shift(ctx, a, EXT_NONE, tcg_gen_rotl_tl); } static bool trans_grev(DisasContext *ctx, arg_grev *a) { REQUIRE_EXT(ctx, RVB); - return gen_shift(ctx, a, gen_helper_grev); + return gen_shift(ctx, a, EXT_NONE, gen_helper_grev); } -static bool gen_grevi(DisasContext *ctx, arg_grevi *a) +static void gen_grevi(TCGv dest, TCGv src, target_long shamt) { - TCGv source1 = tcg_temp_new(); - TCGv source2; - - gen_get_gpr(ctx, source1, a->rs1); - - if (a->shamt == (TARGET_LONG_BITS - 8)) { + if (shamt == TARGET_LONG_BITS - 8) { /* rev8, byte swaps */ - tcg_gen_bswap_tl(source1, source1); + tcg_gen_bswap_tl(dest, src); } else { - source2 = tcg_temp_new(); - tcg_gen_movi_tl(source2, a->shamt); - gen_helper_grev(source1, source1, source2); - tcg_temp_free(source2); + gen_helper_grev(dest, src, tcg_constant_tl(shamt)); } - - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - return true; } static bool trans_grevi(DisasContext *ctx, arg_grevi *a) { REQUIRE_EXT(ctx, RVB); - - if (a->shamt >= TARGET_LONG_BITS) { - return false; - } - - return gen_grevi(ctx, a); + return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_grevi); } static bool trans_gorc(DisasContext *ctx, arg_gorc *a) { REQUIRE_EXT(ctx, RVB); - return gen_shift(ctx, a, gen_helper_gorc); + return gen_shift(ctx, a, EXT_ZERO, gen_helper_gorc); } static bool trans_gorci(DisasContext *ctx, arg_gorci *a) { REQUIRE_EXT(ctx, RVB); - return gen_shifti(ctx, a, gen_helper_gorc); + return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_helper_gorc); } #define GEN_SHADD(SHAMT) \ @@ -433,77 +416,88 @@ static bool trans_bsetw(DisasContext *ctx, arg_bsetw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftw(ctx, a, gen_bset); + ctx->w = true; + return gen_shift(ctx, a, EXT_NONE, gen_bset); } static bool trans_bsetiw(DisasContext *ctx, arg_bsetiw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftiw(ctx, a, gen_bset); + ctx->w = true; + return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bset); } static bool trans_bclrw(DisasContext *ctx, arg_bclrw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftw(ctx, a, gen_bclr); + ctx->w = true; + return gen_shift(ctx, a, EXT_NONE, gen_bclr); } static bool trans_bclriw(DisasContext *ctx, arg_bclriw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftiw(ctx, a, gen_bclr); + ctx->w = true; + return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bclr); } static bool trans_binvw(DisasContext *ctx, arg_binvw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftw(ctx, a, gen_binv); + ctx->w = true; + return gen_shift(ctx, a, EXT_NONE, gen_binv); } static bool trans_binviw(DisasContext *ctx, arg_binviw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftiw(ctx, a, gen_binv); + ctx->w = true; + return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_binv); } static bool trans_bextw(DisasContext *ctx, arg_bextw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftw(ctx, a, gen_bext); + ctx->w = true; + return gen_shift(ctx, a, EXT_NONE, gen_bext); } static bool trans_slow(DisasContext *ctx, arg_slow *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftw(ctx, a, gen_slo); + ctx->w = true; + return gen_shift(ctx, a, EXT_NONE, gen_slo); } static bool trans_sloiw(DisasContext *ctx, arg_sloiw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftiw(ctx, a, gen_slo); + ctx->w = true; + return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_slo); } static bool trans_srow(DisasContext *ctx, arg_srow *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftw(ctx, a, gen_sro); + ctx->w = true; + return gen_shift(ctx, a, EXT_ZERO, gen_sro); } static bool trans_sroiw(DisasContext *ctx, arg_sroiw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftiw(ctx, a, gen_sro); + ctx->w = true; + return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_sro); } static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2) @@ -528,14 +522,16 @@ static bool trans_rorw(DisasContext *ctx, arg_rorw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftw(ctx, a, gen_rorw); + ctx->w = true; + return gen_shift(ctx, a, EXT_NONE, gen_rorw); } static bool trans_roriw(DisasContext *ctx, arg_roriw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftiw(ctx, a, gen_rorw); + ctx->w = true; + return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_rorw); } static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2) @@ -560,47 +556,40 @@ static bool trans_rolw(DisasContext *ctx, arg_rolw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftw(ctx, a, gen_rolw); -} - -static void gen_grevw(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_ext32u_tl(arg1, arg1); - gen_helper_grev(ret, arg1, arg2); + ctx->w = true; + return gen_shift(ctx, a, EXT_NONE, gen_rolw); } static bool trans_grevw(DisasContext *ctx, arg_grevw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftw(ctx, a, gen_grevw); + ctx->w = true; + return gen_shift(ctx, a, EXT_ZERO, gen_helper_grev); } static bool trans_greviw(DisasContext *ctx, arg_greviw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftiw(ctx, a, gen_grevw); -} - -static void gen_gorcw(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_ext32u_tl(arg1, arg1); - gen_helper_gorcw(ret, arg1, arg2); + ctx->w = true; + return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_helper_grev); } static bool trans_gorcw(DisasContext *ctx, arg_gorcw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftw(ctx, a, gen_gorcw); + ctx->w = true; + return gen_shift(ctx, a, EXT_ZERO, gen_helper_gorc); } static bool trans_gorciw(DisasContext *ctx, arg_gorciw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - return gen_shiftiw(ctx, a, gen_gorcw); + ctx->w = true; + return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_helper_gorc); } #define GEN_SHADD_UW(SHAMT) \ diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index bd80476..e4726e6 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -270,17 +270,17 @@ static bool trans_andi(DisasContext *ctx, arg_andi *a) static bool trans_slli(DisasContext *ctx, arg_slli *a) { - return gen_shifti(ctx, a, tcg_gen_shl_tl); + return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl); } static bool trans_srli(DisasContext *ctx, arg_srli *a) { - return gen_shifti(ctx, a, tcg_gen_shr_tl); + return gen_shift_imm_fn(ctx, a, EXT_ZERO, tcg_gen_shri_tl); } static bool trans_srai(DisasContext *ctx, arg_srai *a) { - return gen_shifti(ctx, a, tcg_gen_sar_tl); + return gen_shift_imm_fn(ctx, a, EXT_SIGN, tcg_gen_sari_tl); } static bool trans_add(DisasContext *ctx, arg_add *a) @@ -295,7 +295,7 @@ static bool trans_sub(DisasContext *ctx, arg_sub *a) static bool trans_sll(DisasContext *ctx, arg_sll *a) { - return gen_shift(ctx, a, &tcg_gen_shl_tl); + return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl); } static bool trans_slt(DisasContext *ctx, arg_slt *a) @@ -315,12 +315,12 @@ static bool trans_xor(DisasContext *ctx, arg_xor *a) static bool trans_srl(DisasContext *ctx, arg_srl *a) { - return gen_shift(ctx, a, &tcg_gen_shr_tl); + return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl); } static bool trans_sra(DisasContext *ctx, arg_sra *a) { - return gen_shift(ctx, a, &tcg_gen_sar_tl); + return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl); } static bool trans_or(DisasContext *ctx, arg_or *a) @@ -343,31 +343,22 @@ static bool trans_addiw(DisasContext *ctx, arg_addiw *a) static bool trans_slliw(DisasContext *ctx, arg_slliw *a) { REQUIRE_64BIT(ctx); - return gen_shiftiw(ctx, a, tcg_gen_shl_tl); + ctx->w = true; + return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl); } static bool trans_srliw(DisasContext *ctx, arg_srliw *a) { REQUIRE_64BIT(ctx); - TCGv t = tcg_temp_new(); - gen_get_gpr(ctx, t, a->rs1); - tcg_gen_extract_tl(t, t, a->shamt, 32 - a->shamt); - /* sign-extend for W instructions */ - tcg_gen_ext32s_tl(t, t); - gen_set_gpr(ctx, a->rd, t); - tcg_temp_free(t); - return true; + ctx->w = true; + return gen_shift_imm_fn(ctx, a, EXT_ZERO, tcg_gen_shri_tl); } static bool trans_sraiw(DisasContext *ctx, arg_sraiw *a) { REQUIRE_64BIT(ctx); - TCGv t = tcg_temp_new(); - gen_get_gpr(ctx, t, a->rs1); - tcg_gen_sextract_tl(t, t, a->shamt, 32 - a->shamt); - gen_set_gpr(ctx, a->rd, t); - tcg_temp_free(t); - return true; + ctx->w = true; + return gen_shift_imm_fn(ctx, a, EXT_SIGN, tcg_gen_sari_tl); } static bool trans_addw(DisasContext *ctx, arg_addw *a) @@ -387,65 +378,22 @@ static bool trans_subw(DisasContext *ctx, arg_subw *a) static bool trans_sllw(DisasContext *ctx, arg_sllw *a) { REQUIRE_64BIT(ctx); - TCGv source1 = tcg_temp_new(); - TCGv source2 = tcg_temp_new(); - - gen_get_gpr(ctx, source1, a->rs1); - gen_get_gpr(ctx, source2, a->rs2); - - tcg_gen_andi_tl(source2, source2, 0x1F); - tcg_gen_shl_tl(source1, source1, source2); - - tcg_gen_ext32s_tl(source1, source1); - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); - return true; + ctx->w = true; + return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl); } static bool trans_srlw(DisasContext *ctx, arg_srlw *a) { REQUIRE_64BIT(ctx); - TCGv source1 = tcg_temp_new(); - TCGv source2 = tcg_temp_new(); - - gen_get_gpr(ctx, source1, a->rs1); - gen_get_gpr(ctx, source2, a->rs2); - - /* clear upper 32 */ - tcg_gen_ext32u_tl(source1, source1); - tcg_gen_andi_tl(source2, source2, 0x1F); - tcg_gen_shr_tl(source1, source1, source2); - - tcg_gen_ext32s_tl(source1, source1); - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); - return true; + ctx->w = true; + return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl); } static bool trans_sraw(DisasContext *ctx, arg_sraw *a) { REQUIRE_64BIT(ctx); - TCGv source1 = tcg_temp_new(); - TCGv source2 = tcg_temp_new(); - - gen_get_gpr(ctx, source1, a->rs1); - gen_get_gpr(ctx, source2, a->rs2); - - /* - * first, trick to get it to act like working on 32 bits (get rid of - * upper 32, sign extend to fill space) - */ - tcg_gen_ext32s_tl(source1, source1); - tcg_gen_andi_tl(source2, source2, 0x1F); - tcg_gen_sar_tl(source1, source1, source2); - - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); - - return true; + ctx->w = true; + return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl); } static bool trans_fence(DisasContext *ctx, arg_fence *a) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 785e9e58..e44254e 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -99,6 +99,13 @@ static inline bool is_32bit(DisasContext *ctx) } #endif +/* The word size for this operation. */ +static inline int oper_len(DisasContext *ctx) +{ + return ctx->w ? 32 : TARGET_LONG_BITS; +} + + /* * RISC-V requires NaN-boxing of narrower width floating point values. * This applies when a 32-bit value is assigned to a 64-bit FP register. @@ -393,88 +400,58 @@ static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext, return true; } -static bool gen_shift(DisasContext *ctx, arg_r *a, - void(*func)(TCGv, TCGv, TCGv)) -{ - TCGv source1 = tcg_temp_new(); - TCGv source2 = tcg_temp_new(); - - gen_get_gpr(ctx, source1, a->rs1); - gen_get_gpr(ctx, source2, a->rs2); - - tcg_gen_andi_tl(source2, source2, TARGET_LONG_BITS - 1); - (*func)(source1, source1, source2); - - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); - return true; -} - -static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) +static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext, + void (*func)(TCGv, TCGv, target_long)) { - DisasContext *ctx = container_of(dcbase, DisasContext, base); - CPUState *cpu = ctx->cs; - CPURISCVState *env = cpu->env_ptr; + TCGv dest, src1; + int max_len = oper_len(ctx); - return cpu_ldl_code(env, pc); -} - -static bool gen_shifti(DisasContext *ctx, arg_shift *a, - void(*func)(TCGv, TCGv, TCGv)) -{ - if (a->shamt >= TARGET_LONG_BITS) { + if (a->shamt >= max_len) { return false; } - TCGv source1 = tcg_temp_new(); - TCGv source2 = tcg_temp_new(); - - gen_get_gpr(ctx, source1, a->rs1); + dest = dest_gpr(ctx, a->rd); + src1 = get_gpr(ctx, a->rs1, ext); - tcg_gen_movi_tl(source2, a->shamt); - (*func)(source1, source1, source2); + func(dest, src1, a->shamt); - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); + gen_set_gpr(ctx, a->rd, dest); return true; } -static bool gen_shiftw(DisasContext *ctx, arg_r *a, - void(*func)(TCGv, TCGv, TCGv)) +static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext, + void (*func)(TCGv, TCGv, TCGv)) { - TCGv source1 = tcg_temp_new(); - TCGv source2 = tcg_temp_new(); + TCGv dest, src1, src2; + int max_len = oper_len(ctx); + + if (a->shamt >= max_len) { + return false; + } - gen_get_gpr(ctx, source1, a->rs1); - gen_get_gpr(ctx, source2, a->rs2); + dest = dest_gpr(ctx, a->rd); + src1 = get_gpr(ctx, a->rs1, ext); + src2 = tcg_constant_tl(a->shamt); - tcg_gen_andi_tl(source2, source2, 31); - (*func)(source1, source1, source2); - tcg_gen_ext32s_tl(source1, source1); + func(dest, src1, src2); - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); + gen_set_gpr(ctx, a->rd, dest); return true; } -static bool gen_shiftiw(DisasContext *ctx, arg_shift *a, - void(*func)(TCGv, TCGv, TCGv)) +static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext, + void (*func)(TCGv, TCGv, TCGv)) { - TCGv source1 = tcg_temp_new(); - TCGv source2 = tcg_temp_new(); - - gen_get_gpr(ctx, source1, a->rs1); - tcg_gen_movi_tl(source2, a->shamt); + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); + TCGv ext2 = tcg_temp_new(); - (*func)(source1, source1, source2); - tcg_gen_ext32s_tl(source1, source1); + tcg_gen_andi_tl(ext2, src2, oper_len(ctx) - 1); + func(dest, src1, ext2); - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); + gen_set_gpr(ctx, a->rd, dest); + tcg_temp_free(ext2); return true; } @@ -490,6 +467,15 @@ static bool gen_unary(DisasContext *ctx, arg_r2 *a, DisasExtend ext, return true; } +static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); + CPUState *cpu = ctx->cs; + CPURISCVState *env = cpu->env_ptr; + + return cpu_ldl_code(env, pc); +} + /* Include insn module translation function */ #include "insn_trans/trans_rvi.c.inc" #include "insn_trans/trans_rvm.c.inc" -- cgit v1.1 From 23c108868943f9315be0bb675f6cd4dac7295b99 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:18 -0700 Subject: target/riscv: Use extracts for sraiw and srliw These operations can be done in one instruction on some hosts. Signed-off-by: Richard Henderson Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Message-id: 20210823195529.560295-14-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvi.c.inc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index e4726e6..9e8d99b 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -347,18 +347,28 @@ static bool trans_slliw(DisasContext *ctx, arg_slliw *a) return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl); } +static void gen_srliw(TCGv dst, TCGv src, target_long shamt) +{ + tcg_gen_extract_tl(dst, src, shamt, 32 - shamt); +} + static bool trans_srliw(DisasContext *ctx, arg_srliw *a) { REQUIRE_64BIT(ctx); ctx->w = true; - return gen_shift_imm_fn(ctx, a, EXT_ZERO, tcg_gen_shri_tl); + return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_srliw); +} + +static void gen_sraiw(TCGv dst, TCGv src, target_long shamt) +{ + tcg_gen_sextract_tl(dst, src, shamt, 32 - shamt); } static bool trans_sraiw(DisasContext *ctx, arg_sraiw *a) { REQUIRE_64BIT(ctx); ctx->w = true; - return gen_shift_imm_fn(ctx, a, EXT_SIGN, tcg_gen_sari_tl); + return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_sraiw); } static bool trans_addw(DisasContext *ctx, arg_addw *a) -- cgit v1.1 From 9b21b64345c91ca71c7c33ac7caffd8804ae32cb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:19 -0700 Subject: target/riscv: Use get_gpr in branches Narrow the scope of t0 in trans_jalr. Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20210823195529.560295-15-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvi.c.inc | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 9e8d99b..a5249e7 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -54,24 +54,25 @@ static bool trans_jal(DisasContext *ctx, arg_jal *a) static bool trans_jalr(DisasContext *ctx, arg_jalr *a) { - /* no chaining with JALR */ TCGLabel *misaligned = NULL; - TCGv t0 = tcg_temp_new(); - - gen_get_gpr(ctx, cpu_pc, a->rs1); - tcg_gen_addi_tl(cpu_pc, cpu_pc, a->imm); + tcg_gen_addi_tl(cpu_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm); tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2); if (!has_ext(ctx, RVC)) { + TCGv t0 = tcg_temp_new(); + misaligned = gen_new_label(); tcg_gen_andi_tl(t0, cpu_pc, 0x2); tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned); + tcg_temp_free(t0); } if (a->rd != 0) { tcg_gen_movi_tl(cpu_gpr[a->rd], ctx->pc_succ_insn); } + + /* No chaining with JALR. */ lookup_and_goto_ptr(ctx); if (misaligned) { @@ -80,21 +81,18 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a) } ctx->base.is_jmp = DISAS_NORETURN; - tcg_temp_free(t0); return true; } static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond) { TCGLabel *l = gen_new_label(); - TCGv source1, source2; - source1 = tcg_temp_new(); - source2 = tcg_temp_new(); - gen_get_gpr(ctx, source1, a->rs1); - gen_get_gpr(ctx, source2, a->rs2); + TCGv src1 = get_gpr(ctx, a->rs1, EXT_SIGN); + TCGv src2 = get_gpr(ctx, a->rs2, EXT_SIGN); - tcg_gen_brcond_tl(cond, source1, source2, l); + tcg_gen_brcond_tl(cond, src1, src2, l); gen_goto_tb(ctx, 1, ctx->pc_succ_insn); + gen_set_label(l); /* branch taken */ if (!has_ext(ctx, RVC) && ((ctx->base.pc_next + a->imm) & 0x3)) { @@ -105,9 +103,6 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond) } ctx->base.is_jmp = DISAS_NORETURN; - tcg_temp_free(source1); - tcg_temp_free(source2); - return true; } -- cgit v1.1 From 6ecf39e2dd854ff7ea21c365165c1957061263bb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:20 -0700 Subject: target/riscv: Use {get, dest}_gpr for integer load/store Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20210823195529.560295-16-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvi.c.inc | 38 +++++++++++++++++---------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index a5249e7..76454fb 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -138,15 +138,17 @@ static bool trans_bgeu(DisasContext *ctx, arg_bgeu *a) static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop) { - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); - tcg_gen_addi_tl(t0, t0, a->imm); - - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, memop); - gen_set_gpr(ctx, a->rd, t1); - tcg_temp_free(t0); - tcg_temp_free(t1); + TCGv dest = dest_gpr(ctx, a->rd); + TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE); + + if (a->imm) { + TCGv temp = temp_new(ctx); + tcg_gen_addi_tl(temp, addr, a->imm); + addr = temp; + } + + tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, memop); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -177,19 +179,19 @@ static bool trans_lhu(DisasContext *ctx, arg_lhu *a) static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop) { - TCGv t0 = tcg_temp_new(); - TCGv dat = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); - tcg_gen_addi_tl(t0, t0, a->imm); - gen_get_gpr(ctx, dat, a->rs2); + TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE); + TCGv data = get_gpr(ctx, a->rs2, EXT_NONE); - tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx, memop); - tcg_temp_free(t0); - tcg_temp_free(dat); + if (a->imm) { + TCGv temp = temp_new(ctx); + tcg_gen_addi_tl(temp, addr, a->imm); + addr = temp; + } + + tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop); return true; } - static bool trans_sb(DisasContext *ctx, arg_sb *a) { return gen_store(ctx, a, MO_SB); -- cgit v1.1 From 33979526cad412b72afd1989a22dcd218b2ce170 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:21 -0700 Subject: target/riscv: Fix rmw_sip, rmw_vsip, rmw_hsip vs write-only operation We distinguish write-only by passing ret_value as NULL. Signed-off-by: Richard Henderson Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Message-id: 20210823195529.560295-17-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/csr.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 6d7f2c2..16bd859 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -937,9 +937,12 @@ static RISCVException rmw_vsip(CPURISCVState *env, int csrno, /* Shift the S bits to their VS bit location in mip */ int ret = rmw_mip(env, 0, ret_value, new_value << 1, (write_mask << 1) & vsip_writable_mask & env->hideleg); - *ret_value &= VS_MODE_INTERRUPTS; - /* Shift the VS bits to their S bit location in vsip */ - *ret_value >>= 1; + + if (ret_value) { + *ret_value &= VS_MODE_INTERRUPTS; + /* Shift the VS bits to their S bit location in vsip */ + *ret_value >>= 1; + } return ret; } @@ -956,7 +959,9 @@ static RISCVException rmw_sip(CPURISCVState *env, int csrno, write_mask & env->mideleg & sip_writable_mask); } - *ret_value &= env->mideleg; + if (ret_value) { + *ret_value &= env->mideleg; + } return ret; } @@ -1072,8 +1077,9 @@ static RISCVException rmw_hvip(CPURISCVState *env, int csrno, int ret = rmw_mip(env, 0, ret_value, new_value, write_mask & hvip_writable_mask); - *ret_value &= hvip_writable_mask; - + if (ret_value) { + *ret_value &= hvip_writable_mask; + } return ret; } @@ -1084,8 +1090,9 @@ static RISCVException rmw_hip(CPURISCVState *env, int csrno, int ret = rmw_mip(env, 0, ret_value, new_value, write_mask & hip_writable_mask); - *ret_value &= hip_writable_mask; - + if (ret_value) { + *ret_value &= hip_writable_mask; + } return ret; } -- cgit v1.1 From 377cbb4bdbe2ee4155d740bf1d7fc9a081a61219 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:22 -0700 Subject: target/riscv: Fix hgeie, hgeip We failed to write into *val for these read functions; replace them with read_zero. Only warn about unsupported non-zero value when writing a non-zero value. Signed-off-by: Richard Henderson Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Message-id: 20210823195529.560295-18-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/csr.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 16bd859..50a2c3a 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1124,17 +1124,12 @@ static RISCVException write_hcounteren(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } -static RISCVException read_hgeie(CPURISCVState *env, int csrno, - target_ulong *val) -{ - qemu_log_mask(LOG_UNIMP, "No support for a non-zero GEILEN."); - return RISCV_EXCP_NONE; -} - static RISCVException write_hgeie(CPURISCVState *env, int csrno, target_ulong val) { - qemu_log_mask(LOG_UNIMP, "No support for a non-zero GEILEN."); + if (val) { + qemu_log_mask(LOG_UNIMP, "No support for a non-zero GEILEN."); + } return RISCV_EXCP_NONE; } @@ -1165,17 +1160,12 @@ static RISCVException write_htinst(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } -static RISCVException read_hgeip(CPURISCVState *env, int csrno, - target_ulong *val) -{ - qemu_log_mask(LOG_UNIMP, "No support for a non-zero GEILEN."); - return RISCV_EXCP_NONE; -} - static RISCVException write_hgeip(CPURISCVState *env, int csrno, target_ulong val) { - qemu_log_mask(LOG_UNIMP, "No support for a non-zero GEILEN."); + if (val) { + qemu_log_mask(LOG_UNIMP, "No support for a non-zero GEILEN."); + } return RISCV_EXCP_NONE; } @@ -1601,10 +1591,10 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_HIP] = { "hip", hmode, NULL, NULL, rmw_hip }, [CSR_HIE] = { "hie", hmode, read_hie, write_hie }, [CSR_HCOUNTEREN] = { "hcounteren", hmode, read_hcounteren, write_hcounteren }, - [CSR_HGEIE] = { "hgeie", hmode, read_hgeie, write_hgeie }, + [CSR_HGEIE] = { "hgeie", hmode, read_zero, write_hgeie }, [CSR_HTVAL] = { "htval", hmode, read_htval, write_htval }, [CSR_HTINST] = { "htinst", hmode, read_htinst, write_htinst }, - [CSR_HGEIP] = { "hgeip", hmode, read_hgeip, write_hgeip }, + [CSR_HGEIP] = { "hgeip", hmode, read_zero, write_hgeip }, [CSR_HGATP] = { "hgatp", hmode, read_hgatp, write_hgatp }, [CSR_HTIMEDELTA] = { "htimedelta", hmode, read_htimedelta, write_htimedelta }, [CSR_HTIMEDELTAH] = { "htimedeltah", hmode32, read_htimedeltah, write_htimedeltah }, -- cgit v1.1 From a974879b4581b58369a1e5e01d8ce6736764c679 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:23 -0700 Subject: target/riscv: Reorg csr instructions Introduce csrr and csrw helpers, for read-only and write-only insns. Note that we do not properly implement this in riscv_csrrw, in that we cannot distinguish true read-only (rs1 == 0) from any other zero write_mask another source register -- this should still raise an exception for read-only registers. Only issue gen_io_start for CF_USE_ICOUNT. Use ctx->zero for csrrc. Use get_gpr and dest_gpr. Reviewed-by: Bin Meng Signed-off-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210823195529.560295-19-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/helper.h | 6 +- target/riscv/insn_trans/trans_rvi.c.inc | 174 ++++++++++++++++++++++---------- target/riscv/op_helper.c | 18 ++-- 3 files changed, 132 insertions(+), 66 deletions(-) diff --git a/target/riscv/helper.h b/target/riscv/helper.h index 415e37b..460eee9 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -65,9 +65,9 @@ DEF_HELPER_FLAGS_2(gorc, TCG_CALL_NO_RWG_SE, tl, tl, tl) DEF_HELPER_FLAGS_2(gorcw, TCG_CALL_NO_RWG_SE, tl, tl, tl) /* Special functions */ -DEF_HELPER_3(csrrw, tl, env, tl, tl) -DEF_HELPER_4(csrrs, tl, env, tl, tl, tl) -DEF_HELPER_4(csrrc, tl, env, tl, tl, tl) +DEF_HELPER_2(csrr, tl, env, int) +DEF_HELPER_3(csrw, void, env, int, tl) +DEF_HELPER_4(csrrw, tl, env, int, tl, tl) #ifndef CONFIG_USER_ONLY DEF_HELPER_2(sret, tl, env, tl) DEF_HELPER_2(mret, tl, env, tl) diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 76454fb..920ae0e 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -426,80 +426,150 @@ static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a) return true; } -#define RISCV_OP_CSR_PRE do {\ - source1 = tcg_temp_new(); \ - csr_store = tcg_temp_new(); \ - dest = tcg_temp_new(); \ - rs1_pass = tcg_temp_new(); \ - gen_get_gpr(ctx, source1, a->rs1); \ - tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); \ - tcg_gen_movi_tl(rs1_pass, a->rs1); \ - tcg_gen_movi_tl(csr_store, a->csr); \ - gen_io_start();\ -} while (0) - -#define RISCV_OP_CSR_POST do {\ - gen_set_gpr(ctx, a->rd, dest); \ - tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); \ - exit_tb(ctx); \ - ctx->base.is_jmp = DISAS_NORETURN; \ - tcg_temp_free(source1); \ - tcg_temp_free(csr_store); \ - tcg_temp_free(dest); \ - tcg_temp_free(rs1_pass); \ -} while (0) +static bool do_csr_post(DisasContext *ctx) +{ + /* We may have changed important cpu state -- exit to main loop. */ + tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); + exit_tb(ctx); + ctx->base.is_jmp = DISAS_NORETURN; + return true; +} + +static bool do_csrr(DisasContext *ctx, int rd, int rc) +{ + TCGv dest = dest_gpr(ctx, rd); + TCGv_i32 csr = tcg_constant_i32(rc); + + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } + gen_helper_csrr(dest, cpu_env, csr); + gen_set_gpr(ctx, rd, dest); + return do_csr_post(ctx); +} + +static bool do_csrw(DisasContext *ctx, int rc, TCGv src) +{ + TCGv_i32 csr = tcg_constant_i32(rc); + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } + gen_helper_csrw(cpu_env, csr, src); + return do_csr_post(ctx); +} + +static bool do_csrrw(DisasContext *ctx, int rd, int rc, TCGv src, TCGv mask) +{ + TCGv dest = dest_gpr(ctx, rd); + TCGv_i32 csr = tcg_constant_i32(rc); + + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } + gen_helper_csrrw(dest, cpu_env, csr, src, mask); + gen_set_gpr(ctx, rd, dest); + return do_csr_post(ctx); +} static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a) { - TCGv source1, csr_store, dest, rs1_pass; - RISCV_OP_CSR_PRE; - gen_helper_csrrw(dest, cpu_env, source1, csr_store); - RISCV_OP_CSR_POST; - return true; + TCGv src = get_gpr(ctx, a->rs1, EXT_NONE); + + /* + * If rd == 0, the insn shall not read the csr, nor cause any of the + * side effects that might occur on a csr read. + */ + if (a->rd == 0) { + return do_csrw(ctx, a->csr, src); + } + + TCGv mask = tcg_constant_tl(-1); + return do_csrrw(ctx, a->rd, a->csr, src, mask); } static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a) { - TCGv source1, csr_store, dest, rs1_pass; - RISCV_OP_CSR_PRE; - gen_helper_csrrs(dest, cpu_env, source1, csr_store, rs1_pass); - RISCV_OP_CSR_POST; - return true; + /* + * If rs1 == 0, the insn shall not write to the csr at all, nor + * cause any of the side effects that might occur on a csr write. + * Note that if rs1 specifies a register other than x0, holding + * a zero value, the instruction will still attempt to write the + * unmodified value back to the csr and will cause side effects. + */ + if (a->rs1 == 0) { + return do_csrr(ctx, a->rd, a->csr); + } + + TCGv ones = tcg_constant_tl(-1); + TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO); + return do_csrrw(ctx, a->rd, a->csr, ones, mask); } static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a) { - TCGv source1, csr_store, dest, rs1_pass; - RISCV_OP_CSR_PRE; - gen_helper_csrrc(dest, cpu_env, source1, csr_store, rs1_pass); - RISCV_OP_CSR_POST; - return true; + /* + * If rs1 == 0, the insn shall not write to the csr at all, nor + * cause any of the side effects that might occur on a csr write. + * Note that if rs1 specifies a register other than x0, holding + * a zero value, the instruction will still attempt to write the + * unmodified value back to the csr and will cause side effects. + */ + if (a->rs1 == 0) { + return do_csrr(ctx, a->rd, a->csr); + } + + TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO); + return do_csrrw(ctx, a->rd, a->csr, ctx->zero, mask); } static bool trans_csrrwi(DisasContext *ctx, arg_csrrwi *a) { - TCGv source1, csr_store, dest, rs1_pass; - RISCV_OP_CSR_PRE; - gen_helper_csrrw(dest, cpu_env, rs1_pass, csr_store); - RISCV_OP_CSR_POST; - return true; + TCGv src = tcg_constant_tl(a->rs1); + + /* + * If rd == 0, the insn shall not read the csr, nor cause any of the + * side effects that might occur on a csr read. + */ + if (a->rd == 0) { + return do_csrw(ctx, a->csr, src); + } + + TCGv mask = tcg_constant_tl(-1); + return do_csrrw(ctx, a->rd, a->csr, src, mask); } static bool trans_csrrsi(DisasContext *ctx, arg_csrrsi *a) { - TCGv source1, csr_store, dest, rs1_pass; - RISCV_OP_CSR_PRE; - gen_helper_csrrs(dest, cpu_env, rs1_pass, csr_store, rs1_pass); - RISCV_OP_CSR_POST; - return true; + /* + * If rs1 == 0, the insn shall not write to the csr at all, nor + * cause any of the side effects that might occur on a csr write. + * Note that if rs1 specifies a register other than x0, holding + * a zero value, the instruction will still attempt to write the + * unmodified value back to the csr and will cause side effects. + */ + if (a->rs1 == 0) { + return do_csrr(ctx, a->rd, a->csr); + } + + TCGv ones = tcg_constant_tl(-1); + TCGv mask = tcg_constant_tl(a->rs1); + return do_csrrw(ctx, a->rd, a->csr, ones, mask); } static bool trans_csrrci(DisasContext *ctx, arg_csrrci *a) { - TCGv source1, csr_store, dest, rs1_pass; - RISCV_OP_CSR_PRE; - gen_helper_csrrc(dest, cpu_env, rs1_pass, csr_store, rs1_pass); - RISCV_OP_CSR_POST; - return true; + /* + * If rs1 == 0, the insn shall not write to the csr at all, nor + * cause any of the side effects that might occur on a csr write. + * Note that if rs1 specifies a register other than x0, holding + * a zero value, the instruction will still attempt to write the + * unmodified value back to the csr and will cause side effects. + */ + if (a->rs1 == 0) { + return do_csrr(ctx, a->rd, a->csr); + } + + TCGv mask = tcg_constant_tl(a->rs1); + return do_csrrw(ctx, a->rd, a->csr, ctx->zero, mask); } diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 3c48e73..ee7c24e 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -37,11 +37,10 @@ void helper_raise_exception(CPURISCVState *env, uint32_t exception) riscv_raise_exception(env, exception, 0); } -target_ulong helper_csrrw(CPURISCVState *env, target_ulong src, - target_ulong csr) +target_ulong helper_csrr(CPURISCVState *env, int csr) { target_ulong val = 0; - RISCVException ret = riscv_csrrw(env, csr, &val, src, -1); + RISCVException ret = riscv_csrrw(env, csr, &val, 0, 0); if (ret != RISCV_EXCP_NONE) { riscv_raise_exception(env, ret, GETPC()); @@ -49,23 +48,20 @@ target_ulong helper_csrrw(CPURISCVState *env, target_ulong src, return val; } -target_ulong helper_csrrs(CPURISCVState *env, target_ulong src, - target_ulong csr, target_ulong rs1_pass) +void helper_csrw(CPURISCVState *env, int csr, target_ulong src) { - target_ulong val = 0; - RISCVException ret = riscv_csrrw(env, csr, &val, -1, rs1_pass ? src : 0); + RISCVException ret = riscv_csrrw(env, csr, NULL, src, -1); if (ret != RISCV_EXCP_NONE) { riscv_raise_exception(env, ret, GETPC()); } - return val; } -target_ulong helper_csrrc(CPURISCVState *env, target_ulong src, - target_ulong csr, target_ulong rs1_pass) +target_ulong helper_csrrw(CPURISCVState *env, int csr, + target_ulong src, target_ulong write_mask) { target_ulong val = 0; - RISCVException ret = riscv_csrrw(env, csr, &val, 0, rs1_pass ? src : 0); + RISCVException ret = riscv_csrrw(env, csr, &val, src, write_mask); if (ret != RISCV_EXCP_NONE) { riscv_raise_exception(env, ret, GETPC()); -- cgit v1.1 From cce762a75e2cd9d9f121949c68f04ab8fabcdd3a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:24 -0700 Subject: target/riscv: Use {get,dest}_gpr for RVA Reviewed-by: Bin Meng Signed-off-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210823195529.560295-20-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rva.c.inc | 47 +++++++++++++-------------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/target/riscv/insn_trans/trans_rva.c.inc b/target/riscv/insn_trans/trans_rva.c.inc index 3cc3c3b..6ea07d8 100644 --- a/target/riscv/insn_trans/trans_rva.c.inc +++ b/target/riscv/insn_trans/trans_rva.c.inc @@ -18,11 +18,10 @@ * this program. If not, see . */ -static inline bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop) +static bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop) { - TCGv src1 = tcg_temp_new(); - /* Put addr in load_res, data in load_val. */ - gen_get_gpr(ctx, src1, a->rs1); + TCGv src1 = get_gpr(ctx, a->rs1, EXT_ZERO); + if (a->rl) { tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL); } @@ -30,33 +29,33 @@ static inline bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop) if (a->aq) { tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ); } + + /* Put addr in load_res, data in load_val. */ tcg_gen_mov_tl(load_res, src1); gen_set_gpr(ctx, a->rd, load_val); - tcg_temp_free(src1); return true; } -static inline bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) +static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) { - TCGv src1 = tcg_temp_new(); - TCGv src2 = tcg_temp_new(); - TCGv dat = tcg_temp_new(); + TCGv dest, src1, src2; TCGLabel *l1 = gen_new_label(); TCGLabel *l2 = gen_new_label(); - gen_get_gpr(ctx, src1, a->rs1); + src1 = get_gpr(ctx, a->rs1, EXT_ZERO); tcg_gen_brcond_tl(TCG_COND_NE, load_res, src1, l1); - gen_get_gpr(ctx, src2, a->rs2); /* * Note that the TCG atomic primitives are SC, * so we can ignore AQ/RL along this path. */ - tcg_gen_atomic_cmpxchg_tl(src1, load_res, load_val, src2, + dest = dest_gpr(ctx, a->rd); + src2 = get_gpr(ctx, a->rs2, EXT_NONE); + tcg_gen_atomic_cmpxchg_tl(dest, load_res, load_val, src2, ctx->mem_idx, mop); - tcg_gen_setcond_tl(TCG_COND_NE, dat, src1, load_val); - gen_set_gpr(ctx, a->rd, dat); + tcg_gen_setcond_tl(TCG_COND_NE, dest, dest, load_val); + gen_set_gpr(ctx, a->rd, dest); tcg_gen_br(l2); gen_set_label(l1); @@ -65,8 +64,7 @@ static inline bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) * provide the memory barrier implied by AQ/RL. */ tcg_gen_mb(TCG_MO_ALL + a->aq * TCG_BAR_LDAQ + a->rl * TCG_BAR_STRL); - tcg_gen_movi_tl(dat, 1); - gen_set_gpr(ctx, a->rd, dat); + gen_set_gpr(ctx, a->rd, tcg_constant_tl(1)); gen_set_label(l2); /* @@ -75,9 +73,6 @@ static inline bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) */ tcg_gen_movi_tl(load_res, -1); - tcg_temp_free(dat); - tcg_temp_free(src1); - tcg_temp_free(src2); return true; } @@ -85,17 +80,13 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a, void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp), MemOp mop) { - TCGv src1 = tcg_temp_new(); - TCGv src2 = tcg_temp_new(); - - gen_get_gpr(ctx, src1, a->rs1); - gen_get_gpr(ctx, src2, a->rs2); + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); - (*func)(src2, src1, src2, ctx->mem_idx, mop); + func(dest, src1, src2, ctx->mem_idx, mop); - gen_set_gpr(ctx, a->rd, src2); - tcg_temp_free(src1); - tcg_temp_free(src2); + gen_set_gpr(ctx, a->rd, dest); return true; } -- cgit v1.1 From 6922eee6acc09720883653246daa16e7dc4e2d3c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:25 -0700 Subject: target/riscv: Use gen_shift_imm_fn for slli_uw Always use tcg_gen_deposit_z_tl; the special case for shamt >= 32 is handled there. Signed-off-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210823195529.560295-21-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvb.c.inc | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index b97c3ca..b72e762 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -635,21 +635,14 @@ static bool trans_add_uw(DisasContext *ctx, arg_add_uw *a) return gen_arith(ctx, a, EXT_NONE, gen_add_uw); } +static void gen_slli_uw(TCGv dest, TCGv src, target_long shamt) +{ + tcg_gen_deposit_z_tl(dest, src, shamt, MIN(32, TARGET_LONG_BITS - shamt)); +} + static bool trans_slli_uw(DisasContext *ctx, arg_slli_uw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVB); - - TCGv source1 = tcg_temp_new(); - gen_get_gpr(ctx, source1, a->rs1); - - if (a->shamt < 32) { - tcg_gen_deposit_z_tl(source1, source1, a->shamt, 32); - } else { - tcg_gen_shli_tl(source1, source1, a->shamt); - } - - gen_set_gpr(ctx, a->rd, source1); - tcg_temp_free(source1); - return true; + return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_slli_uw); } -- cgit v1.1 From 75234a284316610c55749962b302a6ef46c0f745 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:26 -0700 Subject: target/riscv: Use {get,dest}_gpr for RVF Reviewed-by: Bin Meng Signed-off-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210823195529.560295-22-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvf.c.inc | 146 +++++++++++++++----------------- 1 file changed, 70 insertions(+), 76 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvf.c.inc b/target/riscv/insn_trans/trans_rvf.c.inc index fb9f7f9..bddbd41 100644 --- a/target/riscv/insn_trans/trans_rvf.c.inc +++ b/target/riscv/insn_trans/trans_rvf.c.inc @@ -25,32 +25,43 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a) { + TCGv_i64 dest; + TCGv addr; + REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); - tcg_gen_addi_tl(t0, t0, a->imm); - tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], t0, ctx->mem_idx, MO_TEUL); - gen_nanbox_s(cpu_fpr[a->rd], cpu_fpr[a->rd]); + addr = get_gpr(ctx, a->rs1, EXT_NONE); + if (a->imm) { + TCGv temp = temp_new(ctx); + tcg_gen_addi_tl(temp, addr, a->imm); + addr = temp; + } + + dest = cpu_fpr[a->rd]; + tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_TEUL); + gen_nanbox_s(dest, dest); - tcg_temp_free(t0); mark_fs_dirty(ctx); return true; } static bool trans_fsw(DisasContext *ctx, arg_fsw *a) { + TCGv addr; + REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); - tcg_gen_addi_tl(t0, t0, a->imm); + addr = get_gpr(ctx, a->rs1, EXT_NONE); + if (a->imm) { + TCGv temp = tcg_temp_new(); + tcg_gen_addi_tl(temp, addr, a->imm); + addr = temp; + } - tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEUL); + tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUL); - tcg_temp_free(t0); return true; } @@ -271,12 +282,11 @@ static bool trans_fcvt_w_s(DisasContext *ctx, arg_fcvt_w_s *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); - gen_set_rm(ctx, a->rm); - gen_helper_fcvt_w_s(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + TCGv dest = dest_gpr(ctx, a->rd); + gen_set_rm(ctx, a->rm); + gen_helper_fcvt_w_s(dest, cpu_env, cpu_fpr[a->rs1]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -285,12 +295,11 @@ static bool trans_fcvt_wu_s(DisasContext *ctx, arg_fcvt_wu_s *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); - gen_set_rm(ctx, a->rm); - gen_helper_fcvt_wu_s(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + TCGv dest = dest_gpr(ctx, a->rd); + gen_set_rm(ctx, a->rm); + gen_helper_fcvt_wu_s(dest, cpu_env, cpu_fpr[a->rs1]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -300,17 +309,15 @@ static bool trans_fmv_x_w(DisasContext *ctx, arg_fmv_x_w *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); + TCGv dest = dest_gpr(ctx, a->rd); #if defined(TARGET_RISCV64) - tcg_gen_ext32s_tl(t0, cpu_fpr[a->rs1]); + tcg_gen_ext32s_tl(dest, cpu_fpr[a->rs1]); #else - tcg_gen_extrl_i64_i32(t0, cpu_fpr[a->rs1]); + tcg_gen_extrl_i64_i32(dest, cpu_fpr[a->rs1]); #endif - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); - + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -318,10 +325,11 @@ static bool trans_feq_s(DisasContext *ctx, arg_feq_s *a) { REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); - gen_helper_feq_s(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + + TCGv dest = dest_gpr(ctx, a->rd); + + gen_helper_feq_s(dest, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -329,10 +337,11 @@ static bool trans_flt_s(DisasContext *ctx, arg_flt_s *a) { REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); - gen_helper_flt_s(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + + TCGv dest = dest_gpr(ctx, a->rd); + + gen_helper_flt_s(dest, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -340,10 +349,11 @@ static bool trans_fle_s(DisasContext *ctx, arg_fle_s *a) { REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); - gen_helper_fle_s(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + + TCGv dest = dest_gpr(ctx, a->rd); + + gen_helper_fle_s(dest, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -352,13 +362,10 @@ static bool trans_fclass_s(DisasContext *ctx, arg_fclass_s *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); - - gen_helper_fclass_s(t0, cpu_fpr[a->rs1]); - - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + TCGv dest = dest_gpr(ctx, a->rd); + gen_helper_fclass_s(dest, cpu_fpr[a->rs1]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -367,15 +374,12 @@ static bool trans_fcvt_s_w(DisasContext *ctx, arg_fcvt_s_w *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); + TCGv src = get_gpr(ctx, a->rs1, EXT_SIGN); gen_set_rm(ctx, a->rm); - gen_helper_fcvt_s_w(cpu_fpr[a->rd], cpu_env, t0); + gen_helper_fcvt_s_w(cpu_fpr[a->rd], cpu_env, src); mark_fs_dirty(ctx); - tcg_temp_free(t0); - return true; } @@ -384,15 +388,12 @@ static bool trans_fcvt_s_wu(DisasContext *ctx, arg_fcvt_s_wu *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); + TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO); gen_set_rm(ctx, a->rm); - gen_helper_fcvt_s_wu(cpu_fpr[a->rd], cpu_env, t0); + gen_helper_fcvt_s_wu(cpu_fpr[a->rd], cpu_env, src); mark_fs_dirty(ctx); - tcg_temp_free(t0); - return true; } @@ -402,15 +403,12 @@ static bool trans_fmv_w_x(DisasContext *ctx, arg_fmv_w_x *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); + TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO); - tcg_gen_extu_tl_i64(cpu_fpr[a->rd], t0); + tcg_gen_extu_tl_i64(cpu_fpr[a->rd], src); gen_nanbox_s(cpu_fpr[a->rd], cpu_fpr[a->rd]); mark_fs_dirty(ctx); - tcg_temp_free(t0); - return true; } @@ -420,11 +418,11 @@ static bool trans_fcvt_l_s(DisasContext *ctx, arg_fcvt_l_s *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); + TCGv dest = dest_gpr(ctx, a->rd); + gen_set_rm(ctx, a->rm); - gen_helper_fcvt_l_s(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + gen_helper_fcvt_l_s(dest, cpu_env, cpu_fpr[a->rs1]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -434,11 +432,11 @@ static bool trans_fcvt_lu_s(DisasContext *ctx, arg_fcvt_lu_s *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); + TCGv dest = dest_gpr(ctx, a->rd); + gen_set_rm(ctx, a->rm); - gen_helper_fcvt_lu_s(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + gen_helper_fcvt_lu_s(dest, cpu_env, cpu_fpr[a->rs1]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -448,14 +446,12 @@ static bool trans_fcvt_s_l(DisasContext *ctx, arg_fcvt_s_l *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); + TCGv src = get_gpr(ctx, a->rs1, EXT_SIGN); gen_set_rm(ctx, a->rm); - gen_helper_fcvt_s_l(cpu_fpr[a->rd], cpu_env, t0); + gen_helper_fcvt_s_l(cpu_fpr[a->rd], cpu_env, src); mark_fs_dirty(ctx); - tcg_temp_free(t0); return true; } @@ -465,13 +461,11 @@ static bool trans_fcvt_s_lu(DisasContext *ctx, arg_fcvt_s_lu *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - TCGv t0 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); + TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO); gen_set_rm(ctx, a->rm); - gen_helper_fcvt_s_lu(cpu_fpr[a->rd], cpu_env, t0); + gen_helper_fcvt_s_lu(cpu_fpr[a->rd], cpu_env, src); mark_fs_dirty(ctx); - tcg_temp_free(t0); return true; } -- cgit v1.1 From 7976837f9a1faa80a7b0eb12d2b8209b596fb3e2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:27 -0700 Subject: target/riscv: Use {get,dest}_gpr for RVD Reviewed-by: Bin Meng Signed-off-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210823195529.560295-23-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvd.c.inc | 125 +++++++++++++++----------------- 1 file changed, 60 insertions(+), 65 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvd.c.inc b/target/riscv/insn_trans/trans_rvd.c.inc index 11b9b3f..db9ae15 100644 --- a/target/riscv/insn_trans/trans_rvd.c.inc +++ b/target/riscv/insn_trans/trans_rvd.c.inc @@ -20,30 +20,40 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) { + TCGv addr; + REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - TCGv t0 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); - tcg_gen_addi_tl(t0, t0, a->imm); - tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], t0, ctx->mem_idx, MO_TEQ); + addr = get_gpr(ctx, a->rs1, EXT_NONE); + if (a->imm) { + TCGv temp = temp_new(ctx); + tcg_gen_addi_tl(temp, addr, a->imm); + addr = temp; + } + + tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, MO_TEQ); mark_fs_dirty(ctx); - tcg_temp_free(t0); return true; } static bool trans_fsd(DisasContext *ctx, arg_fsd *a) { + TCGv addr; + REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - TCGv t0 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); - tcg_gen_addi_tl(t0, t0, a->imm); - tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEQ); + addr = get_gpr(ctx, a->rs1, EXT_NONE); + if (a->imm) { + TCGv temp = temp_new(ctx); + tcg_gen_addi_tl(temp, addr, a->imm); + addr = temp; + } + + tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEQ); - tcg_temp_free(t0); return true; } @@ -252,11 +262,10 @@ static bool trans_feq_d(DisasContext *ctx, arg_feq_d *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - TCGv t0 = tcg_temp_new(); - gen_helper_feq_d(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + TCGv dest = dest_gpr(ctx, a->rd); + gen_helper_feq_d(dest, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -265,11 +274,10 @@ static bool trans_flt_d(DisasContext *ctx, arg_flt_d *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - TCGv t0 = tcg_temp_new(); - gen_helper_flt_d(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + TCGv dest = dest_gpr(ctx, a->rd); + gen_helper_flt_d(dest, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -278,11 +286,10 @@ static bool trans_fle_d(DisasContext *ctx, arg_fle_d *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - TCGv t0 = tcg_temp_new(); - gen_helper_fle_d(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + TCGv dest = dest_gpr(ctx, a->rd); + gen_helper_fle_d(dest, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -291,10 +298,10 @@ static bool trans_fclass_d(DisasContext *ctx, arg_fclass_d *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - TCGv t0 = tcg_temp_new(); - gen_helper_fclass_d(t0, cpu_fpr[a->rs1]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + TCGv dest = dest_gpr(ctx, a->rd); + + gen_helper_fclass_d(dest, cpu_fpr[a->rs1]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -303,12 +310,11 @@ static bool trans_fcvt_w_d(DisasContext *ctx, arg_fcvt_w_d *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - TCGv t0 = tcg_temp_new(); - gen_set_rm(ctx, a->rm); - gen_helper_fcvt_w_d(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + TCGv dest = dest_gpr(ctx, a->rd); + gen_set_rm(ctx, a->rm); + gen_helper_fcvt_w_d(dest, cpu_env, cpu_fpr[a->rs1]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -317,12 +323,11 @@ static bool trans_fcvt_wu_d(DisasContext *ctx, arg_fcvt_wu_d *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - TCGv t0 = tcg_temp_new(); - gen_set_rm(ctx, a->rm); - gen_helper_fcvt_wu_d(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + TCGv dest = dest_gpr(ctx, a->rd); + gen_set_rm(ctx, a->rm); + gen_helper_fcvt_wu_d(dest, cpu_env, cpu_fpr[a->rs1]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -331,12 +336,10 @@ static bool trans_fcvt_d_w(DisasContext *ctx, arg_fcvt_d_w *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - TCGv t0 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); + TCGv src = get_gpr(ctx, a->rs1, EXT_SIGN); gen_set_rm(ctx, a->rm); - gen_helper_fcvt_d_w(cpu_fpr[a->rd], cpu_env, t0); - tcg_temp_free(t0); + gen_helper_fcvt_d_w(cpu_fpr[a->rd], cpu_env, src); mark_fs_dirty(ctx); return true; @@ -347,12 +350,10 @@ static bool trans_fcvt_d_wu(DisasContext *ctx, arg_fcvt_d_wu *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - TCGv t0 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); + TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO); gen_set_rm(ctx, a->rm); - gen_helper_fcvt_d_wu(cpu_fpr[a->rd], cpu_env, t0); - tcg_temp_free(t0); + gen_helper_fcvt_d_wu(cpu_fpr[a->rd], cpu_env, src); mark_fs_dirty(ctx); return true; @@ -364,11 +365,11 @@ static bool trans_fcvt_l_d(DisasContext *ctx, arg_fcvt_l_d *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - TCGv t0 = tcg_temp_new(); + TCGv dest = dest_gpr(ctx, a->rd); + gen_set_rm(ctx, a->rm); - gen_helper_fcvt_l_d(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + gen_helper_fcvt_l_d(dest, cpu_env, cpu_fpr[a->rs1]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -378,11 +379,11 @@ static bool trans_fcvt_lu_d(DisasContext *ctx, arg_fcvt_lu_d *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - TCGv t0 = tcg_temp_new(); + TCGv dest = dest_gpr(ctx, a->rd); + gen_set_rm(ctx, a->rm); - gen_helper_fcvt_lu_d(t0, cpu_env, cpu_fpr[a->rs1]); - gen_set_gpr(ctx, a->rd, t0); - tcg_temp_free(t0); + gen_helper_fcvt_lu_d(dest, cpu_env, cpu_fpr[a->rs1]); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -406,12 +407,11 @@ static bool trans_fcvt_d_l(DisasContext *ctx, arg_fcvt_d_l *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - TCGv t0 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); + TCGv src = get_gpr(ctx, a->rs1, EXT_SIGN); gen_set_rm(ctx, a->rm); - gen_helper_fcvt_d_l(cpu_fpr[a->rd], cpu_env, t0); - tcg_temp_free(t0); + gen_helper_fcvt_d_l(cpu_fpr[a->rd], cpu_env, src); + mark_fs_dirty(ctx); return true; } @@ -422,12 +422,11 @@ static bool trans_fcvt_d_lu(DisasContext *ctx, arg_fcvt_d_lu *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - TCGv t0 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); + TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO); gen_set_rm(ctx, a->rm); - gen_helper_fcvt_d_lu(cpu_fpr[a->rd], cpu_env, t0); - tcg_temp_free(t0); + gen_helper_fcvt_d_lu(cpu_fpr[a->rd], cpu_env, src); + mark_fs_dirty(ctx); return true; } @@ -439,11 +438,7 @@ static bool trans_fmv_d_x(DisasContext *ctx, arg_fmv_d_x *a) REQUIRE_EXT(ctx, RVD); #ifdef TARGET_RISCV64 - TCGv t0 = tcg_temp_new(); - gen_get_gpr(ctx, t0, a->rs1); - - tcg_gen_mov_tl(cpu_fpr[a->rd], t0); - tcg_temp_free(t0); + tcg_gen_mov_tl(cpu_fpr[a->rd], get_gpr(ctx, a->rs1, EXT_NONE)); mark_fs_dirty(ctx); return true; #else -- cgit v1.1 From f33960df5b377ba4b6b673f5e239402395fab6e3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:28 -0700 Subject: target/riscv: Tidy trans_rvh.c.inc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Exit early if check_access fails. Split out do_hlv, do_hsv, do_hlvx subroutines. Use dest_gpr, get_gpr in the new subroutines. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210823195529.560295-24-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 1 + target/riscv/insn_trans/trans_rvh.c.inc | 266 +++++++------------------------- 2 files changed, 57 insertions(+), 210 deletions(-) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index f09f8d5..2cd921d 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -42,6 +42,7 @@ &j imm rd &r rd rs1 rs2 &r2 rd rs1 +&r2_s rs1 rs2 &s imm rs1 rs2 &u imm rd &shift shamt rs1 rd diff --git a/target/riscv/insn_trans/trans_rvh.c.inc b/target/riscv/insn_trans/trans_rvh.c.inc index 585eb1d..ecbf77f 100644 --- a/target/riscv/insn_trans/trans_rvh.c.inc +++ b/target/riscv/insn_trans/trans_rvh.c.inc @@ -17,281 +17,139 @@ */ #ifndef CONFIG_USER_ONLY -static void check_access(DisasContext *ctx) { +static bool check_access(DisasContext *ctx) +{ if (!ctx->hlsx) { if (ctx->virt_enabled) { generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); } else { generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); } + return false; } + return true; } #endif -static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a) +static bool do_hlv(DisasContext *ctx, arg_r2 *a, MemOp mop) { - REQUIRE_EXT(ctx, RVH); -#ifndef CONFIG_USER_ONLY - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - check_access(ctx); - - gen_get_gpr(ctx, t0, a->rs1); - - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_SB); - gen_set_gpr(ctx, a->rd, t1); - - tcg_temp_free(t0); - tcg_temp_free(t1); - return true; -#else +#ifdef CONFIG_USER_ONLY return false; +#else + if (check_access(ctx)) { + TCGv dest = dest_gpr(ctx, a->rd); + TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE); + int mem_idx = ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK; + tcg_gen_qemu_ld_tl(dest, addr, mem_idx, mop); + gen_set_gpr(ctx, a->rd, dest); + } + return true; #endif } -static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a) +static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a) { REQUIRE_EXT(ctx, RVH); -#ifndef CONFIG_USER_ONLY - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - check_access(ctx); - - gen_get_gpr(ctx, t0, a->rs1); - - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESW); - gen_set_gpr(ctx, a->rd, t1); + return do_hlv(ctx, a, MO_SB); +} - tcg_temp_free(t0); - tcg_temp_free(t1); - return true; -#else - return false; -#endif +static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a) +{ + REQUIRE_EXT(ctx, RVH); + return do_hlv(ctx, a, MO_TESW); } static bool trans_hlv_w(DisasContext *ctx, arg_hlv_w *a) { REQUIRE_EXT(ctx, RVH); -#ifndef CONFIG_USER_ONLY - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - check_access(ctx); - - gen_get_gpr(ctx, t0, a->rs1); - - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESL); - gen_set_gpr(ctx, a->rd, t1); - - tcg_temp_free(t0); - tcg_temp_free(t1); - return true; -#else - return false; -#endif + return do_hlv(ctx, a, MO_TESL); } static bool trans_hlv_bu(DisasContext *ctx, arg_hlv_bu *a) { REQUIRE_EXT(ctx, RVH); -#ifndef CONFIG_USER_ONLY - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - check_access(ctx); - - gen_get_gpr(ctx, t0, a->rs1); - - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_UB); - gen_set_gpr(ctx, a->rd, t1); - - tcg_temp_free(t0); - tcg_temp_free(t1); - return true; -#else - return false; -#endif + return do_hlv(ctx, a, MO_UB); } static bool trans_hlv_hu(DisasContext *ctx, arg_hlv_hu *a) { REQUIRE_EXT(ctx, RVH); -#ifndef CONFIG_USER_ONLY - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - check_access(ctx); - - gen_get_gpr(ctx, t0, a->rs1); - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUW); - gen_set_gpr(ctx, a->rd, t1); + return do_hlv(ctx, a, MO_TEUW); +} - tcg_temp_free(t0); - tcg_temp_free(t1); - return true; -#else +static bool do_hsv(DisasContext *ctx, arg_r2_s *a, MemOp mop) +{ +#ifdef CONFIG_USER_ONLY return false; +#else + if (check_access(ctx)) { + TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE); + TCGv data = get_gpr(ctx, a->rs2, EXT_NONE); + int mem_idx = ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK; + tcg_gen_qemu_st_tl(data, addr, mem_idx, mop); + } + return true; #endif } static bool trans_hsv_b(DisasContext *ctx, arg_hsv_b *a) { REQUIRE_EXT(ctx, RVH); -#ifndef CONFIG_USER_ONLY - TCGv t0 = tcg_temp_new(); - TCGv dat = tcg_temp_new(); - - check_access(ctx); - - gen_get_gpr(ctx, t0, a->rs1); - gen_get_gpr(ctx, dat, a->rs2); - - tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_SB); - - tcg_temp_free(t0); - tcg_temp_free(dat); - return true; -#else - return false; -#endif + return do_hsv(ctx, a, MO_SB); } static bool trans_hsv_h(DisasContext *ctx, arg_hsv_h *a) { REQUIRE_EXT(ctx, RVH); -#ifndef CONFIG_USER_ONLY - TCGv t0 = tcg_temp_new(); - TCGv dat = tcg_temp_new(); - - check_access(ctx); - - gen_get_gpr(ctx, t0, a->rs1); - gen_get_gpr(ctx, dat, a->rs2); - - tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESW); - - tcg_temp_free(t0); - tcg_temp_free(dat); - return true; -#else - return false; -#endif + return do_hsv(ctx, a, MO_TESW); } static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a) { REQUIRE_EXT(ctx, RVH); -#ifndef CONFIG_USER_ONLY - TCGv t0 = tcg_temp_new(); - TCGv dat = tcg_temp_new(); - - check_access(ctx); - - gen_get_gpr(ctx, t0, a->rs1); - gen_get_gpr(ctx, dat, a->rs2); - - tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESL); - - tcg_temp_free(t0); - tcg_temp_free(dat); - return true; -#else - return false; -#endif + return do_hsv(ctx, a, MO_TESL); } static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVH); - -#ifndef CONFIG_USER_ONLY - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - check_access(ctx); - - gen_get_gpr(ctx, t0, a->rs1); - - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUL); - gen_set_gpr(ctx, a->rd, t1); - - tcg_temp_free(t0); - tcg_temp_free(t1); - return true; -#else - return false; -#endif + return do_hlv(ctx, a, MO_TEUL); } static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVH); - -#ifndef CONFIG_USER_ONLY - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - check_access(ctx); - - gen_get_gpr(ctx, t0, a->rs1); - - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEQ); - gen_set_gpr(ctx, a->rd, t1); - - tcg_temp_free(t0); - tcg_temp_free(t1); - return true; -#else - return false; -#endif + return do_hlv(ctx, a, MO_TEQ); } static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVH); + return do_hsv(ctx, a, MO_TEQ); +} #ifndef CONFIG_USER_ONLY - TCGv t0 = tcg_temp_new(); - TCGv dat = tcg_temp_new(); - - check_access(ctx); - - gen_get_gpr(ctx, t0, a->rs1); - gen_get_gpr(ctx, dat, a->rs2); - - tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEQ); - - tcg_temp_free(t0); - tcg_temp_free(dat); +static bool do_hlvx(DisasContext *ctx, arg_r2 *a, + void (*func)(TCGv, TCGv_env, TCGv)) +{ + if (check_access(ctx)) { + TCGv dest = dest_gpr(ctx, a->rd); + TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE); + func(dest, cpu_env, addr); + gen_set_gpr(ctx, a->rd, dest); + } return true; -#else - return false; -#endif } +#endif static bool trans_hlvx_hu(DisasContext *ctx, arg_hlvx_hu *a) { REQUIRE_EXT(ctx, RVH); #ifndef CONFIG_USER_ONLY - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - check_access(ctx); - - gen_get_gpr(ctx, t0, a->rs1); - - gen_helper_hyp_hlvx_hu(t1, cpu_env, t0); - gen_set_gpr(ctx, a->rd, t1); - - tcg_temp_free(t0); - tcg_temp_free(t1); - return true; + return do_hlvx(ctx, a, gen_helper_hyp_hlvx_hu); #else return false; #endif @@ -301,19 +159,7 @@ static bool trans_hlvx_wu(DisasContext *ctx, arg_hlvx_wu *a) { REQUIRE_EXT(ctx, RVH); #ifndef CONFIG_USER_ONLY - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - check_access(ctx); - - gen_get_gpr(ctx, t0, a->rs1); - - gen_helper_hyp_hlvx_wu(t1, cpu_env, t0); - gen_set_gpr(ctx, a->rd, t1); - - tcg_temp_free(t0); - tcg_temp_free(t1); - return true; + return do_hlvx(ctx, a, gen_helper_hyp_hlvx_wu); #else return false; #endif -- cgit v1.1 From 8e034ae44dba6291beb07f7f2a932c1e5ab83e98 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Aug 2021 12:55:29 -0700 Subject: target/riscv: Use {get,dest}_gpr for RVV Remove gen_get_gpr, as the function becomes unused. Signed-off-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210823195529.560295-25-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 74 ++++++++++----------------------- target/riscv/translate.c | 13 +++--- 2 files changed, 26 insertions(+), 61 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index de580c4..fa45193 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -27,27 +27,22 @@ static bool trans_vsetvl(DisasContext *ctx, arg_vsetvl *a) return false; } - s2 = tcg_temp_new(); - dst = tcg_temp_new(); + s2 = get_gpr(ctx, a->rs2, EXT_ZERO); + dst = dest_gpr(ctx, a->rd); /* Using x0 as the rs1 register specifier, encodes an infinite AVL */ if (a->rs1 == 0) { /* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */ s1 = tcg_constant_tl(RV_VLEN_MAX); } else { - s1 = tcg_temp_new(); - gen_get_gpr(ctx, s1, a->rs1); + s1 = get_gpr(ctx, a->rs1, EXT_ZERO); } - gen_get_gpr(ctx, s2, a->rs2); gen_helper_vsetvl(dst, cpu_env, s1, s2); gen_set_gpr(ctx, a->rd, dst); + tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); lookup_and_goto_ptr(ctx); ctx->base.is_jmp = DISAS_NORETURN; - - tcg_temp_free(s1); - tcg_temp_free(s2); - tcg_temp_free(dst); return true; } @@ -60,23 +55,20 @@ static bool trans_vsetvli(DisasContext *ctx, arg_vsetvli *a) } s2 = tcg_constant_tl(a->zimm); - dst = tcg_temp_new(); + dst = dest_gpr(ctx, a->rd); /* Using x0 as the rs1 register specifier, encodes an infinite AVL */ if (a->rs1 == 0) { /* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */ s1 = tcg_constant_tl(RV_VLEN_MAX); } else { - s1 = tcg_temp_new(); - gen_get_gpr(ctx, s1, a->rs1); + s1 = get_gpr(ctx, a->rs1, EXT_ZERO); } gen_helper_vsetvl(dst, cpu_env, s1, s2); gen_set_gpr(ctx, a->rd, dst); + gen_goto_tb(ctx, 0, ctx->pc_succ_insn); ctx->base.is_jmp = DISAS_NORETURN; - - tcg_temp_free(s1); - tcg_temp_free(dst); return true; } @@ -173,7 +165,7 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data, dest = tcg_temp_new_ptr(); mask = tcg_temp_new_ptr(); - base = tcg_temp_new(); + base = get_gpr(s, rs1, EXT_NONE); /* * As simd_desc supports at most 256 bytes, and in this implementation, @@ -184,7 +176,6 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data, */ desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); - gen_get_gpr(s, base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); @@ -192,7 +183,6 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data, tcg_temp_free_ptr(dest); tcg_temp_free_ptr(mask); - tcg_temp_free(base); gen_set_label(over); return true; } @@ -330,12 +320,10 @@ static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, uint32_t rs2, dest = tcg_temp_new_ptr(); mask = tcg_temp_new_ptr(); - base = tcg_temp_new(); - stride = tcg_temp_new(); + base = get_gpr(s, rs1, EXT_NONE); + stride = get_gpr(s, rs2, EXT_NONE); desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); - gen_get_gpr(s, base, rs1); - gen_get_gpr(s, stride, rs2); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); @@ -343,8 +331,6 @@ static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, uint32_t rs2, tcg_temp_free_ptr(dest); tcg_temp_free_ptr(mask); - tcg_temp_free(base); - tcg_temp_free(stride); gen_set_label(over); return true; } @@ -458,10 +444,9 @@ static bool ldst_index_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, dest = tcg_temp_new_ptr(); mask = tcg_temp_new_ptr(); index = tcg_temp_new_ptr(); - base = tcg_temp_new(); + base = get_gpr(s, rs1, EXT_NONE); desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); - gen_get_gpr(s, base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(index, cpu_env, vreg_ofs(s, vs2)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); @@ -471,7 +456,6 @@ static bool ldst_index_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, tcg_temp_free_ptr(dest); tcg_temp_free_ptr(mask); tcg_temp_free_ptr(index); - tcg_temp_free(base); gen_set_label(over); return true; } @@ -589,10 +573,9 @@ static bool ldff_trans(uint32_t vd, uint32_t rs1, uint32_t data, dest = tcg_temp_new_ptr(); mask = tcg_temp_new_ptr(); - base = tcg_temp_new(); + base = get_gpr(s, rs1, EXT_NONE); desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); - gen_get_gpr(s, base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); @@ -600,7 +583,6 @@ static bool ldff_trans(uint32_t vd, uint32_t rs1, uint32_t data, tcg_temp_free_ptr(dest); tcg_temp_free_ptr(mask); - tcg_temp_free(base); gen_set_label(over); return true; } @@ -665,10 +647,9 @@ static bool amo_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, dest = tcg_temp_new_ptr(); mask = tcg_temp_new_ptr(); index = tcg_temp_new_ptr(); - base = tcg_temp_new(); + base = get_gpr(s, rs1, EXT_NONE); desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); - gen_get_gpr(s, base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(index, cpu_env, vreg_ofs(s, vs2)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); @@ -678,7 +659,6 @@ static bool amo_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, tcg_temp_free_ptr(dest); tcg_temp_free_ptr(mask); tcg_temp_free_ptr(index); - tcg_temp_free(base); gen_set_label(over); return true; } @@ -862,8 +842,7 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm, dest = tcg_temp_new_ptr(); mask = tcg_temp_new_ptr(); src2 = tcg_temp_new_ptr(); - src1 = tcg_temp_new(); - gen_get_gpr(s, src1, rs1); + src1 = get_gpr(s, rs1, EXT_NONE); data = FIELD_DP32(data, VDATA, MLEN, s->mlen); data = FIELD_DP32(data, VDATA, VM, vm); @@ -879,7 +858,6 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm, tcg_temp_free_ptr(dest); tcg_temp_free_ptr(mask); tcg_temp_free_ptr(src2); - tcg_temp_free(src1); gen_set_label(over); return true; } @@ -905,15 +883,12 @@ do_opivx_gvec(DisasContext *s, arg_rmrr *a, GVecGen2sFn *gvec_fn, if (a->vm && s->vl_eq_vlmax) { TCGv_i64 src1 = tcg_temp_new_i64(); - TCGv tmp = tcg_temp_new(); - gen_get_gpr(s, tmp, a->rs1); - tcg_gen_ext_tl_i64(src1, tmp); + tcg_gen_ext_tl_i64(src1, get_gpr(s, a->rs1, EXT_SIGN)); gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), src1, MAXSZ(s), MAXSZ(s)); tcg_temp_free_i64(src1); - tcg_temp_free(tmp); return true; } return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s); @@ -1398,16 +1373,13 @@ do_opivx_gvec_shift(DisasContext *s, arg_rmrr *a, GVecGen2sFn32 *gvec_fn, if (a->vm && s->vl_eq_vlmax) { TCGv_i32 src1 = tcg_temp_new_i32(); - TCGv tmp = tcg_temp_new(); - gen_get_gpr(s, tmp, a->rs1); - tcg_gen_trunc_tl_i32(src1, tmp); + tcg_gen_trunc_tl_i32(src1, get_gpr(s, a->rs1, EXT_NONE)); tcg_gen_extract_i32(src1, src1, 0, s->sew + 3); gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), src1, MAXSZ(s), MAXSZ(s)); tcg_temp_free_i32(src1); - tcg_temp_free(tmp); return true; } return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s); @@ -1665,8 +1637,7 @@ static bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x *a) TCGLabel *over = gen_new_label(); tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); - s1 = tcg_temp_new(); - gen_get_gpr(s, s1, a->rs1); + 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), @@ -1690,7 +1661,6 @@ static bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x *a) tcg_temp_free_i64(s1_i64); } - tcg_temp_free(s1); gen_set_label(over); return true; } @@ -2412,7 +2382,7 @@ static bool trans_vmpopc_m(DisasContext *s, arg_rmr *a) mask = tcg_temp_new_ptr(); src2 = tcg_temp_new_ptr(); - dst = tcg_temp_new(); + dst = dest_gpr(s, a->rd); desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2)); @@ -2423,7 +2393,6 @@ static bool trans_vmpopc_m(DisasContext *s, arg_rmr *a) tcg_temp_free_ptr(mask); tcg_temp_free_ptr(src2); - tcg_temp_free(dst); return true; } return false; @@ -2443,7 +2412,7 @@ static bool trans_vmfirst_m(DisasContext *s, arg_rmr *a) mask = tcg_temp_new_ptr(); src2 = tcg_temp_new_ptr(); - dst = tcg_temp_new(); + dst = dest_gpr(s, a->rd); desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2)); @@ -2454,7 +2423,6 @@ static bool trans_vmfirst_m(DisasContext *s, arg_rmr *a) tcg_temp_free_ptr(mask); tcg_temp_free_ptr(src2); - tcg_temp_free(dst); return true; } return false; @@ -2638,7 +2606,7 @@ static void vec_element_loadi(DisasContext *s, TCGv_i64 dest, static bool trans_vext_x_v(DisasContext *s, arg_r *a) { TCGv_i64 tmp = tcg_temp_new_i64(); - TCGv dest = tcg_temp_new(); + TCGv dest = dest_gpr(s, a->rd); if (a->rs1 == 0) { /* Special case vmv.x.s rd, vs2. */ @@ -2648,10 +2616,10 @@ static bool trans_vext_x_v(DisasContext *s, arg_r *a) int vlmax = s->vlen >> (3 + s->sew); vec_element_loadx(s, tmp, a->rs2, cpu_gpr[a->rs1], vlmax); } + tcg_gen_trunc_i64_tl(dest, tmp); gen_set_gpr(s, a->rd, dest); - tcg_temp_free(dest); tcg_temp_free_i64(tmp); return true; } diff --git a/target/riscv/translate.c b/target/riscv/translate.c index e44254e..e356fc6 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -232,11 +232,6 @@ static TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend ext) g_assert_not_reached(); } -static void gen_get_gpr(DisasContext *ctx, TCGv t, int reg_num) -{ - tcg_gen_mov_tl(t, get_gpr(ctx, reg_num, EXT_NONE)); -} - static TCGv dest_gpr(DisasContext *ctx, int reg_num) { if (reg_num == 0 || ctx->w) { @@ -637,9 +632,11 @@ void riscv_translate_init(void) { int i; - /* cpu_gpr[0] is a placeholder for the zero register. Do not use it. */ - /* Use the gen_set_gpr and gen_get_gpr helper functions when accessing */ - /* registers, unless you specifically block reads/writes to reg 0 */ + /* + * cpu_gpr[0] is a placeholder for the zero register. Do not use it. + * Use the gen_set_gpr and get_gpr helper functions when accessing regs, + * unless you specifically block reads/writes to reg 0. + */ cpu_gpr[0] = NULL; for (i = 1; i < 32; i++) { -- cgit v1.1