xref: /illumos-kvm-cmd/target-m68k/helper.c (revision 68396ea9)
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 <stdio.h>
22 #include <string.h>
23 
24 #include "config.h"
25 #include "cpu.h"
26 #include "exec-all.h"
27 #include "qemu-common.h"
28 #include "gdbstub.h"
29 
30 #include "helpers.h"
31 
32 #define SIGNBIT (1u << 31)
33 
34 enum m68k_cpuid {
35     M68K_CPUID_M5206,
36     M68K_CPUID_M5208,
37     M68K_CPUID_CFV4E,
38     M68K_CPUID_ANY,
39 };
40 
41 typedef struct m68k_def_t m68k_def_t;
42 
43 struct m68k_def_t {
44     const char * name;
45     enum m68k_cpuid id;
46 };
47 
48 static m68k_def_t m68k_cpu_defs[] = {
49     {"m5206", M68K_CPUID_M5206},
50     {"m5208", M68K_CPUID_M5208},
51     {"cfv4e", M68K_CPUID_CFV4E},
52     {"any", M68K_CPUID_ANY},
53     {NULL, 0},
54 };
55 
m68k_cpu_list(FILE * f,fprintf_function cpu_fprintf)56 void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
57 {
58     unsigned int i;
59 
60     for (i = 0; m68k_cpu_defs[i].name; i++) {
61         (*cpu_fprintf)(f, "%s\n", m68k_cpu_defs[i].name);
62     }
63 }
64 
fpu_gdb_get_reg(CPUState * env,uint8_t * mem_buf,int n)65 static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
66 {
67     if (n < 8) {
68         stfq_p(mem_buf, env->fregs[n]);
69         return 8;
70     }
71     if (n < 11) {
72         /* FP control registers (not implemented)  */
73         memset(mem_buf, 0, 4);
74         return 4;
75     }
76     return 0;
77 }
78 
fpu_gdb_set_reg(CPUState * env,uint8_t * mem_buf,int n)79 static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
80 {
81     if (n < 8) {
82         env->fregs[n] = ldfq_p(mem_buf);
83         return 8;
84     }
85     if (n < 11) {
86         /* FP control registers (not implemented)  */
87         return 4;
88     }
89     return 0;
90 }
91 
m68k_set_feature(CPUM68KState * env,int feature)92 static void m68k_set_feature(CPUM68KState *env, int feature)
93 {
94     env->features |= (1u << feature);
95 }
96 
cpu_m68k_set_model(CPUM68KState * env,const char * name)97 static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
98 {
99     m68k_def_t *def;
100 
101     for (def = m68k_cpu_defs; def->name; def++) {
102         if (strcmp(def->name, name) == 0)
103             break;
104     }
105     if (!def->name)
106         return -1;
107 
108     switch (def->id) {
109     case M68K_CPUID_M5206:
110         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
111         break;
112     case M68K_CPUID_M5208:
113         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
114         m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
115         m68k_set_feature(env, M68K_FEATURE_BRAL);
116         m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
117         m68k_set_feature(env, M68K_FEATURE_USP);
118         break;
119     case M68K_CPUID_CFV4E:
120         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
121         m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
122         m68k_set_feature(env, M68K_FEATURE_BRAL);
123         m68k_set_feature(env, M68K_FEATURE_CF_FPU);
124         m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
125         m68k_set_feature(env, M68K_FEATURE_USP);
126         break;
127     case M68K_CPUID_ANY:
128         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
129         m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
130         m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
131         m68k_set_feature(env, M68K_FEATURE_BRAL);
132         m68k_set_feature(env, M68K_FEATURE_CF_FPU);
133         /* MAC and EMAC are mututally exclusive, so pick EMAC.
134            It's mostly backwards compatible.  */
135         m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
136         m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
137         m68k_set_feature(env, M68K_FEATURE_USP);
138         m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
139         m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
140         break;
141     }
142 
143     register_m68k_insns(env);
144     if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
145         gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
146                                  11, "cf-fp.xml", 18);
147     }
148     /* TODO: Add [E]MAC registers.  */
149     return 0;
150 }
151 
cpu_reset(CPUM68KState * env)152 void cpu_reset(CPUM68KState *env)
153 {
154     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
155         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
156         log_cpu_state(env, 0);
157     }
158 
159     memset(env, 0, offsetof(CPUM68KState, breakpoints));
160 #if !defined (CONFIG_USER_ONLY)
161     env->sr = 0x2700;
162 #endif
163     m68k_switch_sp(env);
164     /* ??? FP regs should be initialized to NaN.  */
165     env->cc_op = CC_OP_FLAGS;
166     /* TODO: We should set PC from the interrupt vector.  */
167     env->pc = 0;
168     tlb_flush(env, 1);
169 }
170 
cpu_m68k_init(const char * cpu_model)171 CPUM68KState *cpu_m68k_init(const char *cpu_model)
172 {
173     CPUM68KState *env;
174     static int inited;
175 
176     env = qemu_mallocz(sizeof(CPUM68KState));
177     cpu_exec_init(env);
178     if (!inited) {
179         inited = 1;
180         m68k_tcg_init();
181     }
182 
183     env->cpu_model_str = cpu_model;
184 
185     if (cpu_m68k_set_model(env, cpu_model) < 0) {
186         cpu_m68k_close(env);
187         return NULL;
188     }
189 
190     cpu_reset(env);
191     qemu_init_vcpu(env);
192     return env;
193 }
194 
cpu_m68k_close(CPUM68KState * env)195 void cpu_m68k_close(CPUM68KState *env)
196 {
197     qemu_free(env);
198 }
199 
cpu_m68k_flush_flags(CPUM68KState * env,int cc_op)200 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
201 {
202     int flags;
203     uint32_t src;
204     uint32_t dest;
205     uint32_t tmp;
206 
207 #define HIGHBIT 0x80000000u
208 
209 #define SET_NZ(x) do { \
210     if ((x) == 0) \
211         flags |= CCF_Z; \
212     else if ((int32_t)(x) < 0) \
213         flags |= CCF_N; \
214     } while (0)
215 
216 #define SET_FLAGS_SUB(type, utype) do { \
217     SET_NZ((type)dest); \
218     tmp = dest + src; \
219     if ((utype) tmp < (utype) src) \
220         flags |= CCF_C; \
221     if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
222         flags |= CCF_V; \
223     } while (0)
224 
225     flags = 0;
226     src = env->cc_src;
227     dest = env->cc_dest;
228     switch (cc_op) {
229     case CC_OP_FLAGS:
230         flags = dest;
231         break;
232     case CC_OP_LOGIC:
233         SET_NZ(dest);
234         break;
235     case CC_OP_ADD:
236         SET_NZ(dest);
237         if (dest < src)
238             flags |= CCF_C;
239         tmp = dest - src;
240         if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
241             flags |= CCF_V;
242         break;
243     case CC_OP_SUB:
244         SET_FLAGS_SUB(int32_t, uint32_t);
245         break;
246     case CC_OP_CMPB:
247         SET_FLAGS_SUB(int8_t, uint8_t);
248         break;
249     case CC_OP_CMPW:
250         SET_FLAGS_SUB(int16_t, uint16_t);
251         break;
252     case CC_OP_ADDX:
253         SET_NZ(dest);
254         if (dest <= src)
255             flags |= CCF_C;
256         tmp = dest - src - 1;
257         if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
258             flags |= CCF_V;
259         break;
260     case CC_OP_SUBX:
261         SET_NZ(dest);
262         tmp = dest + src + 1;
263         if (tmp <= src)
264             flags |= CCF_C;
265         if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
266             flags |= CCF_V;
267         break;
268     case CC_OP_SHIFT:
269         SET_NZ(dest);
270         if (src)
271             flags |= CCF_C;
272         break;
273     default:
274         cpu_abort(env, "Bad CC_OP %d", cc_op);
275     }
276     env->cc_op = CC_OP_FLAGS;
277     env->cc_dest = flags;
278 }
279 
HELPER(movec)280 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
281 {
282     switch (reg) {
283     case 0x02: /* CACR */
284         env->cacr = val;
285         m68k_switch_sp(env);
286         break;
287     case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
288         /* TODO: Implement Access Control Registers.  */
289         break;
290     case 0x801: /* VBR */
291         env->vbr = val;
292         break;
293     /* TODO: Implement control registers.  */
294     default:
295         cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
296                   reg, val);
297     }
298 }
299 
HELPER(set_macsr)300 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
301 {
302     uint32_t acc;
303     int8_t exthigh;
304     uint8_t extlow;
305     uint64_t regval;
306     int i;
307     if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
308         for (i = 0; i < 4; i++) {
309             regval = env->macc[i];
310             exthigh = regval >> 40;
311             if (env->macsr & MACSR_FI) {
312                 acc = regval >> 8;
313                 extlow = regval;
314             } else {
315                 acc = regval;
316                 extlow = regval >> 32;
317             }
318             if (env->macsr & MACSR_FI) {
319                 regval = (((uint64_t)acc) << 8) | extlow;
320                 regval |= ((int64_t)exthigh) << 40;
321             } else if (env->macsr & MACSR_SU) {
322                 regval = acc | (((int64_t)extlow) << 32);
323                 regval |= ((int64_t)exthigh) << 40;
324             } else {
325                 regval = acc | (((uint64_t)extlow) << 32);
326                 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
327             }
328             env->macc[i] = regval;
329         }
330     }
331     env->macsr = val;
332 }
333 
m68k_switch_sp(CPUM68KState * env)334 void m68k_switch_sp(CPUM68KState *env)
335 {
336     int new_sp;
337 
338     env->sp[env->current_sp] = env->aregs[7];
339     new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
340              ? M68K_SSP : M68K_USP;
341     env->aregs[7] = env->sp[new_sp];
342     env->current_sp = new_sp;
343 }
344 
345 #if defined(CONFIG_USER_ONLY)
346 
cpu_m68k_handle_mmu_fault(CPUState * env,target_ulong address,int rw,int mmu_idx,int is_softmmu)347 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
348                                int mmu_idx, int is_softmmu)
349 {
350     env->exception_index = EXCP_ACCESS;
351     env->mmu.ar = address;
352     return 1;
353 }
354 
355 #else
356 
357 /* MMU */
358 
359 /* TODO: This will need fixing once the MMU is implemented.  */
cpu_get_phys_page_debug(CPUState * env,target_ulong addr)360 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
361 {
362     return addr;
363 }
364 
cpu_m68k_handle_mmu_fault(CPUState * env,target_ulong address,int rw,int mmu_idx,int is_softmmu)365 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
366                                int mmu_idx, int is_softmmu)
367 {
368     int prot;
369 
370     address &= TARGET_PAGE_MASK;
371     prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
372     tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
373     return 0;
374 }
375 
376 /* Notify CPU of a pending interrupt.  Prioritization and vectoring should
377    be handled by the interrupt controller.  Real hardware only requests
378    the vector when the interrupt is acknowledged by the CPU.  For
379    simplicitly we calculate it when the interrupt is signalled.  */
m68k_set_irq_level(CPUM68KState * env,int level,uint8_t vector)380 void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
381 {
382     env->pending_level = level;
383     env->pending_vector = vector;
384     if (level)
385         cpu_interrupt(env, CPU_INTERRUPT_HARD);
386     else
387         cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
388 }
389 
390 #endif
391 
HELPER(bitrev)392 uint32_t HELPER(bitrev)(uint32_t x)
393 {
394     x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
395     x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
396     x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
397     return bswap32(x);
398 }
399 
HELPER(ff1)400 uint32_t HELPER(ff1)(uint32_t x)
401 {
402     int n;
403     for (n = 32; x; n--)
404         x >>= 1;
405     return n;
406 }
407 
HELPER(sats)408 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
409 {
410     /* The result has the opposite sign to the original value.  */
411     if (ccr & CCF_V)
412         val = (((int32_t)val) >> 31) ^ SIGNBIT;
413     return val;
414 }
415 
HELPER(subx_cc)416 uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
417 {
418     uint32_t res;
419     uint32_t old_flags;
420 
421     old_flags = env->cc_dest;
422     if (env->cc_x) {
423         env->cc_x = (op1 <= op2);
424         env->cc_op = CC_OP_SUBX;
425         res = op1 - (op2 + 1);
426     } else {
427         env->cc_x = (op1 < op2);
428         env->cc_op = CC_OP_SUB;
429         res = op1 - op2;
430     }
431     env->cc_dest = res;
432     env->cc_src = op2;
433     cpu_m68k_flush_flags(env, env->cc_op);
434     /* !Z is sticky.  */
435     env->cc_dest &= (old_flags | ~CCF_Z);
436     return res;
437 }
438 
HELPER(addx_cc)439 uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
440 {
441     uint32_t res;
442     uint32_t old_flags;
443 
444     old_flags = env->cc_dest;
445     if (env->cc_x) {
446         res = op1 + op2 + 1;
447         env->cc_x = (res <= op2);
448         env->cc_op = CC_OP_ADDX;
449     } else {
450         res = op1 + op2;
451         env->cc_x = (res < op2);
452         env->cc_op = CC_OP_ADD;
453     }
454     env->cc_dest = res;
455     env->cc_src = op2;
456     cpu_m68k_flush_flags(env, env->cc_op);
457     /* !Z is sticky.  */
458     env->cc_dest &= (old_flags | ~CCF_Z);
459     return res;
460 }
461 
HELPER(xflag_lt)462 uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
463 {
464     return a < b;
465 }
466 
HELPER(set_sr)467 void HELPER(set_sr)(CPUState *env, uint32_t val)
468 {
469     env->sr = val & 0xffff;
470     m68k_switch_sp(env);
471 }
472 
HELPER(shl_cc)473 uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
474 {
475     uint32_t result;
476     uint32_t cf;
477 
478     shift &= 63;
479     if (shift == 0) {
480         result = val;
481         cf = env->cc_src & CCF_C;
482     } else if (shift < 32) {
483         result = val << shift;
484         cf = (val >> (32 - shift)) & 1;
485     } else if (shift == 32) {
486         result = 0;
487         cf = val & 1;
488     } else /* shift > 32 */ {
489         result = 0;
490         cf = 0;
491     }
492     env->cc_src = cf;
493     env->cc_x = (cf != 0);
494     env->cc_dest = result;
495     return result;
496 }
497 
HELPER(shr_cc)498 uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
499 {
500     uint32_t result;
501     uint32_t cf;
502 
503     shift &= 63;
504     if (shift == 0) {
505         result = val;
506         cf = env->cc_src & CCF_C;
507     } else if (shift < 32) {
508         result = val >> shift;
509         cf = (val >> (shift - 1)) & 1;
510     } else if (shift == 32) {
511         result = 0;
512         cf = val >> 31;
513     } else /* shift > 32 */ {
514         result = 0;
515         cf = 0;
516     }
517     env->cc_src = cf;
518     env->cc_x = (cf != 0);
519     env->cc_dest = result;
520     return result;
521 }
522 
HELPER(sar_cc)523 uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
524 {
525     uint32_t result;
526     uint32_t cf;
527 
528     shift &= 63;
529     if (shift == 0) {
530         result = val;
531         cf = (env->cc_src & CCF_C) != 0;
532     } else if (shift < 32) {
533         result = (int32_t)val >> shift;
534         cf = (val >> (shift - 1)) & 1;
535     } else /* shift >= 32 */ {
536         result = (int32_t)val >> 31;
537         cf = val >> 31;
538     }
539     env->cc_src = cf;
540     env->cc_x = cf;
541     env->cc_dest = result;
542     return result;
543 }
544 
545 /* FPU helpers.  */
HELPER(f64_to_i32)546 uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
547 {
548     return float64_to_int32(val, &env->fp_status);
549 }
550 
HELPER(f64_to_f32)551 float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
552 {
553     return float64_to_float32(val, &env->fp_status);
554 }
555 
HELPER(i32_to_f64)556 float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
557 {
558     return int32_to_float64(val, &env->fp_status);
559 }
560 
HELPER(f32_to_f64)561 float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
562 {
563     return float32_to_float64(val, &env->fp_status);
564 }
565 
HELPER(iround_f64)566 float64 HELPER(iround_f64)(CPUState *env, float64 val)
567 {
568     return float64_round_to_int(val, &env->fp_status);
569 }
570 
HELPER(itrunc_f64)571 float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
572 {
573     return float64_trunc_to_int(val, &env->fp_status);
574 }
575 
HELPER(sqrt_f64)576 float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
577 {
578     return float64_sqrt(val, &env->fp_status);
579 }
580 
HELPER(abs_f64)581 float64 HELPER(abs_f64)(float64 val)
582 {
583     return float64_abs(val);
584 }
585 
HELPER(chs_f64)586 float64 HELPER(chs_f64)(float64 val)
587 {
588     return float64_chs(val);
589 }
590 
HELPER(add_f64)591 float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
592 {
593     return float64_add(a, b, &env->fp_status);
594 }
595 
HELPER(sub_f64)596 float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
597 {
598     return float64_sub(a, b, &env->fp_status);
599 }
600 
HELPER(mul_f64)601 float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
602 {
603     return float64_mul(a, b, &env->fp_status);
604 }
605 
HELPER(div_f64)606 float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
607 {
608     return float64_div(a, b, &env->fp_status);
609 }
610 
HELPER(sub_cmp_f64)611 float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
612 {
613     /* ??? This may incorrectly raise exceptions.  */
614     /* ??? Should flush denormals to zero.  */
615     float64 res;
616     res = float64_sub(a, b, &env->fp_status);
617     if (float64_is_quiet_nan(res)) {
618         /* +/-inf compares equal against itself, but sub returns nan.  */
619         if (!float64_is_quiet_nan(a)
620             && !float64_is_quiet_nan(b)) {
621             res = float64_zero;
622             if (float64_lt_quiet(a, res, &env->fp_status))
623                 res = float64_chs(res);
624         }
625     }
626     return res;
627 }
628 
HELPER(compare_f64)629 uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
630 {
631     return float64_compare_quiet(val, float64_zero, &env->fp_status);
632 }
633 
634 /* MAC unit.  */
635 /* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
636    take values,  others take register numbers and manipulate the contents
637    in-place.  */
HELPER(mac_move)638 void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
639 {
640     uint32_t mask;
641     env->macc[dest] = env->macc[src];
642     mask = MACSR_PAV0 << dest;
643     if (env->macsr & (MACSR_PAV0 << src))
644         env->macsr |= mask;
645     else
646         env->macsr &= ~mask;
647 }
648 
HELPER(macmuls)649 uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
650 {
651     int64_t product;
652     int64_t res;
653 
654     product = (uint64_t)op1 * op2;
655     res = (product << 24) >> 24;
656     if (res != product) {
657         env->macsr |= MACSR_V;
658         if (env->macsr & MACSR_OMC) {
659             /* Make sure the accumulate operation overflows.  */
660             if (product < 0)
661                 res = ~(1ll << 50);
662             else
663                 res = 1ll << 50;
664         }
665     }
666     return res;
667 }
668 
HELPER(macmulu)669 uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
670 {
671     uint64_t product;
672 
673     product = (uint64_t)op1 * op2;
674     if (product & (0xffffffull << 40)) {
675         env->macsr |= MACSR_V;
676         if (env->macsr & MACSR_OMC) {
677             /* Make sure the accumulate operation overflows.  */
678             product = 1ll << 50;
679         } else {
680             product &= ((1ull << 40) - 1);
681         }
682     }
683     return product;
684 }
685 
HELPER(macmulf)686 uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
687 {
688     uint64_t product;
689     uint32_t remainder;
690 
691     product = (uint64_t)op1 * op2;
692     if (env->macsr & MACSR_RT) {
693         remainder = product & 0xffffff;
694         product >>= 24;
695         if (remainder > 0x800000)
696             product++;
697         else if (remainder == 0x800000)
698             product += (product & 1);
699     } else {
700         product >>= 24;
701     }
702     return product;
703 }
704 
HELPER(macsats)705 void HELPER(macsats)(CPUState *env, uint32_t acc)
706 {
707     int64_t tmp;
708     int64_t result;
709     tmp = env->macc[acc];
710     result = ((tmp << 16) >> 16);
711     if (result != tmp) {
712         env->macsr |= MACSR_V;
713     }
714     if (env->macsr & MACSR_V) {
715         env->macsr |= MACSR_PAV0 << acc;
716         if (env->macsr & MACSR_OMC) {
717             /* The result is saturated to 32 bits, despite overflow occuring
718                at 48 bits.  Seems weird, but that's what the hardware docs
719                say.  */
720             result = (result >> 63) ^ 0x7fffffff;
721         }
722     }
723     env->macc[acc] = result;
724 }
725 
HELPER(macsatu)726 void HELPER(macsatu)(CPUState *env, uint32_t acc)
727 {
728     uint64_t val;
729 
730     val = env->macc[acc];
731     if (val & (0xffffull << 48)) {
732         env->macsr |= MACSR_V;
733     }
734     if (env->macsr & MACSR_V) {
735         env->macsr |= MACSR_PAV0 << acc;
736         if (env->macsr & MACSR_OMC) {
737             if (val > (1ull << 53))
738                 val = 0;
739             else
740                 val = (1ull << 48) - 1;
741         } else {
742             val &= ((1ull << 48) - 1);
743         }
744     }
745     env->macc[acc] = val;
746 }
747 
HELPER(macsatf)748 void HELPER(macsatf)(CPUState *env, uint32_t acc)
749 {
750     int64_t sum;
751     int64_t result;
752 
753     sum = env->macc[acc];
754     result = (sum << 16) >> 16;
755     if (result != sum) {
756         env->macsr |= MACSR_V;
757     }
758     if (env->macsr & MACSR_V) {
759         env->macsr |= MACSR_PAV0 << acc;
760         if (env->macsr & MACSR_OMC) {
761             result = (result >> 63) ^ 0x7fffffffffffll;
762         }
763     }
764     env->macc[acc] = result;
765 }
766 
HELPER(mac_set_flags)767 void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
768 {
769     uint64_t val;
770     val = env->macc[acc];
771     if (val == 0) {
772         env->macsr |= MACSR_Z;
773     } else if (val & (1ull << 47)) {
774         env->macsr |= MACSR_N;
775     }
776     if (env->macsr & (MACSR_PAV0 << acc)) {
777         env->macsr |= MACSR_V;
778     }
779     if (env->macsr & MACSR_FI) {
780         val = ((int64_t)val) >> 40;
781         if (val != 0 && val != -1)
782             env->macsr |= MACSR_EV;
783     } else if (env->macsr & MACSR_SU) {
784         val = ((int64_t)val) >> 32;
785         if (val != 0 && val != -1)
786             env->macsr |= MACSR_EV;
787     } else {
788         if ((val >> 32) != 0)
789             env->macsr |= MACSR_EV;
790     }
791 }
792 
HELPER(flush_flags)793 void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
794 {
795     cpu_m68k_flush_flags(env, cc_op);
796 }
797 
HELPER(get_macf)798 uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
799 {
800     int rem;
801     uint32_t result;
802 
803     if (env->macsr & MACSR_SU) {
804         /* 16-bit rounding.  */
805         rem = val & 0xffffff;
806         val = (val >> 24) & 0xffffu;
807         if (rem > 0x800000)
808             val++;
809         else if (rem == 0x800000)
810             val += (val & 1);
811     } else if (env->macsr & MACSR_RT) {
812         /* 32-bit rounding.  */
813         rem = val & 0xff;
814         val >>= 8;
815         if (rem > 0x80)
816             val++;
817         else if (rem == 0x80)
818             val += (val & 1);
819     } else {
820         /* No rounding.  */
821         val >>= 8;
822     }
823     if (env->macsr & MACSR_OMC) {
824         /* Saturate.  */
825         if (env->macsr & MACSR_SU) {
826             if (val != (uint16_t) val) {
827                 result = ((val >> 63) ^ 0x7fff) & 0xffff;
828             } else {
829                 result = val & 0xffff;
830             }
831         } else {
832             if (val != (uint32_t)val) {
833                 result = ((uint32_t)(val >> 63) & 0x7fffffff);
834             } else {
835                 result = (uint32_t)val;
836             }
837         }
838     } else {
839         /* No saturation.  */
840         if (env->macsr & MACSR_SU) {
841             result = val & 0xffff;
842         } else {
843             result = (uint32_t)val;
844         }
845     }
846     return result;
847 }
848 
HELPER(get_macs)849 uint32_t HELPER(get_macs)(uint64_t val)
850 {
851     if (val == (int32_t)val) {
852         return (int32_t)val;
853     } else {
854         return (val >> 61) ^ ~SIGNBIT;
855     }
856 }
857 
HELPER(get_macu)858 uint32_t HELPER(get_macu)(uint64_t val)
859 {
860     if ((val >> 32) == 0) {
861         return (uint32_t)val;
862     } else {
863         return 0xffffffffu;
864     }
865 }
866 
HELPER(get_mac_extf)867 uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
868 {
869     uint32_t val;
870     val = env->macc[acc] & 0x00ff;
871     val = (env->macc[acc] >> 32) & 0xff00;
872     val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
873     val |= (env->macc[acc + 1] >> 16) & 0xff000000;
874     return val;
875 }
876 
HELPER(get_mac_exti)877 uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
878 {
879     uint32_t val;
880     val = (env->macc[acc] >> 32) & 0xffff;
881     val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
882     return val;
883 }
884 
HELPER(set_mac_extf)885 void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
886 {
887     int64_t res;
888     int32_t tmp;
889     res = env->macc[acc] & 0xffffffff00ull;
890     tmp = (int16_t)(val & 0xff00);
891     res |= ((int64_t)tmp) << 32;
892     res |= val & 0xff;
893     env->macc[acc] = res;
894     res = env->macc[acc + 1] & 0xffffffff00ull;
895     tmp = (val & 0xff000000);
896     res |= ((int64_t)tmp) << 16;
897     res |= (val >> 16) & 0xff;
898     env->macc[acc + 1] = res;
899 }
900 
HELPER(set_mac_exts)901 void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
902 {
903     int64_t res;
904     int32_t tmp;
905     res = (uint32_t)env->macc[acc];
906     tmp = (int16_t)val;
907     res |= ((int64_t)tmp) << 32;
908     env->macc[acc] = res;
909     res = (uint32_t)env->macc[acc + 1];
910     tmp = val & 0xffff0000;
911     res |= (int64_t)tmp << 16;
912     env->macc[acc + 1] = res;
913 }
914 
HELPER(set_mac_extu)915 void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
916 {
917     uint64_t res;
918     res = (uint32_t)env->macc[acc];
919     res |= ((uint64_t)(val & 0xffff)) << 32;
920     env->macc[acc] = res;
921     res = (uint32_t)env->macc[acc + 1];
922     res |= (uint64_t)(val & 0xffff0000) << 16;
923     env->macc[acc + 1] = res;
924 }
925