]> git.proxmox.com Git - mirror_qemu.git/blame - target-m68k/op.c
Don't try to use "vt" output in nographic mode.
[mirror_qemu.git] / target-m68k / op.c
CommitLineData
e6e5906b
PB
1/*
2 * m68k micro operations
3 *
0633879f 4 * Copyright (c) 2006-2007 CodeSourcery
e6e5906b
PB
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
29static 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
48uint32_t
49get_op(int qreg)
50{
7ec47ead
PB
51 if (qreg >= TARGET_NUM_QREGS) {
52 return env->qregs[qreg - TARGET_NUM_QREGS];
53 } else if (qreg == QREG_T0) {
e6e5906b 54 return T0;
e6e5906b 55 } else {
7ec47ead 56 return *(uint32_t *)(((long)env) + qreg_offsets[qreg]);
e6e5906b
PB
57 }
58}
59
60void set_op(int qreg, uint32_t val)
61{
7ec47ead
PB
62 if (qreg >= TARGET_NUM_QREGS) {
63 env->qregs[qreg - TARGET_NUM_QREGS] = val;
64 } else if (qreg == QREG_T0) {
e6e5906b 65 T0 = val;
e6e5906b 66 } else {
7ec47ead 67 *(uint32_t *)(((long)env) + qreg_offsets[qreg]) = val;
e6e5906b
PB
68 }
69}
70
71float64 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
80void 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
0633879f 89#define OP(name) void OPPROTO glue(op_,name) (void)
e6e5906b
PB
90
91OP(mov32)
92{
93 set_op(PARAM1, get_op(PARAM2));
94 FORCE_RET();
95}
96
97OP(mov32_im)
98{
99 set_op(PARAM1, PARAM2);
100 FORCE_RET();
101}
102
103OP(movf64)
104{
105 set_opf64(PARAM1, get_opf64(PARAM2));
106 FORCE_RET();
107}
108
109OP(zerof64)
110{
111 set_opf64(PARAM1, 0);
112 FORCE_RET();
113}
114
115OP(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
123OP(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
131OP(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
139OP(not32)
140{
141 uint32_t arg = get_op(PARAM2);
142 set_op(PARAM1, ~arg);
143 FORCE_RET();
144}
145
146OP(neg32)
147{
148 uint32_t arg = get_op(PARAM2);
149 set_op(PARAM1, -arg);
150 FORCE_RET();
151}
152
153OP(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
162OP(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
821f7e76
PB
173OP(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
8d7fe053 183OP(subx_cc)
e6e5906b
PB
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
8d7fe053 201OP(addx_cc)
e6e5906b
PB
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
221OP(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
229OP(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
237OP(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. */
246OP(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
256OP(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
267OP(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
277OP(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
acf930aa
PB
288OP(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
e6e5906b
PB
298OP(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
311OP(ext8u32)
312{
313 uint32_t op2 = get_op(PARAM2);
314 set_op(PARAM1, (uint8_t)op2);
315 FORCE_RET();
316}
317
318OP(ext8s32)
319{
320 uint32_t op2 = get_op(PARAM2);
321 set_op(PARAM1, (int8_t)op2);
322 FORCE_RET();
323}
324
325OP(ext16u32)
326{
327 uint32_t op2 = get_op(PARAM2);
328 set_op(PARAM1, (uint16_t)op2);
329 FORCE_RET();
330}
331
332OP(ext16s32)
333{
334 uint32_t op2 = get_op(PARAM2);
335 set_op(PARAM1, (int16_t)op2);
336 FORCE_RET();
337}
338
e6e5906b
PB
339OP(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
348OP(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;
2d37be61
PB
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)
e6e5906b
PB
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
379OP(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;
2d37be61 394 if (PARAM1 == 2 && quot != (int16_t)quot)
e6e5906b
PB
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
a87295e8 406/* Halt is special because it may be a semihosting call. */
0633879f 407OP(halt)
a87295e8
PB
408{
409 RAISE_EXCEPTION(EXCP_HALT_INSN);
410 FORCE_RET();
411}
412
413OP(stop)
0633879f
PB
414{
415 env->halted = 1;
416 RAISE_EXCEPTION(EXCP_HLT);
417 FORCE_RET();
418}
419
e6e5906b
PB
420OP(raise_exception)
421{
422 RAISE_EXCEPTION(PARAM1);
423 FORCE_RET();
424}
425
426/* Floating point comparison sets flags differently to other instructions. */
427
428OP(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
438OP(update_xflag_tst)
439{
440 uint32_t op1 = get_op(PARAM1);
441 env->cc_x = op1;
442 FORCE_RET();
443}
444
445OP(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
453OP(get_xflag)
454{
455 set_op(PARAM1, env->cc_x);
456 FORCE_RET();
457}
458
459OP(logic_cc)
460{
461 uint32_t op1 = get_op(PARAM1);
462 env->cc_dest = op1;
463 FORCE_RET();
464}
465
466OP(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
475OP(fp_result)
476{
477 env->fp_result = get_opf64(PARAM1);
478 FORCE_RET();
479}
480
20dcee94
PB
481OP(set_sr)
482{
483 env->sr = get_op(PARAM1);
484 m68k_switch_sp(env);
485 FORCE_RET();
486}
487
e6e5906b
PB
488OP(jmp)
489{
490 GOTO_LABEL_PARAM(1);
491}
492
493/* These ops involve a function call, which probably requires a stack frame
494 and breaks things on some hosts. */
495OP(jmp_z32)
496{
497 uint32_t arg = get_op(PARAM1);
498 if (arg == 0)
499 GOTO_LABEL_PARAM(2);
500 FORCE_RET();
501}
502
503OP(jmp_nz32)
504{
505 uint32_t arg = get_op(PARAM1);
506 if (arg != 0)
507 GOTO_LABEL_PARAM(2);
508 FORCE_RET();
509}
510
511OP(jmp_s32)
512{
513 int32_t arg = get_op(PARAM1);
514 if (arg < 0)
515 GOTO_LABEL_PARAM(2);
516 FORCE_RET();
517}
518
519OP(jmp_ns32)
520{
521 int32_t arg = get_op(PARAM1);
522 if (arg >= 0)
523 GOTO_LABEL_PARAM(2);
524 FORCE_RET();
525}
526
527void OPPROTO op_goto_tb0(void)
528{
529 GOTO_TB(op_goto_tb0, PARAM1, 0);
530}
531
532void OPPROTO op_goto_tb1(void)
533{
534 GOTO_TB(op_goto_tb1, PARAM1, 1);
535}
536
537OP(exit_tb)
538{
539 EXIT_TB();
540}
541
542
543/* Floating point. */
544OP(f64_to_i32)
545{
546 set_op(PARAM1, float64_to_int32(get_opf64(PARAM2), &CPU_FP_STATUS));
547 FORCE_RET();
548}
549
550OP(f64_to_f32)
551{
552 union {
553 float32 f;
554 uint32_t i;
555 } u;
556 u.f = float64_to_float32(get_opf64(PARAM2), &CPU_FP_STATUS);
557 set_op(PARAM1, u.i);
558 FORCE_RET();
559}
560
561OP(i32_to_f64)
562{
563 set_opf64(PARAM1, int32_to_float64(get_op(PARAM2), &CPU_FP_STATUS));
564 FORCE_RET();
565}
566
567OP(f32_to_f64)
568{
569 union {
570 float32 f;
571 uint32_t i;
572 } u;
573 u.i = get_op(PARAM2);
574 set_opf64(PARAM1, float32_to_float64(u.f, &CPU_FP_STATUS));
575 FORCE_RET();
576}
577
578OP(absf64)
579{
580 float64 op0 = get_opf64(PARAM2);
581 set_opf64(PARAM1, float64_abs(op0));
582 FORCE_RET();
583}
584
585OP(chsf64)
586{
587 float64 op0 = get_opf64(PARAM2);
588 set_opf64(PARAM1, float64_chs(op0));
589 FORCE_RET();
590}
591
592OP(sqrtf64)
593{
594 float64 op0 = get_opf64(PARAM2);
595 set_opf64(PARAM1, float64_sqrt(op0, &CPU_FP_STATUS));
596 FORCE_RET();
597}
598
599OP(addf64)
600{
601 float64 op0 = get_opf64(PARAM2);
602 float64 op1 = get_opf64(PARAM3);
603 set_opf64(PARAM1, float64_add(op0, op1, &CPU_FP_STATUS));
604 FORCE_RET();
605}
606
607OP(subf64)
608{
609 float64 op0 = get_opf64(PARAM2);
610 float64 op1 = get_opf64(PARAM3);
611 set_opf64(PARAM1, float64_sub(op0, op1, &CPU_FP_STATUS));
612 FORCE_RET();
613}
614
615OP(mulf64)
616{
617 float64 op0 = get_opf64(PARAM2);
618 float64 op1 = get_opf64(PARAM3);
619 set_opf64(PARAM1, float64_mul(op0, op1, &CPU_FP_STATUS));
620 FORCE_RET();
621}
622
623OP(divf64)
624{
625 float64 op0 = get_opf64(PARAM2);
626 float64 op1 = get_opf64(PARAM3);
627 set_opf64(PARAM1, float64_div(op0, op1, &CPU_FP_STATUS));
628 FORCE_RET();
629}
630
631OP(iround_f64)
632{
633 float64 op0 = get_opf64(PARAM2);
634 set_opf64(PARAM1, float64_round_to_int(op0, &CPU_FP_STATUS));
635 FORCE_RET();
636}
637
638OP(itrunc_f64)
639{
640 float64 op0 = get_opf64(PARAM2);
641 set_opf64(PARAM1, float64_trunc_to_int(op0, &CPU_FP_STATUS));
642 FORCE_RET();
643}
644
645OP(compare_quietf64)
646{
647 float64 op0 = get_opf64(PARAM2);
648 float64 op1 = get_opf64(PARAM3);
649 set_op(PARAM1, float64_compare_quiet(op0, op1, &CPU_FP_STATUS));
650 FORCE_RET();
651}
0633879f
PB
652
653OP(movec)
654{
655 int op1 = get_op(PARAM1);
656 uint32_t op2 = get_op(PARAM2);
657 helper_movec(env, op1, op2);
658}
659
660/* Memory access. */
661
662#define MEMSUFFIX _raw
663#include "op_mem.h"
664
665#if !defined(CONFIG_USER_ONLY)
666#define MEMSUFFIX _user
667#include "op_mem.h"
668#define MEMSUFFIX _kernel
669#include "op_mem.h"
670#endif
acf930aa
PB
671
672/* MAC unit. */
673/* TODO: The MAC instructions use 64-bit arithmetic fairly extensively.
674 This results in fairly large ops (and sometimes other issues) on 32-bit
675 hosts. Maybe move most of them into helpers. */
676OP(macmuls)
677{
678 uint32_t op1 = get_op(PARAM1);
679 uint32_t op2 = get_op(PARAM2);
680 int64_t product;
681 int64_t res;
682
683 product = (uint64_t)op1 * op2;
684 res = (product << 24) >> 24;
685 if (res != product) {
686 env->macsr |= MACSR_V;
687 if (env->macsr & MACSR_OMC) {
688 /* Make sure the accumulate operation overflows. */
689 if (product < 0)
690 res = ~(1ll << 50);
691 else
692 res = 1ll << 50;
693 }
694 }
695 env->mactmp = res;
696 FORCE_RET();
697}
698
699OP(macmulu)
700{
701 uint32_t op1 = get_op(PARAM1);
702 uint32_t op2 = get_op(PARAM2);
703 uint64_t product;
704
705 product = (uint64_t)op1 * op2;
706 if (product & (0xffffffull << 40)) {
707 env->macsr |= MACSR_V;
708 if (env->macsr & MACSR_OMC) {
709 /* Make sure the accumulate operation overflows. */
710 product = 1ll << 50;
711 } else {
712 product &= ((1ull << 40) - 1);
713 }
714 }
715 env->mactmp = product;
716 FORCE_RET();
717}
718
719OP(macmulf)
720{
721 int32_t op1 = get_op(PARAM1);
722 int32_t op2 = get_op(PARAM2);
723 uint64_t product;
724 uint32_t remainder;
725
726 product = (uint64_t)op1 * op2;
727 if (env->macsr & MACSR_RT) {
728 remainder = product & 0xffffff;
729 product >>= 24;
730 if (remainder > 0x800000)
731 product++;
732 else if (remainder == 0x800000)
733 product += (product & 1);
734 } else {
735 product >>= 24;
736 }
737 env->mactmp = product;
738 FORCE_RET();
739}
740
741OP(macshl)
742{
743 env->mactmp <<= 1;
744}
745
746OP(macshr)
747{
748 env->mactmp >>= 1;
749}
750
751OP(macadd)
752{
753 int acc = PARAM1;
754 env->macc[acc] += env->mactmp;
755 FORCE_RET();
756}
757
758OP(macsub)
759{
760 int acc = PARAM1;
761 env->macc[acc] -= env->mactmp;
762 FORCE_RET();
763}
764
765OP(macsats)
766{
767 int acc = PARAM1;
768 int64_t sum;
769 int64_t result;
770
771 sum = env->macc[acc];
772 result = (sum << 16) >> 16;
773 if (result != sum) {
774 env->macsr |= MACSR_V;
775 }
776 if (env->macsr & MACSR_V) {
777 env->macsr |= MACSR_PAV0 << acc;
778 if (env->macsr & MACSR_OMC) {
779 /* The result is saturated to 32 bits, despite overflow occuring
780 at 48 bits. Seems weird, but that's what the hardware docs
781 say. */
782 result = (result >> 63) ^ 0x7fffffff;
783 }
784 }
785 env->macc[acc] = result;
786 FORCE_RET();
787}
788
789OP(macsatu)
790{
791 int acc = PARAM1;
792 uint64_t sum;
793
794 sum = env->macc[acc];
795 if (sum & (0xffffull << 48)) {
796 env->macsr |= MACSR_V;
797 }
798 if (env->macsr & MACSR_V) {
799 env->macsr |= MACSR_PAV0 << acc;
800 if (env->macsr & MACSR_OMC) {
801 if (sum > (1ull << 53))
802 sum = 0;
803 else
804 sum = (1ull << 48) - 1;
805 } else {
806 sum &= ((1ull << 48) - 1);
807 }
808 }
809 FORCE_RET();
810}
811
812OP(macsatf)
813{
814 int acc = PARAM1;
815 int64_t sum;
816 int64_t result;
817
818 sum = env->macc[acc];
819 result = (sum << 16) >> 16;
820 if (result != sum) {
821 env->macsr |= MACSR_V;
822 }
823 if (env->macsr & MACSR_V) {
824 env->macsr |= MACSR_PAV0 << acc;
825 if (env->macsr & MACSR_OMC) {
826 result = (result >> 63) ^ 0x7fffffffffffll;
827 }
828 }
829 env->macc[acc] = result;
830 FORCE_RET();
831}
832
833OP(mac_clear_flags)
834{
835 env->macsr &= ~(MACSR_V | MACSR_Z | MACSR_N | MACSR_EV);
836}
837
838OP(mac_set_flags)
839{
840 int acc = PARAM1;
841 uint64_t val;
842 val = env->macc[acc];
843 if (val == 0)
844 env->macsr |= MACSR_Z;
845 else if (val & (1ull << 47));
846 env->macsr |= MACSR_N;
847 if (env->macsr & (MACSR_PAV0 << acc)) {
848 env->macsr |= MACSR_V;
849 }
850 if (env->macsr & MACSR_FI) {
851 val = ((int64_t)val) >> 40;
852 if (val != 0 && val != -1)
853 env->macsr |= MACSR_EV;
854 } else if (env->macsr & MACSR_SU) {
855 val = ((int64_t)val) >> 32;
856 if (val != 0 && val != -1)
857 env->macsr |= MACSR_EV;
858 } else {
859 if ((val >> 32) != 0)
860 env->macsr |= MACSR_EV;
861 }
862 FORCE_RET();
863}
864
865OP(get_macf)
866{
867 int acc = PARAM2;
868 int64_t val;
869 int rem;
870 uint32_t result;
871
872 val = env->macc[acc];
873 if (env->macsr & MACSR_SU) {
874 /* 16-bit rounding. */
875 rem = val & 0xffffff;
876 val = (val >> 24) & 0xffffu;
877 if (rem > 0x800000)
878 val++;
879 else if (rem == 0x800000)
880 val += (val & 1);
881 } else if (env->macsr & MACSR_RT) {
882 /* 32-bit rounding. */
883 rem = val & 0xff;
884 val >>= 8;
885 if (rem > 0x80)
886 val++;
887 else if (rem == 0x80)
888 val += (val & 1);
889 } else {
890 /* No rounding. */
891 val >>= 8;
892 }
893 if (env->macsr & MACSR_OMC) {
894 /* Saturate. */
895 if (env->macsr & MACSR_SU) {
896 if (val != (uint16_t) val) {
897 result = ((val >> 63) ^ 0x7fff) & 0xffff;
898 } else {
899 result = val & 0xffff;
900 }
901 } else {
902 if (val != (uint32_t)val) {
903 result = ((uint32_t)(val >> 63) & 0x7fffffff);
904 } else {
905 result = (uint32_t)val;
906 }
907 }
908 } else {
909 /* No saturation. */
910 if (env->macsr & MACSR_SU) {
911 result = val & 0xffff;
912 } else {
913 result = (uint32_t)val;
914 }
915 }
916 set_op(PARAM1, result);
917 FORCE_RET();
918}
919
920OP(get_maci)
921{
922 int acc = PARAM2;
923 set_op(PARAM1, (uint32_t)env->macc[acc]);
924 FORCE_RET();
925}
926
927OP(get_macs)
928{
929 int acc = PARAM2;
930 int64_t val = env->macc[acc];
931 uint32_t result;
932 if (val == (int32_t)val) {
933 result = (int32_t)val;
934 } else {
935 result = (val >> 61) ^ 0x7fffffff;
936 }
937 set_op(PARAM1, result);
938 FORCE_RET();
939}
940
941OP(get_macu)
942{
943 int acc = PARAM2;
944 uint64_t val = env->macc[acc];
945 uint32_t result;
946 if ((val >> 32) == 0) {
947 result = (uint32_t)val;
948 } else {
949 result = 0xffffffffu;
950 }
951 set_op(PARAM1, result);
952 FORCE_RET();
953}
954
955OP(clear_mac)
956{
957 int acc = PARAM1;
958
959 env->macc[acc] = 0;
960 env->macsr &= ~(MACSR_PAV0 << acc);
961 FORCE_RET();
962}
963
964OP(move_mac)
965{
966 int dest = PARAM1;
967 int src = PARAM2;
968 uint32_t mask;
969 env->macc[dest] = env->macc[src];
970 mask = MACSR_PAV0 << dest;
971 if (env->macsr & (MACSR_PAV0 << src))
972 env->macsr |= mask;
973 else
974 env->macsr &= ~mask;
975 FORCE_RET();
976}
977
978OP(get_mac_extf)
979{
980 uint32_t val;
981 int acc = PARAM2;
982 val = env->macc[acc] & 0x00ff;
983 val = (env->macc[acc] >> 32) & 0xff00;
984 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
985 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
986 set_op(PARAM1, val);
987 FORCE_RET();
988}
989
990OP(get_mac_exti)
991{
992 uint32_t val;
993 int acc = PARAM2;
994 val = (env->macc[acc] >> 32) & 0xffff;
995 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
996 set_op(PARAM1, val);
997 FORCE_RET();
998}
999
1000OP(set_macf)
1001{
1002 int acc = PARAM2;
1003 int32_t val = get_op(PARAM1);
1004 env->macc[acc] = ((int64_t)val) << 8;
1005 env->macsr &= ~(MACSR_PAV0 << acc);
1006 FORCE_RET();
1007}
1008
1009OP(set_macs)
1010{
1011 int acc = PARAM2;
1012 int32_t val = get_op(PARAM1);
1013 env->macc[acc] = val;
1014 env->macsr &= ~(MACSR_PAV0 << acc);
1015 FORCE_RET();
1016}
1017
1018OP(set_macu)
1019{
1020 int acc = PARAM2;
1021 uint32_t val = get_op(PARAM1);
1022 env->macc[acc] = val;
1023 env->macsr &= ~(MACSR_PAV0 << acc);
1024 FORCE_RET();
1025}
1026
1027OP(set_mac_extf)
1028{
1029 int acc = PARAM2;
1030 int32_t val = get_op(PARAM1);
1031 int64_t res;
1032 int32_t tmp;
1033 res = env->macc[acc] & 0xffffffff00ull;
1034 tmp = (int16_t)(val & 0xff00);
1035 res |= ((int64_t)tmp) << 32;
1036 res |= val & 0xff;
1037 env->macc[acc] = res;
1038 res = env->macc[acc + 1] & 0xffffffff00ull;
1039 tmp = (val & 0xff000000);
1040 res |= ((int64_t)tmp) << 16;
1041 res |= (val >> 16) & 0xff;
1042 env->macc[acc + 1] = res;
1043}
1044
1045OP(set_mac_exts)
1046{
1047 int acc = PARAM2;
1048 int32_t val = get_op(PARAM1);
1049 int64_t res;
1050 int32_t tmp;
1051 res = (uint32_t)env->macc[acc];
1052 tmp = (int16_t)val;
1053 res |= ((int64_t)tmp) << 32;
1054 env->macc[acc] = res;
1055 res = (uint32_t)env->macc[acc + 1];
1056 tmp = val & 0xffff0000;
1057 res |= (int64_t)tmp << 16;
1058 env->macc[acc + 1] = res;
1059}
1060
1061OP(set_mac_extu)
1062{
1063 int acc = PARAM2;
1064 int32_t val = get_op(PARAM1);
1065 uint64_t res;
1066 res = (uint32_t)env->macc[acc];
1067 res |= ((uint64_t)(val & 0xffff)) << 32;
1068 env->macc[acc] = res;
1069 res = (uint32_t)env->macc[acc + 1];
1070 res |= (uint64_t)(val & 0xffff0000) << 16;
1071 env->macc[acc + 1] = res;
1072}
1073
1074OP(set_macsr)
1075{
1076 m68k_set_macsr(env, get_op(PARAM1));
1077}