kvm: user: include arch specific headers from $(KERNELDIR)
[qemu-kvm/fedora.git] / target-m68k / helper.c
blob7eb21ddd3d702650f8f3deeae7052e5365eccb5b
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 cpu_exec_init(env);
170 if (!inited) {
171 inited = 1;
172 m68k_tcg_init();
175 env->cpu_model_str = cpu_model;
177 if (cpu_m68k_set_model(env, cpu_model) < 0) {
178 cpu_m68k_close(env);
179 return NULL;
182 cpu_reset(env);
183 return env;
186 void cpu_m68k_close(CPUM68KState *env)
188 qemu_free(env);
191 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
193 int flags;
194 uint32_t src;
195 uint32_t dest;
196 uint32_t tmp;
198 #define HIGHBIT 0x80000000u
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)
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)
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;
259 case CC_OP_SHIFT:
260 SET_NZ(dest);
261 if (src)
262 flags |= CCF_C;
263 break;
264 default:
265 cpu_abort(env, "Bad CC_OP %d", cc_op);
267 env->cc_op = CC_OP_FLAGS;
268 env->cc_dest = flags;
271 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
273 switch (reg) {
274 case 0x02: /* CACR */
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. */
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);
291 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
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;
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;
319 env->macc[i] = regval;
322 env->macsr = val;
325 void m68k_switch_sp(CPUM68KState *env)
327 int new_sp;
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;
336 /* MMU */
338 /* TODO: This will need fixing once the MMU is implemented. */
339 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
341 return addr;
344 #if defined(CONFIG_USER_ONLY)
346 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
347 int mmu_idx, int is_softmmu)
349 env->exception_index = EXCP_ACCESS;
350 env->mmu.ar = address;
351 return 1;
354 #else
356 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
357 int mmu_idx, int is_softmmu)
359 int prot;
361 address &= TARGET_PAGE_MASK;
362 prot = PAGE_READ | PAGE_WRITE;
363 return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
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. */
370 void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
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);
380 #endif
382 uint32_t HELPER(bitrev)(uint32_t x)
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);
390 uint32_t HELPER(ff1)(uint32_t x)
392 int n;
393 for (n = 32; x; n--)
394 x >>= 1;
395 return n;
398 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
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;
406 uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
408 uint32_t res;
409 uint32_t old_flags;
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;
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;
429 uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
431 uint32_t res;
432 uint32_t old_flags;
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;
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;
452 uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
454 return a < b;
457 uint32_t HELPER(btest)(uint32_t x)
459 return x != 0;
462 void HELPER(set_sr)(CPUState *env, uint32_t val)
464 env->sr = val & 0xffff;
465 m68k_switch_sp(env);
468 uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
470 uint32_t result;
471 uint32_t cf;
473 shift &= 63;
474 if (shift == 0) {
475 result = val;
476 cf = env->cc_src & CCF_C;
477 } else if (shift < 32) {
478 result = val << shift;
479 cf = (val >> (32 - shift)) & 1;
480 } else if (shift == 32) {
481 result = 0;
482 cf = val & 1;
483 } else /* shift > 32 */ {
484 result = 0;
485 cf = 0;
487 env->cc_src = cf;
488 env->cc_x = (cf != 0);
489 env->cc_dest = result;
490 return result;
493 uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
495 uint32_t result;
496 uint32_t cf;
498 shift &= 63;
499 if (shift == 0) {
500 result = val;
501 cf = env->cc_src & CCF_C;
502 } else if (shift < 32) {
503 result = val >> shift;
504 cf = (val >> (shift - 1)) & 1;
505 } else if (shift == 32) {
506 result = 0;
507 cf = val >> 31;
508 } else /* shift > 32 */ {
509 result = 0;
510 cf = 0;
512 env->cc_src = cf;
513 env->cc_x = (cf != 0);
514 env->cc_dest = result;
515 return result;
518 uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
520 uint32_t result;
521 uint32_t cf;
523 shift &= 63;
524 if (shift == 0) {
525 result = val;
526 cf = (env->cc_src & CCF_C) != 0;
527 } else if (shift < 32) {
528 result = (int32_t)val >> shift;
529 cf = (val >> (shift - 1)) & 1;
530 } else /* shift >= 32 */ {
531 result = (int32_t)val >> 31;
532 cf = val >> 31;
534 env->cc_src = cf;
535 env->cc_x = cf;
536 env->cc_dest = result;
537 return result;
540 /* FPU helpers. */
541 uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
543 return float64_to_int32(val, &env->fp_status);
546 float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
548 return float64_to_float32(val, &env->fp_status);
551 float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
553 return int32_to_float64(val, &env->fp_status);
556 float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
558 return float32_to_float64(val, &env->fp_status);
561 float64 HELPER(iround_f64)(CPUState *env, float64 val)
563 return float64_round_to_int(val, &env->fp_status);
566 float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
568 return float64_trunc_to_int(val, &env->fp_status);
571 float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
573 return float64_sqrt(val, &env->fp_status);
576 float64 HELPER(abs_f64)(float64 val)
578 return float64_abs(val);
581 float64 HELPER(chs_f64)(float64 val)
583 return float64_chs(val);
586 float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
588 return float64_add(a, b, &env->fp_status);
591 float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
593 return float64_sub(a, b, &env->fp_status);
596 float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
598 return float64_mul(a, b, &env->fp_status);
601 float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
603 return float64_div(a, b, &env->fp_status);
606 float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
608 /* ??? This may incorrectly raise exceptions. */
609 /* ??? Should flush denormals to zero. */
610 float64 res;
611 res = float64_sub(a, b, &env->fp_status);
612 if (float64_is_nan(res)) {
613 /* +/-inf compares equal against itself, but sub returns nan. */
614 if (!float64_is_nan(a)
615 && !float64_is_nan(b)) {
616 res = float64_zero;
617 if (float64_lt_quiet(a, res, &env->fp_status))
618 res = float64_chs(res);
621 return res;
624 uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
626 return float64_compare_quiet(val, float64_zero, &env->fp_status);
629 /* MAC unit. */
630 /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
631 take values, others take register numbers and manipulate the contents
632 in-place. */
633 void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
635 uint32_t mask;
636 env->macc[dest] = env->macc[src];
637 mask = MACSR_PAV0 << dest;
638 if (env->macsr & (MACSR_PAV0 << src))
639 env->macsr |= mask;
640 else
641 env->macsr &= ~mask;
644 uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
646 int64_t product;
647 int64_t res;
649 product = (uint64_t)op1 * op2;
650 res = (product << 24) >> 24;
651 if (res != product) {
652 env->macsr |= MACSR_V;
653 if (env->macsr & MACSR_OMC) {
654 /* Make sure the accumulate operation overflows. */
655 if (product < 0)
656 res = ~(1ll << 50);
657 else
658 res = 1ll << 50;
661 return res;
664 uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
666 uint64_t product;
668 product = (uint64_t)op1 * op2;
669 if (product & (0xffffffull << 40)) {
670 env->macsr |= MACSR_V;
671 if (env->macsr & MACSR_OMC) {
672 /* Make sure the accumulate operation overflows. */
673 product = 1ll << 50;
674 } else {
675 product &= ((1ull << 40) - 1);
678 return product;
681 uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
683 uint64_t product;
684 uint32_t remainder;
686 product = (uint64_t)op1 * op2;
687 if (env->macsr & MACSR_RT) {
688 remainder = product & 0xffffff;
689 product >>= 24;
690 if (remainder > 0x800000)
691 product++;
692 else if (remainder == 0x800000)
693 product += (product & 1);
694 } else {
695 product >>= 24;
697 return product;
700 void HELPER(macsats)(CPUState *env, uint32_t acc)
702 int64_t tmp;
703 int64_t result;
704 tmp = env->macc[acc];
705 result = ((tmp << 16) >> 16);
706 if (result != tmp) {
707 env->macsr |= MACSR_V;
709 if (env->macsr & MACSR_V) {
710 env->macsr |= MACSR_PAV0 << acc;
711 if (env->macsr & MACSR_OMC) {
712 /* The result is saturated to 32 bits, despite overflow occuring
713 at 48 bits. Seems weird, but that's what the hardware docs
714 say. */
715 result = (result >> 63) ^ 0x7fffffff;
718 env->macc[acc] = result;
721 void HELPER(macsatu)(CPUState *env, uint32_t acc)
723 uint64_t val;
725 val = env->macc[acc];
726 if (val & (0xffffull << 48)) {
727 env->macsr |= MACSR_V;
729 if (env->macsr & MACSR_V) {
730 env->macsr |= MACSR_PAV0 << acc;
731 if (env->macsr & MACSR_OMC) {
732 if (val > (1ull << 53))
733 val = 0;
734 else
735 val = (1ull << 48) - 1;
736 } else {
737 val &= ((1ull << 48) - 1);
740 env->macc[acc] = val;
743 void HELPER(macsatf)(CPUState *env, uint32_t acc)
745 int64_t sum;
746 int64_t result;
748 sum = env->macc[acc];
749 result = (sum << 16) >> 16;
750 if (result != sum) {
751 env->macsr |= MACSR_V;
753 if (env->macsr & MACSR_V) {
754 env->macsr |= MACSR_PAV0 << acc;
755 if (env->macsr & MACSR_OMC) {
756 result = (result >> 63) ^ 0x7fffffffffffll;
759 env->macc[acc] = result;
762 void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
764 uint64_t val;
765 val = env->macc[acc];
766 if (val == 0)
767 env->macsr |= MACSR_Z;
768 else if (val & (1ull << 47));
769 env->macsr |= MACSR_N;
770 if (env->macsr & (MACSR_PAV0 << acc)) {
771 env->macsr |= MACSR_V;
773 if (env->macsr & MACSR_FI) {
774 val = ((int64_t)val) >> 40;
775 if (val != 0 && val != -1)
776 env->macsr |= MACSR_EV;
777 } else if (env->macsr & MACSR_SU) {
778 val = ((int64_t)val) >> 32;
779 if (val != 0 && val != -1)
780 env->macsr |= MACSR_EV;
781 } else {
782 if ((val >> 32) != 0)
783 env->macsr |= MACSR_EV;
787 void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
789 cpu_m68k_flush_flags(env, cc_op);
792 uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
794 int rem;
795 uint32_t result;
797 if (env->macsr & MACSR_SU) {
798 /* 16-bit rounding. */
799 rem = val & 0xffffff;
800 val = (val >> 24) & 0xffffu;
801 if (rem > 0x800000)
802 val++;
803 else if (rem == 0x800000)
804 val += (val & 1);
805 } else if (env->macsr & MACSR_RT) {
806 /* 32-bit rounding. */
807 rem = val & 0xff;
808 val >>= 8;
809 if (rem > 0x80)
810 val++;
811 else if (rem == 0x80)
812 val += (val & 1);
813 } else {
814 /* No rounding. */
815 val >>= 8;
817 if (env->macsr & MACSR_OMC) {
818 /* Saturate. */
819 if (env->macsr & MACSR_SU) {
820 if (val != (uint16_t) val) {
821 result = ((val >> 63) ^ 0x7fff) & 0xffff;
822 } else {
823 result = val & 0xffff;
825 } else {
826 if (val != (uint32_t)val) {
827 result = ((uint32_t)(val >> 63) & 0x7fffffff);
828 } else {
829 result = (uint32_t)val;
832 } else {
833 /* No saturation. */
834 if (env->macsr & MACSR_SU) {
835 result = val & 0xffff;
836 } else {
837 result = (uint32_t)val;
840 return result;
843 uint32_t HELPER(get_macs)(uint64_t val)
845 if (val == (int32_t)val) {
846 return (int32_t)val;
847 } else {
848 return (val >> 61) ^ ~SIGNBIT;
852 uint32_t HELPER(get_macu)(uint64_t val)
854 if ((val >> 32) == 0) {
855 return (uint32_t)val;
856 } else {
857 return 0xffffffffu;
861 uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
863 uint32_t val;
864 val = env->macc[acc] & 0x00ff;
865 val = (env->macc[acc] >> 32) & 0xff00;
866 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
867 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
868 return val;
871 uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
873 uint32_t val;
874 val = (env->macc[acc] >> 32) & 0xffff;
875 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
876 return val;
879 void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
881 int64_t res;
882 int32_t tmp;
883 res = env->macc[acc] & 0xffffffff00ull;
884 tmp = (int16_t)(val & 0xff00);
885 res |= ((int64_t)tmp) << 32;
886 res |= val & 0xff;
887 env->macc[acc] = res;
888 res = env->macc[acc + 1] & 0xffffffff00ull;
889 tmp = (val & 0xff000000);
890 res |= ((int64_t)tmp) << 16;
891 res |= (val >> 16) & 0xff;
892 env->macc[acc + 1] = res;
895 void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
897 int64_t res;
898 int32_t tmp;
899 res = (uint32_t)env->macc[acc];
900 tmp = (int16_t)val;
901 res |= ((int64_t)tmp) << 32;
902 env->macc[acc] = res;
903 res = (uint32_t)env->macc[acc + 1];
904 tmp = val & 0xffff0000;
905 res |= (int64_t)tmp << 16;
906 env->macc[acc + 1] = res;
909 void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
911 uint64_t res;
912 res = (uint32_t)env->macc[acc];
913 res |= ((uint64_t)(val & 0xffff)) << 32;
914 env->macc[acc] = res;
915 res = (uint32_t)env->macc[acc + 1];
916 res |= (uint64_t)(val & 0xffff0000) << 16;
917 env->macc[acc + 1] = res;