mirror of https://github.com/xemu-project/xemu.git
Recall that the semantics of a Hexagon mem_noshuf packet are that the
store effectively happens before the load. There are two bug fixes in this series. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEENjXHiM5iuR/UxZq0ewJE+xLeRCIFAmLXIT8ACgkQewJE+xLe RCKL7gf9E1NE9EXNVpFUcv9E6SvEnZdqxYotXqNi2MduNKe+d9EYvDMEeNgZLWme ltw9kYuAP41WLTYFQkrx2zCbonYljxEWqouQe8jZUwR78Ig/8GXk0MJ7C4l5AkEy ZMuTMA59nbU98Ss6E9vbafFegWzZVP0SQcoV5YyHleihJU67we5kG8gNmQliUj93 rahG66gKxVbcUGsknSN6OeGjgPG1vD8EQyrTzIw55alD510Ih2C1I2Xhi1eibbfJ B1sQulYJ3Q5qBq6GHlZovsz+c0fPQu4bY8j3G3fDcNCjYYEk37DqPNGKiZhIMjRE DJ5uJhcot7ImCSB3tO5lKKTp9VSY5g== =1Kkg -----END PGP SIGNATURE----- Merge tag 'pull-hex-20220719-1' of https://github.com/quic/qemu into staging Recall that the semantics of a Hexagon mem_noshuf packet are that the store effectively happens before the load. There are two bug fixes in this series. # gpg: Signature made Tue 19 Jul 2022 22:25:19 BST # gpg: using RSA key 3635C788CE62B91FD4C59AB47B0244FB12DE4422 # gpg: Good signature from "Taylor Simpson (Rock on) <tsimpson@quicinc.com>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 3635 C788 CE62 B91F D4C5 9AB4 7B02 44FB 12DE 4422 * tag 'pull-hex-20220719-1' of https://github.com/quic/qemu: Hexagon (target/hexagon) fix bug in mem_noshuf load exception Hexagon (target/hexagon) fix store w/mem_noshuf & predicated load Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
1f64dd76a1
|
@ -339,12 +339,13 @@
|
|||
do { \
|
||||
TCGv LSB = tcg_temp_local_new(); \
|
||||
TCGLabel *label = gen_new_label(); \
|
||||
GET_EA; \
|
||||
tcg_gen_movi_tl(EA, 0); \
|
||||
PRED; \
|
||||
CHECK_NOSHUF_PRED(GET_EA, SIZE, LSB); \
|
||||
PRED_LOAD_CANCEL(LSB, EA); \
|
||||
tcg_gen_movi_tl(RdV, 0); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, label); \
|
||||
fLOAD(1, SIZE, SIGN, EA, RdV); \
|
||||
fLOAD(1, SIZE, SIGN, EA, RdV); \
|
||||
gen_set_label(label); \
|
||||
tcg_temp_free(LSB); \
|
||||
} while (0)
|
||||
|
@ -398,12 +399,13 @@
|
|||
do { \
|
||||
TCGv LSB = tcg_temp_local_new(); \
|
||||
TCGLabel *label = gen_new_label(); \
|
||||
GET_EA; \
|
||||
tcg_gen_movi_tl(EA, 0); \
|
||||
PRED; \
|
||||
CHECK_NOSHUF_PRED(GET_EA, 8, LSB); \
|
||||
PRED_LOAD_CANCEL(LSB, EA); \
|
||||
tcg_gen_movi_i64(RddV, 0); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, label); \
|
||||
fLOAD(1, 8, u, EA, RddV); \
|
||||
fLOAD(1, 8, u, EA, RddV); \
|
||||
gen_set_label(label); \
|
||||
tcg_temp_free(LSB); \
|
||||
} while (0)
|
||||
|
|
|
@ -638,5 +638,12 @@ static void vec_to_qvec(size_t size, intptr_t dstoff, intptr_t srcoff)
|
|||
tcg_temp_free_i64(mask);
|
||||
}
|
||||
|
||||
static void probe_noshuf_load(TCGv va, int s, int mi)
|
||||
{
|
||||
TCGv size = tcg_constant_tl(s);
|
||||
TCGv mem_idx = tcg_constant_tl(mi);
|
||||
gen_helper_probe_noshuf_load(cpu_env, va, size, mem_idx);
|
||||
}
|
||||
|
||||
#include "tcg_funcs_generated.c.inc"
|
||||
#include "tcg_func_table_generated.c.inc"
|
||||
|
|
|
@ -104,6 +104,7 @@ DEF_HELPER_1(vwhist128q, void, env)
|
|||
DEF_HELPER_2(vwhist128m, void, env, s32)
|
||||
DEF_HELPER_2(vwhist128qm, void, env, s32)
|
||||
|
||||
DEF_HELPER_4(probe_noshuf_load, void, env, i32, int, int)
|
||||
DEF_HELPER_2(probe_pkt_scalar_store_s0, void, env, int)
|
||||
DEF_HELPER_2(probe_hvx_stores, void, env, int)
|
||||
DEF_HELPER_3(probe_pkt_scalar_hvx_stores, void, env, int, int)
|
||||
|
|
|
@ -87,11 +87,28 @@
|
|||
*
|
||||
*
|
||||
* For qemu, we look for a load in slot 0 when there is a store in slot 1
|
||||
* in the same packet. When we see this, we call a helper that merges the
|
||||
* bytes from the store buffer with the value loaded from memory.
|
||||
* in the same packet. When we see this, we call a helper that probes the
|
||||
* load to make sure it doesn't fault. Then, we process the store ahead of
|
||||
* the actual load.
|
||||
|
||||
*/
|
||||
#define CHECK_NOSHUF \
|
||||
#define CHECK_NOSHUF(VA, SIZE) \
|
||||
do { \
|
||||
if (insn->slot == 0 && pkt->pkt_has_store_s1) { \
|
||||
probe_noshuf_load(VA, SIZE, ctx->mem_idx); \
|
||||
process_store(ctx, pkt, 1); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_NOSHUF_PRED(GET_EA, SIZE, PRED) \
|
||||
do { \
|
||||
TCGLabel *label = gen_new_label(); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, PRED, 0, label); \
|
||||
GET_EA; \
|
||||
if (insn->slot == 0 && pkt->pkt_has_store_s1) { \
|
||||
probe_noshuf_load(EA, SIZE, ctx->mem_idx); \
|
||||
} \
|
||||
gen_set_label(label); \
|
||||
if (insn->slot == 0 && pkt->pkt_has_store_s1) { \
|
||||
process_store(ctx, pkt, 1); \
|
||||
} \
|
||||
|
@ -99,37 +116,37 @@
|
|||
|
||||
#define MEM_LOAD1s(DST, VA) \
|
||||
do { \
|
||||
CHECK_NOSHUF; \
|
||||
CHECK_NOSHUF(VA, 1); \
|
||||
tcg_gen_qemu_ld8s(DST, VA, ctx->mem_idx); \
|
||||
} while (0)
|
||||
#define MEM_LOAD1u(DST, VA) \
|
||||
do { \
|
||||
CHECK_NOSHUF; \
|
||||
CHECK_NOSHUF(VA, 1); \
|
||||
tcg_gen_qemu_ld8u(DST, VA, ctx->mem_idx); \
|
||||
} while (0)
|
||||
#define MEM_LOAD2s(DST, VA) \
|
||||
do { \
|
||||
CHECK_NOSHUF; \
|
||||
CHECK_NOSHUF(VA, 2); \
|
||||
tcg_gen_qemu_ld16s(DST, VA, ctx->mem_idx); \
|
||||
} while (0)
|
||||
#define MEM_LOAD2u(DST, VA) \
|
||||
do { \
|
||||
CHECK_NOSHUF; \
|
||||
CHECK_NOSHUF(VA, 2); \
|
||||
tcg_gen_qemu_ld16u(DST, VA, ctx->mem_idx); \
|
||||
} while (0)
|
||||
#define MEM_LOAD4s(DST, VA) \
|
||||
do { \
|
||||
CHECK_NOSHUF; \
|
||||
CHECK_NOSHUF(VA, 4); \
|
||||
tcg_gen_qemu_ld32s(DST, VA, ctx->mem_idx); \
|
||||
} while (0)
|
||||
#define MEM_LOAD4u(DST, VA) \
|
||||
do { \
|
||||
CHECK_NOSHUF; \
|
||||
CHECK_NOSHUF(VA, 4); \
|
||||
tcg_gen_qemu_ld32s(DST, VA, ctx->mem_idx); \
|
||||
} while (0)
|
||||
#define MEM_LOAD8u(DST, VA) \
|
||||
do { \
|
||||
CHECK_NOSHUF; \
|
||||
CHECK_NOSHUF(VA, 8); \
|
||||
tcg_gen_qemu_ld64(DST, VA, ctx->mem_idx); \
|
||||
} while (0)
|
||||
|
||||
|
|
|
@ -442,6 +442,17 @@ static void probe_store(CPUHexagonState *env, int slot, int mmu_idx)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called from a mem_noshuf packet to make sure the load doesn't
|
||||
* raise an exception
|
||||
*/
|
||||
void HELPER(probe_noshuf_load)(CPUHexagonState *env, target_ulong va,
|
||||
int size, int mmu_idx)
|
||||
{
|
||||
uintptr_t retaddr = GETPC();
|
||||
probe_read(env, va, size, mmu_idx, retaddr);
|
||||
}
|
||||
|
||||
/* Called during packet commit when there are two scalar stores */
|
||||
void HELPER(probe_pkt_scalar_store_s0)(CPUHexagonState *env, int mmu_idx)
|
||||
{
|
||||
|
@ -514,10 +525,12 @@ void HELPER(probe_pkt_scalar_hvx_stores)(CPUHexagonState *env, int mask,
|
|||
* If the load is in slot 0 and there is a store in slot1 (that
|
||||
* wasn't cancelled), we have to do the store first.
|
||||
*/
|
||||
static void check_noshuf(CPUHexagonState *env, uint32_t slot)
|
||||
static void check_noshuf(CPUHexagonState *env, uint32_t slot,
|
||||
target_ulong vaddr, int size)
|
||||
{
|
||||
if (slot == 0 && env->pkt_has_store_s1 &&
|
||||
((env->slot_cancelled & (1 << 1)) == 0)) {
|
||||
HELPER(probe_noshuf_load)(env, vaddr, size, MMU_USER_IDX);
|
||||
HELPER(commit_store)(env, 1);
|
||||
}
|
||||
}
|
||||
|
@ -526,7 +539,7 @@ static uint8_t mem_load1(CPUHexagonState *env, uint32_t slot,
|
|||
target_ulong vaddr)
|
||||
{
|
||||
uintptr_t ra = GETPC();
|
||||
check_noshuf(env, slot);
|
||||
check_noshuf(env, slot, vaddr, 1);
|
||||
return cpu_ldub_data_ra(env, vaddr, ra);
|
||||
}
|
||||
|
||||
|
@ -534,7 +547,7 @@ static uint16_t mem_load2(CPUHexagonState *env, uint32_t slot,
|
|||
target_ulong vaddr)
|
||||
{
|
||||
uintptr_t ra = GETPC();
|
||||
check_noshuf(env, slot);
|
||||
check_noshuf(env, slot, vaddr, 2);
|
||||
return cpu_lduw_data_ra(env, vaddr, ra);
|
||||
}
|
||||
|
||||
|
@ -542,7 +555,7 @@ static uint32_t mem_load4(CPUHexagonState *env, uint32_t slot,
|
|||
target_ulong vaddr)
|
||||
{
|
||||
uintptr_t ra = GETPC();
|
||||
check_noshuf(env, slot);
|
||||
check_noshuf(env, slot, vaddr, 4);
|
||||
return cpu_ldl_data_ra(env, vaddr, ra);
|
||||
}
|
||||
|
||||
|
@ -550,7 +563,7 @@ static uint64_t mem_load8(CPUHexagonState *env, uint32_t slot,
|
|||
target_ulong vaddr)
|
||||
{
|
||||
uintptr_t ra = GETPC();
|
||||
check_noshuf(env, slot);
|
||||
check_noshuf(env, slot, vaddr, 8);
|
||||
return cpu_ldq_data_ra(env, vaddr, ra);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ HEX_TESTS += preg_alias
|
|||
HEX_TESTS += dual_stores
|
||||
HEX_TESTS += multi_result
|
||||
HEX_TESTS += mem_noshuf
|
||||
HEX_TESTS += mem_noshuf_exception
|
||||
HEX_TESTS += circ
|
||||
HEX_TESTS += brev
|
||||
HEX_TESTS += load_unpack
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
* Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -84,6 +84,70 @@ MEM_NOSHUF32(mem_noshuf_sd_luh, long long, unsigned short, memd, memuh)
|
|||
MEM_NOSHUF32(mem_noshuf_sd_lw, long long, signed int, memd, memw)
|
||||
MEM_NOSHUF64(mem_noshuf_sd_ld, long long, signed long long, memd, memd)
|
||||
|
||||
static inline int pred_lw_sw(int pred, int *p, int *q, int x, int y)
|
||||
{
|
||||
int ret;
|
||||
asm volatile("p0 = cmp.eq(%5, #0)\n\t"
|
||||
"%0 = %3\n\t"
|
||||
"{\n\t"
|
||||
" memw(%1) = %4\n\t"
|
||||
" if (!p0) %0 = memw(%2)\n\t"
|
||||
"}:mem_noshuf\n"
|
||||
: "=&r"(ret)
|
||||
: "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred)
|
||||
: "p0", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int pred_lw_sw_pi(int pred, int *p, int *q, int x, int y)
|
||||
{
|
||||
int ret;
|
||||
asm volatile("p0 = cmp.eq(%5, #0)\n\t"
|
||||
"%0 = %3\n\t"
|
||||
"r7 = %2\n\t"
|
||||
"{\n\t"
|
||||
" memw(%1) = %4\n\t"
|
||||
" if (!p0) %0 = memw(r7++#4)\n\t"
|
||||
"}:mem_noshuf\n"
|
||||
: "=&r"(ret)
|
||||
: "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred)
|
||||
: "r7", "p0", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline long long pred_ld_sd(int pred, long long *p, long long *q,
|
||||
long long x, long long y)
|
||||
{
|
||||
unsigned long long ret;
|
||||
asm volatile("p0 = cmp.eq(%5, #0)\n\t"
|
||||
"%0 = %3\n\t"
|
||||
"{\n\t"
|
||||
" memd(%1) = %4\n\t"
|
||||
" if (!p0) %0 = memd(%2)\n\t"
|
||||
"}:mem_noshuf\n"
|
||||
: "=&r"(ret)
|
||||
: "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred)
|
||||
: "p0", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline long long pred_ld_sd_pi(int pred, long long *p, long long *q,
|
||||
long long x, long long y)
|
||||
{
|
||||
long long ret;
|
||||
asm volatile("p0 = cmp.eq(%5, #0)\n\t"
|
||||
"%0 = %3\n\t"
|
||||
"r7 = %2\n\t"
|
||||
"{\n\t"
|
||||
" memd(%1) = %4\n\t"
|
||||
" if (!p0) %0 = memd(r7++#8)\n\t"
|
||||
"}:mem_noshuf\n"
|
||||
: "=&r"(ret)
|
||||
: "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred)
|
||||
: "p0", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned int cancel_sw_lb(int pred, int *p, signed char *q, int x)
|
||||
{
|
||||
unsigned int ret;
|
||||
|
@ -126,18 +190,22 @@ typedef union {
|
|||
|
||||
int err;
|
||||
|
||||
static void check32(int n, int expect)
|
||||
#define check32(n, expect) check32_(n, expect, __LINE__)
|
||||
|
||||
static void check32_(int n, int expect, int line)
|
||||
{
|
||||
if (n != expect) {
|
||||
printf("ERROR: 0x%08x != 0x%08x\n", n, expect);
|
||||
printf("ERROR: 0x%08x != 0x%08x, line %d\n", n, expect, line);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
static void check64(long long n, long long expect)
|
||||
#define check64(n, expect) check64_(n, expect, __LINE__)
|
||||
|
||||
static void check64_(long long n, long long expect, int line)
|
||||
{
|
||||
if (n != expect) {
|
||||
printf("ERROR: 0x%08llx != 0x%08llx\n", n, expect);
|
||||
printf("ERROR: 0x%08llx != 0x%08llx, line %d\n", n, expect, line);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
@ -323,6 +391,50 @@ int main()
|
|||
res64 = mem_noshuf_sd_ld(&n.d[0], &n.d[1], 0x123456789abcdef0LL);
|
||||
check64(res64, 0xffffffffffffffffLL);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = pred_lw_sw(0, &n.w[0], &n.w[0], 0x12345678, 0xc0ffeeda);
|
||||
check32(res32, 0x12345678);
|
||||
check32(n.w[0], 0xc0ffeeda);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = pred_lw_sw(1, &n.w[0], &n.w[0], 0x12345678, 0xc0ffeeda);
|
||||
check32(res32, 0xc0ffeeda);
|
||||
check32(n.w[0], 0xc0ffeeda);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = pred_lw_sw_pi(0, &n.w[0], &n.w[0], 0x12345678, 0xc0ffeeda);
|
||||
check32(res32, 0x12345678);
|
||||
check32(n.w[0], 0xc0ffeeda);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = pred_lw_sw_pi(1, &n.w[0], &n.w[0], 0x12345678, 0xc0ffeeda);
|
||||
check32(res32, 0xc0ffeeda);
|
||||
check32(n.w[0], 0xc0ffeeda);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res64 = pred_ld_sd(0, &n.d[0], &n.d[0],
|
||||
0x1234567812345678LL, 0xc0ffeedac0ffeedaLL);
|
||||
check64(res64, 0x1234567812345678LL);
|
||||
check64(n.d[0], 0xc0ffeedac0ffeedaLL);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res64 = pred_ld_sd(1, &n.d[0], &n.d[0],
|
||||
0x1234567812345678LL, 0xc0ffeedac0ffeedaLL);
|
||||
check64(res64, 0xc0ffeedac0ffeedaLL);
|
||||
check64(n.d[0], 0xc0ffeedac0ffeedaLL);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res64 = pred_ld_sd_pi(0, &n.d[0], &n.d[0],
|
||||
0x1234567812345678LL, 0xc0ffeedac0ffeedaLL);
|
||||
check64(res64, 0x1234567812345678LL);
|
||||
check64(n.d[0], 0xc0ffeedac0ffeedaLL);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res64 = pred_ld_sd_pi(1, &n.d[0], &n.d[0],
|
||||
0x1234567812345678LL, 0xc0ffeedac0ffeedaLL);
|
||||
check64(res64, 0xc0ffeedac0ffeedaLL);
|
||||
check64(n.d[0], 0xc0ffeedac0ffeedaLL);
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* Copyright(c) 2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test the VLIW semantics of exceptions with mem_noshuf
|
||||
*
|
||||
* When a packet has the :mem_noshuf attribute, the semantics dictate
|
||||
* That the load will get the data from the store if the addresses overlap.
|
||||
* To accomplish this, we perform the store first. However, we have to
|
||||
* handle the case where the store raises an exception. In that case, the
|
||||
* store should not alter the machine state.
|
||||
*
|
||||
* We test this with a mem_noshuf packet with a store to a global variable,
|
||||
* "should_not_change" and a load from NULL. After the SIGSEGV is caught,
|
||||
* we check * that the "should_not_change" value is the same.
|
||||
*
|
||||
* We also check that a predicated load where the predicate is false doesn't
|
||||
* raise an exception and allows the store to happen.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
|
||||
int err;
|
||||
int segv_caught;
|
||||
|
||||
#define SHOULD_NOT_CHANGE_VAL 5
|
||||
int should_not_change = SHOULD_NOT_CHANGE_VAL;
|
||||
|
||||
#define OK_TO_CHANGE_VAL 13
|
||||
int ok_to_change = OK_TO_CHANGE_VAL;
|
||||
|
||||
static void __check(const char *filename, int line, int x, int expect)
|
||||
{
|
||||
if (x != expect) {
|
||||
printf("ERROR %s:%d - %d != %d\n",
|
||||
filename, line, x, expect);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
#define check(x, expect) __check(__FILE__, __LINE__, (x), (expect))
|
||||
|
||||
static void __chk_error(const char *filename, int line, int ret)
|
||||
{
|
||||
if (ret < 0) {
|
||||
printf("ERROR %s:%d - %d\n", filename, line, ret);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
#define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret))
|
||||
|
||||
jmp_buf jmp_env;
|
||||
|
||||
static void sig_segv(int sig, siginfo_t *info, void *puc)
|
||||
{
|
||||
check(sig, SIGSEGV);
|
||||
segv_caught = 1;
|
||||
longjmp(jmp_env, 1);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
struct sigaction act;
|
||||
int dummy32;
|
||||
long long dummy64;
|
||||
void *p;
|
||||
|
||||
/* SIGSEGV test */
|
||||
act.sa_sigaction = sig_segv;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
chk_error(sigaction(SIGSEGV, &act, NULL));
|
||||
if (setjmp(jmp_env) == 0) {
|
||||
asm volatile("r18 = ##should_not_change\n\t"
|
||||
"r19 = #0\n\t"
|
||||
"{\n\t"
|
||||
" memw(r18) = #7\n\t"
|
||||
" %0 = memw(r19)\n\t"
|
||||
"}:mem_noshuf\n\t"
|
||||
: "=r"(dummy32) : : "r18", "r19", "memory");
|
||||
}
|
||||
|
||||
act.sa_handler = SIG_DFL;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
chk_error(sigaction(SIGSEGV, &act, NULL));
|
||||
|
||||
check(segv_caught, 1);
|
||||
check(should_not_change, SHOULD_NOT_CHANGE_VAL);
|
||||
|
||||
/*
|
||||
* Check that a predicated load where the predicate is false doesn't
|
||||
* raise an exception and allows the store to happen.
|
||||
*/
|
||||
asm volatile("r18 = ##ok_to_change\n\t"
|
||||
"r19 = #0\n\t"
|
||||
"p0 = cmp.gt(r0, r0)\n\t"
|
||||
"{\n\t"
|
||||
" memw(r18) = #7\n\t"
|
||||
" if (p0) %0 = memw(r19)\n\t"
|
||||
"}:mem_noshuf\n\t"
|
||||
: "=r"(dummy32) : : "r18", "r19", "p0", "memory");
|
||||
|
||||
check(ok_to_change, 7);
|
||||
|
||||
/*
|
||||
* Also check that the post-increment doesn't happen when the
|
||||
* predicate is false.
|
||||
*/
|
||||
ok_to_change = OK_TO_CHANGE_VAL;
|
||||
p = NULL;
|
||||
asm volatile("r18 = ##ok_to_change\n\t"
|
||||
"p0 = cmp.gt(r0, r0)\n\t"
|
||||
"{\n\t"
|
||||
" memw(r18) = #9\n\t"
|
||||
" if (p0) %1 = memd(%0 ++ #8)\n\t"
|
||||
"}:mem_noshuf\n\t"
|
||||
: "+r"(p), "=r"(dummy64) : : "r18", "p0", "memory");
|
||||
|
||||
check(ok_to_change, 9);
|
||||
check((int)p, (int)NULL);
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue