target-m68k: remove m68k_cpu_exec_enter() and m68k_cpu_exec_exit()
[qemu/ar7.git] / target-m68k / helper.c
blob92d1deda3cc0ae1b66050bbee769a69857d89698
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, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
22 #include "cpu.h"
23 #include "exec/exec-all.h"
24 #include "exec/gdbstub.h"
26 #include "exec/helper-proto.h"
28 #define SIGNBIT (1u << 31)
30 /* Sort alphabetically, except for "any". */
31 static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
33 ObjectClass *class_a = (ObjectClass *)a;
34 ObjectClass *class_b = (ObjectClass *)b;
35 const char *name_a, *name_b;
37 name_a = object_class_get_name(class_a);
38 name_b = object_class_get_name(class_b);
39 if (strcmp(name_a, "any-" TYPE_M68K_CPU) == 0) {
40 return 1;
41 } else if (strcmp(name_b, "any-" TYPE_M68K_CPU) == 0) {
42 return -1;
43 } else {
44 return strcasecmp(name_a, name_b);
48 static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
50 ObjectClass *c = data;
51 CPUListState *s = user_data;
52 const char *typename;
53 char *name;
55 typename = object_class_get_name(c);
56 name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_M68K_CPU));
57 (*s->cpu_fprintf)(s->file, "%s\n",
58 name);
59 g_free(name);
62 void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
64 CPUListState s = {
65 .file = f,
66 .cpu_fprintf = cpu_fprintf,
68 GSList *list;
70 list = object_class_get_list(TYPE_M68K_CPU, false);
71 list = g_slist_sort(list, m68k_cpu_list_compare);
72 g_slist_foreach(list, m68k_cpu_list_entry, &s);
73 g_slist_free(list);
76 static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
78 if (n < 8) {
79 stfq_p(mem_buf, env->fregs[n]);
80 return 8;
82 if (n < 11) {
83 /* FP control registers (not implemented) */
84 memset(mem_buf, 0, 4);
85 return 4;
87 return 0;
90 static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
92 if (n < 8) {
93 env->fregs[n] = ldfq_p(mem_buf);
94 return 8;
96 if (n < 11) {
97 /* FP control registers (not implemented) */
98 return 4;
100 return 0;
103 M68kCPU *cpu_m68k_init(const char *cpu_model)
105 M68kCPU *cpu;
106 CPUM68KState *env;
107 ObjectClass *oc;
109 oc = cpu_class_by_name(TYPE_M68K_CPU, cpu_model);
110 if (oc == NULL) {
111 return NULL;
113 cpu = M68K_CPU(object_new(object_class_get_name(oc)));
114 env = &cpu->env;
116 register_m68k_insns(env);
118 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
120 return cpu;
123 void m68k_cpu_init_gdb(M68kCPU *cpu)
125 CPUState *cs = CPU(cpu);
126 CPUM68KState *env = &cpu->env;
128 if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
129 gdb_register_coprocessor(cs, fpu_gdb_get_reg, fpu_gdb_set_reg,
130 11, "cf-fp.xml", 18);
132 /* TODO: Add [E]MAC registers. */
135 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
137 M68kCPU *cpu = m68k_env_get_cpu(env);
138 int flags;
139 uint32_t src;
140 uint32_t dest;
141 uint32_t tmp;
143 #define HIGHBIT(type) (1u << (sizeof(type) * 8 - 1))
145 #define SET_NZ(x, type) do { \
146 if ((type)(x) == 0) { \
147 flags |= CCF_Z; \
148 } else if ((type)(x) < 0) { \
149 flags |= CCF_N; \
151 } while (0)
153 #define SET_FLAGS_SUB(type, utype) do { \
154 SET_NZ(dest, type); \
155 tmp = dest + src; \
156 if ((utype) tmp < (utype) src) { \
157 flags |= CCF_C; \
159 if (HIGHBIT(type) & (tmp ^ dest) & (tmp ^ src)) { \
160 flags |= CCF_V; \
162 } while (0)
164 #define SET_FLAGS_ADD(type, utype) do { \
165 SET_NZ(dest, type); \
166 if ((utype) dest < (utype) src) { \
167 flags |= CCF_C; \
169 tmp = dest - src; \
170 if (HIGHBIT(type) & (src ^ dest) & ~(tmp ^ src)) { \
171 flags |= CCF_V; \
173 } while (0)
175 #define SET_FLAGS_ADDX(type, utype) do { \
176 SET_NZ(dest, type); \
177 if ((utype) dest <= (utype) src) { \
178 flags |= CCF_C; \
180 tmp = dest - src - 1; \
181 if (HIGHBIT(type) & (src ^ dest) & ~(tmp ^ src)) { \
182 flags |= CCF_V; \
184 } while (0)
186 #define SET_FLAGS_SUBX(type, utype) do { \
187 SET_NZ(dest, type); \
188 tmp = dest + src + 1; \
189 if ((utype) tmp <= (utype) src) { \
190 flags |= CCF_C; \
192 if (HIGHBIT(type) & (tmp ^ dest) & (tmp ^ src)) { \
193 flags |= CCF_V; \
195 } while (0)
197 #define SET_FLAGS_SHIFT(type) do { \
198 SET_NZ(dest, type); \
199 flags |= src; \
200 } while (0)
202 flags = 0;
203 src = env->cc_src;
204 dest = env->cc_dest;
205 switch (cc_op) {
206 case CC_OP_FLAGS:
207 flags = dest;
208 break;
209 case CC_OP_LOGICB:
210 SET_NZ(dest, int8_t);
211 goto set_x;
212 break;
213 case CC_OP_LOGICW:
214 SET_NZ(dest, int16_t);
215 goto set_x;
216 break;
217 case CC_OP_LOGIC:
218 SET_NZ(dest, int32_t);
219 set_x:
220 if (!m68k_feature(env, M68K_FEATURE_M68000)) {
221 /* Unlike m68k, coldfire always clears the overflow bit. */
222 env->cc_x = 0;
224 break;
225 case CC_OP_ADDB:
226 SET_FLAGS_ADD(int8_t, uint8_t);
227 break;
228 case CC_OP_ADDW:
229 SET_FLAGS_ADD(int16_t, uint16_t);
230 break;
231 case CC_OP_ADD:
232 SET_FLAGS_ADD(int32_t, uint32_t);
233 break;
234 case CC_OP_SUBB:
235 SET_FLAGS_SUB(int8_t, uint8_t);
236 break;
237 case CC_OP_SUBW:
238 SET_FLAGS_SUB(int16_t, uint16_t);
239 break;
240 case CC_OP_SUB:
241 SET_FLAGS_SUB(int32_t, uint32_t);
242 break;
243 case CC_OP_ADDXB:
244 SET_FLAGS_ADDX(int8_t, uint8_t);
245 break;
246 case CC_OP_ADDXW:
247 SET_FLAGS_ADDX(int16_t, uint16_t);
248 break;
249 case CC_OP_ADDX:
250 SET_FLAGS_ADDX(int32_t, uint32_t);
251 break;
252 case CC_OP_SUBXB:
253 SET_FLAGS_SUBX(int8_t, uint8_t);
254 break;
255 case CC_OP_SUBXW:
256 SET_FLAGS_SUBX(int16_t, uint16_t);
257 break;
258 case CC_OP_SUBX:
259 SET_FLAGS_SUBX(int32_t, uint32_t);
260 break;
261 case CC_OP_SHIFTB:
262 SET_FLAGS_SHIFT(int8_t);
263 break;
264 case CC_OP_SHIFTW:
265 SET_FLAGS_SHIFT(int16_t);
266 break;
267 case CC_OP_SHIFT:
268 SET_FLAGS_SHIFT(int32_t);
269 break;
270 default:
271 cpu_abort(CPU(cpu), "Bad CC_OP %d", cc_op);
273 env->cc_op = CC_OP_FLAGS;
274 env->cc_dest = flags;
277 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
279 M68kCPU *cpu = m68k_env_get_cpu(env);
281 switch (reg) {
282 case 0x02: /* CACR */
283 env->cacr = val;
284 m68k_switch_sp(env);
285 break;
286 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
287 /* TODO: Implement Access Control Registers. */
288 break;
289 case 0x801: /* VBR */
290 env->vbr = val;
291 break;
292 /* TODO: Implement control registers. */
293 default:
294 cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
295 reg, val);
299 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
301 uint32_t acc;
302 int8_t exthigh;
303 uint8_t extlow;
304 uint64_t regval;
305 int i;
306 if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
307 for (i = 0; i < 4; i++) {
308 regval = env->macc[i];
309 exthigh = regval >> 40;
310 if (env->macsr & MACSR_FI) {
311 acc = regval >> 8;
312 extlow = regval;
313 } else {
314 acc = regval;
315 extlow = regval >> 32;
317 if (env->macsr & MACSR_FI) {
318 regval = (((uint64_t)acc) << 8) | extlow;
319 regval |= ((int64_t)exthigh) << 40;
320 } else if (env->macsr & MACSR_SU) {
321 regval = acc | (((int64_t)extlow) << 32);
322 regval |= ((int64_t)exthigh) << 40;
323 } else {
324 regval = acc | (((uint64_t)extlow) << 32);
325 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
327 env->macc[i] = regval;
330 env->macsr = val;
333 void m68k_switch_sp(CPUM68KState *env)
335 int new_sp;
337 env->sp[env->current_sp] = env->aregs[7];
338 new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
339 ? M68K_SSP : M68K_USP;
340 env->aregs[7] = env->sp[new_sp];
341 env->current_sp = new_sp;
344 #if defined(CONFIG_USER_ONLY)
346 int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
347 int mmu_idx)
349 M68kCPU *cpu = M68K_CPU(cs);
351 cs->exception_index = EXCP_ACCESS;
352 cpu->env.mmu.ar = address;
353 return 1;
356 #else
358 /* MMU */
360 /* TODO: This will need fixing once the MMU is implemented. */
361 hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
363 return addr;
366 int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
367 int mmu_idx)
369 int prot;
371 address &= TARGET_PAGE_MASK;
372 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
373 tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
374 return 0;
377 /* Notify CPU of a pending interrupt. Prioritization and vectoring should
378 be handled by the interrupt controller. Real hardware only requests
379 the vector when the interrupt is acknowledged by the CPU. For
380 simplicitly we calculate it when the interrupt is signalled. */
381 void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
383 CPUState *cs = CPU(cpu);
384 CPUM68KState *env = &cpu->env;
386 env->pending_level = level;
387 env->pending_vector = vector;
388 if (level) {
389 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
390 } else {
391 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
395 #endif
397 uint32_t HELPER(bitrev)(uint32_t x)
399 x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
400 x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
401 x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
402 return bswap32(x);
405 uint32_t HELPER(ff1)(uint32_t x)
407 int n;
408 for (n = 32; x; n--)
409 x >>= 1;
410 return n;
413 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
415 /* The result has the opposite sign to the original value. */
416 if (ccr & CCF_V)
417 val = (((int32_t)val) >> 31) ^ SIGNBIT;
418 return val;
421 uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
423 uint32_t res;
424 uint32_t old_flags;
426 old_flags = env->cc_dest;
427 if (env->cc_x) {
428 env->cc_x = (op1 <= op2);
429 env->cc_op = CC_OP_SUBX;
430 res = op1 - (op2 + 1);
431 } else {
432 env->cc_x = (op1 < op2);
433 env->cc_op = CC_OP_SUB;
434 res = op1 - op2;
436 env->cc_dest = res;
437 env->cc_src = op2;
438 cpu_m68k_flush_flags(env, env->cc_op);
439 /* !Z is sticky. */
440 env->cc_dest &= (old_flags | ~CCF_Z);
441 return res;
444 uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
446 uint32_t res;
447 uint32_t old_flags;
449 old_flags = env->cc_dest;
450 if (env->cc_x) {
451 res = op1 + op2 + 1;
452 env->cc_x = (res <= op2);
453 env->cc_op = CC_OP_ADDX;
454 } else {
455 res = op1 + op2;
456 env->cc_x = (res < op2);
457 env->cc_op = CC_OP_ADD;
459 env->cc_dest = res;
460 env->cc_src = op2;
461 cpu_m68k_flush_flags(env, env->cc_op);
462 /* !Z is sticky. */
463 env->cc_dest &= (old_flags | ~CCF_Z);
464 return res;
467 void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
469 env->sr = val & 0xffff;
470 m68k_switch_sp(env);
473 uint32_t HELPER(shl_cc)(CPUM68KState *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)(CPUM68KState *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)(CPUM68KState *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)(CPUM68KState *env, float64 val)
548 return float64_to_int32(val, &env->fp_status);
551 float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
553 return float64_to_float32(val, &env->fp_status);
556 float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
558 return int32_to_float64(val, &env->fp_status);
561 float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
563 return float32_to_float64(val, &env->fp_status);
566 float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
568 return float64_round_to_int(val, &env->fp_status);
571 float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
573 return float64_trunc_to_int(val, &env->fp_status);
576 float64 HELPER(sqrt_f64)(CPUM68KState *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)(CPUM68KState *env, float64 a, float64 b)
593 return float64_add(a, b, &env->fp_status);
596 float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
598 return float64_sub(a, b, &env->fp_status);
601 float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
603 return float64_mul(a, b, &env->fp_status);
606 float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
608 return float64_div(a, b, &env->fp_status);
611 float64 HELPER(sub_cmp_f64)(CPUM68KState *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_quiet_nan(res, &env->fp_status)) {
618 /* +/-inf compares equal against itself, but sub returns nan. */
619 if (!float64_is_quiet_nan(a, &env->fp_status)
620 && !float64_is_quiet_nan(b, &env->fp_status)) {
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)(CPUM68KState *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)(CPUM68KState *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)(CPUM68KState *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)(CPUM68KState *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)(CPUM68KState *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)(CPUM68KState *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 occurring
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)(CPUM68KState *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)(CPUM68KState *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)(CPUM68KState *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;
776 if (env->macsr & (MACSR_PAV0 << acc)) {
777 env->macsr |= MACSR_V;
779 if (env->macsr & MACSR_FI) {
780 val = ((int64_t)val) >> 40;
781 if (val != 0 && val != -1)
782 env->macsr |= MACSR_EV;
783 } else if (env->macsr & MACSR_SU) {
784 val = ((int64_t)val) >> 32;
785 if (val != 0 && val != -1)
786 env->macsr |= MACSR_EV;
787 } else {
788 if ((val >> 32) != 0)
789 env->macsr |= MACSR_EV;
793 void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
795 cpu_m68k_flush_flags(env, cc_op);
798 uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
800 int rem;
801 uint32_t result;
803 if (env->macsr & MACSR_SU) {
804 /* 16-bit rounding. */
805 rem = val & 0xffffff;
806 val = (val >> 24) & 0xffffu;
807 if (rem > 0x800000)
808 val++;
809 else if (rem == 0x800000)
810 val += (val & 1);
811 } else if (env->macsr & MACSR_RT) {
812 /* 32-bit rounding. */
813 rem = val & 0xff;
814 val >>= 8;
815 if (rem > 0x80)
816 val++;
817 else if (rem == 0x80)
818 val += (val & 1);
819 } else {
820 /* No rounding. */
821 val >>= 8;
823 if (env->macsr & MACSR_OMC) {
824 /* Saturate. */
825 if (env->macsr & MACSR_SU) {
826 if (val != (uint16_t) val) {
827 result = ((val >> 63) ^ 0x7fff) & 0xffff;
828 } else {
829 result = val & 0xffff;
831 } else {
832 if (val != (uint32_t)val) {
833 result = ((uint32_t)(val >> 63) & 0x7fffffff);
834 } else {
835 result = (uint32_t)val;
838 } else {
839 /* No saturation. */
840 if (env->macsr & MACSR_SU) {
841 result = val & 0xffff;
842 } else {
843 result = (uint32_t)val;
846 return result;
849 uint32_t HELPER(get_macs)(uint64_t val)
851 if (val == (int32_t)val) {
852 return (int32_t)val;
853 } else {
854 return (val >> 61) ^ ~SIGNBIT;
858 uint32_t HELPER(get_macu)(uint64_t val)
860 if ((val >> 32) == 0) {
861 return (uint32_t)val;
862 } else {
863 return 0xffffffffu;
867 uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
869 uint32_t val;
870 val = env->macc[acc] & 0x00ff;
871 val |= (env->macc[acc] >> 32) & 0xff00;
872 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
873 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
874 return val;
877 uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
879 uint32_t val;
880 val = (env->macc[acc] >> 32) & 0xffff;
881 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
882 return val;
885 void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
887 int64_t res;
888 int32_t tmp;
889 res = env->macc[acc] & 0xffffffff00ull;
890 tmp = (int16_t)(val & 0xff00);
891 res |= ((int64_t)tmp) << 32;
892 res |= val & 0xff;
893 env->macc[acc] = res;
894 res = env->macc[acc + 1] & 0xffffffff00ull;
895 tmp = (val & 0xff000000);
896 res |= ((int64_t)tmp) << 16;
897 res |= (val >> 16) & 0xff;
898 env->macc[acc + 1] = res;
901 void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
903 int64_t res;
904 int32_t tmp;
905 res = (uint32_t)env->macc[acc];
906 tmp = (int16_t)val;
907 res |= ((int64_t)tmp) << 32;
908 env->macc[acc] = res;
909 res = (uint32_t)env->macc[acc + 1];
910 tmp = val & 0xffff0000;
911 res |= (int64_t)tmp << 16;
912 env->macc[acc + 1] = res;
915 void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
917 uint64_t res;
918 res = (uint32_t)env->macc[acc];
919 res |= ((uint64_t)(val & 0xffff)) << 32;
920 env->macc[acc] = res;
921 res = (uint32_t)env->macc[acc + 1];
922 res |= (uint64_t)(val & 0xffff0000) << 16;
923 env->macc[acc + 1] = res;