]> git.proxmox.com Git - mirror_qemu.git/blame - target-mips/op.c
Switch most MIPS FP load/stores to TCG.
[mirror_qemu.git] / target-mips / op.c
CommitLineData
6af0bf9c
FB
1/*
2 * MIPS emulation micro-operations for qemu.
5fafdf24 3 *
6af0bf9c 4 * Copyright (c) 2004-2005 Jocelyn Mayer
6ea83fed 5 * Copyright (c) 2006 Marius Groeger (FPU operations)
93b12ccc 6 * Copyright (c) 2007 Thiemo Seufer (64-bit FPU support)
6af0bf9c
FB
7 *
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.
12 *
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.
17 *
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
21 */
22
23#include "config.h"
24#include "exec.h"
05f778c8 25#include "host-utils.h"
6af0bf9c 26
1b351e52 27#ifndef CALL_FROM_TB0
5a5012ec 28#define CALL_FROM_TB0(func) func()
1b351e52
FB
29#endif
30#ifndef CALL_FROM_TB1
5a5012ec 31#define CALL_FROM_TB1(func, arg0) func(arg0)
1b351e52
FB
32#endif
33#ifndef CALL_FROM_TB1_CONST16
5a5012ec 34#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
1b351e52
FB
35#endif
36#ifndef CALL_FROM_TB2
5a5012ec 37#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
1b351e52
FB
38#endif
39#ifndef CALL_FROM_TB2_CONST16
40#define CALL_FROM_TB2_CONST16(func, arg0, arg1) \
5a5012ec 41 CALL_FROM_TB2(func, arg0, arg1)
1b351e52
FB
42#endif
43#ifndef CALL_FROM_TB3
5a5012ec 44#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
1b351e52
FB
45#endif
46#ifndef CALL_FROM_TB4
47#define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
5a5012ec 48 func(arg0, arg1, arg2, arg3)
1b351e52
FB
49#endif
50
6af0bf9c
FB
51/* Load and store */
52#define MEMSUFFIX _raw
53#include "op_mem.c"
54#undef MEMSUFFIX
55#if !defined(CONFIG_USER_ONLY)
56#define MEMSUFFIX _user
57#include "op_mem.c"
58#undef MEMSUFFIX
59
623a930e
TS
60#define MEMSUFFIX _super
61#include "op_mem.c"
62#undef MEMSUFFIX
63
6af0bf9c
FB
64#define MEMSUFFIX _kernel
65#include "op_mem.c"
66#undef MEMSUFFIX
67#endif
68
c570fd16
TS
69/* 64 bits arithmetic */
70#if TARGET_LONG_BITS > HOST_LONG_BITS
6af0bf9c
FB
71void op_mult (void)
72{
73 CALL_FROM_TB0(do_mult);
8f6f6026 74 FORCE_RET();
6af0bf9c
FB
75}
76
77void op_multu (void)
78{
79 CALL_FROM_TB0(do_multu);
8f6f6026 80 FORCE_RET();
6af0bf9c
FB
81}
82
83void op_madd (void)
84{
85 CALL_FROM_TB0(do_madd);
8f6f6026 86 FORCE_RET();
6af0bf9c
FB
87}
88
89void op_maddu (void)
90{
91 CALL_FROM_TB0(do_maddu);
8f6f6026 92 FORCE_RET();
6af0bf9c
FB
93}
94
95void op_msub (void)
96{
97 CALL_FROM_TB0(do_msub);
8f6f6026 98 FORCE_RET();
6af0bf9c
FB
99}
100
101void op_msubu (void)
102{
103 CALL_FROM_TB0(do_msubu);
8f6f6026 104 FORCE_RET();
6af0bf9c 105}
c570fd16 106
e9c71dd1
TS
107/* Multiplication variants of the vr54xx. */
108void op_muls (void)
109{
110 CALL_FROM_TB0(do_muls);
111 FORCE_RET();
112}
113
114void op_mulsu (void)
115{
116 CALL_FROM_TB0(do_mulsu);
117 FORCE_RET();
118}
119
120void op_macc (void)
121{
122 CALL_FROM_TB0(do_macc);
123 FORCE_RET();
124}
125
126void op_macchi (void)
127{
128 CALL_FROM_TB0(do_macchi);
129 FORCE_RET();
130}
131
132void op_maccu (void)
133{
134 CALL_FROM_TB0(do_maccu);
135 FORCE_RET();
136}
137void op_macchiu (void)
138{
139 CALL_FROM_TB0(do_macchiu);
140 FORCE_RET();
141}
142
143void op_msac (void)
144{
145 CALL_FROM_TB0(do_msac);
146 FORCE_RET();
147}
148
149void op_msachi (void)
150{
151 CALL_FROM_TB0(do_msachi);
152 FORCE_RET();
153}
154
155void op_msacu (void)
156{
157 CALL_FROM_TB0(do_msacu);
158 FORCE_RET();
159}
160
161void op_msachiu (void)
162{
163 CALL_FROM_TB0(do_msachiu);
164 FORCE_RET();
165}
166
167void op_mulhi (void)
168{
169 CALL_FROM_TB0(do_mulhi);
170 FORCE_RET();
171}
172
173void op_mulhiu (void)
174{
175 CALL_FROM_TB0(do_mulhiu);
176 FORCE_RET();
177}
178
179void op_mulshi (void)
180{
181 CALL_FROM_TB0(do_mulshi);
182 FORCE_RET();
183}
184
185void op_mulshiu (void)
186{
187 CALL_FROM_TB0(do_mulshiu);
188 FORCE_RET();
189}
190
c570fd16
TS
191#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
192
aa343735 193static always_inline uint64_t get_HILO (void)
c570fd16 194{
d0dc7dc3
TS
195 return ((uint64_t)env->HI[env->current_tc][0] << 32) |
196 ((uint64_t)(uint32_t)env->LO[env->current_tc][0]);
c570fd16
TS
197}
198
aa343735 199static always_inline void set_HILO (uint64_t HILO)
c570fd16 200{
d0dc7dc3
TS
201 env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
202 env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
c570fd16
TS
203}
204
e9c71dd1
TS
205static always_inline void set_HIT0_LO (uint64_t HILO)
206{
d0dc7dc3
TS
207 env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
208 T0 = env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
e9c71dd1
TS
209}
210
211static always_inline void set_HI_LOT0 (uint64_t HILO)
212{
d0dc7dc3
TS
213 T0 = env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
214 env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
e9c71dd1
TS
215}
216
c570fd16
TS
217void op_mult (void)
218{
219 set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
8f6f6026 220 FORCE_RET();
c570fd16
TS
221}
222
223void op_multu (void)
224{
225 set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
8f6f6026 226 FORCE_RET();
c570fd16
TS
227}
228
229void op_madd (void)
230{
231 int64_t tmp;
232
233 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
234 set_HILO((int64_t)get_HILO() + tmp);
8f6f6026 235 FORCE_RET();
c570fd16
TS
236}
237
238void op_maddu (void)
239{
240 uint64_t tmp;
241
242 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
243 set_HILO(get_HILO() + tmp);
8f6f6026 244 FORCE_RET();
c570fd16
TS
245}
246
247void op_msub (void)
248{
249 int64_t tmp;
250
251 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
252 set_HILO((int64_t)get_HILO() - tmp);
8f6f6026 253 FORCE_RET();
c570fd16
TS
254}
255
256void op_msubu (void)
257{
258 uint64_t tmp;
259
260 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
261 set_HILO(get_HILO() - tmp);
8f6f6026 262 FORCE_RET();
c570fd16 263}
e9c71dd1
TS
264
265/* Multiplication variants of the vr54xx. */
266void op_muls (void)
267{
268 set_HI_LOT0(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
269 FORCE_RET();
270}
271
272void op_mulsu (void)
273{
274 set_HI_LOT0(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
275 FORCE_RET();
276}
277
278void op_macc (void)
279{
280 set_HI_LOT0(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
281 FORCE_RET();
282}
283
284void op_macchi (void)
285{
286 set_HIT0_LO(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
287 FORCE_RET();
288}
289
290void op_maccu (void)
291{
292 set_HI_LOT0(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
293 FORCE_RET();
294}
295
296void op_macchiu (void)
297{
298 set_HIT0_LO(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
299 FORCE_RET();
300}
301
302void op_msac (void)
303{
304 set_HI_LOT0(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
305 FORCE_RET();
306}
307
308void op_msachi (void)
309{
310 set_HIT0_LO(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
311 FORCE_RET();
312}
313
314void op_msacu (void)
315{
316 set_HI_LOT0(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
317 FORCE_RET();
318}
319
320void op_msachiu (void)
321{
322 set_HIT0_LO(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
323 FORCE_RET();
324}
325
326void op_mulhi (void)
327{
328 set_HIT0_LO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
329 FORCE_RET();
330}
331
332void op_mulhiu (void)
333{
334 set_HIT0_LO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
335 FORCE_RET();
336}
337
338void op_mulshi (void)
339{
340 set_HIT0_LO(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
341 FORCE_RET();
342}
343
344void op_mulshiu (void)
345{
346 set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
347 FORCE_RET();
348}
349
c570fd16
TS
350#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
351
d26bc211 352#if defined(TARGET_MIPS64)
c570fd16
TS
353void op_dmult (void)
354{
d0dc7dc3 355 CALL_FROM_TB4(muls64, &(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1);
8f6f6026 356 FORCE_RET();
c570fd16
TS
357}
358
359void op_dmultu (void)
360{
d0dc7dc3 361 CALL_FROM_TB4(mulu64, &(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1);
8f6f6026 362 FORCE_RET();
c570fd16 363}
6af0bf9c
FB
364#endif
365
5a5012ec 366/* CP1 functions */
6ea83fed
FB
367#if 0
368# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
369#else
370# define DEBUG_FPU_STATE() do { } while(0)
371#endif
372
6ea83fed
FB
373/* Float support.
374 Single precition routines have a "s" suffix, double precision a
5a5012ec
TS
375 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
376 paired single lowwer "pl", paired single upper "pu". */
6ea83fed
FB
377
378#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
379
dd016883
FB
380FLOAT_OP(cvtd, s)
381{
fd4a04eb 382 CALL_FROM_TB0(do_float_cvtd_s);
dd016883 383 DEBUG_FPU_STATE();
8f6f6026 384 FORCE_RET();
dd016883 385}
6ea83fed
FB
386FLOAT_OP(cvtd, w)
387{
fd4a04eb 388 CALL_FROM_TB0(do_float_cvtd_w);
5a5012ec 389 DEBUG_FPU_STATE();
8f6f6026 390 FORCE_RET();
5a5012ec
TS
391}
392FLOAT_OP(cvtd, l)
393{
fd4a04eb 394 CALL_FROM_TB0(do_float_cvtd_l);
5a5012ec 395 DEBUG_FPU_STATE();
8f6f6026 396 FORCE_RET();
5a5012ec
TS
397}
398FLOAT_OP(cvtl, d)
399{
fd4a04eb 400 CALL_FROM_TB0(do_float_cvtl_d);
5a5012ec 401 DEBUG_FPU_STATE();
8f6f6026 402 FORCE_RET();
5a5012ec
TS
403}
404FLOAT_OP(cvtl, s)
405{
fd4a04eb 406 CALL_FROM_TB0(do_float_cvtl_s);
5a5012ec 407 DEBUG_FPU_STATE();
8f6f6026 408 FORCE_RET();
5a5012ec
TS
409}
410FLOAT_OP(cvtps, s)
411{
412 WT2 = WT0;
413 WTH2 = WT1;
414 DEBUG_FPU_STATE();
8f6f6026 415 FORCE_RET();
5a5012ec
TS
416}
417FLOAT_OP(cvtps, pw)
418{
fd4a04eb 419 CALL_FROM_TB0(do_float_cvtps_pw);
5a5012ec 420 DEBUG_FPU_STATE();
8f6f6026 421 FORCE_RET();
5a5012ec
TS
422}
423FLOAT_OP(cvtpw, ps)
424{
fd4a04eb 425 CALL_FROM_TB0(do_float_cvtpw_ps);
6ea83fed 426 DEBUG_FPU_STATE();
8f6f6026 427 FORCE_RET();
6ea83fed 428}
dd016883
FB
429FLOAT_OP(cvts, d)
430{
fd4a04eb 431 CALL_FROM_TB0(do_float_cvts_d);
dd016883 432 DEBUG_FPU_STATE();
8f6f6026 433 FORCE_RET();
dd016883 434}
6ea83fed
FB
435FLOAT_OP(cvts, w)
436{
fd4a04eb 437 CALL_FROM_TB0(do_float_cvts_w);
5a5012ec 438 DEBUG_FPU_STATE();
8f6f6026 439 FORCE_RET();
5a5012ec
TS
440}
441FLOAT_OP(cvts, l)
442{
fd4a04eb 443 CALL_FROM_TB0(do_float_cvts_l);
5a5012ec 444 DEBUG_FPU_STATE();
8f6f6026 445 FORCE_RET();
5a5012ec
TS
446}
447FLOAT_OP(cvts, pl)
448{
fd4a04eb 449 CALL_FROM_TB0(do_float_cvts_pl);
5a5012ec 450 DEBUG_FPU_STATE();
8f6f6026 451 FORCE_RET();
5a5012ec
TS
452}
453FLOAT_OP(cvts, pu)
454{
fd4a04eb 455 CALL_FROM_TB0(do_float_cvts_pu);
6ea83fed 456 DEBUG_FPU_STATE();
8f6f6026 457 FORCE_RET();
6ea83fed
FB
458}
459FLOAT_OP(cvtw, s)
460{
fd4a04eb 461 CALL_FROM_TB0(do_float_cvtw_s);
6ea83fed 462 DEBUG_FPU_STATE();
8f6f6026 463 FORCE_RET();
6ea83fed
FB
464}
465FLOAT_OP(cvtw, d)
466{
fd4a04eb 467 CALL_FROM_TB0(do_float_cvtw_d);
5a5012ec 468 DEBUG_FPU_STATE();
8f6f6026 469 FORCE_RET();
5a5012ec
TS
470}
471
472FLOAT_OP(pll, ps)
473{
474 DT2 = ((uint64_t)WT0 << 32) | WT1;
475 DEBUG_FPU_STATE();
8f6f6026 476 FORCE_RET();
5a5012ec
TS
477}
478FLOAT_OP(plu, ps)
479{
480 DT2 = ((uint64_t)WT0 << 32) | WTH1;
481 DEBUG_FPU_STATE();
8f6f6026 482 FORCE_RET();
5a5012ec
TS
483}
484FLOAT_OP(pul, ps)
485{
486 DT2 = ((uint64_t)WTH0 << 32) | WT1;
487 DEBUG_FPU_STATE();
8f6f6026 488 FORCE_RET();
5a5012ec
TS
489}
490FLOAT_OP(puu, ps)
491{
492 DT2 = ((uint64_t)WTH0 << 32) | WTH1;
6ea83fed 493 DEBUG_FPU_STATE();
8f6f6026 494 FORCE_RET();
6ea83fed
FB
495}
496
fd4a04eb
TS
497#define FLOAT_ROUNDOP(op, ttype, stype) \
498FLOAT_OP(op ## ttype, stype) \
499{ \
500 CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
501 DEBUG_FPU_STATE(); \
8f6f6026 502 FORCE_RET(); \
6ea83fed
FB
503}
504
fd4a04eb
TS
505FLOAT_ROUNDOP(round, l, d)
506FLOAT_ROUNDOP(round, l, s)
507FLOAT_ROUNDOP(round, w, d)
508FLOAT_ROUNDOP(round, w, s)
6ea83fed 509
fd4a04eb
TS
510FLOAT_ROUNDOP(trunc, l, d)
511FLOAT_ROUNDOP(trunc, l, s)
512FLOAT_ROUNDOP(trunc, w, d)
513FLOAT_ROUNDOP(trunc, w, s)
6ea83fed 514
fd4a04eb
TS
515FLOAT_ROUNDOP(ceil, l, d)
516FLOAT_ROUNDOP(ceil, l, s)
517FLOAT_ROUNDOP(ceil, w, d)
518FLOAT_ROUNDOP(ceil, w, s)
519
520FLOAT_ROUNDOP(floor, l, d)
521FLOAT_ROUNDOP(floor, l, s)
522FLOAT_ROUNDOP(floor, w, d)
523FLOAT_ROUNDOP(floor, w, s)
524#undef FLOAR_ROUNDOP
6ea83fed 525
5a5012ec
TS
526FLOAT_OP(movf, d)
527{
ead9360e 528 if (!(env->fpu->fcr31 & PARAM1))
5a5012ec
TS
529 DT2 = DT0;
530 DEBUG_FPU_STATE();
8f6f6026 531 FORCE_RET();
5a5012ec
TS
532}
533FLOAT_OP(movf, s)
534{
ead9360e 535 if (!(env->fpu->fcr31 & PARAM1))
5a5012ec
TS
536 WT2 = WT0;
537 DEBUG_FPU_STATE();
8f6f6026 538 FORCE_RET();
5a5012ec
TS
539}
540FLOAT_OP(movf, ps)
541{
e6bb7d7e
TS
542 unsigned int mask = GET_FP_COND (env->fpu) >> PARAM1;
543 if (!(mask & 1))
5a5012ec 544 WT2 = WT0;
e6bb7d7e 545 if (!(mask & 2))
5a5012ec 546 WTH2 = WTH0;
5a5012ec 547 DEBUG_FPU_STATE();
8f6f6026 548 FORCE_RET();
5a5012ec
TS
549}
550FLOAT_OP(movt, d)
551{
ead9360e 552 if (env->fpu->fcr31 & PARAM1)
5a5012ec
TS
553 DT2 = DT0;
554 DEBUG_FPU_STATE();
8f6f6026 555 FORCE_RET();
5a5012ec
TS
556}
557FLOAT_OP(movt, s)
558{
ead9360e 559 if (env->fpu->fcr31 & PARAM1)
5a5012ec
TS
560 WT2 = WT0;
561 DEBUG_FPU_STATE();
8f6f6026 562 FORCE_RET();
5a5012ec
TS
563}
564FLOAT_OP(movt, ps)
565{
e6bb7d7e
TS
566 unsigned int mask = GET_FP_COND (env->fpu) >> PARAM1;
567 if (mask & 1)
5a5012ec 568 WT2 = WT0;
e6bb7d7e 569 if (mask & 2)
5a5012ec 570 WTH2 = WTH0;
5a5012ec 571 DEBUG_FPU_STATE();
8f6f6026 572 FORCE_RET();
5a5012ec
TS
573}
574FLOAT_OP(movz, d)
575{
576 if (!T0)
577 DT2 = DT0;
578 DEBUG_FPU_STATE();
8f6f6026 579 FORCE_RET();
5a5012ec
TS
580}
581FLOAT_OP(movz, s)
582{
583 if (!T0)
584 WT2 = WT0;
585 DEBUG_FPU_STATE();
8f6f6026 586 FORCE_RET();
5a5012ec
TS
587}
588FLOAT_OP(movz, ps)
589{
590 if (!T0) {
591 WT2 = WT0;
592 WTH2 = WTH0;
593 }
594 DEBUG_FPU_STATE();
8f6f6026 595 FORCE_RET();
5a5012ec
TS
596}
597FLOAT_OP(movn, d)
598{
599 if (T0)
600 DT2 = DT0;
601 DEBUG_FPU_STATE();
8f6f6026 602 FORCE_RET();
5a5012ec
TS
603}
604FLOAT_OP(movn, s)
605{
606 if (T0)
607 WT2 = WT0;
608 DEBUG_FPU_STATE();
8f6f6026 609 FORCE_RET();
5a5012ec
TS
610}
611FLOAT_OP(movn, ps)
612{
613 if (T0) {
614 WT2 = WT0;
615 WTH2 = WTH0;
616 }
617 DEBUG_FPU_STATE();
8f6f6026 618 FORCE_RET();
5a5012ec
TS
619}
620
57fa1fb3 621/* operations calling helpers, for s, d and ps */
8f6f6026 622#define FLOAT_HOP(name) \
6ea83fed
FB
623FLOAT_OP(name, d) \
624{ \
fd4a04eb 625 CALL_FROM_TB0(do_float_ ## name ## _d); \
6ea83fed 626 DEBUG_FPU_STATE(); \
8f6f6026 627 FORCE_RET(); \
6ea83fed
FB
628} \
629FLOAT_OP(name, s) \
630{ \
fd4a04eb 631 CALL_FROM_TB0(do_float_ ## name ## _s); \
5a5012ec 632 DEBUG_FPU_STATE(); \
8f6f6026 633 FORCE_RET(); \
5a5012ec
TS
634} \
635FLOAT_OP(name, ps) \
636{ \
fd4a04eb 637 CALL_FROM_TB0(do_float_ ## name ## _ps); \
6ea83fed 638 DEBUG_FPU_STATE(); \
8f6f6026 639 FORCE_RET(); \
6ea83fed 640}
57fa1fb3
TS
641FLOAT_HOP(add)
642FLOAT_HOP(sub)
643FLOAT_HOP(mul)
644FLOAT_HOP(div)
645FLOAT_HOP(recip2)
646FLOAT_HOP(rsqrt2)
647FLOAT_HOP(rsqrt1)
648FLOAT_HOP(recip1)
649#undef FLOAT_HOP
650
651/* operations calling helpers, for s and d */
652#define FLOAT_HOP(name) \
653FLOAT_OP(name, d) \
654{ \
655 CALL_FROM_TB0(do_float_ ## name ## _d); \
656 DEBUG_FPU_STATE(); \
8f6f6026 657 FORCE_RET(); \
57fa1fb3
TS
658} \
659FLOAT_OP(name, s) \
660{ \
661 CALL_FROM_TB0(do_float_ ## name ## _s); \
662 DEBUG_FPU_STATE(); \
8f6f6026 663 FORCE_RET(); \
57fa1fb3
TS
664}
665FLOAT_HOP(rsqrt)
666FLOAT_HOP(recip)
667#undef FLOAT_HOP
6ea83fed 668
57fa1fb3
TS
669/* operations calling helpers, for ps */
670#define FLOAT_HOP(name) \
671FLOAT_OP(name, ps) \
672{ \
673 CALL_FROM_TB0(do_float_ ## name ## _ps); \
674 DEBUG_FPU_STATE(); \
8f6f6026 675 FORCE_RET(); \
fbcc6828 676}
57fa1fb3
TS
677FLOAT_HOP(addr)
678FLOAT_HOP(mulr)
679#undef FLOAT_HOP
fbcc6828 680
5a5012ec
TS
681/* ternary operations */
682#define FLOAT_TERNOP(name1, name2) \
683FLOAT_OP(name1 ## name2, d) \
684{ \
ead9360e
TS
685 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
686 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
5a5012ec 687 DEBUG_FPU_STATE(); \
8f6f6026 688 FORCE_RET(); \
5a5012ec
TS
689} \
690FLOAT_OP(name1 ## name2, s) \
691{ \
ead9360e
TS
692 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
693 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
5a5012ec 694 DEBUG_FPU_STATE(); \
8f6f6026 695 FORCE_RET(); \
5a5012ec
TS
696} \
697FLOAT_OP(name1 ## name2, ps) \
698{ \
ead9360e
TS
699 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
700 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
701 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
702 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
5a5012ec 703 DEBUG_FPU_STATE(); \
8f6f6026 704 FORCE_RET(); \
5a5012ec
TS
705}
706FLOAT_TERNOP(mul, add)
707FLOAT_TERNOP(mul, sub)
708#undef FLOAT_TERNOP
709
fbcc6828
TS
710/* negated ternary operations */
711#define FLOAT_NTERNOP(name1, name2) \
712FLOAT_OP(n ## name1 ## name2, d) \
713{ \
ead9360e
TS
714 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
715 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
5747c073 716 FDT2 = float64_chs(FDT2); \
fbcc6828 717 DEBUG_FPU_STATE(); \
8f6f6026 718 FORCE_RET(); \
fbcc6828
TS
719} \
720FLOAT_OP(n ## name1 ## name2, s) \
721{ \
ead9360e
TS
722 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
723 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
5747c073 724 FST2 = float32_chs(FST2); \
fbcc6828 725 DEBUG_FPU_STATE(); \
8f6f6026 726 FORCE_RET(); \
fbcc6828
TS
727} \
728FLOAT_OP(n ## name1 ## name2, ps) \
729{ \
ead9360e
TS
730 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
731 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
732 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
733 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
5747c073
PB
734 FST2 = float32_chs(FST2); \
735 FSTH2 = float32_chs(FSTH2); \
fbcc6828 736 DEBUG_FPU_STATE(); \
8f6f6026 737 FORCE_RET(); \
fbcc6828
TS
738}
739FLOAT_NTERNOP(mul, add)
740FLOAT_NTERNOP(mul, sub)
741#undef FLOAT_NTERNOP
742
6ea83fed
FB
743/* unary operations, modifying fp status */
744#define FLOAT_UNOP(name) \
745FLOAT_OP(name, d) \
746{ \
8f6f6026 747 FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
6ea83fed 748 DEBUG_FPU_STATE(); \
8f6f6026 749 FORCE_RET(); \
6ea83fed
FB
750} \
751FLOAT_OP(name, s) \
752{ \
8f6f6026 753 FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
6ea83fed 754 DEBUG_FPU_STATE(); \
8f6f6026 755 FORCE_RET(); \
6ea83fed
FB
756}
757FLOAT_UNOP(sqrt)
758#undef FLOAT_UNOP
759
760/* unary operations, not modifying fp status */
761#define FLOAT_UNOP(name) \
762FLOAT_OP(name, d) \
763{ \
764 FDT2 = float64_ ## name(FDT0); \
765 DEBUG_FPU_STATE(); \
8f6f6026 766 FORCE_RET(); \
6ea83fed
FB
767} \
768FLOAT_OP(name, s) \
769{ \
770 FST2 = float32_ ## name(FST0); \
771 DEBUG_FPU_STATE(); \
8f6f6026 772 FORCE_RET(); \
5a5012ec
TS
773} \
774FLOAT_OP(name, ps) \
775{ \
776 FST2 = float32_ ## name(FST0); \
777 FSTH2 = float32_ ## name(FSTH0); \
778 DEBUG_FPU_STATE(); \
8f6f6026 779 FORCE_RET(); \
6ea83fed
FB
780}
781FLOAT_UNOP(abs)
782FLOAT_UNOP(chs)
783#undef FLOAT_UNOP
784
785FLOAT_OP(mov, d)
786{
787 FDT2 = FDT0;
788 DEBUG_FPU_STATE();
8f6f6026 789 FORCE_RET();
6ea83fed
FB
790}
791FLOAT_OP(mov, s)
792{
793 FST2 = FST0;
794 DEBUG_FPU_STATE();
8f6f6026 795 FORCE_RET();
6ea83fed 796}
5a5012ec
TS
797FLOAT_OP(mov, ps)
798{
799 FST2 = FST0;
800 FSTH2 = FSTH0;
801 DEBUG_FPU_STATE();
8f6f6026 802 FORCE_RET();
5a5012ec
TS
803}
804FLOAT_OP(alnv, ps)
805{
806 switch (T0 & 0x7) {
807 case 0:
808 FST2 = FST0;
809 FSTH2 = FSTH0;
810 break;
811 case 4:
812#ifdef TARGET_WORDS_BIGENDIAN
813 FSTH2 = FST0;
814 FST2 = FSTH1;
815#else
816 FSTH2 = FST1;
817 FST2 = FSTH0;
818#endif
819 break;
820 default: /* unpredictable */
821 break;
822 }
823 DEBUG_FPU_STATE();
8f6f6026 824 FORCE_RET();
5a5012ec 825}
6ea83fed
FB
826
827#ifdef CONFIG_SOFTFLOAT
828#define clear_invalid() do { \
ead9360e 829 int flags = get_float_exception_flags(&env->fpu->fp_status); \
6ea83fed 830 flags &= ~float_flag_invalid; \
8f6f6026 831 set_float_exception_flags(flags, &env->fpu->fp_status); \
6ea83fed
FB
832} while(0)
833#else
834#define clear_invalid() do { } while(0)
835#endif
836
837extern void dump_fpu_s(CPUState *env);
838
fd4a04eb
TS
839#define CMP_OP(fmt, op) \
840void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void) \
841{ \
842 CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
843 DEBUG_FPU_STATE(); \
8f6f6026 844 FORCE_RET(); \
fd4a04eb
TS
845} \
846void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void) \
847{ \
848 CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
849 DEBUG_FPU_STATE(); \
8f6f6026 850 FORCE_RET(); \
fd4a04eb
TS
851}
852#define CMP_OPS(op) \
853CMP_OP(d, op) \
854CMP_OP(s, op) \
855CMP_OP(ps, op)
856
857CMP_OPS(f)
858CMP_OPS(un)
859CMP_OPS(eq)
860CMP_OPS(ueq)
861CMP_OPS(olt)
862CMP_OPS(ult)
863CMP_OPS(ole)
864CMP_OPS(ule)
865CMP_OPS(sf)
866CMP_OPS(ngle)
867CMP_OPS(seq)
868CMP_OPS(ngl)
869CMP_OPS(lt)
870CMP_OPS(nge)
871CMP_OPS(le)
872CMP_OPS(ngt)
873#undef CMP_OPS
874#undef CMP_OP
6ea83fed
FB
875
876void op_bc1f (void)
877{
ead9360e 878 T0 = !!(~GET_FP_COND(env->fpu) & (0x1 << PARAM1));
5a5012ec 879 DEBUG_FPU_STATE();
8f6f6026 880 FORCE_RET();
5a5012ec 881}
fd4a04eb 882void op_bc1any2f (void)
5a5012ec 883{
ead9360e 884 T0 = !!(~GET_FP_COND(env->fpu) & (0x3 << PARAM1));
5a5012ec 885 DEBUG_FPU_STATE();
8f6f6026 886 FORCE_RET();
5a5012ec 887}
fd4a04eb 888void op_bc1any4f (void)
5a5012ec 889{
ead9360e 890 T0 = !!(~GET_FP_COND(env->fpu) & (0xf << PARAM1));
6ea83fed 891 DEBUG_FPU_STATE();
8f6f6026 892 FORCE_RET();
6ea83fed
FB
893}
894
895void op_bc1t (void)
896{
ead9360e 897 T0 = !!(GET_FP_COND(env->fpu) & (0x1 << PARAM1));
5a5012ec 898 DEBUG_FPU_STATE();
8f6f6026 899 FORCE_RET();
5a5012ec 900}
fd4a04eb 901void op_bc1any2t (void)
5a5012ec 902{
ead9360e 903 T0 = !!(GET_FP_COND(env->fpu) & (0x3 << PARAM1));
5a5012ec 904 DEBUG_FPU_STATE();
8f6f6026 905 FORCE_RET();
5a5012ec 906}
fd4a04eb 907void op_bc1any4t (void)
5a5012ec 908{
ead9360e 909 T0 = !!(GET_FP_COND(env->fpu) & (0xf << PARAM1));
6ea83fed 910 DEBUG_FPU_STATE();
8f6f6026 911 FORCE_RET();
6ea83fed 912}
6ea83fed 913
6af0bf9c
FB
914void op_tlbwi (void)
915{
ead9360e 916 CALL_FROM_TB0(env->tlb->do_tlbwi);
8f6f6026 917 FORCE_RET();
6af0bf9c
FB
918}
919
920void op_tlbwr (void)
921{
ead9360e 922 CALL_FROM_TB0(env->tlb->do_tlbwr);
8f6f6026 923 FORCE_RET();
6af0bf9c
FB
924}
925
926void op_tlbp (void)
927{
ead9360e 928 CALL_FROM_TB0(env->tlb->do_tlbp);
8f6f6026 929 FORCE_RET();
6af0bf9c
FB
930}
931
932void op_tlbr (void)
933{
ead9360e 934 CALL_FROM_TB0(env->tlb->do_tlbr);
8f6f6026 935 FORCE_RET();
6af0bf9c 936}
6af0bf9c
FB
937
938/* Specials */
6f5b89a0
TS
939#if defined (CONFIG_USER_ONLY)
940void op_tls_value (void)
941{
5a5012ec 942 T0 = env->tls_value;
6f5b89a0
TS
943}
944#endif
945
6af0bf9c
FB
946void op_pmon (void)
947{
948 CALL_FROM_TB1(do_pmon, PARAM1);
8f6f6026 949 FORCE_RET();
7a387fff
TS
950}
951
952void op_di (void)
953{
7a387fff 954 T0 = env->CP0_Status;
4de9b249
TS
955 env->CP0_Status = T0 & ~(1 << CP0St_IE);
956 CALL_FROM_TB1(cpu_mips_update_irq, env);
8f6f6026 957 FORCE_RET();
7a387fff
TS
958}
959
960void op_ei (void)
961{
7a387fff 962 T0 = env->CP0_Status;
4de9b249
TS
963 env->CP0_Status = T0 | (1 << CP0St_IE);
964 CALL_FROM_TB1(cpu_mips_update_irq, env);
8f6f6026 965 FORCE_RET();
6af0bf9c
FB
966}
967
968void op_trap (void)
969{
970 if (T0) {
1579a72e 971 CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
6af0bf9c 972 }
8f6f6026 973 FORCE_RET();
6af0bf9c
FB
974}
975
4ad40f36
FB
976void op_debug (void)
977{
7a387fff 978 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
8f6f6026 979 FORCE_RET();
4ad40f36
FB
980}
981
f41c52f1
TS
982void debug_pre_eret (void);
983void debug_post_eret (void);
6af0bf9c
FB
984void op_eret (void)
985{
f41c52f1
TS
986 if (loglevel & CPU_LOG_EXEC)
987 CALL_FROM_TB0(debug_pre_eret);
24c7b0e3 988 if (env->CP0_Status & (1 << CP0St_ERL)) {
ead9360e 989 env->PC[env->current_tc] = env->CP0_ErrorEPC;
24c7b0e3 990 env->CP0_Status &= ~(1 << CP0St_ERL);
51e11d9e 991 } else {
ead9360e 992 env->PC[env->current_tc] = env->CP0_EPC;
24c7b0e3 993 env->CP0_Status &= ~(1 << CP0St_EXL);
51e11d9e 994 }
08fa4bab 995 CALL_FROM_TB1(compute_hflags, env);
f41c52f1
TS
996 if (loglevel & CPU_LOG_EXEC)
997 CALL_FROM_TB0(debug_post_eret);
6af0bf9c 998 env->CP0_LLAddr = 1;
8f6f6026 999 FORCE_RET();
6af0bf9c
FB
1000}
1001
1002void op_deret (void)
1003{
f41c52f1
TS
1004 if (loglevel & CPU_LOG_EXEC)
1005 CALL_FROM_TB0(debug_pre_eret);
ead9360e 1006 env->PC[env->current_tc] = env->CP0_DEPC;
08fa4bab
TS
1007 env->hflags &= MIPS_HFLAG_DM;
1008 CALL_FROM_TB1(compute_hflags, env);
f41c52f1
TS
1009 if (loglevel & CPU_LOG_EXEC)
1010 CALL_FROM_TB0(debug_post_eret);
24c7b0e3 1011 env->CP0_LLAddr = 1;
8f6f6026 1012 FORCE_RET();
7a387fff
TS
1013}
1014
1015void op_rdhwr_cpunum(void)
1016{
387a8fe5
TS
1017 if ((env->hflags & MIPS_HFLAG_CP0) ||
1018 (env->CP0_HWREna & (1 << 0)))
1579a72e 1019 T0 = env->CP0_EBase & 0x3ff;
7a387fff 1020 else
1579a72e 1021 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
8f6f6026 1022 FORCE_RET();
7a387fff
TS
1023}
1024
1025void op_rdhwr_synci_step(void)
1026{
387a8fe5
TS
1027 if ((env->hflags & MIPS_HFLAG_CP0) ||
1028 (env->CP0_HWREna & (1 << 1)))
1579a72e 1029 T0 = env->SYNCI_Step;
7a387fff 1030 else
1579a72e 1031 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
8f6f6026 1032 FORCE_RET();
7a387fff
TS
1033}
1034
1035void op_rdhwr_cc(void)
1036{
387a8fe5
TS
1037 if ((env->hflags & MIPS_HFLAG_CP0) ||
1038 (env->CP0_HWREna & (1 << 2)))
1579a72e 1039 T0 = env->CP0_Count;
7a387fff 1040 else
1579a72e 1041 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
8f6f6026 1042 FORCE_RET();
7a387fff
TS
1043}
1044
1045void op_rdhwr_ccres(void)
1046{
387a8fe5
TS
1047 if ((env->hflags & MIPS_HFLAG_CP0) ||
1048 (env->CP0_HWREna & (1 << 3)))
1579a72e 1049 T0 = env->CCRes;
7a387fff 1050 else
1579a72e 1051 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
8f6f6026 1052 FORCE_RET();
1579a72e
TS
1053}
1054
6af0bf9c
FB
1055void op_save_state (void)
1056{
1057 env->hflags = PARAM1;
8f6f6026 1058 FORCE_RET();
6af0bf9c
FB
1059}
1060
4ad40f36
FB
1061void op_wait (void)
1062{
1063 env->halted = 1;
1064 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
8f6f6026 1065 FORCE_RET();
7a387fff
TS
1066}
1067
1068/* Bitfield operations. */
1069void op_ext(void)
1070{
1071 unsigned int pos = PARAM1;
1072 unsigned int size = PARAM2;
1073
c6d6dd7c 1074 T0 = (int32_t)((T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0));
8f6f6026 1075 FORCE_RET();
7a387fff
TS
1076}
1077
1078void op_ins(void)
1079{
1080 unsigned int pos = PARAM1;
1081 unsigned int size = PARAM2;
f757d6ff 1082 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
7a387fff 1083
c6d6dd7c 1084 T0 = (int32_t)((T0 & ~mask) | ((T1 << pos) & mask));
8f6f6026 1085 FORCE_RET();
7a387fff
TS
1086}
1087
1088void op_wsbh(void)
1089{
c6d6dd7c 1090 T0 = (int32_t)(((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF));
8f6f6026 1091 FORCE_RET();
7a387fff
TS
1092}
1093
d26bc211 1094#if defined(TARGET_MIPS64)
c570fd16
TS
1095void op_dext(void)
1096{
1097 unsigned int pos = PARAM1;
1098 unsigned int size = PARAM2;
1099
c6d6dd7c 1100 T0 = (T1 >> pos) & ((size < 64) ? ((1ULL << size) - 1) : ~0ULL);
8f6f6026 1101 FORCE_RET();
c570fd16
TS
1102}
1103
1104void op_dins(void)
1105{
1106 unsigned int pos = PARAM1;
1107 unsigned int size = PARAM2;
c6d6dd7c 1108 target_ulong mask = ((size < 64) ? ((1ULL << size) - 1) : ~0ULL) << pos;
c570fd16 1109
171b31e7 1110 T0 = (T0 & ~mask) | ((T1 << pos) & mask);
8f6f6026 1111 FORCE_RET();
c570fd16
TS
1112}
1113
7a387fff
TS
1114void op_dsbh(void)
1115{
1116 T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
8f6f6026 1117 FORCE_RET();
7a387fff
TS
1118}
1119
1120void op_dshd(void)
1121{
c6d6dd7c
TS
1122 T1 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
1123 T0 = (T1 << 32) | (T1 >> 32);
8f6f6026 1124 FORCE_RET();
7a387fff 1125}
c570fd16 1126#endif