15c23704eSSong Gao/* SPDX-License-Identifier: GPL-2.0-or-later */ 25c23704eSSong Gao/* 35c23704eSSong Gao * Copyright (c) 2021 Loongson Technology Corporation Limited 45c23704eSSong Gao * 55c23704eSSong Gao * LoongArch translation routines for the privileged instructions. 65c23704eSSong Gao */ 75c23704eSSong Gao 85c23704eSSong Gao#include "cpu-csr.h" 95c23704eSSong Gao 105c23704eSSong Gao#ifdef CONFIG_USER_ONLY 115c23704eSSong Gao 125c23704eSSong Gao#define GEN_FALSE_TRANS(name) \ 135c23704eSSong Gaostatic bool trans_##name(DisasContext *ctx, arg_##name * a) \ 145c23704eSSong Gao{ \ 155c23704eSSong Gao return false; \ 165c23704eSSong Gao} 175c23704eSSong Gao 185c23704eSSong GaoGEN_FALSE_TRANS(csrrd) 195c23704eSSong GaoGEN_FALSE_TRANS(csrwr) 205c23704eSSong GaoGEN_FALSE_TRANS(csrxchg) 215c23704eSSong GaoGEN_FALSE_TRANS(iocsrrd_b) 225c23704eSSong GaoGEN_FALSE_TRANS(iocsrrd_h) 235c23704eSSong GaoGEN_FALSE_TRANS(iocsrrd_w) 245c23704eSSong GaoGEN_FALSE_TRANS(iocsrrd_d) 255c23704eSSong GaoGEN_FALSE_TRANS(iocsrwr_b) 265c23704eSSong GaoGEN_FALSE_TRANS(iocsrwr_h) 275c23704eSSong GaoGEN_FALSE_TRANS(iocsrwr_w) 285c23704eSSong GaoGEN_FALSE_TRANS(iocsrwr_d) 295c23704eSSong GaoGEN_FALSE_TRANS(tlbsrch) 305c23704eSSong GaoGEN_FALSE_TRANS(tlbrd) 315c23704eSSong GaoGEN_FALSE_TRANS(tlbwr) 325c23704eSSong GaoGEN_FALSE_TRANS(tlbfill) 335c23704eSSong GaoGEN_FALSE_TRANS(tlbclr) 345c23704eSSong GaoGEN_FALSE_TRANS(tlbflush) 355c23704eSSong GaoGEN_FALSE_TRANS(invtlb) 365c23704eSSong GaoGEN_FALSE_TRANS(cacop) 375c23704eSSong GaoGEN_FALSE_TRANS(ldpte) 385c23704eSSong GaoGEN_FALSE_TRANS(lddir) 395c23704eSSong GaoGEN_FALSE_TRANS(ertn) 405c23704eSSong GaoGEN_FALSE_TRANS(dbcl) 415c23704eSSong GaoGEN_FALSE_TRANS(idle) 425c23704eSSong Gao 435c23704eSSong Gao#else 445c23704eSSong Gao 455c23704eSSong Gaotypedef void (*GenCSRRead)(TCGv dest, TCGv_ptr env); 465c23704eSSong Gaotypedef void (*GenCSRWrite)(TCGv dest, TCGv_ptr env, TCGv src); 475c23704eSSong Gao 485c23704eSSong Gaotypedef struct { 495c23704eSSong Gao int offset; 505c23704eSSong Gao int flags; 515c23704eSSong Gao GenCSRRead readfn; 525c23704eSSong Gao GenCSRWrite writefn; 535c23704eSSong Gao} CSRInfo; 545c23704eSSong Gao 555c23704eSSong Gaoenum { 565c23704eSSong Gao CSRFL_READONLY = (1 << 0), 575c23704eSSong Gao CSRFL_EXITTB = (1 << 1), 585c23704eSSong Gao CSRFL_IO = (1 << 2), 595c23704eSSong Gao}; 605c23704eSSong Gao 615c23704eSSong Gao#define CSR_OFF_FUNCS(NAME, FL, RD, WR) \ 625c23704eSSong Gao [LOONGARCH_CSR_##NAME] = { \ 635c23704eSSong Gao .offset = offsetof(CPULoongArchState, CSR_##NAME), \ 645c23704eSSong Gao .flags = FL, .readfn = RD, .writefn = WR \ 655c23704eSSong Gao } 665c23704eSSong Gao 675c23704eSSong Gao#define CSR_OFF_ARRAY(NAME, N) \ 685c23704eSSong Gao [LOONGARCH_CSR_##NAME(N)] = { \ 695c23704eSSong Gao .offset = offsetof(CPULoongArchState, CSR_##NAME[N]), \ 705c23704eSSong Gao .flags = 0, .readfn = NULL, .writefn = NULL \ 715c23704eSSong Gao } 725c23704eSSong Gao 735c23704eSSong Gao#define CSR_OFF_FLAGS(NAME, FL) \ 745c23704eSSong Gao CSR_OFF_FUNCS(NAME, FL, NULL, NULL) 755c23704eSSong Gao 765c23704eSSong Gao#define CSR_OFF(NAME) \ 775c23704eSSong Gao CSR_OFF_FLAGS(NAME, 0) 785c23704eSSong Gao 795c23704eSSong Gaostatic const CSRInfo csr_info[] = { 805c23704eSSong Gao CSR_OFF_FLAGS(CRMD, CSRFL_EXITTB), 815c23704eSSong Gao CSR_OFF(PRMD), 825c23704eSSong Gao CSR_OFF_FLAGS(EUEN, CSRFL_EXITTB), 835c23704eSSong Gao CSR_OFF_FLAGS(MISC, CSRFL_READONLY), 845c23704eSSong Gao CSR_OFF(ECFG), 855c23704eSSong Gao CSR_OFF_FUNCS(ESTAT, CSRFL_EXITTB, NULL, gen_helper_csrwr_estat), 865c23704eSSong Gao CSR_OFF(ERA), 875c23704eSSong Gao CSR_OFF(BADV), 885c23704eSSong Gao CSR_OFF_FLAGS(BADI, CSRFL_READONLY), 895c23704eSSong Gao CSR_OFF(EENTRY), 905c23704eSSong Gao CSR_OFF(TLBIDX), 915c23704eSSong Gao CSR_OFF(TLBEHI), 925c23704eSSong Gao CSR_OFF(TLBELO0), 935c23704eSSong Gao CSR_OFF(TLBELO1), 945c23704eSSong Gao CSR_OFF_FUNCS(ASID, CSRFL_EXITTB, NULL, gen_helper_csrwr_asid), 955c23704eSSong Gao CSR_OFF(PGDL), 965c23704eSSong Gao CSR_OFF(PGDH), 975c23704eSSong Gao CSR_OFF_FUNCS(PGD, CSRFL_READONLY, gen_helper_csrrd_pgd, NULL), 985c23704eSSong Gao CSR_OFF(PWCL), 995c23704eSSong Gao CSR_OFF(PWCH), 1005c23704eSSong Gao CSR_OFF(STLBPS), 1015c23704eSSong Gao CSR_OFF(RVACFG), 1025c23704eSSong Gao CSR_OFF_FUNCS(CPUID, CSRFL_READONLY, gen_helper_csrrd_cpuid, NULL), 1035c23704eSSong Gao CSR_OFF_FLAGS(PRCFG1, CSRFL_READONLY), 1045c23704eSSong Gao CSR_OFF_FLAGS(PRCFG2, CSRFL_READONLY), 1055c23704eSSong Gao CSR_OFF_FLAGS(PRCFG3, CSRFL_READONLY), 1065c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 0), 1075c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 1), 1085c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 2), 1095c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 3), 1105c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 4), 1115c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 5), 1125c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 6), 1135c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 7), 1145c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 8), 1155c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 9), 1165c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 10), 1175c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 11), 1185c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 12), 1195c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 13), 1205c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 14), 1215c23704eSSong Gao CSR_OFF_ARRAY(SAVE, 15), 1225c23704eSSong Gao CSR_OFF(TID), 1235c23704eSSong Gao CSR_OFF_FUNCS(TCFG, CSRFL_IO, NULL, gen_helper_csrwr_tcfg), 1245c23704eSSong Gao CSR_OFF_FUNCS(TVAL, CSRFL_READONLY | CSRFL_IO, gen_helper_csrrd_tval, NULL), 1255c23704eSSong Gao CSR_OFF(CNTC), 1265c23704eSSong Gao CSR_OFF_FUNCS(TICLR, CSRFL_IO, NULL, gen_helper_csrwr_ticlr), 1275c23704eSSong Gao CSR_OFF(LLBCTL), 1285c23704eSSong Gao CSR_OFF(IMPCTL1), 1295c23704eSSong Gao CSR_OFF(IMPCTL2), 1305c23704eSSong Gao CSR_OFF(TLBRENTRY), 1315c23704eSSong Gao CSR_OFF(TLBRBADV), 1325c23704eSSong Gao CSR_OFF(TLBRERA), 1335c23704eSSong Gao CSR_OFF(TLBRSAVE), 1345c23704eSSong Gao CSR_OFF(TLBRELO0), 1355c23704eSSong Gao CSR_OFF(TLBRELO1), 1365c23704eSSong Gao CSR_OFF(TLBREHI), 1375c23704eSSong Gao CSR_OFF(TLBRPRMD), 1385c23704eSSong Gao CSR_OFF(MERRCTL), 1395c23704eSSong Gao CSR_OFF(MERRINFO1), 1405c23704eSSong Gao CSR_OFF(MERRINFO2), 1415c23704eSSong Gao CSR_OFF(MERRENTRY), 1425c23704eSSong Gao CSR_OFF(MERRERA), 1435c23704eSSong Gao CSR_OFF(MERRSAVE), 1445c23704eSSong Gao CSR_OFF(CTAG), 1455c23704eSSong Gao CSR_OFF_ARRAY(DMW, 0), 1465c23704eSSong Gao CSR_OFF_ARRAY(DMW, 1), 1475c23704eSSong Gao CSR_OFF_ARRAY(DMW, 2), 1485c23704eSSong Gao CSR_OFF_ARRAY(DMW, 3), 1495c23704eSSong Gao CSR_OFF(DBG), 1505c23704eSSong Gao CSR_OFF(DERA), 1515c23704eSSong Gao CSR_OFF(DSAVE), 1525c23704eSSong Gao}; 1535c23704eSSong Gao 1545c23704eSSong Gaostatic bool check_plv(DisasContext *ctx) 1555c23704eSSong Gao{ 1565c23704eSSong Gao if (ctx->plv == MMU_PLV_USER) { 1575c23704eSSong Gao generate_exception(ctx, EXCCODE_IPE); 1585c23704eSSong Gao return true; 1595c23704eSSong Gao } 1605c23704eSSong Gao return false; 1615c23704eSSong Gao} 1625c23704eSSong Gao 1635c23704eSSong Gaostatic const CSRInfo *get_csr(unsigned csr_num) 1645c23704eSSong Gao{ 1655c23704eSSong Gao const CSRInfo *csr; 1665c23704eSSong Gao 1675c23704eSSong Gao if (csr_num >= ARRAY_SIZE(csr_info)) { 1685c23704eSSong Gao return NULL; 1695c23704eSSong Gao } 1705c23704eSSong Gao csr = &csr_info[csr_num]; 1715c23704eSSong Gao if (csr->offset == 0) { 1725c23704eSSong Gao return NULL; 1735c23704eSSong Gao } 1745c23704eSSong Gao return csr; 1755c23704eSSong Gao} 1765c23704eSSong Gao 1775c23704eSSong Gaostatic bool check_csr_flags(DisasContext *ctx, const CSRInfo *csr, bool write) 1785c23704eSSong Gao{ 1795c23704eSSong Gao if ((csr->flags & CSRFL_READONLY) && write) { 1805c23704eSSong Gao return false; 1815c23704eSSong Gao } 1825c23704eSSong Gao if ((csr->flags & CSRFL_IO) && translator_io_start(&ctx->base)) { 1835c23704eSSong Gao ctx->base.is_jmp = DISAS_EXIT_UPDATE; 1845c23704eSSong Gao } else if ((csr->flags & CSRFL_EXITTB) && write) { 1855c23704eSSong Gao ctx->base.is_jmp = DISAS_EXIT_UPDATE; 1865c23704eSSong Gao } 1875c23704eSSong Gao return true; 1885c23704eSSong Gao} 1895c23704eSSong Gao 1905c23704eSSong Gaostatic bool trans_csrrd(DisasContext *ctx, arg_csrrd *a) 1915c23704eSSong Gao{ 1925c23704eSSong Gao TCGv dest; 1935c23704eSSong Gao const CSRInfo *csr; 1945c23704eSSong Gao 1955c23704eSSong Gao if (check_plv(ctx)) { 1965c23704eSSong Gao return false; 1975c23704eSSong Gao } 1985c23704eSSong Gao csr = get_csr(a->csr); 1995c23704eSSong Gao if (csr == NULL) { 2005c23704eSSong Gao /* CSR is undefined: read as 0. */ 2015c23704eSSong Gao dest = tcg_constant_tl(0); 2025c23704eSSong Gao } else { 2035c23704eSSong Gao check_csr_flags(ctx, csr, false); 2045c23704eSSong Gao dest = gpr_dst(ctx, a->rd, EXT_NONE); 2055c23704eSSong Gao if (csr->readfn) { 2065c23704eSSong Gao csr->readfn(dest, tcg_env); 2075c23704eSSong Gao } else { 2085c23704eSSong Gao tcg_gen_ld_tl(dest, tcg_env, csr->offset); 2095c23704eSSong Gao } 2105c23704eSSong Gao } 2115c23704eSSong Gao gen_set_gpr(a->rd, dest, EXT_NONE); 2125c23704eSSong Gao return true; 2135c23704eSSong Gao} 2145c23704eSSong Gao 2155c23704eSSong Gaostatic bool trans_csrwr(DisasContext *ctx, arg_csrwr *a) 2165c23704eSSong Gao{ 2175c23704eSSong Gao TCGv dest, src1; 2185c23704eSSong Gao const CSRInfo *csr; 2195c23704eSSong Gao 2205c23704eSSong Gao if (check_plv(ctx)) { 2215c23704eSSong Gao return false; 2225c23704eSSong Gao } 2235c23704eSSong Gao csr = get_csr(a->csr); 2245c23704eSSong Gao if (csr == NULL) { 2255c23704eSSong Gao /* CSR is undefined: write ignored, read old_value as 0. */ 2265c23704eSSong Gao gen_set_gpr(a->rd, tcg_constant_tl(0), EXT_NONE); 2275c23704eSSong Gao return true; 2285c23704eSSong Gao } 2295c23704eSSong Gao if (!check_csr_flags(ctx, csr, true)) { 2305c23704eSSong Gao /* CSR is readonly: trap. */ 2315c23704eSSong Gao return false; 2325c23704eSSong Gao } 2335c23704eSSong Gao src1 = gpr_src(ctx, a->rd, EXT_NONE); 2345c23704eSSong Gao if (csr->writefn) { 2355c23704eSSong Gao dest = gpr_dst(ctx, a->rd, EXT_NONE); 2365c23704eSSong Gao csr->writefn(dest, tcg_env, src1); 2375c23704eSSong Gao } else { 2385c23704eSSong Gao dest = tcg_temp_new(); 2395c23704eSSong Gao tcg_gen_ld_tl(dest, tcg_env, csr->offset); 2405c23704eSSong Gao tcg_gen_st_tl(src1, tcg_env, csr->offset); 2415c23704eSSong Gao } 2425c23704eSSong Gao gen_set_gpr(a->rd, dest, EXT_NONE); 2435c23704eSSong Gao return true; 2445c23704eSSong Gao} 2455c23704eSSong Gao 2465c23704eSSong Gaostatic bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a) 2475c23704eSSong Gao{ 2485c23704eSSong Gao TCGv src1, mask, oldv, newv, temp; 2495c23704eSSong Gao const CSRInfo *csr; 2505c23704eSSong Gao 2515c23704eSSong Gao if (check_plv(ctx)) { 2525c23704eSSong Gao return false; 2535c23704eSSong Gao } 2545c23704eSSong Gao csr = get_csr(a->csr); 2555c23704eSSong Gao if (csr == NULL) { 2565c23704eSSong Gao /* CSR is undefined: write ignored, read old_value as 0. */ 2575c23704eSSong Gao gen_set_gpr(a->rd, tcg_constant_tl(0), EXT_NONE); 2585c23704eSSong Gao return true; 2595c23704eSSong Gao } 2605c23704eSSong Gao 2615c23704eSSong Gao if (!check_csr_flags(ctx, csr, true)) { 2625c23704eSSong Gao /* CSR is readonly: trap. */ 2635c23704eSSong Gao return false; 2645c23704eSSong Gao } 2655c23704eSSong Gao 2665c23704eSSong Gao /* So far only readonly csrs have readfn. */ 2675c23704eSSong Gao assert(csr->readfn == NULL); 2685c23704eSSong Gao 2695c23704eSSong Gao src1 = gpr_src(ctx, a->rd, EXT_NONE); 2705c23704eSSong Gao mask = gpr_src(ctx, a->rj, EXT_NONE); 2715c23704eSSong Gao oldv = tcg_temp_new(); 2725c23704eSSong Gao newv = tcg_temp_new(); 2735c23704eSSong Gao temp = tcg_temp_new(); 2745c23704eSSong Gao 2755c23704eSSong Gao tcg_gen_ld_tl(oldv, tcg_env, csr->offset); 2765c23704eSSong Gao tcg_gen_and_tl(newv, src1, mask); 2775c23704eSSong Gao tcg_gen_andc_tl(temp, oldv, mask); 2785c23704eSSong Gao tcg_gen_or_tl(newv, newv, temp); 2795c23704eSSong Gao 2805c23704eSSong Gao if (csr->writefn) { 2815c23704eSSong Gao csr->writefn(oldv, tcg_env, newv); 2825c23704eSSong Gao } else { 2835c23704eSSong Gao tcg_gen_st_tl(newv, tcg_env, csr->offset); 2845c23704eSSong Gao } 2855c23704eSSong Gao gen_set_gpr(a->rd, oldv, EXT_NONE); 2865c23704eSSong Gao return true; 2875c23704eSSong Gao} 2885c23704eSSong Gao 2895c23704eSSong Gaostatic bool gen_iocsrrd(DisasContext *ctx, arg_rr *a, 2905c23704eSSong Gao void (*func)(TCGv, TCGv_ptr, TCGv)) 2915c23704eSSong Gao{ 2925c23704eSSong Gao TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); 2935c23704eSSong Gao TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); 2945c23704eSSong Gao 2955c23704eSSong Gao if (check_plv(ctx)) { 2965c23704eSSong Gao return false; 2975c23704eSSong Gao } 2985c23704eSSong Gao func(dest, tcg_env, src1); 2995c23704eSSong Gao return true; 3005c23704eSSong Gao} 3015c23704eSSong Gao 3025c23704eSSong Gaostatic bool gen_iocsrwr(DisasContext *ctx, arg_rr *a, 3035c23704eSSong Gao void (*func)(TCGv_ptr, TCGv, TCGv)) 3045c23704eSSong Gao{ 3055c23704eSSong Gao TCGv val = gpr_src(ctx, a->rd, EXT_NONE); 3065c23704eSSong Gao TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); 3075c23704eSSong Gao 3085c23704eSSong Gao if (check_plv(ctx)) { 3095c23704eSSong Gao return false; 3105c23704eSSong Gao } 3115c23704eSSong Gao func(tcg_env, addr, val); 3125c23704eSSong Gao return true; 3135c23704eSSong Gao} 3145c23704eSSong Gao 3155c23704eSSong GaoTRANS(iocsrrd_b, IOCSR, gen_iocsrrd, gen_helper_iocsrrd_b) 3165c23704eSSong GaoTRANS(iocsrrd_h, IOCSR, gen_iocsrrd, gen_helper_iocsrrd_h) 3175c23704eSSong GaoTRANS(iocsrrd_w, IOCSR, gen_iocsrrd, gen_helper_iocsrrd_w) 3185c23704eSSong GaoTRANS(iocsrrd_d, IOCSR, gen_iocsrrd, gen_helper_iocsrrd_d) 3195c23704eSSong GaoTRANS(iocsrwr_b, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_b) 3205c23704eSSong GaoTRANS(iocsrwr_h, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_h) 3215c23704eSSong GaoTRANS(iocsrwr_w, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_w) 3225c23704eSSong GaoTRANS(iocsrwr_d, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_d) 3235c23704eSSong Gao 3245c23704eSSong Gaostatic void check_mmu_idx(DisasContext *ctx) 3255c23704eSSong Gao{ 326*3f262d25SRichard Henderson if (ctx->mem_idx != MMU_DA_IDX) { 3275c23704eSSong Gao tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next + 4); 3285c23704eSSong Gao ctx->base.is_jmp = DISAS_EXIT; 3295c23704eSSong Gao } 3305c23704eSSong Gao} 3315c23704eSSong Gao 3325c23704eSSong Gaostatic bool trans_tlbsrch(DisasContext *ctx, arg_tlbsrch *a) 3335c23704eSSong Gao{ 3345c23704eSSong Gao if (check_plv(ctx)) { 3355c23704eSSong Gao return false; 3365c23704eSSong Gao } 3375c23704eSSong Gao gen_helper_tlbsrch(tcg_env); 3385c23704eSSong Gao return true; 3395c23704eSSong Gao} 3405c23704eSSong Gao 3415c23704eSSong Gaostatic bool trans_tlbrd(DisasContext *ctx, arg_tlbrd *a) 3425c23704eSSong Gao{ 3435c23704eSSong Gao if (check_plv(ctx)) { 3445c23704eSSong Gao return false; 3455c23704eSSong Gao } 3465c23704eSSong Gao gen_helper_tlbrd(tcg_env); 3475c23704eSSong Gao return true; 3485c23704eSSong Gao} 3495c23704eSSong Gao 3505c23704eSSong Gaostatic bool trans_tlbwr(DisasContext *ctx, arg_tlbwr *a) 3515c23704eSSong Gao{ 3525c23704eSSong Gao if (check_plv(ctx)) { 3535c23704eSSong Gao return false; 3545c23704eSSong Gao } 3555c23704eSSong Gao gen_helper_tlbwr(tcg_env); 3565c23704eSSong Gao check_mmu_idx(ctx); 3575c23704eSSong Gao return true; 3585c23704eSSong Gao} 3595c23704eSSong Gao 3605c23704eSSong Gaostatic bool trans_tlbfill(DisasContext *ctx, arg_tlbfill *a) 3615c23704eSSong Gao{ 3625c23704eSSong Gao if (check_plv(ctx)) { 3635c23704eSSong Gao return false; 3645c23704eSSong Gao } 3655c23704eSSong Gao gen_helper_tlbfill(tcg_env); 3665c23704eSSong Gao check_mmu_idx(ctx); 3675c23704eSSong Gao return true; 3685c23704eSSong Gao} 3695c23704eSSong Gao 3705c23704eSSong Gaostatic bool trans_tlbclr(DisasContext *ctx, arg_tlbclr *a) 3715c23704eSSong Gao{ 3725c23704eSSong Gao if (check_plv(ctx)) { 3735c23704eSSong Gao return false; 3745c23704eSSong Gao } 3755c23704eSSong Gao gen_helper_tlbclr(tcg_env); 3765c23704eSSong Gao check_mmu_idx(ctx); 3775c23704eSSong Gao return true; 3785c23704eSSong Gao} 3795c23704eSSong Gao 3805c23704eSSong Gaostatic bool trans_tlbflush(DisasContext *ctx, arg_tlbflush *a) 3815c23704eSSong Gao{ 3825c23704eSSong Gao if (check_plv(ctx)) { 3835c23704eSSong Gao return false; 3845c23704eSSong Gao } 3855c23704eSSong Gao gen_helper_tlbflush(tcg_env); 3865c23704eSSong Gao check_mmu_idx(ctx); 3875c23704eSSong Gao return true; 3885c23704eSSong Gao} 3895c23704eSSong Gao 3905c23704eSSong Gaostatic bool trans_invtlb(DisasContext *ctx, arg_invtlb *a) 3915c23704eSSong Gao{ 3925c23704eSSong Gao TCGv rj = gpr_src(ctx, a->rj, EXT_NONE); 3935c23704eSSong Gao TCGv rk = gpr_src(ctx, a->rk, EXT_NONE); 3945c23704eSSong Gao 3955c23704eSSong Gao if (check_plv(ctx)) { 3965c23704eSSong Gao return false; 3975c23704eSSong Gao } 3985c23704eSSong Gao 3995c23704eSSong Gao switch (a->imm) { 4005c23704eSSong Gao case 0: 4015c23704eSSong Gao case 1: 4025c23704eSSong Gao gen_helper_invtlb_all(tcg_env); 4035c23704eSSong Gao break; 4045c23704eSSong Gao case 2: 4055c23704eSSong Gao gen_helper_invtlb_all_g(tcg_env, tcg_constant_i32(1)); 4065c23704eSSong Gao break; 4075c23704eSSong Gao case 3: 4085c23704eSSong Gao gen_helper_invtlb_all_g(tcg_env, tcg_constant_i32(0)); 4095c23704eSSong Gao break; 4105c23704eSSong Gao case 4: 4115c23704eSSong Gao gen_helper_invtlb_all_asid(tcg_env, rj); 4125c23704eSSong Gao break; 4135c23704eSSong Gao case 5: 4145c23704eSSong Gao gen_helper_invtlb_page_asid(tcg_env, rj, rk); 4155c23704eSSong Gao break; 4165c23704eSSong Gao case 6: 4175c23704eSSong Gao gen_helper_invtlb_page_asid_or_g(tcg_env, rj, rk); 4185c23704eSSong Gao break; 4195c23704eSSong Gao default: 4205c23704eSSong Gao return false; 4215c23704eSSong Gao } 4225c23704eSSong Gao ctx->base.is_jmp = DISAS_STOP; 4235c23704eSSong Gao return true; 4245c23704eSSong Gao} 4255c23704eSSong Gao 4265c23704eSSong Gaostatic bool trans_cacop(DisasContext *ctx, arg_cacop *a) 4275c23704eSSong Gao{ 4285c23704eSSong Gao /* Treat the cacop as a nop */ 4295c23704eSSong Gao if (check_plv(ctx)) { 4305c23704eSSong Gao return false; 4315c23704eSSong Gao } 4325c23704eSSong Gao return true; 4335c23704eSSong Gao} 4345c23704eSSong Gao 4355c23704eSSong Gaostatic bool trans_ldpte(DisasContext *ctx, arg_ldpte *a) 4365c23704eSSong Gao{ 4375c23704eSSong Gao TCGv_i32 mem_idx = tcg_constant_i32(ctx->mem_idx); 4385c23704eSSong Gao TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); 4395c23704eSSong Gao 4405c23704eSSong Gao if (!avail_LSPW(ctx)) { 4415c23704eSSong Gao return true; 4425c23704eSSong Gao } 4435c23704eSSong Gao 4445c23704eSSong Gao if (check_plv(ctx)) { 4455c23704eSSong Gao return false; 4465c23704eSSong Gao } 4475c23704eSSong Gao gen_helper_ldpte(tcg_env, src1, tcg_constant_tl(a->imm), mem_idx); 4485c23704eSSong Gao return true; 4495c23704eSSong Gao} 4505c23704eSSong Gao 4515c23704eSSong Gaostatic bool trans_lddir(DisasContext *ctx, arg_lddir *a) 4525c23704eSSong Gao{ 4535c23704eSSong Gao TCGv_i32 mem_idx = tcg_constant_i32(ctx->mem_idx); 4545c23704eSSong Gao TCGv src = gpr_src(ctx, a->rj, EXT_NONE); 4555c23704eSSong Gao TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); 4565c23704eSSong Gao 4575c23704eSSong Gao if (!avail_LSPW(ctx)) { 4585c23704eSSong Gao return true; 4595c23704eSSong Gao } 4605c23704eSSong Gao 4615c23704eSSong Gao if (check_plv(ctx)) { 4625c23704eSSong Gao return false; 4635c23704eSSong Gao } 4645c23704eSSong Gao gen_helper_lddir(dest, tcg_env, src, tcg_constant_tl(a->imm), mem_idx); 4655c23704eSSong Gao return true; 4665c23704eSSong Gao} 4675c23704eSSong Gao 4685c23704eSSong Gaostatic bool trans_ertn(DisasContext *ctx, arg_ertn *a) 4695c23704eSSong Gao{ 4705c23704eSSong Gao if (check_plv(ctx)) { 4715c23704eSSong Gao return false; 4725c23704eSSong Gao } 4735c23704eSSong Gao gen_helper_ertn(tcg_env); 4745c23704eSSong Gao ctx->base.is_jmp = DISAS_EXIT; 4755c23704eSSong Gao return true; 4765c23704eSSong Gao} 4775c23704eSSong Gao 4785c23704eSSong Gaostatic bool trans_dbcl(DisasContext *ctx, arg_dbcl *a) 4795c23704eSSong Gao{ 4805c23704eSSong Gao if (check_plv(ctx)) { 4815c23704eSSong Gao return false; 4825c23704eSSong Gao } 4835c23704eSSong Gao generate_exception(ctx, EXCCODE_DBP); 4845c23704eSSong Gao return true; 4855c23704eSSong Gao} 4865c23704eSSong Gao 4875c23704eSSong Gaostatic bool trans_idle(DisasContext *ctx, arg_idle *a) 4885c23704eSSong Gao{ 4895c23704eSSong Gao if (check_plv(ctx)) { 4905c23704eSSong Gao return false; 4915c23704eSSong Gao } 4925c23704eSSong Gao 4935c23704eSSong Gao tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next + 4); 4945c23704eSSong Gao gen_helper_idle(tcg_env); 4955c23704eSSong Gao ctx->base.is_jmp = DISAS_NORETURN; 4965c23704eSSong Gao return true; 4975c23704eSSong Gao} 4985c23704eSSong Gao#endif 499