]>
git.proxmox.com Git - mirror_qemu.git/blob - target-mips/op.c
2c99ad754d775f5480982d91f3742490ce4310e1
2 * MIPS emulation micro-operations for qemu.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2007 Thiemo Seufer (64-bit FPU support)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "host-utils.h"
28 #define CALL_FROM_TB0(func) func()
31 #define CALL_FROM_TB1(func, arg0) func(arg0)
33 #ifndef CALL_FROM_TB1_CONST16
34 #define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
37 #define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
39 #ifndef CALL_FROM_TB2_CONST16
40 #define CALL_FROM_TB2_CONST16(func, arg0, arg1) \
41 CALL_FROM_TB2(func, arg0, arg1)
44 #define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
47 #define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
48 func(arg0, arg1, arg2, arg3)
52 #define MEMSUFFIX _raw
55 #if !defined(CONFIG_USER_ONLY)
56 #define MEMSUFFIX _user
60 #define MEMSUFFIX _super
64 #define MEMSUFFIX _kernel
69 /* 64 bits arithmetic */
70 #if TARGET_LONG_BITS > HOST_LONG_BITS
73 CALL_FROM_TB0(do_madd
);
79 CALL_FROM_TB0(do_maddu
);
85 CALL_FROM_TB0(do_msub
);
91 CALL_FROM_TB0(do_msubu
);
95 /* Multiplication variants of the vr54xx. */
98 CALL_FROM_TB0(do_muls
);
104 CALL_FROM_TB0(do_mulsu
);
110 CALL_FROM_TB0(do_macc
);
114 void op_macchi (void)
116 CALL_FROM_TB0(do_macchi
);
122 CALL_FROM_TB0(do_maccu
);
125 void op_macchiu (void)
127 CALL_FROM_TB0(do_macchiu
);
133 CALL_FROM_TB0(do_msac
);
137 void op_msachi (void)
139 CALL_FROM_TB0(do_msachi
);
145 CALL_FROM_TB0(do_msacu
);
149 void op_msachiu (void)
151 CALL_FROM_TB0(do_msachiu
);
157 CALL_FROM_TB0(do_mulhi
);
161 void op_mulhiu (void)
163 CALL_FROM_TB0(do_mulhiu
);
167 void op_mulshi (void)
169 CALL_FROM_TB0(do_mulshi
);
173 void op_mulshiu (void)
175 CALL_FROM_TB0(do_mulshiu
);
179 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
181 static always_inline
uint64_t get_HILO (void)
183 return ((uint64_t)env
->HI
[env
->current_tc
][0] << 32) |
184 ((uint64_t)(uint32_t)env
->LO
[env
->current_tc
][0]);
187 static always_inline
void set_HILO (uint64_t HILO
)
189 env
->LO
[env
->current_tc
][0] = (int32_t)(HILO
& 0xFFFFFFFF);
190 env
->HI
[env
->current_tc
][0] = (int32_t)(HILO
>> 32);
193 static always_inline
void set_HIT0_LO (uint64_t HILO
)
195 env
->LO
[env
->current_tc
][0] = (int32_t)(HILO
& 0xFFFFFFFF);
196 T0
= env
->HI
[env
->current_tc
][0] = (int32_t)(HILO
>> 32);
199 static always_inline
void set_HI_LOT0 (uint64_t HILO
)
201 T0
= env
->LO
[env
->current_tc
][0] = (int32_t)(HILO
& 0xFFFFFFFF);
202 env
->HI
[env
->current_tc
][0] = (int32_t)(HILO
>> 32);
205 /* Multiplication variants of the vr54xx. */
208 set_HI_LOT0(0 - ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
));
214 set_HI_LOT0(0 - ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
));
220 set_HI_LOT0(get_HILO() + ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
));
224 void op_macchi (void)
226 set_HIT0_LO(get_HILO() + ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
));
232 set_HI_LOT0(get_HILO() + ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
));
236 void op_macchiu (void)
238 set_HIT0_LO(get_HILO() + ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
));
244 set_HI_LOT0(get_HILO() - ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
));
248 void op_msachi (void)
250 set_HIT0_LO(get_HILO() - ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
));
256 set_HI_LOT0(get_HILO() - ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
));
260 void op_msachiu (void)
262 set_HIT0_LO(get_HILO() - ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
));
268 set_HIT0_LO((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
);
272 void op_mulhiu (void)
274 set_HIT0_LO((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
);
278 void op_mulshi (void)
280 set_HIT0_LO(0 - ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
));
284 void op_mulshiu (void)
286 set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
));
290 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
294 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
296 # define DEBUG_FPU_STATE() do { } while(0)
300 Single precition routines have a "s" suffix, double precision a
301 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
302 paired single lowwer "pl", paired single upper "pu". */
304 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
308 DT2
= ((uint64_t)WT0
<< 32) | WT1
;
314 DT2
= ((uint64_t)WT0
<< 32) | WTH1
;
320 DT2
= ((uint64_t)WTH0
<< 32) | WT1
;
326 DT2
= ((uint64_t)WTH0
<< 32) | WTH1
;
333 if (!(env
->fpu
->fcr31
& PARAM1
))
340 if (!(env
->fpu
->fcr31
& PARAM1
))
347 unsigned int mask
= GET_FP_COND (env
->fpu
) >> PARAM1
;
357 if (env
->fpu
->fcr31
& PARAM1
)
364 if (env
->fpu
->fcr31
& PARAM1
)
371 unsigned int mask
= GET_FP_COND (env
->fpu
) >> PARAM1
;
426 /* ternary operations */
427 #define FLOAT_TERNOP(name1, name2) \
428 FLOAT_OP(name1 ## name2, d) \
430 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
431 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
435 FLOAT_OP(name1 ## name2, s) \
437 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
438 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
442 FLOAT_OP(name1 ## name2, ps) \
444 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
445 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
446 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
447 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
451 FLOAT_TERNOP(mul
, add
)
452 FLOAT_TERNOP(mul
, sub
)
455 /* negated ternary operations */
456 #define FLOAT_NTERNOP(name1, name2) \
457 FLOAT_OP(n ## name1 ## name2, d) \
459 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
460 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
461 FDT2 = float64_chs(FDT2); \
465 FLOAT_OP(n ## name1 ## name2, s) \
467 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
468 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
469 FST2 = float32_chs(FST2); \
473 FLOAT_OP(n ## name1 ## name2, ps) \
475 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
476 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
477 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
478 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
479 FST2 = float32_chs(FST2); \
480 FSTH2 = float32_chs(FSTH2); \
484 FLOAT_NTERNOP(mul
, add
)
485 FLOAT_NTERNOP(mul
, sub
)
488 /* unary operations, modifying fp status */
489 #define FLOAT_UNOP(name) \
492 FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
498 FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
505 /* unary operations, not modifying fp status */
506 #define FLOAT_UNOP(name) \
509 FDT2 = float64_ ## name(FDT0); \
515 FST2 = float32_ ## name(FST0); \
521 FST2 = float32_ ## name(FST0); \
522 FSTH2 = float32_ ## name(FSTH0); \
538 #ifdef TARGET_WORDS_BIGENDIAN
546 default: /* unpredictable */
555 T0
= !!(~GET_FP_COND(env
->fpu
) & (0x1 << PARAM1
));
559 void op_bc1any2f (void)
561 T0
= !!(~GET_FP_COND(env
->fpu
) & (0x3 << PARAM1
));
565 void op_bc1any4f (void)
567 T0
= !!(~GET_FP_COND(env
->fpu
) & (0xf << PARAM1
));
574 T0
= !!(GET_FP_COND(env
->fpu
) & (0x1 << PARAM1
));
578 void op_bc1any2t (void)
580 T0
= !!(GET_FP_COND(env
->fpu
) & (0x3 << PARAM1
));
584 void op_bc1any4t (void)
586 T0
= !!(GET_FP_COND(env
->fpu
) & (0xf << PARAM1
));