live migration: Allow cleanup after cancellation or error
[qemu/mdroth.git] / target-m68k / helper.c
blob9f30a7479db9e126a69db2ec4174372c46f4db44
1 /*
2 * m68k op helpers
4 * Copyright (c) 2006-2007 CodeSourcery
5 * Written by Paul Brook
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.
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.
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/>.
21 #include <stdio.h>
22 #include <string.h>
24 #include "config.h"
25 #include "cpu.h"
26 #include "exec-all.h"
27 #include "qemu-common.h"
28 #include "gdbstub.h"
30 #include "helpers.h"
32 #define SIGNBIT (1u << 31)
34 enum m68k_cpuid {
35 M68K_CPUID_M5206,
36 M68K_CPUID_M5208,
37 M68K_CPUID_CFV4E,
38 M68K_CPUID_ANY,
41 typedef struct m68k_def_t m68k_def_t;
43 struct m68k_def_t {
44 const char * name;
45 enum m68k_cpuid id;
48 static m68k_def_t m68k_cpu_defs[] = {
49 {"m5206", M68K_CPUID_M5206},
50 {"m5208", M68K_CPUID_M5208},
51 {"cfv4e", M68K_CPUID_CFV4E},
52 {"any", M68K_CPUID_ANY},
53 {NULL, 0},
56 void m68k_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
58 unsigned int i;
60 for (i = 0; m68k_cpu_defs[i].name; i++) {
61 (*cpu_fprintf)(f, "%s\n", m68k_cpu_defs[i].name);
65 static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
67 if (n < 8) {
68 stfq_p(mem_buf, env->fregs[n]);
69 return 8;
71 if (n < 11) {
72 /* FP control registers (not implemented) */
73 memset(mem_buf, 0, 4);
74 return 4;
76 return 0;
79 static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
81 if (n < 8) {
82 env->fregs[n] = ldfq_p(mem_buf);
83 return 8;
85 if (n < 11) {
86 /* FP control registers (not implemented) */
87 return 4;
89 return 0;
92 static void m68k_set_feature(CPUM68KState *env, int feature)
94 env->features |= (1u << feature);
97 static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
99 m68k_def_t *def;
101 for (def = m68k_cpu_defs; def->name; def++) {
102 if (strcmp(def->name, name) == 0)
103 break;
105 if (!def->name)
106 return -1;
108 switch (def->id) {
109 case M68K_CPUID_M5206:
110 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
111 break;
112 case M68K_CPUID_M5208:
113 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
114 m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
115 m68k_set_feature(env, M68K_FEATURE_BRAL);
116 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
117 m68k_set_feature(env, M68K_FEATURE_USP);
118 break;
119 case M68K_CPUID_CFV4E:
120 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
121 m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
122 m68k_set_feature(env, M68K_FEATURE_BRAL);
123 m68k_set_feature(env, M68K_FEATURE_CF_FPU);
124 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
125 m68k_set_feature(env, M68K_FEATURE_USP);
126 break;
127 case M68K_CPUID_ANY:
128 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
129 m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
130 m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
131 m68k_set_feature(env, M68K_FEATURE_BRAL);
132 m68k_set_feature(env, M68K_FEATURE_CF_FPU);
133 /* MAC and EMAC are mututally exclusive, so pick EMAC.
134 It's mostly backwards compatible. */
135 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
136 m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
137 m68k_set_feature(env, M68K_FEATURE_USP);
138 m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
139 m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
140 break;
143 register_m68k_insns(env);
144 if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
145 gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
146 11, "cf-fp.xml", 18);
148 /* TODO: Add [E]MAC registers. */
149 return 0;
152 void cpu_reset(CPUM68KState *env)
154 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
155 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
156 log_cpu_state(env, 0);
159 memset(env, 0, offsetof(CPUM68KState, breakpoints));
160 #if !defined (CONFIG_USER_ONLY)
161 env->sr = 0x2700;
162 #endif
163 m68k_switch_sp(env);
164 /* ??? FP regs should be initialized to NaN. */
165 env->cc_op = CC_OP_FLAGS;
166 /* TODO: We should set PC from the interrupt vector. */
167 env->pc = 0;
168 tlb_flush(env, 1);
171 CPUM68KState *cpu_m68k_init(const char *cpu_model)
173 CPUM68KState *env;
174 static int inited;
176 env = qemu_mallocz(sizeof(CPUM68KState));
177 cpu_exec_init(env);
178 if (!inited) {
179 inited = 1;
180 m68k_tcg_init();
183 env->cpu_model_str = cpu_model;
185 if (cpu_m68k_set_model(env, cpu_model) < 0) {
186 cpu_m68k_close(env);
187 return NULL;
190 cpu_reset(env);
191 qemu_init_vcpu(env);
192 return env;
195 void cpu_m68k_close(CPUM68KState *env)
197 qemu_free(env);
200 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
202 int flags;
203 uint32_t src;
204 uint32_t dest;
205 uint32_t tmp;
207 #define HIGHBIT 0x80000000u
209 #define SET_NZ(x) do { \
210 if ((x) == 0) \
211 flags |= CCF_Z; \
212 else if ((int32_t)(x) < 0) \
213 flags |= CCF_N; \
214 } while (0)
216 #define SET_FLAGS_SUB(type, utype) do { \
217 SET_NZ((type)dest); \
218 tmp = dest + src; \
219 if ((utype) tmp < (utype) src) \
220 flags |= CCF_C; \
221 if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
222 flags |= CCF_V; \
223 } while (0)
225 flags = 0;
226 src = env->cc_src;
227 dest = env->cc_dest;
228 switch (cc_op) {
229 case CC_OP_FLAGS:
230 flags = dest;
231 break;
232 case CC_OP_LOGIC:
233 SET_NZ(dest);
234 break;
235 case CC_OP_ADD:
236 SET_NZ(dest);
237 if (dest < src)
238 flags |= CCF_C;
239 tmp = dest - src;
240 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
241 flags |= CCF_V;
242 break;
243 case CC_OP_SUB:
244 SET_FLAGS_SUB(int32_t, uint32_t);
245 break;
246 case CC_OP_CMPB:
247 SET_FLAGS_SUB(int8_t, uint8_t);
248 break;
249 case CC_OP_CMPW:
250 SET_FLAGS_SUB(int16_t, uint16_t);
251 break;
252 case CC_OP_ADDX:
253 SET_NZ(dest);
254 if (dest <= src)
255 flags |= CCF_C;
256 tmp = dest - src - 1;
257 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
258 flags |= CCF_V;
259 break;
260 case CC_OP_SUBX:
261 SET_NZ(dest);
262 tmp = dest + src + 1;
263 if (tmp <= src)
264 flags |= CCF_C;
265 if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
266 flags |= CCF_V;
267 break;
268 case CC_OP_SHIFT:
269 SET_NZ(dest);
270 if (src)
271 flags |= CCF_C;
272 break;
273 default:
274 cpu_abort(env, "Bad CC_OP %d", cc_op);
276 env->cc_op = CC_OP_FLAGS;
277 env->cc_dest = flags;
280 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
282 switch (reg) {
283 case 0x02: /* CACR */
284 env->cacr = val;
285 m68k_switch_sp(env);
286 break;
287 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
288 /* TODO: Implement Access Control Registers. */
289 break;
290 case 0x801: /* VBR */
291 env->vbr = val;
292 break;
293 /* TODO: Implement control registers. */
294 default:
295 cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
296 reg, val);
300 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
302 uint32_t acc;
303 int8_t exthigh;
304 uint8_t extlow;
305 uint64_t regval;
306 int i;
307 if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
308 for (i = 0; i < 4; i++) {
309 regval = env->macc[i];
310 exthigh = regval >> 40;
311 if (env->macsr & MACSR_FI) {
312 acc = regval >> 8;
313 extlow = regval;
314 } else {
315 acc = regval;
316 extlow = regval >> 32;
318 if (env->macsr & MACSR_FI) {
319 regval = (((uint64_t)acc) << 8) | extlow;
320 regval |= ((int64_t)exthigh) << 40;
321 } else if (env->macsr & MACSR_SU) {
322 regval = acc | (((int64_t)extlow) << 32);
323 regval |= ((int64_t)exthigh) << 40;
324 } else {
325 regval = acc | (((uint64_t)extlow) << 32);
326 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
328 env->macc[i] = regval;
331 env->macsr = val;
334 void m68k_switch_sp(CPUM68KState *env)
336 int new_sp;
338 env->sp[env->current_sp] = env->aregs[7];
339 new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
340 ? M68K_SSP : M68K_USP;
341 env->aregs[7] = env->sp[new_sp];
342 env->current_sp = new_sp;
345 /* MMU */
347 /* TODO: This will need fixing once the MMU is implemented. */
348 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
350 return addr;
353 #if defined(CONFIG_USER_ONLY)
355 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
356 int mmu_idx, int is_softmmu)
358 env->exception_index = EXCP_ACCESS;
359 env->mmu.ar = address;
360 return 1;
363 #else
365 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
366 int mmu_idx, int is_softmmu)
368 int prot;
370 address &= TARGET_PAGE_MASK;
371 prot = PAGE_READ | PAGE_WRITE;
372 return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
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)
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);
389 #endif
391 uint32_t HELPER(bitrev)(uint32_t x)
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);
399 uint32_t HELPER(ff1)(uint32_t x)
401 int n;
402 for (n = 32; x; n--)
403 x >>= 1;
404 return n;
407 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
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;
415 uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
417 uint32_t res;
418 uint32_t old_flags;
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;
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;
438 uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
440 uint32_t res;
441 uint32_t old_flags;
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;
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;
461 uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
463 return a < b;
466 void HELPER(set_sr)(CPUState *env, uint32_t val)
468 env->sr = val & 0xffff;
469 m68k_switch_sp(env);
472 uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
474 uint32_t result;
475 uint32_t cf;
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;
491 env->cc_src = cf;
492 env->cc_x = (cf != 0);
493 env->cc_dest = result;
494 return result;
497 uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
499 uint32_t result;
500 uint32_t cf;
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;
516 env->cc_src = cf;
517 env->cc_x = (cf != 0);
518 env->cc_dest = result;
519 return result;
522 uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
524 uint32_t result;
525 uint32_t cf;
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;
538 env->cc_src = cf;
539 env->cc_x = cf;
540 env->cc_dest = result;
541 return result;
544 /* FPU helpers. */
545 uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
547 return float64_to_int32(val, &env->fp_status);
550 float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
552 return float64_to_float32(val, &env->fp_status);
555 float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
557 return int32_to_float64(val, &env->fp_status);
560 float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
562 return float32_to_float64(val, &env->fp_status);
565 float64 HELPER(iround_f64)(CPUState *env, float64 val)
567 return float64_round_to_int(val, &env->fp_status);
570 float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
572 return float64_trunc_to_int(val, &env->fp_status);
575 float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
577 return float64_sqrt(val, &env->fp_status);
580 float64 HELPER(abs_f64)(float64 val)
582 return float64_abs(val);
585 float64 HELPER(chs_f64)(float64 val)
587 return float64_chs(val);
590 float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
592 return float64_add(a, b, &env->fp_status);
595 float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
597 return float64_sub(a, b, &env->fp_status);
600 float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
602 return float64_mul(a, b, &env->fp_status);
605 float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
607 return float64_div(a, b, &env->fp_status);
610 float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
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_nan(res)) {
617 /* +/-inf compares equal against itself, but sub returns nan. */
618 if (!float64_is_nan(a)
619 && !float64_is_nan(b)) {
620 res = float64_zero;
621 if (float64_lt_quiet(a, res, &env->fp_status))
622 res = float64_chs(res);
625 return res;
628 uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
630 return float64_compare_quiet(val, float64_zero, &env->fp_status);
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)
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;
648 uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
650 int64_t product;
651 int64_t res;
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;
665 return res;
668 uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
670 uint64_t product;
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);
682 return product;
685 uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
687 uint64_t product;
688 uint32_t remainder;
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;
701 return product;
704 void HELPER(macsats)(CPUState *env, uint32_t acc)
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;
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 occuring
717 at 48 bits. Seems weird, but that's what the hardware docs
718 say. */
719 result = (result >> 63) ^ 0x7fffffff;
722 env->macc[acc] = result;
725 void HELPER(macsatu)(CPUState *env, uint32_t acc)
727 uint64_t val;
729 val = env->macc[acc];
730 if (val & (0xffffull << 48)) {
731 env->macsr |= MACSR_V;
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);
744 env->macc[acc] = val;
747 void HELPER(macsatf)(CPUState *env, uint32_t acc)
749 int64_t sum;
750 int64_t result;
752 sum = env->macc[acc];
753 result = (sum << 16) >> 16;
754 if (result != sum) {
755 env->macsr |= MACSR_V;
757 if (env->macsr & MACSR_V) {
758 env->macsr |= MACSR_PAV0 << acc;
759 if (env->macsr & MACSR_OMC) {
760 result = (result >> 63) ^ 0x7fffffffffffll;
763 env->macc[acc] = result;
766 void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
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 if (env->macsr & (MACSR_PAV0 << acc)) {
775 env->macsr |= MACSR_V;
777 if (env->macsr & MACSR_FI) {
778 val = ((int64_t)val) >> 40;
779 if (val != 0 && val != -1)
780 env->macsr |= MACSR_EV;
781 } else if (env->macsr & MACSR_SU) {
782 val = ((int64_t)val) >> 32;
783 if (val != 0 && val != -1)
784 env->macsr |= MACSR_EV;
785 } else {
786 if ((val >> 32) != 0)
787 env->macsr |= MACSR_EV;
791 void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
793 cpu_m68k_flush_flags(env, cc_op);
796 uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
798 int rem;
799 uint32_t result;
801 if (env->macsr & MACSR_SU) {
802 /* 16-bit rounding. */
803 rem = val & 0xffffff;
804 val = (val >> 24) & 0xffffu;
805 if (rem > 0x800000)
806 val++;
807 else if (rem == 0x800000)
808 val += (val & 1);
809 } else if (env->macsr & MACSR_RT) {
810 /* 32-bit rounding. */
811 rem = val & 0xff;
812 val >>= 8;
813 if (rem > 0x80)
814 val++;
815 else if (rem == 0x80)
816 val += (val & 1);
817 } else {
818 /* No rounding. */
819 val >>= 8;
821 if (env->macsr & MACSR_OMC) {
822 /* Saturate. */
823 if (env->macsr & MACSR_SU) {
824 if (val != (uint16_t) val) {
825 result = ((val >> 63) ^ 0x7fff) & 0xffff;
826 } else {
827 result = val & 0xffff;
829 } else {
830 if (val != (uint32_t)val) {
831 result = ((uint32_t)(val >> 63) & 0x7fffffff);
832 } else {
833 result = (uint32_t)val;
836 } else {
837 /* No saturation. */
838 if (env->macsr & MACSR_SU) {
839 result = val & 0xffff;
840 } else {
841 result = (uint32_t)val;
844 return result;
847 uint32_t HELPER(get_macs)(uint64_t val)
849 if (val == (int32_t)val) {
850 return (int32_t)val;
851 } else {
852 return (val >> 61) ^ ~SIGNBIT;
856 uint32_t HELPER(get_macu)(uint64_t val)
858 if ((val >> 32) == 0) {
859 return (uint32_t)val;
860 } else {
861 return 0xffffffffu;
865 uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
867 uint32_t val;
868 val = env->macc[acc] & 0x00ff;
869 val = (env->macc[acc] >> 32) & 0xff00;
870 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
871 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
872 return val;
875 uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
877 uint32_t val;
878 val = (env->macc[acc] >> 32) & 0xffff;
879 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
880 return val;
883 void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
885 int64_t res;
886 int32_t tmp;
887 res = env->macc[acc] & 0xffffffff00ull;
888 tmp = (int16_t)(val & 0xff00);
889 res |= ((int64_t)tmp) << 32;
890 res |= val & 0xff;
891 env->macc[acc] = res;
892 res = env->macc[acc + 1] & 0xffffffff00ull;
893 tmp = (val & 0xff000000);
894 res |= ((int64_t)tmp) << 16;
895 res |= (val >> 16) & 0xff;
896 env->macc[acc + 1] = res;
899 void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
901 int64_t res;
902 int32_t tmp;
903 res = (uint32_t)env->macc[acc];
904 tmp = (int16_t)val;
905 res |= ((int64_t)tmp) << 32;
906 env->macc[acc] = res;
907 res = (uint32_t)env->macc[acc + 1];
908 tmp = val & 0xffff0000;
909 res |= (int64_t)tmp << 16;
910 env->macc[acc + 1] = res;
913 void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
915 uint64_t res;
916 res = (uint32_t)env->macc[acc];
917 res |= ((uint64_t)(val & 0xffff)) << 32;
918 env->macc[acc] = res;
919 res = (uint32_t)env->macc[acc + 1];
920 res |= (uint64_t)(val & 0xffff0000) << 16;
921 env->macc[acc + 1] = res;