1 /* 2 * m68k op helpers 3 * 4 * Copyright (c) 2006-2007 CodeSourcery 5 * Written by Paul Brook 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include "qemu/osdep.h" 22 #include "cpu.h" 23 #include "exec/exec-all.h" 24 #include "exec/gdbstub.h" 25 26 #include "exec/helper-proto.h" 27 28 #define SIGNBIT (1u << 31) 29 30 /* Sort alphabetically, except for "any". */ 31 static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b) 32 { 33 ObjectClass *class_a = (ObjectClass *)a; 34 ObjectClass *class_b = (ObjectClass *)b; 35 const char *name_a, *name_b; 36 37 name_a = object_class_get_name(class_a); 38 name_b = object_class_get_name(class_b); 39 if (strcmp(name_a, "any-" TYPE_M68K_CPU) == 0) { 40 return 1; 41 } else if (strcmp(name_b, "any-" TYPE_M68K_CPU) == 0) { 42 return -1; 43 } else { 44 return strcasecmp(name_a, name_b); 45 } 46 } 47 48 static void m68k_cpu_list_entry(gpointer data, gpointer user_data) 49 { 50 ObjectClass *c = data; 51 CPUListState *s = user_data; 52 const char *typename; 53 char *name; 54 55 typename = object_class_get_name(c); 56 name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_M68K_CPU)); 57 (*s->cpu_fprintf)(s->file, "%s\n", 58 name); 59 g_free(name); 60 } 61 62 void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf) 63 { 64 CPUListState s = { 65 .file = f, 66 .cpu_fprintf = cpu_fprintf, 67 }; 68 GSList *list; 69 70 list = object_class_get_list(TYPE_M68K_CPU, false); 71 list = g_slist_sort(list, m68k_cpu_list_compare); 72 g_slist_foreach(list, m68k_cpu_list_entry, &s); 73 g_slist_free(list); 74 } 75 76 static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n) 77 { 78 if (n < 8) { 79 stfq_p(mem_buf, env->fregs[n]); 80 return 8; 81 } 82 if (n < 11) { 83 /* FP control registers (not implemented) */ 84 memset(mem_buf, 0, 4); 85 return 4; 86 } 87 return 0; 88 } 89 90 static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n) 91 { 92 if (n < 8) { 93 env->fregs[n] = ldfq_p(mem_buf); 94 return 8; 95 } 96 if (n < 11) { 97 /* FP control registers (not implemented) */ 98 return 4; 99 } 100 return 0; 101 } 102 103 M68kCPU *cpu_m68k_init(const char *cpu_model) 104 { 105 M68kCPU *cpu; 106 CPUM68KState *env; 107 ObjectClass *oc; 108 109 oc = cpu_class_by_name(TYPE_M68K_CPU, cpu_model); 110 if (oc == NULL) { 111 return NULL; 112 } 113 cpu = M68K_CPU(object_new(object_class_get_name(oc))); 114 env = &cpu->env; 115 116 register_m68k_insns(env); 117 118 object_property_set_bool(OBJECT(cpu), true, "realized", NULL); 119 120 return cpu; 121 } 122 123 void m68k_cpu_init_gdb(M68kCPU *cpu) 124 { 125 CPUState *cs = CPU(cpu); 126 CPUM68KState *env = &cpu->env; 127 128 if (m68k_feature(env, M68K_FEATURE_CF_FPU)) { 129 gdb_register_coprocessor(cs, fpu_gdb_get_reg, fpu_gdb_set_reg, 130 11, "cf-fp.xml", 18); 131 } 132 /* TODO: Add [E]MAC registers. */ 133 } 134 135 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val) 136 { 137 M68kCPU *cpu = m68k_env_get_cpu(env); 138 139 switch (reg) { 140 case 0x02: /* CACR */ 141 env->cacr = val; 142 m68k_switch_sp(env); 143 break; 144 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */ 145 /* TODO: Implement Access Control Registers. */ 146 break; 147 case 0x801: /* VBR */ 148 env->vbr = val; 149 break; 150 /* TODO: Implement control registers. */ 151 default: 152 cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n", 153 reg, val); 154 } 155 } 156 157 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val) 158 { 159 uint32_t acc; 160 int8_t exthigh; 161 uint8_t extlow; 162 uint64_t regval; 163 int i; 164 if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) { 165 for (i = 0; i < 4; i++) { 166 regval = env->macc[i]; 167 exthigh = regval >> 40; 168 if (env->macsr & MACSR_FI) { 169 acc = regval >> 8; 170 extlow = regval; 171 } else { 172 acc = regval; 173 extlow = regval >> 32; 174 } 175 if (env->macsr & MACSR_FI) { 176 regval = (((uint64_t)acc) << 8) | extlow; 177 regval |= ((int64_t)exthigh) << 40; 178 } else if (env->macsr & MACSR_SU) { 179 regval = acc | (((int64_t)extlow) << 32); 180 regval |= ((int64_t)exthigh) << 40; 181 } else { 182 regval = acc | (((uint64_t)extlow) << 32); 183 regval |= ((uint64_t)(uint8_t)exthigh) << 40; 184 } 185 env->macc[i] = regval; 186 } 187 } 188 env->macsr = val; 189 } 190 191 void m68k_switch_sp(CPUM68KState *env) 192 { 193 int new_sp; 194 195 env->sp[env->current_sp] = env->aregs[7]; 196 new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP) 197 ? M68K_SSP : M68K_USP; 198 env->aregs[7] = env->sp[new_sp]; 199 env->current_sp = new_sp; 200 } 201 202 #if defined(CONFIG_USER_ONLY) 203 204 int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, 205 int mmu_idx) 206 { 207 M68kCPU *cpu = M68K_CPU(cs); 208 209 cs->exception_index = EXCP_ACCESS; 210 cpu->env.mmu.ar = address; 211 return 1; 212 } 213 214 #else 215 216 /* MMU */ 217 218 /* TODO: This will need fixing once the MMU is implemented. */ 219 hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) 220 { 221 return addr; 222 } 223 224 int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, 225 int mmu_idx) 226 { 227 int prot; 228 229 address &= TARGET_PAGE_MASK; 230 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; 231 tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE); 232 return 0; 233 } 234 235 /* Notify CPU of a pending interrupt. Prioritization and vectoring should 236 be handled by the interrupt controller. Real hardware only requests 237 the vector when the interrupt is acknowledged by the CPU. For 238 simplicitly we calculate it when the interrupt is signalled. */ 239 void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector) 240 { 241 CPUState *cs = CPU(cpu); 242 CPUM68KState *env = &cpu->env; 243 244 env->pending_level = level; 245 env->pending_vector = vector; 246 if (level) { 247 cpu_interrupt(cs, CPU_INTERRUPT_HARD); 248 } else { 249 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); 250 } 251 } 252 253 #endif 254 255 uint32_t HELPER(bitrev)(uint32_t x) 256 { 257 x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau); 258 x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu); 259 x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u); 260 return bswap32(x); 261 } 262 263 uint32_t HELPER(ff1)(uint32_t x) 264 { 265 int n; 266 for (n = 32; x; n--) 267 x >>= 1; 268 return n; 269 } 270 271 uint32_t HELPER(sats)(uint32_t val, uint32_t v) 272 { 273 /* The result has the opposite sign to the original value. */ 274 if ((int32_t)v < 0) { 275 val = (((int32_t)val) >> 31) ^ SIGNBIT; 276 } 277 return val; 278 } 279 280 void HELPER(set_sr)(CPUM68KState *env, uint32_t val) 281 { 282 env->sr = val & 0xffe0; 283 cpu_m68k_set_ccr(env, val); 284 m68k_switch_sp(env); 285 } 286 287 /* FPU helpers. */ 288 uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val) 289 { 290 return float64_to_int32(val, &env->fp_status); 291 } 292 293 float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val) 294 { 295 return float64_to_float32(val, &env->fp_status); 296 } 297 298 float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val) 299 { 300 return int32_to_float64(val, &env->fp_status); 301 } 302 303 float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val) 304 { 305 return float32_to_float64(val, &env->fp_status); 306 } 307 308 float64 HELPER(iround_f64)(CPUM68KState *env, float64 val) 309 { 310 return float64_round_to_int(val, &env->fp_status); 311 } 312 313 float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val) 314 { 315 return float64_trunc_to_int(val, &env->fp_status); 316 } 317 318 float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val) 319 { 320 return float64_sqrt(val, &env->fp_status); 321 } 322 323 float64 HELPER(abs_f64)(float64 val) 324 { 325 return float64_abs(val); 326 } 327 328 float64 HELPER(chs_f64)(float64 val) 329 { 330 return float64_chs(val); 331 } 332 333 float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b) 334 { 335 return float64_add(a, b, &env->fp_status); 336 } 337 338 float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b) 339 { 340 return float64_sub(a, b, &env->fp_status); 341 } 342 343 float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b) 344 { 345 return float64_mul(a, b, &env->fp_status); 346 } 347 348 float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b) 349 { 350 return float64_div(a, b, &env->fp_status); 351 } 352 353 float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b) 354 { 355 /* ??? This may incorrectly raise exceptions. */ 356 /* ??? Should flush denormals to zero. */ 357 float64 res; 358 res = float64_sub(a, b, &env->fp_status); 359 if (float64_is_quiet_nan(res, &env->fp_status)) { 360 /* +/-inf compares equal against itself, but sub returns nan. */ 361 if (!float64_is_quiet_nan(a, &env->fp_status) 362 && !float64_is_quiet_nan(b, &env->fp_status)) { 363 res = float64_zero; 364 if (float64_lt_quiet(a, res, &env->fp_status)) 365 res = float64_chs(res); 366 } 367 } 368 return res; 369 } 370 371 uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val) 372 { 373 return float64_compare_quiet(val, float64_zero, &env->fp_status); 374 } 375 376 /* MAC unit. */ 377 /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers 378 take values, others take register numbers and manipulate the contents 379 in-place. */ 380 void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src) 381 { 382 uint32_t mask; 383 env->macc[dest] = env->macc[src]; 384 mask = MACSR_PAV0 << dest; 385 if (env->macsr & (MACSR_PAV0 << src)) 386 env->macsr |= mask; 387 else 388 env->macsr &= ~mask; 389 } 390 391 uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2) 392 { 393 int64_t product; 394 int64_t res; 395 396 product = (uint64_t)op1 * op2; 397 res = (product << 24) >> 24; 398 if (res != product) { 399 env->macsr |= MACSR_V; 400 if (env->macsr & MACSR_OMC) { 401 /* Make sure the accumulate operation overflows. */ 402 if (product < 0) 403 res = ~(1ll << 50); 404 else 405 res = 1ll << 50; 406 } 407 } 408 return res; 409 } 410 411 uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2) 412 { 413 uint64_t product; 414 415 product = (uint64_t)op1 * op2; 416 if (product & (0xffffffull << 40)) { 417 env->macsr |= MACSR_V; 418 if (env->macsr & MACSR_OMC) { 419 /* Make sure the accumulate operation overflows. */ 420 product = 1ll << 50; 421 } else { 422 product &= ((1ull << 40) - 1); 423 } 424 } 425 return product; 426 } 427 428 uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2) 429 { 430 uint64_t product; 431 uint32_t remainder; 432 433 product = (uint64_t)op1 * op2; 434 if (env->macsr & MACSR_RT) { 435 remainder = product & 0xffffff; 436 product >>= 24; 437 if (remainder > 0x800000) 438 product++; 439 else if (remainder == 0x800000) 440 product += (product & 1); 441 } else { 442 product >>= 24; 443 } 444 return product; 445 } 446 447 void HELPER(macsats)(CPUM68KState *env, uint32_t acc) 448 { 449 int64_t tmp; 450 int64_t result; 451 tmp = env->macc[acc]; 452 result = ((tmp << 16) >> 16); 453 if (result != tmp) { 454 env->macsr |= MACSR_V; 455 } 456 if (env->macsr & MACSR_V) { 457 env->macsr |= MACSR_PAV0 << acc; 458 if (env->macsr & MACSR_OMC) { 459 /* The result is saturated to 32 bits, despite overflow occurring 460 at 48 bits. Seems weird, but that's what the hardware docs 461 say. */ 462 result = (result >> 63) ^ 0x7fffffff; 463 } 464 } 465 env->macc[acc] = result; 466 } 467 468 void HELPER(macsatu)(CPUM68KState *env, uint32_t acc) 469 { 470 uint64_t val; 471 472 val = env->macc[acc]; 473 if (val & (0xffffull << 48)) { 474 env->macsr |= MACSR_V; 475 } 476 if (env->macsr & MACSR_V) { 477 env->macsr |= MACSR_PAV0 << acc; 478 if (env->macsr & MACSR_OMC) { 479 if (val > (1ull << 53)) 480 val = 0; 481 else 482 val = (1ull << 48) - 1; 483 } else { 484 val &= ((1ull << 48) - 1); 485 } 486 } 487 env->macc[acc] = val; 488 } 489 490 void HELPER(macsatf)(CPUM68KState *env, uint32_t acc) 491 { 492 int64_t sum; 493 int64_t result; 494 495 sum = env->macc[acc]; 496 result = (sum << 16) >> 16; 497 if (result != sum) { 498 env->macsr |= MACSR_V; 499 } 500 if (env->macsr & MACSR_V) { 501 env->macsr |= MACSR_PAV0 << acc; 502 if (env->macsr & MACSR_OMC) { 503 result = (result >> 63) ^ 0x7fffffffffffll; 504 } 505 } 506 env->macc[acc] = result; 507 } 508 509 void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc) 510 { 511 uint64_t val; 512 val = env->macc[acc]; 513 if (val == 0) { 514 env->macsr |= MACSR_Z; 515 } else if (val & (1ull << 47)) { 516 env->macsr |= MACSR_N; 517 } 518 if (env->macsr & (MACSR_PAV0 << acc)) { 519 env->macsr |= MACSR_V; 520 } 521 if (env->macsr & MACSR_FI) { 522 val = ((int64_t)val) >> 40; 523 if (val != 0 && val != -1) 524 env->macsr |= MACSR_EV; 525 } else if (env->macsr & MACSR_SU) { 526 val = ((int64_t)val) >> 32; 527 if (val != 0 && val != -1) 528 env->macsr |= MACSR_EV; 529 } else { 530 if ((val >> 32) != 0) 531 env->macsr |= MACSR_EV; 532 } 533 } 534 535 #define EXTSIGN(val, index) ( \ 536 (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \ 537 ) 538 539 #define COMPUTE_CCR(op, x, n, z, v, c) { \ 540 switch (op) { \ 541 case CC_OP_FLAGS: \ 542 /* Everything in place. */ \ 543 break; \ 544 case CC_OP_ADDB: \ 545 case CC_OP_ADDW: \ 546 case CC_OP_ADDL: \ 547 res = n; \ 548 src2 = v; \ 549 src1 = EXTSIGN(res - src2, op - CC_OP_ADDB); \ 550 c = x; \ 551 z = n; \ 552 v = (res ^ src1) & ~(src1 ^ src2); \ 553 break; \ 554 case CC_OP_SUBB: \ 555 case CC_OP_SUBW: \ 556 case CC_OP_SUBL: \ 557 res = n; \ 558 src2 = v; \ 559 src1 = EXTSIGN(res + src2, op - CC_OP_SUBB); \ 560 c = x; \ 561 z = n; \ 562 v = (res ^ src1) & (src1 ^ src2); \ 563 break; \ 564 case CC_OP_CMPB: \ 565 case CC_OP_CMPW: \ 566 case CC_OP_CMPL: \ 567 src1 = n; \ 568 src2 = v; \ 569 res = EXTSIGN(src1 - src2, op - CC_OP_CMPB); \ 570 n = res; \ 571 z = res; \ 572 c = src1 < src2; \ 573 v = (res ^ src1) & (src1 ^ src2); \ 574 break; \ 575 case CC_OP_LOGIC: \ 576 c = v = 0; \ 577 z = n; \ 578 break; \ 579 default: \ 580 cpu_abort(CPU(m68k_env_get_cpu(env)), "Bad CC_OP %d", op); \ 581 } \ 582 } while (0) 583 584 uint32_t cpu_m68k_get_ccr(CPUM68KState *env) 585 { 586 uint32_t x, c, n, z, v; 587 uint32_t res, src1, src2; 588 589 x = env->cc_x; 590 n = env->cc_n; 591 z = env->cc_z; 592 v = env->cc_v; 593 c = env->cc_c; 594 595 COMPUTE_CCR(env->cc_op, x, n, z, v, c); 596 597 n = n >> 31; 598 z = (z == 0); 599 v = v >> 31; 600 601 return x * CCF_X + n * CCF_N + z * CCF_Z + v * CCF_V + c * CCF_C; 602 } 603 604 uint32_t HELPER(get_ccr)(CPUM68KState *env) 605 { 606 return cpu_m68k_get_ccr(env); 607 } 608 609 void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t ccr) 610 { 611 env->cc_x = (ccr & CCF_X ? 1 : 0); 612 env->cc_n = (ccr & CCF_N ? -1 : 0); 613 env->cc_z = (ccr & CCF_Z ? 0 : 1); 614 env->cc_v = (ccr & CCF_V ? -1 : 0); 615 env->cc_c = (ccr & CCF_C ? 1 : 0); 616 env->cc_op = CC_OP_FLAGS; 617 } 618 619 void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr) 620 { 621 cpu_m68k_set_ccr(env, ccr); 622 } 623 624 void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op) 625 { 626 uint32_t res, src1, src2; 627 628 COMPUTE_CCR(cc_op, env->cc_x, env->cc_n, env->cc_z, env->cc_v, env->cc_c); 629 env->cc_op = CC_OP_FLAGS; 630 } 631 632 uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val) 633 { 634 int rem; 635 uint32_t result; 636 637 if (env->macsr & MACSR_SU) { 638 /* 16-bit rounding. */ 639 rem = val & 0xffffff; 640 val = (val >> 24) & 0xffffu; 641 if (rem > 0x800000) 642 val++; 643 else if (rem == 0x800000) 644 val += (val & 1); 645 } else if (env->macsr & MACSR_RT) { 646 /* 32-bit rounding. */ 647 rem = val & 0xff; 648 val >>= 8; 649 if (rem > 0x80) 650 val++; 651 else if (rem == 0x80) 652 val += (val & 1); 653 } else { 654 /* No rounding. */ 655 val >>= 8; 656 } 657 if (env->macsr & MACSR_OMC) { 658 /* Saturate. */ 659 if (env->macsr & MACSR_SU) { 660 if (val != (uint16_t) val) { 661 result = ((val >> 63) ^ 0x7fff) & 0xffff; 662 } else { 663 result = val & 0xffff; 664 } 665 } else { 666 if (val != (uint32_t)val) { 667 result = ((uint32_t)(val >> 63) & 0x7fffffff); 668 } else { 669 result = (uint32_t)val; 670 } 671 } 672 } else { 673 /* No saturation. */ 674 if (env->macsr & MACSR_SU) { 675 result = val & 0xffff; 676 } else { 677 result = (uint32_t)val; 678 } 679 } 680 return result; 681 } 682 683 uint32_t HELPER(get_macs)(uint64_t val) 684 { 685 if (val == (int32_t)val) { 686 return (int32_t)val; 687 } else { 688 return (val >> 61) ^ ~SIGNBIT; 689 } 690 } 691 692 uint32_t HELPER(get_macu)(uint64_t val) 693 { 694 if ((val >> 32) == 0) { 695 return (uint32_t)val; 696 } else { 697 return 0xffffffffu; 698 } 699 } 700 701 uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc) 702 { 703 uint32_t val; 704 val = env->macc[acc] & 0x00ff; 705 val |= (env->macc[acc] >> 32) & 0xff00; 706 val |= (env->macc[acc + 1] << 16) & 0x00ff0000; 707 val |= (env->macc[acc + 1] >> 16) & 0xff000000; 708 return val; 709 } 710 711 uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc) 712 { 713 uint32_t val; 714 val = (env->macc[acc] >> 32) & 0xffff; 715 val |= (env->macc[acc + 1] >> 16) & 0xffff0000; 716 return val; 717 } 718 719 void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc) 720 { 721 int64_t res; 722 int32_t tmp; 723 res = env->macc[acc] & 0xffffffff00ull; 724 tmp = (int16_t)(val & 0xff00); 725 res |= ((int64_t)tmp) << 32; 726 res |= val & 0xff; 727 env->macc[acc] = res; 728 res = env->macc[acc + 1] & 0xffffffff00ull; 729 tmp = (val & 0xff000000); 730 res |= ((int64_t)tmp) << 16; 731 res |= (val >> 16) & 0xff; 732 env->macc[acc + 1] = res; 733 } 734 735 void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc) 736 { 737 int64_t res; 738 int32_t tmp; 739 res = (uint32_t)env->macc[acc]; 740 tmp = (int16_t)val; 741 res |= ((int64_t)tmp) << 32; 742 env->macc[acc] = res; 743 res = (uint32_t)env->macc[acc + 1]; 744 tmp = val & 0xffff0000; 745 res |= (int64_t)tmp << 16; 746 env->macc[acc + 1] = res; 747 } 748 749 void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc) 750 { 751 uint64_t res; 752 res = (uint32_t)env->macc[acc]; 753 res |= ((uint64_t)(val & 0xffff)) << 32; 754 env->macc[acc] = res; 755 res = (uint32_t)env->macc[acc + 1]; 756 res |= (uint64_t)(val & 0xffff0000) << 16; 757 env->macc[acc + 1] = res; 758 } 759