1 /* 2 * m68k translation 3 * 4 * Copyright (c) 2005-2007 CodeSourcery 5 * Written by Paul Brook 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include "qemu/osdep.h" 22 #include "cpu.h" 23 #include "disas/disas.h" 24 #include "exec/exec-all.h" 25 #include "tcg-op.h" 26 #include "qemu/log.h" 27 #include "qemu/qemu-print.h" 28 #include "exec/cpu_ldst.h" 29 #include "exec/translator.h" 30 31 #include "exec/helper-proto.h" 32 #include "exec/helper-gen.h" 33 34 #include "trace-tcg.h" 35 #include "exec/log.h" 36 #include "fpu/softfloat.h" 37 38 39 //#define DEBUG_DISPATCH 1 40 41 #define DEFO32(name, offset) static TCGv QREG_##name; 42 #define DEFO64(name, offset) static TCGv_i64 QREG_##name; 43 #include "qregs.def" 44 #undef DEFO32 45 #undef DEFO64 46 47 static TCGv_i32 cpu_halted; 48 static TCGv_i32 cpu_exception_index; 49 50 static char cpu_reg_names[2 * 8 * 3 + 5 * 4]; 51 static TCGv cpu_dregs[8]; 52 static TCGv cpu_aregs[8]; 53 static TCGv_i64 cpu_macc[4]; 54 55 #define REG(insn, pos) (((insn) >> (pos)) & 7) 56 #define DREG(insn, pos) cpu_dregs[REG(insn, pos)] 57 #define AREG(insn, pos) get_areg(s, REG(insn, pos)) 58 #define MACREG(acc) cpu_macc[acc] 59 #define QREG_SP get_areg(s, 7) 60 61 static TCGv NULL_QREG; 62 #define IS_NULL_QREG(t) (t == NULL_QREG) 63 /* Used to distinguish stores from bad addressing modes. */ 64 static TCGv store_dummy; 65 66 #include "exec/gen-icount.h" 67 68 void m68k_tcg_init(void) 69 { 70 char *p; 71 int i; 72 73 #define DEFO32(name, offset) \ 74 QREG_##name = tcg_global_mem_new_i32(cpu_env, \ 75 offsetof(CPUM68KState, offset), #name); 76 #define DEFO64(name, offset) \ 77 QREG_##name = tcg_global_mem_new_i64(cpu_env, \ 78 offsetof(CPUM68KState, offset), #name); 79 #include "qregs.def" 80 #undef DEFO32 81 #undef DEFO64 82 83 cpu_halted = tcg_global_mem_new_i32(cpu_env, 84 -offsetof(M68kCPU, env) + 85 offsetof(CPUState, halted), "HALTED"); 86 cpu_exception_index = tcg_global_mem_new_i32(cpu_env, 87 -offsetof(M68kCPU, env) + 88 offsetof(CPUState, exception_index), 89 "EXCEPTION"); 90 91 p = cpu_reg_names; 92 for (i = 0; i < 8; i++) { 93 sprintf(p, "D%d", i); 94 cpu_dregs[i] = tcg_global_mem_new(cpu_env, 95 offsetof(CPUM68KState, dregs[i]), p); 96 p += 3; 97 sprintf(p, "A%d", i); 98 cpu_aregs[i] = tcg_global_mem_new(cpu_env, 99 offsetof(CPUM68KState, aregs[i]), p); 100 p += 3; 101 } 102 for (i = 0; i < 4; i++) { 103 sprintf(p, "ACC%d", i); 104 cpu_macc[i] = tcg_global_mem_new_i64(cpu_env, 105 offsetof(CPUM68KState, macc[i]), p); 106 p += 5; 107 } 108 109 NULL_QREG = tcg_global_mem_new(cpu_env, -4, "NULL"); 110 store_dummy = tcg_global_mem_new(cpu_env, -8, "NULL"); 111 } 112 113 /* internal defines */ 114 typedef struct DisasContext { 115 DisasContextBase base; 116 CPUM68KState *env; 117 target_ulong pc; 118 CCOp cc_op; /* Current CC operation */ 119 int cc_op_synced; 120 TCGv_i64 mactmp; 121 int done_mac; 122 int writeback_mask; 123 TCGv writeback[8]; 124 #define MAX_TO_RELEASE 8 125 int release_count; 126 TCGv release[MAX_TO_RELEASE]; 127 } DisasContext; 128 129 static void init_release_array(DisasContext *s) 130 { 131 #ifdef CONFIG_DEBUG_TCG 132 memset(s->release, 0, sizeof(s->release)); 133 #endif 134 s->release_count = 0; 135 } 136 137 static void do_release(DisasContext *s) 138 { 139 int i; 140 for (i = 0; i < s->release_count; i++) { 141 tcg_temp_free(s->release[i]); 142 } 143 init_release_array(s); 144 } 145 146 static TCGv mark_to_release(DisasContext *s, TCGv tmp) 147 { 148 g_assert(s->release_count < MAX_TO_RELEASE); 149 return s->release[s->release_count++] = tmp; 150 } 151 152 static TCGv get_areg(DisasContext *s, unsigned regno) 153 { 154 if (s->writeback_mask & (1 << regno)) { 155 return s->writeback[regno]; 156 } else { 157 return cpu_aregs[regno]; 158 } 159 } 160 161 static void delay_set_areg(DisasContext *s, unsigned regno, 162 TCGv val, bool give_temp) 163 { 164 if (s->writeback_mask & (1 << regno)) { 165 if (give_temp) { 166 tcg_temp_free(s->writeback[regno]); 167 s->writeback[regno] = val; 168 } else { 169 tcg_gen_mov_i32(s->writeback[regno], val); 170 } 171 } else { 172 s->writeback_mask |= 1 << regno; 173 if (give_temp) { 174 s->writeback[regno] = val; 175 } else { 176 TCGv tmp = tcg_temp_new(); 177 s->writeback[regno] = tmp; 178 tcg_gen_mov_i32(tmp, val); 179 } 180 } 181 } 182 183 static void do_writebacks(DisasContext *s) 184 { 185 unsigned mask = s->writeback_mask; 186 if (mask) { 187 s->writeback_mask = 0; 188 do { 189 unsigned regno = ctz32(mask); 190 tcg_gen_mov_i32(cpu_aregs[regno], s->writeback[regno]); 191 tcg_temp_free(s->writeback[regno]); 192 mask &= mask - 1; 193 } while (mask); 194 } 195 } 196 197 /* is_jmp field values */ 198 #define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */ 199 #define DISAS_EXIT DISAS_TARGET_1 /* cpu state was modified dynamically */ 200 201 #if defined(CONFIG_USER_ONLY) 202 #define IS_USER(s) 1 203 #else 204 #define IS_USER(s) (!(s->base.tb->flags & TB_FLAGS_MSR_S)) 205 #define SFC_INDEX(s) ((s->base.tb->flags & TB_FLAGS_SFC_S) ? \ 206 MMU_KERNEL_IDX : MMU_USER_IDX) 207 #define DFC_INDEX(s) ((s->base.tb->flags & TB_FLAGS_DFC_S) ? \ 208 MMU_KERNEL_IDX : MMU_USER_IDX) 209 #endif 210 211 typedef void (*disas_proc)(CPUM68KState *env, DisasContext *s, uint16_t insn); 212 213 #ifdef DEBUG_DISPATCH 214 #define DISAS_INSN(name) \ 215 static void real_disas_##name(CPUM68KState *env, DisasContext *s, \ 216 uint16_t insn); \ 217 static void disas_##name(CPUM68KState *env, DisasContext *s, \ 218 uint16_t insn) \ 219 { \ 220 qemu_log("Dispatch " #name "\n"); \ 221 real_disas_##name(env, s, insn); \ 222 } \ 223 static void real_disas_##name(CPUM68KState *env, DisasContext *s, \ 224 uint16_t insn) 225 #else 226 #define DISAS_INSN(name) \ 227 static void disas_##name(CPUM68KState *env, DisasContext *s, \ 228 uint16_t insn) 229 #endif 230 231 static const uint8_t cc_op_live[CC_OP_NB] = { 232 [CC_OP_DYNAMIC] = CCF_C | CCF_V | CCF_Z | CCF_N | CCF_X, 233 [CC_OP_FLAGS] = CCF_C | CCF_V | CCF_Z | CCF_N | CCF_X, 234 [CC_OP_ADDB ... CC_OP_ADDL] = CCF_X | CCF_N | CCF_V, 235 [CC_OP_SUBB ... CC_OP_SUBL] = CCF_X | CCF_N | CCF_V, 236 [CC_OP_CMPB ... CC_OP_CMPL] = CCF_X | CCF_N | CCF_V, 237 [CC_OP_LOGIC] = CCF_X | CCF_N 238 }; 239 240 static void set_cc_op(DisasContext *s, CCOp op) 241 { 242 CCOp old_op = s->cc_op; 243 int dead; 244 245 if (old_op == op) { 246 return; 247 } 248 s->cc_op = op; 249 s->cc_op_synced = 0; 250 251 /* 252 * Discard CC computation that will no longer be used. 253 * Note that X and N are never dead. 254 */ 255 dead = cc_op_live[old_op] & ~cc_op_live[op]; 256 if (dead & CCF_C) { 257 tcg_gen_discard_i32(QREG_CC_C); 258 } 259 if (dead & CCF_Z) { 260 tcg_gen_discard_i32(QREG_CC_Z); 261 } 262 if (dead & CCF_V) { 263 tcg_gen_discard_i32(QREG_CC_V); 264 } 265 } 266 267 /* Update the CPU env CC_OP state. */ 268 static void update_cc_op(DisasContext *s) 269 { 270 if (!s->cc_op_synced) { 271 s->cc_op_synced = 1; 272 tcg_gen_movi_i32(QREG_CC_OP, s->cc_op); 273 } 274 } 275 276 /* Generate a jump to an immediate address. */ 277 static void gen_jmp_im(DisasContext *s, uint32_t dest) 278 { 279 update_cc_op(s); 280 tcg_gen_movi_i32(QREG_PC, dest); 281 s->base.is_jmp = DISAS_JUMP; 282 } 283 284 /* Generate a jump to the address in qreg DEST. */ 285 static void gen_jmp(DisasContext *s, TCGv dest) 286 { 287 update_cc_op(s); 288 tcg_gen_mov_i32(QREG_PC, dest); 289 s->base.is_jmp = DISAS_JUMP; 290 } 291 292 static void gen_exception(DisasContext *s, uint32_t dest, int nr) 293 { 294 TCGv_i32 tmp; 295 296 update_cc_op(s); 297 tcg_gen_movi_i32(QREG_PC, dest); 298 299 tmp = tcg_const_i32(nr); 300 gen_helper_raise_exception(cpu_env, tmp); 301 tcg_temp_free_i32(tmp); 302 303 s->base.is_jmp = DISAS_NORETURN; 304 } 305 306 static inline void gen_addr_fault(DisasContext *s) 307 { 308 gen_exception(s, s->base.pc_next, EXCP_ADDRESS); 309 } 310 311 /* 312 * Generate a load from the specified address. Narrow values are 313 * sign extended to full register width. 314 */ 315 static inline TCGv gen_load(DisasContext *s, int opsize, TCGv addr, 316 int sign, int index) 317 { 318 TCGv tmp; 319 tmp = tcg_temp_new_i32(); 320 switch(opsize) { 321 case OS_BYTE: 322 if (sign) 323 tcg_gen_qemu_ld8s(tmp, addr, index); 324 else 325 tcg_gen_qemu_ld8u(tmp, addr, index); 326 break; 327 case OS_WORD: 328 if (sign) 329 tcg_gen_qemu_ld16s(tmp, addr, index); 330 else 331 tcg_gen_qemu_ld16u(tmp, addr, index); 332 break; 333 case OS_LONG: 334 tcg_gen_qemu_ld32u(tmp, addr, index); 335 break; 336 default: 337 g_assert_not_reached(); 338 } 339 return tmp; 340 } 341 342 /* Generate a store. */ 343 static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val, 344 int index) 345 { 346 switch(opsize) { 347 case OS_BYTE: 348 tcg_gen_qemu_st8(val, addr, index); 349 break; 350 case OS_WORD: 351 tcg_gen_qemu_st16(val, addr, index); 352 break; 353 case OS_LONG: 354 tcg_gen_qemu_st32(val, addr, index); 355 break; 356 default: 357 g_assert_not_reached(); 358 } 359 } 360 361 typedef enum { 362 EA_STORE, 363 EA_LOADU, 364 EA_LOADS 365 } ea_what; 366 367 /* 368 * Generate an unsigned load if VAL is 0 a signed load if val is -1, 369 * otherwise generate a store. 370 */ 371 static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val, 372 ea_what what, int index) 373 { 374 if (what == EA_STORE) { 375 gen_store(s, opsize, addr, val, index); 376 return store_dummy; 377 } else { 378 return mark_to_release(s, gen_load(s, opsize, addr, 379 what == EA_LOADS, index)); 380 } 381 } 382 383 /* Read a 16-bit immediate constant */ 384 static inline uint16_t read_im16(CPUM68KState *env, DisasContext *s) 385 { 386 uint16_t im; 387 im = translator_lduw(env, s->pc); 388 s->pc += 2; 389 return im; 390 } 391 392 /* Read an 8-bit immediate constant */ 393 static inline uint8_t read_im8(CPUM68KState *env, DisasContext *s) 394 { 395 return read_im16(env, s); 396 } 397 398 /* Read a 32-bit immediate constant. */ 399 static inline uint32_t read_im32(CPUM68KState *env, DisasContext *s) 400 { 401 uint32_t im; 402 im = read_im16(env, s) << 16; 403 im |= 0xffff & read_im16(env, s); 404 return im; 405 } 406 407 /* Read a 64-bit immediate constant. */ 408 static inline uint64_t read_im64(CPUM68KState *env, DisasContext *s) 409 { 410 uint64_t im; 411 im = (uint64_t)read_im32(env, s) << 32; 412 im |= (uint64_t)read_im32(env, s); 413 return im; 414 } 415 416 /* Calculate and address index. */ 417 static TCGv gen_addr_index(DisasContext *s, uint16_t ext, TCGv tmp) 418 { 419 TCGv add; 420 int scale; 421 422 add = (ext & 0x8000) ? AREG(ext, 12) : DREG(ext, 12); 423 if ((ext & 0x800) == 0) { 424 tcg_gen_ext16s_i32(tmp, add); 425 add = tmp; 426 } 427 scale = (ext >> 9) & 3; 428 if (scale != 0) { 429 tcg_gen_shli_i32(tmp, add, scale); 430 add = tmp; 431 } 432 return add; 433 } 434 435 /* 436 * Handle a base + index + displacement effective addresss. 437 * A NULL_QREG base means pc-relative. 438 */ 439 static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base) 440 { 441 uint32_t offset; 442 uint16_t ext; 443 TCGv add; 444 TCGv tmp; 445 uint32_t bd, od; 446 447 offset = s->pc; 448 ext = read_im16(env, s); 449 450 if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX)) 451 return NULL_QREG; 452 453 if (m68k_feature(s->env, M68K_FEATURE_M68000) && 454 !m68k_feature(s->env, M68K_FEATURE_SCALED_INDEX)) { 455 ext &= ~(3 << 9); 456 } 457 458 if (ext & 0x100) { 459 /* full extension word format */ 460 if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL)) 461 return NULL_QREG; 462 463 if ((ext & 0x30) > 0x10) { 464 /* base displacement */ 465 if ((ext & 0x30) == 0x20) { 466 bd = (int16_t)read_im16(env, s); 467 } else { 468 bd = read_im32(env, s); 469 } 470 } else { 471 bd = 0; 472 } 473 tmp = mark_to_release(s, tcg_temp_new()); 474 if ((ext & 0x44) == 0) { 475 /* pre-index */ 476 add = gen_addr_index(s, ext, tmp); 477 } else { 478 add = NULL_QREG; 479 } 480 if ((ext & 0x80) == 0) { 481 /* base not suppressed */ 482 if (IS_NULL_QREG(base)) { 483 base = mark_to_release(s, tcg_const_i32(offset + bd)); 484 bd = 0; 485 } 486 if (!IS_NULL_QREG(add)) { 487 tcg_gen_add_i32(tmp, add, base); 488 add = tmp; 489 } else { 490 add = base; 491 } 492 } 493 if (!IS_NULL_QREG(add)) { 494 if (bd != 0) { 495 tcg_gen_addi_i32(tmp, add, bd); 496 add = tmp; 497 } 498 } else { 499 add = mark_to_release(s, tcg_const_i32(bd)); 500 } 501 if ((ext & 3) != 0) { 502 /* memory indirect */ 503 base = mark_to_release(s, gen_load(s, OS_LONG, add, 0, IS_USER(s))); 504 if ((ext & 0x44) == 4) { 505 add = gen_addr_index(s, ext, tmp); 506 tcg_gen_add_i32(tmp, add, base); 507 add = tmp; 508 } else { 509 add = base; 510 } 511 if ((ext & 3) > 1) { 512 /* outer displacement */ 513 if ((ext & 3) == 2) { 514 od = (int16_t)read_im16(env, s); 515 } else { 516 od = read_im32(env, s); 517 } 518 } else { 519 od = 0; 520 } 521 if (od != 0) { 522 tcg_gen_addi_i32(tmp, add, od); 523 add = tmp; 524 } 525 } 526 } else { 527 /* brief extension word format */ 528 tmp = mark_to_release(s, tcg_temp_new()); 529 add = gen_addr_index(s, ext, tmp); 530 if (!IS_NULL_QREG(base)) { 531 tcg_gen_add_i32(tmp, add, base); 532 if ((int8_t)ext) 533 tcg_gen_addi_i32(tmp, tmp, (int8_t)ext); 534 } else { 535 tcg_gen_addi_i32(tmp, add, offset + (int8_t)ext); 536 } 537 add = tmp; 538 } 539 return add; 540 } 541 542 /* Sign or zero extend a value. */ 543 544 static inline void gen_ext(TCGv res, TCGv val, int opsize, int sign) 545 { 546 switch (opsize) { 547 case OS_BYTE: 548 if (sign) { 549 tcg_gen_ext8s_i32(res, val); 550 } else { 551 tcg_gen_ext8u_i32(res, val); 552 } 553 break; 554 case OS_WORD: 555 if (sign) { 556 tcg_gen_ext16s_i32(res, val); 557 } else { 558 tcg_gen_ext16u_i32(res, val); 559 } 560 break; 561 case OS_LONG: 562 tcg_gen_mov_i32(res, val); 563 break; 564 default: 565 g_assert_not_reached(); 566 } 567 } 568 569 /* Evaluate all the CC flags. */ 570 571 static void gen_flush_flags(DisasContext *s) 572 { 573 TCGv t0, t1; 574 575 switch (s->cc_op) { 576 case CC_OP_FLAGS: 577 return; 578 579 case CC_OP_ADDB: 580 case CC_OP_ADDW: 581 case CC_OP_ADDL: 582 tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); 583 tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N); 584 /* Compute signed overflow for addition. */ 585 t0 = tcg_temp_new(); 586 t1 = tcg_temp_new(); 587 tcg_gen_sub_i32(t0, QREG_CC_N, QREG_CC_V); 588 gen_ext(t0, t0, s->cc_op - CC_OP_ADDB, 1); 589 tcg_gen_xor_i32(t1, QREG_CC_N, QREG_CC_V); 590 tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0); 591 tcg_temp_free(t0); 592 tcg_gen_andc_i32(QREG_CC_V, t1, QREG_CC_V); 593 tcg_temp_free(t1); 594 break; 595 596 case CC_OP_SUBB: 597 case CC_OP_SUBW: 598 case CC_OP_SUBL: 599 tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); 600 tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N); 601 /* Compute signed overflow for subtraction. */ 602 t0 = tcg_temp_new(); 603 t1 = tcg_temp_new(); 604 tcg_gen_add_i32(t0, QREG_CC_N, QREG_CC_V); 605 gen_ext(t0, t0, s->cc_op - CC_OP_SUBB, 1); 606 tcg_gen_xor_i32(t1, QREG_CC_N, t0); 607 tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0); 608 tcg_temp_free(t0); 609 tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, t1); 610 tcg_temp_free(t1); 611 break; 612 613 case CC_OP_CMPB: 614 case CC_OP_CMPW: 615 case CC_OP_CMPL: 616 tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_C, QREG_CC_N, QREG_CC_V); 617 tcg_gen_sub_i32(QREG_CC_Z, QREG_CC_N, QREG_CC_V); 618 gen_ext(QREG_CC_Z, QREG_CC_Z, s->cc_op - CC_OP_CMPB, 1); 619 /* Compute signed overflow for subtraction. */ 620 t0 = tcg_temp_new(); 621 tcg_gen_xor_i32(t0, QREG_CC_Z, QREG_CC_N); 622 tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, QREG_CC_N); 623 tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, t0); 624 tcg_temp_free(t0); 625 tcg_gen_mov_i32(QREG_CC_N, QREG_CC_Z); 626 break; 627 628 case CC_OP_LOGIC: 629 tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N); 630 tcg_gen_movi_i32(QREG_CC_C, 0); 631 tcg_gen_movi_i32(QREG_CC_V, 0); 632 break; 633 634 case CC_OP_DYNAMIC: 635 gen_helper_flush_flags(cpu_env, QREG_CC_OP); 636 s->cc_op_synced = 1; 637 break; 638 639 default: 640 t0 = tcg_const_i32(s->cc_op); 641 gen_helper_flush_flags(cpu_env, t0); 642 tcg_temp_free(t0); 643 s->cc_op_synced = 1; 644 break; 645 } 646 647 /* Note that flush_flags also assigned to env->cc_op. */ 648 s->cc_op = CC_OP_FLAGS; 649 } 650 651 static inline TCGv gen_extend(DisasContext *s, TCGv val, int opsize, int sign) 652 { 653 TCGv tmp; 654 655 if (opsize == OS_LONG) { 656 tmp = val; 657 } else { 658 tmp = mark_to_release(s, tcg_temp_new()); 659 gen_ext(tmp, val, opsize, sign); 660 } 661 662 return tmp; 663 } 664 665 static void gen_logic_cc(DisasContext *s, TCGv val, int opsize) 666 { 667 gen_ext(QREG_CC_N, val, opsize, 1); 668 set_cc_op(s, CC_OP_LOGIC); 669 } 670 671 static void gen_update_cc_cmp(DisasContext *s, TCGv dest, TCGv src, int opsize) 672 { 673 tcg_gen_mov_i32(QREG_CC_N, dest); 674 tcg_gen_mov_i32(QREG_CC_V, src); 675 set_cc_op(s, CC_OP_CMPB + opsize); 676 } 677 678 static void gen_update_cc_add(TCGv dest, TCGv src, int opsize) 679 { 680 gen_ext(QREG_CC_N, dest, opsize, 1); 681 tcg_gen_mov_i32(QREG_CC_V, src); 682 } 683 684 static inline int opsize_bytes(int opsize) 685 { 686 switch (opsize) { 687 case OS_BYTE: return 1; 688 case OS_WORD: return 2; 689 case OS_LONG: return 4; 690 case OS_SINGLE: return 4; 691 case OS_DOUBLE: return 8; 692 case OS_EXTENDED: return 12; 693 case OS_PACKED: return 12; 694 default: 695 g_assert_not_reached(); 696 } 697 } 698 699 static inline int insn_opsize(int insn) 700 { 701 switch ((insn >> 6) & 3) { 702 case 0: return OS_BYTE; 703 case 1: return OS_WORD; 704 case 2: return OS_LONG; 705 default: 706 g_assert_not_reached(); 707 } 708 } 709 710 static inline int ext_opsize(int ext, int pos) 711 { 712 switch ((ext >> pos) & 7) { 713 case 0: return OS_LONG; 714 case 1: return OS_SINGLE; 715 case 2: return OS_EXTENDED; 716 case 3: return OS_PACKED; 717 case 4: return OS_WORD; 718 case 5: return OS_DOUBLE; 719 case 6: return OS_BYTE; 720 default: 721 g_assert_not_reached(); 722 } 723 } 724 725 /* 726 * Assign value to a register. If the width is less than the register width 727 * only the low part of the register is set. 728 */ 729 static void gen_partset_reg(int opsize, TCGv reg, TCGv val) 730 { 731 TCGv tmp; 732 switch (opsize) { 733 case OS_BYTE: 734 tcg_gen_andi_i32(reg, reg, 0xffffff00); 735 tmp = tcg_temp_new(); 736 tcg_gen_ext8u_i32(tmp, val); 737 tcg_gen_or_i32(reg, reg, tmp); 738 tcg_temp_free(tmp); 739 break; 740 case OS_WORD: 741 tcg_gen_andi_i32(reg, reg, 0xffff0000); 742 tmp = tcg_temp_new(); 743 tcg_gen_ext16u_i32(tmp, val); 744 tcg_gen_or_i32(reg, reg, tmp); 745 tcg_temp_free(tmp); 746 break; 747 case OS_LONG: 748 case OS_SINGLE: 749 tcg_gen_mov_i32(reg, val); 750 break; 751 default: 752 g_assert_not_reached(); 753 } 754 } 755 756 /* 757 * Generate code for an "effective address". Does not adjust the base 758 * register for autoincrement addressing modes. 759 */ 760 static TCGv gen_lea_mode(CPUM68KState *env, DisasContext *s, 761 int mode, int reg0, int opsize) 762 { 763 TCGv reg; 764 TCGv tmp; 765 uint16_t ext; 766 uint32_t offset; 767 768 switch (mode) { 769 case 0: /* Data register direct. */ 770 case 1: /* Address register direct. */ 771 return NULL_QREG; 772 case 3: /* Indirect postincrement. */ 773 if (opsize == OS_UNSIZED) { 774 return NULL_QREG; 775 } 776 /* fallthru */ 777 case 2: /* Indirect register */ 778 return get_areg(s, reg0); 779 case 4: /* Indirect predecrememnt. */ 780 if (opsize == OS_UNSIZED) { 781 return NULL_QREG; 782 } 783 reg = get_areg(s, reg0); 784 tmp = mark_to_release(s, tcg_temp_new()); 785 if (reg0 == 7 && opsize == OS_BYTE && 786 m68k_feature(s->env, M68K_FEATURE_M68000)) { 787 tcg_gen_subi_i32(tmp, reg, 2); 788 } else { 789 tcg_gen_subi_i32(tmp, reg, opsize_bytes(opsize)); 790 } 791 return tmp; 792 case 5: /* Indirect displacement. */ 793 reg = get_areg(s, reg0); 794 tmp = mark_to_release(s, tcg_temp_new()); 795 ext = read_im16(env, s); 796 tcg_gen_addi_i32(tmp, reg, (int16_t)ext); 797 return tmp; 798 case 6: /* Indirect index + displacement. */ 799 reg = get_areg(s, reg0); 800 return gen_lea_indexed(env, s, reg); 801 case 7: /* Other */ 802 switch (reg0) { 803 case 0: /* Absolute short. */ 804 offset = (int16_t)read_im16(env, s); 805 return mark_to_release(s, tcg_const_i32(offset)); 806 case 1: /* Absolute long. */ 807 offset = read_im32(env, s); 808 return mark_to_release(s, tcg_const_i32(offset)); 809 case 2: /* pc displacement */ 810 offset = s->pc; 811 offset += (int16_t)read_im16(env, s); 812 return mark_to_release(s, tcg_const_i32(offset)); 813 case 3: /* pc index+displacement. */ 814 return gen_lea_indexed(env, s, NULL_QREG); 815 case 4: /* Immediate. */ 816 default: 817 return NULL_QREG; 818 } 819 } 820 /* Should never happen. */ 821 return NULL_QREG; 822 } 823 824 static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn, 825 int opsize) 826 { 827 int mode = extract32(insn, 3, 3); 828 int reg0 = REG(insn, 0); 829 return gen_lea_mode(env, s, mode, reg0, opsize); 830 } 831 832 /* 833 * Generate code to load/store a value from/into an EA. If WHAT > 0 this is 834 * a write otherwise it is a read (0 == sign extend, -1 == zero extend). 835 * ADDRP is non-null for readwrite operands. 836 */ 837 static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0, 838 int opsize, TCGv val, TCGv *addrp, ea_what what, 839 int index) 840 { 841 TCGv reg, tmp, result; 842 int32_t offset; 843 844 switch (mode) { 845 case 0: /* Data register direct. */ 846 reg = cpu_dregs[reg0]; 847 if (what == EA_STORE) { 848 gen_partset_reg(opsize, reg, val); 849 return store_dummy; 850 } else { 851 return gen_extend(s, reg, opsize, what == EA_LOADS); 852 } 853 case 1: /* Address register direct. */ 854 reg = get_areg(s, reg0); 855 if (what == EA_STORE) { 856 tcg_gen_mov_i32(reg, val); 857 return store_dummy; 858 } else { 859 return gen_extend(s, reg, opsize, what == EA_LOADS); 860 } 861 case 2: /* Indirect register */ 862 reg = get_areg(s, reg0); 863 return gen_ldst(s, opsize, reg, val, what, index); 864 case 3: /* Indirect postincrement. */ 865 reg = get_areg(s, reg0); 866 result = gen_ldst(s, opsize, reg, val, what, index); 867 if (what == EA_STORE || !addrp) { 868 TCGv tmp = tcg_temp_new(); 869 if (reg0 == 7 && opsize == OS_BYTE && 870 m68k_feature(s->env, M68K_FEATURE_M68000)) { 871 tcg_gen_addi_i32(tmp, reg, 2); 872 } else { 873 tcg_gen_addi_i32(tmp, reg, opsize_bytes(opsize)); 874 } 875 delay_set_areg(s, reg0, tmp, true); 876 } 877 return result; 878 case 4: /* Indirect predecrememnt. */ 879 if (addrp && what == EA_STORE) { 880 tmp = *addrp; 881 } else { 882 tmp = gen_lea_mode(env, s, mode, reg0, opsize); 883 if (IS_NULL_QREG(tmp)) { 884 return tmp; 885 } 886 if (addrp) { 887 *addrp = tmp; 888 } 889 } 890 result = gen_ldst(s, opsize, tmp, val, what, index); 891 if (what == EA_STORE || !addrp) { 892 delay_set_areg(s, reg0, tmp, false); 893 } 894 return result; 895 case 5: /* Indirect displacement. */ 896 case 6: /* Indirect index + displacement. */ 897 do_indirect: 898 if (addrp && what == EA_STORE) { 899 tmp = *addrp; 900 } else { 901 tmp = gen_lea_mode(env, s, mode, reg0, opsize); 902 if (IS_NULL_QREG(tmp)) { 903 return tmp; 904 } 905 if (addrp) { 906 *addrp = tmp; 907 } 908 } 909 return gen_ldst(s, opsize, tmp, val, what, index); 910 case 7: /* Other */ 911 switch (reg0) { 912 case 0: /* Absolute short. */ 913 case 1: /* Absolute long. */ 914 case 2: /* pc displacement */ 915 case 3: /* pc index+displacement. */ 916 goto do_indirect; 917 case 4: /* Immediate. */ 918 /* Sign extend values for consistency. */ 919 switch (opsize) { 920 case OS_BYTE: 921 if (what == EA_LOADS) { 922 offset = (int8_t)read_im8(env, s); 923 } else { 924 offset = read_im8(env, s); 925 } 926 break; 927 case OS_WORD: 928 if (what == EA_LOADS) { 929 offset = (int16_t)read_im16(env, s); 930 } else { 931 offset = read_im16(env, s); 932 } 933 break; 934 case OS_LONG: 935 offset = read_im32(env, s); 936 break; 937 default: 938 g_assert_not_reached(); 939 } 940 return mark_to_release(s, tcg_const_i32(offset)); 941 default: 942 return NULL_QREG; 943 } 944 } 945 /* Should never happen. */ 946 return NULL_QREG; 947 } 948 949 static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn, 950 int opsize, TCGv val, TCGv *addrp, ea_what what, int index) 951 { 952 int mode = extract32(insn, 3, 3); 953 int reg0 = REG(insn, 0); 954 return gen_ea_mode(env, s, mode, reg0, opsize, val, addrp, what, index); 955 } 956 957 static TCGv_ptr gen_fp_ptr(int freg) 958 { 959 TCGv_ptr fp = tcg_temp_new_ptr(); 960 tcg_gen_addi_ptr(fp, cpu_env, offsetof(CPUM68KState, fregs[freg])); 961 return fp; 962 } 963 964 static TCGv_ptr gen_fp_result_ptr(void) 965 { 966 TCGv_ptr fp = tcg_temp_new_ptr(); 967 tcg_gen_addi_ptr(fp, cpu_env, offsetof(CPUM68KState, fp_result)); 968 return fp; 969 } 970 971 static void gen_fp_move(TCGv_ptr dest, TCGv_ptr src) 972 { 973 TCGv t32; 974 TCGv_i64 t64; 975 976 t32 = tcg_temp_new(); 977 tcg_gen_ld16u_i32(t32, src, offsetof(FPReg, l.upper)); 978 tcg_gen_st16_i32(t32, dest, offsetof(FPReg, l.upper)); 979 tcg_temp_free(t32); 980 981 t64 = tcg_temp_new_i64(); 982 tcg_gen_ld_i64(t64, src, offsetof(FPReg, l.lower)); 983 tcg_gen_st_i64(t64, dest, offsetof(FPReg, l.lower)); 984 tcg_temp_free_i64(t64); 985 } 986 987 static void gen_load_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp, 988 int index) 989 { 990 TCGv tmp; 991 TCGv_i64 t64; 992 993 t64 = tcg_temp_new_i64(); 994 tmp = tcg_temp_new(); 995 switch (opsize) { 996 case OS_BYTE: 997 tcg_gen_qemu_ld8s(tmp, addr, index); 998 gen_helper_exts32(cpu_env, fp, tmp); 999 break; 1000 case OS_WORD: 1001 tcg_gen_qemu_ld16s(tmp, addr, index); 1002 gen_helper_exts32(cpu_env, fp, tmp); 1003 break; 1004 case OS_LONG: 1005 tcg_gen_qemu_ld32u(tmp, addr, index); 1006 gen_helper_exts32(cpu_env, fp, tmp); 1007 break; 1008 case OS_SINGLE: 1009 tcg_gen_qemu_ld32u(tmp, addr, index); 1010 gen_helper_extf32(cpu_env, fp, tmp); 1011 break; 1012 case OS_DOUBLE: 1013 tcg_gen_qemu_ld64(t64, addr, index); 1014 gen_helper_extf64(cpu_env, fp, t64); 1015 break; 1016 case OS_EXTENDED: 1017 if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) { 1018 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP); 1019 break; 1020 } 1021 tcg_gen_qemu_ld32u(tmp, addr, index); 1022 tcg_gen_shri_i32(tmp, tmp, 16); 1023 tcg_gen_st16_i32(tmp, fp, offsetof(FPReg, l.upper)); 1024 tcg_gen_addi_i32(tmp, addr, 4); 1025 tcg_gen_qemu_ld64(t64, tmp, index); 1026 tcg_gen_st_i64(t64, fp, offsetof(FPReg, l.lower)); 1027 break; 1028 case OS_PACKED: 1029 /* 1030 * unimplemented data type on 68040/ColdFire 1031 * FIXME if needed for another FPU 1032 */ 1033 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP); 1034 break; 1035 default: 1036 g_assert_not_reached(); 1037 } 1038 tcg_temp_free(tmp); 1039 tcg_temp_free_i64(t64); 1040 } 1041 1042 static void gen_store_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp, 1043 int index) 1044 { 1045 TCGv tmp; 1046 TCGv_i64 t64; 1047 1048 t64 = tcg_temp_new_i64(); 1049 tmp = tcg_temp_new(); 1050 switch (opsize) { 1051 case OS_BYTE: 1052 gen_helper_reds32(tmp, cpu_env, fp); 1053 tcg_gen_qemu_st8(tmp, addr, index); 1054 break; 1055 case OS_WORD: 1056 gen_helper_reds32(tmp, cpu_env, fp); 1057 tcg_gen_qemu_st16(tmp, addr, index); 1058 break; 1059 case OS_LONG: 1060 gen_helper_reds32(tmp, cpu_env, fp); 1061 tcg_gen_qemu_st32(tmp, addr, index); 1062 break; 1063 case OS_SINGLE: 1064 gen_helper_redf32(tmp, cpu_env, fp); 1065 tcg_gen_qemu_st32(tmp, addr, index); 1066 break; 1067 case OS_DOUBLE: 1068 gen_helper_redf64(t64, cpu_env, fp); 1069 tcg_gen_qemu_st64(t64, addr, index); 1070 break; 1071 case OS_EXTENDED: 1072 if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) { 1073 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP); 1074 break; 1075 } 1076 tcg_gen_ld16u_i32(tmp, fp, offsetof(FPReg, l.upper)); 1077 tcg_gen_shli_i32(tmp, tmp, 16); 1078 tcg_gen_qemu_st32(tmp, addr, index); 1079 tcg_gen_addi_i32(tmp, addr, 4); 1080 tcg_gen_ld_i64(t64, fp, offsetof(FPReg, l.lower)); 1081 tcg_gen_qemu_st64(t64, tmp, index); 1082 break; 1083 case OS_PACKED: 1084 /* 1085 * unimplemented data type on 68040/ColdFire 1086 * FIXME if needed for another FPU 1087 */ 1088 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP); 1089 break; 1090 default: 1091 g_assert_not_reached(); 1092 } 1093 tcg_temp_free(tmp); 1094 tcg_temp_free_i64(t64); 1095 } 1096 1097 static void gen_ldst_fp(DisasContext *s, int opsize, TCGv addr, 1098 TCGv_ptr fp, ea_what what, int index) 1099 { 1100 if (what == EA_STORE) { 1101 gen_store_fp(s, opsize, addr, fp, index); 1102 } else { 1103 gen_load_fp(s, opsize, addr, fp, index); 1104 } 1105 } 1106 1107 static int gen_ea_mode_fp(CPUM68KState *env, DisasContext *s, int mode, 1108 int reg0, int opsize, TCGv_ptr fp, ea_what what, 1109 int index) 1110 { 1111 TCGv reg, addr, tmp; 1112 TCGv_i64 t64; 1113 1114 switch (mode) { 1115 case 0: /* Data register direct. */ 1116 reg = cpu_dregs[reg0]; 1117 if (what == EA_STORE) { 1118 switch (opsize) { 1119 case OS_BYTE: 1120 case OS_WORD: 1121 case OS_LONG: 1122 gen_helper_reds32(reg, cpu_env, fp); 1123 break; 1124 case OS_SINGLE: 1125 gen_helper_redf32(reg, cpu_env, fp); 1126 break; 1127 default: 1128 g_assert_not_reached(); 1129 } 1130 } else { 1131 tmp = tcg_temp_new(); 1132 switch (opsize) { 1133 case OS_BYTE: 1134 tcg_gen_ext8s_i32(tmp, reg); 1135 gen_helper_exts32(cpu_env, fp, tmp); 1136 break; 1137 case OS_WORD: 1138 tcg_gen_ext16s_i32(tmp, reg); 1139 gen_helper_exts32(cpu_env, fp, tmp); 1140 break; 1141 case OS_LONG: 1142 gen_helper_exts32(cpu_env, fp, reg); 1143 break; 1144 case OS_SINGLE: 1145 gen_helper_extf32(cpu_env, fp, reg); 1146 break; 1147 default: 1148 g_assert_not_reached(); 1149 } 1150 tcg_temp_free(tmp); 1151 } 1152 return 0; 1153 case 1: /* Address register direct. */ 1154 return -1; 1155 case 2: /* Indirect register */ 1156 addr = get_areg(s, reg0); 1157 gen_ldst_fp(s, opsize, addr, fp, what, index); 1158 return 0; 1159 case 3: /* Indirect postincrement. */ 1160 addr = cpu_aregs[reg0]; 1161 gen_ldst_fp(s, opsize, addr, fp, what, index); 1162 tcg_gen_addi_i32(addr, addr, opsize_bytes(opsize)); 1163 return 0; 1164 case 4: /* Indirect predecrememnt. */ 1165 addr = gen_lea_mode(env, s, mode, reg0, opsize); 1166 if (IS_NULL_QREG(addr)) { 1167 return -1; 1168 } 1169 gen_ldst_fp(s, opsize, addr, fp, what, index); 1170 tcg_gen_mov_i32(cpu_aregs[reg0], addr); 1171 return 0; 1172 case 5: /* Indirect displacement. */ 1173 case 6: /* Indirect index + displacement. */ 1174 do_indirect: 1175 addr = gen_lea_mode(env, s, mode, reg0, opsize); 1176 if (IS_NULL_QREG(addr)) { 1177 return -1; 1178 } 1179 gen_ldst_fp(s, opsize, addr, fp, what, index); 1180 return 0; 1181 case 7: /* Other */ 1182 switch (reg0) { 1183 case 0: /* Absolute short. */ 1184 case 1: /* Absolute long. */ 1185 case 2: /* pc displacement */ 1186 case 3: /* pc index+displacement. */ 1187 goto do_indirect; 1188 case 4: /* Immediate. */ 1189 if (what == EA_STORE) { 1190 return -1; 1191 } 1192 switch (opsize) { 1193 case OS_BYTE: 1194 tmp = tcg_const_i32((int8_t)read_im8(env, s)); 1195 gen_helper_exts32(cpu_env, fp, tmp); 1196 tcg_temp_free(tmp); 1197 break; 1198 case OS_WORD: 1199 tmp = tcg_const_i32((int16_t)read_im16(env, s)); 1200 gen_helper_exts32(cpu_env, fp, tmp); 1201 tcg_temp_free(tmp); 1202 break; 1203 case OS_LONG: 1204 tmp = tcg_const_i32(read_im32(env, s)); 1205 gen_helper_exts32(cpu_env, fp, tmp); 1206 tcg_temp_free(tmp); 1207 break; 1208 case OS_SINGLE: 1209 tmp = tcg_const_i32(read_im32(env, s)); 1210 gen_helper_extf32(cpu_env, fp, tmp); 1211 tcg_temp_free(tmp); 1212 break; 1213 case OS_DOUBLE: 1214 t64 = tcg_const_i64(read_im64(env, s)); 1215 gen_helper_extf64(cpu_env, fp, t64); 1216 tcg_temp_free_i64(t64); 1217 break; 1218 case OS_EXTENDED: 1219 if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) { 1220 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP); 1221 break; 1222 } 1223 tmp = tcg_const_i32(read_im32(env, s) >> 16); 1224 tcg_gen_st16_i32(tmp, fp, offsetof(FPReg, l.upper)); 1225 tcg_temp_free(tmp); 1226 t64 = tcg_const_i64(read_im64(env, s)); 1227 tcg_gen_st_i64(t64, fp, offsetof(FPReg, l.lower)); 1228 tcg_temp_free_i64(t64); 1229 break; 1230 case OS_PACKED: 1231 /* 1232 * unimplemented data type on 68040/ColdFire 1233 * FIXME if needed for another FPU 1234 */ 1235 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP); 1236 break; 1237 default: 1238 g_assert_not_reached(); 1239 } 1240 return 0; 1241 default: 1242 return -1; 1243 } 1244 } 1245 return -1; 1246 } 1247 1248 static int gen_ea_fp(CPUM68KState *env, DisasContext *s, uint16_t insn, 1249 int opsize, TCGv_ptr fp, ea_what what, int index) 1250 { 1251 int mode = extract32(insn, 3, 3); 1252 int reg0 = REG(insn, 0); 1253 return gen_ea_mode_fp(env, s, mode, reg0, opsize, fp, what, index); 1254 } 1255 1256 typedef struct { 1257 TCGCond tcond; 1258 bool g1; 1259 bool g2; 1260 TCGv v1; 1261 TCGv v2; 1262 } DisasCompare; 1263 1264 static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond) 1265 { 1266 TCGv tmp, tmp2; 1267 TCGCond tcond; 1268 CCOp op = s->cc_op; 1269 1270 /* The CC_OP_CMP form can handle most normal comparisons directly. */ 1271 if (op == CC_OP_CMPB || op == CC_OP_CMPW || op == CC_OP_CMPL) { 1272 c->g1 = c->g2 = 1; 1273 c->v1 = QREG_CC_N; 1274 c->v2 = QREG_CC_V; 1275 switch (cond) { 1276 case 2: /* HI */ 1277 case 3: /* LS */ 1278 tcond = TCG_COND_LEU; 1279 goto done; 1280 case 4: /* CC */ 1281 case 5: /* CS */ 1282 tcond = TCG_COND_LTU; 1283 goto done; 1284 case 6: /* NE */ 1285 case 7: /* EQ */ 1286 tcond = TCG_COND_EQ; 1287 goto done; 1288 case 10: /* PL */ 1289 case 11: /* MI */ 1290 c->g1 = c->g2 = 0; 1291 c->v2 = tcg_const_i32(0); 1292 c->v1 = tmp = tcg_temp_new(); 1293 tcg_gen_sub_i32(tmp, QREG_CC_N, QREG_CC_V); 1294 gen_ext(tmp, tmp, op - CC_OP_CMPB, 1); 1295 /* fallthru */ 1296 case 12: /* GE */ 1297 case 13: /* LT */ 1298 tcond = TCG_COND_LT; 1299 goto done; 1300 case 14: /* GT */ 1301 case 15: /* LE */ 1302 tcond = TCG_COND_LE; 1303 goto done; 1304 } 1305 } 1306 1307 c->g1 = 1; 1308 c->g2 = 0; 1309 c->v2 = tcg_const_i32(0); 1310 1311 switch (cond) { 1312 case 0: /* T */ 1313 case 1: /* F */ 1314 c->v1 = c->v2; 1315 tcond = TCG_COND_NEVER; 1316 goto done; 1317 case 14: /* GT (!(Z || (N ^ V))) */ 1318 case 15: /* LE (Z || (N ^ V)) */ 1319 /* 1320 * Logic operations clear V, which simplifies LE to (Z || N), 1321 * and since Z and N are co-located, this becomes a normal 1322 * comparison vs N. 1323 */ 1324 if (op == CC_OP_LOGIC) { 1325 c->v1 = QREG_CC_N; 1326 tcond = TCG_COND_LE; 1327 goto done; 1328 } 1329 break; 1330 case 12: /* GE (!(N ^ V)) */ 1331 case 13: /* LT (N ^ V) */ 1332 /* Logic operations clear V, which simplifies this to N. */ 1333 if (op != CC_OP_LOGIC) { 1334 break; 1335 } 1336 /* fallthru */ 1337 case 10: /* PL (!N) */ 1338 case 11: /* MI (N) */ 1339 /* Several cases represent N normally. */ 1340 if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL || 1341 op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL || 1342 op == CC_OP_LOGIC) { 1343 c->v1 = QREG_CC_N; 1344 tcond = TCG_COND_LT; 1345 goto done; 1346 } 1347 break; 1348 case 6: /* NE (!Z) */ 1349 case 7: /* EQ (Z) */ 1350 /* Some cases fold Z into N. */ 1351 if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL || 1352 op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL || 1353 op == CC_OP_LOGIC) { 1354 tcond = TCG_COND_EQ; 1355 c->v1 = QREG_CC_N; 1356 goto done; 1357 } 1358 break; 1359 case 4: /* CC (!C) */ 1360 case 5: /* CS (C) */ 1361 /* Some cases fold C into X. */ 1362 if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL || 1363 op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL) { 1364 tcond = TCG_COND_NE; 1365 c->v1 = QREG_CC_X; 1366 goto done; 1367 } 1368 /* fallthru */ 1369 case 8: /* VC (!V) */ 1370 case 9: /* VS (V) */ 1371 /* Logic operations clear V and C. */ 1372 if (op == CC_OP_LOGIC) { 1373 tcond = TCG_COND_NEVER; 1374 c->v1 = c->v2; 1375 goto done; 1376 } 1377 break; 1378 } 1379 1380 /* Otherwise, flush flag state to CC_OP_FLAGS. */ 1381 gen_flush_flags(s); 1382 1383 switch (cond) { 1384 case 0: /* T */ 1385 case 1: /* F */ 1386 default: 1387 /* Invalid, or handled above. */ 1388 abort(); 1389 case 2: /* HI (!C && !Z) -> !(C || Z)*/ 1390 case 3: /* LS (C || Z) */ 1391 c->v1 = tmp = tcg_temp_new(); 1392 c->g1 = 0; 1393 tcg_gen_setcond_i32(TCG_COND_EQ, tmp, QREG_CC_Z, c->v2); 1394 tcg_gen_or_i32(tmp, tmp, QREG_CC_C); 1395 tcond = TCG_COND_NE; 1396 break; 1397 case 4: /* CC (!C) */ 1398 case 5: /* CS (C) */ 1399 c->v1 = QREG_CC_C; 1400 tcond = TCG_COND_NE; 1401 break; 1402 case 6: /* NE (!Z) */ 1403 case 7: /* EQ (Z) */ 1404 c->v1 = QREG_CC_Z; 1405 tcond = TCG_COND_EQ; 1406 break; 1407 case 8: /* VC (!V) */ 1408 case 9: /* VS (V) */ 1409 c->v1 = QREG_CC_V; 1410 tcond = TCG_COND_LT; 1411 break; 1412 case 10: /* PL (!N) */ 1413 case 11: /* MI (N) */ 1414 c->v1 = QREG_CC_N; 1415 tcond = TCG_COND_LT; 1416 break; 1417 case 12: /* GE (!(N ^ V)) */ 1418 case 13: /* LT (N ^ V) */ 1419 c->v1 = tmp = tcg_temp_new(); 1420 c->g1 = 0; 1421 tcg_gen_xor_i32(tmp, QREG_CC_N, QREG_CC_V); 1422 tcond = TCG_COND_LT; 1423 break; 1424 case 14: /* GT (!(Z || (N ^ V))) */ 1425 case 15: /* LE (Z || (N ^ V)) */ 1426 c->v1 = tmp = tcg_temp_new(); 1427 c->g1 = 0; 1428 tcg_gen_setcond_i32(TCG_COND_EQ, tmp, QREG_CC_Z, c->v2); 1429 tcg_gen_neg_i32(tmp, tmp); 1430 tmp2 = tcg_temp_new(); 1431 tcg_gen_xor_i32(tmp2, QREG_CC_N, QREG_CC_V); 1432 tcg_gen_or_i32(tmp, tmp, tmp2); 1433 tcg_temp_free(tmp2); 1434 tcond = TCG_COND_LT; 1435 break; 1436 } 1437 1438 done: 1439 if ((cond & 1) == 0) { 1440 tcond = tcg_invert_cond(tcond); 1441 } 1442 c->tcond = tcond; 1443 } 1444 1445 static void free_cond(DisasCompare *c) 1446 { 1447 if (!c->g1) { 1448 tcg_temp_free(c->v1); 1449 } 1450 if (!c->g2) { 1451 tcg_temp_free(c->v2); 1452 } 1453 } 1454 1455 static void gen_jmpcc(DisasContext *s, int cond, TCGLabel *l1) 1456 { 1457 DisasCompare c; 1458 1459 gen_cc_cond(&c, s, cond); 1460 update_cc_op(s); 1461 tcg_gen_brcond_i32(c.tcond, c.v1, c.v2, l1); 1462 free_cond(&c); 1463 } 1464 1465 /* Force a TB lookup after an instruction that changes the CPU state. */ 1466 static void gen_exit_tb(DisasContext *s) 1467 { 1468 update_cc_op(s); 1469 tcg_gen_movi_i32(QREG_PC, s->pc); 1470 s->base.is_jmp = DISAS_EXIT; 1471 } 1472 1473 #define SRC_EA(env, result, opsize, op_sign, addrp) do { \ 1474 result = gen_ea(env, s, insn, opsize, NULL_QREG, addrp, \ 1475 op_sign ? EA_LOADS : EA_LOADU, IS_USER(s)); \ 1476 if (IS_NULL_QREG(result)) { \ 1477 gen_addr_fault(s); \ 1478 return; \ 1479 } \ 1480 } while (0) 1481 1482 #define DEST_EA(env, insn, opsize, val, addrp) do { \ 1483 TCGv ea_result = gen_ea(env, s, insn, opsize, val, addrp, \ 1484 EA_STORE, IS_USER(s)); \ 1485 if (IS_NULL_QREG(ea_result)) { \ 1486 gen_addr_fault(s); \ 1487 return; \ 1488 } \ 1489 } while (0) 1490 1491 static inline bool use_goto_tb(DisasContext *s, uint32_t dest) 1492 { 1493 #ifndef CONFIG_USER_ONLY 1494 return (s->base.pc_first & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) 1495 || (s->base.pc_next & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); 1496 #else 1497 return true; 1498 #endif 1499 } 1500 1501 /* Generate a jump to an immediate address. */ 1502 static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest) 1503 { 1504 if (unlikely(s->base.singlestep_enabled)) { 1505 gen_exception(s, dest, EXCP_DEBUG); 1506 } else if (use_goto_tb(s, dest)) { 1507 tcg_gen_goto_tb(n); 1508 tcg_gen_movi_i32(QREG_PC, dest); 1509 tcg_gen_exit_tb(s->base.tb, n); 1510 } else { 1511 gen_jmp_im(s, dest); 1512 tcg_gen_exit_tb(NULL, 0); 1513 } 1514 s->base.is_jmp = DISAS_NORETURN; 1515 } 1516 1517 DISAS_INSN(scc) 1518 { 1519 DisasCompare c; 1520 int cond; 1521 TCGv tmp; 1522 1523 cond = (insn >> 8) & 0xf; 1524 gen_cc_cond(&c, s, cond); 1525 1526 tmp = tcg_temp_new(); 1527 tcg_gen_setcond_i32(c.tcond, tmp, c.v1, c.v2); 1528 free_cond(&c); 1529 1530 tcg_gen_neg_i32(tmp, tmp); 1531 DEST_EA(env, insn, OS_BYTE, tmp, NULL); 1532 tcg_temp_free(tmp); 1533 } 1534 1535 DISAS_INSN(dbcc) 1536 { 1537 TCGLabel *l1; 1538 TCGv reg; 1539 TCGv tmp; 1540 int16_t offset; 1541 uint32_t base; 1542 1543 reg = DREG(insn, 0); 1544 base = s->pc; 1545 offset = (int16_t)read_im16(env, s); 1546 l1 = gen_new_label(); 1547 gen_jmpcc(s, (insn >> 8) & 0xf, l1); 1548 1549 tmp = tcg_temp_new(); 1550 tcg_gen_ext16s_i32(tmp, reg); 1551 tcg_gen_addi_i32(tmp, tmp, -1); 1552 gen_partset_reg(OS_WORD, reg, tmp); 1553 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, -1, l1); 1554 gen_jmp_tb(s, 1, base + offset); 1555 gen_set_label(l1); 1556 gen_jmp_tb(s, 0, s->pc); 1557 } 1558 1559 DISAS_INSN(undef_mac) 1560 { 1561 gen_exception(s, s->base.pc_next, EXCP_LINEA); 1562 } 1563 1564 DISAS_INSN(undef_fpu) 1565 { 1566 gen_exception(s, s->base.pc_next, EXCP_LINEF); 1567 } 1568 1569 DISAS_INSN(undef) 1570 { 1571 /* 1572 * ??? This is both instructions that are as yet unimplemented 1573 * for the 680x0 series, as well as those that are implemented 1574 * but actually illegal for CPU32 or pre-68020. 1575 */ 1576 qemu_log_mask(LOG_UNIMP, "Illegal instruction: %04x @ %08x\n", 1577 insn, s->base.pc_next); 1578 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL); 1579 } 1580 1581 DISAS_INSN(mulw) 1582 { 1583 TCGv reg; 1584 TCGv tmp; 1585 TCGv src; 1586 int sign; 1587 1588 sign = (insn & 0x100) != 0; 1589 reg = DREG(insn, 9); 1590 tmp = tcg_temp_new(); 1591 if (sign) 1592 tcg_gen_ext16s_i32(tmp, reg); 1593 else 1594 tcg_gen_ext16u_i32(tmp, reg); 1595 SRC_EA(env, src, OS_WORD, sign, NULL); 1596 tcg_gen_mul_i32(tmp, tmp, src); 1597 tcg_gen_mov_i32(reg, tmp); 1598 gen_logic_cc(s, tmp, OS_LONG); 1599 tcg_temp_free(tmp); 1600 } 1601 1602 DISAS_INSN(divw) 1603 { 1604 int sign; 1605 TCGv src; 1606 TCGv destr; 1607 1608 /* divX.w <EA>,Dn 32/16 -> 16r:16q */ 1609 1610 sign = (insn & 0x100) != 0; 1611 1612 /* dest.l / src.w */ 1613 1614 SRC_EA(env, src, OS_WORD, sign, NULL); 1615 destr = tcg_const_i32(REG(insn, 9)); 1616 if (sign) { 1617 gen_helper_divsw(cpu_env, destr, src); 1618 } else { 1619 gen_helper_divuw(cpu_env, destr, src); 1620 } 1621 tcg_temp_free(destr); 1622 1623 set_cc_op(s, CC_OP_FLAGS); 1624 } 1625 1626 DISAS_INSN(divl) 1627 { 1628 TCGv num, reg, den; 1629 int sign; 1630 uint16_t ext; 1631 1632 ext = read_im16(env, s); 1633 1634 sign = (ext & 0x0800) != 0; 1635 1636 if (ext & 0x400) { 1637 if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) { 1638 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL); 1639 return; 1640 } 1641 1642 /* divX.l <EA>, Dr:Dq 64/32 -> 32r:32q */ 1643 1644 SRC_EA(env, den, OS_LONG, 0, NULL); 1645 num = tcg_const_i32(REG(ext, 12)); 1646 reg = tcg_const_i32(REG(ext, 0)); 1647 if (sign) { 1648 gen_helper_divsll(cpu_env, num, reg, den); 1649 } else { 1650 gen_helper_divull(cpu_env, num, reg, den); 1651 } 1652 tcg_temp_free(reg); 1653 tcg_temp_free(num); 1654 set_cc_op(s, CC_OP_FLAGS); 1655 return; 1656 } 1657 1658 /* divX.l <EA>, Dq 32/32 -> 32q */ 1659 /* divXl.l <EA>, Dr:Dq 32/32 -> 32r:32q */ 1660 1661 SRC_EA(env, den, OS_LONG, 0, NULL); 1662 num = tcg_const_i32(REG(ext, 12)); 1663 reg = tcg_const_i32(REG(ext, 0)); 1664 if (sign) { 1665 gen_helper_divsl(cpu_env, num, reg, den); 1666 } else { 1667 gen_helper_divul(cpu_env, num, reg, den); 1668 } 1669 tcg_temp_free(reg); 1670 tcg_temp_free(num); 1671 1672 set_cc_op(s, CC_OP_FLAGS); 1673 } 1674 1675 static void bcd_add(TCGv dest, TCGv src) 1676 { 1677 TCGv t0, t1; 1678 1679 /* 1680 * dest10 = dest10 + src10 + X 1681 * 1682 * t1 = src 1683 * t2 = t1 + 0x066 1684 * t3 = t2 + dest + X 1685 * t4 = t2 ^ dest 1686 * t5 = t3 ^ t4 1687 * t6 = ~t5 & 0x110 1688 * t7 = (t6 >> 2) | (t6 >> 3) 1689 * return t3 - t7 1690 */ 1691 1692 /* 1693 * t1 = (src + 0x066) + dest + X 1694 * = result with some possible exceding 0x6 1695 */ 1696 1697 t0 = tcg_const_i32(0x066); 1698 tcg_gen_add_i32(t0, t0, src); 1699 1700 t1 = tcg_temp_new(); 1701 tcg_gen_add_i32(t1, t0, dest); 1702 tcg_gen_add_i32(t1, t1, QREG_CC_X); 1703 1704 /* we will remove exceding 0x6 where there is no carry */ 1705 1706 /* 1707 * t0 = (src + 0x0066) ^ dest 1708 * = t1 without carries 1709 */ 1710 1711 tcg_gen_xor_i32(t0, t0, dest); 1712 1713 /* 1714 * extract the carries 1715 * t0 = t0 ^ t1 1716 * = only the carries 1717 */ 1718 1719 tcg_gen_xor_i32(t0, t0, t1); 1720 1721 /* 1722 * generate 0x1 where there is no carry 1723 * and for each 0x10, generate a 0x6 1724 */ 1725 1726 tcg_gen_shri_i32(t0, t0, 3); 1727 tcg_gen_not_i32(t0, t0); 1728 tcg_gen_andi_i32(t0, t0, 0x22); 1729 tcg_gen_add_i32(dest, t0, t0); 1730 tcg_gen_add_i32(dest, dest, t0); 1731 tcg_temp_free(t0); 1732 1733 /* 1734 * remove the exceding 0x6 1735 * for digits that have not generated a carry 1736 */ 1737 1738 tcg_gen_sub_i32(dest, t1, dest); 1739 tcg_temp_free(t1); 1740 } 1741 1742 static void bcd_sub(TCGv dest, TCGv src) 1743 { 1744 TCGv t0, t1, t2; 1745 1746 /* 1747 * dest10 = dest10 - src10 - X 1748 * = bcd_add(dest + 1 - X, 0x199 - src) 1749 */ 1750 1751 /* t0 = 0x066 + (0x199 - src) */ 1752 1753 t0 = tcg_temp_new(); 1754 tcg_gen_subfi_i32(t0, 0x1ff, src); 1755 1756 /* t1 = t0 + dest + 1 - X*/ 1757 1758 t1 = tcg_temp_new(); 1759 tcg_gen_add_i32(t1, t0, dest); 1760 tcg_gen_addi_i32(t1, t1, 1); 1761 tcg_gen_sub_i32(t1, t1, QREG_CC_X); 1762 1763 /* t2 = t0 ^ dest */ 1764 1765 t2 = tcg_temp_new(); 1766 tcg_gen_xor_i32(t2, t0, dest); 1767 1768 /* t0 = t1 ^ t2 */ 1769 1770 tcg_gen_xor_i32(t0, t1, t2); 1771 1772 /* 1773 * t2 = ~t0 & 0x110 1774 * t0 = (t2 >> 2) | (t2 >> 3) 1775 * 1776 * to fit on 8bit operands, changed in: 1777 * 1778 * t2 = ~(t0 >> 3) & 0x22 1779 * t0 = t2 + t2 1780 * t0 = t0 + t2 1781 */ 1782 1783 tcg_gen_shri_i32(t2, t0, 3); 1784 tcg_gen_not_i32(t2, t2); 1785 tcg_gen_andi_i32(t2, t2, 0x22); 1786 tcg_gen_add_i32(t0, t2, t2); 1787 tcg_gen_add_i32(t0, t0, t2); 1788 tcg_temp_free(t2); 1789 1790 /* return t1 - t0 */ 1791 1792 tcg_gen_sub_i32(dest, t1, t0); 1793 tcg_temp_free(t0); 1794 tcg_temp_free(t1); 1795 } 1796 1797 static void bcd_flags(TCGv val) 1798 { 1799 tcg_gen_andi_i32(QREG_CC_C, val, 0x0ff); 1800 tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_C); 1801 1802 tcg_gen_extract_i32(QREG_CC_C, val, 8, 1); 1803 1804 tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C); 1805 } 1806 1807 DISAS_INSN(abcd_reg) 1808 { 1809 TCGv src; 1810 TCGv dest; 1811 1812 gen_flush_flags(s); /* !Z is sticky */ 1813 1814 src = gen_extend(s, DREG(insn, 0), OS_BYTE, 0); 1815 dest = gen_extend(s, DREG(insn, 9), OS_BYTE, 0); 1816 bcd_add(dest, src); 1817 gen_partset_reg(OS_BYTE, DREG(insn, 9), dest); 1818 1819 bcd_flags(dest); 1820 } 1821 1822 DISAS_INSN(abcd_mem) 1823 { 1824 TCGv src, dest, addr; 1825 1826 gen_flush_flags(s); /* !Z is sticky */ 1827 1828 /* Indirect pre-decrement load (mode 4) */ 1829 1830 src = gen_ea_mode(env, s, 4, REG(insn, 0), OS_BYTE, 1831 NULL_QREG, NULL, EA_LOADU, IS_USER(s)); 1832 dest = gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE, 1833 NULL_QREG, &addr, EA_LOADU, IS_USER(s)); 1834 1835 bcd_add(dest, src); 1836 1837 gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE, dest, &addr, 1838 EA_STORE, IS_USER(s)); 1839 1840 bcd_flags(dest); 1841 } 1842 1843 DISAS_INSN(sbcd_reg) 1844 { 1845 TCGv src, dest; 1846 1847 gen_flush_flags(s); /* !Z is sticky */ 1848 1849 src = gen_extend(s, DREG(insn, 0), OS_BYTE, 0); 1850 dest = gen_extend(s, DREG(insn, 9), OS_BYTE, 0); 1851 1852 bcd_sub(dest, src); 1853 1854 gen_partset_reg(OS_BYTE, DREG(insn, 9), dest); 1855 1856 bcd_flags(dest); 1857 } 1858 1859 DISAS_INSN(sbcd_mem) 1860 { 1861 TCGv src, dest, addr; 1862 1863 gen_flush_flags(s); /* !Z is sticky */ 1864 1865 /* Indirect pre-decrement load (mode 4) */ 1866 1867 src = gen_ea_mode(env, s, 4, REG(insn, 0), OS_BYTE, 1868 NULL_QREG, NULL, EA_LOADU, IS_USER(s)); 1869 dest = gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE, 1870 NULL_QREG, &addr, EA_LOADU, IS_USER(s)); 1871 1872 bcd_sub(dest, src); 1873 1874 gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE, dest, &addr, 1875 EA_STORE, IS_USER(s)); 1876 1877 bcd_flags(dest); 1878 } 1879 1880 DISAS_INSN(nbcd) 1881 { 1882 TCGv src, dest; 1883 TCGv addr; 1884 1885 gen_flush_flags(s); /* !Z is sticky */ 1886 1887 SRC_EA(env, src, OS_BYTE, 0, &addr); 1888 1889 dest = tcg_const_i32(0); 1890 bcd_sub(dest, src); 1891 1892 DEST_EA(env, insn, OS_BYTE, dest, &addr); 1893 1894 bcd_flags(dest); 1895 1896 tcg_temp_free(dest); 1897 } 1898 1899 DISAS_INSN(addsub) 1900 { 1901 TCGv reg; 1902 TCGv dest; 1903 TCGv src; 1904 TCGv tmp; 1905 TCGv addr; 1906 int add; 1907 int opsize; 1908 1909 add = (insn & 0x4000) != 0; 1910 opsize = insn_opsize(insn); 1911 reg = gen_extend(s, DREG(insn, 9), opsize, 1); 1912 dest = tcg_temp_new(); 1913 if (insn & 0x100) { 1914 SRC_EA(env, tmp, opsize, 1, &addr); 1915 src = reg; 1916 } else { 1917 tmp = reg; 1918 SRC_EA(env, src, opsize, 1, NULL); 1919 } 1920 if (add) { 1921 tcg_gen_add_i32(dest, tmp, src); 1922 tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src); 1923 set_cc_op(s, CC_OP_ADDB + opsize); 1924 } else { 1925 tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, tmp, src); 1926 tcg_gen_sub_i32(dest, tmp, src); 1927 set_cc_op(s, CC_OP_SUBB + opsize); 1928 } 1929 gen_update_cc_add(dest, src, opsize); 1930 if (insn & 0x100) { 1931 DEST_EA(env, insn, opsize, dest, &addr); 1932 } else { 1933 gen_partset_reg(opsize, DREG(insn, 9), dest); 1934 } 1935 tcg_temp_free(dest); 1936 } 1937 1938 /* Reverse the order of the bits in REG. */ 1939 DISAS_INSN(bitrev) 1940 { 1941 TCGv reg; 1942 reg = DREG(insn, 0); 1943 gen_helper_bitrev(reg, reg); 1944 } 1945 1946 DISAS_INSN(bitop_reg) 1947 { 1948 int opsize; 1949 int op; 1950 TCGv src1; 1951 TCGv src2; 1952 TCGv tmp; 1953 TCGv addr; 1954 TCGv dest; 1955 1956 if ((insn & 0x38) != 0) 1957 opsize = OS_BYTE; 1958 else 1959 opsize = OS_LONG; 1960 op = (insn >> 6) & 3; 1961 SRC_EA(env, src1, opsize, 0, op ? &addr: NULL); 1962 1963 gen_flush_flags(s); 1964 src2 = tcg_temp_new(); 1965 if (opsize == OS_BYTE) 1966 tcg_gen_andi_i32(src2, DREG(insn, 9), 7); 1967 else 1968 tcg_gen_andi_i32(src2, DREG(insn, 9), 31); 1969 1970 tmp = tcg_const_i32(1); 1971 tcg_gen_shl_i32(tmp, tmp, src2); 1972 tcg_temp_free(src2); 1973 1974 tcg_gen_and_i32(QREG_CC_Z, src1, tmp); 1975 1976 dest = tcg_temp_new(); 1977 switch (op) { 1978 case 1: /* bchg */ 1979 tcg_gen_xor_i32(dest, src1, tmp); 1980 break; 1981 case 2: /* bclr */ 1982 tcg_gen_andc_i32(dest, src1, tmp); 1983 break; 1984 case 3: /* bset */ 1985 tcg_gen_or_i32(dest, src1, tmp); 1986 break; 1987 default: /* btst */ 1988 break; 1989 } 1990 tcg_temp_free(tmp); 1991 if (op) { 1992 DEST_EA(env, insn, opsize, dest, &addr); 1993 } 1994 tcg_temp_free(dest); 1995 } 1996 1997 DISAS_INSN(sats) 1998 { 1999 TCGv reg; 2000 reg = DREG(insn, 0); 2001 gen_flush_flags(s); 2002 gen_helper_sats(reg, reg, QREG_CC_V); 2003 gen_logic_cc(s, reg, OS_LONG); 2004 } 2005 2006 static void gen_push(DisasContext *s, TCGv val) 2007 { 2008 TCGv tmp; 2009 2010 tmp = tcg_temp_new(); 2011 tcg_gen_subi_i32(tmp, QREG_SP, 4); 2012 gen_store(s, OS_LONG, tmp, val, IS_USER(s)); 2013 tcg_gen_mov_i32(QREG_SP, tmp); 2014 tcg_temp_free(tmp); 2015 } 2016 2017 static TCGv mreg(int reg) 2018 { 2019 if (reg < 8) { 2020 /* Dx */ 2021 return cpu_dregs[reg]; 2022 } 2023 /* Ax */ 2024 return cpu_aregs[reg & 7]; 2025 } 2026 2027 DISAS_INSN(movem) 2028 { 2029 TCGv addr, incr, tmp, r[16]; 2030 int is_load = (insn & 0x0400) != 0; 2031 int opsize = (insn & 0x40) != 0 ? OS_LONG : OS_WORD; 2032 uint16_t mask = read_im16(env, s); 2033 int mode = extract32(insn, 3, 3); 2034 int reg0 = REG(insn, 0); 2035 int i; 2036 2037 tmp = cpu_aregs[reg0]; 2038 2039 switch (mode) { 2040 case 0: /* data register direct */ 2041 case 1: /* addr register direct */ 2042 do_addr_fault: 2043 gen_addr_fault(s); 2044 return; 2045 2046 case 2: /* indirect */ 2047 break; 2048 2049 case 3: /* indirect post-increment */ 2050 if (!is_load) { 2051 /* post-increment is not allowed */ 2052 goto do_addr_fault; 2053 } 2054 break; 2055 2056 case 4: /* indirect pre-decrement */ 2057 if (is_load) { 2058 /* pre-decrement is not allowed */ 2059 goto do_addr_fault; 2060 } 2061 /* 2062 * We want a bare copy of the address reg, without any pre-decrement 2063 * adjustment, as gen_lea would provide. 2064 */ 2065 break; 2066 2067 default: 2068 tmp = gen_lea_mode(env, s, mode, reg0, opsize); 2069 if (IS_NULL_QREG(tmp)) { 2070 goto do_addr_fault; 2071 } 2072 break; 2073 } 2074 2075 addr = tcg_temp_new(); 2076 tcg_gen_mov_i32(addr, tmp); 2077 incr = tcg_const_i32(opsize_bytes(opsize)); 2078 2079 if (is_load) { 2080 /* memory to register */ 2081 for (i = 0; i < 16; i++) { 2082 if (mask & (1 << i)) { 2083 r[i] = gen_load(s, opsize, addr, 1, IS_USER(s)); 2084 tcg_gen_add_i32(addr, addr, incr); 2085 } 2086 } 2087 for (i = 0; i < 16; i++) { 2088 if (mask & (1 << i)) { 2089 tcg_gen_mov_i32(mreg(i), r[i]); 2090 tcg_temp_free(r[i]); 2091 } 2092 } 2093 if (mode == 3) { 2094 /* post-increment: movem (An)+,X */ 2095 tcg_gen_mov_i32(cpu_aregs[reg0], addr); 2096 } 2097 } else { 2098 /* register to memory */ 2099 if (mode == 4) { 2100 /* pre-decrement: movem X,-(An) */ 2101 for (i = 15; i >= 0; i--) { 2102 if ((mask << i) & 0x8000) { 2103 tcg_gen_sub_i32(addr, addr, incr); 2104 if (reg0 + 8 == i && 2105 m68k_feature(s->env, M68K_FEATURE_EXT_FULL)) { 2106 /* 2107 * M68020+: if the addressing register is the 2108 * register moved to memory, the value written 2109 * is the initial value decremented by the size of 2110 * the operation, regardless of how many actual 2111 * stores have been performed until this point. 2112 * M68000/M68010: the value is the initial value. 2113 */ 2114 tmp = tcg_temp_new(); 2115 tcg_gen_sub_i32(tmp, cpu_aregs[reg0], incr); 2116 gen_store(s, opsize, addr, tmp, IS_USER(s)); 2117 tcg_temp_free(tmp); 2118 } else { 2119 gen_store(s, opsize, addr, mreg(i), IS_USER(s)); 2120 } 2121 } 2122 } 2123 tcg_gen_mov_i32(cpu_aregs[reg0], addr); 2124 } else { 2125 for (i = 0; i < 16; i++) { 2126 if (mask & (1 << i)) { 2127 gen_store(s, opsize, addr, mreg(i), IS_USER(s)); 2128 tcg_gen_add_i32(addr, addr, incr); 2129 } 2130 } 2131 } 2132 } 2133 2134 tcg_temp_free(incr); 2135 tcg_temp_free(addr); 2136 } 2137 2138 DISAS_INSN(movep) 2139 { 2140 uint8_t i; 2141 int16_t displ; 2142 TCGv reg; 2143 TCGv addr; 2144 TCGv abuf; 2145 TCGv dbuf; 2146 2147 displ = read_im16(env, s); 2148 2149 addr = AREG(insn, 0); 2150 reg = DREG(insn, 9); 2151 2152 abuf = tcg_temp_new(); 2153 tcg_gen_addi_i32(abuf, addr, displ); 2154 dbuf = tcg_temp_new(); 2155 2156 if (insn & 0x40) { 2157 i = 4; 2158 } else { 2159 i = 2; 2160 } 2161 2162 if (insn & 0x80) { 2163 for ( ; i > 0 ; i--) { 2164 tcg_gen_shri_i32(dbuf, reg, (i - 1) * 8); 2165 tcg_gen_qemu_st8(dbuf, abuf, IS_USER(s)); 2166 if (i > 1) { 2167 tcg_gen_addi_i32(abuf, abuf, 2); 2168 } 2169 } 2170 } else { 2171 for ( ; i > 0 ; i--) { 2172 tcg_gen_qemu_ld8u(dbuf, abuf, IS_USER(s)); 2173 tcg_gen_deposit_i32(reg, reg, dbuf, (i - 1) * 8, 8); 2174 if (i > 1) { 2175 tcg_gen_addi_i32(abuf, abuf, 2); 2176 } 2177 } 2178 } 2179 tcg_temp_free(abuf); 2180 tcg_temp_free(dbuf); 2181 } 2182 2183 DISAS_INSN(bitop_im) 2184 { 2185 int opsize; 2186 int op; 2187 TCGv src1; 2188 uint32_t mask; 2189 int bitnum; 2190 TCGv tmp; 2191 TCGv addr; 2192 2193 if ((insn & 0x38) != 0) 2194 opsize = OS_BYTE; 2195 else 2196 opsize = OS_LONG; 2197 op = (insn >> 6) & 3; 2198 2199 bitnum = read_im16(env, s); 2200 if (m68k_feature(s->env, M68K_FEATURE_M68000)) { 2201 if (bitnum & 0xfe00) { 2202 disas_undef(env, s, insn); 2203 return; 2204 } 2205 } else { 2206 if (bitnum & 0xff00) { 2207 disas_undef(env, s, insn); 2208 return; 2209 } 2210 } 2211 2212 SRC_EA(env, src1, opsize, 0, op ? &addr: NULL); 2213 2214 gen_flush_flags(s); 2215 if (opsize == OS_BYTE) 2216 bitnum &= 7; 2217 else 2218 bitnum &= 31; 2219 mask = 1 << bitnum; 2220 2221 tcg_gen_andi_i32(QREG_CC_Z, src1, mask); 2222 2223 if (op) { 2224 tmp = tcg_temp_new(); 2225 switch (op) { 2226 case 1: /* bchg */ 2227 tcg_gen_xori_i32(tmp, src1, mask); 2228 break; 2229 case 2: /* bclr */ 2230 tcg_gen_andi_i32(tmp, src1, ~mask); 2231 break; 2232 case 3: /* bset */ 2233 tcg_gen_ori_i32(tmp, src1, mask); 2234 break; 2235 default: /* btst */ 2236 break; 2237 } 2238 DEST_EA(env, insn, opsize, tmp, &addr); 2239 tcg_temp_free(tmp); 2240 } 2241 } 2242 2243 static TCGv gen_get_ccr(DisasContext *s) 2244 { 2245 TCGv dest; 2246 2247 update_cc_op(s); 2248 dest = tcg_temp_new(); 2249 gen_helper_get_ccr(dest, cpu_env); 2250 return dest; 2251 } 2252 2253 static TCGv gen_get_sr(DisasContext *s) 2254 { 2255 TCGv ccr; 2256 TCGv sr; 2257 2258 ccr = gen_get_ccr(s); 2259 sr = tcg_temp_new(); 2260 tcg_gen_andi_i32(sr, QREG_SR, 0xffe0); 2261 tcg_gen_or_i32(sr, sr, ccr); 2262 tcg_temp_free(ccr); 2263 return sr; 2264 } 2265 2266 static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only) 2267 { 2268 if (ccr_only) { 2269 tcg_gen_movi_i32(QREG_CC_C, val & CCF_C ? 1 : 0); 2270 tcg_gen_movi_i32(QREG_CC_V, val & CCF_V ? -1 : 0); 2271 tcg_gen_movi_i32(QREG_CC_Z, val & CCF_Z ? 0 : 1); 2272 tcg_gen_movi_i32(QREG_CC_N, val & CCF_N ? -1 : 0); 2273 tcg_gen_movi_i32(QREG_CC_X, val & CCF_X ? 1 : 0); 2274 } else { 2275 TCGv sr = tcg_const_i32(val); 2276 gen_helper_set_sr(cpu_env, sr); 2277 tcg_temp_free(sr); 2278 } 2279 set_cc_op(s, CC_OP_FLAGS); 2280 } 2281 2282 static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only) 2283 { 2284 if (ccr_only) { 2285 gen_helper_set_ccr(cpu_env, val); 2286 } else { 2287 gen_helper_set_sr(cpu_env, val); 2288 } 2289 set_cc_op(s, CC_OP_FLAGS); 2290 } 2291 2292 static void gen_move_to_sr(CPUM68KState *env, DisasContext *s, uint16_t insn, 2293 bool ccr_only) 2294 { 2295 if ((insn & 0x3f) == 0x3c) { 2296 uint16_t val; 2297 val = read_im16(env, s); 2298 gen_set_sr_im(s, val, ccr_only); 2299 } else { 2300 TCGv src; 2301 SRC_EA(env, src, OS_WORD, 0, NULL); 2302 gen_set_sr(s, src, ccr_only); 2303 } 2304 } 2305 2306 DISAS_INSN(arith_im) 2307 { 2308 int op; 2309 TCGv im; 2310 TCGv src1; 2311 TCGv dest; 2312 TCGv addr; 2313 int opsize; 2314 bool with_SR = ((insn & 0x3f) == 0x3c); 2315 2316 op = (insn >> 9) & 7; 2317 opsize = insn_opsize(insn); 2318 switch (opsize) { 2319 case OS_BYTE: 2320 im = tcg_const_i32((int8_t)read_im8(env, s)); 2321 break; 2322 case OS_WORD: 2323 im = tcg_const_i32((int16_t)read_im16(env, s)); 2324 break; 2325 case OS_LONG: 2326 im = tcg_const_i32(read_im32(env, s)); 2327 break; 2328 default: 2329 g_assert_not_reached(); 2330 } 2331 2332 if (with_SR) { 2333 /* SR/CCR can only be used with andi/eori/ori */ 2334 if (op == 2 || op == 3 || op == 6) { 2335 disas_undef(env, s, insn); 2336 return; 2337 } 2338 switch (opsize) { 2339 case OS_BYTE: 2340 src1 = gen_get_ccr(s); 2341 break; 2342 case OS_WORD: 2343 if (IS_USER(s)) { 2344 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 2345 return; 2346 } 2347 src1 = gen_get_sr(s); 2348 break; 2349 default: 2350 /* OS_LONG; others already g_assert_not_reached. */ 2351 disas_undef(env, s, insn); 2352 return; 2353 } 2354 } else { 2355 SRC_EA(env, src1, opsize, 1, (op == 6) ? NULL : &addr); 2356 } 2357 dest = tcg_temp_new(); 2358 switch (op) { 2359 case 0: /* ori */ 2360 tcg_gen_or_i32(dest, src1, im); 2361 if (with_SR) { 2362 gen_set_sr(s, dest, opsize == OS_BYTE); 2363 } else { 2364 DEST_EA(env, insn, opsize, dest, &addr); 2365 gen_logic_cc(s, dest, opsize); 2366 } 2367 break; 2368 case 1: /* andi */ 2369 tcg_gen_and_i32(dest, src1, im); 2370 if (with_SR) { 2371 gen_set_sr(s, dest, opsize == OS_BYTE); 2372 } else { 2373 DEST_EA(env, insn, opsize, dest, &addr); 2374 gen_logic_cc(s, dest, opsize); 2375 } 2376 break; 2377 case 2: /* subi */ 2378 tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, src1, im); 2379 tcg_gen_sub_i32(dest, src1, im); 2380 gen_update_cc_add(dest, im, opsize); 2381 set_cc_op(s, CC_OP_SUBB + opsize); 2382 DEST_EA(env, insn, opsize, dest, &addr); 2383 break; 2384 case 3: /* addi */ 2385 tcg_gen_add_i32(dest, src1, im); 2386 gen_update_cc_add(dest, im, opsize); 2387 tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, im); 2388 set_cc_op(s, CC_OP_ADDB + opsize); 2389 DEST_EA(env, insn, opsize, dest, &addr); 2390 break; 2391 case 5: /* eori */ 2392 tcg_gen_xor_i32(dest, src1, im); 2393 if (with_SR) { 2394 gen_set_sr(s, dest, opsize == OS_BYTE); 2395 } else { 2396 DEST_EA(env, insn, opsize, dest, &addr); 2397 gen_logic_cc(s, dest, opsize); 2398 } 2399 break; 2400 case 6: /* cmpi */ 2401 gen_update_cc_cmp(s, src1, im, opsize); 2402 break; 2403 default: 2404 abort(); 2405 } 2406 tcg_temp_free(im); 2407 tcg_temp_free(dest); 2408 } 2409 2410 DISAS_INSN(cas) 2411 { 2412 int opsize; 2413 TCGv addr; 2414 uint16_t ext; 2415 TCGv load; 2416 TCGv cmp; 2417 MemOp opc; 2418 2419 switch ((insn >> 9) & 3) { 2420 case 1: 2421 opsize = OS_BYTE; 2422 opc = MO_SB; 2423 break; 2424 case 2: 2425 opsize = OS_WORD; 2426 opc = MO_TESW; 2427 break; 2428 case 3: 2429 opsize = OS_LONG; 2430 opc = MO_TESL; 2431 break; 2432 default: 2433 g_assert_not_reached(); 2434 } 2435 2436 ext = read_im16(env, s); 2437 2438 /* cas Dc,Du,<EA> */ 2439 2440 addr = gen_lea(env, s, insn, opsize); 2441 if (IS_NULL_QREG(addr)) { 2442 gen_addr_fault(s); 2443 return; 2444 } 2445 2446 cmp = gen_extend(s, DREG(ext, 0), opsize, 1); 2447 2448 /* 2449 * if <EA> == Dc then 2450 * <EA> = Du 2451 * Dc = <EA> (because <EA> == Dc) 2452 * else 2453 * Dc = <EA> 2454 */ 2455 2456 load = tcg_temp_new(); 2457 tcg_gen_atomic_cmpxchg_i32(load, addr, cmp, DREG(ext, 6), 2458 IS_USER(s), opc); 2459 /* update flags before setting cmp to load */ 2460 gen_update_cc_cmp(s, load, cmp, opsize); 2461 gen_partset_reg(opsize, DREG(ext, 0), load); 2462 2463 tcg_temp_free(load); 2464 2465 switch (extract32(insn, 3, 3)) { 2466 case 3: /* Indirect postincrement. */ 2467 tcg_gen_addi_i32(AREG(insn, 0), addr, opsize_bytes(opsize)); 2468 break; 2469 case 4: /* Indirect predecrememnt. */ 2470 tcg_gen_mov_i32(AREG(insn, 0), addr); 2471 break; 2472 } 2473 } 2474 2475 DISAS_INSN(cas2w) 2476 { 2477 uint16_t ext1, ext2; 2478 TCGv addr1, addr2; 2479 TCGv regs; 2480 2481 /* cas2 Dc1:Dc2,Du1:Du2,(Rn1):(Rn2) */ 2482 2483 ext1 = read_im16(env, s); 2484 2485 if (ext1 & 0x8000) { 2486 /* Address Register */ 2487 addr1 = AREG(ext1, 12); 2488 } else { 2489 /* Data Register */ 2490 addr1 = DREG(ext1, 12); 2491 } 2492 2493 ext2 = read_im16(env, s); 2494 if (ext2 & 0x8000) { 2495 /* Address Register */ 2496 addr2 = AREG(ext2, 12); 2497 } else { 2498 /* Data Register */ 2499 addr2 = DREG(ext2, 12); 2500 } 2501 2502 /* 2503 * if (R1) == Dc1 && (R2) == Dc2 then 2504 * (R1) = Du1 2505 * (R2) = Du2 2506 * else 2507 * Dc1 = (R1) 2508 * Dc2 = (R2) 2509 */ 2510 2511 regs = tcg_const_i32(REG(ext2, 6) | 2512 (REG(ext1, 6) << 3) | 2513 (REG(ext2, 0) << 6) | 2514 (REG(ext1, 0) << 9)); 2515 if (tb_cflags(s->base.tb) & CF_PARALLEL) { 2516 gen_helper_exit_atomic(cpu_env); 2517 } else { 2518 gen_helper_cas2w(cpu_env, regs, addr1, addr2); 2519 } 2520 tcg_temp_free(regs); 2521 2522 /* Note that cas2w also assigned to env->cc_op. */ 2523 s->cc_op = CC_OP_CMPW; 2524 s->cc_op_synced = 1; 2525 } 2526 2527 DISAS_INSN(cas2l) 2528 { 2529 uint16_t ext1, ext2; 2530 TCGv addr1, addr2, regs; 2531 2532 /* cas2 Dc1:Dc2,Du1:Du2,(Rn1):(Rn2) */ 2533 2534 ext1 = read_im16(env, s); 2535 2536 if (ext1 & 0x8000) { 2537 /* Address Register */ 2538 addr1 = AREG(ext1, 12); 2539 } else { 2540 /* Data Register */ 2541 addr1 = DREG(ext1, 12); 2542 } 2543 2544 ext2 = read_im16(env, s); 2545 if (ext2 & 0x8000) { 2546 /* Address Register */ 2547 addr2 = AREG(ext2, 12); 2548 } else { 2549 /* Data Register */ 2550 addr2 = DREG(ext2, 12); 2551 } 2552 2553 /* 2554 * if (R1) == Dc1 && (R2) == Dc2 then 2555 * (R1) = Du1 2556 * (R2) = Du2 2557 * else 2558 * Dc1 = (R1) 2559 * Dc2 = (R2) 2560 */ 2561 2562 regs = tcg_const_i32(REG(ext2, 6) | 2563 (REG(ext1, 6) << 3) | 2564 (REG(ext2, 0) << 6) | 2565 (REG(ext1, 0) << 9)); 2566 if (tb_cflags(s->base.tb) & CF_PARALLEL) { 2567 gen_helper_cas2l_parallel(cpu_env, regs, addr1, addr2); 2568 } else { 2569 gen_helper_cas2l(cpu_env, regs, addr1, addr2); 2570 } 2571 tcg_temp_free(regs); 2572 2573 /* Note that cas2l also assigned to env->cc_op. */ 2574 s->cc_op = CC_OP_CMPL; 2575 s->cc_op_synced = 1; 2576 } 2577 2578 DISAS_INSN(byterev) 2579 { 2580 TCGv reg; 2581 2582 reg = DREG(insn, 0); 2583 tcg_gen_bswap32_i32(reg, reg); 2584 } 2585 2586 DISAS_INSN(move) 2587 { 2588 TCGv src; 2589 TCGv dest; 2590 int op; 2591 int opsize; 2592 2593 switch (insn >> 12) { 2594 case 1: /* move.b */ 2595 opsize = OS_BYTE; 2596 break; 2597 case 2: /* move.l */ 2598 opsize = OS_LONG; 2599 break; 2600 case 3: /* move.w */ 2601 opsize = OS_WORD; 2602 break; 2603 default: 2604 abort(); 2605 } 2606 SRC_EA(env, src, opsize, 1, NULL); 2607 op = (insn >> 6) & 7; 2608 if (op == 1) { 2609 /* movea */ 2610 /* The value will already have been sign extended. */ 2611 dest = AREG(insn, 9); 2612 tcg_gen_mov_i32(dest, src); 2613 } else { 2614 /* normal move */ 2615 uint16_t dest_ea; 2616 dest_ea = ((insn >> 9) & 7) | (op << 3); 2617 DEST_EA(env, dest_ea, opsize, src, NULL); 2618 /* This will be correct because loads sign extend. */ 2619 gen_logic_cc(s, src, opsize); 2620 } 2621 } 2622 2623 DISAS_INSN(negx) 2624 { 2625 TCGv z; 2626 TCGv src; 2627 TCGv addr; 2628 int opsize; 2629 2630 opsize = insn_opsize(insn); 2631 SRC_EA(env, src, opsize, 1, &addr); 2632 2633 gen_flush_flags(s); /* compute old Z */ 2634 2635 /* 2636 * Perform substract with borrow. 2637 * (X, N) = -(src + X); 2638 */ 2639 2640 z = tcg_const_i32(0); 2641 tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, z, QREG_CC_X, z); 2642 tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, z, z, QREG_CC_N, QREG_CC_X); 2643 tcg_temp_free(z); 2644 gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1); 2645 2646 tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1); 2647 2648 /* 2649 * Compute signed-overflow for negation. The normal formula for 2650 * subtraction is (res ^ src) & (src ^ dest), but with dest==0 2651 * this simplies to res & src. 2652 */ 2653 2654 tcg_gen_and_i32(QREG_CC_V, QREG_CC_N, src); 2655 2656 /* Copy the rest of the results into place. */ 2657 tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */ 2658 tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); 2659 2660 set_cc_op(s, CC_OP_FLAGS); 2661 2662 /* result is in QREG_CC_N */ 2663 2664 DEST_EA(env, insn, opsize, QREG_CC_N, &addr); 2665 } 2666 2667 DISAS_INSN(lea) 2668 { 2669 TCGv reg; 2670 TCGv tmp; 2671 2672 reg = AREG(insn, 9); 2673 tmp = gen_lea(env, s, insn, OS_LONG); 2674 if (IS_NULL_QREG(tmp)) { 2675 gen_addr_fault(s); 2676 return; 2677 } 2678 tcg_gen_mov_i32(reg, tmp); 2679 } 2680 2681 DISAS_INSN(clr) 2682 { 2683 int opsize; 2684 TCGv zero; 2685 2686 zero = tcg_const_i32(0); 2687 2688 opsize = insn_opsize(insn); 2689 DEST_EA(env, insn, opsize, zero, NULL); 2690 gen_logic_cc(s, zero, opsize); 2691 tcg_temp_free(zero); 2692 } 2693 2694 DISAS_INSN(move_from_ccr) 2695 { 2696 TCGv ccr; 2697 2698 ccr = gen_get_ccr(s); 2699 DEST_EA(env, insn, OS_WORD, ccr, NULL); 2700 } 2701 2702 DISAS_INSN(neg) 2703 { 2704 TCGv src1; 2705 TCGv dest; 2706 TCGv addr; 2707 int opsize; 2708 2709 opsize = insn_opsize(insn); 2710 SRC_EA(env, src1, opsize, 1, &addr); 2711 dest = tcg_temp_new(); 2712 tcg_gen_neg_i32(dest, src1); 2713 set_cc_op(s, CC_OP_SUBB + opsize); 2714 gen_update_cc_add(dest, src1, opsize); 2715 tcg_gen_setcondi_i32(TCG_COND_NE, QREG_CC_X, dest, 0); 2716 DEST_EA(env, insn, opsize, dest, &addr); 2717 tcg_temp_free(dest); 2718 } 2719 2720 DISAS_INSN(move_to_ccr) 2721 { 2722 gen_move_to_sr(env, s, insn, true); 2723 } 2724 2725 DISAS_INSN(not) 2726 { 2727 TCGv src1; 2728 TCGv dest; 2729 TCGv addr; 2730 int opsize; 2731 2732 opsize = insn_opsize(insn); 2733 SRC_EA(env, src1, opsize, 1, &addr); 2734 dest = tcg_temp_new(); 2735 tcg_gen_not_i32(dest, src1); 2736 DEST_EA(env, insn, opsize, dest, &addr); 2737 gen_logic_cc(s, dest, opsize); 2738 } 2739 2740 DISAS_INSN(swap) 2741 { 2742 TCGv src1; 2743 TCGv src2; 2744 TCGv reg; 2745 2746 src1 = tcg_temp_new(); 2747 src2 = tcg_temp_new(); 2748 reg = DREG(insn, 0); 2749 tcg_gen_shli_i32(src1, reg, 16); 2750 tcg_gen_shri_i32(src2, reg, 16); 2751 tcg_gen_or_i32(reg, src1, src2); 2752 tcg_temp_free(src2); 2753 tcg_temp_free(src1); 2754 gen_logic_cc(s, reg, OS_LONG); 2755 } 2756 2757 DISAS_INSN(bkpt) 2758 { 2759 gen_exception(s, s->base.pc_next, EXCP_DEBUG); 2760 } 2761 2762 DISAS_INSN(pea) 2763 { 2764 TCGv tmp; 2765 2766 tmp = gen_lea(env, s, insn, OS_LONG); 2767 if (IS_NULL_QREG(tmp)) { 2768 gen_addr_fault(s); 2769 return; 2770 } 2771 gen_push(s, tmp); 2772 } 2773 2774 DISAS_INSN(ext) 2775 { 2776 int op; 2777 TCGv reg; 2778 TCGv tmp; 2779 2780 reg = DREG(insn, 0); 2781 op = (insn >> 6) & 7; 2782 tmp = tcg_temp_new(); 2783 if (op == 3) 2784 tcg_gen_ext16s_i32(tmp, reg); 2785 else 2786 tcg_gen_ext8s_i32(tmp, reg); 2787 if (op == 2) 2788 gen_partset_reg(OS_WORD, reg, tmp); 2789 else 2790 tcg_gen_mov_i32(reg, tmp); 2791 gen_logic_cc(s, tmp, OS_LONG); 2792 tcg_temp_free(tmp); 2793 } 2794 2795 DISAS_INSN(tst) 2796 { 2797 int opsize; 2798 TCGv tmp; 2799 2800 opsize = insn_opsize(insn); 2801 SRC_EA(env, tmp, opsize, 1, NULL); 2802 gen_logic_cc(s, tmp, opsize); 2803 } 2804 2805 DISAS_INSN(pulse) 2806 { 2807 /* Implemented as a NOP. */ 2808 } 2809 2810 DISAS_INSN(illegal) 2811 { 2812 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL); 2813 } 2814 2815 /* ??? This should be atomic. */ 2816 DISAS_INSN(tas) 2817 { 2818 TCGv dest; 2819 TCGv src1; 2820 TCGv addr; 2821 2822 dest = tcg_temp_new(); 2823 SRC_EA(env, src1, OS_BYTE, 1, &addr); 2824 gen_logic_cc(s, src1, OS_BYTE); 2825 tcg_gen_ori_i32(dest, src1, 0x80); 2826 DEST_EA(env, insn, OS_BYTE, dest, &addr); 2827 tcg_temp_free(dest); 2828 } 2829 2830 DISAS_INSN(mull) 2831 { 2832 uint16_t ext; 2833 TCGv src1; 2834 int sign; 2835 2836 ext = read_im16(env, s); 2837 2838 sign = ext & 0x800; 2839 2840 if (ext & 0x400) { 2841 if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) { 2842 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL); 2843 return; 2844 } 2845 2846 SRC_EA(env, src1, OS_LONG, 0, NULL); 2847 2848 if (sign) { 2849 tcg_gen_muls2_i32(QREG_CC_Z, QREG_CC_N, src1, DREG(ext, 12)); 2850 } else { 2851 tcg_gen_mulu2_i32(QREG_CC_Z, QREG_CC_N, src1, DREG(ext, 12)); 2852 } 2853 /* if Dl == Dh, 68040 returns low word */ 2854 tcg_gen_mov_i32(DREG(ext, 0), QREG_CC_N); 2855 tcg_gen_mov_i32(DREG(ext, 12), QREG_CC_Z); 2856 tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); 2857 2858 tcg_gen_movi_i32(QREG_CC_V, 0); 2859 tcg_gen_movi_i32(QREG_CC_C, 0); 2860 2861 set_cc_op(s, CC_OP_FLAGS); 2862 return; 2863 } 2864 SRC_EA(env, src1, OS_LONG, 0, NULL); 2865 if (m68k_feature(s->env, M68K_FEATURE_M68000)) { 2866 tcg_gen_movi_i32(QREG_CC_C, 0); 2867 if (sign) { 2868 tcg_gen_muls2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12)); 2869 /* QREG_CC_V is -(QREG_CC_V != (QREG_CC_N >> 31)) */ 2870 tcg_gen_sari_i32(QREG_CC_Z, QREG_CC_N, 31); 2871 tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, QREG_CC_Z); 2872 } else { 2873 tcg_gen_mulu2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12)); 2874 /* QREG_CC_V is -(QREG_CC_V != 0), use QREG_CC_C as 0 */ 2875 tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, QREG_CC_C); 2876 } 2877 tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V); 2878 tcg_gen_mov_i32(DREG(ext, 12), QREG_CC_N); 2879 2880 tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N); 2881 2882 set_cc_op(s, CC_OP_FLAGS); 2883 } else { 2884 /* 2885 * The upper 32 bits of the product are discarded, so 2886 * muls.l and mulu.l are functionally equivalent. 2887 */ 2888 tcg_gen_mul_i32(DREG(ext, 12), src1, DREG(ext, 12)); 2889 gen_logic_cc(s, DREG(ext, 12), OS_LONG); 2890 } 2891 } 2892 2893 static void gen_link(DisasContext *s, uint16_t insn, int32_t offset) 2894 { 2895 TCGv reg; 2896 TCGv tmp; 2897 2898 reg = AREG(insn, 0); 2899 tmp = tcg_temp_new(); 2900 tcg_gen_subi_i32(tmp, QREG_SP, 4); 2901 gen_store(s, OS_LONG, tmp, reg, IS_USER(s)); 2902 if ((insn & 7) != 7) { 2903 tcg_gen_mov_i32(reg, tmp); 2904 } 2905 tcg_gen_addi_i32(QREG_SP, tmp, offset); 2906 tcg_temp_free(tmp); 2907 } 2908 2909 DISAS_INSN(link) 2910 { 2911 int16_t offset; 2912 2913 offset = read_im16(env, s); 2914 gen_link(s, insn, offset); 2915 } 2916 2917 DISAS_INSN(linkl) 2918 { 2919 int32_t offset; 2920 2921 offset = read_im32(env, s); 2922 gen_link(s, insn, offset); 2923 } 2924 2925 DISAS_INSN(unlk) 2926 { 2927 TCGv src; 2928 TCGv reg; 2929 TCGv tmp; 2930 2931 src = tcg_temp_new(); 2932 reg = AREG(insn, 0); 2933 tcg_gen_mov_i32(src, reg); 2934 tmp = gen_load(s, OS_LONG, src, 0, IS_USER(s)); 2935 tcg_gen_mov_i32(reg, tmp); 2936 tcg_gen_addi_i32(QREG_SP, src, 4); 2937 tcg_temp_free(src); 2938 tcg_temp_free(tmp); 2939 } 2940 2941 #if defined(CONFIG_SOFTMMU) 2942 DISAS_INSN(reset) 2943 { 2944 if (IS_USER(s)) { 2945 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 2946 return; 2947 } 2948 2949 gen_helper_reset(cpu_env); 2950 } 2951 #endif 2952 2953 DISAS_INSN(nop) 2954 { 2955 } 2956 2957 DISAS_INSN(rtd) 2958 { 2959 TCGv tmp; 2960 int16_t offset = read_im16(env, s); 2961 2962 tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s)); 2963 tcg_gen_addi_i32(QREG_SP, QREG_SP, offset + 4); 2964 gen_jmp(s, tmp); 2965 } 2966 2967 DISAS_INSN(rts) 2968 { 2969 TCGv tmp; 2970 2971 tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s)); 2972 tcg_gen_addi_i32(QREG_SP, QREG_SP, 4); 2973 gen_jmp(s, tmp); 2974 } 2975 2976 DISAS_INSN(jump) 2977 { 2978 TCGv tmp; 2979 2980 /* 2981 * Load the target address first to ensure correct exception 2982 * behavior. 2983 */ 2984 tmp = gen_lea(env, s, insn, OS_LONG); 2985 if (IS_NULL_QREG(tmp)) { 2986 gen_addr_fault(s); 2987 return; 2988 } 2989 if ((insn & 0x40) == 0) { 2990 /* jsr */ 2991 gen_push(s, tcg_const_i32(s->pc)); 2992 } 2993 gen_jmp(s, tmp); 2994 } 2995 2996 DISAS_INSN(addsubq) 2997 { 2998 TCGv src; 2999 TCGv dest; 3000 TCGv val; 3001 int imm; 3002 TCGv addr; 3003 int opsize; 3004 3005 if ((insn & 070) == 010) { 3006 /* Operation on address register is always long. */ 3007 opsize = OS_LONG; 3008 } else { 3009 opsize = insn_opsize(insn); 3010 } 3011 SRC_EA(env, src, opsize, 1, &addr); 3012 imm = (insn >> 9) & 7; 3013 if (imm == 0) { 3014 imm = 8; 3015 } 3016 val = tcg_const_i32(imm); 3017 dest = tcg_temp_new(); 3018 tcg_gen_mov_i32(dest, src); 3019 if ((insn & 0x38) == 0x08) { 3020 /* 3021 * Don't update condition codes if the destination is an 3022 * address register. 3023 */ 3024 if (insn & 0x0100) { 3025 tcg_gen_sub_i32(dest, dest, val); 3026 } else { 3027 tcg_gen_add_i32(dest, dest, val); 3028 } 3029 } else { 3030 if (insn & 0x0100) { 3031 tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, val); 3032 tcg_gen_sub_i32(dest, dest, val); 3033 set_cc_op(s, CC_OP_SUBB + opsize); 3034 } else { 3035 tcg_gen_add_i32(dest, dest, val); 3036 tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, val); 3037 set_cc_op(s, CC_OP_ADDB + opsize); 3038 } 3039 gen_update_cc_add(dest, val, opsize); 3040 } 3041 tcg_temp_free(val); 3042 DEST_EA(env, insn, opsize, dest, &addr); 3043 tcg_temp_free(dest); 3044 } 3045 3046 DISAS_INSN(tpf) 3047 { 3048 switch (insn & 7) { 3049 case 2: /* One extension word. */ 3050 s->pc += 2; 3051 break; 3052 case 3: /* Two extension words. */ 3053 s->pc += 4; 3054 break; 3055 case 4: /* No extension words. */ 3056 break; 3057 default: 3058 disas_undef(env, s, insn); 3059 } 3060 } 3061 3062 DISAS_INSN(branch) 3063 { 3064 int32_t offset; 3065 uint32_t base; 3066 int op; 3067 3068 base = s->pc; 3069 op = (insn >> 8) & 0xf; 3070 offset = (int8_t)insn; 3071 if (offset == 0) { 3072 offset = (int16_t)read_im16(env, s); 3073 } else if (offset == -1) { 3074 offset = read_im32(env, s); 3075 } 3076 if (op == 1) { 3077 /* bsr */ 3078 gen_push(s, tcg_const_i32(s->pc)); 3079 } 3080 if (op > 1) { 3081 /* Bcc */ 3082 TCGLabel *l1 = gen_new_label(); 3083 gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1); 3084 gen_jmp_tb(s, 1, base + offset); 3085 gen_set_label(l1); 3086 gen_jmp_tb(s, 0, s->pc); 3087 } else { 3088 /* Unconditional branch. */ 3089 update_cc_op(s); 3090 gen_jmp_tb(s, 0, base + offset); 3091 } 3092 } 3093 3094 DISAS_INSN(moveq) 3095 { 3096 tcg_gen_movi_i32(DREG(insn, 9), (int8_t)insn); 3097 gen_logic_cc(s, DREG(insn, 9), OS_LONG); 3098 } 3099 3100 DISAS_INSN(mvzs) 3101 { 3102 int opsize; 3103 TCGv src; 3104 TCGv reg; 3105 3106 if (insn & 0x40) 3107 opsize = OS_WORD; 3108 else 3109 opsize = OS_BYTE; 3110 SRC_EA(env, src, opsize, (insn & 0x80) == 0, NULL); 3111 reg = DREG(insn, 9); 3112 tcg_gen_mov_i32(reg, src); 3113 gen_logic_cc(s, src, opsize); 3114 } 3115 3116 DISAS_INSN(or) 3117 { 3118 TCGv reg; 3119 TCGv dest; 3120 TCGv src; 3121 TCGv addr; 3122 int opsize; 3123 3124 opsize = insn_opsize(insn); 3125 reg = gen_extend(s, DREG(insn, 9), opsize, 0); 3126 dest = tcg_temp_new(); 3127 if (insn & 0x100) { 3128 SRC_EA(env, src, opsize, 0, &addr); 3129 tcg_gen_or_i32(dest, src, reg); 3130 DEST_EA(env, insn, opsize, dest, &addr); 3131 } else { 3132 SRC_EA(env, src, opsize, 0, NULL); 3133 tcg_gen_or_i32(dest, src, reg); 3134 gen_partset_reg(opsize, DREG(insn, 9), dest); 3135 } 3136 gen_logic_cc(s, dest, opsize); 3137 tcg_temp_free(dest); 3138 } 3139 3140 DISAS_INSN(suba) 3141 { 3142 TCGv src; 3143 TCGv reg; 3144 3145 SRC_EA(env, src, (insn & 0x100) ? OS_LONG : OS_WORD, 1, NULL); 3146 reg = AREG(insn, 9); 3147 tcg_gen_sub_i32(reg, reg, src); 3148 } 3149 3150 static inline void gen_subx(DisasContext *s, TCGv src, TCGv dest, int opsize) 3151 { 3152 TCGv tmp; 3153 3154 gen_flush_flags(s); /* compute old Z */ 3155 3156 /* 3157 * Perform substract with borrow. 3158 * (X, N) = dest - (src + X); 3159 */ 3160 3161 tmp = tcg_const_i32(0); 3162 tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, tmp, QREG_CC_X, tmp); 3163 tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, dest, tmp, QREG_CC_N, QREG_CC_X); 3164 gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1); 3165 tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1); 3166 3167 /* Compute signed-overflow for substract. */ 3168 3169 tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, dest); 3170 tcg_gen_xor_i32(tmp, dest, src); 3171 tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, tmp); 3172 tcg_temp_free(tmp); 3173 3174 /* Copy the rest of the results into place. */ 3175 tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */ 3176 tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); 3177 3178 set_cc_op(s, CC_OP_FLAGS); 3179 3180 /* result is in QREG_CC_N */ 3181 } 3182 3183 DISAS_INSN(subx_reg) 3184 { 3185 TCGv dest; 3186 TCGv src; 3187 int opsize; 3188 3189 opsize = insn_opsize(insn); 3190 3191 src = gen_extend(s, DREG(insn, 0), opsize, 1); 3192 dest = gen_extend(s, DREG(insn, 9), opsize, 1); 3193 3194 gen_subx(s, src, dest, opsize); 3195 3196 gen_partset_reg(opsize, DREG(insn, 9), QREG_CC_N); 3197 } 3198 3199 DISAS_INSN(subx_mem) 3200 { 3201 TCGv src; 3202 TCGv addr_src; 3203 TCGv dest; 3204 TCGv addr_dest; 3205 int opsize; 3206 3207 opsize = insn_opsize(insn); 3208 3209 addr_src = AREG(insn, 0); 3210 tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(opsize)); 3211 src = gen_load(s, opsize, addr_src, 1, IS_USER(s)); 3212 3213 addr_dest = AREG(insn, 9); 3214 tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(opsize)); 3215 dest = gen_load(s, opsize, addr_dest, 1, IS_USER(s)); 3216 3217 gen_subx(s, src, dest, opsize); 3218 3219 gen_store(s, opsize, addr_dest, QREG_CC_N, IS_USER(s)); 3220 3221 tcg_temp_free(dest); 3222 tcg_temp_free(src); 3223 } 3224 3225 DISAS_INSN(mov3q) 3226 { 3227 TCGv src; 3228 int val; 3229 3230 val = (insn >> 9) & 7; 3231 if (val == 0) 3232 val = -1; 3233 src = tcg_const_i32(val); 3234 gen_logic_cc(s, src, OS_LONG); 3235 DEST_EA(env, insn, OS_LONG, src, NULL); 3236 tcg_temp_free(src); 3237 } 3238 3239 DISAS_INSN(cmp) 3240 { 3241 TCGv src; 3242 TCGv reg; 3243 int opsize; 3244 3245 opsize = insn_opsize(insn); 3246 SRC_EA(env, src, opsize, 1, NULL); 3247 reg = gen_extend(s, DREG(insn, 9), opsize, 1); 3248 gen_update_cc_cmp(s, reg, src, opsize); 3249 } 3250 3251 DISAS_INSN(cmpa) 3252 { 3253 int opsize; 3254 TCGv src; 3255 TCGv reg; 3256 3257 if (insn & 0x100) { 3258 opsize = OS_LONG; 3259 } else { 3260 opsize = OS_WORD; 3261 } 3262 SRC_EA(env, src, opsize, 1, NULL); 3263 reg = AREG(insn, 9); 3264 gen_update_cc_cmp(s, reg, src, OS_LONG); 3265 } 3266 3267 DISAS_INSN(cmpm) 3268 { 3269 int opsize = insn_opsize(insn); 3270 TCGv src, dst; 3271 3272 /* Post-increment load (mode 3) from Ay. */ 3273 src = gen_ea_mode(env, s, 3, REG(insn, 0), opsize, 3274 NULL_QREG, NULL, EA_LOADS, IS_USER(s)); 3275 /* Post-increment load (mode 3) from Ax. */ 3276 dst = gen_ea_mode(env, s, 3, REG(insn, 9), opsize, 3277 NULL_QREG, NULL, EA_LOADS, IS_USER(s)); 3278 3279 gen_update_cc_cmp(s, dst, src, opsize); 3280 } 3281 3282 DISAS_INSN(eor) 3283 { 3284 TCGv src; 3285 TCGv dest; 3286 TCGv addr; 3287 int opsize; 3288 3289 opsize = insn_opsize(insn); 3290 3291 SRC_EA(env, src, opsize, 0, &addr); 3292 dest = tcg_temp_new(); 3293 tcg_gen_xor_i32(dest, src, DREG(insn, 9)); 3294 gen_logic_cc(s, dest, opsize); 3295 DEST_EA(env, insn, opsize, dest, &addr); 3296 tcg_temp_free(dest); 3297 } 3298 3299 static void do_exg(TCGv reg1, TCGv reg2) 3300 { 3301 TCGv temp = tcg_temp_new(); 3302 tcg_gen_mov_i32(temp, reg1); 3303 tcg_gen_mov_i32(reg1, reg2); 3304 tcg_gen_mov_i32(reg2, temp); 3305 tcg_temp_free(temp); 3306 } 3307 3308 DISAS_INSN(exg_dd) 3309 { 3310 /* exchange Dx and Dy */ 3311 do_exg(DREG(insn, 9), DREG(insn, 0)); 3312 } 3313 3314 DISAS_INSN(exg_aa) 3315 { 3316 /* exchange Ax and Ay */ 3317 do_exg(AREG(insn, 9), AREG(insn, 0)); 3318 } 3319 3320 DISAS_INSN(exg_da) 3321 { 3322 /* exchange Dx and Ay */ 3323 do_exg(DREG(insn, 9), AREG(insn, 0)); 3324 } 3325 3326 DISAS_INSN(and) 3327 { 3328 TCGv src; 3329 TCGv reg; 3330 TCGv dest; 3331 TCGv addr; 3332 int opsize; 3333 3334 dest = tcg_temp_new(); 3335 3336 opsize = insn_opsize(insn); 3337 reg = DREG(insn, 9); 3338 if (insn & 0x100) { 3339 SRC_EA(env, src, opsize, 0, &addr); 3340 tcg_gen_and_i32(dest, src, reg); 3341 DEST_EA(env, insn, opsize, dest, &addr); 3342 } else { 3343 SRC_EA(env, src, opsize, 0, NULL); 3344 tcg_gen_and_i32(dest, src, reg); 3345 gen_partset_reg(opsize, reg, dest); 3346 } 3347 gen_logic_cc(s, dest, opsize); 3348 tcg_temp_free(dest); 3349 } 3350 3351 DISAS_INSN(adda) 3352 { 3353 TCGv src; 3354 TCGv reg; 3355 3356 SRC_EA(env, src, (insn & 0x100) ? OS_LONG : OS_WORD, 1, NULL); 3357 reg = AREG(insn, 9); 3358 tcg_gen_add_i32(reg, reg, src); 3359 } 3360 3361 static inline void gen_addx(DisasContext *s, TCGv src, TCGv dest, int opsize) 3362 { 3363 TCGv tmp; 3364 3365 gen_flush_flags(s); /* compute old Z */ 3366 3367 /* 3368 * Perform addition with carry. 3369 * (X, N) = src + dest + X; 3370 */ 3371 3372 tmp = tcg_const_i32(0); 3373 tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_X, tmp, dest, tmp); 3374 tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_N, QREG_CC_X, src, tmp); 3375 gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1); 3376 3377 /* Compute signed-overflow for addition. */ 3378 3379 tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, src); 3380 tcg_gen_xor_i32(tmp, dest, src); 3381 tcg_gen_andc_i32(QREG_CC_V, QREG_CC_V, tmp); 3382 tcg_temp_free(tmp); 3383 3384 /* Copy the rest of the results into place. */ 3385 tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */ 3386 tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); 3387 3388 set_cc_op(s, CC_OP_FLAGS); 3389 3390 /* result is in QREG_CC_N */ 3391 } 3392 3393 DISAS_INSN(addx_reg) 3394 { 3395 TCGv dest; 3396 TCGv src; 3397 int opsize; 3398 3399 opsize = insn_opsize(insn); 3400 3401 dest = gen_extend(s, DREG(insn, 9), opsize, 1); 3402 src = gen_extend(s, DREG(insn, 0), opsize, 1); 3403 3404 gen_addx(s, src, dest, opsize); 3405 3406 gen_partset_reg(opsize, DREG(insn, 9), QREG_CC_N); 3407 } 3408 3409 DISAS_INSN(addx_mem) 3410 { 3411 TCGv src; 3412 TCGv addr_src; 3413 TCGv dest; 3414 TCGv addr_dest; 3415 int opsize; 3416 3417 opsize = insn_opsize(insn); 3418 3419 addr_src = AREG(insn, 0); 3420 tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(opsize)); 3421 src = gen_load(s, opsize, addr_src, 1, IS_USER(s)); 3422 3423 addr_dest = AREG(insn, 9); 3424 tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(opsize)); 3425 dest = gen_load(s, opsize, addr_dest, 1, IS_USER(s)); 3426 3427 gen_addx(s, src, dest, opsize); 3428 3429 gen_store(s, opsize, addr_dest, QREG_CC_N, IS_USER(s)); 3430 3431 tcg_temp_free(dest); 3432 tcg_temp_free(src); 3433 } 3434 3435 static inline void shift_im(DisasContext *s, uint16_t insn, int opsize) 3436 { 3437 int count = (insn >> 9) & 7; 3438 int logical = insn & 8; 3439 int left = insn & 0x100; 3440 int bits = opsize_bytes(opsize) * 8; 3441 TCGv reg = gen_extend(s, DREG(insn, 0), opsize, !logical); 3442 3443 if (count == 0) { 3444 count = 8; 3445 } 3446 3447 tcg_gen_movi_i32(QREG_CC_V, 0); 3448 if (left) { 3449 tcg_gen_shri_i32(QREG_CC_C, reg, bits - count); 3450 tcg_gen_shli_i32(QREG_CC_N, reg, count); 3451 3452 /* 3453 * Note that ColdFire always clears V (done above), 3454 * while M68000 sets if the most significant bit is changed at 3455 * any time during the shift operation. 3456 */ 3457 if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) { 3458 /* if shift count >= bits, V is (reg != 0) */ 3459 if (count >= bits) { 3460 tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, reg, QREG_CC_V); 3461 } else { 3462 TCGv t0 = tcg_temp_new(); 3463 tcg_gen_sari_i32(QREG_CC_V, reg, bits - 1); 3464 tcg_gen_sari_i32(t0, reg, bits - count - 1); 3465 tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, t0); 3466 tcg_temp_free(t0); 3467 } 3468 tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V); 3469 } 3470 } else { 3471 tcg_gen_shri_i32(QREG_CC_C, reg, count - 1); 3472 if (logical) { 3473 tcg_gen_shri_i32(QREG_CC_N, reg, count); 3474 } else { 3475 tcg_gen_sari_i32(QREG_CC_N, reg, count); 3476 } 3477 } 3478 3479 gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1); 3480 tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1); 3481 tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N); 3482 tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C); 3483 3484 gen_partset_reg(opsize, DREG(insn, 0), QREG_CC_N); 3485 set_cc_op(s, CC_OP_FLAGS); 3486 } 3487 3488 static inline void shift_reg(DisasContext *s, uint16_t insn, int opsize) 3489 { 3490 int logical = insn & 8; 3491 int left = insn & 0x100; 3492 int bits = opsize_bytes(opsize) * 8; 3493 TCGv reg = gen_extend(s, DREG(insn, 0), opsize, !logical); 3494 TCGv s32; 3495 TCGv_i64 t64, s64; 3496 3497 t64 = tcg_temp_new_i64(); 3498 s64 = tcg_temp_new_i64(); 3499 s32 = tcg_temp_new(); 3500 3501 /* 3502 * Note that m68k truncates the shift count modulo 64, not 32. 3503 * In addition, a 64-bit shift makes it easy to find "the last 3504 * bit shifted out", for the carry flag. 3505 */ 3506 tcg_gen_andi_i32(s32, DREG(insn, 9), 63); 3507 tcg_gen_extu_i32_i64(s64, s32); 3508 tcg_gen_extu_i32_i64(t64, reg); 3509 3510 /* Optimistically set V=0. Also used as a zero source below. */ 3511 tcg_gen_movi_i32(QREG_CC_V, 0); 3512 if (left) { 3513 tcg_gen_shl_i64(t64, t64, s64); 3514 3515 if (opsize == OS_LONG) { 3516 tcg_gen_extr_i64_i32(QREG_CC_N, QREG_CC_C, t64); 3517 /* Note that C=0 if shift count is 0, and we get that for free. */ 3518 } else { 3519 TCGv zero = tcg_const_i32(0); 3520 tcg_gen_extrl_i64_i32(QREG_CC_N, t64); 3521 tcg_gen_shri_i32(QREG_CC_C, QREG_CC_N, bits); 3522 tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C, 3523 s32, zero, zero, QREG_CC_C); 3524 tcg_temp_free(zero); 3525 } 3526 tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1); 3527 3528 /* X = C, but only if the shift count was non-zero. */ 3529 tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V, 3530 QREG_CC_C, QREG_CC_X); 3531 3532 /* 3533 * M68000 sets V if the most significant bit is changed at 3534 * any time during the shift operation. Do this via creating 3535 * an extension of the sign bit, comparing, and discarding 3536 * the bits below the sign bit. I.e. 3537 * int64_t s = (intN_t)reg; 3538 * int64_t t = (int64_t)(intN_t)reg << count; 3539 * V = ((s ^ t) & (-1 << (bits - 1))) != 0 3540 */ 3541 if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) { 3542 TCGv_i64 tt = tcg_const_i64(32); 3543 /* if shift is greater than 32, use 32 */ 3544 tcg_gen_movcond_i64(TCG_COND_GT, s64, s64, tt, tt, s64); 3545 tcg_temp_free_i64(tt); 3546 /* Sign extend the input to 64 bits; re-do the shift. */ 3547 tcg_gen_ext_i32_i64(t64, reg); 3548 tcg_gen_shl_i64(s64, t64, s64); 3549 /* Clear all bits that are unchanged. */ 3550 tcg_gen_xor_i64(t64, t64, s64); 3551 /* Ignore the bits below the sign bit. */ 3552 tcg_gen_andi_i64(t64, t64, -1ULL << (bits - 1)); 3553 /* If any bits remain set, we have overflow. */ 3554 tcg_gen_setcondi_i64(TCG_COND_NE, t64, t64, 0); 3555 tcg_gen_extrl_i64_i32(QREG_CC_V, t64); 3556 tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V); 3557 } 3558 } else { 3559 tcg_gen_shli_i64(t64, t64, 32); 3560 if (logical) { 3561 tcg_gen_shr_i64(t64, t64, s64); 3562 } else { 3563 tcg_gen_sar_i64(t64, t64, s64); 3564 } 3565 tcg_gen_extr_i64_i32(QREG_CC_C, QREG_CC_N, t64); 3566 3567 /* Note that C=0 if shift count is 0, and we get that for free. */ 3568 tcg_gen_shri_i32(QREG_CC_C, QREG_CC_C, 31); 3569 3570 /* X = C, but only if the shift count was non-zero. */ 3571 tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V, 3572 QREG_CC_C, QREG_CC_X); 3573 } 3574 gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1); 3575 tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N); 3576 3577 tcg_temp_free(s32); 3578 tcg_temp_free_i64(s64); 3579 tcg_temp_free_i64(t64); 3580 3581 /* Write back the result. */ 3582 gen_partset_reg(opsize, DREG(insn, 0), QREG_CC_N); 3583 set_cc_op(s, CC_OP_FLAGS); 3584 } 3585 3586 DISAS_INSN(shift8_im) 3587 { 3588 shift_im(s, insn, OS_BYTE); 3589 } 3590 3591 DISAS_INSN(shift16_im) 3592 { 3593 shift_im(s, insn, OS_WORD); 3594 } 3595 3596 DISAS_INSN(shift_im) 3597 { 3598 shift_im(s, insn, OS_LONG); 3599 } 3600 3601 DISAS_INSN(shift8_reg) 3602 { 3603 shift_reg(s, insn, OS_BYTE); 3604 } 3605 3606 DISAS_INSN(shift16_reg) 3607 { 3608 shift_reg(s, insn, OS_WORD); 3609 } 3610 3611 DISAS_INSN(shift_reg) 3612 { 3613 shift_reg(s, insn, OS_LONG); 3614 } 3615 3616 DISAS_INSN(shift_mem) 3617 { 3618 int logical = insn & 8; 3619 int left = insn & 0x100; 3620 TCGv src; 3621 TCGv addr; 3622 3623 SRC_EA(env, src, OS_WORD, !logical, &addr); 3624 tcg_gen_movi_i32(QREG_CC_V, 0); 3625 if (left) { 3626 tcg_gen_shri_i32(QREG_CC_C, src, 15); 3627 tcg_gen_shli_i32(QREG_CC_N, src, 1); 3628 3629 /* 3630 * Note that ColdFire always clears V, 3631 * while M68000 sets if the most significant bit is changed at 3632 * any time during the shift operation 3633 */ 3634 if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) { 3635 src = gen_extend(s, src, OS_WORD, 1); 3636 tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, src); 3637 } 3638 } else { 3639 tcg_gen_mov_i32(QREG_CC_C, src); 3640 if (logical) { 3641 tcg_gen_shri_i32(QREG_CC_N, src, 1); 3642 } else { 3643 tcg_gen_sari_i32(QREG_CC_N, src, 1); 3644 } 3645 } 3646 3647 gen_ext(QREG_CC_N, QREG_CC_N, OS_WORD, 1); 3648 tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1); 3649 tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N); 3650 tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C); 3651 3652 DEST_EA(env, insn, OS_WORD, QREG_CC_N, &addr); 3653 set_cc_op(s, CC_OP_FLAGS); 3654 } 3655 3656 static void rotate(TCGv reg, TCGv shift, int left, int size) 3657 { 3658 switch (size) { 3659 case 8: 3660 /* Replicate the 8-bit input so that a 32-bit rotate works. */ 3661 tcg_gen_ext8u_i32(reg, reg); 3662 tcg_gen_muli_i32(reg, reg, 0x01010101); 3663 goto do_long; 3664 case 16: 3665 /* Replicate the 16-bit input so that a 32-bit rotate works. */ 3666 tcg_gen_deposit_i32(reg, reg, reg, 16, 16); 3667 goto do_long; 3668 do_long: 3669 default: 3670 if (left) { 3671 tcg_gen_rotl_i32(reg, reg, shift); 3672 } else { 3673 tcg_gen_rotr_i32(reg, reg, shift); 3674 } 3675 } 3676 3677 /* compute flags */ 3678 3679 switch (size) { 3680 case 8: 3681 tcg_gen_ext8s_i32(reg, reg); 3682 break; 3683 case 16: 3684 tcg_gen_ext16s_i32(reg, reg); 3685 break; 3686 default: 3687 break; 3688 } 3689 3690 /* QREG_CC_X is not affected */ 3691 3692 tcg_gen_mov_i32(QREG_CC_N, reg); 3693 tcg_gen_mov_i32(QREG_CC_Z, reg); 3694 3695 if (left) { 3696 tcg_gen_andi_i32(QREG_CC_C, reg, 1); 3697 } else { 3698 tcg_gen_shri_i32(QREG_CC_C, reg, 31); 3699 } 3700 3701 tcg_gen_movi_i32(QREG_CC_V, 0); /* always cleared */ 3702 } 3703 3704 static void rotate_x_flags(TCGv reg, TCGv X, int size) 3705 { 3706 switch (size) { 3707 case 8: 3708 tcg_gen_ext8s_i32(reg, reg); 3709 break; 3710 case 16: 3711 tcg_gen_ext16s_i32(reg, reg); 3712 break; 3713 default: 3714 break; 3715 } 3716 tcg_gen_mov_i32(QREG_CC_N, reg); 3717 tcg_gen_mov_i32(QREG_CC_Z, reg); 3718 tcg_gen_mov_i32(QREG_CC_X, X); 3719 tcg_gen_mov_i32(QREG_CC_C, X); 3720 tcg_gen_movi_i32(QREG_CC_V, 0); 3721 } 3722 3723 /* Result of rotate_x() is valid if 0 <= shift <= size */ 3724 static TCGv rotate_x(TCGv reg, TCGv shift, int left, int size) 3725 { 3726 TCGv X, shl, shr, shx, sz, zero; 3727 3728 sz = tcg_const_i32(size); 3729 3730 shr = tcg_temp_new(); 3731 shl = tcg_temp_new(); 3732 shx = tcg_temp_new(); 3733 if (left) { 3734 tcg_gen_mov_i32(shl, shift); /* shl = shift */ 3735 tcg_gen_movi_i32(shr, size + 1); 3736 tcg_gen_sub_i32(shr, shr, shift); /* shr = size + 1 - shift */ 3737 tcg_gen_subi_i32(shx, shift, 1); /* shx = shift - 1 */ 3738 /* shx = shx < 0 ? size : shx; */ 3739 zero = tcg_const_i32(0); 3740 tcg_gen_movcond_i32(TCG_COND_LT, shx, shx, zero, sz, shx); 3741 tcg_temp_free(zero); 3742 } else { 3743 tcg_gen_mov_i32(shr, shift); /* shr = shift */ 3744 tcg_gen_movi_i32(shl, size + 1); 3745 tcg_gen_sub_i32(shl, shl, shift); /* shl = size + 1 - shift */ 3746 tcg_gen_sub_i32(shx, sz, shift); /* shx = size - shift */ 3747 } 3748 tcg_temp_free_i32(sz); 3749 3750 /* reg = (reg << shl) | (reg >> shr) | (x << shx); */ 3751 3752 tcg_gen_shl_i32(shl, reg, shl); 3753 tcg_gen_shr_i32(shr, reg, shr); 3754 tcg_gen_or_i32(reg, shl, shr); 3755 tcg_temp_free(shl); 3756 tcg_temp_free(shr); 3757 tcg_gen_shl_i32(shx, QREG_CC_X, shx); 3758 tcg_gen_or_i32(reg, reg, shx); 3759 tcg_temp_free(shx); 3760 3761 /* X = (reg >> size) & 1 */ 3762 3763 X = tcg_temp_new(); 3764 tcg_gen_extract_i32(X, reg, size, 1); 3765 3766 return X; 3767 } 3768 3769 /* Result of rotate32_x() is valid if 0 <= shift < 33 */ 3770 static TCGv rotate32_x(TCGv reg, TCGv shift, int left) 3771 { 3772 TCGv_i64 t0, shift64; 3773 TCGv X, lo, hi, zero; 3774 3775 shift64 = tcg_temp_new_i64(); 3776 tcg_gen_extu_i32_i64(shift64, shift); 3777 3778 t0 = tcg_temp_new_i64(); 3779 3780 X = tcg_temp_new(); 3781 lo = tcg_temp_new(); 3782 hi = tcg_temp_new(); 3783 3784 if (left) { 3785 /* create [reg:X:..] */ 3786 3787 tcg_gen_shli_i32(lo, QREG_CC_X, 31); 3788 tcg_gen_concat_i32_i64(t0, lo, reg); 3789 3790 /* rotate */ 3791 3792 tcg_gen_rotl_i64(t0, t0, shift64); 3793 tcg_temp_free_i64(shift64); 3794 3795 /* result is [reg:..:reg:X] */ 3796 3797 tcg_gen_extr_i64_i32(lo, hi, t0); 3798 tcg_gen_andi_i32(X, lo, 1); 3799 3800 tcg_gen_shri_i32(lo, lo, 1); 3801 } else { 3802 /* create [..:X:reg] */ 3803 3804 tcg_gen_concat_i32_i64(t0, reg, QREG_CC_X); 3805 3806 tcg_gen_rotr_i64(t0, t0, shift64); 3807 tcg_temp_free_i64(shift64); 3808 3809 /* result is value: [X:reg:..:reg] */ 3810 3811 tcg_gen_extr_i64_i32(lo, hi, t0); 3812 3813 /* extract X */ 3814 3815 tcg_gen_shri_i32(X, hi, 31); 3816 3817 /* extract result */ 3818 3819 tcg_gen_shli_i32(hi, hi, 1); 3820 } 3821 tcg_temp_free_i64(t0); 3822 tcg_gen_or_i32(lo, lo, hi); 3823 tcg_temp_free(hi); 3824 3825 /* if shift == 0, register and X are not affected */ 3826 3827 zero = tcg_const_i32(0); 3828 tcg_gen_movcond_i32(TCG_COND_EQ, X, shift, zero, QREG_CC_X, X); 3829 tcg_gen_movcond_i32(TCG_COND_EQ, reg, shift, zero, reg, lo); 3830 tcg_temp_free(zero); 3831 tcg_temp_free(lo); 3832 3833 return X; 3834 } 3835 3836 DISAS_INSN(rotate_im) 3837 { 3838 TCGv shift; 3839 int tmp; 3840 int left = (insn & 0x100); 3841 3842 tmp = (insn >> 9) & 7; 3843 if (tmp == 0) { 3844 tmp = 8; 3845 } 3846 3847 shift = tcg_const_i32(tmp); 3848 if (insn & 8) { 3849 rotate(DREG(insn, 0), shift, left, 32); 3850 } else { 3851 TCGv X = rotate32_x(DREG(insn, 0), shift, left); 3852 rotate_x_flags(DREG(insn, 0), X, 32); 3853 tcg_temp_free(X); 3854 } 3855 tcg_temp_free(shift); 3856 3857 set_cc_op(s, CC_OP_FLAGS); 3858 } 3859 3860 DISAS_INSN(rotate8_im) 3861 { 3862 int left = (insn & 0x100); 3863 TCGv reg; 3864 TCGv shift; 3865 int tmp; 3866 3867 reg = gen_extend(s, DREG(insn, 0), OS_BYTE, 0); 3868 3869 tmp = (insn >> 9) & 7; 3870 if (tmp == 0) { 3871 tmp = 8; 3872 } 3873 3874 shift = tcg_const_i32(tmp); 3875 if (insn & 8) { 3876 rotate(reg, shift, left, 8); 3877 } else { 3878 TCGv X = rotate_x(reg, shift, left, 8); 3879 rotate_x_flags(reg, X, 8); 3880 tcg_temp_free(X); 3881 } 3882 tcg_temp_free(shift); 3883 gen_partset_reg(OS_BYTE, DREG(insn, 0), reg); 3884 set_cc_op(s, CC_OP_FLAGS); 3885 } 3886 3887 DISAS_INSN(rotate16_im) 3888 { 3889 int left = (insn & 0x100); 3890 TCGv reg; 3891 TCGv shift; 3892 int tmp; 3893 3894 reg = gen_extend(s, DREG(insn, 0), OS_WORD, 0); 3895 tmp = (insn >> 9) & 7; 3896 if (tmp == 0) { 3897 tmp = 8; 3898 } 3899 3900 shift = tcg_const_i32(tmp); 3901 if (insn & 8) { 3902 rotate(reg, shift, left, 16); 3903 } else { 3904 TCGv X = rotate_x(reg, shift, left, 16); 3905 rotate_x_flags(reg, X, 16); 3906 tcg_temp_free(X); 3907 } 3908 tcg_temp_free(shift); 3909 gen_partset_reg(OS_WORD, DREG(insn, 0), reg); 3910 set_cc_op(s, CC_OP_FLAGS); 3911 } 3912 3913 DISAS_INSN(rotate_reg) 3914 { 3915 TCGv reg; 3916 TCGv src; 3917 TCGv t0, t1; 3918 int left = (insn & 0x100); 3919 3920 reg = DREG(insn, 0); 3921 src = DREG(insn, 9); 3922 /* shift in [0..63] */ 3923 t0 = tcg_temp_new(); 3924 tcg_gen_andi_i32(t0, src, 63); 3925 t1 = tcg_temp_new_i32(); 3926 if (insn & 8) { 3927 tcg_gen_andi_i32(t1, src, 31); 3928 rotate(reg, t1, left, 32); 3929 /* if shift == 0, clear C */ 3930 tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C, 3931 t0, QREG_CC_V /* 0 */, 3932 QREG_CC_V /* 0 */, QREG_CC_C); 3933 } else { 3934 TCGv X; 3935 /* modulo 33 */ 3936 tcg_gen_movi_i32(t1, 33); 3937 tcg_gen_remu_i32(t1, t0, t1); 3938 X = rotate32_x(DREG(insn, 0), t1, left); 3939 rotate_x_flags(DREG(insn, 0), X, 32); 3940 tcg_temp_free(X); 3941 } 3942 tcg_temp_free(t1); 3943 tcg_temp_free(t0); 3944 set_cc_op(s, CC_OP_FLAGS); 3945 } 3946 3947 DISAS_INSN(rotate8_reg) 3948 { 3949 TCGv reg; 3950 TCGv src; 3951 TCGv t0, t1; 3952 int left = (insn & 0x100); 3953 3954 reg = gen_extend(s, DREG(insn, 0), OS_BYTE, 0); 3955 src = DREG(insn, 9); 3956 /* shift in [0..63] */ 3957 t0 = tcg_temp_new_i32(); 3958 tcg_gen_andi_i32(t0, src, 63); 3959 t1 = tcg_temp_new_i32(); 3960 if (insn & 8) { 3961 tcg_gen_andi_i32(t1, src, 7); 3962 rotate(reg, t1, left, 8); 3963 /* if shift == 0, clear C */ 3964 tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C, 3965 t0, QREG_CC_V /* 0 */, 3966 QREG_CC_V /* 0 */, QREG_CC_C); 3967 } else { 3968 TCGv X; 3969 /* modulo 9 */ 3970 tcg_gen_movi_i32(t1, 9); 3971 tcg_gen_remu_i32(t1, t0, t1); 3972 X = rotate_x(reg, t1, left, 8); 3973 rotate_x_flags(reg, X, 8); 3974 tcg_temp_free(X); 3975 } 3976 tcg_temp_free(t1); 3977 tcg_temp_free(t0); 3978 gen_partset_reg(OS_BYTE, DREG(insn, 0), reg); 3979 set_cc_op(s, CC_OP_FLAGS); 3980 } 3981 3982 DISAS_INSN(rotate16_reg) 3983 { 3984 TCGv reg; 3985 TCGv src; 3986 TCGv t0, t1; 3987 int left = (insn & 0x100); 3988 3989 reg = gen_extend(s, DREG(insn, 0), OS_WORD, 0); 3990 src = DREG(insn, 9); 3991 /* shift in [0..63] */ 3992 t0 = tcg_temp_new_i32(); 3993 tcg_gen_andi_i32(t0, src, 63); 3994 t1 = tcg_temp_new_i32(); 3995 if (insn & 8) { 3996 tcg_gen_andi_i32(t1, src, 15); 3997 rotate(reg, t1, left, 16); 3998 /* if shift == 0, clear C */ 3999 tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C, 4000 t0, QREG_CC_V /* 0 */, 4001 QREG_CC_V /* 0 */, QREG_CC_C); 4002 } else { 4003 TCGv X; 4004 /* modulo 17 */ 4005 tcg_gen_movi_i32(t1, 17); 4006 tcg_gen_remu_i32(t1, t0, t1); 4007 X = rotate_x(reg, t1, left, 16); 4008 rotate_x_flags(reg, X, 16); 4009 tcg_temp_free(X); 4010 } 4011 tcg_temp_free(t1); 4012 tcg_temp_free(t0); 4013 gen_partset_reg(OS_WORD, DREG(insn, 0), reg); 4014 set_cc_op(s, CC_OP_FLAGS); 4015 } 4016 4017 DISAS_INSN(rotate_mem) 4018 { 4019 TCGv src; 4020 TCGv addr; 4021 TCGv shift; 4022 int left = (insn & 0x100); 4023 4024 SRC_EA(env, src, OS_WORD, 0, &addr); 4025 4026 shift = tcg_const_i32(1); 4027 if (insn & 0x0200) { 4028 rotate(src, shift, left, 16); 4029 } else { 4030 TCGv X = rotate_x(src, shift, left, 16); 4031 rotate_x_flags(src, X, 16); 4032 tcg_temp_free(X); 4033 } 4034 tcg_temp_free(shift); 4035 DEST_EA(env, insn, OS_WORD, src, &addr); 4036 set_cc_op(s, CC_OP_FLAGS); 4037 } 4038 4039 DISAS_INSN(bfext_reg) 4040 { 4041 int ext = read_im16(env, s); 4042 int is_sign = insn & 0x200; 4043 TCGv src = DREG(insn, 0); 4044 TCGv dst = DREG(ext, 12); 4045 int len = ((extract32(ext, 0, 5) - 1) & 31) + 1; 4046 int ofs = extract32(ext, 6, 5); /* big bit-endian */ 4047 int pos = 32 - ofs - len; /* little bit-endian */ 4048 TCGv tmp = tcg_temp_new(); 4049 TCGv shift; 4050 4051 /* 4052 * In general, we're going to rotate the field so that it's at the 4053 * top of the word and then right-shift by the complement of the 4054 * width to extend the field. 4055 */ 4056 if (ext & 0x20) { 4057 /* Variable width. */ 4058 if (ext & 0x800) { 4059 /* Variable offset. */ 4060 tcg_gen_andi_i32(tmp, DREG(ext, 6), 31); 4061 tcg_gen_rotl_i32(tmp, src, tmp); 4062 } else { 4063 tcg_gen_rotli_i32(tmp, src, ofs); 4064 } 4065 4066 shift = tcg_temp_new(); 4067 tcg_gen_neg_i32(shift, DREG(ext, 0)); 4068 tcg_gen_andi_i32(shift, shift, 31); 4069 tcg_gen_sar_i32(QREG_CC_N, tmp, shift); 4070 if (is_sign) { 4071 tcg_gen_mov_i32(dst, QREG_CC_N); 4072 } else { 4073 tcg_gen_shr_i32(dst, tmp, shift); 4074 } 4075 tcg_temp_free(shift); 4076 } else { 4077 /* Immediate width. */ 4078 if (ext & 0x800) { 4079 /* Variable offset */ 4080 tcg_gen_andi_i32(tmp, DREG(ext, 6), 31); 4081 tcg_gen_rotl_i32(tmp, src, tmp); 4082 src = tmp; 4083 pos = 32 - len; 4084 } else { 4085 /* 4086 * Immediate offset. If the field doesn't wrap around the 4087 * end of the word, rely on (s)extract completely. 4088 */ 4089 if (pos < 0) { 4090 tcg_gen_rotli_i32(tmp, src, ofs); 4091 src = tmp; 4092 pos = 32 - len; 4093 } 4094 } 4095 4096 tcg_gen_sextract_i32(QREG_CC_N, src, pos, len); 4097 if (is_sign) { 4098 tcg_gen_mov_i32(dst, QREG_CC_N); 4099 } else { 4100 tcg_gen_extract_i32(dst, src, pos, len); 4101 } 4102 } 4103 4104 tcg_temp_free(tmp); 4105 set_cc_op(s, CC_OP_LOGIC); 4106 } 4107 4108 DISAS_INSN(bfext_mem) 4109 { 4110 int ext = read_im16(env, s); 4111 int is_sign = insn & 0x200; 4112 TCGv dest = DREG(ext, 12); 4113 TCGv addr, len, ofs; 4114 4115 addr = gen_lea(env, s, insn, OS_UNSIZED); 4116 if (IS_NULL_QREG(addr)) { 4117 gen_addr_fault(s); 4118 return; 4119 } 4120 4121 if (ext & 0x20) { 4122 len = DREG(ext, 0); 4123 } else { 4124 len = tcg_const_i32(extract32(ext, 0, 5)); 4125 } 4126 if (ext & 0x800) { 4127 ofs = DREG(ext, 6); 4128 } else { 4129 ofs = tcg_const_i32(extract32(ext, 6, 5)); 4130 } 4131 4132 if (is_sign) { 4133 gen_helper_bfexts_mem(dest, cpu_env, addr, ofs, len); 4134 tcg_gen_mov_i32(QREG_CC_N, dest); 4135 } else { 4136 TCGv_i64 tmp = tcg_temp_new_i64(); 4137 gen_helper_bfextu_mem(tmp, cpu_env, addr, ofs, len); 4138 tcg_gen_extr_i64_i32(dest, QREG_CC_N, tmp); 4139 tcg_temp_free_i64(tmp); 4140 } 4141 set_cc_op(s, CC_OP_LOGIC); 4142 4143 if (!(ext & 0x20)) { 4144 tcg_temp_free(len); 4145 } 4146 if (!(ext & 0x800)) { 4147 tcg_temp_free(ofs); 4148 } 4149 } 4150 4151 DISAS_INSN(bfop_reg) 4152 { 4153 int ext = read_im16(env, s); 4154 TCGv src = DREG(insn, 0); 4155 int len = ((extract32(ext, 0, 5) - 1) & 31) + 1; 4156 int ofs = extract32(ext, 6, 5); /* big bit-endian */ 4157 TCGv mask, tofs, tlen; 4158 4159 tofs = NULL; 4160 tlen = NULL; 4161 if ((insn & 0x0f00) == 0x0d00) { /* bfffo */ 4162 tofs = tcg_temp_new(); 4163 tlen = tcg_temp_new(); 4164 } 4165 4166 if ((ext & 0x820) == 0) { 4167 /* Immediate width and offset. */ 4168 uint32_t maski = 0x7fffffffu >> (len - 1); 4169 if (ofs + len <= 32) { 4170 tcg_gen_shli_i32(QREG_CC_N, src, ofs); 4171 } else { 4172 tcg_gen_rotli_i32(QREG_CC_N, src, ofs); 4173 } 4174 tcg_gen_andi_i32(QREG_CC_N, QREG_CC_N, ~maski); 4175 mask = tcg_const_i32(ror32(maski, ofs)); 4176 if (tofs) { 4177 tcg_gen_movi_i32(tofs, ofs); 4178 tcg_gen_movi_i32(tlen, len); 4179 } 4180 } else { 4181 TCGv tmp = tcg_temp_new(); 4182 if (ext & 0x20) { 4183 /* Variable width */ 4184 tcg_gen_subi_i32(tmp, DREG(ext, 0), 1); 4185 tcg_gen_andi_i32(tmp, tmp, 31); 4186 mask = tcg_const_i32(0x7fffffffu); 4187 tcg_gen_shr_i32(mask, mask, tmp); 4188 if (tlen) { 4189 tcg_gen_addi_i32(tlen, tmp, 1); 4190 } 4191 } else { 4192 /* Immediate width */ 4193 mask = tcg_const_i32(0x7fffffffu >> (len - 1)); 4194 if (tlen) { 4195 tcg_gen_movi_i32(tlen, len); 4196 } 4197 } 4198 if (ext & 0x800) { 4199 /* Variable offset */ 4200 tcg_gen_andi_i32(tmp, DREG(ext, 6), 31); 4201 tcg_gen_rotl_i32(QREG_CC_N, src, tmp); 4202 tcg_gen_andc_i32(QREG_CC_N, QREG_CC_N, mask); 4203 tcg_gen_rotr_i32(mask, mask, tmp); 4204 if (tofs) { 4205 tcg_gen_mov_i32(tofs, tmp); 4206 } 4207 } else { 4208 /* Immediate offset (and variable width) */ 4209 tcg_gen_rotli_i32(QREG_CC_N, src, ofs); 4210 tcg_gen_andc_i32(QREG_CC_N, QREG_CC_N, mask); 4211 tcg_gen_rotri_i32(mask, mask, ofs); 4212 if (tofs) { 4213 tcg_gen_movi_i32(tofs, ofs); 4214 } 4215 } 4216 tcg_temp_free(tmp); 4217 } 4218 set_cc_op(s, CC_OP_LOGIC); 4219 4220 switch (insn & 0x0f00) { 4221 case 0x0a00: /* bfchg */ 4222 tcg_gen_eqv_i32(src, src, mask); 4223 break; 4224 case 0x0c00: /* bfclr */ 4225 tcg_gen_and_i32(src, src, mask); 4226 break; 4227 case 0x0d00: /* bfffo */ 4228 gen_helper_bfffo_reg(DREG(ext, 12), QREG_CC_N, tofs, tlen); 4229 tcg_temp_free(tlen); 4230 tcg_temp_free(tofs); 4231 break; 4232 case 0x0e00: /* bfset */ 4233 tcg_gen_orc_i32(src, src, mask); 4234 break; 4235 case 0x0800: /* bftst */ 4236 /* flags already set; no other work to do. */ 4237 break; 4238 default: 4239 g_assert_not_reached(); 4240 } 4241 tcg_temp_free(mask); 4242 } 4243 4244 DISAS_INSN(bfop_mem) 4245 { 4246 int ext = read_im16(env, s); 4247 TCGv addr, len, ofs; 4248 TCGv_i64 t64; 4249 4250 addr = gen_lea(env, s, insn, OS_UNSIZED); 4251 if (IS_NULL_QREG(addr)) { 4252 gen_addr_fault(s); 4253 return; 4254 } 4255 4256 if (ext & 0x20) { 4257 len = DREG(ext, 0); 4258 } else { 4259 len = tcg_const_i32(extract32(ext, 0, 5)); 4260 } 4261 if (ext & 0x800) { 4262 ofs = DREG(ext, 6); 4263 } else { 4264 ofs = tcg_const_i32(extract32(ext, 6, 5)); 4265 } 4266 4267 switch (insn & 0x0f00) { 4268 case 0x0a00: /* bfchg */ 4269 gen_helper_bfchg_mem(QREG_CC_N, cpu_env, addr, ofs, len); 4270 break; 4271 case 0x0c00: /* bfclr */ 4272 gen_helper_bfclr_mem(QREG_CC_N, cpu_env, addr, ofs, len); 4273 break; 4274 case 0x0d00: /* bfffo */ 4275 t64 = tcg_temp_new_i64(); 4276 gen_helper_bfffo_mem(t64, cpu_env, addr, ofs, len); 4277 tcg_gen_extr_i64_i32(DREG(ext, 12), QREG_CC_N, t64); 4278 tcg_temp_free_i64(t64); 4279 break; 4280 case 0x0e00: /* bfset */ 4281 gen_helper_bfset_mem(QREG_CC_N, cpu_env, addr, ofs, len); 4282 break; 4283 case 0x0800: /* bftst */ 4284 gen_helper_bfexts_mem(QREG_CC_N, cpu_env, addr, ofs, len); 4285 break; 4286 default: 4287 g_assert_not_reached(); 4288 } 4289 set_cc_op(s, CC_OP_LOGIC); 4290 4291 if (!(ext & 0x20)) { 4292 tcg_temp_free(len); 4293 } 4294 if (!(ext & 0x800)) { 4295 tcg_temp_free(ofs); 4296 } 4297 } 4298 4299 DISAS_INSN(bfins_reg) 4300 { 4301 int ext = read_im16(env, s); 4302 TCGv dst = DREG(insn, 0); 4303 TCGv src = DREG(ext, 12); 4304 int len = ((extract32(ext, 0, 5) - 1) & 31) + 1; 4305 int ofs = extract32(ext, 6, 5); /* big bit-endian */ 4306 int pos = 32 - ofs - len; /* little bit-endian */ 4307 TCGv tmp; 4308 4309 tmp = tcg_temp_new(); 4310 4311 if (ext & 0x20) { 4312 /* Variable width */ 4313 tcg_gen_neg_i32(tmp, DREG(ext, 0)); 4314 tcg_gen_andi_i32(tmp, tmp, 31); 4315 tcg_gen_shl_i32(QREG_CC_N, src, tmp); 4316 } else { 4317 /* Immediate width */ 4318 tcg_gen_shli_i32(QREG_CC_N, src, 32 - len); 4319 } 4320 set_cc_op(s, CC_OP_LOGIC); 4321 4322 /* Immediate width and offset */ 4323 if ((ext & 0x820) == 0) { 4324 /* Check for suitability for deposit. */ 4325 if (pos >= 0) { 4326 tcg_gen_deposit_i32(dst, dst, src, pos, len); 4327 } else { 4328 uint32_t maski = -2U << (len - 1); 4329 uint32_t roti = (ofs + len) & 31; 4330 tcg_gen_andi_i32(tmp, src, ~maski); 4331 tcg_gen_rotri_i32(tmp, tmp, roti); 4332 tcg_gen_andi_i32(dst, dst, ror32(maski, roti)); 4333 tcg_gen_or_i32(dst, dst, tmp); 4334 } 4335 } else { 4336 TCGv mask = tcg_temp_new(); 4337 TCGv rot = tcg_temp_new(); 4338 4339 if (ext & 0x20) { 4340 /* Variable width */ 4341 tcg_gen_subi_i32(rot, DREG(ext, 0), 1); 4342 tcg_gen_andi_i32(rot, rot, 31); 4343 tcg_gen_movi_i32(mask, -2); 4344 tcg_gen_shl_i32(mask, mask, rot); 4345 tcg_gen_mov_i32(rot, DREG(ext, 0)); 4346 tcg_gen_andc_i32(tmp, src, mask); 4347 } else { 4348 /* Immediate width (variable offset) */ 4349 uint32_t maski = -2U << (len - 1); 4350 tcg_gen_andi_i32(tmp, src, ~maski); 4351 tcg_gen_movi_i32(mask, maski); 4352 tcg_gen_movi_i32(rot, len & 31); 4353 } 4354 if (ext & 0x800) { 4355 /* Variable offset */ 4356 tcg_gen_add_i32(rot, rot, DREG(ext, 6)); 4357 } else { 4358 /* Immediate offset (variable width) */ 4359 tcg_gen_addi_i32(rot, rot, ofs); 4360 } 4361 tcg_gen_andi_i32(rot, rot, 31); 4362 tcg_gen_rotr_i32(mask, mask, rot); 4363 tcg_gen_rotr_i32(tmp, tmp, rot); 4364 tcg_gen_and_i32(dst, dst, mask); 4365 tcg_gen_or_i32(dst, dst, tmp); 4366 4367 tcg_temp_free(rot); 4368 tcg_temp_free(mask); 4369 } 4370 tcg_temp_free(tmp); 4371 } 4372 4373 DISAS_INSN(bfins_mem) 4374 { 4375 int ext = read_im16(env, s); 4376 TCGv src = DREG(ext, 12); 4377 TCGv addr, len, ofs; 4378 4379 addr = gen_lea(env, s, insn, OS_UNSIZED); 4380 if (IS_NULL_QREG(addr)) { 4381 gen_addr_fault(s); 4382 return; 4383 } 4384 4385 if (ext & 0x20) { 4386 len = DREG(ext, 0); 4387 } else { 4388 len = tcg_const_i32(extract32(ext, 0, 5)); 4389 } 4390 if (ext & 0x800) { 4391 ofs = DREG(ext, 6); 4392 } else { 4393 ofs = tcg_const_i32(extract32(ext, 6, 5)); 4394 } 4395 4396 gen_helper_bfins_mem(QREG_CC_N, cpu_env, addr, src, ofs, len); 4397 set_cc_op(s, CC_OP_LOGIC); 4398 4399 if (!(ext & 0x20)) { 4400 tcg_temp_free(len); 4401 } 4402 if (!(ext & 0x800)) { 4403 tcg_temp_free(ofs); 4404 } 4405 } 4406 4407 DISAS_INSN(ff1) 4408 { 4409 TCGv reg; 4410 reg = DREG(insn, 0); 4411 gen_logic_cc(s, reg, OS_LONG); 4412 gen_helper_ff1(reg, reg); 4413 } 4414 4415 DISAS_INSN(chk) 4416 { 4417 TCGv src, reg; 4418 int opsize; 4419 4420 switch ((insn >> 7) & 3) { 4421 case 3: 4422 opsize = OS_WORD; 4423 break; 4424 case 2: 4425 if (m68k_feature(env, M68K_FEATURE_CHK2)) { 4426 opsize = OS_LONG; 4427 break; 4428 } 4429 /* fallthru */ 4430 default: 4431 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL); 4432 return; 4433 } 4434 SRC_EA(env, src, opsize, 1, NULL); 4435 reg = gen_extend(s, DREG(insn, 9), opsize, 1); 4436 4437 gen_flush_flags(s); 4438 gen_helper_chk(cpu_env, reg, src); 4439 } 4440 4441 DISAS_INSN(chk2) 4442 { 4443 uint16_t ext; 4444 TCGv addr1, addr2, bound1, bound2, reg; 4445 int opsize; 4446 4447 switch ((insn >> 9) & 3) { 4448 case 0: 4449 opsize = OS_BYTE; 4450 break; 4451 case 1: 4452 opsize = OS_WORD; 4453 break; 4454 case 2: 4455 opsize = OS_LONG; 4456 break; 4457 default: 4458 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL); 4459 return; 4460 } 4461 4462 ext = read_im16(env, s); 4463 if ((ext & 0x0800) == 0) { 4464 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL); 4465 return; 4466 } 4467 4468 addr1 = gen_lea(env, s, insn, OS_UNSIZED); 4469 addr2 = tcg_temp_new(); 4470 tcg_gen_addi_i32(addr2, addr1, opsize_bytes(opsize)); 4471 4472 bound1 = gen_load(s, opsize, addr1, 1, IS_USER(s)); 4473 tcg_temp_free(addr1); 4474 bound2 = gen_load(s, opsize, addr2, 1, IS_USER(s)); 4475 tcg_temp_free(addr2); 4476 4477 reg = tcg_temp_new(); 4478 if (ext & 0x8000) { 4479 tcg_gen_mov_i32(reg, AREG(ext, 12)); 4480 } else { 4481 gen_ext(reg, DREG(ext, 12), opsize, 1); 4482 } 4483 4484 gen_flush_flags(s); 4485 gen_helper_chk2(cpu_env, reg, bound1, bound2); 4486 tcg_temp_free(reg); 4487 tcg_temp_free(bound1); 4488 tcg_temp_free(bound2); 4489 } 4490 4491 static void m68k_copy_line(TCGv dst, TCGv src, int index) 4492 { 4493 TCGv addr; 4494 TCGv_i64 t0, t1; 4495 4496 addr = tcg_temp_new(); 4497 4498 t0 = tcg_temp_new_i64(); 4499 t1 = tcg_temp_new_i64(); 4500 4501 tcg_gen_andi_i32(addr, src, ~15); 4502 tcg_gen_qemu_ld64(t0, addr, index); 4503 tcg_gen_addi_i32(addr, addr, 8); 4504 tcg_gen_qemu_ld64(t1, addr, index); 4505 4506 tcg_gen_andi_i32(addr, dst, ~15); 4507 tcg_gen_qemu_st64(t0, addr, index); 4508 tcg_gen_addi_i32(addr, addr, 8); 4509 tcg_gen_qemu_st64(t1, addr, index); 4510 4511 tcg_temp_free_i64(t0); 4512 tcg_temp_free_i64(t1); 4513 tcg_temp_free(addr); 4514 } 4515 4516 DISAS_INSN(move16_reg) 4517 { 4518 int index = IS_USER(s); 4519 TCGv tmp; 4520 uint16_t ext; 4521 4522 ext = read_im16(env, s); 4523 if ((ext & (1 << 15)) == 0) { 4524 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL); 4525 } 4526 4527 m68k_copy_line(AREG(ext, 12), AREG(insn, 0), index); 4528 4529 /* Ax can be Ay, so save Ay before incrementing Ax */ 4530 tmp = tcg_temp_new(); 4531 tcg_gen_mov_i32(tmp, AREG(ext, 12)); 4532 tcg_gen_addi_i32(AREG(insn, 0), AREG(insn, 0), 16); 4533 tcg_gen_addi_i32(AREG(ext, 12), tmp, 16); 4534 tcg_temp_free(tmp); 4535 } 4536 4537 DISAS_INSN(move16_mem) 4538 { 4539 int index = IS_USER(s); 4540 TCGv reg, addr; 4541 4542 reg = AREG(insn, 0); 4543 addr = tcg_const_i32(read_im32(env, s)); 4544 4545 if ((insn >> 3) & 1) { 4546 /* MOVE16 (xxx).L, (Ay) */ 4547 m68k_copy_line(reg, addr, index); 4548 } else { 4549 /* MOVE16 (Ay), (xxx).L */ 4550 m68k_copy_line(addr, reg, index); 4551 } 4552 4553 tcg_temp_free(addr); 4554 4555 if (((insn >> 3) & 2) == 0) { 4556 /* (Ay)+ */ 4557 tcg_gen_addi_i32(reg, reg, 16); 4558 } 4559 } 4560 4561 DISAS_INSN(strldsr) 4562 { 4563 uint16_t ext; 4564 uint32_t addr; 4565 4566 addr = s->pc - 2; 4567 ext = read_im16(env, s); 4568 if (ext != 0x46FC) { 4569 gen_exception(s, addr, EXCP_ILLEGAL); 4570 return; 4571 } 4572 ext = read_im16(env, s); 4573 if (IS_USER(s) || (ext & SR_S) == 0) { 4574 gen_exception(s, addr, EXCP_PRIVILEGE); 4575 return; 4576 } 4577 gen_push(s, gen_get_sr(s)); 4578 gen_set_sr_im(s, ext, 0); 4579 } 4580 4581 DISAS_INSN(move_from_sr) 4582 { 4583 TCGv sr; 4584 4585 if (IS_USER(s) && !m68k_feature(env, M68K_FEATURE_M68000)) { 4586 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4587 return; 4588 } 4589 sr = gen_get_sr(s); 4590 DEST_EA(env, insn, OS_WORD, sr, NULL); 4591 } 4592 4593 #if defined(CONFIG_SOFTMMU) 4594 DISAS_INSN(moves) 4595 { 4596 int opsize; 4597 uint16_t ext; 4598 TCGv reg; 4599 TCGv addr; 4600 int extend; 4601 4602 if (IS_USER(s)) { 4603 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4604 return; 4605 } 4606 4607 ext = read_im16(env, s); 4608 4609 opsize = insn_opsize(insn); 4610 4611 if (ext & 0x8000) { 4612 /* address register */ 4613 reg = AREG(ext, 12); 4614 extend = 1; 4615 } else { 4616 /* data register */ 4617 reg = DREG(ext, 12); 4618 extend = 0; 4619 } 4620 4621 addr = gen_lea(env, s, insn, opsize); 4622 if (IS_NULL_QREG(addr)) { 4623 gen_addr_fault(s); 4624 return; 4625 } 4626 4627 if (ext & 0x0800) { 4628 /* from reg to ea */ 4629 gen_store(s, opsize, addr, reg, DFC_INDEX(s)); 4630 } else { 4631 /* from ea to reg */ 4632 TCGv tmp = gen_load(s, opsize, addr, 0, SFC_INDEX(s)); 4633 if (extend) { 4634 gen_ext(reg, tmp, opsize, 1); 4635 } else { 4636 gen_partset_reg(opsize, reg, tmp); 4637 } 4638 tcg_temp_free(tmp); 4639 } 4640 switch (extract32(insn, 3, 3)) { 4641 case 3: /* Indirect postincrement. */ 4642 tcg_gen_addi_i32(AREG(insn, 0), addr, 4643 REG(insn, 0) == 7 && opsize == OS_BYTE 4644 ? 2 4645 : opsize_bytes(opsize)); 4646 break; 4647 case 4: /* Indirect predecrememnt. */ 4648 tcg_gen_mov_i32(AREG(insn, 0), addr); 4649 break; 4650 } 4651 } 4652 4653 DISAS_INSN(move_to_sr) 4654 { 4655 if (IS_USER(s)) { 4656 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4657 return; 4658 } 4659 gen_move_to_sr(env, s, insn, false); 4660 gen_exit_tb(s); 4661 } 4662 4663 DISAS_INSN(move_from_usp) 4664 { 4665 if (IS_USER(s)) { 4666 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4667 return; 4668 } 4669 tcg_gen_ld_i32(AREG(insn, 0), cpu_env, 4670 offsetof(CPUM68KState, sp[M68K_USP])); 4671 } 4672 4673 DISAS_INSN(move_to_usp) 4674 { 4675 if (IS_USER(s)) { 4676 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4677 return; 4678 } 4679 tcg_gen_st_i32(AREG(insn, 0), cpu_env, 4680 offsetof(CPUM68KState, sp[M68K_USP])); 4681 } 4682 4683 DISAS_INSN(halt) 4684 { 4685 if (IS_USER(s)) { 4686 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4687 return; 4688 } 4689 4690 gen_exception(s, s->pc, EXCP_HALT_INSN); 4691 } 4692 4693 DISAS_INSN(stop) 4694 { 4695 uint16_t ext; 4696 4697 if (IS_USER(s)) { 4698 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4699 return; 4700 } 4701 4702 ext = read_im16(env, s); 4703 4704 gen_set_sr_im(s, ext, 0); 4705 tcg_gen_movi_i32(cpu_halted, 1); 4706 gen_exception(s, s->pc, EXCP_HLT); 4707 } 4708 4709 DISAS_INSN(rte) 4710 { 4711 if (IS_USER(s)) { 4712 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4713 return; 4714 } 4715 gen_exception(s, s->base.pc_next, EXCP_RTE); 4716 } 4717 4718 DISAS_INSN(cf_movec) 4719 { 4720 uint16_t ext; 4721 TCGv reg; 4722 4723 if (IS_USER(s)) { 4724 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4725 return; 4726 } 4727 4728 ext = read_im16(env, s); 4729 4730 if (ext & 0x8000) { 4731 reg = AREG(ext, 12); 4732 } else { 4733 reg = DREG(ext, 12); 4734 } 4735 gen_helper_cf_movec_to(cpu_env, tcg_const_i32(ext & 0xfff), reg); 4736 gen_exit_tb(s); 4737 } 4738 4739 DISAS_INSN(m68k_movec) 4740 { 4741 uint16_t ext; 4742 TCGv reg; 4743 4744 if (IS_USER(s)) { 4745 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4746 return; 4747 } 4748 4749 ext = read_im16(env, s); 4750 4751 if (ext & 0x8000) { 4752 reg = AREG(ext, 12); 4753 } else { 4754 reg = DREG(ext, 12); 4755 } 4756 if (insn & 1) { 4757 gen_helper_m68k_movec_to(cpu_env, tcg_const_i32(ext & 0xfff), reg); 4758 } else { 4759 gen_helper_m68k_movec_from(reg, cpu_env, tcg_const_i32(ext & 0xfff)); 4760 } 4761 gen_exit_tb(s); 4762 } 4763 4764 DISAS_INSN(intouch) 4765 { 4766 if (IS_USER(s)) { 4767 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4768 return; 4769 } 4770 /* ICache fetch. Implement as no-op. */ 4771 } 4772 4773 DISAS_INSN(cpushl) 4774 { 4775 if (IS_USER(s)) { 4776 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4777 return; 4778 } 4779 /* Cache push/invalidate. Implement as no-op. */ 4780 } 4781 4782 DISAS_INSN(cpush) 4783 { 4784 if (IS_USER(s)) { 4785 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4786 return; 4787 } 4788 /* Cache push/invalidate. Implement as no-op. */ 4789 } 4790 4791 DISAS_INSN(cinv) 4792 { 4793 if (IS_USER(s)) { 4794 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4795 return; 4796 } 4797 /* Invalidate cache line. Implement as no-op. */ 4798 } 4799 4800 #if defined(CONFIG_SOFTMMU) 4801 DISAS_INSN(pflush) 4802 { 4803 TCGv opmode; 4804 4805 if (IS_USER(s)) { 4806 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4807 return; 4808 } 4809 4810 opmode = tcg_const_i32((insn >> 3) & 3); 4811 gen_helper_pflush(cpu_env, AREG(insn, 0), opmode); 4812 tcg_temp_free(opmode); 4813 } 4814 4815 DISAS_INSN(ptest) 4816 { 4817 TCGv is_read; 4818 4819 if (IS_USER(s)) { 4820 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4821 return; 4822 } 4823 is_read = tcg_const_i32((insn >> 5) & 1); 4824 gen_helper_ptest(cpu_env, AREG(insn, 0), is_read); 4825 tcg_temp_free(is_read); 4826 } 4827 #endif 4828 4829 DISAS_INSN(wddata) 4830 { 4831 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4832 } 4833 4834 DISAS_INSN(wdebug) 4835 { 4836 if (IS_USER(s)) { 4837 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 4838 return; 4839 } 4840 /* TODO: Implement wdebug. */ 4841 cpu_abort(env_cpu(env), "WDEBUG not implemented"); 4842 } 4843 #endif 4844 4845 DISAS_INSN(trap) 4846 { 4847 gen_exception(s, s->base.pc_next, EXCP_TRAP0 + (insn & 0xf)); 4848 } 4849 4850 static void gen_load_fcr(DisasContext *s, TCGv res, int reg) 4851 { 4852 switch (reg) { 4853 case M68K_FPIAR: 4854 tcg_gen_movi_i32(res, 0); 4855 break; 4856 case M68K_FPSR: 4857 tcg_gen_ld_i32(res, cpu_env, offsetof(CPUM68KState, fpsr)); 4858 break; 4859 case M68K_FPCR: 4860 tcg_gen_ld_i32(res, cpu_env, offsetof(CPUM68KState, fpcr)); 4861 break; 4862 } 4863 } 4864 4865 static void gen_store_fcr(DisasContext *s, TCGv val, int reg) 4866 { 4867 switch (reg) { 4868 case M68K_FPIAR: 4869 break; 4870 case M68K_FPSR: 4871 tcg_gen_st_i32(val, cpu_env, offsetof(CPUM68KState, fpsr)); 4872 break; 4873 case M68K_FPCR: 4874 gen_helper_set_fpcr(cpu_env, val); 4875 break; 4876 } 4877 } 4878 4879 static void gen_qemu_store_fcr(DisasContext *s, TCGv addr, int reg) 4880 { 4881 int index = IS_USER(s); 4882 TCGv tmp; 4883 4884 tmp = tcg_temp_new(); 4885 gen_load_fcr(s, tmp, reg); 4886 tcg_gen_qemu_st32(tmp, addr, index); 4887 tcg_temp_free(tmp); 4888 } 4889 4890 static void gen_qemu_load_fcr(DisasContext *s, TCGv addr, int reg) 4891 { 4892 int index = IS_USER(s); 4893 TCGv tmp; 4894 4895 tmp = tcg_temp_new(); 4896 tcg_gen_qemu_ld32u(tmp, addr, index); 4897 gen_store_fcr(s, tmp, reg); 4898 tcg_temp_free(tmp); 4899 } 4900 4901 4902 static void gen_op_fmove_fcr(CPUM68KState *env, DisasContext *s, 4903 uint32_t insn, uint32_t ext) 4904 { 4905 int mask = (ext >> 10) & 7; 4906 int is_write = (ext >> 13) & 1; 4907 int mode = extract32(insn, 3, 3); 4908 int i; 4909 TCGv addr, tmp; 4910 4911 switch (mode) { 4912 case 0: /* Dn */ 4913 if (mask != M68K_FPIAR && mask != M68K_FPSR && mask != M68K_FPCR) { 4914 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL); 4915 return; 4916 } 4917 if (is_write) { 4918 gen_load_fcr(s, DREG(insn, 0), mask); 4919 } else { 4920 gen_store_fcr(s, DREG(insn, 0), mask); 4921 } 4922 return; 4923 case 1: /* An, only with FPIAR */ 4924 if (mask != M68K_FPIAR) { 4925 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL); 4926 return; 4927 } 4928 if (is_write) { 4929 gen_load_fcr(s, AREG(insn, 0), mask); 4930 } else { 4931 gen_store_fcr(s, AREG(insn, 0), mask); 4932 } 4933 return; 4934 default: 4935 break; 4936 } 4937 4938 tmp = gen_lea(env, s, insn, OS_LONG); 4939 if (IS_NULL_QREG(tmp)) { 4940 gen_addr_fault(s); 4941 return; 4942 } 4943 4944 addr = tcg_temp_new(); 4945 tcg_gen_mov_i32(addr, tmp); 4946 4947 /* 4948 * mask: 4949 * 4950 * 0b100 Floating-Point Control Register 4951 * 0b010 Floating-Point Status Register 4952 * 0b001 Floating-Point Instruction Address Register 4953 * 4954 */ 4955 4956 if (is_write && mode == 4) { 4957 for (i = 2; i >= 0; i--, mask >>= 1) { 4958 if (mask & 1) { 4959 gen_qemu_store_fcr(s, addr, 1 << i); 4960 if (mask != 1) { 4961 tcg_gen_subi_i32(addr, addr, opsize_bytes(OS_LONG)); 4962 } 4963 } 4964 } 4965 tcg_gen_mov_i32(AREG(insn, 0), addr); 4966 } else { 4967 for (i = 0; i < 3; i++, mask >>= 1) { 4968 if (mask & 1) { 4969 if (is_write) { 4970 gen_qemu_store_fcr(s, addr, 1 << i); 4971 } else { 4972 gen_qemu_load_fcr(s, addr, 1 << i); 4973 } 4974 if (mask != 1 || mode == 3) { 4975 tcg_gen_addi_i32(addr, addr, opsize_bytes(OS_LONG)); 4976 } 4977 } 4978 } 4979 if (mode == 3) { 4980 tcg_gen_mov_i32(AREG(insn, 0), addr); 4981 } 4982 } 4983 tcg_temp_free_i32(addr); 4984 } 4985 4986 static void gen_op_fmovem(CPUM68KState *env, DisasContext *s, 4987 uint32_t insn, uint32_t ext) 4988 { 4989 int opsize; 4990 TCGv addr, tmp; 4991 int mode = (ext >> 11) & 0x3; 4992 int is_load = ((ext & 0x2000) == 0); 4993 4994 if (m68k_feature(s->env, M68K_FEATURE_FPU)) { 4995 opsize = OS_EXTENDED; 4996 } else { 4997 opsize = OS_DOUBLE; /* FIXME */ 4998 } 4999 5000 addr = gen_lea(env, s, insn, opsize); 5001 if (IS_NULL_QREG(addr)) { 5002 gen_addr_fault(s); 5003 return; 5004 } 5005 5006 tmp = tcg_temp_new(); 5007 if (mode & 0x1) { 5008 /* Dynamic register list */ 5009 tcg_gen_ext8u_i32(tmp, DREG(ext, 4)); 5010 } else { 5011 /* Static register list */ 5012 tcg_gen_movi_i32(tmp, ext & 0xff); 5013 } 5014 5015 if (!is_load && (mode & 2) == 0) { 5016 /* 5017 * predecrement addressing mode 5018 * only available to store register to memory 5019 */ 5020 if (opsize == OS_EXTENDED) { 5021 gen_helper_fmovemx_st_predec(tmp, cpu_env, addr, tmp); 5022 } else { 5023 gen_helper_fmovemd_st_predec(tmp, cpu_env, addr, tmp); 5024 } 5025 } else { 5026 /* postincrement addressing mode */ 5027 if (opsize == OS_EXTENDED) { 5028 if (is_load) { 5029 gen_helper_fmovemx_ld_postinc(tmp, cpu_env, addr, tmp); 5030 } else { 5031 gen_helper_fmovemx_st_postinc(tmp, cpu_env, addr, tmp); 5032 } 5033 } else { 5034 if (is_load) { 5035 gen_helper_fmovemd_ld_postinc(tmp, cpu_env, addr, tmp); 5036 } else { 5037 gen_helper_fmovemd_st_postinc(tmp, cpu_env, addr, tmp); 5038 } 5039 } 5040 } 5041 if ((insn & 070) == 030 || (insn & 070) == 040) { 5042 tcg_gen_mov_i32(AREG(insn, 0), tmp); 5043 } 5044 tcg_temp_free(tmp); 5045 } 5046 5047 /* 5048 * ??? FP exceptions are not implemented. Most exceptions are deferred until 5049 * immediately before the next FP instruction is executed. 5050 */ 5051 DISAS_INSN(fpu) 5052 { 5053 uint16_t ext; 5054 int opmode; 5055 int opsize; 5056 TCGv_ptr cpu_src, cpu_dest; 5057 5058 ext = read_im16(env, s); 5059 opmode = ext & 0x7f; 5060 switch ((ext >> 13) & 7) { 5061 case 0: 5062 break; 5063 case 1: 5064 goto undef; 5065 case 2: 5066 if (insn == 0xf200 && (ext & 0xfc00) == 0x5c00) { 5067 /* fmovecr */ 5068 TCGv rom_offset = tcg_const_i32(opmode); 5069 cpu_dest = gen_fp_ptr(REG(ext, 7)); 5070 gen_helper_fconst(cpu_env, cpu_dest, rom_offset); 5071 tcg_temp_free_ptr(cpu_dest); 5072 tcg_temp_free(rom_offset); 5073 return; 5074 } 5075 break; 5076 case 3: /* fmove out */ 5077 cpu_src = gen_fp_ptr(REG(ext, 7)); 5078 opsize = ext_opsize(ext, 10); 5079 if (gen_ea_fp(env, s, insn, opsize, cpu_src, 5080 EA_STORE, IS_USER(s)) == -1) { 5081 gen_addr_fault(s); 5082 } 5083 gen_helper_ftst(cpu_env, cpu_src); 5084 tcg_temp_free_ptr(cpu_src); 5085 return; 5086 case 4: /* fmove to control register. */ 5087 case 5: /* fmove from control register. */ 5088 gen_op_fmove_fcr(env, s, insn, ext); 5089 return; 5090 case 6: /* fmovem */ 5091 case 7: 5092 if ((ext & 0x1000) == 0 && !m68k_feature(s->env, M68K_FEATURE_FPU)) { 5093 goto undef; 5094 } 5095 gen_op_fmovem(env, s, insn, ext); 5096 return; 5097 } 5098 if (ext & (1 << 14)) { 5099 /* Source effective address. */ 5100 opsize = ext_opsize(ext, 10); 5101 cpu_src = gen_fp_result_ptr(); 5102 if (gen_ea_fp(env, s, insn, opsize, cpu_src, 5103 EA_LOADS, IS_USER(s)) == -1) { 5104 gen_addr_fault(s); 5105 return; 5106 } 5107 } else { 5108 /* Source register. */ 5109 opsize = OS_EXTENDED; 5110 cpu_src = gen_fp_ptr(REG(ext, 10)); 5111 } 5112 cpu_dest = gen_fp_ptr(REG(ext, 7)); 5113 switch (opmode) { 5114 case 0: /* fmove */ 5115 gen_fp_move(cpu_dest, cpu_src); 5116 break; 5117 case 0x40: /* fsmove */ 5118 gen_helper_fsround(cpu_env, cpu_dest, cpu_src); 5119 break; 5120 case 0x44: /* fdmove */ 5121 gen_helper_fdround(cpu_env, cpu_dest, cpu_src); 5122 break; 5123 case 1: /* fint */ 5124 gen_helper_firound(cpu_env, cpu_dest, cpu_src); 5125 break; 5126 case 2: /* fsinh */ 5127 gen_helper_fsinh(cpu_env, cpu_dest, cpu_src); 5128 break; 5129 case 3: /* fintrz */ 5130 gen_helper_fitrunc(cpu_env, cpu_dest, cpu_src); 5131 break; 5132 case 4: /* fsqrt */ 5133 gen_helper_fsqrt(cpu_env, cpu_dest, cpu_src); 5134 break; 5135 case 0x41: /* fssqrt */ 5136 gen_helper_fssqrt(cpu_env, cpu_dest, cpu_src); 5137 break; 5138 case 0x45: /* fdsqrt */ 5139 gen_helper_fdsqrt(cpu_env, cpu_dest, cpu_src); 5140 break; 5141 case 0x06: /* flognp1 */ 5142 gen_helper_flognp1(cpu_env, cpu_dest, cpu_src); 5143 break; 5144 case 0x09: /* ftanh */ 5145 gen_helper_ftanh(cpu_env, cpu_dest, cpu_src); 5146 break; 5147 case 0x0a: /* fatan */ 5148 gen_helper_fatan(cpu_env, cpu_dest, cpu_src); 5149 break; 5150 case 0x0c: /* fasin */ 5151 gen_helper_fasin(cpu_env, cpu_dest, cpu_src); 5152 break; 5153 case 0x0d: /* fatanh */ 5154 gen_helper_fatanh(cpu_env, cpu_dest, cpu_src); 5155 break; 5156 case 0x0e: /* fsin */ 5157 gen_helper_fsin(cpu_env, cpu_dest, cpu_src); 5158 break; 5159 case 0x0f: /* ftan */ 5160 gen_helper_ftan(cpu_env, cpu_dest, cpu_src); 5161 break; 5162 case 0x10: /* fetox */ 5163 gen_helper_fetox(cpu_env, cpu_dest, cpu_src); 5164 break; 5165 case 0x11: /* ftwotox */ 5166 gen_helper_ftwotox(cpu_env, cpu_dest, cpu_src); 5167 break; 5168 case 0x12: /* ftentox */ 5169 gen_helper_ftentox(cpu_env, cpu_dest, cpu_src); 5170 break; 5171 case 0x14: /* flogn */ 5172 gen_helper_flogn(cpu_env, cpu_dest, cpu_src); 5173 break; 5174 case 0x15: /* flog10 */ 5175 gen_helper_flog10(cpu_env, cpu_dest, cpu_src); 5176 break; 5177 case 0x16: /* flog2 */ 5178 gen_helper_flog2(cpu_env, cpu_dest, cpu_src); 5179 break; 5180 case 0x18: /* fabs */ 5181 gen_helper_fabs(cpu_env, cpu_dest, cpu_src); 5182 break; 5183 case 0x58: /* fsabs */ 5184 gen_helper_fsabs(cpu_env, cpu_dest, cpu_src); 5185 break; 5186 case 0x5c: /* fdabs */ 5187 gen_helper_fdabs(cpu_env, cpu_dest, cpu_src); 5188 break; 5189 case 0x19: /* fcosh */ 5190 gen_helper_fcosh(cpu_env, cpu_dest, cpu_src); 5191 break; 5192 case 0x1a: /* fneg */ 5193 gen_helper_fneg(cpu_env, cpu_dest, cpu_src); 5194 break; 5195 case 0x5a: /* fsneg */ 5196 gen_helper_fsneg(cpu_env, cpu_dest, cpu_src); 5197 break; 5198 case 0x5e: /* fdneg */ 5199 gen_helper_fdneg(cpu_env, cpu_dest, cpu_src); 5200 break; 5201 case 0x1c: /* facos */ 5202 gen_helper_facos(cpu_env, cpu_dest, cpu_src); 5203 break; 5204 case 0x1d: /* fcos */ 5205 gen_helper_fcos(cpu_env, cpu_dest, cpu_src); 5206 break; 5207 case 0x1e: /* fgetexp */ 5208 gen_helper_fgetexp(cpu_env, cpu_dest, cpu_src); 5209 break; 5210 case 0x1f: /* fgetman */ 5211 gen_helper_fgetman(cpu_env, cpu_dest, cpu_src); 5212 break; 5213 case 0x20: /* fdiv */ 5214 gen_helper_fdiv(cpu_env, cpu_dest, cpu_src, cpu_dest); 5215 break; 5216 case 0x60: /* fsdiv */ 5217 gen_helper_fsdiv(cpu_env, cpu_dest, cpu_src, cpu_dest); 5218 break; 5219 case 0x64: /* fddiv */ 5220 gen_helper_fddiv(cpu_env, cpu_dest, cpu_src, cpu_dest); 5221 break; 5222 case 0x21: /* fmod */ 5223 gen_helper_fmod(cpu_env, cpu_dest, cpu_src, cpu_dest); 5224 break; 5225 case 0x22: /* fadd */ 5226 gen_helper_fadd(cpu_env, cpu_dest, cpu_src, cpu_dest); 5227 break; 5228 case 0x62: /* fsadd */ 5229 gen_helper_fsadd(cpu_env, cpu_dest, cpu_src, cpu_dest); 5230 break; 5231 case 0x66: /* fdadd */ 5232 gen_helper_fdadd(cpu_env, cpu_dest, cpu_src, cpu_dest); 5233 break; 5234 case 0x23: /* fmul */ 5235 gen_helper_fmul(cpu_env, cpu_dest, cpu_src, cpu_dest); 5236 break; 5237 case 0x63: /* fsmul */ 5238 gen_helper_fsmul(cpu_env, cpu_dest, cpu_src, cpu_dest); 5239 break; 5240 case 0x67: /* fdmul */ 5241 gen_helper_fdmul(cpu_env, cpu_dest, cpu_src, cpu_dest); 5242 break; 5243 case 0x24: /* fsgldiv */ 5244 gen_helper_fsgldiv(cpu_env, cpu_dest, cpu_src, cpu_dest); 5245 break; 5246 case 0x25: /* frem */ 5247 gen_helper_frem(cpu_env, cpu_dest, cpu_src, cpu_dest); 5248 break; 5249 case 0x26: /* fscale */ 5250 gen_helper_fscale(cpu_env, cpu_dest, cpu_src, cpu_dest); 5251 break; 5252 case 0x27: /* fsglmul */ 5253 gen_helper_fsglmul(cpu_env, cpu_dest, cpu_src, cpu_dest); 5254 break; 5255 case 0x28: /* fsub */ 5256 gen_helper_fsub(cpu_env, cpu_dest, cpu_src, cpu_dest); 5257 break; 5258 case 0x68: /* fssub */ 5259 gen_helper_fssub(cpu_env, cpu_dest, cpu_src, cpu_dest); 5260 break; 5261 case 0x6c: /* fdsub */ 5262 gen_helper_fdsub(cpu_env, cpu_dest, cpu_src, cpu_dest); 5263 break; 5264 case 0x30: case 0x31: case 0x32: 5265 case 0x33: case 0x34: case 0x35: 5266 case 0x36: case 0x37: { 5267 TCGv_ptr cpu_dest2 = gen_fp_ptr(REG(ext, 0)); 5268 gen_helper_fsincos(cpu_env, cpu_dest, cpu_dest2, cpu_src); 5269 tcg_temp_free_ptr(cpu_dest2); 5270 } 5271 break; 5272 case 0x38: /* fcmp */ 5273 gen_helper_fcmp(cpu_env, cpu_src, cpu_dest); 5274 return; 5275 case 0x3a: /* ftst */ 5276 gen_helper_ftst(cpu_env, cpu_src); 5277 return; 5278 default: 5279 goto undef; 5280 } 5281 tcg_temp_free_ptr(cpu_src); 5282 gen_helper_ftst(cpu_env, cpu_dest); 5283 tcg_temp_free_ptr(cpu_dest); 5284 return; 5285 undef: 5286 /* FIXME: Is this right for offset addressing modes? */ 5287 s->pc -= 2; 5288 disas_undef_fpu(env, s, insn); 5289 } 5290 5291 static void gen_fcc_cond(DisasCompare *c, DisasContext *s, int cond) 5292 { 5293 TCGv fpsr; 5294 5295 c->g1 = 1; 5296 c->v2 = tcg_const_i32(0); 5297 c->g2 = 0; 5298 /* TODO: Raise BSUN exception. */ 5299 fpsr = tcg_temp_new(); 5300 gen_load_fcr(s, fpsr, M68K_FPSR); 5301 switch (cond) { 5302 case 0: /* False */ 5303 case 16: /* Signaling False */ 5304 c->v1 = c->v2; 5305 c->tcond = TCG_COND_NEVER; 5306 break; 5307 case 1: /* EQual Z */ 5308 case 17: /* Signaling EQual Z */ 5309 c->v1 = tcg_temp_new(); 5310 c->g1 = 0; 5311 tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z); 5312 c->tcond = TCG_COND_NE; 5313 break; 5314 case 2: /* Ordered Greater Than !(A || Z || N) */ 5315 case 18: /* Greater Than !(A || Z || N) */ 5316 c->v1 = tcg_temp_new(); 5317 c->g1 = 0; 5318 tcg_gen_andi_i32(c->v1, fpsr, 5319 FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N); 5320 c->tcond = TCG_COND_EQ; 5321 break; 5322 case 3: /* Ordered Greater than or Equal Z || !(A || N) */ 5323 case 19: /* Greater than or Equal Z || !(A || N) */ 5324 c->v1 = tcg_temp_new(); 5325 c->g1 = 0; 5326 tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A); 5327 tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_A)); 5328 tcg_gen_andi_i32(fpsr, fpsr, FPSR_CC_Z | FPSR_CC_N); 5329 tcg_gen_or_i32(c->v1, c->v1, fpsr); 5330 tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N); 5331 c->tcond = TCG_COND_NE; 5332 break; 5333 case 4: /* Ordered Less Than !(!N || A || Z); */ 5334 case 20: /* Less Than !(!N || A || Z); */ 5335 c->v1 = tcg_temp_new(); 5336 c->g1 = 0; 5337 tcg_gen_xori_i32(c->v1, fpsr, FPSR_CC_N); 5338 tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_N | FPSR_CC_A | FPSR_CC_Z); 5339 c->tcond = TCG_COND_EQ; 5340 break; 5341 case 5: /* Ordered Less than or Equal Z || (N && !A) */ 5342 case 21: /* Less than or Equal Z || (N && !A) */ 5343 c->v1 = tcg_temp_new(); 5344 c->g1 = 0; 5345 tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A); 5346 tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_A)); 5347 tcg_gen_andc_i32(c->v1, fpsr, c->v1); 5348 tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_Z | FPSR_CC_N); 5349 c->tcond = TCG_COND_NE; 5350 break; 5351 case 6: /* Ordered Greater or Less than !(A || Z) */ 5352 case 22: /* Greater or Less than !(A || Z) */ 5353 c->v1 = tcg_temp_new(); 5354 c->g1 = 0; 5355 tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z); 5356 c->tcond = TCG_COND_EQ; 5357 break; 5358 case 7: /* Ordered !A */ 5359 case 23: /* Greater, Less or Equal !A */ 5360 c->v1 = tcg_temp_new(); 5361 c->g1 = 0; 5362 tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A); 5363 c->tcond = TCG_COND_EQ; 5364 break; 5365 case 8: /* Unordered A */ 5366 case 24: /* Not Greater, Less or Equal A */ 5367 c->v1 = tcg_temp_new(); 5368 c->g1 = 0; 5369 tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A); 5370 c->tcond = TCG_COND_NE; 5371 break; 5372 case 9: /* Unordered or Equal A || Z */ 5373 case 25: /* Not Greater or Less then A || Z */ 5374 c->v1 = tcg_temp_new(); 5375 c->g1 = 0; 5376 tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z); 5377 c->tcond = TCG_COND_NE; 5378 break; 5379 case 10: /* Unordered or Greater Than A || !(N || Z)) */ 5380 case 26: /* Not Less or Equal A || !(N || Z)) */ 5381 c->v1 = tcg_temp_new(); 5382 c->g1 = 0; 5383 tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z); 5384 tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_Z)); 5385 tcg_gen_andi_i32(fpsr, fpsr, FPSR_CC_A | FPSR_CC_N); 5386 tcg_gen_or_i32(c->v1, c->v1, fpsr); 5387 tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N); 5388 c->tcond = TCG_COND_NE; 5389 break; 5390 case 11: /* Unordered or Greater or Equal A || Z || !N */ 5391 case 27: /* Not Less Than A || Z || !N */ 5392 c->v1 = tcg_temp_new(); 5393 c->g1 = 0; 5394 tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N); 5395 tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N); 5396 c->tcond = TCG_COND_NE; 5397 break; 5398 case 12: /* Unordered or Less Than A || (N && !Z) */ 5399 case 28: /* Not Greater than or Equal A || (N && !Z) */ 5400 c->v1 = tcg_temp_new(); 5401 c->g1 = 0; 5402 tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z); 5403 tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_Z)); 5404 tcg_gen_andc_i32(c->v1, fpsr, c->v1); 5405 tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_A | FPSR_CC_N); 5406 c->tcond = TCG_COND_NE; 5407 break; 5408 case 13: /* Unordered or Less or Equal A || Z || N */ 5409 case 29: /* Not Greater Than A || Z || N */ 5410 c->v1 = tcg_temp_new(); 5411 c->g1 = 0; 5412 tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N); 5413 c->tcond = TCG_COND_NE; 5414 break; 5415 case 14: /* Not Equal !Z */ 5416 case 30: /* Signaling Not Equal !Z */ 5417 c->v1 = tcg_temp_new(); 5418 c->g1 = 0; 5419 tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z); 5420 c->tcond = TCG_COND_EQ; 5421 break; 5422 case 15: /* True */ 5423 case 31: /* Signaling True */ 5424 c->v1 = c->v2; 5425 c->tcond = TCG_COND_ALWAYS; 5426 break; 5427 } 5428 tcg_temp_free(fpsr); 5429 } 5430 5431 static void gen_fjmpcc(DisasContext *s, int cond, TCGLabel *l1) 5432 { 5433 DisasCompare c; 5434 5435 gen_fcc_cond(&c, s, cond); 5436 update_cc_op(s); 5437 tcg_gen_brcond_i32(c.tcond, c.v1, c.v2, l1); 5438 free_cond(&c); 5439 } 5440 5441 DISAS_INSN(fbcc) 5442 { 5443 uint32_t offset; 5444 uint32_t base; 5445 TCGLabel *l1; 5446 5447 base = s->pc; 5448 offset = (int16_t)read_im16(env, s); 5449 if (insn & (1 << 6)) { 5450 offset = (offset << 16) | read_im16(env, s); 5451 } 5452 5453 l1 = gen_new_label(); 5454 update_cc_op(s); 5455 gen_fjmpcc(s, insn & 0x3f, l1); 5456 gen_jmp_tb(s, 0, s->pc); 5457 gen_set_label(l1); 5458 gen_jmp_tb(s, 1, base + offset); 5459 } 5460 5461 DISAS_INSN(fscc) 5462 { 5463 DisasCompare c; 5464 int cond; 5465 TCGv tmp; 5466 uint16_t ext; 5467 5468 ext = read_im16(env, s); 5469 cond = ext & 0x3f; 5470 gen_fcc_cond(&c, s, cond); 5471 5472 tmp = tcg_temp_new(); 5473 tcg_gen_setcond_i32(c.tcond, tmp, c.v1, c.v2); 5474 free_cond(&c); 5475 5476 tcg_gen_neg_i32(tmp, tmp); 5477 DEST_EA(env, insn, OS_BYTE, tmp, NULL); 5478 tcg_temp_free(tmp); 5479 } 5480 5481 #if defined(CONFIG_SOFTMMU) 5482 DISAS_INSN(frestore) 5483 { 5484 TCGv addr; 5485 5486 if (IS_USER(s)) { 5487 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 5488 return; 5489 } 5490 if (m68k_feature(s->env, M68K_FEATURE_M68040)) { 5491 SRC_EA(env, addr, OS_LONG, 0, NULL); 5492 /* FIXME: check the state frame */ 5493 } else { 5494 disas_undef(env, s, insn); 5495 } 5496 } 5497 5498 DISAS_INSN(fsave) 5499 { 5500 if (IS_USER(s)) { 5501 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); 5502 return; 5503 } 5504 5505 if (m68k_feature(s->env, M68K_FEATURE_M68040)) { 5506 /* always write IDLE */ 5507 TCGv idle = tcg_const_i32(0x41000000); 5508 DEST_EA(env, insn, OS_LONG, idle, NULL); 5509 tcg_temp_free(idle); 5510 } else { 5511 disas_undef(env, s, insn); 5512 } 5513 } 5514 #endif 5515 5516 static inline TCGv gen_mac_extract_word(DisasContext *s, TCGv val, int upper) 5517 { 5518 TCGv tmp = tcg_temp_new(); 5519 if (s->env->macsr & MACSR_FI) { 5520 if (upper) 5521 tcg_gen_andi_i32(tmp, val, 0xffff0000); 5522 else 5523 tcg_gen_shli_i32(tmp, val, 16); 5524 } else if (s->env->macsr & MACSR_SU) { 5525 if (upper) 5526 tcg_gen_sari_i32(tmp, val, 16); 5527 else 5528 tcg_gen_ext16s_i32(tmp, val); 5529 } else { 5530 if (upper) 5531 tcg_gen_shri_i32(tmp, val, 16); 5532 else 5533 tcg_gen_ext16u_i32(tmp, val); 5534 } 5535 return tmp; 5536 } 5537 5538 static void gen_mac_clear_flags(void) 5539 { 5540 tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR, 5541 ~(MACSR_V | MACSR_Z | MACSR_N | MACSR_EV)); 5542 } 5543 5544 DISAS_INSN(mac) 5545 { 5546 TCGv rx; 5547 TCGv ry; 5548 uint16_t ext; 5549 int acc; 5550 TCGv tmp; 5551 TCGv addr; 5552 TCGv loadval; 5553 int dual; 5554 TCGv saved_flags; 5555 5556 if (!s->done_mac) { 5557 s->mactmp = tcg_temp_new_i64(); 5558 s->done_mac = 1; 5559 } 5560 5561 ext = read_im16(env, s); 5562 5563 acc = ((insn >> 7) & 1) | ((ext >> 3) & 2); 5564 dual = ((insn & 0x30) != 0 && (ext & 3) != 0); 5565 if (dual && !m68k_feature(s->env, M68K_FEATURE_CF_EMAC_B)) { 5566 disas_undef(env, s, insn); 5567 return; 5568 } 5569 if (insn & 0x30) { 5570 /* MAC with load. */ 5571 tmp = gen_lea(env, s, insn, OS_LONG); 5572 addr = tcg_temp_new(); 5573 tcg_gen_and_i32(addr, tmp, QREG_MAC_MASK); 5574 /* 5575 * Load the value now to ensure correct exception behavior. 5576 * Perform writeback after reading the MAC inputs. 5577 */ 5578 loadval = gen_load(s, OS_LONG, addr, 0, IS_USER(s)); 5579 5580 acc ^= 1; 5581 rx = (ext & 0x8000) ? AREG(ext, 12) : DREG(insn, 12); 5582 ry = (ext & 8) ? AREG(ext, 0) : DREG(ext, 0); 5583 } else { 5584 loadval = addr = NULL_QREG; 5585 rx = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9); 5586 ry = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0); 5587 } 5588 5589 gen_mac_clear_flags(); 5590 #if 0 5591 l1 = -1; 5592 /* Disabled because conditional branches clobber temporary vars. */ 5593 if ((s->env->macsr & MACSR_OMC) != 0 && !dual) { 5594 /* Skip the multiply if we know we will ignore it. */ 5595 l1 = gen_new_label(); 5596 tmp = tcg_temp_new(); 5597 tcg_gen_andi_i32(tmp, QREG_MACSR, 1 << (acc + 8)); 5598 gen_op_jmp_nz32(tmp, l1); 5599 } 5600 #endif 5601 5602 if ((ext & 0x0800) == 0) { 5603 /* Word. */ 5604 rx = gen_mac_extract_word(s, rx, (ext & 0x80) != 0); 5605 ry = gen_mac_extract_word(s, ry, (ext & 0x40) != 0); 5606 } 5607 if (s->env->macsr & MACSR_FI) { 5608 gen_helper_macmulf(s->mactmp, cpu_env, rx, ry); 5609 } else { 5610 if (s->env->macsr & MACSR_SU) 5611 gen_helper_macmuls(s->mactmp, cpu_env, rx, ry); 5612 else 5613 gen_helper_macmulu(s->mactmp, cpu_env, rx, ry); 5614 switch ((ext >> 9) & 3) { 5615 case 1: 5616 tcg_gen_shli_i64(s->mactmp, s->mactmp, 1); 5617 break; 5618 case 3: 5619 tcg_gen_shri_i64(s->mactmp, s->mactmp, 1); 5620 break; 5621 } 5622 } 5623 5624 if (dual) { 5625 /* Save the overflow flag from the multiply. */ 5626 saved_flags = tcg_temp_new(); 5627 tcg_gen_mov_i32(saved_flags, QREG_MACSR); 5628 } else { 5629 saved_flags = NULL_QREG; 5630 } 5631 5632 #if 0 5633 /* Disabled because conditional branches clobber temporary vars. */ 5634 if ((s->env->macsr & MACSR_OMC) != 0 && dual) { 5635 /* Skip the accumulate if the value is already saturated. */ 5636 l1 = gen_new_label(); 5637 tmp = tcg_temp_new(); 5638 gen_op_and32(tmp, QREG_MACSR, tcg_const_i32(MACSR_PAV0 << acc)); 5639 gen_op_jmp_nz32(tmp, l1); 5640 } 5641 #endif 5642 5643 if (insn & 0x100) 5644 tcg_gen_sub_i64(MACREG(acc), MACREG(acc), s->mactmp); 5645 else 5646 tcg_gen_add_i64(MACREG(acc), MACREG(acc), s->mactmp); 5647 5648 if (s->env->macsr & MACSR_FI) 5649 gen_helper_macsatf(cpu_env, tcg_const_i32(acc)); 5650 else if (s->env->macsr & MACSR_SU) 5651 gen_helper_macsats(cpu_env, tcg_const_i32(acc)); 5652 else 5653 gen_helper_macsatu(cpu_env, tcg_const_i32(acc)); 5654 5655 #if 0 5656 /* Disabled because conditional branches clobber temporary vars. */ 5657 if (l1 != -1) 5658 gen_set_label(l1); 5659 #endif 5660 5661 if (dual) { 5662 /* Dual accumulate variant. */ 5663 acc = (ext >> 2) & 3; 5664 /* Restore the overflow flag from the multiplier. */ 5665 tcg_gen_mov_i32(QREG_MACSR, saved_flags); 5666 #if 0 5667 /* Disabled because conditional branches clobber temporary vars. */ 5668 if ((s->env->macsr & MACSR_OMC) != 0) { 5669 /* Skip the accumulate if the value is already saturated. */ 5670 l1 = gen_new_label(); 5671 tmp = tcg_temp_new(); 5672 gen_op_and32(tmp, QREG_MACSR, tcg_const_i32(MACSR_PAV0 << acc)); 5673 gen_op_jmp_nz32(tmp, l1); 5674 } 5675 #endif 5676 if (ext & 2) 5677 tcg_gen_sub_i64(MACREG(acc), MACREG(acc), s->mactmp); 5678 else 5679 tcg_gen_add_i64(MACREG(acc), MACREG(acc), s->mactmp); 5680 if (s->env->macsr & MACSR_FI) 5681 gen_helper_macsatf(cpu_env, tcg_const_i32(acc)); 5682 else if (s->env->macsr & MACSR_SU) 5683 gen_helper_macsats(cpu_env, tcg_const_i32(acc)); 5684 else 5685 gen_helper_macsatu(cpu_env, tcg_const_i32(acc)); 5686 #if 0 5687 /* Disabled because conditional branches clobber temporary vars. */ 5688 if (l1 != -1) 5689 gen_set_label(l1); 5690 #endif 5691 } 5692 gen_helper_mac_set_flags(cpu_env, tcg_const_i32(acc)); 5693 5694 if (insn & 0x30) { 5695 TCGv rw; 5696 rw = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9); 5697 tcg_gen_mov_i32(rw, loadval); 5698 /* 5699 * FIXME: Should address writeback happen with the masked or 5700 * unmasked value? 5701 */ 5702 switch ((insn >> 3) & 7) { 5703 case 3: /* Post-increment. */ 5704 tcg_gen_addi_i32(AREG(insn, 0), addr, 4); 5705 break; 5706 case 4: /* Pre-decrement. */ 5707 tcg_gen_mov_i32(AREG(insn, 0), addr); 5708 } 5709 tcg_temp_free(loadval); 5710 } 5711 } 5712 5713 DISAS_INSN(from_mac) 5714 { 5715 TCGv rx; 5716 TCGv_i64 acc; 5717 int accnum; 5718 5719 rx = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0); 5720 accnum = (insn >> 9) & 3; 5721 acc = MACREG(accnum); 5722 if (s->env->macsr & MACSR_FI) { 5723 gen_helper_get_macf(rx, cpu_env, acc); 5724 } else if ((s->env->macsr & MACSR_OMC) == 0) { 5725 tcg_gen_extrl_i64_i32(rx, acc); 5726 } else if (s->env->macsr & MACSR_SU) { 5727 gen_helper_get_macs(rx, acc); 5728 } else { 5729 gen_helper_get_macu(rx, acc); 5730 } 5731 if (insn & 0x40) { 5732 tcg_gen_movi_i64(acc, 0); 5733 tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR, ~(MACSR_PAV0 << accnum)); 5734 } 5735 } 5736 5737 DISAS_INSN(move_mac) 5738 { 5739 /* FIXME: This can be done without a helper. */ 5740 int src; 5741 TCGv dest; 5742 src = insn & 3; 5743 dest = tcg_const_i32((insn >> 9) & 3); 5744 gen_helper_mac_move(cpu_env, dest, tcg_const_i32(src)); 5745 gen_mac_clear_flags(); 5746 gen_helper_mac_set_flags(cpu_env, dest); 5747 } 5748 5749 DISAS_INSN(from_macsr) 5750 { 5751 TCGv reg; 5752 5753 reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0); 5754 tcg_gen_mov_i32(reg, QREG_MACSR); 5755 } 5756 5757 DISAS_INSN(from_mask) 5758 { 5759 TCGv reg; 5760 reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0); 5761 tcg_gen_mov_i32(reg, QREG_MAC_MASK); 5762 } 5763 5764 DISAS_INSN(from_mext) 5765 { 5766 TCGv reg; 5767 TCGv acc; 5768 reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0); 5769 acc = tcg_const_i32((insn & 0x400) ? 2 : 0); 5770 if (s->env->macsr & MACSR_FI) 5771 gen_helper_get_mac_extf(reg, cpu_env, acc); 5772 else 5773 gen_helper_get_mac_exti(reg, cpu_env, acc); 5774 } 5775 5776 DISAS_INSN(macsr_to_ccr) 5777 { 5778 TCGv tmp = tcg_temp_new(); 5779 tcg_gen_andi_i32(tmp, QREG_MACSR, 0xf); 5780 gen_helper_set_sr(cpu_env, tmp); 5781 tcg_temp_free(tmp); 5782 set_cc_op(s, CC_OP_FLAGS); 5783 } 5784 5785 DISAS_INSN(to_mac) 5786 { 5787 TCGv_i64 acc; 5788 TCGv val; 5789 int accnum; 5790 accnum = (insn >> 9) & 3; 5791 acc = MACREG(accnum); 5792 SRC_EA(env, val, OS_LONG, 0, NULL); 5793 if (s->env->macsr & MACSR_FI) { 5794 tcg_gen_ext_i32_i64(acc, val); 5795 tcg_gen_shli_i64(acc, acc, 8); 5796 } else if (s->env->macsr & MACSR_SU) { 5797 tcg_gen_ext_i32_i64(acc, val); 5798 } else { 5799 tcg_gen_extu_i32_i64(acc, val); 5800 } 5801 tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR, ~(MACSR_PAV0 << accnum)); 5802 gen_mac_clear_flags(); 5803 gen_helper_mac_set_flags(cpu_env, tcg_const_i32(accnum)); 5804 } 5805 5806 DISAS_INSN(to_macsr) 5807 { 5808 TCGv val; 5809 SRC_EA(env, val, OS_LONG, 0, NULL); 5810 gen_helper_set_macsr(cpu_env, val); 5811 gen_exit_tb(s); 5812 } 5813 5814 DISAS_INSN(to_mask) 5815 { 5816 TCGv val; 5817 SRC_EA(env, val, OS_LONG, 0, NULL); 5818 tcg_gen_ori_i32(QREG_MAC_MASK, val, 0xffff0000); 5819 } 5820 5821 DISAS_INSN(to_mext) 5822 { 5823 TCGv val; 5824 TCGv acc; 5825 SRC_EA(env, val, OS_LONG, 0, NULL); 5826 acc = tcg_const_i32((insn & 0x400) ? 2 : 0); 5827 if (s->env->macsr & MACSR_FI) 5828 gen_helper_set_mac_extf(cpu_env, val, acc); 5829 else if (s->env->macsr & MACSR_SU) 5830 gen_helper_set_mac_exts(cpu_env, val, acc); 5831 else 5832 gen_helper_set_mac_extu(cpu_env, val, acc); 5833 } 5834 5835 static disas_proc opcode_table[65536]; 5836 5837 static void 5838 register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask) 5839 { 5840 int i; 5841 int from; 5842 int to; 5843 5844 /* Sanity check. All set bits must be included in the mask. */ 5845 if (opcode & ~mask) { 5846 fprintf(stderr, 5847 "qemu internal error: bogus opcode definition %04x/%04x\n", 5848 opcode, mask); 5849 abort(); 5850 } 5851 /* 5852 * This could probably be cleverer. For now just optimize the case where 5853 * the top bits are known. 5854 */ 5855 /* Find the first zero bit in the mask. */ 5856 i = 0x8000; 5857 while ((i & mask) != 0) 5858 i >>= 1; 5859 /* Iterate over all combinations of this and lower bits. */ 5860 if (i == 0) 5861 i = 1; 5862 else 5863 i <<= 1; 5864 from = opcode & ~(i - 1); 5865 to = from + i; 5866 for (i = from; i < to; i++) { 5867 if ((i & mask) == opcode) 5868 opcode_table[i] = proc; 5869 } 5870 } 5871 5872 /* 5873 * Register m68k opcode handlers. Order is important. 5874 * Later insn override earlier ones. 5875 */ 5876 void register_m68k_insns (CPUM68KState *env) 5877 { 5878 /* 5879 * Build the opcode table only once to avoid 5880 * multithreading issues. 5881 */ 5882 if (opcode_table[0] != NULL) { 5883 return; 5884 } 5885 5886 /* 5887 * use BASE() for instruction available 5888 * for CF_ISA_A and M68000. 5889 */ 5890 #define BASE(name, opcode, mask) \ 5891 register_opcode(disas_##name, 0x##opcode, 0x##mask) 5892 #define INSN(name, opcode, mask, feature) do { \ 5893 if (m68k_feature(env, M68K_FEATURE_##feature)) \ 5894 BASE(name, opcode, mask); \ 5895 } while(0) 5896 BASE(undef, 0000, 0000); 5897 INSN(arith_im, 0080, fff8, CF_ISA_A); 5898 INSN(arith_im, 0000, ff00, M68000); 5899 INSN(chk2, 00c0, f9c0, CHK2); 5900 INSN(bitrev, 00c0, fff8, CF_ISA_APLUSC); 5901 BASE(bitop_reg, 0100, f1c0); 5902 BASE(bitop_reg, 0140, f1c0); 5903 BASE(bitop_reg, 0180, f1c0); 5904 BASE(bitop_reg, 01c0, f1c0); 5905 INSN(movep, 0108, f138, MOVEP); 5906 INSN(arith_im, 0280, fff8, CF_ISA_A); 5907 INSN(arith_im, 0200, ff00, M68000); 5908 INSN(undef, 02c0, ffc0, M68000); 5909 INSN(byterev, 02c0, fff8, CF_ISA_APLUSC); 5910 INSN(arith_im, 0480, fff8, CF_ISA_A); 5911 INSN(arith_im, 0400, ff00, M68000); 5912 INSN(undef, 04c0, ffc0, M68000); 5913 INSN(arith_im, 0600, ff00, M68000); 5914 INSN(undef, 06c0, ffc0, M68000); 5915 INSN(ff1, 04c0, fff8, CF_ISA_APLUSC); 5916 INSN(arith_im, 0680, fff8, CF_ISA_A); 5917 INSN(arith_im, 0c00, ff38, CF_ISA_A); 5918 INSN(arith_im, 0c00, ff00, M68000); 5919 BASE(bitop_im, 0800, ffc0); 5920 BASE(bitop_im, 0840, ffc0); 5921 BASE(bitop_im, 0880, ffc0); 5922 BASE(bitop_im, 08c0, ffc0); 5923 INSN(arith_im, 0a80, fff8, CF_ISA_A); 5924 INSN(arith_im, 0a00, ff00, M68000); 5925 #if defined(CONFIG_SOFTMMU) 5926 INSN(moves, 0e00, ff00, M68000); 5927 #endif 5928 INSN(cas, 0ac0, ffc0, CAS); 5929 INSN(cas, 0cc0, ffc0, CAS); 5930 INSN(cas, 0ec0, ffc0, CAS); 5931 INSN(cas2w, 0cfc, ffff, CAS); 5932 INSN(cas2l, 0efc, ffff, CAS); 5933 BASE(move, 1000, f000); 5934 BASE(move, 2000, f000); 5935 BASE(move, 3000, f000); 5936 INSN(chk, 4000, f040, M68000); 5937 INSN(strldsr, 40e7, ffff, CF_ISA_APLUSC); 5938 INSN(negx, 4080, fff8, CF_ISA_A); 5939 INSN(negx, 4000, ff00, M68000); 5940 INSN(undef, 40c0, ffc0, M68000); 5941 INSN(move_from_sr, 40c0, fff8, CF_ISA_A); 5942 INSN(move_from_sr, 40c0, ffc0, M68000); 5943 BASE(lea, 41c0, f1c0); 5944 BASE(clr, 4200, ff00); 5945 BASE(undef, 42c0, ffc0); 5946 INSN(move_from_ccr, 42c0, fff8, CF_ISA_A); 5947 INSN(move_from_ccr, 42c0, ffc0, M68000); 5948 INSN(neg, 4480, fff8, CF_ISA_A); 5949 INSN(neg, 4400, ff00, M68000); 5950 INSN(undef, 44c0, ffc0, M68000); 5951 BASE(move_to_ccr, 44c0, ffc0); 5952 INSN(not, 4680, fff8, CF_ISA_A); 5953 INSN(not, 4600, ff00, M68000); 5954 #if defined(CONFIG_SOFTMMU) 5955 BASE(move_to_sr, 46c0, ffc0); 5956 #endif 5957 INSN(nbcd, 4800, ffc0, M68000); 5958 INSN(linkl, 4808, fff8, M68000); 5959 BASE(pea, 4840, ffc0); 5960 BASE(swap, 4840, fff8); 5961 INSN(bkpt, 4848, fff8, BKPT); 5962 INSN(movem, 48d0, fbf8, CF_ISA_A); 5963 INSN(movem, 48e8, fbf8, CF_ISA_A); 5964 INSN(movem, 4880, fb80, M68000); 5965 BASE(ext, 4880, fff8); 5966 BASE(ext, 48c0, fff8); 5967 BASE(ext, 49c0, fff8); 5968 BASE(tst, 4a00, ff00); 5969 INSN(tas, 4ac0, ffc0, CF_ISA_B); 5970 INSN(tas, 4ac0, ffc0, M68000); 5971 #if defined(CONFIG_SOFTMMU) 5972 INSN(halt, 4ac8, ffff, CF_ISA_A); 5973 #endif 5974 INSN(pulse, 4acc, ffff, CF_ISA_A); 5975 BASE(illegal, 4afc, ffff); 5976 INSN(mull, 4c00, ffc0, CF_ISA_A); 5977 INSN(mull, 4c00, ffc0, LONG_MULDIV); 5978 INSN(divl, 4c40, ffc0, CF_ISA_A); 5979 INSN(divl, 4c40, ffc0, LONG_MULDIV); 5980 INSN(sats, 4c80, fff8, CF_ISA_B); 5981 BASE(trap, 4e40, fff0); 5982 BASE(link, 4e50, fff8); 5983 BASE(unlk, 4e58, fff8); 5984 #if defined(CONFIG_SOFTMMU) 5985 INSN(move_to_usp, 4e60, fff8, USP); 5986 INSN(move_from_usp, 4e68, fff8, USP); 5987 INSN(reset, 4e70, ffff, M68000); 5988 BASE(stop, 4e72, ffff); 5989 BASE(rte, 4e73, ffff); 5990 INSN(cf_movec, 4e7b, ffff, CF_ISA_A); 5991 INSN(m68k_movec, 4e7a, fffe, M68000); 5992 #endif 5993 BASE(nop, 4e71, ffff); 5994 INSN(rtd, 4e74, ffff, RTD); 5995 BASE(rts, 4e75, ffff); 5996 BASE(jump, 4e80, ffc0); 5997 BASE(jump, 4ec0, ffc0); 5998 INSN(addsubq, 5000, f080, M68000); 5999 BASE(addsubq, 5080, f0c0); 6000 INSN(scc, 50c0, f0f8, CF_ISA_A); /* Scc.B Dx */ 6001 INSN(scc, 50c0, f0c0, M68000); /* Scc.B <EA> */ 6002 INSN(dbcc, 50c8, f0f8, M68000); 6003 INSN(tpf, 51f8, fff8, CF_ISA_A); 6004 6005 /* Branch instructions. */ 6006 BASE(branch, 6000, f000); 6007 /* Disable long branch instructions, then add back the ones we want. */ 6008 BASE(undef, 60ff, f0ff); /* All long branches. */ 6009 INSN(branch, 60ff, f0ff, CF_ISA_B); 6010 INSN(undef, 60ff, ffff, CF_ISA_B); /* bra.l */ 6011 INSN(branch, 60ff, ffff, BRAL); 6012 INSN(branch, 60ff, f0ff, BCCL); 6013 6014 BASE(moveq, 7000, f100); 6015 INSN(mvzs, 7100, f100, CF_ISA_B); 6016 BASE(or, 8000, f000); 6017 BASE(divw, 80c0, f0c0); 6018 INSN(sbcd_reg, 8100, f1f8, M68000); 6019 INSN(sbcd_mem, 8108, f1f8, M68000); 6020 BASE(addsub, 9000, f000); 6021 INSN(undef, 90c0, f0c0, CF_ISA_A); 6022 INSN(subx_reg, 9180, f1f8, CF_ISA_A); 6023 INSN(subx_reg, 9100, f138, M68000); 6024 INSN(subx_mem, 9108, f138, M68000); 6025 INSN(suba, 91c0, f1c0, CF_ISA_A); 6026 INSN(suba, 90c0, f0c0, M68000); 6027 6028 BASE(undef_mac, a000, f000); 6029 INSN(mac, a000, f100, CF_EMAC); 6030 INSN(from_mac, a180, f9b0, CF_EMAC); 6031 INSN(move_mac, a110, f9fc, CF_EMAC); 6032 INSN(from_macsr,a980, f9f0, CF_EMAC); 6033 INSN(from_mask, ad80, fff0, CF_EMAC); 6034 INSN(from_mext, ab80, fbf0, CF_EMAC); 6035 INSN(macsr_to_ccr, a9c0, ffff, CF_EMAC); 6036 INSN(to_mac, a100, f9c0, CF_EMAC); 6037 INSN(to_macsr, a900, ffc0, CF_EMAC); 6038 INSN(to_mext, ab00, fbc0, CF_EMAC); 6039 INSN(to_mask, ad00, ffc0, CF_EMAC); 6040 6041 INSN(mov3q, a140, f1c0, CF_ISA_B); 6042 INSN(cmp, b000, f1c0, CF_ISA_B); /* cmp.b */ 6043 INSN(cmp, b040, f1c0, CF_ISA_B); /* cmp.w */ 6044 INSN(cmpa, b0c0, f1c0, CF_ISA_B); /* cmpa.w */ 6045 INSN(cmp, b080, f1c0, CF_ISA_A); 6046 INSN(cmpa, b1c0, f1c0, CF_ISA_A); 6047 INSN(cmp, b000, f100, M68000); 6048 INSN(eor, b100, f100, M68000); 6049 INSN(cmpm, b108, f138, M68000); 6050 INSN(cmpa, b0c0, f0c0, M68000); 6051 INSN(eor, b180, f1c0, CF_ISA_A); 6052 BASE(and, c000, f000); 6053 INSN(exg_dd, c140, f1f8, M68000); 6054 INSN(exg_aa, c148, f1f8, M68000); 6055 INSN(exg_da, c188, f1f8, M68000); 6056 BASE(mulw, c0c0, f0c0); 6057 INSN(abcd_reg, c100, f1f8, M68000); 6058 INSN(abcd_mem, c108, f1f8, M68000); 6059 BASE(addsub, d000, f000); 6060 INSN(undef, d0c0, f0c0, CF_ISA_A); 6061 INSN(addx_reg, d180, f1f8, CF_ISA_A); 6062 INSN(addx_reg, d100, f138, M68000); 6063 INSN(addx_mem, d108, f138, M68000); 6064 INSN(adda, d1c0, f1c0, CF_ISA_A); 6065 INSN(adda, d0c0, f0c0, M68000); 6066 INSN(shift_im, e080, f0f0, CF_ISA_A); 6067 INSN(shift_reg, e0a0, f0f0, CF_ISA_A); 6068 INSN(shift8_im, e000, f0f0, M68000); 6069 INSN(shift16_im, e040, f0f0, M68000); 6070 INSN(shift_im, e080, f0f0, M68000); 6071 INSN(shift8_reg, e020, f0f0, M68000); 6072 INSN(shift16_reg, e060, f0f0, M68000); 6073 INSN(shift_reg, e0a0, f0f0, M68000); 6074 INSN(shift_mem, e0c0, fcc0, M68000); 6075 INSN(rotate_im, e090, f0f0, M68000); 6076 INSN(rotate8_im, e010, f0f0, M68000); 6077 INSN(rotate16_im, e050, f0f0, M68000); 6078 INSN(rotate_reg, e0b0, f0f0, M68000); 6079 INSN(rotate8_reg, e030, f0f0, M68000); 6080 INSN(rotate16_reg, e070, f0f0, M68000); 6081 INSN(rotate_mem, e4c0, fcc0, M68000); 6082 INSN(bfext_mem, e9c0, fdc0, BITFIELD); /* bfextu & bfexts */ 6083 INSN(bfext_reg, e9c0, fdf8, BITFIELD); 6084 INSN(bfins_mem, efc0, ffc0, BITFIELD); 6085 INSN(bfins_reg, efc0, fff8, BITFIELD); 6086 INSN(bfop_mem, eac0, ffc0, BITFIELD); /* bfchg */ 6087 INSN(bfop_reg, eac0, fff8, BITFIELD); /* bfchg */ 6088 INSN(bfop_mem, ecc0, ffc0, BITFIELD); /* bfclr */ 6089 INSN(bfop_reg, ecc0, fff8, BITFIELD); /* bfclr */ 6090 INSN(bfop_mem, edc0, ffc0, BITFIELD); /* bfffo */ 6091 INSN(bfop_reg, edc0, fff8, BITFIELD); /* bfffo */ 6092 INSN(bfop_mem, eec0, ffc0, BITFIELD); /* bfset */ 6093 INSN(bfop_reg, eec0, fff8, BITFIELD); /* bfset */ 6094 INSN(bfop_mem, e8c0, ffc0, BITFIELD); /* bftst */ 6095 INSN(bfop_reg, e8c0, fff8, BITFIELD); /* bftst */ 6096 BASE(undef_fpu, f000, f000); 6097 INSN(fpu, f200, ffc0, CF_FPU); 6098 INSN(fbcc, f280, ffc0, CF_FPU); 6099 INSN(fpu, f200, ffc0, FPU); 6100 INSN(fscc, f240, ffc0, FPU); 6101 INSN(fbcc, f280, ff80, FPU); 6102 #if defined(CONFIG_SOFTMMU) 6103 INSN(frestore, f340, ffc0, CF_FPU); 6104 INSN(fsave, f300, ffc0, CF_FPU); 6105 INSN(frestore, f340, ffc0, FPU); 6106 INSN(fsave, f300, ffc0, FPU); 6107 INSN(intouch, f340, ffc0, CF_ISA_A); 6108 INSN(cpushl, f428, ff38, CF_ISA_A); 6109 INSN(cpush, f420, ff20, M68040); 6110 INSN(cinv, f400, ff20, M68040); 6111 INSN(pflush, f500, ffe0, M68040); 6112 INSN(ptest, f548, ffd8, M68040); 6113 INSN(wddata, fb00, ff00, CF_ISA_A); 6114 INSN(wdebug, fbc0, ffc0, CF_ISA_A); 6115 #endif 6116 INSN(move16_mem, f600, ffe0, M68040); 6117 INSN(move16_reg, f620, fff8, M68040); 6118 #undef INSN 6119 } 6120 6121 static void m68k_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) 6122 { 6123 DisasContext *dc = container_of(dcbase, DisasContext, base); 6124 CPUM68KState *env = cpu->env_ptr; 6125 6126 dc->env = env; 6127 dc->pc = dc->base.pc_first; 6128 dc->cc_op = CC_OP_DYNAMIC; 6129 dc->cc_op_synced = 1; 6130 dc->done_mac = 0; 6131 dc->writeback_mask = 0; 6132 init_release_array(dc); 6133 } 6134 6135 static void m68k_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu) 6136 { 6137 } 6138 6139 static void m68k_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) 6140 { 6141 DisasContext *dc = container_of(dcbase, DisasContext, base); 6142 tcg_gen_insn_start(dc->base.pc_next, dc->cc_op); 6143 } 6144 6145 static bool m68k_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, 6146 const CPUBreakpoint *bp) 6147 { 6148 DisasContext *dc = container_of(dcbase, DisasContext, base); 6149 6150 gen_exception(dc, dc->base.pc_next, EXCP_DEBUG); 6151 /* 6152 * The address covered by the breakpoint must be included in 6153 * [tb->pc, tb->pc + tb->size) in order to for it to be 6154 * properly cleared -- thus we increment the PC here so that 6155 * the logic setting tb->size below does the right thing. 6156 */ 6157 dc->base.pc_next += 2; 6158 6159 return true; 6160 } 6161 6162 static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) 6163 { 6164 DisasContext *dc = container_of(dcbase, DisasContext, base); 6165 CPUM68KState *env = cpu->env_ptr; 6166 uint16_t insn = read_im16(env, dc); 6167 6168 opcode_table[insn](env, dc, insn); 6169 do_writebacks(dc); 6170 do_release(dc); 6171 6172 dc->base.pc_next = dc->pc; 6173 6174 if (dc->base.is_jmp == DISAS_NEXT) { 6175 /* 6176 * Stop translation when the next insn might touch a new page. 6177 * This ensures that prefetch aborts at the right place. 6178 * 6179 * We cannot determine the size of the next insn without 6180 * completely decoding it. However, the maximum insn size 6181 * is 32 bytes, so end if we do not have that much remaining. 6182 * This may produce several small TBs at the end of each page, 6183 * but they will all be linked with goto_tb. 6184 * 6185 * ??? ColdFire maximum is 4 bytes; MC68000's maximum is also 6186 * smaller than MC68020's. 6187 */ 6188 target_ulong start_page_offset 6189 = dc->pc - (dc->base.pc_first & TARGET_PAGE_MASK); 6190 6191 if (start_page_offset >= TARGET_PAGE_SIZE - 32) { 6192 dc->base.is_jmp = DISAS_TOO_MANY; 6193 } 6194 } 6195 } 6196 6197 static void m68k_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) 6198 { 6199 DisasContext *dc = container_of(dcbase, DisasContext, base); 6200 6201 if (dc->base.is_jmp == DISAS_NORETURN) { 6202 return; 6203 } 6204 if (dc->base.singlestep_enabled) { 6205 gen_helper_raise_exception(cpu_env, tcg_const_i32(EXCP_DEBUG)); 6206 return; 6207 } 6208 6209 switch (dc->base.is_jmp) { 6210 case DISAS_TOO_MANY: 6211 update_cc_op(dc); 6212 gen_jmp_tb(dc, 0, dc->pc); 6213 break; 6214 case DISAS_JUMP: 6215 /* We updated CC_OP and PC in gen_jmp/gen_jmp_im. */ 6216 tcg_gen_lookup_and_goto_ptr(); 6217 break; 6218 case DISAS_EXIT: 6219 /* 6220 * We updated CC_OP and PC in gen_exit_tb, but also modified 6221 * other state that may require returning to the main loop. 6222 */ 6223 tcg_gen_exit_tb(NULL, 0); 6224 break; 6225 default: 6226 g_assert_not_reached(); 6227 } 6228 } 6229 6230 static void m68k_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu) 6231 { 6232 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first)); 6233 log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size); 6234 } 6235 6236 static const TranslatorOps m68k_tr_ops = { 6237 .init_disas_context = m68k_tr_init_disas_context, 6238 .tb_start = m68k_tr_tb_start, 6239 .insn_start = m68k_tr_insn_start, 6240 .breakpoint_check = m68k_tr_breakpoint_check, 6241 .translate_insn = m68k_tr_translate_insn, 6242 .tb_stop = m68k_tr_tb_stop, 6243 .disas_log = m68k_tr_disas_log, 6244 }; 6245 6246 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns) 6247 { 6248 DisasContext dc; 6249 translator_loop(&m68k_tr_ops, &dc.base, cpu, tb, max_insns); 6250 } 6251 6252 static double floatx80_to_double(CPUM68KState *env, uint16_t high, uint64_t low) 6253 { 6254 floatx80 a = { .high = high, .low = low }; 6255 union { 6256 float64 f64; 6257 double d; 6258 } u; 6259 6260 u.f64 = floatx80_to_float64(a, &env->fp_status); 6261 return u.d; 6262 } 6263 6264 void m68k_cpu_dump_state(CPUState *cs, FILE *f, int flags) 6265 { 6266 M68kCPU *cpu = M68K_CPU(cs); 6267 CPUM68KState *env = &cpu->env; 6268 int i; 6269 uint16_t sr; 6270 for (i = 0; i < 8; i++) { 6271 qemu_fprintf(f, "D%d = %08x A%d = %08x " 6272 "F%d = %04x %016"PRIx64" (%12g)\n", 6273 i, env->dregs[i], i, env->aregs[i], 6274 i, env->fregs[i].l.upper, env->fregs[i].l.lower, 6275 floatx80_to_double(env, env->fregs[i].l.upper, 6276 env->fregs[i].l.lower)); 6277 } 6278 qemu_fprintf(f, "PC = %08x ", env->pc); 6279 sr = env->sr | cpu_m68k_get_ccr(env); 6280 qemu_fprintf(f, "SR = %04x T:%x I:%x %c%c %c%c%c%c%c\n", 6281 sr, (sr & SR_T) >> SR_T_SHIFT, (sr & SR_I) >> SR_I_SHIFT, 6282 (sr & SR_S) ? 'S' : 'U', (sr & SR_M) ? '%' : 'I', 6283 (sr & CCF_X) ? 'X' : '-', (sr & CCF_N) ? 'N' : '-', 6284 (sr & CCF_Z) ? 'Z' : '-', (sr & CCF_V) ? 'V' : '-', 6285 (sr & CCF_C) ? 'C' : '-'); 6286 qemu_fprintf(f, "FPSR = %08x %c%c%c%c ", env->fpsr, 6287 (env->fpsr & FPSR_CC_A) ? 'A' : '-', 6288 (env->fpsr & FPSR_CC_I) ? 'I' : '-', 6289 (env->fpsr & FPSR_CC_Z) ? 'Z' : '-', 6290 (env->fpsr & FPSR_CC_N) ? 'N' : '-'); 6291 qemu_fprintf(f, "\n " 6292 "FPCR = %04x ", env->fpcr); 6293 switch (env->fpcr & FPCR_PREC_MASK) { 6294 case FPCR_PREC_X: 6295 qemu_fprintf(f, "X "); 6296 break; 6297 case FPCR_PREC_S: 6298 qemu_fprintf(f, "S "); 6299 break; 6300 case FPCR_PREC_D: 6301 qemu_fprintf(f, "D "); 6302 break; 6303 } 6304 switch (env->fpcr & FPCR_RND_MASK) { 6305 case FPCR_RND_N: 6306 qemu_fprintf(f, "RN "); 6307 break; 6308 case FPCR_RND_Z: 6309 qemu_fprintf(f, "RZ "); 6310 break; 6311 case FPCR_RND_M: 6312 qemu_fprintf(f, "RM "); 6313 break; 6314 case FPCR_RND_P: 6315 qemu_fprintf(f, "RP "); 6316 break; 6317 } 6318 qemu_fprintf(f, "\n"); 6319 #ifdef CONFIG_SOFTMMU 6320 qemu_fprintf(f, "%sA7(MSP) = %08x %sA7(USP) = %08x %sA7(ISP) = %08x\n", 6321 env->current_sp == M68K_SSP ? "->" : " ", env->sp[M68K_SSP], 6322 env->current_sp == M68K_USP ? "->" : " ", env->sp[M68K_USP], 6323 env->current_sp == M68K_ISP ? "->" : " ", env->sp[M68K_ISP]); 6324 qemu_fprintf(f, "VBR = 0x%08x\n", env->vbr); 6325 qemu_fprintf(f, "SFC = %x DFC %x\n", env->sfc, env->dfc); 6326 qemu_fprintf(f, "SSW %08x TCR %08x URP %08x SRP %08x\n", 6327 env->mmu.ssw, env->mmu.tcr, env->mmu.urp, env->mmu.srp); 6328 qemu_fprintf(f, "DTTR0/1: %08x/%08x ITTR0/1: %08x/%08x\n", 6329 env->mmu.ttr[M68K_DTTR0], env->mmu.ttr[M68K_DTTR1], 6330 env->mmu.ttr[M68K_ITTR0], env->mmu.ttr[M68K_ITTR1]); 6331 qemu_fprintf(f, "MMUSR %08x, fault at %08x\n", 6332 env->mmu.mmusr, env->mmu.ar); 6333 #endif 6334 } 6335 6336 void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb, 6337 target_ulong *data) 6338 { 6339 int cc_op = data[1]; 6340 env->pc = data[0]; 6341 if (cc_op != CC_OP_DYNAMIC) { 6342 env->cc_op = cc_op; 6343 } 6344 } 6345