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