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