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