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