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