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