1/* 2 * RISC-V translation routines for the Zc[b,mp] Standard Extensions. 3 * 4 * Copyright (c) 2021-2022 PLCT Lab 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#define REQUIRE_ZCB(ctx) do { \ 20 if (!ctx->cfg_ptr->ext_zcb) \ 21 return false; \ 22} while (0) 23 24#define REQUIRE_ZCMP(ctx) do { \ 25 if (!ctx->cfg_ptr->ext_zcmp) \ 26 return false; \ 27} while (0) 28 29static bool trans_c_zext_b(DisasContext *ctx, arg_c_zext_b *a) 30{ 31 REQUIRE_ZCB(ctx); 32 return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext8u_tl); 33} 34 35static bool trans_c_zext_h(DisasContext *ctx, arg_c_zext_h *a) 36{ 37 REQUIRE_ZCB(ctx); 38 REQUIRE_ZBB(ctx); 39 return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext16u_tl); 40} 41 42static bool trans_c_sext_b(DisasContext *ctx, arg_c_sext_b *a) 43{ 44 REQUIRE_ZCB(ctx); 45 REQUIRE_ZBB(ctx); 46 return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext8s_tl); 47} 48 49static bool trans_c_sext_h(DisasContext *ctx, arg_c_sext_h *a) 50{ 51 REQUIRE_ZCB(ctx); 52 REQUIRE_ZBB(ctx); 53 return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext16s_tl); 54} 55 56static bool trans_c_zext_w(DisasContext *ctx, arg_c_zext_w *a) 57{ 58 REQUIRE_64BIT(ctx); 59 REQUIRE_ZCB(ctx); 60 REQUIRE_ZBA(ctx); 61 return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext32u_tl); 62} 63 64static bool trans_c_not(DisasContext *ctx, arg_c_not *a) 65{ 66 REQUIRE_ZCB(ctx); 67 return gen_unary(ctx, a, EXT_NONE, tcg_gen_not_tl); 68} 69 70static bool trans_c_mul(DisasContext *ctx, arg_c_mul *a) 71{ 72 REQUIRE_ZCB(ctx); 73 REQUIRE_M_OR_ZMMUL(ctx); 74 return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl, NULL); 75} 76 77static bool trans_c_lbu(DisasContext *ctx, arg_c_lbu *a) 78{ 79 REQUIRE_ZCB(ctx); 80 return gen_load(ctx, a, MO_UB); 81} 82 83static bool trans_c_lhu(DisasContext *ctx, arg_c_lhu *a) 84{ 85 REQUIRE_ZCB(ctx); 86 return gen_load(ctx, a, MO_UW); 87} 88 89static bool trans_c_lh(DisasContext *ctx, arg_c_lh *a) 90{ 91 REQUIRE_ZCB(ctx); 92 return gen_load(ctx, a, MO_SW); 93} 94 95static bool trans_c_sb(DisasContext *ctx, arg_c_sb *a) 96{ 97 REQUIRE_ZCB(ctx); 98 return gen_store(ctx, a, MO_UB); 99} 100 101static bool trans_c_sh(DisasContext *ctx, arg_c_sh *a) 102{ 103 REQUIRE_ZCB(ctx); 104 return gen_store(ctx, a, MO_UW); 105} 106 107#define X_S0 8 108#define X_S1 9 109#define X_Sn 16 110 111static uint32_t decode_push_pop_list(DisasContext *ctx, target_ulong rlist) 112{ 113 uint32_t reg_bitmap = 0; 114 115 if (ctx->cfg_ptr->ext_e && rlist > 6) { 116 return 0; 117 } 118 119 switch (rlist) { 120 case 15: 121 reg_bitmap |= 1 << (X_Sn + 11) ; 122 reg_bitmap |= 1 << (X_Sn + 10) ; 123 /* FALL THROUGH */ 124 case 14: 125 reg_bitmap |= 1 << (X_Sn + 9) ; 126 /* FALL THROUGH */ 127 case 13: 128 reg_bitmap |= 1 << (X_Sn + 8) ; 129 /* FALL THROUGH */ 130 case 12: 131 reg_bitmap |= 1 << (X_Sn + 7) ; 132 /* FALL THROUGH */ 133 case 11: 134 reg_bitmap |= 1 << (X_Sn + 6) ; 135 /* FALL THROUGH */ 136 case 10: 137 reg_bitmap |= 1 << (X_Sn + 5) ; 138 /* FALL THROUGH */ 139 case 9: 140 reg_bitmap |= 1 << (X_Sn + 4) ; 141 /* FALL THROUGH */ 142 case 8: 143 reg_bitmap |= 1 << (X_Sn + 3) ; 144 /* FALL THROUGH */ 145 case 7: 146 reg_bitmap |= 1 << (X_Sn + 2) ; 147 /* FALL THROUGH */ 148 case 6: 149 reg_bitmap |= 1 << X_S1 ; 150 /* FALL THROUGH */ 151 case 5: 152 reg_bitmap |= 1 << X_S0; 153 /* FALL THROUGH */ 154 case 4: 155 reg_bitmap |= 1 << xRA; 156 break; 157 default: 158 break; 159 } 160 161 return reg_bitmap; 162} 163 164static bool gen_pop(DisasContext *ctx, arg_cmpp *a, bool ret, bool ret_val) 165{ 166 REQUIRE_ZCMP(ctx); 167 168 uint32_t reg_bitmap = decode_push_pop_list(ctx, a->urlist); 169 if (reg_bitmap == 0) { 170 return false; 171 } 172 173 MemOp memop = get_ol(ctx) == MXL_RV32 ? MO_TEUL : MO_TEUQ; 174 int reg_size = memop_size(memop); 175 target_ulong stack_adj = ROUND_UP(ctpop32(reg_bitmap) * reg_size, 16) + 176 a->spimm; 177 TCGv sp = dest_gpr(ctx, xSP); 178 TCGv addr = tcg_temp_new(); 179 int i; 180 181 tcg_gen_addi_tl(addr, sp, stack_adj - reg_size); 182 183 for (i = X_Sn + 11; i >= 0; i--) { 184 if (reg_bitmap & (1 << i)) { 185 TCGv dest = dest_gpr(ctx, i); 186 tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, memop); 187 gen_set_gpr(ctx, i, dest); 188 tcg_gen_subi_tl(addr, addr, reg_size); 189 } 190 } 191 192 tcg_gen_addi_tl(sp, sp, stack_adj); 193 gen_set_gpr(ctx, xSP, sp); 194 195 if (ret_val) { 196 gen_set_gpr(ctx, xA0, ctx->zero); 197 } 198 199 if (ret) { 200 TCGv ret_addr = get_gpr(ctx, xRA, EXT_NONE); 201 gen_set_pc(ctx, ret_addr); 202 tcg_gen_lookup_and_goto_ptr(); 203 ctx->base.is_jmp = DISAS_NORETURN; 204 } 205 206 return true; 207} 208 209static bool trans_cm_push(DisasContext *ctx, arg_cm_push *a) 210{ 211 REQUIRE_ZCMP(ctx); 212 213 uint32_t reg_bitmap = decode_push_pop_list(ctx, a->urlist); 214 if (reg_bitmap == 0) { 215 return false; 216 } 217 218 MemOp memop = get_ol(ctx) == MXL_RV32 ? MO_TEUL : MO_TEUQ; 219 int reg_size = memop_size(memop); 220 target_ulong stack_adj = ROUND_UP(ctpop32(reg_bitmap) * reg_size, 16) + 221 a->spimm; 222 TCGv sp = dest_gpr(ctx, xSP); 223 TCGv addr = tcg_temp_new(); 224 int i; 225 226 tcg_gen_subi_tl(addr, sp, reg_size); 227 228 for (i = X_Sn + 11; i >= 0; i--) { 229 if (reg_bitmap & (1 << i)) { 230 TCGv val = get_gpr(ctx, i, EXT_NONE); 231 tcg_gen_qemu_st_tl(val, addr, ctx->mem_idx, memop); 232 tcg_gen_subi_tl(addr, addr, reg_size); 233 } 234 } 235 236 tcg_gen_subi_tl(sp, sp, stack_adj); 237 gen_set_gpr(ctx, xSP, sp); 238 239 return true; 240} 241 242static bool trans_cm_pop(DisasContext *ctx, arg_cm_pop *a) 243{ 244 return gen_pop(ctx, a, false, false); 245} 246 247static bool trans_cm_popret(DisasContext *ctx, arg_cm_popret *a) 248{ 249 return gen_pop(ctx, a, true, false); 250} 251 252static bool trans_cm_popretz(DisasContext *ctx, arg_cm_popret *a) 253{ 254 return gen_pop(ctx, a, true, true); 255} 256 257static bool trans_cm_mva01s(DisasContext *ctx, arg_cm_mva01s *a) 258{ 259 REQUIRE_ZCMP(ctx); 260 261 TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); 262 TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); 263 264 gen_set_gpr(ctx, xA0, src1); 265 gen_set_gpr(ctx, xA1, src2); 266 267 return true; 268} 269 270static bool trans_cm_mvsa01(DisasContext *ctx, arg_cm_mvsa01 *a) 271{ 272 REQUIRE_ZCMP(ctx); 273 274 if (a->rs1 == a->rs2) { 275 return false; 276 } 277 278 TCGv a0 = get_gpr(ctx, xA0, EXT_NONE); 279 TCGv a1 = get_gpr(ctx, xA1, EXT_NONE); 280 281 gen_set_gpr(ctx, a->rs1, a0); 282 gen_set_gpr(ctx, a->rs2, a1); 283 284 return true; 285} 286