Hexagon update: patches from several folks

-----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEENjXHiM5iuR/UxZq0ewJE+xLeRCIFAmO3Cl8ACgkQewJE+xLe
 RCKopQf/eVpmA04C792MIYHJnAaASbXZ1FA2Q33l9zrPt9V5oL0cer+rNPlqwVIb
 jUdFLrT6ppe3jgkzeZVzLTGoNiLO1BnpH3+NV5ZpnMBON4g6/uyagRJekvb5xcDw
 a832LM77zWrSQbV+Z3C0sn87j7u0YFYiXtya3mJUv6iSfKZnR4bGZH+LW2dOrnXn
 +uMGnjjUQ2Ac7mvHTnrtooVUNhgRpTq4tMBwl1mE/hacUuejBjDgMLHDb6e4yPC7
 g0/BuMB1ygBYFDINJ9El5oD0JtYHZjHOX4TKs6i0oXntoeveut62oGRwgLrk8eRe
 lwKiEvFNrz/RYmCIy8Pz7s+5HQUgqA==
 =/i3r
 -----END PGP SIGNATURE-----

Merge tag 'pull-hex-20230105' of https://github.com/quic/qemu into staging

Hexagon update: patches from several folks

# gpg: Signature made Thu 05 Jan 2023 17:35:27 GMT
# gpg:                using RSA key 3635C788CE62B91FD4C59AB47B0244FB12DE4422
# gpg: Good signature from "Taylor Simpson (Rock on) <tsimpson@quicinc.com>" [unknown]
# 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-20230105' of https://github.com/quic/qemu:
  Update scripts/meson-buildoptions.sh
  Hexagon (target/hexagon) implement mutability mask for GPRs
  target/hexagon: suppress unused variable warning
  target/hexagon/idef-parser: fix two typos in README
  tests/tcg/hexagon: fix underspecifed asm constraints
  target/hexagon: rename aliased register HEX_REG_P3_0
  linux-user/hexagon: fix signal context save & restore

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2023-01-06 12:11:22 +00:00
commit 171033e8db
13 changed files with 321 additions and 31 deletions

View File

@ -39,15 +39,12 @@ struct target_sigcontext {
target_ulong m0;
target_ulong m1;
target_ulong usr;
target_ulong p3_0;
target_ulong gp;
target_ulong ugp;
target_ulong pc;
target_ulong cause;
target_ulong badva;
target_ulong pad1;
target_ulong pad2;
target_ulong pad3;
target_ulong pred[NUM_PREGS];
};
struct target_ucontext {
@ -118,10 +115,14 @@ static void setup_sigcontext(struct target_sigcontext *sc, CPUHexagonState *env)
__put_user(env->gpr[HEX_REG_M0], &sc->m0);
__put_user(env->gpr[HEX_REG_M1], &sc->m1);
__put_user(env->gpr[HEX_REG_USR], &sc->usr);
__put_user(env->gpr[HEX_REG_P3_0], &sc->p3_0);
__put_user(env->gpr[HEX_REG_GP], &sc->gp);
__put_user(env->gpr[HEX_REG_UGP], &sc->ugp);
__put_user(env->gpr[HEX_REG_PC], &sc->pc);
int i;
for (i = 0; i < NUM_PREGS; i++) {
__put_user(env->pred[i], &(sc->pred[i]));
}
}
static void setup_ucontext(struct target_ucontext *uc,
@ -230,10 +231,14 @@ static void restore_sigcontext(CPUHexagonState *env,
__get_user(env->gpr[HEX_REG_M0], &sc->m0);
__get_user(env->gpr[HEX_REG_M1], &sc->m1);
__get_user(env->gpr[HEX_REG_USR], &sc->usr);
__get_user(env->gpr[HEX_REG_P3_0], &sc->p3_0);
__get_user(env->gpr[HEX_REG_GP], &sc->gp);
__get_user(env->gpr[HEX_REG_UGP], &sc->ugp);
__get_user(env->gpr[HEX_REG_PC], &sc->pc);
int i;
for (i = 0; i < NUM_PREGS; i++) {
__get_user(env->pred[i], &(sc->pred[i]));
}
}
static void restore_ucontext(CPUHexagonState *env, struct target_ucontext *uc)

View File

@ -10,6 +10,9 @@ meson_options_help() {
printf "%s\n" ' affects only QEMU, not tools like qemu-img)'
printf "%s\n" ' --datadir=VALUE Data file directory [share]'
printf "%s\n" ' --disable-coroutine-pool coroutine freelist (better performance)'
printf "%s\n" ' --disable-hexagon-idef-parser'
printf "%s\n" ' use idef-parser to automatically generate TCG'
printf "%s\n" ' code for the Hexagon frontend'
printf "%s\n" ' --disable-install-blobs install provided firmware blobs'
printf "%s\n" ' --docdir=VALUE Base directory for documentation installation'
printf "%s\n" ' (can be empty) [share/doc]'
@ -40,7 +43,8 @@ meson_options_help() {
printf "%s\n" ' --enable-trace-backends=CHOICES'
printf "%s\n" ' Set available tracing backends [log] (choices:'
printf "%s\n" ' dtrace/ftrace/log/nop/simple/syslog/ust)'
printf "%s\n" ' --firmwarepath=VALUES search PATH for firmware files [share/qemu-firmware]'
printf "%s\n" ' --firmwarepath=VALUES search PATH for firmware files [share/qemu-'
printf "%s\n" ' firmware]'
printf "%s\n" ' --iasl=VALUE Path to ACPI disassembler'
printf "%s\n" ' --includedir=VALUE Header file directory [include]'
printf "%s\n" ' --interp-prefix=VALUE where to find shared libraries etc., use %M for'
@ -93,7 +97,7 @@ meson_options_help() {
printf "%s\n" ' glusterfs Glusterfs block device driver'
printf "%s\n" ' gnutls GNUTLS cryptography support'
printf "%s\n" ' gtk GTK+ user interface'
printf "%s\n" ' gtk-clipboard clipboard support for GTK (EXPERIMENTAL, MAY HANG)'
printf "%s\n" ' gtk-clipboard clipboard support for the gtk UI (EXPERIMENTAL, MAY HANG)'
printf "%s\n" ' guest-agent Build QEMU Guest Agent'
printf "%s\n" ' guest-agent-msi Build MSI package for the QEMU Guest Agent'
printf "%s\n" ' hax HAX acceleration support'
@ -156,6 +160,8 @@ meson_options_help() {
printf "%s\n" ' usb-redir libusbredir support'
printf "%s\n" ' vde vde network backend support'
printf "%s\n" ' vdi vdi image format support'
printf "%s\n" ' vduse-blk-export'
printf "%s\n" ' VDUSE block export support'
printf "%s\n" ' vfio-user-server'
printf "%s\n" ' vfio-user server support'
printf "%s\n" ' vhost-crypto vhost-user crypto backend support'
@ -164,8 +170,6 @@ meson_options_help() {
printf "%s\n" ' vhost-user vhost-user backend support'
printf "%s\n" ' vhost-user-blk-server'
printf "%s\n" ' build vhost-user-blk server'
printf "%s\n" ' vduse-blk-export'
printf "%s\n" ' VDUSE block export support'
printf "%s\n" ' vhost-vdpa vhost-vdpa kernel backend support'
printf "%s\n" ' virglrenderer virgl rendering support'
printf "%s\n" ' virtfs virtio-9p support'
@ -283,6 +287,8 @@ _meson_option_parse() {
--disable-guest-agent-msi) printf "%s" -Dguest_agent_msi=disabled ;;
--enable-hax) printf "%s" -Dhax=enabled ;;
--disable-hax) printf "%s" -Dhax=disabled ;;
--enable-hexagon-idef-parser) printf "%s" -Dhexagon_idef_parser=true ;;
--disable-hexagon-idef-parser) printf "%s" -Dhexagon_idef_parser=false ;;
--enable-hvf) printf "%s" -Dhvf=enabled ;;
--disable-hvf) printf "%s" -Dhvf=disabled ;;
--iasl=*) quote_sh "-Diasl=$2" ;;
@ -429,6 +435,8 @@ _meson_option_parse() {
--disable-vde) printf "%s" -Dvde=disabled ;;
--enable-vdi) printf "%s" -Dvdi=enabled ;;
--disable-vdi) printf "%s" -Dvdi=disabled ;;
--enable-vduse-blk-export) printf "%s" -Dvduse_blk_export=enabled ;;
--disable-vduse-blk-export) printf "%s" -Dvduse_blk_export=disabled ;;
--enable-vfio-user-server) printf "%s" -Dvfio_user_server=enabled ;;
--disable-vfio-user-server) printf "%s" -Dvfio_user_server=disabled ;;
--enable-vhost-crypto) printf "%s" -Dvhost_crypto=enabled ;;
@ -441,8 +449,6 @@ _meson_option_parse() {
--disable-vhost-user) printf "%s" -Dvhost_user=disabled ;;
--enable-vhost-user-blk-server) printf "%s" -Dvhost_user_blk_server=enabled ;;
--disable-vhost-user-blk-server) printf "%s" -Dvhost_user_blk_server=disabled ;;
--enable-vduse-blk-export) printf "%s" -Dvduse_blk_export=enabled ;;
--disable-vduse-blk-export) printf "%s" -Dvduse_blk_export=disabled ;;
--enable-vhost-vdpa) printf "%s" -Dvhost_vdpa=enabled ;;
--disable-vhost-vdpa) printf "%s" -Dvhost_vdpa=disabled ;;
--enable-virglrenderer) printf "%s" -Dvirglrenderer=enabled ;;

View File

@ -86,7 +86,7 @@ static target_ulong adjust_stack_ptrs(CPUHexagonState *env, target_ulong addr)
return addr;
}
/* HEX_REG_P3_0 (aka C4) is an alias for the predicate registers */
/* HEX_REG_P3_0_ALIASED (aka C4) is an alias for the predicate registers */
static target_ulong read_p3_0(CPUHexagonState *env)
{
int32_t control_reg = 0;
@ -102,7 +102,7 @@ static void print_reg(FILE *f, CPUHexagonState *env, int regnum)
{
target_ulong value;
if (regnum == HEX_REG_P3_0) {
if (regnum == HEX_REG_P3_0_ALIASED) {
value = read_p3_0(env);
} else {
value = regnum < 32 ? adjust_stack_ptrs(env, env->gpr[regnum])
@ -198,7 +198,7 @@ static void hexagon_dump(CPUHexagonState *env, FILE *f, int flags)
print_reg(f, env, HEX_REG_M0);
print_reg(f, env, HEX_REG_M1);
print_reg(f, env, HEX_REG_USR);
print_reg(f, env, HEX_REG_P3_0);
print_reg(f, env, HEX_REG_P3_0_ALIASED);
print_reg(f, env, HEX_REG_GP);
print_reg(f, env, HEX_REG_UGP);
print_reg(f, env, HEX_REG_PC);

View File

@ -43,6 +43,33 @@ TCGv gen_read_preg(TCGv pred, uint8_t num)
return pred;
}
#define IMMUTABLE (~0)
static const target_ulong reg_immut_masks[TOTAL_PER_THREAD_REGS] = {
[HEX_REG_USR] = 0xc13000c0,
[HEX_REG_PC] = IMMUTABLE,
[HEX_REG_GP] = 0x3f,
[HEX_REG_UPCYCLELO] = IMMUTABLE,
[HEX_REG_UPCYCLEHI] = IMMUTABLE,
[HEX_REG_UTIMERLO] = IMMUTABLE,
[HEX_REG_UTIMERHI] = IMMUTABLE,
};
static inline void gen_masked_reg_write(TCGv new_val, TCGv cur_val,
target_ulong reg_mask)
{
if (reg_mask) {
TCGv tmp = tcg_temp_new();
/* new_val = (new_val & ~reg_mask) | (cur_val & reg_mask) */
tcg_gen_andi_tl(new_val, new_val, ~reg_mask);
tcg_gen_andi_tl(tmp, cur_val, reg_mask);
tcg_gen_or_tl(new_val, new_val, tmp);
tcg_temp_free(tmp);
}
}
static inline void gen_log_predicated_reg_write(int rnum, TCGv val,
uint32_t slot)
{
@ -69,6 +96,9 @@ static inline void gen_log_predicated_reg_write(int rnum, TCGv val,
void gen_log_reg_write(int rnum, TCGv val)
{
const target_ulong reg_mask = reg_immut_masks[rnum];
gen_masked_reg_write(val, hex_gpr[rnum], reg_mask);
tcg_gen_mov_tl(hex_new_value[rnum], val);
if (HEX_DEBUG) {
/* Do this so HELPER(debug_commit_end) will know */
@ -114,19 +144,29 @@ static void gen_log_predicated_reg_write_pair(int rnum, TCGv_i64 val,
static void gen_log_reg_write_pair(int rnum, TCGv_i64 val)
{
const target_ulong reg_mask_low = reg_immut_masks[rnum];
const target_ulong reg_mask_high = reg_immut_masks[rnum + 1];
TCGv val32 = tcg_temp_new();
/* Low word */
tcg_gen_extrl_i64_i32(hex_new_value[rnum], val);
tcg_gen_extrl_i64_i32(val32, val);
gen_masked_reg_write(val32, hex_gpr[rnum], reg_mask_low);
tcg_gen_mov_tl(hex_new_value[rnum], val32);
if (HEX_DEBUG) {
/* Do this so HELPER(debug_commit_end) will know */
tcg_gen_movi_tl(hex_reg_written[rnum], 1);
}
/* High word */
tcg_gen_extrh_i64_i32(hex_new_value[rnum + 1], val);
tcg_gen_extrh_i64_i32(val32, val);
gen_masked_reg_write(val32, hex_gpr[rnum + 1], reg_mask_high);
tcg_gen_mov_tl(hex_new_value[rnum + 1], val32);
if (HEX_DEBUG) {
/* Do this so HELPER(debug_commit_end) will know */
tcg_gen_movi_tl(hex_reg_written[rnum + 1], 1);
}
tcg_temp_free(val32);
}
void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val)
@ -163,7 +203,7 @@ static inline void gen_read_p3_0(TCGv control_reg)
/*
* Certain control registers require special handling on read
* HEX_REG_P3_0 aliased to the predicate registers
* HEX_REG_P3_0_ALIASED aliased to the predicate registers
* -> concat the 4 predicate registers together
* HEX_REG_PC actual value stored in DisasContext
* -> assign from ctx->base.pc_next
@ -173,7 +213,7 @@ static inline void gen_read_p3_0(TCGv control_reg)
static inline void gen_read_ctrl_reg(DisasContext *ctx, const int reg_num,
TCGv dest)
{
if (reg_num == HEX_REG_P3_0) {
if (reg_num == HEX_REG_P3_0_ALIASED) {
gen_read_p3_0(dest);
} else if (reg_num == HEX_REG_PC) {
tcg_gen_movi_tl(dest, ctx->base.pc_next);
@ -194,7 +234,7 @@ static inline void gen_read_ctrl_reg(DisasContext *ctx, const int reg_num,
static inline void gen_read_ctrl_reg_pair(DisasContext *ctx, const int reg_num,
TCGv_i64 dest)
{
if (reg_num == HEX_REG_P3_0) {
if (reg_num == HEX_REG_P3_0_ALIASED) {
TCGv p3_0 = tcg_temp_new();
gen_read_p3_0(p3_0);
tcg_gen_concat_i32_i64(dest, p3_0, hex_gpr[reg_num + 1]);
@ -238,7 +278,7 @@ static void gen_write_p3_0(DisasContext *ctx, TCGv control_reg)
/*
* Certain control registers require special handling on write
* HEX_REG_P3_0 aliased to the predicate registers
* HEX_REG_P3_0_ALIASED aliased to the predicate registers
* -> break the value across 4 predicate registers
* HEX_REG_QEMU_*_CNT changes in current TB in DisasContext
* -> clear the changes
@ -246,7 +286,7 @@ static void gen_write_p3_0(DisasContext *ctx, TCGv control_reg)
static inline void gen_write_ctrl_reg(DisasContext *ctx, int reg_num,
TCGv val)
{
if (reg_num == HEX_REG_P3_0) {
if (reg_num == HEX_REG_P3_0_ALIASED) {
gen_write_p3_0(ctx, val);
} else {
gen_log_reg_write(reg_num, val);
@ -266,7 +306,7 @@ static inline void gen_write_ctrl_reg(DisasContext *ctx, int reg_num,
static inline void gen_write_ctrl_reg_pair(DisasContext *ctx, int reg_num,
TCGv_i64 val)
{
if (reg_num == HEX_REG_P3_0) {
if (reg_num == HEX_REG_P3_0_ALIASED) {
TCGv val32 = tcg_temp_new();
tcg_gen_extrl_i64_i32(val32, val);
gen_write_p3_0(ctx, val32);

View File

@ -58,7 +58,7 @@ enum {
HEX_REG_LC0 = 33,
HEX_REG_SA1 = 34,
HEX_REG_LC1 = 35,
HEX_REG_P3_0 = 36,
HEX_REG_P3_0_ALIASED = 36,
HEX_REG_M0 = 38,
HEX_REG_M1 = 39,
HEX_REG_USR = 40,

View File

@ -552,11 +552,11 @@ to compare our buggy CPU state against, running
::
meson configure -Dhexagon_idef_parser_enabled=false
meson configure -Dhexagon_idef_parser=false
will disable the idef-parser for all instructions and fallback on manual
tinycode generator overrides, or on helper function implementations. Recompiling
gives us ``qemu-hexagon`` which passes all tests. If ``qemu-heaxgon-buggy`` is
gives us ``qemu-hexagon`` which passes all tests. If ``qemu-hexagon-buggy`` is
our binary with the incorrect tinycode generators, we can compare the CPU state
between the two versions

View File

@ -99,6 +99,8 @@
/* Input file containing the description of each hexagon instruction */
input : instructions
{
/* Suppress warning about unused yynerrs */
(void) yynerrs;
YYACCEPT;
}
;

View File

@ -197,7 +197,6 @@ if idef_parser_enabled and 'hexagon-linux-user' in target_dirs
idef_parser_dir / 'parser-helpers.c'],
include_directories: ['idef-parser', '../../include/'],
dependencies: [glib_dep],
c_args: ['-Wextra'],
native: true
)

View File

@ -43,6 +43,8 @@ HEX_TESTS += load_align
HEX_TESTS += atomics
HEX_TESTS += fpstuff
HEX_TESTS += overflow
HEX_TESTS += signal_context
HEX_TESTS += reg_mut
HEX_TESTS += test_abs
HEX_TESTS += test_bitcnt

View File

@ -144,7 +144,7 @@ static inline long long pred_ld_sd_pi(int pred, long long *p, long long *q,
"}:mem_noshuf\n"
: "=&r"(ret)
: "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred)
: "p0", "memory");
: "r7", "p0", "memory");
return ret;
}

View File

@ -186,10 +186,10 @@ static int L2_ploadrifnew_pi(void *p, int pred)
int result;
asm volatile("%0 = #31\n\t"
"{\n\t"
" p0 = cmp.eq(%1, #1)\n\t"
" if (!p0.new) %0 = memw(%2++#4)\n\t"
" p0 = cmp.eq(%2, #1)\n\t"
" if (!p0.new) %0 = memw(%1++#4)\n\t"
"}\n\t"
: "=r"(result) : "r"(pred), "r"(p)
: "=&r"(result), "+r"(p) : "r"(pred)
: "p0");
return result;
}

152
tests/tcg/hexagon/reg_mut.c Normal file
View File

@ -0,0 +1,152 @@
/*
* 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/>.
*/
#include <stdio.h>
#include <stdint.h>
static int err;
#define check(N, EXPECT) \
do { \
uint64_t value = N; \
uint64_t expect = EXPECT; \
if (value != EXPECT) { \
printf("ERROR: \"%s\" 0x%04llx != 0x%04llx at %s:%d\n", #N, value, \
expect, __FILE__, __LINE__); \
err++; \
} \
} while (0)
#define check_ne(N, EXPECT) \
do { \
uint64_t value = N; \
uint64_t expect = EXPECT; \
if (value == EXPECT) { \
printf("ERROR: \"%s\" 0x%04llx == 0x%04llx at %s:%d\n", #N, value, \
expect, __FILE__, __LINE__); \
err++; \
} \
} while (0)
#define WRITE_REG_NOCLOBBER(output, reg_name, input) \
asm volatile(reg_name " = %1\n\t" \
"%0 = " reg_name "\n\t" \
: "=r"(output) \
: "r"(input) \
: );
#define WRITE_REG_ENCODED(output, reg_name, input, encoding) \
asm volatile("r0 = %1\n\t" \
encoding "\n\t" \
"%0 = " reg_name "\n\t" \
: "=r"(output) \
: "r"(input) \
: "r0");
#define WRITE_REG_PAIR_ENCODED(output, reg_name, input, encoding) \
asm volatile("r1:0 = %1\n\t" \
encoding "\n\t" \
"%0 = " reg_name "\n\t" \
: "=r"(output) \
: "r"(input) \
: "r1:0");
/*
* Instruction word: { pc = r0 }
*
* This instruction is barred by the assembler.
*
* 3 2 1
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Opc[A2_tfrrcr] | Src[R0] |P P| | C9/PC |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#define PC_EQ_R0 ".word 0x6220c009"
#define C9_8_EQ_R1_0 ".word 0x6320c008"
static inline void write_control_registers(void)
{
uint32_t result = 0;
WRITE_REG_NOCLOBBER(result, "usr", 0xffffffff);
check(result, 0x3ecfff3f);
WRITE_REG_NOCLOBBER(result, "gp", 0xffffffff);
check(result, 0xffffffc0);
WRITE_REG_NOCLOBBER(result, "upcyclelo", 0xffffffff);
check(result, 0x00000000);
WRITE_REG_NOCLOBBER(result, "upcyclehi", 0xffffffff);
check(result, 0x00000000);
WRITE_REG_NOCLOBBER(result, "utimerlo", 0xffffffff);
check(result, 0x00000000);
WRITE_REG_NOCLOBBER(result, "utimerhi", 0xffffffff);
check(result, 0x00000000);
/*
* PC is special. Setting it to these values
* should cause a catastrophic failure.
*/
WRITE_REG_ENCODED(result, "pc", 0x00000000, PC_EQ_R0);
check_ne(result, 0x00000000);
WRITE_REG_ENCODED(result, "pc", 0x00000001, PC_EQ_R0);
check_ne(result, 0x00000001);
WRITE_REG_ENCODED(result, "pc", 0xffffffff, PC_EQ_R0);
check_ne(result, 0xffffffff);
}
static inline void write_control_register_pairs(void)
{
uint64_t result = 0;
WRITE_REG_NOCLOBBER(result, "c11:10", 0xffffffffffffffff);
check(result, 0xffffffc0ffffffff);
WRITE_REG_NOCLOBBER(result, "c15:14", 0xffffffffffffffff);
check(result, 0x0000000000000000);
WRITE_REG_NOCLOBBER(result, "c31:30", 0xffffffffffffffff);
check(result, 0x0000000000000000);
WRITE_REG_PAIR_ENCODED(result, "c9:8", (uint64_t) 0x0000000000000000,
C9_8_EQ_R1_0);
check_ne(result, 0x000000000000000);
WRITE_REG_PAIR_ENCODED(result, "c9:8", 0x0000000100000000, C9_8_EQ_R1_0);
check_ne(result, 0x0000000100000000);
WRITE_REG_PAIR_ENCODED(result, "c9:8", 0xffffffffffffffff, C9_8_EQ_R1_0);
check_ne(result, 0xffffffffffffffff);
}
int main()
{
err = 0;
write_control_registers();
write_control_register_pairs();
puts(err ? "FAIL" : "PASS");
return err;
}

View File

@ -0,0 +1,84 @@
/*
* 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/>.
*/
#include <stdio.h>
#include <signal.h>
#include <time.h>
void sig_user(int sig, siginfo_t *info, void *puc)
{
asm("r7 = #0\n\t"
"p0 = r7\n\t"
"p1 = r7\n\t"
"p2 = r7\n\t"
"p3 = r7\n\t"
: : : "r7", "p0", "p1", "p2", "p3");
}
int main()
{
int err = 0;
unsigned int i = 100000;
struct sigaction act;
struct itimerspec it;
timer_t tid;
struct sigevent sev;
act.sa_sigaction = sig_user;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
sigaction(SIGUSR1, &act, NULL);
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGUSR1;
sev.sigev_value.sival_ptr = &tid;
timer_create(CLOCK_REALTIME, &sev, &tid);
it.it_interval.tv_sec = 0;
it.it_interval.tv_nsec = 100000;
it.it_value.tv_sec = 0;
it.it_value.tv_nsec = 100000;
timer_settime(tid, 0, &it, NULL);
asm("loop0(1f, %1)\n\t"
"1: r8 = #0xff\n\t"
" p0 = r8\n\t"
" p1 = r8\n\t"
" p2 = r8\n\t"
" p3 = r8\n\t"
" jump 3f\n\t"
"2: memb(%0) = #1\n\t"
" jump 4f\n\t"
"3:\n\t"
" r8 = p0\n\t"
" p0 = cmp.eq(r8, #0xff)\n\t"
" if (!p0) jump 2b\n\t"
" r8 = p1\n\t"
" p0 = cmp.eq(r8, #0xff)\n\t"
" if (!p0) jump 2b\n\t"
" r8 = p2\n\t"
" p0 = cmp.eq(r8, #0xff)\n\t"
" if (!p0) jump 2b\n\t"
" r8 = p3\n\t"
" p0 = cmp.eq(r8, #0xff)\n\t"
" if (!p0) jump 2b\n\t"
"4: {}: endloop0\n\t"
:
: "r"(&err), "r"(i)
: "memory", "r8", "p0", "p1", "p2", "p3");
puts(err ? "FAIL" : "PASS");
return err;
}