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 op1 = get_op(PARAM1);
291 uint32_t op2 = get_op(PARAM2);
294 set_op(PARAM1, result);
295 env->cc_x = (op1 >> (op2 - 1)) & 1;
303 uint32_t op2 = get_op(PARAM2);
304 set_op(PARAM1, (uint8_t)op2);
310 uint32_t op2 = get_op(PARAM2);
311 set_op(PARAM1, (int8_t)op2);
317 uint32_t op2 = get_op(PARAM2);
318 set_op(PARAM1, (uint16_t)op2);
324 uint32_t op2 = get_op(PARAM2);
325 set_op(PARAM1, (int16_t)op2);
332 if (cc_op == CC_OP_DYNAMIC)
334 cpu_m68k_flush_flags(env, cc_op);
348 /* ??? This needs to make sure the throwing location is accurate. */
350 RAISE_EXCEPTION(EXCP_DIV0);
354 /* Avoid using a PARAM1 of zero. This breaks dyngen because it uses
355 the address of a symbol, and gcc knows symbols can't have address
357 if (PARAM1 == 2 && quot > 0xffff)
361 else if ((int32_t)quot < 0)
365 env->cc_dest = flags;
380 RAISE_EXCEPTION(EXCP_DIV0);
384 if (PARAM1 == 2 && quot != (int16_t)quot)
392 env->cc_dest = flags;
396 /* Halt is special because it may be a semihosting call. */
399 RAISE_EXCEPTION(EXCP_HALT_INSN);
406 RAISE_EXCEPTION(EXCP_HLT);
412 RAISE_EXCEPTION(PARAM1);
416 /* Floating point comparison sets flags differently to other instructions. */
422 src0 = get_opf64(PARAM2);
423 src1 = get_opf64(PARAM3);
424 set_opf64(PARAM1, helper_sub_cmpf64(env, src0, src1));
430 uint32_t op1 = get_op(PARAM1);
437 uint32_t op1 = get_op(PARAM1);
438 uint32_t op2 = get_op(PARAM2);
439 env->cc_x = (op1 < op2);
445 set_op(PARAM1, env->cc_x);
451 uint32_t op1 = get_op(PARAM1);
458 uint32_t op1 = get_op(PARAM1);
459 uint32_t op2 = get_op(PARAM2);
467 env->fp_result = get_opf64(PARAM1);
476 /* These ops involve a function call, which probably requires a stack frame
477 and breaks things on some hosts. */
480 uint32_t arg = get_op(PARAM1);
488 uint32_t arg = get_op(PARAM1);
496 int32_t arg = get_op(PARAM1);
504 int32_t arg = get_op(PARAM1);
510 void OPPROTO op_goto_tb0(void)
512 GOTO_TB(op_goto_tb0, PARAM1, 0);
515 void OPPROTO op_goto_tb1(void)
517 GOTO_TB(op_goto_tb1, PARAM1, 1);
526 /* Floating point. */
529 set_op(PARAM1, float64_to_int32(get_opf64(PARAM2), &CPU_FP_STATUS));
539 u.f = float64_to_float32(get_opf64(PARAM2), &CPU_FP_STATUS);
546 set_opf64(PARAM1, int32_to_float64(get_op(PARAM2), &CPU_FP_STATUS));
556 u.i = get_op(PARAM2);
557 set_opf64(PARAM1, float32_to_float64(u.f, &CPU_FP_STATUS));
563 float64 op0 = get_opf64(PARAM2);
564 set_opf64(PARAM1, float64_abs(op0));
570 float64 op0 = get_opf64(PARAM2);
571 set_opf64(PARAM1, float64_chs(op0));
577 float64 op0 = get_opf64(PARAM2);
578 set_opf64(PARAM1, float64_sqrt(op0, &CPU_FP_STATUS));
584 float64 op0 = get_opf64(PARAM2);
585 float64 op1 = get_opf64(PARAM3);
586 set_opf64(PARAM1, float64_add(op0, op1, &CPU_FP_STATUS));
592 float64 op0 = get_opf64(PARAM2);
593 float64 op1 = get_opf64(PARAM3);
594 set_opf64(PARAM1, float64_sub(op0, op1, &CPU_FP_STATUS));
600 float64 op0 = get_opf64(PARAM2);
601 float64 op1 = get_opf64(PARAM3);
602 set_opf64(PARAM1, float64_mul(op0, op1, &CPU_FP_STATUS));
608 float64 op0 = get_opf64(PARAM2);
609 float64 op1 = get_opf64(PARAM3);
610 set_opf64(PARAM1, float64_div(op0, op1, &CPU_FP_STATUS));
616 float64 op0 = get_opf64(PARAM2);
617 set_opf64(PARAM1, float64_round_to_int(op0, &CPU_FP_STATUS));
623 float64 op0 = get_opf64(PARAM2);
624 set_opf64(PARAM1, float64_trunc_to_int(op0, &CPU_FP_STATUS));
630 float64 op0 = get_opf64(PARAM2);
631 float64 op1 = get_opf64(PARAM3);
632 set_op(PARAM1, float64_compare_quiet(op0, op1, &CPU_FP_STATUS));
638 int op1 = get_op(PARAM1);
639 uint32_t op2 = get_op(PARAM2);
640 helper_movec(env, op1, op2);
645 #define MEMSUFFIX _raw
648 #if !defined(CONFIG_USER_ONLY)
649 #define MEMSUFFIX _user
651 #define MEMSUFFIX _kernel