Fix kernel loading
[qemu/mini2440.git] / target-m68k / helper.c
blob045687f639db935bd827b93a139e91fad6c237af
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 memset(env, 0, offsetof(CPUM68KState, breakpoints));
147 #if !defined (CONFIG_USER_ONLY)
148 env->sr = 0x2700;
149 #endif
150 m68k_switch_sp(env);
151 /* ??? FP regs should be initialized to NaN. */
152 env->cc_op = CC_OP_FLAGS;
153 /* TODO: We should set PC from the interrupt vector. */
154 env->pc = 0;
155 tlb_flush(env, 1);
158 CPUM68KState *cpu_m68k_init(const char *cpu_model)
160 CPUM68KState *env;
161 static int inited;
163 env = qemu_mallocz(sizeof(CPUM68KState));
164 if (!env)
165 return NULL;
166 cpu_exec_init(env);
167 if (!inited) {
168 inited = 1;
169 m68k_tcg_init();
172 env->cpu_model_str = cpu_model;
174 if (cpu_m68k_set_model(env, cpu_model) < 0) {
175 cpu_m68k_close(env);
176 return NULL;
179 cpu_reset(env);
180 return env;
183 void cpu_m68k_close(CPUM68KState *env)
185 qemu_free(env);
188 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
190 int flags;
191 uint32_t src;
192 uint32_t dest;
193 uint32_t tmp;
195 #define HIGHBIT 0x80000000u
197 #define SET_NZ(x) do { \
198 if ((x) == 0) \
199 flags |= CCF_Z; \
200 else if ((int32_t)(x) < 0) \
201 flags |= CCF_N; \
202 } while (0)
204 #define SET_FLAGS_SUB(type, utype) do { \
205 SET_NZ((type)dest); \
206 tmp = dest + src; \
207 if ((utype) tmp < (utype) src) \
208 flags |= CCF_C; \
209 if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
210 flags |= CCF_V; \
211 } while (0)
213 flags = 0;
214 src = env->cc_src;
215 dest = env->cc_dest;
216 switch (cc_op) {
217 case CC_OP_FLAGS:
218 flags = dest;
219 break;
220 case CC_OP_LOGIC:
221 SET_NZ(dest);
222 break;
223 case CC_OP_ADD:
224 SET_NZ(dest);
225 if (dest < src)
226 flags |= CCF_C;
227 tmp = dest - src;
228 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
229 flags |= CCF_V;
230 break;
231 case CC_OP_SUB:
232 SET_FLAGS_SUB(int32_t, uint32_t);
233 break;
234 case CC_OP_CMPB:
235 SET_FLAGS_SUB(int8_t, uint8_t);
236 break;
237 case CC_OP_CMPW:
238 SET_FLAGS_SUB(int16_t, uint16_t);
239 break;
240 case CC_OP_ADDX:
241 SET_NZ(dest);
242 if (dest <= src)
243 flags |= CCF_C;
244 tmp = dest - src - 1;
245 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
246 flags |= CCF_V;
247 break;
248 case CC_OP_SUBX:
249 SET_NZ(dest);
250 tmp = dest + src + 1;
251 if (tmp <= src)
252 flags |= CCF_C;
253 if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
254 flags |= CCF_V;
255 break;
256 case CC_OP_SHIFT:
257 SET_NZ(dest);
258 if (src)
259 flags |= CCF_C;
260 break;
261 default:
262 cpu_abort(env, "Bad CC_OP %d", cc_op);
264 env->cc_op = CC_OP_FLAGS;
265 env->cc_dest = flags;
268 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
270 switch (reg) {
271 case 0x02: /* CACR */
272 env->cacr = val;
273 m68k_switch_sp(env);
274 break;
275 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
276 /* TODO: Implement Access Control Registers. */
277 break;
278 case 0x801: /* VBR */
279 env->vbr = val;
280 break;
281 /* TODO: Implement control registers. */
282 default:
283 cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
284 reg, val);
288 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
290 uint32_t acc;
291 int8_t exthigh;
292 uint8_t extlow;
293 uint64_t regval;
294 int i;
295 if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
296 for (i = 0; i < 4; i++) {
297 regval = env->macc[i];
298 exthigh = regval >> 40;
299 if (env->macsr & MACSR_FI) {
300 acc = regval >> 8;
301 extlow = regval;
302 } else {
303 acc = regval;
304 extlow = regval >> 32;
306 if (env->macsr & MACSR_FI) {
307 regval = (((uint64_t)acc) << 8) | extlow;
308 regval |= ((int64_t)exthigh) << 40;
309 } else if (env->macsr & MACSR_SU) {
310 regval = acc | (((int64_t)extlow) << 32);
311 regval |= ((int64_t)exthigh) << 40;
312 } else {
313 regval = acc | (((uint64_t)extlow) << 32);
314 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
316 env->macc[i] = regval;
319 env->macsr = val;
322 void m68k_switch_sp(CPUM68KState *env)
324 int new_sp;
326 env->sp[env->current_sp] = env->aregs[7];
327 new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
328 ? M68K_SSP : M68K_USP;
329 env->aregs[7] = env->sp[new_sp];
330 env->current_sp = new_sp;
333 /* MMU */
335 /* TODO: This will need fixing once the MMU is implemented. */
336 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
338 return addr;
341 #if defined(CONFIG_USER_ONLY)
343 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
344 int mmu_idx, int is_softmmu)
346 env->exception_index = EXCP_ACCESS;
347 env->mmu.ar = address;
348 return 1;
351 #else
353 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
354 int mmu_idx, int is_softmmu)
356 int prot;
358 address &= TARGET_PAGE_MASK;
359 prot = PAGE_READ | PAGE_WRITE;
360 return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
363 /* Notify CPU of a pending interrupt. Prioritization and vectoring should
364 be handled by the interrupt controller. Real hardware only requests
365 the vector when the interrupt is acknowledged by the CPU. For
366 simplicitly we calculate it when the interrupt is signalled. */
367 void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
369 env->pending_level = level;
370 env->pending_vector = vector;
371 if (level)
372 cpu_interrupt(env, CPU_INTERRUPT_HARD);
373 else
374 cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
377 #endif
379 uint32_t HELPER(bitrev)(uint32_t x)
381 x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
382 x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
383 x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
384 return bswap32(x);
387 uint32_t HELPER(ff1)(uint32_t x)
389 int n;
390 for (n = 32; x; n--)
391 x >>= 1;
392 return n;
395 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
397 /* The result has the opposite sign to the original value. */
398 if (ccr & CCF_V)
399 val = (((int32_t)val) >> 31) ^ SIGNBIT;
400 return val;
403 uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
405 uint32_t res;
406 uint32_t old_flags;
408 old_flags = env->cc_dest;
409 if (env->cc_x) {
410 env->cc_x = (op1 <= op2);
411 env->cc_op = CC_OP_SUBX;
412 res = op1 - (op2 + 1);
413 } else {
414 env->cc_x = (op1 < op2);
415 env->cc_op = CC_OP_SUB;
416 res = op1 - op2;
418 env->cc_dest = res;
419 env->cc_src = op2;
420 cpu_m68k_flush_flags(env, env->cc_op);
421 /* !Z is sticky. */
422 env->cc_dest &= (old_flags | ~CCF_Z);
423 return res;
426 uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
428 uint32_t res;
429 uint32_t old_flags;
431 old_flags = env->cc_dest;
432 if (env->cc_x) {
433 res = op1 + op2 + 1;
434 env->cc_x = (res <= op2);
435 env->cc_op = CC_OP_ADDX;
436 } else {
437 res = op1 + op2;
438 env->cc_x = (res < op2);
439 env->cc_op = CC_OP_ADD;
441 env->cc_dest = res;
442 env->cc_src = op2;
443 cpu_m68k_flush_flags(env, env->cc_op);
444 /* !Z is sticky. */
445 env->cc_dest &= (old_flags | ~CCF_Z);
446 return res;
449 uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
451 return a < b;
454 uint32_t HELPER(btest)(uint32_t x)
456 return x != 0;
459 void HELPER(set_sr)(CPUState *env, uint32_t val)
461 env->sr = val & 0xffff;
462 m68k_switch_sp(env);
465 uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
467 uint32_t result;
468 uint32_t cf;
470 shift &= 63;
471 if (shift == 0) {
472 result = val;
473 cf = env->cc_src & CCF_C;
474 } else if (shift < 32) {
475 result = val << shift;
476 cf = (val >> (32 - shift)) & 1;
477 } else if (shift == 32) {
478 result = 0;
479 cf = val & 1;
480 } else /* shift > 32 */ {
481 result = 0;
482 cf = 0;
484 env->cc_src = cf;
485 env->cc_x = (cf != 0);
486 env->cc_dest = result;
487 return result;
490 uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
492 uint32_t result;
493 uint32_t cf;
495 shift &= 63;
496 if (shift == 0) {
497 result = val;
498 cf = env->cc_src & CCF_C;
499 } else if (shift < 32) {
500 result = val >> shift;
501 cf = (val >> (shift - 1)) & 1;
502 } else if (shift == 32) {
503 result = 0;
504 cf = val >> 31;
505 } else /* shift > 32 */ {
506 result = 0;
507 cf = 0;
509 env->cc_src = cf;
510 env->cc_x = (cf != 0);
511 env->cc_dest = result;
512 return result;
515 uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
517 uint32_t result;
518 uint32_t cf;
520 shift &= 63;
521 if (shift == 0) {
522 result = val;
523 cf = (env->cc_src & CCF_C) != 0;
524 } else if (shift < 32) {
525 result = (int32_t)val >> shift;
526 cf = (val >> (shift - 1)) & 1;
527 } else /* shift >= 32 */ {
528 result = (int32_t)val >> 31;
529 cf = val >> 31;
531 env->cc_src = cf;
532 env->cc_x = cf;
533 env->cc_dest = result;
534 return result;
537 /* FPU helpers. */
538 uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
540 return float64_to_int32(val, &env->fp_status);
543 float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
545 return float64_to_float32(val, &env->fp_status);
548 float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
550 return int32_to_float64(val, &env->fp_status);
553 float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
555 return float32_to_float64(val, &env->fp_status);
558 float64 HELPER(iround_f64)(CPUState *env, float64 val)
560 return float64_round_to_int(val, &env->fp_status);
563 float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
565 return float64_trunc_to_int(val, &env->fp_status);
568 float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
570 return float64_sqrt(val, &env->fp_status);
573 float64 HELPER(abs_f64)(float64 val)
575 return float64_abs(val);
578 float64 HELPER(chs_f64)(float64 val)
580 return float64_chs(val);
583 float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
585 return float64_add(a, b, &env->fp_status);
588 float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
590 return float64_sub(a, b, &env->fp_status);
593 float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
595 return float64_mul(a, b, &env->fp_status);
598 float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
600 return float64_div(a, b, &env->fp_status);
603 float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
605 /* ??? This may incorrectly raise exceptions. */
606 /* ??? Should flush denormals to zero. */
607 float64 res;
608 res = float64_sub(a, b, &env->fp_status);
609 if (float64_is_nan(res)) {
610 /* +/-inf compares equal against itself, but sub returns nan. */
611 if (!float64_is_nan(a)
612 && !float64_is_nan(b)) {
613 res = float64_zero;
614 if (float64_lt_quiet(a, res, &env->fp_status))
615 res = float64_chs(res);
618 return res;
621 uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
623 return float64_compare_quiet(val, float64_zero, &env->fp_status);
626 /* MAC unit. */
627 /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
628 take values, others take register numbers and manipulate the contents
629 in-place. */
630 void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
632 uint32_t mask;
633 env->macc[dest] = env->macc[src];
634 mask = MACSR_PAV0 << dest;
635 if (env->macsr & (MACSR_PAV0 << src))
636 env->macsr |= mask;
637 else
638 env->macsr &= ~mask;
641 uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
643 int64_t product;
644 int64_t res;
646 product = (uint64_t)op1 * op2;
647 res = (product << 24) >> 24;
648 if (res != product) {
649 env->macsr |= MACSR_V;
650 if (env->macsr & MACSR_OMC) {
651 /* Make sure the accumulate operation overflows. */
652 if (product < 0)
653 res = ~(1ll << 50);
654 else
655 res = 1ll << 50;
658 return res;
661 uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
663 uint64_t product;
665 product = (uint64_t)op1 * op2;
666 if (product & (0xffffffull << 40)) {
667 env->macsr |= MACSR_V;
668 if (env->macsr & MACSR_OMC) {
669 /* Make sure the accumulate operation overflows. */
670 product = 1ll << 50;
671 } else {
672 product &= ((1ull << 40) - 1);
675 return product;
678 uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
680 uint64_t product;
681 uint32_t remainder;
683 product = (uint64_t)op1 * op2;
684 if (env->macsr & MACSR_RT) {
685 remainder = product & 0xffffff;
686 product >>= 24;
687 if (remainder > 0x800000)
688 product++;
689 else if (remainder == 0x800000)
690 product += (product & 1);
691 } else {
692 product >>= 24;
694 return product;
697 void HELPER(macsats)(CPUState *env, uint32_t acc)
699 int64_t tmp;
700 int64_t result;
701 tmp = env->macc[acc];
702 result = ((tmp << 16) >> 16);
703 if (result != tmp) {
704 env->macsr |= MACSR_V;
706 if (env->macsr & MACSR_V) {
707 env->macsr |= MACSR_PAV0 << acc;
708 if (env->macsr & MACSR_OMC) {
709 /* The result is saturated to 32 bits, despite overflow occuring
710 at 48 bits. Seems weird, but that's what the hardware docs
711 say. */
712 result = (result >> 63) ^ 0x7fffffff;
715 env->macc[acc] = result;
718 void HELPER(macsatu)(CPUState *env, uint32_t acc)
720 uint64_t val;
722 val = env->macc[acc];
723 if (val & (0xffffull << 48)) {
724 env->macsr |= MACSR_V;
726 if (env->macsr & MACSR_V) {
727 env->macsr |= MACSR_PAV0 << acc;
728 if (env->macsr & MACSR_OMC) {
729 if (val > (1ull << 53))
730 val = 0;
731 else
732 val = (1ull << 48) - 1;
733 } else {
734 val &= ((1ull << 48) - 1);
737 env->macc[acc] = val;
740 void HELPER(macsatf)(CPUState *env, uint32_t acc)
742 int64_t sum;
743 int64_t result;
745 sum = env->macc[acc];
746 result = (sum << 16) >> 16;
747 if (result != sum) {
748 env->macsr |= MACSR_V;
750 if (env->macsr & MACSR_V) {
751 env->macsr |= MACSR_PAV0 << acc;
752 if (env->macsr & MACSR_OMC) {
753 result = (result >> 63) ^ 0x7fffffffffffll;
756 env->macc[acc] = result;
759 void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
761 uint64_t val;
762 val = env->macc[acc];
763 if (val == 0)
764 env->macsr |= MACSR_Z;
765 else if (val & (1ull << 47));
766 env->macsr |= MACSR_N;
767 if (env->macsr & (MACSR_PAV0 << acc)) {
768 env->macsr |= MACSR_V;
770 if (env->macsr & MACSR_FI) {
771 val = ((int64_t)val) >> 40;
772 if (val != 0 && val != -1)
773 env->macsr |= MACSR_EV;
774 } else if (env->macsr & MACSR_SU) {
775 val = ((int64_t)val) >> 32;
776 if (val != 0 && val != -1)
777 env->macsr |= MACSR_EV;
778 } else {
779 if ((val >> 32) != 0)
780 env->macsr |= MACSR_EV;
784 void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
786 cpu_m68k_flush_flags(env, cc_op);
789 uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
791 int rem;
792 uint32_t result;
794 if (env->macsr & MACSR_SU) {
795 /* 16-bit rounding. */
796 rem = val & 0xffffff;
797 val = (val >> 24) & 0xffffu;
798 if (rem > 0x800000)
799 val++;
800 else if (rem == 0x800000)
801 val += (val & 1);
802 } else if (env->macsr & MACSR_RT) {
803 /* 32-bit rounding. */
804 rem = val & 0xff;
805 val >>= 8;
806 if (rem > 0x80)
807 val++;
808 else if (rem == 0x80)
809 val += (val & 1);
810 } else {
811 /* No rounding. */
812 val >>= 8;
814 if (env->macsr & MACSR_OMC) {
815 /* Saturate. */
816 if (env->macsr & MACSR_SU) {
817 if (val != (uint16_t) val) {
818 result = ((val >> 63) ^ 0x7fff) & 0xffff;
819 } else {
820 result = val & 0xffff;
822 } else {
823 if (val != (uint32_t)val) {
824 result = ((uint32_t)(val >> 63) & 0x7fffffff);
825 } else {
826 result = (uint32_t)val;
829 } else {
830 /* No saturation. */
831 if (env->macsr & MACSR_SU) {
832 result = val & 0xffff;
833 } else {
834 result = (uint32_t)val;
837 return result;
840 uint32_t HELPER(get_macs)(uint64_t val)
842 if (val == (int32_t)val) {
843 return (int32_t)val;
844 } else {
845 return (val >> 61) ^ ~SIGNBIT;
849 uint32_t HELPER(get_macu)(uint64_t val)
851 if ((val >> 32) == 0) {
852 return (uint32_t)val;
853 } else {
854 return 0xffffffffu;
858 uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
860 uint32_t val;
861 val = env->macc[acc] & 0x00ff;
862 val = (env->macc[acc] >> 32) & 0xff00;
863 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
864 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
865 return val;
868 uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
870 uint32_t val;
871 val = (env->macc[acc] >> 32) & 0xffff;
872 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
873 return val;
876 void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
878 int64_t res;
879 int32_t tmp;
880 res = env->macc[acc] & 0xffffffff00ull;
881 tmp = (int16_t)(val & 0xff00);
882 res |= ((int64_t)tmp) << 32;
883 res |= val & 0xff;
884 env->macc[acc] = res;
885 res = env->macc[acc + 1] & 0xffffffff00ull;
886 tmp = (val & 0xff000000);
887 res |= ((int64_t)tmp) << 16;
888 res |= (val >> 16) & 0xff;
889 env->macc[acc + 1] = res;
892 void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
894 int64_t res;
895 int32_t tmp;
896 res = (uint32_t)env->macc[acc];
897 tmp = (int16_t)val;
898 res |= ((int64_t)tmp) << 32;
899 env->macc[acc] = res;
900 res = (uint32_t)env->macc[acc + 1];
901 tmp = val & 0xffff0000;
902 res |= (int64_t)tmp << 16;
903 env->macc[acc + 1] = res;
906 void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
908 uint64_t res;
909 res = (uint32_t)env->macc[acc];
910 res |= ((uint64_t)(val & 0xffff)) << 32;
911 env->macc[acc] = res;
912 res = (uint32_t)env->macc[acc + 1];
913 res |= (uint64_t)(val & 0xffff0000) << 16;
914 env->macc[acc + 1] = res;