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