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