Optimize cmp x, 0 case
[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     qemu_init_vcpu(env);
184     return env;
185 }
186
187 void cpu_m68k_close(CPUM68KState *env)
188 {
189     qemu_free(env);
190 }
191
192 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
193 {
194     int flags;
195     uint32_t src;
196     uint32_t dest;
197     uint32_t tmp;
198
199 #define HIGHBIT 0x80000000u
200
201 #define SET_NZ(x) do { \
202     if ((x) == 0) \
203         flags |= CCF_Z; \
204     else if ((int32_t)(x) < 0) \
205         flags |= CCF_N; \
206     } while (0)
207
208 #define SET_FLAGS_SUB(type, utype) do { \
209     SET_NZ((type)dest); \
210     tmp = dest + src; \
211     if ((utype) tmp < (utype) src) \
212         flags |= CCF_C; \
213     if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
214         flags |= CCF_V; \
215     } while (0)
216
217     flags = 0;
218     src = env->cc_src;
219     dest = env->cc_dest;
220     switch (cc_op) {
221     case CC_OP_FLAGS:
222         flags = dest;
223         break;
224     case CC_OP_LOGIC:
225         SET_NZ(dest);
226         break;
227     case CC_OP_ADD:
228         SET_NZ(dest);
229         if (dest < src)
230             flags |= CCF_C;
231         tmp = dest - src;
232         if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
233             flags |= CCF_V;
234         break;
235     case CC_OP_SUB:
236         SET_FLAGS_SUB(int32_t, uint32_t);
237         break;
238     case CC_OP_CMPB:
239         SET_FLAGS_SUB(int8_t, uint8_t);
240         break;
241     case CC_OP_CMPW:
242         SET_FLAGS_SUB(int16_t, uint16_t);
243         break;
244     case CC_OP_ADDX:
245         SET_NZ(dest);
246         if (dest <= src)
247             flags |= CCF_C;
248         tmp = dest - src - 1;
249         if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
250             flags |= CCF_V;
251         break;
252     case CC_OP_SUBX:
253         SET_NZ(dest);
254         tmp = dest + src + 1;
255         if (tmp <= src)
256             flags |= CCF_C;
257         if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
258             flags |= CCF_V;
259         break;
260     case CC_OP_SHIFT:
261         SET_NZ(dest);
262         if (src)
263             flags |= CCF_C;
264         break;
265     default:
266         cpu_abort(env, "Bad CC_OP %d", cc_op);
267     }
268     env->cc_op = CC_OP_FLAGS;
269     env->cc_dest = flags;
270 }
271
272 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
273 {
274     switch (reg) {
275     case 0x02: /* CACR */
276         env->cacr = val;
277         m68k_switch_sp(env);
278         break;
279     case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
280         /* TODO: Implement Access Control Registers.  */
281         break;
282     case 0x801: /* VBR */
283         env->vbr = val;
284         break;
285     /* TODO: Implement control registers.  */
286     default:
287         cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
288                   reg, val);
289     }
290 }
291
292 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
293 {
294     uint32_t acc;
295     int8_t exthigh;
296     uint8_t extlow;
297     uint64_t regval;
298     int i;
299     if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
300         for (i = 0; i < 4; i++) {
301             regval = env->macc[i];
302             exthigh = regval >> 40;
303             if (env->macsr & MACSR_FI) {
304                 acc = regval >> 8;
305                 extlow = regval;
306             } else {
307                 acc = regval;
308                 extlow = regval >> 32;
309             }
310             if (env->macsr & MACSR_FI) {
311                 regval = (((uint64_t)acc) << 8) | extlow;
312                 regval |= ((int64_t)exthigh) << 40;
313             } else if (env->macsr & MACSR_SU) {
314                 regval = acc | (((int64_t)extlow) << 32);
315                 regval |= ((int64_t)exthigh) << 40;
316             } else {
317                 regval = acc | (((uint64_t)extlow) << 32);
318                 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
319             }
320             env->macc[i] = regval;
321         }
322     }
323     env->macsr = val;
324 }
325
326 void m68k_switch_sp(CPUM68KState *env)
327 {
328     int new_sp;
329
330     env->sp[env->current_sp] = env->aregs[7];
331     new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
332              ? M68K_SSP : M68K_USP;
333     env->aregs[7] = env->sp[new_sp];
334     env->current_sp = new_sp;
335 }
336
337 /* MMU */
338
339 /* TODO: This will need fixing once the MMU is implemented.  */
340 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
341 {
342     return addr;
343 }
344
345 #if defined(CONFIG_USER_ONLY)
346
347 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
348                                int mmu_idx, int is_softmmu)
349 {
350     env->exception_index = EXCP_ACCESS;
351     env->mmu.ar = address;
352     return 1;
353 }
354
355 #else
356
357 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
358                                int mmu_idx, int is_softmmu)
359 {
360     int prot;
361
362     address &= TARGET_PAGE_MASK;
363     prot = PAGE_READ | PAGE_WRITE;
364     return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
365 }
366
367 /* Notify CPU of a pending interrupt.  Prioritization and vectoring should
368    be handled by the interrupt controller.  Real hardware only requests
369    the vector when the interrupt is acknowledged by the CPU.  For
370    simplicitly we calculate it when the interrupt is signalled.  */
371 void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
372 {
373     env->pending_level = level;
374     env->pending_vector = vector;
375     if (level)
376         cpu_interrupt(env, CPU_INTERRUPT_HARD);
377     else
378         cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
379 }
380
381 #endif
382
383 uint32_t HELPER(bitrev)(uint32_t x)
384 {
385     x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
386     x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
387     x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
388     return bswap32(x);
389 }
390
391 uint32_t HELPER(ff1)(uint32_t x)
392 {
393     int n;
394     for (n = 32; x; n--)
395         x >>= 1;
396     return n;
397 }
398
399 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
400 {
401     /* The result has the opposite sign to the original value.  */
402     if (ccr & CCF_V)
403         val = (((int32_t)val) >> 31) ^ SIGNBIT;
404     return val;
405 }
406
407 uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
408 {
409     uint32_t res;
410     uint32_t old_flags;
411
412     old_flags = env->cc_dest;
413     if (env->cc_x) {
414         env->cc_x = (op1 <= op2);
415         env->cc_op = CC_OP_SUBX;
416         res = op1 - (op2 + 1);
417     } else {
418         env->cc_x = (op1 < op2);
419         env->cc_op = CC_OP_SUB;
420         res = op1 - op2;
421     }
422     env->cc_dest = res;
423     env->cc_src = op2;
424     cpu_m68k_flush_flags(env, env->cc_op);
425     /* !Z is sticky.  */
426     env->cc_dest &= (old_flags | ~CCF_Z);
427     return res;
428 }
429
430 uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
431 {
432     uint32_t res;
433     uint32_t old_flags;
434
435     old_flags = env->cc_dest;
436     if (env->cc_x) {
437         res = op1 + op2 + 1;
438         env->cc_x = (res <= op2);
439         env->cc_op = CC_OP_ADDX;
440     } else {
441         res = op1 + op2;
442         env->cc_x = (res < op2);
443         env->cc_op = CC_OP_ADD;
444     }
445     env->cc_dest = res;
446     env->cc_src = op2;
447     cpu_m68k_flush_flags(env, env->cc_op);
448     /* !Z is sticky.  */
449     env->cc_dest &= (old_flags | ~CCF_Z);
450     return res;
451 }
452
453 uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
454 {
455     return a < b;
456 }
457
458 void HELPER(set_sr)(CPUState *env, uint32_t val)
459 {
460     env->sr = val & 0xffff;
461     m68k_switch_sp(env);
462 }
463
464 uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
465 {
466     uint32_t result;
467     uint32_t cf;
468
469     shift &= 63;
470     if (shift == 0) {
471         result = val;
472         cf = env->cc_src & CCF_C;
473     } else if (shift < 32) {
474         result = val << shift;
475         cf = (val >> (32 - shift)) & 1;
476     } else if (shift == 32) {
477         result = 0;
478         cf = val & 1;
479     } else /* shift > 32 */ {
480         result = 0;
481         cf = 0;
482     }
483     env->cc_src = cf;
484     env->cc_x = (cf != 0);
485     env->cc_dest = result;
486     return result;
487 }
488
489 uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
490 {
491     uint32_t result;
492     uint32_t cf;
493
494     shift &= 63;
495     if (shift == 0) {
496         result = val;
497         cf = env->cc_src & CCF_C;
498     } else if (shift < 32) {
499         result = val >> shift;
500         cf = (val >> (shift - 1)) & 1;
501     } else if (shift == 32) {
502         result = 0;
503         cf = val >> 31;
504     } else /* shift > 32 */ {
505         result = 0;
506         cf = 0;
507     }
508     env->cc_src = cf;
509     env->cc_x = (cf != 0);
510     env->cc_dest = result;
511     return result;
512 }
513
514 uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
515 {
516     uint32_t result;
517     uint32_t cf;
518
519     shift &= 63;
520     if (shift == 0) {
521         result = val;
522         cf = (env->cc_src & CCF_C) != 0;
523     } else if (shift < 32) {
524         result = (int32_t)val >> shift;
525         cf = (val >> (shift - 1)) & 1;
526     } else /* shift >= 32 */ {
527         result = (int32_t)val >> 31;
528         cf = val >> 31;
529     }
530     env->cc_src = cf;
531     env->cc_x = cf;
532     env->cc_dest = result;
533     return result;
534 }
535
536 /* FPU helpers.  */
537 uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
538 {
539     return float64_to_int32(val, &env->fp_status);
540 }
541
542 float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
543 {
544     return float64_to_float32(val, &env->fp_status);
545 }
546
547 float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
548 {
549     return int32_to_float64(val, &env->fp_status);
550 }
551
552 float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
553 {
554     return float32_to_float64(val, &env->fp_status);
555 }
556
557 float64 HELPER(iround_f64)(CPUState *env, float64 val)
558 {
559     return float64_round_to_int(val, &env->fp_status);
560 }
561
562 float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
563 {
564     return float64_trunc_to_int(val, &env->fp_status);
565 }
566
567 float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
568 {
569     return float64_sqrt(val, &env->fp_status);
570 }
571
572 float64 HELPER(abs_f64)(float64 val)
573 {
574     return float64_abs(val);
575 }
576
577 float64 HELPER(chs_f64)(float64 val)
578 {
579     return float64_chs(val);
580 }
581
582 float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
583 {
584     return float64_add(a, b, &env->fp_status);
585 }
586
587 float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
588 {
589     return float64_sub(a, b, &env->fp_status);
590 }
591
592 float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
593 {
594     return float64_mul(a, b, &env->fp_status);
595 }
596
597 float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
598 {
599     return float64_div(a, b, &env->fp_status);
600 }
601
602 float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
603 {
604     /* ??? This may incorrectly raise exceptions.  */
605     /* ??? Should flush denormals to zero.  */
606     float64 res;
607     res = float64_sub(a, b, &env->fp_status);
608     if (float64_is_nan(res)) {
609         /* +/-inf compares equal against itself, but sub returns nan.  */
610         if (!float64_is_nan(a)
611             && !float64_is_nan(b)) {
612             res = float64_zero;
613             if (float64_lt_quiet(a, res, &env->fp_status))
614                 res = float64_chs(res);
615         }
616     }
617     return res;
618 }
619
620 uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
621 {
622     return float64_compare_quiet(val, float64_zero, &env->fp_status);
623 }
624
625 /* MAC unit.  */
626 /* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
627    take values,  others take register numbers and manipulate the contents
628    in-place.  */
629 void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
630 {
631     uint32_t mask;
632     env->macc[dest] = env->macc[src];
633     mask = MACSR_PAV0 << dest;
634     if (env->macsr & (MACSR_PAV0 << src))
635         env->macsr |= mask;
636     else
637         env->macsr &= ~mask;
638 }
639
640 uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
641 {
642     int64_t product;
643     int64_t res;
644
645     product = (uint64_t)op1 * op2;
646     res = (product << 24) >> 24;
647     if (res != product) {
648         env->macsr |= MACSR_V;
649         if (env->macsr & MACSR_OMC) {
650             /* Make sure the accumulate operation overflows.  */
651             if (product < 0)
652                 res = ~(1ll << 50);
653             else
654                 res = 1ll << 50;
655         }
656     }
657     return res;
658 }
659
660 uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
661 {
662     uint64_t product;
663
664     product = (uint64_t)op1 * op2;
665     if (product & (0xffffffull << 40)) {
666         env->macsr |= MACSR_V;
667         if (env->macsr & MACSR_OMC) {
668             /* Make sure the accumulate operation overflows.  */
669             product = 1ll << 50;
670         } else {
671             product &= ((1ull << 40) - 1);
672         }
673     }
674     return product;
675 }
676
677 uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
678 {
679     uint64_t product;
680     uint32_t remainder;
681
682     product = (uint64_t)op1 * op2;
683     if (env->macsr & MACSR_RT) {
684         remainder = product & 0xffffff;
685         product >>= 24;
686         if (remainder > 0x800000)
687             product++;
688         else if (remainder == 0x800000)
689             product += (product & 1);
690     } else {
691         product >>= 24;
692     }
693     return product;
694 }
695
696 void HELPER(macsats)(CPUState *env, uint32_t acc)
697 {
698     int64_t tmp;
699     int64_t result;
700     tmp = env->macc[acc];
701     result = ((tmp << 16) >> 16);
702     if (result != tmp) {
703         env->macsr |= MACSR_V;
704     }
705     if (env->macsr & MACSR_V) {
706         env->macsr |= MACSR_PAV0 << acc;
707         if (env->macsr & MACSR_OMC) {
708             /* The result is saturated to 32 bits, despite overflow occuring
709                at 48 bits.  Seems weird, but that's what the hardware docs
710                say.  */
711             result = (result >> 63) ^ 0x7fffffff;
712         }
713     }
714     env->macc[acc] = result;
715 }
716
717 void HELPER(macsatu)(CPUState *env, uint32_t acc)
718 {
719     uint64_t val;
720
721     val = env->macc[acc];
722     if (val & (0xffffull << 48)) {
723         env->macsr |= MACSR_V;
724     }
725     if (env->macsr & MACSR_V) {
726         env->macsr |= MACSR_PAV0 << acc;
727         if (env->macsr & MACSR_OMC) {
728             if (val > (1ull << 53))
729                 val = 0;
730             else
731                 val = (1ull << 48) - 1;
732         } else {
733             val &= ((1ull << 48) - 1);
734         }
735     }
736     env->macc[acc] = val;
737 }
738
739 void HELPER(macsatf)(CPUState *env, uint32_t acc)
740 {
741     int64_t sum;
742     int64_t result;
743
744     sum = env->macc[acc];
745     result = (sum << 16) >> 16;
746     if (result != sum) {
747         env->macsr |= MACSR_V;
748     }
749     if (env->macsr & MACSR_V) {
750         env->macsr |= MACSR_PAV0 << acc;
751         if (env->macsr & MACSR_OMC) {
752             result = (result >> 63) ^ 0x7fffffffffffll;
753         }
754     }
755     env->macc[acc] = result;
756 }
757
758 void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
759 {
760     uint64_t val;
761     val = env->macc[acc];
762     if (val == 0)
763         env->macsr |= MACSR_Z;
764     else if (val & (1ull << 47));
765         env->macsr |= MACSR_N;
766     if (env->macsr & (MACSR_PAV0 << acc)) {
767         env->macsr |= MACSR_V;
768     }
769     if (env->macsr & MACSR_FI) {
770         val = ((int64_t)val) >> 40;
771         if (val != 0 && val != -1)
772             env->macsr |= MACSR_EV;
773     } else if (env->macsr & MACSR_SU) {
774         val = ((int64_t)val) >> 32;
775         if (val != 0 && val != -1)
776             env->macsr |= MACSR_EV;
777     } else {
778         if ((val >> 32) != 0)
779             env->macsr |= MACSR_EV;
780     }
781 }
782
783 void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
784 {
785     cpu_m68k_flush_flags(env, cc_op);
786 }
787
788 uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
789 {
790     int rem;
791     uint32_t result;
792
793     if (env->macsr & MACSR_SU) {
794         /* 16-bit rounding.  */
795         rem = val & 0xffffff;
796         val = (val >> 24) & 0xffffu;
797         if (rem > 0x800000)
798             val++;
799         else if (rem == 0x800000)
800             val += (val & 1);
801     } else if (env->macsr & MACSR_RT) {
802         /* 32-bit rounding.  */
803         rem = val & 0xff;
804         val >>= 8;
805         if (rem > 0x80)
806             val++;
807         else if (rem == 0x80)
808             val += (val & 1);
809     } else {
810         /* No rounding.  */
811         val >>= 8;
812     }
813     if (env->macsr & MACSR_OMC) {
814         /* Saturate.  */
815         if (env->macsr & MACSR_SU) {
816             if (val != (uint16_t) val) {
817                 result = ((val >> 63) ^ 0x7fff) & 0xffff;
818             } else {
819                 result = val & 0xffff;
820             }
821         } else {
822             if (val != (uint32_t)val) {
823                 result = ((uint32_t)(val >> 63) & 0x7fffffff);
824             } else {
825                 result = (uint32_t)val;
826             }
827         }
828     } else {
829         /* No saturation.  */
830         if (env->macsr & MACSR_SU) {
831             result = val & 0xffff;
832         } else {
833             result = (uint32_t)val;
834         }
835     }
836     return result;
837 }
838
839 uint32_t HELPER(get_macs)(uint64_t val)
840 {
841     if (val == (int32_t)val) {
842         return (int32_t)val;
843     } else {
844         return (val >> 61) ^ ~SIGNBIT;
845     }
846 }
847
848 uint32_t HELPER(get_macu)(uint64_t val)
849 {
850     if ((val >> 32) == 0) {
851         return (uint32_t)val;
852     } else {
853         return 0xffffffffu;
854     }
855 }
856
857 uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
858 {
859     uint32_t val;
860     val = env->macc[acc] & 0x00ff;
861     val = (env->macc[acc] >> 32) & 0xff00;
862     val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
863     val |= (env->macc[acc + 1] >> 16) & 0xff000000;
864     return val;
865 }
866
867 uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
868 {
869     uint32_t val;
870     val = (env->macc[acc] >> 32) & 0xffff;
871     val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
872     return val;
873 }
874
875 void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
876 {
877     int64_t res;
878     int32_t tmp;
879     res = env->macc[acc] & 0xffffffff00ull;
880     tmp = (int16_t)(val & 0xff00);
881     res |= ((int64_t)tmp) << 32;
882     res |= val & 0xff;
883     env->macc[acc] = res;
884     res = env->macc[acc + 1] & 0xffffffff00ull;
885     tmp = (val & 0xff000000);
886     res |= ((int64_t)tmp) << 16;
887     res |= (val >> 16) & 0xff;
888     env->macc[acc + 1] = res;
889 }
890
891 void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
892 {
893     int64_t res;
894     int32_t tmp;
895     res = (uint32_t)env->macc[acc];
896     tmp = (int16_t)val;
897     res |= ((int64_t)tmp) << 32;
898     env->macc[acc] = res;
899     res = (uint32_t)env->macc[acc + 1];
900     tmp = val & 0xffff0000;
901     res |= (int64_t)tmp << 16;
902     env->macc[acc + 1] = res;
903 }
904
905 void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
906 {
907     uint64_t res;
908     res = (uint32_t)env->macc[acc];
909     res |= ((uint64_t)(val & 0xffff)) << 32;
910     env->macc[acc] = res;
911     res = (uint32_t)env->macc[acc + 1];
912     res |= (uint64_t)(val & 0xffff0000) << 16;
913     env->macc[acc + 1] = res;
914 }