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