]>
git.proxmox.com Git - qemu.git/blob - target-m68k/op.c
466fdc23426b01d584b9643cb89fad24b67fa2a1
2 * m68k micro operations
4 * Copyright (c) 2006-2007 CodeSourcery
5 * Written by Paul Brook
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.
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.
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
23 #include "m68k-qreg.h"
26 #define offsetof(type, field) ((size_t) &((type *)0)->field)
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),
37 #define CPU_FP_STATUS env->fp_status
39 #define RAISE_EXCEPTION(n) do { \
40 env->exception_index = n; \
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
51 if (qreg
>= TARGET_NUM_QREGS
) {
52 return env
->qregs
[qreg
- TARGET_NUM_QREGS
];
53 } else if (qreg
== QREG_T0
) {
56 return *(uint32_t *)(((long)env
) + qreg_offsets
[qreg
]);
60 void set_op(int qreg
, uint32_t val
)
62 if (qreg
>= TARGET_NUM_QREGS
) {
63 env
->qregs
[qreg
- TARGET_NUM_QREGS
] = val
;
64 } else if (qreg
== QREG_T0
) {
67 *(uint32_t *)(((long)env
) + qreg_offsets
[qreg
]) = val
;
71 float64
get_opf64(int qreg
)
73 if (qreg
< TARGET_NUM_QREGS
) {
74 return *(float64
*)(((long)env
) + qreg_offsets
[qreg
]);
76 return *(float64
*)&env
->qregs
[qreg
- TARGET_NUM_QREGS
];
80 void set_opf64(int qreg
, float64 val
)
82 if (qreg
< TARGET_NUM_QREGS
) {
83 *(float64
*)(((long)env
) + qreg_offsets
[qreg
]) = val
;
85 *(float64
*)&env
->qregs
[qreg
- TARGET_NUM_QREGS
] = val
;
89 #define OP(name) void OPPROTO glue(op_,name) (void)
93 set_op(PARAM1
, get_op(PARAM2
));
99 set_op(PARAM1
, PARAM2
);
105 set_opf64(PARAM1
, get_opf64(PARAM2
));
111 set_opf64(PARAM1
, 0);
117 uint32_t op2
= get_op(PARAM2
);
118 uint32_t op3
= get_op(PARAM3
);
119 set_op(PARAM1
, op2
+ op3
);
125 uint32_t op2
= get_op(PARAM2
);
126 uint32_t op3
= get_op(PARAM3
);
127 set_op(PARAM1
, op2
- op3
);
133 uint32_t op2
= get_op(PARAM2
);
134 uint32_t op3
= get_op(PARAM3
);
135 set_op(PARAM1
, op2
* op3
);
141 uint32_t arg
= get_op(PARAM2
);
142 set_op(PARAM1
, ~arg
);
148 uint32_t arg
= get_op(PARAM2
);
149 set_op(PARAM1
, -arg
);
155 uint32_t arg
= get_op(PARAM2
);
156 arg
= (arg
>> 24) | (arg
<< 24)
157 | ((arg
>> 16) & 0xff00) | ((arg
<< 16) & 0xff0000);
164 uint32_t op1
= get_op(PARAM1
);
165 uint32_t op2
= get_op(PARAM2
);
167 env
->cc_dest
&= ~CCF_Z
;
169 env
->cc_dest
|= CCF_Z
;
175 uint32_t arg
= get_op(PARAM2
);
177 for (n
= 32; arg
; n
--)
185 uint32_t op1
= get_op(PARAM1
);
186 uint32_t op2
= get_op(PARAM2
);
189 env
->cc_x
= (op1
<= op2
);
190 env
->cc_op
= CC_OP_SUBX
;
191 res
= op1
- (op2
+ 1);
193 env
->cc_x
= (op1
< op2
);
194 env
->cc_op
= CC_OP_SUB
;
203 uint32_t op1
= get_op(PARAM1
);
204 uint32_t op2
= get_op(PARAM2
);
208 env
->cc_x
= (res
<= op2
);
209 env
->cc_op
= CC_OP_ADDX
;
212 env
->cc_x
= (res
< op2
);
213 env
->cc_op
= CC_OP_ADD
;
223 uint32_t op2
= get_op(PARAM2
);
224 uint32_t op3
= get_op(PARAM3
);
225 set_op(PARAM1
, op2
& op3
);
231 uint32_t op2
= get_op(PARAM2
);
232 uint32_t op3
= get_op(PARAM3
);
233 set_op(PARAM1
, op2
| op3
);
239 uint32_t op2
= get_op(PARAM2
);
240 uint32_t op3
= get_op(PARAM3
);
241 set_op(PARAM1
, op2
^ op3
);
248 uint32_t op2
= get_op(PARAM2
);
249 uint32_t op3
= get_op(PARAM3
);
252 set_op(PARAM1
, result
);
258 uint32_t op1
= get_op(PARAM1
);
259 uint32_t op2
= get_op(PARAM2
);
262 set_op(PARAM1
, result
);
263 env
->cc_x
= (op1
<< (op2
- 1)) & 1;
269 uint32_t op2
= get_op(PARAM2
);
270 uint32_t op3
= get_op(PARAM3
);
273 set_op(PARAM1
, result
);
279 uint32_t op1
= get_op(PARAM1
);
280 uint32_t op2
= get_op(PARAM2
);
283 set_op(PARAM1
, result
);
284 env
->cc_x
= (op1
>> (op2
- 1)) & 1;
290 int32_t op2
= get_op(PARAM2
);
291 uint32_t op3
= get_op(PARAM3
);
294 set_op(PARAM1
, result
);
300 int32_t op1
= get_op(PARAM1
);
301 uint32_t op2
= get_op(PARAM2
);
304 set_op(PARAM1
, result
);
305 env
->cc_x
= (op1
>> (op2
- 1)) & 1;
313 uint32_t op2
= get_op(PARAM2
);
314 set_op(PARAM1
, (uint8_t)op2
);
320 uint32_t op2
= get_op(PARAM2
);
321 set_op(PARAM1
, (int8_t)op2
);
327 uint32_t op2
= get_op(PARAM2
);
328 set_op(PARAM1
, (uint16_t)op2
);
334 uint32_t op2
= get_op(PARAM2
);
335 set_op(PARAM1
, (int16_t)op2
);
341 cpu_m68k_flush_flags(env
, env
->cc_op
);
355 /* ??? This needs to make sure the throwing location is accurate. */
357 RAISE_EXCEPTION(EXCP_DIV0
);
361 /* Avoid using a PARAM1 of zero. This breaks dyngen because it uses
362 the address of a symbol, and gcc knows symbols can't have address
364 if (PARAM1
== 2 && quot
> 0xffff)
368 else if ((int32_t)quot
< 0)
372 env
->cc_dest
= flags
;
387 RAISE_EXCEPTION(EXCP_DIV0
);
391 if (PARAM1
== 2 && quot
!= (int16_t)quot
)
399 env
->cc_dest
= flags
;
403 /* Halt is special because it may be a semihosting call. */
406 RAISE_EXCEPTION(EXCP_HALT_INSN
);
413 RAISE_EXCEPTION(EXCP_HLT
);
419 RAISE_EXCEPTION(PARAM1
);
423 /* Floating point comparison sets flags differently to other instructions. */
429 src0
= get_opf64(PARAM2
);
430 src1
= get_opf64(PARAM3
);
431 set_opf64(PARAM1
, helper_sub_cmpf64(env
, src0
, src1
));
437 uint32_t op1
= get_op(PARAM1
);
444 uint32_t op1
= get_op(PARAM1
);
445 uint32_t op2
= get_op(PARAM2
);
446 env
->cc_x
= (op1
< op2
);
452 set_op(PARAM1
, env
->cc_x
);
458 uint32_t op1
= get_op(PARAM1
);
465 uint32_t op1
= get_op(PARAM1
);
466 uint32_t op2
= get_op(PARAM2
);
474 env
->fp_result
= get_opf64(PARAM1
);
480 env
->sr
= get_op(PARAM1
) & 0xffff;
490 /* These ops involve a function call, which probably requires a stack frame
491 and breaks things on some hosts. */
494 uint32_t arg
= get_op(PARAM1
);
502 uint32_t arg
= get_op(PARAM1
);
510 int32_t arg
= get_op(PARAM1
);
518 int32_t arg
= get_op(PARAM1
);
524 void OPPROTO
op_goto_tb0(void)
526 GOTO_TB(op_goto_tb0
, PARAM1
, 0);
529 void OPPROTO
op_goto_tb1(void)
531 GOTO_TB(op_goto_tb1
, PARAM1
, 1);
540 /* Floating point. */
543 set_op(PARAM1
, float64_to_int32(get_opf64(PARAM2
), &CPU_FP_STATUS
));
553 u
.f
= float64_to_float32(get_opf64(PARAM2
), &CPU_FP_STATUS
);
560 set_opf64(PARAM1
, int32_to_float64(get_op(PARAM2
), &CPU_FP_STATUS
));
570 u
.i
= get_op(PARAM2
);
571 set_opf64(PARAM1
, float32_to_float64(u
.f
, &CPU_FP_STATUS
));
577 float64 op0
= get_opf64(PARAM2
);
578 set_opf64(PARAM1
, float64_abs(op0
));
584 float64 op0
= get_opf64(PARAM2
);
585 set_opf64(PARAM1
, float64_chs(op0
));
591 float64 op0
= get_opf64(PARAM2
);
592 set_opf64(PARAM1
, float64_sqrt(op0
, &CPU_FP_STATUS
));
598 float64 op0
= get_opf64(PARAM2
);
599 float64 op1
= get_opf64(PARAM3
);
600 set_opf64(PARAM1
, float64_add(op0
, op1
, &CPU_FP_STATUS
));
606 float64 op0
= get_opf64(PARAM2
);
607 float64 op1
= get_opf64(PARAM3
);
608 set_opf64(PARAM1
, float64_sub(op0
, op1
, &CPU_FP_STATUS
));
614 float64 op0
= get_opf64(PARAM2
);
615 float64 op1
= get_opf64(PARAM3
);
616 set_opf64(PARAM1
, float64_mul(op0
, op1
, &CPU_FP_STATUS
));
622 float64 op0
= get_opf64(PARAM2
);
623 float64 op1
= get_opf64(PARAM3
);
624 set_opf64(PARAM1
, float64_div(op0
, op1
, &CPU_FP_STATUS
));
630 float64 op0
= get_opf64(PARAM2
);
631 set_opf64(PARAM1
, float64_round_to_int(op0
, &CPU_FP_STATUS
));
637 float64 op0
= get_opf64(PARAM2
);
638 set_opf64(PARAM1
, float64_trunc_to_int(op0
, &CPU_FP_STATUS
));
644 float64 op0
= get_opf64(PARAM2
);
645 float64 op1
= get_opf64(PARAM3
);
646 set_op(PARAM1
, float64_compare_quiet(op0
, op1
, &CPU_FP_STATUS
));
652 int op1
= get_op(PARAM1
);
653 uint32_t op2
= get_op(PARAM2
);
654 helper_movec(env
, op1
, op2
);
659 #define MEMSUFFIX _raw
662 #if !defined(CONFIG_USER_ONLY)
663 #define MEMSUFFIX _user
665 #define MEMSUFFIX _kernel
670 /* TODO: The MAC instructions use 64-bit arithmetic fairly extensively.
671 This results in fairly large ops (and sometimes other issues) on 32-bit
672 hosts. Maybe move most of them into helpers. */
675 uint32_t op1
= get_op(PARAM1
);
676 uint32_t op2
= get_op(PARAM2
);
680 product
= (uint64_t)op1
* op2
;
681 res
= (product
<< 24) >> 24;
682 if (res
!= product
) {
683 env
->macsr
|= MACSR_V
;
684 if (env
->macsr
& MACSR_OMC
) {
685 /* Make sure the accumulate operation overflows. */
698 uint32_t op1
= get_op(PARAM1
);
699 uint32_t op2
= get_op(PARAM2
);
702 product
= (uint64_t)op1
* op2
;
703 if (product
& (0xffffffull
<< 40)) {
704 env
->macsr
|= MACSR_V
;
705 if (env
->macsr
& MACSR_OMC
) {
706 /* Make sure the accumulate operation overflows. */
709 product
&= ((1ull << 40) - 1);
712 env
->mactmp
= product
;
718 int32_t op1
= get_op(PARAM1
);
719 int32_t op2
= get_op(PARAM2
);
723 product
= (uint64_t)op1
* op2
;
724 if (env
->macsr
& MACSR_RT
) {
725 remainder
= product
& 0xffffff;
727 if (remainder
> 0x800000)
729 else if (remainder
== 0x800000)
730 product
+= (product
& 1);
734 env
->mactmp
= product
;
751 env
->macc
[acc
] += env
->mactmp
;
758 env
->macc
[acc
] -= env
->mactmp
;
768 sum
= env
->macc
[acc
];
769 result
= (sum
<< 16) >> 16;
771 env
->macsr
|= MACSR_V
;
773 if (env
->macsr
& MACSR_V
) {
774 env
->macsr
|= MACSR_PAV0
<< acc
;
775 if (env
->macsr
& MACSR_OMC
) {
776 /* The result is saturated to 32 bits, despite overflow occuring
777 at 48 bits. Seems weird, but that's what the hardware docs
779 result
= (result
>> 63) ^ 0x7fffffff;
782 env
->macc
[acc
] = result
;
791 sum
= env
->macc
[acc
];
792 if (sum
& (0xffffull
<< 48)) {
793 env
->macsr
|= MACSR_V
;
795 if (env
->macsr
& MACSR_V
) {
796 env
->macsr
|= MACSR_PAV0
<< acc
;
797 if (env
->macsr
& MACSR_OMC
) {
798 if (sum
> (1ull << 53))
801 sum
= (1ull << 48) - 1;
803 sum
&= ((1ull << 48) - 1);
815 sum
= env
->macc
[acc
];
816 result
= (sum
<< 16) >> 16;
818 env
->macsr
|= MACSR_V
;
820 if (env
->macsr
& MACSR_V
) {
821 env
->macsr
|= MACSR_PAV0
<< acc
;
822 if (env
->macsr
& MACSR_OMC
) {
823 result
= (result
>> 63) ^ 0x7fffffffffffll
;
826 env
->macc
[acc
] = result
;
832 env
->macsr
&= ~(MACSR_V
| MACSR_Z
| MACSR_N
| MACSR_EV
);
839 val
= env
->macc
[acc
];
841 env
->macsr
|= MACSR_Z
;
842 else if (val
& (1ull << 47));
843 env
->macsr
|= MACSR_N
;
844 if (env
->macsr
& (MACSR_PAV0
<< acc
)) {
845 env
->macsr
|= MACSR_V
;
847 if (env
->macsr
& MACSR_FI
) {
848 val
= ((int64_t)val
) >> 40;
849 if (val
!= 0 && val
!= -1)
850 env
->macsr
|= MACSR_EV
;
851 } else if (env
->macsr
& MACSR_SU
) {
852 val
= ((int64_t)val
) >> 32;
853 if (val
!= 0 && val
!= -1)
854 env
->macsr
|= MACSR_EV
;
856 if ((val
>> 32) != 0)
857 env
->macsr
|= MACSR_EV
;
869 val
= env
->macc
[acc
];
870 if (env
->macsr
& MACSR_SU
) {
871 /* 16-bit rounding. */
872 rem
= val
& 0xffffff;
873 val
= (val
>> 24) & 0xffffu
;
876 else if (rem
== 0x800000)
878 } else if (env
->macsr
& MACSR_RT
) {
879 /* 32-bit rounding. */
884 else if (rem
== 0x80)
890 if (env
->macsr
& MACSR_OMC
) {
892 if (env
->macsr
& MACSR_SU
) {
893 if (val
!= (uint16_t) val
) {
894 result
= ((val
>> 63) ^ 0x7fff) & 0xffff;
896 result
= val
& 0xffff;
899 if (val
!= (uint32_t)val
) {
900 result
= ((uint32_t)(val
>> 63) & 0x7fffffff);
902 result
= (uint32_t)val
;
907 if (env
->macsr
& MACSR_SU
) {
908 result
= val
& 0xffff;
910 result
= (uint32_t)val
;
913 set_op(PARAM1
, result
);
920 set_op(PARAM1
, (uint32_t)env
->macc
[acc
]);
927 int64_t val
= env
->macc
[acc
];
929 if (val
== (int32_t)val
) {
930 result
= (int32_t)val
;
932 result
= (val
>> 61) ^ 0x7fffffff;
934 set_op(PARAM1
, result
);
941 uint64_t val
= env
->macc
[acc
];
943 if ((val
>> 32) == 0) {
944 result
= (uint32_t)val
;
946 result
= 0xffffffffu
;
948 set_op(PARAM1
, result
);
957 env
->macsr
&= ~(MACSR_PAV0
<< acc
);
966 env
->macc
[dest
] = env
->macc
[src
];
967 mask
= MACSR_PAV0
<< dest
;
968 if (env
->macsr
& (MACSR_PAV0
<< src
))
979 val
= env
->macc
[acc
] & 0x00ff;
980 val
= (env
->macc
[acc
] >> 32) & 0xff00;
981 val
|= (env
->macc
[acc
+ 1] << 16) & 0x00ff0000;
982 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xff000000;
991 val
= (env
->macc
[acc
] >> 32) & 0xffff;
992 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xffff0000;
1000 int32_t val
= get_op(PARAM1
);
1001 env
->macc
[acc
] = ((int64_t)val
) << 8;
1002 env
->macsr
&= ~(MACSR_PAV0
<< acc
);
1009 int32_t val
= get_op(PARAM1
);
1010 env
->macc
[acc
] = val
;
1011 env
->macsr
&= ~(MACSR_PAV0
<< acc
);
1018 uint32_t val
= get_op(PARAM1
);
1019 env
->macc
[acc
] = val
;
1020 env
->macsr
&= ~(MACSR_PAV0
<< acc
);
1027 int32_t val
= get_op(PARAM1
);
1030 res
= env
->macc
[acc
] & 0xffffffff00ull
;
1031 tmp
= (int16_t)(val
& 0xff00);
1032 res
|= ((int64_t)tmp
) << 32;
1034 env
->macc
[acc
] = res
;
1035 res
= env
->macc
[acc
+ 1] & 0xffffffff00ull
;
1036 tmp
= (val
& 0xff000000);
1037 res
|= ((int64_t)tmp
) << 16;
1038 res
|= (val
>> 16) & 0xff;
1039 env
->macc
[acc
+ 1] = res
;
1045 int32_t val
= get_op(PARAM1
);
1048 res
= (uint32_t)env
->macc
[acc
];
1050 res
|= ((int64_t)tmp
) << 32;
1051 env
->macc
[acc
] = res
;
1052 res
= (uint32_t)env
->macc
[acc
+ 1];
1053 tmp
= val
& 0xffff0000;
1054 res
|= (int64_t)tmp
<< 16;
1055 env
->macc
[acc
+ 1] = res
;
1061 int32_t val
= get_op(PARAM1
);
1063 res
= (uint32_t)env
->macc
[acc
];
1064 res
|= ((uint64_t)(val
& 0xffff)) << 32;
1065 env
->macc
[acc
] = res
;
1066 res
= (uint32_t)env
->macc
[acc
+ 1];
1067 res
|= (uint64_t)(val
& 0xffff0000) << 16;
1068 env
->macc
[acc
+ 1] = res
;
1073 m68k_set_macsr(env
, get_op(PARAM1
));