qemu/target/hexagon/translate.c
<<
>>
Prefs
   1/*
   2 *  Copyright(c) 2019-2021 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 "exec/cpu_ldst.h"
  23#include "exec/log.h"
  24#include "internal.h"
  25#include "attribs.h"
  26#include "insn.h"
  27#include "decode.h"
  28#include "translate.h"
  29#include "printinsn.h"
  30
  31TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
  32TCGv hex_pred[NUM_PREGS];
  33TCGv hex_next_PC;
  34TCGv hex_this_PC;
  35TCGv hex_slot_cancelled;
  36TCGv hex_branch_taken;
  37TCGv hex_new_value[TOTAL_PER_THREAD_REGS];
  38TCGv hex_reg_written[TOTAL_PER_THREAD_REGS];
  39TCGv hex_new_pred_value[NUM_PREGS];
  40TCGv hex_pred_written;
  41TCGv hex_store_addr[STORES_MAX];
  42TCGv hex_store_width[STORES_MAX];
  43TCGv hex_store_val32[STORES_MAX];
  44TCGv_i64 hex_store_val64[STORES_MAX];
  45TCGv hex_pkt_has_store_s1;
  46TCGv hex_dczero_addr;
  47TCGv hex_llsc_addr;
  48TCGv hex_llsc_val;
  49TCGv_i64 hex_llsc_val_i64;
  50
  51static const char * const hexagon_prednames[] = {
  52  "p0", "p1", "p2", "p3"
  53};
  54
  55static void gen_exception_raw(int excp)
  56{
  57    TCGv_i32 helper_tmp = tcg_const_i32(excp);
  58    gen_helper_raise_exception(cpu_env, helper_tmp);
  59    tcg_temp_free_i32(helper_tmp);
  60}
  61
  62static void gen_exec_counters(DisasContext *ctx)
  63{
  64    tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_PKT_CNT],
  65                    hex_gpr[HEX_REG_QEMU_PKT_CNT], ctx->num_packets);
  66    tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_INSN_CNT],
  67                    hex_gpr[HEX_REG_QEMU_INSN_CNT], ctx->num_insns);
  68}
  69
  70static void gen_end_tb(DisasContext *ctx)
  71{
  72    gen_exec_counters(ctx);
  73    tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], hex_next_PC);
  74    if (ctx->base.singlestep_enabled) {
  75        gen_exception_raw(EXCP_DEBUG);
  76    } else {
  77        tcg_gen_exit_tb(NULL, 0);
  78    }
  79    ctx->base.is_jmp = DISAS_NORETURN;
  80}
  81
  82static void gen_exception_end_tb(DisasContext *ctx, int excp)
  83{
  84    gen_exec_counters(ctx);
  85    tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], hex_next_PC);
  86    gen_exception_raw(excp);
  87    ctx->base.is_jmp = DISAS_NORETURN;
  88
  89}
  90
  91#define PACKET_BUFFER_LEN              1028
  92static void print_pkt(Packet *pkt)
  93{
  94    GString *buf = g_string_sized_new(PACKET_BUFFER_LEN);
  95    snprint_a_pkt_debug(buf, pkt);
  96    HEX_DEBUG_LOG("%s", buf->str);
  97    g_string_free(buf, true);
  98}
  99#define HEX_DEBUG_PRINT_PKT(pkt) \
 100    do { \
 101        if (HEX_DEBUG) { \
 102            print_pkt(pkt); \
 103        } \
 104    } while (0)
 105
 106static int read_packet_words(CPUHexagonState *env, DisasContext *ctx,
 107                             uint32_t words[])
 108{
 109    bool found_end = false;
 110    int nwords, max_words;
 111
 112    memset(words, 0, PACKET_WORDS_MAX * sizeof(uint32_t));
 113    for (nwords = 0; !found_end && nwords < PACKET_WORDS_MAX; nwords++) {
 114        words[nwords] =
 115            translator_ldl(env, ctx->base.pc_next + nwords * sizeof(uint32_t));
 116        found_end = is_packet_end(words[nwords]);
 117    }
 118    if (!found_end) {
 119        /* Read too many words without finding the end */
 120        return 0;
 121    }
 122
 123    /* Check for page boundary crossing */
 124    max_words = -(ctx->base.pc_next | TARGET_PAGE_MASK) / sizeof(uint32_t);
 125    if (nwords > max_words) {
 126        /* We can only cross a page boundary at the beginning of a TB */
 127        g_assert(ctx->base.num_insns == 1);
 128    }
 129
 130    HEX_DEBUG_LOG("decode_packet: pc = 0x%x\n", ctx->base.pc_next);
 131    HEX_DEBUG_LOG("    words = { ");
 132    for (int i = 0; i < nwords; i++) {
 133        HEX_DEBUG_LOG("0x%x, ", words[i]);
 134    }
 135    HEX_DEBUG_LOG("}\n");
 136
 137    return nwords;
 138}
 139
 140static bool check_for_attrib(Packet *pkt, int attrib)
 141{
 142    for (int i = 0; i < pkt->num_insns; i++) {
 143        if (GET_ATTRIB(pkt->insn[i].opcode, attrib)) {
 144            return true;
 145        }
 146    }
 147    return false;
 148}
 149
 150static bool need_pc(Packet *pkt)
 151{
 152    return check_for_attrib(pkt, A_IMPLICIT_READS_PC);
 153}
 154
 155static bool need_slot_cancelled(Packet *pkt)
 156{
 157    return check_for_attrib(pkt, A_CONDEXEC);
 158}
 159
 160static bool need_pred_written(Packet *pkt)
 161{
 162    return check_for_attrib(pkt, A_WRITES_PRED_REG);
 163}
 164
 165static void gen_start_packet(DisasContext *ctx, Packet *pkt)
 166{
 167    target_ulong next_PC = ctx->base.pc_next + pkt->encod_pkt_size_in_bytes;
 168    int i;
 169
 170    /* Clear out the disassembly context */
 171    ctx->reg_log_idx = 0;
 172    bitmap_zero(ctx->regs_written, TOTAL_PER_THREAD_REGS);
 173    ctx->preg_log_idx = 0;
 174    bitmap_zero(ctx->pregs_written, NUM_PREGS);
 175    for (i = 0; i < STORES_MAX; i++) {
 176        ctx->store_width[i] = 0;
 177    }
 178    tcg_gen_movi_tl(hex_pkt_has_store_s1, pkt->pkt_has_store_s1);
 179    ctx->s1_store_processed = false;
 180
 181    if (HEX_DEBUG) {
 182        /* Handy place to set a breakpoint before the packet executes */
 183        gen_helper_debug_start_packet(cpu_env);
 184        tcg_gen_movi_tl(hex_this_PC, ctx->base.pc_next);
 185    }
 186
 187    /* Initialize the runtime state for packet semantics */
 188    if (need_pc(pkt)) {
 189        tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->base.pc_next);
 190    }
 191    if (need_slot_cancelled(pkt)) {
 192        tcg_gen_movi_tl(hex_slot_cancelled, 0);
 193    }
 194    if (pkt->pkt_has_cof) {
 195        tcg_gen_movi_tl(hex_branch_taken, 0);
 196        tcg_gen_movi_tl(hex_next_PC, next_PC);
 197    }
 198    if (need_pred_written(pkt)) {
 199        tcg_gen_movi_tl(hex_pred_written, 0);
 200    }
 201}
 202
 203/*
 204 * The LOG_*_WRITE macros mark most of the writes in a packet
 205 * However, there are some implicit writes marked as attributes
 206 * of the applicable instructions.
 207 */
 208static void mark_implicit_reg_write(DisasContext *ctx, Insn *insn,
 209                                    int attrib, int rnum)
 210{
 211    if (GET_ATTRIB(insn->opcode, attrib)) {
 212        bool is_predicated = GET_ATTRIB(insn->opcode, A_CONDEXEC);
 213        if (is_predicated && !is_preloaded(ctx, rnum)) {
 214            tcg_gen_mov_tl(hex_new_value[rnum], hex_gpr[rnum]);
 215        }
 216
 217        ctx_log_reg_write(ctx, rnum);
 218    }
 219}
 220
 221static void mark_implicit_pred_write(DisasContext *ctx, Insn *insn,
 222                                     int attrib, int pnum)
 223{
 224    if (GET_ATTRIB(insn->opcode, attrib)) {
 225        ctx_log_pred_write(ctx, pnum);
 226    }
 227}
 228
 229static void mark_implicit_reg_writes(DisasContext *ctx, Insn *insn)
 230{
 231    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_FP,  HEX_REG_FP);
 232    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SP,  HEX_REG_SP);
 233    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_LR,  HEX_REG_LR);
 234    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_LC0, HEX_REG_LC0);
 235    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SA0, HEX_REG_SA0);
 236    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_LC1, HEX_REG_LC1);
 237    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SA1, HEX_REG_SA1);
 238}
 239
 240static void mark_implicit_pred_writes(DisasContext *ctx, Insn *insn)
 241{
 242    mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P0, 0);
 243    mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P1, 1);
 244    mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P2, 2);
 245    mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P3, 3);
 246}
 247
 248static void gen_insn(CPUHexagonState *env, DisasContext *ctx,
 249                     Insn *insn, Packet *pkt)
 250{
 251    if (insn->generate) {
 252        mark_implicit_reg_writes(ctx, insn);
 253        insn->generate(env, ctx, insn, pkt);
 254        mark_implicit_pred_writes(ctx, insn);
 255    } else {
 256        gen_exception_end_tb(ctx, HEX_EXCP_INVALID_OPCODE);
 257    }
 258}
 259
 260/*
 261 * Helpers for generating the packet commit
 262 */
 263static void gen_reg_writes(DisasContext *ctx)
 264{
 265    int i;
 266
 267    for (i = 0; i < ctx->reg_log_idx; i++) {
 268        int reg_num = ctx->reg_log[i];
 269
 270        tcg_gen_mov_tl(hex_gpr[reg_num], hex_new_value[reg_num]);
 271    }
 272}
 273
 274static void gen_pred_writes(DisasContext *ctx, Packet *pkt)
 275{
 276    int i;
 277
 278    /* Early exit if the log is empty */
 279    if (!ctx->preg_log_idx) {
 280        return;
 281    }
 282
 283    /*
 284     * Only endloop instructions will conditionally
 285     * write a predicate.  If there are no endloop
 286     * instructions, we can use the non-conditional
 287     * write of the predicates.
 288     */
 289    if (pkt->pkt_has_endloop) {
 290        TCGv zero = tcg_const_tl(0);
 291        TCGv pred_written = tcg_temp_new();
 292        for (i = 0; i < ctx->preg_log_idx; i++) {
 293            int pred_num = ctx->preg_log[i];
 294
 295            tcg_gen_andi_tl(pred_written, hex_pred_written, 1 << pred_num);
 296            tcg_gen_movcond_tl(TCG_COND_NE, hex_pred[pred_num],
 297                               pred_written, zero,
 298                               hex_new_pred_value[pred_num],
 299                               hex_pred[pred_num]);
 300        }
 301        tcg_temp_free(zero);
 302        tcg_temp_free(pred_written);
 303    } else {
 304        for (i = 0; i < ctx->preg_log_idx; i++) {
 305            int pred_num = ctx->preg_log[i];
 306            tcg_gen_mov_tl(hex_pred[pred_num], hex_new_pred_value[pred_num]);
 307            if (HEX_DEBUG) {
 308                /* Do this so HELPER(debug_commit_end) will know */
 309                tcg_gen_ori_tl(hex_pred_written, hex_pred_written,
 310                               1 << pred_num);
 311            }
 312        }
 313    }
 314}
 315
 316static void gen_check_store_width(DisasContext *ctx, int slot_num)
 317{
 318    if (HEX_DEBUG) {
 319        TCGv slot = tcg_const_tl(slot_num);
 320        TCGv check = tcg_const_tl(ctx->store_width[slot_num]);
 321        gen_helper_debug_check_store_width(cpu_env, slot, check);
 322        tcg_temp_free(slot);
 323        tcg_temp_free(check);
 324    }
 325}
 326
 327static bool slot_is_predicated(Packet *pkt, int slot_num)
 328{
 329    for (int i = 0; i < pkt->num_insns; i++) {
 330        if (pkt->insn[i].slot == slot_num) {
 331            return GET_ATTRIB(pkt->insn[i].opcode, A_CONDEXEC);
 332        }
 333    }
 334    /* If we get to here, we didn't find an instruction in the requested slot */
 335    g_assert_not_reached();
 336}
 337
 338void process_store(DisasContext *ctx, Packet *pkt, int slot_num)
 339{
 340    bool is_predicated = slot_is_predicated(pkt, slot_num);
 341    TCGLabel *label_end = NULL;
 342
 343    /*
 344     * We may have already processed this store
 345     * See CHECK_NOSHUF in macros.h
 346     */
 347    if (slot_num == 1 && ctx->s1_store_processed) {
 348        return;
 349    }
 350    ctx->s1_store_processed = true;
 351
 352    if (is_predicated) {
 353        TCGv cancelled = tcg_temp_new();
 354        label_end = gen_new_label();
 355
 356        /* Don't do anything if the slot was cancelled */
 357        tcg_gen_extract_tl(cancelled, hex_slot_cancelled, slot_num, 1);
 358        tcg_gen_brcondi_tl(TCG_COND_NE, cancelled, 0, label_end);
 359        tcg_temp_free(cancelled);
 360    }
 361    {
 362        TCGv address = tcg_temp_local_new();
 363        tcg_gen_mov_tl(address, hex_store_addr[slot_num]);
 364
 365        /*
 366         * If we know the width from the DisasContext, we can
 367         * generate much cleaner code.
 368         * Unfortunately, not all instructions execute the fSTORE
 369         * macro during code generation.  Anything that uses the
 370         * generic helper will have this problem.  Instructions
 371         * that use fWRAP to generate proper TCG code will be OK.
 372         */
 373        switch (ctx->store_width[slot_num]) {
 374        case 1:
 375            gen_check_store_width(ctx, slot_num);
 376            tcg_gen_qemu_st8(hex_store_val32[slot_num],
 377                             hex_store_addr[slot_num],
 378                             ctx->mem_idx);
 379            break;
 380        case 2:
 381            gen_check_store_width(ctx, slot_num);
 382            tcg_gen_qemu_st16(hex_store_val32[slot_num],
 383                              hex_store_addr[slot_num],
 384                              ctx->mem_idx);
 385            break;
 386        case 4:
 387            gen_check_store_width(ctx, slot_num);
 388            tcg_gen_qemu_st32(hex_store_val32[slot_num],
 389                              hex_store_addr[slot_num],
 390                              ctx->mem_idx);
 391            break;
 392        case 8:
 393            gen_check_store_width(ctx, slot_num);
 394            tcg_gen_qemu_st64(hex_store_val64[slot_num],
 395                              hex_store_addr[slot_num],
 396                              ctx->mem_idx);
 397            break;
 398        default:
 399            {
 400                /*
 401                 * If we get to here, we don't know the width at
 402                 * TCG generation time, we'll use a helper to
 403                 * avoid branching based on the width at runtime.
 404                 */
 405                TCGv slot = tcg_const_tl(slot_num);
 406                gen_helper_commit_store(cpu_env, slot);
 407                tcg_temp_free(slot);
 408            }
 409        }
 410        tcg_temp_free(address);
 411    }
 412    if (is_predicated) {
 413        gen_set_label(label_end);
 414    }
 415}
 416
 417static void process_store_log(DisasContext *ctx, Packet *pkt)
 418{
 419    /*
 420     *  When a packet has two stores, the hardware processes
 421     *  slot 1 and then slot 2.  This will be important when
 422     *  the memory accesses overlap.
 423     */
 424    if (pkt->pkt_has_store_s1 && !pkt->pkt_has_dczeroa) {
 425        process_store(ctx, pkt, 1);
 426    }
 427    if (pkt->pkt_has_store_s0 && !pkt->pkt_has_dczeroa) {
 428        process_store(ctx, pkt, 0);
 429    }
 430}
 431
 432/* Zero out a 32-bit cache line */
 433static void process_dczeroa(DisasContext *ctx, Packet *pkt)
 434{
 435    if (pkt->pkt_has_dczeroa) {
 436        /* Store 32 bytes of zero starting at (addr & ~0x1f) */
 437        TCGv addr = tcg_temp_new();
 438        TCGv_i64 zero = tcg_const_i64(0);
 439
 440        tcg_gen_andi_tl(addr, hex_dczero_addr, ~0x1f);
 441        tcg_gen_qemu_st64(zero, addr, ctx->mem_idx);
 442        tcg_gen_addi_tl(addr, addr, 8);
 443        tcg_gen_qemu_st64(zero, addr, ctx->mem_idx);
 444        tcg_gen_addi_tl(addr, addr, 8);
 445        tcg_gen_qemu_st64(zero, addr, ctx->mem_idx);
 446        tcg_gen_addi_tl(addr, addr, 8);
 447        tcg_gen_qemu_st64(zero, addr, ctx->mem_idx);
 448
 449        tcg_temp_free(addr);
 450        tcg_temp_free_i64(zero);
 451    }
 452}
 453
 454static void update_exec_counters(DisasContext *ctx, Packet *pkt)
 455{
 456    int num_insns = pkt->num_insns;
 457    int num_real_insns = 0;
 458
 459    for (int i = 0; i < num_insns; i++) {
 460        if (!pkt->insn[i].is_endloop &&
 461            !pkt->insn[i].part1 &&
 462            !GET_ATTRIB(pkt->insn[i].opcode, A_IT_NOP)) {
 463            num_real_insns++;
 464        }
 465    }
 466
 467    ctx->num_packets++;
 468    ctx->num_insns += num_real_insns;
 469}
 470
 471static void gen_commit_packet(DisasContext *ctx, Packet *pkt)
 472{
 473    gen_reg_writes(ctx);
 474    gen_pred_writes(ctx, pkt);
 475    process_store_log(ctx, pkt);
 476    process_dczeroa(ctx, pkt);
 477    update_exec_counters(ctx, pkt);
 478    if (HEX_DEBUG) {
 479        TCGv has_st0 =
 480            tcg_const_tl(pkt->pkt_has_store_s0 && !pkt->pkt_has_dczeroa);
 481        TCGv has_st1 =
 482            tcg_const_tl(pkt->pkt_has_store_s1 && !pkt->pkt_has_dczeroa);
 483
 484        /* Handy place to set a breakpoint at the end of execution */
 485        gen_helper_debug_commit_end(cpu_env, has_st0, has_st1);
 486
 487        tcg_temp_free(has_st0);
 488        tcg_temp_free(has_st1);
 489    }
 490
 491    if (pkt->pkt_has_cof) {
 492        gen_end_tb(ctx);
 493    }
 494}
 495
 496static void decode_and_translate_packet(CPUHexagonState *env, DisasContext *ctx)
 497{
 498    uint32_t words[PACKET_WORDS_MAX];
 499    int nwords;
 500    Packet pkt;
 501    int i;
 502
 503    nwords = read_packet_words(env, ctx, words);
 504    if (!nwords) {
 505        gen_exception_end_tb(ctx, HEX_EXCP_INVALID_PACKET);
 506        return;
 507    }
 508
 509    if (decode_packet(nwords, words, &pkt, false) > 0) {
 510        HEX_DEBUG_PRINT_PKT(&pkt);
 511        gen_start_packet(ctx, &pkt);
 512        for (i = 0; i < pkt.num_insns; i++) {
 513            gen_insn(env, ctx, &pkt.insn[i], &pkt);
 514        }
 515        gen_commit_packet(ctx, &pkt);
 516        ctx->base.pc_next += pkt.encod_pkt_size_in_bytes;
 517    } else {
 518        gen_exception_end_tb(ctx, HEX_EXCP_INVALID_PACKET);
 519    }
 520}
 521
 522static void hexagon_tr_init_disas_context(DisasContextBase *dcbase,
 523                                          CPUState *cs)
 524{
 525    DisasContext *ctx = container_of(dcbase, DisasContext, base);
 526
 527    ctx->mem_idx = MMU_USER_IDX;
 528    ctx->num_packets = 0;
 529    ctx->num_insns = 0;
 530}
 531
 532static void hexagon_tr_tb_start(DisasContextBase *db, CPUState *cpu)
 533{
 534}
 535
 536static void hexagon_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
 537{
 538    DisasContext *ctx = container_of(dcbase, DisasContext, base);
 539
 540    tcg_gen_insn_start(ctx->base.pc_next);
 541}
 542
 543static bool pkt_crosses_page(CPUHexagonState *env, DisasContext *ctx)
 544{
 545    target_ulong page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
 546    bool found_end = false;
 547    int nwords;
 548
 549    for (nwords = 0; !found_end && nwords < PACKET_WORDS_MAX; nwords++) {
 550        uint32_t word = cpu_ldl_code(env,
 551                            ctx->base.pc_next + nwords * sizeof(uint32_t));
 552        found_end = is_packet_end(word);
 553    }
 554    uint32_t next_ptr =  ctx->base.pc_next + nwords * sizeof(uint32_t);
 555    return found_end && next_ptr - page_start >= TARGET_PAGE_SIZE;
 556}
 557
 558static void hexagon_tr_translate_packet(DisasContextBase *dcbase, CPUState *cpu)
 559{
 560    DisasContext *ctx = container_of(dcbase, DisasContext, base);
 561    CPUHexagonState *env = cpu->env_ptr;
 562
 563    decode_and_translate_packet(env, ctx);
 564
 565    if (ctx->base.is_jmp == DISAS_NEXT) {
 566        target_ulong page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
 567        target_ulong bytes_max = PACKET_WORDS_MAX * sizeof(target_ulong);
 568
 569        if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE ||
 570            (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE - bytes_max &&
 571             pkt_crosses_page(env, ctx))) {
 572            ctx->base.is_jmp = DISAS_TOO_MANY;
 573        }
 574
 575        /*
 576         * The CPU log is used to compare against LLDB single stepping,
 577         * so end the TLB after every packet.
 578         */
 579        HexagonCPU *hex_cpu = env_archcpu(env);
 580        if (hex_cpu->lldb_compat && qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
 581            ctx->base.is_jmp = DISAS_TOO_MANY;
 582        }
 583    }
 584}
 585
 586static void hexagon_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
 587{
 588    DisasContext *ctx = container_of(dcbase, DisasContext, base);
 589
 590    switch (ctx->base.is_jmp) {
 591    case DISAS_TOO_MANY:
 592        gen_exec_counters(ctx);
 593        tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->base.pc_next);
 594        if (ctx->base.singlestep_enabled) {
 595            gen_exception_raw(EXCP_DEBUG);
 596        } else {
 597            tcg_gen_exit_tb(NULL, 0);
 598        }
 599        break;
 600    case DISAS_NORETURN:
 601        break;
 602    default:
 603        g_assert_not_reached();
 604    }
 605}
 606
 607static void hexagon_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
 608{
 609    qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
 610    log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size);
 611}
 612
 613
 614static const TranslatorOps hexagon_tr_ops = {
 615    .init_disas_context = hexagon_tr_init_disas_context,
 616    .tb_start           = hexagon_tr_tb_start,
 617    .insn_start         = hexagon_tr_insn_start,
 618    .translate_insn     = hexagon_tr_translate_packet,
 619    .tb_stop            = hexagon_tr_tb_stop,
 620    .disas_log          = hexagon_tr_disas_log,
 621};
 622
 623void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
 624{
 625    DisasContext ctx;
 626
 627    translator_loop(&hexagon_tr_ops, &ctx.base, cs, tb, max_insns);
 628}
 629
 630#define NAME_LEN               64
 631static char new_value_names[TOTAL_PER_THREAD_REGS][NAME_LEN];
 632static char reg_written_names[TOTAL_PER_THREAD_REGS][NAME_LEN];
 633static char new_pred_value_names[NUM_PREGS][NAME_LEN];
 634static char store_addr_names[STORES_MAX][NAME_LEN];
 635static char store_width_names[STORES_MAX][NAME_LEN];
 636static char store_val32_names[STORES_MAX][NAME_LEN];
 637static char store_val64_names[STORES_MAX][NAME_LEN];
 638
 639void hexagon_translate_init(void)
 640{
 641    int i;
 642
 643    opcode_init();
 644
 645    if (HEX_DEBUG) {
 646        if (!qemu_logfile) {
 647            qemu_set_log(qemu_loglevel);
 648        }
 649    }
 650
 651    for (i = 0; i < TOTAL_PER_THREAD_REGS; i++) {
 652        hex_gpr[i] = tcg_global_mem_new(cpu_env,
 653            offsetof(CPUHexagonState, gpr[i]),
 654            hexagon_regnames[i]);
 655
 656        snprintf(new_value_names[i], NAME_LEN, "new_%s", hexagon_regnames[i]);
 657        hex_new_value[i] = tcg_global_mem_new(cpu_env,
 658            offsetof(CPUHexagonState, new_value[i]),
 659            new_value_names[i]);
 660
 661        if (HEX_DEBUG) {
 662            snprintf(reg_written_names[i], NAME_LEN, "reg_written_%s",
 663                     hexagon_regnames[i]);
 664            hex_reg_written[i] = tcg_global_mem_new(cpu_env,
 665                offsetof(CPUHexagonState, reg_written[i]),
 666                reg_written_names[i]);
 667        }
 668    }
 669    for (i = 0; i < NUM_PREGS; i++) {
 670        hex_pred[i] = tcg_global_mem_new(cpu_env,
 671            offsetof(CPUHexagonState, pred[i]),
 672            hexagon_prednames[i]);
 673
 674        snprintf(new_pred_value_names[i], NAME_LEN, "new_pred_%s",
 675                 hexagon_prednames[i]);
 676        hex_new_pred_value[i] = tcg_global_mem_new(cpu_env,
 677            offsetof(CPUHexagonState, new_pred_value[i]),
 678            new_pred_value_names[i]);
 679    }
 680    hex_pred_written = tcg_global_mem_new(cpu_env,
 681        offsetof(CPUHexagonState, pred_written), "pred_written");
 682    hex_next_PC = tcg_global_mem_new(cpu_env,
 683        offsetof(CPUHexagonState, next_PC), "next_PC");
 684    hex_this_PC = tcg_global_mem_new(cpu_env,
 685        offsetof(CPUHexagonState, this_PC), "this_PC");
 686    hex_slot_cancelled = tcg_global_mem_new(cpu_env,
 687        offsetof(CPUHexagonState, slot_cancelled), "slot_cancelled");
 688    hex_branch_taken = tcg_global_mem_new(cpu_env,
 689        offsetof(CPUHexagonState, branch_taken), "branch_taken");
 690    hex_pkt_has_store_s1 = tcg_global_mem_new(cpu_env,
 691        offsetof(CPUHexagonState, pkt_has_store_s1), "pkt_has_store_s1");
 692    hex_dczero_addr = tcg_global_mem_new(cpu_env,
 693        offsetof(CPUHexagonState, dczero_addr), "dczero_addr");
 694    hex_llsc_addr = tcg_global_mem_new(cpu_env,
 695        offsetof(CPUHexagonState, llsc_addr), "llsc_addr");
 696    hex_llsc_val = tcg_global_mem_new(cpu_env,
 697        offsetof(CPUHexagonState, llsc_val), "llsc_val");
 698    hex_llsc_val_i64 = tcg_global_mem_new_i64(cpu_env,
 699        offsetof(CPUHexagonState, llsc_val_i64), "llsc_val_i64");
 700    for (i = 0; i < STORES_MAX; i++) {
 701        snprintf(store_addr_names[i], NAME_LEN, "store_addr_%d", i);
 702        hex_store_addr[i] = tcg_global_mem_new(cpu_env,
 703            offsetof(CPUHexagonState, mem_log_stores[i].va),
 704            store_addr_names[i]);
 705
 706        snprintf(store_width_names[i], NAME_LEN, "store_width_%d", i);
 707        hex_store_width[i] = tcg_global_mem_new(cpu_env,
 708            offsetof(CPUHexagonState, mem_log_stores[i].width),
 709            store_width_names[i]);
 710
 711        snprintf(store_val32_names[i], NAME_LEN, "store_val32_%d", i);
 712        hex_store_val32[i] = tcg_global_mem_new(cpu_env,
 713            offsetof(CPUHexagonState, mem_log_stores[i].data32),
 714            store_val32_names[i]);
 715
 716        snprintf(store_val64_names[i], NAME_LEN, "store_val64_%d", i);
 717        hex_store_val64[i] = tcg_global_mem_new_i64(cpu_env,
 718            offsetof(CPUHexagonState, mem_log_stores[i].data64),
 719            store_val64_names[i]);
 720    }
 721}
 722