idef-parser cleanup, HVX & PC-alignment fixes

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEPWaq5HRZSCTIjOD4GlSvuOVkbDIFAmZk/L4ACgkQGlSvuOVk
 bDLKag//ZzAuoChJOkz7EPeRzFKWuz4QL9cXA6+FrWRoD43geXiJ/eDihlLIjFvr
 JN2deqaYZTyqlfbWR1BUIgkPxYnwBFlaqCnOO4xgbAaUJSxtdmkuWr8GBlftZt2s
 PV2Nm9pDjDOEJrnfbSA2f3nMkMa7e64N+tXZ5Svt8pJC8DOZg3oI3KXWX6uZZ5YA
 9DAGgiHBlZONKQk/EebQ1DAcc+RDu68f+UtzsQ9Q4MiO/Mga/Z2u5wdOdrXmk5Lh
 ba6W4sLqBNU8oB6hkA5sy+5EhlzPIhX1+G1c21fRSlLR74BFK8ByZ802kWSVY1j/
 /MS01yH46Kb3aFVqpMvoYzBZ+kGlbMVKYY4c9AXtrH5tojHQ83ijnl2V/0y+s+i8
 f6bqErchbDZPM8H6vVDdbUewx3Sq/KA7WhiK9GCgnHWc0Z5kj15l121vJr6JVMwS
 fkccK1s8fOTUNCZNJiu4czakNQTGsf4jWGjcOo7EREstIXin0E/cUxZKrJWYshzc
 88Ys1pxSk+1f7ajla4+uQ3oDw+RDqkA1unUA5cfJz/61ho5TWx6dcd5XKziNk7o4
 PyOhxfoLSV9j5+XczAO+nugpN0zQUHb7lz2k0sNiypScbXVSIw/ebKgYMVlLyMSf
 yEZTh8p+rbzmmJbkJBB5X/8kpU0qyp6fK5dRv1wvNPau0ExBwcs=
 =CwAl
 -----END PGP SIGNATURE-----

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

idef-parser cleanup, HVX & PC-alignment fixes

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCgAdFiEEPWaq5HRZSCTIjOD4GlSvuOVkbDIFAmZk/L4ACgkQGlSvuOVk
# bDLKag//ZzAuoChJOkz7EPeRzFKWuz4QL9cXA6+FrWRoD43geXiJ/eDihlLIjFvr
# JN2deqaYZTyqlfbWR1BUIgkPxYnwBFlaqCnOO4xgbAaUJSxtdmkuWr8GBlftZt2s
# PV2Nm9pDjDOEJrnfbSA2f3nMkMa7e64N+tXZ5Svt8pJC8DOZg3oI3KXWX6uZZ5YA
# 9DAGgiHBlZONKQk/EebQ1DAcc+RDu68f+UtzsQ9Q4MiO/Mga/Z2u5wdOdrXmk5Lh
# ba6W4sLqBNU8oB6hkA5sy+5EhlzPIhX1+G1c21fRSlLR74BFK8ByZ802kWSVY1j/
# /MS01yH46Kb3aFVqpMvoYzBZ+kGlbMVKYY4c9AXtrH5tojHQ83ijnl2V/0y+s+i8
# f6bqErchbDZPM8H6vVDdbUewx3Sq/KA7WhiK9GCgnHWc0Z5kj15l121vJr6JVMwS
# fkccK1s8fOTUNCZNJiu4czakNQTGsf4jWGjcOo7EREstIXin0E/cUxZKrJWYshzc
# 88Ys1pxSk+1f7ajla4+uQ3oDw+RDqkA1unUA5cfJz/61ho5TWx6dcd5XKziNk7o4
# PyOhxfoLSV9j5+XczAO+nugpN0zQUHb7lz2k0sNiypScbXVSIw/ebKgYMVlLyMSf
# yEZTh8p+rbzmmJbkJBB5X/8kpU0qyp6fK5dRv1wvNPau0ExBwcs=
# =CwAl
# -----END PGP SIGNATURE-----
# gpg: Signature made Sat 08 Jun 2024 05:52:14 PM PDT
# gpg:                using RSA key 3D66AAE474594824C88CE0F81A54AFB8E5646C32
# gpg: Good signature from "Brian Cain (QUIC) <quic_bcain@quicinc.com>" [unknown]
# gpg:                 aka "Brian Cain <bcain@kernel.org>" [unknown]
# gpg:                 aka "Brian Cain (QuIC) <bcain@quicinc.com>" [unknown]
# gpg:                 aka "Brian Cain (CAF) <bcain@codeaurora.org>" [unknown]
# gpg:                 aka "bcain" [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: 6350 20F9 67A7 7164 79EF  49E0 175C 464E 541B 6D47
#      Subkey fingerprint: 3D66 AAE4 7459 4824 C88C  E0F8 1A54 AFB8 E564 6C32

* tag 'pull-hex-20240608' of https://github.com/quic/qemu:
  target/hexagon: idef-parser simplify predicate init
  target/hexagon: idef-parser fix leak of init_list
  target/hexagon: idef-parser remove undefined functions
  target/hexagon: idef-parser remove unused defines
  Hexagon: add PC alignment check and exception
  Hexagon: fix HVX store new

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2024-06-09 08:14:27 -07:00
commit 593aab332f
13 changed files with 179 additions and 49 deletions

View File

@ -60,6 +60,10 @@ void cpu_loop(CPUHexagonState *env)
env->gpr[0] = ret;
}
break;
case HEX_EXCP_PC_NOT_ALIGNED:
force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN,
env->gpr[HEX_REG_R31]);
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
break;

View File

@ -134,6 +134,10 @@ struct ArchCPU {
FIELD(TB_FLAGS, IS_TIGHT_LOOP, 0, 1)
G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
uint32_t exception,
uintptr_t pc);
static inline void cpu_get_tb_cpu_state(CPUHexagonState *env, vaddr *pc,
uint64_t *cs_base, uint32_t *flags)
{
@ -144,6 +148,9 @@ static inline void cpu_get_tb_cpu_state(CPUHexagonState *env, vaddr *pc,
hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, IS_TIGHT_LOOP, 1);
}
*flags = hex_flags;
if (*pc & PCALIGN_MASK) {
hexagon_raise_exception_err(env, HEX_EXCP_PC_NOT_ALIGNED, 0);
}
}
typedef HexagonCPU ArchCPU;

View File

@ -20,9 +20,13 @@
#include "qemu/bitops.h"
#define PCALIGN 4
#define PCALIGN_MASK (PCALIGN - 1)
#define HEX_EXCP_FETCH_NO_UPAGE 0x012
#define HEX_EXCP_INVALID_PACKET 0x015
#define HEX_EXCP_INVALID_OPCODE 0x015
#define HEX_EXCP_PC_NOT_ALIGNED 0x01e
#define HEX_EXCP_PRIV_NO_UREAD 0x024
#define HEX_EXCP_PRIV_NO_UWRITE 0x025

View File

@ -89,6 +89,7 @@ def gen_trans_funcs(f):
new_read_idx = -1
dest_idx = -1
dest_idx_reg_id = None
has_pred_dest = "false"
for regno, (reg_type, reg_id, *_) in enumerate(regs):
reg = hex_common.get_register(tag, reg_type, reg_id)
@ -97,9 +98,11 @@ def gen_trans_funcs(f):
"""))
if reg.is_read() and reg.is_new():
new_read_idx = regno
# dest_idx should be the first destination, so check for -1
if reg.is_written() and dest_idx == -1:
dest_idx = regno
if reg.is_written():
# dest_idx should be the first destination alphabetically
if dest_idx_reg_id is None or reg_id < dest_idx_reg_id:
dest_idx = regno
dest_idx_reg_id = reg_id
if reg_type == "P" and reg.is_written() and not reg.is_read():
has_pred_dest = "true"

View File

@ -23,16 +23,6 @@
#include <stdbool.h>
#include <glib.h>
#define TCGV_NAME_SIZE 7
#define MAX_WRITTEN_REGS 32
#define OFFSET_STR_LEN 32
#define ALLOC_LIST_LEN 32
#define ALLOC_NAME_SIZE 32
#define INIT_LIST_LEN 32
#define OUT_BUF_LEN (1024 * 1024)
#define SIGNATURE_BUF_LEN (128 * 1024)
#define HEADER_BUF_LEN (128 * 1024)
/* Variadic macros to wrap the buffer printing functions */
#define EMIT(c, ...) \
do { \

View File

@ -233,8 +233,6 @@ code : '{' statements '}'
argument_decl : REG
{
emit_arg(c, &@1, &$1);
/* Enqueue register into initialization list */
g_array_append_val(c->inst.init_list, $1);
}
| PRED
{

View File

@ -1652,26 +1652,28 @@ void gen_inst(Context *c, GString *iname)
/*
* Initialize declared but uninitialized registers, but only for
* non-conditional instructions
* Initialize declared but uninitialized instruction arguments. Only needed for
* predicate arguments, initialization of registers is handled by the Hexagon
* frontend.
*/
void gen_inst_init_args(Context *c, YYLTYPE *locp)
{
HexValue *val = NULL;
char suffix;
/* If init_list is NULL arguments have already been initialized */
if (!c->inst.init_list) {
return;
}
for (unsigned i = 0; i < c->inst.init_list->len; i++) {
HexValue *val = &g_array_index(c->inst.init_list, HexValue, i);
if (val->type == REGISTER_ARG) {
/* Nothing to do here */
} else if (val->type == PREDICATE) {
char suffix = val->is_dotnew ? 'N' : 'V';
EMIT_HEAD(c, "tcg_gen_movi_i%u(P%c%c, 0);\n", val->bit_width,
val->pred.id, suffix);
} else {
yyassert(c, locp, false, "Invalid arg type!");
}
val = &g_array_index(c->inst.init_list, HexValue, i);
suffix = val->is_dotnew ? 'N' : 'V';
yyassert(c, locp, val->type == PREDICATE,
"Only predicates need to be initialized!");
yyassert(c, locp, val->bit_width == 32,
"Predicates should always be 32 bits");
EMIT_HEAD(c, "tcg_gen_movi_i32(P%c%c, 0);\n", val->pred.id, suffix);
}
/* Free argument init list once we have initialized everything */
@ -2121,9 +2123,16 @@ void free_instruction(Context *c)
g_string_free(g_array_index(c->inst.strings, GString*, i), TRUE);
}
g_array_free(c->inst.strings, TRUE);
/*
* Free list of arguments that might need initialization, if they haven't
* already been freed.
*/
if (c->inst.init_list) {
g_array_free(c->inst.init_list, TRUE);
}
/* Free INAME token value */
g_string_free(c->inst.name, TRUE);
/* Free variables and registers */
/* Free declared TCGv variables */
g_array_free(c->inst.allocated, TRUE);
/* Initialize instruction-specific portion of the context */
memset(&(c->inst), 0, sizeof(Inst));

View File

@ -143,8 +143,6 @@ void commit(Context *c);
#define OUT(c, locp, ...) FOR_EACH((c), (locp), OUT_IMPL, __VA_ARGS__)
const char *cmp_swap(Context *c, YYLTYPE *locp, const char *type);
/**
* Temporary values creation
*/
@ -236,8 +234,6 @@ HexValue gen_extract_op(Context *c,
HexValue *index,
HexExtract *extract);
HexValue gen_read_reg(Context *c, YYLTYPE *locp, HexValue *reg);
void gen_write_reg(Context *c, YYLTYPE *locp, HexValue *reg, HexValue *value);
void gen_assign(Context *c,
@ -274,13 +270,6 @@ HexValue gen_ctpop_op(Context *c, YYLTYPE *locp, HexValue *src);
HexValue gen_rotl(Context *c, YYLTYPE *locp, HexValue *src, HexValue *n);
HexValue gen_deinterleave(Context *c, YYLTYPE *locp, HexValue *mixed);
HexValue gen_interleave(Context *c,
YYLTYPE *locp,
HexValue *odd,
HexValue *even);
HexValue gen_carry_from_add(Context *c,
YYLTYPE *locp,
HexValue *op1,
@ -349,8 +338,6 @@ HexValue gen_rvalue_ternary(Context *c, YYLTYPE *locp, HexValue *cond,
const char *cond_to_str(TCGCond cond);
void emit_header(Context *c);
void emit_arg(Context *c, YYLTYPE *locp, HexValue *arg);
void emit_footer(Context *c);

View File

@ -22,9 +22,6 @@
#include "hex_regs.h"
#include "reg_fields.h"
#define PCALIGN 4
#define PCALIGN_MASK (PCALIGN - 1)
#define GET_FIELD(FIELD, REGIN) \
fEXTRACTU_BITS(REGIN, reg_field_info[FIELD].width, \
reg_field_info[FIELD].offset)

View File

@ -36,10 +36,9 @@
#define SF_MANTBITS 23
/* Exceptions processing helpers */
static G_NORETURN
void do_raise_exception_err(CPUHexagonState *env,
uint32_t exception,
uintptr_t pc)
G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
uint32_t exception,
uintptr_t pc)
{
CPUState *cs = env_cpu(env);
qemu_log_mask(CPU_LOG_INT, "%s: %d\n", __func__, exception);
@ -49,7 +48,7 @@ void do_raise_exception_err(CPUHexagonState *env,
G_NORETURN void HELPER(raise_exception)(CPUHexagonState *env, uint32_t excp)
{
do_raise_exception_err(env, excp, 0);
hexagon_raise_exception_err(env, excp, 0);
}
void log_store32(CPUHexagonState *env, target_ulong addr,

View File

@ -51,6 +51,7 @@ HEX_TESTS += scatter_gather
HEX_TESTS += hvx_misc
HEX_TESTS += hvx_histogram
HEX_TESTS += invalid-slots
HEX_TESTS += unaligned_pc
run-and-check-exception = $(call run-test,$2,$3 2>$2.stderr; \
test $$? -eq 1 && grep -q "exception $(strip $1)" $2.stderr)
@ -107,6 +108,7 @@ overflow: overflow.c hex_test.h
preg_alias: preg_alias.c hex_test.h
read_write_overlap: read_write_overlap.c hex_test.h
reg_mut: reg_mut.c hex_test.h
unaligned_pc: unaligned_pc.c
# This test has to be compiled for the -mv67t target
usr: usr.c hex_test.h

View File

@ -474,6 +474,27 @@ static void test_vcombine(void)
check_output_w(__LINE__, BUFSIZE);
}
void test_store_new()
{
asm volatile(
"r0 = #0x12345678\n"
"v0 = vsplat(r0)\n"
"r0 = #0xff00ff00\n"
"v1 = vsplat(r0)\n"
"{\n"
" vdeal(v1,v0,r0)\n"
" vmem(%0) = v0.new\n"
"}\n"
:
: "r"(&output[0])
: "r0", "v0", "v1", "memory"
);
for (int i = 0; i < MAX_VEC_SIZE_BYTES / 4; i++) {
expect[0].w[i] = 0x12345678;
}
check_output_w(__LINE__, 1);
}
int main()
{
init_buffers();
@ -515,6 +536,8 @@ int main()
test_vcombine();
test_store_new();
puts(err ? "FAIL" : "PASS");
return err ? 1 : 0;
}

View File

@ -0,0 +1,107 @@
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <stdlib.h>
/* will be changed in signal handler */
volatile sig_atomic_t completed_tests;
static jmp_buf after_test;
static int nr_tests;
void __attribute__((naked)) test_return(void)
{
asm volatile(
"allocframe(#0x8)\n"
"r0 = #0xffffffff\n"
"framekey = r0\n"
"dealloc_return\n"
:
:
: "r0", "r29", "r30", "r31", "framekey");
}
void test_endloop(void)
{
asm volatile(
"loop0(1f, #2)\n"
"1: r0 = #0x3\n"
"sa0 = r0\n"
"{ nop }:endloop0\n"
:
:
: "r0", "sa0", "lc0", "usr");
}
asm(
".pushsection .text.unaligned\n"
".org 0x3\n"
".global test_multi_cof_unaligned\n"
"test_multi_cof_unaligned:\n"
" jumpr r31\n"
".popsection\n"
);
#define SYS_EXIT 94
void test_multi_cof(void)
{
asm volatile(
"p0 = cmp.eq(r0, r0)\n"
"{\n"
" if (p0) jump test_multi_cof_unaligned\n"
" if (!p0) jump 1f\n"
"}\n"
"1:"
" r0 = #1\n"
" r6 = #%0\n"
" trap0(#1)\n"
:
: "i"(SYS_EXIT)
: "p0", "r0", "r6");
}
void sigbus_handler(int signum)
{
/* retore framekey after test_return */
asm volatile(
"r0 = #0\n"
"framekey = r0\n"
:
:
: "r0", "framekey");
printf("Test %d complete\n", completed_tests);
completed_tests++;
siglongjmp(after_test, 1);
}
void test_done(void)
{
int err = (completed_tests != nr_tests);
puts(err ? "FAIL" : "PASS");
exit(err);
}
typedef void (*test_fn)(void);
int main()
{
test_fn tests[] = { test_return, test_endloop, test_multi_cof, test_done };
nr_tests = (sizeof(tests) / sizeof(tests[0])) - 1;
struct sigaction sa = {
.sa_sigaction = sigbus_handler,
.sa_flags = SA_SIGINFO
};
if (sigaction(SIGBUS, &sa, NULL) < 0) {
perror("sigaction");
return EXIT_FAILURE;
}
sigsetjmp(after_test, 1);
tests[completed_tests]();
/* should never get here */
puts("FAIL");
return 1;
}