qemu/target/hexagon/translate.c
<<
>>
Prefs
   1/*
   2 *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
   3 *
   4 *  This program is free software; you can redistribute it and/or modify
   5 *  it under the terms of the GNU General Public License as published by
   6 *  the Free Software Foundation; either version 2 of the License, or
   7 *  (at your option) any later version.
   8 *
   9 *  This program is distributed in the hope that it will be useful,
  10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 *  GNU General Public License for more details.
  13 *
  14 *  You should have received a copy of the GNU General Public License
  15 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  16 */
  17
  18#define QEMU_GENERATE
  19#include "qemu/osdep.h"
  20#include "cpu.h"
  21#include "tcg/tcg-op.h"
  22#include "tcg/tcg-op-gvec.h"
  23#include "exec/helper-gen.h"
  24#include "exec/helper-proto.h"
  25#include "exec/translation-block.h"
  26#include "exec/cpu_ldst.h"
  27#include "exec/log.h"
  28#include "internal.h"
  29#include "attribs.h"
  30#include "insn.h"
  31#include "decode.h"
  32#include "translate.h"
  33#include "genptr.h"
  34#include "printinsn.h"
  35
  36#define HELPER_H "helper.h"
  37#include "exec/helper-info.c.inc"
  38#undef  HELPER_H
  39
  40#include "analyze_funcs_generated.c.inc"
  41
  42typedef void (*AnalyzeInsn)(DisasContext *ctx);
  43static const AnalyzeInsn opcode_analyze[XX_LAST_OPCODE] = {
  44#define OPCODE(X)    [X] = analyze_##X
  45#include "opcodes_def_generated.h.inc"
  46#undef OPCODE
  47};
  48
  49TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
  50TCGv hex_pred[NUM_PREGS];
  51TCGv hex_slot_cancelled;
  52TCGv hex_new_value_usr;
  53TCGv hex_reg_written[TOTAL_PER_THREAD_REGS];
  54TCGv hex_store_addr[STORES_MAX];
  55TCGv hex_store_width[STORES_MAX];
  56TCGv hex_store_val32[STORES_MAX];
  57TCGv_i64 hex_store_val64[STORES_MAX];
  58TCGv hex_llsc_addr;
  59TCGv hex_llsc_val;
  60TCGv_i64 hex_llsc_val_i64;
  61TCGv hex_vstore_addr[VSTORES_MAX];
  62TCGv hex_vstore_size[VSTORES_MAX];
  63TCGv hex_vstore_pending[VSTORES_MAX];
  64
  65static const char * const hexagon_prednames[] = {
  66  "p0", "p1", "p2", "p3"
  67};
  68
  69intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
  70                          int num, bool alloc_ok)
  71{
  72    intptr_t offset;
  73
  74    if (!ctx->need_commit) {
  75        return offsetof(CPUHexagonState, VRegs[regnum]);
  76    }
  77
  78    /* See if it is already allocated */
  79    for (int i = 0; i < ctx->future_vregs_idx; i++) {
  80        if (ctx->future_vregs_num[i] == regnum) {
  81            return offsetof(CPUHexagonState, future_VRegs[i]);
  82        }
  83    }
  84
  85    g_assert(alloc_ok);
  86    offset = offsetof(CPUHexagonState, future_VRegs[ctx->future_vregs_idx]);
  87    for (int i = 0; i < num; i++) {
  88        ctx->future_vregs_num[ctx->future_vregs_idx + i] = regnum++;
  89    }
  90    ctx->future_vregs_idx += num;
  91    g_assert(ctx->future_vregs_idx <= VECTOR_TEMPS_MAX);
  92    return offset;
  93}
  94
  95intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
  96                          int num, bool alloc_ok)
  97{
  98    intptr_t offset;
  99
 100    /* See if it is already allocated */
 101    for (int i = 0; i < ctx->tmp_vregs_idx; i++) {
 102        if (ctx->tmp_vregs_num[i] == regnum) {
 103            return offsetof(CPUHexagonState, tmp_VRegs[i]);
 104        }
 105    }
 106
 107    g_assert(alloc_ok);
 108    offset = offsetof(CPUHexagonState, tmp_VRegs[ctx->tmp_vregs_idx]);
 109    for (int i = 0; i < num; i++) {
 110        ctx->tmp_vregs_num[ctx->tmp_vregs_idx + i] = regnum++;
 111    }
 112    ctx->tmp_vregs_idx += num;
 113    g_assert(ctx->tmp_vregs_idx <= VECTOR_TEMPS_MAX);
 114    return offset;
 115}
 116
 117static void gen_exception_raw(int excp)
 118{
 119    gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
 120}
 121
 122static void gen_exec_counters(DisasContext *ctx)
 123{
 124    tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_PKT_CNT],
 125                    hex_gpr[HEX_REG_QEMU_PKT_CNT], ctx->num_packets);
 126    tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_INSN_CNT],
 127                    hex_gpr[HEX_REG_QEMU_INSN_CNT], ctx->num_insns);
 128    tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_HVX_CNT],
 129                    hex_gpr[HEX_REG_QEMU_HVX_CNT], ctx->num_hvx_insns);
 130}
 131
 132static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
 133{
 134    return translator_use_goto_tb(&ctx->base, dest);
 135}
 136
 137static void gen_goto_tb(DisasContext *ctx, int idx, target_ulong dest, bool
 138                        move_to_pc)
 139{
 140    if (use_goto_tb(ctx, dest)) {
 141        tcg_gen_goto_tb(idx);
 142        if (move_to_pc) {
 143            tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], dest);
 144        }
 145        tcg_gen_exit_tb(ctx->base.tb, idx);
 146    } else {
 147        if (move_to_pc) {
 148            tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], dest);
 149        }
 150        tcg_gen_lookup_and_goto_ptr();
 151    }
 152}
 153
 154static void gen_end_tb(DisasContext *ctx)
 155{
 156    Packet *pkt = ctx->pkt;
 157
 158    gen_exec_counters(ctx);
 159
 160    if (ctx->branch_cond != TCG_COND_NEVER) {
 161        if (ctx->branch_cond != TCG_COND_ALWAYS) {
 162            TCGLabel *skip = gen_new_label();
 163            tcg_gen_brcondi_tl(ctx->branch_cond, ctx->branch_taken, 0, skip);
 164            gen_goto_tb(ctx, 0, ctx->branch_dest, true);
 165            gen_set_label(skip);
 166            gen_goto_tb(ctx, 1, ctx->next_PC, false);
 167        } else {
 168            gen_goto_tb(ctx, 0, ctx->branch_dest, true);
 169        }
 170    } else if (ctx->is_tight_loop &&
 171               pkt->insn[pkt->num_insns - 1].opcode == J2_endloop0) {
 172        /*
 173         * When we're in a tight loop, we defer the endloop0 processing
 174         * to take advantage of direct block chaining
 175         */
 176        TCGLabel *skip = gen_new_label();
 177        tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, skip);
 178        tcg_gen_subi_tl(hex_gpr[HEX_REG_LC0], hex_gpr[HEX_REG_LC0], 1);
 179        gen_goto_tb(ctx, 0, ctx->base.tb->pc, true);
 180        gen_set_label(skip);
 181        gen_goto_tb(ctx, 1, ctx->next_PC, false);
 182    } else {
 183        tcg_gen_lookup_and_goto_ptr();
 184    }
 185
 186    ctx->base.is_jmp = DISAS_NORETURN;
 187}
 188
 189static void gen_exception_end_tb(DisasContext *ctx, int excp)
 190{
 191    gen_exec_counters(ctx);
 192    tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->next_PC);
 193    gen_exception_raw(excp);
 194    ctx->base.is_jmp = DISAS_NORETURN;
 195
 196}
 197
 198#define PACKET_BUFFER_LEN              1028
 199static void print_pkt(Packet *pkt)
 200{
 201    GString *buf = g_string_sized_new(PACKET_BUFFER_LEN);
 202    snprint_a_pkt_debug(buf, pkt);
 203    HEX_DEBUG_LOG("%s", buf->str);
 204    g_string_free(buf, true);
 205}
 206#define HEX_DEBUG_PRINT_PKT(pkt) \
 207    do { \
 208        if (HEX_DEBUG) { \
 209            print_pkt(pkt); \
 210        } \
 211    } while (0)
 212
 213static int read_packet_words(CPUHexagonState *env, DisasContext *ctx,
 214                             uint32_t words[])
 215{
 216    bool found_end = false;
 217    int nwords, max_words;
 218
 219    memset(words, 0, PACKET_WORDS_MAX * sizeof(uint32_t));
 220    for (nwords = 0; !found_end && nwords < PACKET_WORDS_MAX; nwords++) {
 221        words[nwords] =
 222            translator_ldl(env, &ctx->base,
 223                           ctx->base.pc_next + nwords * sizeof(uint32_t));
 224        found_end = is_packet_end(words[nwords]);
 225    }
 226    if (!found_end) {
 227        /* Read too many words without finding the end */
 228        return 0;
 229    }
 230
 231    /* Check for page boundary crossing */
 232    max_words = -(ctx->base.pc_next | TARGET_PAGE_MASK) / sizeof(uint32_t);
 233    if (nwords > max_words) {
 234        /* We can only cross a page boundary at the beginning of a TB */
 235        g_assert(ctx->base.num_insns == 1);
 236    }
 237
 238    HEX_DEBUG_LOG("decode_packet: pc = 0x%x\n", ctx->base.pc_next);
 239    HEX_DEBUG_LOG("    words = { ");
 240    for (int i = 0; i < nwords; i++) {
 241        HEX_DEBUG_LOG("0x%x, ", words[i]);
 242    }
 243    HEX_DEBUG_LOG("}\n");
 244
 245    return nwords;
 246}
 247
 248static bool check_for_attrib(Packet *pkt, int attrib)
 249{
 250    for (int i = 0; i < pkt->num_insns; i++) {
 251        if (GET_ATTRIB(pkt->insn[i].opcode, attrib)) {
 252            return true;
 253        }
 254    }
 255    return false;
 256}
 257
 258static bool need_slot_cancelled(Packet *pkt)
 259{
 260    /* We only need slot_cancelled for conditional store instructions */
 261    for (int i = 0; i < pkt->num_insns; i++) {
 262        uint16_t opcode = pkt->insn[i].opcode;
 263        if (GET_ATTRIB(opcode, A_CONDEXEC) &&
 264            GET_ATTRIB(opcode, A_SCALAR_STORE)) {
 265            return true;
 266        }
 267    }
 268    return false;
 269}
 270
 271static bool need_next_PC(DisasContext *ctx)
 272{
 273    Packet *pkt = ctx->pkt;
 274
 275    /* Check for conditional control flow or HW loop end */
 276    for (int i = 0; i < pkt->num_insns; i++) {
 277        uint16_t opcode = pkt->insn[i].opcode;
 278        if (GET_ATTRIB(opcode, A_CONDEXEC) && GET_ATTRIB(opcode, A_COF)) {
 279            return true;
 280        }
 281        if (GET_ATTRIB(opcode, A_HWLOOP0_END) ||
 282            GET_ATTRIB(opcode, A_HWLOOP1_END)) {
 283            return true;
 284        }
 285    }
 286    return false;
 287}
 288
 289/*
 290 * The opcode_analyze functions mark most of the writes in a packet
 291 * However, there are some implicit writes marked as attributes
 292 * of the applicable instructions.
 293 */
 294static void mark_implicit_reg_write(DisasContext *ctx, int attrib, int rnum)
 295{
 296    uint16_t opcode = ctx->insn->opcode;
 297    if (GET_ATTRIB(opcode, attrib)) {
 298        /*
 299         * USR is used to set overflow and FP exceptions,
 300         * so treat it as conditional
 301         */
 302        bool is_predicated = GET_ATTRIB(opcode, A_CONDEXEC) ||
 303                             rnum == HEX_REG_USR;
 304
 305        /* LC0/LC1 is conditionally written by endloop instructions */
 306        if ((rnum == HEX_REG_LC0 || rnum == HEX_REG_LC1) &&
 307            (opcode == J2_endloop0 ||
 308             opcode == J2_endloop1 ||
 309             opcode == J2_endloop01)) {
 310            is_predicated = true;
 311        }
 312
 313        ctx_log_reg_write(ctx, rnum, is_predicated);
 314    }
 315}
 316
 317static void mark_implicit_reg_writes(DisasContext *ctx)
 318{
 319    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_FP,  HEX_REG_FP);
 320    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_SP,  HEX_REG_SP);
 321    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_LR,  HEX_REG_LR);
 322    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_LC0, HEX_REG_LC0);
 323    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_SA0, HEX_REG_SA0);
 324    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_LC1, HEX_REG_LC1);
 325    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_SA1, HEX_REG_SA1);
 326    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_USR, HEX_REG_USR);
 327    mark_implicit_reg_write(ctx, A_FPOP, HEX_REG_USR);
 328}
 329
 330static void mark_implicit_pred_write(DisasContext *ctx, int attrib, int pnum)
 331{
 332    if (GET_ATTRIB(ctx->insn->opcode, attrib)) {
 333        ctx_log_pred_write(ctx, pnum);
 334    }
 335}
 336
 337static void mark_implicit_pred_writes(DisasContext *ctx)
 338{
 339    mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P0, 0);
 340    mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P1, 1);
 341    mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P2, 2);
 342    mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P3, 3);
 343}
 344
 345static bool pkt_raises_exception(Packet *pkt)
 346{
 347    if (check_for_attrib(pkt, A_LOAD) ||
 348        check_for_attrib(pkt, A_STORE)) {
 349        return true;
 350    }
 351    return false;
 352}
 353
 354static bool need_commit(DisasContext *ctx)
 355{
 356    Packet *pkt = ctx->pkt;
 357
 358    /*
 359     * If the short-circuit property is set to false, we'll always do the commit
 360     */
 361    if (!ctx->short_circuit) {
 362        return true;
 363    }
 364
 365    if (pkt_raises_exception(pkt)) {
 366        return true;
 367    }
 368
 369    /* Registers with immutability flags require new_value */
 370    for (int i = 0; i < ctx->reg_log_idx; i++) {
 371        int rnum = ctx->reg_log[i];
 372        if (reg_immut_masks[rnum]) {
 373            return true;
 374        }
 375    }
 376
 377    /* Floating point instructions are hard-coded to use new_value */
 378    if (check_for_attrib(pkt, A_FPOP)) {
 379        return true;
 380    }
 381
 382    if (pkt->num_insns == 1) {
 383        if (pkt->pkt_has_hvx) {
 384            /*
 385             * The HVX instructions with generated helpers use
 386             * pass-by-reference, so they need the read/write overlap
 387             * check below.
 388             * The HVX instructions with overrides are OK.
 389             */
 390            if (!ctx->has_hvx_helper) {
 391                return false;
 392            }
 393        } else {
 394            return false;
 395        }
 396    }
 397
 398    /* Check for overlap between register reads and writes */
 399    for (int i = 0; i < ctx->reg_log_idx; i++) {
 400        int rnum = ctx->reg_log[i];
 401        if (test_bit(rnum, ctx->regs_read)) {
 402            return true;
 403        }
 404    }
 405
 406    /* Check for overlap between predicate reads and writes */
 407    for (int i = 0; i < ctx->preg_log_idx; i++) {
 408        int pnum = ctx->preg_log[i];
 409        if (test_bit(pnum, ctx->pregs_read)) {
 410            return true;
 411        }
 412    }
 413
 414    /* Check for overlap between HVX reads and writes */
 415    for (int i = 0; i < ctx->vreg_log_idx; i++) {
 416        int vnum = ctx->vreg_log[i];
 417        if (test_bit(vnum, ctx->vregs_read)) {
 418            return true;
 419        }
 420    }
 421    if (!bitmap_empty(ctx->vregs_updated_tmp, NUM_VREGS)) {
 422        int i = find_first_bit(ctx->vregs_updated_tmp, NUM_VREGS);
 423        while (i < NUM_VREGS) {
 424            if (test_bit(i, ctx->vregs_read)) {
 425                return true;
 426            }
 427            i = find_next_bit(ctx->vregs_updated_tmp, NUM_VREGS, i + 1);
 428        }
 429    }
 430    if (!bitmap_empty(ctx->vregs_select, NUM_VREGS)) {
 431        int i = find_first_bit(ctx->vregs_select, NUM_VREGS);
 432        while (i < NUM_VREGS) {
 433            if (test_bit(i, ctx->vregs_read)) {
 434                return true;
 435            }
 436            i = find_next_bit(ctx->vregs_select, NUM_VREGS, i + 1);
 437        }
 438    }
 439
 440    /* Check for overlap between HVX predicate reads and writes */
 441    for (int i = 0; i < ctx->qreg_log_idx; i++) {
 442        int qnum = ctx->qreg_log[i];
 443        if (test_bit(qnum, ctx->qregs_read)) {
 444            return true;
 445        }
 446    }
 447
 448    return false;
 449}
 450
 451static void mark_implicit_pred_read(DisasContext *ctx, int attrib, int pnum)
 452{
 453    if (GET_ATTRIB(ctx->insn->opcode, attrib)) {
 454        ctx_log_pred_read(ctx, pnum);
 455    }
 456}
 457
 458static void mark_implicit_pred_reads(DisasContext *ctx)
 459{
 460    mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P0, 0);
 461    mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P1, 1);
 462    mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P3, 2);
 463    mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P3, 3);
 464}
 465
 466static void analyze_packet(DisasContext *ctx)
 467{
 468    Packet *pkt = ctx->pkt;
 469    ctx->has_hvx_helper = false;
 470    for (int i = 0; i < pkt->num_insns; i++) {
 471        Insn *insn = &pkt->insn[i];
 472        ctx->insn = insn;
 473        if (opcode_analyze[insn->opcode]) {
 474            opcode_analyze[insn->opcode](ctx);
 475        }
 476        mark_implicit_reg_writes(ctx);
 477        mark_implicit_pred_writes(ctx);
 478        mark_implicit_pred_reads(ctx);
 479    }
 480
 481    ctx->need_commit = need_commit(ctx);
 482}
 483
 484static void gen_start_packet(DisasContext *ctx)
 485{
 486    Packet *pkt = ctx->pkt;
 487    target_ulong next_PC = ctx->base.pc_next + pkt->encod_pkt_size_in_bytes;
 488    int i;
 489
 490    /* Clear out the disassembly context */
 491    ctx->next_PC = next_PC;
 492    ctx->reg_log_idx = 0;
 493    bitmap_zero(ctx->regs_written, TOTAL_PER_THREAD_REGS);
 494    bitmap_zero(ctx->regs_read, TOTAL_PER_THREAD_REGS);
 495    bitmap_zero(ctx->predicated_regs, TOTAL_PER_THREAD_REGS);
 496    ctx->preg_log_idx = 0;
 497    bitmap_zero(ctx->pregs_written, NUM_PREGS);
 498    bitmap_zero(ctx->pregs_read, NUM_PREGS);
 499    ctx->future_vregs_idx = 0;
 500    ctx->tmp_vregs_idx = 0;
 501    ctx->vreg_log_idx = 0;
 502    bitmap_zero(ctx->vregs_updated_tmp, NUM_VREGS);
 503    bitmap_zero(ctx->vregs_updated, NUM_VREGS);
 504    bitmap_zero(ctx->vregs_select, NUM_VREGS);
 505    bitmap_zero(ctx->predicated_future_vregs, NUM_VREGS);
 506    bitmap_zero(ctx->predicated_tmp_vregs, NUM_VREGS);
 507    bitmap_zero(ctx->vregs_read, NUM_VREGS);
 508    bitmap_zero(ctx->qregs_read, NUM_QREGS);
 509    ctx->qreg_log_idx = 0;
 510    for (i = 0; i < STORES_MAX; i++) {
 511        ctx->store_width[i] = 0;
 512    }
 513    ctx->s1_store_processed = false;
 514    ctx->pre_commit = true;
 515    for (i = 0; i < TOTAL_PER_THREAD_REGS; i++) {
 516        ctx->new_value[i] = NULL;
 517    }
 518    for (i = 0; i < NUM_PREGS; i++) {
 519        ctx->new_pred_value[i] = NULL;
 520    }
 521
 522    analyze_packet(ctx);
 523
 524    /*
 525     * pregs_written is used both in the analyze phase as well as the code
 526     * gen phase, so clear it again.
 527     */
 528    bitmap_zero(ctx->pregs_written, NUM_PREGS);
 529
 530    if (HEX_DEBUG) {
 531        /* Handy place to set a breakpoint before the packet executes */
 532        gen_helper_debug_start_packet(cpu_env);
 533    }
 534
 535    /* Initialize the runtime state for packet semantics */
 536    if (need_slot_cancelled(pkt)) {
 537        tcg_gen_movi_tl(hex_slot_cancelled, 0);
 538    }
 539    ctx->branch_taken = NULL;
 540    if (pkt->pkt_has_cof) {
 541        ctx->branch_taken = tcg_temp_new();
 542        if (pkt->pkt_has_multi_cof) {
 543            tcg_gen_movi_tl(ctx->branch_taken, 0);
 544        }
 545        if (need_next_PC(ctx)) {
 546            tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], next_PC);
 547        }
 548    }
 549    if (HEX_DEBUG) {
 550        ctx->pred_written = tcg_temp_new();
 551        tcg_gen_movi_tl(ctx->pred_written, 0);
 552    }
 553
 554    /* Preload the predicated registers into get_result_gpr(ctx, i) */
 555    if (ctx->need_commit &&
 556        !bitmap_empty(ctx->predicated_regs, TOTAL_PER_THREAD_REGS)) {
 557        int i = find_first_bit(ctx->predicated_regs, TOTAL_PER_THREAD_REGS);
 558        while (i < TOTAL_PER_THREAD_REGS) {
 559            tcg_gen_mov_tl(get_result_gpr(ctx, i), hex_gpr[i]);
 560            i = find_next_bit(ctx->predicated_regs, TOTAL_PER_THREAD_REGS,
 561                              i + 1);
 562        }
 563    }
 564
 565    /*
 566     * Preload the predicated pred registers into ctx->new_pred_value[pred_num]
 567     * Only endloop instructions conditionally write to pred registers
 568     */
 569    if (ctx->need_commit && pkt->pkt_has_endloop) {
 570        for (int i = 0; i < ctx->preg_log_idx; i++) {
 571            int pred_num = ctx->preg_log[i];
 572            ctx->new_pred_value[pred_num] = tcg_temp_new();
 573            tcg_gen_mov_tl(ctx->new_pred_value[pred_num], hex_pred[pred_num]);
 574        }
 575    }
 576
 577    /* Preload the predicated HVX registers into future_VRegs and tmp_VRegs */
 578    if (!bitmap_empty(ctx->predicated_future_vregs, NUM_VREGS)) {
 579        int i = find_first_bit(ctx->predicated_future_vregs, NUM_VREGS);
 580        while (i < NUM_VREGS) {
 581            const intptr_t VdV_off =
 582                ctx_future_vreg_off(ctx, i, 1, true);
 583            intptr_t src_off = offsetof(CPUHexagonState, VRegs[i]);
 584            tcg_gen_gvec_mov(MO_64, VdV_off,
 585                             src_off,
 586                             sizeof(MMVector),
 587                             sizeof(MMVector));
 588            i = find_next_bit(ctx->predicated_future_vregs, NUM_VREGS, i + 1);
 589        }
 590    }
 591    if (!bitmap_empty(ctx->predicated_tmp_vregs, NUM_VREGS)) {
 592        int i = find_first_bit(ctx->predicated_tmp_vregs, NUM_VREGS);
 593        while (i < NUM_VREGS) {
 594            const intptr_t VdV_off =
 595                ctx_tmp_vreg_off(ctx, i, 1, true);
 596            intptr_t src_off = offsetof(CPUHexagonState, VRegs[i]);
 597            tcg_gen_gvec_mov(MO_64, VdV_off,
 598                             src_off,
 599                             sizeof(MMVector),
 600                             sizeof(MMVector));
 601            i = find_next_bit(ctx->predicated_tmp_vregs, NUM_VREGS, i + 1);
 602        }
 603    }
 604}
 605
 606bool is_gather_store_insn(DisasContext *ctx)
 607{
 608    Packet *pkt = ctx->pkt;
 609    Insn *insn = ctx->insn;
 610    if (GET_ATTRIB(insn->opcode, A_CVI_NEW) &&
 611        insn->new_value_producer_slot == 1) {
 612        /* Look for gather instruction */
 613        for (int i = 0; i < pkt->num_insns; i++) {
 614            Insn *in = &pkt->insn[i];
 615            if (GET_ATTRIB(in->opcode, A_CVI_GATHER) && in->slot == 1) {
 616                return true;
 617            }
 618        }
 619    }
 620    return false;
 621}
 622
 623static void mark_store_width(DisasContext *ctx)
 624{
 625    uint16_t opcode = ctx->insn->opcode;
 626    uint32_t slot = ctx->insn->slot;
 627    uint8_t width = 0;
 628
 629    if (GET_ATTRIB(opcode, A_SCALAR_STORE)) {
 630        if (GET_ATTRIB(opcode, A_MEMSIZE_0B)) {
 631            return;
 632        }
 633        if (GET_ATTRIB(opcode, A_MEMSIZE_1B)) {
 634            width |= 1;
 635        }
 636        if (GET_ATTRIB(opcode, A_MEMSIZE_2B)) {
 637            width |= 2;
 638        }
 639        if (GET_ATTRIB(opcode, A_MEMSIZE_4B)) {
 640            width |= 4;
 641        }
 642        if (GET_ATTRIB(opcode, A_MEMSIZE_8B)) {
 643            width |= 8;
 644        }
 645        tcg_debug_assert(is_power_of_2(width));
 646        ctx->store_width[slot] = width;
 647    }
 648}
 649
 650static void gen_insn(DisasContext *ctx)
 651{
 652    if (ctx->insn->generate) {
 653        ctx->insn->generate(ctx);
 654        mark_store_width(ctx);
 655    } else {
 656        gen_exception_end_tb(ctx, HEX_EXCP_INVALID_OPCODE);
 657    }
 658}
 659
 660/*
 661 * Helpers for generating the packet commit
 662 */
 663static void gen_reg_writes(DisasContext *ctx)
 664{
 665    int i;
 666
 667    /* Early exit if not needed */
 668    if (!ctx->need_commit) {
 669        return;
 670    }
 671
 672    for (i = 0; i < ctx->reg_log_idx; i++) {
 673        int reg_num = ctx->reg_log[i];
 674
 675        tcg_gen_mov_tl(hex_gpr[reg_num], get_result_gpr(ctx, reg_num));
 676
 677        /*
 678         * ctx->is_tight_loop is set when SA0 points to the beginning of the TB.
 679         * If we write to SA0, we have to turn off tight loop handling.
 680         */
 681        if (reg_num == HEX_REG_SA0) {
 682            ctx->is_tight_loop = false;
 683        }
 684    }
 685}
 686
 687static void gen_pred_writes(DisasContext *ctx)
 688{
 689    /* Early exit if not needed or the log is empty */
 690    if (!ctx->need_commit || !ctx->preg_log_idx) {
 691        return;
 692    }
 693
 694    for (int i = 0; i < ctx->preg_log_idx; i++) {
 695        int pred_num = ctx->preg_log[i];
 696        tcg_gen_mov_tl(hex_pred[pred_num], ctx->new_pred_value[pred_num]);
 697    }
 698}
 699
 700static void gen_check_store_width(DisasContext *ctx, int slot_num)
 701{
 702    if (HEX_DEBUG) {
 703        TCGv slot = tcg_constant_tl(slot_num);
 704        TCGv check = tcg_constant_tl(ctx->store_width[slot_num]);
 705        gen_helper_debug_check_store_width(cpu_env, slot, check);
 706    }
 707}
 708
 709static bool slot_is_predicated(Packet *pkt, int slot_num)
 710{
 711    for (int i = 0; i < pkt->num_insns; i++) {
 712        if (pkt->insn[i].slot == slot_num) {
 713            return GET_ATTRIB(pkt->insn[i].opcode, A_CONDEXEC);
 714        }
 715    }
 716    /* If we get to here, we didn't find an instruction in the requested slot */
 717    g_assert_not_reached();
 718}
 719
 720void process_store(DisasContext *ctx, int slot_num)
 721{
 722    bool is_predicated = slot_is_predicated(ctx->pkt, slot_num);
 723    TCGLabel *label_end = NULL;
 724
 725    /*
 726     * We may have already processed this store
 727     * See CHECK_NOSHUF in macros.h
 728     */
 729    if (slot_num == 1 && ctx->s1_store_processed) {
 730        return;
 731    }
 732    ctx->s1_store_processed = true;
 733
 734    if (is_predicated) {
 735        TCGv cancelled = tcg_temp_new();
 736        label_end = gen_new_label();
 737
 738        /* Don't do anything if the slot was cancelled */
 739        tcg_gen_extract_tl(cancelled, hex_slot_cancelled, slot_num, 1);
 740        tcg_gen_brcondi_tl(TCG_COND_NE, cancelled, 0, label_end);
 741    }
 742    {
 743        TCGv address = tcg_temp_new();
 744        tcg_gen_mov_tl(address, hex_store_addr[slot_num]);
 745
 746        /*
 747         * If we know the width from the DisasContext, we can
 748         * generate much cleaner code.
 749         * Unfortunately, not all instructions execute the fSTORE
 750         * macro during code generation.  Anything that uses the
 751         * generic helper will have this problem.  Instructions
 752         * that use fWRAP to generate proper TCG code will be OK.
 753         */
 754        switch (ctx->store_width[slot_num]) {
 755        case 1:
 756            gen_check_store_width(ctx, slot_num);
 757            tcg_gen_qemu_st_tl(hex_store_val32[slot_num],
 758                               hex_store_addr[slot_num],
 759                               ctx->mem_idx, MO_UB);
 760            break;
 761        case 2:
 762            gen_check_store_width(ctx, slot_num);
 763            tcg_gen_qemu_st_tl(hex_store_val32[slot_num],
 764                               hex_store_addr[slot_num],
 765                               ctx->mem_idx, MO_TEUW);
 766            break;
 767        case 4:
 768            gen_check_store_width(ctx, slot_num);
 769            tcg_gen_qemu_st_tl(hex_store_val32[slot_num],
 770                               hex_store_addr[slot_num],
 771                               ctx->mem_idx, MO_TEUL);
 772            break;
 773        case 8:
 774            gen_check_store_width(ctx, slot_num);
 775            tcg_gen_qemu_st_i64(hex_store_val64[slot_num],
 776                                hex_store_addr[slot_num],
 777                                ctx->mem_idx, MO_TEUQ);
 778            break;
 779        default:
 780            {
 781                /*
 782                 * If we get to here, we don't know the width at
 783                 * TCG generation time, we'll use a helper to
 784                 * avoid branching based on the width at runtime.
 785                 */
 786                TCGv slot = tcg_constant_tl(slot_num);
 787                gen_helper_commit_store(cpu_env, slot);
 788            }
 789        }
 790    }
 791    if (is_predicated) {
 792        gen_set_label(label_end);
 793    }
 794}
 795
 796static void process_store_log(DisasContext *ctx)
 797{
 798    /*
 799     *  When a packet has two stores, the hardware processes
 800     *  slot 1 and then slot 0.  This will be important when
 801     *  the memory accesses overlap.
 802     */
 803    Packet *pkt = ctx->pkt;
 804    if (pkt->pkt_has_store_s1) {
 805        g_assert(!pkt->pkt_has_dczeroa);
 806        process_store(ctx, 1);
 807    }
 808    if (pkt->pkt_has_store_s0) {
 809        g_assert(!pkt->pkt_has_dczeroa);
 810        process_store(ctx, 0);
 811    }
 812}
 813
 814/* Zero out a 32-bit cache line */
 815static void process_dczeroa(DisasContext *ctx)
 816{
 817    if (ctx->pkt->pkt_has_dczeroa) {
 818        /* Store 32 bytes of zero starting at (addr & ~0x1f) */
 819        TCGv addr = tcg_temp_new();
 820        TCGv_i64 zero = tcg_constant_i64(0);
 821
 822        tcg_gen_andi_tl(addr, ctx->dczero_addr, ~0x1f);
 823        tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ);
 824        tcg_gen_addi_tl(addr, addr, 8);
 825        tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ);
 826        tcg_gen_addi_tl(addr, addr, 8);
 827        tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ);
 828        tcg_gen_addi_tl(addr, addr, 8);
 829        tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ);
 830    }
 831}
 832
 833static bool pkt_has_hvx_store(Packet *pkt)
 834{
 835    int i;
 836    for (i = 0; i < pkt->num_insns; i++) {
 837        int opcode = pkt->insn[i].opcode;
 838        if (GET_ATTRIB(opcode, A_CVI) && GET_ATTRIB(opcode, A_STORE)) {
 839            return true;
 840        }
 841    }
 842    return false;
 843}
 844
 845static void gen_commit_hvx(DisasContext *ctx)
 846{
 847    int i;
 848
 849    /* Early exit if not needed */
 850    if (!ctx->need_commit) {
 851        g_assert(!pkt_has_hvx_store(ctx->pkt));
 852        return;
 853    }
 854
 855    /*
 856     *    for (i = 0; i < ctx->vreg_log_idx; i++) {
 857     *        int rnum = ctx->vreg_log[i];
 858     *        env->VRegs[rnum] = env->future_VRegs[rnum];
 859     *    }
 860     */
 861    for (i = 0; i < ctx->vreg_log_idx; i++) {
 862        int rnum = ctx->vreg_log[i];
 863        intptr_t dstoff = offsetof(CPUHexagonState, VRegs[rnum]);
 864        intptr_t srcoff = ctx_future_vreg_off(ctx, rnum, 1, false);
 865        size_t size = sizeof(MMVector);
 866
 867        tcg_gen_gvec_mov(MO_64, dstoff, srcoff, size, size);
 868    }
 869
 870    /*
 871     *    for (i = 0; i < ctx->qreg_log_idx; i++) {
 872     *        int rnum = ctx->qreg_log[i];
 873     *        env->QRegs[rnum] = env->future_QRegs[rnum];
 874     *    }
 875     */
 876    for (i = 0; i < ctx->qreg_log_idx; i++) {
 877        int rnum = ctx->qreg_log[i];
 878        intptr_t dstoff = offsetof(CPUHexagonState, QRegs[rnum]);
 879        intptr_t srcoff = offsetof(CPUHexagonState, future_QRegs[rnum]);
 880        size_t size = sizeof(MMQReg);
 881
 882        tcg_gen_gvec_mov(MO_64, dstoff, srcoff, size, size);
 883    }
 884
 885    if (pkt_has_hvx_store(ctx->pkt)) {
 886        gen_helper_commit_hvx_stores(cpu_env);
 887    }
 888}
 889
 890static void update_exec_counters(DisasContext *ctx)
 891{
 892    Packet *pkt = ctx->pkt;
 893    int num_insns = pkt->num_insns;
 894    int num_real_insns = 0;
 895    int num_hvx_insns = 0;
 896
 897    for (int i = 0; i < num_insns; i++) {
 898        if (!pkt->insn[i].is_endloop &&
 899            !pkt->insn[i].part1 &&
 900            !GET_ATTRIB(pkt->insn[i].opcode, A_IT_NOP)) {
 901            num_real_insns++;
 902        }
 903        if (GET_ATTRIB(pkt->insn[i].opcode, A_CVI)) {
 904            num_hvx_insns++;
 905        }
 906    }
 907
 908    ctx->num_packets++;
 909    ctx->num_insns += num_real_insns;
 910    ctx->num_hvx_insns += num_hvx_insns;
 911}
 912
 913static void gen_commit_packet(DisasContext *ctx)
 914{
 915    /*
 916     * If there is more than one store in a packet, make sure they are all OK
 917     * before proceeding with the rest of the packet commit.
 918     *
 919     * dczeroa has to be the only store operation in the packet, so we go
 920     * ahead and process that first.
 921     *
 922     * When there is an HVX store, there can also be a scalar store in either
 923     * slot 0 or slot1, so we create a mask for the helper to indicate what
 924     * work to do.
 925     *
 926     * When there are two scalar stores, we probe the one in slot 0.
 927     *
 928     * Note that we don't call the probe helper for packets with only one
 929     * store.  Therefore, we call process_store_log before anything else
 930     * involved in committing the packet.
 931     */
 932    Packet *pkt = ctx->pkt;
 933    bool has_store_s0 = pkt->pkt_has_store_s0;
 934    bool has_store_s1 = (pkt->pkt_has_store_s1 && !ctx->s1_store_processed);
 935    bool has_hvx_store = pkt_has_hvx_store(pkt);
 936    if (pkt->pkt_has_dczeroa) {
 937        /*
 938         * The dczeroa will be the store in slot 0, check that we don't have
 939         * a store in slot 1 or an HVX store.
 940         */
 941        g_assert(!has_store_s1 && !has_hvx_store);
 942        process_dczeroa(ctx);
 943    } else if (has_hvx_store) {
 944        if (!has_store_s0 && !has_store_s1) {
 945            TCGv mem_idx = tcg_constant_tl(ctx->mem_idx);
 946            gen_helper_probe_hvx_stores(cpu_env, mem_idx);
 947        } else {
 948            int mask = 0;
 949
 950            if (has_store_s0) {
 951                mask =
 952                    FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_ST0, 1);
 953            }
 954            if (has_store_s1) {
 955                mask =
 956                    FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_ST1, 1);
 957            }
 958            if (has_hvx_store) {
 959                mask =
 960                    FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES,
 961                               HAS_HVX_STORES, 1);
 962            }
 963            if (has_store_s0 && slot_is_predicated(pkt, 0)) {
 964                mask =
 965                    FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES,
 966                               S0_IS_PRED, 1);
 967            }
 968            if (has_store_s1 && slot_is_predicated(pkt, 1)) {
 969                mask =
 970                    FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES,
 971                               S1_IS_PRED, 1);
 972            }
 973            mask = FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES, MMU_IDX,
 974                              ctx->mem_idx);
 975            gen_helper_probe_pkt_scalar_hvx_stores(cpu_env,
 976                                                   tcg_constant_tl(mask));
 977        }
 978    } else if (has_store_s0 && has_store_s1) {
 979        /*
 980         * process_store_log will execute the slot 1 store first,
 981         * so we only have to probe the store in slot 0
 982         */
 983        int args = 0;
 984        args =
 985            FIELD_DP32(args, PROBE_PKT_SCALAR_STORE_S0, MMU_IDX, ctx->mem_idx);
 986        if (slot_is_predicated(pkt, 0)) {
 987            args =
 988                FIELD_DP32(args, PROBE_PKT_SCALAR_STORE_S0, IS_PREDICATED, 1);
 989        }
 990        TCGv args_tcgv = tcg_constant_tl(args);
 991        gen_helper_probe_pkt_scalar_store_s0(cpu_env, args_tcgv);
 992    }
 993
 994    process_store_log(ctx);
 995
 996    gen_reg_writes(ctx);
 997    gen_pred_writes(ctx);
 998    if (pkt->pkt_has_hvx) {
 999        gen_commit_hvx(ctx);
1000    }
1001    update_exec_counters(ctx);
1002    if (HEX_DEBUG) {
1003        TCGv has_st0 =
1004            tcg_constant_tl(pkt->pkt_has_store_s0 && !pkt->pkt_has_dczeroa);
1005        TCGv has_st1 =
1006            tcg_constant_tl(pkt->pkt_has_store_s1 && !pkt->pkt_has_dczeroa);
1007
1008        /* Handy place to set a breakpoint at the end of execution */
1009        gen_helper_debug_commit_end(cpu_env, tcg_constant_tl(ctx->pkt->pc),
1010                                    ctx->pred_written, has_st0, has_st1);
1011    }
1012
1013    if (pkt->vhist_insn != NULL) {
1014        ctx->pre_commit = false;
1015        ctx->insn = pkt->vhist_insn;
1016        pkt->vhist_insn->generate(ctx);
1017    }
1018
1019    if (pkt->pkt_has_cof) {
1020        gen_end_tb(ctx);
1021    }
1022}
1023
1024static void decode_and_translate_packet(CPUHexagonState *env, DisasContext *ctx)
1025{
1026    uint32_t words[PACKET_WORDS_MAX];
1027    int nwords;
1028    Packet pkt;
1029    int i;
1030
1031    nwords = read_packet_words(env, ctx, words);
1032    if (!nwords) {
1033        gen_exception_end_tb(ctx, HEX_EXCP_INVALID_PACKET);
1034        return;
1035    }
1036
1037    if (decode_packet(nwords, words, &pkt, false) > 0) {
1038        pkt.pc = ctx->base.pc_next;
1039        HEX_DEBUG_PRINT_PKT(&pkt);
1040        ctx->pkt = &pkt;
1041        gen_start_packet(ctx);
1042        for (i = 0; i < pkt.num_insns; i++) {
1043            ctx->insn = &pkt.insn[i];
1044            gen_insn(ctx);
1045        }
1046        gen_commit_packet(ctx);
1047        ctx->base.pc_next += pkt.encod_pkt_size_in_bytes;
1048    } else {
1049        gen_exception_end_tb(ctx, HEX_EXCP_INVALID_PACKET);
1050    }
1051}
1052
1053static void hexagon_tr_init_disas_context(DisasContextBase *dcbase,
1054                                          CPUState *cs)
1055{
1056    DisasContext *ctx = container_of(dcbase, DisasContext, base);
1057    HexagonCPU *hex_cpu = env_archcpu(cs->env_ptr);
1058    uint32_t hex_flags = dcbase->tb->flags;
1059
1060    ctx->mem_idx = MMU_USER_IDX;
1061    ctx->num_packets = 0;
1062    ctx->num_insns = 0;
1063    ctx->num_hvx_insns = 0;
1064    ctx->branch_cond = TCG_COND_NEVER;
1065    ctx->is_tight_loop = FIELD_EX32(hex_flags, TB_FLAGS, IS_TIGHT_LOOP);
1066    ctx->short_circuit = hex_cpu->short_circuit;
1067}
1068
1069static void hexagon_tr_tb_start(DisasContextBase *db, CPUState *cpu)
1070{
1071}
1072
1073static void hexagon_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
1074{
1075    DisasContext *ctx = container_of(dcbase, DisasContext, base);
1076
1077    tcg_gen_insn_start(ctx->base.pc_next);
1078}
1079
1080static bool pkt_crosses_page(CPUHexagonState *env, DisasContext *ctx)
1081{
1082    target_ulong page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
1083    bool found_end = false;
1084    int nwords;
1085
1086    for (nwords = 0; !found_end && nwords < PACKET_WORDS_MAX; nwords++) {
1087        uint32_t word = cpu_ldl_code(env,
1088                            ctx->base.pc_next + nwords * sizeof(uint32_t));
1089        found_end = is_packet_end(word);
1090    }
1091    uint32_t next_ptr =  ctx->base.pc_next + nwords * sizeof(uint32_t);
1092    return found_end && next_ptr - page_start >= TARGET_PAGE_SIZE;
1093}
1094
1095static void hexagon_tr_translate_packet(DisasContextBase *dcbase, CPUState *cpu)
1096{
1097    DisasContext *ctx = container_of(dcbase, DisasContext, base);
1098    CPUHexagonState *env = cpu->env_ptr;
1099
1100    decode_and_translate_packet(env, ctx);
1101
1102    if (ctx->base.is_jmp == DISAS_NEXT) {
1103        target_ulong page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
1104        target_ulong bytes_max = PACKET_WORDS_MAX * sizeof(target_ulong);
1105
1106        if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE ||
1107            (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE - bytes_max &&
1108             pkt_crosses_page(env, ctx))) {
1109            ctx->base.is_jmp = DISAS_TOO_MANY;
1110        }
1111
1112        /*
1113         * The CPU log is used to compare against LLDB single stepping,
1114         * so end the TLB after every packet.
1115         */
1116        HexagonCPU *hex_cpu = env_archcpu(env);
1117        if (hex_cpu->lldb_compat && qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
1118            ctx->base.is_jmp = DISAS_TOO_MANY;
1119        }
1120    }
1121}
1122
1123static void hexagon_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
1124{
1125    DisasContext *ctx = container_of(dcbase, DisasContext, base);
1126
1127    switch (ctx->base.is_jmp) {
1128    case DISAS_TOO_MANY:
1129        gen_exec_counters(ctx);
1130        tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->base.pc_next);
1131        tcg_gen_exit_tb(NULL, 0);
1132        break;
1133    case DISAS_NORETURN:
1134        break;
1135    default:
1136        g_assert_not_reached();
1137    }
1138}
1139
1140static void hexagon_tr_disas_log(const DisasContextBase *dcbase,
1141                                 CPUState *cpu, FILE *logfile)
1142{
1143    fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
1144    target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size);
1145}
1146
1147
1148static const TranslatorOps hexagon_tr_ops = {
1149    .init_disas_context = hexagon_tr_init_disas_context,
1150    .tb_start           = hexagon_tr_tb_start,
1151    .insn_start         = hexagon_tr_insn_start,
1152    .translate_insn     = hexagon_tr_translate_packet,
1153    .tb_stop            = hexagon_tr_tb_stop,
1154    .disas_log          = hexagon_tr_disas_log,
1155};
1156
1157void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
1158                           target_ulong pc, void *host_pc)
1159{
1160    DisasContext ctx;
1161
1162    translator_loop(cs, tb, max_insns, pc, host_pc,
1163                    &hexagon_tr_ops, &ctx.base);
1164}
1165
1166#define NAME_LEN               64
1167static char reg_written_names[TOTAL_PER_THREAD_REGS][NAME_LEN];
1168static char store_addr_names[STORES_MAX][NAME_LEN];
1169static char store_width_names[STORES_MAX][NAME_LEN];
1170static char store_val32_names[STORES_MAX][NAME_LEN];
1171static char store_val64_names[STORES_MAX][NAME_LEN];
1172static char vstore_addr_names[VSTORES_MAX][NAME_LEN];
1173static char vstore_size_names[VSTORES_MAX][NAME_LEN];
1174static char vstore_pending_names[VSTORES_MAX][NAME_LEN];
1175
1176void hexagon_translate_init(void)
1177{
1178    int i;
1179
1180    opcode_init();
1181
1182    for (i = 0; i < TOTAL_PER_THREAD_REGS; i++) {
1183        hex_gpr[i] = tcg_global_mem_new(cpu_env,
1184            offsetof(CPUHexagonState, gpr[i]),
1185            hexagon_regnames[i]);
1186
1187        if (HEX_DEBUG) {
1188            snprintf(reg_written_names[i], NAME_LEN, "reg_written_%s",
1189                     hexagon_regnames[i]);
1190            hex_reg_written[i] = tcg_global_mem_new(cpu_env,
1191                offsetof(CPUHexagonState, reg_written[i]),
1192                reg_written_names[i]);
1193        }
1194    }
1195    hex_new_value_usr = tcg_global_mem_new(cpu_env,
1196        offsetof(CPUHexagonState, new_value_usr), "new_value_usr");
1197
1198    for (i = 0; i < NUM_PREGS; i++) {
1199        hex_pred[i] = tcg_global_mem_new(cpu_env,
1200            offsetof(CPUHexagonState, pred[i]),
1201            hexagon_prednames[i]);
1202    }
1203    hex_slot_cancelled = tcg_global_mem_new(cpu_env,
1204        offsetof(CPUHexagonState, slot_cancelled), "slot_cancelled");
1205    hex_llsc_addr = tcg_global_mem_new(cpu_env,
1206        offsetof(CPUHexagonState, llsc_addr), "llsc_addr");
1207    hex_llsc_val = tcg_global_mem_new(cpu_env,
1208        offsetof(CPUHexagonState, llsc_val), "llsc_val");
1209    hex_llsc_val_i64 = tcg_global_mem_new_i64(cpu_env,
1210        offsetof(CPUHexagonState, llsc_val_i64), "llsc_val_i64");
1211    for (i = 0; i < STORES_MAX; i++) {
1212        snprintf(store_addr_names[i], NAME_LEN, "store_addr_%d", i);
1213        hex_store_addr[i] = tcg_global_mem_new(cpu_env,
1214            offsetof(CPUHexagonState, mem_log_stores[i].va),
1215            store_addr_names[i]);
1216
1217        snprintf(store_width_names[i], NAME_LEN, "store_width_%d", i);
1218        hex_store_width[i] = tcg_global_mem_new(cpu_env,
1219            offsetof(CPUHexagonState, mem_log_stores[i].width),
1220            store_width_names[i]);
1221
1222        snprintf(store_val32_names[i], NAME_LEN, "store_val32_%d", i);
1223        hex_store_val32[i] = tcg_global_mem_new(cpu_env,
1224            offsetof(CPUHexagonState, mem_log_stores[i].data32),
1225            store_val32_names[i]);
1226
1227        snprintf(store_val64_names[i], NAME_LEN, "store_val64_%d", i);
1228        hex_store_val64[i] = tcg_global_mem_new_i64(cpu_env,
1229            offsetof(CPUHexagonState, mem_log_stores[i].data64),
1230            store_val64_names[i]);
1231    }
1232    for (int i = 0; i < VSTORES_MAX; i++) {
1233        snprintf(vstore_addr_names[i], NAME_LEN, "vstore_addr_%d", i);
1234        hex_vstore_addr[i] = tcg_global_mem_new(cpu_env,
1235            offsetof(CPUHexagonState, vstore[i].va),
1236            vstore_addr_names[i]);
1237
1238        snprintf(vstore_size_names[i], NAME_LEN, "vstore_size_%d", i);
1239        hex_vstore_size[i] = tcg_global_mem_new(cpu_env,
1240            offsetof(CPUHexagonState, vstore[i].size),
1241            vstore_size_names[i]);
1242
1243        snprintf(vstore_pending_names[i], NAME_LEN, "vstore_pending_%d", i);
1244        hex_vstore_pending[i] = tcg_global_mem_new(cpu_env,
1245            offsetof(CPUHexagonState, vstore_pending[i]),
1246            vstore_pending_names[i]);
1247    }
1248}
1249