]> git.proxmox.com Git - qemu.git/blob - target-m68k/op.c
ColdFire EMAC support.
[qemu.git] / target-m68k / op.c
1 /*
2 * m68k micro operations
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, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include "exec.h"
23 #include "m68k-qreg.h"
24
25 #ifndef offsetof
26 #define offsetof(type, field) ((size_t) &((type *)0)->field)
27 #endif
28
29 static long qreg_offsets[] = {
30 #define DEFO32(name, offset) offsetof(CPUState, offset),
31 #define DEFR(name, reg, mode) -1,
32 #define DEFF64(name, offset) offsetof(CPUState, offset),
33 0,
34 #include "qregs.def"
35 };
36
37 #define CPU_FP_STATUS env->fp_status
38
39 #define RAISE_EXCEPTION(n) do { \
40 env->exception_index = n; \
41 cpu_loop_exit(); \
42 } while(0)
43
44 #define get_op helper_get_op
45 #define set_op helper_set_op
46 #define get_opf64 helper_get_opf64
47 #define set_opf64 helper_set_opf64
48 uint32_t
49 get_op(int qreg)
50 {
51 if (qreg >= TARGET_NUM_QREGS) {
52 return env->qregs[qreg - TARGET_NUM_QREGS];
53 } else if (qreg == QREG_T0) {
54 return T0;
55 } else {
56 return *(uint32_t *)(((long)env) + qreg_offsets[qreg]);
57 }
58 }
59
60 void set_op(int qreg, uint32_t val)
61 {
62 if (qreg >= TARGET_NUM_QREGS) {
63 env->qregs[qreg - TARGET_NUM_QREGS] = val;
64 } else if (qreg == QREG_T0) {
65 T0 = val;
66 } else {
67 *(uint32_t *)(((long)env) + qreg_offsets[qreg]) = val;
68 }
69 }
70
71 float64 get_opf64(int qreg)
72 {
73 if (qreg < TARGET_NUM_QREGS) {
74 return *(float64 *)(((long)env) + qreg_offsets[qreg]);
75 } else {
76 return *(float64 *)&env->qregs[qreg - TARGET_NUM_QREGS];
77 }
78 }
79
80 void set_opf64(int qreg, float64 val)
81 {
82 if (qreg < TARGET_NUM_QREGS) {
83 *(float64 *)(((long)env) + qreg_offsets[qreg]) = val;
84 } else {
85 *(float64 *)&env->qregs[qreg - TARGET_NUM_QREGS] = val;
86 }
87 }
88
89 #define OP(name) void OPPROTO glue(op_,name) (void)
90
91 OP(mov32)
92 {
93 set_op(PARAM1, get_op(PARAM2));
94 FORCE_RET();
95 }
96
97 OP(mov32_im)
98 {
99 set_op(PARAM1, PARAM2);
100 FORCE_RET();
101 }
102
103 OP(movf64)
104 {
105 set_opf64(PARAM1, get_opf64(PARAM2));
106 FORCE_RET();
107 }
108
109 OP(zerof64)
110 {
111 set_opf64(PARAM1, 0);
112 FORCE_RET();
113 }
114
115 OP(add32)
116 {
117 uint32_t op2 = get_op(PARAM2);
118 uint32_t op3 = get_op(PARAM3);
119 set_op(PARAM1, op2 + op3);
120 FORCE_RET();
121 }
122
123 OP(sub32)
124 {
125 uint32_t op2 = get_op(PARAM2);
126 uint32_t op3 = get_op(PARAM3);
127 set_op(PARAM1, op2 - op3);
128 FORCE_RET();
129 }
130
131 OP(mul32)
132 {
133 uint32_t op2 = get_op(PARAM2);
134 uint32_t op3 = get_op(PARAM3);
135 set_op(PARAM1, op2 * op3);
136 FORCE_RET();
137 }
138
139 OP(not32)
140 {
141 uint32_t arg = get_op(PARAM2);
142 set_op(PARAM1, ~arg);
143 FORCE_RET();
144 }
145
146 OP(neg32)
147 {
148 uint32_t arg = get_op(PARAM2);
149 set_op(PARAM1, -arg);
150 FORCE_RET();
151 }
152
153 OP(bswap32)
154 {
155 uint32_t arg = get_op(PARAM2);
156 arg = (arg >> 24) | (arg << 24)
157 | ((arg >> 16) & 0xff00) | ((arg << 16) & 0xff0000);
158 set_op(PARAM1, arg);
159 FORCE_RET();
160 }
161
162 OP(btest)
163 {
164 uint32_t op1 = get_op(PARAM1);
165 uint32_t op2 = get_op(PARAM2);
166 if (op1 & op2)
167 env->cc_dest &= ~CCF_Z;
168 else
169 env->cc_dest |= CCF_Z;
170 FORCE_RET();
171 }
172
173 OP(ff1)
174 {
175 uint32_t arg = get_op(PARAM2);
176 int n;
177 for (n = 32; arg; n--)
178 arg >>= 1;
179 set_op(PARAM1, n);
180 FORCE_RET();
181 }
182
183 OP(subx_cc)
184 {
185 uint32_t op1 = get_op(PARAM1);
186 uint32_t op2 = get_op(PARAM2);
187 uint32_t res;
188 if (env->cc_x) {
189 env->cc_x = (op1 <= op2);
190 env->cc_op = CC_OP_SUBX;
191 res = op1 - (op2 + 1);
192 } else {
193 env->cc_x = (op1 < op2);
194 env->cc_op = CC_OP_SUB;
195 res = op1 - op2;
196 }
197 set_op(PARAM1, res);
198 FORCE_RET();
199 }
200
201 OP(addx_cc)
202 {
203 uint32_t op1 = get_op(PARAM1);
204 uint32_t op2 = get_op(PARAM2);
205 uint32_t res;
206 if (env->cc_x) {
207 res = op1 + op2 + 1;
208 env->cc_x = (res <= op2);
209 env->cc_op = CC_OP_ADDX;
210 } else {
211 res = op1 + op2;
212 env->cc_x = (res < op2);
213 env->cc_op = CC_OP_ADD;
214 }
215 set_op(PARAM1, res);
216 FORCE_RET();
217 }
218
219 /* Logic ops. */
220
221 OP(and32)
222 {
223 uint32_t op2 = get_op(PARAM2);
224 uint32_t op3 = get_op(PARAM3);
225 set_op(PARAM1, op2 & op3);
226 FORCE_RET();
227 }
228
229 OP(or32)
230 {
231 uint32_t op2 = get_op(PARAM2);
232 uint32_t op3 = get_op(PARAM3);
233 set_op(PARAM1, op2 | op3);
234 FORCE_RET();
235 }
236
237 OP(xor32)
238 {
239 uint32_t op2 = get_op(PARAM2);
240 uint32_t op3 = get_op(PARAM3);
241 set_op(PARAM1, op2 ^ op3);
242 FORCE_RET();
243 }
244
245 /* Shifts. */
246 OP(shl32)
247 {
248 uint32_t op2 = get_op(PARAM2);
249 uint32_t op3 = get_op(PARAM3);
250 uint32_t result;
251 result = op2 << op3;
252 set_op(PARAM1, result);
253 FORCE_RET();
254 }
255
256 OP(shl_cc)
257 {
258 uint32_t op1 = get_op(PARAM1);
259 uint32_t op2 = get_op(PARAM2);
260 uint32_t result;
261 result = op1 << op2;
262 set_op(PARAM1, result);
263 env->cc_x = (op1 << (op2 - 1)) & 1;
264 FORCE_RET();
265 }
266
267 OP(shr32)
268 {
269 uint32_t op2 = get_op(PARAM2);
270 uint32_t op3 = get_op(PARAM3);
271 uint32_t result;
272 result = op2 >> op3;
273 set_op(PARAM1, result);
274 FORCE_RET();
275 }
276
277 OP(shr_cc)
278 {
279 uint32_t op1 = get_op(PARAM1);
280 uint32_t op2 = get_op(PARAM2);
281 uint32_t result;
282 result = op1 >> op2;
283 set_op(PARAM1, result);
284 env->cc_x = (op1 >> (op2 - 1)) & 1;
285 FORCE_RET();
286 }
287
288 OP(sar32)
289 {
290 int32_t op2 = get_op(PARAM2);
291 uint32_t op3 = get_op(PARAM3);
292 uint32_t result;
293 result = op2 >> op3;
294 set_op(PARAM1, result);
295 FORCE_RET();
296 }
297
298 OP(sar_cc)
299 {
300 int32_t op1 = get_op(PARAM1);
301 uint32_t op2 = get_op(PARAM2);
302 uint32_t result;
303 result = op1 >> op2;
304 set_op(PARAM1, result);
305 env->cc_x = (op1 >> (op2 - 1)) & 1;
306 FORCE_RET();
307 }
308
309 /* Value extend. */
310
311 OP(ext8u32)
312 {
313 uint32_t op2 = get_op(PARAM2);
314 set_op(PARAM1, (uint8_t)op2);
315 FORCE_RET();
316 }
317
318 OP(ext8s32)
319 {
320 uint32_t op2 = get_op(PARAM2);
321 set_op(PARAM1, (int8_t)op2);
322 FORCE_RET();
323 }
324
325 OP(ext16u32)
326 {
327 uint32_t op2 = get_op(PARAM2);
328 set_op(PARAM1, (uint16_t)op2);
329 FORCE_RET();
330 }
331
332 OP(ext16s32)
333 {
334 uint32_t op2 = get_op(PARAM2);
335 set_op(PARAM1, (int16_t)op2);
336 FORCE_RET();
337 }
338
339 OP(flush_flags)
340 {
341 int cc_op = PARAM1;
342 if (cc_op == CC_OP_DYNAMIC)
343 cc_op = env->cc_op;
344 cpu_m68k_flush_flags(env, cc_op);
345 FORCE_RET();
346 }
347
348 OP(divu)
349 {
350 uint32_t num;
351 uint32_t den;
352 uint32_t quot;
353 uint32_t rem;
354 uint32_t flags;
355
356 num = env->div1;
357 den = env->div2;
358 /* ??? This needs to make sure the throwing location is accurate. */
359 if (den == 0)
360 RAISE_EXCEPTION(EXCP_DIV0);
361 quot = num / den;
362 rem = num % den;
363 flags = 0;
364 /* Avoid using a PARAM1 of zero. This breaks dyngen because it uses
365 the address of a symbol, and gcc knows symbols can't have address
366 zero. */
367 if (PARAM1 == 2 && quot > 0xffff)
368 flags |= CCF_V;
369 if (quot == 0)
370 flags |= CCF_Z;
371 else if ((int32_t)quot < 0)
372 flags |= CCF_N;
373 env->div1 = quot;
374 env->div2 = rem;
375 env->cc_dest = flags;
376 FORCE_RET();
377 }
378
379 OP(divs)
380 {
381 int32_t num;
382 int32_t den;
383 int32_t quot;
384 int32_t rem;
385 int32_t flags;
386
387 num = env->div1;
388 den = env->div2;
389 if (den == 0)
390 RAISE_EXCEPTION(EXCP_DIV0);
391 quot = num / den;
392 rem = num % den;
393 flags = 0;
394 if (PARAM1 == 2 && quot != (int16_t)quot)
395 flags |= CCF_V;
396 if (quot == 0)
397 flags |= CCF_Z;
398 else if (quot < 0)
399 flags |= CCF_N;
400 env->div1 = quot;
401 env->div2 = rem;
402 env->cc_dest = flags;
403 FORCE_RET();
404 }
405
406 /* Halt is special because it may be a semihosting call. */
407 OP(halt)
408 {
409 RAISE_EXCEPTION(EXCP_HALT_INSN);
410 FORCE_RET();
411 }
412
413 OP(stop)
414 {
415 env->halted = 1;
416 RAISE_EXCEPTION(EXCP_HLT);
417 FORCE_RET();
418 }
419
420 OP(raise_exception)
421 {
422 RAISE_EXCEPTION(PARAM1);
423 FORCE_RET();
424 }
425
426 /* Floating point comparison sets flags differently to other instructions. */
427
428 OP(sub_cmpf64)
429 {
430 float64 src0;
431 float64 src1;
432 src0 = get_opf64(PARAM2);
433 src1 = get_opf64(PARAM3);
434 set_opf64(PARAM1, helper_sub_cmpf64(env, src0, src1));
435 FORCE_RET();
436 }
437
438 OP(update_xflag_tst)
439 {
440 uint32_t op1 = get_op(PARAM1);
441 env->cc_x = op1;
442 FORCE_RET();
443 }
444
445 OP(update_xflag_lt)
446 {
447 uint32_t op1 = get_op(PARAM1);
448 uint32_t op2 = get_op(PARAM2);
449 env->cc_x = (op1 < op2);
450 FORCE_RET();
451 }
452
453 OP(get_xflag)
454 {
455 set_op(PARAM1, env->cc_x);
456 FORCE_RET();
457 }
458
459 OP(logic_cc)
460 {
461 uint32_t op1 = get_op(PARAM1);
462 env->cc_dest = op1;
463 FORCE_RET();
464 }
465
466 OP(update_cc_add)
467 {
468 uint32_t op1 = get_op(PARAM1);
469 uint32_t op2 = get_op(PARAM2);
470 env->cc_dest = op1;
471 env->cc_src = op2;
472 FORCE_RET();
473 }
474
475 OP(fp_result)
476 {
477 env->fp_result = get_opf64(PARAM1);
478 FORCE_RET();
479 }
480
481 OP(jmp)
482 {
483 GOTO_LABEL_PARAM(1);
484 }
485
486 /* These ops involve a function call, which probably requires a stack frame
487 and breaks things on some hosts. */
488 OP(jmp_z32)
489 {
490 uint32_t arg = get_op(PARAM1);
491 if (arg == 0)
492 GOTO_LABEL_PARAM(2);
493 FORCE_RET();
494 }
495
496 OP(jmp_nz32)
497 {
498 uint32_t arg = get_op(PARAM1);
499 if (arg != 0)
500 GOTO_LABEL_PARAM(2);
501 FORCE_RET();
502 }
503
504 OP(jmp_s32)
505 {
506 int32_t arg = get_op(PARAM1);
507 if (arg < 0)
508 GOTO_LABEL_PARAM(2);
509 FORCE_RET();
510 }
511
512 OP(jmp_ns32)
513 {
514 int32_t arg = get_op(PARAM1);
515 if (arg >= 0)
516 GOTO_LABEL_PARAM(2);
517 FORCE_RET();
518 }
519
520 void OPPROTO op_goto_tb0(void)
521 {
522 GOTO_TB(op_goto_tb0, PARAM1, 0);
523 }
524
525 void OPPROTO op_goto_tb1(void)
526 {
527 GOTO_TB(op_goto_tb1, PARAM1, 1);
528 }
529
530 OP(exit_tb)
531 {
532 EXIT_TB();
533 }
534
535
536 /* Floating point. */
537 OP(f64_to_i32)
538 {
539 set_op(PARAM1, float64_to_int32(get_opf64(PARAM2), &CPU_FP_STATUS));
540 FORCE_RET();
541 }
542
543 OP(f64_to_f32)
544 {
545 union {
546 float32 f;
547 uint32_t i;
548 } u;
549 u.f = float64_to_float32(get_opf64(PARAM2), &CPU_FP_STATUS);
550 set_op(PARAM1, u.i);
551 FORCE_RET();
552 }
553
554 OP(i32_to_f64)
555 {
556 set_opf64(PARAM1, int32_to_float64(get_op(PARAM2), &CPU_FP_STATUS));
557 FORCE_RET();
558 }
559
560 OP(f32_to_f64)
561 {
562 union {
563 float32 f;
564 uint32_t i;
565 } u;
566 u.i = get_op(PARAM2);
567 set_opf64(PARAM1, float32_to_float64(u.f, &CPU_FP_STATUS));
568 FORCE_RET();
569 }
570
571 OP(absf64)
572 {
573 float64 op0 = get_opf64(PARAM2);
574 set_opf64(PARAM1, float64_abs(op0));
575 FORCE_RET();
576 }
577
578 OP(chsf64)
579 {
580 float64 op0 = get_opf64(PARAM2);
581 set_opf64(PARAM1, float64_chs(op0));
582 FORCE_RET();
583 }
584
585 OP(sqrtf64)
586 {
587 float64 op0 = get_opf64(PARAM2);
588 set_opf64(PARAM1, float64_sqrt(op0, &CPU_FP_STATUS));
589 FORCE_RET();
590 }
591
592 OP(addf64)
593 {
594 float64 op0 = get_opf64(PARAM2);
595 float64 op1 = get_opf64(PARAM3);
596 set_opf64(PARAM1, float64_add(op0, op1, &CPU_FP_STATUS));
597 FORCE_RET();
598 }
599
600 OP(subf64)
601 {
602 float64 op0 = get_opf64(PARAM2);
603 float64 op1 = get_opf64(PARAM3);
604 set_opf64(PARAM1, float64_sub(op0, op1, &CPU_FP_STATUS));
605 FORCE_RET();
606 }
607
608 OP(mulf64)
609 {
610 float64 op0 = get_opf64(PARAM2);
611 float64 op1 = get_opf64(PARAM3);
612 set_opf64(PARAM1, float64_mul(op0, op1, &CPU_FP_STATUS));
613 FORCE_RET();
614 }
615
616 OP(divf64)
617 {
618 float64 op0 = get_opf64(PARAM2);
619 float64 op1 = get_opf64(PARAM3);
620 set_opf64(PARAM1, float64_div(op0, op1, &CPU_FP_STATUS));
621 FORCE_RET();
622 }
623
624 OP(iround_f64)
625 {
626 float64 op0 = get_opf64(PARAM2);
627 set_opf64(PARAM1, float64_round_to_int(op0, &CPU_FP_STATUS));
628 FORCE_RET();
629 }
630
631 OP(itrunc_f64)
632 {
633 float64 op0 = get_opf64(PARAM2);
634 set_opf64(PARAM1, float64_trunc_to_int(op0, &CPU_FP_STATUS));
635 FORCE_RET();
636 }
637
638 OP(compare_quietf64)
639 {
640 float64 op0 = get_opf64(PARAM2);
641 float64 op1 = get_opf64(PARAM3);
642 set_op(PARAM1, float64_compare_quiet(op0, op1, &CPU_FP_STATUS));
643 FORCE_RET();
644 }
645
646 OP(movec)
647 {
648 int op1 = get_op(PARAM1);
649 uint32_t op2 = get_op(PARAM2);
650 helper_movec(env, op1, op2);
651 }
652
653 /* Memory access. */
654
655 #define MEMSUFFIX _raw
656 #include "op_mem.h"
657
658 #if !defined(CONFIG_USER_ONLY)
659 #define MEMSUFFIX _user
660 #include "op_mem.h"
661 #define MEMSUFFIX _kernel
662 #include "op_mem.h"
663 #endif
664
665 /* MAC unit. */
666 /* TODO: The MAC instructions use 64-bit arithmetic fairly extensively.
667 This results in fairly large ops (and sometimes other issues) on 32-bit
668 hosts. Maybe move most of them into helpers. */
669 OP(macmuls)
670 {
671 uint32_t op1 = get_op(PARAM1);
672 uint32_t op2 = get_op(PARAM2);
673 int64_t product;
674 int64_t res;
675
676 product = (uint64_t)op1 * op2;
677 res = (product << 24) >> 24;
678 if (res != product) {
679 env->macsr |= MACSR_V;
680 if (env->macsr & MACSR_OMC) {
681 /* Make sure the accumulate operation overflows. */
682 if (product < 0)
683 res = ~(1ll << 50);
684 else
685 res = 1ll << 50;
686 }
687 }
688 env->mactmp = res;
689 FORCE_RET();
690 }
691
692 OP(macmulu)
693 {
694 uint32_t op1 = get_op(PARAM1);
695 uint32_t op2 = get_op(PARAM2);
696 uint64_t product;
697
698 product = (uint64_t)op1 * op2;
699 if (product & (0xffffffull << 40)) {
700 env->macsr |= MACSR_V;
701 if (env->macsr & MACSR_OMC) {
702 /* Make sure the accumulate operation overflows. */
703 product = 1ll << 50;
704 } else {
705 product &= ((1ull << 40) - 1);
706 }
707 }
708 env->mactmp = product;
709 FORCE_RET();
710 }
711
712 OP(macmulf)
713 {
714 int32_t op1 = get_op(PARAM1);
715 int32_t op2 = get_op(PARAM2);
716 uint64_t product;
717 uint32_t remainder;
718
719 product = (uint64_t)op1 * op2;
720 if (env->macsr & MACSR_RT) {
721 remainder = product & 0xffffff;
722 product >>= 24;
723 if (remainder > 0x800000)
724 product++;
725 else if (remainder == 0x800000)
726 product += (product & 1);
727 } else {
728 product >>= 24;
729 }
730 env->mactmp = product;
731 FORCE_RET();
732 }
733
734 OP(macshl)
735 {
736 env->mactmp <<= 1;
737 }
738
739 OP(macshr)
740 {
741 env->mactmp >>= 1;
742 }
743
744 OP(macadd)
745 {
746 int acc = PARAM1;
747 env->macc[acc] += env->mactmp;
748 FORCE_RET();
749 }
750
751 OP(macsub)
752 {
753 int acc = PARAM1;
754 env->macc[acc] -= env->mactmp;
755 FORCE_RET();
756 }
757
758 OP(macsats)
759 {
760 int acc = PARAM1;
761 int64_t sum;
762 int64_t result;
763
764 sum = env->macc[acc];
765 result = (sum << 16) >> 16;
766 if (result != sum) {
767 env->macsr |= MACSR_V;
768 }
769 if (env->macsr & MACSR_V) {
770 env->macsr |= MACSR_PAV0 << acc;
771 if (env->macsr & MACSR_OMC) {
772 /* The result is saturated to 32 bits, despite overflow occuring
773 at 48 bits. Seems weird, but that's what the hardware docs
774 say. */
775 result = (result >> 63) ^ 0x7fffffff;
776 }
777 }
778 env->macc[acc] = result;
779 FORCE_RET();
780 }
781
782 OP(macsatu)
783 {
784 int acc = PARAM1;
785 uint64_t sum;
786
787 sum = env->macc[acc];
788 if (sum & (0xffffull << 48)) {
789 env->macsr |= MACSR_V;
790 }
791 if (env->macsr & MACSR_V) {
792 env->macsr |= MACSR_PAV0 << acc;
793 if (env->macsr & MACSR_OMC) {
794 if (sum > (1ull << 53))
795 sum = 0;
796 else
797 sum = (1ull << 48) - 1;
798 } else {
799 sum &= ((1ull << 48) - 1);
800 }
801 }
802 FORCE_RET();
803 }
804
805 OP(macsatf)
806 {
807 int acc = PARAM1;
808 int64_t sum;
809 int64_t result;
810
811 sum = env->macc[acc];
812 result = (sum << 16) >> 16;
813 if (result != sum) {
814 env->macsr |= MACSR_V;
815 }
816 if (env->macsr & MACSR_V) {
817 env->macsr |= MACSR_PAV0 << acc;
818 if (env->macsr & MACSR_OMC) {
819 result = (result >> 63) ^ 0x7fffffffffffll;
820 }
821 }
822 env->macc[acc] = result;
823 FORCE_RET();
824 }
825
826 OP(mac_clear_flags)
827 {
828 env->macsr &= ~(MACSR_V | MACSR_Z | MACSR_N | MACSR_EV);
829 }
830
831 OP(mac_set_flags)
832 {
833 int acc = PARAM1;
834 uint64_t val;
835 val = env->macc[acc];
836 if (val == 0)
837 env->macsr |= MACSR_Z;
838 else if (val & (1ull << 47));
839 env->macsr |= MACSR_N;
840 if (env->macsr & (MACSR_PAV0 << acc)) {
841 env->macsr |= MACSR_V;
842 }
843 if (env->macsr & MACSR_FI) {
844 val = ((int64_t)val) >> 40;
845 if (val != 0 && val != -1)
846 env->macsr |= MACSR_EV;
847 } else if (env->macsr & MACSR_SU) {
848 val = ((int64_t)val) >> 32;
849 if (val != 0 && val != -1)
850 env->macsr |= MACSR_EV;
851 } else {
852 if ((val >> 32) != 0)
853 env->macsr |= MACSR_EV;
854 }
855 FORCE_RET();
856 }
857
858 OP(get_macf)
859 {
860 int acc = PARAM2;
861 int64_t val;
862 int rem;
863 uint32_t result;
864
865 val = env->macc[acc];
866 if (env->macsr & MACSR_SU) {
867 /* 16-bit rounding. */
868 rem = val & 0xffffff;
869 val = (val >> 24) & 0xffffu;
870 if (rem > 0x800000)
871 val++;
872 else if (rem == 0x800000)
873 val += (val & 1);
874 } else if (env->macsr & MACSR_RT) {
875 /* 32-bit rounding. */
876 rem = val & 0xff;
877 val >>= 8;
878 if (rem > 0x80)
879 val++;
880 else if (rem == 0x80)
881 val += (val & 1);
882 } else {
883 /* No rounding. */
884 val >>= 8;
885 }
886 if (env->macsr & MACSR_OMC) {
887 /* Saturate. */
888 if (env->macsr & MACSR_SU) {
889 if (val != (uint16_t) val) {
890 result = ((val >> 63) ^ 0x7fff) & 0xffff;
891 } else {
892 result = val & 0xffff;
893 }
894 } else {
895 if (val != (uint32_t)val) {
896 result = ((uint32_t)(val >> 63) & 0x7fffffff);
897 } else {
898 result = (uint32_t)val;
899 }
900 }
901 } else {
902 /* No saturation. */
903 if (env->macsr & MACSR_SU) {
904 result = val & 0xffff;
905 } else {
906 result = (uint32_t)val;
907 }
908 }
909 set_op(PARAM1, result);
910 FORCE_RET();
911 }
912
913 OP(get_maci)
914 {
915 int acc = PARAM2;
916 set_op(PARAM1, (uint32_t)env->macc[acc]);
917 FORCE_RET();
918 }
919
920 OP(get_macs)
921 {
922 int acc = PARAM2;
923 int64_t val = env->macc[acc];
924 uint32_t result;
925 if (val == (int32_t)val) {
926 result = (int32_t)val;
927 } else {
928 result = (val >> 61) ^ 0x7fffffff;
929 }
930 set_op(PARAM1, result);
931 FORCE_RET();
932 }
933
934 OP(get_macu)
935 {
936 int acc = PARAM2;
937 uint64_t val = env->macc[acc];
938 uint32_t result;
939 if ((val >> 32) == 0) {
940 result = (uint32_t)val;
941 } else {
942 result = 0xffffffffu;
943 }
944 set_op(PARAM1, result);
945 FORCE_RET();
946 }
947
948 OP(clear_mac)
949 {
950 int acc = PARAM1;
951
952 env->macc[acc] = 0;
953 env->macsr &= ~(MACSR_PAV0 << acc);
954 FORCE_RET();
955 }
956
957 OP(move_mac)
958 {
959 int dest = PARAM1;
960 int src = PARAM2;
961 uint32_t mask;
962 env->macc[dest] = env->macc[src];
963 mask = MACSR_PAV0 << dest;
964 if (env->macsr & (MACSR_PAV0 << src))
965 env->macsr |= mask;
966 else
967 env->macsr &= ~mask;
968 FORCE_RET();
969 }
970
971 OP(get_mac_extf)
972 {
973 uint32_t val;
974 int acc = PARAM2;
975 val = env->macc[acc] & 0x00ff;
976 val = (env->macc[acc] >> 32) & 0xff00;
977 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
978 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
979 set_op(PARAM1, val);
980 FORCE_RET();
981 }
982
983 OP(get_mac_exti)
984 {
985 uint32_t val;
986 int acc = PARAM2;
987 val = (env->macc[acc] >> 32) & 0xffff;
988 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
989 set_op(PARAM1, val);
990 FORCE_RET();
991 }
992
993 OP(set_macf)
994 {
995 int acc = PARAM2;
996 int32_t val = get_op(PARAM1);
997 env->macc[acc] = ((int64_t)val) << 8;
998 env->macsr &= ~(MACSR_PAV0 << acc);
999 FORCE_RET();
1000 }
1001
1002 OP(set_macs)
1003 {
1004 int acc = PARAM2;
1005 int32_t val = get_op(PARAM1);
1006 env->macc[acc] = val;
1007 env->macsr &= ~(MACSR_PAV0 << acc);
1008 FORCE_RET();
1009 }
1010
1011 OP(set_macu)
1012 {
1013 int acc = PARAM2;
1014 uint32_t val = get_op(PARAM1);
1015 env->macc[acc] = val;
1016 env->macsr &= ~(MACSR_PAV0 << acc);
1017 FORCE_RET();
1018 }
1019
1020 OP(set_mac_extf)
1021 {
1022 int acc = PARAM2;
1023 int32_t val = get_op(PARAM1);
1024 int64_t res;
1025 int32_t tmp;
1026 res = env->macc[acc] & 0xffffffff00ull;
1027 tmp = (int16_t)(val & 0xff00);
1028 res |= ((int64_t)tmp) << 32;
1029 res |= val & 0xff;
1030 env->macc[acc] = res;
1031 res = env->macc[acc + 1] & 0xffffffff00ull;
1032 tmp = (val & 0xff000000);
1033 res |= ((int64_t)tmp) << 16;
1034 res |= (val >> 16) & 0xff;
1035 env->macc[acc + 1] = res;
1036 }
1037
1038 OP(set_mac_exts)
1039 {
1040 int acc = PARAM2;
1041 int32_t val = get_op(PARAM1);
1042 int64_t res;
1043 int32_t tmp;
1044 res = (uint32_t)env->macc[acc];
1045 tmp = (int16_t)val;
1046 res |= ((int64_t)tmp) << 32;
1047 env->macc[acc] = res;
1048 res = (uint32_t)env->macc[acc + 1];
1049 tmp = val & 0xffff0000;
1050 res |= (int64_t)tmp << 16;
1051 env->macc[acc + 1] = res;
1052 }
1053
1054 OP(set_mac_extu)
1055 {
1056 int acc = PARAM2;
1057 int32_t val = get_op(PARAM1);
1058 uint64_t res;
1059 res = (uint32_t)env->macc[acc];
1060 res |= ((uint64_t)(val & 0xffff)) << 32;
1061 env->macc[acc] = res;
1062 res = (uint32_t)env->macc[acc + 1];
1063 res |= (uint64_t)(val & 0xffff0000) << 16;
1064 env->macc[acc + 1] = res;
1065 }
1066
1067 OP(set_macsr)
1068 {
1069 m68k_set_macsr(env, get_op(PARAM1));
1070 }