Use hxtool for qemu-img command list
[qemu.git] / target-m68k / helper.c
blobaf9ce229e71c4e3cf08fa114fc696226152696b9
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 void m68k_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
59 unsigned int i;
61 for (i = 0; m68k_cpu_defs[i].name; i++) {
62 (*cpu_fprintf)(f, "%s\n", m68k_cpu_defs[i].name);
66 static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
68 if (n < 8) {
69 stfq_p(mem_buf, env->fregs[n]);
70 return 8;
72 if (n < 11) {
73 /* FP control registers (not implemented) */
74 memset(mem_buf, 0, 4);
75 return 4;
77 return 0;
80 static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
82 if (n < 8) {
83 env->fregs[n] = ldfq_p(mem_buf);
84 return 8;
86 if (n < 11) {
87 /* FP control registers (not implemented) */
88 return 4;
90 return 0;
93 static void m68k_set_feature(CPUM68KState *env, int feature)
95 env->features |= (1u << feature);
98 static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
100 m68k_def_t *def;
102 for (def = m68k_cpu_defs; def->name; def++) {
103 if (strcmp(def->name, name) == 0)
104 break;
106 if (!def->name)
107 return -1;
109 switch (def->id) {
110 case M68K_CPUID_M5206:
111 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
112 break;
113 case M68K_CPUID_M5208:
114 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
115 m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
116 m68k_set_feature(env, M68K_FEATURE_BRAL);
117 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
118 m68k_set_feature(env, M68K_FEATURE_USP);
119 break;
120 case M68K_CPUID_CFV4E:
121 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
122 m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
123 m68k_set_feature(env, M68K_FEATURE_BRAL);
124 m68k_set_feature(env, M68K_FEATURE_CF_FPU);
125 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
126 m68k_set_feature(env, M68K_FEATURE_USP);
127 break;
128 case M68K_CPUID_ANY:
129 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
130 m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
131 m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
132 m68k_set_feature(env, M68K_FEATURE_BRAL);
133 m68k_set_feature(env, M68K_FEATURE_CF_FPU);
134 /* MAC and EMAC are mututally exclusive, so pick EMAC.
135 It's mostly backwards compatible. */
136 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
137 m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
138 m68k_set_feature(env, M68K_FEATURE_USP);
139 m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
140 m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
141 break;
144 register_m68k_insns(env);
145 if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
146 gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
147 11, "cf-fp.xml", 18);
149 /* TODO: Add [E]MAC registers. */
150 return 0;
153 void cpu_reset(CPUM68KState *env)
155 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
156 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
157 log_cpu_state(env, 0);
160 memset(env, 0, offsetof(CPUM68KState, breakpoints));
161 #if !defined (CONFIG_USER_ONLY)
162 env->sr = 0x2700;
163 #endif
164 m68k_switch_sp(env);
165 /* ??? FP regs should be initialized to NaN. */
166 env->cc_op = CC_OP_FLAGS;
167 /* TODO: We should set PC from the interrupt vector. */
168 env->pc = 0;
169 tlb_flush(env, 1);
172 CPUM68KState *cpu_m68k_init(const char *cpu_model)
174 CPUM68KState *env;
175 static int inited;
177 env = qemu_mallocz(sizeof(CPUM68KState));
178 cpu_exec_init(env);
179 if (!inited) {
180 inited = 1;
181 m68k_tcg_init();
184 env->cpu_model_str = cpu_model;
186 if (cpu_m68k_set_model(env, cpu_model) < 0) {
187 cpu_m68k_close(env);
188 return NULL;
191 cpu_reset(env);
192 qemu_init_vcpu(env);
193 return env;
196 void cpu_m68k_close(CPUM68KState *env)
198 qemu_free(env);
201 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
203 int flags;
204 uint32_t src;
205 uint32_t dest;
206 uint32_t tmp;
208 #define HIGHBIT 0x80000000u
210 #define SET_NZ(x) do { \
211 if ((x) == 0) \
212 flags |= CCF_Z; \
213 else if ((int32_t)(x) < 0) \
214 flags |= CCF_N; \
215 } while (0)
217 #define SET_FLAGS_SUB(type, utype) do { \
218 SET_NZ((type)dest); \
219 tmp = dest + src; \
220 if ((utype) tmp < (utype) src) \
221 flags |= CCF_C; \
222 if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
223 flags |= CCF_V; \
224 } while (0)
226 flags = 0;
227 src = env->cc_src;
228 dest = env->cc_dest;
229 switch (cc_op) {
230 case CC_OP_FLAGS:
231 flags = dest;
232 break;
233 case CC_OP_LOGIC:
234 SET_NZ(dest);
235 break;
236 case CC_OP_ADD:
237 SET_NZ(dest);
238 if (dest < src)
239 flags |= CCF_C;
240 tmp = dest - src;
241 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
242 flags |= CCF_V;
243 break;
244 case CC_OP_SUB:
245 SET_FLAGS_SUB(int32_t, uint32_t);
246 break;
247 case CC_OP_CMPB:
248 SET_FLAGS_SUB(int8_t, uint8_t);
249 break;
250 case CC_OP_CMPW:
251 SET_FLAGS_SUB(int16_t, uint16_t);
252 break;
253 case CC_OP_ADDX:
254 SET_NZ(dest);
255 if (dest <= src)
256 flags |= CCF_C;
257 tmp = dest - src - 1;
258 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
259 flags |= CCF_V;
260 break;
261 case CC_OP_SUBX:
262 SET_NZ(dest);
263 tmp = dest + src + 1;
264 if (tmp <= src)
265 flags |= CCF_C;
266 if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
267 flags |= CCF_V;
268 break;
269 case CC_OP_SHIFT:
270 SET_NZ(dest);
271 if (src)
272 flags |= CCF_C;
273 break;
274 default:
275 cpu_abort(env, "Bad CC_OP %d", cc_op);
277 env->cc_op = CC_OP_FLAGS;
278 env->cc_dest = flags;
281 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
283 switch (reg) {
284 case 0x02: /* CACR */
285 env->cacr = val;
286 m68k_switch_sp(env);
287 break;
288 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
289 /* TODO: Implement Access Control Registers. */
290 break;
291 case 0x801: /* VBR */
292 env->vbr = val;
293 break;
294 /* TODO: Implement control registers. */
295 default:
296 cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
297 reg, val);
301 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
303 uint32_t acc;
304 int8_t exthigh;
305 uint8_t extlow;
306 uint64_t regval;
307 int i;
308 if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
309 for (i = 0; i < 4; i++) {
310 regval = env->macc[i];
311 exthigh = regval >> 40;
312 if (env->macsr & MACSR_FI) {
313 acc = regval >> 8;
314 extlow = regval;
315 } else {
316 acc = regval;
317 extlow = regval >> 32;
319 if (env->macsr & MACSR_FI) {
320 regval = (((uint64_t)acc) << 8) | extlow;
321 regval |= ((int64_t)exthigh) << 40;
322 } else if (env->macsr & MACSR_SU) {
323 regval = acc | (((int64_t)extlow) << 32);
324 regval |= ((int64_t)exthigh) << 40;
325 } else {
326 regval = acc | (((uint64_t)extlow) << 32);
327 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
329 env->macc[i] = regval;
332 env->macsr = val;
335 void m68k_switch_sp(CPUM68KState *env)
337 int new_sp;
339 env->sp[env->current_sp] = env->aregs[7];
340 new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
341 ? M68K_SSP : M68K_USP;
342 env->aregs[7] = env->sp[new_sp];
343 env->current_sp = new_sp;
346 /* MMU */
348 /* TODO: This will need fixing once the MMU is implemented. */
349 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
351 return addr;
354 #if defined(CONFIG_USER_ONLY)
356 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
357 int mmu_idx, int is_softmmu)
359 env->exception_index = EXCP_ACCESS;
360 env->mmu.ar = address;
361 return 1;
364 #else
366 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
367 int mmu_idx, int is_softmmu)
369 int prot;
371 address &= TARGET_PAGE_MASK;
372 prot = PAGE_READ | PAGE_WRITE;
373 return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
376 /* Notify CPU of a pending interrupt. Prioritization and vectoring should
377 be handled by the interrupt controller. Real hardware only requests
378 the vector when the interrupt is acknowledged by the CPU. For
379 simplicitly we calculate it when the interrupt is signalled. */
380 void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
382 env->pending_level = level;
383 env->pending_vector = vector;
384 if (level)
385 cpu_interrupt(env, CPU_INTERRUPT_HARD);
386 else
387 cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
390 #endif
392 uint32_t HELPER(bitrev)(uint32_t x)
394 x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
395 x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
396 x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
397 return bswap32(x);
400 uint32_t HELPER(ff1)(uint32_t x)
402 int n;
403 for (n = 32; x; n--)
404 x >>= 1;
405 return n;
408 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
410 /* The result has the opposite sign to the original value. */
411 if (ccr & CCF_V)
412 val = (((int32_t)val) >> 31) ^ SIGNBIT;
413 return val;
416 uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
418 uint32_t res;
419 uint32_t old_flags;
421 old_flags = env->cc_dest;
422 if (env->cc_x) {
423 env->cc_x = (op1 <= op2);
424 env->cc_op = CC_OP_SUBX;
425 res = op1 - (op2 + 1);
426 } else {
427 env->cc_x = (op1 < op2);
428 env->cc_op = CC_OP_SUB;
429 res = op1 - op2;
431 env->cc_dest = res;
432 env->cc_src = op2;
433 cpu_m68k_flush_flags(env, env->cc_op);
434 /* !Z is sticky. */
435 env->cc_dest &= (old_flags | ~CCF_Z);
436 return res;
439 uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
441 uint32_t res;
442 uint32_t old_flags;
444 old_flags = env->cc_dest;
445 if (env->cc_x) {
446 res = op1 + op2 + 1;
447 env->cc_x = (res <= op2);
448 env->cc_op = CC_OP_ADDX;
449 } else {
450 res = op1 + op2;
451 env->cc_x = (res < op2);
452 env->cc_op = CC_OP_ADD;
454 env->cc_dest = res;
455 env->cc_src = op2;
456 cpu_m68k_flush_flags(env, env->cc_op);
457 /* !Z is sticky. */
458 env->cc_dest &= (old_flags | ~CCF_Z);
459 return res;
462 uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
464 return a < b;
467 void HELPER(set_sr)(CPUState *env, uint32_t val)
469 env->sr = val & 0xffff;
470 m68k_switch_sp(env);
473 uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
475 uint32_t result;
476 uint32_t cf;
478 shift &= 63;
479 if (shift == 0) {
480 result = val;
481 cf = env->cc_src & CCF_C;
482 } else if (shift < 32) {
483 result = val << shift;
484 cf = (val >> (32 - shift)) & 1;
485 } else if (shift == 32) {
486 result = 0;
487 cf = val & 1;
488 } else /* shift > 32 */ {
489 result = 0;
490 cf = 0;
492 env->cc_src = cf;
493 env->cc_x = (cf != 0);
494 env->cc_dest = result;
495 return result;
498 uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
500 uint32_t result;
501 uint32_t cf;
503 shift &= 63;
504 if (shift == 0) {
505 result = val;
506 cf = env->cc_src & CCF_C;
507 } else if (shift < 32) {
508 result = val >> shift;
509 cf = (val >> (shift - 1)) & 1;
510 } else if (shift == 32) {
511 result = 0;
512 cf = val >> 31;
513 } else /* shift > 32 */ {
514 result = 0;
515 cf = 0;
517 env->cc_src = cf;
518 env->cc_x = (cf != 0);
519 env->cc_dest = result;
520 return result;
523 uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
525 uint32_t result;
526 uint32_t cf;
528 shift &= 63;
529 if (shift == 0) {
530 result = val;
531 cf = (env->cc_src & CCF_C) != 0;
532 } else if (shift < 32) {
533 result = (int32_t)val >> shift;
534 cf = (val >> (shift - 1)) & 1;
535 } else /* shift >= 32 */ {
536 result = (int32_t)val >> 31;
537 cf = val >> 31;
539 env->cc_src = cf;
540 env->cc_x = cf;
541 env->cc_dest = result;
542 return result;
545 /* FPU helpers. */
546 uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
548 return float64_to_int32(val, &env->fp_status);
551 float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
553 return float64_to_float32(val, &env->fp_status);
556 float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
558 return int32_to_float64(val, &env->fp_status);
561 float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
563 return float32_to_float64(val, &env->fp_status);
566 float64 HELPER(iround_f64)(CPUState *env, float64 val)
568 return float64_round_to_int(val, &env->fp_status);
571 float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
573 return float64_trunc_to_int(val, &env->fp_status);
576 float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
578 return float64_sqrt(val, &env->fp_status);
581 float64 HELPER(abs_f64)(float64 val)
583 return float64_abs(val);
586 float64 HELPER(chs_f64)(float64 val)
588 return float64_chs(val);
591 float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
593 return float64_add(a, b, &env->fp_status);
596 float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
598 return float64_sub(a, b, &env->fp_status);
601 float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
603 return float64_mul(a, b, &env->fp_status);
606 float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
608 return float64_div(a, b, &env->fp_status);
611 float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
613 /* ??? This may incorrectly raise exceptions. */
614 /* ??? Should flush denormals to zero. */
615 float64 res;
616 res = float64_sub(a, b, &env->fp_status);
617 if (float64_is_nan(res)) {
618 /* +/-inf compares equal against itself, but sub returns nan. */
619 if (!float64_is_nan(a)
620 && !float64_is_nan(b)) {
621 res = float64_zero;
622 if (float64_lt_quiet(a, res, &env->fp_status))
623 res = float64_chs(res);
626 return res;
629 uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
631 return float64_compare_quiet(val, float64_zero, &env->fp_status);
634 /* MAC unit. */
635 /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
636 take values, others take register numbers and manipulate the contents
637 in-place. */
638 void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
640 uint32_t mask;
641 env->macc[dest] = env->macc[src];
642 mask = MACSR_PAV0 << dest;
643 if (env->macsr & (MACSR_PAV0 << src))
644 env->macsr |= mask;
645 else
646 env->macsr &= ~mask;
649 uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
651 int64_t product;
652 int64_t res;
654 product = (uint64_t)op1 * op2;
655 res = (product << 24) >> 24;
656 if (res != product) {
657 env->macsr |= MACSR_V;
658 if (env->macsr & MACSR_OMC) {
659 /* Make sure the accumulate operation overflows. */
660 if (product < 0)
661 res = ~(1ll << 50);
662 else
663 res = 1ll << 50;
666 return res;
669 uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
671 uint64_t product;
673 product = (uint64_t)op1 * op2;
674 if (product & (0xffffffull << 40)) {
675 env->macsr |= MACSR_V;
676 if (env->macsr & MACSR_OMC) {
677 /* Make sure the accumulate operation overflows. */
678 product = 1ll << 50;
679 } else {
680 product &= ((1ull << 40) - 1);
683 return product;
686 uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
688 uint64_t product;
689 uint32_t remainder;
691 product = (uint64_t)op1 * op2;
692 if (env->macsr & MACSR_RT) {
693 remainder = product & 0xffffff;
694 product >>= 24;
695 if (remainder > 0x800000)
696 product++;
697 else if (remainder == 0x800000)
698 product += (product & 1);
699 } else {
700 product >>= 24;
702 return product;
705 void HELPER(macsats)(CPUState *env, uint32_t acc)
707 int64_t tmp;
708 int64_t result;
709 tmp = env->macc[acc];
710 result = ((tmp << 16) >> 16);
711 if (result != tmp) {
712 env->macsr |= MACSR_V;
714 if (env->macsr & MACSR_V) {
715 env->macsr |= MACSR_PAV0 << acc;
716 if (env->macsr & MACSR_OMC) {
717 /* The result is saturated to 32 bits, despite overflow occuring
718 at 48 bits. Seems weird, but that's what the hardware docs
719 say. */
720 result = (result >> 63) ^ 0x7fffffff;
723 env->macc[acc] = result;
726 void HELPER(macsatu)(CPUState *env, uint32_t acc)
728 uint64_t val;
730 val = env->macc[acc];
731 if (val & (0xffffull << 48)) {
732 env->macsr |= MACSR_V;
734 if (env->macsr & MACSR_V) {
735 env->macsr |= MACSR_PAV0 << acc;
736 if (env->macsr & MACSR_OMC) {
737 if (val > (1ull << 53))
738 val = 0;
739 else
740 val = (1ull << 48) - 1;
741 } else {
742 val &= ((1ull << 48) - 1);
745 env->macc[acc] = val;
748 void HELPER(macsatf)(CPUState *env, uint32_t acc)
750 int64_t sum;
751 int64_t result;
753 sum = env->macc[acc];
754 result = (sum << 16) >> 16;
755 if (result != sum) {
756 env->macsr |= MACSR_V;
758 if (env->macsr & MACSR_V) {
759 env->macsr |= MACSR_PAV0 << acc;
760 if (env->macsr & MACSR_OMC) {
761 result = (result >> 63) ^ 0x7fffffffffffll;
764 env->macc[acc] = result;
767 void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
769 uint64_t val;
770 val = env->macc[acc];
771 if (val == 0)
772 env->macsr |= MACSR_Z;
773 else if (val & (1ull << 47));
774 env->macsr |= MACSR_N;
775 if (env->macsr & (MACSR_PAV0 << acc)) {
776 env->macsr |= MACSR_V;
778 if (env->macsr & MACSR_FI) {
779 val = ((int64_t)val) >> 40;
780 if (val != 0 && val != -1)
781 env->macsr |= MACSR_EV;
782 } else if (env->macsr & MACSR_SU) {
783 val = ((int64_t)val) >> 32;
784 if (val != 0 && val != -1)
785 env->macsr |= MACSR_EV;
786 } else {
787 if ((val >> 32) != 0)
788 env->macsr |= MACSR_EV;
792 void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
794 cpu_m68k_flush_flags(env, cc_op);
797 uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
799 int rem;
800 uint32_t result;
802 if (env->macsr & MACSR_SU) {
803 /* 16-bit rounding. */
804 rem = val & 0xffffff;
805 val = (val >> 24) & 0xffffu;
806 if (rem > 0x800000)
807 val++;
808 else if (rem == 0x800000)
809 val += (val & 1);
810 } else if (env->macsr & MACSR_RT) {
811 /* 32-bit rounding. */
812 rem = val & 0xff;
813 val >>= 8;
814 if (rem > 0x80)
815 val++;
816 else if (rem == 0x80)
817 val += (val & 1);
818 } else {
819 /* No rounding. */
820 val >>= 8;
822 if (env->macsr & MACSR_OMC) {
823 /* Saturate. */
824 if (env->macsr & MACSR_SU) {
825 if (val != (uint16_t) val) {
826 result = ((val >> 63) ^ 0x7fff) & 0xffff;
827 } else {
828 result = val & 0xffff;
830 } else {
831 if (val != (uint32_t)val) {
832 result = ((uint32_t)(val >> 63) & 0x7fffffff);
833 } else {
834 result = (uint32_t)val;
837 } else {
838 /* No saturation. */
839 if (env->macsr & MACSR_SU) {
840 result = val & 0xffff;
841 } else {
842 result = (uint32_t)val;
845 return result;
848 uint32_t HELPER(get_macs)(uint64_t val)
850 if (val == (int32_t)val) {
851 return (int32_t)val;
852 } else {
853 return (val >> 61) ^ ~SIGNBIT;
857 uint32_t HELPER(get_macu)(uint64_t val)
859 if ((val >> 32) == 0) {
860 return (uint32_t)val;
861 } else {
862 return 0xffffffffu;
866 uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
868 uint32_t val;
869 val = env->macc[acc] & 0x00ff;
870 val = (env->macc[acc] >> 32) & 0xff00;
871 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
872 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
873 return val;
876 uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
878 uint32_t val;
879 val = (env->macc[acc] >> 32) & 0xffff;
880 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
881 return val;
884 void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
886 int64_t res;
887 int32_t tmp;
888 res = env->macc[acc] & 0xffffffff00ull;
889 tmp = (int16_t)(val & 0xff00);
890 res |= ((int64_t)tmp) << 32;
891 res |= val & 0xff;
892 env->macc[acc] = res;
893 res = env->macc[acc + 1] & 0xffffffff00ull;
894 tmp = (val & 0xff000000);
895 res |= ((int64_t)tmp) << 16;
896 res |= (val >> 16) & 0xff;
897 env->macc[acc + 1] = res;
900 void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
902 int64_t res;
903 int32_t tmp;
904 res = (uint32_t)env->macc[acc];
905 tmp = (int16_t)val;
906 res |= ((int64_t)tmp) << 32;
907 env->macc[acc] = res;
908 res = (uint32_t)env->macc[acc + 1];
909 tmp = val & 0xffff0000;
910 res |= (int64_t)tmp << 16;
911 env->macc[acc + 1] = res;
914 void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
916 uint64_t res;
917 res = (uint32_t)env->macc[acc];
918 res |= ((uint64_t)(val & 0xffff)) << 32;
919 env->macc[acc] = res;
920 res = (uint32_t)env->macc[acc + 1];
921 res |= (uint64_t)(val & 0xffff0000) << 16;
922 env->macc[acc + 1] = res;