10849c2623
We create a new generator that creates an analyze_<tag> function for each instruction. Currently, these functions record the writes to R, P, and C registers by calling ctx_log_reg_write[_pair] or ctx_log_pred_write. During gen_start_packet, we invoke the analyze_<tag> function for each instruction in the packet, and we mark the implicit register and predicate writes. Doing the analysis up front has several advantages - We remove calls to ctx_log_* from gen_tcg_funcs.py and genptr.c - After the analysis is performed, we can initialize hex_new_value for each of the predicated assignments rather than during TCG generation for the instructions - This is a stepping stone for future work where the analysis will include the set of registers that are read. In cases where the packet doesn't have an overlap between the registers that are written and registers that are read, we can avoid the intermediate step of writing to hex_new_value. Note that other checks will also be needed (e.g., no instructions can raise an exception). Signed-off-by: Taylor Simpson <tsimpson@quicinc.com> Reviewed-by: Anton Johansson <anjo@rev.ng> Message-Id: <20230307025828.1612809-6-tsimpson@quicinc.com>
173 lines
5.5 KiB
C
173 lines
5.5 KiB
C
/*
|
|
* Copyright(c) 2019-2023 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/>.
|
|
*/
|
|
|
|
#ifndef HEXAGON_TRANSLATE_H
|
|
#define HEXAGON_TRANSLATE_H
|
|
|
|
#include "qemu/bitmap.h"
|
|
#include "qemu/log.h"
|
|
#include "cpu.h"
|
|
#include "exec/translator.h"
|
|
#include "tcg/tcg-op.h"
|
|
#include "insn.h"
|
|
#include "internal.h"
|
|
|
|
typedef struct DisasContext {
|
|
DisasContextBase base;
|
|
Packet *pkt;
|
|
Insn *insn;
|
|
uint32_t next_PC;
|
|
uint32_t mem_idx;
|
|
uint32_t num_packets;
|
|
uint32_t num_insns;
|
|
uint32_t num_hvx_insns;
|
|
int reg_log[REG_WRITES_MAX];
|
|
int reg_log_idx;
|
|
DECLARE_BITMAP(regs_written, TOTAL_PER_THREAD_REGS);
|
|
DECLARE_BITMAP(predicated_regs, TOTAL_PER_THREAD_REGS);
|
|
int preg_log[PRED_WRITES_MAX];
|
|
int preg_log_idx;
|
|
DECLARE_BITMAP(pregs_written, NUM_PREGS);
|
|
uint8_t store_width[STORES_MAX];
|
|
bool s1_store_processed;
|
|
int future_vregs_idx;
|
|
int future_vregs_num[VECTOR_TEMPS_MAX];
|
|
int tmp_vregs_idx;
|
|
int tmp_vregs_num[VECTOR_TEMPS_MAX];
|
|
int vreg_log[NUM_VREGS];
|
|
bool vreg_is_predicated[NUM_VREGS];
|
|
int vreg_log_idx;
|
|
DECLARE_BITMAP(vregs_updated_tmp, NUM_VREGS);
|
|
DECLARE_BITMAP(vregs_updated, NUM_VREGS);
|
|
DECLARE_BITMAP(vregs_select, NUM_VREGS);
|
|
int qreg_log[NUM_QREGS];
|
|
bool qreg_is_predicated[NUM_QREGS];
|
|
int qreg_log_idx;
|
|
bool pre_commit;
|
|
TCGCond branch_cond;
|
|
target_ulong branch_dest;
|
|
bool is_tight_loop;
|
|
} DisasContext;
|
|
|
|
static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
|
|
{
|
|
if (!test_bit(pnum, ctx->pregs_written)) {
|
|
ctx->preg_log[ctx->preg_log_idx] = pnum;
|
|
ctx->preg_log_idx++;
|
|
set_bit(pnum, ctx->pregs_written);
|
|
}
|
|
}
|
|
|
|
static inline void ctx_log_reg_write(DisasContext *ctx, int rnum,
|
|
bool is_predicated)
|
|
{
|
|
if (rnum == HEX_REG_P3_0_ALIASED) {
|
|
for (int i = 0; i < NUM_PREGS; i++) {
|
|
ctx_log_pred_write(ctx, i);
|
|
}
|
|
} else {
|
|
if (!test_bit(rnum, ctx->regs_written)) {
|
|
ctx->reg_log[ctx->reg_log_idx] = rnum;
|
|
ctx->reg_log_idx++;
|
|
set_bit(rnum, ctx->regs_written);
|
|
}
|
|
if (is_predicated) {
|
|
set_bit(rnum, ctx->predicated_regs);
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void ctx_log_reg_write_pair(DisasContext *ctx, int rnum,
|
|
bool is_predicated)
|
|
{
|
|
ctx_log_reg_write(ctx, rnum, is_predicated);
|
|
ctx_log_reg_write(ctx, rnum + 1, is_predicated);
|
|
}
|
|
|
|
static inline bool is_vreg_preloaded(DisasContext *ctx, int num)
|
|
{
|
|
return test_bit(num, ctx->vregs_updated) ||
|
|
test_bit(num, ctx->vregs_updated_tmp);
|
|
}
|
|
|
|
intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
|
|
int num, bool alloc_ok);
|
|
intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
|
|
int num, bool alloc_ok);
|
|
|
|
static inline void ctx_log_vreg_write(DisasContext *ctx,
|
|
int rnum, VRegWriteType type,
|
|
bool is_predicated)
|
|
{
|
|
if (type != EXT_TMP) {
|
|
ctx->vreg_log[ctx->vreg_log_idx] = rnum;
|
|
ctx->vreg_is_predicated[ctx->vreg_log_idx] = is_predicated;
|
|
ctx->vreg_log_idx++;
|
|
|
|
set_bit(rnum, ctx->vregs_updated);
|
|
}
|
|
if (type == EXT_NEW) {
|
|
set_bit(rnum, ctx->vregs_select);
|
|
}
|
|
if (type == EXT_TMP) {
|
|
set_bit(rnum, ctx->vregs_updated_tmp);
|
|
}
|
|
}
|
|
|
|
static inline void ctx_log_vreg_write_pair(DisasContext *ctx,
|
|
int rnum, VRegWriteType type,
|
|
bool is_predicated)
|
|
{
|
|
ctx_log_vreg_write(ctx, rnum ^ 0, type, is_predicated);
|
|
ctx_log_vreg_write(ctx, rnum ^ 1, type, is_predicated);
|
|
}
|
|
|
|
static inline void ctx_log_qreg_write(DisasContext *ctx,
|
|
int rnum, bool is_predicated)
|
|
{
|
|
ctx->qreg_log[ctx->qreg_log_idx] = rnum;
|
|
ctx->qreg_is_predicated[ctx->qreg_log_idx] = is_predicated;
|
|
ctx->qreg_log_idx++;
|
|
}
|
|
|
|
extern TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
|
|
extern TCGv hex_pred[NUM_PREGS];
|
|
extern TCGv hex_this_PC;
|
|
extern TCGv hex_slot_cancelled;
|
|
extern TCGv hex_branch_taken;
|
|
extern TCGv hex_new_value[TOTAL_PER_THREAD_REGS];
|
|
extern TCGv hex_reg_written[TOTAL_PER_THREAD_REGS];
|
|
extern TCGv hex_new_pred_value[NUM_PREGS];
|
|
extern TCGv hex_pred_written;
|
|
extern TCGv hex_store_addr[STORES_MAX];
|
|
extern TCGv hex_store_width[STORES_MAX];
|
|
extern TCGv hex_store_val32[STORES_MAX];
|
|
extern TCGv_i64 hex_store_val64[STORES_MAX];
|
|
extern TCGv hex_dczero_addr;
|
|
extern TCGv hex_llsc_addr;
|
|
extern TCGv hex_llsc_val;
|
|
extern TCGv_i64 hex_llsc_val_i64;
|
|
extern TCGv hex_VRegs_updated;
|
|
extern TCGv hex_QRegs_updated;
|
|
extern TCGv hex_vstore_addr[VSTORES_MAX];
|
|
extern TCGv hex_vstore_size[VSTORES_MAX];
|
|
extern TCGv hex_vstore_pending[VSTORES_MAX];
|
|
|
|
bool is_gather_store_insn(DisasContext *ctx);
|
|
void process_store(DisasContext *ctx, int slot_num);
|
|
#endif
|