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-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 34 /* global register indices */ 35 static TCGv cpu_gpr[32], cpu_pc; 36 static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */ 37 static TCGv load_res; 38 static TCGv load_val; 39 40 #include "exec/gen-icount.h" 41 42 typedef struct DisasContext { 43 DisasContextBase base; 44 /* pc_succ_insn points to the instruction following base.pc_next */ 45 target_ulong pc_succ_insn; 46 target_ulong priv_ver; 47 uint32_t opcode; 48 uint32_t mstatus_fs; 49 uint32_t misa; 50 uint32_t mem_idx; 51 /* Remember the rounding mode encoded in the previous fp instruction, 52 which we have already installed into env->fp_status. Or -1 for 53 no previous fp instruction. Note that we exit the TB when writing 54 to any system register, which includes CSR_FRM, so we do not have 55 to reset this known value. */ 56 int frm; 57 } DisasContext; 58 59 /* convert riscv funct3 to qemu memop for load/store */ 60 static const int tcg_memop_lookup[8] = { 61 [0 ... 7] = -1, 62 [0] = MO_SB, 63 [1] = MO_TESW, 64 [2] = MO_TESL, 65 [4] = MO_UB, 66 [5] = MO_TEUW, 67 #ifdef TARGET_RISCV64 68 [3] = MO_TEQ, 69 [6] = MO_TEUL, 70 #endif 71 }; 72 73 #ifdef TARGET_RISCV64 74 #define CASE_OP_32_64(X) case X: case glue(X, W) 75 #else 76 #define CASE_OP_32_64(X) case X 77 #endif 78 79 static inline bool has_ext(DisasContext *ctx, uint32_t ext) 80 { 81 return ctx->misa & ext; 82 } 83 84 static void generate_exception(DisasContext *ctx, int excp) 85 { 86 tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); 87 TCGv_i32 helper_tmp = tcg_const_i32(excp); 88 gen_helper_raise_exception(cpu_env, helper_tmp); 89 tcg_temp_free_i32(helper_tmp); 90 ctx->base.is_jmp = DISAS_NORETURN; 91 } 92 93 static void generate_exception_mbadaddr(DisasContext *ctx, int excp) 94 { 95 tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); 96 tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr)); 97 TCGv_i32 helper_tmp = tcg_const_i32(excp); 98 gen_helper_raise_exception(cpu_env, helper_tmp); 99 tcg_temp_free_i32(helper_tmp); 100 ctx->base.is_jmp = DISAS_NORETURN; 101 } 102 103 static void gen_exception_debug(void) 104 { 105 TCGv_i32 helper_tmp = tcg_const_i32(EXCP_DEBUG); 106 gen_helper_raise_exception(cpu_env, helper_tmp); 107 tcg_temp_free_i32(helper_tmp); 108 } 109 110 static void gen_exception_illegal(DisasContext *ctx) 111 { 112 generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); 113 } 114 115 static void gen_exception_inst_addr_mis(DisasContext *ctx) 116 { 117 generate_exception_mbadaddr(ctx, RISCV_EXCP_INST_ADDR_MIS); 118 } 119 120 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest) 121 { 122 if (unlikely(ctx->base.singlestep_enabled)) { 123 return false; 124 } 125 126 #ifndef CONFIG_USER_ONLY 127 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); 128 #else 129 return true; 130 #endif 131 } 132 133 static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) 134 { 135 if (use_goto_tb(ctx, dest)) { 136 /* chaining is only allowed when the jump is to the same page */ 137 tcg_gen_goto_tb(n); 138 tcg_gen_movi_tl(cpu_pc, dest); 139 tcg_gen_exit_tb(ctx->base.tb, n); 140 } else { 141 tcg_gen_movi_tl(cpu_pc, dest); 142 if (ctx->base.singlestep_enabled) { 143 gen_exception_debug(); 144 } else { 145 tcg_gen_lookup_and_goto_ptr(); 146 } 147 } 148 } 149 150 /* Wrapper for getting reg values - need to check of reg is zero since 151 * cpu_gpr[0] is not actually allocated 152 */ 153 static inline void gen_get_gpr(TCGv t, int reg_num) 154 { 155 if (reg_num == 0) { 156 tcg_gen_movi_tl(t, 0); 157 } else { 158 tcg_gen_mov_tl(t, cpu_gpr[reg_num]); 159 } 160 } 161 162 /* Wrapper for setting reg values - need to check of reg is zero since 163 * cpu_gpr[0] is not actually allocated. this is more for safety purposes, 164 * since we usually avoid calling the OP_TYPE_gen function if we see a write to 165 * $zero 166 */ 167 static inline void gen_set_gpr(int reg_num_dst, TCGv t) 168 { 169 if (reg_num_dst != 0) { 170 tcg_gen_mov_tl(cpu_gpr[reg_num_dst], t); 171 } 172 } 173 174 static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2) 175 { 176 TCGv rl = tcg_temp_new(); 177 TCGv rh = tcg_temp_new(); 178 179 tcg_gen_mulu2_tl(rl, rh, arg1, arg2); 180 /* fix up for one negative */ 181 tcg_gen_sari_tl(rl, arg1, TARGET_LONG_BITS - 1); 182 tcg_gen_and_tl(rl, rl, arg2); 183 tcg_gen_sub_tl(ret, rh, rl); 184 185 tcg_temp_free(rl); 186 tcg_temp_free(rh); 187 } 188 189 static void gen_fsgnj(DisasContext *ctx, uint32_t rd, uint32_t rs1, 190 uint32_t rs2, int rm, uint64_t min) 191 { 192 switch (rm) { 193 case 0: /* fsgnj */ 194 if (rs1 == rs2) { /* FMOV */ 195 tcg_gen_mov_i64(cpu_fpr[rd], cpu_fpr[rs1]); 196 } else { 197 tcg_gen_deposit_i64(cpu_fpr[rd], cpu_fpr[rs2], cpu_fpr[rs1], 198 0, min == INT32_MIN ? 31 : 63); 199 } 200 break; 201 case 1: /* fsgnjn */ 202 if (rs1 == rs2) { /* FNEG */ 203 tcg_gen_xori_i64(cpu_fpr[rd], cpu_fpr[rs1], min); 204 } else { 205 TCGv_i64 t0 = tcg_temp_new_i64(); 206 tcg_gen_not_i64(t0, cpu_fpr[rs2]); 207 tcg_gen_deposit_i64(cpu_fpr[rd], t0, cpu_fpr[rs1], 208 0, min == INT32_MIN ? 31 : 63); 209 tcg_temp_free_i64(t0); 210 } 211 break; 212 case 2: /* fsgnjx */ 213 if (rs1 == rs2) { /* FABS */ 214 tcg_gen_andi_i64(cpu_fpr[rd], cpu_fpr[rs1], ~min); 215 } else { 216 TCGv_i64 t0 = tcg_temp_new_i64(); 217 tcg_gen_andi_i64(t0, cpu_fpr[rs2], min); 218 tcg_gen_xor_i64(cpu_fpr[rd], cpu_fpr[rs1], t0); 219 tcg_temp_free_i64(t0); 220 } 221 break; 222 default: 223 gen_exception_illegal(ctx); 224 } 225 } 226 227 static void gen_arith(DisasContext *ctx, uint32_t opc, int rd, int rs1, 228 int rs2) 229 { 230 TCGv source1, source2, cond1, cond2, zeroreg, resultopt1; 231 source1 = tcg_temp_new(); 232 source2 = tcg_temp_new(); 233 gen_get_gpr(source1, rs1); 234 gen_get_gpr(source2, rs2); 235 236 switch (opc) { 237 CASE_OP_32_64(OPC_RISC_ADD): 238 tcg_gen_add_tl(source1, source1, source2); 239 break; 240 CASE_OP_32_64(OPC_RISC_SUB): 241 tcg_gen_sub_tl(source1, source1, source2); 242 break; 243 #if defined(TARGET_RISCV64) 244 case OPC_RISC_SLLW: 245 tcg_gen_andi_tl(source2, source2, 0x1F); 246 tcg_gen_shl_tl(source1, source1, source2); 247 break; 248 #endif 249 case OPC_RISC_SLL: 250 tcg_gen_andi_tl(source2, source2, TARGET_LONG_BITS - 1); 251 tcg_gen_shl_tl(source1, source1, source2); 252 break; 253 case OPC_RISC_SLT: 254 tcg_gen_setcond_tl(TCG_COND_LT, source1, source1, source2); 255 break; 256 case OPC_RISC_SLTU: 257 tcg_gen_setcond_tl(TCG_COND_LTU, source1, source1, source2); 258 break; 259 case OPC_RISC_XOR: 260 tcg_gen_xor_tl(source1, source1, source2); 261 break; 262 #if defined(TARGET_RISCV64) 263 case OPC_RISC_SRLW: 264 /* clear upper 32 */ 265 tcg_gen_ext32u_tl(source1, source1); 266 tcg_gen_andi_tl(source2, source2, 0x1F); 267 tcg_gen_shr_tl(source1, source1, source2); 268 break; 269 #endif 270 case OPC_RISC_SRL: 271 tcg_gen_andi_tl(source2, source2, TARGET_LONG_BITS - 1); 272 tcg_gen_shr_tl(source1, source1, source2); 273 break; 274 #if defined(TARGET_RISCV64) 275 case OPC_RISC_SRAW: 276 /* first, trick to get it to act like working on 32 bits (get rid of 277 upper 32, sign extend to fill space) */ 278 tcg_gen_ext32s_tl(source1, source1); 279 tcg_gen_andi_tl(source2, source2, 0x1F); 280 tcg_gen_sar_tl(source1, source1, source2); 281 break; 282 #endif 283 case OPC_RISC_SRA: 284 tcg_gen_andi_tl(source2, source2, TARGET_LONG_BITS - 1); 285 tcg_gen_sar_tl(source1, source1, source2); 286 break; 287 case OPC_RISC_OR: 288 tcg_gen_or_tl(source1, source1, source2); 289 break; 290 case OPC_RISC_AND: 291 tcg_gen_and_tl(source1, source1, source2); 292 break; 293 CASE_OP_32_64(OPC_RISC_MUL): 294 if (!has_ext(ctx, RVM)) { 295 goto do_illegal; 296 } 297 tcg_gen_mul_tl(source1, source1, source2); 298 break; 299 case OPC_RISC_MULH: 300 if (!has_ext(ctx, RVM)) { 301 goto do_illegal; 302 } 303 tcg_gen_muls2_tl(source2, source1, source1, source2); 304 break; 305 case OPC_RISC_MULHSU: 306 if (!has_ext(ctx, RVM)) { 307 goto do_illegal; 308 } 309 gen_mulhsu(source1, source1, source2); 310 break; 311 case OPC_RISC_MULHU: 312 if (!has_ext(ctx, RVM)) { 313 goto do_illegal; 314 } 315 tcg_gen_mulu2_tl(source2, source1, source1, source2); 316 break; 317 #if defined(TARGET_RISCV64) 318 case OPC_RISC_DIVW: 319 if (!has_ext(ctx, RVM)) { 320 goto do_illegal; 321 } 322 tcg_gen_ext32s_tl(source1, source1); 323 tcg_gen_ext32s_tl(source2, source2); 324 /* fall through to DIV */ 325 #endif 326 case OPC_RISC_DIV: 327 if (!has_ext(ctx, RVM)) { 328 goto do_illegal; 329 } 330 /* Handle by altering args to tcg_gen_div to produce req'd results: 331 * For overflow: want source1 in source1 and 1 in source2 332 * For div by zero: want -1 in source1 and 1 in source2 -> -1 result */ 333 cond1 = tcg_temp_new(); 334 cond2 = tcg_temp_new(); 335 zeroreg = tcg_const_tl(0); 336 resultopt1 = tcg_temp_new(); 337 338 tcg_gen_movi_tl(resultopt1, (target_ulong)-1); 339 tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, (target_ulong)(~0L)); 340 tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1, 341 ((target_ulong)1) << (TARGET_LONG_BITS - 1)); 342 tcg_gen_and_tl(cond1, cond1, cond2); /* cond1 = overflow */ 343 tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, 0); /* cond2 = div 0 */ 344 /* if div by zero, set source1 to -1, otherwise don't change */ 345 tcg_gen_movcond_tl(TCG_COND_EQ, source1, cond2, zeroreg, source1, 346 resultopt1); 347 /* if overflow or div by zero, set source2 to 1, else don't change */ 348 tcg_gen_or_tl(cond1, cond1, cond2); 349 tcg_gen_movi_tl(resultopt1, (target_ulong)1); 350 tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, 351 resultopt1); 352 tcg_gen_div_tl(source1, source1, source2); 353 354 tcg_temp_free(cond1); 355 tcg_temp_free(cond2); 356 tcg_temp_free(zeroreg); 357 tcg_temp_free(resultopt1); 358 break; 359 #if defined(TARGET_RISCV64) 360 case OPC_RISC_DIVUW: 361 if (!has_ext(ctx, RVM)) { 362 goto do_illegal; 363 } 364 tcg_gen_ext32u_tl(source1, source1); 365 tcg_gen_ext32u_tl(source2, source2); 366 /* fall through to DIVU */ 367 #endif 368 case OPC_RISC_DIVU: 369 if (!has_ext(ctx, RVM)) { 370 goto do_illegal; 371 } 372 cond1 = tcg_temp_new(); 373 zeroreg = tcg_const_tl(0); 374 resultopt1 = tcg_temp_new(); 375 376 tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); 377 tcg_gen_movi_tl(resultopt1, (target_ulong)-1); 378 tcg_gen_movcond_tl(TCG_COND_EQ, source1, cond1, zeroreg, source1, 379 resultopt1); 380 tcg_gen_movi_tl(resultopt1, (target_ulong)1); 381 tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, 382 resultopt1); 383 tcg_gen_divu_tl(source1, source1, source2); 384 385 tcg_temp_free(cond1); 386 tcg_temp_free(zeroreg); 387 tcg_temp_free(resultopt1); 388 break; 389 #if defined(TARGET_RISCV64) 390 case OPC_RISC_REMW: 391 if (!has_ext(ctx, RVM)) { 392 goto do_illegal; 393 } 394 tcg_gen_ext32s_tl(source1, source1); 395 tcg_gen_ext32s_tl(source2, source2); 396 /* fall through to REM */ 397 #endif 398 case OPC_RISC_REM: 399 if (!has_ext(ctx, RVM)) { 400 goto do_illegal; 401 } 402 cond1 = tcg_temp_new(); 403 cond2 = tcg_temp_new(); 404 zeroreg = tcg_const_tl(0); 405 resultopt1 = tcg_temp_new(); 406 407 tcg_gen_movi_tl(resultopt1, 1L); 408 tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, (target_ulong)-1); 409 tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1, 410 (target_ulong)1 << (TARGET_LONG_BITS - 1)); 411 tcg_gen_and_tl(cond2, cond1, cond2); /* cond1 = overflow */ 412 tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); /* cond2 = div 0 */ 413 /* if overflow or div by zero, set source2 to 1, else don't change */ 414 tcg_gen_or_tl(cond2, cond1, cond2); 415 tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond2, zeroreg, source2, 416 resultopt1); 417 tcg_gen_rem_tl(resultopt1, source1, source2); 418 /* if div by zero, just return the original dividend */ 419 tcg_gen_movcond_tl(TCG_COND_EQ, source1, cond1, zeroreg, resultopt1, 420 source1); 421 422 tcg_temp_free(cond1); 423 tcg_temp_free(cond2); 424 tcg_temp_free(zeroreg); 425 tcg_temp_free(resultopt1); 426 break; 427 #if defined(TARGET_RISCV64) 428 case OPC_RISC_REMUW: 429 if (!has_ext(ctx, RVM)) { 430 goto do_illegal; 431 } 432 tcg_gen_ext32u_tl(source1, source1); 433 tcg_gen_ext32u_tl(source2, source2); 434 /* fall through to REMU */ 435 #endif 436 case OPC_RISC_REMU: 437 if (!has_ext(ctx, RVM)) { 438 goto do_illegal; 439 } 440 cond1 = tcg_temp_new(); 441 zeroreg = tcg_const_tl(0); 442 resultopt1 = tcg_temp_new(); 443 444 tcg_gen_movi_tl(resultopt1, (target_ulong)1); 445 tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); 446 tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, 447 resultopt1); 448 tcg_gen_remu_tl(resultopt1, source1, source2); 449 /* if div by zero, just return the original dividend */ 450 tcg_gen_movcond_tl(TCG_COND_EQ, source1, cond1, zeroreg, resultopt1, 451 source1); 452 453 tcg_temp_free(cond1); 454 tcg_temp_free(zeroreg); 455 tcg_temp_free(resultopt1); 456 break; 457 do_illegal: 458 default: 459 gen_exception_illegal(ctx); 460 return; 461 } 462 463 if (opc & 0x8) { /* sign extend for W instructions */ 464 tcg_gen_ext32s_tl(source1, source1); 465 } 466 467 gen_set_gpr(rd, source1); 468 tcg_temp_free(source1); 469 tcg_temp_free(source2); 470 } 471 472 static void gen_arith_imm(DisasContext *ctx, uint32_t opc, int rd, 473 int rs1, target_long imm) 474 { 475 TCGv source1 = tcg_temp_new(); 476 int shift_len = TARGET_LONG_BITS; 477 int shift_a; 478 479 gen_get_gpr(source1, rs1); 480 481 switch (opc) { 482 case OPC_RISC_ADDI: 483 #if defined(TARGET_RISCV64) 484 case OPC_RISC_ADDIW: 485 #endif 486 tcg_gen_addi_tl(source1, source1, imm); 487 break; 488 case OPC_RISC_SLTI: 489 tcg_gen_setcondi_tl(TCG_COND_LT, source1, source1, imm); 490 break; 491 case OPC_RISC_SLTIU: 492 tcg_gen_setcondi_tl(TCG_COND_LTU, source1, source1, imm); 493 break; 494 case OPC_RISC_XORI: 495 tcg_gen_xori_tl(source1, source1, imm); 496 break; 497 case OPC_RISC_ORI: 498 tcg_gen_ori_tl(source1, source1, imm); 499 break; 500 case OPC_RISC_ANDI: 501 tcg_gen_andi_tl(source1, source1, imm); 502 break; 503 #if defined(TARGET_RISCV64) 504 case OPC_RISC_SLLIW: 505 shift_len = 32; 506 /* FALLTHRU */ 507 #endif 508 case OPC_RISC_SLLI: 509 if (imm >= shift_len) { 510 goto do_illegal; 511 } 512 tcg_gen_shli_tl(source1, source1, imm); 513 break; 514 #if defined(TARGET_RISCV64) 515 case OPC_RISC_SHIFT_RIGHT_IW: 516 shift_len = 32; 517 /* FALLTHRU */ 518 #endif 519 case OPC_RISC_SHIFT_RIGHT_I: 520 /* differentiate on IMM */ 521 shift_a = imm & 0x400; 522 imm &= 0x3ff; 523 if (imm >= shift_len) { 524 goto do_illegal; 525 } 526 if (imm != 0) { 527 if (shift_a) { 528 /* SRAI[W] */ 529 tcg_gen_sextract_tl(source1, source1, imm, shift_len - imm); 530 } else { 531 /* SRLI[W] */ 532 tcg_gen_extract_tl(source1, source1, imm, shift_len - imm); 533 } 534 /* No further sign-extension needed for W instructions. */ 535 opc &= ~0x8; 536 } 537 break; 538 default: 539 do_illegal: 540 gen_exception_illegal(ctx); 541 return; 542 } 543 544 if (opc & 0x8) { /* sign-extend for W instructions */ 545 tcg_gen_ext32s_tl(source1, source1); 546 } 547 548 gen_set_gpr(rd, source1); 549 tcg_temp_free(source1); 550 } 551 552 static void gen_jal(DisasContext *ctx, int rd, target_ulong imm) 553 { 554 target_ulong next_pc; 555 556 /* check misaligned: */ 557 next_pc = ctx->base.pc_next + imm; 558 if (!has_ext(ctx, RVC)) { 559 if ((next_pc & 0x3) != 0) { 560 gen_exception_inst_addr_mis(ctx); 561 return; 562 } 563 } 564 if (rd != 0) { 565 tcg_gen_movi_tl(cpu_gpr[rd], ctx->pc_succ_insn); 566 } 567 568 gen_goto_tb(ctx, 0, ctx->base.pc_next + imm); /* must use this for safety */ 569 ctx->base.is_jmp = DISAS_NORETURN; 570 } 571 572 static void gen_jalr(DisasContext *ctx, uint32_t opc, int rd, int rs1, 573 target_long imm) 574 { 575 /* no chaining with JALR */ 576 TCGLabel *misaligned = NULL; 577 TCGv t0 = tcg_temp_new(); 578 579 switch (opc) { 580 case OPC_RISC_JALR: 581 gen_get_gpr(cpu_pc, rs1); 582 tcg_gen_addi_tl(cpu_pc, cpu_pc, imm); 583 tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2); 584 585 if (!has_ext(ctx, RVC)) { 586 misaligned = gen_new_label(); 587 tcg_gen_andi_tl(t0, cpu_pc, 0x2); 588 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned); 589 } 590 591 if (rd != 0) { 592 tcg_gen_movi_tl(cpu_gpr[rd], ctx->pc_succ_insn); 593 } 594 tcg_gen_lookup_and_goto_ptr(); 595 596 if (misaligned) { 597 gen_set_label(misaligned); 598 gen_exception_inst_addr_mis(ctx); 599 } 600 ctx->base.is_jmp = DISAS_NORETURN; 601 break; 602 603 default: 604 gen_exception_illegal(ctx); 605 break; 606 } 607 tcg_temp_free(t0); 608 } 609 610 static void gen_branch(DisasContext *ctx, uint32_t opc, int rs1, int rs2, 611 target_long bimm) 612 { 613 TCGLabel *l = gen_new_label(); 614 TCGv source1, source2; 615 source1 = tcg_temp_new(); 616 source2 = tcg_temp_new(); 617 gen_get_gpr(source1, rs1); 618 gen_get_gpr(source2, rs2); 619 620 switch (opc) { 621 case OPC_RISC_BEQ: 622 tcg_gen_brcond_tl(TCG_COND_EQ, source1, source2, l); 623 break; 624 case OPC_RISC_BNE: 625 tcg_gen_brcond_tl(TCG_COND_NE, source1, source2, l); 626 break; 627 case OPC_RISC_BLT: 628 tcg_gen_brcond_tl(TCG_COND_LT, source1, source2, l); 629 break; 630 case OPC_RISC_BGE: 631 tcg_gen_brcond_tl(TCG_COND_GE, source1, source2, l); 632 break; 633 case OPC_RISC_BLTU: 634 tcg_gen_brcond_tl(TCG_COND_LTU, source1, source2, l); 635 break; 636 case OPC_RISC_BGEU: 637 tcg_gen_brcond_tl(TCG_COND_GEU, source1, source2, l); 638 break; 639 default: 640 gen_exception_illegal(ctx); 641 return; 642 } 643 tcg_temp_free(source1); 644 tcg_temp_free(source2); 645 646 gen_goto_tb(ctx, 1, ctx->pc_succ_insn); 647 gen_set_label(l); /* branch taken */ 648 if (!has_ext(ctx, RVC) && ((ctx->base.pc_next + bimm) & 0x3)) { 649 /* misaligned */ 650 gen_exception_inst_addr_mis(ctx); 651 } else { 652 gen_goto_tb(ctx, 0, ctx->base.pc_next + bimm); 653 } 654 ctx->base.is_jmp = DISAS_NORETURN; 655 } 656 657 static void gen_load(DisasContext *ctx, uint32_t opc, int rd, int rs1, 658 target_long imm) 659 { 660 TCGv t0 = tcg_temp_new(); 661 TCGv t1 = tcg_temp_new(); 662 gen_get_gpr(t0, rs1); 663 tcg_gen_addi_tl(t0, t0, imm); 664 int memop = tcg_memop_lookup[(opc >> 12) & 0x7]; 665 666 if (memop < 0) { 667 gen_exception_illegal(ctx); 668 return; 669 } 670 671 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, memop); 672 gen_set_gpr(rd, t1); 673 tcg_temp_free(t0); 674 tcg_temp_free(t1); 675 } 676 677 static void gen_store(DisasContext *ctx, uint32_t opc, int rs1, int rs2, 678 target_long imm) 679 { 680 TCGv t0 = tcg_temp_new(); 681 TCGv dat = tcg_temp_new(); 682 gen_get_gpr(t0, rs1); 683 tcg_gen_addi_tl(t0, t0, imm); 684 gen_get_gpr(dat, rs2); 685 int memop = tcg_memop_lookup[(opc >> 12) & 0x7]; 686 687 if (memop < 0) { 688 gen_exception_illegal(ctx); 689 return; 690 } 691 692 tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx, memop); 693 tcg_temp_free(t0); 694 tcg_temp_free(dat); 695 } 696 697 #ifndef CONFIG_USER_ONLY 698 /* The states of mstatus_fs are: 699 * 0 = disabled, 1 = initial, 2 = clean, 3 = dirty 700 * We will have already diagnosed disabled state, 701 * and need to turn initial/clean into dirty. 702 */ 703 static void mark_fs_dirty(DisasContext *ctx) 704 { 705 TCGv tmp; 706 if (ctx->mstatus_fs == MSTATUS_FS) { 707 return; 708 } 709 /* Remember the state change for the rest of the TB. */ 710 ctx->mstatus_fs = MSTATUS_FS; 711 712 tmp = tcg_temp_new(); 713 tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus)); 714 tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS); 715 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus)); 716 tcg_temp_free(tmp); 717 } 718 #else 719 static inline void mark_fs_dirty(DisasContext *ctx) { } 720 #endif 721 722 static void gen_fp_load(DisasContext *ctx, uint32_t opc, int rd, 723 int rs1, target_long imm) 724 { 725 TCGv t0; 726 727 if (ctx->mstatus_fs == 0) { 728 gen_exception_illegal(ctx); 729 return; 730 } 731 732 t0 = tcg_temp_new(); 733 gen_get_gpr(t0, rs1); 734 tcg_gen_addi_tl(t0, t0, imm); 735 736 switch (opc) { 737 case OPC_RISC_FLW: 738 if (!has_ext(ctx, RVF)) { 739 goto do_illegal; 740 } 741 tcg_gen_qemu_ld_i64(cpu_fpr[rd], t0, ctx->mem_idx, MO_TEUL); 742 /* RISC-V requires NaN-boxing of narrower width floating point values */ 743 tcg_gen_ori_i64(cpu_fpr[rd], cpu_fpr[rd], 0xffffffff00000000ULL); 744 break; 745 case OPC_RISC_FLD: 746 if (!has_ext(ctx, RVD)) { 747 goto do_illegal; 748 } 749 tcg_gen_qemu_ld_i64(cpu_fpr[rd], t0, ctx->mem_idx, MO_TEQ); 750 break; 751 do_illegal: 752 default: 753 gen_exception_illegal(ctx); 754 break; 755 } 756 tcg_temp_free(t0); 757 758 mark_fs_dirty(ctx); 759 } 760 761 static void gen_fp_store(DisasContext *ctx, uint32_t opc, int rs1, 762 int rs2, target_long imm) 763 { 764 TCGv t0; 765 766 if (ctx->mstatus_fs == 0) { 767 gen_exception_illegal(ctx); 768 return; 769 } 770 771 t0 = tcg_temp_new(); 772 gen_get_gpr(t0, rs1); 773 tcg_gen_addi_tl(t0, t0, imm); 774 775 switch (opc) { 776 case OPC_RISC_FSW: 777 if (!has_ext(ctx, RVF)) { 778 goto do_illegal; 779 } 780 tcg_gen_qemu_st_i64(cpu_fpr[rs2], t0, ctx->mem_idx, MO_TEUL); 781 break; 782 case OPC_RISC_FSD: 783 if (!has_ext(ctx, RVD)) { 784 goto do_illegal; 785 } 786 tcg_gen_qemu_st_i64(cpu_fpr[rs2], t0, ctx->mem_idx, MO_TEQ); 787 break; 788 do_illegal: 789 default: 790 gen_exception_illegal(ctx); 791 break; 792 } 793 794 tcg_temp_free(t0); 795 } 796 797 static void gen_atomic(DisasContext *ctx, uint32_t opc, 798 int rd, int rs1, int rs2) 799 { 800 TCGv src1, src2, dat; 801 TCGLabel *l1, *l2; 802 TCGMemOp mop; 803 bool aq, rl; 804 805 /* Extract the size of the atomic operation. */ 806 switch (extract32(opc, 12, 3)) { 807 case 2: /* 32-bit */ 808 mop = MO_ALIGN | MO_TESL; 809 break; 810 #if defined(TARGET_RISCV64) 811 case 3: /* 64-bit */ 812 mop = MO_ALIGN | MO_TEQ; 813 break; 814 #endif 815 default: 816 gen_exception_illegal(ctx); 817 return; 818 } 819 rl = extract32(opc, 25, 1); 820 aq = extract32(opc, 26, 1); 821 822 src1 = tcg_temp_new(); 823 src2 = tcg_temp_new(); 824 825 switch (MASK_OP_ATOMIC_NO_AQ_RL_SZ(opc)) { 826 case OPC_RISC_LR: 827 /* Put addr in load_res, data in load_val. */ 828 gen_get_gpr(src1, rs1); 829 if (rl) { 830 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL); 831 } 832 tcg_gen_qemu_ld_tl(load_val, src1, ctx->mem_idx, mop); 833 if (aq) { 834 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ); 835 } 836 tcg_gen_mov_tl(load_res, src1); 837 gen_set_gpr(rd, load_val); 838 break; 839 840 case OPC_RISC_SC: 841 l1 = gen_new_label(); 842 l2 = gen_new_label(); 843 dat = tcg_temp_new(); 844 845 gen_get_gpr(src1, rs1); 846 tcg_gen_brcond_tl(TCG_COND_NE, load_res, src1, l1); 847 848 gen_get_gpr(src2, rs2); 849 /* Note that the TCG atomic primitives are SC, 850 so we can ignore AQ/RL along this path. */ 851 tcg_gen_atomic_cmpxchg_tl(src1, load_res, load_val, src2, 852 ctx->mem_idx, mop); 853 tcg_gen_setcond_tl(TCG_COND_NE, dat, src1, load_val); 854 gen_set_gpr(rd, dat); 855 tcg_gen_br(l2); 856 857 gen_set_label(l1); 858 /* Address comparion failure. However, we still need to 859 provide the memory barrier implied by AQ/RL. */ 860 tcg_gen_mb(TCG_MO_ALL + aq * TCG_BAR_LDAQ + rl * TCG_BAR_STRL); 861 tcg_gen_movi_tl(dat, 1); 862 gen_set_gpr(rd, dat); 863 864 gen_set_label(l2); 865 tcg_temp_free(dat); 866 break; 867 868 case OPC_RISC_AMOSWAP: 869 /* Note that the TCG atomic primitives are SC, 870 so we can ignore AQ/RL along this path. */ 871 gen_get_gpr(src1, rs1); 872 gen_get_gpr(src2, rs2); 873 tcg_gen_atomic_xchg_tl(src2, src1, src2, ctx->mem_idx, mop); 874 gen_set_gpr(rd, src2); 875 break; 876 case OPC_RISC_AMOADD: 877 gen_get_gpr(src1, rs1); 878 gen_get_gpr(src2, rs2); 879 tcg_gen_atomic_fetch_add_tl(src2, src1, src2, ctx->mem_idx, mop); 880 gen_set_gpr(rd, src2); 881 break; 882 case OPC_RISC_AMOXOR: 883 gen_get_gpr(src1, rs1); 884 gen_get_gpr(src2, rs2); 885 tcg_gen_atomic_fetch_xor_tl(src2, src1, src2, ctx->mem_idx, mop); 886 gen_set_gpr(rd, src2); 887 break; 888 case OPC_RISC_AMOAND: 889 gen_get_gpr(src1, rs1); 890 gen_get_gpr(src2, rs2); 891 tcg_gen_atomic_fetch_and_tl(src2, src1, src2, ctx->mem_idx, mop); 892 gen_set_gpr(rd, src2); 893 break; 894 case OPC_RISC_AMOOR: 895 gen_get_gpr(src1, rs1); 896 gen_get_gpr(src2, rs2); 897 tcg_gen_atomic_fetch_or_tl(src2, src1, src2, ctx->mem_idx, mop); 898 gen_set_gpr(rd, src2); 899 break; 900 case OPC_RISC_AMOMIN: 901 gen_get_gpr(src1, rs1); 902 gen_get_gpr(src2, rs2); 903 tcg_gen_atomic_fetch_smin_tl(src2, src1, src2, ctx->mem_idx, mop); 904 gen_set_gpr(rd, src2); 905 break; 906 case OPC_RISC_AMOMAX: 907 gen_get_gpr(src1, rs1); 908 gen_get_gpr(src2, rs2); 909 tcg_gen_atomic_fetch_smax_tl(src2, src1, src2, ctx->mem_idx, mop); 910 gen_set_gpr(rd, src2); 911 break; 912 case OPC_RISC_AMOMINU: 913 gen_get_gpr(src1, rs1); 914 gen_get_gpr(src2, rs2); 915 tcg_gen_atomic_fetch_umin_tl(src2, src1, src2, ctx->mem_idx, mop); 916 gen_set_gpr(rd, src2); 917 break; 918 case OPC_RISC_AMOMAXU: 919 gen_get_gpr(src1, rs1); 920 gen_get_gpr(src2, rs2); 921 tcg_gen_atomic_fetch_umax_tl(src2, src1, src2, ctx->mem_idx, mop); 922 gen_set_gpr(rd, src2); 923 break; 924 925 default: 926 gen_exception_illegal(ctx); 927 break; 928 } 929 930 tcg_temp_free(src1); 931 tcg_temp_free(src2); 932 } 933 934 static void gen_set_rm(DisasContext *ctx, int rm) 935 { 936 TCGv_i32 t0; 937 938 if (ctx->frm == rm) { 939 return; 940 } 941 ctx->frm = rm; 942 t0 = tcg_const_i32(rm); 943 gen_helper_set_rounding_mode(cpu_env, t0); 944 tcg_temp_free_i32(t0); 945 } 946 947 static void gen_fp_fmadd(DisasContext *ctx, uint32_t opc, int rd, 948 int rs1, int rs2, int rs3, int rm) 949 { 950 switch (opc) { 951 case OPC_RISC_FMADD_S: 952 if (!has_ext(ctx, RVF)) { 953 goto do_illegal; 954 } 955 gen_set_rm(ctx, rm); 956 gen_helper_fmadd_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], 957 cpu_fpr[rs2], cpu_fpr[rs3]); 958 break; 959 case OPC_RISC_FMADD_D: 960 if (!has_ext(ctx, RVD)) { 961 goto do_illegal; 962 } 963 gen_set_rm(ctx, rm); 964 gen_helper_fmadd_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], 965 cpu_fpr[rs2], cpu_fpr[rs3]); 966 break; 967 do_illegal: 968 default: 969 gen_exception_illegal(ctx); 970 break; 971 } 972 } 973 974 static void gen_fp_fmsub(DisasContext *ctx, uint32_t opc, int rd, 975 int rs1, int rs2, int rs3, int rm) 976 { 977 switch (opc) { 978 case OPC_RISC_FMSUB_S: 979 if (!has_ext(ctx, RVF)) { 980 goto do_illegal; 981 } 982 gen_set_rm(ctx, rm); 983 gen_helper_fmsub_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], 984 cpu_fpr[rs2], cpu_fpr[rs3]); 985 break; 986 case OPC_RISC_FMSUB_D: 987 if (!has_ext(ctx, RVD)) { 988 goto do_illegal; 989 } 990 gen_set_rm(ctx, rm); 991 gen_helper_fmsub_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], 992 cpu_fpr[rs2], cpu_fpr[rs3]); 993 break; 994 do_illegal: 995 default: 996 gen_exception_illegal(ctx); 997 break; 998 } 999 } 1000 1001 static void gen_fp_fnmsub(DisasContext *ctx, uint32_t opc, int rd, 1002 int rs1, int rs2, int rs3, int rm) 1003 { 1004 switch (opc) { 1005 case OPC_RISC_FNMSUB_S: 1006 if (!has_ext(ctx, RVF)) { 1007 goto do_illegal; 1008 } 1009 gen_set_rm(ctx, rm); 1010 gen_helper_fnmsub_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], 1011 cpu_fpr[rs2], cpu_fpr[rs3]); 1012 break; 1013 case OPC_RISC_FNMSUB_D: 1014 if (!has_ext(ctx, RVD)) { 1015 goto do_illegal; 1016 } 1017 gen_set_rm(ctx, rm); 1018 gen_helper_fnmsub_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], 1019 cpu_fpr[rs2], cpu_fpr[rs3]); 1020 break; 1021 do_illegal: 1022 default: 1023 gen_exception_illegal(ctx); 1024 break; 1025 } 1026 } 1027 1028 static void gen_fp_fnmadd(DisasContext *ctx, uint32_t opc, int rd, 1029 int rs1, int rs2, int rs3, int rm) 1030 { 1031 switch (opc) { 1032 case OPC_RISC_FNMADD_S: 1033 if (!has_ext(ctx, RVF)) { 1034 goto do_illegal; 1035 } 1036 gen_set_rm(ctx, rm); 1037 gen_helper_fnmadd_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], 1038 cpu_fpr[rs2], cpu_fpr[rs3]); 1039 break; 1040 case OPC_RISC_FNMADD_D: 1041 if (!has_ext(ctx, RVD)) { 1042 goto do_illegal; 1043 } 1044 gen_set_rm(ctx, rm); 1045 gen_helper_fnmadd_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], 1046 cpu_fpr[rs2], cpu_fpr[rs3]); 1047 break; 1048 do_illegal: 1049 default: 1050 gen_exception_illegal(ctx); 1051 break; 1052 } 1053 } 1054 1055 static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd, 1056 int rs1, int rs2, int rm) 1057 { 1058 TCGv t0 = NULL; 1059 bool fp_output = true; 1060 1061 if (ctx->mstatus_fs == 0) { 1062 goto do_illegal; 1063 } 1064 1065 switch (opc) { 1066 case OPC_RISC_FADD_S: 1067 if (!has_ext(ctx, RVF)) { 1068 goto do_illegal; 1069 } 1070 gen_set_rm(ctx, rm); 1071 gen_helper_fadd_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1072 break; 1073 case OPC_RISC_FSUB_S: 1074 if (!has_ext(ctx, RVF)) { 1075 goto do_illegal; 1076 } 1077 gen_set_rm(ctx, rm); 1078 gen_helper_fsub_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1079 break; 1080 case OPC_RISC_FMUL_S: 1081 if (!has_ext(ctx, RVF)) { 1082 goto do_illegal; 1083 } 1084 gen_set_rm(ctx, rm); 1085 gen_helper_fmul_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1086 break; 1087 case OPC_RISC_FDIV_S: 1088 if (!has_ext(ctx, RVF)) { 1089 goto do_illegal; 1090 } 1091 gen_set_rm(ctx, rm); 1092 gen_helper_fdiv_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1093 break; 1094 case OPC_RISC_FSQRT_S: 1095 if (!has_ext(ctx, RVF)) { 1096 goto do_illegal; 1097 } 1098 gen_set_rm(ctx, rm); 1099 gen_helper_fsqrt_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1]); 1100 break; 1101 case OPC_RISC_FSGNJ_S: 1102 if (!has_ext(ctx, RVF)) { 1103 goto do_illegal; 1104 } 1105 gen_fsgnj(ctx, rd, rs1, rs2, rm, INT32_MIN); 1106 break; 1107 1108 case OPC_RISC_FMIN_S: 1109 if (!has_ext(ctx, RVF)) { 1110 goto do_illegal; 1111 } 1112 /* also handles: OPC_RISC_FMAX_S */ 1113 switch (rm) { 1114 case 0x0: 1115 gen_helper_fmin_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1116 break; 1117 case 0x1: 1118 gen_helper_fmax_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1119 break; 1120 default: 1121 goto do_illegal; 1122 } 1123 break; 1124 1125 case OPC_RISC_FEQ_S: 1126 /* also handles: OPC_RISC_FLT_S, OPC_RISC_FLE_S */ 1127 if (!has_ext(ctx, RVF)) { 1128 goto do_illegal; 1129 } 1130 t0 = tcg_temp_new(); 1131 switch (rm) { 1132 case 0x0: 1133 gen_helper_fle_s(t0, cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1134 break; 1135 case 0x1: 1136 gen_helper_flt_s(t0, cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1137 break; 1138 case 0x2: 1139 gen_helper_feq_s(t0, cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1140 break; 1141 default: 1142 goto do_illegal; 1143 } 1144 gen_set_gpr(rd, t0); 1145 tcg_temp_free(t0); 1146 fp_output = false; 1147 break; 1148 1149 case OPC_RISC_FCVT_W_S: 1150 /* also OPC_RISC_FCVT_WU_S, OPC_RISC_FCVT_L_S, OPC_RISC_FCVT_LU_S */ 1151 if (!has_ext(ctx, RVF)) { 1152 goto do_illegal; 1153 } 1154 t0 = tcg_temp_new(); 1155 switch (rs2) { 1156 case 0: /* FCVT_W_S */ 1157 gen_set_rm(ctx, rm); 1158 gen_helper_fcvt_w_s(t0, cpu_env, cpu_fpr[rs1]); 1159 break; 1160 case 1: /* FCVT_WU_S */ 1161 gen_set_rm(ctx, rm); 1162 gen_helper_fcvt_wu_s(t0, cpu_env, cpu_fpr[rs1]); 1163 break; 1164 #if defined(TARGET_RISCV64) 1165 case 2: /* FCVT_L_S */ 1166 gen_set_rm(ctx, rm); 1167 gen_helper_fcvt_l_s(t0, cpu_env, cpu_fpr[rs1]); 1168 break; 1169 case 3: /* FCVT_LU_S */ 1170 gen_set_rm(ctx, rm); 1171 gen_helper_fcvt_lu_s(t0, cpu_env, cpu_fpr[rs1]); 1172 break; 1173 #endif 1174 default: 1175 goto do_illegal; 1176 } 1177 gen_set_gpr(rd, t0); 1178 tcg_temp_free(t0); 1179 fp_output = false; 1180 break; 1181 1182 case OPC_RISC_FCVT_S_W: 1183 /* also OPC_RISC_FCVT_S_WU, OPC_RISC_FCVT_S_L, OPC_RISC_FCVT_S_LU */ 1184 if (!has_ext(ctx, RVF)) { 1185 goto do_illegal; 1186 } 1187 t0 = tcg_temp_new(); 1188 gen_get_gpr(t0, rs1); 1189 switch (rs2) { 1190 case 0: /* FCVT_S_W */ 1191 gen_set_rm(ctx, rm); 1192 gen_helper_fcvt_s_w(cpu_fpr[rd], cpu_env, t0); 1193 break; 1194 case 1: /* FCVT_S_WU */ 1195 gen_set_rm(ctx, rm); 1196 gen_helper_fcvt_s_wu(cpu_fpr[rd], cpu_env, t0); 1197 break; 1198 #if defined(TARGET_RISCV64) 1199 case 2: /* FCVT_S_L */ 1200 gen_set_rm(ctx, rm); 1201 gen_helper_fcvt_s_l(cpu_fpr[rd], cpu_env, t0); 1202 break; 1203 case 3: /* FCVT_S_LU */ 1204 gen_set_rm(ctx, rm); 1205 gen_helper_fcvt_s_lu(cpu_fpr[rd], cpu_env, t0); 1206 break; 1207 #endif 1208 default: 1209 goto do_illegal; 1210 } 1211 tcg_temp_free(t0); 1212 break; 1213 1214 case OPC_RISC_FMV_X_S: 1215 /* also OPC_RISC_FCLASS_S */ 1216 if (!has_ext(ctx, RVF)) { 1217 goto do_illegal; 1218 } 1219 t0 = tcg_temp_new(); 1220 switch (rm) { 1221 case 0: /* FMV */ 1222 #if defined(TARGET_RISCV64) 1223 tcg_gen_ext32s_tl(t0, cpu_fpr[rs1]); 1224 #else 1225 tcg_gen_extrl_i64_i32(t0, cpu_fpr[rs1]); 1226 #endif 1227 break; 1228 case 1: 1229 gen_helper_fclass_s(t0, cpu_fpr[rs1]); 1230 break; 1231 default: 1232 goto do_illegal; 1233 } 1234 gen_set_gpr(rd, t0); 1235 tcg_temp_free(t0); 1236 fp_output = false; 1237 break; 1238 1239 case OPC_RISC_FMV_S_X: 1240 if (!has_ext(ctx, RVF)) { 1241 goto do_illegal; 1242 } 1243 t0 = tcg_temp_new(); 1244 gen_get_gpr(t0, rs1); 1245 #if defined(TARGET_RISCV64) 1246 tcg_gen_mov_i64(cpu_fpr[rd], t0); 1247 #else 1248 tcg_gen_extu_i32_i64(cpu_fpr[rd], t0); 1249 #endif 1250 tcg_temp_free(t0); 1251 break; 1252 1253 /* double */ 1254 case OPC_RISC_FADD_D: 1255 if (!has_ext(ctx, RVD)) { 1256 goto do_illegal; 1257 } 1258 gen_set_rm(ctx, rm); 1259 gen_helper_fadd_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1260 break; 1261 case OPC_RISC_FSUB_D: 1262 if (!has_ext(ctx, RVD)) { 1263 goto do_illegal; 1264 } 1265 gen_set_rm(ctx, rm); 1266 gen_helper_fsub_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1267 break; 1268 case OPC_RISC_FMUL_D: 1269 if (!has_ext(ctx, RVD)) { 1270 goto do_illegal; 1271 } 1272 gen_set_rm(ctx, rm); 1273 gen_helper_fmul_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1274 break; 1275 case OPC_RISC_FDIV_D: 1276 if (!has_ext(ctx, RVD)) { 1277 goto do_illegal; 1278 } 1279 gen_set_rm(ctx, rm); 1280 gen_helper_fdiv_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1281 break; 1282 case OPC_RISC_FSQRT_D: 1283 if (!has_ext(ctx, RVD)) { 1284 goto do_illegal; 1285 } 1286 gen_set_rm(ctx, rm); 1287 gen_helper_fsqrt_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1]); 1288 break; 1289 case OPC_RISC_FSGNJ_D: 1290 gen_fsgnj(ctx, rd, rs1, rs2, rm, INT64_MIN); 1291 break; 1292 1293 case OPC_RISC_FMIN_D: 1294 /* also OPC_RISC_FMAX_D */ 1295 if (!has_ext(ctx, RVD)) { 1296 goto do_illegal; 1297 } 1298 switch (rm) { 1299 case 0: 1300 gen_helper_fmin_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1301 break; 1302 case 1: 1303 gen_helper_fmax_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1304 break; 1305 default: 1306 goto do_illegal; 1307 } 1308 break; 1309 1310 case OPC_RISC_FCVT_S_D: 1311 if (!has_ext(ctx, RVD)) { 1312 goto do_illegal; 1313 } 1314 switch (rs2) { 1315 case 1: 1316 gen_set_rm(ctx, rm); 1317 gen_helper_fcvt_s_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1]); 1318 break; 1319 default: 1320 goto do_illegal; 1321 } 1322 break; 1323 1324 case OPC_RISC_FCVT_D_S: 1325 if (!has_ext(ctx, RVD)) { 1326 goto do_illegal; 1327 } 1328 switch (rs2) { 1329 case 0: 1330 gen_set_rm(ctx, rm); 1331 gen_helper_fcvt_d_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1]); 1332 break; 1333 default: 1334 goto do_illegal; 1335 } 1336 break; 1337 1338 case OPC_RISC_FEQ_D: 1339 /* also OPC_RISC_FLT_D, OPC_RISC_FLE_D */ 1340 if (!has_ext(ctx, RVD)) { 1341 goto do_illegal; 1342 } 1343 t0 = tcg_temp_new(); 1344 switch (rm) { 1345 case 0: 1346 gen_helper_fle_d(t0, cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1347 break; 1348 case 1: 1349 gen_helper_flt_d(t0, cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1350 break; 1351 case 2: 1352 gen_helper_feq_d(t0, cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]); 1353 break; 1354 default: 1355 goto do_illegal; 1356 } 1357 gen_set_gpr(rd, t0); 1358 tcg_temp_free(t0); 1359 fp_output = false; 1360 break; 1361 1362 case OPC_RISC_FCVT_W_D: 1363 /* also OPC_RISC_FCVT_WU_D, OPC_RISC_FCVT_L_D, OPC_RISC_FCVT_LU_D */ 1364 if (!has_ext(ctx, RVD)) { 1365 goto do_illegal; 1366 } 1367 t0 = tcg_temp_new(); 1368 switch (rs2) { 1369 case 0: 1370 gen_set_rm(ctx, rm); 1371 gen_helper_fcvt_w_d(t0, cpu_env, cpu_fpr[rs1]); 1372 break; 1373 case 1: 1374 gen_set_rm(ctx, rm); 1375 gen_helper_fcvt_wu_d(t0, cpu_env, cpu_fpr[rs1]); 1376 break; 1377 #if defined(TARGET_RISCV64) 1378 case 2: 1379 gen_set_rm(ctx, rm); 1380 gen_helper_fcvt_l_d(t0, cpu_env, cpu_fpr[rs1]); 1381 break; 1382 case 3: 1383 gen_set_rm(ctx, rm); 1384 gen_helper_fcvt_lu_d(t0, cpu_env, cpu_fpr[rs1]); 1385 break; 1386 #endif 1387 default: 1388 goto do_illegal; 1389 } 1390 gen_set_gpr(rd, t0); 1391 tcg_temp_free(t0); 1392 fp_output = false; 1393 break; 1394 1395 case OPC_RISC_FCVT_D_W: 1396 /* also OPC_RISC_FCVT_D_WU, OPC_RISC_FCVT_D_L, OPC_RISC_FCVT_D_LU */ 1397 if (!has_ext(ctx, RVD)) { 1398 goto do_illegal; 1399 } 1400 t0 = tcg_temp_new(); 1401 gen_get_gpr(t0, rs1); 1402 switch (rs2) { 1403 case 0: 1404 gen_set_rm(ctx, rm); 1405 gen_helper_fcvt_d_w(cpu_fpr[rd], cpu_env, t0); 1406 break; 1407 case 1: 1408 gen_set_rm(ctx, rm); 1409 gen_helper_fcvt_d_wu(cpu_fpr[rd], cpu_env, t0); 1410 break; 1411 #if defined(TARGET_RISCV64) 1412 case 2: 1413 gen_set_rm(ctx, rm); 1414 gen_helper_fcvt_d_l(cpu_fpr[rd], cpu_env, t0); 1415 break; 1416 case 3: 1417 gen_set_rm(ctx, rm); 1418 gen_helper_fcvt_d_lu(cpu_fpr[rd], cpu_env, t0); 1419 break; 1420 #endif 1421 default: 1422 goto do_illegal; 1423 } 1424 tcg_temp_free(t0); 1425 break; 1426 1427 case OPC_RISC_FMV_X_D: 1428 /* also OPC_RISC_FCLASS_D */ 1429 if (!has_ext(ctx, RVD)) { 1430 goto do_illegal; 1431 } 1432 switch (rm) { 1433 #if defined(TARGET_RISCV64) 1434 case 0: /* FMV */ 1435 gen_set_gpr(rd, cpu_fpr[rs1]); 1436 break; 1437 #endif 1438 case 1: 1439 t0 = tcg_temp_new(); 1440 gen_helper_fclass_d(t0, cpu_fpr[rs1]); 1441 gen_set_gpr(rd, t0); 1442 tcg_temp_free(t0); 1443 break; 1444 default: 1445 goto do_illegal; 1446 } 1447 fp_output = false; 1448 break; 1449 1450 #if defined(TARGET_RISCV64) 1451 case OPC_RISC_FMV_D_X: 1452 if (!has_ext(ctx, RVD)) { 1453 goto do_illegal; 1454 } 1455 t0 = tcg_temp_new(); 1456 gen_get_gpr(t0, rs1); 1457 tcg_gen_mov_tl(cpu_fpr[rd], t0); 1458 tcg_temp_free(t0); 1459 break; 1460 #endif 1461 1462 default: 1463 do_illegal: 1464 if (t0) { 1465 tcg_temp_free(t0); 1466 } 1467 gen_exception_illegal(ctx); 1468 return; 1469 } 1470 1471 if (fp_output) { 1472 mark_fs_dirty(ctx); 1473 } 1474 } 1475 1476 static void gen_system(DisasContext *ctx, uint32_t opc, int rd, int rs1, 1477 int csr) 1478 { 1479 TCGv source1, csr_store, dest, rs1_pass, imm_rs1; 1480 source1 = tcg_temp_new(); 1481 csr_store = tcg_temp_new(); 1482 dest = tcg_temp_new(); 1483 rs1_pass = tcg_temp_new(); 1484 imm_rs1 = tcg_temp_new(); 1485 gen_get_gpr(source1, rs1); 1486 tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); 1487 tcg_gen_movi_tl(rs1_pass, rs1); 1488 tcg_gen_movi_tl(csr_store, csr); /* copy into temp reg to feed to helper */ 1489 1490 #ifndef CONFIG_USER_ONLY 1491 /* Extract funct7 value and check whether it matches SFENCE.VMA */ 1492 if ((opc == OPC_RISC_ECALL) && ((csr >> 5) == 9)) { 1493 if (ctx->priv_ver == PRIV_VERSION_1_10_0) { 1494 /* sfence.vma */ 1495 /* TODO: handle ASID specific fences */ 1496 gen_helper_tlb_flush(cpu_env); 1497 return; 1498 } else { 1499 gen_exception_illegal(ctx); 1500 } 1501 } 1502 #endif 1503 1504 switch (opc) { 1505 case OPC_RISC_ECALL: 1506 switch (csr) { 1507 case 0x0: /* ECALL */ 1508 /* always generates U-level ECALL, fixed in do_interrupt handler */ 1509 generate_exception(ctx, RISCV_EXCP_U_ECALL); 1510 tcg_gen_exit_tb(NULL, 0); /* no chaining */ 1511 ctx->base.is_jmp = DISAS_NORETURN; 1512 break; 1513 case 0x1: /* EBREAK */ 1514 generate_exception(ctx, RISCV_EXCP_BREAKPOINT); 1515 tcg_gen_exit_tb(NULL, 0); /* no chaining */ 1516 ctx->base.is_jmp = DISAS_NORETURN; 1517 break; 1518 #ifndef CONFIG_USER_ONLY 1519 case 0x002: /* URET */ 1520 gen_exception_illegal(ctx); 1521 break; 1522 case 0x102: /* SRET */ 1523 if (has_ext(ctx, RVS)) { 1524 gen_helper_sret(cpu_pc, cpu_env, cpu_pc); 1525 tcg_gen_exit_tb(NULL, 0); /* no chaining */ 1526 ctx->base.is_jmp = DISAS_NORETURN; 1527 } else { 1528 gen_exception_illegal(ctx); 1529 } 1530 break; 1531 case 0x202: /* HRET */ 1532 gen_exception_illegal(ctx); 1533 break; 1534 case 0x302: /* MRET */ 1535 gen_helper_mret(cpu_pc, cpu_env, cpu_pc); 1536 tcg_gen_exit_tb(NULL, 0); /* no chaining */ 1537 ctx->base.is_jmp = DISAS_NORETURN; 1538 break; 1539 case 0x7b2: /* DRET */ 1540 gen_exception_illegal(ctx); 1541 break; 1542 case 0x105: /* WFI */ 1543 tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); 1544 gen_helper_wfi(cpu_env); 1545 break; 1546 case 0x104: /* SFENCE.VM */ 1547 if (ctx->priv_ver <= PRIV_VERSION_1_09_1) { 1548 gen_helper_tlb_flush(cpu_env); 1549 } else { 1550 gen_exception_illegal(ctx); 1551 } 1552 break; 1553 #endif 1554 default: 1555 gen_exception_illegal(ctx); 1556 break; 1557 } 1558 break; 1559 default: 1560 tcg_gen_movi_tl(imm_rs1, rs1); 1561 gen_io_start(); 1562 switch (opc) { 1563 case OPC_RISC_CSRRW: 1564 gen_helper_csrrw(dest, cpu_env, source1, csr_store); 1565 break; 1566 case OPC_RISC_CSRRS: 1567 gen_helper_csrrs(dest, cpu_env, source1, csr_store, rs1_pass); 1568 break; 1569 case OPC_RISC_CSRRC: 1570 gen_helper_csrrc(dest, cpu_env, source1, csr_store, rs1_pass); 1571 break; 1572 case OPC_RISC_CSRRWI: 1573 gen_helper_csrrw(dest, cpu_env, imm_rs1, csr_store); 1574 break; 1575 case OPC_RISC_CSRRSI: 1576 gen_helper_csrrs(dest, cpu_env, imm_rs1, csr_store, rs1_pass); 1577 break; 1578 case OPC_RISC_CSRRCI: 1579 gen_helper_csrrc(dest, cpu_env, imm_rs1, csr_store, rs1_pass); 1580 break; 1581 default: 1582 gen_exception_illegal(ctx); 1583 return; 1584 } 1585 gen_io_end(); 1586 gen_set_gpr(rd, dest); 1587 /* end tb since we may be changing priv modes, to get mmu_index right */ 1588 tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); 1589 tcg_gen_exit_tb(NULL, 0); /* no chaining */ 1590 ctx->base.is_jmp = DISAS_NORETURN; 1591 break; 1592 } 1593 tcg_temp_free(source1); 1594 tcg_temp_free(csr_store); 1595 tcg_temp_free(dest); 1596 tcg_temp_free(rs1_pass); 1597 tcg_temp_free(imm_rs1); 1598 } 1599 1600 static void decode_RV32_64C0(DisasContext *ctx) 1601 { 1602 uint8_t funct3 = extract32(ctx->opcode, 13, 3); 1603 uint8_t rd_rs2 = GET_C_RS2S(ctx->opcode); 1604 uint8_t rs1s = GET_C_RS1S(ctx->opcode); 1605 1606 switch (funct3) { 1607 case 0: 1608 /* illegal */ 1609 if (ctx->opcode == 0) { 1610 gen_exception_illegal(ctx); 1611 } else { 1612 /* C.ADDI4SPN -> addi rd', x2, zimm[9:2]*/ 1613 gen_arith_imm(ctx, OPC_RISC_ADDI, rd_rs2, 2, 1614 GET_C_ADDI4SPN_IMM(ctx->opcode)); 1615 } 1616 break; 1617 case 1: 1618 /* C.FLD -> fld rd', offset[7:3](rs1')*/ 1619 gen_fp_load(ctx, OPC_RISC_FLD, rd_rs2, rs1s, 1620 GET_C_LD_IMM(ctx->opcode)); 1621 /* C.LQ(RV128) */ 1622 break; 1623 case 2: 1624 /* C.LW -> lw rd', offset[6:2](rs1') */ 1625 gen_load(ctx, OPC_RISC_LW, rd_rs2, rs1s, 1626 GET_C_LW_IMM(ctx->opcode)); 1627 break; 1628 case 3: 1629 #if defined(TARGET_RISCV64) 1630 /* C.LD(RV64/128) -> ld rd', offset[7:3](rs1')*/ 1631 gen_load(ctx, OPC_RISC_LD, rd_rs2, rs1s, 1632 GET_C_LD_IMM(ctx->opcode)); 1633 #else 1634 /* C.FLW (RV32) -> flw rd', offset[6:2](rs1')*/ 1635 gen_fp_load(ctx, OPC_RISC_FLW, rd_rs2, rs1s, 1636 GET_C_LW_IMM(ctx->opcode)); 1637 #endif 1638 break; 1639 case 4: 1640 /* reserved */ 1641 gen_exception_illegal(ctx); 1642 break; 1643 case 5: 1644 /* C.FSD(RV32/64) -> fsd rs2', offset[7:3](rs1') */ 1645 gen_fp_store(ctx, OPC_RISC_FSD, rs1s, rd_rs2, 1646 GET_C_LD_IMM(ctx->opcode)); 1647 /* C.SQ (RV128) */ 1648 break; 1649 case 6: 1650 /* C.SW -> sw rs2', offset[6:2](rs1')*/ 1651 gen_store(ctx, OPC_RISC_SW, rs1s, rd_rs2, 1652 GET_C_LW_IMM(ctx->opcode)); 1653 break; 1654 case 7: 1655 #if defined(TARGET_RISCV64) 1656 /* C.SD (RV64/128) -> sd rs2', offset[7:3](rs1')*/ 1657 gen_store(ctx, OPC_RISC_SD, rs1s, rd_rs2, 1658 GET_C_LD_IMM(ctx->opcode)); 1659 #else 1660 /* C.FSW (RV32) -> fsw rs2', offset[6:2](rs1')*/ 1661 gen_fp_store(ctx, OPC_RISC_FSW, rs1s, rd_rs2, 1662 GET_C_LW_IMM(ctx->opcode)); 1663 #endif 1664 break; 1665 } 1666 } 1667 1668 static void decode_RV32_64C1(DisasContext *ctx) 1669 { 1670 uint8_t funct3 = extract32(ctx->opcode, 13, 3); 1671 uint8_t rd_rs1 = GET_C_RS1(ctx->opcode); 1672 uint8_t rs1s, rs2s; 1673 uint8_t funct2; 1674 1675 switch (funct3) { 1676 case 0: 1677 /* C.ADDI -> addi rd, rd, nzimm[5:0] */ 1678 gen_arith_imm(ctx, OPC_RISC_ADDI, rd_rs1, rd_rs1, 1679 GET_C_IMM(ctx->opcode)); 1680 break; 1681 case 1: 1682 #if defined(TARGET_RISCV64) 1683 /* C.ADDIW (RV64/128) -> addiw rd, rd, imm[5:0]*/ 1684 gen_arith_imm(ctx, OPC_RISC_ADDIW, rd_rs1, rd_rs1, 1685 GET_C_IMM(ctx->opcode)); 1686 #else 1687 /* C.JAL(RV32) -> jal x1, offset[11:1] */ 1688 gen_jal(ctx, 1, GET_C_J_IMM(ctx->opcode)); 1689 #endif 1690 break; 1691 case 2: 1692 /* C.LI -> addi rd, x0, imm[5:0]*/ 1693 gen_arith_imm(ctx, OPC_RISC_ADDI, rd_rs1, 0, GET_C_IMM(ctx->opcode)); 1694 break; 1695 case 3: 1696 if (rd_rs1 == 2) { 1697 /* C.ADDI16SP -> addi x2, x2, nzimm[9:4]*/ 1698 gen_arith_imm(ctx, OPC_RISC_ADDI, 2, 2, 1699 GET_C_ADDI16SP_IMM(ctx->opcode)); 1700 } else if (rd_rs1 != 0) { 1701 /* C.LUI (rs1/rd =/= {0,2}) -> lui rd, nzimm[17:12]*/ 1702 tcg_gen_movi_tl(cpu_gpr[rd_rs1], 1703 GET_C_IMM(ctx->opcode) << 12); 1704 } 1705 break; 1706 case 4: 1707 funct2 = extract32(ctx->opcode, 10, 2); 1708 rs1s = GET_C_RS1S(ctx->opcode); 1709 switch (funct2) { 1710 case 0: /* C.SRLI(RV32) -> srli rd', rd', shamt[5:0] */ 1711 gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_I, rs1s, rs1s, 1712 GET_C_ZIMM(ctx->opcode)); 1713 /* C.SRLI64(RV128) */ 1714 break; 1715 case 1: 1716 /* C.SRAI -> srai rd', rd', shamt[5:0]*/ 1717 gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_I, rs1s, rs1s, 1718 GET_C_ZIMM(ctx->opcode) | 0x400); 1719 /* C.SRAI64(RV128) */ 1720 break; 1721 case 2: 1722 /* C.ANDI -> andi rd', rd', imm[5:0]*/ 1723 gen_arith_imm(ctx, OPC_RISC_ANDI, rs1s, rs1s, 1724 GET_C_IMM(ctx->opcode)); 1725 break; 1726 case 3: 1727 funct2 = extract32(ctx->opcode, 5, 2); 1728 rs2s = GET_C_RS2S(ctx->opcode); 1729 switch (funct2) { 1730 case 0: 1731 /* C.SUB -> sub rd', rd', rs2' */ 1732 if (extract32(ctx->opcode, 12, 1) == 0) { 1733 gen_arith(ctx, OPC_RISC_SUB, rs1s, rs1s, rs2s); 1734 } 1735 #if defined(TARGET_RISCV64) 1736 else { 1737 gen_arith(ctx, OPC_RISC_SUBW, rs1s, rs1s, rs2s); 1738 } 1739 #endif 1740 break; 1741 case 1: 1742 /* C.XOR -> xor rs1', rs1', rs2' */ 1743 if (extract32(ctx->opcode, 12, 1) == 0) { 1744 gen_arith(ctx, OPC_RISC_XOR, rs1s, rs1s, rs2s); 1745 } 1746 #if defined(TARGET_RISCV64) 1747 else { 1748 /* C.ADDW (RV64/128) */ 1749 gen_arith(ctx, OPC_RISC_ADDW, rs1s, rs1s, rs2s); 1750 } 1751 #endif 1752 break; 1753 case 2: 1754 /* C.OR -> or rs1', rs1', rs2' */ 1755 gen_arith(ctx, OPC_RISC_OR, rs1s, rs1s, rs2s); 1756 break; 1757 case 3: 1758 /* C.AND -> and rs1', rs1', rs2' */ 1759 gen_arith(ctx, OPC_RISC_AND, rs1s, rs1s, rs2s); 1760 break; 1761 } 1762 break; 1763 } 1764 break; 1765 case 5: 1766 /* C.J -> jal x0, offset[11:1]*/ 1767 gen_jal(ctx, 0, GET_C_J_IMM(ctx->opcode)); 1768 break; 1769 case 6: 1770 /* C.BEQZ -> beq rs1', x0, offset[8:1]*/ 1771 rs1s = GET_C_RS1S(ctx->opcode); 1772 gen_branch(ctx, OPC_RISC_BEQ, rs1s, 0, GET_C_B_IMM(ctx->opcode)); 1773 break; 1774 case 7: 1775 /* C.BNEZ -> bne rs1', x0, offset[8:1]*/ 1776 rs1s = GET_C_RS1S(ctx->opcode); 1777 gen_branch(ctx, OPC_RISC_BNE, rs1s, 0, GET_C_B_IMM(ctx->opcode)); 1778 break; 1779 } 1780 } 1781 1782 static void decode_RV32_64C2(DisasContext *ctx) 1783 { 1784 uint8_t rd, rs2; 1785 uint8_t funct3 = extract32(ctx->opcode, 13, 3); 1786 1787 1788 rd = GET_RD(ctx->opcode); 1789 1790 switch (funct3) { 1791 case 0: /* C.SLLI -> slli rd, rd, shamt[5:0] 1792 C.SLLI64 -> */ 1793 gen_arith_imm(ctx, OPC_RISC_SLLI, rd, rd, GET_C_ZIMM(ctx->opcode)); 1794 break; 1795 case 1: /* C.FLDSP(RV32/64DC) -> fld rd, offset[8:3](x2) */ 1796 gen_fp_load(ctx, OPC_RISC_FLD, rd, 2, GET_C_LDSP_IMM(ctx->opcode)); 1797 break; 1798 case 2: /* C.LWSP -> lw rd, offset[7:2](x2) */ 1799 gen_load(ctx, OPC_RISC_LW, rd, 2, GET_C_LWSP_IMM(ctx->opcode)); 1800 break; 1801 case 3: 1802 #if defined(TARGET_RISCV64) 1803 /* C.LDSP(RVC64) -> ld rd, offset[8:3](x2) */ 1804 gen_load(ctx, OPC_RISC_LD, rd, 2, GET_C_LDSP_IMM(ctx->opcode)); 1805 #else 1806 /* C.FLWSP(RV32FC) -> flw rd, offset[7:2](x2) */ 1807 gen_fp_load(ctx, OPC_RISC_FLW, rd, 2, GET_C_LWSP_IMM(ctx->opcode)); 1808 #endif 1809 break; 1810 case 4: 1811 rs2 = GET_C_RS2(ctx->opcode); 1812 1813 if (extract32(ctx->opcode, 12, 1) == 0) { 1814 if (rs2 == 0) { 1815 /* C.JR -> jalr x0, rs1, 0*/ 1816 gen_jalr(ctx, OPC_RISC_JALR, 0, rd, 0); 1817 } else { 1818 /* C.MV -> add rd, x0, rs2 */ 1819 gen_arith(ctx, OPC_RISC_ADD, rd, 0, rs2); 1820 } 1821 } else { 1822 if (rd == 0) { 1823 /* C.EBREAK -> ebreak*/ 1824 gen_system(ctx, OPC_RISC_ECALL, 0, 0, 0x1); 1825 } else { 1826 if (rs2 == 0) { 1827 /* C.JALR -> jalr x1, rs1, 0*/ 1828 gen_jalr(ctx, OPC_RISC_JALR, 1, rd, 0); 1829 } else { 1830 /* C.ADD -> add rd, rd, rs2 */ 1831 gen_arith(ctx, OPC_RISC_ADD, rd, rd, rs2); 1832 } 1833 } 1834 } 1835 break; 1836 case 5: 1837 /* C.FSDSP -> fsd rs2, offset[8:3](x2)*/ 1838 gen_fp_store(ctx, OPC_RISC_FSD, 2, GET_C_RS2(ctx->opcode), 1839 GET_C_SDSP_IMM(ctx->opcode)); 1840 /* C.SQSP */ 1841 break; 1842 case 6: /* C.SWSP -> sw rs2, offset[7:2](x2)*/ 1843 gen_store(ctx, OPC_RISC_SW, 2, GET_C_RS2(ctx->opcode), 1844 GET_C_SWSP_IMM(ctx->opcode)); 1845 break; 1846 case 7: 1847 #if defined(TARGET_RISCV64) 1848 /* C.SDSP(Rv64/128) -> sd rs2, offset[8:3](x2)*/ 1849 gen_store(ctx, OPC_RISC_SD, 2, GET_C_RS2(ctx->opcode), 1850 GET_C_SDSP_IMM(ctx->opcode)); 1851 #else 1852 /* C.FSWSP(RV32) -> fsw rs2, offset[7:2](x2) */ 1853 gen_fp_store(ctx, OPC_RISC_FSW, 2, GET_C_RS2(ctx->opcode), 1854 GET_C_SWSP_IMM(ctx->opcode)); 1855 #endif 1856 break; 1857 } 1858 } 1859 1860 static void decode_RV32_64C(DisasContext *ctx) 1861 { 1862 uint8_t op = extract32(ctx->opcode, 0, 2); 1863 1864 switch (op) { 1865 case 0: 1866 decode_RV32_64C0(ctx); 1867 break; 1868 case 1: 1869 decode_RV32_64C1(ctx); 1870 break; 1871 case 2: 1872 decode_RV32_64C2(ctx); 1873 break; 1874 } 1875 } 1876 1877 #define EX_SH(amount) \ 1878 static int ex_shift_##amount(int imm) \ 1879 { \ 1880 return imm << amount; \ 1881 } 1882 EX_SH(12) 1883 1884 bool decode_insn32(DisasContext *ctx, uint32_t insn); 1885 /* Include the auto-generated decoder for 32 bit insn */ 1886 #include "decode_insn32.inc.c" 1887 /* Include insn module translation function */ 1888 #include "insn_trans/trans_rvi.inc.c" 1889 1890 static void decode_RV32_64G(DisasContext *ctx) 1891 { 1892 int rs1; 1893 int rs2; 1894 int rd; 1895 uint32_t op; 1896 target_long imm; 1897 1898 /* We do not do misaligned address check here: the address should never be 1899 * misaligned at this point. Instructions that set PC must do the check, 1900 * since epc must be the address of the instruction that caused us to 1901 * perform the misaligned instruction fetch */ 1902 1903 op = MASK_OP_MAJOR(ctx->opcode); 1904 rs1 = GET_RS1(ctx->opcode); 1905 rs2 = GET_RS2(ctx->opcode); 1906 rd = GET_RD(ctx->opcode); 1907 imm = GET_IMM(ctx->opcode); 1908 1909 switch (op) { 1910 case OPC_RISC_JAL: 1911 imm = GET_JAL_IMM(ctx->opcode); 1912 gen_jal(ctx, rd, imm); 1913 break; 1914 case OPC_RISC_JALR: 1915 gen_jalr(ctx, MASK_OP_JALR(ctx->opcode), rd, rs1, imm); 1916 break; 1917 case OPC_RISC_BRANCH: 1918 gen_branch(ctx, MASK_OP_BRANCH(ctx->opcode), rs1, rs2, 1919 GET_B_IMM(ctx->opcode)); 1920 break; 1921 case OPC_RISC_LOAD: 1922 gen_load(ctx, MASK_OP_LOAD(ctx->opcode), rd, rs1, imm); 1923 break; 1924 case OPC_RISC_STORE: 1925 gen_store(ctx, MASK_OP_STORE(ctx->opcode), rs1, rs2, 1926 GET_STORE_IMM(ctx->opcode)); 1927 break; 1928 case OPC_RISC_ARITH_IMM: 1929 #if defined(TARGET_RISCV64) 1930 case OPC_RISC_ARITH_IMM_W: 1931 #endif 1932 if (rd == 0) { 1933 break; /* NOP */ 1934 } 1935 gen_arith_imm(ctx, MASK_OP_ARITH_IMM(ctx->opcode), rd, rs1, imm); 1936 break; 1937 case OPC_RISC_ARITH: 1938 #if defined(TARGET_RISCV64) 1939 case OPC_RISC_ARITH_W: 1940 #endif 1941 if (rd == 0) { 1942 break; /* NOP */ 1943 } 1944 gen_arith(ctx, MASK_OP_ARITH(ctx->opcode), rd, rs1, rs2); 1945 break; 1946 case OPC_RISC_FP_LOAD: 1947 gen_fp_load(ctx, MASK_OP_FP_LOAD(ctx->opcode), rd, rs1, imm); 1948 break; 1949 case OPC_RISC_FP_STORE: 1950 gen_fp_store(ctx, MASK_OP_FP_STORE(ctx->opcode), rs1, rs2, 1951 GET_STORE_IMM(ctx->opcode)); 1952 break; 1953 case OPC_RISC_ATOMIC: 1954 if (!has_ext(ctx, RVA)) { 1955 goto do_illegal; 1956 } 1957 gen_atomic(ctx, MASK_OP_ATOMIC(ctx->opcode), rd, rs1, rs2); 1958 break; 1959 case OPC_RISC_FMADD: 1960 gen_fp_fmadd(ctx, MASK_OP_FP_FMADD(ctx->opcode), rd, rs1, rs2, 1961 GET_RS3(ctx->opcode), GET_RM(ctx->opcode)); 1962 break; 1963 case OPC_RISC_FMSUB: 1964 gen_fp_fmsub(ctx, MASK_OP_FP_FMSUB(ctx->opcode), rd, rs1, rs2, 1965 GET_RS3(ctx->opcode), GET_RM(ctx->opcode)); 1966 break; 1967 case OPC_RISC_FNMSUB: 1968 gen_fp_fnmsub(ctx, MASK_OP_FP_FNMSUB(ctx->opcode), rd, rs1, rs2, 1969 GET_RS3(ctx->opcode), GET_RM(ctx->opcode)); 1970 break; 1971 case OPC_RISC_FNMADD: 1972 gen_fp_fnmadd(ctx, MASK_OP_FP_FNMADD(ctx->opcode), rd, rs1, rs2, 1973 GET_RS3(ctx->opcode), GET_RM(ctx->opcode)); 1974 break; 1975 case OPC_RISC_FP_ARITH: 1976 gen_fp_arith(ctx, MASK_OP_FP_ARITH(ctx->opcode), rd, rs1, rs2, 1977 GET_RM(ctx->opcode)); 1978 break; 1979 case OPC_RISC_FENCE: 1980 if (ctx->opcode & 0x1000) { 1981 /* FENCE_I is a no-op in QEMU, 1982 * however we need to end the translation block */ 1983 tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); 1984 tcg_gen_exit_tb(NULL, 0); 1985 ctx->base.is_jmp = DISAS_NORETURN; 1986 } else { 1987 /* FENCE is a full memory barrier. */ 1988 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); 1989 } 1990 break; 1991 case OPC_RISC_SYSTEM: 1992 gen_system(ctx, MASK_OP_SYSTEM(ctx->opcode), rd, rs1, 1993 (ctx->opcode & 0xFFF00000) >> 20); 1994 break; 1995 do_illegal: 1996 default: 1997 gen_exception_illegal(ctx); 1998 break; 1999 } 2000 } 2001 2002 static void decode_opc(DisasContext *ctx) 2003 { 2004 /* check for compressed insn */ 2005 if (extract32(ctx->opcode, 0, 2) != 3) { 2006 if (!has_ext(ctx, RVC)) { 2007 gen_exception_illegal(ctx); 2008 } else { 2009 ctx->pc_succ_insn = ctx->base.pc_next + 2; 2010 decode_RV32_64C(ctx); 2011 } 2012 } else { 2013 ctx->pc_succ_insn = ctx->base.pc_next + 4; 2014 if (!decode_insn32(ctx, ctx->opcode)) { 2015 /* fallback to old decoder */ 2016 decode_RV32_64G(ctx); 2017 } 2018 } 2019 } 2020 2021 static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) 2022 { 2023 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2024 CPURISCVState *env = cs->env_ptr; 2025 2026 ctx->pc_succ_insn = ctx->base.pc_first; 2027 ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK; 2028 ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS; 2029 ctx->priv_ver = env->priv_ver; 2030 ctx->misa = env->misa; 2031 ctx->frm = -1; /* unknown rounding mode */ 2032 } 2033 2034 static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu) 2035 { 2036 } 2037 2038 static void riscv_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) 2039 { 2040 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2041 2042 tcg_gen_insn_start(ctx->base.pc_next); 2043 } 2044 2045 static bool riscv_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, 2046 const CPUBreakpoint *bp) 2047 { 2048 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2049 2050 tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); 2051 ctx->base.is_jmp = DISAS_NORETURN; 2052 gen_exception_debug(); 2053 /* The address covered by the breakpoint must be included in 2054 [tb->pc, tb->pc + tb->size) in order to for it to be 2055 properly cleared -- thus we increment the PC here so that 2056 the logic setting tb->size below does the right thing. */ 2057 ctx->base.pc_next += 4; 2058 return true; 2059 } 2060 2061 static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) 2062 { 2063 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2064 CPURISCVState *env = cpu->env_ptr; 2065 2066 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next); 2067 decode_opc(ctx); 2068 ctx->base.pc_next = ctx->pc_succ_insn; 2069 2070 if (ctx->base.is_jmp == DISAS_NEXT) { 2071 target_ulong page_start; 2072 2073 page_start = ctx->base.pc_first & TARGET_PAGE_MASK; 2074 if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE) { 2075 ctx->base.is_jmp = DISAS_TOO_MANY; 2076 } 2077 } 2078 } 2079 2080 static void riscv_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) 2081 { 2082 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2083 2084 switch (ctx->base.is_jmp) { 2085 case DISAS_TOO_MANY: 2086 gen_goto_tb(ctx, 0, ctx->base.pc_next); 2087 break; 2088 case DISAS_NORETURN: 2089 break; 2090 default: 2091 g_assert_not_reached(); 2092 } 2093 } 2094 2095 static void riscv_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu) 2096 { 2097 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first)); 2098 log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size); 2099 } 2100 2101 static const TranslatorOps riscv_tr_ops = { 2102 .init_disas_context = riscv_tr_init_disas_context, 2103 .tb_start = riscv_tr_tb_start, 2104 .insn_start = riscv_tr_insn_start, 2105 .breakpoint_check = riscv_tr_breakpoint_check, 2106 .translate_insn = riscv_tr_translate_insn, 2107 .tb_stop = riscv_tr_tb_stop, 2108 .disas_log = riscv_tr_disas_log, 2109 }; 2110 2111 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) 2112 { 2113 DisasContext ctx; 2114 2115 translator_loop(&riscv_tr_ops, &ctx.base, cs, tb); 2116 } 2117 2118 void riscv_translate_init(void) 2119 { 2120 int i; 2121 2122 /* cpu_gpr[0] is a placeholder for the zero register. Do not use it. */ 2123 /* Use the gen_set_gpr and gen_get_gpr helper functions when accessing */ 2124 /* registers, unless you specifically block reads/writes to reg 0 */ 2125 cpu_gpr[0] = NULL; 2126 2127 for (i = 1; i < 32; i++) { 2128 cpu_gpr[i] = tcg_global_mem_new(cpu_env, 2129 offsetof(CPURISCVState, gpr[i]), riscv_int_regnames[i]); 2130 } 2131 2132 for (i = 0; i < 32; i++) { 2133 cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env, 2134 offsetof(CPURISCVState, fpr[i]), riscv_fpr_regnames[i]); 2135 } 2136 2137 cpu_pc = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, pc), "pc"); 2138 load_res = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_res), 2139 "load_res"); 2140 load_val = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_val), 2141 "load_val"); 2142 } 2143