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