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