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 65c23704eSSong Gaostatic bool gen_ll(DisasContext *ctx, arg_rr_i *a, MemOp mop) 75c23704eSSong Gao{ 8*77642f92SSong Gao TCGv t1 = tcg_temp_new(); 95c23704eSSong Gao TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); 105c23704eSSong Gao TCGv t0 = make_address_i(ctx, src1, a->imm); 115c23704eSSong Gao 12*77642f92SSong Gao tcg_gen_qemu_ld_i64(t1, t0, ctx->mem_idx, mop); 135c23704eSSong Gao tcg_gen_st_tl(t0, tcg_env, offsetof(CPULoongArchState, lladdr)); 14*77642f92SSong Gao tcg_gen_st_tl(t1, tcg_env, offsetof(CPULoongArchState, llval)); 15*77642f92SSong Gao gen_set_gpr(a->rd, t1, EXT_NONE); 165c23704eSSong Gao 175c23704eSSong Gao return true; 185c23704eSSong Gao} 195c23704eSSong Gao 205c23704eSSong Gaostatic bool gen_sc(DisasContext *ctx, arg_rr_i *a, MemOp mop) 215c23704eSSong Gao{ 225c23704eSSong Gao TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); 235c23704eSSong Gao TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); 245c23704eSSong Gao TCGv src2 = gpr_src(ctx, a->rd, EXT_NONE); 255c23704eSSong Gao TCGv t0 = tcg_temp_new(); 265c23704eSSong Gao TCGv val = tcg_temp_new(); 275c23704eSSong Gao 285c23704eSSong Gao TCGLabel *l1 = gen_new_label(); 295c23704eSSong Gao TCGLabel *done = gen_new_label(); 305c23704eSSong Gao 315c23704eSSong Gao tcg_gen_addi_tl(t0, src1, a->imm); 325c23704eSSong Gao tcg_gen_brcond_tl(TCG_COND_EQ, t0, cpu_lladdr, l1); 335c23704eSSong Gao tcg_gen_movi_tl(dest, 0); 345c23704eSSong Gao tcg_gen_br(done); 355c23704eSSong Gao 365c23704eSSong Gao gen_set_label(l1); 375c23704eSSong Gao tcg_gen_mov_tl(val, src2); 385c23704eSSong Gao /* generate cmpxchg */ 395c23704eSSong Gao tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, 405c23704eSSong Gao val, ctx->mem_idx, mop); 415c23704eSSong Gao tcg_gen_setcond_tl(TCG_COND_EQ, dest, t0, cpu_llval); 425c23704eSSong Gao gen_set_label(done); 435c23704eSSong Gao gen_set_gpr(a->rd, dest, EXT_NONE); 445c23704eSSong Gao 455c23704eSSong Gao return true; 465c23704eSSong Gao} 475c23704eSSong Gao 485c23704eSSong Gaostatic bool gen_am(DisasContext *ctx, arg_rrr *a, 495c23704eSSong Gao void (*func)(TCGv, TCGv, TCGv, TCGArg, MemOp), 505c23704eSSong Gao MemOp mop) 515c23704eSSong Gao{ 525c23704eSSong Gao TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); 535c23704eSSong Gao TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); 545c23704eSSong Gao TCGv val = gpr_src(ctx, a->rk, EXT_NONE); 555c23704eSSong Gao 565c23704eSSong Gao if (a->rd != 0 && (a->rj == a->rd || a->rk == a->rd)) { 575c23704eSSong Gao qemu_log_mask(LOG_GUEST_ERROR, 585c23704eSSong Gao "Warning: source register overlaps destination register" 595c23704eSSong Gao "in atomic insn at pc=0x" TARGET_FMT_lx "\n", 605c23704eSSong Gao ctx->base.pc_next - 4); 615c23704eSSong Gao return false; 625c23704eSSong Gao } 635c23704eSSong Gao 645c23704eSSong Gao addr = make_address_i(ctx, addr, 0); 655c23704eSSong Gao 665c23704eSSong Gao func(dest, addr, val, ctx->mem_idx, mop); 675c23704eSSong Gao gen_set_gpr(a->rd, dest, EXT_NONE); 685c23704eSSong Gao 695c23704eSSong Gao return true; 705c23704eSSong Gao} 715c23704eSSong Gao 725c23704eSSong GaoTRANS(ll_w, ALL, gen_ll, MO_TESL) 735c23704eSSong GaoTRANS(sc_w, ALL, gen_sc, MO_TESL) 745c23704eSSong GaoTRANS(ll_d, 64, gen_ll, MO_TEUQ) 755c23704eSSong GaoTRANS(sc_d, 64, gen_sc, MO_TEUQ) 765c23704eSSong GaoTRANS(amswap_w, LAM, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL) 775c23704eSSong GaoTRANS(amswap_d, LAM, gen_am, tcg_gen_atomic_xchg_tl, MO_TEUQ) 785c23704eSSong GaoTRANS(amadd_w, LAM, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL) 795c23704eSSong GaoTRANS(amadd_d, LAM, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEUQ) 805c23704eSSong GaoTRANS(amand_w, LAM, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL) 815c23704eSSong GaoTRANS(amand_d, LAM, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEUQ) 825c23704eSSong GaoTRANS(amor_w, LAM, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL) 835c23704eSSong GaoTRANS(amor_d, LAM, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEUQ) 845c23704eSSong GaoTRANS(amxor_w, LAM, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TESL) 855c23704eSSong GaoTRANS(amxor_d, LAM, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEUQ) 865c23704eSSong GaoTRANS(ammax_w, LAM, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TESL) 875c23704eSSong GaoTRANS(ammax_d, LAM, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEUQ) 885c23704eSSong GaoTRANS(ammin_w, LAM, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TESL) 895c23704eSSong GaoTRANS(ammin_d, LAM, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEUQ) 905c23704eSSong GaoTRANS(ammax_wu, LAM, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TESL) 915c23704eSSong GaoTRANS(ammax_du, LAM, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEUQ) 925c23704eSSong GaoTRANS(ammin_wu, LAM, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TESL) 935c23704eSSong GaoTRANS(ammin_du, LAM, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEUQ) 945c23704eSSong GaoTRANS(amswap_db_w, LAM, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL) 955c23704eSSong GaoTRANS(amswap_db_d, LAM, gen_am, tcg_gen_atomic_xchg_tl, MO_TEUQ) 965c23704eSSong GaoTRANS(amadd_db_w, LAM, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL) 975c23704eSSong GaoTRANS(amadd_db_d, LAM, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEUQ) 985c23704eSSong GaoTRANS(amand_db_w, LAM, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL) 995c23704eSSong GaoTRANS(amand_db_d, LAM, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEUQ) 1005c23704eSSong GaoTRANS(amor_db_w, LAM, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL) 1015c23704eSSong GaoTRANS(amor_db_d, LAM, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEUQ) 1025c23704eSSong GaoTRANS(amxor_db_w, LAM, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TESL) 1035c23704eSSong GaoTRANS(amxor_db_d, LAM, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEUQ) 1045c23704eSSong GaoTRANS(ammax_db_w, LAM, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TESL) 1055c23704eSSong GaoTRANS(ammax_db_d, LAM, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEUQ) 1065c23704eSSong GaoTRANS(ammin_db_w, LAM, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TESL) 1075c23704eSSong GaoTRANS(ammin_db_d, LAM, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEUQ) 1085c23704eSSong GaoTRANS(ammax_db_wu, LAM, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TESL) 1095c23704eSSong GaoTRANS(ammax_db_du, LAM, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEUQ) 1105c23704eSSong GaoTRANS(ammin_db_wu, LAM, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TESL) 1115c23704eSSong GaoTRANS(ammin_db_du, LAM, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEUQ) 112