cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

translate.c (24282B)


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