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