target-arm queue:
* target/arm: Correct ID_AA64ISAR1_EL1 value for neoverse-v1 * target/arm: More conversions to decodetree of A64 SIMD insns * hw/char/stm32l4x5_usart.c: Enable USART ACK bit response * tests: update aarch64/sbsa-ref tests * kvm: minor Coverity nit fixes * docs/devel: Remove nested-papr.txt -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmbsIloZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3k96EACgUaTSEX1BNee0Xsk8wIHb KebGryNymj7LPpWdRxiyQYmZbjfelZPJW7F2tr3iGfiphz+N5TIdRDQlPrRePNg4 5Ure0ShRgn+RlkjFe8r9yjrr3HEAXLnVb5fgzPqGEQ+UXWRVzr72+q+wrGFVuXtn zfqxpc6F0TCxeyH88X6mpKkTeEjfuE++TIf885VVX6nB8qkkDUifRLjdrDcJoxp3 BRrE0Ntob2W0NAHm/QTbATLDErsYXIzm6pX2hWy3DNEQrVHw2rJ1FAzsjt2J/8ZU PC7hwmkPBsrnq5wcpBtOwloHzrIYuwUBI7ABPGctCPziCSw7N55vkgUmGWZ+nYHc DwYGu3H84su0hBi/E9gxl8z/ATBvuAIVa1RLHvbYiwdd088DqxdBe1YLLRaZeKzP oldQBzVegaN1n5n8tHO43b/38V7uknu3fDXGw/OrsO5DouDAj9NoRil1caRx4ZYd dr4IiWKzmlW8wpWgoBnrRbycuNsi6b9HblOX1umjwubCGO+GFesBRAInUeg9gbuv xolfYOScUE/nkTaqulAiPGqGZV8P0fqVMbXmXuowm7iIdw3JihEUm+mU18CTPFBd P/6SH47lXTaQA0JJQmD4LKraZQFYzm5rlSvW/15/mnzutZXMUlWzvxK/E5fX3vhL VUguR6XO8Cjb0cQJWohB1w== =JklH -----END PGP SIGNATURE----- Merge tag 'pull-target-arm-20240919' of https://git.linaro.org/people/pmaydell/qemu-arm into staging target-arm queue: * target/arm: Correct ID_AA64ISAR1_EL1 value for neoverse-v1 * target/arm: More conversions to decodetree of A64 SIMD insns * hw/char/stm32l4x5_usart.c: Enable USART ACK bit response * tests: update aarch64/sbsa-ref tests * kvm: minor Coverity nit fixes * docs/devel: Remove nested-papr.txt # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmbsIloZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3k96EACgUaTSEX1BNee0Xsk8wIHb # KebGryNymj7LPpWdRxiyQYmZbjfelZPJW7F2tr3iGfiphz+N5TIdRDQlPrRePNg4 # 5Ure0ShRgn+RlkjFe8r9yjrr3HEAXLnVb5fgzPqGEQ+UXWRVzr72+q+wrGFVuXtn # zfqxpc6F0TCxeyH88X6mpKkTeEjfuE++TIf885VVX6nB8qkkDUifRLjdrDcJoxp3 # BRrE0Ntob2W0NAHm/QTbATLDErsYXIzm6pX2hWy3DNEQrVHw2rJ1FAzsjt2J/8ZU # PC7hwmkPBsrnq5wcpBtOwloHzrIYuwUBI7ABPGctCPziCSw7N55vkgUmGWZ+nYHc # DwYGu3H84su0hBi/E9gxl8z/ATBvuAIVa1RLHvbYiwdd088DqxdBe1YLLRaZeKzP # oldQBzVegaN1n5n8tHO43b/38V7uknu3fDXGw/OrsO5DouDAj9NoRil1caRx4ZYd # dr4IiWKzmlW8wpWgoBnrRbycuNsi6b9HblOX1umjwubCGO+GFesBRAInUeg9gbuv # xolfYOScUE/nkTaqulAiPGqGZV8P0fqVMbXmXuowm7iIdw3JihEUm+mU18CTPFBd # P/6SH47lXTaQA0JJQmD4LKraZQFYzm5rlSvW/15/mnzutZXMUlWzvxK/E5fX3vhL # VUguR6XO8Cjb0cQJWohB1w== # =JklH # -----END PGP SIGNATURE----- # gpg: Signature made Thu 19 Sep 2024 14:08:42 BST # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # gpg: aka "Peter Maydell <peter@archaic.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * tag 'pull-target-arm-20240919' of https://git.linaro.org/people/pmaydell/qemu-arm: (38 commits) docs/devel: Remove nested-papr.txt target/arm: Correct ID_AA64ISAR1_EL1 value for neoverse-v1 kvm: Remove unreachable code in kvm_dirty_ring_reaper_thread() kvm: Make 'mmap_size' be 'int' in kvm_init_vcpu(), do_kvm_destroy_vcpu() tests: drop OpenBSD tests for aarch64/sbsa-ref tests: expand timeout information for aarch64/sbsa-ref tests: add FreeBSD tests for aarch64/sbsa-ref tests: use default cpu for aarch64/sbsa-ref hw/char/stm32l4x5_usart.c: Enable USART ACK bit response target/arm: Convert scalar [US]QSHRN, [US]QRSHRN, SQSHRUN to decodetree target/arm: Convert vector [US]QSHRN, [US]QRSHRN, SQSHRUN to decodetree target/arm: Convert SQSHL, UQSHL, SQSHLU (immediate) to decodetree target/arm: Widen NeonGenNarrowEnvFn return to 64 bits target/arm: Convert VQSHL, VQSHLU to gvec target/arm: Convert handle_scalar_simd_shli to decodetree target/arm: Convert handle_scalar_simd_shri to decodetree target/arm: Convert SHRN, RSHRN to decodetree target/arm: Split out subroutines of handle_shri_with_rndacc target/arm: Push tcg_rnd into handle_shri_with_rndacc target/arm: Convert SSHLL, USHLL to decodetree ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
01dc65a3bc
@ -414,7 +414,7 @@ int kvm_create_and_park_vcpu(CPUState *cpu)
|
||||
static int do_kvm_destroy_vcpu(CPUState *cpu)
|
||||
{
|
||||
KVMState *s = kvm_state;
|
||||
long mmap_size;
|
||||
int mmap_size;
|
||||
int ret = 0;
|
||||
|
||||
trace_kvm_destroy_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu));
|
||||
@ -459,7 +459,7 @@ void kvm_destroy_vcpu(CPUState *cpu)
|
||||
int kvm_init_vcpu(CPUState *cpu, Error **errp)
|
||||
{
|
||||
KVMState *s = kvm_state;
|
||||
long mmap_size;
|
||||
int mmap_size;
|
||||
int ret;
|
||||
|
||||
trace_kvm_init_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu));
|
||||
@ -1525,11 +1525,7 @@ static void *kvm_dirty_ring_reaper_thread(void *data)
|
||||
r->reaper_iteration++;
|
||||
}
|
||||
|
||||
trace_kvm_dirty_ring_reaper("exit");
|
||||
|
||||
rcu_unregister_thread();
|
||||
|
||||
return NULL;
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static void kvm_dirty_ring_reaper_init(KVMState *s)
|
||||
|
@ -1,119 +0,0 @@
|
||||
Nested PAPR API (aka KVM on PowerVM)
|
||||
====================================
|
||||
|
||||
This API aims at providing support to enable nested virtualization with
|
||||
KVM on PowerVM. While the existing support for nested KVM on PowerNV was
|
||||
introduced with cap-nested-hv option, however, with a slight design change,
|
||||
to enable this on papr/pseries, a new cap-nested-papr option is added. eg:
|
||||
|
||||
qemu-system-ppc64 -cpu POWER10 -machine pseries,cap-nested-papr=true ...
|
||||
|
||||
Work by:
|
||||
Michael Neuling <mikey@neuling.org>
|
||||
Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Jordan Niethe <jniethe5@gmail.com>
|
||||
Harsh Prateek Bora <harshpb@linux.ibm.com>
|
||||
Shivaprasad G Bhat <sbhat@linux.ibm.com>
|
||||
Kautuk Consul <kconsul@linux.vnet.ibm.com>
|
||||
|
||||
Below taken from the kernel documentation:
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This document explains how a guest operating system can act as a
|
||||
hypervisor and run nested guests through the use of hypercalls, if the
|
||||
hypervisor has implemented them. The terms L0, L1, and L2 are used to
|
||||
refer to different software entities. L0 is the hypervisor mode entity
|
||||
that would normally be called the "host" or "hypervisor". L1 is a
|
||||
guest virtual machine that is directly run under L0 and is initiated
|
||||
and controlled by L0. L2 is a guest virtual machine that is initiated
|
||||
and controlled by L1 acting as a hypervisor. A significant design change
|
||||
wrt existing API is that now the entire L2 state is maintained within L0.
|
||||
|
||||
Existing Nested-HV API
|
||||
======================
|
||||
|
||||
Linux/KVM has had support for Nesting as an L0 or L1 since 2018
|
||||
|
||||
The L0 code was added::
|
||||
|
||||
commit 8e3f5fc1045dc49fd175b978c5457f5f51e7a2ce
|
||||
Author: Paul Mackerras <paulus@ozlabs.org>
|
||||
Date: Mon Oct 8 16:31:03 2018 +1100
|
||||
KVM: PPC: Book3S HV: Framework and hcall stubs for nested virtualization
|
||||
|
||||
The L1 code was added::
|
||||
|
||||
commit 360cae313702cdd0b90f82c261a8302fecef030a
|
||||
Author: Paul Mackerras <paulus@ozlabs.org>
|
||||
Date: Mon Oct 8 16:31:04 2018 +1100
|
||||
KVM: PPC: Book3S HV: Nested guest entry via hypercall
|
||||
|
||||
This API works primarily using a signal hcall h_enter_nested(). This
|
||||
call made by the L1 to tell the L0 to start an L2 vCPU with the given
|
||||
state. The L0 then starts this L2 and runs until an L2 exit condition
|
||||
is reached. Once the L2 exits, the state of the L2 is given back to
|
||||
the L1 by the L0. The full L2 vCPU state is always transferred from
|
||||
and to L1 when the L2 is run. The L0 doesn't keep any state on the L2
|
||||
vCPU (except in the short sequence in the L0 on L1 -> L2 entry and L2
|
||||
-> L1 exit).
|
||||
|
||||
The only state kept by the L0 is the partition table. The L1 registers
|
||||
it's partition table using the h_set_partition_table() hcall. All
|
||||
other state held by the L0 about the L2s is cached state (such as
|
||||
shadow page tables).
|
||||
|
||||
The L1 may run any L2 or vCPU without first informing the L0. It
|
||||
simply starts the vCPU using h_enter_nested(). The creation of L2s and
|
||||
vCPUs is done implicitly whenever h_enter_nested() is called.
|
||||
|
||||
In this document, we call this existing API the v1 API.
|
||||
|
||||
New PAPR API
|
||||
===============
|
||||
|
||||
The new PAPR API changes from the v1 API such that the creating L2 and
|
||||
associated vCPUs is explicit. In this document, we call this the v2
|
||||
API.
|
||||
|
||||
h_enter_nested() is replaced with H_GUEST_VCPU_RUN(). Before this can
|
||||
be called the L1 must explicitly create the L2 using h_guest_create()
|
||||
and any associated vCPUs() created with h_guest_create_vCPU(). Getting
|
||||
and setting vCPU state can also be performed using h_guest_{g|s}et
|
||||
hcall.
|
||||
|
||||
The basic execution flow is for an L1 to create an L2, run it, and
|
||||
delete it is:
|
||||
|
||||
- L1 and L0 negotiate capabilities with H_GUEST_{G,S}ET_CAPABILITIES()
|
||||
(normally at L1 boot time).
|
||||
|
||||
- L1 requests the L0 to create an L2 with H_GUEST_CREATE() and receives a token
|
||||
|
||||
- L1 requests the L0 to create an L2 vCPU with H_GUEST_CREATE_VCPU()
|
||||
|
||||
- L1 and L0 communicate the vCPU state using the H_GUEST_{G,S}ET() hcall
|
||||
|
||||
- L1 requests the L0 to run the vCPU using H_GUEST_RUN_VCPU() hcall
|
||||
|
||||
- L1 deletes L2 with H_GUEST_DELETE()
|
||||
|
||||
For more details, please refer:
|
||||
|
||||
[1] Linux Kernel documentation (upstream documentation commit):
|
||||
|
||||
commit 476652297f94a2e5e5ef29e734b0da37ade94110
|
||||
Author: Michael Neuling <mikey@neuling.org>
|
||||
Date: Thu Sep 14 13:06:00 2023 +1000
|
||||
|
||||
docs: powerpc: Document nested KVM on POWER
|
||||
|
||||
Document support for nested KVM on POWER using the existing API as well
|
||||
as the new PAPR API. This includes the new HCALL interface and how it
|
||||
used by KVM.
|
||||
|
||||
Signed-off-by: Michael Neuling <mikey@neuling.org>
|
||||
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
|
||||
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
|
||||
Link: https://msgid.link/20230914030600.16993-12-jniethe5@gmail.com
|
@ -154,6 +154,21 @@ REG32(RDR, 0x24)
|
||||
REG32(TDR, 0x28)
|
||||
FIELD(TDR, TDR, 0, 9)
|
||||
|
||||
static void stm32l4x5_update_isr(Stm32l4x5UsartBaseState *s)
|
||||
{
|
||||
if (s->cr1 & R_CR1_TE_MASK) {
|
||||
s->isr |= R_ISR_TEACK_MASK;
|
||||
} else {
|
||||
s->isr &= ~R_ISR_TEACK_MASK;
|
||||
}
|
||||
|
||||
if (s->cr1 & R_CR1_RE_MASK) {
|
||||
s->isr |= R_ISR_REACK_MASK;
|
||||
} else {
|
||||
s->isr &= ~R_ISR_REACK_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
static void stm32l4x5_update_irq(Stm32l4x5UsartBaseState *s)
|
||||
{
|
||||
if (((s->isr & R_ISR_WUF_MASK) && (s->cr3 & R_CR3_WUFIE_MASK)) ||
|
||||
@ -456,6 +471,7 @@ static void stm32l4x5_usart_base_write(void *opaque, hwaddr addr,
|
||||
case A_CR1:
|
||||
s->cr1 = value;
|
||||
stm32l4x5_update_params(s);
|
||||
stm32l4x5_update_isr(s);
|
||||
stm32l4x5_update_irq(s);
|
||||
return;
|
||||
case A_CR2:
|
||||
|
@ -324,6 +324,18 @@ DEF_HELPER_FLAGS_5(neon_uqrshl_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32
|
||||
DEF_HELPER_FLAGS_5(neon_uqrshl_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_5(neon_uqrshl_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_5(neon_uqrshl_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(neon_sqshli_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(neon_sqshli_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(neon_sqshli_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(neon_sqshli_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(neon_uqshli_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(neon_uqshli_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(neon_uqshli_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(neon_uqshli_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(neon_sqshlui_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(neon_sqshlui_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(neon_sqshlui_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(neon_sqshlui_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_srshl_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_srshl_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
@ -363,17 +375,17 @@ DEF_HELPER_3(neon_qrdmulh_s32, i32, env, i32, i32)
|
||||
DEF_HELPER_4(neon_qrdmlah_s32, i32, env, s32, s32, s32)
|
||||
DEF_HELPER_4(neon_qrdmlsh_s32, i32, env, s32, s32, s32)
|
||||
|
||||
DEF_HELPER_1(neon_narrow_u8, i32, i64)
|
||||
DEF_HELPER_1(neon_narrow_u16, i32, i64)
|
||||
DEF_HELPER_2(neon_unarrow_sat8, i32, env, i64)
|
||||
DEF_HELPER_2(neon_narrow_sat_u8, i32, env, i64)
|
||||
DEF_HELPER_2(neon_narrow_sat_s8, i32, env, i64)
|
||||
DEF_HELPER_2(neon_unarrow_sat16, i32, env, i64)
|
||||
DEF_HELPER_2(neon_narrow_sat_u16, i32, env, i64)
|
||||
DEF_HELPER_2(neon_narrow_sat_s16, i32, env, i64)
|
||||
DEF_HELPER_2(neon_unarrow_sat32, i32, env, i64)
|
||||
DEF_HELPER_2(neon_narrow_sat_u32, i32, env, i64)
|
||||
DEF_HELPER_2(neon_narrow_sat_s32, i32, env, i64)
|
||||
DEF_HELPER_1(neon_narrow_u8, i64, i64)
|
||||
DEF_HELPER_1(neon_narrow_u16, i64, i64)
|
||||
DEF_HELPER_2(neon_unarrow_sat8, i64, env, i64)
|
||||
DEF_HELPER_2(neon_narrow_sat_u8, i64, env, i64)
|
||||
DEF_HELPER_2(neon_narrow_sat_s8, i64, env, i64)
|
||||
DEF_HELPER_2(neon_unarrow_sat16, i64, env, i64)
|
||||
DEF_HELPER_2(neon_narrow_sat_u16, i64, env, i64)
|
||||
DEF_HELPER_2(neon_narrow_sat_s16, i64, env, i64)
|
||||
DEF_HELPER_2(neon_unarrow_sat32, i64, env, i64)
|
||||
DEF_HELPER_2(neon_narrow_sat_u32, i64, env, i64)
|
||||
DEF_HELPER_2(neon_narrow_sat_s32, i64, env, i64)
|
||||
DEF_HELPER_1(neon_narrow_high_u8, i32, i64)
|
||||
DEF_HELPER_1(neon_narrow_high_u16, i32, i64)
|
||||
DEF_HELPER_1(neon_narrow_round_high_u8, i32, i64)
|
||||
|
@ -30,10 +30,12 @@
|
||||
&rri_sf rd rn imm sf
|
||||
&i imm
|
||||
&rr_e rd rn esz
|
||||
&rri_e rd rn imm esz
|
||||
&rrr_e rd rn rm esz
|
||||
&rrx_e rd rn rm idx esz
|
||||
&rrrr_e rd rn rm ra esz
|
||||
&qrr_e q rd rn esz
|
||||
&qrri_e q rd rn imm esz
|
||||
&qrrr_e q rd rn rm esz
|
||||
&qrrx_e q rd rn rm idx esz
|
||||
&qrrrr_e q rd rn rm ra esz
|
||||
@ -54,11 +56,15 @@
|
||||
@rrx_d ........ .. . rm:5 .... idx:1 . rn:5 rd:5 &rrx_e esz=3
|
||||
|
||||
@rr_q1e0 ........ ........ ...... rn:5 rd:5 &qrr_e q=1 esz=0
|
||||
@rr_q1e2 ........ ........ ...... rn:5 rd:5 &qrr_e q=1 esz=2
|
||||
@r2r_q1e0 ........ ........ ...... rm:5 rd:5 &qrrr_e rn=%rd q=1 esz=0
|
||||
@rrr_q1e0 ........ ... rm:5 ...... rn:5 rd:5 &qrrr_e q=1 esz=0
|
||||
@rrr_q1e3 ........ ... rm:5 ...... rn:5 rd:5 &qrrr_e q=1 esz=3
|
||||
@rrrr_q1e3 ........ ... rm:5 . ra:5 rn:5 rd:5 &qrrrr_e q=1 esz=3
|
||||
|
||||
@qrr_h . q:1 ...... .. ...... ...... rn:5 rd:5 &qrr_e esz=1
|
||||
@qrr_e . q:1 ...... esz:2 ...... ...... rn:5 rd:5 &qrr_e
|
||||
|
||||
@qrrr_b . q:1 ...... ... rm:5 ...... rn:5 rd:5 &qrrr_e esz=0
|
||||
@qrrr_h . q:1 ...... ... rm:5 ...... rn:5 rd:5 &qrrr_e esz=1
|
||||
@qrrr_s . q:1 ...... ... rm:5 ...... rn:5 rd:5 &qrrr_e esz=2
|
||||
@ -1136,3 +1142,254 @@ FMADD 0001 1111 .. 0 ..... 0 ..... ..... ..... @rrrr_hsd
|
||||
FMSUB 0001 1111 .. 0 ..... 1 ..... ..... ..... @rrrr_hsd
|
||||
FNMADD 0001 1111 .. 1 ..... 0 ..... ..... ..... @rrrr_hsd
|
||||
FNMSUB 0001 1111 .. 1 ..... 1 ..... ..... ..... @rrrr_hsd
|
||||
|
||||
# Advanced SIMD Extract
|
||||
|
||||
EXT_d 0010 1110 00 0 rm:5 00 imm:3 0 rn:5 rd:5
|
||||
EXT_q 0110 1110 00 0 rm:5 0 imm:4 0 rn:5 rd:5
|
||||
|
||||
# Advanced SIMD Table Lookup
|
||||
|
||||
TBL_TBX 0 q:1 00 1110 000 rm:5 0 len:2 tbx:1 00 rn:5 rd:5
|
||||
|
||||
# Advanced SIMD Permute
|
||||
|
||||
UZP1 0.00 1110 .. 0 ..... 0 001 10 ..... ..... @qrrr_e
|
||||
UZP2 0.00 1110 .. 0 ..... 0 101 10 ..... ..... @qrrr_e
|
||||
TRN1 0.00 1110 .. 0 ..... 0 010 10 ..... ..... @qrrr_e
|
||||
TRN2 0.00 1110 .. 0 ..... 0 110 10 ..... ..... @qrrr_e
|
||||
ZIP1 0.00 1110 .. 0 ..... 0 011 10 ..... ..... @qrrr_e
|
||||
ZIP2 0.00 1110 .. 0 ..... 0 111 10 ..... ..... @qrrr_e
|
||||
|
||||
# Advanced SIMD Across Lanes
|
||||
|
||||
ADDV 0.00 1110 .. 11000 11011 10 ..... ..... @qrr_e
|
||||
SADDLV 0.00 1110 .. 11000 00011 10 ..... ..... @qrr_e
|
||||
UADDLV 0.10 1110 .. 11000 00011 10 ..... ..... @qrr_e
|
||||
SMAXV 0.00 1110 .. 11000 01010 10 ..... ..... @qrr_e
|
||||
UMAXV 0.10 1110 .. 11000 01010 10 ..... ..... @qrr_e
|
||||
SMINV 0.00 1110 .. 11000 11010 10 ..... ..... @qrr_e
|
||||
UMINV 0.10 1110 .. 11000 11010 10 ..... ..... @qrr_e
|
||||
|
||||
FMAXNMV_h 0.00 1110 00 11000 01100 10 ..... ..... @qrr_h
|
||||
FMAXNMV_s 0110 1110 00 11000 01100 10 ..... ..... @rr_q1e2
|
||||
|
||||
FMINNMV_h 0.00 1110 10 11000 01100 10 ..... ..... @qrr_h
|
||||
FMINNMV_s 0110 1110 10 11000 01100 10 ..... ..... @rr_q1e2
|
||||
|
||||
FMAXV_h 0.00 1110 00 11000 01111 10 ..... ..... @qrr_h
|
||||
FMAXV_s 0110 1110 00 11000 01111 10 ..... ..... @rr_q1e2
|
||||
|
||||
FMINV_h 0.00 1110 10 11000 01111 10 ..... ..... @qrr_h
|
||||
FMINV_s 0110 1110 10 11000 01111 10 ..... ..... @rr_q1e2
|
||||
|
||||
# Floating-point Immediate
|
||||
|
||||
FMOVI_s 0001 1110 .. 1 imm:8 100 00000 rd:5 esz=%esz_hsd
|
||||
|
||||
# Advanced SIMD Modified Immediate / Shift by Immediate
|
||||
|
||||
%abcdefgh 16:3 5:5
|
||||
|
||||
# Right shifts are encoded as N - shift, where N is the element size in bits.
|
||||
%neon_rshift_i6 16:6 !function=rsub_64
|
||||
%neon_rshift_i5 16:5 !function=rsub_32
|
||||
%neon_rshift_i4 16:4 !function=rsub_16
|
||||
%neon_rshift_i3 16:3 !function=rsub_8
|
||||
|
||||
@q_shri_b . q:1 .. ..... 0001 ... ..... . rn:5 rd:5 \
|
||||
&qrri_e esz=0 imm=%neon_rshift_i3
|
||||
@q_shri_h . q:1 .. ..... 001 .... ..... . rn:5 rd:5 \
|
||||
&qrri_e esz=1 imm=%neon_rshift_i4
|
||||
@q_shri_s . q:1 .. ..... 01 ..... ..... . rn:5 rd:5 \
|
||||
&qrri_e esz=2 imm=%neon_rshift_i5
|
||||
@q_shri_d . 1 .. ..... 1 ...... ..... . rn:5 rd:5 \
|
||||
&qrri_e esz=3 imm=%neon_rshift_i6 q=1
|
||||
|
||||
@q_shli_b . q:1 .. ..... 0001 imm:3 ..... . rn:5 rd:5 &qrri_e esz=0
|
||||
@q_shli_h . q:1 .. ..... 001 imm:4 ..... . rn:5 rd:5 &qrri_e esz=1
|
||||
@q_shli_s . q:1 .. ..... 01 imm:5 ..... . rn:5 rd:5 &qrri_e esz=2
|
||||
@q_shli_d . 1 .. ..... 1 imm:6 ..... . rn:5 rd:5 &qrri_e esz=3 q=1
|
||||
|
||||
FMOVI_v_h 0 q:1 00 1111 00000 ... 1111 11 ..... rd:5 %abcdefgh
|
||||
|
||||
# MOVI, MVNI, ORR, BIC, FMOV are all intermixed via cmode.
|
||||
Vimm 0 q:1 op:1 0 1111 00000 ... cmode:4 01 ..... rd:5 %abcdefgh
|
||||
|
||||
SSHR_v 0.00 11110 .... ... 00000 1 ..... ..... @q_shri_b
|
||||
SSHR_v 0.00 11110 .... ... 00000 1 ..... ..... @q_shri_h
|
||||
SSHR_v 0.00 11110 .... ... 00000 1 ..... ..... @q_shri_s
|
||||
SSHR_v 0.00 11110 .... ... 00000 1 ..... ..... @q_shri_d
|
||||
|
||||
USHR_v 0.10 11110 .... ... 00000 1 ..... ..... @q_shri_b
|
||||
USHR_v 0.10 11110 .... ... 00000 1 ..... ..... @q_shri_h
|
||||
USHR_v 0.10 11110 .... ... 00000 1 ..... ..... @q_shri_s
|
||||
USHR_v 0.10 11110 .... ... 00000 1 ..... ..... @q_shri_d
|
||||
|
||||
SSRA_v 0.00 11110 .... ... 00010 1 ..... ..... @q_shri_b
|
||||
SSRA_v 0.00 11110 .... ... 00010 1 ..... ..... @q_shri_h
|
||||
SSRA_v 0.00 11110 .... ... 00010 1 ..... ..... @q_shri_s
|
||||
SSRA_v 0.00 11110 .... ... 00010 1 ..... ..... @q_shri_d
|
||||
|
||||
USRA_v 0.10 11110 .... ... 00010 1 ..... ..... @q_shri_b
|
||||
USRA_v 0.10 11110 .... ... 00010 1 ..... ..... @q_shri_h
|
||||
USRA_v 0.10 11110 .... ... 00010 1 ..... ..... @q_shri_s
|
||||
USRA_v 0.10 11110 .... ... 00010 1 ..... ..... @q_shri_d
|
||||
|
||||
SRSHR_v 0.00 11110 .... ... 00100 1 ..... ..... @q_shri_b
|
||||
SRSHR_v 0.00 11110 .... ... 00100 1 ..... ..... @q_shri_h
|
||||
SRSHR_v 0.00 11110 .... ... 00100 1 ..... ..... @q_shri_s
|
||||
SRSHR_v 0.00 11110 .... ... 00100 1 ..... ..... @q_shri_d
|
||||
|
||||
URSHR_v 0.10 11110 .... ... 00100 1 ..... ..... @q_shri_b
|
||||
URSHR_v 0.10 11110 .... ... 00100 1 ..... ..... @q_shri_h
|
||||
URSHR_v 0.10 11110 .... ... 00100 1 ..... ..... @q_shri_s
|
||||
URSHR_v 0.10 11110 .... ... 00100 1 ..... ..... @q_shri_d
|
||||
|
||||
SRSRA_v 0.00 11110 .... ... 00110 1 ..... ..... @q_shri_b
|
||||
SRSRA_v 0.00 11110 .... ... 00110 1 ..... ..... @q_shri_h
|
||||
SRSRA_v 0.00 11110 .... ... 00110 1 ..... ..... @q_shri_s
|
||||
SRSRA_v 0.00 11110 .... ... 00110 1 ..... ..... @q_shri_d
|
||||
|
||||
URSRA_v 0.10 11110 .... ... 00110 1 ..... ..... @q_shri_b
|
||||
URSRA_v 0.10 11110 .... ... 00110 1 ..... ..... @q_shri_h
|
||||
URSRA_v 0.10 11110 .... ... 00110 1 ..... ..... @q_shri_s
|
||||
URSRA_v 0.10 11110 .... ... 00110 1 ..... ..... @q_shri_d
|
||||
|
||||
SRI_v 0.10 11110 .... ... 01000 1 ..... ..... @q_shri_b
|
||||
SRI_v 0.10 11110 .... ... 01000 1 ..... ..... @q_shri_h
|
||||
SRI_v 0.10 11110 .... ... 01000 1 ..... ..... @q_shri_s
|
||||
SRI_v 0.10 11110 .... ... 01000 1 ..... ..... @q_shri_d
|
||||
|
||||
SHL_v 0.00 11110 .... ... 01010 1 ..... ..... @q_shli_b
|
||||
SHL_v 0.00 11110 .... ... 01010 1 ..... ..... @q_shli_h
|
||||
SHL_v 0.00 11110 .... ... 01010 1 ..... ..... @q_shli_s
|
||||
SHL_v 0.00 11110 .... ... 01010 1 ..... ..... @q_shli_d
|
||||
|
||||
SLI_v 0.10 11110 .... ... 01010 1 ..... ..... @q_shli_b
|
||||
SLI_v 0.10 11110 .... ... 01010 1 ..... ..... @q_shli_h
|
||||
SLI_v 0.10 11110 .... ... 01010 1 ..... ..... @q_shli_s
|
||||
SLI_v 0.10 11110 .... ... 01010 1 ..... ..... @q_shli_d
|
||||
|
||||
SSHLL_v 0.00 11110 .... ... 10100 1 ..... ..... @q_shli_b
|
||||
SSHLL_v 0.00 11110 .... ... 10100 1 ..... ..... @q_shli_h
|
||||
SSHLL_v 0.00 11110 .... ... 10100 1 ..... ..... @q_shli_s
|
||||
|
||||
USHLL_v 0.10 11110 .... ... 10100 1 ..... ..... @q_shli_b
|
||||
USHLL_v 0.10 11110 .... ... 10100 1 ..... ..... @q_shli_h
|
||||
USHLL_v 0.10 11110 .... ... 10100 1 ..... ..... @q_shli_s
|
||||
|
||||
SHRN_v 0.00 11110 .... ... 10000 1 ..... ..... @q_shri_b
|
||||
SHRN_v 0.00 11110 .... ... 10000 1 ..... ..... @q_shri_h
|
||||
SHRN_v 0.00 11110 .... ... 10000 1 ..... ..... @q_shri_s
|
||||
|
||||
RSHRN_v 0.00 11110 .... ... 10001 1 ..... ..... @q_shri_b
|
||||
RSHRN_v 0.00 11110 .... ... 10001 1 ..... ..... @q_shri_h
|
||||
RSHRN_v 0.00 11110 .... ... 10001 1 ..... ..... @q_shri_s
|
||||
|
||||
SQSHL_vi 0.00 11110 .... ... 01110 1 ..... ..... @q_shli_b
|
||||
SQSHL_vi 0.00 11110 .... ... 01110 1 ..... ..... @q_shli_h
|
||||
SQSHL_vi 0.00 11110 .... ... 01110 1 ..... ..... @q_shli_s
|
||||
SQSHL_vi 0.00 11110 .... ... 01110 1 ..... ..... @q_shli_d
|
||||
|
||||
UQSHL_vi 0.10 11110 .... ... 01110 1 ..... ..... @q_shli_b
|
||||
UQSHL_vi 0.10 11110 .... ... 01110 1 ..... ..... @q_shli_h
|
||||
UQSHL_vi 0.10 11110 .... ... 01110 1 ..... ..... @q_shli_s
|
||||
UQSHL_vi 0.10 11110 .... ... 01110 1 ..... ..... @q_shli_d
|
||||
|
||||
SQSHLU_vi 0.10 11110 .... ... 01100 1 ..... ..... @q_shli_b
|
||||
SQSHLU_vi 0.10 11110 .... ... 01100 1 ..... ..... @q_shli_h
|
||||
SQSHLU_vi 0.10 11110 .... ... 01100 1 ..... ..... @q_shli_s
|
||||
SQSHLU_vi 0.10 11110 .... ... 01100 1 ..... ..... @q_shli_d
|
||||
|
||||
SQSHRN_v 0.00 11110 .... ... 10010 1 ..... ..... @q_shri_b
|
||||
SQSHRN_v 0.00 11110 .... ... 10010 1 ..... ..... @q_shri_h
|
||||
SQSHRN_v 0.00 11110 .... ... 10010 1 ..... ..... @q_shri_s
|
||||
|
||||
UQSHRN_v 0.10 11110 .... ... 10010 1 ..... ..... @q_shri_b
|
||||
UQSHRN_v 0.10 11110 .... ... 10010 1 ..... ..... @q_shri_h
|
||||
UQSHRN_v 0.10 11110 .... ... 10010 1 ..... ..... @q_shri_s
|
||||
|
||||
SQSHRUN_v 0.10 11110 .... ... 10000 1 ..... ..... @q_shri_b
|
||||
SQSHRUN_v 0.10 11110 .... ... 10000 1 ..... ..... @q_shri_h
|
||||
SQSHRUN_v 0.10 11110 .... ... 10000 1 ..... ..... @q_shri_s
|
||||
|
||||
SQRSHRN_v 0.00 11110 .... ... 10011 1 ..... ..... @q_shri_b
|
||||
SQRSHRN_v 0.00 11110 .... ... 10011 1 ..... ..... @q_shri_h
|
||||
SQRSHRN_v 0.00 11110 .... ... 10011 1 ..... ..... @q_shri_s
|
||||
|
||||
UQRSHRN_v 0.10 11110 .... ... 10011 1 ..... ..... @q_shri_b
|
||||
UQRSHRN_v 0.10 11110 .... ... 10011 1 ..... ..... @q_shri_h
|
||||
UQRSHRN_v 0.10 11110 .... ... 10011 1 ..... ..... @q_shri_s
|
||||
|
||||
SQRSHRUN_v 0.10 11110 .... ... 10001 1 ..... ..... @q_shri_b
|
||||
SQRSHRUN_v 0.10 11110 .... ... 10001 1 ..... ..... @q_shri_h
|
||||
SQRSHRUN_v 0.10 11110 .... ... 10001 1 ..... ..... @q_shri_s
|
||||
|
||||
# Advanced SIMD scalar shift by immediate
|
||||
|
||||
@shri_b .... ..... 0001 ... ..... . rn:5 rd:5 \
|
||||
&rri_e esz=0 imm=%neon_rshift_i3
|
||||
@shri_h .... ..... 001 .... ..... . rn:5 rd:5 \
|
||||
&rri_e esz=1 imm=%neon_rshift_i4
|
||||
@shri_s .... ..... 01 ..... ..... . rn:5 rd:5 \
|
||||
&rri_e esz=2 imm=%neon_rshift_i5
|
||||
@shri_d .... ..... 1 ...... ..... . rn:5 rd:5 \
|
||||
&rri_e esz=3 imm=%neon_rshift_i6
|
||||
|
||||
@shli_b .... ..... 0001 imm:3 ..... . rn:5 rd:5 &rri_e esz=0
|
||||
@shli_h .... ..... 001 imm:4 ..... . rn:5 rd:5 &rri_e esz=1
|
||||
@shli_s .... ..... 01 imm:5 ..... . rn:5 rd:5 &rri_e esz=2
|
||||
@shli_d .... ..... 1 imm:6 ..... . rn:5 rd:5 &rri_e esz=3
|
||||
|
||||
SSHR_s 0101 11110 .... ... 00000 1 ..... ..... @shri_d
|
||||
USHR_s 0111 11110 .... ... 00000 1 ..... ..... @shri_d
|
||||
SSRA_s 0101 11110 .... ... 00010 1 ..... ..... @shri_d
|
||||
USRA_s 0111 11110 .... ... 00010 1 ..... ..... @shri_d
|
||||
SRSHR_s 0101 11110 .... ... 00100 1 ..... ..... @shri_d
|
||||
URSHR_s 0111 11110 .... ... 00100 1 ..... ..... @shri_d
|
||||
SRSRA_s 0101 11110 .... ... 00110 1 ..... ..... @shri_d
|
||||
URSRA_s 0111 11110 .... ... 00110 1 ..... ..... @shri_d
|
||||
SRI_s 0111 11110 .... ... 01000 1 ..... ..... @shri_d
|
||||
|
||||
SHL_s 0101 11110 .... ... 01010 1 ..... ..... @shli_d
|
||||
SLI_s 0111 11110 .... ... 01010 1 ..... ..... @shli_d
|
||||
|
||||
SQSHL_si 0101 11110 .... ... 01110 1 ..... ..... @shli_b
|
||||
SQSHL_si 0101 11110 .... ... 01110 1 ..... ..... @shli_h
|
||||
SQSHL_si 0101 11110 .... ... 01110 1 ..... ..... @shli_s
|
||||
SQSHL_si 0101 11110 .... ... 01110 1 ..... ..... @shli_d
|
||||
|
||||
UQSHL_si 0111 11110 .... ... 01110 1 ..... ..... @shli_b
|
||||
UQSHL_si 0111 11110 .... ... 01110 1 ..... ..... @shli_h
|
||||
UQSHL_si 0111 11110 .... ... 01110 1 ..... ..... @shli_s
|
||||
UQSHL_si 0111 11110 .... ... 01110 1 ..... ..... @shli_d
|
||||
|
||||
SQSHLU_si 0111 11110 .... ... 01100 1 ..... ..... @shli_b
|
||||
SQSHLU_si 0111 11110 .... ... 01100 1 ..... ..... @shli_h
|
||||
SQSHLU_si 0111 11110 .... ... 01100 1 ..... ..... @shli_s
|
||||
SQSHLU_si 0111 11110 .... ... 01100 1 ..... ..... @shli_d
|
||||
|
||||
SQSHRN_si 0101 11110 .... ... 10010 1 ..... ..... @shri_b
|
||||
SQSHRN_si 0101 11110 .... ... 10010 1 ..... ..... @shri_h
|
||||
SQSHRN_si 0101 11110 .... ... 10010 1 ..... ..... @shri_s
|
||||
|
||||
UQSHRN_si 0111 11110 .... ... 10010 1 ..... ..... @shri_b
|
||||
UQSHRN_si 0111 11110 .... ... 10010 1 ..... ..... @shri_h
|
||||
UQSHRN_si 0111 11110 .... ... 10010 1 ..... ..... @shri_s
|
||||
|
||||
SQSHRUN_si 0111 11110 .... ... 10000 1 ..... ..... @shri_b
|
||||
SQSHRUN_si 0111 11110 .... ... 10000 1 ..... ..... @shri_h
|
||||
SQSHRUN_si 0111 11110 .... ... 10000 1 ..... ..... @shri_s
|
||||
|
||||
SQRSHRN_si 0101 11110 .... ... 10011 1 ..... ..... @shri_b
|
||||
SQRSHRN_si 0101 11110 .... ... 10011 1 ..... ..... @shri_h
|
||||
SQRSHRN_si 0101 11110 .... ... 10011 1 ..... ..... @shri_s
|
||||
|
||||
UQRSHRN_si 0111 11110 .... ... 10011 1 ..... ..... @shri_b
|
||||
UQRSHRN_si 0111 11110 .... ... 10011 1 ..... ..... @shri_h
|
||||
UQRSHRN_si 0111 11110 .... ... 10011 1 ..... ..... @shri_s
|
||||
|
||||
SQRSHRUN_si 0111 11110 .... ... 10001 1 ..... ..... @shri_b
|
||||
SQRSHRUN_si 0111 11110 .... ... 10001 1 ..... ..... @shri_h
|
||||
SQRSHRUN_si 0111 11110 .... ... 10001 1 ..... ..... @shri_s
|
||||
|
@ -677,7 +677,7 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
|
||||
cpu->isar.id_aa64dfr0 = 0x000001f210305519ull;
|
||||
cpu->isar.id_aa64dfr1 = 0x00000000;
|
||||
cpu->isar.id_aa64isar0 = 0x1011111110212120ull; /* with FEAT_RNG */
|
||||
cpu->isar.id_aa64isar1 = 0x0111000001211032ull;
|
||||
cpu->isar.id_aa64isar1 = 0x0011100001211032ull;
|
||||
cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull;
|
||||
cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
|
||||
cpu->isar.id_aa64mmfr2 = 0x0220011102101011ull;
|
||||
|
@ -88,6 +88,25 @@ GEN_CMP0(gen_gvec_cgt0, TCG_COND_GT)
|
||||
|
||||
#undef GEN_CMP0
|
||||
|
||||
void gen_gvec_sshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
|
||||
int64_t shift, uint32_t opr_sz, uint32_t max_sz)
|
||||
{
|
||||
/* Signed shift out of range results in all-sign-bits */
|
||||
shift = MIN(shift, (8 << vece) - 1);
|
||||
tcg_gen_gvec_sari(vece, rd_ofs, rm_ofs, shift, opr_sz, max_sz);
|
||||
}
|
||||
|
||||
void gen_gvec_ushr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
|
||||
int64_t shift, uint32_t opr_sz, uint32_t max_sz)
|
||||
{
|
||||
/* Unsigned shift out of range results in all-zero-bits */
|
||||
if (shift >= (8 << vece)) {
|
||||
tcg_gen_gvec_dup_imm(vece, rd_ofs, opr_sz, max_sz, 0);
|
||||
} else {
|
||||
tcg_gen_gvec_shri(vece, rd_ofs, rm_ofs, shift, opr_sz, max_sz);
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
|
||||
{
|
||||
tcg_gen_vec_sar8i_i64(a, a, shift);
|
||||
@ -285,7 +304,7 @@ void gen_srshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
|
||||
tcg_gen_add_i32(d, d, t);
|
||||
}
|
||||
|
||||
void gen_srshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
|
||||
void gen_srshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
|
||||
{
|
||||
TCGv_i64 t = tcg_temp_new_i64();
|
||||
|
||||
@ -297,10 +316,9 @@ void gen_srshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
|
||||
static void gen_srshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
TCGv_vec ones = tcg_temp_new_vec_matching(d);
|
||||
TCGv_vec ones = tcg_constant_vec_matching(d, vece, 1);
|
||||
|
||||
tcg_gen_shri_vec(vece, t, a, sh - 1);
|
||||
tcg_gen_dupi_vec(vece, ones, 1);
|
||||
tcg_gen_and_vec(vece, t, t, ones);
|
||||
tcg_gen_sari_vec(vece, d, a, sh);
|
||||
tcg_gen_add_vec(vece, d, d, t);
|
||||
@ -492,10 +510,9 @@ void gen_urshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
|
||||
static void gen_urshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t shift)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
TCGv_vec ones = tcg_temp_new_vec_matching(d);
|
||||
TCGv_vec ones = tcg_constant_vec_matching(d, vece, 1);
|
||||
|
||||
tcg_gen_shri_vec(vece, t, a, shift - 1);
|
||||
tcg_gen_dupi_vec(vece, ones, 1);
|
||||
tcg_gen_and_vec(vece, t, t, ones);
|
||||
tcg_gen_shri_vec(vece, d, a, shift);
|
||||
tcg_gen_add_vec(vece, d, d, t);
|
||||
@ -685,9 +702,9 @@ static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
|
||||
static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
TCGv_vec m = tcg_temp_new_vec_matching(d);
|
||||
int64_t mi = MAKE_64BIT_MASK((8 << vece) - sh, sh);
|
||||
TCGv_vec m = tcg_constant_vec_matching(d, vece, mi);
|
||||
|
||||
tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
|
||||
tcg_gen_shri_vec(vece, t, a, sh);
|
||||
tcg_gen_and_vec(vece, d, d, m);
|
||||
tcg_gen_or_vec(vece, d, d, t);
|
||||
@ -773,10 +790,9 @@ static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
|
||||
static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
TCGv_vec m = tcg_temp_new_vec_matching(d);
|
||||
TCGv_vec m = tcg_constant_vec_matching(d, vece, MAKE_64BIT_MASK(0, sh));
|
||||
|
||||
tcg_gen_shli_vec(vece, t, a, sh);
|
||||
tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
|
||||
tcg_gen_and_vec(vece, d, d, m);
|
||||
tcg_gen_or_vec(vece, d, d, t);
|
||||
}
|
||||
@ -1044,14 +1060,13 @@ static void gen_ushl_vec(unsigned vece, TCGv_vec dst,
|
||||
TCGv_vec rval = tcg_temp_new_vec_matching(dst);
|
||||
TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
|
||||
TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
|
||||
TCGv_vec msk, max;
|
||||
TCGv_vec max, zero;
|
||||
|
||||
tcg_gen_neg_vec(vece, rsh, shift);
|
||||
if (vece == MO_8) {
|
||||
tcg_gen_mov_vec(lsh, shift);
|
||||
} else {
|
||||
msk = tcg_temp_new_vec_matching(dst);
|
||||
tcg_gen_dupi_vec(vece, msk, 0xff);
|
||||
TCGv_vec msk = tcg_constant_vec_matching(dst, vece, 0xff);
|
||||
tcg_gen_and_vec(vece, lsh, shift, msk);
|
||||
tcg_gen_and_vec(vece, rsh, rsh, msk);
|
||||
}
|
||||
@ -1064,26 +1079,21 @@ static void gen_ushl_vec(unsigned vece, TCGv_vec dst,
|
||||
tcg_gen_shlv_vec(vece, lval, src, lsh);
|
||||
tcg_gen_shrv_vec(vece, rval, src, rsh);
|
||||
|
||||
max = tcg_temp_new_vec_matching(dst);
|
||||
tcg_gen_dupi_vec(vece, max, 8 << vece);
|
||||
|
||||
/*
|
||||
* The choice of LT (signed) and GEU (unsigned) are biased toward
|
||||
* The choice of GE (signed) and GEU (unsigned) are biased toward
|
||||
* the instructions of the x86_64 host. For MO_8, the whole byte
|
||||
* is significant so we must use an unsigned compare; otherwise we
|
||||
* have already masked to a byte and so a signed compare works.
|
||||
* Other tcg hosts have a full set of comparisons and do not care.
|
||||
*/
|
||||
zero = tcg_constant_vec_matching(dst, vece, 0);
|
||||
max = tcg_constant_vec_matching(dst, vece, 8 << vece);
|
||||
if (vece == MO_8) {
|
||||
tcg_gen_cmp_vec(TCG_COND_GEU, vece, lsh, lsh, max);
|
||||
tcg_gen_cmp_vec(TCG_COND_GEU, vece, rsh, rsh, max);
|
||||
tcg_gen_andc_vec(vece, lval, lval, lsh);
|
||||
tcg_gen_andc_vec(vece, rval, rval, rsh);
|
||||
tcg_gen_cmpsel_vec(TCG_COND_GEU, vece, lval, lsh, max, zero, lval);
|
||||
tcg_gen_cmpsel_vec(TCG_COND_GEU, vece, rval, rsh, max, zero, rval);
|
||||
} else {
|
||||
tcg_gen_cmp_vec(TCG_COND_LT, vece, lsh, lsh, max);
|
||||
tcg_gen_cmp_vec(TCG_COND_LT, vece, rsh, rsh, max);
|
||||
tcg_gen_and_vec(vece, lval, lval, lsh);
|
||||
tcg_gen_and_vec(vece, rval, rval, rsh);
|
||||
tcg_gen_cmpsel_vec(TCG_COND_GE, vece, lval, lsh, max, zero, lval);
|
||||
tcg_gen_cmpsel_vec(TCG_COND_GE, vece, rval, rsh, max, zero, rval);
|
||||
}
|
||||
tcg_gen_or_vec(vece, dst, lval, rval);
|
||||
}
|
||||
@ -1093,7 +1103,7 @@ void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||
{
|
||||
static const TCGOpcode vecop_list[] = {
|
||||
INDEX_op_neg_vec, INDEX_op_shlv_vec,
|
||||
INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
|
||||
INDEX_op_shrv_vec, INDEX_op_cmpsel_vec, 0
|
||||
};
|
||||
static const GVecGen3 ops[4] = {
|
||||
{ .fniv = gen_ushl_vec,
|
||||
@ -1169,7 +1179,7 @@ static void gen_sshl_vec(unsigned vece, TCGv_vec dst,
|
||||
TCGv_vec rval = tcg_temp_new_vec_matching(dst);
|
||||
TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
|
||||
TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
|
||||
TCGv_vec tmp = tcg_temp_new_vec_matching(dst);
|
||||
TCGv_vec max, zero;
|
||||
|
||||
/*
|
||||
* Rely on the TCG guarantee that out of range shifts produce
|
||||
@ -1180,29 +1190,28 @@ static void gen_sshl_vec(unsigned vece, TCGv_vec dst,
|
||||
if (vece == MO_8) {
|
||||
tcg_gen_mov_vec(lsh, shift);
|
||||
} else {
|
||||
tcg_gen_dupi_vec(vece, tmp, 0xff);
|
||||
tcg_gen_and_vec(vece, lsh, shift, tmp);
|
||||
tcg_gen_and_vec(vece, rsh, rsh, tmp);
|
||||
TCGv_vec msk = tcg_constant_vec_matching(dst, vece, 0xff);
|
||||
tcg_gen_and_vec(vece, lsh, shift, msk);
|
||||
tcg_gen_and_vec(vece, rsh, rsh, msk);
|
||||
}
|
||||
|
||||
/* Bound rsh so out of bound right shift gets -1. */
|
||||
tcg_gen_dupi_vec(vece, tmp, (8 << vece) - 1);
|
||||
tcg_gen_umin_vec(vece, rsh, rsh, tmp);
|
||||
tcg_gen_cmp_vec(TCG_COND_GT, vece, tmp, lsh, tmp);
|
||||
max = tcg_constant_vec_matching(dst, vece, (8 << vece) - 1);
|
||||
tcg_gen_umin_vec(vece, rsh, rsh, max);
|
||||
|
||||
tcg_gen_shlv_vec(vece, lval, src, lsh);
|
||||
tcg_gen_sarv_vec(vece, rval, src, rsh);
|
||||
|
||||
/* Select in-bound left shift. */
|
||||
tcg_gen_andc_vec(vece, lval, lval, tmp);
|
||||
zero = tcg_constant_vec_matching(dst, vece, 0);
|
||||
tcg_gen_cmpsel_vec(TCG_COND_GT, vece, lval, lsh, max, zero, lval);
|
||||
|
||||
/* Select between left and right shift. */
|
||||
if (vece == MO_8) {
|
||||
tcg_gen_dupi_vec(vece, tmp, 0);
|
||||
tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, rval, lval);
|
||||
tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, zero, rval, lval);
|
||||
} else {
|
||||
tcg_gen_dupi_vec(vece, tmp, 0x80);
|
||||
tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, lval, rval);
|
||||
TCGv_vec sgn = tcg_constant_vec_matching(dst, vece, 0x80);
|
||||
tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, sgn, lval, rval);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1211,7 +1220,7 @@ void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||
{
|
||||
static const TCGOpcode vecop_list[] = {
|
||||
INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
|
||||
INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
|
||||
INDEX_op_sarv_vec, INDEX_op_cmpsel_vec, 0
|
||||
};
|
||||
static const GVecGen3 ops[4] = {
|
||||
{ .fniv = gen_sshl_vec,
|
||||
@ -1304,6 +1313,42 @@ void gen_neon_uqrshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||
opr_sz, max_sz, 0, fns[vece]);
|
||||
}
|
||||
|
||||
void gen_neon_sqshli(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||
int64_t c, uint32_t opr_sz, uint32_t max_sz)
|
||||
{
|
||||
static gen_helper_gvec_2_ptr * const fns[] = {
|
||||
gen_helper_neon_sqshli_b, gen_helper_neon_sqshli_h,
|
||||
gen_helper_neon_sqshli_s, gen_helper_neon_sqshli_d,
|
||||
};
|
||||
tcg_debug_assert(vece <= MO_64);
|
||||
tcg_debug_assert(c >= 0 && c <= (8 << vece));
|
||||
tcg_gen_gvec_2_ptr(rd_ofs, rn_ofs, tcg_env, opr_sz, max_sz, c, fns[vece]);
|
||||
}
|
||||
|
||||
void gen_neon_uqshli(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||
int64_t c, uint32_t opr_sz, uint32_t max_sz)
|
||||
{
|
||||
static gen_helper_gvec_2_ptr * const fns[] = {
|
||||
gen_helper_neon_uqshli_b, gen_helper_neon_uqshli_h,
|
||||
gen_helper_neon_uqshli_s, gen_helper_neon_uqshli_d,
|
||||
};
|
||||
tcg_debug_assert(vece <= MO_64);
|
||||
tcg_debug_assert(c >= 0 && c <= (8 << vece));
|
||||
tcg_gen_gvec_2_ptr(rd_ofs, rn_ofs, tcg_env, opr_sz, max_sz, c, fns[vece]);
|
||||
}
|
||||
|
||||
void gen_neon_sqshlui(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||
int64_t c, uint32_t opr_sz, uint32_t max_sz)
|
||||
{
|
||||
static gen_helper_gvec_2_ptr * const fns[] = {
|
||||
gen_helper_neon_sqshlui_b, gen_helper_neon_sqshlui_h,
|
||||
gen_helper_neon_sqshlui_s, gen_helper_neon_sqshlui_d,
|
||||
};
|
||||
tcg_debug_assert(vece <= MO_64);
|
||||
tcg_debug_assert(c >= 0 && c <= (8 << vece));
|
||||
tcg_gen_gvec_2_ptr(rd_ofs, rn_ofs, tcg_env, opr_sz, max_sz, c, fns[vece]);
|
||||
}
|
||||
|
||||
void gen_uqadd_bhs(TCGv_i64 res, TCGv_i64 qc, TCGv_i64 a, TCGv_i64 b, MemOp esz)
|
||||
{
|
||||
uint64_t max = MAKE_64BIT_MASK(0, 8 << esz);
|
||||
|
@ -291,17 +291,17 @@ VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_s
|
||||
VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_h
|
||||
VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_b
|
||||
|
||||
VQSHLU_64_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_d
|
||||
VQSHLU_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_d
|
||||
VQSHLU_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_s
|
||||
VQSHLU_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_h
|
||||
VQSHLU_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_b
|
||||
|
||||
VQSHL_S_64_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_d
|
||||
VQSHL_S_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_d
|
||||
VQSHL_S_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_s
|
||||
VQSHL_S_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_h
|
||||
VQSHL_S_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_b
|
||||
|
||||
VQSHL_U_64_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_d
|
||||
VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_d
|
||||
VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_s
|
||||
VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_h
|
||||
VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_b
|
||||
|
@ -141,6 +141,19 @@ void HELPER(name)(void *vd, void *vn, void *vm, void *venv, uint32_t desc) \
|
||||
clear_tail(d, opr_sz, simd_maxsz(desc)); \
|
||||
}
|
||||
|
||||
#define NEON_GVEC_VOP2i_ENV(name, vtype) \
|
||||
void HELPER(name)(void *vd, void *vn, void *venv, uint32_t desc) \
|
||||
{ \
|
||||
intptr_t i, opr_sz = simd_oprsz(desc); \
|
||||
int imm = simd_data(desc); \
|
||||
vtype *d = vd, *n = vn; \
|
||||
CPUARMState *env = venv; \
|
||||
for (i = 0; i < opr_sz / sizeof(vtype); i++) { \
|
||||
NEON_FN(d[i], n[i], imm); \
|
||||
} \
|
||||
clear_tail(d, opr_sz, simd_maxsz(desc)); \
|
||||
}
|
||||
|
||||
/* Pairwise operations. */
|
||||
/* For 32-bit elements each segment only contains a single element, so
|
||||
the elementwise and pairwise operations are the same. */
|
||||
@ -271,22 +284,26 @@ uint64_t HELPER(neon_rshl_u64)(uint64_t val, uint64_t shift)
|
||||
(dest = do_uqrshl_bhs(src1, (int8_t)src2, 8, false, env->vfp.qc))
|
||||
NEON_VOP_ENV(qshl_u8, neon_u8, 4)
|
||||
NEON_GVEC_VOP2_ENV(neon_uqshl_b, uint8_t)
|
||||
NEON_GVEC_VOP2i_ENV(neon_uqshli_b, uint8_t)
|
||||
#undef NEON_FN
|
||||
|
||||
#define NEON_FN(dest, src1, src2) \
|
||||
(dest = do_uqrshl_bhs(src1, (int8_t)src2, 16, false, env->vfp.qc))
|
||||
NEON_VOP_ENV(qshl_u16, neon_u16, 2)
|
||||
NEON_GVEC_VOP2_ENV(neon_uqshl_h, uint16_t)
|
||||
NEON_GVEC_VOP2i_ENV(neon_uqshli_h, uint16_t)
|
||||
#undef NEON_FN
|
||||
|
||||
#define NEON_FN(dest, src1, src2) \
|
||||
(dest = do_uqrshl_bhs(src1, (int8_t)src2, 32, false, env->vfp.qc))
|
||||
NEON_GVEC_VOP2_ENV(neon_uqshl_s, uint32_t)
|
||||
NEON_GVEC_VOP2i_ENV(neon_uqshli_s, uint32_t)
|
||||
#undef NEON_FN
|
||||
|
||||
#define NEON_FN(dest, src1, src2) \
|
||||
(dest = do_uqrshl_d(src1, (int8_t)src2, false, env->vfp.qc))
|
||||
NEON_GVEC_VOP2_ENV(neon_uqshl_d, uint64_t)
|
||||
NEON_GVEC_VOP2i_ENV(neon_uqshli_d, uint64_t)
|
||||
#undef NEON_FN
|
||||
|
||||
uint32_t HELPER(neon_qshl_u32)(CPUARMState *env, uint32_t val, uint32_t shift)
|
||||
@ -303,22 +320,26 @@ uint64_t HELPER(neon_qshl_u64)(CPUARMState *env, uint64_t val, uint64_t shift)
|
||||
(dest = do_sqrshl_bhs(src1, (int8_t)src2, 8, false, env->vfp.qc))
|
||||
NEON_VOP_ENV(qshl_s8, neon_s8, 4)
|
||||
NEON_GVEC_VOP2_ENV(neon_sqshl_b, int8_t)
|
||||
NEON_GVEC_VOP2i_ENV(neon_sqshli_b, int8_t)
|
||||
#undef NEON_FN
|
||||
|
||||
#define NEON_FN(dest, src1, src2) \
|
||||
(dest = do_sqrshl_bhs(src1, (int8_t)src2, 16, false, env->vfp.qc))
|
||||
NEON_VOP_ENV(qshl_s16, neon_s16, 2)
|
||||
NEON_GVEC_VOP2_ENV(neon_sqshl_h, int16_t)
|
||||
NEON_GVEC_VOP2i_ENV(neon_sqshli_h, int16_t)
|
||||
#undef NEON_FN
|
||||
|
||||
#define NEON_FN(dest, src1, src2) \
|
||||
(dest = do_sqrshl_bhs(src1, (int8_t)src2, 32, false, env->vfp.qc))
|
||||
NEON_GVEC_VOP2_ENV(neon_sqshl_s, int32_t)
|
||||
NEON_GVEC_VOP2i_ENV(neon_sqshli_s, int32_t)
|
||||
#undef NEON_FN
|
||||
|
||||
#define NEON_FN(dest, src1, src2) \
|
||||
(dest = do_sqrshl_d(src1, (int8_t)src2, false, env->vfp.qc))
|
||||
NEON_GVEC_VOP2_ENV(neon_sqshl_d, int64_t)
|
||||
NEON_GVEC_VOP2i_ENV(neon_sqshli_d, int64_t)
|
||||
#undef NEON_FN
|
||||
|
||||
uint32_t HELPER(neon_qshl_s32)(CPUARMState *env, uint32_t val, uint32_t shift)
|
||||
@ -334,11 +355,13 @@ uint64_t HELPER(neon_qshl_s64)(CPUARMState *env, uint64_t val, uint64_t shift)
|
||||
#define NEON_FN(dest, src1, src2) \
|
||||
(dest = do_suqrshl_bhs(src1, (int8_t)src2, 8, false, env->vfp.qc))
|
||||
NEON_VOP_ENV(qshlu_s8, neon_s8, 4)
|
||||
NEON_GVEC_VOP2i_ENV(neon_sqshlui_b, int8_t)
|
||||
#undef NEON_FN
|
||||
|
||||
#define NEON_FN(dest, src1, src2) \
|
||||
(dest = do_suqrshl_bhs(src1, (int8_t)src2, 16, false, env->vfp.qc))
|
||||
NEON_VOP_ENV(qshlu_s16, neon_s16, 2)
|
||||
NEON_GVEC_VOP2i_ENV(neon_sqshlui_h, int16_t)
|
||||
#undef NEON_FN
|
||||
|
||||
uint32_t HELPER(neon_qshlu_s32)(CPUARMState *env, uint32_t val, uint32_t shift)
|
||||
@ -351,6 +374,16 @@ uint64_t HELPER(neon_qshlu_s64)(CPUARMState *env, uint64_t val, uint64_t shift)
|
||||
return do_suqrshl_d(val, (int8_t)shift, false, env->vfp.qc);
|
||||
}
|
||||
|
||||
#define NEON_FN(dest, src1, src2) \
|
||||
(dest = do_suqrshl_bhs(src1, (int8_t)src2, 32, false, env->vfp.qc))
|
||||
NEON_GVEC_VOP2i_ENV(neon_sqshlui_s, int32_t)
|
||||
#undef NEON_FN
|
||||
|
||||
#define NEON_FN(dest, src1, src2) \
|
||||
(dest = do_suqrshl_d(src1, (int8_t)src2, false, env->vfp.qc))
|
||||
NEON_GVEC_VOP2i_ENV(neon_sqshlui_d, int64_t)
|
||||
#undef NEON_FN
|
||||
|
||||
#define NEON_FN(dest, src1, src2) \
|
||||
(dest = do_uqrshl_bhs(src1, (int8_t)src2, 8, true, env->vfp.qc))
|
||||
NEON_VOP_ENV(qrshl_u8, neon_u8, 4)
|
||||
@ -565,13 +598,15 @@ NEON_VOP_ENV(qrdmulh_s32, neon_s32, 1)
|
||||
#undef NEON_FN
|
||||
#undef NEON_QDMULH32
|
||||
|
||||
uint32_t HELPER(neon_narrow_u8)(uint64_t x)
|
||||
/* Only the low 32-bits of output are significant. */
|
||||
uint64_t HELPER(neon_narrow_u8)(uint64_t x)
|
||||
{
|
||||
return (x & 0xffu) | ((x >> 8) & 0xff00u) | ((x >> 16) & 0xff0000u)
|
||||
| ((x >> 24) & 0xff000000u);
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_narrow_u16)(uint64_t x)
|
||||
/* Only the low 32-bits of output are significant. */
|
||||
uint64_t HELPER(neon_narrow_u16)(uint64_t x)
|
||||
{
|
||||
return (x & 0xffffu) | ((x >> 16) & 0xffff0000u);
|
||||
}
|
||||
@ -602,7 +637,8 @@ uint32_t HELPER(neon_narrow_round_high_u16)(uint64_t x)
|
||||
return ((x >> 16) & 0xffff) | ((x >> 32) & 0xffff0000);
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_unarrow_sat8)(CPUARMState *env, uint64_t x)
|
||||
/* Only the low 32-bits of output are significant. */
|
||||
uint64_t HELPER(neon_unarrow_sat8)(CPUARMState *env, uint64_t x)
|
||||
{
|
||||
uint16_t s;
|
||||
uint8_t d;
|
||||
@ -629,7 +665,8 @@ uint32_t HELPER(neon_unarrow_sat8)(CPUARMState *env, uint64_t x)
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_narrow_sat_u8)(CPUARMState *env, uint64_t x)
|
||||
/* Only the low 32-bits of output are significant. */
|
||||
uint64_t HELPER(neon_narrow_sat_u8)(CPUARMState *env, uint64_t x)
|
||||
{
|
||||
uint16_t s;
|
||||
uint8_t d;
|
||||
@ -652,7 +689,8 @@ uint32_t HELPER(neon_narrow_sat_u8)(CPUARMState *env, uint64_t x)
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_narrow_sat_s8)(CPUARMState *env, uint64_t x)
|
||||
/* Only the low 32-bits of output are significant. */
|
||||
uint64_t HELPER(neon_narrow_sat_s8)(CPUARMState *env, uint64_t x)
|
||||
{
|
||||
int16_t s;
|
||||
uint8_t d;
|
||||
@ -675,7 +713,8 @@ uint32_t HELPER(neon_narrow_sat_s8)(CPUARMState *env, uint64_t x)
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_unarrow_sat16)(CPUARMState *env, uint64_t x)
|
||||
/* Only the low 32-bits of output are significant. */
|
||||
uint64_t HELPER(neon_unarrow_sat16)(CPUARMState *env, uint64_t x)
|
||||
{
|
||||
uint32_t high;
|
||||
uint32_t low;
|
||||
@ -695,10 +734,11 @@ uint32_t HELPER(neon_unarrow_sat16)(CPUARMState *env, uint64_t x)
|
||||
high = 0xffff;
|
||||
SET_QC();
|
||||
}
|
||||
return low | (high << 16);
|
||||
return deposit32(low, 16, 16, high);
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_narrow_sat_u16)(CPUARMState *env, uint64_t x)
|
||||
/* Only the low 32-bits of output are significant. */
|
||||
uint64_t HELPER(neon_narrow_sat_u16)(CPUARMState *env, uint64_t x)
|
||||
{
|
||||
uint32_t high;
|
||||
uint32_t low;
|
||||
@ -712,10 +752,11 @@ uint32_t HELPER(neon_narrow_sat_u16)(CPUARMState *env, uint64_t x)
|
||||
high = 0xffff;
|
||||
SET_QC();
|
||||
}
|
||||
return low | (high << 16);
|
||||
return deposit32(low, 16, 16, high);
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_narrow_sat_s16)(CPUARMState *env, uint64_t x)
|
||||
/* Only the low 32-bits of output are significant. */
|
||||
uint64_t HELPER(neon_narrow_sat_s16)(CPUARMState *env, uint64_t x)
|
||||
{
|
||||
int32_t low;
|
||||
int32_t high;
|
||||
@ -729,10 +770,11 @@ uint32_t HELPER(neon_narrow_sat_s16)(CPUARMState *env, uint64_t x)
|
||||
high = (high >> 31) ^ 0x7fff;
|
||||
SET_QC();
|
||||
}
|
||||
return (uint16_t)low | (high << 16);
|
||||
return deposit32(low, 16, 16, high);
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_unarrow_sat32)(CPUARMState *env, uint64_t x)
|
||||
/* Only the low 32-bits of output are significant. */
|
||||
uint64_t HELPER(neon_unarrow_sat32)(CPUARMState *env, uint64_t x)
|
||||
{
|
||||
if (x & 0x8000000000000000ull) {
|
||||
SET_QC();
|
||||
@ -745,7 +787,8 @@ uint32_t HELPER(neon_unarrow_sat32)(CPUARMState *env, uint64_t x)
|
||||
return x;
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_narrow_sat_u32)(CPUARMState *env, uint64_t x)
|
||||
/* Only the low 32-bits of output are significant. */
|
||||
uint64_t HELPER(neon_narrow_sat_u32)(CPUARMState *env, uint64_t x)
|
||||
{
|
||||
if (x > 0xffffffffu) {
|
||||
SET_QC();
|
||||
@ -754,13 +797,14 @@ uint32_t HELPER(neon_narrow_sat_u32)(CPUARMState *env, uint64_t x)
|
||||
return x;
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_narrow_sat_s32)(CPUARMState *env, uint64_t x)
|
||||
/* Only the low 32-bits of output are significant. */
|
||||
uint64_t HELPER(neon_narrow_sat_s32)(CPUARMState *env, uint64_t x)
|
||||
{
|
||||
if ((int64_t)x != (int32_t)x) {
|
||||
SET_QC();
|
||||
return ((int64_t)x >> 63) ^ 0x7fffffff;
|
||||
return (uint32_t)((int64_t)x >> 63) ^ 0x7fffffff;
|
||||
}
|
||||
return x;
|
||||
return (uint32_t)x;
|
||||
}
|
||||
|
||||
uint64_t HELPER(neon_widen_u8)(uint32_t x)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1099,144 +1099,18 @@ DO_2SH(VRSHR_S, gen_gvec_srshr)
|
||||
DO_2SH(VRSHR_U, gen_gvec_urshr)
|
||||
DO_2SH(VRSRA_S, gen_gvec_srsra)
|
||||
DO_2SH(VRSRA_U, gen_gvec_ursra)
|
||||
|
||||
static bool trans_VSHR_S_2sh(DisasContext *s, arg_2reg_shift *a)
|
||||
{
|
||||
/* Signed shift out of range results in all-sign-bits */
|
||||
a->shift = MIN(a->shift, (8 << a->size) - 1);
|
||||
return do_vector_2sh(s, a, tcg_gen_gvec_sari);
|
||||
}
|
||||
|
||||
static void gen_zero_rd_2sh(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
|
||||
int64_t shift, uint32_t oprsz, uint32_t maxsz)
|
||||
{
|
||||
tcg_gen_gvec_dup_imm(vece, rd_ofs, oprsz, maxsz, 0);
|
||||
}
|
||||
|
||||
static bool trans_VSHR_U_2sh(DisasContext *s, arg_2reg_shift *a)
|
||||
{
|
||||
/* Shift out of range is architecturally valid and results in zero. */
|
||||
if (a->shift >= (8 << a->size)) {
|
||||
return do_vector_2sh(s, a, gen_zero_rd_2sh);
|
||||
} else {
|
||||
return do_vector_2sh(s, a, tcg_gen_gvec_shri);
|
||||
}
|
||||
}
|
||||
|
||||
static bool do_2shift_env_64(DisasContext *s, arg_2reg_shift *a,
|
||||
NeonGenTwo64OpEnvFn *fn)
|
||||
{
|
||||
/*
|
||||
* 2-reg-and-shift operations, size == 3 case, where the
|
||||
* function needs to be passed tcg_env.
|
||||
*/
|
||||
TCGv_i64 constimm;
|
||||
int pass;
|
||||
|
||||
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* UNDEF accesses to D16-D31 if they don't exist. */
|
||||
if (!dc_isar_feature(aa32_simd_r32, s) &&
|
||||
((a->vd | a->vm) & 0x10)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((a->vm | a->vd) & a->q) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!vfp_access_check(s)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* To avoid excessive duplication of ops we implement shift
|
||||
* by immediate using the variable shift operations.
|
||||
*/
|
||||
constimm = tcg_constant_i64(dup_const(a->size, a->shift));
|
||||
|
||||
for (pass = 0; pass < a->q + 1; pass++) {
|
||||
TCGv_i64 tmp = tcg_temp_new_i64();
|
||||
|
||||
read_neon_element64(tmp, a->vm, pass, MO_64);
|
||||
fn(tmp, tcg_env, tmp, constimm);
|
||||
write_neon_element64(tmp, a->vd, pass, MO_64);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool do_2shift_env_32(DisasContext *s, arg_2reg_shift *a,
|
||||
NeonGenTwoOpEnvFn *fn)
|
||||
{
|
||||
/*
|
||||
* 2-reg-and-shift operations, size < 3 case, where the
|
||||
* helper needs to be passed tcg_env.
|
||||
*/
|
||||
TCGv_i32 constimm, tmp;
|
||||
int pass;
|
||||
|
||||
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* UNDEF accesses to D16-D31 if they don't exist. */
|
||||
if (!dc_isar_feature(aa32_simd_r32, s) &&
|
||||
((a->vd | a->vm) & 0x10)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((a->vm | a->vd) & a->q) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!vfp_access_check(s)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* To avoid excessive duplication of ops we implement shift
|
||||
* by immediate using the variable shift operations.
|
||||
*/
|
||||
constimm = tcg_constant_i32(dup_const(a->size, a->shift));
|
||||
tmp = tcg_temp_new_i32();
|
||||
|
||||
for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
|
||||
read_neon_element32(tmp, a->vm, pass, MO_32);
|
||||
fn(tmp, tcg_env, tmp, constimm);
|
||||
write_neon_element32(tmp, a->vd, pass, MO_32);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define DO_2SHIFT_ENV(INSN, FUNC) \
|
||||
static bool trans_##INSN##_64_2sh(DisasContext *s, arg_2reg_shift *a) \
|
||||
{ \
|
||||
return do_2shift_env_64(s, a, gen_helper_neon_##FUNC##64); \
|
||||
} \
|
||||
static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \
|
||||
{ \
|
||||
static NeonGenTwoOpEnvFn * const fns[] = { \
|
||||
gen_helper_neon_##FUNC##8, \
|
||||
gen_helper_neon_##FUNC##16, \
|
||||
gen_helper_neon_##FUNC##32, \
|
||||
}; \
|
||||
assert(a->size < ARRAY_SIZE(fns)); \
|
||||
return do_2shift_env_32(s, a, fns[a->size]); \
|
||||
}
|
||||
|
||||
DO_2SHIFT_ENV(VQSHLU, qshlu_s)
|
||||
DO_2SHIFT_ENV(VQSHL_U, qshl_u)
|
||||
DO_2SHIFT_ENV(VQSHL_S, qshl_s)
|
||||
DO_2SH(VSHR_S, gen_gvec_sshr)
|
||||
DO_2SH(VSHR_U, gen_gvec_ushr)
|
||||
DO_2SH(VQSHLU, gen_neon_sqshlui)
|
||||
DO_2SH(VQSHL_U, gen_neon_uqshli)
|
||||
DO_2SH(VQSHL_S, gen_neon_sqshli)
|
||||
|
||||
static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a,
|
||||
NeonGenTwo64OpFn *shiftfn,
|
||||
NeonGenNarrowEnvFn *narrowfn)
|
||||
NeonGenOne64OpEnvFn *narrowfn)
|
||||
{
|
||||
/* 2-reg-and-shift narrowing-shift operations, size == 3 case */
|
||||
TCGv_i64 constimm, rm1, rm2;
|
||||
TCGv_i32 rd;
|
||||
TCGv_i64 constimm, rm1, rm2, rd;
|
||||
|
||||
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
|
||||
return false;
|
||||
@ -1263,7 +1137,7 @@ static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a,
|
||||
constimm = tcg_constant_i64(-a->shift);
|
||||
rm1 = tcg_temp_new_i64();
|
||||
rm2 = tcg_temp_new_i64();
|
||||
rd = tcg_temp_new_i32();
|
||||
rd = tcg_temp_new_i64();
|
||||
|
||||
/* Load both inputs first to avoid potential overwrite if rm == rd */
|
||||
read_neon_element64(rm1, a->vm, 0, MO_64);
|
||||
@ -1271,18 +1145,18 @@ static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a,
|
||||
|
||||
shiftfn(rm1, rm1, constimm);
|
||||
narrowfn(rd, tcg_env, rm1);
|
||||
write_neon_element32(rd, a->vd, 0, MO_32);
|
||||
write_neon_element64(rd, a->vd, 0, MO_32);
|
||||
|
||||
shiftfn(rm2, rm2, constimm);
|
||||
narrowfn(rd, tcg_env, rm2);
|
||||
write_neon_element32(rd, a->vd, 1, MO_32);
|
||||
write_neon_element64(rd, a->vd, 1, MO_32);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a,
|
||||
NeonGenTwoOpFn *shiftfn,
|
||||
NeonGenNarrowEnvFn *narrowfn)
|
||||
NeonGenOne64OpEnvFn *narrowfn)
|
||||
{
|
||||
/* 2-reg-and-shift narrowing-shift operations, size < 3 case */
|
||||
TCGv_i32 constimm, rm1, rm2, rm3, rm4;
|
||||
@ -1337,16 +1211,16 @@ static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a,
|
||||
|
||||
tcg_gen_concat_i32_i64(rtmp, rm1, rm2);
|
||||
|
||||
narrowfn(rm1, tcg_env, rtmp);
|
||||
write_neon_element32(rm1, a->vd, 0, MO_32);
|
||||
narrowfn(rtmp, tcg_env, rtmp);
|
||||
write_neon_element64(rtmp, a->vd, 0, MO_32);
|
||||
|
||||
shiftfn(rm3, rm3, constimm);
|
||||
shiftfn(rm4, rm4, constimm);
|
||||
|
||||
tcg_gen_concat_i32_i64(rtmp, rm3, rm4);
|
||||
|
||||
narrowfn(rm3, tcg_env, rtmp);
|
||||
write_neon_element32(rm3, a->vd, 1, MO_32);
|
||||
narrowfn(rtmp, tcg_env, rtmp);
|
||||
write_neon_element64(rtmp, a->vd, 1, MO_32);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1361,17 +1235,17 @@ static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a,
|
||||
return do_2shift_narrow_32(s, a, FUNC, NARROWFUNC); \
|
||||
}
|
||||
|
||||
static void gen_neon_narrow_u32(TCGv_i32 dest, TCGv_ptr env, TCGv_i64 src)
|
||||
static void gen_neon_narrow_u32(TCGv_i64 dest, TCGv_ptr env, TCGv_i64 src)
|
||||
{
|
||||
tcg_gen_extrl_i64_i32(dest, src);
|
||||
tcg_gen_ext32u_i64(dest, src);
|
||||
}
|
||||
|
||||
static void gen_neon_narrow_u16(TCGv_i32 dest, TCGv_ptr env, TCGv_i64 src)
|
||||
static void gen_neon_narrow_u16(TCGv_i64 dest, TCGv_ptr env, TCGv_i64 src)
|
||||
{
|
||||
gen_helper_neon_narrow_u16(dest, src);
|
||||
}
|
||||
|
||||
static void gen_neon_narrow_u8(TCGv_i32 dest, TCGv_ptr env, TCGv_i64 src)
|
||||
static void gen_neon_narrow_u8(TCGv_i64 dest, TCGv_ptr env, TCGv_i64 src)
|
||||
{
|
||||
gen_helper_neon_narrow_u8(dest, src);
|
||||
}
|
||||
@ -2962,10 +2836,9 @@ static bool trans_VZIP(DisasContext *s, arg_2misc *a)
|
||||
}
|
||||
|
||||
static bool do_vmovn(DisasContext *s, arg_2misc *a,
|
||||
NeonGenNarrowEnvFn *narrowfn)
|
||||
NeonGenOne64OpEnvFn *narrowfn)
|
||||
{
|
||||
TCGv_i64 rm;
|
||||
TCGv_i32 rd0, rd1;
|
||||
TCGv_i64 rm, rd0, rd1;
|
||||
|
||||
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
|
||||
return false;
|
||||
@ -2990,22 +2863,22 @@ static bool do_vmovn(DisasContext *s, arg_2misc *a,
|
||||
}
|
||||
|
||||
rm = tcg_temp_new_i64();
|
||||
rd0 = tcg_temp_new_i32();
|
||||
rd1 = tcg_temp_new_i32();
|
||||
rd0 = tcg_temp_new_i64();
|
||||
rd1 = tcg_temp_new_i64();
|
||||
|
||||
read_neon_element64(rm, a->vm, 0, MO_64);
|
||||
narrowfn(rd0, tcg_env, rm);
|
||||
read_neon_element64(rm, a->vm, 1, MO_64);
|
||||
narrowfn(rd1, tcg_env, rm);
|
||||
write_neon_element32(rd0, a->vd, 0, MO_32);
|
||||
write_neon_element32(rd1, a->vd, 1, MO_32);
|
||||
write_neon_element64(rd0, a->vd, 0, MO_32);
|
||||
write_neon_element64(rd1, a->vd, 1, MO_32);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define DO_VMOVN(INSN, FUNC) \
|
||||
static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
|
||||
{ \
|
||||
static NeonGenNarrowEnvFn * const narrowfn[] = { \
|
||||
static NeonGenOne64OpEnvFn * const narrowfn[] = { \
|
||||
FUNC##8, \
|
||||
FUNC##16, \
|
||||
FUNC##32, \
|
||||
|
@ -6081,9 +6081,9 @@ static void gen_sshll_vec(unsigned vece, TCGv_vec d, TCGv_vec n, int64_t imm)
|
||||
|
||||
if (top) {
|
||||
if (shl == halfbits) {
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
tcg_gen_dupi_vec(vece, t, MAKE_64BIT_MASK(halfbits, halfbits));
|
||||
tcg_gen_and_vec(vece, d, n, t);
|
||||
tcg_gen_and_vec(vece, d, n,
|
||||
tcg_constant_vec_matching(d, vece,
|
||||
MAKE_64BIT_MASK(halfbits, halfbits)));
|
||||
} else {
|
||||
tcg_gen_sari_vec(vece, d, n, halfbits);
|
||||
tcg_gen_shli_vec(vece, d, d, shl);
|
||||
@ -6138,18 +6138,18 @@ static void gen_ushll_vec(unsigned vece, TCGv_vec d, TCGv_vec n, int64_t imm)
|
||||
|
||||
if (top) {
|
||||
if (shl == halfbits) {
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
tcg_gen_dupi_vec(vece, t, MAKE_64BIT_MASK(halfbits, halfbits));
|
||||
tcg_gen_and_vec(vece, d, n, t);
|
||||
tcg_gen_and_vec(vece, d, n,
|
||||
tcg_constant_vec_matching(d, vece,
|
||||
MAKE_64BIT_MASK(halfbits, halfbits)));
|
||||
} else {
|
||||
tcg_gen_shri_vec(vece, d, n, halfbits);
|
||||
tcg_gen_shli_vec(vece, d, d, shl);
|
||||
}
|
||||
} else {
|
||||
if (shl == 0) {
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
tcg_gen_dupi_vec(vece, t, MAKE_64BIT_MASK(0, halfbits));
|
||||
tcg_gen_and_vec(vece, d, n, t);
|
||||
tcg_gen_and_vec(vece, d, n,
|
||||
tcg_constant_vec_matching(d, vece,
|
||||
MAKE_64BIT_MASK(0, halfbits)));
|
||||
} else {
|
||||
tcg_gen_shli_vec(vece, d, n, halfbits);
|
||||
tcg_gen_shri_vec(vece, d, d, halfbits - shl);
|
||||
@ -6317,18 +6317,14 @@ static const TCGOpcode sqxtn_list[] = {
|
||||
|
||||
static void gen_sqxtnb_vec(unsigned vece, TCGv_vec d, TCGv_vec n)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
int halfbits = 4 << vece;
|
||||
int64_t mask = (1ull << halfbits) - 1;
|
||||
int64_t min = -1ull << (halfbits - 1);
|
||||
int64_t max = -min - 1;
|
||||
|
||||
tcg_gen_dupi_vec(vece, t, min);
|
||||
tcg_gen_smax_vec(vece, d, n, t);
|
||||
tcg_gen_dupi_vec(vece, t, max);
|
||||
tcg_gen_smin_vec(vece, d, d, t);
|
||||
tcg_gen_dupi_vec(vece, t, mask);
|
||||
tcg_gen_and_vec(vece, d, d, t);
|
||||
tcg_gen_smax_vec(vece, d, n, tcg_constant_vec_matching(d, vece, min));
|
||||
tcg_gen_smin_vec(vece, d, d, tcg_constant_vec_matching(d, vece, max));
|
||||
tcg_gen_and_vec(vece, d, d, tcg_constant_vec_matching(d, vece, mask));
|
||||
}
|
||||
|
||||
static const GVecGen2 sqxtnb_ops[3] = {
|
||||
@ -6349,19 +6345,15 @@ TRANS_FEAT(SQXTNB, aa64_sve2, do_narrow_extract, a, sqxtnb_ops)
|
||||
|
||||
static void gen_sqxtnt_vec(unsigned vece, TCGv_vec d, TCGv_vec n)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
int halfbits = 4 << vece;
|
||||
int64_t mask = (1ull << halfbits) - 1;
|
||||
int64_t min = -1ull << (halfbits - 1);
|
||||
int64_t max = -min - 1;
|
||||
|
||||
tcg_gen_dupi_vec(vece, t, min);
|
||||
tcg_gen_smax_vec(vece, n, n, t);
|
||||
tcg_gen_dupi_vec(vece, t, max);
|
||||
tcg_gen_smin_vec(vece, n, n, t);
|
||||
tcg_gen_smax_vec(vece, n, n, tcg_constant_vec_matching(d, vece, min));
|
||||
tcg_gen_smin_vec(vece, n, n, tcg_constant_vec_matching(d, vece, max));
|
||||
tcg_gen_shli_vec(vece, n, n, halfbits);
|
||||
tcg_gen_dupi_vec(vece, t, mask);
|
||||
tcg_gen_bitsel_vec(vece, d, t, d, n);
|
||||
tcg_gen_bitsel_vec(vece, d, tcg_constant_vec_matching(d, vece, mask), d, n);
|
||||
}
|
||||
|
||||
static const GVecGen2 sqxtnt_ops[3] = {
|
||||
@ -6389,12 +6381,10 @@ static const TCGOpcode uqxtn_list[] = {
|
||||
|
||||
static void gen_uqxtnb_vec(unsigned vece, TCGv_vec d, TCGv_vec n)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
int halfbits = 4 << vece;
|
||||
int64_t max = (1ull << halfbits) - 1;
|
||||
|
||||
tcg_gen_dupi_vec(vece, t, max);
|
||||
tcg_gen_umin_vec(vece, d, n, t);
|
||||
tcg_gen_umin_vec(vece, d, n, tcg_constant_vec_matching(d, vece, max));
|
||||
}
|
||||
|
||||
static const GVecGen2 uqxtnb_ops[3] = {
|
||||
@ -6415,14 +6405,13 @@ TRANS_FEAT(UQXTNB, aa64_sve2, do_narrow_extract, a, uqxtnb_ops)
|
||||
|
||||
static void gen_uqxtnt_vec(unsigned vece, TCGv_vec d, TCGv_vec n)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
int halfbits = 4 << vece;
|
||||
int64_t max = (1ull << halfbits) - 1;
|
||||
TCGv_vec maxv = tcg_constant_vec_matching(d, vece, max);
|
||||
|
||||
tcg_gen_dupi_vec(vece, t, max);
|
||||
tcg_gen_umin_vec(vece, n, n, t);
|
||||
tcg_gen_umin_vec(vece, n, n, maxv);
|
||||
tcg_gen_shli_vec(vece, n, n, halfbits);
|
||||
tcg_gen_bitsel_vec(vece, d, t, d, n);
|
||||
tcg_gen_bitsel_vec(vece, d, maxv, d, n);
|
||||
}
|
||||
|
||||
static const GVecGen2 uqxtnt_ops[3] = {
|
||||
@ -6450,14 +6439,11 @@ static const TCGOpcode sqxtun_list[] = {
|
||||
|
||||
static void gen_sqxtunb_vec(unsigned vece, TCGv_vec d, TCGv_vec n)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
int halfbits = 4 << vece;
|
||||
int64_t max = (1ull << halfbits) - 1;
|
||||
|
||||
tcg_gen_dupi_vec(vece, t, 0);
|
||||
tcg_gen_smax_vec(vece, d, n, t);
|
||||
tcg_gen_dupi_vec(vece, t, max);
|
||||
tcg_gen_umin_vec(vece, d, d, t);
|
||||
tcg_gen_smax_vec(vece, d, n, tcg_constant_vec_matching(d, vece, 0));
|
||||
tcg_gen_umin_vec(vece, d, d, tcg_constant_vec_matching(d, vece, max));
|
||||
}
|
||||
|
||||
static const GVecGen2 sqxtunb_ops[3] = {
|
||||
@ -6478,16 +6464,14 @@ TRANS_FEAT(SQXTUNB, aa64_sve2, do_narrow_extract, a, sqxtunb_ops)
|
||||
|
||||
static void gen_sqxtunt_vec(unsigned vece, TCGv_vec d, TCGv_vec n)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
int halfbits = 4 << vece;
|
||||
int64_t max = (1ull << halfbits) - 1;
|
||||
TCGv_vec maxv = tcg_constant_vec_matching(d, vece, max);
|
||||
|
||||
tcg_gen_dupi_vec(vece, t, 0);
|
||||
tcg_gen_smax_vec(vece, n, n, t);
|
||||
tcg_gen_dupi_vec(vece, t, max);
|
||||
tcg_gen_umin_vec(vece, n, n, t);
|
||||
tcg_gen_smax_vec(vece, n, n, tcg_constant_vec_matching(d, vece, 0));
|
||||
tcg_gen_umin_vec(vece, n, n, maxv);
|
||||
tcg_gen_shli_vec(vece, n, n, halfbits);
|
||||
tcg_gen_bitsel_vec(vece, d, t, d, n);
|
||||
tcg_gen_bitsel_vec(vece, d, maxv, d, n);
|
||||
}
|
||||
|
||||
static const GVecGen2 sqxtunt_ops[3] = {
|
||||
@ -6551,13 +6535,11 @@ static void gen_shrnb64_i64(TCGv_i64 d, TCGv_i64 n, int64_t shr)
|
||||
|
||||
static void gen_shrnb_vec(unsigned vece, TCGv_vec d, TCGv_vec n, int64_t shr)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
int halfbits = 4 << vece;
|
||||
uint64_t mask = MAKE_64BIT_MASK(0, halfbits);
|
||||
|
||||
tcg_gen_shri_vec(vece, n, n, shr);
|
||||
tcg_gen_dupi_vec(vece, t, mask);
|
||||
tcg_gen_and_vec(vece, d, n, t);
|
||||
tcg_gen_and_vec(vece, d, n, tcg_constant_vec_matching(d, vece, mask));
|
||||
}
|
||||
|
||||
static const TCGOpcode shrnb_vec_list[] = { INDEX_op_shri_vec, 0 };
|
||||
@ -6609,13 +6591,11 @@ static void gen_shrnt64_i64(TCGv_i64 d, TCGv_i64 n, int64_t shr)
|
||||
|
||||
static void gen_shrnt_vec(unsigned vece, TCGv_vec d, TCGv_vec n, int64_t shr)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
int halfbits = 4 << vece;
|
||||
uint64_t mask = MAKE_64BIT_MASK(0, halfbits);
|
||||
|
||||
tcg_gen_shli_vec(vece, n, n, halfbits - shr);
|
||||
tcg_gen_dupi_vec(vece, t, mask);
|
||||
tcg_gen_bitsel_vec(vece, d, t, d, n);
|
||||
tcg_gen_bitsel_vec(vece, d, tcg_constant_vec_matching(d, vece, mask), d, n);
|
||||
}
|
||||
|
||||
static const TCGOpcode shrnt_vec_list[] = { INDEX_op_shli_vec, 0 };
|
||||
@ -6658,14 +6638,12 @@ TRANS_FEAT(RSHRNT, aa64_sve2, do_shr_narrow, a, rshrnt_ops)
|
||||
static void gen_sqshrunb_vec(unsigned vece, TCGv_vec d,
|
||||
TCGv_vec n, int64_t shr)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
int halfbits = 4 << vece;
|
||||
uint64_t max = MAKE_64BIT_MASK(0, halfbits);
|
||||
|
||||
tcg_gen_sari_vec(vece, n, n, shr);
|
||||
tcg_gen_dupi_vec(vece, t, 0);
|
||||
tcg_gen_smax_vec(vece, n, n, t);
|
||||
tcg_gen_dupi_vec(vece, t, MAKE_64BIT_MASK(0, halfbits));
|
||||
tcg_gen_umin_vec(vece, d, n, t);
|
||||
tcg_gen_smax_vec(vece, n, n, tcg_constant_vec_matching(d, vece, 0));
|
||||
tcg_gen_umin_vec(vece, d, n, tcg_constant_vec_matching(d, vece, max));
|
||||
}
|
||||
|
||||
static const TCGOpcode sqshrunb_vec_list[] = {
|
||||
@ -6690,16 +6668,15 @@ TRANS_FEAT(SQSHRUNB, aa64_sve2, do_shr_narrow, a, sqshrunb_ops)
|
||||
static void gen_sqshrunt_vec(unsigned vece, TCGv_vec d,
|
||||
TCGv_vec n, int64_t shr)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
int halfbits = 4 << vece;
|
||||
uint64_t max = MAKE_64BIT_MASK(0, halfbits);
|
||||
TCGv_vec maxv = tcg_constant_vec_matching(d, vece, max);
|
||||
|
||||
tcg_gen_sari_vec(vece, n, n, shr);
|
||||
tcg_gen_dupi_vec(vece, t, 0);
|
||||
tcg_gen_smax_vec(vece, n, n, t);
|
||||
tcg_gen_dupi_vec(vece, t, MAKE_64BIT_MASK(0, halfbits));
|
||||
tcg_gen_umin_vec(vece, n, n, t);
|
||||
tcg_gen_smax_vec(vece, n, n, tcg_constant_vec_matching(d, vece, 0));
|
||||
tcg_gen_umin_vec(vece, n, n, maxv);
|
||||
tcg_gen_shli_vec(vece, n, n, halfbits);
|
||||
tcg_gen_bitsel_vec(vece, d, t, d, n);
|
||||
tcg_gen_bitsel_vec(vece, d, maxv, d, n);
|
||||
}
|
||||
|
||||
static const TCGOpcode sqshrunt_vec_list[] = {
|
||||
@ -6742,18 +6719,15 @@ TRANS_FEAT(SQRSHRUNT, aa64_sve2, do_shr_narrow, a, sqrshrunt_ops)
|
||||
static void gen_sqshrnb_vec(unsigned vece, TCGv_vec d,
|
||||
TCGv_vec n, int64_t shr)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
int halfbits = 4 << vece;
|
||||
int64_t max = MAKE_64BIT_MASK(0, halfbits - 1);
|
||||
int64_t min = -max - 1;
|
||||
int64_t mask = MAKE_64BIT_MASK(0, halfbits);
|
||||
|
||||
tcg_gen_sari_vec(vece, n, n, shr);
|
||||
tcg_gen_dupi_vec(vece, t, min);
|
||||
tcg_gen_smax_vec(vece, n, n, t);
|
||||
tcg_gen_dupi_vec(vece, t, max);
|
||||
tcg_gen_smin_vec(vece, n, n, t);
|
||||
tcg_gen_dupi_vec(vece, t, MAKE_64BIT_MASK(0, halfbits));
|
||||
tcg_gen_and_vec(vece, d, n, t);
|
||||
tcg_gen_smax_vec(vece, n, n, tcg_constant_vec_matching(d, vece, min));
|
||||
tcg_gen_smin_vec(vece, n, n, tcg_constant_vec_matching(d, vece, max));
|
||||
tcg_gen_and_vec(vece, d, n, tcg_constant_vec_matching(d, vece, mask));
|
||||
}
|
||||
|
||||
static const TCGOpcode sqshrnb_vec_list[] = {
|
||||
@ -6778,19 +6752,16 @@ TRANS_FEAT(SQSHRNB, aa64_sve2, do_shr_narrow, a, sqshrnb_ops)
|
||||
static void gen_sqshrnt_vec(unsigned vece, TCGv_vec d,
|
||||
TCGv_vec n, int64_t shr)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
int halfbits = 4 << vece;
|
||||
int64_t max = MAKE_64BIT_MASK(0, halfbits - 1);
|
||||
int64_t min = -max - 1;
|
||||
int64_t mask = MAKE_64BIT_MASK(0, halfbits);
|
||||
|
||||
tcg_gen_sari_vec(vece, n, n, shr);
|
||||
tcg_gen_dupi_vec(vece, t, min);
|
||||
tcg_gen_smax_vec(vece, n, n, t);
|
||||
tcg_gen_dupi_vec(vece, t, max);
|
||||
tcg_gen_smin_vec(vece, n, n, t);
|
||||
tcg_gen_smax_vec(vece, n, n, tcg_constant_vec_matching(d, vece, min));
|
||||
tcg_gen_smin_vec(vece, n, n, tcg_constant_vec_matching(d, vece, max));
|
||||
tcg_gen_shli_vec(vece, n, n, halfbits);
|
||||
tcg_gen_dupi_vec(vece, t, MAKE_64BIT_MASK(0, halfbits));
|
||||
tcg_gen_bitsel_vec(vece, d, t, d, n);
|
||||
tcg_gen_bitsel_vec(vece, d, tcg_constant_vec_matching(d, vece, mask), d, n);
|
||||
}
|
||||
|
||||
static const TCGOpcode sqshrnt_vec_list[] = {
|
||||
@ -6833,12 +6804,11 @@ TRANS_FEAT(SQRSHRNT, aa64_sve2, do_shr_narrow, a, sqrshrnt_ops)
|
||||
static void gen_uqshrnb_vec(unsigned vece, TCGv_vec d,
|
||||
TCGv_vec n, int64_t shr)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
int halfbits = 4 << vece;
|
||||
int64_t max = MAKE_64BIT_MASK(0, halfbits);
|
||||
|
||||
tcg_gen_shri_vec(vece, n, n, shr);
|
||||
tcg_gen_dupi_vec(vece, t, MAKE_64BIT_MASK(0, halfbits));
|
||||
tcg_gen_umin_vec(vece, d, n, t);
|
||||
tcg_gen_umin_vec(vece, d, n, tcg_constant_vec_matching(d, vece, max));
|
||||
}
|
||||
|
||||
static const TCGOpcode uqshrnb_vec_list[] = {
|
||||
@ -6863,14 +6833,14 @@ TRANS_FEAT(UQSHRNB, aa64_sve2, do_shr_narrow, a, uqshrnb_ops)
|
||||
static void gen_uqshrnt_vec(unsigned vece, TCGv_vec d,
|
||||
TCGv_vec n, int64_t shr)
|
||||
{
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||
int halfbits = 4 << vece;
|
||||
int64_t max = MAKE_64BIT_MASK(0, halfbits);
|
||||
TCGv_vec maxv = tcg_constant_vec_matching(d, vece, max);
|
||||
|
||||
tcg_gen_shri_vec(vece, n, n, shr);
|
||||
tcg_gen_dupi_vec(vece, t, MAKE_64BIT_MASK(0, halfbits));
|
||||
tcg_gen_umin_vec(vece, n, n, t);
|
||||
tcg_gen_umin_vec(vece, n, n, maxv);
|
||||
tcg_gen_shli_vec(vece, n, n, halfbits);
|
||||
tcg_gen_bitsel_vec(vece, d, t, d, n);
|
||||
tcg_gen_bitsel_vec(vece, d, maxv, d, n);
|
||||
}
|
||||
|
||||
static const TCGOpcode uqshrnt_vec_list[] = {
|
||||
|
@ -471,6 +471,13 @@ void gen_neon_sqrshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||
void gen_neon_uqrshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
|
||||
|
||||
void gen_neon_sqshli(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||
int64_t c, uint32_t opr_sz, uint32_t max_sz);
|
||||
void gen_neon_uqshli(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||
int64_t c, uint32_t opr_sz, uint32_t max_sz);
|
||||
void gen_neon_sqshlui(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||
int64_t c, uint32_t opr_sz, uint32_t max_sz);
|
||||
|
||||
void gen_gvec_shadd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
|
||||
void gen_gvec_uhadd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||
@ -514,6 +521,11 @@ void gen_sqsub_d(TCGv_i64 d, TCGv_i64 q, TCGv_i64 a, TCGv_i64 b);
|
||||
void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
|
||||
|
||||
void gen_gvec_sshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
|
||||
int64_t shift, uint32_t opr_sz, uint32_t max_sz);
|
||||
void gen_gvec_ushr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
|
||||
int64_t shift, uint32_t opr_sz, uint32_t max_sz);
|
||||
|
||||
void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
|
||||
int64_t shift, uint32_t opr_sz, uint32_t max_sz);
|
||||
void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
|
||||
@ -593,13 +605,13 @@ typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
|
||||
typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64);
|
||||
typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64);
|
||||
typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
|
||||
typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
|
||||
typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
|
||||
typedef void NeonGenTwoOpWidenFn(TCGv_i64, TCGv_i32, TCGv_i32);
|
||||
typedef void NeonGenOneSingleOpFn(TCGv_i32, TCGv_i32, TCGv_ptr);
|
||||
typedef void NeonGenTwoSingleOpFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
|
||||
typedef void NeonGenTwoDoubleOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
|
||||
typedef void NeonGenOne64OpFn(TCGv_i64, TCGv_i64);
|
||||
typedef void NeonGenOne64OpEnvFn(TCGv_i64, TCGv_env, TCGv_i64);
|
||||
typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
|
||||
typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
|
||||
typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Functional test that boots a Linux kernel and checks the console
|
||||
# Functional test that boots a kernel and checks the console
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2023-2024 Linaro Ltd.
|
||||
# SPDX-FileContributor: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
@ -110,16 +110,17 @@ class Aarch64SbsarefMachine(QemuSystemTest):
|
||||
# This tests the whole boot chain from EFI to Userspace
|
||||
# We only boot a whole OS for the current top level CPU and GIC
|
||||
# Other test profiles should use more minimal boots
|
||||
def boot_alpine_linux(self, cpu):
|
||||
def boot_alpine_linux(self, cpu=None):
|
||||
self.fetch_firmware()
|
||||
|
||||
iso_path = self.ASSET_ALPINE_ISO.fetch()
|
||||
|
||||
self.vm.set_console()
|
||||
self.vm.add_args(
|
||||
"-cpu", cpu,
|
||||
"-drive", f"file={iso_path},media=cdrom,format=raw",
|
||||
)
|
||||
if cpu:
|
||||
self.vm.add_args("-cpu", cpu)
|
||||
|
||||
self.vm.launch()
|
||||
wait_for_console_pattern(self, "Welcome to Alpine Linux 3.17")
|
||||
@ -127,8 +128,8 @@ class Aarch64SbsarefMachine(QemuSystemTest):
|
||||
def test_sbsaref_alpine_linux_cortex_a57(self):
|
||||
self.boot_alpine_linux("cortex-a57")
|
||||
|
||||
def test_sbsaref_alpine_linux_neoverse_n1(self):
|
||||
self.boot_alpine_linux("neoverse-n1")
|
||||
def test_sbsaref_alpine_linux_default_cpu(self):
|
||||
self.boot_alpine_linux()
|
||||
|
||||
def test_sbsaref_alpine_linux_max_pauth_off(self):
|
||||
self.boot_alpine_linux("max,pauth=off")
|
||||
@ -136,50 +137,53 @@ class Aarch64SbsarefMachine(QemuSystemTest):
|
||||
def test_sbsaref_alpine_linux_max_pauth_impdef(self):
|
||||
self.boot_alpine_linux("max,pauth-impdef=on")
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'), 'Test might timeout')
|
||||
@skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'),
|
||||
'Test might timeout due to PAuth emulation')
|
||||
def test_sbsaref_alpine_linux_max(self):
|
||||
self.boot_alpine_linux("max")
|
||||
|
||||
|
||||
ASSET_OPENBSD_ISO = Asset(
|
||||
('https://cdn.openbsd.org/pub/OpenBSD/7.3/arm64/miniroot73.img'),
|
||||
'7fc2c75401d6f01fbfa25f4953f72ad7d7c18650056d30755c44b9c129b707e5')
|
||||
ASSET_FREEBSD_ISO = Asset(
|
||||
('https://download.freebsd.org/releases/arm64/aarch64/ISO-IMAGES/'
|
||||
'14.1/FreeBSD-14.1-RELEASE-arm64-aarch64-bootonly.iso'),
|
||||
'44cdbae275ef1bb6dab1d5fbb59473d4f741e1c8ea8a80fd9e906b531d6ad461')
|
||||
|
||||
# This tests the whole boot chain from EFI to Userspace
|
||||
# We only boot a whole OS for the current top level CPU and GIC
|
||||
# Other test profiles should use more minimal boots
|
||||
def boot_openbsd73(self, cpu):
|
||||
def boot_freebsd14(self, cpu=None):
|
||||
self.fetch_firmware()
|
||||
|
||||
img_path = self.ASSET_OPENBSD_ISO.fetch()
|
||||
img_path = self.ASSET_FREEBSD_ISO.fetch()
|
||||
|
||||
self.vm.set_console()
|
||||
self.vm.add_args(
|
||||
"-cpu", cpu,
|
||||
"-drive", f"file={img_path},format=raw,snapshot=on",
|
||||
)
|
||||
if cpu:
|
||||
self.vm.add_args("-cpu", cpu)
|
||||
|
||||
self.vm.launch()
|
||||
wait_for_console_pattern(self,
|
||||
"Welcome to the OpenBSD/arm64"
|
||||
" 7.3 installation program.")
|
||||
wait_for_console_pattern(self, 'Welcome to FreeBSD!')
|
||||
|
||||
def test_sbsaref_openbsd73_cortex_a57(self):
|
||||
self.boot_openbsd73("cortex-a57")
|
||||
def test_sbsaref_freebsd14_cortex_a57(self):
|
||||
self.boot_freebsd14("cortex-a57")
|
||||
|
||||
def test_sbsaref_openbsd73_neoverse_n1(self):
|
||||
self.boot_openbsd73("neoverse-n1")
|
||||
def test_sbsaref_freebsd14_default_cpu(self):
|
||||
self.boot_freebsd14()
|
||||
|
||||
def test_sbsaref_openbsd73_max_pauth_off(self):
|
||||
self.boot_openbsd73("max,pauth=off")
|
||||
def test_sbsaref_freebsd14_max_pauth_off(self):
|
||||
self.boot_freebsd14("max,pauth=off")
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'), 'Test might timeout')
|
||||
def test_sbsaref_openbsd73_max_pauth_impdef(self):
|
||||
self.boot_openbsd73("max,pauth-impdef=on")
|
||||
@skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'),
|
||||
'Test might timeout due to PAuth emulation')
|
||||
def test_sbsaref_freebsd14_max_pauth_impdef(self):
|
||||
self.boot_freebsd14("max,pauth-impdef=on")
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'), 'Test might timeout')
|
||||
def test_sbsaref_openbsd73_max(self):
|
||||
self.boot_openbsd73("max")
|
||||
@skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'),
|
||||
'Test might timeout due to PAuth emulation')
|
||||
def test_sbsaref_freebsd14_max(self):
|
||||
self.boot_freebsd14("max")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -36,6 +36,8 @@ REG32(GTPR, 0x10)
|
||||
REG32(RTOR, 0x14)
|
||||
REG32(RQR, 0x18)
|
||||
REG32(ISR, 0x1C)
|
||||
FIELD(ISR, REACK, 22, 1)
|
||||
FIELD(ISR, TEACK, 21, 1)
|
||||
FIELD(ISR, TXE, 7, 1)
|
||||
FIELD(ISR, RXNE, 5, 1)
|
||||
FIELD(ISR, ORE, 3, 1)
|
||||
@ -191,7 +193,7 @@ static void init_uart(QTestState *qts)
|
||||
|
||||
/* Enable the transmitter, the receiver and the USART. */
|
||||
qtest_writel(qts, (USART1_BASE_ADDR + A_CR1),
|
||||
R_CR1_UE_MASK | R_CR1_RE_MASK | R_CR1_TE_MASK);
|
||||
cr1 | R_CR1_UE_MASK | R_CR1_RE_MASK | R_CR1_TE_MASK);
|
||||
}
|
||||
|
||||
static void test_write_read(void)
|
||||
@ -298,6 +300,37 @@ static void test_send_str(void)
|
||||
qtest_quit(qts);
|
||||
}
|
||||
|
||||
static void test_ack(void)
|
||||
{
|
||||
uint32_t cr1;
|
||||
uint32_t isr;
|
||||
QTestState *qts = qtest_init("-M b-l475e-iot01a");
|
||||
|
||||
init_uart(qts);
|
||||
|
||||
cr1 = qtest_readl(qts, (USART1_BASE_ADDR + A_CR1));
|
||||
|
||||
/* Disable the transmitter and receiver. */
|
||||
qtest_writel(qts, (USART1_BASE_ADDR + A_CR1),
|
||||
cr1 & ~(R_CR1_RE_MASK | R_CR1_TE_MASK));
|
||||
|
||||
/* Test ISR ACK for transmitter and receiver disabled */
|
||||
isr = qtest_readl(qts, (USART1_BASE_ADDR + A_ISR));
|
||||
g_assert_false(isr & R_ISR_TEACK_MASK);
|
||||
g_assert_false(isr & R_ISR_REACK_MASK);
|
||||
|
||||
/* Enable the transmitter and receiver. */
|
||||
qtest_writel(qts, (USART1_BASE_ADDR + A_CR1),
|
||||
cr1 | (R_CR1_RE_MASK | R_CR1_TE_MASK));
|
||||
|
||||
/* Test ISR ACK for transmitter and receiver disabled */
|
||||
isr = qtest_readl(qts, (USART1_BASE_ADDR + A_ISR));
|
||||
g_assert_true(isr & R_ISR_TEACK_MASK);
|
||||
g_assert_true(isr & R_ISR_REACK_MASK);
|
||||
|
||||
qtest_quit(qts);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
@ -310,6 +343,7 @@ int main(int argc, char **argv)
|
||||
qtest_add_func("stm32l4x5/usart/send_char", test_send_char);
|
||||
qtest_add_func("stm32l4x5/usart/receive_str", test_receive_str);
|
||||
qtest_add_func("stm32l4x5/usart/send_str", test_send_str);
|
||||
qtest_add_func("stm32l4x5/usart/ack", test_ack);
|
||||
ret = g_test_run();
|
||||
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user