hw/eeprom93xx.c: substitute structure dump with discrete dump in eeprom_save/load
[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 void HELPER(set_sr)(CPUState *env, uint32_t val)
458 {
459     env->sr = val & 0xffff;
460     m68k_switch_sp(env);
461 }
462
463 uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
464 {
465     uint32_t result;
466     uint32_t cf;
467
468     shift &= 63;
469     if (shift == 0) {
470         result = val;
471         cf = env->cc_src & CCF_C;
472     } else if (shift < 32) {
473         result = val << shift;
474         cf = (val >> (32 - shift)) & 1;
475     } else if (shift == 32) {
476         result = 0;
477         cf = val & 1;
478     } else /* shift > 32 */ {
479         result = 0;
480         cf = 0;
481     }
482     env->cc_src = cf;
483     env->cc_x = (cf != 0);
484     env->cc_dest = result;
485     return result;
486 }
487
488 uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
489 {
490     uint32_t result;
491     uint32_t cf;
492
493     shift &= 63;
494     if (shift == 0) {
495         result = val;
496         cf = env->cc_src & CCF_C;
497     } else if (shift < 32) {
498         result = val >> shift;
499         cf = (val >> (shift - 1)) & 1;
500     } else if (shift == 32) {
501         result = 0;
502         cf = val >> 31;
503     } else /* shift > 32 */ {
504         result = 0;
505         cf = 0;
506     }
507     env->cc_src = cf;
508     env->cc_x = (cf != 0);
509     env->cc_dest = result;
510     return result;
511 }
512
513 uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
514 {
515     uint32_t result;
516     uint32_t cf;
517
518     shift &= 63;
519     if (shift == 0) {
520         result = val;
521         cf = (env->cc_src & CCF_C) != 0;
522     } else if (shift < 32) {
523         result = (int32_t)val >> shift;
524         cf = (val >> (shift - 1)) & 1;
525     } else /* shift >= 32 */ {
526         result = (int32_t)val >> 31;
527         cf = val >> 31;
528     }
529     env->cc_src = cf;
530     env->cc_x = cf;
531     env->cc_dest = result;
532     return result;
533 }
534
535 /* FPU helpers.  */
536 uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
537 {
538     return float64_to_int32(val, &env->fp_status);
539 }
540
541 float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
542 {
543     return float64_to_float32(val, &env->fp_status);
544 }
545
546 float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
547 {
548     return int32_to_float64(val, &env->fp_status);
549 }
550
551 float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
552 {
553     return float32_to_float64(val, &env->fp_status);
554 }
555
556 float64 HELPER(iround_f64)(CPUState *env, float64 val)
557 {
558     return float64_round_to_int(val, &env->fp_status);
559 }
560
561 float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
562 {
563     return float64_trunc_to_int(val, &env->fp_status);
564 }
565
566 float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
567 {
568     return float64_sqrt(val, &env->fp_status);
569 }
570
571 float64 HELPER(abs_f64)(float64 val)
572 {
573     return float64_abs(val);
574 }
575
576 float64 HELPER(chs_f64)(float64 val)
577 {
578     return float64_chs(val);
579 }
580
581 float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
582 {
583     return float64_add(a, b, &env->fp_status);
584 }
585
586 float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
587 {
588     return float64_sub(a, b, &env->fp_status);
589 }
590
591 float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
592 {
593     return float64_mul(a, b, &env->fp_status);
594 }
595
596 float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
597 {
598     return float64_div(a, b, &env->fp_status);
599 }
600
601 float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
602 {
603     /* ??? This may incorrectly raise exceptions.  */
604     /* ??? Should flush denormals to zero.  */
605     float64 res;
606     res = float64_sub(a, b, &env->fp_status);
607     if (float64_is_nan(res)) {
608         /* +/-inf compares equal against itself, but sub returns nan.  */
609         if (!float64_is_nan(a)
610             && !float64_is_nan(b)) {
611             res = float64_zero;
612             if (float64_lt_quiet(a, res, &env->fp_status))
613                 res = float64_chs(res);
614         }
615     }
616     return res;
617 }
618
619 uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
620 {
621     return float64_compare_quiet(val, float64_zero, &env->fp_status);
622 }
623
624 /* MAC unit.  */
625 /* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
626    take values,  others take register numbers and manipulate the contents
627    in-place.  */
628 void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
629 {
630     uint32_t mask;
631     env->macc[dest] = env->macc[src];
632     mask = MACSR_PAV0 << dest;
633     if (env->macsr & (MACSR_PAV0 << src))
634         env->macsr |= mask;
635     else
636         env->macsr &= ~mask;
637 }
638
639 uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
640 {
641     int64_t product;
642     int64_t res;
643
644     product = (uint64_t)op1 * op2;
645     res = (product << 24) >> 24;
646     if (res != product) {
647         env->macsr |= MACSR_V;
648         if (env->macsr & MACSR_OMC) {
649             /* Make sure the accumulate operation overflows.  */
650             if (product < 0)
651                 res = ~(1ll << 50);
652             else
653                 res = 1ll << 50;
654         }
655     }
656     return res;
657 }
658
659 uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
660 {
661     uint64_t product;
662
663     product = (uint64_t)op1 * op2;
664     if (product & (0xffffffull << 40)) {
665         env->macsr |= MACSR_V;
666         if (env->macsr & MACSR_OMC) {
667             /* Make sure the accumulate operation overflows.  */
668             product = 1ll << 50;
669         } else {
670             product &= ((1ull << 40) - 1);
671         }
672     }
673     return product;
674 }
675
676 uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
677 {
678     uint64_t product;
679     uint32_t remainder;
680
681     product = (uint64_t)op1 * op2;
682     if (env->macsr & MACSR_RT) {
683         remainder = product & 0xffffff;
684         product >>= 24;
685         if (remainder > 0x800000)
686             product++;
687         else if (remainder == 0x800000)
688             product += (product & 1);
689     } else {
690         product >>= 24;
691     }
692     return product;
693 }
694
695 void HELPER(macsats)(CPUState *env, uint32_t acc)
696 {
697     int64_t tmp;
698     int64_t result;
699     tmp = env->macc[acc];
700     result = ((tmp << 16) >> 16);
701     if (result != tmp) {
702         env->macsr |= MACSR_V;
703     }
704     if (env->macsr & MACSR_V) {
705         env->macsr |= MACSR_PAV0 << acc;
706         if (env->macsr & MACSR_OMC) {
707             /* The result is saturated to 32 bits, despite overflow occuring
708                at 48 bits.  Seems weird, but that's what the hardware docs
709                say.  */
710             result = (result >> 63) ^ 0x7fffffff;
711         }
712     }
713     env->macc[acc] = result;
714 }
715
716 void HELPER(macsatu)(CPUState *env, uint32_t acc)
717 {
718     uint64_t val;
719
720     val = env->macc[acc];
721     if (val & (0xffffull << 48)) {
722         env->macsr |= MACSR_V;
723     }
724     if (env->macsr & MACSR_V) {
725         env->macsr |= MACSR_PAV0 << acc;
726         if (env->macsr & MACSR_OMC) {
727             if (val > (1ull << 53))
728                 val = 0;
729             else
730                 val = (1ull << 48) - 1;
731         } else {
732             val &= ((1ull << 48) - 1);
733         }
734     }
735     env->macc[acc] = val;
736 }
737
738 void HELPER(macsatf)(CPUState *env, uint32_t acc)
739 {
740     int64_t sum;
741     int64_t result;
742
743     sum = env->macc[acc];
744     result = (sum << 16) >> 16;
745     if (result != sum) {
746         env->macsr |= MACSR_V;
747     }
748     if (env->macsr & MACSR_V) {
749         env->macsr |= MACSR_PAV0 << acc;
750         if (env->macsr & MACSR_OMC) {
751             result = (result >> 63) ^ 0x7fffffffffffll;
752         }
753     }
754     env->macc[acc] = result;
755 }
756
757 void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
758 {
759     uint64_t val;
760     val = env->macc[acc];
761     if (val == 0)
762         env->macsr |= MACSR_Z;
763     else if (val & (1ull << 47));
764         env->macsr |= MACSR_N;
765     if (env->macsr & (MACSR_PAV0 << acc)) {
766         env->macsr |= MACSR_V;
767     }
768     if (env->macsr & MACSR_FI) {
769         val = ((int64_t)val) >> 40;
770         if (val != 0 && val != -1)
771             env->macsr |= MACSR_EV;
772     } else if (env->macsr & MACSR_SU) {
773         val = ((int64_t)val) >> 32;
774         if (val != 0 && val != -1)
775             env->macsr |= MACSR_EV;
776     } else {
777         if ((val >> 32) != 0)
778             env->macsr |= MACSR_EV;
779     }
780 }
781
782 void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
783 {
784     cpu_m68k_flush_flags(env, cc_op);
785 }
786
787 uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
788 {
789     int rem;
790     uint32_t result;
791
792     if (env->macsr & MACSR_SU) {
793         /* 16-bit rounding.  */
794         rem = val & 0xffffff;
795         val = (val >> 24) & 0xffffu;
796         if (rem > 0x800000)
797             val++;
798         else if (rem == 0x800000)
799             val += (val & 1);
800     } else if (env->macsr & MACSR_RT) {
801         /* 32-bit rounding.  */
802         rem = val & 0xff;
803         val >>= 8;
804         if (rem > 0x80)
805             val++;
806         else if (rem == 0x80)
807             val += (val & 1);
808     } else {
809         /* No rounding.  */
810         val >>= 8;
811     }
812     if (env->macsr & MACSR_OMC) {
813         /* Saturate.  */
814         if (env->macsr & MACSR_SU) {
815             if (val != (uint16_t) val) {
816                 result = ((val >> 63) ^ 0x7fff) & 0xffff;
817             } else {
818                 result = val & 0xffff;
819             }
820         } else {
821             if (val != (uint32_t)val) {
822                 result = ((uint32_t)(val >> 63) & 0x7fffffff);
823             } else {
824                 result = (uint32_t)val;
825             }
826         }
827     } else {
828         /* No saturation.  */
829         if (env->macsr & MACSR_SU) {
830             result = val & 0xffff;
831         } else {
832             result = (uint32_t)val;
833         }
834     }
835     return result;
836 }
837
838 uint32_t HELPER(get_macs)(uint64_t val)
839 {
840     if (val == (int32_t)val) {
841         return (int32_t)val;
842     } else {
843         return (val >> 61) ^ ~SIGNBIT;
844     }
845 }
846
847 uint32_t HELPER(get_macu)(uint64_t val)
848 {
849     if ((val >> 32) == 0) {
850         return (uint32_t)val;
851     } else {
852         return 0xffffffffu;
853     }
854 }
855
856 uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
857 {
858     uint32_t val;
859     val = env->macc[acc] & 0x00ff;
860     val = (env->macc[acc] >> 32) & 0xff00;
861     val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
862     val |= (env->macc[acc + 1] >> 16) & 0xff000000;
863     return val;
864 }
865
866 uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
867 {
868     uint32_t val;
869     val = (env->macc[acc] >> 32) & 0xffff;
870     val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
871     return val;
872 }
873
874 void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
875 {
876     int64_t res;
877     int32_t tmp;
878     res = env->macc[acc] & 0xffffffff00ull;
879     tmp = (int16_t)(val & 0xff00);
880     res |= ((int64_t)tmp) << 32;
881     res |= val & 0xff;
882     env->macc[acc] = res;
883     res = env->macc[acc + 1] & 0xffffffff00ull;
884     tmp = (val & 0xff000000);
885     res |= ((int64_t)tmp) << 16;
886     res |= (val >> 16) & 0xff;
887     env->macc[acc + 1] = res;
888 }
889
890 void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
891 {
892     int64_t res;
893     int32_t tmp;
894     res = (uint32_t)env->macc[acc];
895     tmp = (int16_t)val;
896     res |= ((int64_t)tmp) << 32;
897     env->macc[acc] = res;
898     res = (uint32_t)env->macc[acc + 1];
899     tmp = val & 0xffff0000;
900     res |= (int64_t)tmp << 16;
901     env->macc[acc + 1] = res;
902 }
903
904 void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
905 {
906     uint64_t res;
907     res = (uint32_t)env->macc[acc];
908     res |= ((uint64_t)(val & 0xffff)) << 32;
909     env->macc[acc] = res;
910     res = (uint32_t)env->macc[acc + 1];
911     res |= (uint64_t)(val & 0xffff0000) << 16;
912     env->macc[acc + 1] = res;
913 }