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