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