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