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