net: add checking device state before run command
[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 "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 uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
288 {
289     uint64_t result;
290
291     shift &= 63;
292     result = (uint64_t)val << shift;
293
294     env->cc_c = (result >> 32) & 1;
295     env->cc_n = result;
296     env->cc_z = result;
297     env->cc_v = 0;
298     env->cc_x = shift ? env->cc_c : env->cc_x;
299
300     return result;
301 }
302
303 uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
304 {
305     uint64_t temp;
306     uint32_t result;
307
308     shift &= 63;
309     temp = (uint64_t)val << 32 >> shift;
310     result = temp >> 32;
311
312     env->cc_c = (temp >> 31) & 1;
313     env->cc_n = result;
314     env->cc_z = result;
315     env->cc_v = 0;
316     env->cc_x = shift ? env->cc_c : env->cc_x;
317
318     return result;
319 }
320
321 uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
322 {
323     uint64_t temp;
324     uint32_t result;
325
326     shift &= 63;
327     temp = (int64_t)val << 32 >> shift;
328     result = temp >> 32;
329
330     env->cc_c = (temp >> 31) & 1;
331     env->cc_n = result;
332     env->cc_z = result;
333     env->cc_v = result ^ val;
334     env->cc_x = shift ? env->cc_c : env->cc_x;
335
336     return result;
337 }
338
339 /* FPU helpers.  */
340 uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
341 {
342     return float64_to_int32(val, &env->fp_status);
343 }
344
345 float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
346 {
347     return float64_to_float32(val, &env->fp_status);
348 }
349
350 float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
351 {
352     return int32_to_float64(val, &env->fp_status);
353 }
354
355 float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
356 {
357     return float32_to_float64(val, &env->fp_status);
358 }
359
360 float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
361 {
362     return float64_round_to_int(val, &env->fp_status);
363 }
364
365 float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
366 {
367     return float64_trunc_to_int(val, &env->fp_status);
368 }
369
370 float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val)
371 {
372     return float64_sqrt(val, &env->fp_status);
373 }
374
375 float64 HELPER(abs_f64)(float64 val)
376 {
377     return float64_abs(val);
378 }
379
380 float64 HELPER(chs_f64)(float64 val)
381 {
382     return float64_chs(val);
383 }
384
385 float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b)
386 {
387     return float64_add(a, b, &env->fp_status);
388 }
389
390 float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
391 {
392     return float64_sub(a, b, &env->fp_status);
393 }
394
395 float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
396 {
397     return float64_mul(a, b, &env->fp_status);
398 }
399
400 float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
401 {
402     return float64_div(a, b, &env->fp_status);
403 }
404
405 float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b)
406 {
407     /* ??? This may incorrectly raise exceptions.  */
408     /* ??? Should flush denormals to zero.  */
409     float64 res;
410     res = float64_sub(a, b, &env->fp_status);
411     if (float64_is_quiet_nan(res, &env->fp_status)) {
412         /* +/-inf compares equal against itself, but sub returns nan.  */
413         if (!float64_is_quiet_nan(a, &env->fp_status)
414             && !float64_is_quiet_nan(b, &env->fp_status)) {
415             res = float64_zero;
416             if (float64_lt_quiet(a, res, &env->fp_status))
417                 res = float64_chs(res);
418         }
419     }
420     return res;
421 }
422
423 uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val)
424 {
425     return float64_compare_quiet(val, float64_zero, &env->fp_status);
426 }
427
428 /* MAC unit.  */
429 /* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
430    take values,  others take register numbers and manipulate the contents
431    in-place.  */
432 void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
433 {
434     uint32_t mask;
435     env->macc[dest] = env->macc[src];
436     mask = MACSR_PAV0 << dest;
437     if (env->macsr & (MACSR_PAV0 << src))
438         env->macsr |= mask;
439     else
440         env->macsr &= ~mask;
441 }
442
443 uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
444 {
445     int64_t product;
446     int64_t res;
447
448     product = (uint64_t)op1 * op2;
449     res = (product << 24) >> 24;
450     if (res != product) {
451         env->macsr |= MACSR_V;
452         if (env->macsr & MACSR_OMC) {
453             /* Make sure the accumulate operation overflows.  */
454             if (product < 0)
455                 res = ~(1ll << 50);
456             else
457                 res = 1ll << 50;
458         }
459     }
460     return res;
461 }
462
463 uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
464 {
465     uint64_t product;
466
467     product = (uint64_t)op1 * op2;
468     if (product & (0xffffffull << 40)) {
469         env->macsr |= MACSR_V;
470         if (env->macsr & MACSR_OMC) {
471             /* Make sure the accumulate operation overflows.  */
472             product = 1ll << 50;
473         } else {
474             product &= ((1ull << 40) - 1);
475         }
476     }
477     return product;
478 }
479
480 uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
481 {
482     uint64_t product;
483     uint32_t remainder;
484
485     product = (uint64_t)op1 * op2;
486     if (env->macsr & MACSR_RT) {
487         remainder = product & 0xffffff;
488         product >>= 24;
489         if (remainder > 0x800000)
490             product++;
491         else if (remainder == 0x800000)
492             product += (product & 1);
493     } else {
494         product >>= 24;
495     }
496     return product;
497 }
498
499 void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
500 {
501     int64_t tmp;
502     int64_t result;
503     tmp = env->macc[acc];
504     result = ((tmp << 16) >> 16);
505     if (result != tmp) {
506         env->macsr |= MACSR_V;
507     }
508     if (env->macsr & MACSR_V) {
509         env->macsr |= MACSR_PAV0 << acc;
510         if (env->macsr & MACSR_OMC) {
511             /* The result is saturated to 32 bits, despite overflow occurring
512                at 48 bits.  Seems weird, but that's what the hardware docs
513                say.  */
514             result = (result >> 63) ^ 0x7fffffff;
515         }
516     }
517     env->macc[acc] = result;
518 }
519
520 void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
521 {
522     uint64_t val;
523
524     val = env->macc[acc];
525     if (val & (0xffffull << 48)) {
526         env->macsr |= MACSR_V;
527     }
528     if (env->macsr & MACSR_V) {
529         env->macsr |= MACSR_PAV0 << acc;
530         if (env->macsr & MACSR_OMC) {
531             if (val > (1ull << 53))
532                 val = 0;
533             else
534                 val = (1ull << 48) - 1;
535         } else {
536             val &= ((1ull << 48) - 1);
537         }
538     }
539     env->macc[acc] = val;
540 }
541
542 void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
543 {
544     int64_t sum;
545     int64_t result;
546
547     sum = env->macc[acc];
548     result = (sum << 16) >> 16;
549     if (result != sum) {
550         env->macsr |= MACSR_V;
551     }
552     if (env->macsr & MACSR_V) {
553         env->macsr |= MACSR_PAV0 << acc;
554         if (env->macsr & MACSR_OMC) {
555             result = (result >> 63) ^ 0x7fffffffffffll;
556         }
557     }
558     env->macc[acc] = result;
559 }
560
561 void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
562 {
563     uint64_t val;
564     val = env->macc[acc];
565     if (val == 0) {
566         env->macsr |= MACSR_Z;
567     } else if (val & (1ull << 47)) {
568         env->macsr |= MACSR_N;
569     }
570     if (env->macsr & (MACSR_PAV0 << acc)) {
571         env->macsr |= MACSR_V;
572     }
573     if (env->macsr & MACSR_FI) {
574         val = ((int64_t)val) >> 40;
575         if (val != 0 && val != -1)
576             env->macsr |= MACSR_EV;
577     } else if (env->macsr & MACSR_SU) {
578         val = ((int64_t)val) >> 32;
579         if (val != 0 && val != -1)
580             env->macsr |= MACSR_EV;
581     } else {
582         if ((val >> 32) != 0)
583             env->macsr |= MACSR_EV;
584     }
585 }
586
587 #define EXTSIGN(val, index) (     \
588     (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \
589 )
590
591 #define COMPUTE_CCR(op, x, n, z, v, c) {                                   \
592     switch (op) {                                                          \
593     case CC_OP_FLAGS:                                                      \
594         /* Everything in place.  */                                        \
595         break;                                                             \
596     case CC_OP_ADDB:                                                       \
597     case CC_OP_ADDW:                                                       \
598     case CC_OP_ADDL:                                                       \
599         res = n;                                                           \
600         src2 = v;                                                          \
601         src1 = EXTSIGN(res - src2, op - CC_OP_ADDB);                       \
602         c = x;                                                             \
603         z = n;                                                             \
604         v = (res ^ src1) & ~(src1 ^ src2);                                 \
605         break;                                                             \
606     case CC_OP_SUBB:                                                       \
607     case CC_OP_SUBW:                                                       \
608     case CC_OP_SUBL:                                                       \
609         res = n;                                                           \
610         src2 = v;                                                          \
611         src1 = EXTSIGN(res + src2, op - CC_OP_SUBB);                       \
612         c = x;                                                             \
613         z = n;                                                             \
614         v = (res ^ src1) & (src1 ^ src2);                                  \
615         break;                                                             \
616     case CC_OP_CMPB:                                                       \
617     case CC_OP_CMPW:                                                       \
618     case CC_OP_CMPL:                                                       \
619         src1 = n;                                                          \
620         src2 = v;                                                          \
621         res = EXTSIGN(src1 - src2, op - CC_OP_CMPB);                       \
622         n = res;                                                           \
623         z = res;                                                           \
624         c = src1 < src2;                                                   \
625         v = (res ^ src1) & (src1 ^ src2);                                  \
626         break;                                                             \
627     case CC_OP_LOGIC:                                                      \
628         c = v = 0;                                                         \
629         z = n;                                                             \
630         break;                                                             \
631     default:                                                               \
632         cpu_abort(CPU(m68k_env_get_cpu(env)), "Bad CC_OP %d", op);         \
633     }                                                                      \
634 } while (0)
635
636 uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
637 {
638     uint32_t x, c, n, z, v;
639     uint32_t res, src1, src2;
640
641     x = env->cc_x;
642     n = env->cc_n;
643     z = env->cc_z;
644     v = env->cc_v;
645     c = env->cc_c;
646
647     COMPUTE_CCR(env->cc_op, x, n, z, v, c);
648
649     n = n >> 31;
650     z = (z == 0);
651     v = v >> 31;
652
653     return x * CCF_X + n * CCF_N + z * CCF_Z + v * CCF_V + c * CCF_C;
654 }
655
656 uint32_t HELPER(get_ccr)(CPUM68KState *env)
657 {
658     return cpu_m68k_get_ccr(env);
659 }
660
661 void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t ccr)
662 {
663     env->cc_x = (ccr & CCF_X ? 1 : 0);
664     env->cc_n = (ccr & CCF_N ? -1 : 0);
665     env->cc_z = (ccr & CCF_Z ? 0 : 1);
666     env->cc_v = (ccr & CCF_V ? -1 : 0);
667     env->cc_c = (ccr & CCF_C ? 1 : 0);
668     env->cc_op = CC_OP_FLAGS;
669 }
670
671 void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr)
672 {
673     cpu_m68k_set_ccr(env, ccr);
674 }
675
676 void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
677 {
678     uint32_t res, src1, src2;
679
680     COMPUTE_CCR(cc_op, env->cc_x, env->cc_n, env->cc_z, env->cc_v, env->cc_c);
681     env->cc_op = CC_OP_FLAGS;
682 }
683
684 uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
685 {
686     int rem;
687     uint32_t result;
688
689     if (env->macsr & MACSR_SU) {
690         /* 16-bit rounding.  */
691         rem = val & 0xffffff;
692         val = (val >> 24) & 0xffffu;
693         if (rem > 0x800000)
694             val++;
695         else if (rem == 0x800000)
696             val += (val & 1);
697     } else if (env->macsr & MACSR_RT) {
698         /* 32-bit rounding.  */
699         rem = val & 0xff;
700         val >>= 8;
701         if (rem > 0x80)
702             val++;
703         else if (rem == 0x80)
704             val += (val & 1);
705     } else {
706         /* No rounding.  */
707         val >>= 8;
708     }
709     if (env->macsr & MACSR_OMC) {
710         /* Saturate.  */
711         if (env->macsr & MACSR_SU) {
712             if (val != (uint16_t) val) {
713                 result = ((val >> 63) ^ 0x7fff) & 0xffff;
714             } else {
715                 result = val & 0xffff;
716             }
717         } else {
718             if (val != (uint32_t)val) {
719                 result = ((uint32_t)(val >> 63) & 0x7fffffff);
720             } else {
721                 result = (uint32_t)val;
722             }
723         }
724     } else {
725         /* No saturation.  */
726         if (env->macsr & MACSR_SU) {
727             result = val & 0xffff;
728         } else {
729             result = (uint32_t)val;
730         }
731     }
732     return result;
733 }
734
735 uint32_t HELPER(get_macs)(uint64_t val)
736 {
737     if (val == (int32_t)val) {
738         return (int32_t)val;
739     } else {
740         return (val >> 61) ^ ~SIGNBIT;
741     }
742 }
743
744 uint32_t HELPER(get_macu)(uint64_t val)
745 {
746     if ((val >> 32) == 0) {
747         return (uint32_t)val;
748     } else {
749         return 0xffffffffu;
750     }
751 }
752
753 uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
754 {
755     uint32_t val;
756     val = env->macc[acc] & 0x00ff;
757     val |= (env->macc[acc] >> 32) & 0xff00;
758     val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
759     val |= (env->macc[acc + 1] >> 16) & 0xff000000;
760     return val;
761 }
762
763 uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
764 {
765     uint32_t val;
766     val = (env->macc[acc] >> 32) & 0xffff;
767     val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
768     return val;
769 }
770
771 void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
772 {
773     int64_t res;
774     int32_t tmp;
775     res = env->macc[acc] & 0xffffffff00ull;
776     tmp = (int16_t)(val & 0xff00);
777     res |= ((int64_t)tmp) << 32;
778     res |= val & 0xff;
779     env->macc[acc] = res;
780     res = env->macc[acc + 1] & 0xffffffff00ull;
781     tmp = (val & 0xff000000);
782     res |= ((int64_t)tmp) << 16;
783     res |= (val >> 16) & 0xff;
784     env->macc[acc + 1] = res;
785 }
786
787 void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
788 {
789     int64_t res;
790     int32_t tmp;
791     res = (uint32_t)env->macc[acc];
792     tmp = (int16_t)val;
793     res |= ((int64_t)tmp) << 32;
794     env->macc[acc] = res;
795     res = (uint32_t)env->macc[acc + 1];
796     tmp = val & 0xffff0000;
797     res |= (int64_t)tmp << 16;
798     env->macc[acc + 1] = res;
799 }
800
801 void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
802 {
803     uint64_t res;
804     res = (uint32_t)env->macc[acc];
805     res |= ((uint64_t)(val & 0xffff)) << 32;
806     env->macc[acc] = res;
807     res = (uint32_t)env->macc[acc + 1];
808     res |= (uint64_t)(val & 0xffff0000) << 16;
809     env->macc[acc + 1] = res;
810 }