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