OSDN Git Service

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