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