1 /* 2 * Alpha emulation cpu translation for qemu. 3 * 4 * Copyright (c) 2007 Jocelyn Mayer 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "qemu/osdep.h" 21 #include "cpu.h" 22 #include "sysemu/cpus.h" 23 #include "disas/disas.h" 24 #include "qemu/host-utils.h" 25 #include "exec/exec-all.h" 26 #include "tcg/tcg-op.h" 27 #include "exec/cpu_ldst.h" 28 #include "exec/helper-proto.h" 29 #include "exec/helper-gen.h" 30 #include "exec/translator.h" 31 #include "exec/log.h" 32 33 34 #undef ALPHA_DEBUG_DISAS 35 #define CONFIG_SOFTFLOAT_INLINE 36 37 #ifdef ALPHA_DEBUG_DISAS 38 # define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__) 39 #else 40 # define LOG_DISAS(...) do { } while (0) 41 #endif 42 43 typedef struct DisasContext DisasContext; 44 struct DisasContext { 45 DisasContextBase base; 46 47 #ifdef CONFIG_USER_ONLY 48 MemOp unalign; 49 #else 50 uint64_t palbr; 51 #endif 52 uint32_t tbflags; 53 int mem_idx; 54 55 /* implver and amask values for this CPU. */ 56 int implver; 57 int amask; 58 59 /* Current rounding mode for this TB. */ 60 int tb_rm; 61 /* Current flush-to-zero setting for this TB. */ 62 int tb_ftz; 63 64 /* The set of registers active in the current context. */ 65 TCGv *ir; 66 67 /* Temporaries for $31 and $f31 as source and destination. */ 68 TCGv zero; 69 TCGv sink; 70 }; 71 72 #ifdef CONFIG_USER_ONLY 73 #define UNALIGN(C) (C)->unalign 74 #else 75 #define UNALIGN(C) 0 76 #endif 77 78 /* Target-specific return values from translate_one, indicating the 79 state of the TB. Note that DISAS_NEXT indicates that we are not 80 exiting the TB. */ 81 #define DISAS_PC_UPDATED_NOCHAIN DISAS_TARGET_0 82 #define DISAS_PC_UPDATED DISAS_TARGET_1 83 #define DISAS_PC_STALE DISAS_TARGET_2 84 85 /* global register indexes */ 86 static TCGv cpu_std_ir[31]; 87 static TCGv cpu_fir[31]; 88 static TCGv cpu_pc; 89 static TCGv cpu_lock_addr; 90 static TCGv cpu_lock_value; 91 92 #ifndef CONFIG_USER_ONLY 93 static TCGv cpu_pal_ir[31]; 94 #endif 95 96 #include "exec/gen-icount.h" 97 98 void alpha_translate_init(void) 99 { 100 #define DEF_VAR(V) { &cpu_##V, #V, offsetof(CPUAlphaState, V) } 101 102 typedef struct { TCGv *var; const char *name; int ofs; } GlobalVar; 103 static const GlobalVar vars[] = { 104 DEF_VAR(pc), 105 DEF_VAR(lock_addr), 106 DEF_VAR(lock_value), 107 }; 108 109 #undef DEF_VAR 110 111 /* Use the symbolic register names that match the disassembler. */ 112 static const char greg_names[31][4] = { 113 "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6", 114 "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp", 115 "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9", 116 "t10", "t11", "ra", "t12", "at", "gp", "sp" 117 }; 118 static const char freg_names[31][4] = { 119 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 120 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", 121 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", 122 "f24", "f25", "f26", "f27", "f28", "f29", "f30" 123 }; 124 #ifndef CONFIG_USER_ONLY 125 static const char shadow_names[8][8] = { 126 "pal_t7", "pal_s0", "pal_s1", "pal_s2", 127 "pal_s3", "pal_s4", "pal_s5", "pal_t11" 128 }; 129 #endif 130 131 int i; 132 133 for (i = 0; i < 31; i++) { 134 cpu_std_ir[i] = tcg_global_mem_new_i64(cpu_env, 135 offsetof(CPUAlphaState, ir[i]), 136 greg_names[i]); 137 } 138 139 for (i = 0; i < 31; i++) { 140 cpu_fir[i] = tcg_global_mem_new_i64(cpu_env, 141 offsetof(CPUAlphaState, fir[i]), 142 freg_names[i]); 143 } 144 145 #ifndef CONFIG_USER_ONLY 146 memcpy(cpu_pal_ir, cpu_std_ir, sizeof(cpu_pal_ir)); 147 for (i = 0; i < 8; i++) { 148 int r = (i == 7 ? 25 : i + 8); 149 cpu_pal_ir[r] = tcg_global_mem_new_i64(cpu_env, 150 offsetof(CPUAlphaState, 151 shadow[i]), 152 shadow_names[i]); 153 } 154 #endif 155 156 for (i = 0; i < ARRAY_SIZE(vars); ++i) { 157 const GlobalVar *v = &vars[i]; 158 *v->var = tcg_global_mem_new_i64(cpu_env, v->ofs, v->name); 159 } 160 } 161 162 static TCGv load_zero(DisasContext *ctx) 163 { 164 if (!ctx->zero) { 165 ctx->zero = tcg_constant_i64(0); 166 } 167 return ctx->zero; 168 } 169 170 static TCGv dest_sink(DisasContext *ctx) 171 { 172 if (!ctx->sink) { 173 ctx->sink = tcg_temp_new(); 174 } 175 return ctx->sink; 176 } 177 178 static void free_context_temps(DisasContext *ctx) 179 { 180 if (ctx->sink) { 181 tcg_gen_discard_i64(ctx->sink); 182 tcg_temp_free(ctx->sink); 183 ctx->sink = NULL; 184 } 185 } 186 187 static TCGv load_gpr(DisasContext *ctx, unsigned reg) 188 { 189 if (likely(reg < 31)) { 190 return ctx->ir[reg]; 191 } else { 192 return load_zero(ctx); 193 } 194 } 195 196 static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg, 197 uint8_t lit, bool islit) 198 { 199 if (islit) { 200 return tcg_constant_i64(lit); 201 } else if (likely(reg < 31)) { 202 return ctx->ir[reg]; 203 } else { 204 return load_zero(ctx); 205 } 206 } 207 208 static TCGv dest_gpr(DisasContext *ctx, unsigned reg) 209 { 210 if (likely(reg < 31)) { 211 return ctx->ir[reg]; 212 } else { 213 return dest_sink(ctx); 214 } 215 } 216 217 static TCGv load_fpr(DisasContext *ctx, unsigned reg) 218 { 219 if (likely(reg < 31)) { 220 return cpu_fir[reg]; 221 } else { 222 return load_zero(ctx); 223 } 224 } 225 226 static TCGv dest_fpr(DisasContext *ctx, unsigned reg) 227 { 228 if (likely(reg < 31)) { 229 return cpu_fir[reg]; 230 } else { 231 return dest_sink(ctx); 232 } 233 } 234 235 static int get_flag_ofs(unsigned shift) 236 { 237 int ofs = offsetof(CPUAlphaState, flags); 238 #if HOST_BIG_ENDIAN 239 ofs += 3 - (shift / 8); 240 #else 241 ofs += shift / 8; 242 #endif 243 return ofs; 244 } 245 246 static void ld_flag_byte(TCGv val, unsigned shift) 247 { 248 tcg_gen_ld8u_i64(val, cpu_env, get_flag_ofs(shift)); 249 } 250 251 static void st_flag_byte(TCGv val, unsigned shift) 252 { 253 tcg_gen_st8_i64(val, cpu_env, get_flag_ofs(shift)); 254 } 255 256 static void gen_excp_1(int exception, int error_code) 257 { 258 TCGv_i32 tmp1, tmp2; 259 260 tmp1 = tcg_constant_i32(exception); 261 tmp2 = tcg_constant_i32(error_code); 262 gen_helper_excp(cpu_env, tmp1, tmp2); 263 } 264 265 static DisasJumpType gen_excp(DisasContext *ctx, int exception, int error_code) 266 { 267 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next); 268 gen_excp_1(exception, error_code); 269 return DISAS_NORETURN; 270 } 271 272 static inline DisasJumpType gen_invalid(DisasContext *ctx) 273 { 274 return gen_excp(ctx, EXCP_OPCDEC, 0); 275 } 276 277 static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr) 278 { 279 TCGv_i32 tmp32 = tcg_temp_new_i32(); 280 tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx)); 281 gen_helper_memory_to_f(dest, tmp32); 282 tcg_temp_free_i32(tmp32); 283 } 284 285 static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr) 286 { 287 TCGv tmp = tcg_temp_new(); 288 tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx)); 289 gen_helper_memory_to_g(dest, tmp); 290 tcg_temp_free(tmp); 291 } 292 293 static void gen_lds(DisasContext *ctx, TCGv dest, TCGv addr) 294 { 295 TCGv_i32 tmp32 = tcg_temp_new_i32(); 296 tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx)); 297 gen_helper_memory_to_s(dest, tmp32); 298 tcg_temp_free_i32(tmp32); 299 } 300 301 static void gen_ldt(DisasContext *ctx, TCGv dest, TCGv addr) 302 { 303 tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx)); 304 } 305 306 static void gen_load_fp(DisasContext *ctx, int ra, int rb, int32_t disp16, 307 void (*func)(DisasContext *, TCGv, TCGv)) 308 { 309 /* Loads to $f31 are prefetches, which we can treat as nops. */ 310 if (likely(ra != 31)) { 311 TCGv addr = tcg_temp_new(); 312 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16); 313 func(ctx, cpu_fir[ra], addr); 314 tcg_temp_free(addr); 315 } 316 } 317 318 static void gen_load_int(DisasContext *ctx, int ra, int rb, int32_t disp16, 319 MemOp op, bool clear, bool locked) 320 { 321 TCGv addr, dest; 322 323 /* LDQ_U with ra $31 is UNOP. Other various loads are forms of 324 prefetches, which we can treat as nops. No worries about 325 missed exceptions here. */ 326 if (unlikely(ra == 31)) { 327 return; 328 } 329 330 addr = tcg_temp_new(); 331 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16); 332 if (clear) { 333 tcg_gen_andi_i64(addr, addr, ~0x7); 334 } else if (!locked) { 335 op |= UNALIGN(ctx); 336 } 337 338 dest = ctx->ir[ra]; 339 tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, op); 340 341 if (locked) { 342 tcg_gen_mov_i64(cpu_lock_addr, addr); 343 tcg_gen_mov_i64(cpu_lock_value, dest); 344 } 345 tcg_temp_free(addr); 346 } 347 348 static void gen_stf(DisasContext *ctx, TCGv src, TCGv addr) 349 { 350 TCGv_i32 tmp32 = tcg_temp_new_i32(); 351 gen_helper_f_to_memory(tmp32, addr); 352 tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx)); 353 tcg_temp_free_i32(tmp32); 354 } 355 356 static void gen_stg(DisasContext *ctx, TCGv src, TCGv addr) 357 { 358 TCGv tmp = tcg_temp_new(); 359 gen_helper_g_to_memory(tmp, src); 360 tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx)); 361 tcg_temp_free(tmp); 362 } 363 364 static void gen_sts(DisasContext *ctx, TCGv src, TCGv addr) 365 { 366 TCGv_i32 tmp32 = tcg_temp_new_i32(); 367 gen_helper_s_to_memory(tmp32, src); 368 tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx)); 369 tcg_temp_free_i32(tmp32); 370 } 371 372 static void gen_stt(DisasContext *ctx, TCGv src, TCGv addr) 373 { 374 tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx)); 375 } 376 377 static void gen_store_fp(DisasContext *ctx, int ra, int rb, int32_t disp16, 378 void (*func)(DisasContext *, TCGv, TCGv)) 379 { 380 TCGv addr = tcg_temp_new(); 381 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16); 382 func(ctx, load_fpr(ctx, ra), addr); 383 tcg_temp_free(addr); 384 } 385 386 static void gen_store_int(DisasContext *ctx, int ra, int rb, int32_t disp16, 387 MemOp op, bool clear) 388 { 389 TCGv addr, src; 390 391 addr = tcg_temp_new(); 392 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16); 393 if (clear) { 394 tcg_gen_andi_i64(addr, addr, ~0x7); 395 } else { 396 op |= UNALIGN(ctx); 397 } 398 399 src = load_gpr(ctx, ra); 400 tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, op); 401 402 tcg_temp_free(addr); 403 } 404 405 static DisasJumpType gen_store_conditional(DisasContext *ctx, int ra, int rb, 406 int32_t disp16, int mem_idx, 407 MemOp op) 408 { 409 TCGLabel *lab_fail, *lab_done; 410 TCGv addr, val; 411 412 addr = tcg_temp_new_i64(); 413 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16); 414 free_context_temps(ctx); 415 416 lab_fail = gen_new_label(); 417 lab_done = gen_new_label(); 418 tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail); 419 tcg_temp_free_i64(addr); 420 421 val = tcg_temp_new_i64(); 422 tcg_gen_atomic_cmpxchg_i64(val, cpu_lock_addr, cpu_lock_value, 423 load_gpr(ctx, ra), mem_idx, op); 424 free_context_temps(ctx); 425 426 if (ra != 31) { 427 tcg_gen_setcond_i64(TCG_COND_EQ, ctx->ir[ra], val, cpu_lock_value); 428 } 429 tcg_temp_free_i64(val); 430 tcg_gen_br(lab_done); 431 432 gen_set_label(lab_fail); 433 if (ra != 31) { 434 tcg_gen_movi_i64(ctx->ir[ra], 0); 435 } 436 437 gen_set_label(lab_done); 438 tcg_gen_movi_i64(cpu_lock_addr, -1); 439 return DISAS_NEXT; 440 } 441 442 static bool use_goto_tb(DisasContext *ctx, uint64_t dest) 443 { 444 return translator_use_goto_tb(&ctx->base, dest); 445 } 446 447 static DisasJumpType gen_bdirect(DisasContext *ctx, int ra, int32_t disp) 448 { 449 uint64_t dest = ctx->base.pc_next + (disp << 2); 450 451 if (ra != 31) { 452 tcg_gen_movi_i64(ctx->ir[ra], ctx->base.pc_next); 453 } 454 455 /* Notice branch-to-next; used to initialize RA with the PC. */ 456 if (disp == 0) { 457 return 0; 458 } else if (use_goto_tb(ctx, dest)) { 459 tcg_gen_goto_tb(0); 460 tcg_gen_movi_i64(cpu_pc, dest); 461 tcg_gen_exit_tb(ctx->base.tb, 0); 462 return DISAS_NORETURN; 463 } else { 464 tcg_gen_movi_i64(cpu_pc, dest); 465 return DISAS_PC_UPDATED; 466 } 467 } 468 469 static DisasJumpType gen_bcond_internal(DisasContext *ctx, TCGCond cond, 470 TCGv cmp, int32_t disp) 471 { 472 uint64_t dest = ctx->base.pc_next + (disp << 2); 473 TCGLabel *lab_true = gen_new_label(); 474 475 if (use_goto_tb(ctx, dest)) { 476 tcg_gen_brcondi_i64(cond, cmp, 0, lab_true); 477 478 tcg_gen_goto_tb(0); 479 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next); 480 tcg_gen_exit_tb(ctx->base.tb, 0); 481 482 gen_set_label(lab_true); 483 tcg_gen_goto_tb(1); 484 tcg_gen_movi_i64(cpu_pc, dest); 485 tcg_gen_exit_tb(ctx->base.tb, 1); 486 487 return DISAS_NORETURN; 488 } else { 489 TCGv_i64 z = load_zero(ctx); 490 TCGv_i64 d = tcg_constant_i64(dest); 491 TCGv_i64 p = tcg_constant_i64(ctx->base.pc_next); 492 493 tcg_gen_movcond_i64(cond, cpu_pc, cmp, z, d, p); 494 return DISAS_PC_UPDATED; 495 } 496 } 497 498 static DisasJumpType gen_bcond(DisasContext *ctx, TCGCond cond, int ra, 499 int32_t disp, int mask) 500 { 501 if (mask) { 502 TCGv tmp = tcg_temp_new(); 503 DisasJumpType ret; 504 505 tcg_gen_andi_i64(tmp, load_gpr(ctx, ra), 1); 506 ret = gen_bcond_internal(ctx, cond, tmp, disp); 507 tcg_temp_free(tmp); 508 return ret; 509 } 510 return gen_bcond_internal(ctx, cond, load_gpr(ctx, ra), disp); 511 } 512 513 /* Fold -0.0 for comparison with COND. */ 514 515 static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src) 516 { 517 uint64_t mzero = 1ull << 63; 518 519 switch (cond) { 520 case TCG_COND_LE: 521 case TCG_COND_GT: 522 /* For <= or >, the -0.0 value directly compares the way we want. */ 523 tcg_gen_mov_i64(dest, src); 524 break; 525 526 case TCG_COND_EQ: 527 case TCG_COND_NE: 528 /* For == or !=, we can simply mask off the sign bit and compare. */ 529 tcg_gen_andi_i64(dest, src, mzero - 1); 530 break; 531 532 case TCG_COND_GE: 533 case TCG_COND_LT: 534 /* For >= or <, map -0.0 to +0.0 via comparison and mask. */ 535 tcg_gen_setcondi_i64(TCG_COND_NE, dest, src, mzero); 536 tcg_gen_neg_i64(dest, dest); 537 tcg_gen_and_i64(dest, dest, src); 538 break; 539 540 default: 541 abort(); 542 } 543 } 544 545 static DisasJumpType gen_fbcond(DisasContext *ctx, TCGCond cond, int ra, 546 int32_t disp) 547 { 548 TCGv cmp_tmp = tcg_temp_new(); 549 DisasJumpType ret; 550 551 gen_fold_mzero(cond, cmp_tmp, load_fpr(ctx, ra)); 552 ret = gen_bcond_internal(ctx, cond, cmp_tmp, disp); 553 tcg_temp_free(cmp_tmp); 554 return ret; 555 } 556 557 static void gen_fcmov(DisasContext *ctx, TCGCond cond, int ra, int rb, int rc) 558 { 559 TCGv_i64 va, vb, z; 560 561 z = load_zero(ctx); 562 vb = load_fpr(ctx, rb); 563 va = tcg_temp_new(); 564 gen_fold_mzero(cond, va, load_fpr(ctx, ra)); 565 566 tcg_gen_movcond_i64(cond, dest_fpr(ctx, rc), va, z, vb, load_fpr(ctx, rc)); 567 568 tcg_temp_free(va); 569 } 570 571 #define QUAL_RM_N 0x080 /* Round mode nearest even */ 572 #define QUAL_RM_C 0x000 /* Round mode chopped */ 573 #define QUAL_RM_M 0x040 /* Round mode minus infinity */ 574 #define QUAL_RM_D 0x0c0 /* Round mode dynamic */ 575 #define QUAL_RM_MASK 0x0c0 576 577 #define QUAL_U 0x100 /* Underflow enable (fp output) */ 578 #define QUAL_V 0x100 /* Overflow enable (int output) */ 579 #define QUAL_S 0x400 /* Software completion enable */ 580 #define QUAL_I 0x200 /* Inexact detection enable */ 581 582 static void gen_qual_roundmode(DisasContext *ctx, int fn11) 583 { 584 TCGv_i32 tmp; 585 586 fn11 &= QUAL_RM_MASK; 587 if (fn11 == ctx->tb_rm) { 588 return; 589 } 590 ctx->tb_rm = fn11; 591 592 tmp = tcg_temp_new_i32(); 593 switch (fn11) { 594 case QUAL_RM_N: 595 tcg_gen_movi_i32(tmp, float_round_nearest_even); 596 break; 597 case QUAL_RM_C: 598 tcg_gen_movi_i32(tmp, float_round_to_zero); 599 break; 600 case QUAL_RM_M: 601 tcg_gen_movi_i32(tmp, float_round_down); 602 break; 603 case QUAL_RM_D: 604 tcg_gen_ld8u_i32(tmp, cpu_env, 605 offsetof(CPUAlphaState, fpcr_dyn_round)); 606 break; 607 } 608 609 #if defined(CONFIG_SOFTFLOAT_INLINE) 610 /* ??? The "fpu/softfloat.h" interface is to call set_float_rounding_mode. 611 With CONFIG_SOFTFLOAT that expands to an out-of-line call that just 612 sets the one field. */ 613 tcg_gen_st8_i32(tmp, cpu_env, 614 offsetof(CPUAlphaState, fp_status.float_rounding_mode)); 615 #else 616 gen_helper_setroundmode(tmp); 617 #endif 618 619 tcg_temp_free_i32(tmp); 620 } 621 622 static void gen_qual_flushzero(DisasContext *ctx, int fn11) 623 { 624 TCGv_i32 tmp; 625 626 fn11 &= QUAL_U; 627 if (fn11 == ctx->tb_ftz) { 628 return; 629 } 630 ctx->tb_ftz = fn11; 631 632 tmp = tcg_temp_new_i32(); 633 if (fn11) { 634 /* Underflow is enabled, use the FPCR setting. */ 635 tcg_gen_ld8u_i32(tmp, cpu_env, 636 offsetof(CPUAlphaState, fpcr_flush_to_zero)); 637 } else { 638 /* Underflow is disabled, force flush-to-zero. */ 639 tcg_gen_movi_i32(tmp, 1); 640 } 641 642 #if defined(CONFIG_SOFTFLOAT_INLINE) 643 tcg_gen_st8_i32(tmp, cpu_env, 644 offsetof(CPUAlphaState, fp_status.flush_to_zero)); 645 #else 646 gen_helper_setflushzero(tmp); 647 #endif 648 649 tcg_temp_free_i32(tmp); 650 } 651 652 static TCGv gen_ieee_input(DisasContext *ctx, int reg, int fn11, int is_cmp) 653 { 654 TCGv val; 655 656 if (unlikely(reg == 31)) { 657 val = load_zero(ctx); 658 } else { 659 val = cpu_fir[reg]; 660 if ((fn11 & QUAL_S) == 0) { 661 if (is_cmp) { 662 gen_helper_ieee_input_cmp(cpu_env, val); 663 } else { 664 gen_helper_ieee_input(cpu_env, val); 665 } 666 } else { 667 #ifndef CONFIG_USER_ONLY 668 /* In system mode, raise exceptions for denormals like real 669 hardware. In user mode, proceed as if the OS completion 670 handler is handling the denormal as per spec. */ 671 gen_helper_ieee_input_s(cpu_env, val); 672 #endif 673 } 674 } 675 return val; 676 } 677 678 static void gen_fp_exc_raise(int rc, int fn11) 679 { 680 /* ??? We ought to be able to do something with imprecise exceptions. 681 E.g. notice we're still in the trap shadow of something within the 682 TB and do not generate the code to signal the exception; end the TB 683 when an exception is forced to arrive, either by consumption of a 684 register value or TRAPB or EXCB. */ 685 TCGv_i32 reg, ign; 686 uint32_t ignore = 0; 687 688 if (!(fn11 & QUAL_U)) { 689 /* Note that QUAL_U == QUAL_V, so ignore either. */ 690 ignore |= FPCR_UNF | FPCR_IOV; 691 } 692 if (!(fn11 & QUAL_I)) { 693 ignore |= FPCR_INE; 694 } 695 ign = tcg_constant_i32(ignore); 696 697 /* ??? Pass in the regno of the destination so that the helper can 698 set EXC_MASK, which contains a bitmask of destination registers 699 that have caused arithmetic traps. A simple userspace emulation 700 does not require this. We do need it for a guest kernel's entArith, 701 or if we were to do something clever with imprecise exceptions. */ 702 reg = tcg_constant_i32(rc + 32); 703 if (fn11 & QUAL_S) { 704 gen_helper_fp_exc_raise_s(cpu_env, ign, reg); 705 } else { 706 gen_helper_fp_exc_raise(cpu_env, ign, reg); 707 } 708 } 709 710 static void gen_cvtlq(TCGv vc, TCGv vb) 711 { 712 TCGv tmp = tcg_temp_new(); 713 714 /* The arithmetic right shift here, plus the sign-extended mask below 715 yields a sign-extended result without an explicit ext32s_i64. */ 716 tcg_gen_shri_i64(tmp, vb, 29); 717 tcg_gen_sari_i64(vc, vb, 32); 718 tcg_gen_deposit_i64(vc, vc, tmp, 0, 30); 719 720 tcg_temp_free(tmp); 721 } 722 723 static void gen_ieee_arith2(DisasContext *ctx, 724 void (*helper)(TCGv, TCGv_ptr, TCGv), 725 int rb, int rc, int fn11) 726 { 727 TCGv vb; 728 729 gen_qual_roundmode(ctx, fn11); 730 gen_qual_flushzero(ctx, fn11); 731 732 vb = gen_ieee_input(ctx, rb, fn11, 0); 733 helper(dest_fpr(ctx, rc), cpu_env, vb); 734 735 gen_fp_exc_raise(rc, fn11); 736 } 737 738 #define IEEE_ARITH2(name) \ 739 static inline void glue(gen_, name)(DisasContext *ctx, \ 740 int rb, int rc, int fn11) \ 741 { \ 742 gen_ieee_arith2(ctx, gen_helper_##name, rb, rc, fn11); \ 743 } 744 IEEE_ARITH2(sqrts) 745 IEEE_ARITH2(sqrtt) 746 IEEE_ARITH2(cvtst) 747 IEEE_ARITH2(cvtts) 748 749 static void gen_cvttq(DisasContext *ctx, int rb, int rc, int fn11) 750 { 751 TCGv vb, vc; 752 753 /* No need to set flushzero, since we have an integer output. */ 754 vb = gen_ieee_input(ctx, rb, fn11, 0); 755 vc = dest_fpr(ctx, rc); 756 757 /* Almost all integer conversions use cropped rounding; 758 special case that. */ 759 if ((fn11 & QUAL_RM_MASK) == QUAL_RM_C) { 760 gen_helper_cvttq_c(vc, cpu_env, vb); 761 } else { 762 gen_qual_roundmode(ctx, fn11); 763 gen_helper_cvttq(vc, cpu_env, vb); 764 } 765 gen_fp_exc_raise(rc, fn11); 766 } 767 768 static void gen_ieee_intcvt(DisasContext *ctx, 769 void (*helper)(TCGv, TCGv_ptr, TCGv), 770 int rb, int rc, int fn11) 771 { 772 TCGv vb, vc; 773 774 gen_qual_roundmode(ctx, fn11); 775 vb = load_fpr(ctx, rb); 776 vc = dest_fpr(ctx, rc); 777 778 /* The only exception that can be raised by integer conversion 779 is inexact. Thus we only need to worry about exceptions when 780 inexact handling is requested. */ 781 if (fn11 & QUAL_I) { 782 helper(vc, cpu_env, vb); 783 gen_fp_exc_raise(rc, fn11); 784 } else { 785 helper(vc, cpu_env, vb); 786 } 787 } 788 789 #define IEEE_INTCVT(name) \ 790 static inline void glue(gen_, name)(DisasContext *ctx, \ 791 int rb, int rc, int fn11) \ 792 { \ 793 gen_ieee_intcvt(ctx, gen_helper_##name, rb, rc, fn11); \ 794 } 795 IEEE_INTCVT(cvtqs) 796 IEEE_INTCVT(cvtqt) 797 798 static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask) 799 { 800 TCGv vmask = tcg_constant_i64(mask); 801 TCGv tmp = tcg_temp_new_i64(); 802 803 if (inv_a) { 804 tcg_gen_andc_i64(tmp, vmask, va); 805 } else { 806 tcg_gen_and_i64(tmp, va, vmask); 807 } 808 809 tcg_gen_andc_i64(vc, vb, vmask); 810 tcg_gen_or_i64(vc, vc, tmp); 811 812 tcg_temp_free(tmp); 813 } 814 815 static void gen_ieee_arith3(DisasContext *ctx, 816 void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv), 817 int ra, int rb, int rc, int fn11) 818 { 819 TCGv va, vb, vc; 820 821 gen_qual_roundmode(ctx, fn11); 822 gen_qual_flushzero(ctx, fn11); 823 824 va = gen_ieee_input(ctx, ra, fn11, 0); 825 vb = gen_ieee_input(ctx, rb, fn11, 0); 826 vc = dest_fpr(ctx, rc); 827 helper(vc, cpu_env, va, vb); 828 829 gen_fp_exc_raise(rc, fn11); 830 } 831 832 #define IEEE_ARITH3(name) \ 833 static inline void glue(gen_, name)(DisasContext *ctx, \ 834 int ra, int rb, int rc, int fn11) \ 835 { \ 836 gen_ieee_arith3(ctx, gen_helper_##name, ra, rb, rc, fn11); \ 837 } 838 IEEE_ARITH3(adds) 839 IEEE_ARITH3(subs) 840 IEEE_ARITH3(muls) 841 IEEE_ARITH3(divs) 842 IEEE_ARITH3(addt) 843 IEEE_ARITH3(subt) 844 IEEE_ARITH3(mult) 845 IEEE_ARITH3(divt) 846 847 static void gen_ieee_compare(DisasContext *ctx, 848 void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv), 849 int ra, int rb, int rc, int fn11) 850 { 851 TCGv va, vb, vc; 852 853 va = gen_ieee_input(ctx, ra, fn11, 1); 854 vb = gen_ieee_input(ctx, rb, fn11, 1); 855 vc = dest_fpr(ctx, rc); 856 helper(vc, cpu_env, va, vb); 857 858 gen_fp_exc_raise(rc, fn11); 859 } 860 861 #define IEEE_CMP3(name) \ 862 static inline void glue(gen_, name)(DisasContext *ctx, \ 863 int ra, int rb, int rc, int fn11) \ 864 { \ 865 gen_ieee_compare(ctx, gen_helper_##name, ra, rb, rc, fn11); \ 866 } 867 IEEE_CMP3(cmptun) 868 IEEE_CMP3(cmpteq) 869 IEEE_CMP3(cmptlt) 870 IEEE_CMP3(cmptle) 871 872 static inline uint64_t zapnot_mask(uint8_t lit) 873 { 874 uint64_t mask = 0; 875 int i; 876 877 for (i = 0; i < 8; ++i) { 878 if ((lit >> i) & 1) { 879 mask |= 0xffull << (i * 8); 880 } 881 } 882 return mask; 883 } 884 885 /* Implement zapnot with an immediate operand, which expands to some 886 form of immediate AND. This is a basic building block in the 887 definition of many of the other byte manipulation instructions. */ 888 static void gen_zapnoti(TCGv dest, TCGv src, uint8_t lit) 889 { 890 switch (lit) { 891 case 0x00: 892 tcg_gen_movi_i64(dest, 0); 893 break; 894 case 0x01: 895 tcg_gen_ext8u_i64(dest, src); 896 break; 897 case 0x03: 898 tcg_gen_ext16u_i64(dest, src); 899 break; 900 case 0x0f: 901 tcg_gen_ext32u_i64(dest, src); 902 break; 903 case 0xff: 904 tcg_gen_mov_i64(dest, src); 905 break; 906 default: 907 tcg_gen_andi_i64(dest, src, zapnot_mask(lit)); 908 break; 909 } 910 } 911 912 /* EXTWH, EXTLH, EXTQH */ 913 static void gen_ext_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit, 914 uint8_t lit, uint8_t byte_mask) 915 { 916 if (islit) { 917 int pos = (64 - lit * 8) & 0x3f; 918 int len = cto32(byte_mask) * 8; 919 if (pos < len) { 920 tcg_gen_deposit_z_i64(vc, va, pos, len - pos); 921 } else { 922 tcg_gen_movi_i64(vc, 0); 923 } 924 } else { 925 TCGv tmp = tcg_temp_new(); 926 tcg_gen_shli_i64(tmp, load_gpr(ctx, rb), 3); 927 tcg_gen_neg_i64(tmp, tmp); 928 tcg_gen_andi_i64(tmp, tmp, 0x3f); 929 tcg_gen_shl_i64(vc, va, tmp); 930 tcg_temp_free(tmp); 931 } 932 gen_zapnoti(vc, vc, byte_mask); 933 } 934 935 /* EXTBL, EXTWL, EXTLL, EXTQL */ 936 static void gen_ext_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit, 937 uint8_t lit, uint8_t byte_mask) 938 { 939 if (islit) { 940 int pos = (lit & 7) * 8; 941 int len = cto32(byte_mask) * 8; 942 if (pos + len >= 64) { 943 len = 64 - pos; 944 } 945 tcg_gen_extract_i64(vc, va, pos, len); 946 } else { 947 TCGv tmp = tcg_temp_new(); 948 tcg_gen_andi_i64(tmp, load_gpr(ctx, rb), 7); 949 tcg_gen_shli_i64(tmp, tmp, 3); 950 tcg_gen_shr_i64(vc, va, tmp); 951 tcg_temp_free(tmp); 952 gen_zapnoti(vc, vc, byte_mask); 953 } 954 } 955 956 /* INSWH, INSLH, INSQH */ 957 static void gen_ins_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit, 958 uint8_t lit, uint8_t byte_mask) 959 { 960 if (islit) { 961 int pos = 64 - (lit & 7) * 8; 962 int len = cto32(byte_mask) * 8; 963 if (pos < len) { 964 tcg_gen_extract_i64(vc, va, pos, len - pos); 965 } else { 966 tcg_gen_movi_i64(vc, 0); 967 } 968 } else { 969 TCGv tmp = tcg_temp_new(); 970 TCGv shift = tcg_temp_new(); 971 972 /* The instruction description has us left-shift the byte mask 973 and extract bits <15:8> and apply that zap at the end. This 974 is equivalent to simply performing the zap first and shifting 975 afterward. */ 976 gen_zapnoti(tmp, va, byte_mask); 977 978 /* If (B & 7) == 0, we need to shift by 64 and leave a zero. Do this 979 portably by splitting the shift into two parts: shift_count-1 and 1. 980 Arrange for the -1 by using ones-complement instead of 981 twos-complement in the negation: ~(B * 8) & 63. */ 982 983 tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3); 984 tcg_gen_not_i64(shift, shift); 985 tcg_gen_andi_i64(shift, shift, 0x3f); 986 987 tcg_gen_shr_i64(vc, tmp, shift); 988 tcg_gen_shri_i64(vc, vc, 1); 989 tcg_temp_free(shift); 990 tcg_temp_free(tmp); 991 } 992 } 993 994 /* INSBL, INSWL, INSLL, INSQL */ 995 static void gen_ins_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit, 996 uint8_t lit, uint8_t byte_mask) 997 { 998 if (islit) { 999 int pos = (lit & 7) * 8; 1000 int len = cto32(byte_mask) * 8; 1001 if (pos + len > 64) { 1002 len = 64 - pos; 1003 } 1004 tcg_gen_deposit_z_i64(vc, va, pos, len); 1005 } else { 1006 TCGv tmp = tcg_temp_new(); 1007 TCGv shift = tcg_temp_new(); 1008 1009 /* The instruction description has us left-shift the byte mask 1010 and extract bits <15:8> and apply that zap at the end. This 1011 is equivalent to simply performing the zap first and shifting 1012 afterward. */ 1013 gen_zapnoti(tmp, va, byte_mask); 1014 1015 tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7); 1016 tcg_gen_shli_i64(shift, shift, 3); 1017 tcg_gen_shl_i64(vc, tmp, shift); 1018 tcg_temp_free(shift); 1019 tcg_temp_free(tmp); 1020 } 1021 } 1022 1023 /* MSKWH, MSKLH, MSKQH */ 1024 static void gen_msk_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit, 1025 uint8_t lit, uint8_t byte_mask) 1026 { 1027 if (islit) { 1028 gen_zapnoti(vc, va, ~((byte_mask << (lit & 7)) >> 8)); 1029 } else { 1030 TCGv shift = tcg_temp_new(); 1031 TCGv mask = tcg_temp_new(); 1032 1033 /* The instruction description is as above, where the byte_mask 1034 is shifted left, and then we extract bits <15:8>. This can be 1035 emulated with a right-shift on the expanded byte mask. This 1036 requires extra care because for an input <2:0> == 0 we need a 1037 shift of 64 bits in order to generate a zero. This is done by 1038 splitting the shift into two parts, the variable shift - 1 1039 followed by a constant 1 shift. The code we expand below is 1040 equivalent to ~(B * 8) & 63. */ 1041 1042 tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3); 1043 tcg_gen_not_i64(shift, shift); 1044 tcg_gen_andi_i64(shift, shift, 0x3f); 1045 tcg_gen_movi_i64(mask, zapnot_mask (byte_mask)); 1046 tcg_gen_shr_i64(mask, mask, shift); 1047 tcg_gen_shri_i64(mask, mask, 1); 1048 1049 tcg_gen_andc_i64(vc, va, mask); 1050 1051 tcg_temp_free(mask); 1052 tcg_temp_free(shift); 1053 } 1054 } 1055 1056 /* MSKBL, MSKWL, MSKLL, MSKQL */ 1057 static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit, 1058 uint8_t lit, uint8_t byte_mask) 1059 { 1060 if (islit) { 1061 gen_zapnoti(vc, va, ~(byte_mask << (lit & 7))); 1062 } else { 1063 TCGv shift = tcg_temp_new(); 1064 TCGv mask = tcg_temp_new(); 1065 1066 tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7); 1067 tcg_gen_shli_i64(shift, shift, 3); 1068 tcg_gen_movi_i64(mask, zapnot_mask(byte_mask)); 1069 tcg_gen_shl_i64(mask, mask, shift); 1070 1071 tcg_gen_andc_i64(vc, va, mask); 1072 1073 tcg_temp_free(mask); 1074 tcg_temp_free(shift); 1075 } 1076 } 1077 1078 static void gen_rx(DisasContext *ctx, int ra, int set) 1079 { 1080 if (ra != 31) { 1081 ld_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT); 1082 } 1083 1084 st_flag_byte(tcg_constant_i64(set), ENV_FLAG_RX_SHIFT); 1085 } 1086 1087 static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode) 1088 { 1089 /* We're emulating OSF/1 PALcode. Many of these are trivial access 1090 to internal cpu registers. */ 1091 1092 /* Unprivileged PAL call */ 1093 if (palcode >= 0x80 && palcode < 0xC0) { 1094 switch (palcode) { 1095 case 0x86: 1096 /* IMB */ 1097 /* No-op inside QEMU. */ 1098 break; 1099 case 0x9E: 1100 /* RDUNIQUE */ 1101 tcg_gen_ld_i64(ctx->ir[IR_V0], cpu_env, 1102 offsetof(CPUAlphaState, unique)); 1103 break; 1104 case 0x9F: 1105 /* WRUNIQUE */ 1106 tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env, 1107 offsetof(CPUAlphaState, unique)); 1108 break; 1109 default: 1110 palcode &= 0xbf; 1111 goto do_call_pal; 1112 } 1113 return DISAS_NEXT; 1114 } 1115 1116 #ifndef CONFIG_USER_ONLY 1117 /* Privileged PAL code */ 1118 if (palcode < 0x40 && (ctx->tbflags & ENV_FLAG_PS_USER) == 0) { 1119 switch (palcode) { 1120 case 0x01: 1121 /* CFLUSH */ 1122 /* No-op inside QEMU. */ 1123 break; 1124 case 0x02: 1125 /* DRAINA */ 1126 /* No-op inside QEMU. */ 1127 break; 1128 case 0x2D: 1129 /* WRVPTPTR */ 1130 tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env, 1131 offsetof(CPUAlphaState, vptptr)); 1132 break; 1133 case 0x31: 1134 /* WRVAL */ 1135 tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env, 1136 offsetof(CPUAlphaState, sysval)); 1137 break; 1138 case 0x32: 1139 /* RDVAL */ 1140 tcg_gen_ld_i64(ctx->ir[IR_V0], cpu_env, 1141 offsetof(CPUAlphaState, sysval)); 1142 break; 1143 1144 case 0x35: 1145 /* SWPIPL */ 1146 /* Note that we already know we're in kernel mode, so we know 1147 that PS only contains the 3 IPL bits. */ 1148 ld_flag_byte(ctx->ir[IR_V0], ENV_FLAG_PS_SHIFT); 1149 1150 /* But make sure and store only the 3 IPL bits from the user. */ 1151 { 1152 TCGv tmp = tcg_temp_new(); 1153 tcg_gen_andi_i64(tmp, ctx->ir[IR_A0], PS_INT_MASK); 1154 st_flag_byte(tmp, ENV_FLAG_PS_SHIFT); 1155 tcg_temp_free(tmp); 1156 } 1157 1158 /* Allow interrupts to be recognized right away. */ 1159 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next); 1160 return DISAS_PC_UPDATED_NOCHAIN; 1161 1162 case 0x36: 1163 /* RDPS */ 1164 ld_flag_byte(ctx->ir[IR_V0], ENV_FLAG_PS_SHIFT); 1165 break; 1166 1167 case 0x38: 1168 /* WRUSP */ 1169 tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env, 1170 offsetof(CPUAlphaState, usp)); 1171 break; 1172 case 0x3A: 1173 /* RDUSP */ 1174 tcg_gen_ld_i64(ctx->ir[IR_V0], cpu_env, 1175 offsetof(CPUAlphaState, usp)); 1176 break; 1177 case 0x3C: 1178 /* WHAMI */ 1179 tcg_gen_ld32s_i64(ctx->ir[IR_V0], cpu_env, 1180 -offsetof(AlphaCPU, env) + offsetof(CPUState, cpu_index)); 1181 break; 1182 1183 case 0x3E: 1184 /* WTINT */ 1185 tcg_gen_st_i32(tcg_constant_i32(1), cpu_env, 1186 -offsetof(AlphaCPU, env) + 1187 offsetof(CPUState, halted)); 1188 tcg_gen_movi_i64(ctx->ir[IR_V0], 0); 1189 return gen_excp(ctx, EXCP_HALTED, 0); 1190 1191 default: 1192 palcode &= 0x3f; 1193 goto do_call_pal; 1194 } 1195 return DISAS_NEXT; 1196 } 1197 #endif 1198 return gen_invalid(ctx); 1199 1200 do_call_pal: 1201 #ifdef CONFIG_USER_ONLY 1202 return gen_excp(ctx, EXCP_CALL_PAL, palcode); 1203 #else 1204 { 1205 TCGv tmp = tcg_temp_new(); 1206 uint64_t exc_addr = ctx->base.pc_next; 1207 uint64_t entry = ctx->palbr; 1208 1209 if (ctx->tbflags & ENV_FLAG_PAL_MODE) { 1210 exc_addr |= 1; 1211 } else { 1212 tcg_gen_movi_i64(tmp, 1); 1213 st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT); 1214 } 1215 1216 tcg_gen_movi_i64(tmp, exc_addr); 1217 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr)); 1218 tcg_temp_free(tmp); 1219 1220 entry += (palcode & 0x80 1221 ? 0x2000 + (palcode - 0x80) * 64 1222 : 0x1000 + palcode * 64); 1223 1224 tcg_gen_movi_i64(cpu_pc, entry); 1225 return DISAS_PC_UPDATED; 1226 } 1227 #endif 1228 } 1229 1230 #ifndef CONFIG_USER_ONLY 1231 1232 #define PR_LONG 0x200000 1233 1234 static int cpu_pr_data(int pr) 1235 { 1236 switch (pr) { 1237 case 2: return offsetof(CPUAlphaState, pcc_ofs) | PR_LONG; 1238 case 3: return offsetof(CPUAlphaState, trap_arg0); 1239 case 4: return offsetof(CPUAlphaState, trap_arg1); 1240 case 5: return offsetof(CPUAlphaState, trap_arg2); 1241 case 6: return offsetof(CPUAlphaState, exc_addr); 1242 case 7: return offsetof(CPUAlphaState, palbr); 1243 case 8: return offsetof(CPUAlphaState, ptbr); 1244 case 9: return offsetof(CPUAlphaState, vptptr); 1245 case 10: return offsetof(CPUAlphaState, unique); 1246 case 11: return offsetof(CPUAlphaState, sysval); 1247 case 12: return offsetof(CPUAlphaState, usp); 1248 1249 case 40 ... 63: 1250 return offsetof(CPUAlphaState, scratch[pr - 40]); 1251 1252 case 251: 1253 return offsetof(CPUAlphaState, alarm_expire); 1254 } 1255 return 0; 1256 } 1257 1258 static DisasJumpType gen_mfpr(DisasContext *ctx, TCGv va, int regno) 1259 { 1260 void (*helper)(TCGv); 1261 int data; 1262 1263 switch (regno) { 1264 case 32 ... 39: 1265 /* Accessing the "non-shadow" general registers. */ 1266 regno = regno == 39 ? 25 : regno - 32 + 8; 1267 tcg_gen_mov_i64(va, cpu_std_ir[regno]); 1268 break; 1269 1270 case 250: /* WALLTIME */ 1271 helper = gen_helper_get_walltime; 1272 goto do_helper; 1273 case 249: /* VMTIME */ 1274 helper = gen_helper_get_vmtime; 1275 do_helper: 1276 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { 1277 gen_io_start(); 1278 helper(va); 1279 return DISAS_PC_STALE; 1280 } else { 1281 helper(va); 1282 } 1283 break; 1284 1285 case 0: /* PS */ 1286 ld_flag_byte(va, ENV_FLAG_PS_SHIFT); 1287 break; 1288 case 1: /* FEN */ 1289 ld_flag_byte(va, ENV_FLAG_FEN_SHIFT); 1290 break; 1291 1292 default: 1293 /* The basic registers are data only, and unknown registers 1294 are read-zero, write-ignore. */ 1295 data = cpu_pr_data(regno); 1296 if (data == 0) { 1297 tcg_gen_movi_i64(va, 0); 1298 } else if (data & PR_LONG) { 1299 tcg_gen_ld32s_i64(va, cpu_env, data & ~PR_LONG); 1300 } else { 1301 tcg_gen_ld_i64(va, cpu_env, data); 1302 } 1303 break; 1304 } 1305 1306 return DISAS_NEXT; 1307 } 1308 1309 static DisasJumpType gen_mtpr(DisasContext *ctx, TCGv vb, int regno) 1310 { 1311 int data; 1312 DisasJumpType ret = DISAS_NEXT; 1313 1314 switch (regno) { 1315 case 255: 1316 /* TBIA */ 1317 gen_helper_tbia(cpu_env); 1318 break; 1319 1320 case 254: 1321 /* TBIS */ 1322 gen_helper_tbis(cpu_env, vb); 1323 break; 1324 1325 case 253: 1326 /* WAIT */ 1327 tcg_gen_st_i32(tcg_constant_i32(1), cpu_env, 1328 -offsetof(AlphaCPU, env) + offsetof(CPUState, halted)); 1329 return gen_excp(ctx, EXCP_HALTED, 0); 1330 1331 case 252: 1332 /* HALT */ 1333 gen_helper_halt(vb); 1334 return DISAS_PC_STALE; 1335 1336 case 251: 1337 /* ALARM */ 1338 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { 1339 gen_io_start(); 1340 ret = DISAS_PC_STALE; 1341 } 1342 gen_helper_set_alarm(cpu_env, vb); 1343 break; 1344 1345 case 7: 1346 /* PALBR */ 1347 tcg_gen_st_i64(vb, cpu_env, offsetof(CPUAlphaState, palbr)); 1348 /* Changing the PAL base register implies un-chaining all of the TBs 1349 that ended with a CALL_PAL. Since the base register usually only 1350 changes during boot, flushing everything works well. */ 1351 gen_helper_tb_flush(cpu_env); 1352 return DISAS_PC_STALE; 1353 1354 case 32 ... 39: 1355 /* Accessing the "non-shadow" general registers. */ 1356 regno = regno == 39 ? 25 : regno - 32 + 8; 1357 tcg_gen_mov_i64(cpu_std_ir[regno], vb); 1358 break; 1359 1360 case 0: /* PS */ 1361 st_flag_byte(vb, ENV_FLAG_PS_SHIFT); 1362 break; 1363 case 1: /* FEN */ 1364 st_flag_byte(vb, ENV_FLAG_FEN_SHIFT); 1365 break; 1366 1367 default: 1368 /* The basic registers are data only, and unknown registers 1369 are read-zero, write-ignore. */ 1370 data = cpu_pr_data(regno); 1371 if (data != 0) { 1372 if (data & PR_LONG) { 1373 tcg_gen_st32_i64(vb, cpu_env, data & ~PR_LONG); 1374 } else { 1375 tcg_gen_st_i64(vb, cpu_env, data); 1376 } 1377 } 1378 break; 1379 } 1380 1381 return ret; 1382 } 1383 #endif /* !USER_ONLY*/ 1384 1385 #define REQUIRE_NO_LIT \ 1386 do { \ 1387 if (real_islit) { \ 1388 goto invalid_opc; \ 1389 } \ 1390 } while (0) 1391 1392 #define REQUIRE_AMASK(FLAG) \ 1393 do { \ 1394 if ((ctx->amask & AMASK_##FLAG) == 0) { \ 1395 goto invalid_opc; \ 1396 } \ 1397 } while (0) 1398 1399 #define REQUIRE_TB_FLAG(FLAG) \ 1400 do { \ 1401 if ((ctx->tbflags & (FLAG)) == 0) { \ 1402 goto invalid_opc; \ 1403 } \ 1404 } while (0) 1405 1406 #define REQUIRE_REG_31(WHICH) \ 1407 do { \ 1408 if (WHICH != 31) { \ 1409 goto invalid_opc; \ 1410 } \ 1411 } while (0) 1412 1413 #define REQUIRE_FEN \ 1414 do { \ 1415 if (!(ctx->tbflags & ENV_FLAG_FEN)) { \ 1416 goto raise_fen; \ 1417 } \ 1418 } while (0) 1419 1420 static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) 1421 { 1422 int32_t disp21, disp16, disp12 __attribute__((unused)); 1423 uint16_t fn11; 1424 uint8_t opc, ra, rb, rc, fpfn, fn7, lit; 1425 bool islit, real_islit; 1426 TCGv va, vb, vc, tmp, tmp2; 1427 TCGv_i32 t32; 1428 DisasJumpType ret; 1429 1430 /* Decode all instruction fields */ 1431 opc = extract32(insn, 26, 6); 1432 ra = extract32(insn, 21, 5); 1433 rb = extract32(insn, 16, 5); 1434 rc = extract32(insn, 0, 5); 1435 real_islit = islit = extract32(insn, 12, 1); 1436 lit = extract32(insn, 13, 8); 1437 1438 disp21 = sextract32(insn, 0, 21); 1439 disp16 = sextract32(insn, 0, 16); 1440 disp12 = sextract32(insn, 0, 12); 1441 1442 fn11 = extract32(insn, 5, 11); 1443 fpfn = extract32(insn, 5, 6); 1444 fn7 = extract32(insn, 5, 7); 1445 1446 if (rb == 31 && !islit) { 1447 islit = true; 1448 lit = 0; 1449 } 1450 1451 ret = DISAS_NEXT; 1452 switch (opc) { 1453 case 0x00: 1454 /* CALL_PAL */ 1455 ret = gen_call_pal(ctx, insn & 0x03ffffff); 1456 break; 1457 case 0x01: 1458 /* OPC01 */ 1459 goto invalid_opc; 1460 case 0x02: 1461 /* OPC02 */ 1462 goto invalid_opc; 1463 case 0x03: 1464 /* OPC03 */ 1465 goto invalid_opc; 1466 case 0x04: 1467 /* OPC04 */ 1468 goto invalid_opc; 1469 case 0x05: 1470 /* OPC05 */ 1471 goto invalid_opc; 1472 case 0x06: 1473 /* OPC06 */ 1474 goto invalid_opc; 1475 case 0x07: 1476 /* OPC07 */ 1477 goto invalid_opc; 1478 1479 case 0x09: 1480 /* LDAH */ 1481 disp16 = (uint32_t)disp16 << 16; 1482 /* fall through */ 1483 case 0x08: 1484 /* LDA */ 1485 va = dest_gpr(ctx, ra); 1486 /* It's worth special-casing immediate loads. */ 1487 if (rb == 31) { 1488 tcg_gen_movi_i64(va, disp16); 1489 } else { 1490 tcg_gen_addi_i64(va, load_gpr(ctx, rb), disp16); 1491 } 1492 break; 1493 1494 case 0x0A: 1495 /* LDBU */ 1496 REQUIRE_AMASK(BWX); 1497 gen_load_int(ctx, ra, rb, disp16, MO_UB, 0, 0); 1498 break; 1499 case 0x0B: 1500 /* LDQ_U */ 1501 gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 1, 0); 1502 break; 1503 case 0x0C: 1504 /* LDWU */ 1505 REQUIRE_AMASK(BWX); 1506 gen_load_int(ctx, ra, rb, disp16, MO_LEUW, 0, 0); 1507 break; 1508 case 0x0D: 1509 /* STW */ 1510 REQUIRE_AMASK(BWX); 1511 gen_store_int(ctx, ra, rb, disp16, MO_LEUW, 0); 1512 break; 1513 case 0x0E: 1514 /* STB */ 1515 REQUIRE_AMASK(BWX); 1516 gen_store_int(ctx, ra, rb, disp16, MO_UB, 0); 1517 break; 1518 case 0x0F: 1519 /* STQ_U */ 1520 gen_store_int(ctx, ra, rb, disp16, MO_LEUQ, 1); 1521 break; 1522 1523 case 0x10: 1524 vc = dest_gpr(ctx, rc); 1525 vb = load_gpr_lit(ctx, rb, lit, islit); 1526 1527 if (ra == 31) { 1528 if (fn7 == 0x00) { 1529 /* Special case ADDL as SEXTL. */ 1530 tcg_gen_ext32s_i64(vc, vb); 1531 break; 1532 } 1533 if (fn7 == 0x29) { 1534 /* Special case SUBQ as NEGQ. */ 1535 tcg_gen_neg_i64(vc, vb); 1536 break; 1537 } 1538 } 1539 1540 va = load_gpr(ctx, ra); 1541 switch (fn7) { 1542 case 0x00: 1543 /* ADDL */ 1544 tcg_gen_add_i64(vc, va, vb); 1545 tcg_gen_ext32s_i64(vc, vc); 1546 break; 1547 case 0x02: 1548 /* S4ADDL */ 1549 tmp = tcg_temp_new(); 1550 tcg_gen_shli_i64(tmp, va, 2); 1551 tcg_gen_add_i64(tmp, tmp, vb); 1552 tcg_gen_ext32s_i64(vc, tmp); 1553 tcg_temp_free(tmp); 1554 break; 1555 case 0x09: 1556 /* SUBL */ 1557 tcg_gen_sub_i64(vc, va, vb); 1558 tcg_gen_ext32s_i64(vc, vc); 1559 break; 1560 case 0x0B: 1561 /* S4SUBL */ 1562 tmp = tcg_temp_new(); 1563 tcg_gen_shli_i64(tmp, va, 2); 1564 tcg_gen_sub_i64(tmp, tmp, vb); 1565 tcg_gen_ext32s_i64(vc, tmp); 1566 tcg_temp_free(tmp); 1567 break; 1568 case 0x0F: 1569 /* CMPBGE */ 1570 if (ra == 31) { 1571 /* Special case 0 >= X as X == 0. */ 1572 gen_helper_cmpbe0(vc, vb); 1573 } else { 1574 gen_helper_cmpbge(vc, va, vb); 1575 } 1576 break; 1577 case 0x12: 1578 /* S8ADDL */ 1579 tmp = tcg_temp_new(); 1580 tcg_gen_shli_i64(tmp, va, 3); 1581 tcg_gen_add_i64(tmp, tmp, vb); 1582 tcg_gen_ext32s_i64(vc, tmp); 1583 tcg_temp_free(tmp); 1584 break; 1585 case 0x1B: 1586 /* S8SUBL */ 1587 tmp = tcg_temp_new(); 1588 tcg_gen_shli_i64(tmp, va, 3); 1589 tcg_gen_sub_i64(tmp, tmp, vb); 1590 tcg_gen_ext32s_i64(vc, tmp); 1591 tcg_temp_free(tmp); 1592 break; 1593 case 0x1D: 1594 /* CMPULT */ 1595 tcg_gen_setcond_i64(TCG_COND_LTU, vc, va, vb); 1596 break; 1597 case 0x20: 1598 /* ADDQ */ 1599 tcg_gen_add_i64(vc, va, vb); 1600 break; 1601 case 0x22: 1602 /* S4ADDQ */ 1603 tmp = tcg_temp_new(); 1604 tcg_gen_shli_i64(tmp, va, 2); 1605 tcg_gen_add_i64(vc, tmp, vb); 1606 tcg_temp_free(tmp); 1607 break; 1608 case 0x29: 1609 /* SUBQ */ 1610 tcg_gen_sub_i64(vc, va, vb); 1611 break; 1612 case 0x2B: 1613 /* S4SUBQ */ 1614 tmp = tcg_temp_new(); 1615 tcg_gen_shli_i64(tmp, va, 2); 1616 tcg_gen_sub_i64(vc, tmp, vb); 1617 tcg_temp_free(tmp); 1618 break; 1619 case 0x2D: 1620 /* CMPEQ */ 1621 tcg_gen_setcond_i64(TCG_COND_EQ, vc, va, vb); 1622 break; 1623 case 0x32: 1624 /* S8ADDQ */ 1625 tmp = tcg_temp_new(); 1626 tcg_gen_shli_i64(tmp, va, 3); 1627 tcg_gen_add_i64(vc, tmp, vb); 1628 tcg_temp_free(tmp); 1629 break; 1630 case 0x3B: 1631 /* S8SUBQ */ 1632 tmp = tcg_temp_new(); 1633 tcg_gen_shli_i64(tmp, va, 3); 1634 tcg_gen_sub_i64(vc, tmp, vb); 1635 tcg_temp_free(tmp); 1636 break; 1637 case 0x3D: 1638 /* CMPULE */ 1639 tcg_gen_setcond_i64(TCG_COND_LEU, vc, va, vb); 1640 break; 1641 case 0x40: 1642 /* ADDL/V */ 1643 tmp = tcg_temp_new(); 1644 tcg_gen_ext32s_i64(tmp, va); 1645 tcg_gen_ext32s_i64(vc, vb); 1646 tcg_gen_add_i64(tmp, tmp, vc); 1647 tcg_gen_ext32s_i64(vc, tmp); 1648 gen_helper_check_overflow(cpu_env, vc, tmp); 1649 tcg_temp_free(tmp); 1650 break; 1651 case 0x49: 1652 /* SUBL/V */ 1653 tmp = tcg_temp_new(); 1654 tcg_gen_ext32s_i64(tmp, va); 1655 tcg_gen_ext32s_i64(vc, vb); 1656 tcg_gen_sub_i64(tmp, tmp, vc); 1657 tcg_gen_ext32s_i64(vc, tmp); 1658 gen_helper_check_overflow(cpu_env, vc, tmp); 1659 tcg_temp_free(tmp); 1660 break; 1661 case 0x4D: 1662 /* CMPLT */ 1663 tcg_gen_setcond_i64(TCG_COND_LT, vc, va, vb); 1664 break; 1665 case 0x60: 1666 /* ADDQ/V */ 1667 tmp = tcg_temp_new(); 1668 tmp2 = tcg_temp_new(); 1669 tcg_gen_eqv_i64(tmp, va, vb); 1670 tcg_gen_mov_i64(tmp2, va); 1671 tcg_gen_add_i64(vc, va, vb); 1672 tcg_gen_xor_i64(tmp2, tmp2, vc); 1673 tcg_gen_and_i64(tmp, tmp, tmp2); 1674 tcg_gen_shri_i64(tmp, tmp, 63); 1675 tcg_gen_movi_i64(tmp2, 0); 1676 gen_helper_check_overflow(cpu_env, tmp, tmp2); 1677 tcg_temp_free(tmp); 1678 tcg_temp_free(tmp2); 1679 break; 1680 case 0x69: 1681 /* SUBQ/V */ 1682 tmp = tcg_temp_new(); 1683 tmp2 = tcg_temp_new(); 1684 tcg_gen_xor_i64(tmp, va, vb); 1685 tcg_gen_mov_i64(tmp2, va); 1686 tcg_gen_sub_i64(vc, va, vb); 1687 tcg_gen_xor_i64(tmp2, tmp2, vc); 1688 tcg_gen_and_i64(tmp, tmp, tmp2); 1689 tcg_gen_shri_i64(tmp, tmp, 63); 1690 tcg_gen_movi_i64(tmp2, 0); 1691 gen_helper_check_overflow(cpu_env, tmp, tmp2); 1692 tcg_temp_free(tmp); 1693 tcg_temp_free(tmp2); 1694 break; 1695 case 0x6D: 1696 /* CMPLE */ 1697 tcg_gen_setcond_i64(TCG_COND_LE, vc, va, vb); 1698 break; 1699 default: 1700 goto invalid_opc; 1701 } 1702 break; 1703 1704 case 0x11: 1705 if (fn7 == 0x20) { 1706 if (rc == 31) { 1707 /* Special case BIS as NOP. */ 1708 break; 1709 } 1710 if (ra == 31) { 1711 /* Special case BIS as MOV. */ 1712 vc = dest_gpr(ctx, rc); 1713 if (islit) { 1714 tcg_gen_movi_i64(vc, lit); 1715 } else { 1716 tcg_gen_mov_i64(vc, load_gpr(ctx, rb)); 1717 } 1718 break; 1719 } 1720 } 1721 1722 vc = dest_gpr(ctx, rc); 1723 vb = load_gpr_lit(ctx, rb, lit, islit); 1724 1725 if (fn7 == 0x28 && ra == 31) { 1726 /* Special case ORNOT as NOT. */ 1727 tcg_gen_not_i64(vc, vb); 1728 break; 1729 } 1730 1731 va = load_gpr(ctx, ra); 1732 switch (fn7) { 1733 case 0x00: 1734 /* AND */ 1735 tcg_gen_and_i64(vc, va, vb); 1736 break; 1737 case 0x08: 1738 /* BIC */ 1739 tcg_gen_andc_i64(vc, va, vb); 1740 break; 1741 case 0x14: 1742 /* CMOVLBS */ 1743 tmp = tcg_temp_new(); 1744 tcg_gen_andi_i64(tmp, va, 1); 1745 tcg_gen_movcond_i64(TCG_COND_NE, vc, tmp, load_zero(ctx), 1746 vb, load_gpr(ctx, rc)); 1747 tcg_temp_free(tmp); 1748 break; 1749 case 0x16: 1750 /* CMOVLBC */ 1751 tmp = tcg_temp_new(); 1752 tcg_gen_andi_i64(tmp, va, 1); 1753 tcg_gen_movcond_i64(TCG_COND_EQ, vc, tmp, load_zero(ctx), 1754 vb, load_gpr(ctx, rc)); 1755 tcg_temp_free(tmp); 1756 break; 1757 case 0x20: 1758 /* BIS */ 1759 tcg_gen_or_i64(vc, va, vb); 1760 break; 1761 case 0x24: 1762 /* CMOVEQ */ 1763 tcg_gen_movcond_i64(TCG_COND_EQ, vc, va, load_zero(ctx), 1764 vb, load_gpr(ctx, rc)); 1765 break; 1766 case 0x26: 1767 /* CMOVNE */ 1768 tcg_gen_movcond_i64(TCG_COND_NE, vc, va, load_zero(ctx), 1769 vb, load_gpr(ctx, rc)); 1770 break; 1771 case 0x28: 1772 /* ORNOT */ 1773 tcg_gen_orc_i64(vc, va, vb); 1774 break; 1775 case 0x40: 1776 /* XOR */ 1777 tcg_gen_xor_i64(vc, va, vb); 1778 break; 1779 case 0x44: 1780 /* CMOVLT */ 1781 tcg_gen_movcond_i64(TCG_COND_LT, vc, va, load_zero(ctx), 1782 vb, load_gpr(ctx, rc)); 1783 break; 1784 case 0x46: 1785 /* CMOVGE */ 1786 tcg_gen_movcond_i64(TCG_COND_GE, vc, va, load_zero(ctx), 1787 vb, load_gpr(ctx, rc)); 1788 break; 1789 case 0x48: 1790 /* EQV */ 1791 tcg_gen_eqv_i64(vc, va, vb); 1792 break; 1793 case 0x61: 1794 /* AMASK */ 1795 REQUIRE_REG_31(ra); 1796 tcg_gen_andi_i64(vc, vb, ~ctx->amask); 1797 break; 1798 case 0x64: 1799 /* CMOVLE */ 1800 tcg_gen_movcond_i64(TCG_COND_LE, vc, va, load_zero(ctx), 1801 vb, load_gpr(ctx, rc)); 1802 break; 1803 case 0x66: 1804 /* CMOVGT */ 1805 tcg_gen_movcond_i64(TCG_COND_GT, vc, va, load_zero(ctx), 1806 vb, load_gpr(ctx, rc)); 1807 break; 1808 case 0x6C: 1809 /* IMPLVER */ 1810 REQUIRE_REG_31(ra); 1811 tcg_gen_movi_i64(vc, ctx->implver); 1812 break; 1813 default: 1814 goto invalid_opc; 1815 } 1816 break; 1817 1818 case 0x12: 1819 vc = dest_gpr(ctx, rc); 1820 va = load_gpr(ctx, ra); 1821 switch (fn7) { 1822 case 0x02: 1823 /* MSKBL */ 1824 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x01); 1825 break; 1826 case 0x06: 1827 /* EXTBL */ 1828 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x01); 1829 break; 1830 case 0x0B: 1831 /* INSBL */ 1832 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x01); 1833 break; 1834 case 0x12: 1835 /* MSKWL */ 1836 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x03); 1837 break; 1838 case 0x16: 1839 /* EXTWL */ 1840 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x03); 1841 break; 1842 case 0x1B: 1843 /* INSWL */ 1844 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x03); 1845 break; 1846 case 0x22: 1847 /* MSKLL */ 1848 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x0f); 1849 break; 1850 case 0x26: 1851 /* EXTLL */ 1852 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x0f); 1853 break; 1854 case 0x2B: 1855 /* INSLL */ 1856 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x0f); 1857 break; 1858 case 0x30: 1859 /* ZAP */ 1860 if (islit) { 1861 gen_zapnoti(vc, va, ~lit); 1862 } else { 1863 gen_helper_zap(vc, va, load_gpr(ctx, rb)); 1864 } 1865 break; 1866 case 0x31: 1867 /* ZAPNOT */ 1868 if (islit) { 1869 gen_zapnoti(vc, va, lit); 1870 } else { 1871 gen_helper_zapnot(vc, va, load_gpr(ctx, rb)); 1872 } 1873 break; 1874 case 0x32: 1875 /* MSKQL */ 1876 gen_msk_l(ctx, vc, va, rb, islit, lit, 0xff); 1877 break; 1878 case 0x34: 1879 /* SRL */ 1880 if (islit) { 1881 tcg_gen_shri_i64(vc, va, lit & 0x3f); 1882 } else { 1883 tmp = tcg_temp_new(); 1884 vb = load_gpr(ctx, rb); 1885 tcg_gen_andi_i64(tmp, vb, 0x3f); 1886 tcg_gen_shr_i64(vc, va, tmp); 1887 tcg_temp_free(tmp); 1888 } 1889 break; 1890 case 0x36: 1891 /* EXTQL */ 1892 gen_ext_l(ctx, vc, va, rb, islit, lit, 0xff); 1893 break; 1894 case 0x39: 1895 /* SLL */ 1896 if (islit) { 1897 tcg_gen_shli_i64(vc, va, lit & 0x3f); 1898 } else { 1899 tmp = tcg_temp_new(); 1900 vb = load_gpr(ctx, rb); 1901 tcg_gen_andi_i64(tmp, vb, 0x3f); 1902 tcg_gen_shl_i64(vc, va, tmp); 1903 tcg_temp_free(tmp); 1904 } 1905 break; 1906 case 0x3B: 1907 /* INSQL */ 1908 gen_ins_l(ctx, vc, va, rb, islit, lit, 0xff); 1909 break; 1910 case 0x3C: 1911 /* SRA */ 1912 if (islit) { 1913 tcg_gen_sari_i64(vc, va, lit & 0x3f); 1914 } else { 1915 tmp = tcg_temp_new(); 1916 vb = load_gpr(ctx, rb); 1917 tcg_gen_andi_i64(tmp, vb, 0x3f); 1918 tcg_gen_sar_i64(vc, va, tmp); 1919 tcg_temp_free(tmp); 1920 } 1921 break; 1922 case 0x52: 1923 /* MSKWH */ 1924 gen_msk_h(ctx, vc, va, rb, islit, lit, 0x03); 1925 break; 1926 case 0x57: 1927 /* INSWH */ 1928 gen_ins_h(ctx, vc, va, rb, islit, lit, 0x03); 1929 break; 1930 case 0x5A: 1931 /* EXTWH */ 1932 gen_ext_h(ctx, vc, va, rb, islit, lit, 0x03); 1933 break; 1934 case 0x62: 1935 /* MSKLH */ 1936 gen_msk_h(ctx, vc, va, rb, islit, lit, 0x0f); 1937 break; 1938 case 0x67: 1939 /* INSLH */ 1940 gen_ins_h(ctx, vc, va, rb, islit, lit, 0x0f); 1941 break; 1942 case 0x6A: 1943 /* EXTLH */ 1944 gen_ext_h(ctx, vc, va, rb, islit, lit, 0x0f); 1945 break; 1946 case 0x72: 1947 /* MSKQH */ 1948 gen_msk_h(ctx, vc, va, rb, islit, lit, 0xff); 1949 break; 1950 case 0x77: 1951 /* INSQH */ 1952 gen_ins_h(ctx, vc, va, rb, islit, lit, 0xff); 1953 break; 1954 case 0x7A: 1955 /* EXTQH */ 1956 gen_ext_h(ctx, vc, va, rb, islit, lit, 0xff); 1957 break; 1958 default: 1959 goto invalid_opc; 1960 } 1961 break; 1962 1963 case 0x13: 1964 vc = dest_gpr(ctx, rc); 1965 vb = load_gpr_lit(ctx, rb, lit, islit); 1966 va = load_gpr(ctx, ra); 1967 switch (fn7) { 1968 case 0x00: 1969 /* MULL */ 1970 tcg_gen_mul_i64(vc, va, vb); 1971 tcg_gen_ext32s_i64(vc, vc); 1972 break; 1973 case 0x20: 1974 /* MULQ */ 1975 tcg_gen_mul_i64(vc, va, vb); 1976 break; 1977 case 0x30: 1978 /* UMULH */ 1979 tmp = tcg_temp_new(); 1980 tcg_gen_mulu2_i64(tmp, vc, va, vb); 1981 tcg_temp_free(tmp); 1982 break; 1983 case 0x40: 1984 /* MULL/V */ 1985 tmp = tcg_temp_new(); 1986 tcg_gen_ext32s_i64(tmp, va); 1987 tcg_gen_ext32s_i64(vc, vb); 1988 tcg_gen_mul_i64(tmp, tmp, vc); 1989 tcg_gen_ext32s_i64(vc, tmp); 1990 gen_helper_check_overflow(cpu_env, vc, tmp); 1991 tcg_temp_free(tmp); 1992 break; 1993 case 0x60: 1994 /* MULQ/V */ 1995 tmp = tcg_temp_new(); 1996 tmp2 = tcg_temp_new(); 1997 tcg_gen_muls2_i64(vc, tmp, va, vb); 1998 tcg_gen_sari_i64(tmp2, vc, 63); 1999 gen_helper_check_overflow(cpu_env, tmp, tmp2); 2000 tcg_temp_free(tmp); 2001 tcg_temp_free(tmp2); 2002 break; 2003 default: 2004 goto invalid_opc; 2005 } 2006 break; 2007 2008 case 0x14: 2009 REQUIRE_AMASK(FIX); 2010 vc = dest_fpr(ctx, rc); 2011 switch (fpfn) { /* fn11 & 0x3F */ 2012 case 0x04: 2013 /* ITOFS */ 2014 REQUIRE_REG_31(rb); 2015 REQUIRE_FEN; 2016 t32 = tcg_temp_new_i32(); 2017 va = load_gpr(ctx, ra); 2018 tcg_gen_extrl_i64_i32(t32, va); 2019 gen_helper_memory_to_s(vc, t32); 2020 tcg_temp_free_i32(t32); 2021 break; 2022 case 0x0A: 2023 /* SQRTF */ 2024 REQUIRE_REG_31(ra); 2025 REQUIRE_FEN; 2026 vb = load_fpr(ctx, rb); 2027 gen_helper_sqrtf(vc, cpu_env, vb); 2028 break; 2029 case 0x0B: 2030 /* SQRTS */ 2031 REQUIRE_REG_31(ra); 2032 REQUIRE_FEN; 2033 gen_sqrts(ctx, rb, rc, fn11); 2034 break; 2035 case 0x14: 2036 /* ITOFF */ 2037 REQUIRE_REG_31(rb); 2038 REQUIRE_FEN; 2039 t32 = tcg_temp_new_i32(); 2040 va = load_gpr(ctx, ra); 2041 tcg_gen_extrl_i64_i32(t32, va); 2042 gen_helper_memory_to_f(vc, t32); 2043 tcg_temp_free_i32(t32); 2044 break; 2045 case 0x24: 2046 /* ITOFT */ 2047 REQUIRE_REG_31(rb); 2048 REQUIRE_FEN; 2049 va = load_gpr(ctx, ra); 2050 tcg_gen_mov_i64(vc, va); 2051 break; 2052 case 0x2A: 2053 /* SQRTG */ 2054 REQUIRE_REG_31(ra); 2055 REQUIRE_FEN; 2056 vb = load_fpr(ctx, rb); 2057 gen_helper_sqrtg(vc, cpu_env, vb); 2058 break; 2059 case 0x02B: 2060 /* SQRTT */ 2061 REQUIRE_REG_31(ra); 2062 REQUIRE_FEN; 2063 gen_sqrtt(ctx, rb, rc, fn11); 2064 break; 2065 default: 2066 goto invalid_opc; 2067 } 2068 break; 2069 2070 case 0x15: 2071 /* VAX floating point */ 2072 /* XXX: rounding mode and trap are ignored (!) */ 2073 vc = dest_fpr(ctx, rc); 2074 vb = load_fpr(ctx, rb); 2075 va = load_fpr(ctx, ra); 2076 switch (fpfn) { /* fn11 & 0x3F */ 2077 case 0x00: 2078 /* ADDF */ 2079 REQUIRE_FEN; 2080 gen_helper_addf(vc, cpu_env, va, vb); 2081 break; 2082 case 0x01: 2083 /* SUBF */ 2084 REQUIRE_FEN; 2085 gen_helper_subf(vc, cpu_env, va, vb); 2086 break; 2087 case 0x02: 2088 /* MULF */ 2089 REQUIRE_FEN; 2090 gen_helper_mulf(vc, cpu_env, va, vb); 2091 break; 2092 case 0x03: 2093 /* DIVF */ 2094 REQUIRE_FEN; 2095 gen_helper_divf(vc, cpu_env, va, vb); 2096 break; 2097 case 0x1E: 2098 /* CVTDG -- TODO */ 2099 REQUIRE_REG_31(ra); 2100 goto invalid_opc; 2101 case 0x20: 2102 /* ADDG */ 2103 REQUIRE_FEN; 2104 gen_helper_addg(vc, cpu_env, va, vb); 2105 break; 2106 case 0x21: 2107 /* SUBG */ 2108 REQUIRE_FEN; 2109 gen_helper_subg(vc, cpu_env, va, vb); 2110 break; 2111 case 0x22: 2112 /* MULG */ 2113 REQUIRE_FEN; 2114 gen_helper_mulg(vc, cpu_env, va, vb); 2115 break; 2116 case 0x23: 2117 /* DIVG */ 2118 REQUIRE_FEN; 2119 gen_helper_divg(vc, cpu_env, va, vb); 2120 break; 2121 case 0x25: 2122 /* CMPGEQ */ 2123 REQUIRE_FEN; 2124 gen_helper_cmpgeq(vc, cpu_env, va, vb); 2125 break; 2126 case 0x26: 2127 /* CMPGLT */ 2128 REQUIRE_FEN; 2129 gen_helper_cmpglt(vc, cpu_env, va, vb); 2130 break; 2131 case 0x27: 2132 /* CMPGLE */ 2133 REQUIRE_FEN; 2134 gen_helper_cmpgle(vc, cpu_env, va, vb); 2135 break; 2136 case 0x2C: 2137 /* CVTGF */ 2138 REQUIRE_REG_31(ra); 2139 REQUIRE_FEN; 2140 gen_helper_cvtgf(vc, cpu_env, vb); 2141 break; 2142 case 0x2D: 2143 /* CVTGD -- TODO */ 2144 REQUIRE_REG_31(ra); 2145 goto invalid_opc; 2146 case 0x2F: 2147 /* CVTGQ */ 2148 REQUIRE_REG_31(ra); 2149 REQUIRE_FEN; 2150 gen_helper_cvtgq(vc, cpu_env, vb); 2151 break; 2152 case 0x3C: 2153 /* CVTQF */ 2154 REQUIRE_REG_31(ra); 2155 REQUIRE_FEN; 2156 gen_helper_cvtqf(vc, cpu_env, vb); 2157 break; 2158 case 0x3E: 2159 /* CVTQG */ 2160 REQUIRE_REG_31(ra); 2161 REQUIRE_FEN; 2162 gen_helper_cvtqg(vc, cpu_env, vb); 2163 break; 2164 default: 2165 goto invalid_opc; 2166 } 2167 break; 2168 2169 case 0x16: 2170 /* IEEE floating-point */ 2171 switch (fpfn) { /* fn11 & 0x3F */ 2172 case 0x00: 2173 /* ADDS */ 2174 REQUIRE_FEN; 2175 gen_adds(ctx, ra, rb, rc, fn11); 2176 break; 2177 case 0x01: 2178 /* SUBS */ 2179 REQUIRE_FEN; 2180 gen_subs(ctx, ra, rb, rc, fn11); 2181 break; 2182 case 0x02: 2183 /* MULS */ 2184 REQUIRE_FEN; 2185 gen_muls(ctx, ra, rb, rc, fn11); 2186 break; 2187 case 0x03: 2188 /* DIVS */ 2189 REQUIRE_FEN; 2190 gen_divs(ctx, ra, rb, rc, fn11); 2191 break; 2192 case 0x20: 2193 /* ADDT */ 2194 REQUIRE_FEN; 2195 gen_addt(ctx, ra, rb, rc, fn11); 2196 break; 2197 case 0x21: 2198 /* SUBT */ 2199 REQUIRE_FEN; 2200 gen_subt(ctx, ra, rb, rc, fn11); 2201 break; 2202 case 0x22: 2203 /* MULT */ 2204 REQUIRE_FEN; 2205 gen_mult(ctx, ra, rb, rc, fn11); 2206 break; 2207 case 0x23: 2208 /* DIVT */ 2209 REQUIRE_FEN; 2210 gen_divt(ctx, ra, rb, rc, fn11); 2211 break; 2212 case 0x24: 2213 /* CMPTUN */ 2214 REQUIRE_FEN; 2215 gen_cmptun(ctx, ra, rb, rc, fn11); 2216 break; 2217 case 0x25: 2218 /* CMPTEQ */ 2219 REQUIRE_FEN; 2220 gen_cmpteq(ctx, ra, rb, rc, fn11); 2221 break; 2222 case 0x26: 2223 /* CMPTLT */ 2224 REQUIRE_FEN; 2225 gen_cmptlt(ctx, ra, rb, rc, fn11); 2226 break; 2227 case 0x27: 2228 /* CMPTLE */ 2229 REQUIRE_FEN; 2230 gen_cmptle(ctx, ra, rb, rc, fn11); 2231 break; 2232 case 0x2C: 2233 REQUIRE_REG_31(ra); 2234 REQUIRE_FEN; 2235 if (fn11 == 0x2AC || fn11 == 0x6AC) { 2236 /* CVTST */ 2237 gen_cvtst(ctx, rb, rc, fn11); 2238 } else { 2239 /* CVTTS */ 2240 gen_cvtts(ctx, rb, rc, fn11); 2241 } 2242 break; 2243 case 0x2F: 2244 /* CVTTQ */ 2245 REQUIRE_REG_31(ra); 2246 REQUIRE_FEN; 2247 gen_cvttq(ctx, rb, rc, fn11); 2248 break; 2249 case 0x3C: 2250 /* CVTQS */ 2251 REQUIRE_REG_31(ra); 2252 REQUIRE_FEN; 2253 gen_cvtqs(ctx, rb, rc, fn11); 2254 break; 2255 case 0x3E: 2256 /* CVTQT */ 2257 REQUIRE_REG_31(ra); 2258 REQUIRE_FEN; 2259 gen_cvtqt(ctx, rb, rc, fn11); 2260 break; 2261 default: 2262 goto invalid_opc; 2263 } 2264 break; 2265 2266 case 0x17: 2267 switch (fn11) { 2268 case 0x010: 2269 /* CVTLQ */ 2270 REQUIRE_REG_31(ra); 2271 REQUIRE_FEN; 2272 vc = dest_fpr(ctx, rc); 2273 vb = load_fpr(ctx, rb); 2274 gen_cvtlq(vc, vb); 2275 break; 2276 case 0x020: 2277 /* CPYS */ 2278 REQUIRE_FEN; 2279 if (rc == 31) { 2280 /* Special case CPYS as FNOP. */ 2281 } else { 2282 vc = dest_fpr(ctx, rc); 2283 va = load_fpr(ctx, ra); 2284 if (ra == rb) { 2285 /* Special case CPYS as FMOV. */ 2286 tcg_gen_mov_i64(vc, va); 2287 } else { 2288 vb = load_fpr(ctx, rb); 2289 gen_cpy_mask(vc, va, vb, 0, 0x8000000000000000ULL); 2290 } 2291 } 2292 break; 2293 case 0x021: 2294 /* CPYSN */ 2295 REQUIRE_FEN; 2296 vc = dest_fpr(ctx, rc); 2297 vb = load_fpr(ctx, rb); 2298 va = load_fpr(ctx, ra); 2299 gen_cpy_mask(vc, va, vb, 1, 0x8000000000000000ULL); 2300 break; 2301 case 0x022: 2302 /* CPYSE */ 2303 REQUIRE_FEN; 2304 vc = dest_fpr(ctx, rc); 2305 vb = load_fpr(ctx, rb); 2306 va = load_fpr(ctx, ra); 2307 gen_cpy_mask(vc, va, vb, 0, 0xFFF0000000000000ULL); 2308 break; 2309 case 0x024: 2310 /* MT_FPCR */ 2311 REQUIRE_FEN; 2312 va = load_fpr(ctx, ra); 2313 gen_helper_store_fpcr(cpu_env, va); 2314 if (ctx->tb_rm == QUAL_RM_D) { 2315 /* Re-do the copy of the rounding mode to fp_status 2316 the next time we use dynamic rounding. */ 2317 ctx->tb_rm = -1; 2318 } 2319 break; 2320 case 0x025: 2321 /* MF_FPCR */ 2322 REQUIRE_FEN; 2323 va = dest_fpr(ctx, ra); 2324 gen_helper_load_fpcr(va, cpu_env); 2325 break; 2326 case 0x02A: 2327 /* FCMOVEQ */ 2328 REQUIRE_FEN; 2329 gen_fcmov(ctx, TCG_COND_EQ, ra, rb, rc); 2330 break; 2331 case 0x02B: 2332 /* FCMOVNE */ 2333 REQUIRE_FEN; 2334 gen_fcmov(ctx, TCG_COND_NE, ra, rb, rc); 2335 break; 2336 case 0x02C: 2337 /* FCMOVLT */ 2338 REQUIRE_FEN; 2339 gen_fcmov(ctx, TCG_COND_LT, ra, rb, rc); 2340 break; 2341 case 0x02D: 2342 /* FCMOVGE */ 2343 REQUIRE_FEN; 2344 gen_fcmov(ctx, TCG_COND_GE, ra, rb, rc); 2345 break; 2346 case 0x02E: 2347 /* FCMOVLE */ 2348 REQUIRE_FEN; 2349 gen_fcmov(ctx, TCG_COND_LE, ra, rb, rc); 2350 break; 2351 case 0x02F: 2352 /* FCMOVGT */ 2353 REQUIRE_FEN; 2354 gen_fcmov(ctx, TCG_COND_GT, ra, rb, rc); 2355 break; 2356 case 0x030: /* CVTQL */ 2357 case 0x130: /* CVTQL/V */ 2358 case 0x530: /* CVTQL/SV */ 2359 REQUIRE_REG_31(ra); 2360 REQUIRE_FEN; 2361 vc = dest_fpr(ctx, rc); 2362 vb = load_fpr(ctx, rb); 2363 gen_helper_cvtql(vc, cpu_env, vb); 2364 gen_fp_exc_raise(rc, fn11); 2365 break; 2366 default: 2367 goto invalid_opc; 2368 } 2369 break; 2370 2371 case 0x18: 2372 switch ((uint16_t)disp16) { 2373 case 0x0000: 2374 /* TRAPB */ 2375 /* No-op. */ 2376 break; 2377 case 0x0400: 2378 /* EXCB */ 2379 /* No-op. */ 2380 break; 2381 case 0x4000: 2382 /* MB */ 2383 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); 2384 break; 2385 case 0x4400: 2386 /* WMB */ 2387 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC); 2388 break; 2389 case 0x8000: 2390 /* FETCH */ 2391 /* No-op */ 2392 break; 2393 case 0xA000: 2394 /* FETCH_M */ 2395 /* No-op */ 2396 break; 2397 case 0xC000: 2398 /* RPCC */ 2399 va = dest_gpr(ctx, ra); 2400 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { 2401 gen_io_start(); 2402 gen_helper_load_pcc(va, cpu_env); 2403 ret = DISAS_PC_STALE; 2404 } else { 2405 gen_helper_load_pcc(va, cpu_env); 2406 } 2407 break; 2408 case 0xE000: 2409 /* RC */ 2410 gen_rx(ctx, ra, 0); 2411 break; 2412 case 0xE800: 2413 /* ECB */ 2414 break; 2415 case 0xF000: 2416 /* RS */ 2417 gen_rx(ctx, ra, 1); 2418 break; 2419 case 0xF800: 2420 /* WH64 */ 2421 /* No-op */ 2422 break; 2423 case 0xFC00: 2424 /* WH64EN */ 2425 /* No-op */ 2426 break; 2427 default: 2428 goto invalid_opc; 2429 } 2430 break; 2431 2432 case 0x19: 2433 /* HW_MFPR (PALcode) */ 2434 #ifndef CONFIG_USER_ONLY 2435 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE); 2436 va = dest_gpr(ctx, ra); 2437 ret = gen_mfpr(ctx, va, insn & 0xffff); 2438 break; 2439 #else 2440 goto invalid_opc; 2441 #endif 2442 2443 case 0x1A: 2444 /* JMP, JSR, RET, JSR_COROUTINE. These only differ by the branch 2445 prediction stack action, which of course we don't implement. */ 2446 vb = load_gpr(ctx, rb); 2447 tcg_gen_andi_i64(cpu_pc, vb, ~3); 2448 if (ra != 31) { 2449 tcg_gen_movi_i64(ctx->ir[ra], ctx->base.pc_next); 2450 } 2451 ret = DISAS_PC_UPDATED; 2452 break; 2453 2454 case 0x1B: 2455 /* HW_LD (PALcode) */ 2456 #ifndef CONFIG_USER_ONLY 2457 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE); 2458 { 2459 TCGv addr = tcg_temp_new(); 2460 vb = load_gpr(ctx, rb); 2461 va = dest_gpr(ctx, ra); 2462 2463 tcg_gen_addi_i64(addr, vb, disp12); 2464 switch ((insn >> 12) & 0xF) { 2465 case 0x0: 2466 /* Longword physical access (hw_ldl/p) */ 2467 tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL); 2468 break; 2469 case 0x1: 2470 /* Quadword physical access (hw_ldq/p) */ 2471 tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ); 2472 break; 2473 case 0x2: 2474 /* Longword physical access with lock (hw_ldl_l/p) */ 2475 tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL); 2476 tcg_gen_mov_i64(cpu_lock_addr, addr); 2477 tcg_gen_mov_i64(cpu_lock_value, va); 2478 break; 2479 case 0x3: 2480 /* Quadword physical access with lock (hw_ldq_l/p) */ 2481 tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ); 2482 tcg_gen_mov_i64(cpu_lock_addr, addr); 2483 tcg_gen_mov_i64(cpu_lock_value, va); 2484 break; 2485 case 0x4: 2486 /* Longword virtual PTE fetch (hw_ldl/v) */ 2487 goto invalid_opc; 2488 case 0x5: 2489 /* Quadword virtual PTE fetch (hw_ldq/v) */ 2490 goto invalid_opc; 2491 break; 2492 case 0x6: 2493 /* Invalid */ 2494 goto invalid_opc; 2495 case 0x7: 2496 /* Invaliid */ 2497 goto invalid_opc; 2498 case 0x8: 2499 /* Longword virtual access (hw_ldl) */ 2500 goto invalid_opc; 2501 case 0x9: 2502 /* Quadword virtual access (hw_ldq) */ 2503 goto invalid_opc; 2504 case 0xA: 2505 /* Longword virtual access with protection check (hw_ldl/w) */ 2506 tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LESL); 2507 break; 2508 case 0xB: 2509 /* Quadword virtual access with protection check (hw_ldq/w) */ 2510 tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LEUQ); 2511 break; 2512 case 0xC: 2513 /* Longword virtual access with alt access mode (hw_ldl/a)*/ 2514 goto invalid_opc; 2515 case 0xD: 2516 /* Quadword virtual access with alt access mode (hw_ldq/a) */ 2517 goto invalid_opc; 2518 case 0xE: 2519 /* Longword virtual access with alternate access mode and 2520 protection checks (hw_ldl/wa) */ 2521 tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LESL); 2522 break; 2523 case 0xF: 2524 /* Quadword virtual access with alternate access mode and 2525 protection checks (hw_ldq/wa) */ 2526 tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LEUQ); 2527 break; 2528 } 2529 tcg_temp_free(addr); 2530 break; 2531 } 2532 #else 2533 goto invalid_opc; 2534 #endif 2535 2536 case 0x1C: 2537 vc = dest_gpr(ctx, rc); 2538 if (fn7 == 0x70) { 2539 /* FTOIT */ 2540 REQUIRE_AMASK(FIX); 2541 REQUIRE_REG_31(rb); 2542 va = load_fpr(ctx, ra); 2543 tcg_gen_mov_i64(vc, va); 2544 break; 2545 } else if (fn7 == 0x78) { 2546 /* FTOIS */ 2547 REQUIRE_AMASK(FIX); 2548 REQUIRE_REG_31(rb); 2549 t32 = tcg_temp_new_i32(); 2550 va = load_fpr(ctx, ra); 2551 gen_helper_s_to_memory(t32, va); 2552 tcg_gen_ext_i32_i64(vc, t32); 2553 tcg_temp_free_i32(t32); 2554 break; 2555 } 2556 2557 vb = load_gpr_lit(ctx, rb, lit, islit); 2558 switch (fn7) { 2559 case 0x00: 2560 /* SEXTB */ 2561 REQUIRE_AMASK(BWX); 2562 REQUIRE_REG_31(ra); 2563 tcg_gen_ext8s_i64(vc, vb); 2564 break; 2565 case 0x01: 2566 /* SEXTW */ 2567 REQUIRE_AMASK(BWX); 2568 REQUIRE_REG_31(ra); 2569 tcg_gen_ext16s_i64(vc, vb); 2570 break; 2571 case 0x30: 2572 /* CTPOP */ 2573 REQUIRE_AMASK(CIX); 2574 REQUIRE_REG_31(ra); 2575 REQUIRE_NO_LIT; 2576 tcg_gen_ctpop_i64(vc, vb); 2577 break; 2578 case 0x31: 2579 /* PERR */ 2580 REQUIRE_AMASK(MVI); 2581 REQUIRE_NO_LIT; 2582 va = load_gpr(ctx, ra); 2583 gen_helper_perr(vc, va, vb); 2584 break; 2585 case 0x32: 2586 /* CTLZ */ 2587 REQUIRE_AMASK(CIX); 2588 REQUIRE_REG_31(ra); 2589 REQUIRE_NO_LIT; 2590 tcg_gen_clzi_i64(vc, vb, 64); 2591 break; 2592 case 0x33: 2593 /* CTTZ */ 2594 REQUIRE_AMASK(CIX); 2595 REQUIRE_REG_31(ra); 2596 REQUIRE_NO_LIT; 2597 tcg_gen_ctzi_i64(vc, vb, 64); 2598 break; 2599 case 0x34: 2600 /* UNPKBW */ 2601 REQUIRE_AMASK(MVI); 2602 REQUIRE_REG_31(ra); 2603 REQUIRE_NO_LIT; 2604 gen_helper_unpkbw(vc, vb); 2605 break; 2606 case 0x35: 2607 /* UNPKBL */ 2608 REQUIRE_AMASK(MVI); 2609 REQUIRE_REG_31(ra); 2610 REQUIRE_NO_LIT; 2611 gen_helper_unpkbl(vc, vb); 2612 break; 2613 case 0x36: 2614 /* PKWB */ 2615 REQUIRE_AMASK(MVI); 2616 REQUIRE_REG_31(ra); 2617 REQUIRE_NO_LIT; 2618 gen_helper_pkwb(vc, vb); 2619 break; 2620 case 0x37: 2621 /* PKLB */ 2622 REQUIRE_AMASK(MVI); 2623 REQUIRE_REG_31(ra); 2624 REQUIRE_NO_LIT; 2625 gen_helper_pklb(vc, vb); 2626 break; 2627 case 0x38: 2628 /* MINSB8 */ 2629 REQUIRE_AMASK(MVI); 2630 va = load_gpr(ctx, ra); 2631 gen_helper_minsb8(vc, va, vb); 2632 break; 2633 case 0x39: 2634 /* MINSW4 */ 2635 REQUIRE_AMASK(MVI); 2636 va = load_gpr(ctx, ra); 2637 gen_helper_minsw4(vc, va, vb); 2638 break; 2639 case 0x3A: 2640 /* MINUB8 */ 2641 REQUIRE_AMASK(MVI); 2642 va = load_gpr(ctx, ra); 2643 gen_helper_minub8(vc, va, vb); 2644 break; 2645 case 0x3B: 2646 /* MINUW4 */ 2647 REQUIRE_AMASK(MVI); 2648 va = load_gpr(ctx, ra); 2649 gen_helper_minuw4(vc, va, vb); 2650 break; 2651 case 0x3C: 2652 /* MAXUB8 */ 2653 REQUIRE_AMASK(MVI); 2654 va = load_gpr(ctx, ra); 2655 gen_helper_maxub8(vc, va, vb); 2656 break; 2657 case 0x3D: 2658 /* MAXUW4 */ 2659 REQUIRE_AMASK(MVI); 2660 va = load_gpr(ctx, ra); 2661 gen_helper_maxuw4(vc, va, vb); 2662 break; 2663 case 0x3E: 2664 /* MAXSB8 */ 2665 REQUIRE_AMASK(MVI); 2666 va = load_gpr(ctx, ra); 2667 gen_helper_maxsb8(vc, va, vb); 2668 break; 2669 case 0x3F: 2670 /* MAXSW4 */ 2671 REQUIRE_AMASK(MVI); 2672 va = load_gpr(ctx, ra); 2673 gen_helper_maxsw4(vc, va, vb); 2674 break; 2675 default: 2676 goto invalid_opc; 2677 } 2678 break; 2679 2680 case 0x1D: 2681 /* HW_MTPR (PALcode) */ 2682 #ifndef CONFIG_USER_ONLY 2683 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE); 2684 vb = load_gpr(ctx, rb); 2685 ret = gen_mtpr(ctx, vb, insn & 0xffff); 2686 break; 2687 #else 2688 goto invalid_opc; 2689 #endif 2690 2691 case 0x1E: 2692 /* HW_RET (PALcode) */ 2693 #ifndef CONFIG_USER_ONLY 2694 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE); 2695 if (rb == 31) { 2696 /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return 2697 address from EXC_ADDR. This turns out to be useful for our 2698 emulation PALcode, so continue to accept it. */ 2699 vb = dest_sink(ctx); 2700 tcg_gen_ld_i64(vb, cpu_env, offsetof(CPUAlphaState, exc_addr)); 2701 } else { 2702 vb = load_gpr(ctx, rb); 2703 } 2704 tcg_gen_movi_i64(cpu_lock_addr, -1); 2705 st_flag_byte(load_zero(ctx), ENV_FLAG_RX_SHIFT); 2706 tmp = tcg_temp_new(); 2707 tcg_gen_andi_i64(tmp, vb, 1); 2708 st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT); 2709 tcg_temp_free(tmp); 2710 tcg_gen_andi_i64(cpu_pc, vb, ~3); 2711 /* Allow interrupts to be recognized right away. */ 2712 ret = DISAS_PC_UPDATED_NOCHAIN; 2713 break; 2714 #else 2715 goto invalid_opc; 2716 #endif 2717 2718 case 0x1F: 2719 /* HW_ST (PALcode) */ 2720 #ifndef CONFIG_USER_ONLY 2721 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE); 2722 { 2723 switch ((insn >> 12) & 0xF) { 2724 case 0x0: 2725 /* Longword physical access */ 2726 va = load_gpr(ctx, ra); 2727 vb = load_gpr(ctx, rb); 2728 tmp = tcg_temp_new(); 2729 tcg_gen_addi_i64(tmp, vb, disp12); 2730 tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LESL); 2731 tcg_temp_free(tmp); 2732 break; 2733 case 0x1: 2734 /* Quadword physical access */ 2735 va = load_gpr(ctx, ra); 2736 vb = load_gpr(ctx, rb); 2737 tmp = tcg_temp_new(); 2738 tcg_gen_addi_i64(tmp, vb, disp12); 2739 tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEUQ); 2740 tcg_temp_free(tmp); 2741 break; 2742 case 0x2: 2743 /* Longword physical access with lock */ 2744 ret = gen_store_conditional(ctx, ra, rb, disp12, 2745 MMU_PHYS_IDX, MO_LESL); 2746 break; 2747 case 0x3: 2748 /* Quadword physical access with lock */ 2749 ret = gen_store_conditional(ctx, ra, rb, disp12, 2750 MMU_PHYS_IDX, MO_LEUQ); 2751 break; 2752 case 0x4: 2753 /* Longword virtual access */ 2754 goto invalid_opc; 2755 case 0x5: 2756 /* Quadword virtual access */ 2757 goto invalid_opc; 2758 case 0x6: 2759 /* Invalid */ 2760 goto invalid_opc; 2761 case 0x7: 2762 /* Invalid */ 2763 goto invalid_opc; 2764 case 0x8: 2765 /* Invalid */ 2766 goto invalid_opc; 2767 case 0x9: 2768 /* Invalid */ 2769 goto invalid_opc; 2770 case 0xA: 2771 /* Invalid */ 2772 goto invalid_opc; 2773 case 0xB: 2774 /* Invalid */ 2775 goto invalid_opc; 2776 case 0xC: 2777 /* Longword virtual access with alternate access mode */ 2778 goto invalid_opc; 2779 case 0xD: 2780 /* Quadword virtual access with alternate access mode */ 2781 goto invalid_opc; 2782 case 0xE: 2783 /* Invalid */ 2784 goto invalid_opc; 2785 case 0xF: 2786 /* Invalid */ 2787 goto invalid_opc; 2788 } 2789 break; 2790 } 2791 #else 2792 goto invalid_opc; 2793 #endif 2794 case 0x20: 2795 /* LDF */ 2796 REQUIRE_FEN; 2797 gen_load_fp(ctx, ra, rb, disp16, gen_ldf); 2798 break; 2799 case 0x21: 2800 /* LDG */ 2801 REQUIRE_FEN; 2802 gen_load_fp(ctx, ra, rb, disp16, gen_ldg); 2803 break; 2804 case 0x22: 2805 /* LDS */ 2806 REQUIRE_FEN; 2807 gen_load_fp(ctx, ra, rb, disp16, gen_lds); 2808 break; 2809 case 0x23: 2810 /* LDT */ 2811 REQUIRE_FEN; 2812 gen_load_fp(ctx, ra, rb, disp16, gen_ldt); 2813 break; 2814 case 0x24: 2815 /* STF */ 2816 REQUIRE_FEN; 2817 gen_store_fp(ctx, ra, rb, disp16, gen_stf); 2818 break; 2819 case 0x25: 2820 /* STG */ 2821 REQUIRE_FEN; 2822 gen_store_fp(ctx, ra, rb, disp16, gen_stg); 2823 break; 2824 case 0x26: 2825 /* STS */ 2826 REQUIRE_FEN; 2827 gen_store_fp(ctx, ra, rb, disp16, gen_sts); 2828 break; 2829 case 0x27: 2830 /* STT */ 2831 REQUIRE_FEN; 2832 gen_store_fp(ctx, ra, rb, disp16, gen_stt); 2833 break; 2834 case 0x28: 2835 /* LDL */ 2836 gen_load_int(ctx, ra, rb, disp16, MO_LESL, 0, 0); 2837 break; 2838 case 0x29: 2839 /* LDQ */ 2840 gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 0, 0); 2841 break; 2842 case 0x2A: 2843 /* LDL_L */ 2844 gen_load_int(ctx, ra, rb, disp16, MO_LESL, 0, 1); 2845 break; 2846 case 0x2B: 2847 /* LDQ_L */ 2848 gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 0, 1); 2849 break; 2850 case 0x2C: 2851 /* STL */ 2852 gen_store_int(ctx, ra, rb, disp16, MO_LEUL, 0); 2853 break; 2854 case 0x2D: 2855 /* STQ */ 2856 gen_store_int(ctx, ra, rb, disp16, MO_LEUQ, 0); 2857 break; 2858 case 0x2E: 2859 /* STL_C */ 2860 ret = gen_store_conditional(ctx, ra, rb, disp16, 2861 ctx->mem_idx, MO_LESL); 2862 break; 2863 case 0x2F: 2864 /* STQ_C */ 2865 ret = gen_store_conditional(ctx, ra, rb, disp16, 2866 ctx->mem_idx, MO_LEUQ); 2867 break; 2868 case 0x30: 2869 /* BR */ 2870 ret = gen_bdirect(ctx, ra, disp21); 2871 break; 2872 case 0x31: /* FBEQ */ 2873 REQUIRE_FEN; 2874 ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21); 2875 break; 2876 case 0x32: /* FBLT */ 2877 REQUIRE_FEN; 2878 ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21); 2879 break; 2880 case 0x33: /* FBLE */ 2881 REQUIRE_FEN; 2882 ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21); 2883 break; 2884 case 0x34: 2885 /* BSR */ 2886 ret = gen_bdirect(ctx, ra, disp21); 2887 break; 2888 case 0x35: /* FBNE */ 2889 REQUIRE_FEN; 2890 ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21); 2891 break; 2892 case 0x36: /* FBGE */ 2893 REQUIRE_FEN; 2894 ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21); 2895 break; 2896 case 0x37: /* FBGT */ 2897 REQUIRE_FEN; 2898 ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21); 2899 break; 2900 case 0x38: 2901 /* BLBC */ 2902 ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1); 2903 break; 2904 case 0x39: 2905 /* BEQ */ 2906 ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0); 2907 break; 2908 case 0x3A: 2909 /* BLT */ 2910 ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0); 2911 break; 2912 case 0x3B: 2913 /* BLE */ 2914 ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0); 2915 break; 2916 case 0x3C: 2917 /* BLBS */ 2918 ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1); 2919 break; 2920 case 0x3D: 2921 /* BNE */ 2922 ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0); 2923 break; 2924 case 0x3E: 2925 /* BGE */ 2926 ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0); 2927 break; 2928 case 0x3F: 2929 /* BGT */ 2930 ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0); 2931 break; 2932 invalid_opc: 2933 ret = gen_invalid(ctx); 2934 break; 2935 raise_fen: 2936 ret = gen_excp(ctx, EXCP_FEN, 0); 2937 break; 2938 } 2939 2940 return ret; 2941 } 2942 2943 static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) 2944 { 2945 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2946 CPUAlphaState *env = cpu->env_ptr; 2947 int64_t bound; 2948 2949 ctx->tbflags = ctx->base.tb->flags; 2950 ctx->mem_idx = cpu_mmu_index(env, false); 2951 ctx->implver = env->implver; 2952 ctx->amask = env->amask; 2953 2954 #ifdef CONFIG_USER_ONLY 2955 ctx->ir = cpu_std_ir; 2956 ctx->unalign = (ctx->tbflags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN); 2957 #else 2958 ctx->palbr = env->palbr; 2959 ctx->ir = (ctx->tbflags & ENV_FLAG_PAL_MODE ? cpu_pal_ir : cpu_std_ir); 2960 #endif 2961 2962 /* ??? Every TB begins with unset rounding mode, to be initialized on 2963 the first fp insn of the TB. Alternately we could define a proper 2964 default for every TB (e.g. QUAL_RM_N or QUAL_RM_D) and make sure 2965 to reset the FP_STATUS to that default at the end of any TB that 2966 changes the default. We could even (gasp) dynamiclly figure out 2967 what default would be most efficient given the running program. */ 2968 ctx->tb_rm = -1; 2969 /* Similarly for flush-to-zero. */ 2970 ctx->tb_ftz = -1; 2971 2972 ctx->zero = NULL; 2973 ctx->sink = NULL; 2974 2975 /* Bound the number of insns to execute to those left on the page. */ 2976 bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4; 2977 ctx->base.max_insns = MIN(ctx->base.max_insns, bound); 2978 } 2979 2980 static void alpha_tr_tb_start(DisasContextBase *db, CPUState *cpu) 2981 { 2982 } 2983 2984 static void alpha_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) 2985 { 2986 tcg_gen_insn_start(dcbase->pc_next); 2987 } 2988 2989 static void alpha_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) 2990 { 2991 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2992 CPUAlphaState *env = cpu->env_ptr; 2993 uint32_t insn = translator_ldl(env, &ctx->base, ctx->base.pc_next); 2994 2995 ctx->base.pc_next += 4; 2996 ctx->base.is_jmp = translate_one(ctx, insn); 2997 2998 free_context_temps(ctx); 2999 translator_loop_temp_check(&ctx->base); 3000 } 3001 3002 static void alpha_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) 3003 { 3004 DisasContext *ctx = container_of(dcbase, DisasContext, base); 3005 3006 switch (ctx->base.is_jmp) { 3007 case DISAS_NORETURN: 3008 break; 3009 case DISAS_TOO_MANY: 3010 if (use_goto_tb(ctx, ctx->base.pc_next)) { 3011 tcg_gen_goto_tb(0); 3012 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next); 3013 tcg_gen_exit_tb(ctx->base.tb, 0); 3014 } 3015 /* FALLTHRU */ 3016 case DISAS_PC_STALE: 3017 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next); 3018 /* FALLTHRU */ 3019 case DISAS_PC_UPDATED: 3020 tcg_gen_lookup_and_goto_ptr(); 3021 break; 3022 case DISAS_PC_UPDATED_NOCHAIN: 3023 tcg_gen_exit_tb(NULL, 0); 3024 break; 3025 default: 3026 g_assert_not_reached(); 3027 } 3028 } 3029 3030 static void alpha_tr_disas_log(const DisasContextBase *dcbase, 3031 CPUState *cpu, FILE *logfile) 3032 { 3033 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first)); 3034 target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size); 3035 } 3036 3037 static const TranslatorOps alpha_tr_ops = { 3038 .init_disas_context = alpha_tr_init_disas_context, 3039 .tb_start = alpha_tr_tb_start, 3040 .insn_start = alpha_tr_insn_start, 3041 .translate_insn = alpha_tr_translate_insn, 3042 .tb_stop = alpha_tr_tb_stop, 3043 .disas_log = alpha_tr_disas_log, 3044 }; 3045 3046 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns) 3047 { 3048 DisasContext dc; 3049 translator_loop(&alpha_tr_ops, &dc.base, cpu, tb, max_insns); 3050 } 3051 3052 void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, 3053 target_ulong *data) 3054 { 3055 env->pc = data[0]; 3056 } 3057