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