kvm: external module: hrtimer_expires_remaining was introduced in 2.6.28
[qemu-kvm/fedora.git] / target-m68k / helper.c
blob076ea353c8004daa5e2ed8dcdb659b2839d637ac
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, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
22 #include <stdio.h>
23 #include <string.h>
25 #include "config.h"
26 #include "cpu.h"
27 #include "exec-all.h"
28 #include "qemu-common.h"
29 #include "gdbstub.h"
31 #include "helpers.h"
33 #define SIGNBIT (1u << 31)
35 enum m68k_cpuid {
36 M68K_CPUID_M5206,
37 M68K_CPUID_M5208,
38 M68K_CPUID_CFV4E,
39 M68K_CPUID_ANY,
42 typedef struct m68k_def_t m68k_def_t;
44 struct m68k_def_t {
45 const char * name;
46 enum m68k_cpuid id;
49 static m68k_def_t m68k_cpu_defs[] = {
50 {"m5206", M68K_CPUID_M5206},
51 {"m5208", M68K_CPUID_M5208},
52 {"cfv4e", M68K_CPUID_CFV4E},
53 {"any", M68K_CPUID_ANY},
54 {NULL, 0},
57 static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
59 if (n < 8) {
60 stfq_p(mem_buf, env->fregs[n]);
61 return 8;
63 if (n < 11) {
64 /* FP control registers (not implemented) */
65 memset(mem_buf, 0, 4);
66 return 4;
68 return 0;
71 static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
73 if (n < 8) {
74 env->fregs[n] = ldfq_p(mem_buf);
75 return 8;
77 if (n < 11) {
78 /* FP control registers (not implemented) */
79 return 4;
81 return 0;
84 static void m68k_set_feature(CPUM68KState *env, int feature)
86 env->features |= (1u << feature);
89 static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
91 m68k_def_t *def;
93 for (def = m68k_cpu_defs; def->name; def++) {
94 if (strcmp(def->name, name) == 0)
95 break;
97 if (!def->name)
98 return -1;
100 switch (def->id) {
101 case M68K_CPUID_M5206:
102 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
103 break;
104 case M68K_CPUID_M5208:
105 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
106 m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
107 m68k_set_feature(env, M68K_FEATURE_BRAL);
108 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
109 m68k_set_feature(env, M68K_FEATURE_USP);
110 break;
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);
114 m68k_set_feature(env, M68K_FEATURE_BRAL);
115 m68k_set_feature(env, M68K_FEATURE_CF_FPU);
116 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
117 m68k_set_feature(env, M68K_FEATURE_USP);
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);
122 m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
123 m68k_set_feature(env, M68K_FEATURE_BRAL);
124 m68k_set_feature(env, M68K_FEATURE_CF_FPU);
125 /* MAC and EMAC are mututally exclusive, so pick EMAC.
126 It's mostly backwards compatible. */
127 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
128 m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
129 m68k_set_feature(env, M68K_FEATURE_USP);
130 m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
131 m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
132 break;
135 register_m68k_insns(env);
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);
140 /* TODO: Add [E]MAC registers. */
141 return 0;
144 void cpu_reset(CPUM68KState *env)
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);
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);
163 CPUM68KState *cpu_m68k_init(const char *cpu_model)
165 CPUM68KState *env;
166 static int inited;
168 env = qemu_mallocz(sizeof(CPUM68KState));
169 if (!env)
170 return NULL;
171 cpu_exec_init(env);
172 if (!inited) {
173 inited = 1;
174 m68k_tcg_init();
177 env->cpu_model_str = cpu_model;
179 if (cpu_m68k_set_model(env, cpu_model) < 0) {
180 cpu_m68k_close(env);
181 return NULL;
184 cpu_reset(env);
185 return env;
188 void cpu_m68k_close(CPUM68KState *env)
190 qemu_free(env);
193 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
195 int flags;
196 uint32_t src;
197 uint32_t dest;
198 uint32_t tmp;
200 #define HIGHBIT 0x80000000u
202 #define SET_NZ(x) do { \
203 if ((x) == 0) \
204 flags |= CCF_Z; \
205 else if ((int32_t)(x) < 0) \
206 flags |= CCF_N; \
207 } while (0)
209 #define SET_FLAGS_SUB(type, utype) do { \
210 SET_NZ((type)dest); \
211 tmp = dest + src; \
212 if ((utype) tmp < (utype) src) \
213 flags |= CCF_C; \
214 if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
215 flags |= CCF_V; \
216 } while (0)
218 flags = 0;
219 src = env->cc_src;
220 dest = env->cc_dest;
221 switch (cc_op) {
222 case CC_OP_FLAGS:
223 flags = dest;
224 break;
225 case CC_OP_LOGIC:
226 SET_NZ(dest);
227 break;
228 case CC_OP_ADD:
229 SET_NZ(dest);
230 if (dest < src)
231 flags |= CCF_C;
232 tmp = dest - src;
233 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
234 flags |= CCF_V;
235 break;
236 case CC_OP_SUB:
237 SET_FLAGS_SUB(int32_t, uint32_t);
238 break;
239 case CC_OP_CMPB:
240 SET_FLAGS_SUB(int8_t, uint8_t);
241 break;
242 case CC_OP_CMPW:
243 SET_FLAGS_SUB(int16_t, uint16_t);
244 break;
245 case CC_OP_ADDX:
246 SET_NZ(dest);
247 if (dest <= src)
248 flags |= CCF_C;
249 tmp = dest - src - 1;
250 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
251 flags |= CCF_V;
252 break;
253 case CC_OP_SUBX:
254 SET_NZ(dest);
255 tmp = dest + src + 1;
256 if (tmp <= src)
257 flags |= CCF_C;
258 if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
259 flags |= CCF_V;
260 break;
261 case CC_OP_SHIFT:
262 SET_NZ(dest);
263 if (src)
264 flags |= CCF_C;
265 break;
266 default:
267 cpu_abort(env, "Bad CC_OP %d", cc_op);
269 env->cc_op = CC_OP_FLAGS;
270 env->cc_dest = flags;
273 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
275 switch (reg) {
276 case 0x02: /* CACR */
277 env->cacr = val;
278 m68k_switch_sp(env);
279 break;
280 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
281 /* TODO: Implement Access Control Registers. */
282 break;
283 case 0x801: /* VBR */
284 env->vbr = val;
285 break;
286 /* TODO: Implement control registers. */
287 default:
288 cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
289 reg, val);
293 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
295 uint32_t acc;
296 int8_t exthigh;
297 uint8_t extlow;
298 uint64_t regval;
299 int i;
300 if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
301 for (i = 0; i < 4; i++) {
302 regval = env->macc[i];
303 exthigh = regval >> 40;
304 if (env->macsr & MACSR_FI) {
305 acc = regval >> 8;
306 extlow = regval;
307 } else {
308 acc = regval;
309 extlow = regval >> 32;
311 if (env->macsr & MACSR_FI) {
312 regval = (((uint64_t)acc) << 8) | extlow;
313 regval |= ((int64_t)exthigh) << 40;
314 } else if (env->macsr & MACSR_SU) {
315 regval = acc | (((int64_t)extlow) << 32);
316 regval |= ((int64_t)exthigh) << 40;
317 } else {
318 regval = acc | (((uint64_t)extlow) << 32);
319 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
321 env->macc[i] = regval;
324 env->macsr = val;
327 void m68k_switch_sp(CPUM68KState *env)
329 int new_sp;
331 env->sp[env->current_sp] = env->aregs[7];
332 new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
333 ? M68K_SSP : M68K_USP;
334 env->aregs[7] = env->sp[new_sp];
335 env->current_sp = new_sp;
338 /* MMU */
340 /* TODO: This will need fixing once the MMU is implemented. */
341 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
343 return addr;
346 #if defined(CONFIG_USER_ONLY)
348 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
349 int mmu_idx, int is_softmmu)
351 env->exception_index = EXCP_ACCESS;
352 env->mmu.ar = address;
353 return 1;
356 #else
358 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
359 int mmu_idx, int is_softmmu)
361 int prot;
363 address &= TARGET_PAGE_MASK;
364 prot = PAGE_READ | PAGE_WRITE;
365 return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
368 /* Notify CPU of a pending interrupt. Prioritization and vectoring should
369 be handled by the interrupt controller. Real hardware only requests
370 the vector when the interrupt is acknowledged by the CPU. For
371 simplicitly we calculate it when the interrupt is signalled. */
372 void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
374 env->pending_level = level;
375 env->pending_vector = vector;
376 if (level)
377 cpu_interrupt(env, CPU_INTERRUPT_HARD);
378 else
379 cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
382 #endif
384 uint32_t HELPER(bitrev)(uint32_t x)
386 x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
387 x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
388 x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
389 return bswap32(x);
392 uint32_t HELPER(ff1)(uint32_t x)
394 int n;
395 for (n = 32; x; n--)
396 x >>= 1;
397 return n;
400 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
402 /* The result has the opposite sign to the original value. */
403 if (ccr & CCF_V)
404 val = (((int32_t)val) >> 31) ^ SIGNBIT;
405 return val;
408 uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
410 uint32_t res;
411 uint32_t old_flags;
413 old_flags = env->cc_dest;
414 if (env->cc_x) {
415 env->cc_x = (op1 <= op2);
416 env->cc_op = CC_OP_SUBX;
417 res = op1 - (op2 + 1);
418 } else {
419 env->cc_x = (op1 < op2);
420 env->cc_op = CC_OP_SUB;
421 res = op1 - op2;
423 env->cc_dest = res;
424 env->cc_src = op2;
425 cpu_m68k_flush_flags(env, env->cc_op);
426 /* !Z is sticky. */
427 env->cc_dest &= (old_flags | ~CCF_Z);
428 return res;
431 uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
433 uint32_t res;
434 uint32_t old_flags;
436 old_flags = env->cc_dest;
437 if (env->cc_x) {
438 res = op1 + op2 + 1;
439 env->cc_x = (res <= op2);
440 env->cc_op = CC_OP_ADDX;
441 } else {
442 res = op1 + op2;
443 env->cc_x = (res < op2);
444 env->cc_op = CC_OP_ADD;
446 env->cc_dest = res;
447 env->cc_src = op2;
448 cpu_m68k_flush_flags(env, env->cc_op);
449 /* !Z is sticky. */
450 env->cc_dest &= (old_flags | ~CCF_Z);
451 return res;
454 uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
456 return a < b;
459 uint32_t HELPER(btest)(uint32_t x)
461 return x != 0;
464 void HELPER(set_sr)(CPUState *env, uint32_t val)
466 env->sr = val & 0xffff;
467 m68k_switch_sp(env);
470 uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
472 uint32_t result;
473 uint32_t cf;
475 shift &= 63;
476 if (shift == 0) {
477 result = val;
478 cf = env->cc_src & CCF_C;
479 } else if (shift < 32) {
480 result = val << shift;
481 cf = (val >> (32 - shift)) & 1;
482 } else if (shift == 32) {
483 result = 0;
484 cf = val & 1;
485 } else /* shift > 32 */ {
486 result = 0;
487 cf = 0;
489 env->cc_src = cf;
490 env->cc_x = (cf != 0);
491 env->cc_dest = result;
492 return result;
495 uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
497 uint32_t result;
498 uint32_t cf;
500 shift &= 63;
501 if (shift == 0) {
502 result = val;
503 cf = env->cc_src & CCF_C;
504 } else if (shift < 32) {
505 result = val >> shift;
506 cf = (val >> (shift - 1)) & 1;
507 } else if (shift == 32) {
508 result = 0;
509 cf = val >> 31;
510 } else /* shift > 32 */ {
511 result = 0;
512 cf = 0;
514 env->cc_src = cf;
515 env->cc_x = (cf != 0);
516 env->cc_dest = result;
517 return result;
520 uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
522 uint32_t result;
523 uint32_t cf;
525 shift &= 63;
526 if (shift == 0) {
527 result = val;
528 cf = (env->cc_src & CCF_C) != 0;
529 } else if (shift < 32) {
530 result = (int32_t)val >> shift;
531 cf = (val >> (shift - 1)) & 1;
532 } else /* shift >= 32 */ {
533 result = (int32_t)val >> 31;
534 cf = val >> 31;
536 env->cc_src = cf;
537 env->cc_x = cf;
538 env->cc_dest = result;
539 return result;
542 /* FPU helpers. */
543 uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
545 return float64_to_int32(val, &env->fp_status);
548 float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
550 return float64_to_float32(val, &env->fp_status);
553 float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
555 return int32_to_float64(val, &env->fp_status);
558 float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
560 return float32_to_float64(val, &env->fp_status);
563 float64 HELPER(iround_f64)(CPUState *env, float64 val)
565 return float64_round_to_int(val, &env->fp_status);
568 float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
570 return float64_trunc_to_int(val, &env->fp_status);
573 float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
575 return float64_sqrt(val, &env->fp_status);
578 float64 HELPER(abs_f64)(float64 val)
580 return float64_abs(val);
583 float64 HELPER(chs_f64)(float64 val)
585 return float64_chs(val);
588 float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
590 return float64_add(a, b, &env->fp_status);
593 float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
595 return float64_sub(a, b, &env->fp_status);
598 float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
600 return float64_mul(a, b, &env->fp_status);
603 float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
605 return float64_div(a, b, &env->fp_status);
608 float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
610 /* ??? This may incorrectly raise exceptions. */
611 /* ??? Should flush denormals to zero. */
612 float64 res;
613 res = float64_sub(a, b, &env->fp_status);
614 if (float64_is_nan(res)) {
615 /* +/-inf compares equal against itself, but sub returns nan. */
616 if (!float64_is_nan(a)
617 && !float64_is_nan(b)) {
618 res = float64_zero;
619 if (float64_lt_quiet(a, res, &env->fp_status))
620 res = float64_chs(res);
623 return res;
626 uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
628 return float64_compare_quiet(val, float64_zero, &env->fp_status);
631 /* MAC unit. */
632 /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
633 take values, others take register numbers and manipulate the contents
634 in-place. */
635 void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
637 uint32_t mask;
638 env->macc[dest] = env->macc[src];
639 mask = MACSR_PAV0 << dest;
640 if (env->macsr & (MACSR_PAV0 << src))
641 env->macsr |= mask;
642 else
643 env->macsr &= ~mask;
646 uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
648 int64_t product;
649 int64_t res;
651 product = (uint64_t)op1 * op2;
652 res = (product << 24) >> 24;
653 if (res != product) {
654 env->macsr |= MACSR_V;
655 if (env->macsr & MACSR_OMC) {
656 /* Make sure the accumulate operation overflows. */
657 if (product < 0)
658 res = ~(1ll << 50);
659 else
660 res = 1ll << 50;
663 return res;
666 uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
668 uint64_t product;
670 product = (uint64_t)op1 * op2;
671 if (product & (0xffffffull << 40)) {
672 env->macsr |= MACSR_V;
673 if (env->macsr & MACSR_OMC) {
674 /* Make sure the accumulate operation overflows. */
675 product = 1ll << 50;
676 } else {
677 product &= ((1ull << 40) - 1);
680 return product;
683 uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
685 uint64_t product;
686 uint32_t remainder;
688 product = (uint64_t)op1 * op2;
689 if (env->macsr & MACSR_RT) {
690 remainder = product & 0xffffff;
691 product >>= 24;
692 if (remainder > 0x800000)
693 product++;
694 else if (remainder == 0x800000)
695 product += (product & 1);
696 } else {
697 product >>= 24;
699 return product;
702 void HELPER(macsats)(CPUState *env, uint32_t acc)
704 int64_t tmp;
705 int64_t result;
706 tmp = env->macc[acc];
707 result = ((tmp << 16) >> 16);
708 if (result != tmp) {
709 env->macsr |= MACSR_V;
711 if (env->macsr & MACSR_V) {
712 env->macsr |= MACSR_PAV0 << acc;
713 if (env->macsr & MACSR_OMC) {
714 /* The result is saturated to 32 bits, despite overflow occuring
715 at 48 bits. Seems weird, but that's what the hardware docs
716 say. */
717 result = (result >> 63) ^ 0x7fffffff;
720 env->macc[acc] = result;
723 void HELPER(macsatu)(CPUState *env, uint32_t acc)
725 uint64_t val;
727 val = env->macc[acc];
728 if (val & (0xffffull << 48)) {
729 env->macsr |= MACSR_V;
731 if (env->macsr & MACSR_V) {
732 env->macsr |= MACSR_PAV0 << acc;
733 if (env->macsr & MACSR_OMC) {
734 if (val > (1ull << 53))
735 val = 0;
736 else
737 val = (1ull << 48) - 1;
738 } else {
739 val &= ((1ull << 48) - 1);
742 env->macc[acc] = val;
745 void HELPER(macsatf)(CPUState *env, uint32_t acc)
747 int64_t sum;
748 int64_t result;
750 sum = env->macc[acc];
751 result = (sum << 16) >> 16;
752 if (result != sum) {
753 env->macsr |= MACSR_V;
755 if (env->macsr & MACSR_V) {
756 env->macsr |= MACSR_PAV0 << acc;
757 if (env->macsr & MACSR_OMC) {
758 result = (result >> 63) ^ 0x7fffffffffffll;
761 env->macc[acc] = result;
764 void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
766 uint64_t val;
767 val = env->macc[acc];
768 if (val == 0)
769 env->macsr |= MACSR_Z;
770 else if (val & (1ull << 47));
771 env->macsr |= MACSR_N;
772 if (env->macsr & (MACSR_PAV0 << acc)) {
773 env->macsr |= MACSR_V;
775 if (env->macsr & MACSR_FI) {
776 val = ((int64_t)val) >> 40;
777 if (val != 0 && val != -1)
778 env->macsr |= MACSR_EV;
779 } else if (env->macsr & MACSR_SU) {
780 val = ((int64_t)val) >> 32;
781 if (val != 0 && val != -1)
782 env->macsr |= MACSR_EV;
783 } else {
784 if ((val >> 32) != 0)
785 env->macsr |= MACSR_EV;
789 void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
791 cpu_m68k_flush_flags(env, cc_op);
794 uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
796 int rem;
797 uint32_t result;
799 if (env->macsr & MACSR_SU) {
800 /* 16-bit rounding. */
801 rem = val & 0xffffff;
802 val = (val >> 24) & 0xffffu;
803 if (rem > 0x800000)
804 val++;
805 else if (rem == 0x800000)
806 val += (val & 1);
807 } else if (env->macsr & MACSR_RT) {
808 /* 32-bit rounding. */
809 rem = val & 0xff;
810 val >>= 8;
811 if (rem > 0x80)
812 val++;
813 else if (rem == 0x80)
814 val += (val & 1);
815 } else {
816 /* No rounding. */
817 val >>= 8;
819 if (env->macsr & MACSR_OMC) {
820 /* Saturate. */
821 if (env->macsr & MACSR_SU) {
822 if (val != (uint16_t) val) {
823 result = ((val >> 63) ^ 0x7fff) & 0xffff;
824 } else {
825 result = val & 0xffff;
827 } else {
828 if (val != (uint32_t)val) {
829 result = ((uint32_t)(val >> 63) & 0x7fffffff);
830 } else {
831 result = (uint32_t)val;
834 } else {
835 /* No saturation. */
836 if (env->macsr & MACSR_SU) {
837 result = val & 0xffff;
838 } else {
839 result = (uint32_t)val;
842 return result;
845 uint32_t HELPER(get_macs)(uint64_t val)
847 if (val == (int32_t)val) {
848 return (int32_t)val;
849 } else {
850 return (val >> 61) ^ ~SIGNBIT;
854 uint32_t HELPER(get_macu)(uint64_t val)
856 if ((val >> 32) == 0) {
857 return (uint32_t)val;
858 } else {
859 return 0xffffffffu;
863 uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
865 uint32_t val;
866 val = env->macc[acc] & 0x00ff;
867 val = (env->macc[acc] >> 32) & 0xff00;
868 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
869 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
870 return val;
873 uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
875 uint32_t val;
876 val = (env->macc[acc] >> 32) & 0xffff;
877 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
878 return val;
881 void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
883 int64_t res;
884 int32_t tmp;
885 res = env->macc[acc] & 0xffffffff00ull;
886 tmp = (int16_t)(val & 0xff00);
887 res |= ((int64_t)tmp) << 32;
888 res |= val & 0xff;
889 env->macc[acc] = res;
890 res = env->macc[acc + 1] & 0xffffffff00ull;
891 tmp = (val & 0xff000000);
892 res |= ((int64_t)tmp) << 16;
893 res |= (val >> 16) & 0xff;
894 env->macc[acc + 1] = res;
897 void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
899 int64_t res;
900 int32_t tmp;
901 res = (uint32_t)env->macc[acc];
902 tmp = (int16_t)val;
903 res |= ((int64_t)tmp) << 32;
904 env->macc[acc] = res;
905 res = (uint32_t)env->macc[acc + 1];
906 tmp = val & 0xffff0000;
907 res |= (int64_t)tmp << 16;
908 env->macc[acc + 1] = res;
911 void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
913 uint64_t res;
914 res = (uint32_t)env->macc[acc];
915 res |= ((uint64_t)(val & 0xffff)) << 32;
916 env->macc[acc] = res;
917 res = (uint32_t)env->macc[acc + 1];
918 res |= (uint64_t)(val & 0xffff0000) << 16;
919 env->macc[acc + 1] = res;