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