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