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