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