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