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