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