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