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