target-mips: use nor instead of or + not
[qemu/mini2440/sniper_sniper_test.git] / target-m68k / helper.c
blob493498e9b4dd7a7490c0095582c01bafb4128492
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 void HELPER(set_sr)(CPUState *env, uint32_t val)
459 env->sr = val & 0xffff;
460 m68k_switch_sp(env);
463 uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
465 uint32_t result;
466 uint32_t cf;
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;
482 env->cc_src = cf;
483 env->cc_x = (cf != 0);
484 env->cc_dest = result;
485 return result;
488 uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
490 uint32_t result;
491 uint32_t cf;
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;
507 env->cc_src = cf;
508 env->cc_x = (cf != 0);
509 env->cc_dest = result;
510 return result;
513 uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
515 uint32_t result;
516 uint32_t cf;
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;
529 env->cc_src = cf;
530 env->cc_x = cf;
531 env->cc_dest = result;
532 return result;
535 /* FPU helpers. */
536 uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
538 return float64_to_int32(val, &env->fp_status);
541 float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
543 return float64_to_float32(val, &env->fp_status);
546 float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
548 return int32_to_float64(val, &env->fp_status);
551 float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
553 return float32_to_float64(val, &env->fp_status);
556 float64 HELPER(iround_f64)(CPUState *env, float64 val)
558 return float64_round_to_int(val, &env->fp_status);
561 float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
563 return float64_trunc_to_int(val, &env->fp_status);
566 float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
568 return float64_sqrt(val, &env->fp_status);
571 float64 HELPER(abs_f64)(float64 val)
573 return float64_abs(val);
576 float64 HELPER(chs_f64)(float64 val)
578 return float64_chs(val);
581 float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
583 return float64_add(a, b, &env->fp_status);
586 float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
588 return float64_sub(a, b, &env->fp_status);
591 float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
593 return float64_mul(a, b, &env->fp_status);
596 float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
598 return float64_div(a, b, &env->fp_status);
601 float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
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);
616 return res;
619 uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
621 return float64_compare_quiet(val, float64_zero, &env->fp_status);
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. */
628 void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
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;
639 uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
641 int64_t product;
642 int64_t res;
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;
656 return res;
659 uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
661 uint64_t product;
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);
673 return product;
676 uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
678 uint64_t product;
679 uint32_t remainder;
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;
692 return product;
695 void HELPER(macsats)(CPUState *env, uint32_t acc)
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;
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;
713 env->macc[acc] = result;
716 void HELPER(macsatu)(CPUState *env, uint32_t acc)
718 uint64_t val;
720 val = env->macc[acc];
721 if (val & (0xffffull << 48)) {
722 env->macsr |= MACSR_V;
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);
735 env->macc[acc] = val;
738 void HELPER(macsatf)(CPUState *env, uint32_t acc)
740 int64_t sum;
741 int64_t result;
743 sum = env->macc[acc];
744 result = (sum << 16) >> 16;
745 if (result != sum) {
746 env->macsr |= MACSR_V;
748 if (env->macsr & MACSR_V) {
749 env->macsr |= MACSR_PAV0 << acc;
750 if (env->macsr & MACSR_OMC) {
751 result = (result >> 63) ^ 0x7fffffffffffll;
754 env->macc[acc] = result;
757 void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
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;
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;
782 void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
784 cpu_m68k_flush_flags(env, cc_op);
787 uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
789 int rem;
790 uint32_t result;
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;
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;
820 } else {
821 if (val != (uint32_t)val) {
822 result = ((uint32_t)(val >> 63) & 0x7fffffff);
823 } else {
824 result = (uint32_t)val;
827 } else {
828 /* No saturation. */
829 if (env->macsr & MACSR_SU) {
830 result = val & 0xffff;
831 } else {
832 result = (uint32_t)val;
835 return result;
838 uint32_t HELPER(get_macs)(uint64_t val)
840 if (val == (int32_t)val) {
841 return (int32_t)val;
842 } else {
843 return (val >> 61) ^ ~SIGNBIT;
847 uint32_t HELPER(get_macu)(uint64_t val)
849 if ((val >> 32) == 0) {
850 return (uint32_t)val;
851 } else {
852 return 0xffffffffu;
856 uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
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;
866 uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
868 uint32_t val;
869 val = (env->macc[acc] >> 32) & 0xffff;
870 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
871 return val;
874 void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
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;
890 void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
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;
904 void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
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;