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