]> git.proxmox.com Git - qemu.git/blob - target-m68k/helper.c
target-m68k: Use type_register() instead of type_register_static()
[qemu.git] / target-m68k / helper.c
1 /*
2 * m68k op helpers
3 *
4 * Copyright (c) 2006-2007 CodeSourcery
5 * Written by Paul Brook
6 *
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.
11 *
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.
16 *
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/>.
19 */
20
21 #include "cpu.h"
22 #include "exec/gdbstub.h"
23
24 #include "helpers.h"
25
26 #define SIGNBIT (1u << 31)
27
28 /* Sort alphabetically, except for "any". */
29 static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
30 {
31 ObjectClass *class_a = (ObjectClass *)a;
32 ObjectClass *class_b = (ObjectClass *)b;
33 const char *name_a, *name_b;
34
35 name_a = object_class_get_name(class_a);
36 name_b = object_class_get_name(class_b);
37 if (strcmp(name_a, "any") == 0) {
38 return 1;
39 } else if (strcmp(name_b, "any") == 0) {
40 return -1;
41 } else {
42 return strcasecmp(name_a, name_b);
43 }
44 }
45
46 static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
47 {
48 ObjectClass *c = data;
49 CPUListState *s = user_data;
50
51 (*s->cpu_fprintf)(s->file, "%s\n",
52 object_class_get_name(c));
53 }
54
55 void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
56 {
57 CPUListState s = {
58 .file = f,
59 .cpu_fprintf = cpu_fprintf,
60 };
61 GSList *list;
62
63 list = object_class_get_list(TYPE_M68K_CPU, false);
64 list = g_slist_sort(list, m68k_cpu_list_compare);
65 g_slist_foreach(list, m68k_cpu_list_entry, &s);
66 g_slist_free(list);
67 }
68
69 static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
70 {
71 if (n < 8) {
72 stfq_p(mem_buf, env->fregs[n]);
73 return 8;
74 }
75 if (n < 11) {
76 /* FP control registers (not implemented) */
77 memset(mem_buf, 0, 4);
78 return 4;
79 }
80 return 0;
81 }
82
83 static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
84 {
85 if (n < 8) {
86 env->fregs[n] = ldfq_p(mem_buf);
87 return 8;
88 }
89 if (n < 11) {
90 /* FP control registers (not implemented) */
91 return 4;
92 }
93 return 0;
94 }
95
96 CPUM68KState *cpu_m68k_init(const char *cpu_model)
97 {
98 M68kCPU *cpu;
99 CPUM68KState *env;
100 ObjectClass *oc;
101 static int inited;
102
103 oc = cpu_class_by_name(TYPE_M68K_CPU, cpu_model);
104 if (oc == NULL) {
105 return NULL;
106 }
107 cpu = M68K_CPU(object_new(object_class_get_name(oc)));
108 env = &cpu->env;
109
110 if (!inited) {
111 inited = 1;
112 m68k_tcg_init();
113 }
114
115 env->cpu_model_str = cpu_model;
116
117 register_m68k_insns(env);
118 if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
119 gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
120 11, "cf-fp.xml", 18);
121 }
122 /* TODO: Add [E]MAC registers. */
123
124 cpu_reset(ENV_GET_CPU(env));
125 qemu_init_vcpu(env);
126 return env;
127 }
128
129 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
130 {
131 int flags;
132 uint32_t src;
133 uint32_t dest;
134 uint32_t tmp;
135
136 #define HIGHBIT 0x80000000u
137
138 #define SET_NZ(x) do { \
139 if ((x) == 0) \
140 flags |= CCF_Z; \
141 else if ((int32_t)(x) < 0) \
142 flags |= CCF_N; \
143 } while (0)
144
145 #define SET_FLAGS_SUB(type, utype) do { \
146 SET_NZ((type)dest); \
147 tmp = dest + src; \
148 if ((utype) tmp < (utype) src) \
149 flags |= CCF_C; \
150 if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
151 flags |= CCF_V; \
152 } while (0)
153
154 flags = 0;
155 src = env->cc_src;
156 dest = env->cc_dest;
157 switch (cc_op) {
158 case CC_OP_FLAGS:
159 flags = dest;
160 break;
161 case CC_OP_LOGIC:
162 SET_NZ(dest);
163 break;
164 case CC_OP_ADD:
165 SET_NZ(dest);
166 if (dest < src)
167 flags |= CCF_C;
168 tmp = dest - src;
169 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
170 flags |= CCF_V;
171 break;
172 case CC_OP_SUB:
173 SET_FLAGS_SUB(int32_t, uint32_t);
174 break;
175 case CC_OP_CMPB:
176 SET_FLAGS_SUB(int8_t, uint8_t);
177 break;
178 case CC_OP_CMPW:
179 SET_FLAGS_SUB(int16_t, uint16_t);
180 break;
181 case CC_OP_ADDX:
182 SET_NZ(dest);
183 if (dest <= src)
184 flags |= CCF_C;
185 tmp = dest - src - 1;
186 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
187 flags |= CCF_V;
188 break;
189 case CC_OP_SUBX:
190 SET_NZ(dest);
191 tmp = dest + src + 1;
192 if (tmp <= src)
193 flags |= CCF_C;
194 if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
195 flags |= CCF_V;
196 break;
197 case CC_OP_SHIFT:
198 SET_NZ(dest);
199 if (src)
200 flags |= CCF_C;
201 break;
202 default:
203 cpu_abort(env, "Bad CC_OP %d", cc_op);
204 }
205 env->cc_op = CC_OP_FLAGS;
206 env->cc_dest = flags;
207 }
208
209 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
210 {
211 switch (reg) {
212 case 0x02: /* CACR */
213 env->cacr = val;
214 m68k_switch_sp(env);
215 break;
216 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
217 /* TODO: Implement Access Control Registers. */
218 break;
219 case 0x801: /* VBR */
220 env->vbr = val;
221 break;
222 /* TODO: Implement control registers. */
223 default:
224 cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
225 reg, val);
226 }
227 }
228
229 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
230 {
231 uint32_t acc;
232 int8_t exthigh;
233 uint8_t extlow;
234 uint64_t regval;
235 int i;
236 if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
237 for (i = 0; i < 4; i++) {
238 regval = env->macc[i];
239 exthigh = regval >> 40;
240 if (env->macsr & MACSR_FI) {
241 acc = regval >> 8;
242 extlow = regval;
243 } else {
244 acc = regval;
245 extlow = regval >> 32;
246 }
247 if (env->macsr & MACSR_FI) {
248 regval = (((uint64_t)acc) << 8) | extlow;
249 regval |= ((int64_t)exthigh) << 40;
250 } else if (env->macsr & MACSR_SU) {
251 regval = acc | (((int64_t)extlow) << 32);
252 regval |= ((int64_t)exthigh) << 40;
253 } else {
254 regval = acc | (((uint64_t)extlow) << 32);
255 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
256 }
257 env->macc[i] = regval;
258 }
259 }
260 env->macsr = val;
261 }
262
263 void m68k_switch_sp(CPUM68KState *env)
264 {
265 int new_sp;
266
267 env->sp[env->current_sp] = env->aregs[7];
268 new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
269 ? M68K_SSP : M68K_USP;
270 env->aregs[7] = env->sp[new_sp];
271 env->current_sp = new_sp;
272 }
273
274 #if defined(CONFIG_USER_ONLY)
275
276 int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
277 int mmu_idx)
278 {
279 env->exception_index = EXCP_ACCESS;
280 env->mmu.ar = address;
281 return 1;
282 }
283
284 #else
285
286 /* MMU */
287
288 /* TODO: This will need fixing once the MMU is implemented. */
289 hwaddr cpu_get_phys_page_debug(CPUM68KState *env, target_ulong addr)
290 {
291 return addr;
292 }
293
294 int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
295 int mmu_idx)
296 {
297 int prot;
298
299 address &= TARGET_PAGE_MASK;
300 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
301 tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
302 return 0;
303 }
304
305 /* Notify CPU of a pending interrupt. Prioritization and vectoring should
306 be handled by the interrupt controller. Real hardware only requests
307 the vector when the interrupt is acknowledged by the CPU. For
308 simplicitly we calculate it when the interrupt is signalled. */
309 void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
310 {
311 env->pending_level = level;
312 env->pending_vector = vector;
313 if (level)
314 cpu_interrupt(env, CPU_INTERRUPT_HARD);
315 else
316 cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
317 }
318
319 #endif
320
321 uint32_t HELPER(bitrev)(uint32_t x)
322 {
323 x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
324 x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
325 x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
326 return bswap32(x);
327 }
328
329 uint32_t HELPER(ff1)(uint32_t x)
330 {
331 int n;
332 for (n = 32; x; n--)
333 x >>= 1;
334 return n;
335 }
336
337 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
338 {
339 /* The result has the opposite sign to the original value. */
340 if (ccr & CCF_V)
341 val = (((int32_t)val) >> 31) ^ SIGNBIT;
342 return val;
343 }
344
345 uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
346 {
347 uint32_t res;
348 uint32_t old_flags;
349
350 old_flags = env->cc_dest;
351 if (env->cc_x) {
352 env->cc_x = (op1 <= op2);
353 env->cc_op = CC_OP_SUBX;
354 res = op1 - (op2 + 1);
355 } else {
356 env->cc_x = (op1 < op2);
357 env->cc_op = CC_OP_SUB;
358 res = op1 - op2;
359 }
360 env->cc_dest = res;
361 env->cc_src = op2;
362 cpu_m68k_flush_flags(env, env->cc_op);
363 /* !Z is sticky. */
364 env->cc_dest &= (old_flags | ~CCF_Z);
365 return res;
366 }
367
368 uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
369 {
370 uint32_t res;
371 uint32_t old_flags;
372
373 old_flags = env->cc_dest;
374 if (env->cc_x) {
375 res = op1 + op2 + 1;
376 env->cc_x = (res <= op2);
377 env->cc_op = CC_OP_ADDX;
378 } else {
379 res = op1 + op2;
380 env->cc_x = (res < op2);
381 env->cc_op = CC_OP_ADD;
382 }
383 env->cc_dest = res;
384 env->cc_src = op2;
385 cpu_m68k_flush_flags(env, env->cc_op);
386 /* !Z is sticky. */
387 env->cc_dest &= (old_flags | ~CCF_Z);
388 return res;
389 }
390
391 uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
392 {
393 return a < b;
394 }
395
396 void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
397 {
398 env->sr = val & 0xffff;
399 m68k_switch_sp(env);
400 }
401
402 uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
403 {
404 uint32_t result;
405 uint32_t cf;
406
407 shift &= 63;
408 if (shift == 0) {
409 result = val;
410 cf = env->cc_src & CCF_C;
411 } else if (shift < 32) {
412 result = val << shift;
413 cf = (val >> (32 - shift)) & 1;
414 } else if (shift == 32) {
415 result = 0;
416 cf = val & 1;
417 } else /* shift > 32 */ {
418 result = 0;
419 cf = 0;
420 }
421 env->cc_src = cf;
422 env->cc_x = (cf != 0);
423 env->cc_dest = result;
424 return result;
425 }
426
427 uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
428 {
429 uint32_t result;
430 uint32_t cf;
431
432 shift &= 63;
433 if (shift == 0) {
434 result = val;
435 cf = env->cc_src & CCF_C;
436 } else if (shift < 32) {
437 result = val >> shift;
438 cf = (val >> (shift - 1)) & 1;
439 } else if (shift == 32) {
440 result = 0;
441 cf = val >> 31;
442 } else /* shift > 32 */ {
443 result = 0;
444 cf = 0;
445 }
446 env->cc_src = cf;
447 env->cc_x = (cf != 0);
448 env->cc_dest = result;
449 return result;
450 }
451
452 uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
453 {
454 uint32_t result;
455 uint32_t cf;
456
457 shift &= 63;
458 if (shift == 0) {
459 result = val;
460 cf = (env->cc_src & CCF_C) != 0;
461 } else if (shift < 32) {
462 result = (int32_t)val >> shift;
463 cf = (val >> (shift - 1)) & 1;
464 } else /* shift >= 32 */ {
465 result = (int32_t)val >> 31;
466 cf = val >> 31;
467 }
468 env->cc_src = cf;
469 env->cc_x = cf;
470 env->cc_dest = result;
471 return result;
472 }
473
474 /* FPU helpers. */
475 uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
476 {
477 return float64_to_int32(val, &env->fp_status);
478 }
479
480 float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
481 {
482 return float64_to_float32(val, &env->fp_status);
483 }
484
485 float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
486 {
487 return int32_to_float64(val, &env->fp_status);
488 }
489
490 float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
491 {
492 return float32_to_float64(val, &env->fp_status);
493 }
494
495 float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
496 {
497 return float64_round_to_int(val, &env->fp_status);
498 }
499
500 float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
501 {
502 return float64_trunc_to_int(val, &env->fp_status);
503 }
504
505 float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val)
506 {
507 return float64_sqrt(val, &env->fp_status);
508 }
509
510 float64 HELPER(abs_f64)(float64 val)
511 {
512 return float64_abs(val);
513 }
514
515 float64 HELPER(chs_f64)(float64 val)
516 {
517 return float64_chs(val);
518 }
519
520 float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b)
521 {
522 return float64_add(a, b, &env->fp_status);
523 }
524
525 float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
526 {
527 return float64_sub(a, b, &env->fp_status);
528 }
529
530 float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
531 {
532 return float64_mul(a, b, &env->fp_status);
533 }
534
535 float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
536 {
537 return float64_div(a, b, &env->fp_status);
538 }
539
540 float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b)
541 {
542 /* ??? This may incorrectly raise exceptions. */
543 /* ??? Should flush denormals to zero. */
544 float64 res;
545 res = float64_sub(a, b, &env->fp_status);
546 if (float64_is_quiet_nan(res)) {
547 /* +/-inf compares equal against itself, but sub returns nan. */
548 if (!float64_is_quiet_nan(a)
549 && !float64_is_quiet_nan(b)) {
550 res = float64_zero;
551 if (float64_lt_quiet(a, res, &env->fp_status))
552 res = float64_chs(res);
553 }
554 }
555 return res;
556 }
557
558 uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val)
559 {
560 return float64_compare_quiet(val, float64_zero, &env->fp_status);
561 }
562
563 /* MAC unit. */
564 /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
565 take values, others take register numbers and manipulate the contents
566 in-place. */
567 void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
568 {
569 uint32_t mask;
570 env->macc[dest] = env->macc[src];
571 mask = MACSR_PAV0 << dest;
572 if (env->macsr & (MACSR_PAV0 << src))
573 env->macsr |= mask;
574 else
575 env->macsr &= ~mask;
576 }
577
578 uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
579 {
580 int64_t product;
581 int64_t res;
582
583 product = (uint64_t)op1 * op2;
584 res = (product << 24) >> 24;
585 if (res != product) {
586 env->macsr |= MACSR_V;
587 if (env->macsr & MACSR_OMC) {
588 /* Make sure the accumulate operation overflows. */
589 if (product < 0)
590 res = ~(1ll << 50);
591 else
592 res = 1ll << 50;
593 }
594 }
595 return res;
596 }
597
598 uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
599 {
600 uint64_t product;
601
602 product = (uint64_t)op1 * op2;
603 if (product & (0xffffffull << 40)) {
604 env->macsr |= MACSR_V;
605 if (env->macsr & MACSR_OMC) {
606 /* Make sure the accumulate operation overflows. */
607 product = 1ll << 50;
608 } else {
609 product &= ((1ull << 40) - 1);
610 }
611 }
612 return product;
613 }
614
615 uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
616 {
617 uint64_t product;
618 uint32_t remainder;
619
620 product = (uint64_t)op1 * op2;
621 if (env->macsr & MACSR_RT) {
622 remainder = product & 0xffffff;
623 product >>= 24;
624 if (remainder > 0x800000)
625 product++;
626 else if (remainder == 0x800000)
627 product += (product & 1);
628 } else {
629 product >>= 24;
630 }
631 return product;
632 }
633
634 void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
635 {
636 int64_t tmp;
637 int64_t result;
638 tmp = env->macc[acc];
639 result = ((tmp << 16) >> 16);
640 if (result != tmp) {
641 env->macsr |= MACSR_V;
642 }
643 if (env->macsr & MACSR_V) {
644 env->macsr |= MACSR_PAV0 << acc;
645 if (env->macsr & MACSR_OMC) {
646 /* The result is saturated to 32 bits, despite overflow occurring
647 at 48 bits. Seems weird, but that's what the hardware docs
648 say. */
649 result = (result >> 63) ^ 0x7fffffff;
650 }
651 }
652 env->macc[acc] = result;
653 }
654
655 void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
656 {
657 uint64_t val;
658
659 val = env->macc[acc];
660 if (val & (0xffffull << 48)) {
661 env->macsr |= MACSR_V;
662 }
663 if (env->macsr & MACSR_V) {
664 env->macsr |= MACSR_PAV0 << acc;
665 if (env->macsr & MACSR_OMC) {
666 if (val > (1ull << 53))
667 val = 0;
668 else
669 val = (1ull << 48) - 1;
670 } else {
671 val &= ((1ull << 48) - 1);
672 }
673 }
674 env->macc[acc] = val;
675 }
676
677 void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
678 {
679 int64_t sum;
680 int64_t result;
681
682 sum = env->macc[acc];
683 result = (sum << 16) >> 16;
684 if (result != sum) {
685 env->macsr |= MACSR_V;
686 }
687 if (env->macsr & MACSR_V) {
688 env->macsr |= MACSR_PAV0 << acc;
689 if (env->macsr & MACSR_OMC) {
690 result = (result >> 63) ^ 0x7fffffffffffll;
691 }
692 }
693 env->macc[acc] = result;
694 }
695
696 void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
697 {
698 uint64_t val;
699 val = env->macc[acc];
700 if (val == 0) {
701 env->macsr |= MACSR_Z;
702 } else if (val & (1ull << 47)) {
703 env->macsr |= MACSR_N;
704 }
705 if (env->macsr & (MACSR_PAV0 << acc)) {
706 env->macsr |= MACSR_V;
707 }
708 if (env->macsr & MACSR_FI) {
709 val = ((int64_t)val) >> 40;
710 if (val != 0 && val != -1)
711 env->macsr |= MACSR_EV;
712 } else if (env->macsr & MACSR_SU) {
713 val = ((int64_t)val) >> 32;
714 if (val != 0 && val != -1)
715 env->macsr |= MACSR_EV;
716 } else {
717 if ((val >> 32) != 0)
718 env->macsr |= MACSR_EV;
719 }
720 }
721
722 void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
723 {
724 cpu_m68k_flush_flags(env, cc_op);
725 }
726
727 uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
728 {
729 int rem;
730 uint32_t result;
731
732 if (env->macsr & MACSR_SU) {
733 /* 16-bit rounding. */
734 rem = val & 0xffffff;
735 val = (val >> 24) & 0xffffu;
736 if (rem > 0x800000)
737 val++;
738 else if (rem == 0x800000)
739 val += (val & 1);
740 } else if (env->macsr & MACSR_RT) {
741 /* 32-bit rounding. */
742 rem = val & 0xff;
743 val >>= 8;
744 if (rem > 0x80)
745 val++;
746 else if (rem == 0x80)
747 val += (val & 1);
748 } else {
749 /* No rounding. */
750 val >>= 8;
751 }
752 if (env->macsr & MACSR_OMC) {
753 /* Saturate. */
754 if (env->macsr & MACSR_SU) {
755 if (val != (uint16_t) val) {
756 result = ((val >> 63) ^ 0x7fff) & 0xffff;
757 } else {
758 result = val & 0xffff;
759 }
760 } else {
761 if (val != (uint32_t)val) {
762 result = ((uint32_t)(val >> 63) & 0x7fffffff);
763 } else {
764 result = (uint32_t)val;
765 }
766 }
767 } else {
768 /* No saturation. */
769 if (env->macsr & MACSR_SU) {
770 result = val & 0xffff;
771 } else {
772 result = (uint32_t)val;
773 }
774 }
775 return result;
776 }
777
778 uint32_t HELPER(get_macs)(uint64_t val)
779 {
780 if (val == (int32_t)val) {
781 return (int32_t)val;
782 } else {
783 return (val >> 61) ^ ~SIGNBIT;
784 }
785 }
786
787 uint32_t HELPER(get_macu)(uint64_t val)
788 {
789 if ((val >> 32) == 0) {
790 return (uint32_t)val;
791 } else {
792 return 0xffffffffu;
793 }
794 }
795
796 uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
797 {
798 uint32_t val;
799 val = env->macc[acc] & 0x00ff;
800 val = (env->macc[acc] >> 32) & 0xff00;
801 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
802 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
803 return val;
804 }
805
806 uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
807 {
808 uint32_t val;
809 val = (env->macc[acc] >> 32) & 0xffff;
810 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
811 return val;
812 }
813
814 void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
815 {
816 int64_t res;
817 int32_t tmp;
818 res = env->macc[acc] & 0xffffffff00ull;
819 tmp = (int16_t)(val & 0xff00);
820 res |= ((int64_t)tmp) << 32;
821 res |= val & 0xff;
822 env->macc[acc] = res;
823 res = env->macc[acc + 1] & 0xffffffff00ull;
824 tmp = (val & 0xff000000);
825 res |= ((int64_t)tmp) << 16;
826 res |= (val >> 16) & 0xff;
827 env->macc[acc + 1] = res;
828 }
829
830 void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
831 {
832 int64_t res;
833 int32_t tmp;
834 res = (uint32_t)env->macc[acc];
835 tmp = (int16_t)val;
836 res |= ((int64_t)tmp) << 32;
837 env->macc[acc] = res;
838 res = (uint32_t)env->macc[acc + 1];
839 tmp = val & 0xffff0000;
840 res |= (int64_t)tmp << 16;
841 env->macc[acc + 1] = res;
842 }
843
844 void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
845 {
846 uint64_t res;
847 res = (uint32_t)env->macc[acc];
848 res |= ((uint64_t)(val & 0xffff)) << 32;
849 env->macc[acc] = res;
850 res = (uint32_t)env->macc[acc + 1];
851 res |= (uint64_t)(val & 0xffff0000) << 16;
852 env->macc[acc + 1] = res;
853 }