qemu/target/riscv/translate.c
<<
>>
Prefs
   1/*
   2 * RISC-V emulation for qemu: main translation routines.
   3 *
   4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms and conditions of the GNU General Public License,
   8 * version 2 or later, as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope it will be useful, but WITHOUT
  11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  13 * more details.
  14 *
  15 * You should have received a copy of the GNU General Public License along with
  16 * this program.  If not, see <http://www.gnu.org/licenses/>.
  17 */
  18
  19#include "qemu/osdep.h"
  20#include "qemu/log.h"
  21#include "cpu.h"
  22#include "tcg/tcg-op.h"
  23#include "disas/disas.h"
  24#include "exec/cpu_ldst.h"
  25#include "exec/exec-all.h"
  26#include "exec/helper-proto.h"
  27#include "exec/helper-gen.h"
  28
  29#include "exec/translator.h"
  30#include "exec/log.h"
  31
  32#include "instmap.h"
  33#include "internals.h"
  34
  35/* global register indices */
  36static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
  37static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
  38static TCGv load_res;
  39static TCGv load_val;
  40/* globals for PM CSRs */
  41static TCGv pm_mask;
  42static TCGv pm_base;
  43
  44#include "exec/gen-icount.h"
  45
  46/*
  47 * If an operation is being performed on less than TARGET_LONG_BITS,
  48 * it may require the inputs to be sign- or zero-extended; which will
  49 * depend on the exact operation being performed.
  50 */
  51typedef enum {
  52    EXT_NONE,
  53    EXT_SIGN,
  54    EXT_ZERO,
  55} DisasExtend;
  56
  57typedef struct DisasContext {
  58    DisasContextBase base;
  59    /* pc_succ_insn points to the instruction following base.pc_next */
  60    target_ulong pc_succ_insn;
  61    target_ulong priv_ver;
  62    RISCVMXL misa_mxl_max;
  63    RISCVMXL xl;
  64    uint32_t misa_ext;
  65    uint32_t opcode;
  66    uint32_t mstatus_fs;
  67    uint32_t mstatus_vs;
  68    uint32_t mstatus_hs_fs;
  69    uint32_t mstatus_hs_vs;
  70    uint32_t mem_idx;
  71    /* Remember the rounding mode encoded in the previous fp instruction,
  72       which we have already installed into env->fp_status.  Or -1 for
  73       no previous fp instruction.  Note that we exit the TB when writing
  74       to any system register, which includes CSR_FRM, so we do not have
  75       to reset this known value.  */
  76    int frm;
  77    RISCVMXL ol;
  78    bool virt_enabled;
  79    const RISCVCPUConfig *cfg_ptr;
  80    bool hlsx;
  81    /* vector extension */
  82    bool vill;
  83    /*
  84     * Encode LMUL to lmul as follows:
  85     *     LMUL    vlmul    lmul
  86     *      1       000       0
  87     *      2       001       1
  88     *      4       010       2
  89     *      8       011       3
  90     *      -       100       -
  91     *     1/8      101      -3
  92     *     1/4      110      -2
  93     *     1/2      111      -1
  94     */
  95    int8_t lmul;
  96    uint8_t sew;
  97    target_ulong vstart;
  98    bool vl_eq_vlmax;
  99    uint8_t ntemp;
 100    CPUState *cs;
 101    TCGv zero;
 102    /* Space for 3 operands plus 1 extra for address computation. */
 103    TCGv temp[4];
 104    /* Space for 4 operands(1 dest and <=3 src) for float point computation */
 105    TCGv_i64 ftemp[4];
 106    uint8_t nftemp;
 107    /* PointerMasking extension */
 108    bool pm_mask_enabled;
 109    bool pm_base_enabled;
 110} DisasContext;
 111
 112static inline bool has_ext(DisasContext *ctx, uint32_t ext)
 113{
 114    return ctx->misa_ext & ext;
 115}
 116
 117static bool always_true_p(DisasContext *ctx  __attribute__((__unused__)))
 118{
 119    return true;
 120}
 121
 122#define MATERIALISE_EXT_PREDICATE(ext)  \
 123    static bool has_ ## ext ## _p(DisasContext *ctx)    \
 124    { \
 125        return ctx->cfg_ptr->ext_ ## ext ; \
 126    }
 127
 128MATERIALISE_EXT_PREDICATE(XVentanaCondOps);
 129
 130#ifdef TARGET_RISCV32
 131#define get_xl(ctx)    MXL_RV32
 132#elif defined(CONFIG_USER_ONLY)
 133#define get_xl(ctx)    MXL_RV64
 134#else
 135#define get_xl(ctx)    ((ctx)->xl)
 136#endif
 137
 138/* The word size for this machine mode. */
 139static inline int __attribute__((unused)) get_xlen(DisasContext *ctx)
 140{
 141    return 16 << get_xl(ctx);
 142}
 143
 144/* The operation length, as opposed to the xlen. */
 145#ifdef TARGET_RISCV32
 146#define get_ol(ctx)    MXL_RV32
 147#else
 148#define get_ol(ctx)    ((ctx)->ol)
 149#endif
 150
 151static inline int get_olen(DisasContext *ctx)
 152{
 153    return 16 << get_ol(ctx);
 154}
 155
 156/* The maximum register length */
 157#ifdef TARGET_RISCV32
 158#define get_xl_max(ctx)    MXL_RV32
 159#else
 160#define get_xl_max(ctx)    ((ctx)->misa_mxl_max)
 161#endif
 162
 163/*
 164 * RISC-V requires NaN-boxing of narrower width floating point values.
 165 * This applies when a 32-bit value is assigned to a 64-bit FP register.
 166 * For consistency and simplicity, we nanbox results even when the RVD
 167 * extension is not present.
 168 */
 169static void gen_nanbox_s(TCGv_i64 out, TCGv_i64 in)
 170{
 171    tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(32, 32));
 172}
 173
 174static void gen_nanbox_h(TCGv_i64 out, TCGv_i64 in)
 175{
 176    tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(16, 48));
 177}
 178
 179/*
 180 * A narrow n-bit operation, where n < FLEN, checks that input operands
 181 * are correctly Nan-boxed, i.e., all upper FLEN - n bits are 1.
 182 * If so, the least-significant bits of the input are used, otherwise the
 183 * input value is treated as an n-bit canonical NaN (v2.2 section 9.2).
 184 *
 185 * Here, the result is always nan-boxed, even the canonical nan.
 186 */
 187static void gen_check_nanbox_h(TCGv_i64 out, TCGv_i64 in)
 188{
 189    TCGv_i64 t_max = tcg_const_i64(0xffffffffffff0000ull);
 190    TCGv_i64 t_nan = tcg_const_i64(0xffffffffffff7e00ull);
 191
 192    tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan);
 193    tcg_temp_free_i64(t_max);
 194    tcg_temp_free_i64(t_nan);
 195}
 196
 197static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in)
 198{
 199    TCGv_i64 t_max = tcg_constant_i64(0xffffffff00000000ull);
 200    TCGv_i64 t_nan = tcg_constant_i64(0xffffffff7fc00000ull);
 201
 202    tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan);
 203}
 204
 205static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
 206{
 207    if (get_xl(ctx) == MXL_RV32) {
 208        dest = (int32_t)dest;
 209    }
 210    tcg_gen_movi_tl(cpu_pc, dest);
 211}
 212
 213static void gen_set_pc(DisasContext *ctx, TCGv dest)
 214{
 215    if (get_xl(ctx) == MXL_RV32) {
 216        tcg_gen_ext32s_tl(cpu_pc, dest);
 217    } else {
 218        tcg_gen_mov_tl(cpu_pc, dest);
 219    }
 220}
 221
 222static void generate_exception(DisasContext *ctx, int excp)
 223{
 224    gen_set_pc_imm(ctx, ctx->base.pc_next);
 225    gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
 226    ctx->base.is_jmp = DISAS_NORETURN;
 227}
 228
 229static void generate_exception_mtval(DisasContext *ctx, int excp)
 230{
 231    gen_set_pc_imm(ctx, ctx->base.pc_next);
 232    tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr));
 233    gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
 234    ctx->base.is_jmp = DISAS_NORETURN;
 235}
 236
 237static void gen_exception_illegal(DisasContext *ctx)
 238{
 239    tcg_gen_st_i32(tcg_constant_i32(ctx->opcode), cpu_env,
 240                   offsetof(CPURISCVState, bins));
 241
 242    generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
 243}
 244
 245static void gen_exception_inst_addr_mis(DisasContext *ctx)
 246{
 247    generate_exception_mtval(ctx, RISCV_EXCP_INST_ADDR_MIS);
 248}
 249
 250static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
 251{
 252    if (translator_use_goto_tb(&ctx->base, dest)) {
 253        tcg_gen_goto_tb(n);
 254        gen_set_pc_imm(ctx, dest);
 255        tcg_gen_exit_tb(ctx->base.tb, n);
 256    } else {
 257        gen_set_pc_imm(ctx, dest);
 258        tcg_gen_lookup_and_goto_ptr();
 259    }
 260}
 261
 262/*
 263 * Wrappers for getting reg values.
 264 *
 265 * The $zero register does not have cpu_gpr[0] allocated -- we supply the
 266 * constant zero as a source, and an uninitialized sink as destination.
 267 *
 268 * Further, we may provide an extension for word operations.
 269 */
 270static TCGv temp_new(DisasContext *ctx)
 271{
 272    assert(ctx->ntemp < ARRAY_SIZE(ctx->temp));
 273    return ctx->temp[ctx->ntemp++] = tcg_temp_new();
 274}
 275
 276static TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend ext)
 277{
 278    TCGv t;
 279
 280    if (reg_num == 0) {
 281        return ctx->zero;
 282    }
 283
 284    switch (get_ol(ctx)) {
 285    case MXL_RV32:
 286        switch (ext) {
 287        case EXT_NONE:
 288            break;
 289        case EXT_SIGN:
 290            t = temp_new(ctx);
 291            tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]);
 292            return t;
 293        case EXT_ZERO:
 294            t = temp_new(ctx);
 295            tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]);
 296            return t;
 297        default:
 298            g_assert_not_reached();
 299        }
 300        break;
 301    case MXL_RV64:
 302    case MXL_RV128:
 303        break;
 304    default:
 305        g_assert_not_reached();
 306    }
 307    return cpu_gpr[reg_num];
 308}
 309
 310static TCGv get_gprh(DisasContext *ctx, int reg_num)
 311{
 312    assert(get_xl(ctx) == MXL_RV128);
 313    if (reg_num == 0) {
 314        return ctx->zero;
 315    }
 316    return cpu_gprh[reg_num];
 317}
 318
 319static TCGv dest_gpr(DisasContext *ctx, int reg_num)
 320{
 321    if (reg_num == 0 || get_olen(ctx) < TARGET_LONG_BITS) {
 322        return temp_new(ctx);
 323    }
 324    return cpu_gpr[reg_num];
 325}
 326
 327static TCGv dest_gprh(DisasContext *ctx, int reg_num)
 328{
 329    if (reg_num == 0) {
 330        return temp_new(ctx);
 331    }
 332    return cpu_gprh[reg_num];
 333}
 334
 335static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t)
 336{
 337    if (reg_num != 0) {
 338        switch (get_ol(ctx)) {
 339        case MXL_RV32:
 340            tcg_gen_ext32s_tl(cpu_gpr[reg_num], t);
 341            break;
 342        case MXL_RV64:
 343        case MXL_RV128:
 344            tcg_gen_mov_tl(cpu_gpr[reg_num], t);
 345            break;
 346        default:
 347            g_assert_not_reached();
 348        }
 349
 350        if (get_xl_max(ctx) == MXL_RV128) {
 351            tcg_gen_sari_tl(cpu_gprh[reg_num], cpu_gpr[reg_num], 63);
 352        }
 353    }
 354}
 355
 356static void gen_set_gpri(DisasContext *ctx, int reg_num, target_long imm)
 357{
 358    if (reg_num != 0) {
 359        switch (get_ol(ctx)) {
 360        case MXL_RV32:
 361            tcg_gen_movi_tl(cpu_gpr[reg_num], (int32_t)imm);
 362            break;
 363        case MXL_RV64:
 364        case MXL_RV128:
 365            tcg_gen_movi_tl(cpu_gpr[reg_num], imm);
 366            break;
 367        default:
 368            g_assert_not_reached();
 369        }
 370
 371        if (get_xl_max(ctx) == MXL_RV128) {
 372            tcg_gen_movi_tl(cpu_gprh[reg_num], -(imm < 0));
 373        }
 374    }
 375}
 376
 377static void gen_set_gpr128(DisasContext *ctx, int reg_num, TCGv rl, TCGv rh)
 378{
 379    assert(get_ol(ctx) == MXL_RV128);
 380    if (reg_num != 0) {
 381        tcg_gen_mov_tl(cpu_gpr[reg_num], rl);
 382        tcg_gen_mov_tl(cpu_gprh[reg_num], rh);
 383    }
 384}
 385
 386static TCGv_i64 ftemp_new(DisasContext *ctx)
 387{
 388    assert(ctx->nftemp < ARRAY_SIZE(ctx->ftemp));
 389    return ctx->ftemp[ctx->nftemp++] = tcg_temp_new_i64();
 390}
 391
 392static TCGv_i64 get_fpr_hs(DisasContext *ctx, int reg_num)
 393{
 394    if (!ctx->cfg_ptr->ext_zfinx) {
 395        return cpu_fpr[reg_num];
 396    }
 397
 398    if (reg_num == 0) {
 399        return tcg_constant_i64(0);
 400    }
 401    switch (get_xl(ctx)) {
 402    case MXL_RV32:
 403#ifdef TARGET_RISCV32
 404    {
 405        TCGv_i64 t = ftemp_new(ctx);
 406        tcg_gen_ext_i32_i64(t, cpu_gpr[reg_num]);
 407        return t;
 408    }
 409#else
 410    /* fall through */
 411    case MXL_RV64:
 412        return cpu_gpr[reg_num];
 413#endif
 414    default:
 415        g_assert_not_reached();
 416    }
 417}
 418
 419static TCGv_i64 get_fpr_d(DisasContext *ctx, int reg_num)
 420{
 421    if (!ctx->cfg_ptr->ext_zfinx) {
 422        return cpu_fpr[reg_num];
 423    }
 424
 425    if (reg_num == 0) {
 426        return tcg_constant_i64(0);
 427    }
 428    switch (get_xl(ctx)) {
 429    case MXL_RV32:
 430    {
 431        TCGv_i64 t = ftemp_new(ctx);
 432        tcg_gen_concat_tl_i64(t, cpu_gpr[reg_num], cpu_gpr[reg_num + 1]);
 433        return t;
 434    }
 435#ifdef TARGET_RISCV64
 436    case MXL_RV64:
 437        return cpu_gpr[reg_num];
 438#endif
 439    default:
 440        g_assert_not_reached();
 441    }
 442}
 443
 444static TCGv_i64 dest_fpr(DisasContext *ctx, int reg_num)
 445{
 446    if (!ctx->cfg_ptr->ext_zfinx) {
 447        return cpu_fpr[reg_num];
 448    }
 449
 450    if (reg_num == 0) {
 451        return ftemp_new(ctx);
 452    }
 453
 454    switch (get_xl(ctx)) {
 455    case MXL_RV32:
 456        return ftemp_new(ctx);
 457#ifdef TARGET_RISCV64
 458    case MXL_RV64:
 459        return cpu_gpr[reg_num];
 460#endif
 461    default:
 462        g_assert_not_reached();
 463    }
 464}
 465
 466/* assume t is nanboxing (for normal) or sign-extended (for zfinx) */
 467static void gen_set_fpr_hs(DisasContext *ctx, int reg_num, TCGv_i64 t)
 468{
 469    if (!ctx->cfg_ptr->ext_zfinx) {
 470        tcg_gen_mov_i64(cpu_fpr[reg_num], t);
 471        return;
 472    }
 473    if (reg_num != 0) {
 474        switch (get_xl(ctx)) {
 475        case MXL_RV32:
 476#ifdef TARGET_RISCV32
 477            tcg_gen_extrl_i64_i32(cpu_gpr[reg_num], t);
 478            break;
 479#else
 480        /* fall through */
 481        case MXL_RV64:
 482            tcg_gen_mov_i64(cpu_gpr[reg_num], t);
 483            break;
 484#endif
 485        default:
 486            g_assert_not_reached();
 487        }
 488    }
 489}
 490
 491static void gen_set_fpr_d(DisasContext *ctx, int reg_num, TCGv_i64 t)
 492{
 493    if (!ctx->cfg_ptr->ext_zfinx) {
 494        tcg_gen_mov_i64(cpu_fpr[reg_num], t);
 495        return;
 496    }
 497
 498    if (reg_num != 0) {
 499        switch (get_xl(ctx)) {
 500        case MXL_RV32:
 501#ifdef TARGET_RISCV32
 502            tcg_gen_extr_i64_i32(cpu_gpr[reg_num], cpu_gpr[reg_num + 1], t);
 503            break;
 504#else
 505            tcg_gen_ext32s_i64(cpu_gpr[reg_num], t);
 506            tcg_gen_sari_i64(cpu_gpr[reg_num + 1], t, 32);
 507            break;
 508        case MXL_RV64:
 509            tcg_gen_mov_i64(cpu_gpr[reg_num], t);
 510            break;
 511#endif
 512        default:
 513            g_assert_not_reached();
 514        }
 515    }
 516}
 517
 518static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
 519{
 520    target_ulong next_pc;
 521
 522    /* check misaligned: */
 523    next_pc = ctx->base.pc_next + imm;
 524    if (!has_ext(ctx, RVC)) {
 525        if ((next_pc & 0x3) != 0) {
 526            gen_exception_inst_addr_mis(ctx);
 527            return;
 528        }
 529    }
 530
 531    gen_set_gpri(ctx, rd, ctx->pc_succ_insn);
 532    gen_goto_tb(ctx, 0, ctx->base.pc_next + imm); /* must use this for safety */
 533    ctx->base.is_jmp = DISAS_NORETURN;
 534}
 535
 536/* Compute a canonical address from a register plus offset. */
 537static TCGv get_address(DisasContext *ctx, int rs1, int imm)
 538{
 539    TCGv addr = temp_new(ctx);
 540    TCGv src1 = get_gpr(ctx, rs1, EXT_NONE);
 541
 542    tcg_gen_addi_tl(addr, src1, imm);
 543    if (ctx->pm_mask_enabled) {
 544        tcg_gen_and_tl(addr, addr, pm_mask);
 545    } else if (get_xl(ctx) == MXL_RV32) {
 546        tcg_gen_ext32u_tl(addr, addr);
 547    }
 548    if (ctx->pm_base_enabled) {
 549        tcg_gen_or_tl(addr, addr, pm_base);
 550    }
 551    return addr;
 552}
 553
 554#ifndef CONFIG_USER_ONLY
 555/* The states of mstatus_fs are:
 556 * 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
 557 * We will have already diagnosed disabled state,
 558 * and need to turn initial/clean into dirty.
 559 */
 560static void mark_fs_dirty(DisasContext *ctx)
 561{
 562    TCGv tmp;
 563
 564    if (!has_ext(ctx, RVF)) {
 565        return;
 566    }
 567
 568    if (ctx->mstatus_fs != MSTATUS_FS) {
 569        /* Remember the state change for the rest of the TB. */
 570        ctx->mstatus_fs = MSTATUS_FS;
 571
 572        tmp = tcg_temp_new();
 573        tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
 574        tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
 575        tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
 576        tcg_temp_free(tmp);
 577    }
 578
 579    if (ctx->virt_enabled && ctx->mstatus_hs_fs != MSTATUS_FS) {
 580        /* Remember the stage change for the rest of the TB. */
 581        ctx->mstatus_hs_fs = MSTATUS_FS;
 582
 583        tmp = tcg_temp_new();
 584        tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
 585        tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
 586        tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
 587        tcg_temp_free(tmp);
 588    }
 589}
 590#else
 591static inline void mark_fs_dirty(DisasContext *ctx) { }
 592#endif
 593
 594#ifndef CONFIG_USER_ONLY
 595/* The states of mstatus_vs are:
 596 * 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
 597 * We will have already diagnosed disabled state,
 598 * and need to turn initial/clean into dirty.
 599 */
 600static void mark_vs_dirty(DisasContext *ctx)
 601{
 602    TCGv tmp;
 603
 604    if (ctx->mstatus_vs != MSTATUS_VS) {
 605        /* Remember the state change for the rest of the TB.  */
 606        ctx->mstatus_vs = MSTATUS_VS;
 607
 608        tmp = tcg_temp_new();
 609        tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
 610        tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
 611        tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
 612        tcg_temp_free(tmp);
 613    }
 614
 615    if (ctx->virt_enabled && ctx->mstatus_hs_vs != MSTATUS_VS) {
 616        /* Remember the stage change for the rest of the TB. */
 617        ctx->mstatus_hs_vs = MSTATUS_VS;
 618
 619        tmp = tcg_temp_new();
 620        tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
 621        tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
 622        tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
 623        tcg_temp_free(tmp);
 624    }
 625}
 626#else
 627static inline void mark_vs_dirty(DisasContext *ctx) { }
 628#endif
 629
 630static void gen_set_rm(DisasContext *ctx, int rm)
 631{
 632    if (ctx->frm == rm) {
 633        return;
 634    }
 635    ctx->frm = rm;
 636
 637    if (rm == RISCV_FRM_ROD) {
 638        gen_helper_set_rod_rounding_mode(cpu_env);
 639        return;
 640    }
 641
 642    gen_helper_set_rounding_mode(cpu_env, tcg_constant_i32(rm));
 643}
 644
 645static int ex_plus_1(DisasContext *ctx, int nf)
 646{
 647    return nf + 1;
 648}
 649
 650#define EX_SH(amount) \
 651    static int ex_shift_##amount(DisasContext *ctx, int imm) \
 652    {                                         \
 653        return imm << amount;                 \
 654    }
 655EX_SH(1)
 656EX_SH(2)
 657EX_SH(3)
 658EX_SH(4)
 659EX_SH(12)
 660
 661#define REQUIRE_EXT(ctx, ext) do { \
 662    if (!has_ext(ctx, ext)) {      \
 663        return false;              \
 664    }                              \
 665} while (0)
 666
 667#define REQUIRE_32BIT(ctx) do {    \
 668    if (get_xl(ctx) != MXL_RV32) { \
 669        return false;              \
 670    }                              \
 671} while (0)
 672
 673#define REQUIRE_64BIT(ctx) do {     \
 674    if (get_xl(ctx) != MXL_RV64) {  \
 675        return false;               \
 676    }                               \
 677} while (0)
 678
 679#define REQUIRE_128BIT(ctx) do {    \
 680    if (get_xl(ctx) != MXL_RV128) { \
 681        return false;               \
 682    }                               \
 683} while (0)
 684
 685#define REQUIRE_64_OR_128BIT(ctx) do { \
 686    if (get_xl(ctx) == MXL_RV32) {     \
 687        return false;                  \
 688    }                                  \
 689} while (0)
 690
 691static int ex_rvc_register(DisasContext *ctx, int reg)
 692{
 693    return 8 + reg;
 694}
 695
 696static int ex_rvc_shifti(DisasContext *ctx, int imm)
 697{
 698    /* For RV128 a shamt of 0 means a shift by 64. */
 699    return imm ? imm : 64;
 700}
 701
 702/* Include the auto-generated decoder for 32 bit insn */
 703#include "decode-insn32.c.inc"
 704
 705static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a,
 706                             void (*func)(TCGv, TCGv, target_long))
 707{
 708    TCGv dest = dest_gpr(ctx, a->rd);
 709    TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
 710
 711    func(dest, src1, a->imm);
 712
 713    if (get_xl(ctx) == MXL_RV128) {
 714        TCGv src1h = get_gprh(ctx, a->rs1);
 715        TCGv desth = dest_gprh(ctx, a->rd);
 716
 717        func(desth, src1h, -(a->imm < 0));
 718        gen_set_gpr128(ctx, a->rd, dest, desth);
 719    } else {
 720        gen_set_gpr(ctx, a->rd, dest);
 721    }
 722
 723    return true;
 724}
 725
 726static bool gen_logic(DisasContext *ctx, arg_r *a,
 727                      void (*func)(TCGv, TCGv, TCGv))
 728{
 729    TCGv dest = dest_gpr(ctx, a->rd);
 730    TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
 731    TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 732
 733    func(dest, src1, src2);
 734
 735    if (get_xl(ctx) == MXL_RV128) {
 736        TCGv src1h = get_gprh(ctx, a->rs1);
 737        TCGv src2h = get_gprh(ctx, a->rs2);
 738        TCGv desth = dest_gprh(ctx, a->rd);
 739
 740        func(desth, src1h, src2h);
 741        gen_set_gpr128(ctx, a->rd, dest, desth);
 742    } else {
 743        gen_set_gpr(ctx, a->rd, dest);
 744    }
 745
 746    return true;
 747}
 748
 749static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext,
 750                             void (*func)(TCGv, TCGv, target_long),
 751                             void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
 752{
 753    TCGv dest = dest_gpr(ctx, a->rd);
 754    TCGv src1 = get_gpr(ctx, a->rs1, ext);
 755
 756    if (get_ol(ctx) < MXL_RV128) {
 757        func(dest, src1, a->imm);
 758        gen_set_gpr(ctx, a->rd, dest);
 759    } else {
 760        if (f128 == NULL) {
 761            return false;
 762        }
 763
 764        TCGv src1h = get_gprh(ctx, a->rs1);
 765        TCGv desth = dest_gprh(ctx, a->rd);
 766
 767        f128(dest, desth, src1, src1h, a->imm);
 768        gen_set_gpr128(ctx, a->rd, dest, desth);
 769    }
 770    return true;
 771}
 772
 773static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, DisasExtend ext,
 774                             void (*func)(TCGv, TCGv, TCGv),
 775                             void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 776{
 777    TCGv dest = dest_gpr(ctx, a->rd);
 778    TCGv src1 = get_gpr(ctx, a->rs1, ext);
 779    TCGv src2 = tcg_constant_tl(a->imm);
 780
 781    if (get_ol(ctx) < MXL_RV128) {
 782        func(dest, src1, src2);
 783        gen_set_gpr(ctx, a->rd, dest);
 784    } else {
 785        if (f128 == NULL) {
 786            return false;
 787        }
 788
 789        TCGv src1h = get_gprh(ctx, a->rs1);
 790        TCGv src2h = tcg_constant_tl(-(a->imm < 0));
 791        TCGv desth = dest_gprh(ctx, a->rd);
 792
 793        f128(dest, desth, src1, src1h, src2, src2h);
 794        gen_set_gpr128(ctx, a->rd, dest, desth);
 795    }
 796    return true;
 797}
 798
 799static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext,
 800                      void (*func)(TCGv, TCGv, TCGv),
 801                      void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 802{
 803    TCGv dest = dest_gpr(ctx, a->rd);
 804    TCGv src1 = get_gpr(ctx, a->rs1, ext);
 805    TCGv src2 = get_gpr(ctx, a->rs2, ext);
 806
 807    if (get_ol(ctx) < MXL_RV128) {
 808        func(dest, src1, src2);
 809        gen_set_gpr(ctx, a->rd, dest);
 810    } else {
 811        if (f128 == NULL) {
 812            return false;
 813        }
 814
 815        TCGv src1h = get_gprh(ctx, a->rs1);
 816        TCGv src2h = get_gprh(ctx, a->rs2);
 817        TCGv desth = dest_gprh(ctx, a->rd);
 818
 819        f128(dest, desth, src1, src1h, src2, src2h);
 820        gen_set_gpr128(ctx, a->rd, dest, desth);
 821    }
 822    return true;
 823}
 824
 825static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
 826                             void (*f_tl)(TCGv, TCGv, TCGv),
 827                             void (*f_32)(TCGv, TCGv, TCGv),
 828                             void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 829{
 830    int olen = get_olen(ctx);
 831
 832    if (olen != TARGET_LONG_BITS) {
 833        if (olen == 32) {
 834            f_tl = f_32;
 835        } else if (olen != 128) {
 836            g_assert_not_reached();
 837        }
 838    }
 839    return gen_arith(ctx, a, ext, f_tl, f_128);
 840}
 841
 842static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext,
 843                             void (*func)(TCGv, TCGv, target_long),
 844                             void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
 845{
 846    TCGv dest, src1;
 847    int max_len = get_olen(ctx);
 848
 849    if (a->shamt >= max_len) {
 850        return false;
 851    }
 852
 853    dest = dest_gpr(ctx, a->rd);
 854    src1 = get_gpr(ctx, a->rs1, ext);
 855
 856    if (max_len < 128) {
 857        func(dest, src1, a->shamt);
 858        gen_set_gpr(ctx, a->rd, dest);
 859    } else {
 860        TCGv src1h = get_gprh(ctx, a->rs1);
 861        TCGv desth = dest_gprh(ctx, a->rd);
 862
 863        if (f128 == NULL) {
 864            return false;
 865        }
 866        f128(dest, desth, src1, src1h, a->shamt);
 867        gen_set_gpr128(ctx, a->rd, dest, desth);
 868    }
 869    return true;
 870}
 871
 872static bool gen_shift_imm_fn_per_ol(DisasContext *ctx, arg_shift *a,
 873                                    DisasExtend ext,
 874                                    void (*f_tl)(TCGv, TCGv, target_long),
 875                                    void (*f_32)(TCGv, TCGv, target_long),
 876                                    void (*f_128)(TCGv, TCGv, TCGv, TCGv,
 877                                                  target_long))
 878{
 879    int olen = get_olen(ctx);
 880    if (olen != TARGET_LONG_BITS) {
 881        if (olen == 32) {
 882            f_tl = f_32;
 883        } else if (olen != 128) {
 884            g_assert_not_reached();
 885        }
 886    }
 887    return gen_shift_imm_fn(ctx, a, ext, f_tl, f_128);
 888}
 889
 890static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext,
 891                             void (*func)(TCGv, TCGv, TCGv))
 892{
 893    TCGv dest, src1, src2;
 894    int max_len = get_olen(ctx);
 895
 896    if (a->shamt >= max_len) {
 897        return false;
 898    }
 899
 900    dest = dest_gpr(ctx, a->rd);
 901    src1 = get_gpr(ctx, a->rs1, ext);
 902    src2 = tcg_constant_tl(a->shamt);
 903
 904    func(dest, src1, src2);
 905
 906    gen_set_gpr(ctx, a->rd, dest);
 907    return true;
 908}
 909
 910static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext,
 911                      void (*func)(TCGv, TCGv, TCGv),
 912                      void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv))
 913{
 914    TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 915    TCGv ext2 = tcg_temp_new();
 916    int max_len = get_olen(ctx);
 917
 918    tcg_gen_andi_tl(ext2, src2, max_len - 1);
 919
 920    TCGv dest = dest_gpr(ctx, a->rd);
 921    TCGv src1 = get_gpr(ctx, a->rs1, ext);
 922
 923    if (max_len < 128) {
 924        func(dest, src1, ext2);
 925        gen_set_gpr(ctx, a->rd, dest);
 926    } else {
 927        TCGv src1h = get_gprh(ctx, a->rs1);
 928        TCGv desth = dest_gprh(ctx, a->rd);
 929
 930        if (f128 == NULL) {
 931            return false;
 932        }
 933        f128(dest, desth, src1, src1h, ext2);
 934        gen_set_gpr128(ctx, a->rd, dest, desth);
 935    }
 936    tcg_temp_free(ext2);
 937    return true;
 938}
 939
 940static bool gen_shift_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
 941                             void (*f_tl)(TCGv, TCGv, TCGv),
 942                             void (*f_32)(TCGv, TCGv, TCGv),
 943                             void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv))
 944{
 945    int olen = get_olen(ctx);
 946    if (olen != TARGET_LONG_BITS) {
 947        if (olen == 32) {
 948            f_tl = f_32;
 949        } else if (olen != 128) {
 950            g_assert_not_reached();
 951        }
 952    }
 953    return gen_shift(ctx, a, ext, f_tl, f_128);
 954}
 955
 956static bool gen_unary(DisasContext *ctx, arg_r2 *a, DisasExtend ext,
 957                      void (*func)(TCGv, TCGv))
 958{
 959    TCGv dest = dest_gpr(ctx, a->rd);
 960    TCGv src1 = get_gpr(ctx, a->rs1, ext);
 961
 962    func(dest, src1);
 963
 964    gen_set_gpr(ctx, a->rd, dest);
 965    return true;
 966}
 967
 968static bool gen_unary_per_ol(DisasContext *ctx, arg_r2 *a, DisasExtend ext,
 969                             void (*f_tl)(TCGv, TCGv),
 970                             void (*f_32)(TCGv, TCGv))
 971{
 972    int olen = get_olen(ctx);
 973
 974    if (olen != TARGET_LONG_BITS) {
 975        if (olen == 32) {
 976            f_tl = f_32;
 977        } else {
 978            g_assert_not_reached();
 979        }
 980    }
 981    return gen_unary(ctx, a, ext, f_tl);
 982}
 983
 984static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
 985{
 986    DisasContext *ctx = container_of(dcbase, DisasContext, base);
 987    CPUState *cpu = ctx->cs;
 988    CPURISCVState *env = cpu->env_ptr;
 989
 990    return cpu_ldl_code(env, pc);
 991}
 992
 993/* Include insn module translation function */
 994#include "insn_trans/trans_rvi.c.inc"
 995#include "insn_trans/trans_rvm.c.inc"
 996#include "insn_trans/trans_rva.c.inc"
 997#include "insn_trans/trans_rvf.c.inc"
 998#include "insn_trans/trans_rvd.c.inc"
 999#include "insn_trans/trans_rvh.c.inc"
1000#include "insn_trans/trans_rvv.c.inc"
1001#include "insn_trans/trans_rvb.c.inc"
1002#include "insn_trans/trans_rvzfh.c.inc"
1003#include "insn_trans/trans_privileged.c.inc"
1004#include "insn_trans/trans_svinval.c.inc"
1005#include "insn_trans/trans_xventanacondops.c.inc"
1006
1007/* Include the auto-generated decoder for 16 bit insn */
1008#include "decode-insn16.c.inc"
1009/* Include decoders for factored-out extensions */
1010#include "decode-XVentanaCondOps.c.inc"
1011
1012static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
1013{
1014    /*
1015     * A table with predicate (i.e., guard) functions and decoder functions
1016     * that are tested in-order until a decoder matches onto the opcode.
1017     */
1018    static const struct {
1019        bool (*guard_func)(DisasContext *);
1020        bool (*decode_func)(DisasContext *, uint32_t);
1021    } decoders[] = {
1022        { always_true_p,  decode_insn32 },
1023        { has_XVentanaCondOps_p,  decode_XVentanaCodeOps },
1024    };
1025
1026    /* Check for compressed insn */
1027    if (extract16(opcode, 0, 2) != 3) {
1028        if (!has_ext(ctx, RVC)) {
1029            gen_exception_illegal(ctx);
1030        } else {
1031            ctx->opcode = opcode;
1032            ctx->pc_succ_insn = ctx->base.pc_next + 2;
1033            if (decode_insn16(ctx, opcode)) {
1034                return;
1035            }
1036        }
1037    } else {
1038        uint32_t opcode32 = opcode;
1039        opcode32 = deposit32(opcode32, 16, 16,
1040                             translator_lduw(env, &ctx->base,
1041                                             ctx->base.pc_next + 2));
1042        ctx->opcode = opcode32;
1043        ctx->pc_succ_insn = ctx->base.pc_next + 4;
1044
1045        for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) {
1046            if (decoders[i].guard_func(ctx) &&
1047                decoders[i].decode_func(ctx, opcode32)) {
1048                return;
1049            }
1050        }
1051    }
1052
1053    gen_exception_illegal(ctx);
1054}
1055
1056static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
1057{
1058    DisasContext *ctx = container_of(dcbase, DisasContext, base);
1059    CPURISCVState *env = cs->env_ptr;
1060    RISCVCPU *cpu = RISCV_CPU(cs);
1061    uint32_t tb_flags = ctx->base.tb->flags;
1062
1063    ctx->pc_succ_insn = ctx->base.pc_first;
1064    ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MEM_IDX);
1065    ctx->mstatus_fs = tb_flags & TB_FLAGS_MSTATUS_FS;
1066    ctx->mstatus_vs = tb_flags & TB_FLAGS_MSTATUS_VS;
1067    ctx->priv_ver = env->priv_ver;
1068#if !defined(CONFIG_USER_ONLY)
1069    if (riscv_has_ext(env, RVH)) {
1070        ctx->virt_enabled = riscv_cpu_virt_enabled(env);
1071    } else {
1072        ctx->virt_enabled = false;
1073    }
1074#else
1075    ctx->virt_enabled = false;
1076#endif
1077    ctx->misa_ext = env->misa_ext;
1078    ctx->frm = -1;  /* unknown rounding mode */
1079    ctx->cfg_ptr = &(cpu->cfg);
1080    ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS);
1081    ctx->mstatus_hs_vs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_VS);
1082    ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
1083    ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
1084    ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
1085    ctx->lmul = sextract32(FIELD_EX32(tb_flags, TB_FLAGS, LMUL), 0, 3);
1086    ctx->vstart = env->vstart;
1087    ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
1088    ctx->misa_mxl_max = env->misa_mxl_max;
1089    ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
1090    ctx->cs = cs;
1091    ctx->ntemp = 0;
1092    memset(ctx->temp, 0, sizeof(ctx->temp));
1093    ctx->nftemp = 0;
1094    memset(ctx->ftemp, 0, sizeof(ctx->ftemp));
1095    ctx->pm_mask_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_MASK_ENABLED);
1096    ctx->pm_base_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_BASE_ENABLED);
1097    ctx->zero = tcg_constant_tl(0);
1098}
1099
1100static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
1101{
1102}
1103
1104static void riscv_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
1105{
1106    DisasContext *ctx = container_of(dcbase, DisasContext, base);
1107
1108    tcg_gen_insn_start(ctx->base.pc_next);
1109}
1110
1111static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
1112{
1113    DisasContext *ctx = container_of(dcbase, DisasContext, base);
1114    CPURISCVState *env = cpu->env_ptr;
1115    uint16_t opcode16 = translator_lduw(env, &ctx->base, ctx->base.pc_next);
1116    int i;
1117
1118    ctx->ol = ctx->xl;
1119    decode_opc(env, ctx, opcode16);
1120    ctx->base.pc_next = ctx->pc_succ_insn;
1121
1122    for (i = ctx->ntemp - 1; i >= 0; --i) {
1123        tcg_temp_free(ctx->temp[i]);
1124        ctx->temp[i] = NULL;
1125    }
1126    ctx->ntemp = 0;
1127    for (i = ctx->nftemp - 1; i >= 0; --i) {
1128        tcg_temp_free_i64(ctx->ftemp[i]);
1129        ctx->ftemp[i] = NULL;
1130    }
1131    ctx->nftemp = 0;
1132
1133    if (ctx->base.is_jmp == DISAS_NEXT) {
1134        target_ulong page_start;
1135
1136        page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
1137        if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE) {
1138            ctx->base.is_jmp = DISAS_TOO_MANY;
1139        }
1140    }
1141}
1142
1143static void riscv_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
1144{
1145    DisasContext *ctx = container_of(dcbase, DisasContext, base);
1146
1147    switch (ctx->base.is_jmp) {
1148    case DISAS_TOO_MANY:
1149        gen_goto_tb(ctx, 0, ctx->base.pc_next);
1150        break;
1151    case DISAS_NORETURN:
1152        break;
1153    default:
1154        g_assert_not_reached();
1155    }
1156}
1157
1158static void riscv_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
1159{
1160#ifndef CONFIG_USER_ONLY
1161    RISCVCPU *rvcpu = RISCV_CPU(cpu);
1162    CPURISCVState *env = &rvcpu->env;
1163#endif
1164
1165    qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
1166#ifndef CONFIG_USER_ONLY
1167    qemu_log("Priv: "TARGET_FMT_ld"; Virt: "TARGET_FMT_ld"\n", env->priv, env->virt);
1168#endif
1169    log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size);
1170}
1171
1172static const TranslatorOps riscv_tr_ops = {
1173    .init_disas_context = riscv_tr_init_disas_context,
1174    .tb_start           = riscv_tr_tb_start,
1175    .insn_start         = riscv_tr_insn_start,
1176    .translate_insn     = riscv_tr_translate_insn,
1177    .tb_stop            = riscv_tr_tb_stop,
1178    .disas_log          = riscv_tr_disas_log,
1179};
1180
1181void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
1182{
1183    DisasContext ctx;
1184
1185    translator_loop(&riscv_tr_ops, &ctx.base, cs, tb, max_insns);
1186}
1187
1188void riscv_translate_init(void)
1189{
1190    int i;
1191
1192    /*
1193     * cpu_gpr[0] is a placeholder for the zero register. Do not use it.
1194     * Use the gen_set_gpr and get_gpr helper functions when accessing regs,
1195     * unless you specifically block reads/writes to reg 0.
1196     */
1197    cpu_gpr[0] = NULL;
1198    cpu_gprh[0] = NULL;
1199
1200    for (i = 1; i < 32; i++) {
1201        cpu_gpr[i] = tcg_global_mem_new(cpu_env,
1202            offsetof(CPURISCVState, gpr[i]), riscv_int_regnames[i]);
1203        cpu_gprh[i] = tcg_global_mem_new(cpu_env,
1204            offsetof(CPURISCVState, gprh[i]), riscv_int_regnamesh[i]);
1205    }
1206
1207    for (i = 0; i < 32; i++) {
1208        cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env,
1209            offsetof(CPURISCVState, fpr[i]), riscv_fpr_regnames[i]);
1210    }
1211
1212    cpu_pc = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, pc), "pc");
1213    cpu_vl = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, vl), "vl");
1214    cpu_vstart = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, vstart),
1215                            "vstart");
1216    load_res = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_res),
1217                             "load_res");
1218    load_val = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_val),
1219                             "load_val");
1220    /* Assign PM CSRs to tcg globals */
1221    pm_mask = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, cur_pmmask),
1222                                 "pmmask");
1223    pm_base = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, cur_pmbase),
1224                                 "pmbase");
1225}
1226